chat-recall 0.7.16 → 0.7.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +573 -331
- package/dist/mcp-relay.js +136 -40
- package/dist/mcp-relay.js.map +1 -1
- package/dist/mcp.js +381 -128
- package/dist/mcp.js.map +1 -1
- package/dist/raw-archive-parts.d.ts +46 -0
- package/dist/raw-archive-parts.d.ts.map +1 -0
- package/dist/raw-archive-parts.js +175 -0
- package/dist/raw-archive-parts.js.map +1 -0
- package/dist/relay-lifecycle.d.ts +23 -0
- package/dist/relay-lifecycle.d.ts.map +1 -1
- package/dist/relay-lifecycle.js +173 -0
- package/dist/relay-lifecycle.js.map +1 -1
- package/dist/repair.d.ts.map +1 -1
- package/dist/repair.js +15 -7
- package/dist/repair.js.map +1 -1
- package/dist/scan-worker.js +2 -0
- package/dist/sync-client.d.ts +8 -0
- package/dist/sync-client.d.ts.map +1 -1
- package/dist/sync-client.js +86 -5
- package/dist/sync-client.js.map +1 -1
- package/dist/sync-ledger.d.ts +31 -1
- package/dist/sync-ledger.d.ts.map +1 -1
- package/dist/sync-ledger.js +47 -1
- package/dist/sync-ledger.js.map +1 -1
- package/dist/watch.js +447 -202
- package/package.json +1 -1
package/dist/mcp.js
CHANGED
|
@@ -2034,7 +2034,7 @@ var require_thread_stream = __commonJS({
|
|
|
2034
2034
|
var { version: version2 } = require_package();
|
|
2035
2035
|
var { EventEmitter } = __require("events");
|
|
2036
2036
|
var { Worker: Worker2 } = __require("worker_threads");
|
|
2037
|
-
var { join:
|
|
2037
|
+
var { join: join54 } = __require("path");
|
|
2038
2038
|
var { pathToFileURL } = __require("url");
|
|
2039
2039
|
var { wait } = require_wait();
|
|
2040
2040
|
var {
|
|
@@ -2077,7 +2077,7 @@ var require_thread_stream = __commonJS({
|
|
|
2077
2077
|
function createWorker(stream, opts) {
|
|
2078
2078
|
const { filename, workerData } = opts;
|
|
2079
2079
|
const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {};
|
|
2080
|
-
const toExecute = bundlerOverrides["thread-stream-worker"] ||
|
|
2080
|
+
const toExecute = bundlerOverrides["thread-stream-worker"] || join54(__dirname, "lib", "worker.js");
|
|
2081
2081
|
const worker = new Worker2(toExecute, {
|
|
2082
2082
|
...opts.workerOpts,
|
|
2083
2083
|
trackUnmanagedFds: false,
|
|
@@ -2480,7 +2480,7 @@ var require_transport = __commonJS({
|
|
|
2480
2480
|
"use strict";
|
|
2481
2481
|
var { createRequire: createRequire3 } = __require("module");
|
|
2482
2482
|
var getCallers = require_caller();
|
|
2483
|
-
var { join:
|
|
2483
|
+
var { join: join54, isAbsolute: isAbsolute3, sep: sep4 } = __require("node:path");
|
|
2484
2484
|
var sleep = require_atomic_sleep();
|
|
2485
2485
|
var onExit = require_on_exit_leak_free();
|
|
2486
2486
|
var ThreadStream = require_thread_stream();
|
|
@@ -2543,7 +2543,7 @@ var require_transport = __commonJS({
|
|
|
2543
2543
|
throw new Error("only one of target or targets can be specified");
|
|
2544
2544
|
}
|
|
2545
2545
|
if (targets) {
|
|
2546
|
-
target = bundlerOverrides["pino-worker"] ||
|
|
2546
|
+
target = bundlerOverrides["pino-worker"] || join54(__dirname, "worker.js");
|
|
2547
2547
|
options.targets = targets.filter((dest) => dest.target).map((dest) => {
|
|
2548
2548
|
return {
|
|
2549
2549
|
...dest,
|
|
@@ -2561,7 +2561,7 @@ var require_transport = __commonJS({
|
|
|
2561
2561
|
});
|
|
2562
2562
|
});
|
|
2563
2563
|
} else if (pipeline) {
|
|
2564
|
-
target = bundlerOverrides["pino-worker"] ||
|
|
2564
|
+
target = bundlerOverrides["pino-worker"] || join54(__dirname, "worker.js");
|
|
2565
2565
|
options.pipelines = [pipeline.map((dest) => {
|
|
2566
2566
|
return {
|
|
2567
2567
|
...dest,
|
|
@@ -2583,7 +2583,7 @@ var require_transport = __commonJS({
|
|
|
2583
2583
|
return origin;
|
|
2584
2584
|
}
|
|
2585
2585
|
if (origin === "pino/file") {
|
|
2586
|
-
return
|
|
2586
|
+
return join54(__dirname, "..", "file.js");
|
|
2587
2587
|
}
|
|
2588
2588
|
let fixTarget2;
|
|
2589
2589
|
for (const filePath of callers) {
|
|
@@ -3572,7 +3572,7 @@ var require_safe_stable_stringify = __commonJS({
|
|
|
3572
3572
|
return circularValue;
|
|
3573
3573
|
}
|
|
3574
3574
|
let res = "";
|
|
3575
|
-
let
|
|
3575
|
+
let join54 = ",";
|
|
3576
3576
|
const originalIndentation = indentation;
|
|
3577
3577
|
if (Array.isArray(value)) {
|
|
3578
3578
|
if (value.length === 0) {
|
|
@@ -3586,7 +3586,7 @@ var require_safe_stable_stringify = __commonJS({
|
|
|
3586
3586
|
indentation += spacer;
|
|
3587
3587
|
res += `
|
|
3588
3588
|
${indentation}`;
|
|
3589
|
-
|
|
3589
|
+
join54 = `,
|
|
3590
3590
|
${indentation}`;
|
|
3591
3591
|
}
|
|
3592
3592
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
@@ -3594,13 +3594,13 @@ ${indentation}`;
|
|
|
3594
3594
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
3595
3595
|
const tmp2 = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
|
|
3596
3596
|
res += tmp2 !== void 0 ? tmp2 : "null";
|
|
3597
|
-
res +=
|
|
3597
|
+
res += join54;
|
|
3598
3598
|
}
|
|
3599
3599
|
const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
|
|
3600
3600
|
res += tmp !== void 0 ? tmp : "null";
|
|
3601
3601
|
if (value.length - 1 > maximumBreadth) {
|
|
3602
3602
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
3603
|
-
res += `${
|
|
3603
|
+
res += `${join54}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
3604
3604
|
}
|
|
3605
3605
|
if (spacer !== "") {
|
|
3606
3606
|
res += `
|
|
@@ -3621,7 +3621,7 @@ ${originalIndentation}`;
|
|
|
3621
3621
|
let separator = "";
|
|
3622
3622
|
if (spacer !== "") {
|
|
3623
3623
|
indentation += spacer;
|
|
3624
|
-
|
|
3624
|
+
join54 = `,
|
|
3625
3625
|
${indentation}`;
|
|
3626
3626
|
whitespace = " ";
|
|
3627
3627
|
}
|
|
@@ -3635,13 +3635,13 @@ ${indentation}`;
|
|
|
3635
3635
|
const tmp = stringifyFnReplacer(key3, value, stack, replacer, spacer, indentation);
|
|
3636
3636
|
if (tmp !== void 0) {
|
|
3637
3637
|
res += `${separator}${strEscape(key3)}:${whitespace}${tmp}`;
|
|
3638
|
-
separator =
|
|
3638
|
+
separator = join54;
|
|
3639
3639
|
}
|
|
3640
3640
|
}
|
|
3641
3641
|
if (keyLength > maximumBreadth) {
|
|
3642
3642
|
const removedKeys = keyLength - maximumBreadth;
|
|
3643
3643
|
res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`;
|
|
3644
|
-
separator =
|
|
3644
|
+
separator = join54;
|
|
3645
3645
|
}
|
|
3646
3646
|
if (spacer !== "" && separator.length > 1) {
|
|
3647
3647
|
res = `
|
|
@@ -3682,7 +3682,7 @@ ${originalIndentation}`;
|
|
|
3682
3682
|
}
|
|
3683
3683
|
const originalIndentation = indentation;
|
|
3684
3684
|
let res = "";
|
|
3685
|
-
let
|
|
3685
|
+
let join54 = ",";
|
|
3686
3686
|
if (Array.isArray(value)) {
|
|
3687
3687
|
if (value.length === 0) {
|
|
3688
3688
|
return "[]";
|
|
@@ -3695,7 +3695,7 @@ ${originalIndentation}`;
|
|
|
3695
3695
|
indentation += spacer;
|
|
3696
3696
|
res += `
|
|
3697
3697
|
${indentation}`;
|
|
3698
|
-
|
|
3698
|
+
join54 = `,
|
|
3699
3699
|
${indentation}`;
|
|
3700
3700
|
}
|
|
3701
3701
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
@@ -3703,13 +3703,13 @@ ${indentation}`;
|
|
|
3703
3703
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
3704
3704
|
const tmp2 = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
|
|
3705
3705
|
res += tmp2 !== void 0 ? tmp2 : "null";
|
|
3706
|
-
res +=
|
|
3706
|
+
res += join54;
|
|
3707
3707
|
}
|
|
3708
3708
|
const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
|
|
3709
3709
|
res += tmp !== void 0 ? tmp : "null";
|
|
3710
3710
|
if (value.length - 1 > maximumBreadth) {
|
|
3711
3711
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
3712
|
-
res += `${
|
|
3712
|
+
res += `${join54}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
3713
3713
|
}
|
|
3714
3714
|
if (spacer !== "") {
|
|
3715
3715
|
res += `
|
|
@@ -3722,7 +3722,7 @@ ${originalIndentation}`;
|
|
|
3722
3722
|
let whitespace = "";
|
|
3723
3723
|
if (spacer !== "") {
|
|
3724
3724
|
indentation += spacer;
|
|
3725
|
-
|
|
3725
|
+
join54 = `,
|
|
3726
3726
|
${indentation}`;
|
|
3727
3727
|
whitespace = " ";
|
|
3728
3728
|
}
|
|
@@ -3731,7 +3731,7 @@ ${indentation}`;
|
|
|
3731
3731
|
const tmp = stringifyArrayReplacer(key3, value[key3], stack, replacer, spacer, indentation);
|
|
3732
3732
|
if (tmp !== void 0) {
|
|
3733
3733
|
res += `${separator}${strEscape(key3)}:${whitespace}${tmp}`;
|
|
3734
|
-
separator =
|
|
3734
|
+
separator = join54;
|
|
3735
3735
|
}
|
|
3736
3736
|
}
|
|
3737
3737
|
if (spacer !== "" && separator.length > 1) {
|
|
@@ -3789,20 +3789,20 @@ ${originalIndentation}`;
|
|
|
3789
3789
|
indentation += spacer;
|
|
3790
3790
|
let res2 = `
|
|
3791
3791
|
${indentation}`;
|
|
3792
|
-
const
|
|
3792
|
+
const join55 = `,
|
|
3793
3793
|
${indentation}`;
|
|
3794
3794
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
3795
3795
|
let i = 0;
|
|
3796
3796
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
3797
3797
|
const tmp2 = stringifyIndent(String(i), value[i], stack, spacer, indentation);
|
|
3798
3798
|
res2 += tmp2 !== void 0 ? tmp2 : "null";
|
|
3799
|
-
res2 +=
|
|
3799
|
+
res2 += join55;
|
|
3800
3800
|
}
|
|
3801
3801
|
const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation);
|
|
3802
3802
|
res2 += tmp !== void 0 ? tmp : "null";
|
|
3803
3803
|
if (value.length - 1 > maximumBreadth) {
|
|
3804
3804
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
3805
|
-
res2 += `${
|
|
3805
|
+
res2 += `${join55}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
3806
3806
|
}
|
|
3807
3807
|
res2 += `
|
|
3808
3808
|
${originalIndentation}`;
|
|
@@ -3818,16 +3818,16 @@ ${originalIndentation}`;
|
|
|
3818
3818
|
return '"[Object]"';
|
|
3819
3819
|
}
|
|
3820
3820
|
indentation += spacer;
|
|
3821
|
-
const
|
|
3821
|
+
const join54 = `,
|
|
3822
3822
|
${indentation}`;
|
|
3823
3823
|
let res = "";
|
|
3824
3824
|
let separator = "";
|
|
3825
3825
|
let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
|
|
3826
3826
|
if (isTypedArrayWithEntries(value)) {
|
|
3827
|
-
res += stringifyTypedArray(value,
|
|
3827
|
+
res += stringifyTypedArray(value, join54, maximumBreadth);
|
|
3828
3828
|
keys = keys.slice(value.length);
|
|
3829
3829
|
maximumPropertiesToStringify -= value.length;
|
|
3830
|
-
separator =
|
|
3830
|
+
separator = join54;
|
|
3831
3831
|
}
|
|
3832
3832
|
if (deterministic) {
|
|
3833
3833
|
keys = sort(keys, comparator);
|
|
@@ -3838,13 +3838,13 @@ ${indentation}`;
|
|
|
3838
3838
|
const tmp = stringifyIndent(key3, value[key3], stack, spacer, indentation);
|
|
3839
3839
|
if (tmp !== void 0) {
|
|
3840
3840
|
res += `${separator}${strEscape(key3)}: ${tmp}`;
|
|
3841
|
-
separator =
|
|
3841
|
+
separator = join54;
|
|
3842
3842
|
}
|
|
3843
3843
|
}
|
|
3844
3844
|
if (keyLength > maximumBreadth) {
|
|
3845
3845
|
const removedKeys = keyLength - maximumBreadth;
|
|
3846
3846
|
res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`;
|
|
3847
|
-
separator =
|
|
3847
|
+
separator = join54;
|
|
3848
3848
|
}
|
|
3849
3849
|
if (separator !== "") {
|
|
3850
3850
|
res = `
|
|
@@ -11680,6 +11680,7 @@ var init_from_events = __esm({
|
|
|
11680
11680
|
// ../engine/dist/transcript/raw.js
|
|
11681
11681
|
var raw_exports = {};
|
|
11682
11682
|
__export(raw_exports, {
|
|
11683
|
+
RAW_PARSE_MAX_BYTES: () => RAW_PARSE_MAX_BYTES,
|
|
11683
11684
|
archiveRawSession: () => archiveRawSession,
|
|
11684
11685
|
buildRawContainer: () => buildRawContainer,
|
|
11685
11686
|
containerSrcHash: () => containerSrcHash,
|
|
@@ -11979,11 +11980,11 @@ async function archiveRawSession(store2, sessionId) {
|
|
|
11979
11980
|
return await store2.putRawSession(sessionId, exp.tool, Math.floor(exp.mtime), gz, size);
|
|
11980
11981
|
}
|
|
11981
11982
|
function detectForkPredecessor(sessionPath) {
|
|
11982
|
-
const { readFileSync:
|
|
11983
|
-
const { dirname: dirname21, join:
|
|
11983
|
+
const { readFileSync: readFileSync45, readdirSync: readdirSync34 } = requireFs();
|
|
11984
|
+
const { dirname: dirname21, join: join54, basename: basename24 } = requirePath();
|
|
11984
11985
|
let text;
|
|
11985
11986
|
try {
|
|
11986
|
-
text =
|
|
11987
|
+
text = readFileSync45(sessionPath, "utf-8");
|
|
11987
11988
|
} catch {
|
|
11988
11989
|
return null;
|
|
11989
11990
|
}
|
|
@@ -12017,7 +12018,7 @@ function detectForkPredecessor(sessionPath) {
|
|
|
12017
12018
|
if (!f.endsWith(".jsonl") || f === self || f === "sessions-index.json")
|
|
12018
12019
|
continue;
|
|
12019
12020
|
try {
|
|
12020
|
-
if (
|
|
12021
|
+
if (readFileSync45(join54(dir, f), "utf-8").includes(`"uuid":"${headParent}"`)) {
|
|
12021
12022
|
return basename24(f, ".jsonl");
|
|
12022
12023
|
}
|
|
12023
12024
|
} catch {
|
|
@@ -12031,7 +12032,7 @@ function requireFs() {
|
|
|
12031
12032
|
function requirePath() {
|
|
12032
12033
|
return pathMod;
|
|
12033
12034
|
}
|
|
12034
|
-
var MARKER_QUOTE;
|
|
12035
|
+
var RAW_PARSE_MAX_BYTES, MARKER_QUOTE;
|
|
12035
12036
|
var init_raw = __esm({
|
|
12036
12037
|
"../engine/dist/transcript/raw.js"() {
|
|
12037
12038
|
"use strict";
|
|
@@ -12039,6 +12040,7 @@ var init_raw = __esm({
|
|
|
12039
12040
|
init_claude2();
|
|
12040
12041
|
init_codex2();
|
|
12041
12042
|
init_from_events();
|
|
12043
|
+
RAW_PARSE_MAX_BYTES = 40 * 1024 * 1024;
|
|
12042
12044
|
MARKER_QUOTE = /\[REDACTED:[A-Za-z0-9_-]+\]"/g;
|
|
12043
12045
|
}
|
|
12044
12046
|
});
|
|
@@ -12195,18 +12197,20 @@ function updateShadow(sessionId, exp, prebuilt) {
|
|
|
12195
12197
|
const curHash = containerSrcHash(current);
|
|
12196
12198
|
if (!prior) {
|
|
12197
12199
|
current.srcHash = curHash;
|
|
12200
|
+
current.mergeVersion = SHADOW_MERGE_VERSION;
|
|
12198
12201
|
try {
|
|
12199
12202
|
writeShadowContainer(tool, rawId, current);
|
|
12200
12203
|
} catch {
|
|
12201
12204
|
}
|
|
12202
12205
|
return { status: "created", sessionId, tool, container: current, recovered: 0, path: path2 };
|
|
12203
12206
|
}
|
|
12204
|
-
if (prior.srcHash && prior.srcHash === curHash) {
|
|
12207
|
+
if (prior.srcHash && prior.srcHash === curHash && prior.mergeVersion === SHADOW_MERGE_VERSION) {
|
|
12205
12208
|
return { status: "unchanged", sessionId, tool, container: prior, recovered: 0, path: path2 };
|
|
12206
12209
|
}
|
|
12207
12210
|
const merged = mergeContainer(prior, current);
|
|
12208
|
-
if (merged.status !== "unchanged" || prior.srcHash !== curHash) {
|
|
12211
|
+
if (merged.status !== "unchanged" || prior.srcHash !== curHash || prior.mergeVersion !== SHADOW_MERGE_VERSION) {
|
|
12209
12212
|
merged.container.srcHash = curHash;
|
|
12213
|
+
merged.container.mergeVersion = SHADOW_MERGE_VERSION;
|
|
12210
12214
|
try {
|
|
12211
12215
|
writeShadowContainer(tool, rawId, merged.container);
|
|
12212
12216
|
} catch {
|
|
@@ -12244,7 +12248,7 @@ function shadowUncompressedBytes(tool, rawId) {
|
|
|
12244
12248
|
}
|
|
12245
12249
|
}
|
|
12246
12250
|
}
|
|
12247
|
-
var WHOLE_FILE_TOOLS, STATE_META;
|
|
12251
|
+
var WHOLE_FILE_TOOLS, STATE_META, SHADOW_MERGE_VERSION;
|
|
12248
12252
|
var init_shadow = __esm({
|
|
12249
12253
|
"../engine/dist/transcript/shadow.js"() {
|
|
12250
12254
|
"use strict";
|
|
@@ -12252,6 +12256,7 @@ var init_shadow = __esm({
|
|
|
12252
12256
|
init_raw();
|
|
12253
12257
|
WHOLE_FILE_TOOLS = /* @__PURE__ */ new Set(["cursor"]);
|
|
12254
12258
|
STATE_META = /* @__PURE__ */ new Set(["mode", "permission-mode", "ai-title", "last-prompt", "pr-link", "summary"]);
|
|
12259
|
+
SHADOW_MERGE_VERSION = 2;
|
|
12255
12260
|
}
|
|
12256
12261
|
});
|
|
12257
12262
|
|
|
@@ -19731,6 +19736,11 @@ function markSynced(server, rows) {
|
|
|
19731
19736
|
base2.s = s;
|
|
19732
19737
|
}
|
|
19733
19738
|
if (r.hash !== void 0) base2.h = r.hash;
|
|
19739
|
+
const completesChunked = cursorFromCaller && r.chunkFinal === true && prev?.k === 1;
|
|
19740
|
+
if (cursorFromCaller && (r.full || completesChunked) && o > 0) base2.F = o;
|
|
19741
|
+
else if (prev?.F !== void 0) base2.F = prev.F;
|
|
19742
|
+
if (cursorFromCaller && r.chunkedHead) base2.k = 1;
|
|
19743
|
+
else if (prev?.k && !completesChunked && !(cursorFromCaller && r.full)) base2.k = 1;
|
|
19734
19744
|
forServer[r.id] = base2;
|
|
19735
19745
|
}
|
|
19736
19746
|
persist(data);
|
|
@@ -19787,6 +19797,14 @@ function markFieldFullPassDone(server, field) {
|
|
|
19787
19797
|
delete st.force[field.name];
|
|
19788
19798
|
persistReconcile(data);
|
|
19789
19799
|
}
|
|
19800
|
+
function forgetFullCoverage(server, sessionId) {
|
|
19801
|
+
const data = load();
|
|
19802
|
+
const row = data[server]?.[sessionId];
|
|
19803
|
+
if (!row || typeof row !== "object") return;
|
|
19804
|
+
delete row.F;
|
|
19805
|
+
delete row.h;
|
|
19806
|
+
persist(data);
|
|
19807
|
+
}
|
|
19790
19808
|
function markFullResync(server, sessionId) {
|
|
19791
19809
|
const data = load();
|
|
19792
19810
|
const forServer = data[server];
|
|
@@ -19795,7 +19813,11 @@ function markFullResync(server, sessionId) {
|
|
|
19795
19813
|
delete forServer[sessionId];
|
|
19796
19814
|
persist(data);
|
|
19797
19815
|
}
|
|
19798
|
-
function
|
|
19816
|
+
function fullCoveredOffset(row) {
|
|
19817
|
+
if (row.F !== void 0) return row.F;
|
|
19818
|
+
return row.h ? row.s ?? 0 : 0;
|
|
19819
|
+
}
|
|
19820
|
+
function syncMode(row, mtime, fileSize, extractorVersion, isAppendOnly, nowMs = Date.now()) {
|
|
19799
19821
|
if (!row) return "full";
|
|
19800
19822
|
if (row.v < extractorVersion) return "full";
|
|
19801
19823
|
const offset = row.o ?? 0;
|
|
@@ -19803,10 +19825,13 @@ function syncMode(row, mtime, fileSize, extractorVersion, isAppendOnly) {
|
|
|
19803
19825
|
if (process.env.CHAT_RECALL_TAIL_APPEND !== "0" && isAppendOnly && fileSize > 0 && offset > 0 && fileSize > (row.s ?? 0)) {
|
|
19804
19826
|
return "append";
|
|
19805
19827
|
}
|
|
19828
|
+
if (isAppendOnly && offset > 0 && fileSize > 0 && fileSize === (row.s ?? 0) && !row.k && fullCoveredOffset(row) < offset && nowMs - Math.floor(mtime) >= SETTLE_QUIET_MS) {
|
|
19829
|
+
return "full";
|
|
19830
|
+
}
|
|
19806
19831
|
if (row.m >= Math.floor(mtime)) return "skip";
|
|
19807
19832
|
return "full";
|
|
19808
19833
|
}
|
|
19809
|
-
var ledgerPath, cache3, base, diskStamp, rowKey, LEDGER_FLUSH_MS, pendingWrite, flushTimer, itemVersionsPath, itemVersionsCache, inventoryPath, unackedCursorAttempts, reconcilePath, reconcileCache;
|
|
19834
|
+
var ledgerPath, cache3, base, diskStamp, rowKey, LEDGER_FLUSH_MS, pendingWrite, flushTimer, itemVersionsPath, itemVersionsCache, inventoryPath, unackedCursorAttempts, reconcilePath, reconcileCache, SETTLE_QUIET_MS;
|
|
19810
19835
|
var init_sync_ledger = __esm({
|
|
19811
19836
|
"src/sync-ledger.ts"() {
|
|
19812
19837
|
"use strict";
|
|
@@ -19826,6 +19851,7 @@ var init_sync_ledger = __esm({
|
|
|
19826
19851
|
unackedCursorAttempts = 0;
|
|
19827
19852
|
reconcilePath = () => join46(getDataDir(), "sync-field-reconcile.json");
|
|
19828
19853
|
reconcileCache = null;
|
|
19854
|
+
SETTLE_QUIET_MS = 2 * 60 * 60 * 1e3;
|
|
19829
19855
|
}
|
|
19830
19856
|
});
|
|
19831
19857
|
|
|
@@ -19971,7 +19997,7 @@ var init_http = __esm({
|
|
|
19971
19997
|
CLI_VERSION = JSON.parse(readFileSync36(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
|
|
19972
19998
|
} catch {
|
|
19973
19999
|
try {
|
|
19974
|
-
if (true) CLI_VERSION = "0.7.
|
|
20000
|
+
if (true) CLI_VERSION = "0.7.18";
|
|
19975
20001
|
} catch {
|
|
19976
20002
|
}
|
|
19977
20003
|
}
|
|
@@ -20469,7 +20495,7 @@ var init_telemetry = __esm({
|
|
|
20469
20495
|
init_sync_client();
|
|
20470
20496
|
cliVersion2 = () => {
|
|
20471
20497
|
try {
|
|
20472
|
-
return true ? "0.7.
|
|
20498
|
+
return true ? "0.7.18" : "dev";
|
|
20473
20499
|
} catch {
|
|
20474
20500
|
return "dev";
|
|
20475
20501
|
}
|
|
@@ -20479,6 +20505,150 @@ var init_telemetry = __esm({
|
|
|
20479
20505
|
}
|
|
20480
20506
|
});
|
|
20481
20507
|
|
|
20508
|
+
// src/raw-archive-parts.ts
|
|
20509
|
+
import { createReadStream as createReadStream4, createWriteStream as createWriteStream2, openSync as openSync10, readSync as readSync8, closeSync as closeSync10, rmSync as rmSync5, statSync as statSync42 } from "node:fs";
|
|
20510
|
+
import { tmpdir as tmpdir3 } from "node:os";
|
|
20511
|
+
import { join as join48 } from "node:path";
|
|
20512
|
+
import { randomBytes } from "node:crypto";
|
|
20513
|
+
import { createGzip } from "node:zlib";
|
|
20514
|
+
import { once } from "node:events";
|
|
20515
|
+
import { readFileSync as readFileSync37 } from "node:fs";
|
|
20516
|
+
async function* fileLines(path2) {
|
|
20517
|
+
let rest = "";
|
|
20518
|
+
const decoder = new TextDecoder("utf-8");
|
|
20519
|
+
for await (const chunk of createReadStream4(path2, { highWaterMark: 1024 * 1024 })) {
|
|
20520
|
+
rest += decoder.decode(chunk, { stream: true });
|
|
20521
|
+
let nl = rest.indexOf("\n");
|
|
20522
|
+
while (nl >= 0) {
|
|
20523
|
+
yield rest.slice(0, nl + 1);
|
|
20524
|
+
rest = rest.slice(nl + 1);
|
|
20525
|
+
nl = rest.indexOf("\n");
|
|
20526
|
+
}
|
|
20527
|
+
}
|
|
20528
|
+
rest += decoder.decode();
|
|
20529
|
+
if (rest) yield rest;
|
|
20530
|
+
}
|
|
20531
|
+
function* textLines(text) {
|
|
20532
|
+
let at = 0;
|
|
20533
|
+
while (at < text.length) {
|
|
20534
|
+
const nl = text.indexOf("\n", at);
|
|
20535
|
+
const end = nl < 0 ? text.length : nl + 1;
|
|
20536
|
+
yield text.slice(at, end);
|
|
20537
|
+
at = end;
|
|
20538
|
+
}
|
|
20539
|
+
}
|
|
20540
|
+
async function writeArchiveFile(source, meta, redact, dir = tmpdir3()) {
|
|
20541
|
+
const path2 = join48(dir, `cr-archive-${randomBytes(8).toString("hex")}.json.gz`);
|
|
20542
|
+
const gzip = createGzip({ level: 6 });
|
|
20543
|
+
const out = createWriteStream2(path2, { mode: 384 });
|
|
20544
|
+
const done = once(out, "finish");
|
|
20545
|
+
gzip.pipe(out);
|
|
20546
|
+
let size = 0;
|
|
20547
|
+
const write = async (s) => {
|
|
20548
|
+
size += Buffer.byteLength(s);
|
|
20549
|
+
if (!gzip.write(s)) await once(gzip, "drain");
|
|
20550
|
+
};
|
|
20551
|
+
try {
|
|
20552
|
+
await write(`{"v":1,"tool":${JSON.stringify(meta.tool)},"mtime":${Math.floor(meta.mtime)},"files":[`);
|
|
20553
|
+
for (const [i, f] of source.files.entries()) {
|
|
20554
|
+
await write(`${i ? "," : ""}{"name":${JSON.stringify(f.name)},"text":"`);
|
|
20555
|
+
const whole = () => source.kind === "memory" ? f.text : readFileSync37(f.path, "utf-8");
|
|
20556
|
+
if (!f.name.endsWith(".jsonl")) {
|
|
20557
|
+
await write(escapeJson(redact(whole())));
|
|
20558
|
+
} else {
|
|
20559
|
+
const lines = source.kind === "memory" ? textLines(f.text) : fileLines(f.path);
|
|
20560
|
+
for await (const line of lines) {
|
|
20561
|
+
const nl = line.endsWith("\n");
|
|
20562
|
+
const body2 = nl ? line.slice(0, -1) : line;
|
|
20563
|
+
await write(escapeJson((body2 ? redactJsonLine(body2, redact) : body2) + (nl ? "\n" : "")));
|
|
20564
|
+
}
|
|
20565
|
+
}
|
|
20566
|
+
await write('"}');
|
|
20567
|
+
}
|
|
20568
|
+
await write("]}");
|
|
20569
|
+
gzip.end();
|
|
20570
|
+
await done;
|
|
20571
|
+
} catch (err) {
|
|
20572
|
+
gzip.destroy();
|
|
20573
|
+
out.destroy();
|
|
20574
|
+
rmSync5(path2, { force: true });
|
|
20575
|
+
throw err;
|
|
20576
|
+
}
|
|
20577
|
+
return { path: path2, gzSize: statSync42(path2).size, size };
|
|
20578
|
+
}
|
|
20579
|
+
async function putPart(url, body2) {
|
|
20580
|
+
let last;
|
|
20581
|
+
for (let attempt = 1; attempt <= PART_ATTEMPTS; attempt++) {
|
|
20582
|
+
const ac = new AbortController();
|
|
20583
|
+
const timer = setTimeout(() => ac.abort(), PART_TIMEOUT_MS);
|
|
20584
|
+
try {
|
|
20585
|
+
const r = await fetch(url, { method: "PUT", body: body2, signal: ac.signal });
|
|
20586
|
+
const etag = r.headers.get("etag");
|
|
20587
|
+
if (r.ok && etag) return etag;
|
|
20588
|
+
last = new Error(`part PUT answered ${r.status}`);
|
|
20589
|
+
if (r.status === 403 || r.status === 404) break;
|
|
20590
|
+
} catch (err) {
|
|
20591
|
+
last = err;
|
|
20592
|
+
} finally {
|
|
20593
|
+
clearTimeout(timer);
|
|
20594
|
+
}
|
|
20595
|
+
}
|
|
20596
|
+
throw last instanceof Error ? last : new Error(String(last));
|
|
20597
|
+
}
|
|
20598
|
+
async function uploadArchiveFile(base2, token, args) {
|
|
20599
|
+
const headers = { "content-type": "application/json" };
|
|
20600
|
+
if (token) headers.authorization = `Bearer ${token}`;
|
|
20601
|
+
const post = async (path2, body2) => {
|
|
20602
|
+
const r = await fetch(`${base2}/api/sync/raw-upload/${path2}`, { method: "POST", headers, body: JSON.stringify(body2) });
|
|
20603
|
+
const json = await r.json().catch(() => ({}));
|
|
20604
|
+
return { status: r.status, json };
|
|
20605
|
+
};
|
|
20606
|
+
const start = await post("start", {
|
|
20607
|
+
session_id: args.sessionId,
|
|
20608
|
+
tool: args.tool,
|
|
20609
|
+
mtime: Math.floor(args.mtime),
|
|
20610
|
+
size: args.file.size,
|
|
20611
|
+
gz_size: args.file.gzSize,
|
|
20612
|
+
project_id: args.projectId,
|
|
20613
|
+
project_path: args.projectPath
|
|
20614
|
+
});
|
|
20615
|
+
if (start.status === 501 || start.status === 404) return "unsupported";
|
|
20616
|
+
if (start.status !== 200) throw new Error(`raw upload start answered ${start.status}: ${start.json.error ?? ""}`);
|
|
20617
|
+
if (start.json.result === "unchanged" || start.json.result === "shrink-protected") return start.json.result;
|
|
20618
|
+
const urls = start.json.urls;
|
|
20619
|
+
const partBytes = Number(start.json.part_bytes);
|
|
20620
|
+
const parts = [];
|
|
20621
|
+
const fd = openSync10(args.file.path, "r");
|
|
20622
|
+
try {
|
|
20623
|
+
for (const [i, url] of urls.entries()) {
|
|
20624
|
+
const len = Math.min(partBytes, args.file.gzSize - i * partBytes);
|
|
20625
|
+
const buf = Buffer.allocUnsafe(len);
|
|
20626
|
+
let got = 0;
|
|
20627
|
+
while (got < len) {
|
|
20628
|
+
const n = readSync8(fd, buf, got, len - got, i * partBytes + got);
|
|
20629
|
+
if (n <= 0) break;
|
|
20630
|
+
got += n;
|
|
20631
|
+
}
|
|
20632
|
+
parts.push({ part_number: i + 1, etag: await putPart(url, buf.subarray(0, got)) });
|
|
20633
|
+
}
|
|
20634
|
+
} finally {
|
|
20635
|
+
closeSync10(fd);
|
|
20636
|
+
}
|
|
20637
|
+
const done = await post("complete", { session_id: args.sessionId, upload_id: start.json.upload_id, parts });
|
|
20638
|
+
if (done.status !== 200) throw new Error(`raw upload complete answered ${done.status}: ${done.json.error ?? ""}`);
|
|
20639
|
+
return done.json.result;
|
|
20640
|
+
}
|
|
20641
|
+
var escapeJson, PART_TIMEOUT_MS, PART_ATTEMPTS;
|
|
20642
|
+
var init_raw_archive_parts = __esm({
|
|
20643
|
+
"src/raw-archive-parts.ts"() {
|
|
20644
|
+
"use strict";
|
|
20645
|
+
init_transcript();
|
|
20646
|
+
escapeJson = (s) => JSON.stringify(s).slice(1, -1);
|
|
20647
|
+
PART_TIMEOUT_MS = 12e4;
|
|
20648
|
+
PART_ATTEMPTS = 3;
|
|
20649
|
+
}
|
|
20650
|
+
});
|
|
20651
|
+
|
|
20482
20652
|
// src/server-probe.ts
|
|
20483
20653
|
var server_probe_exports = {};
|
|
20484
20654
|
__export(server_probe_exports, {
|
|
@@ -20640,11 +20810,11 @@ __export(auto_update_exports, {
|
|
|
20640
20810
|
tarballUrl: () => tarballUrl
|
|
20641
20811
|
});
|
|
20642
20812
|
import { execSync as execSync4, execFileSync as execFileSync3 } from "node:child_process";
|
|
20643
|
-
import { readFileSync as
|
|
20813
|
+
import { readFileSync as readFileSync38, existsSync as existsSync45 } from "node:fs";
|
|
20644
20814
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
20645
|
-
import { writeFileSync as writeFileSync9, mkdtempSync as mkdtempSync3, rmSync as
|
|
20646
|
-
import { join as
|
|
20647
|
-
import { tmpdir as
|
|
20815
|
+
import { writeFileSync as writeFileSync9, mkdtempSync as mkdtempSync3, rmSync as rmSync6, readdirSync as readdirSync31, statSync as statSync43, mkdirSync as mkdirSync12 } from "node:fs";
|
|
20816
|
+
import { join as join49, dirname as dirname19, sep as sep3, posix as pathPosix, win32 as pathWin32 } from "node:path";
|
|
20817
|
+
import { tmpdir as tmpdir4, homedir as homedir17 } from "node:os";
|
|
20648
20818
|
import { createHash as createHash10 } from "node:crypto";
|
|
20649
20819
|
function compareVersions(a, b) {
|
|
20650
20820
|
const pa = String(a).split("-")[0].split(".").map((n) => parseInt(n, 10) || 0);
|
|
@@ -20668,7 +20838,7 @@ function newerOf(a, b) {
|
|
|
20668
20838
|
function installedVersion() {
|
|
20669
20839
|
try {
|
|
20670
20840
|
const here = dirname19(fileURLToPath2(import.meta.url));
|
|
20671
|
-
const raw =
|
|
20841
|
+
const raw = readFileSync38(join49(here, "..", "package.json"), "utf-8");
|
|
20672
20842
|
return JSON.parse(raw).version || null;
|
|
20673
20843
|
} catch {
|
|
20674
20844
|
return null;
|
|
@@ -20681,7 +20851,7 @@ function planAutoUpdate(base2, caps, ownVersion2, flag) {
|
|
|
20681
20851
|
if (compareVersions(rel.version, ownVersion2) <= 0) return { update: false, reason: `already current (own ${ownVersion2} >= server ${rel.version})` };
|
|
20682
20852
|
return { update: true, reason: `server ${rel.version} > own ${ownVersion2}`, url: tarballUrl(base2, rel.version), fallbackUrl: tarballUrl(base2), sha256: rel.sha256, from: ownVersion2, to: rel.version };
|
|
20683
20853
|
}
|
|
20684
|
-
function sweepStaleStaging(root =
|
|
20854
|
+
function sweepStaleStaging(root = tmpdir4(), now = Date.now()) {
|
|
20685
20855
|
const MKDTEMP_SUFFIX = /^cr-update-.{6}$/s;
|
|
20686
20856
|
const COLD_MS = 60 * 60 * 1e3;
|
|
20687
20857
|
let removed = 0;
|
|
@@ -20693,13 +20863,13 @@ function sweepStaleStaging(root = tmpdir3(), now = Date.now()) {
|
|
|
20693
20863
|
}
|
|
20694
20864
|
for (const name of entries) {
|
|
20695
20865
|
if (!MKDTEMP_SUFFIX.test(name)) continue;
|
|
20696
|
-
const dir =
|
|
20866
|
+
const dir = join49(root, name);
|
|
20697
20867
|
try {
|
|
20698
|
-
const st =
|
|
20868
|
+
const st = statSync43(dir);
|
|
20699
20869
|
if (!st.isDirectory() || now - st.mtimeMs < COLD_MS) continue;
|
|
20700
20870
|
const inside = readdirSync31(dir);
|
|
20701
20871
|
if (inside.length > 1 || inside.length === 1 && inside[0] !== "chat-recall.tgz") continue;
|
|
20702
|
-
|
|
20872
|
+
rmSync6(dir, { recursive: true, force: true });
|
|
20703
20873
|
removed++;
|
|
20704
20874
|
} catch {
|
|
20705
20875
|
}
|
|
@@ -20722,14 +20892,14 @@ async function executeAutoUpdate(plan, deps) {
|
|
|
20722
20892
|
}
|
|
20723
20893
|
const got = createHash10("sha256").update(buf).digest("hex");
|
|
20724
20894
|
if (got !== plan.sha256) return { updated: false, reason: `checksum mismatch (expected ${plan.sha256.slice(0, 12)}\u2026, got ${got.slice(0, 12)}\u2026) \u2014 NOT installing` };
|
|
20725
|
-
const dir = mkdtempSync3(
|
|
20895
|
+
const dir = mkdtempSync3(join49(tmpdir4(), "cr-update-"));
|
|
20726
20896
|
const discardStaging = () => {
|
|
20727
20897
|
try {
|
|
20728
|
-
|
|
20898
|
+
rmSync6(dir, { recursive: true, force: true });
|
|
20729
20899
|
} catch {
|
|
20730
20900
|
}
|
|
20731
20901
|
};
|
|
20732
|
-
const tgz =
|
|
20902
|
+
const tgz = join49(dir, "chat-recall.tgz");
|
|
20733
20903
|
writeFileSync9(tgz, buf);
|
|
20734
20904
|
if (deps.stopping?.()) {
|
|
20735
20905
|
discardStaging();
|
|
@@ -20809,7 +20979,7 @@ function realInstall(tgz) {
|
|
|
20809
20979
|
try {
|
|
20810
20980
|
npmInstall(npm, ["install", "-g", tgz]);
|
|
20811
20981
|
} catch {
|
|
20812
|
-
npmInstall(npm, ["install", "-g", "--prefix",
|
|
20982
|
+
npmInstall(npm, ["install", "-g", "--prefix", join49(homedir17(), ".local"), tgz]);
|
|
20813
20983
|
}
|
|
20814
20984
|
}
|
|
20815
20985
|
function acquireUpdateLock() {
|
|
@@ -20826,12 +20996,12 @@ function realRestart(platform2) {
|
|
|
20826
20996
|
if (c) execSync4(c.cmd, { stdio: "ignore", ...c.shell ? { shell: c.shell } : {} });
|
|
20827
20997
|
}
|
|
20828
20998
|
function updateStatePath() {
|
|
20829
|
-
const dir = process.env.CHAT_RECALL_DATA_DIR ||
|
|
20830
|
-
return
|
|
20999
|
+
const dir = process.env.CHAT_RECALL_DATA_DIR || join49(homedir17(), ".chat-recall");
|
|
21000
|
+
return join49(dir, "auto-update-state.json");
|
|
20831
21001
|
}
|
|
20832
21002
|
function readUpdateState() {
|
|
20833
21003
|
try {
|
|
20834
|
-
return JSON.parse(
|
|
21004
|
+
return JSON.parse(readFileSync38(updateStatePath(), "utf8"));
|
|
20835
21005
|
} catch {
|
|
20836
21006
|
return {};
|
|
20837
21007
|
}
|
|
@@ -20972,9 +21142,9 @@ __export(sync_client_exports, {
|
|
|
20972
21142
|
syncIncremental: () => syncIncremental,
|
|
20973
21143
|
syncSessions: () => syncSessions
|
|
20974
21144
|
});
|
|
20975
|
-
import { join as
|
|
20976
|
-
import { readFileSync as
|
|
20977
|
-
import { tmpdir as
|
|
21145
|
+
import { join as join50, dirname as dirname20, basename as basename22 } from "node:path";
|
|
21146
|
+
import { readFileSync as readFileSync39, writeFileSync as writeFileSync10, mkdirSync as mkdirSync13, mkdtempSync as mkdtempSync4, rmSync as rmSync7, chmodSync as chmodSync6, unlinkSync as unlinkSync3, readdirSync as readdirSync32, statSync as statSync44 } from "node:fs";
|
|
21147
|
+
import { tmpdir as tmpdir5, hostname as hostname2 } from "node:os";
|
|
20978
21148
|
import { createHash as createHash11 } from "node:crypto";
|
|
20979
21149
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
20980
21150
|
import { gzipSync as gzipSync3 } from "zlib";
|
|
@@ -21028,7 +21198,7 @@ function loadAllCredentials() {
|
|
|
21028
21198
|
const fromEnv = envCredentials();
|
|
21029
21199
|
if (fromEnv) return [{ serverUrl: fromEnv.serverUrl, token: fromEnv.token }];
|
|
21030
21200
|
try {
|
|
21031
|
-
const parsed = JSON.parse(
|
|
21201
|
+
const parsed = JSON.parse(readFileSync39(credPath(), "utf-8"));
|
|
21032
21202
|
if (Array.isArray(parsed?.targets)) return parsed.targets.filter((t) => t?.serverUrl).map((t) => ({ serverUrl: t.serverUrl, token: t.token || "" }));
|
|
21033
21203
|
if (parsed?.serverUrl) return [{ serverUrl: parsed.serverUrl, token: parsed.token || "" }];
|
|
21034
21204
|
} catch {
|
|
@@ -21090,11 +21260,11 @@ function _resetTenantSecurityConfigCache() {
|
|
|
21090
21260
|
_securityConfigCache.clear();
|
|
21091
21261
|
}
|
|
21092
21262
|
function syncConfigCachePath() {
|
|
21093
|
-
return
|
|
21263
|
+
return join50(getDataDir(), "sync-config-cache.json");
|
|
21094
21264
|
}
|
|
21095
21265
|
function readPersistedSyncConfigs() {
|
|
21096
21266
|
try {
|
|
21097
|
-
return JSON.parse(
|
|
21267
|
+
return JSON.parse(readFileSync39(syncConfigCachePath(), "utf-8"));
|
|
21098
21268
|
} catch {
|
|
21099
21269
|
return {};
|
|
21100
21270
|
}
|
|
@@ -21372,7 +21542,7 @@ async function reconcileFields(opts = {}) {
|
|
|
21372
21542
|
}
|
|
21373
21543
|
return { sessions: fullRefs().length, scanned, pushed, absent, perTarget };
|
|
21374
21544
|
}
|
|
21375
|
-
function reapStaleScanDirs(dir =
|
|
21545
|
+
function reapStaleScanDirs(dir = tmpdir5(), maxAgeMs = 6 * 36e5, now = Date.now()) {
|
|
21376
21546
|
let reaped = 0;
|
|
21377
21547
|
let names;
|
|
21378
21548
|
try {
|
|
@@ -21382,10 +21552,10 @@ function reapStaleScanDirs(dir = tmpdir4(), maxAgeMs = 6 * 36e5, now = Date.now(
|
|
|
21382
21552
|
}
|
|
21383
21553
|
for (const name of names) {
|
|
21384
21554
|
if (!name.startsWith("cr-batchscan-")) continue;
|
|
21385
|
-
const p =
|
|
21555
|
+
const p = join50(dir, name);
|
|
21386
21556
|
try {
|
|
21387
|
-
if (now -
|
|
21388
|
-
|
|
21557
|
+
if (now - statSync44(p).mtimeMs < maxAgeMs) continue;
|
|
21558
|
+
rmSync7(p, { recursive: true, force: true });
|
|
21389
21559
|
reaped++;
|
|
21390
21560
|
} catch {
|
|
21391
21561
|
}
|
|
@@ -21399,7 +21569,7 @@ function batchScanExternal(items, opts = {}) {
|
|
|
21399
21569
|
let scanned = 0, slices = 0, scanMs = 0;
|
|
21400
21570
|
if (items.length === 0) return { findings, scanned, slices, scanMs };
|
|
21401
21571
|
reapStaleScanDirs();
|
|
21402
|
-
let scanDir = mkdtempSync4(
|
|
21572
|
+
let scanDir = mkdtempSync4(join50(tmpdir5(), "cr-batchscan-"));
|
|
21403
21573
|
let safeToId = /* @__PURE__ */ new Map();
|
|
21404
21574
|
let bytesInDir = 0;
|
|
21405
21575
|
const flushSlice = () => {
|
|
@@ -21417,7 +21587,7 @@ function batchScanExternal(items, opts = {}) {
|
|
|
21417
21587
|
slices++;
|
|
21418
21588
|
}
|
|
21419
21589
|
try {
|
|
21420
|
-
|
|
21590
|
+
rmSync7(scanDir, { recursive: true, force: true });
|
|
21421
21591
|
} catch {
|
|
21422
21592
|
}
|
|
21423
21593
|
safeToId = /* @__PURE__ */ new Map();
|
|
@@ -21430,19 +21600,19 @@ function batchScanExternal(items, opts = {}) {
|
|
|
21430
21600
|
if (raw === null) continue;
|
|
21431
21601
|
const safe = item.id.replace(/[^A-Za-z0-9_-]/g, "");
|
|
21432
21602
|
safeToId.set(safe, item.id);
|
|
21433
|
-
writeFileSync10(
|
|
21603
|
+
writeFileSync10(join50(scanDir, `${safe}.txt`), raw);
|
|
21434
21604
|
bytesInDir += Buffer.byteLength(raw);
|
|
21435
21605
|
} catch {
|
|
21436
21606
|
}
|
|
21437
21607
|
if (bytesInDir >= maxBytes) {
|
|
21438
21608
|
flushSlice();
|
|
21439
|
-
scanDir = mkdtempSync4(
|
|
21609
|
+
scanDir = mkdtempSync4(join50(tmpdir5(), "cr-batchscan-"));
|
|
21440
21610
|
}
|
|
21441
21611
|
}
|
|
21442
21612
|
flushSlice();
|
|
21443
21613
|
} finally {
|
|
21444
21614
|
try {
|
|
21445
|
-
|
|
21615
|
+
rmSync7(scanDir, { recursive: true, force: true });
|
|
21446
21616
|
} catch {
|
|
21447
21617
|
}
|
|
21448
21618
|
}
|
|
@@ -21686,12 +21856,13 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
21686
21856
|
markSynced(base2, rows.map((r) => {
|
|
21687
21857
|
const off = typeof r.from_offset === "number" ? r.from_offset : 0;
|
|
21688
21858
|
const hash = shippedHash.get(r.session_id);
|
|
21689
|
-
return off > 0 ? { id: r.session_id, mtime: r.mtime, offset: off, size: off, hash, acked: true } : { id: r.session_id, mtime: r.mtime, hash };
|
|
21859
|
+
return off > 0 ? { id: r.session_id, mtime: r.mtime, offset: off, size: off, hash, acked: true, full: true } : { id: r.session_id, mtime: r.mtime, hash };
|
|
21690
21860
|
}));
|
|
21691
21861
|
} catch {
|
|
21692
21862
|
}
|
|
21693
21863
|
});
|
|
21694
21864
|
const appendResults = { uploaded: 0, fullResyncNeeded: /* @__PURE__ */ new Set() };
|
|
21865
|
+
const pendingArchives = [];
|
|
21695
21866
|
const postAppend = async (convs) => {
|
|
21696
21867
|
const headers = { "content-type": "application/json" };
|
|
21697
21868
|
if (cred.token) headers.authorization = `Bearer ${cred.token}`;
|
|
@@ -21726,8 +21897,10 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
21726
21897
|
offset: c.from_offset,
|
|
21727
21898
|
size: c.from_offset,
|
|
21728
21899
|
// size = new offset (file grew to here)
|
|
21729
|
-
acked: true
|
|
21900
|
+
acked: true,
|
|
21730
21901
|
// server merged this tail
|
|
21902
|
+
chunkFinal: c.final === true
|
|
21903
|
+
// completes a chunked full sync
|
|
21731
21904
|
})));
|
|
21732
21905
|
} catch {
|
|
21733
21906
|
}
|
|
@@ -21759,9 +21932,9 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
21759
21932
|
const mtime = conv.mtime;
|
|
21760
21933
|
try {
|
|
21761
21934
|
if (staged || !guarded) {
|
|
21762
|
-
markSynced(base2, [{ id, mtime, offset: conv.from_offset, size: conv.from_offset, acked: true }]);
|
|
21935
|
+
markSynced(base2, [{ id, mtime, offset: conv.from_offset, size: conv.from_offset, acked: true, chunkedHead: true }]);
|
|
21763
21936
|
} else if (typeof guarded.o === "number" && guarded.o > 0 && guarded.o <= fileSize) {
|
|
21764
|
-
markSynced(base2, [{ id, mtime, offset: guarded.o, size: guarded.o, acked: true }]);
|
|
21937
|
+
markSynced(base2, [{ id, mtime, offset: guarded.o, size: guarded.o, acked: true, chunkedHead: true }]);
|
|
21765
21938
|
} else {
|
|
21766
21939
|
markSynced(base2, [{ id, mtime }]);
|
|
21767
21940
|
}
|
|
@@ -21970,6 +22143,14 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
21970
22143
|
if (built.srcHash) shippedHash.set(ref.prefixedId, built.srcHash);
|
|
21971
22144
|
if (built.conv.chunked) await postChunkedHead(built.conv, sessionFileBytes(ref));
|
|
21972
22145
|
else await convBatch.add(built.conv);
|
|
22146
|
+
if (built.archive) {
|
|
22147
|
+
pendingArchives.push({
|
|
22148
|
+
id: ref.prefixedId,
|
|
22149
|
+
...built.archive,
|
|
22150
|
+
projectId: built.conv.project_id,
|
|
22151
|
+
projectPath: built.conv.project_path
|
|
22152
|
+
});
|
|
22153
|
+
}
|
|
21973
22154
|
if (built.findings.length > 0) await findingsBatch.add(built.findings);
|
|
21974
22155
|
if (upload.sessionMeta) {
|
|
21975
22156
|
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);
|
|
@@ -22122,6 +22303,30 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
22122
22303
|
await kgTripleBatch.drain();
|
|
22123
22304
|
await findingsBatch.drain();
|
|
22124
22305
|
await drainInflight();
|
|
22306
|
+
let archivesUnsupported = false;
|
|
22307
|
+
for (const a of pendingArchives) {
|
|
22308
|
+
try {
|
|
22309
|
+
if (!archivesUnsupported) {
|
|
22310
|
+
const r = await uploadArchiveFile(base2, cred.token, {
|
|
22311
|
+
sessionId: a.id,
|
|
22312
|
+
tool: a.tool,
|
|
22313
|
+
mtime: a.mtime,
|
|
22314
|
+
projectId: a.projectId,
|
|
22315
|
+
projectPath: a.projectPath,
|
|
22316
|
+
file: a.file
|
|
22317
|
+
});
|
|
22318
|
+
if (r === "unsupported") archivesUnsupported = true;
|
|
22319
|
+
}
|
|
22320
|
+
} catch (err) {
|
|
22321
|
+
console.error(`[sync] raw archive for ${a.id} not uploaded (tried again when the session is next quiet): ${err instanceof Error ? err.message : err}`);
|
|
22322
|
+
try {
|
|
22323
|
+
forgetFullCoverage(base2, a.id);
|
|
22324
|
+
} catch {
|
|
22325
|
+
}
|
|
22326
|
+
} finally {
|
|
22327
|
+
rmSync7(a.file.path, { force: true });
|
|
22328
|
+
}
|
|
22329
|
+
}
|
|
22125
22330
|
{
|
|
22126
22331
|
const sentHashes = loadInventoryHashes(base2);
|
|
22127
22332
|
const entries = [];
|
|
@@ -22227,6 +22432,7 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
22227
22432
|
let includeRaw = opts.includeRaw !== false;
|
|
22228
22433
|
let includeMeta = opts.includeMeta !== false;
|
|
22229
22434
|
let srcHash;
|
|
22435
|
+
const wantRaw = opts.includeRaw !== false;
|
|
22230
22436
|
const oversized = sessionBuildBytes(ref) > FULL_BUILD_MAX_BYTES;
|
|
22231
22437
|
let headOffsetEnd = 0;
|
|
22232
22438
|
let oversizedFindings = null;
|
|
@@ -22395,7 +22601,7 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
22395
22601
|
} else if (opts.scanSecrets) {
|
|
22396
22602
|
let tmp = null;
|
|
22397
22603
|
try {
|
|
22398
|
-
tmp =
|
|
22604
|
+
tmp = join50(tmpdir5(), `cr-scan-${ref.prefixedId.replace(/[^A-Za-z0-9_-]/g, "")}-${mtime}.txt`);
|
|
22399
22605
|
writeFileSync10(tmp, rawText);
|
|
22400
22606
|
for (const f of scanFileForSecrets(tmp, { verifyOnly: opts.verifySecrets, tenantRules: opts.tenantRules })) {
|
|
22401
22607
|
const verifiedAt = f.verified ? (/* @__PURE__ */ new Date()).toISOString() : null;
|
|
@@ -22447,6 +22653,25 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
22447
22653
|
}
|
|
22448
22654
|
const envTexts = envelope.messages.filter((m) => m.content?.trim());
|
|
22449
22655
|
const redactedText = envTexts.map((m) => m.content).join("\n");
|
|
22656
|
+
let archive;
|
|
22657
|
+
if (wantRaw && !raw_b64) {
|
|
22658
|
+
try {
|
|
22659
|
+
const redact = (t) => redactSecrets(t, { force: true, count });
|
|
22660
|
+
let source = null;
|
|
22661
|
+
let archiveMtime = Math.floor(ref.mtime) || 0;
|
|
22662
|
+
let archiveTool = ref.toolId;
|
|
22663
|
+
if (container) {
|
|
22664
|
+
source = { kind: "memory", files: container.files };
|
|
22665
|
+
archiveMtime = container.mtime;
|
|
22666
|
+
archiveTool = container.tool;
|
|
22667
|
+
} else if (oversized) {
|
|
22668
|
+
source = diskArchiveSource(ref);
|
|
22669
|
+
}
|
|
22670
|
+
if (source) archive = { file: await writeArchiveFile(source, { tool: archiveTool, mtime: archiveMtime }, redact), tool: archiveTool, mtime: archiveMtime };
|
|
22671
|
+
} catch (err) {
|
|
22672
|
+
console.error(`[sync] raw archive for ${ref.prefixedId} not written: ${err instanceof Error ? err.message : err}`);
|
|
22673
|
+
}
|
|
22674
|
+
}
|
|
22450
22675
|
return {
|
|
22451
22676
|
conv: {
|
|
22452
22677
|
session_id: ref.prefixedId,
|
|
@@ -22478,7 +22703,17 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
22478
22703
|
redactions: count.redactions,
|
|
22479
22704
|
findings,
|
|
22480
22705
|
scanMs,
|
|
22481
|
-
srcHash
|
|
22706
|
+
srcHash,
|
|
22707
|
+
archive
|
|
22708
|
+
};
|
|
22709
|
+
}
|
|
22710
|
+
function diskArchiveSource(ref) {
|
|
22711
|
+
if (ref.toolId !== "claude") return null;
|
|
22712
|
+
const groups = resolveSessionContentGroups(ref.rawId);
|
|
22713
|
+
if (groups.length === 0 || groups.some((g) => g.paths.length !== 1)) return null;
|
|
22714
|
+
return {
|
|
22715
|
+
kind: "disk",
|
|
22716
|
+
files: groups.map((g) => ({ name: g.name === "main" ? `${ref.rawId}.jsonl` : g.name, path: g.paths[0] }))
|
|
22482
22717
|
};
|
|
22483
22718
|
}
|
|
22484
22719
|
function parseTailMessages(tool, text) {
|
|
@@ -22634,14 +22869,15 @@ var init_sync_client = __esm({
|
|
|
22634
22869
|
init_telemetry();
|
|
22635
22870
|
init_collector_health();
|
|
22636
22871
|
init_live_session_scan();
|
|
22872
|
+
init_raw_archive_parts();
|
|
22637
22873
|
init_backends();
|
|
22638
22874
|
ownVersion = "0.0.0";
|
|
22639
22875
|
try {
|
|
22640
22876
|
const dir = dirname20(fileURLToPath3(import.meta.url));
|
|
22641
|
-
ownVersion = JSON.parse(
|
|
22877
|
+
ownVersion = JSON.parse(readFileSync39(join50(dir, "../package.json"), "utf-8")).version || ownVersion;
|
|
22642
22878
|
} catch {
|
|
22643
22879
|
try {
|
|
22644
|
-
if (true) ownVersion = "0.7.
|
|
22880
|
+
if (true) ownVersion = "0.7.18";
|
|
22645
22881
|
} catch {
|
|
22646
22882
|
}
|
|
22647
22883
|
}
|
|
@@ -22653,7 +22889,7 @@ var init_sync_client = __esm({
|
|
|
22653
22889
|
]);
|
|
22654
22890
|
walkProgressForUpload = null;
|
|
22655
22891
|
lastServerPackSpec = null;
|
|
22656
|
-
credPath = () =>
|
|
22892
|
+
credPath = () => join50(getDataDir(), "credentials.json");
|
|
22657
22893
|
_securityConfigCache = /* @__PURE__ */ new Map();
|
|
22658
22894
|
SECURITY_CONFIG_TTL_MS = 5 * 60 * 1e3;
|
|
22659
22895
|
_syncConfigCache = /* @__PURE__ */ new Map();
|
|
@@ -22682,7 +22918,7 @@ __export(client_events_exports, {
|
|
|
22682
22918
|
isTelemetryEnabled: () => isTelemetryEnabled,
|
|
22683
22919
|
reportClientEvent: () => reportClientEvent2
|
|
22684
22920
|
});
|
|
22685
|
-
import { readFileSync as
|
|
22921
|
+
import { readFileSync as readFileSync40 } from "node:fs";
|
|
22686
22922
|
function scrub(msg) {
|
|
22687
22923
|
if (!msg) return "";
|
|
22688
22924
|
const noHome = msg.replace(/\/(?:home|Users)\/[^/\s]+/g, "~");
|
|
@@ -22735,7 +22971,7 @@ var init_client_events = __esm({
|
|
|
22735
22971
|
init_secret_redactor();
|
|
22736
22972
|
CLI_VERSION2 = "0.0.0";
|
|
22737
22973
|
try {
|
|
22738
|
-
CLI_VERSION2 = JSON.parse(
|
|
22974
|
+
CLI_VERSION2 = JSON.parse(readFileSync40(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION2;
|
|
22739
22975
|
} catch {
|
|
22740
22976
|
}
|
|
22741
22977
|
}
|
|
@@ -22749,15 +22985,15 @@ __export(update_notice_exports, {
|
|
|
22749
22985
|
refreshUpdateCheck: () => refreshUpdateCheck,
|
|
22750
22986
|
updateNotice: () => updateNotice2
|
|
22751
22987
|
});
|
|
22752
|
-
import { readFileSync as
|
|
22753
|
-
import { join as
|
|
22988
|
+
import { readFileSync as readFileSync41, writeFileSync as writeFileSync11 } from "node:fs";
|
|
22989
|
+
import { join as join51 } from "node:path";
|
|
22754
22990
|
function newestKnown(c) {
|
|
22755
22991
|
const npm = c.npmVersion ?? "0.0.0";
|
|
22756
22992
|
return compareVersions(npm, c.serverVersion) > 0 ? { version: npm, source: "npm" } : { version: c.serverVersion, source: "server" };
|
|
22757
22993
|
}
|
|
22758
22994
|
function readCheck() {
|
|
22759
22995
|
try {
|
|
22760
|
-
const c = JSON.parse(
|
|
22996
|
+
const c = JSON.parse(readFileSync41(checkPath(), "utf-8"));
|
|
22761
22997
|
return c && typeof c.serverVersion === "string" ? c : null;
|
|
22762
22998
|
} catch {
|
|
22763
22999
|
return null;
|
|
@@ -22851,7 +23087,7 @@ var init_update_notice = __esm({
|
|
|
22851
23087
|
init_http();
|
|
22852
23088
|
CHECK_TTL_MS = 6 * 3600 * 1e3;
|
|
22853
23089
|
NPM_LATEST_URL = "https://registry.npmjs.org/chat-recall";
|
|
22854
|
-
checkPath = () =>
|
|
23090
|
+
checkPath = () => join51(getDataDir(), "update-check.json");
|
|
22855
23091
|
printed = false;
|
|
22856
23092
|
}
|
|
22857
23093
|
});
|
|
@@ -22923,15 +23159,15 @@ __export(service_installer_exports, {
|
|
|
22923
23159
|
uninstallService: () => uninstallService
|
|
22924
23160
|
});
|
|
22925
23161
|
import { execSync as execSync5 } from "child_process";
|
|
22926
|
-
import { existsSync as existsSync46, mkdirSync as mkdirSync14, readFileSync as
|
|
23162
|
+
import { existsSync as existsSync46, mkdirSync as mkdirSync14, readFileSync as readFileSync42, rmSync as rmSync8, writeFileSync as writeFileSync12 } from "fs";
|
|
22927
23163
|
import { homedir as homedir18 } from "os";
|
|
22928
|
-
import { join as
|
|
23164
|
+
import { join as join52 } from "path";
|
|
22929
23165
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
22930
23166
|
function resolveDaemonPaths() {
|
|
22931
23167
|
const watchJs = fileURLToPath4(new URL("./watch.js", import.meta.url));
|
|
22932
23168
|
const node = process.execPath;
|
|
22933
|
-
const dataDir =
|
|
22934
|
-
const logFile =
|
|
23169
|
+
const dataDir = join52(homedir18(), ".chat-recall");
|
|
23170
|
+
const logFile = join52(dataDir, "watch.log");
|
|
22935
23171
|
return { watchJs, node, logFile, dataDir };
|
|
22936
23172
|
}
|
|
22937
23173
|
function tryCmd(cmd) {
|
|
@@ -22958,12 +23194,12 @@ function refreshServiceDefinition() {
|
|
|
22958
23194
|
if (process.platform !== "linux") return false;
|
|
22959
23195
|
try {
|
|
22960
23196
|
const { watchJs, node, logFile } = resolveDaemonPaths();
|
|
22961
|
-
const unitPath =
|
|
23197
|
+
const unitPath = join52(homedir18(), ".config", "systemd", "user", "chat-recall-watch.service");
|
|
22962
23198
|
if (!existsSync46(unitPath)) return false;
|
|
22963
|
-
const current =
|
|
23199
|
+
const current = readFileSync42(unitPath, "utf8");
|
|
22964
23200
|
if (!current.includes(watchJs)) return false;
|
|
22965
23201
|
const wanted = renderSystemdUnit(watchJs, node, logFile);
|
|
22966
|
-
if (
|
|
23202
|
+
if (readFileSync42(unitPath, "utf8") === wanted) return false;
|
|
22967
23203
|
writeFileSync12(unitPath, wanted);
|
|
22968
23204
|
execSync5("systemctl --user daemon-reload", { stdio: "ignore" });
|
|
22969
23205
|
return true;
|
|
@@ -22989,8 +23225,8 @@ function installService() {
|
|
|
22989
23225
|
);
|
|
22990
23226
|
}
|
|
22991
23227
|
function installSystemd(watchJs, node, logFile) {
|
|
22992
|
-
const unitDir =
|
|
22993
|
-
const unitPath =
|
|
23228
|
+
const unitDir = join52(homedir18(), ".config", "systemd", "user");
|
|
23229
|
+
const unitPath = join52(unitDir, "chat-recall-watch.service");
|
|
22994
23230
|
const unit = renderSystemdUnit(watchJs, node, logFile);
|
|
22995
23231
|
mkdirSync14(unitDir, { recursive: true });
|
|
22996
23232
|
writeFileSync12(unitPath, unit);
|
|
@@ -23069,8 +23305,8 @@ function renderSystemdUnit(watchJs, node, logFile) {
|
|
|
23069
23305
|
}
|
|
23070
23306
|
function installLaunchd(watchJs, node, logFile) {
|
|
23071
23307
|
const label = "com.chat-recall.watch";
|
|
23072
|
-
const plistDir =
|
|
23073
|
-
const plistPath =
|
|
23308
|
+
const plistDir = join52(homedir18(), "Library", "LaunchAgents");
|
|
23309
|
+
const plistPath = join52(plistDir, `${label}.plist`);
|
|
23074
23310
|
const plist = renderLaunchdPlist(watchJs, node, logFile, label);
|
|
23075
23311
|
mkdirSync14(plistDir, { recursive: true });
|
|
23076
23312
|
writeFileSync12(plistPath, plist);
|
|
@@ -23126,9 +23362,9 @@ function uninstallService() {
|
|
|
23126
23362
|
removed = true;
|
|
23127
23363
|
} catch {
|
|
23128
23364
|
}
|
|
23129
|
-
const unitPath =
|
|
23365
|
+
const unitPath = join52(homedir18(), ".config", "systemd", "user", "chat-recall-watch.service");
|
|
23130
23366
|
if (existsSync46(unitPath)) {
|
|
23131
|
-
|
|
23367
|
+
rmSync8(unitPath, { force: true });
|
|
23132
23368
|
removed = true;
|
|
23133
23369
|
}
|
|
23134
23370
|
try {
|
|
@@ -23138,14 +23374,14 @@ function uninstallService() {
|
|
|
23138
23374
|
return removed;
|
|
23139
23375
|
}
|
|
23140
23376
|
if (process.platform === "darwin") {
|
|
23141
|
-
const plistPath =
|
|
23377
|
+
const plistPath = join52(homedir18(), "Library", "LaunchAgents", "com.chat-recall.watch.plist");
|
|
23142
23378
|
try {
|
|
23143
23379
|
execSync5(`launchctl unload "${plistPath}" 2>/dev/null`, { stdio: "ignore" });
|
|
23144
23380
|
} catch {
|
|
23145
23381
|
}
|
|
23146
23382
|
let removed = false;
|
|
23147
23383
|
if (existsSync46(plistPath)) {
|
|
23148
|
-
|
|
23384
|
+
rmSync8(plistPath, { force: true });
|
|
23149
23385
|
removed = true;
|
|
23150
23386
|
}
|
|
23151
23387
|
return removed;
|
|
@@ -23191,15 +23427,15 @@ __export(install_skills_exports, {
|
|
|
23191
23427
|
skillsSourceDir: () => skillsSourceDir,
|
|
23192
23428
|
uninstallSkills: () => uninstallSkills
|
|
23193
23429
|
});
|
|
23194
|
-
import { readdirSync as readdirSync33, existsSync as existsSync47, mkdirSync as mkdirSync15, rmSync as
|
|
23430
|
+
import { readdirSync as readdirSync33, existsSync as existsSync47, mkdirSync as mkdirSync15, rmSync as rmSync9, cpSync, writeFileSync as writeFileSync13, readFileSync as readFileSync43, statSync as statSync45, realpathSync as realpathSync4 } from "fs";
|
|
23195
23431
|
import { createHash as createHash12 } from "crypto";
|
|
23196
|
-
import { join as
|
|
23432
|
+
import { join as join53, basename as basename23 } from "path";
|
|
23197
23433
|
function skillsSourceDir() {
|
|
23198
|
-
return
|
|
23434
|
+
return join53(import.meta.dirname, "..", "skills");
|
|
23199
23435
|
}
|
|
23200
23436
|
function version() {
|
|
23201
23437
|
try {
|
|
23202
|
-
return JSON.parse(
|
|
23438
|
+
return JSON.parse(readFileSync43(new URL("../package.json", import.meta.url), "utf-8")).version || "0.0.0";
|
|
23203
23439
|
} catch {
|
|
23204
23440
|
return "0.0.0";
|
|
23205
23441
|
}
|
|
@@ -23208,9 +23444,9 @@ function skillsFingerprint() {
|
|
|
23208
23444
|
const src = skillsSourceDir();
|
|
23209
23445
|
const h = createHash12("sha256");
|
|
23210
23446
|
for (const name of bundledSkillNames()) {
|
|
23211
|
-
for (const rel of filesUnder(
|
|
23447
|
+
for (const rel of filesUnder(join53(src, name)).sort()) {
|
|
23212
23448
|
h.update(name + "/" + rel);
|
|
23213
|
-
h.update(
|
|
23449
|
+
h.update(readFileSync43(join53(src, name, rel)));
|
|
23214
23450
|
}
|
|
23215
23451
|
}
|
|
23216
23452
|
return h.digest("hex").slice(0, 12);
|
|
@@ -23220,7 +23456,7 @@ function filesUnder(dir, prefix = "") {
|
|
|
23220
23456
|
for (const e of readdirSync33(dir, { withFileTypes: true })) {
|
|
23221
23457
|
if (e.name === MARKER) continue;
|
|
23222
23458
|
const rel = prefix ? `${prefix}/${e.name}` : e.name;
|
|
23223
|
-
if (e.isDirectory()) out.push(...filesUnder(
|
|
23459
|
+
if (e.isDirectory()) out.push(...filesUnder(join53(dir, e.name), rel));
|
|
23224
23460
|
else out.push(rel);
|
|
23225
23461
|
}
|
|
23226
23462
|
return out;
|
|
@@ -23231,7 +23467,7 @@ function skillStamp() {
|
|
|
23231
23467
|
function bundledSkillNames() {
|
|
23232
23468
|
const src = skillsSourceDir();
|
|
23233
23469
|
if (!existsSync47(src)) return [];
|
|
23234
|
-
return readdirSync33(src, { withFileTypes: true }).filter((e) => e.isDirectory() && existsSync47(
|
|
23470
|
+
return readdirSync33(src, { withFileTypes: true }).filter((e) => e.isDirectory() && existsSync47(join53(src, e.name, "SKILL.md"))).map((e) => e.name).sort();
|
|
23235
23471
|
}
|
|
23236
23472
|
function realPathOrSelf(p) {
|
|
23237
23473
|
try {
|
|
@@ -23244,7 +23480,7 @@ function claudeSkillTargets() {
|
|
|
23244
23480
|
const targets = [];
|
|
23245
23481
|
const seen = /* @__PURE__ */ new Set();
|
|
23246
23482
|
for (const home of claudeHomeDirs()) {
|
|
23247
|
-
const dir =
|
|
23483
|
+
const dir = join53(home, "skills");
|
|
23248
23484
|
const key2 = realPathOrSelf(dir);
|
|
23249
23485
|
if (seen.has(key2)) continue;
|
|
23250
23486
|
seen.add(key2);
|
|
@@ -23255,7 +23491,7 @@ function claudeSkillTargets() {
|
|
|
23255
23491
|
dir,
|
|
23256
23492
|
// Judge each profile on ITS OWN transcripts, not the primary's: a home
|
|
23257
23493
|
// with no projects/ is a directory someone made, not a Claude install.
|
|
23258
|
-
available: existsSync47(
|
|
23494
|
+
available: existsSync47(join53(home, "projects"))
|
|
23259
23495
|
});
|
|
23260
23496
|
}
|
|
23261
23497
|
if (targets.length === 0) {
|
|
@@ -23270,16 +23506,16 @@ function skillTargets() {
|
|
|
23270
23506
|
// both produces "skill conflict" duplicate warnings. Every tool we support
|
|
23271
23507
|
// has its own dir, so per-tool coverage is complete.
|
|
23272
23508
|
...claudeSkillTargets(),
|
|
23273
|
-
{ id: "agy", label: "Antigravity", dir:
|
|
23509
|
+
{ id: "agy", label: "Antigravity", dir: join53(agyBackend.homeDir(), "skills"), available: agyBackend.isAvailable() },
|
|
23274
23510
|
{ id: "codex", label: "Codex", dir: codexBackend.skillsDir(), available: codexBackend.isAvailable() },
|
|
23275
23511
|
{ id: "opencode", label: "OpenCode", dir: opencodeBackend.skillsDir(), available: opencodeBackend.isAvailable() },
|
|
23276
23512
|
// Cursor DOES have its own dir (~/.cursor/skills). `skills-cursor` next to
|
|
23277
23513
|
// it is Cursor's bundled set — read-only, never an install target.
|
|
23278
|
-
{ id: "cursor", label: "Cursor", dir:
|
|
23514
|
+
{ id: "cursor", label: "Cursor", dir: join53(cursorHomeDir(), "skills"), available: cursorBackend.isAvailable() }
|
|
23279
23515
|
];
|
|
23280
23516
|
}
|
|
23281
23517
|
function isManaged(dir) {
|
|
23282
|
-
return existsSync47(
|
|
23518
|
+
return existsSync47(join53(dir, MARKER));
|
|
23283
23519
|
}
|
|
23284
23520
|
function installSkills(opts = {}) {
|
|
23285
23521
|
const onlyAvailable = opts.onlyAvailable ?? true;
|
|
@@ -23296,15 +23532,15 @@ function installSkills(opts = {}) {
|
|
|
23296
23532
|
continue;
|
|
23297
23533
|
}
|
|
23298
23534
|
for (const name of names) {
|
|
23299
|
-
const dest =
|
|
23535
|
+
const dest = join53(t.dir, name);
|
|
23300
23536
|
if (existsSync47(dest) && !isManaged(dest)) {
|
|
23301
23537
|
skippedUserOwned.push(name);
|
|
23302
23538
|
continue;
|
|
23303
23539
|
}
|
|
23304
23540
|
mkdirSync15(t.dir, { recursive: true });
|
|
23305
|
-
|
|
23306
|
-
cpSync(
|
|
23307
|
-
writeFileSync13(
|
|
23541
|
+
rmSync9(dest, { recursive: true, force: true });
|
|
23542
|
+
cpSync(join53(src, name), dest, { recursive: true });
|
|
23543
|
+
writeFileSync13(join53(dest, MARKER), `${stamp}
|
|
23308
23544
|
`);
|
|
23309
23545
|
installed.push(name);
|
|
23310
23546
|
}
|
|
@@ -23323,9 +23559,9 @@ function uninstallSkills() {
|
|
|
23323
23559
|
}
|
|
23324
23560
|
for (const entry of readdirSync33(t.dir, { withFileTypes: true })) {
|
|
23325
23561
|
if (!entry.isDirectory()) continue;
|
|
23326
|
-
const dir =
|
|
23562
|
+
const dir = join53(t.dir, entry.name);
|
|
23327
23563
|
if (isManaged(dir) && (names.has(entry.name) || entry.name.startsWith("chat-recall"))) {
|
|
23328
|
-
|
|
23564
|
+
rmSync9(dir, { recursive: true, force: true });
|
|
23329
23565
|
removed.push(entry.name);
|
|
23330
23566
|
}
|
|
23331
23567
|
}
|
|
@@ -23340,10 +23576,10 @@ function skillsNeedRefresh() {
|
|
|
23340
23576
|
for (const t of skillTargets()) {
|
|
23341
23577
|
if (!t.available) continue;
|
|
23342
23578
|
for (const name of names) {
|
|
23343
|
-
const marker =
|
|
23579
|
+
const marker = join53(t.dir, name, MARKER);
|
|
23344
23580
|
if (!existsSync47(marker)) return true;
|
|
23345
23581
|
try {
|
|
23346
|
-
if (
|
|
23582
|
+
if (readFileSync43(marker, "utf-8").trim() !== cur) return true;
|
|
23347
23583
|
} catch {
|
|
23348
23584
|
return true;
|
|
23349
23585
|
}
|
|
@@ -23358,11 +23594,11 @@ function skillStatus() {
|
|
|
23358
23594
|
let installed = 0;
|
|
23359
23595
|
let ver = null;
|
|
23360
23596
|
for (const name of names) {
|
|
23361
|
-
const marker =
|
|
23597
|
+
const marker = join53(t.dir, name, MARKER);
|
|
23362
23598
|
if (existsSync47(marker)) {
|
|
23363
23599
|
installed++;
|
|
23364
23600
|
try {
|
|
23365
|
-
ver =
|
|
23601
|
+
ver = readFileSync43(marker, "utf-8").trim();
|
|
23366
23602
|
} catch {
|
|
23367
23603
|
}
|
|
23368
23604
|
}
|
|
@@ -29457,9 +29693,9 @@ function openBrowser(url) {
|
|
|
29457
29693
|
// src/mcp.ts
|
|
29458
29694
|
init_client_events();
|
|
29459
29695
|
init_update_notice();
|
|
29460
|
-
import { readFileSync as
|
|
29696
|
+
import { readFileSync as readFileSync44 } from "node:fs";
|
|
29461
29697
|
setServerVersion(JSON.parse(
|
|
29462
|
-
|
|
29698
|
+
readFileSync44(new URL("../package.json", import.meta.url), "utf-8")
|
|
29463
29699
|
).version);
|
|
29464
29700
|
setEventReporter(reportClientEvent2);
|
|
29465
29701
|
setIndexRunner(runIndexChild2);
|
|
@@ -29576,9 +29812,9 @@ var SYNC_TICK_MS = 3 * 6e4;
|
|
|
29576
29812
|
function startBackgroundSync() {
|
|
29577
29813
|
const tick = async (scope) => {
|
|
29578
29814
|
try {
|
|
29579
|
-
const { installedVersion:
|
|
29815
|
+
const { installedVersion: installedVersion3 } = await Promise.resolve().then(() => (init_auto_update(), auto_update_exports));
|
|
29580
29816
|
const { installedIsNewer: installedIsNewer2, runInstalledSync: runInstalledSync2 } = await Promise.resolve().then(() => (init_sync_delegate(), sync_delegate_exports));
|
|
29581
|
-
const installed =
|
|
29817
|
+
const installed = installedVersion3();
|
|
29582
29818
|
if (installedIsNewer2(RELAY_VERSION, installed)) {
|
|
29583
29819
|
const code = await runInstalledSync2(fileURLToPath5(new URL("./cli.js", import.meta.url)));
|
|
29584
29820
|
if (code !== 0) console.error(`[mcp] sync by the installed CLI ${installed} ended with ${code ?? "no exit code"}`);
|
|
@@ -29632,7 +29868,7 @@ function installCrashGuards() {
|
|
|
29632
29868
|
reportClientEvent2("mcp_crash", { message: err.stack || err.message });
|
|
29633
29869
|
});
|
|
29634
29870
|
}
|
|
29635
|
-
var RELAY_VERSION = true ? "0.7.
|
|
29871
|
+
var RELAY_VERSION = true ? "0.7.18" : "0.0.0";
|
|
29636
29872
|
function daemonIdleSecs() {
|
|
29637
29873
|
const raw = process.env.CHAT_RECALL_DAEMON_IDLE_SECS;
|
|
29638
29874
|
if (raw === void 0) return 900;
|
|
@@ -29728,8 +29964,25 @@ async function runDaemon() {
|
|
|
29728
29964
|
};
|
|
29729
29965
|
process.on("SIGTERM", shutdown);
|
|
29730
29966
|
process.on("SIGINT", shutdown);
|
|
29967
|
+
const upgradeTimer = setInterval(() => {
|
|
29968
|
+
const installed = installedVersion2();
|
|
29969
|
+
if (installed && RELAY_VERSION !== "0.0.0" && installed !== RELAY_VERSION) {
|
|
29970
|
+
console.error(`[mcp] v${installed} is installed; daemon v${RELAY_VERSION} is leaving`);
|
|
29971
|
+
clearInterval(upgradeTimer);
|
|
29972
|
+
shutdown();
|
|
29973
|
+
}
|
|
29974
|
+
}, 3e4);
|
|
29975
|
+
upgradeTimer.unref();
|
|
29731
29976
|
return true;
|
|
29732
29977
|
}
|
|
29978
|
+
function installedVersion2() {
|
|
29979
|
+
try {
|
|
29980
|
+
const pkg = JSON.parse(readFileSync44(new URL("../package.json", import.meta.url), "utf-8"));
|
|
29981
|
+
return typeof pkg.version === "string" ? pkg.version : null;
|
|
29982
|
+
} catch {
|
|
29983
|
+
return null;
|
|
29984
|
+
}
|
|
29985
|
+
}
|
|
29733
29986
|
async function main() {
|
|
29734
29987
|
installCrashGuards();
|
|
29735
29988
|
if (process.argv.includes("--daemon")) {
|