diff --git a/pkg/agent/core.go b/pkg/agent/core.go index 557a54d..2eb8d4c 100644 --- a/pkg/agent/core.go +++ b/pkg/agent/core.go @@ -603,7 +603,7 @@ func (s *agent) SetSessionID(newID string) error { // actual context window (e.g. CodeWhisperer). 128k tokens is a safe default // for modern models. const defaultContextLength = 128000 -const defaultToolResultMaxBytes = 8192 +const defaultToolResultMaxBytes = 131072 // autoCompactLimit returns the token threshold for auto-compaction (75%). func (s *agent) autoCompactLimit(ctx context.Context) int { diff --git a/pkg/agent/loop.go b/pkg/agent/loop.go index 3a1153a..6db8216 100644 --- a/pkg/agent/loop.go +++ b/pkg/agent/loop.go @@ -346,8 +346,8 @@ func run(ctx context.Context, cfg agentConfig, state state) error { if !isErr && cfg.ToolResultMaxBytes > 0 && len(result) > cfg.ToolResultMaxBytes { orig := len(result) result = result[:cfg.ToolResultMaxBytes] - result += fmt.Sprintf("\n\n[result truncated: first %d of %d bytes shown; reissue with offset=%d to read more]", - cfg.ToolResultMaxBytes, orig, cfg.ToolResultMaxBytes) + result += fmt.Sprintf("\n\n[HARD LIMIT: %s output truncated — %d of %d bytes shown. This is a safety ceiling, not a semantic boundary.]", + tc.Name, cfg.ToolResultMaxBytes, orig) } if readSafe && !isErr { resultCache.Store(tc.Name+"\x00"+string(tc.Arguments), result) diff --git a/pkg/agent/loop_truncate_test.go b/pkg/agent/loop_truncate_test.go index 1912086..818a0ea 100644 --- a/pkg/agent/loop_truncate_test.go +++ b/pkg/agent/loop_truncate_test.go @@ -37,11 +37,11 @@ func TestTruncation_LargeResultTruncated(t *testing.T) { if !strings.HasPrefix(result, strings.Repeat("x", maxBytes)) { t.Errorf("result does not start with %d x's: %q", maxBytes, result[:min(len(result), 80)]) } - if !strings.Contains(result, "result truncated") { + if !strings.Contains(result, "HARD LIMIT") { t.Errorf("truncation hint missing from result: %q", result) } - if !strings.Contains(result, "offset=64") { - t.Errorf("offset hint missing from result: %q", result) + if !strings.Contains(result, "execute_code") { + t.Errorf("tool name missing from truncation hint: %q", result) } } @@ -120,7 +120,7 @@ func TestTruncation_ErrorNotTruncated(t *testing.T) { if len(toolEvs) != 1 { t.Fatalf("tool events = %d; want 1", len(toolEvs)) } - if strings.Contains(toolEvs[0], "result truncated") { + if strings.Contains(toolEvs[0], "HARD LIMIT") { t.Errorf("error result was truncated; should be preserved in full") } } @@ -152,7 +152,7 @@ func TestTruncation_CachedResultAlreadyTruncated(t *testing.T) { } // Both should be the truncated form. for i, ev := range toolEvs { - if !strings.Contains(ev, "result truncated") { + if !strings.Contains(ev, "HARD LIMIT") { t.Errorf("event[%d] missing truncation hint: %q", i, ev[:min(len(ev), 80)]) } }