lobehub/packages
Arvin Xu ccbb75da06
♻️ refactor(hetero-agent): persist per-step usage to each step assistant message (#13964)
* ♻️ 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>
2026-04-19 16:19:18 +08:00
..
agent-gateway-client ♻️ refactor: extract agent-stream into @lobechat/agent-gateway-client package (#13866) 2026-04-16 11:25:32 +08:00
agent-manager-runtime ♻️ refactor: add more tools in lobe-agent-manangerment(modify、update、delete) (#13842) 2026-04-15 17:57:05 +08:00
agent-runtime feat(agent-runtime): server-side human approval flow (#13829) 2026-04-15 11:07:06 +08:00
agent-templates 🐛 fix: allow templates to specify policyLoad so default docs are fully injected (#13672) 2026-04-09 10:09:05 +08:00
agent-tracing 🐛 fix: resolve agent runtime service error serialization producing [object Object] (#13704) 2026-04-10 00:01:01 +08:00
builtin-agents ♻️ refactor(web-onboarding): rename doc tools and drive incremental persona writes (#13933) 2026-04-18 20:02:39 +08:00
builtin-skills 🐛 fix: should inject current agnets information when actived the lobehub_skill (#13661) 2026-04-09 16:11:18 +08:00
builtin-tool-activator 🐛 fix: add the lost tools into manual agent runtime mode (#13918) 2026-04-17 17:02:53 +08:00
builtin-tool-agent-builder feat(agent-browser): add browser automation skill and tool detection (#12858) 2026-03-10 16:13:33 +08:00
builtin-tool-agent-documents ♻️ refactor(agent-documents): fix title/documentId flow + split Inspector per action (#13940) 2026-04-19 01:06:06 +08:00
builtin-tool-agent-management ♻️ refactor: add more tools in lobe-agent-manangerment(modify、update、delete) (#13842) 2026-04-15 17:57:05 +08:00
builtin-tool-brief feat: support agent tasks system (#13289) 2026-03-26 17:43:51 +08:00
builtin-tool-calculator ⬆️ chore(deps): migrate @lobehub/ui to base-ui exports (#12587) 2026-03-02 22:40:46 +08:00
builtin-tool-claude-code feat(cc): account card, topic filter, and CC integration polish (#13955) 2026-04-18 21:58:50 +08:00
builtin-tool-cloud-sandbox ♻️ refactor: update the codesandbox systemRole(preinstalled_software) (#13799) 2026-04-14 12:11:44 +08:00
builtin-tool-creds 🐛 fix: fixed the when call saveCreds the bad request problem (#13809) 2026-04-14 17:51:00 +08:00
builtin-tool-cron ♻️ refactor: add the cronjob tools executiors (#13536) 2026-04-03 15:21:32 +08:00
builtin-tool-group-agent-builder feat(onboarding): agent web onboarding, feature toggle, and lifecycle sync (#13139) 2026-03-30 20:28:54 +08:00
builtin-tool-group-management 💄 style: batch fix eslint violations across packages (#12601) 2026-03-03 02:19:50 +08:00
builtin-tool-gtd 🐛 fix(builtin-tool-gtd): add server runtime for GTD tool (#13854) 2026-04-16 00:04:48 +08:00
builtin-tool-knowledge-base 🐛 fix: add some lost lobe-kb builtin tools (#13876) 2026-04-16 17:08:22 +08:00
builtin-tool-local-system 🐛 fix(builtin-tool-local-system): honor glob scope in local system tool (#13875) 2026-04-16 22:09:38 +08:00
builtin-tool-memory ♻️ refactor: remove promptfoo configs and dependencies (#13665) 2026-04-08 17:50:55 +08:00
builtin-tool-message 🔨 chore: optimize message tool (#13444) 2026-03-31 21:28:18 +08:00
builtin-tool-notebook feat: support agent tasks system (#13289) 2026-03-26 17:43:51 +08:00
builtin-tool-page-agent ♻️ refactor(chat): remove reject-only button, unify to rejected_continue (#13865) 2026-04-16 10:45:17 +08:00
builtin-tool-remote-device feat: improve agent context injection (skills discovery, device optimization, prompt cleanup) (#13021) 2026-03-17 00:35:18 +08:00
builtin-tool-skill-store ♻️ refactor: add the user creds modules & skill should auto inject the need creds (#13124) 2026-03-24 14:28:23 +08:00
builtin-tool-skills 🐛 fix: add the lost tools into manual agent runtime mode (#13918) 2026-04-17 17:02:53 +08:00
builtin-tool-task feat: support agent tasks system (#13289) 2026-03-26 17:43:51 +08:00
builtin-tool-topic-reference ♻️ refactor(tool): decouple topic-reference executor from app TRPC client (#13451) 2026-03-31 23:27:42 +08:00
builtin-tool-user-interaction 💄 style: Update agent onboarding style (#13678) 2026-04-10 10:44:09 +08:00
builtin-tool-web-browsing feat: associate web crawl documents with agent documents (#13893) 2026-04-16 23:11:21 +08:00
builtin-tool-web-onboarding ♻️ refactor(web-onboarding): rename doc tools and drive incremental persona writes (#13933) 2026-04-18 20:02:39 +08:00
builtin-tools feat: claude code intergration polish (#13942) 2026-04-18 13:42:00 +08:00
business ♻️ refactor: gate agent onboarding with dedicated business flag (#13472) 2026-04-01 19:38:14 +08:00
chat-adapter-feishu feat: support multi media and multiple connection mode (#13624) 2026-04-09 14:16:03 +08:00
chat-adapter-qq feat: support multi media and multiple connection mode (#13624) 2026-04-09 14:16:03 +08:00
chat-adapter-wechat feat: support multi media and multiple connection mode (#13624) 2026-04-09 14:16:03 +08:00
config feat: add notification system (temporarily disabled) (#13301) 2026-03-26 21:16:38 +08:00
const ♻️ refactor(types): break circular dep between types and const packages (#13948) 2026-04-18 22:36:13 +08:00
context-engine ♻️ refactor(web-onboarding): rename doc tools and drive incremental persona writes (#13933) 2026-04-18 20:02:39 +08:00
conversation-flow ♻️ refactor(hetero-agent): persist per-step usage to each step assistant message (#13964) 2026-04-19 16:19:18 +08:00
database ♻️ refactor(agent-documents): fix title/documentId flow + split Inspector per action (#13940) 2026-04-19 01:06:06 +08:00
desktop-bridge feat(trpc): add response metadata and auth header handling (#11816) 2026-01-25 20:39:51 +08:00
device-gateway-client 🐛 fix(device-gateway-client): prevent uncaught WebSocket error on disconnect (#13635) 2026-04-07 23:59:03 +08:00
edge-config feat: billboard in sidebar (#13962) 2026-04-19 00:00:34 +08:00
editor-runtime feat(document): add history management and compare workflow (#13725) 2026-04-16 23:24:28 +08:00
electron-client-ipc feat(desktop): add dedicated topic popup window with cross-window sync (#13957) 2026-04-19 02:15:29 +08:00
electron-server-ipc 📝 docs: Polishing and improving product documentation (#12612) 2026-03-03 16:01:41 +08:00
eval-dataset-parser test: add unit tests for eval-dataset-parser (#13197) 2026-03-25 10:55:58 +08:00
eval-rubric feat(eval): add external scoring mode (#12729) 2026-03-10 09:53:26 +08:00
fetch-sse 🐛 fix(fetch-sse): stop injecting contextBody into structured provider errors (#13477) 2026-04-01 21:24:01 +08:00
file-loaders 📝 docs: Polishing and improving product documentation (#12612) 2026-03-03 16:01:41 +08:00
heterogeneous-agents ♻️ refactor(hetero-agent): persist per-step usage to each step assistant message (#13964) 2026-04-19 16:19:18 +08:00
local-file-shell feat(desktop): embed CLI in app and PATH install (#13669) 2026-04-09 00:53:49 +08:00
markdown-patch feat(onboarding): add feature flags and footer promotion pipeline (#13853) 2026-04-17 21:14:27 +08:00
memory-user-memory ♻️ refactor: remove promptfoo configs and dependencies (#13665) 2026-04-08 17:50:55 +08:00
model-bank 💄 style: add qwen3.6-flash/plus & pixverse-c1 support (#13923) 2026-04-17 19:46:49 +08:00
model-runtime 🐛 fix: strip temperature/top_p for Claude Opus 4.7 (#13909) 2026-04-17 11:47:22 +08:00
observability-otel 🔨 chore: remove dead eslint disable comments for deleted rules (#12597) 2026-03-02 23:18:01 +08:00
openapi 🐛 fix(kb): clean up vector storage when deleting knowledge bases (#13254) 2026-04-10 01:56:05 +08:00
prompts 🔨 chore: return full brief data in task activities (#13914) 2026-04-17 19:10:48 +08:00
python-interpreter feat(desktop): implement subscription pages embedding with webview (#12114) 2026-02-11 13:05:10 +08:00
shared-tool-ui 💄 style(shared-tool-ui): wrap Bash inspector in a rounded chip (#13959) 2026-04-18 22:01:23 +08:00
ssrf-safe-fetch 🐛 fix: distinguish SSRF block errors from network errors (#13103) 2026-03-18 18:16:19 +08:00
tool-runtime ♻️ refactor: unify tool content formatting with ComputerRuntime and shared UI (#13470) 2026-04-02 19:42:45 +08:00
types feat: billboard in sidebar (#13962) 2026-04-19 00:00:34 +08:00
utils feat(cc): account card, topic filter, and CC integration polish (#13955) 2026-04-18 21:58:50 +08:00
web-crawler 🐛 fix(web-crawler): prevent happy-dom CSS parsing crash in htmlToMarkdown (#13652) 2026-04-08 12:59:49 +08:00