sidekick-shared 0.24.5 → 0.26.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 (157) hide show
  1. package/CHANGELOG.md +92 -0
  2. package/README.md +205 -52
  3. package/dist/accountChangeSignal.d.ts +3 -0
  4. package/dist/accountChangeSignal.js +19 -0
  5. package/dist/accountChanges.d.ts +21 -0
  6. package/dist/accountChanges.js +170 -0
  7. package/dist/accountRegistry.d.ts +25 -2
  8. package/dist/accountRegistry.js +41 -13
  9. package/dist/accountStatus.d.ts +9 -1
  10. package/dist/accountStatus.js +3 -3
  11. package/dist/accounts.d.ts +3 -1
  12. package/dist/accounts.js +84 -64
  13. package/dist/aggregation/EventAggregator.d.ts +15 -2
  14. package/dist/aggregation/EventAggregator.js +54 -9
  15. package/dist/aggregation/costProvenance.d.ts +14 -0
  16. package/dist/aggregation/costProvenance.js +35 -0
  17. package/dist/aggregation/snapshot.d.ts +13 -2
  18. package/dist/aggregation/snapshot.js +57 -6
  19. package/dist/aggregation/types.d.ts +30 -1
  20. package/dist/analytics/compactionLedger.js +15 -5
  21. package/dist/analytics/qualityScore.js +2 -1
  22. package/dist/browser.d.ts +19 -4
  23. package/dist/browser.js +43 -1
  24. package/dist/codexProfiles.d.ts +3 -1
  25. package/dist/codexProfiles.js +4 -2
  26. package/dist/codexQuota.d.ts +2 -0
  27. package/dist/codexQuota.js +11 -66
  28. package/dist/codexQuotaWatcher.d.ts +6 -0
  29. package/dist/codexQuotaWatcher.js +101 -47
  30. package/dist/failingTools.d.ts +37 -0
  31. package/dist/failingTools.js +70 -0
  32. package/dist/formatters/sessionDump.js +13 -7
  33. package/dist/formatting.d.ts +13 -0
  34. package/dist/formatting.js +35 -0
  35. package/dist/historicalStore.d.ts +47 -0
  36. package/dist/historicalStore.js +312 -0
  37. package/dist/index.d.ts +67 -23
  38. package/dist/index.js +138 -26
  39. package/dist/modelAliases.d.ts +13 -0
  40. package/dist/modelAliases.js +58 -0
  41. package/dist/modelCatalog.d.ts +32 -0
  42. package/dist/modelCatalog.js +145 -0
  43. package/dist/modelContext.d.ts +36 -3
  44. package/dist/modelContext.js +109 -34
  45. package/dist/modelInfo.d.ts +30 -1
  46. package/dist/modelInfo.js +116 -26
  47. package/dist/multiProviderQuotaService.d.ts +8 -0
  48. package/dist/multiProviderQuotaService.js +64 -3
  49. package/dist/node.d.ts +23 -4
  50. package/dist/node.js +50 -1
  51. package/dist/observedContextWindows.d.ts +7 -0
  52. package/dist/observedContextWindows.js +17 -2
  53. package/dist/observedSessionCollector.d.ts +72 -6
  54. package/dist/observedSessionCollector.js +440 -47
  55. package/dist/parsers/codexHistory.d.ts +4 -2
  56. package/dist/parsers/codexHistory.js +9 -2
  57. package/dist/parsers/sessionActivityDetector.d.ts +28 -0
  58. package/dist/parsers/sessionActivityDetector.js +110 -15
  59. package/dist/parsers/sessionPathResolver.d.ts +11 -0
  60. package/dist/parsers/sessionPathResolver.js +13 -10
  61. package/dist/peakHours.d.ts +34 -3
  62. package/dist/peakHours.js +92 -7
  63. package/dist/pricingCatalog.d.ts +7 -0
  64. package/dist/pricingCatalog.js +8 -5
  65. package/dist/providerIds.d.ts +11 -0
  66. package/dist/providerIds.js +9 -0
  67. package/dist/providerQuota.d.ts +3 -1
  68. package/dist/providerQuota.js +3 -0
  69. package/dist/providers/claudeCode.d.ts +10 -1
  70. package/dist/providers/claudeCode.js +211 -131
  71. package/dist/providers/codex.d.ts +20 -1
  72. package/dist/providers/codex.js +308 -244
  73. package/dist/providers/codexDatabase.d.ts +9 -0
  74. package/dist/providers/codexDatabase.js +107 -2
  75. package/dist/providers/detect.d.ts +2 -0
  76. package/dist/providers/detect.js +29 -24
  77. package/dist/providers/diagnostics.d.ts +13 -0
  78. package/dist/providers/diagnostics.js +88 -0
  79. package/dist/providers/factory.d.ts +20 -0
  80. package/dist/providers/factory.js +57 -0
  81. package/dist/providers/openCode.d.ts +22 -1
  82. package/dist/providers/openCode.js +460 -126
  83. package/dist/providers/openCodeDatabase.d.ts +10 -0
  84. package/dist/providers/openCodeDatabase.js +69 -0
  85. package/dist/providers/rolloutWalker.d.ts +53 -0
  86. package/dist/providers/rolloutWalker.js +209 -0
  87. package/dist/providers/types.d.ts +82 -2
  88. package/dist/providers/types.js +4 -0
  89. package/dist/quota.d.ts +34 -4
  90. package/dist/quota.js +37 -9
  91. package/dist/quotaHistory.d.ts +3 -2
  92. package/dist/quotaHistory.js +36 -35
  93. package/dist/quotaPoller.d.ts +13 -1
  94. package/dist/quotaPoller.js +65 -3
  95. package/dist/quotaResolver.d.ts +81 -0
  96. package/dist/quotaResolver.js +213 -0
  97. package/dist/quotaSnapshots.d.ts +15 -2
  98. package/dist/quotaSnapshots.js +25 -3
  99. package/dist/quotaThresholds.d.ts +60 -0
  100. package/dist/quotaThresholds.js +90 -0
  101. package/dist/report/htmlReportGenerator.js +10 -4
  102. package/dist/report/sessionReportInputs.d.ts +23 -0
  103. package/dist/report/sessionReportInputs.js +34 -0
  104. package/dist/schemas/accountManager.d.ts +2 -2
  105. package/dist/schemas/accountManager.js +2 -4
  106. package/dist/schemas/accountStatus.d.ts +3 -0
  107. package/dist/schemas/accountStatus.js +1 -0
  108. package/dist/schemas/index.d.ts +3 -0
  109. package/dist/schemas/index.js +16 -2
  110. package/dist/schemas/observedSessionV1.d.ts +27 -26
  111. package/dist/schemas/observedSessionV1.js +6 -4
  112. package/dist/schemas/quota.d.ts +141 -2
  113. package/dist/schemas/quota.js +20 -8
  114. package/dist/schemas/quotaHistory.d.ts +3 -2
  115. package/dist/schemas/quotaHistory.js +1 -1
  116. package/dist/schemas/sessionEvent.d.ts +6 -0
  117. package/dist/schemas/sessionEvent.js +1 -0
  118. package/dist/schemas/stateFile.d.ts +198 -0
  119. package/dist/schemas/stateFile.js +77 -0
  120. package/dist/schemas/tokenEstimation.d.ts +1 -1
  121. package/dist/schemas/transcript.js +2 -0
  122. package/dist/sessionFingerprint.d.ts +25 -0
  123. package/dist/sessionFingerprint.js +46 -0
  124. package/dist/sessionMonitor.d.ts +15 -0
  125. package/dist/sessionMonitor.js +142 -0
  126. package/dist/sessionPreviews.d.ts +33 -2
  127. package/dist/sessionPreviews.js +333 -6
  128. package/dist/sessionStats.d.ts +51 -0
  129. package/dist/sessionStats.js +166 -0
  130. package/dist/stateFile.d.ts +113 -0
  131. package/dist/stateFile.js +160 -0
  132. package/dist/statusline/claudeStatuslinePayload.d.ts +89 -0
  133. package/dist/statusline/claudeStatuslinePayload.js +152 -0
  134. package/dist/statusline/formatter.d.ts +13 -0
  135. package/dist/statusline/formatter.js +48 -6
  136. package/dist/statusline/index.d.ts +10 -2
  137. package/dist/statusline/index.js +19 -1
  138. package/dist/tokenSummary.d.ts +62 -0
  139. package/dist/tokenSummary.js +72 -0
  140. package/dist/transcript.d.ts +5 -0
  141. package/dist/transcript.js +2 -0
  142. package/dist/types/observedSessionV1.d.ts +8 -2
  143. package/dist/types/observedSessionV1.js +88 -25
  144. package/dist/types/sessionEvent.d.ts +2 -0
  145. package/dist/usage/billingBlocks.d.ts +85 -0
  146. package/dist/usage/billingBlocks.js +153 -0
  147. package/dist/usage/importSessionHistory.d.ts +53 -0
  148. package/dist/usage/importSessionHistory.js +88 -0
  149. package/dist/usage/usageEvents.d.ts +92 -0
  150. package/dist/usage/usageEvents.js +322 -0
  151. package/dist/usage/usageReports.d.ts +76 -0
  152. package/dist/usage/usageReports.js +208 -0
  153. package/dist/watchers/factory.d.ts +6 -0
  154. package/dist/watchers/factory.js +30 -25
  155. package/dist/zaiQuotaApi.d.ts +2 -0
  156. package/dist/zaiQuotaApi.js +2 -0
  157. package/package.json +22 -1
