chat-recall 0.7.14 → 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 +348 -283
- 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 +255 -190
- 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 +297 -230
- 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);
|
|
@@ -12280,8 +12280,8 @@ function serverRulePackVersion() {
|
|
|
12280
12280
|
return serverPack ? serverPack.version || "unversioned" : null;
|
|
12281
12281
|
}
|
|
12282
12282
|
function activeRules() {
|
|
12283
|
-
const
|
|
12284
|
-
return serverPack && serverPack.rules.length > 0 ? [...
|
|
12283
|
+
const base3 = settingsView().rules;
|
|
12284
|
+
return serverPack && serverPack.rules.length > 0 ? [...base3, ...serverPack.rules] : base3;
|
|
12285
12285
|
}
|
|
12286
12286
|
function isRedactionEnabled() {
|
|
12287
12287
|
const env = isEnvRedactionRequested();
|
|
@@ -18064,7 +18064,7 @@ __export(sync_ledger_exports, {
|
|
|
18064
18064
|
syncMode: () => syncMode,
|
|
18065
18065
|
unackedCursorAttemptCount: () => unackedCursorAttemptCount
|
|
18066
18066
|
});
|
|
18067
|
-
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";
|
|
18068
18068
|
import { join as join39, dirname as dirname16 } from "node:path";
|
|
18069
18069
|
function toRow(entry) {
|
|
18070
18070
|
if (entry === void 0) return void 0;
|
|
@@ -18073,32 +18073,94 @@ function toRow(entry) {
|
|
|
18073
18073
|
function ledgerFilePath() {
|
|
18074
18074
|
return ledgerPath();
|
|
18075
18075
|
}
|
|
18076
|
-
function
|
|
18077
|
-
|
|
18076
|
+
function stampOf(path) {
|
|
18077
|
+
try {
|
|
18078
|
+
const st = statSync35(path);
|
|
18079
|
+
return `${st.mtimeMs}:${st.size}`;
|
|
18080
|
+
} catch {
|
|
18081
|
+
return null;
|
|
18082
|
+
}
|
|
18083
|
+
}
|
|
18084
|
+
function readDisk(path) {
|
|
18078
18085
|
try {
|
|
18079
|
-
const parsed = JSON.parse(readFileSync30(
|
|
18080
|
-
|
|
18086
|
+
const parsed = JSON.parse(readFileSync30(path, "utf-8"));
|
|
18087
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
18081
18088
|
} catch {
|
|
18082
|
-
|
|
18089
|
+
return {};
|
|
18083
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;
|
|
18084
18143
|
return cache3;
|
|
18085
18144
|
}
|
|
18086
|
-
function persistNow(
|
|
18145
|
+
function persistNow() {
|
|
18087
18146
|
const path = ledgerPath();
|
|
18088
18147
|
mkdirSync7(dirname16(path), { recursive: true });
|
|
18089
|
-
|
|
18090
|
-
|
|
18148
|
+
load();
|
|
18149
|
+
const tmp = `${path}.tmp-${process.pid}`;
|
|
18150
|
+
writeFileSync6(tmp, JSON.stringify(cache3 ?? {}));
|
|
18091
18151
|
renameSync4(tmp, path);
|
|
18152
|
+
base = snapshot(cache3 ?? {});
|
|
18153
|
+
diskStamp = stampOf(path);
|
|
18092
18154
|
pendingWrite = false;
|
|
18093
18155
|
}
|
|
18094
|
-
function persist(
|
|
18156
|
+
function persist(_data) {
|
|
18095
18157
|
pendingWrite = true;
|
|
18096
18158
|
if (flushTimer) return;
|
|
18097
18159
|
flushTimer = setTimeout(() => {
|
|
18098
18160
|
flushTimer = null;
|
|
18099
18161
|
if (pendingWrite) {
|
|
18100
18162
|
try {
|
|
18101
|
-
persistNow(
|
|
18163
|
+
persistNow();
|
|
18102
18164
|
} catch {
|
|
18103
18165
|
}
|
|
18104
18166
|
}
|
|
@@ -18132,7 +18194,7 @@ function pruneLedgerTargets(configuredServers) {
|
|
|
18132
18194
|
}
|
|
18133
18195
|
const rows = names.reduce((n, s) => n + Object.keys(orphans[s]).length, 0);
|
|
18134
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.`);
|
|
18135
|
-
persistNow(
|
|
18197
|
+
persistNow();
|
|
18136
18198
|
return names.length;
|
|
18137
18199
|
}
|
|
18138
18200
|
function flushLedger() {
|
|
@@ -18141,7 +18203,7 @@ function flushLedger() {
|
|
|
18141
18203
|
flushTimer = null;
|
|
18142
18204
|
}
|
|
18143
18205
|
if (!pendingWrite || !cache3) return;
|
|
18144
|
-
persistNow(
|
|
18206
|
+
persistNow();
|
|
18145
18207
|
}
|
|
18146
18208
|
function loadItemVersionsAll() {
|
|
18147
18209
|
if (itemVersionsCache) return itemVersionsCache;
|
|
@@ -18229,13 +18291,13 @@ function markSynced(server, rows) {
|
|
|
18229
18291
|
const o = (cursorFromCaller ? r.offset : void 0) ?? prevOS.o ?? 0;
|
|
18230
18292
|
const s = (cursorFromCaller ? r.size : void 0) ?? prevOS.s ?? 0;
|
|
18231
18293
|
const ev = extractorVersionForId(r.id);
|
|
18232
|
-
const
|
|
18294
|
+
const base3 = prevF ? { m: Math.floor(r.mtime), v: ev, f: prevF } : { m: Math.floor(r.mtime), v: ev };
|
|
18233
18295
|
if (o > 0 || s > 0) {
|
|
18234
|
-
|
|
18235
|
-
|
|
18296
|
+
base3.o = o;
|
|
18297
|
+
base3.s = s;
|
|
18236
18298
|
}
|
|
18237
|
-
if (r.hash !== void 0)
|
|
18238
|
-
forServer[r.id] =
|
|
18299
|
+
if (r.hash !== void 0) base3.h = r.hash;
|
|
18300
|
+
forServer[r.id] = base3;
|
|
18239
18301
|
}
|
|
18240
18302
|
persist(data);
|
|
18241
18303
|
}
|
|
@@ -18304,6 +18366,8 @@ function forceFieldRescan(fieldName, server) {
|
|
|
18304
18366
|
function _resetLedgerCacheForTests() {
|
|
18305
18367
|
flushLedger();
|
|
18306
18368
|
cache3 = null;
|
|
18369
|
+
base = /* @__PURE__ */ new Map();
|
|
18370
|
+
diskStamp = null;
|
|
18307
18371
|
reconcileCache = null;
|
|
18308
18372
|
}
|
|
18309
18373
|
function markFullResync(server, sessionId) {
|
|
@@ -18325,7 +18389,7 @@ function syncMode(row, mtime, fileSize, extractorVersion, isAppendOnly) {
|
|
|
18325
18389
|
if (row.m >= Math.floor(mtime)) return "skip";
|
|
18326
18390
|
return "full";
|
|
18327
18391
|
}
|
|
18328
|
-
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;
|
|
18329
18393
|
var init_sync_ledger = __esm({
|
|
18330
18394
|
"src/sync-ledger.ts"() {
|
|
18331
18395
|
"use strict";
|
|
@@ -18333,6 +18397,9 @@ var init_sync_ledger = __esm({
|
|
|
18333
18397
|
init_extractor_version();
|
|
18334
18398
|
ledgerPath = () => join39(getDataDir(), "sync-ledger.json");
|
|
18335
18399
|
cache3 = null;
|
|
18400
|
+
base = /* @__PURE__ */ new Map();
|
|
18401
|
+
diskStamp = null;
|
|
18402
|
+
rowKey = (server, id) => `${server}\0${id}`;
|
|
18336
18403
|
LEDGER_FLUSH_MS = 2e3;
|
|
18337
18404
|
pendingWrite = false;
|
|
18338
18405
|
flushTimer = null;
|
|
@@ -18371,7 +18438,7 @@ var init_sync_fields = __esm({
|
|
|
18371
18438
|
});
|
|
18372
18439
|
|
|
18373
18440
|
// ../engine/dist/core/index-lock.js
|
|
18374
|
-
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";
|
|
18375
18442
|
import { dirname as dirname17, join as join40 } from "path";
|
|
18376
18443
|
function acquireIndexLock(opts) {
|
|
18377
18444
|
const lockPath = lockFilePath(opts.file);
|
|
@@ -18421,7 +18488,7 @@ function lockFilePath(file = ".compact.lock") {
|
|
|
18421
18488
|
}
|
|
18422
18489
|
function stealStaleLock(lockPath, staleAfterMs) {
|
|
18423
18490
|
try {
|
|
18424
|
-
const s =
|
|
18491
|
+
const s = statSync36(lockPath);
|
|
18425
18492
|
const age = Date.now() - s.mtimeMs;
|
|
18426
18493
|
let payload;
|
|
18427
18494
|
try {
|
|
@@ -18484,7 +18551,7 @@ var init_http = __esm({
|
|
|
18484
18551
|
CLI_VERSION = JSON.parse(readFileSync32(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
|
|
18485
18552
|
} catch {
|
|
18486
18553
|
try {
|
|
18487
|
-
if (true) CLI_VERSION = "0.7.
|
|
18554
|
+
if (true) CLI_VERSION = "0.7.15";
|
|
18488
18555
|
} catch {
|
|
18489
18556
|
}
|
|
18490
18557
|
}
|
|
@@ -18978,7 +19045,7 @@ var init_telemetry = __esm({
|
|
|
18978
19045
|
init_sync_client();
|
|
18979
19046
|
cliVersion = () => {
|
|
18980
19047
|
try {
|
|
18981
|
-
return true ? "0.7.
|
|
19048
|
+
return true ? "0.7.15" : "dev";
|
|
18982
19049
|
} catch {
|
|
18983
19050
|
return "dev";
|
|
18984
19051
|
}
|
|
@@ -19001,11 +19068,11 @@ __export(server_probe_exports, {
|
|
|
19001
19068
|
function probeOk(r) {
|
|
19002
19069
|
return r.kind === "ok" && r.apiVersion >= 2;
|
|
19003
19070
|
}
|
|
19004
|
-
async function probeServer(
|
|
19071
|
+
async function probeServer(base3, opts = {}) {
|
|
19005
19072
|
const f = opts.fetchImpl || fetch;
|
|
19006
19073
|
let res;
|
|
19007
19074
|
try {
|
|
19008
|
-
res = await f(`${
|
|
19075
|
+
res = await f(`${base3.replace(/\/+$/, "")}/api/capabilities`, {
|
|
19009
19076
|
signal: AbortSignal.timeout(opts.timeoutMs ?? 1e4)
|
|
19010
19077
|
});
|
|
19011
19078
|
} catch (err) {
|
|
@@ -19042,34 +19109,34 @@ async function probeServer(base2, opts = {}) {
|
|
|
19042
19109
|
raw: parsed
|
|
19043
19110
|
};
|
|
19044
19111
|
}
|
|
19045
|
-
function probeAdvice(r,
|
|
19112
|
+
function probeAdvice(r, base3) {
|
|
19046
19113
|
switch (r.kind) {
|
|
19047
19114
|
case "ok":
|
|
19048
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`;
|
|
19049
19116
|
case "moved":
|
|
19050
|
-
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>\``;
|
|
19051
19118
|
case "unauthorized":
|
|
19052
|
-
return `HTTP ${r.status} \u2014 ${
|
|
19119
|
+
return `HTTP ${r.status} \u2014 ${base3} rejected the credential. Re-login: \`chat-recall login ` + base3 + "`";
|
|
19053
19120
|
case "server_error":
|
|
19054
|
-
return `HTTP ${r.status} \u2014 ${
|
|
19121
|
+
return `HTTP ${r.status} \u2014 ${base3} is up but failing. Nothing to fix locally; check the server.`;
|
|
19055
19122
|
case "not_api":
|
|
19056
|
-
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`;
|
|
19057
19124
|
case "unreachable":
|
|
19058
19125
|
switch (r.reason) {
|
|
19059
19126
|
case "dns":
|
|
19060
|
-
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`;
|
|
19061
19128
|
case "refused":
|
|
19062
|
-
return `${
|
|
19129
|
+
return `${base3} resolves but refused the connection (${r.error}) \u2014 the server is not running, or the port is wrong`;
|
|
19063
19130
|
case "tls":
|
|
19064
|
-
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.`;
|
|
19065
19132
|
case "timeout":
|
|
19066
|
-
return `${
|
|
19133
|
+
return `${base3} did not answer in time (${r.error}) \u2014 a firewall or proxy that drops traffic silently looks exactly like this`;
|
|
19067
19134
|
case "reset":
|
|
19068
|
-
return `the connection to ${
|
|
19135
|
+
return `the connection to ${base3} was cut (${r.error}) \u2014 often a proxy or a captive portal`;
|
|
19069
19136
|
case "bad_port":
|
|
19070
|
-
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`;
|
|
19071
19138
|
default:
|
|
19072
|
-
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`;
|
|
19073
19140
|
}
|
|
19074
19141
|
}
|
|
19075
19142
|
}
|
|
@@ -19102,8 +19169,8 @@ function describeCause(err) {
|
|
|
19102
19169
|
const code = e.code;
|
|
19103
19170
|
if (typeof code === "string" && code && !parts.includes(code)) parts.push(code);
|
|
19104
19171
|
}
|
|
19105
|
-
const
|
|
19106
|
-
return parts.length ? `${
|
|
19172
|
+
const base3 = err instanceof Error ? err.message : String(err);
|
|
19173
|
+
return parts.length ? `${base3}: ${parts.join(" \u2192 ")}` : base3;
|
|
19107
19174
|
}
|
|
19108
19175
|
function describeUnreachable(err) {
|
|
19109
19176
|
const reason = classifyUnreachable(err);
|
|
@@ -19216,7 +19283,7 @@ __export(auto_update_exports, {
|
|
|
19216
19283
|
import { execSync as execSync2, execFileSync as execFileSync3 } from "node:child_process";
|
|
19217
19284
|
import { readFileSync as readFileSync34, existsSync as existsSync41 } from "node:fs";
|
|
19218
19285
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
19219
|
-
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";
|
|
19220
19287
|
import { join as join41, dirname as dirname18, sep as sep2, posix as pathPosix, win32 as pathWin32 } from "node:path";
|
|
19221
19288
|
import { tmpdir as tmpdir2, homedir as homedir15 } from "node:os";
|
|
19222
19289
|
import { createHash as createHash7 } from "node:crypto";
|
|
@@ -19248,12 +19315,12 @@ function installedVersion() {
|
|
|
19248
19315
|
return null;
|
|
19249
19316
|
}
|
|
19250
19317
|
}
|
|
19251
|
-
function planAutoUpdate(
|
|
19318
|
+
function planAutoUpdate(base3, caps, ownVersion3, flag) {
|
|
19252
19319
|
const rel = caps.cli;
|
|
19253
19320
|
if (!rel || !rel.version || !rel.sha256) return { update: false, reason: "server advertises no CLI release" };
|
|
19254
19321
|
if (!isAutoUpdateEnabled(caps.edition, flag)) return { update: false, reason: `auto-update disabled (edition ${caps.edition ?? "?"})` };
|
|
19255
19322
|
if (compareVersions(rel.version, ownVersion3) <= 0) return { update: false, reason: `already current (own ${ownVersion3} >= server ${rel.version})` };
|
|
19256
|
-
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 };
|
|
19257
19324
|
}
|
|
19258
19325
|
function sweepStaleStaging(root = tmpdir2(), now = Date.now()) {
|
|
19259
19326
|
const MKDTEMP_SUFFIX = /^cr-update-.{6}$/s;
|
|
@@ -19269,7 +19336,7 @@ function sweepStaleStaging(root = tmpdir2(), now = Date.now()) {
|
|
|
19269
19336
|
if (!MKDTEMP_SUFFIX.test(name)) continue;
|
|
19270
19337
|
const dir = join41(root, name);
|
|
19271
19338
|
try {
|
|
19272
|
-
const st =
|
|
19339
|
+
const st = statSync37(dir);
|
|
19273
19340
|
if (!st.isDirectory() || now - st.mtimeMs < COLD_MS) continue;
|
|
19274
19341
|
const inside = readdirSync30(dir);
|
|
19275
19342
|
if (inside.length > 1 || inside.length === 1 && inside[0] !== "chat-recall.tgz") continue;
|
|
@@ -19433,20 +19500,20 @@ function clearUpdateFailures() {
|
|
|
19433
19500
|
function stopAutoUpdates() {
|
|
19434
19501
|
stopRequested = true;
|
|
19435
19502
|
}
|
|
19436
|
-
async function runAutoUpdate(
|
|
19503
|
+
async function runAutoUpdate(base3, authHeaders, ownVersion3, deps) {
|
|
19437
19504
|
let caps;
|
|
19438
19505
|
try {
|
|
19439
|
-
const res = await fetchWithTimeout(`${
|
|
19506
|
+
const res = await fetchWithTimeout(`${base3.replace(/\/+$/, "")}/api/capabilities`, { headers: authHeaders });
|
|
19440
19507
|
if (!res.ok) return { updated: false, reason: `capabilities HTTP ${res.status}` };
|
|
19441
19508
|
caps = await res.json();
|
|
19442
19509
|
} catch (e) {
|
|
19443
19510
|
return { updated: false, reason: `capabilities unreachable: ${e instanceof Error ? e.message : e}` };
|
|
19444
19511
|
}
|
|
19445
19512
|
const effectiveOwn = newerOf(ownVersion3, installedVersion());
|
|
19446
|
-
const plan = planAutoUpdate(
|
|
19513
|
+
const plan = planAutoUpdate(base3, caps, effectiveOwn, process.env.CHAT_RECALL_AUTO_UPDATE);
|
|
19447
19514
|
if (!plan.update) {
|
|
19448
|
-
if (/disabled|no CLI release/.test(plan.reason) && !reportedStandingSkip.has(
|
|
19449
|
-
reportedStandingSkip.add(
|
|
19515
|
+
if (/disabled|no CLI release/.test(plan.reason) && !reportedStandingSkip.has(base3)) {
|
|
19516
|
+
reportedStandingSkip.add(base3);
|
|
19450
19517
|
try {
|
|
19451
19518
|
const { reportClientEvent: reportClientEvent2 } = await Promise.resolve().then(() => (init_client_events(), client_events_exports));
|
|
19452
19519
|
reportClientEvent2("auto_update_skipped", { message: `${plan.reason} (server offers ${caps.cli?.version ?? "?"}, this device runs ${effectiveOwn})` });
|
|
@@ -19502,7 +19569,7 @@ var init_auto_update = __esm({
|
|
|
19502
19569
|
"use strict";
|
|
19503
19570
|
init_http();
|
|
19504
19571
|
init_index_lock();
|
|
19505
|
-
tarballUrl = (
|
|
19572
|
+
tarballUrl = (base3, version) => `${base3.replace(/\/+$/, "")}/install/${version ? `chat-recall-${version}.tgz` : "chat-recall.tgz"}`;
|
|
19506
19573
|
GIVE_UP_AFTER = 3;
|
|
19507
19574
|
reportedStandingSkip = /* @__PURE__ */ new Set();
|
|
19508
19575
|
STOPPING_REASON = "not installed: this process is shutting down";
|
|
@@ -19513,7 +19580,7 @@ var init_auto_update = __esm({
|
|
|
19513
19580
|
|
|
19514
19581
|
// src/sync-client.ts
|
|
19515
19582
|
import { join as join42, dirname as dirname19, basename as basename20 } from "node:path";
|
|
19516
|
-
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";
|
|
19517
19584
|
import { tmpdir as tmpdir3, hostname as hostname2 } from "node:os";
|
|
19518
19585
|
import { createHash as createHash8 } from "node:crypto";
|
|
19519
19586
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
@@ -19558,15 +19625,15 @@ function loadAllCredentials() {
|
|
|
19558
19625
|
return [];
|
|
19559
19626
|
}
|
|
19560
19627
|
async function fetchTenantSecurityConfig(cred) {
|
|
19561
|
-
const
|
|
19562
|
-
const cached = _securityConfigCache.get(
|
|
19628
|
+
const base3 = cred.serverUrl.replace(/\/+$/, "");
|
|
19629
|
+
const cached = _securityConfigCache.get(base3);
|
|
19563
19630
|
if (cached && Date.now() - cached.fetchedAt < SECURITY_CONFIG_TTL_MS) return cached.config;
|
|
19564
19631
|
const headers = { "content-type": "application/json" };
|
|
19565
19632
|
if (cred.token) headers.authorization = `Bearer ${cred.token}`;
|
|
19566
19633
|
try {
|
|
19567
19634
|
const [rulesRes, settingsRes] = await Promise.all([
|
|
19568
|
-
fetchWithTimeout(`${
|
|
19569
|
-
fetchWithTimeout(`${
|
|
19635
|
+
fetchWithTimeout(`${base3}/api/secrets/rules`, { headers }),
|
|
19636
|
+
fetchWithTimeout(`${base3}/api/teams/security-config`, { headers }).catch(() => null)
|
|
19570
19637
|
]);
|
|
19571
19638
|
let tenantRules = [];
|
|
19572
19639
|
let rulePackVersion = null;
|
|
@@ -19591,18 +19658,18 @@ async function fetchTenantSecurityConfig(cred) {
|
|
|
19591
19658
|
const body = await settingsRes.json().catch(() => ({}));
|
|
19592
19659
|
if (typeof body.verifySecrets === "boolean") verifySecrets = body.verifySecrets;
|
|
19593
19660
|
if (typeof body.telemetry === "boolean") {
|
|
19594
|
-
setTelemetryEligible(
|
|
19661
|
+
setTelemetryEligible(base3, body.telemetry);
|
|
19595
19662
|
try {
|
|
19596
19663
|
const prior = readCollectorHealth()?.telemetryEligible ?? {};
|
|
19597
19664
|
updateCollectorHealth({
|
|
19598
|
-
telemetryEligible: { ...prior, [
|
|
19665
|
+
telemetryEligible: { ...prior, [base3]: { allowed: body.telemetry, at: Date.now() } }
|
|
19599
19666
|
});
|
|
19600
19667
|
} catch {
|
|
19601
19668
|
}
|
|
19602
19669
|
}
|
|
19603
19670
|
}
|
|
19604
19671
|
const config = { tenantRules, verifySecrets, rulePackVersion };
|
|
19605
|
-
_securityConfigCache.set(
|
|
19672
|
+
_securityConfigCache.set(base3, { fetchedAt: Date.now(), config });
|
|
19606
19673
|
return config;
|
|
19607
19674
|
} catch {
|
|
19608
19675
|
return { tenantRules: [], verifySecrets: true, rulePackVersion: null };
|
|
@@ -19618,18 +19685,18 @@ function readPersistedSyncConfigs() {
|
|
|
19618
19685
|
return {};
|
|
19619
19686
|
}
|
|
19620
19687
|
}
|
|
19621
|
-
function persistSyncConfig(
|
|
19688
|
+
function persistSyncConfig(base3, config) {
|
|
19622
19689
|
try {
|
|
19623
19690
|
const all = readPersistedSyncConfigs();
|
|
19624
|
-
all[
|
|
19691
|
+
all[base3] = { fetchedAt: Date.now(), config };
|
|
19625
19692
|
mkdirSync10(dirname19(syncConfigCachePath()), { recursive: true });
|
|
19626
19693
|
writeFileSync9(syncConfigCachePath(), JSON.stringify(all, null, 2));
|
|
19627
19694
|
} catch {
|
|
19628
19695
|
}
|
|
19629
19696
|
}
|
|
19630
19697
|
async function fetchTenantSyncConfig(cred) {
|
|
19631
|
-
const
|
|
19632
|
-
const cached = _syncConfigCache.get(
|
|
19698
|
+
const base3 = cred.serverUrl.replace(/\/+$/, "");
|
|
19699
|
+
const cached = _syncConfigCache.get(base3);
|
|
19633
19700
|
if (cached && Date.now() - cached.fetchedAt < SECURITY_CONFIG_TTL_MS) return cached.config;
|
|
19634
19701
|
const headers = { "content-type": "application/json" };
|
|
19635
19702
|
if (cred.token) headers.authorization = `Bearer ${cred.token}`;
|
|
@@ -19637,7 +19704,7 @@ async function fetchTenantSyncConfig(cred) {
|
|
|
19637
19704
|
try {
|
|
19638
19705
|
const sources2 = discoverSessionSources();
|
|
19639
19706
|
if (sources2.length > 0) {
|
|
19640
|
-
await fetchWithTimeout(`${
|
|
19707
|
+
await fetchWithTimeout(`${base3}/api/sync-config/sources`, {
|
|
19641
19708
|
method: "POST",
|
|
19642
19709
|
headers,
|
|
19643
19710
|
body: JSON.stringify({ device: deviceLabel(), sources: sources2 })
|
|
@@ -19645,12 +19712,12 @@ async function fetchTenantSyncConfig(cred) {
|
|
|
19645
19712
|
}
|
|
19646
19713
|
} catch {
|
|
19647
19714
|
}
|
|
19648
|
-
const res = await fetchWithTimeout(`${
|
|
19715
|
+
const res = await fetchWithTimeout(`${base3}/api/sync-config`, { headers });
|
|
19649
19716
|
if (res.status === 404) {
|
|
19650
|
-
_syncConfigCache.set(
|
|
19717
|
+
_syncConfigCache.set(base3, { fetchedAt: Date.now(), config: EMPTY_SYNC_CONFIG });
|
|
19651
19718
|
return EMPTY_SYNC_CONFIG;
|
|
19652
19719
|
}
|
|
19653
|
-
if (!res.ok) return lastKnownSyncConfig(
|
|
19720
|
+
if (!res.ok) return lastKnownSyncConfig(base3, `HTTP ${res.status}`);
|
|
19654
19721
|
const body = await res.json().catch(() => ({}));
|
|
19655
19722
|
const config = {
|
|
19656
19723
|
excludeTools: Array.isArray(body.excludeTools) ? body.excludeTools.filter((t) => typeof t === "string") : [],
|
|
@@ -19687,22 +19754,22 @@ async function fetchTenantSyncConfig(cred) {
|
|
|
19687
19754
|
if (decided > 0) console.error(`[sync] applied ${decided} folder decision(s) from the dashboard`);
|
|
19688
19755
|
} catch {
|
|
19689
19756
|
}
|
|
19690
|
-
_syncConfigCache.set(
|
|
19691
|
-
persistSyncConfig(
|
|
19757
|
+
_syncConfigCache.set(base3, { fetchedAt: Date.now(), config });
|
|
19758
|
+
persistSyncConfig(base3, config);
|
|
19692
19759
|
return config;
|
|
19693
19760
|
} catch (err) {
|
|
19694
19761
|
if (isSyncRulesRefusal(err)) throw err;
|
|
19695
|
-
return lastKnownSyncConfig(
|
|
19762
|
+
return lastKnownSyncConfig(base3, err instanceof Error ? err.message : "request failed");
|
|
19696
19763
|
}
|
|
19697
19764
|
}
|
|
19698
|
-
function lastKnownSyncConfig(
|
|
19699
|
-
const remembered = _syncConfigCache.get(
|
|
19765
|
+
function lastKnownSyncConfig(base3, reason) {
|
|
19766
|
+
const remembered = _syncConfigCache.get(base3) ?? readPersistedSyncConfigs()[base3];
|
|
19700
19767
|
if (remembered) {
|
|
19701
19768
|
console.error(`[sync] could not read server-side sync rules (${reason}) \u2014 applying the last known set from ${new Date(remembered.fetchedAt).toISOString()}`);
|
|
19702
19769
|
return remembered.config;
|
|
19703
19770
|
}
|
|
19704
19771
|
const refusal = new Error(
|
|
19705
|
-
`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.`
|
|
19706
19773
|
);
|
|
19707
19774
|
refusal[SYNC_RULES_REFUSAL] = true;
|
|
19708
19775
|
throw refusal;
|
|
@@ -19810,25 +19877,25 @@ async function syncSessions(opts = {}) {
|
|
|
19810
19877
|
${errors.join("\n ")}`);
|
|
19811
19878
|
return { ...agg, perTarget };
|
|
19812
19879
|
}
|
|
19813
|
-
async function postFieldBatch(
|
|
19880
|
+
async function postFieldBatch(base3, token, rows) {
|
|
19814
19881
|
const headers = { "content-type": "application/json" };
|
|
19815
19882
|
if (token) headers.authorization = `Bearer ${token}`;
|
|
19816
19883
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
19817
19884
|
for (let attempt = 0; ; attempt++) {
|
|
19818
|
-
const res = await fetchWithTimeout(`${
|
|
19885
|
+
const res = await fetchWithTimeout(`${base3}/api/sync`, { method: "POST", headers, body: JSON.stringify({ fields: rows }) }, 6e4);
|
|
19819
19886
|
if (res.ok) return;
|
|
19820
19887
|
const retryable = res.status === 429 || res.status >= 500;
|
|
19821
|
-
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(() => "")}`);
|
|
19822
19889
|
const ra = Number(res.headers.get("retry-after")) || 0;
|
|
19823
19890
|
await sleep(ra > 0 ? ra * 1e3 : [500, 1500, 4e3, 8e3, 15e3][Math.min(attempt, 4)]);
|
|
19824
19891
|
}
|
|
19825
19892
|
}
|
|
19826
19893
|
async function reconcileFieldsForTarget(cred, fullRefs, opts = {}) {
|
|
19827
|
-
const
|
|
19828
|
-
const ledger = getSyncedRows(
|
|
19894
|
+
const base3 = cred.serverUrl.replace(/\/+$/, "");
|
|
19895
|
+
const ledger = getSyncedRows(base3);
|
|
19829
19896
|
let pushed = 0, absent = 0, scanned = 0;
|
|
19830
19897
|
for (const field of SYNC_FIELDS) {
|
|
19831
|
-
const needFull = !!opts.force || fieldNeedsFullPass(
|
|
19898
|
+
const needFull = !!opts.force || fieldNeedsFullPass(base3, field);
|
|
19832
19899
|
const candidates2 = needFull ? fullRefs() : opts.convRefs ?? fullRefs();
|
|
19833
19900
|
const send = [];
|
|
19834
19901
|
const mtimeById = /* @__PURE__ */ new Map();
|
|
@@ -19844,15 +19911,15 @@ async function reconcileFieldsForTarget(cred, fullRefs, opts = {}) {
|
|
|
19844
19911
|
}
|
|
19845
19912
|
for (let i = 0; i < send.length; i += 200) {
|
|
19846
19913
|
const chunk = send.slice(i, i + 200);
|
|
19847
|
-
await postFieldBatch(
|
|
19848
|
-
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 })));
|
|
19849
19916
|
pushed += chunk.length;
|
|
19850
19917
|
}
|
|
19851
19918
|
if (absentIds.length) {
|
|
19852
|
-
markFieldCoverage(
|
|
19919
|
+
markFieldCoverage(base3, field, absentIds.map((id) => ({ id, present: false, mtime: mtimeById.get(id) ?? 0 })));
|
|
19853
19920
|
absent += absentIds.length;
|
|
19854
19921
|
}
|
|
19855
|
-
if (needFull) markFieldFullPassDone(
|
|
19922
|
+
if (needFull) markFieldFullPassDone(base3, field);
|
|
19856
19923
|
}
|
|
19857
19924
|
return { pushed, absent, scanned };
|
|
19858
19925
|
}
|
|
@@ -19868,7 +19935,7 @@ function reapStaleScanDirs(dir = tmpdir3(), maxAgeMs = 6 * 36e5, now = Date.now(
|
|
|
19868
19935
|
if (!name.startsWith("cr-batchscan-")) continue;
|
|
19869
19936
|
const p = join42(dir, name);
|
|
19870
19937
|
try {
|
|
19871
|
-
if (now -
|
|
19938
|
+
if (now - statSync38(p).mtimeMs < maxAgeMs) continue;
|
|
19872
19939
|
rmSync6(p, { recursive: true, force: true });
|
|
19873
19940
|
reaped++;
|
|
19874
19941
|
} catch {
|
|
@@ -19942,25 +20009,25 @@ function serverIngestConcurrency(serverUrl) {
|
|
|
19942
20009
|
return advertisedIngestConc.get(serverUrl.replace(/\/$/, "")) ?? null;
|
|
19943
20010
|
}
|
|
19944
20011
|
async function verifyServerApi(serverUrl, minApi) {
|
|
19945
|
-
const
|
|
19946
|
-
const seen = capsOk.get(
|
|
20012
|
+
const base3 = serverUrl.replace(/\/$/, "");
|
|
20013
|
+
const seen = capsOk.get(base3);
|
|
19947
20014
|
if (seen !== void 0 && Date.now() - seen < CAPS_TTL_MS) return true;
|
|
19948
20015
|
const { probeServer: probeServer2, probeAdvice: probeAdvice2 } = await Promise.resolve().then(() => (init_server_probe(), server_probe_exports));
|
|
19949
|
-
const probe = await probeServer2(
|
|
20016
|
+
const probe = await probeServer2(base3, {
|
|
19950
20017
|
fetchImpl: ((url, init) => fetchWithTimeout(String(url), init ?? {}))
|
|
19951
20018
|
});
|
|
19952
|
-
if (probe.kind !== "ok") throw new Error(probeAdvice2(probe,
|
|
20019
|
+
if (probe.kind !== "ok") throw new Error(probeAdvice2(probe, base3));
|
|
19953
20020
|
const caps = probe.raw;
|
|
19954
20021
|
if ((caps.apiVersion ?? 0) < minApi) {
|
|
19955
20022
|
throw new Error(`server too old: apiVersion ${caps.apiVersion ?? "none"} < required ${minApi} \u2014 update the server image before syncing`);
|
|
19956
20023
|
}
|
|
19957
20024
|
const adv = caps.limits?.ingestConcurrencyPerTenant;
|
|
19958
20025
|
if (typeof adv === "number" && Number.isFinite(adv) && adv >= 1) {
|
|
19959
|
-
advertisedIngestConc.set(
|
|
20026
|
+
advertisedIngestConc.set(base3, Math.floor(adv));
|
|
19960
20027
|
}
|
|
19961
|
-
if (caps.limits?.acceptsGzipBody === true) advertisedGzipBody.add(
|
|
19962
|
-
else advertisedGzipBody.delete(
|
|
19963
|
-
capsOk.set(
|
|
20028
|
+
if (caps.limits?.acceptsGzipBody === true) advertisedGzipBody.add(base3);
|
|
20029
|
+
else advertisedGzipBody.delete(base3);
|
|
20030
|
+
capsOk.set(base3, Date.now());
|
|
19964
20031
|
return true;
|
|
19965
20032
|
}
|
|
19966
20033
|
async function syncToTarget(cred, opts = {}) {
|
|
@@ -20025,7 +20092,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20025
20092
|
const ac = new AbortController();
|
|
20026
20093
|
const timer = setTimeout(() => ac.abort(new Error(`upload timed out after ${UPLOAD_TIMEOUT_MS}ms`)), UPLOAD_TIMEOUT_MS);
|
|
20027
20094
|
try {
|
|
20028
|
-
const res = await fetch(`${
|
|
20095
|
+
const res = await fetch(`${base3}/api/sync`, {
|
|
20029
20096
|
method: "POST",
|
|
20030
20097
|
// No token ⇒ no auth header: a no-auth local server (AUTH_PROVIDER=none)
|
|
20031
20098
|
// accepts it as the single 'default' tenant.
|
|
@@ -20041,26 +20108,26 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20041
20108
|
acceptedUploads.set(cred.serverUrl, (acceptedUploads.get(cred.serverUrl) ?? 0) + 1);
|
|
20042
20109
|
const body2 = await res.json().catch(() => ({}));
|
|
20043
20110
|
if (typeof body2.telemetry === "boolean") {
|
|
20044
|
-
setTelemetryEligible(
|
|
20111
|
+
setTelemetryEligible(base3, body2.telemetry);
|
|
20045
20112
|
try {
|
|
20046
20113
|
const prior = readCollectorHealth()?.telemetryEligible ?? {};
|
|
20047
20114
|
updateCollectorHealth({
|
|
20048
|
-
telemetryEligible: { ...prior, [
|
|
20115
|
+
telemetryEligible: { ...prior, [base3]: { allowed: body2.telemetry, at: Date.now() } }
|
|
20049
20116
|
});
|
|
20050
20117
|
} catch {
|
|
20051
20118
|
}
|
|
20052
20119
|
}
|
|
20053
20120
|
const adv = body2.limits?.ingestConcurrencyPerTenant;
|
|
20054
20121
|
if (typeof adv === "number" && Number.isFinite(adv) && adv >= 1) {
|
|
20055
|
-
setServerIngestConcurrency(
|
|
20122
|
+
setServerIngestConcurrency(base3, Math.floor(adv));
|
|
20056
20123
|
}
|
|
20057
20124
|
if (body2.cli && body2.cli.version) {
|
|
20058
20125
|
const { planAutoUpdate: planAutoUpdate2, runAutoUpdate: runAutoUpdate2, sweepStaleStaging: sweepStaleStaging2 } = await Promise.resolve().then(() => (init_auto_update(), auto_update_exports));
|
|
20059
20126
|
const authHeaders = cred.token ? { authorization: `Bearer ${cred.token}` } : {};
|
|
20060
|
-
const plan = planAutoUpdate2(
|
|
20127
|
+
const plan = planAutoUpdate2(base3, { cli: body2.cli }, ownVersion, process.env.CHAT_RECALL_AUTO_UPDATE);
|
|
20061
20128
|
sweepStaleStaging2();
|
|
20062
20129
|
if (plan.update) {
|
|
20063
|
-
void runAutoUpdate2(
|
|
20130
|
+
void runAutoUpdate2(base3, authHeaders, ownVersion).catch(() => {
|
|
20064
20131
|
});
|
|
20065
20132
|
}
|
|
20066
20133
|
}
|
|
@@ -20069,7 +20136,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20069
20136
|
const retryable = res.status === 429 || res.status >= 500;
|
|
20070
20137
|
const text = await res.text().catch(() => "");
|
|
20071
20138
|
if (res.status === 401 || res.status === 403) {
|
|
20072
|
-
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}`);
|
|
20073
20140
|
}
|
|
20074
20141
|
if (res.status === 402) {
|
|
20075
20142
|
let detail = text;
|
|
@@ -20090,7 +20157,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20090
20157
|
const retryAfterS = Number(res.headers.get("retry-after"));
|
|
20091
20158
|
const waitMs = res.status === 429 && retryAfterS > 0 ? retryAfterS * 1e3 : RETRY_DELAYS_MS[attempt];
|
|
20092
20159
|
const why = res.status === 524 ? ` \u2014 the proxy cut the request at its time limit; the batch is too big for one request` : "";
|
|
20093
|
-
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})`);
|
|
20094
20161
|
await sleep(waitMs);
|
|
20095
20162
|
continue;
|
|
20096
20163
|
} catch (err) {
|
|
@@ -20158,11 +20225,11 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20158
20225
|
}
|
|
20159
20226
|
};
|
|
20160
20227
|
};
|
|
20161
|
-
const
|
|
20162
|
-
const ledger = opts.useLedger ? getSyncedRows(
|
|
20228
|
+
const base3 = cred.serverUrl.replace(/\/$/, "");
|
|
20229
|
+
const ledger = opts.useLedger ? getSyncedRows(base3) : null;
|
|
20163
20230
|
const convBatch = makeBatcher("conversations", 25, false, (rows) => {
|
|
20164
20231
|
try {
|
|
20165
|
-
markSynced(
|
|
20232
|
+
markSynced(base3, rows.map((r) => {
|
|
20166
20233
|
const off = typeof r.from_offset === "number" ? r.from_offset : 0;
|
|
20167
20234
|
const hash = shippedHash.get(r.session_id);
|
|
20168
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 };
|
|
@@ -20177,7 +20244,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20177
20244
|
const ac = new AbortController();
|
|
20178
20245
|
const timer = setTimeout(() => ac.abort(new Error(`upload timed out after ${UPLOAD_TIMEOUT_MS}ms`)), UPLOAD_TIMEOUT_MS);
|
|
20179
20246
|
try {
|
|
20180
|
-
const res = await fetch(`${
|
|
20247
|
+
const res = await fetch(`${base3}/api/sync`, {
|
|
20181
20248
|
method: "POST",
|
|
20182
20249
|
headers,
|
|
20183
20250
|
body: JSON.stringify({ conversations: convs }),
|
|
@@ -20188,10 +20255,10 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20188
20255
|
if (body.cli && body.cli.version) {
|
|
20189
20256
|
const { planAutoUpdate: planAutoUpdate2, runAutoUpdate: runAutoUpdate2, sweepStaleStaging: sweepStaleStaging2 } = await Promise.resolve().then(() => (init_auto_update(), auto_update_exports));
|
|
20190
20257
|
const authHeaders = cred.token ? { authorization: `Bearer ${cred.token}` } : {};
|
|
20191
|
-
const plan = planAutoUpdate2(
|
|
20258
|
+
const plan = planAutoUpdate2(base3, { cli: body.cli }, ownVersion, process.env.CHAT_RECALL_AUTO_UPDATE);
|
|
20192
20259
|
sweepStaleStaging2();
|
|
20193
20260
|
if (plan.update) {
|
|
20194
|
-
void runAutoUpdate2(
|
|
20261
|
+
void runAutoUpdate2(base3, authHeaders, ownVersion).catch(() => {
|
|
20195
20262
|
});
|
|
20196
20263
|
}
|
|
20197
20264
|
}
|
|
@@ -20199,7 +20266,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20199
20266
|
const acked = convs.filter((c) => !fullNeeded.has(c.session_id));
|
|
20200
20267
|
if (acked.length > 0) {
|
|
20201
20268
|
try {
|
|
20202
|
-
markSynced(
|
|
20269
|
+
markSynced(base3, acked.map((c) => ({
|
|
20203
20270
|
id: c.session_id,
|
|
20204
20271
|
mtime: c.mtime,
|
|
20205
20272
|
offset: c.from_offset,
|
|
@@ -20223,7 +20290,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20223
20290
|
const ac = new AbortController();
|
|
20224
20291
|
const timer = setTimeout(() => ac.abort(new Error(`upload timed out after ${UPLOAD_TIMEOUT_MS}ms`)), UPLOAD_TIMEOUT_MS);
|
|
20225
20292
|
try {
|
|
20226
|
-
const res = await fetch(`${
|
|
20293
|
+
const res = await fetch(`${base3}/api/sync`, {
|
|
20227
20294
|
method: "POST",
|
|
20228
20295
|
headers,
|
|
20229
20296
|
body: JSON.stringify({ conversations: [conv] }),
|
|
@@ -20236,11 +20303,11 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20236
20303
|
const mtime = conv.mtime;
|
|
20237
20304
|
try {
|
|
20238
20305
|
if (!guarded) {
|
|
20239
|
-
markSynced(
|
|
20306
|
+
markSynced(base3, [{ id, mtime, offset: conv.from_offset, size: conv.from_offset, acked: true }]);
|
|
20240
20307
|
} else if (typeof guarded.o === "number" && guarded.o > 0 && guarded.o <= fileSize) {
|
|
20241
|
-
markSynced(
|
|
20308
|
+
markSynced(base3, [{ id, mtime, offset: guarded.o, size: guarded.o, acked: true }]);
|
|
20242
20309
|
} else {
|
|
20243
|
-
markSynced(
|
|
20310
|
+
markSynced(base3, [{ id, mtime }]);
|
|
20244
20311
|
}
|
|
20245
20312
|
} catch {
|
|
20246
20313
|
}
|
|
@@ -20306,7 +20373,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20306
20373
|
const m = process.memoryUsage();
|
|
20307
20374
|
console.error(`[sync-trace] ${msg} \xB7 heap=${(m.heapUsed / 1048576).toFixed(0)}MB rss=${(m.rss / 1048576).toFixed(0)}MB`);
|
|
20308
20375
|
} : null;
|
|
20309
|
-
trace?.(`walk start: ${slice.length} ref(s) \u2192 ${
|
|
20376
|
+
trace?.(`walk start: ${slice.length} ref(s) \u2192 ${base3}`);
|
|
20310
20377
|
if (upload.sessionMeta) {
|
|
20311
20378
|
try {
|
|
20312
20379
|
await reconcileFieldsForTarget(
|
|
@@ -20321,7 +20388,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20321
20388
|
{ convRefs: slice }
|
|
20322
20389
|
);
|
|
20323
20390
|
} catch (e) {
|
|
20324
|
-
console.error(`[sync] field reconcile (${
|
|
20391
|
+
console.error(`[sync] field reconcile (${base3}): ${e instanceof Error ? e.message : e}`);
|
|
20325
20392
|
}
|
|
20326
20393
|
}
|
|
20327
20394
|
trace?.("field reconcile done");
|
|
@@ -20363,7 +20430,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20363
20430
|
}
|
|
20364
20431
|
trace?.("conversation walk start");
|
|
20365
20432
|
const walkStartedAt = Date.now();
|
|
20366
|
-
const firstWalk = (ledger ?? getSyncedRows(
|
|
20433
|
+
const firstWalk = (ledger ?? getSyncedRows(base3)).size === 0;
|
|
20367
20434
|
reportWalkProgress({ done: 0, total: slice.length, startedAt: walkStartedAt, complete: false, first: firstWalk });
|
|
20368
20435
|
walkProgressForUpload = { done: 0, total: slice.length, complete: false };
|
|
20369
20436
|
let traceN = 0;
|
|
@@ -20403,7 +20470,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20403
20470
|
continue;
|
|
20404
20471
|
} else {
|
|
20405
20472
|
try {
|
|
20406
|
-
markSynced(
|
|
20473
|
+
markSynced(base3, [{ id: ref.prefixedId, mtime: ref.mtime }]);
|
|
20407
20474
|
} catch {
|
|
20408
20475
|
}
|
|
20409
20476
|
skipped++;
|
|
@@ -20426,7 +20493,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20426
20493
|
const off = getBackendForId(ref.prefixedId)?.fileSize?.(ref.rawId) ?? 0;
|
|
20427
20494
|
const priorCursor = ackRow?.s ?? 0;
|
|
20428
20495
|
const safeToAck = off > 0 && off <= priorCursor;
|
|
20429
|
-
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 }]);
|
|
20430
20497
|
} catch {
|
|
20431
20498
|
}
|
|
20432
20499
|
}
|
|
@@ -20436,7 +20503,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20436
20503
|
if (!built) {
|
|
20437
20504
|
if (ledger) {
|
|
20438
20505
|
try {
|
|
20439
|
-
markSynced(
|
|
20506
|
+
markSynced(base3, [{ id: ref.prefixedId, mtime: ref.mtime }]);
|
|
20440
20507
|
} catch {
|
|
20441
20508
|
}
|
|
20442
20509
|
}
|
|
@@ -20493,7 +20560,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20493
20560
|
walked++;
|
|
20494
20561
|
if (walked % 250 === 0) console.error(`[sync] ${walked}/${slice.length} sessions\u2026`);
|
|
20495
20562
|
}
|
|
20496
|
-
const itemVersions = loadItemVersions(
|
|
20563
|
+
const itemVersions = loadItemVersions(base3);
|
|
20497
20564
|
const seenTools = /* @__PURE__ */ new Set();
|
|
20498
20565
|
const seenItemKeys = /* @__PURE__ */ new Map();
|
|
20499
20566
|
const registry = buildSourceRegistry();
|
|
@@ -20587,7 +20654,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20587
20654
|
await appendFlush();
|
|
20588
20655
|
for (const id of appendResults.fullResyncNeeded) {
|
|
20589
20656
|
try {
|
|
20590
|
-
markFullResync(
|
|
20657
|
+
markFullResync(base3, id);
|
|
20591
20658
|
} catch {
|
|
20592
20659
|
}
|
|
20593
20660
|
}
|
|
@@ -20600,7 +20667,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20600
20667
|
await findingsBatch.drain();
|
|
20601
20668
|
await drainInflight();
|
|
20602
20669
|
{
|
|
20603
|
-
const sentHashes = loadInventoryHashes(
|
|
20670
|
+
const sentHashes = loadInventoryHashes(base3);
|
|
20604
20671
|
const entries = [];
|
|
20605
20672
|
const hashes = {};
|
|
20606
20673
|
for (const [sourceType, ids] of inventory) {
|
|
@@ -20614,7 +20681,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20614
20681
|
if (entries.length > 0) {
|
|
20615
20682
|
try {
|
|
20616
20683
|
await post({ inventory: entries });
|
|
20617
|
-
saveInventoryHashes(
|
|
20684
|
+
saveInventoryHashes(base3, hashes);
|
|
20618
20685
|
} catch (err) {
|
|
20619
20686
|
console.error(`[sync] toolkit inventory not sent (it is retried next sync): ${err instanceof Error ? err.message : err}`);
|
|
20620
20687
|
}
|
|
@@ -20625,7 +20692,7 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20625
20692
|
const rec = {};
|
|
20626
20693
|
for (const t of seenTools) rec[t] = extractorVersionForTool(t);
|
|
20627
20694
|
for (const [k, v] of seenItemKeys) rec[k] = v;
|
|
20628
|
-
saveItemVersions(
|
|
20695
|
+
saveItemVersions(base3, rec);
|
|
20629
20696
|
} catch {
|
|
20630
20697
|
}
|
|
20631
20698
|
}
|
|
@@ -20638,9 +20705,9 @@ async function syncToTargetInScope(cred, opts = {}) {
|
|
|
20638
20705
|
}
|
|
20639
20706
|
if (tombstones.length > 0) {
|
|
20640
20707
|
await post({ tombstones });
|
|
20641
|
-
const data = getLedgerData(
|
|
20708
|
+
const data = getLedgerData(base3);
|
|
20642
20709
|
for (const t of tombstones) delete data[t.session_id];
|
|
20643
|
-
persistLedgerData(
|
|
20710
|
+
persistLedgerData(base3, data);
|
|
20644
20711
|
}
|
|
20645
20712
|
}
|
|
20646
20713
|
if (opts.prune) await post({ prune_empty_sessions: true });
|
|
@@ -21111,7 +21178,7 @@ var init_sync_client = __esm({
|
|
|
21111
21178
|
ownVersion = JSON.parse(readFileSync35(join42(dir, "../package.json"), "utf-8")).version || ownVersion;
|
|
21112
21179
|
} catch {
|
|
21113
21180
|
try {
|
|
21114
|
-
if (true) ownVersion = "0.7.
|
|
21181
|
+
if (true) ownVersion = "0.7.15";
|
|
21115
21182
|
} catch {
|
|
21116
21183
|
}
|
|
21117
21184
|
}
|
|
@@ -21170,10 +21237,10 @@ function parseAgentText(content, format, fallbackName) {
|
|
|
21170
21237
|
return { name: fm.name || fallbackName, description: fm.description || "", tools: fm.tools, body: body.trim() };
|
|
21171
21238
|
}
|
|
21172
21239
|
function readCommand(filePath, format) {
|
|
21173
|
-
return parseCommandText(readFileSync36(filePath, "utf-8"), format,
|
|
21240
|
+
return parseCommandText(readFileSync36(filePath, "utf-8"), format, base2(filePath));
|
|
21174
21241
|
}
|
|
21175
21242
|
function readAgent(filePath, format) {
|
|
21176
|
-
return parseAgentText(readFileSync36(filePath, "utf-8"), format,
|
|
21243
|
+
return parseAgentText(readFileSync36(filePath, "utf-8"), format, base2(filePath));
|
|
21177
21244
|
}
|
|
21178
21245
|
function readInstructions(filePath, name) {
|
|
21179
21246
|
const content = readFileSync36(filePath, "utf-8");
|
|
@@ -21273,7 +21340,7 @@ function emit(type, art, toTool, projectPath) {
|
|
|
21273
21340
|
content: stringifyFrontmatter({ name: art.name, description: art.description, ...art.tools ? { tools: art.tools } : {} }, art.body)
|
|
21274
21341
|
};
|
|
21275
21342
|
}
|
|
21276
|
-
function
|
|
21343
|
+
function base2(filePath) {
|
|
21277
21344
|
return basename21(filePath).replace(/\.(md|toml)$/, "");
|
|
21278
21345
|
}
|
|
21279
21346
|
var init_artifact_codec = __esm({
|
|
@@ -21711,11 +21778,11 @@ var init_toolkit_sync = __esm({
|
|
|
21711
21778
|
});
|
|
21712
21779
|
|
|
21713
21780
|
// ../engine/dist/core/which.js
|
|
21714
|
-
import { existsSync as existsSync44, statSync as
|
|
21781
|
+
import { existsSync as existsSync44, statSync as statSync40, accessSync, constants } from "node:fs";
|
|
21715
21782
|
import { join as join46, isAbsolute as isAbsolute2, delimiter as delimiter2, sep as sep3 } from "node:path";
|
|
21716
21783
|
function executable(p) {
|
|
21717
21784
|
try {
|
|
21718
|
-
if (!
|
|
21785
|
+
if (!statSync40(p).isFile())
|
|
21719
21786
|
return false;
|
|
21720
21787
|
} catch {
|
|
21721
21788
|
return false;
|
|
@@ -21778,11 +21845,11 @@ __export(toolkit_pull_exports, {
|
|
|
21778
21845
|
platformRefusal: () => platformRefusal,
|
|
21779
21846
|
portableCommand: () => portableCommand
|
|
21780
21847
|
});
|
|
21781
|
-
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";
|
|
21782
21849
|
import { dirname as dirname22, join as join47, basename as basename23, isAbsolute as isAbsolute3 } from "node:path";
|
|
21783
21850
|
function isExecutableFile(p) {
|
|
21784
21851
|
try {
|
|
21785
|
-
return
|
|
21852
|
+
return statSync41(p).isFile();
|
|
21786
21853
|
} catch {
|
|
21787
21854
|
return false;
|
|
21788
21855
|
}
|
|
@@ -21796,9 +21863,9 @@ function portableCommand(cmd) {
|
|
|
21796
21863
|
}
|
|
21797
21864
|
if (isExecutableFile(cmd))
|
|
21798
21865
|
return { command: cmd, rewritten: false };
|
|
21799
|
-
const
|
|
21800
|
-
if (onPath(
|
|
21801
|
-
return { command:
|
|
21866
|
+
const base3 = basename23(cmd);
|
|
21867
|
+
if (onPath(base3))
|
|
21868
|
+
return { command: base3, rewritten: true };
|
|
21802
21869
|
return { missing: cmd };
|
|
21803
21870
|
}
|
|
21804
21871
|
function entryFromSpec(spec) {
|
|
@@ -22315,7 +22382,7 @@ __export(shadow_prune_exports, {
|
|
|
22315
22382
|
DEFAULT_MAX_TOTAL_BYTES: () => DEFAULT_MAX_TOTAL_BYTES,
|
|
22316
22383
|
pruneShadow: () => pruneShadow
|
|
22317
22384
|
});
|
|
22318
|
-
import { readdirSync as readdirSync32, statSync as
|
|
22385
|
+
import { readdirSync as readdirSync32, statSync as statSync44, unlinkSync as unlinkSync3 } from "fs";
|
|
22319
22386
|
import { join as join50 } from "path";
|
|
22320
22387
|
function listShadows(isFullyAcked) {
|
|
22321
22388
|
const out = [];
|
|
@@ -22340,7 +22407,7 @@ function listShadows(isFullyAcked) {
|
|
|
22340
22407
|
const path = join50(dir, name);
|
|
22341
22408
|
let st;
|
|
22342
22409
|
try {
|
|
22343
|
-
st =
|
|
22410
|
+
st = statSync44(path);
|
|
22344
22411
|
} catch {
|
|
22345
22412
|
continue;
|
|
22346
22413
|
}
|
|
@@ -22455,7 +22522,7 @@ var init_code_intel = __esm({
|
|
|
22455
22522
|
});
|
|
22456
22523
|
|
|
22457
22524
|
// ../engine/dist/core/companions.js
|
|
22458
|
-
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";
|
|
22459
22526
|
import { homedir as homedir19 } from "node:os";
|
|
22460
22527
|
import { join as join51 } from "node:path";
|
|
22461
22528
|
import { execSync as execSync3 } from "node:child_process";
|
|
@@ -22506,7 +22573,7 @@ function checkCodeindexStatus() {
|
|
|
22506
22573
|
status.installed = true;
|
|
22507
22574
|
status.path = foundPath;
|
|
22508
22575
|
try {
|
|
22509
|
-
status.size =
|
|
22576
|
+
status.size = statSync45(foundPath).size;
|
|
22510
22577
|
} catch {
|
|
22511
22578
|
}
|
|
22512
22579
|
try {
|
|
@@ -22846,17 +22913,17 @@ async function collectCode(opts) {
|
|
|
22846
22913
|
return r;
|
|
22847
22914
|
};
|
|
22848
22915
|
log6(`indexing ${ws} + analyses \u2026`);
|
|
22849
|
-
const
|
|
22916
|
+
const base3 = await runMcp(bin, ws, [
|
|
22850
22917
|
call(1, "index_workspace", { path: ws }),
|
|
22851
22918
|
call(2, "status"),
|
|
22852
22919
|
call(3, "get_tree"),
|
|
22853
22920
|
...ANALYSES.map((a, i) => call(10 + i, "analyze", { analysis: a }))
|
|
22854
22921
|
]);
|
|
22855
|
-
const st = parseJson(
|
|
22856
|
-
const tree = parseJson(
|
|
22922
|
+
const st = parseJson(base3, 2, {});
|
|
22923
|
+
const tree = parseJson(base3, 3, []);
|
|
22857
22924
|
const A = {};
|
|
22858
22925
|
ANALYSES.forEach((a, i) => {
|
|
22859
|
-
A[a] = parseJson(
|
|
22926
|
+
A[a] = parseJson(base3, 10 + i, {});
|
|
22860
22927
|
});
|
|
22861
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;
|
|
22862
22929
|
if (tree.length === 0) {
|
|
@@ -23949,7 +24016,7 @@ import { join as join48 } from "node:path";
|
|
|
23949
24016
|
|
|
23950
24017
|
// src/project-tasks.ts
|
|
23951
24018
|
init_http();
|
|
23952
|
-
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";
|
|
23953
24020
|
import { join as join45, dirname as dirname21 } from "node:path";
|
|
23954
24021
|
import { homedir as homedir18 } from "node:os";
|
|
23955
24022
|
|
|
@@ -24042,14 +24109,14 @@ var FILE_KINDS = [
|
|
|
24042
24109
|
{ kind: "secret", filename: "SECURITY_TASKS.md", trackedPath: "/api/secrets/tasks/tracked", statusPath: "/api/secrets/tasks/status" },
|
|
24043
24110
|
{ kind: "code", filename: "CODE_TASKS.md", trackedPath: "/api/code/tasks/tracked", statusPath: "/api/code/tasks/status" }
|
|
24044
24111
|
];
|
|
24045
|
-
async function pushProjectTaskStatuses(
|
|
24112
|
+
async function pushProjectTaskStatuses(base3, authHeaders, opts = {}) {
|
|
24046
24113
|
const out = { files: 0, pushedTasks: 0 };
|
|
24047
24114
|
const ledger = readLedger();
|
|
24048
24115
|
let ledgerDirty = false;
|
|
24049
24116
|
for (const fk of FILE_KINDS) {
|
|
24050
24117
|
let projects;
|
|
24051
24118
|
try {
|
|
24052
|
-
const res = await fetchWithTimeout(`${
|
|
24119
|
+
const res = await fetchWithTimeout(`${base3}${fk.trackedPath}`, { headers: authHeaders });
|
|
24053
24120
|
if (!res.ok) continue;
|
|
24054
24121
|
projects = (await res.json()).projects || [];
|
|
24055
24122
|
} catch {
|
|
@@ -24060,7 +24127,7 @@ async function pushProjectTaskStatuses(base2, authHeaders, opts = {}) {
|
|
|
24060
24127
|
if (!existsSync43(file)) continue;
|
|
24061
24128
|
let mtime;
|
|
24062
24129
|
try {
|
|
24063
|
-
mtime =
|
|
24130
|
+
mtime = statSync39(file).mtimeMs;
|
|
24064
24131
|
} catch {
|
|
24065
24132
|
continue;
|
|
24066
24133
|
}
|
|
@@ -24077,7 +24144,7 @@ async function pushProjectTaskStatuses(base2, authHeaders, opts = {}) {
|
|
|
24077
24144
|
continue;
|
|
24078
24145
|
}
|
|
24079
24146
|
try {
|
|
24080
|
-
const res = await fetchWithTimeout(`${
|
|
24147
|
+
const res = await fetchWithTimeout(`${base3}${fk.statusPath}`, {
|
|
24081
24148
|
method: "POST",
|
|
24082
24149
|
headers: { "content-type": "application/json", ...authHeaders },
|
|
24083
24150
|
body: JSON.stringify({ project, items: changed.map((t) => ({ id: t.id, status: t.intent })) })
|
|
@@ -24167,16 +24234,16 @@ ${block}`);
|
|
|
24167
24234
|
return { status: "error", result: JSON.stringify({ error: e instanceof Error ? e.message : "failed" }) };
|
|
24168
24235
|
}
|
|
24169
24236
|
}
|
|
24170
|
-
async function runPull(
|
|
24237
|
+
async function runPull(base3, opts) {
|
|
24171
24238
|
const { executePull: executePull2 } = await Promise.resolve().then(() => (init_toolkit_pull(), toolkit_pull_exports));
|
|
24172
24239
|
const { hostname: hostname3 } = await import("node:os");
|
|
24173
|
-
const creds = loadAllCredentials().find((c) => c.serverUrl.replace(/\/+$/, "") ===
|
|
24240
|
+
const creds = loadAllCredentials().find((c) => c.serverUrl.replace(/\/+$/, "") === base3.replace(/\/+$/, ""));
|
|
24174
24241
|
const headers = creds?.token ? { authorization: `Bearer ${creds.token}` } : {};
|
|
24175
24242
|
const wanted = opts.types?.length ? opts.types : ["mcp", "skill", "command", "agent", "instructions"];
|
|
24176
24243
|
const rows = [];
|
|
24177
24244
|
for (const type of wanted) {
|
|
24178
24245
|
try {
|
|
24179
|
-
const res = await fetchWithTimeout(`${
|
|
24246
|
+
const res = await fetchWithTimeout(`${base3}/api/toolkit/browse/${type}?limit=1000`, { headers });
|
|
24180
24247
|
if (!res.ok) continue;
|
|
24181
24248
|
const body = await res.json();
|
|
24182
24249
|
for (const it of body.items || []) rows.push(it);
|
|
@@ -24248,27 +24315,27 @@ try {
|
|
|
24248
24315
|
ownVersion2 = JSON.parse(readFileSync39(join48(dir, "../package.json"), "utf-8")).version || ownVersion2;
|
|
24249
24316
|
} catch {
|
|
24250
24317
|
try {
|
|
24251
|
-
if (true) ownVersion2 = "0.7.
|
|
24318
|
+
if (true) ownVersion2 = "0.7.15";
|
|
24252
24319
|
} catch {
|
|
24253
24320
|
}
|
|
24254
24321
|
}
|
|
24255
24322
|
async function drainSyncIntents(opts = {}) {
|
|
24256
24323
|
const out = { processed: 0, done: 0, errored: 0 };
|
|
24257
24324
|
for (const cred of loadAllCredentials()) {
|
|
24258
|
-
const
|
|
24325
|
+
const base3 = cred.serverUrl.replace(/\/+$/, "");
|
|
24259
24326
|
const authHeaders = cred.token ? { authorization: `Bearer ${cred.token}` } : {};
|
|
24260
24327
|
let pending;
|
|
24261
24328
|
try {
|
|
24262
|
-
const res = await fetchWithTimeout(`${
|
|
24329
|
+
const res = await fetchWithTimeout(`${base3}/api/sync-intents/pending`, { headers: authHeaders });
|
|
24263
24330
|
if (!res.ok) continue;
|
|
24264
24331
|
const data = await res.json();
|
|
24265
24332
|
pending = data.intents || [];
|
|
24266
24333
|
if (data.cli && data.cli.version) {
|
|
24267
24334
|
const { planAutoUpdate: planAutoUpdate2, runAutoUpdate: runAutoUpdate2, sweepStaleStaging: sweepStaleStaging2 } = await Promise.resolve().then(() => (init_auto_update(), auto_update_exports));
|
|
24268
|
-
const plan = planAutoUpdate2(
|
|
24335
|
+
const plan = planAutoUpdate2(base3, { cli: data.cli }, ownVersion2, process.env.CHAT_RECALL_AUTO_UPDATE);
|
|
24269
24336
|
sweepStaleStaging2();
|
|
24270
24337
|
if (plan.update) {
|
|
24271
|
-
void runAutoUpdate2(
|
|
24338
|
+
void runAutoUpdate2(base3, authHeaders, ownVersion2).catch(() => {
|
|
24272
24339
|
});
|
|
24273
24340
|
}
|
|
24274
24341
|
}
|
|
@@ -24276,7 +24343,7 @@ async function drainSyncIntents(opts = {}) {
|
|
|
24276
24343
|
continue;
|
|
24277
24344
|
}
|
|
24278
24345
|
for (const intent of pending) {
|
|
24279
|
-
const { status, result } = await runIntent(intent, { base:
|
|
24346
|
+
const { status, result } = await runIntent(intent, { base: base3 });
|
|
24280
24347
|
out.processed++;
|
|
24281
24348
|
if (status === "done") out.done++;
|
|
24282
24349
|
else out.errored++;
|
|
@@ -24285,7 +24352,7 @@ async function drainSyncIntents(opts = {}) {
|
|
|
24285
24352
|
console.error(`[sync-intent] ${label}: ${status}`);
|
|
24286
24353
|
}
|
|
24287
24354
|
try {
|
|
24288
|
-
await fetchWithTimeout(`${
|
|
24355
|
+
await fetchWithTimeout(`${base3}/api/sync-intents/${intent.id}/ack`, {
|
|
24289
24356
|
method: "POST",
|
|
24290
24357
|
headers: { "content-type": "application/json", ...authHeaders },
|
|
24291
24358
|
body: JSON.stringify({ status, result })
|
|
@@ -24294,7 +24361,7 @@ async function drainSyncIntents(opts = {}) {
|
|
|
24294
24361
|
}
|
|
24295
24362
|
}
|
|
24296
24363
|
try {
|
|
24297
|
-
await pushProjectTaskStatuses(
|
|
24364
|
+
await pushProjectTaskStatuses(base3, authHeaders, { verbose: opts.verbose });
|
|
24298
24365
|
} catch {
|
|
24299
24366
|
}
|
|
24300
24367
|
}
|
|
@@ -24313,7 +24380,7 @@ init_auto_update();
|
|
|
24313
24380
|
|
|
24314
24381
|
// src/code-index-cursor.ts
|
|
24315
24382
|
init_paths();
|
|
24316
|
-
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";
|
|
24317
24384
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
24318
24385
|
import { createHash as createHash10 } from "crypto";
|
|
24319
24386
|
import { join as join49, dirname as dirname24 } from "path";
|
|
@@ -24364,7 +24431,7 @@ function workspaceFingerprint(workspace, collectorVersion) {
|
|
|
24364
24431
|
const rel = entry.slice(3);
|
|
24365
24432
|
let stamp2 = "gone";
|
|
24366
24433
|
try {
|
|
24367
|
-
const s =
|
|
24434
|
+
const s = statSync42(join49(workspace, rel));
|
|
24368
24435
|
stamp2 = `${s.size}:${Math.floor(s.mtimeMs)}`;
|
|
24369
24436
|
} catch {
|
|
24370
24437
|
}
|
|
@@ -24573,11 +24640,11 @@ function checkSelfRestart(opts) {
|
|
|
24573
24640
|
}
|
|
24574
24641
|
|
|
24575
24642
|
// src/log-rotate.ts
|
|
24576
|
-
import { statSync as
|
|
24643
|
+
import { statSync as statSync43, copyFileSync as copyFileSync3, truncateSync } from "fs";
|
|
24577
24644
|
var LOG_MAX_BYTES = 32 * 1024 * 1024;
|
|
24578
24645
|
function rotateLogIfLarge(logPath, maxBytes = LOG_MAX_BYTES) {
|
|
24579
24646
|
try {
|
|
24580
|
-
const size =
|
|
24647
|
+
const size = statSync43(logPath).size;
|
|
24581
24648
|
if (size < maxBytes) return { rotated: false, sizeBefore: 0 };
|
|
24582
24649
|
copyFileSync3(logPath, `${logPath}.1`);
|
|
24583
24650
|
truncateSync(logPath, 0);
|
|
@@ -24632,8 +24699,8 @@ async function runCollectorMigration(opts) {
|
|
|
24632
24699
|
// auto-indexer/indexer.ts
|
|
24633
24700
|
init_sync_ledger();
|
|
24634
24701
|
init_collector_health();
|
|
24635
|
-
import { existsSync as existsSync50, readFileSync as readFileSync45, statSync as
|
|
24636
|
-
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";
|
|
24637
24704
|
var DEBOUNCE_MS = 5e3;
|
|
24638
24705
|
var PLANS_DIR = claudeBackend.plansDir();
|
|
24639
24706
|
var TASKS_DIR = claudeBackend.tasksDir();
|
|
@@ -24738,7 +24805,7 @@ var CLAUDE_SESSION_ROOTS = claudeProjectDirs();
|
|
|
24738
24805
|
var sessionWatcher = watchWithFallback("sessions", CLAUDE_SESSION_ROOTS.map((root) => `${root}/**/*.jsonl`), {
|
|
24739
24806
|
ignored: (p, stats) => {
|
|
24740
24807
|
if (/agent-/.test(p) || /^\./.test(basename25(p))) return true;
|
|
24741
|
-
const st = stats ??
|
|
24808
|
+
const st = stats ?? statSync46(p, { throwIfNoEntry: false });
|
|
24742
24809
|
if (!st || st.isDirectory()) return false;
|
|
24743
24810
|
return st.mtimeMs < Date.now() - WATCH_WINDOW_MS;
|
|
24744
24811
|
},
|
|
@@ -25108,10 +25175,10 @@ async function codeIndexTick() {
|
|
|
25108
25175
|
continue;
|
|
25109
25176
|
}
|
|
25110
25177
|
for (const cred of creds) {
|
|
25111
|
-
const
|
|
25178
|
+
const base3 = cred.serverUrl.replace(/\/+$/, "");
|
|
25112
25179
|
const headers = { "content-type": "application/json", ...cred.token ? { authorization: `Bearer ${cred.token}` } : {} };
|
|
25113
25180
|
try {
|
|
25114
|
-
await fetchWithTimeout(`${
|
|
25181
|
+
await fetchWithTimeout(`${base3}/api/code/index`, { method: "POST", headers, body: JSON.stringify(result) }, 6e4);
|
|
25115
25182
|
} catch {
|
|
25116
25183
|
}
|
|
25117
25184
|
}
|
|
@@ -25134,12 +25201,12 @@ if (CODE_INDEX_ON) {
|
|
|
25134
25201
|
}
|
|
25135
25202
|
async function autoUpdateTick() {
|
|
25136
25203
|
for (const cred of loadAllCredentials()) {
|
|
25137
|
-
const
|
|
25204
|
+
const base3 = cred.serverUrl.replace(/\/+$/, "");
|
|
25138
25205
|
const headers = cred.token ? { authorization: `Bearer ${cred.token}` } : {};
|
|
25139
25206
|
try {
|
|
25140
|
-
const r = await runAutoUpdate(
|
|
25141
|
-
if (r.updated) daemonLog.info(`auto-update: ${r.reason} (${
|
|
25142
|
-
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})`);
|
|
25143
25210
|
} catch {
|
|
25144
25211
|
}
|
|
25145
25212
|
}
|
|
@@ -25166,20 +25233,20 @@ async function collectorMigrationOnce() {
|
|
|
25166
25233
|
return;
|
|
25167
25234
|
}
|
|
25168
25235
|
for (const cred of creds) {
|
|
25169
|
-
const
|
|
25236
|
+
const base3 = cred.serverUrl.replace(/\/+$/, "");
|
|
25170
25237
|
const headers = { "content-type": "application/json", ...cred.token ? { authorization: `Bearer ${cred.token}` } : {} };
|
|
25171
25238
|
const reindex = async (rootPath) => {
|
|
25172
25239
|
try {
|
|
25173
25240
|
const result = await collectCode2({ workspace: rootPath, binPath: bin });
|
|
25174
|
-
const res = await fetchWithTimeout(`${
|
|
25241
|
+
const res = await fetchWithTimeout(`${base3}/api/code/index`, { method: "POST", headers, body: JSON.stringify(result) }, 6e4);
|
|
25175
25242
|
return res.ok;
|
|
25176
25243
|
} catch {
|
|
25177
25244
|
return false;
|
|
25178
25245
|
}
|
|
25179
25246
|
};
|
|
25180
25247
|
try {
|
|
25181
|
-
const r = await runCollectorMigration({ base:
|
|
25182
|
-
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}`);
|
|
25183
25250
|
} catch {
|
|
25184
25251
|
}
|
|
25185
25252
|
}
|