Runner should expose `usage` from `result` / `error` events in RunResult
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 2
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
Bug: usage field is dropped by the runner
The AgentProc protocol explicitly allows a usage object on result and error events (spec/protocol.md lines 262-264):
resultanderrorMAY include ausageobject for token/cost stats. Bridges MAY ignore it. Recommended keys (all optional):input_tokens,output_tokens,total_tokens(numbers). Additional keys are forward-compatible and SHOULD be ignored if unrecognised. There is no separateusageevent type.
However, the Node SDK runner currently silently discards the field. Two locations:
1. RunResult shape (sdk/node/src/runner.js lines 469-477)
@typedef {Object} RunResult
@property {string} reply
@property {string} sessionId
@property {string} error
@property {number} exitCode
@property {boolean} timedOut
No usage field. Even if the agent emits it correctly, the runner does not expose it.
2. Shared stream utils (hub/_shared/stream_utils.js)
emitResult(text, sessionId) and emitError(text, sessionId) do not accept a usage parameter. The hub bridges can't easily forward CLI-reported token counts without monkey-patching the shared utility.
Fix
Runner side
In handleLine() (around line 680-732 of runner.js), when processing a result or error event:
- Capture
obj.usageif it's a plain object - Attach it to
RunResultasusage?: object - Document the field as "whatever the agent emitted; opaque pass-through, not validated"
Hub bridge utility side
Extend emitResult(text, sessionId, usage?) and emitError(text, sessionId, usage?) in stream_utils.js so bridges can forward CLI-reported usage without bypassing the helper.
Why this matters
Cost / token accounting for IM-bridged agents is the headline use case of bridge observability. Without this, any host that wants to surface "this turn cost $0.012 / used 1234 input tokens" has to parse the agent's stdout itself, defeating the point of using the SDK.
Suggested labels
bug, sdk/node, good first issue
Related
Companion to #1 (Add in-process executor). Once usage is plumbed through, the in-process executor's RunResult will also expose usage — no extra work needed.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read spec/protocol.md lines 262-264, then inspect handleLine() in sdk/node/src/runner.js and emitResult()/emitError() in hub/_shared/stream_utils.js. Trace how result and error events become RunResult values and how bridges emit them. Done means plain-object usage is passed through on both paths, documented as opaque, and the shared helpers accept and forward optional usage.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, node.js
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100