@@ -11,15 +11,15 @@
11
11
  import { z } from 'zod';
12
12
  export declare const quotaHistoryRuntimeProviderSchema: z.ZodEnum<{
13
13
  codex: "codex";
14
- claude: "claude";
15
14
  zai: "zai";
15
+ claude: "claude";
16
16
  }>;
17
17
  export declare const quotaHistorySampleSchema: z.ZodObject<{
18
18
  timestamp: z.ZodString;
19
19
  runtimeProvider: z.ZodEnum<{
20
20
  codex: "codex";
21
- claude: "claude";
22
21
  zai: "zai";
22
+ claude: "claude";
23
23
  }>;
24
24
  providerId: z.ZodString;
25
25
  workspaceId: z.ZodString;
@@ -37,6 +37,7 @@ export declare const quotaHistorySampleSchema: z.ZodObject<{
37
37
  api: "api";
38
38
  cache: "cache";
39
39
  session: "session";
40
+ statusline: "statusline";
40
41
  }>>;
41
42
  stale: z.ZodOptional<z.ZodBoolean>;
42
43
  }, z.core.$strip>;
@@ -28,7 +28,7 @@ exports.quotaHistorySampleSchema = zod_1.z.object({
28
28
  sevenDay: zod_1.z.object({ utilization: zod_1.z.number(), resetsAt: zod_1.z.string() }),
29
29
  available: zod_1.z.boolean(),
30
30
  error: zod_1.z.string().optional(),
31
- source: zod_1.z.enum(['session', 'cache', 'api']).optional(),
31
+ source: zod_1.z.enum(['session', 'cache', 'api', 'statusline']).optional(),
32
32
  stale: zod_1.z.boolean().optional(),
33
33
  });
