summaryrefslogtreecommitdiff
path: root/bot.go
diff options
context:
space:
mode:
authorGrail Finder <wohilas@gmail.com>2025-12-19 15:39:55 +0300
committerGrail Finder <wohilas@gmail.com>2025-12-19 15:39:55 +0300
commitf779f039745f97f08f25967214d07716ce213326 (patch)
tree9868dfe5e77845e27d4fe8b36f993a5fade2ea7b /bot.go
parenta875abcf198dd2f85c518f8bf2c599db66d3e69f (diff)
Enha: agent request builder
Diffstat (limited to 'bot.go')
-rw-r--r--bot.go72
1 files changed, 68 insertions, 4 deletions
diff --git a/bot.go b/bot.go
index 8206c63..779278e 100644
--- a/bot.go
+++ b/bot.go
@@ -6,6 +6,7 @@ import (
"context"
"encoding/json"
"fmt"
+ "strconv"
"gf-lt/config"
"gf-lt/extra"
"gf-lt/models"
@@ -659,14 +660,75 @@ func cleanChatBody() {
}
}
+// convertJSONToMapStringString unmarshals JSON into map[string]interface{} and converts all values to strings.
+func convertJSONToMapStringString(jsonStr string) (map[string]string, error) {
+ var raw map[string]interface{}
+ if err := json.Unmarshal([]byte(jsonStr), &raw); err != nil {
+ return nil, err
+ }
+ result := make(map[string]string, len(raw))
+ for k, v := range raw {
+ switch val := v.(type) {
+ case string:
+ result[k] = val
+ case float64:
+ result[k] = strconv.FormatFloat(val, 'f', -1, 64)
+ case int, int64, int32:
+ // json.Unmarshal converts numbers to float64, but handle other integer types if they appear
+ result[k] = fmt.Sprintf("%v", val)
+ case bool:
+ result[k] = strconv.FormatBool(val)
+ case nil:
+ result[k] = ""
+ default:
+ result[k] = fmt.Sprintf("%v", val)
+ }
+ }
+ return result, nil
+}
+
+// unmarshalFuncCall unmarshals a JSON tool call, converting numeric arguments to strings.
+func unmarshalFuncCall(jsonStr string) (*models.FuncCall, error) {
+ type tempFuncCall struct {
+ ID string `json:"id,omitempty"`
+ Name string `json:"name"`
+ Args map[string]interface{} `json:"args"`
+ }
+ var temp tempFuncCall
+ if err := json.Unmarshal([]byte(jsonStr), &temp); err != nil {
+ return nil, err
+ }
+ fc := &models.FuncCall{
+ ID: temp.ID,
+ Name: temp.Name,
+ Args: make(map[string]string, len(temp.Args)),
+ }
+ for k, v := range temp.Args {
+ switch val := v.(type) {
+ case string:
+ fc.Args[k] = val
+ case float64:
+ fc.Args[k] = strconv.FormatFloat(val, 'f', -1, 64)
+ case int, int64, int32:
+ fc.Args[k] = fmt.Sprintf("%v", val)
+ case bool:
+ fc.Args[k] = strconv.FormatBool(val)
+ case nil:
+ fc.Args[k] = ""
+ default:
+ fc.Args[k] = fmt.Sprintf("%v", val)
+ }
+ }
+ return fc, nil
+}
+
func findCall(msg, toolCall string, tv *tview.TextView) {
fc := &models.FuncCall{}
if toolCall != "" {
// HTML-decode the tool call string to handle encoded characters like &lt; -> <=
decodedToolCall := html.UnescapeString(toolCall)
- openAIToolMap := make(map[string]string)
- // respect tool call
- if err := json.Unmarshal([]byte(decodedToolCall), &openAIToolMap); err != nil {
+ openAIToolMap, err := convertJSONToMapStringString(decodedToolCall)
+ if err != nil {
logger.Error("failed to unmarshal openai tool call", "call", decodedToolCall, "error", err)
// Send error response to LLM so it can retry or handle the error
toolResponseMsg := models.RoleMsg{
@@ -700,7 +762,9 @@ func findCall(msg, toolCall string, tv *tview.TextView) {
jsStr = strings.TrimSuffix(strings.TrimPrefix(jsStr, prefix), suffix)
// HTML-decode the JSON string to handle encoded characters like &lt; -> <=
decodedJsStr := html.UnescapeString(jsStr)
- if err := json.Unmarshal([]byte(decodedJsStr), &fc); err != nil {
+ var err error
+ fc, err = unmarshalFuncCall(decodedJsStr)
+ if err != nil {
logger.Error("failed to unmarshal tool call", "error", err, "json_string", decodedJsStr)
// Send error response to LLM so it can retry or handle the error
toolResponseMsg := models.RoleMsg{