chat-recall 0.7.18 → 0.7.19
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/README.md +2 -2
- package/dist/cli.js +873 -248
- package/dist/cli.js.map +1 -1
- package/dist/mcp-relay.js +1 -1
- package/dist/mcp.js +799 -179
- package/dist/scan-worker.js +615 -31
- package/dist/sync-client.d.ts.map +1 -1
- package/dist/sync-client.js +24 -10
- package/dist/sync-client.js.map +1 -1
- package/dist/sync-ledger.d.ts +6 -0
- package/dist/sync-ledger.d.ts.map +1 -1
- package/dist/sync-ledger.js +3 -0
- package/dist/sync-ledger.js.map +1 -1
- package/dist/watch.js +801 -170
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -4586,6 +4586,8 @@ function declaredOrigin(value) {
|
|
|
4586
4586
|
function userRecordOrigin(obj, text) {
|
|
4587
4587
|
if (obj.isSidechain === true)
|
|
4588
4588
|
return "subagent";
|
|
4589
|
+
if (obj.isCompactSummary === true)
|
|
4590
|
+
return "compact-summary";
|
|
4589
4591
|
const declared = declaredOrigin(obj.origin);
|
|
4590
4592
|
if (declared && declared !== "human")
|
|
4591
4593
|
return declared;
|
|
@@ -4769,6 +4771,7 @@ function defaultSourcesEnabled() {
|
|
|
4769
4771
|
commands: true
|
|
4770
4772
|
},
|
|
4771
4773
|
cursor: { sessions: true, skills: true, agents: true, commands: true },
|
|
4774
|
+
hermes: { sessions: true },
|
|
4772
4775
|
shared: { skills: true },
|
|
4773
4776
|
common: { mcps: true, agentMd: true }
|
|
4774
4777
|
};
|
|
@@ -4845,6 +4848,7 @@ function mergeSources(base4, partial) {
|
|
|
4845
4848
|
codex: { ...base4.enabled.codex, ...partial.enabled?.codex ?? {} },
|
|
4846
4849
|
agy: { ...base4.enabled.agy, ...inherited, ...partial.enabled?.agy ?? {} },
|
|
4847
4850
|
cursor: { ...base4.enabled.cursor, ...partial.enabled?.cursor ?? {} },
|
|
4851
|
+
hermes: { ...base4.enabled.hermes, ...partial.enabled?.hermes ?? {} },
|
|
4848
4852
|
shared: { ...base4.enabled.shared, ...partial.enabled?.shared ?? {} },
|
|
4849
4853
|
common: { ...base4.enabled.common, ...partial.enabled?.common ?? {} }
|
|
4850
4854
|
};
|
|
@@ -4856,6 +4860,7 @@ function mergeSources(base4, partial) {
|
|
|
4856
4860
|
agyHome: partial.agyHome ?? base4.agyHome,
|
|
4857
4861
|
cursorHome: partial.cursorHome ?? base4.cursorHome,
|
|
4858
4862
|
cursorIdeHome: partial.cursorIdeHome ?? base4.cursorIdeHome,
|
|
4863
|
+
hermesHome: partial.hermesHome ?? base4.hermesHome,
|
|
4859
4864
|
extraClaudeHomes: partial.extraClaudeHomes ?? base4.extraClaudeHomes,
|
|
4860
4865
|
approvedHomes: partial.approvedHomes ?? base4.approvedHomes,
|
|
4861
4866
|
declinedHomes: partial.declinedHomes ?? base4.declinedHomes,
|
|
@@ -5180,6 +5185,7 @@ var home_approval_exports = {};
|
|
|
5180
5185
|
__export(home_approval_exports, {
|
|
5181
5186
|
approveHome: () => approveHome,
|
|
5182
5187
|
declineHome: () => declineHome,
|
|
5188
|
+
defaultHermesHome: () => defaultHermesHome,
|
|
5183
5189
|
grandfatherLegacyHomes: () => grandfatherLegacyHomes,
|
|
5184
5190
|
homeDecision: () => homeDecision,
|
|
5185
5191
|
isHomeSynced: () => isHomeSynced,
|
|
@@ -5262,6 +5268,13 @@ function grandfatherLegacyHomes() {
|
|
|
5262
5268
|
}
|
|
5263
5269
|
return { seeded };
|
|
5264
5270
|
}
|
|
5271
|
+
function defaultHermesHome() {
|
|
5272
|
+
if (process.platform === "win32") {
|
|
5273
|
+
const local = process.env.LOCALAPPDATA?.trim() || join3(homedir2(), "AppData", "Local");
|
|
5274
|
+
return join3(local, "hermes");
|
|
5275
|
+
}
|
|
5276
|
+
return join3(homedir2(), ".hermes");
|
|
5277
|
+
}
|
|
5265
5278
|
function primaryHomes() {
|
|
5266
5279
|
const home = homedir2();
|
|
5267
5280
|
const env = process.env;
|
|
@@ -5278,7 +5291,8 @@ function primaryHomes() {
|
|
|
5278
5291
|
env.CHAT_RECALL_CODEX_HOME || s?.codexHome || join3(home, ".codex"),
|
|
5279
5292
|
env.CHAT_RECALL_AGY_HOME || s?.agyHome || join3(home, ".gemini", "antigravity-cli"),
|
|
5280
5293
|
env.CHAT_RECALL_CURSOR_HOME || s?.cursorHome || join3(home, ".cursor"),
|
|
5281
|
-
dirOf(opencodeDb)
|
|
5294
|
+
dirOf(opencodeDb),
|
|
5295
|
+
env.CHAT_RECALL_HERMES_HOME || s?.hermesHome || env.HERMES_HOME?.trim() || defaultHermesHome()
|
|
5282
5296
|
];
|
|
5283
5297
|
return candidates2.map(normalizeHomePath);
|
|
5284
5298
|
}
|
|
@@ -5405,6 +5419,9 @@ function geminiHomeDir() {
|
|
|
5405
5419
|
function opencodeDbPath() {
|
|
5406
5420
|
return process.env.CHAT_RECALL_OPENCODE_DB || sources().opencodeDbPath || join4(homedir3(), ".local", "share", "opencode", "opencode.db");
|
|
5407
5421
|
}
|
|
5422
|
+
function hermesHomeDir() {
|
|
5423
|
+
return process.env.CHAT_RECALL_HERMES_HOME || sources().hermesHome || process.env.HERMES_HOME?.trim() || defaultHermesHome();
|
|
5424
|
+
}
|
|
5408
5425
|
function codexHomeDir() {
|
|
5409
5426
|
return process.env.CHAT_RECALL_CODEX_HOME || sources().codexHome || join4(homedir3(), ".codex");
|
|
5410
5427
|
}
|
|
@@ -5506,6 +5523,22 @@ function opencodeDbPaths(opts = {}) {
|
|
|
5506
5523
|
dbs.push(primary);
|
|
5507
5524
|
return applyExclusions(dbs, opts.includeExcluded);
|
|
5508
5525
|
}
|
|
5526
|
+
function hermesDbPaths(opts = {}) {
|
|
5527
|
+
const root = hermesHomeDir();
|
|
5528
|
+
const dbs = [join4(root, "state.db")];
|
|
5529
|
+
try {
|
|
5530
|
+
const profiles = join4(root, "profiles");
|
|
5531
|
+
for (const entry of readdirSync3(profiles, { withFileTypes: true })) {
|
|
5532
|
+
if (!entry.isDirectory())
|
|
5533
|
+
continue;
|
|
5534
|
+
const p = join4(profiles, entry.name, "state.db");
|
|
5535
|
+
if (existsSync4(p))
|
|
5536
|
+
dbs.push(p);
|
|
5537
|
+
}
|
|
5538
|
+
} catch {
|
|
5539
|
+
}
|
|
5540
|
+
return applyExclusions(dbs, opts.includeExcluded);
|
|
5541
|
+
}
|
|
5509
5542
|
function extraClaudeHomeDirs() {
|
|
5510
5543
|
const extras = sources().extraClaudeHomes ?? [];
|
|
5511
5544
|
const primary = claudeHomeDir();
|
|
@@ -6574,7 +6607,7 @@ function canonicalEventsToMessages(events) {
|
|
|
6574
6607
|
switch (e.kind) {
|
|
6575
6608
|
case "user":
|
|
6576
6609
|
cur = null;
|
|
6577
|
-
messages.push({ line: e.line, role: "user", content: e.text ?? "", timestamp: e.tsIso });
|
|
6610
|
+
messages.push({ line: e.line, role: "user", content: e.text ?? "", timestamp: e.tsIso, ...e.origin ? { origin: e.origin } : {} });
|
|
6578
6611
|
break;
|
|
6579
6612
|
case "assistant_text":
|
|
6580
6613
|
cur = { line: e.line, role: "assistant", content: e.text ?? "", timestamp: e.tsIso };
|
|
@@ -8459,6 +8492,71 @@ function readTailFromOffset(path, offset, maxBytes = TAIL_READ_MAX_BYTES) {
|
|
|
8459
8492
|
}
|
|
8460
8493
|
}
|
|
8461
8494
|
}
|
|
8495
|
+
function readSourcesFromOffset(paths, offset, maxBytes = TAIL_READ_MAX_BYTES) {
|
|
8496
|
+
let start = 0;
|
|
8497
|
+
let linesBefore = 0;
|
|
8498
|
+
for (let i = 0; i < paths.length; i++) {
|
|
8499
|
+
const path = paths[i];
|
|
8500
|
+
let size = 0;
|
|
8501
|
+
try {
|
|
8502
|
+
size = statSync4(path).size;
|
|
8503
|
+
} catch {
|
|
8504
|
+
size = 0;
|
|
8505
|
+
}
|
|
8506
|
+
const last = i === paths.length - 1;
|
|
8507
|
+
if (!last && offset >= start + size) {
|
|
8508
|
+
const lines = linesBeforeOffset(path, size);
|
|
8509
|
+
if (lines === void 0)
|
|
8510
|
+
return { text: "", newOffset: offset };
|
|
8511
|
+
linesBefore += lines + (size > 0 && !endsWithNewline(path, size) ? 1 : 0);
|
|
8512
|
+
start += size;
|
|
8513
|
+
continue;
|
|
8514
|
+
}
|
|
8515
|
+
const local = offset - start;
|
|
8516
|
+
const read = readTailFromOffset(path, local, maxBytes);
|
|
8517
|
+
const shift = (r) => ({
|
|
8518
|
+
...r,
|
|
8519
|
+
newOffset: start + r.newOffset,
|
|
8520
|
+
...r.baseLine !== void 0 ? { baseLine: linesBefore + r.baseLine } : {}
|
|
8521
|
+
});
|
|
8522
|
+
if (last || read.newOffset > local || local >= size)
|
|
8523
|
+
return shift(read);
|
|
8524
|
+
if (size - local > maxBytes)
|
|
8525
|
+
return { text: "", newOffset: start + size, skippedBytes: size - local };
|
|
8526
|
+
let fd = null;
|
|
8527
|
+
try {
|
|
8528
|
+
fd = openSync2(path, "r");
|
|
8529
|
+
const text = readAt(fd, local, size - local).toString("utf-8");
|
|
8530
|
+
return shift({ text, newOffset: size, baseLine: linesBeforeOffset(path, local) });
|
|
8531
|
+
} catch {
|
|
8532
|
+
return { text: "", newOffset: offset };
|
|
8533
|
+
} finally {
|
|
8534
|
+
if (fd !== null) {
|
|
8535
|
+
try {
|
|
8536
|
+
closeSync2(fd);
|
|
8537
|
+
} catch {
|
|
8538
|
+
}
|
|
8539
|
+
}
|
|
8540
|
+
}
|
|
8541
|
+
}
|
|
8542
|
+
return { text: "", newOffset: offset };
|
|
8543
|
+
}
|
|
8544
|
+
function endsWithNewline(path, size) {
|
|
8545
|
+
let fd = null;
|
|
8546
|
+
try {
|
|
8547
|
+
fd = openSync2(path, "r");
|
|
8548
|
+
return readAt(fd, size - 1, 1)[0] === 10;
|
|
8549
|
+
} catch {
|
|
8550
|
+
return true;
|
|
8551
|
+
} finally {
|
|
8552
|
+
if (fd !== null) {
|
|
8553
|
+
try {
|
|
8554
|
+
closeSync2(fd);
|
|
8555
|
+
} catch {
|
|
8556
|
+
}
|
|
8557
|
+
}
|
|
8558
|
+
}
|
|
8559
|
+
}
|
|
8462
8560
|
function findNewline(fd, from, size) {
|
|
8463
8561
|
const block = Buffer.allocUnsafe(SKIP_SCAN_BYTES);
|
|
8464
8562
|
let pos = from;
|
|
@@ -10937,6 +11035,473 @@ var init_cursor = __esm({
|
|
|
10937
11035
|
}
|
|
10938
11036
|
});
|
|
10939
11037
|
|
|
11038
|
+
// ../engine/dist/core/backends/hermes.js
|
|
11039
|
+
import { existsSync as existsSync12 } from "fs";
|
|
11040
|
+
function firstUserPrompt(db, sessionId) {
|
|
11041
|
+
try {
|
|
11042
|
+
const row = db.prepare(`
|
|
11043
|
+
SELECT substr(content, 1, 400) AS text FROM messages
|
|
11044
|
+
WHERE session_id = ? AND role = 'user' AND active = 1 AND _compressed_summary = 0
|
|
11045
|
+
AND (display_kind IS NULL OR display_kind = 'steer')
|
|
11046
|
+
AND length(trim(content)) > 0
|
|
11047
|
+
ORDER BY id LIMIT 1
|
|
11048
|
+
`).get(sessionId);
|
|
11049
|
+
return row?.text ? flatString(row.text.slice(0, 200)) : "";
|
|
11050
|
+
} catch {
|
|
11051
|
+
return "";
|
|
11052
|
+
}
|
|
11053
|
+
}
|
|
11054
|
+
function messageRowsToEvents(rows) {
|
|
11055
|
+
const events = [];
|
|
11056
|
+
let line = 0;
|
|
11057
|
+
for (const r of rows) {
|
|
11058
|
+
line++;
|
|
11059
|
+
if (r.active === 0)
|
|
11060
|
+
continue;
|
|
11061
|
+
if (r.display_kind === "failed_turn" || r.display_kind === "hidden")
|
|
11062
|
+
continue;
|
|
11063
|
+
const ts = Math.round((r.timestamp || 0) * 1e3);
|
|
11064
|
+
const tsIso = ts ? new Date(ts).toISOString() : void 0;
|
|
11065
|
+
const text = (r.content ?? "").trim();
|
|
11066
|
+
if (r._compressed_summary === 1) {
|
|
11067
|
+
if (text)
|
|
11068
|
+
events.push({ kind: "summary", ts, tsIso, line, text });
|
|
11069
|
+
continue;
|
|
11070
|
+
}
|
|
11071
|
+
if (r.role === "user") {
|
|
11072
|
+
if (!text)
|
|
11073
|
+
continue;
|
|
11074
|
+
events.push({
|
|
11075
|
+
kind: "user",
|
|
11076
|
+
ts,
|
|
11077
|
+
tsIso,
|
|
11078
|
+
line,
|
|
11079
|
+
text,
|
|
11080
|
+
...r.display_kind === "process_complete" ? { origin: "task-notification" } : {}
|
|
11081
|
+
});
|
|
11082
|
+
continue;
|
|
11083
|
+
}
|
|
11084
|
+
if (r.role === "assistant") {
|
|
11085
|
+
if (text)
|
|
11086
|
+
events.push({ kind: "assistant_text", ts, tsIso, line, text });
|
|
11087
|
+
for (const call2 of parseToolCalls(r.tool_calls)) {
|
|
11088
|
+
const toolName = call2.function?.name ?? "";
|
|
11089
|
+
const toolInput = parseArguments(call2.function?.arguments);
|
|
11090
|
+
const command = toolName === "terminal" && typeof toolInput?.command === "string" ? toolInput.command : void 0;
|
|
11091
|
+
events.push({
|
|
11092
|
+
kind: "tool_use",
|
|
11093
|
+
ts,
|
|
11094
|
+
tsIso,
|
|
11095
|
+
line,
|
|
11096
|
+
toolName,
|
|
11097
|
+
toolUseId: call2.id || call2.call_id || `${r.id}:${toolName}`,
|
|
11098
|
+
toolInput,
|
|
11099
|
+
...command ? { command } : {}
|
|
11100
|
+
});
|
|
11101
|
+
}
|
|
11102
|
+
continue;
|
|
11103
|
+
}
|
|
11104
|
+
if (r.role === "tool") {
|
|
11105
|
+
const body2 = r.content ?? "";
|
|
11106
|
+
const { exitCode, isError } = toolResultStatus(body2);
|
|
11107
|
+
events.push({
|
|
11108
|
+
kind: "tool_result",
|
|
11109
|
+
ts,
|
|
11110
|
+
tsIso,
|
|
11111
|
+
line,
|
|
11112
|
+
toolUseId: r.tool_call_id ?? void 0,
|
|
11113
|
+
toolName: r.tool_name ?? void 0,
|
|
11114
|
+
resultBody: body2,
|
|
11115
|
+
resultIsError: isError,
|
|
11116
|
+
...exitCode !== void 0 ? { resultExitCode: exitCode } : {},
|
|
11117
|
+
resultBytes: Buffer.byteLength(body2)
|
|
11118
|
+
});
|
|
11119
|
+
}
|
|
11120
|
+
}
|
|
11121
|
+
return events;
|
|
11122
|
+
}
|
|
11123
|
+
function parseToolCalls(json) {
|
|
11124
|
+
if (!json)
|
|
11125
|
+
return [];
|
|
11126
|
+
try {
|
|
11127
|
+
const calls = JSON.parse(json);
|
|
11128
|
+
return Array.isArray(calls) ? calls : [];
|
|
11129
|
+
} catch {
|
|
11130
|
+
return [];
|
|
11131
|
+
}
|
|
11132
|
+
}
|
|
11133
|
+
function parseArguments(args) {
|
|
11134
|
+
if (typeof args !== "string")
|
|
11135
|
+
return args ?? {};
|
|
11136
|
+
try {
|
|
11137
|
+
return JSON.parse(args);
|
|
11138
|
+
} catch {
|
|
11139
|
+
return { raw: args };
|
|
11140
|
+
}
|
|
11141
|
+
}
|
|
11142
|
+
function toolResultStatus(body2) {
|
|
11143
|
+
if (!body2.startsWith("{"))
|
|
11144
|
+
return { isError: false };
|
|
11145
|
+
try {
|
|
11146
|
+
const r = JSON.parse(body2);
|
|
11147
|
+
const exitCode = typeof r.exit_code === "number" ? r.exit_code : void 0;
|
|
11148
|
+
const hasError = r.error !== void 0 && r.error !== null && r.error !== "";
|
|
11149
|
+
return { exitCode, isError: hasError || exitCode !== void 0 && exitCode !== 0 };
|
|
11150
|
+
} catch {
|
|
11151
|
+
return { isError: false };
|
|
11152
|
+
}
|
|
11153
|
+
}
|
|
11154
|
+
var PREFIX5, MESSAGE_COLUMNS, ARCHIVED_SESSION_COLUMNS, SESSION_MTIME_SQL, HermesBackend, hermesBackend;
|
|
11155
|
+
var init_hermes = __esm({
|
|
11156
|
+
"../engine/dist/core/backends/hermes.js"() {
|
|
11157
|
+
"use strict";
|
|
11158
|
+
init_sqlite_reader();
|
|
11159
|
+
init_tool_paths();
|
|
11160
|
+
init_session_outcome();
|
|
11161
|
+
init_session_git();
|
|
11162
|
+
init_generic_engine();
|
|
11163
|
+
init_flat_string();
|
|
11164
|
+
PREFIX5 = "hermes_";
|
|
11165
|
+
MESSAGE_COLUMNS = "id, role, content, tool_calls, tool_call_id, tool_name, timestamp, display_kind, active, _compressed_summary";
|
|
11166
|
+
ARCHIVED_SESSION_COLUMNS = [
|
|
11167
|
+
"id",
|
|
11168
|
+
"source",
|
|
11169
|
+
"title",
|
|
11170
|
+
"model",
|
|
11171
|
+
"cwd",
|
|
11172
|
+
"git_branch",
|
|
11173
|
+
"git_repo_root",
|
|
11174
|
+
"parent_session_id",
|
|
11175
|
+
"started_at",
|
|
11176
|
+
"ended_at",
|
|
11177
|
+
"end_reason",
|
|
11178
|
+
"message_count",
|
|
11179
|
+
"tool_call_count",
|
|
11180
|
+
"input_tokens",
|
|
11181
|
+
"output_tokens",
|
|
11182
|
+
"cache_read_tokens",
|
|
11183
|
+
"cache_write_tokens",
|
|
11184
|
+
"reasoning_tokens",
|
|
11185
|
+
"estimated_cost_usd",
|
|
11186
|
+
"actual_cost_usd"
|
|
11187
|
+
];
|
|
11188
|
+
SESSION_MTIME_SQL = `MAX(
|
|
11189
|
+
s.started_at,
|
|
11190
|
+
COALESCE(s.ended_at, 0),
|
|
11191
|
+
COALESCE(s.last_activity_at, 0),
|
|
11192
|
+
COALESCE((SELECT MAX(m.timestamp) FROM messages m WHERE m.session_id = s.id), 0)
|
|
11193
|
+
)`;
|
|
11194
|
+
HermesBackend = class {
|
|
11195
|
+
id = "hermes";
|
|
11196
|
+
idPrefix = PREFIX5;
|
|
11197
|
+
displayName = "Hermes";
|
|
11198
|
+
homeDir() {
|
|
11199
|
+
return hermesHomeDir();
|
|
11200
|
+
}
|
|
11201
|
+
/** Every Hermes database on this machine, the root profile first. */
|
|
11202
|
+
dbPaths() {
|
|
11203
|
+
return hermesDbPaths();
|
|
11204
|
+
}
|
|
11205
|
+
isAvailable() {
|
|
11206
|
+
return this.dbPaths().some((p) => existsSync12(p));
|
|
11207
|
+
}
|
|
11208
|
+
/** The database that holds this session. A session id is unique within a
|
|
11209
|
+
* database, and each named profile has its own. */
|
|
11210
|
+
dbPathFor(rawId) {
|
|
11211
|
+
const cached = this._dbForSession.get(rawId);
|
|
11212
|
+
if (cached)
|
|
11213
|
+
return cached;
|
|
11214
|
+
for (const path of this.dbPaths()) {
|
|
11215
|
+
const db = openSqliteReadonly(path);
|
|
11216
|
+
if (!db)
|
|
11217
|
+
continue;
|
|
11218
|
+
try {
|
|
11219
|
+
if (db.prepare("SELECT 1 AS ok FROM sessions WHERE id = ?").get(rawId)) {
|
|
11220
|
+
this._dbForSession.set(rawId, path);
|
|
11221
|
+
return path;
|
|
11222
|
+
}
|
|
11223
|
+
} catch {
|
|
11224
|
+
} finally {
|
|
11225
|
+
db.close();
|
|
11226
|
+
}
|
|
11227
|
+
}
|
|
11228
|
+
return null;
|
|
11229
|
+
}
|
|
11230
|
+
_dbForSession = /* @__PURE__ */ new Map();
|
|
11231
|
+
/** Tests, and anything that adds a profile mid-process. */
|
|
11232
|
+
_clearDbRouting() {
|
|
11233
|
+
this._dbForSession.clear();
|
|
11234
|
+
}
|
|
11235
|
+
// ── ID handling ────────────────────────────────────────────────
|
|
11236
|
+
matchesId(id) {
|
|
11237
|
+
return id.startsWith(PREFIX5);
|
|
11238
|
+
}
|
|
11239
|
+
toRawId(id) {
|
|
11240
|
+
return id.startsWith(PREFIX5) ? id.slice(PREFIX5.length) : id;
|
|
11241
|
+
}
|
|
11242
|
+
toPrefixedId(rawId) {
|
|
11243
|
+
return rawId.startsWith(PREFIX5) ? rawId : PREFIX5 + rawId;
|
|
11244
|
+
}
|
|
11245
|
+
// ── Location ───────────────────────────────────────────────────
|
|
11246
|
+
findSession(id) {
|
|
11247
|
+
const rawId = this.toRawId(id);
|
|
11248
|
+
const path = this.dbPathFor(rawId);
|
|
11249
|
+
if (!path)
|
|
11250
|
+
return null;
|
|
11251
|
+
const db = openSqliteReadonly(path);
|
|
11252
|
+
if (!db)
|
|
11253
|
+
return null;
|
|
11254
|
+
try {
|
|
11255
|
+
const row = db.prepare(`
|
|
11256
|
+
SELECT s.cwd, s.git_repo_root, ${SESSION_MTIME_SQL} AS mtime
|
|
11257
|
+
FROM sessions s WHERE s.id = ?
|
|
11258
|
+
`).get(rawId);
|
|
11259
|
+
if (!row)
|
|
11260
|
+
return null;
|
|
11261
|
+
return {
|
|
11262
|
+
path,
|
|
11263
|
+
format: "sqlite",
|
|
11264
|
+
projectDir: "",
|
|
11265
|
+
projectPath: row.git_repo_root || row.cwd || "",
|
|
11266
|
+
mtime: Math.round((row.mtime || 0) * 1e3)
|
|
11267
|
+
};
|
|
11268
|
+
} catch {
|
|
11269
|
+
return null;
|
|
11270
|
+
} finally {
|
|
11271
|
+
db.close();
|
|
11272
|
+
}
|
|
11273
|
+
}
|
|
11274
|
+
listSessions(opts = {}) {
|
|
11275
|
+
const byId = /* @__PURE__ */ new Map();
|
|
11276
|
+
for (const dbPath of this.dbPaths()) {
|
|
11277
|
+
if (!existsSync12(dbPath))
|
|
11278
|
+
continue;
|
|
11279
|
+
for (const ref of this.listSessionsInDb(dbPath, opts)) {
|
|
11280
|
+
const prior = byId.get(ref.rawId);
|
|
11281
|
+
if (!prior || ref.mtime > prior.mtime)
|
|
11282
|
+
byId.set(ref.rawId, ref);
|
|
11283
|
+
}
|
|
11284
|
+
}
|
|
11285
|
+
const all = [...byId.values()].sort((a, b) => b.mtime - a.mtime);
|
|
11286
|
+
return opts.limit ? all.slice(0, opts.limit) : all;
|
|
11287
|
+
}
|
|
11288
|
+
listSessionsInDb(dbPath, opts) {
|
|
11289
|
+
const cutoffSec = (opts.sinceMs ?? 0) / 1e3;
|
|
11290
|
+
const filter = opts.projectFilter?.toLowerCase();
|
|
11291
|
+
const db = openSqliteReadonly(dbPath);
|
|
11292
|
+
if (!db)
|
|
11293
|
+
return [];
|
|
11294
|
+
try {
|
|
11295
|
+
const rows = db.prepare(`
|
|
11296
|
+
SELECT * FROM (
|
|
11297
|
+
SELECT s.id, s.cwd, s.git_repo_root, s.started_at, s.message_count,
|
|
11298
|
+
${SESSION_MTIME_SQL} AS mtime
|
|
11299
|
+
FROM sessions s
|
|
11300
|
+
) WHERE mtime >= ? ORDER BY mtime DESC
|
|
11301
|
+
`).all(cutoffSec);
|
|
11302
|
+
const out = [];
|
|
11303
|
+
for (const row of rows) {
|
|
11304
|
+
const projectPath = row.git_repo_root || row.cwd || "";
|
|
11305
|
+
if (filter && !projectPath.toLowerCase().includes(filter))
|
|
11306
|
+
continue;
|
|
11307
|
+
const mtime = Math.round(row.mtime * 1e3);
|
|
11308
|
+
this._dbForSession.set(row.id, dbPath);
|
|
11309
|
+
out.push({
|
|
11310
|
+
toolId: "hermes",
|
|
11311
|
+
rawId: row.id,
|
|
11312
|
+
prefixedId: this.toPrefixedId(row.id),
|
|
11313
|
+
projectPath,
|
|
11314
|
+
projectDir: "",
|
|
11315
|
+
fullPath: dbPath,
|
|
11316
|
+
created: new Date(Math.round(row.started_at * 1e3)).toISOString(),
|
|
11317
|
+
modified: new Date(mtime).toISOString(),
|
|
11318
|
+
mtime,
|
|
11319
|
+
firstPrompt: opts.previews === false ? "" : firstUserPrompt(db, row.id),
|
|
11320
|
+
messageCount: opts.previews === false ? 0 : row.message_count ?? 0
|
|
11321
|
+
});
|
|
11322
|
+
if (opts.limit && out.length >= opts.limit)
|
|
11323
|
+
break;
|
|
11324
|
+
}
|
|
11325
|
+
return out;
|
|
11326
|
+
} catch {
|
|
11327
|
+
return [];
|
|
11328
|
+
} finally {
|
|
11329
|
+
db.close();
|
|
11330
|
+
}
|
|
11331
|
+
}
|
|
11332
|
+
/** Hermes writes a title for each session (a model-written one, or the
|
|
11333
|
+
* first prompt for a one-shot run). */
|
|
11334
|
+
getNativeTitle(rawId) {
|
|
11335
|
+
const path = this.dbPathFor(this.toRawId(rawId));
|
|
11336
|
+
if (!path)
|
|
11337
|
+
return null;
|
|
11338
|
+
const db = openSqliteReadonly(path);
|
|
11339
|
+
if (!db)
|
|
11340
|
+
return null;
|
|
11341
|
+
try {
|
|
11342
|
+
const row = db.prepare("SELECT title FROM sessions WHERE id = ?").get(this.toRawId(rawId));
|
|
11343
|
+
const t = row?.title?.trim();
|
|
11344
|
+
return t ? t.slice(0, 200) : null;
|
|
11345
|
+
} catch {
|
|
11346
|
+
return null;
|
|
11347
|
+
} finally {
|
|
11348
|
+
db.close();
|
|
11349
|
+
}
|
|
11350
|
+
}
|
|
11351
|
+
// ── Generic-engine inputs ───────────────────────────────────────
|
|
11352
|
+
fileToolMap = {
|
|
11353
|
+
write_file: "write",
|
|
11354
|
+
patch: "edit",
|
|
11355
|
+
read_file: "read"
|
|
11356
|
+
};
|
|
11357
|
+
/**
|
|
11358
|
+
* `write_file` carries `{ path, content }`. `patch` carries
|
|
11359
|
+
* `{ mode: 'replace', path, old_string, new_string }`; its other mode,
|
|
11360
|
+
* `patch`, is a multi-file V4A patch with no single before and after.
|
|
11361
|
+
*/
|
|
11362
|
+
extractEditDelta(toolName, input) {
|
|
11363
|
+
if (input == null || typeof input !== "object")
|
|
11364
|
+
return null;
|
|
11365
|
+
const inp = input;
|
|
11366
|
+
if (toolName === "write_file") {
|
|
11367
|
+
return { before: "", after: typeof inp.content === "string" ? inp.content : null };
|
|
11368
|
+
}
|
|
11369
|
+
if (toolName === "patch" && (inp.mode === void 0 || inp.mode === "replace")) {
|
|
11370
|
+
const before = typeof inp.old_string === "string" ? inp.old_string : null;
|
|
11371
|
+
const after = typeof inp.new_string === "string" ? inp.new_string : null;
|
|
11372
|
+
if (before === null && after === null)
|
|
11373
|
+
return null;
|
|
11374
|
+
return { before, after };
|
|
11375
|
+
}
|
|
11376
|
+
return null;
|
|
11377
|
+
}
|
|
11378
|
+
readEvents(rawId) {
|
|
11379
|
+
const id = this.toRawId(rawId);
|
|
11380
|
+
const path = this.dbPathFor(id);
|
|
11381
|
+
if (!path)
|
|
11382
|
+
return [];
|
|
11383
|
+
const db = openSqliteReadonly(path);
|
|
11384
|
+
if (!db)
|
|
11385
|
+
return [];
|
|
11386
|
+
try {
|
|
11387
|
+
const rows = db.prepare(`SELECT ${MESSAGE_COLUMNS} FROM messages WHERE session_id = ? ORDER BY id`).all(id);
|
|
11388
|
+
return messageRowsToEvents(rows);
|
|
11389
|
+
} catch {
|
|
11390
|
+
return [];
|
|
11391
|
+
} finally {
|
|
11392
|
+
db.close();
|
|
11393
|
+
}
|
|
11394
|
+
}
|
|
11395
|
+
/**
|
|
11396
|
+
* Events from the dump `exportRawSession` writes, for a session rebuilt from
|
|
11397
|
+
* the server's archive. The archive joins the lines of every dump it got, so
|
|
11398
|
+
* a row that changed (a rewind sets `active` to 0) is there more than once.
|
|
11399
|
+
* The last copy of each row id is the newest.
|
|
11400
|
+
*/
|
|
11401
|
+
readEventsFromText(text) {
|
|
11402
|
+
const rows = /* @__PURE__ */ new Map();
|
|
11403
|
+
for (const line of text.split("\n")) {
|
|
11404
|
+
if (!line.trim())
|
|
11405
|
+
continue;
|
|
11406
|
+
try {
|
|
11407
|
+
const rec = JSON.parse(line);
|
|
11408
|
+
if (rec.kind === "message" && rec.row) {
|
|
11409
|
+
rows.delete(rec.row.id);
|
|
11410
|
+
rows.set(rec.row.id, rec.row);
|
|
11411
|
+
}
|
|
11412
|
+
} catch {
|
|
11413
|
+
}
|
|
11414
|
+
}
|
|
11415
|
+
return messageRowsToEvents([...rows.values()].sort((a, b) => a.id - b.id));
|
|
11416
|
+
}
|
|
11417
|
+
// ── Per-session operations — all delegate to the generic engine ─
|
|
11418
|
+
extractTurns(id, opts = {}) {
|
|
11419
|
+
return extractTurnsFromEvents(this.toPrefixedId(id), this.readEvents(id), opts);
|
|
11420
|
+
}
|
|
11421
|
+
liveScanEdits(id) {
|
|
11422
|
+
const located = this.findSession(id);
|
|
11423
|
+
if (!located) {
|
|
11424
|
+
return { found: false, projectPath: "", projectDir: "", edits: [], fileMtime: 0, tool: "hermes" };
|
|
11425
|
+
}
|
|
11426
|
+
return liveScanEditsFromEvents(this.readEvents(id), this.fileToolMap, {
|
|
11427
|
+
sessionId: this.toPrefixedId(id),
|
|
11428
|
+
tool: "hermes",
|
|
11429
|
+
projectPath: located.projectPath,
|
|
11430
|
+
projectDir: located.projectDir,
|
|
11431
|
+
fileMtime: located.mtime,
|
|
11432
|
+
found: true
|
|
11433
|
+
});
|
|
11434
|
+
}
|
|
11435
|
+
replay(id) {
|
|
11436
|
+
const located = this.findSession(id);
|
|
11437
|
+
if (!located) {
|
|
11438
|
+
return { sessionId: this.toPrefixedId(id), found: false, projectPath: "", files: [], totalLinesAdded: 0, totalLinesRemoved: 0 };
|
|
11439
|
+
}
|
|
11440
|
+
return replayFromEvents(this.toPrefixedId(id), this.readEvents(id), this.fileToolMap, this.extractEditDelta.bind(this), {
|
|
11441
|
+
projectPath: located.projectPath,
|
|
11442
|
+
found: true
|
|
11443
|
+
});
|
|
11444
|
+
}
|
|
11445
|
+
computeOutcome(id, opts) {
|
|
11446
|
+
return computeOutcome(this.toPrefixedId(id), opts);
|
|
11447
|
+
}
|
|
11448
|
+
/** File edits since `sinceMs` across the sessions active since then. */
|
|
11449
|
+
collectRecentEdits(opts) {
|
|
11450
|
+
const refs = this.listSessions({ sinceMs: opts.sinceMs, projectFilter: opts.projectFilter, previews: false });
|
|
11451
|
+
const edits = [];
|
|
11452
|
+
for (const ref of opts.limitSessions ? refs.slice(0, opts.limitSessions) : refs) {
|
|
11453
|
+
for (const e of this.liveScanEdits(ref.rawId).edits) {
|
|
11454
|
+
if (e.ts >= opts.sinceMs)
|
|
11455
|
+
edits.push(e);
|
|
11456
|
+
}
|
|
11457
|
+
}
|
|
11458
|
+
return edits.sort((a, b) => b.ts - a.ts);
|
|
11459
|
+
}
|
|
11460
|
+
getCommits(id, files, startMs, endMs, bufferMinutes) {
|
|
11461
|
+
return getSessionCommits(this.toPrefixedId(id), files, startMs, endMs, bufferMinutes);
|
|
11462
|
+
}
|
|
11463
|
+
/**
|
|
11464
|
+
* The session row and its messages as JSONL, one row per line in id order.
|
|
11465
|
+
* Hermes rewrites and compacts its database, so the archive keeps the rows
|
|
11466
|
+
* as they were synced.
|
|
11467
|
+
*/
|
|
11468
|
+
exportRawSession(id) {
|
|
11469
|
+
const rawId = this.toRawId(id);
|
|
11470
|
+
const path = this.dbPathFor(rawId);
|
|
11471
|
+
if (!path)
|
|
11472
|
+
return null;
|
|
11473
|
+
const db = openSqliteReadonly(path);
|
|
11474
|
+
if (!db)
|
|
11475
|
+
return null;
|
|
11476
|
+
try {
|
|
11477
|
+
const have = new Set(db.prepare(`SELECT name FROM pragma_table_info('sessions')`).all().map((c) => c.name));
|
|
11478
|
+
const cols = ARCHIVED_SESSION_COLUMNS.filter((c) => have.has(c)).map((c) => `s.${c}`);
|
|
11479
|
+
const session = db.prepare(`
|
|
11480
|
+
SELECT ${[...cols, `${SESSION_MTIME_SQL} AS mtime`].join(", ")}
|
|
11481
|
+
FROM sessions s WHERE s.id = ?
|
|
11482
|
+
`).get(rawId);
|
|
11483
|
+
if (!session)
|
|
11484
|
+
return null;
|
|
11485
|
+
const rows = db.prepare(`SELECT ${MESSAGE_COLUMNS} FROM messages WHERE session_id = ? ORDER BY id`).all(rawId);
|
|
11486
|
+
const lines = [JSON.stringify({ kind: "session", row: session })];
|
|
11487
|
+
for (const r of rows)
|
|
11488
|
+
lines.push(JSON.stringify({ kind: "message", row: r }));
|
|
11489
|
+
return {
|
|
11490
|
+
tool: "hermes",
|
|
11491
|
+
mtime: Math.round(Number(session.mtime || 0) * 1e3),
|
|
11492
|
+
files: [{ name: `${rawId}.dump.jsonl`, bytes: Buffer.from(lines.join("\n") + "\n", "utf-8") }]
|
|
11493
|
+
};
|
|
11494
|
+
} catch {
|
|
11495
|
+
return null;
|
|
11496
|
+
} finally {
|
|
11497
|
+
db.close();
|
|
11498
|
+
}
|
|
11499
|
+
}
|
|
11500
|
+
};
|
|
11501
|
+
hermesBackend = new HermesBackend();
|
|
11502
|
+
}
|
|
11503
|
+
});
|
|
11504
|
+
|
|
10940
11505
|
// ../engine/dist/core/backends/index.js
|
|
10941
11506
|
var backends_exports = {};
|
|
10942
11507
|
__export(backends_exports, {
|
|
@@ -10944,6 +11509,7 @@ __export(backends_exports, {
|
|
|
10944
11509
|
ClaudeBackend: () => ClaudeBackend,
|
|
10945
11510
|
CodexBackend: () => CodexBackend,
|
|
10946
11511
|
CursorBackend: () => CursorBackend,
|
|
11512
|
+
HermesBackend: () => HermesBackend,
|
|
10947
11513
|
OpencodeBackend: () => OpencodeBackend,
|
|
10948
11514
|
agyBackend: () => agyBackend,
|
|
10949
11515
|
bootstrapBackends: () => bootstrapBackends,
|
|
@@ -10952,6 +11518,7 @@ __export(backends_exports, {
|
|
|
10952
11518
|
cursorBackend: () => cursorBackend,
|
|
10953
11519
|
getBackend: () => getBackend,
|
|
10954
11520
|
getBackendForId: () => getBackendForId,
|
|
11521
|
+
hermesBackend: () => hermesBackend,
|
|
10955
11522
|
listAllBackends: () => listAllBackends,
|
|
10956
11523
|
listAvailableBackends: () => listAvailableBackends,
|
|
10957
11524
|
opencodeBackend: () => opencodeBackend,
|
|
@@ -10964,6 +11531,7 @@ function bootstrapBackends() {
|
|
|
10964
11531
|
registerBackend(codexBackend);
|
|
10965
11532
|
registerBackend(agyBackend);
|
|
10966
11533
|
registerBackend(cursorBackend);
|
|
11534
|
+
registerBackend(hermesBackend);
|
|
10967
11535
|
}
|
|
10968
11536
|
var init_backends = __esm({
|
|
10969
11537
|
"../engine/dist/core/backends/index.js"() {
|
|
@@ -10974,6 +11542,7 @@ var init_backends = __esm({
|
|
|
10974
11542
|
init_codex2();
|
|
10975
11543
|
init_agy();
|
|
10976
11544
|
init_cursor();
|
|
11545
|
+
init_hermes();
|
|
10977
11546
|
init_tool_backend();
|
|
10978
11547
|
_setRegistryBootstrapper(bootstrapBackends);
|
|
10979
11548
|
}
|
|
@@ -10982,7 +11551,7 @@ var init_backends = __esm({
|
|
|
10982
11551
|
// ../engine/dist/transcript/shadow.js
|
|
10983
11552
|
import { gzipSync as gzipSync2, gunzipSync as gunzipSync2 } from "zlib";
|
|
10984
11553
|
import { createHash as createHash2 } from "crypto";
|
|
10985
|
-
import { existsSync as
|
|
11554
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync2, renameSync as renameSync2, statSync as statSync10, openSync as openSync4, readSync as readSync4, closeSync as closeSync4 } from "fs";
|
|
10986
11555
|
import { dirname as dirname12, join as join14 } from "path";
|
|
10987
11556
|
function shadowRoot() {
|
|
10988
11557
|
return join14(getDataDir(), "shadow");
|
|
@@ -10993,7 +11562,7 @@ function shadowFileFor(tool, rawId) {
|
|
|
10993
11562
|
}
|
|
10994
11563
|
function readShadowContainer(tool, rawId) {
|
|
10995
11564
|
const path = shadowFileFor(tool, rawId);
|
|
10996
|
-
if (!
|
|
11565
|
+
if (!existsSync13(path))
|
|
10997
11566
|
return null;
|
|
10998
11567
|
try {
|
|
10999
11568
|
const c = JSON.parse(gunzipSync2(readFileSync8(path)).toString("utf-8"));
|
|
@@ -11251,7 +11820,7 @@ var init_shadow = __esm({
|
|
|
11251
11820
|
});
|
|
11252
11821
|
|
|
11253
11822
|
// ../engine/dist/core/live-session-scan.js
|
|
11254
|
-
import { existsSync as
|
|
11823
|
+
import { existsSync as existsSync14, readdirSync as readdirSync10, readFileSync as readFileSync9, statSync as statSync11, openSync as openSync5, readSync as readSync5, closeSync as closeSync5 } from "fs";
|
|
11255
11824
|
import { join as join15, basename as basename9 } from "path";
|
|
11256
11825
|
function detectTool(sessionId) {
|
|
11257
11826
|
return getBackendForId(sessionId)?.id ?? "claude";
|
|
@@ -11308,7 +11877,7 @@ function sessionFileIndex() {
|
|
|
11308
11877
|
return p;
|
|
11309
11878
|
};
|
|
11310
11879
|
for (const root of roots) {
|
|
11311
|
-
if (seenRoots.has(root) || !
|
|
11880
|
+
if (seenRoots.has(root) || !existsSync14(root))
|
|
11312
11881
|
continue;
|
|
11313
11882
|
seenRoots.add(root);
|
|
11314
11883
|
dirs.set(root, dirMtime(root));
|
|
@@ -11434,7 +12003,7 @@ function resolveSessionContentPaths(sessionFile) {
|
|
|
11434
12003
|
if (!hasSubagentsDir(sessionFile))
|
|
11435
12004
|
return [sessionFile];
|
|
11436
12005
|
const subDir = join15(sessionFile.slice(0, -6), "subagents");
|
|
11437
|
-
if (!
|
|
12006
|
+
if (!existsSync14(subDir))
|
|
11438
12007
|
return [sessionFile];
|
|
11439
12008
|
const subPaths = readdirSync10(subDir).filter((f) => f.endsWith(".jsonl")).sort().map((f) => join15(subDir, f));
|
|
11440
12009
|
return [sessionFile, ...subPaths];
|
|
@@ -11451,7 +12020,7 @@ function findCodexSessionFile(sessionId) {
|
|
|
11451
12020
|
return null;
|
|
11452
12021
|
}
|
|
11453
12022
|
function findCodexSessionFileIn(root, sessionId) {
|
|
11454
|
-
if (!
|
|
12023
|
+
if (!existsSync14(root))
|
|
11455
12024
|
return null;
|
|
11456
12025
|
for (const year of readdirSync10(root, { withFileTypes: true })) {
|
|
11457
12026
|
if (!year.isDirectory())
|
|
@@ -11534,7 +12103,7 @@ var init_live_session_scan = __esm({
|
|
|
11534
12103
|
});
|
|
11535
12104
|
|
|
11536
12105
|
// ../engine/dist/core/first-prompt.js
|
|
11537
|
-
import { createReadStream as createReadStream2, existsSync as
|
|
12106
|
+
import { createReadStream as createReadStream2, existsSync as existsSync15, openSync as openSync6, readSync as readSync6, closeSync as closeSync6 } from "fs";
|
|
11538
12107
|
import { StringDecoder } from "string_decoder";
|
|
11539
12108
|
function stripBanners2(s) {
|
|
11540
12109
|
let out = s;
|
|
@@ -11645,7 +12214,7 @@ var init_first_prompt = __esm({
|
|
|
11645
12214
|
});
|
|
11646
12215
|
|
|
11647
12216
|
// ../engine/dist/core/backends/claude.js
|
|
11648
|
-
import { existsSync as
|
|
12217
|
+
import { existsSync as existsSync16, readdirSync as readdirSync11, readFileSync as readFileSync10, statSync as statSync12, openSync as openSync7, readSync as readSync7, closeSync as closeSync7 } from "fs";
|
|
11649
12218
|
import { join as join16, basename as basename10 } from "path";
|
|
11650
12219
|
function stripReminders(text) {
|
|
11651
12220
|
return text.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/g, "").trim();
|
|
@@ -11715,7 +12284,7 @@ var init_claude2 = __esm({
|
|
|
11715
12284
|
return join16(this.homeDir(), "history.jsonl");
|
|
11716
12285
|
}
|
|
11717
12286
|
isAvailable() {
|
|
11718
|
-
return
|
|
12287
|
+
return existsSync16(this.projectsDir());
|
|
11719
12288
|
}
|
|
11720
12289
|
// ── ID handling ────────────────────────────────────────────────
|
|
11721
12290
|
/**
|
|
@@ -11821,7 +12390,7 @@ var init_claude2 = __esm({
|
|
|
11821
12390
|
prior.modified = ref.modified;
|
|
11822
12391
|
}
|
|
11823
12392
|
};
|
|
11824
|
-
if (!
|
|
12393
|
+
if (!existsSync16(root))
|
|
11825
12394
|
return;
|
|
11826
12395
|
for (const proj of readdirSync11(root, { withFileTypes: true })) {
|
|
11827
12396
|
if (!proj.isDirectory())
|
|
@@ -11832,12 +12401,12 @@ var init_claude2 = __esm({
|
|
|
11832
12401
|
const projectPath = resolveProjectDirName(proj.name);
|
|
11833
12402
|
const indexPath = join16(projPath, "sessions-index.json");
|
|
11834
12403
|
const indexed = /* @__PURE__ */ new Set();
|
|
11835
|
-
if (
|
|
12404
|
+
if (existsSync16(indexPath)) {
|
|
11836
12405
|
try {
|
|
11837
12406
|
const indexData = JSON.parse(readFileSync10(indexPath, "utf-8"));
|
|
11838
12407
|
const entries = indexData.entries || [];
|
|
11839
12408
|
for (const entry of entries) {
|
|
11840
|
-
if (!entry.fullPath || !
|
|
12409
|
+
if (!entry.fullPath || !existsSync16(entry.fullPath))
|
|
11841
12410
|
continue;
|
|
11842
12411
|
indexed.add(entry.sessionId);
|
|
11843
12412
|
add({
|
|
@@ -12162,7 +12731,7 @@ var init_claude2 = __esm({
|
|
|
12162
12731
|
collectRecentEdits(opts) {
|
|
12163
12732
|
const candidates2 = [];
|
|
12164
12733
|
for (const root of claudeProjectDirs()) {
|
|
12165
|
-
if (!
|
|
12734
|
+
if (!existsSync16(root))
|
|
12166
12735
|
continue;
|
|
12167
12736
|
for (const projEntry of readdirSync11(root, { withFileTypes: true })) {
|
|
12168
12737
|
if (!projEntry.isDirectory())
|
|
@@ -12184,7 +12753,7 @@ var init_claude2 = __esm({
|
|
|
12184
12753
|
const st = statSync12(fp);
|
|
12185
12754
|
let mtime = st.mtimeMs;
|
|
12186
12755
|
const subDir = join16(projPath, f.slice(0, -6), "subagents");
|
|
12187
|
-
if (
|
|
12756
|
+
if (existsSync16(subDir)) {
|
|
12188
12757
|
for (const sub of readdirSync11(subDir)) {
|
|
12189
12758
|
try {
|
|
12190
12759
|
const subSt = statSync12(join16(subDir, sub));
|
|
@@ -12261,27 +12830,45 @@ var init_claude2 = __esm({
|
|
|
12261
12830
|
/**
|
|
12262
12831
|
* True when this session exists in MORE THAN ONE home.
|
|
12263
12832
|
*
|
|
12264
|
-
* Such a session cannot be tail-appended: `fileSize()` is the SUM across
|
|
12265
|
-
* copies while a byte offset addresses ONE file, so the two disagree by
|
|
12266
|
-
* construction and the "tail" is either empty or the wrong bytes. The caller
|
|
12267
|
-
* uses this to force a FULL sync, which ships the unioned container and is
|
|
12268
|
-
* correct regardless of how the halves are arranged.
|
|
12269
|
-
*
|
|
12270
12833
|
* Measured on ec05f266: ~/.claude 1715 records, ~/.claude-work 205 records,
|
|
12271
|
-
* zero overlap.
|
|
12272
|
-
*
|
|
12834
|
+
* zero overlap. `fileSize()` is the sum across the copies, and
|
|
12835
|
+
* `readFromOffset()` reads them joined end to end, primary first.
|
|
12273
12836
|
*/
|
|
12274
12837
|
spansMultipleSources(prefixedId) {
|
|
12275
12838
|
return findSessionFiles(this.toRawId(prefixedId)).length > 1;
|
|
12276
12839
|
}
|
|
12840
|
+
/**
|
|
12841
|
+
* The copies before the last one, each with its size. Claude Code writes to
|
|
12842
|
+
* the home of the profile that runs the session, so the live copy can grow,
|
|
12843
|
+
* appear, vanish or merge back into the primary. Each of those moves bytes
|
|
12844
|
+
* under an offset into the joined copies; this key changes with all of them.
|
|
12845
|
+
*/
|
|
12846
|
+
sourceLayout(prefixedId) {
|
|
12847
|
+
const copies = findSessionFiles(this.toRawId(prefixedId));
|
|
12848
|
+
if (copies.length < 2)
|
|
12849
|
+
return "";
|
|
12850
|
+
return copies.slice(0, -1).map((c) => {
|
|
12851
|
+
let size = -1;
|
|
12852
|
+
try {
|
|
12853
|
+
size = statSync12(c.path).size;
|
|
12854
|
+
} catch {
|
|
12855
|
+
}
|
|
12856
|
+
return `${c.path}:${size}`;
|
|
12857
|
+
}).join("|");
|
|
12858
|
+
}
|
|
12859
|
+
/**
|
|
12860
|
+
* Session 8de13d0a had 31 MB in ~/.claude and 2 MB in ~/.claude-work. Over
|
|
12861
|
+
* the 24 MB build ceiling a sync ships the transcript in chunks read here,
|
|
12862
|
+
* and this returned no text for a session in two homes. Each sync shipped
|
|
12863
|
+
* nothing, and the server stayed three hours behind.
|
|
12864
|
+
*/
|
|
12277
12865
|
async readFromOffset(prefixedId, offset, maxBytes) {
|
|
12278
|
-
const
|
|
12279
|
-
const copies = findSessionFiles(rawId);
|
|
12866
|
+
const copies = findSessionFiles(this.toRawId(prefixedId));
|
|
12280
12867
|
if (copies.length === 0)
|
|
12281
12868
|
return { text: "", newOffset: offset };
|
|
12282
|
-
if (copies.length
|
|
12283
|
-
return
|
|
12284
|
-
return
|
|
12869
|
+
if (copies.length === 1)
|
|
12870
|
+
return readTailFromOffset(copies[0].path, offset, maxBytes);
|
|
12871
|
+
return readSourcesFromOffset(copies.map((c) => c.path), offset, maxBytes);
|
|
12285
12872
|
}
|
|
12286
12873
|
};
|
|
12287
12874
|
claudeBackend = new ClaudeBackend();
|
|
@@ -12302,7 +12889,7 @@ __export(project_resolver_exports, {
|
|
|
12302
12889
|
});
|
|
12303
12890
|
import { execSync } from "child_process";
|
|
12304
12891
|
import { createHash as createHash3 } from "crypto";
|
|
12305
|
-
import { existsSync as
|
|
12892
|
+
import { existsSync as existsSync17, readFileSync as readFileSync11, realpathSync as realpathSync2, readdirSync as readdirSync12, statSync as statSync13 } from "fs";
|
|
12306
12893
|
import { basename as basename11, dirname as dirname13, isAbsolute, join as join17, resolve, sep } from "path";
|
|
12307
12894
|
function getProjectsConfigPath() {
|
|
12308
12895
|
return join17(getDataDir(), "projects.json");
|
|
@@ -12312,7 +12899,7 @@ function loadProjectsConfig() {
|
|
|
12312
12899
|
return cachedConfig.cfg;
|
|
12313
12900
|
}
|
|
12314
12901
|
const path = getProjectsConfigPath();
|
|
12315
|
-
if (!
|
|
12902
|
+
if (!existsSync17(path)) {
|
|
12316
12903
|
cachedConfig = { mtime: 0, cfg: {} };
|
|
12317
12904
|
return cachedConfig.cfg;
|
|
12318
12905
|
}
|
|
@@ -12486,7 +13073,7 @@ function findGitToplevel(realPath) {
|
|
|
12486
13073
|
let cur = realPath;
|
|
12487
13074
|
let last = "";
|
|
12488
13075
|
while (cur && cur !== last) {
|
|
12489
|
-
if (
|
|
13076
|
+
if (existsSync17(join17(cur, ".git")))
|
|
12490
13077
|
return cur;
|
|
12491
13078
|
last = cur;
|
|
12492
13079
|
cur = dirname13(cur);
|
|
@@ -12553,7 +13140,7 @@ function resolveAutoWorkspace(realPath, minRepos) {
|
|
|
12553
13140
|
let last = "";
|
|
12554
13141
|
let depth = 0;
|
|
12555
13142
|
while (cur && cur !== last && depth < AUTO_WORKSPACE_MAX_DEPTH) {
|
|
12556
|
-
if (!
|
|
13143
|
+
if (!existsSync17(join17(cur, ".git"))) {
|
|
12557
13144
|
const cached = workspaceCache.get(cur);
|
|
12558
13145
|
let qualifies;
|
|
12559
13146
|
if (cached === void 0) {
|
|
@@ -12589,7 +13176,7 @@ function countGitChildren(dir) {
|
|
|
12589
13176
|
const st = statSync13(child);
|
|
12590
13177
|
if (!st.isDirectory())
|
|
12591
13178
|
continue;
|
|
12592
|
-
if (
|
|
13179
|
+
if (existsSync17(join17(child, ".git")))
|
|
12593
13180
|
count++;
|
|
12594
13181
|
} catch {
|
|
12595
13182
|
}
|
|
@@ -13179,7 +13766,7 @@ var init_secret_redactor = __esm({
|
|
|
13179
13766
|
|
|
13180
13767
|
// ../engine/dist/core/source-discovery.js
|
|
13181
13768
|
import { createHash as createHash5 } from "crypto";
|
|
13182
|
-
import { existsSync as
|
|
13769
|
+
import { existsSync as existsSync18, readdirSync as readdirSync13, statSync as statSync15 } from "fs";
|
|
13183
13770
|
import { join as join18 } from "path";
|
|
13184
13771
|
function sourceId(path) {
|
|
13185
13772
|
return "src_" + createHash5("sha256").update(path).digest("hex").slice(0, 12);
|
|
@@ -13238,7 +13825,7 @@ function countTranscripts(root, tool) {
|
|
|
13238
13825
|
walk(root, 0);
|
|
13239
13826
|
return { sessions, newestMtime };
|
|
13240
13827
|
}
|
|
13241
|
-
function
|
|
13828
|
+
function countDbSessions(dbPath) {
|
|
13242
13829
|
try {
|
|
13243
13830
|
const st = statSync15(dbPath);
|
|
13244
13831
|
return { sessions: 0, newestMtime: st.mtimeMs };
|
|
@@ -13256,18 +13843,24 @@ function discoverSessionSources() {
|
|
|
13256
13843
|
];
|
|
13257
13844
|
for (const [tool, dirs] of dirTools) {
|
|
13258
13845
|
for (const [i, path] of dirs.entries()) {
|
|
13259
|
-
if (!
|
|
13846
|
+
if (!existsSync18(path))
|
|
13260
13847
|
continue;
|
|
13261
13848
|
const { sessions, newestMtime } = countTranscripts(path, tool);
|
|
13262
13849
|
out.push({ id: sourceId(path), tool, path, sessions, newestMtime, isPrimary: i === 0 });
|
|
13263
13850
|
}
|
|
13264
13851
|
}
|
|
13265
13852
|
for (const [i, path] of opencodeDbPaths({ includeExcluded: true }).entries()) {
|
|
13266
|
-
if (!
|
|
13853
|
+
if (!existsSync18(path))
|
|
13267
13854
|
continue;
|
|
13268
|
-
const { sessions, newestMtime } =
|
|
13855
|
+
const { sessions, newestMtime } = countDbSessions(path);
|
|
13269
13856
|
out.push({ id: sourceId(path), tool: "opencode", path, sessions, newestMtime, isPrimary: i === 0 });
|
|
13270
13857
|
}
|
|
13858
|
+
for (const [i, path] of hermesDbPaths({ includeExcluded: true }).entries()) {
|
|
13859
|
+
if (!existsSync18(path))
|
|
13860
|
+
continue;
|
|
13861
|
+
const { sessions, newestMtime } = countDbSessions(path);
|
|
13862
|
+
out.push({ id: sourceId(path), tool: "hermes", path, sessions, newestMtime, isPrimary: i === 0 });
|
|
13863
|
+
}
|
|
13271
13864
|
return out;
|
|
13272
13865
|
}
|
|
13273
13866
|
var excludedIds, SOURCE_ID_RE, MAX_DEPTH;
|
|
@@ -13292,7 +13885,7 @@ __export(home_discovery_exports, {
|
|
|
13292
13885
|
sessionIdsInHome: () => sessionIdsInHome
|
|
13293
13886
|
});
|
|
13294
13887
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
13295
|
-
import { existsSync as
|
|
13888
|
+
import { existsSync as existsSync19, readdirSync as readdirSync14, readFileSync as readFileSync12, realpathSync as realpathSync3, statSync as statSync16 } from "fs";
|
|
13296
13889
|
import { homedir as homedir5, platform as osPlatform } from "os";
|
|
13297
13890
|
import { join as join19 } from "path";
|
|
13298
13891
|
function candidateRoots(plat = osPlatform(), env = process.env) {
|
|
@@ -13313,10 +13906,10 @@ function candidateRoots(plat = osPlatform(), env = process.env) {
|
|
|
13313
13906
|
add(env.XDG_CONFIG_HOME || join19(home, ".config"));
|
|
13314
13907
|
add(env.XDG_DATA_HOME || join19(home, ".local", "share"));
|
|
13315
13908
|
}
|
|
13316
|
-
return roots.filter((r) =>
|
|
13909
|
+
return roots.filter((r) => existsSync19(r));
|
|
13317
13910
|
}
|
|
13318
13911
|
function identifyHome(dir) {
|
|
13319
|
-
const has = (...parts) =>
|
|
13912
|
+
const has = (...parts) => existsSync19(join19(dir, ...parts));
|
|
13320
13913
|
if (has("projects") && dirHasTranscript(join19(dir, "projects"), (f) => f.endsWith(".jsonl"), 2))
|
|
13321
13914
|
return "claude";
|
|
13322
13915
|
if (has("sessions") && dirHasTranscript(join19(dir, "sessions"), (f) => f.startsWith("rollout-") && f.endsWith(".jsonl"), 4))
|
|
@@ -13327,6 +13920,8 @@ function identifyHome(dir) {
|
|
|
13327
13920
|
return "cursor";
|
|
13328
13921
|
if (has("opencode.db"))
|
|
13329
13922
|
return "opencode";
|
|
13923
|
+
if (has("state.db") && has("SOUL.md"))
|
|
13924
|
+
return "hermes";
|
|
13330
13925
|
return null;
|
|
13331
13926
|
}
|
|
13332
13927
|
function dirHasTranscript(root, match, depth) {
|
|
@@ -13354,7 +13949,8 @@ function countSessions(dir, tool) {
|
|
|
13354
13949
|
codex: { sub: "sessions", depth: 4, match: (f) => f.startsWith("rollout-") && f.endsWith(".jsonl") },
|
|
13355
13950
|
agy: { sub: "brain", depth: 4, match: (f) => f.endsWith(".jsonl") },
|
|
13356
13951
|
cursor: { sub: "chats", depth: 3, match: (f) => f === "store.db" },
|
|
13357
|
-
opencode: { sub: "", depth: 0, match: () => false }
|
|
13952
|
+
opencode: { sub: "", depth: 0, match: () => false },
|
|
13953
|
+
hermes: { sub: "", depth: 0, match: () => false }
|
|
13358
13954
|
};
|
|
13359
13955
|
const s = spec[tool];
|
|
13360
13956
|
if (!s.sub)
|
|
@@ -13404,7 +14000,9 @@ function sessionIdsInHome(dir, tool) {
|
|
|
13404
14000
|
// id is the DIRECTORY name
|
|
13405
14001
|
cursor: { sub: "chats", depth: 2, idOf: () => null },
|
|
13406
14002
|
// id is the DIRECTORY name
|
|
13407
|
-
opencode: { sub: "", depth: 0, idOf: () => null }
|
|
14003
|
+
opencode: { sub: "", depth: 0, idOf: () => null },
|
|
14004
|
+
// rows, not files
|
|
14005
|
+
hermes: { sub: "", depth: 0, idOf: () => null }
|
|
13408
14006
|
// rows, not files
|
|
13409
14007
|
};
|
|
13410
14008
|
const s = spec[tool];
|
|
@@ -13477,6 +14075,8 @@ function declaredHomes(env = process.env, plat = osPlatform()) {
|
|
|
13477
14075
|
add(env.CHAT_RECALL_AGY_HOME);
|
|
13478
14076
|
add(env.CHAT_RECALL_CURSOR_HOME);
|
|
13479
14077
|
add(env.CHAT_RECALL_CURSOR_IDE_HOME);
|
|
14078
|
+
add(env.CHAT_RECALL_HERMES_HOME);
|
|
14079
|
+
add(env.HERMES_HOME);
|
|
13480
14080
|
for (const d of (env.CLAUDE_DIRS || "").split(","))
|
|
13481
14081
|
add(d);
|
|
13482
14082
|
if (plat === "win32") {
|
|
@@ -13576,6 +14176,15 @@ function discoverHomes(opts = {}) {
|
|
|
13576
14176
|
if (prior && !(via === "declared" && prior.via !== "declared"))
|
|
13577
14177
|
return;
|
|
13578
14178
|
found.set(real, { tool, path: real, via, sessions: countSessions(real, tool) });
|
|
14179
|
+
if (tool === "hermes") {
|
|
14180
|
+
try {
|
|
14181
|
+
for (const e of readdirSync14(join19(real, "profiles"), { withFileTypes: true })) {
|
|
14182
|
+
if (e.isDirectory())
|
|
14183
|
+
consider(join19(real, "profiles", e.name), via);
|
|
14184
|
+
}
|
|
14185
|
+
} catch {
|
|
14186
|
+
}
|
|
14187
|
+
}
|
|
13579
14188
|
};
|
|
13580
14189
|
for (const d of declaredHomes(env, plat))
|
|
13581
14190
|
consider(d, "declared");
|
|
@@ -13655,7 +14264,7 @@ __export(detector_install_exports, {
|
|
|
13655
14264
|
});
|
|
13656
14265
|
import { spawnSync } from "child_process";
|
|
13657
14266
|
import { createHash as createHash6 } from "crypto";
|
|
13658
|
-
import { existsSync as
|
|
14267
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync4, mkdtempSync, chmodSync as chmodSync2, renameSync as renameSync3, rmSync as rmSync2, writeFileSync as writeFileSync3, readFileSync as readFileSync13, statSync as statSync17, copyFileSync as copyFileSync2 } from "fs";
|
|
13659
14268
|
import { join as join20 } from "path";
|
|
13660
14269
|
function managedDetectorPath(name) {
|
|
13661
14270
|
return join20(getDetectorBinDir(), name + exeSuffix());
|
|
@@ -13698,7 +14307,7 @@ function resolveDetector(name) {
|
|
|
13698
14307
|
const dir = configuredDir();
|
|
13699
14308
|
if (dir) {
|
|
13700
14309
|
const p2 = join20(dir, name + exeSuffix());
|
|
13701
|
-
if (
|
|
14310
|
+
if (existsSync20(p2))
|
|
13702
14311
|
return { path: p2, version: "operator-supplied", source: "configured" };
|
|
13703
14312
|
return { error: "not-installed" };
|
|
13704
14313
|
}
|
|
@@ -13706,7 +14315,7 @@ function resolveDetector(name) {
|
|
|
13706
14315
|
if (!spec.assets[platformKey()])
|
|
13707
14316
|
return { error: "unsupported-platform" };
|
|
13708
14317
|
const p = managedDetectorPath(name);
|
|
13709
|
-
if (!
|
|
14318
|
+
if (!existsSync20(p))
|
|
13710
14319
|
return { error: "not-installed" };
|
|
13711
14320
|
const receipt = readReceipt(name);
|
|
13712
14321
|
if (!receipt)
|
|
@@ -13726,7 +14335,7 @@ function downloadUrl(spec, asset) {
|
|
|
13726
14335
|
}
|
|
13727
14336
|
function extractMember(archive, member, destDir) {
|
|
13728
14337
|
const r = spawnSync("tar", ["-xf", archive, "-C", destDir, member], { encoding: "utf-8", timeout: 12e4 });
|
|
13729
|
-
if (r.status === 0 &&
|
|
14338
|
+
if (r.status === 0 && existsSync20(join20(destDir, member)))
|
|
13730
14339
|
return true;
|
|
13731
14340
|
log4.error({ status: r.status, stderr: (r.stderr || "").slice(0, 400), archive, member }, "extract failed");
|
|
13732
14341
|
return false;
|
|
@@ -13795,7 +14404,7 @@ function removeDetector(name) {
|
|
|
13795
14404
|
let removed = false;
|
|
13796
14405
|
for (const p of [managedDetectorPath(name), receiptPath(name)]) {
|
|
13797
14406
|
try {
|
|
13798
|
-
if (
|
|
14407
|
+
if (existsSync20(p)) {
|
|
13799
14408
|
rmSync2(p, { force: true });
|
|
13800
14409
|
removed = true;
|
|
13801
14410
|
}
|
|
@@ -13821,7 +14430,7 @@ function detectorStatus() {
|
|
|
13821
14430
|
}
|
|
13822
14431
|
function ensureDetectorBinDir() {
|
|
13823
14432
|
const d = getDetectorBinDir();
|
|
13824
|
-
if (!
|
|
14433
|
+
if (!existsSync20(d))
|
|
13825
14434
|
mkdirSync4(d, { recursive: true, mode: 493 });
|
|
13826
14435
|
return d;
|
|
13827
14436
|
}
|
|
@@ -13879,7 +14488,7 @@ __export(secret_scanner_exports, {
|
|
|
13879
14488
|
scanTenantRules: () => scanTenantRules
|
|
13880
14489
|
});
|
|
13881
14490
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
13882
|
-
import { existsSync as
|
|
14491
|
+
import { existsSync as existsSync21, unlinkSync, readFileSync as readFileSync14, mkdtempSync as mkdtempSync2, rmSync as rmSync3 } from "fs";
|
|
13883
14492
|
import { tmpdir } from "os";
|
|
13884
14493
|
import { join as join21 } from "path";
|
|
13885
14494
|
function mask(s) {
|
|
@@ -14048,7 +14657,7 @@ function runTrufflehogDir(binary, dir, opts = {}) {
|
|
|
14048
14657
|
return out;
|
|
14049
14658
|
}
|
|
14050
14659
|
function scanDirForSecrets(dir, opts = {}) {
|
|
14051
|
-
if (!
|
|
14660
|
+
if (!existsSync21(dir))
|
|
14052
14661
|
return [];
|
|
14053
14662
|
const gitleaks = whichDetector("gitleaks");
|
|
14054
14663
|
const trufflehog = whichDetector("trufflehog");
|
|
@@ -14085,7 +14694,7 @@ function scanTenantRules(text, tenantRules) {
|
|
|
14085
14694
|
return out;
|
|
14086
14695
|
}
|
|
14087
14696
|
function scanFileForSecrets(filePath, opts = {}) {
|
|
14088
|
-
if (!
|
|
14697
|
+
if (!existsSync21(filePath))
|
|
14089
14698
|
return [];
|
|
14090
14699
|
const gitleaks = whichDetector("gitleaks");
|
|
14091
14700
|
const trufflehog = whichDetector("trufflehog");
|
|
@@ -14107,7 +14716,7 @@ function scanFileForSecrets(filePath, opts = {}) {
|
|
|
14107
14716
|
}
|
|
14108
14717
|
async function scanSessionForSecrets(opts) {
|
|
14109
14718
|
const result = { sessionId: opts.sessionId, byDetector: {}, total: 0, ran: false };
|
|
14110
|
-
if (!
|
|
14719
|
+
if (!existsSync21(opts.filePath))
|
|
14111
14720
|
return result;
|
|
14112
14721
|
const gitleaks = whichDetector("gitleaks");
|
|
14113
14722
|
const trufflehog = whichDetector("trufflehog");
|
|
@@ -14263,10 +14872,10 @@ var init_types = __esm({
|
|
|
14263
14872
|
|
|
14264
14873
|
// ../engine/dist/transcript/opencode.js
|
|
14265
14874
|
async function parseOpenCodeSubagents(parentSessionId) {
|
|
14266
|
-
const { existsSync:
|
|
14875
|
+
const { existsSync: existsSync59 } = await import("fs");
|
|
14267
14876
|
const { opencodeBackend: opencodeBackend2 } = await Promise.resolve().then(() => (init_opencode(), opencode_exports));
|
|
14268
14877
|
const dbPath = opencodeBackend2.dbPath();
|
|
14269
|
-
if (!
|
|
14878
|
+
if (!existsSync59(dbPath))
|
|
14270
14879
|
return [];
|
|
14271
14880
|
const realParent = parentSessionId.replace("opencode_", "");
|
|
14272
14881
|
const db = openSqliteReadonlyOrThrow(dbPath);
|
|
@@ -14307,10 +14916,10 @@ async function parseOpenCodeSubagents(parentSessionId) {
|
|
|
14307
14916
|
}
|
|
14308
14917
|
}
|
|
14309
14918
|
async function parseOpenCodeTranscript(sessionId) {
|
|
14310
|
-
const { existsSync:
|
|
14919
|
+
const { existsSync: existsSync59 } = await import("fs");
|
|
14311
14920
|
const { opencodeBackend: opencodeBackend2 } = await Promise.resolve().then(() => (init_opencode(), opencode_exports));
|
|
14312
14921
|
const dbPath = opencodeBackend2.dbPath();
|
|
14313
|
-
if (!
|
|
14922
|
+
if (!existsSync59(dbPath))
|
|
14314
14923
|
return [];
|
|
14315
14924
|
const realId = sessionId.replace("opencode_", "");
|
|
14316
14925
|
const db = openSqliteReadonlyOrThrow(dbPath);
|
|
@@ -15068,7 +15677,7 @@ var init_source_policy = __esm({
|
|
|
15068
15677
|
init_project_path_match();
|
|
15069
15678
|
init_settings();
|
|
15070
15679
|
cache2 = null;
|
|
15071
|
-
TOOLS = ["claude", "opencode", "codex", "agy", "cursor"];
|
|
15680
|
+
TOOLS = ["claude", "opencode", "codex", "agy", "cursor", "hermes"];
|
|
15072
15681
|
}
|
|
15073
15682
|
});
|
|
15074
15683
|
|
|
@@ -15163,7 +15772,7 @@ var init_source_registry = __esm({
|
|
|
15163
15772
|
});
|
|
15164
15773
|
|
|
15165
15774
|
// ../engine/dist/core/utils.js
|
|
15166
|
-
import { existsSync as
|
|
15775
|
+
import { existsSync as existsSync22, readdirSync as readdirSync15 } from "fs";
|
|
15167
15776
|
import { homedir as homedir6 } from "os";
|
|
15168
15777
|
import { join as join22 } from "path";
|
|
15169
15778
|
function splitByHeaders(markdown) {
|
|
@@ -15199,7 +15808,7 @@ function getClaudeDirs() {
|
|
|
15199
15808
|
const dirs = [];
|
|
15200
15809
|
const seen = /* @__PURE__ */ new Set();
|
|
15201
15810
|
const add = (dir) => {
|
|
15202
|
-
if (!seen.has(dir) &&
|
|
15811
|
+
if (!seen.has(dir) && existsSync22(dir)) {
|
|
15203
15812
|
seen.add(dir);
|
|
15204
15813
|
dirs.push(dir);
|
|
15205
15814
|
}
|
|
@@ -15218,7 +15827,7 @@ function getClaudeDirs() {
|
|
|
15218
15827
|
for (const entry of entries) {
|
|
15219
15828
|
if (entry.isDirectory() && entry.name.startsWith(".claude-") && entry.name !== ".claude-code") {
|
|
15220
15829
|
const candidate = join22(home, entry.name);
|
|
15221
|
-
if (
|
|
15830
|
+
if (existsSync22(join22(candidate, "projects"))) {
|
|
15222
15831
|
add(candidate);
|
|
15223
15832
|
}
|
|
15224
15833
|
}
|
|
@@ -15231,7 +15840,7 @@ function discoverSubdirs(subdir) {
|
|
|
15231
15840
|
const result = [];
|
|
15232
15841
|
for (const claudeDir of getClaudeDirs()) {
|
|
15233
15842
|
const path = join22(claudeDir, subdir);
|
|
15234
|
-
if (
|
|
15843
|
+
if (existsSync22(path)) {
|
|
15235
15844
|
result.push(path);
|
|
15236
15845
|
}
|
|
15237
15846
|
}
|
|
@@ -15244,7 +15853,7 @@ var init_utils = __esm({
|
|
|
15244
15853
|
});
|
|
15245
15854
|
|
|
15246
15855
|
// ../engine/dist/parsers/plan-source.js
|
|
15247
|
-
import { existsSync as
|
|
15856
|
+
import { existsSync as existsSync23, readdirSync as readdirSync16, readFileSync as readFileSync15, statSync as statSync20 } from "fs";
|
|
15248
15857
|
import { homedir as homedir7 } from "os";
|
|
15249
15858
|
import { join as join23, basename as basename12 } from "path";
|
|
15250
15859
|
function parseFrontmatter(content) {
|
|
@@ -15302,7 +15911,7 @@ var init_plan_source = __esm({
|
|
|
15302
15911
|
return this._knownProjectDirs;
|
|
15303
15912
|
const projectsDir = claudeBackend.projectsDir();
|
|
15304
15913
|
this._knownProjectDirs = [];
|
|
15305
|
-
if (!
|
|
15914
|
+
if (!existsSync23(projectsDir))
|
|
15306
15915
|
return this._knownProjectDirs;
|
|
15307
15916
|
try {
|
|
15308
15917
|
const entries = readdirSync16(projectsDir, { withFileTypes: true });
|
|
@@ -15310,7 +15919,7 @@ var init_plan_source = __esm({
|
|
|
15310
15919
|
if (!entry.isDirectory() || entry.name.startsWith("."))
|
|
15311
15920
|
continue;
|
|
15312
15921
|
const projectPath = resolveProjectDirName(entry.name);
|
|
15313
|
-
if (
|
|
15922
|
+
if (existsSync23(projectPath)) {
|
|
15314
15923
|
this._knownProjectDirs.push(projectPath);
|
|
15315
15924
|
}
|
|
15316
15925
|
}
|
|
@@ -15334,7 +15943,7 @@ var init_plan_source = __esm({
|
|
|
15334
15943
|
async *discoverClaudePlans() {
|
|
15335
15944
|
const seenClaude = /* @__PURE__ */ new Set();
|
|
15336
15945
|
for (const plansDir of this.plansDirs) {
|
|
15337
|
-
if (!
|
|
15946
|
+
if (!existsSync23(plansDir))
|
|
15338
15947
|
continue;
|
|
15339
15948
|
const files = readdirSync16(plansDir).filter((f) => f.endsWith(".md"));
|
|
15340
15949
|
for (const file of files) {
|
|
@@ -15376,7 +15985,7 @@ var init_plan_source = __esm({
|
|
|
15376
15985
|
}
|
|
15377
15986
|
async *discoverOpenCodePlans() {
|
|
15378
15987
|
const plansDir = opencodeBackend.plansDir();
|
|
15379
|
-
if (!
|
|
15988
|
+
if (!existsSync23(plansDir))
|
|
15380
15989
|
return;
|
|
15381
15990
|
let files;
|
|
15382
15991
|
try {
|
|
@@ -15463,7 +16072,7 @@ var init_plan_source = __esm({
|
|
|
15463
16072
|
return "";
|
|
15464
16073
|
}
|
|
15465
16074
|
async parse(item) {
|
|
15466
|
-
if (!
|
|
16075
|
+
if (!existsSync23(item.filePath))
|
|
15467
16076
|
return [];
|
|
15468
16077
|
const content = readFileSync15(item.filePath, "utf-8");
|
|
15469
16078
|
const chunks = [];
|
|
@@ -15504,7 +16113,7 @@ var init_plan_source = __esm({
|
|
|
15504
16113
|
const projPath = join23(root, proj);
|
|
15505
16114
|
for (const sessionEntry of safeReaddir(projPath)) {
|
|
15506
16115
|
const subDir = join23(projPath, sessionEntry, "subagents");
|
|
15507
|
-
if (!
|
|
16116
|
+
if (!existsSync23(subDir))
|
|
15508
16117
|
continue;
|
|
15509
16118
|
for (const f of safeReaddir(subDir)) {
|
|
15510
16119
|
const m = f.match(/^agent-([a-z0-9_-]+)\.jsonl$/i);
|
|
@@ -15579,7 +16188,7 @@ var init_plan_source = __esm({
|
|
|
15579
16188
|
}
|
|
15580
16189
|
async *discoverAgyPlans() {
|
|
15581
16190
|
const brainDir = join23(agyBackend.homeDir(), "brain");
|
|
15582
|
-
if (!
|
|
16191
|
+
if (!existsSync23(brainDir))
|
|
15583
16192
|
return;
|
|
15584
16193
|
let sessionDirs;
|
|
15585
16194
|
try {
|
|
@@ -15634,7 +16243,7 @@ var init_plan_source = __esm({
|
|
|
15634
16243
|
});
|
|
15635
16244
|
|
|
15636
16245
|
// ../engine/dist/parsers/task-source.js
|
|
15637
|
-
import { existsSync as
|
|
16246
|
+
import { existsSync as existsSync24, readdirSync as readdirSync17, readFileSync as readFileSync16, statSync as statSync21 } from "fs";
|
|
15638
16247
|
import { join as join24 } from "path";
|
|
15639
16248
|
var MAX_CHUNK_CHARS2, TaskSource;
|
|
15640
16249
|
var init_task_source = __esm({
|
|
@@ -15664,7 +16273,7 @@ var init_task_source = __esm({
|
|
|
15664
16273
|
}
|
|
15665
16274
|
async *discoverClaudeTodos() {
|
|
15666
16275
|
const todosDir = claudeBackend.todosDir();
|
|
15667
|
-
if (!
|
|
16276
|
+
if (!existsSync24(todosDir))
|
|
15668
16277
|
return;
|
|
15669
16278
|
let files;
|
|
15670
16279
|
try {
|
|
@@ -15715,7 +16324,7 @@ var init_task_source = __esm({
|
|
|
15715
16324
|
}
|
|
15716
16325
|
}
|
|
15717
16326
|
async *discoverInDir(tasksDir) {
|
|
15718
|
-
if (!
|
|
16327
|
+
if (!existsSync24(tasksDir))
|
|
15719
16328
|
return;
|
|
15720
16329
|
const entries = readdirSync17(tasksDir, { withFileTypes: true });
|
|
15721
16330
|
for (const entry of entries) {
|
|
@@ -15757,7 +16366,7 @@ var init_task_source = __esm({
|
|
|
15757
16366
|
return this.parseAgentTodo(item);
|
|
15758
16367
|
}
|
|
15759
16368
|
const taskDir = item.filePath;
|
|
15760
|
-
if (!
|
|
16369
|
+
if (!existsSync24(taskDir))
|
|
15761
16370
|
return [];
|
|
15762
16371
|
const taskFiles = readdirSync17(taskDir).filter((f) => f.endsWith(".json"));
|
|
15763
16372
|
const tasks2 = this.readTasks(taskDir, taskFiles);
|
|
@@ -15818,7 +16427,7 @@ ${task.description}`.slice(0, MAX_CHUNK_CHARS2);
|
|
|
15818
16427
|
}];
|
|
15819
16428
|
}
|
|
15820
16429
|
async parseAgentTodo(item) {
|
|
15821
|
-
if (!
|
|
16430
|
+
if (!existsSync24(item.filePath))
|
|
15822
16431
|
return [];
|
|
15823
16432
|
let parsed;
|
|
15824
16433
|
try {
|
|
@@ -15870,7 +16479,7 @@ ${task.description}`.slice(0, MAX_CHUNK_CHARS2);
|
|
|
15870
16479
|
});
|
|
15871
16480
|
|
|
15872
16481
|
// ../engine/dist/parsers/claude-md-source.js
|
|
15873
|
-
import { existsSync as
|
|
16482
|
+
import { existsSync as existsSync25, readFileSync as readFileSync17, readdirSync as readdirSync18, statSync as statSync22 } from "fs";
|
|
15874
16483
|
import { homedir as homedir8 } from "os";
|
|
15875
16484
|
import { join as join25, basename as basename13, dirname as dirname14 } from "path";
|
|
15876
16485
|
import { createHash as createHash7 } from "crypto";
|
|
@@ -15878,13 +16487,13 @@ function discoverProjectDirs(claudeDir) {
|
|
|
15878
16487
|
const dirs = [];
|
|
15879
16488
|
const seen = /* @__PURE__ */ new Set();
|
|
15880
16489
|
const addProject = (path) => {
|
|
15881
|
-
if (!seen.has(path) &&
|
|
16490
|
+
if (!seen.has(path) && existsSync25(path)) {
|
|
15882
16491
|
seen.add(path);
|
|
15883
16492
|
dirs.push(path);
|
|
15884
16493
|
}
|
|
15885
16494
|
};
|
|
15886
16495
|
const scanProjectsDir = (projectsDir) => {
|
|
15887
|
-
if (!
|
|
16496
|
+
if (!existsSync25(projectsDir))
|
|
15888
16497
|
return;
|
|
15889
16498
|
try {
|
|
15890
16499
|
const entries = readdirSync18(projectsDir, { withFileTypes: true });
|
|
@@ -15912,7 +16521,7 @@ function discoverProjectDirs(claudeDir) {
|
|
|
15912
16521
|
} catch {
|
|
15913
16522
|
}
|
|
15914
16523
|
const gemProjects = agyBackend.sharedProjectsJson();
|
|
15915
|
-
if (
|
|
16524
|
+
if (existsSync25(gemProjects)) {
|
|
15916
16525
|
try {
|
|
15917
16526
|
const data = JSON.parse(readFileSync17(gemProjects, "utf-8"));
|
|
15918
16527
|
for (const path of Object.keys(data.projects || {}))
|
|
@@ -15921,7 +16530,7 @@ function discoverProjectDirs(claudeDir) {
|
|
|
15921
16530
|
}
|
|
15922
16531
|
}
|
|
15923
16532
|
const ocDb = opencodeBackend.dbPath();
|
|
15924
|
-
if (
|
|
16533
|
+
if (existsSync25(ocDb)) {
|
|
15925
16534
|
try {
|
|
15926
16535
|
const db = openSqliteReadonlyOrThrow(ocDb);
|
|
15927
16536
|
try {
|
|
@@ -15972,7 +16581,7 @@ var init_claude_md_source = __esm({
|
|
|
15972
16581
|
for (const note of NOTE_FILES) {
|
|
15973
16582
|
const p = join25(homedir8(), note.filename);
|
|
15974
16583
|
const key2 = seenKey(p, note.tool);
|
|
15975
|
-
if (
|
|
16584
|
+
if (existsSync25(p) && !seen.has(key2)) {
|
|
15976
16585
|
seen.add(key2);
|
|
15977
16586
|
const item = this.fileToItem(p, note.filename, note.tool);
|
|
15978
16587
|
if (item)
|
|
@@ -15984,7 +16593,7 @@ var init_claude_md_source = __esm({
|
|
|
15984
16593
|
for (const note of NOTE_FILES) {
|
|
15985
16594
|
const p = join25(projectDir, note.filename);
|
|
15986
16595
|
const key2 = seenKey(p, note.tool);
|
|
15987
|
-
if (
|
|
16596
|
+
if (existsSync25(p) && !seen.has(key2)) {
|
|
15988
16597
|
seen.add(key2);
|
|
15989
16598
|
const item = this.fileToItem(p, note.filename, note.tool);
|
|
15990
16599
|
if (item)
|
|
@@ -15993,12 +16602,12 @@ var init_claude_md_source = __esm({
|
|
|
15993
16602
|
}
|
|
15994
16603
|
}
|
|
15995
16604
|
for (const searchDir of this.searchDirs) {
|
|
15996
|
-
if (!
|
|
16605
|
+
if (!existsSync25(searchDir))
|
|
15997
16606
|
continue;
|
|
15998
16607
|
for (const note of NOTE_FILES) {
|
|
15999
16608
|
const directPath = join25(searchDir, note.filename);
|
|
16000
16609
|
const key2 = seenKey(directPath, note.tool);
|
|
16001
|
-
if (
|
|
16610
|
+
if (existsSync25(directPath) && !seen.has(key2)) {
|
|
16002
16611
|
seen.add(key2);
|
|
16003
16612
|
const item = this.fileToItem(directPath, note.filename, note.tool);
|
|
16004
16613
|
if (item)
|
|
@@ -16013,7 +16622,7 @@ var init_claude_md_source = __esm({
|
|
|
16013
16622
|
for (const note of NOTE_FILES) {
|
|
16014
16623
|
const p = join25(searchDir, entry.name, note.filename);
|
|
16015
16624
|
const key2 = seenKey(p, note.tool);
|
|
16016
|
-
if (
|
|
16625
|
+
if (existsSync25(p) && !seen.has(key2)) {
|
|
16017
16626
|
seen.add(key2);
|
|
16018
16627
|
const item = this.fileToItem(p, note.filename, note.tool);
|
|
16019
16628
|
if (item)
|
|
@@ -16027,7 +16636,7 @@ var init_claude_md_source = __esm({
|
|
|
16027
16636
|
}
|
|
16028
16637
|
}
|
|
16029
16638
|
async parse(item) {
|
|
16030
|
-
if (!
|
|
16639
|
+
if (!existsSync25(item.filePath))
|
|
16031
16640
|
return [];
|
|
16032
16641
|
const content = readFileSync17(item.filePath, "utf-8");
|
|
16033
16642
|
const chunks = [];
|
|
@@ -16096,7 +16705,7 @@ var init_claude_md_source = __esm({
|
|
|
16096
16705
|
});
|
|
16097
16706
|
|
|
16098
16707
|
// ../engine/dist/parsers/agent-memory-source.js
|
|
16099
|
-
import { existsSync as
|
|
16708
|
+
import { existsSync as existsSync26, readFileSync as readFileSync18, readdirSync as readdirSync19, statSync as statSync23 } from "fs";
|
|
16100
16709
|
import { homedir as homedir9 } from "os";
|
|
16101
16710
|
import { join as join26, basename as basename14 } from "path";
|
|
16102
16711
|
function parseFrontmatter2(content) {
|
|
@@ -16130,7 +16739,7 @@ function discoverMemoryDirs() {
|
|
|
16130
16739
|
const out = [];
|
|
16131
16740
|
const seen = /* @__PURE__ */ new Set();
|
|
16132
16741
|
const add = (memoryDir, projectHash) => {
|
|
16133
|
-
if (!seen.has(memoryDir) &&
|
|
16742
|
+
if (!seen.has(memoryDir) && existsSync26(memoryDir)) {
|
|
16134
16743
|
seen.add(memoryDir);
|
|
16135
16744
|
out.push({ memoryDir, projectHash });
|
|
16136
16745
|
}
|
|
@@ -16146,7 +16755,7 @@ function discoverMemoryDirs() {
|
|
|
16146
16755
|
} catch {
|
|
16147
16756
|
}
|
|
16148
16757
|
for (const projectsDir of claudeRoots) {
|
|
16149
|
-
if (!
|
|
16758
|
+
if (!existsSync26(projectsDir))
|
|
16150
16759
|
continue;
|
|
16151
16760
|
try {
|
|
16152
16761
|
for (const entry of readdirSync19(projectsDir, { withFileTypes: true })) {
|
|
@@ -16195,7 +16804,7 @@ var init_agent_memory_source = __esm({
|
|
|
16195
16804
|
}
|
|
16196
16805
|
}
|
|
16197
16806
|
async parse(item) {
|
|
16198
|
-
if (!
|
|
16807
|
+
if (!existsSync26(item.filePath))
|
|
16199
16808
|
return [];
|
|
16200
16809
|
const content = readFileSync18(item.filePath, "utf-8");
|
|
16201
16810
|
const { body: body2 } = parseFrontmatter2(content);
|
|
@@ -16281,7 +16890,7 @@ var init_agent_memory_source = __esm({
|
|
|
16281
16890
|
});
|
|
16282
16891
|
|
|
16283
16892
|
// ../engine/dist/parsers/history-source.js
|
|
16284
|
-
import { existsSync as
|
|
16893
|
+
import { existsSync as existsSync27, readdirSync as readdirSync20, statSync as statSync24 } from "fs";
|
|
16285
16894
|
import { createReadStream as createReadStream3 } from "fs";
|
|
16286
16895
|
import { createInterface as createInterface2 } from "readline";
|
|
16287
16896
|
import { homedir as homedir10 } from "os";
|
|
@@ -16303,7 +16912,7 @@ var init_history_source = __esm({
|
|
|
16303
16912
|
const home = homedir10();
|
|
16304
16913
|
const paths = [];
|
|
16305
16914
|
const tryAdd = (p) => {
|
|
16306
|
-
if (
|
|
16915
|
+
if (existsSync27(p) && !paths.includes(p))
|
|
16307
16916
|
paths.push(p);
|
|
16308
16917
|
};
|
|
16309
16918
|
tryAdd(claudeBackend.historyFile());
|
|
@@ -16321,7 +16930,7 @@ var init_history_source = __esm({
|
|
|
16321
16930
|
async *discover() {
|
|
16322
16931
|
if (!isSourceEnabled("claude", "history"))
|
|
16323
16932
|
return;
|
|
16324
|
-
const historyPath = this.historyPaths.find((p) =>
|
|
16933
|
+
const historyPath = this.historyPaths.find((p) => existsSync27(p));
|
|
16325
16934
|
if (!historyPath)
|
|
16326
16935
|
return;
|
|
16327
16936
|
const stat3 = statSync24(historyPath);
|
|
@@ -16417,7 +17026,7 @@ var init_history_source = __esm({
|
|
|
16417
17026
|
async groupByProject() {
|
|
16418
17027
|
const groups = /* @__PURE__ */ new Map();
|
|
16419
17028
|
for (const historyPath of this.historyPaths) {
|
|
16420
|
-
if (!
|
|
17029
|
+
if (!existsSync27(historyPath))
|
|
16421
17030
|
continue;
|
|
16422
17031
|
const rl = createInterface2({
|
|
16423
17032
|
input: createReadStream3(historyPath),
|
|
@@ -16465,7 +17074,7 @@ var init_history_source = __esm({
|
|
|
16465
17074
|
});
|
|
16466
17075
|
|
|
16467
17076
|
// ../engine/dist/parsers/paste-source.js
|
|
16468
|
-
import { existsSync as
|
|
17077
|
+
import { existsSync as existsSync28, readdirSync as readdirSync21, readFileSync as readFileSync19, statSync as statSync25 } from "fs";
|
|
16469
17078
|
import { homedir as homedir11 } from "os";
|
|
16470
17079
|
import { join as join28, basename as basename15 } from "path";
|
|
16471
17080
|
var MAX_CHUNK_CHARS6, MAX_FILE_SIZE, PasteSource;
|
|
@@ -16486,7 +17095,7 @@ var init_paste_source = __esm({
|
|
|
16486
17095
|
const home = homedir11();
|
|
16487
17096
|
const dirs = [];
|
|
16488
17097
|
const tryAdd = (p) => {
|
|
16489
|
-
if (
|
|
17098
|
+
if (existsSync28(p) && !dirs.includes(p))
|
|
16490
17099
|
dirs.push(p);
|
|
16491
17100
|
};
|
|
16492
17101
|
tryAdd(claudeBackend.pasteCacheDir());
|
|
@@ -16506,7 +17115,7 @@ var init_paste_source = __esm({
|
|
|
16506
17115
|
return;
|
|
16507
17116
|
const seen = /* @__PURE__ */ new Set();
|
|
16508
17117
|
for (const cacheDir of this.cacheDirs) {
|
|
16509
|
-
if (!
|
|
17118
|
+
if (!existsSync28(cacheDir))
|
|
16510
17119
|
continue;
|
|
16511
17120
|
const files = readdirSync21(cacheDir).filter((f) => f.endsWith(".txt"));
|
|
16512
17121
|
for (const file of files) {
|
|
@@ -16540,7 +17149,7 @@ var init_paste_source = __esm({
|
|
|
16540
17149
|
}
|
|
16541
17150
|
}
|
|
16542
17151
|
async parse(item) {
|
|
16543
|
-
if (!
|
|
17152
|
+
if (!existsSync28(item.filePath))
|
|
16544
17153
|
return [];
|
|
16545
17154
|
const content = readFileSync19(item.filePath, "utf-8");
|
|
16546
17155
|
if (content.trim().length < 20)
|
|
@@ -16565,7 +17174,7 @@ var init_paste_source = __esm({
|
|
|
16565
17174
|
});
|
|
16566
17175
|
|
|
16567
17176
|
// ../engine/dist/parsers/antigravity-brain-source.js
|
|
16568
|
-
import { existsSync as
|
|
17177
|
+
import { existsSync as existsSync29, readdirSync as readdirSync22, readFileSync as readFileSync20, statSync as statSync26 } from "fs";
|
|
16569
17178
|
import { join as join29 } from "path";
|
|
16570
17179
|
var MAX_CHUNK_CHARS7, AntigravityBrainSource;
|
|
16571
17180
|
var init_antigravity_brain_source = __esm({
|
|
@@ -16584,7 +17193,7 @@ var init_antigravity_brain_source = __esm({
|
|
|
16584
17193
|
async *discover() {
|
|
16585
17194
|
if (!isSourceEnabled("agy", "brain"))
|
|
16586
17195
|
return;
|
|
16587
|
-
if (!
|
|
17196
|
+
if (!existsSync29(this.brainDir))
|
|
16588
17197
|
return;
|
|
16589
17198
|
const sessions = readdirSync22(this.brainDir, { withFileTypes: true });
|
|
16590
17199
|
for (const entry of sessions) {
|
|
@@ -16603,7 +17212,7 @@ var init_antigravity_brain_source = __esm({
|
|
|
16603
17212
|
const heading = content.split("\n").find((l) => l.startsWith("#"))?.replace(/^#+\s*/, "").trim() || file;
|
|
16604
17213
|
const metaPath = `${filePath}.metadata.json`;
|
|
16605
17214
|
let metaSummary = "";
|
|
16606
|
-
if (
|
|
17215
|
+
if (existsSync29(metaPath)) {
|
|
16607
17216
|
try {
|
|
16608
17217
|
const meta = JSON.parse(readFileSync20(metaPath, "utf-8"));
|
|
16609
17218
|
metaSummary = meta.summary || "";
|
|
@@ -16634,7 +17243,7 @@ var init_antigravity_brain_source = __esm({
|
|
|
16634
17243
|
}
|
|
16635
17244
|
}
|
|
16636
17245
|
async parse(item) {
|
|
16637
|
-
if (!
|
|
17246
|
+
if (!existsSync29(item.filePath))
|
|
16638
17247
|
return [];
|
|
16639
17248
|
const content = readFileSync20(item.filePath, "utf-8");
|
|
16640
17249
|
const chunks = [];
|
|
@@ -16677,7 +17286,7 @@ var init_antigravity_brain_source = __esm({
|
|
|
16677
17286
|
});
|
|
16678
17287
|
|
|
16679
17288
|
// ../engine/dist/parsers/opencode-source.js
|
|
16680
|
-
import { existsSync as
|
|
17289
|
+
import { existsSync as existsSync30 } from "fs";
|
|
16681
17290
|
var MAX_CHUNK_CHARS8, OpenCodeSource;
|
|
16682
17291
|
var init_opencode_source = __esm({
|
|
16683
17292
|
"../engine/dist/parsers/opencode-source.js"() {
|
|
@@ -16695,7 +17304,7 @@ var init_opencode_source = __esm({
|
|
|
16695
17304
|
async *discover() {
|
|
16696
17305
|
if (!isSourceEnabled("opencode", "sessions"))
|
|
16697
17306
|
return;
|
|
16698
|
-
if (!
|
|
17307
|
+
if (!existsSync30(this.dbPath))
|
|
16699
17308
|
return;
|
|
16700
17309
|
let db;
|
|
16701
17310
|
try {
|
|
@@ -16793,7 +17402,7 @@ var init_opencode_source = __esm({
|
|
|
16793
17402
|
}
|
|
16794
17403
|
}
|
|
16795
17404
|
async parse(item) {
|
|
16796
|
-
if (!
|
|
17405
|
+
if (!existsSync30(this.dbPath))
|
|
16797
17406
|
return [];
|
|
16798
17407
|
const sessionId = item.id.replace("opencode_", "");
|
|
16799
17408
|
const db = openSqliteReadonlyOrThrow(this.dbPath);
|
|
@@ -16865,7 +17474,7 @@ var init_opencode_source = __esm({
|
|
|
16865
17474
|
});
|
|
16866
17475
|
|
|
16867
17476
|
// ../engine/dist/parsers/opencode-todo-source.js
|
|
16868
|
-
import { existsSync as
|
|
17477
|
+
import { existsSync as existsSync31 } from "fs";
|
|
16869
17478
|
var OpenCodeTodoSource;
|
|
16870
17479
|
var init_opencode_todo_source = __esm({
|
|
16871
17480
|
"../engine/dist/parsers/opencode-todo-source.js"() {
|
|
@@ -16882,7 +17491,7 @@ var init_opencode_todo_source = __esm({
|
|
|
16882
17491
|
async *discover() {
|
|
16883
17492
|
if (!isSourceEnabled("opencode", "todos"))
|
|
16884
17493
|
return;
|
|
16885
|
-
if (!
|
|
17494
|
+
if (!existsSync31(this.dbPath))
|
|
16886
17495
|
return;
|
|
16887
17496
|
let db;
|
|
16888
17497
|
try {
|
|
@@ -16931,7 +17540,7 @@ var init_opencode_todo_source = __esm({
|
|
|
16931
17540
|
}
|
|
16932
17541
|
}
|
|
16933
17542
|
async parse(item) {
|
|
16934
|
-
if (!
|
|
17543
|
+
if (!existsSync31(this.dbPath))
|
|
16935
17544
|
return [];
|
|
16936
17545
|
const sessionId = item.extra?.sessionId || item.id.replace(`${opencodeBackend.idPrefix}todo_`, "");
|
|
16937
17546
|
const db = openSqliteReadonlyOrThrow(this.dbPath);
|
|
@@ -16979,7 +17588,7 @@ var init_opencode_todo_source = __esm({
|
|
|
16979
17588
|
});
|
|
16980
17589
|
|
|
16981
17590
|
// ../engine/dist/parsers/codex-session-source.js
|
|
16982
|
-
import { existsSync as
|
|
17591
|
+
import { existsSync as existsSync32, readdirSync as readdirSync23, readFileSync as readFileSync21, statSync as statSync27 } from "fs";
|
|
16983
17592
|
import { join as join30, basename as basename16 } from "path";
|
|
16984
17593
|
function getCodexSessionsDir() {
|
|
16985
17594
|
return codexBackend.sessionsDir();
|
|
@@ -17036,7 +17645,7 @@ var init_codex_session_source = __esm({
|
|
|
17036
17645
|
async *discover() {
|
|
17037
17646
|
if (!isSourceEnabled("codex", "sessions"))
|
|
17038
17647
|
return;
|
|
17039
|
-
if (!
|
|
17648
|
+
if (!existsSync32(this.sessionsDir))
|
|
17040
17649
|
return;
|
|
17041
17650
|
const jsonlFiles = this.collectJsonlFiles(this.sessionsDir);
|
|
17042
17651
|
for (const filePath of jsonlFiles) {
|
|
@@ -17095,7 +17704,7 @@ var init_codex_session_source = __esm({
|
|
|
17095
17704
|
}
|
|
17096
17705
|
}
|
|
17097
17706
|
async parse(item) {
|
|
17098
|
-
if (!
|
|
17707
|
+
if (!existsSync32(item.filePath))
|
|
17099
17708
|
return [];
|
|
17100
17709
|
const events = readJsonlLines(item.filePath);
|
|
17101
17710
|
const chunks = [];
|
|
@@ -17198,7 +17807,7 @@ var init_codex_session_source = __esm({
|
|
|
17198
17807
|
}
|
|
17199
17808
|
collectJsonlFiles(dir) {
|
|
17200
17809
|
const results = [];
|
|
17201
|
-
if (!
|
|
17810
|
+
if (!existsSync32(dir))
|
|
17202
17811
|
return results;
|
|
17203
17812
|
for (const entry of readdirSync23(dir, { withFileTypes: true })) {
|
|
17204
17813
|
const fullPath = join30(dir, entry.name);
|
|
@@ -17215,7 +17824,7 @@ var init_codex_session_source = __esm({
|
|
|
17215
17824
|
});
|
|
17216
17825
|
|
|
17217
17826
|
// ../engine/dist/parsers/diary-source.js
|
|
17218
|
-
import { existsSync as
|
|
17827
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync5, readdirSync as readdirSync24, readFileSync as readFileSync22, writeFileSync as writeFileSync4, statSync as statSync28 } from "fs";
|
|
17219
17828
|
import { join as join31, basename as basename17 } from "path";
|
|
17220
17829
|
var MAX_CHUNK_CHARS10, DiarySource;
|
|
17221
17830
|
var init_diary_source = __esm({
|
|
@@ -17231,7 +17840,7 @@ var init_diary_source = __esm({
|
|
|
17231
17840
|
}
|
|
17232
17841
|
/** Discover all diary entries across all agents. */
|
|
17233
17842
|
async *discover() {
|
|
17234
|
-
if (!
|
|
17843
|
+
if (!existsSync33(this.diaryDir))
|
|
17235
17844
|
return;
|
|
17236
17845
|
const agents = readdirSync24(this.diaryDir, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
17237
17846
|
for (const agentDir of agents) {
|
|
@@ -17266,7 +17875,7 @@ var init_diary_source = __esm({
|
|
|
17266
17875
|
}
|
|
17267
17876
|
}
|
|
17268
17877
|
async parse(item) {
|
|
17269
|
-
if (!
|
|
17878
|
+
if (!existsSync33(item.filePath))
|
|
17270
17879
|
return [];
|
|
17271
17880
|
const raw = readFileSync22(item.filePath, "utf-8");
|
|
17272
17881
|
const entry = JSON.parse(raw);
|
|
@@ -17306,7 +17915,7 @@ var init_diary_source = __esm({
|
|
|
17306
17915
|
static write(entry, diaryDir) {
|
|
17307
17916
|
const dir = diaryDir || getDiaryDir();
|
|
17308
17917
|
const agentDir = join31(dir, entry.agent.toLowerCase().replace(/[^a-z0-9_-]/g, "_"));
|
|
17309
|
-
if (!
|
|
17918
|
+
if (!existsSync33(agentDir)) {
|
|
17310
17919
|
mkdirSync5(agentDir, { recursive: true });
|
|
17311
17920
|
}
|
|
17312
17921
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
@@ -17325,7 +17934,7 @@ var init_diary_source = __esm({
|
|
|
17325
17934
|
static read(agentName, lastN = 10, diaryDir) {
|
|
17326
17935
|
const dir = diaryDir || getDiaryDir();
|
|
17327
17936
|
const agentDir = join31(dir, agentName.toLowerCase().replace(/[^a-z0-9_-]/g, "_"));
|
|
17328
|
-
if (!
|
|
17937
|
+
if (!existsSync33(agentDir))
|
|
17329
17938
|
return [];
|
|
17330
17939
|
const files = readdirSync24(agentDir).filter((f) => f.endsWith(".json")).sort().reverse().slice(0, lastN);
|
|
17331
17940
|
const entries = [];
|
|
@@ -17376,7 +17985,7 @@ var init_redact_inline = __esm({
|
|
|
17376
17985
|
});
|
|
17377
17986
|
|
|
17378
17987
|
// ../engine/dist/parsers/skills-source.js
|
|
17379
|
-
import { existsSync as
|
|
17988
|
+
import { existsSync as existsSync34, readdirSync as readdirSync25, readFileSync as readFileSync23, statSync as statSync29 } from "fs";
|
|
17380
17989
|
import { homedir as homedir12 } from "os";
|
|
17381
17990
|
import { join as join32 } from "path";
|
|
17382
17991
|
function rebuildBody(content) {
|
|
@@ -17416,7 +18025,7 @@ function resolveRoots() {
|
|
|
17416
18025
|
all.push({ path: join32(cursorHomeDir(), "skills"), tool: "cursor" });
|
|
17417
18026
|
all.push({ path: join32(cursorHomeDir(), "skills-cursor"), tool: "cursor", readonly: true });
|
|
17418
18027
|
}
|
|
17419
|
-
return all.filter((r) =>
|
|
18028
|
+
return all.filter((r) => existsSync34(r.path));
|
|
17420
18029
|
}
|
|
17421
18030
|
function parseFrontmatter3(text) {
|
|
17422
18031
|
const m = text.match(/^---\n([\s\S]*?)\n---/);
|
|
@@ -17458,7 +18067,7 @@ var init_skills_source = __esm({
|
|
|
17458
18067
|
return;
|
|
17459
18068
|
for (const { name: pluginName, dir } of codexBackend.installedPluginDirs()) {
|
|
17460
18069
|
const skillsDir = join32(dir, "skills");
|
|
17461
|
-
if (!
|
|
18070
|
+
if (!existsSync34(skillsDir))
|
|
17462
18071
|
continue;
|
|
17463
18072
|
yield* this.fromSkillRoot({ path: skillsDir, tool: "codex" }, pluginName);
|
|
17464
18073
|
}
|
|
@@ -17483,7 +18092,7 @@ var init_skills_source = __esm({
|
|
|
17483
18092
|
if (!st.isDirectory())
|
|
17484
18093
|
continue;
|
|
17485
18094
|
const skillMd = join32(skillDir, "SKILL.md");
|
|
17486
|
-
if (!
|
|
18095
|
+
if (!existsSync34(skillMd))
|
|
17487
18096
|
continue;
|
|
17488
18097
|
let content;
|
|
17489
18098
|
try {
|
|
@@ -17548,7 +18157,7 @@ var init_skills_source = __esm({
|
|
|
17548
18157
|
}
|
|
17549
18158
|
}
|
|
17550
18159
|
async parse(item) {
|
|
17551
|
-
if (!
|
|
18160
|
+
if (!existsSync34(item.filePath))
|
|
17552
18161
|
return [];
|
|
17553
18162
|
const content = readFileSync23(item.filePath, "utf-8");
|
|
17554
18163
|
if (!content.trim())
|
|
@@ -17573,11 +18182,11 @@ var init_skills_source = __esm({
|
|
|
17573
18182
|
});
|
|
17574
18183
|
|
|
17575
18184
|
// ../engine/dist/parsers/mcps-source.js
|
|
17576
|
-
import { existsSync as
|
|
18185
|
+
import { existsSync as existsSync35, readFileSync as readFileSync24, statSync as statSync30 } from "fs";
|
|
17577
18186
|
import { homedir as homedir13 } from "os";
|
|
17578
18187
|
import { join as join33 } from "path";
|
|
17579
18188
|
function readJson(path) {
|
|
17580
|
-
if (!
|
|
18189
|
+
if (!existsSync35(path))
|
|
17581
18190
|
return null;
|
|
17582
18191
|
try {
|
|
17583
18192
|
const raw = readFileSync24(path, "utf-8");
|
|
@@ -17740,7 +18349,7 @@ var init_mcps_source = __esm({
|
|
|
17740
18349
|
}
|
|
17741
18350
|
}
|
|
17742
18351
|
async *fromCodexToml(path) {
|
|
17743
|
-
if (!
|
|
18352
|
+
if (!existsSync35(path))
|
|
17744
18353
|
return;
|
|
17745
18354
|
let content;
|
|
17746
18355
|
try {
|
|
@@ -17913,7 +18522,7 @@ var init_toolkit_format = __esm({
|
|
|
17913
18522
|
});
|
|
17914
18523
|
|
|
17915
18524
|
// ../engine/dist/parsers/slash-commands-source.js
|
|
17916
|
-
import { existsSync as
|
|
18525
|
+
import { existsSync as existsSync36, readdirSync as readdirSync26, readFileSync as readFileSync25, statSync as statSync31 } from "fs";
|
|
17917
18526
|
import { join as join34, basename as basename18 } from "path";
|
|
17918
18527
|
function rebuildBody2(content) {
|
|
17919
18528
|
const { text, redacted } = redactInlineSecrets(content);
|
|
@@ -17966,14 +18575,14 @@ var init_slash_commands_source = __esm({
|
|
|
17966
18575
|
if (isSourceEnabled("claude", "commands")) {
|
|
17967
18576
|
roots.push({ path: claudeBackend.commandsDir(), tool: "claude", scope: "user", projectPath: "", format: "md" });
|
|
17968
18577
|
const projectsRoot = claudeBackend.projectsDir();
|
|
17969
|
-
if (
|
|
18578
|
+
if (existsSync36(projectsRoot)) {
|
|
17970
18579
|
try {
|
|
17971
18580
|
for (const entry of readdirSync26(projectsRoot, { withFileTypes: true })) {
|
|
17972
18581
|
if (!entry.isDirectory() || entry.name.startsWith("."))
|
|
17973
18582
|
continue;
|
|
17974
18583
|
const projectPath = resolveProjectDirName(entry.name);
|
|
17975
18584
|
const cmdDir = join34(projectPath, ".claude", "commands");
|
|
17976
|
-
if (
|
|
18585
|
+
if (existsSync36(cmdDir))
|
|
17977
18586
|
roots.push({ path: cmdDir, tool: "claude", scope: "project", projectPath, format: "md" });
|
|
17978
18587
|
}
|
|
17979
18588
|
} catch {
|
|
@@ -18035,7 +18644,7 @@ var init_slash_commands_source = __esm({
|
|
|
18035
18644
|
}
|
|
18036
18645
|
}
|
|
18037
18646
|
async parse(item) {
|
|
18038
|
-
if (!
|
|
18647
|
+
if (!existsSync36(item.filePath))
|
|
18039
18648
|
return [];
|
|
18040
18649
|
const content = readFileSync25(item.filePath, "utf-8");
|
|
18041
18650
|
if (!content.trim())
|
|
@@ -18060,7 +18669,7 @@ var init_slash_commands_source = __esm({
|
|
|
18060
18669
|
});
|
|
18061
18670
|
|
|
18062
18671
|
// ../engine/dist/parsers/subagents-source.js
|
|
18063
|
-
import { existsSync as
|
|
18672
|
+
import { existsSync as existsSync37, readdirSync as readdirSync27, readFileSync as readFileSync26, statSync as statSync32 } from "fs";
|
|
18064
18673
|
import { join as join35, basename as basename19 } from "path";
|
|
18065
18674
|
function rebuildBody3(content) {
|
|
18066
18675
|
const { text, redacted } = redactInlineSecrets(content);
|
|
@@ -18115,14 +18724,14 @@ var init_subagents_source = __esm({
|
|
|
18115
18724
|
if (isSourceEnabled("claude", "agents")) {
|
|
18116
18725
|
roots.push({ path: claudeBackend.agentsDir(), tool: "claude", scope: "user", projectPath: "", format: "md" });
|
|
18117
18726
|
const projectsRoot = claudeBackend.projectsDir();
|
|
18118
|
-
if (
|
|
18727
|
+
if (existsSync37(projectsRoot)) {
|
|
18119
18728
|
try {
|
|
18120
18729
|
for (const entry of readdirSync27(projectsRoot, { withFileTypes: true })) {
|
|
18121
18730
|
if (!entry.isDirectory() || entry.name.startsWith("."))
|
|
18122
18731
|
continue;
|
|
18123
18732
|
const projectPath = resolveProjectDirName(entry.name);
|
|
18124
18733
|
const agentDir = join35(projectPath, ".claude", "agents");
|
|
18125
|
-
if (
|
|
18734
|
+
if (existsSync37(agentDir))
|
|
18126
18735
|
roots.push({ path: agentDir, tool: "claude", scope: "project", projectPath, format: "md" });
|
|
18127
18736
|
}
|
|
18128
18737
|
} catch {
|
|
@@ -18185,7 +18794,7 @@ var init_subagents_source = __esm({
|
|
|
18185
18794
|
}
|
|
18186
18795
|
}
|
|
18187
18796
|
async parse(item) {
|
|
18188
|
-
if (!
|
|
18797
|
+
if (!existsSync37(item.filePath))
|
|
18189
18798
|
return [];
|
|
18190
18799
|
const content = readFileSync26(item.filePath, "utf-8");
|
|
18191
18800
|
if (!content.trim())
|
|
@@ -18210,10 +18819,10 @@ var init_subagents_source = __esm({
|
|
|
18210
18819
|
});
|
|
18211
18820
|
|
|
18212
18821
|
// ../engine/dist/parsers/hooks-source.js
|
|
18213
|
-
import { existsSync as
|
|
18822
|
+
import { existsSync as existsSync38, readFileSync as readFileSync27, readdirSync as readdirSync28, statSync as statSync33 } from "fs";
|
|
18214
18823
|
import { join as join36 } from "path";
|
|
18215
18824
|
function readJson2(path) {
|
|
18216
|
-
if (!
|
|
18825
|
+
if (!existsSync38(path))
|
|
18217
18826
|
return null;
|
|
18218
18827
|
try {
|
|
18219
18828
|
return JSON.parse(readFileSync27(path, "utf-8"));
|
|
@@ -18235,14 +18844,14 @@ var init_hooks_source = __esm({
|
|
|
18235
18844
|
return;
|
|
18236
18845
|
yield* this.fromSettings(claudeBackend.settingsFile(), "user", "");
|
|
18237
18846
|
const projectsRoot = claudeBackend.projectsDir();
|
|
18238
|
-
if (
|
|
18847
|
+
if (existsSync38(projectsRoot)) {
|
|
18239
18848
|
try {
|
|
18240
18849
|
for (const entry of readdirSync28(projectsRoot, { withFileTypes: true })) {
|
|
18241
18850
|
if (!entry.isDirectory() || entry.name.startsWith("."))
|
|
18242
18851
|
continue;
|
|
18243
18852
|
const projectPath = resolveProjectDirName(entry.name);
|
|
18244
18853
|
const settingsPath2 = join36(projectPath, ".claude", "settings.json");
|
|
18245
|
-
if (
|
|
18854
|
+
if (existsSync38(settingsPath2)) {
|
|
18246
18855
|
yield* this.fromSettings(settingsPath2, "project", projectPath);
|
|
18247
18856
|
}
|
|
18248
18857
|
}
|
|
@@ -18333,11 +18942,11 @@ var init_hooks_source = __esm({
|
|
|
18333
18942
|
});
|
|
18334
18943
|
|
|
18335
18944
|
// ../engine/dist/parsers/plugins-source.js
|
|
18336
|
-
import { existsSync as
|
|
18945
|
+
import { existsSync as existsSync39, readFileSync as readFileSync28, readdirSync as readdirSync29, statSync as statSync34 } from "fs";
|
|
18337
18946
|
import { homedir as homedir14 } from "os";
|
|
18338
18947
|
import { join as join37 } from "path";
|
|
18339
18948
|
function readJson3(path) {
|
|
18340
|
-
if (!
|
|
18949
|
+
if (!existsSync39(path))
|
|
18341
18950
|
return null;
|
|
18342
18951
|
try {
|
|
18343
18952
|
return JSON.parse(readFileSync28(path, "utf-8"));
|
|
@@ -18392,7 +19001,7 @@ var init_plugins_source = __esm({
|
|
|
18392
19001
|
}
|
|
18393
19002
|
}
|
|
18394
19003
|
const gemRoot = agyBackend.sharedExtensionsDir();
|
|
18395
|
-
if (isSourceEnabled("agy", "extensions") &&
|
|
19004
|
+
if (isSourceEnabled("agy", "extensions") && existsSync39(gemRoot)) {
|
|
18396
19005
|
let entries;
|
|
18397
19006
|
try {
|
|
18398
19007
|
entries = readdirSync29(gemRoot);
|
|
@@ -18568,6 +19177,8 @@ function toolOfId(id) {
|
|
|
18568
19177
|
return "codex";
|
|
18569
19178
|
if (id.startsWith("cursor_"))
|
|
18570
19179
|
return "cursor";
|
|
19180
|
+
if (id.startsWith("hermes_"))
|
|
19181
|
+
return "hermes";
|
|
18571
19182
|
return "claude";
|
|
18572
19183
|
}
|
|
18573
19184
|
function extractorVersionForTool(tool) {
|
|
@@ -18828,6 +19439,8 @@ function markSynced(server, rows) {
|
|
|
18828
19439
|
else if (prev?.F !== void 0) base4.F = prev.F;
|
|
18829
19440
|
if (cursorFromCaller && r.chunkedHead) base4.k = 1;
|
|
18830
19441
|
else if (prev?.k && !completesChunked && !(cursorFromCaller && r.full)) base4.k = 1;
|
|
19442
|
+
const layout = cursorFromCaller ? r.layout : prev?.L;
|
|
19443
|
+
if (layout) base4.L = layout;
|
|
18831
19444
|
forServer[r.id] = base4;
|
|
18832
19445
|
}
|
|
18833
19446
|
persist(data);
|
|
@@ -18968,12 +19581,12 @@ var init_sync_fields = __esm({
|
|
|
18968
19581
|
});
|
|
18969
19582
|
|
|
18970
19583
|
// ../engine/dist/core/index-lock.js
|
|
18971
|
-
import { existsSync as
|
|
19584
|
+
import { existsSync as existsSync40, mkdirSync as mkdirSync7, openSync as openSync8, writeFileSync as writeFileSync6, readFileSync as readFileSync30, rmSync as rmSync4, statSync as statSync36, closeSync as closeSync8 } from "fs";
|
|
18972
19585
|
import { dirname as dirname16, join as join39 } from "path";
|
|
18973
19586
|
function acquireIndexLock(opts) {
|
|
18974
19587
|
const lockPath = lockFilePath(opts.file);
|
|
18975
19588
|
mkdirSync7(dirname16(lockPath), { recursive: true });
|
|
18976
|
-
if (
|
|
19589
|
+
if (existsSync40(lockPath)) {
|
|
18977
19590
|
if (!stealStaleLock(lockPath, opts.staleAfterMs ?? 10 * 6e4)) {
|
|
18978
19591
|
return null;
|
|
18979
19592
|
}
|
|
@@ -19090,7 +19703,7 @@ var init_http = __esm({
|
|
|
19090
19703
|
CLI_VERSION = JSON.parse(readFileSync31(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
|
|
19091
19704
|
} catch {
|
|
19092
19705
|
try {
|
|
19093
|
-
if (true) CLI_VERSION = "0.7.
|
|
19706
|
+
if (true) CLI_VERSION = "0.7.19";
|
|
19094
19707
|
} catch {
|
|
19095
19708
|
}
|
|
19096
19709
|
}
|
|
@@ -19187,7 +19800,7 @@ var init_derived = __esm({
|
|
|
19187
19800
|
|
|
19188
19801
|
// src/scan-pool.ts
|
|
19189
19802
|
import { Worker } from "node:worker_threads";
|
|
19190
|
-
import { existsSync as
|
|
19803
|
+
import { existsSync as existsSync41 } from "node:fs";
|
|
19191
19804
|
import { fileURLToPath } from "node:url";
|
|
19192
19805
|
import { cpus } from "node:os";
|
|
19193
19806
|
function poolSize() {
|
|
@@ -19202,7 +19815,7 @@ function workerScript() {
|
|
|
19202
19815
|
for (const rel of ["./scan-worker.js", "../dist/scan-worker.js"]) {
|
|
19203
19816
|
try {
|
|
19204
19817
|
const p = fileURLToPath(new URL(rel, import.meta.url));
|
|
19205
|
-
if (
|
|
19818
|
+
if (existsSync41(p)) return p;
|
|
19206
19819
|
} catch {
|
|
19207
19820
|
}
|
|
19208
19821
|
}
|
|
@@ -19588,7 +20201,7 @@ var init_telemetry = __esm({
|
|
|
19588
20201
|
init_sync_client();
|
|
19589
20202
|
cliVersion2 = () => {
|
|
19590
20203
|
try {
|
|
19591
|
-
return true ? "0.7.
|
|
20204
|
+
return true ? "0.7.19" : "dev";
|
|
19592
20205
|
} catch {
|
|
19593
20206
|
return "dev";
|
|
19594
20207
|
}
|
|
@@ -20121,7 +20734,7 @@ __export(auto_update_exports, {
|
|
|
20121
20734
|
tarballUrl: () => tarballUrl
|
|
20122
20735
|
});
|
|
20123
20736
|
import { execSync as execSync2, execFileSync as execFileSync3 } from "node:child_process";
|
|
20124
|
-
import { readFileSync as readFileSync35, existsSync as
|
|
20737
|
+
import { readFileSync as readFileSync35, existsSync as existsSync42 } from "node:fs";
|
|
20125
20738
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
20126
20739
|
import { writeFileSync as writeFileSync8, mkdtempSync as mkdtempSync3, rmSync as rmSync6, readdirSync as readdirSync30, statSync as statSync38, mkdirSync as mkdirSync9 } from "node:fs";
|
|
20127
20740
|
import { join as join42, dirname as dirname18, sep as sep2, posix as pathPosix, win32 as pathWin32 } from "node:path";
|
|
@@ -20282,7 +20895,7 @@ function resolveNpm(loc) {
|
|
|
20282
20895
|
}
|
|
20283
20896
|
function realInstall(tgz) {
|
|
20284
20897
|
const prefix = runningPrefix();
|
|
20285
|
-
const npm = resolveNpm({ execPath: process.execPath, prefix, platform: process.platform, env: process.env, exists:
|
|
20898
|
+
const npm = resolveNpm({ execPath: process.execPath, prefix, platform: process.platform, env: process.env, exists: existsSync42 });
|
|
20286
20899
|
if (prefix) {
|
|
20287
20900
|
npmInstall(npm, ["install", "-g", "--prefix", prefix, tgz]);
|
|
20288
20901
|
return;
|
|
@@ -21135,6 +21748,11 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
21135
21748
|
};
|
|
21136
21749
|
const localSessionIds = /* @__PURE__ */ new Set();
|
|
21137
21750
|
const shippedHash = /* @__PURE__ */ new Map();
|
|
21751
|
+
const shippedLayout = /* @__PURE__ */ new Map();
|
|
21752
|
+
const layoutOf = (id) => {
|
|
21753
|
+
const layout = shippedLayout.get(id);
|
|
21754
|
+
return layout ? { layout } : {};
|
|
21755
|
+
};
|
|
21138
21756
|
const makeBatcher = (field, maxItems, flatten = false, onFlush, barrier) => {
|
|
21139
21757
|
let batch = [];
|
|
21140
21758
|
let batchBytes = 0;
|
|
@@ -21167,7 +21785,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
21167
21785
|
markSynced(base4, rows.map((r) => {
|
|
21168
21786
|
const off = typeof r.from_offset === "number" ? r.from_offset : 0;
|
|
21169
21787
|
const hash = shippedHash.get(r.session_id);
|
|
21170
|
-
return off > 0 ? { id: r.session_id, mtime: r.mtime, offset: off, size: off, hash, acked: true, full: true } : { id: r.session_id, mtime: r.mtime, hash };
|
|
21788
|
+
return off > 0 ? { id: r.session_id, mtime: r.mtime, offset: off, size: off, hash, acked: true, full: true, ...layoutOf(r.session_id) } : { id: r.session_id, mtime: r.mtime, hash };
|
|
21171
21789
|
}));
|
|
21172
21790
|
} catch {
|
|
21173
21791
|
}
|
|
@@ -21210,8 +21828,9 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
21210
21828
|
// size = new offset (file grew to here)
|
|
21211
21829
|
acked: true,
|
|
21212
21830
|
// server merged this tail
|
|
21213
|
-
chunkFinal: c.final === true
|
|
21831
|
+
chunkFinal: c.final === true,
|
|
21214
21832
|
// completes a chunked full sync
|
|
21833
|
+
...layoutOf(c.session_id)
|
|
21215
21834
|
})));
|
|
21216
21835
|
} catch {
|
|
21217
21836
|
}
|
|
@@ -21243,9 +21862,9 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
21243
21862
|
const mtime = conv.mtime;
|
|
21244
21863
|
try {
|
|
21245
21864
|
if (staged || !guarded) {
|
|
21246
|
-
markSynced(base4, [{ id, mtime, offset: conv.from_offset, size: conv.from_offset, acked: true, chunkedHead: true }]);
|
|
21865
|
+
markSynced(base4, [{ id, mtime, offset: conv.from_offset, size: conv.from_offset, acked: true, chunkedHead: true, ...layoutOf(id) }]);
|
|
21247
21866
|
} else if (typeof guarded.o === "number" && guarded.o > 0 && guarded.o <= fileSize) {
|
|
21248
|
-
markSynced(base4, [{ id, mtime, offset: guarded.o, size: guarded.o, acked: true, chunkedHead: true }]);
|
|
21867
|
+
markSynced(base4, [{ id, mtime, offset: guarded.o, size: guarded.o, acked: true, chunkedHead: true, ...layoutOf(id) }]);
|
|
21249
21868
|
} else {
|
|
21250
21869
|
markSynced(base4, [{ id, mtime }]);
|
|
21251
21870
|
}
|
|
@@ -21340,8 +21959,8 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
21340
21959
|
if (!ledger) return ref.mtime >= (opts.sinceMs ?? 0) ? "full" : "skip";
|
|
21341
21960
|
const ack = ledger.get(ref.prefixedId);
|
|
21342
21961
|
const backend = backendFor(ref);
|
|
21343
|
-
const
|
|
21344
|
-
const isAO = !!backend?.isAppendOnly?.() &&
|
|
21962
|
+
const sameLayout = (ack?.L ?? "") === (backend?.sourceLayout?.(ref.prefixedId) ?? "");
|
|
21963
|
+
const isAO = !!backend?.isAppendOnly?.() && sameLayout;
|
|
21345
21964
|
const size = isAO ? backend?.fileSize?.(ref.prefixedId) ?? 0 : 0;
|
|
21346
21965
|
return syncMode(ack, ref.mtime, size, extractorVersionForTool(ref.toolId), isAO);
|
|
21347
21966
|
};
|
|
@@ -21388,6 +22007,9 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
21388
22007
|
skipped++;
|
|
21389
22008
|
continue;
|
|
21390
22009
|
}
|
|
22010
|
+
const layout = backendFor(ref)?.sourceLayout?.(ref.prefixedId) ?? "";
|
|
22011
|
+
if (layout) shippedLayout.set(ref.prefixedId, layout);
|
|
22012
|
+
else shippedLayout.delete(ref.prefixedId);
|
|
21391
22013
|
trace?.(`build (${mode}) ${ref.prefixedId} \xB7 ${(sessionFileBytes(ref) / 1048576).toFixed(1)}MB`);
|
|
21392
22014
|
let promotedForFindings = false;
|
|
21393
22015
|
if (mode === "append" && ledger) {
|
|
@@ -21433,7 +22055,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
21433
22055
|
const off = getBackendForId(ref.prefixedId)?.fileSize?.(ref.rawId) ?? 0;
|
|
21434
22056
|
const priorCursor = ackRow?.s ?? 0;
|
|
21435
22057
|
const safeToAck = off > 0 && off <= priorCursor;
|
|
21436
|
-
markSynced(base4, [safeToAck ? { id: ref.prefixedId, mtime: ref.mtime, offset: off, size: off, hash: built.srcHash, acked: true } : { id: ref.prefixedId, mtime: ref.mtime, hash: built.srcHash }]);
|
|
22058
|
+
markSynced(base4, [safeToAck ? { id: ref.prefixedId, mtime: ref.mtime, offset: off, size: off, hash: built.srcHash, acked: true, ...layoutOf(ref.prefixedId) } : { id: ref.prefixedId, mtime: ref.mtime, hash: built.srcHash }]);
|
|
21437
22059
|
} catch {
|
|
21438
22060
|
}
|
|
21439
22061
|
}
|
|
@@ -22188,7 +22810,7 @@ var init_sync_client = __esm({
|
|
|
22188
22810
|
ownVersion = JSON.parse(readFileSync36(join43(dir, "../package.json"), "utf-8")).version || ownVersion;
|
|
22189
22811
|
} catch {
|
|
22190
22812
|
try {
|
|
22191
|
-
if (true) ownVersion = "0.7.
|
|
22813
|
+
if (true) ownVersion = "0.7.19";
|
|
22192
22814
|
} catch {
|
|
22193
22815
|
}
|
|
22194
22816
|
}
|
|
@@ -22339,7 +22961,7 @@ var init_update_notice = __esm({
|
|
|
22339
22961
|
});
|
|
22340
22962
|
|
|
22341
22963
|
// ../engine/dist/core/which.js
|
|
22342
|
-
import { existsSync as
|
|
22964
|
+
import { existsSync as existsSync43, statSync as statSync40, accessSync, constants } from "node:fs";
|
|
22343
22965
|
import { join as join45, isAbsolute as isAbsolute2, delimiter as delimiter2, sep as sep3 } from "node:path";
|
|
22344
22966
|
function executable(p) {
|
|
22345
22967
|
try {
|
|
@@ -22380,7 +23002,7 @@ function resolveOnPath(name) {
|
|
|
22380
23002
|
continue;
|
|
22381
23003
|
for (const c of candidates(name)) {
|
|
22382
23004
|
const full = join45(dir, c);
|
|
22383
|
-
if (
|
|
23005
|
+
if (existsSync43(full) && executable(full))
|
|
22384
23006
|
return full;
|
|
22385
23007
|
}
|
|
22386
23008
|
}
|
|
@@ -22443,7 +23065,7 @@ __export(mcp_clients_exports, {
|
|
|
22443
23065
|
inspectMcpClients: () => inspectMcpClients,
|
|
22444
23066
|
registerMcpEverywhere: () => registerMcpEverywhere
|
|
22445
23067
|
});
|
|
22446
|
-
import { existsSync as
|
|
23068
|
+
import { existsSync as existsSync45, mkdirSync as mkdirSync12, readFileSync as readFileSync38, writeFileSync as writeFileSync12 } from "fs";
|
|
22447
23069
|
import { homedir as homedir16 } from "os";
|
|
22448
23070
|
import { dirname as dirname21, join as join47 } from "path";
|
|
22449
23071
|
function envHome(varName, fallback) {
|
|
@@ -22462,7 +23084,7 @@ function readJsonObject(path) {
|
|
|
22462
23084
|
}
|
|
22463
23085
|
function registerMcpServersJson(target, path, spec) {
|
|
22464
23086
|
let cfg = {};
|
|
22465
|
-
if (
|
|
23087
|
+
if (existsSync45(path)) {
|
|
22466
23088
|
try {
|
|
22467
23089
|
cfg = readJsonObject(path);
|
|
22468
23090
|
} catch (err) {
|
|
@@ -22491,7 +23113,7 @@ function registerOpencodeJson(path, spec) {
|
|
|
22491
23113
|
const id = "opencode";
|
|
22492
23114
|
const label = "OpenCode";
|
|
22493
23115
|
let cfg = {};
|
|
22494
|
-
if (
|
|
23116
|
+
if (existsSync45(path)) {
|
|
22495
23117
|
try {
|
|
22496
23118
|
cfg = readJsonObject(path);
|
|
22497
23119
|
} catch (err) {
|
|
@@ -22530,7 +23152,7 @@ function registerCodexToml(path, spec) {
|
|
|
22530
23152
|
const id = "codex";
|
|
22531
23153
|
const label = "Codex";
|
|
22532
23154
|
const block = codexBlock(spec);
|
|
22533
|
-
const prev =
|
|
23155
|
+
const prev = existsSync45(path) ? readFileSync38(path, "utf-8") : "";
|
|
22534
23156
|
const lines = prev.length ? prev.split("\n") : [];
|
|
22535
23157
|
const start = lines.findIndex((l) => l.trim() === CODEX_HEADER);
|
|
22536
23158
|
if (start === -1) {
|
|
@@ -22571,7 +23193,7 @@ function inspectMcpClients(opts = {}) {
|
|
|
22571
23193
|
return MCP_CLIENTS.map((c) => {
|
|
22572
23194
|
const path = c.configPath(home);
|
|
22573
23195
|
let registered = false;
|
|
22574
|
-
if (
|
|
23196
|
+
if (existsSync45(path)) {
|
|
22575
23197
|
try {
|
|
22576
23198
|
const raw = readFileSync38(path, "utf-8");
|
|
22577
23199
|
registered = c.id === "codex" ? raw.includes(CODEX_HEADER) : !!(JSON.parse(raw).mcpServers?.[MCP_SERVER_NAME] ?? JSON.parse(raw).mcp?.[MCP_SERVER_NAME]);
|
|
@@ -22608,7 +23230,7 @@ var init_mcp_clients = __esm({
|
|
|
22608
23230
|
configPath: (home) => join47(envHome("CHAT_RECALL_CODEX_HOME", join47(home, ".codex")), "config.toml"),
|
|
22609
23231
|
isPresent(home) {
|
|
22610
23232
|
const p = this.configPath(home);
|
|
22611
|
-
return
|
|
23233
|
+
return existsSync45(p) || existsSync45(dirname21(p));
|
|
22612
23234
|
},
|
|
22613
23235
|
register(spec, home) {
|
|
22614
23236
|
return registerCodexToml(this.configPath(home), spec);
|
|
@@ -22621,7 +23243,7 @@ var init_mcp_clients = __esm({
|
|
|
22621
23243
|
configPath: (home) => join47(envHome("XDG_CONFIG_HOME", join47(home, ".config")), "opencode", "opencode.json"),
|
|
22622
23244
|
isPresent(home) {
|
|
22623
23245
|
const p = this.configPath(home);
|
|
22624
|
-
return
|
|
23246
|
+
return existsSync45(p) || existsSync45(dirname21(p));
|
|
22625
23247
|
},
|
|
22626
23248
|
register(spec, home) {
|
|
22627
23249
|
return registerOpencodeJson(this.configPath(home), spec);
|
|
@@ -22635,7 +23257,7 @@ var init_mcp_clients = __esm({
|
|
|
22635
23257
|
bin: "agy",
|
|
22636
23258
|
configPath: (home) => join47(home, ".gemini", "config", "mcp_config.json"),
|
|
22637
23259
|
isPresent(home) {
|
|
22638
|
-
return
|
|
23260
|
+
return existsSync45(join47(home, ".gemini", "antigravity-cli")) || existsSync45(this.configPath(home));
|
|
22639
23261
|
},
|
|
22640
23262
|
register(spec, home) {
|
|
22641
23263
|
return registerMcpServersJson(this, this.configPath(home), spec);
|
|
@@ -22648,7 +23270,7 @@ var init_mcp_clients = __esm({
|
|
|
22648
23270
|
configPath: (home) => join47(home, ".cursor", "mcp.json"),
|
|
22649
23271
|
isPresent(home) {
|
|
22650
23272
|
const p = this.configPath(home);
|
|
22651
|
-
return
|
|
23273
|
+
return existsSync45(p) || existsSync45(dirname21(p));
|
|
22652
23274
|
},
|
|
22653
23275
|
register(spec, home) {
|
|
22654
23276
|
return registerMcpServersJson(this, this.configPath(home), spec);
|
|
@@ -22672,7 +23294,7 @@ __export(companions_exports, {
|
|
|
22672
23294
|
uninstallCodeindex: () => uninstallCodeindex,
|
|
22673
23295
|
unregisterCodeindexMcp: () => unregisterCodeindexMcp
|
|
22674
23296
|
});
|
|
22675
|
-
import { existsSync as
|
|
23297
|
+
import { existsSync as existsSync46, mkdirSync as mkdirSync13, statSync as statSync41, chmodSync as chmodSync4, unlinkSync as unlinkSync3, renameSync as renameSync5, createWriteStream as createWriteStream2, readFileSync as readFileSync39, writeFileSync as writeFileSync13 } from "node:fs";
|
|
22676
23298
|
import { homedir as homedir17 } from "node:os";
|
|
22677
23299
|
import { join as join48 } from "node:path";
|
|
22678
23300
|
import { execSync as execSync3 } from "node:child_process";
|
|
@@ -22795,7 +23417,7 @@ Refusing to install. The release may have been re-uploaded, or something is serv
|
|
|
22795
23417
|
renameSync5(tmpPath, CODEINDEX_BIN_PATH);
|
|
22796
23418
|
} catch (err) {
|
|
22797
23419
|
try {
|
|
22798
|
-
if (
|
|
23420
|
+
if (existsSync46(tmpPath))
|
|
22799
23421
|
unlinkSync3(tmpPath);
|
|
22800
23422
|
} catch {
|
|
22801
23423
|
}
|
|
@@ -22804,7 +23426,7 @@ Refusing to install. The release may have been re-uploaded, or something is serv
|
|
|
22804
23426
|
return checkCodeindexStatus();
|
|
22805
23427
|
}
|
|
22806
23428
|
function uninstallCodeindex() {
|
|
22807
|
-
if (
|
|
23429
|
+
if (existsSync46(CODEINDEX_BIN_PATH)) {
|
|
22808
23430
|
unlinkSync3(CODEINDEX_BIN_PATH);
|
|
22809
23431
|
return { removed: true, path: CODEINDEX_BIN_PATH };
|
|
22810
23432
|
}
|
|
@@ -22812,7 +23434,7 @@ function uninstallCodeindex() {
|
|
|
22812
23434
|
}
|
|
22813
23435
|
function registerCodeindexMcp(mcpJsonPath, binaryPath) {
|
|
22814
23436
|
let cfg = {};
|
|
22815
|
-
if (
|
|
23437
|
+
if (existsSync46(mcpJsonPath)) {
|
|
22816
23438
|
try {
|
|
22817
23439
|
cfg = JSON.parse(readFileSync39(mcpJsonPath, "utf-8"));
|
|
22818
23440
|
} catch {
|
|
@@ -22827,7 +23449,7 @@ function registerCodeindexMcp(mcpJsonPath, binaryPath) {
|
|
|
22827
23449
|
return { added: true };
|
|
22828
23450
|
}
|
|
22829
23451
|
function unregisterCodeindexMcp(mcpJsonPath) {
|
|
22830
|
-
if (!
|
|
23452
|
+
if (!existsSync46(mcpJsonPath))
|
|
22831
23453
|
return { removed: false };
|
|
22832
23454
|
let cfg;
|
|
22833
23455
|
try {
|
|
@@ -22873,7 +23495,7 @@ __export(install_skills_exports, {
|
|
|
22873
23495
|
skillsSourceDir: () => skillsSourceDir,
|
|
22874
23496
|
uninstallSkills: () => uninstallSkills
|
|
22875
23497
|
});
|
|
22876
|
-
import { readdirSync as readdirSync32, existsSync as
|
|
23498
|
+
import { readdirSync as readdirSync32, existsSync as existsSync47, mkdirSync as mkdirSync14, rmSync as rmSync8, cpSync, writeFileSync as writeFileSync14, readFileSync as readFileSync40, statSync as statSync42, realpathSync as realpathSync4 } from "fs";
|
|
22877
23499
|
import { createHash as createHash11 } from "crypto";
|
|
22878
23500
|
import { join as join49, basename as basename21 } from "path";
|
|
22879
23501
|
function skillsSourceDir() {
|
|
@@ -22912,8 +23534,8 @@ function skillStamp() {
|
|
|
22912
23534
|
}
|
|
22913
23535
|
function bundledSkillNames() {
|
|
22914
23536
|
const src = skillsSourceDir();
|
|
22915
|
-
if (!
|
|
22916
|
-
return readdirSync32(src, { withFileTypes: true }).filter((e) => e.isDirectory() &&
|
|
23537
|
+
if (!existsSync47(src)) return [];
|
|
23538
|
+
return readdirSync32(src, { withFileTypes: true }).filter((e) => e.isDirectory() && existsSync47(join49(src, e.name, "SKILL.md"))).map((e) => e.name).sort();
|
|
22917
23539
|
}
|
|
22918
23540
|
function realPathOrSelf(p) {
|
|
22919
23541
|
try {
|
|
@@ -22937,7 +23559,7 @@ function claudeSkillTargets() {
|
|
|
22937
23559
|
dir,
|
|
22938
23560
|
// Judge each profile on ITS OWN transcripts, not the primary's: a home
|
|
22939
23561
|
// with no projects/ is a directory someone made, not a Claude install.
|
|
22940
|
-
available:
|
|
23562
|
+
available: existsSync47(join49(home, "projects"))
|
|
22941
23563
|
});
|
|
22942
23564
|
}
|
|
22943
23565
|
if (targets.length === 0) {
|
|
@@ -22961,7 +23583,7 @@ function skillTargets() {
|
|
|
22961
23583
|
];
|
|
22962
23584
|
}
|
|
22963
23585
|
function isManaged(dir) {
|
|
22964
|
-
return
|
|
23586
|
+
return existsSync47(join49(dir, MARKER));
|
|
22965
23587
|
}
|
|
22966
23588
|
function installSkills(opts = {}) {
|
|
22967
23589
|
const onlyAvailable = opts.onlyAvailable ?? true;
|
|
@@ -22979,7 +23601,7 @@ function installSkills(opts = {}) {
|
|
|
22979
23601
|
}
|
|
22980
23602
|
for (const name of names) {
|
|
22981
23603
|
const dest = join49(t.dir, name);
|
|
22982
|
-
if (
|
|
23604
|
+
if (existsSync47(dest) && !isManaged(dest)) {
|
|
22983
23605
|
skippedUserOwned.push(name);
|
|
22984
23606
|
continue;
|
|
22985
23607
|
}
|
|
@@ -22999,7 +23621,7 @@ function uninstallSkills() {
|
|
|
22999
23621
|
const perTarget = [];
|
|
23000
23622
|
for (const t of skillTargets()) {
|
|
23001
23623
|
const removed = [];
|
|
23002
|
-
if (!
|
|
23624
|
+
if (!existsSync47(t.dir)) {
|
|
23003
23625
|
perTarget.push({ id: t.id, label: t.label, removed });
|
|
23004
23626
|
continue;
|
|
23005
23627
|
}
|
|
@@ -23023,7 +23645,7 @@ function skillsNeedRefresh() {
|
|
|
23023
23645
|
if (!t.available) continue;
|
|
23024
23646
|
for (const name of names) {
|
|
23025
23647
|
const marker = join49(t.dir, name, MARKER);
|
|
23026
|
-
if (!
|
|
23648
|
+
if (!existsSync47(marker)) return true;
|
|
23027
23649
|
try {
|
|
23028
23650
|
if (readFileSync40(marker, "utf-8").trim() !== cur) return true;
|
|
23029
23651
|
} catch {
|
|
@@ -23041,7 +23663,7 @@ function skillStatus() {
|
|
|
23041
23663
|
let ver = null;
|
|
23042
23664
|
for (const name of names) {
|
|
23043
23665
|
const marker = join49(t.dir, name, MARKER);
|
|
23044
|
-
if (
|
|
23666
|
+
if (existsSync47(marker)) {
|
|
23045
23667
|
installed++;
|
|
23046
23668
|
try {
|
|
23047
23669
|
ver = readFileSync40(marker, "utf-8").trim();
|
|
@@ -23229,7 +23851,7 @@ __export(toolkit_sync_exports, {
|
|
|
23229
23851
|
supportedTargetsFor: () => supportedTargetsFor,
|
|
23230
23852
|
writeMcpEntry: () => writeMcpEntry
|
|
23231
23853
|
});
|
|
23232
|
-
import { existsSync as
|
|
23854
|
+
import { existsSync as existsSync48, mkdirSync as mkdirSync15, readFileSync as readFileSync42, writeFileSync as writeFileSync15, cpSync as cpSync2 } from "fs";
|
|
23233
23855
|
import { dirname as dirname22, join as join51, basename as basename23 } from "path";
|
|
23234
23856
|
import { homedir as homedir19 } from "os";
|
|
23235
23857
|
function supportedTargetsFor(type) {
|
|
@@ -23284,11 +23906,11 @@ function skillsDirFor(tool) {
|
|
|
23284
23906
|
}
|
|
23285
23907
|
function copySkill(row, toTool) {
|
|
23286
23908
|
const skillDir = row.extra.skillDir || dirname22(row.filePath);
|
|
23287
|
-
if (!
|
|
23909
|
+
if (!existsSync48(skillDir))
|
|
23288
23910
|
return { ok: false, status: 404, error: `Source dir missing: ${skillDir}` };
|
|
23289
23911
|
const name = row.extra.skillName || basename23(skillDir);
|
|
23290
23912
|
const targetDir = join51(skillsDirFor(toTool), name);
|
|
23291
|
-
if (
|
|
23913
|
+
if (existsSync48(targetDir))
|
|
23292
23914
|
return { ok: false, status: 409, error: `Already exists: ${targetDir}` };
|
|
23293
23915
|
try {
|
|
23294
23916
|
mkdirSync15(dirname22(targetDir), { recursive: true });
|
|
@@ -23320,7 +23942,7 @@ function readMcpEntry(tool, name) {
|
|
|
23320
23942
|
return entry;
|
|
23321
23943
|
}
|
|
23322
23944
|
for (const t of tries) {
|
|
23323
|
-
if (!
|
|
23945
|
+
if (!existsSync48(t.path))
|
|
23324
23946
|
continue;
|
|
23325
23947
|
try {
|
|
23326
23948
|
const cfg = JSON.parse(readFileSync42(t.path, "utf-8"));
|
|
@@ -23333,7 +23955,7 @@ function readMcpEntry(tool, name) {
|
|
|
23333
23955
|
return null;
|
|
23334
23956
|
}
|
|
23335
23957
|
function readCodexMcpEntry(path, target) {
|
|
23336
|
-
if (!
|
|
23958
|
+
if (!existsSync48(path))
|
|
23337
23959
|
return null;
|
|
23338
23960
|
let content;
|
|
23339
23961
|
try {
|
|
@@ -23387,7 +24009,7 @@ function readCodexMcpEntry(path, target) {
|
|
|
23387
24009
|
}
|
|
23388
24010
|
function writeCodexMcpEntry(path, name, entry) {
|
|
23389
24011
|
let content = "";
|
|
23390
|
-
if (
|
|
24012
|
+
if (existsSync48(path))
|
|
23391
24013
|
content = readFileSync42(path, "utf-8");
|
|
23392
24014
|
const header = `[mcp_servers.${name}]`;
|
|
23393
24015
|
if (content.includes(header))
|
|
@@ -23445,7 +24067,7 @@ function writeMcpEntry(toTool, name, entry) {
|
|
|
23445
24067
|
key2 = "mcp";
|
|
23446
24068
|
}
|
|
23447
24069
|
let cfg = {};
|
|
23448
|
-
if (
|
|
24070
|
+
if (existsSync48(path)) {
|
|
23449
24071
|
try {
|
|
23450
24072
|
cfg = JSON.parse(readFileSync42(path, "utf-8"));
|
|
23451
24073
|
} catch {
|
|
@@ -23509,7 +24131,7 @@ function copyCommandOrAgent(type, row, toTool) {
|
|
|
23509
24131
|
return { ok: false, status: 404, error: `Source unreadable: ${e instanceof Error ? e.message : "failed"}` };
|
|
23510
24132
|
}
|
|
23511
24133
|
const out = emit(type, art, toTool);
|
|
23512
|
-
if (
|
|
24134
|
+
if (existsSync48(out.path))
|
|
23513
24135
|
return { ok: false, status: 409, error: `Already exists: ${out.path}` };
|
|
23514
24136
|
try {
|
|
23515
24137
|
mkdirSync15(dirname22(out.path), { recursive: true });
|
|
@@ -23529,7 +24151,7 @@ function copyInstructions(row, toTool) {
|
|
|
23529
24151
|
return { ok: false, status: 404, error: `Source unreadable: ${e instanceof Error ? e.message : "failed"}` };
|
|
23530
24152
|
}
|
|
23531
24153
|
const out = emit("instructions", art, toTool, row.projectPath || void 0);
|
|
23532
|
-
if (
|
|
24154
|
+
if (existsSync48(out.path))
|
|
23533
24155
|
return { ok: false, status: 409, error: `Already exists: ${out.path}` };
|
|
23534
24156
|
try {
|
|
23535
24157
|
mkdirSync15(dirname22(out.path), { recursive: true });
|
|
@@ -23680,7 +24302,7 @@ __export(toolkit_pull_exports, {
|
|
|
23680
24302
|
platformRefusal: () => platformRefusal,
|
|
23681
24303
|
portableCommand: () => portableCommand
|
|
23682
24304
|
});
|
|
23683
|
-
import { existsSync as
|
|
24305
|
+
import { existsSync as existsSync49, mkdirSync as mkdirSync16, statSync as statSync43, writeFileSync as writeFileSync16 } from "node:fs";
|
|
23684
24306
|
import { dirname as dirname23, join as join52, basename as basename24, isAbsolute as isAbsolute3 } from "node:path";
|
|
23685
24307
|
function isExecutableFile(p) {
|
|
23686
24308
|
try {
|
|
@@ -23853,7 +24475,7 @@ function executePull(rows, opts = {}) {
|
|
|
23853
24475
|
for (const tool of tools) {
|
|
23854
24476
|
const dir = join52(skillsDirFor(tool), name);
|
|
23855
24477
|
const file = join52(dir, "SKILL.md");
|
|
23856
|
-
if (
|
|
24478
|
+
if (existsSync49(file)) {
|
|
23857
24479
|
outcomes.push({ type: "skill", name, tool, status: "present" });
|
|
23858
24480
|
continue;
|
|
23859
24481
|
}
|
|
@@ -23898,7 +24520,7 @@ function executePull(rows, opts = {}) {
|
|
|
23898
24520
|
outcomes.push({ type, name, tool, status: "failed", reason: e instanceof Error ? e.message : "emit failed" });
|
|
23899
24521
|
continue;
|
|
23900
24522
|
}
|
|
23901
|
-
if (
|
|
24523
|
+
if (existsSync49(out.path)) {
|
|
23902
24524
|
outcomes.push({ type, name, tool, status: "present" });
|
|
23903
24525
|
continue;
|
|
23904
24526
|
}
|
|
@@ -24061,7 +24683,7 @@ __export(board_hooks_exports, {
|
|
|
24061
24683
|
removeBoardHooks: () => removeBoardHooks,
|
|
24062
24684
|
resolveCliEntry: () => resolveCliEntry
|
|
24063
24685
|
});
|
|
24064
|
-
import { existsSync as
|
|
24686
|
+
import { existsSync as existsSync50, mkdirSync as mkdirSync17, readFileSync as readFileSync43, writeFileSync as writeFileSync17 } from "node:fs";
|
|
24065
24687
|
import { dirname as dirname24, join as join53 } from "node:path";
|
|
24066
24688
|
function boardHookCommand(execPath, cliEntry, mode) {
|
|
24067
24689
|
return `"${execPath}" "${cliEntry}" task-hook --${mode}`;
|
|
@@ -24101,7 +24723,7 @@ function removeBoardHooks(config2) {
|
|
|
24101
24723
|
return removed;
|
|
24102
24724
|
}
|
|
24103
24725
|
function readConfig(file) {
|
|
24104
|
-
if (!
|
|
24726
|
+
if (!existsSync50(file)) return { hooks: {} };
|
|
24105
24727
|
try {
|
|
24106
24728
|
const parsed = JSON.parse(readFileSync43(file, "utf-8"));
|
|
24107
24729
|
if (!parsed.hooks || typeof parsed.hooks !== "object") parsed.hooks = {};
|
|
@@ -24113,7 +24735,7 @@ function readConfig(file) {
|
|
|
24113
24735
|
function registerBoardHooks(files, execPath, cliEntry) {
|
|
24114
24736
|
const written = [];
|
|
24115
24737
|
for (const file of files) {
|
|
24116
|
-
if (
|
|
24738
|
+
if (existsSync50(file)) {
|
|
24117
24739
|
try {
|
|
24118
24740
|
JSON.parse(readFileSync43(file, "utf-8"));
|
|
24119
24741
|
} catch {
|
|
@@ -24133,7 +24755,7 @@ function registerBoardHooks(files, execPath, cliEntry) {
|
|
|
24133
24755
|
}
|
|
24134
24756
|
function resolveCliEntry(distDir) {
|
|
24135
24757
|
const bundled = join53(distDir, "cli.js");
|
|
24136
|
-
return
|
|
24758
|
+
return existsSync50(bundled) ? bundled : join53(distDir, "cli.ts");
|
|
24137
24759
|
}
|
|
24138
24760
|
var BOARD_HOOKS;
|
|
24139
24761
|
var init_board_hooks = __esm({
|
|
@@ -24805,11 +25427,11 @@ var verify_repair_exports = {};
|
|
|
24805
25427
|
__export(verify_repair_exports, {
|
|
24806
25428
|
forceFullResync: () => forceFullResync
|
|
24807
25429
|
});
|
|
24808
|
-
import { copyFileSync as copyFileSync3, existsSync as
|
|
25430
|
+
import { copyFileSync as copyFileSync3, existsSync as existsSync51 } from "fs";
|
|
24809
25431
|
function forceFullResync(server, sessionIds) {
|
|
24810
25432
|
if (sessionIds.length === 0) return 0;
|
|
24811
25433
|
const path = ledgerFilePath();
|
|
24812
|
-
if (
|
|
25434
|
+
if (existsSync51(path)) {
|
|
24813
25435
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "").replace(/-/g, "");
|
|
24814
25436
|
try {
|
|
24815
25437
|
copyFileSync3(path, `${path}.bak-${stamp}`);
|
|
@@ -25966,7 +26588,7 @@ __export(project_tasks_exports, {
|
|
|
25966
26588
|
pushProjectTaskStatuses: () => pushProjectTaskStatuses,
|
|
25967
26589
|
renderTeamTasksMd: () => renderTeamTasksMd
|
|
25968
26590
|
});
|
|
25969
|
-
import { existsSync as
|
|
26591
|
+
import { existsSync as existsSync52, readFileSync as readFileSync45, writeFileSync as writeFileSync18, mkdirSync as mkdirSync18, statSync as statSync44 } from "node:fs";
|
|
25970
26592
|
import { join as join56, dirname as dirname25 } from "node:path";
|
|
25971
26593
|
import { homedir as homedir21 } from "node:os";
|
|
25972
26594
|
function isTeamTaskStatus(v) {
|
|
@@ -26052,7 +26674,7 @@ async function pushProjectTaskStatuses(base4, authHeaders, opts = {}) {
|
|
|
26052
26674
|
}
|
|
26053
26675
|
for (const project of projects) {
|
|
26054
26676
|
const file = join56(project, fk.filename);
|
|
26055
|
-
if (!
|
|
26677
|
+
if (!existsSync52(file)) continue;
|
|
26056
26678
|
let mtime;
|
|
26057
26679
|
try {
|
|
26058
26680
|
mtime = statSync44(file).mtimeMs;
|
|
@@ -26134,7 +26756,7 @@ __export(intent_drain_exports, {
|
|
|
26134
26756
|
drainSyncIntents: () => drainSyncIntents,
|
|
26135
26757
|
instructionTargets: () => instructionTargets
|
|
26136
26758
|
});
|
|
26137
|
-
import { existsSync as
|
|
26759
|
+
import { existsSync as existsSync53, readFileSync as readFileSync46, writeFileSync as writeFileSync19, appendFileSync, mkdirSync as mkdirSync19 } from "node:fs";
|
|
26138
26760
|
import { join as join57 } from "node:path";
|
|
26139
26761
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
26140
26762
|
import { dirname as dirname26 } from "node:path";
|
|
@@ -26149,7 +26771,7 @@ function instructionTargets(rootPath, isGlobal) {
|
|
|
26149
26771
|
const tools = installed.length ? installed : [INSTRUCTION_TOOLS[0]];
|
|
26150
26772
|
if (isGlobal) return [...new Set(tools.map((t) => instructionsPath(t.id)))];
|
|
26151
26773
|
if (!rootPath) return [];
|
|
26152
|
-
const present = INSTRUCTION_FILENAMES.map((f) => join57(rootPath, f)).filter((p) =>
|
|
26774
|
+
const present = INSTRUCTION_FILENAMES.map((f) => join57(rootPath, f)).filter((p) => existsSync53(p));
|
|
26153
26775
|
if (present.length) return present;
|
|
26154
26776
|
return [...new Set(tools.map((t) => join57(rootPath, instructionsFilename(t.id))))];
|
|
26155
26777
|
}
|
|
@@ -26177,7 +26799,7 @@ function applyCodeRecommendation(intent) {
|
|
|
26177
26799
|
mkdirSync19(dir, { recursive: true });
|
|
26178
26800
|
} catch {
|
|
26179
26801
|
}
|
|
26180
|
-
const existing =
|
|
26802
|
+
const existing = existsSync53(file) ? readFileSync46(file, "utf8") : "";
|
|
26181
26803
|
if (existing.includes(text)) {
|
|
26182
26804
|
skipped.push(file);
|
|
26183
26805
|
continue;
|
|
@@ -26355,7 +26977,7 @@ var init_intent_drain = __esm({
|
|
|
26355
26977
|
ownVersion2 = JSON.parse(readFileSync46(join57(dir, "../package.json"), "utf-8")).version || ownVersion2;
|
|
26356
26978
|
} catch {
|
|
26357
26979
|
try {
|
|
26358
|
-
if (true) ownVersion2 = "0.7.
|
|
26980
|
+
if (true) ownVersion2 = "0.7.19";
|
|
26359
26981
|
} catch {
|
|
26360
26982
|
}
|
|
26361
26983
|
}
|
|
@@ -26556,7 +27178,7 @@ var team_merge_exports = {};
|
|
|
26556
27178
|
__export(team_merge_exports, {
|
|
26557
27179
|
mergePullResult: () => mergePullResult
|
|
26558
27180
|
});
|
|
26559
|
-
import { existsSync as
|
|
27181
|
+
import { existsSync as existsSync54, mkdirSync as mkdirSync20, readFileSync as readFileSync47, rmSync as rmSync9, writeFileSync as writeFileSync20, statSync as statSync45 } from "fs";
|
|
26560
27182
|
import { dirname as dirname27, join as join58 } from "path";
|
|
26561
27183
|
import { createHash as createHash14 } from "crypto";
|
|
26562
27184
|
function installPathFor(art, tool) {
|
|
@@ -26673,7 +27295,7 @@ async function mergePullResult(opts) {
|
|
|
26673
27295
|
if (!path)
|
|
26674
27296
|
continue;
|
|
26675
27297
|
try {
|
|
26676
|
-
if (
|
|
27298
|
+
if (existsSync54(path))
|
|
26677
27299
|
rmSync9(path, { force: true });
|
|
26678
27300
|
await teamInstallsForget(id, row.tool);
|
|
26679
27301
|
report.removed.push({ artifactId: id, path });
|
|
@@ -26691,7 +27313,7 @@ async function mergePullResult(opts) {
|
|
|
26691
27313
|
}
|
|
26692
27314
|
function readFileIfExists(path) {
|
|
26693
27315
|
try {
|
|
26694
|
-
if (!
|
|
27316
|
+
if (!existsSync54(path))
|
|
26695
27317
|
return null;
|
|
26696
27318
|
const s = statSync45(path);
|
|
26697
27319
|
if (!s.isFile())
|
|
@@ -26777,7 +27399,7 @@ var init_vault_crypto = __esm({
|
|
|
26777
27399
|
});
|
|
26778
27400
|
|
|
26779
27401
|
// ../engine/dist/core/vault-source.js
|
|
26780
|
-
import { existsSync as
|
|
27402
|
+
import { existsSync as existsSync55, readdirSync as readdirSync33, statSync as statSync46 } from "fs";
|
|
26781
27403
|
import { extname, join as join59 } from "path";
|
|
26782
27404
|
function* walkVaultSources() {
|
|
26783
27405
|
const t = loadSettings().team.vault;
|
|
@@ -26803,7 +27425,7 @@ function safeStat(path) {
|
|
|
26803
27425
|
}
|
|
26804
27426
|
function* walkClaude() {
|
|
26805
27427
|
const root = claudeBackend.projectsDir();
|
|
26806
|
-
if (!
|
|
27428
|
+
if (!existsSync55(root))
|
|
26807
27429
|
return;
|
|
26808
27430
|
let projectDirs = [];
|
|
26809
27431
|
try {
|
|
@@ -26856,7 +27478,7 @@ function* walkCursor() {
|
|
|
26856
27478
|
}
|
|
26857
27479
|
function* walkCodex() {
|
|
26858
27480
|
const sessionsRoot = join59(codexBackend.homeDir(), "sessions");
|
|
26859
|
-
if (!
|
|
27481
|
+
if (!existsSync55(sessionsRoot))
|
|
26860
27482
|
return;
|
|
26861
27483
|
const stack = [sessionsRoot];
|
|
26862
27484
|
while (stack.length) {
|
|
@@ -26885,7 +27507,7 @@ function* walkCodex() {
|
|
|
26885
27507
|
}
|
|
26886
27508
|
function* walkAgy() {
|
|
26887
27509
|
const brainDir = join59(agyBackend.homeDir(), "brain");
|
|
26888
|
-
if (!
|
|
27510
|
+
if (!existsSync55(brainDir))
|
|
26889
27511
|
return;
|
|
26890
27512
|
let sessionDirs = [];
|
|
26891
27513
|
try {
|
|
@@ -26902,10 +27524,10 @@ function* walkAgy() {
|
|
|
26902
27524
|
continue;
|
|
26903
27525
|
}
|
|
26904
27526
|
let filePath = join59(sessionPath, ".system_generated", "logs", "transcript.jsonl");
|
|
26905
|
-
if (!
|
|
27527
|
+
if (!existsSync55(filePath)) {
|
|
26906
27528
|
filePath = join59(sessionPath, ".system_generated", "logs", "transcript_full.jsonl");
|
|
26907
27529
|
}
|
|
26908
|
-
if (!
|
|
27530
|
+
if (!existsSync55(filePath))
|
|
26909
27531
|
continue;
|
|
26910
27532
|
const s = safeStat(filePath);
|
|
26911
27533
|
if (!s)
|
|
@@ -26941,7 +27563,7 @@ __export(vault_client_exports, {
|
|
|
26941
27563
|
vaultStatus: () => vaultStatus,
|
|
26942
27564
|
vaultSync: () => vaultSync
|
|
26943
27565
|
});
|
|
26944
|
-
import { mkdirSync as mkdirSync21, readFileSync as readFileSync48, writeFileSync as writeFileSync21, existsSync as
|
|
27566
|
+
import { mkdirSync as mkdirSync21, readFileSync as readFileSync48, writeFileSync as writeFileSync21, existsSync as existsSync56 } from "fs";
|
|
26945
27567
|
import { dirname as dirname28, join as join60 } from "path";
|
|
26946
27568
|
function context2() {
|
|
26947
27569
|
const s = loadSettings().team;
|
|
@@ -27154,7 +27776,7 @@ async function vaultRestore(passphrase, opts = {}) {
|
|
|
27154
27776
|
}
|
|
27155
27777
|
try {
|
|
27156
27778
|
const path = importedPathFor(blob.tool, blob.sessionId);
|
|
27157
|
-
if (
|
|
27779
|
+
if (existsSync56(path)) {
|
|
27158
27780
|
const localStat = await import("fs").then((m) => m.statSync(path));
|
|
27159
27781
|
if (Math.abs(localStat.mtimeMs - blob.mtimeSourceMs) < 1) {
|
|
27160
27782
|
report.skipped.push({ sessionId: blob.sessionId, tool: blob.tool, reason: "unchanged" });
|
|
@@ -27784,7 +28406,7 @@ __export(service_installer_exports, {
|
|
|
27784
28406
|
uninstallService: () => uninstallService
|
|
27785
28407
|
});
|
|
27786
28408
|
import { execSync as execSync5 } from "child_process";
|
|
27787
|
-
import { existsSync as
|
|
28409
|
+
import { existsSync as existsSync57, mkdirSync as mkdirSync22, readFileSync as readFileSync49, rmSync as rmSync10, writeFileSync as writeFileSync22 } from "fs";
|
|
27788
28410
|
import { homedir as homedir22 } from "os";
|
|
27789
28411
|
import { join as join61 } from "path";
|
|
27790
28412
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
@@ -27820,7 +28442,7 @@ function refreshServiceDefinition() {
|
|
|
27820
28442
|
try {
|
|
27821
28443
|
const { watchJs, node, logFile } = resolveDaemonPaths();
|
|
27822
28444
|
const unitPath = join61(homedir22(), ".config", "systemd", "user", "chat-recall-watch.service");
|
|
27823
|
-
if (!
|
|
28445
|
+
if (!existsSync57(unitPath)) return false;
|
|
27824
28446
|
const current = readFileSync49(unitPath, "utf8");
|
|
27825
28447
|
if (!current.includes(watchJs)) return false;
|
|
27826
28448
|
const wanted = renderSystemdUnit(watchJs, node, logFile);
|
|
@@ -27988,7 +28610,7 @@ function uninstallService() {
|
|
|
27988
28610
|
} catch {
|
|
27989
28611
|
}
|
|
27990
28612
|
const unitPath = join61(homedir22(), ".config", "systemd", "user", "chat-recall-watch.service");
|
|
27991
|
-
if (
|
|
28613
|
+
if (existsSync57(unitPath)) {
|
|
27992
28614
|
rmSync10(unitPath, { force: true });
|
|
27993
28615
|
removed = true;
|
|
27994
28616
|
}
|
|
@@ -28005,7 +28627,7 @@ function uninstallService() {
|
|
|
28005
28627
|
} catch {
|
|
28006
28628
|
}
|
|
28007
28629
|
let removed = false;
|
|
28008
|
-
if (
|
|
28630
|
+
if (existsSync57(plistPath)) {
|
|
28009
28631
|
rmSync10(plistPath, { force: true });
|
|
28010
28632
|
removed = true;
|
|
28011
28633
|
}
|
|
@@ -28377,6 +28999,7 @@ var SESSION_ID_PREFIXES = {
|
|
|
28377
28999
|
opencode: "opencode_",
|
|
28378
29000
|
agy: "agy_",
|
|
28379
29001
|
cursor: "cursor_",
|
|
29002
|
+
hermes: "hermes_",
|
|
28380
29003
|
gemini: "gemini_"
|
|
28381
29004
|
};
|
|
28382
29005
|
function toolOfSessionId(sessionId) {
|
|
@@ -28405,6 +29028,8 @@ function resumeCommandFor(sessionId, tool) {
|
|
|
28405
29028
|
// available answer for either.
|
|
28406
29029
|
case "cursor":
|
|
28407
29030
|
return `cursor-agent --resume ${raw("cursor_")}`;
|
|
29031
|
+
case "hermes":
|
|
29032
|
+
return `hermes --resume ${raw("hermes_")}`;
|
|
28408
29033
|
// Gemini's `--resume` takes an index or "latest", never a session id.
|
|
28409
29034
|
default:
|
|
28410
29035
|
return null;
|
|
@@ -28528,7 +29153,7 @@ init_project_resolver();
|
|
|
28528
29153
|
import { config } from "dotenv";
|
|
28529
29154
|
import { Command } from "commander";
|
|
28530
29155
|
import chalk2 from "chalk";
|
|
28531
|
-
import { existsSync as
|
|
29156
|
+
import { existsSync as existsSync58, readFileSync as readFileSync50, writeFileSync as writeFileSync23, realpathSync as realpathSync5 } from "fs";
|
|
28532
29157
|
import { homedir as homedir23 } from "os";
|
|
28533
29158
|
import { join as join62, resolve as resolve2, dirname as dirname29, basename as basename27 } from "path";
|
|
28534
29159
|
|
|
@@ -28637,7 +29262,7 @@ function renderEnvNeeds(needs, installedCount) {
|
|
|
28637
29262
|
|
|
28638
29263
|
// src/star-nudge.ts
|
|
28639
29264
|
init_paths();
|
|
28640
|
-
import { existsSync as
|
|
29265
|
+
import { existsSync as existsSync44, mkdirSync as mkdirSync11, writeFileSync as writeFileSync11 } from "node:fs";
|
|
28641
29266
|
import { dirname as dirname20, join as join46 } from "node:path";
|
|
28642
29267
|
var REPO = "https://github.com/munhq/chat-recall";
|
|
28643
29268
|
function markerPath() {
|
|
@@ -28653,7 +29278,7 @@ function shouldAskForStar(resultCount) {
|
|
|
28653
29278
|
if (suppressed()) return false;
|
|
28654
29279
|
if (!process.stderr.isTTY) return false;
|
|
28655
29280
|
try {
|
|
28656
|
-
return !
|
|
29281
|
+
return !existsSync44(markerPath());
|
|
28657
29282
|
} catch {
|
|
28658
29283
|
return false;
|
|
28659
29284
|
}
|
|
@@ -28694,7 +29319,7 @@ function claudeHookConfigFiles() {
|
|
|
28694
29319
|
const out = [];
|
|
28695
29320
|
const seen = /* @__PURE__ */ new Set();
|
|
28696
29321
|
for (const home of claudeHomeDirs()) {
|
|
28697
|
-
if (!
|
|
29322
|
+
if (!existsSync58(join62(home, "projects"))) continue;
|
|
28698
29323
|
const file = join62(home, "hooks.json");
|
|
28699
29324
|
let key2;
|
|
28700
29325
|
try {
|
|
@@ -29479,7 +30104,7 @@ memory.command("wake-up").description("Generate wake-up context (high-importance
|
|
|
29479
30104
|
try {
|
|
29480
30105
|
const identityFile = getIdentityFilePath();
|
|
29481
30106
|
let identity = "AI coding assistant";
|
|
29482
|
-
if (
|
|
30107
|
+
if (existsSync58(identityFile)) {
|
|
29483
30108
|
identity = readFileSync50(identityFile, "utf-8").trim();
|
|
29484
30109
|
}
|
|
29485
30110
|
const lines = [
|
|
@@ -29580,7 +30205,7 @@ program.command("feedback").argument("<message...>", "what you want to say \u201
|
|
|
29580
30205
|
}
|
|
29581
30206
|
});
|
|
29582
30207
|
program.command("doctor").description("Quick health check across login, server, credentials, hooks, MCP server, and codeindex").option("--purge-local", "Remove the legacy local index (cache.db + vector/KG files) left by pre-thin-collector versions \u2014 storage is server-side now. Requires login; keeps credentials, sync ledger, identity, and the audit log.").action(async (opts) => {
|
|
29583
|
-
const { existsSync:
|
|
30208
|
+
const { existsSync: existsSync59, readFileSync: readFileSync51, statSync: statSync47 } = await import("fs");
|
|
29584
30209
|
const { execSync: execSync6 } = await import("child_process");
|
|
29585
30210
|
const rows = [];
|
|
29586
30211
|
const note = (ok, label, detail) => rows.push({ ok, label, detail });
|
|
@@ -29644,7 +30269,7 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
29644
30269
|
}
|
|
29645
30270
|
}
|
|
29646
30271
|
const credFile = join62(getDataDir(), "credentials.json");
|
|
29647
|
-
if (!
|
|
30272
|
+
if (!existsSync59(credFile)) {
|
|
29648
30273
|
note(false, "Credentials file", `missing \u2014 run \`chat-recall login <server-url>\``);
|
|
29649
30274
|
} else {
|
|
29650
30275
|
try {
|
|
@@ -29659,13 +30284,13 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
29659
30284
|
for (const hooksJson of claudeHookConfigFiles()) {
|
|
29660
30285
|
const profile = basename27(dirname29(hooksJson));
|
|
29661
30286
|
const label = `Claude hooks (${profile})`;
|
|
29662
|
-
if (!
|
|
30287
|
+
if (!existsSync59(hooksJson)) {
|
|
29663
30288
|
note(false, label, `no ${hooksJson} \u2014 run \`chat-recall install-hooks\``);
|
|
29664
30289
|
continue;
|
|
29665
30290
|
}
|
|
29666
30291
|
try {
|
|
29667
30292
|
const readHooks = (file) => {
|
|
29668
|
-
if (!
|
|
30293
|
+
if (!existsSync59(file)) return {};
|
|
29669
30294
|
try {
|
|
29670
30295
|
return JSON.parse(readFileSync51(file, "utf-8")).hooks || {};
|
|
29671
30296
|
} catch {
|
|
@@ -29708,9 +30333,9 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
29708
30333
|
try {
|
|
29709
30334
|
const reg = await Promise.resolve().then(() => (init_guard_registration(), guard_registration_exports));
|
|
29710
30335
|
for (const target2 of reg.guardTargets()) {
|
|
29711
|
-
if (!
|
|
30336
|
+
if (!existsSync59(target2.homeDir)) continue;
|
|
29712
30337
|
const label = `Decision guard \u2014 ${target2.label}`;
|
|
29713
|
-
if (!
|
|
30338
|
+
if (!existsSync59(target2.configPath)) {
|
|
29714
30339
|
note(false, label, `not registered \u2014 run \`chat-recall install-hooks\``);
|
|
29715
30340
|
continue;
|
|
29716
30341
|
}
|
|
@@ -29735,7 +30360,7 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
29735
30360
|
const want = bundledSkillNames2().length;
|
|
29736
30361
|
for (const t of skillTargets2()) {
|
|
29737
30362
|
if (!t.available) continue;
|
|
29738
|
-
const have = want === 0 ? 0 : bundledSkillNames2().filter((n) =>
|
|
30363
|
+
const have = want === 0 ? 0 : bundledSkillNames2().filter((n) => existsSync59(join62(t.dir, n, ".chat-recall-managed"))).length;
|
|
29739
30364
|
note(
|
|
29740
30365
|
have === want,
|
|
29741
30366
|
`Skills \u2014 ${t.label}`,
|
|
@@ -29817,7 +30442,7 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
29817
30442
|
join62(dataDir, "index", "knowledge_graph.db"),
|
|
29818
30443
|
join62(dataDir, "index", "metadata.db")
|
|
29819
30444
|
];
|
|
29820
|
-
const legacyPresent = legacyPaths.filter((p) =>
|
|
30445
|
+
const legacyPresent = legacyPaths.filter((p) => existsSync59(p));
|
|
29821
30446
|
if (opts.purgeLocal) {
|
|
29822
30447
|
if (!target) {
|
|
29823
30448
|
note(false, "Purge legacy index", "refused \u2014 log in and `chat-recall sync` first, so your history is on the server before removing local copies");
|
|
@@ -30462,10 +31087,10 @@ tasks.command("pull [dir]").description("Write TEAM_TASKS.md for your tasks in t
|
|
|
30462
31087
|
try {
|
|
30463
31088
|
const { resolveProjectId: resolveProjectId2 } = await Promise.resolve().then(() => (init_project_resolver(), project_resolver_exports));
|
|
30464
31089
|
const { renderTeamTasksMd: renderTeamTasksMd2, parseTeamTasksFile: parseTeamTasksFile2 } = await Promise.resolve().then(() => (init_project_tasks(), project_tasks_exports));
|
|
30465
|
-
const { writeFileSync: writeFileSync24, readFileSync: readFileSync51, existsSync:
|
|
31090
|
+
const { writeFileSync: writeFileSync24, readFileSync: readFileSync51, existsSync: existsSync59 } = await import("node:fs");
|
|
30466
31091
|
const { join: join63 } = await import("node:path");
|
|
30467
31092
|
const file = join63(cwd, "TEAM_TASKS.md");
|
|
30468
|
-
if (!opts.force &&
|
|
31093
|
+
if (!opts.force && existsSync59(file) && parseTeamTasksFile2(readFileSync51(file, "utf8")).length > 0) {
|
|
30469
31094
|
console.error(chalk2.red("TEAM_TASKS.md has unpushed edits."), "Run", chalk2.bold("chat-recall tasks push"), "first, or", chalk2.bold("tasks pull --force"), "to discard.");
|
|
30470
31095
|
process.exit(1);
|
|
30471
31096
|
}
|
|
@@ -30484,10 +31109,10 @@ tasks.command("push [dir]").description("Push TEAM_TASKS.md status edits back to
|
|
|
30484
31109
|
const cwd = dir || process.cwd();
|
|
30485
31110
|
try {
|
|
30486
31111
|
const { parseTeamTasksFile: parseTeamTasksFile2 } = await Promise.resolve().then(() => (init_project_tasks(), project_tasks_exports));
|
|
30487
|
-
const { readFileSync: readFileSync51, existsSync:
|
|
31112
|
+
const { readFileSync: readFileSync51, existsSync: existsSync59 } = await import("node:fs");
|
|
30488
31113
|
const { join: join63 } = await import("node:path");
|
|
30489
31114
|
const file = join63(cwd, "TEAM_TASKS.md");
|
|
30490
|
-
if (!
|
|
31115
|
+
if (!existsSync59(file)) {
|
|
30491
31116
|
console.error(chalk2.red("no TEAM_TASKS.md here \u2014"), "run", chalk2.bold("chat-recall tasks pull"), "first");
|
|
30492
31117
|
process.exit(1);
|
|
30493
31118
|
}
|
|
@@ -30974,7 +31599,7 @@ program.command("task-hook").description("Move a board card when a prompt or a c
|
|
|
30974
31599
|
}
|
|
30975
31600
|
});
|
|
30976
31601
|
program.command("install-hooks").description("Install Claude Code hooks (Stop + PreCompact + UserPromptSubmit + SessionEnd + SessionStart) into every Claude profile").option("--uninstall", "Remove hooks instead of installing them").option("--no-resume-hint", "Don't install the UserPromptSubmit resume-hint hook").option("--no-escalate", "Don't install the SessionEnd learnings-escalation hook").option("--no-wakeup", "Don't install the SessionStart wake-up hook").option("--no-guard", "Don't install the PreToolUse decision guard").option("--no-task-board", "Don't install the hooks that claim and close board cards").action(async (opts) => {
|
|
30977
|
-
const { mkdirSync: mkdirSync23, copyFileSync: copyFileSync4, chmodSync: chmodSync5, existsSync:
|
|
31602
|
+
const { mkdirSync: mkdirSync23, copyFileSync: copyFileSync4, chmodSync: chmodSync5, existsSync: existsSync59, readFileSync: readFileSync51, writeFileSync: writeFileSync24, statSync: statSync47, unlinkSync: unlinkSync4 } = await import("fs");
|
|
30978
31603
|
const { fileURLToPath: fileURLToPath6 } = await import("url");
|
|
30979
31604
|
const { boardHookEntries: boardHookEntries2, isBoardHookEntry: isBoardHookEntry2, registerBoardHooks: registerBoardHooks2, resolveCliEntry: resolveCliEntry2 } = await Promise.resolve().then(() => (init_board_hooks(), board_hooks_exports));
|
|
30980
31605
|
const here = fileURLToPath6(new URL(".", import.meta.url));
|
|
@@ -30987,7 +31612,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
30987
31612
|
// freshly added script is only at the root until that build runs.
|
|
30988
31613
|
join62(here, "..", "..", "..", "hooks", name)
|
|
30989
31614
|
];
|
|
30990
|
-
return candidates2.find((p) =>
|
|
31615
|
+
return candidates2.find((p) => existsSync59(p));
|
|
30991
31616
|
};
|
|
30992
31617
|
const sourceSaveHook = findHook("chat_recall_save_hook.sh");
|
|
30993
31618
|
const sourceGuardHook = findHook("chat_recall_guard_hook.sh");
|
|
@@ -31006,7 +31631,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
31006
31631
|
const installedWakeupHook = join62(hooksDir, "chat_recall_wakeup_hook.sh");
|
|
31007
31632
|
const wakeupWiredInSettings = (home) => {
|
|
31008
31633
|
const settings2 = join62(home, "settings.json");
|
|
31009
|
-
if (!
|
|
31634
|
+
if (!existsSync59(settings2)) return false;
|
|
31010
31635
|
try {
|
|
31011
31636
|
const cfg = JSON.parse(readFileSync51(settings2, "utf-8"));
|
|
31012
31637
|
const arr = Array.isArray(cfg.hooks?.SessionStart) ? cfg.hooks.SessionStart : [];
|
|
@@ -31017,7 +31642,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
31017
31642
|
};
|
|
31018
31643
|
const hookConfigFiles = claudeHookConfigFiles();
|
|
31019
31644
|
const readHookConfig = (file) => {
|
|
31020
|
-
if (!
|
|
31645
|
+
if (!existsSync59(file)) return { hooks: {} };
|
|
31021
31646
|
try {
|
|
31022
31647
|
const c = JSON.parse(readFileSync51(file, "utf-8"));
|
|
31023
31648
|
if (!c.hooks || typeof c.hooks !== "object") c.hooks = {};
|
|
@@ -31034,7 +31659,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
31034
31659
|
};
|
|
31035
31660
|
const HOOK_EVENTS = ["Stop", "PreCompact", "UserPromptSubmit", "SessionEnd", "SessionStart", "PreToolUse"];
|
|
31036
31661
|
const readJson4 = (file) => {
|
|
31037
|
-
if (!
|
|
31662
|
+
if (!existsSync59(file)) return {};
|
|
31038
31663
|
try {
|
|
31039
31664
|
return JSON.parse(readFileSync51(file, "utf-8"));
|
|
31040
31665
|
} catch {
|
|
@@ -31045,7 +31670,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
31045
31670
|
const reg = await Promise.resolve().then(() => (init_guard_registration(), guard_registration_exports));
|
|
31046
31671
|
const notes = [];
|
|
31047
31672
|
for (const target of reg.guardTargets()) {
|
|
31048
|
-
if (!
|
|
31673
|
+
if (!existsSync59(target.homeDir)) continue;
|
|
31049
31674
|
const wrapper = join62(hooksDir, reg.guardWrapperName(target.tool));
|
|
31050
31675
|
writeFileSync24(wrapper, reg.guardWrapperSource(target.tool, hookPath));
|
|
31051
31676
|
chmodSync5(wrapper, 493);
|
|
@@ -31066,7 +31691,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
31066
31691
|
const reg = await Promise.resolve().then(() => (init_guard_registration(), guard_registration_exports));
|
|
31067
31692
|
let removed = 0;
|
|
31068
31693
|
for (const target of reg.guardTargets()) {
|
|
31069
|
-
if (!
|
|
31694
|
+
if (!existsSync59(target.configPath)) continue;
|
|
31070
31695
|
if (target.tool === "opencode") {
|
|
31071
31696
|
const body2 = readFileSync51(target.configPath, "utf-8");
|
|
31072
31697
|
if (!body2.includes("chat-recall install-hooks")) continue;
|
|
@@ -31094,7 +31719,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
31094
31719
|
if (filtered.length) config2.hooks[event] = filtered;
|
|
31095
31720
|
else delete config2.hooks[event];
|
|
31096
31721
|
}
|
|
31097
|
-
if (removed === 0 && !
|
|
31722
|
+
if (removed === 0 && !existsSync59(hooksJson)) continue;
|
|
31098
31723
|
writeFileSync24(hooksJson, JSON.stringify(config2, null, 2) + "\n");
|
|
31099
31724
|
total += removed;
|
|
31100
31725
|
console.log(chalk2.green(`\u2713 Removed ${removed} chat-recall hook entr${removed === 1 ? "y" : "ies"} from ${hooksJson}`));
|
|
@@ -31669,8 +32294,8 @@ exclude.command("project <path>").description("Exclude a project path from synci
|
|
|
31669
32294
|
saveSettings2(s);
|
|
31670
32295
|
console.log(chalk2.green(`\u2713 Excluded ${abs}`) + chalk2.dim(" \u2014 takes effect next sync; already-synced rows stay until deleted."));
|
|
31671
32296
|
});
|
|
31672
|
-
exclude.command("tool <tool>").description("Exclude an AI tool entirely (claude | gemini | codex | opencode | agy | cursor)").action(async (tool) => {
|
|
31673
|
-
const valid = ["claude", "gemini", "codex", "opencode", "agy", "cursor"];
|
|
32297
|
+
exclude.command("tool <tool>").description("Exclude an AI tool entirely (claude | gemini | codex | opencode | agy | cursor | hermes)").action(async (tool) => {
|
|
32298
|
+
const valid = ["claude", "gemini", "codex", "opencode", "agy", "cursor", "hermes"];
|
|
31674
32299
|
if (!valid.includes(tool)) {
|
|
31675
32300
|
console.error(chalk2.red(`Unknown tool '${tool}'.`) + chalk2.dim(` Use one of: ${valid.join(" | ")}`));
|
|
31676
32301
|
process.exit(1);
|