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/watch.js
CHANGED
|
@@ -152,6 +152,8 @@ function declaredOrigin(value) {
|
|
|
152
152
|
function userRecordOrigin(obj, text) {
|
|
153
153
|
if (obj.isSidechain === true)
|
|
154
154
|
return "subagent";
|
|
155
|
+
if (obj.isCompactSummary === true)
|
|
156
|
+
return "compact-summary";
|
|
155
157
|
const declared = declaredOrigin(obj.origin);
|
|
156
158
|
if (declared && declared !== "human")
|
|
157
159
|
return declared;
|
|
@@ -4816,6 +4818,7 @@ function defaultSourcesEnabled() {
|
|
|
4816
4818
|
commands: true
|
|
4817
4819
|
},
|
|
4818
4820
|
cursor: { sessions: true, skills: true, agents: true, commands: true },
|
|
4821
|
+
hermes: { sessions: true },
|
|
4819
4822
|
shared: { skills: true },
|
|
4820
4823
|
common: { mcps: true, agentMd: true }
|
|
4821
4824
|
};
|
|
@@ -4892,6 +4895,7 @@ function mergeSources(base3, partial) {
|
|
|
4892
4895
|
codex: { ...base3.enabled.codex, ...partial.enabled?.codex ?? {} },
|
|
4893
4896
|
agy: { ...base3.enabled.agy, ...inherited, ...partial.enabled?.agy ?? {} },
|
|
4894
4897
|
cursor: { ...base3.enabled.cursor, ...partial.enabled?.cursor ?? {} },
|
|
4898
|
+
hermes: { ...base3.enabled.hermes, ...partial.enabled?.hermes ?? {} },
|
|
4895
4899
|
shared: { ...base3.enabled.shared, ...partial.enabled?.shared ?? {} },
|
|
4896
4900
|
common: { ...base3.enabled.common, ...partial.enabled?.common ?? {} }
|
|
4897
4901
|
};
|
|
@@ -4903,6 +4907,7 @@ function mergeSources(base3, partial) {
|
|
|
4903
4907
|
agyHome: partial.agyHome ?? base3.agyHome,
|
|
4904
4908
|
cursorHome: partial.cursorHome ?? base3.cursorHome,
|
|
4905
4909
|
cursorIdeHome: partial.cursorIdeHome ?? base3.cursorIdeHome,
|
|
4910
|
+
hermesHome: partial.hermesHome ?? base3.hermesHome,
|
|
4906
4911
|
extraClaudeHomes: partial.extraClaudeHomes ?? base3.extraClaudeHomes,
|
|
4907
4912
|
approvedHomes: partial.approvedHomes ?? base3.approvedHomes,
|
|
4908
4913
|
declinedHomes: partial.declinedHomes ?? base3.declinedHomes,
|
|
@@ -5200,6 +5205,13 @@ function grandfatherLegacyHomes() {
|
|
|
5200
5205
|
}
|
|
5201
5206
|
return { seeded };
|
|
5202
5207
|
}
|
|
5208
|
+
function defaultHermesHome() {
|
|
5209
|
+
if (process.platform === "win32") {
|
|
5210
|
+
const local = process.env.LOCALAPPDATA?.trim() || join3(homedir2(), "AppData", "Local");
|
|
5211
|
+
return join3(local, "hermes");
|
|
5212
|
+
}
|
|
5213
|
+
return join3(homedir2(), ".hermes");
|
|
5214
|
+
}
|
|
5203
5215
|
function primaryHomes() {
|
|
5204
5216
|
const home = homedir2();
|
|
5205
5217
|
const env = process.env;
|
|
@@ -5216,7 +5228,8 @@ function primaryHomes() {
|
|
|
5216
5228
|
env.CHAT_RECALL_CODEX_HOME || s?.codexHome || join3(home, ".codex"),
|
|
5217
5229
|
env.CHAT_RECALL_AGY_HOME || s?.agyHome || join3(home, ".gemini", "antigravity-cli"),
|
|
5218
5230
|
env.CHAT_RECALL_CURSOR_HOME || s?.cursorHome || join3(home, ".cursor"),
|
|
5219
|
-
dirOf(opencodeDb)
|
|
5231
|
+
dirOf(opencodeDb),
|
|
5232
|
+
env.CHAT_RECALL_HERMES_HOME || s?.hermesHome || env.HERMES_HOME?.trim() || defaultHermesHome()
|
|
5220
5233
|
];
|
|
5221
5234
|
return candidates2.map(normalizeHomePath);
|
|
5222
5235
|
}
|
|
@@ -5326,6 +5339,9 @@ function geminiHomeDir() {
|
|
|
5326
5339
|
function opencodeDbPath() {
|
|
5327
5340
|
return process.env.CHAT_RECALL_OPENCODE_DB || sources().opencodeDbPath || join4(homedir3(), ".local", "share", "opencode", "opencode.db");
|
|
5328
5341
|
}
|
|
5342
|
+
function hermesHomeDir() {
|
|
5343
|
+
return process.env.CHAT_RECALL_HERMES_HOME || sources().hermesHome || process.env.HERMES_HOME?.trim() || defaultHermesHome();
|
|
5344
|
+
}
|
|
5329
5345
|
function codexHomeDir() {
|
|
5330
5346
|
return process.env.CHAT_RECALL_CODEX_HOME || sources().codexHome || join4(homedir3(), ".codex");
|
|
5331
5347
|
}
|
|
@@ -5427,6 +5443,22 @@ function opencodeDbPaths(opts = {}) {
|
|
|
5427
5443
|
dbs.push(primary);
|
|
5428
5444
|
return applyExclusions(dbs, opts.includeExcluded);
|
|
5429
5445
|
}
|
|
5446
|
+
function hermesDbPaths(opts = {}) {
|
|
5447
|
+
const root = hermesHomeDir();
|
|
5448
|
+
const dbs = [join4(root, "state.db")];
|
|
5449
|
+
try {
|
|
5450
|
+
const profiles = join4(root, "profiles");
|
|
5451
|
+
for (const entry of readdirSync3(profiles, { withFileTypes: true })) {
|
|
5452
|
+
if (!entry.isDirectory())
|
|
5453
|
+
continue;
|
|
5454
|
+
const p = join4(profiles, entry.name, "state.db");
|
|
5455
|
+
if (existsSync4(p))
|
|
5456
|
+
dbs.push(p);
|
|
5457
|
+
}
|
|
5458
|
+
} catch {
|
|
5459
|
+
}
|
|
5460
|
+
return applyExclusions(dbs, opts.includeExcluded);
|
|
5461
|
+
}
|
|
5430
5462
|
var sources, _sourceExclusionFilter;
|
|
5431
5463
|
var init_tool_paths = __esm({
|
|
5432
5464
|
"../engine/dist/core/tool-paths.js"() {
|
|
@@ -6405,7 +6437,7 @@ function canonicalEventsToMessages(events) {
|
|
|
6405
6437
|
switch (e.kind) {
|
|
6406
6438
|
case "user":
|
|
6407
6439
|
cur = null;
|
|
6408
|
-
messages.push({ line: e.line, role: "user", content: e.text ?? "", timestamp: e.tsIso });
|
|
6440
|
+
messages.push({ line: e.line, role: "user", content: e.text ?? "", timestamp: e.tsIso, ...e.origin ? { origin: e.origin } : {} });
|
|
6409
6441
|
break;
|
|
6410
6442
|
case "assistant_text":
|
|
6411
6443
|
cur = { line: e.line, role: "assistant", content: e.text ?? "", timestamp: e.tsIso };
|
|
@@ -8082,6 +8114,71 @@ function readTailFromOffset(path, offset, maxBytes = TAIL_READ_MAX_BYTES) {
|
|
|
8082
8114
|
}
|
|
8083
8115
|
}
|
|
8084
8116
|
}
|
|
8117
|
+
function readSourcesFromOffset(paths, offset, maxBytes = TAIL_READ_MAX_BYTES) {
|
|
8118
|
+
let start = 0;
|
|
8119
|
+
let linesBefore = 0;
|
|
8120
|
+
for (let i = 0; i < paths.length; i++) {
|
|
8121
|
+
const path = paths[i];
|
|
8122
|
+
let size = 0;
|
|
8123
|
+
try {
|
|
8124
|
+
size = statSync6(path).size;
|
|
8125
|
+
} catch {
|
|
8126
|
+
size = 0;
|
|
8127
|
+
}
|
|
8128
|
+
const last = i === paths.length - 1;
|
|
8129
|
+
if (!last && offset >= start + size) {
|
|
8130
|
+
const lines = linesBeforeOffset(path, size);
|
|
8131
|
+
if (lines === void 0)
|
|
8132
|
+
return { text: "", newOffset: offset };
|
|
8133
|
+
linesBefore += lines + (size > 0 && !endsWithNewline(path, size) ? 1 : 0);
|
|
8134
|
+
start += size;
|
|
8135
|
+
continue;
|
|
8136
|
+
}
|
|
8137
|
+
const local = offset - start;
|
|
8138
|
+
const read = readTailFromOffset(path, local, maxBytes);
|
|
8139
|
+
const shift = (r) => ({
|
|
8140
|
+
...r,
|
|
8141
|
+
newOffset: start + r.newOffset,
|
|
8142
|
+
...r.baseLine !== void 0 ? { baseLine: linesBefore + r.baseLine } : {}
|
|
8143
|
+
});
|
|
8144
|
+
if (last || read.newOffset > local || local >= size)
|
|
8145
|
+
return shift(read);
|
|
8146
|
+
if (size - local > maxBytes)
|
|
8147
|
+
return { text: "", newOffset: start + size, skippedBytes: size - local };
|
|
8148
|
+
let fd = null;
|
|
8149
|
+
try {
|
|
8150
|
+
fd = openSync5(path, "r");
|
|
8151
|
+
const text = readAt(fd, local, size - local).toString("utf-8");
|
|
8152
|
+
return shift({ text, newOffset: size, baseLine: linesBeforeOffset(path, local) });
|
|
8153
|
+
} catch {
|
|
8154
|
+
return { text: "", newOffset: offset };
|
|
8155
|
+
} finally {
|
|
8156
|
+
if (fd !== null) {
|
|
8157
|
+
try {
|
|
8158
|
+
closeSync5(fd);
|
|
8159
|
+
} catch {
|
|
8160
|
+
}
|
|
8161
|
+
}
|
|
8162
|
+
}
|
|
8163
|
+
}
|
|
8164
|
+
return { text: "", newOffset: offset };
|
|
8165
|
+
}
|
|
8166
|
+
function endsWithNewline(path, size) {
|
|
8167
|
+
let fd = null;
|
|
8168
|
+
try {
|
|
8169
|
+
fd = openSync5(path, "r");
|
|
8170
|
+
return readAt(fd, size - 1, 1)[0] === 10;
|
|
8171
|
+
} catch {
|
|
8172
|
+
return true;
|
|
8173
|
+
} finally {
|
|
8174
|
+
if (fd !== null) {
|
|
8175
|
+
try {
|
|
8176
|
+
closeSync5(fd);
|
|
8177
|
+
} catch {
|
|
8178
|
+
}
|
|
8179
|
+
}
|
|
8180
|
+
}
|
|
8181
|
+
}
|
|
8085
8182
|
function findNewline(fd, from, size) {
|
|
8086
8183
|
const block = Buffer.allocUnsafe(SKIP_SCAN_BYTES);
|
|
8087
8184
|
let pos = from;
|
|
@@ -8998,27 +9095,45 @@ var init_claude2 = __esm({
|
|
|
8998
9095
|
/**
|
|
8999
9096
|
* True when this session exists in MORE THAN ONE home.
|
|
9000
9097
|
*
|
|
9001
|
-
* Such a session cannot be tail-appended: `fileSize()` is the SUM across
|
|
9002
|
-
* copies while a byte offset addresses ONE file, so the two disagree by
|
|
9003
|
-
* construction and the "tail" is either empty or the wrong bytes. The caller
|
|
9004
|
-
* uses this to force a FULL sync, which ships the unioned container and is
|
|
9005
|
-
* correct regardless of how the halves are arranged.
|
|
9006
|
-
*
|
|
9007
9098
|
* Measured on ec05f266: ~/.claude 1715 records, ~/.claude-work 205 records,
|
|
9008
|
-
* zero overlap.
|
|
9009
|
-
*
|
|
9099
|
+
* zero overlap. `fileSize()` is the sum across the copies, and
|
|
9100
|
+
* `readFromOffset()` reads them joined end to end, primary first.
|
|
9010
9101
|
*/
|
|
9011
9102
|
spansMultipleSources(prefixedId) {
|
|
9012
9103
|
return findSessionFiles(this.toRawId(prefixedId)).length > 1;
|
|
9013
9104
|
}
|
|
9105
|
+
/**
|
|
9106
|
+
* The copies before the last one, each with its size. Claude Code writes to
|
|
9107
|
+
* the home of the profile that runs the session, so the live copy can grow,
|
|
9108
|
+
* appear, vanish or merge back into the primary. Each of those moves bytes
|
|
9109
|
+
* under an offset into the joined copies; this key changes with all of them.
|
|
9110
|
+
*/
|
|
9111
|
+
sourceLayout(prefixedId) {
|
|
9112
|
+
const copies = findSessionFiles(this.toRawId(prefixedId));
|
|
9113
|
+
if (copies.length < 2)
|
|
9114
|
+
return "";
|
|
9115
|
+
return copies.slice(0, -1).map((c) => {
|
|
9116
|
+
let size = -1;
|
|
9117
|
+
try {
|
|
9118
|
+
size = statSync7(c.path).size;
|
|
9119
|
+
} catch {
|
|
9120
|
+
}
|
|
9121
|
+
return `${c.path}:${size}`;
|
|
9122
|
+
}).join("|");
|
|
9123
|
+
}
|
|
9124
|
+
/**
|
|
9125
|
+
* Session 8de13d0a had 31 MB in ~/.claude and 2 MB in ~/.claude-work. Over
|
|
9126
|
+
* the 24 MB build ceiling a sync ships the transcript in chunks read here,
|
|
9127
|
+
* and this returned no text for a session in two homes. Each sync shipped
|
|
9128
|
+
* nothing, and the server stayed three hours behind.
|
|
9129
|
+
*/
|
|
9014
9130
|
async readFromOffset(prefixedId, offset, maxBytes) {
|
|
9015
|
-
const
|
|
9016
|
-
const copies = findSessionFiles(rawId);
|
|
9131
|
+
const copies = findSessionFiles(this.toRawId(prefixedId));
|
|
9017
9132
|
if (copies.length === 0)
|
|
9018
9133
|
return { text: "", newOffset: offset };
|
|
9019
|
-
if (copies.length
|
|
9020
|
-
return
|
|
9021
|
-
return
|
|
9134
|
+
if (copies.length === 1)
|
|
9135
|
+
return readTailFromOffset(copies[0].path, offset, maxBytes);
|
|
9136
|
+
return readSourcesFromOffset(copies.map((c) => c.path), offset, maxBytes);
|
|
9022
9137
|
}
|
|
9023
9138
|
};
|
|
9024
9139
|
claudeBackend = new ClaudeBackend();
|
|
@@ -12077,6 +12192,473 @@ var init_cursor = __esm({
|
|
|
12077
12192
|
}
|
|
12078
12193
|
});
|
|
12079
12194
|
|
|
12195
|
+
// ../engine/dist/core/backends/hermes.js
|
|
12196
|
+
import { existsSync as existsSync16 } from "fs";
|
|
12197
|
+
function firstUserPrompt(db, sessionId) {
|
|
12198
|
+
try {
|
|
12199
|
+
const row = db.prepare(`
|
|
12200
|
+
SELECT substr(content, 1, 400) AS text FROM messages
|
|
12201
|
+
WHERE session_id = ? AND role = 'user' AND active = 1 AND _compressed_summary = 0
|
|
12202
|
+
AND (display_kind IS NULL OR display_kind = 'steer')
|
|
12203
|
+
AND length(trim(content)) > 0
|
|
12204
|
+
ORDER BY id LIMIT 1
|
|
12205
|
+
`).get(sessionId);
|
|
12206
|
+
return row?.text ? flatString(row.text.slice(0, 200)) : "";
|
|
12207
|
+
} catch {
|
|
12208
|
+
return "";
|
|
12209
|
+
}
|
|
12210
|
+
}
|
|
12211
|
+
function messageRowsToEvents(rows) {
|
|
12212
|
+
const events = [];
|
|
12213
|
+
let line = 0;
|
|
12214
|
+
for (const r of rows) {
|
|
12215
|
+
line++;
|
|
12216
|
+
if (r.active === 0)
|
|
12217
|
+
continue;
|
|
12218
|
+
if (r.display_kind === "failed_turn" || r.display_kind === "hidden")
|
|
12219
|
+
continue;
|
|
12220
|
+
const ts = Math.round((r.timestamp || 0) * 1e3);
|
|
12221
|
+
const tsIso = ts ? new Date(ts).toISOString() : void 0;
|
|
12222
|
+
const text = (r.content ?? "").trim();
|
|
12223
|
+
if (r._compressed_summary === 1) {
|
|
12224
|
+
if (text)
|
|
12225
|
+
events.push({ kind: "summary", ts, tsIso, line, text });
|
|
12226
|
+
continue;
|
|
12227
|
+
}
|
|
12228
|
+
if (r.role === "user") {
|
|
12229
|
+
if (!text)
|
|
12230
|
+
continue;
|
|
12231
|
+
events.push({
|
|
12232
|
+
kind: "user",
|
|
12233
|
+
ts,
|
|
12234
|
+
tsIso,
|
|
12235
|
+
line,
|
|
12236
|
+
text,
|
|
12237
|
+
...r.display_kind === "process_complete" ? { origin: "task-notification" } : {}
|
|
12238
|
+
});
|
|
12239
|
+
continue;
|
|
12240
|
+
}
|
|
12241
|
+
if (r.role === "assistant") {
|
|
12242
|
+
if (text)
|
|
12243
|
+
events.push({ kind: "assistant_text", ts, tsIso, line, text });
|
|
12244
|
+
for (const call2 of parseToolCalls(r.tool_calls)) {
|
|
12245
|
+
const toolName = call2.function?.name ?? "";
|
|
12246
|
+
const toolInput = parseArguments(call2.function?.arguments);
|
|
12247
|
+
const command = toolName === "terminal" && typeof toolInput?.command === "string" ? toolInput.command : void 0;
|
|
12248
|
+
events.push({
|
|
12249
|
+
kind: "tool_use",
|
|
12250
|
+
ts,
|
|
12251
|
+
tsIso,
|
|
12252
|
+
line,
|
|
12253
|
+
toolName,
|
|
12254
|
+
toolUseId: call2.id || call2.call_id || `${r.id}:${toolName}`,
|
|
12255
|
+
toolInput,
|
|
12256
|
+
...command ? { command } : {}
|
|
12257
|
+
});
|
|
12258
|
+
}
|
|
12259
|
+
continue;
|
|
12260
|
+
}
|
|
12261
|
+
if (r.role === "tool") {
|
|
12262
|
+
const body = r.content ?? "";
|
|
12263
|
+
const { exitCode, isError } = toolResultStatus(body);
|
|
12264
|
+
events.push({
|
|
12265
|
+
kind: "tool_result",
|
|
12266
|
+
ts,
|
|
12267
|
+
tsIso,
|
|
12268
|
+
line,
|
|
12269
|
+
toolUseId: r.tool_call_id ?? void 0,
|
|
12270
|
+
toolName: r.tool_name ?? void 0,
|
|
12271
|
+
resultBody: body,
|
|
12272
|
+
resultIsError: isError,
|
|
12273
|
+
...exitCode !== void 0 ? { resultExitCode: exitCode } : {},
|
|
12274
|
+
resultBytes: Buffer.byteLength(body)
|
|
12275
|
+
});
|
|
12276
|
+
}
|
|
12277
|
+
}
|
|
12278
|
+
return events;
|
|
12279
|
+
}
|
|
12280
|
+
function parseToolCalls(json) {
|
|
12281
|
+
if (!json)
|
|
12282
|
+
return [];
|
|
12283
|
+
try {
|
|
12284
|
+
const calls = JSON.parse(json);
|
|
12285
|
+
return Array.isArray(calls) ? calls : [];
|
|
12286
|
+
} catch {
|
|
12287
|
+
return [];
|
|
12288
|
+
}
|
|
12289
|
+
}
|
|
12290
|
+
function parseArguments(args) {
|
|
12291
|
+
if (typeof args !== "string")
|
|
12292
|
+
return args ?? {};
|
|
12293
|
+
try {
|
|
12294
|
+
return JSON.parse(args);
|
|
12295
|
+
} catch {
|
|
12296
|
+
return { raw: args };
|
|
12297
|
+
}
|
|
12298
|
+
}
|
|
12299
|
+
function toolResultStatus(body) {
|
|
12300
|
+
if (!body.startsWith("{"))
|
|
12301
|
+
return { isError: false };
|
|
12302
|
+
try {
|
|
12303
|
+
const r = JSON.parse(body);
|
|
12304
|
+
const exitCode = typeof r.exit_code === "number" ? r.exit_code : void 0;
|
|
12305
|
+
const hasError = r.error !== void 0 && r.error !== null && r.error !== "";
|
|
12306
|
+
return { exitCode, isError: hasError || exitCode !== void 0 && exitCode !== 0 };
|
|
12307
|
+
} catch {
|
|
12308
|
+
return { isError: false };
|
|
12309
|
+
}
|
|
12310
|
+
}
|
|
12311
|
+
var PREFIX5, MESSAGE_COLUMNS, ARCHIVED_SESSION_COLUMNS, SESSION_MTIME_SQL, HermesBackend, hermesBackend;
|
|
12312
|
+
var init_hermes = __esm({
|
|
12313
|
+
"../engine/dist/core/backends/hermes.js"() {
|
|
12314
|
+
"use strict";
|
|
12315
|
+
init_sqlite_reader();
|
|
12316
|
+
init_tool_paths();
|
|
12317
|
+
init_session_outcome();
|
|
12318
|
+
init_session_git();
|
|
12319
|
+
init_generic_engine();
|
|
12320
|
+
init_flat_string();
|
|
12321
|
+
PREFIX5 = "hermes_";
|
|
12322
|
+
MESSAGE_COLUMNS = "id, role, content, tool_calls, tool_call_id, tool_name, timestamp, display_kind, active, _compressed_summary";
|
|
12323
|
+
ARCHIVED_SESSION_COLUMNS = [
|
|
12324
|
+
"id",
|
|
12325
|
+
"source",
|
|
12326
|
+
"title",
|
|
12327
|
+
"model",
|
|
12328
|
+
"cwd",
|
|
12329
|
+
"git_branch",
|
|
12330
|
+
"git_repo_root",
|
|
12331
|
+
"parent_session_id",
|
|
12332
|
+
"started_at",
|
|
12333
|
+
"ended_at",
|
|
12334
|
+
"end_reason",
|
|
12335
|
+
"message_count",
|
|
12336
|
+
"tool_call_count",
|
|
12337
|
+
"input_tokens",
|
|
12338
|
+
"output_tokens",
|
|
12339
|
+
"cache_read_tokens",
|
|
12340
|
+
"cache_write_tokens",
|
|
12341
|
+
"reasoning_tokens",
|
|
12342
|
+
"estimated_cost_usd",
|
|
12343
|
+
"actual_cost_usd"
|
|
12344
|
+
];
|
|
12345
|
+
SESSION_MTIME_SQL = `MAX(
|
|
12346
|
+
s.started_at,
|
|
12347
|
+
COALESCE(s.ended_at, 0),
|
|
12348
|
+
COALESCE(s.last_activity_at, 0),
|
|
12349
|
+
COALESCE((SELECT MAX(m.timestamp) FROM messages m WHERE m.session_id = s.id), 0)
|
|
12350
|
+
)`;
|
|
12351
|
+
HermesBackend = class {
|
|
12352
|
+
id = "hermes";
|
|
12353
|
+
idPrefix = PREFIX5;
|
|
12354
|
+
displayName = "Hermes";
|
|
12355
|
+
homeDir() {
|
|
12356
|
+
return hermesHomeDir();
|
|
12357
|
+
}
|
|
12358
|
+
/** Every Hermes database on this machine, the root profile first. */
|
|
12359
|
+
dbPaths() {
|
|
12360
|
+
return hermesDbPaths();
|
|
12361
|
+
}
|
|
12362
|
+
isAvailable() {
|
|
12363
|
+
return this.dbPaths().some((p) => existsSync16(p));
|
|
12364
|
+
}
|
|
12365
|
+
/** The database that holds this session. A session id is unique within a
|
|
12366
|
+
* database, and each named profile has its own. */
|
|
12367
|
+
dbPathFor(rawId) {
|
|
12368
|
+
const cached = this._dbForSession.get(rawId);
|
|
12369
|
+
if (cached)
|
|
12370
|
+
return cached;
|
|
12371
|
+
for (const path of this.dbPaths()) {
|
|
12372
|
+
const db = openSqliteReadonly(path);
|
|
12373
|
+
if (!db)
|
|
12374
|
+
continue;
|
|
12375
|
+
try {
|
|
12376
|
+
if (db.prepare("SELECT 1 AS ok FROM sessions WHERE id = ?").get(rawId)) {
|
|
12377
|
+
this._dbForSession.set(rawId, path);
|
|
12378
|
+
return path;
|
|
12379
|
+
}
|
|
12380
|
+
} catch {
|
|
12381
|
+
} finally {
|
|
12382
|
+
db.close();
|
|
12383
|
+
}
|
|
12384
|
+
}
|
|
12385
|
+
return null;
|
|
12386
|
+
}
|
|
12387
|
+
_dbForSession = /* @__PURE__ */ new Map();
|
|
12388
|
+
/** Tests, and anything that adds a profile mid-process. */
|
|
12389
|
+
_clearDbRouting() {
|
|
12390
|
+
this._dbForSession.clear();
|
|
12391
|
+
}
|
|
12392
|
+
// ── ID handling ────────────────────────────────────────────────
|
|
12393
|
+
matchesId(id) {
|
|
12394
|
+
return id.startsWith(PREFIX5);
|
|
12395
|
+
}
|
|
12396
|
+
toRawId(id) {
|
|
12397
|
+
return id.startsWith(PREFIX5) ? id.slice(PREFIX5.length) : id;
|
|
12398
|
+
}
|
|
12399
|
+
toPrefixedId(rawId) {
|
|
12400
|
+
return rawId.startsWith(PREFIX5) ? rawId : PREFIX5 + rawId;
|
|
12401
|
+
}
|
|
12402
|
+
// ── Location ───────────────────────────────────────────────────
|
|
12403
|
+
findSession(id) {
|
|
12404
|
+
const rawId = this.toRawId(id);
|
|
12405
|
+
const path = this.dbPathFor(rawId);
|
|
12406
|
+
if (!path)
|
|
12407
|
+
return null;
|
|
12408
|
+
const db = openSqliteReadonly(path);
|
|
12409
|
+
if (!db)
|
|
12410
|
+
return null;
|
|
12411
|
+
try {
|
|
12412
|
+
const row = db.prepare(`
|
|
12413
|
+
SELECT s.cwd, s.git_repo_root, ${SESSION_MTIME_SQL} AS mtime
|
|
12414
|
+
FROM sessions s WHERE s.id = ?
|
|
12415
|
+
`).get(rawId);
|
|
12416
|
+
if (!row)
|
|
12417
|
+
return null;
|
|
12418
|
+
return {
|
|
12419
|
+
path,
|
|
12420
|
+
format: "sqlite",
|
|
12421
|
+
projectDir: "",
|
|
12422
|
+
projectPath: row.git_repo_root || row.cwd || "",
|
|
12423
|
+
mtime: Math.round((row.mtime || 0) * 1e3)
|
|
12424
|
+
};
|
|
12425
|
+
} catch {
|
|
12426
|
+
return null;
|
|
12427
|
+
} finally {
|
|
12428
|
+
db.close();
|
|
12429
|
+
}
|
|
12430
|
+
}
|
|
12431
|
+
listSessions(opts = {}) {
|
|
12432
|
+
const byId = /* @__PURE__ */ new Map();
|
|
12433
|
+
for (const dbPath of this.dbPaths()) {
|
|
12434
|
+
if (!existsSync16(dbPath))
|
|
12435
|
+
continue;
|
|
12436
|
+
for (const ref of this.listSessionsInDb(dbPath, opts)) {
|
|
12437
|
+
const prior = byId.get(ref.rawId);
|
|
12438
|
+
if (!prior || ref.mtime > prior.mtime)
|
|
12439
|
+
byId.set(ref.rawId, ref);
|
|
12440
|
+
}
|
|
12441
|
+
}
|
|
12442
|
+
const all = [...byId.values()].sort((a, b) => b.mtime - a.mtime);
|
|
12443
|
+
return opts.limit ? all.slice(0, opts.limit) : all;
|
|
12444
|
+
}
|
|
12445
|
+
listSessionsInDb(dbPath, opts) {
|
|
12446
|
+
const cutoffSec = (opts.sinceMs ?? 0) / 1e3;
|
|
12447
|
+
const filter = opts.projectFilter?.toLowerCase();
|
|
12448
|
+
const db = openSqliteReadonly(dbPath);
|
|
12449
|
+
if (!db)
|
|
12450
|
+
return [];
|
|
12451
|
+
try {
|
|
12452
|
+
const rows = db.prepare(`
|
|
12453
|
+
SELECT * FROM (
|
|
12454
|
+
SELECT s.id, s.cwd, s.git_repo_root, s.started_at, s.message_count,
|
|
12455
|
+
${SESSION_MTIME_SQL} AS mtime
|
|
12456
|
+
FROM sessions s
|
|
12457
|
+
) WHERE mtime >= ? ORDER BY mtime DESC
|
|
12458
|
+
`).all(cutoffSec);
|
|
12459
|
+
const out = [];
|
|
12460
|
+
for (const row of rows) {
|
|
12461
|
+
const projectPath = row.git_repo_root || row.cwd || "";
|
|
12462
|
+
if (filter && !projectPath.toLowerCase().includes(filter))
|
|
12463
|
+
continue;
|
|
12464
|
+
const mtime = Math.round(row.mtime * 1e3);
|
|
12465
|
+
this._dbForSession.set(row.id, dbPath);
|
|
12466
|
+
out.push({
|
|
12467
|
+
toolId: "hermes",
|
|
12468
|
+
rawId: row.id,
|
|
12469
|
+
prefixedId: this.toPrefixedId(row.id),
|
|
12470
|
+
projectPath,
|
|
12471
|
+
projectDir: "",
|
|
12472
|
+
fullPath: dbPath,
|
|
12473
|
+
created: new Date(Math.round(row.started_at * 1e3)).toISOString(),
|
|
12474
|
+
modified: new Date(mtime).toISOString(),
|
|
12475
|
+
mtime,
|
|
12476
|
+
firstPrompt: opts.previews === false ? "" : firstUserPrompt(db, row.id),
|
|
12477
|
+
messageCount: opts.previews === false ? 0 : row.message_count ?? 0
|
|
12478
|
+
});
|
|
12479
|
+
if (opts.limit && out.length >= opts.limit)
|
|
12480
|
+
break;
|
|
12481
|
+
}
|
|
12482
|
+
return out;
|
|
12483
|
+
} catch {
|
|
12484
|
+
return [];
|
|
12485
|
+
} finally {
|
|
12486
|
+
db.close();
|
|
12487
|
+
}
|
|
12488
|
+
}
|
|
12489
|
+
/** Hermes writes a title for each session (a model-written one, or the
|
|
12490
|
+
* first prompt for a one-shot run). */
|
|
12491
|
+
getNativeTitle(rawId) {
|
|
12492
|
+
const path = this.dbPathFor(this.toRawId(rawId));
|
|
12493
|
+
if (!path)
|
|
12494
|
+
return null;
|
|
12495
|
+
const db = openSqliteReadonly(path);
|
|
12496
|
+
if (!db)
|
|
12497
|
+
return null;
|
|
12498
|
+
try {
|
|
12499
|
+
const row = db.prepare("SELECT title FROM sessions WHERE id = ?").get(this.toRawId(rawId));
|
|
12500
|
+
const t = row?.title?.trim();
|
|
12501
|
+
return t ? t.slice(0, 200) : null;
|
|
12502
|
+
} catch {
|
|
12503
|
+
return null;
|
|
12504
|
+
} finally {
|
|
12505
|
+
db.close();
|
|
12506
|
+
}
|
|
12507
|
+
}
|
|
12508
|
+
// ── Generic-engine inputs ───────────────────────────────────────
|
|
12509
|
+
fileToolMap = {
|
|
12510
|
+
write_file: "write",
|
|
12511
|
+
patch: "edit",
|
|
12512
|
+
read_file: "read"
|
|
12513
|
+
};
|
|
12514
|
+
/**
|
|
12515
|
+
* `write_file` carries `{ path, content }`. `patch` carries
|
|
12516
|
+
* `{ mode: 'replace', path, old_string, new_string }`; its other mode,
|
|
12517
|
+
* `patch`, is a multi-file V4A patch with no single before and after.
|
|
12518
|
+
*/
|
|
12519
|
+
extractEditDelta(toolName, input) {
|
|
12520
|
+
if (input == null || typeof input !== "object")
|
|
12521
|
+
return null;
|
|
12522
|
+
const inp = input;
|
|
12523
|
+
if (toolName === "write_file") {
|
|
12524
|
+
return { before: "", after: typeof inp.content === "string" ? inp.content : null };
|
|
12525
|
+
}
|
|
12526
|
+
if (toolName === "patch" && (inp.mode === void 0 || inp.mode === "replace")) {
|
|
12527
|
+
const before = typeof inp.old_string === "string" ? inp.old_string : null;
|
|
12528
|
+
const after = typeof inp.new_string === "string" ? inp.new_string : null;
|
|
12529
|
+
if (before === null && after === null)
|
|
12530
|
+
return null;
|
|
12531
|
+
return { before, after };
|
|
12532
|
+
}
|
|
12533
|
+
return null;
|
|
12534
|
+
}
|
|
12535
|
+
readEvents(rawId) {
|
|
12536
|
+
const id = this.toRawId(rawId);
|
|
12537
|
+
const path = this.dbPathFor(id);
|
|
12538
|
+
if (!path)
|
|
12539
|
+
return [];
|
|
12540
|
+
const db = openSqliteReadonly(path);
|
|
12541
|
+
if (!db)
|
|
12542
|
+
return [];
|
|
12543
|
+
try {
|
|
12544
|
+
const rows = db.prepare(`SELECT ${MESSAGE_COLUMNS} FROM messages WHERE session_id = ? ORDER BY id`).all(id);
|
|
12545
|
+
return messageRowsToEvents(rows);
|
|
12546
|
+
} catch {
|
|
12547
|
+
return [];
|
|
12548
|
+
} finally {
|
|
12549
|
+
db.close();
|
|
12550
|
+
}
|
|
12551
|
+
}
|
|
12552
|
+
/**
|
|
12553
|
+
* Events from the dump `exportRawSession` writes, for a session rebuilt from
|
|
12554
|
+
* the server's archive. The archive joins the lines of every dump it got, so
|
|
12555
|
+
* a row that changed (a rewind sets `active` to 0) is there more than once.
|
|
12556
|
+
* The last copy of each row id is the newest.
|
|
12557
|
+
*/
|
|
12558
|
+
readEventsFromText(text) {
|
|
12559
|
+
const rows = /* @__PURE__ */ new Map();
|
|
12560
|
+
for (const line of text.split("\n")) {
|
|
12561
|
+
if (!line.trim())
|
|
12562
|
+
continue;
|
|
12563
|
+
try {
|
|
12564
|
+
const rec = JSON.parse(line);
|
|
12565
|
+
if (rec.kind === "message" && rec.row) {
|
|
12566
|
+
rows.delete(rec.row.id);
|
|
12567
|
+
rows.set(rec.row.id, rec.row);
|
|
12568
|
+
}
|
|
12569
|
+
} catch {
|
|
12570
|
+
}
|
|
12571
|
+
}
|
|
12572
|
+
return messageRowsToEvents([...rows.values()].sort((a, b) => a.id - b.id));
|
|
12573
|
+
}
|
|
12574
|
+
// ── Per-session operations — all delegate to the generic engine ─
|
|
12575
|
+
extractTurns(id, opts = {}) {
|
|
12576
|
+
return extractTurnsFromEvents(this.toPrefixedId(id), this.readEvents(id), opts);
|
|
12577
|
+
}
|
|
12578
|
+
liveScanEdits(id) {
|
|
12579
|
+
const located = this.findSession(id);
|
|
12580
|
+
if (!located) {
|
|
12581
|
+
return { found: false, projectPath: "", projectDir: "", edits: [], fileMtime: 0, tool: "hermes" };
|
|
12582
|
+
}
|
|
12583
|
+
return liveScanEditsFromEvents(this.readEvents(id), this.fileToolMap, {
|
|
12584
|
+
sessionId: this.toPrefixedId(id),
|
|
12585
|
+
tool: "hermes",
|
|
12586
|
+
projectPath: located.projectPath,
|
|
12587
|
+
projectDir: located.projectDir,
|
|
12588
|
+
fileMtime: located.mtime,
|
|
12589
|
+
found: true
|
|
12590
|
+
});
|
|
12591
|
+
}
|
|
12592
|
+
replay(id) {
|
|
12593
|
+
const located = this.findSession(id);
|
|
12594
|
+
if (!located) {
|
|
12595
|
+
return { sessionId: this.toPrefixedId(id), found: false, projectPath: "", files: [], totalLinesAdded: 0, totalLinesRemoved: 0 };
|
|
12596
|
+
}
|
|
12597
|
+
return replayFromEvents(this.toPrefixedId(id), this.readEvents(id), this.fileToolMap, this.extractEditDelta.bind(this), {
|
|
12598
|
+
projectPath: located.projectPath,
|
|
12599
|
+
found: true
|
|
12600
|
+
});
|
|
12601
|
+
}
|
|
12602
|
+
computeOutcome(id, opts) {
|
|
12603
|
+
return computeOutcome(this.toPrefixedId(id), opts);
|
|
12604
|
+
}
|
|
12605
|
+
/** File edits since `sinceMs` across the sessions active since then. */
|
|
12606
|
+
collectRecentEdits(opts) {
|
|
12607
|
+
const refs = this.listSessions({ sinceMs: opts.sinceMs, projectFilter: opts.projectFilter, previews: false });
|
|
12608
|
+
const edits = [];
|
|
12609
|
+
for (const ref of opts.limitSessions ? refs.slice(0, opts.limitSessions) : refs) {
|
|
12610
|
+
for (const e of this.liveScanEdits(ref.rawId).edits) {
|
|
12611
|
+
if (e.ts >= opts.sinceMs)
|
|
12612
|
+
edits.push(e);
|
|
12613
|
+
}
|
|
12614
|
+
}
|
|
12615
|
+
return edits.sort((a, b) => b.ts - a.ts);
|
|
12616
|
+
}
|
|
12617
|
+
getCommits(id, files, startMs, endMs, bufferMinutes) {
|
|
12618
|
+
return getSessionCommits(this.toPrefixedId(id), files, startMs, endMs, bufferMinutes);
|
|
12619
|
+
}
|
|
12620
|
+
/**
|
|
12621
|
+
* The session row and its messages as JSONL, one row per line in id order.
|
|
12622
|
+
* Hermes rewrites and compacts its database, so the archive keeps the rows
|
|
12623
|
+
* as they were synced.
|
|
12624
|
+
*/
|
|
12625
|
+
exportRawSession(id) {
|
|
12626
|
+
const rawId = this.toRawId(id);
|
|
12627
|
+
const path = this.dbPathFor(rawId);
|
|
12628
|
+
if (!path)
|
|
12629
|
+
return null;
|
|
12630
|
+
const db = openSqliteReadonly(path);
|
|
12631
|
+
if (!db)
|
|
12632
|
+
return null;
|
|
12633
|
+
try {
|
|
12634
|
+
const have = new Set(db.prepare(`SELECT name FROM pragma_table_info('sessions')`).all().map((c) => c.name));
|
|
12635
|
+
const cols = ARCHIVED_SESSION_COLUMNS.filter((c) => have.has(c)).map((c) => `s.${c}`);
|
|
12636
|
+
const session = db.prepare(`
|
|
12637
|
+
SELECT ${[...cols, `${SESSION_MTIME_SQL} AS mtime`].join(", ")}
|
|
12638
|
+
FROM sessions s WHERE s.id = ?
|
|
12639
|
+
`).get(rawId);
|
|
12640
|
+
if (!session)
|
|
12641
|
+
return null;
|
|
12642
|
+
const rows = db.prepare(`SELECT ${MESSAGE_COLUMNS} FROM messages WHERE session_id = ? ORDER BY id`).all(rawId);
|
|
12643
|
+
const lines = [JSON.stringify({ kind: "session", row: session })];
|
|
12644
|
+
for (const r of rows)
|
|
12645
|
+
lines.push(JSON.stringify({ kind: "message", row: r }));
|
|
12646
|
+
return {
|
|
12647
|
+
tool: "hermes",
|
|
12648
|
+
mtime: Math.round(Number(session.mtime || 0) * 1e3),
|
|
12649
|
+
files: [{ name: `${rawId}.dump.jsonl`, bytes: Buffer.from(lines.join("\n") + "\n", "utf-8") }]
|
|
12650
|
+
};
|
|
12651
|
+
} catch {
|
|
12652
|
+
return null;
|
|
12653
|
+
} finally {
|
|
12654
|
+
db.close();
|
|
12655
|
+
}
|
|
12656
|
+
}
|
|
12657
|
+
};
|
|
12658
|
+
hermesBackend = new HermesBackend();
|
|
12659
|
+
}
|
|
12660
|
+
});
|
|
12661
|
+
|
|
12080
12662
|
// ../engine/dist/core/backends/index.js
|
|
12081
12663
|
var backends_exports = {};
|
|
12082
12664
|
__export(backends_exports, {
|
|
@@ -12084,6 +12666,7 @@ __export(backends_exports, {
|
|
|
12084
12666
|
ClaudeBackend: () => ClaudeBackend,
|
|
12085
12667
|
CodexBackend: () => CodexBackend,
|
|
12086
12668
|
CursorBackend: () => CursorBackend,
|
|
12669
|
+
HermesBackend: () => HermesBackend,
|
|
12087
12670
|
OpencodeBackend: () => OpencodeBackend,
|
|
12088
12671
|
agyBackend: () => agyBackend,
|
|
12089
12672
|
bootstrapBackends: () => bootstrapBackends,
|
|
@@ -12092,6 +12675,7 @@ __export(backends_exports, {
|
|
|
12092
12675
|
cursorBackend: () => cursorBackend,
|
|
12093
12676
|
getBackend: () => getBackend,
|
|
12094
12677
|
getBackendForId: () => getBackendForId,
|
|
12678
|
+
hermesBackend: () => hermesBackend,
|
|
12095
12679
|
listAllBackends: () => listAllBackends,
|
|
12096
12680
|
listAvailableBackends: () => listAvailableBackends,
|
|
12097
12681
|
opencodeBackend: () => opencodeBackend,
|
|
@@ -12104,6 +12688,7 @@ function bootstrapBackends() {
|
|
|
12104
12688
|
registerBackend(codexBackend);
|
|
12105
12689
|
registerBackend(agyBackend);
|
|
12106
12690
|
registerBackend(cursorBackend);
|
|
12691
|
+
registerBackend(hermesBackend);
|
|
12107
12692
|
}
|
|
12108
12693
|
var init_backends = __esm({
|
|
12109
12694
|
"../engine/dist/core/backends/index.js"() {
|
|
@@ -12114,6 +12699,7 @@ var init_backends = __esm({
|
|
|
12114
12699
|
init_codex2();
|
|
12115
12700
|
init_agy();
|
|
12116
12701
|
init_cursor();
|
|
12702
|
+
init_hermes();
|
|
12117
12703
|
init_tool_backend();
|
|
12118
12704
|
_setRegistryBootstrapper(bootstrapBackends);
|
|
12119
12705
|
}
|
|
@@ -12630,7 +13216,7 @@ var init_secret_redactor = __esm({
|
|
|
12630
13216
|
|
|
12631
13217
|
// ../engine/dist/core/source-discovery.js
|
|
12632
13218
|
import { createHash as createHash3 } from "crypto";
|
|
12633
|
-
import { existsSync as
|
|
13219
|
+
import { existsSync as existsSync17, readdirSync as readdirSync12, statSync as statSync14 } from "fs";
|
|
12634
13220
|
import { join as join18 } from "path";
|
|
12635
13221
|
function sourceId(path) {
|
|
12636
13222
|
return "src_" + createHash3("sha256").update(path).digest("hex").slice(0, 12);
|
|
@@ -12689,7 +13275,7 @@ function countTranscripts(root, tool) {
|
|
|
12689
13275
|
walk(root, 0);
|
|
12690
13276
|
return { sessions, newestMtime };
|
|
12691
13277
|
}
|
|
12692
|
-
function
|
|
13278
|
+
function countDbSessions(dbPath) {
|
|
12693
13279
|
try {
|
|
12694
13280
|
const st = statSync14(dbPath);
|
|
12695
13281
|
return { sessions: 0, newestMtime: st.mtimeMs };
|
|
@@ -12707,18 +13293,24 @@ function discoverSessionSources() {
|
|
|
12707
13293
|
];
|
|
12708
13294
|
for (const [tool, dirs] of dirTools) {
|
|
12709
13295
|
for (const [i, path] of dirs.entries()) {
|
|
12710
|
-
if (!
|
|
13296
|
+
if (!existsSync17(path))
|
|
12711
13297
|
continue;
|
|
12712
13298
|
const { sessions, newestMtime } = countTranscripts(path, tool);
|
|
12713
13299
|
out.push({ id: sourceId(path), tool, path, sessions, newestMtime, isPrimary: i === 0 });
|
|
12714
13300
|
}
|
|
12715
13301
|
}
|
|
12716
13302
|
for (const [i, path] of opencodeDbPaths({ includeExcluded: true }).entries()) {
|
|
12717
|
-
if (!
|
|
13303
|
+
if (!existsSync17(path))
|
|
12718
13304
|
continue;
|
|
12719
|
-
const { sessions, newestMtime } =
|
|
13305
|
+
const { sessions, newestMtime } = countDbSessions(path);
|
|
12720
13306
|
out.push({ id: sourceId(path), tool: "opencode", path, sessions, newestMtime, isPrimary: i === 0 });
|
|
12721
13307
|
}
|
|
13308
|
+
for (const [i, path] of hermesDbPaths({ includeExcluded: true }).entries()) {
|
|
13309
|
+
if (!existsSync17(path))
|
|
13310
|
+
continue;
|
|
13311
|
+
const { sessions, newestMtime } = countDbSessions(path);
|
|
13312
|
+
out.push({ id: sourceId(path), tool: "hermes", path, sessions, newestMtime, isPrimary: i === 0 });
|
|
13313
|
+
}
|
|
12722
13314
|
return out;
|
|
12723
13315
|
}
|
|
12724
13316
|
var excludedIds, SOURCE_ID_RE, MAX_DEPTH;
|
|
@@ -12734,7 +13326,7 @@ var init_source_discovery = __esm({
|
|
|
12734
13326
|
|
|
12735
13327
|
// ../engine/dist/core/home-discovery.js
|
|
12736
13328
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
12737
|
-
import { existsSync as
|
|
13329
|
+
import { existsSync as existsSync18, readdirSync as readdirSync13, readFileSync as readFileSync12, realpathSync as realpathSync2, statSync as statSync15 } from "fs";
|
|
12738
13330
|
import { homedir as homedir5, platform as osPlatform } from "os";
|
|
12739
13331
|
import { join as join19 } from "path";
|
|
12740
13332
|
function candidateRoots(plat = osPlatform(), env = process.env) {
|
|
@@ -12755,10 +13347,10 @@ function candidateRoots(plat = osPlatform(), env = process.env) {
|
|
|
12755
13347
|
add(env.XDG_CONFIG_HOME || join19(home, ".config"));
|
|
12756
13348
|
add(env.XDG_DATA_HOME || join19(home, ".local", "share"));
|
|
12757
13349
|
}
|
|
12758
|
-
return roots.filter((r) =>
|
|
13350
|
+
return roots.filter((r) => existsSync18(r));
|
|
12759
13351
|
}
|
|
12760
13352
|
function identifyHome(dir) {
|
|
12761
|
-
const has = (...parts) =>
|
|
13353
|
+
const has = (...parts) => existsSync18(join19(dir, ...parts));
|
|
12762
13354
|
if (has("projects") && dirHasTranscript(join19(dir, "projects"), (f) => f.endsWith(".jsonl"), 2))
|
|
12763
13355
|
return "claude";
|
|
12764
13356
|
if (has("sessions") && dirHasTranscript(join19(dir, "sessions"), (f) => f.startsWith("rollout-") && f.endsWith(".jsonl"), 4))
|
|
@@ -12769,6 +13361,8 @@ function identifyHome(dir) {
|
|
|
12769
13361
|
return "cursor";
|
|
12770
13362
|
if (has("opencode.db"))
|
|
12771
13363
|
return "opencode";
|
|
13364
|
+
if (has("state.db") && has("SOUL.md"))
|
|
13365
|
+
return "hermes";
|
|
12772
13366
|
return null;
|
|
12773
13367
|
}
|
|
12774
13368
|
function dirHasTranscript(root, match, depth) {
|
|
@@ -12796,7 +13390,8 @@ function countSessions(dir, tool) {
|
|
|
12796
13390
|
codex: { sub: "sessions", depth: 4, match: (f) => f.startsWith("rollout-") && f.endsWith(".jsonl") },
|
|
12797
13391
|
agy: { sub: "brain", depth: 4, match: (f) => f.endsWith(".jsonl") },
|
|
12798
13392
|
cursor: { sub: "chats", depth: 3, match: (f) => f === "store.db" },
|
|
12799
|
-
opencode: { sub: "", depth: 0, match: () => false }
|
|
13393
|
+
opencode: { sub: "", depth: 0, match: () => false },
|
|
13394
|
+
hermes: { sub: "", depth: 0, match: () => false }
|
|
12800
13395
|
};
|
|
12801
13396
|
const s = spec[tool];
|
|
12802
13397
|
if (!s.sub)
|
|
@@ -12839,6 +13434,8 @@ function declaredHomes(env = process.env, plat = osPlatform()) {
|
|
|
12839
13434
|
add(env.CHAT_RECALL_AGY_HOME);
|
|
12840
13435
|
add(env.CHAT_RECALL_CURSOR_HOME);
|
|
12841
13436
|
add(env.CHAT_RECALL_CURSOR_IDE_HOME);
|
|
13437
|
+
add(env.CHAT_RECALL_HERMES_HOME);
|
|
13438
|
+
add(env.HERMES_HOME);
|
|
12842
13439
|
for (const d of (env.CLAUDE_DIRS || "").split(","))
|
|
12843
13440
|
add(d);
|
|
12844
13441
|
if (plat === "win32") {
|
|
@@ -12938,6 +13535,15 @@ function discoverHomes(opts = {}) {
|
|
|
12938
13535
|
if (prior && !(via === "declared" && prior.via !== "declared"))
|
|
12939
13536
|
return;
|
|
12940
13537
|
found.set(real, { tool, path: real, via, sessions: countSessions(real, tool) });
|
|
13538
|
+
if (tool === "hermes") {
|
|
13539
|
+
try {
|
|
13540
|
+
for (const e of readdirSync13(join19(real, "profiles"), { withFileTypes: true })) {
|
|
13541
|
+
if (e.isDirectory())
|
|
13542
|
+
consider(join19(real, "profiles", e.name), via);
|
|
13543
|
+
}
|
|
13544
|
+
} catch {
|
|
13545
|
+
}
|
|
13546
|
+
}
|
|
12941
13547
|
};
|
|
12942
13548
|
for (const d of declaredHomes(env, plat))
|
|
12943
13549
|
consider(d, "declared");
|
|
@@ -13004,7 +13610,7 @@ var init_home_discovery = __esm({
|
|
|
13004
13610
|
|
|
13005
13611
|
// ../engine/dist/core/detector-install.js
|
|
13006
13612
|
import { createHash as createHash4 } from "crypto";
|
|
13007
|
-
import { existsSync as
|
|
13613
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync5, mkdtempSync, chmodSync as chmodSync2, renameSync as renameSync3, rmSync as rmSync2, writeFileSync as writeFileSync4, readFileSync as readFileSync13, statSync as statSync16, copyFileSync as copyFileSync2 } from "fs";
|
|
13008
13614
|
import { join as join20 } from "path";
|
|
13009
13615
|
function managedDetectorPath(name) {
|
|
13010
13616
|
return join20(getDetectorBinDir(), name + exeSuffix());
|
|
@@ -13044,7 +13650,7 @@ function resolveDetector(name) {
|
|
|
13044
13650
|
const dir = configuredDir();
|
|
13045
13651
|
if (dir) {
|
|
13046
13652
|
const p2 = join20(dir, name + exeSuffix());
|
|
13047
|
-
if (
|
|
13653
|
+
if (existsSync19(p2))
|
|
13048
13654
|
return { path: p2, version: "operator-supplied", source: "configured" };
|
|
13049
13655
|
return { error: "not-installed" };
|
|
13050
13656
|
}
|
|
@@ -13052,7 +13658,7 @@ function resolveDetector(name) {
|
|
|
13052
13658
|
if (!spec.assets[platformKey()])
|
|
13053
13659
|
return { error: "unsupported-platform" };
|
|
13054
13660
|
const p = managedDetectorPath(name);
|
|
13055
|
-
if (!
|
|
13661
|
+
if (!existsSync19(p))
|
|
13056
13662
|
return { error: "not-installed" };
|
|
13057
13663
|
const receipt = readReceipt(name);
|
|
13058
13664
|
if (!receipt)
|
|
@@ -13108,7 +13714,7 @@ var init_detector_install = __esm({
|
|
|
13108
13714
|
|
|
13109
13715
|
// ../engine/dist/core/secret-scanner.js
|
|
13110
13716
|
import { spawnSync } from "child_process";
|
|
13111
|
-
import { existsSync as
|
|
13717
|
+
import { existsSync as existsSync20, unlinkSync, readFileSync as readFileSync14, mkdtempSync as mkdtempSync2, rmSync as rmSync3 } from "fs";
|
|
13112
13718
|
import { tmpdir } from "os";
|
|
13113
13719
|
import { join as join21 } from "path";
|
|
13114
13720
|
function mask(s) {
|
|
@@ -13274,7 +13880,7 @@ function runTrufflehogDir(binary, dir, opts = {}) {
|
|
|
13274
13880
|
return out;
|
|
13275
13881
|
}
|
|
13276
13882
|
function scanDirForSecrets(dir, opts = {}) {
|
|
13277
|
-
if (!
|
|
13883
|
+
if (!existsSync20(dir))
|
|
13278
13884
|
return [];
|
|
13279
13885
|
const gitleaks = whichDetector("gitleaks");
|
|
13280
13886
|
const trufflehog = whichDetector("trufflehog");
|
|
@@ -13311,7 +13917,7 @@ function scanTenantRules(text, tenantRules) {
|
|
|
13311
13917
|
return out;
|
|
13312
13918
|
}
|
|
13313
13919
|
function scanFileForSecrets(filePath, opts = {}) {
|
|
13314
|
-
if (!
|
|
13920
|
+
if (!existsSync20(filePath))
|
|
13315
13921
|
return [];
|
|
13316
13922
|
const gitleaks = whichDetector("gitleaks");
|
|
13317
13923
|
const trufflehog = whichDetector("trufflehog");
|
|
@@ -13428,10 +14034,10 @@ var init_types = __esm({
|
|
|
13428
14034
|
|
|
13429
14035
|
// ../engine/dist/transcript/opencode.js
|
|
13430
14036
|
async function parseOpenCodeSubagents(parentSessionId) {
|
|
13431
|
-
const { existsSync:
|
|
14037
|
+
const { existsSync: existsSync52 } = await import("fs");
|
|
13432
14038
|
const { opencodeBackend: opencodeBackend2 } = await Promise.resolve().then(() => (init_opencode(), opencode_exports));
|
|
13433
14039
|
const dbPath = opencodeBackend2.dbPath();
|
|
13434
|
-
if (!
|
|
14040
|
+
if (!existsSync52(dbPath))
|
|
13435
14041
|
return [];
|
|
13436
14042
|
const realParent = parentSessionId.replace("opencode_", "");
|
|
13437
14043
|
const db = openSqliteReadonlyOrThrow(dbPath);
|
|
@@ -13472,10 +14078,10 @@ async function parseOpenCodeSubagents(parentSessionId) {
|
|
|
13472
14078
|
}
|
|
13473
14079
|
}
|
|
13474
14080
|
async function parseOpenCodeTranscript(sessionId) {
|
|
13475
|
-
const { existsSync:
|
|
14081
|
+
const { existsSync: existsSync52 } = await import("fs");
|
|
13476
14082
|
const { opencodeBackend: opencodeBackend2 } = await Promise.resolve().then(() => (init_opencode(), opencode_exports));
|
|
13477
14083
|
const dbPath = opencodeBackend2.dbPath();
|
|
13478
|
-
if (!
|
|
14084
|
+
if (!existsSync52(dbPath))
|
|
13479
14085
|
return [];
|
|
13480
14086
|
const realId = sessionId.replace("opencode_", "");
|
|
13481
14087
|
const db = openSqliteReadonlyOrThrow(dbPath);
|
|
@@ -13706,7 +14312,7 @@ var init_transcript = __esm({
|
|
|
13706
14312
|
// ../engine/dist/core/project-resolver.js
|
|
13707
14313
|
import { execSync } from "child_process";
|
|
13708
14314
|
import { createHash as createHash5 } from "crypto";
|
|
13709
|
-
import { existsSync as
|
|
14315
|
+
import { existsSync as existsSync21, readFileSync as readFileSync15, realpathSync as realpathSync3, readdirSync as readdirSync14, statSync as statSync18 } from "fs";
|
|
13710
14316
|
import { basename as basename11, dirname as dirname14, isAbsolute, join as join22, resolve, sep } from "path";
|
|
13711
14317
|
function getProjectsConfigPath() {
|
|
13712
14318
|
return join22(getDataDir(), "projects.json");
|
|
@@ -13716,7 +14322,7 @@ function loadProjectsConfig() {
|
|
|
13716
14322
|
return cachedConfig.cfg;
|
|
13717
14323
|
}
|
|
13718
14324
|
const path = getProjectsConfigPath();
|
|
13719
|
-
if (!
|
|
14325
|
+
if (!existsSync21(path)) {
|
|
13720
14326
|
cachedConfig = { mtime: 0, cfg: {} };
|
|
13721
14327
|
return cachedConfig.cfg;
|
|
13722
14328
|
}
|
|
@@ -13856,7 +14462,7 @@ function findGitToplevel(realPath) {
|
|
|
13856
14462
|
let cur = realPath;
|
|
13857
14463
|
let last = "";
|
|
13858
14464
|
while (cur && cur !== last) {
|
|
13859
|
-
if (
|
|
14465
|
+
if (existsSync21(join22(cur, ".git")))
|
|
13860
14466
|
return cur;
|
|
13861
14467
|
last = cur;
|
|
13862
14468
|
cur = dirname14(cur);
|
|
@@ -13923,7 +14529,7 @@ function resolveAutoWorkspace(realPath, minRepos) {
|
|
|
13923
14529
|
let last = "";
|
|
13924
14530
|
let depth = 0;
|
|
13925
14531
|
while (cur && cur !== last && depth < AUTO_WORKSPACE_MAX_DEPTH) {
|
|
13926
|
-
if (!
|
|
14532
|
+
if (!existsSync21(join22(cur, ".git"))) {
|
|
13927
14533
|
const cached = workspaceCache.get(cur);
|
|
13928
14534
|
let qualifies;
|
|
13929
14535
|
if (cached === void 0) {
|
|
@@ -13959,7 +14565,7 @@ function countGitChildren(dir) {
|
|
|
13959
14565
|
const st = statSync18(child);
|
|
13960
14566
|
if (!st.isDirectory())
|
|
13961
14567
|
continue;
|
|
13962
|
-
if (
|
|
14568
|
+
if (existsSync21(join22(child, ".git")))
|
|
13963
14569
|
count++;
|
|
13964
14570
|
} catch {
|
|
13965
14571
|
}
|
|
@@ -14572,7 +15178,7 @@ var init_source_policy = __esm({
|
|
|
14572
15178
|
init_project_path_match();
|
|
14573
15179
|
init_settings();
|
|
14574
15180
|
cache2 = null;
|
|
14575
|
-
TOOLS = ["claude", "opencode", "codex", "agy", "cursor"];
|
|
15181
|
+
TOOLS = ["claude", "opencode", "codex", "agy", "cursor", "hermes"];
|
|
14576
15182
|
}
|
|
14577
15183
|
});
|
|
14578
15184
|
|
|
@@ -14667,7 +15273,7 @@ var init_source_registry = __esm({
|
|
|
14667
15273
|
});
|
|
14668
15274
|
|
|
14669
15275
|
// ../engine/dist/core/utils.js
|
|
14670
|
-
import { existsSync as
|
|
15276
|
+
import { existsSync as existsSync22, readdirSync as readdirSync15 } from "fs";
|
|
14671
15277
|
import { homedir as homedir6 } from "os";
|
|
14672
15278
|
import { join as join23 } from "path";
|
|
14673
15279
|
function splitByHeaders(markdown) {
|
|
@@ -14703,7 +15309,7 @@ function getClaudeDirs() {
|
|
|
14703
15309
|
const dirs = [];
|
|
14704
15310
|
const seen = /* @__PURE__ */ new Set();
|
|
14705
15311
|
const add = (dir) => {
|
|
14706
|
-
if (!seen.has(dir) &&
|
|
15312
|
+
if (!seen.has(dir) && existsSync22(dir)) {
|
|
14707
15313
|
seen.add(dir);
|
|
14708
15314
|
dirs.push(dir);
|
|
14709
15315
|
}
|
|
@@ -14722,7 +15328,7 @@ function getClaudeDirs() {
|
|
|
14722
15328
|
for (const entry of entries) {
|
|
14723
15329
|
if (entry.isDirectory() && entry.name.startsWith(".claude-") && entry.name !== ".claude-code") {
|
|
14724
15330
|
const candidate = join23(home, entry.name);
|
|
14725
|
-
if (
|
|
15331
|
+
if (existsSync22(join23(candidate, "projects"))) {
|
|
14726
15332
|
add(candidate);
|
|
14727
15333
|
}
|
|
14728
15334
|
}
|
|
@@ -14735,7 +15341,7 @@ function discoverSubdirs(subdir) {
|
|
|
14735
15341
|
const result = [];
|
|
14736
15342
|
for (const claudeDir of getClaudeDirs()) {
|
|
14737
15343
|
const path = join23(claudeDir, subdir);
|
|
14738
|
-
if (
|
|
15344
|
+
if (existsSync22(path)) {
|
|
14739
15345
|
result.push(path);
|
|
14740
15346
|
}
|
|
14741
15347
|
}
|
|
@@ -14748,7 +15354,7 @@ var init_utils = __esm({
|
|
|
14748
15354
|
});
|
|
14749
15355
|
|
|
14750
15356
|
// ../engine/dist/parsers/plan-source.js
|
|
14751
|
-
import { existsSync as
|
|
15357
|
+
import { existsSync as existsSync23, readdirSync as readdirSync16, readFileSync as readFileSync16, statSync as statSync20 } from "fs";
|
|
14752
15358
|
import { homedir as homedir7 } from "os";
|
|
14753
15359
|
import { join as join24, basename as basename12 } from "path";
|
|
14754
15360
|
function parseFrontmatter(content) {
|
|
@@ -14806,7 +15412,7 @@ var init_plan_source = __esm({
|
|
|
14806
15412
|
return this._knownProjectDirs;
|
|
14807
15413
|
const projectsDir = claudeBackend.projectsDir();
|
|
14808
15414
|
this._knownProjectDirs = [];
|
|
14809
|
-
if (!
|
|
15415
|
+
if (!existsSync23(projectsDir))
|
|
14810
15416
|
return this._knownProjectDirs;
|
|
14811
15417
|
try {
|
|
14812
15418
|
const entries = readdirSync16(projectsDir, { withFileTypes: true });
|
|
@@ -14814,7 +15420,7 @@ var init_plan_source = __esm({
|
|
|
14814
15420
|
if (!entry.isDirectory() || entry.name.startsWith("."))
|
|
14815
15421
|
continue;
|
|
14816
15422
|
const projectPath = resolveProjectDirName(entry.name);
|
|
14817
|
-
if (
|
|
15423
|
+
if (existsSync23(projectPath)) {
|
|
14818
15424
|
this._knownProjectDirs.push(projectPath);
|
|
14819
15425
|
}
|
|
14820
15426
|
}
|
|
@@ -14838,7 +15444,7 @@ var init_plan_source = __esm({
|
|
|
14838
15444
|
async *discoverClaudePlans() {
|
|
14839
15445
|
const seenClaude = /* @__PURE__ */ new Set();
|
|
14840
15446
|
for (const plansDir of this.plansDirs) {
|
|
14841
|
-
if (!
|
|
15447
|
+
if (!existsSync23(plansDir))
|
|
14842
15448
|
continue;
|
|
14843
15449
|
const files = readdirSync16(plansDir).filter((f) => f.endsWith(".md"));
|
|
14844
15450
|
for (const file of files) {
|
|
@@ -14880,7 +15486,7 @@ var init_plan_source = __esm({
|
|
|
14880
15486
|
}
|
|
14881
15487
|
async *discoverOpenCodePlans() {
|
|
14882
15488
|
const plansDir = opencodeBackend.plansDir();
|
|
14883
|
-
if (!
|
|
15489
|
+
if (!existsSync23(plansDir))
|
|
14884
15490
|
return;
|
|
14885
15491
|
let files;
|
|
14886
15492
|
try {
|
|
@@ -14967,7 +15573,7 @@ var init_plan_source = __esm({
|
|
|
14967
15573
|
return "";
|
|
14968
15574
|
}
|
|
14969
15575
|
async parse(item) {
|
|
14970
|
-
if (!
|
|
15576
|
+
if (!existsSync23(item.filePath))
|
|
14971
15577
|
return [];
|
|
14972
15578
|
const content = readFileSync16(item.filePath, "utf-8");
|
|
14973
15579
|
const chunks = [];
|
|
@@ -15008,7 +15614,7 @@ var init_plan_source = __esm({
|
|
|
15008
15614
|
const projPath = join24(root, proj);
|
|
15009
15615
|
for (const sessionEntry of safeReaddir(projPath)) {
|
|
15010
15616
|
const subDir = join24(projPath, sessionEntry, "subagents");
|
|
15011
|
-
if (!
|
|
15617
|
+
if (!existsSync23(subDir))
|
|
15012
15618
|
continue;
|
|
15013
15619
|
for (const f of safeReaddir(subDir)) {
|
|
15014
15620
|
const m = f.match(/^agent-([a-z0-9_-]+)\.jsonl$/i);
|
|
@@ -15083,7 +15689,7 @@ var init_plan_source = __esm({
|
|
|
15083
15689
|
}
|
|
15084
15690
|
async *discoverAgyPlans() {
|
|
15085
15691
|
const brainDir = join24(agyBackend.homeDir(), "brain");
|
|
15086
|
-
if (!
|
|
15692
|
+
if (!existsSync23(brainDir))
|
|
15087
15693
|
return;
|
|
15088
15694
|
let sessionDirs;
|
|
15089
15695
|
try {
|
|
@@ -15138,7 +15744,7 @@ var init_plan_source = __esm({
|
|
|
15138
15744
|
});
|
|
15139
15745
|
|
|
15140
15746
|
// ../engine/dist/parsers/task-source.js
|
|
15141
|
-
import { existsSync as
|
|
15747
|
+
import { existsSync as existsSync24, readdirSync as readdirSync17, readFileSync as readFileSync17, statSync as statSync21 } from "fs";
|
|
15142
15748
|
import { join as join25 } from "path";
|
|
15143
15749
|
var MAX_CHUNK_CHARS2, TaskSource;
|
|
15144
15750
|
var init_task_source = __esm({
|
|
@@ -15168,7 +15774,7 @@ var init_task_source = __esm({
|
|
|
15168
15774
|
}
|
|
15169
15775
|
async *discoverClaudeTodos() {
|
|
15170
15776
|
const todosDir = claudeBackend.todosDir();
|
|
15171
|
-
if (!
|
|
15777
|
+
if (!existsSync24(todosDir))
|
|
15172
15778
|
return;
|
|
15173
15779
|
let files;
|
|
15174
15780
|
try {
|
|
@@ -15219,7 +15825,7 @@ var init_task_source = __esm({
|
|
|
15219
15825
|
}
|
|
15220
15826
|
}
|
|
15221
15827
|
async *discoverInDir(tasksDir) {
|
|
15222
|
-
if (!
|
|
15828
|
+
if (!existsSync24(tasksDir))
|
|
15223
15829
|
return;
|
|
15224
15830
|
const entries = readdirSync17(tasksDir, { withFileTypes: true });
|
|
15225
15831
|
for (const entry of entries) {
|
|
@@ -15261,7 +15867,7 @@ var init_task_source = __esm({
|
|
|
15261
15867
|
return this.parseAgentTodo(item);
|
|
15262
15868
|
}
|
|
15263
15869
|
const taskDir = item.filePath;
|
|
15264
|
-
if (!
|
|
15870
|
+
if (!existsSync24(taskDir))
|
|
15265
15871
|
return [];
|
|
15266
15872
|
const taskFiles = readdirSync17(taskDir).filter((f) => f.endsWith(".json"));
|
|
15267
15873
|
const tasks = this.readTasks(taskDir, taskFiles);
|
|
@@ -15322,7 +15928,7 @@ ${task.description}`.slice(0, MAX_CHUNK_CHARS2);
|
|
|
15322
15928
|
}];
|
|
15323
15929
|
}
|
|
15324
15930
|
async parseAgentTodo(item) {
|
|
15325
|
-
if (!
|
|
15931
|
+
if (!existsSync24(item.filePath))
|
|
15326
15932
|
return [];
|
|
15327
15933
|
let parsed;
|
|
15328
15934
|
try {
|
|
@@ -15374,7 +15980,7 @@ ${task.description}`.slice(0, MAX_CHUNK_CHARS2);
|
|
|
15374
15980
|
});
|
|
15375
15981
|
|
|
15376
15982
|
// ../engine/dist/parsers/claude-md-source.js
|
|
15377
|
-
import { existsSync as
|
|
15983
|
+
import { existsSync as existsSync25, readFileSync as readFileSync18, readdirSync as readdirSync18, statSync as statSync22 } from "fs";
|
|
15378
15984
|
import { homedir as homedir8 } from "os";
|
|
15379
15985
|
import { join as join26, basename as basename13, dirname as dirname15 } from "path";
|
|
15380
15986
|
import { createHash as createHash6 } from "crypto";
|
|
@@ -15382,13 +15988,13 @@ function discoverProjectDirs(claudeDir) {
|
|
|
15382
15988
|
const dirs = [];
|
|
15383
15989
|
const seen = /* @__PURE__ */ new Set();
|
|
15384
15990
|
const addProject = (path) => {
|
|
15385
|
-
if (!seen.has(path) &&
|
|
15991
|
+
if (!seen.has(path) && existsSync25(path)) {
|
|
15386
15992
|
seen.add(path);
|
|
15387
15993
|
dirs.push(path);
|
|
15388
15994
|
}
|
|
15389
15995
|
};
|
|
15390
15996
|
const scanProjectsDir = (projectsDir) => {
|
|
15391
|
-
if (!
|
|
15997
|
+
if (!existsSync25(projectsDir))
|
|
15392
15998
|
return;
|
|
15393
15999
|
try {
|
|
15394
16000
|
const entries = readdirSync18(projectsDir, { withFileTypes: true });
|
|
@@ -15416,7 +16022,7 @@ function discoverProjectDirs(claudeDir) {
|
|
|
15416
16022
|
} catch {
|
|
15417
16023
|
}
|
|
15418
16024
|
const gemProjects = agyBackend.sharedProjectsJson();
|
|
15419
|
-
if (
|
|
16025
|
+
if (existsSync25(gemProjects)) {
|
|
15420
16026
|
try {
|
|
15421
16027
|
const data = JSON.parse(readFileSync18(gemProjects, "utf-8"));
|
|
15422
16028
|
for (const path of Object.keys(data.projects || {}))
|
|
@@ -15425,7 +16031,7 @@ function discoverProjectDirs(claudeDir) {
|
|
|
15425
16031
|
}
|
|
15426
16032
|
}
|
|
15427
16033
|
const ocDb = opencodeBackend.dbPath();
|
|
15428
|
-
if (
|
|
16034
|
+
if (existsSync25(ocDb)) {
|
|
15429
16035
|
try {
|
|
15430
16036
|
const db = openSqliteReadonlyOrThrow(ocDb);
|
|
15431
16037
|
try {
|
|
@@ -15476,7 +16082,7 @@ var init_claude_md_source = __esm({
|
|
|
15476
16082
|
for (const note of NOTE_FILES) {
|
|
15477
16083
|
const p = join26(homedir8(), note.filename);
|
|
15478
16084
|
const key2 = seenKey(p, note.tool);
|
|
15479
|
-
if (
|
|
16085
|
+
if (existsSync25(p) && !seen.has(key2)) {
|
|
15480
16086
|
seen.add(key2);
|
|
15481
16087
|
const item = this.fileToItem(p, note.filename, note.tool);
|
|
15482
16088
|
if (item)
|
|
@@ -15488,7 +16094,7 @@ var init_claude_md_source = __esm({
|
|
|
15488
16094
|
for (const note of NOTE_FILES) {
|
|
15489
16095
|
const p = join26(projectDir, note.filename);
|
|
15490
16096
|
const key2 = seenKey(p, note.tool);
|
|
15491
|
-
if (
|
|
16097
|
+
if (existsSync25(p) && !seen.has(key2)) {
|
|
15492
16098
|
seen.add(key2);
|
|
15493
16099
|
const item = this.fileToItem(p, note.filename, note.tool);
|
|
15494
16100
|
if (item)
|
|
@@ -15497,12 +16103,12 @@ var init_claude_md_source = __esm({
|
|
|
15497
16103
|
}
|
|
15498
16104
|
}
|
|
15499
16105
|
for (const searchDir of this.searchDirs) {
|
|
15500
|
-
if (!
|
|
16106
|
+
if (!existsSync25(searchDir))
|
|
15501
16107
|
continue;
|
|
15502
16108
|
for (const note of NOTE_FILES) {
|
|
15503
16109
|
const directPath = join26(searchDir, note.filename);
|
|
15504
16110
|
const key2 = seenKey(directPath, note.tool);
|
|
15505
|
-
if (
|
|
16111
|
+
if (existsSync25(directPath) && !seen.has(key2)) {
|
|
15506
16112
|
seen.add(key2);
|
|
15507
16113
|
const item = this.fileToItem(directPath, note.filename, note.tool);
|
|
15508
16114
|
if (item)
|
|
@@ -15517,7 +16123,7 @@ var init_claude_md_source = __esm({
|
|
|
15517
16123
|
for (const note of NOTE_FILES) {
|
|
15518
16124
|
const p = join26(searchDir, entry.name, note.filename);
|
|
15519
16125
|
const key2 = seenKey(p, note.tool);
|
|
15520
|
-
if (
|
|
16126
|
+
if (existsSync25(p) && !seen.has(key2)) {
|
|
15521
16127
|
seen.add(key2);
|
|
15522
16128
|
const item = this.fileToItem(p, note.filename, note.tool);
|
|
15523
16129
|
if (item)
|
|
@@ -15531,7 +16137,7 @@ var init_claude_md_source = __esm({
|
|
|
15531
16137
|
}
|
|
15532
16138
|
}
|
|
15533
16139
|
async parse(item) {
|
|
15534
|
-
if (!
|
|
16140
|
+
if (!existsSync25(item.filePath))
|
|
15535
16141
|
return [];
|
|
15536
16142
|
const content = readFileSync18(item.filePath, "utf-8");
|
|
15537
16143
|
const chunks = [];
|
|
@@ -15600,7 +16206,7 @@ var init_claude_md_source = __esm({
|
|
|
15600
16206
|
});
|
|
15601
16207
|
|
|
15602
16208
|
// ../engine/dist/parsers/agent-memory-source.js
|
|
15603
|
-
import { existsSync as
|
|
16209
|
+
import { existsSync as existsSync26, readFileSync as readFileSync19, readdirSync as readdirSync19, statSync as statSync23 } from "fs";
|
|
15604
16210
|
import { homedir as homedir9 } from "os";
|
|
15605
16211
|
import { join as join27, basename as basename14 } from "path";
|
|
15606
16212
|
function parseFrontmatter2(content) {
|
|
@@ -15634,7 +16240,7 @@ function discoverMemoryDirs() {
|
|
|
15634
16240
|
const out = [];
|
|
15635
16241
|
const seen = /* @__PURE__ */ new Set();
|
|
15636
16242
|
const add = (memoryDir, projectHash) => {
|
|
15637
|
-
if (!seen.has(memoryDir) &&
|
|
16243
|
+
if (!seen.has(memoryDir) && existsSync26(memoryDir)) {
|
|
15638
16244
|
seen.add(memoryDir);
|
|
15639
16245
|
out.push({ memoryDir, projectHash });
|
|
15640
16246
|
}
|
|
@@ -15650,7 +16256,7 @@ function discoverMemoryDirs() {
|
|
|
15650
16256
|
} catch {
|
|
15651
16257
|
}
|
|
15652
16258
|
for (const projectsDir of claudeRoots) {
|
|
15653
|
-
if (!
|
|
16259
|
+
if (!existsSync26(projectsDir))
|
|
15654
16260
|
continue;
|
|
15655
16261
|
try {
|
|
15656
16262
|
for (const entry of readdirSync19(projectsDir, { withFileTypes: true })) {
|
|
@@ -15699,7 +16305,7 @@ var init_agent_memory_source = __esm({
|
|
|
15699
16305
|
}
|
|
15700
16306
|
}
|
|
15701
16307
|
async parse(item) {
|
|
15702
|
-
if (!
|
|
16308
|
+
if (!existsSync26(item.filePath))
|
|
15703
16309
|
return [];
|
|
15704
16310
|
const content = readFileSync19(item.filePath, "utf-8");
|
|
15705
16311
|
const { body } = parseFrontmatter2(content);
|
|
@@ -15785,7 +16391,7 @@ var init_agent_memory_source = __esm({
|
|
|
15785
16391
|
});
|
|
15786
16392
|
|
|
15787
16393
|
// ../engine/dist/parsers/history-source.js
|
|
15788
|
-
import { existsSync as
|
|
16394
|
+
import { existsSync as existsSync27, readdirSync as readdirSync20, statSync as statSync24 } from "fs";
|
|
15789
16395
|
import { createReadStream as createReadStream3 } from "fs";
|
|
15790
16396
|
import { createInterface as createInterface2 } from "readline";
|
|
15791
16397
|
import { homedir as homedir10 } from "os";
|
|
@@ -15807,7 +16413,7 @@ var init_history_source = __esm({
|
|
|
15807
16413
|
const home = homedir10();
|
|
15808
16414
|
const paths = [];
|
|
15809
16415
|
const tryAdd = (p) => {
|
|
15810
|
-
if (
|
|
16416
|
+
if (existsSync27(p) && !paths.includes(p))
|
|
15811
16417
|
paths.push(p);
|
|
15812
16418
|
};
|
|
15813
16419
|
tryAdd(claudeBackend.historyFile());
|
|
@@ -15825,7 +16431,7 @@ var init_history_source = __esm({
|
|
|
15825
16431
|
async *discover() {
|
|
15826
16432
|
if (!isSourceEnabled("claude", "history"))
|
|
15827
16433
|
return;
|
|
15828
|
-
const historyPath = this.historyPaths.find((p) =>
|
|
16434
|
+
const historyPath = this.historyPaths.find((p) => existsSync27(p));
|
|
15829
16435
|
if (!historyPath)
|
|
15830
16436
|
return;
|
|
15831
16437
|
const stat3 = statSync24(historyPath);
|
|
@@ -15921,7 +16527,7 @@ var init_history_source = __esm({
|
|
|
15921
16527
|
async groupByProject() {
|
|
15922
16528
|
const groups = /* @__PURE__ */ new Map();
|
|
15923
16529
|
for (const historyPath of this.historyPaths) {
|
|
15924
|
-
if (!
|
|
16530
|
+
if (!existsSync27(historyPath))
|
|
15925
16531
|
continue;
|
|
15926
16532
|
const rl = createInterface2({
|
|
15927
16533
|
input: createReadStream3(historyPath),
|
|
@@ -15969,7 +16575,7 @@ var init_history_source = __esm({
|
|
|
15969
16575
|
});
|
|
15970
16576
|
|
|
15971
16577
|
// ../engine/dist/parsers/paste-source.js
|
|
15972
|
-
import { existsSync as
|
|
16578
|
+
import { existsSync as existsSync28, readdirSync as readdirSync21, readFileSync as readFileSync20, statSync as statSync25 } from "fs";
|
|
15973
16579
|
import { homedir as homedir11 } from "os";
|
|
15974
16580
|
import { join as join29, basename as basename15 } from "path";
|
|
15975
16581
|
var MAX_CHUNK_CHARS6, MAX_FILE_SIZE, PasteSource;
|
|
@@ -15990,7 +16596,7 @@ var init_paste_source = __esm({
|
|
|
15990
16596
|
const home = homedir11();
|
|
15991
16597
|
const dirs = [];
|
|
15992
16598
|
const tryAdd = (p) => {
|
|
15993
|
-
if (
|
|
16599
|
+
if (existsSync28(p) && !dirs.includes(p))
|
|
15994
16600
|
dirs.push(p);
|
|
15995
16601
|
};
|
|
15996
16602
|
tryAdd(claudeBackend.pasteCacheDir());
|
|
@@ -16010,7 +16616,7 @@ var init_paste_source = __esm({
|
|
|
16010
16616
|
return;
|
|
16011
16617
|
const seen = /* @__PURE__ */ new Set();
|
|
16012
16618
|
for (const cacheDir of this.cacheDirs) {
|
|
16013
|
-
if (!
|
|
16619
|
+
if (!existsSync28(cacheDir))
|
|
16014
16620
|
continue;
|
|
16015
16621
|
const files = readdirSync21(cacheDir).filter((f) => f.endsWith(".txt"));
|
|
16016
16622
|
for (const file of files) {
|
|
@@ -16044,7 +16650,7 @@ var init_paste_source = __esm({
|
|
|
16044
16650
|
}
|
|
16045
16651
|
}
|
|
16046
16652
|
async parse(item) {
|
|
16047
|
-
if (!
|
|
16653
|
+
if (!existsSync28(item.filePath))
|
|
16048
16654
|
return [];
|
|
16049
16655
|
const content = readFileSync20(item.filePath, "utf-8");
|
|
16050
16656
|
if (content.trim().length < 20)
|
|
@@ -16069,7 +16675,7 @@ var init_paste_source = __esm({
|
|
|
16069
16675
|
});
|
|
16070
16676
|
|
|
16071
16677
|
// ../engine/dist/parsers/antigravity-brain-source.js
|
|
16072
|
-
import { existsSync as
|
|
16678
|
+
import { existsSync as existsSync29, readdirSync as readdirSync22, readFileSync as readFileSync21, statSync as statSync26 } from "fs";
|
|
16073
16679
|
import { join as join30 } from "path";
|
|
16074
16680
|
var MAX_CHUNK_CHARS7, AntigravityBrainSource;
|
|
16075
16681
|
var init_antigravity_brain_source = __esm({
|
|
@@ -16088,7 +16694,7 @@ var init_antigravity_brain_source = __esm({
|
|
|
16088
16694
|
async *discover() {
|
|
16089
16695
|
if (!isSourceEnabled("agy", "brain"))
|
|
16090
16696
|
return;
|
|
16091
|
-
if (!
|
|
16697
|
+
if (!existsSync29(this.brainDir))
|
|
16092
16698
|
return;
|
|
16093
16699
|
const sessions = readdirSync22(this.brainDir, { withFileTypes: true });
|
|
16094
16700
|
for (const entry of sessions) {
|
|
@@ -16107,7 +16713,7 @@ var init_antigravity_brain_source = __esm({
|
|
|
16107
16713
|
const heading = content.split("\n").find((l) => l.startsWith("#"))?.replace(/^#+\s*/, "").trim() || file;
|
|
16108
16714
|
const metaPath = `${filePath}.metadata.json`;
|
|
16109
16715
|
let metaSummary = "";
|
|
16110
|
-
if (
|
|
16716
|
+
if (existsSync29(metaPath)) {
|
|
16111
16717
|
try {
|
|
16112
16718
|
const meta = JSON.parse(readFileSync21(metaPath, "utf-8"));
|
|
16113
16719
|
metaSummary = meta.summary || "";
|
|
@@ -16138,7 +16744,7 @@ var init_antigravity_brain_source = __esm({
|
|
|
16138
16744
|
}
|
|
16139
16745
|
}
|
|
16140
16746
|
async parse(item) {
|
|
16141
|
-
if (!
|
|
16747
|
+
if (!existsSync29(item.filePath))
|
|
16142
16748
|
return [];
|
|
16143
16749
|
const content = readFileSync21(item.filePath, "utf-8");
|
|
16144
16750
|
const chunks = [];
|
|
@@ -16181,7 +16787,7 @@ var init_antigravity_brain_source = __esm({
|
|
|
16181
16787
|
});
|
|
16182
16788
|
|
|
16183
16789
|
// ../engine/dist/parsers/opencode-source.js
|
|
16184
|
-
import { existsSync as
|
|
16790
|
+
import { existsSync as existsSync30 } from "fs";
|
|
16185
16791
|
var MAX_CHUNK_CHARS8, OpenCodeSource;
|
|
16186
16792
|
var init_opencode_source = __esm({
|
|
16187
16793
|
"../engine/dist/parsers/opencode-source.js"() {
|
|
@@ -16199,7 +16805,7 @@ var init_opencode_source = __esm({
|
|
|
16199
16805
|
async *discover() {
|
|
16200
16806
|
if (!isSourceEnabled("opencode", "sessions"))
|
|
16201
16807
|
return;
|
|
16202
|
-
if (!
|
|
16808
|
+
if (!existsSync30(this.dbPath))
|
|
16203
16809
|
return;
|
|
16204
16810
|
let db;
|
|
16205
16811
|
try {
|
|
@@ -16297,7 +16903,7 @@ var init_opencode_source = __esm({
|
|
|
16297
16903
|
}
|
|
16298
16904
|
}
|
|
16299
16905
|
async parse(item) {
|
|
16300
|
-
if (!
|
|
16906
|
+
if (!existsSync30(this.dbPath))
|
|
16301
16907
|
return [];
|
|
16302
16908
|
const sessionId = item.id.replace("opencode_", "");
|
|
16303
16909
|
const db = openSqliteReadonlyOrThrow(this.dbPath);
|
|
@@ -16369,7 +16975,7 @@ var init_opencode_source = __esm({
|
|
|
16369
16975
|
});
|
|
16370
16976
|
|
|
16371
16977
|
// ../engine/dist/parsers/opencode-todo-source.js
|
|
16372
|
-
import { existsSync as
|
|
16978
|
+
import { existsSync as existsSync31 } from "fs";
|
|
16373
16979
|
var OpenCodeTodoSource;
|
|
16374
16980
|
var init_opencode_todo_source = __esm({
|
|
16375
16981
|
"../engine/dist/parsers/opencode-todo-source.js"() {
|
|
@@ -16386,7 +16992,7 @@ var init_opencode_todo_source = __esm({
|
|
|
16386
16992
|
async *discover() {
|
|
16387
16993
|
if (!isSourceEnabled("opencode", "todos"))
|
|
16388
16994
|
return;
|
|
16389
|
-
if (!
|
|
16995
|
+
if (!existsSync31(this.dbPath))
|
|
16390
16996
|
return;
|
|
16391
16997
|
let db;
|
|
16392
16998
|
try {
|
|
@@ -16435,7 +17041,7 @@ var init_opencode_todo_source = __esm({
|
|
|
16435
17041
|
}
|
|
16436
17042
|
}
|
|
16437
17043
|
async parse(item) {
|
|
16438
|
-
if (!
|
|
17044
|
+
if (!existsSync31(this.dbPath))
|
|
16439
17045
|
return [];
|
|
16440
17046
|
const sessionId = item.extra?.sessionId || item.id.replace(`${opencodeBackend.idPrefix}todo_`, "");
|
|
16441
17047
|
const db = openSqliteReadonlyOrThrow(this.dbPath);
|
|
@@ -16483,7 +17089,7 @@ var init_opencode_todo_source = __esm({
|
|
|
16483
17089
|
});
|
|
16484
17090
|
|
|
16485
17091
|
// ../engine/dist/parsers/codex-session-source.js
|
|
16486
|
-
import { existsSync as
|
|
17092
|
+
import { existsSync as existsSync32, readdirSync as readdirSync23, readFileSync as readFileSync22, statSync as statSync27 } from "fs";
|
|
16487
17093
|
import { join as join31, basename as basename16 } from "path";
|
|
16488
17094
|
function getCodexSessionsDir() {
|
|
16489
17095
|
return codexBackend.sessionsDir();
|
|
@@ -16540,7 +17146,7 @@ var init_codex_session_source = __esm({
|
|
|
16540
17146
|
async *discover() {
|
|
16541
17147
|
if (!isSourceEnabled("codex", "sessions"))
|
|
16542
17148
|
return;
|
|
16543
|
-
if (!
|
|
17149
|
+
if (!existsSync32(this.sessionsDir))
|
|
16544
17150
|
return;
|
|
16545
17151
|
const jsonlFiles = this.collectJsonlFiles(this.sessionsDir);
|
|
16546
17152
|
for (const filePath of jsonlFiles) {
|
|
@@ -16599,7 +17205,7 @@ var init_codex_session_source = __esm({
|
|
|
16599
17205
|
}
|
|
16600
17206
|
}
|
|
16601
17207
|
async parse(item) {
|
|
16602
|
-
if (!
|
|
17208
|
+
if (!existsSync32(item.filePath))
|
|
16603
17209
|
return [];
|
|
16604
17210
|
const events = readJsonlLines(item.filePath);
|
|
16605
17211
|
const chunks = [];
|
|
@@ -16702,7 +17308,7 @@ var init_codex_session_source = __esm({
|
|
|
16702
17308
|
}
|
|
16703
17309
|
collectJsonlFiles(dir) {
|
|
16704
17310
|
const results = [];
|
|
16705
|
-
if (!
|
|
17311
|
+
if (!existsSync32(dir))
|
|
16706
17312
|
return results;
|
|
16707
17313
|
for (const entry of readdirSync23(dir, { withFileTypes: true })) {
|
|
16708
17314
|
const fullPath = join31(dir, entry.name);
|
|
@@ -16719,7 +17325,7 @@ var init_codex_session_source = __esm({
|
|
|
16719
17325
|
});
|
|
16720
17326
|
|
|
16721
17327
|
// ../engine/dist/parsers/diary-source.js
|
|
16722
|
-
import { existsSync as
|
|
17328
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync6, readdirSync as readdirSync24, readFileSync as readFileSync23, writeFileSync as writeFileSync5, statSync as statSync28 } from "fs";
|
|
16723
17329
|
import { join as join32, basename as basename17 } from "path";
|
|
16724
17330
|
var MAX_CHUNK_CHARS10, DiarySource;
|
|
16725
17331
|
var init_diary_source = __esm({
|
|
@@ -16735,7 +17341,7 @@ var init_diary_source = __esm({
|
|
|
16735
17341
|
}
|
|
16736
17342
|
/** Discover all diary entries across all agents. */
|
|
16737
17343
|
async *discover() {
|
|
16738
|
-
if (!
|
|
17344
|
+
if (!existsSync33(this.diaryDir))
|
|
16739
17345
|
return;
|
|
16740
17346
|
const agents = readdirSync24(this.diaryDir, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
16741
17347
|
for (const agentDir of agents) {
|
|
@@ -16770,7 +17376,7 @@ var init_diary_source = __esm({
|
|
|
16770
17376
|
}
|
|
16771
17377
|
}
|
|
16772
17378
|
async parse(item) {
|
|
16773
|
-
if (!
|
|
17379
|
+
if (!existsSync33(item.filePath))
|
|
16774
17380
|
return [];
|
|
16775
17381
|
const raw = readFileSync23(item.filePath, "utf-8");
|
|
16776
17382
|
const entry = JSON.parse(raw);
|
|
@@ -16810,7 +17416,7 @@ var init_diary_source = __esm({
|
|
|
16810
17416
|
static write(entry, diaryDir) {
|
|
16811
17417
|
const dir = diaryDir || getDiaryDir();
|
|
16812
17418
|
const agentDir = join32(dir, entry.agent.toLowerCase().replace(/[^a-z0-9_-]/g, "_"));
|
|
16813
|
-
if (!
|
|
17419
|
+
if (!existsSync33(agentDir)) {
|
|
16814
17420
|
mkdirSync6(agentDir, { recursive: true });
|
|
16815
17421
|
}
|
|
16816
17422
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
@@ -16829,7 +17435,7 @@ var init_diary_source = __esm({
|
|
|
16829
17435
|
static read(agentName, lastN = 10, diaryDir) {
|
|
16830
17436
|
const dir = diaryDir || getDiaryDir();
|
|
16831
17437
|
const agentDir = join32(dir, agentName.toLowerCase().replace(/[^a-z0-9_-]/g, "_"));
|
|
16832
|
-
if (!
|
|
17438
|
+
if (!existsSync33(agentDir))
|
|
16833
17439
|
return [];
|
|
16834
17440
|
const files = readdirSync24(agentDir).filter((f) => f.endsWith(".json")).sort().reverse().slice(0, lastN);
|
|
16835
17441
|
const entries = [];
|
|
@@ -16880,7 +17486,7 @@ var init_redact_inline = __esm({
|
|
|
16880
17486
|
});
|
|
16881
17487
|
|
|
16882
17488
|
// ../engine/dist/parsers/skills-source.js
|
|
16883
|
-
import { existsSync as
|
|
17489
|
+
import { existsSync as existsSync34, readdirSync as readdirSync25, readFileSync as readFileSync24, statSync as statSync29 } from "fs";
|
|
16884
17490
|
import { homedir as homedir12 } from "os";
|
|
16885
17491
|
import { join as join33 } from "path";
|
|
16886
17492
|
function rebuildBody(content) {
|
|
@@ -16920,7 +17526,7 @@ function resolveRoots() {
|
|
|
16920
17526
|
all.push({ path: join33(cursorHomeDir(), "skills"), tool: "cursor" });
|
|
16921
17527
|
all.push({ path: join33(cursorHomeDir(), "skills-cursor"), tool: "cursor", readonly: true });
|
|
16922
17528
|
}
|
|
16923
|
-
return all.filter((r) =>
|
|
17529
|
+
return all.filter((r) => existsSync34(r.path));
|
|
16924
17530
|
}
|
|
16925
17531
|
function parseFrontmatter3(text) {
|
|
16926
17532
|
const m = text.match(/^---\n([\s\S]*?)\n---/);
|
|
@@ -16962,7 +17568,7 @@ var init_skills_source = __esm({
|
|
|
16962
17568
|
return;
|
|
16963
17569
|
for (const { name: pluginName, dir } of codexBackend.installedPluginDirs()) {
|
|
16964
17570
|
const skillsDir = join33(dir, "skills");
|
|
16965
|
-
if (!
|
|
17571
|
+
if (!existsSync34(skillsDir))
|
|
16966
17572
|
continue;
|
|
16967
17573
|
yield* this.fromSkillRoot({ path: skillsDir, tool: "codex" }, pluginName);
|
|
16968
17574
|
}
|
|
@@ -16987,7 +17593,7 @@ var init_skills_source = __esm({
|
|
|
16987
17593
|
if (!st.isDirectory())
|
|
16988
17594
|
continue;
|
|
16989
17595
|
const skillMd = join33(skillDir, "SKILL.md");
|
|
16990
|
-
if (!
|
|
17596
|
+
if (!existsSync34(skillMd))
|
|
16991
17597
|
continue;
|
|
16992
17598
|
let content;
|
|
16993
17599
|
try {
|
|
@@ -17052,7 +17658,7 @@ var init_skills_source = __esm({
|
|
|
17052
17658
|
}
|
|
17053
17659
|
}
|
|
17054
17660
|
async parse(item) {
|
|
17055
|
-
if (!
|
|
17661
|
+
if (!existsSync34(item.filePath))
|
|
17056
17662
|
return [];
|
|
17057
17663
|
const content = readFileSync24(item.filePath, "utf-8");
|
|
17058
17664
|
if (!content.trim())
|
|
@@ -17077,11 +17683,11 @@ var init_skills_source = __esm({
|
|
|
17077
17683
|
});
|
|
17078
17684
|
|
|
17079
17685
|
// ../engine/dist/parsers/mcps-source.js
|
|
17080
|
-
import { existsSync as
|
|
17686
|
+
import { existsSync as existsSync35, readFileSync as readFileSync25, statSync as statSync30 } from "fs";
|
|
17081
17687
|
import { homedir as homedir13 } from "os";
|
|
17082
17688
|
import { join as join34 } from "path";
|
|
17083
17689
|
function readJson(path) {
|
|
17084
|
-
if (!
|
|
17690
|
+
if (!existsSync35(path))
|
|
17085
17691
|
return null;
|
|
17086
17692
|
try {
|
|
17087
17693
|
const raw = readFileSync25(path, "utf-8");
|
|
@@ -17244,7 +17850,7 @@ var init_mcps_source = __esm({
|
|
|
17244
17850
|
}
|
|
17245
17851
|
}
|
|
17246
17852
|
async *fromCodexToml(path) {
|
|
17247
|
-
if (!
|
|
17853
|
+
if (!existsSync35(path))
|
|
17248
17854
|
return;
|
|
17249
17855
|
let content;
|
|
17250
17856
|
try {
|
|
@@ -17417,7 +18023,7 @@ var init_toolkit_format = __esm({
|
|
|
17417
18023
|
});
|
|
17418
18024
|
|
|
17419
18025
|
// ../engine/dist/parsers/slash-commands-source.js
|
|
17420
|
-
import { existsSync as
|
|
18026
|
+
import { existsSync as existsSync36, readdirSync as readdirSync26, readFileSync as readFileSync26, statSync as statSync31 } from "fs";
|
|
17421
18027
|
import { join as join35, basename as basename18 } from "path";
|
|
17422
18028
|
function rebuildBody2(content) {
|
|
17423
18029
|
const { text, redacted } = redactInlineSecrets(content);
|
|
@@ -17470,14 +18076,14 @@ var init_slash_commands_source = __esm({
|
|
|
17470
18076
|
if (isSourceEnabled("claude", "commands")) {
|
|
17471
18077
|
roots.push({ path: claudeBackend.commandsDir(), tool: "claude", scope: "user", projectPath: "", format: "md" });
|
|
17472
18078
|
const projectsRoot = claudeBackend.projectsDir();
|
|
17473
|
-
if (
|
|
18079
|
+
if (existsSync36(projectsRoot)) {
|
|
17474
18080
|
try {
|
|
17475
18081
|
for (const entry of readdirSync26(projectsRoot, { withFileTypes: true })) {
|
|
17476
18082
|
if (!entry.isDirectory() || entry.name.startsWith("."))
|
|
17477
18083
|
continue;
|
|
17478
18084
|
const projectPath = resolveProjectDirName(entry.name);
|
|
17479
18085
|
const cmdDir = join35(projectPath, ".claude", "commands");
|
|
17480
|
-
if (
|
|
18086
|
+
if (existsSync36(cmdDir))
|
|
17481
18087
|
roots.push({ path: cmdDir, tool: "claude", scope: "project", projectPath, format: "md" });
|
|
17482
18088
|
}
|
|
17483
18089
|
} catch {
|
|
@@ -17539,7 +18145,7 @@ var init_slash_commands_source = __esm({
|
|
|
17539
18145
|
}
|
|
17540
18146
|
}
|
|
17541
18147
|
async parse(item) {
|
|
17542
|
-
if (!
|
|
18148
|
+
if (!existsSync36(item.filePath))
|
|
17543
18149
|
return [];
|
|
17544
18150
|
const content = readFileSync26(item.filePath, "utf-8");
|
|
17545
18151
|
if (!content.trim())
|
|
@@ -17564,7 +18170,7 @@ var init_slash_commands_source = __esm({
|
|
|
17564
18170
|
});
|
|
17565
18171
|
|
|
17566
18172
|
// ../engine/dist/parsers/subagents-source.js
|
|
17567
|
-
import { existsSync as
|
|
18173
|
+
import { existsSync as existsSync37, readdirSync as readdirSync27, readFileSync as readFileSync27, statSync as statSync32 } from "fs";
|
|
17568
18174
|
import { join as join36, basename as basename19 } from "path";
|
|
17569
18175
|
function rebuildBody3(content) {
|
|
17570
18176
|
const { text, redacted } = redactInlineSecrets(content);
|
|
@@ -17619,14 +18225,14 @@ var init_subagents_source = __esm({
|
|
|
17619
18225
|
if (isSourceEnabled("claude", "agents")) {
|
|
17620
18226
|
roots.push({ path: claudeBackend.agentsDir(), tool: "claude", scope: "user", projectPath: "", format: "md" });
|
|
17621
18227
|
const projectsRoot = claudeBackend.projectsDir();
|
|
17622
|
-
if (
|
|
18228
|
+
if (existsSync37(projectsRoot)) {
|
|
17623
18229
|
try {
|
|
17624
18230
|
for (const entry of readdirSync27(projectsRoot, { withFileTypes: true })) {
|
|
17625
18231
|
if (!entry.isDirectory() || entry.name.startsWith("."))
|
|
17626
18232
|
continue;
|
|
17627
18233
|
const projectPath = resolveProjectDirName(entry.name);
|
|
17628
18234
|
const agentDir = join36(projectPath, ".claude", "agents");
|
|
17629
|
-
if (
|
|
18235
|
+
if (existsSync37(agentDir))
|
|
17630
18236
|
roots.push({ path: agentDir, tool: "claude", scope: "project", projectPath, format: "md" });
|
|
17631
18237
|
}
|
|
17632
18238
|
} catch {
|
|
@@ -17689,7 +18295,7 @@ var init_subagents_source = __esm({
|
|
|
17689
18295
|
}
|
|
17690
18296
|
}
|
|
17691
18297
|
async parse(item) {
|
|
17692
|
-
if (!
|
|
18298
|
+
if (!existsSync37(item.filePath))
|
|
17693
18299
|
return [];
|
|
17694
18300
|
const content = readFileSync27(item.filePath, "utf-8");
|
|
17695
18301
|
if (!content.trim())
|
|
@@ -17714,10 +18320,10 @@ var init_subagents_source = __esm({
|
|
|
17714
18320
|
});
|
|
17715
18321
|
|
|
17716
18322
|
// ../engine/dist/parsers/hooks-source.js
|
|
17717
|
-
import { existsSync as
|
|
18323
|
+
import { existsSync as existsSync38, readFileSync as readFileSync28, readdirSync as readdirSync28, statSync as statSync33 } from "fs";
|
|
17718
18324
|
import { join as join37 } from "path";
|
|
17719
18325
|
function readJson2(path) {
|
|
17720
|
-
if (!
|
|
18326
|
+
if (!existsSync38(path))
|
|
17721
18327
|
return null;
|
|
17722
18328
|
try {
|
|
17723
18329
|
return JSON.parse(readFileSync28(path, "utf-8"));
|
|
@@ -17739,14 +18345,14 @@ var init_hooks_source = __esm({
|
|
|
17739
18345
|
return;
|
|
17740
18346
|
yield* this.fromSettings(claudeBackend.settingsFile(), "user", "");
|
|
17741
18347
|
const projectsRoot = claudeBackend.projectsDir();
|
|
17742
|
-
if (
|
|
18348
|
+
if (existsSync38(projectsRoot)) {
|
|
17743
18349
|
try {
|
|
17744
18350
|
for (const entry of readdirSync28(projectsRoot, { withFileTypes: true })) {
|
|
17745
18351
|
if (!entry.isDirectory() || entry.name.startsWith("."))
|
|
17746
18352
|
continue;
|
|
17747
18353
|
const projectPath = resolveProjectDirName(entry.name);
|
|
17748
18354
|
const settingsPath2 = join37(projectPath, ".claude", "settings.json");
|
|
17749
|
-
if (
|
|
18355
|
+
if (existsSync38(settingsPath2)) {
|
|
17750
18356
|
yield* this.fromSettings(settingsPath2, "project", projectPath);
|
|
17751
18357
|
}
|
|
17752
18358
|
}
|
|
@@ -17837,11 +18443,11 @@ var init_hooks_source = __esm({
|
|
|
17837
18443
|
});
|
|
17838
18444
|
|
|
17839
18445
|
// ../engine/dist/parsers/plugins-source.js
|
|
17840
|
-
import { existsSync as
|
|
18446
|
+
import { existsSync as existsSync39, readFileSync as readFileSync29, readdirSync as readdirSync29, statSync as statSync34 } from "fs";
|
|
17841
18447
|
import { homedir as homedir14 } from "os";
|
|
17842
18448
|
import { join as join38 } from "path";
|
|
17843
18449
|
function readJson3(path) {
|
|
17844
|
-
if (!
|
|
18450
|
+
if (!existsSync39(path))
|
|
17845
18451
|
return null;
|
|
17846
18452
|
try {
|
|
17847
18453
|
return JSON.parse(readFileSync29(path, "utf-8"));
|
|
@@ -17896,7 +18502,7 @@ var init_plugins_source = __esm({
|
|
|
17896
18502
|
}
|
|
17897
18503
|
}
|
|
17898
18504
|
const gemRoot = agyBackend.sharedExtensionsDir();
|
|
17899
|
-
if (isSourceEnabled("agy", "extensions") &&
|
|
18505
|
+
if (isSourceEnabled("agy", "extensions") && existsSync39(gemRoot)) {
|
|
17900
18506
|
let entries;
|
|
17901
18507
|
try {
|
|
17902
18508
|
entries = readdirSync29(gemRoot);
|
|
@@ -18072,6 +18678,8 @@ function toolOfId(id) {
|
|
|
18072
18678
|
return "codex";
|
|
18073
18679
|
if (id.startsWith("cursor_"))
|
|
18074
18680
|
return "cursor";
|
|
18681
|
+
if (id.startsWith("hermes_"))
|
|
18682
|
+
return "hermes";
|
|
18075
18683
|
return "claude";
|
|
18076
18684
|
}
|
|
18077
18685
|
function extractorVersionForTool(tool) {
|
|
@@ -18372,6 +18980,8 @@ function markSynced(server, rows) {
|
|
|
18372
18980
|
else if (prev?.F !== void 0) base3.F = prev.F;
|
|
18373
18981
|
if (cursorFromCaller && r.chunkedHead) base3.k = 1;
|
|
18374
18982
|
else if (prev?.k && !completesChunked && !(cursorFromCaller && r.full)) base3.k = 1;
|
|
18983
|
+
const layout = cursorFromCaller ? r.layout : prev?.L;
|
|
18984
|
+
if (layout) base3.L = layout;
|
|
18375
18985
|
forServer[r.id] = base3;
|
|
18376
18986
|
}
|
|
18377
18987
|
persist(data);
|
|
@@ -18529,12 +19139,12 @@ var init_sync_fields = __esm({
|
|
|
18529
19139
|
});
|
|
18530
19140
|
|
|
18531
19141
|
// ../engine/dist/core/index-lock.js
|
|
18532
|
-
import { existsSync as
|
|
19142
|
+
import { existsSync as existsSync40, mkdirSync as mkdirSync8, openSync as openSync8, writeFileSync as writeFileSync7, readFileSync as readFileSync31, rmSync as rmSync4, statSync as statSync36, closeSync as closeSync8 } from "fs";
|
|
18533
19143
|
import { dirname as dirname17, join as join40 } from "path";
|
|
18534
19144
|
function acquireIndexLock(opts) {
|
|
18535
19145
|
const lockPath = lockFilePath(opts.file);
|
|
18536
19146
|
mkdirSync8(dirname17(lockPath), { recursive: true });
|
|
18537
|
-
if (
|
|
19147
|
+
if (existsSync40(lockPath)) {
|
|
18538
19148
|
if (!stealStaleLock(lockPath, opts.staleAfterMs ?? 10 * 6e4)) {
|
|
18539
19149
|
return null;
|
|
18540
19150
|
}
|
|
@@ -18642,7 +19252,7 @@ var init_http = __esm({
|
|
|
18642
19252
|
CLI_VERSION = JSON.parse(readFileSync32(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
|
|
18643
19253
|
} catch {
|
|
18644
19254
|
try {
|
|
18645
|
-
if (true) CLI_VERSION = "0.7.
|
|
19255
|
+
if (true) CLI_VERSION = "0.7.19";
|
|
18646
19256
|
} catch {
|
|
18647
19257
|
}
|
|
18648
19258
|
}
|
|
@@ -18739,7 +19349,7 @@ var init_derived = __esm({
|
|
|
18739
19349
|
|
|
18740
19350
|
// src/scan-pool.ts
|
|
18741
19351
|
import { Worker } from "node:worker_threads";
|
|
18742
|
-
import { existsSync as
|
|
19352
|
+
import { existsSync as existsSync41 } from "node:fs";
|
|
18743
19353
|
import { fileURLToPath } from "node:url";
|
|
18744
19354
|
import { cpus } from "node:os";
|
|
18745
19355
|
function poolSize() {
|
|
@@ -18754,7 +19364,7 @@ function workerScript() {
|
|
|
18754
19364
|
for (const rel of ["./scan-worker.js", "../dist/scan-worker.js"]) {
|
|
18755
19365
|
try {
|
|
18756
19366
|
const p = fileURLToPath(new URL(rel, import.meta.url));
|
|
18757
|
-
if (
|
|
19367
|
+
if (existsSync41(p)) return p;
|
|
18758
19368
|
} catch {
|
|
18759
19369
|
}
|
|
18760
19370
|
}
|
|
@@ -19136,7 +19746,7 @@ var init_telemetry = __esm({
|
|
|
19136
19746
|
init_sync_client();
|
|
19137
19747
|
cliVersion = () => {
|
|
19138
19748
|
try {
|
|
19139
|
-
return true ? "0.7.
|
|
19749
|
+
return true ? "0.7.19" : "dev";
|
|
19140
19750
|
} catch {
|
|
19141
19751
|
return "dev";
|
|
19142
19752
|
}
|
|
@@ -19516,7 +20126,7 @@ __export(auto_update_exports, {
|
|
|
19516
20126
|
tarballUrl: () => tarballUrl
|
|
19517
20127
|
});
|
|
19518
20128
|
import { execSync as execSync2, execFileSync as execFileSync3 } from "node:child_process";
|
|
19519
|
-
import { readFileSync as readFileSync35, existsSync as
|
|
20129
|
+
import { readFileSync as readFileSync35, existsSync as existsSync42 } from "node:fs";
|
|
19520
20130
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
19521
20131
|
import { writeFileSync as writeFileSync8, mkdtempSync as mkdtempSync3, rmSync as rmSync6, readdirSync as readdirSync30, statSync as statSync38, mkdirSync as mkdirSync9 } from "node:fs";
|
|
19522
20132
|
import { join as join42, dirname as dirname18, sep as sep2, posix as pathPosix, win32 as pathWin32 } from "node:path";
|
|
@@ -19677,7 +20287,7 @@ function resolveNpm(loc) {
|
|
|
19677
20287
|
}
|
|
19678
20288
|
function realInstall(tgz) {
|
|
19679
20289
|
const prefix = runningPrefix();
|
|
19680
|
-
const npm = resolveNpm({ execPath: process.execPath, prefix, platform: process.platform, env: process.env, exists:
|
|
20290
|
+
const npm = resolveNpm({ execPath: process.execPath, prefix, platform: process.platform, env: process.env, exists: existsSync42 });
|
|
19681
20291
|
if (prefix) {
|
|
19682
20292
|
npmInstall(npm, ["install", "-g", "--prefix", prefix, tgz]);
|
|
19683
20293
|
return;
|
|
@@ -20435,6 +21045,11 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20435
21045
|
};
|
|
20436
21046
|
const localSessionIds = /* @__PURE__ */ new Set();
|
|
20437
21047
|
const shippedHash = /* @__PURE__ */ new Map();
|
|
21048
|
+
const shippedLayout = /* @__PURE__ */ new Map();
|
|
21049
|
+
const layoutOf = (id) => {
|
|
21050
|
+
const layout = shippedLayout.get(id);
|
|
21051
|
+
return layout ? { layout } : {};
|
|
21052
|
+
};
|
|
20438
21053
|
const makeBatcher = (field, maxItems, flatten = false, onFlush, barrier) => {
|
|
20439
21054
|
let batch = [];
|
|
20440
21055
|
let batchBytes = 0;
|
|
@@ -20467,7 +21082,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20467
21082
|
markSynced(base3, rows.map((r) => {
|
|
20468
21083
|
const off = typeof r.from_offset === "number" ? r.from_offset : 0;
|
|
20469
21084
|
const hash = shippedHash.get(r.session_id);
|
|
20470
|
-
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 };
|
|
21085
|
+
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 };
|
|
20471
21086
|
}));
|
|
20472
21087
|
} catch {
|
|
20473
21088
|
}
|
|
@@ -20510,8 +21125,9 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20510
21125
|
// size = new offset (file grew to here)
|
|
20511
21126
|
acked: true,
|
|
20512
21127
|
// server merged this tail
|
|
20513
|
-
chunkFinal: c.final === true
|
|
21128
|
+
chunkFinal: c.final === true,
|
|
20514
21129
|
// completes a chunked full sync
|
|
21130
|
+
...layoutOf(c.session_id)
|
|
20515
21131
|
})));
|
|
20516
21132
|
} catch {
|
|
20517
21133
|
}
|
|
@@ -20543,9 +21159,9 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20543
21159
|
const mtime = conv.mtime;
|
|
20544
21160
|
try {
|
|
20545
21161
|
if (staged || !guarded) {
|
|
20546
|
-
markSynced(base3, [{ id, mtime, offset: conv.from_offset, size: conv.from_offset, acked: true, chunkedHead: true }]);
|
|
21162
|
+
markSynced(base3, [{ id, mtime, offset: conv.from_offset, size: conv.from_offset, acked: true, chunkedHead: true, ...layoutOf(id) }]);
|
|
20547
21163
|
} else if (typeof guarded.o === "number" && guarded.o > 0 && guarded.o <= fileSize) {
|
|
20548
|
-
markSynced(base3, [{ id, mtime, offset: guarded.o, size: guarded.o, acked: true, chunkedHead: true }]);
|
|
21164
|
+
markSynced(base3, [{ id, mtime, offset: guarded.o, size: guarded.o, acked: true, chunkedHead: true, ...layoutOf(id) }]);
|
|
20549
21165
|
} else {
|
|
20550
21166
|
markSynced(base3, [{ id, mtime }]);
|
|
20551
21167
|
}
|
|
@@ -20640,8 +21256,8 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20640
21256
|
if (!ledger) return ref.mtime >= (opts.sinceMs ?? 0) ? "full" : "skip";
|
|
20641
21257
|
const ack = ledger.get(ref.prefixedId);
|
|
20642
21258
|
const backend = backendFor(ref);
|
|
20643
|
-
const
|
|
20644
|
-
const isAO = !!backend?.isAppendOnly?.() &&
|
|
21259
|
+
const sameLayout = (ack?.L ?? "") === (backend?.sourceLayout?.(ref.prefixedId) ?? "");
|
|
21260
|
+
const isAO = !!backend?.isAppendOnly?.() && sameLayout;
|
|
20645
21261
|
const size = isAO ? backend?.fileSize?.(ref.prefixedId) ?? 0 : 0;
|
|
20646
21262
|
return syncMode(ack, ref.mtime, size, extractorVersionForTool(ref.toolId), isAO);
|
|
20647
21263
|
};
|
|
@@ -20688,6 +21304,9 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20688
21304
|
skipped++;
|
|
20689
21305
|
continue;
|
|
20690
21306
|
}
|
|
21307
|
+
const layout = backendFor(ref)?.sourceLayout?.(ref.prefixedId) ?? "";
|
|
21308
|
+
if (layout) shippedLayout.set(ref.prefixedId, layout);
|
|
21309
|
+
else shippedLayout.delete(ref.prefixedId);
|
|
20691
21310
|
trace?.(`build (${mode}) ${ref.prefixedId} \xB7 ${(sessionFileBytes(ref) / 1048576).toFixed(1)}MB`);
|
|
20692
21311
|
let promotedForFindings = false;
|
|
20693
21312
|
if (mode === "append" && ledger) {
|
|
@@ -20733,7 +21352,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20733
21352
|
const off = getBackendForId(ref.prefixedId)?.fileSize?.(ref.rawId) ?? 0;
|
|
20734
21353
|
const priorCursor = ackRow?.s ?? 0;
|
|
20735
21354
|
const safeToAck = off > 0 && off <= priorCursor;
|
|
20736
|
-
markSynced(base3, [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 }]);
|
|
21355
|
+
markSynced(base3, [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 }]);
|
|
20737
21356
|
} catch {
|
|
20738
21357
|
}
|
|
20739
21358
|
}
|
|
@@ -21488,7 +22107,7 @@ var init_sync_client = __esm({
|
|
|
21488
22107
|
ownVersion = JSON.parse(readFileSync36(join43(dir, "../package.json"), "utf-8")).version || ownVersion;
|
|
21489
22108
|
} catch {
|
|
21490
22109
|
try {
|
|
21491
|
-
if (true) ownVersion = "0.7.
|
|
22110
|
+
if (true) ownVersion = "0.7.19";
|
|
21492
22111
|
} catch {
|
|
21493
22112
|
}
|
|
21494
22113
|
}
|
|
@@ -21666,7 +22285,7 @@ var init_artifact_codec = __esm({
|
|
|
21666
22285
|
});
|
|
21667
22286
|
|
|
21668
22287
|
// ../engine/dist/core/toolkit-sync.js
|
|
21669
|
-
import { existsSync as
|
|
22288
|
+
import { existsSync as existsSync43, mkdirSync as mkdirSync11, readFileSync as readFileSync38, writeFileSync as writeFileSync10, cpSync } from "fs";
|
|
21670
22289
|
import { dirname as dirname20, join as join45, basename as basename22 } from "path";
|
|
21671
22290
|
import { homedir as homedir17 } from "os";
|
|
21672
22291
|
function rowFromMemoryItem(type, item) {
|
|
@@ -21700,11 +22319,11 @@ function skillsDirFor(tool) {
|
|
|
21700
22319
|
}
|
|
21701
22320
|
function copySkill(row, toTool) {
|
|
21702
22321
|
const skillDir = row.extra.skillDir || dirname20(row.filePath);
|
|
21703
|
-
if (!
|
|
22322
|
+
if (!existsSync43(skillDir))
|
|
21704
22323
|
return { ok: false, status: 404, error: `Source dir missing: ${skillDir}` };
|
|
21705
22324
|
const name = row.extra.skillName || basename22(skillDir);
|
|
21706
22325
|
const targetDir = join45(skillsDirFor(toTool), name);
|
|
21707
|
-
if (
|
|
22326
|
+
if (existsSync43(targetDir))
|
|
21708
22327
|
return { ok: false, status: 409, error: `Already exists: ${targetDir}` };
|
|
21709
22328
|
try {
|
|
21710
22329
|
mkdirSync11(dirname20(targetDir), { recursive: true });
|
|
@@ -21736,7 +22355,7 @@ function readMcpEntry(tool, name) {
|
|
|
21736
22355
|
return entry;
|
|
21737
22356
|
}
|
|
21738
22357
|
for (const t of tries) {
|
|
21739
|
-
if (!
|
|
22358
|
+
if (!existsSync43(t.path))
|
|
21740
22359
|
continue;
|
|
21741
22360
|
try {
|
|
21742
22361
|
const cfg = JSON.parse(readFileSync38(t.path, "utf-8"));
|
|
@@ -21749,7 +22368,7 @@ function readMcpEntry(tool, name) {
|
|
|
21749
22368
|
return null;
|
|
21750
22369
|
}
|
|
21751
22370
|
function readCodexMcpEntry(path, target) {
|
|
21752
|
-
if (!
|
|
22371
|
+
if (!existsSync43(path))
|
|
21753
22372
|
return null;
|
|
21754
22373
|
let content;
|
|
21755
22374
|
try {
|
|
@@ -21803,7 +22422,7 @@ function readCodexMcpEntry(path, target) {
|
|
|
21803
22422
|
}
|
|
21804
22423
|
function writeCodexMcpEntry(path, name, entry) {
|
|
21805
22424
|
let content = "";
|
|
21806
|
-
if (
|
|
22425
|
+
if (existsSync43(path))
|
|
21807
22426
|
content = readFileSync38(path, "utf-8");
|
|
21808
22427
|
const header = `[mcp_servers.${name}]`;
|
|
21809
22428
|
if (content.includes(header))
|
|
@@ -21861,7 +22480,7 @@ function writeMcpEntry(toTool, name, entry) {
|
|
|
21861
22480
|
key2 = "mcp";
|
|
21862
22481
|
}
|
|
21863
22482
|
let cfg = {};
|
|
21864
|
-
if (
|
|
22483
|
+
if (existsSync43(path)) {
|
|
21865
22484
|
try {
|
|
21866
22485
|
cfg = JSON.parse(readFileSync38(path, "utf-8"));
|
|
21867
22486
|
} catch {
|
|
@@ -21925,7 +22544,7 @@ function copyCommandOrAgent(type, row, toTool) {
|
|
|
21925
22544
|
return { ok: false, status: 404, error: `Source unreadable: ${e instanceof Error ? e.message : "failed"}` };
|
|
21926
22545
|
}
|
|
21927
22546
|
const out = emit(type, art, toTool);
|
|
21928
|
-
if (
|
|
22547
|
+
if (existsSync43(out.path))
|
|
21929
22548
|
return { ok: false, status: 409, error: `Already exists: ${out.path}` };
|
|
21930
22549
|
try {
|
|
21931
22550
|
mkdirSync11(dirname20(out.path), { recursive: true });
|
|
@@ -21945,7 +22564,7 @@ function copyInstructions(row, toTool) {
|
|
|
21945
22564
|
return { ok: false, status: 404, error: `Source unreadable: ${e instanceof Error ? e.message : "failed"}` };
|
|
21946
22565
|
}
|
|
21947
22566
|
const out = emit("instructions", art, toTool, row.projectPath || void 0);
|
|
21948
|
-
if (
|
|
22567
|
+
if (existsSync43(out.path))
|
|
21949
22568
|
return { ok: false, status: 409, error: `Already exists: ${out.path}` };
|
|
21950
22569
|
try {
|
|
21951
22570
|
mkdirSync11(dirname20(out.path), { recursive: true });
|
|
@@ -22088,7 +22707,7 @@ var init_toolkit_sync = __esm({
|
|
|
22088
22707
|
});
|
|
22089
22708
|
|
|
22090
22709
|
// ../engine/dist/core/which.js
|
|
22091
|
-
import { existsSync as
|
|
22710
|
+
import { existsSync as existsSync45, statSync as statSync41, accessSync, constants } from "node:fs";
|
|
22092
22711
|
import { join as join47, isAbsolute as isAbsolute2, delimiter as delimiter2, sep as sep3 } from "node:path";
|
|
22093
22712
|
function executable(p) {
|
|
22094
22713
|
try {
|
|
@@ -22129,7 +22748,7 @@ function resolveOnPath(name) {
|
|
|
22129
22748
|
continue;
|
|
22130
22749
|
for (const c of candidates(name)) {
|
|
22131
22750
|
const full = join47(dir, c);
|
|
22132
|
-
if (
|
|
22751
|
+
if (existsSync45(full) && executable(full))
|
|
22133
22752
|
return full;
|
|
22134
22753
|
}
|
|
22135
22754
|
}
|
|
@@ -22155,7 +22774,7 @@ __export(toolkit_pull_exports, {
|
|
|
22155
22774
|
platformRefusal: () => platformRefusal,
|
|
22156
22775
|
portableCommand: () => portableCommand
|
|
22157
22776
|
});
|
|
22158
|
-
import { existsSync as
|
|
22777
|
+
import { existsSync as existsSync46, mkdirSync as mkdirSync13, statSync as statSync42, writeFileSync as writeFileSync12 } from "node:fs";
|
|
22159
22778
|
import { dirname as dirname22, join as join48, basename as basename23, isAbsolute as isAbsolute3 } from "node:path";
|
|
22160
22779
|
function isExecutableFile(p) {
|
|
22161
22780
|
try {
|
|
@@ -22328,7 +22947,7 @@ function executePull(rows, opts = {}) {
|
|
|
22328
22947
|
for (const tool of tools) {
|
|
22329
22948
|
const dir = join48(skillsDirFor(tool), name);
|
|
22330
22949
|
const file = join48(dir, "SKILL.md");
|
|
22331
|
-
if (
|
|
22950
|
+
if (existsSync46(file)) {
|
|
22332
22951
|
outcomes.push({ type: "skill", name, tool, status: "present" });
|
|
22333
22952
|
continue;
|
|
22334
22953
|
}
|
|
@@ -22373,7 +22992,7 @@ function executePull(rows, opts = {}) {
|
|
|
22373
22992
|
outcomes.push({ type, name, tool, status: "failed", reason: e instanceof Error ? e.message : "emit failed" });
|
|
22374
22993
|
continue;
|
|
22375
22994
|
}
|
|
22376
|
-
if (
|
|
22995
|
+
if (existsSync46(out.path)) {
|
|
22377
22996
|
outcomes.push({ type, name, tool, status: "present" });
|
|
22378
22997
|
continue;
|
|
22379
22998
|
}
|
|
@@ -22837,7 +23456,7 @@ var init_code_intel = __esm({
|
|
|
22837
23456
|
});
|
|
22838
23457
|
|
|
22839
23458
|
// ../engine/dist/core/companions.js
|
|
22840
|
-
import { existsSync as
|
|
23459
|
+
import { existsSync as existsSync49, mkdirSync as mkdirSync16, statSync as statSync46, chmodSync as chmodSync4, unlinkSync as unlinkSync4, renameSync as renameSync5, createWriteStream as createWriteStream2, readFileSync as readFileSync43, writeFileSync as writeFileSync15 } from "node:fs";
|
|
22841
23460
|
import { homedir as homedir19 } from "node:os";
|
|
22842
23461
|
import { join as join52 } from "node:path";
|
|
22843
23462
|
import { execSync as execSync3 } from "node:child_process";
|
|
@@ -22960,7 +23579,7 @@ Refusing to install. The release may have been re-uploaded, or something is serv
|
|
|
22960
23579
|
renameSync5(tmpPath, CODEINDEX_BIN_PATH);
|
|
22961
23580
|
} catch (err) {
|
|
22962
23581
|
try {
|
|
22963
|
-
if (
|
|
23582
|
+
if (existsSync49(tmpPath))
|
|
22964
23583
|
unlinkSync4(tmpPath);
|
|
22965
23584
|
} catch {
|
|
22966
23585
|
}
|
|
@@ -24047,7 +24666,7 @@ __export(service_installer_exports, {
|
|
|
24047
24666
|
uninstallService: () => uninstallService
|
|
24048
24667
|
});
|
|
24049
24668
|
import { execSync as execSync5 } from "child_process";
|
|
24050
|
-
import { existsSync as
|
|
24669
|
+
import { existsSync as existsSync50, mkdirSync as mkdirSync17, readFileSync as readFileSync45, rmSync as rmSync8, writeFileSync as writeFileSync16 } from "fs";
|
|
24051
24670
|
import { homedir as homedir20 } from "os";
|
|
24052
24671
|
import { join as join54 } from "path";
|
|
24053
24672
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
@@ -24083,7 +24702,7 @@ function refreshServiceDefinition() {
|
|
|
24083
24702
|
try {
|
|
24084
24703
|
const { watchJs, node, logFile } = resolveDaemonPaths();
|
|
24085
24704
|
const unitPath = join54(homedir20(), ".config", "systemd", "user", "chat-recall-watch.service");
|
|
24086
|
-
if (!
|
|
24705
|
+
if (!existsSync50(unitPath)) return false;
|
|
24087
24706
|
const current = readFileSync45(unitPath, "utf8");
|
|
24088
24707
|
if (!current.includes(watchJs)) return false;
|
|
24089
24708
|
const wanted = renderSystemdUnit(watchJs, node, logFile);
|
|
@@ -24251,7 +24870,7 @@ function uninstallService() {
|
|
|
24251
24870
|
} catch {
|
|
24252
24871
|
}
|
|
24253
24872
|
const unitPath = join54(homedir20(), ".config", "systemd", "user", "chat-recall-watch.service");
|
|
24254
|
-
if (
|
|
24873
|
+
if (existsSync50(unitPath)) {
|
|
24255
24874
|
rmSync8(unitPath, { force: true });
|
|
24256
24875
|
removed = true;
|
|
24257
24876
|
}
|
|
@@ -24268,7 +24887,7 @@ function uninstallService() {
|
|
|
24268
24887
|
} catch {
|
|
24269
24888
|
}
|
|
24270
24889
|
let removed = false;
|
|
24271
|
-
if (
|
|
24890
|
+
if (existsSync50(plistPath)) {
|
|
24272
24891
|
rmSync8(plistPath, { force: true });
|
|
24273
24892
|
removed = true;
|
|
24274
24893
|
}
|
|
@@ -24326,12 +24945,12 @@ init_codex2();
|
|
|
24326
24945
|
init_cursor();
|
|
24327
24946
|
init_opencode();
|
|
24328
24947
|
init_agy();
|
|
24329
|
-
import { existsSync as
|
|
24948
|
+
import { existsSync as existsSync47, readFileSync as readFileSync40, writeFileSync as writeFileSync13, appendFileSync, mkdirSync as mkdirSync14 } from "node:fs";
|
|
24330
24949
|
import { join as join49 } from "node:path";
|
|
24331
24950
|
|
|
24332
24951
|
// src/project-tasks.ts
|
|
24333
24952
|
init_http();
|
|
24334
|
-
import { existsSync as
|
|
24953
|
+
import { existsSync as existsSync44, readFileSync as readFileSync39, writeFileSync as writeFileSync11, mkdirSync as mkdirSync12, statSync as statSync40 } from "node:fs";
|
|
24335
24954
|
import { join as join46, dirname as dirname21 } from "node:path";
|
|
24336
24955
|
import { homedir as homedir18 } from "node:os";
|
|
24337
24956
|
|
|
@@ -24439,7 +25058,7 @@ async function pushProjectTaskStatuses(base3, authHeaders, opts = {}) {
|
|
|
24439
25058
|
}
|
|
24440
25059
|
for (const project of projects) {
|
|
24441
25060
|
const file = join46(project, fk.filename);
|
|
24442
|
-
if (!
|
|
25061
|
+
if (!existsSync44(file)) continue;
|
|
24443
25062
|
let mtime;
|
|
24444
25063
|
try {
|
|
24445
25064
|
mtime = statSync40(file).mtimeMs;
|
|
@@ -24500,7 +25119,7 @@ function instructionTargets(rootPath, isGlobal) {
|
|
|
24500
25119
|
const tools = installed.length ? installed : [INSTRUCTION_TOOLS[0]];
|
|
24501
25120
|
if (isGlobal) return [...new Set(tools.map((t) => instructionsPath(t.id)))];
|
|
24502
25121
|
if (!rootPath) return [];
|
|
24503
|
-
const present = INSTRUCTION_FILENAMES.map((f) => join49(rootPath, f)).filter((p) =>
|
|
25122
|
+
const present = INSTRUCTION_FILENAMES.map((f) => join49(rootPath, f)).filter((p) => existsSync47(p));
|
|
24504
25123
|
if (present.length) return present;
|
|
24505
25124
|
return [...new Set(tools.map((t) => join49(rootPath, instructionsFilename(t.id))))];
|
|
24506
25125
|
}
|
|
@@ -24528,7 +25147,7 @@ function applyCodeRecommendation(intent) {
|
|
|
24528
25147
|
mkdirSync14(dir, { recursive: true });
|
|
24529
25148
|
} catch {
|
|
24530
25149
|
}
|
|
24531
|
-
const existing =
|
|
25150
|
+
const existing = existsSync47(file) ? readFileSync40(file, "utf8") : "";
|
|
24532
25151
|
if (existing.includes(text)) {
|
|
24533
25152
|
skipped.push(file);
|
|
24534
25153
|
continue;
|
|
@@ -24630,7 +25249,7 @@ try {
|
|
|
24630
25249
|
ownVersion2 = JSON.parse(readFileSync40(join49(dir, "../package.json"), "utf-8")).version || ownVersion2;
|
|
24631
25250
|
} catch {
|
|
24632
25251
|
try {
|
|
24633
|
-
if (true) ownVersion2 = "0.7.
|
|
25252
|
+
if (true) ownVersion2 = "0.7.19";
|
|
24634
25253
|
} catch {
|
|
24635
25254
|
}
|
|
24636
25255
|
}
|
|
@@ -24971,8 +25590,8 @@ function rotateLogIfLarge(logPath, maxBytes = LOG_MAX_BYTES) {
|
|
|
24971
25590
|
|
|
24972
25591
|
// src/collector-migrate.ts
|
|
24973
25592
|
init_http();
|
|
24974
|
-
import { existsSync as
|
|
24975
|
-
function selectProjectsToReindex(projects, current, existsFn =
|
|
25593
|
+
import { existsSync as existsSync48 } from "node:fs";
|
|
25594
|
+
function selectProjectsToReindex(projects, current, existsFn = existsSync48) {
|
|
24976
25595
|
const reindex = [];
|
|
24977
25596
|
const missing = [];
|
|
24978
25597
|
for (const p of projects) {
|
|
@@ -25014,8 +25633,8 @@ async function runCollectorMigration(opts) {
|
|
|
25014
25633
|
// auto-indexer/indexer.ts
|
|
25015
25634
|
init_sync_ledger();
|
|
25016
25635
|
init_collector_health();
|
|
25017
|
-
import { existsSync as
|
|
25018
|
-
var CLI_VERSION3 = true ? "0.7.
|
|
25636
|
+
import { existsSync as existsSync51, readFileSync as readFileSync46, statSync as statSync47 } from "fs";
|
|
25637
|
+
var CLI_VERSION3 = true ? "0.7.19" : "0.0.0";
|
|
25019
25638
|
var DEBOUNCE_MS = 5e3;
|
|
25020
25639
|
var PLANS_DIR = claudeBackend.plansDir();
|
|
25021
25640
|
var TASKS_DIR = claudeBackend.tasksDir();
|
|
@@ -25167,6 +25786,16 @@ var opencodeWatcher = chokidar.watch(
|
|
|
25167
25786
|
...POLL(1e4)
|
|
25168
25787
|
}
|
|
25169
25788
|
);
|
|
25789
|
+
var HERMES_DB_PATHS = hermesBackend.dbPaths();
|
|
25790
|
+
var hermesWatcher = chokidar.watch(
|
|
25791
|
+
HERMES_DB_PATHS.flatMap((p) => [p, `${p}-wal`]),
|
|
25792
|
+
{
|
|
25793
|
+
persistent: true,
|
|
25794
|
+
ignoreInitial: true,
|
|
25795
|
+
awaitWriteFinish: { stabilityThreshold: 2500, pollInterval: 500 },
|
|
25796
|
+
...POLL(1e4)
|
|
25797
|
+
}
|
|
25798
|
+
);
|
|
25170
25799
|
var agentMemoryWatcher = chokidar.watch(CLAUDE_SESSION_ROOTS.map((root) => `${root}/*/memory/*.md`), {
|
|
25171
25800
|
persistent: true,
|
|
25172
25801
|
ignoreInitial: true,
|
|
@@ -25187,6 +25816,7 @@ var watchers = {
|
|
|
25187
25816
|
diary: diaryWatcher,
|
|
25188
25817
|
codex: codexWatcher,
|
|
25189
25818
|
opencode: opencodeWatcher,
|
|
25819
|
+
hermes: hermesWatcher,
|
|
25190
25820
|
agentMemory: agentMemoryWatcher,
|
|
25191
25821
|
cleanup: cleanupWatcher
|
|
25192
25822
|
};
|
|
@@ -25222,6 +25852,7 @@ daemonLog.info(` Watching history: ${HISTORY_PATH}`);
|
|
|
25222
25852
|
daemonLog.info(` Watching diary: ${DIARY_DIR}`);
|
|
25223
25853
|
daemonLog.info(` Watching codex: ${CODEX_SESSIONS_DIR}`);
|
|
25224
25854
|
daemonLog.info(` Watching opencode: ${OPENCODE_DB_DIR}`);
|
|
25855
|
+
daemonLog.info(` Watching hermes: ${HERMES_DB_PATHS.join(", ")}`);
|
|
25225
25856
|
daemonLog.info(` Watching agent memory: ${CLAUDE_SESSION_ROOTS.map((root) => `${root}/*/memory/`).join(", ")}`);
|
|
25226
25857
|
daemonLog.info(` Resume-guard: ${CURRENT_RESUME_PATH}`);
|
|
25227
25858
|
daemonLog.info(` Debounce: ${DEBOUNCE_MS}ms \xB7 ships via syncIncremental() to the configured server`);
|
|
@@ -25416,7 +26047,7 @@ function discoverWorkspaces() {
|
|
|
25416
26047
|
const isExcluded = (p) => excluded.some((x) => p.includes(x));
|
|
25417
26048
|
const candidates2 = [...newest.entries()].filter(([p]) => !isExcluded(p)).filter(([p]) => !isPersonalPath(p, includeProjects)).filter(([p]) => {
|
|
25418
26049
|
try {
|
|
25419
|
-
return
|
|
26050
|
+
return existsSync51(p);
|
|
25420
26051
|
} catch {
|
|
25421
26052
|
return false;
|
|
25422
26053
|
}
|
|
@@ -25448,7 +26079,7 @@ function isCodeWorkspace(p) {
|
|
|
25448
26079
|
}
|
|
25449
26080
|
return WORKSPACE_MARKERS.some((m) => {
|
|
25450
26081
|
try {
|
|
25451
|
-
return
|
|
26082
|
+
return existsSync51(join55(p, m));
|
|
25452
26083
|
} catch {
|
|
25453
26084
|
return false;
|
|
25454
26085
|
}
|