chat-recall 0.7.13 → 0.7.15
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 +371 -307
- package/dist/hostile-server.d.ts.map +1 -1
- package/dist/hostile-server.js +10 -1
- package/dist/hostile-server.js.map +1 -1
- package/dist/mcp-relay.js +1 -1
- package/dist/mcp.js +278 -214
- package/dist/scan-worker.js +23 -24
- package/dist/sync-ledger.d.ts.map +1 -1
- package/dist/sync-ledger.js +112 -17
- package/dist/sync-ledger.js.map +1 -1
- package/dist/watch.js +320 -254
- package/package.json +1 -1
package/dist/watch.js
CHANGED
|
@@ -4458,7 +4458,7 @@ var require_pino = __commonJS({
|
|
|
4458
4458
|
messageKey,
|
|
4459
4459
|
errorKey,
|
|
4460
4460
|
nestedKey,
|
|
4461
|
-
base:
|
|
4461
|
+
base: base3,
|
|
4462
4462
|
name,
|
|
4463
4463
|
level: level2,
|
|
4464
4464
|
customLevels,
|
|
@@ -4497,11 +4497,11 @@ var require_pino = __commonJS({
|
|
|
4497
4497
|
[formattersSym]: allFormatters
|
|
4498
4498
|
});
|
|
4499
4499
|
let chindings = "";
|
|
4500
|
-
if (
|
|
4500
|
+
if (base3 !== null) {
|
|
4501
4501
|
if (name === void 0) {
|
|
4502
|
-
chindings = coreChindings(
|
|
4502
|
+
chindings = coreChindings(base3);
|
|
4503
4503
|
} else {
|
|
4504
|
-
chindings = coreChindings(Object.assign({},
|
|
4504
|
+
chindings = coreChindings(Object.assign({}, base3, { name }));
|
|
4505
4505
|
}
|
|
4506
4506
|
}
|
|
4507
4507
|
const time2 = timestamp instanceof Function ? timestamp : timestamp ? epochTime : nullTime;
|
|
@@ -4881,57 +4881,57 @@ function freshDefaults() {
|
|
|
4881
4881
|
team: defaultTeam()
|
|
4882
4882
|
};
|
|
4883
4883
|
}
|
|
4884
|
-
function mergeSources(
|
|
4884
|
+
function mergeSources(base3, partial) {
|
|
4885
4885
|
if (!partial)
|
|
4886
|
-
return
|
|
4886
|
+
return base3;
|
|
4887
4887
|
const legacyGemini = partial.enabled?.gemini;
|
|
4888
4888
|
const inherited = legacyGemini && typeof legacyGemini === "object" ? (({ sessions: _s, plans: _p, ...rest }) => rest)(legacyGemini) : {};
|
|
4889
4889
|
const enabled = {
|
|
4890
|
-
claude: { ...
|
|
4891
|
-
opencode: { ...
|
|
4892
|
-
codex: { ...
|
|
4893
|
-
agy: { ...
|
|
4894
|
-
cursor: { ...
|
|
4895
|
-
shared: { ...
|
|
4896
|
-
common: { ...
|
|
4890
|
+
claude: { ...base3.enabled.claude, ...partial.enabled?.claude ?? {} },
|
|
4891
|
+
opencode: { ...base3.enabled.opencode, ...partial.enabled?.opencode ?? {} },
|
|
4892
|
+
codex: { ...base3.enabled.codex, ...partial.enabled?.codex ?? {} },
|
|
4893
|
+
agy: { ...base3.enabled.agy, ...inherited, ...partial.enabled?.agy ?? {} },
|
|
4894
|
+
cursor: { ...base3.enabled.cursor, ...partial.enabled?.cursor ?? {} },
|
|
4895
|
+
shared: { ...base3.enabled.shared, ...partial.enabled?.shared ?? {} },
|
|
4896
|
+
common: { ...base3.enabled.common, ...partial.enabled?.common ?? {} }
|
|
4897
4897
|
};
|
|
4898
4898
|
return {
|
|
4899
|
-
claudeHome: partial.claudeHome ??
|
|
4900
|
-
geminiHome: partial.geminiHome ??
|
|
4901
|
-
codexHome: partial.codexHome ??
|
|
4902
|
-
opencodeDbPath: partial.opencodeDbPath ??
|
|
4903
|
-
agyHome: partial.agyHome ??
|
|
4904
|
-
cursorHome: partial.cursorHome ??
|
|
4905
|
-
cursorIdeHome: partial.cursorIdeHome ??
|
|
4906
|
-
extraClaudeHomes: partial.extraClaudeHomes ??
|
|
4907
|
-
approvedHomes: partial.approvedHomes ??
|
|
4908
|
-
declinedHomes: partial.declinedHomes ??
|
|
4909
|
-
homesGrandfathered: partial.homesGrandfathered ??
|
|
4899
|
+
claudeHome: partial.claudeHome ?? base3.claudeHome,
|
|
4900
|
+
geminiHome: partial.geminiHome ?? base3.geminiHome,
|
|
4901
|
+
codexHome: partial.codexHome ?? base3.codexHome,
|
|
4902
|
+
opencodeDbPath: partial.opencodeDbPath ?? base3.opencodeDbPath,
|
|
4903
|
+
agyHome: partial.agyHome ?? base3.agyHome,
|
|
4904
|
+
cursorHome: partial.cursorHome ?? base3.cursorHome,
|
|
4905
|
+
cursorIdeHome: partial.cursorIdeHome ?? base3.cursorIdeHome,
|
|
4906
|
+
extraClaudeHomes: partial.extraClaudeHomes ?? base3.extraClaudeHomes,
|
|
4907
|
+
approvedHomes: partial.approvedHomes ?? base3.approvedHomes,
|
|
4908
|
+
declinedHomes: partial.declinedHomes ?? base3.declinedHomes,
|
|
4909
|
+
homesGrandfathered: partial.homesGrandfathered ?? base3.homesGrandfathered,
|
|
4910
4910
|
enabled
|
|
4911
4911
|
};
|
|
4912
4912
|
}
|
|
4913
|
-
function mergePrivacy(
|
|
4913
|
+
function mergePrivacy(base3, partial) {
|
|
4914
4914
|
if (!partial)
|
|
4915
|
-
return
|
|
4916
|
-
return { ...
|
|
4915
|
+
return base3;
|
|
4916
|
+
return { ...base3, ...partial };
|
|
4917
4917
|
}
|
|
4918
|
-
function mergeSync(
|
|
4918
|
+
function mergeSync(base3, partial) {
|
|
4919
4919
|
if (!partial)
|
|
4920
|
-
return
|
|
4920
|
+
return base3;
|
|
4921
4921
|
return {
|
|
4922
|
-
...
|
|
4922
|
+
...base3,
|
|
4923
4923
|
...partial,
|
|
4924
|
-
upload: { ...
|
|
4924
|
+
upload: { ...base3.upload, ...partial.upload ?? {} }
|
|
4925
4925
|
};
|
|
4926
4926
|
}
|
|
4927
|
-
function mergeTeam(
|
|
4927
|
+
function mergeTeam(base3, partial) {
|
|
4928
4928
|
if (!partial)
|
|
4929
|
-
return
|
|
4929
|
+
return base3;
|
|
4930
4930
|
return {
|
|
4931
|
-
...
|
|
4931
|
+
...base3,
|
|
4932
4932
|
...partial,
|
|
4933
|
-
publishAllowed: { ...
|
|
4934
|
-
vault: { ...
|
|
4933
|
+
publishAllowed: { ...base3.publishAllowed, ...partial.publishAllowed ?? {} },
|
|
4934
|
+
vault: { ...base3.vault, ...partial.vault ?? {} }
|
|
4935
4935
|
};
|
|
4936
4936
|
}
|
|
4937
4937
|
function settingsFilePath() {
|
|
@@ -5040,15 +5040,15 @@ function loadSettings() {
|
|
|
5040
5040
|
}
|
|
5041
5041
|
try {
|
|
5042
5042
|
const parsed = JSON.parse(readFileSync(path, "utf-8"));
|
|
5043
|
-
const
|
|
5043
|
+
const base3 = freshDefaults();
|
|
5044
5044
|
const result = {
|
|
5045
5045
|
v: SCHEMA_VERSION,
|
|
5046
|
-
embedding: { ...
|
|
5047
|
-
summary: { ...
|
|
5048
|
-
sources: mergeSources(
|
|
5049
|
-
privacy: mergePrivacy(
|
|
5050
|
-
sync: mergeSync(
|
|
5051
|
-
team: mergeTeam(
|
|
5046
|
+
embedding: { ...base3.embedding, ...parsed.embedding ?? {} },
|
|
5047
|
+
summary: { ...base3.summary, ...parsed.summary ?? {} },
|
|
5048
|
+
sources: mergeSources(base3.sources, parsed.sources),
|
|
5049
|
+
privacy: mergePrivacy(base3.privacy, parsed.privacy),
|
|
5050
|
+
sync: mergeSync(base3.sync, parsed.sync),
|
|
5051
|
+
team: mergeTeam(base3.team, parsed.team)
|
|
5052
5052
|
};
|
|
5053
5053
|
if (mtimeMs >= 0)
|
|
5054
5054
|
_settingsCache = { mtimeMs, size, value: structuredClone(result) };
|
|
@@ -5154,10 +5154,10 @@ function legacyAutoSyncedHomes() {
|
|
|
5154
5154
|
{ base: join3(home, ".local", "share", "opencode"), marker: "opencode.db" },
|
|
5155
5155
|
{ base: join3(home, ".cursor"), marker: "chats" }
|
|
5156
5156
|
];
|
|
5157
|
-
for (const { base:
|
|
5158
|
-
add(
|
|
5159
|
-
const parent = dirname3(
|
|
5160
|
-
const leaf =
|
|
5157
|
+
for (const { base: base3, marker } of bases) {
|
|
5158
|
+
add(base3, marker);
|
|
5159
|
+
const parent = dirname3(base3);
|
|
5160
|
+
const leaf = base3.slice(parent.length + 1);
|
|
5161
5161
|
try {
|
|
5162
5162
|
for (const e of readdirSync2(parent, { withFileTypes: true })) {
|
|
5163
5163
|
if (!e.isDirectory())
|
|
@@ -5338,17 +5338,17 @@ function cursorHomeDir() {
|
|
|
5338
5338
|
function cursorIdeHomeDir() {
|
|
5339
5339
|
return process.env.CHAT_RECALL_CURSOR_IDE_HOME || sources().cursorIdeHome || (process.platform === "darwin" ? join4(homedir3(), "Library", "Application Support", "Cursor") : join4(homedir3(), ".config", "Cursor"));
|
|
5340
5340
|
}
|
|
5341
|
-
function siblingHomes(
|
|
5341
|
+
function siblingHomes(base3, overridden, suffix) {
|
|
5342
5342
|
const roots = [];
|
|
5343
5343
|
const add = (home) => {
|
|
5344
5344
|
const root = suffix ? join4(home, suffix) : home;
|
|
5345
5345
|
if (existsSync4(root) && !roots.includes(root))
|
|
5346
5346
|
roots.push(root);
|
|
5347
5347
|
};
|
|
5348
|
-
add(
|
|
5348
|
+
add(base3);
|
|
5349
5349
|
if (!overridden) {
|
|
5350
|
-
const parent = dirname4(
|
|
5351
|
-
const leaf = basename(
|
|
5350
|
+
const parent = dirname4(base3);
|
|
5351
|
+
const leaf = basename(base3);
|
|
5352
5352
|
try {
|
|
5353
5353
|
for (const entry of readdirSync3(parent, { withFileTypes: true })) {
|
|
5354
5354
|
if (!entry.isDirectory())
|
|
@@ -5844,9 +5844,9 @@ async function parseSessionFile(sessionPath, maxMessages = 50) {
|
|
|
5844
5844
|
content.metadata.durationMs += obj.durationMs;
|
|
5845
5845
|
}
|
|
5846
5846
|
if (msgType === "file-history-snapshot") {
|
|
5847
|
-
const
|
|
5848
|
-
if (
|
|
5849
|
-
const backups =
|
|
5847
|
+
const snapshot2 = obj.snapshot;
|
|
5848
|
+
if (snapshot2 && typeof snapshot2 === "object") {
|
|
5849
|
+
const backups = snapshot2.trackedFileBackups;
|
|
5850
5850
|
if (backups && typeof backups === "object") {
|
|
5851
5851
|
for (const filePath2 of Object.keys(backups)) {
|
|
5852
5852
|
filesModified.add(filePath2);
|
|
@@ -6850,12 +6850,14 @@ function lineKey(line) {
|
|
|
6850
6850
|
try {
|
|
6851
6851
|
const o = JSON.parse(line);
|
|
6852
6852
|
if (typeof o?.uuid === "string" && o.uuid)
|
|
6853
|
-
return { key: `u:${o.uuid}`,
|
|
6854
|
-
|
|
6855
|
-
return { key: `m:${o.type}`, singleton: true };
|
|
6853
|
+
return { key: `u:${o.uuid}`, meta: false, json: true };
|
|
6854
|
+
return { key: `h:${sha1(line)}`, meta: typeof o?.type === "string" && STATE_META.has(o.type), json: true };
|
|
6856
6855
|
} catch {
|
|
6857
6856
|
}
|
|
6858
|
-
return { key: `h:${sha1(line)}`,
|
|
6857
|
+
return { key: `h:${sha1(line)}`, meta: false, json: false };
|
|
6858
|
+
}
|
|
6859
|
+
function isHalfWritten(line, currentLines) {
|
|
6860
|
+
return currentLines.some((c) => c.length > line.length && c.startsWith(line));
|
|
6859
6861
|
}
|
|
6860
6862
|
function mergeLineText(shadowText, currentText) {
|
|
6861
6863
|
const shadowLines = shadowText.split("\n").filter((l) => l.trim());
|
|
@@ -6863,27 +6865,24 @@ function mergeLineText(shadowText, currentText) {
|
|
|
6863
6865
|
const currentKeys = /* @__PURE__ */ new Set();
|
|
6864
6866
|
for (const l of currentLines)
|
|
6865
6867
|
currentKeys.add(lineKey(l).key);
|
|
6866
|
-
const
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
let recovered = 0;
|
|
6870
|
-
for (const k of shadowKeys)
|
|
6871
|
-
if (!currentKeys.has(k))
|
|
6872
|
-
recovered++;
|
|
6873
|
-
if (recovered === 0) {
|
|
6874
|
-
return { text: currentText.endsWith("\n") ? currentText : currentText + "\n", recovered: 0, totalRecords: currentKeys.size };
|
|
6875
|
-
}
|
|
6876
|
-
const out = [];
|
|
6877
|
-
const emitted = /* @__PURE__ */ new Set();
|
|
6868
|
+
const kept = [];
|
|
6869
|
+
const keptKeys = /* @__PURE__ */ new Set();
|
|
6870
|
+
const counted = /* @__PURE__ */ new Set();
|
|
6878
6871
|
for (const l of shadowLines) {
|
|
6879
|
-
const { key: key2,
|
|
6880
|
-
if (
|
|
6881
|
-
continue;
|
|
6882
|
-
if (emitted.has(key2))
|
|
6872
|
+
const { key: key2, meta, json } = lineKey(l);
|
|
6873
|
+
if (!json && isHalfWritten(l, currentLines))
|
|
6883
6874
|
continue;
|
|
6884
|
-
|
|
6885
|
-
|
|
6875
|
+
kept.push(l);
|
|
6876
|
+
keptKeys.add(key2);
|
|
6877
|
+
if (!meta && !currentKeys.has(key2))
|
|
6878
|
+
counted.add(key2);
|
|
6886
6879
|
}
|
|
6880
|
+
const recovered = counted.size;
|
|
6881
|
+
if (recovered === 0) {
|
|
6882
|
+
return { text: currentText.endsWith("\n") ? currentText : currentText + "\n", recovered: 0, totalRecords: currentKeys.size };
|
|
6883
|
+
}
|
|
6884
|
+
const out = [...kept];
|
|
6885
|
+
const emitted = keptKeys;
|
|
6887
6886
|
for (const l of currentLines) {
|
|
6888
6887
|
const { key: key2 } = lineKey(l);
|
|
6889
6888
|
if (emitted.has(key2))
|
|
@@ -7068,14 +7067,14 @@ function shadowSizeOnDisk(tool, rawId) {
|
|
|
7068
7067
|
return 0;
|
|
7069
7068
|
}
|
|
7070
7069
|
}
|
|
7071
|
-
var WHOLE_FILE_TOOLS,
|
|
7070
|
+
var WHOLE_FILE_TOOLS, STATE_META, lastLiveFingerprint;
|
|
7072
7071
|
var init_shadow = __esm({
|
|
7073
7072
|
"../engine/dist/transcript/shadow.js"() {
|
|
7074
7073
|
"use strict";
|
|
7075
7074
|
init_paths();
|
|
7076
7075
|
init_raw();
|
|
7077
7076
|
WHOLE_FILE_TOOLS = /* @__PURE__ */ new Set(["cursor"]);
|
|
7078
|
-
|
|
7077
|
+
STATE_META = /* @__PURE__ */ new Set(["mode", "permission-mode", "ai-title", "last-prompt", "pr-link", "summary"]);
|
|
7079
7078
|
lastLiveFingerprint = /* @__PURE__ */ new Map();
|
|
7080
7079
|
}
|
|
7081
7080
|
});
|
|
@@ -12281,8 +12280,8 @@ function serverRulePackVersion() {
|
|
|
12281
12280
|
return serverPack ? serverPack.version || "unversioned" : null;
|
|
12282
12281
|
}
|
|
12283
12282
|
function activeRules() {
|
|
12284
|
-
const
|
|
12285
|
-
return serverPack && serverPack.rules.length > 0 ? [...
|
|
12283
|
+
const base3 = settingsView().rules;
|
|
12284
|
+
return serverPack && serverPack.rules.length > 0 ? [...base3, ...serverPack.rules] : base3;
|
|
12286
12285
|
}
|
|
12287
12286
|
function isRedactionEnabled() {
|
|
12288
12287
|
const env = isEnvRedactionRequested();
|
|
@@ -18065,7 +18064,7 @@ __export(sync_ledger_exports, {
|
|
|
18065
18064
|
syncMode: () => syncMode,
|
|
18066
18065
|
unackedCursorAttemptCount: () => unackedCursorAttemptCount
|
|
18067
18066
|
});
|
|
18068
|
-
import { readFileSync as readFileSync30, writeFileSync as writeFileSync6, renameSync as renameSync4, mkdirSync as mkdirSync7 } from "node:fs";
|
|
18067
|
+
import { readFileSync as readFileSync30, writeFileSync as writeFileSync6, renameSync as renameSync4, mkdirSync as mkdirSync7, statSync as statSync35 } from "node:fs";
|
|
18069
18068
|
import { join as join39, dirname as dirname16 } from "node:path";
|
|
18070
18069
|
function toRow(entry) {
|
|
18071
18070
|
if (entry === void 0) return void 0;
|
|
@@ -18074,32 +18073,94 @@ function toRow(entry) {
|
|
|
18074
18073
|
function ledgerFilePath() {
|
|
18075
18074
|
return ledgerPath();
|
|
18076
18075
|
}
|
|
18077
|
-
function
|
|
18078
|
-
if (cache3) return cache3;
|
|
18076
|
+
function stampOf(path) {
|
|
18079
18077
|
try {
|
|
18080
|
-
const
|
|
18081
|
-
|
|
18078
|
+
const st = statSync35(path);
|
|
18079
|
+
return `${st.mtimeMs}:${st.size}`;
|
|
18082
18080
|
} catch {
|
|
18083
|
-
|
|
18081
|
+
return null;
|
|
18084
18082
|
}
|
|
18083
|
+
}
|
|
18084
|
+
function readDisk(path) {
|
|
18085
|
+
try {
|
|
18086
|
+
const parsed = JSON.parse(readFileSync30(path, "utf-8"));
|
|
18087
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
18088
|
+
} catch {
|
|
18089
|
+
return {};
|
|
18090
|
+
}
|
|
18091
|
+
}
|
|
18092
|
+
function snapshot(data) {
|
|
18093
|
+
const out = /* @__PURE__ */ new Map();
|
|
18094
|
+
for (const [server, rows] of Object.entries(data)) {
|
|
18095
|
+
for (const [id, entry] of Object.entries(rows)) out.set(rowKey(server, id), JSON.stringify(entry));
|
|
18096
|
+
}
|
|
18097
|
+
return out;
|
|
18098
|
+
}
|
|
18099
|
+
function mergeOnto(disk) {
|
|
18100
|
+
const out = {};
|
|
18101
|
+
const put = (server, id, entry) => {
|
|
18102
|
+
(out[server] ??= {})[id] = entry;
|
|
18103
|
+
};
|
|
18104
|
+
const mine = cache3 ?? {};
|
|
18105
|
+
for (const [server, rows] of Object.entries(disk)) {
|
|
18106
|
+
for (const [id, entry] of Object.entries(rows)) {
|
|
18107
|
+
const k = rowKey(server, id);
|
|
18108
|
+
const own = mine[server]?.[id];
|
|
18109
|
+
const was = base.get(k);
|
|
18110
|
+
if (own === void 0) {
|
|
18111
|
+
if (was === void 0) put(server, id, entry);
|
|
18112
|
+
} else {
|
|
18113
|
+
put(server, id, JSON.stringify(own) === was ? entry : own);
|
|
18114
|
+
}
|
|
18115
|
+
}
|
|
18116
|
+
}
|
|
18117
|
+
for (const [server, rows] of Object.entries(mine)) {
|
|
18118
|
+
for (const [id, entry] of Object.entries(rows)) {
|
|
18119
|
+
if (disk[server]?.[id] !== void 0) continue;
|
|
18120
|
+
if (JSON.stringify(entry) !== base.get(rowKey(server, id))) put(server, id, entry);
|
|
18121
|
+
}
|
|
18122
|
+
}
|
|
18123
|
+
return out;
|
|
18124
|
+
}
|
|
18125
|
+
function load() {
|
|
18126
|
+
const path = ledgerPath();
|
|
18127
|
+
const stamp2 = stampOf(path);
|
|
18128
|
+
if (cache3 && stamp2 === diskStamp) return cache3;
|
|
18129
|
+
const disk = readDisk(path);
|
|
18130
|
+
const merged = cache3 ? mergeOnto(disk) : disk;
|
|
18131
|
+
if (cache3) {
|
|
18132
|
+
for (const server of Object.keys(cache3)) if (!(server in merged)) delete cache3[server];
|
|
18133
|
+
for (const [server, rows] of Object.entries(merged)) {
|
|
18134
|
+
const target = cache3[server] ?? (cache3[server] = {});
|
|
18135
|
+
for (const id of Object.keys(target)) if (!(id in rows)) delete target[id];
|
|
18136
|
+
Object.assign(target, rows);
|
|
18137
|
+
}
|
|
18138
|
+
} else {
|
|
18139
|
+
cache3 = merged;
|
|
18140
|
+
}
|
|
18141
|
+
base = snapshot(disk);
|
|
18142
|
+
diskStamp = stamp2;
|
|
18085
18143
|
return cache3;
|
|
18086
18144
|
}
|
|
18087
|
-
function persistNow(
|
|
18145
|
+
function persistNow() {
|
|
18088
18146
|
const path = ledgerPath();
|
|
18089
18147
|
mkdirSync7(dirname16(path), { recursive: true });
|
|
18090
|
-
|
|
18091
|
-
|
|
18148
|
+
load();
|
|
18149
|
+
const tmp = `${path}.tmp-${process.pid}`;
|
|
18150
|
+
writeFileSync6(tmp, JSON.stringify(cache3 ?? {}));
|
|
18092
18151
|
renameSync4(tmp, path);
|
|
18152
|
+
base = snapshot(cache3 ?? {});
|
|
18153
|
+
diskStamp = stampOf(path);
|
|
18093
18154
|
pendingWrite = false;
|
|
18094
18155
|
}
|
|
18095
|
-
function persist(
|
|
18156
|
+
function persist(_data) {
|
|
18096
18157
|
pendingWrite = true;
|
|
18097
18158
|
if (flushTimer) return;
|
|
18098
18159
|
flushTimer = setTimeout(() => {
|
|
18099
18160
|
flushTimer = null;
|
|
18100
18161
|
if (pendingWrite) {
|
|
18101
18162
|
try {
|
|
18102
|
-
persistNow(
|
|
18163
|
+
persistNow();
|
|
18103
18164
|
} catch {
|
|
18104
18165
|
}
|
|
18105
18166
|
}
|
|
@@ -18133,7 +18194,7 @@ function pruneLedgerTargets(configuredServers) {
|
|
|
18133
18194
|
}
|
|
18134
18195
|
const rows = names.reduce((n, s) => n + Object.keys(orphans[s]).length, 0);
|
|
18135
18196
|
console.error(`[sync] tidied local bookkeeping: ${rows} already-synced marker(s) for ${names.length} server(s) you no longer sync to (${names.join(", ")}) moved to ${side}. Nothing was uploaded there; the file is kept so logging back in re-ships nothing.`);
|
|
18136
|
-
persistNow(
|
|
18197
|
+
persistNow();
|
|
18137
18198
|
return names.length;
|
|
18138
18199
|
}
|
|
18139
18200
|
function flushLedger() {
|
|
@@ -18142,7 +18203,7 @@ function flushLedger() {
|
|
|
18142
18203
|
flushTimer = null;
|
|
18143
18204
|
}
|
|
18144
18205
|
if (!pendingWrite || !cache3) return;
|
|
18145
|
-
persistNow(
|
|
18206
|
+
persistNow();
|
|
18146
18207
|
}
|
|
18147
18208
|
function loadItemVersionsAll() {
|
|
18148
18209
|
if (itemVersionsCache) return itemVersionsCache;
|
|
@@ -18230,13 +18291,13 @@ function markSynced(server, rows) {
|
|
|
18230
18291
|
const o = (cursorFromCaller ? r.offset : void 0) ?? prevOS.o ?? 0;
|
|
18231
18292
|
const s = (cursorFromCaller ? r.size : void 0) ?? prevOS.s ?? 0;
|
|
18232
18293
|
const ev = extractorVersionForId(r.id);
|
|
18233
|
-
const
|
|
18294
|
+
const base3 = prevF ? { m: Math.floor(r.mtime), v: ev, f: prevF } : { m: Math.floor(r.mtime), v: ev };
|
|
18234
18295
|
if (o > 0 || s > 0) {
|
|
18235
|
-
|
|
18236
|
-
|
|
18296
|
+
base3.o = o;
|
|
18297
|
+
base3.s = s;
|
|
18237
18298
|
}
|
|
18238
|
-
if (r.hash !== void 0)
|
|
18239
|
-
forServer[r.id] =
|
|
18299
|
+
if (r.hash !== void 0) base3.h = r.hash;
|
|
18300
|
+
forServer[r.id] = base3;
|
|
18240
18301
|
}
|
|
18241
18302
|
persist(data);
|
|
18242
18303
|
}
|
|
@@ -18305,6 +18366,8 @@ function forceFieldRescan(fieldName, server) {
|
|
|
18305
18366
|
function _resetLedgerCacheForTests() {
|
|
18306
18367
|
flushLedger();
|
|
18307
18368
|
cache3 = null;
|
|
18369
|
+
base = /* @__PURE__ */ new Map();
|
|
18370
|
+
diskStamp = null;
|
|
18308
18371
|
reconcileCache = null;
|
|
18309
18372
|
}
|
|
18310
18373
|
function markFullResync(server, sessionId) {
|
|
@@ -18326,7 +18389,7 @@ function syncMode(row, mtime, fileSize, extractorVersion, isAppendOnly) {
|
|
|
18326
18389
|
if (row.m >= Math.floor(mtime)) return "skip";
|
|
18327
18390
|
return "full";
|
|
18328
18391
|
}
|
|
18329
|
-
var ledgerPath, cache3, LEDGER_FLUSH_MS, pendingWrite, flushTimer, itemVersionsPath, itemVersionsCache, inventoryPath, unackedCursorAttempts, reconcilePath, reconcileCache;
|
|
18392
|
+
var ledgerPath, cache3, base, diskStamp, rowKey, LEDGER_FLUSH_MS, pendingWrite, flushTimer, itemVersionsPath, itemVersionsCache, inventoryPath, unackedCursorAttempts, reconcilePath, reconcileCache;
|
|
18330
18393
|
var init_sync_ledger = __esm({
|
|
18331
18394
|
"src/sync-ledger.ts"() {
|
|
18332
18395
|
"use strict";
|
|
@@ -18334,6 +18397,9 @@ var init_sync_ledger = __esm({
|
|
|
18334
18397
|
init_extractor_version();
|
|
18335
18398
|
ledgerPath = () => join39(getDataDir(), "sync-ledger.json");
|
|
18336
18399
|
cache3 = null;
|
|
18400
|
+
base = /* @__PURE__ */ new Map();
|
|
18401
|
+
diskStamp = null;
|
|
18402
|
+
rowKey = (server, id) => `${server}\0${id}`;
|
|
18337
18403
|
LEDGER_FLUSH_MS = 2e3;
|
|
18338
18404
|
pendingWrite = false;
|
|
18339
18405
|
flushTimer = null;
|
|
@@ -18372,7 +18438,7 @@ var init_sync_fields = __esm({
|
|
|
18372
18438
|
});
|
|
18373
18439
|
|
|
18374
18440
|
// ../engine/dist/core/index-lock.js
|
|
18375
|
-
import { existsSync as existsSync39, mkdirSync as mkdirSync8, openSync as openSync8, writeFileSync as writeFileSync7, readFileSync as readFileSync31, rmSync as rmSync4, statSync as
|
|
18441
|
+
import { existsSync as existsSync39, mkdirSync as mkdirSync8, openSync as openSync8, writeFileSync as writeFileSync7, readFileSync as readFileSync31, rmSync as rmSync4, statSync as statSync36, closeSync as closeSync8 } from "fs";
|
|
18376
18442
|
import { dirname as dirname17, join as join40 } from "path";
|
|
18377
18443
|
function acquireIndexLock(opts) {
|
|
18378
18444
|
const lockPath = lockFilePath(opts.file);
|
|
@@ -18422,7 +18488,7 @@ function lockFilePath(file = ".compact.lock") {
|
|
|
18422
18488
|
}
|
|
18423
18489
|
function stealStaleLock(lockPath, staleAfterMs) {
|
|
18424
18490
|
try {
|
|
18425
|
-
const s =
|
|
18491
|
+
const s = statSync36(lockPath);
|
|
18426
18492
|
const age = Date.now() - s.mtimeMs;
|
|
18427
18493
|
let payload;
|
|
18428
18494
|
try {
|
|
@@ -18485,7 +18551,7 @@ var init_http = __esm({
|
|
|
18485
18551
|
CLI_VERSION = JSON.parse(readFileSync32(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
|
|
18486
18552
|
} catch {
|
|
18487
18553
|
try {
|
|
18488
|
-
if (true) CLI_VERSION = "0.7.
|
|
18554
|
+
if (true) CLI_VERSION = "0.7.15";
|
|
18489
18555
|
} catch {
|
|
18490
18556
|
}
|
|
18491
18557
|
}
|
|
@@ -18979,7 +19045,7 @@ var init_telemetry = __esm({
|
|
|
18979
19045
|
init_sync_client();
|
|
18980
19046
|
cliVersion = () => {
|
|
18981
19047
|
try {
|
|
18982
|
-
return true ? "0.7.
|
|
19048
|
+
return true ? "0.7.15" : "dev";
|
|
18983
19049
|
} catch {
|
|
18984
19050
|
return "dev";
|
|
18985
19051
|
}
|
|
@@ -19002,11 +19068,11 @@ __export(server_probe_exports, {
|
|
|
19002
19068
|
function probeOk(r) {
|
|
19003
19069
|
return r.kind === "ok" && r.apiVersion >= 2;
|
|
19004
19070
|
}
|
|
19005
|
-
async function probeServer(
|
|
19071
|
+
async function probeServer(base3, opts = {}) {
|
|
19006
19072
|
const f = opts.fetchImpl || fetch;
|
|
19007
19073
|
let res;
|
|
19008
19074
|
try {
|
|
19009
|
-
res = await f(`${
|
|
19075
|
+
res = await f(`${base3.replace(/\/+$/, "")}/api/capabilities`, {
|
|
19010
19076
|
signal: AbortSignal.timeout(opts.timeoutMs ?? 1e4)
|
|
19011
19077
|
});
|
|
19012
19078
|
} catch (err) {
|
|
@@ -19043,34 +19109,34 @@ async function probeServer(base2, opts = {}) {
|
|
|
19043
19109
|
raw: parsed
|
|
19044
19110
|
};
|
|
19045
19111
|
}
|
|
19046
|
-
function probeAdvice(r,
|
|
19112
|
+
function probeAdvice(r, base3) {
|
|
19047
19113
|
switch (r.kind) {
|
|
19048
19114
|
case "ok":
|
|
19049
19115
|
return r.apiVersion >= 2 ? `apiVersion ${r.apiVersion}${r.edition ? `, edition ${r.edition}` : ""}` : `apiVersion ${r.apiVersion} is too old for this CLI \u2014 upgrade the server`;
|
|
19050
19116
|
case "moved":
|
|
19051
|
-
return `HTTP ${r.status} \u2014 nothing is served at ${
|
|
19117
|
+
return `HTTP ${r.status} \u2014 nothing is served at ${base3}. If the host moved, re-point it: \`chat-recall login <new-server-url>\``;
|
|
19052
19118
|
case "unauthorized":
|
|
19053
|
-
return `HTTP ${r.status} \u2014 ${
|
|
19119
|
+
return `HTTP ${r.status} \u2014 ${base3} rejected the credential. Re-login: \`chat-recall login ` + base3 + "`";
|
|
19054
19120
|
case "server_error":
|
|
19055
|
-
return `HTTP ${r.status} \u2014 ${
|
|
19121
|
+
return `HTTP ${r.status} \u2014 ${base3} is up but failing. Nothing to fix locally; check the server.`;
|
|
19056
19122
|
case "not_api":
|
|
19057
|
-
return `${
|
|
19123
|
+
return `${base3} answered ${r.status} with something that is not the chat-recall API (${JSON.stringify(r.snippet)}) \u2014 check the URL, a proxy or a captive portal`;
|
|
19058
19124
|
case "unreachable":
|
|
19059
19125
|
switch (r.reason) {
|
|
19060
19126
|
case "dns":
|
|
19061
|
-
return `cannot resolve the host in ${
|
|
19127
|
+
return `cannot resolve the host in ${base3} (${r.error}) \u2014 check the URL for a typo, and your DNS or VPN`;
|
|
19062
19128
|
case "refused":
|
|
19063
|
-
return `${
|
|
19129
|
+
return `${base3} resolves but refused the connection (${r.error}) \u2014 the server is not running, or the port is wrong`;
|
|
19064
19130
|
case "tls":
|
|
19065
|
-
return `the TLS certificate at ${
|
|
19131
|
+
return `the TLS certificate at ${base3} was rejected (${r.error}) \u2014 expired, self-signed, or issued for another host. A corporate proxy that re-signs traffic does this.`;
|
|
19066
19132
|
case "timeout":
|
|
19067
|
-
return `${
|
|
19133
|
+
return `${base3} did not answer in time (${r.error}) \u2014 a firewall or proxy that drops traffic silently looks exactly like this`;
|
|
19068
19134
|
case "reset":
|
|
19069
|
-
return `the connection to ${
|
|
19135
|
+
return `the connection to ${base3} was cut (${r.error}) \u2014 often a proxy or a captive portal`;
|
|
19070
19136
|
case "bad_port":
|
|
19071
|
-
return `${
|
|
19137
|
+
return `${base3} names a port that Node and every browser refuse to open (the WHATWG bad-port list) \u2014 use the server's real port`;
|
|
19072
19138
|
default:
|
|
19073
|
-
return `no HTTP response from ${
|
|
19139
|
+
return `no HTTP response from ${base3} (${r.error}) \u2014 check the URL, DNS, or that the server is running`;
|
|
19074
19140
|
}
|
|
19075
19141
|
}
|
|
19076
19142
|
}
|
|
@@ -19103,8 +19169,8 @@ function describeCause(err) {
|
|
|
19103
19169
|
const code = e.code;
|
|
19104
19170
|
if (typeof code === "string" && code && !parts.includes(code)) parts.push(code);
|
|
19105
19171
|
}
|
|
19106
|
-
const
|
|
19107
|
-
return parts.length ? `${
|
|
19172
|
+
const base3 = err instanceof Error ? err.message : String(err);
|
|
19173
|
+
return parts.length ? `${base3}: ${parts.join(" \u2192 ")}` : base3;
|
|
19108
19174
|
}
|
|
19109
19175
|
function describeUnreachable(err) {
|
|
19110
19176
|
const reason = classifyUnreachable(err);
|
|
@@ -19217,7 +19283,7 @@ __export(auto_update_exports, {
|
|
|
19217
19283
|
import { execSync as execSync2, execFileSync as execFileSync3 } from "node:child_process";
|
|
19218
19284
|
import { readFileSync as readFileSync34, existsSync as existsSync41 } from "node:fs";
|
|
19219
19285
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
19220
|
-
import { writeFileSync as writeFileSync8, mkdtempSync as mkdtempSync3, rmSync as rmSync5, readdirSync as readdirSync30, statSync as
|
|
19286
|
+
import { writeFileSync as writeFileSync8, mkdtempSync as mkdtempSync3, rmSync as rmSync5, readdirSync as readdirSync30, statSync as statSync37, mkdirSync as mkdirSync9 } from "node:fs";
|
|
19221
19287
|
import { join as join41, dirname as dirname18, sep as sep2, posix as pathPosix, win32 as pathWin32 } from "node:path";
|
|
19222
19288
|
import { tmpdir as tmpdir2, homedir as homedir15 } from "node:os";
|
|
19223
19289
|
import { createHash as createHash7 } from "node:crypto";
|
|
@@ -19249,12 +19315,12 @@ function installedVersion() {
|
|
|
19249
19315
|
return null;
|
|
19250
19316
|
}
|
|
19251
19317
|
}
|
|
19252
|
-
function planAutoUpdate(
|
|
19318
|
+
function planAutoUpdate(base3, caps, ownVersion3, flag) {
|
|
19253
19319
|
const rel = caps.cli;
|
|
19254
19320
|
if (!rel || !rel.version || !rel.sha256) return { update: false, reason: "server advertises no CLI release" };
|
|
19255
19321
|
if (!isAutoUpdateEnabled(caps.edition, flag)) return { update: false, reason: `auto-update disabled (edition ${caps.edition ?? "?"})` };
|
|
19256
19322
|
if (compareVersions(rel.version, ownVersion3) <= 0) return { update: false, reason: `already current (own ${ownVersion3} >= server ${rel.version})` };
|
|
19257
|
-
return { update: true, reason: `server ${rel.version} > own ${ownVersion3}`, url: tarballUrl(
|
|
19323
|
+
return { update: true, reason: `server ${rel.version} > own ${ownVersion3}`, url: tarballUrl(base3, rel.version), fallbackUrl: tarballUrl(base3), sha256: rel.sha256, from: ownVersion3, to: rel.version };
|
|
19258
19324
|
}
|
|
19259
19325
|
function sweepStaleStaging(root = tmpdir2(), now = Date.now()) {
|
|
19260
19326
|
const MKDTEMP_SUFFIX = /^cr-update-.{6}$/s;
|
|
@@ -19270,7 +19336,7 @@ function sweepStaleStaging(root = tmpdir2(), now = Date.now()) {
|
|
|
19270
19336
|
if (!MKDTEMP_SUFFIX.test(name)) continue;
|
|
19271
19337
|
const dir = join41(root, name);
|
|
19272
19338
|
try {
|
|
19273
|
-
const st =
|
|
19339
|
+
const st = statSync37(dir);
|
|
19274
19340
|
if (!st.isDirectory() || now - st.mtimeMs < COLD_MS) continue;
|
|
19275
19341
|
const inside = readdirSync30(dir);
|
|
19276
19342
|
if (inside.length > 1 || inside.length === 1 && inside[0] !== "chat-recall.tgz") continue;
|
|
@@ -19434,20 +19500,20 @@ function clearUpdateFailures() {
|
|
|
19434
19500
|
function stopAutoUpdates() {
|
|
19435
19501
|
stopRequested = true;
|
|
19436
19502
|
}
|
|
19437
|
-
async function runAutoUpdate(
|
|
19503
|
+
async function runAutoUpdate(base3, authHeaders, ownVersion3, deps) {
|
|
19438
19504
|
let caps;
|
|
19439
19505
|
try {
|
|
19440
|
-
const res = await fetchWithTimeout(`${
|
|
19506
|
+
const res = await fetchWithTimeout(`${base3.replace(/\/+$/, "")}/api/capabilities`, { headers: authHeaders });
|
|
19441
19507
|
if (!res.ok) return { updated: false, reason: `capabilities HTTP ${res.status}` };
|
|
19442
19508
|
caps = await res.json();
|
|
19443
19509
|
} catch (e) {
|
|
19444
19510
|
return { updated: false, reason: `capabilities unreachable: ${e instanceof Error ? e.message : e}` };
|
|
19445
19511
|
}
|
|
19446
19512
|
const effectiveOwn = newerOf(ownVersion3, installedVersion());
|
|
19447
|
-
const plan = planAutoUpdate(
|
|
19513
|
+
const plan = planAutoUpdate(base3, caps, effectiveOwn, process.env.CHAT_RECALL_AUTO_UPDATE);
|
|
19448
19514
|
if (!plan.update) {
|
|
19449
|
-
if (/disabled|no CLI release/.test(plan.reason) && !reportedStandingSkip.has(
|
|
19450
|
-
reportedStandingSkip.add(
|
|
19515
|
+
if (/disabled|no CLI release/.test(plan.reason) && !reportedStandingSkip.has(base3)) {
|
|
19516
|
+
reportedStandingSkip.add(base3);
|
|
19451
19517
|
try {
|
|
19452
19518
|
const { reportClientEvent: reportClientEvent2 } = await Promise.resolve().then(() => (init_client_events(), client_events_exports));
|
|
19453
19519
|
reportClientEvent2("auto_update_skipped", { message: `${plan.reason} (server offers ${caps.cli?.version ?? "?"}, this device runs ${effectiveOwn})` });
|
|
@@ -19503,7 +19569,7 @@ var init_auto_update = __esm({
|
|
|
19503
19569
|
"use strict";
|
|
19504
19570
|
init_http();
|
|
19505
19571
|
init_index_lock();
|
|
19506
|
-
tarballUrl = (
|
|
19572
|
+
tarballUrl = (base3, version) => `${base3.replace(/\/+$/, "")}/install/${version ? `chat-recall-${version}.tgz` : "chat-recall.tgz"}`;
|
|
19507
19573
|
GIVE_UP_AFTER = 3;
|
|
19508
19574
|
reportedStandingSkip = /* @__PURE__ */ new Set();
|
|
19509
19575
|
STOPPING_REASON = "not installed: this process is shutting down";
|
|
@@ -19514,7 +19580,7 @@ var init_auto_update = __esm({
|
|
|
19514
19580
|
|
|
19515
19581
|
// src/sync-client.ts
|
|
19516
19582
|
import { join as join42, dirname as dirname19, basename as basename20 } from "node:path";
|
|
19517
|
-
import { readFileSync as readFileSync35, writeFileSync as writeFileSync9, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync4, rmSync as rmSync6, chmodSync as chmodSync3, unlinkSync as unlinkSync2, readdirSync as readdirSync31, statSync as
|
|
19583
|
+
import { readFileSync as readFileSync35, writeFileSync as writeFileSync9, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync4, rmSync as rmSync6, chmodSync as chmodSync3, unlinkSync as unlinkSync2, readdirSync as readdirSync31, statSync as statSync38 } from "node:fs";
|
|
19518
19584
|
import { tmpdir as tmpdir3, hostname as hostname2 } from "node:os";
|
|
19519
19585
|
import { createHash as createHash8 } from "node:crypto";
|
|
19520
19586
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
@@ -19559,15 +19625,15 @@ function loadAllCredentials() {
|
|
|
19559
19625
|
return [];
|
|
19560
19626
|
}
|
|
19561
19627
|
async function fetchTenantSecurityConfig(cred) {
|
|
19562
|
-
const
|
|
19563
|
-
const cached = _securityConfigCache.get(
|
|
19628
|
+
const base3 = cred.serverUrl.replace(/\/+$/, "");
|
|
19629
|
+
const cached = _securityConfigCache.get(base3);
|
|
19564
19630
|
if (cached && Date.now() - cached.fetchedAt < SECURITY_CONFIG_TTL_MS) return cached.config;
|
|
19565
19631
|
const headers = { "content-type": "application/json" };
|
|
19566
19632
|
if (cred.token) headers.authorization = `Bearer ${cred.token}`;
|
|
19567
19633
|
try {
|
|
19568
19634
|
const [rulesRes, settingsRes] = await Promise.all([
|
|
19569
|
-
fetchWithTimeout(`${
|
|
19570
|
-
fetchWithTimeout(`${
|
|
19635
|
+
fetchWithTimeout(`${base3}/api/secrets/rules`, { headers }),
|
|
19636
|
+
fetchWithTimeout(`${base3}/api/teams/security-config`, { headers }).catch(() => null)
|
|
19571
19637
|
]);
|
|
19572
19638
|
let tenantRules = [];
|
|
19573
19639
|
let rulePackVersion = null;
|
|
@@ -19592,18 +19658,18 @@ async function fetchTenantSecurityConfig(cred) {
|
|
|
19592
19658
|
const body = await settingsRes.json().catch(() => ({}));
|
|
19593
19659
|
if (typeof body.verifySecrets === "boolean") verifySecrets = body.verifySecrets;
|
|
19594
19660
|
if (typeof body.telemetry === "boolean") {
|
|
19595
|
-
setTelemetryEligible(
|
|
19661
|
+
setTelemetryEligible(base3, body.telemetry);
|
|
19596
19662
|
try {
|
|
19597
19663
|
const prior = readCollectorHealth()?.telemetryEligible ?? {};
|
|
19598
19664
|
updateCollectorHealth({
|
|
19599
|
-
telemetryEligible: { ...prior, [
|
|
19665
|
+
telemetryEligible: { ...prior, [base3]: { allowed: body.telemetry, at: Date.now() } }
|
|
19600
19666
|
});
|
|
19601
19667
|
} catch {
|
|
19602
19668
|
}
|
|
19603
19669
|
}
|
|
19604
19670
|
}
|
|
19605
19671
|
const config = { tenantRules, verifySecrets, rulePackVersion };
|
|
19606
|
-
_securityConfigCache.set(
|
|
19672
|
+
_securityConfigCache.set(base3, { fetchedAt: Date.now(), config });
|
|
19607
19673
|
return config;
|
|
19608
19674
|
} catch {
|
|
19609
19675
|
return { tenantRules: [], verifySecrets: true, rulePackVersion: null };
|
|
@@ -19619,18 +19685,18 @@ function readPersistedSyncConfigs() {
|
|
|
19619
19685
|
return {};
|
|
19620
19686
|
}
|
|
19621
19687
|
}
|
|
19622
|
-
function persistSyncConfig(
|
|
19688
|
+
function persistSyncConfig(base3, config) {
|
|
19623
19689
|
try {
|
|
19624
19690
|
const all = readPersistedSyncConfigs();
|
|
19625
|
-
all[
|
|
19691
|
+
all[base3] = { fetchedAt: Date.now(), config };
|
|
19626
19692
|
mkdirSync10(dirname19(syncConfigCachePath()), { recursive: true });
|
|
19627
19693
|
writeFileSync9(syncConfigCachePath(), JSON.stringify(all, null, 2));
|
|
19628
19694
|
} catch {
|
|
19629
19695
|
}
|
|
19630
19696
|
}
|
|
19631
19697
|
async function fetchTenantSyncConfig(cred) {
|
|
19632
|
-
const
|
|
19633
|
-
const cached = _syncConfigCache.get(
|
|
19698
|
+
const base3 = cred.serverUrl.replace(/\/+$/, "");
|
|
19699
|
+
const cached = _syncConfigCache.get(base3);
|
|
19634
19700
|
if (cached && Date.now() - cached.fetchedAt < SECURITY_CONFIG_TTL_MS) return cached.config;
|
|
19635
19701
|
const headers = { "content-type": "application/json" };
|
|
19636
19702
|
if (cred.token) headers.authorization = `Bearer ${cred.token}`;
|
|
@@ -19638,7 +19704,7 @@ async function fetchTenantSyncConfig(cred) {
|
|
|
19638
19704
|
try {
|
|
19639
19705
|
const sources2 = discoverSessionSources();
|
|
19640
19706
|
if (sources2.length > 0) {
|
|
19641
|
-
await fetchWithTimeout(`${
|
|
19707
|
+
await fetchWithTimeout(`${base3}/api/sync-config/sources`, {
|
|
19642
19708
|
method: "POST",
|
|
19643
19709
|
headers,
|
|
19644
19710
|
body: JSON.stringify({ device: deviceLabel(), sources: sources2 })
|
|
@@ -19646,12 +19712,12 @@ async function fetchTenantSyncConfig(cred) {
|
|
|
19646
19712
|
}
|
|
19647
19713
|
} catch {
|
|
19648
19714
|
}
|
|
19649
|
-
const res = await fetchWithTimeout(`${
|
|
19715
|
+
const res = await fetchWithTimeout(`${base3}/api/sync-config`, { headers });
|
|
19650
19716
|
if (res.status === 404) {
|
|
19651
|
-
_syncConfigCache.set(
|
|
19717
|
+
_syncConfigCache.set(base3, { fetchedAt: Date.now(), config: EMPTY_SYNC_CONFIG });
|
|
19652
19718
|
return EMPTY_SYNC_CONFIG;
|
|
19653
19719
|
}
|
|
19654
|
-
if (!res.ok) return lastKnownSyncConfig(
|
|
19720
|
+
if (!res.ok) return lastKnownSyncConfig(base3, `HTTP ${res.status}`);
|
|
19655
19721
|
const body = await res.json().catch(() => ({}));
|
|
19656
19722
|
const config = {
|
|
19657
19723
|
excludeTools: Array.isArray(body.excludeTools) ? body.excludeTools.filter((t) => typeof t === "string") : [],
|
|
@@ -19688,22 +19754,22 @@ async function fetchTenantSyncConfig(cred) {
|
|
|
19688
19754
|
if (decided > 0) console.error(`[sync] applied ${decided} folder decision(s) from the dashboard`);
|
|
19689
19755
|
} catch {
|
|
19690
19756
|
}
|
|
19691
|
-
_syncConfigCache.set(
|
|
19692
|
-
persistSyncConfig(
|
|
19757
|
+
_syncConfigCache.set(base3, { fetchedAt: Date.now(), config });
|
|
19758
|
+
persistSyncConfig(base3, config);
|
|
19693
19759
|
return config;
|
|
19694
19760
|
} catch (err) {
|
|
19695
19761
|
if (isSyncRulesRefusal(err)) throw err;
|
|
19696
|
-
return lastKnownSyncConfig(
|
|
19762
|
+
return lastKnownSyncConfig(base3, err instanceof Error ? err.message : "request failed");
|
|
19697
19763
|
}
|
|
19698
19764
|
}
|
|
19699
|
-
function lastKnownSyncConfig(
|
|
19700
|
-
const remembered = _syncConfigCache.get(
|
|
19765
|
+
function lastKnownSyncConfig(base3, reason) {
|
|
19766
|
+
const remembered = _syncConfigCache.get(base3) ?? readPersistedSyncConfigs()[base3];
|
|
19701
19767
|
if (remembered) {
|
|
19702
19768
|
console.error(`[sync] could not read server-side sync rules (${reason}) \u2014 applying the last known set from ${new Date(remembered.fetchedAt).toISOString()}`);
|
|
19703
19769
|
return remembered.config;
|
|
19704
19770
|
}
|
|
19705
19771
|
const refusal = new Error(
|
|
19706
|
-
`Cannot read the server-side sync rules from ${
|
|
19772
|
+
`Cannot read the server-side sync rules from ${base3} (${reason}), and this machine has never successfully read them. Refusing to sync: uploading without knowing your exclusions could ship a project you told the dashboard to hold back. Fix the server or retry.`
|
|
19707
19773
|
);
|
|
19708
19774
|
refusal[SYNC_RULES_REFUSAL] = true;
|
|
19709
19775
|
throw refusal;
|
|
@@ -19811,25 +19877,25 @@ async function syncSessions(opts = {}) {
|
|
|
19811
19877
|
${errors.join("\n ")}`);
|
|
19812
19878
|
return { ...agg, perTarget };
|
|
19813
19879
|
}
|
|
19814
|
-
async function postFieldBatch(
|
|
19880
|
+
async function postFieldBatch(base3, token, rows) {
|
|
19815
19881
|
const headers = { "content-type": "application/json" };
|
|
19816
19882
|
if (token) headers.authorization = `Bearer ${token}`;
|
|
19817
19883
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
19818
19884
|
for (let attempt = 0; ; attempt++) {
|
|
19819
|
-
const res = await fetchWithTimeout(`${
|
|
19885
|
+
const res = await fetchWithTimeout(`${base3}/api/sync`, { method: "POST", headers, body: JSON.stringify({ fields: rows }) }, 6e4);
|
|
19820
19886
|
if (res.ok) return;
|
|
19821
19887
|
const retryable = res.status === 429 || res.status >= 500;
|
|
19822
|
-
if (!retryable || attempt >= 5) throw new Error(`${
|
|
19888
|
+
if (!retryable || attempt >= 5) throw new Error(`${base3}: fields batch HTTP ${res.status} ${await res.text().catch(() => "")}`);
|
|
19823
19889
|
const ra = Number(res.headers.get("retry-after")) || 0;
|
|
19824
19890
|
await sleep(ra > 0 ? ra * 1e3 : [500, 1500, 4e3, 8e3, 15e3][Math.min(attempt, 4)]);
|
|
19825
19891
|
}
|
|
19826
19892
|
}
|
|
19827
19893
|
async function reconcileFieldsForTarget(cred, fullRefs, opts = {}) {
|
|
19828
|
-
const
|
|
19829
|
-
const ledger = getSyncedRows(
|
|
19894
|
+
const base3 = cred.serverUrl.replace(/\/+$/, "");
|
|
19895
|
+
const ledger = getSyncedRows(base3);
|
|
19830
19896
|
let pushed = 0, absent = 0, scanned = 0;
|
|
19831
19897
|
for (const field of SYNC_FIELDS) {
|
|
19832
|
-
const needFull = !!opts.force || fieldNeedsFullPass(
|
|
19898
|
+
const needFull = !!opts.force || fieldNeedsFullPass(base3, field);
|
|
19833
19899
|
const candidates2 = needFull ? fullRefs() : opts.convRefs ?? fullRefs();
|
|
19834
19900
|
const send = [];
|
|
19835
19901
|
const mtimeById = /* @__PURE__ */ new Map();
|
|
@@ -19845,15 +19911,15 @@ async function reconcileFieldsForTarget(cred, fullRefs, opts = {}) {
|
|
|
19845
19911
|
}
|
|
19846
19912
|
for (let i = 0; i < send.length; i += 200) {
|
|
19847
19913
|
const chunk = send.slice(i, i + 200);
|
|
19848
|
-
await postFieldBatch(
|
|
19849
|
-
markFieldCoverage(
|
|
19914
|
+
await postFieldBatch(base3, cred.token, chunk);
|
|
19915
|
+
markFieldCoverage(base3, field, chunk.map((r) => ({ id: r.session_id, present: true, mtime: mtimeById.get(r.session_id) ?? 0 })));
|
|
19850
19916
|
pushed += chunk.length;
|
|
19851
19917
|
}
|
|
19852
19918
|
if (absentIds.length) {
|
|
19853
|
-
markFieldCoverage(
|
|
19919
|
+
markFieldCoverage(base3, field, absentIds.map((id) => ({ id, present: false, mtime: mtimeById.get(id) ?? 0 })));
|
|
19854
19920
|
absent += absentIds.length;
|
|
19855
19921
|
}
|
|
19856
|
-
if (needFull) markFieldFullPassDone(
|
|
19922
|
+
if (needFull) markFieldFullPassDone(base3, field);
|
|
19857
19923
|
}
|
|
19858
19924
|
return { pushed, absent, scanned };
|
|
19859
19925
|
}
|
|
@@ -19869,7 +19935,7 @@ function reapStaleScanDirs(dir = tmpdir3(), maxAgeMs = 6 * 36e5, now = Date.now(
|
|
|
19869
19935
|
if (!name.startsWith("cr-batchscan-")) continue;
|
|
19870
19936
|
const p = join42(dir, name);
|
|
19871
19937
|
try {
|
|
19872
|
-
if (now -
|
|
19938
|
+
if (now - statSync38(p).mtimeMs < maxAgeMs) continue;
|
|
19873
19939
|
rmSync6(p, { recursive: true, force: true });
|
|
19874
19940
|
reaped++;
|
|
19875
19941
|
} catch {
|
|
@@ -19943,25 +20009,25 @@ function serverIngestConcurrency(serverUrl) {
|
|
|
19943
20009
|
return advertisedIngestConc.get(serverUrl.replace(/\/$/, "")) ?? null;
|
|
19944
20010
|
}
|
|
19945
20011
|
async function verifyServerApi(serverUrl, minApi) {
|
|
19946
|
-
const
|
|
19947
|
-
const seen = capsOk.get(
|
|
20012
|
+
const base3 = serverUrl.replace(/\/$/, "");
|
|
20013
|
+
const seen = capsOk.get(base3);
|
|
19948
20014
|
if (seen !== void 0 && Date.now() - seen < CAPS_TTL_MS) return true;
|
|
19949
20015
|
const { probeServer: probeServer2, probeAdvice: probeAdvice2 } = await Promise.resolve().then(() => (init_server_probe(), server_probe_exports));
|
|
19950
|
-
const probe = await probeServer2(
|
|
20016
|
+
const probe = await probeServer2(base3, {
|
|
19951
20017
|
fetchImpl: ((url, init) => fetchWithTimeout(String(url), init ?? {}))
|
|
19952
20018
|
});
|
|
19953
|
-
if (probe.kind !== "ok") throw new Error(probeAdvice2(probe,
|
|
20019
|
+
if (probe.kind !== "ok") throw new Error(probeAdvice2(probe, base3));
|
|
19954
20020
|
const caps = probe.raw;
|
|
19955
20021
|
if ((caps.apiVersion ?? 0) < minApi) {
|
|
19956
20022
|
throw new Error(`server too old: apiVersion ${caps.apiVersion ?? "none"} < required ${minApi} \u2014 update the server image before syncing`);
|
|
19957
20023
|
}
|
|
19958
20024
|
const adv = caps.limits?.ingestConcurrencyPerTenant;
|
|
19959
20025
|
if (typeof adv === "number" && Number.isFinite(adv) && adv >= 1) {
|
|
19960
|
-
advertisedIngestConc.set(
|
|
20026
|
+
advertisedIngestConc.set(base3, Math.floor(adv));
|
|
19961
20027
|
}
|
|
19962
|
-
if (caps.limits?.acceptsGzipBody === true) advertisedGzipBody.add(
|
|
19963
|
-
else advertisedGzipBody.delete(
|
|
19964
|
-
capsOk.set(
|
|
20028
|
+
if (caps.limits?.acceptsGzipBody === true) advertisedGzipBody.add(base3);
|
|
20029
|
+
else advertisedGzipBody.delete(base3);
|
|
20030
|
+
capsOk.set(base3, Date.now());
|
|
19965
20031
|
return true;
|
|
19966
20032
|
}
|
|
19967
20033
|
async function syncToTarget(cred, opts = {}) {
|
|
@@ -20026,7 +20092,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20026
20092
|
const ac = new AbortController();
|
|
20027
20093
|
const timer = setTimeout(() => ac.abort(new Error(`upload timed out after ${UPLOAD_TIMEOUT_MS}ms`)), UPLOAD_TIMEOUT_MS);
|
|
20028
20094
|
try {
|
|
20029
|
-
const res = await fetch(`${
|
|
20095
|
+
const res = await fetch(`${base3}/api/sync`, {
|
|
20030
20096
|
method: "POST",
|
|
20031
20097
|
// No token ⇒ no auth header: a no-auth local server (AUTH_PROVIDER=none)
|
|
20032
20098
|
// accepts it as the single 'default' tenant.
|
|
@@ -20042,26 +20108,26 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20042
20108
|
acceptedUploads.set(cred.serverUrl, (acceptedUploads.get(cred.serverUrl) ?? 0) + 1);
|
|
20043
20109
|
const body2 = await res.json().catch(() => ({}));
|
|
20044
20110
|
if (typeof body2.telemetry === "boolean") {
|
|
20045
|
-
setTelemetryEligible(
|
|
20111
|
+
setTelemetryEligible(base3, body2.telemetry);
|
|
20046
20112
|
try {
|
|
20047
20113
|
const prior = readCollectorHealth()?.telemetryEligible ?? {};
|
|
20048
20114
|
updateCollectorHealth({
|
|
20049
|
-
telemetryEligible: { ...prior, [
|
|
20115
|
+
telemetryEligible: { ...prior, [base3]: { allowed: body2.telemetry, at: Date.now() } }
|
|
20050
20116
|
});
|
|
20051
20117
|
} catch {
|
|
20052
20118
|
}
|
|
20053
20119
|
}
|
|
20054
20120
|
const adv = body2.limits?.ingestConcurrencyPerTenant;
|
|
20055
20121
|
if (typeof adv === "number" && Number.isFinite(adv) && adv >= 1) {
|
|
20056
|
-
setServerIngestConcurrency(
|
|
20122
|
+
setServerIngestConcurrency(base3, Math.floor(adv));
|
|
20057
20123
|
}
|
|
20058
20124
|
if (body2.cli && body2.cli.version) {
|
|
20059
20125
|
const { planAutoUpdate: planAutoUpdate2, runAutoUpdate: runAutoUpdate2, sweepStaleStaging: sweepStaleStaging2 } = await Promise.resolve().then(() => (init_auto_update(), auto_update_exports));
|
|
20060
20126
|
const authHeaders = cred.token ? { authorization: `Bearer ${cred.token}` } : {};
|
|
20061
|
-
const plan = planAutoUpdate2(
|
|
20127
|
+
const plan = planAutoUpdate2(base3, { cli: body2.cli }, ownVersion, process.env.CHAT_RECALL_AUTO_UPDATE);
|
|
20062
20128
|
sweepStaleStaging2();
|
|
20063
20129
|
if (plan.update) {
|
|
20064
|
-
void runAutoUpdate2(
|
|
20130
|
+
void runAutoUpdate2(base3, authHeaders, ownVersion).catch(() => {
|
|
20065
20131
|
});
|
|
20066
20132
|
}
|
|
20067
20133
|
}
|
|
@@ -20070,7 +20136,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20070
20136
|
const retryable = res.status === 429 || res.status >= 500;
|
|
20071
20137
|
const text = await res.text().catch(() => "");
|
|
20072
20138
|
if (res.status === 401 || res.status === 403) {
|
|
20073
|
-
throw classedError("auth", `server rejected this machine's device token (HTTP ${res.status} \u2014 revoked?). Reconnect with: chat-recall login ${
|
|
20139
|
+
throw classedError("auth", `server rejected this machine's device token (HTTP ${res.status} \u2014 revoked?). Reconnect with: chat-recall login ${base3}`);
|
|
20074
20140
|
}
|
|
20075
20141
|
if (res.status === 402) {
|
|
20076
20142
|
let detail = text;
|
|
@@ -20091,7 +20157,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20091
20157
|
const retryAfterS = Number(res.headers.get("retry-after"));
|
|
20092
20158
|
const waitMs = res.status === 429 && retryAfterS > 0 ? retryAfterS * 1e3 : RETRY_DELAYS_MS[attempt];
|
|
20093
20159
|
const why = res.status === 524 ? ` \u2014 the proxy cut the request at its time limit; the batch is too big for one request` : "";
|
|
20094
|
-
console.error(`[sync] HTTP ${res.status} from ${
|
|
20160
|
+
console.error(`[sync] HTTP ${res.status} from ${base3}${why} \u2014 backing off ${Math.round(waitMs / 1e3)}s (attempt ${attempt + 1})`);
|
|
20095
20161
|
await sleep(waitMs);
|
|
20096
20162
|
continue;
|
|
20097
20163
|
} catch (err) {
|
|
@@ -20159,11 +20225,11 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20159
20225
|
}
|
|
20160
20226
|
};
|
|
20161
20227
|
};
|
|
20162
|
-
const
|
|
20163
|
-
const ledger = opts.useLedger ? getSyncedRows(
|
|
20228
|
+
const base3 = cred.serverUrl.replace(/\/$/, "");
|
|
20229
|
+
const ledger = opts.useLedger ? getSyncedRows(base3) : null;
|
|
20164
20230
|
const convBatch = makeBatcher("conversations", 25, false, (rows) => {
|
|
20165
20231
|
try {
|
|
20166
|
-
markSynced(
|
|
20232
|
+
markSynced(base3, rows.map((r) => {
|
|
20167
20233
|
const off = typeof r.from_offset === "number" ? r.from_offset : 0;
|
|
20168
20234
|
const hash = shippedHash.get(r.session_id);
|
|
20169
20235
|
return off > 0 ? { id: r.session_id, mtime: r.mtime, offset: off, size: off, hash, acked: true } : { id: r.session_id, mtime: r.mtime, hash };
|
|
@@ -20178,7 +20244,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20178
20244
|
const ac = new AbortController();
|
|
20179
20245
|
const timer = setTimeout(() => ac.abort(new Error(`upload timed out after ${UPLOAD_TIMEOUT_MS}ms`)), UPLOAD_TIMEOUT_MS);
|
|
20180
20246
|
try {
|
|
20181
|
-
const res = await fetch(`${
|
|
20247
|
+
const res = await fetch(`${base3}/api/sync`, {
|
|
20182
20248
|
method: "POST",
|
|
20183
20249
|
headers,
|
|
20184
20250
|
body: JSON.stringify({ conversations: convs }),
|
|
@@ -20189,10 +20255,10 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20189
20255
|
if (body.cli && body.cli.version) {
|
|
20190
20256
|
const { planAutoUpdate: planAutoUpdate2, runAutoUpdate: runAutoUpdate2, sweepStaleStaging: sweepStaleStaging2 } = await Promise.resolve().then(() => (init_auto_update(), auto_update_exports));
|
|
20191
20257
|
const authHeaders = cred.token ? { authorization: `Bearer ${cred.token}` } : {};
|
|
20192
|
-
const plan = planAutoUpdate2(
|
|
20258
|
+
const plan = planAutoUpdate2(base3, { cli: body.cli }, ownVersion, process.env.CHAT_RECALL_AUTO_UPDATE);
|
|
20193
20259
|
sweepStaleStaging2();
|
|
20194
20260
|
if (plan.update) {
|
|
20195
|
-
void runAutoUpdate2(
|
|
20261
|
+
void runAutoUpdate2(base3, authHeaders, ownVersion).catch(() => {
|
|
20196
20262
|
});
|
|
20197
20263
|
}
|
|
20198
20264
|
}
|
|
@@ -20200,7 +20266,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20200
20266
|
const acked = convs.filter((c) => !fullNeeded.has(c.session_id));
|
|
20201
20267
|
if (acked.length > 0) {
|
|
20202
20268
|
try {
|
|
20203
|
-
markSynced(
|
|
20269
|
+
markSynced(base3, acked.map((c) => ({
|
|
20204
20270
|
id: c.session_id,
|
|
20205
20271
|
mtime: c.mtime,
|
|
20206
20272
|
offset: c.from_offset,
|
|
@@ -20224,7 +20290,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20224
20290
|
const ac = new AbortController();
|
|
20225
20291
|
const timer = setTimeout(() => ac.abort(new Error(`upload timed out after ${UPLOAD_TIMEOUT_MS}ms`)), UPLOAD_TIMEOUT_MS);
|
|
20226
20292
|
try {
|
|
20227
|
-
const res = await fetch(`${
|
|
20293
|
+
const res = await fetch(`${base3}/api/sync`, {
|
|
20228
20294
|
method: "POST",
|
|
20229
20295
|
headers,
|
|
20230
20296
|
body: JSON.stringify({ conversations: [conv] }),
|
|
@@ -20237,11 +20303,11 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20237
20303
|
const mtime = conv.mtime;
|
|
20238
20304
|
try {
|
|
20239
20305
|
if (!guarded) {
|
|
20240
|
-
markSynced(
|
|
20306
|
+
markSynced(base3, [{ id, mtime, offset: conv.from_offset, size: conv.from_offset, acked: true }]);
|
|
20241
20307
|
} else if (typeof guarded.o === "number" && guarded.o > 0 && guarded.o <= fileSize) {
|
|
20242
|
-
markSynced(
|
|
20308
|
+
markSynced(base3, [{ id, mtime, offset: guarded.o, size: guarded.o, acked: true }]);
|
|
20243
20309
|
} else {
|
|
20244
|
-
markSynced(
|
|
20310
|
+
markSynced(base3, [{ id, mtime }]);
|
|
20245
20311
|
}
|
|
20246
20312
|
} catch {
|
|
20247
20313
|
}
|
|
@@ -20307,7 +20373,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20307
20373
|
const m = process.memoryUsage();
|
|
20308
20374
|
console.error(`[sync-trace] ${msg} \xB7 heap=${(m.heapUsed / 1048576).toFixed(0)}MB rss=${(m.rss / 1048576).toFixed(0)}MB`);
|
|
20309
20375
|
} : null;
|
|
20310
|
-
trace?.(`walk start: ${slice.length} ref(s) \u2192 ${
|
|
20376
|
+
trace?.(`walk start: ${slice.length} ref(s) \u2192 ${base3}`);
|
|
20311
20377
|
if (upload.sessionMeta) {
|
|
20312
20378
|
try {
|
|
20313
20379
|
await reconcileFieldsForTarget(
|
|
@@ -20322,7 +20388,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20322
20388
|
{ convRefs: slice }
|
|
20323
20389
|
);
|
|
20324
20390
|
} catch (e) {
|
|
20325
|
-
console.error(`[sync] field reconcile (${
|
|
20391
|
+
console.error(`[sync] field reconcile (${base3}): ${e instanceof Error ? e.message : e}`);
|
|
20326
20392
|
}
|
|
20327
20393
|
}
|
|
20328
20394
|
trace?.("field reconcile done");
|
|
@@ -20364,7 +20430,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20364
20430
|
}
|
|
20365
20431
|
trace?.("conversation walk start");
|
|
20366
20432
|
const walkStartedAt = Date.now();
|
|
20367
|
-
const firstWalk = (ledger ?? getSyncedRows(
|
|
20433
|
+
const firstWalk = (ledger ?? getSyncedRows(base3)).size === 0;
|
|
20368
20434
|
reportWalkProgress({ done: 0, total: slice.length, startedAt: walkStartedAt, complete: false, first: firstWalk });
|
|
20369
20435
|
walkProgressForUpload = { done: 0, total: slice.length, complete: false };
|
|
20370
20436
|
let traceN = 0;
|
|
@@ -20404,7 +20470,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20404
20470
|
continue;
|
|
20405
20471
|
} else {
|
|
20406
20472
|
try {
|
|
20407
|
-
markSynced(
|
|
20473
|
+
markSynced(base3, [{ id: ref.prefixedId, mtime: ref.mtime }]);
|
|
20408
20474
|
} catch {
|
|
20409
20475
|
}
|
|
20410
20476
|
skipped++;
|
|
@@ -20427,7 +20493,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20427
20493
|
const off = getBackendForId(ref.prefixedId)?.fileSize?.(ref.rawId) ?? 0;
|
|
20428
20494
|
const priorCursor = ackRow?.s ?? 0;
|
|
20429
20495
|
const safeToAck = off > 0 && off <= priorCursor;
|
|
20430
|
-
markSynced(
|
|
20496
|
+
markSynced(base3, [safeToAck ? { id: ref.prefixedId, mtime: ref.mtime, offset: off, size: off, hash: built.srcHash, acked: true } : { id: ref.prefixedId, mtime: ref.mtime, hash: built.srcHash }]);
|
|
20431
20497
|
} catch {
|
|
20432
20498
|
}
|
|
20433
20499
|
}
|
|
@@ -20437,7 +20503,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20437
20503
|
if (!built) {
|
|
20438
20504
|
if (ledger) {
|
|
20439
20505
|
try {
|
|
20440
|
-
markSynced(
|
|
20506
|
+
markSynced(base3, [{ id: ref.prefixedId, mtime: ref.mtime }]);
|
|
20441
20507
|
} catch {
|
|
20442
20508
|
}
|
|
20443
20509
|
}
|
|
@@ -20494,7 +20560,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20494
20560
|
walked++;
|
|
20495
20561
|
if (walked % 250 === 0) console.error(`[sync] ${walked}/${slice.length} sessions\u2026`);
|
|
20496
20562
|
}
|
|
20497
|
-
const itemVersions = loadItemVersions(
|
|
20563
|
+
const itemVersions = loadItemVersions(base3);
|
|
20498
20564
|
const seenTools = /* @__PURE__ */ new Set();
|
|
20499
20565
|
const seenItemKeys = /* @__PURE__ */ new Map();
|
|
20500
20566
|
const registry = buildSourceRegistry();
|
|
@@ -20588,7 +20654,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20588
20654
|
await appendFlush();
|
|
20589
20655
|
for (const id of appendResults.fullResyncNeeded) {
|
|
20590
20656
|
try {
|
|
20591
|
-
markFullResync(
|
|
20657
|
+
markFullResync(base3, id);
|
|
20592
20658
|
} catch {
|
|
20593
20659
|
}
|
|
20594
20660
|
}
|
|
@@ -20601,7 +20667,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20601
20667
|
await findingsBatch.drain();
|
|
20602
20668
|
await drainInflight();
|
|
20603
20669
|
{
|
|
20604
|
-
const sentHashes = loadInventoryHashes(
|
|
20670
|
+
const sentHashes = loadInventoryHashes(base3);
|
|
20605
20671
|
const entries = [];
|
|
20606
20672
|
const hashes = {};
|
|
20607
20673
|
for (const [sourceType, ids] of inventory) {
|
|
@@ -20615,7 +20681,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20615
20681
|
if (entries.length > 0) {
|
|
20616
20682
|
try {
|
|
20617
20683
|
await post({ inventory: entries });
|
|
20618
|
-
saveInventoryHashes(
|
|
20684
|
+
saveInventoryHashes(base3, hashes);
|
|
20619
20685
|
} catch (err) {
|
|
20620
20686
|
console.error(`[sync] toolkit inventory not sent (it is retried next sync): ${err instanceof Error ? err.message : err}`);
|
|
20621
20687
|
}
|
|
@@ -20626,7 +20692,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20626
20692
|
const rec = {};
|
|
20627
20693
|
for (const t of seenTools) rec[t] = extractorVersionForTool(t);
|
|
20628
20694
|
for (const [k, v] of seenItemKeys) rec[k] = v;
|
|
20629
|
-
saveItemVersions(
|
|
20695
|
+
saveItemVersions(base3, rec);
|
|
20630
20696
|
} catch {
|
|
20631
20697
|
}
|
|
20632
20698
|
}
|
|
@@ -20639,9 +20705,9 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20639
20705
|
}
|
|
20640
20706
|
if (tombstones.length > 0) {
|
|
20641
20707
|
await post({ tombstones });
|
|
20642
|
-
const data = getLedgerData(
|
|
20708
|
+
const data = getLedgerData(base3);
|
|
20643
20709
|
for (const t of tombstones) delete data[t.session_id];
|
|
20644
|
-
persistLedgerData(
|
|
20710
|
+
persistLedgerData(base3, data);
|
|
20645
20711
|
}
|
|
20646
20712
|
}
|
|
20647
20713
|
if (opts.prune) await post({ prune_empty_sessions: true });
|
|
@@ -21112,7 +21178,7 @@ var init_sync_client = __esm({
|
|
|
21112
21178
|
ownVersion = JSON.parse(readFileSync35(join42(dir, "../package.json"), "utf-8")).version || ownVersion;
|
|
21113
21179
|
} catch {
|
|
21114
21180
|
try {
|
|
21115
|
-
if (true) ownVersion = "0.7.
|
|
21181
|
+
if (true) ownVersion = "0.7.15";
|
|
21116
21182
|
} catch {
|
|
21117
21183
|
}
|
|
21118
21184
|
}
|
|
@@ -21171,10 +21237,10 @@ function parseAgentText(content, format, fallbackName) {
|
|
|
21171
21237
|
return { name: fm.name || fallbackName, description: fm.description || "", tools: fm.tools, body: body.trim() };
|
|
21172
21238
|
}
|
|
21173
21239
|
function readCommand(filePath, format) {
|
|
21174
|
-
return parseCommandText(readFileSync36(filePath, "utf-8"), format,
|
|
21240
|
+
return parseCommandText(readFileSync36(filePath, "utf-8"), format, base2(filePath));
|
|
21175
21241
|
}
|
|
21176
21242
|
function readAgent(filePath, format) {
|
|
21177
|
-
return parseAgentText(readFileSync36(filePath, "utf-8"), format,
|
|
21243
|
+
return parseAgentText(readFileSync36(filePath, "utf-8"), format, base2(filePath));
|
|
21178
21244
|
}
|
|
21179
21245
|
function readInstructions(filePath, name) {
|
|
21180
21246
|
const content = readFileSync36(filePath, "utf-8");
|
|
@@ -21274,7 +21340,7 @@ function emit(type, art, toTool, projectPath) {
|
|
|
21274
21340
|
content: stringifyFrontmatter({ name: art.name, description: art.description, ...art.tools ? { tools: art.tools } : {} }, art.body)
|
|
21275
21341
|
};
|
|
21276
21342
|
}
|
|
21277
|
-
function
|
|
21343
|
+
function base2(filePath) {
|
|
21278
21344
|
return basename21(filePath).replace(/\.(md|toml)$/, "");
|
|
21279
21345
|
}
|
|
21280
21346
|
var init_artifact_codec = __esm({
|
|
@@ -21712,11 +21778,11 @@ var init_toolkit_sync = __esm({
|
|
|
21712
21778
|
});
|
|
21713
21779
|
|
|
21714
21780
|
// ../engine/dist/core/which.js
|
|
21715
|
-
import { existsSync as existsSync44, statSync as
|
|
21781
|
+
import { existsSync as existsSync44, statSync as statSync40, accessSync, constants } from "node:fs";
|
|
21716
21782
|
import { join as join46, isAbsolute as isAbsolute2, delimiter as delimiter2, sep as sep3 } from "node:path";
|
|
21717
21783
|
function executable(p) {
|
|
21718
21784
|
try {
|
|
21719
|
-
if (!
|
|
21785
|
+
if (!statSync40(p).isFile())
|
|
21720
21786
|
return false;
|
|
21721
21787
|
} catch {
|
|
21722
21788
|
return false;
|
|
@@ -21779,11 +21845,11 @@ __export(toolkit_pull_exports, {
|
|
|
21779
21845
|
platformRefusal: () => platformRefusal,
|
|
21780
21846
|
portableCommand: () => portableCommand
|
|
21781
21847
|
});
|
|
21782
|
-
import { existsSync as existsSync45, mkdirSync as mkdirSync13, statSync as
|
|
21848
|
+
import { existsSync as existsSync45, mkdirSync as mkdirSync13, statSync as statSync41, writeFileSync as writeFileSync12 } from "node:fs";
|
|
21783
21849
|
import { dirname as dirname22, join as join47, basename as basename23, isAbsolute as isAbsolute3 } from "node:path";
|
|
21784
21850
|
function isExecutableFile(p) {
|
|
21785
21851
|
try {
|
|
21786
|
-
return
|
|
21852
|
+
return statSync41(p).isFile();
|
|
21787
21853
|
} catch {
|
|
21788
21854
|
return false;
|
|
21789
21855
|
}
|
|
@@ -21797,9 +21863,9 @@ function portableCommand(cmd) {
|
|
|
21797
21863
|
}
|
|
21798
21864
|
if (isExecutableFile(cmd))
|
|
21799
21865
|
return { command: cmd, rewritten: false };
|
|
21800
|
-
const
|
|
21801
|
-
if (onPath(
|
|
21802
|
-
return { command:
|
|
21866
|
+
const base3 = basename23(cmd);
|
|
21867
|
+
if (onPath(base3))
|
|
21868
|
+
return { command: base3, rewritten: true };
|
|
21803
21869
|
return { missing: cmd };
|
|
21804
21870
|
}
|
|
21805
21871
|
function entryFromSpec(spec) {
|
|
@@ -22316,7 +22382,7 @@ __export(shadow_prune_exports, {
|
|
|
22316
22382
|
DEFAULT_MAX_TOTAL_BYTES: () => DEFAULT_MAX_TOTAL_BYTES,
|
|
22317
22383
|
pruneShadow: () => pruneShadow
|
|
22318
22384
|
});
|
|
22319
|
-
import { readdirSync as readdirSync32, statSync as
|
|
22385
|
+
import { readdirSync as readdirSync32, statSync as statSync44, unlinkSync as unlinkSync3 } from "fs";
|
|
22320
22386
|
import { join as join50 } from "path";
|
|
22321
22387
|
function listShadows(isFullyAcked) {
|
|
22322
22388
|
const out = [];
|
|
@@ -22341,7 +22407,7 @@ function listShadows(isFullyAcked) {
|
|
|
22341
22407
|
const path = join50(dir, name);
|
|
22342
22408
|
let st;
|
|
22343
22409
|
try {
|
|
22344
|
-
st =
|
|
22410
|
+
st = statSync44(path);
|
|
22345
22411
|
} catch {
|
|
22346
22412
|
continue;
|
|
22347
22413
|
}
|
|
@@ -22456,7 +22522,7 @@ var init_code_intel = __esm({
|
|
|
22456
22522
|
});
|
|
22457
22523
|
|
|
22458
22524
|
// ../engine/dist/core/companions.js
|
|
22459
|
-
import { existsSync as existsSync48, mkdirSync as mkdirSync16, statSync as
|
|
22525
|
+
import { existsSync as existsSync48, mkdirSync as mkdirSync16, statSync as statSync45, chmodSync as chmodSync4, unlinkSync as unlinkSync4, renameSync as renameSync5, createWriteStream, readFileSync as readFileSync42, writeFileSync as writeFileSync15 } from "node:fs";
|
|
22460
22526
|
import { homedir as homedir19 } from "node:os";
|
|
22461
22527
|
import { join as join51 } from "node:path";
|
|
22462
22528
|
import { execSync as execSync3 } from "node:child_process";
|
|
@@ -22507,7 +22573,7 @@ function checkCodeindexStatus() {
|
|
|
22507
22573
|
status.installed = true;
|
|
22508
22574
|
status.path = foundPath;
|
|
22509
22575
|
try {
|
|
22510
|
-
status.size =
|
|
22576
|
+
status.size = statSync45(foundPath).size;
|
|
22511
22577
|
} catch {
|
|
22512
22578
|
}
|
|
22513
22579
|
try {
|
|
@@ -22847,17 +22913,17 @@ async function collectCode(opts) {
|
|
|
22847
22913
|
return r;
|
|
22848
22914
|
};
|
|
22849
22915
|
log6(`indexing ${ws} + analyses \u2026`);
|
|
22850
|
-
const
|
|
22916
|
+
const base3 = await runMcp(bin, ws, [
|
|
22851
22917
|
call(1, "index_workspace", { path: ws }),
|
|
22852
22918
|
call(2, "status"),
|
|
22853
22919
|
call(3, "get_tree"),
|
|
22854
22920
|
...ANALYSES.map((a, i) => call(10 + i, "analyze", { analysis: a }))
|
|
22855
22921
|
]);
|
|
22856
|
-
const st = parseJson(
|
|
22857
|
-
const tree = parseJson(
|
|
22922
|
+
const st = parseJson(base3, 2, {});
|
|
22923
|
+
const tree = parseJson(base3, 3, []);
|
|
22858
22924
|
const A = {};
|
|
22859
22925
|
ANALYSES.forEach((a, i) => {
|
|
22860
|
-
A[a] = parseJson(
|
|
22926
|
+
A[a] = parseJson(base3, 10 + i, {});
|
|
22861
22927
|
});
|
|
22862
22928
|
const { health, security: sec, duplication: dup, clones, literal_scan: lit, coupling: coup, cycles: cyc, dead_code: dead, unwrap_audit: unwrap, test_coverage: coverage, architecture: arch, crossref, type_drift: typeDrift, db_schema: dbSchema, migration_parity: migParity, manifest_compliance: manifest } = A;
|
|
22863
22929
|
if (tree.length === 0) {
|
|
@@ -23950,7 +24016,7 @@ import { join as join48 } from "node:path";
|
|
|
23950
24016
|
|
|
23951
24017
|
// src/project-tasks.ts
|
|
23952
24018
|
init_http();
|
|
23953
|
-
import { existsSync as existsSync43, readFileSync as readFileSync38, writeFileSync as writeFileSync11, mkdirSync as mkdirSync12, statSync as
|
|
24019
|
+
import { existsSync as existsSync43, readFileSync as readFileSync38, writeFileSync as writeFileSync11, mkdirSync as mkdirSync12, statSync as statSync39 } from "node:fs";
|
|
23954
24020
|
import { join as join45, dirname as dirname21 } from "node:path";
|
|
23955
24021
|
import { homedir as homedir18 } from "node:os";
|
|
23956
24022
|
|
|
@@ -24043,14 +24109,14 @@ var FILE_KINDS = [
|
|
|
24043
24109
|
{ kind: "secret", filename: "SECURITY_TASKS.md", trackedPath: "/api/secrets/tasks/tracked", statusPath: "/api/secrets/tasks/status" },
|
|
24044
24110
|
{ kind: "code", filename: "CODE_TASKS.md", trackedPath: "/api/code/tasks/tracked", statusPath: "/api/code/tasks/status" }
|
|
24045
24111
|
];
|
|
24046
|
-
async function pushProjectTaskStatuses(
|
|
24112
|
+
async function pushProjectTaskStatuses(base3, authHeaders, opts = {}) {
|
|
24047
24113
|
const out = { files: 0, pushedTasks: 0 };
|
|
24048
24114
|
const ledger = readLedger();
|
|
24049
24115
|
let ledgerDirty = false;
|
|
24050
24116
|
for (const fk of FILE_KINDS) {
|
|
24051
24117
|
let projects;
|
|
24052
24118
|
try {
|
|
24053
|
-
const res = await fetchWithTimeout(`${
|
|
24119
|
+
const res = await fetchWithTimeout(`${base3}${fk.trackedPath}`, { headers: authHeaders });
|
|
24054
24120
|
if (!res.ok) continue;
|
|
24055
24121
|
projects = (await res.json()).projects || [];
|
|
24056
24122
|
} catch {
|
|
@@ -24061,7 +24127,7 @@ async function pushProjectTaskStatuses(base2, authHeaders, opts = {}) {
|
|
|
24061
24127
|
if (!existsSync43(file)) continue;
|
|
24062
24128
|
let mtime;
|
|
24063
24129
|
try {
|
|
24064
|
-
mtime =
|
|
24130
|
+
mtime = statSync39(file).mtimeMs;
|
|
24065
24131
|
} catch {
|
|
24066
24132
|
continue;
|
|
24067
24133
|
}
|
|
@@ -24078,7 +24144,7 @@ async function pushProjectTaskStatuses(base2, authHeaders, opts = {}) {
|
|
|
24078
24144
|
continue;
|
|
24079
24145
|
}
|
|
24080
24146
|
try {
|
|
24081
|
-
const res = await fetchWithTimeout(`${
|
|
24147
|
+
const res = await fetchWithTimeout(`${base3}${fk.statusPath}`, {
|
|
24082
24148
|
method: "POST",
|
|
24083
24149
|
headers: { "content-type": "application/json", ...authHeaders },
|
|
24084
24150
|
body: JSON.stringify({ project, items: changed.map((t) => ({ id: t.id, status: t.intent })) })
|
|
@@ -24168,16 +24234,16 @@ ${block}`);
|
|
|
24168
24234
|
return { status: "error", result: JSON.stringify({ error: e instanceof Error ? e.message : "failed" }) };
|
|
24169
24235
|
}
|
|
24170
24236
|
}
|
|
24171
|
-
async function runPull(
|
|
24237
|
+
async function runPull(base3, opts) {
|
|
24172
24238
|
const { executePull: executePull2 } = await Promise.resolve().then(() => (init_toolkit_pull(), toolkit_pull_exports));
|
|
24173
24239
|
const { hostname: hostname3 } = await import("node:os");
|
|
24174
|
-
const creds = loadAllCredentials().find((c) => c.serverUrl.replace(/\/+$/, "") ===
|
|
24240
|
+
const creds = loadAllCredentials().find((c) => c.serverUrl.replace(/\/+$/, "") === base3.replace(/\/+$/, ""));
|
|
24175
24241
|
const headers = creds?.token ? { authorization: `Bearer ${creds.token}` } : {};
|
|
24176
24242
|
const wanted = opts.types?.length ? opts.types : ["mcp", "skill", "command", "agent", "instructions"];
|
|
24177
24243
|
const rows = [];
|
|
24178
24244
|
for (const type of wanted) {
|
|
24179
24245
|
try {
|
|
24180
|
-
const res = await fetchWithTimeout(`${
|
|
24246
|
+
const res = await fetchWithTimeout(`${base3}/api/toolkit/browse/${type}?limit=1000`, { headers });
|
|
24181
24247
|
if (!res.ok) continue;
|
|
24182
24248
|
const body = await res.json();
|
|
24183
24249
|
for (const it of body.items || []) rows.push(it);
|
|
@@ -24249,27 +24315,27 @@ try {
|
|
|
24249
24315
|
ownVersion2 = JSON.parse(readFileSync39(join48(dir, "../package.json"), "utf-8")).version || ownVersion2;
|
|
24250
24316
|
} catch {
|
|
24251
24317
|
try {
|
|
24252
|
-
if (true) ownVersion2 = "0.7.
|
|
24318
|
+
if (true) ownVersion2 = "0.7.15";
|
|
24253
24319
|
} catch {
|
|
24254
24320
|
}
|
|
24255
24321
|
}
|
|
24256
24322
|
async function drainSyncIntents(opts = {}) {
|
|
24257
24323
|
const out = { processed: 0, done: 0, errored: 0 };
|
|
24258
24324
|
for (const cred of loadAllCredentials()) {
|
|
24259
|
-
const
|
|
24325
|
+
const base3 = cred.serverUrl.replace(/\/+$/, "");
|
|
24260
24326
|
const authHeaders = cred.token ? { authorization: `Bearer ${cred.token}` } : {};
|
|
24261
24327
|
let pending;
|
|
24262
24328
|
try {
|
|
24263
|
-
const res = await fetchWithTimeout(`${
|
|
24329
|
+
const res = await fetchWithTimeout(`${base3}/api/sync-intents/pending`, { headers: authHeaders });
|
|
24264
24330
|
if (!res.ok) continue;
|
|
24265
24331
|
const data = await res.json();
|
|
24266
24332
|
pending = data.intents || [];
|
|
24267
24333
|
if (data.cli && data.cli.version) {
|
|
24268
24334
|
const { planAutoUpdate: planAutoUpdate2, runAutoUpdate: runAutoUpdate2, sweepStaleStaging: sweepStaleStaging2 } = await Promise.resolve().then(() => (init_auto_update(), auto_update_exports));
|
|
24269
|
-
const plan = planAutoUpdate2(
|
|
24335
|
+
const plan = planAutoUpdate2(base3, { cli: data.cli }, ownVersion2, process.env.CHAT_RECALL_AUTO_UPDATE);
|
|
24270
24336
|
sweepStaleStaging2();
|
|
24271
24337
|
if (plan.update) {
|
|
24272
|
-
void runAutoUpdate2(
|
|
24338
|
+
void runAutoUpdate2(base3, authHeaders, ownVersion2).catch(() => {
|
|
24273
24339
|
});
|
|
24274
24340
|
}
|
|
24275
24341
|
}
|
|
@@ -24277,7 +24343,7 @@ async function drainSyncIntents(opts = {}) {
|
|
|
24277
24343
|
continue;
|
|
24278
24344
|
}
|
|
24279
24345
|
for (const intent of pending) {
|
|
24280
|
-
const { status, result } = await runIntent(intent, { base:
|
|
24346
|
+
const { status, result } = await runIntent(intent, { base: base3 });
|
|
24281
24347
|
out.processed++;
|
|
24282
24348
|
if (status === "done") out.done++;
|
|
24283
24349
|
else out.errored++;
|
|
@@ -24286,7 +24352,7 @@ async function drainSyncIntents(opts = {}) {
|
|
|
24286
24352
|
console.error(`[sync-intent] ${label}: ${status}`);
|
|
24287
24353
|
}
|
|
24288
24354
|
try {
|
|
24289
|
-
await fetchWithTimeout(`${
|
|
24355
|
+
await fetchWithTimeout(`${base3}/api/sync-intents/${intent.id}/ack`, {
|
|
24290
24356
|
method: "POST",
|
|
24291
24357
|
headers: { "content-type": "application/json", ...authHeaders },
|
|
24292
24358
|
body: JSON.stringify({ status, result })
|
|
@@ -24295,7 +24361,7 @@ async function drainSyncIntents(opts = {}) {
|
|
|
24295
24361
|
}
|
|
24296
24362
|
}
|
|
24297
24363
|
try {
|
|
24298
|
-
await pushProjectTaskStatuses(
|
|
24364
|
+
await pushProjectTaskStatuses(base3, authHeaders, { verbose: opts.verbose });
|
|
24299
24365
|
} catch {
|
|
24300
24366
|
}
|
|
24301
24367
|
}
|
|
@@ -24314,7 +24380,7 @@ init_auto_update();
|
|
|
24314
24380
|
|
|
24315
24381
|
// src/code-index-cursor.ts
|
|
24316
24382
|
init_paths();
|
|
24317
|
-
import { readFileSync as readFileSync40, writeFileSync as writeFileSync14, mkdirSync as mkdirSync15, statSync as
|
|
24383
|
+
import { readFileSync as readFileSync40, writeFileSync as writeFileSync14, mkdirSync as mkdirSync15, statSync as statSync42 } from "fs";
|
|
24318
24384
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
24319
24385
|
import { createHash as createHash10 } from "crypto";
|
|
24320
24386
|
import { join as join49, dirname as dirname24 } from "path";
|
|
@@ -24365,7 +24431,7 @@ function workspaceFingerprint(workspace, collectorVersion) {
|
|
|
24365
24431
|
const rel = entry.slice(3);
|
|
24366
24432
|
let stamp2 = "gone";
|
|
24367
24433
|
try {
|
|
24368
|
-
const s =
|
|
24434
|
+
const s = statSync42(join49(workspace, rel));
|
|
24369
24435
|
stamp2 = `${s.size}:${Math.floor(s.mtimeMs)}`;
|
|
24370
24436
|
} catch {
|
|
24371
24437
|
}
|
|
@@ -24574,11 +24640,11 @@ function checkSelfRestart(opts) {
|
|
|
24574
24640
|
}
|
|
24575
24641
|
|
|
24576
24642
|
// src/log-rotate.ts
|
|
24577
|
-
import { statSync as
|
|
24643
|
+
import { statSync as statSync43, copyFileSync as copyFileSync3, truncateSync } from "fs";
|
|
24578
24644
|
var LOG_MAX_BYTES = 32 * 1024 * 1024;
|
|
24579
24645
|
function rotateLogIfLarge(logPath, maxBytes = LOG_MAX_BYTES) {
|
|
24580
24646
|
try {
|
|
24581
|
-
const size =
|
|
24647
|
+
const size = statSync43(logPath).size;
|
|
24582
24648
|
if (size < maxBytes) return { rotated: false, sizeBefore: 0 };
|
|
24583
24649
|
copyFileSync3(logPath, `${logPath}.1`);
|
|
24584
24650
|
truncateSync(logPath, 0);
|
|
@@ -24633,8 +24699,8 @@ async function runCollectorMigration(opts) {
|
|
|
24633
24699
|
// auto-indexer/indexer.ts
|
|
24634
24700
|
init_sync_ledger();
|
|
24635
24701
|
init_collector_health();
|
|
24636
|
-
import { existsSync as existsSync50, readFileSync as readFileSync45, statSync as
|
|
24637
|
-
var CLI_VERSION3 = true ? "0.7.
|
|
24702
|
+
import { existsSync as existsSync50, readFileSync as readFileSync45, statSync as statSync46 } from "fs";
|
|
24703
|
+
var CLI_VERSION3 = true ? "0.7.15" : "0.0.0";
|
|
24638
24704
|
var DEBOUNCE_MS = 5e3;
|
|
24639
24705
|
var PLANS_DIR = claudeBackend.plansDir();
|
|
24640
24706
|
var TASKS_DIR = claudeBackend.tasksDir();
|
|
@@ -24739,7 +24805,7 @@ var CLAUDE_SESSION_ROOTS = claudeProjectDirs();
|
|
|
24739
24805
|
var sessionWatcher = watchWithFallback("sessions", CLAUDE_SESSION_ROOTS.map((root) => `${root}/**/*.jsonl`), {
|
|
24740
24806
|
ignored: (p, stats) => {
|
|
24741
24807
|
if (/agent-/.test(p) || /^\./.test(basename25(p))) return true;
|
|
24742
|
-
const st = stats ??
|
|
24808
|
+
const st = stats ?? statSync46(p, { throwIfNoEntry: false });
|
|
24743
24809
|
if (!st || st.isDirectory()) return false;
|
|
24744
24810
|
return st.mtimeMs < Date.now() - WATCH_WINDOW_MS;
|
|
24745
24811
|
},
|
|
@@ -25109,10 +25175,10 @@ async function codeIndexTick() {
|
|
|
25109
25175
|
continue;
|
|
25110
25176
|
}
|
|
25111
25177
|
for (const cred of creds) {
|
|
25112
|
-
const
|
|
25178
|
+
const base3 = cred.serverUrl.replace(/\/+$/, "");
|
|
25113
25179
|
const headers = { "content-type": "application/json", ...cred.token ? { authorization: `Bearer ${cred.token}` } : {} };
|
|
25114
25180
|
try {
|
|
25115
|
-
await fetchWithTimeout(`${
|
|
25181
|
+
await fetchWithTimeout(`${base3}/api/code/index`, { method: "POST", headers, body: JSON.stringify(result) }, 6e4);
|
|
25116
25182
|
} catch {
|
|
25117
25183
|
}
|
|
25118
25184
|
}
|
|
@@ -25135,12 +25201,12 @@ if (CODE_INDEX_ON) {
|
|
|
25135
25201
|
}
|
|
25136
25202
|
async function autoUpdateTick() {
|
|
25137
25203
|
for (const cred of loadAllCredentials()) {
|
|
25138
|
-
const
|
|
25204
|
+
const base3 = cred.serverUrl.replace(/\/+$/, "");
|
|
25139
25205
|
const headers = cred.token ? { authorization: `Bearer ${cred.token}` } : {};
|
|
25140
25206
|
try {
|
|
25141
|
-
const r = await runAutoUpdate(
|
|
25142
|
-
if (r.updated) daemonLog.info(`auto-update: ${r.reason} (${
|
|
25143
|
-
else if (!/already current|disabled|no CLI release/.test(r.reason)) daemonLog.info(`auto-update: ${r.reason} (${
|
|
25207
|
+
const r = await runAutoUpdate(base3, headers, CLI_VERSION3);
|
|
25208
|
+
if (r.updated) daemonLog.info(`auto-update: ${r.reason} (${base3}) \u2014 restarting service`);
|
|
25209
|
+
else if (!/already current|disabled|no CLI release/.test(r.reason)) daemonLog.info(`auto-update: ${r.reason} (${base3})`);
|
|
25144
25210
|
} catch {
|
|
25145
25211
|
}
|
|
25146
25212
|
}
|
|
@@ -25167,20 +25233,20 @@ async function collectorMigrationOnce() {
|
|
|
25167
25233
|
return;
|
|
25168
25234
|
}
|
|
25169
25235
|
for (const cred of creds) {
|
|
25170
|
-
const
|
|
25236
|
+
const base3 = cred.serverUrl.replace(/\/+$/, "");
|
|
25171
25237
|
const headers = { "content-type": "application/json", ...cred.token ? { authorization: `Bearer ${cred.token}` } : {} };
|
|
25172
25238
|
const reindex = async (rootPath) => {
|
|
25173
25239
|
try {
|
|
25174
25240
|
const result = await collectCode2({ workspace: rootPath, binPath: bin });
|
|
25175
|
-
const res = await fetchWithTimeout(`${
|
|
25241
|
+
const res = await fetchWithTimeout(`${base3}/api/code/index`, { method: "POST", headers, body: JSON.stringify(result) }, 6e4);
|
|
25176
25242
|
return res.ok;
|
|
25177
25243
|
} catch {
|
|
25178
25244
|
return false;
|
|
25179
25245
|
}
|
|
25180
25246
|
};
|
|
25181
25247
|
try {
|
|
25182
|
-
const r = await runCollectorMigration({ base:
|
|
25183
|
-
if (r.reindexed || r.failed || r.missing) daemonLog.info(`collector migration (${
|
|
25248
|
+
const r = await runCollectorMigration({ base: base3, authHeaders: headers, current: COLLECTOR_VERSION2, reindex, log: (m) => daemonLog.info(`${m}`) });
|
|
25249
|
+
if (r.reindexed || r.failed || r.missing) daemonLog.info(`collector migration (${base3}): re-derived ${r.reindexed}, failed ${r.failed}, skipped-missing ${r.missing}`);
|
|
25184
25250
|
} catch {
|
|
25185
25251
|
}
|
|
25186
25252
|
}
|