From 7a7e205cc809fc23c58db01cff19bb404d81c24c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E6=99=BA=E8=B6=850668000959?= Date: Sat, 6 Jun 2026 00:28:32 +0800 Subject: [PATCH] fix(context): expose history tokens and remove leaked state files Address remaining review feedback: 1) Add HistoryTokens field to ContextUsage/ContextStats, showing history-only token count in /context and frontend UI alongside SummarizeAtTokens so users can see the actual summarization trigger comparison. 2) Remove .codebuddy/github-contribute/ state files accidentally included in the PR. --- .codebuddy/github-contribute/config.md | 17 -------------- .codebuddy/github-contribute/handoff.md | 12 ---------- .codebuddy/github-contribute/journal.md | 22 ------------------- .codebuddy/github-contribute/pr-board.md | 15 ------------- .codebuddy/github-contribute/queue.md | 16 -------------- pkg/agent/agent_command.go | 1 + pkg/agent/context_usage.go | 10 ++++----- pkg/bus/types.go | 3 ++- pkg/channels/pico/pico.go | 1 + pkg/channels/pico/pico_test.go | 4 ++++ pkg/commands/cmd_context.go | 3 ++- pkg/commands/runtime.go | 1 + .../components/chat/context-usage-ring.tsx | 8 +++++++ web/frontend/src/features/chat/protocol.ts | 1 + web/frontend/src/store/chat.ts | 1 + 15 files changed, 25 insertions(+), 90 deletions(-) delete mode 100644 .codebuddy/github-contribute/config.md delete mode 100644 .codebuddy/github-contribute/handoff.md delete mode 100644 .codebuddy/github-contribute/journal.md delete mode 100644 .codebuddy/github-contribute/pr-board.md delete mode 100644 .codebuddy/github-contribute/queue.md diff --git a/.codebuddy/github-contribute/config.md b/.codebuddy/github-contribute/config.md deleted file mode 100644 index 1c4123f59..000000000 --- a/.codebuddy/github-contribute/config.md +++ /dev/null @@ -1,17 +0,0 @@ -# GitHub Contribution Config — sipeed/picoclaw - -- run_mode: resume -- credential_source: session_override_env -- github_username: chengzhichao-xydt -- github_token: [session-provided] -- auth_mode: env_pat -- pat_type: classic -- max_open_prs_per_project: 5 -- max_prs_waiting_for_first_review: 3 -- tasks_per_batch: 3 -- pr_recheck_interval_minutes: 20 -- report_language: zh-CN -- report_timezone: Asia/Shanghai (UTC+8) -- default_branch_prefix: codex -- default_risk_level: low -- github_communication_language: en diff --git a/.codebuddy/github-contribute/handoff.md b/.codebuddy/github-contribute/handoff.md deleted file mode 100644 index a49021db7..000000000 --- a/.codebuddy/github-contribute/handoff.md +++ /dev/null @@ -1,12 +0,0 @@ -# Handoff — sipeed/picoclaw - -Last updated: 2026-06-05 09:30 UTC+8 -Run mode: resume (fix round complete) - -## Quick Resume -- Repo: sipeed/picoclaw (fork: chengzhichao-xydt/picoclaw) -- Upstream main: 5224b9a4 -- Open PRs: #3001, #2985 — both pushed with review fixes -- Both waiting for afjcjsbx re-review -- 7 merged PRs this round -- Next: monitor CI/review, scan new candidates if desired diff --git a/.codebuddy/github-contribute/journal.md b/.codebuddy/github-contribute/journal.md deleted file mode 100644 index 41389855f..000000000 --- a/.codebuddy/github-contribute/journal.md +++ /dev/null @@ -1,22 +0,0 @@ -# Journal — sipeed/picoclaw - -## 2026-06-05 08:58 UTC+8 — Resume + Fix round - -- run_mode=resume, 2 open PRs identified -- Initialized repo-local state directory (.codebuddy/github-contribute) -- Cleaned up merged local branches - -## 2026-06-05 09:05 UTC+8 — #3001 fix -- Added TestShellTool_SchemelessURLDetection to shell_test.go -- Covers all 7 web schemes + multi-URL commands -- Test PASS, pushed a6735517, commented on PR - -## 2026-06-05 09:25 UTC+8 — #2985 fix -- Issue 1: Added comment explaining summarizeAtTokens vs UsedTokens difference -- Issue 2: Replaced hardcoded strings with i18n keys (5 locale files) -- Issue 3: Added SummarizeAtTokens field to pico_test.go with assertion -- Build PASS, pico test PASS, pushed 296a8ae2, commented on PR - -## 2026-06-05 09:30 UTC+8 — State update -- Both PRs now in 'wait' — awaiting afjcjsbx re-review -- Ready for next batch of candidate scanning diff --git a/.codebuddy/github-contribute/pr-board.md b/.codebuddy/github-contribute/pr-board.md deleted file mode 100644 index bccd7a70c..000000000 --- a/.codebuddy/github-contribute/pr-board.md +++ /dev/null @@ -1,15 +0,0 @@ -# PR Board — sipeed/picoclaw - -## awaiting_maintainer_review (2) - -### #3001 — fix(tools): allow scheme-less URLs in workspace guard -- Branch: codex/workspace-guard-schemeless-url -- Fix: Added TestShellTool_SchemelessURLDetection (7 schemes + multi-URL) -- Pushed: a6735517 | Comment: https://github.com/sipeed/picoclaw/pull/3001#issuecomment-4627308317 -- Next: wait for afjcjsbx re-review - -### #2985 — fix(context): show both summarize and compress thresholds in /context -- Branch: codex/context-show-summarize-threshold -- Fix: ① Threshold alignment comment ② i18n (5 locales) ③ Test coverage for summarize_at_tokens -- Pushed: 296a8ae2 | Comment: https://github.com/sipeed/picoclaw/pull/2985#issuecomment-4627346564 -- Next: wait for afjcjsbx re-review diff --git a/.codebuddy/github-contribute/queue.md b/.codebuddy/github-contribute/queue.md deleted file mode 100644 index a522d774c..000000000 --- a/.codebuddy/github-contribute/queue.md +++ /dev/null @@ -1,16 +0,0 @@ -# Active Queue — sipeed/picoclaw - -## Active (0) - -## Waiting for maintainer review (2) - -| ID | PR | Title | Status | Action | -|----|-----|-------|--------|--------| -| T1 | #3001 | fix(tools): allow scheme-less URLs in workspace guard | ✅ fix pushed (unit tests added) | wait | -| T2 | #2985 | fix(context): show both summarize and compress thresholds | ✅ fix pushed (3 review issues) | wait | - -## Merged (7) -#3000, #2999, #2996, #2995, #2992, #2991, #2986 - -## Blocked (0) -None diff --git a/pkg/agent/agent_command.go b/pkg/agent/agent_command.go index efd5326cf..277d1bda8 100644 --- a/pkg/agent/agent_command.go +++ b/pkg/agent/agent_command.go @@ -352,6 +352,7 @@ func (al *AgentLoop) buildCommandsRuntime( return &commands.ContextStats{ UsedTokens: usage.UsedTokens, TotalTokens: usage.TotalTokens, + HistoryTokens: usage.HistoryTokens, CompressAtTokens: usage.CompressAtTokens, SummarizeAtTokens: usage.SummarizeAtTokens, UsedPercent: usage.UsedPercent, diff --git a/pkg/agent/context_usage.go b/pkg/agent/context_usage.go index ca170d20d..1463dde95 100644 --- a/pkg/agent/context_usage.go +++ b/pkg/agent/context_usage.go @@ -64,12 +64,9 @@ func computeContextUsage(agent *AgentInstance, sessionKey string) *bus.ContextUs // summarizeAt = soft summarization trigger: matches maybeSummarize's // threshold (contextWindow * SummarizeTokenPercent / 100). // - // NOTE: The engine's maybeSummarize compares this threshold against - // history-message tokens only (via estimateTokens), while UsedTokens - // (shown in /context) includes system prompt, summary, and tool - // definitions on top of history tokens. A "Used > SummarizeAt" display - // does not necessarily mean summarization will fire — the engine may - // still consider the history-token budget to be under threshold. + // The engine compares this against history-message tokens ONLY (not + // UsedTokens). HistoryTokens is exposed alongside UsedTokens so the + // UI can show both values and avoid user confusion. summarizeAt := contextWindow * agent.SummarizeTokenPercent / 100 if summarizeAt <= 0 { summarizeAt = compressAt @@ -86,6 +83,7 @@ func computeContextUsage(agent *AgentInstance, sessionKey string) *bus.ContextUs return &bus.ContextUsage{ UsedTokens: usedTokens, TotalTokens: contextWindow, + HistoryTokens: historyTokens, CompressAtTokens: compressAt, SummarizeAtTokens: summarizeAt, UsedPercent: usedPercent, diff --git a/pkg/bus/types.go b/pkg/bus/types.go index 6863a49ec..0e23ea0f1 100644 --- a/pkg/bus/types.go +++ b/pkg/bus/types.go @@ -66,8 +66,9 @@ type OutboundScope struct { type ContextUsage struct { UsedTokens int `json:"used_tokens"` TotalTokens int `json:"total_tokens"` // model context window + HistoryTokens int `json:"history_tokens"` // history-message tokens only (what maybeSummarize checks) CompressAtTokens int `json:"compress_at_tokens"` // hard budget compression threshold (contextWindow - maxTokens) - SummarizeAtTokens int `json:"summarize_at_tokens"` // soft summarization trigger (contextWindow * summarizeTokenPercent / 100) + SummarizeAtTokens int `json:"summarize_at_tokens"` // soft summarization trigger (vs history tokens) UsedPercent int `json:"used_percent"` // 0-100, relative to compressAt } diff --git a/pkg/channels/pico/pico.go b/pkg/channels/pico/pico.go index adceecad7..587f889ab 100644 --- a/pkg/channels/pico/pico.go +++ b/pkg/channels/pico/pico.go @@ -1396,6 +1396,7 @@ func setContextUsagePayload(payload map[string]any, u *bus.ContextUsage) { payload["context_usage"] = map[string]any{ "used_tokens": u.UsedTokens, "total_tokens": u.TotalTokens, + "history_tokens": u.HistoryTokens, "compress_at_tokens": u.CompressAtTokens, "summarize_at_tokens": u.SummarizeAtTokens, "used_percent": u.UsedPercent, diff --git a/pkg/channels/pico/pico_test.go b/pkg/channels/pico/pico_test.go index 4a12f542c..b776b4149 100644 --- a/pkg/channels/pico/pico_test.go +++ b/pkg/channels/pico/pico_test.go @@ -604,6 +604,7 @@ func TestBeginStream_FinalizeIncludesContextUsage(t *testing.T) { if err := contextStreamer.FinalizeWithContext(context.Background(), "final", &bus.ContextUsage{ UsedTokens: 10, TotalTokens: 100, + HistoryTokens: 5, CompressAtTokens: 80, SummarizeAtTokens: 60, UsedPercent: 10, @@ -628,6 +629,9 @@ func TestBeginStream_FinalizeIncludesContextUsage(t *testing.T) { if got := rawUsage["used_tokens"]; got != float64(10) { t.Fatalf("used_tokens = %#v, want 10", got) } + if got := rawUsage["history_tokens"]; got != float64(5) { + t.Fatalf("history_tokens = %#v, want 5", got) + } if got := rawUsage["summarize_at_tokens"]; got != float64(60) { t.Fatalf("summarize_at_tokens = %#v, want 60", got) } diff --git a/pkg/commands/cmd_context.go b/pkg/commands/cmd_context.go index 4b4eddfa6..22a441d42 100644 --- a/pkg/commands/cmd_context.go +++ b/pkg/commands/cmd_context.go @@ -30,11 +30,12 @@ func formatContextStats(s *ContextStats) string { } usedWindowPercent := s.UsedTokens * 100 / max(s.TotalTokens, 1) msg := fmt.Sprintf( - "Context usage \nMessages: %d \nUsed: ~%d / %d tokens (%d%%) \nCompress at: %d tokens \nSummarize at: %d tokens \nCompression progress: %d%% \nRemaining: ~%d tokens", + "Context usage \nMessages: %d \nUsed: ~%d / %d tokens (%d%%) \nHistory: ~%d tokens \nCompress at: %d tokens \nSummarize at: %d tokens \nCompression progress: %d%% \nRemaining: ~%d tokens", s.MessageCount, s.UsedTokens, s.TotalTokens, usedWindowPercent, + s.HistoryTokens, s.CompressAtTokens, s.SummarizeAtTokens, s.UsedPercent, diff --git a/pkg/commands/runtime.go b/pkg/commands/runtime.go index ba7d003c4..2c773eb0f 100644 --- a/pkg/commands/runtime.go +++ b/pkg/commands/runtime.go @@ -31,6 +31,7 @@ type MCPToolInfo struct { type ContextStats struct { UsedTokens int TotalTokens int // model context window + HistoryTokens int // history-only tokens (what maybeSummarize checks) CompressAtTokens int // hard budget compression threshold SummarizeAtTokens int // soft summarization trigger UsedPercent int // 0-100 diff --git a/web/frontend/src/components/chat/context-usage-ring.tsx b/web/frontend/src/components/chat/context-usage-ring.tsx index 1a60d62c6..000bcb4dd 100644 --- a/web/frontend/src/components/chat/context-usage-ring.tsx +++ b/web/frontend/src/components/chat/context-usage-ring.tsx @@ -146,6 +146,14 @@ export function ContextUsageRing({
+ {usage.history_tokens != null && usage.history_tokens > 0 && ( +
+ History + + {formatTokens(usage.history_tokens)} + +
+ )}
{t("chat.contextCompressAt")} diff --git a/web/frontend/src/features/chat/protocol.ts b/web/frontend/src/features/chat/protocol.ts index 59eff92cd..f2fe4cddd 100644 --- a/web/frontend/src/features/chat/protocol.ts +++ b/web/frontend/src/features/chat/protocol.ts @@ -78,6 +78,7 @@ function parseContextUsage( return { used_tokens: used, total_tokens: total, + history_tokens: obj.history_tokens != null ? Number(obj.history_tokens) : undefined, compress_at_tokens: Number(obj.compress_at_tokens) || 0, summarize_at_tokens: obj.summarize_at_tokens != null ? Number(obj.summarize_at_tokens) : undefined, used_percent: Number(obj.used_percent) || 0, diff --git a/web/frontend/src/store/chat.ts b/web/frontend/src/store/chat.ts index 7c605b13f..7d733784b 100644 --- a/web/frontend/src/store/chat.ts +++ b/web/frontend/src/store/chat.ts @@ -52,6 +52,7 @@ export interface ChatMessage { export interface ContextUsage { used_tokens: number total_tokens: number + history_tokens?: number compress_at_tokens: number summarize_at_tokens?: number used_percent: number