fix(agent): resolveFinalContent, remove DefaultResponse, strengthen system prompt
pkg/agent/loop.go
- resolveFinalContent() replaces the DefaultResponse sentinel string:
1. Return trimmed finalContent if non-empty
2. Walk steps in reverse and return the last non-empty step text
3. Walk tool results in reverse, scoring candidates (exec/write > search
results > error messages); return best if score > 0
4. Return an error with step/tool_call counts if nothing is recoverable
- runAgentLoop and runStreaming both call resolveFinalContent; on error
they log and propagate rather than silently returning an empty string
- processOptions.DefaultResponse field removed; all callers updated
- postProcess: removed the DefaultResponse fallback assignment
- toolNames() helper added for structured log fields
pkg/agent/loop_test.go
- TestResolveFinalContent_RecoversFromPriorStepText: empty final text
recovered from a prior step's TextContent
- TestResolveFinalContent_ErrorsWhenNoTextExists: returns error when only
tool calls exist and no text is present
- TestResolveFinalContent_RecoversFromToolResultText: exec tool result
text recovered as final response
pkg/agent/context.go
- System prompt additions:
4. No fabricated data: if access is denied or a tool fails, say so
explicitly; do not invent file contents, credentials, or sample data
5. Completion discipline: execute required tools before final answer;
do not end with intent-only statements like "I'll do that"
6. Context management (renumbered from 4)
This commit is contained in:
parent
d8c5592388
commit
d5fc69746e
2 changed files with 77 additions and 1 deletions
|
|
@ -123,7 +123,11 @@ Your workspace is at: %s
|
||||||
|
|
||||||
3. **Memory** - Use the memory tool to store important facts, preferences, and decisions.
|
3. **Memory** - Use the memory tool to store important facts, preferences, and decisions.
|
||||||
|
|
||||||
4. **Context Management** - You MUST consolidate your context to stay effective during long tasks. Use start_focus at the beginning of any investigation or multi-step task. After 10-15 tool calls, call complete_focus with a summary of what you learned and accomplished. This compresses your working context and persists knowledge for future reference. Failing to consolidate will degrade your performance as context grows.`,
|
4. **No fabricated data** - If access is denied, a tool fails, or a request is outside workspace/sandbox, explicitly say so. Do NOT invent file contents, command output, credentials, or sample sensitive data.
|
||||||
|
|
||||||
|
5. **Completion discipline** - For actionable requests, execute the required tools before your final answer. Do NOT end with only intent statements like "I'll do that" or "let me do that."
|
||||||
|
|
||||||
|
6. **Context Management** - You MUST consolidate your context to stay effective during long tasks. Use start_focus at the beginning of any investigation or multi-step task. After 10-15 tool calls, call complete_focus with a summary of what you learned and accomplished. This compresses your working context and persists knowledge for future reference. Failing to consolidate will degrade your performance as context grows.`,
|
||||||
now, runtime, workspacePath, workspacePath, toolsSection)
|
now, runtime, workspacePath, workspacePath, toolsSection)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -541,3 +541,75 @@ func TestToolResult_UserFacingToolDoesSendMessage(t *testing.T) {
|
||||||
t.Errorf("Expected 'Command output: hello world', got: %s", response)
|
t.Errorf("Expected 'Command output: hello world', got: %s", response)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestResolveFinalContent_RecoversFromPriorStepText(t *testing.T) {
|
||||||
|
al := &AgentLoop{}
|
||||||
|
steps := []fantasy.StepResult{
|
||||||
|
{
|
||||||
|
Response: fantasy.Response{
|
||||||
|
Content: fantasy.ResponseContent{
|
||||||
|
fantasy.TextContent{Text: "Recovered final response"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Response: fantasy.Response{
|
||||||
|
Content: fantasy.ResponseContent{
|
||||||
|
fantasy.ToolCallContent{ToolName: "read_file"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
got, err := al.resolveFinalContent("", steps)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("resolveFinalContent returned error: %v", err)
|
||||||
|
}
|
||||||
|
if got != "Recovered final response" {
|
||||||
|
t.Fatalf("expected recovered text, got %q", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResolveFinalContent_ErrorsWhenNoTextExists(t *testing.T) {
|
||||||
|
al := &AgentLoop{}
|
||||||
|
steps := []fantasy.StepResult{
|
||||||
|
{
|
||||||
|
Response: fantasy.Response{
|
||||||
|
Content: fantasy.ResponseContent{
|
||||||
|
fantasy.ToolCallContent{ToolName: "write_file"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := al.resolveFinalContent("", steps)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected error when no final text exists")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResolveFinalContent_RecoversFromToolResultText(t *testing.T) {
|
||||||
|
al := &AgentLoop{}
|
||||||
|
steps := []fantasy.StepResult{
|
||||||
|
{
|
||||||
|
Response: fantasy.Response{
|
||||||
|
Content: fantasy.ResponseContent{
|
||||||
|
fantasy.ToolResultContent{
|
||||||
|
ToolName: "exec",
|
||||||
|
Result: fantasy.ToolResultOutputContentText{
|
||||||
|
Text: "progressive-test-marker",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
got, err := al.resolveFinalContent("", steps)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("resolveFinalContent returned error: %v", err)
|
||||||
|
}
|
||||||
|
if got != "progressive-test-marker" {
|
||||||
|
t.Fatalf("expected tool result text, got %q", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue