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:
ZanzyTHEbar 2026-02-21 00:41:10 +00:00
parent d8c5592388
commit d5fc69746e
2 changed files with 77 additions and 1 deletions

View file

@ -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)
} }

View file

@ -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)
}
}