v0.0.5: context compaction, minimal config, retry/search/code symbols/diff/status/test commands
This commit is contained in:
+42
-5
@@ -5,12 +5,15 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"agentu/internal/llm"
|
||||
)
|
||||
|
||||
const MaxToolOutputBytes = 64 * 1024
|
||||
|
||||
const truncationNoticeBudget = 160
|
||||
|
||||
type Tool interface {
|
||||
Definition() llm.Tool
|
||||
Execute(ctx context.Context, args json.RawMessage) (string, error)
|
||||
@@ -62,11 +65,13 @@ func ReadOnlyBuiltins(workingDir string) *Registry {
|
||||
fileRead := NewFileReadTool(workingDir)
|
||||
fileList := NewFileListTool(workingDir)
|
||||
fileSearch := NewFileSearchTool(workingDir)
|
||||
codeSymbols := NewCodeSymbolsTool(workingDir)
|
||||
|
||||
registry := NewRegistry(fileRead, fileList, fileSearch)
|
||||
registry := NewRegistry(fileRead, fileList, fileSearch, codeSymbols)
|
||||
registry.RegisterAlias("file.read", fileRead)
|
||||
registry.RegisterAlias("file.list", fileList)
|
||||
registry.RegisterAlias("file.search", fileSearch)
|
||||
registry.RegisterAlias("code.symbols", codeSymbols)
|
||||
return registry
|
||||
}
|
||||
|
||||
@@ -83,8 +88,8 @@ func Builtins(workingDir string) *Registry {
|
||||
|
||||
func AgentInstructions(workingDir string, yolo bool) string {
|
||||
searchInstructions := webSearchInstructions()
|
||||
readOnlyTools := "file_list, file_read, file_search, web_search, web_fetch"
|
||||
yoloTools := "file_list, file_read, file_search, file_write, shell_run, web_search, web_fetch"
|
||||
readOnlyTools := "file_list, file_read, file_search, code_symbols, web_search, web_fetch"
|
||||
yoloTools := "file_list, file_read, file_search, code_symbols, file_write, shell_run, web_search, web_fetch"
|
||||
if yolo {
|
||||
return fmt.Sprintf(`Local project context:
|
||||
- The project working directory is %q.
|
||||
@@ -92,6 +97,7 @@ func AgentInstructions(workingDir string, yolo bool) string {
|
||||
- Do not call tools for greetings, small talk, simple Q&A, or general questions that do not require local project or command context.
|
||||
- Do not explore the project preemptively. Do not call file_list just to discover context unless the user asks about project files or the answer truly depends on local files.
|
||||
- When the user asks to inspect, list, search, or read project files, use file_list, file_search, and file_read instead of saying you cannot access local files.
|
||||
- When the user asks about code structure, symbols, functions, methods, types, or definitions in Go files, use code_symbols before reading whole files.
|
||||
- When the user asks to run, execute, test, check, debug, or inspect a shell command, use shell_run. This includes local commands written in backticks, such as go, make, git, pwd, ls, ps, and similar terminal commands.
|
||||
- Do not use file tools as a substitute for a command execution request.
|
||||
- Do not start interactive or long-running sessions. Prefer bounded, non-interactive local commands with clear completion conditions.
|
||||
@@ -105,6 +111,7 @@ func AgentInstructions(workingDir string, yolo bool) string {
|
||||
- Do not call tools for greetings, small talk, simple Q&A, or general questions that do not require local project context.
|
||||
- Do not explore the project preemptively. Do not call file_list just to discover context unless the user asks about project files or the answer truly depends on local files.
|
||||
- When the user asks to inspect, list, search, or read project files, use file_list, file_search, and file_read instead of saying you cannot access local files.
|
||||
- When the user asks about code structure, symbols, functions, methods, types, or definitions in Go files, use code_symbols before reading whole files.
|
||||
- Shell command execution is disabled in this mode. When the user asks to run, execute, test, check, debug, or inspect a shell command, do not use file tools as a substitute; explain that they need to restart agentu with --yolo to enable shell_run.
|
||||
- %s
|
||||
- Tool paths should normally be relative to the project working directory.
|
||||
@@ -120,10 +127,40 @@ func JSONSchema(schema string) json.RawMessage {
|
||||
}
|
||||
|
||||
func FormatResult(output string) string {
|
||||
if len(output) <= MaxToolOutputBytes {
|
||||
return FormatResultLimit(output, MaxToolOutputBytes)
|
||||
}
|
||||
|
||||
func FormatResultLimit(output string, limit int) string {
|
||||
if limit <= 0 || len(output) <= limit {
|
||||
return output
|
||||
}
|
||||
return output[:MaxToolOutputBytes] + fmt.Sprintf("\n\n[truncated after %d bytes]", MaxToolOutputBytes)
|
||||
if limit <= truncationNoticeBudget {
|
||||
return output[:limit]
|
||||
}
|
||||
notice := fmt.Sprintf("\n\n[truncated: showing head and tail; omitted %d bytes]\n\n", len(output)-limit)
|
||||
keep := limit - len(notice)
|
||||
if keep <= 0 {
|
||||
return output[:limit]
|
||||
}
|
||||
headLen := keep / 2
|
||||
tailLen := keep - headLen
|
||||
head := trimHeadAtLine(output[:headLen])
|
||||
tail := trimTailAtLine(output[len(output)-tailLen:])
|
||||
return head + notice + tail
|
||||
}
|
||||
|
||||
func trimHeadAtLine(value string) string {
|
||||
if idx := strings.LastIndexByte(value, '\n'); idx > 0 {
|
||||
return value[:idx+1]
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func trimTailAtLine(value string) string {
|
||||
if idx := strings.IndexByte(value, '\n'); idx >= 0 && idx+1 < len(value) {
|
||||
return value[idx+1:]
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func FormatError(err error) string {
|
||||
|
||||
Reference in New Issue
Block a user