feat: complete v0.3.1 agent workflow
This commit is contained in:
+47
-6
@@ -34,12 +34,39 @@ type MutatingTool interface {
|
||||
Mutates() bool
|
||||
}
|
||||
|
||||
// CallMutatingTool can refine a tool's mutation classification per call.
|
||||
// This is useful for tools such as apply_patch whose dry-run mode is read-only.
|
||||
type CallMutatingTool interface {
|
||||
MutatesCall(args json.RawMessage) bool
|
||||
}
|
||||
|
||||
// PreviewableTool describes a pending mutation for interactive approval.
|
||||
type PreviewableTool interface {
|
||||
Preview(ctx context.Context, args json.RawMessage) (string, error)
|
||||
}
|
||||
|
||||
// TargetPathTool reports files that should be snapshotted before a mutation.
|
||||
type TargetPathTool interface {
|
||||
TargetPaths(args json.RawMessage) ([]string, error)
|
||||
}
|
||||
|
||||
// IsMutating reports whether tool implements MutatingTool and returns true.
|
||||
func IsMutating(tool Tool) bool {
|
||||
mutating, ok := tool.(MutatingTool)
|
||||
return ok && mutating.Mutates()
|
||||
}
|
||||
|
||||
// IsMutatingCall reports whether this invocation modifies external state.
|
||||
func IsMutatingCall(tool Tool, args json.RawMessage) bool {
|
||||
if !IsMutating(tool) {
|
||||
return false
|
||||
}
|
||||
if call, ok := tool.(CallMutatingTool); ok {
|
||||
return call.MutatesCall(args)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
type Registry struct {
|
||||
tools map[string]Tool
|
||||
primary []string
|
||||
@@ -90,8 +117,10 @@ func ReadOnlyBuiltins(workingDir string) *Registry {
|
||||
gitStatus := NewGitStatusTool(workingDir)
|
||||
gitDiff := NewGitDiffTool(workingDir)
|
||||
gitLog := NewGitLogTool(workingDir)
|
||||
projectOutline := NewProjectOutlineTool(workingDir)
|
||||
todo := NewTodoTool()
|
||||
|
||||
registry := NewRegistry(fileRead, fileList, fileSearch, codeSymbols, gitStatus, gitDiff, gitLog)
|
||||
registry := NewRegistry(fileRead, fileList, fileSearch, codeSymbols, projectOutline, todo, gitStatus, gitDiff, gitLog)
|
||||
registry.RegisterAlias("file.read", fileRead)
|
||||
registry.RegisterAlias("file.list", fileList)
|
||||
registry.RegisterAlias("file.search", fileSearch)
|
||||
@@ -106,36 +135,48 @@ func Builtins(workingDir string) *Registry {
|
||||
registry := ReadOnlyBuiltins(workingDir)
|
||||
fileWrite := NewFileWriteTool(workingDir)
|
||||
fileEdit := NewFileEditTool(workingDir)
|
||||
applyPatch := NewApplyPatchTool(workingDir)
|
||||
shellRun := NewShellRunTool(workingDir)
|
||||
registry.Register(fileWrite)
|
||||
registry.Register(fileEdit)
|
||||
registry.Register(applyPatch)
|
||||
registry.Register(shellRun)
|
||||
registry.RegisterAlias("file.write", fileWrite)
|
||||
registry.RegisterAlias("file.edit", fileEdit)
|
||||
registry.RegisterAlias("apply.patch", applyPatch)
|
||||
registry.RegisterAlias("shell.run", shellRun)
|
||||
return registry
|
||||
}
|
||||
|
||||
func AgentInstructions(workingDir string, yolo bool) string {
|
||||
return AgentInstructionsForMode(workingDir, yolo, yolo)
|
||||
}
|
||||
|
||||
func AgentInstructionsForMode(workingDir string, writesEnabled bool, yolo bool) string {
|
||||
searchInstructions := webSearchInstructions()
|
||||
readOnlyTools := "file_list, file_read, file_search, code_symbols, git_status, git_diff, git_log, web_search, web_fetch"
|
||||
yoloTools := "file_list, file_read, file_search, code_symbols, file_write, file_edit, shell_run, git_status, git_diff, git_log, web_search, web_fetch"
|
||||
if yolo {
|
||||
readOnlyTools := "file_list, file_read, file_search, code_symbols, project_outline, todo, git_status, git_diff, git_log, web_search, web_fetch"
|
||||
writeTools := "file_list, file_read, file_search, code_symbols, project_outline, todo, file_write, file_edit, apply_patch, shell_run, git_status, git_diff, git_log, web_search, web_fetch"
|
||||
if writesEnabled {
|
||||
approval := "Mutating tools require interactive user approval before execution. Explain the intended change through the tool call and wait for the decision."
|
||||
if yolo {
|
||||
approval = "Mutating tools execute automatically because --yolo is enabled."
|
||||
}
|
||||
return fmt.Sprintf(`Local project context:
|
||||
- The project working directory is %q.
|
||||
- Tools are available, but use them only when needed to satisfy the user's request.
|
||||
- %s
|
||||
- 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.
|
||||
- When editing existing files, prefer file_edit for small or localized changes; use file_write only for creating files, replacing whole files intentionally, or appending.
|
||||
- Use project_outline first when the user asks for a broad understanding of a project; prefer file_edit for localized changes, apply_patch for related multi-file changes, and file_write for whole-file creation or replacement.
|
||||
- Do not use file tools as a substitute for a command execution request.
|
||||
- When the user asks about changed files, diffs, or git history, use git_status, git_diff, or git_log instead of shell_run.
|
||||
- Do not start interactive or long-running sessions. Prefer bounded, non-interactive local commands with clear completion conditions.
|
||||
- %s
|
||||
- Tool paths should normally be relative to the project working directory.
|
||||
- Available tools: %s.`, workingDir, searchInstructions, yoloTools)
|
||||
- Available tools: %s.`, workingDir, approval, searchInstructions, writeTools)
|
||||
}
|
||||
return fmt.Sprintf(`Local project context:
|
||||
- The project working directory is %q.
|
||||
|
||||
Reference in New Issue
Block a user