Feat: tool write_append

This commit is contained in:
Grail Finder
2025-12-31 13:38:48 +03:00
parent 1022b099e4
commit 88bf281dd9
2 changed files with 73 additions and 48 deletions

120
tools.go
View File

@@ -71,8 +71,13 @@ Your current tools:
}, },
{ {
"name":"file_write", "name":"file_write",
"args": ["path", "content", "mode"], "args": ["path", "content"],
"when_to_use": "when asked to write content to a file; mode is optional (overwrite or append, default: overwrite)" "when_to_use": "when needed to overwrite content to a file"
},
{
"name":"file_write_append",
"args": ["path", "content"],
"when_to_use": "when asked to append content to a file; use sed to edit content"
}, },
{ {
"name":"file_delete", "name":"file_delete",
@@ -146,9 +151,9 @@ After that you are free to respond to the user.
sysMap = map[string]*models.CharCard{"basic_sys": basicCard} sysMap = map[string]*models.CharCard{"basic_sys": basicCard}
sysLabels = []string{"basic_sys"} sysLabels = []string{"basic_sys"}
webAgentClient *agent.AgentClient webAgentClient *agent.AgentClient
webAgentClientOnce sync.Once webAgentClientOnce sync.Once
webAgentsOnce sync.Once webAgentsOnce sync.Once
) )
// getWebAgentClient returns a singleton AgentClient for web agents. // getWebAgentClient returns a singleton AgentClient for web agents.
@@ -359,36 +364,35 @@ func fileWrite(args map[string]string) []byte {
logger.Error(msg) logger.Error(msg)
return []byte(msg) return []byte(msg)
} }
content, ok := args["content"] content, ok := args["content"]
if !ok { if !ok {
content = "" content = ""
} }
if err := writeStringToFile(path, content); err != nil {
mode, ok := args["mode"] msg := "failed to write to file; error: " + err.Error()
if !ok || mode == "" {
mode = "overwrite"
}
switch mode {
case "overwrite":
if err := writeStringToFile(path, content); err != nil {
msg := "failed to write to file; error: " + err.Error()
logger.Error(msg)
return []byte(msg)
}
case "append":
if err := appendStringToFile(path, content); err != nil {
msg := "failed to append to file; error: " + err.Error()
logger.Error(msg)
return []byte(msg)
}
default:
msg := "invalid mode; use 'overwrite' or 'append'"
logger.Error(msg) logger.Error(msg)
return []byte(msg) return []byte(msg)
} }
msg := "file written successfully at " + path
return []byte(msg)
}
func fileWriteAppend(args map[string]string) []byte {
path, ok := args["path"]
if !ok || path == "" {
msg := "path not provided to file_write_append tool"
logger.Error(msg)
return []byte(msg)
}
content, ok := args["content"]
if !ok {
content = ""
}
if err := appendStringToFile(path, content); err != nil {
msg := "failed to append to file; error: " + err.Error()
logger.Error(msg)
return []byte(msg)
}
msg := "file written successfully at " + path msg := "file written successfully at " + path
return []byte(msg) return []byte(msg)
} }
@@ -879,24 +883,25 @@ func summarizeChat(args map[string]string) []byte {
type fnSig func(map[string]string) []byte type fnSig func(map[string]string) []byte
var fnMap = map[string]fnSig{ var fnMap = map[string]fnSig{
"recall": recall, "recall": recall,
"recall_topics": recallTopics, "recall_topics": recallTopics,
"memorise": memorise, "memorise": memorise,
"websearch": websearch, "websearch": websearch,
"read_url": readURL, "read_url": readURL,
"file_create": fileCreate, "file_create": fileCreate,
"file_read": fileRead, "file_read": fileRead,
"file_write": fileWrite, "file_write": fileWrite,
"file_delete": fileDelete, "file_write_append": fileWriteAppend,
"file_move": fileMove, "file_delete": fileDelete,
"file_copy": fileCopy, "file_move": fileMove,
"file_list": fileList, "file_copy": fileCopy,
"execute_command": executeCommand, "file_list": fileList,
"todo_create": todoCreate, "execute_command": executeCommand,
"todo_read": todoRead, "todo_create": todoCreate,
"todo_update": todoUpdate, "todo_read": todoRead,
"todo_delete": todoDelete, "todo_update": todoUpdate,
"summarize_chat": summarizeChat, "todo_delete": todoDelete,
"summarize_chat": summarizeChat,
} }
// callToolWithAgent calls the tool and applies any registered agent. // callToolWithAgent calls the tool and applies any registered agent.
@@ -1056,7 +1061,7 @@ var baseTools = []models.Tool{
Type: "function", Type: "function",
Function: models.ToolFunc{ Function: models.ToolFunc{
Name: "file_write", Name: "file_write",
Description: "Write content to a file. Use when you want to create or modify a file (overwrite or append).", Description: "Write content to a file. Will overwrite any content present.",
Parameters: models.ToolFuncParams{ Parameters: models.ToolFuncParams{
Type: "object", Type: "object",
Required: []string{"path", "content"}, Required: []string{"path", "content"},
@@ -1069,9 +1074,28 @@ var baseTools = []models.Tool{
Type: "string", Type: "string",
Description: "content to write to the file", Description: "content to write to the file",
}, },
"mode": models.ToolArgProps{ },
},
},
},
// file_write_append
models.Tool{
Type: "function",
Function: models.ToolFunc{
Name: "file_write_append",
Description: "Append content to a file.",
Parameters: models.ToolFuncParams{
Type: "object",
Required: []string{"path", "content"},
Properties: map[string]models.ToolArgProps{
"path": models.ToolArgProps{
Type: "string", Type: "string",
Description: "write mode: 'overwrite' to replace entire file content, 'append' to add to the end (defaults to 'overwrite')", Description: "path of the file to write to",
},
"content": models.ToolArgProps{
Type: "string",
Description: "content to write to the file",
}, },
}, },
}, },

1
tui.go
View File

@@ -1259,6 +1259,7 @@ func init() {
// cannot send msg in editMode or botRespMode // cannot send msg in editMode or botRespMode
if event.Key() == tcell.KeyEscape && !editMode && !botRespMode { if event.Key() == tcell.KeyEscape && !editMode && !botRespMode {
msgText := textArea.GetText() msgText := textArea.GetText()
// TODO: add shellmode command -> output to the chat history, or at least have an option
if shellMode && msgText != "" { if shellMode && msgText != "" {
// In shell mode, execute command instead of sending to LLM // In shell mode, execute command instead of sending to LLM
executeCommandAndDisplay(msgText) executeCommandAndDisplay(msgText)