oc2token 0.1.0

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 (159) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +399 -0
  3. package/dist/src/accounting/index.d.ts +1 -0
  4. package/dist/src/accounting/index.js +2 -0
  5. package/dist/src/accounting/index.js.map +1 -0
  6. package/dist/src/accounting/reducer.d.ts +21 -0
  7. package/dist/src/accounting/reducer.js +105 -0
  8. package/dist/src/accounting/reducer.js.map +1 -0
  9. package/dist/src/antigravity/discovery.d.ts +18 -0
  10. package/dist/src/antigravity/discovery.js +95 -0
  11. package/dist/src/antigravity/discovery.js.map +1 -0
  12. package/dist/src/antigravity/doctor.d.ts +6 -0
  13. package/dist/src/antigravity/doctor.js +78 -0
  14. package/dist/src/antigravity/doctor.js.map +1 -0
  15. package/dist/src/antigravity/index.d.ts +3 -0
  16. package/dist/src/antigravity/index.js +4 -0
  17. package/dist/src/antigravity/index.js.map +1 -0
  18. package/dist/src/antigravity/proto.d.ts +73 -0
  19. package/dist/src/antigravity/proto.js +259 -0
  20. package/dist/src/antigravity/proto.js.map +1 -0
  21. package/dist/src/antigravity/scanner.d.ts +8 -0
  22. package/dist/src/antigravity/scanner.js +552 -0
  23. package/dist/src/antigravity/scanner.js.map +1 -0
  24. package/dist/src/application.d.ts +73 -0
  25. package/dist/src/application.js +657 -0
  26. package/dist/src/application.js.map +1 -0
  27. package/dist/src/cache/filesystem.d.ts +8 -0
  28. package/dist/src/cache/filesystem.js +70 -0
  29. package/dist/src/cache/filesystem.js.map +1 -0
  30. package/dist/src/cache/index.d.ts +5 -0
  31. package/dist/src/cache/index.js +6 -0
  32. package/dist/src/cache/index.js.map +1 -0
  33. package/dist/src/cache/lock.d.ts +40 -0
  34. package/dist/src/cache/lock.js +227 -0
  35. package/dist/src/cache/lock.js.map +1 -0
  36. package/dist/src/cache/schema.d.ts +45 -0
  37. package/dist/src/cache/schema.js +308 -0
  38. package/dist/src/cache/schema.js.map +1 -0
  39. package/dist/src/cache/store.d.ts +46 -0
  40. package/dist/src/cache/store.js +396 -0
  41. package/dist/src/cache/store.js.map +1 -0
  42. package/dist/src/cache/types.d.ts +130 -0
  43. package/dist/src/cache/types.js +6 -0
  44. package/dist/src/cache/types.js.map +1 -0
  45. package/dist/src/cli.d.ts +8 -0
  46. package/dist/src/cli.js +874 -0
  47. package/dist/src/cli.js.map +1 -0
  48. package/dist/src/codex/discovery.d.ts +6 -0
  49. package/dist/src/codex/discovery.js +88 -0
  50. package/dist/src/codex/discovery.js.map +1 -0
  51. package/dist/src/codex/doctor.d.ts +6 -0
  52. package/dist/src/codex/doctor.js +52 -0
  53. package/dist/src/codex/doctor.js.map +1 -0
  54. package/dist/src/codex/index.d.ts +3 -0
  55. package/dist/src/codex/index.js +3 -0
  56. package/dist/src/codex/index.js.map +1 -0
  57. package/dist/src/codex/scanner.d.ts +6 -0
  58. package/dist/src/codex/scanner.js +487 -0
  59. package/dist/src/codex/scanner.js.map +1 -0
  60. package/dist/src/codex/types.d.ts +31 -0
  61. package/dist/src/codex/types.js +5 -0
  62. package/dist/src/codex/types.js.map +1 -0
  63. package/dist/src/collector/collector.d.ts +15 -0
  64. package/dist/src/collector/collector.js +597 -0
  65. package/dist/src/collector/collector.js.map +1 -0
  66. package/dist/src/collector/index.d.ts +3 -0
  67. package/dist/src/collector/index.js +3 -0
  68. package/dist/src/collector/index.js.map +1 -0
  69. package/dist/src/collector/types.d.ts +55 -0
  70. package/dist/src/collector/types.js +18 -0
  71. package/dist/src/collector/types.js.map +1 -0
  72. package/dist/src/dashboard/render/ansi.d.ts +53 -0
  73. package/dist/src/dashboard/render/ansi.js +106 -0
  74. package/dist/src/dashboard/render/ansi.js.map +1 -0
  75. package/dist/src/dashboard/render/dashboard.d.ts +13 -0
  76. package/dist/src/dashboard/render/dashboard.js +750 -0
  77. package/dist/src/dashboard/render/dashboard.js.map +1 -0
  78. package/dist/src/dashboard/render/format.d.ts +23 -0
  79. package/dist/src/dashboard/render/format.js +169 -0
  80. package/dist/src/dashboard/render/format.js.map +1 -0
  81. package/dist/src/dashboard/render/redraw.d.ts +13 -0
  82. package/dist/src/dashboard/render/redraw.js +24 -0
  83. package/dist/src/dashboard/render/redraw.js.map +1 -0
  84. package/dist/src/dashboard/render/types.d.ts +83 -0
  85. package/dist/src/dashboard/render/types.js +528 -0
  86. package/dist/src/dashboard/render/types.js.map +1 -0
  87. package/dist/src/dashboard/scheduler/index.d.ts +1 -0
  88. package/dist/src/dashboard/scheduler/index.js +2 -0
  89. package/dist/src/dashboard/scheduler/index.js.map +1 -0
  90. package/dist/src/dashboard/scheduler/refresh-scheduler.d.ts +46 -0
  91. package/dist/src/dashboard/scheduler/refresh-scheduler.js +137 -0
  92. package/dist/src/dashboard/scheduler/refresh-scheduler.js.map +1 -0
  93. package/dist/src/dashboard/settings/index.d.ts +25 -0
  94. package/dist/src/dashboard/settings/index.js +162 -0
  95. package/dist/src/dashboard/settings/index.js.map +1 -0
  96. package/dist/src/dashboard/state/index.d.ts +2 -0
  97. package/dist/src/dashboard/state/index.js +3 -0
  98. package/dist/src/dashboard/state/index.js.map +1 -0
  99. package/dist/src/dashboard/state/refresh-coordinator.d.ts +72 -0
  100. package/dist/src/dashboard/state/refresh-coordinator.js +346 -0
  101. package/dist/src/dashboard/state/refresh-coordinator.js.map +1 -0
  102. package/dist/src/dashboard/state/types.d.ts +68 -0
  103. package/dist/src/dashboard/state/types.js +2 -0
  104. package/dist/src/dashboard/state/types.js.map +1 -0
  105. package/dist/src/domain/contracts.d.ts +219 -0
  106. package/dist/src/domain/contracts.js +2 -0
  107. package/dist/src/domain/contracts.js.map +1 -0
  108. package/dist/src/domain/errors.d.ts +25 -0
  109. package/dist/src/domain/errors.js +65 -0
  110. package/dist/src/domain/errors.js.map +1 -0
  111. package/dist/src/domain/index.d.ts +5 -0
  112. package/dist/src/domain/index.js +6 -0
  113. package/dist/src/domain/index.js.map +1 -0
  114. package/dist/src/domain/records.d.ts +59 -0
  115. package/dist/src/domain/records.js +141 -0
  116. package/dist/src/domain/records.js.map +1 -0
  117. package/dist/src/domain/tokens.d.ts +51 -0
  118. package/dist/src/domain/tokens.js +93 -0
  119. package/dist/src/domain/tokens.js.map +1 -0
  120. package/dist/src/domain/windows.d.ts +59 -0
  121. package/dist/src/domain/windows.js +272 -0
  122. package/dist/src/domain/windows.js.map +1 -0
  123. package/dist/src/index.d.ts +9 -0
  124. package/dist/src/index.js +9 -0
  125. package/dist/src/index.js.map +1 -0
  126. package/dist/src/opencode/adapter.d.ts +47 -0
  127. package/dist/src/opencode/adapter.js +118 -0
  128. package/dist/src/opencode/adapter.js.map +1 -0
  129. package/dist/src/opencode/client.d.ts +64 -0
  130. package/dist/src/opencode/client.js +118 -0
  131. package/dist/src/opencode/client.js.map +1 -0
  132. package/dist/src/opencode/doctor.d.ts +28 -0
  133. package/dist/src/opencode/doctor.js +82 -0
  134. package/dist/src/opencode/doctor.js.map +1 -0
  135. package/dist/src/opencode/index.d.ts +5 -0
  136. package/dist/src/opencode/index.js +6 -0
  137. package/dist/src/opencode/index.js.map +1 -0
  138. package/dist/src/opencode/stats.d.ts +8 -0
  139. package/dist/src/opencode/stats.js +174 -0
  140. package/dist/src/opencode/stats.js.map +1 -0
  141. package/dist/src/opencode/transport.d.ts +54 -0
  142. package/dist/src/opencode/transport.js +621 -0
  143. package/dist/src/opencode/transport.js.map +1 -0
  144. package/dist/src/output/index.d.ts +20 -0
  145. package/dist/src/output/index.js +46 -0
  146. package/dist/src/output/index.js.map +1 -0
  147. package/dist/src/output/json.d.ts +72 -0
  148. package/dist/src/output/json.js +133 -0
  149. package/dist/src/output/json.js.map +1 -0
  150. package/dist/src/output/table.d.ts +4 -0
  151. package/dist/src/output/table.js +81 -0
  152. package/dist/src/output/table.js.map +1 -0
  153. package/dist/src/pricing/index.d.ts +1 -0
  154. package/dist/src/pricing/index.js +2 -0
  155. package/dist/src/pricing/index.js.map +1 -0
  156. package/dist/src/pricing/pricing.d.ts +19 -0
  157. package/dist/src/pricing/pricing.js +441 -0
  158. package/dist/src/pricing/pricing.js.map +1 -0
  159. package/package.json +27 -0
