mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-13 16:14:57 +00:00
fix(tools): hint model when shell commands target DB-backed memory files
Memory files (MEMORY.md, memory/*.md) are stored in PostgreSQL, not on disk. When the model uses exec to run cat/ls/grep/find on memory paths, short-circuit with a hint to use memory_search or memory_get instead. Also append [Source: database, not filesystem] to read_file and list_files results served from the memory interceptor.
This commit is contained in:
1 parent
99720892a7
commit
7ba3a5115a
4 files changed
+54
-2
No files matched your search
@@ -0,0 +1,47 @@
|
||||
package tools
|
||||
|
||||
import "strings"
|
||||
|
||||
// memoryHintPrefixes are shell commands that read/list/search filesystem content.
|
||||
// If these target memory paths, the model should use dedicated memory tools instead.
|
||||
var memoryHintPrefixes = []string{
|
||||
"cat ", "head ", "tail ", "less ", "more ",
|
||||
"grep ", "rg ", "ag ",
|
||||
"find ", "ls ", "wc ",
|
||||
}
|
||||
|
||||
// memoryPathTokens are path fragments indicating memory file access.
|
||||
var memoryPathTokens = []string{
|
||||
"MEMORY.md", "memory.md", "memory/",
|
||||
}
|
||||
|
||||
// MaybeMemoryExecHint checks if a shell command targets memory files
|
||||
// (which live in the database, not on disk) and returns an LLM hint.
|
||||
// Returns empty string if no memory path detected.
|
||||
func MaybeMemoryExecHint(command string) string {
|
||||
trimmed := strings.TrimSpace(command)
|
||||
if trimmed == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Check if command uses a filesystem read/list/search binary.
|
||||
hasReadCmd := false
|
||||
for _, prefix := range memoryHintPrefixes {
|
||||
if strings.HasPrefix(trimmed, prefix) {
|
||||
hasReadCmd = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !hasReadCmd {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Check if the command references a memory path.
|
||||
for _, token := range memoryPathTokens {
|
||||
if strings.Contains(trimmed, token) {
|
||||
return "[HINT] Memory files are in the database, not on disk. Use memory_search or memory_get tool instead."
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
@@ -139,7 +139,7 @@ func (t *ReadFileTool) Execute(ctx context.Context, args map[string]any) *Result
|
||||
if content == "" {
|
||||
return SilentResult(fmt.Sprintf("(memory file %s does not exist yet — it will be created when memory is saved)", path))
|
||||
}
|
||||
return SilentResult(content)
|
||||
return SilentResult(content + "\n\n[Source: database, not filesystem]")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ func (t *ListFilesTool) Execute(ctx context.Context, args map[string]any) *Resul
|
||||
if listing == "" {
|
||||
return SilentResult("No memory files stored yet")
|
||||
}
|
||||
return SilentResult(listing)
|
||||
return SilentResult(listing + "\n[Source: database, not filesystem]")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -199,6 +199,11 @@ func (t *ExecTool) Execute(ctx context.Context, args map[string]any) *Result {
|
||||
}
|
||||
}
|
||||
|
||||
// Memory path hint: shell commands can't access DB-backed memory files.
|
||||
if hint := MaybeMemoryExecHint(normalizedCommand); hint != "" {
|
||||
return SilentResult(hint)
|
||||
}
|
||||
|
||||
// Credentialed exec: if command matches a configured binary, use Direct Exec Mode.
|
||||
// This bypasses approval (admin trust) and shell (security).
|
||||
if cred, binary, cmdArgs := t.lookupCredentialedBinary(ctx, command); cred != nil {
|
||||
|
||||
Reference in new issue
Block a user