sidekick-shared 0.29.0 → 0.30.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 (142) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +198 -56
  3. package/dist/aggregation/EventAggregator.d.ts +96 -2
  4. package/dist/aggregation/EventAggregator.js +535 -42
  5. package/dist/aggregation/snapshot.d.ts +37 -8
  6. package/dist/aggregation/snapshot.js +31 -9
  7. package/dist/aggregation/types.d.ts +38 -1
  8. package/dist/browser.d.ts +9 -1
  9. package/dist/browser.js +29 -3
  10. package/dist/context/sessionContext.js +8 -0
  11. package/dist/esm/aggregation/EventAggregator.js +535 -42
  12. package/dist/esm/aggregation/snapshot.js +31 -9
  13. package/dist/esm/browser.js +3 -0
  14. package/dist/esm/context/sessionContext.js +8 -0
  15. package/dist/esm/fileContinuity.js +149 -0
  16. package/dist/esm/formatters/toolSummary.js +4 -1
  17. package/dist/esm/index.js +7 -2
  18. package/dist/esm/modelCatalog.js +5 -4
  19. package/dist/esm/modelContext.js +4 -3
  20. package/dist/esm/modelInfo.js +4 -3
  21. package/dist/esm/node.js +3 -1
  22. package/dist/esm/observedContextWindows.js +2 -1
  23. package/dist/esm/ownKey.js +26 -0
  24. package/dist/esm/parsers/codexParser.js +372 -7
  25. package/dist/esm/parsers/openCodeParser.js +2 -1
  26. package/dist/esm/parsers/subagentEndState.js +61 -0
  27. package/dist/esm/parsers/subagentScanner.js +37 -12
  28. package/dist/esm/parsers/subagentTraceParser.js +103 -37
  29. package/dist/esm/pricingCatalog.js +3 -2
  30. package/dist/esm/promptHistory.js +22 -11
  31. package/dist/esm/providers/claudeCode.js +60 -29
  32. package/dist/esm/providers/codex.js +235 -201
  33. package/dist/esm/providers/codexCompressedReader.js +184 -0
  34. package/dist/esm/providers/codexDatabase.js +47 -2
  35. package/dist/esm/providers/codexRollouts.js +20 -2
  36. package/dist/esm/providers/codexSubagents.js +456 -0
  37. package/dist/esm/providers/compressedRollouts.js +330 -0
  38. package/dist/esm/providers/factory.js +4 -1
  39. package/dist/esm/providers/rolloutWalker.js +32 -4
  40. package/dist/esm/schemas/sessionEvent.js +63 -14
  41. package/dist/esm/sessionMonitor.js +7 -1
  42. package/dist/esm/sessionPreviews.js +9 -0
  43. package/dist/esm/sessionPromptHistory.js +5 -3
  44. package/dist/esm/subagentActivity.js +125 -0
  45. package/dist/esm/subagentDisplayState.js +81 -0
  46. package/dist/esm/subagentSpawn.js +363 -0
  47. package/dist/esm/testing/codexSubagentFixtures.js +336 -0
  48. package/dist/esm/toolCallOrigins.js +17 -10
  49. package/dist/esm/toolCategory.js +6 -2
  50. package/dist/esm/transcript.js +8 -0
  51. package/dist/esm/turns/assistantTurn.js +6 -2
  52. package/dist/esm/usage/claudeUsageDedupe.js +68 -0
  53. package/dist/esm/usage/usageEvents.js +4 -1
  54. package/dist/esm/watchers/eventBridge.js +45 -0
  55. package/dist/esm/watchers/factory.js +5 -3
  56. package/dist/esm/watchers/jsonlTail.js +82 -48
  57. package/dist/esm/watchers/jsonlWatcher.js +61 -4
  58. package/dist/esm/watchers/providerReaderWatcher.js +18 -4
  59. package/dist/esm/zaiQuota.js +2 -1
  60. package/dist/fileContinuity.d.ts +95 -0
  61. package/dist/fileContinuity.js +187 -0
  62. package/dist/formatters/toolSummary.js +4 -1
  63. package/dist/index.d.ts +19 -7
  64. package/dist/index.js +48 -10
  65. package/dist/modelCatalog.js +5 -4
  66. package/dist/modelContext.js +4 -3
  67. package/dist/modelInfo.js +4 -3
  68. package/dist/node.d.ts +5 -1
  69. package/dist/node.js +18 -2
  70. package/dist/observedContextWindows.js +2 -1
  71. package/dist/ownKey.d.ts +16 -0
  72. package/dist/ownKey.js +30 -0
  73. package/dist/parsers/codexParser.d.ts +107 -0
  74. package/dist/parsers/codexParser.js +373 -7
  75. package/dist/parsers/openCodeParser.js +2 -1
  76. package/dist/parsers/subagentEndState.d.ts +20 -0
  77. package/dist/parsers/subagentEndState.js +65 -0
  78. package/dist/parsers/subagentScanner.d.ts +19 -6
  79. package/dist/parsers/subagentScanner.js +37 -12
  80. package/dist/parsers/subagentTraceParser.d.ts +33 -5
  81. package/dist/parsers/subagentTraceParser.js +103 -37
  82. package/dist/pricingCatalog.js +3 -2
  83. package/dist/promptHistory.d.ts +13 -3
  84. package/dist/promptHistory.js +22 -11
  85. package/dist/providers/claudeCode.js +59 -28
  86. package/dist/providers/codex.d.ts +35 -5
  87. package/dist/providers/codex.js +232 -198
  88. package/dist/providers/codexCompressedReader.d.ts +58 -0
  89. package/dist/providers/codexCompressedReader.js +221 -0
  90. package/dist/providers/codexDatabase.d.ts +25 -0
  91. package/dist/providers/codexDatabase.js +48 -2
  92. package/dist/providers/codexRollouts.d.ts +16 -2
  93. package/dist/providers/codexRollouts.js +20 -2
  94. package/dist/providers/codexSubagents.d.ts +66 -0
  95. package/dist/providers/codexSubagents.js +495 -0
  96. package/dist/providers/compressedRollouts.d.ts +114 -0
  97. package/dist/providers/compressedRollouts.js +380 -0
  98. package/dist/providers/factory.d.ts +5 -0
  99. package/dist/providers/factory.js +4 -1
  100. package/dist/providers/rolloutWalker.d.ts +15 -2
  101. package/dist/providers/rolloutWalker.js +33 -4
  102. package/dist/providers/types.d.ts +36 -1
  103. package/dist/schemas/index.d.ts +1 -0
  104. package/dist/schemas/sessionEvent.d.ts +51 -10
  105. package/dist/schemas/sessionEvent.js +63 -14
  106. package/dist/sessionMonitor.d.ts +6 -0
  107. package/dist/sessionMonitor.js +7 -1
  108. package/dist/sessionPreviews.js +9 -0
  109. package/dist/sessionPromptHistory.d.ts +5 -0
  110. package/dist/sessionPromptHistory.js +5 -36
  111. package/dist/subagentActivity.d.ts +91 -0
  112. package/dist/subagentActivity.js +132 -0
  113. package/dist/subagentDisplayState.d.ts +81 -0
  114. package/dist/subagentDisplayState.js +86 -0
  115. package/dist/subagentSpawn.d.ts +175 -0
  116. package/dist/subagentSpawn.js +385 -0
  117. package/dist/testing/codexSubagentFixtures.d.ts +48 -0
  118. package/dist/testing/codexSubagentFixtures.js +344 -0
  119. package/dist/toolCallOrigins.d.ts +5 -0
  120. package/dist/toolCallOrigins.js +17 -10
  121. package/dist/toolCategory.js +6 -2
  122. package/dist/transcript.js +8 -0
  123. package/dist/turns/assistantTurn.d.ts +4 -0
  124. package/dist/turns/assistantTurn.js +6 -2
  125. package/dist/types/codex.d.ts +71 -2
  126. package/dist/types/sessionEvent.d.ts +38 -3
  127. package/dist/usage/claudeUsageDedupe.d.ts +31 -0
  128. package/dist/usage/claudeUsageDedupe.js +68 -0
  129. package/dist/usage/usageEvents.d.ts +4 -1
  130. package/dist/usage/usageEvents.js +4 -1
  131. package/dist/watchers/eventBridge.js +45 -0
  132. package/dist/watchers/factory.d.ts +6 -0
  133. package/dist/watchers/factory.js +5 -3
  134. package/dist/watchers/jsonlTail.d.ts +27 -4
  135. package/dist/watchers/jsonlTail.js +84 -48
  136. package/dist/watchers/jsonlWatcher.d.ts +22 -1
  137. package/dist/watchers/jsonlWatcher.js +60 -3
  138. package/dist/watchers/providerReaderWatcher.d.ts +7 -0
  139. package/dist/watchers/providerReaderWatcher.js +18 -4
  140. package/dist/watchers/types.d.ts +12 -0
  141. package/dist/zaiQuota.js +2 -1
  142. package/package.json +1 -1
