Confirm the wire shape of Devin's turn_stats/billingInformation notifications, to price Devin turns
- Dominant language
- TypeScript
- Stars
- 1
- Forks
- 0
- Avg merge
- 1h 12m
- Merged PRs (30d)
- 46
Description
## What is wrong
#115 (Devin per-turn usage) shipped `turnTokens` and a carried `usage` block, but left cost
unset. Devin turns still show no spend at all — not a wrong number, but a real gap: there is
static evidence a cost figure exists somewhere on the wire, and nobody has confirmed its shape.
## The evidence
From #115's implementation comment (static analysis of `/usr/local/bin/devin`, `3000.10.23
(deb81600)`, via `strings` + byte-offset scanning — no live wire capture, this sandbox has no
reliable egress to `api.devin.ai`):
- `cognition.ai/turn_stats` and `cognition.ai/billingInformation` are real extension
**notification method names** in the binary's JSON-RPC method table, alongside
`cognition.ai/compaction`, `cognition.ai/agent_stopped`, etc. The original #115 ticket also
reports a `_cognition.ai/turn_stats` notification observed live, before the `session/prompt`
result.
- `cognition.ai/acuUsed` and `cognition.ai/overageDollars` (a dollar figure) sit together with
session-list metadata keys (`isPinned`, `sessionRepos`, `folder`, `isUnread`) — reads as
**session-level cumulative** fields, plausibly on a `session_info_update`, not obviously
per-turn.
- `committed_acu_cost` / `committed_credit_cost` are real field names, but on a struct the binary
itself labels `ChatMessageMetadata` (16 fields, snake_case, alongside `input_tokens`,
`ttft_ms`, `tokens_per_sec`) — reads as internal message-history bookkeeping. Nothing found
confirms this struct is what's serialized into the `turn_stats`/`billingInformation`
notification actually sent to an ACP host, or in what shape.
`DevinSession.endTurn` (`src/daemon/devin-session.ts`) currently never sets `total_cost_usd`,
so `registry.ts`'s `bill()` sees `costFrom(result) === null` and never charges — correct per
#115's "absent, not a confident zero," but it means Devin turns are permanently unpriced until
this is closed.
## Acceptance criteria
- [ ] Drive a real `devin acp` session (needs actual network egress to `api.devin.ai` and valid
credentials) and capture the raw JSON of a `cognition.ai/turn_stats` notification and/or a
`cognition.ai/billingInformation` notification, verbatim.
- [ ] Say, from that capture, whether a per-turn dollar or ACU figure is actually present, and
its exact field name(s).
- [ ] If present: wire it into `DevinSession.endTurn`, in the same spirit as #115 — carried onto
the `ResultEvent`, with unknown/absent staying absent rather than a confident zero.
- [ ] If not present after checking: say so here and close as won't-fix, same standard #115 held
itself to.
## Out of scope
- Re-deriving the token-count work #115 already shipped (`turnTokens`, `usage` on
`ResultEvent`) — that part is done and confirmed.
- Any change to how Claude turns are priced.
- Cloud/org-level Devin billing APIs — this is about the per-turn ACP stdio wire only, same as
#115.
## Verification
```
pnpm test
pnpm exec tsc -p tsconfig.json --noEmit
```
Manual check a green build won't catch: run a real Devin turn from the cockpit with the captured
shape wired in, confirm the roster/ledger shows a real, non-invented dollar figure for that turn.
## Related
- #115 — parent ticket, shipped the token side of this; this issue is the cost side that #115
explicitly declined to guess at.
Contributor guide
Research direction
Start in src/daemon/devin-session.ts and inspect registry.ts's bill() and costFrom(result) flow. Run a real devin acp session with valid credentials, capture the raw turn_stats or billingInformation notification, and compare its fields with the ResultEvent path. Done means wiring a confirmed per-turn value through endTurn, or documenting that no such value is sent and closing as won't-fix; verify with pnpm test and pnpm exec tsc -p tsconfig.json --noEmit.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- ai-infra-agents, api, devtools
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100