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/watch.js CHANGED
@@ -4458,7 +4458,7 @@ var require_pino = __commonJS({
4458
4458
  messageKey,
4459
4459
  errorKey,
4460
4460
  nestedKey,
4461
- base: base2,
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 (base2 !== null) {
4500
+ if (base3 !== null) {
4501
4501
  if (name === void 0) {
4502
- chindings = coreChindings(base2);
4502
+ chindings = coreChindings(base3);
4503
4503
  } else {
4504
- chindings = coreChindings(Object.assign({}, base2, { name }));
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(base2, partial) {
4884
+ function mergeSources(base3, partial) {
4885
4885
  if (!partial)
4886
- return base2;
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: { ...base2.enabled.claude, ...partial.enabled?.claude ?? {} },
4891
- opencode: { ...base2.enabled.opencode, ...partial.enabled?.opencode ?? {} },
4892
- codex: { ...base2.enabled.codex, ...partial.enabled?.codex ?? {} },
4893
- agy: { ...base2.enabled.agy, ...inherited, ...partial.enabled?.agy ?? {} },
4894
- cursor: { ...base2.enabled.cursor, ...partial.enabled?.cursor ?? {} },
4895
- shared: { ...base2.enabled.shared, ...partial.enabled?.shared ?? {} },
4896
- common: { ...base2.enabled.common, ...partial.enabled?.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 ?? base2.claudeHome,
4900
- geminiHome: partial.geminiHome ?? base2.geminiHome,
4901
- codexHome: partial.codexHome ?? base2.codexHome,
4902
- opencodeDbPath: partial.opencodeDbPath ?? base2.opencodeDbPath,
4903
- agyHome: partial.agyHome ?? base2.agyHome,
4904
- cursorHome: partial.cursorHome ?? base2.cursorHome,
4905
- cursorIdeHome: partial.cursorIdeHome ?? base2.cursorIdeHome,
4906
- extraClaudeHomes: partial.extraClaudeHomes ?? base2.extraClaudeHomes,
4907
- approvedHomes: partial.approvedHomes ?? base2.approvedHomes,
4908
- declinedHomes: partial.declinedHomes ?? base2.declinedHomes,
4909
- homesGrandfathered: partial.homesGrandfathered ?? base2.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(base2, partial) {
4913
+ function mergePrivacy(base3, partial) {
4914
4914
  if (!partial)
4915
- return base2;
4916
- return { ...base2, ...partial };
4915
+ return base3;
4916
+ return { ...base3, ...partial };
4917
4917
  }
4918
- function mergeSync(base2, partial) {
4918
+ function mergeSync(base3, partial) {
4919
4919
  if (!partial)
4920
- return base2;
4920
+ return base3;
4921
4921
  return {
4922
- ...base2,
4922
+ ...base3,
4923
4923
  ...partial,
4924
- upload: { ...base2.upload, ...partial.upload ?? {} }
4924
+ upload: { ...base3.upload, ...partial.upload ?? {} }
4925
4925
  };
4926
4926
  }
4927
- function mergeTeam(base2, partial) {
4927
+ function mergeTeam(base3, partial) {
4928
4928
  if (!partial)
4929
- return base2;
4929
+ return base3;
4930
4930
  return {
4931
- ...base2,
4931
+ ...base3,
4932
4932
  ...partial,
4933
- publishAllowed: { ...base2.publishAllowed, ...partial.publishAllowed ?? {} },
4934
- vault: { ...base2.vault, ...partial.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 base2 = freshDefaults();
5043
+ const base3 = freshDefaults();
5044
5044
  const result = {
5045
5045
  v: SCHEMA_VERSION,
5046
- embedding: { ...base2.embedding, ...parsed.embedding ?? {} },
5047
- summary: { ...base2.summary, ...parsed.summary ?? {} },
5048
- sources: mergeSources(base2.sources, parsed.sources),
5049
- privacy: mergePrivacy(base2.privacy, parsed.privacy),
5050
- sync: mergeSync(base2.sync, parsed.sync),
5051
- team: mergeTeam(base2.team, parsed.team)
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: base2, marker } of bases) {
5158
- add(base2, marker);
5159
- const parent = dirname3(base2);
5160
- const leaf = base2.slice(parent.length + 1);
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(base2, overridden, suffix) {
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(base2);
5348
+ add(base3);
5349
5349
  if (!overridden) {
5350
- const parent = dirname4(base2);
5351
- const leaf = basename(base2);
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 snapshot = obj.snapshot;
5848
- if (snapshot && typeof snapshot === "object") {
5849
- const backups = snapshot.trackedFileBackups;
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 base2 = settingsView().rules;
12284
- return serverPack && serverPack.rules.length > 0 ? [...base2, ...serverPack.rules] : base2;
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 load() {
18077
- if (cache3) return cache3;
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(ledgerPath(), "utf-8"));
18080
- cache3 = parsed && typeof parsed === "object" ? parsed : {};
18086
+ const parsed = JSON.parse(readFileSync30(path, "utf-8"));
18087
+ return parsed && typeof parsed === "object" ? parsed : {};
18081
18088
  } catch {
18082
- cache3 = {};
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(data) {
18145
+ function persistNow() {
18087
18146
  const path = ledgerPath();
18088
18147
  mkdirSync7(dirname16(path), { recursive: true });
18089
- const tmp = `${path}.tmp`;
18090
- writeFileSync6(tmp, JSON.stringify(data));
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(data) {
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(data);
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(data);
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(cache3);
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 base2 = prevF ? { m: Math.floor(r.mtime), v: ev, f: prevF } : { m: Math.floor(r.mtime), v: ev };
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
- base2.o = o;
18235
- base2.s = s;
18296
+ base3.o = o;
18297
+ base3.s = s;
18236
18298
  }
18237
- if (r.hash !== void 0) base2.h = r.hash;
18238
- forServer[r.id] = base2;
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 statSync35, closeSync as closeSync8 } from "fs";
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 = statSync35(lockPath);
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.14";
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.14" : "dev";
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(base2, opts = {}) {
19071
+ async function probeServer(base3, opts = {}) {
19005
19072
  const f = opts.fetchImpl || fetch;
19006
19073
  let res;
19007
19074
  try {
19008
- res = await f(`${base2.replace(/\/+$/, "")}/api/capabilities`, {
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, base2) {
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 ${base2}. If the host moved, re-point it: \`chat-recall login <new-server-url>\``;
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 ${base2} rejected the credential. Re-login: \`chat-recall login ` + base2 + "`";
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 ${base2} is up but failing. Nothing to fix locally; check the server.`;
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 `${base2} 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`;
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 ${base2} (${r.error}) \u2014 check the URL for a typo, and your DNS or VPN`;
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 `${base2} resolves but refused the connection (${r.error}) \u2014 the server is not running, or the port is wrong`;
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 ${base2} was rejected (${r.error}) \u2014 expired, self-signed, or issued for another host. A corporate proxy that re-signs traffic does this.`;
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 `${base2} did not answer in time (${r.error}) \u2014 a firewall or proxy that drops traffic silently looks exactly like this`;
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 ${base2} was cut (${r.error}) \u2014 often a proxy or a captive portal`;
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 `${base2} names a port that Node and every browser refuse to open (the WHATWG bad-port list) \u2014 use the server's real port`;
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 ${base2} (${r.error}) \u2014 check the URL, DNS, or that the server is running`;
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 base2 = err instanceof Error ? err.message : String(err);
19106
- return parts.length ? `${base2}: ${parts.join(" \u2192 ")}` : base2;
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 statSync36, mkdirSync as mkdirSync9 } from "node:fs";
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(base2, caps, ownVersion3, flag) {
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(base2, rel.version), fallbackUrl: tarballUrl(base2), sha256: rel.sha256, from: ownVersion3, to: rel.version };
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 = statSync36(dir);
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(base2, authHeaders, ownVersion3, deps) {
19503
+ async function runAutoUpdate(base3, authHeaders, ownVersion3, deps) {
19437
19504
  let caps;
19438
19505
  try {
19439
- const res = await fetchWithTimeout(`${base2.replace(/\/+$/, "")}/api/capabilities`, { headers: authHeaders });
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(base2, caps, effectiveOwn, process.env.CHAT_RECALL_AUTO_UPDATE);
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(base2)) {
19449
- reportedStandingSkip.add(base2);
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 = (base2, version) => `${base2.replace(/\/+$/, "")}/install/${version ? `chat-recall-${version}.tgz` : "chat-recall.tgz"}`;
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 statSync37 } from "node:fs";
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 base2 = cred.serverUrl.replace(/\/+$/, "");
19562
- const cached = _securityConfigCache.get(base2);
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(`${base2}/api/secrets/rules`, { headers }),
19569
- fetchWithTimeout(`${base2}/api/teams/security-config`, { headers }).catch(() => null)
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(base2, body.telemetry);
19661
+ setTelemetryEligible(base3, body.telemetry);
19595
19662
  try {
19596
19663
  const prior = readCollectorHealth()?.telemetryEligible ?? {};
19597
19664
  updateCollectorHealth({
19598
- telemetryEligible: { ...prior, [base2]: { allowed: body.telemetry, at: Date.now() } }
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(base2, { fetchedAt: Date.now(), config });
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(base2, config) {
19688
+ function persistSyncConfig(base3, config) {
19622
19689
  try {
19623
19690
  const all = readPersistedSyncConfigs();
19624
- all[base2] = { fetchedAt: Date.now(), config };
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 base2 = cred.serverUrl.replace(/\/+$/, "");
19632
- const cached = _syncConfigCache.get(base2);
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(`${base2}/api/sync-config/sources`, {
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(`${base2}/api/sync-config`, { headers });
19715
+ const res = await fetchWithTimeout(`${base3}/api/sync-config`, { headers });
19649
19716
  if (res.status === 404) {
19650
- _syncConfigCache.set(base2, { fetchedAt: Date.now(), config: EMPTY_SYNC_CONFIG });
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(base2, `HTTP ${res.status}`);
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(base2, { fetchedAt: Date.now(), config });
19691
- persistSyncConfig(base2, config);
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(base2, err instanceof Error ? err.message : "request failed");
19762
+ return lastKnownSyncConfig(base3, err instanceof Error ? err.message : "request failed");
19696
19763
  }
19697
19764
  }
19698
- function lastKnownSyncConfig(base2, reason) {
19699
- const remembered = _syncConfigCache.get(base2) ?? readPersistedSyncConfigs()[base2];
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 ${base2} (${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.`
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(base2, token, rows) {
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(`${base2}/api/sync`, { method: "POST", headers, body: JSON.stringify({ fields: rows }) }, 6e4);
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(`${base2}: fields batch HTTP ${res.status} ${await res.text().catch(() => "")}`);
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 base2 = cred.serverUrl.replace(/\/+$/, "");
19828
- const ledger = getSyncedRows(base2);
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(base2, field);
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(base2, cred.token, chunk);
19848
- markFieldCoverage(base2, field, chunk.map((r) => ({ id: r.session_id, present: true, mtime: mtimeById.get(r.session_id) ?? 0 })));
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(base2, field, absentIds.map((id) => ({ id, present: false, mtime: mtimeById.get(id) ?? 0 })));
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(base2, field);
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 - statSync37(p).mtimeMs < maxAgeMs) continue;
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 base2 = serverUrl.replace(/\/$/, "");
19946
- const seen = capsOk.get(base2);
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(base2, {
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, base2));
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(base2, Math.floor(adv));
20026
+ advertisedIngestConc.set(base3, Math.floor(adv));
19960
20027
  }
19961
- if (caps.limits?.acceptsGzipBody === true) advertisedGzipBody.add(base2);
19962
- else advertisedGzipBody.delete(base2);
19963
- capsOk.set(base2, Date.now());
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(`${base2}/api/sync`, {
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(base2, body2.telemetry);
20111
+ setTelemetryEligible(base3, body2.telemetry);
20045
20112
  try {
20046
20113
  const prior = readCollectorHealth()?.telemetryEligible ?? {};
20047
20114
  updateCollectorHealth({
20048
- telemetryEligible: { ...prior, [base2]: { allowed: body2.telemetry, at: Date.now() } }
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(base2, Math.floor(adv));
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(base2, { cli: body2.cli }, ownVersion, process.env.CHAT_RECALL_AUTO_UPDATE);
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(base2, authHeaders, ownVersion).catch(() => {
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 ${base2}`);
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 ${base2}${why} \u2014 backing off ${Math.round(waitMs / 1e3)}s (attempt ${attempt + 1})`);
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 base2 = cred.serverUrl.replace(/\/$/, "");
20162
- const ledger = opts.useLedger ? getSyncedRows(base2) : null;
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(base2, rows.map((r) => {
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(`${base2}/api/sync`, {
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(base2, { cli: body.cli }, ownVersion, process.env.CHAT_RECALL_AUTO_UPDATE);
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(base2, authHeaders, ownVersion).catch(() => {
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(base2, acked.map((c) => ({
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(`${base2}/api/sync`, {
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(base2, [{ id, mtime, offset: conv.from_offset, size: conv.from_offset, acked: true }]);
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(base2, [{ id, mtime, offset: guarded.o, size: guarded.o, acked: true }]);
20308
+ markSynced(base3, [{ id, mtime, offset: guarded.o, size: guarded.o, acked: true }]);
20242
20309
  } else {
20243
- markSynced(base2, [{ id, mtime }]);
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 ${base2}`);
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 (${base2}): ${e instanceof Error ? e.message : e}`);
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(base2)).size === 0;
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(base2, [{ id: ref.prefixedId, mtime: ref.mtime }]);
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(base2, [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 }]);
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(base2, [{ id: ref.prefixedId, mtime: ref.mtime }]);
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(base2);
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(base2, id);
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(base2);
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(base2, hashes);
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(base2, rec);
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(base2);
20708
+ const data = getLedgerData(base3);
20642
20709
  for (const t of tombstones) delete data[t.session_id];
20643
- persistLedgerData(base2, data);
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.14";
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, base(filePath));
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, base(filePath));
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 base(filePath) {
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 statSync39, accessSync, constants } from "node:fs";
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 (!statSync39(p).isFile())
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 statSync40, writeFileSync as writeFileSync12 } from "node:fs";
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 statSync40(p).isFile();
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 base2 = basename23(cmd);
21800
- if (onPath(base2))
21801
- return { command: base2, rewritten: true };
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 statSync43, unlinkSync as unlinkSync3 } from "fs";
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 = statSync43(path);
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 statSync44, chmodSync as chmodSync4, unlinkSync as unlinkSync4, renameSync as renameSync5, createWriteStream, readFileSync as readFileSync42, writeFileSync as writeFileSync15 } from "node:fs";
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 = statSync44(foundPath).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 base2 = await runMcp(bin, ws, [
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(base2, 2, {});
22856
- const tree = parseJson(base2, 3, []);
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(base2, 10 + i, {});
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 statSync38 } from "node:fs";
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(base2, authHeaders, opts = {}) {
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(`${base2}${fk.trackedPath}`, { headers: authHeaders });
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 = statSync38(file).mtimeMs;
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(`${base2}${fk.statusPath}`, {
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(base2, opts) {
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(/\/+$/, "") === base2.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(`${base2}/api/toolkit/browse/${type}?limit=1000`, { headers });
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.14";
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 base2 = cred.serverUrl.replace(/\/+$/, "");
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(`${base2}/api/sync-intents/pending`, { headers: authHeaders });
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(base2, { cli: data.cli }, ownVersion2, process.env.CHAT_RECALL_AUTO_UPDATE);
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(base2, authHeaders, ownVersion2).catch(() => {
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: base2 });
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(`${base2}/api/sync-intents/${intent.id}/ack`, {
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(base2, authHeaders, { verbose: opts.verbose });
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 statSync41 } from "fs";
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 = statSync41(join49(workspace, rel));
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 statSync42, copyFileSync as copyFileSync3, truncateSync } from "fs";
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 = statSync42(logPath).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 statSync45 } from "fs";
24636
- var CLI_VERSION3 = true ? "0.7.14" : "0.0.0";
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 ?? statSync45(p, { throwIfNoEntry: false });
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 base2 = cred.serverUrl.replace(/\/+$/, "");
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(`${base2}/api/code/index`, { method: "POST", headers, body: JSON.stringify(result) }, 6e4);
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 base2 = cred.serverUrl.replace(/\/+$/, "");
25204
+ const base3 = cred.serverUrl.replace(/\/+$/, "");
25138
25205
  const headers = cred.token ? { authorization: `Bearer ${cred.token}` } : {};
25139
25206
  try {
25140
- const r = await runAutoUpdate(base2, headers, CLI_VERSION3);
25141
- if (r.updated) daemonLog.info(`auto-update: ${r.reason} (${base2}) \u2014 restarting service`);
25142
- else if (!/already current|disabled|no CLI release/.test(r.reason)) daemonLog.info(`auto-update: ${r.reason} (${base2})`);
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 base2 = cred.serverUrl.replace(/\/+$/, "");
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(`${base2}/api/code/index`, { method: "POST", headers, body: JSON.stringify(result) }, 6e4);
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: base2, authHeaders: headers, current: COLLECTOR_VERSION2, reindex, log: (m) => daemonLog.info(`${m}`) });
25182
- if (r.reindexed || r.failed || r.missing) daemonLog.info(`collector migration (${base2}): re-derived ${r.reindexed}, failed ${r.failed}, skipped-missing ${r.missing}`);
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
  }