@@ -9,6 +9,7 @@ const jsonlTail_1 = require("./jsonlTail");
9
9
  const codexParser_1 = require("../parsers/codexParser");
10
10
  const toolSummary_1 = require("../formatters/toolSummary");
11
11
  const claudeUsageDedupe_1 = require("../usage/claudeUsageDedupe");
12
+ const subagentSpawn_1 = require("../subagentSpawn");
12
13
  // ── Normalizers ──
13
14
  /**
14
15
  * Split lines of one Claude response repeat its usage; run the raw usage
@@ -24,7 +25,7 @@ function dedupedClaudeUsage(raw, deduper) {
24
25
  }));
25
26
  return { usage: event.message?.usage, usageKind: event.message?.usageKind };
26
27
  }
27
- function normalizeClaudeCodeEvent(raw, deduper) {
28
+ function normalizeClaudeCodeEvent(raw, deduper, includeTaskNotifications) {
28
29
  const events = [];
29
30
  const ts = raw.timestamp || new Date().toISOString();
30
31
  const permissionMode = raw.permissionMode;
@@ -136,6 +137,29 @@ function normalizeClaudeCodeEvent(raw, deduper) {
136
137
  raw,
137
138
  });
138
139
  }
140
+ else if (includeTaskNotifications) {
141
+ // A task notification that landed mid-turn is only an attachment line.
142
+ const prompt = (0, subagentSpawn_1.taskNotificationPromptFromAttachment)(raw);
143
+ const notification = (0, subagentSpawn_1.parseTaskNotification)(prompt);
144
+ const stopped = notification ? null : (0, subagentSpawn_1.parseAgentsStoppedNotice)(prompt);
145
+ const taskStatus = (0, subagentSpawn_1.taskStatusFromAttachment)(raw);
146
+ let summary = null;
147
+ if (notification) {
148
+ summary = notification.summary ?? `Background task ${notification.status ?? 'finished'}`;
149
+ }
150
+ else if (stopped) {
151
+ summary = (0, subagentSpawn_1.describeAgentsStopped)(stopped);
152
+ }
153
+ else if (taskStatus && (0, subagentSpawn_1.isFinalTaskStatus)(taskStatus.status)) {
154
+ summary = (0, subagentSpawn_1.describeTaskStatus)(taskStatus);
155
+ }
156
+ else if ((0, subagentSpawn_1.isAgentsKilledSystemEvent)(raw)) {
157
+ summary = (0, subagentSpawn_1.describeAgentsStopped)(null);
158
+ }
159
+ if (summary !== null) {
160
+ events.push({ providerId: 'claude-code', type: 'system', timestamp: ts, summary, raw });
161
+ }
162
+ }
139
163
  }
140
164
  // Propagate permission mode to all generated events
141
165
  if (permissionMode) {
@@ -207,16 +231,18 @@ class JsonlSessionWatcher {
207
231
  providerId;
208
232
  sessionPath;
209
233
  callbacks;
234
+ options;
210
235
  tail;
211
236
  startOffset;
212
237
  codexInPlanMode = false;
213
238
  claudeUsageDeduper = new claudeUsageDedupe_1.ClaudeUsageDeduper();
214
239
  /** Last Codex cumulative usage seen; repeated `token_count` events carry the same value. */
