chat-recall 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auto-update.d.ts +34 -0
- package/dist/auto-update.d.ts.map +1 -1
- package/dist/auto-update.js +51 -8
- package/dist/auto-update.js.map +1 -1
- package/dist/cli.js +370 -183
- package/dist/cli.js.map +1 -1
- package/dist/mcp-relay.js +76 -13
- package/dist/mcp-relay.js.map +1 -1
- package/dist/mcp.js +620 -345
- package/dist/mcp.js.map +1 -1
- package/dist/relay-lifecycle.d.ts +69 -0
- package/dist/relay-lifecycle.d.ts.map +1 -0
- package/dist/relay-lifecycle.js +117 -0
- package/dist/relay-lifecycle.js.map +1 -0
- package/dist/repair.d.ts +2 -0
- package/dist/repair.d.ts.map +1 -1
- package/dist/repair.js +23 -3
- package/dist/repair.js.map +1 -1
- package/dist/scan-worker.js +44 -13
- package/dist/service-installer.d.ts.map +1 -1
- package/dist/service-installer.js +7 -2
- package/dist/service-installer.js.map +1 -1
- package/dist/sync-client.d.ts +38 -5
- package/dist/sync-client.d.ts.map +1 -1
- package/dist/sync-client.js +191 -58
- package/dist/sync-client.js.map +1 -1
- package/dist/sync-supervisor.d.ts +43 -0
- package/dist/sync-supervisor.d.ts.map +1 -0
- package/dist/sync-supervisor.js +84 -0
- package/dist/sync-supervisor.js.map +1 -0
- package/dist/watch.js +310 -127
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -8093,7 +8093,7 @@ var init_opencode = __esm({
|
|
|
8093
8093
|
|
|
8094
8094
|
// ../engine/dist/core/backends/tail-read.js
|
|
8095
8095
|
import { openSync as openSync2, readSync as readSync2, closeSync as closeSync2, statSync as statSync4 } from "node:fs";
|
|
8096
|
-
function readTailFromOffset(path, offset) {
|
|
8096
|
+
function readTailFromOffset(path, offset, maxBytes = TAIL_READ_MAX_BYTES) {
|
|
8097
8097
|
let size = 0;
|
|
8098
8098
|
try {
|
|
8099
8099
|
size = statSync4(path).size;
|
|
@@ -8102,7 +8102,7 @@ function readTailFromOffset(path, offset) {
|
|
|
8102
8102
|
}
|
|
8103
8103
|
if (size <= offset)
|
|
8104
8104
|
return { text: "", newOffset: offset };
|
|
8105
|
-
const len = Math.min(size - offset,
|
|
8105
|
+
const len = Math.min(size - offset, Math.max(1, maxBytes));
|
|
8106
8106
|
const buf = Buffer.allocUnsafe(len);
|
|
8107
8107
|
let fd = null;
|
|
8108
8108
|
try {
|
|
@@ -8118,11 +8118,16 @@ function readTailFromOffset(path, offset) {
|
|
|
8118
8118
|
return { text: "", newOffset: offset };
|
|
8119
8119
|
const slice = got < len ? buf.subarray(0, got) : buf;
|
|
8120
8120
|
const lastNl = slice.lastIndexOf(10);
|
|
8121
|
-
if (lastNl
|
|
8122
|
-
|
|
8121
|
+
if (lastNl >= 0) {
|
|
8122
|
+
const text = slice.subarray(0, lastNl + 1).toString("utf-8");
|
|
8123
|
+
return { text, newOffset: offset + lastNl + 1 };
|
|
8123
8124
|
}
|
|
8124
|
-
|
|
8125
|
-
|
|
8125
|
+
if (offset + got >= size)
|
|
8126
|
+
return { text: "", newOffset: offset };
|
|
8127
|
+
const end = findNewline(fd, offset + got, size);
|
|
8128
|
+
if (end < 0)
|
|
8129
|
+
return { text: "", newOffset: offset };
|
|
8130
|
+
return { text: "", newOffset: end + 1, skippedBytes: end + 1 - offset };
|
|
8126
8131
|
} catch {
|
|
8127
8132
|
return { text: "", newOffset: offset };
|
|
8128
8133
|
} finally {
|
|
@@ -8134,9 +8139,26 @@ function readTailFromOffset(path, offset) {
|
|
|
8134
8139
|
}
|
|
8135
8140
|
}
|
|
8136
8141
|
}
|
|
8142
|
+
function findNewline(fd, from, size) {
|
|
8143
|
+
const block = Buffer.allocUnsafe(SKIP_SCAN_BYTES);
|
|
8144
|
+
let pos = from;
|
|
8145
|
+
while (pos < size) {
|
|
8146
|
+
const n = readSync2(fd, block, 0, Math.min(SKIP_SCAN_BYTES, size - pos), pos);
|
|
8147
|
+
if (n <= 0)
|
|
8148
|
+
return -1;
|
|
8149
|
+
const i = block.subarray(0, n).indexOf(10);
|
|
8150
|
+
if (i >= 0)
|
|
8151
|
+
return pos + i;
|
|
8152
|
+
pos += n;
|
|
8153
|
+
}
|
|
8154
|
+
return -1;
|
|
8155
|
+
}
|
|
8156
|
+
var TAIL_READ_MAX_BYTES, SKIP_SCAN_BYTES;
|
|
8137
8157
|
var init_tail_read = __esm({
|
|
8138
8158
|
"../engine/dist/core/backends/tail-read.js"() {
|
|
8139
8159
|
"use strict";
|
|
8160
|
+
TAIL_READ_MAX_BYTES = 16 * 1024 * 1024;
|
|
8161
|
+
SKIP_SCAN_BYTES = 1024 * 1024;
|
|
8140
8162
|
}
|
|
8141
8163
|
});
|
|
8142
8164
|
|
|
@@ -8843,11 +8865,11 @@ var init_codex2 = __esm({
|
|
|
8843
8865
|
return 0;
|
|
8844
8866
|
}
|
|
8845
8867
|
}
|
|
8846
|
-
async readFromOffset(prefixedId, offset) {
|
|
8868
|
+
async readFromOffset(prefixedId, offset, maxBytes) {
|
|
8847
8869
|
const loc = this.findSession(prefixedId);
|
|
8848
8870
|
if (!loc)
|
|
8849
8871
|
return { text: "", newOffset: offset };
|
|
8850
|
-
return readTailFromOffset(loc.path, offset);
|
|
8872
|
+
return readTailFromOffset(loc.path, offset, maxBytes);
|
|
8851
8873
|
}
|
|
8852
8874
|
};
|
|
8853
8875
|
codexBackend = new CodexBackend();
|
|
@@ -9408,11 +9430,11 @@ var init_agy = __esm({
|
|
|
9408
9430
|
return 0;
|
|
9409
9431
|
}
|
|
9410
9432
|
}
|
|
9411
|
-
async readFromOffset(prefixedId, offset) {
|
|
9433
|
+
async readFromOffset(prefixedId, offset, maxBytes) {
|
|
9412
9434
|
const loc = this.findSession(prefixedId);
|
|
9413
9435
|
if (!loc)
|
|
9414
9436
|
return { text: "", newOffset: offset };
|
|
9415
|
-
return readTailFromOffset(loc.path, offset);
|
|
9437
|
+
return readTailFromOffset(loc.path, offset, maxBytes);
|
|
9416
9438
|
}
|
|
9417
9439
|
};
|
|
9418
9440
|
agyBackend = new AgyBackend();
|
|
@@ -10608,7 +10630,7 @@ var init_backends = __esm({
|
|
|
10608
10630
|
// ../engine/dist/transcript/shadow.js
|
|
10609
10631
|
import { gzipSync as gzipSync2, gunzipSync as gunzipSync2 } from "zlib";
|
|
10610
10632
|
import { createHash as createHash2 } from "crypto";
|
|
10611
|
-
import { existsSync as existsSync12, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync2, renameSync as renameSync2, statSync as statSync10 } from "fs";
|
|
10633
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync2, renameSync as renameSync2, statSync as statSync10, openSync as openSync4, readSync as readSync4, closeSync as closeSync4 } from "fs";
|
|
10612
10634
|
import { dirname as dirname12, join as join14 } from "path";
|
|
10613
10635
|
function shadowRoot() {
|
|
10614
10636
|
return join14(getDataDir(), "shadow");
|
|
@@ -10832,6 +10854,29 @@ function seedShadow(sessionId, container) {
|
|
|
10832
10854
|
}
|
|
10833
10855
|
return fullest;
|
|
10834
10856
|
}
|
|
10857
|
+
function shadowUncompressedBytes(tool, rawId) {
|
|
10858
|
+
const path = shadowFileFor(tool, rawId);
|
|
10859
|
+
let fd = null;
|
|
10860
|
+
try {
|
|
10861
|
+
const size = statSync10(path).size;
|
|
10862
|
+
if (size < 18)
|
|
10863
|
+
return 0;
|
|
10864
|
+
fd = openSync4(path, "r");
|
|
10865
|
+
const tail = Buffer.alloc(4);
|
|
10866
|
+
if (readSync4(fd, tail, 0, 4, size - 4) !== 4)
|
|
10867
|
+
return 0;
|
|
10868
|
+
return tail.readUInt32LE(0);
|
|
10869
|
+
} catch {
|
|
10870
|
+
return 0;
|
|
10871
|
+
} finally {
|
|
10872
|
+
if (fd !== null) {
|
|
10873
|
+
try {
|
|
10874
|
+
closeSync4(fd);
|
|
10875
|
+
} catch {
|
|
10876
|
+
}
|
|
10877
|
+
}
|
|
10878
|
+
}
|
|
10879
|
+
}
|
|
10835
10880
|
function shadowSizeOnDisk(tool, rawId) {
|
|
10836
10881
|
try {
|
|
10837
10882
|
return statSync10(shadowFileFor(tool, rawId)).size;
|
|
@@ -10852,7 +10897,7 @@ var init_shadow = __esm({
|
|
|
10852
10897
|
});
|
|
10853
10898
|
|
|
10854
10899
|
// ../engine/dist/core/live-session-scan.js
|
|
10855
|
-
import { existsSync as existsSync13, readdirSync as readdirSync10, readFileSync as readFileSync9, statSync as statSync11, openSync as
|
|
10900
|
+
import { existsSync as existsSync13, readdirSync as readdirSync10, readFileSync as readFileSync9, statSync as statSync11, openSync as openSync5, readSync as readSync5, closeSync as closeSync5 } from "fs";
|
|
10856
10901
|
import { join as join15, basename as basename9 } from "path";
|
|
10857
10902
|
function detectTool(sessionId) {
|
|
10858
10903
|
return getBackendForId(sessionId)?.id ?? "claude";
|
|
@@ -10879,6 +10924,15 @@ function sessionFileIndex() {
|
|
|
10879
10924
|
return indexCache;
|
|
10880
10925
|
const byId = /* @__PURE__ */ new Map();
|
|
10881
10926
|
const seenRoots = /* @__PURE__ */ new Set();
|
|
10927
|
+
const projectPaths = /* @__PURE__ */ new Map();
|
|
10928
|
+
const projectPathOf = (dirName) => {
|
|
10929
|
+
let p = projectPaths.get(dirName);
|
|
10930
|
+
if (p === void 0) {
|
|
10931
|
+
p = resolveProjectDirName(dirName);
|
|
10932
|
+
projectPaths.set(dirName, p);
|
|
10933
|
+
}
|
|
10934
|
+
return p;
|
|
10935
|
+
};
|
|
10882
10936
|
for (const root of claudeProjectDirs()) {
|
|
10883
10937
|
if (seenRoots.has(root) || !existsSync13(root))
|
|
10884
10938
|
continue;
|
|
@@ -10906,7 +10960,7 @@ function sessionFileIndex() {
|
|
|
10906
10960
|
const located = {
|
|
10907
10961
|
path: join15(dir, name),
|
|
10908
10962
|
projectDir: entry.name,
|
|
10909
|
-
projectPath:
|
|
10963
|
+
projectPath: projectPathOf(entry.name)
|
|
10910
10964
|
};
|
|
10911
10965
|
const prior = byId.get(id);
|
|
10912
10966
|
if (prior)
|
|
@@ -11096,7 +11150,7 @@ var init_live_session_scan = __esm({
|
|
|
11096
11150
|
});
|
|
11097
11151
|
|
|
11098
11152
|
// ../engine/dist/core/first-prompt.js
|
|
11099
|
-
import { createReadStream as createReadStream2, existsSync as existsSync14, openSync as
|
|
11153
|
+
import { createReadStream as createReadStream2, existsSync as existsSync14, openSync as openSync6, readSync as readSync6, closeSync as closeSync6 } from "fs";
|
|
11100
11154
|
import { StringDecoder } from "string_decoder";
|
|
11101
11155
|
function stripBanners2(s) {
|
|
11102
11156
|
let out = s;
|
|
@@ -11150,7 +11204,7 @@ function extractFirstUserPromptSync(filePath, options = {}) {
|
|
|
11150
11204
|
const maxBytes = options.maxBytes ?? 4 * 1024 * 1024;
|
|
11151
11205
|
let fd;
|
|
11152
11206
|
try {
|
|
11153
|
-
fd =
|
|
11207
|
+
fd = openSync6(filePath, "r");
|
|
11154
11208
|
} catch {
|
|
11155
11209
|
return "";
|
|
11156
11210
|
}
|
|
@@ -11162,7 +11216,7 @@ function extractFirstUserPromptSync(filePath, options = {}) {
|
|
|
11162
11216
|
let pos = 0;
|
|
11163
11217
|
let lineNo = 0;
|
|
11164
11218
|
for (; ; ) {
|
|
11165
|
-
const n =
|
|
11219
|
+
const n = readSync6(fd, buf, 0, CHUNK, pos);
|
|
11166
11220
|
if (n <= 0)
|
|
11167
11221
|
break;
|
|
11168
11222
|
pos += n;
|
|
@@ -11188,7 +11242,7 @@ function extractFirstUserPromptSync(filePath, options = {}) {
|
|
|
11188
11242
|
return "";
|
|
11189
11243
|
} finally {
|
|
11190
11244
|
try {
|
|
11191
|
-
|
|
11245
|
+
closeSync6(fd);
|
|
11192
11246
|
} catch {
|
|
11193
11247
|
}
|
|
11194
11248
|
}
|
|
@@ -11207,7 +11261,7 @@ var init_first_prompt = __esm({
|
|
|
11207
11261
|
});
|
|
11208
11262
|
|
|
11209
11263
|
// ../engine/dist/core/backends/claude.js
|
|
11210
|
-
import { existsSync as existsSync15, readdirSync as readdirSync11, readFileSync as readFileSync10, statSync as statSync12, openSync as
|
|
11264
|
+
import { existsSync as existsSync15, readdirSync as readdirSync11, readFileSync as readFileSync10, statSync as statSync12, openSync as openSync7, readSync as readSync7, closeSync as closeSync7 } from "fs";
|
|
11211
11265
|
import { join as join16, basename as basename10 } from "path";
|
|
11212
11266
|
function stripReminders(text) {
|
|
11213
11267
|
return text.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/g, "").trim();
|
|
@@ -11304,13 +11358,13 @@ var init_claude2 = __esm({
|
|
|
11304
11358
|
return null;
|
|
11305
11359
|
let head;
|
|
11306
11360
|
try {
|
|
11307
|
-
const fd =
|
|
11361
|
+
const fd = openSync7(located.path, "r");
|
|
11308
11362
|
try {
|
|
11309
11363
|
const buf = Buffer.alloc(65536);
|
|
11310
|
-
const n =
|
|
11364
|
+
const n = readSync7(fd, buf, 0, buf.length, 0);
|
|
11311
11365
|
head = buf.toString("utf-8", 0, n);
|
|
11312
11366
|
} finally {
|
|
11313
|
-
|
|
11367
|
+
closeSync7(fd);
|
|
11314
11368
|
}
|
|
11315
11369
|
} catch {
|
|
11316
11370
|
return null;
|
|
@@ -11782,14 +11836,14 @@ var init_claude2 = __esm({
|
|
|
11782
11836
|
spansMultipleSources(prefixedId) {
|
|
11783
11837
|
return findSessionFiles(this.toRawId(prefixedId)).length > 1;
|
|
11784
11838
|
}
|
|
11785
|
-
async readFromOffset(prefixedId, offset) {
|
|
11839
|
+
async readFromOffset(prefixedId, offset, maxBytes) {
|
|
11786
11840
|
const rawId = this.toRawId(prefixedId);
|
|
11787
11841
|
const copies = findSessionFiles(rawId);
|
|
11788
11842
|
if (copies.length === 0)
|
|
11789
11843
|
return { text: "", newOffset: offset };
|
|
11790
11844
|
if (copies.length > 1)
|
|
11791
11845
|
return { text: "", newOffset: offset };
|
|
11792
|
-
return readTailFromOffset(copies[0].path, offset);
|
|
11846
|
+
return readTailFromOffset(copies[0].path, offset, maxBytes);
|
|
11793
11847
|
}
|
|
11794
11848
|
};
|
|
11795
11849
|
claudeBackend = new ClaudeBackend();
|
|
@@ -13742,10 +13796,10 @@ var init_types = __esm({
|
|
|
13742
13796
|
|
|
13743
13797
|
// ../engine/dist/transcript/opencode.js
|
|
13744
13798
|
async function parseOpenCodeSubagents(parentSessionId) {
|
|
13745
|
-
const { existsSync:
|
|
13799
|
+
const { existsSync: existsSync58 } = await import("fs");
|
|
13746
13800
|
const { opencodeBackend: opencodeBackend2 } = await Promise.resolve().then(() => (init_opencode(), opencode_exports));
|
|
13747
13801
|
const dbPath = opencodeBackend2.dbPath();
|
|
13748
|
-
if (!
|
|
13802
|
+
if (!existsSync58(dbPath))
|
|
13749
13803
|
return [];
|
|
13750
13804
|
const realParent = parentSessionId.replace("opencode_", "");
|
|
13751
13805
|
const db = openSqliteReadonlyOrThrow(dbPath);
|
|
@@ -13786,10 +13840,10 @@ async function parseOpenCodeSubagents(parentSessionId) {
|
|
|
13786
13840
|
}
|
|
13787
13841
|
}
|
|
13788
13842
|
async function parseOpenCodeTranscript(sessionId) {
|
|
13789
|
-
const { existsSync:
|
|
13843
|
+
const { existsSync: existsSync58 } = await import("fs");
|
|
13790
13844
|
const { opencodeBackend: opencodeBackend2 } = await Promise.resolve().then(() => (init_opencode(), opencode_exports));
|
|
13791
13845
|
const dbPath = opencodeBackend2.dbPath();
|
|
13792
|
-
if (!
|
|
13846
|
+
if (!existsSync58(dbPath))
|
|
13793
13847
|
return [];
|
|
13794
13848
|
const realId = sessionId.replace("opencode_", "");
|
|
13795
13849
|
const db = openSqliteReadonlyOrThrow(dbPath);
|
|
@@ -13866,6 +13920,7 @@ __export(transcript_exports, {
|
|
|
13866
13920
|
shadowFileFor: () => shadowFileFor,
|
|
13867
13921
|
shadowRoot: () => shadowRoot,
|
|
13868
13922
|
shadowSizeOnDisk: () => shadowSizeOnDisk,
|
|
13923
|
+
shadowUncompressedBytes: () => shadowUncompressedBytes,
|
|
13869
13924
|
snapshotShadow: () => snapshotShadow,
|
|
13870
13925
|
trimTranscriptForSync: () => trimTranscriptForSync,
|
|
13871
13926
|
updateShadow: () => updateShadow,
|
|
@@ -18335,7 +18390,7 @@ var init_sync_fields = __esm({
|
|
|
18335
18390
|
});
|
|
18336
18391
|
|
|
18337
18392
|
// ../engine/dist/core/index-lock.js
|
|
18338
|
-
import { existsSync as existsSync39, mkdirSync as mkdirSync7, openSync as
|
|
18393
|
+
import { existsSync as existsSync39, mkdirSync as mkdirSync7, openSync as openSync8, writeFileSync as writeFileSync6, readFileSync as readFileSync30, rmSync as rmSync4, statSync as statSync35, closeSync as closeSync8 } from "fs";
|
|
18339
18394
|
import { dirname as dirname16, join as join39 } from "path";
|
|
18340
18395
|
function acquireIndexLock(opts) {
|
|
18341
18396
|
const lockPath = lockFilePath();
|
|
@@ -18347,7 +18402,7 @@ function acquireIndexLock(opts) {
|
|
|
18347
18402
|
}
|
|
18348
18403
|
let fd;
|
|
18349
18404
|
try {
|
|
18350
|
-
fd =
|
|
18405
|
+
fd = openSync8(lockPath, "wx", 384);
|
|
18351
18406
|
} catch (err) {
|
|
18352
18407
|
if (err.code === "EEXIST")
|
|
18353
18408
|
return null;
|
|
@@ -18357,7 +18412,7 @@ function acquireIndexLock(opts) {
|
|
|
18357
18412
|
try {
|
|
18358
18413
|
writeFileSync6(fd, JSON.stringify(holder));
|
|
18359
18414
|
} finally {
|
|
18360
|
-
|
|
18415
|
+
closeSync8(fd);
|
|
18361
18416
|
}
|
|
18362
18417
|
let released = false;
|
|
18363
18418
|
return {
|
|
@@ -18457,7 +18512,7 @@ var init_http = __esm({
|
|
|
18457
18512
|
CLI_VERSION = JSON.parse(readFileSync31(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
|
|
18458
18513
|
} catch {
|
|
18459
18514
|
try {
|
|
18460
|
-
if (true) CLI_VERSION = "0.7.
|
|
18515
|
+
if (true) CLI_VERSION = "0.7.1";
|
|
18461
18516
|
} catch {
|
|
18462
18517
|
}
|
|
18463
18518
|
}
|
|
@@ -18956,7 +19011,7 @@ var init_telemetry = __esm({
|
|
|
18956
19011
|
init_sync_client();
|
|
18957
19012
|
cliVersion2 = () => {
|
|
18958
19013
|
try {
|
|
18959
|
-
return true ? "0.7.
|
|
19014
|
+
return true ? "0.7.1" : "dev";
|
|
18960
19015
|
} catch {
|
|
18961
19016
|
return "dev";
|
|
18962
19017
|
}
|
|
@@ -19312,16 +19367,17 @@ __export(auto_update_exports, {
|
|
|
19312
19367
|
noteUpdateFailure: () => noteUpdateFailure,
|
|
19313
19368
|
planAutoUpdate: () => planAutoUpdate,
|
|
19314
19369
|
readUpdateState: () => readUpdateState,
|
|
19370
|
+
resolveNpm: () => resolveNpm,
|
|
19315
19371
|
runAutoUpdate: () => runAutoUpdate,
|
|
19316
19372
|
runningPrefix: () => runningPrefix,
|
|
19317
19373
|
sweepStaleStaging: () => sweepStaleStaging,
|
|
19318
19374
|
tarballUrl: () => tarballUrl
|
|
19319
19375
|
});
|
|
19320
|
-
import { execSync as execSync2 } from "node:child_process";
|
|
19321
|
-
import { readFileSync as readFileSync34 } from "node:fs";
|
|
19376
|
+
import { execSync as execSync2, execFileSync as execFileSync3 } from "node:child_process";
|
|
19377
|
+
import { readFileSync as readFileSync34, existsSync as existsSync41 } from "node:fs";
|
|
19322
19378
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
19323
19379
|
import { writeFileSync as writeFileSync8, mkdtempSync as mkdtempSync3, rmSync as rmSync5, readdirSync as readdirSync31, statSync as statSync36, mkdirSync as mkdirSync9 } from "node:fs";
|
|
19324
|
-
import { join as join41, dirname as dirname18, sep as sep2 } from "node:path";
|
|
19380
|
+
import { join as join41, dirname as dirname18, sep as sep2, posix as pathPosix, win32 as pathWin32 } from "node:path";
|
|
19325
19381
|
import { tmpdir as tmpdir2, homedir as homedir15 } from "node:os";
|
|
19326
19382
|
import { createHash as createHash8 } from "node:crypto";
|
|
19327
19383
|
function compareVersions(a, b) {
|
|
@@ -19436,25 +19492,46 @@ function runningPrefix(moduleUrl = import.meta.url) {
|
|
|
19436
19492
|
const beforeNodeModules = here.slice(0, at);
|
|
19437
19493
|
return beforeNodeModules.endsWith(`${sep2}lib`) ? beforeNodeModules.slice(0, -4) : beforeNodeModules;
|
|
19438
19494
|
}
|
|
19439
|
-
function npmInstall(
|
|
19495
|
+
function npmInstall(npm, args) {
|
|
19440
19496
|
try {
|
|
19441
|
-
|
|
19497
|
+
const opts = { stdio: ["ignore", "ignore", "pipe"], env: npm.env };
|
|
19498
|
+
if (npm.shell) execSync2([npm.file, ...npm.args, ...args].map((a) => `"${a}"`).join(" "), opts);
|
|
19499
|
+
else execFileSync3(npm.file, [...npm.args, ...args], opts);
|
|
19442
19500
|
} catch (e) {
|
|
19443
19501
|
const err = e;
|
|
19444
19502
|
const detail = String(err.stderr ?? "").trim().split("\n").filter((l) => l.trim() && !/^npm (notice|warn)\b/i.test(l)).slice(-4).join(" | ").slice(0, 400);
|
|
19445
19503
|
throw new Error(detail ? `${err.message ?? "install failed"} \u2014 ${detail}` : err.message ?? "install failed");
|
|
19446
19504
|
}
|
|
19447
19505
|
}
|
|
19506
|
+
function resolveNpm(loc) {
|
|
19507
|
+
const win = loc.platform === "win32";
|
|
19508
|
+
const p = win ? pathWin32 : pathPosix;
|
|
19509
|
+
const nodeDir = p.dirname(loc.execPath);
|
|
19510
|
+
const cliUnder = (root) => win ? p.join(root, "node_modules", "npm", "bin", "npm-cli.js") : p.join(root, "lib", "node_modules", "npm", "bin", "npm-cli.js");
|
|
19511
|
+
const candidates2 = [
|
|
19512
|
+
cliUnder(win ? nodeDir : p.join(nodeDir, "..")),
|
|
19513
|
+
...loc.prefix ? [cliUnder(loc.prefix)] : []
|
|
19514
|
+
];
|
|
19515
|
+
const pathKey = Object.keys(loc.env).find((k) => k.toUpperCase() === "PATH") ?? "PATH";
|
|
19516
|
+
const binDirs = [nodeDir, ...loc.prefix ? [win ? loc.prefix : p.join(loc.prefix, "bin")] : []];
|
|
19517
|
+
const delimiter3 = win ? ";" : ":";
|
|
19518
|
+
const current = loc.env[pathKey] ?? "";
|
|
19519
|
+
const env = { ...loc.env, [pathKey]: [...binDirs, ...current ? [current] : []].join(delimiter3) };
|
|
19520
|
+
const cli = candidates2.find((c) => loc.exists(c));
|
|
19521
|
+
if (cli) return { file: loc.execPath, args: [cli], env, shell: false };
|
|
19522
|
+
return { file: "npm", args: [], env, shell: true };
|
|
19523
|
+
}
|
|
19448
19524
|
function realInstall(tgz) {
|
|
19449
19525
|
const prefix = runningPrefix();
|
|
19526
|
+
const npm = resolveNpm({ execPath: process.execPath, prefix, platform: process.platform, env: process.env, exists: existsSync41 });
|
|
19450
19527
|
if (prefix) {
|
|
19451
|
-
npmInstall(
|
|
19528
|
+
npmInstall(npm, ["install", "-g", "--prefix", prefix, tgz]);
|
|
19452
19529
|
return;
|
|
19453
19530
|
}
|
|
19454
19531
|
try {
|
|
19455
|
-
npmInstall(
|
|
19532
|
+
npmInstall(npm, ["install", "-g", tgz]);
|
|
19456
19533
|
} catch {
|
|
19457
|
-
npmInstall(
|
|
19534
|
+
npmInstall(npm, ["install", "-g", "--prefix", join41(homedir15(), ".local"), tgz]);
|
|
19458
19535
|
}
|
|
19459
19536
|
}
|
|
19460
19537
|
function realRestart(platform2) {
|
|
@@ -19555,7 +19632,9 @@ var init_auto_update = __esm({
|
|
|
19555
19632
|
var sync_client_exports = {};
|
|
19556
19633
|
__export(sync_client_exports, {
|
|
19557
19634
|
BATCH_SCAN_MAX_BYTES: () => BATCH_SCAN_MAX_BYTES,
|
|
19635
|
+
DERIVED_MAX_BYTES: () => DERIVED_MAX_BYTES,
|
|
19558
19636
|
FULL_BUILD_MAX_BYTES: () => FULL_BUILD_MAX_BYTES,
|
|
19637
|
+
SYNC_CHUNK_BYTES: () => SYNC_CHUNK_BYTES,
|
|
19559
19638
|
_acceptedUploads: () => _acceptedUploads,
|
|
19560
19639
|
_fetchTenantSyncConfigForTests: () => _fetchTenantSyncConfigForTests,
|
|
19561
19640
|
_resetCapsCacheForTests: () => _resetCapsCacheForTests,
|
|
@@ -19574,8 +19653,10 @@ __export(sync_client_exports, {
|
|
|
19574
19653
|
reconcileFields: () => reconcileFields,
|
|
19575
19654
|
removeCredentials: () => removeCredentials,
|
|
19576
19655
|
saveCredentials: () => saveCredentials,
|
|
19656
|
+
scanTranscriptFindingsChunked: () => scanTranscriptFindingsChunked,
|
|
19577
19657
|
serverAcceptsGzipBody: () => serverAcceptsGzipBody,
|
|
19578
19658
|
serverIngestConcurrency: () => serverIngestConcurrency,
|
|
19659
|
+
sessionBuildBytes: () => sessionBuildBytes,
|
|
19579
19660
|
sessionFileBytes: () => sessionFileBytes,
|
|
19580
19661
|
setServerIngestConcurrency: () => setServerIngestConcurrency,
|
|
19581
19662
|
syncIncremental: () => syncIncremental,
|
|
@@ -20347,16 +20428,53 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20347
20428
|
clearTimeout(timer);
|
|
20348
20429
|
}
|
|
20349
20430
|
};
|
|
20431
|
+
const postChunkedHead = async (conv, fileSize) => {
|
|
20432
|
+
const headers = { "content-type": "application/json" };
|
|
20433
|
+
if (cred.token) headers.authorization = `Bearer ${cred.token}`;
|
|
20434
|
+
const ac = new AbortController();
|
|
20435
|
+
const timer = setTimeout(() => ac.abort(new Error(`upload timed out after ${UPLOAD_TIMEOUT_MS}ms`)), UPLOAD_TIMEOUT_MS);
|
|
20436
|
+
try {
|
|
20437
|
+
const res = await fetch(`${base3}/api/sync`, {
|
|
20438
|
+
method: "POST",
|
|
20439
|
+
headers,
|
|
20440
|
+
body: JSON.stringify({ conversations: [conv] }),
|
|
20441
|
+
signal: ac.signal
|
|
20442
|
+
});
|
|
20443
|
+
if (!res.ok) throw new Error(`chunked head sync failed: HTTP ${res.status} ${await res.text().catch(() => "")}`);
|
|
20444
|
+
const body = await res.json().catch(() => ({}));
|
|
20445
|
+
const id = conv.session_id;
|
|
20446
|
+
const guarded = (body.shrink_guarded ?? []).find((g) => g.session_id === id);
|
|
20447
|
+
const mtime = conv.mtime;
|
|
20448
|
+
try {
|
|
20449
|
+
if (!guarded) {
|
|
20450
|
+
markSynced(base3, [{ id, mtime, offset: conv.from_offset, size: conv.from_offset, acked: true }]);
|
|
20451
|
+
} else if (typeof guarded.o === "number" && guarded.o > 0 && guarded.o <= fileSize) {
|
|
20452
|
+
markSynced(base3, [{ id, mtime, offset: guarded.o, size: guarded.o, acked: true }]);
|
|
20453
|
+
} else {
|
|
20454
|
+
markSynced(base3, [{ id, mtime }]);
|
|
20455
|
+
}
|
|
20456
|
+
} catch {
|
|
20457
|
+
}
|
|
20458
|
+
appendResults.uploaded++;
|
|
20459
|
+
} finally {
|
|
20460
|
+
clearTimeout(timer);
|
|
20461
|
+
}
|
|
20462
|
+
};
|
|
20350
20463
|
let appendBatch = [];
|
|
20464
|
+
let appendBatchBytes = 0;
|
|
20351
20465
|
const APPEND_BATCH_SIZE = 50;
|
|
20466
|
+
const APPEND_BATCH_MAX_BYTES = SYNC_CHUNK_BYTES;
|
|
20352
20467
|
const appendFlush = async () => {
|
|
20353
20468
|
if (appendBatch.length === 0) return;
|
|
20354
20469
|
const batch = appendBatch;
|
|
20355
20470
|
appendBatch = [];
|
|
20471
|
+
appendBatchBytes = 0;
|
|
20356
20472
|
await postAppend(batch);
|
|
20357
20473
|
};
|
|
20358
|
-
const appendAdd = async (conv) => {
|
|
20474
|
+
const appendAdd = async (conv, bytes = 0) => {
|
|
20475
|
+
if (appendBatch.length > 0 && appendBatchBytes + bytes > APPEND_BATCH_MAX_BYTES) await appendFlush();
|
|
20359
20476
|
appendBatch.push(conv);
|
|
20477
|
+
appendBatchBytes += bytes;
|
|
20360
20478
|
if (appendBatch.length >= APPEND_BATCH_SIZE) await appendFlush();
|
|
20361
20479
|
};
|
|
20362
20480
|
const itemsBatch = makeBatcher("items", 100);
|
|
@@ -20435,7 +20553,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20435
20553
|
let externalFindings = null;
|
|
20436
20554
|
if (scanSecrets) {
|
|
20437
20555
|
externalFindings = /* @__PURE__ */ new Map();
|
|
20438
|
-
const toScan = slice.filter((ref) => modeOf(ref) === "full" &&
|
|
20556
|
+
const toScan = slice.filter((ref) => modeOf(ref) === "full" && sessionBuildBytes(ref) <= FULL_BUILD_MAX_BYTES);
|
|
20439
20557
|
trace?.(`batch secret scan start: ${toScan.length} session(s), \u2264${(BATCH_SCAN_MAX_BYTES / 1048576).toFixed(0)}MB per slice`);
|
|
20440
20558
|
const batch = batchScanExternal(
|
|
20441
20559
|
toScan.map((ref) => ({
|
|
@@ -20479,11 +20597,17 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20479
20597
|
const ack = ledger.get(ref.prefixedId);
|
|
20480
20598
|
try {
|
|
20481
20599
|
const tail = await buildConversationTail(ref, ack.o ?? 0, { mapPath, tenantRules });
|
|
20482
|
-
|
|
20600
|
+
const chunked = sessionBuildBytes(ref) > FULL_BUILD_MAX_BYTES;
|
|
20601
|
+
if (tail && tail.findings.length > 0 && !chunked) {
|
|
20483
20602
|
promotedForFindings = true;
|
|
20484
20603
|
} else if (tail) {
|
|
20485
20604
|
redactions += tail.redactions;
|
|
20486
|
-
await appendAdd(tail.conv);
|
|
20605
|
+
await appendAdd(tail.conv, tail.bytes);
|
|
20606
|
+
if (tail.findings.length > 0) {
|
|
20607
|
+
await appendFlush();
|
|
20608
|
+
const all = await scanTranscriptFindingsChunked(ref, tenantRules);
|
|
20609
|
+
if (all.length > 0) await findingsBatch.add(all);
|
|
20610
|
+
}
|
|
20487
20611
|
walked++;
|
|
20488
20612
|
if (walked % 250 === 0) console.error(`[sync] ${walked}/${slice.length} sessions\u2026`);
|
|
20489
20613
|
continue;
|
|
@@ -20531,12 +20655,13 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20531
20655
|
}
|
|
20532
20656
|
redactions += built.redactions;
|
|
20533
20657
|
if (built.srcHash) shippedHash.set(ref.prefixedId, built.srcHash);
|
|
20534
|
-
await
|
|
20658
|
+
if (built.conv.chunked) await postChunkedHead(built.conv, sessionFileBytes(ref));
|
|
20659
|
+
else await convBatch.add(built.conv);
|
|
20535
20660
|
if (built.findings.length > 0) await findingsBatch.add(built.findings);
|
|
20536
20661
|
if (upload.sessionMeta) {
|
|
20537
20662
|
await accumulateKg(extractEntities(built.kgText, { projectPath: built.projectPath, sourceType: "session", sessionId: ref.prefixedId, validFrom: ref.mtime ? new Date(ref.mtime).toISOString().slice(0, 10) : void 0 }), ref.prefixedId);
|
|
20538
20663
|
}
|
|
20539
|
-
if (upload.sessionMeta && sessionFileBytes(ref) <=
|
|
20664
|
+
if (upload.sessionMeta && sessionFileBytes(ref) <= DERIVED_MAX_BYTES) {
|
|
20540
20665
|
try {
|
|
20541
20666
|
const count = { redactions: 0 };
|
|
20542
20667
|
const offloaded = await scanPool().runDerived({
|
|
@@ -20716,35 +20841,70 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20716
20841
|
scanMs: Math.round(scanMs)
|
|
20717
20842
|
};
|
|
20718
20843
|
}
|
|
20844
|
+
async function scanTranscriptFindingsChunked(ref, tenantRules) {
|
|
20845
|
+
const backend = getBackendForId(ref.prefixedId);
|
|
20846
|
+
const findings = [];
|
|
20847
|
+
if (!backend?.readFromOffset) return findings;
|
|
20848
|
+
let offset = 0;
|
|
20849
|
+
let lineBase = 0;
|
|
20850
|
+
for (; ; ) {
|
|
20851
|
+
const chunk = await backend.readFromOffset(ref.prefixedId, offset, SYNC_CHUNK_BYTES);
|
|
20852
|
+
if (chunk.newOffset <= offset) break;
|
|
20853
|
+
offset = chunk.newOffset;
|
|
20854
|
+
if (chunk.skippedBytes) {
|
|
20855
|
+
lineBase += 1;
|
|
20856
|
+
continue;
|
|
20857
|
+
}
|
|
20858
|
+
try {
|
|
20859
|
+
for (const f of scanTextForFindings(chunk.text)) {
|
|
20860
|
+
findings.push({ session_id: ref.prefixedId, detector: "builtin", rule: f.rule, line: lineBase + f.line, preview: f.preview });
|
|
20861
|
+
}
|
|
20862
|
+
if (tenantRules && tenantRules.length > 0) {
|
|
20863
|
+
for (const f of scanTenantRules(chunk.text, tenantRules)) {
|
|
20864
|
+
findings.push({ session_id: ref.prefixedId, detector: f.detector, rule: f.rule, line: lineBase + f.line, preview: f.preview });
|
|
20865
|
+
}
|
|
20866
|
+
}
|
|
20867
|
+
} catch {
|
|
20868
|
+
}
|
|
20869
|
+
for (let i = chunk.text.indexOf("\n"); i >= 0; i = chunk.text.indexOf("\n", i + 1)) lineBase++;
|
|
20870
|
+
}
|
|
20871
|
+
return dropFuzzyFindings(findings, (f) => ({ detector: f.detector, rule: f.rule }));
|
|
20872
|
+
}
|
|
20719
20873
|
function sessionFileBytes(ref) {
|
|
20720
20874
|
const backend = getBackendForId(ref.prefixedId);
|
|
20721
20875
|
if (!backend?.isAppendOnly?.()) return 0;
|
|
20722
20876
|
return backend.fileSize?.(ref.prefixedId) ?? 0;
|
|
20723
20877
|
}
|
|
20878
|
+
function sessionBuildBytes(ref) {
|
|
20879
|
+
const main = sessionFileBytes(ref);
|
|
20880
|
+
if (main === 0) return 0;
|
|
20881
|
+
return Math.max(main, shadowUncompressedBytes(ref.toolId, ref.rawId));
|
|
20882
|
+
}
|
|
20724
20883
|
async function buildConversationSync(ref, mtime, opts = {}) {
|
|
20725
20884
|
const mapPath = opts.mapPath ?? ((p) => p);
|
|
20726
20885
|
let includeRaw = opts.includeRaw !== false;
|
|
20727
20886
|
let includeMeta = opts.includeMeta !== false;
|
|
20728
20887
|
let srcHash;
|
|
20729
|
-
const
|
|
20730
|
-
|
|
20731
|
-
let
|
|
20732
|
-
let tailOffsetEnd = 0;
|
|
20888
|
+
const oversized = sessionBuildBytes(ref) > FULL_BUILD_MAX_BYTES;
|
|
20889
|
+
let headOffsetEnd = 0;
|
|
20890
|
+
let oversizedFindings = null;
|
|
20733
20891
|
let transcript = null;
|
|
20734
20892
|
let fullestContainer = null;
|
|
20735
20893
|
if (oversized) {
|
|
20736
20894
|
const backend = getBackendForId(ref.prefixedId);
|
|
20737
20895
|
if (!backend?.readFromOffset) return null;
|
|
20738
20896
|
try {
|
|
20739
|
-
|
|
20740
|
-
|
|
20741
|
-
|
|
20742
|
-
|
|
20897
|
+
let head = await backend.readFromOffset(ref.prefixedId, 0, SYNC_CHUNK_BYTES);
|
|
20898
|
+
for (let hops = 0; head.skippedBytes && hops < 8; hops++) {
|
|
20899
|
+
head = await backend.readFromOffset(ref.prefixedId, head.newOffset, SYNC_CHUNK_BYTES);
|
|
20900
|
+
}
|
|
20901
|
+
headOffsetEnd = head.newOffset;
|
|
20902
|
+
const messages = parseTailMessages(ref.toolId, head.text);
|
|
20743
20903
|
if (messages.length > 0) transcript = { messages, subagents: [] };
|
|
20744
20904
|
} catch {
|
|
20745
20905
|
}
|
|
20746
20906
|
includeRaw = false;
|
|
20747
|
-
|
|
20907
|
+
oversizedFindings = await scanTranscriptFindingsChunked(ref, opts.tenantRules);
|
|
20748
20908
|
} else {
|
|
20749
20909
|
try {
|
|
20750
20910
|
const backend = getBackendForId(ref.prefixedId) ?? getBackend("claude");
|
|
@@ -20805,7 +20965,6 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
20805
20965
|
);
|
|
20806
20966
|
let projectPath = ref.projectPath;
|
|
20807
20967
|
const meta = { messageCount: textMessages.length };
|
|
20808
|
-
if (oversized) meta.truncated = true;
|
|
20809
20968
|
if (textMessages.filter((m) => m.role === "user").length <= 1) meta.oneShot = true;
|
|
20810
20969
|
try {
|
|
20811
20970
|
const cwd = ref.fullPath ? readCwdFromJsonl(ref.fullPath) : "";
|
|
@@ -20919,21 +21078,7 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
20919
21078
|
}
|
|
20920
21079
|
scanMs = performance.now() - t0;
|
|
20921
21080
|
}
|
|
20922
|
-
if (
|
|
20923
|
-
const t0 = performance.now();
|
|
20924
|
-
try {
|
|
20925
|
-
for (const f of scanTextForFindings(tailText)) {
|
|
20926
|
-
findings.push({ session_id: ref.prefixedId, detector: "builtin", rule: f.rule, line: f.line, preview: f.preview });
|
|
20927
|
-
}
|
|
20928
|
-
if (opts.tenantRules && opts.tenantRules.length > 0) {
|
|
20929
|
-
for (const f of scanTenantRules(tailText, opts.tenantRules)) {
|
|
20930
|
-
findings.push({ session_id: ref.prefixedId, detector: f.detector, rule: f.rule, line: f.line, preview: f.preview });
|
|
20931
|
-
}
|
|
20932
|
-
}
|
|
20933
|
-
} catch {
|
|
20934
|
-
}
|
|
20935
|
-
scanMs = performance.now() - t0;
|
|
20936
|
-
}
|
|
21081
|
+
if (oversizedFindings) findings.push(...oversizedFindings);
|
|
20937
21082
|
const keptFindings = dropFuzzyFindings(findings, (f) => ({ detector: f.detector, rule: f.rule }));
|
|
20938
21083
|
findings.length = 0;
|
|
20939
21084
|
findings.push(...keptFindings);
|
|
@@ -20979,7 +21124,10 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
20979
21124
|
// (convBatch onFlush uses this, not a recomputed size) so the next
|
|
20980
21125
|
// append's base_offset matches exactly — no spurious continuity misses on
|
|
20981
21126
|
// an actively-growing session. undefined for non-append-only backends.
|
|
20982
|
-
from_offset: oversized ?
|
|
21127
|
+
from_offset: oversized ? headOffsetEnd : getBackendForId(ref.prefixedId)?.fileSize?.(ref.rawId),
|
|
21128
|
+
// The head of a chunked session. The server reports back when its shrink
|
|
21129
|
+
// guard keeps a fuller stored copy, so the client appends from there.
|
|
21130
|
+
...oversized ? { chunked: true } : {},
|
|
20983
21131
|
meta,
|
|
20984
21132
|
mtime
|
|
20985
21133
|
},
|
|
@@ -21001,12 +21149,30 @@ async function buildConversationTail(ref, fromOffset, opts = {}) {
|
|
|
21001
21149
|
const backend = getBackendForId(ref.prefixedId);
|
|
21002
21150
|
if (!backend?.readFromOffset) return null;
|
|
21003
21151
|
const mapPath = opts.mapPath ?? ((p) => p);
|
|
21004
|
-
const { text: tailText, newOffset } = await backend.readFromOffset(ref.prefixedId, fromOffset);
|
|
21005
|
-
if (
|
|
21006
|
-
const messages = parseTailMessages(ref.toolId, tailText);
|
|
21007
|
-
if (messages.length === 0) return null;
|
|
21152
|
+
const { text: tailText, newOffset, skippedBytes } = await backend.readFromOffset(ref.prefixedId, fromOffset, SYNC_CHUNK_BYTES);
|
|
21153
|
+
if (newOffset <= fromOffset) return null;
|
|
21154
|
+
const messages = skippedBytes ? [] : parseTailMessages(ref.toolId, tailText);
|
|
21008
21155
|
const textMessages = messages.filter((m) => m.role !== "summary" && m.content?.trim());
|
|
21009
|
-
|
|
21156
|
+
const hasContent = textMessages.length > 0 || messages.some((m) => m.toolCalls?.length);
|
|
21157
|
+
if (!hasContent) {
|
|
21158
|
+
return {
|
|
21159
|
+
conv: {
|
|
21160
|
+
session_id: ref.prefixedId,
|
|
21161
|
+
tool: ref.toolId,
|
|
21162
|
+
project_path: mapPath(ref.projectPath),
|
|
21163
|
+
append: true,
|
|
21164
|
+
base_offset: fromOffset,
|
|
21165
|
+
from_offset: newOffset,
|
|
21166
|
+
redacted_text: "",
|
|
21167
|
+
envelope: { v: TRANSCRIPT_VERSION, messages: [], subagents: [] },
|
|
21168
|
+
mtime: Math.floor(ref.mtime) || 0
|
|
21169
|
+
},
|
|
21170
|
+
redactions: 0,
|
|
21171
|
+
newOffset,
|
|
21172
|
+
findings: [],
|
|
21173
|
+
bytes: 0
|
|
21174
|
+
};
|
|
21175
|
+
}
|
|
21010
21176
|
const firstUser = textMessages.find((m) => m.role === "user");
|
|
21011
21177
|
if (isInternalToolPrompt(firstUser?.content)) return null;
|
|
21012
21178
|
const count = { redactions: 0 };
|
|
@@ -21049,7 +21215,8 @@ async function buildConversationTail(ref, fromOffset, opts = {}) {
|
|
|
21049
21215
|
},
|
|
21050
21216
|
redactions: count.redactions,
|
|
21051
21217
|
newOffset,
|
|
21052
|
-
findings
|
|
21218
|
+
findings,
|
|
21219
|
+
bytes: Buffer.byteLength(tailText)
|
|
21053
21220
|
};
|
|
21054
21221
|
}
|
|
21055
21222
|
function isSyncSkip(r) {
|
|
@@ -21079,7 +21246,7 @@ async function syncIncremental(opts = {}) {
|
|
|
21079
21246
|
lock.release();
|
|
21080
21247
|
}
|
|
21081
21248
|
}
|
|
21082
|
-
var ownVersion, ERROR_CLASS, STANDING_FAILURE, walkProgressForUpload, lastServerPackSpec, credPath, _securityConfigCache, SECURITY_CONFIG_TTL_MS, _syncConfigCache, EMPTY_SYNC_CONFIG, _fetchTenantSyncConfigForTests, SYNC_RULES_REFUSAL, hashPath, acceptedUploads, MAX_DERIVED_ROW_BYTES, isLocalHost, CAPS_TTL_MS, capsOk, advertisedIngestConc, advertisedGzipBody, FULL_BUILD_MAX_BYTES,
|
|
21249
|
+
var ownVersion, ERROR_CLASS, STANDING_FAILURE, walkProgressForUpload, lastServerPackSpec, credPath, _securityConfigCache, SECURITY_CONFIG_TTL_MS, _syncConfigCache, EMPTY_SYNC_CONFIG, _fetchTenantSyncConfigForTests, SYNC_RULES_REFUSAL, hashPath, acceptedUploads, MAX_DERIVED_ROW_BYTES, isLocalHost, CAPS_TTL_MS, capsOk, advertisedIngestConc, advertisedGzipBody, FULL_BUILD_MAX_BYTES, DERIVED_MAX_BYTES, SYNC_CHUNK_BYTES, BATCH_SCAN_MAX_BYTES;
|
|
21083
21250
|
var init_sync_client = __esm({
|
|
21084
21251
|
"src/sync-client.ts"() {
|
|
21085
21252
|
"use strict";
|
|
@@ -21124,7 +21291,7 @@ var init_sync_client = __esm({
|
|
|
21124
21291
|
ownVersion = JSON.parse(readFileSync35(join42(dir, "../package.json"), "utf-8")).version || ownVersion;
|
|
21125
21292
|
} catch {
|
|
21126
21293
|
try {
|
|
21127
|
-
if (true) ownVersion = "0.7.
|
|
21294
|
+
if (true) ownVersion = "0.7.1";
|
|
21128
21295
|
} catch {
|
|
21129
21296
|
}
|
|
21130
21297
|
}
|
|
@@ -21151,8 +21318,9 @@ var init_sync_client = __esm({
|
|
|
21151
21318
|
capsOk = /* @__PURE__ */ new Map();
|
|
21152
21319
|
advertisedIngestConc = /* @__PURE__ */ new Map();
|
|
21153
21320
|
advertisedGzipBody = /* @__PURE__ */ new Set();
|
|
21154
|
-
FULL_BUILD_MAX_BYTES = Math.max(8, parseInt(process.env.CHAT_RECALL_FULL_BUILD_MAX_MB || "
|
|
21155
|
-
|
|
21321
|
+
FULL_BUILD_MAX_BYTES = Math.max(8, parseInt(process.env.CHAT_RECALL_FULL_BUILD_MAX_MB || "24", 10)) * 1024 * 1024;
|
|
21322
|
+
DERIVED_MAX_BYTES = Math.max(8, parseInt(process.env.CHAT_RECALL_DERIVED_MAX_MB || "64", 10)) * 1024 * 1024;
|
|
21323
|
+
SYNC_CHUNK_BYTES = 8 * 1024 * 1024;
|
|
21156
21324
|
BATCH_SCAN_MAX_BYTES = Math.max(1, parseInt(process.env.CHAT_RECALL_BATCHSCAN_MAX_MB || "64", 10)) * 1024 * 1024;
|
|
21157
21325
|
}
|
|
21158
21326
|
});
|
|
@@ -21273,7 +21441,7 @@ var init_update_notice = __esm({
|
|
|
21273
21441
|
});
|
|
21274
21442
|
|
|
21275
21443
|
// ../engine/dist/core/which.js
|
|
21276
|
-
import { existsSync as
|
|
21444
|
+
import { existsSync as existsSync42, statSync as statSync38, accessSync, constants } from "node:fs";
|
|
21277
21445
|
import { join as join44, isAbsolute as isAbsolute2, delimiter as delimiter2, sep as sep3 } from "node:path";
|
|
21278
21446
|
function executable(p) {
|
|
21279
21447
|
try {
|
|
@@ -21314,7 +21482,7 @@ function resolveOnPath(name) {
|
|
|
21314
21482
|
continue;
|
|
21315
21483
|
for (const c of candidates(name)) {
|
|
21316
21484
|
const full = join44(dir, c);
|
|
21317
|
-
if (
|
|
21485
|
+
if (existsSync42(full) && executable(full))
|
|
21318
21486
|
return full;
|
|
21319
21487
|
}
|
|
21320
21488
|
}
|
|
@@ -21377,7 +21545,7 @@ __export(mcp_clients_exports, {
|
|
|
21377
21545
|
inspectMcpClients: () => inspectMcpClients,
|
|
21378
21546
|
registerMcpEverywhere: () => registerMcpEverywhere
|
|
21379
21547
|
});
|
|
21380
|
-
import { existsSync as
|
|
21548
|
+
import { existsSync as existsSync44, mkdirSync as mkdirSync12, readFileSync as readFileSync37, writeFileSync as writeFileSync12 } from "fs";
|
|
21381
21549
|
import { homedir as homedir16 } from "os";
|
|
21382
21550
|
import { dirname as dirname21, join as join46 } from "path";
|
|
21383
21551
|
function envHome(varName, fallback) {
|
|
@@ -21396,7 +21564,7 @@ function readJsonObject(path) {
|
|
|
21396
21564
|
}
|
|
21397
21565
|
function registerMcpServersJson(target, path, spec) {
|
|
21398
21566
|
let cfg = {};
|
|
21399
|
-
if (
|
|
21567
|
+
if (existsSync44(path)) {
|
|
21400
21568
|
try {
|
|
21401
21569
|
cfg = readJsonObject(path);
|
|
21402
21570
|
} catch (err) {
|
|
@@ -21425,7 +21593,7 @@ function registerOpencodeJson(path, spec) {
|
|
|
21425
21593
|
const id = "opencode";
|
|
21426
21594
|
const label = "OpenCode";
|
|
21427
21595
|
let cfg = {};
|
|
21428
|
-
if (
|
|
21596
|
+
if (existsSync44(path)) {
|
|
21429
21597
|
try {
|
|
21430
21598
|
cfg = readJsonObject(path);
|
|
21431
21599
|
} catch (err) {
|
|
@@ -21464,7 +21632,7 @@ function registerCodexToml(path, spec) {
|
|
|
21464
21632
|
const id = "codex";
|
|
21465
21633
|
const label = "Codex";
|
|
21466
21634
|
const block = codexBlock(spec);
|
|
21467
|
-
const prev =
|
|
21635
|
+
const prev = existsSync44(path) ? readFileSync37(path, "utf-8") : "";
|
|
21468
21636
|
const lines = prev.length ? prev.split("\n") : [];
|
|
21469
21637
|
const start = lines.findIndex((l) => l.trim() === CODEX_HEADER);
|
|
21470
21638
|
if (start === -1) {
|
|
@@ -21505,7 +21673,7 @@ function inspectMcpClients(opts = {}) {
|
|
|
21505
21673
|
return MCP_CLIENTS.map((c) => {
|
|
21506
21674
|
const path = c.configPath(home);
|
|
21507
21675
|
let registered = false;
|
|
21508
|
-
if (
|
|
21676
|
+
if (existsSync44(path)) {
|
|
21509
21677
|
try {
|
|
21510
21678
|
const raw = readFileSync37(path, "utf-8");
|
|
21511
21679
|
registered = c.id === "codex" ? raw.includes(CODEX_HEADER) : !!(JSON.parse(raw).mcpServers?.[MCP_SERVER_NAME] ?? JSON.parse(raw).mcp?.[MCP_SERVER_NAME]);
|
|
@@ -21542,7 +21710,7 @@ var init_mcp_clients = __esm({
|
|
|
21542
21710
|
configPath: (home) => join46(envHome("CHAT_RECALL_CODEX_HOME", join46(home, ".codex")), "config.toml"),
|
|
21543
21711
|
isPresent(home) {
|
|
21544
21712
|
const p = this.configPath(home);
|
|
21545
|
-
return
|
|
21713
|
+
return existsSync44(p) || existsSync44(dirname21(p));
|
|
21546
21714
|
},
|
|
21547
21715
|
register(spec, home) {
|
|
21548
21716
|
return registerCodexToml(this.configPath(home), spec);
|
|
@@ -21555,7 +21723,7 @@ var init_mcp_clients = __esm({
|
|
|
21555
21723
|
configPath: (home) => join46(envHome("XDG_CONFIG_HOME", join46(home, ".config")), "opencode", "opencode.json"),
|
|
21556
21724
|
isPresent(home) {
|
|
21557
21725
|
const p = this.configPath(home);
|
|
21558
|
-
return
|
|
21726
|
+
return existsSync44(p) || existsSync44(dirname21(p));
|
|
21559
21727
|
},
|
|
21560
21728
|
register(spec, home) {
|
|
21561
21729
|
return registerOpencodeJson(this.configPath(home), spec);
|
|
@@ -21569,7 +21737,7 @@ var init_mcp_clients = __esm({
|
|
|
21569
21737
|
bin: "agy",
|
|
21570
21738
|
configPath: (home) => join46(home, ".gemini", "config", "mcp_config.json"),
|
|
21571
21739
|
isPresent(home) {
|
|
21572
|
-
return
|
|
21740
|
+
return existsSync44(join46(home, ".gemini", "antigravity-cli")) || existsSync44(this.configPath(home));
|
|
21573
21741
|
},
|
|
21574
21742
|
register(spec, home) {
|
|
21575
21743
|
return registerMcpServersJson(this, this.configPath(home), spec);
|
|
@@ -21582,7 +21750,7 @@ var init_mcp_clients = __esm({
|
|
|
21582
21750
|
configPath: (home) => join46(home, ".cursor", "mcp.json"),
|
|
21583
21751
|
isPresent(home) {
|
|
21584
21752
|
const p = this.configPath(home);
|
|
21585
|
-
return
|
|
21753
|
+
return existsSync44(p) || existsSync44(dirname21(p));
|
|
21586
21754
|
},
|
|
21587
21755
|
register(spec, home) {
|
|
21588
21756
|
return registerMcpServersJson(this, this.configPath(home), spec);
|
|
@@ -21606,7 +21774,7 @@ __export(companions_exports, {
|
|
|
21606
21774
|
uninstallCodeindex: () => uninstallCodeindex,
|
|
21607
21775
|
unregisterCodeindexMcp: () => unregisterCodeindexMcp
|
|
21608
21776
|
});
|
|
21609
|
-
import { existsSync as
|
|
21777
|
+
import { existsSync as existsSync45, mkdirSync as mkdirSync13, statSync as statSync39, chmodSync as chmodSync4, unlinkSync as unlinkSync3, renameSync as renameSync5, createWriteStream, readFileSync as readFileSync38, writeFileSync as writeFileSync13 } from "node:fs";
|
|
21610
21778
|
import { homedir as homedir17 } from "node:os";
|
|
21611
21779
|
import { join as join47 } from "node:path";
|
|
21612
21780
|
import { execSync as execSync3 } from "node:child_process";
|
|
@@ -21729,7 +21897,7 @@ Refusing to install. The release may have been re-uploaded, or something is serv
|
|
|
21729
21897
|
renameSync5(tmpPath, CODEINDEX_BIN_PATH);
|
|
21730
21898
|
} catch (err) {
|
|
21731
21899
|
try {
|
|
21732
|
-
if (
|
|
21900
|
+
if (existsSync45(tmpPath))
|
|
21733
21901
|
unlinkSync3(tmpPath);
|
|
21734
21902
|
} catch {
|
|
21735
21903
|
}
|
|
@@ -21738,7 +21906,7 @@ Refusing to install. The release may have been re-uploaded, or something is serv
|
|
|
21738
21906
|
return checkCodeindexStatus();
|
|
21739
21907
|
}
|
|
21740
21908
|
function uninstallCodeindex() {
|
|
21741
|
-
if (
|
|
21909
|
+
if (existsSync45(CODEINDEX_BIN_PATH)) {
|
|
21742
21910
|
unlinkSync3(CODEINDEX_BIN_PATH);
|
|
21743
21911
|
return { removed: true, path: CODEINDEX_BIN_PATH };
|
|
21744
21912
|
}
|
|
@@ -21746,7 +21914,7 @@ function uninstallCodeindex() {
|
|
|
21746
21914
|
}
|
|
21747
21915
|
function registerCodeindexMcp(mcpJsonPath, binaryPath) {
|
|
21748
21916
|
let cfg = {};
|
|
21749
|
-
if (
|
|
21917
|
+
if (existsSync45(mcpJsonPath)) {
|
|
21750
21918
|
try {
|
|
21751
21919
|
cfg = JSON.parse(readFileSync38(mcpJsonPath, "utf-8"));
|
|
21752
21920
|
} catch {
|
|
@@ -21761,7 +21929,7 @@ function registerCodeindexMcp(mcpJsonPath, binaryPath) {
|
|
|
21761
21929
|
return { added: true };
|
|
21762
21930
|
}
|
|
21763
21931
|
function unregisterCodeindexMcp(mcpJsonPath) {
|
|
21764
|
-
if (!
|
|
21932
|
+
if (!existsSync45(mcpJsonPath))
|
|
21765
21933
|
return { removed: false };
|
|
21766
21934
|
let cfg;
|
|
21767
21935
|
try {
|
|
@@ -21807,7 +21975,7 @@ __export(install_skills_exports, {
|
|
|
21807
21975
|
skillsSourceDir: () => skillsSourceDir,
|
|
21808
21976
|
uninstallSkills: () => uninstallSkills
|
|
21809
21977
|
});
|
|
21810
|
-
import { readdirSync as readdirSync33, existsSync as
|
|
21978
|
+
import { readdirSync as readdirSync33, existsSync as existsSync46, mkdirSync as mkdirSync14, rmSync as rmSync7, cpSync, writeFileSync as writeFileSync14, readFileSync as readFileSync39, statSync as statSync40, realpathSync as realpathSync4 } from "fs";
|
|
21811
21979
|
import { createHash as createHash11 } from "crypto";
|
|
21812
21980
|
import { join as join48, basename as basename21 } from "path";
|
|
21813
21981
|
function skillsSourceDir() {
|
|
@@ -21846,8 +22014,8 @@ function skillStamp() {
|
|
|
21846
22014
|
}
|
|
21847
22015
|
function bundledSkillNames() {
|
|
21848
22016
|
const src = skillsSourceDir();
|
|
21849
|
-
if (!
|
|
21850
|
-
return readdirSync33(src, { withFileTypes: true }).filter((e) => e.isDirectory() &&
|
|
22017
|
+
if (!existsSync46(src)) return [];
|
|
22018
|
+
return readdirSync33(src, { withFileTypes: true }).filter((e) => e.isDirectory() && existsSync46(join48(src, e.name, "SKILL.md"))).map((e) => e.name).sort();
|
|
21851
22019
|
}
|
|
21852
22020
|
function realPathOrSelf(p) {
|
|
21853
22021
|
try {
|
|
@@ -21871,7 +22039,7 @@ function claudeSkillTargets() {
|
|
|
21871
22039
|
dir,
|
|
21872
22040
|
// Judge each profile on ITS OWN transcripts, not the primary's: a home
|
|
21873
22041
|
// with no projects/ is a directory someone made, not a Claude install.
|
|
21874
|
-
available:
|
|
22042
|
+
available: existsSync46(join48(home, "projects"))
|
|
21875
22043
|
});
|
|
21876
22044
|
}
|
|
21877
22045
|
if (targets.length === 0) {
|
|
@@ -21895,7 +22063,7 @@ function skillTargets() {
|
|
|
21895
22063
|
];
|
|
21896
22064
|
}
|
|
21897
22065
|
function isManaged(dir) {
|
|
21898
|
-
return
|
|
22066
|
+
return existsSync46(join48(dir, MARKER));
|
|
21899
22067
|
}
|
|
21900
22068
|
function installSkills(opts = {}) {
|
|
21901
22069
|
const onlyAvailable = opts.onlyAvailable ?? true;
|
|
@@ -21913,7 +22081,7 @@ function installSkills(opts = {}) {
|
|
|
21913
22081
|
}
|
|
21914
22082
|
for (const name of names) {
|
|
21915
22083
|
const dest = join48(t.dir, name);
|
|
21916
|
-
if (
|
|
22084
|
+
if (existsSync46(dest) && !isManaged(dest)) {
|
|
21917
22085
|
skippedUserOwned.push(name);
|
|
21918
22086
|
continue;
|
|
21919
22087
|
}
|
|
@@ -21933,7 +22101,7 @@ function uninstallSkills() {
|
|
|
21933
22101
|
const perTarget = [];
|
|
21934
22102
|
for (const t of skillTargets()) {
|
|
21935
22103
|
const removed = [];
|
|
21936
|
-
if (!
|
|
22104
|
+
if (!existsSync46(t.dir)) {
|
|
21937
22105
|
perTarget.push({ id: t.id, label: t.label, removed });
|
|
21938
22106
|
continue;
|
|
21939
22107
|
}
|
|
@@ -21957,7 +22125,7 @@ function skillsNeedRefresh() {
|
|
|
21957
22125
|
if (!t.available) continue;
|
|
21958
22126
|
for (const name of names) {
|
|
21959
22127
|
const marker = join48(t.dir, name, MARKER);
|
|
21960
|
-
if (!
|
|
22128
|
+
if (!existsSync46(marker)) return true;
|
|
21961
22129
|
try {
|
|
21962
22130
|
if (readFileSync39(marker, "utf-8").trim() !== cur) return true;
|
|
21963
22131
|
} catch {
|
|
@@ -21975,7 +22143,7 @@ function skillStatus() {
|
|
|
21975
22143
|
let ver = null;
|
|
21976
22144
|
for (const name of names) {
|
|
21977
22145
|
const marker = join48(t.dir, name, MARKER);
|
|
21978
|
-
if (
|
|
22146
|
+
if (existsSync46(marker)) {
|
|
21979
22147
|
installed++;
|
|
21980
22148
|
try {
|
|
21981
22149
|
ver = readFileSync39(marker, "utf-8").trim();
|
|
@@ -22163,7 +22331,7 @@ __export(toolkit_sync_exports, {
|
|
|
22163
22331
|
supportedTargetsFor: () => supportedTargetsFor,
|
|
22164
22332
|
writeMcpEntry: () => writeMcpEntry
|
|
22165
22333
|
});
|
|
22166
|
-
import { existsSync as
|
|
22334
|
+
import { existsSync as existsSync47, mkdirSync as mkdirSync15, readFileSync as readFileSync41, writeFileSync as writeFileSync15, cpSync as cpSync2 } from "fs";
|
|
22167
22335
|
import { dirname as dirname22, join as join50, basename as basename23 } from "path";
|
|
22168
22336
|
import { homedir as homedir19 } from "os";
|
|
22169
22337
|
function supportedTargetsFor(type) {
|
|
@@ -22218,11 +22386,11 @@ function skillsDirFor(tool) {
|
|
|
22218
22386
|
}
|
|
22219
22387
|
function copySkill(row, toTool) {
|
|
22220
22388
|
const skillDir = row.extra.skillDir || dirname22(row.filePath);
|
|
22221
|
-
if (!
|
|
22389
|
+
if (!existsSync47(skillDir))
|
|
22222
22390
|
return { ok: false, status: 404, error: `Source dir missing: ${skillDir}` };
|
|
22223
22391
|
const name = row.extra.skillName || basename23(skillDir);
|
|
22224
22392
|
const targetDir = join50(skillsDirFor(toTool), name);
|
|
22225
|
-
if (
|
|
22393
|
+
if (existsSync47(targetDir))
|
|
22226
22394
|
return { ok: false, status: 409, error: `Already exists: ${targetDir}` };
|
|
22227
22395
|
try {
|
|
22228
22396
|
mkdirSync15(dirname22(targetDir), { recursive: true });
|
|
@@ -22254,7 +22422,7 @@ function readMcpEntry(tool, name) {
|
|
|
22254
22422
|
return entry;
|
|
22255
22423
|
}
|
|
22256
22424
|
for (const t of tries) {
|
|
22257
|
-
if (!
|
|
22425
|
+
if (!existsSync47(t.path))
|
|
22258
22426
|
continue;
|
|
22259
22427
|
try {
|
|
22260
22428
|
const cfg = JSON.parse(readFileSync41(t.path, "utf-8"));
|
|
@@ -22267,7 +22435,7 @@ function readMcpEntry(tool, name) {
|
|
|
22267
22435
|
return null;
|
|
22268
22436
|
}
|
|
22269
22437
|
function readCodexMcpEntry(path, target) {
|
|
22270
|
-
if (!
|
|
22438
|
+
if (!existsSync47(path))
|
|
22271
22439
|
return null;
|
|
22272
22440
|
let content;
|
|
22273
22441
|
try {
|
|
@@ -22321,7 +22489,7 @@ function readCodexMcpEntry(path, target) {
|
|
|
22321
22489
|
}
|
|
22322
22490
|
function writeCodexMcpEntry(path, name, entry) {
|
|
22323
22491
|
let content = "";
|
|
22324
|
-
if (
|
|
22492
|
+
if (existsSync47(path))
|
|
22325
22493
|
content = readFileSync41(path, "utf-8");
|
|
22326
22494
|
const header = `[mcp_servers.${name}]`;
|
|
22327
22495
|
if (content.includes(header))
|
|
@@ -22379,7 +22547,7 @@ function writeMcpEntry(toTool, name, entry) {
|
|
|
22379
22547
|
key2 = "mcp";
|
|
22380
22548
|
}
|
|
22381
22549
|
let cfg = {};
|
|
22382
|
-
if (
|
|
22550
|
+
if (existsSync47(path)) {
|
|
22383
22551
|
try {
|
|
22384
22552
|
cfg = JSON.parse(readFileSync41(path, "utf-8"));
|
|
22385
22553
|
} catch {
|
|
@@ -22443,7 +22611,7 @@ function copyCommandOrAgent(type, row, toTool) {
|
|
|
22443
22611
|
return { ok: false, status: 404, error: `Source unreadable: ${e instanceof Error ? e.message : "failed"}` };
|
|
22444
22612
|
}
|
|
22445
22613
|
const out = emit(type, art, toTool);
|
|
22446
|
-
if (
|
|
22614
|
+
if (existsSync47(out.path))
|
|
22447
22615
|
return { ok: false, status: 409, error: `Already exists: ${out.path}` };
|
|
22448
22616
|
try {
|
|
22449
22617
|
mkdirSync15(dirname22(out.path), { recursive: true });
|
|
@@ -22463,7 +22631,7 @@ function copyInstructions(row, toTool) {
|
|
|
22463
22631
|
return { ok: false, status: 404, error: `Source unreadable: ${e instanceof Error ? e.message : "failed"}` };
|
|
22464
22632
|
}
|
|
22465
22633
|
const out = emit("instructions", art, toTool, row.projectPath || void 0);
|
|
22466
|
-
if (
|
|
22634
|
+
if (existsSync47(out.path))
|
|
22467
22635
|
return { ok: false, status: 409, error: `Already exists: ${out.path}` };
|
|
22468
22636
|
try {
|
|
22469
22637
|
mkdirSync15(dirname22(out.path), { recursive: true });
|
|
@@ -22613,7 +22781,7 @@ __export(toolkit_pull_exports, {
|
|
|
22613
22781
|
planPull: () => planPull,
|
|
22614
22782
|
portableCommand: () => portableCommand
|
|
22615
22783
|
});
|
|
22616
|
-
import { existsSync as
|
|
22784
|
+
import { existsSync as existsSync48, mkdirSync as mkdirSync16, statSync as statSync41, writeFileSync as writeFileSync16 } from "node:fs";
|
|
22617
22785
|
import { dirname as dirname23, join as join51, basename as basename24, isAbsolute as isAbsolute3 } from "node:path";
|
|
22618
22786
|
function isExecutableFile(p) {
|
|
22619
22787
|
try {
|
|
@@ -22766,7 +22934,7 @@ function executePull(rows, opts = {}) {
|
|
|
22766
22934
|
for (const tool of tools) {
|
|
22767
22935
|
const dir = join51(skillsDirFor(tool), name);
|
|
22768
22936
|
const file = join51(dir, "SKILL.md");
|
|
22769
|
-
if (
|
|
22937
|
+
if (existsSync48(file)) {
|
|
22770
22938
|
outcomes.push({ type: "skill", name, tool, status: "present" });
|
|
22771
22939
|
continue;
|
|
22772
22940
|
}
|
|
@@ -22811,7 +22979,7 @@ function executePull(rows, opts = {}) {
|
|
|
22811
22979
|
outcomes.push({ type, name, tool, status: "failed", reason: e instanceof Error ? e.message : "emit failed" });
|
|
22812
22980
|
continue;
|
|
22813
22981
|
}
|
|
22814
|
-
if (
|
|
22982
|
+
if (existsSync48(out.path)) {
|
|
22815
22983
|
outcomes.push({ type, name, tool, status: "present" });
|
|
22816
22984
|
continue;
|
|
22817
22985
|
}
|
|
@@ -22969,7 +23137,7 @@ __export(board_hooks_exports, {
|
|
|
22969
23137
|
removeBoardHooks: () => removeBoardHooks,
|
|
22970
23138
|
resolveCliEntry: () => resolveCliEntry
|
|
22971
23139
|
});
|
|
22972
|
-
import { existsSync as
|
|
23140
|
+
import { existsSync as existsSync49, mkdirSync as mkdirSync17, readFileSync as readFileSync42, writeFileSync as writeFileSync17 } from "node:fs";
|
|
22973
23141
|
import { dirname as dirname24, join as join52 } from "node:path";
|
|
22974
23142
|
function boardHookCommand(execPath, cliEntry, mode) {
|
|
22975
23143
|
return `"${execPath}" "${cliEntry}" task-hook --${mode}`;
|
|
@@ -23009,7 +23177,7 @@ function removeBoardHooks(config2) {
|
|
|
23009
23177
|
return removed;
|
|
23010
23178
|
}
|
|
23011
23179
|
function readConfig(file) {
|
|
23012
|
-
if (!
|
|
23180
|
+
if (!existsSync49(file)) return { hooks: {} };
|
|
23013
23181
|
try {
|
|
23014
23182
|
const parsed = JSON.parse(readFileSync42(file, "utf-8"));
|
|
23015
23183
|
if (!parsed.hooks || typeof parsed.hooks !== "object") parsed.hooks = {};
|
|
@@ -23021,7 +23189,7 @@ function readConfig(file) {
|
|
|
23021
23189
|
function registerBoardHooks(files, execPath, cliEntry) {
|
|
23022
23190
|
const written = [];
|
|
23023
23191
|
for (const file of files) {
|
|
23024
|
-
if (
|
|
23192
|
+
if (existsSync49(file)) {
|
|
23025
23193
|
try {
|
|
23026
23194
|
JSON.parse(readFileSync42(file, "utf-8"));
|
|
23027
23195
|
} catch {
|
|
@@ -23041,7 +23209,7 @@ function registerBoardHooks(files, execPath, cliEntry) {
|
|
|
23041
23209
|
}
|
|
23042
23210
|
function resolveCliEntry(distDir) {
|
|
23043
23211
|
const bundled = join52(distDir, "cli.js");
|
|
23044
|
-
return
|
|
23212
|
+
return existsSync49(bundled) ? bundled : join52(distDir, "cli.ts");
|
|
23045
23213
|
}
|
|
23046
23214
|
var BOARD_HOOKS;
|
|
23047
23215
|
var init_board_hooks = __esm({
|
|
@@ -23144,6 +23312,9 @@ async function repairSession(id, opts = {}) {
|
|
|
23144
23312
|
note: "archive count is a lower bound; the rebuild also unions the on-disk tail"
|
|
23145
23313
|
};
|
|
23146
23314
|
}
|
|
23315
|
+
if (!opts.force && endpoints.every((ep) => (currentOnServer.get(ep.url) ?? 0) >= fullest.messages)) {
|
|
23316
|
+
return { sessionId: id, status: "already-full", fullestMessages: fullest.messages, fullestSource: fullest.source, pushed: [] };
|
|
23317
|
+
}
|
|
23147
23318
|
seedShadow(rawId, fullest.container);
|
|
23148
23319
|
const located = backend.findSession(rawId);
|
|
23149
23320
|
const projectPath = located?.projectPath || cwdFromContainer(fullest.container);
|
|
@@ -23186,7 +23357,7 @@ async function repairSession(id, opts = {}) {
|
|
|
23186
23357
|
try {
|
|
23187
23358
|
const res = await fetchWithTimeout(`${ep.url}/api/sync`, { method: "POST", headers, body: JSON.stringify({ conversations: [built.conv] }) }, 6e4);
|
|
23188
23359
|
if (!res.ok) {
|
|
23189
|
-
pushed.push({ server: ep.url, before, after: before });
|
|
23360
|
+
pushed.push({ server: ep.url, before, after: before, error: `HTTP ${res.status}` });
|
|
23190
23361
|
log6(`push to ${ep.url} FAILED: HTTP ${res.status}`);
|
|
23191
23362
|
continue;
|
|
23192
23363
|
}
|
|
@@ -23195,10 +23366,21 @@ async function repairSession(id, opts = {}) {
|
|
|
23195
23366
|
pushed.push({ server: ep.url, before, after: afterN });
|
|
23196
23367
|
log6(`pushed to ${ep.url}: ${before} \u2192 ${afterN} msg(s)`);
|
|
23197
23368
|
} catch (e) {
|
|
23198
|
-
|
|
23199
|
-
|
|
23369
|
+
const error = e instanceof Error ? e.message : String(e);
|
|
23370
|
+
pushed.push({ server: ep.url, before, after: before, error });
|
|
23371
|
+
log6(`push to ${ep.url} errored: ${error}`);
|
|
23200
23372
|
}
|
|
23201
23373
|
}
|
|
23374
|
+
if (pushed.every((p) => p.error)) {
|
|
23375
|
+
return {
|
|
23376
|
+
sessionId: id,
|
|
23377
|
+
status: "error",
|
|
23378
|
+
fullestMessages: builtCount,
|
|
23379
|
+
fullestSource: fullest.source,
|
|
23380
|
+
pushed,
|
|
23381
|
+
note: `every push failed: ${pushed.map((p) => `${p.server}: ${p.error}`).join("; ")}`
|
|
23382
|
+
};
|
|
23383
|
+
}
|
|
23202
23384
|
return { sessionId: id, status: "repaired", fullestMessages: builtCount, fullestSource: fullest.source, pushed };
|
|
23203
23385
|
}
|
|
23204
23386
|
async function repairSessions(ids, opts = {}) {
|
|
@@ -23693,11 +23875,11 @@ var verify_repair_exports = {};
|
|
|
23693
23875
|
__export(verify_repair_exports, {
|
|
23694
23876
|
forceFullResync: () => forceFullResync
|
|
23695
23877
|
});
|
|
23696
|
-
import { copyFileSync as copyFileSync3, existsSync as
|
|
23878
|
+
import { copyFileSync as copyFileSync3, existsSync as existsSync50 } from "fs";
|
|
23697
23879
|
function forceFullResync(server, sessionIds) {
|
|
23698
23880
|
if (sessionIds.length === 0) return 0;
|
|
23699
23881
|
const path = ledgerFilePath();
|
|
23700
|
-
if (
|
|
23882
|
+
if (existsSync50(path)) {
|
|
23701
23883
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "").replace(/-/g, "");
|
|
23702
23884
|
try {
|
|
23703
23885
|
copyFileSync3(path, `${path}.bak-${stamp}`);
|
|
@@ -24851,7 +25033,7 @@ __export(project_tasks_exports, {
|
|
|
24851
25033
|
pushProjectTaskStatuses: () => pushProjectTaskStatuses,
|
|
24852
25034
|
renderTeamTasksMd: () => renderTeamTasksMd
|
|
24853
25035
|
});
|
|
24854
|
-
import { existsSync as
|
|
25036
|
+
import { existsSync as existsSync51, readFileSync as readFileSync44, writeFileSync as writeFileSync18, mkdirSync as mkdirSync18, statSync as statSync42 } from "node:fs";
|
|
24855
25037
|
import { join as join55, dirname as dirname25 } from "node:path";
|
|
24856
25038
|
import { homedir as homedir21 } from "node:os";
|
|
24857
25039
|
function isTeamTaskStatus(v) {
|
|
@@ -24937,7 +25119,7 @@ async function pushProjectTaskStatuses(base3, authHeaders, opts = {}) {
|
|
|
24937
25119
|
}
|
|
24938
25120
|
for (const project of projects) {
|
|
24939
25121
|
const file = join55(project, fk.filename);
|
|
24940
|
-
if (!
|
|
25122
|
+
if (!existsSync51(file)) continue;
|
|
24941
25123
|
let mtime;
|
|
24942
25124
|
try {
|
|
24943
25125
|
mtime = statSync42(file).mtimeMs;
|
|
@@ -25019,7 +25201,7 @@ __export(intent_drain_exports, {
|
|
|
25019
25201
|
drainSyncIntents: () => drainSyncIntents,
|
|
25020
25202
|
instructionTargets: () => instructionTargets
|
|
25021
25203
|
});
|
|
25022
|
-
import { existsSync as
|
|
25204
|
+
import { existsSync as existsSync52, readFileSync as readFileSync45, writeFileSync as writeFileSync19, appendFileSync, mkdirSync as mkdirSync19 } from "node:fs";
|
|
25023
25205
|
import { join as join56 } from "node:path";
|
|
25024
25206
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
25025
25207
|
import { dirname as dirname26 } from "node:path";
|
|
@@ -25034,7 +25216,7 @@ function instructionTargets(rootPath, isGlobal) {
|
|
|
25034
25216
|
const tools = installed.length ? installed : [INSTRUCTION_TOOLS[0]];
|
|
25035
25217
|
if (isGlobal) return [...new Set(tools.map((t) => instructionsPath(t.id)))];
|
|
25036
25218
|
if (!rootPath) return [];
|
|
25037
|
-
const present = INSTRUCTION_FILENAMES.map((f) => join56(rootPath, f)).filter((p) =>
|
|
25219
|
+
const present = INSTRUCTION_FILENAMES.map((f) => join56(rootPath, f)).filter((p) => existsSync52(p));
|
|
25038
25220
|
if (present.length) return present;
|
|
25039
25221
|
return [...new Set(tools.map((t) => join56(rootPath, instructionsFilename(t.id))))];
|
|
25040
25222
|
}
|
|
@@ -25062,7 +25244,7 @@ function applyCodeRecommendation(intent) {
|
|
|
25062
25244
|
mkdirSync19(dir, { recursive: true });
|
|
25063
25245
|
} catch {
|
|
25064
25246
|
}
|
|
25065
|
-
const existing =
|
|
25247
|
+
const existing = existsSync52(file) ? readFileSync45(file, "utf8") : "";
|
|
25066
25248
|
if (existing.includes(text)) {
|
|
25067
25249
|
skipped.push(file);
|
|
25068
25250
|
continue;
|
|
@@ -25240,7 +25422,7 @@ var init_intent_drain = __esm({
|
|
|
25240
25422
|
ownVersion2 = JSON.parse(readFileSync45(join56(dir, "../package.json"), "utf-8")).version || ownVersion2;
|
|
25241
25423
|
} catch {
|
|
25242
25424
|
try {
|
|
25243
|
-
if (true) ownVersion2 = "0.7.
|
|
25425
|
+
if (true) ownVersion2 = "0.7.1";
|
|
25244
25426
|
} catch {
|
|
25245
25427
|
}
|
|
25246
25428
|
}
|
|
@@ -25441,7 +25623,7 @@ var team_merge_exports = {};
|
|
|
25441
25623
|
__export(team_merge_exports, {
|
|
25442
25624
|
mergePullResult: () => mergePullResult
|
|
25443
25625
|
});
|
|
25444
|
-
import { existsSync as
|
|
25626
|
+
import { existsSync as existsSync53, mkdirSync as mkdirSync20, readFileSync as readFileSync46, rmSync as rmSync8, writeFileSync as writeFileSync20, statSync as statSync43 } from "fs";
|
|
25445
25627
|
import { dirname as dirname27, join as join57 } from "path";
|
|
25446
25628
|
import { createHash as createHash14 } from "crypto";
|
|
25447
25629
|
function installPathFor(art, tool) {
|
|
@@ -25558,7 +25740,7 @@ async function mergePullResult(opts) {
|
|
|
25558
25740
|
if (!path)
|
|
25559
25741
|
continue;
|
|
25560
25742
|
try {
|
|
25561
|
-
if (
|
|
25743
|
+
if (existsSync53(path))
|
|
25562
25744
|
rmSync8(path, { force: true });
|
|
25563
25745
|
await teamInstallsForget(id, row.tool);
|
|
25564
25746
|
report.removed.push({ artifactId: id, path });
|
|
@@ -25576,7 +25758,7 @@ async function mergePullResult(opts) {
|
|
|
25576
25758
|
}
|
|
25577
25759
|
function readFileIfExists(path) {
|
|
25578
25760
|
try {
|
|
25579
|
-
if (!
|
|
25761
|
+
if (!existsSync53(path))
|
|
25580
25762
|
return null;
|
|
25581
25763
|
const s = statSync43(path);
|
|
25582
25764
|
if (!s.isFile())
|
|
@@ -25662,7 +25844,7 @@ var init_vault_crypto = __esm({
|
|
|
25662
25844
|
});
|
|
25663
25845
|
|
|
25664
25846
|
// ../engine/dist/core/vault-source.js
|
|
25665
|
-
import { existsSync as
|
|
25847
|
+
import { existsSync as existsSync54, readdirSync as readdirSync34, statSync as statSync44 } from "fs";
|
|
25666
25848
|
import { extname, join as join58 } from "path";
|
|
25667
25849
|
function* walkVaultSources() {
|
|
25668
25850
|
const t = loadSettings().team.vault;
|
|
@@ -25688,7 +25870,7 @@ function safeStat(path) {
|
|
|
25688
25870
|
}
|
|
25689
25871
|
function* walkClaude() {
|
|
25690
25872
|
const root = claudeBackend.projectsDir();
|
|
25691
|
-
if (!
|
|
25873
|
+
if (!existsSync54(root))
|
|
25692
25874
|
return;
|
|
25693
25875
|
let projectDirs = [];
|
|
25694
25876
|
try {
|
|
@@ -25741,7 +25923,7 @@ function* walkCursor() {
|
|
|
25741
25923
|
}
|
|
25742
25924
|
function* walkCodex() {
|
|
25743
25925
|
const sessionsRoot = join58(codexBackend.homeDir(), "sessions");
|
|
25744
|
-
if (!
|
|
25926
|
+
if (!existsSync54(sessionsRoot))
|
|
25745
25927
|
return;
|
|
25746
25928
|
const stack = [sessionsRoot];
|
|
25747
25929
|
while (stack.length) {
|
|
@@ -25770,7 +25952,7 @@ function* walkCodex() {
|
|
|
25770
25952
|
}
|
|
25771
25953
|
function* walkAgy() {
|
|
25772
25954
|
const brainDir = join58(agyBackend.homeDir(), "brain");
|
|
25773
|
-
if (!
|
|
25955
|
+
if (!existsSync54(brainDir))
|
|
25774
25956
|
return;
|
|
25775
25957
|
let sessionDirs = [];
|
|
25776
25958
|
try {
|
|
@@ -25787,10 +25969,10 @@ function* walkAgy() {
|
|
|
25787
25969
|
continue;
|
|
25788
25970
|
}
|
|
25789
25971
|
let filePath = join58(sessionPath, ".system_generated", "logs", "transcript.jsonl");
|
|
25790
|
-
if (!
|
|
25972
|
+
if (!existsSync54(filePath)) {
|
|
25791
25973
|
filePath = join58(sessionPath, ".system_generated", "logs", "transcript_full.jsonl");
|
|
25792
25974
|
}
|
|
25793
|
-
if (!
|
|
25975
|
+
if (!existsSync54(filePath))
|
|
25794
25976
|
continue;
|
|
25795
25977
|
const s = safeStat(filePath);
|
|
25796
25978
|
if (!s)
|
|
@@ -25826,7 +26008,7 @@ __export(vault_client_exports, {
|
|
|
25826
26008
|
vaultStatus: () => vaultStatus,
|
|
25827
26009
|
vaultSync: () => vaultSync
|
|
25828
26010
|
});
|
|
25829
|
-
import { mkdirSync as mkdirSync21, readFileSync as readFileSync47, writeFileSync as writeFileSync21, existsSync as
|
|
26011
|
+
import { mkdirSync as mkdirSync21, readFileSync as readFileSync47, writeFileSync as writeFileSync21, existsSync as existsSync55 } from "fs";
|
|
25830
26012
|
import { dirname as dirname28, join as join59 } from "path";
|
|
25831
26013
|
function context2() {
|
|
25832
26014
|
const s = loadSettings().team;
|
|
@@ -26039,7 +26221,7 @@ async function vaultRestore(passphrase, opts = {}) {
|
|
|
26039
26221
|
}
|
|
26040
26222
|
try {
|
|
26041
26223
|
const path = importedPathFor(blob.tool, blob.sessionId);
|
|
26042
|
-
if (
|
|
26224
|
+
if (existsSync55(path)) {
|
|
26043
26225
|
const localStat = await import("fs").then((m) => m.statSync(path));
|
|
26044
26226
|
if (Math.abs(localStat.mtimeMs - blob.mtimeSourceMs) < 1) {
|
|
26045
26227
|
report.skipped.push({ sessionId: blob.sessionId, tool: blob.tool, reason: "unchanged" });
|
|
@@ -26122,7 +26304,7 @@ __export(keyring_exports, {
|
|
|
26122
26304
|
psQuote: () => psQuote,
|
|
26123
26305
|
shQuote: () => shQuote
|
|
26124
26306
|
});
|
|
26125
|
-
import { execFileSync as
|
|
26307
|
+
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
26126
26308
|
function probeKeyring(r = realRunner) {
|
|
26127
26309
|
if (r.platform === "darwin") {
|
|
26128
26310
|
try {
|
|
@@ -26234,7 +26416,7 @@ var init_keyring = __esm({
|
|
|
26234
26416
|
ACCOUNT = "vault-passphrase";
|
|
26235
26417
|
realRunner = {
|
|
26236
26418
|
run(file, args, input) {
|
|
26237
|
-
return
|
|
26419
|
+
return execFileSync4(file, args, {
|
|
26238
26420
|
input,
|
|
26239
26421
|
encoding: "utf-8",
|
|
26240
26422
|
stdio: input === void 0 ? ["ignore", "pipe", "pipe"] : ["pipe", "pipe", "pipe"]
|
|
@@ -26669,7 +26851,7 @@ __export(service_installer_exports, {
|
|
|
26669
26851
|
uninstallService: () => uninstallService
|
|
26670
26852
|
});
|
|
26671
26853
|
import { execSync as execSync5 } from "child_process";
|
|
26672
|
-
import { existsSync as
|
|
26854
|
+
import { existsSync as existsSync56, mkdirSync as mkdirSync22, readFileSync as readFileSync48, rmSync as rmSync9, writeFileSync as writeFileSync22 } from "fs";
|
|
26673
26855
|
import { homedir as homedir22 } from "os";
|
|
26674
26856
|
import { join as join60 } from "path";
|
|
26675
26857
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
@@ -26696,7 +26878,7 @@ function isServiceRunning() {
|
|
|
26696
26878
|
return /com\.chat-recall\.watch/.test(tryCmd("launchctl list 2>/dev/null"));
|
|
26697
26879
|
}
|
|
26698
26880
|
if (process.platform === "linux") {
|
|
26699
|
-
return
|
|
26881
|
+
return /^active$/m.test(tryCmd("systemctl --user is-active chat-recall-watch.service 2>/dev/null"));
|
|
26700
26882
|
}
|
|
26701
26883
|
return false;
|
|
26702
26884
|
}
|
|
@@ -26705,7 +26887,7 @@ function refreshServiceDefinition() {
|
|
|
26705
26887
|
try {
|
|
26706
26888
|
const { watchJs, node, logFile } = resolveDaemonPaths();
|
|
26707
26889
|
const unitPath = join60(homedir22(), ".config", "systemd", "user", "chat-recall-watch.service");
|
|
26708
|
-
if (!
|
|
26890
|
+
if (!existsSync56(unitPath)) return false;
|
|
26709
26891
|
const current = readFileSync48(unitPath, "utf8");
|
|
26710
26892
|
if (!current.includes(watchJs)) return false;
|
|
26711
26893
|
const wanted = renderSystemdUnit(watchJs, node, logFile);
|
|
@@ -26772,7 +26954,12 @@ function renderSystemdUnit(watchJs, node, logFile) {
|
|
|
26772
26954
|
// sawtooth. 1536MB keeps GC honest (768 OOMed on the largest subagent-fanout session) with plenty of headroom for the
|
|
26773
26955
|
// largest transcripts.
|
|
26774
26956
|
`ExecStart=${node} --max-old-space-size=1536 ${watchJs}`,
|
|
26775
|
-
|
|
26957
|
+
// ALWAYS: the collector never ends its own work, so any exit systemd did
|
|
26958
|
+
// not ask for is a fault. Under on-failure a clean exit left it dead: on
|
|
26959
|
+
// 2026-09-16 the unit went "inactive (dead) … status=0/SUCCESS" and stayed
|
|
26960
|
+
// down for 8 days, so nothing synced and the auto-update tick, which runs
|
|
26961
|
+
// inside the daemon, never ran. `systemctl stop` still stops it.
|
|
26962
|
+
"Restart=always",
|
|
26776
26963
|
"RestartSec=10",
|
|
26777
26964
|
"Nice=10",
|
|
26778
26965
|
// NEVER STOP RETRYING. systemd's default start limiter gives up after a
|
|
@@ -26868,7 +27055,7 @@ function uninstallService() {
|
|
|
26868
27055
|
} catch {
|
|
26869
27056
|
}
|
|
26870
27057
|
const unitPath = join60(homedir22(), ".config", "systemd", "user", "chat-recall-watch.service");
|
|
26871
|
-
if (
|
|
27058
|
+
if (existsSync56(unitPath)) {
|
|
26872
27059
|
rmSync9(unitPath, { force: true });
|
|
26873
27060
|
removed = true;
|
|
26874
27061
|
}
|
|
@@ -26885,7 +27072,7 @@ function uninstallService() {
|
|
|
26885
27072
|
} catch {
|
|
26886
27073
|
}
|
|
26887
27074
|
let removed = false;
|
|
26888
|
-
if (
|
|
27075
|
+
if (existsSync56(plistPath)) {
|
|
26889
27076
|
rmSync9(plistPath, { force: true });
|
|
26890
27077
|
removed = true;
|
|
26891
27078
|
}
|
|
@@ -27298,7 +27485,7 @@ init_project_resolver();
|
|
|
27298
27485
|
import { config } from "dotenv";
|
|
27299
27486
|
import { Command } from "commander";
|
|
27300
27487
|
import chalk2 from "chalk";
|
|
27301
|
-
import { existsSync as
|
|
27488
|
+
import { existsSync as existsSync57, readFileSync as readFileSync49, writeFileSync as writeFileSync23, realpathSync as realpathSync5 } from "fs";
|
|
27302
27489
|
import { homedir as homedir23 } from "os";
|
|
27303
27490
|
import { join as join61, resolve as resolve2, dirname as dirname29, basename as basename27 } from "path";
|
|
27304
27491
|
|
|
@@ -27407,7 +27594,7 @@ function renderEnvNeeds(needs, installedCount) {
|
|
|
27407
27594
|
|
|
27408
27595
|
// src/star-nudge.ts
|
|
27409
27596
|
init_paths();
|
|
27410
|
-
import { existsSync as
|
|
27597
|
+
import { existsSync as existsSync43, mkdirSync as mkdirSync11, writeFileSync as writeFileSync11 } from "node:fs";
|
|
27411
27598
|
import { dirname as dirname20, join as join45 } from "node:path";
|
|
27412
27599
|
var REPO = "https://github.com/munhq/chat-recall";
|
|
27413
27600
|
function markerPath() {
|
|
@@ -27423,7 +27610,7 @@ function shouldAskForStar(resultCount) {
|
|
|
27423
27610
|
if (suppressed()) return false;
|
|
27424
27611
|
if (!process.stderr.isTTY) return false;
|
|
27425
27612
|
try {
|
|
27426
|
-
return !
|
|
27613
|
+
return !existsSync43(markerPath());
|
|
27427
27614
|
} catch {
|
|
27428
27615
|
return false;
|
|
27429
27616
|
}
|
|
@@ -27464,7 +27651,7 @@ function claudeHookConfigFiles() {
|
|
|
27464
27651
|
const out = [];
|
|
27465
27652
|
const seen = /* @__PURE__ */ new Set();
|
|
27466
27653
|
for (const home of claudeHomeDirs()) {
|
|
27467
|
-
if (!
|
|
27654
|
+
if (!existsSync57(join61(home, "projects"))) continue;
|
|
27468
27655
|
const file = join61(home, "hooks.json");
|
|
27469
27656
|
let key2;
|
|
27470
27657
|
try {
|
|
@@ -28250,7 +28437,7 @@ memory.command("wake-up").description("Generate wake-up context (high-importance
|
|
|
28250
28437
|
try {
|
|
28251
28438
|
const identityFile = getIdentityFilePath();
|
|
28252
28439
|
let identity = "AI coding assistant";
|
|
28253
|
-
if (
|
|
28440
|
+
if (existsSync57(identityFile)) {
|
|
28254
28441
|
identity = readFileSync49(identityFile, "utf-8").trim();
|
|
28255
28442
|
}
|
|
28256
28443
|
const lines = [
|
|
@@ -28351,7 +28538,7 @@ program.command("feedback").argument("<message...>", "what you want to say \u201
|
|
|
28351
28538
|
}
|
|
28352
28539
|
});
|
|
28353
28540
|
program.command("doctor").description("Quick health check across login, server, credentials, hooks, MCP server, and codeindex").option("--purge-local", "Remove the legacy local index (cache.db + vector/KG files) left by pre-thin-collector versions \u2014 storage is server-side now. Requires login; keeps credentials, sync ledger, identity, and the audit log.").action(async (opts) => {
|
|
28354
|
-
const { existsSync:
|
|
28541
|
+
const { existsSync: existsSync58, readFileSync: readFileSync50, statSync: statSync45 } = await import("fs");
|
|
28355
28542
|
const { execSync: execSync6 } = await import("child_process");
|
|
28356
28543
|
const rows = [];
|
|
28357
28544
|
const note = (ok, label, detail) => rows.push({ ok, label, detail });
|
|
@@ -28415,7 +28602,7 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
28415
28602
|
}
|
|
28416
28603
|
}
|
|
28417
28604
|
const credFile = join61(getDataDir(), "credentials.json");
|
|
28418
|
-
if (!
|
|
28605
|
+
if (!existsSync58(credFile)) {
|
|
28419
28606
|
note(false, "Credentials file", `missing \u2014 run \`chat-recall login <server-url>\``);
|
|
28420
28607
|
} else {
|
|
28421
28608
|
try {
|
|
@@ -28430,13 +28617,13 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
28430
28617
|
for (const hooksJson of claudeHookConfigFiles()) {
|
|
28431
28618
|
const profile = basename27(dirname29(hooksJson));
|
|
28432
28619
|
const label = `Claude hooks (${profile})`;
|
|
28433
|
-
if (!
|
|
28620
|
+
if (!existsSync58(hooksJson)) {
|
|
28434
28621
|
note(false, label, `no ${hooksJson} \u2014 run \`chat-recall install-hooks\``);
|
|
28435
28622
|
continue;
|
|
28436
28623
|
}
|
|
28437
28624
|
try {
|
|
28438
28625
|
const readHooks = (file) => {
|
|
28439
|
-
if (!
|
|
28626
|
+
if (!existsSync58(file)) return {};
|
|
28440
28627
|
try {
|
|
28441
28628
|
return JSON.parse(readFileSync50(file, "utf-8")).hooks || {};
|
|
28442
28629
|
} catch {
|
|
@@ -28479,9 +28666,9 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
28479
28666
|
try {
|
|
28480
28667
|
const reg = await Promise.resolve().then(() => (init_guard_registration(), guard_registration_exports));
|
|
28481
28668
|
for (const target2 of reg.guardTargets()) {
|
|
28482
|
-
if (!
|
|
28669
|
+
if (!existsSync58(target2.homeDir)) continue;
|
|
28483
28670
|
const label = `Decision guard \u2014 ${target2.label}`;
|
|
28484
|
-
if (!
|
|
28671
|
+
if (!existsSync58(target2.configPath)) {
|
|
28485
28672
|
note(false, label, `not registered \u2014 run \`chat-recall install-hooks\``);
|
|
28486
28673
|
continue;
|
|
28487
28674
|
}
|
|
@@ -28506,7 +28693,7 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
28506
28693
|
const want = bundledSkillNames2().length;
|
|
28507
28694
|
for (const t of skillTargets2()) {
|
|
28508
28695
|
if (!t.available) continue;
|
|
28509
|
-
const have = want === 0 ? 0 : bundledSkillNames2().filter((n) =>
|
|
28696
|
+
const have = want === 0 ? 0 : bundledSkillNames2().filter((n) => existsSync58(join61(t.dir, n, ".chat-recall-managed"))).length;
|
|
28510
28697
|
note(
|
|
28511
28698
|
have === want,
|
|
28512
28699
|
`Skills \u2014 ${t.label}`,
|
|
@@ -28576,7 +28763,7 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
28576
28763
|
} else if (process.platform === "darwin") {
|
|
28577
28764
|
watchRunning = /com\.chat-recall\.watch/.test(tryCmd2("launchctl list 2>/dev/null"));
|
|
28578
28765
|
} else {
|
|
28579
|
-
watchRunning =
|
|
28766
|
+
watchRunning = /^active$/m.test(tryCmd2("systemctl --user is-active chat-recall-watch.service 2>/dev/null"));
|
|
28580
28767
|
}
|
|
28581
28768
|
note(watchRunning, "Watch daemon", watchRunning ? "running" : "not running (run `chat-recall watch --install-service` to keep collection running)");
|
|
28582
28769
|
const dataDir = getDataDir();
|
|
@@ -28588,7 +28775,7 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
28588
28775
|
join61(dataDir, "index", "knowledge_graph.db"),
|
|
28589
28776
|
join61(dataDir, "index", "metadata.db")
|
|
28590
28777
|
];
|
|
28591
|
-
const legacyPresent = legacyPaths.filter((p) =>
|
|
28778
|
+
const legacyPresent = legacyPaths.filter((p) => existsSync58(p));
|
|
28592
28779
|
if (opts.purgeLocal) {
|
|
28593
28780
|
if (!target) {
|
|
28594
28781
|
note(false, "Purge legacy index", "refused \u2014 log in and `chat-recall sync` first, so your history is on the server before removing local copies");
|
|
@@ -29232,10 +29419,10 @@ tasks.command("pull [dir]").description("Write TEAM_TASKS.md for your tasks in t
|
|
|
29232
29419
|
try {
|
|
29233
29420
|
const { resolveProjectId: resolveProjectId2 } = await Promise.resolve().then(() => (init_project_resolver(), project_resolver_exports));
|
|
29234
29421
|
const { renderTeamTasksMd: renderTeamTasksMd2, parseTeamTasksFile: parseTeamTasksFile2 } = await Promise.resolve().then(() => (init_project_tasks(), project_tasks_exports));
|
|
29235
|
-
const { writeFileSync: writeFileSync24, readFileSync: readFileSync50, existsSync:
|
|
29422
|
+
const { writeFileSync: writeFileSync24, readFileSync: readFileSync50, existsSync: existsSync58 } = await import("node:fs");
|
|
29236
29423
|
const { join: join62 } = await import("node:path");
|
|
29237
29424
|
const file = join62(cwd, "TEAM_TASKS.md");
|
|
29238
|
-
if (!opts.force &&
|
|
29425
|
+
if (!opts.force && existsSync58(file) && parseTeamTasksFile2(readFileSync50(file, "utf8")).length > 0) {
|
|
29239
29426
|
console.error(chalk2.red("TEAM_TASKS.md has unpushed edits."), "Run", chalk2.bold("chat-recall tasks push"), "first, or", chalk2.bold("tasks pull --force"), "to discard.");
|
|
29240
29427
|
process.exit(1);
|
|
29241
29428
|
}
|
|
@@ -29254,10 +29441,10 @@ tasks.command("push [dir]").description("Push TEAM_TASKS.md status edits back to
|
|
|
29254
29441
|
const cwd = dir || process.cwd();
|
|
29255
29442
|
try {
|
|
29256
29443
|
const { parseTeamTasksFile: parseTeamTasksFile2 } = await Promise.resolve().then(() => (init_project_tasks(), project_tasks_exports));
|
|
29257
|
-
const { readFileSync: readFileSync50, existsSync:
|
|
29444
|
+
const { readFileSync: readFileSync50, existsSync: existsSync58 } = await import("node:fs");
|
|
29258
29445
|
const { join: join62 } = await import("node:path");
|
|
29259
29446
|
const file = join62(cwd, "TEAM_TASKS.md");
|
|
29260
|
-
if (!
|
|
29447
|
+
if (!existsSync58(file)) {
|
|
29261
29448
|
console.error(chalk2.red("no TEAM_TASKS.md here \u2014"), "run", chalk2.bold("chat-recall tasks pull"), "first");
|
|
29262
29449
|
process.exit(1);
|
|
29263
29450
|
}
|
|
@@ -29699,10 +29886,10 @@ program.command("task-hook").description("Move a board card when a prompt or a c
|
|
|
29699
29886
|
return;
|
|
29700
29887
|
}
|
|
29701
29888
|
if (!opts.close) return;
|
|
29702
|
-
const { execFileSync:
|
|
29889
|
+
const { execFileSync: execFileSync5 } = await import("node:child_process");
|
|
29703
29890
|
const git2 = (args) => {
|
|
29704
29891
|
try {
|
|
29705
|
-
return
|
|
29892
|
+
return execFileSync5("git", args, {
|
|
29706
29893
|
cwd,
|
|
29707
29894
|
encoding: "utf8",
|
|
29708
29895
|
timeout: 5e3,
|
|
@@ -29744,7 +29931,7 @@ program.command("task-hook").description("Move a board card when a prompt or a c
|
|
|
29744
29931
|
}
|
|
29745
29932
|
});
|
|
29746
29933
|
program.command("install-hooks").description("Install Claude Code hooks (Stop + PreCompact + UserPromptSubmit + SessionEnd + SessionStart) into every Claude profile").option("--uninstall", "Remove hooks instead of installing them").option("--no-resume-hint", "Don't install the UserPromptSubmit resume-hint hook").option("--no-escalate", "Don't install the SessionEnd learnings-escalation hook").option("--no-wakeup", "Don't install the SessionStart wake-up hook").option("--no-guard", "Don't install the PreToolUse decision guard").option("--no-task-board", "Don't install the hooks that claim and close board cards").action(async (opts) => {
|
|
29747
|
-
const { mkdirSync: mkdirSync23, copyFileSync: copyFileSync4, chmodSync: chmodSync5, existsSync:
|
|
29934
|
+
const { mkdirSync: mkdirSync23, copyFileSync: copyFileSync4, chmodSync: chmodSync5, existsSync: existsSync58, readFileSync: readFileSync50, writeFileSync: writeFileSync24, statSync: statSync45, unlinkSync: unlinkSync4 } = await import("fs");
|
|
29748
29935
|
const { fileURLToPath: fileURLToPath6 } = await import("url");
|
|
29749
29936
|
const { boardHookEntries: boardHookEntries2, isBoardHookEntry: isBoardHookEntry2, registerBoardHooks: registerBoardHooks2, resolveCliEntry: resolveCliEntry2 } = await Promise.resolve().then(() => (init_board_hooks(), board_hooks_exports));
|
|
29750
29937
|
const here = fileURLToPath6(new URL(".", import.meta.url));
|
|
@@ -29757,7 +29944,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
29757
29944
|
// freshly added script is only at the root until that build runs.
|
|
29758
29945
|
join61(here, "..", "..", "..", "hooks", name)
|
|
29759
29946
|
];
|
|
29760
|
-
return candidates2.find((p) =>
|
|
29947
|
+
return candidates2.find((p) => existsSync58(p));
|
|
29761
29948
|
};
|
|
29762
29949
|
const sourceSaveHook = findHook("chat_recall_save_hook.sh");
|
|
29763
29950
|
const sourceGuardHook = findHook("chat_recall_guard_hook.sh");
|
|
@@ -29776,7 +29963,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
29776
29963
|
const installedWakeupHook = join61(hooksDir, "chat_recall_wakeup_hook.sh");
|
|
29777
29964
|
const wakeupWiredInSettings = (home) => {
|
|
29778
29965
|
const settings2 = join61(home, "settings.json");
|
|
29779
|
-
if (!
|
|
29966
|
+
if (!existsSync58(settings2)) return false;
|
|
29780
29967
|
try {
|
|
29781
29968
|
const cfg = JSON.parse(readFileSync50(settings2, "utf-8"));
|
|
29782
29969
|
const arr = Array.isArray(cfg.hooks?.SessionStart) ? cfg.hooks.SessionStart : [];
|
|
@@ -29787,7 +29974,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
29787
29974
|
};
|
|
29788
29975
|
const hookConfigFiles = claudeHookConfigFiles();
|
|
29789
29976
|
const readHookConfig = (file) => {
|
|
29790
|
-
if (!
|
|
29977
|
+
if (!existsSync58(file)) return { hooks: {} };
|
|
29791
29978
|
try {
|
|
29792
29979
|
const c = JSON.parse(readFileSync50(file, "utf-8"));
|
|
29793
29980
|
if (!c.hooks || typeof c.hooks !== "object") c.hooks = {};
|
|
@@ -29804,7 +29991,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
29804
29991
|
};
|
|
29805
29992
|
const HOOK_EVENTS = ["Stop", "PreCompact", "UserPromptSubmit", "SessionEnd", "SessionStart", "PreToolUse"];
|
|
29806
29993
|
const readJson4 = (file) => {
|
|
29807
|
-
if (!
|
|
29994
|
+
if (!existsSync58(file)) return {};
|
|
29808
29995
|
try {
|
|
29809
29996
|
return JSON.parse(readFileSync50(file, "utf-8"));
|
|
29810
29997
|
} catch {
|
|
@@ -29815,7 +30002,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
29815
30002
|
const reg = await Promise.resolve().then(() => (init_guard_registration(), guard_registration_exports));
|
|
29816
30003
|
const notes = [];
|
|
29817
30004
|
for (const target of reg.guardTargets()) {
|
|
29818
|
-
if (!
|
|
30005
|
+
if (!existsSync58(target.homeDir)) continue;
|
|
29819
30006
|
const wrapper = join61(hooksDir, reg.guardWrapperName(target.tool));
|
|
29820
30007
|
writeFileSync24(wrapper, reg.guardWrapperSource(target.tool, hookPath));
|
|
29821
30008
|
chmodSync5(wrapper, 493);
|
|
@@ -29836,7 +30023,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
29836
30023
|
const reg = await Promise.resolve().then(() => (init_guard_registration(), guard_registration_exports));
|
|
29837
30024
|
let removed = 0;
|
|
29838
30025
|
for (const target of reg.guardTargets()) {
|
|
29839
|
-
if (!
|
|
30026
|
+
if (!existsSync58(target.configPath)) continue;
|
|
29840
30027
|
if (target.tool === "opencode") {
|
|
29841
30028
|
const body = readFileSync50(target.configPath, "utf-8");
|
|
29842
30029
|
if (!body.includes("chat-recall install-hooks")) continue;
|
|
@@ -29864,7 +30051,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
29864
30051
|
if (filtered.length) config2.hooks[event] = filtered;
|
|
29865
30052
|
else delete config2.hooks[event];
|
|
29866
30053
|
}
|
|
29867
|
-
if (removed === 0 && !
|
|
30054
|
+
if (removed === 0 && !existsSync58(hooksJson)) continue;
|
|
29868
30055
|
writeFileSync24(hooksJson, JSON.stringify(config2, null, 2) + "\n");
|
|
29869
30056
|
total += removed;
|
|
29870
30057
|
console.log(chalk2.green(`\u2713 Removed ${removed} chat-recall hook entr${removed === 1 ? "y" : "ies"} from ${hooksJson}`));
|
|
@@ -30737,8 +30924,8 @@ npm has ${version2}; the server you sync to still serves ${check.serverVersion}.
|
|
|
30737
30924
|
console.log(chalk2.dim(`
|
|
30738
30925
|
Installing ${version2} from npm\u2026`));
|
|
30739
30926
|
try {
|
|
30740
|
-
const { execFileSync:
|
|
30741
|
-
|
|
30927
|
+
const { execFileSync: execFileSync5 } = await import("node:child_process");
|
|
30928
|
+
execFileSync5("npm", ["install", "-g", `chat-recall@${version2}`], { stdio: "inherit" });
|
|
30742
30929
|
const { installedVersion: installedVersion2 } = await Promise.resolve().then(() => (init_auto_update(), auto_update_exports));
|
|
30743
30930
|
const landed = installedVersion2();
|
|
30744
30931
|
if (landed && compareVersions2(landed, version2) >= 0) {
|