chat-recall 0.5.27 → 0.5.29
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 +4 -4
- package/dist/cli.js +243 -136
- package/dist/cli.js.map +1 -1
- package/dist/init-progress.d.ts +52 -0
- package/dist/init-progress.d.ts.map +1 -0
- package/dist/init-progress.js +98 -0
- package/dist/init-progress.js.map +1 -0
- package/dist/init-report.d.ts +38 -0
- package/dist/init-report.d.ts.map +1 -0
- package/dist/init-report.js +53 -0
- package/dist/init-report.js.map +1 -0
- package/dist/mcp.js +225 -33
- package/dist/sync-ledger.d.ts.map +1 -1
- package/dist/sync-ledger.js +8 -2
- package/dist/sync-ledger.js.map +1 -1
- package/dist/watch.js +47 -27
- package/package.json +1 -1
- package/skills/chat-recall/SKILL.md +2 -1
- package/skills/chat-recall-project/SKILL.md +17 -0
package/dist/cli.js
CHANGED
|
@@ -7134,13 +7134,13 @@ async function parseCodexSubagents(sessionPath) {
|
|
|
7134
7134
|
if (meta?.type !== "session_meta")
|
|
7135
7135
|
continue;
|
|
7136
7136
|
const payload = meta.payload || {};
|
|
7137
|
-
const
|
|
7138
|
-
if (!
|
|
7137
|
+
const spawn4 = payload.source?.subagent?.thread_spawn;
|
|
7138
|
+
if (!spawn4)
|
|
7139
7139
|
continue;
|
|
7140
|
-
if (
|
|
7140
|
+
if (spawn4.parent_thread_id !== parentId)
|
|
7141
7141
|
continue;
|
|
7142
7142
|
const id = fileName.replace(/\.jsonl$/i, "");
|
|
7143
|
-
const role = String(
|
|
7143
|
+
const role = String(spawn4.agent_role || payload.agent_role || "").toLowerCase();
|
|
7144
7144
|
const kind = role.includes("compact") ? "compact" : role.includes("aside") ? "aside" : role.includes("worker") || role.includes("explore") ? "explore" : "other";
|
|
7145
7145
|
let messages = [];
|
|
7146
7146
|
try {
|
|
@@ -7152,8 +7152,8 @@ async function parseCodexSubagents(sessionPath) {
|
|
|
7152
7152
|
subagents.push({
|
|
7153
7153
|
id,
|
|
7154
7154
|
kind,
|
|
7155
|
-
agentType:
|
|
7156
|
-
description:
|
|
7155
|
+
agentType: spawn4.agent_role || payload.agent_role,
|
|
7156
|
+
description: spawn4.agent_nickname || payload.agent_nickname,
|
|
7157
7157
|
filePath,
|
|
7158
7158
|
messageCount: messages.length,
|
|
7159
7159
|
toolUseCount,
|
|
@@ -9781,8 +9781,8 @@ var init_codex2 = __esm({
|
|
|
9781
9781
|
} catch {
|
|
9782
9782
|
continue;
|
|
9783
9783
|
}
|
|
9784
|
-
const
|
|
9785
|
-
if (!
|
|
9784
|
+
const spawn4 = meta?.payload?.source?.subagent?.thread_spawn;
|
|
9785
|
+
if (!spawn4 || spawn4.parent_thread_id !== parentUuid)
|
|
9786
9786
|
continue;
|
|
9787
9787
|
events.push(...this.parseRollout(path));
|
|
9788
9788
|
}
|
|
@@ -9975,10 +9975,10 @@ var init_codex2 = __esm({
|
|
|
9975
9975
|
const meta = JSON.parse(first);
|
|
9976
9976
|
const payload = meta?.payload || {};
|
|
9977
9977
|
projectPath = payload.cwd || "";
|
|
9978
|
-
const
|
|
9979
|
-
if (
|
|
9978
|
+
const spawn4 = payload.source?.subagent?.thread_spawn;
|
|
9979
|
+
if (spawn4 || payload.agent_role || payload.agent_nickname) {
|
|
9980
9980
|
isSubagent = true;
|
|
9981
|
-
parentId =
|
|
9981
|
+
parentId = spawn4?.parent_thread_id || null;
|
|
9982
9982
|
}
|
|
9983
9983
|
}
|
|
9984
9984
|
} catch {
|
|
@@ -13266,9 +13266,9 @@ function doResolve(realPath) {
|
|
|
13266
13266
|
const bot = resolveBotWorktree(realPath);
|
|
13267
13267
|
if (bot)
|
|
13268
13268
|
return bot;
|
|
13269
|
-
const
|
|
13270
|
-
if (
|
|
13271
|
-
return
|
|
13269
|
+
const git2 = resolveGit(realPath);
|
|
13270
|
+
if (git2)
|
|
13271
|
+
return git2;
|
|
13272
13272
|
const ws = resolveAutoWorkspace(realPath, cfg.autoWorkspaceMinRepos ?? DEFAULT_AUTO_WORKSPACE_MIN_REPOS);
|
|
13273
13273
|
if (ws)
|
|
13274
13274
|
return ws;
|
|
@@ -13337,9 +13337,9 @@ function resolveGit(realPath) {
|
|
|
13337
13337
|
const toplevel = findGitToplevel(realPath);
|
|
13338
13338
|
if (!toplevel)
|
|
13339
13339
|
return null;
|
|
13340
|
-
const
|
|
13341
|
-
if (remote) {
|
|
13342
|
-
const parsed = parseGitRemote(
|
|
13340
|
+
const probe = getGitRemote(toplevel);
|
|
13341
|
+
if (probe.kind === "remote") {
|
|
13342
|
+
const parsed = parseGitRemote(probe.url);
|
|
13343
13343
|
if (parsed) {
|
|
13344
13344
|
return {
|
|
13345
13345
|
id: `git:${parsed.host}/${parsed.owner}/${parsed.repo}`,
|
|
@@ -13348,6 +13348,9 @@ function resolveGit(realPath) {
|
|
|
13348
13348
|
};
|
|
13349
13349
|
}
|
|
13350
13350
|
}
|
|
13351
|
+
if (probe.kind === "failed") {
|
|
13352
|
+
console.error(`[project] could not read git remotes in ${toplevel} \u2014 filing it as a local-only repo for now, which is probably wrong: ${probe.reason}`);
|
|
13353
|
+
}
|
|
13351
13354
|
const hash = createHash6("sha1").update(toplevel).digest("hex").slice(0, 12);
|
|
13352
13355
|
return {
|
|
13353
13356
|
id: `git-local:${hash}`,
|
|
@@ -13366,23 +13369,39 @@ function findGitToplevel(realPath) {
|
|
|
13366
13369
|
}
|
|
13367
13370
|
return null;
|
|
13368
13371
|
}
|
|
13372
|
+
function git(toplevel, args) {
|
|
13373
|
+
return execSync(`git ${args}`, {
|
|
13374
|
+
cwd: toplevel,
|
|
13375
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
13376
|
+
encoding: "utf-8",
|
|
13377
|
+
timeout: GIT_TIMEOUT_MS
|
|
13378
|
+
});
|
|
13379
|
+
}
|
|
13380
|
+
function probeGitRemote(toplevel) {
|
|
13381
|
+
let names;
|
|
13382
|
+
try {
|
|
13383
|
+
names = git(toplevel, "remote").split("\n").map((n) => n.trim()).filter(Boolean);
|
|
13384
|
+
} catch (err) {
|
|
13385
|
+
return { kind: "failed", reason: err instanceof Error ? err.message : String(err) };
|
|
13386
|
+
}
|
|
13387
|
+
if (names.length === 0)
|
|
13388
|
+
return { kind: "none" };
|
|
13389
|
+
const pick = names.includes("origin") ? "origin" : names[0];
|
|
13390
|
+
try {
|
|
13391
|
+
const url = git(toplevel, `remote get-url ${pick}`).trim();
|
|
13392
|
+
return url ? { kind: "remote", url } : { kind: "none" };
|
|
13393
|
+
} catch (err) {
|
|
13394
|
+
return { kind: "failed", reason: err instanceof Error ? err.message : String(err) };
|
|
13395
|
+
}
|
|
13396
|
+
}
|
|
13369
13397
|
function getGitRemote(toplevel) {
|
|
13370
13398
|
const cached = gitCache.get(toplevel);
|
|
13371
13399
|
if (cached)
|
|
13372
|
-
return cached
|
|
13373
|
-
|
|
13374
|
-
|
|
13375
|
-
|
|
13376
|
-
|
|
13377
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
13378
|
-
encoding: "utf-8",
|
|
13379
|
-
timeout: 2e3
|
|
13380
|
-
}).trim() || null;
|
|
13381
|
-
} catch {
|
|
13382
|
-
remote = null;
|
|
13383
|
-
}
|
|
13384
|
-
gitCache.set(toplevel, { remote });
|
|
13385
|
-
return remote;
|
|
13400
|
+
return cached;
|
|
13401
|
+
const probe = probeGitRemote(toplevel);
|
|
13402
|
+
if (probe.kind !== "failed")
|
|
13403
|
+
gitCache.set(toplevel, probe);
|
|
13404
|
+
return probe;
|
|
13386
13405
|
}
|
|
13387
13406
|
function parseGitRemote(url) {
|
|
13388
13407
|
const trimmed = url.trim().replace(/\.git$/, "");
|
|
@@ -13512,7 +13531,7 @@ function globToRegex(glob) {
|
|
|
13512
13531
|
function escapeRe(s) {
|
|
13513
13532
|
return s.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
13514
13533
|
}
|
|
13515
|
-
var DEFAULT_AUTO_WORKSPACE_MIN_REPOS, BOT_WORKTREE_MARKERS, resolveCache, gitCache, workspaceCache, wsIdCache, cachedConfig, AUTO_WORKSPACE_MAX_DEPTH;
|
|
13534
|
+
var DEFAULT_AUTO_WORKSPACE_MIN_REPOS, BOT_WORKTREE_MARKERS, resolveCache, gitCache, workspaceCache, wsIdCache, cachedConfig, GIT_TIMEOUT_MS, AUTO_WORKSPACE_MAX_DEPTH;
|
|
13516
13535
|
var init_project_resolver = __esm({
|
|
13517
13536
|
"../engine/dist/core/project-resolver.js"() {
|
|
13518
13537
|
"use strict";
|
|
@@ -13524,6 +13543,7 @@ var init_project_resolver = __esm({
|
|
|
13524
13543
|
workspaceCache = /* @__PURE__ */ new Map();
|
|
13525
13544
|
wsIdCache = /* @__PURE__ */ new Map();
|
|
13526
13545
|
cachedConfig = null;
|
|
13546
|
+
GIT_TIMEOUT_MS = 1e4;
|
|
13527
13547
|
AUTO_WORKSPACE_MAX_DEPTH = 2;
|
|
13528
13548
|
}
|
|
13529
13549
|
});
|
|
@@ -19418,7 +19438,7 @@ function pruneLedgerTargets(configuredServers) {
|
|
|
19418
19438
|
return 0;
|
|
19419
19439
|
}
|
|
19420
19440
|
const rows = names.reduce((n, s) => n + Object.keys(orphans[s]).length, 0);
|
|
19421
|
-
console.error(`[sync]
|
|
19441
|
+
console.error(`[sync] tidied local bookkeeping: ${rows} already-synced marker(s) for ${names.length} server(s) you no longer sync to (${names.join(", ")}) moved to ${side}. Nothing was uploaded there; the file is kept so logging back in re-ships nothing.`);
|
|
19422
19442
|
persistNow(data);
|
|
19423
19443
|
return names.length;
|
|
19424
19444
|
}
|
|
@@ -19730,7 +19750,7 @@ var init_http = __esm({
|
|
|
19730
19750
|
CLI_VERSION = JSON.parse(readFileSync33(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
|
|
19731
19751
|
} catch {
|
|
19732
19752
|
try {
|
|
19733
|
-
if (true) CLI_VERSION = "0.5.
|
|
19753
|
+
if (true) CLI_VERSION = "0.5.29";
|
|
19734
19754
|
} catch {
|
|
19735
19755
|
}
|
|
19736
19756
|
}
|
|
@@ -20242,7 +20262,7 @@ var init_telemetry = __esm({
|
|
|
20242
20262
|
init_sync_client();
|
|
20243
20263
|
cliVersion2 = () => {
|
|
20244
20264
|
try {
|
|
20245
|
-
return true ? "0.5.
|
|
20265
|
+
return true ? "0.5.29" : "dev";
|
|
20246
20266
|
} catch {
|
|
20247
20267
|
return "dev";
|
|
20248
20268
|
}
|
|
@@ -20253,6 +20273,18 @@ var init_telemetry = __esm({
|
|
|
20253
20273
|
});
|
|
20254
20274
|
|
|
20255
20275
|
// ../engine/dist/core/collector-health.js
|
|
20276
|
+
var collector_health_exports = {};
|
|
20277
|
+
__export(collector_health_exports, {
|
|
20278
|
+
CRASHLOOP_RESTARTS: () => CRASHLOOP_RESTARTS,
|
|
20279
|
+
STALE_AFTER_MS: () => STALE_AFTER_MS,
|
|
20280
|
+
collectorHealthPath: () => collectorHealthPath,
|
|
20281
|
+
judgeHealth: () => judgeHealth,
|
|
20282
|
+
progressLine: () => progressLine,
|
|
20283
|
+
readCollectorHealth: () => readCollectorHealth,
|
|
20284
|
+
reportWalkProgress: () => reportWalkProgress,
|
|
20285
|
+
updateCollectorHealth: () => updateCollectorHealth,
|
|
20286
|
+
writeCollectorHealth: () => writeCollectorHealth
|
|
20287
|
+
});
|
|
20256
20288
|
import { readFileSync as readFileSync34, writeFileSync as writeFileSync7, mkdirSync as mkdirSync8 } from "node:fs";
|
|
20257
20289
|
import { join as join42, dirname as dirname17 } from "node:path";
|
|
20258
20290
|
function progressLine(h) {
|
|
@@ -22238,7 +22270,7 @@ var init_sync_client = __esm({
|
|
|
22238
22270
|
ownVersion = JSON.parse(readFileSync37(join44(dir, "../package.json"), "utf-8")).version || ownVersion;
|
|
22239
22271
|
} catch {
|
|
22240
22272
|
try {
|
|
22241
|
-
if (true) ownVersion = "0.5.
|
|
22273
|
+
if (true) ownVersion = "0.5.29";
|
|
22242
22274
|
} catch {
|
|
22243
22275
|
}
|
|
22244
22276
|
}
|
|
@@ -22410,6 +22442,43 @@ var init_which = __esm({
|
|
|
22410
22442
|
}
|
|
22411
22443
|
});
|
|
22412
22444
|
|
|
22445
|
+
// src/init-report.ts
|
|
22446
|
+
var init_report_exports = {};
|
|
22447
|
+
__export(init_report_exports, {
|
|
22448
|
+
createInitReporter: () => createInitReporter
|
|
22449
|
+
});
|
|
22450
|
+
function createInitReporter(opts) {
|
|
22451
|
+
let painted = false;
|
|
22452
|
+
const clear = () => {
|
|
22453
|
+
if (painted && opts.tty) opts.write(`\r${" ".repeat(INSTALLING.length)}\r`);
|
|
22454
|
+
painted = false;
|
|
22455
|
+
};
|
|
22456
|
+
return {
|
|
22457
|
+
start() {
|
|
22458
|
+
if (painted) return;
|
|
22459
|
+
if (opts.tty) {
|
|
22460
|
+
opts.write(INSTALLING);
|
|
22461
|
+
painted = true;
|
|
22462
|
+
} else opts.line(INSTALLING);
|
|
22463
|
+
},
|
|
22464
|
+
warn(text) {
|
|
22465
|
+
clear();
|
|
22466
|
+
opts.line(text);
|
|
22467
|
+
},
|
|
22468
|
+
done(text) {
|
|
22469
|
+
clear();
|
|
22470
|
+
opts.line(text);
|
|
22471
|
+
}
|
|
22472
|
+
};
|
|
22473
|
+
}
|
|
22474
|
+
var INSTALLING;
|
|
22475
|
+
var init_init_report = __esm({
|
|
22476
|
+
"src/init-report.ts"() {
|
|
22477
|
+
"use strict";
|
|
22478
|
+
INSTALLING = "Installing\u2026";
|
|
22479
|
+
}
|
|
22480
|
+
});
|
|
22481
|
+
|
|
22413
22482
|
// ../engine/dist/core/mcp-clients.js
|
|
22414
22483
|
var mcp_clients_exports = {};
|
|
22415
22484
|
__export(mcp_clients_exports, {
|
|
@@ -22430,11 +22499,17 @@ function writeFileMkdir(path, body) {
|
|
|
22430
22499
|
mkdirSync10(dirname20(path), { recursive: true });
|
|
22431
22500
|
writeFileSync11(path, body);
|
|
22432
22501
|
}
|
|
22502
|
+
function readJsonObject(path) {
|
|
22503
|
+
const raw = readFileSync39(path, "utf-8");
|
|
22504
|
+
if (raw.trim() === "")
|
|
22505
|
+
return {};
|
|
22506
|
+
return JSON.parse(raw);
|
|
22507
|
+
}
|
|
22433
22508
|
function registerMcpServersJson(target, path, spec) {
|
|
22434
22509
|
let cfg = {};
|
|
22435
22510
|
if (existsSync44(path)) {
|
|
22436
22511
|
try {
|
|
22437
|
-
cfg =
|
|
22512
|
+
cfg = readJsonObject(path);
|
|
22438
22513
|
} catch (err) {
|
|
22439
22514
|
return { id: target.id, label: target.label, path, state: "unparseable", error: String(err) };
|
|
22440
22515
|
}
|
|
@@ -22463,7 +22538,7 @@ function registerOpencodeJson(path, spec) {
|
|
|
22463
22538
|
let cfg = {};
|
|
22464
22539
|
if (existsSync44(path)) {
|
|
22465
22540
|
try {
|
|
22466
|
-
cfg =
|
|
22541
|
+
cfg = readJsonObject(path);
|
|
22467
22542
|
} catch (err) {
|
|
22468
22543
|
return { id, label, path, state: "unparseable", error: String(err) };
|
|
22469
22544
|
}
|
|
@@ -23957,6 +24032,66 @@ var init_toolkit_pull = __esm({
|
|
|
23957
24032
|
}
|
|
23958
24033
|
});
|
|
23959
24034
|
|
|
24035
|
+
// src/init-progress.ts
|
|
24036
|
+
var init_progress_exports = {};
|
|
24037
|
+
__export(init_progress_exports, {
|
|
24038
|
+
handOffLine: () => handOffLine,
|
|
24039
|
+
progressLine: () => progressLine2,
|
|
24040
|
+
renderBar: () => renderBar,
|
|
24041
|
+
renderCount: () => renderCount,
|
|
24042
|
+
spawnDetachedSync: () => spawnDetachedSync,
|
|
24043
|
+
watchFirstSync: () => watchFirstSync
|
|
24044
|
+
});
|
|
24045
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
24046
|
+
function renderBar(done, total, width = 12) {
|
|
24047
|
+
if (total <= 0) return "\u2591".repeat(width);
|
|
24048
|
+
const ratio = Math.max(0, Math.min(1, done / total));
|
|
24049
|
+
const filled = Math.round(ratio * width);
|
|
24050
|
+
return "\u2588".repeat(filled) + "\u2591".repeat(width - filled);
|
|
24051
|
+
}
|
|
24052
|
+
function renderCount(done, total) {
|
|
24053
|
+
const n = (x) => x.toLocaleString("en-US");
|
|
24054
|
+
return `${n(done)}/${n(total)}`;
|
|
24055
|
+
}
|
|
24056
|
+
function progressLine2(snap) {
|
|
24057
|
+
if (!snap || snap.total <= 0) return "starting\u2026";
|
|
24058
|
+
if (snap.complete) return `${renderCount(snap.done, snap.total)} indexed`;
|
|
24059
|
+
return `${renderBar(snap.done, snap.total)} ${renderCount(snap.done, snap.total)}`;
|
|
24060
|
+
}
|
|
24061
|
+
function handOffLine(snap) {
|
|
24062
|
+
const where = snap && snap.total > 0 ? `${renderCount(snap.done, snap.total)} so far` : "started";
|
|
24063
|
+
return `${where} \u2014 continuing in the background`;
|
|
24064
|
+
}
|
|
24065
|
+
async function watchFirstSync(deps) {
|
|
24066
|
+
const handOffAfterMs = deps.handOffAfterMs ?? 2e4;
|
|
24067
|
+
const pollMs = deps.pollMs ?? 400;
|
|
24068
|
+
const started = deps.now();
|
|
24069
|
+
deps.startWorker();
|
|
24070
|
+
let snap = null;
|
|
24071
|
+
for (; ; ) {
|
|
24072
|
+
snap = deps.readProgress();
|
|
24073
|
+
if (snap?.complete) return { finished: true, snapshot: snap };
|
|
24074
|
+
if (deps.now() - started >= handOffAfterMs) return { finished: false, snapshot: snap };
|
|
24075
|
+
deps.draw(progressLine2(snap));
|
|
24076
|
+
await deps.sleep(pollMs);
|
|
24077
|
+
}
|
|
24078
|
+
}
|
|
24079
|
+
function spawnDetachedSync(extraArgs = []) {
|
|
24080
|
+
const entry = process.argv[1];
|
|
24081
|
+
if (!entry) return;
|
|
24082
|
+
const child = spawn2(process.execPath, [entry, "sync", ...extraArgs], {
|
|
24083
|
+
detached: true,
|
|
24084
|
+
stdio: "ignore",
|
|
24085
|
+
windowsHide: true
|
|
24086
|
+
});
|
|
24087
|
+
child.unref();
|
|
24088
|
+
}
|
|
24089
|
+
var init_init_progress = __esm({
|
|
24090
|
+
"src/init-progress.ts"() {
|
|
24091
|
+
"use strict";
|
|
24092
|
+
}
|
|
24093
|
+
});
|
|
24094
|
+
|
|
23960
24095
|
// src/repair.ts
|
|
23961
24096
|
var repair_exports = {};
|
|
23962
24097
|
__export(repair_exports, {
|
|
@@ -24572,7 +24707,7 @@ __export(collector_exports, {
|
|
|
24572
24707
|
isSecretRule: () => isSecretRule,
|
|
24573
24708
|
resolveCodeindexBin: () => resolveCodeindexBin
|
|
24574
24709
|
});
|
|
24575
|
-
import { spawn as
|
|
24710
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
24576
24711
|
import { execSync as execSync4 } from "node:child_process";
|
|
24577
24712
|
import { readFileSync as readFileSync44 } from "node:fs";
|
|
24578
24713
|
import { join as join53, basename as basename28 } from "node:path";
|
|
@@ -24587,7 +24722,7 @@ async function resolveCodeindexBin(autoInstall = true) {
|
|
|
24587
24722
|
}
|
|
24588
24723
|
function runMcp(binPath, workspace, calls, timeoutMs = 18e4) {
|
|
24589
24724
|
return new Promise((resolve3, reject) => {
|
|
24590
|
-
const p =
|
|
24725
|
+
const p = spawn3(binPath, ["--mcp", "--workspace", workspace], { stdio: ["pipe", "pipe", "ignore"] });
|
|
24591
24726
|
const res = /* @__PURE__ */ new Map();
|
|
24592
24727
|
let pending = "";
|
|
24593
24728
|
let failed = false;
|
|
@@ -25892,7 +26027,7 @@ var init_intent_drain = __esm({
|
|
|
25892
26027
|
ownVersion2 = JSON.parse(readFileSync46(join55(dir, "../package.json"), "utf-8")).version || ownVersion2;
|
|
25893
26028
|
} catch {
|
|
25894
26029
|
try {
|
|
25895
|
-
if (true) ownVersion2 = "0.5.
|
|
26030
|
+
if (true) ownVersion2 = "0.5.29";
|
|
25896
26031
|
} catch {
|
|
25897
26032
|
}
|
|
25898
26033
|
}
|
|
@@ -27603,6 +27738,7 @@ var DEFAULT_ALLOW = [
|
|
|
27603
27738
|
"recall_task_create",
|
|
27604
27739
|
"recall_task_update",
|
|
27605
27740
|
"recall_task_comment",
|
|
27741
|
+
"recall_task_policy",
|
|
27606
27742
|
"recall_help",
|
|
27607
27743
|
"recall_smart_resume",
|
|
27608
27744
|
"recall_project_context",
|
|
@@ -27653,7 +27789,6 @@ var DEFAULT_ALLOW = [
|
|
|
27653
27789
|
"recall_toolkit_status",
|
|
27654
27790
|
"recall_toolkit_sync"
|
|
27655
27791
|
];
|
|
27656
|
-
var SELF_HOST_DOCS = "https://github.com/munhq/chat-recall/blob/main/docs/SELF_HOSTING.md";
|
|
27657
27792
|
function enforceNodeVersion() {
|
|
27658
27793
|
const required = Number(/(\d+)/.exec(String(pkgEngines))?.[1] ?? 0);
|
|
27659
27794
|
const found = Number(process.versions.node.split(".")[0]);
|
|
@@ -27669,8 +27804,13 @@ program.name("chat-recall").description("Semantic search for Claude Code session
|
|
|
27669
27804
|
program.command("init").description("Set up chat-recall: connect to your server, configure MCP, ship your local sessions").option("--server <url>", "chat-recall server URL to connect this machine to").option("--token <token>", "Self-host device token (skips the interactive OIDC login)").option("--skip-mcp", "Skip MCP server configuration").option("--skip-sync", "Skip the first session sync").option("--with-codeindex", "Force-download the codeindex binary during init. Default behavior is to detect an already-installed codeindex on PATH and register it as an MCP server.").option("--skip-codeindex", "Skip the codeindex companion entirely (no detection, no registration).").option("--skip-service", "Skip installing the per-user background sync service (Linux/macOS/Windows). By default init installs it so new conversations ship automatically.").option("--yes", "Do not pause before the first upload. The scope summary still prints.", false).option("--prompt-json", "Print the device prompt as one JSON line on stdout, then continue", false).action(async (options) => {
|
|
27670
27805
|
try {
|
|
27671
27806
|
console.log(chalk.bold("chat-recall init") + chalk.dim(` v${pkgVersion}`));
|
|
27672
|
-
|
|
27673
|
-
|
|
27807
|
+
const { createInitReporter: createInitReporter2 } = await Promise.resolve().then(() => (init_init_report(), init_report_exports));
|
|
27808
|
+
const rep = createInitReporter2({
|
|
27809
|
+
tty: process.stdout.isTTY === true,
|
|
27810
|
+
write: (t) => process.stdout.write(t),
|
|
27811
|
+
line: (t) => console.log(t)
|
|
27812
|
+
});
|
|
27813
|
+
rep.start();
|
|
27674
27814
|
const clis = [
|
|
27675
27815
|
{ name: "Gemini CLI", cmd: "gemini", available: false },
|
|
27676
27816
|
{ name: "Claude CLI", cmd: "claude", available: false },
|
|
@@ -27686,12 +27826,9 @@ program.command("init").description("Set up chat-recall: connect to your server,
|
|
|
27686
27826
|
} catch {
|
|
27687
27827
|
}
|
|
27688
27828
|
}
|
|
27689
|
-
|
|
27690
|
-
|
|
27691
|
-
|
|
27692
|
-
}
|
|
27693
|
-
console.log();
|
|
27694
|
-
console.log(chalk.bold("2. Connecting to your server..."));
|
|
27829
|
+
const foundTools = clis.filter((c) => c.available).map((c) => c.name.replace(/ (CLI|Code)$/, ""));
|
|
27830
|
+
if (!foundTools.length) rep.warn(chalk.yellow("No AI tools detected \u2014 chat-recall indexes their transcripts, so there is nothing to ship yet."));
|
|
27831
|
+
const serverBad = (text) => rep.warn(`${chalk.yellow("Not connected")} \u2014 ${text}`);
|
|
27695
27832
|
let target = firstTarget();
|
|
27696
27833
|
let deadTarget = false;
|
|
27697
27834
|
if (options.server) {
|
|
@@ -27699,25 +27836,20 @@ program.command("init").description("Set up chat-recall: connect to your server,
|
|
|
27699
27836
|
await runLogin(options.server, { token: options.token, fromInit: true, promptJson: options.promptJson });
|
|
27700
27837
|
target = firstTarget();
|
|
27701
27838
|
} catch (e) {
|
|
27702
|
-
|
|
27703
|
-
console.log(` ${chalk.dim(`Run ${chalk.bold(`chat-recall login ${options.server}`)} when ready, or self-host: ${SELF_HOST_DOCS}`)}`);
|
|
27839
|
+
serverBad(describeProbeError(e));
|
|
27704
27840
|
}
|
|
27705
27841
|
} else if (!target) {
|
|
27706
|
-
console.log(` Connecting to ${chalk.bold(DEFAULT_SERVER)} \u2014 sign in to approve this machine.`);
|
|
27707
|
-
console.log(` ${chalk.dim(`Prefer your own server? ${chalk.bold("--server <url>")}. Self-hosting is free: ${SELF_HOST_DOCS}`)}`);
|
|
27708
27842
|
try {
|
|
27709
27843
|
await runLogin(DEFAULT_SERVER, { token: options.token, fromInit: true, promptJson: options.promptJson });
|
|
27710
27844
|
target = firstTarget();
|
|
27711
27845
|
} catch (e) {
|
|
27712
|
-
|
|
27713
|
-
console.log(` ${chalk.dim(`Run ${chalk.bold("chat-recall login <server-url>")} when ready, or self-host: ${SELF_HOST_DOCS}`)}`);
|
|
27846
|
+
serverBad(describeProbeError(e));
|
|
27714
27847
|
}
|
|
27715
27848
|
}
|
|
27716
27849
|
if (target && !options.server) {
|
|
27717
27850
|
const { probeServer: probeServer2, probeOk: probeOk2, probeAdvice: probeAdvice2 } = await Promise.resolve().then(() => (init_server_probe(), server_probe_exports));
|
|
27718
27851
|
const probe = await probeServer2(target.base, { timeoutMs: 1e4 });
|
|
27719
27852
|
if (probeOk2(probe)) {
|
|
27720
|
-
console.log(` ${chalk.green("Connected")} \u2192 ${target.base}`);
|
|
27721
27853
|
} else if (probe.kind === "moved" || probe.kind === "not_api") {
|
|
27722
27854
|
const retired = target.base;
|
|
27723
27855
|
console.log(` ${chalk.yellow("The saved server no longer serves chat-recall")} \u2192 ${retired}`);
|
|
@@ -27732,7 +27864,7 @@ program.command("init").description("Set up chat-recall: connect to your server,
|
|
|
27732
27864
|
target = firstTarget();
|
|
27733
27865
|
if (target) console.log(` ${chalk.green("Connected")} \u2192 ${target.base}`);
|
|
27734
27866
|
} catch (e) {
|
|
27735
|
-
|
|
27867
|
+
serverBad(describeProbeError(e));
|
|
27736
27868
|
console.log(` ${chalk.dim(`Run ${chalk.bold(`chat-recall login ${DEFAULT_SERVER}`)} when ready, then ${chalk.bold(`chat-recall logout ${retired}`)}.`)}`);
|
|
27737
27869
|
deadTarget = true;
|
|
27738
27870
|
}
|
|
@@ -27741,11 +27873,8 @@ program.command("init").description("Set up chat-recall: connect to your server,
|
|
|
27741
27873
|
console.log(` ${probeAdvice2(probe, target.base)}`);
|
|
27742
27874
|
}
|
|
27743
27875
|
} else if (target) {
|
|
27744
|
-
console.log(` ${chalk.green("Connected")} \u2192 ${target.base}`);
|
|
27745
27876
|
}
|
|
27746
|
-
console.log();
|
|
27747
27877
|
if (!options.skipMcp) {
|
|
27748
|
-
console.log(chalk.bold("3. Configuring MCP server..."));
|
|
27749
27878
|
const projectRoot = join60(import.meta.dirname, "..");
|
|
27750
27879
|
let mcpBinOnPath = false;
|
|
27751
27880
|
mcpBinOnPath = isOnPath("chat-recall-mcp");
|
|
@@ -27764,19 +27893,22 @@ program.command("init").description("Set up chat-recall: connect to your server,
|
|
|
27764
27893
|
{ ...launch, env: MCP_ENV, alwaysAllow: DEFAULT_ALLOW },
|
|
27765
27894
|
{ extraIds: detectedClients }
|
|
27766
27895
|
);
|
|
27767
|
-
|
|
27768
|
-
|
|
27769
|
-
|
|
27896
|
+
const ok = results.filter((r) => r.state !== "unparseable");
|
|
27897
|
+
const bad = results.filter((r) => r.state === "unparseable");
|
|
27898
|
+
if (ok.length) {
|
|
27899
|
+
}
|
|
27900
|
+
for (const r of bad) {
|
|
27901
|
+
const why = (r.error ?? "").replace(/^SyntaxError:\s*/, "").split("\n")[0];
|
|
27902
|
+
rep.warn(`${chalk.yellow(`${r.label} config left alone \u2014 ${why || "the file does not parse"}`)} ${chalk.dim(r.path)}`);
|
|
27903
|
+
rep.warn(`${chalk.dim(` fix that file, then: chat-recall init (nothing else needs redoing)`)}`);
|
|
27904
|
+
}
|
|
27905
|
+
if (process.env.CHAT_RECALL_VERBOSE) {
|
|
27770
27906
|
}
|
|
27771
|
-
console.log(chalk.dim(` Launch: ${launch.command}${launch.args ? " " + launch.args.join(" ") : ""}`));
|
|
27772
27907
|
} else {
|
|
27773
|
-
console.log(chalk.bold("3. Skipping MCP configuration (--skip-mcp)"));
|
|
27774
27908
|
}
|
|
27775
|
-
console.log();
|
|
27776
27909
|
const skipCodeindex = options.skipCodeindex === true;
|
|
27777
27910
|
const forceInstall = options.withCodeindex === true || process.env.CHAT_RECALL_WITH_CODEINDEX === "1";
|
|
27778
27911
|
if (skipCodeindex) {
|
|
27779
|
-
console.log(chalk.bold("4. Skipping codeindex companion (--skip-codeindex)"));
|
|
27780
27912
|
} else {
|
|
27781
27913
|
const {
|
|
27782
27914
|
checkCodeindexStatus: checkCodeindexStatus2,
|
|
@@ -27786,64 +27918,46 @@ program.command("init").description("Set up chat-recall: connect to your server,
|
|
|
27786
27918
|
} = await Promise.resolve().then(() => (init_companions(), companions_exports));
|
|
27787
27919
|
const detected = checkCodeindexStatus2();
|
|
27788
27920
|
if (detected.installed && !forceInstall) {
|
|
27789
|
-
console.log(chalk.bold("4. Detected codeindex companion"));
|
|
27790
|
-
console.log(` ${chalk.green("codeindex")}: ${detected.path}`);
|
|
27791
27921
|
if (!options.skipMcp) {
|
|
27792
27922
|
const mcpJsonPath = join60(homedir22(), ".mcp.json");
|
|
27793
27923
|
const reg = registerCodeindexMcp2(mcpJsonPath, detected.path);
|
|
27794
|
-
if (reg.added) console.log(` ${chalk.green("codeindex MCP server registered")} in ${mcpJsonPath}`);
|
|
27795
|
-
else console.log(` codeindex MCP server: ${chalk.green("already registered")}`);
|
|
27796
27924
|
}
|
|
27797
27925
|
} else if (forceInstall) {
|
|
27798
|
-
console.log(chalk.bold("4. Installing codeindex companion (--with-codeindex)..."));
|
|
27799
27926
|
try {
|
|
27800
27927
|
const result = await installCodeindex2({ force: true });
|
|
27801
27928
|
if (result.installed) {
|
|
27802
27929
|
const sizeMb = result.size ? `${(result.size / 1024 / 1024).toFixed(1)} MB` : "?";
|
|
27803
|
-
console.log(` ${chalk.green("codeindex installed")} (${sizeMb}) \u2192 ${result.path}`);
|
|
27804
27930
|
if (!options.skipMcp) {
|
|
27805
27931
|
const mcpJsonPath = join60(homedir22(), ".mcp.json");
|
|
27806
27932
|
const reg = registerCodeindexMcp2(mcpJsonPath, CODEINDEX_BIN_PATH2);
|
|
27807
|
-
if (reg.added) console.log(` ${chalk.green("codeindex MCP server registered")} in ${mcpJsonPath}`);
|
|
27808
27933
|
}
|
|
27809
27934
|
} else if (!result.prebuiltAvailable) {
|
|
27810
|
-
|
|
27935
|
+
rep.warn(`${chalk.yellow("codeindex")}: ${result.unsupportedReason}`);
|
|
27811
27936
|
}
|
|
27812
27937
|
} catch (err) {
|
|
27813
27938
|
const msg = String(err);
|
|
27814
|
-
|
|
27939
|
+
rep.warn(`${chalk.yellow("codeindex install failed")}: ${msg}`);
|
|
27815
27940
|
if (msg.includes("404")) {
|
|
27816
27941
|
console.log(chalk.dim(" The codeindex release returned 404. If the repo is private,"));
|
|
27817
27942
|
console.log(chalk.dim(" authenticate `gh` to it, or build from source."));
|
|
27818
27943
|
}
|
|
27819
27944
|
}
|
|
27820
27945
|
} else {
|
|
27821
|
-
console.log(chalk.bold("4. codeindex companion: not installed"));
|
|
27822
|
-
console.log(chalk.dim(" codeindex is a separate MCP server for code-level lookup \u2014"));
|
|
27823
|
-
console.log(chalk.dim(" find_symbol, plan_change, get_change_impact, etc."));
|
|
27824
|
-
console.log(chalk.dim(" To install: `chat-recall init --with-codeindex`"));
|
|
27825
|
-
console.log(chalk.dim(" Or grab the binary from https://github.com/munhq/codeindex"));
|
|
27826
27946
|
}
|
|
27827
27947
|
}
|
|
27828
|
-
console.log();
|
|
27829
|
-
console.log(chalk.bold("Installing chat-recall skills into your AI tools..."));
|
|
27830
27948
|
try {
|
|
27831
27949
|
const { installSkills: installSkills2 } = await Promise.resolve().then(() => (init_install_skills(), install_skills_exports));
|
|
27832
27950
|
const r = installSkills2();
|
|
27833
27951
|
const hits = r.perTarget.filter((t) => t.installed.length > 0);
|
|
27834
27952
|
if (hits.length) {
|
|
27835
|
-
|
|
27953
|
+
const skills = Math.max(...hits.map((t) => t.installed.length));
|
|
27836
27954
|
} else {
|
|
27837
|
-
console.log(chalk.dim(" No supported AI tools detected \u2014 skills not installed."));
|
|
27838
27955
|
}
|
|
27839
27956
|
const userOwned = [...new Set(r.perTarget.flatMap((t) => t.skippedUserOwned))];
|
|
27840
|
-
if (userOwned.length) console.log(chalk.yellow(` Kept your existing skill(s) of the same name: ${userOwned.join(", ")}`));
|
|
27841
27957
|
} catch (err) {
|
|
27842
|
-
|
|
27958
|
+
rep.warn(`${chalk.yellow("Skill install failed")} \u2014 ${err instanceof Error ? err.message : err}`);
|
|
27843
27959
|
}
|
|
27844
|
-
console.log();
|
|
27845
27960
|
if (!options.skipMcp && firstTarget()) {
|
|
27846
|
-
console.log(chalk.bold("Installing your other MCP servers from your account..."));
|
|
27847
27961
|
try {
|
|
27848
27962
|
const { loadAllCredentials: loadAllCredentials2 } = await Promise.resolve().then(() => (init_sync_client(), sync_client_exports));
|
|
27849
27963
|
const { executePull: executePull2 } = await Promise.resolve().then(() => (init_toolkit_pull(), toolkit_pull_exports));
|
|
@@ -27879,66 +27993,59 @@ program.command("init").description("Set up chat-recall: connect to your server,
|
|
|
27879
27993
|
const written = report.outcomes.filter((o) => o.status === "written");
|
|
27880
27994
|
const present = report.outcomes.filter((o) => o.status === "present").length;
|
|
27881
27995
|
if (answered === 0) {
|
|
27882
|
-
|
|
27996
|
+
rep.warn(chalk.yellow("Could not ask your server what MCP servers are on your account"));
|
|
27883
27997
|
for (const f of askFailed) console.log(` ${chalk.dim(f)}`);
|
|
27884
27998
|
console.log(` ${chalk.dim("Re-run `chat-recall toolkit pull` once the server answers.")}`);
|
|
27885
27999
|
} else if (written.length === 0 && present === 0) {
|
|
27886
|
-
console.log(chalk.dim(" Nothing on your account to install yet."));
|
|
27887
28000
|
} else {
|
|
27888
|
-
console.log(` ${chalk.green(`Installed ${written.length}`)} ${chalk.dim(`(${present} already present)`)}`);
|
|
27889
28001
|
const envVars = [...new Set(written.flatMap((o) => o.needsEnv || []))].sort();
|
|
27890
28002
|
if (envVars.length) {
|
|
27891
|
-
|
|
28003
|
+
rep.warn(`${chalk.yellow("Set these env vars \u2014 their values were never uploaded:")} ${envVars.join(", ")}`);
|
|
27892
28004
|
}
|
|
27893
28005
|
}
|
|
27894
28006
|
} catch (err) {
|
|
27895
|
-
|
|
28007
|
+
rep.warn(`${chalk.yellow("Could not install account MCPs")} \u2014 ${err instanceof Error ? err.message : err}`);
|
|
27896
28008
|
console.log(` ${chalk.dim("Re-run `chat-recall toolkit pull` later.")}`);
|
|
27897
28009
|
}
|
|
27898
|
-
console.log();
|
|
27899
28010
|
}
|
|
27900
28011
|
if (deadTarget) {
|
|
27901
|
-
console.log(chalk.bold("
|
|
28012
|
+
console.log(chalk.bold("Skipping first sync \u2014 the saved server is not serving chat-recall"));
|
|
27902
28013
|
console.log(` ${chalk.dim(`Re-point with the two commands above, then run ${chalk.bold("chat-recall sync")}.`)}`);
|
|
27903
28014
|
} else if (!options.skipSync && firstTarget()) {
|
|
27904
|
-
|
|
27905
|
-
|
|
27906
|
-
|
|
27907
|
-
|
|
27908
|
-
|
|
27909
|
-
|
|
27910
|
-
|
|
27911
|
-
|
|
28015
|
+
const { watchFirstSync: watchFirstSync2, spawnDetachedSync: spawnDetachedSync2, handOffLine: handOffLine2, progressLine: renderProgress } = await Promise.resolve().then(() => (init_init_progress(), init_progress_exports));
|
|
28016
|
+
const { readCollectorHealth: readCollectorHealth2 } = await Promise.resolve().then(() => (init_collector_health(), collector_health_exports));
|
|
28017
|
+
const label = (text) => `${chalk.bold("Indexing")} ${text}`;
|
|
28018
|
+
const tty = process.stdout.isTTY === true;
|
|
28019
|
+
const outcome = await watchFirstSync2({
|
|
28020
|
+
startWorker: () => spawnDetachedSync2(),
|
|
28021
|
+
readProgress: () => {
|
|
28022
|
+
const p = readCollectorHealth2()?.progress;
|
|
28023
|
+
return p ? { done: p.done, total: p.total, complete: p.complete } : null;
|
|
28024
|
+
},
|
|
28025
|
+
// In place on a terminal; a single final line when piped, so a log or
|
|
28026
|
+
// a CI transcript does not collect one line per poll.
|
|
28027
|
+
draw: (text) => {
|
|
28028
|
+
if (tty) process.stdout.write(`\r${label(text)} `);
|
|
28029
|
+
},
|
|
28030
|
+
now: () => Date.now(),
|
|
28031
|
+
sleep: (ms) => new Promise((r) => setTimeout(r, ms))
|
|
28032
|
+
});
|
|
28033
|
+
if (tty) process.stdout.write("\r");
|
|
28034
|
+
if (outcome.finished) {
|
|
28035
|
+
console.log(label(chalk.green(renderProgress(outcome.snapshot))));
|
|
28036
|
+
} else {
|
|
28037
|
+
console.log(label(chalk.dim(handOffLine2(outcome.snapshot))));
|
|
28038
|
+
console.log(` ${chalk.dim("watch it with: " + chalk.bold("chat-recall status"))}`);
|
|
28039
|
+
}
|
|
28040
|
+
const failed = Object.entries(readCollectorHealth2()?.targets ?? {}).filter(([, t]) => (t.failures ?? 0) > 0 && t.lastError);
|
|
28041
|
+
for (const [server, t] of failed) {
|
|
28042
|
+
console.log(` ${chalk.yellow("sync error")} ${chalk.dim(server)}: ${t.lastError}`);
|
|
27912
28043
|
}
|
|
27913
28044
|
} else if (!options.skipSync) {
|
|
27914
|
-
console.log(chalk.bold("5. Skipping first sync (not logged in)"));
|
|
27915
28045
|
} else {
|
|
27916
|
-
console.log(chalk.bold("5. Skipping first sync (--skip-sync)"));
|
|
27917
28046
|
}
|
|
27918
|
-
console.log();
|
|
27919
|
-
console.log(chalk.bold("6. Background sync"));
|
|
27920
|
-
console.log(chalk.dim(" Runs via the MCP server while Claude Code is open (no extra service to install)."));
|
|
27921
|
-
console.log(chalk.dim(" Always-on / headless? Opt in with `chat-recall watch --install-service`."));
|
|
27922
28047
|
void options.skipService;
|
|
27923
|
-
|
|
27924
|
-
console.log(chalk.green.bold("Setup complete!"));
|
|
27925
|
-
console.log();
|
|
27926
|
-
console.log(`chat-recall MCP tools (${DEFAULT_ALLOW.length}):`);
|
|
27927
|
-
for (let i = 0; i < DEFAULT_ALLOW.length; i += 3) {
|
|
27928
|
-
console.log(" " + DEFAULT_ALLOW.slice(i, i + 3).join(", "));
|
|
27929
|
-
}
|
|
27930
|
-
if (!skipCodeindex) {
|
|
27931
|
-
const { checkCodeindexStatus: checkCodeindexStatus2 } = await Promise.resolve().then(() => (init_companions(), companions_exports));
|
|
27932
|
-
if (checkCodeindexStatus2().installed) {
|
|
27933
|
-
console.log();
|
|
27934
|
-
console.log("codeindex MCP tools (16): status, search, find_symbol, find_word, get_outline,");
|
|
27935
|
-
console.log(" get_tree, get_imports, get_imported_by, find_callers, plan_change,");
|
|
27936
|
-
console.log(" get_hot_files, index_workspace, analyze, read_file, read_symbol,");
|
|
27937
|
-
console.log(" get_change_impact");
|
|
27938
|
-
}
|
|
27939
|
-
}
|
|
27940
|
-
console.log();
|
|
27941
|
-
console.log(`${chalk.dim("Background sync is running \u2014 new conversations ship automatically. Manage it with `chat-recall service status|uninstall`.")}`);
|
|
28048
|
+
rep.done(chalk.green.bold("\u2713 Done"));
|
|
27942
28049
|
} catch (err) {
|
|
27943
28050
|
console.error(chalk.red("Error:"), err);
|
|
27944
28051
|
process.exit(1);
|
|
@@ -29850,13 +29957,13 @@ async function runLogin(serverUrl, opts) {
|
|
|
29850
29957
|
return;
|
|
29851
29958
|
}
|
|
29852
29959
|
console.log();
|
|
29853
|
-
console.log(chalk.bold("
|
|
29960
|
+
console.log(chalk.bold("Open this to approve the machine:"));
|
|
29854
29961
|
console.log(" " + chalk.cyan(p.url));
|
|
29855
|
-
|
|
29856
|
-
|
|
29857
|
-
|
|
29858
|
-
console.log(chalk.dim(
|
|
29859
|
-
console.log(chalk.dim("
|
|
29962
|
+
if (openBrowser(p.url)) {
|
|
29963
|
+
console.log(chalk.dim(" (tried to open it for you \u2014 if no window appeared, use the link above)"));
|
|
29964
|
+
}
|
|
29965
|
+
console.log(chalk.dim(` If the page asks for a code: ${chalk.bold(p.userCode)}`));
|
|
29966
|
+
console.log(chalk.dim("Then come back here \u2014 this finishes on its own. Waiting\u2026"));
|
|
29860
29967
|
};
|
|
29861
29968
|
const tokens = authProvider === "better-auth" ? await betterAuthDeviceLogin2(base2, onPrompt) : await deviceLogin2({ issuer, clientId: opts.clientId }, onPrompt);
|
|
29862
29969
|
const authHdr = { authorization: `Bearer ${tokens.accessToken}`, "content-type": "application/json" };
|