chat-recall 0.7.17 → 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 +567 -328
- package/dist/mcp-relay.js +136 -40
- package/dist/mcp-relay.js.map +1 -1
- package/dist/mcp.js +375 -125
- 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 +441 -199
- 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
|
});
|
|
@@ -19734,6 +19736,11 @@ function markSynced(server, rows) {
|
|
|
19734
19736
|
base2.s = s;
|
|
19735
19737
|
}
|
|
19736
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;
|
|
19737
19744
|
forServer[r.id] = base2;
|
|
19738
19745
|
}
|
|
19739
19746
|
persist(data);
|
|
@@ -19790,6 +19797,14 @@ function markFieldFullPassDone(server, field) {
|
|
|
19790
19797
|
delete st.force[field.name];
|
|
19791
19798
|
persistReconcile(data);
|
|
19792
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
|
+
}
|
|
19793
19808
|
function markFullResync(server, sessionId) {
|
|
19794
19809
|
const data = load();
|
|
19795
19810
|
const forServer = data[server];
|
|
@@ -19798,7 +19813,11 @@ function markFullResync(server, sessionId) {
|
|
|
19798
19813
|
delete forServer[sessionId];
|
|
19799
19814
|
persist(data);
|
|
19800
19815
|
}
|
|
19801
|
-
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()) {
|
|
19802
19821
|
if (!row) return "full";
|
|
19803
19822
|
if (row.v < extractorVersion) return "full";
|
|
19804
19823
|
const offset = row.o ?? 0;
|
|
@@ -19806,10 +19825,13 @@ function syncMode(row, mtime, fileSize, extractorVersion, isAppendOnly) {
|
|
|
19806
19825
|
if (process.env.CHAT_RECALL_TAIL_APPEND !== "0" && isAppendOnly && fileSize > 0 && offset > 0 && fileSize > (row.s ?? 0)) {
|
|
19807
19826
|
return "append";
|
|
19808
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
|
+
}
|
|
19809
19831
|
if (row.m >= Math.floor(mtime)) return "skip";
|
|
19810
19832
|
return "full";
|
|
19811
19833
|
}
|
|
19812
|
-
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;
|
|
19813
19835
|
var init_sync_ledger = __esm({
|
|
19814
19836
|
"src/sync-ledger.ts"() {
|
|
19815
19837
|
"use strict";
|
|
@@ -19829,6 +19851,7 @@ var init_sync_ledger = __esm({
|
|
|
19829
19851
|
unackedCursorAttempts = 0;
|
|
19830
19852
|
reconcilePath = () => join46(getDataDir(), "sync-field-reconcile.json");
|
|
19831
19853
|
reconcileCache = null;
|
|
19854
|
+
SETTLE_QUIET_MS = 2 * 60 * 60 * 1e3;
|
|
19832
19855
|
}
|
|
19833
19856
|
});
|
|
19834
19857
|
|
|
@@ -19974,7 +19997,7 @@ var init_http = __esm({
|
|
|
19974
19997
|
CLI_VERSION = JSON.parse(readFileSync36(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
|
|
19975
19998
|
} catch {
|
|
19976
19999
|
try {
|
|
19977
|
-
if (true) CLI_VERSION = "0.7.
|
|
20000
|
+
if (true) CLI_VERSION = "0.7.18";
|
|
19978
20001
|
} catch {
|
|
19979
20002
|
}
|
|
19980
20003
|
}
|
|
@@ -20472,7 +20495,7 @@ var init_telemetry = __esm({
|
|
|
20472
20495
|
init_sync_client();
|
|
20473
20496
|
cliVersion2 = () => {
|
|
20474
20497
|
try {
|
|
20475
|
-
return true ? "0.7.
|
|
20498
|
+
return true ? "0.7.18" : "dev";
|
|
20476
20499
|
} catch {
|
|
20477
20500
|
return "dev";
|
|
20478
20501
|
}
|
|
@@ -20482,6 +20505,150 @@ var init_telemetry = __esm({
|
|
|
20482
20505
|
}
|
|
20483
20506
|
});
|
|
20484
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
|
+
|
|
20485
20652
|
// src/server-probe.ts
|
|
20486
20653
|
var server_probe_exports = {};
|
|
20487
20654
|
__export(server_probe_exports, {
|
|
@@ -20643,11 +20810,11 @@ __export(auto_update_exports, {
|
|
|
20643
20810
|
tarballUrl: () => tarballUrl
|
|
20644
20811
|
});
|
|
20645
20812
|
import { execSync as execSync4, execFileSync as execFileSync3 } from "node:child_process";
|
|
20646
|
-
import { readFileSync as
|
|
20813
|
+
import { readFileSync as readFileSync38, existsSync as existsSync45 } from "node:fs";
|
|
20647
20814
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
20648
|
-
import { writeFileSync as writeFileSync9, mkdtempSync as mkdtempSync3, rmSync as
|
|
20649
|
-
import { join as
|
|
20650
|
-
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";
|
|
20651
20818
|
import { createHash as createHash10 } from "node:crypto";
|
|
20652
20819
|
function compareVersions(a, b) {
|
|
20653
20820
|
const pa = String(a).split("-")[0].split(".").map((n) => parseInt(n, 10) || 0);
|
|
@@ -20671,7 +20838,7 @@ function newerOf(a, b) {
|
|
|
20671
20838
|
function installedVersion() {
|
|
20672
20839
|
try {
|
|
20673
20840
|
const here = dirname19(fileURLToPath2(import.meta.url));
|
|
20674
|
-
const raw =
|
|
20841
|
+
const raw = readFileSync38(join49(here, "..", "package.json"), "utf-8");
|
|
20675
20842
|
return JSON.parse(raw).version || null;
|
|
20676
20843
|
} catch {
|
|
20677
20844
|
return null;
|
|
@@ -20684,7 +20851,7 @@ function planAutoUpdate(base2, caps, ownVersion2, flag) {
|
|
|
20684
20851
|
if (compareVersions(rel.version, ownVersion2) <= 0) return { update: false, reason: `already current (own ${ownVersion2} >= server ${rel.version})` };
|
|
20685
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 };
|
|
20686
20853
|
}
|
|
20687
|
-
function sweepStaleStaging(root =
|
|
20854
|
+
function sweepStaleStaging(root = tmpdir4(), now = Date.now()) {
|
|
20688
20855
|
const MKDTEMP_SUFFIX = /^cr-update-.{6}$/s;
|
|
20689
20856
|
const COLD_MS = 60 * 60 * 1e3;
|
|
20690
20857
|
let removed = 0;
|
|
@@ -20696,13 +20863,13 @@ function sweepStaleStaging(root = tmpdir3(), now = Date.now()) {
|
|
|
20696
20863
|
}
|
|
20697
20864
|
for (const name of entries) {
|
|
20698
20865
|
if (!MKDTEMP_SUFFIX.test(name)) continue;
|
|
20699
|
-
const dir =
|
|
20866
|
+
const dir = join49(root, name);
|
|
20700
20867
|
try {
|
|
20701
|
-
const st =
|
|
20868
|
+
const st = statSync43(dir);
|
|
20702
20869
|
if (!st.isDirectory() || now - st.mtimeMs < COLD_MS) continue;
|
|
20703
20870
|
const inside = readdirSync31(dir);
|
|
20704
20871
|
if (inside.length > 1 || inside.length === 1 && inside[0] !== "chat-recall.tgz") continue;
|
|
20705
|
-
|
|
20872
|
+
rmSync6(dir, { recursive: true, force: true });
|
|
20706
20873
|
removed++;
|
|
20707
20874
|
} catch {
|
|
20708
20875
|
}
|
|
@@ -20725,14 +20892,14 @@ async function executeAutoUpdate(plan, deps) {
|
|
|
20725
20892
|
}
|
|
20726
20893
|
const got = createHash10("sha256").update(buf).digest("hex");
|
|
20727
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` };
|
|
20728
|
-
const dir = mkdtempSync3(
|
|
20895
|
+
const dir = mkdtempSync3(join49(tmpdir4(), "cr-update-"));
|
|
20729
20896
|
const discardStaging = () => {
|
|
20730
20897
|
try {
|
|
20731
|
-
|
|
20898
|
+
rmSync6(dir, { recursive: true, force: true });
|
|
20732
20899
|
} catch {
|
|
20733
20900
|
}
|
|
20734
20901
|
};
|
|
20735
|
-
const tgz =
|
|
20902
|
+
const tgz = join49(dir, "chat-recall.tgz");
|
|
20736
20903
|
writeFileSync9(tgz, buf);
|
|
20737
20904
|
if (deps.stopping?.()) {
|
|
20738
20905
|
discardStaging();
|
|
@@ -20812,7 +20979,7 @@ function realInstall(tgz) {
|
|
|
20812
20979
|
try {
|
|
20813
20980
|
npmInstall(npm, ["install", "-g", tgz]);
|
|
20814
20981
|
} catch {
|
|
20815
|
-
npmInstall(npm, ["install", "-g", "--prefix",
|
|
20982
|
+
npmInstall(npm, ["install", "-g", "--prefix", join49(homedir17(), ".local"), tgz]);
|
|
20816
20983
|
}
|
|
20817
20984
|
}
|
|
20818
20985
|
function acquireUpdateLock() {
|
|
@@ -20829,12 +20996,12 @@ function realRestart(platform2) {
|
|
|
20829
20996
|
if (c) execSync4(c.cmd, { stdio: "ignore", ...c.shell ? { shell: c.shell } : {} });
|
|
20830
20997
|
}
|
|
20831
20998
|
function updateStatePath() {
|
|
20832
|
-
const dir = process.env.CHAT_RECALL_DATA_DIR ||
|
|
20833
|
-
return
|
|
20999
|
+
const dir = process.env.CHAT_RECALL_DATA_DIR || join49(homedir17(), ".chat-recall");
|
|
21000
|
+
return join49(dir, "auto-update-state.json");
|
|
20834
21001
|
}
|
|
20835
21002
|
function readUpdateState() {
|
|
20836
21003
|
try {
|
|
20837
|
-
return JSON.parse(
|
|
21004
|
+
return JSON.parse(readFileSync38(updateStatePath(), "utf8"));
|
|
20838
21005
|
} catch {
|
|
20839
21006
|
return {};
|
|
20840
21007
|
}
|
|
@@ -20975,9 +21142,9 @@ __export(sync_client_exports, {
|
|
|
20975
21142
|
syncIncremental: () => syncIncremental,
|
|
20976
21143
|
syncSessions: () => syncSessions
|
|
20977
21144
|
});
|
|
20978
|
-
import { join as
|
|
20979
|
-
import { readFileSync as
|
|
20980
|
-
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";
|
|
20981
21148
|
import { createHash as createHash11 } from "node:crypto";
|
|
20982
21149
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
20983
21150
|
import { gzipSync as gzipSync3 } from "zlib";
|
|
@@ -21031,7 +21198,7 @@ function loadAllCredentials() {
|
|
|
21031
21198
|
const fromEnv = envCredentials();
|
|
21032
21199
|
if (fromEnv) return [{ serverUrl: fromEnv.serverUrl, token: fromEnv.token }];
|
|
21033
21200
|
try {
|
|
21034
|
-
const parsed = JSON.parse(
|
|
21201
|
+
const parsed = JSON.parse(readFileSync39(credPath(), "utf-8"));
|
|
21035
21202
|
if (Array.isArray(parsed?.targets)) return parsed.targets.filter((t) => t?.serverUrl).map((t) => ({ serverUrl: t.serverUrl, token: t.token || "" }));
|
|
21036
21203
|
if (parsed?.serverUrl) return [{ serverUrl: parsed.serverUrl, token: parsed.token || "" }];
|
|
21037
21204
|
} catch {
|
|
@@ -21093,11 +21260,11 @@ function _resetTenantSecurityConfigCache() {
|
|
|
21093
21260
|
_securityConfigCache.clear();
|
|
21094
21261
|
}
|
|
21095
21262
|
function syncConfigCachePath() {
|
|
21096
|
-
return
|
|
21263
|
+
return join50(getDataDir(), "sync-config-cache.json");
|
|
21097
21264
|
}
|
|
21098
21265
|
function readPersistedSyncConfigs() {
|
|
21099
21266
|
try {
|
|
21100
|
-
return JSON.parse(
|
|
21267
|
+
return JSON.parse(readFileSync39(syncConfigCachePath(), "utf-8"));
|
|
21101
21268
|
} catch {
|
|
21102
21269
|
return {};
|
|
21103
21270
|
}
|
|
@@ -21375,7 +21542,7 @@ async function reconcileFields(opts = {}) {
|
|
|
21375
21542
|
}
|
|
21376
21543
|
return { sessions: fullRefs().length, scanned, pushed, absent, perTarget };
|
|
21377
21544
|
}
|
|
21378
|
-
function reapStaleScanDirs(dir =
|
|
21545
|
+
function reapStaleScanDirs(dir = tmpdir5(), maxAgeMs = 6 * 36e5, now = Date.now()) {
|
|
21379
21546
|
let reaped = 0;
|
|
21380
21547
|
let names;
|
|
21381
21548
|
try {
|
|
@@ -21385,10 +21552,10 @@ function reapStaleScanDirs(dir = tmpdir4(), maxAgeMs = 6 * 36e5, now = Date.now(
|
|
|
21385
21552
|
}
|
|
21386
21553
|
for (const name of names) {
|
|
21387
21554
|
if (!name.startsWith("cr-batchscan-")) continue;
|
|
21388
|
-
const p =
|
|
21555
|
+
const p = join50(dir, name);
|
|
21389
21556
|
try {
|
|
21390
|
-
if (now -
|
|
21391
|
-
|
|
21557
|
+
if (now - statSync44(p).mtimeMs < maxAgeMs) continue;
|
|
21558
|
+
rmSync7(p, { recursive: true, force: true });
|
|
21392
21559
|
reaped++;
|
|
21393
21560
|
} catch {
|
|
21394
21561
|
}
|
|
@@ -21402,7 +21569,7 @@ function batchScanExternal(items, opts = {}) {
|
|
|
21402
21569
|
let scanned = 0, slices = 0, scanMs = 0;
|
|
21403
21570
|
if (items.length === 0) return { findings, scanned, slices, scanMs };
|
|
21404
21571
|
reapStaleScanDirs();
|
|
21405
|
-
let scanDir = mkdtempSync4(
|
|
21572
|
+
let scanDir = mkdtempSync4(join50(tmpdir5(), "cr-batchscan-"));
|
|
21406
21573
|
let safeToId = /* @__PURE__ */ new Map();
|
|
21407
21574
|
let bytesInDir = 0;
|
|
21408
21575
|
const flushSlice = () => {
|
|
@@ -21420,7 +21587,7 @@ function batchScanExternal(items, opts = {}) {
|
|
|
21420
21587
|
slices++;
|
|
21421
21588
|
}
|
|
21422
21589
|
try {
|
|
21423
|
-
|
|
21590
|
+
rmSync7(scanDir, { recursive: true, force: true });
|
|
21424
21591
|
} catch {
|
|
21425
21592
|
}
|
|
21426
21593
|
safeToId = /* @__PURE__ */ new Map();
|
|
@@ -21433,19 +21600,19 @@ function batchScanExternal(items, opts = {}) {
|
|
|
21433
21600
|
if (raw === null) continue;
|
|
21434
21601
|
const safe = item.id.replace(/[^A-Za-z0-9_-]/g, "");
|
|
21435
21602
|
safeToId.set(safe, item.id);
|
|
21436
|
-
writeFileSync10(
|
|
21603
|
+
writeFileSync10(join50(scanDir, `${safe}.txt`), raw);
|
|
21437
21604
|
bytesInDir += Buffer.byteLength(raw);
|
|
21438
21605
|
} catch {
|
|
21439
21606
|
}
|
|
21440
21607
|
if (bytesInDir >= maxBytes) {
|
|
21441
21608
|
flushSlice();
|
|
21442
|
-
scanDir = mkdtempSync4(
|
|
21609
|
+
scanDir = mkdtempSync4(join50(tmpdir5(), "cr-batchscan-"));
|
|
21443
21610
|
}
|
|
21444
21611
|
}
|
|
21445
21612
|
flushSlice();
|
|
21446
21613
|
} finally {
|
|
21447
21614
|
try {
|
|
21448
|
-
|
|
21615
|
+
rmSync7(scanDir, { recursive: true, force: true });
|
|
21449
21616
|
} catch {
|
|
21450
21617
|
}
|
|
21451
21618
|
}
|
|
@@ -21689,12 +21856,13 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
21689
21856
|
markSynced(base2, rows.map((r) => {
|
|
21690
21857
|
const off = typeof r.from_offset === "number" ? r.from_offset : 0;
|
|
21691
21858
|
const hash = shippedHash.get(r.session_id);
|
|
21692
|
-
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 };
|
|
21693
21860
|
}));
|
|
21694
21861
|
} catch {
|
|
21695
21862
|
}
|
|
21696
21863
|
});
|
|
21697
21864
|
const appendResults = { uploaded: 0, fullResyncNeeded: /* @__PURE__ */ new Set() };
|
|
21865
|
+
const pendingArchives = [];
|
|
21698
21866
|
const postAppend = async (convs) => {
|
|
21699
21867
|
const headers = { "content-type": "application/json" };
|
|
21700
21868
|
if (cred.token) headers.authorization = `Bearer ${cred.token}`;
|
|
@@ -21729,8 +21897,10 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
21729
21897
|
offset: c.from_offset,
|
|
21730
21898
|
size: c.from_offset,
|
|
21731
21899
|
// size = new offset (file grew to here)
|
|
21732
|
-
acked: true
|
|
21900
|
+
acked: true,
|
|
21733
21901
|
// server merged this tail
|
|
21902
|
+
chunkFinal: c.final === true
|
|
21903
|
+
// completes a chunked full sync
|
|
21734
21904
|
})));
|
|
21735
21905
|
} catch {
|
|
21736
21906
|
}
|
|
@@ -21762,9 +21932,9 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
21762
21932
|
const mtime = conv.mtime;
|
|
21763
21933
|
try {
|
|
21764
21934
|
if (staged || !guarded) {
|
|
21765
|
-
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 }]);
|
|
21766
21936
|
} else if (typeof guarded.o === "number" && guarded.o > 0 && guarded.o <= fileSize) {
|
|
21767
|
-
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 }]);
|
|
21768
21938
|
} else {
|
|
21769
21939
|
markSynced(base2, [{ id, mtime }]);
|
|
21770
21940
|
}
|
|
@@ -21973,6 +22143,14 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
21973
22143
|
if (built.srcHash) shippedHash.set(ref.prefixedId, built.srcHash);
|
|
21974
22144
|
if (built.conv.chunked) await postChunkedHead(built.conv, sessionFileBytes(ref));
|
|
21975
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
|
+
}
|
|
21976
22154
|
if (built.findings.length > 0) await findingsBatch.add(built.findings);
|
|
21977
22155
|
if (upload.sessionMeta) {
|
|
21978
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);
|
|
@@ -22125,6 +22303,30 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
22125
22303
|
await kgTripleBatch.drain();
|
|
22126
22304
|
await findingsBatch.drain();
|
|
22127
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
|
+
}
|
|
22128
22330
|
{
|
|
22129
22331
|
const sentHashes = loadInventoryHashes(base2);
|
|
22130
22332
|
const entries = [];
|
|
@@ -22230,6 +22432,7 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
22230
22432
|
let includeRaw = opts.includeRaw !== false;
|
|
22231
22433
|
let includeMeta = opts.includeMeta !== false;
|
|
22232
22434
|
let srcHash;
|
|
22435
|
+
const wantRaw = opts.includeRaw !== false;
|
|
22233
22436
|
const oversized = sessionBuildBytes(ref) > FULL_BUILD_MAX_BYTES;
|
|
22234
22437
|
let headOffsetEnd = 0;
|
|
22235
22438
|
let oversizedFindings = null;
|
|
@@ -22398,7 +22601,7 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
22398
22601
|
} else if (opts.scanSecrets) {
|
|
22399
22602
|
let tmp = null;
|
|
22400
22603
|
try {
|
|
22401
|
-
tmp =
|
|
22604
|
+
tmp = join50(tmpdir5(), `cr-scan-${ref.prefixedId.replace(/[^A-Za-z0-9_-]/g, "")}-${mtime}.txt`);
|
|
22402
22605
|
writeFileSync10(tmp, rawText);
|
|
22403
22606
|
for (const f of scanFileForSecrets(tmp, { verifyOnly: opts.verifySecrets, tenantRules: opts.tenantRules })) {
|
|
22404
22607
|
const verifiedAt = f.verified ? (/* @__PURE__ */ new Date()).toISOString() : null;
|
|
@@ -22450,6 +22653,25 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
22450
22653
|
}
|
|
22451
22654
|
const envTexts = envelope.messages.filter((m) => m.content?.trim());
|
|
22452
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
|
+
}
|
|
22453
22675
|
return {
|
|
22454
22676
|
conv: {
|
|
22455
22677
|
session_id: ref.prefixedId,
|
|
@@ -22481,7 +22703,17 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
22481
22703
|
redactions: count.redactions,
|
|
22482
22704
|
findings,
|
|
22483
22705
|
scanMs,
|
|
22484
|
-
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] }))
|
|
22485
22717
|
};
|
|
22486
22718
|
}
|
|
22487
22719
|
function parseTailMessages(tool, text) {
|
|
@@ -22637,14 +22869,15 @@ var init_sync_client = __esm({
|
|
|
22637
22869
|
init_telemetry();
|
|
22638
22870
|
init_collector_health();
|
|
22639
22871
|
init_live_session_scan();
|
|
22872
|
+
init_raw_archive_parts();
|
|
22640
22873
|
init_backends();
|
|
22641
22874
|
ownVersion = "0.0.0";
|
|
22642
22875
|
try {
|
|
22643
22876
|
const dir = dirname20(fileURLToPath3(import.meta.url));
|
|
22644
|
-
ownVersion = JSON.parse(
|
|
22877
|
+
ownVersion = JSON.parse(readFileSync39(join50(dir, "../package.json"), "utf-8")).version || ownVersion;
|
|
22645
22878
|
} catch {
|
|
22646
22879
|
try {
|
|
22647
|
-
if (true) ownVersion = "0.7.
|
|
22880
|
+
if (true) ownVersion = "0.7.18";
|
|
22648
22881
|
} catch {
|
|
22649
22882
|
}
|
|
22650
22883
|
}
|
|
@@ -22656,7 +22889,7 @@ var init_sync_client = __esm({
|
|
|
22656
22889
|
]);
|
|
22657
22890
|
walkProgressForUpload = null;
|
|
22658
22891
|
lastServerPackSpec = null;
|
|
22659
|
-
credPath = () =>
|
|
22892
|
+
credPath = () => join50(getDataDir(), "credentials.json");
|
|
22660
22893
|
_securityConfigCache = /* @__PURE__ */ new Map();
|
|
22661
22894
|
SECURITY_CONFIG_TTL_MS = 5 * 60 * 1e3;
|
|
22662
22895
|
_syncConfigCache = /* @__PURE__ */ new Map();
|
|
@@ -22685,7 +22918,7 @@ __export(client_events_exports, {
|
|
|
22685
22918
|
isTelemetryEnabled: () => isTelemetryEnabled,
|
|
22686
22919
|
reportClientEvent: () => reportClientEvent2
|
|
22687
22920
|
});
|
|
22688
|
-
import { readFileSync as
|
|
22921
|
+
import { readFileSync as readFileSync40 } from "node:fs";
|
|
22689
22922
|
function scrub(msg) {
|
|
22690
22923
|
if (!msg) return "";
|
|
22691
22924
|
const noHome = msg.replace(/\/(?:home|Users)\/[^/\s]+/g, "~");
|
|
@@ -22738,7 +22971,7 @@ var init_client_events = __esm({
|
|
|
22738
22971
|
init_secret_redactor();
|
|
22739
22972
|
CLI_VERSION2 = "0.0.0";
|
|
22740
22973
|
try {
|
|
22741
|
-
CLI_VERSION2 = JSON.parse(
|
|
22974
|
+
CLI_VERSION2 = JSON.parse(readFileSync40(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION2;
|
|
22742
22975
|
} catch {
|
|
22743
22976
|
}
|
|
22744
22977
|
}
|
|
@@ -22752,15 +22985,15 @@ __export(update_notice_exports, {
|
|
|
22752
22985
|
refreshUpdateCheck: () => refreshUpdateCheck,
|
|
22753
22986
|
updateNotice: () => updateNotice2
|
|
22754
22987
|
});
|
|
22755
|
-
import { readFileSync as
|
|
22756
|
-
import { join as
|
|
22988
|
+
import { readFileSync as readFileSync41, writeFileSync as writeFileSync11 } from "node:fs";
|
|
22989
|
+
import { join as join51 } from "node:path";
|
|
22757
22990
|
function newestKnown(c) {
|
|
22758
22991
|
const npm = c.npmVersion ?? "0.0.0";
|
|
22759
22992
|
return compareVersions(npm, c.serverVersion) > 0 ? { version: npm, source: "npm" } : { version: c.serverVersion, source: "server" };
|
|
22760
22993
|
}
|
|
22761
22994
|
function readCheck() {
|
|
22762
22995
|
try {
|
|
22763
|
-
const c = JSON.parse(
|
|
22996
|
+
const c = JSON.parse(readFileSync41(checkPath(), "utf-8"));
|
|
22764
22997
|
return c && typeof c.serverVersion === "string" ? c : null;
|
|
22765
22998
|
} catch {
|
|
22766
22999
|
return null;
|
|
@@ -22854,7 +23087,7 @@ var init_update_notice = __esm({
|
|
|
22854
23087
|
init_http();
|
|
22855
23088
|
CHECK_TTL_MS = 6 * 3600 * 1e3;
|
|
22856
23089
|
NPM_LATEST_URL = "https://registry.npmjs.org/chat-recall";
|
|
22857
|
-
checkPath = () =>
|
|
23090
|
+
checkPath = () => join51(getDataDir(), "update-check.json");
|
|
22858
23091
|
printed = false;
|
|
22859
23092
|
}
|
|
22860
23093
|
});
|
|
@@ -22926,15 +23159,15 @@ __export(service_installer_exports, {
|
|
|
22926
23159
|
uninstallService: () => uninstallService
|
|
22927
23160
|
});
|
|
22928
23161
|
import { execSync as execSync5 } from "child_process";
|
|
22929
|
-
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";
|
|
22930
23163
|
import { homedir as homedir18 } from "os";
|
|
22931
|
-
import { join as
|
|
23164
|
+
import { join as join52 } from "path";
|
|
22932
23165
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
22933
23166
|
function resolveDaemonPaths() {
|
|
22934
23167
|
const watchJs = fileURLToPath4(new URL("./watch.js", import.meta.url));
|
|
22935
23168
|
const node = process.execPath;
|
|
22936
|
-
const dataDir =
|
|
22937
|
-
const logFile =
|
|
23169
|
+
const dataDir = join52(homedir18(), ".chat-recall");
|
|
23170
|
+
const logFile = join52(dataDir, "watch.log");
|
|
22938
23171
|
return { watchJs, node, logFile, dataDir };
|
|
22939
23172
|
}
|
|
22940
23173
|
function tryCmd(cmd) {
|
|
@@ -22961,12 +23194,12 @@ function refreshServiceDefinition() {
|
|
|
22961
23194
|
if (process.platform !== "linux") return false;
|
|
22962
23195
|
try {
|
|
22963
23196
|
const { watchJs, node, logFile } = resolveDaemonPaths();
|
|
22964
|
-
const unitPath =
|
|
23197
|
+
const unitPath = join52(homedir18(), ".config", "systemd", "user", "chat-recall-watch.service");
|
|
22965
23198
|
if (!existsSync46(unitPath)) return false;
|
|
22966
|
-
const current =
|
|
23199
|
+
const current = readFileSync42(unitPath, "utf8");
|
|
22967
23200
|
if (!current.includes(watchJs)) return false;
|
|
22968
23201
|
const wanted = renderSystemdUnit(watchJs, node, logFile);
|
|
22969
|
-
if (
|
|
23202
|
+
if (readFileSync42(unitPath, "utf8") === wanted) return false;
|
|
22970
23203
|
writeFileSync12(unitPath, wanted);
|
|
22971
23204
|
execSync5("systemctl --user daemon-reload", { stdio: "ignore" });
|
|
22972
23205
|
return true;
|
|
@@ -22992,8 +23225,8 @@ function installService() {
|
|
|
22992
23225
|
);
|
|
22993
23226
|
}
|
|
22994
23227
|
function installSystemd(watchJs, node, logFile) {
|
|
22995
|
-
const unitDir =
|
|
22996
|
-
const unitPath =
|
|
23228
|
+
const unitDir = join52(homedir18(), ".config", "systemd", "user");
|
|
23229
|
+
const unitPath = join52(unitDir, "chat-recall-watch.service");
|
|
22997
23230
|
const unit = renderSystemdUnit(watchJs, node, logFile);
|
|
22998
23231
|
mkdirSync14(unitDir, { recursive: true });
|
|
22999
23232
|
writeFileSync12(unitPath, unit);
|
|
@@ -23072,8 +23305,8 @@ function renderSystemdUnit(watchJs, node, logFile) {
|
|
|
23072
23305
|
}
|
|
23073
23306
|
function installLaunchd(watchJs, node, logFile) {
|
|
23074
23307
|
const label = "com.chat-recall.watch";
|
|
23075
|
-
const plistDir =
|
|
23076
|
-
const plistPath =
|
|
23308
|
+
const plistDir = join52(homedir18(), "Library", "LaunchAgents");
|
|
23309
|
+
const plistPath = join52(plistDir, `${label}.plist`);
|
|
23077
23310
|
const plist = renderLaunchdPlist(watchJs, node, logFile, label);
|
|
23078
23311
|
mkdirSync14(plistDir, { recursive: true });
|
|
23079
23312
|
writeFileSync12(plistPath, plist);
|
|
@@ -23129,9 +23362,9 @@ function uninstallService() {
|
|
|
23129
23362
|
removed = true;
|
|
23130
23363
|
} catch {
|
|
23131
23364
|
}
|
|
23132
|
-
const unitPath =
|
|
23365
|
+
const unitPath = join52(homedir18(), ".config", "systemd", "user", "chat-recall-watch.service");
|
|
23133
23366
|
if (existsSync46(unitPath)) {
|
|
23134
|
-
|
|
23367
|
+
rmSync8(unitPath, { force: true });
|
|
23135
23368
|
removed = true;
|
|
23136
23369
|
}
|
|
23137
23370
|
try {
|
|
@@ -23141,14 +23374,14 @@ function uninstallService() {
|
|
|
23141
23374
|
return removed;
|
|
23142
23375
|
}
|
|
23143
23376
|
if (process.platform === "darwin") {
|
|
23144
|
-
const plistPath =
|
|
23377
|
+
const plistPath = join52(homedir18(), "Library", "LaunchAgents", "com.chat-recall.watch.plist");
|
|
23145
23378
|
try {
|
|
23146
23379
|
execSync5(`launchctl unload "${plistPath}" 2>/dev/null`, { stdio: "ignore" });
|
|
23147
23380
|
} catch {
|
|
23148
23381
|
}
|
|
23149
23382
|
let removed = false;
|
|
23150
23383
|
if (existsSync46(plistPath)) {
|
|
23151
|
-
|
|
23384
|
+
rmSync8(plistPath, { force: true });
|
|
23152
23385
|
removed = true;
|
|
23153
23386
|
}
|
|
23154
23387
|
return removed;
|
|
@@ -23194,15 +23427,15 @@ __export(install_skills_exports, {
|
|
|
23194
23427
|
skillsSourceDir: () => skillsSourceDir,
|
|
23195
23428
|
uninstallSkills: () => uninstallSkills
|
|
23196
23429
|
});
|
|
23197
|
-
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";
|
|
23198
23431
|
import { createHash as createHash12 } from "crypto";
|
|
23199
|
-
import { join as
|
|
23432
|
+
import { join as join53, basename as basename23 } from "path";
|
|
23200
23433
|
function skillsSourceDir() {
|
|
23201
|
-
return
|
|
23434
|
+
return join53(import.meta.dirname, "..", "skills");
|
|
23202
23435
|
}
|
|
23203
23436
|
function version() {
|
|
23204
23437
|
try {
|
|
23205
|
-
return JSON.parse(
|
|
23438
|
+
return JSON.parse(readFileSync43(new URL("../package.json", import.meta.url), "utf-8")).version || "0.0.0";
|
|
23206
23439
|
} catch {
|
|
23207
23440
|
return "0.0.0";
|
|
23208
23441
|
}
|
|
@@ -23211,9 +23444,9 @@ function skillsFingerprint() {
|
|
|
23211
23444
|
const src = skillsSourceDir();
|
|
23212
23445
|
const h = createHash12("sha256");
|
|
23213
23446
|
for (const name of bundledSkillNames()) {
|
|
23214
|
-
for (const rel of filesUnder(
|
|
23447
|
+
for (const rel of filesUnder(join53(src, name)).sort()) {
|
|
23215
23448
|
h.update(name + "/" + rel);
|
|
23216
|
-
h.update(
|
|
23449
|
+
h.update(readFileSync43(join53(src, name, rel)));
|
|
23217
23450
|
}
|
|
23218
23451
|
}
|
|
23219
23452
|
return h.digest("hex").slice(0, 12);
|
|
@@ -23223,7 +23456,7 @@ function filesUnder(dir, prefix = "") {
|
|
|
23223
23456
|
for (const e of readdirSync33(dir, { withFileTypes: true })) {
|
|
23224
23457
|
if (e.name === MARKER) continue;
|
|
23225
23458
|
const rel = prefix ? `${prefix}/${e.name}` : e.name;
|
|
23226
|
-
if (e.isDirectory()) out.push(...filesUnder(
|
|
23459
|
+
if (e.isDirectory()) out.push(...filesUnder(join53(dir, e.name), rel));
|
|
23227
23460
|
else out.push(rel);
|
|
23228
23461
|
}
|
|
23229
23462
|
return out;
|
|
@@ -23234,7 +23467,7 @@ function skillStamp() {
|
|
|
23234
23467
|
function bundledSkillNames() {
|
|
23235
23468
|
const src = skillsSourceDir();
|
|
23236
23469
|
if (!existsSync47(src)) return [];
|
|
23237
|
-
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();
|
|
23238
23471
|
}
|
|
23239
23472
|
function realPathOrSelf(p) {
|
|
23240
23473
|
try {
|
|
@@ -23247,7 +23480,7 @@ function claudeSkillTargets() {
|
|
|
23247
23480
|
const targets = [];
|
|
23248
23481
|
const seen = /* @__PURE__ */ new Set();
|
|
23249
23482
|
for (const home of claudeHomeDirs()) {
|
|
23250
|
-
const dir =
|
|
23483
|
+
const dir = join53(home, "skills");
|
|
23251
23484
|
const key2 = realPathOrSelf(dir);
|
|
23252
23485
|
if (seen.has(key2)) continue;
|
|
23253
23486
|
seen.add(key2);
|
|
@@ -23258,7 +23491,7 @@ function claudeSkillTargets() {
|
|
|
23258
23491
|
dir,
|
|
23259
23492
|
// Judge each profile on ITS OWN transcripts, not the primary's: a home
|
|
23260
23493
|
// with no projects/ is a directory someone made, not a Claude install.
|
|
23261
|
-
available: existsSync47(
|
|
23494
|
+
available: existsSync47(join53(home, "projects"))
|
|
23262
23495
|
});
|
|
23263
23496
|
}
|
|
23264
23497
|
if (targets.length === 0) {
|
|
@@ -23273,16 +23506,16 @@ function skillTargets() {
|
|
|
23273
23506
|
// both produces "skill conflict" duplicate warnings. Every tool we support
|
|
23274
23507
|
// has its own dir, so per-tool coverage is complete.
|
|
23275
23508
|
...claudeSkillTargets(),
|
|
23276
|
-
{ id: "agy", label: "Antigravity", dir:
|
|
23509
|
+
{ id: "agy", label: "Antigravity", dir: join53(agyBackend.homeDir(), "skills"), available: agyBackend.isAvailable() },
|
|
23277
23510
|
{ id: "codex", label: "Codex", dir: codexBackend.skillsDir(), available: codexBackend.isAvailable() },
|
|
23278
23511
|
{ id: "opencode", label: "OpenCode", dir: opencodeBackend.skillsDir(), available: opencodeBackend.isAvailable() },
|
|
23279
23512
|
// Cursor DOES have its own dir (~/.cursor/skills). `skills-cursor` next to
|
|
23280
23513
|
// it is Cursor's bundled set — read-only, never an install target.
|
|
23281
|
-
{ id: "cursor", label: "Cursor", dir:
|
|
23514
|
+
{ id: "cursor", label: "Cursor", dir: join53(cursorHomeDir(), "skills"), available: cursorBackend.isAvailable() }
|
|
23282
23515
|
];
|
|
23283
23516
|
}
|
|
23284
23517
|
function isManaged(dir) {
|
|
23285
|
-
return existsSync47(
|
|
23518
|
+
return existsSync47(join53(dir, MARKER));
|
|
23286
23519
|
}
|
|
23287
23520
|
function installSkills(opts = {}) {
|
|
23288
23521
|
const onlyAvailable = opts.onlyAvailable ?? true;
|
|
@@ -23299,15 +23532,15 @@ function installSkills(opts = {}) {
|
|
|
23299
23532
|
continue;
|
|
23300
23533
|
}
|
|
23301
23534
|
for (const name of names) {
|
|
23302
|
-
const dest =
|
|
23535
|
+
const dest = join53(t.dir, name);
|
|
23303
23536
|
if (existsSync47(dest) && !isManaged(dest)) {
|
|
23304
23537
|
skippedUserOwned.push(name);
|
|
23305
23538
|
continue;
|
|
23306
23539
|
}
|
|
23307
23540
|
mkdirSync15(t.dir, { recursive: true });
|
|
23308
|
-
|
|
23309
|
-
cpSync(
|
|
23310
|
-
writeFileSync13(
|
|
23541
|
+
rmSync9(dest, { recursive: true, force: true });
|
|
23542
|
+
cpSync(join53(src, name), dest, { recursive: true });
|
|
23543
|
+
writeFileSync13(join53(dest, MARKER), `${stamp}
|
|
23311
23544
|
`);
|
|
23312
23545
|
installed.push(name);
|
|
23313
23546
|
}
|
|
@@ -23326,9 +23559,9 @@ function uninstallSkills() {
|
|
|
23326
23559
|
}
|
|
23327
23560
|
for (const entry of readdirSync33(t.dir, { withFileTypes: true })) {
|
|
23328
23561
|
if (!entry.isDirectory()) continue;
|
|
23329
|
-
const dir =
|
|
23562
|
+
const dir = join53(t.dir, entry.name);
|
|
23330
23563
|
if (isManaged(dir) && (names.has(entry.name) || entry.name.startsWith("chat-recall"))) {
|
|
23331
|
-
|
|
23564
|
+
rmSync9(dir, { recursive: true, force: true });
|
|
23332
23565
|
removed.push(entry.name);
|
|
23333
23566
|
}
|
|
23334
23567
|
}
|
|
@@ -23343,10 +23576,10 @@ function skillsNeedRefresh() {
|
|
|
23343
23576
|
for (const t of skillTargets()) {
|
|
23344
23577
|
if (!t.available) continue;
|
|
23345
23578
|
for (const name of names) {
|
|
23346
|
-
const marker =
|
|
23579
|
+
const marker = join53(t.dir, name, MARKER);
|
|
23347
23580
|
if (!existsSync47(marker)) return true;
|
|
23348
23581
|
try {
|
|
23349
|
-
if (
|
|
23582
|
+
if (readFileSync43(marker, "utf-8").trim() !== cur) return true;
|
|
23350
23583
|
} catch {
|
|
23351
23584
|
return true;
|
|
23352
23585
|
}
|
|
@@ -23361,11 +23594,11 @@ function skillStatus() {
|
|
|
23361
23594
|
let installed = 0;
|
|
23362
23595
|
let ver = null;
|
|
23363
23596
|
for (const name of names) {
|
|
23364
|
-
const marker =
|
|
23597
|
+
const marker = join53(t.dir, name, MARKER);
|
|
23365
23598
|
if (existsSync47(marker)) {
|
|
23366
23599
|
installed++;
|
|
23367
23600
|
try {
|
|
23368
|
-
ver =
|
|
23601
|
+
ver = readFileSync43(marker, "utf-8").trim();
|
|
23369
23602
|
} catch {
|
|
23370
23603
|
}
|
|
23371
23604
|
}
|
|
@@ -29460,9 +29693,9 @@ function openBrowser(url) {
|
|
|
29460
29693
|
// src/mcp.ts
|
|
29461
29694
|
init_client_events();
|
|
29462
29695
|
init_update_notice();
|
|
29463
|
-
import { readFileSync as
|
|
29696
|
+
import { readFileSync as readFileSync44 } from "node:fs";
|
|
29464
29697
|
setServerVersion(JSON.parse(
|
|
29465
|
-
|
|
29698
|
+
readFileSync44(new URL("../package.json", import.meta.url), "utf-8")
|
|
29466
29699
|
).version);
|
|
29467
29700
|
setEventReporter(reportClientEvent2);
|
|
29468
29701
|
setIndexRunner(runIndexChild2);
|
|
@@ -29579,9 +29812,9 @@ var SYNC_TICK_MS = 3 * 6e4;
|
|
|
29579
29812
|
function startBackgroundSync() {
|
|
29580
29813
|
const tick = async (scope) => {
|
|
29581
29814
|
try {
|
|
29582
|
-
const { installedVersion:
|
|
29815
|
+
const { installedVersion: installedVersion3 } = await Promise.resolve().then(() => (init_auto_update(), auto_update_exports));
|
|
29583
29816
|
const { installedIsNewer: installedIsNewer2, runInstalledSync: runInstalledSync2 } = await Promise.resolve().then(() => (init_sync_delegate(), sync_delegate_exports));
|
|
29584
|
-
const installed =
|
|
29817
|
+
const installed = installedVersion3();
|
|
29585
29818
|
if (installedIsNewer2(RELAY_VERSION, installed)) {
|
|
29586
29819
|
const code = await runInstalledSync2(fileURLToPath5(new URL("./cli.js", import.meta.url)));
|
|
29587
29820
|
if (code !== 0) console.error(`[mcp] sync by the installed CLI ${installed} ended with ${code ?? "no exit code"}`);
|
|
@@ -29635,7 +29868,7 @@ function installCrashGuards() {
|
|
|
29635
29868
|
reportClientEvent2("mcp_crash", { message: err.stack || err.message });
|
|
29636
29869
|
});
|
|
29637
29870
|
}
|
|
29638
|
-
var RELAY_VERSION = true ? "0.7.
|
|
29871
|
+
var RELAY_VERSION = true ? "0.7.18" : "0.0.0";
|
|
29639
29872
|
function daemonIdleSecs() {
|
|
29640
29873
|
const raw = process.env.CHAT_RECALL_DAEMON_IDLE_SECS;
|
|
29641
29874
|
if (raw === void 0) return 900;
|
|
@@ -29731,8 +29964,25 @@ async function runDaemon() {
|
|
|
29731
29964
|
};
|
|
29732
29965
|
process.on("SIGTERM", shutdown);
|
|
29733
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();
|
|
29734
29976
|
return true;
|
|
29735
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
|
+
}
|
|
29736
29986
|
async function main() {
|
|
29737
29987
|
installCrashGuards();
|
|
29738
29988
|
if (process.argv.includes("--daemon")) {
|