chat-recall 0.7.14 → 0.7.16

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 CHANGED
@@ -4259,7 +4259,7 @@ var require_pino = __commonJS({
4259
4259
  messageKey,
4260
4260
  errorKey,
4261
4261
  nestedKey,
4262
- base: base3,
4262
+ base: base4,
4263
4263
  name,
4264
4264
  level: level2,
4265
4265
  customLevels,
@@ -4298,11 +4298,11 @@ var require_pino = __commonJS({
4298
4298
  [formattersSym]: allFormatters
4299
4299
  });
4300
4300
  let chindings = "";
4301
- if (base3 !== null) {
4301
+ if (base4 !== null) {
4302
4302
  if (name === void 0) {
4303
- chindings = coreChindings(base3);
4303
+ chindings = coreChindings(base4);
4304
4304
  } else {
4305
- chindings = coreChindings(Object.assign({}, base3, { name }));
4305
+ chindings = coreChindings(Object.assign({}, base4, { name }));
4306
4306
  }
4307
4307
  }
4308
4308
  const time2 = timestamp instanceof Function ? timestamp : timestamp ? epochTime : nullTime;
@@ -4834,57 +4834,57 @@ function freshDefaults() {
4834
4834
  team: defaultTeam()
4835
4835
  };
4836
4836
  }
4837
- function mergeSources(base3, partial) {
4837
+ function mergeSources(base4, partial) {
4838
4838
  if (!partial)
4839
- return base3;
4839
+ return base4;
4840
4840
  const legacyGemini = partial.enabled?.gemini;
4841
4841
  const inherited = legacyGemini && typeof legacyGemini === "object" ? (({ sessions: _s, plans: _p, ...rest }) => rest)(legacyGemini) : {};
4842
4842
  const enabled = {
4843
- claude: { ...base3.enabled.claude, ...partial.enabled?.claude ?? {} },
4844
- opencode: { ...base3.enabled.opencode, ...partial.enabled?.opencode ?? {} },
4845
- codex: { ...base3.enabled.codex, ...partial.enabled?.codex ?? {} },
4846
- agy: { ...base3.enabled.agy, ...inherited, ...partial.enabled?.agy ?? {} },
4847
- cursor: { ...base3.enabled.cursor, ...partial.enabled?.cursor ?? {} },
4848
- shared: { ...base3.enabled.shared, ...partial.enabled?.shared ?? {} },
4849
- common: { ...base3.enabled.common, ...partial.enabled?.common ?? {} }
4843
+ claude: { ...base4.enabled.claude, ...partial.enabled?.claude ?? {} },
4844
+ opencode: { ...base4.enabled.opencode, ...partial.enabled?.opencode ?? {} },
4845
+ codex: { ...base4.enabled.codex, ...partial.enabled?.codex ?? {} },
4846
+ agy: { ...base4.enabled.agy, ...inherited, ...partial.enabled?.agy ?? {} },
4847
+ cursor: { ...base4.enabled.cursor, ...partial.enabled?.cursor ?? {} },
4848
+ shared: { ...base4.enabled.shared, ...partial.enabled?.shared ?? {} },
4849
+ common: { ...base4.enabled.common, ...partial.enabled?.common ?? {} }
4850
4850
  };
4851
4851
  return {
4852
- claudeHome: partial.claudeHome ?? base3.claudeHome,
4853
- geminiHome: partial.geminiHome ?? base3.geminiHome,
4854
- codexHome: partial.codexHome ?? base3.codexHome,
4855
- opencodeDbPath: partial.opencodeDbPath ?? base3.opencodeDbPath,
4856
- agyHome: partial.agyHome ?? base3.agyHome,
4857
- cursorHome: partial.cursorHome ?? base3.cursorHome,
4858
- cursorIdeHome: partial.cursorIdeHome ?? base3.cursorIdeHome,
4859
- extraClaudeHomes: partial.extraClaudeHomes ?? base3.extraClaudeHomes,
4860
- approvedHomes: partial.approvedHomes ?? base3.approvedHomes,
4861
- declinedHomes: partial.declinedHomes ?? base3.declinedHomes,
4862
- homesGrandfathered: partial.homesGrandfathered ?? base3.homesGrandfathered,
4852
+ claudeHome: partial.claudeHome ?? base4.claudeHome,
4853
+ geminiHome: partial.geminiHome ?? base4.geminiHome,
4854
+ codexHome: partial.codexHome ?? base4.codexHome,
4855
+ opencodeDbPath: partial.opencodeDbPath ?? base4.opencodeDbPath,
4856
+ agyHome: partial.agyHome ?? base4.agyHome,
4857
+ cursorHome: partial.cursorHome ?? base4.cursorHome,
4858
+ cursorIdeHome: partial.cursorIdeHome ?? base4.cursorIdeHome,
4859
+ extraClaudeHomes: partial.extraClaudeHomes ?? base4.extraClaudeHomes,
4860
+ approvedHomes: partial.approvedHomes ?? base4.approvedHomes,
4861
+ declinedHomes: partial.declinedHomes ?? base4.declinedHomes,
4862
+ homesGrandfathered: partial.homesGrandfathered ?? base4.homesGrandfathered,
4863
4863
  enabled
4864
4864
  };
4865
4865
  }
4866
- function mergePrivacy(base3, partial) {
4866
+ function mergePrivacy(base4, partial) {
4867
4867
  if (!partial)
4868
- return base3;
4869
- return { ...base3, ...partial };
4868
+ return base4;
4869
+ return { ...base4, ...partial };
4870
4870
  }
4871
- function mergeSync(base3, partial) {
4871
+ function mergeSync(base4, partial) {
4872
4872
  if (!partial)
4873
- return base3;
4873
+ return base4;
4874
4874
  return {
4875
- ...base3,
4875
+ ...base4,
4876
4876
  ...partial,
4877
- upload: { ...base3.upload, ...partial.upload ?? {} }
4877
+ upload: { ...base4.upload, ...partial.upload ?? {} }
4878
4878
  };
4879
4879
  }
4880
- function mergeTeam(base3, partial) {
4880
+ function mergeTeam(base4, partial) {
4881
4881
  if (!partial)
4882
- return base3;
4882
+ return base4;
4883
4883
  return {
4884
- ...base3,
4884
+ ...base4,
4885
4885
  ...partial,
4886
- publishAllowed: { ...base3.publishAllowed, ...partial.publishAllowed ?? {} },
4887
- vault: { ...base3.vault, ...partial.vault ?? {} }
4886
+ publishAllowed: { ...base4.publishAllowed, ...partial.publishAllowed ?? {} },
4887
+ vault: { ...base4.vault, ...partial.vault ?? {} }
4888
4888
  };
4889
4889
  }
4890
4890
  function settingsFilePath() {
@@ -5002,15 +5002,15 @@ function loadSettings() {
5002
5002
  }
5003
5003
  try {
5004
5004
  const parsed = JSON.parse(readFileSync(path, "utf-8"));
5005
- const base3 = freshDefaults();
5005
+ const base4 = freshDefaults();
5006
5006
  const result = {
5007
5007
  v: SCHEMA_VERSION,
5008
- embedding: { ...base3.embedding, ...parsed.embedding ?? {} },
5009
- summary: { ...base3.summary, ...parsed.summary ?? {} },
5010
- sources: mergeSources(base3.sources, parsed.sources),
5011
- privacy: mergePrivacy(base3.privacy, parsed.privacy),
5012
- sync: mergeSync(base3.sync, parsed.sync),
5013
- team: mergeTeam(base3.team, parsed.team)
5008
+ embedding: { ...base4.embedding, ...parsed.embedding ?? {} },
5009
+ summary: { ...base4.summary, ...parsed.summary ?? {} },
5010
+ sources: mergeSources(base4.sources, parsed.sources),
5011
+ privacy: mergePrivacy(base4.privacy, parsed.privacy),
5012
+ sync: mergeSync(base4.sync, parsed.sync),
5013
+ team: mergeTeam(base4.team, parsed.team)
5014
5014
  };
5015
5015
  if (mtimeMs >= 0)
5016
5016
  _settingsCache = { mtimeMs, size, value: structuredClone(result) };
@@ -5216,10 +5216,10 @@ function legacyAutoSyncedHomes() {
5216
5216
  { base: join3(home, ".local", "share", "opencode"), marker: "opencode.db" },
5217
5217
  { base: join3(home, ".cursor"), marker: "chats" }
5218
5218
  ];
5219
- for (const { base: base3, marker } of bases) {
5220
- add(base3, marker);
5221
- const parent = dirname3(base3);
5222
- const leaf = base3.slice(parent.length + 1);
5219
+ for (const { base: base4, marker } of bases) {
5220
+ add(base4, marker);
5221
+ const parent = dirname3(base4);
5222
+ const leaf = base4.slice(parent.length + 1);
5223
5223
  try {
5224
5224
  for (const e of readdirSync2(parent, { withFileTypes: true })) {
5225
5225
  if (!e.isDirectory())
@@ -5417,17 +5417,17 @@ function cursorHomeDir() {
5417
5417
  function cursorIdeHomeDir() {
5418
5418
  return process.env.CHAT_RECALL_CURSOR_IDE_HOME || sources().cursorIdeHome || (process.platform === "darwin" ? join4(homedir3(), "Library", "Application Support", "Cursor") : join4(homedir3(), ".config", "Cursor"));
5419
5419
  }
5420
- function siblingHomes(base3, overridden, suffix) {
5420
+ function siblingHomes(base4, overridden, suffix) {
5421
5421
  const roots = [];
5422
5422
  const add = (home) => {
5423
5423
  const root = suffix ? join4(home, suffix) : home;
5424
5424
  if (existsSync4(root) && !roots.includes(root))
5425
5425
  roots.push(root);
5426
5426
  };
5427
- add(base3);
5427
+ add(base4);
5428
5428
  if (!overridden) {
5429
- const parent = dirname4(base3);
5430
- const leaf = basename(base3);
5429
+ const parent = dirname4(base4);
5430
+ const leaf = basename(base4);
5431
5431
  try {
5432
5432
  for (const entry of readdirSync3(parent, { withFileTypes: true })) {
5433
5433
  if (!entry.isDirectory())
@@ -5937,9 +5937,9 @@ async function parseSessionFile(sessionPath, maxMessages = 50) {
5937
5937
  content.metadata.durationMs += obj.durationMs;
5938
5938
  }
5939
5939
  if (msgType === "file-history-snapshot") {
5940
- const snapshot = obj.snapshot;
5941
- if (snapshot && typeof snapshot === "object") {
5942
- const backups = snapshot.trackedFileBackups;
5940
+ const snapshot2 = obj.snapshot;
5941
+ if (snapshot2 && typeof snapshot2 === "object") {
5942
+ const backups = snapshot2.trackedFileBackups;
5943
5943
  if (backups && typeof backups === "object") {
5944
5944
  for (const filePath2 of Object.keys(backups)) {
5945
5945
  filesModified.add(filePath2);
@@ -8353,7 +8353,64 @@ var init_opencode = __esm({
8353
8353
  });
8354
8354
 
8355
8355
  // ../engine/dist/core/backends/tail-read.js
8356
- import { openSync as openSync2, readSync as readSync2, closeSync as closeSync2, statSync as statSync4 } from "node:fs";
8356
+ import { openSync as openSync2, readSync as readSync2, closeSync as closeSync2, statSync as statSync4, fstatSync } from "node:fs";
8357
+ function readAt(fd, pos, len) {
8358
+ const buf = Buffer.alloc(len);
8359
+ let got = 0;
8360
+ while (got < len) {
8361
+ const n = readSync2(fd, buf, got, len - got, pos + got);
8362
+ if (n <= 0)
8363
+ break;
8364
+ got += n;
8365
+ }
8366
+ return buf.subarray(0, got);
8367
+ }
8368
+ function linesBeforeOffset(path, offset) {
8369
+ if (offset <= 0)
8370
+ return 0;
8371
+ let fd = null;
8372
+ try {
8373
+ fd = openSync2(path, "r");
8374
+ const ino = fstatSync(fd).ino;
8375
+ const known = lineCounts.get(path);
8376
+ let pos = 0;
8377
+ let lines = 0;
8378
+ if (known && known.ino === ino && known.offset <= offset) {
8379
+ const edgeStart2 = Math.max(0, known.offset - EDGE_BYTES);
8380
+ if (readAt(fd, edgeStart2, known.offset - edgeStart2).equals(known.edge)) {
8381
+ pos = known.offset;
8382
+ lines = known.lines;
8383
+ }
8384
+ }
8385
+ const block = Buffer.allocUnsafe(SKIP_SCAN_BYTES);
8386
+ while (pos < offset) {
8387
+ const n = readSync2(fd, block, 0, Math.min(SKIP_SCAN_BYTES, offset - pos), pos);
8388
+ if (n <= 0)
8389
+ return void 0;
8390
+ for (let i = block.indexOf(10, 0); i >= 0 && i < n; i = block.indexOf(10, i + 1))
8391
+ lines++;
8392
+ pos += n;
8393
+ }
8394
+ const edgeStart = Math.max(0, offset - EDGE_BYTES);
8395
+ const edge = readAt(fd, edgeStart, offset - edgeStart);
8396
+ if (lineCounts.size >= LINE_COUNT_CACHE_MAX && !lineCounts.has(path)) {
8397
+ const oldest = lineCounts.keys().next().value;
8398
+ if (oldest !== void 0)
8399
+ lineCounts.delete(oldest);
8400
+ }
8401
+ lineCounts.set(path, { offset, lines, ino, edge });
8402
+ return lines;
8403
+ } catch {
8404
+ return void 0;
8405
+ } finally {
8406
+ if (fd !== null) {
8407
+ try {
8408
+ closeSync2(fd);
8409
+ } catch {
8410
+ }
8411
+ }
8412
+ }
8413
+ }
8357
8414
  function readTailFromOffset(path, offset, maxBytes = TAIL_READ_MAX_BYTES) {
8358
8415
  let size = 0;
8359
8416
  try {
@@ -8381,7 +8438,7 @@ function readTailFromOffset(path, offset, maxBytes = TAIL_READ_MAX_BYTES) {
8381
8438
  const lastNl = slice.lastIndexOf(10);
8382
8439
  if (lastNl >= 0) {
8383
8440
  const text = slice.subarray(0, lastNl + 1).toString("utf-8");
8384
- return { text, newOffset: offset + lastNl + 1 };
8441
+ return { text, newOffset: offset + lastNl + 1, baseLine: linesBeforeOffset(path, offset) };
8385
8442
  }
8386
8443
  if (offset + got >= size)
8387
8444
  return { text: "", newOffset: offset };
@@ -8414,12 +8471,15 @@ function findNewline(fd, from, size) {
8414
8471
  }
8415
8472
  return -1;
8416
8473
  }
8417
- var TAIL_READ_MAX_BYTES, SKIP_SCAN_BYTES;
8474
+ var TAIL_READ_MAX_BYTES, SKIP_SCAN_BYTES, lineCounts, LINE_COUNT_CACHE_MAX, EDGE_BYTES;
8418
8475
  var init_tail_read = __esm({
8419
8476
  "../engine/dist/core/backends/tail-read.js"() {
8420
8477
  "use strict";
8421
8478
  TAIL_READ_MAX_BYTES = 16 * 1024 * 1024;
8422
8479
  SKIP_SCAN_BYTES = 1024 * 1024;
8480
+ lineCounts = /* @__PURE__ */ new Map();
8481
+ LINE_COUNT_CACHE_MAX = 2048;
8482
+ EDGE_BYTES = 64;
8423
8483
  }
8424
8484
  });
8425
8485
 
@@ -12776,8 +12836,8 @@ function _clearServerRulePack() {
12776
12836
  serverPack = null;
12777
12837
  }
12778
12838
  function activeRules() {
12779
- const base3 = settingsView().rules;
12780
- return serverPack && serverPack.rules.length > 0 ? [...base3, ...serverPack.rules] : base3;
12839
+ const base4 = settingsView().rules;
12840
+ return serverPack && serverPack.rules.length > 0 ? [...base4, ...serverPack.rules] : base4;
12781
12841
  }
12782
12842
  function isRedactionEnabled() {
12783
12843
  const env = isEnvRedactionRequested();
@@ -18535,7 +18595,7 @@ var init_extractor_version = __esm({
18535
18595
  });
18536
18596
 
18537
18597
  // src/sync-ledger.ts
18538
- import { readFileSync as readFileSync29, writeFileSync as writeFileSync5, renameSync as renameSync4, mkdirSync as mkdirSync6 } from "node:fs";
18598
+ import { readFileSync as readFileSync29, writeFileSync as writeFileSync5, renameSync as renameSync4, mkdirSync as mkdirSync6, statSync as statSync35 } from "node:fs";
18539
18599
  import { join as join38, dirname as dirname15 } from "node:path";
18540
18600
  function toRow(entry) {
18541
18601
  if (entry === void 0) return void 0;
@@ -18544,32 +18604,94 @@ function toRow(entry) {
18544
18604
  function ledgerFilePath() {
18545
18605
  return ledgerPath();
18546
18606
  }
18547
- function load() {
18548
- if (cache3) return cache3;
18607
+ function stampOf(path) {
18608
+ try {
18609
+ const st = statSync35(path);
18610
+ return `${st.mtimeMs}:${st.size}`;
18611
+ } catch {
18612
+ return null;
18613
+ }
18614
+ }
18615
+ function readDisk(path) {
18549
18616
  try {
18550
- const parsed = JSON.parse(readFileSync29(ledgerPath(), "utf-8"));
18551
- cache3 = parsed && typeof parsed === "object" ? parsed : {};
18617
+ const parsed = JSON.parse(readFileSync29(path, "utf-8"));
18618
+ return parsed && typeof parsed === "object" ? parsed : {};
18552
18619
  } catch {
18553
- cache3 = {};
18620
+ return {};
18621
+ }
18622
+ }
18623
+ function snapshot(data) {
18624
+ const out = /* @__PURE__ */ new Map();
18625
+ for (const [server, rows] of Object.entries(data)) {
18626
+ for (const [id, entry] of Object.entries(rows)) out.set(rowKey(server, id), JSON.stringify(entry));
18627
+ }
18628
+ return out;
18629
+ }
18630
+ function mergeOnto(disk) {
18631
+ const out = {};
18632
+ const put = (server, id, entry) => {
18633
+ (out[server] ??= {})[id] = entry;
18634
+ };
18635
+ const mine = cache3 ?? {};
18636
+ for (const [server, rows] of Object.entries(disk)) {
18637
+ for (const [id, entry] of Object.entries(rows)) {
18638
+ const k = rowKey(server, id);
18639
+ const own = mine[server]?.[id];
18640
+ const was = base.get(k);
18641
+ if (own === void 0) {
18642
+ if (was === void 0) put(server, id, entry);
18643
+ } else {
18644
+ put(server, id, JSON.stringify(own) === was ? entry : own);
18645
+ }
18646
+ }
18554
18647
  }
18648
+ for (const [server, rows] of Object.entries(mine)) {
18649
+ for (const [id, entry] of Object.entries(rows)) {
18650
+ if (disk[server]?.[id] !== void 0) continue;
18651
+ if (JSON.stringify(entry) !== base.get(rowKey(server, id))) put(server, id, entry);
18652
+ }
18653
+ }
18654
+ return out;
18655
+ }
18656
+ function load() {
18657
+ const path = ledgerPath();
18658
+ const stamp = stampOf(path);
18659
+ if (cache3 && stamp === diskStamp) return cache3;
18660
+ const disk = readDisk(path);
18661
+ const merged = cache3 ? mergeOnto(disk) : disk;
18662
+ if (cache3) {
18663
+ for (const server of Object.keys(cache3)) if (!(server in merged)) delete cache3[server];
18664
+ for (const [server, rows] of Object.entries(merged)) {
18665
+ const target = cache3[server] ?? (cache3[server] = {});
18666
+ for (const id of Object.keys(target)) if (!(id in rows)) delete target[id];
18667
+ Object.assign(target, rows);
18668
+ }
18669
+ } else {
18670
+ cache3 = merged;
18671
+ }
18672
+ base = snapshot(disk);
18673
+ diskStamp = stamp;
18555
18674
  return cache3;
18556
18675
  }
18557
- function persistNow(data) {
18676
+ function persistNow() {
18558
18677
  const path = ledgerPath();
18559
18678
  mkdirSync6(dirname15(path), { recursive: true });
18560
- const tmp = `${path}.tmp`;
18561
- writeFileSync5(tmp, JSON.stringify(data));
18679
+ load();
18680
+ const tmp = `${path}.tmp-${process.pid}`;
18681
+ writeFileSync5(tmp, JSON.stringify(cache3 ?? {}));
18562
18682
  renameSync4(tmp, path);
18683
+ base = snapshot(cache3 ?? {});
18684
+ diskStamp = stampOf(path);
18563
18685
  pendingWrite = false;
18564
18686
  }
18565
- function persist(data) {
18687
+ function persist(_data) {
18566
18688
  pendingWrite = true;
18567
18689
  if (flushTimer) return;
18568
18690
  flushTimer = setTimeout(() => {
18569
18691
  flushTimer = null;
18570
18692
  if (pendingWrite) {
18571
18693
  try {
18572
- persistNow(data);
18694
+ persistNow();
18573
18695
  } catch {
18574
18696
  }
18575
18697
  }
@@ -18603,7 +18725,7 @@ function pruneLedgerTargets(configuredServers) {
18603
18725
  }
18604
18726
  const rows = names.reduce((n, s) => n + Object.keys(orphans[s]).length, 0);
18605
18727
  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.`);
18606
- persistNow(data);
18728
+ persistNow();
18607
18729
  return names.length;
18608
18730
  }
18609
18731
  function flushLedger() {
@@ -18612,7 +18734,7 @@ function flushLedger() {
18612
18734
  flushTimer = null;
18613
18735
  }
18614
18736
  if (!pendingWrite || !cache3) return;
18615
- persistNow(cache3);
18737
+ persistNow();
18616
18738
  }
18617
18739
  function loadItemVersionsAll() {
18618
18740
  if (itemVersionsCache) return itemVersionsCache;
@@ -18672,6 +18794,7 @@ function persistLedgerData(server, serverData) {
18672
18794
  const data = load();
18673
18795
  data[server] = serverData;
18674
18796
  persist(data);
18797
+ flushLedger();
18675
18798
  }
18676
18799
  function markSynced(server, rows) {
18677
18800
  if (rows.length === 0) return;
@@ -18688,13 +18811,13 @@ function markSynced(server, rows) {
18688
18811
  const o = (cursorFromCaller ? r.offset : void 0) ?? prevOS.o ?? 0;
18689
18812
  const s = (cursorFromCaller ? r.size : void 0) ?? prevOS.s ?? 0;
18690
18813
  const ev = extractorVersionForId(r.id);
18691
- const base3 = prevF ? { m: Math.floor(r.mtime), v: ev, f: prevF } : { m: Math.floor(r.mtime), v: ev };
18814
+ const base4 = prevF ? { m: Math.floor(r.mtime), v: ev, f: prevF } : { m: Math.floor(r.mtime), v: ev };
18692
18815
  if (o > 0 || s > 0) {
18693
- base3.o = o;
18694
- base3.s = s;
18816
+ base4.o = o;
18817
+ base4.s = s;
18695
18818
  }
18696
- if (r.hash !== void 0) base3.h = r.hash;
18697
- forServer[r.id] = base3;
18819
+ if (r.hash !== void 0) base4.h = r.hash;
18820
+ forServer[r.id] = base4;
18698
18821
  }
18699
18822
  persist(data);
18700
18823
  }
@@ -18769,7 +18892,7 @@ function syncMode(row, mtime, fileSize, extractorVersion, isAppendOnly) {
18769
18892
  if (row.m >= Math.floor(mtime)) return "skip";
18770
18893
  return "full";
18771
18894
  }
18772
- var ledgerPath, cache3, LEDGER_FLUSH_MS, pendingWrite, flushTimer, itemVersionsPath, itemVersionsCache, inventoryPath, unackedCursorAttempts, reconcilePath, reconcileCache;
18895
+ var ledgerPath, cache3, base, diskStamp, rowKey, LEDGER_FLUSH_MS, pendingWrite, flushTimer, itemVersionsPath, itemVersionsCache, inventoryPath, unackedCursorAttempts, reconcilePath, reconcileCache;
18773
18896
  var init_sync_ledger = __esm({
18774
18897
  "src/sync-ledger.ts"() {
18775
18898
  "use strict";
@@ -18777,6 +18900,9 @@ var init_sync_ledger = __esm({
18777
18900
  init_extractor_version();
18778
18901
  ledgerPath = () => join38(getDataDir(), "sync-ledger.json");
18779
18902
  cache3 = null;
18903
+ base = /* @__PURE__ */ new Map();
18904
+ diskStamp = null;
18905
+ rowKey = (server, id) => `${server}\0${id}`;
18780
18906
  LEDGER_FLUSH_MS = 2e3;
18781
18907
  pendingWrite = false;
18782
18908
  flushTimer = null;
@@ -18815,7 +18941,7 @@ var init_sync_fields = __esm({
18815
18941
  });
18816
18942
 
18817
18943
  // ../engine/dist/core/index-lock.js
18818
- import { existsSync as existsSync39, mkdirSync as mkdirSync7, openSync as openSync8, writeFileSync as writeFileSync6, readFileSync as readFileSync30, rmSync as rmSync4, statSync as statSync35, closeSync as closeSync8 } from "fs";
18944
+ import { existsSync as existsSync39, mkdirSync as mkdirSync7, openSync as openSync8, writeFileSync as writeFileSync6, readFileSync as readFileSync30, rmSync as rmSync4, statSync as statSync36, closeSync as closeSync8 } from "fs";
18819
18945
  import { dirname as dirname16, join as join39 } from "path";
18820
18946
  function acquireIndexLock(opts) {
18821
18947
  const lockPath = lockFilePath(opts.file);
@@ -18865,7 +18991,7 @@ function lockFilePath(file = ".compact.lock") {
18865
18991
  }
18866
18992
  function stealStaleLock(lockPath, staleAfterMs) {
18867
18993
  try {
18868
- const s = statSync35(lockPath);
18994
+ const s = statSync36(lockPath);
18869
18995
  const age = Date.now() - s.mtimeMs;
18870
18996
  let payload;
18871
18997
  try {
@@ -18937,7 +19063,7 @@ var init_http = __esm({
18937
19063
  CLI_VERSION = JSON.parse(readFileSync31(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
18938
19064
  } catch {
18939
19065
  try {
18940
- if (true) CLI_VERSION = "0.7.14";
19066
+ if (true) CLI_VERSION = "0.7.16";
18941
19067
  } catch {
18942
19068
  }
18943
19069
  }
@@ -19435,7 +19561,7 @@ var init_telemetry = __esm({
19435
19561
  init_sync_client();
19436
19562
  cliVersion2 = () => {
19437
19563
  try {
19438
- return true ? "0.7.14" : "dev";
19564
+ return true ? "0.7.16" : "dev";
19439
19565
  } catch {
19440
19566
  return "dev";
19441
19567
  }
@@ -19611,11 +19737,11 @@ __export(server_probe_exports, {
19611
19737
  function probeOk(r) {
19612
19738
  return r.kind === "ok" && r.apiVersion >= 2;
19613
19739
  }
19614
- async function probeServer(base3, opts = {}) {
19740
+ async function probeServer(base4, opts = {}) {
19615
19741
  const f = opts.fetchImpl || fetch;
19616
19742
  let res;
19617
19743
  try {
19618
- res = await f(`${base3.replace(/\/+$/, "")}/api/capabilities`, {
19744
+ res = await f(`${base4.replace(/\/+$/, "")}/api/capabilities`, {
19619
19745
  signal: AbortSignal.timeout(opts.timeoutMs ?? 1e4)
19620
19746
  });
19621
19747
  } catch (err) {
@@ -19652,34 +19778,34 @@ async function probeServer(base3, opts = {}) {
19652
19778
  raw: parsed
19653
19779
  };
19654
19780
  }
19655
- function probeAdvice(r, base3) {
19781
+ function probeAdvice(r, base4) {
19656
19782
  switch (r.kind) {
19657
19783
  case "ok":
19658
19784
  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`;
19659
19785
  case "moved":
19660
- return `HTTP ${r.status} \u2014 nothing is served at ${base3}. If the host moved, re-point it: \`chat-recall login <new-server-url>\``;
19786
+ return `HTTP ${r.status} \u2014 nothing is served at ${base4}. If the host moved, re-point it: \`chat-recall login <new-server-url>\``;
19661
19787
  case "unauthorized":
19662
- return `HTTP ${r.status} \u2014 ${base3} rejected the credential. Re-login: \`chat-recall login ` + base3 + "`";
19788
+ return `HTTP ${r.status} \u2014 ${base4} rejected the credential. Re-login: \`chat-recall login ` + base4 + "`";
19663
19789
  case "server_error":
19664
- return `HTTP ${r.status} \u2014 ${base3} is up but failing. Nothing to fix locally; check the server.`;
19790
+ return `HTTP ${r.status} \u2014 ${base4} is up but failing. Nothing to fix locally; check the server.`;
19665
19791
  case "not_api":
19666
- 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`;
19792
+ return `${base4} 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`;
19667
19793
  case "unreachable":
19668
19794
  switch (r.reason) {
19669
19795
  case "dns":
19670
- return `cannot resolve the host in ${base3} (${r.error}) \u2014 check the URL for a typo, and your DNS or VPN`;
19796
+ return `cannot resolve the host in ${base4} (${r.error}) \u2014 check the URL for a typo, and your DNS or VPN`;
19671
19797
  case "refused":
19672
- return `${base3} resolves but refused the connection (${r.error}) \u2014 the server is not running, or the port is wrong`;
19798
+ return `${base4} resolves but refused the connection (${r.error}) \u2014 the server is not running, or the port is wrong`;
19673
19799
  case "tls":
19674
- 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.`;
19800
+ return `the TLS certificate at ${base4} was rejected (${r.error}) \u2014 expired, self-signed, or issued for another host. A corporate proxy that re-signs traffic does this.`;
19675
19801
  case "timeout":
19676
- return `${base3} did not answer in time (${r.error}) \u2014 a firewall or proxy that drops traffic silently looks exactly like this`;
19802
+ return `${base4} did not answer in time (${r.error}) \u2014 a firewall or proxy that drops traffic silently looks exactly like this`;
19677
19803
  case "reset":
19678
- return `the connection to ${base3} was cut (${r.error}) \u2014 often a proxy or a captive portal`;
19804
+ return `the connection to ${base4} was cut (${r.error}) \u2014 often a proxy or a captive portal`;
19679
19805
  case "bad_port":
19680
- 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`;
19806
+ return `${base4} names a port that Node and every browser refuse to open (the WHATWG bad-port list) \u2014 use the server's real port`;
19681
19807
  default:
19682
- return `no HTTP response from ${base3} (${r.error}) \u2014 check the URL, DNS, or that the server is running`;
19808
+ return `no HTTP response from ${base4} (${r.error}) \u2014 check the URL, DNS, or that the server is running`;
19683
19809
  }
19684
19810
  }
19685
19811
  }
@@ -19712,8 +19838,8 @@ function describeCause(err) {
19712
19838
  const code2 = e.code;
19713
19839
  if (typeof code2 === "string" && code2 && !parts.includes(code2)) parts.push(code2);
19714
19840
  }
19715
- const base3 = err instanceof Error ? err.message : String(err);
19716
- return parts.length ? `${base3}: ${parts.join(" \u2192 ")}` : base3;
19841
+ const base4 = err instanceof Error ? err.message : String(err);
19842
+ return parts.length ? `${base4}: ${parts.join(" \u2192 ")}` : base4;
19717
19843
  }
19718
19844
  function describeUnreachable(err) {
19719
19845
  const reason = classifyUnreachable(err);
@@ -19826,7 +19952,7 @@ __export(auto_update_exports, {
19826
19952
  import { execSync as execSync2, execFileSync as execFileSync3 } from "node:child_process";
19827
19953
  import { readFileSync as readFileSync34, existsSync as existsSync41 } from "node:fs";
19828
19954
  import { fileURLToPath as fileURLToPath2 } from "node:url";
19829
- import { writeFileSync as writeFileSync8, mkdtempSync as mkdtempSync3, rmSync as rmSync5, readdirSync as readdirSync30, statSync as statSync36, mkdirSync as mkdirSync9 } from "node:fs";
19955
+ import { writeFileSync as writeFileSync8, mkdtempSync as mkdtempSync3, rmSync as rmSync5, readdirSync as readdirSync30, statSync as statSync37, mkdirSync as mkdirSync9 } from "node:fs";
19830
19956
  import { join as join41, dirname as dirname18, sep as sep2, posix as pathPosix, win32 as pathWin32 } from "node:path";
19831
19957
  import { tmpdir as tmpdir2, homedir as homedir15 } from "node:os";
19832
19958
  import { createHash as createHash8 } from "node:crypto";
@@ -19858,12 +19984,12 @@ function installedVersion() {
19858
19984
  return null;
19859
19985
  }
19860
19986
  }
19861
- function planAutoUpdate(base3, caps, ownVersion3, flag) {
19987
+ function planAutoUpdate(base4, caps, ownVersion3, flag) {
19862
19988
  const rel = caps.cli;
19863
19989
  if (!rel || !rel.version || !rel.sha256) return { update: false, reason: "server advertises no CLI release" };
19864
19990
  if (!isAutoUpdateEnabled(caps.edition, flag)) return { update: false, reason: `auto-update disabled (edition ${caps.edition ?? "?"})` };
19865
19991
  if (compareVersions(rel.version, ownVersion3) <= 0) return { update: false, reason: `already current (own ${ownVersion3} >= server ${rel.version})` };
19866
- 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 };
19992
+ return { update: true, reason: `server ${rel.version} > own ${ownVersion3}`, url: tarballUrl(base4, rel.version), fallbackUrl: tarballUrl(base4), sha256: rel.sha256, from: ownVersion3, to: rel.version };
19867
19993
  }
19868
19994
  function sweepStaleStaging(root = tmpdir2(), now = Date.now()) {
19869
19995
  const MKDTEMP_SUFFIX = /^cr-update-.{6}$/s;
@@ -19879,7 +20005,7 @@ function sweepStaleStaging(root = tmpdir2(), now = Date.now()) {
19879
20005
  if (!MKDTEMP_SUFFIX.test(name)) continue;
19880
20006
  const dir = join41(root, name);
19881
20007
  try {
19882
- const st = statSync36(dir);
20008
+ const st = statSync37(dir);
19883
20009
  if (!st.isDirectory() || now - st.mtimeMs < COLD_MS) continue;
19884
20010
  const inside = readdirSync30(dir);
19885
20011
  if (inside.length > 1 || inside.length === 1 && inside[0] !== "chat-recall.tgz") continue;
@@ -20043,20 +20169,20 @@ function clearUpdateFailures() {
20043
20169
  function stopAutoUpdates() {
20044
20170
  stopRequested = true;
20045
20171
  }
20046
- async function runAutoUpdate(base3, authHeaders, ownVersion3, deps) {
20172
+ async function runAutoUpdate(base4, authHeaders, ownVersion3, deps) {
20047
20173
  let caps;
20048
20174
  try {
20049
- const res = await fetchWithTimeout(`${base3.replace(/\/+$/, "")}/api/capabilities`, { headers: authHeaders });
20175
+ const res = await fetchWithTimeout(`${base4.replace(/\/+$/, "")}/api/capabilities`, { headers: authHeaders });
20050
20176
  if (!res.ok) return { updated: false, reason: `capabilities HTTP ${res.status}` };
20051
20177
  caps = await res.json();
20052
20178
  } catch (e) {
20053
20179
  return { updated: false, reason: `capabilities unreachable: ${e instanceof Error ? e.message : e}` };
20054
20180
  }
20055
20181
  const effectiveOwn = newerOf(ownVersion3, installedVersion());
20056
- const plan = planAutoUpdate(base3, caps, effectiveOwn, process.env.CHAT_RECALL_AUTO_UPDATE);
20182
+ const plan = planAutoUpdate(base4, caps, effectiveOwn, process.env.CHAT_RECALL_AUTO_UPDATE);
20057
20183
  if (!plan.update) {
20058
- if (/disabled|no CLI release/.test(plan.reason) && !reportedStandingSkip.has(base3)) {
20059
- reportedStandingSkip.add(base3);
20184
+ if (/disabled|no CLI release/.test(plan.reason) && !reportedStandingSkip.has(base4)) {
20185
+ reportedStandingSkip.add(base4);
20060
20186
  try {
20061
20187
  const { reportClientEvent: reportClientEvent2 } = await Promise.resolve().then(() => (init_client_events(), client_events_exports));
20062
20188
  reportClientEvent2("auto_update_skipped", { message: `${plan.reason} (server offers ${caps.cli?.version ?? "?"}, this device runs ${effectiveOwn})` });
@@ -20112,7 +20238,7 @@ var init_auto_update = __esm({
20112
20238
  "use strict";
20113
20239
  init_http();
20114
20240
  init_index_lock();
20115
- tarballUrl = (base3, version2) => `${base3.replace(/\/+$/, "")}/install/${version2 ? `chat-recall-${version2}.tgz` : "chat-recall.tgz"}`;
20241
+ tarballUrl = (base4, version2) => `${base4.replace(/\/+$/, "")}/install/${version2 ? `chat-recall-${version2}.tgz` : "chat-recall.tgz"}`;
20116
20242
  GIVE_UP_AFTER = 3;
20117
20243
  reportedStandingSkip = /* @__PURE__ */ new Set();
20118
20244
  STOPPING_REASON = "not installed: this process is shutting down";
@@ -20157,7 +20283,7 @@ __export(sync_client_exports, {
20157
20283
  syncSessions: () => syncSessions
20158
20284
  });
20159
20285
  import { join as join42, dirname as dirname19, basename as basename20 } from "node:path";
20160
- 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";
20286
+ 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";
20161
20287
  import { tmpdir as tmpdir3, hostname as hostname2 } from "node:os";
20162
20288
  import { createHash as createHash9 } from "node:crypto";
20163
20289
  import { fileURLToPath as fileURLToPath3 } from "node:url";
@@ -20220,15 +20346,15 @@ function loadAllCredentials() {
20220
20346
  return [];
20221
20347
  }
20222
20348
  async function fetchTenantSecurityConfig(cred) {
20223
- const base3 = cred.serverUrl.replace(/\/+$/, "");
20224
- const cached = _securityConfigCache.get(base3);
20349
+ const base4 = cred.serverUrl.replace(/\/+$/, "");
20350
+ const cached = _securityConfigCache.get(base4);
20225
20351
  if (cached && Date.now() - cached.fetchedAt < SECURITY_CONFIG_TTL_MS) return cached.config;
20226
20352
  const headers = { "content-type": "application/json" };
20227
20353
  if (cred.token) headers.authorization = `Bearer ${cred.token}`;
20228
20354
  try {
20229
20355
  const [rulesRes, settingsRes] = await Promise.all([
20230
- fetchWithTimeout(`${base3}/api/secrets/rules`, { headers }),
20231
- fetchWithTimeout(`${base3}/api/teams/security-config`, { headers }).catch(() => null)
20356
+ fetchWithTimeout(`${base4}/api/secrets/rules`, { headers }),
20357
+ fetchWithTimeout(`${base4}/api/teams/security-config`, { headers }).catch(() => null)
20232
20358
  ]);
20233
20359
  let tenantRules = [];
20234
20360
  let rulePackVersion = null;
@@ -20253,18 +20379,18 @@ async function fetchTenantSecurityConfig(cred) {
20253
20379
  const body2 = await settingsRes.json().catch(() => ({}));
20254
20380
  if (typeof body2.verifySecrets === "boolean") verifySecrets = body2.verifySecrets;
20255
20381
  if (typeof body2.telemetry === "boolean") {
20256
- setTelemetryEligible(base3, body2.telemetry);
20382
+ setTelemetryEligible(base4, body2.telemetry);
20257
20383
  try {
20258
20384
  const prior = readCollectorHealth()?.telemetryEligible ?? {};
20259
20385
  updateCollectorHealth({
20260
- telemetryEligible: { ...prior, [base3]: { allowed: body2.telemetry, at: Date.now() } }
20386
+ telemetryEligible: { ...prior, [base4]: { allowed: body2.telemetry, at: Date.now() } }
20261
20387
  });
20262
20388
  } catch {
20263
20389
  }
20264
20390
  }
20265
20391
  }
20266
20392
  const config2 = { tenantRules, verifySecrets, rulePackVersion };
20267
- _securityConfigCache.set(base3, { fetchedAt: Date.now(), config: config2 });
20393
+ _securityConfigCache.set(base4, { fetchedAt: Date.now(), config: config2 });
20268
20394
  return config2;
20269
20395
  } catch {
20270
20396
  return { tenantRules: [], verifySecrets: true, rulePackVersion: null };
@@ -20283,18 +20409,18 @@ function readPersistedSyncConfigs() {
20283
20409
  return {};
20284
20410
  }
20285
20411
  }
20286
- function persistSyncConfig(base3, config2) {
20412
+ function persistSyncConfig(base4, config2) {
20287
20413
  try {
20288
20414
  const all = readPersistedSyncConfigs();
20289
- all[base3] = { fetchedAt: Date.now(), config: config2 };
20415
+ all[base4] = { fetchedAt: Date.now(), config: config2 };
20290
20416
  mkdirSync10(dirname19(syncConfigCachePath()), { recursive: true });
20291
20417
  writeFileSync9(syncConfigCachePath(), JSON.stringify(all, null, 2));
20292
20418
  } catch {
20293
20419
  }
20294
20420
  }
20295
20421
  async function fetchTenantSyncConfig(cred) {
20296
- const base3 = cred.serverUrl.replace(/\/+$/, "");
20297
- const cached = _syncConfigCache.get(base3);
20422
+ const base4 = cred.serverUrl.replace(/\/+$/, "");
20423
+ const cached = _syncConfigCache.get(base4);
20298
20424
  if (cached && Date.now() - cached.fetchedAt < SECURITY_CONFIG_TTL_MS) return cached.config;
20299
20425
  const headers = { "content-type": "application/json" };
20300
20426
  if (cred.token) headers.authorization = `Bearer ${cred.token}`;
@@ -20302,7 +20428,7 @@ async function fetchTenantSyncConfig(cred) {
20302
20428
  try {
20303
20429
  const sources3 = discoverSessionSources();
20304
20430
  if (sources3.length > 0) {
20305
- await fetchWithTimeout(`${base3}/api/sync-config/sources`, {
20431
+ await fetchWithTimeout(`${base4}/api/sync-config/sources`, {
20306
20432
  method: "POST",
20307
20433
  headers,
20308
20434
  body: JSON.stringify({ device: deviceLabel(), sources: sources3 })
@@ -20310,12 +20436,12 @@ async function fetchTenantSyncConfig(cred) {
20310
20436
  }
20311
20437
  } catch {
20312
20438
  }
20313
- const res = await fetchWithTimeout(`${base3}/api/sync-config`, { headers });
20439
+ const res = await fetchWithTimeout(`${base4}/api/sync-config`, { headers });
20314
20440
  if (res.status === 404) {
20315
- _syncConfigCache.set(base3, { fetchedAt: Date.now(), config: EMPTY_SYNC_CONFIG });
20441
+ _syncConfigCache.set(base4, { fetchedAt: Date.now(), config: EMPTY_SYNC_CONFIG });
20316
20442
  return EMPTY_SYNC_CONFIG;
20317
20443
  }
20318
- if (!res.ok) return lastKnownSyncConfig(base3, `HTTP ${res.status}`);
20444
+ if (!res.ok) return lastKnownSyncConfig(base4, `HTTP ${res.status}`);
20319
20445
  const body2 = await res.json().catch(() => ({}));
20320
20446
  const config2 = {
20321
20447
  excludeTools: Array.isArray(body2.excludeTools) ? body2.excludeTools.filter((t) => typeof t === "string") : [],
@@ -20352,22 +20478,22 @@ async function fetchTenantSyncConfig(cred) {
20352
20478
  if (decided > 0) console.error(`[sync] applied ${decided} folder decision(s) from the dashboard`);
20353
20479
  } catch {
20354
20480
  }
20355
- _syncConfigCache.set(base3, { fetchedAt: Date.now(), config: config2 });
20356
- persistSyncConfig(base3, config2);
20481
+ _syncConfigCache.set(base4, { fetchedAt: Date.now(), config: config2 });
20482
+ persistSyncConfig(base4, config2);
20357
20483
  return config2;
20358
20484
  } catch (err) {
20359
20485
  if (isSyncRulesRefusal(err)) throw err;
20360
- return lastKnownSyncConfig(base3, err instanceof Error ? err.message : "request failed");
20486
+ return lastKnownSyncConfig(base4, err instanceof Error ? err.message : "request failed");
20361
20487
  }
20362
20488
  }
20363
- function lastKnownSyncConfig(base3, reason) {
20364
- const remembered = _syncConfigCache.get(base3) ?? readPersistedSyncConfigs()[base3];
20489
+ function lastKnownSyncConfig(base4, reason) {
20490
+ const remembered = _syncConfigCache.get(base4) ?? readPersistedSyncConfigs()[base4];
20365
20491
  if (remembered) {
20366
20492
  console.error(`[sync] could not read server-side sync rules (${reason}) \u2014 applying the last known set from ${new Date(remembered.fetchedAt).toISOString()}`);
20367
20493
  return remembered.config;
20368
20494
  }
20369
20495
  const refusal = new Error(
20370
- `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.`
20496
+ `Cannot read the server-side sync rules from ${base4} (${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.`
20371
20497
  );
20372
20498
  refusal[SYNC_RULES_REFUSAL] = true;
20373
20499
  throw refusal;
@@ -20488,25 +20614,25 @@ async function syncSessions(opts = {}) {
20488
20614
  ${errors.join("\n ")}`);
20489
20615
  return { ...agg, perTarget };
20490
20616
  }
20491
- async function postFieldBatch(base3, token, rows) {
20617
+ async function postFieldBatch(base4, token, rows) {
20492
20618
  const headers = { "content-type": "application/json" };
20493
20619
  if (token) headers.authorization = `Bearer ${token}`;
20494
20620
  const sleep2 = (ms) => new Promise((r) => setTimeout(r, ms));
20495
20621
  for (let attempt = 0; ; attempt++) {
20496
- const res = await fetchWithTimeout(`${base3}/api/sync`, { method: "POST", headers, body: JSON.stringify({ fields: rows }) }, 6e4);
20622
+ const res = await fetchWithTimeout(`${base4}/api/sync`, { method: "POST", headers, body: JSON.stringify({ fields: rows }) }, 6e4);
20497
20623
  if (res.ok) return;
20498
20624
  const retryable = res.status === 429 || res.status >= 500;
20499
- if (!retryable || attempt >= 5) throw new Error(`${base3}: fields batch HTTP ${res.status} ${await res.text().catch(() => "")}`);
20625
+ if (!retryable || attempt >= 5) throw new Error(`${base4}: fields batch HTTP ${res.status} ${await res.text().catch(() => "")}`);
20500
20626
  const ra = Number(res.headers.get("retry-after")) || 0;
20501
20627
  await sleep2(ra > 0 ? ra * 1e3 : [500, 1500, 4e3, 8e3, 15e3][Math.min(attempt, 4)]);
20502
20628
  }
20503
20629
  }
20504
20630
  async function reconcileFieldsForTarget(cred, fullRefs, opts = {}) {
20505
- const base3 = cred.serverUrl.replace(/\/+$/, "");
20506
- const ledger = getSyncedRows(base3);
20631
+ const base4 = cred.serverUrl.replace(/\/+$/, "");
20632
+ const ledger = getSyncedRows(base4);
20507
20633
  let pushed = 0, absent = 0, scanned = 0;
20508
20634
  for (const field of SYNC_FIELDS) {
20509
- const needFull = !!opts.force || fieldNeedsFullPass(base3, field);
20635
+ const needFull = !!opts.force || fieldNeedsFullPass(base4, field);
20510
20636
  const candidates2 = needFull ? fullRefs() : opts.convRefs ?? fullRefs();
20511
20637
  const send = [];
20512
20638
  const mtimeById = /* @__PURE__ */ new Map();
@@ -20522,15 +20648,15 @@ async function reconcileFieldsForTarget(cred, fullRefs, opts = {}) {
20522
20648
  }
20523
20649
  for (let i = 0; i < send.length; i += 200) {
20524
20650
  const chunk = send.slice(i, i + 200);
20525
- await postFieldBatch(base3, cred.token, chunk);
20526
- markFieldCoverage(base3, field, chunk.map((r) => ({ id: r.session_id, present: true, mtime: mtimeById.get(r.session_id) ?? 0 })));
20651
+ await postFieldBatch(base4, cred.token, chunk);
20652
+ markFieldCoverage(base4, field, chunk.map((r) => ({ id: r.session_id, present: true, mtime: mtimeById.get(r.session_id) ?? 0 })));
20527
20653
  pushed += chunk.length;
20528
20654
  }
20529
20655
  if (absentIds.length) {
20530
- markFieldCoverage(base3, field, absentIds.map((id) => ({ id, present: false, mtime: mtimeById.get(id) ?? 0 })));
20656
+ markFieldCoverage(base4, field, absentIds.map((id) => ({ id, present: false, mtime: mtimeById.get(id) ?? 0 })));
20531
20657
  absent += absentIds.length;
20532
20658
  }
20533
- if (needFull) markFieldFullPassDone(base3, field);
20659
+ if (needFull) markFieldFullPassDone(base4, field);
20534
20660
  }
20535
20661
  return { pushed, absent, scanned };
20536
20662
  }
@@ -20568,7 +20694,7 @@ function reapStaleScanDirs(dir = tmpdir3(), maxAgeMs = 6 * 36e5, now = Date.now(
20568
20694
  if (!name.startsWith("cr-batchscan-")) continue;
20569
20695
  const p = join42(dir, name);
20570
20696
  try {
20571
- if (now - statSync37(p).mtimeMs < maxAgeMs) continue;
20697
+ if (now - statSync38(p).mtimeMs < maxAgeMs) continue;
20572
20698
  rmSync6(p, { recursive: true, force: true });
20573
20699
  reaped++;
20574
20700
  } catch {
@@ -20647,25 +20773,25 @@ function serverIngestConcurrency(serverUrl) {
20647
20773
  return advertisedIngestConc.get(serverUrl.replace(/\/$/, "")) ?? null;
20648
20774
  }
20649
20775
  async function verifyServerApi(serverUrl, minApi) {
20650
- const base3 = serverUrl.replace(/\/$/, "");
20651
- const seen = capsOk.get(base3);
20776
+ const base4 = serverUrl.replace(/\/$/, "");
20777
+ const seen = capsOk.get(base4);
20652
20778
  if (seen !== void 0 && Date.now() - seen < CAPS_TTL_MS) return true;
20653
20779
  const { probeServer: probeServer2, probeAdvice: probeAdvice2 } = await Promise.resolve().then(() => (init_server_probe(), server_probe_exports));
20654
- const probe = await probeServer2(base3, {
20780
+ const probe = await probeServer2(base4, {
20655
20781
  fetchImpl: ((url, init) => fetchWithTimeout(String(url), init ?? {}))
20656
20782
  });
20657
- if (probe.kind !== "ok") throw new Error(probeAdvice2(probe, base3));
20783
+ if (probe.kind !== "ok") throw new Error(probeAdvice2(probe, base4));
20658
20784
  const caps = probe.raw;
20659
20785
  if ((caps.apiVersion ?? 0) < minApi) {
20660
20786
  throw new Error(`server too old: apiVersion ${caps.apiVersion ?? "none"} < required ${minApi} \u2014 update the server image before syncing`);
20661
20787
  }
20662
20788
  const adv = caps.limits?.ingestConcurrencyPerTenant;
20663
20789
  if (typeof adv === "number" && Number.isFinite(adv) && adv >= 1) {
20664
- advertisedIngestConc.set(base3, Math.floor(adv));
20790
+ advertisedIngestConc.set(base4, Math.floor(adv));
20665
20791
  }
20666
- if (caps.limits?.acceptsGzipBody === true) advertisedGzipBody.add(base3);
20667
- else advertisedGzipBody.delete(base3);
20668
- capsOk.set(base3, Date.now());
20792
+ if (caps.limits?.acceptsGzipBody === true) advertisedGzipBody.add(base4);
20793
+ else advertisedGzipBody.delete(base4);
20794
+ capsOk.set(base4, Date.now());
20669
20795
  return true;
20670
20796
  }
20671
20797
  async function syncToTarget(cred, opts = {}) {
@@ -20730,7 +20856,7 @@ async function syncToTargetInScope(cred, opts = {}) {
20730
20856
  const ac = new AbortController();
20731
20857
  const timer = setTimeout(() => ac.abort(new Error(`upload timed out after ${UPLOAD_TIMEOUT_MS}ms`)), UPLOAD_TIMEOUT_MS);
20732
20858
  try {
20733
- const res = await fetch(`${base3}/api/sync`, {
20859
+ const res = await fetch(`${base4}/api/sync`, {
20734
20860
  method: "POST",
20735
20861
  // No token ⇒ no auth header: a no-auth local server (AUTH_PROVIDER=none)
20736
20862
  // accepts it as the single 'default' tenant.
@@ -20746,26 +20872,26 @@ async function syncToTargetInScope(cred, opts = {}) {
20746
20872
  acceptedUploads.set(cred.serverUrl, (acceptedUploads.get(cred.serverUrl) ?? 0) + 1);
20747
20873
  const body3 = await res.json().catch(() => ({}));
20748
20874
  if (typeof body3.telemetry === "boolean") {
20749
- setTelemetryEligible(base3, body3.telemetry);
20875
+ setTelemetryEligible(base4, body3.telemetry);
20750
20876
  try {
20751
20877
  const prior = readCollectorHealth()?.telemetryEligible ?? {};
20752
20878
  updateCollectorHealth({
20753
- telemetryEligible: { ...prior, [base3]: { allowed: body3.telemetry, at: Date.now() } }
20879
+ telemetryEligible: { ...prior, [base4]: { allowed: body3.telemetry, at: Date.now() } }
20754
20880
  });
20755
20881
  } catch {
20756
20882
  }
20757
20883
  }
20758
20884
  const adv = body3.limits?.ingestConcurrencyPerTenant;
20759
20885
  if (typeof adv === "number" && Number.isFinite(adv) && adv >= 1) {
20760
- setServerIngestConcurrency(base3, Math.floor(adv));
20886
+ setServerIngestConcurrency(base4, Math.floor(adv));
20761
20887
  }
20762
20888
  if (body3.cli && body3.cli.version) {
20763
20889
  const { planAutoUpdate: planAutoUpdate2, runAutoUpdate: runAutoUpdate2, sweepStaleStaging: sweepStaleStaging2 } = await Promise.resolve().then(() => (init_auto_update(), auto_update_exports));
20764
20890
  const authHeaders = cred.token ? { authorization: `Bearer ${cred.token}` } : {};
20765
- const plan = planAutoUpdate2(base3, { cli: body3.cli }, ownVersion, process.env.CHAT_RECALL_AUTO_UPDATE);
20891
+ const plan = planAutoUpdate2(base4, { cli: body3.cli }, ownVersion, process.env.CHAT_RECALL_AUTO_UPDATE);
20766
20892
  sweepStaleStaging2();
20767
20893
  if (plan.update) {
20768
- void runAutoUpdate2(base3, authHeaders, ownVersion).catch(() => {
20894
+ void runAutoUpdate2(base4, authHeaders, ownVersion).catch(() => {
20769
20895
  });
20770
20896
  }
20771
20897
  }
@@ -20774,7 +20900,7 @@ async function syncToTargetInScope(cred, opts = {}) {
20774
20900
  const retryable = res.status === 429 || res.status >= 500;
20775
20901
  const text = await res.text().catch(() => "");
20776
20902
  if (res.status === 401 || res.status === 403) {
20777
- throw classedError("auth", `server rejected this machine's device token (HTTP ${res.status} \u2014 revoked?). Reconnect with: chat-recall login ${base3}`);
20903
+ throw classedError("auth", `server rejected this machine's device token (HTTP ${res.status} \u2014 revoked?). Reconnect with: chat-recall login ${base4}`);
20778
20904
  }
20779
20905
  if (res.status === 402) {
20780
20906
  let detail = text;
@@ -20795,7 +20921,7 @@ async function syncToTargetInScope(cred, opts = {}) {
20795
20921
  const retryAfterS = Number(res.headers.get("retry-after"));
20796
20922
  const waitMs = res.status === 429 && retryAfterS > 0 ? retryAfterS * 1e3 : RETRY_DELAYS_MS[attempt];
20797
20923
  const why = res.status === 524 ? ` \u2014 the proxy cut the request at its time limit; the batch is too big for one request` : "";
20798
- console.error(`[sync] HTTP ${res.status} from ${base3}${why} \u2014 backing off ${Math.round(waitMs / 1e3)}s (attempt ${attempt + 1})`);
20924
+ console.error(`[sync] HTTP ${res.status} from ${base4}${why} \u2014 backing off ${Math.round(waitMs / 1e3)}s (attempt ${attempt + 1})`);
20799
20925
  await sleep2(waitMs);
20800
20926
  continue;
20801
20927
  } catch (err) {
@@ -20863,11 +20989,11 @@ async function syncToTargetInScope(cred, opts = {}) {
20863
20989
  }
20864
20990
  };
20865
20991
  };
20866
- const base3 = cred.serverUrl.replace(/\/$/, "");
20867
- const ledger = opts.useLedger ? getSyncedRows(base3) : null;
20992
+ const base4 = cred.serverUrl.replace(/\/$/, "");
20993
+ const ledger = opts.useLedger ? getSyncedRows(base4) : null;
20868
20994
  const convBatch = makeBatcher("conversations", 25, false, (rows) => {
20869
20995
  try {
20870
- markSynced(base3, rows.map((r) => {
20996
+ markSynced(base4, rows.map((r) => {
20871
20997
  const off = typeof r.from_offset === "number" ? r.from_offset : 0;
20872
20998
  const hash = shippedHash.get(r.session_id);
20873
20999
  return off > 0 ? { id: r.session_id, mtime: r.mtime, offset: off, size: off, hash, acked: true } : { id: r.session_id, mtime: r.mtime, hash };
@@ -20882,7 +21008,7 @@ async function syncToTargetInScope(cred, opts = {}) {
20882
21008
  const ac = new AbortController();
20883
21009
  const timer = setTimeout(() => ac.abort(new Error(`upload timed out after ${UPLOAD_TIMEOUT_MS}ms`)), UPLOAD_TIMEOUT_MS);
20884
21010
  try {
20885
- const res = await fetch(`${base3}/api/sync`, {
21011
+ const res = await fetch(`${base4}/api/sync`, {
20886
21012
  method: "POST",
20887
21013
  headers,
20888
21014
  body: JSON.stringify({ conversations: convs }),
@@ -20893,10 +21019,10 @@ async function syncToTargetInScope(cred, opts = {}) {
20893
21019
  if (body2.cli && body2.cli.version) {
20894
21020
  const { planAutoUpdate: planAutoUpdate2, runAutoUpdate: runAutoUpdate2, sweepStaleStaging: sweepStaleStaging2 } = await Promise.resolve().then(() => (init_auto_update(), auto_update_exports));
20895
21021
  const authHeaders = cred.token ? { authorization: `Bearer ${cred.token}` } : {};
20896
- const plan = planAutoUpdate2(base3, { cli: body2.cli }, ownVersion, process.env.CHAT_RECALL_AUTO_UPDATE);
21022
+ const plan = planAutoUpdate2(base4, { cli: body2.cli }, ownVersion, process.env.CHAT_RECALL_AUTO_UPDATE);
20897
21023
  sweepStaleStaging2();
20898
21024
  if (plan.update) {
20899
- void runAutoUpdate2(base3, authHeaders, ownVersion).catch(() => {
21025
+ void runAutoUpdate2(base4, authHeaders, ownVersion).catch(() => {
20900
21026
  });
20901
21027
  }
20902
21028
  }
@@ -20904,7 +21030,7 @@ async function syncToTargetInScope(cred, opts = {}) {
20904
21030
  const acked = convs.filter((c) => !fullNeeded.has(c.session_id));
20905
21031
  if (acked.length > 0) {
20906
21032
  try {
20907
- markSynced(base3, acked.map((c) => ({
21033
+ markSynced(base4, acked.map((c) => ({
20908
21034
  id: c.session_id,
20909
21035
  mtime: c.mtime,
20910
21036
  offset: c.from_offset,
@@ -20922,13 +21048,14 @@ async function syncToTargetInScope(cred, opts = {}) {
20922
21048
  clearTimeout(timer);
20923
21049
  }
20924
21050
  };
20925
- const postChunkedHead = async (conv, fileSize) => {
21051
+ const postChunkedHead = async (head, fileSize) => {
21052
+ const conv = { ...head, chunk_head: true };
20926
21053
  const headers = { "content-type": "application/json" };
20927
21054
  if (cred.token) headers.authorization = `Bearer ${cred.token}`;
20928
21055
  const ac = new AbortController();
20929
21056
  const timer = setTimeout(() => ac.abort(new Error(`upload timed out after ${UPLOAD_TIMEOUT_MS}ms`)), UPLOAD_TIMEOUT_MS);
20930
21057
  try {
20931
- const res = await fetch(`${base3}/api/sync`, {
21058
+ const res = await fetch(`${base4}/api/sync`, {
20932
21059
  method: "POST",
20933
21060
  headers,
20934
21061
  body: JSON.stringify({ conversations: [conv] }),
@@ -20938,14 +21065,15 @@ async function syncToTargetInScope(cred, opts = {}) {
20938
21065
  const body2 = await res.json().catch(() => ({}));
20939
21066
  const id = conv.session_id;
20940
21067
  const guarded = (body2.shrink_guarded ?? []).find((g) => g.session_id === id);
21068
+ const staged = (body2.rebuild_staged ?? []).includes(id);
20941
21069
  const mtime = conv.mtime;
20942
21070
  try {
20943
- if (!guarded) {
20944
- markSynced(base3, [{ id, mtime, offset: conv.from_offset, size: conv.from_offset, acked: true }]);
21071
+ if (staged || !guarded) {
21072
+ markSynced(base4, [{ id, mtime, offset: conv.from_offset, size: conv.from_offset, acked: true }]);
20945
21073
  } else if (typeof guarded.o === "number" && guarded.o > 0 && guarded.o <= fileSize) {
20946
- markSynced(base3, [{ id, mtime, offset: guarded.o, size: guarded.o, acked: true }]);
21074
+ markSynced(base4, [{ id, mtime, offset: guarded.o, size: guarded.o, acked: true }]);
20947
21075
  } else {
20948
- markSynced(base3, [{ id, mtime }]);
21076
+ markSynced(base4, [{ id, mtime }]);
20949
21077
  }
20950
21078
  } catch {
20951
21079
  }
@@ -21011,7 +21139,7 @@ async function syncToTargetInScope(cred, opts = {}) {
21011
21139
  const m = process.memoryUsage();
21012
21140
  console.error(`[sync-trace] ${msg} \xB7 heap=${(m.heapUsed / 1048576).toFixed(0)}MB rss=${(m.rss / 1048576).toFixed(0)}MB`);
21013
21141
  } : null;
21014
- trace?.(`walk start: ${slice.length} ref(s) \u2192 ${base3}`);
21142
+ trace?.(`walk start: ${slice.length} ref(s) \u2192 ${base4}`);
21015
21143
  if (upload.sessionMeta) {
21016
21144
  try {
21017
21145
  await reconcileFieldsForTarget(
@@ -21026,7 +21154,7 @@ async function syncToTargetInScope(cred, opts = {}) {
21026
21154
  { convRefs: slice }
21027
21155
  );
21028
21156
  } catch (e) {
21029
- console.error(`[sync] field reconcile (${base3}): ${e instanceof Error ? e.message : e}`);
21157
+ console.error(`[sync] field reconcile (${base4}): ${e instanceof Error ? e.message : e}`);
21030
21158
  }
21031
21159
  }
21032
21160
  trace?.("field reconcile done");
@@ -21068,7 +21196,7 @@ async function syncToTargetInScope(cred, opts = {}) {
21068
21196
  }
21069
21197
  trace?.("conversation walk start");
21070
21198
  const walkStartedAt = Date.now();
21071
- const firstWalk = (ledger ?? getSyncedRows(base3)).size === 0;
21199
+ const firstWalk = (ledger ?? getSyncedRows(base4)).size === 0;
21072
21200
  reportWalkProgress({ done: 0, total: slice.length, startedAt: walkStartedAt, complete: false, first: firstWalk });
21073
21201
  walkProgressForUpload = { done: 0, total: slice.length, complete: false };
21074
21202
  let traceN = 0;
@@ -21108,7 +21236,7 @@ async function syncToTargetInScope(cred, opts = {}) {
21108
21236
  continue;
21109
21237
  } else {
21110
21238
  try {
21111
- markSynced(base3, [{ id: ref.prefixedId, mtime: ref.mtime }]);
21239
+ markSynced(base4, [{ id: ref.prefixedId, mtime: ref.mtime }]);
21112
21240
  } catch {
21113
21241
  }
21114
21242
  skipped++;
@@ -21131,7 +21259,7 @@ async function syncToTargetInScope(cred, opts = {}) {
21131
21259
  const off = getBackendForId(ref.prefixedId)?.fileSize?.(ref.rawId) ?? 0;
21132
21260
  const priorCursor = ackRow?.s ?? 0;
21133
21261
  const safeToAck = off > 0 && off <= priorCursor;
21134
- 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 }]);
21262
+ markSynced(base4, [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 }]);
21135
21263
  } catch {
21136
21264
  }
21137
21265
  }
@@ -21141,7 +21269,7 @@ async function syncToTargetInScope(cred, opts = {}) {
21141
21269
  if (!built) {
21142
21270
  if (ledger) {
21143
21271
  try {
21144
- markSynced(base3, [{ id: ref.prefixedId, mtime: ref.mtime }]);
21272
+ markSynced(base4, [{ id: ref.prefixedId, mtime: ref.mtime }]);
21145
21273
  } catch {
21146
21274
  }
21147
21275
  }
@@ -21198,7 +21326,7 @@ async function syncToTargetInScope(cred, opts = {}) {
21198
21326
  walked++;
21199
21327
  if (walked % 250 === 0) console.error(`[sync] ${walked}/${slice.length} sessions\u2026`);
21200
21328
  }
21201
- const itemVersions = loadItemVersions(base3);
21329
+ const itemVersions = loadItemVersions(base4);
21202
21330
  const seenTools = /* @__PURE__ */ new Set();
21203
21331
  const seenItemKeys = /* @__PURE__ */ new Map();
21204
21332
  const registry = buildSourceRegistry();
@@ -21292,7 +21420,7 @@ async function syncToTargetInScope(cred, opts = {}) {
21292
21420
  await appendFlush();
21293
21421
  for (const id of appendResults.fullResyncNeeded) {
21294
21422
  try {
21295
- markFullResync(base3, id);
21423
+ markFullResync(base4, id);
21296
21424
  } catch {
21297
21425
  }
21298
21426
  }
@@ -21305,7 +21433,7 @@ async function syncToTargetInScope(cred, opts = {}) {
21305
21433
  await findingsBatch.drain();
21306
21434
  await drainInflight();
21307
21435
  {
21308
- const sentHashes = loadInventoryHashes(base3);
21436
+ const sentHashes = loadInventoryHashes(base4);
21309
21437
  const entries = [];
21310
21438
  const hashes = {};
21311
21439
  for (const [sourceType, ids] of inventory) {
@@ -21319,7 +21447,7 @@ async function syncToTargetInScope(cred, opts = {}) {
21319
21447
  if (entries.length > 0) {
21320
21448
  try {
21321
21449
  await post({ inventory: entries });
21322
- saveInventoryHashes(base3, hashes);
21450
+ saveInventoryHashes(base4, hashes);
21323
21451
  } catch (err) {
21324
21452
  console.error(`[sync] toolkit inventory not sent (it is retried next sync): ${err instanceof Error ? err.message : err}`);
21325
21453
  }
@@ -21330,7 +21458,7 @@ async function syncToTargetInScope(cred, opts = {}) {
21330
21458
  const rec = {};
21331
21459
  for (const t of seenTools) rec[t] = extractorVersionForTool(t);
21332
21460
  for (const [k, v] of seenItemKeys) rec[k] = v;
21333
- saveItemVersions(base3, rec);
21461
+ saveItemVersions(base4, rec);
21334
21462
  } catch {
21335
21463
  }
21336
21464
  }
@@ -21343,9 +21471,9 @@ async function syncToTargetInScope(cred, opts = {}) {
21343
21471
  }
21344
21472
  if (tombstones.length > 0) {
21345
21473
  await post({ tombstones });
21346
- const data = getLedgerData(base3);
21474
+ const data = getLedgerData(base4);
21347
21475
  for (const t of tombstones) delete data[t.session_id];
21348
- persistLedgerData(base3, data);
21476
+ persistLedgerData(base4, data);
21349
21477
  }
21350
21478
  }
21351
21479
  if (opts.prune) await post({ prune_empty_sessions: true });
@@ -21673,8 +21801,13 @@ async function buildConversationTail(ref, fromOffset, opts = {}) {
21673
21801
  const backend = getBackendForId(ref.prefixedId);
21674
21802
  if (!backend?.readFromOffset) return null;
21675
21803
  const mapPath = opts.mapPath ?? ((p) => p);
21676
- const { text: tailText, newOffset, skippedBytes } = await backend.readFromOffset(ref.prefixedId, fromOffset, SYNC_CHUNK_BYTES);
21804
+ const { text: tailText, newOffset, skippedBytes, baseLine } = await backend.readFromOffset(ref.prefixedId, fromOffset, SYNC_CHUNK_BYTES);
21677
21805
  if (newOffset <= fromOffset) return null;
21806
+ const fileSize = backend.fileSize?.(ref.prefixedId) ?? 0;
21807
+ const position = {
21808
+ ...typeof baseLine === "number" ? { base_line: baseLine } : {},
21809
+ final: fileSize > 0 && newOffset >= fileSize
21810
+ };
21678
21811
  const messages = skippedBytes ? [] : parseTailMessages(ref.toolId, tailText);
21679
21812
  const textMessages = messages.filter((m) => m.role !== "summary" && m.content?.trim());
21680
21813
  const hasContent = textMessages.length > 0 || messages.some((m) => m.toolCalls?.length);
@@ -21687,6 +21820,7 @@ async function buildConversationTail(ref, fromOffset, opts = {}) {
21687
21820
  append: true,
21688
21821
  base_offset: fromOffset,
21689
21822
  from_offset: newOffset,
21823
+ ...position,
21690
21824
  redacted_text: "",
21691
21825
  envelope: { v: TRANSCRIPT_VERSION, messages: [], subagents: [] },
21692
21826
  mtime: Math.floor(ref.mtime) || 0
@@ -21733,6 +21867,7 @@ async function buildConversationTail(ref, fromOffset, opts = {}) {
21733
21867
  // equals its stored synced-through offset.
21734
21868
  from_offset: newOffset,
21735
21869
  // where it ends → new synced-through offset.
21870
+ ...position,
21736
21871
  redacted_text: redactedText,
21737
21872
  envelope,
21738
21873
  mtime: Math.floor(ref.mtime) || 0
@@ -21816,7 +21951,7 @@ var init_sync_client = __esm({
21816
21951
  ownVersion = JSON.parse(readFileSync35(join42(dir, "../package.json"), "utf-8")).version || ownVersion;
21817
21952
  } catch {
21818
21953
  try {
21819
- if (true) ownVersion = "0.7.14";
21954
+ if (true) ownVersion = "0.7.16";
21820
21955
  } catch {
21821
21956
  }
21822
21957
  }
@@ -21910,9 +22045,9 @@ async function refreshUpdateCheck(force = false) {
21910
22045
  const { loadAllCredentials: loadAllCredentials2 } = await Promise.resolve().then(() => (init_sync_client(), sync_client_exports));
21911
22046
  for (const cred of loadAllCredentials2()) {
21912
22047
  if (!cred.serverUrl) continue;
21913
- const base3 = cred.serverUrl.replace(/\/+$/, "");
22048
+ const base4 = cred.serverUrl.replace(/\/+$/, "");
21914
22049
  try {
21915
- const res = await fetchWithTimeout(`${base3}/api/capabilities`, {
22050
+ const res = await fetchWithTimeout(`${base4}/api/capabilities`, {
21916
22051
  headers: cred.token ? { authorization: `Bearer ${cred.token}` } : {}
21917
22052
  }, 5e3);
21918
22053
  if (!res.ok) continue;
@@ -21967,11 +22102,11 @@ var init_update_notice = __esm({
21967
22102
  });
21968
22103
 
21969
22104
  // ../engine/dist/core/which.js
21970
- import { existsSync as existsSync42, statSync as statSync38, accessSync, constants } from "node:fs";
22105
+ import { existsSync as existsSync42, statSync as statSync39, accessSync, constants } from "node:fs";
21971
22106
  import { join as join44, isAbsolute as isAbsolute2, delimiter as delimiter2, sep as sep3 } from "node:path";
21972
22107
  function executable(p) {
21973
22108
  try {
21974
- if (!statSync38(p).isFile())
22109
+ if (!statSync39(p).isFile())
21975
22110
  return false;
21976
22111
  } catch {
21977
22112
  return false;
@@ -22300,7 +22435,7 @@ __export(companions_exports, {
22300
22435
  uninstallCodeindex: () => uninstallCodeindex,
22301
22436
  unregisterCodeindexMcp: () => unregisterCodeindexMcp
22302
22437
  });
22303
- import { existsSync as existsSync45, mkdirSync as mkdirSync13, statSync as statSync39, chmodSync as chmodSync4, unlinkSync as unlinkSync3, renameSync as renameSync5, createWriteStream, readFileSync as readFileSync38, writeFileSync as writeFileSync13 } from "node:fs";
22438
+ import { existsSync as existsSync45, mkdirSync as mkdirSync13, statSync as statSync40, chmodSync as chmodSync4, unlinkSync as unlinkSync3, renameSync as renameSync5, createWriteStream, readFileSync as readFileSync38, writeFileSync as writeFileSync13 } from "node:fs";
22304
22439
  import { homedir as homedir17 } from "node:os";
22305
22440
  import { join as join47 } from "node:path";
22306
22441
  import { execSync as execSync3 } from "node:child_process";
@@ -22351,7 +22486,7 @@ function checkCodeindexStatus() {
22351
22486
  status.installed = true;
22352
22487
  status.path = foundPath;
22353
22488
  try {
22354
- status.size = statSync39(foundPath).size;
22489
+ status.size = statSync40(foundPath).size;
22355
22490
  } catch {
22356
22491
  }
22357
22492
  try {
@@ -22501,7 +22636,7 @@ __export(install_skills_exports, {
22501
22636
  skillsSourceDir: () => skillsSourceDir,
22502
22637
  uninstallSkills: () => uninstallSkills
22503
22638
  });
22504
- import { readdirSync as readdirSync32, existsSync as existsSync46, mkdirSync as mkdirSync14, rmSync as rmSync7, cpSync, writeFileSync as writeFileSync14, readFileSync as readFileSync39, statSync as statSync40, realpathSync as realpathSync4 } from "fs";
22639
+ import { readdirSync as readdirSync32, existsSync as existsSync46, mkdirSync as mkdirSync14, rmSync as rmSync7, cpSync, writeFileSync as writeFileSync14, readFileSync as readFileSync39, statSync as statSync41, realpathSync as realpathSync4 } from "fs";
22505
22640
  import { createHash as createHash11 } from "crypto";
22506
22641
  import { join as join48, basename as basename21 } from "path";
22507
22642
  function skillsSourceDir() {
@@ -22720,10 +22855,10 @@ function parseAgentText(content, format, fallbackName) {
22720
22855
  return { name: fm.name || fallbackName, description: fm.description || "", tools: fm.tools, body: body2.trim() };
22721
22856
  }
22722
22857
  function readCommand(filePath, format) {
22723
- return parseCommandText(readFileSync40(filePath, "utf-8"), format, base(filePath));
22858
+ return parseCommandText(readFileSync40(filePath, "utf-8"), format, base2(filePath));
22724
22859
  }
22725
22860
  function readAgent(filePath, format) {
22726
- return parseAgentText(readFileSync40(filePath, "utf-8"), format, base(filePath));
22861
+ return parseAgentText(readFileSync40(filePath, "utf-8"), format, base2(filePath));
22727
22862
  }
22728
22863
  function readInstructions(filePath, name) {
22729
22864
  const content = readFileSync40(filePath, "utf-8");
@@ -22823,7 +22958,7 @@ function emit(type, art, toTool, projectPath) {
22823
22958
  content: stringifyFrontmatter({ name: art.name, description: art.description, ...art.tools ? { tools: art.tools } : {} }, art.body)
22824
22959
  };
22825
22960
  }
22826
- function base(filePath) {
22961
+ function base2(filePath) {
22827
22962
  return basename22(filePath).replace(/\.(md|toml)$/, "");
22828
22963
  }
22829
22964
  var init_artifact_codec = __esm({
@@ -23308,11 +23443,11 @@ __export(toolkit_pull_exports, {
23308
23443
  platformRefusal: () => platformRefusal,
23309
23444
  portableCommand: () => portableCommand
23310
23445
  });
23311
- import { existsSync as existsSync48, mkdirSync as mkdirSync16, statSync as statSync41, writeFileSync as writeFileSync16 } from "node:fs";
23446
+ import { existsSync as existsSync48, mkdirSync as mkdirSync16, statSync as statSync42, writeFileSync as writeFileSync16 } from "node:fs";
23312
23447
  import { dirname as dirname23, join as join51, basename as basename24, isAbsolute as isAbsolute3 } from "node:path";
23313
23448
  function isExecutableFile(p) {
23314
23449
  try {
23315
- return statSync41(p).isFile();
23450
+ return statSync42(p).isFile();
23316
23451
  } catch {
23317
23452
  return false;
23318
23453
  }
@@ -23326,9 +23461,9 @@ function portableCommand(cmd) {
23326
23461
  }
23327
23462
  if (isExecutableFile(cmd))
23328
23463
  return { command: cmd, rewritten: false };
23329
- const base3 = basename24(cmd);
23330
- if (onPath(base3))
23331
- return { command: base3, rewritten: true };
23464
+ const base4 = basename24(cmd);
23465
+ if (onPath(base4))
23466
+ return { command: base4, rewritten: true };
23332
23467
  return { missing: cmd };
23333
23468
  }
23334
23469
  function entryFromSpec(spec) {
@@ -24162,8 +24297,8 @@ import { homedir as homedir20 } from "os";
24162
24297
  import { join as join53 } from "path";
24163
24298
  function opencodeConfigDir() {
24164
24299
  const xdg = process.env.XDG_CONFIG_HOME;
24165
- const base3 = xdg && xdg.trim() ? xdg : join53(homedir20(), ".config");
24166
- return join53(base3, "opencode");
24300
+ const base4 = xdg && xdg.trim() ? xdg : join53(homedir20(), ".config");
24301
+ return join53(base4, "opencode");
24167
24302
  }
24168
24303
  function opencodePluginDir() {
24169
24304
  return join53(opencodeConfigDir(), "plugins");
@@ -24750,17 +24885,17 @@ async function collectCode(opts) {
24750
24885
  return r;
24751
24886
  };
24752
24887
  log6(`indexing ${ws} + analyses \u2026`);
24753
- const base3 = await runMcp(bin, ws, [
24888
+ const base4 = await runMcp(bin, ws, [
24754
24889
  call(1, "index_workspace", { path: ws }),
24755
24890
  call(2, "status"),
24756
24891
  call(3, "get_tree"),
24757
24892
  ...ANALYSES.map((a, i) => call(10 + i, "analyze", { analysis: a }))
24758
24893
  ]);
24759
- const st = parseJson(base3, 2, {});
24760
- const tree = parseJson(base3, 3, []);
24894
+ const st = parseJson(base4, 2, {});
24895
+ const tree = parseJson(base4, 3, []);
24761
24896
  const A = {};
24762
24897
  ANALYSES.forEach((a, i) => {
24763
- A[a] = parseJson(base3, 10 + i, {});
24898
+ A[a] = parseJson(base4, 10 + i, {});
24764
24899
  });
24765
24900
  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;
24766
24901
  if (tree.length === 0) {
@@ -25589,7 +25724,7 @@ __export(project_tasks_exports, {
25589
25724
  pushProjectTaskStatuses: () => pushProjectTaskStatuses,
25590
25725
  renderTeamTasksMd: () => renderTeamTasksMd
25591
25726
  });
25592
- import { existsSync as existsSync51, readFileSync as readFileSync44, writeFileSync as writeFileSync18, mkdirSync as mkdirSync18, statSync as statSync42 } from "node:fs";
25727
+ import { existsSync as existsSync51, readFileSync as readFileSync44, writeFileSync as writeFileSync18, mkdirSync as mkdirSync18, statSync as statSync43 } from "node:fs";
25593
25728
  import { join as join55, dirname as dirname25 } from "node:path";
25594
25729
  import { homedir as homedir21 } from "node:os";
25595
25730
  function isTeamTaskStatus(v) {
@@ -25660,14 +25795,14 @@ function writeLedger(l) {
25660
25795
  } catch {
25661
25796
  }
25662
25797
  }
25663
- async function pushProjectTaskStatuses(base3, authHeaders, opts = {}) {
25798
+ async function pushProjectTaskStatuses(base4, authHeaders, opts = {}) {
25664
25799
  const out = { files: 0, pushedTasks: 0 };
25665
25800
  const ledger = readLedger();
25666
25801
  let ledgerDirty = false;
25667
25802
  for (const fk of FILE_KINDS) {
25668
25803
  let projects;
25669
25804
  try {
25670
- const res = await fetchWithTimeout(`${base3}${fk.trackedPath}`, { headers: authHeaders });
25805
+ const res = await fetchWithTimeout(`${base4}${fk.trackedPath}`, { headers: authHeaders });
25671
25806
  if (!res.ok) continue;
25672
25807
  projects = (await res.json()).projects || [];
25673
25808
  } catch {
@@ -25678,7 +25813,7 @@ async function pushProjectTaskStatuses(base3, authHeaders, opts = {}) {
25678
25813
  if (!existsSync51(file)) continue;
25679
25814
  let mtime;
25680
25815
  try {
25681
- mtime = statSync42(file).mtimeMs;
25816
+ mtime = statSync43(file).mtimeMs;
25682
25817
  } catch {
25683
25818
  continue;
25684
25819
  }
@@ -25695,7 +25830,7 @@ async function pushProjectTaskStatuses(base3, authHeaders, opts = {}) {
25695
25830
  continue;
25696
25831
  }
25697
25832
  try {
25698
- const res = await fetchWithTimeout(`${base3}${fk.statusPath}`, {
25833
+ const res = await fetchWithTimeout(`${base4}${fk.statusPath}`, {
25699
25834
  method: "POST",
25700
25835
  headers: { "content-type": "application/json", ...authHeaders },
25701
25836
  body: JSON.stringify({ project, items: changed.map((t) => ({ id: t.id, status: t.intent })) })
@@ -25821,16 +25956,16 @@ ${block}`);
25821
25956
  return { status: "error", result: JSON.stringify({ error: e instanceof Error ? e.message : "failed" }) };
25822
25957
  }
25823
25958
  }
25824
- async function runPull(base3, opts) {
25959
+ async function runPull(base4, opts) {
25825
25960
  const { executePull: executePull2 } = await Promise.resolve().then(() => (init_toolkit_pull(), toolkit_pull_exports));
25826
25961
  const { hostname: hostname3 } = await import("node:os");
25827
- const creds = loadAllCredentials().find((c) => c.serverUrl.replace(/\/+$/, "") === base3.replace(/\/+$/, ""));
25962
+ const creds = loadAllCredentials().find((c) => c.serverUrl.replace(/\/+$/, "") === base4.replace(/\/+$/, ""));
25828
25963
  const headers = creds?.token ? { authorization: `Bearer ${creds.token}` } : {};
25829
25964
  const wanted = opts.types?.length ? opts.types : ["mcp", "skill", "command", "agent", "instructions"];
25830
25965
  const rows = [];
25831
25966
  for (const type of wanted) {
25832
25967
  try {
25833
- const res = await fetchWithTimeout(`${base3}/api/toolkit/browse/${type}?limit=1000`, { headers });
25968
+ const res = await fetchWithTimeout(`${base4}/api/toolkit/browse/${type}?limit=1000`, { headers });
25834
25969
  if (!res.ok) continue;
25835
25970
  const body2 = await res.json();
25836
25971
  for (const it of body2.items || []) rows.push(it);
@@ -25899,20 +26034,20 @@ async function runIntent(intent, ctx) {
25899
26034
  async function drainSyncIntents(opts = {}) {
25900
26035
  const out = { processed: 0, done: 0, errored: 0 };
25901
26036
  for (const cred of loadAllCredentials()) {
25902
- const base3 = cred.serverUrl.replace(/\/+$/, "");
26037
+ const base4 = cred.serverUrl.replace(/\/+$/, "");
25903
26038
  const authHeaders = cred.token ? { authorization: `Bearer ${cred.token}` } : {};
25904
26039
  let pending;
25905
26040
  try {
25906
- const res = await fetchWithTimeout(`${base3}/api/sync-intents/pending`, { headers: authHeaders });
26041
+ const res = await fetchWithTimeout(`${base4}/api/sync-intents/pending`, { headers: authHeaders });
25907
26042
  if (!res.ok) continue;
25908
26043
  const data = await res.json();
25909
26044
  pending = data.intents || [];
25910
26045
  if (data.cli && data.cli.version) {
25911
26046
  const { planAutoUpdate: planAutoUpdate2, runAutoUpdate: runAutoUpdate2, sweepStaleStaging: sweepStaleStaging2 } = await Promise.resolve().then(() => (init_auto_update(), auto_update_exports));
25912
- const plan = planAutoUpdate2(base3, { cli: data.cli }, ownVersion2, process.env.CHAT_RECALL_AUTO_UPDATE);
26047
+ const plan = planAutoUpdate2(base4, { cli: data.cli }, ownVersion2, process.env.CHAT_RECALL_AUTO_UPDATE);
25913
26048
  sweepStaleStaging2();
25914
26049
  if (plan.update) {
25915
- void runAutoUpdate2(base3, authHeaders, ownVersion2).catch(() => {
26050
+ void runAutoUpdate2(base4, authHeaders, ownVersion2).catch(() => {
25916
26051
  });
25917
26052
  }
25918
26053
  }
@@ -25920,7 +26055,7 @@ async function drainSyncIntents(opts = {}) {
25920
26055
  continue;
25921
26056
  }
25922
26057
  for (const intent of pending) {
25923
- const { status, result } = await runIntent(intent, { base: base3 });
26058
+ const { status, result } = await runIntent(intent, { base: base4 });
25924
26059
  out.processed++;
25925
26060
  if (status === "done") out.done++;
25926
26061
  else out.errored++;
@@ -25929,7 +26064,7 @@ async function drainSyncIntents(opts = {}) {
25929
26064
  console.error(`[sync-intent] ${label}: ${status}`);
25930
26065
  }
25931
26066
  try {
25932
- await fetchWithTimeout(`${base3}/api/sync-intents/${intent.id}/ack`, {
26067
+ await fetchWithTimeout(`${base4}/api/sync-intents/${intent.id}/ack`, {
25933
26068
  method: "POST",
25934
26069
  headers: { "content-type": "application/json", ...authHeaders },
25935
26070
  body: JSON.stringify({ status, result })
@@ -25938,7 +26073,7 @@ async function drainSyncIntents(opts = {}) {
25938
26073
  }
25939
26074
  }
25940
26075
  try {
25941
- await pushProjectTaskStatuses(base3, authHeaders, { verbose: opts.verbose });
26076
+ await pushProjectTaskStatuses(base4, authHeaders, { verbose: opts.verbose });
25942
26077
  } catch {
25943
26078
  }
25944
26079
  }
@@ -25978,7 +26113,7 @@ var init_intent_drain = __esm({
25978
26113
  ownVersion2 = JSON.parse(readFileSync45(join56(dir, "../package.json"), "utf-8")).version || ownVersion2;
25979
26114
  } catch {
25980
26115
  try {
25981
- if (true) ownVersion2 = "0.7.14";
26116
+ if (true) ownVersion2 = "0.7.16";
25982
26117
  } catch {
25983
26118
  }
25984
26119
  }
@@ -26179,7 +26314,7 @@ var team_merge_exports = {};
26179
26314
  __export(team_merge_exports, {
26180
26315
  mergePullResult: () => mergePullResult
26181
26316
  });
26182
- import { existsSync as existsSync53, mkdirSync as mkdirSync20, readFileSync as readFileSync46, rmSync as rmSync8, writeFileSync as writeFileSync20, statSync as statSync43 } from "fs";
26317
+ import { existsSync as existsSync53, mkdirSync as mkdirSync20, readFileSync as readFileSync46, rmSync as rmSync8, writeFileSync as writeFileSync20, statSync as statSync44 } from "fs";
26183
26318
  import { dirname as dirname27, join as join57 } from "path";
26184
26319
  import { createHash as createHash14 } from "crypto";
26185
26320
  function installPathFor(art, tool) {
@@ -26316,7 +26451,7 @@ function readFileIfExists(path) {
26316
26451
  try {
26317
26452
  if (!existsSync53(path))
26318
26453
  return null;
26319
- const s = statSync43(path);
26454
+ const s = statSync44(path);
26320
26455
  if (!s.isFile())
26321
26456
  return null;
26322
26457
  return readFileSync46(path);
@@ -26400,7 +26535,7 @@ var init_vault_crypto = __esm({
26400
26535
  });
26401
26536
 
26402
26537
  // ../engine/dist/core/vault-source.js
26403
- import { existsSync as existsSync54, readdirSync as readdirSync33, statSync as statSync44 } from "fs";
26538
+ import { existsSync as existsSync54, readdirSync as readdirSync33, statSync as statSync45 } from "fs";
26404
26539
  import { extname, join as join58 } from "path";
26405
26540
  function* walkVaultSources() {
26406
26541
  const t = loadSettings().team.vault;
@@ -26416,7 +26551,7 @@ function* walkVaultSources() {
26416
26551
  }
26417
26552
  function safeStat(path) {
26418
26553
  try {
26419
- const s = statSync44(path);
26554
+ const s = statSync45(path);
26420
26555
  if (!s.isFile())
26421
26556
  return null;
26422
26557
  return { mtimeMs: s.mtimeMs, size: s.size };
@@ -26501,8 +26636,8 @@ function* walkCodex() {
26501
26636
  const s = safeStat(path);
26502
26637
  if (!s)
26503
26638
  continue;
26504
- const base3 = e.name.replace(/\.jsonl$/, "");
26505
- yield { sessionId: `codex_${base3}`, tool: "codex", path, mtimeMs: s.mtimeMs, sizeBytes: s.size };
26639
+ const base4 = e.name.replace(/\.jsonl$/, "");
26640
+ yield { sessionId: `codex_${base4}`, tool: "codex", path, mtimeMs: s.mtimeMs, sizeBytes: s.size };
26506
26641
  }
26507
26642
  }
26508
26643
  }
@@ -26519,7 +26654,7 @@ function* walkAgy() {
26519
26654
  for (const rawId of sessionDirs) {
26520
26655
  const sessionPath = join58(brainDir, rawId);
26521
26656
  try {
26522
- if (!statSync44(sessionPath).isDirectory())
26657
+ if (!statSync45(sessionPath).isDirectory())
26523
26658
  continue;
26524
26659
  } catch {
26525
26660
  continue;
@@ -26644,11 +26779,11 @@ function vaultEnable(passphrase, opts = {}) {
26644
26779
  }
26645
26780
  async function vaultEnableWithRemote(passphrase, remote, opts = {}) {
26646
26781
  const doFetch = opts.fetchImpl ?? fetch;
26647
- const base3 = remote.baseUrl.replace(/\/+$/, "");
26782
+ const base4 = remote.baseUrl.replace(/\/+$/, "");
26648
26783
  const headers = { authorization: `Bearer ${remote.token}`, "content-type": "application/json" };
26649
26784
  let published = { saltHex: null, keyId: null };
26650
26785
  try {
26651
- const r = await doFetch(`${base3}/api/vault/salt`, { headers });
26786
+ const r = await doFetch(`${base4}/api/vault/salt`, { headers });
26652
26787
  if (r.ok)
26653
26788
  published = await r.json();
26654
26789
  } catch {
@@ -26662,7 +26797,7 @@ async function vaultEnableWithRemote(passphrase, remote, opts = {}) {
26662
26797
  }
26663
26798
  const result = vaultEnable(passphrase);
26664
26799
  try {
26665
- const r = await doFetch(`${base3}/api/vault/salt`, {
26800
+ const r = await doFetch(`${base4}/api/vault/salt`, {
26666
26801
  method: "POST",
26667
26802
  headers,
26668
26803
  body: JSON.stringify({ saltHex: result.saltHex, keyId: result.keyId })
@@ -26755,8 +26890,8 @@ async function vaultSync(passphrase) {
26755
26890
  return report;
26756
26891
  }
26757
26892
  function importedPathFor(tool, sessionId) {
26758
- const base3 = sessionId.replace(/^gemini_/, "").replace(/^codex_/, "").replace(/^agy_/, "").replace(/^cursor_/, "").replace(/^opencode_/, "");
26759
- return join59(IMPORTED_ROOT(), tool, `${base3}.jsonl`);
26893
+ const base4 = sessionId.replace(/^gemini_/, "").replace(/^codex_/, "").replace(/^agy_/, "").replace(/^cursor_/, "").replace(/^opencode_/, "");
26894
+ return join59(IMPORTED_ROOT(), tool, `${base4}.jsonl`);
26760
26895
  }
26761
26896
  async function vaultRestore(passphrase, opts = {}) {
26762
26897
  const ctx = context2();
@@ -27157,8 +27292,8 @@ var init_decision_guard = __esm({
27157
27292
  isManifest = (p) => {
27158
27293
  if (!p)
27159
27294
  return false;
27160
- const base3 = p.split(/[\\/]/).pop()?.toLowerCase() ?? "";
27161
- return MANIFESTS.includes(base3);
27295
+ const base4 = p.split(/[\\/]/).pop()?.toLowerCase() ?? "";
27296
+ return MANIFESTS.includes(base4);
27162
27297
  };
27163
27298
  }
27164
27299
  });
@@ -27756,8 +27891,8 @@ async function deviceLogin(opts, onPrompt) {
27756
27891
  throw new Error("device-auth timed out \u2014 the code expired before approval.");
27757
27892
  }
27758
27893
  async function betterAuthDeviceLogin(serverUrl, onPrompt) {
27759
- const base3 = serverUrl.replace(/\/+$/, "");
27760
- const startRes = await fetch(`${base3}/api/auth/device/code`, {
27894
+ const base4 = serverUrl.replace(/\/+$/, "");
27895
+ const startRes = await fetch(`${base4}/api/auth/device/code`, {
27761
27896
  method: "POST",
27762
27897
  headers: { "content-type": "application/json" },
27763
27898
  body: JSON.stringify({ client_id: BETTER_AUTH_CLI_CLIENT_ID })
@@ -27765,7 +27900,7 @@ async function betterAuthDeviceLogin(serverUrl, onPrompt) {
27765
27900
  if (!startRes.ok) {
27766
27901
  throw new Error(`device-auth init failed: HTTP ${startRes.status} ${await startRes.text().catch(() => "")}`);
27767
27902
  }
27768
- const start = await readDeviceCode(startRes, base3);
27903
+ const start = await readDeviceCode(startRes, base4);
27769
27904
  onPrompt({
27770
27905
  url: start.verification_uri_complete || start.verification_uri,
27771
27906
  userCode: start.user_code,
@@ -27775,7 +27910,7 @@ async function betterAuthDeviceLogin(serverUrl, onPrompt) {
27775
27910
  let interval = (start.interval ?? 5) * 1e3;
27776
27911
  while (Date.now() < deadline) {
27777
27912
  await sleep(interval);
27778
- const res = await fetch(`${base3}/api/auth/device/token`, {
27913
+ const res = await fetch(`${base4}/api/auth/device/token`, {
27779
27914
  method: "POST",
27780
27915
  headers: { "content-type": "application/json" },
27781
27916
  body: JSON.stringify({
@@ -27877,7 +28012,7 @@ async function selectSessions(target, opts, fetchImpl = fetch) {
27877
28012
  const qs = new URLSearchParams({ limit: String(PAGE), offset: String(offset) });
27878
28013
  if (opts.project) qs.set("project", opts.project);
27879
28014
  if (opts.tool) qs.set("tool", opts.tool);
27880
- const res = await fetchImpl(`${base2(target.serverUrl)}/api/conversations/recent?${qs}`, {
28015
+ const res = await fetchImpl(`${base3(target.serverUrl)}/api/conversations/recent?${qs}`, {
27881
28016
  headers: { authorization: `Bearer ${target.token}` }
27882
28017
  });
27883
28018
  if (!res.ok) throw new Error(`list failed: HTTP ${res.status}`);
@@ -27906,7 +28041,7 @@ async function bulkDelete(ids, opts = {}) {
27906
28041
  try {
27907
28042
  for (let i = 0; i < unique.length; i += BATCH) {
27908
28043
  const slice = unique.slice(i, i + BATCH);
27909
- const res = await fetchImpl(`${base2(t.serverUrl)}/api/sync`, {
28044
+ const res = await fetchImpl(`${base3(t.serverUrl)}/api/sync`, {
27910
28045
  method: "POST",
27911
28046
  headers: { "content-type": "application/json", authorization: `Bearer ${t.token}` },
27912
28047
  body: JSON.stringify({
@@ -27942,7 +28077,7 @@ async function bulkDelete(ids, opts = {}) {
27942
28077
  return out;
27943
28078
  }
27944
28079
  async function listTombstones(target, limit = 500, fetchImpl = fetch) {
27945
- const res = await fetchImpl(`${base2(target.serverUrl)}/api/data/tombstones?limit=${limit}`, {
28080
+ const res = await fetchImpl(`${base3(target.serverUrl)}/api/data/tombstones?limit=${limit}`, {
27946
28081
  headers: { authorization: `Bearer ${target.token}` }
27947
28082
  });
27948
28083
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
@@ -27959,7 +28094,7 @@ async function restoreSessions(ids, opts = {}) {
27959
28094
  try {
27960
28095
  let restored = 0, notDeleted = 0;
27961
28096
  for (let i = 0; i < unique.length; i += BATCH) {
27962
- const res = await fetchImpl(`${base2(t.serverUrl)}/api/data/restore`, {
28097
+ const res = await fetchImpl(`${base3(t.serverUrl)}/api/data/restore`, {
27963
28098
  method: "POST",
27964
28099
  headers: { "content-type": "application/json", authorization: `Bearer ${t.token}` },
27965
28100
  body: JSON.stringify({ session_ids: unique.slice(i, i + BATCH) })
@@ -27982,7 +28117,7 @@ function needsConfirmation(opts) {
27982
28117
  const enumeratedByCaller = opts.argvIds > 0 && !opts.project && !opts.stdin;
27983
28118
  return !enumeratedByCaller;
27984
28119
  }
27985
- var PAGE, BATCH, base2;
28120
+ var PAGE, BATCH, base3;
27986
28121
  var init_bulk_delete = __esm({
27987
28122
  "src/bulk-delete.ts"() {
27988
28123
  "use strict";
@@ -27990,7 +28125,7 @@ var init_bulk_delete = __esm({
27990
28125
  init_sync_ledger();
27991
28126
  PAGE = 200;
27992
28127
  BATCH = 250;
27993
- base2 = (url) => url.replace(/\/+$/, "");
28128
+ base3 = (url) => url.replace(/\/+$/, "");
27994
28129
  }
27995
28130
  });
27996
28131
 
@@ -28355,13 +28490,13 @@ function requireTarget() {
28355
28490
  }
28356
28491
  return t;
28357
28492
  }
28358
- async function readJsonBody(res, base3, what) {
28493
+ async function readJsonBody(res, base4, what) {
28359
28494
  const text = await res.text().catch(() => "");
28360
28495
  try {
28361
28496
  return JSON.parse(text);
28362
28497
  } catch {
28363
28498
  throw new Error(
28364
- `${base3} answered ${res.status} with something that is not JSON (${JSON.stringify(text.trim().slice(0, 60))}) for ${what} \u2014 a proxy, a captive portal or a host that no longer serves the chat-recall API`
28499
+ `${base4} answered ${res.status} with something that is not JSON (${JSON.stringify(text.trim().slice(0, 60))}) for ${what} \u2014 a proxy, a captive portal or a host that no longer serves the chat-recall API`
28365
28500
  );
28366
28501
  }
28367
28502
  }
@@ -29167,9 +29302,9 @@ program.command("feedback").argument("<message...>", "what you want to say \u201
29167
29302
  return;
29168
29303
  }
29169
29304
  const target = firstTarget();
29170
- const base3 = target?.base || (process.env.CHAT_RECALL_SERVER || "https://chatrecall.dev").replace(/\/+$/, "");
29305
+ const base4 = target?.base || (process.env.CHAT_RECALL_SERVER || "https://chatrecall.dev").replace(/\/+$/, "");
29171
29306
  try {
29172
- const res = await fetch(`${base3}/api/contact/feedback`, {
29307
+ const res = await fetch(`${base4}/api/contact/feedback`, {
29173
29308
  method: "POST",
29174
29309
  headers: {
29175
29310
  "content-type": "application/json",
@@ -29196,14 +29331,14 @@ program.command("feedback").argument("<message...>", "what you want to say \u201
29196
29331
  console.log(chalk2.dim(" Add --email <address> next time if you want a reply."));
29197
29332
  }
29198
29333
  } catch (err) {
29199
- console.error(chalk2.red(`Could not reach ${base3}.`));
29334
+ console.error(chalk2.red(`Could not reach ${base4}.`));
29200
29335
  console.error(chalk2.dim(" Your message, so it is not lost:"));
29201
29336
  console.error(chalk2.dim(` ${message}`));
29202
29337
  process.exitCode = 1;
29203
29338
  }
29204
29339
  });
29205
29340
  program.command("doctor").description("Quick health check across login, server, credentials, hooks, MCP server, and codeindex").option("--purge-local", "Remove the legacy local index (cache.db + vector/KG files) left by pre-thin-collector versions \u2014 storage is server-side now. Requires login; keeps credentials, sync ledger, identity, and the audit log.").action(async (opts) => {
29206
- const { existsSync: existsSync58, readFileSync: readFileSync50, statSync: statSync45 } = await import("fs");
29341
+ const { existsSync: existsSync58, readFileSync: readFileSync50, statSync: statSync46 } = await import("fs");
29207
29342
  const { execSync: execSync6 } = await import("child_process");
29208
29343
  const rows = [];
29209
29344
  const note = (ok, label, detail) => rows.push({ ok, label, detail });
@@ -29271,7 +29406,7 @@ program.command("doctor").description("Quick health check across login, server,
29271
29406
  note(false, "Credentials file", `missing \u2014 run \`chat-recall login <server-url>\``);
29272
29407
  } else {
29273
29408
  try {
29274
- const mode = statSync45(credFile).mode & 511;
29409
+ const mode = statSync46(credFile).mode & 511;
29275
29410
  const isWin = process.platform === "win32";
29276
29411
  const safe = isWin || (mode & 63) === 0;
29277
29412
  note(safe, "Credentials file", isWin ? `${credFile} (Windows ACL \u2014 POSIX mode does not apply)` : `${credFile} (mode ${mode.toString(8).padStart(3, "0")}${safe ? "" : " \u2014 should be 600"})`);
@@ -29801,13 +29936,13 @@ sources2.command("decline <path>").description("Keep a folder out of sync (e.g.
29801
29936
  }
29802
29937
  const { fetchWithTimeout: fetchWithTimeout2 } = await Promise.resolve().then(() => (init_http(), http_exports));
29803
29938
  for (const t of targets) {
29804
- const base3 = t.serverUrl.replace(/\/+$/, "");
29939
+ const base4 = t.serverUrl.replace(/\/+$/, "");
29805
29940
  const headers = {};
29806
29941
  if (t.token) headers.authorization = `Bearer ${t.token}`;
29807
29942
  let deleted = 0, missing = 0, failed = 0;
29808
29943
  for (const id of ids) {
29809
29944
  try {
29810
- const res = await fetchWithTimeout2(`${base3}/api/conversations/${encodeURIComponent(id)}`, { method: "DELETE", headers }, 3e4);
29945
+ const res = await fetchWithTimeout2(`${base4}/api/conversations/${encodeURIComponent(id)}`, { method: "DELETE", headers }, 3e4);
29811
29946
  if (res.ok) deleted++;
29812
29947
  else if (res.status === 404) missing++;
29813
29948
  else failed++;
@@ -29815,7 +29950,7 @@ sources2.command("decline <path>").description("Keep a folder out of sync (e.g.
29815
29950
  failed++;
29816
29951
  }
29817
29952
  }
29818
- const line = ` ${base3}: deleted ${deleted}` + (missing ? `, ${missing} were not there` : "") + (failed ? chalk2.red(`, ${failed} FAILED`) : "");
29953
+ const line = ` ${base4}: deleted ${deleted}` + (missing ? `, ${missing} were not there` : "") + (failed ? chalk2.red(`, ${failed} FAILED`) : "");
29819
29954
  console.log(failed ? chalk2.yellow(line) : chalk2.green(line));
29820
29955
  if (failed) process.exitCode = 1;
29821
29956
  }
@@ -30597,7 +30732,7 @@ program.command("task-hook").description("Move a board card when a prompt or a c
30597
30732
  }
30598
30733
  });
30599
30734
  program.command("install-hooks").description("Install Claude Code hooks (Stop + PreCompact + UserPromptSubmit + SessionEnd + SessionStart) into every Claude profile").option("--uninstall", "Remove hooks instead of installing them").option("--no-resume-hint", "Don't install the UserPromptSubmit resume-hint hook").option("--no-escalate", "Don't install the SessionEnd learnings-escalation hook").option("--no-wakeup", "Don't install the SessionStart wake-up hook").option("--no-guard", "Don't install the PreToolUse decision guard").option("--no-task-board", "Don't install the hooks that claim and close board cards").action(async (opts) => {
30600
- const { mkdirSync: mkdirSync23, copyFileSync: copyFileSync4, chmodSync: chmodSync5, existsSync: existsSync58, readFileSync: readFileSync50, writeFileSync: writeFileSync24, statSync: statSync45, unlinkSync: unlinkSync4 } = await import("fs");
30735
+ const { mkdirSync: mkdirSync23, copyFileSync: copyFileSync4, chmodSync: chmodSync5, existsSync: existsSync58, readFileSync: readFileSync50, writeFileSync: writeFileSync24, statSync: statSync46, unlinkSync: unlinkSync4 } = await import("fs");
30601
30736
  const { fileURLToPath: fileURLToPath6 } = await import("url");
30602
30737
  const { boardHookEntries: boardHookEntries2, isBoardHookEntry: isBoardHookEntry2, registerBoardHooks: registerBoardHooks2, resolveCliEntry: resolveCliEntry2 } = await Promise.resolve().then(() => (init_board_hooks(), board_hooks_exports));
30603
30738
  const here = fileURLToPath6(new URL(".", import.meta.url));
@@ -30812,18 +30947,18 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
30812
30947
  writeFileSync24(hooksJson, JSON.stringify(config2, null, 2) + "\n");
30813
30948
  }
30814
30949
  if (installGuard) await addGuardToOtherTools(installedGuardHook);
30815
- const saveSz = statSync45(installedSaveHook).size;
30950
+ const saveSz = statSync46(installedSaveHook).size;
30816
30951
  console.log(chalk2.green(`\u2713 Installed chat-recall save hook (${saveSz} bytes)`));
30817
30952
  if (installResume) {
30818
- const resumeSz = statSync45(installedResumeHook).size;
30953
+ const resumeSz = statSync46(installedResumeHook).size;
30819
30954
  console.log(chalk2.green(`\u2713 Installed chat-recall resume-hint hook (${resumeSz} bytes)`));
30820
30955
  }
30821
30956
  if (installEscalate) {
30822
- const escalateSz = statSync45(installedEscalateHook).size;
30957
+ const escalateSz = statSync46(installedEscalateHook).size;
30823
30958
  console.log(chalk2.green(`\u2713 Installed chat-recall learnings-escalation hook (${escalateSz} bytes)`));
30824
30959
  }
30825
30960
  if (installGuard) {
30826
- const guardSz = statSync45(installedGuardHook).size;
30961
+ const guardSz = statSync46(installedGuardHook).size;
30827
30962
  console.log(chalk2.green(`\u2713 Installed chat-recall decision guard (${guardSz} bytes)`));
30828
30963
  }
30829
30964
  if (installTaskBoard) {
@@ -30831,7 +30966,7 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
30831
30966
  console.log(chalk2.dim(" A prompt naming a card id claims it; a commit message naming one closes it."));
30832
30967
  }
30833
30968
  if (installWakeup) {
30834
- const wakeupSz = statSync45(installedWakeupHook).size;
30969
+ const wakeupSz = statSync46(installedWakeupHook).size;
30835
30970
  console.log(chalk2.green(`\u2713 Installed chat-recall wake-up hook (${wakeupSz} bytes)`));
30836
30971
  for (const f of wakeupSkipped) {
30837
30972
  console.log(chalk2.dim(` (SessionStart already wired in ${f} \u2014 left as is, not duplicated)`));
@@ -30948,10 +31083,10 @@ program.command("service <action>").description("Manage the per-user background
30948
31083
  });
30949
31084
  async function runLogin(serverUrl, opts) {
30950
31085
  const { saveCredentials: saveCredentials2, loadAllCredentials: loadAllCredentials2 } = await Promise.resolve().then(() => (init_sync_client(), sync_client_exports));
30951
- const base3 = serverUrl.replace(/\/+$/, "");
31086
+ const base4 = serverUrl.replace(/\/+$/, "");
30952
31087
  const verifyToken = async (token) => {
30953
31088
  try {
30954
- const res = await fetch(`${base3}/api/status`, {
31089
+ const res = await fetch(`${base4}/api/status`, {
30955
31090
  headers: token ? { authorization: `Bearer ${token}` } : {},
30956
31091
  signal: AbortSignal.timeout(1e4)
30957
31092
  });
@@ -30967,36 +31102,36 @@ async function runLogin(serverUrl, opts) {
30967
31102
  return failLogin(opts, 'the token contains non-ASCII characters \u2014 this looks like a masked/truncated copy (e.g. "ct_12345678\u2026")');
30968
31103
  }
30969
31104
  const { probeServer: identifyServer, probeOk: identified, probeAdvice: identifyAdvice } = await Promise.resolve().then(() => (init_server_probe(), server_probe_exports));
30970
- const who = await identifyServer(base3, { timeoutMs: 1e4 });
30971
- if (!identified(who)) return failLogin(opts, identifyAdvice(who, base3));
31105
+ const who = await identifyServer(base4, { timeoutMs: 1e4 });
31106
+ if (!identified(who)) return failLogin(opts, identifyAdvice(who, base4));
30972
31107
  const check = await verifyToken(token);
30973
31108
  if (!check.ok) {
30974
31109
  if (check.status === 401 || check.status === 403) {
30975
31110
  console.error(chalk2.dim("Tokens are shown once \u2014 mint a fresh one (Account \u2192 Connect your machine) and copy the whole line."));
30976
- return failLogin(opts, `${base3} rejected the token (HTTP ${check.status})`);
31111
+ return failLogin(opts, `${base4} rejected the token (HTTP ${check.status})`);
30977
31112
  }
30978
31113
  if (check.status !== void 0 && check.status >= 500) {
30979
- return failLogin(opts, `${base3} answered HTTP ${check.status} \u2014 the server is up but failing. The token was never checked. Nothing to fix locally.`);
31114
+ return failLogin(opts, `${base4} answered HTTP ${check.status} \u2014 the server is up but failing. The token was never checked. Nothing to fix locally.`);
30980
31115
  }
30981
31116
  if (check.status === 404 || check.status === 410) {
30982
- return failLogin(opts, `${base3} does not serve the chat-recall API (HTTP ${check.status}). If the server moved, log in to its new URL.`);
31117
+ return failLogin(opts, `${base4} does not serve the chat-recall API (HTTP ${check.status}). If the server moved, log in to its new URL.`);
30983
31118
  }
30984
- return failLogin(opts, `could not verify the token against ${base3}: ${check.error || `HTTP ${check.status}`}`);
31119
+ return failLogin(opts, `could not verify the token against ${base4}: ${check.error || `HTTP ${check.status}`}`);
30985
31120
  }
30986
31121
  saveCredentials2({ serverUrl, token });
30987
31122
  console.log(chalk2.green("\u2713 Logged in.") + chalk2.dim(` server: ${serverUrl} (token verified)`));
30988
31123
  return;
30989
31124
  }
30990
- const existing = loadAllCredentials2().find((t) => t.serverUrl.replace(/\/+$/, "") === base3);
31125
+ const existing = loadAllCredentials2().find((t) => t.serverUrl.replace(/\/+$/, "") === base4);
30991
31126
  if (existing && (await verifyToken(existing.token)).ok) {
30992
31127
  console.log(chalk2.green("\u2713 Already connected.") + chalk2.dim(` server: ${serverUrl} (existing token verified)`));
30993
31128
  return;
30994
31129
  }
30995
31130
  try {
30996
31131
  const { probeServer: probeServer2, probeOk: probeOk2 } = await Promise.resolve().then(() => (init_server_probe(), server_probe_exports));
30997
- const identified = await probeServer2(base3, { timeoutMs: 8e3 });
31132
+ const identified = await probeServer2(base4, { timeoutMs: 8e3 });
30998
31133
  if (probeOk2(identified)) {
30999
- const probe = await fetch(`${base3}/api/status`, { signal: AbortSignal.timeout(8e3) });
31134
+ const probe = await fetch(`${base4}/api/status`, { signal: AbortSignal.timeout(8e3) });
31000
31135
  if (probe.status === 200) {
31001
31136
  saveCredentials2({ serverUrl, token: "" });
31002
31137
  console.log(chalk2.green("\u2713 Logged in.") + chalk2.dim(` ${serverUrl} (local server \u2014 no auth, no token needed)`));
@@ -31017,16 +31152,16 @@ async function runLogin(serverUrl, opts) {
31017
31152
  if (!issuer) {
31018
31153
  const { probeServer: probeServer2, probeOk: probeOk2, probeAdvice: probeAdvice2 } = await Promise.resolve().then(() => (init_server_probe(), server_probe_exports));
31019
31154
  for (let attempt = 1; attempt <= 3 && !authProvider; attempt++) {
31020
- const probe = await probeServer2(base3, { timeoutMs: 15e3 });
31155
+ const probe = await probeServer2(base4, { timeoutMs: 15e3 });
31021
31156
  if (probeOk2(probe)) {
31022
31157
  const caps = probe.raw;
31023
31158
  authProvider = caps?.authProvider;
31024
31159
  if (caps?.oidcIssuer) issuer = caps.oidcIssuer;
31025
31160
  capsError = null;
31026
31161
  } else if (probe.kind === "moved" || probe.kind === "not_api") {
31027
- return failLogin(opts, probeAdvice2(probe, base3));
31162
+ return failLogin(opts, probeAdvice2(probe, base4));
31028
31163
  } else {
31029
- capsError = probeAdvice2(probe, base3);
31164
+ capsError = probeAdvice2(probe, base4);
31030
31165
  }
31031
31166
  if (!authProvider && attempt < 3) await new Promise((r) => setTimeout(r, attempt * 1e3));
31032
31167
  }
@@ -31035,7 +31170,7 @@ async function runLogin(serverUrl, opts) {
31035
31170
  authProvider = "better-auth";
31036
31171
  if (capsError) {
31037
31172
  console.log(` ${chalk2.yellow("Could not read the server's capabilities")} (${capsError}) \u2014 assuming the standard sign-in flow.`);
31038
- void Promise.resolve().then(() => (init_install_report(), install_report_exports)).then(({ reportInstallFailure: reportInstallFailure2 }) => reportInstallFailure2(base3, {
31173
+ void Promise.resolve().then(() => (init_install_report(), install_report_exports)).then(({ reportInstallFailure: reportInstallFailure2 }) => reportInstallFailure2(base4, {
31039
31174
  step: "cli_login_probe",
31040
31175
  reason: capsError?.slice(0, 40) ?? null,
31041
31176
  message: capsError
@@ -31057,20 +31192,20 @@ async function runLogin(serverUrl, opts) {
31057
31192
  console.log(chalk2.dim(` If the page asks for a code: ${chalk2.bold(p.userCode)}`));
31058
31193
  console.log(chalk2.dim("Then come back here \u2014 this finishes on its own. Waiting\u2026"));
31059
31194
  };
31060
- const tokens = authProvider === "better-auth" ? await betterAuthDeviceLogin2(base3, onPrompt) : await deviceLogin2({ issuer, clientId: opts.clientId }, onPrompt);
31195
+ const tokens = authProvider === "better-auth" ? await betterAuthDeviceLogin2(base4, onPrompt) : await deviceLogin2({ issuer, clientId: opts.clientId }, onPrompt);
31061
31196
  const authHdr = { authorization: `Bearer ${tokens.accessToken}`, "content-type": "application/json" };
31062
- const meRes = await fetch(`${base3}/api/me`, { headers: authHdr });
31063
- if (!meRes.ok) throw new Error(`${base3}/api/me: HTTP ${meRes.status} ${await meRes.text().catch(() => "")}`);
31064
- const me = await readJsonBody(meRes, base3, "GET /api/me");
31197
+ const meRes = await fetch(`${base4}/api/me`, { headers: authHdr });
31198
+ if (!meRes.ok) throw new Error(`${base4}/api/me: HTTP ${meRes.status} ${await meRes.text().catch(() => "")}`);
31199
+ const me = await readJsonBody(meRes, base4, "GET /api/me");
31065
31200
  const teams = me.teams || [];
31066
31201
  let slug = opts.team;
31067
31202
  if (!slug) {
31068
31203
  if (teams.length === 1) slug = teams[0].team_slug;
31069
31204
  else if (teams.length === 0) {
31070
31205
  const name = me.user?.email?.split("@")[0]?.replace(/[^a-z0-9]/gi, "") || "workspace";
31071
- const created = await fetch(`${base3}/api/teams`, { method: "POST", headers: authHdr, body: JSON.stringify({ name }) });
31206
+ const created = await fetch(`${base4}/api/teams`, { method: "POST", headers: authHdr, body: JSON.stringify({ name }) });
31072
31207
  if (!created.ok) throw new Error(`workspace create failed: HTTP ${created.status} ${await created.text().catch(() => "")}`);
31073
- slug = (await readJsonBody(created, base3, "POST /api/teams")).slug;
31208
+ slug = (await readJsonBody(created, base4, "POST /api/teams")).slug;
31074
31209
  console.log(chalk2.dim(`Created workspace "${name}" (${slug}) \u2014 you're its owner.`));
31075
31210
  } else {
31076
31211
  teams.forEach((t) => console.error(` ${t.team_slug} ${chalk2.dim(t.name)}`));
@@ -31078,13 +31213,13 @@ async function runLogin(serverUrl, opts) {
31078
31213
  }
31079
31214
  }
31080
31215
  const deviceId = opts.deviceId || (await import("node:os")).hostname();
31081
- const mint = await fetch(`${base3}/api/teams/${encodeURIComponent(slug)}/tokens`, {
31216
+ const mint = await fetch(`${base4}/api/teams/${encodeURIComponent(slug)}/tokens`, {
31082
31217
  method: "POST",
31083
31218
  headers: authHdr,
31084
31219
  body: JSON.stringify({ device_id: deviceId })
31085
31220
  });
31086
31221
  if (!mint.ok) throw new Error(`token mint failed: HTTP ${mint.status} ${await mint.text().catch(() => "")}`);
31087
- const { token } = await readJsonBody(mint, base3, "POST /api/teams/:slug/tokens");
31222
+ const { token } = await readJsonBody(mint, base4, "POST /api/teams/:slug/tokens");
31088
31223
  saveCredentials2({ serverUrl, token });
31089
31224
  console.log(chalk2.green(`\u2713 Logged in to ${chalk2.bold(slug)}`) + chalk2.dim(` (device: ${deviceId}) server: ${serverUrl}`));
31090
31225
  if (!opts.fromInit) {
@@ -31561,16 +31696,16 @@ program.command("update").description("Update this CLI now from the server you s
31561
31696
  }
31562
31697
  let installFailed = false;
31563
31698
  for (const cred of targets) {
31564
- const base3 = cred.serverUrl.replace(/\/+$/, "");
31699
+ const base4 = cred.serverUrl.replace(/\/+$/, "");
31565
31700
  const headers = cred.token ? { authorization: `Bearer ${cred.token}` } : {};
31566
- const r = await runAutoUpdate2(base3, headers, cliVersion3());
31701
+ const r = await runAutoUpdate2(base4, headers, cliVersion3());
31567
31702
  if (r.updated) {
31568
- console.log(chalk2.green(`\u2713 ${r.reason}`) + chalk2.dim(` (${base3})`));
31703
+ console.log(chalk2.green(`\u2713 ${r.reason}`) + chalk2.dim(` (${base4})`));
31569
31704
  continue;
31570
31705
  }
31571
31706
  const benign = /already current|no CLI release|disabled/.test(r.reason);
31572
31707
  if (/install failed|download failed|checksum/.test(r.reason)) installFailed = true;
31573
- console.log((benign ? chalk2.dim("\u2022 ") : chalk2.red("\u2717 ")) + r.reason + chalk2.dim(` (${base3})`));
31708
+ console.log((benign ? chalk2.dim("\u2022 ") : chalk2.red("\u2717 ")) + r.reason + chalk2.dim(` (${base4})`));
31574
31709
  }
31575
31710
  const check = await refreshUpdateCheck2(true);
31576
31711
  if (installFailed) {