@ckanner/flywheel 0.32.1 → 0.33.1

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 (134) hide show
  1. package/CHANGELOG.md +20 -1
  2. package/README.md +7 -0
  3. package/README.zh-CN.md +5 -0
  4. package/THIRD_PARTY_NOTICES.md +42 -0
  5. package/bin/runtime.js +25 -31
  6. package/cordis.patch.yml +5 -0
  7. package/dist/bridge.mjs +421 -0
  8. package/dist/claude-code-pro-bridge.mjs +82 -0
  9. package/dist/claude-code-pro-worker.mjs +5 -0
  10. package/dist/client.js +4140 -0
  11. package/dist/codex-pro-bridge.mjs +75 -0
  12. package/dist/codex-pro-worker.mjs +5 -0
  13. package/dist/console-read.mjs +51 -0
  14. package/dist/control.mjs +218 -0
  15. package/dist/index.mjs +185 -0
  16. package/dist/installation.mjs +56 -0
  17. package/dist/machine-worker.mjs +241 -0
  18. package/dist/policy.mjs +91 -0
  19. package/dist/prewarm.mjs +136 -0
  20. package/dist/protocol.mjs +260 -0
  21. package/dist/task-association.mjs +127 -0
  22. package/dist/worker.mjs +52 -0
  23. package/dist/workspaces.mjs +42 -0
  24. package/docs/README.md +1 -1
  25. package/docs/README.zh-CN.md +1 -1
  26. package/docs/design.md +8 -5
  27. package/docs/en/configuration.md +1 -1
  28. package/docs/en/contributing.md +5 -6
  29. package/docs/en/flow-console.md +2 -2
  30. package/docs/en/getting-started.md +9 -2
  31. package/docs/en/releasing.md +132 -174
  32. package/docs/validation/2026-11-13-release-0.32.1.md +83 -0
  33. package/docs/validation/2026-11-14-release-0.33.0.md +49 -0
  34. package/docs/validation/2026-11-14-single-package.md +60 -0
  35. package/docs/validation/README.md +3 -0
  36. package/docs/zh-CN/configuration.md +1 -1
  37. package/docs/zh-CN/contributing.md +4 -5
  38. package/docs/zh-CN/flow-console.md +2 -2
  39. package/docs/zh-CN/getting-started.md +7 -3
  40. package/docs/zh-CN/releasing.md +97 -81
  41. package/native/darwin-amd64/flywheel +0 -0
  42. package/native/darwin-arm64/flywheel +0 -0
  43. package/native/linux-amd64/flywheel +0 -0
  44. package/native/linux-arm64/flywheel +0 -0
  45. package/native/manifest.json +22 -0
  46. package/node_modules/dsh-subagent-codex-pro/CHANGELOG.md +403 -0
  47. package/node_modules/dsh-subagent-codex-pro/LICENSE +21 -0
  48. package/node_modules/dsh-subagent-codex-pro/README.md +557 -0
  49. package/node_modules/dsh-subagent-codex-pro/cordis.patch.yml +30 -0
  50. package/node_modules/dsh-subagent-codex-pro/docs/README.zh.md +355 -0
  51. package/node_modules/dsh-subagent-codex-pro/docs/machine-lifecycle-validation.md +65 -0
  52. package/node_modules/dsh-subagent-codex-pro/docs/machine-lifecycle.md +144 -0
  53. package/node_modules/dsh-subagent-codex-pro/docs/machine-lifecycle.zh.md +98 -0
  54. package/node_modules/dsh-subagent-codex-pro/docs/machine.md +194 -0
  55. package/node_modules/dsh-subagent-codex-pro/docs/orchestration.zh.md +86 -0
  56. package/node_modules/dsh-subagent-codex-pro/lib/codex-exec.js +68 -0
  57. package/node_modules/dsh-subagent-codex-pro/lib/codex-exec.js.map +1 -0
  58. package/node_modules/dsh-subagent-codex-pro/lib/dsh-types.js +15 -0
  59. package/node_modules/dsh-subagent-codex-pro/lib/dsh-types.js.map +1 -0
  60. package/node_modules/dsh-subagent-codex-pro/lib/index.js +830 -0
  61. package/node_modules/dsh-subagent-codex-pro/lib/index.js.map +1 -0
  62. package/node_modules/dsh-subagent-codex-pro/lib/jobs.js +35 -0
  63. package/node_modules/dsh-subagent-codex-pro/lib/jobs.js.map +1 -0
  64. package/node_modules/dsh-subagent-codex-pro/lib/jsonrpc.js +229 -0
  65. package/node_modules/dsh-subagent-codex-pro/lib/jsonrpc.js.map +1 -0
  66. package/node_modules/dsh-subagent-codex-pro/lib/machine-cli.js +101 -0
  67. package/node_modules/dsh-subagent-codex-pro/lib/machine-cli.js.map +1 -0
  68. package/node_modules/dsh-subagent-codex-pro/lib/machine-local.js +122 -0
  69. package/node_modules/dsh-subagent-codex-pro/lib/machine-local.js.map +1 -0
  70. package/node_modules/dsh-subagent-codex-pro/lib/machine-recovery.js +167 -0
  71. package/node_modules/dsh-subagent-codex-pro/lib/machine-recovery.js.map +1 -0
  72. package/node_modules/dsh-subagent-codex-pro/lib/machine-supervision.js +141 -0
  73. package/node_modules/dsh-subagent-codex-pro/lib/machine-supervision.js.map +1 -0
  74. package/node_modules/dsh-subagent-codex-pro/lib/machine-supervisor.js +128 -0
  75. package/node_modules/dsh-subagent-codex-pro/lib/machine-supervisor.js.map +1 -0
  76. package/node_modules/dsh-subagent-codex-pro/lib/machine.js +104 -0
  77. package/node_modules/dsh-subagent-codex-pro/lib/machine.js.map +1 -0
  78. package/node_modules/dsh-subagent-codex-pro/lib/process-guardian.js +156 -0
  79. package/node_modules/dsh-subagent-codex-pro/lib/process-guardian.js.map +1 -0
  80. package/node_modules/dsh-subagent-codex-pro/lib/run.js +842 -0
  81. package/node_modules/dsh-subagent-codex-pro/lib/run.js.map +1 -0
  82. package/node_modules/dsh-subagent-codex-pro/lib/structured.js +329 -0
  83. package/node_modules/dsh-subagent-codex-pro/lib/structured.js.map +1 -0
  84. package/node_modules/dsh-subagent-codex-pro/lib/tool.js +295 -0
  85. package/node_modules/dsh-subagent-codex-pro/lib/tool.js.map +1 -0
  86. package/node_modules/dsh-subagent-codex-pro/lib/types/codex-exec.d.ts +88 -0
  87. package/node_modules/dsh-subagent-codex-pro/lib/types/codex-exec.d.ts.map +1 -0
  88. package/node_modules/dsh-subagent-codex-pro/lib/types/dsh-types.d.ts +179 -0
  89. package/node_modules/dsh-subagent-codex-pro/lib/types/dsh-types.d.ts.map +1 -0
  90. package/node_modules/dsh-subagent-codex-pro/lib/types/index.d.ts +266 -0
  91. package/node_modules/dsh-subagent-codex-pro/lib/types/index.d.ts.map +1 -0
  92. package/node_modules/dsh-subagent-codex-pro/lib/types/jobs.d.ts +34 -0
  93. package/node_modules/dsh-subagent-codex-pro/lib/types/jobs.d.ts.map +1 -0
  94. package/node_modules/dsh-subagent-codex-pro/lib/types/jsonrpc.d.ts +113 -0
  95. package/node_modules/dsh-subagent-codex-pro/lib/types/jsonrpc.d.ts.map +1 -0
  96. package/node_modules/dsh-subagent-codex-pro/lib/types/machine-cli.d.ts +3 -0
  97. package/node_modules/dsh-subagent-codex-pro/lib/types/machine-cli.d.ts.map +1 -0
  98. package/node_modules/dsh-subagent-codex-pro/lib/types/machine-local.d.ts +4 -0
  99. package/node_modules/dsh-subagent-codex-pro/lib/types/machine-local.d.ts.map +1 -0
  100. package/node_modules/dsh-subagent-codex-pro/lib/types/machine-recovery.d.ts +53 -0
  101. package/node_modules/dsh-subagent-codex-pro/lib/types/machine-recovery.d.ts.map +1 -0
  102. package/node_modules/dsh-subagent-codex-pro/lib/types/machine-supervision.d.ts +8 -0
  103. package/node_modules/dsh-subagent-codex-pro/lib/types/machine-supervision.d.ts.map +1 -0
  104. package/node_modules/dsh-subagent-codex-pro/lib/types/machine-supervisor.d.ts +2 -0
  105. package/node_modules/dsh-subagent-codex-pro/lib/types/machine-supervisor.d.ts.map +1 -0
  106. package/node_modules/dsh-subagent-codex-pro/lib/types/machine.d.ts +70 -0
  107. package/node_modules/dsh-subagent-codex-pro/lib/types/machine.d.ts.map +1 -0
  108. package/node_modules/dsh-subagent-codex-pro/lib/types/process-guardian.d.ts +22 -0
  109. package/node_modules/dsh-subagent-codex-pro/lib/types/process-guardian.d.ts.map +1 -0
  110. package/node_modules/dsh-subagent-codex-pro/lib/types/run.d.ts +386 -0
  111. package/node_modules/dsh-subagent-codex-pro/lib/types/run.d.ts.map +1 -0
  112. package/node_modules/dsh-subagent-codex-pro/lib/types/structured.d.ts +35 -0
  113. package/node_modules/dsh-subagent-codex-pro/lib/types/structured.d.ts.map +1 -0
  114. package/node_modules/dsh-subagent-codex-pro/lib/types/tool.d.ts +107 -0
  115. package/node_modules/dsh-subagent-codex-pro/lib/types/tool.d.ts.map +1 -0
  116. package/node_modules/dsh-subagent-codex-pro/lib/types/usage.d.ts +131 -0
  117. package/node_modules/dsh-subagent-codex-pro/lib/types/usage.d.ts.map +1 -0
  118. package/node_modules/dsh-subagent-codex-pro/lib/types/wire.d.ts +321 -0
  119. package/node_modules/dsh-subagent-codex-pro/lib/types/wire.d.ts.map +1 -0
  120. package/node_modules/dsh-subagent-codex-pro/lib/usage.js +356 -0
  121. package/node_modules/dsh-subagent-codex-pro/lib/usage.js.map +1 -0
  122. package/node_modules/dsh-subagent-codex-pro/lib/wire.js +986 -0
  123. package/node_modules/dsh-subagent-codex-pro/lib/wire.js.map +1 -0
  124. package/node_modules/dsh-subagent-codex-pro/package.json +76 -0
  125. package/npm/install.js +59 -6
  126. package/package.json +74 -12
  127. package/plugins/dsh/LICENSE +21 -0
  128. package/plugins/dsh/PROTOCOL.md +609 -0
  129. package/plugins/dsh/README.en.md +4 -0
  130. package/plugins/dsh/README.md +342 -0
  131. package/plugins/dsh/README.zh-CN.md +279 -0
  132. package/plugins/dsh/THIRD_PARTY_NOTICES.md +42 -0
  133. package/plugins/dsh/vendor/README.md +17 -0
  134. package/plugins/dsh/vendor/codex-pro.json +16 -0
