sidekick-shared 0.29.1 → 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 +26 -0
- package/README.md +171 -60
- package/dist/aggregation/EventAggregator.d.ts +79 -4
- package/dist/aggregation/EventAggregator.js +391 -37
- package/dist/aggregation/types.d.ts +27 -3
- package/dist/browser.d.ts +7 -3
- package/dist/browser.js +23 -3
- package/dist/context/sessionContext.js +5 -1
- package/dist/esm/aggregation/EventAggregator.js +392 -38
- package/dist/esm/browser.js +3 -1
- package/dist/esm/context/sessionContext.js +6 -2
- package/dist/esm/fileContinuity.js +149 -0
- package/dist/esm/index.js +5 -2
- package/dist/esm/node.js +2 -0
- package/dist/esm/parsers/codexParser.js +192 -3
- package/dist/esm/parsers/subagentEndState.js +61 -0
- package/dist/esm/parsers/subagentScanner.js +4 -0
- package/dist/esm/parsers/subagentTraceParser.js +6 -0
- package/dist/esm/promptHistory.js +22 -11
- package/dist/esm/providers/claudeCode.js +50 -27
- package/dist/esm/providers/codex.js +153 -163
- 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 +32 -4
- 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 +206 -6
- 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 +6 -2
- package/dist/esm/turns/assistantTurn.js +6 -3
- package/dist/esm/usage/usageEvents.js +4 -1
- package/dist/esm/watchers/eventBridge.js +31 -1
- package/dist/esm/watchers/jsonlTail.js +11 -42
- package/dist/esm/watchers/jsonlWatcher.js +19 -9
- package/dist/esm/watchers/providerReaderWatcher.js +5 -4
- package/dist/fileContinuity.d.ts +95 -0
- package/dist/fileContinuity.js +187 -0
- package/dist/index.d.ts +14 -7
- package/dist/index.js +39 -10
- package/dist/node.d.ts +4 -0
- package/dist/node.js +16 -2
- package/dist/parsers/codexParser.d.ts +44 -0
- package/dist/parsers/codexParser.js +192 -3
- package/dist/parsers/subagentEndState.d.ts +20 -0
- package/dist/parsers/subagentEndState.js +65 -0
- package/dist/parsers/subagentScanner.js +4 -0
- package/dist/parsers/subagentTraceParser.d.ts +8 -0
- package/dist/parsers/subagentTraceParser.js +6 -0
- package/dist/promptHistory.d.ts +13 -3
- package/dist/promptHistory.js +22 -11
- package/dist/providers/claudeCode.js +50 -27
- package/dist/providers/codex.d.ts +35 -5
- package/dist/providers/codex.js +150 -160
- 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 +22 -1
- package/dist/schemas/sessionEvent.d.ts +26 -2
- package/dist/schemas/sessionEvent.js +31 -3
- 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 +100 -5
- package/dist/subagentSpawn.js +218 -7
- 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 +5 -1
- package/dist/turns/assistantTurn.d.ts +4 -1
- package/dist/turns/assistantTurn.js +5 -2
- package/dist/types/codex.d.ts +71 -2
- package/dist/types/sessionEvent.d.ts +38 -3
- package/dist/usage/usageEvents.d.ts +4 -1
- package/dist/usage/usageEvents.js +4 -1
- package/dist/watchers/eventBridge.js +30 -0
- package/dist/watchers/jsonlTail.js +11 -42
- package/dist/watchers/jsonlWatcher.d.ts +5 -1
- package/dist/watchers/jsonlWatcher.js +18 -8
- package/dist/watchers/providerReaderWatcher.js +5 -4
- package/package.json +1 -1
package/dist/promptHistory.js
CHANGED
|
@@ -69,11 +69,11 @@ exports.resolveRoots = resolveRoots;
|
|
|
69
69
|
exports.listCandidates = listCandidates;
|
|
70
70
|
exports.scanFile = scanFile;
|
|
71
71
|
const crypto_1 = require("crypto");
|
|
72
|
-
const fs = __importStar(require("fs"));
|
|
73
72
|
const path = __importStar(require("path"));
|
|
74
73
|
const humanPrompt_1 = require("./humanPrompt");
|
|
75
74
|
const claudeListing_1 = require("./providers/claudeListing");
|
|
76
75
|
const codexRollouts_1 = require("./providers/codexRollouts");
|
|
76
|
+
const compressedRollouts_1 = require("./providers/compressedRollouts");
|
|
77
77
|
const directoryListingCache_1 = require("./providers/directoryListingCache");
|
|
78
78
|
const workspaceRoots_1 = require("./workspaceRoots");
|
|
79
79
|
const fileHead_1 = require("./fileHead");
|
|
@@ -150,7 +150,9 @@ async function collectPromptHistory(options) {
|
|
|
150
150
|
return finish();
|
|
151
151
|
const sinceMs = options.since ? options.since.getTime() : null;
|
|
152
152
|
const providers = options.providers ?? ALL_PROVIDERS;
|
|
153
|
-
const candidates = rotate(await listCandidates(providers, listingRoots, sinceMs
|
|
153
|
+
const candidates = rotate(await listCandidates(providers, listingRoots, sinceMs, {
|
|
154
|
+
includeCompressedRollouts: options.includeCompressedRollouts,
|
|
155
|
+
}), previousNext);
|
|
154
156
|
const moved = movedSessionKeys(previous, candidates);
|
|
155
157
|
const context = {
|
|
156
158
|
roots,
|
|
@@ -186,7 +188,8 @@ async function collectPromptHistory(options) {
|
|
|
186
188
|
}
|
|
187
189
|
let stat;
|
|
188
190
|
try {
|
|
189
|
-
|
|
191
|
+
// A compressed rollout's size is its decompressed content's.
|
|
192
|
+
stat = await (0, compressedRollouts_1.statRolloutContent)(candidate.filePath);
|
|
190
193
|
}
|
|
191
194
|
catch {
|
|
192
195
|
continue;
|
|
@@ -291,7 +294,7 @@ async function collectPromptHistory(options) {
|
|
|
291
294
|
*/
|
|
292
295
|
async function readPromptOrdinalMarks(provider, sessionId, filePath) {
|
|
293
296
|
const marks = [];
|
|
294
|
-
const stat = await
|
|
297
|
+
const stat = await (0, compressedRollouts_1.statRolloutContent)(filePath);
|
|
295
298
|
const unbounded = Number.MAX_SAFE_INTEGER;
|
|
296
299
|
const context = {
|
|
297
300
|
roots: [],
|
|
@@ -480,19 +483,24 @@ function scopedCwd(cwd, roots, realpaths) {
|
|
|
480
483
|
return null;
|
|
481
484
|
}
|
|
482
485
|
/** @internal */
|
|
483
|
-
async function listCandidates(providers, listingRoots, sinceMs) {
|
|
486
|
+
async function listCandidates(providers, listingRoots, sinceMs, options = {}) {
|
|
484
487
|
const byPath = new Map();
|
|
485
488
|
const listOptions = sinceMs !== null ? { since: sinceMs } : {};
|
|
486
489
|
for (const provider of [...new Set(providers)]) {
|
|
487
490
|
if (!ALL_PROVIDERS.includes(provider))
|
|
488
491
|
continue;
|
|
489
492
|
// Listings are only candidate supersets; scope is re-checked per prompt.
|
|
490
|
-
const list = provider === 'claude-code' ? claudeListing_1.listClaudeSessionFilesAsync : codexRollouts_1.listCodexSessionFilesAsync;
|
|
491
493
|
const cache = new directoryListingCache_1.DirectoryListingCache();
|
|
492
494
|
for (const root of listingRoots) {
|
|
493
495
|
let files;
|
|
494
496
|
try {
|
|
495
|
-
files =
|
|
497
|
+
files =
|
|
498
|
+
provider === 'claude-code'
|
|
499
|
+
? await (0, claudeListing_1.listClaudeSessionFilesAsync)(root, listOptions, cache)
|
|
500
|
+
: await (0, codexRollouts_1.listCodexSessionFilesAsync)(root, {
|
|
501
|
+
...listOptions,
|
|
502
|
+
includeCompressed: options.includeCompressedRollouts === true && (0, compressedRollouts_1.canReadCompressedRollouts)(),
|
|
503
|
+
}, cache);
|
|
496
504
|
}
|
|
497
505
|
catch {
|
|
498
506
|
files = [];
|
|
@@ -514,11 +522,11 @@ async function listCandidates(providers, listingRoots, sinceMs) {
|
|
|
514
522
|
compareStrings(left.sessionId, right.sessionId) ||
|
|
515
523
|
compareStrings(left.key, right.key));
|
|
516
524
|
}
|
|
517
|
-
/** True when the file's first bytes still match a recorded head. */
|
|
525
|
+
/** True when the file's first bytes (a compressed rollout's content) still match a recorded head. */
|
|
518
526
|
async function fileStartsWith(filePath, head) {
|
|
519
527
|
let handle;
|
|
520
528
|
try {
|
|
521
|
-
handle = await
|
|
529
|
+
({ handle } = await (0, compressedRollouts_1.openRolloutReadHandle)(filePath));
|
|
522
530
|
return (0, fileHead_1.headMatches)(head, await readAt(handle, 0, Math.min(fileHead_1.HEAD_BYTES, head.bytes)));
|
|
523
531
|
}
|
|
524
532
|
catch {
|
|
@@ -591,8 +599,11 @@ async function verifyFile(handle, size, session) {
|
|
|
591
599
|
return { head: (0, fileHead_1.fileHeadOf)(head), bytesRead };
|
|
592
600
|
}
|
|
593
601
|
/** @internal */
|
|
594
|
-
async function scanFile(candidate,
|
|
595
|
-
|
|
602
|
+
async function scanFile(candidate, fileStat, prior, budget, context) {
|
|
603
|
+
// A compressed rollout is scanned over its decompressed content.
|
|
604
|
+
const opened = await (0, compressedRollouts_1.openRolloutReadHandle)(candidate.filePath);
|
|
605
|
+
const handle = opened.handle;
|
|
606
|
+
const stat = opened.size === null ? fileStat : { size: opened.size, mtimeMs: fileStat.mtimeMs };
|
|
596
607
|
try {
|
|
597
608
|
let bytesRead = 0;
|
|
598
609
|
const verified = await verifyFile(handle, stat.size, prior);
|
|
@@ -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;
|
|
@@ -167,37 +171,28 @@ class ClaudeCodeReader {
|
|
|
167
171
|
}
|
|
168
172
|
readNew() {
|
|
169
173
|
this.events = [];
|
|
170
|
-
this.
|
|
174
|
+
this._lastReset = null;
|
|
175
|
+
let fd = null;
|
|
171
176
|
try {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
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);
|
|
176
187
|
const currentSize = stats.size;
|
|
177
|
-
// Handle truncation
|
|
178
|
-
if (currentSize < this.filePosition) {
|
|
179
|
-
this._wasTruncated = true;
|
|
180
|
-
this.filePosition = 0;
|
|
181
|
-
this.committedPosition = 0;
|
|
182
|
-
this.parser.reset();
|
|
183
|
-
this.decoder = new string_decoder_1.StringDecoder('utf8');
|
|
184
|
-
this.usageDeduper.reset();
|
|
185
|
-
}
|
|
186
188
|
// No new content
|
|
187
189
|
if (currentSize <= this.filePosition) {
|
|
188
|
-
return
|
|
190
|
+
return this.events;
|
|
189
191
|
}
|
|
190
192
|
// Read new bytes from last position
|
|
191
|
-
const fd = fs.openSync(this.sessionPath, 'r');
|
|
192
193
|
const bufferSize = currentSize - this.filePosition;
|
|
193
194
|
const buffer = Buffer.alloc(bufferSize);
|
|
194
|
-
|
|
195
|
-
try {
|
|
196
|
-
bytesRead = fs.readSync(fd, buffer, 0, bufferSize, this.filePosition);
|
|
197
|
-
}
|
|
198
|
-
finally {
|
|
199
|
-
fs.closeSync(fd);
|
|
200
|
-
}
|
|
195
|
+
const bytesRead = fs.readSync(fd, buffer, 0, bufferSize, this.filePosition);
|
|
201
196
|
const bytes = buffer.subarray(0, bytesRead);
|
|
202
197
|
const newline = bytes.lastIndexOf(0x0a);
|
|
203
198
|
if (newline >= 0)
|
|
@@ -207,10 +202,31 @@ class ClaudeCodeReader {
|
|
|
207
202
|
this.filePosition += bytesRead;
|
|
208
203
|
}
|
|
209
204
|
catch (error) {
|
|
210
|
-
|
|
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
|
+
}
|
|
211
218
|
}
|
|
212
219
|
return this.events;
|
|
213
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
|
+
}
|
|
214
230
|
readAll() {
|
|
215
231
|
this.reset();
|
|
216
232
|
return this.readNew();
|
|
@@ -221,7 +237,8 @@ class ClaudeCodeReader {
|
|
|
221
237
|
this.parser.reset();
|
|
222
238
|
this.decoder = new string_decoder_1.StringDecoder('utf8');
|
|
223
239
|
this.usageDeduper.reset();
|
|
224
|
-
this.
|
|
240
|
+
this._lastReset = null;
|
|
241
|
+
this.continuity.forget();
|
|
225
242
|
}
|
|
226
243
|
exists() {
|
|
227
244
|
return fs.existsSync(this.sessionPath);
|
|
@@ -241,9 +258,15 @@ class ClaudeCodeReader {
|
|
|
241
258
|
this.committedPosition = position;
|
|
242
259
|
this.parser.reset();
|
|
243
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();
|
|
244
264
|
}
|
|
245
265
|
wasTruncated() {
|
|
246
|
-
return this.
|
|
266
|
+
return this._lastReset !== null;
|
|
267
|
+
}
|
|
268
|
+
lastReset() {
|
|
269
|
+
return this._lastReset ? { ...this._lastReset } : null;
|
|
247
270
|
}
|
|
248
271
|
/** The usage deduper's recent message ids, so a resumed reader does not recount a split response. */
|
|
249
272
|
getResumeState() {
|
|
@@ -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[];
|