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.
- package/CHANGELOG.md +48 -0
- package/README.md +198 -56
- package/dist/aggregation/EventAggregator.d.ts +96 -2
- package/dist/aggregation/EventAggregator.js +535 -42
- package/dist/aggregation/snapshot.d.ts +37 -8
- package/dist/aggregation/snapshot.js +31 -9
- package/dist/aggregation/types.d.ts +38 -1
- package/dist/browser.d.ts +9 -1
- package/dist/browser.js +29 -3
- package/dist/context/sessionContext.js +8 -0
- package/dist/esm/aggregation/EventAggregator.js +535 -42
- package/dist/esm/aggregation/snapshot.js +31 -9
- package/dist/esm/browser.js +3 -0
- package/dist/esm/context/sessionContext.js +8 -0
- package/dist/esm/fileContinuity.js +149 -0
- package/dist/esm/formatters/toolSummary.js +4 -1
- package/dist/esm/index.js +7 -2
- package/dist/esm/modelCatalog.js +5 -4
- package/dist/esm/modelContext.js +4 -3
- package/dist/esm/modelInfo.js +4 -3
- package/dist/esm/node.js +3 -1
- package/dist/esm/observedContextWindows.js +2 -1
- package/dist/esm/ownKey.js +26 -0
- package/dist/esm/parsers/codexParser.js +372 -7
- package/dist/esm/parsers/openCodeParser.js +2 -1
- package/dist/esm/parsers/subagentEndState.js +61 -0
- package/dist/esm/parsers/subagentScanner.js +37 -12
- package/dist/esm/parsers/subagentTraceParser.js +103 -37
- package/dist/esm/pricingCatalog.js +3 -2
- package/dist/esm/promptHistory.js +22 -11
- package/dist/esm/providers/claudeCode.js +60 -29
- package/dist/esm/providers/codex.js +235 -201
- package/dist/esm/providers/codexCompressedReader.js +184 -0
- package/dist/esm/providers/codexDatabase.js +47 -2
- package/dist/esm/providers/codexRollouts.js +20 -2
- package/dist/esm/providers/codexSubagents.js +456 -0
- package/dist/esm/providers/compressedRollouts.js +330 -0
- package/dist/esm/providers/factory.js +4 -1
- package/dist/esm/providers/rolloutWalker.js +32 -4
- package/dist/esm/schemas/sessionEvent.js +63 -14
- package/dist/esm/sessionMonitor.js +7 -1
- package/dist/esm/sessionPreviews.js +9 -0
- package/dist/esm/sessionPromptHistory.js +5 -3
- package/dist/esm/subagentActivity.js +125 -0
- package/dist/esm/subagentDisplayState.js +81 -0
- package/dist/esm/subagentSpawn.js +363 -0
- package/dist/esm/testing/codexSubagentFixtures.js +336 -0
- package/dist/esm/toolCallOrigins.js +17 -10
- package/dist/esm/toolCategory.js +6 -2
- package/dist/esm/transcript.js +8 -0
- package/dist/esm/turns/assistantTurn.js +6 -2
- package/dist/esm/usage/claudeUsageDedupe.js +68 -0
- package/dist/esm/usage/usageEvents.js +4 -1
- package/dist/esm/watchers/eventBridge.js +45 -0
- package/dist/esm/watchers/factory.js +5 -3
- package/dist/esm/watchers/jsonlTail.js +82 -48
- package/dist/esm/watchers/jsonlWatcher.js +61 -4
- package/dist/esm/watchers/providerReaderWatcher.js +18 -4
- package/dist/esm/zaiQuota.js +2 -1
- package/dist/fileContinuity.d.ts +95 -0
- package/dist/fileContinuity.js +187 -0
- package/dist/formatters/toolSummary.js +4 -1
- package/dist/index.d.ts +19 -7
- package/dist/index.js +48 -10
- package/dist/modelCatalog.js +5 -4
- package/dist/modelContext.js +4 -3
- package/dist/modelInfo.js +4 -3
- package/dist/node.d.ts +5 -1
- package/dist/node.js +18 -2
- package/dist/observedContextWindows.js +2 -1
- package/dist/ownKey.d.ts +16 -0
- package/dist/ownKey.js +30 -0
- package/dist/parsers/codexParser.d.ts +107 -0
- package/dist/parsers/codexParser.js +373 -7
- package/dist/parsers/openCodeParser.js +2 -1
- package/dist/parsers/subagentEndState.d.ts +20 -0
- package/dist/parsers/subagentEndState.js +65 -0
- package/dist/parsers/subagentScanner.d.ts +19 -6
- package/dist/parsers/subagentScanner.js +37 -12
- package/dist/parsers/subagentTraceParser.d.ts +33 -5
- package/dist/parsers/subagentTraceParser.js +103 -37
- package/dist/pricingCatalog.js +3 -2
- package/dist/promptHistory.d.ts +13 -3
- package/dist/promptHistory.js +22 -11
- package/dist/providers/claudeCode.js +59 -28
- package/dist/providers/codex.d.ts +35 -5
- package/dist/providers/codex.js +232 -198
- package/dist/providers/codexCompressedReader.d.ts +58 -0
- package/dist/providers/codexCompressedReader.js +221 -0
- package/dist/providers/codexDatabase.d.ts +25 -0
- package/dist/providers/codexDatabase.js +48 -2
- package/dist/providers/codexRollouts.d.ts +16 -2
- package/dist/providers/codexRollouts.js +20 -2
- package/dist/providers/codexSubagents.d.ts +66 -0
- package/dist/providers/codexSubagents.js +495 -0
- package/dist/providers/compressedRollouts.d.ts +114 -0
- package/dist/providers/compressedRollouts.js +380 -0
- package/dist/providers/factory.d.ts +5 -0
- package/dist/providers/factory.js +4 -1
- package/dist/providers/rolloutWalker.d.ts +15 -2
- package/dist/providers/rolloutWalker.js +33 -4
- package/dist/providers/types.d.ts +36 -1
- package/dist/schemas/index.d.ts +1 -0
- package/dist/schemas/sessionEvent.d.ts +51 -10
- package/dist/schemas/sessionEvent.js +63 -14
- package/dist/sessionMonitor.d.ts +6 -0
- package/dist/sessionMonitor.js +7 -1
- package/dist/sessionPreviews.js +9 -0
- package/dist/sessionPromptHistory.d.ts +5 -0
- package/dist/sessionPromptHistory.js +5 -36
- package/dist/subagentActivity.d.ts +91 -0
- package/dist/subagentActivity.js +132 -0
- package/dist/subagentDisplayState.d.ts +81 -0
- package/dist/subagentDisplayState.js +86 -0
- package/dist/subagentSpawn.d.ts +175 -0
- package/dist/subagentSpawn.js +385 -0
- package/dist/testing/codexSubagentFixtures.d.ts +48 -0
- package/dist/testing/codexSubagentFixtures.js +344 -0
- package/dist/toolCallOrigins.d.ts +5 -0
- package/dist/toolCallOrigins.js +17 -10
- package/dist/toolCategory.js +6 -2
- package/dist/transcript.js +8 -0
- package/dist/turns/assistantTurn.d.ts +4 -0
- package/dist/turns/assistantTurn.js +6 -2
- package/dist/types/codex.d.ts +71 -2
- package/dist/types/sessionEvent.d.ts +38 -3
- package/dist/usage/claudeUsageDedupe.d.ts +31 -0
- package/dist/usage/claudeUsageDedupe.js +68 -0
- package/dist/usage/usageEvents.d.ts +4 -1
- package/dist/usage/usageEvents.js +4 -1
- package/dist/watchers/eventBridge.js +45 -0
- package/dist/watchers/factory.d.ts +6 -0
- package/dist/watchers/factory.js +5 -3
- package/dist/watchers/jsonlTail.d.ts +27 -4
- package/dist/watchers/jsonlTail.js +84 -48
- package/dist/watchers/jsonlWatcher.d.ts +22 -1
- package/dist/watchers/jsonlWatcher.js +60 -3
- package/dist/watchers/providerReaderWatcher.d.ts +7 -0
- package/dist/watchers/providerReaderWatcher.js +18 -4
- package/dist/watchers/types.d.ts +12 -0
- package/dist/zaiQuota.js +2 -1
- package/package.json +1 -1
|
@@ -49,6 +49,7 @@ const string_decoder_1 = require("string_decoder");
|
|
|
49
49
|
const sessionContext_1 = require("../context/sessionContext");
|
|
50
50
|
const sessionStats_1 = require("../sessionStats");
|
|
51
51
|
const jsonl_1 = require("../parsers/jsonl");
|
|
52
|
+
const fileContinuity_1 = require("../fileContinuity");
|
|
52
53
|
const claudeUsageDedupe_1 = require("../usage/claudeUsageDedupe");
|
|
53
54
|
const diagnostics_1 = require("./diagnostics");
|
|
54
55
|
const directoryListingCache_1 = require("./directoryListingCache");
|
|
@@ -146,7 +147,10 @@ class ClaudeCodeReader {
|
|
|
146
147
|
/** Cursor after the last complete line, safe to persist across restarts. */
|
|
147
148
|
committedPosition = 0;
|
|
148
149
|
events = [];
|
|
149
|
-
|
|
150
|
+
/** Why the last `readNew()` started over from offset 0, if it did. */
|
|
151
|
+
_lastReset = null;
|
|
152
|
+
/** Whether the file is still the one the positions refer to. */
|
|
153
|
+
continuity = new fileContinuity_1.FileContinuity();
|
|
150
154
|
decoder = new string_decoder_1.StringDecoder('utf8');
|
|
151
155
|
/** Split lines of one response repeat its usage; count each response once. */
|
|
152
156
|
usageDeduper;
|
|
@@ -155,7 +159,8 @@ class ClaudeCodeReader {
|
|
|
155
159
|
this.usageDeduper = usageDeduper ?? new claudeUsageDedupe_1.ClaudeUsageDeduper();
|
|
156
160
|
this.parser = new jsonl_1.JsonlParser({
|
|
157
161
|
onEvent: (raw) => {
|
|
158
|
-
|
|
162
|
+
// Mid-turn task notifications finish background subagents.
|
|
163
|
+
for (const event of (0, sessionEvent_1.extractSessionEvents)(raw, { includeTaskNotifications: true })) {
|
|
159
164
|
this.events.push(this.usageDeduper.apply((0, claudeUsageDedupe_1.normalizeClaudeUsage)(event)));
|
|
160
165
|
}
|
|
161
166
|
},
|
|
@@ -166,37 +171,28 @@ class ClaudeCodeReader {
|
|
|
166
171
|
}
|
|
167
172
|
readNew() {
|
|
168
173
|
this.events = [];
|
|
169
|
-
this.
|
|
174
|
+
this._lastReset = null;
|
|
175
|
+
let fd = null;
|
|
170
176
|
try {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
const stats = fs.
|
|
177
|
+
// Open first and stat the descriptor: the size and identity checked
|
|
178
|
+
// are those of the file actually read, even if the path is replaced.
|
|
179
|
+
fd = fs.openSync(this.sessionPath, 'r');
|
|
180
|
+
const stats = fs.fstatSync(fd);
|
|
181
|
+
const reason = this.continuity.check(fd, stats, this.filePosition, this.committedPosition);
|
|
182
|
+
// Truncated, rewritten, or replaced: what was read no longer describes
|
|
183
|
+
// the file, so start over from its beginning.
|
|
184
|
+
if (reason !== null)
|
|
185
|
+
this.restart(reason);
|
|
186
|
+
this.continuity.adopt(stats);
|
|
175
187
|
const currentSize = stats.size;
|
|
176
|
-
// Handle truncation
|
|
177
|
-
if (currentSize < this.filePosition) {
|
|
178
|
-
this._wasTruncated = true;
|
|
179
|
-
this.filePosition = 0;
|
|
180
|
-
this.committedPosition = 0;
|
|
181
|
-
this.parser.reset();
|
|
182
|
-
this.decoder = new string_decoder_1.StringDecoder('utf8');
|
|
183
|
-
this.usageDeduper.reset();
|
|
184
|
-
}
|
|
185
188
|
// No new content
|
|
186
189
|
if (currentSize <= this.filePosition) {
|
|
187
|
-
return
|
|
190
|
+
return this.events;
|
|
188
191
|
}
|
|
189
192
|
// Read new bytes from last position
|
|
190
|
-
const fd = fs.openSync(this.sessionPath, 'r');
|
|
191
193
|
const bufferSize = currentSize - this.filePosition;
|
|
192
194
|
const buffer = Buffer.alloc(bufferSize);
|
|
193
|
-
|
|
194
|
-
try {
|
|
195
|
-
bytesRead = fs.readSync(fd, buffer, 0, bufferSize, this.filePosition);
|
|
196
|
-
}
|
|
197
|
-
finally {
|
|
198
|
-
fs.closeSync(fd);
|
|
199
|
-
}
|
|
195
|
+
const bytesRead = fs.readSync(fd, buffer, 0, bufferSize, this.filePosition);
|
|
200
196
|
const bytes = buffer.subarray(0, bytesRead);
|
|
201
197
|
const newline = bytes.lastIndexOf(0x0a);
|
|
202
198
|
if (newline >= 0)
|
|
@@ -206,10 +202,31 @@ class ClaudeCodeReader {
|
|
|
206
202
|
this.filePosition += bytesRead;
|
|
207
203
|
}
|
|
208
204
|
catch (error) {
|
|
209
|
-
|
|
205
|
+
if (error?.code !== 'ENOENT') {
|
|
206
|
+
console.error(`ClaudeCodeReader: error reading ${this.sessionPath}: ${error}`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
finally {
|
|
210
|
+
if (fd !== null) {
|
|
211
|
+
try {
|
|
212
|
+
fs.closeSync(fd);
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
// Ignore close errors.
|
|
216
|
+
}
|
|
217
|
+
}
|
|
210
218
|
}
|
|
211
219
|
return this.events;
|
|
212
220
|
}
|
|
221
|
+
/** Starts over from offset 0 of a file that was truncated, rewritten, or replaced. */
|
|
222
|
+
restart(reason) {
|
|
223
|
+
this._lastReset = { reason, previousPosition: this.committedPosition };
|
|
224
|
+
this.filePosition = 0;
|
|
225
|
+
this.committedPosition = 0;
|
|
226
|
+
this.parser.reset();
|
|
227
|
+
this.decoder = new string_decoder_1.StringDecoder('utf8');
|
|
228
|
+
this.usageDeduper.reset();
|
|
229
|
+
}
|
|
213
230
|
readAll() {
|
|
214
231
|
this.reset();
|
|
215
232
|
return this.readNew();
|
|
@@ -220,7 +237,8 @@ class ClaudeCodeReader {
|
|
|
220
237
|
this.parser.reset();
|
|
221
238
|
this.decoder = new string_decoder_1.StringDecoder('utf8');
|
|
222
239
|
this.usageDeduper.reset();
|
|
223
|
-
this.
|
|
240
|
+
this._lastReset = null;
|
|
241
|
+
this.continuity.forget();
|
|
224
242
|
}
|
|
225
243
|
exists() {
|
|
226
244
|
return fs.existsSync(this.sessionPath);
|
|
@@ -240,9 +258,22 @@ class ClaudeCodeReader {
|
|
|
240
258
|
this.committedPosition = position;
|
|
241
259
|
this.parser.reset();
|
|
242
260
|
this.decoder = new string_decoder_1.StringDecoder('utf8');
|
|
261
|
+
// The position comes from elsewhere (a snapshot): adopt the file the next
|
|
262
|
+
// read finds rather than compare it with one read before.
|
|
263
|
+
this.continuity.forget();
|
|
243
264
|
}
|
|
244
265
|
wasTruncated() {
|
|
245
|
-
return this.
|
|
266
|
+
return this._lastReset !== null;
|
|
267
|
+
}
|
|
268
|
+
lastReset() {
|
|
269
|
+
return this._lastReset ? { ...this._lastReset } : null;
|
|
270
|
+
}
|
|
271
|
+
/** The usage deduper's recent message ids, so a resumed reader does not recount a split response. */
|
|
272
|
+
getResumeState() {
|
|
273
|
+
return this.usageDeduper.exportState();
|
|
274
|
+
}
|
|
275
|
+
restoreResumeState(state) {
|
|
276
|
+
return this.usageDeduper.importState(state);
|
|
246
277
|
}
|
|
247
278
|
}
|
|
248
279
|
/**
|
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
* Implements SessionProviderBase for monitoring Codex CLI sessions.
|
|
5
5
|
* Codex stores sessions as JSONL rollout files in:
|
|
6
6
|
* ~/.codex/sessions/YYYY/MM/DD/rollout-<timestamp>-<uuid>.jsonl
|
|
7
|
-
* with an optional SQLite index at ~/.codex/state.sqlite.
|
|
7
|
+
* with an optional SQLite index at ~/.codex/state.sqlite. Older rollouts are
|
|
8
|
+
* compressed in place to `….jsonl.zst`; those are read only with the
|
|
9
|
+
* `includeCompressedRollouts` option (see `providers/compressedRollouts`).
|
|
8
10
|
*
|
|
9
11
|
* Ported from sidekick-vscode/src/services/providers/CodexSessionProvider.ts
|
|
10
12
|
*/
|
|
@@ -15,6 +17,19 @@ import type { SubagentStats, TokenUsage } from '../types/sessionEvent';
|
|
|
15
17
|
import type { CodexRateLimits } from '../types/codex';
|
|
16
18
|
export { findCodexRolloutFile };
|
|
17
19
|
export type { FindCodexRolloutFileOptions } from './codexRollouts';
|
|
20
|
+
/** Options for {@link CodexProvider}; every field is optional and additive. */
|
|
21
|
+
export interface CodexProviderOptions extends SessionProviderOptions {
|
|
22
|
+
/**
|
|
23
|
+
* Also discover and read compressed rollouts (`rollout-….jsonl.zst`,
|
|
24
|
+
* which Codex writes for older sessions). Listings, session lookups,
|
|
25
|
+
* labels, `createReader()` (a whole-file reader; live tailing stays
|
|
26
|
+
* `.jsonl`-only), search, and subagent stats then include them. Reading
|
|
27
|
+
* needs `zlib.zstdDecompressSync` (Node 22.15+); without it they are
|
|
28
|
+
* skipped and reported once through `onDiagnostic`. Default false, so
|
|
29
|
+
* session and history counts are unchanged.
|
|
30
|
+
*/
|
|
31
|
+
includeCompressedRollouts?: boolean;
|
|
32
|
+
}
|
|
18
33
|
/**
|
|
19
34
|
* Session provider for Codex CLI.
|
|
20
35
|
*
|
|
@@ -33,7 +48,17 @@ export declare class CodexProvider implements SessionProviderBase {
|
|
|
33
48
|
private lastTokenUsageData;
|
|
34
49
|
/** Dated rollout-directory listings reused across async enumerations. */
|
|
35
50
|
private readonly directoryCache;
|
|
36
|
-
|
|
51
|
+
/** See {@link CodexProviderOptions.includeCompressedRollouts}. */
|
|
52
|
+
private readonly compressedRequested;
|
|
53
|
+
private readonly onDiagnostic;
|
|
54
|
+
constructor(options?: CodexProviderOptions);
|
|
55
|
+
/**
|
|
56
|
+
* Whether compressed rollouts are discovered and read: requested, and the
|
|
57
|
+
* runtime can decompress them (otherwise reported once, on first use).
|
|
58
|
+
*/
|
|
59
|
+
private get includeCompressed();
|
|
60
|
+
/** A stored rollout path as it exists now (its `.zst` when compressed and enabled). */
|
|
61
|
+
private resolveRollout;
|
|
37
62
|
/** Lazy-initialize database connection. */
|
|
38
63
|
private ensureDb;
|
|
39
64
|
private ensureDbAsync;
|
|
@@ -70,11 +95,16 @@ export declare class CodexProvider implements SessionProviderBase {
|
|
|
70
95
|
extractSessionLabel(sessionPath: string): string | null;
|
|
71
96
|
extractSessionLabelsAsync(sessionPaths: readonly string[]): Promise<Map<string, string | null>>;
|
|
72
97
|
createReader(sessionPath: string): SessionReader;
|
|
73
|
-
scanSubagents(_sessionDir: string, sessionId: string): SubagentStats[];
|
|
74
98
|
/**
|
|
75
|
-
*
|
|
99
|
+
* Every subagent below the session, any depth: spawned threads (the
|
|
100
|
+
* database's `threads.source`, else the newest rollouts' session_meta)
|
|
101
|
+
* and, on older schemas, forks (`forked_from_id`). Each carries its
|
|
102
|
+
* rollout (`filePath`), the parent's spawn call (`spawnToolUseId`),
|
|
103
|
+
* `agentNickname`, `agentPath`, `parentAgentId`, and `depth`; tool calls
|
|
104
|
+
* and tokens come from the child's own records, not the parent history a
|
|
105
|
+
* forked child embeds.
|
|
76
106
|
*/
|
|
77
|
-
|
|
107
|
+
scanSubagents(_sessionDir: string, sessionId: string): SubagentStats[];
|
|
78
108
|
searchInSession(sessionPath: string, query: string, maxResults: number): SearchHit[];
|
|
79
109
|
getProjectsBaseDir(): string;
|
|
80
110
|
getWatchRoots(): string[];
|