mirror of
https://github.com/lobehub/lobehub
synced 2026-04-21 17:47:27 +00:00
* ♻️ refactor(hetero-agent): persist per-step usage to each step assistant message Previously, usage tokens from a multi-step Claude Code run were accumulated across all turns and written only to the final assistant message, leaving intermediate step messages with no usage metadata. Each Claude Code `turn_metadata` event carries per-turn token usage (deduped by adapter per message.id), so write it straight through to the current step's assistant message via persistQueue (runs after any in-flight stream_start(newStep) that swaps currentAssistantMessageId). The `result_usage` grand-total event is intentionally dropped — applying it would overwrite the last step with the sum of all prior steps. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ♻️ refactor(hetero-agent): normalize usage inside CC adapter (UsageData) Follows the same principle as LOBE-7363: provider-native shape knowledge stays in the adapter, executor only sees normalized events. The previous commit left Anthropic-shape fields (input_tokens, cache_creation_input_tokens, cache_read_input_tokens) leaking into the executor via `buildUsageMetadata`. Introduce `UsageData` in `@lobechat/heterogeneous-agents` types with LobeHub's MessageMetadata.usage field names. The Claude Code adapter now normalizes Anthropic usage into `UsageData` before emitting step_complete, for both turn_metadata (per-turn) and result_usage (grand total). Executor drops `buildUsageMetadata` and writes `{ metadata: { usage: event.data.usage } }` directly. Future adapters (Codex, Kimi-CLI) normalize their native usage into the same shape; executor stays provider-agnostic. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ♻️ refactor(hetero-agent): persist per-step provider alongside model CC / hetero-agent assistant messages were writing `model` per step but leaving `message.provider` NULL, so pricing/usage lookups could not key on the adapter (e.g. `claude-code`, billed via CLI subscription rather than raw Anthropic API rates). CC adapter now emits `provider: 'claude-code'` on every turn_metadata event (same collection point as model + normalized usage). Executor tracks `lastProvider` alongside `lastModel` and writes it into: - the step-boundary update for the previous step - `createMessage` for each new step's assistant - the onComplete write for the final step Provider choice is the CLI flavor (what the adapter knows), not the wrapped model's native vendor — CC runs under its own subscription billing, so downstream pricing must treat `claude-code` as its own provider rather than conflating with `anthropic`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 🐛 fix(hetero-agent): read authoritative usage from message_delta, not assistant Under `--include-partial-messages` (enabled by the CC adapter preset), Claude Code echoes a STALE usage snapshot from `message_start` on every content-block `assistant` event — e.g. `output_tokens: 8` or `1` — and never updates that snapshot as more output tokens are generated. The authoritative per-turn total arrives on a separate `stream_event: message_delta` with the final `input_tokens` + cache counts + cumulative `output_tokens` (e.g. 265). The adapter previously grabbed usage from the first `assistant` event per message.id and deduped, so DB rows ended up with `totalOutputTokens: 1` on every CC turn. Move turn_metadata emission from `handleAssistant` to a new `message_delta` case in `handleStreamEvent`. `handleAssistant` still tracks the latest model so turn_metadata (emitted later on message_delta) carries the correct model even if `message_start` doesn't. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 💄 style(extras-usage): fall back to metadata.usage when top-level is absent The assistant Extras bar passes `message.usage` to the Usage component, which conditionally renders a token-count badge on `!!usage.totalTokens`. Nothing in the read path aggregates `message.metadata.usage` up to `message.usage`, so the top-level field is always undefined for DB-read messages — the badge never shows for CC/hetero turns (and in practice also skips the gateway path where usage only lands in `metadata.usage`). Prefer `usage` when the top-level field is populated, fall back to `metadata.usage` otherwise. Both fields are the same `ModelUsage` shape, so the Usage/TokenDetail components don't need any other change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ♻️ refactor(extras-usage): promote metadata.usage inside conversation-flow parse The previous fix spread a `usage ?? metadata?.usage` fallback across each renderer site that passed usage to the Extras bar. Consolidate: `parse` (src/store → packages/conversation-flow) is the single renderer-side transform every consumer flows through, so promote `metadata.usage` onto the top-level `usage` field there and revert the per-site fallbacks. UIChatMessage exposes a canonical `usage` field, but no server-side or client-side transform populated it — executors write to `metadata.usage` (canonical storage, JSONB-friendly). Doing the promotion in parse keeps the rule in one place, close to where display shapes are built, and covers both desktop (local PGlite) and web (remote Postgres) without a backend deploy. Top-level `usage` is preserved when already present (e.g. group-level aggregates) — `metadata.usage` is strictly a fallback. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| agent-gateway-client | ||
| agent-manager-runtime | ||
| agent-runtime | ||
| agent-templates | ||
| agent-tracing | ||
| builtin-agents | ||
| builtin-skills | ||
| builtin-tool-activator | ||
| builtin-tool-agent-builder | ||
| builtin-tool-agent-documents | ||
| builtin-tool-agent-management | ||
| builtin-tool-brief | ||
| builtin-tool-calculator | ||
| builtin-tool-claude-code | ||
| builtin-tool-cloud-sandbox | ||
| builtin-tool-creds | ||
| builtin-tool-cron | ||
| builtin-tool-group-agent-builder | ||
| builtin-tool-group-management | ||
| builtin-tool-gtd | ||
| builtin-tool-knowledge-base | ||
| builtin-tool-local-system | ||
| builtin-tool-memory | ||
| builtin-tool-message | ||
| builtin-tool-notebook | ||
| builtin-tool-page-agent | ||
| builtin-tool-remote-device | ||
| builtin-tool-skill-store | ||
| builtin-tool-skills | ||
| builtin-tool-task | ||
| builtin-tool-topic-reference | ||
| builtin-tool-user-interaction | ||
| builtin-tool-web-browsing | ||
| builtin-tool-web-onboarding | ||
| builtin-tools | ||
| business | ||
| chat-adapter-feishu | ||
| chat-adapter-qq | ||
| chat-adapter-wechat | ||
| config | ||
| const | ||
| context-engine | ||
| conversation-flow | ||
| database | ||
| desktop-bridge | ||
| device-gateway-client | ||
| edge-config | ||
| editor-runtime | ||
| electron-client-ipc | ||
| electron-server-ipc | ||
| eval-dataset-parser | ||
| eval-rubric | ||
| fetch-sse | ||
| file-loaders | ||
| heterogeneous-agents | ||
| local-file-shell | ||
| markdown-patch | ||
| memory-user-memory | ||
| model-bank | ||
| model-runtime | ||
| observability-otel | ||
| openapi | ||
| prompts | ||
| python-interpreter | ||
| shared-tool-ui | ||
| ssrf-safe-fetch | ||
| tool-runtime | ||
| types | ||
| utils | ||
| web-crawler | ||