@threadbase-sh/streamer 1.27.1 → 1.27.2
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/cli.cjs +933 -710
- package/dist/cli.cjs.map +1 -1
- package/package.json +2 -2
package/dist/cli.cjs
CHANGED
|
@@ -99922,8 +99922,8 @@ var require_pattern = __commonJS({
|
|
|
99922
99922
|
}
|
|
99923
99923
|
exports2.endsWithSlashGlobStar = endsWithSlashGlobStar;
|
|
99924
99924
|
function isAffectDepthOfReadingPattern(pattern) {
|
|
99925
|
-
const
|
|
99926
|
-
return endsWithSlashGlobStar(pattern) || isStaticPattern(
|
|
99925
|
+
const basename12 = path2.basename(pattern);
|
|
99926
|
+
return endsWithSlashGlobStar(pattern) || isStaticPattern(basename12);
|
|
99927
99927
|
}
|
|
99928
99928
|
exports2.isAffectDepthOfReadingPattern = isAffectDepthOfReadingPattern;
|
|
99929
99929
|
function expandPatternsWithBraceExpansion(patterns2) {
|
|
@@ -123750,14 +123750,14 @@ __export(prompt_exports, {
|
|
|
123750
123750
|
interactivePermissionModePrompt: () => interactivePermissionModePrompt,
|
|
123751
123751
|
interactivePrompt: () => interactivePrompt
|
|
123752
123752
|
});
|
|
123753
|
-
var import_node_process2,
|
|
123753
|
+
var import_node_process2, import_promises20, interactivePrompt, interactivePermissionModePrompt;
|
|
123754
123754
|
var init_prompt = __esm({
|
|
123755
123755
|
"src/lifecycle/prompt.ts"() {
|
|
123756
123756
|
"use strict";
|
|
123757
123757
|
import_node_process2 = require("process");
|
|
123758
|
-
|
|
123758
|
+
import_promises20 = require("readline/promises");
|
|
123759
123759
|
interactivePrompt = async ({ prodPort, suggestedAltPort, prodActive }) => {
|
|
123760
|
-
const rl = (0,
|
|
123760
|
+
const rl = (0, import_promises20.createInterface)({ input: import_node_process2.stdin, output: import_node_process2.stdout });
|
|
123761
123761
|
try {
|
|
123762
123762
|
if (!prodActive) {
|
|
123763
123763
|
import_node_process2.stdout.write(
|
|
@@ -123792,7 +123792,7 @@ The supervised prod streamer is already holding port ${prodPort}.
|
|
|
123792
123792
|
}
|
|
123793
123793
|
};
|
|
123794
123794
|
interactivePermissionModePrompt = async () => {
|
|
123795
|
-
const rl = (0,
|
|
123795
|
+
const rl = (0, import_promises20.createInterface)({ input: import_node_process2.stdin, output: import_node_process2.stdout });
|
|
123796
123796
|
try {
|
|
123797
123797
|
import_node_process2.stdout.write(
|
|
123798
123798
|
"\nWhich permission mode should spawned Claude Code sessions use?\n [a] acceptEdits \u2014 auto-approve file edits, still prompt for shell commands (default)\n [m] manual \u2014 prompt for every edit and command\n"
|
|
@@ -128528,35 +128528,38 @@ var flexsearch_bundle_module_min_default = { Index: N, Document: U, Worker: S, r
|
|
|
128528
128528
|
|
|
128529
128529
|
// node_modules/@threadbase-sh/scanner/dist/index.js
|
|
128530
128530
|
var import_fs5 = require("fs");
|
|
128531
|
-
var import_promises4 = require("fs/promises");
|
|
128532
|
-
var import_os4 = require("os");
|
|
128533
128531
|
var import_path3 = require("path");
|
|
128534
|
-
var import_fast_glob = __toESM(require_out4(), 1);
|
|
128535
|
-
var import_fs6 = require("fs");
|
|
128536
|
-
var import_promises5 = require("fs/promises");
|
|
128537
|
-
var import_path4 = require("path");
|
|
128538
128532
|
var import_readline = require("readline");
|
|
128539
|
-
var
|
|
128540
|
-
var
|
|
128533
|
+
var import_path4 = require("path");
|
|
128534
|
+
var import_fs6 = require("fs");
|
|
128535
|
+
var import_promises4 = require("fs/promises");
|
|
128536
|
+
var import_os4 = require("os");
|
|
128541
128537
|
var import_path5 = require("path");
|
|
128538
|
+
var import_fast_glob = __toESM(require_out4(), 1);
|
|
128542
128539
|
var import_fs7 = require("fs");
|
|
128540
|
+
var import_promises5 = require("fs/promises");
|
|
128543
128541
|
var import_path6 = require("path");
|
|
128544
128542
|
var import_readline2 = require("readline");
|
|
128543
|
+
var import_fast_glob2 = __toESM(require_out4(), 1);
|
|
128544
|
+
var import_promises6 = require("fs/promises");
|
|
128545
128545
|
var import_events2 = require("events");
|
|
128546
128546
|
var import_fs8 = require("fs");
|
|
128547
128547
|
var import_os5 = require("os");
|
|
128548
128548
|
var import_path7 = require("path");
|
|
128549
|
-
var
|
|
128549
|
+
var import_path8 = require("path");
|
|
128550
128550
|
var import_fs9 = require("fs");
|
|
128551
|
+
var import_promises7 = require("timers/promises");
|
|
128551
128552
|
var import_fs10 = require("fs");
|
|
128552
|
-
var
|
|
128553
|
-
var
|
|
128553
|
+
var import_promises8 = require("timers/promises");
|
|
128554
|
+
var import_crypto2 = require("crypto");
|
|
128554
128555
|
var import_fs11 = require("fs");
|
|
128555
|
-
var import_path8 = require("path");
|
|
128556
|
-
var import_promises7 = require("fs/promises");
|
|
128557
128556
|
var import_fs12 = require("fs");
|
|
128557
|
+
var import_readline3 = require("readline");
|
|
128558
|
+
var import_better_sqlite3 = __toESM(require("better-sqlite3"), 1);
|
|
128558
128559
|
var import_fs13 = require("fs");
|
|
128559
128560
|
var import_path9 = require("path");
|
|
128561
|
+
var import_promises9 = require("fs/promises");
|
|
128562
|
+
var import_path10 = require("path");
|
|
128560
128563
|
|
|
128561
128564
|
// node_modules/@threadbase-sh/scanner/node_modules/chokidar/esm/index.js
|
|
128562
128565
|
var import_fs3 = require("fs");
|
|
@@ -128711,10 +128714,10 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
128711
128714
|
}
|
|
128712
128715
|
async _formatEntry(dirent, path2) {
|
|
128713
128716
|
let entry;
|
|
128714
|
-
const
|
|
128717
|
+
const basename12 = this._isDirent ? dirent.name : dirent;
|
|
128715
128718
|
try {
|
|
128716
|
-
const fullPath = (0, import_node_path5.resolve)((0, import_node_path5.join)(path2,
|
|
128717
|
-
entry = { path: (0, import_node_path5.relative)(this._root, fullPath), fullPath, basename:
|
|
128719
|
+
const fullPath = (0, import_node_path5.resolve)((0, import_node_path5.join)(path2, basename12));
|
|
128720
|
+
entry = { path: (0, import_node_path5.relative)(this._root, fullPath), fullPath, basename: basename12 };
|
|
128718
128721
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
128719
128722
|
} catch (err) {
|
|
128720
128723
|
this._onError(err);
|
|
@@ -129253,9 +129256,9 @@ var NodeFsHandler = class {
|
|
|
129253
129256
|
_watchWithNodeFs(path2, listener) {
|
|
129254
129257
|
const opts = this.fsw.options;
|
|
129255
129258
|
const directory = sysPath.dirname(path2);
|
|
129256
|
-
const
|
|
129259
|
+
const basename12 = sysPath.basename(path2);
|
|
129257
129260
|
const parent = this.fsw._getWatchedDir(directory);
|
|
129258
|
-
parent.add(
|
|
129261
|
+
parent.add(basename12);
|
|
129259
129262
|
const absolutePath = sysPath.resolve(path2);
|
|
129260
129263
|
const options = {
|
|
129261
129264
|
persistent: opts.persistent
|
|
@@ -129265,7 +129268,7 @@ var NodeFsHandler = class {
|
|
|
129265
129268
|
let closer;
|
|
129266
129269
|
if (opts.usePolling) {
|
|
129267
129270
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
129268
|
-
options.interval = enableBin && isBinaryPath(
|
|
129271
|
+
options.interval = enableBin && isBinaryPath(basename12) ? opts.binaryInterval : opts.interval;
|
|
129269
129272
|
closer = setFsWatchFileListener(path2, absolutePath, options, {
|
|
129270
129273
|
listener,
|
|
129271
129274
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -129288,10 +129291,10 @@ var NodeFsHandler = class {
|
|
|
129288
129291
|
return;
|
|
129289
129292
|
}
|
|
129290
129293
|
const dirname17 = sysPath.dirname(file2);
|
|
129291
|
-
const
|
|
129294
|
+
const basename12 = sysPath.basename(file2);
|
|
129292
129295
|
const parent = this.fsw._getWatchedDir(dirname17);
|
|
129293
129296
|
let prevStats = stats;
|
|
129294
|
-
if (parent.has(
|
|
129297
|
+
if (parent.has(basename12))
|
|
129295
129298
|
return;
|
|
129296
129299
|
const listener = async (path2, newStats) => {
|
|
129297
129300
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file2, 5))
|
|
@@ -129316,9 +129319,9 @@ var NodeFsHandler = class {
|
|
|
129316
129319
|
prevStats = newStats2;
|
|
129317
129320
|
}
|
|
129318
129321
|
} catch (error51) {
|
|
129319
|
-
this.fsw._remove(dirname17,
|
|
129322
|
+
this.fsw._remove(dirname17, basename12);
|
|
129320
129323
|
}
|
|
129321
|
-
} else if (parent.has(
|
|
129324
|
+
} else if (parent.has(basename12)) {
|
|
129322
129325
|
const at2 = newStats.atimeMs;
|
|
129323
129326
|
const mt2 = newStats.mtimeMs;
|
|
129324
129327
|
if (!at2 || at2 <= mt2 || mt2 !== prevStats.mtimeMs) {
|
|
@@ -130514,6 +130517,435 @@ var SearchIndexer = class {
|
|
|
130514
130517
|
getLogger2().trace("indexer: cleared");
|
|
130515
130518
|
}
|
|
130516
130519
|
};
|
|
130520
|
+
var CLAUDE_CODE_PROVIDER = "claude-code";
|
|
130521
|
+
var CODEX_CLI_PROVIDER = "codex-cli";
|
|
130522
|
+
function initialReducerState() {
|
|
130523
|
+
return {
|
|
130524
|
+
sessionId: "",
|
|
130525
|
+
sessionName: "",
|
|
130526
|
+
latestTimestamp: "",
|
|
130527
|
+
cwd: "",
|
|
130528
|
+
teamName: "",
|
|
130529
|
+
model: null,
|
|
130530
|
+
messageCount: 0,
|
|
130531
|
+
lastMessageSender: "user",
|
|
130532
|
+
isTeammate: false,
|
|
130533
|
+
firstUserSeen: false,
|
|
130534
|
+
firstMessage: null,
|
|
130535
|
+
lastMessage: null,
|
|
130536
|
+
lastPrompt: "",
|
|
130537
|
+
pageMessageCount: 0,
|
|
130538
|
+
toolNames: [],
|
|
130539
|
+
previewParts: [],
|
|
130540
|
+
snippetParts: [],
|
|
130541
|
+
previewLength: 0,
|
|
130542
|
+
snippetLength: 0,
|
|
130543
|
+
badJsonLines: 0
|
|
130544
|
+
};
|
|
130545
|
+
}
|
|
130546
|
+
function reduceLine(state, entry, tier) {
|
|
130547
|
+
if (entry.cwd && !state.cwd) state.cwd = entry.cwd;
|
|
130548
|
+
if (entry.sessionId && !state.sessionId) state.sessionId = entry.sessionId;
|
|
130549
|
+
if (entry.slug && !state.sessionName) state.sessionName = entry.slug;
|
|
130550
|
+
if (entry.teamName && !state.teamName) state.teamName = entry.teamName;
|
|
130551
|
+
if (entry.timestamp) {
|
|
130552
|
+
const ts2 = entry.timestamp;
|
|
130553
|
+
if (!state.latestTimestamp || ts2 > state.latestTimestamp) state.latestTimestamp = ts2;
|
|
130554
|
+
}
|
|
130555
|
+
const type = entry.type;
|
|
130556
|
+
if (type === "last-prompt") {
|
|
130557
|
+
if (entry.lastPrompt && !state.lastPrompt) state.lastPrompt = entry.lastPrompt;
|
|
130558
|
+
return;
|
|
130559
|
+
}
|
|
130560
|
+
if (type !== "user" && type !== "assistant") return;
|
|
130561
|
+
if (entry.isMeta) return;
|
|
130562
|
+
const msg = entry.message;
|
|
130563
|
+
if (state.model === null && msg?.model) state.model = msg.model;
|
|
130564
|
+
if (type === "user" && !state.firstUserSeen) {
|
|
130565
|
+
state.firstUserSeen = true;
|
|
130566
|
+
if (isTeammateContent(msg?.content)) state.isTeammate = true;
|
|
130567
|
+
}
|
|
130568
|
+
const content = extractTextContent(msg?.content);
|
|
130569
|
+
const hasToolUseResult = type === "user" && entry.toolUseResult != null;
|
|
130570
|
+
const isOnlyToolResult = hasToolUseResult && isOnlyToolResultContent(msg?.content);
|
|
130571
|
+
const toolSet = new Set(state.toolNames);
|
|
130572
|
+
collectToolNames(msg?.content, toolSet);
|
|
130573
|
+
state.toolNames = Array.from(toolSet);
|
|
130574
|
+
const toolUseBlocks = extractToolUseBlocks(msg?.content);
|
|
130575
|
+
const thinking = type === "assistant" ? extractThinking(msg?.content) : null;
|
|
130576
|
+
const hasThinking = !!(thinking?.content || thinking?.signature);
|
|
130577
|
+
if (content || isOnlyToolResult || toolUseBlocks.length > 0 || hasThinking) {
|
|
130578
|
+
state.pageMessageCount++;
|
|
130579
|
+
}
|
|
130580
|
+
if (content || isOnlyToolResult) {
|
|
130581
|
+
state.messageCount++;
|
|
130582
|
+
state.lastMessageSender = type;
|
|
130583
|
+
if (content) {
|
|
130584
|
+
const ts2 = entry.timestamp || "";
|
|
130585
|
+
if (!state.firstMessage) state.firstMessage = { text: content.slice(0, 200), timestamp: ts2 };
|
|
130586
|
+
state.lastMessage = { text: content.slice(0, 200), timestamp: ts2 };
|
|
130587
|
+
if (state.previewLength < tier.previewMax) {
|
|
130588
|
+
state.previewParts.push(content);
|
|
130589
|
+
state.previewLength += content.length;
|
|
130590
|
+
}
|
|
130591
|
+
if (state.snippetLength < tier.snippetMax) {
|
|
130592
|
+
const remaining = tier.snippetMax - state.snippetLength;
|
|
130593
|
+
const chunk = content.length > remaining ? content.slice(0, remaining) : content;
|
|
130594
|
+
state.snippetParts.push(chunk);
|
|
130595
|
+
state.snippetLength += chunk.length;
|
|
130596
|
+
}
|
|
130597
|
+
}
|
|
130598
|
+
}
|
|
130599
|
+
}
|
|
130600
|
+
function finalizeMeta(state, filePath, account, tier) {
|
|
130601
|
+
if (state.messageCount === 0) return null;
|
|
130602
|
+
const isSubagent = filePath.includes("/subagents/");
|
|
130603
|
+
let parentSessionId = null;
|
|
130604
|
+
if (isSubagent) {
|
|
130605
|
+
const uuidDir = (0, import_path4.dirname)((0, import_path4.dirname)(filePath));
|
|
130606
|
+
parentSessionId = (0, import_path4.join)((0, import_path4.dirname)(uuidDir), `${(0, import_path4.basename)(uuidDir)}.jsonl`);
|
|
130607
|
+
}
|
|
130608
|
+
const projectPath = state.cwd;
|
|
130609
|
+
return {
|
|
130610
|
+
id: filePath,
|
|
130611
|
+
filePath,
|
|
130612
|
+
provider: CLAUDE_CODE_PROVIDER,
|
|
130613
|
+
sessionId: state.sessionId || (0, import_path4.basename)(filePath, ".jsonl"),
|
|
130614
|
+
sessionName: state.sessionName,
|
|
130615
|
+
projectPath,
|
|
130616
|
+
projectName: getShortProjectName(projectPath),
|
|
130617
|
+
account,
|
|
130618
|
+
timestamp: state.latestTimestamp || (/* @__PURE__ */ new Date()).toISOString(),
|
|
130619
|
+
messageCount: state.messageCount,
|
|
130620
|
+
lastMessageSender: state.lastMessageSender,
|
|
130621
|
+
preview: state.previewParts.join(" ").slice(0, tier.previewMax),
|
|
130622
|
+
contentSnippet: state.snippetParts.join(" "),
|
|
130623
|
+
gitBranch: null,
|
|
130624
|
+
model: state.model,
|
|
130625
|
+
isSubagent,
|
|
130626
|
+
parentSessionId,
|
|
130627
|
+
isTeammate: state.isTeammate,
|
|
130628
|
+
teamName: state.teamName || null,
|
|
130629
|
+
toolNames: state.toolNames,
|
|
130630
|
+
firstMessage: state.firstMessage,
|
|
130631
|
+
lastMessage: state.lastMessage,
|
|
130632
|
+
lastPrompt: state.lastPrompt || void 0
|
|
130633
|
+
};
|
|
130634
|
+
}
|
|
130635
|
+
function getShortProjectName(fullPath) {
|
|
130636
|
+
const parts = fullPath.split("/").filter(Boolean);
|
|
130637
|
+
return parts.slice(-3).join("/");
|
|
130638
|
+
}
|
|
130639
|
+
var SYSTEM_TAGS = [
|
|
130640
|
+
"system-reminder",
|
|
130641
|
+
"command-name",
|
|
130642
|
+
"command-message",
|
|
130643
|
+
"command-args",
|
|
130644
|
+
"ide_selection",
|
|
130645
|
+
"ide_opened_file",
|
|
130646
|
+
"local-command-stdout",
|
|
130647
|
+
"local-command-caveat",
|
|
130648
|
+
"retrieval_status",
|
|
130649
|
+
"task_id",
|
|
130650
|
+
"task_type",
|
|
130651
|
+
"task-id",
|
|
130652
|
+
"task-notification",
|
|
130653
|
+
"fast_mode_info",
|
|
130654
|
+
"persisted-output",
|
|
130655
|
+
"tool_use_error",
|
|
130656
|
+
"user-prompt-submit-hook",
|
|
130657
|
+
"thinking",
|
|
130658
|
+
"ask_user",
|
|
130659
|
+
"teammate-message"
|
|
130660
|
+
];
|
|
130661
|
+
var SYSTEM_TAG_RE = new RegExp(`<(${SYSTEM_TAGS.join("|")})[^>]*>[\\s\\S]*?<\\/\\1>`, "g");
|
|
130662
|
+
function cleanSystemTags(text) {
|
|
130663
|
+
return text.replace(SYSTEM_TAG_RE, "").replace(/[^\S\n]+/g, " ").replace(/\n{3,}/g, "\n\n").trim();
|
|
130664
|
+
}
|
|
130665
|
+
async function parseMeta(filePath, account, tier) {
|
|
130666
|
+
const log8 = getLogger2();
|
|
130667
|
+
log8.trace({ filePath, account, tier: tier.name }, "parseMeta: start");
|
|
130668
|
+
const state = initialReducerState();
|
|
130669
|
+
const fileStream = (0, import_fs5.createReadStream)(filePath);
|
|
130670
|
+
const rl = (0, import_readline.createInterface)({ input: fileStream, crlfDelay: Infinity });
|
|
130671
|
+
try {
|
|
130672
|
+
for await (const line of rl) {
|
|
130673
|
+
if (!line.trim()) continue;
|
|
130674
|
+
let entry;
|
|
130675
|
+
try {
|
|
130676
|
+
entry = JSON.parse(line);
|
|
130677
|
+
} catch {
|
|
130678
|
+
state.badJsonLines++;
|
|
130679
|
+
continue;
|
|
130680
|
+
}
|
|
130681
|
+
reduceLine(state, entry, tier);
|
|
130682
|
+
}
|
|
130683
|
+
} catch (err) {
|
|
130684
|
+
log8.warn({ filePath, err }, "parseMeta: read failed");
|
|
130685
|
+
return null;
|
|
130686
|
+
}
|
|
130687
|
+
if (state.badJsonLines > 0) {
|
|
130688
|
+
log8.warn(
|
|
130689
|
+
{ filePath, badJsonLines: state.badJsonLines },
|
|
130690
|
+
"parseMeta: skipped malformed JSON lines"
|
|
130691
|
+
);
|
|
130692
|
+
}
|
|
130693
|
+
const meta3 = finalizeMeta(state, filePath, account, tier);
|
|
130694
|
+
if (!meta3) log8.trace({ filePath }, "parseMeta: no messages");
|
|
130695
|
+
return meta3;
|
|
130696
|
+
}
|
|
130697
|
+
async function parseConversation(filePath, account) {
|
|
130698
|
+
const log8 = getLogger2();
|
|
130699
|
+
log8.trace({ filePath, account }, "parseConversation: start");
|
|
130700
|
+
const messages = [];
|
|
130701
|
+
let badJsonLines = 0;
|
|
130702
|
+
const textParts = [];
|
|
130703
|
+
const turnDurations = [];
|
|
130704
|
+
const state = initialConvState();
|
|
130705
|
+
const fileStream = (0, import_fs5.createReadStream)(filePath);
|
|
130706
|
+
const rl = (0, import_readline.createInterface)({ input: fileStream, crlfDelay: Infinity });
|
|
130707
|
+
try {
|
|
130708
|
+
for await (const line of rl) {
|
|
130709
|
+
if (!line.trim()) continue;
|
|
130710
|
+
let entry;
|
|
130711
|
+
try {
|
|
130712
|
+
entry = JSON.parse(line);
|
|
130713
|
+
} catch {
|
|
130714
|
+
badJsonLines++;
|
|
130715
|
+
continue;
|
|
130716
|
+
}
|
|
130717
|
+
if (entry.type === "system" && entry.subtype === "turn_duration" && typeof entry.durationMs === "number") {
|
|
130718
|
+
turnDurations.push({
|
|
130719
|
+
durationMs: entry.durationMs,
|
|
130720
|
+
messageCount: entry.messageCount || 0,
|
|
130721
|
+
uuid: entry.uuid
|
|
130722
|
+
});
|
|
130723
|
+
continue;
|
|
130724
|
+
}
|
|
130725
|
+
const message = reduceConvLine(state, entry);
|
|
130726
|
+
if (message) {
|
|
130727
|
+
messages.push(message);
|
|
130728
|
+
if (message.text) textParts.push(message.text);
|
|
130729
|
+
}
|
|
130730
|
+
}
|
|
130731
|
+
} catch (err) {
|
|
130732
|
+
log8.warn({ filePath, err }, "parseConversation: read failed");
|
|
130733
|
+
return null;
|
|
130734
|
+
}
|
|
130735
|
+
if (badJsonLines > 0) {
|
|
130736
|
+
log8.warn({ filePath, badJsonLines }, "parseConversation: skipped malformed JSON lines");
|
|
130737
|
+
}
|
|
130738
|
+
if (messages.length === 0) {
|
|
130739
|
+
log8.trace({ filePath }, "parseConversation: no messages");
|
|
130740
|
+
return null;
|
|
130741
|
+
}
|
|
130742
|
+
log8.debug({ filePath, messageCount: messages.length }, "parseConversation: complete");
|
|
130743
|
+
applyTeamInfo(messages, state);
|
|
130744
|
+
return {
|
|
130745
|
+
id: filePath,
|
|
130746
|
+
filePath,
|
|
130747
|
+
projectPath: state.cwd,
|
|
130748
|
+
projectName: getShortProjectName2(state.cwd),
|
|
130749
|
+
sessionId: state.sessionId || (0, import_path3.basename)(filePath, ".jsonl"),
|
|
130750
|
+
sessionName: state.sessionName,
|
|
130751
|
+
messages,
|
|
130752
|
+
fullText: textParts.join(" "),
|
|
130753
|
+
timestamp: state.latestTimestamp || (/* @__PURE__ */ new Date()).toISOString(),
|
|
130754
|
+
messageCount: messages.length,
|
|
130755
|
+
account,
|
|
130756
|
+
turnDurations: turnDurations.length > 0 ? turnDurations : void 0,
|
|
130757
|
+
lastPrompt: state.lastPrompt || void 0
|
|
130758
|
+
};
|
|
130759
|
+
}
|
|
130760
|
+
function extractTextContent(content) {
|
|
130761
|
+
if (!content) return "";
|
|
130762
|
+
if (typeof content === "string") return cleanSystemTags(content);
|
|
130763
|
+
if (Array.isArray(content)) {
|
|
130764
|
+
return content.map((item) => {
|
|
130765
|
+
if (typeof item === "string") return item;
|
|
130766
|
+
if (item?.type === "text" && item?.text) return item.text;
|
|
130767
|
+
if (item?.type === "tool_result" && typeof item?.content === "string") return item.content;
|
|
130768
|
+
return "";
|
|
130769
|
+
}).filter(Boolean).map(cleanSystemTags).join(" ");
|
|
130770
|
+
}
|
|
130771
|
+
return "";
|
|
130772
|
+
}
|
|
130773
|
+
function extractToolUseNames(content) {
|
|
130774
|
+
if (!Array.isArray(content)) return [];
|
|
130775
|
+
return content.filter((item) => item?.type === "tool_use" && item?.name).map((item) => item.name);
|
|
130776
|
+
}
|
|
130777
|
+
function extractToolUseBlocks(content) {
|
|
130778
|
+
if (!Array.isArray(content)) return [];
|
|
130779
|
+
return content.filter((item) => item?.type === "tool_use" && item?.name && item?.id).map((item) => ({
|
|
130780
|
+
id: item.id,
|
|
130781
|
+
name: item.name,
|
|
130782
|
+
input: item.input || {}
|
|
130783
|
+
}));
|
|
130784
|
+
}
|
|
130785
|
+
var TOOL_NAME_TO_TYPE = {
|
|
130786
|
+
Edit: "edit",
|
|
130787
|
+
Write: "write",
|
|
130788
|
+
Read: "read",
|
|
130789
|
+
Bash: "bash",
|
|
130790
|
+
Grep: "grep",
|
|
130791
|
+
Glob: "glob",
|
|
130792
|
+
Agent: "taskAgent",
|
|
130793
|
+
TaskCreate: "taskCreate",
|
|
130794
|
+
TaskUpdate: "taskUpdate"
|
|
130795
|
+
};
|
|
130796
|
+
function extractToolResultBlocks(content, pendingToolUses) {
|
|
130797
|
+
if (!Array.isArray(content)) return [];
|
|
130798
|
+
return content.filter((item) => item?.type === "tool_result" && item?.tool_use_id).map((item) => {
|
|
130799
|
+
const toolName = pendingToolUses.get(item.tool_use_id)?.name ?? "";
|
|
130800
|
+
return {
|
|
130801
|
+
toolUseId: item.tool_use_id,
|
|
130802
|
+
type: TOOL_NAME_TO_TYPE[toolName] ?? "generic",
|
|
130803
|
+
content: typeof item.content === "string" ? { text: item.content } : item.content ?? {},
|
|
130804
|
+
isError: typeof item.is_error === "boolean" ? item.is_error : void 0
|
|
130805
|
+
};
|
|
130806
|
+
});
|
|
130807
|
+
}
|
|
130808
|
+
function collectToolNames(content, toolSet) {
|
|
130809
|
+
if (!Array.isArray(content)) return;
|
|
130810
|
+
for (const item of content) {
|
|
130811
|
+
if (item?.type === "tool_use" && item?.name) {
|
|
130812
|
+
toolSet.add(item.name);
|
|
130813
|
+
}
|
|
130814
|
+
}
|
|
130815
|
+
}
|
|
130816
|
+
function isOnlyToolResultContent(content) {
|
|
130817
|
+
if (!Array.isArray(content)) return false;
|
|
130818
|
+
return content.length > 0 && content.every((item) => item?.type === "tool_result");
|
|
130819
|
+
}
|
|
130820
|
+
function isTeammateContent(content) {
|
|
130821
|
+
const raw2 = typeof content === "string" ? content : Array.isArray(content) ? content.map(
|
|
130822
|
+
(item) => typeof item === "string" ? item : item?.type === "text" ? item.text ?? "" : ""
|
|
130823
|
+
).join("") : "";
|
|
130824
|
+
return raw2.includes("<teammate-message");
|
|
130825
|
+
}
|
|
130826
|
+
function extractThinking(content) {
|
|
130827
|
+
if (!Array.isArray(content)) return { content: "", signature: "" };
|
|
130828
|
+
const blocks = content.filter((item) => item?.type === "thinking");
|
|
130829
|
+
return {
|
|
130830
|
+
content: blocks.map((b2) => b2.thinking).filter(Boolean).join("\n\n"),
|
|
130831
|
+
signature: blocks.map((b2) => b2.signature).filter(Boolean).join("")
|
|
130832
|
+
};
|
|
130833
|
+
}
|
|
130834
|
+
function hasImageBlocks(content) {
|
|
130835
|
+
if (!Array.isArray(content)) return false;
|
|
130836
|
+
return content.some(
|
|
130837
|
+
(item) => item?.type === "image" && (item?.source?.type === "base64" || item?.file?.base64 !== void 0)
|
|
130838
|
+
);
|
|
130839
|
+
}
|
|
130840
|
+
function parseTeammateMessageTag(content) {
|
|
130841
|
+
const match2 = content.match(/<teammate-message\s+([^>]*)>/);
|
|
130842
|
+
if (!match2) return null;
|
|
130843
|
+
const attrs = match2[1];
|
|
130844
|
+
const id = attrs.match(/teammate_id="([^"]*)"/)?.[1];
|
|
130845
|
+
if (!id) return null;
|
|
130846
|
+
const summary = attrs.match(/summary="([^"]*)"/)?.[1];
|
|
130847
|
+
const color = attrs.match(/color="([^"]*)"/)?.[1];
|
|
130848
|
+
return { teammateId: id, summary, color };
|
|
130849
|
+
}
|
|
130850
|
+
function getShortProjectName2(fullPath) {
|
|
130851
|
+
const parts = fullPath.split("/").filter(Boolean);
|
|
130852
|
+
return parts.slice(-3).join("/");
|
|
130853
|
+
}
|
|
130854
|
+
function initialConvState() {
|
|
130855
|
+
return {
|
|
130856
|
+
cwd: "",
|
|
130857
|
+
sessionId: "",
|
|
130858
|
+
sessionName: "",
|
|
130859
|
+
latestTimestamp: "",
|
|
130860
|
+
lastPrompt: "",
|
|
130861
|
+
pendingToolUses: {},
|
|
130862
|
+
teamInfo: {}
|
|
130863
|
+
};
|
|
130864
|
+
}
|
|
130865
|
+
function reduceConvLine(state, entry) {
|
|
130866
|
+
if (entry.cwd && !state.cwd) state.cwd = entry.cwd;
|
|
130867
|
+
if (entry.sessionId && !state.sessionId) state.sessionId = entry.sessionId;
|
|
130868
|
+
if (entry.slug && !state.sessionName) state.sessionName = entry.slug;
|
|
130869
|
+
if (entry.timestamp) {
|
|
130870
|
+
const ts2 = entry.timestamp;
|
|
130871
|
+
if (!state.latestTimestamp || ts2 > state.latestTimestamp) state.latestTimestamp = ts2;
|
|
130872
|
+
}
|
|
130873
|
+
const type = entry.type;
|
|
130874
|
+
if (type === "last-prompt") {
|
|
130875
|
+
if (entry.lastPrompt && !state.lastPrompt) state.lastPrompt = entry.lastPrompt;
|
|
130876
|
+
return null;
|
|
130877
|
+
}
|
|
130878
|
+
if (type !== "user" && type !== "assistant") return null;
|
|
130879
|
+
if (entry.isMeta) return null;
|
|
130880
|
+
const msg = entry.message;
|
|
130881
|
+
const toolUseBlocks = extractToolUseBlocks(msg?.content);
|
|
130882
|
+
for (const block of toolUseBlocks) state.pendingToolUses[block.id] = block;
|
|
130883
|
+
const hasToolUseResult = type === "user" && entry.toolUseResult != null;
|
|
130884
|
+
const isToolResultOnly = hasToolUseResult && isOnlyToolResultContent(msg?.content);
|
|
130885
|
+
const content = extractTextContent(msg?.content);
|
|
130886
|
+
const thinking = type === "assistant" ? extractThinking(msg?.content) : null;
|
|
130887
|
+
const hasThinking = !!(thinking?.content || thinking?.signature);
|
|
130888
|
+
if (!(content || isToolResultOnly || toolUseBlocks.length > 0 || hasThinking)) return null;
|
|
130889
|
+
const metadata = {};
|
|
130890
|
+
if (msg?.model) metadata.model = msg.model;
|
|
130891
|
+
if (msg?.stop_reason !== void 0) metadata.stopReason = msg.stop_reason;
|
|
130892
|
+
if (entry.gitBranch) metadata.gitBranch = entry.gitBranch;
|
|
130893
|
+
if (entry.version) metadata.version = entry.version;
|
|
130894
|
+
const usage = msg?.usage;
|
|
130895
|
+
if (usage) {
|
|
130896
|
+
if (usage.input_tokens) metadata.inputTokens = usage.input_tokens;
|
|
130897
|
+
if (usage.output_tokens) metadata.outputTokens = usage.output_tokens;
|
|
130898
|
+
if (usage.cache_read_input_tokens) metadata.cacheReadTokens = usage.cache_read_input_tokens;
|
|
130899
|
+
if (usage.cache_creation_input_tokens)
|
|
130900
|
+
metadata.cacheCreationTokens = usage.cache_creation_input_tokens;
|
|
130901
|
+
}
|
|
130902
|
+
const toolUseNames = extractToolUseNames(msg?.content);
|
|
130903
|
+
if (toolUseNames.length > 0) metadata.toolUses = toolUseNames;
|
|
130904
|
+
if (toolUseBlocks.length > 0) metadata.toolUseBlocks = toolUseBlocks;
|
|
130905
|
+
if (isToolResultOnly) {
|
|
130906
|
+
const pending = new Map(Object.entries(state.pendingToolUses));
|
|
130907
|
+
const toolResultBlocks = extractToolResultBlocks(msg?.content, pending);
|
|
130908
|
+
if (toolResultBlocks.length > 0) {
|
|
130909
|
+
metadata.toolResults = toolResultBlocks;
|
|
130910
|
+
for (const block of toolResultBlocks) delete state.pendingToolUses[block.toolUseId];
|
|
130911
|
+
}
|
|
130912
|
+
}
|
|
130913
|
+
if (entry.teamName) {
|
|
130914
|
+
metadata.teamName = entry.teamName;
|
|
130915
|
+
if (!state.teamInfo[metadata.teamName] && content) {
|
|
130916
|
+
const info = parseTeammateMessageTag(content);
|
|
130917
|
+
if (info) state.teamInfo[metadata.teamName] = info;
|
|
130918
|
+
}
|
|
130919
|
+
}
|
|
130920
|
+
const thinkingContent = thinking?.content || void 0;
|
|
130921
|
+
const thinkingSignature = thinking?.signature || void 0;
|
|
130922
|
+
const hasMetadata = Object.keys(metadata).length > 0;
|
|
130923
|
+
return {
|
|
130924
|
+
role: type,
|
|
130925
|
+
text: content || "",
|
|
130926
|
+
timestamp: entry.timestamp || "",
|
|
130927
|
+
uuid: entry.uuid || void 0,
|
|
130928
|
+
metadata: hasMetadata ? metadata : void 0,
|
|
130929
|
+
isToolResult: isToolResultOnly || void 0,
|
|
130930
|
+
isThinking: thinkingContent || thinkingSignature ? true : void 0,
|
|
130931
|
+
thinkingContent,
|
|
130932
|
+
thinkingSignature,
|
|
130933
|
+
parentUuid: entry.parentUuid !== void 0 ? entry.parentUuid : void 0,
|
|
130934
|
+
requestId: type === "assistant" ? entry.requestId : void 0,
|
|
130935
|
+
promptId: type === "user" ? entry.promptId : void 0,
|
|
130936
|
+
isSidechain: typeof entry.isSidechain === "boolean" ? entry.isSidechain : void 0,
|
|
130937
|
+
permissionMode: type === "user" ? entry.permissionMode : void 0,
|
|
130938
|
+
hasImages: hasImageBlocks(msg?.content) || void 0,
|
|
130939
|
+
attachment: entry.attachment !== void 0 ? entry.attachment : void 0
|
|
130940
|
+
};
|
|
130941
|
+
}
|
|
130942
|
+
function applyTeamInfo(messages, state) {
|
|
130943
|
+
if (Object.keys(state.teamInfo).length === 0) return;
|
|
130944
|
+
for (const m2 of messages) {
|
|
130945
|
+
const name = m2.metadata?.teamName;
|
|
130946
|
+
if (name && state.teamInfo[name] && m2.metadata) m2.metadata.teamInfo = state.teamInfo[name];
|
|
130947
|
+
}
|
|
130948
|
+
}
|
|
130517
130949
|
var SIDECAR_VERSION = 1;
|
|
130518
130950
|
function sidecarPath(jsonlPath) {
|
|
130519
130951
|
return `${jsonlPath}.idx.json`;
|
|
@@ -130539,7 +130971,7 @@ function buildSidecar(meta3, cursor, updatedAt) {
|
|
|
130539
130971
|
}
|
|
130540
130972
|
function writeSidecar(jsonlPath, sidecar) {
|
|
130541
130973
|
try {
|
|
130542
|
-
(0,
|
|
130974
|
+
(0, import_fs6.writeFileSync)(sidecarPath(jsonlPath), JSON.stringify(sidecar, null, 2));
|
|
130543
130975
|
} catch (err) {
|
|
130544
130976
|
getLogger2().warn({ jsonlPath, err }, "sidecar: write failed");
|
|
130545
130977
|
}
|
|
@@ -130549,13 +130981,13 @@ function resolveConfigDir(configDir2) {
|
|
|
130549
130981
|
return configDir2.replace(/^~/, (0, import_os4.homedir)());
|
|
130550
130982
|
}
|
|
130551
130983
|
function getProjectsDir(profile) {
|
|
130552
|
-
return (0,
|
|
130984
|
+
return (0, import_path5.join)(resolveConfigDir(profile.configDir), "projects");
|
|
130553
130985
|
}
|
|
130554
130986
|
async function detectDefaultProfile() {
|
|
130555
130987
|
return {
|
|
130556
130988
|
id: "default",
|
|
130557
130989
|
label: "Default",
|
|
130558
|
-
configDir: (0,
|
|
130990
|
+
configDir: (0, import_path5.join)((0, import_os4.homedir)(), ".claude"),
|
|
130559
130991
|
enabled: true,
|
|
130560
130992
|
emoji: "\u{1F916}"
|
|
130561
130993
|
};
|
|
@@ -130564,7 +130996,7 @@ async function loadProfiles(configPath) {
|
|
|
130564
130996
|
const log8 = getLogger2();
|
|
130565
130997
|
try {
|
|
130566
130998
|
const resolved = resolveConfigDir(configPath);
|
|
130567
|
-
const data = await (0, import_promises4.readFile)((0,
|
|
130999
|
+
const data = await (0, import_promises4.readFile)((0, import_path5.join)(resolved, PROFILES_FILE), "utf-8");
|
|
130568
131000
|
const profiles = JSON.parse(data);
|
|
130569
131001
|
log8.debug({ configPath, count: profiles.length }, "profiles: loaded");
|
|
130570
131002
|
return profiles;
|
|
@@ -130574,34 +131006,6 @@ async function loadProfiles(configPath) {
|
|
|
130574
131006
|
return [defaultProfile];
|
|
130575
131007
|
}
|
|
130576
131008
|
}
|
|
130577
|
-
var SYSTEM_TAGS = [
|
|
130578
|
-
"system-reminder",
|
|
130579
|
-
"command-name",
|
|
130580
|
-
"command-message",
|
|
130581
|
-
"command-args",
|
|
130582
|
-
"ide_selection",
|
|
130583
|
-
"ide_opened_file",
|
|
130584
|
-
"local-command-stdout",
|
|
130585
|
-
"local-command-caveat",
|
|
130586
|
-
"retrieval_status",
|
|
130587
|
-
"task_id",
|
|
130588
|
-
"task_type",
|
|
130589
|
-
"task-id",
|
|
130590
|
-
"task-notification",
|
|
130591
|
-
"fast_mode_info",
|
|
130592
|
-
"persisted-output",
|
|
130593
|
-
"tool_use_error",
|
|
130594
|
-
"user-prompt-submit-hook",
|
|
130595
|
-
"thinking",
|
|
130596
|
-
"ask_user",
|
|
130597
|
-
"teammate-message"
|
|
130598
|
-
];
|
|
130599
|
-
var SYSTEM_TAG_RE = new RegExp(`<(${SYSTEM_TAGS.join("|")})[^>]*>[\\s\\S]*?<\\/\\1>`, "g");
|
|
130600
|
-
function cleanSystemTags(text) {
|
|
130601
|
-
return text.replace(SYSTEM_TAG_RE, "").replace(/[^\S\n]+/g, " ").replace(/\n{3,}/g, "\n\n").trim();
|
|
130602
|
-
}
|
|
130603
|
-
var CLAUDE_CODE_PROVIDER = "claude-code";
|
|
130604
|
-
var CODEX_CLI_PROVIDER = "codex-cli";
|
|
130605
131009
|
var CodexCliProvider = class {
|
|
130606
131010
|
name = CODEX_CLI_PROVIDER;
|
|
130607
131011
|
async discover(roots) {
|
|
@@ -130734,7 +131138,7 @@ function reduceCodexEntry(acc, entry, tier) {
|
|
|
130734
131138
|
}
|
|
130735
131139
|
function finalizeCodexMeta(acc, filePath, account, tier) {
|
|
130736
131140
|
if (acc.messageCount === 0) return null;
|
|
130737
|
-
const sessionId = acc.sessionId || (0,
|
|
131141
|
+
const sessionId = acc.sessionId || (0, import_path6.basename)(filePath, ".jsonl");
|
|
130738
131142
|
const projectPath = acc.cwd;
|
|
130739
131143
|
const kind = acc.lastAssistant === null && acc.toolNames.length > 0 ? "task" : "conversation";
|
|
130740
131144
|
return {
|
|
@@ -130746,7 +131150,7 @@ function finalizeCodexMeta(acc, filePath, account, tier) {
|
|
|
130746
131150
|
sessionId,
|
|
130747
131151
|
sessionName: "",
|
|
130748
131152
|
projectPath,
|
|
130749
|
-
projectName:
|
|
131153
|
+
projectName: getShortProjectName3(projectPath),
|
|
130750
131154
|
account,
|
|
130751
131155
|
timestamp: acc.latestTimestamp || (/* @__PURE__ */ new Date()).toISOString(),
|
|
130752
131156
|
messageCount: acc.messageCount,
|
|
@@ -130765,7 +131169,7 @@ function finalizeCodexMeta(acc, filePath, account, tier) {
|
|
|
130765
131169
|
lastPrompt: acc.lastUser?.text || void 0
|
|
130766
131170
|
};
|
|
130767
131171
|
}
|
|
130768
|
-
function
|
|
131172
|
+
function getShortProjectName3(fullPath) {
|
|
130769
131173
|
return fullPath.split("/").filter(Boolean).slice(-3).join("/");
|
|
130770
131174
|
}
|
|
130771
131175
|
async function parseCodexConversation(filePath, account) {
|
|
@@ -130776,7 +131180,7 @@ async function parseCodexConversation(filePath, account) {
|
|
|
130776
131180
|
let cwd = "";
|
|
130777
131181
|
let latestTimestamp = "";
|
|
130778
131182
|
let lastUserText = "";
|
|
130779
|
-
const rl = (0,
|
|
131183
|
+
const rl = (0, import_readline2.createInterface)({ input: (0, import_fs7.createReadStream)(filePath), crlfDelay: Infinity });
|
|
130780
131184
|
try {
|
|
130781
131185
|
for await (const line of rl) {
|
|
130782
131186
|
if (!line.trim()) continue;
|
|
@@ -130813,8 +131217,8 @@ async function parseCodexConversation(filePath, account) {
|
|
|
130813
131217
|
id: filePath,
|
|
130814
131218
|
filePath,
|
|
130815
131219
|
projectPath: cwd,
|
|
130816
|
-
projectName:
|
|
130817
|
-
sessionId: sessionId || (0,
|
|
131220
|
+
projectName: getShortProjectName3(cwd),
|
|
131221
|
+
sessionId: sessionId || (0, import_path6.basename)(filePath, ".jsonl"),
|
|
130818
131222
|
sessionName: "",
|
|
130819
131223
|
messages,
|
|
130820
131224
|
fullText: textParts.join(" "),
|
|
@@ -130886,404 +131290,6 @@ async function discoverJsonlFiles(dirs, onProgress) {
|
|
|
130886
131290
|
log8.debug({ totalFiles: results.length, dirs: dirs.length }, "discovery: complete");
|
|
130887
131291
|
return results;
|
|
130888
131292
|
}
|
|
130889
|
-
function initialConvState() {
|
|
130890
|
-
return {
|
|
130891
|
-
cwd: "",
|
|
130892
|
-
sessionId: "",
|
|
130893
|
-
sessionName: "",
|
|
130894
|
-
latestTimestamp: "",
|
|
130895
|
-
lastPrompt: "",
|
|
130896
|
-
pendingToolUses: {},
|
|
130897
|
-
teamInfo: {}
|
|
130898
|
-
};
|
|
130899
|
-
}
|
|
130900
|
-
function reduceConvLine(state, entry) {
|
|
130901
|
-
if (entry.cwd && !state.cwd) state.cwd = entry.cwd;
|
|
130902
|
-
if (entry.sessionId && !state.sessionId) state.sessionId = entry.sessionId;
|
|
130903
|
-
if (entry.slug && !state.sessionName) state.sessionName = entry.slug;
|
|
130904
|
-
if (entry.timestamp) {
|
|
130905
|
-
const ts2 = entry.timestamp;
|
|
130906
|
-
if (!state.latestTimestamp || ts2 > state.latestTimestamp) state.latestTimestamp = ts2;
|
|
130907
|
-
}
|
|
130908
|
-
const type = entry.type;
|
|
130909
|
-
if (type === "last-prompt") {
|
|
130910
|
-
if (entry.lastPrompt && !state.lastPrompt) state.lastPrompt = entry.lastPrompt;
|
|
130911
|
-
return null;
|
|
130912
|
-
}
|
|
130913
|
-
if (type !== "user" && type !== "assistant") return null;
|
|
130914
|
-
if (entry.isMeta) return null;
|
|
130915
|
-
const msg = entry.message;
|
|
130916
|
-
const toolUseBlocks = extractToolUseBlocks(msg?.content);
|
|
130917
|
-
for (const block of toolUseBlocks) state.pendingToolUses[block.id] = block;
|
|
130918
|
-
const hasToolUseResult = type === "user" && entry.toolUseResult != null;
|
|
130919
|
-
const isToolResultOnly = hasToolUseResult && isOnlyToolResultContent(msg?.content);
|
|
130920
|
-
const content = extractTextContent(msg?.content);
|
|
130921
|
-
const thinking = type === "assistant" ? extractThinking(msg?.content) : null;
|
|
130922
|
-
const hasThinking = !!(thinking?.content || thinking?.signature);
|
|
130923
|
-
if (!(content || isToolResultOnly || toolUseBlocks.length > 0 || hasThinking)) return null;
|
|
130924
|
-
const metadata = {};
|
|
130925
|
-
if (msg?.model) metadata.model = msg.model;
|
|
130926
|
-
if (msg?.stop_reason !== void 0) metadata.stopReason = msg.stop_reason;
|
|
130927
|
-
if (entry.gitBranch) metadata.gitBranch = entry.gitBranch;
|
|
130928
|
-
if (entry.version) metadata.version = entry.version;
|
|
130929
|
-
const usage = msg?.usage;
|
|
130930
|
-
if (usage) {
|
|
130931
|
-
if (usage.input_tokens) metadata.inputTokens = usage.input_tokens;
|
|
130932
|
-
if (usage.output_tokens) metadata.outputTokens = usage.output_tokens;
|
|
130933
|
-
if (usage.cache_read_input_tokens) metadata.cacheReadTokens = usage.cache_read_input_tokens;
|
|
130934
|
-
if (usage.cache_creation_input_tokens)
|
|
130935
|
-
metadata.cacheCreationTokens = usage.cache_creation_input_tokens;
|
|
130936
|
-
}
|
|
130937
|
-
const toolUseNames = extractToolUseNames(msg?.content);
|
|
130938
|
-
if (toolUseNames.length > 0) metadata.toolUses = toolUseNames;
|
|
130939
|
-
if (toolUseBlocks.length > 0) metadata.toolUseBlocks = toolUseBlocks;
|
|
130940
|
-
if (isToolResultOnly) {
|
|
130941
|
-
const pending = new Map(Object.entries(state.pendingToolUses));
|
|
130942
|
-
const toolResultBlocks = extractToolResultBlocks(msg?.content, pending);
|
|
130943
|
-
if (toolResultBlocks.length > 0) metadata.toolResults = toolResultBlocks;
|
|
130944
|
-
}
|
|
130945
|
-
if (entry.teamName) {
|
|
130946
|
-
metadata.teamName = entry.teamName;
|
|
130947
|
-
if (!state.teamInfo[metadata.teamName] && content) {
|
|
130948
|
-
const info = parseTeammateMessageTag(content);
|
|
130949
|
-
if (info) state.teamInfo[metadata.teamName] = info;
|
|
130950
|
-
}
|
|
130951
|
-
}
|
|
130952
|
-
const thinkingContent = thinking?.content || void 0;
|
|
130953
|
-
const thinkingSignature = thinking?.signature || void 0;
|
|
130954
|
-
const hasMetadata = Object.keys(metadata).length > 0;
|
|
130955
|
-
return {
|
|
130956
|
-
role: type,
|
|
130957
|
-
text: content || "",
|
|
130958
|
-
timestamp: entry.timestamp || "",
|
|
130959
|
-
uuid: entry.uuid || void 0,
|
|
130960
|
-
metadata: hasMetadata ? metadata : void 0,
|
|
130961
|
-
isToolResult: isToolResultOnly || void 0,
|
|
130962
|
-
isThinking: thinkingContent || thinkingSignature ? true : void 0,
|
|
130963
|
-
thinkingContent,
|
|
130964
|
-
thinkingSignature,
|
|
130965
|
-
parentUuid: entry.parentUuid !== void 0 ? entry.parentUuid : void 0,
|
|
130966
|
-
requestId: type === "assistant" ? entry.requestId : void 0,
|
|
130967
|
-
promptId: type === "user" ? entry.promptId : void 0,
|
|
130968
|
-
isSidechain: typeof entry.isSidechain === "boolean" ? entry.isSidechain : void 0,
|
|
130969
|
-
permissionMode: type === "user" ? entry.permissionMode : void 0,
|
|
130970
|
-
hasImages: hasImageBlocks(msg?.content) || void 0,
|
|
130971
|
-
attachment: entry.attachment !== void 0 ? entry.attachment : void 0
|
|
130972
|
-
};
|
|
130973
|
-
}
|
|
130974
|
-
function applyTeamInfo(messages, state) {
|
|
130975
|
-
if (Object.keys(state.teamInfo).length === 0) return;
|
|
130976
|
-
for (const m2 of messages) {
|
|
130977
|
-
const name = m2.metadata?.teamName;
|
|
130978
|
-
if (name && state.teamInfo[name] && m2.metadata) m2.metadata.teamInfo = state.teamInfo[name];
|
|
130979
|
-
}
|
|
130980
|
-
}
|
|
130981
|
-
async function parseMeta(filePath, account, tier) {
|
|
130982
|
-
const log8 = getLogger2();
|
|
130983
|
-
log8.trace({ filePath, account, tier: tier.name }, "parseMeta: start");
|
|
130984
|
-
const state = initialReducerState();
|
|
130985
|
-
const fileStream = (0, import_fs7.createReadStream)(filePath);
|
|
130986
|
-
const rl = (0, import_readline2.createInterface)({ input: fileStream, crlfDelay: Infinity });
|
|
130987
|
-
try {
|
|
130988
|
-
for await (const line of rl) {
|
|
130989
|
-
if (!line.trim()) continue;
|
|
130990
|
-
let entry;
|
|
130991
|
-
try {
|
|
130992
|
-
entry = JSON.parse(line);
|
|
130993
|
-
} catch {
|
|
130994
|
-
state.badJsonLines++;
|
|
130995
|
-
continue;
|
|
130996
|
-
}
|
|
130997
|
-
reduceLine(state, entry, tier);
|
|
130998
|
-
}
|
|
130999
|
-
} catch (err) {
|
|
131000
|
-
log8.warn({ filePath, err }, "parseMeta: read failed");
|
|
131001
|
-
return null;
|
|
131002
|
-
}
|
|
131003
|
-
if (state.badJsonLines > 0) {
|
|
131004
|
-
log8.warn(
|
|
131005
|
-
{ filePath, badJsonLines: state.badJsonLines },
|
|
131006
|
-
"parseMeta: skipped malformed JSON lines"
|
|
131007
|
-
);
|
|
131008
|
-
}
|
|
131009
|
-
const meta3 = finalizeMeta(state, filePath, account, tier);
|
|
131010
|
-
if (!meta3) log8.trace({ filePath }, "parseMeta: no messages");
|
|
131011
|
-
return meta3;
|
|
131012
|
-
}
|
|
131013
|
-
async function parseConversation(filePath, account) {
|
|
131014
|
-
const log8 = getLogger2();
|
|
131015
|
-
log8.trace({ filePath, account }, "parseConversation: start");
|
|
131016
|
-
const messages = [];
|
|
131017
|
-
let badJsonLines = 0;
|
|
131018
|
-
const textParts = [];
|
|
131019
|
-
const turnDurations = [];
|
|
131020
|
-
const state = initialConvState();
|
|
131021
|
-
const fileStream = (0, import_fs7.createReadStream)(filePath);
|
|
131022
|
-
const rl = (0, import_readline2.createInterface)({ input: fileStream, crlfDelay: Infinity });
|
|
131023
|
-
try {
|
|
131024
|
-
for await (const line of rl) {
|
|
131025
|
-
if (!line.trim()) continue;
|
|
131026
|
-
let entry;
|
|
131027
|
-
try {
|
|
131028
|
-
entry = JSON.parse(line);
|
|
131029
|
-
} catch {
|
|
131030
|
-
badJsonLines++;
|
|
131031
|
-
continue;
|
|
131032
|
-
}
|
|
131033
|
-
if (entry.type === "system" && entry.subtype === "turn_duration" && typeof entry.durationMs === "number") {
|
|
131034
|
-
turnDurations.push({
|
|
131035
|
-
durationMs: entry.durationMs,
|
|
131036
|
-
messageCount: entry.messageCount || 0,
|
|
131037
|
-
uuid: entry.uuid
|
|
131038
|
-
});
|
|
131039
|
-
continue;
|
|
131040
|
-
}
|
|
131041
|
-
const message = reduceConvLine(state, entry);
|
|
131042
|
-
if (message) {
|
|
131043
|
-
messages.push(message);
|
|
131044
|
-
if (message.text) textParts.push(message.text);
|
|
131045
|
-
}
|
|
131046
|
-
}
|
|
131047
|
-
} catch (err) {
|
|
131048
|
-
log8.warn({ filePath, err }, "parseConversation: read failed");
|
|
131049
|
-
return null;
|
|
131050
|
-
}
|
|
131051
|
-
if (badJsonLines > 0) {
|
|
131052
|
-
log8.warn({ filePath, badJsonLines }, "parseConversation: skipped malformed JSON lines");
|
|
131053
|
-
}
|
|
131054
|
-
if (messages.length === 0) {
|
|
131055
|
-
log8.trace({ filePath }, "parseConversation: no messages");
|
|
131056
|
-
return null;
|
|
131057
|
-
}
|
|
131058
|
-
log8.debug({ filePath, messageCount: messages.length }, "parseConversation: complete");
|
|
131059
|
-
applyTeamInfo(messages, state);
|
|
131060
|
-
return {
|
|
131061
|
-
id: filePath,
|
|
131062
|
-
filePath,
|
|
131063
|
-
projectPath: state.cwd,
|
|
131064
|
-
projectName: getShortProjectName2(state.cwd),
|
|
131065
|
-
sessionId: state.sessionId || (0, import_path6.basename)(filePath, ".jsonl"),
|
|
131066
|
-
sessionName: state.sessionName,
|
|
131067
|
-
messages,
|
|
131068
|
-
fullText: textParts.join(" "),
|
|
131069
|
-
timestamp: state.latestTimestamp || (/* @__PURE__ */ new Date()).toISOString(),
|
|
131070
|
-
messageCount: messages.length,
|
|
131071
|
-
account,
|
|
131072
|
-
turnDurations: turnDurations.length > 0 ? turnDurations : void 0,
|
|
131073
|
-
lastPrompt: state.lastPrompt || void 0
|
|
131074
|
-
};
|
|
131075
|
-
}
|
|
131076
|
-
function extractTextContent(content) {
|
|
131077
|
-
if (!content) return "";
|
|
131078
|
-
if (typeof content === "string") return cleanSystemTags(content);
|
|
131079
|
-
if (Array.isArray(content)) {
|
|
131080
|
-
return content.map((item) => {
|
|
131081
|
-
if (typeof item === "string") return item;
|
|
131082
|
-
if (item?.type === "text" && item?.text) return item.text;
|
|
131083
|
-
if (item?.type === "tool_result" && typeof item?.content === "string") return item.content;
|
|
131084
|
-
return "";
|
|
131085
|
-
}).filter(Boolean).map(cleanSystemTags).join(" ");
|
|
131086
|
-
}
|
|
131087
|
-
return "";
|
|
131088
|
-
}
|
|
131089
|
-
function extractToolUseNames(content) {
|
|
131090
|
-
if (!Array.isArray(content)) return [];
|
|
131091
|
-
return content.filter((item) => item?.type === "tool_use" && item?.name).map((item) => item.name);
|
|
131092
|
-
}
|
|
131093
|
-
function extractToolUseBlocks(content) {
|
|
131094
|
-
if (!Array.isArray(content)) return [];
|
|
131095
|
-
return content.filter((item) => item?.type === "tool_use" && item?.name && item?.id).map((item) => ({
|
|
131096
|
-
id: item.id,
|
|
131097
|
-
name: item.name,
|
|
131098
|
-
input: item.input || {}
|
|
131099
|
-
}));
|
|
131100
|
-
}
|
|
131101
|
-
var TOOL_NAME_TO_TYPE = {
|
|
131102
|
-
Edit: "edit",
|
|
131103
|
-
Write: "write",
|
|
131104
|
-
Read: "read",
|
|
131105
|
-
Bash: "bash",
|
|
131106
|
-
Grep: "grep",
|
|
131107
|
-
Glob: "glob",
|
|
131108
|
-
Agent: "taskAgent",
|
|
131109
|
-
TaskCreate: "taskCreate",
|
|
131110
|
-
TaskUpdate: "taskUpdate"
|
|
131111
|
-
};
|
|
131112
|
-
function extractToolResultBlocks(content, pendingToolUses) {
|
|
131113
|
-
if (!Array.isArray(content)) return [];
|
|
131114
|
-
return content.filter((item) => item?.type === "tool_result" && item?.tool_use_id).map((item) => {
|
|
131115
|
-
const toolName = pendingToolUses.get(item.tool_use_id)?.name ?? "";
|
|
131116
|
-
return {
|
|
131117
|
-
toolUseId: item.tool_use_id,
|
|
131118
|
-
type: TOOL_NAME_TO_TYPE[toolName] ?? "generic",
|
|
131119
|
-
content: typeof item.content === "string" ? { text: item.content } : item.content ?? {},
|
|
131120
|
-
isError: typeof item.is_error === "boolean" ? item.is_error : void 0
|
|
131121
|
-
};
|
|
131122
|
-
});
|
|
131123
|
-
}
|
|
131124
|
-
function collectToolNames(content, toolSet) {
|
|
131125
|
-
if (!Array.isArray(content)) return;
|
|
131126
|
-
for (const item of content) {
|
|
131127
|
-
if (item?.type === "tool_use" && item?.name) {
|
|
131128
|
-
toolSet.add(item.name);
|
|
131129
|
-
}
|
|
131130
|
-
}
|
|
131131
|
-
}
|
|
131132
|
-
function isOnlyToolResultContent(content) {
|
|
131133
|
-
if (!Array.isArray(content)) return false;
|
|
131134
|
-
return content.length > 0 && content.every((item) => item?.type === "tool_result");
|
|
131135
|
-
}
|
|
131136
|
-
function isTeammateContent(content) {
|
|
131137
|
-
const raw2 = typeof content === "string" ? content : Array.isArray(content) ? content.map(
|
|
131138
|
-
(item) => typeof item === "string" ? item : item?.type === "text" ? item.text ?? "" : ""
|
|
131139
|
-
).join("") : "";
|
|
131140
|
-
return raw2.includes("<teammate-message");
|
|
131141
|
-
}
|
|
131142
|
-
function extractThinking(content) {
|
|
131143
|
-
if (!Array.isArray(content)) return { content: "", signature: "" };
|
|
131144
|
-
const blocks = content.filter((item) => item?.type === "thinking");
|
|
131145
|
-
return {
|
|
131146
|
-
content: blocks.map((b2) => b2.thinking).filter(Boolean).join("\n\n"),
|
|
131147
|
-
signature: blocks.map((b2) => b2.signature).filter(Boolean).join("")
|
|
131148
|
-
};
|
|
131149
|
-
}
|
|
131150
|
-
function hasImageBlocks(content) {
|
|
131151
|
-
if (!Array.isArray(content)) return false;
|
|
131152
|
-
return content.some(
|
|
131153
|
-
(item) => item?.type === "image" && (item?.source?.type === "base64" || item?.file?.base64 !== void 0)
|
|
131154
|
-
);
|
|
131155
|
-
}
|
|
131156
|
-
function parseTeammateMessageTag(content) {
|
|
131157
|
-
const match2 = content.match(/<teammate-message\s+([^>]*)>/);
|
|
131158
|
-
if (!match2) return null;
|
|
131159
|
-
const attrs = match2[1];
|
|
131160
|
-
const id = attrs.match(/teammate_id="([^"]*)"/)?.[1];
|
|
131161
|
-
if (!id) return null;
|
|
131162
|
-
const summary = attrs.match(/summary="([^"]*)"/)?.[1];
|
|
131163
|
-
const color = attrs.match(/color="([^"]*)"/)?.[1];
|
|
131164
|
-
return { teammateId: id, summary, color };
|
|
131165
|
-
}
|
|
131166
|
-
function getShortProjectName2(fullPath) {
|
|
131167
|
-
const parts = fullPath.split("/").filter(Boolean);
|
|
131168
|
-
return parts.slice(-3).join("/");
|
|
131169
|
-
}
|
|
131170
|
-
function initialReducerState() {
|
|
131171
|
-
return {
|
|
131172
|
-
sessionId: "",
|
|
131173
|
-
sessionName: "",
|
|
131174
|
-
latestTimestamp: "",
|
|
131175
|
-
cwd: "",
|
|
131176
|
-
teamName: "",
|
|
131177
|
-
model: null,
|
|
131178
|
-
messageCount: 0,
|
|
131179
|
-
lastMessageSender: "user",
|
|
131180
|
-
isTeammate: false,
|
|
131181
|
-
firstUserSeen: false,
|
|
131182
|
-
firstMessage: null,
|
|
131183
|
-
lastMessage: null,
|
|
131184
|
-
lastPrompt: "",
|
|
131185
|
-
pageMessageCount: 0,
|
|
131186
|
-
toolNames: [],
|
|
131187
|
-
previewParts: [],
|
|
131188
|
-
snippetParts: [],
|
|
131189
|
-
previewLength: 0,
|
|
131190
|
-
snippetLength: 0,
|
|
131191
|
-
badJsonLines: 0
|
|
131192
|
-
};
|
|
131193
|
-
}
|
|
131194
|
-
function reduceLine(state, entry, tier) {
|
|
131195
|
-
if (entry.cwd && !state.cwd) state.cwd = entry.cwd;
|
|
131196
|
-
if (entry.sessionId && !state.sessionId) state.sessionId = entry.sessionId;
|
|
131197
|
-
if (entry.slug && !state.sessionName) state.sessionName = entry.slug;
|
|
131198
|
-
if (entry.teamName && !state.teamName) state.teamName = entry.teamName;
|
|
131199
|
-
if (entry.timestamp) {
|
|
131200
|
-
const ts2 = entry.timestamp;
|
|
131201
|
-
if (!state.latestTimestamp || ts2 > state.latestTimestamp) state.latestTimestamp = ts2;
|
|
131202
|
-
}
|
|
131203
|
-
const type = entry.type;
|
|
131204
|
-
if (type === "last-prompt") {
|
|
131205
|
-
if (entry.lastPrompt && !state.lastPrompt) state.lastPrompt = entry.lastPrompt;
|
|
131206
|
-
return;
|
|
131207
|
-
}
|
|
131208
|
-
if (type !== "user" && type !== "assistant") return;
|
|
131209
|
-
if (entry.isMeta) return;
|
|
131210
|
-
const msg = entry.message;
|
|
131211
|
-
if (state.model === null && msg?.model) state.model = msg.model;
|
|
131212
|
-
if (type === "user" && !state.firstUserSeen) {
|
|
131213
|
-
state.firstUserSeen = true;
|
|
131214
|
-
if (isTeammateContent(msg?.content)) state.isTeammate = true;
|
|
131215
|
-
}
|
|
131216
|
-
const content = extractTextContent(msg?.content);
|
|
131217
|
-
const hasToolUseResult = type === "user" && entry.toolUseResult != null;
|
|
131218
|
-
const isOnlyToolResult = hasToolUseResult && isOnlyToolResultContent(msg?.content);
|
|
131219
|
-
const toolSet = new Set(state.toolNames);
|
|
131220
|
-
collectToolNames(msg?.content, toolSet);
|
|
131221
|
-
state.toolNames = Array.from(toolSet);
|
|
131222
|
-
const toolUseBlocks = extractToolUseBlocks(msg?.content);
|
|
131223
|
-
const thinking = type === "assistant" ? extractThinking(msg?.content) : null;
|
|
131224
|
-
const hasThinking = !!(thinking?.content || thinking?.signature);
|
|
131225
|
-
if (content || isOnlyToolResult || toolUseBlocks.length > 0 || hasThinking) {
|
|
131226
|
-
state.pageMessageCount++;
|
|
131227
|
-
}
|
|
131228
|
-
if (content || isOnlyToolResult) {
|
|
131229
|
-
state.messageCount++;
|
|
131230
|
-
state.lastMessageSender = type;
|
|
131231
|
-
if (content) {
|
|
131232
|
-
const ts2 = entry.timestamp || "";
|
|
131233
|
-
if (!state.firstMessage) state.firstMessage = { text: content.slice(0, 200), timestamp: ts2 };
|
|
131234
|
-
state.lastMessage = { text: content.slice(0, 200), timestamp: ts2 };
|
|
131235
|
-
if (state.previewLength < tier.previewMax) {
|
|
131236
|
-
state.previewParts.push(content);
|
|
131237
|
-
state.previewLength += content.length;
|
|
131238
|
-
}
|
|
131239
|
-
if (state.snippetLength < tier.snippetMax) {
|
|
131240
|
-
const remaining = tier.snippetMax - state.snippetLength;
|
|
131241
|
-
const chunk = content.length > remaining ? content.slice(0, remaining) : content;
|
|
131242
|
-
state.snippetParts.push(chunk);
|
|
131243
|
-
state.snippetLength += chunk.length;
|
|
131244
|
-
}
|
|
131245
|
-
}
|
|
131246
|
-
}
|
|
131247
|
-
}
|
|
131248
|
-
function finalizeMeta(state, filePath, account, tier) {
|
|
131249
|
-
if (state.messageCount === 0) return null;
|
|
131250
|
-
const isSubagent = filePath.includes("/subagents/");
|
|
131251
|
-
let parentSessionId = null;
|
|
131252
|
-
if (isSubagent) {
|
|
131253
|
-
const uuidDir = (0, import_path5.dirname)((0, import_path5.dirname)(filePath));
|
|
131254
|
-
parentSessionId = (0, import_path5.join)((0, import_path5.dirname)(uuidDir), `${(0, import_path5.basename)(uuidDir)}.jsonl`);
|
|
131255
|
-
}
|
|
131256
|
-
const projectPath = state.cwd;
|
|
131257
|
-
return {
|
|
131258
|
-
id: filePath,
|
|
131259
|
-
filePath,
|
|
131260
|
-
provider: CLAUDE_CODE_PROVIDER,
|
|
131261
|
-
sessionId: state.sessionId || (0, import_path5.basename)(filePath, ".jsonl"),
|
|
131262
|
-
sessionName: state.sessionName,
|
|
131263
|
-
projectPath,
|
|
131264
|
-
projectName: getShortProjectName3(projectPath),
|
|
131265
|
-
account,
|
|
131266
|
-
timestamp: state.latestTimestamp || (/* @__PURE__ */ new Date()).toISOString(),
|
|
131267
|
-
messageCount: state.messageCount,
|
|
131268
|
-
lastMessageSender: state.lastMessageSender,
|
|
131269
|
-
preview: state.previewParts.join(" ").slice(0, tier.previewMax),
|
|
131270
|
-
contentSnippet: state.snippetParts.join(" "),
|
|
131271
|
-
gitBranch: null,
|
|
131272
|
-
model: state.model,
|
|
131273
|
-
isSubagent,
|
|
131274
|
-
parentSessionId,
|
|
131275
|
-
isTeammate: state.isTeammate,
|
|
131276
|
-
teamName: state.teamName || null,
|
|
131277
|
-
toolNames: state.toolNames,
|
|
131278
|
-
firstMessage: state.firstMessage,
|
|
131279
|
-
lastMessage: state.lastMessage,
|
|
131280
|
-
lastPrompt: state.lastPrompt || void 0
|
|
131281
|
-
};
|
|
131282
|
-
}
|
|
131283
|
-
function getShortProjectName3(fullPath) {
|
|
131284
|
-
const parts = fullPath.split("/").filter(Boolean);
|
|
131285
|
-
return parts.slice(-3).join("/");
|
|
131286
|
-
}
|
|
131287
131293
|
var ThreadbaseProvider = class {
|
|
131288
131294
|
name = CLAUDE_CODE_PROVIDER;
|
|
131289
131295
|
// Roots are passed as "<projectsDir>\0<account>" so the scanner can carry the
|
|
@@ -131352,32 +131358,219 @@ var LRUCache = class {
|
|
|
131352
131358
|
return this.map.size;
|
|
131353
131359
|
}
|
|
131354
131360
|
};
|
|
131361
|
+
var YIELD_EVERY_LINES = 500;
|
|
131362
|
+
async function tailReduce(filePath, startOffset, startLine, state, tier) {
|
|
131363
|
+
const stream = (0, import_fs10.createReadStream)(filePath, { start: startOffset, encoding: "utf8" });
|
|
131364
|
+
let buffer = "";
|
|
131365
|
+
let offset = startOffset;
|
|
131366
|
+
let line = startLine;
|
|
131367
|
+
let parsedLines = 0;
|
|
131368
|
+
let sinceYield = 0;
|
|
131369
|
+
for await (const chunk of stream) {
|
|
131370
|
+
buffer += chunk;
|
|
131371
|
+
let nl;
|
|
131372
|
+
while ((nl = buffer.indexOf("\n")) >= 0) {
|
|
131373
|
+
const lineWithNewline = buffer.slice(0, nl + 1);
|
|
131374
|
+
const text = lineWithNewline.trimEnd();
|
|
131375
|
+
buffer = buffer.slice(nl + 1);
|
|
131376
|
+
if (text.length > 0) {
|
|
131377
|
+
try {
|
|
131378
|
+
reduceLine(state, JSON.parse(text), tier);
|
|
131379
|
+
} catch {
|
|
131380
|
+
state.badJsonLines++;
|
|
131381
|
+
}
|
|
131382
|
+
parsedLines++;
|
|
131383
|
+
}
|
|
131384
|
+
offset += Buffer.byteLength(lineWithNewline, "utf8");
|
|
131385
|
+
line++;
|
|
131386
|
+
if (++sinceYield >= YIELD_EVERY_LINES) {
|
|
131387
|
+
sinceYield = 0;
|
|
131388
|
+
await (0, import_promises8.setImmediate)();
|
|
131389
|
+
}
|
|
131390
|
+
}
|
|
131391
|
+
}
|
|
131392
|
+
return { newOffset: offset, newLine: line, parsedLines, badJsonLines: state.badJsonLines };
|
|
131393
|
+
}
|
|
131394
|
+
var CHECKPOINT_INTERVAL = 500;
|
|
131395
|
+
async function streamMessages(filePath, startOffset, startLine, state, onMessage, onEntry) {
|
|
131396
|
+
const stream = (0, import_fs9.createReadStream)(filePath, { start: startOffset, encoding: "utf8" });
|
|
131397
|
+
let buffer = "";
|
|
131398
|
+
let offset = startOffset;
|
|
131399
|
+
let line = startLine;
|
|
131400
|
+
let sinceYield = 0;
|
|
131401
|
+
for await (const chunk of stream) {
|
|
131402
|
+
buffer += chunk;
|
|
131403
|
+
let nl;
|
|
131404
|
+
while ((nl = buffer.indexOf("\n")) >= 0) {
|
|
131405
|
+
const lineWithNewline = buffer.slice(0, nl + 1);
|
|
131406
|
+
const text = lineWithNewline.trimEnd();
|
|
131407
|
+
buffer = buffer.slice(nl + 1);
|
|
131408
|
+
offset += Buffer.byteLength(lineWithNewline, "utf8");
|
|
131409
|
+
line += 1;
|
|
131410
|
+
if (++sinceYield >= YIELD_EVERY_LINES) {
|
|
131411
|
+
sinceYield = 0;
|
|
131412
|
+
await (0, import_promises7.setImmediate)();
|
|
131413
|
+
}
|
|
131414
|
+
if (text.length === 0) continue;
|
|
131415
|
+
let entry;
|
|
131416
|
+
try {
|
|
131417
|
+
entry = JSON.parse(text);
|
|
131418
|
+
} catch {
|
|
131419
|
+
continue;
|
|
131420
|
+
}
|
|
131421
|
+
if (onEntry?.(entry)) continue;
|
|
131422
|
+
const message = reduceConvLine(state, entry);
|
|
131423
|
+
if (message && onMessage(message, offset, line)) {
|
|
131424
|
+
stream.destroy();
|
|
131425
|
+
return { offset, line };
|
|
131426
|
+
}
|
|
131427
|
+
}
|
|
131428
|
+
}
|
|
131429
|
+
return { offset, line };
|
|
131430
|
+
}
|
|
131431
|
+
async function buildCheckpoints(filePath, interval = CHECKPOINT_INTERVAL, from = null) {
|
|
131432
|
+
const checkpoints = [];
|
|
131433
|
+
const state = from ? from.state : initialConvState();
|
|
131434
|
+
let index = from ? from.messageIndex : 0;
|
|
131435
|
+
await streamMessages(
|
|
131436
|
+
filePath,
|
|
131437
|
+
from?.byteOffset ?? 0,
|
|
131438
|
+
from?.lineNumber ?? 0,
|
|
131439
|
+
state,
|
|
131440
|
+
(_msg, nextOffset, nextLine) => {
|
|
131441
|
+
index += 1;
|
|
131442
|
+
if (index % interval === 0) {
|
|
131443
|
+
checkpoints.push({
|
|
131444
|
+
messageIndex: index,
|
|
131445
|
+
byteOffset: nextOffset,
|
|
131446
|
+
lineNumber: nextLine,
|
|
131447
|
+
state: structuredClone(state)
|
|
131448
|
+
});
|
|
131449
|
+
}
|
|
131450
|
+
return false;
|
|
131451
|
+
}
|
|
131452
|
+
);
|
|
131453
|
+
return checkpoints;
|
|
131454
|
+
}
|
|
131455
|
+
async function readPage(filePath, total, options, floor) {
|
|
131456
|
+
const beforeIndex = options.beforeIndex ?? total;
|
|
131457
|
+
const fromIndex = Math.max(0, beforeIndex - options.limit);
|
|
131458
|
+
const state = floor ? structuredClone(floor.state) : initialConvState();
|
|
131459
|
+
const startOffset = floor ? floor.byteOffset : 0;
|
|
131460
|
+
const startLine = floor ? floor.lineNumber : 0;
|
|
131461
|
+
let index = floor ? floor.messageIndex : 0;
|
|
131462
|
+
const window2 = [];
|
|
131463
|
+
await streamMessages(filePath, startOffset, startLine, state, (message) => {
|
|
131464
|
+
const current = index;
|
|
131465
|
+
index += 1;
|
|
131466
|
+
if (current >= fromIndex && current < beforeIndex) window2.push(message);
|
|
131467
|
+
return index >= beforeIndex;
|
|
131468
|
+
});
|
|
131469
|
+
applyTeamInfo(window2, state);
|
|
131470
|
+
return { messages: window2, total, fromIndex };
|
|
131471
|
+
}
|
|
131472
|
+
async function foldTail(filePath, resume) {
|
|
131473
|
+
const messages = [];
|
|
131474
|
+
const textParts = [];
|
|
131475
|
+
const turnDurations = [];
|
|
131476
|
+
const end = await streamMessages(
|
|
131477
|
+
filePath,
|
|
131478
|
+
resume.offset,
|
|
131479
|
+
resume.line,
|
|
131480
|
+
resume.state,
|
|
131481
|
+
(message) => {
|
|
131482
|
+
messages.push(message);
|
|
131483
|
+
if (message.text) textParts.push(message.text);
|
|
131484
|
+
return false;
|
|
131485
|
+
},
|
|
131486
|
+
(entry) => {
|
|
131487
|
+
if (entry.type === "system" && entry.subtype === "turn_duration" && typeof entry.durationMs === "number") {
|
|
131488
|
+
turnDurations.push({
|
|
131489
|
+
durationMs: entry.durationMs,
|
|
131490
|
+
messageCount: entry.messageCount || 0,
|
|
131491
|
+
uuid: entry.uuid
|
|
131492
|
+
});
|
|
131493
|
+
return true;
|
|
131494
|
+
}
|
|
131495
|
+
return false;
|
|
131496
|
+
}
|
|
131497
|
+
);
|
|
131498
|
+
return { messages, textParts, turnDurations, end };
|
|
131499
|
+
}
|
|
131500
|
+
function assemble(filePath, account, messages, fullText, turnDurations, state) {
|
|
131501
|
+
return {
|
|
131502
|
+
id: filePath,
|
|
131503
|
+
filePath,
|
|
131504
|
+
projectPath: state.cwd,
|
|
131505
|
+
projectName: getShortProjectName2(state.cwd),
|
|
131506
|
+
sessionId: state.sessionId || (0, import_path8.basename)(filePath, ".jsonl"),
|
|
131507
|
+
sessionName: state.sessionName,
|
|
131508
|
+
messages,
|
|
131509
|
+
fullText,
|
|
131510
|
+
timestamp: state.latestTimestamp || (/* @__PURE__ */ new Date()).toISOString(),
|
|
131511
|
+
messageCount: messages.length,
|
|
131512
|
+
account,
|
|
131513
|
+
turnDurations: turnDurations.length > 0 ? turnDurations : void 0,
|
|
131514
|
+
lastPrompt: state.lastPrompt || void 0
|
|
131515
|
+
};
|
|
131516
|
+
}
|
|
131517
|
+
async function parseConversationResumable(filePath, account) {
|
|
131518
|
+
const resume = { state: initialConvState(), offset: 0, line: 0 };
|
|
131519
|
+
const { messages, textParts, turnDurations, end } = await foldTail(filePath, resume);
|
|
131520
|
+
if (messages.length === 0) return null;
|
|
131521
|
+
applyTeamInfo(messages, resume.state);
|
|
131522
|
+
const conversation = assemble(
|
|
131523
|
+
filePath,
|
|
131524
|
+
account,
|
|
131525
|
+
messages,
|
|
131526
|
+
textParts.join(" "),
|
|
131527
|
+
turnDurations,
|
|
131528
|
+
resume.state
|
|
131529
|
+
);
|
|
131530
|
+
return { conversation, resume: { state: resume.state, offset: end.offset, line: end.line } };
|
|
131531
|
+
}
|
|
131532
|
+
async function extendConversation(previous, resume, filePath, account) {
|
|
131533
|
+
const { messages: fresh, textParts, turnDurations, end } = await foldTail(filePath, resume);
|
|
131534
|
+
const messages = fresh.length > 0 ? previous.messages.concat(fresh) : previous.messages;
|
|
131535
|
+
applyTeamInfo(messages, resume.state);
|
|
131536
|
+
const fullText = textParts.length === 0 ? previous.fullText : previous.fullText ? `${previous.fullText} ${textParts.join(" ")}` : textParts.join(" ");
|
|
131537
|
+
const allTurnDurations = (previous.turnDurations ?? []).concat(turnDurations);
|
|
131538
|
+
const conversation = assemble(
|
|
131539
|
+
filePath,
|
|
131540
|
+
account,
|
|
131541
|
+
messages,
|
|
131542
|
+
fullText,
|
|
131543
|
+
allTurnDurations,
|
|
131544
|
+
resume.state
|
|
131545
|
+
);
|
|
131546
|
+
return { conversation, resume: { state: resume.state, offset: end.offset, line: end.line } };
|
|
131547
|
+
}
|
|
131355
131548
|
var FP_BYTES = 4096;
|
|
131356
131549
|
function fingerprint(filePath, size) {
|
|
131357
131550
|
const hash2 = (0, import_crypto2.createHash)("sha1");
|
|
131358
131551
|
hash2.update(String(size));
|
|
131359
|
-
const fd = (0,
|
|
131552
|
+
const fd = (0, import_fs11.openSync)(filePath, "r");
|
|
131360
131553
|
try {
|
|
131361
131554
|
const head = Buffer.alloc(Math.min(FP_BYTES, size));
|
|
131362
131555
|
if (head.length > 0) {
|
|
131363
|
-
(0,
|
|
131556
|
+
(0, import_fs11.readSync)(fd, head, 0, head.length, 0);
|
|
131364
131557
|
hash2.update(head);
|
|
131365
131558
|
}
|
|
131366
131559
|
if (size > FP_BYTES) {
|
|
131367
131560
|
const tailLen = Math.min(FP_BYTES, size);
|
|
131368
131561
|
const tail = Buffer.alloc(tailLen);
|
|
131369
|
-
(0,
|
|
131562
|
+
(0, import_fs11.readSync)(fd, tail, 0, tailLen, size - tailLen);
|
|
131370
131563
|
hash2.update(tail);
|
|
131371
131564
|
}
|
|
131372
131565
|
} finally {
|
|
131373
|
-
(0,
|
|
131566
|
+
(0, import_fs11.closeSync)(fd);
|
|
131374
131567
|
}
|
|
131375
131568
|
return hash2.digest("hex");
|
|
131376
131569
|
}
|
|
131377
131570
|
function classify(filePath, existing) {
|
|
131378
131571
|
let stat42;
|
|
131379
131572
|
try {
|
|
131380
|
-
const s3 = (0,
|
|
131573
|
+
const s3 = (0, import_fs11.statSync)(filePath);
|
|
131381
131574
|
stat42 = { size: s3.size, mtimeMs: s3.mtimeMs };
|
|
131382
131575
|
} catch {
|
|
131383
131576
|
return { change: "vanished" };
|
|
@@ -131407,7 +131600,7 @@ async function parseMetaWithProvider(provider, filePath, account, tier) {
|
|
|
131407
131600
|
const log8 = getLogger2();
|
|
131408
131601
|
const acc = provider.createEmptyAccumulator();
|
|
131409
131602
|
const rl = (0, import_readline3.createInterface)({
|
|
131410
|
-
input: (0,
|
|
131603
|
+
input: (0, import_fs12.createReadStream)(filePath),
|
|
131411
131604
|
crlfDelay: Infinity
|
|
131412
131605
|
});
|
|
131413
131606
|
try {
|
|
@@ -131630,7 +131823,7 @@ function hasColumn(db, table, column) {
|
|
|
131630
131823
|
}
|
|
131631
131824
|
function openDatabase(dbPath) {
|
|
131632
131825
|
if (dbPath !== ":memory:") {
|
|
131633
|
-
(0,
|
|
131826
|
+
(0, import_fs13.mkdirSync)((0, import_path9.dirname)(dbPath), { recursive: true });
|
|
131634
131827
|
}
|
|
131635
131828
|
const db = new import_better_sqlite3.default(dbPath);
|
|
131636
131829
|
db.pragma("journal_mode = WAL");
|
|
@@ -131656,7 +131849,7 @@ async function discoverJsonlFilesGated(dirs, files, scannedDirs, options = {}) {
|
|
|
131656
131849
|
for (const projectDir of resolved.entries) {
|
|
131657
131850
|
let dirStat;
|
|
131658
131851
|
try {
|
|
131659
|
-
dirStat = await (0,
|
|
131852
|
+
dirStat = await (0, import_promises9.stat)(projectDir);
|
|
131660
131853
|
} catch {
|
|
131661
131854
|
scannedDirs.remove(projectDir);
|
|
131662
131855
|
continue;
|
|
@@ -131694,7 +131887,7 @@ async function discoverJsonlFilesGated(dirs, files, scannedDirs, options = {}) {
|
|
|
131694
131887
|
async function resolveProjectDirs(projectsDir, scannedDirs) {
|
|
131695
131888
|
let rootStat;
|
|
131696
131889
|
try {
|
|
131697
|
-
rootStat = await (0,
|
|
131890
|
+
rootStat = await (0, import_promises9.stat)(projectsDir);
|
|
131698
131891
|
} catch {
|
|
131699
131892
|
return null;
|
|
131700
131893
|
}
|
|
@@ -131704,7 +131897,7 @@ async function resolveProjectDirs(projectsDir, scannedDirs) {
|
|
|
131704
131897
|
}
|
|
131705
131898
|
let entries;
|
|
131706
131899
|
try {
|
|
131707
|
-
entries = (await (0,
|
|
131900
|
+
entries = (await (0, import_promises9.readdir)(projectsDir, { withFileTypes: true })).filter((e) => e.isDirectory()).map((e) => joinPath(projectsDir, e.name));
|
|
131708
131901
|
} catch {
|
|
131709
131902
|
return null;
|
|
131710
131903
|
}
|
|
@@ -131717,98 +131910,6 @@ function dirnameOf(filePath) {
|
|
|
131717
131910
|
function joinPath(dir, name) {
|
|
131718
131911
|
return dir.endsWith("/") ? `${dir}${name}` : `${dir}/${name}`;
|
|
131719
131912
|
}
|
|
131720
|
-
async function tailReduce(filePath, startOffset, startLine, state, tier) {
|
|
131721
|
-
const stream = (0, import_fs12.createReadStream)(filePath, { start: startOffset, encoding: "utf8" });
|
|
131722
|
-
let buffer = "";
|
|
131723
|
-
let offset = startOffset;
|
|
131724
|
-
let line = startLine;
|
|
131725
|
-
let parsedLines = 0;
|
|
131726
|
-
for await (const chunk of stream) {
|
|
131727
|
-
buffer += chunk;
|
|
131728
|
-
let nl;
|
|
131729
|
-
while ((nl = buffer.indexOf("\n")) >= 0) {
|
|
131730
|
-
const lineWithNewline = buffer.slice(0, nl + 1);
|
|
131731
|
-
const text = lineWithNewline.trimEnd();
|
|
131732
|
-
buffer = buffer.slice(nl + 1);
|
|
131733
|
-
if (text.length > 0) {
|
|
131734
|
-
try {
|
|
131735
|
-
reduceLine(state, JSON.parse(text), tier);
|
|
131736
|
-
} catch {
|
|
131737
|
-
state.badJsonLines++;
|
|
131738
|
-
}
|
|
131739
|
-
parsedLines++;
|
|
131740
|
-
}
|
|
131741
|
-
offset += Buffer.byteLength(lineWithNewline, "utf8");
|
|
131742
|
-
line++;
|
|
131743
|
-
}
|
|
131744
|
-
}
|
|
131745
|
-
return { newOffset: offset, newLine: line, parsedLines, badJsonLines: state.badJsonLines };
|
|
131746
|
-
}
|
|
131747
|
-
var CHECKPOINT_INTERVAL = 500;
|
|
131748
|
-
async function streamMessages(filePath, startOffset, startLine, state, onMessage) {
|
|
131749
|
-
const stream = (0, import_fs13.createReadStream)(filePath, { start: startOffset, encoding: "utf8" });
|
|
131750
|
-
let buffer = "";
|
|
131751
|
-
let offset = startOffset;
|
|
131752
|
-
let line = startLine;
|
|
131753
|
-
for await (const chunk of stream) {
|
|
131754
|
-
buffer += chunk;
|
|
131755
|
-
let nl;
|
|
131756
|
-
while ((nl = buffer.indexOf("\n")) >= 0) {
|
|
131757
|
-
const lineWithNewline = buffer.slice(0, nl + 1);
|
|
131758
|
-
const text = lineWithNewline.trimEnd();
|
|
131759
|
-
buffer = buffer.slice(nl + 1);
|
|
131760
|
-
offset += Buffer.byteLength(lineWithNewline, "utf8");
|
|
131761
|
-
line += 1;
|
|
131762
|
-
if (text.length === 0) continue;
|
|
131763
|
-
let entry;
|
|
131764
|
-
try {
|
|
131765
|
-
entry = JSON.parse(text);
|
|
131766
|
-
} catch {
|
|
131767
|
-
continue;
|
|
131768
|
-
}
|
|
131769
|
-
const message = reduceConvLine(state, entry);
|
|
131770
|
-
if (message && onMessage(message, offset, line)) {
|
|
131771
|
-
stream.destroy();
|
|
131772
|
-
return;
|
|
131773
|
-
}
|
|
131774
|
-
}
|
|
131775
|
-
}
|
|
131776
|
-
}
|
|
131777
|
-
async function buildCheckpoints(filePath, interval = CHECKPOINT_INTERVAL) {
|
|
131778
|
-
const checkpoints = [];
|
|
131779
|
-
const state = initialConvState();
|
|
131780
|
-
let index = 0;
|
|
131781
|
-
await streamMessages(filePath, 0, 0, state, (_msg, nextOffset, nextLine) => {
|
|
131782
|
-
index += 1;
|
|
131783
|
-
if (index % interval === 0) {
|
|
131784
|
-
checkpoints.push({
|
|
131785
|
-
messageIndex: index,
|
|
131786
|
-
byteOffset: nextOffset,
|
|
131787
|
-
lineNumber: nextLine,
|
|
131788
|
-
state: structuredClone(state)
|
|
131789
|
-
});
|
|
131790
|
-
}
|
|
131791
|
-
return false;
|
|
131792
|
-
});
|
|
131793
|
-
return checkpoints;
|
|
131794
|
-
}
|
|
131795
|
-
async function readPage(filePath, total, options, floor) {
|
|
131796
|
-
const beforeIndex = options.beforeIndex ?? total;
|
|
131797
|
-
const fromIndex = Math.max(0, beforeIndex - options.limit);
|
|
131798
|
-
const state = floor ? structuredClone(floor.state) : initialConvState();
|
|
131799
|
-
const startOffset = floor ? floor.byteOffset : 0;
|
|
131800
|
-
const startLine = floor ? floor.lineNumber : 0;
|
|
131801
|
-
let index = floor ? floor.messageIndex : 0;
|
|
131802
|
-
const window2 = [];
|
|
131803
|
-
await streamMessages(filePath, startOffset, startLine, state, (message) => {
|
|
131804
|
-
const current = index;
|
|
131805
|
-
index += 1;
|
|
131806
|
-
if (current >= fromIndex && current < beforeIndex) window2.push(message);
|
|
131807
|
-
return index >= beforeIndex;
|
|
131808
|
-
});
|
|
131809
|
-
applyTeamInfo(window2, state);
|
|
131810
|
-
return { messages: window2, total, fromIndex };
|
|
131811
|
-
}
|
|
131812
131913
|
var CheckpointsRepo = class {
|
|
131813
131914
|
constructor(db) {
|
|
131814
131915
|
this.db = db;
|
|
@@ -131828,6 +131929,22 @@ var CheckpointsRepo = class {
|
|
|
131828
131929
|
});
|
|
131829
131930
|
tx();
|
|
131830
131931
|
}
|
|
131932
|
+
// Insert checkpoints without touching existing rows. Appends never invalidate
|
|
131933
|
+
// the chain covering the immutable prefix (Kafka sparse-index style); rows are
|
|
131934
|
+
// only ever removed on truncation/replace or deletion.
|
|
131935
|
+
append(sourcePath, checkpoints) {
|
|
131936
|
+
const tx = this.db.transaction(() => {
|
|
131937
|
+
const insert = this.db.prepare(
|
|
131938
|
+
`INSERT INTO message_checkpoints
|
|
131939
|
+
(source_path, message_index, byte_offset, line_number, parser_state)
|
|
131940
|
+
VALUES (?, ?, ?, ?, ?)`
|
|
131941
|
+
);
|
|
131942
|
+
for (const c of checkpoints) {
|
|
131943
|
+
insert.run(sourcePath, c.messageIndex, c.byteOffset, c.lineNumber, JSON.stringify(c.state));
|
|
131944
|
+
}
|
|
131945
|
+
});
|
|
131946
|
+
tx();
|
|
131947
|
+
}
|
|
131831
131948
|
// The latest checkpoint at or before `messageIndex`, or null if none (read
|
|
131832
131949
|
// from the file start). Lets a page seek to the nearest prior anchor.
|
|
131833
131950
|
floor(sourcePath, messageIndex) {
|
|
@@ -131839,6 +131956,17 @@ var CheckpointsRepo = class {
|
|
|
131839
131956
|
).get(sourcePath, messageIndex);
|
|
131840
131957
|
return row ? toCheckpoint(row) : null;
|
|
131841
131958
|
}
|
|
131959
|
+
// The highest-index checkpoint for a file, or null if none. The resume point
|
|
131960
|
+
// for extending the chain after an append.
|
|
131961
|
+
last(sourcePath) {
|
|
131962
|
+
const row = this.db.prepare(
|
|
131963
|
+
`SELECT message_index, byte_offset, line_number, parser_state
|
|
131964
|
+
FROM message_checkpoints
|
|
131965
|
+
WHERE source_path = ?
|
|
131966
|
+
ORDER BY message_index DESC LIMIT 1`
|
|
131967
|
+
).get(sourcePath);
|
|
131968
|
+
return row ? toCheckpoint(row) : null;
|
|
131969
|
+
}
|
|
131842
131970
|
count(sourcePath) {
|
|
131843
131971
|
return this.db.prepare("SELECT COUNT(*) AS n FROM message_checkpoints WHERE source_path = ?").get(sourcePath).n;
|
|
131844
131972
|
}
|
|
@@ -131870,7 +131998,7 @@ var ConversationFilesRepo = class {
|
|
|
131870
131998
|
const info = this.db.prepare(
|
|
131871
131999
|
`INSERT INTO conversation_files (absolute_path, parent_dir, file_name, account)
|
|
131872
132000
|
VALUES (?, ?, ?, ?)`
|
|
131873
|
-
).run(absolutePath, (0,
|
|
132001
|
+
).run(absolutePath, (0, import_path10.dirname)(absolutePath), (0, import_path10.basename)(absolutePath), account);
|
|
131874
132002
|
return Number(info.lastInsertRowid);
|
|
131875
132003
|
}
|
|
131876
132004
|
// Advance the cursor + persisted reducer state after a successful index pass.
|
|
@@ -132221,6 +132349,9 @@ var PersistentEngine = class {
|
|
|
132221
132349
|
// restart just means the first few post-restart scans don't force an early
|
|
132222
132350
|
// backstop pass, which is harmless (watermarks themselves persist in the DB).
|
|
132223
132351
|
scanCount = 0;
|
|
132352
|
+
// In-flight checkpoint build/extension per file, so concurrent getPage
|
|
132353
|
+
// callers share one stream instead of each walking the file.
|
|
132354
|
+
checkpointBuilds = /* @__PURE__ */ new Map();
|
|
132224
132355
|
constructor(dbPath, options = {}) {
|
|
132225
132356
|
this.db = openDatabase(dbPath);
|
|
132226
132357
|
this.files = new ConversationFilesRepo(this.db);
|
|
@@ -132273,7 +132404,7 @@ var PersistentEngine = class {
|
|
|
132273
132404
|
const batch = discovered.slice(i, i + BATCH_SIZE);
|
|
132274
132405
|
const results = await Promise.all(
|
|
132275
132406
|
batch.map(async ({ filePath, account, provider }) => {
|
|
132276
|
-
const meta3 = await this.indexFile(
|
|
132407
|
+
const { meta: meta3 } = await this.indexFile(
|
|
132277
132408
|
filePath,
|
|
132278
132409
|
account,
|
|
132279
132410
|
tier.name,
|
|
@@ -132308,7 +132439,9 @@ var PersistentEngine = class {
|
|
|
132308
132439
|
// unchanged → return the stored summary; appended → resume the fold and read
|
|
132309
132440
|
// only new bytes; reindex/force → fold from offset 0. Writes the summary +
|
|
132310
132441
|
// cursor + reducer state in one transaction so a crash never leaves a
|
|
132311
|
-
// half-written row or an over-advanced cursor.
|
|
132442
|
+
// half-written row or an over-advanced cursor. Returns the classification
|
|
132443
|
+
// alongside the meta so callers (refreshFile) can keep, extend, or evict
|
|
132444
|
+
// their own per-file caches without re-stat'ing the file (racy) themselves.
|
|
132312
132445
|
async indexFile(filePath, account, tierName, customTiers, resolveGitBranch, force = false, provider) {
|
|
132313
132446
|
const log8 = getLogger2();
|
|
132314
132447
|
const tier = resolveTier(tierName, customTiers);
|
|
@@ -132316,13 +132449,21 @@ var PersistentEngine = class {
|
|
|
132316
132449
|
const { change, stat: stat42 } = classify(filePath, existing);
|
|
132317
132450
|
if (change === "vanished" || !stat42) {
|
|
132318
132451
|
this.markDeleted(filePath);
|
|
132319
|
-
return null;
|
|
132452
|
+
return { meta: null, change: "vanished" };
|
|
132320
132453
|
}
|
|
132321
132454
|
if (change === "unchanged" && !force) {
|
|
132322
|
-
return this.conversations.getBySourcePath(filePath);
|
|
132455
|
+
return { meta: this.conversations.getBySourcePath(filePath), change };
|
|
132323
132456
|
}
|
|
132324
132457
|
if (provider && provider.name !== CLAUDE_CODE_PROVIDER) {
|
|
132325
|
-
|
|
132458
|
+
const meta22 = await this.indexFileWithProvider(
|
|
132459
|
+
provider,
|
|
132460
|
+
filePath,
|
|
132461
|
+
account,
|
|
132462
|
+
tier,
|
|
132463
|
+
stat42,
|
|
132464
|
+
resolveGitBranch
|
|
132465
|
+
);
|
|
132466
|
+
return { meta: meta22, change };
|
|
132326
132467
|
}
|
|
132327
132468
|
const resume = change === "appended" && !force && existing?.reducer_state;
|
|
132328
132469
|
const state = resume ? JSON.parse(existing.reducer_state) : initialReducerState();
|
|
@@ -132333,12 +132474,12 @@ var PersistentEngine = class {
|
|
|
132333
132474
|
result = await tailReduce(filePath, startOffset, startLine, state, tier);
|
|
132334
132475
|
} catch (err) {
|
|
132335
132476
|
log8.warn({ filePath, err }, "persistent: tail read failed");
|
|
132336
|
-
return null;
|
|
132477
|
+
return { meta: null, change };
|
|
132337
132478
|
}
|
|
132338
132479
|
const meta3 = finalizeMeta(state, filePath, account, tier);
|
|
132339
132480
|
if (!meta3) {
|
|
132340
132481
|
this.markDeleted(filePath);
|
|
132341
|
-
return null;
|
|
132482
|
+
return { meta: null, change };
|
|
132342
132483
|
}
|
|
132343
132484
|
meta3.gitBranch = resolveGitBranch(meta3.projectPath);
|
|
132344
132485
|
const fp = stat42.size > 0 ? fingerprint(filePath, stat42.size) : null;
|
|
@@ -132346,7 +132487,7 @@ var PersistentEngine = class {
|
|
|
132346
132487
|
const upsert = this.db.transaction(() => {
|
|
132347
132488
|
this.conversations.upsert(fileId, meta3, state.pageMessageCount);
|
|
132348
132489
|
this.fts.upsert(meta3);
|
|
132349
|
-
this.checkpoints.remove(filePath);
|
|
132490
|
+
if (!resume) this.checkpoints.remove(filePath);
|
|
132350
132491
|
this.files.updateCursor(fileId, {
|
|
132351
132492
|
sizeBytes: stat42.size,
|
|
132352
132493
|
mtimeMs: stat42.mtimeMs,
|
|
@@ -132379,7 +132520,7 @@ var PersistentEngine = class {
|
|
|
132379
132520
|
{ filePath, change, bytesRead: result.newOffset - startOffset, msgs: meta3.messageCount },
|
|
132380
132521
|
"persistent: indexed file"
|
|
132381
132522
|
);
|
|
132382
|
-
return meta3;
|
|
132523
|
+
return { meta: meta3, change };
|
|
132383
132524
|
}
|
|
132384
132525
|
// Index a non-Threadbase provider file: full reparse from offset 0 through the
|
|
132385
132526
|
// provider's reducer/finalize, then the same upsert + FTS write + cursor bump
|
|
@@ -132479,15 +132620,34 @@ var PersistentEngine = class {
|
|
|
132479
132620
|
return { messages: messages.slice(fromIndex2, beforeIndex2), total: total2, fromIndex: fromIndex2 };
|
|
132480
132621
|
}
|
|
132481
132622
|
const total = this.conversations.pageMessageCount(filePath);
|
|
132482
|
-
|
|
132483
|
-
const built = await buildCheckpoints(filePath);
|
|
132484
|
-
if (built.length > 0) this.checkpoints.replaceAll(filePath, built);
|
|
132485
|
-
}
|
|
132623
|
+
await this.ensureCheckpoints(filePath, total);
|
|
132486
132624
|
const beforeIndex = options.beforeIndex ?? total;
|
|
132487
132625
|
const fromIndex = Math.max(0, beforeIndex - options.limit);
|
|
132488
132626
|
const floor = this.checkpoints.floor(filePath, fromIndex);
|
|
132489
132627
|
return readPage(filePath, total, options, floor);
|
|
132490
132628
|
}
|
|
132629
|
+
// Build or extend the checkpoint chain so it covers `total` messages. Cold
|
|
132630
|
+
// file → full build; a file that grew → extend from the last persisted
|
|
132631
|
+
// checkpoint (reads only past its offset, never the prefix). Single-flighted
|
|
132632
|
+
// per path: concurrent getPage callers await the same build instead of
|
|
132633
|
+
// streaming the file in parallel.
|
|
132634
|
+
ensureCheckpoints(filePath, total) {
|
|
132635
|
+
if (total <= CHECKPOINT_INTERVAL) return Promise.resolve();
|
|
132636
|
+
const inFlight = this.checkpointBuilds.get(filePath);
|
|
132637
|
+
if (inFlight) return inFlight;
|
|
132638
|
+
const build2 = (async () => {
|
|
132639
|
+
const last = this.checkpoints.last(filePath);
|
|
132640
|
+
if (last && total < last.messageIndex + CHECKPOINT_INTERVAL) return;
|
|
132641
|
+
const fresh = await buildCheckpoints(filePath, CHECKPOINT_INTERVAL, last);
|
|
132642
|
+
if (fresh.length === 0) return;
|
|
132643
|
+
if (last) this.checkpoints.append(filePath, fresh);
|
|
132644
|
+
else this.checkpoints.replaceAll(filePath, fresh);
|
|
132645
|
+
})().finally(() => {
|
|
132646
|
+
if (this.checkpointBuilds.get(filePath) === build2) this.checkpointBuilds.delete(filePath);
|
|
132647
|
+
});
|
|
132648
|
+
this.checkpointBuilds.set(filePath, build2);
|
|
132649
|
+
return build2;
|
|
132650
|
+
}
|
|
132491
132651
|
};
|
|
132492
132652
|
var EXCLUDED_SEGMENTS2 = ["/memory/", "/tool-results/"];
|
|
132493
132653
|
var FileWatcher = class {
|
|
@@ -132586,6 +132746,8 @@ function defaultDbPath() {
|
|
|
132586
132746
|
}
|
|
132587
132747
|
var ConversationScanner = class {
|
|
132588
132748
|
metadataCache = /* @__PURE__ */ new Map();
|
|
132749
|
+
// Parsed conversations plus (persistent claude-code entries only) the resume
|
|
132750
|
+
// point that lets refreshFile extend them in place when the file grows.
|
|
132589
132751
|
conversationLRU;
|
|
132590
132752
|
// session_id is NOT unique, so this maps a sessionId to every active meta that
|
|
132591
132753
|
// carries it. Resolution picks deterministically (newest timestamp, then path
|
|
@@ -132617,7 +132779,9 @@ var ConversationScanner = class {
|
|
|
132617
132779
|
// can't hit a closed DB (the watch-mode half of Bug #4).
|
|
132618
132780
|
inFlightReconcile = null;
|
|
132619
132781
|
constructor(options) {
|
|
132620
|
-
this.conversationLRU = new LRUCache(
|
|
132782
|
+
this.conversationLRU = new LRUCache(
|
|
132783
|
+
options?.conversationCacheSize ?? 5
|
|
132784
|
+
);
|
|
132621
132785
|
if (options?.persistent === false) {
|
|
132622
132786
|
this.dbPath = null;
|
|
132623
132787
|
this.sidecarEnabled = false;
|
|
@@ -132874,7 +133038,7 @@ var ConversationScanner = class {
|
|
|
132874
133038
|
const cached3 = this.conversationLRU.get(id);
|
|
132875
133039
|
if (cached3) {
|
|
132876
133040
|
log8.debug({ id }, "getConversation: cache hit");
|
|
132877
|
-
return cached3;
|
|
133041
|
+
return cached3.conversation;
|
|
132878
133042
|
}
|
|
132879
133043
|
const meta3 = this.persistent ? this.engine().getByIdOrSession(id) : this.metadataCache.get(id) ?? this.resolveSessionId(id);
|
|
132880
133044
|
if (!meta3) {
|
|
@@ -132883,9 +133047,14 @@ var ConversationScanner = class {
|
|
|
132883
133047
|
}
|
|
132884
133048
|
log8.debug({ id, filePath: meta3.filePath }, "getConversation: cache miss, parsing");
|
|
132885
133049
|
try {
|
|
133050
|
+
if (this.persistent && meta3.provider !== CODEX_CLI_PROVIDER) {
|
|
133051
|
+
const parsed = await parseConversationResumable(meta3.filePath, meta3.account);
|
|
133052
|
+
if (parsed) this.conversationLRU.set(id, parsed);
|
|
133053
|
+
return parsed?.conversation ?? null;
|
|
133054
|
+
}
|
|
132886
133055
|
const conversation = meta3.provider === CODEX_CLI_PROVIDER ? await parseCodexConversation(meta3.filePath, meta3.account) : await parseConversation(meta3.filePath, meta3.account);
|
|
132887
133056
|
if (conversation) {
|
|
132888
|
-
this.conversationLRU.set(id, conversation);
|
|
133057
|
+
this.conversationLRU.set(id, { conversation });
|
|
132889
133058
|
}
|
|
132890
133059
|
return conversation;
|
|
132891
133060
|
} catch (err) {
|
|
@@ -132957,20 +133126,30 @@ var ConversationScanner = class {
|
|
|
132957
133126
|
// not seen before. Returns the fresh ConversationMeta, or null when the file
|
|
132958
133127
|
// no longer parses (missing/empty) — in which case any prior entry for it is
|
|
132959
133128
|
// dropped from all indexes.
|
|
132960
|
-
|
|
133129
|
+
//
|
|
133130
|
+
// Single-flighted per path: concurrent callers (stacked client retries, a
|
|
133131
|
+
// watcher tick racing a caller) await the one in-flight refresh instead of
|
|
133132
|
+
// each re-reading the file.
|
|
133133
|
+
refreshesInFlight = /* @__PURE__ */ new Map();
|
|
133134
|
+
refreshFile(filePath, account) {
|
|
133135
|
+
const inFlight = this.refreshesInFlight.get(filePath);
|
|
133136
|
+
if (inFlight) return inFlight;
|
|
133137
|
+
const refresh = this.doRefreshFile(filePath, account).finally(() => {
|
|
133138
|
+
if (this.refreshesInFlight.get(filePath) === refresh) {
|
|
133139
|
+
this.refreshesInFlight.delete(filePath);
|
|
133140
|
+
}
|
|
133141
|
+
});
|
|
133142
|
+
this.refreshesInFlight.set(filePath, refresh);
|
|
133143
|
+
return refresh;
|
|
133144
|
+
}
|
|
133145
|
+
async doRefreshFile(filePath, account) {
|
|
132961
133146
|
const log8 = getLogger2();
|
|
132962
133147
|
if (this.persistent) {
|
|
132963
133148
|
const engine = this.engine();
|
|
132964
133149
|
const previous2 = engine.getByIdOrSession(filePath);
|
|
132965
133150
|
const resolvedAccount2 = account ?? previous2?.account ?? "default";
|
|
132966
|
-
const evict2 = (m2) => {
|
|
132967
|
-
if (!m2) return;
|
|
132968
|
-
this.conversationLRU.delete(m2.id);
|
|
132969
|
-
this.conversationLRU.delete(m2.sessionId);
|
|
132970
|
-
};
|
|
132971
|
-
evict2(previous2);
|
|
132972
133151
|
const provider = await this.resolveProviderForFile(filePath, previous2);
|
|
132973
|
-
const meta22 = await engine.indexFile(
|
|
133152
|
+
const { meta: meta22, change } = await engine.indexFile(
|
|
132974
133153
|
filePath,
|
|
132975
133154
|
resolvedAccount2,
|
|
132976
133155
|
this.lastTier.name,
|
|
@@ -132979,8 +133158,19 @@ var ConversationScanner = class {
|
|
|
132979
133158
|
false,
|
|
132980
133159
|
provider
|
|
132981
133160
|
);
|
|
132982
|
-
|
|
132983
|
-
|
|
133161
|
+
const cacheKeys = /* @__PURE__ */ new Set();
|
|
133162
|
+
for (const m2 of [previous2, meta22]) {
|
|
133163
|
+
if (m2) {
|
|
133164
|
+
cacheKeys.add(m2.id);
|
|
133165
|
+
cacheKeys.add(m2.sessionId);
|
|
133166
|
+
}
|
|
133167
|
+
}
|
|
133168
|
+
if (!meta22 || change === "reindex" || change === "vanished") {
|
|
133169
|
+
for (const key of cacheKeys) this.conversationLRU.delete(key);
|
|
133170
|
+
} else if (change === "appended") {
|
|
133171
|
+
await this.extendCachedConversations(cacheKeys, filePath, meta22.account);
|
|
133172
|
+
}
|
|
133173
|
+
log8.debug({ filePath, change, kept: !!meta22 }, "refreshFile: updated persistent index");
|
|
132984
133174
|
return meta22;
|
|
132985
133175
|
}
|
|
132986
133176
|
const previous = this.metadataCache.get(filePath);
|
|
@@ -133024,6 +133214,39 @@ var ConversationScanner = class {
|
|
|
133024
133214
|
);
|
|
133025
133215
|
return meta3;
|
|
133026
133216
|
}
|
|
133217
|
+
// Advance every cached parse of an appended file by folding only the new
|
|
133218
|
+
// bytes through the conversation reducer — the in-memory analogue of the
|
|
133219
|
+
// persisted metadata fold. Entries without resume state (Codex) and entries
|
|
133220
|
+
// whose extension fails are evicted so the next read re-parses from scratch.
|
|
133221
|
+
async extendCachedConversations(cacheKeys, filePath, account) {
|
|
133222
|
+
const wrappers = /* @__PURE__ */ new Map();
|
|
133223
|
+
for (const key of cacheKeys) {
|
|
133224
|
+
const wrapper = this.conversationLRU.get(key);
|
|
133225
|
+
if (!wrapper) continue;
|
|
133226
|
+
const keys = wrappers.get(wrapper) ?? [];
|
|
133227
|
+
keys.push(key);
|
|
133228
|
+
wrappers.set(wrapper, keys);
|
|
133229
|
+
}
|
|
133230
|
+
for (const [wrapper, keys] of wrappers) {
|
|
133231
|
+
if (!wrapper.resume) {
|
|
133232
|
+
for (const key of keys) this.conversationLRU.delete(key);
|
|
133233
|
+
continue;
|
|
133234
|
+
}
|
|
133235
|
+
try {
|
|
133236
|
+
const extended = await extendConversation(
|
|
133237
|
+
wrapper.conversation,
|
|
133238
|
+
wrapper.resume,
|
|
133239
|
+
filePath,
|
|
133240
|
+
account
|
|
133241
|
+
);
|
|
133242
|
+
wrapper.conversation = extended.conversation;
|
|
133243
|
+
wrapper.resume = extended.resume;
|
|
133244
|
+
} catch (err) {
|
|
133245
|
+
getLogger2().warn({ filePath, err }, "refreshFile: cache extension failed, evicting");
|
|
133246
|
+
for (const key of keys) this.conversationLRU.delete(key);
|
|
133247
|
+
}
|
|
133248
|
+
}
|
|
133249
|
+
}
|
|
133027
133250
|
getMetadataCache() {
|
|
133028
133251
|
if (this.persistent) {
|
|
133029
133252
|
const map2 = /* @__PURE__ */ new Map();
|
|
@@ -133290,10 +133513,10 @@ async function search(query, options, scanner) {
|
|
|
133290
133513
|
// src/server.ts
|
|
133291
133514
|
var import_events3 = require("events");
|
|
133292
133515
|
var import_fs24 = require("fs");
|
|
133293
|
-
var
|
|
133516
|
+
var import_promises17 = require("fs/promises");
|
|
133294
133517
|
var import_http = require("http");
|
|
133295
133518
|
var import_os10 = require("os");
|
|
133296
|
-
var
|
|
133519
|
+
var import_path22 = require("path");
|
|
133297
133520
|
var import_readline4 = require("readline");
|
|
133298
133521
|
|
|
133299
133522
|
// src/agent/agent-client.ts
|
|
@@ -133382,7 +133605,7 @@ function readAgentConfig(env = process.env) {
|
|
|
133382
133605
|
}
|
|
133383
133606
|
|
|
133384
133607
|
// src/agent/conversation-writer.ts
|
|
133385
|
-
var
|
|
133608
|
+
var import_promises10 = require("fs/promises");
|
|
133386
133609
|
var import_node_path6 = require("path");
|
|
133387
133610
|
function createConversationWriter(opts) {
|
|
133388
133611
|
const { baseDir } = opts;
|
|
@@ -133392,7 +133615,7 @@ function createConversationWriter(opts) {
|
|
|
133392
133615
|
throw new Error("ConversationWriter: refusing to write empty assistant turn");
|
|
133393
133616
|
}
|
|
133394
133617
|
const file2 = (0, import_node_path6.join)(baseDir, `${args.sessionId}.jsonl`);
|
|
133395
|
-
await (0,
|
|
133618
|
+
await (0, import_promises10.mkdir)((0, import_node_path6.dirname)(file2), { recursive: true });
|
|
133396
133619
|
const record2 = {
|
|
133397
133620
|
role: "assistant",
|
|
133398
133621
|
turnId: args.turnId,
|
|
@@ -133402,7 +133625,7 @@ function createConversationWriter(opts) {
|
|
|
133402
133625
|
};
|
|
133403
133626
|
const line = `${JSON.stringify(record2)}
|
|
133404
133627
|
`;
|
|
133405
|
-
await (0,
|
|
133628
|
+
await (0, import_promises10.appendFile)(file2, line, { encoding: "utf8" });
|
|
133406
133629
|
}
|
|
133407
133630
|
};
|
|
133408
133631
|
}
|
|
@@ -136383,8 +136606,8 @@ var createHonoApp = (deps, upgradeWebSocket) => {
|
|
|
136383
136606
|
init_auth();
|
|
136384
136607
|
|
|
136385
136608
|
// src/browse.ts
|
|
136386
|
-
var
|
|
136387
|
-
var
|
|
136609
|
+
var import_promises11 = require("fs/promises");
|
|
136610
|
+
var import_path11 = require("path");
|
|
136388
136611
|
var BrowsePathNotFoundError = class extends Error {
|
|
136389
136612
|
constructor(message) {
|
|
136390
136613
|
super(message);
|
|
@@ -136392,20 +136615,20 @@ var BrowsePathNotFoundError = class extends Error {
|
|
|
136392
136615
|
}
|
|
136393
136616
|
};
|
|
136394
136617
|
async function resolveBrowsePath(browseRoot, relativePath) {
|
|
136395
|
-
const normalizedRoot = (0,
|
|
136618
|
+
const normalizedRoot = (0, import_path11.resolve)(browseRoot);
|
|
136396
136619
|
let sanitized;
|
|
136397
136620
|
if (process.platform !== "win32" && relativePath.startsWith("/") && relativePath.length > 1 && relativePath.includes("/", 1)) {
|
|
136398
136621
|
sanitized = relativePath;
|
|
136399
136622
|
} else {
|
|
136400
136623
|
sanitized = relativePath.replace(/^[/\\]+/, "");
|
|
136401
136624
|
}
|
|
136402
|
-
const target = sanitized ? (0,
|
|
136403
|
-
const rootPrefix = normalizedRoot.endsWith(
|
|
136625
|
+
const target = sanitized ? (0, import_path11.resolve)(normalizedRoot, sanitized) : normalizedRoot;
|
|
136626
|
+
const rootPrefix = normalizedRoot.endsWith(import_path11.sep) ? normalizedRoot : `${normalizedRoot}${import_path11.sep}`;
|
|
136404
136627
|
if (!target.startsWith(rootPrefix) && target !== normalizedRoot) {
|
|
136405
136628
|
throw new Error("Path outside browse root");
|
|
136406
136629
|
}
|
|
136407
136630
|
try {
|
|
136408
|
-
await (0,
|
|
136631
|
+
await (0, import_promises11.realpath)(target);
|
|
136409
136632
|
} catch (err) {
|
|
136410
136633
|
if (err?.code === "ENOENT") {
|
|
136411
136634
|
throw new BrowsePathNotFoundError(`Path not found: ${target}`);
|
|
@@ -136415,37 +136638,37 @@ async function resolveBrowsePath(browseRoot, relativePath) {
|
|
|
136415
136638
|
return target;
|
|
136416
136639
|
}
|
|
136417
136640
|
async function listDirectories(absolutePath) {
|
|
136418
|
-
const entries = await (0,
|
|
136641
|
+
const entries = await (0, import_promises11.readdir)(absolutePath, { withFileTypes: true });
|
|
136419
136642
|
return entries.filter((e) => e.isDirectory()).map((e) => ({ name: e.name })).sort((a, b2) => a.name.localeCompare(b2.name));
|
|
136420
136643
|
}
|
|
136421
136644
|
async function createDirectory(parentAbsolutePath, name) {
|
|
136422
136645
|
if (name.includes("/") || name.includes("\\") || name === ".." || name === ".") {
|
|
136423
136646
|
throw new Error("Invalid directory name");
|
|
136424
136647
|
}
|
|
136425
|
-
const target = (0,
|
|
136648
|
+
const target = (0, import_path11.join)(parentAbsolutePath, name);
|
|
136426
136649
|
try {
|
|
136427
|
-
const s3 = await (0,
|
|
136650
|
+
const s3 = await (0, import_promises11.stat)(target);
|
|
136428
136651
|
if (s3.isDirectory()) throw new Error("Directory already exists");
|
|
136429
136652
|
} catch (err) {
|
|
136430
136653
|
if (err.code !== "ENOENT") throw err;
|
|
136431
136654
|
}
|
|
136432
|
-
await (0,
|
|
136655
|
+
await (0, import_promises11.mkdir)(target);
|
|
136433
136656
|
return target;
|
|
136434
136657
|
}
|
|
136435
136658
|
|
|
136436
136659
|
// src/conversation-cache.ts
|
|
136437
136660
|
var import_better_sqlite32 = __toESM(require("better-sqlite3"), 1);
|
|
136438
136661
|
var import_fs16 = require("fs");
|
|
136439
|
-
var
|
|
136662
|
+
var import_path13 = require("path");
|
|
136440
136663
|
|
|
136441
136664
|
// src/db/sqlite-migrate.ts
|
|
136442
136665
|
var import_fs14 = require("fs");
|
|
136443
|
-
var
|
|
136666
|
+
var import_path12 = require("path");
|
|
136444
136667
|
var import_url6 = require("url");
|
|
136445
136668
|
var import_meta = {};
|
|
136446
136669
|
function getMigrationsDir() {
|
|
136447
136670
|
if (typeof import_meta !== "undefined" && import_meta.url) {
|
|
136448
|
-
return (0,
|
|
136671
|
+
return (0, import_path12.dirname)((0, import_url6.fileURLToPath)(import_meta.url));
|
|
136449
136672
|
}
|
|
136450
136673
|
return __dirname;
|
|
136451
136674
|
}
|
|
@@ -136457,7 +136680,7 @@ CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
|
136457
136680
|
`;
|
|
136458
136681
|
function runSqliteMigrations(db, migrationsDir) {
|
|
136459
136682
|
db.exec(SCHEMA_MIGRATIONS_SQL);
|
|
136460
|
-
const dir = migrationsDir ?? (0,
|
|
136683
|
+
const dir = migrationsDir ?? (0, import_path12.join)(getMigrationsDir(), "migrations");
|
|
136461
136684
|
const files = (0, import_fs14.readdirSync)(dir).filter((f2) => f2.endsWith(".sql")).sort();
|
|
136462
136685
|
const appliedRows = db.prepare("SELECT id FROM schema_migrations").all();
|
|
136463
136686
|
const appliedSet = new Set(appliedRows.map((r) => r.id));
|
|
@@ -136469,7 +136692,7 @@ function runSqliteMigrations(db, migrationsDir) {
|
|
|
136469
136692
|
skipped.push(file2);
|
|
136470
136693
|
continue;
|
|
136471
136694
|
}
|
|
136472
|
-
const sql = (0, import_fs14.readFileSync)((0,
|
|
136695
|
+
const sql = (0, import_fs14.readFileSync)((0, import_path12.join)(dir, file2), "utf-8");
|
|
136473
136696
|
const tx = db.transaction(() => {
|
|
136474
136697
|
db.exec(sql);
|
|
136475
136698
|
recordApplied.run(file2, (/* @__PURE__ */ new Date()).toISOString());
|
|
@@ -136814,7 +137037,7 @@ var ConversationCache = class _ConversationCache {
|
|
|
136814
137037
|
return this.classifyAgentFile(filePath, s3.mtimeMs, s3.size);
|
|
136815
137038
|
}
|
|
136816
137039
|
static open(dbPath, tailSize = 10, migrationsDir, options) {
|
|
136817
|
-
(0, import_fs16.mkdirSync)((0,
|
|
137040
|
+
(0, import_fs16.mkdirSync)((0, import_path13.dirname)(dbPath), { recursive: true });
|
|
136818
137041
|
const db = new import_better_sqlite32.default(dbPath);
|
|
136819
137042
|
db.pragma("journal_mode = WAL");
|
|
136820
137043
|
db.pragma("foreign_keys = ON");
|
|
@@ -137395,12 +137618,12 @@ function getDbConfig() {
|
|
|
137395
137618
|
|
|
137396
137619
|
// src/db/migrations.ts
|
|
137397
137620
|
var import_fs17 = require("fs");
|
|
137398
|
-
var
|
|
137621
|
+
var import_path14 = require("path");
|
|
137399
137622
|
var import_url7 = require("url");
|
|
137400
137623
|
var import_meta2 = {};
|
|
137401
137624
|
function getMigrationsDir2() {
|
|
137402
137625
|
if (import_meta2.url) {
|
|
137403
|
-
return (0,
|
|
137626
|
+
return (0, import_path14.dirname)((0, import_url7.fileURLToPath)(import_meta2.url));
|
|
137404
137627
|
}
|
|
137405
137628
|
return __dirname;
|
|
137406
137629
|
}
|
|
@@ -137416,11 +137639,11 @@ async function runMigrations2(pool2, migrationsDir) {
|
|
|
137416
137639
|
"SELECT name FROM _migrations ORDER BY name"
|
|
137417
137640
|
);
|
|
137418
137641
|
const appliedSet = new Set(applied.map((r) => r.name));
|
|
137419
|
-
const dir = migrationsDir ?? (0,
|
|
137642
|
+
const dir = migrationsDir ?? (0, import_path14.join)(getMigrationsDir2(), "pg-migrations");
|
|
137420
137643
|
const files = (0, import_fs17.readdirSync)(dir).filter((f2) => f2.endsWith(".sql")).sort();
|
|
137421
137644
|
for (const file2 of files) {
|
|
137422
137645
|
if (appliedSet.has(file2)) continue;
|
|
137423
|
-
const sql = (0, import_fs17.readFileSync)((0,
|
|
137646
|
+
const sql = (0, import_fs17.readFileSync)((0, import_path14.join)(dir, file2), "utf-8");
|
|
137424
137647
|
await pool2.query(sql);
|
|
137425
137648
|
await pool2.query("INSERT INTO _migrations (name) VALUES ($1)", [file2]);
|
|
137426
137649
|
}
|
|
@@ -137657,18 +137880,18 @@ async function recordUpload(pool2, instanceId, row) {
|
|
|
137657
137880
|
// src/handlers/handleListProjects.ts
|
|
137658
137881
|
var import_fs18 = require("fs");
|
|
137659
137882
|
var import_os7 = require("os");
|
|
137660
|
-
var
|
|
137883
|
+
var import_path15 = require("path");
|
|
137661
137884
|
function decodeProjectPath(dirName) {
|
|
137662
137885
|
return dirName.replace(/-/g, "/");
|
|
137663
137886
|
}
|
|
137664
137887
|
function handleListProjects(url2, res) {
|
|
137665
137888
|
const limit = Math.max(1, parseInt(url2.searchParams.get("limit") ?? "50", 10) || 50);
|
|
137666
137889
|
const offset = Math.max(0, parseInt(url2.searchParams.get("offset") ?? "0", 10) || 0);
|
|
137667
|
-
const projectsDir = (0,
|
|
137890
|
+
const projectsDir = (0, import_path15.join)((0, import_os7.homedir)(), ".claude", "projects");
|
|
137668
137891
|
let entries;
|
|
137669
137892
|
try {
|
|
137670
137893
|
entries = (0, import_fs18.readdirSync)(projectsDir).map((dirName) => {
|
|
137671
|
-
const fullPath = (0,
|
|
137894
|
+
const fullPath = (0, import_path15.join)(projectsDir, dirName);
|
|
137672
137895
|
let mtime = 0;
|
|
137673
137896
|
try {
|
|
137674
137897
|
mtime = (0, import_fs18.statSync)(fullPath).mtimeMs;
|
|
@@ -137690,20 +137913,20 @@ function handleListProjects(url2, res) {
|
|
|
137690
137913
|
}
|
|
137691
137914
|
|
|
137692
137915
|
// src/live-session-manager.ts
|
|
137693
|
-
var
|
|
137916
|
+
var import_path19 = require("path");
|
|
137694
137917
|
|
|
137695
137918
|
// src/codex-pty-runner.ts
|
|
137696
137919
|
var import_headless = __toESM(require_xterm_headless(), 1);
|
|
137697
137920
|
var import_crypto6 = require("crypto");
|
|
137698
137921
|
var import_fs20 = require("fs");
|
|
137699
|
-
var
|
|
137922
|
+
var import_path17 = require("path");
|
|
137700
137923
|
init_logger();
|
|
137701
137924
|
|
|
137702
137925
|
// src/platform.ts
|
|
137703
137926
|
var import_child_process = require("child_process");
|
|
137704
137927
|
var import_fs19 = require("fs");
|
|
137705
137928
|
var import_os8 = require("os");
|
|
137706
|
-
var
|
|
137929
|
+
var import_path16 = require("path");
|
|
137707
137930
|
var isWindows2 = (0, import_os8.platform)() === "win32";
|
|
137708
137931
|
var _claudeExe;
|
|
137709
137932
|
function resolveClaudeExe() {
|
|
@@ -137722,9 +137945,9 @@ function resolveClaudeExe() {
|
|
|
137722
137945
|
} catch {
|
|
137723
137946
|
}
|
|
137724
137947
|
const candidates = [
|
|
137725
|
-
(0,
|
|
137726
|
-
(0,
|
|
137727
|
-
process.env.LOCALAPPDATA ?? (0,
|
|
137948
|
+
(0, import_path16.join)((0, import_os8.homedir)(), ".local", "bin", "claude.exe"),
|
|
137949
|
+
(0, import_path16.join)(
|
|
137950
|
+
process.env.LOCALAPPDATA ?? (0, import_path16.join)((0, import_os8.homedir)(), "AppData", "Local"),
|
|
137728
137951
|
"Microsoft",
|
|
137729
137952
|
"WindowsApps",
|
|
137730
137953
|
"claude.exe"
|
|
@@ -137751,7 +137974,7 @@ function resolveClaudeExe() {
|
|
|
137751
137974
|
const candidates = [
|
|
137752
137975
|
"/opt/homebrew/bin/claude",
|
|
137753
137976
|
"/usr/local/bin/claude",
|
|
137754
|
-
(0,
|
|
137977
|
+
(0, import_path16.join)((0, import_os8.homedir)(), ".local", "bin", "claude")
|
|
137755
137978
|
];
|
|
137756
137979
|
for (const p2 of candidates) {
|
|
137757
137980
|
if ((0, import_fs19.existsSync)(p2)) {
|
|
@@ -137780,9 +138003,9 @@ function resolveCodexExe() {
|
|
|
137780
138003
|
} catch {
|
|
137781
138004
|
}
|
|
137782
138005
|
const candidates = [
|
|
137783
|
-
(0,
|
|
137784
|
-
(0,
|
|
137785
|
-
process.env.LOCALAPPDATA ?? (0,
|
|
138006
|
+
(0, import_path16.join)((0, import_os8.homedir)(), ".local", "bin", "codex.exe"),
|
|
138007
|
+
(0, import_path16.join)(
|
|
138008
|
+
process.env.LOCALAPPDATA ?? (0, import_path16.join)((0, import_os8.homedir)(), "AppData", "Local"),
|
|
137786
138009
|
"Microsoft",
|
|
137787
138010
|
"WindowsApps",
|
|
137788
138011
|
"codex.exe"
|
|
@@ -137809,7 +138032,7 @@ function resolveCodexExe() {
|
|
|
137809
138032
|
const candidates = [
|
|
137810
138033
|
"/opt/homebrew/bin/codex",
|
|
137811
138034
|
"/usr/local/bin/codex",
|
|
137812
|
-
(0,
|
|
138035
|
+
(0, import_path16.join)((0, import_os8.homedir)(), ".local", "bin", "codex")
|
|
137813
138036
|
];
|
|
137814
138037
|
for (const p2 of candidates) {
|
|
137815
138038
|
if ((0, import_fs19.existsSync)(p2)) {
|
|
@@ -137905,7 +138128,7 @@ var CodexPtyRunner = class {
|
|
|
137905
138128
|
}
|
|
137906
138129
|
async doStart(sessionId, options) {
|
|
137907
138130
|
const nodePty = await loadPty();
|
|
137908
|
-
const projectName = options.projectName ?? (0,
|
|
138131
|
+
const projectName = options.projectName ?? (0, import_path17.basename)(options.projectPath);
|
|
137909
138132
|
const proc = nodePty.spawn(
|
|
137910
138133
|
resolveCodexExe(),
|
|
137911
138134
|
["resume", sessionId, "--cd", options.projectPath, "--no-alt-screen"],
|
|
@@ -137950,7 +138173,7 @@ var CodexPtyRunner = class {
|
|
|
137950
138173
|
async startFresh(options) {
|
|
137951
138174
|
const nodePty = await loadPty();
|
|
137952
138175
|
const sessionId = (0, import_crypto6.randomUUID)();
|
|
137953
|
-
const projectName = options.projectName ?? (0,
|
|
138176
|
+
const projectName = options.projectName ?? (0, import_path17.basename)(options.projectPath);
|
|
137954
138177
|
const args = ["--cd", options.projectPath, "--no-alt-screen"];
|
|
137955
138178
|
if (options.systemPrompt) {
|
|
137956
138179
|
args.push(options.systemPrompt);
|
|
@@ -138280,7 +138503,7 @@ function stripAnsi(str) {
|
|
|
138280
138503
|
var import_headless2 = __toESM(require_xterm_headless(), 1);
|
|
138281
138504
|
var import_crypto7 = require("crypto");
|
|
138282
138505
|
var import_fs21 = require("fs");
|
|
138283
|
-
var
|
|
138506
|
+
var import_path18 = require("path");
|
|
138284
138507
|
init_logger();
|
|
138285
138508
|
|
|
138286
138509
|
// src/services/questions/detectPermissionGate.ts
|
|
@@ -138632,7 +138855,7 @@ var PTYManager = class {
|
|
|
138632
138855
|
}
|
|
138633
138856
|
async doStart(sessionId, options) {
|
|
138634
138857
|
const nodePty = await loadPty2();
|
|
138635
|
-
const projectName = options.projectName ?? (0,
|
|
138858
|
+
const projectName = options.projectName ?? (0, import_path18.basename)(options.projectPath);
|
|
138636
138859
|
const proc = nodePty.spawn(
|
|
138637
138860
|
resolveClaudeExe(),
|
|
138638
138861
|
[
|
|
@@ -138683,7 +138906,7 @@ var PTYManager = class {
|
|
|
138683
138906
|
async startFresh(options) {
|
|
138684
138907
|
const nodePty = await loadPty2();
|
|
138685
138908
|
const sessionId = (0, import_crypto7.randomUUID)();
|
|
138686
|
-
const projectName = options.projectName ?? (0,
|
|
138909
|
+
const projectName = options.projectName ?? (0, import_path18.basename)(options.projectPath);
|
|
138687
138910
|
const args = [
|
|
138688
138911
|
"--permission-mode",
|
|
138689
138912
|
options.permissionMode ?? "acceptEdits",
|
|
@@ -139255,7 +139478,7 @@ var LiveSessionManager = class {
|
|
|
139255
139478
|
const runner = this.runners.get(provider);
|
|
139256
139479
|
if (runner) return runner;
|
|
139257
139480
|
const err = new Error(
|
|
139258
|
-
`Live ${provider} sessions are not implemented yet for ${(0,
|
|
139481
|
+
`Live ${provider} sessions are not implemented yet for ${(0, import_path19.basename)(projectPath)}`
|
|
139259
139482
|
);
|
|
139260
139483
|
err.statusCode = 501;
|
|
139261
139484
|
throw err;
|
|
@@ -139322,7 +139545,7 @@ var PairTokenStore = class {
|
|
|
139322
139545
|
// src/process-discovery.ts
|
|
139323
139546
|
var import_child_process2 = require("child_process");
|
|
139324
139547
|
var import_os9 = require("os");
|
|
139325
|
-
var
|
|
139548
|
+
var import_path20 = require("path");
|
|
139326
139549
|
async function discoverClaudeProcesses() {
|
|
139327
139550
|
if ((0, import_os9.platform)() === "win32") return discoverWindows();
|
|
139328
139551
|
return discoverUnix();
|
|
@@ -139341,7 +139564,7 @@ async function discoverUnix() {
|
|
|
139341
139564
|
return {
|
|
139342
139565
|
pid,
|
|
139343
139566
|
projectPath: cwd,
|
|
139344
|
-
projectName: (0,
|
|
139567
|
+
projectName: (0, import_path20.basename)(cwd),
|
|
139345
139568
|
branch: await readGitBranch2(cwd),
|
|
139346
139569
|
conversationId,
|
|
139347
139570
|
startedAt
|
|
@@ -139363,7 +139586,7 @@ async function discoverWindows() {
|
|
|
139363
139586
|
return {
|
|
139364
139587
|
pid,
|
|
139365
139588
|
projectPath: info.cwd,
|
|
139366
|
-
projectName: (0,
|
|
139589
|
+
projectName: (0, import_path20.basename)(info.cwd),
|
|
139367
139590
|
branch: await readGitBranch2(info.cwd),
|
|
139368
139591
|
conversationId: extractResumeId(info.args),
|
|
139369
139592
|
startedAt: info.startedAt
|
|
@@ -139444,7 +139667,7 @@ async function getProcessInfoWindows(pid) {
|
|
|
139444
139667
|
const startedAt = /* @__PURE__ */ new Date(`${year}-${month}-${day}T${hour}:${min}:${sec}`);
|
|
139445
139668
|
if (Number.isNaN(startedAt.getTime())) return null;
|
|
139446
139669
|
const exePath = parts[3] ?? "";
|
|
139447
|
-
const cwd = exePath ? (0,
|
|
139670
|
+
const cwd = exePath ? (0, import_path20.dirname)(exePath) : "";
|
|
139448
139671
|
return { cwd, args, startedAt };
|
|
139449
139672
|
} catch {
|
|
139450
139673
|
return null;
|
|
@@ -139486,11 +139709,11 @@ function seal(plaintext, recipientPublicKeyBase64) {
|
|
|
139486
139709
|
// node_modules/chokidar/index.js
|
|
139487
139710
|
var import_node_events2 = require("events");
|
|
139488
139711
|
var import_node_fs7 = require("fs");
|
|
139489
|
-
var
|
|
139712
|
+
var import_promises14 = require("fs/promises");
|
|
139490
139713
|
var sp2 = __toESM(require("path"), 1);
|
|
139491
139714
|
|
|
139492
139715
|
// node_modules/readdirp/index.js
|
|
139493
|
-
var
|
|
139716
|
+
var import_promises12 = require("fs/promises");
|
|
139494
139717
|
var import_node_path9 = require("path");
|
|
139495
139718
|
var import_node_stream2 = require("stream");
|
|
139496
139719
|
var EntryTypes2 = {
|
|
@@ -139571,7 +139794,7 @@ var ReaddirpStream2 = class extends import_node_stream2.Readable {
|
|
|
139571
139794
|
const { root, type } = opts;
|
|
139572
139795
|
this._fileFilter = normalizeFilter2(opts.fileFilter);
|
|
139573
139796
|
this._directoryFilter = normalizeFilter2(opts.directoryFilter);
|
|
139574
|
-
const statMethod = opts.lstat ?
|
|
139797
|
+
const statMethod = opts.lstat ? import_promises12.lstat : import_promises12.stat;
|
|
139575
139798
|
if (wantBigintFsStats2) {
|
|
139576
139799
|
this._stat = (path2) => statMethod(path2, { bigint: true });
|
|
139577
139800
|
} else {
|
|
@@ -139642,7 +139865,7 @@ var ReaddirpStream2 = class extends import_node_stream2.Readable {
|
|
|
139642
139865
|
async _exploreDir(path2, depth) {
|
|
139643
139866
|
let files;
|
|
139644
139867
|
try {
|
|
139645
|
-
files = await (0,
|
|
139868
|
+
files = await (0, import_promises12.readdir)(path2, this._rdOptions);
|
|
139646
139869
|
} catch (error51) {
|
|
139647
139870
|
this._onError(error51);
|
|
139648
139871
|
}
|
|
@@ -139650,10 +139873,10 @@ var ReaddirpStream2 = class extends import_node_stream2.Readable {
|
|
|
139650
139873
|
}
|
|
139651
139874
|
async _formatEntry(dirent, path2) {
|
|
139652
139875
|
let entry;
|
|
139653
|
-
const
|
|
139876
|
+
const basename12 = this._isDirent ? dirent.name : dirent;
|
|
139654
139877
|
try {
|
|
139655
|
-
const fullPath = (0, import_node_path9.resolve)((0, import_node_path9.join)(path2,
|
|
139656
|
-
entry = { path: (0, import_node_path9.relative)(this._root, fullPath), fullPath, basename:
|
|
139878
|
+
const fullPath = (0, import_node_path9.resolve)((0, import_node_path9.join)(path2, basename12));
|
|
139879
|
+
entry = { path: (0, import_node_path9.relative)(this._root, fullPath), fullPath, basename: basename12 };
|
|
139657
139880
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
139658
139881
|
} catch (err) {
|
|
139659
139882
|
this._onError(err);
|
|
@@ -139680,8 +139903,8 @@ var ReaddirpStream2 = class extends import_node_stream2.Readable {
|
|
|
139680
139903
|
if (stats && stats.isSymbolicLink()) {
|
|
139681
139904
|
const full = entry.fullPath;
|
|
139682
139905
|
try {
|
|
139683
|
-
const entryRealPath = await (0,
|
|
139684
|
-
const entryRealPathStats = await (0,
|
|
139906
|
+
const entryRealPath = await (0, import_promises12.realpath)(full);
|
|
139907
|
+
const entryRealPathStats = await (0, import_promises12.lstat)(entryRealPath);
|
|
139685
139908
|
if (entryRealPathStats.isFile()) {
|
|
139686
139909
|
return "file";
|
|
139687
139910
|
}
|
|
@@ -139724,7 +139947,7 @@ function readdirp2(root, options = {}) {
|
|
|
139724
139947
|
|
|
139725
139948
|
// node_modules/chokidar/handler.js
|
|
139726
139949
|
var import_node_fs6 = require("fs");
|
|
139727
|
-
var
|
|
139950
|
+
var import_promises13 = require("fs/promises");
|
|
139728
139951
|
var import_node_os3 = require("os");
|
|
139729
139952
|
var sp = __toESM(require("path"), 1);
|
|
139730
139953
|
var STR_DATA2 = "data";
|
|
@@ -139751,7 +139974,7 @@ var EVENTS2 = {
|
|
|
139751
139974
|
};
|
|
139752
139975
|
var EV2 = EVENTS2;
|
|
139753
139976
|
var THROTTLE_MODE_WATCH2 = "watch";
|
|
139754
|
-
var statMethods2 = { lstat:
|
|
139977
|
+
var statMethods2 = { lstat: import_promises13.lstat, stat: import_promises13.stat };
|
|
139755
139978
|
var KEY_LISTENERS2 = "listeners";
|
|
139756
139979
|
var KEY_ERR2 = "errHandlers";
|
|
139757
139980
|
var KEY_RAW2 = "rawEmitters";
|
|
@@ -140108,7 +140331,7 @@ var setFsWatchListener2 = (path2, fullPath, options, handlers) => {
|
|
|
140108
140331
|
cont.watcherUnusable = true;
|
|
140109
140332
|
if (isWindows3 && error51.code === "EPERM") {
|
|
140110
140333
|
try {
|
|
140111
|
-
const fd = await (0,
|
|
140334
|
+
const fd = await (0, import_promises13.open)(path2, "r");
|
|
140112
140335
|
await fd.close();
|
|
140113
140336
|
broadcastErr(error51);
|
|
140114
140337
|
} catch (err) {
|
|
@@ -140194,9 +140417,9 @@ var NodeFsHandler2 = class {
|
|
|
140194
140417
|
_watchWithNodeFs(path2, listener) {
|
|
140195
140418
|
const opts = this.fsw.options;
|
|
140196
140419
|
const directory = sp.dirname(path2);
|
|
140197
|
-
const
|
|
140420
|
+
const basename12 = sp.basename(path2);
|
|
140198
140421
|
const parent = this.fsw._getWatchedDir(directory);
|
|
140199
|
-
parent.add(
|
|
140422
|
+
parent.add(basename12);
|
|
140200
140423
|
const absolutePath = sp.resolve(path2);
|
|
140201
140424
|
const options = {
|
|
140202
140425
|
persistent: opts.persistent
|
|
@@ -140206,7 +140429,7 @@ var NodeFsHandler2 = class {
|
|
|
140206
140429
|
let closer;
|
|
140207
140430
|
if (opts.usePolling) {
|
|
140208
140431
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
140209
|
-
options.interval = enableBin && isBinaryPath2(
|
|
140432
|
+
options.interval = enableBin && isBinaryPath2(basename12) ? opts.binaryInterval : opts.interval;
|
|
140210
140433
|
closer = setFsWatchFileListener2(path2, absolutePath, options, {
|
|
140211
140434
|
listener,
|
|
140212
140435
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -140229,17 +140452,17 @@ var NodeFsHandler2 = class {
|
|
|
140229
140452
|
return;
|
|
140230
140453
|
}
|
|
140231
140454
|
const dirname17 = sp.dirname(file2);
|
|
140232
|
-
const
|
|
140455
|
+
const basename12 = sp.basename(file2);
|
|
140233
140456
|
const parent = this.fsw._getWatchedDir(dirname17);
|
|
140234
140457
|
let prevStats = stats;
|
|
140235
|
-
if (parent.has(
|
|
140458
|
+
if (parent.has(basename12))
|
|
140236
140459
|
return;
|
|
140237
140460
|
const listener = async (path2, newStats) => {
|
|
140238
140461
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH2, file2, 5))
|
|
140239
140462
|
return;
|
|
140240
140463
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
140241
140464
|
try {
|
|
140242
|
-
const newStats2 = await (0,
|
|
140465
|
+
const newStats2 = await (0, import_promises13.stat)(file2);
|
|
140243
140466
|
if (this.fsw.closed)
|
|
140244
140467
|
return;
|
|
140245
140468
|
const at2 = newStats2.atimeMs;
|
|
@@ -140257,9 +140480,9 @@ var NodeFsHandler2 = class {
|
|
|
140257
140480
|
prevStats = newStats2;
|
|
140258
140481
|
}
|
|
140259
140482
|
} catch (error51) {
|
|
140260
|
-
this.fsw._remove(dirname17,
|
|
140483
|
+
this.fsw._remove(dirname17, basename12);
|
|
140261
140484
|
}
|
|
140262
|
-
} else if (parent.has(
|
|
140485
|
+
} else if (parent.has(basename12)) {
|
|
140263
140486
|
const at2 = newStats.atimeMs;
|
|
140264
140487
|
const mt2 = newStats.mtimeMs;
|
|
140265
140488
|
if (!at2 || at2 <= mt2 || mt2 !== prevStats.mtimeMs) {
|
|
@@ -140294,7 +140517,7 @@ var NodeFsHandler2 = class {
|
|
|
140294
140517
|
this.fsw._incrReadyCount();
|
|
140295
140518
|
let linkPath;
|
|
140296
140519
|
try {
|
|
140297
|
-
linkPath = await (0,
|
|
140520
|
+
linkPath = await (0, import_promises13.realpath)(path2);
|
|
140298
140521
|
} catch (e) {
|
|
140299
140522
|
this.fsw._emitReady();
|
|
140300
140523
|
return true;
|
|
@@ -140443,7 +140666,7 @@ var NodeFsHandler2 = class {
|
|
|
140443
140666
|
let closer;
|
|
140444
140667
|
if (stats.isDirectory()) {
|
|
140445
140668
|
const absPath = sp.resolve(path2);
|
|
140446
|
-
const targetPath = follow ? await (0,
|
|
140669
|
+
const targetPath = follow ? await (0, import_promises13.realpath)(path2) : path2;
|
|
140447
140670
|
if (this.fsw.closed)
|
|
140448
140671
|
return;
|
|
140449
140672
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -140453,7 +140676,7 @@ var NodeFsHandler2 = class {
|
|
|
140453
140676
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
140454
140677
|
}
|
|
140455
140678
|
} else if (stats.isSymbolicLink()) {
|
|
140456
|
-
const targetPath = follow ? await (0,
|
|
140679
|
+
const targetPath = follow ? await (0, import_promises13.realpath)(path2) : path2;
|
|
140457
140680
|
if (this.fsw.closed)
|
|
140458
140681
|
return;
|
|
140459
140682
|
const parent = sp.dirname(wh.watchPath);
|
|
@@ -140613,7 +140836,7 @@ var DirEntry2 = class {
|
|
|
140613
140836
|
return;
|
|
140614
140837
|
const dir = this.path;
|
|
140615
140838
|
try {
|
|
140616
|
-
await (0,
|
|
140839
|
+
await (0, import_promises14.readdir)(dir);
|
|
140617
140840
|
} catch (err) {
|
|
140618
140841
|
if (this._removeWatcher) {
|
|
140619
140842
|
this._removeWatcher(sp2.dirname(dir), sp2.basename(dir));
|
|
@@ -140963,7 +141186,7 @@ var FSWatcher2 = class extends import_node_events2.EventEmitter {
|
|
|
140963
141186
|
const fullPath = opts.cwd ? sp2.join(opts.cwd, path2) : path2;
|
|
140964
141187
|
let stats2;
|
|
140965
141188
|
try {
|
|
140966
|
-
stats2 = await (0,
|
|
141189
|
+
stats2 = await (0, import_promises14.stat)(fullPath);
|
|
140967
141190
|
} catch (err) {
|
|
140968
141191
|
}
|
|
140969
141192
|
if (!stats2 || this.closed)
|
|
@@ -141217,7 +141440,7 @@ var chokidar_default = { watch: watch2, FSWatcher: FSWatcher2 };
|
|
|
141217
141440
|
|
|
141218
141441
|
// src/services/conversations/conversationWatcher.ts
|
|
141219
141442
|
var import_fs22 = require("fs");
|
|
141220
|
-
var
|
|
141443
|
+
var import_promises15 = require("fs/promises");
|
|
141221
141444
|
var ConversationWatcher = class {
|
|
141222
141445
|
files = /* @__PURE__ */ new Map();
|
|
141223
141446
|
directories = /* @__PURE__ */ new Map();
|
|
@@ -141321,12 +141544,12 @@ var ConversationWatcher = class {
|
|
|
141321
141544
|
entry.reading = true;
|
|
141322
141545
|
try {
|
|
141323
141546
|
for (; ; ) {
|
|
141324
|
-
const st2 = await (0,
|
|
141547
|
+
const st2 = await (0, import_promises15.stat)(filePath);
|
|
141325
141548
|
if (st2.size <= entry.offset) break;
|
|
141326
141549
|
const readFrom = entry.offset;
|
|
141327
141550
|
const bytesToRead = st2.size - readFrom;
|
|
141328
141551
|
const buf = Buffer.alloc(bytesToRead);
|
|
141329
|
-
const fh = await (0,
|
|
141552
|
+
const fh = await (0, import_promises15.open)(filePath, "r");
|
|
141330
141553
|
try {
|
|
141331
141554
|
await fh.read(buf, 0, bytesToRead, readFrom);
|
|
141332
141555
|
} finally {
|
|
@@ -141775,9 +141998,9 @@ function discoveredToResponse(d, conversationId) {
|
|
|
141775
141998
|
|
|
141776
141999
|
// src/uploads.ts
|
|
141777
142000
|
var import_crypto9 = require("crypto");
|
|
141778
|
-
var
|
|
142001
|
+
var import_promises16 = require("fs/promises");
|
|
141779
142002
|
var import_heic_convert = __toESM(require_heic_convert(), 1);
|
|
141780
|
-
var
|
|
142003
|
+
var import_path21 = require("path");
|
|
141781
142004
|
var UPLOAD_DIR_NAME = ".threadbase-uploads";
|
|
141782
142005
|
var MAX_BYTES = 25 * 1024 * 1024;
|
|
141783
142006
|
var HEIC_MIMES = /* @__PURE__ */ new Set(["image/heic", "image/heif"]);
|
|
@@ -141810,10 +142033,10 @@ async function saveUploadFile(input) {
|
|
|
141810
142033
|
}
|
|
141811
142034
|
const id = `up_${(0, import_crypto9.randomBytes)(8).toString("hex")}`;
|
|
141812
142035
|
const safeName = sanitizeFilename(originalName) || `file${MIME_TO_EXT[mimeType] ?? ""}`;
|
|
141813
|
-
const dir = (0,
|
|
141814
|
-
await (0,
|
|
141815
|
-
const filePath = (0,
|
|
141816
|
-
await (0,
|
|
142036
|
+
const dir = (0, import_path21.join)(input.projectPath, UPLOAD_DIR_NAME, input.sessionId);
|
|
142037
|
+
await (0, import_promises16.mkdir)(dir, { recursive: true });
|
|
142038
|
+
const filePath = (0, import_path21.join)(dir, `${Date.now()}-${id}-${safeName}`);
|
|
142039
|
+
await (0, import_promises16.writeFile)(filePath, buffer);
|
|
141817
142040
|
return {
|
|
141818
142041
|
id,
|
|
141819
142042
|
filePath,
|
|
@@ -142313,11 +142536,11 @@ var StreamerServer = class {
|
|
|
142313
142536
|
this.disableDb = config2.disableDb ?? false;
|
|
142314
142537
|
this.scannerPersistenceDisabled = config2.scannerPersistent === false;
|
|
142315
142538
|
this.scanProfiles = config2.scanProfiles;
|
|
142316
|
-
this.codexRoots = config2.codexRoots ?? [(0,
|
|
142539
|
+
this.codexRoots = config2.codexRoots ?? [(0, import_path22.join)((0, import_os10.homedir)(), ".codex", "sessions")];
|
|
142317
142540
|
this.ptyGracePeriodMs = config2.ptyGracePeriodMs ?? DEFAULT_PTY_GRACE_PERIOD_MS;
|
|
142318
142541
|
this.defaultSystemPrompt = config2.defaultSystemPrompt ?? DEFAULT_SYSTEM_PROMPT;
|
|
142319
142542
|
this.defaultPermissionMode = config2.defaultPermissionMode ?? loadDefaultPermissionMode() ?? "acceptEdits";
|
|
142320
|
-
this.cacheDir = config2.cacheDir ?? loadCacheDir() ?? (0,
|
|
142543
|
+
this.cacheDir = config2.cacheDir ?? loadCacheDir() ?? (0, import_path22.join)((0, import_os10.homedir)(), ".threadbase", "cache");
|
|
142321
142544
|
this.tailSize = config2.tailSize ?? loadTailSize() ?? 10;
|
|
142322
142545
|
this.directoryDebounceMs = parseDirScanDebounceEnv(process.env.THREADBASE_DIR_SCAN_DEBOUNCE_MS) ?? config2.directoryScanDebounceMs ?? 1e3;
|
|
142323
142546
|
this.markScannerStaleDebounced = debounce(() => {
|
|
@@ -142328,7 +142551,7 @@ var StreamerServer = class {
|
|
|
142328
142551
|
this.agentEntrypoints = parseAgentEntrypointsEnv(process.env.THREADBASE_AGENT_ENTRYPOINTS);
|
|
142329
142552
|
const rawRoot = process.env.THREADBASE_BROWSE_ROOT ?? loadBrowseRoot() ?? config2.browseRoot;
|
|
142330
142553
|
if (rawRoot) {
|
|
142331
|
-
(0,
|
|
142554
|
+
(0, import_promises17.realpath)(rawRoot).then((resolved) => {
|
|
142332
142555
|
this.browseRoot = resolved;
|
|
142333
142556
|
if (this.verbose) this.log.info(`Browse root: ${resolved}`, { browseRoot: resolved });
|
|
142334
142557
|
}).catch(() => {
|
|
@@ -142484,7 +142707,7 @@ var StreamerServer = class {
|
|
|
142484
142707
|
temporalClient,
|
|
142485
142708
|
taskQueue: agentConfig.temporal.taskQueue
|
|
142486
142709
|
});
|
|
142487
|
-
const conversationsBaseDir = agentConfig.conversationsDir || (0,
|
|
142710
|
+
const conversationsBaseDir = agentConfig.conversationsDir || (0, import_path22.join)((0, import_path22.dirname)(this.cacheDir), "conversations");
|
|
142488
142711
|
conversationWriter = createConversationWriter({
|
|
142489
142712
|
baseDir: conversationsBaseDir
|
|
142490
142713
|
});
|
|
@@ -142708,7 +142931,7 @@ var StreamerServer = class {
|
|
|
142708
142931
|
});
|
|
142709
142932
|
try {
|
|
142710
142933
|
this.cache = ConversationCache.open(
|
|
142711
|
-
(0,
|
|
142934
|
+
(0, import_path22.join)(this.cacheDir, "cache.db"),
|
|
142712
142935
|
this.tailSize,
|
|
142713
142936
|
void 0,
|
|
142714
142937
|
{
|
|
@@ -142734,11 +142957,11 @@ var StreamerServer = class {
|
|
|
142734
142957
|
if (this.scanProfiles && this.scanProfiles.length > 0) {
|
|
142735
142958
|
for (const profile of this.scanProfiles) {
|
|
142736
142959
|
if (profile.enabled) {
|
|
142737
|
-
this.fileWatcher.watchDirectory((0,
|
|
142960
|
+
this.fileWatcher.watchDirectory((0, import_path22.join)(profile.configDir, "projects"));
|
|
142738
142961
|
}
|
|
142739
142962
|
}
|
|
142740
142963
|
} else {
|
|
142741
|
-
this.fileWatcher.watchDirectory((0,
|
|
142964
|
+
this.fileWatcher.watchDirectory((0, import_path22.join)((0, import_os10.homedir)(), ".claude", "projects"));
|
|
142742
142965
|
}
|
|
142743
142966
|
} catch (err) {
|
|
142744
142967
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -143292,16 +143515,16 @@ var StreamerServer = class {
|
|
|
143292
143515
|
return scanner;
|
|
143293
143516
|
}
|
|
143294
143517
|
findJsonlPath(uuid3) {
|
|
143295
|
-
const projectsDir = (0,
|
|
143518
|
+
const projectsDir = (0, import_path22.join)((0, import_os10.homedir)(), ".claude", "projects");
|
|
143296
143519
|
if (!(0, import_fs24.existsSync)(projectsDir)) return null;
|
|
143297
143520
|
const filename = `${uuid3}.jsonl`;
|
|
143298
143521
|
for (const dir of (0, import_fs24.readdirSync)(projectsDir)) {
|
|
143299
|
-
const fp = (0,
|
|
143522
|
+
const fp = (0, import_path22.join)(projectsDir, dir, filename);
|
|
143300
143523
|
if ((0, import_fs24.existsSync)(fp)) return fp;
|
|
143301
|
-
const projectDir = (0,
|
|
143524
|
+
const projectDir = (0, import_path22.join)(projectsDir, dir);
|
|
143302
143525
|
try {
|
|
143303
143526
|
for (const sub of (0, import_fs24.readdirSync)(projectDir)) {
|
|
143304
|
-
const subagentPath = (0,
|
|
143527
|
+
const subagentPath = (0, import_path22.join)(projectDir, sub, "subagents", filename);
|
|
143305
143528
|
if ((0, import_fs24.existsSync)(subagentPath)) return subagentPath;
|
|
143306
143529
|
}
|
|
143307
143530
|
} catch {
|
|
@@ -144094,7 +144317,7 @@ var StreamerServer = class {
|
|
|
144094
144317
|
sessionStore: this.sessionStore,
|
|
144095
144318
|
// biome-ignore lint/style/noNonNullAssertion: agentClient is set when agentConfig.enabled is true
|
|
144096
144319
|
agentClient: this.agentClient,
|
|
144097
|
-
conversationsDir: this.cacheDir ? (0,
|
|
144320
|
+
conversationsDir: this.cacheDir ? (0, import_path22.join)((0, import_path22.dirname)(this.cacheDir), "conversations") : "",
|
|
144098
144321
|
agentConfig: this.agentConfig
|
|
144099
144322
|
});
|
|
144100
144323
|
json2(res, result.status, result.body);
|
|
@@ -144235,9 +144458,9 @@ var StreamerServer = class {
|
|
|
144235
144458
|
// was passed to Claude via --session-id so the filename matches from the start.
|
|
144236
144459
|
watchForJsonl(sessionId, projectPath) {
|
|
144237
144460
|
const encoded = projectPath.replace(/[/\\:.]/g, "-");
|
|
144238
|
-
const projectsDir = (0,
|
|
144461
|
+
const projectsDir = (0, import_path22.join)((0, import_os10.homedir)(), ".claude", "projects", encoded);
|
|
144239
144462
|
const expectedFile = `${sessionId}.jsonl`;
|
|
144240
|
-
const filePath = (0,
|
|
144463
|
+
const filePath = (0, import_path22.join)(projectsDir, expectedFile);
|
|
144241
144464
|
const deadline = Date.now() + 12e4;
|
|
144242
144465
|
let watcher = null;
|
|
144243
144466
|
const cleanup = () => {
|
|
@@ -144259,8 +144482,8 @@ var StreamerServer = class {
|
|
|
144259
144482
|
if (!resolvedFilePath && (0, import_fs24.existsSync)(projectsDir)) {
|
|
144260
144483
|
try {
|
|
144261
144484
|
const now = Date.now();
|
|
144262
|
-
const recent = (0, import_fs24.readdirSync)(projectsDir).filter((f2) => f2.endsWith(".jsonl")).map((f2) => ({ f: f2, mtime: (0, import_fs24.statSync)((0,
|
|
144263
|
-
if (recent) resolvedFilePath = (0,
|
|
144485
|
+
const recent = (0, import_fs24.readdirSync)(projectsDir).filter((f2) => f2.endsWith(".jsonl")).map((f2) => ({ f: f2, mtime: (0, import_fs24.statSync)((0, import_path22.join)(projectsDir, f2)).mtimeMs })).filter(({ mtime }) => now - mtime < 5e3).sort((a, b2) => b2.mtime - a.mtime)[0];
|
|
144486
|
+
if (recent) resolvedFilePath = (0, import_path22.join)(projectsDir, recent.f);
|
|
144264
144487
|
} catch {
|
|
144265
144488
|
}
|
|
144266
144489
|
}
|
|
@@ -144311,7 +144534,7 @@ var StreamerServer = class {
|
|
|
144311
144534
|
watchForCodexRollout(sessionId, projectPath) {
|
|
144312
144535
|
const deadline = Date.now() + 12e4;
|
|
144313
144536
|
const now = /* @__PURE__ */ new Date();
|
|
144314
|
-
const dateDir = (0,
|
|
144537
|
+
const dateDir = (0, import_path22.join)(
|
|
144315
144538
|
String(now.getFullYear()),
|
|
144316
144539
|
String(now.getMonth() + 1).padStart(2, "0"),
|
|
144317
144540
|
String(now.getDate()).padStart(2, "0")
|
|
@@ -144352,7 +144575,7 @@ var StreamerServer = class {
|
|
|
144352
144575
|
this.sessionStore.listManaged().filter((s3) => s3.id !== sessionId && s3.boundConversationId != null).map((s3) => s3.boundConversationId)
|
|
144353
144576
|
);
|
|
144354
144577
|
for (const root of this.codexRoots) {
|
|
144355
|
-
const sessionsDir = (0,
|
|
144578
|
+
const sessionsDir = (0, import_path22.join)(root, dateDir);
|
|
144356
144579
|
if (!(0, import_fs24.existsSync)(sessionsDir)) continue;
|
|
144357
144580
|
let candidateFiles;
|
|
144358
144581
|
try {
|
|
@@ -144361,9 +144584,9 @@ var StreamerServer = class {
|
|
|
144361
144584
|
continue;
|
|
144362
144585
|
}
|
|
144363
144586
|
const nowMs = Date.now();
|
|
144364
|
-
const recentCandidates = candidateFiles.map((f2) => ({ f: f2, mtime: (0, import_fs24.statSync)((0,
|
|
144587
|
+
const recentCandidates = candidateFiles.map((f2) => ({ f: f2, mtime: (0, import_fs24.statSync)((0, import_path22.join)(sessionsDir, f2)).mtimeMs })).filter(({ mtime }) => nowMs - mtime < 1e4).sort((a, b2) => b2.mtime - a.mtime);
|
|
144365
144588
|
for (const { f: f2 } of recentCandidates) {
|
|
144366
|
-
const candidatePath = (0,
|
|
144589
|
+
const candidatePath = (0, import_path22.join)(sessionsDir, f2);
|
|
144367
144590
|
const match2 = matchesProjectPath(candidatePath);
|
|
144368
144591
|
if (!match2) continue;
|
|
144369
144592
|
if (boundElsewhere.has(match2.id)) continue;
|
|
@@ -144817,7 +145040,7 @@ function isBrewInstall(scriptPath = process.argv[1] ?? "") {
|
|
|
144817
145040
|
var import_node_crypto4 = require("crypto");
|
|
144818
145041
|
var import_node_fs8 = require("fs");
|
|
144819
145042
|
var import_node_path10 = require("path");
|
|
144820
|
-
var
|
|
145043
|
+
var import_promises18 = require("stream/promises");
|
|
144821
145044
|
|
|
144822
145045
|
// src/updater/manifest.ts
|
|
144823
145046
|
init_zod();
|
|
@@ -144892,7 +145115,7 @@ async function downloadAndVerify(opts) {
|
|
|
144892
145115
|
}
|
|
144893
145116
|
});
|
|
144894
145117
|
try {
|
|
144895
|
-
await (0,
|
|
145118
|
+
await (0, import_promises18.pipeline)(res.body.pipeThrough(measured), out);
|
|
144896
145119
|
} catch (err) {
|
|
144897
145120
|
(0, import_node_fs8.rmSync)(targetPath, { force: true });
|
|
144898
145121
|
throw err;
|
|
@@ -145084,7 +145307,7 @@ var import_node_stream3 = __toESM(require("stream"), 1);
|
|
|
145084
145307
|
var import_node_string_decoder = require("string_decoder");
|
|
145085
145308
|
var import_node_path14 = __toESM(require("path"), 1);
|
|
145086
145309
|
var import_node_fs11 = __toESM(require("fs"), 1);
|
|
145087
|
-
var
|
|
145310
|
+
var import_path23 = require("path");
|
|
145088
145311
|
var import_events5 = require("events");
|
|
145089
145312
|
var import_assert = __toESM(require("assert"), 1);
|
|
145090
145313
|
var import_buffer2 = require("buffer");
|
|
@@ -145094,9 +145317,9 @@ var import_node_path15 = require("path");
|
|
|
145094
145317
|
var import_node_path16 = require("path");
|
|
145095
145318
|
var import_fs26 = __toESM(require("fs"), 1);
|
|
145096
145319
|
var import_fs27 = __toESM(require("fs"), 1);
|
|
145097
|
-
var import_path23 = __toESM(require("path"), 1);
|
|
145098
|
-
var import_node_path17 = require("path");
|
|
145099
145320
|
var import_path24 = __toESM(require("path"), 1);
|
|
145321
|
+
var import_node_path17 = require("path");
|
|
145322
|
+
var import_path25 = __toESM(require("path"), 1);
|
|
145100
145323
|
var import_node_fs12 = __toESM(require("fs"), 1);
|
|
145101
145324
|
var import_node_assert = __toESM(require("assert"), 1);
|
|
145102
145325
|
var import_node_crypto5 = require("crypto");
|
|
@@ -145106,7 +145329,7 @@ var import_fs28 = __toESM(require("fs"), 1);
|
|
|
145106
145329
|
var import_node_fs14 = __toESM(require("fs"), 1);
|
|
145107
145330
|
var import_node_path19 = __toESM(require("path"), 1);
|
|
145108
145331
|
var import_node_fs15 = __toESM(require("fs"), 1);
|
|
145109
|
-
var
|
|
145332
|
+
var import_promises19 = __toESM(require("fs/promises"), 1);
|
|
145110
145333
|
var import_node_path20 = __toESM(require("path"), 1);
|
|
145111
145334
|
var import_node_path21 = require("path");
|
|
145112
145335
|
var import_node_fs16 = __toESM(require("fs"), 1);
|
|
@@ -146461,11 +146684,11 @@ var vn = (s3) => {
|
|
|
146461
146684
|
};
|
|
146462
146685
|
var Qi = (s3, t2) => {
|
|
146463
146686
|
let e = new Map(t2.map((n) => [ut(n), true])), i = s3.filter, r = (n, o = "") => {
|
|
146464
|
-
let h = o || (0,
|
|
146687
|
+
let h = o || (0, import_path23.parse)(n).root || ".", a;
|
|
146465
146688
|
if (n === h) a = false;
|
|
146466
146689
|
else {
|
|
146467
146690
|
let l = e.get(n);
|
|
146468
|
-
a = l !== void 0 ? l : r((0,
|
|
146691
|
+
a = l !== void 0 ? l : r((0, import_path23.dirname)(n), h);
|
|
146469
146692
|
}
|
|
146470
146693
|
return e.set(n, a), a;
|
|
146471
146694
|
};
|
|
@@ -146585,7 +146808,7 @@ var de = class extends A {
|
|
|
146585
146808
|
let [o, h] = ce(this.path);
|
|
146586
146809
|
o && typeof h == "string" && (this.path = h, r = o);
|
|
146587
146810
|
}
|
|
146588
|
-
this.win32 = !!i.win32 || process.platform === "win32", this.win32 && (this.path = Qs(this.path.replaceAll(/\\/g, "/")), t2 = t2.replaceAll(/\\/g, "/")), this.absolute = f(i.absolute ||
|
|
146811
|
+
this.win32 = !!i.win32 || process.platform === "win32", this.win32 && (this.path = Qs(this.path.replaceAll(/\\/g, "/")), t2 = t2.replaceAll(/\\/g, "/")), this.absolute = f(i.absolute || import_path24.default.resolve(this.cwd, t2)), this.path === "" && (this.path = "./"), r && this.warn("TAR_ENTRY_INFO", `stripping ${r} from absolute path`, { entry: this, path: r + this.path });
|
|
146589
146812
|
let n = this.statCache.get(this.absolute);
|
|
146590
146813
|
n ? this[si](n) : this[ss]();
|
|
146591
146814
|
}
|
|
@@ -146644,7 +146867,7 @@ var de = class extends A {
|
|
|
146644
146867
|
}
|
|
146645
146868
|
[sr](t2) {
|
|
146646
146869
|
if (!this.stat) throw new Error("cannot create link entry without stat");
|
|
146647
|
-
this.type = "Link", this.linkpath = f(
|
|
146870
|
+
this.type = "Link", this.linkpath = f(import_path24.default.relative(this.cwd, t2)), this.stat.size = 0, this[fe](), this.end();
|
|
146648
146871
|
}
|
|
146649
146872
|
[er]() {
|
|
146650
146873
|
if (!this.stat) throw new Error("cannot create file entry without stat");
|
|
@@ -147058,7 +147281,7 @@ var wt = class extends A {
|
|
|
147058
147281
|
return typeof t2 == "string" ? this[ci](t2) : this[or](t2), this.flowing;
|
|
147059
147282
|
}
|
|
147060
147283
|
[or](t2) {
|
|
147061
|
-
let e = f(
|
|
147284
|
+
let e = f(import_path25.default.resolve(this.cwd, t2.path));
|
|
147062
147285
|
if (!this.filter(t2.path, t2)) t2.resume();
|
|
147063
147286
|
else {
|
|
147064
147287
|
let i = new pi(t2.path, e);
|
|
@@ -147067,7 +147290,7 @@ var wt = class extends A {
|
|
|
147067
147290
|
this[Ft]();
|
|
147068
147291
|
}
|
|
147069
147292
|
[ci](t2) {
|
|
147070
|
-
let e = f(
|
|
147293
|
+
let e = f(import_path25.default.resolve(this.cwd, t2));
|
|
147071
147294
|
this[W].push(new pi(t2, e)), this[Ft]();
|
|
147072
147295
|
}
|
|
147073
147296
|
[ds](t2) {
|
|
@@ -147338,7 +147561,7 @@ var gr = (s3, t2, e) => {
|
|
|
147338
147561
|
E2 ? e(E2) : x2 && a ? Es(x2, o, h, (Le) => S2(Le)) : n ? import_node_fs15.default.chmod(s3, r, e) : e();
|
|
147339
147562
|
};
|
|
147340
147563
|
if (s3 === d) return no(s3, S2);
|
|
147341
|
-
if (l) return
|
|
147564
|
+
if (l) return import_promises19.default.mkdir(s3, { mode: r, recursive: true }).then((E2) => S2(null, E2 ?? void 0), S2);
|
|
147342
147565
|
let D2 = f(import_node_path20.default.relative(d, s3)).split("/");
|
|
147343
147566
|
Ss(d, D2, r, c, d, void 0, S2);
|
|
147344
147567
|
};
|