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/cli.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: join63 } = __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"] || join63(__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: join63, isAbsolute: isAbsolute4, sep: sep4 } = __require("node:path");
|
|
2484
2484
|
var sleep2 = 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"] || join63(__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"] || join63(__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 join63(__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 join63 = ",";
|
|
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
|
+
join63 = `,
|
|
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 += join63;
|
|
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 += `${join63}"... ${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
|
+
join63 = `,
|
|
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 = join63;
|
|
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 = join63;
|
|
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 join63 = ",";
|
|
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
|
+
join63 = `,
|
|
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 += join63;
|
|
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 += `${join63}"... ${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
|
+
join63 = `,
|
|
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 = join63;
|
|
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 join64 = `,
|
|
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 += join64;
|
|
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 += `${join64}"... ${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 join63 = `,
|
|
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, join63, maximumBreadth);
|
|
3828
3828
|
keys = keys.slice(value.length);
|
|
3829
3829
|
maximumPropertiesToStringify -= value.length;
|
|
3830
|
-
separator =
|
|
3830
|
+
separator = join63;
|
|
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 = join63;
|
|
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 = join63;
|
|
3848
3848
|
}
|
|
3849
3849
|
if (separator !== "") {
|
|
3850
3850
|
res = `
|
|
@@ -6617,6 +6617,7 @@ var init_from_events = __esm({
|
|
|
6617
6617
|
// ../engine/dist/transcript/raw.js
|
|
6618
6618
|
var raw_exports = {};
|
|
6619
6619
|
__export(raw_exports, {
|
|
6620
|
+
RAW_PARSE_MAX_BYTES: () => RAW_PARSE_MAX_BYTES,
|
|
6620
6621
|
archiveRawSession: () => archiveRawSession,
|
|
6621
6622
|
buildRawContainer: () => buildRawContainer,
|
|
6622
6623
|
containerSrcHash: () => containerSrcHash,
|
|
@@ -6916,11 +6917,11 @@ async function archiveRawSession(store, sessionId) {
|
|
|
6916
6917
|
return await store.putRawSession(sessionId, exp.tool, Math.floor(exp.mtime), gz, size);
|
|
6917
6918
|
}
|
|
6918
6919
|
function detectForkPredecessor(sessionPath) {
|
|
6919
|
-
const { readFileSync:
|
|
6920
|
-
const { dirname: dirname30, join:
|
|
6920
|
+
const { readFileSync: readFileSync51, readdirSync: readdirSync34 } = requireFs();
|
|
6921
|
+
const { dirname: dirname30, join: join63, basename: basename28 } = requirePath();
|
|
6921
6922
|
let text;
|
|
6922
6923
|
try {
|
|
6923
|
-
text =
|
|
6924
|
+
text = readFileSync51(sessionPath, "utf-8");
|
|
6924
6925
|
} catch {
|
|
6925
6926
|
return null;
|
|
6926
6927
|
}
|
|
@@ -6954,7 +6955,7 @@ function detectForkPredecessor(sessionPath) {
|
|
|
6954
6955
|
if (!f.endsWith(".jsonl") || f === self || f === "sessions-index.json")
|
|
6955
6956
|
continue;
|
|
6956
6957
|
try {
|
|
6957
|
-
if (
|
|
6958
|
+
if (readFileSync51(join63(dir, f), "utf-8").includes(`"uuid":"${headParent}"`)) {
|
|
6958
6959
|
return basename28(f, ".jsonl");
|
|
6959
6960
|
}
|
|
6960
6961
|
} catch {
|
|
@@ -6968,7 +6969,7 @@ function requireFs() {
|
|
|
6968
6969
|
function requirePath() {
|
|
6969
6970
|
return pathMod;
|
|
6970
6971
|
}
|
|
6971
|
-
var MARKER_QUOTE;
|
|
6972
|
+
var RAW_PARSE_MAX_BYTES, MARKER_QUOTE;
|
|
6972
6973
|
var init_raw = __esm({
|
|
6973
6974
|
"../engine/dist/transcript/raw.js"() {
|
|
6974
6975
|
"use strict";
|
|
@@ -6976,6 +6977,7 @@ var init_raw = __esm({
|
|
|
6976
6977
|
init_claude();
|
|
6977
6978
|
init_codex();
|
|
6978
6979
|
init_from_events();
|
|
6980
|
+
RAW_PARSE_MAX_BYTES = 40 * 1024 * 1024;
|
|
6979
6981
|
MARKER_QUOTE = /\[REDACTED:[A-Za-z0-9_-]+\]"/g;
|
|
6980
6982
|
}
|
|
6981
6983
|
});
|
|
@@ -14360,6 +14362,7 @@ var init_opencode2 = __esm({
|
|
|
14360
14362
|
// ../engine/dist/transcript/index.js
|
|
14361
14363
|
var transcript_exports = {};
|
|
14362
14364
|
__export(transcript_exports, {
|
|
14365
|
+
RAW_PARSE_MAX_BYTES: () => RAW_PARSE_MAX_BYTES,
|
|
14363
14366
|
TRANSCRIPT_VERSION: () => TRANSCRIPT_VERSION,
|
|
14364
14367
|
archiveRawSession: () => archiveRawSession,
|
|
14365
14368
|
buildRawContainer: () => buildRawContainer,
|
|
@@ -18820,6 +18823,11 @@ function markSynced(server, rows) {
|
|
|
18820
18823
|
base4.s = s;
|
|
18821
18824
|
}
|
|
18822
18825
|
if (r.hash !== void 0) base4.h = r.hash;
|
|
18826
|
+
const completesChunked = cursorFromCaller && r.chunkFinal === true && prev?.k === 1;
|
|
18827
|
+
if (cursorFromCaller && (r.full || completesChunked) && o > 0) base4.F = o;
|
|
18828
|
+
else if (prev?.F !== void 0) base4.F = prev.F;
|
|
18829
|
+
if (cursorFromCaller && r.chunkedHead) base4.k = 1;
|
|
18830
|
+
else if (prev?.k && !completesChunked && !(cursorFromCaller && r.full)) base4.k = 1;
|
|
18823
18831
|
forServer[r.id] = base4;
|
|
18824
18832
|
}
|
|
18825
18833
|
persist(data);
|
|
@@ -18876,6 +18884,14 @@ function markFieldFullPassDone(server, field) {
|
|
|
18876
18884
|
delete st.force[field.name];
|
|
18877
18885
|
persistReconcile(data);
|
|
18878
18886
|
}
|
|
18887
|
+
function forgetFullCoverage(server, sessionId) {
|
|
18888
|
+
const data = load();
|
|
18889
|
+
const row = data[server]?.[sessionId];
|
|
18890
|
+
if (!row || typeof row !== "object") return;
|
|
18891
|
+
delete row.F;
|
|
18892
|
+
delete row.h;
|
|
18893
|
+
persist(data);
|
|
18894
|
+
}
|
|
18879
18895
|
function markFullResync(server, sessionId) {
|
|
18880
18896
|
const data = load();
|
|
18881
18897
|
const forServer = data[server];
|
|
@@ -18884,7 +18900,11 @@ function markFullResync(server, sessionId) {
|
|
|
18884
18900
|
delete forServer[sessionId];
|
|
18885
18901
|
persist(data);
|
|
18886
18902
|
}
|
|
18887
|
-
function
|
|
18903
|
+
function fullCoveredOffset(row) {
|
|
18904
|
+
if (row.F !== void 0) return row.F;
|
|
18905
|
+
return row.h ? row.s ?? 0 : 0;
|
|
18906
|
+
}
|
|
18907
|
+
function syncMode(row, mtime, fileSize, extractorVersion, isAppendOnly, nowMs = Date.now()) {
|
|
18888
18908
|
if (!row) return "full";
|
|
18889
18909
|
if (row.v < extractorVersion) return "full";
|
|
18890
18910
|
const offset = row.o ?? 0;
|
|
@@ -18892,10 +18912,13 @@ function syncMode(row, mtime, fileSize, extractorVersion, isAppendOnly) {
|
|
|
18892
18912
|
if (process.env.CHAT_RECALL_TAIL_APPEND !== "0" && isAppendOnly && fileSize > 0 && offset > 0 && fileSize > (row.s ?? 0)) {
|
|
18893
18913
|
return "append";
|
|
18894
18914
|
}
|
|
18915
|
+
if (isAppendOnly && offset > 0 && fileSize > 0 && fileSize === (row.s ?? 0) && !row.k && fullCoveredOffset(row) < offset && nowMs - Math.floor(mtime) >= SETTLE_QUIET_MS) {
|
|
18916
|
+
return "full";
|
|
18917
|
+
}
|
|
18895
18918
|
if (row.m >= Math.floor(mtime)) return "skip";
|
|
18896
18919
|
return "full";
|
|
18897
18920
|
}
|
|
18898
|
-
var ledgerPath, cache3, base, diskStamp, rowKey, LEDGER_FLUSH_MS, pendingWrite, flushTimer, itemVersionsPath, itemVersionsCache, inventoryPath, unackedCursorAttempts, reconcilePath, reconcileCache;
|
|
18921
|
+
var ledgerPath, cache3, base, diskStamp, rowKey, LEDGER_FLUSH_MS, pendingWrite, flushTimer, itemVersionsPath, itemVersionsCache, inventoryPath, unackedCursorAttempts, reconcilePath, reconcileCache, SETTLE_QUIET_MS;
|
|
18899
18922
|
var init_sync_ledger = __esm({
|
|
18900
18923
|
"src/sync-ledger.ts"() {
|
|
18901
18924
|
"use strict";
|
|
@@ -18915,6 +18938,7 @@ var init_sync_ledger = __esm({
|
|
|
18915
18938
|
unackedCursorAttempts = 0;
|
|
18916
18939
|
reconcilePath = () => join38(getDataDir(), "sync-field-reconcile.json");
|
|
18917
18940
|
reconcileCache = null;
|
|
18941
|
+
SETTLE_QUIET_MS = 2 * 60 * 60 * 1e3;
|
|
18918
18942
|
}
|
|
18919
18943
|
});
|
|
18920
18944
|
|
|
@@ -19066,7 +19090,7 @@ var init_http = __esm({
|
|
|
19066
19090
|
CLI_VERSION = JSON.parse(readFileSync31(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
|
|
19067
19091
|
} catch {
|
|
19068
19092
|
try {
|
|
19069
|
-
if (true) CLI_VERSION = "0.7.
|
|
19093
|
+
if (true) CLI_VERSION = "0.7.18";
|
|
19070
19094
|
} catch {
|
|
19071
19095
|
}
|
|
19072
19096
|
}
|
|
@@ -19564,7 +19588,7 @@ var init_telemetry = __esm({
|
|
|
19564
19588
|
init_sync_client();
|
|
19565
19589
|
cliVersion2 = () => {
|
|
19566
19590
|
try {
|
|
19567
|
-
return true ? "0.7.
|
|
19591
|
+
return true ? "0.7.18" : "dev";
|
|
19568
19592
|
} catch {
|
|
19569
19593
|
return "dev";
|
|
19570
19594
|
}
|
|
@@ -19727,6 +19751,150 @@ var init_collector_health = __esm({
|
|
|
19727
19751
|
}
|
|
19728
19752
|
});
|
|
19729
19753
|
|
|
19754
|
+
// src/raw-archive-parts.ts
|
|
19755
|
+
import { createReadStream as createReadStream4, createWriteStream, openSync as openSync9, readSync as readSync8, closeSync as closeSync9, rmSync as rmSync5, statSync as statSync37 } from "node:fs";
|
|
19756
|
+
import { tmpdir as tmpdir2 } from "node:os";
|
|
19757
|
+
import { join as join41 } from "node:path";
|
|
19758
|
+
import { randomBytes } from "node:crypto";
|
|
19759
|
+
import { createGzip } from "node:zlib";
|
|
19760
|
+
import { once } from "node:events";
|
|
19761
|
+
import { readFileSync as readFileSync33 } from "node:fs";
|
|
19762
|
+
async function* fileLines(path) {
|
|
19763
|
+
let rest = "";
|
|
19764
|
+
const decoder = new TextDecoder("utf-8");
|
|
19765
|
+
for await (const chunk of createReadStream4(path, { highWaterMark: 1024 * 1024 })) {
|
|
19766
|
+
rest += decoder.decode(chunk, { stream: true });
|
|
19767
|
+
let nl = rest.indexOf("\n");
|
|
19768
|
+
while (nl >= 0) {
|
|
19769
|
+
yield rest.slice(0, nl + 1);
|
|
19770
|
+
rest = rest.slice(nl + 1);
|
|
19771
|
+
nl = rest.indexOf("\n");
|
|
19772
|
+
}
|
|
19773
|
+
}
|
|
19774
|
+
rest += decoder.decode();
|
|
19775
|
+
if (rest) yield rest;
|
|
19776
|
+
}
|
|
19777
|
+
function* textLines(text) {
|
|
19778
|
+
let at = 0;
|
|
19779
|
+
while (at < text.length) {
|
|
19780
|
+
const nl = text.indexOf("\n", at);
|
|
19781
|
+
const end = nl < 0 ? text.length : nl + 1;
|
|
19782
|
+
yield text.slice(at, end);
|
|
19783
|
+
at = end;
|
|
19784
|
+
}
|
|
19785
|
+
}
|
|
19786
|
+
async function writeArchiveFile(source, meta, redact, dir = tmpdir2()) {
|
|
19787
|
+
const path = join41(dir, `cr-archive-${randomBytes(8).toString("hex")}.json.gz`);
|
|
19788
|
+
const gzip = createGzip({ level: 6 });
|
|
19789
|
+
const out = createWriteStream(path, { mode: 384 });
|
|
19790
|
+
const done = once(out, "finish");
|
|
19791
|
+
gzip.pipe(out);
|
|
19792
|
+
let size = 0;
|
|
19793
|
+
const write = async (s) => {
|
|
19794
|
+
size += Buffer.byteLength(s);
|
|
19795
|
+
if (!gzip.write(s)) await once(gzip, "drain");
|
|
19796
|
+
};
|
|
19797
|
+
try {
|
|
19798
|
+
await write(`{"v":1,"tool":${JSON.stringify(meta.tool)},"mtime":${Math.floor(meta.mtime)},"files":[`);
|
|
19799
|
+
for (const [i, f] of source.files.entries()) {
|
|
19800
|
+
await write(`${i ? "," : ""}{"name":${JSON.stringify(f.name)},"text":"`);
|
|
19801
|
+
const whole = () => source.kind === "memory" ? f.text : readFileSync33(f.path, "utf-8");
|
|
19802
|
+
if (!f.name.endsWith(".jsonl")) {
|
|
19803
|
+
await write(escapeJson(redact(whole())));
|
|
19804
|
+
} else {
|
|
19805
|
+
const lines = source.kind === "memory" ? textLines(f.text) : fileLines(f.path);
|
|
19806
|
+
for await (const line of lines) {
|
|
19807
|
+
const nl = line.endsWith("\n");
|
|
19808
|
+
const body2 = nl ? line.slice(0, -1) : line;
|
|
19809
|
+
await write(escapeJson((body2 ? redactJsonLine(body2, redact) : body2) + (nl ? "\n" : "")));
|
|
19810
|
+
}
|
|
19811
|
+
}
|
|
19812
|
+
await write('"}');
|
|
19813
|
+
}
|
|
19814
|
+
await write("]}");
|
|
19815
|
+
gzip.end();
|
|
19816
|
+
await done;
|
|
19817
|
+
} catch (err) {
|
|
19818
|
+
gzip.destroy();
|
|
19819
|
+
out.destroy();
|
|
19820
|
+
rmSync5(path, { force: true });
|
|
19821
|
+
throw err;
|
|
19822
|
+
}
|
|
19823
|
+
return { path, gzSize: statSync37(path).size, size };
|
|
19824
|
+
}
|
|
19825
|
+
async function putPart(url, body2) {
|
|
19826
|
+
let last;
|
|
19827
|
+
for (let attempt = 1; attempt <= PART_ATTEMPTS; attempt++) {
|
|
19828
|
+
const ac = new AbortController();
|
|
19829
|
+
const timer = setTimeout(() => ac.abort(), PART_TIMEOUT_MS);
|
|
19830
|
+
try {
|
|
19831
|
+
const r = await fetch(url, { method: "PUT", body: body2, signal: ac.signal });
|
|
19832
|
+
const etag = r.headers.get("etag");
|
|
19833
|
+
if (r.ok && etag) return etag;
|
|
19834
|
+
last = new Error(`part PUT answered ${r.status}`);
|
|
19835
|
+
if (r.status === 403 || r.status === 404) break;
|
|
19836
|
+
} catch (err) {
|
|
19837
|
+
last = err;
|
|
19838
|
+
} finally {
|
|
19839
|
+
clearTimeout(timer);
|
|
19840
|
+
}
|
|
19841
|
+
}
|
|
19842
|
+
throw last instanceof Error ? last : new Error(String(last));
|
|
19843
|
+
}
|
|
19844
|
+
async function uploadArchiveFile(base4, token, args) {
|
|
19845
|
+
const headers = { "content-type": "application/json" };
|
|
19846
|
+
if (token) headers.authorization = `Bearer ${token}`;
|
|
19847
|
+
const post = async (path, body2) => {
|
|
19848
|
+
const r = await fetch(`${base4}/api/sync/raw-upload/${path}`, { method: "POST", headers, body: JSON.stringify(body2) });
|
|
19849
|
+
const json = await r.json().catch(() => ({}));
|
|
19850
|
+
return { status: r.status, json };
|
|
19851
|
+
};
|
|
19852
|
+
const start = await post("start", {
|
|
19853
|
+
session_id: args.sessionId,
|
|
19854
|
+
tool: args.tool,
|
|
19855
|
+
mtime: Math.floor(args.mtime),
|
|
19856
|
+
size: args.file.size,
|
|
19857
|
+
gz_size: args.file.gzSize,
|
|
19858
|
+
project_id: args.projectId,
|
|
19859
|
+
project_path: args.projectPath
|
|
19860
|
+
});
|
|
19861
|
+
if (start.status === 501 || start.status === 404) return "unsupported";
|
|
19862
|
+
if (start.status !== 200) throw new Error(`raw upload start answered ${start.status}: ${start.json.error ?? ""}`);
|
|
19863
|
+
if (start.json.result === "unchanged" || start.json.result === "shrink-protected") return start.json.result;
|
|
19864
|
+
const urls = start.json.urls;
|
|
19865
|
+
const partBytes = Number(start.json.part_bytes);
|
|
19866
|
+
const parts = [];
|
|
19867
|
+
const fd = openSync9(args.file.path, "r");
|
|
19868
|
+
try {
|
|
19869
|
+
for (const [i, url] of urls.entries()) {
|
|
19870
|
+
const len = Math.min(partBytes, args.file.gzSize - i * partBytes);
|
|
19871
|
+
const buf = Buffer.allocUnsafe(len);
|
|
19872
|
+
let got = 0;
|
|
19873
|
+
while (got < len) {
|
|
19874
|
+
const n = readSync8(fd, buf, got, len - got, i * partBytes + got);
|
|
19875
|
+
if (n <= 0) break;
|
|
19876
|
+
got += n;
|
|
19877
|
+
}
|
|
19878
|
+
parts.push({ part_number: i + 1, etag: await putPart(url, buf.subarray(0, got)) });
|
|
19879
|
+
}
|
|
19880
|
+
} finally {
|
|
19881
|
+
closeSync9(fd);
|
|
19882
|
+
}
|
|
19883
|
+
const done = await post("complete", { session_id: args.sessionId, upload_id: start.json.upload_id, parts });
|
|
19884
|
+
if (done.status !== 200) throw new Error(`raw upload complete answered ${done.status}: ${done.json.error ?? ""}`);
|
|
19885
|
+
return done.json.result;
|
|
19886
|
+
}
|
|
19887
|
+
var escapeJson, PART_TIMEOUT_MS, PART_ATTEMPTS;
|
|
19888
|
+
var init_raw_archive_parts = __esm({
|
|
19889
|
+
"src/raw-archive-parts.ts"() {
|
|
19890
|
+
"use strict";
|
|
19891
|
+
init_transcript();
|
|
19892
|
+
escapeJson = (s) => JSON.stringify(s).slice(1, -1);
|
|
19893
|
+
PART_TIMEOUT_MS = 12e4;
|
|
19894
|
+
PART_ATTEMPTS = 3;
|
|
19895
|
+
}
|
|
19896
|
+
});
|
|
19897
|
+
|
|
19730
19898
|
// src/server-probe.ts
|
|
19731
19899
|
var server_probe_exports = {};
|
|
19732
19900
|
__export(server_probe_exports, {
|
|
@@ -19870,7 +20038,7 @@ __export(client_events_exports, {
|
|
|
19870
20038
|
isTelemetryEnabled: () => isTelemetryEnabled,
|
|
19871
20039
|
reportClientEvent: () => reportClientEvent
|
|
19872
20040
|
});
|
|
19873
|
-
import { readFileSync as
|
|
20041
|
+
import { readFileSync as readFileSync34 } from "node:fs";
|
|
19874
20042
|
function scrub(msg) {
|
|
19875
20043
|
if (!msg) return "";
|
|
19876
20044
|
const noHome = msg.replace(/\/(?:home|Users)\/[^/\s]+/g, "~");
|
|
@@ -19923,7 +20091,7 @@ var init_client_events = __esm({
|
|
|
19923
20091
|
init_secret_redactor();
|
|
19924
20092
|
CLI_VERSION2 = "0.0.0";
|
|
19925
20093
|
try {
|
|
19926
|
-
CLI_VERSION2 = JSON.parse(
|
|
20094
|
+
CLI_VERSION2 = JSON.parse(readFileSync34(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION2;
|
|
19927
20095
|
} catch {
|
|
19928
20096
|
}
|
|
19929
20097
|
}
|
|
@@ -19953,11 +20121,11 @@ __export(auto_update_exports, {
|
|
|
19953
20121
|
tarballUrl: () => tarballUrl
|
|
19954
20122
|
});
|
|
19955
20123
|
import { execSync as execSync2, execFileSync as execFileSync3 } from "node:child_process";
|
|
19956
|
-
import { readFileSync as
|
|
20124
|
+
import { readFileSync as readFileSync35, existsSync as existsSync41 } from "node:fs";
|
|
19957
20125
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
19958
|
-
import { writeFileSync as writeFileSync8, mkdtempSync as mkdtempSync3, rmSync as
|
|
19959
|
-
import { join as
|
|
19960
|
-
import { tmpdir as
|
|
20126
|
+
import { writeFileSync as writeFileSync8, mkdtempSync as mkdtempSync3, rmSync as rmSync6, readdirSync as readdirSync30, statSync as statSync38, mkdirSync as mkdirSync9 } from "node:fs";
|
|
20127
|
+
import { join as join42, dirname as dirname18, sep as sep2, posix as pathPosix, win32 as pathWin32 } from "node:path";
|
|
20128
|
+
import { tmpdir as tmpdir3, homedir as homedir15 } from "node:os";
|
|
19961
20129
|
import { createHash as createHash8 } from "node:crypto";
|
|
19962
20130
|
function compareVersions(a, b) {
|
|
19963
20131
|
const pa = String(a).split("-")[0].split(".").map((n) => parseInt(n, 10) || 0);
|
|
@@ -19981,7 +20149,7 @@ function newerOf(a, b) {
|
|
|
19981
20149
|
function installedVersion() {
|
|
19982
20150
|
try {
|
|
19983
20151
|
const here = dirname18(fileURLToPath2(import.meta.url));
|
|
19984
|
-
const raw =
|
|
20152
|
+
const raw = readFileSync35(join42(here, "..", "package.json"), "utf-8");
|
|
19985
20153
|
return JSON.parse(raw).version || null;
|
|
19986
20154
|
} catch {
|
|
19987
20155
|
return null;
|
|
@@ -19994,7 +20162,7 @@ function planAutoUpdate(base4, caps, ownVersion3, flag) {
|
|
|
19994
20162
|
if (compareVersions(rel.version, ownVersion3) <= 0) return { update: false, reason: `already current (own ${ownVersion3} >= server ${rel.version})` };
|
|
19995
20163
|
return { update: true, reason: `server ${rel.version} > own ${ownVersion3}`, url: tarballUrl(base4, rel.version), fallbackUrl: tarballUrl(base4), sha256: rel.sha256, from: ownVersion3, to: rel.version };
|
|
19996
20164
|
}
|
|
19997
|
-
function sweepStaleStaging(root =
|
|
20165
|
+
function sweepStaleStaging(root = tmpdir3(), now = Date.now()) {
|
|
19998
20166
|
const MKDTEMP_SUFFIX = /^cr-update-.{6}$/s;
|
|
19999
20167
|
const COLD_MS = 60 * 60 * 1e3;
|
|
20000
20168
|
let removed = 0;
|
|
@@ -20006,13 +20174,13 @@ function sweepStaleStaging(root = tmpdir2(), now = Date.now()) {
|
|
|
20006
20174
|
}
|
|
20007
20175
|
for (const name of entries) {
|
|
20008
20176
|
if (!MKDTEMP_SUFFIX.test(name)) continue;
|
|
20009
|
-
const dir =
|
|
20177
|
+
const dir = join42(root, name);
|
|
20010
20178
|
try {
|
|
20011
|
-
const st =
|
|
20179
|
+
const st = statSync38(dir);
|
|
20012
20180
|
if (!st.isDirectory() || now - st.mtimeMs < COLD_MS) continue;
|
|
20013
20181
|
const inside = readdirSync30(dir);
|
|
20014
20182
|
if (inside.length > 1 || inside.length === 1 && inside[0] !== "chat-recall.tgz") continue;
|
|
20015
|
-
|
|
20183
|
+
rmSync6(dir, { recursive: true, force: true });
|
|
20016
20184
|
removed++;
|
|
20017
20185
|
} catch {
|
|
20018
20186
|
}
|
|
@@ -20035,14 +20203,14 @@ async function executeAutoUpdate(plan, deps) {
|
|
|
20035
20203
|
}
|
|
20036
20204
|
const got = createHash8("sha256").update(buf).digest("hex");
|
|
20037
20205
|
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` };
|
|
20038
|
-
const dir = mkdtempSync3(
|
|
20206
|
+
const dir = mkdtempSync3(join42(tmpdir3(), "cr-update-"));
|
|
20039
20207
|
const discardStaging = () => {
|
|
20040
20208
|
try {
|
|
20041
|
-
|
|
20209
|
+
rmSync6(dir, { recursive: true, force: true });
|
|
20042
20210
|
} catch {
|
|
20043
20211
|
}
|
|
20044
20212
|
};
|
|
20045
|
-
const tgz =
|
|
20213
|
+
const tgz = join42(dir, "chat-recall.tgz");
|
|
20046
20214
|
writeFileSync8(tgz, buf);
|
|
20047
20215
|
if (deps.stopping?.()) {
|
|
20048
20216
|
discardStaging();
|
|
@@ -20122,7 +20290,7 @@ function realInstall(tgz) {
|
|
|
20122
20290
|
try {
|
|
20123
20291
|
npmInstall(npm, ["install", "-g", tgz]);
|
|
20124
20292
|
} catch {
|
|
20125
|
-
npmInstall(npm, ["install", "-g", "--prefix",
|
|
20293
|
+
npmInstall(npm, ["install", "-g", "--prefix", join42(homedir15(), ".local"), tgz]);
|
|
20126
20294
|
}
|
|
20127
20295
|
}
|
|
20128
20296
|
function acquireUpdateLock() {
|
|
@@ -20139,12 +20307,12 @@ function realRestart(platform2) {
|
|
|
20139
20307
|
if (c) execSync2(c.cmd, { stdio: "ignore", ...c.shell ? { shell: c.shell } : {} });
|
|
20140
20308
|
}
|
|
20141
20309
|
function updateStatePath() {
|
|
20142
|
-
const dir = process.env.CHAT_RECALL_DATA_DIR ||
|
|
20143
|
-
return
|
|
20310
|
+
const dir = process.env.CHAT_RECALL_DATA_DIR || join42(homedir15(), ".chat-recall");
|
|
20311
|
+
return join42(dir, "auto-update-state.json");
|
|
20144
20312
|
}
|
|
20145
20313
|
function readUpdateState() {
|
|
20146
20314
|
try {
|
|
20147
|
-
return JSON.parse(
|
|
20315
|
+
return JSON.parse(readFileSync35(updateStatePath(), "utf8"));
|
|
20148
20316
|
} catch {
|
|
20149
20317
|
return {};
|
|
20150
20318
|
}
|
|
@@ -20285,9 +20453,9 @@ __export(sync_client_exports, {
|
|
|
20285
20453
|
syncIncremental: () => syncIncremental,
|
|
20286
20454
|
syncSessions: () => syncSessions
|
|
20287
20455
|
});
|
|
20288
|
-
import { join as
|
|
20289
|
-
import { readFileSync as
|
|
20290
|
-
import { tmpdir as
|
|
20456
|
+
import { join as join43, dirname as dirname19, basename as basename20 } from "node:path";
|
|
20457
|
+
import { readFileSync as readFileSync36, writeFileSync as writeFileSync9, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync4, rmSync as rmSync7, chmodSync as chmodSync3, unlinkSync as unlinkSync2, readdirSync as readdirSync31, statSync as statSync39 } from "node:fs";
|
|
20458
|
+
import { tmpdir as tmpdir4, hostname as hostname2 } from "node:os";
|
|
20291
20459
|
import { createHash as createHash9 } from "node:crypto";
|
|
20292
20460
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
20293
20461
|
import { gzipSync as gzipSync3 } from "zlib";
|
|
@@ -20341,7 +20509,7 @@ function loadAllCredentials() {
|
|
|
20341
20509
|
const fromEnv = envCredentials();
|
|
20342
20510
|
if (fromEnv) return [{ serverUrl: fromEnv.serverUrl, token: fromEnv.token }];
|
|
20343
20511
|
try {
|
|
20344
|
-
const parsed = JSON.parse(
|
|
20512
|
+
const parsed = JSON.parse(readFileSync36(credPath(), "utf-8"));
|
|
20345
20513
|
if (Array.isArray(parsed?.targets)) return parsed.targets.filter((t) => t?.serverUrl).map((t) => ({ serverUrl: t.serverUrl, token: t.token || "" }));
|
|
20346
20514
|
if (parsed?.serverUrl) return [{ serverUrl: parsed.serverUrl, token: parsed.token || "" }];
|
|
20347
20515
|
} catch {
|
|
@@ -20403,11 +20571,11 @@ function _resetTenantSecurityConfigCache() {
|
|
|
20403
20571
|
_securityConfigCache.clear();
|
|
20404
20572
|
}
|
|
20405
20573
|
function syncConfigCachePath() {
|
|
20406
|
-
return
|
|
20574
|
+
return join43(getDataDir(), "sync-config-cache.json");
|
|
20407
20575
|
}
|
|
20408
20576
|
function readPersistedSyncConfigs() {
|
|
20409
20577
|
try {
|
|
20410
|
-
return JSON.parse(
|
|
20578
|
+
return JSON.parse(readFileSync36(syncConfigCachePath(), "utf-8"));
|
|
20411
20579
|
} catch {
|
|
20412
20580
|
return {};
|
|
20413
20581
|
}
|
|
@@ -20685,7 +20853,7 @@ async function reconcileFields(opts = {}) {
|
|
|
20685
20853
|
}
|
|
20686
20854
|
return { sessions: fullRefs().length, scanned, pushed, absent, perTarget };
|
|
20687
20855
|
}
|
|
20688
|
-
function reapStaleScanDirs(dir =
|
|
20856
|
+
function reapStaleScanDirs(dir = tmpdir4(), maxAgeMs = 6 * 36e5, now = Date.now()) {
|
|
20689
20857
|
let reaped = 0;
|
|
20690
20858
|
let names;
|
|
20691
20859
|
try {
|
|
@@ -20695,10 +20863,10 @@ function reapStaleScanDirs(dir = tmpdir3(), maxAgeMs = 6 * 36e5, now = Date.now(
|
|
|
20695
20863
|
}
|
|
20696
20864
|
for (const name of names) {
|
|
20697
20865
|
if (!name.startsWith("cr-batchscan-")) continue;
|
|
20698
|
-
const p =
|
|
20866
|
+
const p = join43(dir, name);
|
|
20699
20867
|
try {
|
|
20700
|
-
if (now -
|
|
20701
|
-
|
|
20868
|
+
if (now - statSync39(p).mtimeMs < maxAgeMs) continue;
|
|
20869
|
+
rmSync7(p, { recursive: true, force: true });
|
|
20702
20870
|
reaped++;
|
|
20703
20871
|
} catch {
|
|
20704
20872
|
}
|
|
@@ -20712,7 +20880,7 @@ function batchScanExternal(items, opts = {}) {
|
|
|
20712
20880
|
let scanned = 0, slices = 0, scanMs = 0;
|
|
20713
20881
|
if (items.length === 0) return { findings, scanned, slices, scanMs };
|
|
20714
20882
|
reapStaleScanDirs();
|
|
20715
|
-
let scanDir = mkdtempSync4(
|
|
20883
|
+
let scanDir = mkdtempSync4(join43(tmpdir4(), "cr-batchscan-"));
|
|
20716
20884
|
let safeToId = /* @__PURE__ */ new Map();
|
|
20717
20885
|
let bytesInDir = 0;
|
|
20718
20886
|
const flushSlice = () => {
|
|
@@ -20730,7 +20898,7 @@ function batchScanExternal(items, opts = {}) {
|
|
|
20730
20898
|
slices++;
|
|
20731
20899
|
}
|
|
20732
20900
|
try {
|
|
20733
|
-
|
|
20901
|
+
rmSync7(scanDir, { recursive: true, force: true });
|
|
20734
20902
|
} catch {
|
|
20735
20903
|
}
|
|
20736
20904
|
safeToId = /* @__PURE__ */ new Map();
|
|
@@ -20743,19 +20911,19 @@ function batchScanExternal(items, opts = {}) {
|
|
|
20743
20911
|
if (raw === null) continue;
|
|
20744
20912
|
const safe = item.id.replace(/[^A-Za-z0-9_-]/g, "");
|
|
20745
20913
|
safeToId.set(safe, item.id);
|
|
20746
|
-
writeFileSync9(
|
|
20914
|
+
writeFileSync9(join43(scanDir, `${safe}.txt`), raw);
|
|
20747
20915
|
bytesInDir += Buffer.byteLength(raw);
|
|
20748
20916
|
} catch {
|
|
20749
20917
|
}
|
|
20750
20918
|
if (bytesInDir >= maxBytes) {
|
|
20751
20919
|
flushSlice();
|
|
20752
|
-
scanDir = mkdtempSync4(
|
|
20920
|
+
scanDir = mkdtempSync4(join43(tmpdir4(), "cr-batchscan-"));
|
|
20753
20921
|
}
|
|
20754
20922
|
}
|
|
20755
20923
|
flushSlice();
|
|
20756
20924
|
} finally {
|
|
20757
20925
|
try {
|
|
20758
|
-
|
|
20926
|
+
rmSync7(scanDir, { recursive: true, force: true });
|
|
20759
20927
|
} catch {
|
|
20760
20928
|
}
|
|
20761
20929
|
}
|
|
@@ -20999,12 +21167,13 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20999
21167
|
markSynced(base4, rows.map((r) => {
|
|
21000
21168
|
const off = typeof r.from_offset === "number" ? r.from_offset : 0;
|
|
21001
21169
|
const hash = shippedHash.get(r.session_id);
|
|
21002
|
-
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 };
|
|
21170
|
+
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 };
|
|
21003
21171
|
}));
|
|
21004
21172
|
} catch {
|
|
21005
21173
|
}
|
|
21006
21174
|
});
|
|
21007
21175
|
const appendResults = { uploaded: 0, fullResyncNeeded: /* @__PURE__ */ new Set() };
|
|
21176
|
+
const pendingArchives = [];
|
|
21008
21177
|
const postAppend = async (convs) => {
|
|
21009
21178
|
const headers = { "content-type": "application/json" };
|
|
21010
21179
|
if (cred.token) headers.authorization = `Bearer ${cred.token}`;
|
|
@@ -21039,8 +21208,10 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
21039
21208
|
offset: c.from_offset,
|
|
21040
21209
|
size: c.from_offset,
|
|
21041
21210
|
// size = new offset (file grew to here)
|
|
21042
|
-
acked: true
|
|
21211
|
+
acked: true,
|
|
21043
21212
|
// server merged this tail
|
|
21213
|
+
chunkFinal: c.final === true
|
|
21214
|
+
// completes a chunked full sync
|
|
21044
21215
|
})));
|
|
21045
21216
|
} catch {
|
|
21046
21217
|
}
|
|
@@ -21072,9 +21243,9 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
21072
21243
|
const mtime = conv.mtime;
|
|
21073
21244
|
try {
|
|
21074
21245
|
if (staged || !guarded) {
|
|
21075
|
-
markSynced(base4, [{ id, mtime, offset: conv.from_offset, size: conv.from_offset, acked: true }]);
|
|
21246
|
+
markSynced(base4, [{ id, mtime, offset: conv.from_offset, size: conv.from_offset, acked: true, chunkedHead: true }]);
|
|
21076
21247
|
} else if (typeof guarded.o === "number" && guarded.o > 0 && guarded.o <= fileSize) {
|
|
21077
|
-
markSynced(base4, [{ id, mtime, offset: guarded.o, size: guarded.o, acked: true }]);
|
|
21248
|
+
markSynced(base4, [{ id, mtime, offset: guarded.o, size: guarded.o, acked: true, chunkedHead: true }]);
|
|
21078
21249
|
} else {
|
|
21079
21250
|
markSynced(base4, [{ id, mtime }]);
|
|
21080
21251
|
}
|
|
@@ -21283,6 +21454,14 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
21283
21454
|
if (built.srcHash) shippedHash.set(ref.prefixedId, built.srcHash);
|
|
21284
21455
|
if (built.conv.chunked) await postChunkedHead(built.conv, sessionFileBytes(ref));
|
|
21285
21456
|
else await convBatch.add(built.conv);
|
|
21457
|
+
if (built.archive) {
|
|
21458
|
+
pendingArchives.push({
|
|
21459
|
+
id: ref.prefixedId,
|
|
21460
|
+
...built.archive,
|
|
21461
|
+
projectId: built.conv.project_id,
|
|
21462
|
+
projectPath: built.conv.project_path
|
|
21463
|
+
});
|
|
21464
|
+
}
|
|
21286
21465
|
if (built.findings.length > 0) await findingsBatch.add(built.findings);
|
|
21287
21466
|
if (upload.sessionMeta) {
|
|
21288
21467
|
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);
|
|
@@ -21435,6 +21614,30 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
21435
21614
|
await kgTripleBatch.drain();
|
|
21436
21615
|
await findingsBatch.drain();
|
|
21437
21616
|
await drainInflight();
|
|
21617
|
+
let archivesUnsupported = false;
|
|
21618
|
+
for (const a of pendingArchives) {
|
|
21619
|
+
try {
|
|
21620
|
+
if (!archivesUnsupported) {
|
|
21621
|
+
const r = await uploadArchiveFile(base4, cred.token, {
|
|
21622
|
+
sessionId: a.id,
|
|
21623
|
+
tool: a.tool,
|
|
21624
|
+
mtime: a.mtime,
|
|
21625
|
+
projectId: a.projectId,
|
|
21626
|
+
projectPath: a.projectPath,
|
|
21627
|
+
file: a.file
|
|
21628
|
+
});
|
|
21629
|
+
if (r === "unsupported") archivesUnsupported = true;
|
|
21630
|
+
}
|
|
21631
|
+
} catch (err) {
|
|
21632
|
+
console.error(`[sync] raw archive for ${a.id} not uploaded (tried again when the session is next quiet): ${err instanceof Error ? err.message : err}`);
|
|
21633
|
+
try {
|
|
21634
|
+
forgetFullCoverage(base4, a.id);
|
|
21635
|
+
} catch {
|
|
21636
|
+
}
|
|
21637
|
+
} finally {
|
|
21638
|
+
rmSync7(a.file.path, { force: true });
|
|
21639
|
+
}
|
|
21640
|
+
}
|
|
21438
21641
|
{
|
|
21439
21642
|
const sentHashes = loadInventoryHashes(base4);
|
|
21440
21643
|
const entries = [];
|
|
@@ -21540,6 +21743,7 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
21540
21743
|
let includeRaw = opts.includeRaw !== false;
|
|
21541
21744
|
let includeMeta = opts.includeMeta !== false;
|
|
21542
21745
|
let srcHash;
|
|
21746
|
+
const wantRaw = opts.includeRaw !== false;
|
|
21543
21747
|
const oversized = sessionBuildBytes(ref) > FULL_BUILD_MAX_BYTES;
|
|
21544
21748
|
let headOffsetEnd = 0;
|
|
21545
21749
|
let oversizedFindings = null;
|
|
@@ -21708,7 +21912,7 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
21708
21912
|
} else if (opts.scanSecrets) {
|
|
21709
21913
|
let tmp = null;
|
|
21710
21914
|
try {
|
|
21711
|
-
tmp =
|
|
21915
|
+
tmp = join43(tmpdir4(), `cr-scan-${ref.prefixedId.replace(/[^A-Za-z0-9_-]/g, "")}-${mtime}.txt`);
|
|
21712
21916
|
writeFileSync9(tmp, rawText);
|
|
21713
21917
|
for (const f of scanFileForSecrets(tmp, { verifyOnly: opts.verifySecrets, tenantRules: opts.tenantRules })) {
|
|
21714
21918
|
const verifiedAt = f.verified ? (/* @__PURE__ */ new Date()).toISOString() : null;
|
|
@@ -21760,6 +21964,25 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
21760
21964
|
}
|
|
21761
21965
|
const envTexts = envelope.messages.filter((m) => m.content?.trim());
|
|
21762
21966
|
const redactedText = envTexts.map((m) => m.content).join("\n");
|
|
21967
|
+
let archive;
|
|
21968
|
+
if (wantRaw && !raw_b64) {
|
|
21969
|
+
try {
|
|
21970
|
+
const redact = (t) => redactSecrets(t, { force: true, count });
|
|
21971
|
+
let source = null;
|
|
21972
|
+
let archiveMtime = Math.floor(ref.mtime) || 0;
|
|
21973
|
+
let archiveTool = ref.toolId;
|
|
21974
|
+
if (container) {
|
|
21975
|
+
source = { kind: "memory", files: container.files };
|
|
21976
|
+
archiveMtime = container.mtime;
|
|
21977
|
+
archiveTool = container.tool;
|
|
21978
|
+
} else if (oversized) {
|
|
21979
|
+
source = diskArchiveSource(ref);
|
|
21980
|
+
}
|
|
21981
|
+
if (source) archive = { file: await writeArchiveFile(source, { tool: archiveTool, mtime: archiveMtime }, redact), tool: archiveTool, mtime: archiveMtime };
|
|
21982
|
+
} catch (err) {
|
|
21983
|
+
console.error(`[sync] raw archive for ${ref.prefixedId} not written: ${err instanceof Error ? err.message : err}`);
|
|
21984
|
+
}
|
|
21985
|
+
}
|
|
21763
21986
|
return {
|
|
21764
21987
|
conv: {
|
|
21765
21988
|
session_id: ref.prefixedId,
|
|
@@ -21791,7 +22014,17 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
21791
22014
|
redactions: count.redactions,
|
|
21792
22015
|
findings,
|
|
21793
22016
|
scanMs,
|
|
21794
|
-
srcHash
|
|
22017
|
+
srcHash,
|
|
22018
|
+
archive
|
|
22019
|
+
};
|
|
22020
|
+
}
|
|
22021
|
+
function diskArchiveSource(ref) {
|
|
22022
|
+
if (ref.toolId !== "claude") return null;
|
|
22023
|
+
const groups = resolveSessionContentGroups(ref.rawId);
|
|
22024
|
+
if (groups.length === 0 || groups.some((g) => g.paths.length !== 1)) return null;
|
|
22025
|
+
return {
|
|
22026
|
+
kind: "disk",
|
|
22027
|
+
files: groups.map((g) => ({ name: g.name === "main" ? `${ref.rawId}.jsonl` : g.name, path: g.paths[0] }))
|
|
21795
22028
|
};
|
|
21796
22029
|
}
|
|
21797
22030
|
function parseTailMessages(tool, text) {
|
|
@@ -21947,14 +22180,15 @@ var init_sync_client = __esm({
|
|
|
21947
22180
|
init_telemetry();
|
|
21948
22181
|
init_collector_health();
|
|
21949
22182
|
init_live_session_scan();
|
|
22183
|
+
init_raw_archive_parts();
|
|
21950
22184
|
init_backends();
|
|
21951
22185
|
ownVersion = "0.0.0";
|
|
21952
22186
|
try {
|
|
21953
22187
|
const dir = dirname19(fileURLToPath3(import.meta.url));
|
|
21954
|
-
ownVersion = JSON.parse(
|
|
22188
|
+
ownVersion = JSON.parse(readFileSync36(join43(dir, "../package.json"), "utf-8")).version || ownVersion;
|
|
21955
22189
|
} catch {
|
|
21956
22190
|
try {
|
|
21957
|
-
if (true) ownVersion = "0.7.
|
|
22191
|
+
if (true) ownVersion = "0.7.18";
|
|
21958
22192
|
} catch {
|
|
21959
22193
|
}
|
|
21960
22194
|
}
|
|
@@ -21966,7 +22200,7 @@ var init_sync_client = __esm({
|
|
|
21966
22200
|
]);
|
|
21967
22201
|
walkProgressForUpload = null;
|
|
21968
22202
|
lastServerPackSpec = null;
|
|
21969
|
-
credPath = () =>
|
|
22203
|
+
credPath = () => join43(getDataDir(), "credentials.json");
|
|
21970
22204
|
_securityConfigCache = /* @__PURE__ */ new Map();
|
|
21971
22205
|
SECURITY_CONFIG_TTL_MS = 5 * 60 * 1e3;
|
|
21972
22206
|
_syncConfigCache = /* @__PURE__ */ new Map();
|
|
@@ -21997,15 +22231,15 @@ __export(update_notice_exports, {
|
|
|
21997
22231
|
refreshUpdateCheck: () => refreshUpdateCheck,
|
|
21998
22232
|
updateNotice: () => updateNotice
|
|
21999
22233
|
});
|
|
22000
|
-
import { readFileSync as
|
|
22001
|
-
import { join as
|
|
22234
|
+
import { readFileSync as readFileSync37, writeFileSync as writeFileSync10 } from "node:fs";
|
|
22235
|
+
import { join as join44 } from "node:path";
|
|
22002
22236
|
function newestKnown(c) {
|
|
22003
22237
|
const npm = c.npmVersion ?? "0.0.0";
|
|
22004
22238
|
return compareVersions(npm, c.serverVersion) > 0 ? { version: npm, source: "npm" } : { version: c.serverVersion, source: "server" };
|
|
22005
22239
|
}
|
|
22006
22240
|
function readCheck() {
|
|
22007
22241
|
try {
|
|
22008
|
-
const c = JSON.parse(
|
|
22242
|
+
const c = JSON.parse(readFileSync37(checkPath(), "utf-8"));
|
|
22009
22243
|
return c && typeof c.serverVersion === "string" ? c : null;
|
|
22010
22244
|
} catch {
|
|
22011
22245
|
return null;
|
|
@@ -22099,17 +22333,17 @@ var init_update_notice = __esm({
|
|
|
22099
22333
|
init_http();
|
|
22100
22334
|
CHECK_TTL_MS = 6 * 3600 * 1e3;
|
|
22101
22335
|
NPM_LATEST_URL = "https://registry.npmjs.org/chat-recall";
|
|
22102
|
-
checkPath = () =>
|
|
22336
|
+
checkPath = () => join44(getDataDir(), "update-check.json");
|
|
22103
22337
|
printed = false;
|
|
22104
22338
|
}
|
|
22105
22339
|
});
|
|
22106
22340
|
|
|
22107
22341
|
// ../engine/dist/core/which.js
|
|
22108
|
-
import { existsSync as existsSync42, statSync as
|
|
22109
|
-
import { join as
|
|
22342
|
+
import { existsSync as existsSync42, statSync as statSync40, accessSync, constants } from "node:fs";
|
|
22343
|
+
import { join as join45, isAbsolute as isAbsolute2, delimiter as delimiter2, sep as sep3 } from "node:path";
|
|
22110
22344
|
function executable(p) {
|
|
22111
22345
|
try {
|
|
22112
|
-
if (!
|
|
22346
|
+
if (!statSync40(p).isFile())
|
|
22113
22347
|
return false;
|
|
22114
22348
|
} catch {
|
|
22115
22349
|
return false;
|
|
@@ -22145,7 +22379,7 @@ function resolveOnPath(name) {
|
|
|
22145
22379
|
if (!dir)
|
|
22146
22380
|
continue;
|
|
22147
22381
|
for (const c of candidates(name)) {
|
|
22148
|
-
const full =
|
|
22382
|
+
const full = join45(dir, c);
|
|
22149
22383
|
if (existsSync42(full) && executable(full))
|
|
22150
22384
|
return full;
|
|
22151
22385
|
}
|
|
@@ -22209,9 +22443,9 @@ __export(mcp_clients_exports, {
|
|
|
22209
22443
|
inspectMcpClients: () => inspectMcpClients,
|
|
22210
22444
|
registerMcpEverywhere: () => registerMcpEverywhere
|
|
22211
22445
|
});
|
|
22212
|
-
import { existsSync as existsSync44, mkdirSync as mkdirSync12, readFileSync as
|
|
22446
|
+
import { existsSync as existsSync44, mkdirSync as mkdirSync12, readFileSync as readFileSync38, writeFileSync as writeFileSync12 } from "fs";
|
|
22213
22447
|
import { homedir as homedir16 } from "os";
|
|
22214
|
-
import { dirname as dirname21, join as
|
|
22448
|
+
import { dirname as dirname21, join as join47 } from "path";
|
|
22215
22449
|
function envHome(varName, fallback) {
|
|
22216
22450
|
const v = process.env[varName];
|
|
22217
22451
|
return v && v.trim() ? v.trim() : fallback;
|
|
@@ -22221,7 +22455,7 @@ function writeFileMkdir(path, body2) {
|
|
|
22221
22455
|
writeFileSync12(path, body2);
|
|
22222
22456
|
}
|
|
22223
22457
|
function readJsonObject(path) {
|
|
22224
|
-
const raw =
|
|
22458
|
+
const raw = readFileSync38(path, "utf-8");
|
|
22225
22459
|
if (raw.trim() === "")
|
|
22226
22460
|
return {};
|
|
22227
22461
|
return JSON.parse(raw);
|
|
@@ -22296,7 +22530,7 @@ function registerCodexToml(path, spec) {
|
|
|
22296
22530
|
const id = "codex";
|
|
22297
22531
|
const label = "Codex";
|
|
22298
22532
|
const block = codexBlock(spec);
|
|
22299
|
-
const prev = existsSync44(path) ?
|
|
22533
|
+
const prev = existsSync44(path) ? readFileSync38(path, "utf-8") : "";
|
|
22300
22534
|
const lines = prev.length ? prev.split("\n") : [];
|
|
22301
22535
|
const start = lines.findIndex((l) => l.trim() === CODEX_HEADER);
|
|
22302
22536
|
if (start === -1) {
|
|
@@ -22339,7 +22573,7 @@ function inspectMcpClients(opts = {}) {
|
|
|
22339
22573
|
let registered = false;
|
|
22340
22574
|
if (existsSync44(path)) {
|
|
22341
22575
|
try {
|
|
22342
|
-
const raw =
|
|
22576
|
+
const raw = readFileSync38(path, "utf-8");
|
|
22343
22577
|
registered = c.id === "codex" ? raw.includes(CODEX_HEADER) : !!(JSON.parse(raw).mcpServers?.[MCP_SERVER_NAME] ?? JSON.parse(raw).mcp?.[MCP_SERVER_NAME]);
|
|
22344
22578
|
} catch {
|
|
22345
22579
|
registered = false;
|
|
@@ -22359,7 +22593,7 @@ var init_mcp_clients = __esm({
|
|
|
22359
22593
|
id: "claude",
|
|
22360
22594
|
label: "Claude Code",
|
|
22361
22595
|
bin: "claude",
|
|
22362
|
-
configPath: (home) =>
|
|
22596
|
+
configPath: (home) => join47(home, ".mcp.json"),
|
|
22363
22597
|
// Claude Code is the reference client and `init`'s historical target, so we
|
|
22364
22598
|
// always write it — a fresh machine has no ~/.claude yet on first install.
|
|
22365
22599
|
isPresent: () => true,
|
|
@@ -22371,7 +22605,7 @@ var init_mcp_clients = __esm({
|
|
|
22371
22605
|
id: "codex",
|
|
22372
22606
|
label: "Codex",
|
|
22373
22607
|
bin: "codex",
|
|
22374
|
-
configPath: (home) =>
|
|
22608
|
+
configPath: (home) => join47(envHome("CHAT_RECALL_CODEX_HOME", join47(home, ".codex")), "config.toml"),
|
|
22375
22609
|
isPresent(home) {
|
|
22376
22610
|
const p = this.configPath(home);
|
|
22377
22611
|
return existsSync44(p) || existsSync44(dirname21(p));
|
|
@@ -22384,7 +22618,7 @@ var init_mcp_clients = __esm({
|
|
|
22384
22618
|
id: "opencode",
|
|
22385
22619
|
label: "OpenCode",
|
|
22386
22620
|
bin: "opencode",
|
|
22387
|
-
configPath: (home) =>
|
|
22621
|
+
configPath: (home) => join47(envHome("XDG_CONFIG_HOME", join47(home, ".config")), "opencode", "opencode.json"),
|
|
22388
22622
|
isPresent(home) {
|
|
22389
22623
|
const p = this.configPath(home);
|
|
22390
22624
|
return existsSync44(p) || existsSync44(dirname21(p));
|
|
@@ -22399,9 +22633,9 @@ var init_mcp_clients = __esm({
|
|
|
22399
22633
|
id: "agy",
|
|
22400
22634
|
label: "Antigravity",
|
|
22401
22635
|
bin: "agy",
|
|
22402
|
-
configPath: (home) =>
|
|
22636
|
+
configPath: (home) => join47(home, ".gemini", "config", "mcp_config.json"),
|
|
22403
22637
|
isPresent(home) {
|
|
22404
|
-
return existsSync44(
|
|
22638
|
+
return existsSync44(join47(home, ".gemini", "antigravity-cli")) || existsSync44(this.configPath(home));
|
|
22405
22639
|
},
|
|
22406
22640
|
register(spec, home) {
|
|
22407
22641
|
return registerMcpServersJson(this, this.configPath(home), spec);
|
|
@@ -22411,7 +22645,7 @@ var init_mcp_clients = __esm({
|
|
|
22411
22645
|
id: "cursor",
|
|
22412
22646
|
label: "Cursor",
|
|
22413
22647
|
bin: "cursor",
|
|
22414
|
-
configPath: (home) =>
|
|
22648
|
+
configPath: (home) => join47(home, ".cursor", "mcp.json"),
|
|
22415
22649
|
isPresent(home) {
|
|
22416
22650
|
const p = this.configPath(home);
|
|
22417
22651
|
return existsSync44(p) || existsSync44(dirname21(p));
|
|
@@ -22438,9 +22672,9 @@ __export(companions_exports, {
|
|
|
22438
22672
|
uninstallCodeindex: () => uninstallCodeindex,
|
|
22439
22673
|
unregisterCodeindexMcp: () => unregisterCodeindexMcp
|
|
22440
22674
|
});
|
|
22441
|
-
import { existsSync as existsSync45, mkdirSync as mkdirSync13, statSync as
|
|
22675
|
+
import { existsSync as existsSync45, mkdirSync as mkdirSync13, statSync as statSync41, chmodSync as chmodSync4, unlinkSync as unlinkSync3, renameSync as renameSync5, createWriteStream as createWriteStream2, readFileSync as readFileSync39, writeFileSync as writeFileSync13 } from "node:fs";
|
|
22442
22676
|
import { homedir as homedir17 } from "node:os";
|
|
22443
|
-
import { join as
|
|
22677
|
+
import { join as join48 } from "node:path";
|
|
22444
22678
|
import { execSync as execSync3 } from "node:child_process";
|
|
22445
22679
|
import { createHash as createHash10 } from "node:crypto";
|
|
22446
22680
|
function expectedCodeindexSha256(artifact) {
|
|
@@ -22489,7 +22723,7 @@ function checkCodeindexStatus() {
|
|
|
22489
22723
|
status.installed = true;
|
|
22490
22724
|
status.path = foundPath;
|
|
22491
22725
|
try {
|
|
22492
|
-
status.size =
|
|
22726
|
+
status.size = statSync41(foundPath).size;
|
|
22493
22727
|
} catch {
|
|
22494
22728
|
}
|
|
22495
22729
|
try {
|
|
@@ -22515,7 +22749,7 @@ async function downloadArtifact(artifact, dest) {
|
|
|
22515
22749
|
throw new Error(`Download failed: ${res.status} ${res.statusText}`);
|
|
22516
22750
|
if (!res.body)
|
|
22517
22751
|
throw new Error("Download returned empty body");
|
|
22518
|
-
const file =
|
|
22752
|
+
const file = createWriteStream2(dest);
|
|
22519
22753
|
await new Promise((resolve3, reject) => {
|
|
22520
22754
|
const reader = res.body.getReader();
|
|
22521
22755
|
const pump = async () => {
|
|
@@ -22550,7 +22784,7 @@ async function installCodeindex(opts = {}) {
|
|
|
22550
22784
|
if (!expected) {
|
|
22551
22785
|
throw new Error(`No pinned checksum for ${status.artifactName} \u2014 refusing to install an unverified binary. Add its sha256 to CODEINDEX_SHA256 in companions.ts.`);
|
|
22552
22786
|
}
|
|
22553
|
-
const actual = createHash10("sha256").update(
|
|
22787
|
+
const actual = createHash10("sha256").update(readFileSync39(tmpPath)).digest("hex");
|
|
22554
22788
|
if (actual !== expected) {
|
|
22555
22789
|
throw new Error(`Checksum mismatch for ${status.artifactName}.
|
|
22556
22790
|
expected ${expected}
|
|
@@ -22580,7 +22814,7 @@ function registerCodeindexMcp(mcpJsonPath, binaryPath) {
|
|
|
22580
22814
|
let cfg = {};
|
|
22581
22815
|
if (existsSync45(mcpJsonPath)) {
|
|
22582
22816
|
try {
|
|
22583
|
-
cfg = JSON.parse(
|
|
22817
|
+
cfg = JSON.parse(readFileSync39(mcpJsonPath, "utf-8"));
|
|
22584
22818
|
} catch {
|
|
22585
22819
|
cfg = {};
|
|
22586
22820
|
}
|
|
@@ -22597,7 +22831,7 @@ function unregisterCodeindexMcp(mcpJsonPath) {
|
|
|
22597
22831
|
return { removed: false };
|
|
22598
22832
|
let cfg;
|
|
22599
22833
|
try {
|
|
22600
|
-
cfg = JSON.parse(
|
|
22834
|
+
cfg = JSON.parse(readFileSync39(mcpJsonPath, "utf-8"));
|
|
22601
22835
|
} catch {
|
|
22602
22836
|
return { removed: false };
|
|
22603
22837
|
}
|
|
@@ -22622,9 +22856,9 @@ var init_companions = __esm({
|
|
|
22622
22856
|
"x86_64-windows": "a96fc8c8949bb399a44cc0615b12e458460a529c69f01e8829cc39a20f45ab29",
|
|
22623
22857
|
"aarch64-windows": "42620d56272cd9ba9d785569d8d754d6b4a3e80f36f28db3e0c483fd600ed117"
|
|
22624
22858
|
};
|
|
22625
|
-
CODEINDEX_INSTALL_DIR =
|
|
22859
|
+
CODEINDEX_INSTALL_DIR = join48(homedir17(), ".local", "bin");
|
|
22626
22860
|
CODEINDEX_BIN_NAME = process.platform === "win32" ? "codeindex.exe" : "codeindex";
|
|
22627
|
-
CODEINDEX_BIN_PATH =
|
|
22861
|
+
CODEINDEX_BIN_PATH = join48(CODEINDEX_INSTALL_DIR, CODEINDEX_BIN_NAME);
|
|
22628
22862
|
}
|
|
22629
22863
|
});
|
|
22630
22864
|
|
|
@@ -22639,15 +22873,15 @@ __export(install_skills_exports, {
|
|
|
22639
22873
|
skillsSourceDir: () => skillsSourceDir,
|
|
22640
22874
|
uninstallSkills: () => uninstallSkills
|
|
22641
22875
|
});
|
|
22642
|
-
import { readdirSync as readdirSync32, existsSync as existsSync46, mkdirSync as mkdirSync14, rmSync as
|
|
22876
|
+
import { readdirSync as readdirSync32, existsSync as existsSync46, mkdirSync as mkdirSync14, rmSync as rmSync8, cpSync, writeFileSync as writeFileSync14, readFileSync as readFileSync40, statSync as statSync42, realpathSync as realpathSync4 } from "fs";
|
|
22643
22877
|
import { createHash as createHash11 } from "crypto";
|
|
22644
|
-
import { join as
|
|
22878
|
+
import { join as join49, basename as basename21 } from "path";
|
|
22645
22879
|
function skillsSourceDir() {
|
|
22646
|
-
return
|
|
22880
|
+
return join49(import.meta.dirname, "..", "skills");
|
|
22647
22881
|
}
|
|
22648
22882
|
function version() {
|
|
22649
22883
|
try {
|
|
22650
|
-
return JSON.parse(
|
|
22884
|
+
return JSON.parse(readFileSync40(new URL("../package.json", import.meta.url), "utf-8")).version || "0.0.0";
|
|
22651
22885
|
} catch {
|
|
22652
22886
|
return "0.0.0";
|
|
22653
22887
|
}
|
|
@@ -22656,9 +22890,9 @@ function skillsFingerprint() {
|
|
|
22656
22890
|
const src = skillsSourceDir();
|
|
22657
22891
|
const h = createHash11("sha256");
|
|
22658
22892
|
for (const name of bundledSkillNames()) {
|
|
22659
|
-
for (const rel of filesUnder(
|
|
22893
|
+
for (const rel of filesUnder(join49(src, name)).sort()) {
|
|
22660
22894
|
h.update(name + "/" + rel);
|
|
22661
|
-
h.update(
|
|
22895
|
+
h.update(readFileSync40(join49(src, name, rel)));
|
|
22662
22896
|
}
|
|
22663
22897
|
}
|
|
22664
22898
|
return h.digest("hex").slice(0, 12);
|
|
@@ -22668,7 +22902,7 @@ function filesUnder(dir, prefix = "") {
|
|
|
22668
22902
|
for (const e of readdirSync32(dir, { withFileTypes: true })) {
|
|
22669
22903
|
if (e.name === MARKER) continue;
|
|
22670
22904
|
const rel = prefix ? `${prefix}/${e.name}` : e.name;
|
|
22671
|
-
if (e.isDirectory()) out.push(...filesUnder(
|
|
22905
|
+
if (e.isDirectory()) out.push(...filesUnder(join49(dir, e.name), rel));
|
|
22672
22906
|
else out.push(rel);
|
|
22673
22907
|
}
|
|
22674
22908
|
return out;
|
|
@@ -22679,7 +22913,7 @@ function skillStamp() {
|
|
|
22679
22913
|
function bundledSkillNames() {
|
|
22680
22914
|
const src = skillsSourceDir();
|
|
22681
22915
|
if (!existsSync46(src)) return [];
|
|
22682
|
-
return readdirSync32(src, { withFileTypes: true }).filter((e) => e.isDirectory() && existsSync46(
|
|
22916
|
+
return readdirSync32(src, { withFileTypes: true }).filter((e) => e.isDirectory() && existsSync46(join49(src, e.name, "SKILL.md"))).map((e) => e.name).sort();
|
|
22683
22917
|
}
|
|
22684
22918
|
function realPathOrSelf(p) {
|
|
22685
22919
|
try {
|
|
@@ -22692,7 +22926,7 @@ function claudeSkillTargets() {
|
|
|
22692
22926
|
const targets = [];
|
|
22693
22927
|
const seen = /* @__PURE__ */ new Set();
|
|
22694
22928
|
for (const home of claudeHomeDirs()) {
|
|
22695
|
-
const dir =
|
|
22929
|
+
const dir = join49(home, "skills");
|
|
22696
22930
|
const key2 = realPathOrSelf(dir);
|
|
22697
22931
|
if (seen.has(key2)) continue;
|
|
22698
22932
|
seen.add(key2);
|
|
@@ -22703,7 +22937,7 @@ function claudeSkillTargets() {
|
|
|
22703
22937
|
dir,
|
|
22704
22938
|
// Judge each profile on ITS OWN transcripts, not the primary's: a home
|
|
22705
22939
|
// with no projects/ is a directory someone made, not a Claude install.
|
|
22706
|
-
available: existsSync46(
|
|
22940
|
+
available: existsSync46(join49(home, "projects"))
|
|
22707
22941
|
});
|
|
22708
22942
|
}
|
|
22709
22943
|
if (targets.length === 0) {
|
|
@@ -22718,16 +22952,16 @@ function skillTargets() {
|
|
|
22718
22952
|
// both produces "skill conflict" duplicate warnings. Every tool we support
|
|
22719
22953
|
// has its own dir, so per-tool coverage is complete.
|
|
22720
22954
|
...claudeSkillTargets(),
|
|
22721
|
-
{ id: "agy", label: "Antigravity", dir:
|
|
22955
|
+
{ id: "agy", label: "Antigravity", dir: join49(agyBackend.homeDir(), "skills"), available: agyBackend.isAvailable() },
|
|
22722
22956
|
{ id: "codex", label: "Codex", dir: codexBackend.skillsDir(), available: codexBackend.isAvailable() },
|
|
22723
22957
|
{ id: "opencode", label: "OpenCode", dir: opencodeBackend.skillsDir(), available: opencodeBackend.isAvailable() },
|
|
22724
22958
|
// Cursor DOES have its own dir (~/.cursor/skills). `skills-cursor` next to
|
|
22725
22959
|
// it is Cursor's bundled set — read-only, never an install target.
|
|
22726
|
-
{ id: "cursor", label: "Cursor", dir:
|
|
22960
|
+
{ id: "cursor", label: "Cursor", dir: join49(cursorHomeDir(), "skills"), available: cursorBackend.isAvailable() }
|
|
22727
22961
|
];
|
|
22728
22962
|
}
|
|
22729
22963
|
function isManaged(dir) {
|
|
22730
|
-
return existsSync46(
|
|
22964
|
+
return existsSync46(join49(dir, MARKER));
|
|
22731
22965
|
}
|
|
22732
22966
|
function installSkills(opts = {}) {
|
|
22733
22967
|
const onlyAvailable = opts.onlyAvailable ?? true;
|
|
@@ -22744,15 +22978,15 @@ function installSkills(opts = {}) {
|
|
|
22744
22978
|
continue;
|
|
22745
22979
|
}
|
|
22746
22980
|
for (const name of names) {
|
|
22747
|
-
const dest =
|
|
22981
|
+
const dest = join49(t.dir, name);
|
|
22748
22982
|
if (existsSync46(dest) && !isManaged(dest)) {
|
|
22749
22983
|
skippedUserOwned.push(name);
|
|
22750
22984
|
continue;
|
|
22751
22985
|
}
|
|
22752
22986
|
mkdirSync14(t.dir, { recursive: true });
|
|
22753
|
-
|
|
22754
|
-
cpSync(
|
|
22755
|
-
writeFileSync14(
|
|
22987
|
+
rmSync8(dest, { recursive: true, force: true });
|
|
22988
|
+
cpSync(join49(src, name), dest, { recursive: true });
|
|
22989
|
+
writeFileSync14(join49(dest, MARKER), `${stamp}
|
|
22756
22990
|
`);
|
|
22757
22991
|
installed.push(name);
|
|
22758
22992
|
}
|
|
@@ -22771,9 +23005,9 @@ function uninstallSkills() {
|
|
|
22771
23005
|
}
|
|
22772
23006
|
for (const entry of readdirSync32(t.dir, { withFileTypes: true })) {
|
|
22773
23007
|
if (!entry.isDirectory()) continue;
|
|
22774
|
-
const dir =
|
|
23008
|
+
const dir = join49(t.dir, entry.name);
|
|
22775
23009
|
if (isManaged(dir) && (names.has(entry.name) || entry.name.startsWith("chat-recall"))) {
|
|
22776
|
-
|
|
23010
|
+
rmSync8(dir, { recursive: true, force: true });
|
|
22777
23011
|
removed.push(entry.name);
|
|
22778
23012
|
}
|
|
22779
23013
|
}
|
|
@@ -22788,10 +23022,10 @@ function skillsNeedRefresh() {
|
|
|
22788
23022
|
for (const t of skillTargets()) {
|
|
22789
23023
|
if (!t.available) continue;
|
|
22790
23024
|
for (const name of names) {
|
|
22791
|
-
const marker =
|
|
23025
|
+
const marker = join49(t.dir, name, MARKER);
|
|
22792
23026
|
if (!existsSync46(marker)) return true;
|
|
22793
23027
|
try {
|
|
22794
|
-
if (
|
|
23028
|
+
if (readFileSync40(marker, "utf-8").trim() !== cur) return true;
|
|
22795
23029
|
} catch {
|
|
22796
23030
|
return true;
|
|
22797
23031
|
}
|
|
@@ -22806,11 +23040,11 @@ function skillStatus() {
|
|
|
22806
23040
|
let installed = 0;
|
|
22807
23041
|
let ver = null;
|
|
22808
23042
|
for (const name of names) {
|
|
22809
|
-
const marker =
|
|
23043
|
+
const marker = join49(t.dir, name, MARKER);
|
|
22810
23044
|
if (existsSync46(marker)) {
|
|
22811
23045
|
installed++;
|
|
22812
23046
|
try {
|
|
22813
|
-
ver =
|
|
23047
|
+
ver = readFileSync40(marker, "utf-8").trim();
|
|
22814
23048
|
} catch {
|
|
22815
23049
|
}
|
|
22816
23050
|
}
|
|
@@ -22834,8 +23068,8 @@ var init_install_skills = __esm({
|
|
|
22834
23068
|
});
|
|
22835
23069
|
|
|
22836
23070
|
// ../engine/dist/core/artifact-codec.js
|
|
22837
|
-
import { readFileSync as
|
|
22838
|
-
import { basename as basename22, join as
|
|
23071
|
+
import { readFileSync as readFileSync41 } from "fs";
|
|
23072
|
+
import { basename as basename22, join as join50 } from "path";
|
|
22839
23073
|
import { homedir as homedir18 } from "os";
|
|
22840
23074
|
function parseCommandText(content, format, fallbackName) {
|
|
22841
23075
|
if (format === "toml") {
|
|
@@ -22858,41 +23092,41 @@ function parseAgentText(content, format, fallbackName) {
|
|
|
22858
23092
|
return { name: fm.name || fallbackName, description: fm.description || "", tools: fm.tools, body: body2.trim() };
|
|
22859
23093
|
}
|
|
22860
23094
|
function readCommand(filePath, format) {
|
|
22861
|
-
return parseCommandText(
|
|
23095
|
+
return parseCommandText(readFileSync41(filePath, "utf-8"), format, base2(filePath));
|
|
22862
23096
|
}
|
|
22863
23097
|
function readAgent(filePath, format) {
|
|
22864
|
-
return parseAgentText(
|
|
23098
|
+
return parseAgentText(readFileSync41(filePath, "utf-8"), format, base2(filePath));
|
|
22865
23099
|
}
|
|
22866
23100
|
function readInstructions(filePath, name) {
|
|
22867
|
-
const content =
|
|
23101
|
+
const content = readFileSync41(filePath, "utf-8");
|
|
22868
23102
|
return { name, description: "", body: content };
|
|
22869
23103
|
}
|
|
22870
23104
|
function commandPath(tool, name) {
|
|
22871
23105
|
switch (tool) {
|
|
22872
23106
|
case "claude":
|
|
22873
|
-
return
|
|
23107
|
+
return join50(claudeBackend.commandsDir(), `${name}.md`);
|
|
22874
23108
|
case "agy":
|
|
22875
|
-
return
|
|
23109
|
+
return join50(join50(agyBackend.homeDir(), "commands"), `${name}.toml`);
|
|
22876
23110
|
case "opencode":
|
|
22877
|
-
return
|
|
23111
|
+
return join50(opencodeBackend.commandsDir(), `${name}.md`);
|
|
22878
23112
|
case "codex":
|
|
22879
|
-
return
|
|
23113
|
+
return join50(codexBackend.promptsDir(), `${name}.md`);
|
|
22880
23114
|
case "cursor":
|
|
22881
|
-
return
|
|
23115
|
+
return join50(cursorHomeDir(), "commands", `${name}.md`);
|
|
22882
23116
|
}
|
|
22883
23117
|
}
|
|
22884
23118
|
function agentPath(tool, name) {
|
|
22885
23119
|
switch (tool) {
|
|
22886
23120
|
case "claude":
|
|
22887
|
-
return
|
|
23121
|
+
return join50(claudeBackend.agentsDir(), `${name}.md`);
|
|
22888
23122
|
case "agy":
|
|
22889
|
-
return
|
|
23123
|
+
return join50(join50(agyBackend.homeDir(), "agents"), `${name}.md`);
|
|
22890
23124
|
case "opencode":
|
|
22891
|
-
return
|
|
23125
|
+
return join50(opencodeBackend.agentsDir(), `${name}.md`);
|
|
22892
23126
|
case "codex":
|
|
22893
|
-
return
|
|
23127
|
+
return join50(codexBackend.agentsDir(), `${name}.toml`);
|
|
22894
23128
|
case "cursor":
|
|
22895
|
-
return
|
|
23129
|
+
return join50(cursorHomeDir(), "agents", `${name}.md`);
|
|
22896
23130
|
}
|
|
22897
23131
|
}
|
|
22898
23132
|
function instructionsFilename(tool) {
|
|
@@ -22917,21 +23151,21 @@ function instructionsFilename(tool) {
|
|
|
22917
23151
|
function instructionsPath(tool, projectPath) {
|
|
22918
23152
|
const file = instructionsFilename(tool);
|
|
22919
23153
|
if (projectPath)
|
|
22920
|
-
return
|
|
23154
|
+
return join50(projectPath, file);
|
|
22921
23155
|
switch (tool) {
|
|
22922
23156
|
case "claude":
|
|
22923
|
-
return
|
|
23157
|
+
return join50(claudeBackend.homeDir(), file);
|
|
22924
23158
|
case "agy":
|
|
22925
|
-
return
|
|
23159
|
+
return join50(agyBackend.homeDir(), file);
|
|
22926
23160
|
case "codex":
|
|
22927
|
-
return
|
|
23161
|
+
return join50(codexBackend.homeDir(), file);
|
|
22928
23162
|
case "opencode":
|
|
22929
|
-
return
|
|
23163
|
+
return join50(homedir18(), ".config", "opencode", file);
|
|
22930
23164
|
// Cursor has no single user-scope instructions FILE — user-level guidance
|
|
22931
23165
|
// is User Rules plus ~/.cursor/rules/*.mdc. AGENTS.md at the home root is
|
|
22932
23166
|
// the closest equivalent and is what a mirror can actually write.
|
|
22933
23167
|
case "cursor":
|
|
22934
|
-
return
|
|
23168
|
+
return join50(cursorHomeDir(), file);
|
|
22935
23169
|
}
|
|
22936
23170
|
}
|
|
22937
23171
|
function emit(type, art, toTool, projectPath) {
|
|
@@ -22995,8 +23229,8 @@ __export(toolkit_sync_exports, {
|
|
|
22995
23229
|
supportedTargetsFor: () => supportedTargetsFor,
|
|
22996
23230
|
writeMcpEntry: () => writeMcpEntry
|
|
22997
23231
|
});
|
|
22998
|
-
import { existsSync as existsSync47, mkdirSync as mkdirSync15, readFileSync as
|
|
22999
|
-
import { dirname as dirname22, join as
|
|
23232
|
+
import { existsSync as existsSync47, mkdirSync as mkdirSync15, readFileSync as readFileSync42, writeFileSync as writeFileSync15, cpSync as cpSync2 } from "fs";
|
|
23233
|
+
import { dirname as dirname22, join as join51, basename as basename23 } from "path";
|
|
23000
23234
|
import { homedir as homedir19 } from "os";
|
|
23001
23235
|
function supportedTargetsFor(type) {
|
|
23002
23236
|
return SUPPORTED_TARGETS[type];
|
|
@@ -23038,14 +23272,14 @@ function skillsDirFor(tool) {
|
|
|
23038
23272
|
case "claude":
|
|
23039
23273
|
return claudeBackend.skillsDir();
|
|
23040
23274
|
case "agy":
|
|
23041
|
-
return
|
|
23275
|
+
return join51(agyBackend.homeDir(), "skills");
|
|
23042
23276
|
case "opencode":
|
|
23043
23277
|
return opencodeBackend.skillsDir();
|
|
23044
23278
|
case "codex":
|
|
23045
23279
|
return codexBackend.skillsDir();
|
|
23046
23280
|
// user skills, NOT .system
|
|
23047
23281
|
case "cursor":
|
|
23048
|
-
return
|
|
23282
|
+
return join51(cursorHomeDir(), "skills");
|
|
23049
23283
|
}
|
|
23050
23284
|
}
|
|
23051
23285
|
function copySkill(row, toTool) {
|
|
@@ -23053,7 +23287,7 @@ function copySkill(row, toTool) {
|
|
|
23053
23287
|
if (!existsSync47(skillDir))
|
|
23054
23288
|
return { ok: false, status: 404, error: `Source dir missing: ${skillDir}` };
|
|
23055
23289
|
const name = row.extra.skillName || basename23(skillDir);
|
|
23056
|
-
const targetDir =
|
|
23290
|
+
const targetDir = join51(skillsDirFor(toTool), name);
|
|
23057
23291
|
if (existsSync47(targetDir))
|
|
23058
23292
|
return { ok: false, status: 409, error: `Already exists: ${targetDir}` };
|
|
23059
23293
|
try {
|
|
@@ -23068,20 +23302,20 @@ function readMcpEntry(tool, name) {
|
|
|
23068
23302
|
const home = homedir19();
|
|
23069
23303
|
const tries = [];
|
|
23070
23304
|
if (tool === "claude") {
|
|
23071
|
-
tries.push({ path:
|
|
23072
|
-
tries.push({ path:
|
|
23305
|
+
tries.push({ path: join51(home, ".mcp.json"), key: "mcpServers" });
|
|
23306
|
+
tries.push({ path: join51(home, ".claude.json"), key: "mcpServers" });
|
|
23073
23307
|
} else if (tool === "gemini") {
|
|
23074
|
-
tries.push({ path:
|
|
23308
|
+
tries.push({ path: join51(home, ".gemini", "settings.json"), key: "mcpServers" });
|
|
23075
23309
|
} else if (tool === "agy") {
|
|
23076
|
-
tries.push({ path:
|
|
23310
|
+
tries.push({ path: join51(home, ".gemini", "config", "mcp_config.json"), key: "mcpServers" });
|
|
23077
23311
|
} else if (tool === "cursor") {
|
|
23078
|
-
tries.push({ path:
|
|
23312
|
+
tries.push({ path: join51(cursorHomeDir(), "mcp.json"), key: "mcpServers" });
|
|
23079
23313
|
} else if (tool === "opencode") {
|
|
23080
|
-
tries.push({ path:
|
|
23081
|
-
tries.push({ path:
|
|
23082
|
-
tries.push({ path:
|
|
23314
|
+
tries.push({ path: join51(home, ".config", "opencode", "opencode.json"), key: "mcp" });
|
|
23315
|
+
tries.push({ path: join51(home, ".config", "opencode", "config.json"), key: "mcp" });
|
|
23316
|
+
tries.push({ path: join51(home, ".opencode", "config.json"), key: "mcp" });
|
|
23083
23317
|
} else if (tool === "codex") {
|
|
23084
|
-
const entry = readCodexMcpEntry(
|
|
23318
|
+
const entry = readCodexMcpEntry(join51(home, ".codex", "config.toml"), name);
|
|
23085
23319
|
if (entry)
|
|
23086
23320
|
return entry;
|
|
23087
23321
|
}
|
|
@@ -23089,7 +23323,7 @@ function readMcpEntry(tool, name) {
|
|
|
23089
23323
|
if (!existsSync47(t.path))
|
|
23090
23324
|
continue;
|
|
23091
23325
|
try {
|
|
23092
|
-
const cfg = JSON.parse(
|
|
23326
|
+
const cfg = JSON.parse(readFileSync42(t.path, "utf-8"));
|
|
23093
23327
|
const block = cfg[t.key] || {};
|
|
23094
23328
|
if (block[name])
|
|
23095
23329
|
return block[name];
|
|
@@ -23103,7 +23337,7 @@ function readCodexMcpEntry(path, target) {
|
|
|
23103
23337
|
return null;
|
|
23104
23338
|
let content;
|
|
23105
23339
|
try {
|
|
23106
|
-
content =
|
|
23340
|
+
content = readFileSync42(path, "utf-8");
|
|
23107
23341
|
} catch {
|
|
23108
23342
|
return null;
|
|
23109
23343
|
}
|
|
@@ -23154,7 +23388,7 @@ function readCodexMcpEntry(path, target) {
|
|
|
23154
23388
|
function writeCodexMcpEntry(path, name, entry) {
|
|
23155
23389
|
let content = "";
|
|
23156
23390
|
if (existsSync47(path))
|
|
23157
|
-
content =
|
|
23391
|
+
content = readFileSync42(path, "utf-8");
|
|
23158
23392
|
const header = `[mcp_servers.${name}]`;
|
|
23159
23393
|
if (content.includes(header))
|
|
23160
23394
|
return false;
|
|
@@ -23190,7 +23424,7 @@ function writeCodexMcpEntry(path, name, entry) {
|
|
|
23190
23424
|
function writeMcpEntry(toTool, name, entry) {
|
|
23191
23425
|
const home = homedir19();
|
|
23192
23426
|
if (toTool === "codex") {
|
|
23193
|
-
const path2 =
|
|
23427
|
+
const path2 = join51(home, ".codex", "config.toml");
|
|
23194
23428
|
if (!writeCodexMcpEntry(path2, name, entry))
|
|
23195
23429
|
return { ok: false, status: 409, error: `MCP "${name}" already exists in ${path2}.` };
|
|
23196
23430
|
return { ok: true, targetPath: path2 };
|
|
@@ -23198,22 +23432,22 @@ function writeMcpEntry(toTool, name, entry) {
|
|
|
23198
23432
|
let path;
|
|
23199
23433
|
let key2;
|
|
23200
23434
|
if (toTool === "claude") {
|
|
23201
|
-
path =
|
|
23435
|
+
path = join51(home, ".mcp.json");
|
|
23202
23436
|
key2 = "mcpServers";
|
|
23203
23437
|
} else if (toTool === "agy") {
|
|
23204
|
-
path =
|
|
23438
|
+
path = join51(home, ".gemini", "config", "mcp_config.json");
|
|
23205
23439
|
key2 = "mcpServers";
|
|
23206
23440
|
} else if (toTool === "cursor") {
|
|
23207
|
-
path =
|
|
23441
|
+
path = join51(cursorHomeDir(), "mcp.json");
|
|
23208
23442
|
key2 = "mcpServers";
|
|
23209
23443
|
} else {
|
|
23210
|
-
path =
|
|
23444
|
+
path = join51(home, ".config", "opencode", "opencode.json");
|
|
23211
23445
|
key2 = "mcp";
|
|
23212
23446
|
}
|
|
23213
23447
|
let cfg = {};
|
|
23214
23448
|
if (existsSync47(path)) {
|
|
23215
23449
|
try {
|
|
23216
|
-
cfg = JSON.parse(
|
|
23450
|
+
cfg = JSON.parse(readFileSync42(path, "utf-8"));
|
|
23217
23451
|
} catch {
|
|
23218
23452
|
return { ok: false, status: 500, error: `Target config is malformed: ${path}` };
|
|
23219
23453
|
}
|
|
@@ -23446,11 +23680,11 @@ __export(toolkit_pull_exports, {
|
|
|
23446
23680
|
platformRefusal: () => platformRefusal,
|
|
23447
23681
|
portableCommand: () => portableCommand
|
|
23448
23682
|
});
|
|
23449
|
-
import { existsSync as existsSync48, mkdirSync as mkdirSync16, statSync as
|
|
23450
|
-
import { dirname as dirname23, join as
|
|
23683
|
+
import { existsSync as existsSync48, mkdirSync as mkdirSync16, statSync as statSync43, writeFileSync as writeFileSync16 } from "node:fs";
|
|
23684
|
+
import { dirname as dirname23, join as join52, basename as basename24, isAbsolute as isAbsolute3 } from "node:path";
|
|
23451
23685
|
function isExecutableFile(p) {
|
|
23452
23686
|
try {
|
|
23453
|
-
return
|
|
23687
|
+
return statSync43(p).isFile();
|
|
23454
23688
|
} catch {
|
|
23455
23689
|
return false;
|
|
23456
23690
|
}
|
|
@@ -23617,8 +23851,8 @@ function executePull(rows, opts = {}) {
|
|
|
23617
23851
|
const outcomes = [];
|
|
23618
23852
|
for (const { name, body: body2, truncated, redacted, tools } of skills) {
|
|
23619
23853
|
for (const tool of tools) {
|
|
23620
|
-
const dir =
|
|
23621
|
-
const file =
|
|
23854
|
+
const dir = join52(skillsDirFor(tool), name);
|
|
23855
|
+
const file = join52(dir, "SKILL.md");
|
|
23622
23856
|
if (existsSync48(file)) {
|
|
23623
23857
|
outcomes.push({ type: "skill", name, tool, status: "present" });
|
|
23624
23858
|
continue;
|
|
@@ -23827,8 +24061,8 @@ __export(board_hooks_exports, {
|
|
|
23827
24061
|
removeBoardHooks: () => removeBoardHooks,
|
|
23828
24062
|
resolveCliEntry: () => resolveCliEntry
|
|
23829
24063
|
});
|
|
23830
|
-
import { existsSync as existsSync49, mkdirSync as mkdirSync17, readFileSync as
|
|
23831
|
-
import { dirname as dirname24, join as
|
|
24064
|
+
import { existsSync as existsSync49, mkdirSync as mkdirSync17, readFileSync as readFileSync43, writeFileSync as writeFileSync17 } from "node:fs";
|
|
24065
|
+
import { dirname as dirname24, join as join53 } from "node:path";
|
|
23832
24066
|
function boardHookCommand(execPath, cliEntry, mode) {
|
|
23833
24067
|
return `"${execPath}" "${cliEntry}" task-hook --${mode}`;
|
|
23834
24068
|
}
|
|
@@ -23869,7 +24103,7 @@ function removeBoardHooks(config2) {
|
|
|
23869
24103
|
function readConfig(file) {
|
|
23870
24104
|
if (!existsSync49(file)) return { hooks: {} };
|
|
23871
24105
|
try {
|
|
23872
|
-
const parsed = JSON.parse(
|
|
24106
|
+
const parsed = JSON.parse(readFileSync43(file, "utf-8"));
|
|
23873
24107
|
if (!parsed.hooks || typeof parsed.hooks !== "object") parsed.hooks = {};
|
|
23874
24108
|
return parsed;
|
|
23875
24109
|
} catch {
|
|
@@ -23881,7 +24115,7 @@ function registerBoardHooks(files, execPath, cliEntry) {
|
|
|
23881
24115
|
for (const file of files) {
|
|
23882
24116
|
if (existsSync49(file)) {
|
|
23883
24117
|
try {
|
|
23884
|
-
JSON.parse(
|
|
24118
|
+
JSON.parse(readFileSync43(file, "utf-8"));
|
|
23885
24119
|
} catch {
|
|
23886
24120
|
continue;
|
|
23887
24121
|
}
|
|
@@ -23898,8 +24132,8 @@ function registerBoardHooks(files, execPath, cliEntry) {
|
|
|
23898
24132
|
return written;
|
|
23899
24133
|
}
|
|
23900
24134
|
function resolveCliEntry(distDir) {
|
|
23901
|
-
const bundled =
|
|
23902
|
-
return existsSync49(bundled) ? bundled :
|
|
24135
|
+
const bundled = join53(distDir, "cli.js");
|
|
24136
|
+
return existsSync49(bundled) ? bundled : join53(distDir, "cli.ts");
|
|
23903
24137
|
}
|
|
23904
24138
|
var BOARD_HOOKS;
|
|
23905
24139
|
var init_board_hooks = __esm({
|
|
@@ -24108,11 +24342,16 @@ async function repairAll(opts = {}) {
|
|
|
24108
24342
|
scanned++;
|
|
24109
24343
|
if (opts.verbose && scanned % 50 === 0) log6(`checked ${scanned}/${ids.length}\u2026`);
|
|
24110
24344
|
const arch = await fetchJson(`${primary.url}/api/conversations/${id}/raw-archive?count=1`, primary.token);
|
|
24111
|
-
const
|
|
24112
|
-
if (
|
|
24113
|
-
|
|
24114
|
-
|
|
24115
|
-
|
|
24345
|
+
const counted = arch && arch.messages !== null;
|
|
24346
|
+
if (counted) {
|
|
24347
|
+
const archiveMsgs = typeof arch?.messages === "number" ? arch.messages : 0;
|
|
24348
|
+
if (archiveMsgs < minMessages) continue;
|
|
24349
|
+
const meta = await fetchJson(`${primary.url}/api/conversations/${id}/metadata`, primary.token);
|
|
24350
|
+
const current = typeof meta?.messageCount === "number" ? meta.messageCount : 0;
|
|
24351
|
+
if (archiveMsgs <= current) continue;
|
|
24352
|
+
} else if (!arch) {
|
|
24353
|
+
continue;
|
|
24354
|
+
}
|
|
24116
24355
|
const r = await repairSession(id, { dryRun: !opts.apply, verbose: opts.verbose, server: opts.server });
|
|
24117
24356
|
if (r.status === "already-full") continue;
|
|
24118
24357
|
candidates2.push(r);
|
|
@@ -24297,21 +24536,21 @@ __export(guard_registration_exports, {
|
|
|
24297
24536
|
unregisterGuard: () => unregisterGuard
|
|
24298
24537
|
});
|
|
24299
24538
|
import { homedir as homedir20 } from "os";
|
|
24300
|
-
import { join as
|
|
24539
|
+
import { join as join54 } from "path";
|
|
24301
24540
|
function opencodeConfigDir() {
|
|
24302
24541
|
const xdg = process.env.XDG_CONFIG_HOME;
|
|
24303
|
-
const base4 = xdg && xdg.trim() ? xdg :
|
|
24304
|
-
return
|
|
24542
|
+
const base4 = xdg && xdg.trim() ? xdg : join54(homedir20(), ".config");
|
|
24543
|
+
return join54(base4, "opencode");
|
|
24305
24544
|
}
|
|
24306
24545
|
function opencodePluginDir() {
|
|
24307
|
-
return
|
|
24546
|
+
return join54(opencodeConfigDir(), "plugins");
|
|
24308
24547
|
}
|
|
24309
24548
|
function guardTargets() {
|
|
24310
24549
|
return [
|
|
24311
24550
|
{
|
|
24312
24551
|
tool: "codex",
|
|
24313
24552
|
label: "Codex",
|
|
24314
|
-
configPath:
|
|
24553
|
+
configPath: join54(codexBackend.homeDir(), "hooks.json"),
|
|
24315
24554
|
homeDir: codexBackend.homeDir(),
|
|
24316
24555
|
// Codex will not run a hook until a person has reviewed it, and the
|
|
24317
24556
|
// approval is bound to the hook's hash. There is no way to grant it from
|
|
@@ -24324,20 +24563,20 @@ function guardTargets() {
|
|
|
24324
24563
|
{
|
|
24325
24564
|
tool: "agy",
|
|
24326
24565
|
label: "Antigravity",
|
|
24327
|
-
configPath:
|
|
24566
|
+
configPath: join54(agyBackend.homeDir(), "hooks.json"),
|
|
24328
24567
|
homeDir: agyBackend.homeDir()
|
|
24329
24568
|
},
|
|
24330
24569
|
{
|
|
24331
24570
|
tool: "cursor",
|
|
24332
24571
|
label: "Cursor",
|
|
24333
|
-
configPath:
|
|
24572
|
+
configPath: join54(cursorBackend.homeDir(), "hooks.json"),
|
|
24334
24573
|
homeDir: cursorBackend.homeDir(),
|
|
24335
24574
|
note: "Cursor checks a shell command before it runs and a file edit after it is written."
|
|
24336
24575
|
},
|
|
24337
24576
|
{
|
|
24338
24577
|
tool: "opencode",
|
|
24339
24578
|
label: "OpenCode",
|
|
24340
|
-
configPath:
|
|
24579
|
+
configPath: join54(opencodePluginDir(), "chat-recall-guard.js"),
|
|
24341
24580
|
homeDir: opencodeConfigDir(),
|
|
24342
24581
|
note: "OpenCode plugin hooks do not fire for subagent tool calls, so a delegating agent bypasses this."
|
|
24343
24582
|
}
|
|
@@ -24760,8 +24999,8 @@ __export(collector_exports, {
|
|
|
24760
24999
|
});
|
|
24761
25000
|
import { spawn as spawn3 } from "node:child_process";
|
|
24762
25001
|
import { execSync as execSync4 } from "node:child_process";
|
|
24763
|
-
import { readFileSync as
|
|
24764
|
-
import { join as
|
|
25002
|
+
import { readFileSync as readFileSync44 } from "node:fs";
|
|
25003
|
+
import { join as join55, basename as basename26 } from "node:path";
|
|
24765
25004
|
async function resolveCodeindexBin(autoInstall = true) {
|
|
24766
25005
|
let st = checkCodeindexStatus();
|
|
24767
25006
|
if (!st.installed && autoInstall)
|
|
@@ -24943,7 +25182,7 @@ async function collectCode(opts) {
|
|
|
24943
25182
|
}
|
|
24944
25183
|
const complexity = (r) => {
|
|
24945
25184
|
try {
|
|
24946
|
-
const txt =
|
|
25185
|
+
const txt = readFileSync44(join55(ws, r), "utf8");
|
|
24947
25186
|
if (txt.length > 2e6)
|
|
24948
25187
|
return 1;
|
|
24949
25188
|
const m = txt.match(CF_RE);
|
|
@@ -25727,8 +25966,8 @@ __export(project_tasks_exports, {
|
|
|
25727
25966
|
pushProjectTaskStatuses: () => pushProjectTaskStatuses,
|
|
25728
25967
|
renderTeamTasksMd: () => renderTeamTasksMd
|
|
25729
25968
|
});
|
|
25730
|
-
import { existsSync as existsSync51, readFileSync as
|
|
25731
|
-
import { join as
|
|
25969
|
+
import { existsSync as existsSync51, readFileSync as readFileSync45, writeFileSync as writeFileSync18, mkdirSync as mkdirSync18, statSync as statSync44 } from "node:fs";
|
|
25970
|
+
import { join as join56, dirname as dirname25 } from "node:path";
|
|
25732
25971
|
import { homedir as homedir21 } from "node:os";
|
|
25733
25972
|
function isTeamTaskStatus(v) {
|
|
25734
25973
|
return !!v && TEAM_STATUSES.has(v);
|
|
@@ -25779,11 +26018,11 @@ function parseTaskFile(content) {
|
|
|
25779
26018
|
return out;
|
|
25780
26019
|
}
|
|
25781
26020
|
function ledgerPath2() {
|
|
25782
|
-
return
|
|
26021
|
+
return join56(homedir21(), ".chat-recall", "project-tasks-ledger.json");
|
|
25783
26022
|
}
|
|
25784
26023
|
function readLedger() {
|
|
25785
26024
|
try {
|
|
25786
|
-
return JSON.parse(
|
|
26025
|
+
return JSON.parse(readFileSync45(ledgerPath2(), "utf8"));
|
|
25787
26026
|
} catch {
|
|
25788
26027
|
return {};
|
|
25789
26028
|
}
|
|
@@ -25812,18 +26051,18 @@ async function pushProjectTaskStatuses(base4, authHeaders, opts = {}) {
|
|
|
25812
26051
|
continue;
|
|
25813
26052
|
}
|
|
25814
26053
|
for (const project of projects) {
|
|
25815
|
-
const file =
|
|
26054
|
+
const file = join56(project, fk.filename);
|
|
25816
26055
|
if (!existsSync51(file)) continue;
|
|
25817
26056
|
let mtime;
|
|
25818
26057
|
try {
|
|
25819
|
-
mtime =
|
|
26058
|
+
mtime = statSync44(file).mtimeMs;
|
|
25820
26059
|
} catch {
|
|
25821
26060
|
continue;
|
|
25822
26061
|
}
|
|
25823
26062
|
if (ledger[file] === mtime) continue;
|
|
25824
26063
|
let changed;
|
|
25825
26064
|
try {
|
|
25826
|
-
changed = parseTaskFile(
|
|
26065
|
+
changed = parseTaskFile(readFileSync45(file, "utf8")).filter((t) => t.kind === fk.kind);
|
|
25827
26066
|
} catch {
|
|
25828
26067
|
continue;
|
|
25829
26068
|
}
|
|
@@ -25895,8 +26134,8 @@ __export(intent_drain_exports, {
|
|
|
25895
26134
|
drainSyncIntents: () => drainSyncIntents,
|
|
25896
26135
|
instructionTargets: () => instructionTargets
|
|
25897
26136
|
});
|
|
25898
|
-
import { existsSync as existsSync52, readFileSync as
|
|
25899
|
-
import { join as
|
|
26137
|
+
import { existsSync as existsSync52, readFileSync as readFileSync46, writeFileSync as writeFileSync19, appendFileSync, mkdirSync as mkdirSync19 } from "node:fs";
|
|
26138
|
+
import { join as join57 } from "node:path";
|
|
25900
26139
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
25901
26140
|
import { dirname as dirname26 } from "node:path";
|
|
25902
26141
|
function instructionTargets(rootPath, isGlobal) {
|
|
@@ -25910,16 +26149,16 @@ function instructionTargets(rootPath, isGlobal) {
|
|
|
25910
26149
|
const tools = installed.length ? installed : [INSTRUCTION_TOOLS[0]];
|
|
25911
26150
|
if (isGlobal) return [...new Set(tools.map((t) => instructionsPath(t.id)))];
|
|
25912
26151
|
if (!rootPath) return [];
|
|
25913
|
-
const present = INSTRUCTION_FILENAMES.map((f) =>
|
|
26152
|
+
const present = INSTRUCTION_FILENAMES.map((f) => join57(rootPath, f)).filter((p) => existsSync52(p));
|
|
25914
26153
|
if (present.length) return present;
|
|
25915
|
-
return [...new Set(tools.map((t) =>
|
|
26154
|
+
return [...new Set(tools.map((t) => join57(rootPath, instructionsFilename(t.id))))];
|
|
25916
26155
|
}
|
|
25917
26156
|
function applyCodeRecommendation(intent) {
|
|
25918
26157
|
try {
|
|
25919
26158
|
const meta = JSON.parse(intent.name || "{}");
|
|
25920
26159
|
if (intent.artifact_type === "write_tasks_file") {
|
|
25921
26160
|
if (!meta.rootPath || !meta.content) return { status: "error", result: JSON.stringify({ error: "missing rootPath or content" }) };
|
|
25922
|
-
const file =
|
|
26161
|
+
const file = join57(meta.rootPath, meta.filename || "CODE_TASKS.md");
|
|
25923
26162
|
writeFileSync19(file, meta.content);
|
|
25924
26163
|
return { status: "done", result: JSON.stringify({ wrote: file }) };
|
|
25925
26164
|
}
|
|
@@ -25938,7 +26177,7 @@ function applyCodeRecommendation(intent) {
|
|
|
25938
26177
|
mkdirSync19(dir, { recursive: true });
|
|
25939
26178
|
} catch {
|
|
25940
26179
|
}
|
|
25941
|
-
const existing = existsSync52(file) ?
|
|
26180
|
+
const existing = existsSync52(file) ? readFileSync46(file, "utf8") : "";
|
|
25942
26181
|
if (existing.includes(text)) {
|
|
25943
26182
|
skipped.push(file);
|
|
25944
26183
|
continue;
|
|
@@ -26113,10 +26352,10 @@ var init_intent_drain = __esm({
|
|
|
26113
26352
|
ownVersion2 = "0.0.0";
|
|
26114
26353
|
try {
|
|
26115
26354
|
const dir = dirname26(fileURLToPath4(import.meta.url));
|
|
26116
|
-
ownVersion2 = JSON.parse(
|
|
26355
|
+
ownVersion2 = JSON.parse(readFileSync46(join57(dir, "../package.json"), "utf-8")).version || ownVersion2;
|
|
26117
26356
|
} catch {
|
|
26118
26357
|
try {
|
|
26119
|
-
if (true) ownVersion2 = "0.7.
|
|
26358
|
+
if (true) ownVersion2 = "0.7.18";
|
|
26120
26359
|
} catch {
|
|
26121
26360
|
}
|
|
26122
26361
|
}
|
|
@@ -26317,48 +26556,48 @@ var team_merge_exports = {};
|
|
|
26317
26556
|
__export(team_merge_exports, {
|
|
26318
26557
|
mergePullResult: () => mergePullResult
|
|
26319
26558
|
});
|
|
26320
|
-
import { existsSync as existsSync53, mkdirSync as mkdirSync20, readFileSync as
|
|
26321
|
-
import { dirname as dirname27, join as
|
|
26559
|
+
import { existsSync as existsSync53, mkdirSync as mkdirSync20, readFileSync as readFileSync47, rmSync as rmSync9, writeFileSync as writeFileSync20, statSync as statSync45 } from "fs";
|
|
26560
|
+
import { dirname as dirname27, join as join58 } from "path";
|
|
26322
26561
|
import { createHash as createHash14 } from "crypto";
|
|
26323
26562
|
function installPathFor(art, tool) {
|
|
26324
26563
|
switch (art.type) {
|
|
26325
26564
|
case "skill":
|
|
26326
26565
|
switch (tool) {
|
|
26327
26566
|
case "claude":
|
|
26328
|
-
return
|
|
26567
|
+
return join58(claudeBackend.skillsDir(), art.name, "SKILL.md");
|
|
26329
26568
|
// Antigravity's OWN skills dir. It used to resolve to the shared
|
|
26330
26569
|
// ~/.gemini/skills while toolkit-sync installed to
|
|
26331
26570
|
// ~/.gemini/antigravity-cli/skills, so a team skill landed in one place
|
|
26332
26571
|
// and a synced skill in the other.
|
|
26333
26572
|
case "agy":
|
|
26334
|
-
return
|
|
26573
|
+
return join58(agyBackend.homeDir(), "skills", art.name, "SKILL.md");
|
|
26335
26574
|
case "opencode":
|
|
26336
|
-
return
|
|
26575
|
+
return join58(opencodeBackend.skillsDir(), art.name, "SKILL.md");
|
|
26337
26576
|
// User skills go to ~/.codex/skills (NOT .system, which is OpenAI's bundle).
|
|
26338
26577
|
case "codex":
|
|
26339
|
-
return
|
|
26578
|
+
return join58(codexBackend.skillsDir(), art.name, "SKILL.md");
|
|
26340
26579
|
case "cursor":
|
|
26341
|
-
return
|
|
26580
|
+
return join58(cursorHomeDir(), "skills", art.name, "SKILL.md");
|
|
26342
26581
|
}
|
|
26343
26582
|
break;
|
|
26344
26583
|
case "agent":
|
|
26345
26584
|
if (tool === "claude")
|
|
26346
|
-
return
|
|
26585
|
+
return join58(claudeBackend.agentsDir(), `${art.name}.md`);
|
|
26347
26586
|
return null;
|
|
26348
26587
|
case "command":
|
|
26349
26588
|
if (tool === "claude")
|
|
26350
|
-
return
|
|
26589
|
+
return join58(claudeBackend.commandsDir(), `${art.name}.md`);
|
|
26351
26590
|
return null;
|
|
26352
26591
|
case "hook":
|
|
26353
26592
|
if (tool === "claude")
|
|
26354
|
-
return
|
|
26593
|
+
return join58(claudeBackend.homeDir(), "chat-recall-hooks", `${art.name}.json`);
|
|
26355
26594
|
return null;
|
|
26356
26595
|
case "plan":
|
|
26357
26596
|
switch (tool) {
|
|
26358
26597
|
case "claude":
|
|
26359
|
-
return
|
|
26598
|
+
return join58(claudeBackend.plansDir(), `${art.name}.md`);
|
|
26360
26599
|
case "opencode":
|
|
26361
|
-
return
|
|
26600
|
+
return join58(opencodeBackend.plansDir(), `${art.name}.md`);
|
|
26362
26601
|
case "agy":
|
|
26363
26602
|
return null;
|
|
26364
26603
|
// Antigravity plans live per-session
|
|
@@ -26369,11 +26608,11 @@ function installPathFor(art, tool) {
|
|
|
26369
26608
|
}
|
|
26370
26609
|
break;
|
|
26371
26610
|
case "instructions":
|
|
26372
|
-
return
|
|
26611
|
+
return join58(getDataDir(), "team-instructions", tool, `${art.name}.md`);
|
|
26373
26612
|
case "mcp":
|
|
26374
|
-
return
|
|
26613
|
+
return join58(getDataDir(), "team-mcps", `${art.name}.json`);
|
|
26375
26614
|
case "plugin":
|
|
26376
|
-
return
|
|
26615
|
+
return join58(getDataDir(), "team-plugins", tool, art.name, "manifest.json");
|
|
26377
26616
|
}
|
|
26378
26617
|
return null;
|
|
26379
26618
|
}
|
|
@@ -26435,7 +26674,7 @@ async function mergePullResult(opts) {
|
|
|
26435
26674
|
continue;
|
|
26436
26675
|
try {
|
|
26437
26676
|
if (existsSync53(path))
|
|
26438
|
-
|
|
26677
|
+
rmSync9(path, { force: true });
|
|
26439
26678
|
await teamInstallsForget(id, row.tool);
|
|
26440
26679
|
report.removed.push({ artifactId: id, path });
|
|
26441
26680
|
} catch (err) {
|
|
@@ -26454,10 +26693,10 @@ function readFileIfExists(path) {
|
|
|
26454
26693
|
try {
|
|
26455
26694
|
if (!existsSync53(path))
|
|
26456
26695
|
return null;
|
|
26457
|
-
const s =
|
|
26696
|
+
const s = statSync45(path);
|
|
26458
26697
|
if (!s.isFile())
|
|
26459
26698
|
return null;
|
|
26460
|
-
return
|
|
26699
|
+
return readFileSync47(path);
|
|
26461
26700
|
} catch {
|
|
26462
26701
|
return null;
|
|
26463
26702
|
}
|
|
@@ -26538,8 +26777,8 @@ var init_vault_crypto = __esm({
|
|
|
26538
26777
|
});
|
|
26539
26778
|
|
|
26540
26779
|
// ../engine/dist/core/vault-source.js
|
|
26541
|
-
import { existsSync as existsSync54, readdirSync as readdirSync33, statSync as
|
|
26542
|
-
import { extname, join as
|
|
26780
|
+
import { existsSync as existsSync54, readdirSync as readdirSync33, statSync as statSync46 } from "fs";
|
|
26781
|
+
import { extname, join as join59 } from "path";
|
|
26543
26782
|
function* walkVaultSources() {
|
|
26544
26783
|
const t = loadSettings().team.vault;
|
|
26545
26784
|
const include2 = new Set(t.syncTools);
|
|
@@ -26554,7 +26793,7 @@ function* walkVaultSources() {
|
|
|
26554
26793
|
}
|
|
26555
26794
|
function safeStat(path) {
|
|
26556
26795
|
try {
|
|
26557
|
-
const s =
|
|
26796
|
+
const s = statSync46(path);
|
|
26558
26797
|
if (!s.isFile())
|
|
26559
26798
|
return null;
|
|
26560
26799
|
return { mtimeMs: s.mtimeMs, size: s.size };
|
|
@@ -26576,7 +26815,7 @@ function* walkClaude() {
|
|
|
26576
26815
|
if (proj.startsWith("."))
|
|
26577
26816
|
continue;
|
|
26578
26817
|
const projectPath = resolveProjectDirName(proj);
|
|
26579
|
-
const projDir =
|
|
26818
|
+
const projDir = join59(root, proj);
|
|
26580
26819
|
let entries = [];
|
|
26581
26820
|
try {
|
|
26582
26821
|
entries = readdirSync33(projDir);
|
|
@@ -26586,7 +26825,7 @@ function* walkClaude() {
|
|
|
26586
26825
|
for (const f of entries) {
|
|
26587
26826
|
if (extname(f) !== ".jsonl")
|
|
26588
26827
|
continue;
|
|
26589
|
-
const path =
|
|
26828
|
+
const path = join59(projDir, f);
|
|
26590
26829
|
const s = safeStat(path);
|
|
26591
26830
|
if (!s)
|
|
26592
26831
|
continue;
|
|
@@ -26616,7 +26855,7 @@ function* walkCursor() {
|
|
|
26616
26855
|
}
|
|
26617
26856
|
}
|
|
26618
26857
|
function* walkCodex() {
|
|
26619
|
-
const sessionsRoot =
|
|
26858
|
+
const sessionsRoot = join59(codexBackend.homeDir(), "sessions");
|
|
26620
26859
|
if (!existsSync54(sessionsRoot))
|
|
26621
26860
|
return;
|
|
26622
26861
|
const stack = [sessionsRoot];
|
|
@@ -26629,7 +26868,7 @@ function* walkCodex() {
|
|
|
26629
26868
|
continue;
|
|
26630
26869
|
}
|
|
26631
26870
|
for (const e of entries) {
|
|
26632
|
-
const path =
|
|
26871
|
+
const path = join59(dir, e.name);
|
|
26633
26872
|
if (e.isDirectory()) {
|
|
26634
26873
|
stack.push(path);
|
|
26635
26874
|
continue;
|
|
@@ -26645,7 +26884,7 @@ function* walkCodex() {
|
|
|
26645
26884
|
}
|
|
26646
26885
|
}
|
|
26647
26886
|
function* walkAgy() {
|
|
26648
|
-
const brainDir =
|
|
26887
|
+
const brainDir = join59(agyBackend.homeDir(), "brain");
|
|
26649
26888
|
if (!existsSync54(brainDir))
|
|
26650
26889
|
return;
|
|
26651
26890
|
let sessionDirs = [];
|
|
@@ -26655,16 +26894,16 @@ function* walkAgy() {
|
|
|
26655
26894
|
return;
|
|
26656
26895
|
}
|
|
26657
26896
|
for (const rawId of sessionDirs) {
|
|
26658
|
-
const sessionPath =
|
|
26897
|
+
const sessionPath = join59(brainDir, rawId);
|
|
26659
26898
|
try {
|
|
26660
|
-
if (!
|
|
26899
|
+
if (!statSync46(sessionPath).isDirectory())
|
|
26661
26900
|
continue;
|
|
26662
26901
|
} catch {
|
|
26663
26902
|
continue;
|
|
26664
26903
|
}
|
|
26665
|
-
let filePath =
|
|
26904
|
+
let filePath = join59(sessionPath, ".system_generated", "logs", "transcript.jsonl");
|
|
26666
26905
|
if (!existsSync54(filePath)) {
|
|
26667
|
-
filePath =
|
|
26906
|
+
filePath = join59(sessionPath, ".system_generated", "logs", "transcript_full.jsonl");
|
|
26668
26907
|
}
|
|
26669
26908
|
if (!existsSync54(filePath))
|
|
26670
26909
|
continue;
|
|
@@ -26702,8 +26941,8 @@ __export(vault_client_exports, {
|
|
|
26702
26941
|
vaultStatus: () => vaultStatus,
|
|
26703
26942
|
vaultSync: () => vaultSync
|
|
26704
26943
|
});
|
|
26705
|
-
import { mkdirSync as mkdirSync21, readFileSync as
|
|
26706
|
-
import { dirname as dirname28, join as
|
|
26944
|
+
import { mkdirSync as mkdirSync21, readFileSync as readFileSync48, writeFileSync as writeFileSync21, existsSync as existsSync55 } from "fs";
|
|
26945
|
+
import { dirname as dirname28, join as join60 } from "path";
|
|
26707
26946
|
function context2() {
|
|
26708
26947
|
const s = loadSettings().team;
|
|
26709
26948
|
if (!s.enabled)
|
|
@@ -26842,7 +27081,7 @@ async function vaultSync(passphrase) {
|
|
|
26842
27081
|
continue;
|
|
26843
27082
|
}
|
|
26844
27083
|
try {
|
|
26845
|
-
const plaintext =
|
|
27084
|
+
const plaintext = readFileSync48(src.path);
|
|
26846
27085
|
const sourceSha = sha256Hex(plaintext);
|
|
26847
27086
|
const priorSha = uploaded.get(uploadKey(src.sessionId, src.tool));
|
|
26848
27087
|
if (priorSha === sourceSha) {
|
|
@@ -26894,7 +27133,7 @@ async function vaultSync(passphrase) {
|
|
|
26894
27133
|
}
|
|
26895
27134
|
function importedPathFor(tool, sessionId) {
|
|
26896
27135
|
const base4 = sessionId.replace(/^gemini_/, "").replace(/^codex_/, "").replace(/^agy_/, "").replace(/^cursor_/, "").replace(/^opencode_/, "");
|
|
26897
|
-
return
|
|
27136
|
+
return join60(IMPORTED_ROOT(), tool, `${base4}.jsonl`);
|
|
26898
27137
|
}
|
|
26899
27138
|
async function vaultRestore(passphrase, opts = {}) {
|
|
26900
27139
|
const ctx = context2();
|
|
@@ -26983,7 +27222,7 @@ var init_vault_client = __esm({
|
|
|
26983
27222
|
uploadKey = (sessionId, tool) => `${sessionId}\0${tool}`;
|
|
26984
27223
|
VaultPassphraseMismatchError = class extends Error {
|
|
26985
27224
|
};
|
|
26986
|
-
IMPORTED_ROOT = () =>
|
|
27225
|
+
IMPORTED_ROOT = () => join60(getDataDir(), "imported");
|
|
26987
27226
|
}
|
|
26988
27227
|
});
|
|
26989
27228
|
|
|
@@ -27545,15 +27784,15 @@ __export(service_installer_exports, {
|
|
|
27545
27784
|
uninstallService: () => uninstallService
|
|
27546
27785
|
});
|
|
27547
27786
|
import { execSync as execSync5 } from "child_process";
|
|
27548
|
-
import { existsSync as existsSync56, mkdirSync as mkdirSync22, readFileSync as
|
|
27787
|
+
import { existsSync as existsSync56, mkdirSync as mkdirSync22, readFileSync as readFileSync49, rmSync as rmSync10, writeFileSync as writeFileSync22 } from "fs";
|
|
27549
27788
|
import { homedir as homedir22 } from "os";
|
|
27550
|
-
import { join as
|
|
27789
|
+
import { join as join61 } from "path";
|
|
27551
27790
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
27552
27791
|
function resolveDaemonPaths() {
|
|
27553
27792
|
const watchJs = fileURLToPath5(new URL("./watch.js", import.meta.url));
|
|
27554
27793
|
const node = process.execPath;
|
|
27555
|
-
const dataDir =
|
|
27556
|
-
const logFile =
|
|
27794
|
+
const dataDir = join61(homedir22(), ".chat-recall");
|
|
27795
|
+
const logFile = join61(dataDir, "watch.log");
|
|
27557
27796
|
return { watchJs, node, logFile, dataDir };
|
|
27558
27797
|
}
|
|
27559
27798
|
function tryCmd(cmd) {
|
|
@@ -27580,12 +27819,12 @@ function refreshServiceDefinition() {
|
|
|
27580
27819
|
if (process.platform !== "linux") return false;
|
|
27581
27820
|
try {
|
|
27582
27821
|
const { watchJs, node, logFile } = resolveDaemonPaths();
|
|
27583
|
-
const unitPath =
|
|
27822
|
+
const unitPath = join61(homedir22(), ".config", "systemd", "user", "chat-recall-watch.service");
|
|
27584
27823
|
if (!existsSync56(unitPath)) return false;
|
|
27585
|
-
const current =
|
|
27824
|
+
const current = readFileSync49(unitPath, "utf8");
|
|
27586
27825
|
if (!current.includes(watchJs)) return false;
|
|
27587
27826
|
const wanted = renderSystemdUnit(watchJs, node, logFile);
|
|
27588
|
-
if (
|
|
27827
|
+
if (readFileSync49(unitPath, "utf8") === wanted) return false;
|
|
27589
27828
|
writeFileSync22(unitPath, wanted);
|
|
27590
27829
|
execSync5("systemctl --user daemon-reload", { stdio: "ignore" });
|
|
27591
27830
|
return true;
|
|
@@ -27611,8 +27850,8 @@ function installService() {
|
|
|
27611
27850
|
);
|
|
27612
27851
|
}
|
|
27613
27852
|
function installSystemd(watchJs, node, logFile) {
|
|
27614
|
-
const unitDir =
|
|
27615
|
-
const unitPath =
|
|
27853
|
+
const unitDir = join61(homedir22(), ".config", "systemd", "user");
|
|
27854
|
+
const unitPath = join61(unitDir, "chat-recall-watch.service");
|
|
27616
27855
|
const unit = renderSystemdUnit(watchJs, node, logFile);
|
|
27617
27856
|
mkdirSync22(unitDir, { recursive: true });
|
|
27618
27857
|
writeFileSync22(unitPath, unit);
|
|
@@ -27691,8 +27930,8 @@ function renderSystemdUnit(watchJs, node, logFile) {
|
|
|
27691
27930
|
}
|
|
27692
27931
|
function installLaunchd(watchJs, node, logFile) {
|
|
27693
27932
|
const label = "com.chat-recall.watch";
|
|
27694
|
-
const plistDir =
|
|
27695
|
-
const plistPath =
|
|
27933
|
+
const plistDir = join61(homedir22(), "Library", "LaunchAgents");
|
|
27934
|
+
const plistPath = join61(plistDir, `${label}.plist`);
|
|
27696
27935
|
const plist = renderLaunchdPlist(watchJs, node, logFile, label);
|
|
27697
27936
|
mkdirSync22(plistDir, { recursive: true });
|
|
27698
27937
|
writeFileSync22(plistPath, plist);
|
|
@@ -27748,9 +27987,9 @@ function uninstallService() {
|
|
|
27748
27987
|
removed = true;
|
|
27749
27988
|
} catch {
|
|
27750
27989
|
}
|
|
27751
|
-
const unitPath =
|
|
27990
|
+
const unitPath = join61(homedir22(), ".config", "systemd", "user", "chat-recall-watch.service");
|
|
27752
27991
|
if (existsSync56(unitPath)) {
|
|
27753
|
-
|
|
27992
|
+
rmSync10(unitPath, { force: true });
|
|
27754
27993
|
removed = true;
|
|
27755
27994
|
}
|
|
27756
27995
|
try {
|
|
@@ -27760,14 +27999,14 @@ function uninstallService() {
|
|
|
27760
27999
|
return removed;
|
|
27761
28000
|
}
|
|
27762
28001
|
if (process.platform === "darwin") {
|
|
27763
|
-
const plistPath =
|
|
28002
|
+
const plistPath = join61(homedir22(), "Library", "LaunchAgents", "com.chat-recall.watch.plist");
|
|
27764
28003
|
try {
|
|
27765
28004
|
execSync5(`launchctl unload "${plistPath}" 2>/dev/null`, { stdio: "ignore" });
|
|
27766
28005
|
} catch {
|
|
27767
28006
|
}
|
|
27768
28007
|
let removed = false;
|
|
27769
28008
|
if (existsSync56(plistPath)) {
|
|
27770
|
-
|
|
28009
|
+
rmSync10(plistPath, { force: true });
|
|
27771
28010
|
removed = true;
|
|
27772
28011
|
}
|
|
27773
28012
|
return removed;
|
|
@@ -27811,7 +28050,7 @@ __export(device_auth_exports, {
|
|
|
27811
28050
|
betterAuthDeviceLogin: () => betterAuthDeviceLogin,
|
|
27812
28051
|
deviceLogin: () => deviceLogin
|
|
27813
28052
|
});
|
|
27814
|
-
import { createHash as createHash15, randomBytes } from "node:crypto";
|
|
28053
|
+
import { createHash as createHash15, randomBytes as randomBytes2 } from "node:crypto";
|
|
27815
28054
|
async function readDeviceCode(res, where) {
|
|
27816
28055
|
const text = await res.text().catch(() => "");
|
|
27817
28056
|
let parsed;
|
|
@@ -27839,7 +28078,7 @@ async function deviceLogin(opts, onPrompt) {
|
|
|
27839
28078
|
}
|
|
27840
28079
|
const clientId = opts.clientId || DEFAULT_CLIENT_ID;
|
|
27841
28080
|
const scope = opts.scope || "openid email profile";
|
|
27842
|
-
const codeVerifier = b64url(
|
|
28081
|
+
const codeVerifier = b64url(randomBytes2(32));
|
|
27843
28082
|
const codeChallenge = b64url(createHash15("sha256").update(codeVerifier).digest());
|
|
27844
28083
|
const startRes = await fetch(`${issuer}/protocol/openid-connect/auth/device`, {
|
|
27845
28084
|
method: "POST",
|
|
@@ -28289,9 +28528,9 @@ init_project_resolver();
|
|
|
28289
28528
|
import { config } from "dotenv";
|
|
28290
28529
|
import { Command } from "commander";
|
|
28291
28530
|
import chalk2 from "chalk";
|
|
28292
|
-
import { existsSync as existsSync57, readFileSync as
|
|
28531
|
+
import { existsSync as existsSync57, readFileSync as readFileSync50, writeFileSync as writeFileSync23, realpathSync as realpathSync5 } from "fs";
|
|
28293
28532
|
import { homedir as homedir23 } from "os";
|
|
28294
|
-
import { join as
|
|
28533
|
+
import { join as join62, resolve as resolve2, dirname as dirname29, basename as basename27 } from "path";
|
|
28295
28534
|
|
|
28296
28535
|
// ../engine/dist/core/score-tier.js
|
|
28297
28536
|
var STRONG_RATIO = 0.85;
|
|
@@ -28399,10 +28638,10 @@ function renderEnvNeeds(needs, installedCount) {
|
|
|
28399
28638
|
// src/star-nudge.ts
|
|
28400
28639
|
init_paths();
|
|
28401
28640
|
import { existsSync as existsSync43, mkdirSync as mkdirSync11, writeFileSync as writeFileSync11 } from "node:fs";
|
|
28402
|
-
import { dirname as dirname20, join as
|
|
28641
|
+
import { dirname as dirname20, join as join46 } from "node:path";
|
|
28403
28642
|
var REPO = "https://github.com/munhq/chat-recall";
|
|
28404
28643
|
function markerPath() {
|
|
28405
|
-
return
|
|
28644
|
+
return join46(getDataDir(), ".star-asked");
|
|
28406
28645
|
}
|
|
28407
28646
|
function suppressed() {
|
|
28408
28647
|
const env = process.env;
|
|
@@ -28455,8 +28694,8 @@ function claudeHookConfigFiles() {
|
|
|
28455
28694
|
const out = [];
|
|
28456
28695
|
const seen = /* @__PURE__ */ new Set();
|
|
28457
28696
|
for (const home of claudeHomeDirs()) {
|
|
28458
|
-
if (!existsSync57(
|
|
28459
|
-
const file =
|
|
28697
|
+
if (!existsSync57(join62(home, "projects"))) continue;
|
|
28698
|
+
const file = join62(home, "hooks.json");
|
|
28460
28699
|
let key2;
|
|
28461
28700
|
try {
|
|
28462
28701
|
key2 = realpathSync5(file);
|
|
@@ -28551,13 +28790,13 @@ async function serverDelete(path, body2) {
|
|
|
28551
28790
|
}
|
|
28552
28791
|
var pkgEngines = (() => {
|
|
28553
28792
|
try {
|
|
28554
|
-
return JSON.parse(
|
|
28793
|
+
return JSON.parse(readFileSync50(new URL("../package.json", import.meta.url), "utf-8")).engines?.node ?? "";
|
|
28555
28794
|
} catch {
|
|
28556
28795
|
return "";
|
|
28557
28796
|
}
|
|
28558
28797
|
})();
|
|
28559
28798
|
var pkgVersion = JSON.parse(
|
|
28560
|
-
|
|
28799
|
+
readFileSync50(new URL("../package.json", import.meta.url), "utf-8")
|
|
28561
28800
|
).version;
|
|
28562
28801
|
var DEFAULT_SERVER = (process.env.CHAT_RECALL_DEFAULT_SERVER || "https://chatrecall.dev").replace(/\/+$/, "");
|
|
28563
28802
|
var DEFAULT_ALLOW = [
|
|
@@ -28731,10 +28970,10 @@ program.command("init").description("Set up chat-recall: connect to your server,
|
|
|
28731
28970
|
} else if (target) {
|
|
28732
28971
|
}
|
|
28733
28972
|
if (!options.skipMcp) {
|
|
28734
|
-
const projectRoot =
|
|
28973
|
+
const projectRoot = join62(import.meta.dirname, "..");
|
|
28735
28974
|
let mcpBinOnPath = false;
|
|
28736
28975
|
mcpBinOnPath = isOnPath("chat-recall-mcp");
|
|
28737
|
-
const launch = mcpBinOnPath ? { command: "chat-recall-mcp" } : { command: "node", args: [
|
|
28976
|
+
const launch = mcpBinOnPath ? { command: "chat-recall-mcp" } : { command: "node", args: [join62(projectRoot, "dist", "mcp-relay.js")] };
|
|
28738
28977
|
const MCP_ENV = { NODE_OPTIONS: "--max-old-space-size=1024" };
|
|
28739
28978
|
const { registerMcpEverywhere: registerMcpEverywhere2 } = await Promise.resolve().then(() => (init_mcp_clients(), mcp_clients_exports));
|
|
28740
28979
|
const MCP_CLIENT_FOR_BIN = {
|
|
@@ -28774,7 +29013,7 @@ program.command("init").description("Set up chat-recall: connect to your server,
|
|
|
28774
29013
|
const detected = checkCodeindexStatus2();
|
|
28775
29014
|
if (detected.installed && !forceInstall) {
|
|
28776
29015
|
if (!options.skipMcp) {
|
|
28777
|
-
const mcpJsonPath =
|
|
29016
|
+
const mcpJsonPath = join62(homedir23(), ".mcp.json");
|
|
28778
29017
|
const reg = registerCodeindexMcp2(mcpJsonPath, detected.path);
|
|
28779
29018
|
}
|
|
28780
29019
|
} else if (forceInstall) {
|
|
@@ -28783,7 +29022,7 @@ program.command("init").description("Set up chat-recall: connect to your server,
|
|
|
28783
29022
|
if (result.installed) {
|
|
28784
29023
|
const sizeMb = result.size ? `${(result.size / 1024 / 1024).toFixed(1)} MB` : "?";
|
|
28785
29024
|
if (!options.skipMcp) {
|
|
28786
|
-
const mcpJsonPath =
|
|
29025
|
+
const mcpJsonPath = join62(homedir23(), ".mcp.json");
|
|
28787
29026
|
const reg = registerCodeindexMcp2(mcpJsonPath, CODEINDEX_BIN_PATH2);
|
|
28788
29027
|
}
|
|
28789
29028
|
} else if (!result.prebuiltAvailable) {
|
|
@@ -29241,7 +29480,7 @@ memory.command("wake-up").description("Generate wake-up context (high-importance
|
|
|
29241
29480
|
const identityFile = getIdentityFilePath();
|
|
29242
29481
|
let identity = "AI coding assistant";
|
|
29243
29482
|
if (existsSync57(identityFile)) {
|
|
29244
|
-
identity =
|
|
29483
|
+
identity = readFileSync50(identityFile, "utf-8").trim();
|
|
29245
29484
|
}
|
|
29246
29485
|
const lines = [
|
|
29247
29486
|
chalk2.bold("# Wake-Up Context"),
|
|
@@ -29341,7 +29580,7 @@ program.command("feedback").argument("<message...>", "what you want to say \u201
|
|
|
29341
29580
|
}
|
|
29342
29581
|
});
|
|
29343
29582
|
program.command("doctor").description("Quick health check across login, server, credentials, hooks, MCP server, and codeindex").option("--purge-local", "Remove the legacy local index (cache.db + vector/KG files) left by pre-thin-collector versions \u2014 storage is server-side now. Requires login; keeps credentials, sync ledger, identity, and the audit log.").action(async (opts) => {
|
|
29344
|
-
const { existsSync: existsSync58, readFileSync:
|
|
29583
|
+
const { existsSync: existsSync58, readFileSync: readFileSync51, statSync: statSync47 } = await import("fs");
|
|
29345
29584
|
const { execSync: execSync6 } = await import("child_process");
|
|
29346
29585
|
const rows = [];
|
|
29347
29586
|
const note = (ok, label, detail) => rows.push({ ok, label, detail });
|
|
@@ -29404,12 +29643,12 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
29404
29643
|
}
|
|
29405
29644
|
}
|
|
29406
29645
|
}
|
|
29407
|
-
const credFile =
|
|
29646
|
+
const credFile = join62(getDataDir(), "credentials.json");
|
|
29408
29647
|
if (!existsSync58(credFile)) {
|
|
29409
29648
|
note(false, "Credentials file", `missing \u2014 run \`chat-recall login <server-url>\``);
|
|
29410
29649
|
} else {
|
|
29411
29650
|
try {
|
|
29412
|
-
const mode =
|
|
29651
|
+
const mode = statSync47(credFile).mode & 511;
|
|
29413
29652
|
const isWin = process.platform === "win32";
|
|
29414
29653
|
const safe = isWin || (mode & 63) === 0;
|
|
29415
29654
|
note(safe, "Credentials file", isWin ? `${credFile} (Windows ACL \u2014 POSIX mode does not apply)` : `${credFile} (mode ${mode.toString(8).padStart(3, "0")}${safe ? "" : " \u2014 should be 600"})`);
|
|
@@ -29428,13 +29667,13 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
29428
29667
|
const readHooks = (file) => {
|
|
29429
29668
|
if (!existsSync58(file)) return {};
|
|
29430
29669
|
try {
|
|
29431
|
-
return JSON.parse(
|
|
29670
|
+
return JSON.parse(readFileSync51(file, "utf-8")).hooks || {};
|
|
29432
29671
|
} catch {
|
|
29433
29672
|
return {};
|
|
29434
29673
|
}
|
|
29435
29674
|
};
|
|
29436
29675
|
const cfg = readHooks(hooksJson);
|
|
29437
|
-
const settings2 = readHooks(
|
|
29676
|
+
const settings2 = readHooks(join62(dirname29(hooksJson), "settings.json"));
|
|
29438
29677
|
const all = ["SessionStart", "UserPromptSubmit", "Stop", "PreCompact", "SessionEnd"];
|
|
29439
29678
|
const hits = [];
|
|
29440
29679
|
for (const ev of all) {
|
|
@@ -29481,7 +29720,7 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
29481
29720
|
}
|
|
29482
29721
|
let registered = false;
|
|
29483
29722
|
try {
|
|
29484
|
-
const cfg = JSON.parse(
|
|
29723
|
+
const cfg = JSON.parse(readFileSync51(target2.configPath, "utf-8"));
|
|
29485
29724
|
registered = JSON.stringify(cfg).includes("chat_recall_guard");
|
|
29486
29725
|
} catch {
|
|
29487
29726
|
}
|
|
@@ -29496,7 +29735,7 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
29496
29735
|
const want = bundledSkillNames2().length;
|
|
29497
29736
|
for (const t of skillTargets2()) {
|
|
29498
29737
|
if (!t.available) continue;
|
|
29499
|
-
const have = want === 0 ? 0 : bundledSkillNames2().filter((n) => existsSync58(
|
|
29738
|
+
const have = want === 0 ? 0 : bundledSkillNames2().filter((n) => existsSync58(join62(t.dir, n, ".chat-recall-managed"))).length;
|
|
29500
29739
|
note(
|
|
29501
29740
|
have === want,
|
|
29502
29741
|
`Skills \u2014 ${t.label}`,
|
|
@@ -29571,12 +29810,12 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
29571
29810
|
note(watchRunning, "Watch daemon", watchRunning ? "running" : "not running (run `chat-recall watch --install-service` to keep collection running)");
|
|
29572
29811
|
const dataDir = getDataDir();
|
|
29573
29812
|
const legacyPaths = [
|
|
29574
|
-
|
|
29575
|
-
|
|
29576
|
-
|
|
29577
|
-
|
|
29578
|
-
|
|
29579
|
-
|
|
29813
|
+
join62(dataDir, "cache.db"),
|
|
29814
|
+
join62(dataDir, "cache.db-wal"),
|
|
29815
|
+
join62(dataDir, "cache.db-shm"),
|
|
29816
|
+
join62(dataDir, "index", "lancedb"),
|
|
29817
|
+
join62(dataDir, "index", "knowledge_graph.db"),
|
|
29818
|
+
join62(dataDir, "index", "metadata.db")
|
|
29580
29819
|
];
|
|
29581
29820
|
const legacyPresent = legacyPaths.filter((p) => existsSync58(p));
|
|
29582
29821
|
if (opts.purgeLocal) {
|
|
@@ -29585,11 +29824,11 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
29585
29824
|
} else if (legacyPresent.length === 0) {
|
|
29586
29825
|
note(true, "Purge legacy index", "nothing to remove");
|
|
29587
29826
|
} else {
|
|
29588
|
-
const { rmSync:
|
|
29827
|
+
const { rmSync: rmSync11 } = await import("fs");
|
|
29589
29828
|
let removed = 0;
|
|
29590
29829
|
for (const p of legacyPresent) {
|
|
29591
29830
|
try {
|
|
29592
|
-
|
|
29831
|
+
rmSync11(p, { recursive: true, force: true });
|
|
29593
29832
|
removed++;
|
|
29594
29833
|
} catch {
|
|
29595
29834
|
}
|
|
@@ -29649,7 +29888,7 @@ companions.command("install").description("Install codeindex (downloads from mun
|
|
|
29649
29888
|
if (result.installed) {
|
|
29650
29889
|
const sizeMb = result.size ? `${(result.size / 1024 / 1024).toFixed(1)} MB` : "?";
|
|
29651
29890
|
console.log(chalk2.green(`\u2713 codeindex installed (${sizeMb}) \u2192 ${result.path}`));
|
|
29652
|
-
const mcpJsonPath =
|
|
29891
|
+
const mcpJsonPath = join62(homedir23(), ".mcp.json");
|
|
29653
29892
|
const reg = registerCodeindexMcp2(mcpJsonPath, CODEINDEX_BIN_PATH2);
|
|
29654
29893
|
if (reg.added) console.log(chalk2.dim(` Registered as MCP server in ${mcpJsonPath}`));
|
|
29655
29894
|
else console.log(chalk2.dim(` Already registered as MCP server`));
|
|
@@ -29671,7 +29910,7 @@ companions.command("uninstall").description("Remove the codeindex binary chat-re
|
|
|
29671
29910
|
const r = uninstallCodeindex2();
|
|
29672
29911
|
if (r.removed) console.log(chalk2.green(`\u2713 Removed ${r.path}`));
|
|
29673
29912
|
else console.log(chalk2.dim(` Nothing to remove at ${r.path}`));
|
|
29674
|
-
const mcpJsonPath =
|
|
29913
|
+
const mcpJsonPath = join62(homedir23(), ".mcp.json");
|
|
29675
29914
|
const u = unregisterCodeindexMcp2(mcpJsonPath);
|
|
29676
29915
|
if (u.removed) console.log(chalk2.dim(` Unregistered MCP server from ${mcpJsonPath}`));
|
|
29677
29916
|
});
|
|
@@ -30223,10 +30462,10 @@ tasks.command("pull [dir]").description("Write TEAM_TASKS.md for your tasks in t
|
|
|
30223
30462
|
try {
|
|
30224
30463
|
const { resolveProjectId: resolveProjectId2 } = await Promise.resolve().then(() => (init_project_resolver(), project_resolver_exports));
|
|
30225
30464
|
const { renderTeamTasksMd: renderTeamTasksMd2, parseTeamTasksFile: parseTeamTasksFile2 } = await Promise.resolve().then(() => (init_project_tasks(), project_tasks_exports));
|
|
30226
|
-
const { writeFileSync: writeFileSync24, readFileSync:
|
|
30227
|
-
const { join:
|
|
30228
|
-
const file =
|
|
30229
|
-
if (!opts.force && existsSync58(file) && parseTeamTasksFile2(
|
|
30465
|
+
const { writeFileSync: writeFileSync24, readFileSync: readFileSync51, existsSync: existsSync58 } = await import("node:fs");
|
|
30466
|
+
const { join: join63 } = await import("node:path");
|
|
30467
|
+
const file = join63(cwd, "TEAM_TASKS.md");
|
|
30468
|
+
if (!opts.force && existsSync58(file) && parseTeamTasksFile2(readFileSync51(file, "utf8")).length > 0) {
|
|
30230
30469
|
console.error(chalk2.red("TEAM_TASKS.md has unpushed edits."), "Run", chalk2.bold("chat-recall tasks push"), "first, or", chalk2.bold("tasks pull --force"), "to discard.");
|
|
30231
30470
|
process.exit(1);
|
|
30232
30471
|
}
|
|
@@ -30245,14 +30484,14 @@ tasks.command("push [dir]").description("Push TEAM_TASKS.md status edits back to
|
|
|
30245
30484
|
const cwd = dir || process.cwd();
|
|
30246
30485
|
try {
|
|
30247
30486
|
const { parseTeamTasksFile: parseTeamTasksFile2 } = await Promise.resolve().then(() => (init_project_tasks(), project_tasks_exports));
|
|
30248
|
-
const { readFileSync:
|
|
30249
|
-
const { join:
|
|
30250
|
-
const file =
|
|
30487
|
+
const { readFileSync: readFileSync51, existsSync: existsSync58 } = await import("node:fs");
|
|
30488
|
+
const { join: join63 } = await import("node:path");
|
|
30489
|
+
const file = join63(cwd, "TEAM_TASKS.md");
|
|
30251
30490
|
if (!existsSync58(file)) {
|
|
30252
30491
|
console.error(chalk2.red("no TEAM_TASKS.md here \u2014"), "run", chalk2.bold("chat-recall tasks pull"), "first");
|
|
30253
30492
|
process.exit(1);
|
|
30254
30493
|
}
|
|
30255
|
-
const edits = parseTeamTasksFile2(
|
|
30494
|
+
const edits = parseTeamTasksFile2(readFileSync51(file, "utf8"));
|
|
30256
30495
|
let n = 0;
|
|
30257
30496
|
for (const e of edits) {
|
|
30258
30497
|
await serverPatch(`/api/tasks/${encodeURIComponent(e.id)}`, { status: e.intent });
|
|
@@ -30358,8 +30597,8 @@ team.command("publish <type> <name> <file>").description("Publish a local file a
|
|
|
30358
30597
|
console.error(chalk2.red(`Invalid tool: ${opts.tool}. Must be one of: ${validTools.join(", ")}`));
|
|
30359
30598
|
process.exit(1);
|
|
30360
30599
|
}
|
|
30361
|
-
const { readFileSync:
|
|
30362
|
-
const body2 =
|
|
30600
|
+
const { readFileSync: readFileSync51 } = await import("fs");
|
|
30601
|
+
const body2 = readFileSync51(file);
|
|
30363
30602
|
const { teamPublish: teamPublish2 } = await Promise.resolve().then(() => (init_team_client(), team_client_exports));
|
|
30364
30603
|
const a = await teamPublish2({
|
|
30365
30604
|
type,
|
|
@@ -30735,18 +30974,18 @@ program.command("task-hook").description("Move a board card when a prompt or a c
|
|
|
30735
30974
|
}
|
|
30736
30975
|
});
|
|
30737
30976
|
program.command("install-hooks").description("Install Claude Code hooks (Stop + PreCompact + UserPromptSubmit + SessionEnd + SessionStart) into every Claude profile").option("--uninstall", "Remove hooks instead of installing them").option("--no-resume-hint", "Don't install the UserPromptSubmit resume-hint hook").option("--no-escalate", "Don't install the SessionEnd learnings-escalation hook").option("--no-wakeup", "Don't install the SessionStart wake-up hook").option("--no-guard", "Don't install the PreToolUse decision guard").option("--no-task-board", "Don't install the hooks that claim and close board cards").action(async (opts) => {
|
|
30738
|
-
const { mkdirSync: mkdirSync23, copyFileSync: copyFileSync4, chmodSync: chmodSync5, existsSync: existsSync58, readFileSync:
|
|
30977
|
+
const { mkdirSync: mkdirSync23, copyFileSync: copyFileSync4, chmodSync: chmodSync5, existsSync: existsSync58, readFileSync: readFileSync51, writeFileSync: writeFileSync24, statSync: statSync47, unlinkSync: unlinkSync4 } = await import("fs");
|
|
30739
30978
|
const { fileURLToPath: fileURLToPath6 } = await import("url");
|
|
30740
30979
|
const { boardHookEntries: boardHookEntries2, isBoardHookEntry: isBoardHookEntry2, registerBoardHooks: registerBoardHooks2, resolveCliEntry: resolveCliEntry2 } = await Promise.resolve().then(() => (init_board_hooks(), board_hooks_exports));
|
|
30741
30980
|
const here = fileURLToPath6(new URL(".", import.meta.url));
|
|
30742
30981
|
const findHook = (name) => {
|
|
30743
30982
|
const candidates2 = [
|
|
30744
|
-
|
|
30745
|
-
|
|
30983
|
+
join62(here, "..", "hooks", name),
|
|
30984
|
+
join62(here, "..", "..", "hooks", name),
|
|
30746
30985
|
// The monorepo root, for a run straight from the checkout. The copy
|
|
30747
30986
|
// under packages/cli/hooks is written by the package build, so a
|
|
30748
30987
|
// freshly added script is only at the root until that build runs.
|
|
30749
|
-
|
|
30988
|
+
join62(here, "..", "..", "..", "hooks", name)
|
|
30750
30989
|
];
|
|
30751
30990
|
return candidates2.find((p) => existsSync58(p));
|
|
30752
30991
|
};
|
|
@@ -30760,16 +30999,16 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
30760
30999
|
process.exit(1);
|
|
30761
31000
|
}
|
|
30762
31001
|
const hooksDir = getHooksDir();
|
|
30763
|
-
const installedSaveHook =
|
|
30764
|
-
const installedGuardHook =
|
|
30765
|
-
const installedResumeHook =
|
|
30766
|
-
const installedEscalateHook =
|
|
30767
|
-
const installedWakeupHook =
|
|
31002
|
+
const installedSaveHook = join62(hooksDir, "chat_recall_save_hook.sh");
|
|
31003
|
+
const installedGuardHook = join62(hooksDir, "chat_recall_guard_hook.sh");
|
|
31004
|
+
const installedResumeHook = join62(hooksDir, "chat_recall_resume_hook.sh");
|
|
31005
|
+
const installedEscalateHook = join62(hooksDir, "chat_recall_escalate_hook.sh");
|
|
31006
|
+
const installedWakeupHook = join62(hooksDir, "chat_recall_wakeup_hook.sh");
|
|
30768
31007
|
const wakeupWiredInSettings = (home) => {
|
|
30769
|
-
const settings2 =
|
|
31008
|
+
const settings2 = join62(home, "settings.json");
|
|
30770
31009
|
if (!existsSync58(settings2)) return false;
|
|
30771
31010
|
try {
|
|
30772
|
-
const cfg = JSON.parse(
|
|
31011
|
+
const cfg = JSON.parse(readFileSync51(settings2, "utf-8"));
|
|
30773
31012
|
const arr = Array.isArray(cfg.hooks?.SessionStart) ? cfg.hooks.SessionStart : [];
|
|
30774
31013
|
return arr.some((h) => (h?.hooks?.[0]?.command || "").includes("chat_recall_wakeup_hook"));
|
|
30775
31014
|
} catch {
|
|
@@ -30780,7 +31019,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
30780
31019
|
const readHookConfig = (file) => {
|
|
30781
31020
|
if (!existsSync58(file)) return { hooks: {} };
|
|
30782
31021
|
try {
|
|
30783
|
-
const c = JSON.parse(
|
|
31022
|
+
const c = JSON.parse(readFileSync51(file, "utf-8"));
|
|
30784
31023
|
if (!c.hooks || typeof c.hooks !== "object") c.hooks = {};
|
|
30785
31024
|
return c;
|
|
30786
31025
|
} catch (err) {
|
|
@@ -30797,7 +31036,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
30797
31036
|
const readJson4 = (file) => {
|
|
30798
31037
|
if (!existsSync58(file)) return {};
|
|
30799
31038
|
try {
|
|
30800
|
-
return JSON.parse(
|
|
31039
|
+
return JSON.parse(readFileSync51(file, "utf-8"));
|
|
30801
31040
|
} catch {
|
|
30802
31041
|
return {};
|
|
30803
31042
|
}
|
|
@@ -30807,7 +31046,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
30807
31046
|
const notes = [];
|
|
30808
31047
|
for (const target of reg.guardTargets()) {
|
|
30809
31048
|
if (!existsSync58(target.homeDir)) continue;
|
|
30810
|
-
const wrapper =
|
|
31049
|
+
const wrapper = join62(hooksDir, reg.guardWrapperName(target.tool));
|
|
30811
31050
|
writeFileSync24(wrapper, reg.guardWrapperSource(target.tool, hookPath));
|
|
30812
31051
|
chmodSync5(wrapper, 493);
|
|
30813
31052
|
mkdirSync23(dirname29(target.configPath), { recursive: true });
|
|
@@ -30829,7 +31068,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
30829
31068
|
for (const target of reg.guardTargets()) {
|
|
30830
31069
|
if (!existsSync58(target.configPath)) continue;
|
|
30831
31070
|
if (target.tool === "opencode") {
|
|
30832
|
-
const body2 =
|
|
31071
|
+
const body2 = readFileSync51(target.configPath, "utf-8");
|
|
30833
31072
|
if (!body2.includes("chat-recall install-hooks")) continue;
|
|
30834
31073
|
unlinkSync4(target.configPath);
|
|
30835
31074
|
removed += 1;
|
|
@@ -30937,7 +31176,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
30937
31176
|
const config2 = readHookConfig(hooksJson);
|
|
30938
31177
|
const home = dirname29(hooksJson);
|
|
30939
31178
|
const alreadyWired = wakeupWiredInSettings(home);
|
|
30940
|
-
if (alreadyWired) wakeupSkipped.push(
|
|
31179
|
+
if (alreadyWired) wakeupSkipped.push(join62(home, "settings.json"));
|
|
30941
31180
|
const perProfile = installWakeup && !alreadyWired ? [...events, ["SessionStart", wakeupEntry]] : events;
|
|
30942
31181
|
for (const event of HOOK_EVENTS) {
|
|
30943
31182
|
const arr = Array.isArray(config2.hooks[event]) ? config2.hooks[event] : [];
|
|
@@ -30950,18 +31189,18 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
30950
31189
|
writeFileSync24(hooksJson, JSON.stringify(config2, null, 2) + "\n");
|
|
30951
31190
|
}
|
|
30952
31191
|
if (installGuard) await addGuardToOtherTools(installedGuardHook);
|
|
30953
|
-
const saveSz =
|
|
31192
|
+
const saveSz = statSync47(installedSaveHook).size;
|
|
30954
31193
|
console.log(chalk2.green(`\u2713 Installed chat-recall save hook (${saveSz} bytes)`));
|
|
30955
31194
|
if (installResume) {
|
|
30956
|
-
const resumeSz =
|
|
31195
|
+
const resumeSz = statSync47(installedResumeHook).size;
|
|
30957
31196
|
console.log(chalk2.green(`\u2713 Installed chat-recall resume-hint hook (${resumeSz} bytes)`));
|
|
30958
31197
|
}
|
|
30959
31198
|
if (installEscalate) {
|
|
30960
|
-
const escalateSz =
|
|
31199
|
+
const escalateSz = statSync47(installedEscalateHook).size;
|
|
30961
31200
|
console.log(chalk2.green(`\u2713 Installed chat-recall learnings-escalation hook (${escalateSz} bytes)`));
|
|
30962
31201
|
}
|
|
30963
31202
|
if (installGuard) {
|
|
30964
|
-
const guardSz =
|
|
31203
|
+
const guardSz = statSync47(installedGuardHook).size;
|
|
30965
31204
|
console.log(chalk2.green(`\u2713 Installed chat-recall decision guard (${guardSz} bytes)`));
|
|
30966
31205
|
}
|
|
30967
31206
|
if (installTaskBoard) {
|
|
@@ -30969,7 +31208,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
30969
31208
|
console.log(chalk2.dim(" A prompt naming a card id claims it; a commit message naming one closes it."));
|
|
30970
31209
|
}
|
|
30971
31210
|
if (installWakeup) {
|
|
30972
|
-
const wakeupSz =
|
|
31211
|
+
const wakeupSz = statSync47(installedWakeupHook).size;
|
|
30973
31212
|
console.log(chalk2.green(`\u2713 Installed chat-recall wake-up hook (${wakeupSz} bytes)`));
|
|
30974
31213
|
for (const f of wakeupSkipped) {
|
|
30975
31214
|
console.log(chalk2.dim(` (SessionStart already wired in ${f} \u2014 left as is, not duplicated)`));
|