chat-recall 0.7.16 → 0.7.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +573 -331
- package/dist/mcp-relay.js +136 -40
- package/dist/mcp-relay.js.map +1 -1
- package/dist/mcp.js +381 -128
- package/dist/mcp.js.map +1 -1
- package/dist/raw-archive-parts.d.ts +46 -0
- package/dist/raw-archive-parts.d.ts.map +1 -0
- package/dist/raw-archive-parts.js +175 -0
- package/dist/raw-archive-parts.js.map +1 -0
- package/dist/relay-lifecycle.d.ts +23 -0
- package/dist/relay-lifecycle.d.ts.map +1 -1
- package/dist/relay-lifecycle.js +173 -0
- package/dist/relay-lifecycle.js.map +1 -1
- package/dist/repair.d.ts.map +1 -1
- package/dist/repair.js +15 -7
- package/dist/repair.js.map +1 -1
- package/dist/scan-worker.js +2 -0
- package/dist/sync-client.d.ts +8 -0
- package/dist/sync-client.d.ts.map +1 -1
- package/dist/sync-client.js +86 -5
- package/dist/sync-client.js.map +1 -1
- package/dist/sync-ledger.d.ts +31 -1
- package/dist/sync-ledger.d.ts.map +1 -1
- package/dist/sync-ledger.js +47 -1
- package/dist/sync-ledger.js.map +1 -1
- package/dist/watch.js +447 -202
- package/package.json +1 -1
package/dist/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
|
});
|
|
@@ -11129,18 +11131,20 @@ function updateShadow(sessionId, exp, prebuilt) {
|
|
|
11129
11131
|
const curHash = containerSrcHash(current);
|
|
11130
11132
|
if (!prior) {
|
|
11131
11133
|
current.srcHash = curHash;
|
|
11134
|
+
current.mergeVersion = SHADOW_MERGE_VERSION;
|
|
11132
11135
|
try {
|
|
11133
11136
|
writeShadowContainer(tool, rawId, current);
|
|
11134
11137
|
} catch {
|
|
11135
11138
|
}
|
|
11136
11139
|
return { status: "created", sessionId, tool, container: current, recovered: 0, path };
|
|
11137
11140
|
}
|
|
11138
|
-
if (prior.srcHash && prior.srcHash === curHash) {
|
|
11141
|
+
if (prior.srcHash && prior.srcHash === curHash && prior.mergeVersion === SHADOW_MERGE_VERSION) {
|
|
11139
11142
|
return { status: "unchanged", sessionId, tool, container: prior, recovered: 0, path };
|
|
11140
11143
|
}
|
|
11141
11144
|
const merged = mergeContainer(prior, current);
|
|
11142
|
-
if (merged.status !== "unchanged" || prior.srcHash !== curHash) {
|
|
11145
|
+
if (merged.status !== "unchanged" || prior.srcHash !== curHash || prior.mergeVersion !== SHADOW_MERGE_VERSION) {
|
|
11143
11146
|
merged.container.srcHash = curHash;
|
|
11147
|
+
merged.container.mergeVersion = SHADOW_MERGE_VERSION;
|
|
11144
11148
|
try {
|
|
11145
11149
|
writeShadowContainer(tool, rawId, merged.container);
|
|
11146
11150
|
} catch {
|
|
@@ -11233,7 +11237,7 @@ function shadowSizeOnDisk(tool, rawId) {
|
|
|
11233
11237
|
return 0;
|
|
11234
11238
|
}
|
|
11235
11239
|
}
|
|
11236
|
-
var WHOLE_FILE_TOOLS, STATE_META, lastLiveFingerprint;
|
|
11240
|
+
var WHOLE_FILE_TOOLS, STATE_META, SHADOW_MERGE_VERSION, lastLiveFingerprint;
|
|
11237
11241
|
var init_shadow = __esm({
|
|
11238
11242
|
"../engine/dist/transcript/shadow.js"() {
|
|
11239
11243
|
"use strict";
|
|
@@ -11241,6 +11245,7 @@ var init_shadow = __esm({
|
|
|
11241
11245
|
init_raw();
|
|
11242
11246
|
WHOLE_FILE_TOOLS = /* @__PURE__ */ new Set(["cursor"]);
|
|
11243
11247
|
STATE_META = /* @__PURE__ */ new Set(["mode", "permission-mode", "ai-title", "last-prompt", "pr-link", "summary"]);
|
|
11248
|
+
SHADOW_MERGE_VERSION = 2;
|
|
11244
11249
|
lastLiveFingerprint = /* @__PURE__ */ new Map();
|
|
11245
11250
|
}
|
|
11246
11251
|
});
|
|
@@ -14357,6 +14362,7 @@ var init_opencode2 = __esm({
|
|
|
14357
14362
|
// ../engine/dist/transcript/index.js
|
|
14358
14363
|
var transcript_exports = {};
|
|
14359
14364
|
__export(transcript_exports, {
|
|
14365
|
+
RAW_PARSE_MAX_BYTES: () => RAW_PARSE_MAX_BYTES,
|
|
14360
14366
|
TRANSCRIPT_VERSION: () => TRANSCRIPT_VERSION,
|
|
14361
14367
|
archiveRawSession: () => archiveRawSession,
|
|
14362
14368
|
buildRawContainer: () => buildRawContainer,
|
|
@@ -18817,6 +18823,11 @@ function markSynced(server, rows) {
|
|
|
18817
18823
|
base4.s = s;
|
|
18818
18824
|
}
|
|
18819
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;
|
|
18820
18831
|
forServer[r.id] = base4;
|
|
18821
18832
|
}
|
|
18822
18833
|
persist(data);
|
|
@@ -18873,6 +18884,14 @@ function markFieldFullPassDone(server, field) {
|
|
|
18873
18884
|
delete st.force[field.name];
|
|
18874
18885
|
persistReconcile(data);
|
|
18875
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
|
+
}
|
|
18876
18895
|
function markFullResync(server, sessionId) {
|
|
18877
18896
|
const data = load();
|
|
18878
18897
|
const forServer = data[server];
|
|
@@ -18881,7 +18900,11 @@ function markFullResync(server, sessionId) {
|
|
|
18881
18900
|
delete forServer[sessionId];
|
|
18882
18901
|
persist(data);
|
|
18883
18902
|
}
|
|
18884
|
-
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()) {
|
|
18885
18908
|
if (!row) return "full";
|
|
18886
18909
|
if (row.v < extractorVersion) return "full";
|
|
18887
18910
|
const offset = row.o ?? 0;
|
|
@@ -18889,10 +18912,13 @@ function syncMode(row, mtime, fileSize, extractorVersion, isAppendOnly) {
|
|
|
18889
18912
|
if (process.env.CHAT_RECALL_TAIL_APPEND !== "0" && isAppendOnly && fileSize > 0 && offset > 0 && fileSize > (row.s ?? 0)) {
|
|
18890
18913
|
return "append";
|
|
18891
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
|
+
}
|
|
18892
18918
|
if (row.m >= Math.floor(mtime)) return "skip";
|
|
18893
18919
|
return "full";
|
|
18894
18920
|
}
|
|
18895
|
-
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;
|
|
18896
18922
|
var init_sync_ledger = __esm({
|
|
18897
18923
|
"src/sync-ledger.ts"() {
|
|
18898
18924
|
"use strict";
|
|
@@ -18912,6 +18938,7 @@ var init_sync_ledger = __esm({
|
|
|
18912
18938
|
unackedCursorAttempts = 0;
|
|
18913
18939
|
reconcilePath = () => join38(getDataDir(), "sync-field-reconcile.json");
|
|
18914
18940
|
reconcileCache = null;
|
|
18941
|
+
SETTLE_QUIET_MS = 2 * 60 * 60 * 1e3;
|
|
18915
18942
|
}
|
|
18916
18943
|
});
|
|
18917
18944
|
|
|
@@ -19063,7 +19090,7 @@ var init_http = __esm({
|
|
|
19063
19090
|
CLI_VERSION = JSON.parse(readFileSync31(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
|
|
19064
19091
|
} catch {
|
|
19065
19092
|
try {
|
|
19066
|
-
if (true) CLI_VERSION = "0.7.
|
|
19093
|
+
if (true) CLI_VERSION = "0.7.18";
|
|
19067
19094
|
} catch {
|
|
19068
19095
|
}
|
|
19069
19096
|
}
|
|
@@ -19561,7 +19588,7 @@ var init_telemetry = __esm({
|
|
|
19561
19588
|
init_sync_client();
|
|
19562
19589
|
cliVersion2 = () => {
|
|
19563
19590
|
try {
|
|
19564
|
-
return true ? "0.7.
|
|
19591
|
+
return true ? "0.7.18" : "dev";
|
|
19565
19592
|
} catch {
|
|
19566
19593
|
return "dev";
|
|
19567
19594
|
}
|
|
@@ -19724,6 +19751,150 @@ var init_collector_health = __esm({
|
|
|
19724
19751
|
}
|
|
19725
19752
|
});
|
|
19726
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
|
+
|
|
19727
19898
|
// src/server-probe.ts
|
|
19728
19899
|
var server_probe_exports = {};
|
|
19729
19900
|
__export(server_probe_exports, {
|
|
@@ -19867,7 +20038,7 @@ __export(client_events_exports, {
|
|
|
19867
20038
|
isTelemetryEnabled: () => isTelemetryEnabled,
|
|
19868
20039
|
reportClientEvent: () => reportClientEvent
|
|
19869
20040
|
});
|
|
19870
|
-
import { readFileSync as
|
|
20041
|
+
import { readFileSync as readFileSync34 } from "node:fs";
|
|
19871
20042
|
function scrub(msg) {
|
|
19872
20043
|
if (!msg) return "";
|
|
19873
20044
|
const noHome = msg.replace(/\/(?:home|Users)\/[^/\s]+/g, "~");
|
|
@@ -19920,7 +20091,7 @@ var init_client_events = __esm({
|
|
|
19920
20091
|
init_secret_redactor();
|
|
19921
20092
|
CLI_VERSION2 = "0.0.0";
|
|
19922
20093
|
try {
|
|
19923
|
-
CLI_VERSION2 = JSON.parse(
|
|
20094
|
+
CLI_VERSION2 = JSON.parse(readFileSync34(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION2;
|
|
19924
20095
|
} catch {
|
|
19925
20096
|
}
|
|
19926
20097
|
}
|
|
@@ -19950,11 +20121,11 @@ __export(auto_update_exports, {
|
|
|
19950
20121
|
tarballUrl: () => tarballUrl
|
|
19951
20122
|
});
|
|
19952
20123
|
import { execSync as execSync2, execFileSync as execFileSync3 } from "node:child_process";
|
|
19953
|
-
import { readFileSync as
|
|
20124
|
+
import { readFileSync as readFileSync35, existsSync as existsSync41 } from "node:fs";
|
|
19954
20125
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
19955
|
-
import { writeFileSync as writeFileSync8, mkdtempSync as mkdtempSync3, rmSync as
|
|
19956
|
-
import { join as
|
|
19957
|
-
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";
|
|
19958
20129
|
import { createHash as createHash8 } from "node:crypto";
|
|
19959
20130
|
function compareVersions(a, b) {
|
|
19960
20131
|
const pa = String(a).split("-")[0].split(".").map((n) => parseInt(n, 10) || 0);
|
|
@@ -19978,7 +20149,7 @@ function newerOf(a, b) {
|
|
|
19978
20149
|
function installedVersion() {
|
|
19979
20150
|
try {
|
|
19980
20151
|
const here = dirname18(fileURLToPath2(import.meta.url));
|
|
19981
|
-
const raw =
|
|
20152
|
+
const raw = readFileSync35(join42(here, "..", "package.json"), "utf-8");
|
|
19982
20153
|
return JSON.parse(raw).version || null;
|
|
19983
20154
|
} catch {
|
|
19984
20155
|
return null;
|
|
@@ -19991,7 +20162,7 @@ function planAutoUpdate(base4, caps, ownVersion3, flag) {
|
|
|
19991
20162
|
if (compareVersions(rel.version, ownVersion3) <= 0) return { update: false, reason: `already current (own ${ownVersion3} >= server ${rel.version})` };
|
|
19992
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 };
|
|
19993
20164
|
}
|
|
19994
|
-
function sweepStaleStaging(root =
|
|
20165
|
+
function sweepStaleStaging(root = tmpdir3(), now = Date.now()) {
|
|
19995
20166
|
const MKDTEMP_SUFFIX = /^cr-update-.{6}$/s;
|
|
19996
20167
|
const COLD_MS = 60 * 60 * 1e3;
|
|
19997
20168
|
let removed = 0;
|
|
@@ -20003,13 +20174,13 @@ function sweepStaleStaging(root = tmpdir2(), now = Date.now()) {
|
|
|
20003
20174
|
}
|
|
20004
20175
|
for (const name of entries) {
|
|
20005
20176
|
if (!MKDTEMP_SUFFIX.test(name)) continue;
|
|
20006
|
-
const dir =
|
|
20177
|
+
const dir = join42(root, name);
|
|
20007
20178
|
try {
|
|
20008
|
-
const st =
|
|
20179
|
+
const st = statSync38(dir);
|
|
20009
20180
|
if (!st.isDirectory() || now - st.mtimeMs < COLD_MS) continue;
|
|
20010
20181
|
const inside = readdirSync30(dir);
|
|
20011
20182
|
if (inside.length > 1 || inside.length === 1 && inside[0] !== "chat-recall.tgz") continue;
|
|
20012
|
-
|
|
20183
|
+
rmSync6(dir, { recursive: true, force: true });
|
|
20013
20184
|
removed++;
|
|
20014
20185
|
} catch {
|
|
20015
20186
|
}
|
|
@@ -20032,14 +20203,14 @@ async function executeAutoUpdate(plan, deps) {
|
|
|
20032
20203
|
}
|
|
20033
20204
|
const got = createHash8("sha256").update(buf).digest("hex");
|
|
20034
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` };
|
|
20035
|
-
const dir = mkdtempSync3(
|
|
20206
|
+
const dir = mkdtempSync3(join42(tmpdir3(), "cr-update-"));
|
|
20036
20207
|
const discardStaging = () => {
|
|
20037
20208
|
try {
|
|
20038
|
-
|
|
20209
|
+
rmSync6(dir, { recursive: true, force: true });
|
|
20039
20210
|
} catch {
|
|
20040
20211
|
}
|
|
20041
20212
|
};
|
|
20042
|
-
const tgz =
|
|
20213
|
+
const tgz = join42(dir, "chat-recall.tgz");
|
|
20043
20214
|
writeFileSync8(tgz, buf);
|
|
20044
20215
|
if (deps.stopping?.()) {
|
|
20045
20216
|
discardStaging();
|
|
@@ -20119,7 +20290,7 @@ function realInstall(tgz) {
|
|
|
20119
20290
|
try {
|
|
20120
20291
|
npmInstall(npm, ["install", "-g", tgz]);
|
|
20121
20292
|
} catch {
|
|
20122
|
-
npmInstall(npm, ["install", "-g", "--prefix",
|
|
20293
|
+
npmInstall(npm, ["install", "-g", "--prefix", join42(homedir15(), ".local"), tgz]);
|
|
20123
20294
|
}
|
|
20124
20295
|
}
|
|
20125
20296
|
function acquireUpdateLock() {
|
|
@@ -20136,12 +20307,12 @@ function realRestart(platform2) {
|
|
|
20136
20307
|
if (c) execSync2(c.cmd, { stdio: "ignore", ...c.shell ? { shell: c.shell } : {} });
|
|
20137
20308
|
}
|
|
20138
20309
|
function updateStatePath() {
|
|
20139
|
-
const dir = process.env.CHAT_RECALL_DATA_DIR ||
|
|
20140
|
-
return
|
|
20310
|
+
const dir = process.env.CHAT_RECALL_DATA_DIR || join42(homedir15(), ".chat-recall");
|
|
20311
|
+
return join42(dir, "auto-update-state.json");
|
|
20141
20312
|
}
|
|
20142
20313
|
function readUpdateState() {
|
|
20143
20314
|
try {
|
|
20144
|
-
return JSON.parse(
|
|
20315
|
+
return JSON.parse(readFileSync35(updateStatePath(), "utf8"));
|
|
20145
20316
|
} catch {
|
|
20146
20317
|
return {};
|
|
20147
20318
|
}
|
|
@@ -20282,9 +20453,9 @@ __export(sync_client_exports, {
|
|
|
20282
20453
|
syncIncremental: () => syncIncremental,
|
|
20283
20454
|
syncSessions: () => syncSessions
|
|
20284
20455
|
});
|
|
20285
|
-
import { join as
|
|
20286
|
-
import { readFileSync as
|
|
20287
|
-
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";
|
|
20288
20459
|
import { createHash as createHash9 } from "node:crypto";
|
|
20289
20460
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
20290
20461
|
import { gzipSync as gzipSync3 } from "zlib";
|
|
@@ -20338,7 +20509,7 @@ function loadAllCredentials() {
|
|
|
20338
20509
|
const fromEnv = envCredentials();
|
|
20339
20510
|
if (fromEnv) return [{ serverUrl: fromEnv.serverUrl, token: fromEnv.token }];
|
|
20340
20511
|
try {
|
|
20341
|
-
const parsed = JSON.parse(
|
|
20512
|
+
const parsed = JSON.parse(readFileSync36(credPath(), "utf-8"));
|
|
20342
20513
|
if (Array.isArray(parsed?.targets)) return parsed.targets.filter((t) => t?.serverUrl).map((t) => ({ serverUrl: t.serverUrl, token: t.token || "" }));
|
|
20343
20514
|
if (parsed?.serverUrl) return [{ serverUrl: parsed.serverUrl, token: parsed.token || "" }];
|
|
20344
20515
|
} catch {
|
|
@@ -20400,11 +20571,11 @@ function _resetTenantSecurityConfigCache() {
|
|
|
20400
20571
|
_securityConfigCache.clear();
|
|
20401
20572
|
}
|
|
20402
20573
|
function syncConfigCachePath() {
|
|
20403
|
-
return
|
|
20574
|
+
return join43(getDataDir(), "sync-config-cache.json");
|
|
20404
20575
|
}
|
|
20405
20576
|
function readPersistedSyncConfigs() {
|
|
20406
20577
|
try {
|
|
20407
|
-
return JSON.parse(
|
|
20578
|
+
return JSON.parse(readFileSync36(syncConfigCachePath(), "utf-8"));
|
|
20408
20579
|
} catch {
|
|
20409
20580
|
return {};
|
|
20410
20581
|
}
|
|
@@ -20682,7 +20853,7 @@ async function reconcileFields(opts = {}) {
|
|
|
20682
20853
|
}
|
|
20683
20854
|
return { sessions: fullRefs().length, scanned, pushed, absent, perTarget };
|
|
20684
20855
|
}
|
|
20685
|
-
function reapStaleScanDirs(dir =
|
|
20856
|
+
function reapStaleScanDirs(dir = tmpdir4(), maxAgeMs = 6 * 36e5, now = Date.now()) {
|
|
20686
20857
|
let reaped = 0;
|
|
20687
20858
|
let names;
|
|
20688
20859
|
try {
|
|
@@ -20692,10 +20863,10 @@ function reapStaleScanDirs(dir = tmpdir3(), maxAgeMs = 6 * 36e5, now = Date.now(
|
|
|
20692
20863
|
}
|
|
20693
20864
|
for (const name of names) {
|
|
20694
20865
|
if (!name.startsWith("cr-batchscan-")) continue;
|
|
20695
|
-
const p =
|
|
20866
|
+
const p = join43(dir, name);
|
|
20696
20867
|
try {
|
|
20697
|
-
if (now -
|
|
20698
|
-
|
|
20868
|
+
if (now - statSync39(p).mtimeMs < maxAgeMs) continue;
|
|
20869
|
+
rmSync7(p, { recursive: true, force: true });
|
|
20699
20870
|
reaped++;
|
|
20700
20871
|
} catch {
|
|
20701
20872
|
}
|
|
@@ -20709,7 +20880,7 @@ function batchScanExternal(items, opts = {}) {
|
|
|
20709
20880
|
let scanned = 0, slices = 0, scanMs = 0;
|
|
20710
20881
|
if (items.length === 0) return { findings, scanned, slices, scanMs };
|
|
20711
20882
|
reapStaleScanDirs();
|
|
20712
|
-
let scanDir = mkdtempSync4(
|
|
20883
|
+
let scanDir = mkdtempSync4(join43(tmpdir4(), "cr-batchscan-"));
|
|
20713
20884
|
let safeToId = /* @__PURE__ */ new Map();
|
|
20714
20885
|
let bytesInDir = 0;
|
|
20715
20886
|
const flushSlice = () => {
|
|
@@ -20727,7 +20898,7 @@ function batchScanExternal(items, opts = {}) {
|
|
|
20727
20898
|
slices++;
|
|
20728
20899
|
}
|
|
20729
20900
|
try {
|
|
20730
|
-
|
|
20901
|
+
rmSync7(scanDir, { recursive: true, force: true });
|
|
20731
20902
|
} catch {
|
|
20732
20903
|
}
|
|
20733
20904
|
safeToId = /* @__PURE__ */ new Map();
|
|
@@ -20740,19 +20911,19 @@ function batchScanExternal(items, opts = {}) {
|
|
|
20740
20911
|
if (raw === null) continue;
|
|
20741
20912
|
const safe = item.id.replace(/[^A-Za-z0-9_-]/g, "");
|
|
20742
20913
|
safeToId.set(safe, item.id);
|
|
20743
|
-
writeFileSync9(
|
|
20914
|
+
writeFileSync9(join43(scanDir, `${safe}.txt`), raw);
|
|
20744
20915
|
bytesInDir += Buffer.byteLength(raw);
|
|
20745
20916
|
} catch {
|
|
20746
20917
|
}
|
|
20747
20918
|
if (bytesInDir >= maxBytes) {
|
|
20748
20919
|
flushSlice();
|
|
20749
|
-
scanDir = mkdtempSync4(
|
|
20920
|
+
scanDir = mkdtempSync4(join43(tmpdir4(), "cr-batchscan-"));
|
|
20750
20921
|
}
|
|
20751
20922
|
}
|
|
20752
20923
|
flushSlice();
|
|
20753
20924
|
} finally {
|
|
20754
20925
|
try {
|
|
20755
|
-
|
|
20926
|
+
rmSync7(scanDir, { recursive: true, force: true });
|
|
20756
20927
|
} catch {
|
|
20757
20928
|
}
|
|
20758
20929
|
}
|
|
@@ -20996,12 +21167,13 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20996
21167
|
markSynced(base4, rows.map((r) => {
|
|
20997
21168
|
const off = typeof r.from_offset === "number" ? r.from_offset : 0;
|
|
20998
21169
|
const hash = shippedHash.get(r.session_id);
|
|
20999
|
-
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 };
|
|
21000
21171
|
}));
|
|
21001
21172
|
} catch {
|
|
21002
21173
|
}
|
|
21003
21174
|
});
|
|
21004
21175
|
const appendResults = { uploaded: 0, fullResyncNeeded: /* @__PURE__ */ new Set() };
|
|
21176
|
+
const pendingArchives = [];
|
|
21005
21177
|
const postAppend = async (convs) => {
|
|
21006
21178
|
const headers = { "content-type": "application/json" };
|
|
21007
21179
|
if (cred.token) headers.authorization = `Bearer ${cred.token}`;
|
|
@@ -21036,8 +21208,10 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
21036
21208
|
offset: c.from_offset,
|
|
21037
21209
|
size: c.from_offset,
|
|
21038
21210
|
// size = new offset (file grew to here)
|
|
21039
|
-
acked: true
|
|
21211
|
+
acked: true,
|
|
21040
21212
|
// server merged this tail
|
|
21213
|
+
chunkFinal: c.final === true
|
|
21214
|
+
// completes a chunked full sync
|
|
21041
21215
|
})));
|
|
21042
21216
|
} catch {
|
|
21043
21217
|
}
|
|
@@ -21069,9 +21243,9 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
21069
21243
|
const mtime = conv.mtime;
|
|
21070
21244
|
try {
|
|
21071
21245
|
if (staged || !guarded) {
|
|
21072
|
-
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 }]);
|
|
21073
21247
|
} else if (typeof guarded.o === "number" && guarded.o > 0 && guarded.o <= fileSize) {
|
|
21074
|
-
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 }]);
|
|
21075
21249
|
} else {
|
|
21076
21250
|
markSynced(base4, [{ id, mtime }]);
|
|
21077
21251
|
}
|
|
@@ -21280,6 +21454,14 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
21280
21454
|
if (built.srcHash) shippedHash.set(ref.prefixedId, built.srcHash);
|
|
21281
21455
|
if (built.conv.chunked) await postChunkedHead(built.conv, sessionFileBytes(ref));
|
|
21282
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
|
+
}
|
|
21283
21465
|
if (built.findings.length > 0) await findingsBatch.add(built.findings);
|
|
21284
21466
|
if (upload.sessionMeta) {
|
|
21285
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);
|
|
@@ -21432,6 +21614,30 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
21432
21614
|
await kgTripleBatch.drain();
|
|
21433
21615
|
await findingsBatch.drain();
|
|
21434
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
|
+
}
|
|
21435
21641
|
{
|
|
21436
21642
|
const sentHashes = loadInventoryHashes(base4);
|
|
21437
21643
|
const entries = [];
|
|
@@ -21537,6 +21743,7 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
21537
21743
|
let includeRaw = opts.includeRaw !== false;
|
|
21538
21744
|
let includeMeta = opts.includeMeta !== false;
|
|
21539
21745
|
let srcHash;
|
|
21746
|
+
const wantRaw = opts.includeRaw !== false;
|
|
21540
21747
|
const oversized = sessionBuildBytes(ref) > FULL_BUILD_MAX_BYTES;
|
|
21541
21748
|
let headOffsetEnd = 0;
|
|
21542
21749
|
let oversizedFindings = null;
|
|
@@ -21705,7 +21912,7 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
21705
21912
|
} else if (opts.scanSecrets) {
|
|
21706
21913
|
let tmp = null;
|
|
21707
21914
|
try {
|
|
21708
|
-
tmp =
|
|
21915
|
+
tmp = join43(tmpdir4(), `cr-scan-${ref.prefixedId.replace(/[^A-Za-z0-9_-]/g, "")}-${mtime}.txt`);
|
|
21709
21916
|
writeFileSync9(tmp, rawText);
|
|
21710
21917
|
for (const f of scanFileForSecrets(tmp, { verifyOnly: opts.verifySecrets, tenantRules: opts.tenantRules })) {
|
|
21711
21918
|
const verifiedAt = f.verified ? (/* @__PURE__ */ new Date()).toISOString() : null;
|
|
@@ -21757,6 +21964,25 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
21757
21964
|
}
|
|
21758
21965
|
const envTexts = envelope.messages.filter((m) => m.content?.trim());
|
|
21759
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
|
+
}
|
|
21760
21986
|
return {
|
|
21761
21987
|
conv: {
|
|
21762
21988
|
session_id: ref.prefixedId,
|
|
@@ -21788,7 +22014,17 @@ async function buildConversationSync(ref, mtime, opts = {}) {
|
|
|
21788
22014
|
redactions: count.redactions,
|
|
21789
22015
|
findings,
|
|
21790
22016
|
scanMs,
|
|
21791
|
-
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] }))
|
|
21792
22028
|
};
|
|
21793
22029
|
}
|
|
21794
22030
|
function parseTailMessages(tool, text) {
|
|
@@ -21944,14 +22180,15 @@ var init_sync_client = __esm({
|
|
|
21944
22180
|
init_telemetry();
|
|
21945
22181
|
init_collector_health();
|
|
21946
22182
|
init_live_session_scan();
|
|
22183
|
+
init_raw_archive_parts();
|
|
21947
22184
|
init_backends();
|
|
21948
22185
|
ownVersion = "0.0.0";
|
|
21949
22186
|
try {
|
|
21950
22187
|
const dir = dirname19(fileURLToPath3(import.meta.url));
|
|
21951
|
-
ownVersion = JSON.parse(
|
|
22188
|
+
ownVersion = JSON.parse(readFileSync36(join43(dir, "../package.json"), "utf-8")).version || ownVersion;
|
|
21952
22189
|
} catch {
|
|
21953
22190
|
try {
|
|
21954
|
-
if (true) ownVersion = "0.7.
|
|
22191
|
+
if (true) ownVersion = "0.7.18";
|
|
21955
22192
|
} catch {
|
|
21956
22193
|
}
|
|
21957
22194
|
}
|
|
@@ -21963,7 +22200,7 @@ var init_sync_client = __esm({
|
|
|
21963
22200
|
]);
|
|
21964
22201
|
walkProgressForUpload = null;
|
|
21965
22202
|
lastServerPackSpec = null;
|
|
21966
|
-
credPath = () =>
|
|
22203
|
+
credPath = () => join43(getDataDir(), "credentials.json");
|
|
21967
22204
|
_securityConfigCache = /* @__PURE__ */ new Map();
|
|
21968
22205
|
SECURITY_CONFIG_TTL_MS = 5 * 60 * 1e3;
|
|
21969
22206
|
_syncConfigCache = /* @__PURE__ */ new Map();
|
|
@@ -21994,15 +22231,15 @@ __export(update_notice_exports, {
|
|
|
21994
22231
|
refreshUpdateCheck: () => refreshUpdateCheck,
|
|
21995
22232
|
updateNotice: () => updateNotice
|
|
21996
22233
|
});
|
|
21997
|
-
import { readFileSync as
|
|
21998
|
-
import { join as
|
|
22234
|
+
import { readFileSync as readFileSync37, writeFileSync as writeFileSync10 } from "node:fs";
|
|
22235
|
+
import { join as join44 } from "node:path";
|
|
21999
22236
|
function newestKnown(c) {
|
|
22000
22237
|
const npm = c.npmVersion ?? "0.0.0";
|
|
22001
22238
|
return compareVersions(npm, c.serverVersion) > 0 ? { version: npm, source: "npm" } : { version: c.serverVersion, source: "server" };
|
|
22002
22239
|
}
|
|
22003
22240
|
function readCheck() {
|
|
22004
22241
|
try {
|
|
22005
|
-
const c = JSON.parse(
|
|
22242
|
+
const c = JSON.parse(readFileSync37(checkPath(), "utf-8"));
|
|
22006
22243
|
return c && typeof c.serverVersion === "string" ? c : null;
|
|
22007
22244
|
} catch {
|
|
22008
22245
|
return null;
|
|
@@ -22096,17 +22333,17 @@ var init_update_notice = __esm({
|
|
|
22096
22333
|
init_http();
|
|
22097
22334
|
CHECK_TTL_MS = 6 * 3600 * 1e3;
|
|
22098
22335
|
NPM_LATEST_URL = "https://registry.npmjs.org/chat-recall";
|
|
22099
|
-
checkPath = () =>
|
|
22336
|
+
checkPath = () => join44(getDataDir(), "update-check.json");
|
|
22100
22337
|
printed = false;
|
|
22101
22338
|
}
|
|
22102
22339
|
});
|
|
22103
22340
|
|
|
22104
22341
|
// ../engine/dist/core/which.js
|
|
22105
|
-
import { existsSync as existsSync42, statSync as
|
|
22106
|
-
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";
|
|
22107
22344
|
function executable(p) {
|
|
22108
22345
|
try {
|
|
22109
|
-
if (!
|
|
22346
|
+
if (!statSync40(p).isFile())
|
|
22110
22347
|
return false;
|
|
22111
22348
|
} catch {
|
|
22112
22349
|
return false;
|
|
@@ -22142,7 +22379,7 @@ function resolveOnPath(name) {
|
|
|
22142
22379
|
if (!dir)
|
|
22143
22380
|
continue;
|
|
22144
22381
|
for (const c of candidates(name)) {
|
|
22145
|
-
const full =
|
|
22382
|
+
const full = join45(dir, c);
|
|
22146
22383
|
if (existsSync42(full) && executable(full))
|
|
22147
22384
|
return full;
|
|
22148
22385
|
}
|
|
@@ -22206,9 +22443,9 @@ __export(mcp_clients_exports, {
|
|
|
22206
22443
|
inspectMcpClients: () => inspectMcpClients,
|
|
22207
22444
|
registerMcpEverywhere: () => registerMcpEverywhere
|
|
22208
22445
|
});
|
|
22209
|
-
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";
|
|
22210
22447
|
import { homedir as homedir16 } from "os";
|
|
22211
|
-
import { dirname as dirname21, join as
|
|
22448
|
+
import { dirname as dirname21, join as join47 } from "path";
|
|
22212
22449
|
function envHome(varName, fallback) {
|
|
22213
22450
|
const v = process.env[varName];
|
|
22214
22451
|
return v && v.trim() ? v.trim() : fallback;
|
|
@@ -22218,7 +22455,7 @@ function writeFileMkdir(path, body2) {
|
|
|
22218
22455
|
writeFileSync12(path, body2);
|
|
22219
22456
|
}
|
|
22220
22457
|
function readJsonObject(path) {
|
|
22221
|
-
const raw =
|
|
22458
|
+
const raw = readFileSync38(path, "utf-8");
|
|
22222
22459
|
if (raw.trim() === "")
|
|
22223
22460
|
return {};
|
|
22224
22461
|
return JSON.parse(raw);
|
|
@@ -22293,7 +22530,7 @@ function registerCodexToml(path, spec) {
|
|
|
22293
22530
|
const id = "codex";
|
|
22294
22531
|
const label = "Codex";
|
|
22295
22532
|
const block = codexBlock(spec);
|
|
22296
|
-
const prev = existsSync44(path) ?
|
|
22533
|
+
const prev = existsSync44(path) ? readFileSync38(path, "utf-8") : "";
|
|
22297
22534
|
const lines = prev.length ? prev.split("\n") : [];
|
|
22298
22535
|
const start = lines.findIndex((l) => l.trim() === CODEX_HEADER);
|
|
22299
22536
|
if (start === -1) {
|
|
@@ -22336,7 +22573,7 @@ function inspectMcpClients(opts = {}) {
|
|
|
22336
22573
|
let registered = false;
|
|
22337
22574
|
if (existsSync44(path)) {
|
|
22338
22575
|
try {
|
|
22339
|
-
const raw =
|
|
22576
|
+
const raw = readFileSync38(path, "utf-8");
|
|
22340
22577
|
registered = c.id === "codex" ? raw.includes(CODEX_HEADER) : !!(JSON.parse(raw).mcpServers?.[MCP_SERVER_NAME] ?? JSON.parse(raw).mcp?.[MCP_SERVER_NAME]);
|
|
22341
22578
|
} catch {
|
|
22342
22579
|
registered = false;
|
|
@@ -22356,7 +22593,7 @@ var init_mcp_clients = __esm({
|
|
|
22356
22593
|
id: "claude",
|
|
22357
22594
|
label: "Claude Code",
|
|
22358
22595
|
bin: "claude",
|
|
22359
|
-
configPath: (home) =>
|
|
22596
|
+
configPath: (home) => join47(home, ".mcp.json"),
|
|
22360
22597
|
// Claude Code is the reference client and `init`'s historical target, so we
|
|
22361
22598
|
// always write it — a fresh machine has no ~/.claude yet on first install.
|
|
22362
22599
|
isPresent: () => true,
|
|
@@ -22368,7 +22605,7 @@ var init_mcp_clients = __esm({
|
|
|
22368
22605
|
id: "codex",
|
|
22369
22606
|
label: "Codex",
|
|
22370
22607
|
bin: "codex",
|
|
22371
|
-
configPath: (home) =>
|
|
22608
|
+
configPath: (home) => join47(envHome("CHAT_RECALL_CODEX_HOME", join47(home, ".codex")), "config.toml"),
|
|
22372
22609
|
isPresent(home) {
|
|
22373
22610
|
const p = this.configPath(home);
|
|
22374
22611
|
return existsSync44(p) || existsSync44(dirname21(p));
|
|
@@ -22381,7 +22618,7 @@ var init_mcp_clients = __esm({
|
|
|
22381
22618
|
id: "opencode",
|
|
22382
22619
|
label: "OpenCode",
|
|
22383
22620
|
bin: "opencode",
|
|
22384
|
-
configPath: (home) =>
|
|
22621
|
+
configPath: (home) => join47(envHome("XDG_CONFIG_HOME", join47(home, ".config")), "opencode", "opencode.json"),
|
|
22385
22622
|
isPresent(home) {
|
|
22386
22623
|
const p = this.configPath(home);
|
|
22387
22624
|
return existsSync44(p) || existsSync44(dirname21(p));
|
|
@@ -22396,9 +22633,9 @@ var init_mcp_clients = __esm({
|
|
|
22396
22633
|
id: "agy",
|
|
22397
22634
|
label: "Antigravity",
|
|
22398
22635
|
bin: "agy",
|
|
22399
|
-
configPath: (home) =>
|
|
22636
|
+
configPath: (home) => join47(home, ".gemini", "config", "mcp_config.json"),
|
|
22400
22637
|
isPresent(home) {
|
|
22401
|
-
return existsSync44(
|
|
22638
|
+
return existsSync44(join47(home, ".gemini", "antigravity-cli")) || existsSync44(this.configPath(home));
|
|
22402
22639
|
},
|
|
22403
22640
|
register(spec, home) {
|
|
22404
22641
|
return registerMcpServersJson(this, this.configPath(home), spec);
|
|
@@ -22408,7 +22645,7 @@ var init_mcp_clients = __esm({
|
|
|
22408
22645
|
id: "cursor",
|
|
22409
22646
|
label: "Cursor",
|
|
22410
22647
|
bin: "cursor",
|
|
22411
|
-
configPath: (home) =>
|
|
22648
|
+
configPath: (home) => join47(home, ".cursor", "mcp.json"),
|
|
22412
22649
|
isPresent(home) {
|
|
22413
22650
|
const p = this.configPath(home);
|
|
22414
22651
|
return existsSync44(p) || existsSync44(dirname21(p));
|
|
@@ -22435,9 +22672,9 @@ __export(companions_exports, {
|
|
|
22435
22672
|
uninstallCodeindex: () => uninstallCodeindex,
|
|
22436
22673
|
unregisterCodeindexMcp: () => unregisterCodeindexMcp
|
|
22437
22674
|
});
|
|
22438
|
-
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";
|
|
22439
22676
|
import { homedir as homedir17 } from "node:os";
|
|
22440
|
-
import { join as
|
|
22677
|
+
import { join as join48 } from "node:path";
|
|
22441
22678
|
import { execSync as execSync3 } from "node:child_process";
|
|
22442
22679
|
import { createHash as createHash10 } from "node:crypto";
|
|
22443
22680
|
function expectedCodeindexSha256(artifact) {
|
|
@@ -22486,7 +22723,7 @@ function checkCodeindexStatus() {
|
|
|
22486
22723
|
status.installed = true;
|
|
22487
22724
|
status.path = foundPath;
|
|
22488
22725
|
try {
|
|
22489
|
-
status.size =
|
|
22726
|
+
status.size = statSync41(foundPath).size;
|
|
22490
22727
|
} catch {
|
|
22491
22728
|
}
|
|
22492
22729
|
try {
|
|
@@ -22512,7 +22749,7 @@ async function downloadArtifact(artifact, dest) {
|
|
|
22512
22749
|
throw new Error(`Download failed: ${res.status} ${res.statusText}`);
|
|
22513
22750
|
if (!res.body)
|
|
22514
22751
|
throw new Error("Download returned empty body");
|
|
22515
|
-
const file =
|
|
22752
|
+
const file = createWriteStream2(dest);
|
|
22516
22753
|
await new Promise((resolve3, reject) => {
|
|
22517
22754
|
const reader = res.body.getReader();
|
|
22518
22755
|
const pump = async () => {
|
|
@@ -22547,7 +22784,7 @@ async function installCodeindex(opts = {}) {
|
|
|
22547
22784
|
if (!expected) {
|
|
22548
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.`);
|
|
22549
22786
|
}
|
|
22550
|
-
const actual = createHash10("sha256").update(
|
|
22787
|
+
const actual = createHash10("sha256").update(readFileSync39(tmpPath)).digest("hex");
|
|
22551
22788
|
if (actual !== expected) {
|
|
22552
22789
|
throw new Error(`Checksum mismatch for ${status.artifactName}.
|
|
22553
22790
|
expected ${expected}
|
|
@@ -22577,7 +22814,7 @@ function registerCodeindexMcp(mcpJsonPath, binaryPath) {
|
|
|
22577
22814
|
let cfg = {};
|
|
22578
22815
|
if (existsSync45(mcpJsonPath)) {
|
|
22579
22816
|
try {
|
|
22580
|
-
cfg = JSON.parse(
|
|
22817
|
+
cfg = JSON.parse(readFileSync39(mcpJsonPath, "utf-8"));
|
|
22581
22818
|
} catch {
|
|
22582
22819
|
cfg = {};
|
|
22583
22820
|
}
|
|
@@ -22594,7 +22831,7 @@ function unregisterCodeindexMcp(mcpJsonPath) {
|
|
|
22594
22831
|
return { removed: false };
|
|
22595
22832
|
let cfg;
|
|
22596
22833
|
try {
|
|
22597
|
-
cfg = JSON.parse(
|
|
22834
|
+
cfg = JSON.parse(readFileSync39(mcpJsonPath, "utf-8"));
|
|
22598
22835
|
} catch {
|
|
22599
22836
|
return { removed: false };
|
|
22600
22837
|
}
|
|
@@ -22619,9 +22856,9 @@ var init_companions = __esm({
|
|
|
22619
22856
|
"x86_64-windows": "a96fc8c8949bb399a44cc0615b12e458460a529c69f01e8829cc39a20f45ab29",
|
|
22620
22857
|
"aarch64-windows": "42620d56272cd9ba9d785569d8d754d6b4a3e80f36f28db3e0c483fd600ed117"
|
|
22621
22858
|
};
|
|
22622
|
-
CODEINDEX_INSTALL_DIR =
|
|
22859
|
+
CODEINDEX_INSTALL_DIR = join48(homedir17(), ".local", "bin");
|
|
22623
22860
|
CODEINDEX_BIN_NAME = process.platform === "win32" ? "codeindex.exe" : "codeindex";
|
|
22624
|
-
CODEINDEX_BIN_PATH =
|
|
22861
|
+
CODEINDEX_BIN_PATH = join48(CODEINDEX_INSTALL_DIR, CODEINDEX_BIN_NAME);
|
|
22625
22862
|
}
|
|
22626
22863
|
});
|
|
22627
22864
|
|
|
@@ -22636,15 +22873,15 @@ __export(install_skills_exports, {
|
|
|
22636
22873
|
skillsSourceDir: () => skillsSourceDir,
|
|
22637
22874
|
uninstallSkills: () => uninstallSkills
|
|
22638
22875
|
});
|
|
22639
|
-
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";
|
|
22640
22877
|
import { createHash as createHash11 } from "crypto";
|
|
22641
|
-
import { join as
|
|
22878
|
+
import { join as join49, basename as basename21 } from "path";
|
|
22642
22879
|
function skillsSourceDir() {
|
|
22643
|
-
return
|
|
22880
|
+
return join49(import.meta.dirname, "..", "skills");
|
|
22644
22881
|
}
|
|
22645
22882
|
function version() {
|
|
22646
22883
|
try {
|
|
22647
|
-
return JSON.parse(
|
|
22884
|
+
return JSON.parse(readFileSync40(new URL("../package.json", import.meta.url), "utf-8")).version || "0.0.0";
|
|
22648
22885
|
} catch {
|
|
22649
22886
|
return "0.0.0";
|
|
22650
22887
|
}
|
|
@@ -22653,9 +22890,9 @@ function skillsFingerprint() {
|
|
|
22653
22890
|
const src = skillsSourceDir();
|
|
22654
22891
|
const h = createHash11("sha256");
|
|
22655
22892
|
for (const name of bundledSkillNames()) {
|
|
22656
|
-
for (const rel of filesUnder(
|
|
22893
|
+
for (const rel of filesUnder(join49(src, name)).sort()) {
|
|
22657
22894
|
h.update(name + "/" + rel);
|
|
22658
|
-
h.update(
|
|
22895
|
+
h.update(readFileSync40(join49(src, name, rel)));
|
|
22659
22896
|
}
|
|
22660
22897
|
}
|
|
22661
22898
|
return h.digest("hex").slice(0, 12);
|
|
@@ -22665,7 +22902,7 @@ function filesUnder(dir, prefix = "") {
|
|
|
22665
22902
|
for (const e of readdirSync32(dir, { withFileTypes: true })) {
|
|
22666
22903
|
if (e.name === MARKER) continue;
|
|
22667
22904
|
const rel = prefix ? `${prefix}/${e.name}` : e.name;
|
|
22668
|
-
if (e.isDirectory()) out.push(...filesUnder(
|
|
22905
|
+
if (e.isDirectory()) out.push(...filesUnder(join49(dir, e.name), rel));
|
|
22669
22906
|
else out.push(rel);
|
|
22670
22907
|
}
|
|
22671
22908
|
return out;
|
|
@@ -22676,7 +22913,7 @@ function skillStamp() {
|
|
|
22676
22913
|
function bundledSkillNames() {
|
|
22677
22914
|
const src = skillsSourceDir();
|
|
22678
22915
|
if (!existsSync46(src)) return [];
|
|
22679
|
-
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();
|
|
22680
22917
|
}
|
|
22681
22918
|
function realPathOrSelf(p) {
|
|
22682
22919
|
try {
|
|
@@ -22689,7 +22926,7 @@ function claudeSkillTargets() {
|
|
|
22689
22926
|
const targets = [];
|
|
22690
22927
|
const seen = /* @__PURE__ */ new Set();
|
|
22691
22928
|
for (const home of claudeHomeDirs()) {
|
|
22692
|
-
const dir =
|
|
22929
|
+
const dir = join49(home, "skills");
|
|
22693
22930
|
const key2 = realPathOrSelf(dir);
|
|
22694
22931
|
if (seen.has(key2)) continue;
|
|
22695
22932
|
seen.add(key2);
|
|
@@ -22700,7 +22937,7 @@ function claudeSkillTargets() {
|
|
|
22700
22937
|
dir,
|
|
22701
22938
|
// Judge each profile on ITS OWN transcripts, not the primary's: a home
|
|
22702
22939
|
// with no projects/ is a directory someone made, not a Claude install.
|
|
22703
|
-
available: existsSync46(
|
|
22940
|
+
available: existsSync46(join49(home, "projects"))
|
|
22704
22941
|
});
|
|
22705
22942
|
}
|
|
22706
22943
|
if (targets.length === 0) {
|
|
@@ -22715,16 +22952,16 @@ function skillTargets() {
|
|
|
22715
22952
|
// both produces "skill conflict" duplicate warnings. Every tool we support
|
|
22716
22953
|
// has its own dir, so per-tool coverage is complete.
|
|
22717
22954
|
...claudeSkillTargets(),
|
|
22718
|
-
{ id: "agy", label: "Antigravity", dir:
|
|
22955
|
+
{ id: "agy", label: "Antigravity", dir: join49(agyBackend.homeDir(), "skills"), available: agyBackend.isAvailable() },
|
|
22719
22956
|
{ id: "codex", label: "Codex", dir: codexBackend.skillsDir(), available: codexBackend.isAvailable() },
|
|
22720
22957
|
{ id: "opencode", label: "OpenCode", dir: opencodeBackend.skillsDir(), available: opencodeBackend.isAvailable() },
|
|
22721
22958
|
// Cursor DOES have its own dir (~/.cursor/skills). `skills-cursor` next to
|
|
22722
22959
|
// it is Cursor's bundled set — read-only, never an install target.
|
|
22723
|
-
{ id: "cursor", label: "Cursor", dir:
|
|
22960
|
+
{ id: "cursor", label: "Cursor", dir: join49(cursorHomeDir(), "skills"), available: cursorBackend.isAvailable() }
|
|
22724
22961
|
];
|
|
22725
22962
|
}
|
|
22726
22963
|
function isManaged(dir) {
|
|
22727
|
-
return existsSync46(
|
|
22964
|
+
return existsSync46(join49(dir, MARKER));
|
|
22728
22965
|
}
|
|
22729
22966
|
function installSkills(opts = {}) {
|
|
22730
22967
|
const onlyAvailable = opts.onlyAvailable ?? true;
|
|
@@ -22741,15 +22978,15 @@ function installSkills(opts = {}) {
|
|
|
22741
22978
|
continue;
|
|
22742
22979
|
}
|
|
22743
22980
|
for (const name of names) {
|
|
22744
|
-
const dest =
|
|
22981
|
+
const dest = join49(t.dir, name);
|
|
22745
22982
|
if (existsSync46(dest) && !isManaged(dest)) {
|
|
22746
22983
|
skippedUserOwned.push(name);
|
|
22747
22984
|
continue;
|
|
22748
22985
|
}
|
|
22749
22986
|
mkdirSync14(t.dir, { recursive: true });
|
|
22750
|
-
|
|
22751
|
-
cpSync(
|
|
22752
|
-
writeFileSync14(
|
|
22987
|
+
rmSync8(dest, { recursive: true, force: true });
|
|
22988
|
+
cpSync(join49(src, name), dest, { recursive: true });
|
|
22989
|
+
writeFileSync14(join49(dest, MARKER), `${stamp}
|
|
22753
22990
|
`);
|
|
22754
22991
|
installed.push(name);
|
|
22755
22992
|
}
|
|
@@ -22768,9 +23005,9 @@ function uninstallSkills() {
|
|
|
22768
23005
|
}
|
|
22769
23006
|
for (const entry of readdirSync32(t.dir, { withFileTypes: true })) {
|
|
22770
23007
|
if (!entry.isDirectory()) continue;
|
|
22771
|
-
const dir =
|
|
23008
|
+
const dir = join49(t.dir, entry.name);
|
|
22772
23009
|
if (isManaged(dir) && (names.has(entry.name) || entry.name.startsWith("chat-recall"))) {
|
|
22773
|
-
|
|
23010
|
+
rmSync8(dir, { recursive: true, force: true });
|
|
22774
23011
|
removed.push(entry.name);
|
|
22775
23012
|
}
|
|
22776
23013
|
}
|
|
@@ -22785,10 +23022,10 @@ function skillsNeedRefresh() {
|
|
|
22785
23022
|
for (const t of skillTargets()) {
|
|
22786
23023
|
if (!t.available) continue;
|
|
22787
23024
|
for (const name of names) {
|
|
22788
|
-
const marker =
|
|
23025
|
+
const marker = join49(t.dir, name, MARKER);
|
|
22789
23026
|
if (!existsSync46(marker)) return true;
|
|
22790
23027
|
try {
|
|
22791
|
-
if (
|
|
23028
|
+
if (readFileSync40(marker, "utf-8").trim() !== cur) return true;
|
|
22792
23029
|
} catch {
|
|
22793
23030
|
return true;
|
|
22794
23031
|
}
|
|
@@ -22803,11 +23040,11 @@ function skillStatus() {
|
|
|
22803
23040
|
let installed = 0;
|
|
22804
23041
|
let ver = null;
|
|
22805
23042
|
for (const name of names) {
|
|
22806
|
-
const marker =
|
|
23043
|
+
const marker = join49(t.dir, name, MARKER);
|
|
22807
23044
|
if (existsSync46(marker)) {
|
|
22808
23045
|
installed++;
|
|
22809
23046
|
try {
|
|
22810
|
-
ver =
|
|
23047
|
+
ver = readFileSync40(marker, "utf-8").trim();
|
|
22811
23048
|
} catch {
|
|
22812
23049
|
}
|
|
22813
23050
|
}
|
|
@@ -22831,8 +23068,8 @@ var init_install_skills = __esm({
|
|
|
22831
23068
|
});
|
|
22832
23069
|
|
|
22833
23070
|
// ../engine/dist/core/artifact-codec.js
|
|
22834
|
-
import { readFileSync as
|
|
22835
|
-
import { basename as basename22, join as
|
|
23071
|
+
import { readFileSync as readFileSync41 } from "fs";
|
|
23072
|
+
import { basename as basename22, join as join50 } from "path";
|
|
22836
23073
|
import { homedir as homedir18 } from "os";
|
|
22837
23074
|
function parseCommandText(content, format, fallbackName) {
|
|
22838
23075
|
if (format === "toml") {
|
|
@@ -22855,41 +23092,41 @@ function parseAgentText(content, format, fallbackName) {
|
|
|
22855
23092
|
return { name: fm.name || fallbackName, description: fm.description || "", tools: fm.tools, body: body2.trim() };
|
|
22856
23093
|
}
|
|
22857
23094
|
function readCommand(filePath, format) {
|
|
22858
|
-
return parseCommandText(
|
|
23095
|
+
return parseCommandText(readFileSync41(filePath, "utf-8"), format, base2(filePath));
|
|
22859
23096
|
}
|
|
22860
23097
|
function readAgent(filePath, format) {
|
|
22861
|
-
return parseAgentText(
|
|
23098
|
+
return parseAgentText(readFileSync41(filePath, "utf-8"), format, base2(filePath));
|
|
22862
23099
|
}
|
|
22863
23100
|
function readInstructions(filePath, name) {
|
|
22864
|
-
const content =
|
|
23101
|
+
const content = readFileSync41(filePath, "utf-8");
|
|
22865
23102
|
return { name, description: "", body: content };
|
|
22866
23103
|
}
|
|
22867
23104
|
function commandPath(tool, name) {
|
|
22868
23105
|
switch (tool) {
|
|
22869
23106
|
case "claude":
|
|
22870
|
-
return
|
|
23107
|
+
return join50(claudeBackend.commandsDir(), `${name}.md`);
|
|
22871
23108
|
case "agy":
|
|
22872
|
-
return
|
|
23109
|
+
return join50(join50(agyBackend.homeDir(), "commands"), `${name}.toml`);
|
|
22873
23110
|
case "opencode":
|
|
22874
|
-
return
|
|
23111
|
+
return join50(opencodeBackend.commandsDir(), `${name}.md`);
|
|
22875
23112
|
case "codex":
|
|
22876
|
-
return
|
|
23113
|
+
return join50(codexBackend.promptsDir(), `${name}.md`);
|
|
22877
23114
|
case "cursor":
|
|
22878
|
-
return
|
|
23115
|
+
return join50(cursorHomeDir(), "commands", `${name}.md`);
|
|
22879
23116
|
}
|
|
22880
23117
|
}
|
|
22881
23118
|
function agentPath(tool, name) {
|
|
22882
23119
|
switch (tool) {
|
|
22883
23120
|
case "claude":
|
|
22884
|
-
return
|
|
23121
|
+
return join50(claudeBackend.agentsDir(), `${name}.md`);
|
|
22885
23122
|
case "agy":
|
|
22886
|
-
return
|
|
23123
|
+
return join50(join50(agyBackend.homeDir(), "agents"), `${name}.md`);
|
|
22887
23124
|
case "opencode":
|
|
22888
|
-
return
|
|
23125
|
+
return join50(opencodeBackend.agentsDir(), `${name}.md`);
|
|
22889
23126
|
case "codex":
|
|
22890
|
-
return
|
|
23127
|
+
return join50(codexBackend.agentsDir(), `${name}.toml`);
|
|
22891
23128
|
case "cursor":
|
|
22892
|
-
return
|
|
23129
|
+
return join50(cursorHomeDir(), "agents", `${name}.md`);
|
|
22893
23130
|
}
|
|
22894
23131
|
}
|
|
22895
23132
|
function instructionsFilename(tool) {
|
|
@@ -22914,21 +23151,21 @@ function instructionsFilename(tool) {
|
|
|
22914
23151
|
function instructionsPath(tool, projectPath) {
|
|
22915
23152
|
const file = instructionsFilename(tool);
|
|
22916
23153
|
if (projectPath)
|
|
22917
|
-
return
|
|
23154
|
+
return join50(projectPath, file);
|
|
22918
23155
|
switch (tool) {
|
|
22919
23156
|
case "claude":
|
|
22920
|
-
return
|
|
23157
|
+
return join50(claudeBackend.homeDir(), file);
|
|
22921
23158
|
case "agy":
|
|
22922
|
-
return
|
|
23159
|
+
return join50(agyBackend.homeDir(), file);
|
|
22923
23160
|
case "codex":
|
|
22924
|
-
return
|
|
23161
|
+
return join50(codexBackend.homeDir(), file);
|
|
22925
23162
|
case "opencode":
|
|
22926
|
-
return
|
|
23163
|
+
return join50(homedir18(), ".config", "opencode", file);
|
|
22927
23164
|
// Cursor has no single user-scope instructions FILE — user-level guidance
|
|
22928
23165
|
// is User Rules plus ~/.cursor/rules/*.mdc. AGENTS.md at the home root is
|
|
22929
23166
|
// the closest equivalent and is what a mirror can actually write.
|
|
22930
23167
|
case "cursor":
|
|
22931
|
-
return
|
|
23168
|
+
return join50(cursorHomeDir(), file);
|
|
22932
23169
|
}
|
|
22933
23170
|
}
|
|
22934
23171
|
function emit(type, art, toTool, projectPath) {
|
|
@@ -22992,8 +23229,8 @@ __export(toolkit_sync_exports, {
|
|
|
22992
23229
|
supportedTargetsFor: () => supportedTargetsFor,
|
|
22993
23230
|
writeMcpEntry: () => writeMcpEntry
|
|
22994
23231
|
});
|
|
22995
|
-
import { existsSync as existsSync47, mkdirSync as mkdirSync15, readFileSync as
|
|
22996
|
-
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";
|
|
22997
23234
|
import { homedir as homedir19 } from "os";
|
|
22998
23235
|
function supportedTargetsFor(type) {
|
|
22999
23236
|
return SUPPORTED_TARGETS[type];
|
|
@@ -23035,14 +23272,14 @@ function skillsDirFor(tool) {
|
|
|
23035
23272
|
case "claude":
|
|
23036
23273
|
return claudeBackend.skillsDir();
|
|
23037
23274
|
case "agy":
|
|
23038
|
-
return
|
|
23275
|
+
return join51(agyBackend.homeDir(), "skills");
|
|
23039
23276
|
case "opencode":
|
|
23040
23277
|
return opencodeBackend.skillsDir();
|
|
23041
23278
|
case "codex":
|
|
23042
23279
|
return codexBackend.skillsDir();
|
|
23043
23280
|
// user skills, NOT .system
|
|
23044
23281
|
case "cursor":
|
|
23045
|
-
return
|
|
23282
|
+
return join51(cursorHomeDir(), "skills");
|
|
23046
23283
|
}
|
|
23047
23284
|
}
|
|
23048
23285
|
function copySkill(row, toTool) {
|
|
@@ -23050,7 +23287,7 @@ function copySkill(row, toTool) {
|
|
|
23050
23287
|
if (!existsSync47(skillDir))
|
|
23051
23288
|
return { ok: false, status: 404, error: `Source dir missing: ${skillDir}` };
|
|
23052
23289
|
const name = row.extra.skillName || basename23(skillDir);
|
|
23053
|
-
const targetDir =
|
|
23290
|
+
const targetDir = join51(skillsDirFor(toTool), name);
|
|
23054
23291
|
if (existsSync47(targetDir))
|
|
23055
23292
|
return { ok: false, status: 409, error: `Already exists: ${targetDir}` };
|
|
23056
23293
|
try {
|
|
@@ -23065,20 +23302,20 @@ function readMcpEntry(tool, name) {
|
|
|
23065
23302
|
const home = homedir19();
|
|
23066
23303
|
const tries = [];
|
|
23067
23304
|
if (tool === "claude") {
|
|
23068
|
-
tries.push({ path:
|
|
23069
|
-
tries.push({ path:
|
|
23305
|
+
tries.push({ path: join51(home, ".mcp.json"), key: "mcpServers" });
|
|
23306
|
+
tries.push({ path: join51(home, ".claude.json"), key: "mcpServers" });
|
|
23070
23307
|
} else if (tool === "gemini") {
|
|
23071
|
-
tries.push({ path:
|
|
23308
|
+
tries.push({ path: join51(home, ".gemini", "settings.json"), key: "mcpServers" });
|
|
23072
23309
|
} else if (tool === "agy") {
|
|
23073
|
-
tries.push({ path:
|
|
23310
|
+
tries.push({ path: join51(home, ".gemini", "config", "mcp_config.json"), key: "mcpServers" });
|
|
23074
23311
|
} else if (tool === "cursor") {
|
|
23075
|
-
tries.push({ path:
|
|
23312
|
+
tries.push({ path: join51(cursorHomeDir(), "mcp.json"), key: "mcpServers" });
|
|
23076
23313
|
} else if (tool === "opencode") {
|
|
23077
|
-
tries.push({ path:
|
|
23078
|
-
tries.push({ path:
|
|
23079
|
-
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" });
|
|
23080
23317
|
} else if (tool === "codex") {
|
|
23081
|
-
const entry = readCodexMcpEntry(
|
|
23318
|
+
const entry = readCodexMcpEntry(join51(home, ".codex", "config.toml"), name);
|
|
23082
23319
|
if (entry)
|
|
23083
23320
|
return entry;
|
|
23084
23321
|
}
|
|
@@ -23086,7 +23323,7 @@ function readMcpEntry(tool, name) {
|
|
|
23086
23323
|
if (!existsSync47(t.path))
|
|
23087
23324
|
continue;
|
|
23088
23325
|
try {
|
|
23089
|
-
const cfg = JSON.parse(
|
|
23326
|
+
const cfg = JSON.parse(readFileSync42(t.path, "utf-8"));
|
|
23090
23327
|
const block = cfg[t.key] || {};
|
|
23091
23328
|
if (block[name])
|
|
23092
23329
|
return block[name];
|
|
@@ -23100,7 +23337,7 @@ function readCodexMcpEntry(path, target) {
|
|
|
23100
23337
|
return null;
|
|
23101
23338
|
let content;
|
|
23102
23339
|
try {
|
|
23103
|
-
content =
|
|
23340
|
+
content = readFileSync42(path, "utf-8");
|
|
23104
23341
|
} catch {
|
|
23105
23342
|
return null;
|
|
23106
23343
|
}
|
|
@@ -23151,7 +23388,7 @@ function readCodexMcpEntry(path, target) {
|
|
|
23151
23388
|
function writeCodexMcpEntry(path, name, entry) {
|
|
23152
23389
|
let content = "";
|
|
23153
23390
|
if (existsSync47(path))
|
|
23154
|
-
content =
|
|
23391
|
+
content = readFileSync42(path, "utf-8");
|
|
23155
23392
|
const header = `[mcp_servers.${name}]`;
|
|
23156
23393
|
if (content.includes(header))
|
|
23157
23394
|
return false;
|
|
@@ -23187,7 +23424,7 @@ function writeCodexMcpEntry(path, name, entry) {
|
|
|
23187
23424
|
function writeMcpEntry(toTool, name, entry) {
|
|
23188
23425
|
const home = homedir19();
|
|
23189
23426
|
if (toTool === "codex") {
|
|
23190
|
-
const path2 =
|
|
23427
|
+
const path2 = join51(home, ".codex", "config.toml");
|
|
23191
23428
|
if (!writeCodexMcpEntry(path2, name, entry))
|
|
23192
23429
|
return { ok: false, status: 409, error: `MCP "${name}" already exists in ${path2}.` };
|
|
23193
23430
|
return { ok: true, targetPath: path2 };
|
|
@@ -23195,22 +23432,22 @@ function writeMcpEntry(toTool, name, entry) {
|
|
|
23195
23432
|
let path;
|
|
23196
23433
|
let key2;
|
|
23197
23434
|
if (toTool === "claude") {
|
|
23198
|
-
path =
|
|
23435
|
+
path = join51(home, ".mcp.json");
|
|
23199
23436
|
key2 = "mcpServers";
|
|
23200
23437
|
} else if (toTool === "agy") {
|
|
23201
|
-
path =
|
|
23438
|
+
path = join51(home, ".gemini", "config", "mcp_config.json");
|
|
23202
23439
|
key2 = "mcpServers";
|
|
23203
23440
|
} else if (toTool === "cursor") {
|
|
23204
|
-
path =
|
|
23441
|
+
path = join51(cursorHomeDir(), "mcp.json");
|
|
23205
23442
|
key2 = "mcpServers";
|
|
23206
23443
|
} else {
|
|
23207
|
-
path =
|
|
23444
|
+
path = join51(home, ".config", "opencode", "opencode.json");
|
|
23208
23445
|
key2 = "mcp";
|
|
23209
23446
|
}
|
|
23210
23447
|
let cfg = {};
|
|
23211
23448
|
if (existsSync47(path)) {
|
|
23212
23449
|
try {
|
|
23213
|
-
cfg = JSON.parse(
|
|
23450
|
+
cfg = JSON.parse(readFileSync42(path, "utf-8"));
|
|
23214
23451
|
} catch {
|
|
23215
23452
|
return { ok: false, status: 500, error: `Target config is malformed: ${path}` };
|
|
23216
23453
|
}
|
|
@@ -23443,11 +23680,11 @@ __export(toolkit_pull_exports, {
|
|
|
23443
23680
|
platformRefusal: () => platformRefusal,
|
|
23444
23681
|
portableCommand: () => portableCommand
|
|
23445
23682
|
});
|
|
23446
|
-
import { existsSync as existsSync48, mkdirSync as mkdirSync16, statSync as
|
|
23447
|
-
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";
|
|
23448
23685
|
function isExecutableFile(p) {
|
|
23449
23686
|
try {
|
|
23450
|
-
return
|
|
23687
|
+
return statSync43(p).isFile();
|
|
23451
23688
|
} catch {
|
|
23452
23689
|
return false;
|
|
23453
23690
|
}
|
|
@@ -23614,8 +23851,8 @@ function executePull(rows, opts = {}) {
|
|
|
23614
23851
|
const outcomes = [];
|
|
23615
23852
|
for (const { name, body: body2, truncated, redacted, tools } of skills) {
|
|
23616
23853
|
for (const tool of tools) {
|
|
23617
|
-
const dir =
|
|
23618
|
-
const file =
|
|
23854
|
+
const dir = join52(skillsDirFor(tool), name);
|
|
23855
|
+
const file = join52(dir, "SKILL.md");
|
|
23619
23856
|
if (existsSync48(file)) {
|
|
23620
23857
|
outcomes.push({ type: "skill", name, tool, status: "present" });
|
|
23621
23858
|
continue;
|
|
@@ -23824,8 +24061,8 @@ __export(board_hooks_exports, {
|
|
|
23824
24061
|
removeBoardHooks: () => removeBoardHooks,
|
|
23825
24062
|
resolveCliEntry: () => resolveCliEntry
|
|
23826
24063
|
});
|
|
23827
|
-
import { existsSync as existsSync49, mkdirSync as mkdirSync17, readFileSync as
|
|
23828
|
-
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";
|
|
23829
24066
|
function boardHookCommand(execPath, cliEntry, mode) {
|
|
23830
24067
|
return `"${execPath}" "${cliEntry}" task-hook --${mode}`;
|
|
23831
24068
|
}
|
|
@@ -23866,7 +24103,7 @@ function removeBoardHooks(config2) {
|
|
|
23866
24103
|
function readConfig(file) {
|
|
23867
24104
|
if (!existsSync49(file)) return { hooks: {} };
|
|
23868
24105
|
try {
|
|
23869
|
-
const parsed = JSON.parse(
|
|
24106
|
+
const parsed = JSON.parse(readFileSync43(file, "utf-8"));
|
|
23870
24107
|
if (!parsed.hooks || typeof parsed.hooks !== "object") parsed.hooks = {};
|
|
23871
24108
|
return parsed;
|
|
23872
24109
|
} catch {
|
|
@@ -23878,7 +24115,7 @@ function registerBoardHooks(files, execPath, cliEntry) {
|
|
|
23878
24115
|
for (const file of files) {
|
|
23879
24116
|
if (existsSync49(file)) {
|
|
23880
24117
|
try {
|
|
23881
|
-
JSON.parse(
|
|
24118
|
+
JSON.parse(readFileSync43(file, "utf-8"));
|
|
23882
24119
|
} catch {
|
|
23883
24120
|
continue;
|
|
23884
24121
|
}
|
|
@@ -23895,8 +24132,8 @@ function registerBoardHooks(files, execPath, cliEntry) {
|
|
|
23895
24132
|
return written;
|
|
23896
24133
|
}
|
|
23897
24134
|
function resolveCliEntry(distDir) {
|
|
23898
|
-
const bundled =
|
|
23899
|
-
return existsSync49(bundled) ? bundled :
|
|
24135
|
+
const bundled = join53(distDir, "cli.js");
|
|
24136
|
+
return existsSync49(bundled) ? bundled : join53(distDir, "cli.ts");
|
|
23900
24137
|
}
|
|
23901
24138
|
var BOARD_HOOKS;
|
|
23902
24139
|
var init_board_hooks = __esm({
|
|
@@ -24105,11 +24342,16 @@ async function repairAll(opts = {}) {
|
|
|
24105
24342
|
scanned++;
|
|
24106
24343
|
if (opts.verbose && scanned % 50 === 0) log6(`checked ${scanned}/${ids.length}\u2026`);
|
|
24107
24344
|
const arch = await fetchJson(`${primary.url}/api/conversations/${id}/raw-archive?count=1`, primary.token);
|
|
24108
|
-
const
|
|
24109
|
-
if (
|
|
24110
|
-
|
|
24111
|
-
|
|
24112
|
-
|
|
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
|
+
}
|
|
24113
24355
|
const r = await repairSession(id, { dryRun: !opts.apply, verbose: opts.verbose, server: opts.server });
|
|
24114
24356
|
if (r.status === "already-full") continue;
|
|
24115
24357
|
candidates2.push(r);
|
|
@@ -24294,21 +24536,21 @@ __export(guard_registration_exports, {
|
|
|
24294
24536
|
unregisterGuard: () => unregisterGuard
|
|
24295
24537
|
});
|
|
24296
24538
|
import { homedir as homedir20 } from "os";
|
|
24297
|
-
import { join as
|
|
24539
|
+
import { join as join54 } from "path";
|
|
24298
24540
|
function opencodeConfigDir() {
|
|
24299
24541
|
const xdg = process.env.XDG_CONFIG_HOME;
|
|
24300
|
-
const base4 = xdg && xdg.trim() ? xdg :
|
|
24301
|
-
return
|
|
24542
|
+
const base4 = xdg && xdg.trim() ? xdg : join54(homedir20(), ".config");
|
|
24543
|
+
return join54(base4, "opencode");
|
|
24302
24544
|
}
|
|
24303
24545
|
function opencodePluginDir() {
|
|
24304
|
-
return
|
|
24546
|
+
return join54(opencodeConfigDir(), "plugins");
|
|
24305
24547
|
}
|
|
24306
24548
|
function guardTargets() {
|
|
24307
24549
|
return [
|
|
24308
24550
|
{
|
|
24309
24551
|
tool: "codex",
|
|
24310
24552
|
label: "Codex",
|
|
24311
|
-
configPath:
|
|
24553
|
+
configPath: join54(codexBackend.homeDir(), "hooks.json"),
|
|
24312
24554
|
homeDir: codexBackend.homeDir(),
|
|
24313
24555
|
// Codex will not run a hook until a person has reviewed it, and the
|
|
24314
24556
|
// approval is bound to the hook's hash. There is no way to grant it from
|
|
@@ -24321,20 +24563,20 @@ function guardTargets() {
|
|
|
24321
24563
|
{
|
|
24322
24564
|
tool: "agy",
|
|
24323
24565
|
label: "Antigravity",
|
|
24324
|
-
configPath:
|
|
24566
|
+
configPath: join54(agyBackend.homeDir(), "hooks.json"),
|
|
24325
24567
|
homeDir: agyBackend.homeDir()
|
|
24326
24568
|
},
|
|
24327
24569
|
{
|
|
24328
24570
|
tool: "cursor",
|
|
24329
24571
|
label: "Cursor",
|
|
24330
|
-
configPath:
|
|
24572
|
+
configPath: join54(cursorBackend.homeDir(), "hooks.json"),
|
|
24331
24573
|
homeDir: cursorBackend.homeDir(),
|
|
24332
24574
|
note: "Cursor checks a shell command before it runs and a file edit after it is written."
|
|
24333
24575
|
},
|
|
24334
24576
|
{
|
|
24335
24577
|
tool: "opencode",
|
|
24336
24578
|
label: "OpenCode",
|
|
24337
|
-
configPath:
|
|
24579
|
+
configPath: join54(opencodePluginDir(), "chat-recall-guard.js"),
|
|
24338
24580
|
homeDir: opencodeConfigDir(),
|
|
24339
24581
|
note: "OpenCode plugin hooks do not fire for subagent tool calls, so a delegating agent bypasses this."
|
|
24340
24582
|
}
|
|
@@ -24757,8 +24999,8 @@ __export(collector_exports, {
|
|
|
24757
24999
|
});
|
|
24758
25000
|
import { spawn as spawn3 } from "node:child_process";
|
|
24759
25001
|
import { execSync as execSync4 } from "node:child_process";
|
|
24760
|
-
import { readFileSync as
|
|
24761
|
-
import { join as
|
|
25002
|
+
import { readFileSync as readFileSync44 } from "node:fs";
|
|
25003
|
+
import { join as join55, basename as basename26 } from "node:path";
|
|
24762
25004
|
async function resolveCodeindexBin(autoInstall = true) {
|
|
24763
25005
|
let st = checkCodeindexStatus();
|
|
24764
25006
|
if (!st.installed && autoInstall)
|
|
@@ -24940,7 +25182,7 @@ async function collectCode(opts) {
|
|
|
24940
25182
|
}
|
|
24941
25183
|
const complexity = (r) => {
|
|
24942
25184
|
try {
|
|
24943
|
-
const txt =
|
|
25185
|
+
const txt = readFileSync44(join55(ws, r), "utf8");
|
|
24944
25186
|
if (txt.length > 2e6)
|
|
24945
25187
|
return 1;
|
|
24946
25188
|
const m = txt.match(CF_RE);
|
|
@@ -25724,8 +25966,8 @@ __export(project_tasks_exports, {
|
|
|
25724
25966
|
pushProjectTaskStatuses: () => pushProjectTaskStatuses,
|
|
25725
25967
|
renderTeamTasksMd: () => renderTeamTasksMd
|
|
25726
25968
|
});
|
|
25727
|
-
import { existsSync as existsSync51, readFileSync as
|
|
25728
|
-
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";
|
|
25729
25971
|
import { homedir as homedir21 } from "node:os";
|
|
25730
25972
|
function isTeamTaskStatus(v) {
|
|
25731
25973
|
return !!v && TEAM_STATUSES.has(v);
|
|
@@ -25776,11 +26018,11 @@ function parseTaskFile(content) {
|
|
|
25776
26018
|
return out;
|
|
25777
26019
|
}
|
|
25778
26020
|
function ledgerPath2() {
|
|
25779
|
-
return
|
|
26021
|
+
return join56(homedir21(), ".chat-recall", "project-tasks-ledger.json");
|
|
25780
26022
|
}
|
|
25781
26023
|
function readLedger() {
|
|
25782
26024
|
try {
|
|
25783
|
-
return JSON.parse(
|
|
26025
|
+
return JSON.parse(readFileSync45(ledgerPath2(), "utf8"));
|
|
25784
26026
|
} catch {
|
|
25785
26027
|
return {};
|
|
25786
26028
|
}
|
|
@@ -25809,18 +26051,18 @@ async function pushProjectTaskStatuses(base4, authHeaders, opts = {}) {
|
|
|
25809
26051
|
continue;
|
|
25810
26052
|
}
|
|
25811
26053
|
for (const project of projects) {
|
|
25812
|
-
const file =
|
|
26054
|
+
const file = join56(project, fk.filename);
|
|
25813
26055
|
if (!existsSync51(file)) continue;
|
|
25814
26056
|
let mtime;
|
|
25815
26057
|
try {
|
|
25816
|
-
mtime =
|
|
26058
|
+
mtime = statSync44(file).mtimeMs;
|
|
25817
26059
|
} catch {
|
|
25818
26060
|
continue;
|
|
25819
26061
|
}
|
|
25820
26062
|
if (ledger[file] === mtime) continue;
|
|
25821
26063
|
let changed;
|
|
25822
26064
|
try {
|
|
25823
|
-
changed = parseTaskFile(
|
|
26065
|
+
changed = parseTaskFile(readFileSync45(file, "utf8")).filter((t) => t.kind === fk.kind);
|
|
25824
26066
|
} catch {
|
|
25825
26067
|
continue;
|
|
25826
26068
|
}
|
|
@@ -25892,8 +26134,8 @@ __export(intent_drain_exports, {
|
|
|
25892
26134
|
drainSyncIntents: () => drainSyncIntents,
|
|
25893
26135
|
instructionTargets: () => instructionTargets
|
|
25894
26136
|
});
|
|
25895
|
-
import { existsSync as existsSync52, readFileSync as
|
|
25896
|
-
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";
|
|
25897
26139
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
25898
26140
|
import { dirname as dirname26 } from "node:path";
|
|
25899
26141
|
function instructionTargets(rootPath, isGlobal) {
|
|
@@ -25907,16 +26149,16 @@ function instructionTargets(rootPath, isGlobal) {
|
|
|
25907
26149
|
const tools = installed.length ? installed : [INSTRUCTION_TOOLS[0]];
|
|
25908
26150
|
if (isGlobal) return [...new Set(tools.map((t) => instructionsPath(t.id)))];
|
|
25909
26151
|
if (!rootPath) return [];
|
|
25910
|
-
const present = INSTRUCTION_FILENAMES.map((f) =>
|
|
26152
|
+
const present = INSTRUCTION_FILENAMES.map((f) => join57(rootPath, f)).filter((p) => existsSync52(p));
|
|
25911
26153
|
if (present.length) return present;
|
|
25912
|
-
return [...new Set(tools.map((t) =>
|
|
26154
|
+
return [...new Set(tools.map((t) => join57(rootPath, instructionsFilename(t.id))))];
|
|
25913
26155
|
}
|
|
25914
26156
|
function applyCodeRecommendation(intent) {
|
|
25915
26157
|
try {
|
|
25916
26158
|
const meta = JSON.parse(intent.name || "{}");
|
|
25917
26159
|
if (intent.artifact_type === "write_tasks_file") {
|
|
25918
26160
|
if (!meta.rootPath || !meta.content) return { status: "error", result: JSON.stringify({ error: "missing rootPath or content" }) };
|
|
25919
|
-
const file =
|
|
26161
|
+
const file = join57(meta.rootPath, meta.filename || "CODE_TASKS.md");
|
|
25920
26162
|
writeFileSync19(file, meta.content);
|
|
25921
26163
|
return { status: "done", result: JSON.stringify({ wrote: file }) };
|
|
25922
26164
|
}
|
|
@@ -25935,7 +26177,7 @@ function applyCodeRecommendation(intent) {
|
|
|
25935
26177
|
mkdirSync19(dir, { recursive: true });
|
|
25936
26178
|
} catch {
|
|
25937
26179
|
}
|
|
25938
|
-
const existing = existsSync52(file) ?
|
|
26180
|
+
const existing = existsSync52(file) ? readFileSync46(file, "utf8") : "";
|
|
25939
26181
|
if (existing.includes(text)) {
|
|
25940
26182
|
skipped.push(file);
|
|
25941
26183
|
continue;
|
|
@@ -26110,10 +26352,10 @@ var init_intent_drain = __esm({
|
|
|
26110
26352
|
ownVersion2 = "0.0.0";
|
|
26111
26353
|
try {
|
|
26112
26354
|
const dir = dirname26(fileURLToPath4(import.meta.url));
|
|
26113
|
-
ownVersion2 = JSON.parse(
|
|
26355
|
+
ownVersion2 = JSON.parse(readFileSync46(join57(dir, "../package.json"), "utf-8")).version || ownVersion2;
|
|
26114
26356
|
} catch {
|
|
26115
26357
|
try {
|
|
26116
|
-
if (true) ownVersion2 = "0.7.
|
|
26358
|
+
if (true) ownVersion2 = "0.7.18";
|
|
26117
26359
|
} catch {
|
|
26118
26360
|
}
|
|
26119
26361
|
}
|
|
@@ -26314,48 +26556,48 @@ var team_merge_exports = {};
|
|
|
26314
26556
|
__export(team_merge_exports, {
|
|
26315
26557
|
mergePullResult: () => mergePullResult
|
|
26316
26558
|
});
|
|
26317
|
-
import { existsSync as existsSync53, mkdirSync as mkdirSync20, readFileSync as
|
|
26318
|
-
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";
|
|
26319
26561
|
import { createHash as createHash14 } from "crypto";
|
|
26320
26562
|
function installPathFor(art, tool) {
|
|
26321
26563
|
switch (art.type) {
|
|
26322
26564
|
case "skill":
|
|
26323
26565
|
switch (tool) {
|
|
26324
26566
|
case "claude":
|
|
26325
|
-
return
|
|
26567
|
+
return join58(claudeBackend.skillsDir(), art.name, "SKILL.md");
|
|
26326
26568
|
// Antigravity's OWN skills dir. It used to resolve to the shared
|
|
26327
26569
|
// ~/.gemini/skills while toolkit-sync installed to
|
|
26328
26570
|
// ~/.gemini/antigravity-cli/skills, so a team skill landed in one place
|
|
26329
26571
|
// and a synced skill in the other.
|
|
26330
26572
|
case "agy":
|
|
26331
|
-
return
|
|
26573
|
+
return join58(agyBackend.homeDir(), "skills", art.name, "SKILL.md");
|
|
26332
26574
|
case "opencode":
|
|
26333
|
-
return
|
|
26575
|
+
return join58(opencodeBackend.skillsDir(), art.name, "SKILL.md");
|
|
26334
26576
|
// User skills go to ~/.codex/skills (NOT .system, which is OpenAI's bundle).
|
|
26335
26577
|
case "codex":
|
|
26336
|
-
return
|
|
26578
|
+
return join58(codexBackend.skillsDir(), art.name, "SKILL.md");
|
|
26337
26579
|
case "cursor":
|
|
26338
|
-
return
|
|
26580
|
+
return join58(cursorHomeDir(), "skills", art.name, "SKILL.md");
|
|
26339
26581
|
}
|
|
26340
26582
|
break;
|
|
26341
26583
|
case "agent":
|
|
26342
26584
|
if (tool === "claude")
|
|
26343
|
-
return
|
|
26585
|
+
return join58(claudeBackend.agentsDir(), `${art.name}.md`);
|
|
26344
26586
|
return null;
|
|
26345
26587
|
case "command":
|
|
26346
26588
|
if (tool === "claude")
|
|
26347
|
-
return
|
|
26589
|
+
return join58(claudeBackend.commandsDir(), `${art.name}.md`);
|
|
26348
26590
|
return null;
|
|
26349
26591
|
case "hook":
|
|
26350
26592
|
if (tool === "claude")
|
|
26351
|
-
return
|
|
26593
|
+
return join58(claudeBackend.homeDir(), "chat-recall-hooks", `${art.name}.json`);
|
|
26352
26594
|
return null;
|
|
26353
26595
|
case "plan":
|
|
26354
26596
|
switch (tool) {
|
|
26355
26597
|
case "claude":
|
|
26356
|
-
return
|
|
26598
|
+
return join58(claudeBackend.plansDir(), `${art.name}.md`);
|
|
26357
26599
|
case "opencode":
|
|
26358
|
-
return
|
|
26600
|
+
return join58(opencodeBackend.plansDir(), `${art.name}.md`);
|
|
26359
26601
|
case "agy":
|
|
26360
26602
|
return null;
|
|
26361
26603
|
// Antigravity plans live per-session
|
|
@@ -26366,11 +26608,11 @@ function installPathFor(art, tool) {
|
|
|
26366
26608
|
}
|
|
26367
26609
|
break;
|
|
26368
26610
|
case "instructions":
|
|
26369
|
-
return
|
|
26611
|
+
return join58(getDataDir(), "team-instructions", tool, `${art.name}.md`);
|
|
26370
26612
|
case "mcp":
|
|
26371
|
-
return
|
|
26613
|
+
return join58(getDataDir(), "team-mcps", `${art.name}.json`);
|
|
26372
26614
|
case "plugin":
|
|
26373
|
-
return
|
|
26615
|
+
return join58(getDataDir(), "team-plugins", tool, art.name, "manifest.json");
|
|
26374
26616
|
}
|
|
26375
26617
|
return null;
|
|
26376
26618
|
}
|
|
@@ -26432,7 +26674,7 @@ async function mergePullResult(opts) {
|
|
|
26432
26674
|
continue;
|
|
26433
26675
|
try {
|
|
26434
26676
|
if (existsSync53(path))
|
|
26435
|
-
|
|
26677
|
+
rmSync9(path, { force: true });
|
|
26436
26678
|
await teamInstallsForget(id, row.tool);
|
|
26437
26679
|
report.removed.push({ artifactId: id, path });
|
|
26438
26680
|
} catch (err) {
|
|
@@ -26451,10 +26693,10 @@ function readFileIfExists(path) {
|
|
|
26451
26693
|
try {
|
|
26452
26694
|
if (!existsSync53(path))
|
|
26453
26695
|
return null;
|
|
26454
|
-
const s =
|
|
26696
|
+
const s = statSync45(path);
|
|
26455
26697
|
if (!s.isFile())
|
|
26456
26698
|
return null;
|
|
26457
|
-
return
|
|
26699
|
+
return readFileSync47(path);
|
|
26458
26700
|
} catch {
|
|
26459
26701
|
return null;
|
|
26460
26702
|
}
|
|
@@ -26535,8 +26777,8 @@ var init_vault_crypto = __esm({
|
|
|
26535
26777
|
});
|
|
26536
26778
|
|
|
26537
26779
|
// ../engine/dist/core/vault-source.js
|
|
26538
|
-
import { existsSync as existsSync54, readdirSync as readdirSync33, statSync as
|
|
26539
|
-
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";
|
|
26540
26782
|
function* walkVaultSources() {
|
|
26541
26783
|
const t = loadSettings().team.vault;
|
|
26542
26784
|
const include2 = new Set(t.syncTools);
|
|
@@ -26551,7 +26793,7 @@ function* walkVaultSources() {
|
|
|
26551
26793
|
}
|
|
26552
26794
|
function safeStat(path) {
|
|
26553
26795
|
try {
|
|
26554
|
-
const s =
|
|
26796
|
+
const s = statSync46(path);
|
|
26555
26797
|
if (!s.isFile())
|
|
26556
26798
|
return null;
|
|
26557
26799
|
return { mtimeMs: s.mtimeMs, size: s.size };
|
|
@@ -26573,7 +26815,7 @@ function* walkClaude() {
|
|
|
26573
26815
|
if (proj.startsWith("."))
|
|
26574
26816
|
continue;
|
|
26575
26817
|
const projectPath = resolveProjectDirName(proj);
|
|
26576
|
-
const projDir =
|
|
26818
|
+
const projDir = join59(root, proj);
|
|
26577
26819
|
let entries = [];
|
|
26578
26820
|
try {
|
|
26579
26821
|
entries = readdirSync33(projDir);
|
|
@@ -26583,7 +26825,7 @@ function* walkClaude() {
|
|
|
26583
26825
|
for (const f of entries) {
|
|
26584
26826
|
if (extname(f) !== ".jsonl")
|
|
26585
26827
|
continue;
|
|
26586
|
-
const path =
|
|
26828
|
+
const path = join59(projDir, f);
|
|
26587
26829
|
const s = safeStat(path);
|
|
26588
26830
|
if (!s)
|
|
26589
26831
|
continue;
|
|
@@ -26613,7 +26855,7 @@ function* walkCursor() {
|
|
|
26613
26855
|
}
|
|
26614
26856
|
}
|
|
26615
26857
|
function* walkCodex() {
|
|
26616
|
-
const sessionsRoot =
|
|
26858
|
+
const sessionsRoot = join59(codexBackend.homeDir(), "sessions");
|
|
26617
26859
|
if (!existsSync54(sessionsRoot))
|
|
26618
26860
|
return;
|
|
26619
26861
|
const stack = [sessionsRoot];
|
|
@@ -26626,7 +26868,7 @@ function* walkCodex() {
|
|
|
26626
26868
|
continue;
|
|
26627
26869
|
}
|
|
26628
26870
|
for (const e of entries) {
|
|
26629
|
-
const path =
|
|
26871
|
+
const path = join59(dir, e.name);
|
|
26630
26872
|
if (e.isDirectory()) {
|
|
26631
26873
|
stack.push(path);
|
|
26632
26874
|
continue;
|
|
@@ -26642,7 +26884,7 @@ function* walkCodex() {
|
|
|
26642
26884
|
}
|
|
26643
26885
|
}
|
|
26644
26886
|
function* walkAgy() {
|
|
26645
|
-
const brainDir =
|
|
26887
|
+
const brainDir = join59(agyBackend.homeDir(), "brain");
|
|
26646
26888
|
if (!existsSync54(brainDir))
|
|
26647
26889
|
return;
|
|
26648
26890
|
let sessionDirs = [];
|
|
@@ -26652,16 +26894,16 @@ function* walkAgy() {
|
|
|
26652
26894
|
return;
|
|
26653
26895
|
}
|
|
26654
26896
|
for (const rawId of sessionDirs) {
|
|
26655
|
-
const sessionPath =
|
|
26897
|
+
const sessionPath = join59(brainDir, rawId);
|
|
26656
26898
|
try {
|
|
26657
|
-
if (!
|
|
26899
|
+
if (!statSync46(sessionPath).isDirectory())
|
|
26658
26900
|
continue;
|
|
26659
26901
|
} catch {
|
|
26660
26902
|
continue;
|
|
26661
26903
|
}
|
|
26662
|
-
let filePath =
|
|
26904
|
+
let filePath = join59(sessionPath, ".system_generated", "logs", "transcript.jsonl");
|
|
26663
26905
|
if (!existsSync54(filePath)) {
|
|
26664
|
-
filePath =
|
|
26906
|
+
filePath = join59(sessionPath, ".system_generated", "logs", "transcript_full.jsonl");
|
|
26665
26907
|
}
|
|
26666
26908
|
if (!existsSync54(filePath))
|
|
26667
26909
|
continue;
|
|
@@ -26699,8 +26941,8 @@ __export(vault_client_exports, {
|
|
|
26699
26941
|
vaultStatus: () => vaultStatus,
|
|
26700
26942
|
vaultSync: () => vaultSync
|
|
26701
26943
|
});
|
|
26702
|
-
import { mkdirSync as mkdirSync21, readFileSync as
|
|
26703
|
-
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";
|
|
26704
26946
|
function context2() {
|
|
26705
26947
|
const s = loadSettings().team;
|
|
26706
26948
|
if (!s.enabled)
|
|
@@ -26839,7 +27081,7 @@ async function vaultSync(passphrase) {
|
|
|
26839
27081
|
continue;
|
|
26840
27082
|
}
|
|
26841
27083
|
try {
|
|
26842
|
-
const plaintext =
|
|
27084
|
+
const plaintext = readFileSync48(src.path);
|
|
26843
27085
|
const sourceSha = sha256Hex(plaintext);
|
|
26844
27086
|
const priorSha = uploaded.get(uploadKey(src.sessionId, src.tool));
|
|
26845
27087
|
if (priorSha === sourceSha) {
|
|
@@ -26891,7 +27133,7 @@ async function vaultSync(passphrase) {
|
|
|
26891
27133
|
}
|
|
26892
27134
|
function importedPathFor(tool, sessionId) {
|
|
26893
27135
|
const base4 = sessionId.replace(/^gemini_/, "").replace(/^codex_/, "").replace(/^agy_/, "").replace(/^cursor_/, "").replace(/^opencode_/, "");
|
|
26894
|
-
return
|
|
27136
|
+
return join60(IMPORTED_ROOT(), tool, `${base4}.jsonl`);
|
|
26895
27137
|
}
|
|
26896
27138
|
async function vaultRestore(passphrase, opts = {}) {
|
|
26897
27139
|
const ctx = context2();
|
|
@@ -26980,7 +27222,7 @@ var init_vault_client = __esm({
|
|
|
26980
27222
|
uploadKey = (sessionId, tool) => `${sessionId}\0${tool}`;
|
|
26981
27223
|
VaultPassphraseMismatchError = class extends Error {
|
|
26982
27224
|
};
|
|
26983
|
-
IMPORTED_ROOT = () =>
|
|
27225
|
+
IMPORTED_ROOT = () => join60(getDataDir(), "imported");
|
|
26984
27226
|
}
|
|
26985
27227
|
});
|
|
26986
27228
|
|
|
@@ -27542,15 +27784,15 @@ __export(service_installer_exports, {
|
|
|
27542
27784
|
uninstallService: () => uninstallService
|
|
27543
27785
|
});
|
|
27544
27786
|
import { execSync as execSync5 } from "child_process";
|
|
27545
|
-
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";
|
|
27546
27788
|
import { homedir as homedir22 } from "os";
|
|
27547
|
-
import { join as
|
|
27789
|
+
import { join as join61 } from "path";
|
|
27548
27790
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
27549
27791
|
function resolveDaemonPaths() {
|
|
27550
27792
|
const watchJs = fileURLToPath5(new URL("./watch.js", import.meta.url));
|
|
27551
27793
|
const node = process.execPath;
|
|
27552
|
-
const dataDir =
|
|
27553
|
-
const logFile =
|
|
27794
|
+
const dataDir = join61(homedir22(), ".chat-recall");
|
|
27795
|
+
const logFile = join61(dataDir, "watch.log");
|
|
27554
27796
|
return { watchJs, node, logFile, dataDir };
|
|
27555
27797
|
}
|
|
27556
27798
|
function tryCmd(cmd) {
|
|
@@ -27577,12 +27819,12 @@ function refreshServiceDefinition() {
|
|
|
27577
27819
|
if (process.platform !== "linux") return false;
|
|
27578
27820
|
try {
|
|
27579
27821
|
const { watchJs, node, logFile } = resolveDaemonPaths();
|
|
27580
|
-
const unitPath =
|
|
27822
|
+
const unitPath = join61(homedir22(), ".config", "systemd", "user", "chat-recall-watch.service");
|
|
27581
27823
|
if (!existsSync56(unitPath)) return false;
|
|
27582
|
-
const current =
|
|
27824
|
+
const current = readFileSync49(unitPath, "utf8");
|
|
27583
27825
|
if (!current.includes(watchJs)) return false;
|
|
27584
27826
|
const wanted = renderSystemdUnit(watchJs, node, logFile);
|
|
27585
|
-
if (
|
|
27827
|
+
if (readFileSync49(unitPath, "utf8") === wanted) return false;
|
|
27586
27828
|
writeFileSync22(unitPath, wanted);
|
|
27587
27829
|
execSync5("systemctl --user daemon-reload", { stdio: "ignore" });
|
|
27588
27830
|
return true;
|
|
@@ -27608,8 +27850,8 @@ function installService() {
|
|
|
27608
27850
|
);
|
|
27609
27851
|
}
|
|
27610
27852
|
function installSystemd(watchJs, node, logFile) {
|
|
27611
|
-
const unitDir =
|
|
27612
|
-
const unitPath =
|
|
27853
|
+
const unitDir = join61(homedir22(), ".config", "systemd", "user");
|
|
27854
|
+
const unitPath = join61(unitDir, "chat-recall-watch.service");
|
|
27613
27855
|
const unit = renderSystemdUnit(watchJs, node, logFile);
|
|
27614
27856
|
mkdirSync22(unitDir, { recursive: true });
|
|
27615
27857
|
writeFileSync22(unitPath, unit);
|
|
@@ -27688,8 +27930,8 @@ function renderSystemdUnit(watchJs, node, logFile) {
|
|
|
27688
27930
|
}
|
|
27689
27931
|
function installLaunchd(watchJs, node, logFile) {
|
|
27690
27932
|
const label = "com.chat-recall.watch";
|
|
27691
|
-
const plistDir =
|
|
27692
|
-
const plistPath =
|
|
27933
|
+
const plistDir = join61(homedir22(), "Library", "LaunchAgents");
|
|
27934
|
+
const plistPath = join61(plistDir, `${label}.plist`);
|
|
27693
27935
|
const plist = renderLaunchdPlist(watchJs, node, logFile, label);
|
|
27694
27936
|
mkdirSync22(plistDir, { recursive: true });
|
|
27695
27937
|
writeFileSync22(plistPath, plist);
|
|
@@ -27745,9 +27987,9 @@ function uninstallService() {
|
|
|
27745
27987
|
removed = true;
|
|
27746
27988
|
} catch {
|
|
27747
27989
|
}
|
|
27748
|
-
const unitPath =
|
|
27990
|
+
const unitPath = join61(homedir22(), ".config", "systemd", "user", "chat-recall-watch.service");
|
|
27749
27991
|
if (existsSync56(unitPath)) {
|
|
27750
|
-
|
|
27992
|
+
rmSync10(unitPath, { force: true });
|
|
27751
27993
|
removed = true;
|
|
27752
27994
|
}
|
|
27753
27995
|
try {
|
|
@@ -27757,14 +27999,14 @@ function uninstallService() {
|
|
|
27757
27999
|
return removed;
|
|
27758
28000
|
}
|
|
27759
28001
|
if (process.platform === "darwin") {
|
|
27760
|
-
const plistPath =
|
|
28002
|
+
const plistPath = join61(homedir22(), "Library", "LaunchAgents", "com.chat-recall.watch.plist");
|
|
27761
28003
|
try {
|
|
27762
28004
|
execSync5(`launchctl unload "${plistPath}" 2>/dev/null`, { stdio: "ignore" });
|
|
27763
28005
|
} catch {
|
|
27764
28006
|
}
|
|
27765
28007
|
let removed = false;
|
|
27766
28008
|
if (existsSync56(plistPath)) {
|
|
27767
|
-
|
|
28009
|
+
rmSync10(plistPath, { force: true });
|
|
27768
28010
|
removed = true;
|
|
27769
28011
|
}
|
|
27770
28012
|
return removed;
|
|
@@ -27808,7 +28050,7 @@ __export(device_auth_exports, {
|
|
|
27808
28050
|
betterAuthDeviceLogin: () => betterAuthDeviceLogin,
|
|
27809
28051
|
deviceLogin: () => deviceLogin
|
|
27810
28052
|
});
|
|
27811
|
-
import { createHash as createHash15, randomBytes } from "node:crypto";
|
|
28053
|
+
import { createHash as createHash15, randomBytes as randomBytes2 } from "node:crypto";
|
|
27812
28054
|
async function readDeviceCode(res, where) {
|
|
27813
28055
|
const text = await res.text().catch(() => "");
|
|
27814
28056
|
let parsed;
|
|
@@ -27836,7 +28078,7 @@ async function deviceLogin(opts, onPrompt) {
|
|
|
27836
28078
|
}
|
|
27837
28079
|
const clientId = opts.clientId || DEFAULT_CLIENT_ID;
|
|
27838
28080
|
const scope = opts.scope || "openid email profile";
|
|
27839
|
-
const codeVerifier = b64url(
|
|
28081
|
+
const codeVerifier = b64url(randomBytes2(32));
|
|
27840
28082
|
const codeChallenge = b64url(createHash15("sha256").update(codeVerifier).digest());
|
|
27841
28083
|
const startRes = await fetch(`${issuer}/protocol/openid-connect/auth/device`, {
|
|
27842
28084
|
method: "POST",
|
|
@@ -28286,9 +28528,9 @@ init_project_resolver();
|
|
|
28286
28528
|
import { config } from "dotenv";
|
|
28287
28529
|
import { Command } from "commander";
|
|
28288
28530
|
import chalk2 from "chalk";
|
|
28289
|
-
import { existsSync as existsSync57, readFileSync as
|
|
28531
|
+
import { existsSync as existsSync57, readFileSync as readFileSync50, writeFileSync as writeFileSync23, realpathSync as realpathSync5 } from "fs";
|
|
28290
28532
|
import { homedir as homedir23 } from "os";
|
|
28291
|
-
import { join as
|
|
28533
|
+
import { join as join62, resolve as resolve2, dirname as dirname29, basename as basename27 } from "path";
|
|
28292
28534
|
|
|
28293
28535
|
// ../engine/dist/core/score-tier.js
|
|
28294
28536
|
var STRONG_RATIO = 0.85;
|
|
@@ -28396,10 +28638,10 @@ function renderEnvNeeds(needs, installedCount) {
|
|
|
28396
28638
|
// src/star-nudge.ts
|
|
28397
28639
|
init_paths();
|
|
28398
28640
|
import { existsSync as existsSync43, mkdirSync as mkdirSync11, writeFileSync as writeFileSync11 } from "node:fs";
|
|
28399
|
-
import { dirname as dirname20, join as
|
|
28641
|
+
import { dirname as dirname20, join as join46 } from "node:path";
|
|
28400
28642
|
var REPO = "https://github.com/munhq/chat-recall";
|
|
28401
28643
|
function markerPath() {
|
|
28402
|
-
return
|
|
28644
|
+
return join46(getDataDir(), ".star-asked");
|
|
28403
28645
|
}
|
|
28404
28646
|
function suppressed() {
|
|
28405
28647
|
const env = process.env;
|
|
@@ -28452,8 +28694,8 @@ function claudeHookConfigFiles() {
|
|
|
28452
28694
|
const out = [];
|
|
28453
28695
|
const seen = /* @__PURE__ */ new Set();
|
|
28454
28696
|
for (const home of claudeHomeDirs()) {
|
|
28455
|
-
if (!existsSync57(
|
|
28456
|
-
const file =
|
|
28697
|
+
if (!existsSync57(join62(home, "projects"))) continue;
|
|
28698
|
+
const file = join62(home, "hooks.json");
|
|
28457
28699
|
let key2;
|
|
28458
28700
|
try {
|
|
28459
28701
|
key2 = realpathSync5(file);
|
|
@@ -28548,13 +28790,13 @@ async function serverDelete(path, body2) {
|
|
|
28548
28790
|
}
|
|
28549
28791
|
var pkgEngines = (() => {
|
|
28550
28792
|
try {
|
|
28551
|
-
return JSON.parse(
|
|
28793
|
+
return JSON.parse(readFileSync50(new URL("../package.json", import.meta.url), "utf-8")).engines?.node ?? "";
|
|
28552
28794
|
} catch {
|
|
28553
28795
|
return "";
|
|
28554
28796
|
}
|
|
28555
28797
|
})();
|
|
28556
28798
|
var pkgVersion = JSON.parse(
|
|
28557
|
-
|
|
28799
|
+
readFileSync50(new URL("../package.json", import.meta.url), "utf-8")
|
|
28558
28800
|
).version;
|
|
28559
28801
|
var DEFAULT_SERVER = (process.env.CHAT_RECALL_DEFAULT_SERVER || "https://chatrecall.dev").replace(/\/+$/, "");
|
|
28560
28802
|
var DEFAULT_ALLOW = [
|
|
@@ -28728,10 +28970,10 @@ program.command("init").description("Set up chat-recall: connect to your server,
|
|
|
28728
28970
|
} else if (target) {
|
|
28729
28971
|
}
|
|
28730
28972
|
if (!options.skipMcp) {
|
|
28731
|
-
const projectRoot =
|
|
28973
|
+
const projectRoot = join62(import.meta.dirname, "..");
|
|
28732
28974
|
let mcpBinOnPath = false;
|
|
28733
28975
|
mcpBinOnPath = isOnPath("chat-recall-mcp");
|
|
28734
|
-
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")] };
|
|
28735
28977
|
const MCP_ENV = { NODE_OPTIONS: "--max-old-space-size=1024" };
|
|
28736
28978
|
const { registerMcpEverywhere: registerMcpEverywhere2 } = await Promise.resolve().then(() => (init_mcp_clients(), mcp_clients_exports));
|
|
28737
28979
|
const MCP_CLIENT_FOR_BIN = {
|
|
@@ -28771,7 +29013,7 @@ program.command("init").description("Set up chat-recall: connect to your server,
|
|
|
28771
29013
|
const detected = checkCodeindexStatus2();
|
|
28772
29014
|
if (detected.installed && !forceInstall) {
|
|
28773
29015
|
if (!options.skipMcp) {
|
|
28774
|
-
const mcpJsonPath =
|
|
29016
|
+
const mcpJsonPath = join62(homedir23(), ".mcp.json");
|
|
28775
29017
|
const reg = registerCodeindexMcp2(mcpJsonPath, detected.path);
|
|
28776
29018
|
}
|
|
28777
29019
|
} else if (forceInstall) {
|
|
@@ -28780,7 +29022,7 @@ program.command("init").description("Set up chat-recall: connect to your server,
|
|
|
28780
29022
|
if (result.installed) {
|
|
28781
29023
|
const sizeMb = result.size ? `${(result.size / 1024 / 1024).toFixed(1)} MB` : "?";
|
|
28782
29024
|
if (!options.skipMcp) {
|
|
28783
|
-
const mcpJsonPath =
|
|
29025
|
+
const mcpJsonPath = join62(homedir23(), ".mcp.json");
|
|
28784
29026
|
const reg = registerCodeindexMcp2(mcpJsonPath, CODEINDEX_BIN_PATH2);
|
|
28785
29027
|
}
|
|
28786
29028
|
} else if (!result.prebuiltAvailable) {
|
|
@@ -29238,7 +29480,7 @@ memory.command("wake-up").description("Generate wake-up context (high-importance
|
|
|
29238
29480
|
const identityFile = getIdentityFilePath();
|
|
29239
29481
|
let identity = "AI coding assistant";
|
|
29240
29482
|
if (existsSync57(identityFile)) {
|
|
29241
|
-
identity =
|
|
29483
|
+
identity = readFileSync50(identityFile, "utf-8").trim();
|
|
29242
29484
|
}
|
|
29243
29485
|
const lines = [
|
|
29244
29486
|
chalk2.bold("# Wake-Up Context"),
|
|
@@ -29338,7 +29580,7 @@ program.command("feedback").argument("<message...>", "what you want to say \u201
|
|
|
29338
29580
|
}
|
|
29339
29581
|
});
|
|
29340
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) => {
|
|
29341
|
-
const { existsSync: existsSync58, readFileSync:
|
|
29583
|
+
const { existsSync: existsSync58, readFileSync: readFileSync51, statSync: statSync47 } = await import("fs");
|
|
29342
29584
|
const { execSync: execSync6 } = await import("child_process");
|
|
29343
29585
|
const rows = [];
|
|
29344
29586
|
const note = (ok, label, detail) => rows.push({ ok, label, detail });
|
|
@@ -29401,12 +29643,12 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
29401
29643
|
}
|
|
29402
29644
|
}
|
|
29403
29645
|
}
|
|
29404
|
-
const credFile =
|
|
29646
|
+
const credFile = join62(getDataDir(), "credentials.json");
|
|
29405
29647
|
if (!existsSync58(credFile)) {
|
|
29406
29648
|
note(false, "Credentials file", `missing \u2014 run \`chat-recall login <server-url>\``);
|
|
29407
29649
|
} else {
|
|
29408
29650
|
try {
|
|
29409
|
-
const mode =
|
|
29651
|
+
const mode = statSync47(credFile).mode & 511;
|
|
29410
29652
|
const isWin = process.platform === "win32";
|
|
29411
29653
|
const safe = isWin || (mode & 63) === 0;
|
|
29412
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"})`);
|
|
@@ -29425,13 +29667,13 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
29425
29667
|
const readHooks = (file) => {
|
|
29426
29668
|
if (!existsSync58(file)) return {};
|
|
29427
29669
|
try {
|
|
29428
|
-
return JSON.parse(
|
|
29670
|
+
return JSON.parse(readFileSync51(file, "utf-8")).hooks || {};
|
|
29429
29671
|
} catch {
|
|
29430
29672
|
return {};
|
|
29431
29673
|
}
|
|
29432
29674
|
};
|
|
29433
29675
|
const cfg = readHooks(hooksJson);
|
|
29434
|
-
const settings2 = readHooks(
|
|
29676
|
+
const settings2 = readHooks(join62(dirname29(hooksJson), "settings.json"));
|
|
29435
29677
|
const all = ["SessionStart", "UserPromptSubmit", "Stop", "PreCompact", "SessionEnd"];
|
|
29436
29678
|
const hits = [];
|
|
29437
29679
|
for (const ev of all) {
|
|
@@ -29478,7 +29720,7 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
29478
29720
|
}
|
|
29479
29721
|
let registered = false;
|
|
29480
29722
|
try {
|
|
29481
|
-
const cfg = JSON.parse(
|
|
29723
|
+
const cfg = JSON.parse(readFileSync51(target2.configPath, "utf-8"));
|
|
29482
29724
|
registered = JSON.stringify(cfg).includes("chat_recall_guard");
|
|
29483
29725
|
} catch {
|
|
29484
29726
|
}
|
|
@@ -29493,7 +29735,7 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
29493
29735
|
const want = bundledSkillNames2().length;
|
|
29494
29736
|
for (const t of skillTargets2()) {
|
|
29495
29737
|
if (!t.available) continue;
|
|
29496
|
-
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;
|
|
29497
29739
|
note(
|
|
29498
29740
|
have === want,
|
|
29499
29741
|
`Skills \u2014 ${t.label}`,
|
|
@@ -29568,12 +29810,12 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
29568
29810
|
note(watchRunning, "Watch daemon", watchRunning ? "running" : "not running (run `chat-recall watch --install-service` to keep collection running)");
|
|
29569
29811
|
const dataDir = getDataDir();
|
|
29570
29812
|
const legacyPaths = [
|
|
29571
|
-
|
|
29572
|
-
|
|
29573
|
-
|
|
29574
|
-
|
|
29575
|
-
|
|
29576
|
-
|
|
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")
|
|
29577
29819
|
];
|
|
29578
29820
|
const legacyPresent = legacyPaths.filter((p) => existsSync58(p));
|
|
29579
29821
|
if (opts.purgeLocal) {
|
|
@@ -29582,11 +29824,11 @@ program.command("doctor").description("Quick health check across login, server,
|
|
|
29582
29824
|
} else if (legacyPresent.length === 0) {
|
|
29583
29825
|
note(true, "Purge legacy index", "nothing to remove");
|
|
29584
29826
|
} else {
|
|
29585
|
-
const { rmSync:
|
|
29827
|
+
const { rmSync: rmSync11 } = await import("fs");
|
|
29586
29828
|
let removed = 0;
|
|
29587
29829
|
for (const p of legacyPresent) {
|
|
29588
29830
|
try {
|
|
29589
|
-
|
|
29831
|
+
rmSync11(p, { recursive: true, force: true });
|
|
29590
29832
|
removed++;
|
|
29591
29833
|
} catch {
|
|
29592
29834
|
}
|
|
@@ -29646,7 +29888,7 @@ companions.command("install").description("Install codeindex (downloads from mun
|
|
|
29646
29888
|
if (result.installed) {
|
|
29647
29889
|
const sizeMb = result.size ? `${(result.size / 1024 / 1024).toFixed(1)} MB` : "?";
|
|
29648
29890
|
console.log(chalk2.green(`\u2713 codeindex installed (${sizeMb}) \u2192 ${result.path}`));
|
|
29649
|
-
const mcpJsonPath =
|
|
29891
|
+
const mcpJsonPath = join62(homedir23(), ".mcp.json");
|
|
29650
29892
|
const reg = registerCodeindexMcp2(mcpJsonPath, CODEINDEX_BIN_PATH2);
|
|
29651
29893
|
if (reg.added) console.log(chalk2.dim(` Registered as MCP server in ${mcpJsonPath}`));
|
|
29652
29894
|
else console.log(chalk2.dim(` Already registered as MCP server`));
|
|
@@ -29668,7 +29910,7 @@ companions.command("uninstall").description("Remove the codeindex binary chat-re
|
|
|
29668
29910
|
const r = uninstallCodeindex2();
|
|
29669
29911
|
if (r.removed) console.log(chalk2.green(`\u2713 Removed ${r.path}`));
|
|
29670
29912
|
else console.log(chalk2.dim(` Nothing to remove at ${r.path}`));
|
|
29671
|
-
const mcpJsonPath =
|
|
29913
|
+
const mcpJsonPath = join62(homedir23(), ".mcp.json");
|
|
29672
29914
|
const u = unregisterCodeindexMcp2(mcpJsonPath);
|
|
29673
29915
|
if (u.removed) console.log(chalk2.dim(` Unregistered MCP server from ${mcpJsonPath}`));
|
|
29674
29916
|
});
|
|
@@ -30220,10 +30462,10 @@ tasks.command("pull [dir]").description("Write TEAM_TASKS.md for your tasks in t
|
|
|
30220
30462
|
try {
|
|
30221
30463
|
const { resolveProjectId: resolveProjectId2 } = await Promise.resolve().then(() => (init_project_resolver(), project_resolver_exports));
|
|
30222
30464
|
const { renderTeamTasksMd: renderTeamTasksMd2, parseTeamTasksFile: parseTeamTasksFile2 } = await Promise.resolve().then(() => (init_project_tasks(), project_tasks_exports));
|
|
30223
|
-
const { writeFileSync: writeFileSync24, readFileSync:
|
|
30224
|
-
const { join:
|
|
30225
|
-
const file =
|
|
30226
|
-
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) {
|
|
30227
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.");
|
|
30228
30470
|
process.exit(1);
|
|
30229
30471
|
}
|
|
@@ -30242,14 +30484,14 @@ tasks.command("push [dir]").description("Push TEAM_TASKS.md status edits back to
|
|
|
30242
30484
|
const cwd = dir || process.cwd();
|
|
30243
30485
|
try {
|
|
30244
30486
|
const { parseTeamTasksFile: parseTeamTasksFile2 } = await Promise.resolve().then(() => (init_project_tasks(), project_tasks_exports));
|
|
30245
|
-
const { readFileSync:
|
|
30246
|
-
const { join:
|
|
30247
|
-
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");
|
|
30248
30490
|
if (!existsSync58(file)) {
|
|
30249
30491
|
console.error(chalk2.red("no TEAM_TASKS.md here \u2014"), "run", chalk2.bold("chat-recall tasks pull"), "first");
|
|
30250
30492
|
process.exit(1);
|
|
30251
30493
|
}
|
|
30252
|
-
const edits = parseTeamTasksFile2(
|
|
30494
|
+
const edits = parseTeamTasksFile2(readFileSync51(file, "utf8"));
|
|
30253
30495
|
let n = 0;
|
|
30254
30496
|
for (const e of edits) {
|
|
30255
30497
|
await serverPatch(`/api/tasks/${encodeURIComponent(e.id)}`, { status: e.intent });
|
|
@@ -30355,8 +30597,8 @@ team.command("publish <type> <name> <file>").description("Publish a local file a
|
|
|
30355
30597
|
console.error(chalk2.red(`Invalid tool: ${opts.tool}. Must be one of: ${validTools.join(", ")}`));
|
|
30356
30598
|
process.exit(1);
|
|
30357
30599
|
}
|
|
30358
|
-
const { readFileSync:
|
|
30359
|
-
const body2 =
|
|
30600
|
+
const { readFileSync: readFileSync51 } = await import("fs");
|
|
30601
|
+
const body2 = readFileSync51(file);
|
|
30360
30602
|
const { teamPublish: teamPublish2 } = await Promise.resolve().then(() => (init_team_client(), team_client_exports));
|
|
30361
30603
|
const a = await teamPublish2({
|
|
30362
30604
|
type,
|
|
@@ -30732,18 +30974,18 @@ program.command("task-hook").description("Move a board card when a prompt or a c
|
|
|
30732
30974
|
}
|
|
30733
30975
|
});
|
|
30734
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) => {
|
|
30735
|
-
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");
|
|
30736
30978
|
const { fileURLToPath: fileURLToPath6 } = await import("url");
|
|
30737
30979
|
const { boardHookEntries: boardHookEntries2, isBoardHookEntry: isBoardHookEntry2, registerBoardHooks: registerBoardHooks2, resolveCliEntry: resolveCliEntry2 } = await Promise.resolve().then(() => (init_board_hooks(), board_hooks_exports));
|
|
30738
30980
|
const here = fileURLToPath6(new URL(".", import.meta.url));
|
|
30739
30981
|
const findHook = (name) => {
|
|
30740
30982
|
const candidates2 = [
|
|
30741
|
-
|
|
30742
|
-
|
|
30983
|
+
join62(here, "..", "hooks", name),
|
|
30984
|
+
join62(here, "..", "..", "hooks", name),
|
|
30743
30985
|
// The monorepo root, for a run straight from the checkout. The copy
|
|
30744
30986
|
// under packages/cli/hooks is written by the package build, so a
|
|
30745
30987
|
// freshly added script is only at the root until that build runs.
|
|
30746
|
-
|
|
30988
|
+
join62(here, "..", "..", "..", "hooks", name)
|
|
30747
30989
|
];
|
|
30748
30990
|
return candidates2.find((p) => existsSync58(p));
|
|
30749
30991
|
};
|
|
@@ -30757,16 +30999,16 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
30757
30999
|
process.exit(1);
|
|
30758
31000
|
}
|
|
30759
31001
|
const hooksDir = getHooksDir();
|
|
30760
|
-
const installedSaveHook =
|
|
30761
|
-
const installedGuardHook =
|
|
30762
|
-
const installedResumeHook =
|
|
30763
|
-
const installedEscalateHook =
|
|
30764
|
-
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");
|
|
30765
31007
|
const wakeupWiredInSettings = (home) => {
|
|
30766
|
-
const settings2 =
|
|
31008
|
+
const settings2 = join62(home, "settings.json");
|
|
30767
31009
|
if (!existsSync58(settings2)) return false;
|
|
30768
31010
|
try {
|
|
30769
|
-
const cfg = JSON.parse(
|
|
31011
|
+
const cfg = JSON.parse(readFileSync51(settings2, "utf-8"));
|
|
30770
31012
|
const arr = Array.isArray(cfg.hooks?.SessionStart) ? cfg.hooks.SessionStart : [];
|
|
30771
31013
|
return arr.some((h) => (h?.hooks?.[0]?.command || "").includes("chat_recall_wakeup_hook"));
|
|
30772
31014
|
} catch {
|
|
@@ -30777,7 +31019,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
30777
31019
|
const readHookConfig = (file) => {
|
|
30778
31020
|
if (!existsSync58(file)) return { hooks: {} };
|
|
30779
31021
|
try {
|
|
30780
|
-
const c = JSON.parse(
|
|
31022
|
+
const c = JSON.parse(readFileSync51(file, "utf-8"));
|
|
30781
31023
|
if (!c.hooks || typeof c.hooks !== "object") c.hooks = {};
|
|
30782
31024
|
return c;
|
|
30783
31025
|
} catch (err) {
|
|
@@ -30794,7 +31036,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
30794
31036
|
const readJson4 = (file) => {
|
|
30795
31037
|
if (!existsSync58(file)) return {};
|
|
30796
31038
|
try {
|
|
30797
|
-
return JSON.parse(
|
|
31039
|
+
return JSON.parse(readFileSync51(file, "utf-8"));
|
|
30798
31040
|
} catch {
|
|
30799
31041
|
return {};
|
|
30800
31042
|
}
|
|
@@ -30804,7 +31046,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
30804
31046
|
const notes = [];
|
|
30805
31047
|
for (const target of reg.guardTargets()) {
|
|
30806
31048
|
if (!existsSync58(target.homeDir)) continue;
|
|
30807
|
-
const wrapper =
|
|
31049
|
+
const wrapper = join62(hooksDir, reg.guardWrapperName(target.tool));
|
|
30808
31050
|
writeFileSync24(wrapper, reg.guardWrapperSource(target.tool, hookPath));
|
|
30809
31051
|
chmodSync5(wrapper, 493);
|
|
30810
31052
|
mkdirSync23(dirname29(target.configPath), { recursive: true });
|
|
@@ -30826,7 +31068,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
30826
31068
|
for (const target of reg.guardTargets()) {
|
|
30827
31069
|
if (!existsSync58(target.configPath)) continue;
|
|
30828
31070
|
if (target.tool === "opencode") {
|
|
30829
|
-
const body2 =
|
|
31071
|
+
const body2 = readFileSync51(target.configPath, "utf-8");
|
|
30830
31072
|
if (!body2.includes("chat-recall install-hooks")) continue;
|
|
30831
31073
|
unlinkSync4(target.configPath);
|
|
30832
31074
|
removed += 1;
|
|
@@ -30934,7 +31176,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
30934
31176
|
const config2 = readHookConfig(hooksJson);
|
|
30935
31177
|
const home = dirname29(hooksJson);
|
|
30936
31178
|
const alreadyWired = wakeupWiredInSettings(home);
|
|
30937
|
-
if (alreadyWired) wakeupSkipped.push(
|
|
31179
|
+
if (alreadyWired) wakeupSkipped.push(join62(home, "settings.json"));
|
|
30938
31180
|
const perProfile = installWakeup && !alreadyWired ? [...events, ["SessionStart", wakeupEntry]] : events;
|
|
30939
31181
|
for (const event of HOOK_EVENTS) {
|
|
30940
31182
|
const arr = Array.isArray(config2.hooks[event]) ? config2.hooks[event] : [];
|
|
@@ -30947,18 +31189,18 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
30947
31189
|
writeFileSync24(hooksJson, JSON.stringify(config2, null, 2) + "\n");
|
|
30948
31190
|
}
|
|
30949
31191
|
if (installGuard) await addGuardToOtherTools(installedGuardHook);
|
|
30950
|
-
const saveSz =
|
|
31192
|
+
const saveSz = statSync47(installedSaveHook).size;
|
|
30951
31193
|
console.log(chalk2.green(`\u2713 Installed chat-recall save hook (${saveSz} bytes)`));
|
|
30952
31194
|
if (installResume) {
|
|
30953
|
-
const resumeSz =
|
|
31195
|
+
const resumeSz = statSync47(installedResumeHook).size;
|
|
30954
31196
|
console.log(chalk2.green(`\u2713 Installed chat-recall resume-hint hook (${resumeSz} bytes)`));
|
|
30955
31197
|
}
|
|
30956
31198
|
if (installEscalate) {
|
|
30957
|
-
const escalateSz =
|
|
31199
|
+
const escalateSz = statSync47(installedEscalateHook).size;
|
|
30958
31200
|
console.log(chalk2.green(`\u2713 Installed chat-recall learnings-escalation hook (${escalateSz} bytes)`));
|
|
30959
31201
|
}
|
|
30960
31202
|
if (installGuard) {
|
|
30961
|
-
const guardSz =
|
|
31203
|
+
const guardSz = statSync47(installedGuardHook).size;
|
|
30962
31204
|
console.log(chalk2.green(`\u2713 Installed chat-recall decision guard (${guardSz} bytes)`));
|
|
30963
31205
|
}
|
|
30964
31206
|
if (installTaskBoard) {
|
|
@@ -30966,7 +31208,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
|
|
|
30966
31208
|
console.log(chalk2.dim(" A prompt naming a card id claims it; a commit message naming one closes it."));
|
|
30967
31209
|
}
|
|
30968
31210
|
if (installWakeup) {
|
|
30969
|
-
const wakeupSz =
|
|
31211
|
+
const wakeupSz = statSync47(installedWakeupHook).size;
|
|
30970
31212
|
console.log(chalk2.green(`\u2713 Installed chat-recall wake-up hook (${wakeupSz} bytes)`));
|
|
30971
31213
|
for (const f of wakeupSkipped) {
|
|
30972
31214
|
console.log(chalk2.dim(` (SessionStart already wired in ${f} \u2014 left as is, not duplicated)`));
|