@@ -0,0 +1,356 @@
1
+ /**
2
+ * Token usage observed over one delegation.
3
+ *
4
+ * Codex reports a thread-cumulative snapshot (`total`) and a last-model-call
5
+ * snapshot (`last`) through `thread/tokenUsage/updated`. A delegation can make
6
+ * several model calls, so `last` is never a delegation total, and `total` is an
7
+ * absolute high-water mark rather than an increment. Resume/attach replays the
8
+ * latest persisted snapshot for the new connection, so the first observation
9
+ * after a resume is history, not this run.
10
+ *
11
+ * The tracker therefore:
12
+ * - uses a baseline and computes a delta from later cumulative snapshots;
13
+ * - treats a replay after resume as the baseline;
14
+ * - ignores duplicate and out-of-order snapshots;
15
+ * - never derives a value by adding snapshots;
16
+ * - reports `unknown` rather than zero when no usable observation exists;
17
+ * - retains the last observed totals even when the run failed or was cancelled.
18
+ *
19
+ * `cachedInputTokens` is a subset of `inputTokens`, and
20
+ * `reasoningOutputTokens` is a subset of `outputTokens`. The fields are reported
21
+ * as Codex states them; they are never summed into a larger total.
22
+ *
23
+ * @module dsh-subagent-codex-pro/usage
24
+ */
25
+ const BREAKDOWN_FIELDS = [
26
+ 'totalTokens',
27
+ 'inputTokens',
28
+ 'cachedInputTokens',
29
+ 'cacheWriteInputTokens',
30
+ 'outputTokens',
31
+ 'reasoningOutputTokens',
32
+ ];
33
+ /** A zero breakdown, used as the known baseline of a brand-new thread. */
34
+ const ZERO = {
35
+ totalTokens: 0,
36
+ inputTokens: 0,
37
+ cachedInputTokens: 0,
38
+ cacheWriteInputTokens: 0,
39
+ outputTokens: 0,
40
+ reasoningOutputTokens: 0,
41
+ };
42
+ /** Whether a value is a non-negative safe integer. */
43
+ function count(value) {
44
+ return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0;
45
+ }
46
+ /**
47
+ * Validate a reported breakdown. The five primary counters must be present and
48
+ * valid. `cacheWriteInputTokens` is optional in the protocol schema with a
49
+ * default of zero, so an omitted value is normalized to zero rather than
50
+ * turning an otherwise valid observation into unknown usage.
51
+ */
52
+ function normalizeBreakdown(value) {
53
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
54
+ return undefined;
55
+ const record = value;
56
+ const cacheWrite = record.cacheWriteInputTokens === undefined ? 0 : record.cacheWriteInputTokens;
57
+ if (!count(record.totalTokens) || !count(record.inputTokens) || !count(record.cachedInputTokens)
58
+ || !count(record.outputTokens) || !count(record.reasoningOutputTokens) || !count(cacheWrite)) {
59
+ return undefined;
60
+ }
61
+ return {
62
+ totalTokens: record.totalTokens,
63
+ inputTokens: record.inputTokens,
64
+ cachedInputTokens: record.cachedInputTokens,
65
+ cacheWriteInputTokens: cacheWrite,
66
+ outputTokens: record.outputTokens,
67
+ reasoningOutputTokens: record.reasoningOutputTokens,
68
+ };
69
+ }
70
+ /** Subtract one breakdown from another; returns undefined when any field goes backwards. */
71
+ function subtract(later, earlier) {
72
+ const result = {
73
+ totalTokens: later.totalTokens - earlier.totalTokens,
74
+ inputTokens: later.inputTokens - earlier.inputTokens,
75
+ cachedInputTokens: later.cachedInputTokens - earlier.cachedInputTokens,
76
+ cacheWriteInputTokens: later.cacheWriteInputTokens - earlier.cacheWriteInputTokens,
77
+ outputTokens: later.outputTokens - earlier.outputTokens,
78
+ reasoningOutputTokens: later.reasoningOutputTokens - earlier.reasoningOutputTokens,
79
+ };
80
+ return BREAKDOWN_FIELDS.every((field) => result[field] >= 0) ? result : undefined;
81
+ }
82
+ /** Whether every counter in `later` is at least its counterpart in `earlier`. */
83
+ function notOlder(later, earlier) {
84
+ return BREAKDOWN_FIELDS.every((field) => later[field] >= earlier[field]);
85
+ }
86
+ /**
87
+ * Fold the usage notifications of one thread into one delegation report.
88
+ *
89
+ * One tracker belongs to one wire/thread. `resetForNewThread` is called after a
90
+ * successful `thread/start`; `resetForResume` after a successful
91
+ * `thread/resume`; `beginTurn` when the turn id becomes authoritative. The
92
+ * tracker is deliberately not a Codex client: it only accounts for snapshots,
93
+ * never issues requests.
94
+ */
95
+ export class TokenUsageTracker {
96
+ #mode = 'new';
97
+ #state = 'collecting';
98
+ #baselineKnown = true;
99
+ #baseline = ZERO;
100
+ #latest;
101
+ #highWater = ZERO;
102
+ #modelContextWindow;
103
+ #observations = 0;
104
+ #replaySeen = false;
105
+ #baselineFromLive = false;
106
+ #liveSeen = false;
107
+ #advanced = false;
108
+ #anomaly = false;
109
+ #invalid = false;
110
+ #associationLost = false;
111
+ #reason;
112
+ #threadId;
113
+ #turnId;
114
+ #awaitingTurnId = false;
115
+ #pending = [];
116
+ /** Start accounting for a thread that has no history. */
117
+ resetForNewThread(threadId) {
118
+ this.#mode = 'new';
119
+ this.#state = 'collecting';
120
+ this.#baselineKnown = true;
121
+ this.#baseline = ZERO;
122
+ this.#latest = undefined;
123
+ this.#highWater = ZERO;
124
+ this.#modelContextWindow = undefined;
125
+ this.#observations = 0;
126
+ this.#replaySeen = false;
127
+ this.#baselineFromLive = false;
128
+ this.#liveSeen = false;
129
+ this.#advanced = false;
130
+ this.#anomaly = false;
131
+ this.#invalid = false;
132
+ this.#associationLost = false;
133
+ this.#reason = undefined;
134
+ this.#threadId = threadId;
135
+ this.#turnId = undefined;
136
+ this.#awaitingTurnId = false;
137
+ this.#pending = [];
138
+ }
139
+ /**
140
+ * Start accounting for a resumed thread.
141
+ *
142
+ * Its first usage notification is normally the connection-scoped replay of
143
+ * the last persisted snapshot, so it becomes the baseline and contributes no
144
+ * run usage. If no replay arrives before the turn starts, the first live
145
+ * snapshot is still used as a baseline but the report is `partial`, because
146
+ * usage before that snapshot is unknowable from the protocol.
147
+ */
148
+ resetForResume(threadId) {
149
+ this.resetForNewThread(threadId);
150
+ this.#mode = 'resumed';
151
+ this.#baselineKnown = false;
152
+ this.#baseline = ZERO;
153
+ }
154
+ /**
155
+ * Mark the turn/start request boundary.
156
+ *
157
+ * Notifications are buffered until the response proves the authoritative turn
158
+ * id; that keeps a resumed thread's replay and a current-turn live snapshot
159
+ * distinguishable even when the replay arrives after this request.
160
+ */
161
+ startTurnRequest() {
162
+ this.#awaitingTurnId = true;
163
+ }
164
+ /** Associate early notifications after the response proves the turn id. */
165
+ beginTurn(turnId) {
166
+ this.#turnId = turnId;
167
+ this.#awaitingTurnId = false;
168
+ for (const notification of this.#pending.splice(0))
169
+ this.observe(notification);
170
+ }
171
+ /** The current turn id, when the wire has adopted it. */
172
+ get turnId() {
173
+ return this.#turnId;
174
+ }
175
+ /** The latest absolute thread total, if any observation was accepted. */
176
+ get latest() {
177
+ return this.#latest;
178
+ }
179
+ /** The latest model context window, if Codex reported one. */
180
+ get modelContextWindow() {
181
+ return this.#modelContextWindow;
182
+ }
183
+ /** Begin a report's closing fold; further observations are ignored. */
184
+ close() {
185
+ this.#state = 'closed';
186
+ this.#pending = [];
187
+ }
188
+ /**
189
+ * Fold one `thread/tokenUsage/updated` notification.
190
+ *
191
+ * @param notification - the decoded notification parameters.
192
+ * @returns whether the notification was usable for accounting.
193
+ */
194
+ observe(notification) {
195
+ if (this.#state === 'closed')
196
+ return false;
197
+ if (typeof notification.threadId !== 'string' || notification.threadId === '') {
198
+ this.observeInvalid();
199
+ return false;
200
+ }
201
+ if (notification.threadId !== this.#threadId)
202
+ return false;
203
+ // A server may emit turn/started, usage, and completion before answering
204
+ // turn/start. Buffer this bounded window rather than mistaking live usage
205
+ // for a resumed thread's history or attributing an unrelated turn to ours.
206
+ if (this.#awaitingTurnId) {
207
+ if (this.#pending.length < 128)
208
+ this.#pending.push(notification);
209
+ else {
210
+ this.#invalid = true;
211
+ this.#reason = 'too many usage notifications arrived before the turn id was confirmed';
212
+ }
213
+ return false;
214
+ }
215
+ const turnId = typeof notification.turnId === 'string' && notification.turnId !== ''
216
+ ? notification.turnId
217
+ : undefined;
218
+ const total = this.#totalOf(notification.tokenUsage);
219
+ if (turnId === undefined || total === undefined) {
220
+ this.#invalid = true;
221
+ this.#reason = 'Codex reported a malformed token-usage notification';
222
+ return false;
223
+ }
224
+ this.#observations += 1;
225
+ const modelContextWindow = this.#contextWindowOf(notification.tokenUsage);
226
+ if (modelContextWindow !== undefined)
227
+ this.#modelContextWindow = modelContextWindow;
228
+ // A resumed thread's replay can arrive before or after the turn/start
229
+ // request. Until this turn has produced a live usage snapshot, a snapshot
230
+ // for another turn is the thread's history, not this delegation's
231
+ // consumption; adopt the latest such snapshot as the baseline. A thread
232
+ // has one active writer, so this cannot be concurrent live usage. Once a
233
+ // live snapshot for our turn exists, a later foreign-turn snapshot must
234
+ // remain unattributed and the report partial.
235
+ if (this.#mode === 'resumed' && !this.#liveSeen
236
+ && (this.#turnId === undefined || turnId !== this.#turnId)) {
237
+ if (this.#replaySeen && !notOlder(total, this.#highWater)) {
238
+ this.#anomaly = true;
239
+ this.#reason = 'historical usage moved backwards before the turn started';
240
+ }
241
+ this.#baseline = total;
242
+ this.#baselineKnown = true;
243
+ this.#replaySeen = true;
244
+ this.#highWater = total;
245
+ this.#latest = total;
246
+ return true;
247
+ }
248
+ // Before the request, a new thread cannot have produced this delegation's
249
+ // consumption. Keep the observed baseline, but do not call it our usage.
250
+ if (this.#turnId === undefined) {
251
+ this.#baseline = total;
252
+ this.#highWater = total;
253
+ this.#latest = total;
254
+ this.#invalid = true;
255
+ this.#reason = 'a new thread reported historical usage before this turn was requested';
256
+ return false;
257
+ }
258
+ // Once our request has started, another turn is not a reliable historical
259
+ // baseline. Its consumption can also be included in later thread totals,
260
+ // so ignoring the notification alone would still overcount our next delta.
261
+ if (turnId !== this.#turnId) {
262
+ this.#associationLost = true;
263
+ this.#reason = 'usage for another turn prevents reliable run attribution';
264
+ return false;
265
+ }
266
+ this.#liveSeen = true;
267
+ // No replay arrived before the turn; the first live snapshot is the best
268
+ // baseline available, but usage before it was never observed.
269
+ if (!this.#baselineKnown) {
270
+ this.#baseline = total;
271
+ this.#baselineKnown = true;
272
+ this.#baselineFromLive = true;
273
+ this.#reason = 'the resumed thread did not replay a baseline before its first live usage';
274
+ this.#highWater = total;
275
+ this.#latest = total;
276
+ return false;
277
+ }
278
+ if (!notOlder(total, this.#highWater)) {
279
+ // Counters may reset when a thread is rolled back or rebuilt. Keeping a
280
+ // negative delta would fabricate a negative or inflated result; restart
281
+ // the baseline and report partial rather than a clean number.
282
+ this.#anomaly = true;
283
+ this.#baseline = total;
284
+ this.#highWater = total;
285
+ this.#latest = total;
286
+ this.#reason = 'a usage counter moved backwards; the run total is partial';
287
+ return false;
288
+ }
289
+ if (!BREAKDOWN_FIELDS.some((field) => total[field] > this.#highWater[field])) {
290
+ // Duplicate or older snapshot: same high-water mark, no new information.
291
+ this.#latest = total;
292
+ return true;
293
+ }
294
+ this.#highWater = total;
295
+ this.#latest = total;
296
+ this.#advanced = true;
297
+ return true;
298
+ }
299
+ /** Record a malformed notification so the report can say so. */
300
+ observeInvalid() {
301
+ if (this.#state === 'closed')
302
+ return;
303
+ this.#invalid = true;
304
+ this.#reason = 'Codex reported an invalid token-usage notification';
305
+ }
306
+ /**
307
+ * The report for this run.
308
+ *
309
+ * No observation is `unknown`, never a zero report. A known baseline plus a
310
+ * later snapshot is `complete` unless a reset/partial reason was recorded.
311
+ */
312
+ report() {
313
+ const latest = this.#latest;
314
+ if (latest === undefined || !this.#liveSeen) {
315
+ return {
316
+ status: 'unknown',
317
+ observations: this.#observations,
318
+ replayedBaseline: this.#replaySeen,
319
+ ...(latest === undefined ? {} : { threadTotal: latest }),
320
+ reason: this.#reason ?? (latest === undefined
321
+ ? 'no token-usage notification was observed'
322
+ : 'only replayed historical usage was observed'),
323
+ };
324
+ }
325
+ const delta = this.#baselineKnown && !this.#anomaly && !this.#associationLost && !(this.#baselineFromLive && !this.#advanced)
326
+ ? subtract(latest, this.#baseline)
327
+ : undefined;
328
+ const partial = delta === undefined || this.#invalid || this.#anomaly || this.#associationLost || this.#baselineFromLive || !this.#baselineKnown;
329
+ return {
330
+ status: partial ? 'partial' : 'complete',
331
+ ...(delta === undefined ? {} : { run: delta }),
332
+ threadTotal: latest,
333
+ ...(this.#modelContextWindow === undefined ? {} : { modelContextWindow: this.#modelContextWindow }),
334
+ observations: this.#observations,
335
+ replayedBaseline: this.#replaySeen,
336
+ ...(this.#reason === undefined ? {} : { reason: this.#reason }),
337
+ };
338
+ }
339
+ /** Validate and copy the reported breakdown. */
340
+ #totalOf(tokenUsage) {
341
+ if (typeof tokenUsage !== 'object' || tokenUsage === null || Array.isArray(tokenUsage))
342
+ return undefined;
343
+ const total = tokenUsage.total;
344
+ return normalizeBreakdown(total);
345
+ }
346
+ /** Read `modelContextWindow` from a reported usage object. */
347
+ #contextWindowOf(tokenUsage) {
348
+ if (typeof tokenUsage !== 'object' || tokenUsage === null || Array.isArray(tokenUsage))
349
+ return undefined;
350
+ const value = tokenUsage.modelContextWindow;
351
+ return value === null || (typeof value === 'number' && Number.isSafeInteger(value) && value >= 0)
352
+ ? value
353
+ : undefined;
354
+ }
355
+ }
356
+ //# sourceMappingURL=usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.js","sourceRoot":"","sources":["../src/usage.ts"],"names":[],"mappings":"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"}