215
240
  codexPrevTotal;
216
- constructor(providerId, sessionPath, callbacks) {
241
+ constructor(providerId, sessionPath, callbacks, options = {}) {
217
242
  this.providerId = providerId;
218
243
  this.sessionPath = sessionPath;
219
244
  this.callbacks = callbacks;
245
+ this.options = options;
220
246
  }
221
247
  get isActive() {
222
248
  return this.tail?.isActive ?? false;
@@ -230,6 +256,37 @@ class JsonlSessionWatcher {
230
256
  getPosition() {
231
257
  return this.tail?.getOffset() ?? this.startOffset ?? 0;
232
258
  }
259
+ /**
260
+ * Parse state for {@link getPosition}: for Claude Code, the usage deduper's
261
+ * recent message ids (a `ClaudeUsageDedupeState`); for Codex, the previous
262
+ * cumulative token total and plan mode.
263
+ */
264
+ getResumeState() {
265
+ if (this.providerId === 'codex') {
266
+ return {
267
+ version: 1,
268
+ prevTotalUsage: this.codexPrevTotal ? { ...this.codexPrevTotal } : null,
269
+ inPlanMode: this.codexInPlanMode,
270
+ };
271
+ }
272
+ return this.claudeUsageDeduper.exportState();
273
+ }
274
+ /** Restores state from {@link getResumeState} after `seekTo()` and before `start()`. */
275
+ restoreResumeState(state) {
276
+ if (this.providerId !== 'codex')
277
+ return this.claudeUsageDeduper.importState(state);
278
+ if (!state || typeof state !== 'object')
279
+ return false;
280
+ const { version, prevTotalUsage, inPlanMode } = state;
281
+ if (version !== 1 || typeof inPlanMode !== 'boolean')
282
+ return false;
283
+ const total = (0, codexParser_1.codexTokenUsageFrom)(prevTotalUsage);
284
+ if (total === undefined)
285
+ return false;
286
+ this.codexPrevTotal = total ?? undefined;
287
+ this.codexInPlanMode = inPlanMode;
288
+ return true;
289
+ }
233
290
  start(replay) {
234
291
  if (this.isActive)
235
292
  return;
@@ -261,7 +318,7 @@ class JsonlSessionWatcher {
261
318
  // JsonlParser parses any JSON object. Cast to Record for codex normalizer.
262
319
  const followEvents = this.providerId === 'codex'
263
320
  ? this.normalizeCodexEvent(event)
264
- : normalizeClaudeCodeEvent(event, this.claudeUsageDeduper);
321
+ : normalizeClaudeCodeEvent(event, this.claudeUsageDeduper, this.options.includeTaskNotifications === true);
265
322
  for (const fe of followEvents) {
266
323
  this.callbacks.onEvent(fe);
267
324
  }
@@ -19,6 +19,13 @@ export declare class ProviderReaderSessionWatcher implements SessionWatcher {
19
19
  get isActive(): boolean;
20
20
  seekTo(position: number): void;
21
21
  getPosition(): number;
22
+ /** The reader's resume state, if it keeps any. */
23
+ getResumeState(): unknown;
24
+ /**
25
+ * Restores the reader's resume state after `seekTo()`. A reader that keeps
26
+ * none accepts only `undefined`.
27
+ */
28
+ restoreResumeState(state: unknown): boolean;
22
29
  start(replay: boolean): void;
23
30
  stop(): void;
24
31
  private seekToEnd;
@@ -68,6 +68,19 @@ class ProviderReaderSessionWatcher {
68
68
  getPosition() {
69
69
  return this.reader.getPosition();
70
70
  }
71
+ /** The reader's resume state, if it keeps any. */
72
+ getResumeState() {
73
+ return this.reader.getResumeState?.();
74
+ }
75
+ /**
76
+ * Restores the reader's resume state after `seekTo()`. A reader that keeps
77
+ * none accepts only `undefined`.
78
+ */
79
+ restoreResumeState(state) {
80
+ if (!this.reader.restoreResumeState)
81
+ return state === undefined;
82
+ return this.reader.restoreResumeState(state);
83
+ }
71
84
  start(replay) {
72
85
  if (this._isActive)
73
86
  return;
@@ -135,11 +148,12 @@ class ProviderReaderSessionWatcher {
135
148
  if (!this._isActive)
136
149
  return;
137
150
  try {
138
- if (this.reader.wasTruncated()) {
139
- this.reader.reset();
140
- this.callbacks.onReset?.();
141
- }
142
151
  const events = this.reader.readNew();
152
+ // The reader started over (truncated, rewritten, or replaced file):
153
+ // these events are the session from the beginning, so consumers must
154
+ // drop what they built before receiving them.
155
+ if (this.reader.wasTruncated())
156
+ this.callbacks.onReset?.();
143
157
  for (const event of events) {
144
158
  for (const followEvent of (0, eventBridge_1.toFollowEvents)(event, this.provider.id)) {
145
159
  this.callbacks.onEvent(followEvent);
@@ -70,6 +70,18 @@ export interface SessionWatcher {
70
70
  seekTo?(position: number): void;
71
71
  /** Get current reader position (byte offset or timestamp). */
72
72
  getPosition?(): number;
73
+ /**
74
+ * Parse state to persist with `getPosition()` so a later watcher can
75
+ * resume there without recounting (see `SessionReader.getResumeState`).
76
+ * `undefined` when the watcher keeps none.
77
+ */
78
+ getResumeState?(): unknown;
79
+ /**
80
+ * Restores state from `getResumeState()` right after `seekTo()` and before
81
+ * `start()`. Returns false, changing nothing, when `state` is missing or
82
+ * not valid; replay from the start instead.
83
+ */
84
+ restoreResumeState?(state: unknown): boolean;
73
85
  }
74
86
  export interface CreateWatcherOptions {
75
87
  providerId: ProviderId;
package/dist/zaiQuota.js CHANGED
@@ -10,6 +10,7 @@ exports.parseZaiQuotaError = parseZaiQuotaError;
10
10
  exports.extractNextFlushTime = extractNextFlushTime;
11
11
  exports.makeUnavailableZaiQuotaState = makeUnavailableZaiQuotaState;
12
12
  exports.rowsToZaiTurnsAndErrors = rowsToZaiTurnsAndErrors;
13
+ const ownKey_1 = require("./ownKey");
13
14
  // ── Tier budgets ──
14
15
  /**
15
16
  * Published z.ai coding-plan prompt budgets.
@@ -227,7 +228,7 @@ function parseZaiQuotaError(error) {
227
228
  if (!error)
228
229
  return null;
229
230
  const code = String(error.code ?? '');
230
- const kind = ZAI_ERROR_CODES[code];
231
+ const kind = (0, ownKey_1.ownValue)(ZAI_ERROR_CODES, code);
231
232
  if (!kind)
232
233
  return null;
233
234
  const message = error.message ?? '';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sidekick-shared",
3
- "version": "0.29.0",
3
+ "version": "0.30.0",
4
4
  "description": "Shared data access layer for Sidekick — readers, types, providers, credentials, quota",
5
5
  "keywords": [
6
6
  "claude-code",