@threadbase-sh/streamer 1.66.0 → 1.67.1
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/dist/api/handlers/conversations.handlers.d.ts +29 -0
- package/dist/api/handlers/conversations.handlers.d.ts.map +1 -1
- package/dist/cli.cjs +97 -15
- package/dist/cli.cjs.map +1 -1
- package/dist/index.cjs +74 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +79 -7
- package/dist/index.js.map +1 -1
- package/dist/server-wiring.d.ts +1 -0
- package/dist/server-wiring.d.ts.map +1 -1
- package/dist/server.d.ts +1 -0
- package/dist/server.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -60,6 +60,35 @@ export declare class ConversationHandlers {
|
|
|
60
60
|
handleGetPopularProjects(url: URL, res: ServerResponse): void;
|
|
61
61
|
handleGetProjectSummaries(url: URL, res: ServerResponse): void;
|
|
62
62
|
findJsonlPath(uuid: string): string | null;
|
|
63
|
+
/**
|
|
64
|
+
* Resolve a conversation id to a JSONL path, in order of authority.
|
|
65
|
+
*
|
|
66
|
+
* `findJsonlPath` alone answers 64.0% of this machine's 961 conversations and
|
|
67
|
+
* 0 of 343 Codex ones — it reconstructs `<projectsDir>/<dir>/<uuid>.jsonl`,
|
|
68
|
+
* which is Claude Code's layout, and a Codex rollout is
|
|
69
|
+
* `rollout-<ts>-<uuid>.jsonl` under a date path, so that walk cannot match one
|
|
70
|
+
* by construction. The ladder below answers 99.7%, leaving only the three
|
|
71
|
+
* whose file is genuinely gone.
|
|
72
|
+
*/
|
|
73
|
+
locateJsonlPath(uuid: string, lookupId: string): Promise<string | null>;
|
|
74
|
+
/**
|
|
75
|
+
* Does `filePath` actually hold the conversation `requestedId` names?
|
|
76
|
+
*
|
|
77
|
+
* The filename settles it for both providers: Claude writes `<uuid>.jsonl`
|
|
78
|
+
* (or `agent-<agentId>.jsonl`), Codex writes `rollout-<ts>-<uuid>.jsonl`.
|
|
79
|
+
* Only when the name says nothing do we open the file — and there the naive
|
|
80
|
+
* rule is wrong, because **a Claude subagent transcript carries the PARENT's
|
|
81
|
+
* `sessionId`**. Matching on `sessionId` alone therefore verifies exactly the
|
|
82
|
+
* file this check exists to reject, so a sidechain is refused outright unless
|
|
83
|
+
* it was asked for by its own `agent-<agentId>` name, which the filename
|
|
84
|
+
* branch above already covers.
|
|
85
|
+
*/
|
|
86
|
+
isJsonlPathFor(filePath: string, requestedId: string): Promise<boolean>;
|
|
87
|
+
/** First parseable JSONL line, for identity checks. Null on an empty or unreadable file. */
|
|
88
|
+
readFirstJsonlEntry(filePath: string): Promise<{
|
|
89
|
+
sessionId?: string;
|
|
90
|
+
isSidechain?: boolean;
|
|
91
|
+
} | null>;
|
|
63
92
|
readCwdFromJsonl(filePath: string): Promise<string | null>;
|
|
64
93
|
findConversationByUuid(uuid: string): Promise<Conversation | null>;
|
|
65
94
|
handleGetConversation(id: string, url: URL, res: ServerResponse, ifNoneMatch?: string): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversations.handlers.d.ts","sourceRoot":"","sources":["../../../src/api/handlers/conversations.handlers.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,YAAY,EAKlB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAG5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAO3C,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAazE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIrD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAe1C;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,EAAE,kBAAkB,CAAC;IAC/B,KAAK,EAAE,KAAK,CAAC;IACb,YAAY,EAAE,WAAW,EAAE,GAAG,SAAS,CAAC;IACxC,KAAK,EAAE,MAAM,iBAAiB,GAAG,IAAI,CAAC;IACtC,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,iBAAiB,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC;IACpD,UAAU,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IACrF,eAAe,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IAClD,2BAA2B,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACtD,uBAAuB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACzD,uBAAuB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;CACvD,CAAC;AAEF;;;;;;;;GAQG;AACH,qBAAa,oBAAoB;IACnB,OAAO,CAAC,IAAI;IAAxB,YAAoB,IAAI,EAAE,wBAAwB,EAAI;IAEtD,OAAO,KAAK,cAAc,GAEzB;IAED,OAAO,KAAK,YAAY,GAEvB;IAED,OAAO,KAAK,UAAU,GAErB;IAED,OAAO,KAAK,KAAK,GAEhB;IAED,OAAO,KAAK,YAAY,GAEvB;IAED,OAAO,KAAK,KAAK,GAEhB;IAED,OAAO,KAAK,GAAG,GAEd;IAEK,uBAAuB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAsH1E;IAEK,wBAAwB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAgC3E;IAKD,OAAO,CAAC,wBAAwB;IAmBhC,uBAAuB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI,CA4B3D;IAED,wBAAwB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI,CAQ5D;IAED,yBAAyB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI,CAgB7D;IAED,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAmBzC;IAEK,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAsB/D;IAEK,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"conversations.handlers.d.ts","sourceRoot":"","sources":["../../../src/api/handlers/conversations.handlers.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.cjs
CHANGED
|
@@ -99746,8 +99746,8 @@ var require_pattern = __commonJS({
|
|
|
99746
99746
|
}
|
|
99747
99747
|
exports2.endsWithSlashGlobStar = endsWithSlashGlobStar;
|
|
99748
99748
|
function isAffectDepthOfReadingPattern(pattern) {
|
|
99749
|
-
const
|
|
99750
|
-
return endsWithSlashGlobStar(pattern) || isStaticPattern(
|
|
99749
|
+
const basename13 = path2.basename(pattern);
|
|
99750
|
+
return endsWithSlashGlobStar(pattern) || isStaticPattern(basename13);
|
|
99751
99751
|
}
|
|
99752
99752
|
exports2.isAffectDepthOfReadingPattern = isAffectDepthOfReadingPattern;
|
|
99753
99753
|
function expandPatternsWithBraceExpansion(patterns2) {
|
|
@@ -139150,10 +139150,10 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
139150
139150
|
}
|
|
139151
139151
|
async _formatEntry(dirent, path2) {
|
|
139152
139152
|
let entry;
|
|
139153
|
-
const
|
|
139153
|
+
const basename13 = this._isDirent ? dirent.name : dirent;
|
|
139154
139154
|
try {
|
|
139155
|
-
const fullPath = (0, import_node_path8.resolve)((0, import_node_path8.join)(path2,
|
|
139156
|
-
entry = { path: (0, import_node_path8.relative)(this._root, fullPath), fullPath, basename:
|
|
139155
|
+
const fullPath = (0, import_node_path8.resolve)((0, import_node_path8.join)(path2, basename13));
|
|
139156
|
+
entry = { path: (0, import_node_path8.relative)(this._root, fullPath), fullPath, basename: basename13 };
|
|
139157
139157
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
139158
139158
|
} catch (err) {
|
|
139159
139159
|
this._onError(err);
|
|
@@ -139694,9 +139694,9 @@ var NodeFsHandler = class {
|
|
|
139694
139694
|
_watchWithNodeFs(path2, listener) {
|
|
139695
139695
|
const opts = this.fsw.options;
|
|
139696
139696
|
const directory = sp.dirname(path2);
|
|
139697
|
-
const
|
|
139697
|
+
const basename13 = sp.basename(path2);
|
|
139698
139698
|
const parent = this.fsw._getWatchedDir(directory);
|
|
139699
|
-
parent.add(
|
|
139699
|
+
parent.add(basename13);
|
|
139700
139700
|
const absolutePath = sp.resolve(path2);
|
|
139701
139701
|
const options = {
|
|
139702
139702
|
persistent: opts.persistent
|
|
@@ -139706,7 +139706,7 @@ var NodeFsHandler = class {
|
|
|
139706
139706
|
let closer;
|
|
139707
139707
|
if (opts.usePolling) {
|
|
139708
139708
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
139709
|
-
options.interval = enableBin && isBinaryPath(
|
|
139709
|
+
options.interval = enableBin && isBinaryPath(basename13) ? opts.binaryInterval : opts.interval;
|
|
139710
139710
|
closer = setFsWatchFileListener(path2, absolutePath, options, {
|
|
139711
139711
|
listener,
|
|
139712
139712
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -139729,10 +139729,10 @@ var NodeFsHandler = class {
|
|
|
139729
139729
|
return;
|
|
139730
139730
|
}
|
|
139731
139731
|
const dirname18 = sp.dirname(file2);
|
|
139732
|
-
const
|
|
139732
|
+
const basename13 = sp.basename(file2);
|
|
139733
139733
|
const parent = this.fsw._getWatchedDir(dirname18);
|
|
139734
139734
|
let prevStats = stats;
|
|
139735
|
-
if (parent.has(
|
|
139735
|
+
if (parent.has(basename13))
|
|
139736
139736
|
return;
|
|
139737
139737
|
const listener = async (path2, newStats) => {
|
|
139738
139738
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file2, 5))
|
|
@@ -139757,9 +139757,9 @@ var NodeFsHandler = class {
|
|
|
139757
139757
|
prevStats = newStats2;
|
|
139758
139758
|
}
|
|
139759
139759
|
} catch (error51) {
|
|
139760
|
-
this.fsw._remove(dirname18,
|
|
139760
|
+
this.fsw._remove(dirname18, basename13);
|
|
139761
139761
|
}
|
|
139762
|
-
} else if (parent.has(
|
|
139762
|
+
} else if (parent.has(basename13)) {
|
|
139763
139763
|
const at2 = newStats.atimeMs;
|
|
139764
139764
|
const mt2 = newStats.mtimeMs;
|
|
139765
139765
|
if (!at2 || at2 <= mt2 || mt2 !== prevStats.mtimeMs) {
|
|
@@ -143610,8 +143610,18 @@ var IndexQueue = class {
|
|
|
143610
143610
|
};
|
|
143611
143611
|
var BATCH_SIZE2 = 12;
|
|
143612
143612
|
var DEFAULT_CONFIG_PATH2 = "~/.config/threadbase-scanner";
|
|
143613
|
+
function isTestProcess() {
|
|
143614
|
+
return Boolean(process.env.VITEST) || Boolean(process.env.JEST_WORKER_ID) || process.env.NODE_ENV === "test";
|
|
143615
|
+
}
|
|
143613
143616
|
function defaultDbPath() {
|
|
143614
|
-
|
|
143617
|
+
const override = process.env.TB_SCANNER_DB;
|
|
143618
|
+
if (override) return override;
|
|
143619
|
+
if (isTestProcess()) {
|
|
143620
|
+
throw new Error(
|
|
143621
|
+
"TB_SCANNER_DB must be set under a test runner. Refusing to open the default index at ~/.config/threadbase-scanner/index.db, because test fixtures written there are indistinguishable from real conversations and corrupt every measurement of the index. Point it at a temp directory in your test setup, or pass persistent.dbPath explicitly."
|
|
143622
|
+
);
|
|
143623
|
+
}
|
|
143624
|
+
return (0, import_path10.join)((0, import_os8.homedir)(), ".config", "threadbase-scanner", "index.db");
|
|
143615
143625
|
}
|
|
143616
143626
|
function capForMemory(doc, max) {
|
|
143617
143627
|
const combined = combineSearchContent(doc);
|
|
@@ -146482,6 +146492,64 @@ var ConversationHandlers = class {
|
|
|
146482
146492
|
}
|
|
146483
146493
|
return null;
|
|
146484
146494
|
}
|
|
146495
|
+
/**
|
|
146496
|
+
* Resolve a conversation id to a JSONL path, in order of authority.
|
|
146497
|
+
*
|
|
146498
|
+
* `findJsonlPath` alone answers 64.0% of this machine's 961 conversations and
|
|
146499
|
+
* 0 of 343 Codex ones — it reconstructs `<projectsDir>/<dir>/<uuid>.jsonl`,
|
|
146500
|
+
* which is Claude Code's layout, and a Codex rollout is
|
|
146501
|
+
* `rollout-<ts>-<uuid>.jsonl` under a date path, so that walk cannot match one
|
|
146502
|
+
* by construction. The ladder below answers 99.7%, leaving only the three
|
|
146503
|
+
* whose file is genuinely gone.
|
|
146504
|
+
*/
|
|
146505
|
+
async locateJsonlPath(uuid3, lookupId) {
|
|
146506
|
+
const live = this.deps.findLiveSessionFilePath(uuid3) ?? this.deps.findLiveSessionFilePath(lookupId);
|
|
146507
|
+
if (live) return live;
|
|
146508
|
+
const cached4 = this.cache?.getMetaById(lookupId)?.filePath;
|
|
146509
|
+
if (cached4 && await this.isJsonlPathFor(cached4, lookupId)) return cached4;
|
|
146510
|
+
return this.findJsonlPath(lookupId);
|
|
146511
|
+
}
|
|
146512
|
+
/**
|
|
146513
|
+
* Does `filePath` actually hold the conversation `requestedId` names?
|
|
146514
|
+
*
|
|
146515
|
+
* The filename settles it for both providers: Claude writes `<uuid>.jsonl`
|
|
146516
|
+
* (or `agent-<agentId>.jsonl`), Codex writes `rollout-<ts>-<uuid>.jsonl`.
|
|
146517
|
+
* Only when the name says nothing do we open the file — and there the naive
|
|
146518
|
+
* rule is wrong, because **a Claude subagent transcript carries the PARENT's
|
|
146519
|
+
* `sessionId`**. Matching on `sessionId` alone therefore verifies exactly the
|
|
146520
|
+
* file this check exists to reject, so a sidechain is refused outright unless
|
|
146521
|
+
* it was asked for by its own `agent-<agentId>` name, which the filename
|
|
146522
|
+
* branch above already covers.
|
|
146523
|
+
*/
|
|
146524
|
+
async isJsonlPathFor(filePath, requestedId) {
|
|
146525
|
+
if (!(0, import_fs20.existsSync)(filePath)) return false;
|
|
146526
|
+
const stem = (0, import_path18.basename)(filePath).replace(/\.jsonl$/, "");
|
|
146527
|
+
if (stem === requestedId || stem.includes(requestedId)) return true;
|
|
146528
|
+
const first = await this.readFirstJsonlEntry(filePath);
|
|
146529
|
+
if (!first || first.isSidechain === true) return false;
|
|
146530
|
+
return first.sessionId === requestedId;
|
|
146531
|
+
}
|
|
146532
|
+
/** First parseable JSONL line, for identity checks. Null on an empty or unreadable file. */
|
|
146533
|
+
async readFirstJsonlEntry(filePath) {
|
|
146534
|
+
return new Promise((resolve4) => {
|
|
146535
|
+
const rl = (0, import_readline4.createInterface)({ input: (0, import_fs20.createReadStream)(filePath), crlfDelay: Infinity });
|
|
146536
|
+
let done = false;
|
|
146537
|
+
rl.on("line", (line) => {
|
|
146538
|
+
if (done) return;
|
|
146539
|
+
try {
|
|
146540
|
+
const entry = JSON.parse(line);
|
|
146541
|
+
done = true;
|
|
146542
|
+
rl.close();
|
|
146543
|
+
resolve4(entry);
|
|
146544
|
+
} catch {
|
|
146545
|
+
}
|
|
146546
|
+
});
|
|
146547
|
+
rl.on("close", () => {
|
|
146548
|
+
if (!done) resolve4(null);
|
|
146549
|
+
});
|
|
146550
|
+
rl.on("error", () => resolve4(null));
|
|
146551
|
+
});
|
|
146552
|
+
}
|
|
146485
146553
|
async readCwdFromJsonl(filePath) {
|
|
146486
146554
|
return new Promise((resolve4) => {
|
|
146487
146555
|
const rl = (0, import_readline4.createInterface)({ input: (0, import_fs20.createReadStream)(filePath), crlfDelay: Infinity });
|
|
@@ -146507,7 +146575,7 @@ var ConversationHandlers = class {
|
|
|
146507
146575
|
async findConversationByUuid(uuid3) {
|
|
146508
146576
|
const lookupId = this.deps.resolveConversationLookupId(uuid3);
|
|
146509
146577
|
if (!this.scannerManager.ready && !this.scanProfiles) {
|
|
146510
|
-
const filePath2 =
|
|
146578
|
+
const filePath2 = await this.locateJsonlPath(uuid3, lookupId);
|
|
146511
146579
|
if (filePath2) {
|
|
146512
146580
|
const account = this.cache?.getMetaById(lookupId)?.account ?? void 0;
|
|
146513
146581
|
const coldScanner = this.scannerManager.current ?? this.scannerManager.newScanner();
|
|
@@ -146559,7 +146627,7 @@ var ConversationHandlers = class {
|
|
|
146559
146627
|
return fromIndex;
|
|
146560
146628
|
}
|
|
146561
146629
|
if (this.scanProfiles) return null;
|
|
146562
|
-
const filePath =
|
|
146630
|
+
const filePath = await this.locateJsonlPath(uuid3, lookupId);
|
|
146563
146631
|
if (!filePath) return null;
|
|
146564
146632
|
if (this.scannerManager.ready) {
|
|
146565
146633
|
const account = this.cache?.getMetaById(lookupId)?.account ?? void 0;
|
|
@@ -151283,6 +151351,13 @@ function createApiDeps(deps) {
|
|
|
151283
151351
|
);
|
|
151284
151352
|
}
|
|
151285
151353
|
}
|
|
151354
|
+
if (msg.type === "unsubscribe_session" && typeof msg.sessionId === "string") {
|
|
151355
|
+
if (!wsAllows(principal, "history:read")) {
|
|
151356
|
+
deny(msg.type, "history:read");
|
|
151357
|
+
return;
|
|
151358
|
+
}
|
|
151359
|
+
deps.removeSessionSubscriber(msg.sessionId, ws2);
|
|
151360
|
+
}
|
|
151286
151361
|
if (msg.type === "hold_session" && typeof msg.sessionId === "string") {
|
|
151287
151362
|
if (!wsAllows(principal, "session:control")) {
|
|
151288
151363
|
deny(msg.type, "session:control");
|
|
@@ -154512,6 +154587,7 @@ var StreamerServer = class {
|
|
|
154512
154587
|
withReconciledLifecycle: (sessions) => this.withReconciledLifecycle(sessions),
|
|
154513
154588
|
currentWarmupState: () => this.currentWarmupState(),
|
|
154514
154589
|
addSessionSubscriber: (sessionId, ws2) => this.addSessionSubscriber(sessionId, ws2),
|
|
154590
|
+
removeSessionSubscriber: (sessionId, ws2) => this.removeSessionSubscriber(sessionId, ws2),
|
|
154515
154591
|
startGraceTimer: (sessionId, delayMs) => this.startGraceTimer(sessionId, delayMs),
|
|
154516
154592
|
armHoldWhenIdle: (sessionId) => this.armHoldWhenIdle(sessionId),
|
|
154517
154593
|
handleSessionsCount: (res) => this.handleSessionsCount(res),
|
|
@@ -154641,6 +154717,12 @@ var StreamerServer = class {
|
|
|
154641
154717
|
);
|
|
154642
154718
|
}
|
|
154643
154719
|
}
|
|
154720
|
+
removeSessionSubscriber(sessionId, ws2) {
|
|
154721
|
+
const subs = this.sessionSubscribers.get(sessionId);
|
|
154722
|
+
if (!subs) return;
|
|
154723
|
+
subs.delete(ws2);
|
|
154724
|
+
if (subs.size === 0) this.sessionSubscribers.delete(sessionId);
|
|
154725
|
+
}
|
|
154644
154726
|
/**
|
|
154645
154727
|
* Bring up Live Activity push, if credentials are present (Feature 12).
|
|
154646
154728
|
*
|