Skip to content

fix(acp): report token usage on PromptResponse#1858

Open
Jetiaime wants to merge 2 commits into
MoonshotAI:mainfrom
Jetiaime:feat/acp-report-turn-usage
Open

fix(acp): report token usage on PromptResponse#1858
Jetiaime wants to merge 2 commits into
MoonshotAI:mainfrom
Jetiaime:feat/acp-report-turn-usage

Conversation

@Jetiaime

Copy link
Copy Markdown

Related Issue

Resolve #1855

Problem

The ACP adapter leaves PromptResponse.usage unset and never emits usage, so ACP clients driving kimi over ACP (Multica, OpenCode, Claude Code using kimi as a backend) have zero visibility into token consumption and cost — even though the SDK already tracks usage internally (session.getUsage(), serialized to wire.jsonl). On Multica specifically, runtime usage returns zero rows for the kimi runtime while other providers on the same daemon return full per-model breakdowns.

What changed

  • PromptResponse.usage is now populated on turn end from session.getUsage(), mapping the SDK's cumulative total (TokenUsage) to the ACP Usage shape:
    • inputOtherinputTokens
    • outputoutputTokens
    • inputCacheReadcachedReadTokens
    • inputCacheCreationcachedWriteTokens
    • sum → totalTokens
  • Reuses the same getUsage() the adapter already calls for the /usage built-in, so no new RPC or event accumulation is introduced.
  • Reading usage is best-effort: any failure (or an unset total, or a session stub without getUsage) resolves the prompt with stopReason alone rather than hanging or rejecting. The Promise.resolve().then(() => this.session.getUsage()) wrapper also converts a synchronous throw into a caught rejection so a completed turn can never be left pending.
  • Added a pure mapper sessionUsageToAcpUsage in events-map.ts and two tests in session-prompt.test.ts (usage reported; usage-read failure degrades gracefully).

Verification: pnpm --filter @moonshot-ai/acp-adapter test (308 passed), typecheck clean, oxlint --type-aware 0 errors on changed files.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

The ACP adapter left PromptResponse.usage unset, so ACP clients driving kimi (Multica, OpenCode, Claude Code) had zero token/cost visibility even though the SDK tracks usage internally.

Populate PromptResponse.usage from session.getUsage() on turn end, mapping the SDK's cumulative total to the ACP Usage shape. Reading usage is best-effort: any failure resolves the prompt with stopReason alone rather than hanging or rejecting.
@changeset-bot

changeset-bot Bot commented Jul 17, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 6f621b9

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d8a973ef3e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/acp-adapter/src/session.ts Outdated
Comment on lines +1216 to +1219
Promise.resolve()
.then(() => this.session.getUsage())
.then((usage) => {
resolve({ stopReason, usage: sessionUsageToAcpUsage(usage) });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Report usage for compact slash prompts

Because the usage read is only added in runTurnBody, ACP prompts intercepted by runBuiltInCommand still return the old { stopReason: 'end_turn' } path without usage. In particular, /compact calls runCompactCommand/session.compact, and compaction records model token usage, so ACP clients still see no PromptResponse.usage for a token-consuming compaction prompt; apply the same best-effort usage wrapping to that built-in return path as well.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 6f621b9. Extracted a shared promptResponseWithUsage helper and wired it into both runTurnBody and the runBuiltInCommand return path, so /compact (and every other built-in) now reports PromptResponse.usage. Added a test in session-slash.test.ts covering the built-in return path. acp-adapter: 309 tests passed, typecheck clean, oxlint 0 errors.

Codex review (P2): the usage read was only wired into runTurnBody, so ACP prompts handled by runBuiltInCommand (notably /compact, which runs a token-consuming compaction) still returned end_turn with no usage.

Extract a shared promptResponseWithUsage helper and use it from both the model-turn path and the built-in return path so every terminal prompt reports usage.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ACP adapter does not report token usage (PromptResponse.usage empty, no usage_update emitted)

1 participant