34
34
  // ── QuotaHistoryDailyBucket ──
@@ -52,6 +52,7 @@ export declare const sessionMessageSchema: z.ZodObject<{
52
52
  }, z.core.$strip>;
53
53
  }, z.core.$strip>>;
54
54
  content: z.ZodOptional<z.ZodUnknown>;
55
+ stop_reason: z.ZodOptional<z.ZodString>;
55
56
  }, z.core.$strip>;
56
57
  export declare const permissionModeSchema: z.ZodEnum<{
57
58
  default: "default";
@@ -136,6 +137,7 @@ export declare const userSessionEventSchema: z.ZodObject<{
136
137
  }, z.core.$strip>;
137
138
  }, z.core.$strip>>;
138
139
  content: z.ZodOptional<z.ZodUnknown>;
140
+ stop_reason: z.ZodOptional<z.ZodString>;
139
141
  }, z.core.$strip>;
140
142
  }, z.core.$strip>;
141
143
  export declare const assistantSessionEventSchema: z.ZodObject<{
@@ -215,6 +217,7 @@ export declare const assistantSessionEventSchema: z.ZodObject<{
215
217
  }, z.core.$strip>;
216
218
  }, z.core.$strip>>;
217
219
  content: z.ZodOptional<z.ZodUnknown>;
220
+ stop_reason: z.ZodOptional<z.ZodString>;
218
221
  }, z.core.$strip>;
219
222
  }, z.core.$strip>;
220
223
  export declare const summarySessionEventSchema: z.ZodType<SummarySessionEvent>;
@@ -295,6 +298,7 @@ export declare const systemSessionEventSchema: z.ZodObject<{
295
298
  }, z.core.$strip>;
296
299
  }, z.core.$strip>>;
297
300
  content: z.ZodOptional<z.ZodUnknown>;
301
+ stop_reason: z.ZodOptional<z.ZodString>;
298
302
  }, z.core.$strip>>;
299
303
  }, z.core.$strip>;
300
304
  export declare const toolUseSessionEventSchema: z.ZodObject<{
@@ -378,6 +382,7 @@ export declare const toolUseSessionEventSchema: z.ZodObject<{
378
382
  }, z.core.$strip>;
379
383
  }, z.core.$strip>>;
380
384
  content: z.ZodOptional<z.ZodUnknown>;
385
+ stop_reason: z.ZodOptional<z.ZodString>;
381
386
  }, z.core.$strip>>;
382
387
  }, z.core.$strip>;
383
388
  export declare const toolResultSessionEventSchema: z.ZodObject<{
@@ -462,6 +467,7 @@ export declare const toolResultSessionEventSchema: z.ZodObject<{
462
467
  }, z.core.$strip>;
463
468
  }, z.core.$strip>>;
464
469
  content: z.ZodOptional<z.ZodUnknown>;
470
+ stop_reason: z.ZodOptional<z.ZodString>;
465
471
  }, z.core.$strip>>;
466
472
  }, z.core.$strip>;
467
473
  export declare const sessionEventSchema: z.ZodType<SessionEvent>;
@@ -30,6 +30,7 @@ exports.sessionMessageSchema = zod_1.z.object({
30
30
  usage: exports.messageUsageSchema.optional(),
31
31
  normalizedUsage: usageNormalization_1.normalizedUsageSchema.optional(),
32
32
  content: zod_1.z.unknown().optional(),
33
+ stop_reason: zod_1.z.string().optional(),
33
34
  });
34
35
  // ── PermissionMode ──
