context-mode 1.0.166 → 1.0.167

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.
Files changed (52) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +1 -1
  4. package/.openclaw-plugin/openclaw.plugin.json +1 -1
  5. package/.openclaw-plugin/package.json +1 -1
  6. package/README.md +6 -4
  7. package/build/adapters/codex/usage.d.ts +107 -0
  8. package/build/adapters/codex/usage.js +227 -0
  9. package/build/adapters/gemini-cli/hooks.d.ts +7 -1
  10. package/build/adapters/gemini-cli/hooks.js +9 -1
  11. package/build/adapters/gemini-cli/index.js +11 -0
  12. package/build/adapters/kimi/paths.d.ts +20 -0
  13. package/build/adapters/kimi/paths.js +41 -1
  14. package/build/adapters/kimi/usage.d.ts +82 -0
  15. package/build/adapters/kimi/usage.js +217 -0
  16. package/build/adapters/omp/plugin.d.ts +6 -0
  17. package/build/adapters/omp/plugin.js +87 -2
  18. package/build/adapters/omp/usage.d.ts +49 -0
  19. package/build/adapters/omp/usage.js +110 -0
  20. package/build/adapters/openclaw/plugin.d.ts +10 -0
  21. package/build/adapters/openclaw/plugin.js +57 -0
  22. package/build/adapters/openclaw/usage.d.ts +34 -0
  23. package/build/adapters/openclaw/usage.js +52 -0
  24. package/build/adapters/opencode/plugin.d.ts +17 -0
  25. package/build/adapters/opencode/plugin.js +40 -1
  26. package/build/adapters/pi/extension.js +34 -1
  27. package/build/adapters/qwen-code/index.js +23 -1
  28. package/build/adapters/qwen-code/usage.d.ts +90 -0
  29. package/build/adapters/qwen-code/usage.js +222 -0
  30. package/build/session/db.d.ts +11 -0
  31. package/build/session/db.js +33 -0
  32. package/build/session/extract.d.ts +208 -0
  33. package/build/session/extract.js +670 -43
  34. package/build/session/model-prices.json +429 -0
  35. package/build/session/pricing.d.ts +64 -0
  36. package/build/session/pricing.js +151 -0
  37. package/cli.bundle.mjs +62 -62
  38. package/configs/antigravity-cli/plugin.json +1 -1
  39. package/configs/copilot-cli/.github/plugin/plugin.json +1 -1
  40. package/configs/gemini-cli/settings.json +11 -0
  41. package/hooks/codex/stop.mjs +91 -4
  42. package/hooks/gemini-cli/aftermodel.mjs +70 -0
  43. package/hooks/kimi/stop.mjs +74 -3
  44. package/hooks/qwen-code/platform.mjs +1 -0
  45. package/hooks/qwen-code/stop.mjs +168 -0
  46. package/hooks/session-db.bundle.mjs +7 -7
  47. package/hooks/session-extract.bundle.mjs +3 -2
  48. package/hooks/session-loaders.mjs +9 -1
  49. package/hooks/stop.mjs +35 -2
  50. package/openclaw.plugin.json +1 -1
  51. package/package.json +1 -1
  52. package/server.bundle.mjs +90 -90
@@ -22,6 +22,19 @@ export interface SessionEvent {
22
22
  * `Fetched and indexed N sections (XKB)` preamble.
23
23
  */
24
24
  bytes_avoided?: number;
25
+ /**
26
+ * Optional structured cost/usage fields (Wave 2b). Emitted by
27
+ * extractAgentUsage alongside the colon-string `data` so the forward
28
+ * envelope can spread them to the platform as typed columns instead of an
29
+ * opaque blob. Present only when the source signal is present; cost_usd is
30
+ * omitted on a price miss or a zero-token turn.
31
+ */
32
+ model_id?: string;
33
+ input_tokens?: number;
34
+ output_tokens?: number;
35
+ cache_read_tokens?: number;
36
+ cache_creation_tokens?: number;
37
+ cost_usd?: number;
25
38
  }
26
39
  export interface ToolCall {
27
40
  toolName: string;
@@ -43,6 +56,201 @@ export interface HookInput {
43
56
  is_error?: boolean;
44
57
  };
45
58
  }
