@zvada/agent-server 0.3.7-attribution.1 → 0.3.7-attribution.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.7-attribution.2
4
+
5
+ - Retain Claude's reported 5-minute and 1-hour cache-creation token counts in the existing token usage contract. Missing durations stay absent and reported zeroes are preserved.
6
+ - Document the shared cache accounting contract for custom harness adapters, including totals versus subsets and reported cost.
7
+
3
8
  ## 0.3.7-attribution.1
4
9
 
5
10
  - Preserve per-turn harness, configured model and thinking level in lifecycle events, run summaries and the canonical conversation fold.
package/docs/harnesses.md CHANGED
@@ -82,6 +82,38 @@ The protocol was checked against Codex CLI 0.153.4 and the
82
82
  harness's unparsed event, for migration/debugging/fixture-recording. `data`
83
83
  has **no stability guarantees** and is off by default.
84
84
 
85
+ ## Token and cache accounting
86
+
87
+ Every adapter uses the same `TokenUsage` on `turn.ended.tokens`. A custom
88
+ adapter maps its provider's counts into this contract; storage and consumers
89
+ do not need a new schema for each harness.
90
+
91
+ | Field | Meaning |
92
+ | --- | --- |
93
+ | `input` | Uncached input tokens |
94
+ | `output` | Output tokens, including any reasoning tokens |
95
+ | `reasoning` | Reported reasoning portion of output, when available |
96
+ | `cache.read` | Input tokens reused from the provider's cache |
97
+ | `cache.write` | Input tokens written to the provider's cache |
98
+ | `cache.writeEphemeral5m` | Reported 5-minute portion of cache writes |
99
+ | `cache.writeEphemeral1h` | Reported 1-hour portion of cache writes |
100
+ | `turn.ended.cost` | Harness-reported USD cost, when available |
101
+
102
+ Input, cache reads and cache writes are disjoint. If the native input total
103
+ already includes cached tokens, subtract them once in the adapter. Reasoning
104
+ is part of output and duration buckets are parts of cache writes; do not add
105
+ those subsets to the totals again. Use the shipped `addTokenUsage` helper.
106
+
107
+ Cache values count tokens, not cache entries. Duration buckets describe creation
108
+ usage reported for that turn, not whether a cache entry is still alive. Leave
109
+ unreported duration buckets and cost absent; a reported zero stays zero. Do not
110
+ infer cache durations, savings or prices from the harness name. Final native
111
+ turn totals take precedence over intermediate message usage.
112
+
113
+ `session.usage` describes context occupancy and is not a source for per-turn
114
+ cache accounting. An ACP/custom agent that exposes only this gauge cannot
115
+ provide the cache breakdown without an additional native usage report.
116
+
85
117
  ## Known limitations (roadmap)
86
118
 
87
119
  - **MCP servers** are wired for Claude only; Codex MCP passthrough is pending
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zvada/agent-server",
3
- "version": "0.3.7-attribution.1",
3
+ "version": "0.3.7-attribution.2",
4
4
  "description": "Harness-agnostic agent execution engine: run Claude Code, Codex (SDK/CLI + app-server), and any ACP agent behind one interface with a normalized event stream, multi-turn sessions, and resume. Root export is the wire contract; /core, /server, /client are the seats.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -55,6 +55,10 @@ interface RawUsage {
55
55
  output_tokens?: number;
56
56
  cache_read_input_tokens?: number;
57
57
  cache_creation_input_tokens?: number;
58
+ cache_creation?: {
59
+ ephemeral_5m_input_tokens?: number;
60
+ ephemeral_1h_input_tokens?: number;
61
+ };
58
62
  }
59
63
  interface ContentBlock {
60
64
  type: string;
@@ -499,12 +503,19 @@ export class ClaudeCodeTransformer implements EventTransformer<unknown> {
499
503
  private captureResult(msg: Extract<ClaudeMessage, { type: "result" }>): AdapterEvent[] {
500
504
  this.sawResult = true;
501
505
  if (msg.usage) {
506
+ const creation = msg.usage.cache_creation;
502
507
  this.usage = {
503
508
  input: msg.usage.input_tokens ?? 0,
504
509
  output: msg.usage.output_tokens ?? this.usage.output,
505
510
  cache: {
506
511
  read: msg.usage.cache_read_input_tokens ?? 0,
507
512
  write: msg.usage.cache_creation_input_tokens ?? 0,
513
+ ...(creation?.ephemeral_5m_input_tokens !== undefined && {
514
+ writeEphemeral5m: creation.ephemeral_5m_input_tokens,
515
+ }),
516
+ ...(creation?.ephemeral_1h_input_tokens !== undefined && {
517
+ writeEphemeral1h: creation.ephemeral_1h_input_tokens,
518
+ }),
508
519
  },
509
520
  };
510
521
  }