35
36
  exports.permissionModeSchema = zod_1.z.enum([
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Zod schema for the public `state.json` contract (`schemaVersion: 1`).
3
+ *
4
+ * Mirrors the interfaces in `stateFile.ts` (keep in sync when those change;
5
+ * fields are only ever added). Consumers validating the file from another
6
+ * process import this from `sidekick-shared/schemas`.
7
+ *
8
+ * @module schemas/stateFile
9
+ */
10
+ import { z } from 'zod';
11
+ export declare const stateFileWriterSchema: z.ZodEnum<{
12
+ statusline: "statusline";
13
+ "cli-dashboard": "cli-dashboard";
14
+ "vscode-dashboard": "vscode-dashboard";
15
+ }>;
16
+ export declare const stateFileQuotaWindowSchema: z.ZodObject<{
17
+ utilization: z.ZodNumber;
18
+ resetsAt: z.ZodString;
19
+ }, z.core.$strip>;
20
+ export declare const stateFileQuotaSchema: z.ZodObject<{
21
+ fiveHour: z.ZodObject<{
22
+ utilization: z.ZodNumber;
23
+ resetsAt: z.ZodString;
24
+ }, z.core.$strip>;
25
+ sevenDay: z.ZodObject<{
26
+ utilization: z.ZodNumber;
27
+ resetsAt: z.ZodString;
28
+ }, z.core.$strip>;
29
+ source: z.ZodNullable<z.ZodEnum<{
30
+ api: "api";
31
+ cache: "cache";
32
+ session: "session";
33
+ statusline: "statusline";
34
+ }>>;
35
+ capturedSource: z.ZodNullable<z.ZodEnum<{
36
+ api: "api";
37
+ session: "session";
38
+ statusline: "statusline";
39
+ }>>;
40
+ capturedAt: z.ZodNullable<z.ZodString>;
41
+ ageMs: z.ZodNullable<z.ZodNumber>;
42
+ freshness: z.ZodNullable<z.ZodEnum<{
43
+ fresh: "fresh";
44
+ aging: "aging";
45
+ stale: "stale";
46
+ }>>;
47
+ }, z.core.$strip>;
48
+ export declare const stateFileAccountSchema: z.ZodObject<{
49
+ providerId: z.ZodEnum<{
50
+ "claude-code": "claude-code";
51
+ codex: "codex";
52
+ }>;
53
+ id: z.ZodNullable<z.ZodString>;
54
+ label: z.ZodNullable<z.ZodString>;
55
+ }, z.core.$strip>;
56
+ export declare const stateFileContextSchema: z.ZodObject<{
57
+ usedPercentage: z.ZodNullable<z.ZodNumber>;
58
+ contextWindowSize: z.ZodNullable<z.ZodNumber>;
59
+ totalInputTokens: z.ZodNullable<z.ZodNumber>;
60
+ totalOutputTokens: z.ZodNullable<z.ZodNumber>;
61
+ }, z.core.$strip>;
62
+ export declare const stateFileSessionSchema: z.ZodObject<{
63
+ sessionId: z.ZodNullable<z.ZodString>;
64
+ cwd: z.ZodNullable<z.ZodString>;
65
+ model: z.ZodNullable<z.ZodString>;
66
+ costUsd: z.ZodNullable<z.ZodNumber>;
67
+ durationMs: z.ZodNullable<z.ZodNumber>;
68
+ linesAdded: z.ZodNullable<z.ZodNumber>;
69
+ linesRemoved: z.ZodNullable<z.ZodNumber>;
70
+ promptCacheHitRatio: z.ZodNullable<z.ZodNumber>;
71
+ }, z.core.$strip>;
72
+ export declare const stateFileBillingBlockSchema: z.ZodObject<{
73
+ start: z.ZodString;
74
+ end: z.ZodString;
75
+ isActive: z.ZodBoolean;
76
+ tokens: z.ZodNumber;
77
+ costUsd: z.ZodNumber;
78
+ costProvenance: z.ZodEnum<{
79
+ none: "none";
80
+ reported: "reported";
81
+ estimated: "estimated";
82
+ unpriced: "unpriced";
83
+ mixed: "mixed";
84
+ }>;
85
+ burnRatePerMinute: z.ZodNumber;
86
+ projectedTokens: z.ZodNumber;
87
+ projectedCostUsd: z.ZodNumber;
88
+ remainingMs: z.ZodNumber;
89
+ }, z.core.$strip>;
90
+ export declare const sidekickStateFileSchema: z.ZodObject<{
91
+ schemaVersion: z.ZodLiteral<1>;
92
+ writtenAt: z.ZodString;
93
+ writer: z.ZodEnum<{
94
+ statusline: "statusline";
95
+ "cli-dashboard": "cli-dashboard";
96
+ "vscode-dashboard": "vscode-dashboard";
97
+ }>;
98
+ account: z.ZodNullable<z.ZodObject<{
99
+ providerId: z.ZodEnum<{
100
+ "claude-code": "claude-code";
101
+ codex: "codex";
102
+ }>;
103
+ id: z.ZodNullable<z.ZodString>;
104
+ label: z.ZodNullable<z.ZodString>;
105
+ }, z.core.$strip>>;
106
+ quota: z.ZodObject<{
107
+ claude: z.ZodNullable<z.ZodObject<{
108
+ fiveHour: z.ZodObject<{
109
+ utilization: z.ZodNumber;
110
+ resetsAt: z.ZodString;
111
+ }, z.core.$strip>;
112
+ sevenDay: z.ZodObject<{
113
+ utilization: z.ZodNumber;
114
+ resetsAt: z.ZodString;
115
+ }, z.core.$strip>;
116
+ source: z.ZodNullable<z.ZodEnum<{
117
+ api: "api";
118
+ cache: "cache";
119
+ session: "session";
120
+ statusline: "statusline";
121
+ }>>;
122
+ capturedSource: z.ZodNullable<z.ZodEnum<{
123
+ api: "api";
124
+ session: "session";
125
+ statusline: "statusline";
126
+ }>>;
127
+ capturedAt: z.ZodNullable<z.ZodString>;
128
+ ageMs: z.ZodNullable<z.ZodNumber>;
129
+ freshness: z.ZodNullable<z.ZodEnum<{
130
+ fresh: "fresh";
131
+ aging: "aging";
132
+ stale: "stale";
133
+ }>>;
134
+ }, z.core.$strip>>;
135
+ codex: z.ZodNullable<z.ZodObject<{
136
+ fiveHour: z.ZodObject<{
137
+ utilization: z.ZodNumber;
138
+ resetsAt: z.ZodString;
139
+ }, z.core.$strip>;
140
+ sevenDay: z.ZodObject<{
141
+ utilization: z.ZodNumber;
142
+ resetsAt: z.ZodString;
143
+ }, z.core.$strip>;
144
+ source: z.ZodNullable<z.ZodEnum<{
145
+ api: "api";
146
+ cache: "cache";
147
+ session: "session";
148
+ statusline: "statusline";
149
+ }>>;
150
+ capturedSource: z.ZodNullable<z.ZodEnum<{
151
+ api: "api";
152
+ session: "session";
153
+ statusline: "statusline";
154
+ }>>;
155
+ capturedAt: z.ZodNullable<z.ZodString>;
156
+ ageMs: z.ZodNullable<z.ZodNumber>;
157
+ freshness: z.ZodNullable<z.ZodEnum<{
158
+ fresh: "fresh";
159
+ aging: "aging";
160
+ stale: "stale";
161
+ }>>;
162
+ }, z.core.$strip>>;
163
+ }, z.core.$strip>;
164
+ context: z.ZodNullable<z.ZodObject<{
165
+ usedPercentage: z.ZodNullable<z.ZodNumber>;
166
+ contextWindowSize: z.ZodNullable<z.ZodNumber>;
167
+ totalInputTokens: z.ZodNullable<z.ZodNumber>;
168
+ totalOutputTokens: z.ZodNullable<z.ZodNumber>;
169
+ }, z.core.$strip>>;
170
+ session: z.ZodNullable<z.ZodObject<{
171
+ sessionId: z.ZodNullable<z.ZodString>;
172
+ cwd: z.ZodNullable<z.ZodString>;
173
+ model: z.ZodNullable<z.ZodString>;
174
+ costUsd: z.ZodNullable<z.ZodNumber>;
175
+ durationMs: z.ZodNullable<z.ZodNumber>;
176
+ linesAdded: z.ZodNullable<z.ZodNumber>;
177
+ linesRemoved: z.ZodNullable<z.ZodNumber>;
178
+ promptCacheHitRatio: z.ZodNullable<z.ZodNumber>;
179
+ }, z.core.$strip>>;
180
+ billingBlock: z.ZodNullable<z.ZodObject<{
181
+ start: z.ZodString;
182
+ end: z.ZodString;
183
+ isActive: z.ZodBoolean;
184
+ tokens: z.ZodNumber;
185
+ costUsd: z.ZodNumber;
186
+ costProvenance: z.ZodEnum<{
187
+ none: "none";
188
+ reported: "reported";
189
+ estimated: "estimated";
190
+ unpriced: "unpriced";
191
+ mixed: "mixed";
192
+ }>;
193
+ burnRatePerMinute: z.ZodNumber;
194
+ projectedTokens: z.ZodNumber;
195
+ projectedCostUsd: z.ZodNumber;
196
+ remainingMs: z.ZodNumber;
197
+ }, z.core.$strip>>;
198
+ }, z.core.$strip>;
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ /**
3
+ * Zod schema for the public `state.json` contract (`schemaVersion: 1`).
4
+ *
5
+ * Mirrors the interfaces in `stateFile.ts` (keep in sync when those change;
6
+ * fields are only ever added). Consumers validating the file from another
7
+ * process import this from `sidekick-shared/schemas`.
8
+ *
9
+ * @module schemas/stateFile
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.sidekickStateFileSchema = exports.stateFileBillingBlockSchema = exports.stateFileSessionSchema = exports.stateFileContextSchema = exports.stateFileAccountSchema = exports.stateFileQuotaSchema = exports.stateFileQuotaWindowSchema = exports.stateFileWriterSchema = void 0;
13
+ const zod_1 = require("zod");
14
+ exports.stateFileWriterSchema = zod_1.z.enum([
15
+ 'statusline',
16
+ 'cli-dashboard',
17
+ 'vscode-dashboard',
18
+ ]);
19
+ exports.stateFileQuotaWindowSchema = zod_1.z.object({
20
+ utilization: zod_1.z.number(),
21
+ resetsAt: zod_1.z.string(),
22
+ });
23
+ exports.stateFileQuotaSchema = zod_1.z.object({
24
+ fiveHour: exports.stateFileQuotaWindowSchema,
25
+ sevenDay: exports.stateFileQuotaWindowSchema,
26
+ source: zod_1.z.enum(['api', 'session', 'cache', 'statusline']).nullable(),
27
+ capturedSource: zod_1.z.enum(['api', 'session', 'statusline']).nullable(),
28
+ capturedAt: zod_1.z.string().nullable(),
29
+ ageMs: zod_1.z.number().nullable(),
30
+ freshness: zod_1.z.enum(['fresh', 'aging', 'stale']).nullable(),
31
+ });
32
+ exports.stateFileAccountSchema = zod_1.z.object({
33
+ providerId: zod_1.z.enum(['claude-code', 'codex']),
34
+ id: zod_1.z.string().nullable(),
35
+ label: zod_1.z.string().nullable(),
36
+ });
37
+ exports.stateFileContextSchema = zod_1.z.object({
38
+ usedPercentage: zod_1.z.number().nullable(),
39
+ contextWindowSize: zod_1.z.number().nullable(),
40
+ totalInputTokens: zod_1.z.number().nullable(),
41
+ totalOutputTokens: zod_1.z.number().nullable(),
42
+ });
43
+ exports.stateFileSessionSchema = zod_1.z.object({
44
+ sessionId: zod_1.z.string().nullable(),
45
+ cwd: zod_1.z.string().nullable(),
46
+ model: zod_1.z.string().nullable(),
47
+ costUsd: zod_1.z.number().nullable(),
48
+ durationMs: zod_1.z.number().nullable(),
49
+ linesAdded: zod_1.z.number().nullable(),
50
+ linesRemoved: zod_1.z.number().nullable(),
51
+ promptCacheHitRatio: zod_1.z.number().nullable(),
52
+ });
53
+ exports.stateFileBillingBlockSchema = zod_1.z.object({
54
+ start: zod_1.z.string(),
55
+ end: zod_1.z.string(),
56
+ isActive: zod_1.z.boolean(),
57
+ tokens: zod_1.z.number(),
58
+ costUsd: zod_1.z.number(),
59
+ costProvenance: zod_1.z.enum(['reported', 'estimated', 'mixed', 'unpriced', 'none']),
60
+ burnRatePerMinute: zod_1.z.number(),
61
+ projectedTokens: zod_1.z.number(),
62
+ projectedCostUsd: zod_1.z.number(),
63
+ remainingMs: zod_1.z.number(),
64
+ });
65
+ exports.sidekickStateFileSchema = zod_1.z.object({
66
+ schemaVersion: zod_1.z.literal(1),
67
+ writtenAt: zod_1.z.string(),
68
+ writer: exports.stateFileWriterSchema,
69
+ account: exports.stateFileAccountSchema.nullable(),
70
+ quota: zod_1.z.object({
71
+ claude: exports.stateFileQuotaSchema.nullable(),
72
+ codex: exports.stateFileQuotaSchema.nullable(),
73
+ }),
74
+ context: exports.stateFileContextSchema.nullable(),
75
+ session: exports.stateFileSessionSchema.nullable(),
76
+ billingBlock: exports.stateFileBillingBlockSchema.nullable(),
77
+ });
@@ -6,9 +6,9 @@ export declare const tokenEstimateSchema: z.ZodObject<{
6
6
  "sidekick-fallback-v1": "sidekick-fallback-v1";
7
7
  }>;
8
8
  confidence: z.ZodEnum<{
9
+ exact: "exact";
9
10
  low: "low";
10
11
  medium: "medium";
11
- exact: "exact";
12
12
  }>;
13
13
  provenance: z.ZodString;
14
14
  }, z.core.$strip>;
@@ -78,6 +78,8 @@ exports.canonicalSessionTranscriptSchema = zod_1.z.object({
78
78
  totalTokens: zod_1.z.number().finite().nonnegative(),
79
79
  }),
80
80
  totalCostUsd: zod_1.z.number().finite().nonnegative().nullable(),
81
+ pricedCostUsd: zod_1.z.number().finite().nonnegative(),
82
+ unpricedEvents: zod_1.z.number().int().nonnegative(),
81
83
  }),
82
84
  provenance: zod_1.z.object({
83
85
  source: zod_1.z.literal('session-events'),
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Size/mtime fingerprints for session sources.
3
+ *
4
+ * Shared by the observed-session collector, the V1 adapter's watch loop, and
5
+ * the usage cache, so "has this session changed?" is answered the same way
6
+ * everywhere without re-reading content.
7
+ *
8
+ * @module sessionFingerprint
9
+ */
10
+ import type { SessionProviderBase } from './providers/types';
11
+ export interface ObservedSessionFingerprintParts {
12
+ sizeBytes: number;
13
+ mtimeMs: number;
14
+ }
15
+ /** Structured size/mtime fingerprint; returns null for inaccessible or synthetic paths. */
16
+ export declare function fileFingerprintParts(sourcePath: string): ObservedSessionFingerprintParts | null;
17
+ /** Size/mtime fingerprint suitable for retry bypass; returns null for synthetic DB locators. */
18
+ export declare function fileFingerprint(sourcePath: string): string | null;
19
+ /** Canonical `${sizeBytes}:${mtimeMs}` form of a fingerprint. */
20
+ export declare function fingerprintString(parts: ObservedSessionFingerprintParts): string;
21
+ /**
22
+ * Fingerprint for a session path, falling back to provider metadata (mtime
23
+ * only) for database-backed sessions whose path is synthetic.
24
+ */
25
+ export declare function sessionFingerprintParts(provider: SessionProviderBase, sessionPath: string): ObservedSessionFingerprintParts | null;
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ /**
3
+ * Size/mtime fingerprints for session sources.
4
+ *
5
+ * Shared by the observed-session collector, the V1 adapter's watch loop, and
6
+ * the usage cache, so "has this session changed?" is answered the same way
7
+ * everywhere without re-reading content.
8
+ *
9
+ * @module sessionFingerprint
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.fileFingerprintParts = fileFingerprintParts;
13
+ exports.fileFingerprint = fileFingerprint;
14
+ exports.fingerprintString = fingerprintString;
15
+ exports.sessionFingerprintParts = sessionFingerprintParts;
16
+ const node_fs_1 = require("node:fs");
17
+ /** Structured size/mtime fingerprint; returns null for inaccessible or synthetic paths. */
18
+ function fileFingerprintParts(sourcePath) {
19
+ try {
20
+ const stat = (0, node_fs_1.statSync)(sourcePath);
21
+ return { sizeBytes: stat.size, mtimeMs: stat.mtimeMs };
22
+ }
23
+ catch {
24
+ return null;
25
+ }
26
+ }
27
+ /** Size/mtime fingerprint suitable for retry bypass; returns null for synthetic DB locators. */
28
+ function fileFingerprint(sourcePath) {
29
+ const parts = fileFingerprintParts(sourcePath);
30
+ return parts ? fingerprintString(parts) : null;
31
+ }
32
+ /** Canonical `${sizeBytes}:${mtimeMs}` form of a fingerprint. */
33
+ function fingerprintString(parts) {
34
+ return `${parts.sizeBytes}:${parts.mtimeMs}`;
35
+ }
36
+ /**
37
+ * Fingerprint for a session path, falling back to provider metadata (mtime
38
+ * only) for database-backed sessions whose path is synthetic.
39
+ */
40
+ function sessionFingerprintParts(provider, sessionPath) {
41
+ const parts = fileFingerprintParts(sessionPath);
42
+ if (parts)
43
+ return parts;
44
+ const metadata = provider.getSessionMetadata?.(sessionPath);
45
+ return metadata ? { sizeBytes: 0, mtimeMs: metadata.mtime.getTime() } : null;
46
+ }
@@ -1,9 +1,15 @@
1
1
  import type { AggregatedMetrics, EventAggregatorOptions } from './aggregation/types';
2
2
  import type { SessionProviderBase } from './providers/types';
3
3
  import type { SessionEvent } from './types/sessionEvent';
4
+ import type { ObservedSessionChangeBatch } from './observedSessionCollector';
4
5
  export interface SessionMonitorOptions extends EventAggregatorOptions {
5
6
  replayOnAttach?: boolean;
6
7
  }
8
+ export interface SessionMonitorSubscribeOptions {
9
+ debounceMs?: number;
10
+ pollIntervalMs?: number;
11
+ onChange?: (batch: ObservedSessionChangeBatch) => void;
12
+ }
7
13
  /**
8
14
  * UI-independent session monitor for library consumers. It owns one provider
9
15
  * reader and the canonical aggregator; hosts decide how often to call `poll()`.
@@ -14,6 +20,7 @@ export declare class SessionMonitor {
14
20
  private reader;
15
21
  private sessionPath;
16
22
  private readonly listeners;
23
+ private readonly subscriptions;
17
24
  private readonly replayOnAttach;
18
25
  constructor(provider: SessionProviderBase, options?: SessionMonitorOptions);
19
26
  attach(sessionPath: string, replay?: boolean): AggregatedMetrics;
@@ -21,6 +28,14 @@ export declare class SessionMonitor {
21
28
  poll(): SessionEvent[];
22
29
  process(event: SessionEvent): void;
23
30
  onEvent(listener: (event: SessionEvent) => void): () => void;
31
+ /**
32
+ * Watches the attached session with debouncing and catch-up polling. Matching
33
+ * fingerprint changes automatically call poll(); parsed events still flow
34
+ * through onEvent.
35
+ */
36
+ subscribe(options?: SessionMonitorSubscribeOptions): {
37
+ dispose(): void;
38
+ };
24
39
  getMetrics(): AggregatedMetrics;
25
40
  getSessionPath(): string | null;
26
41
  reset(): void;
@@ -1,7 +1,42 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.SessionMonitor = void 0;
37
+ const fs = __importStar(require("node:fs"));
4
38
  const EventAggregator_1 = require("./aggregation/EventAggregator");
39
+ const observedSessionCollector_1 = require("./observedSessionCollector");
5
40
  /**
6
41
  * UI-independent session monitor for library consumers. It owns one provider
7
42
  * reader and the canonical aggregator; hosts decide how often to call `poll()`.
@@ -12,6 +47,7 @@ class SessionMonitor {
12
47
  reader = null;
13
48
  sessionPath = null;
14
49
  listeners = new Set();
50
+ subscriptions = new Set();
15
51
  replayOnAttach;
16
52
  constructor(provider, options = {}) {
17
53
  this.provider = provider;
@@ -48,6 +84,110 @@ class SessionMonitor {
48
84
  this.listeners.add(listener);
49
85
  return () => this.listeners.delete(listener);
50
86
  }
87
+ /**
88
+ * Watches the attached session with debouncing and catch-up polling. Matching
89
+ * fingerprint changes automatically call poll(); parsed events still flow
90
+ * through onEvent.
91
+ */
92
+ subscribe(options = {}) {
93
+ const source = {
94
+ providerId: this.provider.id,
95
+ discover: async () => {
96
+ if (!this.sessionPath)
97
+ return [];
98
+ let parts = (0, observedSessionCollector_1.fileFingerprintParts)(this.sessionPath);
99
+ if (!parts) {
100
+ try {
101
+ const metadata = this.provider.getSessionMetadataAsync
102
+ ? await this.provider.getSessionMetadataAsync(this.sessionPath)
103
+ : this.provider.getSessionMetadata?.(this.sessionPath);
104
+ parts = metadata ? { sizeBytes: 0, mtimeMs: metadata.mtime.getTime() } : null;
105
+ }
106
+ catch {
107
+ parts = null;
108
+ }
109
+ }
110
+ if (!parts)
111
+ return [];
112
+ return [
113
+ {
114
+ sessionId: this.provider.getSessionId(this.sessionPath),
115
+ sourceKey: this.sessionPath,
116
+ fingerprintHint: `${parts.sizeBytes}:${parts.mtimeMs}`,
117
+ fingerprintParts: parts,
118
+ },
119
+ ];
120
+ },
121
+ read: () => null,
122
+ subscribe: (listener, sourceOptions) => {
123
+ const watchers = new Set();
124
+ let pollTimer = null;
125
+ let roots;
126
+ try {
127
+ roots = this.provider.getWatchRoots?.() ?? [this.provider.getProjectsBaseDir()];
128
+ }
129
+ catch {
130
+ roots = [];
131
+ }
132
+ for (const root of new Set(roots)) {
133
+ try {
134
+ const watcher = fs.watch(root, { persistent: false, recursive: true }, listener);
135
+ watchers.add(watcher);
136
+ watcher.on('error', () => {
137
+ watchers.delete(watcher);
138
+ try {
139
+ watcher.close();
140
+ }
141
+ catch {
142
+ // Collector catch-up polling remains active.
143
+ }
144
+ });
145
+ }
146
+ catch {
147
+ // Collector catch-up polling remains active.
148
+ }
149
+ }
150
+ const pollIntervalMs = sourceOptions?.pollIntervalMs ?? 0;
151
+ if (pollIntervalMs > 0) {
152
+ pollTimer = setInterval(listener, pollIntervalMs);
153
+ pollTimer.unref?.();
154
+ }
155
+ return {
156
+ dispose: () => {
157
+ for (const watcher of watchers)
158
+ watcher.close();
159
+ watchers.clear();
160
+ if (pollTimer)
161
+ clearInterval(pollTimer);
162
+ },
163
+ };
164
+ },
165
+ };
166
+ const collector = new observedSessionCollector_1.ObservedSessionCollector({ sources: [source] });
167
+ const changeSubscription = collector.subscribe((batch) => {
168
+ if (batch.changes.some((change) => change.reference.sourceKey === this.sessionPath)) {
169
+ this.poll();
170
+ }
171
+ try {
172
+ options.onChange?.(batch);
173
+ }
174
+ catch {
175
+ // Change callbacks are observational.
176
+ }
177
+ }, {
178
+ debounceMs: options.debounceMs,
179
+ pollIntervalMs: options.pollIntervalMs,
180
+ });
181
+ const disposable = {
182
+ dispose: () => {
183
+ changeSubscription.dispose();
184
+ collector.dispose();
185
+ this.subscriptions.delete(disposable);
186
+ },
187
+ };
188
+ this.subscriptions.add(disposable);
189
+ return disposable;
190
+ }
51
191
  getMetrics() {
52
192
  return this.aggregator.getMetrics();
53
193
  }
@@ -59,6 +199,8 @@ class SessionMonitor {
59
199
  this.aggregator.reset();
60
200
  }
61
201
  dispose() {
202
+ for (const subscription of [...this.subscriptions])
203
+ subscription.dispose();
62
204
  this.listeners.clear();
63
205
  this.reader = null;
64
206
  this.provider.dispose();