59
+ /** Input shape `buildAgentUsageEvent` consumes — re-exported for parser typing. */
60
+ export interface AgentUsageCounts {
61
+ model_id: string;
62
+ input_tokens: number;
63
+ output_tokens: number;
64
+ cache_creation_tokens: number;
65
+ cache_read_tokens: number;
66
+ native_cost_usd?: number | null;
67
+ }
68
+ export { parseKimiUsage, extractKimiUsageSince } from "../adapters/kimi/usage.js";
69
+ export { parseQwenUsage, extractQwenUsageSince } from "../adapters/qwen-code/usage.js";
70
+ /**
71
+ * Pi (oh-my-pi) per-turn usage parser.
72
+ *
73
+ * Maps a Pi `turn_end` payload (`{ message: AssistantMessage }`) to the
74
+ * `buildAgentUsageEvent` input shape, or null when there is nothing to record.
75
+ *
76
+ * Field provenance (adapter-matrix/pi.md @320261f + cited refs):
77
+ * - usage: AssistantMessage.usage (ai/src/types.ts:521 -> catalog/src/types.ts:100-145)
78
+ * - model_id: AssistantMessage.model (ai/src/types.ts:510; kept "provider/model" — builder normalizes)
79
+ * - input: Usage.input -> input_tokens
80
+ * - output: Usage.output -> output_tokens
81
+ * - cacheWrite: Usage.cacheWrite -> cache_creation_tokens
82
+ * - cacheRead: Usage.cacheRead -> cache_read_tokens
83
+ * - native USD: Usage.cost.total -> native_cost_usd (HIGH confidence; no price-table needed)
84
+ *
85
+ * The event is per-turn incremental (per-response usage; anthropic.ts:1893-1901;
86
+ * "for the turn" catalog/types.ts:103), so each turn_end maps to exactly one
87
+ * agent_usage event with no cross-turn accumulation.
88
+ *
89
+ * Algorithmic + null-safe, NO regex. Accepts either the full TurnEndEvent
90
+ * (`{ message }`) or a bare AssistantMessage (`{ usage, model }`) so callers
91
+ * can pass `event` or `event.message` interchangeably. Returns null when the
92
+ * payload is not an assistant message, carries no usage object, or every token
93
+ * bucket is zero/absent (an all-zero turn emits no event — matches
94
+ * buildAgentUsageEvent's own zero->null contract).
95
+ */
96
+ export declare function parsePiUsage(payload: unknown): AgentUsageCounts | null;
97
+ /**
98
+ * openclaw `model.usage` diagnostic-event capture — parseOpenclawUsage.
99
+ *
100
+ * openclaw exposes a first-class `model.usage` diagnostic event
101
+ * (`DiagnosticUsageEvent`, refs/platforms/openclaw/src/infra/diagnostic-events.ts:18-47),
102
+ * emitted once per turn and consumed via `onDiagnosticEvent(listener)`
103
+ * (diagnostic-events.ts:1156) — the same bus the first-party diagnostics-otel /
104
+ * diagnostics-prometheus extensions read.
105
+ *
106
+ * Field mapping (openclaw → AgentUsageCounts):
107
+ * evt.usage.input → input_tokens
108
+ * evt.usage.output → output_tokens
109
+ * evt.usage.cacheWrite→ cache_creation_tokens (cache-creation)
110
+ * evt.usage.cacheRead → cache_read_tokens (cache-read)
111
+ * evt.costUsd → native_cost_usd (pre-computed via estimateUsageCost,
112
+ * agent-runner.ts:1995 — preferred over catalog)
113
+ * evt.model → model_id
114
+ *
115
+ * CRITICAL: read `evt.usage` (the PER-TURN TOTAL — "Last Turn Total"
116
+ * agent-runner.ts:943), NEVER `evt.lastCallUsage` (the last-model-call DELTA,
117
+ * diagnostic-events.ts:34-40). Summing both would double-count.
118
+ *
119
+ * Returns AgentUsageCounts (the buildAgentUsageEvent input shape) or null when
120
+ * the event is not a usage event / carries no usage / sums to zero. Pure,
121
+ * null-safe, algorithmic — NO regex.
122
+ */
123
+ export declare function parseOpenclawUsage(payload: unknown): AgentUsageCounts | null;
124
+ /**
125
+ * opencode per-turn usage parser.
126
+ *
127
+ * Ground truth: context-mode-platform/docs/prds/2026-06-paid-observability/
128
+ * adapter-matrix/opencode.md. opencode tracks usage per *assistant message*; the
129
+ * usage-bearing payload reaches a plugin via the `message.updated` bus event,
130
+ * whose `event.properties.info` is the full Message. The assistant token shape
131
+ * (refs platforms/opencode .../session/message.ts) is:
132
+ * info.tokens = { input, output, reasoning, cache: { read, write } }
133
+ * info.cost = USD cost for this message
134
+ * info.modelID / info.providerID (older refs may expose a single info.model)
135
+ *
136
+ * Field mapping (refs message.ts):
137
+ * tokens.input -> input_tokens
138
+ * tokens.output -> output_tokens
139
+ * tokens.cache.read -> cache_read_tokens
140
+ * tokens.cache.write -> cache_creation_tokens
141
+ * modelID/providerID -> model_id (`${providerID}/${modelID}` when both present)
142
+ * cost -> native_cost_usd
143
+ *
144
+ * LAST-STEP-SNAPSHOT CAVEAT (refs processor.ts:717-718): message-level
145
+ * `.tokens` is OVERWRITTEN every step-finish, so it holds the LAST step's usage
146
+ * — not the turn total. `.cost`, however, ACCUMULATES (`cost += usage.cost`) and
147
+ * is the correct cumulative turn cost. We therefore pass `info.cost` through as
148
+ * native_cost_usd so the billed $ is exact even though the token snapshot is
149
+ * imprecise; the token columns remain best-effort (last-step) telemetry. A true
150
+ * turn-total token sum would require summing per-step Step.Ended parts, which the
151
+ * `message.updated` payload does not carry — out of scope for this snapshot-based
152
+ * capture.
153
+ *
154
+ * Accepts either the bus event (`{ properties: { info } }`), the wrapped
155
+ * `{ event: { properties: { info } } }`, or the bare Message (`info`) so the
156
+ * caller can hand us whatever the SDK surfaces. NO regex — pure algorithmic,
157
+ * null-safe traversal. Returns null when the payload is not an assistant
158
+ * message, carries no tokens object, or every token bucket is zero/absent
159
+ * (mirrors buildAgentUsageEvent's zero->null contract).
160
+ */
161
+ export declare function parseOpencodeUsage(payload: unknown): AgentUsageCounts | null;
162
+ /**
163
+ * Build a structured `agent_usage` event from summed per-model token counts.
164
+ * Emits the colon-string `data` (human/debug + back-compat) AND the structured
165
+ * top-level fields the forward envelope spreads to the platform. cost_usd via
166
+ * the pricing catalog — omitted on a price miss. Returns null when every token
167
+ * bucket is zero/absent (so an all-zero model emits no event).
168
+ */
169
+ export declare function buildAgentUsageEvent(counts: {
170
+ model_id: string;
171
+ input_tokens: number;
172
+ output_tokens: number;
173
+ cache_creation_tokens: number;
174
+ cache_read_tokens: number;
175
+ /**
176
+ * Provider-supplied USD cost for this turn. When a finite number, it is
177
+ * preferred over the catalog computation (openclaw / pi / omp / opencode
178
+ * ship a native cost — trust the source over our price table). Omit/null to
179
+ * derive cost_usd from the pricing catalog.
180
+ */
181
+ native_cost_usd?: number | null;
182
+ }): SessionEvent | null;
183
+ /**
184
+ * gemini-cli AfterModel usage capture — parse ONE AfterModel hook payload into
185
+ * a builder `agent_usage` event (or null). Pure, null-safe, struct-only — NO regex.
186
+ *
187
+ * Refs (docs/prds/2026-06-paid-observability/adapter-matrix/gemini-cli.md):
188
+ * - AfterModel fires per model call inside the gemini-cli stream loop
189
+ * (geminiChat.ts:1213); the hook input carries `llm_request` + `llm_response`
190
+ * (hooks/types.ts:692-695).
191
+ * - `llm_response.usageMetadata` exposes promptTokenCount / candidatesTokenCount
192
+ * / totalTokenCount (hookTranslator.ts:60-64).
193
+ * - model_id = `response.modelVersion || req.model` (loggingContentGenerator.ts:405,553).
194
+ *
195
+ * Mapping → builder shape:
196
+ * promptTokenCount → input_tokens
197
+ * candidatesTokenCount → output_tokens
198
+ * thoughtsTokenCount → ADDED into output_tokens (Gemini bills reasoning as output)
199
+ * cachedContentTokenCount → cache_read_tokens (when present)
200
+ * model_id → response.modelVersion || llm_request.model
201
+ *
202
+ * CAVEAT — the DECOUPLED AfterModel payload (hookTranslator.ts:60-64) forwards
203
+ * only prompt/candidates/total and DROPS cachedContentTokenCount +
204
+ * thoughtsTokenCount. We map those two defensively WHEN PRESENT (richer payload
205
+ * variant / future fix / OTel-fed input) but never depend on them — the common
206
+ * case is input+output only. For full cached/thoughts fidelity the OTel
207
+ * `api_response` exporter or the chat-recording JSON is the source of record.
208
+ *
209
+ * MULTI-CALL TURNS — one user turn that triggers tool calls spans MULTIPLE
210
+ * model calls, each AfterModel cumulative within itself. This fn emits ONE
211
+ * priced event PER AfterModel call (each call is one billed round-trip).
212
+ * Per-userPromptId summation into a single per-turn total is DEFERRED — emitting
213
+ * per-call never double-counts, since each call's usageMetadata is the
214
+ * authoritative total for that call.
215
+ */
216
+ export declare function parseGeminiUsage(afterModelPayload: unknown): SessionEvent | null;
217
+ /**
218
+ * claude-code MAIN-turn usage capture — the dominant-spend path the Task
219
+ * subagent capture (extractAgentUsage) misses. Parses the session transcript
220
+ * JSONL char-algorithmically (NO regex): each `type:"assistant"` line carries
221
+ * `message.usage` + `message.model`, and usage is a per-turn DELTA, so summing
222
+ * the assistant turns per model = the exact billed total. `isSidechain:true`
223
+ * lines are Task-subagent sidechains written to a SEPARATE transcript (refs:
224
+ * sessionStorage.ts:1042) — excluding them keeps the main-turn sum from
225
+ * double-counting the separate Task-subagent capture. Emits one structured
226
+ * `agent_usage` event per distinct model.
227
+ */
228
+ export declare function extractTranscriptUsage(transcript: string): SessionEvent[];
229
+ /**
230
+ * Cursor-aware variant of extractTranscriptUsage for the Stop hook.
231
+ *
232
+ * The transcript grows every turn and the forward loop forwards ALL passed
233
+ * events unconditionally, so re-running extractTranscriptUsage on the whole
234
+ * transcript each Stop would double-count every prior turn. This walks only
235
+ * the turns NEW since the last Stop, keyed by a per-session high-water cursor
236
+ * (the `uuid` of the last assistant turn seen).
237
+ *
238
+ * - sinceUuid null/empty → process ALL non-sidechain assistant turns.
239
+ * - sinceUuid found → process only turns AFTER it (exclusive).
240
+ * - sinceUuid set but NOT found (transcript compaction dropped it) → process
241
+ * ONLY THE LAST non-sidechain assistant turn. Bounded by design: we never
242
+ * re-emit the whole history when the cursor falls off the front.
243
+ *
244
+ * `cursor` returns the uuid of the LAST non-sidechain assistant turn in the
245
+ * transcript (whether or not it carried usage), so the next Stop resumes
246
+ * exactly past it. When the transcript has no such turn, the input cursor is
247
+ * returned unchanged. Same char-algorithmic JSONL parse (NO regex), same
248
+ * sidechain exclusion, same buildAgentUsageEvent emission path.
249
+ */
250
+ export declare function extractTranscriptUsageSince(transcript: string, sinceUuid: string | null): {
251
+ events: SessionEvent[];
252
+ cursor: string | null;
253
+ };
46
254
  /** Reset error-resolution state (for testing). */
47
255
  export declare function resetErrorResolutionState(): void;
48
256
  /** Reset iteration-loop state (for testing). */