chat-recall 0.5.5 → 0.5.6
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 +1389 -697
- package/dist/cli.js.map +1 -1
- package/dist/mcp-diagnostics.d.ts.map +1 -1
- package/dist/mcp-diagnostics.js +10 -8
- package/dist/mcp-diagnostics.js.map +1 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +1133 -457
- package/dist/mcp.js.map +1 -1
- package/dist/project-tasks.d.ts.map +1 -1
- package/dist/project-tasks.js +12 -7
- package/dist/project-tasks.js.map +1 -1
- package/dist/service-installer.d.ts +1 -1
- package/dist/service-installer.d.ts.map +1 -1
- package/dist/service-installer.js +20 -6
- package/dist/service-installer.js.map +1 -1
- package/dist/sync-client.d.ts +1 -0
- package/dist/sync-client.d.ts.map +1 -1
- package/dist/sync-client.js +162 -93
- package/dist/sync-client.js.map +1 -1
- package/dist/sync-ledger.d.ts +22 -0
- package/dist/sync-ledger.d.ts.map +1 -1
- package/dist/sync-ledger.js +108 -1
- package/dist/sync-ledger.js.map +1 -1
- package/dist/watch.js +989 -445
- package/hooks/chat_recall_escalate_hook.sh +28 -2
- package/hooks/chat_recall_save_hook.sh +17 -11
- package/hooks/chat_recall_wakeup_hook.sh +27 -1
- package/package.json +7 -3
package/dist/watch.js
CHANGED
|
@@ -2110,7 +2110,7 @@ var require_thread_stream = __commonJS({
|
|
|
2110
2110
|
var { version } = require_package();
|
|
2111
2111
|
var { EventEmitter } = __require("events");
|
|
2112
2112
|
var { Worker } = __require("worker_threads");
|
|
2113
|
-
var { join:
|
|
2113
|
+
var { join: join50 } = __require("path");
|
|
2114
2114
|
var { pathToFileURL } = __require("url");
|
|
2115
2115
|
var { wait } = require_wait();
|
|
2116
2116
|
var {
|
|
@@ -2153,7 +2153,7 @@ var require_thread_stream = __commonJS({
|
|
|
2153
2153
|
function createWorker(stream, opts) {
|
|
2154
2154
|
const { filename, workerData } = opts;
|
|
2155
2155
|
const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {};
|
|
2156
|
-
const toExecute = bundlerOverrides["thread-stream-worker"] ||
|
|
2156
|
+
const toExecute = bundlerOverrides["thread-stream-worker"] || join50(__dirname, "lib", "worker.js");
|
|
2157
2157
|
const worker = new Worker(toExecute, {
|
|
2158
2158
|
...opts.workerOpts,
|
|
2159
2159
|
trackUnmanagedFds: false,
|
|
@@ -2556,7 +2556,7 @@ var require_transport = __commonJS({
|
|
|
2556
2556
|
"use strict";
|
|
2557
2557
|
var { createRequire: createRequire3 } = __require("module");
|
|
2558
2558
|
var getCallers = require_caller();
|
|
2559
|
-
var { join:
|
|
2559
|
+
var { join: join50, isAbsolute: isAbsolute3, sep: sep4 } = __require("node:path");
|
|
2560
2560
|
var sleep = require_atomic_sleep();
|
|
2561
2561
|
var onExit = require_on_exit_leak_free();
|
|
2562
2562
|
var ThreadStream = require_thread_stream();
|
|
@@ -2619,7 +2619,7 @@ var require_transport = __commonJS({
|
|
|
2619
2619
|
throw new Error("only one of target or targets can be specified");
|
|
2620
2620
|
}
|
|
2621
2621
|
if (targets) {
|
|
2622
|
-
target = bundlerOverrides["pino-worker"] ||
|
|
2622
|
+
target = bundlerOverrides["pino-worker"] || join50(__dirname, "worker.js");
|
|
2623
2623
|
options.targets = targets.filter((dest) => dest.target).map((dest) => {
|
|
2624
2624
|
return {
|
|
2625
2625
|
...dest,
|
|
@@ -2637,7 +2637,7 @@ var require_transport = __commonJS({
|
|
|
2637
2637
|
});
|
|
2638
2638
|
});
|
|
2639
2639
|
} else if (pipeline) {
|
|
2640
|
-
target = bundlerOverrides["pino-worker"] ||
|
|
2640
|
+
target = bundlerOverrides["pino-worker"] || join50(__dirname, "worker.js");
|
|
2641
2641
|
options.pipelines = [pipeline.map((dest) => {
|
|
2642
2642
|
return {
|
|
2643
2643
|
...dest,
|
|
@@ -2655,16 +2655,16 @@ var require_transport = __commonJS({
|
|
|
2655
2655
|
return buildStream(fixTarget(target), options, worker, sync);
|
|
2656
2656
|
function fixTarget(origin) {
|
|
2657
2657
|
origin = bundlerOverrides[origin] || origin;
|
|
2658
|
-
if (
|
|
2658
|
+
if (isAbsolute3(origin) || origin.indexOf("file://") === 0) {
|
|
2659
2659
|
return origin;
|
|
2660
2660
|
}
|
|
2661
2661
|
if (origin === "pino/file") {
|
|
2662
|
-
return
|
|
2662
|
+
return join50(__dirname, "..", "file.js");
|
|
2663
2663
|
}
|
|
2664
2664
|
let fixTarget2;
|
|
2665
2665
|
for (const filePath of callers) {
|
|
2666
2666
|
try {
|
|
2667
|
-
const context = filePath === "node:repl" ? process.cwd() +
|
|
2667
|
+
const context = filePath === "node:repl" ? process.cwd() + sep4 : filePath;
|
|
2668
2668
|
fixTarget2 = createRequire3(context).resolve(origin);
|
|
2669
2669
|
break;
|
|
2670
2670
|
} catch (err) {
|
|
@@ -3648,7 +3648,7 @@ var require_safe_stable_stringify = __commonJS({
|
|
|
3648
3648
|
return circularValue;
|
|
3649
3649
|
}
|
|
3650
3650
|
let res = "";
|
|
3651
|
-
let
|
|
3651
|
+
let join50 = ",";
|
|
3652
3652
|
const originalIndentation = indentation;
|
|
3653
3653
|
if (Array.isArray(value)) {
|
|
3654
3654
|
if (value.length === 0) {
|
|
@@ -3662,7 +3662,7 @@ var require_safe_stable_stringify = __commonJS({
|
|
|
3662
3662
|
indentation += spacer;
|
|
3663
3663
|
res += `
|
|
3664
3664
|
${indentation}`;
|
|
3665
|
-
|
|
3665
|
+
join50 = `,
|
|
3666
3666
|
${indentation}`;
|
|
3667
3667
|
}
|
|
3668
3668
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
@@ -3670,13 +3670,13 @@ ${indentation}`;
|
|
|
3670
3670
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
3671
3671
|
const tmp2 = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
|
|
3672
3672
|
res += tmp2 !== void 0 ? tmp2 : "null";
|
|
3673
|
-
res +=
|
|
3673
|
+
res += join50;
|
|
3674
3674
|
}
|
|
3675
3675
|
const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
|
|
3676
3676
|
res += tmp !== void 0 ? tmp : "null";
|
|
3677
3677
|
if (value.length - 1 > maximumBreadth) {
|
|
3678
3678
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
3679
|
-
res += `${
|
|
3679
|
+
res += `${join50}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
3680
3680
|
}
|
|
3681
3681
|
if (spacer !== "") {
|
|
3682
3682
|
res += `
|
|
@@ -3697,7 +3697,7 @@ ${originalIndentation}`;
|
|
|
3697
3697
|
let separator = "";
|
|
3698
3698
|
if (spacer !== "") {
|
|
3699
3699
|
indentation += spacer;
|
|
3700
|
-
|
|
3700
|
+
join50 = `,
|
|
3701
3701
|
${indentation}`;
|
|
3702
3702
|
whitespace = " ";
|
|
3703
3703
|
}
|
|
@@ -3711,13 +3711,13 @@ ${indentation}`;
|
|
|
3711
3711
|
const tmp = stringifyFnReplacer(key2, value, stack, replacer, spacer, indentation);
|
|
3712
3712
|
if (tmp !== void 0) {
|
|
3713
3713
|
res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
|
|
3714
|
-
separator =
|
|
3714
|
+
separator = join50;
|
|
3715
3715
|
}
|
|
3716
3716
|
}
|
|
3717
3717
|
if (keyLength > maximumBreadth) {
|
|
3718
3718
|
const removedKeys = keyLength - maximumBreadth;
|
|
3719
3719
|
res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`;
|
|
3720
|
-
separator =
|
|
3720
|
+
separator = join50;
|
|
3721
3721
|
}
|
|
3722
3722
|
if (spacer !== "" && separator.length > 1) {
|
|
3723
3723
|
res = `
|
|
@@ -3758,7 +3758,7 @@ ${originalIndentation}`;
|
|
|
3758
3758
|
}
|
|
3759
3759
|
const originalIndentation = indentation;
|
|
3760
3760
|
let res = "";
|
|
3761
|
-
let
|
|
3761
|
+
let join50 = ",";
|
|
3762
3762
|
if (Array.isArray(value)) {
|
|
3763
3763
|
if (value.length === 0) {
|
|
3764
3764
|
return "[]";
|
|
@@ -3771,7 +3771,7 @@ ${originalIndentation}`;
|
|
|
3771
3771
|
indentation += spacer;
|
|
3772
3772
|
res += `
|
|
3773
3773
|
${indentation}`;
|
|
3774
|
-
|
|
3774
|
+
join50 = `,
|
|
3775
3775
|
${indentation}`;
|
|
3776
3776
|
}
|
|
3777
3777
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
@@ -3779,13 +3779,13 @@ ${indentation}`;
|
|
|
3779
3779
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
3780
3780
|
const tmp2 = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
|
|
3781
3781
|
res += tmp2 !== void 0 ? tmp2 : "null";
|
|
3782
|
-
res +=
|
|
3782
|
+
res += join50;
|
|
3783
3783
|
}
|
|
3784
3784
|
const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
|
|
3785
3785
|
res += tmp !== void 0 ? tmp : "null";
|
|
3786
3786
|
if (value.length - 1 > maximumBreadth) {
|
|
3787
3787
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
3788
|
-
res += `${
|
|
3788
|
+
res += `${join50}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
3789
3789
|
}
|
|
3790
3790
|
if (spacer !== "") {
|
|
3791
3791
|
res += `
|
|
@@ -3798,7 +3798,7 @@ ${originalIndentation}`;
|
|
|
3798
3798
|
let whitespace = "";
|
|
3799
3799
|
if (spacer !== "") {
|
|
3800
3800
|
indentation += spacer;
|
|
3801
|
-
|
|
3801
|
+
join50 = `,
|
|
3802
3802
|
${indentation}`;
|
|
3803
3803
|
whitespace = " ";
|
|
3804
3804
|
}
|
|
@@ -3807,7 +3807,7 @@ ${indentation}`;
|
|
|
3807
3807
|
const tmp = stringifyArrayReplacer(key2, value[key2], stack, replacer, spacer, indentation);
|
|
3808
3808
|
if (tmp !== void 0) {
|
|
3809
3809
|
res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
|
|
3810
|
-
separator =
|
|
3810
|
+
separator = join50;
|
|
3811
3811
|
}
|
|
3812
3812
|
}
|
|
3813
3813
|
if (spacer !== "" && separator.length > 1) {
|
|
@@ -3865,20 +3865,20 @@ ${originalIndentation}`;
|
|
|
3865
3865
|
indentation += spacer;
|
|
3866
3866
|
let res2 = `
|
|
3867
3867
|
${indentation}`;
|
|
3868
|
-
const
|
|
3868
|
+
const join51 = `,
|
|
3869
3869
|
${indentation}`;
|
|
3870
3870
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
3871
3871
|
let i = 0;
|
|
3872
3872
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
3873
3873
|
const tmp2 = stringifyIndent(String(i), value[i], stack, spacer, indentation);
|
|
3874
3874
|
res2 += tmp2 !== void 0 ? tmp2 : "null";
|
|
3875
|
-
res2 +=
|
|
3875
|
+
res2 += join51;
|
|
3876
3876
|
}
|
|
3877
3877
|
const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation);
|
|
3878
3878
|
res2 += tmp !== void 0 ? tmp : "null";
|
|
3879
3879
|
if (value.length - 1 > maximumBreadth) {
|
|
3880
3880
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
3881
|
-
res2 += `${
|
|
3881
|
+
res2 += `${join51}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
3882
3882
|
}
|
|
3883
3883
|
res2 += `
|
|
3884
3884
|
${originalIndentation}`;
|
|
@@ -3894,16 +3894,16 @@ ${originalIndentation}`;
|
|
|
3894
3894
|
return '"[Object]"';
|
|
3895
3895
|
}
|
|
3896
3896
|
indentation += spacer;
|
|
3897
|
-
const
|
|
3897
|
+
const join50 = `,
|
|
3898
3898
|
${indentation}`;
|
|
3899
3899
|
let res = "";
|
|
3900
3900
|
let separator = "";
|
|
3901
3901
|
let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
|
|
3902
3902
|
if (isTypedArrayWithEntries(value)) {
|
|
3903
|
-
res += stringifyTypedArray(value,
|
|
3903
|
+
res += stringifyTypedArray(value, join50, maximumBreadth);
|
|
3904
3904
|
keys = keys.slice(value.length);
|
|
3905
3905
|
maximumPropertiesToStringify -= value.length;
|
|
3906
|
-
separator =
|
|
3906
|
+
separator = join50;
|
|
3907
3907
|
}
|
|
3908
3908
|
if (deterministic) {
|
|
3909
3909
|
keys = sort(keys, comparator);
|
|
@@ -3914,13 +3914,13 @@ ${indentation}`;
|
|
|
3914
3914
|
const tmp = stringifyIndent(key2, value[key2], stack, spacer, indentation);
|
|
3915
3915
|
if (tmp !== void 0) {
|
|
3916
3916
|
res += `${separator}${strEscape(key2)}: ${tmp}`;
|
|
3917
|
-
separator =
|
|
3917
|
+
separator = join50;
|
|
3918
3918
|
}
|
|
3919
3919
|
}
|
|
3920
3920
|
if (keyLength > maximumBreadth) {
|
|
3921
3921
|
const removedKeys = keyLength - maximumBreadth;
|
|
3922
3922
|
res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`;
|
|
3923
|
-
separator =
|
|
3923
|
+
separator = join50;
|
|
3924
3924
|
}
|
|
3925
3925
|
if (separator !== "") {
|
|
3926
3926
|
res = `
|
|
@@ -4721,7 +4721,8 @@ function defaultSync() {
|
|
|
4721
4721
|
function isPersonalPath(projectPath, includeProjects = []) {
|
|
4722
4722
|
if (includeProjects.some((inc) => inc && projectPath.includes(inc)))
|
|
4723
4723
|
return false;
|
|
4724
|
-
|
|
4724
|
+
const norm = (projectPath.replace(/\\/g, "/") + "/").toLowerCase();
|
|
4725
|
+
return PERSONAL_DIR_NAMES.some((n) => norm.includes(`/${n.toLowerCase()}/`));
|
|
4725
4726
|
}
|
|
4726
4727
|
function defaultTeam() {
|
|
4727
4728
|
return {
|
|
@@ -4843,6 +4844,16 @@ function loadSecrets() {
|
|
|
4843
4844
|
const p = secretsPath();
|
|
4844
4845
|
if (!existsSync2(p))
|
|
4845
4846
|
return out;
|
|
4847
|
+
let mtimeMs = -1, size = -1;
|
|
4848
|
+
try {
|
|
4849
|
+
const st = statSync2(p);
|
|
4850
|
+
mtimeMs = st.mtimeMs;
|
|
4851
|
+
size = st.size;
|
|
4852
|
+
} catch {
|
|
4853
|
+
}
|
|
4854
|
+
if (_secretsCache && _secretsCache.mtimeMs === mtimeMs && _secretsCache.size === size) {
|
|
4855
|
+
return { ..._secretsCache.value };
|
|
4856
|
+
}
|
|
4846
4857
|
try {
|
|
4847
4858
|
for (const line of readFileSync(p, "utf-8").split("\n")) {
|
|
4848
4859
|
const t = line.trim();
|
|
@@ -4860,9 +4871,12 @@ function loadSecrets() {
|
|
|
4860
4871
|
}
|
|
4861
4872
|
} catch {
|
|
4862
4873
|
}
|
|
4874
|
+
if (mtimeMs >= 0)
|
|
4875
|
+
_secretsCache = { mtimeMs, size, value: { ...out } };
|
|
4863
4876
|
return out;
|
|
4864
4877
|
}
|
|
4865
4878
|
function writeSecrets(secrets) {
|
|
4879
|
+
_secretsCache = null;
|
|
4866
4880
|
const p = secretsPath();
|
|
4867
4881
|
mkdirSync2(dirname2(p), { recursive: true });
|
|
4868
4882
|
const body = "# chat-recall secrets \u2014 NOT committed/synced. Mode 0600.\n" + Object.entries(secrets).filter(([, v]) => v).map(([k, v]) => `${k}=${v}`).join("\n") + "\n";
|
|
@@ -4872,10 +4886,31 @@ function writeSecrets(secrets) {
|
|
|
4872
4886
|
} catch {
|
|
4873
4887
|
}
|
|
4874
4888
|
}
|
|
4889
|
+
function applySecretOverlay(result) {
|
|
4890
|
+
const secrets = loadSecrets();
|
|
4891
|
+
for (const { block, field, env } of SECRET_FIELDS) {
|
|
4892
|
+
const blk = result[block];
|
|
4893
|
+
const value = process.env[env] || secrets[env] || blk[field];
|
|
4894
|
+
if (value)
|
|
4895
|
+
blk[field] = value;
|
|
4896
|
+
}
|
|
4897
|
+
return result;
|
|
4898
|
+
}
|
|
4875
4899
|
function loadSettings() {
|
|
4876
4900
|
const path = settingsPath();
|
|
4877
4901
|
if (!existsSync2(path))
|
|
4878
4902
|
return freshDefaults();
|
|
4903
|
+
let mtimeMs = -1, size = -1;
|
|
4904
|
+
try {
|
|
4905
|
+
const st = statSync2(path);
|
|
4906
|
+
mtimeMs = st.mtimeMs;
|
|
4907
|
+
size = st.size;
|
|
4908
|
+
} catch {
|
|
4909
|
+
}
|
|
4910
|
+
if (_settingsCache && _settingsCache.mtimeMs === mtimeMs && _settingsCache.size === size) {
|
|
4911
|
+
const cached = structuredClone(_settingsCache.value);
|
|
4912
|
+
return applySecretOverlay(cached);
|
|
4913
|
+
}
|
|
4879
4914
|
try {
|
|
4880
4915
|
const parsed = JSON.parse(readFileSync(path, "utf-8"));
|
|
4881
4916
|
const base2 = freshDefaults();
|
|
@@ -4888,19 +4923,15 @@ function loadSettings() {
|
|
|
4888
4923
|
sync: mergeSync(base2.sync, parsed.sync),
|
|
4889
4924
|
team: mergeTeam(base2.team, parsed.team)
|
|
4890
4925
|
};
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
const value = process.env[env] || secrets[env] || blk[field];
|
|
4895
|
-
if (value)
|
|
4896
|
-
blk[field] = value;
|
|
4897
|
-
}
|
|
4898
|
-
return result;
|
|
4926
|
+
if (mtimeMs >= 0)
|
|
4927
|
+
_settingsCache = { mtimeMs, size, value: structuredClone(result) };
|
|
4928
|
+
return applySecretOverlay(result);
|
|
4899
4929
|
} catch {
|
|
4900
4930
|
return freshDefaults();
|
|
4901
4931
|
}
|
|
4902
4932
|
}
|
|
4903
4933
|
function saveSettings(settings2) {
|
|
4934
|
+
_settingsCache = null;
|
|
4904
4935
|
const secrets = loadSecrets();
|
|
4905
4936
|
const stripped = {
|
|
4906
4937
|
...settings2,
|
|
@@ -4924,7 +4955,7 @@ function saveSettings(settings2) {
|
|
|
4924
4955
|
} catch {
|
|
4925
4956
|
}
|
|
4926
4957
|
}
|
|
4927
|
-
var CLI_DETECTION_ORDER, SCHEMA_VERSION, PERSONAL_DIR_PATTERNS, _sourceSettingsCache, SECRET_FIELDS;
|
|
4958
|
+
var CLI_DETECTION_ORDER, SCHEMA_VERSION, PERSONAL_DIR_NAMES, PERSONAL_DIR_PATTERNS, _sourceSettingsCache, SECRET_FIELDS, _secretsCache, _settingsCache;
|
|
4928
4959
|
var init_settings = __esm({
|
|
4929
4960
|
"../engine/dist/core/settings.js"() {
|
|
4930
4961
|
"use strict";
|
|
@@ -4938,17 +4969,18 @@ var init_settings = __esm({
|
|
|
4938
4969
|
{ preset: "aichat", bin: "aichat", cmd: "aichat --no-stream" }
|
|
4939
4970
|
];
|
|
4940
4971
|
SCHEMA_VERSION = 3;
|
|
4941
|
-
|
|
4942
|
-
"
|
|
4943
|
-
"
|
|
4944
|
-
"
|
|
4945
|
-
"
|
|
4946
|
-
"
|
|
4947
|
-
"
|
|
4948
|
-
"
|
|
4949
|
-
"
|
|
4950
|
-
"
|
|
4972
|
+
PERSONAL_DIR_NAMES = [
|
|
4973
|
+
"Pictures",
|
|
4974
|
+
"Music",
|
|
4975
|
+
"Movies",
|
|
4976
|
+
"Videos",
|
|
4977
|
+
"Photos Library",
|
|
4978
|
+
"Documents",
|
|
4979
|
+
"Desktop",
|
|
4980
|
+
"Downloads",
|
|
4981
|
+
"Library"
|
|
4951
4982
|
];
|
|
4983
|
+
PERSONAL_DIR_PATTERNS = PERSONAL_DIR_NAMES.map((n) => `/${n}/`);
|
|
4952
4984
|
_sourceSettingsCache = null;
|
|
4953
4985
|
SECRET_FIELDS = [
|
|
4954
4986
|
{ block: "summary", field: "apiKey", env: "SUMMARY_API_KEY" },
|
|
@@ -4959,6 +4991,8 @@ var init_settings = __esm({
|
|
|
4959
4991
|
{ block: "embedding", field: "ollamaCloudApiKey", env: "OLLAMA_API_KEY" },
|
|
4960
4992
|
{ block: "embedding", field: "openaiCompatApiKey", env: "OPENAI_COMPAT_API_KEY" }
|
|
4961
4993
|
];
|
|
4994
|
+
_secretsCache = null;
|
|
4995
|
+
_settingsCache = null;
|
|
4962
4996
|
}
|
|
4963
4997
|
});
|
|
4964
4998
|
|
|
@@ -5048,14 +5082,14 @@ function primaryHomes() {
|
|
|
5048
5082
|
s = void 0;
|
|
5049
5083
|
}
|
|
5050
5084
|
const opencodeDb = env.CHAT_RECALL_OPENCODE_DB || s?.opencodeDbPath || join3(home, ".local", "share", "opencode", "opencode.db");
|
|
5051
|
-
const
|
|
5085
|
+
const candidates2 = [
|
|
5052
5086
|
env.CHAT_RECALL_CLAUDE_HOME || s?.claudeHome || join3(home, ".claude"),
|
|
5053
5087
|
env.CHAT_RECALL_GEMINI_HOME || s?.geminiHome || join3(home, ".gemini"),
|
|
5054
5088
|
env.CHAT_RECALL_CODEX_HOME || s?.codexHome || join3(home, ".codex"),
|
|
5055
5089
|
env.CHAT_RECALL_AGY_HOME || s?.agyHome || join3(home, ".gemini", "antigravity-cli"),
|
|
5056
5090
|
dirOf(opencodeDb)
|
|
5057
5091
|
];
|
|
5058
|
-
return
|
|
5092
|
+
return candidates2.map(normalizeHomePath);
|
|
5059
5093
|
}
|
|
5060
5094
|
function homeDecision(path) {
|
|
5061
5095
|
const p = normalizeHomePath(path);
|
|
@@ -5408,28 +5442,55 @@ function maskSecret(s) {
|
|
|
5408
5442
|
return "*".repeat(s.length);
|
|
5409
5443
|
return "*".repeat(Math.min(s.length - 4, 60)) + s.slice(-4);
|
|
5410
5444
|
}
|
|
5445
|
+
function globalRegexFor(pattern) {
|
|
5446
|
+
const flags = pattern.flags.includes("g") ? pattern.flags : pattern.flags + "g";
|
|
5447
|
+
const key = pattern.source + "\0" + flags;
|
|
5448
|
+
let re = globalRegexCache.get(key);
|
|
5449
|
+
if (!re) {
|
|
5450
|
+
re = new RegExp(pattern.source, flags);
|
|
5451
|
+
globalRegexCache.set(key, re);
|
|
5452
|
+
}
|
|
5453
|
+
return re;
|
|
5454
|
+
}
|
|
5455
|
+
function makeLineResolver(text) {
|
|
5456
|
+
const starts = [];
|
|
5457
|
+
for (let i = text.indexOf("\n"); i !== -1; i = text.indexOf("\n", i + 1))
|
|
5458
|
+
starts.push(i);
|
|
5459
|
+
return (index) => {
|
|
5460
|
+
let lo = 0, hi = starts.length;
|
|
5461
|
+
while (lo < hi) {
|
|
5462
|
+
const mid = lo + hi >> 1;
|
|
5463
|
+
if (starts[mid] < index)
|
|
5464
|
+
lo = mid + 1;
|
|
5465
|
+
else
|
|
5466
|
+
hi = mid;
|
|
5467
|
+
}
|
|
5468
|
+
return lo + 1;
|
|
5469
|
+
};
|
|
5470
|
+
}
|
|
5411
5471
|
function scanTextForFindings(text, opts = {}) {
|
|
5412
5472
|
if (!text)
|
|
5413
5473
|
return [];
|
|
5414
5474
|
const rules = opts.rules || activeRules();
|
|
5415
5475
|
const findings = [];
|
|
5416
5476
|
const seenSpans = /* @__PURE__ */ new Set();
|
|
5477
|
+
const lineAt = makeLineResolver(text);
|
|
5417
5478
|
for (const r of rules) {
|
|
5418
|
-
const re =
|
|
5479
|
+
const re = globalRegexFor(r.pattern);
|
|
5480
|
+
re.lastIndex = 0;
|
|
5419
5481
|
let m;
|
|
5420
5482
|
while ((m = re.exec(text)) !== null) {
|
|
5421
5483
|
const span = `${m.index}:${m[0].length}`;
|
|
5422
5484
|
if (!seenSpans.has(span)) {
|
|
5423
5485
|
seenSpans.add(span);
|
|
5424
|
-
|
|
5425
|
-
findings.push({ rule: r.label, line, preview: maskSecret(m[0]) });
|
|
5486
|
+
findings.push({ rule: r.label, line: lineAt(m.index), preview: maskSecret(m[0]) });
|
|
5426
5487
|
}
|
|
5427
5488
|
if (re.lastIndex === m.index)
|
|
5428
5489
|
re.lastIndex++;
|
|
5429
5490
|
}
|
|
5430
5491
|
}
|
|
5431
5492
|
for (const { start, end } of findContextualSecrets(text)) {
|
|
5432
|
-
const line =
|
|
5493
|
+
const line = lineAt(start);
|
|
5433
5494
|
findings.push({ rule: "secret-context", line, preview: maskSecret(text.slice(start, end)) });
|
|
5434
5495
|
}
|
|
5435
5496
|
return findings;
|
|
@@ -5460,7 +5521,7 @@ function redactToolResultBody(toolName, body) {
|
|
|
5460
5521
|
return body;
|
|
5461
5522
|
return `[redacted: ${toolName} output, ${body.length} chars]`;
|
|
5462
5523
|
}
|
|
5463
|
-
var DEFAULT_REDACTION_RULES, SECRET_CONTEXT_RE, HIGH_ENTROPY_TOKEN_RE, cache, CANARY, MAX_PACK_RULES, MAX_PATTERN_LEN, serverPack, privacyCache;
|
|
5524
|
+
var DEFAULT_REDACTION_RULES, SECRET_CONTEXT_RE, HIGH_ENTROPY_TOKEN_RE, cache, CANARY, MAX_PACK_RULES, MAX_PATTERN_LEN, serverPack, globalRegexCache, privacyCache;
|
|
5464
5525
|
var init_secret_redactor = __esm({
|
|
5465
5526
|
"../engine/dist/core/secret-redactor.js"() {
|
|
5466
5527
|
"use strict";
|
|
@@ -5598,6 +5659,7 @@ var init_secret_redactor = __esm({
|
|
|
5598
5659
|
MAX_PACK_RULES = 200;
|
|
5599
5660
|
MAX_PATTERN_LEN = 512;
|
|
5600
5661
|
serverPack = null;
|
|
5662
|
+
globalRegexCache = /* @__PURE__ */ new Map();
|
|
5601
5663
|
privacyCache = null;
|
|
5602
5664
|
}
|
|
5603
5665
|
});
|
|
@@ -6357,8 +6419,8 @@ function decodeDirName(dirName) {
|
|
|
6357
6419
|
}
|
|
6358
6420
|
for (let len = 2; len <= segments.length - i; len++) {
|
|
6359
6421
|
const joinedSegments = segments.slice(i, i + len);
|
|
6360
|
-
for (const
|
|
6361
|
-
const candidate = join5(currentPath, joinedSegments.join(
|
|
6422
|
+
for (const sep4 of ["-", "_", "."]) {
|
|
6423
|
+
const candidate = join5(currentPath, joinedSegments.join(sep4));
|
|
6362
6424
|
if (existsSync5(candidate)) {
|
|
6363
6425
|
currentPath = candidate;
|
|
6364
6426
|
i += len;
|
|
@@ -7110,7 +7172,7 @@ async function archiveRawSession(store, sessionId) {
|
|
|
7110
7172
|
}
|
|
7111
7173
|
function detectForkPredecessor(sessionPath) {
|
|
7112
7174
|
const { readFileSync: readFileSync41, readdirSync: readdirSync31 } = requireFs();
|
|
7113
|
-
const { dirname:
|
|
7175
|
+
const { dirname: dirname22, join: join50, basename: basename26 } = requirePath();
|
|
7114
7176
|
let text;
|
|
7115
7177
|
try {
|
|
7116
7178
|
text = readFileSync41(sessionPath, "utf-8");
|
|
@@ -7135,7 +7197,7 @@ function detectForkPredecessor(sessionPath) {
|
|
|
7135
7197
|
return null;
|
|
7136
7198
|
if (text.includes(`"uuid":"${headParent}"`))
|
|
7137
7199
|
return null;
|
|
7138
|
-
const dir =
|
|
7200
|
+
const dir = dirname22(sessionPath);
|
|
7139
7201
|
const self = basename26(sessionPath);
|
|
7140
7202
|
let entries;
|
|
7141
7203
|
try {
|
|
@@ -7147,7 +7209,7 @@ function detectForkPredecessor(sessionPath) {
|
|
|
7147
7209
|
if (!f.endsWith(".jsonl") || f === self || f === "sessions-index.json")
|
|
7148
7210
|
continue;
|
|
7149
7211
|
try {
|
|
7150
|
-
if (readFileSync41(
|
|
7212
|
+
if (readFileSync41(join50(dir, f), "utf-8").includes(`"uuid":"${headParent}"`)) {
|
|
7151
7213
|
return basename26(f, ".jsonl");
|
|
7152
7214
|
}
|
|
7153
7215
|
} catch {
|
|
@@ -7351,18 +7413,43 @@ function updateShadow(sessionId, exp) {
|
|
|
7351
7413
|
path
|
|
7352
7414
|
};
|
|
7353
7415
|
}
|
|
7354
|
-
async function snapshotShadow(sessionId) {
|
|
7416
|
+
async function snapshotShadow(sessionId, opts = {}) {
|
|
7355
7417
|
await Promise.resolve().then(() => (init_backends(), backends_exports));
|
|
7356
7418
|
const { getBackendForId: getBackendForId2, getBackend: getBackend2 } = await Promise.resolve().then(() => (init_tool_backend(), tool_backend_exports));
|
|
7357
7419
|
const backend = getBackendForId2(sessionId) ?? getBackend2("claude");
|
|
7358
7420
|
const rawId = backend.toRawId(sessionId);
|
|
7421
|
+
const fp = liveFingerprint(backend, rawId);
|
|
7422
|
+
if (!opts.force && fp && lastLiveFingerprint.get(rawId) === fp) {
|
|
7423
|
+
return {
|
|
7424
|
+
status: "skipped",
|
|
7425
|
+
sessionId,
|
|
7426
|
+
tool: backend.id,
|
|
7427
|
+
container: null,
|
|
7428
|
+
recovered: 0,
|
|
7429
|
+
path: shadowFileFor(backend.id, rawId)
|
|
7430
|
+
};
|
|
7431
|
+
}
|
|
7359
7432
|
let exp = null;
|
|
7360
7433
|
try {
|
|
7361
7434
|
exp = backend.exportRawSession(rawId);
|
|
7362
7435
|
} catch {
|
|
7363
7436
|
exp = null;
|
|
7364
7437
|
}
|
|
7365
|
-
|
|
7438
|
+
const result = updateShadow(rawId, exp);
|
|
7439
|
+
if (fp && result.status !== "unavailable")
|
|
7440
|
+
lastLiveFingerprint.set(rawId, fp);
|
|
7441
|
+
return result;
|
|
7442
|
+
}
|
|
7443
|
+
function liveFingerprint(backend, rawId) {
|
|
7444
|
+
try {
|
|
7445
|
+
const loc = backend.findSession(rawId);
|
|
7446
|
+
if (!loc?.path)
|
|
7447
|
+
return "";
|
|
7448
|
+
const st = statSync5(loc.path);
|
|
7449
|
+
return `${st.mtimeMs}:${st.size}`;
|
|
7450
|
+
} catch {
|
|
7451
|
+
return "";
|
|
7452
|
+
}
|
|
7366
7453
|
}
|
|
7367
7454
|
function seedShadow(sessionId, container) {
|
|
7368
7455
|
const tool = container.tool;
|
|
@@ -7381,7 +7468,7 @@ function shadowSizeOnDisk(tool, rawId) {
|
|
|
7381
7468
|
return 0;
|
|
7382
7469
|
}
|
|
7383
7470
|
}
|
|
7384
|
-
var WHOLE_FILE_TOOLS, SINGLETON_META;
|
|
7471
|
+
var WHOLE_FILE_TOOLS, SINGLETON_META, lastLiveFingerprint;
|
|
7385
7472
|
var init_shadow = __esm({
|
|
7386
7473
|
"../engine/dist/transcript/shadow.js"() {
|
|
7387
7474
|
"use strict";
|
|
@@ -7389,6 +7476,27 @@ var init_shadow = __esm({
|
|
|
7389
7476
|
init_raw();
|
|
7390
7477
|
WHOLE_FILE_TOOLS = /* @__PURE__ */ new Set(["gemini"]);
|
|
7391
7478
|
SINGLETON_META = /* @__PURE__ */ new Set(["mode", "permission-mode", "ai-title", "last-prompt", "pr-link", "summary"]);
|
|
7479
|
+
lastLiveFingerprint = /* @__PURE__ */ new Map();
|
|
7480
|
+
}
|
|
7481
|
+
});
|
|
7482
|
+
|
|
7483
|
+
// ../engine/dist/core/project-dir-name.js
|
|
7484
|
+
function looksWindowsEncoded(dirName) {
|
|
7485
|
+
return /^[A-Za-z]--/.test(dirName);
|
|
7486
|
+
}
|
|
7487
|
+
function decodeProjectDirName(dirName) {
|
|
7488
|
+
if (!dirName)
|
|
7489
|
+
return "";
|
|
7490
|
+
if (looksWindowsEncoded(dirName)) {
|
|
7491
|
+
const drive = dirName[0].toUpperCase();
|
|
7492
|
+
const rest = dirName.slice(3).replace(/-/g, "\\");
|
|
7493
|
+
return `${drive}:\\${rest}`;
|
|
7494
|
+
}
|
|
7495
|
+
return "/" + dirName.replace(/^-/, "").replace(/-/g, "/");
|
|
7496
|
+
}
|
|
7497
|
+
var init_project_dir_name = __esm({
|
|
7498
|
+
"../engine/dist/core/project-dir-name.js"() {
|
|
7499
|
+
"use strict";
|
|
7392
7500
|
}
|
|
7393
7501
|
});
|
|
7394
7502
|
|
|
@@ -7415,7 +7523,7 @@ function findSessionFile(sessionId) {
|
|
|
7415
7523
|
path: candidate,
|
|
7416
7524
|
projectDir: entry.name,
|
|
7417
7525
|
// Project path is encoded by replacing slashes with dashes.
|
|
7418
|
-
projectPath: entry.name
|
|
7526
|
+
projectPath: decodeProjectDirName(entry.name)
|
|
7419
7527
|
};
|
|
7420
7528
|
}
|
|
7421
7529
|
}
|
|
@@ -7444,7 +7552,7 @@ function findSessionFiles(sessionId) {
|
|
|
7444
7552
|
out.push({
|
|
7445
7553
|
path: candidate,
|
|
7446
7554
|
projectDir: entry.name,
|
|
7447
|
-
projectPath: entry.name
|
|
7555
|
+
projectPath: decodeProjectDirName(entry.name)
|
|
7448
7556
|
});
|
|
7449
7557
|
}
|
|
7450
7558
|
}
|
|
@@ -7468,7 +7576,31 @@ function resolveSessionContentGroups(sessionId) {
|
|
|
7468
7576
|
const names = [...groups.keys()].sort((a, b) => a === "main" ? -1 : b === "main" ? 1 : a.localeCompare(b));
|
|
7469
7577
|
return names.map((name) => ({ name, paths: groups.get(name) }));
|
|
7470
7578
|
}
|
|
7579
|
+
function withSessionReadCache(fn) {
|
|
7580
|
+
readScopeDepth++;
|
|
7581
|
+
try {
|
|
7582
|
+
return fn();
|
|
7583
|
+
} finally {
|
|
7584
|
+
if (--readScopeDepth === 0)
|
|
7585
|
+
readScope = null;
|
|
7586
|
+
}
|
|
7587
|
+
}
|
|
7471
7588
|
function readSessionGroupText(group) {
|
|
7589
|
+
let key = "";
|
|
7590
|
+
if (readScopeDepth > 0) {
|
|
7591
|
+
const parts = [];
|
|
7592
|
+
for (const p of group.paths) {
|
|
7593
|
+
try {
|
|
7594
|
+
const st = statSync6(p);
|
|
7595
|
+
parts.push(`${p}:${st.mtimeMs}:${st.size}`);
|
|
7596
|
+
} catch {
|
|
7597
|
+
parts.push(`${p}:missing`);
|
|
7598
|
+
}
|
|
7599
|
+
}
|
|
7600
|
+
key = parts.join("|");
|
|
7601
|
+
if (readScope && readScope.key === key)
|
|
7602
|
+
return readScope.value;
|
|
7603
|
+
}
|
|
7472
7604
|
let text = "";
|
|
7473
7605
|
let mtime = 0;
|
|
7474
7606
|
for (const p of group.paths) {
|
|
@@ -7484,7 +7616,10 @@ function readSessionGroupText(group) {
|
|
|
7484
7616
|
}
|
|
7485
7617
|
text = text ? mergeLineText(text, raw).text : raw;
|
|
7486
7618
|
}
|
|
7487
|
-
|
|
7619
|
+
const out = { text, mtime };
|
|
7620
|
+
if (readScopeDepth > 0 && key)
|
|
7621
|
+
readScope = { key, value: out };
|
|
7622
|
+
return out;
|
|
7488
7623
|
}
|
|
7489
7624
|
function resolveSessionContentPaths(sessionFile) {
|
|
7490
7625
|
if (!hasSubagentsDir(sessionFile))
|
|
@@ -7707,7 +7842,7 @@ function findCodexSessionFileIn(root, sessionId) {
|
|
|
7707
7842
|
}
|
|
7708
7843
|
return scanDir(root);
|
|
7709
7844
|
}
|
|
7710
|
-
var geminiProjectMapCache, MAX_EVENT_LINE_BYTES;
|
|
7845
|
+
var readScope, readScopeDepth, geminiProjectMapCache, MAX_EVENT_LINE_BYTES;
|
|
7711
7846
|
var init_live_session_scan = __esm({
|
|
7712
7847
|
"../engine/dist/core/live-session-scan.js"() {
|
|
7713
7848
|
"use strict";
|
|
@@ -7716,6 +7851,9 @@ var init_live_session_scan = __esm({
|
|
|
7716
7851
|
init_tool_backend();
|
|
7717
7852
|
init_tool_paths();
|
|
7718
7853
|
init_backends();
|
|
7854
|
+
init_project_dir_name();
|
|
7855
|
+
readScope = null;
|
|
7856
|
+
readScopeDepth = 0;
|
|
7719
7857
|
geminiProjectMapCache = null;
|
|
7720
7858
|
MAX_EVENT_LINE_BYTES = 8 * 1024 * 1024;
|
|
7721
7859
|
}
|
|
@@ -8176,74 +8314,123 @@ var init_session_outcome = __esm({
|
|
|
8176
8314
|
}
|
|
8177
8315
|
});
|
|
8178
8316
|
|
|
8317
|
+
// ../engine/dist/core/flat-string.js
|
|
8318
|
+
function flatString(s) {
|
|
8319
|
+
if (!s)
|
|
8320
|
+
return "";
|
|
8321
|
+
if (s.length < 13)
|
|
8322
|
+
return s;
|
|
8323
|
+
return Buffer.from(s, "utf8").toString("utf8");
|
|
8324
|
+
}
|
|
8325
|
+
var init_flat_string = __esm({
|
|
8326
|
+
"../engine/dist/core/flat-string.js"() {
|
|
8327
|
+
"use strict";
|
|
8328
|
+
}
|
|
8329
|
+
});
|
|
8330
|
+
|
|
8179
8331
|
// ../engine/dist/core/first-prompt.js
|
|
8180
|
-
import { createReadStream as createReadStream2, existsSync as existsSync9,
|
|
8332
|
+
import { createReadStream as createReadStream2, existsSync as existsSync9, openSync as openSync3, readSync as readSync3, closeSync as closeSync3 } from "fs";
|
|
8333
|
+
import { StringDecoder } from "string_decoder";
|
|
8181
8334
|
function stripBanners2(s) {
|
|
8182
8335
|
let out = s;
|
|
8183
8336
|
for (const re of BANNERS)
|
|
8184
8337
|
out = out.replace(re, " ");
|
|
8185
8338
|
return out.replace(/[ \t]{2,}/g, " ").trim();
|
|
8186
8339
|
}
|
|
8340
|
+
function promptFromLine(raw, maxLength) {
|
|
8341
|
+
if (!raw.trim())
|
|
8342
|
+
return null;
|
|
8343
|
+
let obj;
|
|
8344
|
+
try {
|
|
8345
|
+
obj = JSON.parse(raw);
|
|
8346
|
+
} catch {
|
|
8347
|
+
return null;
|
|
8348
|
+
}
|
|
8349
|
+
if (obj.type !== "user")
|
|
8350
|
+
return null;
|
|
8351
|
+
if (obj.isSidechain === true)
|
|
8352
|
+
return null;
|
|
8353
|
+
const message = obj.message;
|
|
8354
|
+
if (!message)
|
|
8355
|
+
return null;
|
|
8356
|
+
const content = message.content;
|
|
8357
|
+
let text = "";
|
|
8358
|
+
if (typeof content === "string") {
|
|
8359
|
+
text = content;
|
|
8360
|
+
} else if (Array.isArray(content)) {
|
|
8361
|
+
const parts = [];
|
|
8362
|
+
for (const block of content) {
|
|
8363
|
+
if (block && typeof block === "object" && block.type === "text" && typeof block.text === "string") {
|
|
8364
|
+
parts.push(block.text);
|
|
8365
|
+
}
|
|
8366
|
+
}
|
|
8367
|
+
text = parts.join("\n");
|
|
8368
|
+
}
|
|
8369
|
+
if (!text)
|
|
8370
|
+
return null;
|
|
8371
|
+
if (text.includes("<system-reminder>"))
|
|
8372
|
+
return null;
|
|
8373
|
+
if (text.trim() === "[Request interrupted by user]")
|
|
8374
|
+
return null;
|
|
8375
|
+
const cleaned = stripBanners2(text);
|
|
8376
|
+
if (cleaned.length < 10)
|
|
8377
|
+
return null;
|
|
8378
|
+
return flatString(cleaned.slice(0, maxLength));
|
|
8379
|
+
}
|
|
8187
8380
|
function extractFirstUserPromptSync(filePath, options = {}) {
|
|
8188
8381
|
const maxLines = options.maxLines ?? 500;
|
|
8189
8382
|
const maxLength = options.maxLength ?? 1e3;
|
|
8190
|
-
|
|
8191
|
-
|
|
8192
|
-
let raw;
|
|
8383
|
+
const maxBytes = options.maxBytes ?? 4 * 1024 * 1024;
|
|
8384
|
+
let fd;
|
|
8193
8385
|
try {
|
|
8194
|
-
|
|
8386
|
+
fd = openSync3(filePath, "r");
|
|
8195
8387
|
} catch {
|
|
8196
8388
|
return "";
|
|
8197
8389
|
}
|
|
8198
|
-
|
|
8199
|
-
|
|
8200
|
-
|
|
8201
|
-
const
|
|
8202
|
-
|
|
8203
|
-
|
|
8204
|
-
let
|
|
8390
|
+
try {
|
|
8391
|
+
const CHUNK = 64 * 1024;
|
|
8392
|
+
const buf = Buffer.allocUnsafe(CHUNK);
|
|
8393
|
+
const decoder = new StringDecoder("utf-8");
|
|
8394
|
+
let carry = "";
|
|
8395
|
+
let pos = 0;
|
|
8396
|
+
let lineNo = 0;
|
|
8397
|
+
for (; ; ) {
|
|
8398
|
+
const n = readSync3(fd, buf, 0, CHUNK, pos);
|
|
8399
|
+
if (n <= 0)
|
|
8400
|
+
break;
|
|
8401
|
+
pos += n;
|
|
8402
|
+
carry += decoder.write(buf.subarray(0, n));
|
|
8403
|
+
const parts = carry.split("\n");
|
|
8404
|
+
carry = parts.pop() ?? "";
|
|
8405
|
+
for (const line of parts) {
|
|
8406
|
+
if (++lineNo > maxLines)
|
|
8407
|
+
return "";
|
|
8408
|
+
const found = promptFromLine(line, maxLength);
|
|
8409
|
+
if (found !== null)
|
|
8410
|
+
return found;
|
|
8411
|
+
}
|
|
8412
|
+
if (pos >= maxBytes)
|
|
8413
|
+
return "";
|
|
8414
|
+
}
|
|
8415
|
+
carry += decoder.end();
|
|
8416
|
+
if (carry && lineNo < maxLines) {
|
|
8417
|
+
const found = promptFromLine(carry, maxLength);
|
|
8418
|
+
if (found !== null)
|
|
8419
|
+
return found;
|
|
8420
|
+
}
|
|
8421
|
+
return "";
|
|
8422
|
+
} finally {
|
|
8205
8423
|
try {
|
|
8206
|
-
|
|
8424
|
+
closeSync3(fd);
|
|
8207
8425
|
} catch {
|
|
8208
|
-
continue;
|
|
8209
|
-
}
|
|
8210
|
-
if (obj.type !== "user")
|
|
8211
|
-
continue;
|
|
8212
|
-
if (obj.isSidechain === true)
|
|
8213
|
-
continue;
|
|
8214
|
-
const message = obj.message;
|
|
8215
|
-
if (!message)
|
|
8216
|
-
continue;
|
|
8217
|
-
const content = message.content;
|
|
8218
|
-
let text = "";
|
|
8219
|
-
if (typeof content === "string") {
|
|
8220
|
-
text = content;
|
|
8221
|
-
} else if (Array.isArray(content)) {
|
|
8222
|
-
const parts = [];
|
|
8223
|
-
for (const block of content) {
|
|
8224
|
-
if (block && typeof block === "object" && block.type === "text" && typeof block.text === "string") {
|
|
8225
|
-
parts.push(block.text);
|
|
8226
|
-
}
|
|
8227
|
-
}
|
|
8228
|
-
text = parts.join("\n");
|
|
8229
8426
|
}
|
|
8230
|
-
if (!text)
|
|
8231
|
-
continue;
|
|
8232
|
-
if (text.includes("<system-reminder>"))
|
|
8233
|
-
continue;
|
|
8234
|
-
if (text.trim() === "[Request interrupted by user]")
|
|
8235
|
-
continue;
|
|
8236
|
-
const cleaned = stripBanners2(text);
|
|
8237
|
-
if (cleaned.length < 10)
|
|
8238
|
-
continue;
|
|
8239
|
-
return cleaned.slice(0, maxLength);
|
|
8240
8427
|
}
|
|
8241
|
-
return "";
|
|
8242
8428
|
}
|
|
8243
8429
|
var BANNERS;
|
|
8244
8430
|
var init_first_prompt = __esm({
|
|
8245
8431
|
"../engine/dist/core/first-prompt.js"() {
|
|
8246
8432
|
"use strict";
|
|
8433
|
+
init_flat_string();
|
|
8247
8434
|
BANNERS = [
|
|
8248
8435
|
/MCP issues detected\. ?Run \/mcp list for status\.?/g,
|
|
8249
8436
|
/Context low[^\n]*Run \/compact[^\n]*/g,
|
|
@@ -8253,7 +8440,7 @@ var init_first_prompt = __esm({
|
|
|
8253
8440
|
});
|
|
8254
8441
|
|
|
8255
8442
|
// ../engine/dist/core/backends/tail-read.js
|
|
8256
|
-
import { openSync as
|
|
8443
|
+
import { openSync as openSync4, readSync as readSync4, closeSync as closeSync4, statSync as statSync7 } from "node:fs";
|
|
8257
8444
|
function readTailFromOffset(path, offset) {
|
|
8258
8445
|
let size = 0;
|
|
8259
8446
|
try {
|
|
@@ -8267,10 +8454,10 @@ function readTailFromOffset(path, offset) {
|
|
|
8267
8454
|
const buf = Buffer.allocUnsafe(len);
|
|
8268
8455
|
let fd = null;
|
|
8269
8456
|
try {
|
|
8270
|
-
fd =
|
|
8457
|
+
fd = openSync4(path, "r");
|
|
8271
8458
|
let got = 0;
|
|
8272
8459
|
while (got < len) {
|
|
8273
|
-
const n =
|
|
8460
|
+
const n = readSync4(fd, buf, got, len - got, offset + got);
|
|
8274
8461
|
if (n <= 0)
|
|
8275
8462
|
break;
|
|
8276
8463
|
got += n;
|
|
@@ -8289,7 +8476,7 @@ function readTailFromOffset(path, offset) {
|
|
|
8289
8476
|
} finally {
|
|
8290
8477
|
if (fd !== null) {
|
|
8291
8478
|
try {
|
|
8292
|
-
|
|
8479
|
+
closeSync4(fd);
|
|
8293
8480
|
} catch {
|
|
8294
8481
|
}
|
|
8295
8482
|
}
|
|
@@ -8574,7 +8761,7 @@ var init_generic_engine = __esm({
|
|
|
8574
8761
|
});
|
|
8575
8762
|
|
|
8576
8763
|
// ../engine/dist/core/backends/claude.js
|
|
8577
|
-
import { existsSync as existsSync10, readdirSync as readdirSync6, readFileSync as
|
|
8764
|
+
import { existsSync as existsSync10, readdirSync as readdirSync6, readFileSync as readFileSync5, statSync as statSync8, openSync as openSync5, readSync as readSync5, closeSync as closeSync5 } from "fs";
|
|
8578
8765
|
import { join as join10, basename as basename8 } from "path";
|
|
8579
8766
|
function stripReminders(text) {
|
|
8580
8767
|
return text.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/g, "").trim();
|
|
@@ -8593,6 +8780,7 @@ var init_claude2 = __esm({
|
|
|
8593
8780
|
init_session_git();
|
|
8594
8781
|
init_first_prompt();
|
|
8595
8782
|
init_tail_read();
|
|
8783
|
+
init_project_dir_name();
|
|
8596
8784
|
init_generic_engine();
|
|
8597
8785
|
UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
8598
8786
|
ClaudeBackend = class {
|
|
@@ -8669,13 +8857,13 @@ var init_claude2 = __esm({
|
|
|
8669
8857
|
return null;
|
|
8670
8858
|
let head;
|
|
8671
8859
|
try {
|
|
8672
|
-
const fd =
|
|
8860
|
+
const fd = openSync5(located.path, "r");
|
|
8673
8861
|
try {
|
|
8674
8862
|
const buf = Buffer.alloc(65536);
|
|
8675
|
-
const n =
|
|
8863
|
+
const n = readSync5(fd, buf, 0, buf.length, 0);
|
|
8676
8864
|
head = buf.toString("utf-8", 0, n);
|
|
8677
8865
|
} finally {
|
|
8678
|
-
|
|
8866
|
+
closeSync5(fd);
|
|
8679
8867
|
}
|
|
8680
8868
|
} catch {
|
|
8681
8869
|
return null;
|
|
@@ -8734,11 +8922,11 @@ var init_claude2 = __esm({
|
|
|
8734
8922
|
if (filter && !proj.name.toLowerCase().includes(filter))
|
|
8735
8923
|
continue;
|
|
8736
8924
|
const projPath = join10(root, proj.name);
|
|
8737
|
-
const projectPath = proj.name
|
|
8925
|
+
const projectPath = decodeProjectDirName(proj.name);
|
|
8738
8926
|
const indexPath = join10(projPath, "sessions-index.json");
|
|
8739
8927
|
if (existsSync10(indexPath)) {
|
|
8740
8928
|
try {
|
|
8741
|
-
const indexData = JSON.parse(
|
|
8929
|
+
const indexData = JSON.parse(readFileSync5(indexPath, "utf-8"));
|
|
8742
8930
|
const entries = indexData.entries || [];
|
|
8743
8931
|
for (const entry of entries) {
|
|
8744
8932
|
if (!entry.fullPath || !existsSync10(entry.fullPath))
|
|
@@ -9030,7 +9218,7 @@ var init_claude2 = __esm({
|
|
|
9030
9218
|
* with quiet main + active subagents still surfaces.
|
|
9031
9219
|
*/
|
|
9032
9220
|
collectRecentEdits(opts) {
|
|
9033
|
-
const
|
|
9221
|
+
const candidates2 = [];
|
|
9034
9222
|
for (const root of claudeProjectDirs()) {
|
|
9035
9223
|
if (!existsSync10(root))
|
|
9036
9224
|
continue;
|
|
@@ -9066,14 +9254,14 @@ var init_claude2 = __esm({
|
|
|
9066
9254
|
}
|
|
9067
9255
|
if (mtime < opts.sinceMs)
|
|
9068
9256
|
continue;
|
|
9069
|
-
|
|
9257
|
+
candidates2.push({ rawId: basename8(f, ".jsonl"), mtime });
|
|
9070
9258
|
} catch {
|
|
9071
9259
|
}
|
|
9072
9260
|
}
|
|
9073
9261
|
}
|
|
9074
9262
|
}
|
|
9075
|
-
|
|
9076
|
-
const limited = opts.limitSessions ?
|
|
9263
|
+
candidates2.sort((a, b) => b.mtime - a.mtime);
|
|
9264
|
+
const limited = opts.limitSessions ? candidates2.slice(0, opts.limitSessions) : candidates2;
|
|
9077
9265
|
const edits = [];
|
|
9078
9266
|
for (const c of limited) {
|
|
9079
9267
|
const scan = this.liveScanEdits(c.rawId);
|
|
@@ -9160,12 +9348,12 @@ var init_claude2 = __esm({
|
|
|
9160
9348
|
|
|
9161
9349
|
// ../engine/dist/core/backends/gemini.js
|
|
9162
9350
|
import { createHash as createHash4 } from "crypto";
|
|
9163
|
-
import { existsSync as existsSync11, readdirSync as readdirSync7, readFileSync as
|
|
9351
|
+
import { existsSync as existsSync11, readdirSync as readdirSync7, readFileSync as readFileSync6, statSync as statSync9 } from "fs";
|
|
9164
9352
|
import { basename as basename9, join as join11 } from "path";
|
|
9165
9353
|
function readSessionId(path, format) {
|
|
9166
9354
|
try {
|
|
9167
9355
|
if (format === "json") {
|
|
9168
|
-
const json = JSON.parse(
|
|
9356
|
+
const json = JSON.parse(readFileSync6(path, "utf-8"));
|
|
9169
9357
|
return typeof json?.sessionId === "string" ? json.sessionId : null;
|
|
9170
9358
|
}
|
|
9171
9359
|
const head = readHeadSync(path).split("\n", 1)[0] || "";
|
|
@@ -9199,6 +9387,7 @@ var init_gemini2 = __esm({
|
|
|
9199
9387
|
init_session_git();
|
|
9200
9388
|
init_generic_engine();
|
|
9201
9389
|
init_tail_read();
|
|
9390
|
+
init_flat_string();
|
|
9202
9391
|
PREFIX = "gemini_";
|
|
9203
9392
|
FULL_PARSE_MAX = 4 * 1024 * 1024;
|
|
9204
9393
|
GeminiBackend = class {
|
|
@@ -9308,7 +9497,7 @@ var init_gemini2 = __esm({
|
|
|
9308
9497
|
sessionId = readSessionId(fullPath, format);
|
|
9309
9498
|
const messages = readGeminiMessages(fullPath, format);
|
|
9310
9499
|
const firstUser = messages.find((m) => m.type === "user");
|
|
9311
|
-
firstPrompt = (typeof firstUser?.text === "string" ? firstUser.text : flatten(firstUser?.content)).slice(0, 200);
|
|
9500
|
+
firstPrompt = flatString((typeof firstUser?.text === "string" ? firstUser.text : flatten(firstUser?.content)).slice(0, 200));
|
|
9312
9501
|
messageCount = messages.length;
|
|
9313
9502
|
} else if (format === "jsonl") {
|
|
9314
9503
|
const lines = readHeadSync(fullPath, 1048576).split("\n");
|
|
@@ -9330,7 +9519,7 @@ var init_gemini2 = __esm({
|
|
|
9330
9519
|
}
|
|
9331
9520
|
if (m?.type !== "user")
|
|
9332
9521
|
continue;
|
|
9333
|
-
firstPrompt = (typeof m.text === "string" ? m.text : flatten(m.content)).slice(0, 200);
|
|
9522
|
+
firstPrompt = flatString((typeof m.text === "string" ? m.text : flatten(m.content)).slice(0, 200));
|
|
9334
9523
|
break;
|
|
9335
9524
|
}
|
|
9336
9525
|
}
|
|
@@ -9506,7 +9695,7 @@ var init_gemini2 = __esm({
|
|
|
9506
9695
|
if (!existsSync11(tmpRoot))
|
|
9507
9696
|
return [];
|
|
9508
9697
|
const projMap = this.loadProjectMap();
|
|
9509
|
-
const
|
|
9698
|
+
const candidates2 = [];
|
|
9510
9699
|
for (const proj of readdirSync7(tmpRoot, { withFileTypes: true })) {
|
|
9511
9700
|
if (!proj.isDirectory())
|
|
9512
9701
|
continue;
|
|
@@ -9537,13 +9726,13 @@ var init_gemini2 = __esm({
|
|
|
9537
9726
|
if (st.mtimeMs < opts.sinceMs)
|
|
9538
9727
|
continue;
|
|
9539
9728
|
const trimLen = isJsonl ? 6 : 5;
|
|
9540
|
-
|
|
9729
|
+
candidates2.push({ rawIdHint: f.slice(0, -trimLen), mtime: st.mtimeMs });
|
|
9541
9730
|
} catch {
|
|
9542
9731
|
}
|
|
9543
9732
|
}
|
|
9544
9733
|
}
|
|
9545
|
-
|
|
9546
|
-
const limited = opts.limitSessions ?
|
|
9734
|
+
candidates2.sort((a, b) => b.mtime - a.mtime);
|
|
9735
|
+
const limited = opts.limitSessions ? candidates2.slice(0, opts.limitSessions) : candidates2;
|
|
9547
9736
|
const edits = [];
|
|
9548
9737
|
for (const c of limited) {
|
|
9549
9738
|
const scan = this.liveScanEdits(c.rawIdHint);
|
|
@@ -9562,7 +9751,7 @@ var init_gemini2 = __esm({
|
|
|
9562
9751
|
if (!existsSync11(path))
|
|
9563
9752
|
return map;
|
|
9564
9753
|
try {
|
|
9565
|
-
const json = JSON.parse(
|
|
9754
|
+
const json = JSON.parse(readFileSync6(path, "utf-8"));
|
|
9566
9755
|
const projects = json?.projects ?? {};
|
|
9567
9756
|
for (const projectPath of Object.keys(projects)) {
|
|
9568
9757
|
const hash = createHash4("sha256").update(projectPath).digest("hex");
|
|
@@ -9580,7 +9769,7 @@ var init_gemini2 = __esm({
|
|
|
9580
9769
|
return {
|
|
9581
9770
|
tool: "gemini",
|
|
9582
9771
|
mtime: statSync9(loc.path).mtimeMs,
|
|
9583
|
-
files: [{ name: basename9(loc.path), bytes:
|
|
9772
|
+
files: [{ name: basename9(loc.path), bytes: readFileSync6(loc.path) }]
|
|
9584
9773
|
};
|
|
9585
9774
|
} catch {
|
|
9586
9775
|
return null;
|
|
@@ -9675,6 +9864,7 @@ var init_opencode = __esm({
|
|
|
9675
9864
|
init_session_outcome();
|
|
9676
9865
|
init_session_git();
|
|
9677
9866
|
init_generic_engine();
|
|
9867
|
+
init_flat_string();
|
|
9678
9868
|
PREFIX2 = "opencode_";
|
|
9679
9869
|
OpencodeBackend = class {
|
|
9680
9870
|
id = "opencode";
|
|
@@ -9842,7 +10032,7 @@ var init_opencode = __esm({
|
|
|
9842
10032
|
if (firstUser) {
|
|
9843
10033
|
try {
|
|
9844
10034
|
const parsed = JSON.parse(firstUser.data);
|
|
9845
|
-
firstPrompt = String(parsed?.text || "").slice(0, 200);
|
|
10035
|
+
firstPrompt = flatString(String(parsed?.text || "").slice(0, 200));
|
|
9846
10036
|
} catch {
|
|
9847
10037
|
}
|
|
9848
10038
|
}
|
|
@@ -10186,7 +10376,7 @@ var init_opencode = __esm({
|
|
|
10186
10376
|
});
|
|
10187
10377
|
|
|
10188
10378
|
// ../engine/dist/core/backends/codex.js
|
|
10189
|
-
import { readdirSync as readdirSync8, readFileSync as
|
|
10379
|
+
import { readdirSync as readdirSync8, readFileSync as readFileSync7, statSync as statSync10, openSync as openSync6, readSync as readSync6, closeSync as closeSync6 } from "fs";
|
|
10190
10380
|
import { basename as basename10, dirname as dirname10, join as join13 } from "path";
|
|
10191
10381
|
function parseShellWrites(cmd) {
|
|
10192
10382
|
const out = [];
|
|
@@ -10315,7 +10505,7 @@ function flattenContent(content) {
|
|
|
10315
10505
|
}
|
|
10316
10506
|
function readFirstLine(path) {
|
|
10317
10507
|
try {
|
|
10318
|
-
const head =
|
|
10508
|
+
const head = readFileSync7(path, "utf-8").split("\n", 1)[0] || "";
|
|
10319
10509
|
if (!head)
|
|
10320
10510
|
return null;
|
|
10321
10511
|
return JSON.parse(head);
|
|
@@ -10333,6 +10523,7 @@ var init_codex2 = __esm({
|
|
|
10333
10523
|
init_session_git();
|
|
10334
10524
|
init_generic_engine();
|
|
10335
10525
|
init_tail_read();
|
|
10526
|
+
init_flat_string();
|
|
10336
10527
|
PREFIX3 = "codex_";
|
|
10337
10528
|
CodexBackend = class {
|
|
10338
10529
|
id = "codex";
|
|
@@ -10432,7 +10623,7 @@ var init_codex2 = __esm({
|
|
|
10432
10623
|
let firstPrompt = "";
|
|
10433
10624
|
let messageCount = 0;
|
|
10434
10625
|
try {
|
|
10435
|
-
const lines =
|
|
10626
|
+
const lines = readFileSync7(filePath, "utf-8").split("\n");
|
|
10436
10627
|
for (const line of lines) {
|
|
10437
10628
|
if (!line.trim())
|
|
10438
10629
|
continue;
|
|
@@ -10445,7 +10636,7 @@ var init_codex2 = __esm({
|
|
|
10445
10636
|
if (ev.type === "event_msg" && ev.payload?.type === "user_message") {
|
|
10446
10637
|
messageCount++;
|
|
10447
10638
|
if (!firstPrompt && ev.payload.message) {
|
|
10448
|
-
firstPrompt = String(ev.payload.message).slice(0, 200);
|
|
10639
|
+
firstPrompt = flatString(String(ev.payload.message).slice(0, 200));
|
|
10449
10640
|
}
|
|
10450
10641
|
} else if (ev.type === "response_item" && ev.payload?.type === "message") {
|
|
10451
10642
|
messageCount++;
|
|
@@ -10584,7 +10775,7 @@ var init_codex2 = __esm({
|
|
|
10584
10775
|
continue;
|
|
10585
10776
|
let firstLine = "";
|
|
10586
10777
|
try {
|
|
10587
|
-
firstLine =
|
|
10778
|
+
firstLine = readFileSync7(path, "utf-8").split("\n", 1)[0] || "";
|
|
10588
10779
|
} catch {
|
|
10589
10780
|
continue;
|
|
10590
10781
|
}
|
|
@@ -10608,7 +10799,7 @@ var init_codex2 = __esm({
|
|
|
10608
10799
|
let raw = "";
|
|
10609
10800
|
let mtime = 0;
|
|
10610
10801
|
try {
|
|
10611
|
-
raw =
|
|
10802
|
+
raw = readFileSync7(path, "utf-8");
|
|
10612
10803
|
mtime = statSync10(path).mtimeMs;
|
|
10613
10804
|
} catch {
|
|
10614
10805
|
return [];
|
|
@@ -10785,7 +10976,7 @@ var init_codex2 = __esm({
|
|
|
10785
10976
|
let parentId = null;
|
|
10786
10977
|
let isSubagent = false;
|
|
10787
10978
|
try {
|
|
10788
|
-
const first =
|
|
10979
|
+
const first = readFileSync7(p, "utf-8").split("\n")[0];
|
|
10789
10980
|
if (first) {
|
|
10790
10981
|
const meta = JSON.parse(first);
|
|
10791
10982
|
const payload = meta?.payload || {};
|
|
@@ -10841,7 +11032,7 @@ var init_codex2 = __esm({
|
|
|
10841
11032
|
const push = (path, name) => {
|
|
10842
11033
|
try {
|
|
10843
11034
|
const st = statSync10(path);
|
|
10844
|
-
files.push({ name, bytes:
|
|
11035
|
+
files.push({ name, bytes: readFileSync7(path) });
|
|
10845
11036
|
if (st.mtimeMs > mtime)
|
|
10846
11037
|
mtime = st.mtimeMs;
|
|
10847
11038
|
} catch {
|
|
@@ -10859,10 +11050,10 @@ var init_codex2 = __esm({
|
|
|
10859
11050
|
if (p === loc.path)
|
|
10860
11051
|
continue;
|
|
10861
11052
|
try {
|
|
10862
|
-
const fd =
|
|
11053
|
+
const fd = openSync6(p, "r");
|
|
10863
11054
|
const buf = Buffer.alloc(4096);
|
|
10864
|
-
const n =
|
|
10865
|
-
|
|
11055
|
+
const n = readSync6(fd, buf, 0, 4096, 0);
|
|
11056
|
+
closeSync6(fd);
|
|
10866
11057
|
const head = buf.toString("utf-8", 0, n);
|
|
10867
11058
|
if (head.includes(parentId) && head.includes("parent_thread_id"))
|
|
10868
11059
|
push(p, `subagents/${f}`);
|
|
@@ -10899,13 +11090,13 @@ var init_codex2 = __esm({
|
|
|
10899
11090
|
});
|
|
10900
11091
|
|
|
10901
11092
|
// ../engine/dist/core/backends/agy.js
|
|
10902
|
-
import { existsSync as existsSync13, readdirSync as readdirSync9, readFileSync as
|
|
11093
|
+
import { existsSync as existsSync13, readdirSync as readdirSync9, readFileSync as readFileSync8, statSync as statSync11 } from "fs";
|
|
10903
11094
|
import { basename as basename11, dirname as dirname11, join as join14 } from "path";
|
|
10904
11095
|
function getFallbackProjectPath(homeDir) {
|
|
10905
11096
|
try {
|
|
10906
11097
|
const settingsPath2 = join14(homeDir, "settings.json");
|
|
10907
11098
|
if (existsSync13(settingsPath2)) {
|
|
10908
|
-
const json = JSON.parse(
|
|
11099
|
+
const json = JSON.parse(readFileSync8(settingsPath2, "utf-8"));
|
|
10909
11100
|
if (Array.isArray(json?.trustedWorkspaces) && json.trustedWorkspaces[0]) {
|
|
10910
11101
|
return json.trustedWorkspaces[0];
|
|
10911
11102
|
}
|
|
@@ -10932,7 +11123,7 @@ function resolveAgyProject(logsDir, homeDir) {
|
|
|
10932
11123
|
function extractProjectPathFromTranscript(path, homeDir) {
|
|
10933
11124
|
let content;
|
|
10934
11125
|
try {
|
|
10935
|
-
content =
|
|
11126
|
+
content = readFileSync8(path, "utf-8");
|
|
10936
11127
|
} catch {
|
|
10937
11128
|
return "";
|
|
10938
11129
|
}
|
|
@@ -11018,6 +11209,7 @@ var init_agy = __esm({
|
|
|
11018
11209
|
init_session_outcome();
|
|
11019
11210
|
init_session_git();
|
|
11020
11211
|
init_generic_engine();
|
|
11212
|
+
init_flat_string();
|
|
11021
11213
|
PREFIX4 = "agy_";
|
|
11022
11214
|
AgyBackend = class {
|
|
11023
11215
|
id = "agy";
|
|
@@ -11110,7 +11302,7 @@ var init_agy = __esm({
|
|
|
11110
11302
|
let firstPrompt = "";
|
|
11111
11303
|
let messageCount = 0;
|
|
11112
11304
|
try {
|
|
11113
|
-
const lines =
|
|
11305
|
+
const lines = readFileSync8(filePath, "utf-8").split("\n").filter(Boolean);
|
|
11114
11306
|
messageCount = lines.length;
|
|
11115
11307
|
for (const line of lines) {
|
|
11116
11308
|
const obj = JSON.parse(line);
|
|
@@ -11118,7 +11310,7 @@ var init_agy = __esm({
|
|
|
11118
11310
|
const content = obj.content;
|
|
11119
11311
|
const match = content.match(/<USER_REQUEST>([\s\S]*?)<\/USER_REQUEST>/);
|
|
11120
11312
|
const rawText = match ? match[1].trim() : content.trim();
|
|
11121
|
-
firstPrompt = rawText.slice(0, 200);
|
|
11313
|
+
firstPrompt = flatString(rawText.slice(0, 200));
|
|
11122
11314
|
break;
|
|
11123
11315
|
}
|
|
11124
11316
|
}
|
|
@@ -11200,7 +11392,7 @@ var init_agy = __esm({
|
|
|
11200
11392
|
return [];
|
|
11201
11393
|
let rawText;
|
|
11202
11394
|
try {
|
|
11203
|
-
rawText =
|
|
11395
|
+
rawText = readFileSync8(located.path, "utf-8");
|
|
11204
11396
|
} catch {
|
|
11205
11397
|
return [];
|
|
11206
11398
|
}
|
|
@@ -11352,7 +11544,7 @@ var init_agy = __esm({
|
|
|
11352
11544
|
if (brainRoots.length === 0)
|
|
11353
11545
|
return [];
|
|
11354
11546
|
const brainDir = brainRoots[0];
|
|
11355
|
-
const
|
|
11547
|
+
const candidates2 = [];
|
|
11356
11548
|
let sessionDirs;
|
|
11357
11549
|
try {
|
|
11358
11550
|
sessionDirs = readdirSync9(brainDir);
|
|
@@ -11374,12 +11566,12 @@ var init_agy = __esm({
|
|
|
11374
11566
|
const st = statSync11(filePath);
|
|
11375
11567
|
if (st.mtimeMs < opts.sinceMs)
|
|
11376
11568
|
continue;
|
|
11377
|
-
|
|
11569
|
+
candidates2.push({ rawId, mtime: st.mtimeMs });
|
|
11378
11570
|
} catch {
|
|
11379
11571
|
}
|
|
11380
11572
|
}
|
|
11381
|
-
|
|
11382
|
-
const limited = opts.limitSessions ?
|
|
11573
|
+
candidates2.sort((a, b) => b.mtime - a.mtime);
|
|
11574
|
+
const limited = opts.limitSessions ? candidates2.slice(0, opts.limitSessions) : candidates2;
|
|
11383
11575
|
const edits = [];
|
|
11384
11576
|
for (const c of limited) {
|
|
11385
11577
|
const scan = this.liveScanEdits(c.rawId);
|
|
@@ -11400,7 +11592,7 @@ var init_agy = __esm({
|
|
|
11400
11592
|
return {
|
|
11401
11593
|
tool: "agy",
|
|
11402
11594
|
mtime: statSync11(loc.path).mtimeMs,
|
|
11403
|
-
files: [{ name: basename11(loc.path), bytes:
|
|
11595
|
+
files: [{ name: basename11(loc.path), bytes: readFileSync8(loc.path) }]
|
|
11404
11596
|
};
|
|
11405
11597
|
} catch {
|
|
11406
11598
|
return null;
|
|
@@ -11472,6 +11664,24 @@ var init_backends = __esm({
|
|
|
11472
11664
|
}
|
|
11473
11665
|
});
|
|
11474
11666
|
|
|
11667
|
+
// ../engine/dist/core/credentials-env.js
|
|
11668
|
+
function envCredentials(env = process.env) {
|
|
11669
|
+
const token = (env.CHAT_RECALL_TOKEN || "").trim();
|
|
11670
|
+
const server = (env.CHAT_RECALL_SERVER || "").trim();
|
|
11671
|
+
if (!token || !server)
|
|
11672
|
+
return null;
|
|
11673
|
+
if (!/^https?:\/\//i.test(server))
|
|
11674
|
+
return null;
|
|
11675
|
+
return { serverUrl: normalise(server), token };
|
|
11676
|
+
}
|
|
11677
|
+
var normalise;
|
|
11678
|
+
var init_credentials_env = __esm({
|
|
11679
|
+
"../engine/dist/core/credentials-env.js"() {
|
|
11680
|
+
"use strict";
|
|
11681
|
+
normalise = (u) => u.trim().replace(/\/+$/, "");
|
|
11682
|
+
}
|
|
11683
|
+
});
|
|
11684
|
+
|
|
11475
11685
|
// ../engine/dist/core/source-discovery.js
|
|
11476
11686
|
import { createHash as createHash5 } from "crypto";
|
|
11477
11687
|
import { existsSync as existsSync14, readdirSync as readdirSync10, statSync as statSync12 } from "fs";
|
|
@@ -11578,7 +11788,7 @@ var init_source_discovery = __esm({
|
|
|
11578
11788
|
|
|
11579
11789
|
// ../engine/dist/core/home-discovery.js
|
|
11580
11790
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
11581
|
-
import { existsSync as existsSync15, readdirSync as readdirSync11, readFileSync as
|
|
11791
|
+
import { existsSync as existsSync15, readdirSync as readdirSync11, readFileSync as readFileSync9, realpathSync as realpathSync2, statSync as statSync13 } from "fs";
|
|
11582
11792
|
import { homedir as homedir5, platform as osPlatform } from "os";
|
|
11583
11793
|
import { join as join16 } from "path";
|
|
11584
11794
|
function candidateRoots(plat = osPlatform(), env = process.env) {
|
|
@@ -11700,7 +11910,7 @@ function declaredHomes(env = process.env, plat = osPlatform()) {
|
|
|
11700
11910
|
for (const rc of rcs) {
|
|
11701
11911
|
let text;
|
|
11702
11912
|
try {
|
|
11703
|
-
text =
|
|
11913
|
+
text = readFileSync9(rc, "utf-8");
|
|
11704
11914
|
} catch {
|
|
11705
11915
|
continue;
|
|
11706
11916
|
}
|
|
@@ -11725,7 +11935,7 @@ function runningToolHomes(plat = osPlatform()) {
|
|
|
11725
11935
|
for (const pid of pids) {
|
|
11726
11936
|
let env;
|
|
11727
11937
|
try {
|
|
11728
|
-
env =
|
|
11938
|
+
env = readFileSync9(`/proc/${pid}/environ`, "utf-8");
|
|
11729
11939
|
} catch {
|
|
11730
11940
|
continue;
|
|
11731
11941
|
}
|
|
@@ -11846,7 +12056,7 @@ var init_home_discovery = __esm({
|
|
|
11846
12056
|
|
|
11847
12057
|
// ../engine/dist/core/detector-install.js
|
|
11848
12058
|
import { createHash as createHash6 } from "crypto";
|
|
11849
|
-
import { existsSync as existsSync16, mkdirSync as mkdirSync4, mkdtempSync, chmodSync as chmodSync2, renameSync as renameSync3, rmSync as rmSync2, writeFileSync as writeFileSync3, readFileSync as
|
|
12059
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync4, mkdtempSync, chmodSync as chmodSync2, renameSync as renameSync3, rmSync as rmSync2, writeFileSync as writeFileSync3, readFileSync as readFileSync10, statSync as statSync14, copyFileSync as copyFileSync2 } from "fs";
|
|
11850
12060
|
import { join as join17 } from "path";
|
|
11851
12061
|
function managedDetectorPath(name) {
|
|
11852
12062
|
return join17(getDetectorBinDir(), name + exeSuffix());
|
|
@@ -11855,11 +12065,11 @@ function receiptPath(name) {
|
|
|
11855
12065
|
return join17(getDetectorBinDir(), `${name}.receipt.json`);
|
|
11856
12066
|
}
|
|
11857
12067
|
function sha256File(path) {
|
|
11858
|
-
return createHash6("sha256").update(
|
|
12068
|
+
return createHash6("sha256").update(readFileSync10(path)).digest("hex");
|
|
11859
12069
|
}
|
|
11860
12070
|
function readReceipt(name) {
|
|
11861
12071
|
try {
|
|
11862
|
-
return JSON.parse(
|
|
12072
|
+
return JSON.parse(readFileSync10(receiptPath(name), "utf-8"));
|
|
11863
12073
|
} catch {
|
|
11864
12074
|
return null;
|
|
11865
12075
|
}
|
|
@@ -11950,7 +12160,7 @@ var init_detector_install = __esm({
|
|
|
11950
12160
|
|
|
11951
12161
|
// ../engine/dist/core/secret-scanner.js
|
|
11952
12162
|
import { spawnSync } from "child_process";
|
|
11953
|
-
import { existsSync as existsSync17, unlinkSync, readFileSync as
|
|
12163
|
+
import { existsSync as existsSync17, unlinkSync, readFileSync as readFileSync11, mkdtempSync as mkdtempSync2, rmSync as rmSync3 } from "fs";
|
|
11954
12164
|
import { tmpdir } from "os";
|
|
11955
12165
|
import { join as join18 } from "path";
|
|
11956
12166
|
function mask(s) {
|
|
@@ -12011,7 +12221,7 @@ function runGitleaks(binary, filePath) {
|
|
|
12011
12221
|
return [];
|
|
12012
12222
|
let parsed = [];
|
|
12013
12223
|
try {
|
|
12014
|
-
parsed = JSON.parse(
|
|
12224
|
+
parsed = JSON.parse(readFileSync11(reportPath, "utf-8")) || [];
|
|
12015
12225
|
} catch {
|
|
12016
12226
|
}
|
|
12017
12227
|
try {
|
|
@@ -12075,7 +12285,7 @@ function runGitleaksDir(binary, dir) {
|
|
|
12075
12285
|
}
|
|
12076
12286
|
let parsed = [];
|
|
12077
12287
|
try {
|
|
12078
|
-
parsed = JSON.parse(
|
|
12288
|
+
parsed = JSON.parse(readFileSync11(reportPath, "utf-8")) || [];
|
|
12079
12289
|
} catch {
|
|
12080
12290
|
}
|
|
12081
12291
|
try {
|
|
@@ -12166,7 +12376,7 @@ function scanFileForSecrets(filePath, opts = {}) {
|
|
|
12166
12376
|
out.push({ detector: "trufflehog", ...f });
|
|
12167
12377
|
if (opts.tenantRules && opts.tenantRules.length > 0) {
|
|
12168
12378
|
try {
|
|
12169
|
-
const text =
|
|
12379
|
+
const text = readFileSync11(filePath, "utf-8");
|
|
12170
12380
|
out.push(...scanTenantRules(text, opts.tenantRules));
|
|
12171
12381
|
} catch {
|
|
12172
12382
|
}
|
|
@@ -12291,10 +12501,10 @@ var init_types = __esm({
|
|
|
12291
12501
|
|
|
12292
12502
|
// ../engine/dist/transcript/opencode.js
|
|
12293
12503
|
async function parseOpenCodeSubagents(parentSessionId) {
|
|
12294
|
-
const { existsSync:
|
|
12504
|
+
const { existsSync: existsSync46 } = await import("fs");
|
|
12295
12505
|
const { opencodeBackend: opencodeBackend2 } = await Promise.resolve().then(() => (init_opencode(), opencode_exports));
|
|
12296
12506
|
const dbPath = opencodeBackend2.dbPath();
|
|
12297
|
-
if (!
|
|
12507
|
+
if (!existsSync46(dbPath))
|
|
12298
12508
|
return [];
|
|
12299
12509
|
const realParent = parentSessionId.replace("opencode_", "");
|
|
12300
12510
|
const db = openSqliteReadonlyOrThrow(dbPath);
|
|
@@ -12335,10 +12545,10 @@ async function parseOpenCodeSubagents(parentSessionId) {
|
|
|
12335
12545
|
}
|
|
12336
12546
|
}
|
|
12337
12547
|
async function parseOpenCodeTranscript(sessionId) {
|
|
12338
|
-
const { existsSync:
|
|
12548
|
+
const { existsSync: existsSync46 } = await import("fs");
|
|
12339
12549
|
const { opencodeBackend: opencodeBackend2 } = await Promise.resolve().then(() => (init_opencode(), opencode_exports));
|
|
12340
12550
|
const dbPath = opencodeBackend2.dbPath();
|
|
12341
|
-
if (!
|
|
12551
|
+
if (!existsSync46(dbPath))
|
|
12342
12552
|
return [];
|
|
12343
12553
|
const realId = sessionId.replace("opencode_", "");
|
|
12344
12554
|
const db = openSqliteReadonlyOrThrow(dbPath);
|
|
@@ -12572,7 +12782,7 @@ var init_transcript = __esm({
|
|
|
12572
12782
|
// ../engine/dist/core/project-resolver.js
|
|
12573
12783
|
import { execSync } from "child_process";
|
|
12574
12784
|
import { createHash as createHash7 } from "crypto";
|
|
12575
|
-
import { existsSync as existsSync18, readFileSync as
|
|
12785
|
+
import { existsSync as existsSync18, readFileSync as readFileSync12, realpathSync as realpathSync3, readdirSync as readdirSync12, statSync as statSync16 } from "fs";
|
|
12576
12786
|
import { basename as basename12, dirname as dirname12, isAbsolute, join as join19, resolve, sep } from "path";
|
|
12577
12787
|
function getProjectsConfigPath() {
|
|
12578
12788
|
return join19(getDataDir(), "projects.json");
|
|
@@ -12590,7 +12800,7 @@ function loadProjectsConfig() {
|
|
|
12590
12800
|
if (cachedConfig && cachedConfig.mtime === mtime)
|
|
12591
12801
|
return cachedConfig.cfg;
|
|
12592
12802
|
try {
|
|
12593
|
-
const raw =
|
|
12803
|
+
const raw = readFileSync12(path, "utf-8");
|
|
12594
12804
|
const cfg = JSON.parse(raw);
|
|
12595
12805
|
cachedConfig = { mtime, cfg };
|
|
12596
12806
|
return cfg;
|
|
@@ -12658,8 +12868,8 @@ function resolveBotWorktree(realPath) {
|
|
|
12658
12868
|
};
|
|
12659
12869
|
}
|
|
12660
12870
|
function matchDeclaredProject(realPath, projects) {
|
|
12661
|
-
const
|
|
12662
|
-
for (const proj of
|
|
12871
|
+
const candidates2 = [...projects].sort((a, b) => b.root.length - a.root.length);
|
|
12872
|
+
for (const proj of candidates2) {
|
|
12663
12873
|
const root = safeRealpath(proj.root);
|
|
12664
12874
|
if (!isInside(realPath, root))
|
|
12665
12875
|
continue;
|
|
@@ -13693,7 +13903,7 @@ var init_utils = __esm({
|
|
|
13693
13903
|
});
|
|
13694
13904
|
|
|
13695
13905
|
// ../engine/dist/parsers/plan-source.js
|
|
13696
|
-
import { existsSync as existsSync20, readdirSync as readdirSync14, readFileSync as
|
|
13906
|
+
import { existsSync as existsSync20, readdirSync as readdirSync14, readFileSync as readFileSync13, statSync as statSync18 } from "fs";
|
|
13697
13907
|
import { homedir as homedir7 } from "os";
|
|
13698
13908
|
import { join as join21, basename as basename13 } from "path";
|
|
13699
13909
|
import { createHash as createHash8 } from "crypto";
|
|
@@ -13735,6 +13945,7 @@ var init_plan_source = __esm({
|
|
|
13735
13945
|
init_claude2();
|
|
13736
13946
|
init_agy();
|
|
13737
13947
|
init_settings();
|
|
13948
|
+
init_project_dir_name();
|
|
13738
13949
|
MAX_CHUNK_CHARS = 2e3;
|
|
13739
13950
|
UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
13740
13951
|
PlanSource = class {
|
|
@@ -13759,7 +13970,7 @@ var init_plan_source = __esm({
|
|
|
13759
13970
|
for (const entry of entries) {
|
|
13760
13971
|
if (!entry.isDirectory() || entry.name.startsWith("."))
|
|
13761
13972
|
continue;
|
|
13762
|
-
const projectPath = entry.name
|
|
13973
|
+
const projectPath = decodeProjectDirName(entry.name);
|
|
13763
13974
|
if (existsSync20(projectPath)) {
|
|
13764
13975
|
this._knownProjectDirs.push(projectPath);
|
|
13765
13976
|
}
|
|
@@ -13797,7 +14008,7 @@ var init_plan_source = __esm({
|
|
|
13797
14008
|
const stat3 = statSync18(filePath);
|
|
13798
14009
|
const planName = basename13(file, ".md");
|
|
13799
14010
|
const isAgentPlan = planName.includes("-agent-");
|
|
13800
|
-
const content =
|
|
14011
|
+
const content = readFileSync13(filePath, "utf-8");
|
|
13801
14012
|
const fm = parseFrontmatter(content);
|
|
13802
14013
|
const body = fm.body;
|
|
13803
14014
|
const firstLine = body.split("\n").find((l) => l.trim())?.replace(/^#+\s*/, "").trim() || planName;
|
|
@@ -13839,7 +14050,7 @@ var init_plan_source = __esm({
|
|
|
13839
14050
|
const filePath = join21(plansDir, file);
|
|
13840
14051
|
try {
|
|
13841
14052
|
const stat3 = statSync18(filePath);
|
|
13842
|
-
const content =
|
|
14053
|
+
const content = readFileSync13(filePath, "utf-8");
|
|
13843
14054
|
const firstLine = content.split("\n").find((l) => l.trim())?.replace(/^#+\s*/, "").trim() || file;
|
|
13844
14055
|
const planName = `${opencodeBackend.idPrefix}plan_${basename13(file, ".md")}`;
|
|
13845
14056
|
const projectPath = this.extractProjectPath(content);
|
|
@@ -13869,7 +14080,7 @@ var init_plan_source = __esm({
|
|
|
13869
14080
|
const projectsPath = geminiBackend.projectsJson();
|
|
13870
14081
|
if (existsSync20(projectsPath)) {
|
|
13871
14082
|
try {
|
|
13872
|
-
const data = JSON.parse(
|
|
14083
|
+
const data = JSON.parse(readFileSync13(projectsPath, "utf-8"));
|
|
13873
14084
|
for (const path of Object.keys(data.projects || {})) {
|
|
13874
14085
|
projMap.set(createHash8("sha256").update(path).digest("hex"), path);
|
|
13875
14086
|
}
|
|
@@ -13905,7 +14116,7 @@ var init_plan_source = __esm({
|
|
|
13905
14116
|
const filePath = join21(plansDir, file);
|
|
13906
14117
|
try {
|
|
13907
14118
|
const stat3 = statSync18(filePath);
|
|
13908
|
-
const content =
|
|
14119
|
+
const content = readFileSync13(filePath, "utf-8");
|
|
13909
14120
|
const firstLine = content.split("\n").find((l) => l.trim())?.replace(/^#+\s*/, "").trim() || file;
|
|
13910
14121
|
const planName = `${geminiBackend.idPrefix}plan_${sess}_${basename13(file, ".md")}`;
|
|
13911
14122
|
yield {
|
|
@@ -13984,7 +14195,7 @@ var init_plan_source = __esm({
|
|
|
13984
14195
|
async parse(item) {
|
|
13985
14196
|
if (!existsSync20(item.filePath))
|
|
13986
14197
|
return [];
|
|
13987
|
-
const content =
|
|
14198
|
+
const content = readFileSync13(item.filePath, "utf-8");
|
|
13988
14199
|
const chunks = [];
|
|
13989
14200
|
const { body } = parseFrontmatter(content);
|
|
13990
14201
|
const sections = splitByHeaders(body);
|
|
@@ -14128,7 +14339,7 @@ var init_plan_source = __esm({
|
|
|
14128
14339
|
const filePath = join21(sessionPath, file);
|
|
14129
14340
|
try {
|
|
14130
14341
|
const stat3 = statSync18(filePath);
|
|
14131
|
-
const content =
|
|
14342
|
+
const content = readFileSync13(filePath, "utf-8");
|
|
14132
14343
|
const firstLine = content.split("\n").find((l) => l.trim())?.replace(/^#+\s*/, "").trim() || file;
|
|
14133
14344
|
const sessionLoc = agyBackend.findSession(rawId);
|
|
14134
14345
|
const projectPath = sessionLoc?.projectPath || this.extractProjectPath(content);
|
|
@@ -14157,7 +14368,7 @@ var init_plan_source = __esm({
|
|
|
14157
14368
|
});
|
|
14158
14369
|
|
|
14159
14370
|
// ../engine/dist/parsers/task-source.js
|
|
14160
|
-
import { existsSync as existsSync21, readdirSync as readdirSync15, readFileSync as
|
|
14371
|
+
import { existsSync as existsSync21, readdirSync as readdirSync15, readFileSync as readFileSync14, statSync as statSync19 } from "fs";
|
|
14161
14372
|
import { join as join22 } from "path";
|
|
14162
14373
|
var MAX_CHUNK_CHARS2, TaskSource;
|
|
14163
14374
|
var init_task_source = __esm({
|
|
@@ -14207,7 +14418,7 @@ var init_task_source = __esm({
|
|
|
14207
14418
|
continue;
|
|
14208
14419
|
let parsed;
|
|
14209
14420
|
try {
|
|
14210
|
-
const raw =
|
|
14421
|
+
const raw = readFileSync14(filePath, "utf-8");
|
|
14211
14422
|
parsed = JSON.parse(raw);
|
|
14212
14423
|
if (!Array.isArray(parsed) || parsed.length === 0)
|
|
14213
14424
|
continue;
|
|
@@ -14345,7 +14556,7 @@ ${task.description}`.slice(0, MAX_CHUNK_CHARS2);
|
|
|
14345
14556
|
return [];
|
|
14346
14557
|
let parsed;
|
|
14347
14558
|
try {
|
|
14348
|
-
parsed = JSON.parse(
|
|
14559
|
+
parsed = JSON.parse(readFileSync14(item.filePath, "utf-8"));
|
|
14349
14560
|
} catch {
|
|
14350
14561
|
return [];
|
|
14351
14562
|
}
|
|
@@ -14377,7 +14588,7 @@ ${task.description}`.slice(0, MAX_CHUNK_CHARS2);
|
|
|
14377
14588
|
});
|
|
14378
14589
|
for (const file of sorted) {
|
|
14379
14590
|
try {
|
|
14380
|
-
const content =
|
|
14591
|
+
const content = readFileSync14(join22(taskDir, file), "utf-8");
|
|
14381
14592
|
const task = JSON.parse(content);
|
|
14382
14593
|
if (task.subject) {
|
|
14383
14594
|
tasks.push(task);
|
|
@@ -14393,7 +14604,7 @@ ${task.description}`.slice(0, MAX_CHUNK_CHARS2);
|
|
|
14393
14604
|
});
|
|
14394
14605
|
|
|
14395
14606
|
// ../engine/dist/parsers/claude-md-source.js
|
|
14396
|
-
import { existsSync as existsSync22, readFileSync as
|
|
14607
|
+
import { existsSync as existsSync22, readFileSync as readFileSync15, readdirSync as readdirSync16, statSync as statSync20 } from "fs";
|
|
14397
14608
|
import { homedir as homedir8 } from "os";
|
|
14398
14609
|
import { join as join23, basename as basename14, dirname as dirname13 } from "path";
|
|
14399
14610
|
import { createHash as createHash9 } from "crypto";
|
|
@@ -14414,7 +14625,7 @@ function discoverProjectDirs(claudeDir) {
|
|
|
14414
14625
|
for (const entry of entries) {
|
|
14415
14626
|
if (!entry.isDirectory() || entry.name.startsWith("."))
|
|
14416
14627
|
continue;
|
|
14417
|
-
const projectPath = entry.name
|
|
14628
|
+
const projectPath = decodeProjectDirName(entry.name);
|
|
14418
14629
|
addProject(projectPath);
|
|
14419
14630
|
}
|
|
14420
14631
|
} catch {
|
|
@@ -14437,7 +14648,7 @@ function discoverProjectDirs(claudeDir) {
|
|
|
14437
14648
|
const gemProjects = geminiBackend.projectsJson();
|
|
14438
14649
|
if (existsSync22(gemProjects)) {
|
|
14439
14650
|
try {
|
|
14440
|
-
const data = JSON.parse(
|
|
14651
|
+
const data = JSON.parse(readFileSync15(gemProjects, "utf-8"));
|
|
14441
14652
|
for (const path of Object.keys(data.projects || {}))
|
|
14442
14653
|
addProject(path);
|
|
14443
14654
|
} catch {
|
|
@@ -14471,6 +14682,7 @@ var init_claude_md_source = __esm({
|
|
|
14471
14682
|
init_gemini2();
|
|
14472
14683
|
init_settings();
|
|
14473
14684
|
init_opencode();
|
|
14685
|
+
init_project_dir_name();
|
|
14474
14686
|
MAX_CHUNK_CHARS3 = 2e3;
|
|
14475
14687
|
NOTE_FILES = [
|
|
14476
14688
|
{ filename: "CLAUDE.md", tool: "claude" },
|
|
@@ -14551,7 +14763,7 @@ var init_claude_md_source = __esm({
|
|
|
14551
14763
|
async parse(item) {
|
|
14552
14764
|
if (!existsSync22(item.filePath))
|
|
14553
14765
|
return [];
|
|
14554
|
-
const content =
|
|
14766
|
+
const content = readFileSync15(item.filePath, "utf-8");
|
|
14555
14767
|
const chunks = [];
|
|
14556
14768
|
const sections = splitByHeaders(content);
|
|
14557
14769
|
for (let i = 0; i < sections.length; i++) {
|
|
@@ -14593,7 +14805,7 @@ var init_claude_md_source = __esm({
|
|
|
14593
14805
|
const projectDir = dirname13(filePath);
|
|
14594
14806
|
const projectName = basename14(projectDir);
|
|
14595
14807
|
const projectPath = projectDir;
|
|
14596
|
-
const content =
|
|
14808
|
+
const content = readFileSync15(filePath, "utf-8");
|
|
14597
14809
|
const firstLine = content.split("\n").find((l) => l.trim() && !l.startsWith("#"))?.trim()?.slice(0, 200) || `${filename} for ${projectName}`;
|
|
14598
14810
|
const id = tool === "claude" ? projectName : `${projectName}_${tool}`;
|
|
14599
14811
|
return {
|
|
@@ -14618,7 +14830,7 @@ var init_claude_md_source = __esm({
|
|
|
14618
14830
|
});
|
|
14619
14831
|
|
|
14620
14832
|
// ../engine/dist/parsers/agent-memory-source.js
|
|
14621
|
-
import { existsSync as existsSync23, readFileSync as
|
|
14833
|
+
import { existsSync as existsSync23, readFileSync as readFileSync16, readdirSync as readdirSync17, statSync as statSync21 } from "fs";
|
|
14622
14834
|
import { homedir as homedir9 } from "os";
|
|
14623
14835
|
import { join as join24, basename as basename15 } from "path";
|
|
14624
14836
|
function parseFrontmatter2(content) {
|
|
@@ -14646,7 +14858,7 @@ function parseFrontmatter2(content) {
|
|
|
14646
14858
|
return { fm, body };
|
|
14647
14859
|
}
|
|
14648
14860
|
function projectHashToPath(hashDir) {
|
|
14649
|
-
return hashDir
|
|
14861
|
+
return decodeProjectDirName(hashDir);
|
|
14650
14862
|
}
|
|
14651
14863
|
function discoverMemoryDirs() {
|
|
14652
14864
|
const out = [];
|
|
@@ -14688,6 +14900,7 @@ var init_agent_memory_source = __esm({
|
|
|
14688
14900
|
init_utils();
|
|
14689
14901
|
init_claude2();
|
|
14690
14902
|
init_settings();
|
|
14903
|
+
init_project_dir_name();
|
|
14691
14904
|
MAX_CHUNK_CHARS4 = 2e3;
|
|
14692
14905
|
MAX_CHUNKS = 12;
|
|
14693
14906
|
AgentMemorySource = class {
|
|
@@ -14718,7 +14931,7 @@ var init_agent_memory_source = __esm({
|
|
|
14718
14931
|
async parse(item) {
|
|
14719
14932
|
if (!existsSync23(item.filePath))
|
|
14720
14933
|
return [];
|
|
14721
|
-
const content =
|
|
14934
|
+
const content = readFileSync16(item.filePath, "utf-8");
|
|
14722
14935
|
const { body } = parseFrontmatter2(content);
|
|
14723
14936
|
const chunks = [];
|
|
14724
14937
|
const sections = splitByHeaders(body);
|
|
@@ -14771,7 +14984,7 @@ var init_agent_memory_source = __esm({
|
|
|
14771
14984
|
fileToItem(filePath, filename, projectPath, _projectHash) {
|
|
14772
14985
|
try {
|
|
14773
14986
|
const stat3 = statSync21(filePath);
|
|
14774
|
-
const content =
|
|
14987
|
+
const content = readFileSync16(filePath, "utf-8");
|
|
14775
14988
|
const { fm } = parseFrontmatter2(content);
|
|
14776
14989
|
const stem = filename.replace(/\.md$/, "");
|
|
14777
14990
|
const idBase = fm.name || stem;
|
|
@@ -14986,7 +15199,7 @@ var init_history_source = __esm({
|
|
|
14986
15199
|
});
|
|
14987
15200
|
|
|
14988
15201
|
// ../engine/dist/parsers/paste-source.js
|
|
14989
|
-
import { existsSync as existsSync25, readdirSync as readdirSync19, readFileSync as
|
|
15202
|
+
import { existsSync as existsSync25, readdirSync as readdirSync19, readFileSync as readFileSync17, statSync as statSync23 } from "fs";
|
|
14990
15203
|
import { homedir as homedir11 } from "os";
|
|
14991
15204
|
import { join as join26, basename as basename16 } from "path";
|
|
14992
15205
|
var MAX_CHUNK_CHARS6, MAX_FILE_SIZE, PasteSource;
|
|
@@ -15042,7 +15255,7 @@ var init_paste_source = __esm({
|
|
|
15042
15255
|
if (stat3.size < 10)
|
|
15043
15256
|
continue;
|
|
15044
15257
|
const hash = basename16(file, ".txt");
|
|
15045
|
-
const content =
|
|
15258
|
+
const content = readFileSync17(filePath, "utf-8");
|
|
15046
15259
|
const firstLine = content.split("\n").find((l) => l.trim().length > 5)?.trim()?.slice(0, 100) || `Paste ${hash.slice(0, 8)}`;
|
|
15047
15260
|
yield {
|
|
15048
15261
|
id: hash,
|
|
@@ -15063,7 +15276,7 @@ var init_paste_source = __esm({
|
|
|
15063
15276
|
async parse(item) {
|
|
15064
15277
|
if (!existsSync25(item.filePath))
|
|
15065
15278
|
return [];
|
|
15066
|
-
const content =
|
|
15279
|
+
const content = readFileSync17(item.filePath, "utf-8");
|
|
15067
15280
|
if (content.trim().length < 20)
|
|
15068
15281
|
return [];
|
|
15069
15282
|
return [{
|
|
@@ -15086,7 +15299,7 @@ var init_paste_source = __esm({
|
|
|
15086
15299
|
});
|
|
15087
15300
|
|
|
15088
15301
|
// ../engine/dist/parsers/gemini-source.js
|
|
15089
|
-
import { existsSync as existsSync26, readdirSync as readdirSync20, readFileSync as
|
|
15302
|
+
import { existsSync as existsSync26, readdirSync as readdirSync20, readFileSync as readFileSync18, statSync as statSync24 } from "fs";
|
|
15090
15303
|
import { join as join27, basename as basename17 } from "path";
|
|
15091
15304
|
import { createHash as createHash10 } from "crypto";
|
|
15092
15305
|
function loadGeminiProjectMap2() {
|
|
@@ -15095,7 +15308,7 @@ function loadGeminiProjectMap2() {
|
|
|
15095
15308
|
if (!existsSync26(projectsPath))
|
|
15096
15309
|
return map;
|
|
15097
15310
|
try {
|
|
15098
|
-
const data = JSON.parse(
|
|
15311
|
+
const data = JSON.parse(readFileSync18(projectsPath, "utf-8"));
|
|
15099
15312
|
const projects = data.projects || {};
|
|
15100
15313
|
for (const [path] of Object.entries(projects)) {
|
|
15101
15314
|
const hash = createHash10("sha256").update(path).digest("hex");
|
|
@@ -15140,7 +15353,7 @@ var init_gemini_source = __esm({
|
|
|
15140
15353
|
const filePath = join27(chatsDir, file);
|
|
15141
15354
|
try {
|
|
15142
15355
|
const stat3 = statSync24(filePath);
|
|
15143
|
-
const content = JSON.parse(
|
|
15356
|
+
const content = JSON.parse(readFileSync18(filePath, "utf-8"));
|
|
15144
15357
|
const sessionId = content.sessionId || basename17(file, ".json");
|
|
15145
15358
|
if (seen.has(sessionId))
|
|
15146
15359
|
continue;
|
|
@@ -15221,7 +15434,7 @@ var init_gemini_source = __esm({
|
|
|
15221
15434
|
async parse(item) {
|
|
15222
15435
|
if (!existsSync26(item.filePath))
|
|
15223
15436
|
return [];
|
|
15224
|
-
const content = JSON.parse(
|
|
15437
|
+
const content = JSON.parse(readFileSync18(item.filePath, "utf-8"));
|
|
15225
15438
|
const messages = content.messages || [];
|
|
15226
15439
|
const chunks = [];
|
|
15227
15440
|
const getText = (m) => {
|
|
@@ -15269,7 +15482,7 @@ var init_gemini_source = __esm({
|
|
|
15269
15482
|
});
|
|
15270
15483
|
|
|
15271
15484
|
// ../engine/dist/parsers/gemini-brain-source.js
|
|
15272
|
-
import { existsSync as existsSync27, readdirSync as readdirSync21, readFileSync as
|
|
15485
|
+
import { existsSync as existsSync27, readdirSync as readdirSync21, readFileSync as readFileSync19, statSync as statSync25 } from "fs";
|
|
15273
15486
|
import { join as join28 } from "path";
|
|
15274
15487
|
var MAX_CHUNK_CHARS8, GeminiBrainSource;
|
|
15275
15488
|
var init_gemini_brain_source = __esm({
|
|
@@ -15302,14 +15515,14 @@ var init_gemini_brain_source = __esm({
|
|
|
15302
15515
|
const filePath = join28(sessionDir, file);
|
|
15303
15516
|
try {
|
|
15304
15517
|
const stat3 = statSync25(filePath);
|
|
15305
|
-
const content =
|
|
15518
|
+
const content = readFileSync19(filePath, "utf-8");
|
|
15306
15519
|
const firstLine = content.split("\n").find((l) => l.trim() && !l.startsWith("#"))?.trim() || "";
|
|
15307
15520
|
const heading = content.split("\n").find((l) => l.startsWith("#"))?.replace(/^#+\s*/, "").trim() || file;
|
|
15308
15521
|
const metaPath = `${filePath}.metadata.json`;
|
|
15309
15522
|
let metaSummary = "";
|
|
15310
15523
|
if (existsSync27(metaPath)) {
|
|
15311
15524
|
try {
|
|
15312
|
-
const meta = JSON.parse(
|
|
15525
|
+
const meta = JSON.parse(readFileSync19(metaPath, "utf-8"));
|
|
15313
15526
|
metaSummary = meta.summary || "";
|
|
15314
15527
|
} catch {
|
|
15315
15528
|
}
|
|
@@ -15340,7 +15553,7 @@ var init_gemini_brain_source = __esm({
|
|
|
15340
15553
|
async parse(item) {
|
|
15341
15554
|
if (!existsSync27(item.filePath))
|
|
15342
15555
|
return [];
|
|
15343
|
-
const content =
|
|
15556
|
+
const content = readFileSync19(item.filePath, "utf-8");
|
|
15344
15557
|
const chunks = [];
|
|
15345
15558
|
const sections = splitByHeaders(content);
|
|
15346
15559
|
for (let i = 0; i < sections.length; i++) {
|
|
@@ -15683,7 +15896,7 @@ var init_opencode_todo_source = __esm({
|
|
|
15683
15896
|
});
|
|
15684
15897
|
|
|
15685
15898
|
// ../engine/dist/parsers/codex-session-source.js
|
|
15686
|
-
import { existsSync as existsSync30, readdirSync as readdirSync22, readFileSync as
|
|
15899
|
+
import { existsSync as existsSync30, readdirSync as readdirSync22, readFileSync as readFileSync20, statSync as statSync26 } from "fs";
|
|
15687
15900
|
import { join as join29, basename as basename18 } from "path";
|
|
15688
15901
|
function getCodexSessionsDir() {
|
|
15689
15902
|
return codexBackend.sessionsDir();
|
|
@@ -15711,7 +15924,7 @@ function extractReasoningText(event) {
|
|
|
15711
15924
|
return "";
|
|
15712
15925
|
}
|
|
15713
15926
|
function readJsonlLines(filePath) {
|
|
15714
|
-
const text =
|
|
15927
|
+
const text = readFileSync20(filePath, "utf-8");
|
|
15715
15928
|
const lines = text.split("\n");
|
|
15716
15929
|
const events = [];
|
|
15717
15930
|
for (const line of lines) {
|
|
@@ -15746,7 +15959,7 @@ var init_codex_session_source = __esm({
|
|
|
15746
15959
|
for (const filePath of jsonlFiles) {
|
|
15747
15960
|
try {
|
|
15748
15961
|
const stat3 = statSync26(filePath);
|
|
15749
|
-
const lines =
|
|
15962
|
+
const lines = readFileSync20(filePath, "utf-8").split("\n");
|
|
15750
15963
|
const firstLine = lines.find((l) => l.trim());
|
|
15751
15964
|
if (!firstLine)
|
|
15752
15965
|
continue;
|
|
@@ -15919,7 +16132,7 @@ var init_codex_session_source = __esm({
|
|
|
15919
16132
|
});
|
|
15920
16133
|
|
|
15921
16134
|
// ../engine/dist/parsers/diary-source.js
|
|
15922
|
-
import { existsSync as existsSync31, mkdirSync as mkdirSync5, readdirSync as readdirSync23, readFileSync as
|
|
16135
|
+
import { existsSync as existsSync31, mkdirSync as mkdirSync5, readdirSync as readdirSync23, readFileSync as readFileSync21, writeFileSync as writeFileSync4, statSync as statSync27 } from "fs";
|
|
15923
16136
|
import { join as join30, basename as basename19 } from "path";
|
|
15924
16137
|
var MAX_CHUNK_CHARS11, DiarySource;
|
|
15925
16138
|
var init_diary_source = __esm({
|
|
@@ -15945,7 +16158,7 @@ var init_diary_source = __esm({
|
|
|
15945
16158
|
const filePath = join30(agentPath2, file);
|
|
15946
16159
|
try {
|
|
15947
16160
|
const stat3 = statSync27(filePath);
|
|
15948
|
-
const raw =
|
|
16161
|
+
const raw = readFileSync21(filePath, "utf-8");
|
|
15949
16162
|
const entry = JSON.parse(raw);
|
|
15950
16163
|
const entryId = basename19(file, ".json");
|
|
15951
16164
|
const title = `[${entry.agent}] ${entry.topic}: ${entry.content.slice(0, 80)}`;
|
|
@@ -15972,7 +16185,7 @@ var init_diary_source = __esm({
|
|
|
15972
16185
|
async parse(item) {
|
|
15973
16186
|
if (!existsSync31(item.filePath))
|
|
15974
16187
|
return [];
|
|
15975
|
-
const raw =
|
|
16188
|
+
const raw = readFileSync21(item.filePath, "utf-8");
|
|
15976
16189
|
const entry = JSON.parse(raw);
|
|
15977
16190
|
if (!entry.content || entry.content.trim().length < 10)
|
|
15978
16191
|
return [];
|
|
@@ -16035,7 +16248,7 @@ var init_diary_source = __esm({
|
|
|
16035
16248
|
const entries = [];
|
|
16036
16249
|
for (const file of files) {
|
|
16037
16250
|
try {
|
|
16038
|
-
const raw =
|
|
16251
|
+
const raw = readFileSync21(join30(agentDir, file), "utf-8");
|
|
16039
16252
|
entries.push(JSON.parse(raw));
|
|
16040
16253
|
} catch {
|
|
16041
16254
|
continue;
|
|
@@ -16048,7 +16261,7 @@ var init_diary_source = __esm({
|
|
|
16048
16261
|
});
|
|
16049
16262
|
|
|
16050
16263
|
// ../engine/dist/parsers/skills-source.js
|
|
16051
|
-
import { existsSync as existsSync32, readdirSync as readdirSync24, readFileSync as
|
|
16264
|
+
import { existsSync as existsSync32, readdirSync as readdirSync24, readFileSync as readFileSync22, statSync as statSync28 } from "fs";
|
|
16052
16265
|
import { homedir as homedir12 } from "os";
|
|
16053
16266
|
import { join as join31 } from "path";
|
|
16054
16267
|
function resolveRoots() {
|
|
@@ -16141,7 +16354,7 @@ var init_skills_source = __esm({
|
|
|
16141
16354
|
continue;
|
|
16142
16355
|
let content;
|
|
16143
16356
|
try {
|
|
16144
|
-
content =
|
|
16357
|
+
content = readFileSync22(skillMd, "utf-8");
|
|
16145
16358
|
} catch {
|
|
16146
16359
|
continue;
|
|
16147
16360
|
}
|
|
@@ -16201,7 +16414,7 @@ var init_skills_source = __esm({
|
|
|
16201
16414
|
async parse(item) {
|
|
16202
16415
|
if (!existsSync32(item.filePath))
|
|
16203
16416
|
return [];
|
|
16204
|
-
const content =
|
|
16417
|
+
const content = readFileSync22(item.filePath, "utf-8");
|
|
16205
16418
|
if (!content.trim())
|
|
16206
16419
|
return [];
|
|
16207
16420
|
return [{
|
|
@@ -16224,14 +16437,14 @@ var init_skills_source = __esm({
|
|
|
16224
16437
|
});
|
|
16225
16438
|
|
|
16226
16439
|
// ../engine/dist/parsers/mcps-source.js
|
|
16227
|
-
import { existsSync as existsSync33, readdirSync as readdirSync25, readFileSync as
|
|
16440
|
+
import { existsSync as existsSync33, readdirSync as readdirSync25, readFileSync as readFileSync23, statSync as statSync29 } from "fs";
|
|
16228
16441
|
import { homedir as homedir13 } from "os";
|
|
16229
16442
|
import { join as join32 } from "path";
|
|
16230
16443
|
function readJson(path) {
|
|
16231
16444
|
if (!existsSync33(path))
|
|
16232
16445
|
return null;
|
|
16233
16446
|
try {
|
|
16234
|
-
const raw =
|
|
16447
|
+
const raw = readFileSync23(path, "utf-8");
|
|
16235
16448
|
const stripped = path.endsWith(".jsonc") ? raw.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:])\/\/.*$/gm, "$1").replace(/,(\s*[}\]])/g, "$1") : raw;
|
|
16236
16449
|
return JSON.parse(stripped);
|
|
16237
16450
|
} catch {
|
|
@@ -16344,7 +16557,7 @@ var init_mcps_source = __esm({
|
|
|
16344
16557
|
return;
|
|
16345
16558
|
let content;
|
|
16346
16559
|
try {
|
|
16347
|
-
content =
|
|
16560
|
+
content = readFileSync23(path, "utf-8");
|
|
16348
16561
|
} catch {
|
|
16349
16562
|
return;
|
|
16350
16563
|
}
|
|
@@ -16513,7 +16726,7 @@ var init_toolkit_format = __esm({
|
|
|
16513
16726
|
});
|
|
16514
16727
|
|
|
16515
16728
|
// ../engine/dist/parsers/slash-commands-source.js
|
|
16516
|
-
import { existsSync as existsSync34, readdirSync as readdirSync26, readFileSync as
|
|
16729
|
+
import { existsSync as existsSync34, readdirSync as readdirSync26, readFileSync as readFileSync24, statSync as statSync30 } from "fs";
|
|
16517
16730
|
import { join as join33, basename as basename20 } from "path";
|
|
16518
16731
|
function parseCommand(content, fallbackName, format) {
|
|
16519
16732
|
if (format === "toml") {
|
|
@@ -16541,6 +16754,7 @@ var init_slash_commands_source = __esm({
|
|
|
16541
16754
|
init_codex2();
|
|
16542
16755
|
init_settings();
|
|
16543
16756
|
init_toolkit_format();
|
|
16757
|
+
init_project_dir_name();
|
|
16544
16758
|
MAX_CHUNK_CHARS13 = 2e3;
|
|
16545
16759
|
SlashCommandsSource = class {
|
|
16546
16760
|
sourceType = "command";
|
|
@@ -16554,7 +16768,7 @@ var init_slash_commands_source = __esm({
|
|
|
16554
16768
|
for (const entry of readdirSync26(projectsRoot, { withFileTypes: true })) {
|
|
16555
16769
|
if (!entry.isDirectory() || entry.name.startsWith("."))
|
|
16556
16770
|
continue;
|
|
16557
|
-
const projectPath = entry.name
|
|
16771
|
+
const projectPath = decodeProjectDirName(entry.name);
|
|
16558
16772
|
const cmdDir = join33(projectPath, ".claude", "commands");
|
|
16559
16773
|
if (existsSync34(cmdDir))
|
|
16560
16774
|
roots.push({ path: cmdDir, tool: "claude", scope: "project", projectPath, format: "md" });
|
|
@@ -16587,7 +16801,7 @@ var init_slash_commands_source = __esm({
|
|
|
16587
16801
|
const filePath = join33(root.path, file);
|
|
16588
16802
|
try {
|
|
16589
16803
|
const stat3 = statSync30(filePath);
|
|
16590
|
-
const content =
|
|
16804
|
+
const content = readFileSync24(filePath, "utf-8");
|
|
16591
16805
|
const parsed = parseCommand(content, basename20(file, ext), root.format);
|
|
16592
16806
|
yield {
|
|
16593
16807
|
id: `${root.tool}_cmd_${root.scope}_${parsed.name}`,
|
|
@@ -16613,7 +16827,7 @@ var init_slash_commands_source = __esm({
|
|
|
16613
16827
|
async parse(item) {
|
|
16614
16828
|
if (!existsSync34(item.filePath))
|
|
16615
16829
|
return [];
|
|
16616
|
-
const content =
|
|
16830
|
+
const content = readFileSync24(item.filePath, "utf-8");
|
|
16617
16831
|
if (!content.trim())
|
|
16618
16832
|
return [];
|
|
16619
16833
|
return [{
|
|
@@ -16636,7 +16850,7 @@ var init_slash_commands_source = __esm({
|
|
|
16636
16850
|
});
|
|
16637
16851
|
|
|
16638
16852
|
// ../engine/dist/parsers/subagents-source.js
|
|
16639
|
-
import { existsSync as existsSync35, readdirSync as readdirSync27, readFileSync as
|
|
16853
|
+
import { existsSync as existsSync35, readdirSync as readdirSync27, readFileSync as readFileSync25, statSync as statSync31 } from "fs";
|
|
16640
16854
|
import { join as join34, basename as basename21 } from "path";
|
|
16641
16855
|
function parseAgent(content, fallbackName, format) {
|
|
16642
16856
|
if (format === "toml") {
|
|
@@ -16666,6 +16880,7 @@ var init_subagents_source = __esm({
|
|
|
16666
16880
|
init_codex2();
|
|
16667
16881
|
init_settings();
|
|
16668
16882
|
init_toolkit_format();
|
|
16883
|
+
init_project_dir_name();
|
|
16669
16884
|
MAX_CHUNK_CHARS14 = 2e3;
|
|
16670
16885
|
SubagentsSource = class {
|
|
16671
16886
|
sourceType = "agent";
|
|
@@ -16679,7 +16894,7 @@ var init_subagents_source = __esm({
|
|
|
16679
16894
|
for (const entry of readdirSync27(projectsRoot, { withFileTypes: true })) {
|
|
16680
16895
|
if (!entry.isDirectory() || entry.name.startsWith("."))
|
|
16681
16896
|
continue;
|
|
16682
|
-
const projectPath = entry.name
|
|
16897
|
+
const projectPath = decodeProjectDirName(entry.name);
|
|
16683
16898
|
const agentDir = join34(projectPath, ".claude", "agents");
|
|
16684
16899
|
if (existsSync35(agentDir))
|
|
16685
16900
|
roots.push({ path: agentDir, tool: "claude", scope: "project", projectPath, format: "md" });
|
|
@@ -16712,7 +16927,7 @@ var init_subagents_source = __esm({
|
|
|
16712
16927
|
const filePath = join34(root.path, file);
|
|
16713
16928
|
try {
|
|
16714
16929
|
const stat3 = statSync31(filePath);
|
|
16715
|
-
const content =
|
|
16930
|
+
const content = readFileSync25(filePath, "utf-8");
|
|
16716
16931
|
const parsed = parseAgent(content, basename21(file, ext), root.format);
|
|
16717
16932
|
yield {
|
|
16718
16933
|
id: `${root.tool}_agent_${root.scope}_${parsed.name}`,
|
|
@@ -16739,7 +16954,7 @@ var init_subagents_source = __esm({
|
|
|
16739
16954
|
async parse(item) {
|
|
16740
16955
|
if (!existsSync35(item.filePath))
|
|
16741
16956
|
return [];
|
|
16742
|
-
const content =
|
|
16957
|
+
const content = readFileSync25(item.filePath, "utf-8");
|
|
16743
16958
|
if (!content.trim())
|
|
16744
16959
|
return [];
|
|
16745
16960
|
return [{
|
|
@@ -16762,13 +16977,13 @@ var init_subagents_source = __esm({
|
|
|
16762
16977
|
});
|
|
16763
16978
|
|
|
16764
16979
|
// ../engine/dist/parsers/hooks-source.js
|
|
16765
|
-
import { existsSync as existsSync36, readFileSync as
|
|
16980
|
+
import { existsSync as existsSync36, readFileSync as readFileSync26, readdirSync as readdirSync28, statSync as statSync32 } from "fs";
|
|
16766
16981
|
import { join as join35 } from "path";
|
|
16767
16982
|
function readJson2(path) {
|
|
16768
16983
|
if (!existsSync36(path))
|
|
16769
16984
|
return null;
|
|
16770
16985
|
try {
|
|
16771
|
-
return JSON.parse(
|
|
16986
|
+
return JSON.parse(readFileSync26(path, "utf-8"));
|
|
16772
16987
|
} catch {
|
|
16773
16988
|
return null;
|
|
16774
16989
|
}
|
|
@@ -16779,6 +16994,7 @@ var init_hooks_source = __esm({
|
|
|
16779
16994
|
"use strict";
|
|
16780
16995
|
init_claude2();
|
|
16781
16996
|
init_settings();
|
|
16997
|
+
init_project_dir_name();
|
|
16782
16998
|
HooksSource = class {
|
|
16783
16999
|
sourceType = "hook";
|
|
16784
17000
|
async *discover() {
|
|
@@ -16791,7 +17007,7 @@ var init_hooks_source = __esm({
|
|
|
16791
17007
|
for (const entry of readdirSync28(projectsRoot, { withFileTypes: true })) {
|
|
16792
17008
|
if (!entry.isDirectory() || entry.name.startsWith("."))
|
|
16793
17009
|
continue;
|
|
16794
|
-
const projectPath = entry.name
|
|
17010
|
+
const projectPath = decodeProjectDirName(entry.name);
|
|
16795
17011
|
const settingsPath2 = join35(projectPath, ".claude", "settings.json");
|
|
16796
17012
|
if (existsSync36(settingsPath2)) {
|
|
16797
17013
|
yield* this.fromSettings(settingsPath2, "project", projectPath);
|
|
@@ -16884,14 +17100,14 @@ var init_hooks_source = __esm({
|
|
|
16884
17100
|
});
|
|
16885
17101
|
|
|
16886
17102
|
// ../engine/dist/parsers/plugins-source.js
|
|
16887
|
-
import { existsSync as existsSync37, readFileSync as
|
|
17103
|
+
import { existsSync as existsSync37, readFileSync as readFileSync27, readdirSync as readdirSync29, statSync as statSync33 } from "fs";
|
|
16888
17104
|
import { homedir as homedir14 } from "os";
|
|
16889
17105
|
import { join as join36 } from "path";
|
|
16890
17106
|
function readJson3(path) {
|
|
16891
17107
|
if (!existsSync37(path))
|
|
16892
17108
|
return null;
|
|
16893
17109
|
try {
|
|
16894
|
-
return JSON.parse(
|
|
17110
|
+
return JSON.parse(readFileSync27(path, "utf-8"));
|
|
16895
17111
|
} catch {
|
|
16896
17112
|
return null;
|
|
16897
17113
|
}
|
|
@@ -17148,7 +17364,7 @@ var init_extractor_version = __esm({
|
|
|
17148
17364
|
});
|
|
17149
17365
|
|
|
17150
17366
|
// src/sync-ledger.ts
|
|
17151
|
-
import { readFileSync as
|
|
17367
|
+
import { readFileSync as readFileSync28, writeFileSync as writeFileSync5, renameSync as renameSync4, mkdirSync as mkdirSync6 } from "node:fs";
|
|
17152
17368
|
import { join as join37, dirname as dirname14 } from "node:path";
|
|
17153
17369
|
function toRow(entry) {
|
|
17154
17370
|
if (entry === void 0) return void 0;
|
|
@@ -17157,24 +17373,77 @@ function toRow(entry) {
|
|
|
17157
17373
|
function load() {
|
|
17158
17374
|
if (cache3) return cache3;
|
|
17159
17375
|
try {
|
|
17160
|
-
const parsed = JSON.parse(
|
|
17376
|
+
const parsed = JSON.parse(readFileSync28(ledgerPath(), "utf-8"));
|
|
17161
17377
|
cache3 = parsed && typeof parsed === "object" ? parsed : {};
|
|
17162
17378
|
} catch {
|
|
17163
17379
|
cache3 = {};
|
|
17164
17380
|
}
|
|
17165
17381
|
return cache3;
|
|
17166
17382
|
}
|
|
17167
|
-
function
|
|
17383
|
+
function persistNow(data) {
|
|
17168
17384
|
const path = ledgerPath();
|
|
17169
17385
|
mkdirSync6(dirname14(path), { recursive: true });
|
|
17170
17386
|
const tmp = `${path}.tmp`;
|
|
17171
17387
|
writeFileSync5(tmp, JSON.stringify(data));
|
|
17172
17388
|
renameSync4(tmp, path);
|
|
17389
|
+
pendingWrite = false;
|
|
17390
|
+
}
|
|
17391
|
+
function persist(data) {
|
|
17392
|
+
pendingWrite = true;
|
|
17393
|
+
if (flushTimer) return;
|
|
17394
|
+
flushTimer = setTimeout(() => {
|
|
17395
|
+
flushTimer = null;
|
|
17396
|
+
if (pendingWrite) {
|
|
17397
|
+
try {
|
|
17398
|
+
persistNow(data);
|
|
17399
|
+
} catch {
|
|
17400
|
+
}
|
|
17401
|
+
}
|
|
17402
|
+
}, LEDGER_FLUSH_MS);
|
|
17403
|
+
flushTimer.unref?.();
|
|
17404
|
+
}
|
|
17405
|
+
function pruneLedgerTargets(configuredServers) {
|
|
17406
|
+
const data = load();
|
|
17407
|
+
const keep = new Set(configuredServers);
|
|
17408
|
+
const orphans = {};
|
|
17409
|
+
for (const server of Object.keys(data)) {
|
|
17410
|
+
if (!keep.has(server)) {
|
|
17411
|
+
orphans[server] = data[server];
|
|
17412
|
+
delete data[server];
|
|
17413
|
+
}
|
|
17414
|
+
}
|
|
17415
|
+
const names = Object.keys(orphans);
|
|
17416
|
+
if (names.length === 0) return 0;
|
|
17417
|
+
const path = ledgerPath();
|
|
17418
|
+
const side = `${path}.orphans.json`;
|
|
17419
|
+
try {
|
|
17420
|
+
let prior = {};
|
|
17421
|
+
try {
|
|
17422
|
+
prior = JSON.parse(readFileSync28(side, "utf-8"));
|
|
17423
|
+
} catch {
|
|
17424
|
+
}
|
|
17425
|
+
writeFileSync5(side, JSON.stringify({ ...prior, ...orphans }));
|
|
17426
|
+
} catch {
|
|
17427
|
+
for (const n of names) data[n] = orphans[n];
|
|
17428
|
+
return 0;
|
|
17429
|
+
}
|
|
17430
|
+
const rows = names.reduce((n, s) => n + Object.keys(orphans[s]).length, 0);
|
|
17431
|
+
console.error(`[sync] ledger: parked ${rows} row(s) for ${names.length} server(s) no longer configured (${names.join(", ")}) in ${side}`);
|
|
17432
|
+
persistNow(data);
|
|
17433
|
+
return names.length;
|
|
17434
|
+
}
|
|
17435
|
+
function flushLedger() {
|
|
17436
|
+
if (flushTimer) {
|
|
17437
|
+
clearTimeout(flushTimer);
|
|
17438
|
+
flushTimer = null;
|
|
17439
|
+
}
|
|
17440
|
+
if (!pendingWrite || !cache3) return;
|
|
17441
|
+
persistNow(cache3);
|
|
17173
17442
|
}
|
|
17174
17443
|
function loadItemVersionsAll() {
|
|
17175
17444
|
if (itemVersionsCache) return itemVersionsCache;
|
|
17176
17445
|
try {
|
|
17177
|
-
const parsed = JSON.parse(
|
|
17446
|
+
const parsed = JSON.parse(readFileSync28(itemVersionsPath(), "utf-8"));
|
|
17178
17447
|
itemVersionsCache = parsed && typeof parsed === "object" ? parsed : {};
|
|
17179
17448
|
} catch {
|
|
17180
17449
|
itemVersionsCache = {};
|
|
@@ -17256,7 +17525,7 @@ function markFieldCoverage(server, field, rows) {
|
|
|
17256
17525
|
function loadReconcile() {
|
|
17257
17526
|
if (reconcileCache) return reconcileCache;
|
|
17258
17527
|
try {
|
|
17259
|
-
const parsed = JSON.parse(
|
|
17528
|
+
const parsed = JSON.parse(readFileSync28(reconcilePath(), "utf-8"));
|
|
17260
17529
|
reconcileCache = parsed && typeof parsed === "object" ? parsed : {};
|
|
17261
17530
|
} catch {
|
|
17262
17531
|
reconcileCache = {};
|
|
@@ -17304,7 +17573,7 @@ function syncMode(row, mtime, fileSize, extractorVersion, isAppendOnly) {
|
|
|
17304
17573
|
if (row.m >= Math.floor(mtime)) return "skip";
|
|
17305
17574
|
return "full";
|
|
17306
17575
|
}
|
|
17307
|
-
var ledgerPath, cache3, itemVersionsPath, itemVersionsCache, unackedCursorAttempts, reconcilePath, reconcileCache;
|
|
17576
|
+
var ledgerPath, cache3, LEDGER_FLUSH_MS, pendingWrite, flushTimer, itemVersionsPath, itemVersionsCache, unackedCursorAttempts, reconcilePath, reconcileCache;
|
|
17308
17577
|
var init_sync_ledger = __esm({
|
|
17309
17578
|
"src/sync-ledger.ts"() {
|
|
17310
17579
|
"use strict";
|
|
@@ -17312,6 +17581,9 @@ var init_sync_ledger = __esm({
|
|
|
17312
17581
|
init_extractor_version();
|
|
17313
17582
|
ledgerPath = () => join37(getDataDir(), "sync-ledger.json");
|
|
17314
17583
|
cache3 = null;
|
|
17584
|
+
LEDGER_FLUSH_MS = 2e3;
|
|
17585
|
+
pendingWrite = false;
|
|
17586
|
+
flushTimer = null;
|
|
17315
17587
|
itemVersionsPath = () => join37(getDataDir(), "item-versions.json");
|
|
17316
17588
|
itemVersionsCache = null;
|
|
17317
17589
|
unackedCursorAttempts = 0;
|
|
@@ -17346,7 +17618,7 @@ var init_sync_fields = __esm({
|
|
|
17346
17618
|
});
|
|
17347
17619
|
|
|
17348
17620
|
// ../engine/dist/core/index-lock.js
|
|
17349
|
-
import { existsSync as existsSync38, mkdirSync as mkdirSync7, openSync as
|
|
17621
|
+
import { existsSync as existsSync38, mkdirSync as mkdirSync7, openSync as openSync7, writeFileSync as writeFileSync6, readFileSync as readFileSync29, rmSync as rmSync4, statSync as statSync34, closeSync as closeSync7 } from "fs";
|
|
17350
17622
|
import { dirname as dirname15, join as join38 } from "path";
|
|
17351
17623
|
function acquireIndexLock(opts) {
|
|
17352
17624
|
const lockPath = lockFilePath();
|
|
@@ -17358,7 +17630,7 @@ function acquireIndexLock(opts) {
|
|
|
17358
17630
|
}
|
|
17359
17631
|
let fd;
|
|
17360
17632
|
try {
|
|
17361
|
-
fd =
|
|
17633
|
+
fd = openSync7(lockPath, "wx", 384);
|
|
17362
17634
|
} catch (err) {
|
|
17363
17635
|
if (err.code === "EEXIST")
|
|
17364
17636
|
return null;
|
|
@@ -17368,7 +17640,7 @@ function acquireIndexLock(opts) {
|
|
|
17368
17640
|
try {
|
|
17369
17641
|
writeFileSync6(fd, JSON.stringify(holder));
|
|
17370
17642
|
} finally {
|
|
17371
|
-
|
|
17643
|
+
closeSync7(fd);
|
|
17372
17644
|
}
|
|
17373
17645
|
let released = false;
|
|
17374
17646
|
return {
|
|
@@ -17378,7 +17650,7 @@ function acquireIndexLock(opts) {
|
|
|
17378
17650
|
return;
|
|
17379
17651
|
released = true;
|
|
17380
17652
|
try {
|
|
17381
|
-
const current = JSON.parse(
|
|
17653
|
+
const current = JSON.parse(readFileSync29(lockPath, "utf-8"));
|
|
17382
17654
|
if (current.pid !== holder.pid || current.startedAt !== holder.startedAt)
|
|
17383
17655
|
return;
|
|
17384
17656
|
} catch {
|
|
@@ -17400,7 +17672,7 @@ function stealStaleLock(lockPath, staleAfterMs) {
|
|
|
17400
17672
|
const age = Date.now() - s.mtimeMs;
|
|
17401
17673
|
let payload;
|
|
17402
17674
|
try {
|
|
17403
|
-
payload = JSON.parse(
|
|
17675
|
+
payload = JSON.parse(readFileSync29(lockPath, "utf-8"));
|
|
17404
17676
|
} catch {
|
|
17405
17677
|
rmSync4(lockPath, { force: true });
|
|
17406
17678
|
return true;
|
|
@@ -17438,7 +17710,7 @@ var init_index_lock = __esm({
|
|
|
17438
17710
|
});
|
|
17439
17711
|
|
|
17440
17712
|
// src/http.ts
|
|
17441
|
-
import { readFileSync as
|
|
17713
|
+
import { readFileSync as readFileSync30 } from "node:fs";
|
|
17442
17714
|
function clientHeaders() {
|
|
17443
17715
|
return {
|
|
17444
17716
|
"x-chat-recall-cli": CLI_VERSION,
|
|
@@ -17456,10 +17728,10 @@ var init_http = __esm({
|
|
|
17456
17728
|
"use strict";
|
|
17457
17729
|
CLI_VERSION = "0.0.0";
|
|
17458
17730
|
try {
|
|
17459
|
-
CLI_VERSION = JSON.parse(
|
|
17731
|
+
CLI_VERSION = JSON.parse(readFileSync30(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
|
|
17460
17732
|
} catch {
|
|
17461
17733
|
try {
|
|
17462
|
-
if (true) CLI_VERSION = "0.5.
|
|
17734
|
+
if (true) CLI_VERSION = "0.5.6";
|
|
17463
17735
|
} catch {
|
|
17464
17736
|
}
|
|
17465
17737
|
}
|
|
@@ -17472,7 +17744,7 @@ __export(client_events_exports, {
|
|
|
17472
17744
|
isTelemetryEnabled: () => isTelemetryEnabled,
|
|
17473
17745
|
reportClientEvent: () => reportClientEvent
|
|
17474
17746
|
});
|
|
17475
|
-
import { readFileSync as
|
|
17747
|
+
import { readFileSync as readFileSync31 } from "node:fs";
|
|
17476
17748
|
function scrub(msg) {
|
|
17477
17749
|
if (!msg) return "";
|
|
17478
17750
|
const noHome = msg.replace(/\/(?:home|Users)\/[^/\s]+/g, "~");
|
|
@@ -17525,7 +17797,7 @@ var init_client_events = __esm({
|
|
|
17525
17797
|
init_secret_redactor();
|
|
17526
17798
|
CLI_VERSION2 = "0.0.0";
|
|
17527
17799
|
try {
|
|
17528
|
-
CLI_VERSION2 = JSON.parse(
|
|
17800
|
+
CLI_VERSION2 = JSON.parse(readFileSync31(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION2;
|
|
17529
17801
|
} catch {
|
|
17530
17802
|
}
|
|
17531
17803
|
}
|
|
@@ -17645,13 +17917,15 @@ var init_auto_update = __esm({
|
|
|
17645
17917
|
|
|
17646
17918
|
// src/sync-client.ts
|
|
17647
17919
|
import { join as join40, dirname as dirname16, basename as basename22 } from "node:path";
|
|
17648
|
-
import { readFileSync as
|
|
17920
|
+
import { readFileSync as readFileSync32, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8, mkdtempSync as mkdtempSync4, rmSync as rmSync5, chmodSync as chmodSync3, unlinkSync as unlinkSync2, readdirSync as readdirSync30, statSync as statSync35 } from "node:fs";
|
|
17649
17921
|
import { tmpdir as tmpdir3, hostname } from "node:os";
|
|
17650
17922
|
import { createHash as createHash12 } from "node:crypto";
|
|
17651
17923
|
import { fileURLToPath } from "node:url";
|
|
17652
17924
|
function loadAllCredentials() {
|
|
17925
|
+
const fromEnv = envCredentials();
|
|
17926
|
+
if (fromEnv) return [{ serverUrl: fromEnv.serverUrl, token: fromEnv.token }];
|
|
17653
17927
|
try {
|
|
17654
|
-
const parsed = JSON.parse(
|
|
17928
|
+
const parsed = JSON.parse(readFileSync32(credPath(), "utf-8"));
|
|
17655
17929
|
if (Array.isArray(parsed?.targets)) return parsed.targets.filter((t) => t?.serverUrl).map((t) => ({ serverUrl: t.serverUrl, token: t.token || "" }));
|
|
17656
17930
|
if (parsed?.serverUrl) return [{ serverUrl: parsed.serverUrl, token: parsed.token || "" }];
|
|
17657
17931
|
} catch {
|
|
@@ -17797,6 +18071,10 @@ function isLocalHost(serverUrl) {
|
|
|
17797
18071
|
async function syncSessions(opts = {}) {
|
|
17798
18072
|
const targets = loadAllCredentials();
|
|
17799
18073
|
if (targets.length === 0) throw new Error("Not logged in \u2014 run `chat-recall login <server-url> --token <token>`");
|
|
18074
|
+
try {
|
|
18075
|
+
pruneLedgerTargets(targets.map((t) => t.serverUrl));
|
|
18076
|
+
} catch {
|
|
18077
|
+
}
|
|
17800
18078
|
let agg = null;
|
|
17801
18079
|
const errors = [];
|
|
17802
18080
|
for (const cred of targets) {
|
|
@@ -17819,6 +18097,7 @@ async function syncSessions(opts = {}) {
|
|
|
17819
18097
|
errors.push(`${cred.serverUrl}: ${e instanceof Error ? e.message : e}`);
|
|
17820
18098
|
}
|
|
17821
18099
|
}
|
|
18100
|
+
flushLedger();
|
|
17822
18101
|
if (!agg) throw new Error(`sync failed for all targets:
|
|
17823
18102
|
${errors.join("\n ")}`);
|
|
17824
18103
|
if (errors.length > 0) console.error(`[sync] ${errors.length} target(s) failed (others succeeded):
|
|
@@ -17844,11 +18123,11 @@ async function reconcileFieldsForTarget(cred, fullRefs, opts = {}) {
|
|
|
17844
18123
|
let pushed = 0, absent = 0, scanned = 0;
|
|
17845
18124
|
for (const field of SYNC_FIELDS) {
|
|
17846
18125
|
const needFull = !!opts.force || fieldNeedsFullPass(base2, field);
|
|
17847
|
-
const
|
|
18126
|
+
const candidates2 = needFull ? fullRefs() : opts.convRefs ?? fullRefs();
|
|
17848
18127
|
const send = [];
|
|
17849
18128
|
const mtimeById = /* @__PURE__ */ new Map();
|
|
17850
18129
|
const absentIds = [];
|
|
17851
|
-
for (const ref of
|
|
18130
|
+
for (const ref of candidates2) {
|
|
17852
18131
|
if (!fieldNeedsScan(ledger.get(ref.prefixedId), field, ref.mtime, opts.force)) continue;
|
|
17853
18132
|
scanned++;
|
|
17854
18133
|
mtimeById.set(ref.prefixedId, ref.mtime);
|
|
@@ -17947,6 +18226,17 @@ function batchScanExternal(items, opts = {}) {
|
|
|
17947
18226
|
}
|
|
17948
18227
|
return { findings, scanned, slices, scanMs };
|
|
17949
18228
|
}
|
|
18229
|
+
async function verifyServerApi(serverUrl, minApi) {
|
|
18230
|
+
const base2 = serverUrl.replace(/\/$/, "");
|
|
18231
|
+
const seen = capsOk.get(base2);
|
|
18232
|
+
if (seen !== void 0 && Date.now() - seen < CAPS_TTL_MS) return true;
|
|
18233
|
+
const caps = await fetchWithTimeout(`${base2}/api/capabilities`).then((r) => r.json());
|
|
18234
|
+
if ((caps.apiVersion ?? 0) < minApi) {
|
|
18235
|
+
throw new Error(`server too old: apiVersion ${caps.apiVersion ?? "none"} < required ${minApi} \u2014 update the server image before syncing`);
|
|
18236
|
+
}
|
|
18237
|
+
capsOk.set(base2, Date.now());
|
|
18238
|
+
return true;
|
|
18239
|
+
}
|
|
17950
18240
|
async function syncToTarget(cred, opts = {}) {
|
|
17951
18241
|
const sync = loadSettings().sync;
|
|
17952
18242
|
const serverCfg = await fetchTenantSyncConfig(cred);
|
|
@@ -17967,14 +18257,9 @@ async function syncToTarget(cred, opts = {}) {
|
|
|
17967
18257
|
return isProjectSyncable(r.source === "ignored" ? "" : r.id, projectPath, { syncMode: "only", syncOnly });
|
|
17968
18258
|
};
|
|
17969
18259
|
const MIN_SERVER_API = 2;
|
|
17970
|
-
|
|
17971
|
-
const
|
|
17972
|
-
if ((
|
|
17973
|
-
throw new Error(`server too old: apiVersion ${caps.apiVersion ?? "none"} < required ${MIN_SERVER_API} \u2014 update the server image before syncing`);
|
|
17974
|
-
}
|
|
17975
|
-
} catch (e) {
|
|
17976
|
-
if (e instanceof Error && e.message.startsWith("server too old")) throw e;
|
|
17977
|
-
throw new Error(`cannot verify server version (${e instanceof Error ? e.message : e}) \u2014 refusing to sync blind`);
|
|
18260
|
+
{
|
|
18261
|
+
const ok = await verifyServerApi(cred.serverUrl, MIN_SERVER_API);
|
|
18262
|
+
if (!ok) throw new Error(`cannot verify server version \u2014 refusing to sync blind`);
|
|
17978
18263
|
}
|
|
17979
18264
|
const { tenantRules, verifySecrets } = await fetchTenantSecurityConfig(cred);
|
|
17980
18265
|
const CHANGED_WALK_OVERLAP_MS = 15 * 6e4;
|
|
@@ -18031,8 +18316,11 @@ async function syncToTarget(cred, opts = {}) {
|
|
|
18031
18316
|
try {
|
|
18032
18317
|
const body2 = JSON.parse(text);
|
|
18033
18318
|
detail = body2.error ?? text;
|
|
18319
|
+
if (body2.detail) detail += `
|
|
18320
|
+
${body2.detail}`;
|
|
18034
18321
|
if (body2.resetsAt) detail += ` (resets ${new Date(body2.resetsAt).toISOString().slice(0, 10)})`;
|
|
18035
|
-
if (body2.upgradeUrl) detail += `
|
|
18322
|
+
if (body2.upgradeUrl) detail += `
|
|
18323
|
+
${body2.upgradeUrl}`;
|
|
18036
18324
|
} catch {
|
|
18037
18325
|
}
|
|
18038
18326
|
throw new Error(`sync paused by the server: ${detail}`);
|
|
@@ -18179,16 +18467,21 @@ async function syncToTarget(cred, opts = {}) {
|
|
|
18179
18467
|
const findingsBatch = makeBatcher("findings", 200, true);
|
|
18180
18468
|
const scanSecrets = isSecretScannerAvailable() && upload.findings && process.env.CHAT_RECALL_SCAN_SECRETS !== "0";
|
|
18181
18469
|
const verifySecretsScan = verifySecrets;
|
|
18470
|
+
let skipped = 0, redactions = 0, walked = 0;
|
|
18182
18471
|
const kgSeen = /* @__PURE__ */ new Set();
|
|
18183
18472
|
const kgEntityType = /* @__PURE__ */ new Map();
|
|
18184
|
-
const
|
|
18185
|
-
const
|
|
18473
|
+
const kgEntityNames = /* @__PURE__ */ new Set();
|
|
18474
|
+
const kgKey = (subject, predicate, object, validFrom) => createHash12("sha1").update(`${subject}|${predicate}|${object}|${validFrom}`).digest("hex").slice(0, 16);
|
|
18475
|
+
const accumulateKg = async (triples, sourceSession) => {
|
|
18186
18476
|
for (const t of triples) {
|
|
18187
|
-
const key =
|
|
18477
|
+
const key = kgKey(t.subject, t.predicate, t.object, t.validFrom ?? "");
|
|
18188
18478
|
if (kgSeen.has(key)) continue;
|
|
18189
18479
|
kgSeen.add(key);
|
|
18190
18480
|
if (t.predicate === "is_a" && !kgEntityType.has(t.subject)) kgEntityType.set(t.subject, t.object);
|
|
18191
|
-
|
|
18481
|
+
kgEntityNames.add(t.subject);
|
|
18482
|
+
kgEntityNames.add(t.object);
|
|
18483
|
+
const count = { redactions: 0 };
|
|
18484
|
+
await kgTripleBatch.add(redactDeep({
|
|
18192
18485
|
subject: t.subject,
|
|
18193
18486
|
predicate: t.predicate,
|
|
18194
18487
|
object: t.object,
|
|
@@ -18196,10 +18489,10 @@ async function syncToTarget(cred, opts = {}) {
|
|
|
18196
18489
|
valid_to: null,
|
|
18197
18490
|
confidence: t.confidence ?? 1,
|
|
18198
18491
|
source_session: sourceSession
|
|
18199
|
-
});
|
|
18492
|
+
}, count));
|
|
18493
|
+
redactions += count.redactions;
|
|
18200
18494
|
}
|
|
18201
18495
|
};
|
|
18202
|
-
let skipped = 0, redactions = 0, walked = 0;
|
|
18203
18496
|
let scanMs = 0, scanned = 0;
|
|
18204
18497
|
const slice = refs.slice(0, opts.limit ?? refs.length);
|
|
18205
18498
|
const trace = process.env.CHAT_RECALL_SYNC_TRACE === "1" ? (msg) => {
|
|
@@ -18332,7 +18625,7 @@ async function syncToTarget(cred, opts = {}) {
|
|
|
18332
18625
|
await convBatch.add(built.conv);
|
|
18333
18626
|
if (built.findings.length > 0) await findingsBatch.add(built.findings);
|
|
18334
18627
|
if (upload.sessionMeta) {
|
|
18335
|
-
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);
|
|
18628
|
+
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);
|
|
18336
18629
|
}
|
|
18337
18630
|
if (upload.sessionMeta && sessionFileBytes(ref) <= FULL_BUILD_MAX_BYTES) {
|
|
18338
18631
|
try {
|
|
@@ -18411,7 +18704,7 @@ async function syncToTarget(cred, opts = {}) {
|
|
|
18411
18704
|
chunks: redactedChunks
|
|
18412
18705
|
});
|
|
18413
18706
|
if (upload.sessionMeta && redactedChunks.length > 0) {
|
|
18414
|
-
accumulateKg(
|
|
18707
|
+
await accumulateKg(
|
|
18415
18708
|
extractEntities(redactedChunks.map((c) => c.text).join("\n"), { projectPath: item.projectPath || "", sourceType: item.sourceType, validFrom: item.mtime ? new Date(Number(item.mtime)).toISOString().slice(0, 10) : void 0 }),
|
|
18416
18709
|
null
|
|
18417
18710
|
);
|
|
@@ -18436,16 +18729,8 @@ async function syncToTarget(cred, opts = {}) {
|
|
|
18436
18729
|
}
|
|
18437
18730
|
}
|
|
18438
18731
|
}
|
|
18439
|
-
if (upload.sessionMeta &&
|
|
18440
|
-
const
|
|
18441
|
-
for (const t of kgRows) {
|
|
18442
|
-
const count = { redactions: 0 };
|
|
18443
|
-
await kgTripleBatch.add(redactDeep(t, count));
|
|
18444
|
-
redactions += count.redactions;
|
|
18445
|
-
entityNames.add(t.subject);
|
|
18446
|
-
entityNames.add(t.object);
|
|
18447
|
-
}
|
|
18448
|
-
for (const name of entityNames) {
|
|
18732
|
+
if (upload.sessionMeta && kgEntityNames.size > 0) {
|
|
18733
|
+
for (const name of kgEntityNames) {
|
|
18449
18734
|
const count = { redactions: 0 };
|
|
18450
18735
|
await kgEntityBatch.add(redactDeep({ name, type: kgEntityType.get(name) ?? "unknown", properties: {} }, count));
|
|
18451
18736
|
redactions += count.redactions;
|
|
@@ -18805,56 +19090,58 @@ function collectDerived(ref, mtime, count) {
|
|
|
18805
19090
|
const id = ref.prefixedId;
|
|
18806
19091
|
const compute = [];
|
|
18807
19092
|
let fullOutcome = null;
|
|
18808
|
-
|
|
18809
|
-
|
|
18810
|
-
|
|
18811
|
-
|
|
18812
|
-
|
|
18813
|
-
|
|
18814
|
-
|
|
18815
|
-
|
|
18816
|
-
|
|
18817
|
-
|
|
18818
|
-
if (
|
|
18819
|
-
|
|
18820
|
-
|
|
18821
|
-
|
|
18822
|
-
|
|
18823
|
-
|
|
18824
|
-
|
|
18825
|
-
|
|
18826
|
-
|
|
19093
|
+
return withSessionReadCache(() => {
|
|
19094
|
+
for (const kind of COMPUTE_KINDS) {
|
|
19095
|
+
let data = null;
|
|
19096
|
+
try {
|
|
19097
|
+
if (kind === "diff") {
|
|
19098
|
+
const replay = replaySessionAny(id);
|
|
19099
|
+
if (replay.found) data = replay;
|
|
19100
|
+
} else if (kind === "outcome") {
|
|
19101
|
+
fullOutcome = computeOutcome(id);
|
|
19102
|
+
if (fullOutcome.found) data = fullOutcome;
|
|
19103
|
+
} else if (kind === "commits") {
|
|
19104
|
+
if (!fullOutcome) fullOutcome = computeOutcome(id);
|
|
19105
|
+
if (fullOutcome.found) data = fullOutcome.commits;
|
|
19106
|
+
} else if (kind === "markers") {
|
|
19107
|
+
const turns = extractTurnsAny(id, { maxTurns: 5e4 });
|
|
19108
|
+
const prompts = turns.turns.filter((t) => t.kind === "user" && t.text).map((t) => ({ line: t.line, ts: t.ts, tsIso: t.tsIso, ...markPrompt(t.text) }));
|
|
19109
|
+
data = { sessionId: id, prompts, summary: summarizeMarkers(prompts) };
|
|
19110
|
+
}
|
|
19111
|
+
} catch {
|
|
19112
|
+
data = null;
|
|
19113
|
+
}
|
|
19114
|
+
if (data === null) continue;
|
|
19115
|
+
const redacted = redactDeep(data, count);
|
|
19116
|
+
if (JSON.stringify(redacted).length > MAX_DERIVED_ROW_BYTES) continue;
|
|
19117
|
+
compute.push({ kind, mtime, data: redacted });
|
|
19118
|
+
}
|
|
19119
|
+
let outcomeRow = null;
|
|
19120
|
+
if (fullOutcome?.found) {
|
|
19121
|
+
outcomeRow = {
|
|
19122
|
+
sessionId: id,
|
|
19123
|
+
tool: ref.toolId,
|
|
19124
|
+
status: fullOutcome.status,
|
|
19125
|
+
reason: fullOutcome.reason,
|
|
19126
|
+
fileMtime: mtime,
|
|
19127
|
+
fileSize: 0,
|
|
19128
|
+
contentHash: "",
|
|
19129
|
+
fileCount: fullOutcome.fileCount,
|
|
19130
|
+
linesAdded: fullOutcome.totalLinesAdded,
|
|
19131
|
+
linesRemoved: fullOutcome.totalLinesRemoved,
|
|
19132
|
+
commits: fullOutcome.commits?.totalCommits ?? 0,
|
|
19133
|
+
isFull: true,
|
|
19134
|
+
classifiedAt: Date.now(),
|
|
19135
|
+
lastScannedOffset: 0
|
|
19136
|
+
};
|
|
18827
19137
|
}
|
|
18828
|
-
|
|
18829
|
-
|
|
18830
|
-
|
|
18831
|
-
|
|
18832
|
-
|
|
18833
|
-
let outcomeRow = null;
|
|
18834
|
-
if (fullOutcome?.found) {
|
|
18835
|
-
outcomeRow = {
|
|
18836
|
-
sessionId: id,
|
|
18837
|
-
tool: ref.toolId,
|
|
18838
|
-
status: fullOutcome.status,
|
|
18839
|
-
reason: fullOutcome.reason,
|
|
18840
|
-
fileMtime: mtime,
|
|
18841
|
-
fileSize: 0,
|
|
18842
|
-
contentHash: "",
|
|
18843
|
-
fileCount: fullOutcome.fileCount,
|
|
18844
|
-
linesAdded: fullOutcome.totalLinesAdded,
|
|
18845
|
-
linesRemoved: fullOutcome.totalLinesRemoved,
|
|
18846
|
-
commits: fullOutcome.commits?.totalCommits ?? 0,
|
|
18847
|
-
isFull: true,
|
|
18848
|
-
classifiedAt: Date.now(),
|
|
18849
|
-
lastScannedOffset: 0
|
|
19138
|
+
return {
|
|
19139
|
+
session_id: id,
|
|
19140
|
+
mtime,
|
|
19141
|
+
compute,
|
|
19142
|
+
outcome_row: outcomeRow ? redactDeep({ ...outcomeRow, sessionId: void 0 }, count) : null
|
|
18850
19143
|
};
|
|
18851
|
-
}
|
|
18852
|
-
return {
|
|
18853
|
-
session_id: id,
|
|
18854
|
-
mtime,
|
|
18855
|
-
compute,
|
|
18856
|
-
outcome_row: outcomeRow ? redactDeep({ ...outcomeRow, sessionId: void 0 }, count) : null
|
|
18857
|
-
};
|
|
19144
|
+
});
|
|
18858
19145
|
}
|
|
18859
19146
|
function isSyncSkip(r) {
|
|
18860
19147
|
return typeof r.skipped === "string";
|
|
@@ -18883,10 +19170,11 @@ async function syncIncremental(opts = {}) {
|
|
|
18883
19170
|
lock.release();
|
|
18884
19171
|
}
|
|
18885
19172
|
}
|
|
18886
|
-
var ownVersion, credPath, _securityConfigCache, SECURITY_CONFIG_TTL_MS, _syncConfigCache, hashPath, COMPUTE_KINDS, MAX_DERIVED_ROW_BYTES, FULL_BUILD_MAX_BYTES, FULL_BUILD_TAIL_BYTES, BATCH_SCAN_MAX_BYTES;
|
|
19173
|
+
var ownVersion, credPath, _securityConfigCache, SECURITY_CONFIG_TTL_MS, _syncConfigCache, hashPath, COMPUTE_KINDS, MAX_DERIVED_ROW_BYTES, CAPS_TTL_MS, capsOk, FULL_BUILD_MAX_BYTES, FULL_BUILD_TAIL_BYTES, BATCH_SCAN_MAX_BYTES;
|
|
18887
19174
|
var init_sync_client = __esm({
|
|
18888
19175
|
"src/sync-client.ts"() {
|
|
18889
19176
|
"use strict";
|
|
19177
|
+
init_credentials_env();
|
|
18890
19178
|
init_secret_redactor();
|
|
18891
19179
|
init_source_discovery();
|
|
18892
19180
|
init_home_discovery();
|
|
@@ -18914,14 +19202,15 @@ var init_sync_client = __esm({
|
|
|
18914
19202
|
init_sync_fields();
|
|
18915
19203
|
init_index_lock();
|
|
18916
19204
|
init_http();
|
|
19205
|
+
init_live_session_scan();
|
|
18917
19206
|
init_backends();
|
|
18918
19207
|
ownVersion = "0.0.0";
|
|
18919
19208
|
try {
|
|
18920
19209
|
const dir = dirname16(fileURLToPath(import.meta.url));
|
|
18921
|
-
ownVersion = JSON.parse(
|
|
19210
|
+
ownVersion = JSON.parse(readFileSync32(join40(dir, "../package.json"), "utf-8")).version || ownVersion;
|
|
18922
19211
|
} catch {
|
|
18923
19212
|
try {
|
|
18924
|
-
if (true) ownVersion = "0.5.
|
|
19213
|
+
if (true) ownVersion = "0.5.6";
|
|
18925
19214
|
} catch {
|
|
18926
19215
|
}
|
|
18927
19216
|
}
|
|
@@ -18932,6 +19221,8 @@ var init_sync_client = __esm({
|
|
|
18932
19221
|
hashPath = (p) => p ? "p_" + createHash12("sha256").update(p).digest("hex").slice(0, 12) : "";
|
|
18933
19222
|
COMPUTE_KINDS = ["diff", "outcome", "commits", "markers"];
|
|
18934
19223
|
MAX_DERIVED_ROW_BYTES = 2 * 1024 * 1024;
|
|
19224
|
+
CAPS_TTL_MS = 60 * 6e4;
|
|
19225
|
+
capsOk = /* @__PURE__ */ new Map();
|
|
18935
19226
|
FULL_BUILD_MAX_BYTES = Math.max(8, parseInt(process.env.CHAT_RECALL_FULL_BUILD_MAX_MB || "64", 10)) * 1024 * 1024;
|
|
18936
19227
|
FULL_BUILD_TAIL_BYTES = 16 * 1024 * 1024;
|
|
18937
19228
|
BATCH_SCAN_MAX_BYTES = Math.max(1, parseInt(process.env.CHAT_RECALL_BATCHSCAN_MAX_MB || "64", 10)) * 1024 * 1024;
|
|
@@ -18988,11 +19279,11 @@ async function repairSession(id, opts = {}) {
|
|
|
18988
19279
|
const log6 = (m) => {
|
|
18989
19280
|
if (opts.verbose) console.error(` [repair ${id}] ${m}`);
|
|
18990
19281
|
};
|
|
18991
|
-
const
|
|
19282
|
+
const candidates2 = [];
|
|
18992
19283
|
const localShadow = readShadowContainer(tool, rawId);
|
|
18993
19284
|
if (localShadow) {
|
|
18994
19285
|
try {
|
|
18995
|
-
|
|
19286
|
+
candidates2.push({ container: localShadow, messages: parseTranscriptFromContainer(localShadow).messages.length, source: "local-shadow" });
|
|
18996
19287
|
} catch {
|
|
18997
19288
|
}
|
|
18998
19289
|
}
|
|
@@ -19004,15 +19295,15 @@ async function repairSession(id, opts = {}) {
|
|
|
19004
19295
|
if (arch?.gzB64) {
|
|
19005
19296
|
try {
|
|
19006
19297
|
const container = gunzipContainer(Buffer.from(arch.gzB64, "base64"));
|
|
19007
|
-
if (container)
|
|
19298
|
+
if (container) candidates2.push({ container, messages: parseTranscriptFromContainer(container).messages.length, source: ep.url });
|
|
19008
19299
|
} catch {
|
|
19009
19300
|
}
|
|
19010
19301
|
}
|
|
19011
19302
|
}
|
|
19012
|
-
if (
|
|
19303
|
+
if (candidates2.length === 0) {
|
|
19013
19304
|
return { sessionId: id, status: "no-archive", fullestMessages: 0, fullestSource: "", pushed: [], note: "no shadow or server archive found" };
|
|
19014
19305
|
}
|
|
19015
|
-
const fullest =
|
|
19306
|
+
const fullest = candidates2.reduce((a, b) => b.messages > a.messages ? b : a);
|
|
19016
19307
|
log6(`fullest archive = ${fullest.messages} msg(s) from ${fullest.source}`);
|
|
19017
19308
|
if (opts.dryRun) {
|
|
19018
19309
|
const needy2 = endpoints.filter((ep) => (currentOnServer.get(ep.url) ?? 0) < fullest.messages || opts.force);
|
|
@@ -19114,7 +19405,7 @@ async function repairAll(opts = {}) {
|
|
|
19114
19405
|
if (!page?.hasMore || sessions.length === 0) break;
|
|
19115
19406
|
}
|
|
19116
19407
|
log6(`window=${sinceHours}h \u2192 ${ids.length} session(s) to check on ${primary.url}`);
|
|
19117
|
-
const
|
|
19408
|
+
const candidates2 = [];
|
|
19118
19409
|
let scanned = 0;
|
|
19119
19410
|
for (const id of ids) {
|
|
19120
19411
|
scanned++;
|
|
@@ -19127,9 +19418,9 @@ async function repairAll(opts = {}) {
|
|
|
19127
19418
|
if (archiveMsgs <= current) continue;
|
|
19128
19419
|
const r = await repairSession(id, { dryRun: !opts.apply, verbose: opts.verbose, server: opts.server });
|
|
19129
19420
|
if (r.status === "already-full") continue;
|
|
19130
|
-
|
|
19421
|
+
candidates2.push(r);
|
|
19131
19422
|
}
|
|
19132
|
-
return { scanned, candidates, discoveryServer: primary.url };
|
|
19423
|
+
return { scanned, candidates: candidates2, discoveryServer: primary.url };
|
|
19133
19424
|
}
|
|
19134
19425
|
var hashPath2;
|
|
19135
19426
|
var init_repair = __esm({
|
|
@@ -19145,23 +19436,93 @@ var init_repair = __esm({
|
|
|
19145
19436
|
}
|
|
19146
19437
|
});
|
|
19147
19438
|
|
|
19439
|
+
// ../engine/dist/core/which.js
|
|
19440
|
+
import { existsSync as existsSync43, statSync as statSync38, accessSync, constants } from "node:fs";
|
|
19441
|
+
import { join as join46, isAbsolute as isAbsolute2, delimiter as delimiter2, sep as sep2 } from "node:path";
|
|
19442
|
+
function executable(p) {
|
|
19443
|
+
try {
|
|
19444
|
+
if (!statSync38(p).isFile())
|
|
19445
|
+
return false;
|
|
19446
|
+
} catch {
|
|
19447
|
+
return false;
|
|
19448
|
+
}
|
|
19449
|
+
if (isWindows)
|
|
19450
|
+
return true;
|
|
19451
|
+
try {
|
|
19452
|
+
accessSync(p, constants.X_OK);
|
|
19453
|
+
return true;
|
|
19454
|
+
} catch {
|
|
19455
|
+
return false;
|
|
19456
|
+
}
|
|
19457
|
+
}
|
|
19458
|
+
function candidates(name) {
|
|
19459
|
+
if (!isWindows)
|
|
19460
|
+
return [name];
|
|
19461
|
+
const exts = (process.env.PATHEXT || ".COM;.EXE;.BAT;.CMD").split(";").map((e) => e.trim()).filter(Boolean);
|
|
19462
|
+
if (exts.some((e) => name.toLowerCase().endsWith(e.toLowerCase())))
|
|
19463
|
+
return [name];
|
|
19464
|
+
return exts.map((e) => name + e);
|
|
19465
|
+
}
|
|
19466
|
+
function resolveOnPath(name) {
|
|
19467
|
+
if (!name)
|
|
19468
|
+
return null;
|
|
19469
|
+
if (name.includes("/") || isWindows && name.includes(sep2) || isAbsolute2(name)) {
|
|
19470
|
+
for (const c of candidates(name))
|
|
19471
|
+
if (executable(c))
|
|
19472
|
+
return c;
|
|
19473
|
+
return null;
|
|
19474
|
+
}
|
|
19475
|
+
for (const raw of (process.env.PATH || "").split(delimiter2)) {
|
|
19476
|
+
const dir = raw.replace(/^"(.*)"$/, "$1");
|
|
19477
|
+
if (!dir)
|
|
19478
|
+
continue;
|
|
19479
|
+
for (const c of candidates(name)) {
|
|
19480
|
+
const full = join46(dir, c);
|
|
19481
|
+
if (existsSync43(full) && executable(full))
|
|
19482
|
+
return full;
|
|
19483
|
+
}
|
|
19484
|
+
}
|
|
19485
|
+
return null;
|
|
19486
|
+
}
|
|
19487
|
+
function isOnPath(name) {
|
|
19488
|
+
return resolveOnPath(name) !== null;
|
|
19489
|
+
}
|
|
19490
|
+
var isWindows;
|
|
19491
|
+
var init_which = __esm({
|
|
19492
|
+
"../engine/dist/core/which.js"() {
|
|
19493
|
+
"use strict";
|
|
19494
|
+
isWindows = process.platform === "win32";
|
|
19495
|
+
}
|
|
19496
|
+
});
|
|
19497
|
+
|
|
19148
19498
|
// ../engine/dist/core/companions.js
|
|
19149
|
-
import { existsSync as
|
|
19499
|
+
import { existsSync as existsSync44, mkdirSync as mkdirSync13, statSync as statSync39, chmodSync as chmodSync4, unlinkSync as unlinkSync3, renameSync as renameSync5, createWriteStream, readFileSync as readFileSync38, writeFileSync as writeFileSync13 } from "node:fs";
|
|
19150
19500
|
import { homedir as homedir19 } from "node:os";
|
|
19151
|
-
import { join as
|
|
19501
|
+
import { join as join47 } from "node:path";
|
|
19152
19502
|
import { execSync as execSync3 } from "node:child_process";
|
|
19503
|
+
import { createHash as createHash14 } from "node:crypto";
|
|
19504
|
+
function expectedCodeindexSha256(artifact) {
|
|
19505
|
+
return CODEINDEX_SHA256[artifact.replace(/^codeindex-/, "").replace(/\.exe$/, "")] ?? null;
|
|
19506
|
+
}
|
|
19153
19507
|
function detectPlatform() {
|
|
19154
19508
|
const arch = process.arch;
|
|
19155
19509
|
const platform = process.platform;
|
|
19156
19510
|
const archMap = { x64: "x86_64", arm64: "aarch64" };
|
|
19157
|
-
const platformMap = { linux: "linux", darwin: "
|
|
19511
|
+
const platformMap = { linux: "linux", darwin: "macos", win32: "windows" };
|
|
19158
19512
|
const a = archMap[arch];
|
|
19159
19513
|
const p = platformMap[platform];
|
|
19160
19514
|
if (!a || !p) {
|
|
19161
19515
|
return { reason: `Unsupported platform: ${arch}-${platform}` };
|
|
19162
19516
|
}
|
|
19163
|
-
const prebuiltCombos = /* @__PURE__ */ new Set([
|
|
19164
|
-
|
|
19517
|
+
const prebuiltCombos = /* @__PURE__ */ new Set([
|
|
19518
|
+
"x86_64-linux",
|
|
19519
|
+
"aarch64-linux",
|
|
19520
|
+
"x86_64-macos",
|
|
19521
|
+
"aarch64-macos",
|
|
19522
|
+
"x86_64-windows",
|
|
19523
|
+
"aarch64-windows"
|
|
19524
|
+
]);
|
|
19525
|
+
const artifact = `codeindex-${a}-${p}${p === "windows" ? ".exe" : ""}`;
|
|
19165
19526
|
if (!prebuiltCombos.has(`${a}-${p}`)) {
|
|
19166
19527
|
return {
|
|
19167
19528
|
artifact,
|
|
@@ -19178,20 +19539,15 @@ function checkCodeindexStatus() {
|
|
|
19178
19539
|
artifactName: platform.artifact,
|
|
19179
19540
|
unsupportedReason: platform.reason
|
|
19180
19541
|
};
|
|
19181
|
-
let foundPath =
|
|
19182
|
-
|
|
19183
|
-
|
|
19184
|
-
if (out)
|
|
19185
|
-
foundPath = out;
|
|
19186
|
-
} catch {
|
|
19542
|
+
let foundPath = resolveOnPath(CODEINDEX_BIN_NAME);
|
|
19543
|
+
if (!foundPath) {
|
|
19544
|
+
foundPath = resolveOnPath(CODEINDEX_BIN_PATH);
|
|
19187
19545
|
}
|
|
19188
|
-
if (!foundPath && existsSync43(CODEINDEX_BIN_PATH))
|
|
19189
|
-
foundPath = CODEINDEX_BIN_PATH;
|
|
19190
19546
|
if (foundPath) {
|
|
19191
19547
|
status.installed = true;
|
|
19192
19548
|
status.path = foundPath;
|
|
19193
19549
|
try {
|
|
19194
|
-
status.size =
|
|
19550
|
+
status.size = statSync39(foundPath).size;
|
|
19195
19551
|
} catch {
|
|
19196
19552
|
}
|
|
19197
19553
|
try {
|
|
@@ -19203,16 +19559,9 @@ function checkCodeindexStatus() {
|
|
|
19203
19559
|
return status;
|
|
19204
19560
|
}
|
|
19205
19561
|
async function downloadArtifact(artifact, dest) {
|
|
19206
|
-
const hasGh = (
|
|
19207
|
-
try {
|
|
19208
|
-
execSync3("command -v gh", { stdio: "ignore" });
|
|
19209
|
-
return true;
|
|
19210
|
-
} catch {
|
|
19211
|
-
return false;
|
|
19212
|
-
}
|
|
19213
|
-
})();
|
|
19562
|
+
const hasGh = isOnPath("gh");
|
|
19214
19563
|
if (hasGh) {
|
|
19215
|
-
execSync3(`gh release download ${CODEINDEX_VERSION} --repo ${CODEINDEX_REPO} -p ${artifact} -O ${dest}`, {
|
|
19564
|
+
execSync3(`gh release download ${CODEINDEX_VERSION} --repo ${CODEINDEX_REPO} -p ${artifact} -O "${dest}"`, {
|
|
19216
19565
|
stdio: ["ignore", "pipe", "pipe"],
|
|
19217
19566
|
timeout: 6e4
|
|
19218
19567
|
});
|
|
@@ -19225,7 +19574,7 @@ async function downloadArtifact(artifact, dest) {
|
|
|
19225
19574
|
if (!res.body)
|
|
19226
19575
|
throw new Error("Download returned empty body");
|
|
19227
19576
|
const file = createWriteStream(dest);
|
|
19228
|
-
await new Promise((
|
|
19577
|
+
await new Promise((resolve3, reject) => {
|
|
19229
19578
|
const reader = res.body.getReader();
|
|
19230
19579
|
const pump = async () => {
|
|
19231
19580
|
try {
|
|
@@ -19236,7 +19585,7 @@ async function downloadArtifact(artifact, dest) {
|
|
|
19236
19585
|
file.write(value);
|
|
19237
19586
|
}
|
|
19238
19587
|
file.end();
|
|
19239
|
-
file.on("finish", () =>
|
|
19588
|
+
file.on("finish", () => resolve3());
|
|
19240
19589
|
file.on("error", reject);
|
|
19241
19590
|
} catch (e) {
|
|
19242
19591
|
reject(e);
|
|
@@ -19251,15 +19600,26 @@ async function installCodeindex(opts = {}) {
|
|
|
19251
19600
|
return status;
|
|
19252
19601
|
if (!status.prebuiltAvailable)
|
|
19253
19602
|
return status;
|
|
19254
|
-
|
|
19603
|
+
mkdirSync13(CODEINDEX_INSTALL_DIR, { recursive: true });
|
|
19255
19604
|
const tmpPath = `${CODEINDEX_BIN_PATH}.partial`;
|
|
19256
19605
|
try {
|
|
19257
19606
|
await downloadArtifact(status.artifactName, tmpPath);
|
|
19607
|
+
const expected = expectedCodeindexSha256(status.artifactName);
|
|
19608
|
+
if (!expected) {
|
|
19609
|
+
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.`);
|
|
19610
|
+
}
|
|
19611
|
+
const actual = createHash14("sha256").update(readFileSync38(tmpPath)).digest("hex");
|
|
19612
|
+
if (actual !== expected) {
|
|
19613
|
+
throw new Error(`Checksum mismatch for ${status.artifactName}.
|
|
19614
|
+
expected ${expected}
|
|
19615
|
+
actual ${actual}
|
|
19616
|
+
Refusing to install. The release may have been re-uploaded, or something is serving different bytes.`);
|
|
19617
|
+
}
|
|
19258
19618
|
chmodSync4(tmpPath, 493);
|
|
19259
19619
|
renameSync5(tmpPath, CODEINDEX_BIN_PATH);
|
|
19260
19620
|
} catch (err) {
|
|
19261
19621
|
try {
|
|
19262
|
-
if (
|
|
19622
|
+
if (existsSync44(tmpPath))
|
|
19263
19623
|
unlinkSync3(tmpPath);
|
|
19264
19624
|
} catch {
|
|
19265
19625
|
}
|
|
@@ -19267,15 +19627,24 @@ async function installCodeindex(opts = {}) {
|
|
|
19267
19627
|
}
|
|
19268
19628
|
return checkCodeindexStatus();
|
|
19269
19629
|
}
|
|
19270
|
-
var CODEINDEX_REPO, CODEINDEX_VERSION, CODEINDEX_INSTALL_DIR, CODEINDEX_BIN_NAME, CODEINDEX_BIN_PATH;
|
|
19630
|
+
var CODEINDEX_REPO, CODEINDEX_VERSION, CODEINDEX_SHA256, CODEINDEX_INSTALL_DIR, CODEINDEX_BIN_NAME, CODEINDEX_BIN_PATH;
|
|
19271
19631
|
var init_companions = __esm({
|
|
19272
19632
|
"../engine/dist/core/companions.js"() {
|
|
19273
19633
|
"use strict";
|
|
19634
|
+
init_which();
|
|
19274
19635
|
CODEINDEX_REPO = "munhq/codeindex";
|
|
19275
|
-
CODEINDEX_VERSION = "v0.1
|
|
19276
|
-
|
|
19277
|
-
|
|
19278
|
-
|
|
19636
|
+
CODEINDEX_VERSION = "v0.3.1";
|
|
19637
|
+
CODEINDEX_SHA256 = {
|
|
19638
|
+
"x86_64-linux": "4378f12e7c80fa8bb53e41c02db4b95955f2f878369abfb28b5edd94b4adbb85",
|
|
19639
|
+
"aarch64-linux": "5a1d6c9c2592a3721547c42cd9b6b11f460e903bfc46407ae27d5879e7259587",
|
|
19640
|
+
"x86_64-macos": "6ad2a2b40faa4ec72ac35fee84f35ea7c848cddc4f6382b4cafedb644f30389f",
|
|
19641
|
+
"aarch64-macos": "f366d00918f79a4a0acc09c6091d97c6c378c79edbdbe3cb22e4014ea57f08d2",
|
|
19642
|
+
"x86_64-windows": "a96fc8c8949bb399a44cc0615b12e458460a529c69f01e8829cc39a20f45ab29",
|
|
19643
|
+
"aarch64-windows": "42620d56272cd9ba9d785569d8d754d6b4a3e80f36f28db3e0c483fd600ed117"
|
|
19644
|
+
};
|
|
19645
|
+
CODEINDEX_INSTALL_DIR = join47(homedir19(), ".local", "bin");
|
|
19646
|
+
CODEINDEX_BIN_NAME = process.platform === "win32" ? "codeindex.exe" : "codeindex";
|
|
19647
|
+
CODEINDEX_BIN_PATH = join47(CODEINDEX_INSTALL_DIR, CODEINDEX_BIN_NAME);
|
|
19279
19648
|
}
|
|
19280
19649
|
});
|
|
19281
19650
|
|
|
@@ -19381,7 +19750,9 @@ var init_prompts = __esm({
|
|
|
19381
19750
|
var collector_exports = {};
|
|
19382
19751
|
__export(collector_exports, {
|
|
19383
19752
|
COLLECTOR_VERSION: () => COLLECTOR_VERSION,
|
|
19753
|
+
GENERATED_PATTERNS: () => GENERATED_PATTERNS,
|
|
19384
19754
|
collectCode: () => collectCode,
|
|
19755
|
+
isGenerated: () => isGenerated,
|
|
19385
19756
|
isJunkWorkspacePath: () => isJunkWorkspacePath,
|
|
19386
19757
|
isSecretRule: () => isSecretRule,
|
|
19387
19758
|
resolveCodeindexBin: () => resolveCodeindexBin
|
|
@@ -19389,7 +19760,7 @@ __export(collector_exports, {
|
|
|
19389
19760
|
import { spawn as spawn2 } from "node:child_process";
|
|
19390
19761
|
import { execSync as execSync4 } from "node:child_process";
|
|
19391
19762
|
import { readFileSync as readFileSync39 } from "node:fs";
|
|
19392
|
-
import { join as
|
|
19763
|
+
import { join as join48, basename as basename24 } from "node:path";
|
|
19393
19764
|
async function resolveCodeindexBin(autoInstall = true) {
|
|
19394
19765
|
let st = checkCodeindexStatus();
|
|
19395
19766
|
if (!st.installed && autoInstall)
|
|
@@ -19400,7 +19771,7 @@ async function resolveCodeindexBin(autoInstall = true) {
|
|
|
19400
19771
|
return st.path;
|
|
19401
19772
|
}
|
|
19402
19773
|
function runMcp(binPath, workspace, calls, timeoutMs = 18e4) {
|
|
19403
|
-
return new Promise((
|
|
19774
|
+
return new Promise((resolve3, reject) => {
|
|
19404
19775
|
const p = spawn2(binPath, ["--mcp", "--workspace", workspace], { stdio: ["pipe", "pipe", "ignore"] });
|
|
19405
19776
|
let out = "";
|
|
19406
19777
|
const timer = setTimeout(() => {
|
|
@@ -19443,7 +19814,7 @@ function runMcp(binPath, workspace, calls, timeoutMs = 18e4) {
|
|
|
19443
19814
|
if (m?.id != null && typeof text === "string")
|
|
19444
19815
|
res.set(Number(m.id), text);
|
|
19445
19816
|
}
|
|
19446
|
-
|
|
19817
|
+
resolve3(res);
|
|
19447
19818
|
});
|
|
19448
19819
|
p.stdin.write(calls.map((c) => JSON.stringify(c) + "\n").join(""));
|
|
19449
19820
|
p.stdin.end();
|
|
@@ -19476,10 +19847,11 @@ function isSecretRule(rule) {
|
|
|
19476
19847
|
return /secret|password|credential|key|token|auth/i.test(rule);
|
|
19477
19848
|
}
|
|
19478
19849
|
function isJunkWorkspacePath(ws) {
|
|
19479
|
-
|
|
19850
|
+
const norm = ws.replace(/\\/g, "/");
|
|
19851
|
+
return /(^|\/)(scratchpad|\.cache|node_modules|\.git|tmp)(\/|$)|claude-1000/i.test(norm);
|
|
19480
19852
|
}
|
|
19481
19853
|
async function collectCode(opts) {
|
|
19482
|
-
const ws = opts.workspace.replace(
|
|
19854
|
+
const ws = opts.workspace.replace(/[/\\]+$/, "");
|
|
19483
19855
|
const log6 = opts.log ?? (() => {
|
|
19484
19856
|
});
|
|
19485
19857
|
if (isJunkWorkspacePath(ws)) {
|
|
@@ -19487,9 +19859,11 @@ async function collectCode(opts) {
|
|
|
19487
19859
|
}
|
|
19488
19860
|
const bin = opts.binPath ?? await resolveCodeindexBin(opts.autoInstall ?? true);
|
|
19489
19861
|
const projectId = resolveProjectId(ws).id || `path:${ws}`;
|
|
19490
|
-
const
|
|
19862
|
+
const wsNorm = ws.replace(/\\/g, "/");
|
|
19863
|
+
const wsPrefix = wsNorm + "/";
|
|
19491
19864
|
const rel = (p) => {
|
|
19492
|
-
|
|
19865
|
+
const n = p.replace(/\\/g, "/");
|
|
19866
|
+
let r = n.startsWith(wsPrefix) ? n.slice(wsPrefix.length) : n;
|
|
19493
19867
|
if (r.startsWith("./"))
|
|
19494
19868
|
r = r.slice(2);
|
|
19495
19869
|
return r;
|
|
@@ -19550,7 +19924,7 @@ async function collectCode(opts) {
|
|
|
19550
19924
|
}
|
|
19551
19925
|
const complexity = (r) => {
|
|
19552
19926
|
try {
|
|
19553
|
-
const txt = readFileSync39(
|
|
19927
|
+
const txt = readFileSync39(join48(ws, r), "utf8");
|
|
19554
19928
|
if (txt.length > 2e6)
|
|
19555
19929
|
return 1;
|
|
19556
19930
|
const m = txt.match(CF_RE);
|
|
@@ -20134,7 +20508,7 @@ async function collectCode(opts) {
|
|
|
20134
20508
|
void health;
|
|
20135
20509
|
return { project, findings, hotspots, actions };
|
|
20136
20510
|
}
|
|
20137
|
-
var COLLECTOR_VERSION, ANALYSES, GENERATED, CF_RE, DEPTH, MCP_OUT_MAX_BYTES, call, COMMON_SYMBOL_NAMES;
|
|
20511
|
+
var COLLECTOR_VERSION, ANALYSES, GENERATED, CF_RE, DEPTH, MCP_OUT_MAX_BYTES, call, GENERATED_PATTERNS, COMMON_SYMBOL_NAMES;
|
|
20138
20512
|
var init_collector = __esm({
|
|
20139
20513
|
"../engine/dist/core/code/collector.js"() {
|
|
20140
20514
|
"use strict";
|
|
@@ -20176,7 +20550,13 @@ var init_collector = __esm({
|
|
|
20176
20550
|
"/vendor/",
|
|
20177
20551
|
"/third_party/",
|
|
20178
20552
|
"/site-packages/",
|
|
20553
|
+
// Lockfiles. '.lock' alone catches yarn.lock, Cargo.lock, poetry.lock and
|
|
20554
|
+
// composer.lock, and MISSES the two biggest ones in a JS repo —
|
|
20555
|
+
// package-lock.json and pnpm-lock.yaml are named '-lock.<ext>'. Found by
|
|
20556
|
+
// replacing this file's mirror test with one that calls the real predicate.
|
|
20179
20557
|
".lock",
|
|
20558
|
+
"-lock.json",
|
|
20559
|
+
"-lock.yaml",
|
|
20180
20560
|
"/dist/",
|
|
20181
20561
|
"/build/",
|
|
20182
20562
|
"/out/",
|
|
@@ -20193,6 +20573,7 @@ var init_collector = __esm({
|
|
|
20193
20573
|
DEPTH = 2;
|
|
20194
20574
|
MCP_OUT_MAX_BYTES = 64 * 1024 * 1024;
|
|
20195
20575
|
call = (id, name, args = {}) => ({ jsonrpc: "2.0", id, method: "tools/call", params: { name, arguments: args } });
|
|
20576
|
+
GENERATED_PATTERNS = GENERATED;
|
|
20196
20577
|
COMMON_SYMBOL_NAMES = /* @__PURE__ */ new Set([
|
|
20197
20578
|
"error",
|
|
20198
20579
|
"err",
|
|
@@ -20264,12 +20645,13 @@ init_settings();
|
|
|
20264
20645
|
init_sync_client();
|
|
20265
20646
|
init_http();
|
|
20266
20647
|
import chokidar from "chokidar";
|
|
20267
|
-
import { dirname as
|
|
20648
|
+
import { dirname as dirname21, basename as basename25, join as join49, resolve as resolve2, sep as sep3 } from "path";
|
|
20649
|
+
import { homedir as homedir20 } from "os";
|
|
20268
20650
|
|
|
20269
20651
|
// src/intent-drain.ts
|
|
20270
20652
|
init_http();
|
|
20271
20653
|
init_sync_client();
|
|
20272
|
-
import { existsSync as existsSync41, readFileSync as
|
|
20654
|
+
import { existsSync as existsSync41, readFileSync as readFileSync36, writeFileSync as writeFileSync11, appendFileSync, mkdirSync as mkdirSync11 } from "node:fs";
|
|
20273
20655
|
import { join as join44 } from "node:path";
|
|
20274
20656
|
import { homedir as homedir18 } from "node:os";
|
|
20275
20657
|
|
|
@@ -20279,7 +20661,7 @@ init_gemini2();
|
|
|
20279
20661
|
init_opencode();
|
|
20280
20662
|
init_codex2();
|
|
20281
20663
|
init_agy();
|
|
20282
|
-
import { existsSync as existsSync39, mkdirSync as mkdirSync9, readFileSync as
|
|
20664
|
+
import { existsSync as existsSync39, mkdirSync as mkdirSync9, readFileSync as readFileSync34, writeFileSync as writeFileSync9, cpSync } from "fs";
|
|
20283
20665
|
import { dirname as dirname17, join as join42, basename as basename23 } from "path";
|
|
20284
20666
|
import { homedir as homedir16 } from "os";
|
|
20285
20667
|
|
|
@@ -20290,11 +20672,11 @@ init_opencode();
|
|
|
20290
20672
|
init_codex2();
|
|
20291
20673
|
init_agy();
|
|
20292
20674
|
init_toolkit_format();
|
|
20293
|
-
import { readFileSync as
|
|
20675
|
+
import { readFileSync as readFileSync33 } from "fs";
|
|
20294
20676
|
import { join as join41 } from "path";
|
|
20295
20677
|
import { homedir as homedir15 } from "os";
|
|
20296
20678
|
function readCommand(filePath, format) {
|
|
20297
|
-
const content =
|
|
20679
|
+
const content = readFileSync33(filePath, "utf-8");
|
|
20298
20680
|
if (format === "toml") {
|
|
20299
20681
|
const t = parseScalarToml(content);
|
|
20300
20682
|
return { name: t.name || base(filePath), description: t.description || "", body: t.prompt || "" };
|
|
@@ -20303,7 +20685,7 @@ function readCommand(filePath, format) {
|
|
|
20303
20685
|
return { name: fm.name || base(filePath), description: fm.description || "", body: body.trim() };
|
|
20304
20686
|
}
|
|
20305
20687
|
function readAgent(filePath, format) {
|
|
20306
|
-
const content =
|
|
20688
|
+
const content = readFileSync33(filePath, "utf-8");
|
|
20307
20689
|
if (format === "toml") {
|
|
20308
20690
|
const t = parseScalarToml(content);
|
|
20309
20691
|
return {
|
|
@@ -20316,7 +20698,7 @@ function readAgent(filePath, format) {
|
|
|
20316
20698
|
return { name: fm.name || base(filePath), description: fm.description || "", tools: fm.tools, body: body.trim() };
|
|
20317
20699
|
}
|
|
20318
20700
|
function readInstructions(filePath, name) {
|
|
20319
|
-
const content =
|
|
20701
|
+
const content = readFileSync33(filePath, "utf-8");
|
|
20320
20702
|
return { name, description: "", body: content };
|
|
20321
20703
|
}
|
|
20322
20704
|
function commandPath(tool, name) {
|
|
@@ -20503,7 +20885,7 @@ function readMcpEntry(tool, name) {
|
|
|
20503
20885
|
if (!existsSync39(t.path))
|
|
20504
20886
|
continue;
|
|
20505
20887
|
try {
|
|
20506
|
-
const cfg = JSON.parse(
|
|
20888
|
+
const cfg = JSON.parse(readFileSync34(t.path, "utf-8"));
|
|
20507
20889
|
const block = cfg[t.key] || {};
|
|
20508
20890
|
if (block[name])
|
|
20509
20891
|
return block[name];
|
|
@@ -20517,7 +20899,7 @@ function readCodexMcpEntry(path, target) {
|
|
|
20517
20899
|
return null;
|
|
20518
20900
|
let content;
|
|
20519
20901
|
try {
|
|
20520
|
-
content =
|
|
20902
|
+
content = readFileSync34(path, "utf-8");
|
|
20521
20903
|
} catch {
|
|
20522
20904
|
return null;
|
|
20523
20905
|
}
|
|
@@ -20568,7 +20950,7 @@ function readCodexMcpEntry(path, target) {
|
|
|
20568
20950
|
function writeCodexMcpEntry(path, name, entry) {
|
|
20569
20951
|
let content = "";
|
|
20570
20952
|
if (existsSync39(path))
|
|
20571
|
-
content =
|
|
20953
|
+
content = readFileSync34(path, "utf-8");
|
|
20572
20954
|
const header = `[mcp_servers.${name}]`;
|
|
20573
20955
|
if (content.includes(header))
|
|
20574
20956
|
return false;
|
|
@@ -20627,7 +21009,7 @@ function writeMcpEntry(toTool, name, entry) {
|
|
|
20627
21009
|
let cfg = {};
|
|
20628
21010
|
if (existsSync39(path)) {
|
|
20629
21011
|
try {
|
|
20630
|
-
cfg = JSON.parse(
|
|
21012
|
+
cfg = JSON.parse(readFileSync34(path, "utf-8"));
|
|
20631
21013
|
} catch {
|
|
20632
21014
|
return { ok: false, status: 500, error: `Target config is malformed: ${path}` };
|
|
20633
21015
|
}
|
|
@@ -20814,7 +21196,7 @@ async function executeCopy(type, name, fromTool, toTool) {
|
|
|
20814
21196
|
|
|
20815
21197
|
// src/project-tasks.ts
|
|
20816
21198
|
init_http();
|
|
20817
|
-
import { existsSync as existsSync40, readFileSync as
|
|
21199
|
+
import { existsSync as existsSync40, readFileSync as readFileSync35, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10, statSync as statSync36 } from "node:fs";
|
|
20818
21200
|
import { join as join43, dirname as dirname18 } from "node:path";
|
|
20819
21201
|
import { homedir as homedir17 } from "node:os";
|
|
20820
21202
|
|
|
@@ -20831,7 +21213,7 @@ function isCodeTaskStatus(v) {
|
|
|
20831
21213
|
}
|
|
20832
21214
|
|
|
20833
21215
|
// src/project-tasks.ts
|
|
20834
|
-
var TEAM_STATUSES = /* @__PURE__ */ new Set(["todo", "in_progress", "
|
|
21216
|
+
var TEAM_STATUSES = /* @__PURE__ */ new Set(["todo", "in_progress", "done", "rejected"]);
|
|
20835
21217
|
function isTeamTaskStatus(v) {
|
|
20836
21218
|
return !!v && TEAM_STATUSES.has(v);
|
|
20837
21219
|
}
|
|
@@ -20849,7 +21231,7 @@ function reconcile(kind, was, token, checked) {
|
|
|
20849
21231
|
const done = kind === "secret" ? "rotated" : "done";
|
|
20850
21232
|
if (token && token !== was) return token;
|
|
20851
21233
|
if (kind === "team") {
|
|
20852
|
-
if (checked && was
|
|
21234
|
+
if (checked && was === "todo") return "in_progress";
|
|
20853
21235
|
if (!checked && was === "done") return "todo";
|
|
20854
21236
|
return token ?? was;
|
|
20855
21237
|
}
|
|
@@ -20888,7 +21270,7 @@ function ledgerPath2() {
|
|
|
20888
21270
|
}
|
|
20889
21271
|
function readLedger() {
|
|
20890
21272
|
try {
|
|
20891
|
-
return JSON.parse(
|
|
21273
|
+
return JSON.parse(readFileSync35(ledgerPath2(), "utf8"));
|
|
20892
21274
|
} catch {
|
|
20893
21275
|
return {};
|
|
20894
21276
|
}
|
|
@@ -20932,7 +21314,7 @@ async function pushProjectTaskStatuses(base2, authHeaders, opts = {}) {
|
|
|
20932
21314
|
if (ledger[file] === mtime) continue;
|
|
20933
21315
|
let changed;
|
|
20934
21316
|
try {
|
|
20935
|
-
changed = parseTaskFile(
|
|
21317
|
+
changed = parseTaskFile(readFileSync35(file, "utf8")).filter((t) => t.kind === fk.kind);
|
|
20936
21318
|
} catch {
|
|
20937
21319
|
continue;
|
|
20938
21320
|
}
|
|
@@ -20989,7 +21371,7 @@ function applyCodeRecommendation(intent) {
|
|
|
20989
21371
|
if (!meta.rootPath) return { status: "error", result: JSON.stringify({ error: "missing rootPath" }) };
|
|
20990
21372
|
file = join44(meta.rootPath, "CLAUDE.md");
|
|
20991
21373
|
}
|
|
20992
|
-
const existing = existsSync41(file) ?
|
|
21374
|
+
const existing = existsSync41(file) ? readFileSync36(file, "utf8") : "";
|
|
20993
21375
|
if (existing.includes(text)) return { status: "done", result: JSON.stringify({ skipped: "rule already present", file }) };
|
|
20994
21376
|
const block = `${existing && !existing.endsWith("\n") ? "\n" : ""}
|
|
20995
21377
|
## Rule (added by chat-recall recommendation)
|
|
@@ -21035,10 +21417,10 @@ async function runIntent(intent, ctx) {
|
|
|
21035
21417
|
var ownVersion2 = "0.0.0";
|
|
21036
21418
|
try {
|
|
21037
21419
|
const dir = dirname19(fileURLToPath2(import.meta.url));
|
|
21038
|
-
ownVersion2 = JSON.parse(
|
|
21420
|
+
ownVersion2 = JSON.parse(readFileSync36(join44(dir, "../package.json"), "utf-8")).version || ownVersion2;
|
|
21039
21421
|
} catch {
|
|
21040
21422
|
try {
|
|
21041
|
-
if (true) ownVersion2 = "0.5.
|
|
21423
|
+
if (true) ownVersion2 = "0.5.6";
|
|
21042
21424
|
} catch {
|
|
21043
21425
|
}
|
|
21044
21426
|
}
|
|
@@ -21212,8 +21594,37 @@ async function runCollectorMigration(opts) {
|
|
|
21212
21594
|
}
|
|
21213
21595
|
|
|
21214
21596
|
// auto-indexer/indexer.ts
|
|
21215
|
-
|
|
21216
|
-
|
|
21597
|
+
init_sync_ledger();
|
|
21598
|
+
import { existsSync as existsSync45, readFileSync as readFileSync40, statSync as statSync40, renameSync as renameSync6, unlinkSync as unlinkSync4 } from "fs";
|
|
21599
|
+
|
|
21600
|
+
// ../engine/dist/core/collector-health.js
|
|
21601
|
+
init_paths();
|
|
21602
|
+
import { readFileSync as readFileSync37, writeFileSync as writeFileSync12, mkdirSync as mkdirSync12 } from "node:fs";
|
|
21603
|
+
import { join as join45, dirname as dirname20 } from "node:path";
|
|
21604
|
+
var healthPath = () => join45(getDataDir(), "collector-health.json");
|
|
21605
|
+
function collectorHealthPath() {
|
|
21606
|
+
return healthPath();
|
|
21607
|
+
}
|
|
21608
|
+
function readCollectorHealth() {
|
|
21609
|
+
try {
|
|
21610
|
+
const h = JSON.parse(readFileSync37(healthPath(), "utf-8"));
|
|
21611
|
+
return h && h.v === 1 && typeof h.updatedAt === "number" ? h : null;
|
|
21612
|
+
} catch {
|
|
21613
|
+
return null;
|
|
21614
|
+
}
|
|
21615
|
+
}
|
|
21616
|
+
function writeCollectorHealth(h) {
|
|
21617
|
+
try {
|
|
21618
|
+
const p = healthPath();
|
|
21619
|
+
mkdirSync12(dirname20(p), { recursive: true });
|
|
21620
|
+
writeFileSync12(p, JSON.stringify(h));
|
|
21621
|
+
} catch {
|
|
21622
|
+
}
|
|
21623
|
+
}
|
|
21624
|
+
var STALE_AFTER_MS = 30 * 6e4;
|
|
21625
|
+
|
|
21626
|
+
// auto-indexer/indexer.ts
|
|
21627
|
+
var CLI_VERSION3 = true ? "0.5.6" : "0.0.0";
|
|
21217
21628
|
var DEBOUNCE_MS = 5e3;
|
|
21218
21629
|
function ts() {
|
|
21219
21630
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -21226,9 +21637,9 @@ var DIARY_DIR = getDiaryDir();
|
|
|
21226
21637
|
var CODEX_SESSIONS_DIR = codexBackend.sessionsDir();
|
|
21227
21638
|
var GEMINI_TMP_DIR = geminiBackend.tmpDir();
|
|
21228
21639
|
var OPENCODE_DB_PATH = opencodeBackend.dbPath();
|
|
21229
|
-
var OPENCODE_DB_DIR =
|
|
21230
|
-
var CURRENT_RESUME_PATH =
|
|
21231
|
-
var LAST_CLEANUP_PATH =
|
|
21640
|
+
var OPENCODE_DB_DIR = dirname21(OPENCODE_DB_PATH);
|
|
21641
|
+
var CURRENT_RESUME_PATH = join49(claudeBackend.homeDir(), "current-resume");
|
|
21642
|
+
var LAST_CLEANUP_PATH = join49(claudeBackend.homeDir(), ".last-cleanup");
|
|
21232
21643
|
var debounceTimer = null;
|
|
21233
21644
|
var syncInFlight = false;
|
|
21234
21645
|
var pendingFileCount = 0;
|
|
@@ -21250,9 +21661,11 @@ async function shipToServer(trigger) {
|
|
|
21250
21661
|
`[${ts()}] Sync (${trigger}): ${result.uploaded} session(s) pushed, ${result.redactions} secret(s) redacted, ${result.skipped} skipped, ${result.items} items, ${result.links} links, ${result.derived} derived, ${result.kgEntities} KG entities, ${result.kgTriples} KG triples`
|
|
21251
21662
|
);
|
|
21252
21663
|
}
|
|
21664
|
+
for (const server of syncTargetUrls()) noteSyncOutcome(server, true);
|
|
21253
21665
|
} catch (err) {
|
|
21254
21666
|
const msg = err instanceof Error ? err.message : String(err);
|
|
21255
21667
|
console.error(`[${ts()}] Sync failed (${trigger}, will retry next flush): ${msg.slice(0, 200)}`);
|
|
21668
|
+
for (const server of syncTargetUrls()) noteSyncOutcome(server, false, msg);
|
|
21256
21669
|
} finally {
|
|
21257
21670
|
syncInFlight = false;
|
|
21258
21671
|
}
|
|
@@ -21280,39 +21693,58 @@ async function onResumeSignal(path) {
|
|
|
21280
21693
|
lastResumeAt.set(id, now);
|
|
21281
21694
|
const { snapshotShadow: snapshotShadow2 } = await Promise.resolve().then(() => (init_transcript(), transcript_exports));
|
|
21282
21695
|
const r = await snapshotShadow2(id);
|
|
21696
|
+
if (r.status === "skipped") return;
|
|
21283
21697
|
console.log(`[${ts()}] [resume-guard] shadow ${r.status} for ${id.slice(0, 8)}\u2026` + (r.recovered > 0 ? ` (recovered ${r.recovered} record(s))` : ""));
|
|
21284
21698
|
} catch (e) {
|
|
21285
21699
|
console.error(`[${ts()}] [resume-guard] ${e instanceof Error ? e.message : e}`);
|
|
21286
21700
|
}
|
|
21287
21701
|
}
|
|
21288
|
-
var
|
|
21289
|
-
|
|
21702
|
+
var FORCE_POLL = process.env.CHAT_RECALL_WATCH_POLL === "1";
|
|
21703
|
+
var POLL = (interval) => FORCE_POLL ? { usePolling: true, interval } : {};
|
|
21704
|
+
var watchOpts = (t, poll = FORCE_POLL) => ({
|
|
21290
21705
|
persistent: true,
|
|
21291
|
-
ignoreInitial: true,
|
|
21292
|
-
|
|
21293
|
-
interval:
|
|
21294
|
-
|
|
21706
|
+
ignoreInitial: t.ignoreInitial ?? true,
|
|
21707
|
+
...t.ignored ? { ignored: t.ignored } : {},
|
|
21708
|
+
...poll ? { usePolling: true, interval: t.interval } : {}
|
|
21709
|
+
});
|
|
21710
|
+
function watchWithFallback(name, pattern, t) {
|
|
21711
|
+
let w = chokidar.watch(pattern, watchOpts(t));
|
|
21712
|
+
let swapped = false;
|
|
21713
|
+
w.on("error", (err) => {
|
|
21714
|
+
const code = err?.code;
|
|
21715
|
+
if (swapped || FORCE_POLL || code !== "ENOSPC" && code !== "EMFILE") {
|
|
21716
|
+
console.error(`[${ts()}] ${name} watcher error: ${String(err)}`);
|
|
21717
|
+
return;
|
|
21718
|
+
}
|
|
21719
|
+
swapped = true;
|
|
21720
|
+
console.log(`[${ts()}] ${name} watcher: native watching hit ${code} \u2014 falling back to polling every ${t.interval}ms. Raise fs.inotify.max_user_watches to get native events back.`);
|
|
21721
|
+
void w.close().catch(() => {
|
|
21722
|
+
});
|
|
21723
|
+
w = chokidar.watch(pattern, watchOpts(t, true));
|
|
21724
|
+
});
|
|
21725
|
+
return w;
|
|
21726
|
+
}
|
|
21727
|
+
var sessionWatcher = watchWithFallback("sessions", `${CLAUDE_DIR}/**/*.jsonl`, {
|
|
21728
|
+
ignored: (p) => /agent-/.test(p) || /^\./.test(basename25(p)),
|
|
21729
|
+
interval: 5e3
|
|
21295
21730
|
});
|
|
21296
21731
|
var plansWatcher = chokidar.watch(`${PLANS_DIR}/*.md`, {
|
|
21297
21732
|
persistent: true,
|
|
21298
21733
|
ignoreInitial: true,
|
|
21299
21734
|
awaitWriteFinish: { stabilityThreshold: 1e3, pollInterval: 100 },
|
|
21300
|
-
|
|
21301
|
-
interval: 1e4
|
|
21735
|
+
...POLL(1e4)
|
|
21302
21736
|
});
|
|
21303
21737
|
var tasksWatcher = chokidar.watch(`${TASKS_DIR}/**/*.json`, {
|
|
21304
21738
|
persistent: true,
|
|
21305
21739
|
ignoreInitial: true,
|
|
21306
21740
|
awaitWriteFinish: { stabilityThreshold: 1e3, pollInterval: 100 },
|
|
21307
|
-
|
|
21308
|
-
interval: 1e4
|
|
21741
|
+
...POLL(1e4)
|
|
21309
21742
|
});
|
|
21310
21743
|
var historyWatcher = chokidar.watch(HISTORY_PATH, {
|
|
21311
21744
|
persistent: true,
|
|
21312
21745
|
ignoreInitial: true,
|
|
21313
21746
|
awaitWriteFinish: { stabilityThreshold: 2e3, pollInterval: 500 },
|
|
21314
|
-
|
|
21315
|
-
interval: 3e4
|
|
21747
|
+
...POLL(3e4)
|
|
21316
21748
|
// check less frequently
|
|
21317
21749
|
});
|
|
21318
21750
|
var diaryWatcher = chokidar.watch(`${DIARY_DIR}/**/*.json`, {
|
|
@@ -21326,15 +21758,13 @@ var codexWatcher = chokidar.watch(`${CODEX_SESSIONS_DIR}/**/rollout-*.jsonl`, {
|
|
|
21326
21758
|
// Codex rolls every event into its own JSONL line — wait for ~2s of
|
|
21327
21759
|
// write quiescence so we don't ship mid-write.
|
|
21328
21760
|
awaitWriteFinish: { stabilityThreshold: 2e3, pollInterval: 200 },
|
|
21329
|
-
|
|
21330
|
-
interval: 5e3
|
|
21761
|
+
...POLL(5e3)
|
|
21331
21762
|
});
|
|
21332
21763
|
var geminiWatcher = chokidar.watch(`${GEMINI_TMP_DIR}/**/session-*.json`, {
|
|
21333
21764
|
persistent: true,
|
|
21334
21765
|
ignoreInitial: true,
|
|
21335
21766
|
awaitWriteFinish: { stabilityThreshold: 1500, pollInterval: 200 },
|
|
21336
|
-
|
|
21337
|
-
interval: 5e3
|
|
21767
|
+
...POLL(5e3)
|
|
21338
21768
|
});
|
|
21339
21769
|
var opencodeWatcher = chokidar.watch(
|
|
21340
21770
|
[`${OPENCODE_DB_PATH}`, `${OPENCODE_DB_PATH}-wal`],
|
|
@@ -21342,23 +21772,20 @@ var opencodeWatcher = chokidar.watch(
|
|
|
21342
21772
|
persistent: true,
|
|
21343
21773
|
ignoreInitial: true,
|
|
21344
21774
|
awaitWriteFinish: { stabilityThreshold: 2500, pollInterval: 500 },
|
|
21345
|
-
|
|
21346
|
-
interval: 1e4
|
|
21775
|
+
...POLL(1e4)
|
|
21347
21776
|
}
|
|
21348
21777
|
);
|
|
21349
21778
|
var agentMemoryWatcher = chokidar.watch(`${CLAUDE_DIR}/*/memory/*.md`, {
|
|
21350
21779
|
persistent: true,
|
|
21351
21780
|
ignoreInitial: true,
|
|
21352
21781
|
awaitWriteFinish: { stabilityThreshold: 1e3, pollInterval: 100 },
|
|
21353
|
-
|
|
21354
|
-
interval: 1e4
|
|
21782
|
+
...POLL(1e4)
|
|
21355
21783
|
});
|
|
21356
21784
|
var cleanupWatcher = chokidar.watch(LAST_CLEANUP_PATH, {
|
|
21357
21785
|
persistent: true,
|
|
21358
21786
|
ignoreInitial: true,
|
|
21359
21787
|
awaitWriteFinish: { stabilityThreshold: 1e3, pollInterval: 200 },
|
|
21360
|
-
|
|
21361
|
-
interval: 3e4
|
|
21788
|
+
...POLL(3e4)
|
|
21362
21789
|
});
|
|
21363
21790
|
var watchers = {
|
|
21364
21791
|
sessions: sessionWatcher,
|
|
@@ -21372,12 +21799,10 @@ var watchers = {
|
|
|
21372
21799
|
agentMemory: agentMemoryWatcher,
|
|
21373
21800
|
cleanup: cleanupWatcher
|
|
21374
21801
|
};
|
|
21375
|
-
var resumeWatcher = chokidar.watch(CURRENT_RESUME_PATH, {
|
|
21376
|
-
|
|
21377
|
-
ignoreInitial: false
|
|
21378
|
-
|
|
21379
|
-
interval: 1e3
|
|
21380
|
-
});
|
|
21802
|
+
var resumeWatcher = chokidar.watch(CURRENT_RESUME_PATH, watchOpts({
|
|
21803
|
+
interval: 1e3,
|
|
21804
|
+
ignoreInitial: false
|
|
21805
|
+
}));
|
|
21381
21806
|
resumeWatcher.on("add", (p) => {
|
|
21382
21807
|
void onResumeSignal(p);
|
|
21383
21808
|
}).on("change", (p) => {
|
|
@@ -21421,9 +21846,71 @@ var BOOT_CODE = codeFingerprint();
|
|
|
21421
21846
|
if (BOOT_CODE) {
|
|
21422
21847
|
console.log(`[${ts()}] running bundle ${BOOT_CODE.path} (${BOOT_CODE.size} bytes)`);
|
|
21423
21848
|
}
|
|
21849
|
+
function rotateLogIfLarge() {
|
|
21850
|
+
const LOG_MAX_BYTES = 32 * 1024 * 1024;
|
|
21851
|
+
try {
|
|
21852
|
+
const logPath = join49(getDataDir(), "watch.log");
|
|
21853
|
+
const st = statSync40(logPath);
|
|
21854
|
+
if (st.size < LOG_MAX_BYTES) return;
|
|
21855
|
+
const prev = `${logPath}.1`;
|
|
21856
|
+
try {
|
|
21857
|
+
unlinkSync4(prev);
|
|
21858
|
+
} catch {
|
|
21859
|
+
}
|
|
21860
|
+
renameSync6(logPath, prev);
|
|
21861
|
+
console.log(`[${ts()}] rotated watch.log at ${(st.size / 1048576).toFixed(0)}MB \u2192 watch.log.1`);
|
|
21862
|
+
} catch {
|
|
21863
|
+
}
|
|
21864
|
+
}
|
|
21865
|
+
rotateLogIfLarge();
|
|
21866
|
+
var PROC_START = Date.now();
|
|
21867
|
+
var targetHealth = {};
|
|
21868
|
+
function recentStarts() {
|
|
21869
|
+
const prior = readCollectorHealth();
|
|
21870
|
+
const cutoff = Date.now() - 36e5;
|
|
21871
|
+
return [...prior?.starts ?? [], PROC_START].filter((t) => typeof t === "number" && t > cutoff).filter((t, i, a) => a.indexOf(t) === i).sort((a, b) => a - b).slice(-20);
|
|
21872
|
+
}
|
|
21873
|
+
function publishHealth() {
|
|
21874
|
+
const starts = recentStarts();
|
|
21875
|
+
writeCollectorHealth(Object.assign({
|
|
21876
|
+
v: 1,
|
|
21877
|
+
updatedAt: Date.now(),
|
|
21878
|
+
startedAt: PROC_START,
|
|
21879
|
+
restartsLastHour: starts.length,
|
|
21880
|
+
targets: targetHealth
|
|
21881
|
+
}, { starts }));
|
|
21882
|
+
}
|
|
21883
|
+
function syncTargetUrls() {
|
|
21884
|
+
try {
|
|
21885
|
+
return loadAllCredentials().map((c) => c.serverUrl);
|
|
21886
|
+
} catch {
|
|
21887
|
+
return [];
|
|
21888
|
+
}
|
|
21889
|
+
}
|
|
21890
|
+
function noteSyncOutcome(server, ok, err) {
|
|
21891
|
+
const t = targetHealth[server] ?? { lastOkAt: null, failures: 0 };
|
|
21892
|
+
if (ok) {
|
|
21893
|
+
t.lastOkAt = Date.now();
|
|
21894
|
+
t.failures = 0;
|
|
21895
|
+
delete t.lastError;
|
|
21896
|
+
} else {
|
|
21897
|
+
t.failures += 1;
|
|
21898
|
+
t.lastError = (err ?? "unknown error").slice(0, 160);
|
|
21899
|
+
}
|
|
21900
|
+
targetHealth[server] = t;
|
|
21901
|
+
publishHealth();
|
|
21902
|
+
}
|
|
21903
|
+
publishHealth();
|
|
21904
|
+
{
|
|
21905
|
+
const n = recentStarts().length;
|
|
21906
|
+
if (n >= 3) {
|
|
21907
|
+
console.error(`[${ts()}] WARNING: this collector has restarted ${n} times in the last hour. Sync is probably falling behind. Health: ${collectorHealthPath()}`);
|
|
21908
|
+
}
|
|
21909
|
+
}
|
|
21424
21910
|
setInterval(() => {
|
|
21425
21911
|
if (checkSelfRestart({ boot: BOOT_CODE, log: (m) => console.log(`[${ts()}] ${m}`) })) return;
|
|
21426
21912
|
console.log(`[${ts()}] Heartbeat - ${pendingFileCount} pending file event(s), sync ${syncInFlight ? "in-flight" : "idle"}`);
|
|
21913
|
+
publishHealth();
|
|
21427
21914
|
}, 6e4);
|
|
21428
21915
|
var intentDrainInFlight = false;
|
|
21429
21916
|
var intentDrainStartedAt = 0;
|
|
@@ -21432,7 +21919,7 @@ var DRAIN_STALL_MS = 5 * 6e4;
|
|
|
21432
21919
|
async function drainIntentsTick() {
|
|
21433
21920
|
if (intentDrainInFlight) {
|
|
21434
21921
|
const stuckMs = Date.now() - intentDrainStartedAt;
|
|
21435
|
-
if (stuckMs < DRAIN_STALL_MS) return;
|
|
21922
|
+
if (stuckMs < DRAIN_STALL_MS) return false;
|
|
21436
21923
|
console.error(`[${ts()}] sync-intents: previous drain has been running ${Math.round(stuckMs / 1e3)}s \u2014 abandoning it and starting a fresh tick`);
|
|
21437
21924
|
}
|
|
21438
21925
|
intentDrainInFlight = true;
|
|
@@ -21444,18 +21931,28 @@ async function drainIntentsTick() {
|
|
|
21444
21931
|
console.log(`[${ts()}] sync-intents: ${r.done} done, ${r.errored} errored`);
|
|
21445
21932
|
if (r.done > 0) await shipToServer("intent-applied");
|
|
21446
21933
|
}
|
|
21934
|
+
return r.processed > 0;
|
|
21447
21935
|
} catch (err) {
|
|
21448
21936
|
console.error(`[${ts()}] sync-intents drain failed: ${err instanceof Error ? err.message : err}`);
|
|
21937
|
+
return false;
|
|
21449
21938
|
} finally {
|
|
21450
21939
|
if (gen === intentDrainGeneration) intentDrainInFlight = false;
|
|
21451
21940
|
}
|
|
21452
21941
|
}
|
|
21453
|
-
|
|
21454
|
-
|
|
21455
|
-
|
|
21456
|
-
|
|
21457
|
-
|
|
21458
|
-
|
|
21942
|
+
var INTENT_POLL_MIN_MS = 15e3;
|
|
21943
|
+
var INTENT_POLL_MAX_MS = 5 * 6e4;
|
|
21944
|
+
var intentPollMs = INTENT_POLL_MIN_MS;
|
|
21945
|
+
var intentTimer = null;
|
|
21946
|
+
function scheduleIntentPoll(ms) {
|
|
21947
|
+
if (intentTimer) clearTimeout(intentTimer);
|
|
21948
|
+
intentTimer = setTimeout(async () => {
|
|
21949
|
+
const found = await drainIntentsTick();
|
|
21950
|
+
intentPollMs = found ? INTENT_POLL_MIN_MS : Math.min(intentPollMs * 2, INTENT_POLL_MAX_MS);
|
|
21951
|
+
scheduleIntentPoll(intentPollMs);
|
|
21952
|
+
}, ms);
|
|
21953
|
+
intentTimer.unref?.();
|
|
21954
|
+
}
|
|
21955
|
+
scheduleIntentPoll(5e3);
|
|
21459
21956
|
var CODE_INDEX_ON = process.env.CHAT_RECALL_CODE_INDEX !== "0";
|
|
21460
21957
|
var CODE_INDEX_MS = Math.max(15, parseInt(process.env.CHAT_RECALL_CODE_INDEX_MINUTES || "180", 10)) * 60 * 1e3;
|
|
21461
21958
|
var CODE_INDEX_MAX = Math.max(1, parseInt(process.env.CHAT_RECALL_CODE_INDEX_MAX || "50", 10));
|
|
@@ -21491,13 +21988,45 @@ function discoverWorkspaces() {
|
|
|
21491
21988
|
} catch {
|
|
21492
21989
|
}
|
|
21493
21990
|
const isExcluded = (p) => excluded.some((x) => p.includes(x));
|
|
21494
|
-
|
|
21991
|
+
const candidates2 = [...newest.entries()].filter(([p]) => !isExcluded(p)).filter(([p]) => !isPersonalPath(p, includeProjects)).filter(([p]) => {
|
|
21495
21992
|
try {
|
|
21496
|
-
return
|
|
21993
|
+
return existsSync45(p);
|
|
21497
21994
|
} catch {
|
|
21498
21995
|
return false;
|
|
21499
21996
|
}
|
|
21500
|
-
}).sort((a, b) => b[1] - a[1])
|
|
21997
|
+
}).filter(([p]) => isCodeWorkspace(p)).sort((a, b) => b[1] - a[1]);
|
|
21998
|
+
const roots = candidates2.map(([p]) => p);
|
|
21999
|
+
const notAnAncestor = ([p]) => !roots.some((other) => other !== p && other.startsWith(p.endsWith(sep3) ? p : p + sep3));
|
|
22000
|
+
return candidates2.filter(notAnAncestor).slice(0, CODE_INDEX_MAX).map(([p]) => p);
|
|
22001
|
+
}
|
|
22002
|
+
var WORKSPACE_MARKERS = [
|
|
22003
|
+
".git",
|
|
22004
|
+
"package.json",
|
|
22005
|
+
"go.mod",
|
|
22006
|
+
"Cargo.toml",
|
|
22007
|
+
"pyproject.toml",
|
|
22008
|
+
"setup.py",
|
|
22009
|
+
"pom.xml",
|
|
22010
|
+
"build.gradle",
|
|
22011
|
+
"composer.json",
|
|
22012
|
+
"Gemfile",
|
|
22013
|
+
"mix.exs",
|
|
22014
|
+
"deno.json"
|
|
22015
|
+
];
|
|
22016
|
+
function isCodeWorkspace(p) {
|
|
22017
|
+
try {
|
|
22018
|
+
const resolved = resolve2(p);
|
|
22019
|
+
if (resolved === sep3 || resolved === homedir20() || dirname21(resolved) === resolved) return false;
|
|
22020
|
+
} catch {
|
|
22021
|
+
return false;
|
|
22022
|
+
}
|
|
22023
|
+
return WORKSPACE_MARKERS.some((m) => {
|
|
22024
|
+
try {
|
|
22025
|
+
return existsSync45(join49(p, m));
|
|
22026
|
+
} catch {
|
|
22027
|
+
return false;
|
|
22028
|
+
}
|
|
22029
|
+
});
|
|
21501
22030
|
}
|
|
21502
22031
|
async function codeIndexTick() {
|
|
21503
22032
|
if (codeIndexInFlight) return;
|
|
@@ -21602,6 +22131,11 @@ if (CODE_INDEX_ON) setTimeout(() => {
|
|
|
21602
22131
|
}, 15e4);
|
|
21603
22132
|
function shutdown(signal) {
|
|
21604
22133
|
console.log(`[${ts()}] Received ${signal}, shutting down...`);
|
|
22134
|
+
try {
|
|
22135
|
+
flushLedger();
|
|
22136
|
+
} catch (e) {
|
|
22137
|
+
console.error(`[${ts()}] ledger flush on shutdown failed: ${String(e)}`);
|
|
22138
|
+
}
|
|
21605
22139
|
for (const watcher of Object.values(watchers)) {
|
|
21606
22140
|
void watcher.close();
|
|
21607
22141
|
}
|
|
@@ -21610,3 +22144,13 @@ function shutdown(signal) {
|
|
|
21610
22144
|
}
|
|
21611
22145
|
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
|
21612
22146
|
process.on("SIGINT", () => shutdown("SIGINT"));
|
|
22147
|
+
if (process.platform === "win32") {
|
|
22148
|
+
process.on("SIGBREAK", () => shutdown("SIGBREAK"));
|
|
22149
|
+
process.on("SIGHUP", () => shutdown("SIGHUP"));
|
|
22150
|
+
}
|
|
22151
|
+
process.on("exit", () => {
|
|
22152
|
+
try {
|
|
22153
|
+
flushLedger();
|
|
22154
|
+
} catch {
|
|
22155
|
+
}
|
|
22156
|
+
});
|