@@ -0,0 +1,346 @@
1
+ import { createUsageWindows } from "../../domain/windows.js";
2
+ import { RefreshScheduler, } from "../scheduler/refresh-scheduler.js";
3
+ const REASON_PRIORITY = {
4
+ timer: 1,
5
+ wake: 2,
6
+ manual: 3,
7
+ };
8
+ function copyDate(date) {
9
+ return new Date(date.getTime());
10
+ }
11
+ function cancelledOutcome(generation, reason) {
12
+ return { kind: "cancelled", generation, reason };
13
+ }
14
+ /**
15
+ * Owns every visible refresh transition. Sources do not mutate dashboard
16
+ * state; they return one result which is committed only by its current
17
+ * generation.
18
+ */
19
+ export class RefreshCoordinator {
20
+ source;
21
+ clock;
22
+ timezone;
23
+ project;
24
+ listeners = new Set();
25
+ scheduler;
26
+ cleanupTimeoutMilliseconds;
27
+ state;
28
+ active;
29
+ pendingReason;
30
+ pendingWaiters = [];
31
+ nextGeneration = 0;
32
+ started = false;
33
+ quitting = false;
34
+ startPromise;
35
+ configuredOnStateChange;
36
+ constructor(options) {
37
+ this.source = options.source;
38
+ this.clock = options.clock;
39
+ this.timezone = options.timezone;
40
+ this.project = options.project;
41
+ this.cleanupTimeoutMilliseconds = options.cleanupTimeoutMilliseconds ?? 250;
42
+ if (!Number.isFinite(this.cleanupTimeoutMilliseconds) || this.cleanupTimeoutMilliseconds < 0) {
43
+ throw new RangeError("cleanupTimeoutMilliseconds must be non-negative");
44
+ }
45
+ this.configuredOnStateChange = options.onStateChange;
46
+ this.state = {
47
+ status: "idle",
48
+ generation: 0,
49
+ stale: false,
50
+ period: options.initialPeriod ?? "day",
51
+ navigation: options.initialNavigation ?? {},
52
+ ...(options.initialSnapshot === undefined
53
+ ? {}
54
+ : {
55
+ snapshot: options.initialSnapshot,
56
+ lastGoodSnapshot: options.initialSnapshot,
57
+ lastUpdated: new Date(options.initialSnapshot.capturedAt.getTime()),
58
+ stale: true,
59
+ }),
60
+ };
61
+ this.scheduler = options.scheduler ?? new RefreshScheduler({
62
+ clock: options.clock,
63
+ refreshIntervalSeconds: options.refreshIntervalSeconds,
64
+ timers: options.timers,
65
+ onRequest: (reason) => this.handleScheduledRequest(reason),
66
+ });
67
+ }
68
+ get refreshScheduler() {
69
+ return this.scheduler;
70
+ }
71
+ get isRefreshing() {
72
+ return this.active !== undefined;
73
+ }
74
+ get isStopped() {
75
+ return this.quitting;
76
+ }
77
+ getState() {
78
+ // Dates are copied so a renderer cannot mutate coordinator state between
79
+ // event-loop turns. Result/navigation are owned by their immutable seams.
80
+ return {
81
+ ...this.state,
82
+ ...(this.state.lastUpdated === undefined
83
+ ? {}
84
+ : { lastUpdated: copyDate(this.state.lastUpdated) }),
85
+ ...(this.state.nextRefreshAt === undefined
86
+ ? {}
87
+ : { nextRefreshAt: this.state.nextRefreshAt }),
88
+ ...(this.active === undefined ? {} : { activeGeneration: this.active.generation }),
89
+ ...(this.scheduler.nextRefreshAt() === undefined
90
+ ? { nextRefreshAt: undefined, countdownSeconds: undefined }
91
+ : {
92
+ nextRefreshAt: this.scheduler.nextRefreshAt(),
93
+ countdownSeconds: this.scheduler.countdownSeconds(),
94
+ }),
95
+ };
96
+ }
97
+ subscribe(listener) {
98
+ this.listeners.add(listener);
99
+ return () => this.listeners.delete(listener);
100
+ }
101
+ setPeriod(period) {
102
+ this.state = { ...this.state, period };
103
+ this.emit();
104
+ }
105
+ setNavigation(navigation) {
106
+ this.state = { ...this.state, navigation };
107
+ this.emit();
108
+ }
109
+ get refreshIntervalSeconds() {
110
+ return this.scheduler.refreshIntervalSeconds
111
+ ?? this.scheduler.refreshIntervalSeconds
112
+ ?? 0;
113
+ }
114
+ setRefreshIntervalSeconds(seconds) {
115
+ if (this.scheduler.setRefreshIntervalSeconds === undefined) {
116
+ throw new Error("Scheduler does not support dynamic interval updates");
117
+ }
118
+ this.scheduler.setRefreshIntervalSeconds(seconds);
119
+ this.emit();
120
+ }
121
+ /** Start the scheduler and immediately issue exactly one initial refresh. */
122
+ start() {
123
+ if (this.started) {
124
+ return this.startPromise ?? Promise.resolve(cancelledOutcome(this.nextGeneration, "initial"));
125
+ }
126
+ this.started = true;
127
+ this.scheduler.start();
128
+ this.startPromise = this.begin("initial");
129
+ return this.startPromise;
130
+ }
131
+ /** Request a refresh; concurrent requests are reduced to one pending reason. */
132
+ request(reason = "manual") {
133
+ if (!this.started || this.quitting) {
134
+ return Promise.resolve(cancelledOutcome(this.nextGeneration, reason));
135
+ }
136
+ if (reason === "manual" || reason === "wake") {
137
+ this.scheduler.reset();
138
+ }
139
+ if (this.active !== undefined) {
140
+ if (reason === "initial") {
141
+ return this.active.promise;
142
+ }
143
+ this.pendingReason = this.mergePendingReason(this.pendingReason, reason);
144
+ this.state = { ...this.state, pendingReason: this.pendingReason };
145
+ this.emit();
146
+ return new Promise((resolve) => {
147
+ this.pendingWaiters.push({ resolve });
148
+ });
149
+ }
150
+ return this.begin(reason);
151
+ }
152
+ refresh() {
153
+ return this.request("manual");
154
+ }
155
+ manualRefresh() {
156
+ return this.request("manual");
157
+ }
158
+ wake() {
159
+ return this.request("wake");
160
+ }
161
+ /**
162
+ * Stop scheduling, invalidate the current generation, abort network work,
163
+ * and wait only briefly for sources which honor cancellation.
164
+ */
165
+ async quit() {
166
+ if (this.quitting) {
167
+ return;
168
+ }
169
+ this.quitting = true;
170
+ this.scheduler.stop();
171
+ this.nextGeneration += 1;
172
+ const active = this.active;
173
+ if (active !== undefined) {
174
+ active.controller.abort();
175
+ }
176
+ const cancelled = cancelledOutcome(this.nextGeneration, "manual");
177
+ for (const waiter of this.pendingWaiters) {
178
+ waiter.resolve(cancelled);
179
+ }
180
+ this.pendingWaiters = [];
181
+ this.pendingReason = undefined;
182
+ this.state = {
183
+ ...this.state,
184
+ status: "stopped",
185
+ generation: this.nextGeneration,
186
+ activeGeneration: undefined,
187
+ pendingReason: undefined,
188
+ };
189
+ this.emit();
190
+ if (active !== undefined) {
191
+ await this.waitForCleanup(active.promise);
192
+ }
193
+ }
194
+ begin(reason) {
195
+ if (this.quitting) {
196
+ return Promise.resolve(cancelledOutcome(this.nextGeneration, reason));
197
+ }
198
+ const generation = ++this.nextGeneration;
199
+ const controller = new AbortController();
200
+ const wallNow = copyDate(this.clock.wallNow());
201
+ const monotonicStartedAt = this.clock.monotonicNow();
202
+ const active = {
203
+ generation,
204
+ reason,
205
+ controller,
206
+ promise: Promise.resolve(cancelledOutcome(generation, reason)),
207
+ };
208
+ this.active = active;
209
+ this.state = {
210
+ ...this.state,
211
+ status: "refreshing",
212
+ generation,
213
+ activeGeneration: generation,
214
+ pendingReason: undefined,
215
+ // A previous result remains visible while the next one is loading.
216
+ stale: this.state.lastGoodSnapshot !== undefined,
217
+ };
218
+ this.emit();
219
+ active.promise = Promise.resolve()
220
+ .then(() => {
221
+ const request = {
222
+ generation,
223
+ reason,
224
+ wallNow,
225
+ monotonicStartedAt,
226
+ capturedAt: wallNow,
227
+ windows: Object.values(createUsageWindows(wallNow, this.timezone)),
228
+ ...(this.project === undefined ? {} : { project: this.project }),
229
+ includeSubagents: true,
230
+ includeProvisional: false,
231
+ signal: controller.signal,
232
+ };
233
+ return this.source.collect(request);
234
+ })
235
+ .then((result) => {
236
+ if (this.quitting ||
237
+ controller.signal.aborted ||
238
+ this.active !== active ||
239
+ this.nextGeneration !== generation) {
240
+ return { kind: "discarded", generation, reason };
241
+ }
242
+ const lastUpdated = copyDate(this.clock.wallNow());
243
+ this.state = {
244
+ ...this.state,
245
+ status: "ready",
246
+ generation,
247
+ activeGeneration: undefined,
248
+ snapshot: result,
249
+ lastGoodSnapshot: result,
250
+ lastUpdated,
251
+ lastError: undefined,
252
+ stale: false,
253
+ };
254
+ this.emit();
255
+ return { kind: "committed", generation, reason, result };
256
+ }, (error) => {
257
+ if (this.quitting ||
258
+ controller.signal.aborted ||
259
+ this.active !== active ||
260
+ this.nextGeneration !== generation) {
261
+ return { kind: "cancelled", generation, reason, error };
262
+ }
263
+ this.state = {
264
+ ...this.state,
265
+ status: "error",
266
+ generation,
267
+ activeGeneration: undefined,
268
+ // Keep the last good snapshot in both fields. A renderer can show
269
+ // the error without losing the most recent trustworthy totals.
270
+ snapshot: this.state.lastGoodSnapshot,
271
+ lastError: error,
272
+ stale: this.state.lastGoodSnapshot !== undefined,
273
+ };
274
+ this.emit();
275
+ return { kind: "failed", generation, reason, error };
276
+ })
277
+ .finally(() => {
278
+ if (this.active !== active) {
279
+ return;
280
+ }
281
+ this.active = undefined;
282
+ this.state = {
283
+ ...this.state,
284
+ activeGeneration: undefined,
285
+ };
286
+ this.emit();
287
+ if (!this.quitting && this.pendingReason !== undefined) {
288
+ const pendingReason = this.pendingReason;
289
+ const waiters = this.pendingWaiters;
290
+ this.pendingReason = undefined;
291
+ this.pendingWaiters = [];
292
+ this.state = { ...this.state, pendingReason: undefined };
293
+ this.emit();
294
+ void this.begin(pendingReason).then((outcome) => {
295
+ for (const waiter of waiters) {
296
+ waiter.resolve(outcome);
297
+ }
298
+ });
299
+ }
300
+ });
301
+ return active.promise;
302
+ }
303
+ mergePendingReason(current, requested) {
304
+ if (current === undefined || REASON_PRIORITY[requested] > REASON_PRIORITY[current]) {
305
+ return requested;
306
+ }
307
+ return current;
308
+ }
309
+ handleScheduledRequest(reason) {
310
+ if (!this.started || this.quitting) {
311
+ return;
312
+ }
313
+ // Timer callbacks have no caller waiting for a Promise. Update the one
314
+ // pending reason in place so delayed wake/sleep periods cannot accumulate
315
+ // an unbounded waiter queue.
316
+ if (this.active !== undefined) {
317
+ this.pendingReason = this.mergePendingReason(this.pendingReason, reason);
318
+ this.state = { ...this.state, pendingReason: this.pendingReason };
319
+ this.emit();
320
+ return;
321
+ }
322
+ void this.request(reason);
323
+ }
324
+ async waitForCleanup(activePromise) {
325
+ let timeoutHandle;
326
+ const timeout = new Promise((resolve) => {
327
+ timeoutHandle = setTimeout(resolve, this.cleanupTimeoutMilliseconds);
328
+ if (timeoutHandle !== undefined && typeof timeoutHandle === "object" && "unref" in timeoutHandle) {
329
+ timeoutHandle.unref();
330
+ }
331
+ });
332
+ await Promise.race([activePromise.then(() => undefined), timeout]);
333
+ if (timeoutHandle !== undefined) {
334
+ clearTimeout(timeoutHandle);
335
+ }
336
+ }
337
+ emit() {
338
+ const next = this.getState();
339
+ this.configuredOnStateChange?.(next);
340
+ for (const listener of this.listeners) {
341
+ listener(next);
342
+ }
343
+ }
344
+ }
345
+ export { RefreshScheduler };
346
+ //# sourceMappingURL=refresh-coordinator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refresh-coordinator.js","sourceRoot":"","sources":["../../../../src/dashboard/state/refresh-coordinator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ import type { Clock as DomainClock, CollectionRequest, CollectionResult, UsageSource as DomainUsageSource, UsageWindow, UsageWindowKind } from "../../domain/index.js";
2
+ /** Reasons which can enter the refresh lifecycle. */
3
+ export type RefreshReason = "initial" | "timer" | "manual" | "wake";
4
+ /**
5
+ * The clock used by the dashboard. `wallNow` is for report windows and
6
+ * timestamps; `monotonicNow` is for scheduling and countdowns.
7
+ */
8
+ export type Clock = DomainClock;
9
+ /** The request handed to the usage source for one immutable generation. */
10
+ export interface RefreshRequest extends CollectionRequest {
11
+ readonly generation: number;
12
+ readonly reason: RefreshReason;
13
+ readonly wallNow: Date;
14
+ readonly monotonicStartedAt: number;
15
+ readonly capturedAt: Date;
16
+ readonly windows: ReadonlyArray<UsageWindow>;
17
+ readonly signal: AbortSignal;
18
+ }
19
+ /**
20
+ * This is deliberately structural. The collector/domain seam can return its
21
+ * immutable CollectionResult directly, so the dashboard never knows how the
22
+ * result is assembled or persisted.
23
+ */
24
+ export type UsageSource = DomainUsageSource;
25
+ export type DashboardStatus = "idle" | "refreshing" | "ready" | "error" | "stopped";
26
+ export interface DashboardNavigation {
27
+ readonly panel?: string;
28
+ readonly index?: number;
29
+ readonly scrollOffset?: number;
30
+ readonly [key: string]: unknown;
31
+ }
32
+ export interface RefreshState<Navigation = DashboardNavigation> {
33
+ readonly status: DashboardStatus;
34
+ readonly generation: number;
35
+ readonly activeGeneration?: number;
36
+ /** The latest successful result, retained while a refresh is in flight/fails. */
37
+ readonly snapshot?: CollectionResult;
38
+ readonly lastGoodSnapshot?: CollectionResult;
39
+ readonly lastUpdated?: Date;
40
+ readonly lastError?: unknown;
41
+ readonly stale: boolean;
42
+ readonly pendingReason?: Exclude<RefreshReason, "initial">;
43
+ readonly period: UsageWindowKind;
44
+ readonly navigation: Navigation;
45
+ /** Monotonic deadline; absent in manual-only mode. */
46
+ readonly nextRefreshAt?: number;
47
+ /** Whole seconds remaining, derived from monotonic time. */
48
+ readonly countdownSeconds?: number;
49
+ }
50
+ export type RefreshOutcomeKind = "committed" | "failed" | "discarded" | "cancelled";
51
+ export interface RefreshOutcome {
52
+ readonly kind: RefreshOutcomeKind;
53
+ readonly generation: number;
54
+ readonly reason: RefreshReason;
55
+ readonly result?: CollectionResult;
56
+ readonly error?: unknown;
57
+ }
58
+ export interface RefreshSchedulerLike {
59
+ start(): void;
60
+ stop(): void;
61
+ reset(): void;
62
+ manual(): void;
63
+ wake(): void;
64
+ countdownSeconds(): number | undefined;
65
+ nextRefreshAt(): number | undefined;
66
+ readonly refreshIntervalSeconds?: number;
67
+ setRefreshIntervalSeconds?(seconds: number): void;
68
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/dashboard/state/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,219 @@
1
+ import type { CollectionError } from "./errors.js";
2
+ import type { TokenComponentsInput, UsageTotals } from "./tokens.js";
3
+ import type { UsageRecord, UsageRecordCompleteness } from "./records.js";
4
+ import type { UsageBucket, UsageWindow, UsageWindowKind } from "./windows.js";
5
+ export type CollectionSource = "stats" | "message-scan" | "codex" | "antigravity" | "unified";
6
+ export type ProviderKind = "opencode" | "codex" | "antigravity";
7
+ /**
8
+ * Coverage describes what a collection actually observed. `complete` means
9
+ * traversal finished without a known gap; it does not turn provisional usage
10
+ * into final usage and it must never be inferred from non-zero totals.
11
+ */
12
+ export interface Coverage {
13
+ readonly complete: boolean;
14
+ readonly sessionsDiscovered: number;
15
+ readonly sessionsScanned: number;
16
+ readonly sessionsSkipped: number;
17
+ readonly pagesRead: number;
18
+ readonly jobsRetried: number;
19
+ readonly provisionalMessages: number;
20
+ readonly errors: ReadonlyArray<CollectionError>;
21
+ }
22
+ export type UsageTotalsByWindow = Readonly<Partial<Record<UsageWindowKind, UsageTotals>>>;
23
+ /** Aggregate model/provider data returned by the stats endpoint. */
24
+ export interface UsageBreakdown {
25
+ readonly name: string;
26
+ readonly provider?: string;
27
+ readonly totals: UsageTotals;
28
+ }
29
+ export type UsageBreakdownsByWindow = Readonly<Partial<Record<UsageWindowKind, ReadonlyArray<UsageBreakdown>>>>;
30
+ /** Range accepted by the OpenCode stats endpoint. */
31
+ export interface UsageStatsRange {
32
+ readonly from: Date;
33
+ readonly to: Date;
34
+ readonly timezone: string;
35
+ }
36
+ export interface UsageTrendBucket extends UsageBucket {
37
+ readonly totals: UsageTotals;
38
+ }
39
+ export type UsageTrendsByWindow = Readonly<Partial<Record<UsageWindowKind, ReadonlyArray<UsageTrendBucket>>>>;
40
+ /**
41
+ * One immutable collection intent. `capturedAt` and `windows` are created
42
+ * together so hour/day/week workers cannot each choose a different `now`.
43
+ *
44
+ * Recoverable item failures should be represented in a resolved partial result
45
+ * with `coverage.complete === false`. Cancellation is control flow instead:
46
+ * implementations must reject with a `DomainError` whose code is `cancelled`
47
+ * after observing `signal`; callers may retain a prior snapshot but may not
48
+ * publish the cancelled result as current.
49
+ */
50
+ export interface CollectionRequest {
51
+ readonly capturedAt: Date;
52
+ readonly windows: ReadonlyArray<UsageWindow>;
53
+ readonly project?: string;
54
+ /** Defaults to true in the collector; child sessions are model work. */
55
+ readonly includeSubagents?: boolean;
56
+ /** Defaults to false so provisional usage is not silently presented as final. */
57
+ readonly includeProvisional?: boolean;
58
+ /** Refresh generation used to discard late results. */
59
+ readonly generation?: number;
60
+ readonly signal?: AbortSignal;
61
+ }
62
+ /**
63
+ * A collection may be partial while still carrying useful records. Consumers
64
+ * must inspect Coverage and source together with totals. No implementation may
65
+ * combine stats totals and message-scan totals for the same requested window.
66
+ */
67
+ export interface CollectionResult {
68
+ readonly capturedAt: Date;
69
+ readonly windows: ReadonlyArray<UsageWindow>;
70
+ readonly source: CollectionSource;
71
+ readonly records: ReadonlyArray<UsageRecord>;
72
+ readonly totalsByWindow: UsageTotalsByWindow;
73
+ readonly models?: ReadonlyArray<UsageBreakdown>;
74
+ readonly providers?: ReadonlyArray<UsageBreakdown>;
75
+ readonly projects?: ReadonlyArray<UsageBreakdown>;
76
+ readonly modelsByWindow?: UsageBreakdownsByWindow;
77
+ readonly providersByWindow?: UsageBreakdownsByWindow;
78
+ readonly projectsByWindow?: UsageBreakdownsByWindow;
79
+ readonly trendsByWindow?: UsageTrendsByWindow;
80
+ readonly coverage: Coverage;
81
+ readonly serverFingerprint?: string;
82
+ readonly serverVersion?: string;
83
+ }
84
+ export declare const SNAPSHOT_SCHEMA_VERSION: 1;
85
+ /**
86
+ * Persistable read model. A store commit must publish this as one immutable
87
+ * snapshot (normally via temp-file flush and same-directory rename). A failed
88
+ * commit leaves the previous snapshot readable. Store cancellation before the
89
+ * atomic publish must reject and must not report a successful commit.
90
+ */
91
+ export interface StoredSnapshot {
92
+ readonly schemaVersion: typeof SNAPSHOT_SCHEMA_VERSION;
93
+ readonly generation: number;
94
+ readonly capturedAt: Date;
95
+ readonly requestedWindows: ReadonlyArray<UsageWindow>;
96
+ readonly source: CollectionSource;
97
+ readonly records: ReadonlyArray<UsageRecord>;
98
+ readonly totalsByWindow: UsageTotalsByWindow;
99
+ readonly models?: ReadonlyArray<UsageBreakdown>;
100
+ readonly providers?: ReadonlyArray<UsageBreakdown>;
101
+ readonly projects?: ReadonlyArray<UsageBreakdown>;
102
+ readonly modelsByWindow?: UsageBreakdownsByWindow;
103
+ readonly providersByWindow?: UsageBreakdownsByWindow;
104
+ readonly projectsByWindow?: UsageBreakdownsByWindow;
105
+ readonly trendsByWindow?: UsageTrendsByWindow;
106
+ readonly coverage: Coverage;
107
+ readonly serverFingerprint?: string;
108
+ readonly serverVersion?: string;
109
+ }
110
+ export interface TransportRequestOptions {
111
+ /** A transport must stop issuing work and reject with cancellation promptly. */
112
+ readonly signal?: AbortSignal;
113
+ }
114
+ export interface SessionListRequest extends TransportRequestOptions {
115
+ readonly cursor?: string;
116
+ readonly limit?: number;
117
+ }
118
+ export interface MessageListRequest extends TransportRequestOptions {
119
+ readonly sessionID: string;
120
+ readonly cursor?: string;
121
+ readonly limit?: number;
122
+ }
123
+ export interface OpenCodeSession {
124
+ readonly sessionID: string;
125
+ readonly parentSessionID?: string;
126
+ readonly projectID?: string;
127
+ readonly directory?: string;
128
+ readonly workspaceID?: string;
129
+ }
130
+ export interface OpenCodeAssistantMessage {
131
+ readonly sessionID: string;
132
+ readonly messageID: string;
133
+ readonly createdAt: Date;
134
+ readonly model: string;
135
+ /** Undefined means the API omitted the token object, not zero usage. */
136
+ readonly tokens?: TokenComponentsInput;
137
+ readonly completeness: UsageRecordCompleteness;
138
+ }
139
+ export interface SessionPage {
140
+ readonly sessions: ReadonlyArray<OpenCodeSession>;
141
+ /** `null` means exhausted; a repeated cursor is a protocol error. */
142
+ readonly nextCursor: string | null;
143
+ }
144
+ export interface MessagePage {
145
+ readonly messages: ReadonlyArray<OpenCodeAssistantMessage>;
146
+ /** `null` means exhausted; a repeated cursor is a protocol error. */
147
+ readonly nextCursor: string | null;
148
+ }
149
+ export interface OpenCodeHealth {
150
+ readonly version: string;
151
+ readonly fingerprint: string;
152
+ }
153
+ export interface OpenCodeRange {
154
+ readonly from: Date;
155
+ readonly to: Date;
156
+ readonly timezone: string;
157
+ }
158
+ export interface OpenCodeProject {
159
+ readonly id: string;
160
+ readonly canonical: string;
161
+ readonly name?: string;
162
+ }
163
+ export interface OpenCodeSessionStats {
164
+ readonly requestedWindow: UsageStatsRange;
165
+ /** The server-reported range must be compared with requestedWindow by the collector. */
166
+ readonly reportedRange: OpenCodeRange;
167
+ readonly totals: UsageTotals;
168
+ readonly models?: ReadonlyArray<UsageBreakdown>;
169
+ readonly providers?: ReadonlyArray<UsageBreakdown>;
170
+ }
171
+ /**
172
+ * Adapter seam for the read-only OpenCode 2 V2 server API.
173
+ *
174
+ * Every operation is an idempotent read. Implementations may retry reads but
175
+ * must not duplicate accounting as a retry side effect. They must honor an
176
+ * AbortSignal promptly, reject with cancellation rather than return a falsely
177
+ * complete page, and avoid exposing prompts/tool content in these DTOs.
178
+ * `getSessionStats` is usable only after its reported range is validated;
179
+ * callers must fall back to paginated messages when the server ignores bounds.
180
+ */
181
+ export interface OpenCodeTransport {
182
+ getHealth(options?: TransportRequestOptions): Promise<OpenCodeHealth>;
183
+ getSessionStats(window: UsageStatsRange, options?: TransportRequestOptions & {
184
+ readonly project?: string;
185
+ }): Promise<OpenCodeSessionStats>;
186
+ listSessions(request?: SessionListRequest): Promise<SessionPage>;
187
+ listMessages(request: MessageListRequest): Promise<MessagePage>;
188
+ listProjects?(options?: TransportRequestOptions): Promise<ReadonlyArray<OpenCodeProject>>;
189
+ }
190
+ /** A source such as stats or a paginated message collector. */
191
+ export interface UsageSource {
192
+ /**
193
+ * Resolve with a partial result for bounded, recoverable scan gaps. Reject
194
+ * cancellation so the refresh coordinator can discard this generation;
195
+ * never label a partial or cancelled result as complete.
196
+ */
197
+ collect(request: CollectionRequest): Promise<CollectionResult>;
198
+ }
199
+ export interface SnapshotStoreReadOptions extends TransportRequestOptions {
200
+ }
201
+ export interface SnapshotStoreCommitOptions extends TransportRequestOptions {
202
+ }
203
+ /**
204
+ * Process-safe snapshot persistence seam. Implementations serialize commits;
205
+ * a cache-busy condition should be reported rather than waiting forever, so a
206
+ * caller can continue with in-memory data and visible stale/partial status.
207
+ */
208
+ export interface SnapshotStore {
209
+ read(options?: SnapshotStoreReadOptions): Promise<StoredSnapshot | null>;
210
+ commit(snapshot: StoredSnapshot, options?: SnapshotStoreCommitOptions): Promise<void>;
211
+ }
212
+ /**
213
+ * Wall time drives calendar windows; monotonic milliseconds drive scheduling
214
+ * and elapsed-time budgets. Tests provide a fake implementation for both.
215
+ */
216
+ export interface Clock {
217
+ wallNow(): Date;
218
+ monotonicNow(): number;
219
+ }
@@ -0,0 +1,2 @@
1
+ export const SNAPSHOT_SCHEMA_VERSION = 1;
2
+ //# sourceMappingURL=contracts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../../../src/domain/contracts.ts"],"names":[],"mappings":"AAqGA,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAU,CAAC"}