chat-recall 0.5.30 → 0.5.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/watch.js CHANGED
@@ -5917,6 +5917,64 @@ var init_chunker = __esm({
5917
5917
  }
5918
5918
  });
5919
5919
 
5920
+ // ../engine/dist/core/project-dir-name.js
5921
+ import { readdirSync as readdirSync4 } from "node:fs";
5922
+ function looksWindowsEncoded(dirName) {
5923
+ return /^[A-Za-z]--/.test(dirName);
5924
+ }
5925
+ function decodeProjectDirName(dirName) {
5926
+ if (!dirName)
5927
+ return "";
5928
+ if (looksWindowsEncoded(dirName)) {
5929
+ const drive = dirName[0].toUpperCase();
5930
+ const rest = dirName.slice(3).replace(/-/g, "\\");
5931
+ return `${drive}:\\${rest}`;
5932
+ }
5933
+ return "/" + dirName.replace(/^-/, "").replace(/-/g, "/");
5934
+ }
5935
+ function resolveProjectDirName(dirName, deps = {}) {
5936
+ const structural = decodeProjectDirName(dirName);
5937
+ if (!dirName)
5938
+ return structural;
5939
+ if (looksWindowsEncoded(dirName))
5940
+ return structural;
5941
+ const readdir3 = deps.readdir ?? ((p) => readdirSync4(p, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name));
5942
+ const encodeName = (name) => name.replace(/[-_.]/g, "-");
5943
+ let remaining = dirName.replace(/^-/, "");
5944
+ let current = "/";
5945
+ while (remaining) {
5946
+ let children;
5947
+ try {
5948
+ children = readdir3(current);
5949
+ } catch {
5950
+ break;
5951
+ }
5952
+ let best = "";
5953
+ for (const child of children) {
5954
+ const encoded = encodeName(child);
5955
+ if (!encoded || encoded.length < best.length)
5956
+ continue;
5957
+ if (!remaining.startsWith(encoded))
5958
+ continue;
5959
+ const next = remaining[encoded.length];
5960
+ if (next !== void 0 && next !== "-")
5961
+ continue;
5962
+ if (encoded.length > best.length)
5963
+ best = child;
5964
+ }
5965
+ if (!best)
5966
+ break;
5967
+ current = current === "/" ? `/${best}` : `${current}/${best}`;
5968
+ remaining = remaining.slice(encodeName(best).length).replace(/^-/, "");
5969
+ }
5970
+ return remaining ? structural : current;
5971
+ }
5972
+ var init_project_dir_name = __esm({
5973
+ "../engine/dist/core/project-dir-name.js"() {
5974
+ "use strict";
5975
+ }
5976
+ });
5977
+
5920
5978
  // ../engine/dist/core/model-pricing.js
5921
5979
  function pricingFor(modelId) {
5922
5980
  if (!modelId)
@@ -6088,7 +6146,7 @@ var init_model_pricing = __esm({
6088
6146
  });
6089
6147
 
6090
6148
  // ../engine/dist/parsers/session.js
6091
- import { createReadStream, existsSync as existsSync5, readdirSync as readdirSync4, readFileSync as readFileSync2, statSync as statSync4, openSync, readSync, closeSync } from "fs";
6149
+ import { createReadStream, existsSync as existsSync5, readdirSync as readdirSync5, readFileSync as readFileSync2, statSync as statSync4, openSync, readSync, closeSync } from "fs";
6092
6150
  import { createInterface } from "readline";
6093
6151
  import { join as join5, basename as basename2 } from "path";
6094
6152
  function removeCodeBlocks(text) {
@@ -6159,7 +6217,7 @@ function* iterAllSessionIndices(claudeDir) {
6159
6217
  if (!existsSync5(dir)) {
6160
6218
  return;
6161
6219
  }
6162
- const entries = readdirSync4(dir, { withFileTypes: true });
6220
+ const entries = readdirSync5(dir, { withFileTypes: true });
6163
6221
  for (const entry of entries) {
6164
6222
  if (!entry.isDirectory())
6165
6223
  continue;
@@ -6181,7 +6239,7 @@ function getSubagentPaths(sessionPath) {
6181
6239
  const subagentsDir = join5(sessionPath.slice(0, -6), "subagents");
6182
6240
  if (!existsSync5(subagentsDir))
6183
6241
  return [];
6184
- return readdirSync4(subagentsDir).filter((f) => f.endsWith(".jsonl")).sort().map((f) => join5(subagentsDir, f));
6242
+ return readdirSync5(subagentsDir).filter((f) => f.endsWith(".jsonl")).sort().map((f) => join5(subagentsDir, f));
6185
6243
  }
6186
6244
  function getSubagentProjectPath(sessionPath, folderDerivedPath) {
6187
6245
  const subagentPaths = getSubagentPaths(sessionPath);
@@ -6498,40 +6556,6 @@ ${resultText}` : resultText;
6498
6556
  });
6499
6557
  return content;
6500
6558
  }
6501
- function decodeDirName(dirName) {
6502
- const segments = dirName.replace(/^-/, "").split("-");
6503
- let currentPath = "/";
6504
- let i = 0;
6505
- while (i < segments.length) {
6506
- let matched = false;
6507
- const singleCandidate = join5(currentPath, segments[i]);
6508
- if (existsSync5(singleCandidate)) {
6509
- currentPath = singleCandidate;
6510
- i++;
6511
- matched = true;
6512
- continue;
6513
- }
6514
- for (let len = 2; len <= segments.length - i; len++) {
6515
- const joinedSegments = segments.slice(i, i + len);
6516
- for (const sep5 of ["-", "_", "."]) {
6517
- const candidate = join5(currentPath, joinedSegments.join(sep5));
6518
- if (existsSync5(candidate)) {
6519
- currentPath = candidate;
6520
- i += len;
6521
- matched = true;
6522
- break;
6523
- }
6524
- }
6525
- if (matched)
6526
- break;
6527
- }
6528
- if (!matched) {
6529
- currentPath = join5(currentPath, segments[i]);
6530
- i++;
6531
- }
6532
- }
6533
- return currentPath;
6534
- }
6535
6559
  function* getAllSessions(claudeDir) {
6536
6560
  const seenSessionIds = /* @__PURE__ */ new Set();
6537
6561
  const projectDirs = claudeDir ? [claudeDir] : claudeProjectDirs();
@@ -6546,12 +6570,12 @@ function* getAllSessions(claudeDir) {
6546
6570
  }
6547
6571
  if (!existsSync5(dir))
6548
6572
  continue;
6549
- const dirEntries = readdirSync4(dir, { withFileTypes: true });
6573
+ const dirEntries = readdirSync5(dir, { withFileTypes: true });
6550
6574
  for (const projDirEntry of dirEntries) {
6551
6575
  if (!projDirEntry.isDirectory())
6552
6576
  continue;
6553
6577
  const projectPath = join5(dir, projDirEntry.name);
6554
- const files = readdirSync4(projectPath);
6578
+ const files = readdirSync5(projectPath);
6555
6579
  for (const file of files) {
6556
6580
  if (!file.endsWith(".jsonl"))
6557
6581
  continue;
@@ -6565,7 +6589,7 @@ function* getAllSessions(claudeDir) {
6565
6589
  const fullPath = join5(projectPath, file);
6566
6590
  try {
6567
6591
  const stat3 = statSync4(fullPath);
6568
- const derivedProjectPath = decodeDirName(projDirEntry.name);
6592
+ const derivedProjectPath = resolveProjectDirName(projDirEntry.name);
6569
6593
  const effectiveMtime = getSessionMtime(fullPath);
6570
6594
  let projectPath2 = "";
6571
6595
  if (hasSubagentsDir(fullPath)) {
@@ -6604,6 +6628,7 @@ var init_session = __esm({
6604
6628
  init_chunker();
6605
6629
  init_claude2();
6606
6630
  init_tool_paths();
6631
+ init_project_dir_name();
6607
6632
  init_model_pricing();
6608
6633
  }
6609
6634
  });
@@ -7265,7 +7290,7 @@ async function archiveRawSession(store, sessionId) {
7265
7290
  return await store.putRawSession(sessionId, exp.tool, Math.floor(exp.mtime), gz, size);
7266
7291
  }
7267
7292
  function detectForkPredecessor(sessionPath) {
7268
- const { readFileSync: readFileSync47, readdirSync: readdirSync35 } = requireFs();
7293
+ const { readFileSync: readFileSync47, readdirSync: readdirSync36 } = requireFs();
7269
7294
  const { dirname: dirname26, join: join56, basename: basename28 } = requirePath();
7270
7295
  let text;
7271
7296
  try {
@@ -7295,7 +7320,7 @@ function detectForkPredecessor(sessionPath) {
7295
7320
  const self = basename28(sessionPath);
7296
7321
  let entries;
7297
7322
  try {
7298
- entries = readdirSync35(dir);
7323
+ entries = readdirSync36(dir);
7299
7324
  } catch {
7300
7325
  return null;
7301
7326
  }
@@ -7574,28 +7599,8 @@ var init_shadow = __esm({
7574
7599
  }
7575
7600
  });
7576
7601
 
7577
- // ../engine/dist/core/project-dir-name.js
7578
- function looksWindowsEncoded(dirName) {
7579
- return /^[A-Za-z]--/.test(dirName);
7580
- }
7581
- function decodeProjectDirName(dirName) {
7582
- if (!dirName)
7583
- return "";
7584
- if (looksWindowsEncoded(dirName)) {
7585
- const drive = dirName[0].toUpperCase();
7586
- const rest = dirName.slice(3).replace(/-/g, "\\");
7587
- return `${drive}:\\${rest}`;
7588
- }
7589
- return "/" + dirName.replace(/^-/, "").replace(/-/g, "/");
7590
- }
7591
- var init_project_dir_name = __esm({
7592
- "../engine/dist/core/project-dir-name.js"() {
7593
- "use strict";
7594
- }
7595
- });
7596
-
7597
7602
  // ../engine/dist/core/live-session-scan.js
7598
- import { existsSync as existsSync7, readdirSync as readdirSync5, readFileSync as readFileSync4, statSync as statSync6, openSync as openSync2, readSync as readSync2, closeSync as closeSync2 } from "fs";
7603
+ import { existsSync as existsSync7, readdirSync as readdirSync6, readFileSync as readFileSync4, statSync as statSync6, openSync as openSync2, readSync as readSync2, closeSync as closeSync2 } from "fs";
7599
7604
  import { join as join9, basename as basename5 } from "path";
7600
7605
  import { createHash as createHash3 } from "crypto";
7601
7606
  function lazyGeminiProjectsJson() {
@@ -7632,7 +7637,7 @@ function sessionFileIndex() {
7632
7637
  seenRoots.add(root);
7633
7638
  let entries;
7634
7639
  try {
7635
- entries = readdirSync5(root, { withFileTypes: true });
7640
+ entries = readdirSync6(root, { withFileTypes: true });
7636
7641
  } catch {
7637
7642
  continue;
7638
7643
  }
@@ -7642,7 +7647,7 @@ function sessionFileIndex() {
7642
7647
  const dir = join9(root, entry.name);
7643
7648
  let names;
7644
7649
  try {
7645
- names = readdirSync5(dir);
7650
+ names = readdirSync6(dir);
7646
7651
  } catch {
7647
7652
  continue;
7648
7653
  }
@@ -7653,7 +7658,7 @@ function sessionFileIndex() {
7653
7658
  const located = {
7654
7659
  path: join9(dir, name),
7655
7660
  projectDir: entry.name,
7656
- projectPath: decodeProjectDirName(entry.name)
7661
+ projectPath: resolveProjectDirName(entry.name)
7657
7662
  };
7658
7663
  const prior = byId.get(id);
7659
7664
  if (prior)
@@ -7740,7 +7745,7 @@ function resolveSessionContentPaths(sessionFile) {
7740
7745
  const subDir = join9(sessionFile.slice(0, -6), "subagents");
7741
7746
  if (!existsSync7(subDir))
7742
7747
  return [sessionFile];
7743
- const subPaths = readdirSync5(subDir).filter((f) => f.endsWith(".jsonl")).sort().map((f) => join9(subDir, f));
7748
+ const subPaths = readdirSync6(subDir).filter((f) => f.endsWith(".jsonl")).sort().map((f) => join9(subDir, f));
7744
7749
  return [sessionFile, ...subPaths];
7745
7750
  }
7746
7751
  function loadGeminiProjectMap() {
@@ -7788,7 +7793,7 @@ function geminiIndex() {
7788
7793
  continue;
7789
7794
  let projs;
7790
7795
  try {
7791
- projs = readdirSync5(tmpRoot, { withFileTypes: true });
7796
+ projs = readdirSync6(tmpRoot, { withFileTypes: true });
7792
7797
  } catch {
7793
7798
  continue;
7794
7799
  }
@@ -7800,7 +7805,7 @@ function geminiIndex() {
7800
7805
  continue;
7801
7806
  let files;
7802
7807
  try {
7803
- files = readdirSync5(chats);
7808
+ files = readdirSync6(chats);
7804
7809
  } catch {
7805
7810
  continue;
7806
7811
  }
@@ -7919,21 +7924,21 @@ function findCodexSessionFile(sessionId) {
7919
7924
  function findCodexSessionFileIn(root, sessionId) {
7920
7925
  if (!existsSync7(root))
7921
7926
  return null;
7922
- for (const year of readdirSync5(root, { withFileTypes: true })) {
7927
+ for (const year of readdirSync6(root, { withFileTypes: true })) {
7923
7928
  if (!year.isDirectory())
7924
7929
  continue;
7925
7930
  const yearPath = join9(root, year.name);
7926
- for (const month of readdirSync5(yearPath, { withFileTypes: true })) {
7931
+ for (const month of readdirSync6(yearPath, { withFileTypes: true })) {
7927
7932
  if (!month.isDirectory())
7928
7933
  continue;
7929
7934
  const monthPath = join9(yearPath, month.name);
7930
- for (const day of readdirSync5(monthPath, { withFileTypes: true })) {
7935
+ for (const day of readdirSync6(monthPath, { withFileTypes: true })) {
7931
7936
  if (!day.isDirectory())
7932
7937
  continue;
7933
7938
  const dayPath = join9(monthPath, day.name);
7934
7939
  let files;
7935
7940
  try {
7936
- files = readdirSync5(dayPath);
7941
+ files = readdirSync6(dayPath);
7937
7942
  } catch {
7938
7943
  continue;
7939
7944
  }
@@ -7948,7 +7953,7 @@ function findCodexSessionFileIn(root, sessionId) {
7948
7953
  }
7949
7954
  }
7950
7955
  function scanDir(dir) {
7951
- for (const entry of readdirSync5(dir, { withFileTypes: true })) {
7956
+ for (const entry of readdirSync6(dir, { withFileTypes: true })) {
7952
7957
  if (entry.isDirectory()) {
7953
7958
  const found = scanDir(join9(dir, entry.name));
7954
7959
  if (found)
@@ -8893,7 +8898,7 @@ var init_generic_engine = __esm({
8893
8898
  });
8894
8899
 
8895
8900
  // ../engine/dist/core/backends/claude.js
8896
- import { existsSync as existsSync10, readdirSync as readdirSync6, readFileSync as readFileSync5, statSync as statSync8, openSync as openSync5, readSync as readSync5, closeSync as closeSync5 } from "fs";
8901
+ import { existsSync as existsSync10, readdirSync as readdirSync7, readFileSync as readFileSync5, statSync as statSync8, openSync as openSync5, readSync as readSync5, closeSync as closeSync5 } from "fs";
8897
8902
  import { join as join10, basename as basename8 } from "path";
8898
8903
  function stripReminders(text) {
8899
8904
  return text.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/g, "").trim();
@@ -9048,13 +9053,13 @@ var init_claude2 = __esm({
9048
9053
  collectSessionsFromRoot(root, cutoff, filter, seen, out) {
9049
9054
  if (!existsSync10(root))
9050
9055
  return;
9051
- for (const proj of readdirSync6(root, { withFileTypes: true })) {
9056
+ for (const proj of readdirSync7(root, { withFileTypes: true })) {
9052
9057
  if (!proj.isDirectory())
9053
9058
  continue;
9054
9059
  if (filter && !proj.name.toLowerCase().includes(filter))
9055
9060
  continue;
9056
9061
  const projPath = join10(root, proj.name);
9057
- const projectPath = decodeProjectDirName(proj.name);
9062
+ const projectPath = resolveProjectDirName(proj.name);
9058
9063
  const indexPath = join10(projPath, "sessions-index.json");
9059
9064
  if (existsSync10(indexPath)) {
9060
9065
  try {
@@ -9085,7 +9090,7 @@ var init_claude2 = __esm({
9085
9090
  }
9086
9091
  let files;
9087
9092
  try {
9088
- files = readdirSync6(projPath);
9093
+ files = readdirSync7(projPath);
9089
9094
  } catch {
9090
9095
  continue;
9091
9096
  }
@@ -9354,7 +9359,7 @@ var init_claude2 = __esm({
9354
9359
  for (const root of claudeProjectDirs()) {
9355
9360
  if (!existsSync10(root))
9356
9361
  continue;
9357
- for (const projEntry of readdirSync6(root, { withFileTypes: true })) {
9362
+ for (const projEntry of readdirSync7(root, { withFileTypes: true })) {
9358
9363
  if (!projEntry.isDirectory())
9359
9364
  continue;
9360
9365
  if (opts.projectFilter && !projEntry.name.toLowerCase().includes(opts.projectFilter.toLowerCase()))
@@ -9362,7 +9367,7 @@ var init_claude2 = __esm({
9362
9367
  const projPath = join10(root, projEntry.name);
9363
9368
  let files;
9364
9369
  try {
9365
- files = readdirSync6(projPath);
9370
+ files = readdirSync7(projPath);
9366
9371
  } catch {
9367
9372
  continue;
9368
9373
  }
@@ -9375,7 +9380,7 @@ var init_claude2 = __esm({
9375
9380
  let mtime = st.mtimeMs;
9376
9381
  const subDir = join10(projPath, f.slice(0, -6), "subagents");
9377
9382
  if (existsSync10(subDir)) {
9378
- for (const sub of readdirSync6(subDir)) {
9383
+ for (const sub of readdirSync7(subDir)) {
9379
9384
  try {
9380
9385
  const subSt = statSync8(join10(subDir, sub));
9381
9386
  if (subSt.mtimeMs > mtime)
@@ -9480,7 +9485,7 @@ var init_claude2 = __esm({
9480
9485
 
9481
9486
  // ../engine/dist/core/backends/gemini.js
9482
9487
  import { createHash as createHash4 } from "crypto";
9483
- import { existsSync as existsSync11, readdirSync as readdirSync7, readFileSync as readFileSync6, statSync as statSync9 } from "fs";
9488
+ import { existsSync as existsSync11, readdirSync as readdirSync8, readFileSync as readFileSync6, statSync as statSync9 } from "fs";
9484
9489
  import { basename as basename9, join as join11 } from "path";
9485
9490
  function readSessionId(path, format) {
9486
9491
  try {
@@ -9594,7 +9599,7 @@ var init_gemini2 = __esm({
9594
9599
  const out = [];
9595
9600
  const seen = /* @__PURE__ */ new Map();
9596
9601
  for (const root of geminiTmpDirs()) {
9597
- for (const projDir of readdirSync7(root, { withFileTypes: true })) {
9602
+ for (const projDir of readdirSync8(root, { withFileTypes: true })) {
9598
9603
  if (!projDir.isDirectory())
9599
9604
  continue;
9600
9605
  const projectPath = projMap.get(projDir.name) || "";
@@ -9605,7 +9610,7 @@ var init_gemini2 = __esm({
9605
9610
  continue;
9606
9611
  let files;
9607
9612
  try {
9608
- files = readdirSync7(chatsDir);
9613
+ files = readdirSync8(chatsDir);
9609
9614
  } catch {
9610
9615
  continue;
9611
9616
  }
@@ -9828,7 +9833,7 @@ var init_gemini2 = __esm({
9828
9833
  return [];
9829
9834
  const projMap = this.loadProjectMap();
9830
9835
  const candidates2 = [];
9831
- for (const proj of readdirSync7(tmpRoot, { withFileTypes: true })) {
9836
+ for (const proj of readdirSync8(tmpRoot, { withFileTypes: true })) {
9832
9837
  if (!proj.isDirectory())
9833
9838
  continue;
9834
9839
  const projectPath = projMap.get(proj.name) || "";
@@ -9842,7 +9847,7 @@ var init_gemini2 = __esm({
9842
9847
  continue;
9843
9848
  let files;
9844
9849
  try {
9845
- files = readdirSync7(chats);
9850
+ files = readdirSync8(chats);
9846
9851
  } catch {
9847
9852
  continue;
9848
9853
  }
@@ -10508,7 +10513,7 @@ var init_opencode = __esm({
10508
10513
  });
10509
10514
 
10510
10515
  // ../engine/dist/core/backends/codex.js
10511
- import { readdirSync as readdirSync8, readFileSync as readFileSync7, statSync as statSync10, openSync as openSync6, readSync as readSync6, closeSync as closeSync6 } from "fs";
10516
+ import { readdirSync as readdirSync9, readFileSync as readFileSync7, statSync as statSync10, openSync as openSync6, readSync as readSync6, closeSync as closeSync6 } from "fs";
10512
10517
  import { basename as basename10, dirname as dirname10, join as join13 } from "path";
10513
10518
  function parseShellWrites(cmd) {
10514
10519
  const out = [];
@@ -10604,7 +10609,7 @@ function parseCodexPatch(input) {
10604
10609
  function* walkRollouts(root) {
10605
10610
  let entries;
10606
10611
  try {
10607
- entries = readdirSync8(root, { withFileTypes: true });
10612
+ entries = readdirSync9(root, { withFileTypes: true });
10608
10613
  } catch {
10609
10614
  return;
10610
10615
  }
@@ -10896,7 +10901,7 @@ var init_codex2 = __esm({
10896
10901
  const dayDir = located.path.substring(0, located.path.lastIndexOf("/"));
10897
10902
  let entries = [];
10898
10903
  try {
10899
- entries = readdirSync8(dayDir);
10904
+ entries = readdirSync9(dayDir);
10900
10905
  } catch {
10901
10906
  }
10902
10907
  for (const entry of entries) {
@@ -11082,7 +11087,7 @@ var init_codex2 = __esm({
11082
11087
  const scanDir = (dir) => {
11083
11088
  let entries;
11084
11089
  try {
11085
- entries = readdirSync8(dir, { withFileTypes: true });
11090
+ entries = readdirSync9(dir, { withFileTypes: true });
11086
11091
  } catch {
11087
11092
  return;
11088
11093
  }
@@ -11175,7 +11180,7 @@ var init_codex2 = __esm({
11175
11180
  if (parentId) {
11176
11181
  const dayDir = dirname10(loc.path);
11177
11182
  try {
11178
- for (const f of readdirSync8(dayDir)) {
11183
+ for (const f of readdirSync9(dayDir)) {
11179
11184
  if (!f.endsWith(".jsonl") || !f.startsWith("rollout-"))
11180
11185
  continue;
11181
11186
  const p = join13(dayDir, f);
@@ -11222,21 +11227,8 @@ var init_codex2 = __esm({
11222
11227
  });
11223
11228
 
11224
11229
  // ../engine/dist/core/backends/agy.js
11225
- import { existsSync as existsSync13, readdirSync as readdirSync9, readFileSync as readFileSync8, statSync as statSync11 } from "fs";
11230
+ import { existsSync as existsSync13, readdirSync as readdirSync10, readFileSync as readFileSync8, statSync as statSync11 } from "fs";
11226
11231
  import { basename as basename11, dirname as dirname11, join as join14 } from "path";
11227
- function getFallbackProjectPath(homeDir) {
11228
- try {
11229
- const settingsPath2 = join14(homeDir, "settings.json");
11230
- if (existsSync13(settingsPath2)) {
11231
- const json = JSON.parse(readFileSync8(settingsPath2, "utf-8"));
11232
- if (Array.isArray(json?.trustedWorkspaces) && json.trustedWorkspaces[0]) {
11233
- return json.trustedWorkspaces[0];
11234
- }
11235
- }
11236
- } catch {
11237
- }
11238
- return "";
11239
- }
11240
11232
  function agyTranscriptPath(logsDir) {
11241
11233
  const full = join14(logsDir, "transcript_full.jsonl");
11242
11234
  if (existsSync13(full))
@@ -11249,8 +11241,8 @@ function agyTranscriptPath(logsDir) {
11249
11241
  function resolveAgyProject(logsDir, homeDir) {
11250
11242
  const deriveFrom = agyTranscriptPath(logsDir);
11251
11243
  if (!deriveFrom)
11252
- return getFallbackProjectPath(homeDir);
11253
- return extractProjectPathFromTranscript(deriveFrom, homeDir) || getFallbackProjectPath(homeDir);
11244
+ return "";
11245
+ return extractProjectPathFromTranscript(deriveFrom, homeDir);
11254
11246
  }
11255
11247
  function extractProjectPathFromTranscript(path, homeDir) {
11256
11248
  let content;
@@ -11404,7 +11396,7 @@ var init_agy = __esm({
11404
11396
  for (const brainDir of agyBrainDirs()) {
11405
11397
  let sessionDirs;
11406
11398
  try {
11407
- sessionDirs = readdirSync9(brainDir);
11399
+ sessionDirs = readdirSync10(brainDir);
11408
11400
  } catch {
11409
11401
  continue;
11410
11402
  }
@@ -11679,7 +11671,7 @@ var init_agy = __esm({
11679
11671
  const candidates2 = [];
11680
11672
  let sessionDirs;
11681
11673
  try {
11682
- sessionDirs = readdirSync9(brainDir);
11674
+ sessionDirs = readdirSync10(brainDir);
11683
11675
  } catch {
11684
11676
  return [];
11685
11677
  }
@@ -11755,7 +11747,7 @@ var init_agy = __esm({
11755
11747
  });
11756
11748
 
11757
11749
  // ../engine/dist/core/backends/cursor-store.js
11758
- import { existsSync as existsSync14, readdirSync as readdirSync10, readFileSync as readFileSync9, statSync as statSync12 } from "fs";
11750
+ import { existsSync as existsSync14, readdirSync as readdirSync11, readFileSync as readFileSync9, statSync as statSync12 } from "fs";
11759
11751
  import { join as join15 } from "path";
11760
11752
  function cursorProjectSlug(absPath) {
11761
11753
  return absPath.replace(/[^a-zA-Z0-9]/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
@@ -11764,7 +11756,7 @@ function listChatsIn(chatsRoot) {
11764
11756
  const out = [];
11765
11757
  let hashDirs;
11766
11758
  try {
11767
- hashDirs = readdirSync10(chatsRoot);
11759
+ hashDirs = readdirSync11(chatsRoot);
11768
11760
  } catch {
11769
11761
  return out;
11770
11762
  }
@@ -11774,7 +11766,7 @@ function listChatsIn(chatsRoot) {
11774
11766
  try {
11775
11767
  if (!statSync12(hashPath3).isDirectory())
11776
11768
  continue;
11777
- chatIds = readdirSync10(hashPath3);
11769
+ chatIds = readdirSync11(hashPath3);
11778
11770
  } catch {
11779
11771
  continue;
11780
11772
  }
@@ -11819,7 +11811,7 @@ function findChat(chatsRoots, chatId) {
11819
11811
  for (const root of chatsRoots) {
11820
11812
  let hashDirs;
11821
11813
  try {
11822
- hashDirs = readdirSync10(root);
11814
+ hashDirs = readdirSync11(root);
11823
11815
  } catch {
11824
11816
  continue;
11825
11817
  }
@@ -12140,7 +12132,7 @@ var init_cursor_store = __esm({
12140
12132
  });
12141
12133
 
12142
12134
  // ../engine/dist/core/backends/cursor-ide.js
12143
- import { existsSync as existsSync15, readFileSync as readFileSync10, readdirSync as readdirSync11, statSync as statSync13 } from "fs";
12135
+ import { existsSync as existsSync15, readFileSync as readFileSync10, readdirSync as readdirSync12, statSync as statSync13 } from "fs";
12144
12136
  import { dirname as dirname12, join as join16 } from "path";
12145
12137
  function jsonOf(value) {
12146
12138
  if (value == null)
@@ -12203,7 +12195,7 @@ function workspaceIndex(workspaceRoots) {
12203
12195
  for (const root of workspaceRoots) {
12204
12196
  let entries;
12205
12197
  try {
12206
- entries = readdirSync11(root);
12198
+ entries = readdirSync12(root);
12207
12199
  } catch {
12208
12200
  continue;
12209
12201
  }
@@ -12290,7 +12282,7 @@ function listComposers(globalDbPath, workspaceRoots) {
12290
12282
  for (const root of workspaceRoots) {
12291
12283
  let entries;
12292
12284
  try {
12293
- entries = readdirSync11(root);
12285
+ entries = readdirSync12(root);
12294
12286
  } catch {
12295
12287
  continue;
12296
12288
  }
@@ -12964,7 +12956,7 @@ var init_credentials_env = __esm({
12964
12956
 
12965
12957
  // ../engine/dist/core/source-discovery.js
12966
12958
  import { createHash as createHash5 } from "crypto";
12967
- import { existsSync as existsSync17, readdirSync as readdirSync12, statSync as statSync15 } from "fs";
12959
+ import { existsSync as existsSync17, readdirSync as readdirSync13, statSync as statSync15 } from "fs";
12968
12960
  import { join as join18 } from "path";
12969
12961
  function sourceId(path) {
12970
12962
  return "src_" + createHash5("sha256").update(path).digest("hex").slice(0, 12);
@@ -13001,7 +12993,7 @@ function countTranscripts(root, tool) {
13001
12993
  return;
13002
12994
  let entries;
13003
12995
  try {
13004
- entries = readdirSync12(dir, { withFileTypes: true });
12996
+ entries = readdirSync13(dir, { withFileTypes: true });
13005
12997
  } catch {
13006
12998
  return;
13007
12999
  }
@@ -13071,7 +13063,7 @@ var init_source_discovery = __esm({
13071
13063
 
13072
13064
  // ../engine/dist/core/home-discovery.js
13073
13065
  import { execFileSync as execFileSync2 } from "child_process";
13074
- import { existsSync as existsSync18, readdirSync as readdirSync13, readFileSync as readFileSync12, realpathSync as realpathSync2, statSync as statSync16 } from "fs";
13066
+ import { existsSync as existsSync18, readdirSync as readdirSync14, readFileSync as readFileSync12, realpathSync as realpathSync2, statSync as statSync16 } from "fs";
13075
13067
  import { homedir as homedir5, platform as osPlatform } from "os";
13076
13068
  import { join as join19 } from "path";
13077
13069
  function candidateRoots(plat = osPlatform(), env = process.env) {
@@ -13115,7 +13107,7 @@ function dirHasTranscript(root, match, depth) {
13115
13107
  return false;
13116
13108
  let entries;
13117
13109
  try {
13118
- entries = readdirSync13(root, { withFileTypes: true });
13110
+ entries = readdirSync14(root, { withFileTypes: true });
13119
13111
  } catch {
13120
13112
  return false;
13121
13113
  }
@@ -13147,7 +13139,7 @@ function countSessions(dir, tool) {
13147
13139
  return;
13148
13140
  let entries;
13149
13141
  try {
13150
- entries = readdirSync13(d, { withFileTypes: true });
13142
+ entries = readdirSync14(d, { withFileTypes: true });
13151
13143
  } catch {
13152
13144
  return;
13153
13145
  }
@@ -13216,7 +13208,7 @@ function runningToolHomes(plat = osPlatform()) {
13216
13208
  if (plat === "linux") {
13217
13209
  let pids;
13218
13210
  try {
13219
- pids = readdirSync13("/proc").filter((p) => /^\d+$/.test(p));
13211
+ pids = readdirSync14("/proc").filter((p) => /^\d+$/.test(p));
13220
13212
  } catch {
13221
13213
  return out;
13222
13214
  }
@@ -13296,7 +13288,7 @@ function walkForHomes(dir, depth, visit) {
13296
13288
  return;
13297
13289
  let entries;
13298
13290
  try {
13299
- entries = readdirSync13(dir, { withFileTypes: true });
13291
+ entries = readdirSync14(dir, { withFileTypes: true });
13300
13292
  } catch {
13301
13293
  return;
13302
13294
  }
@@ -14049,7 +14041,7 @@ var init_transcript = __esm({
14049
14041
  // ../engine/dist/core/project-resolver.js
14050
14042
  import { execSync } from "child_process";
14051
14043
  import { createHash as createHash7 } from "crypto";
14052
- import { existsSync as existsSync21, readFileSync as readFileSync15, realpathSync as realpathSync3, readdirSync as readdirSync14, statSync as statSync19 } from "fs";
14044
+ import { existsSync as existsSync21, readFileSync as readFileSync15, realpathSync as realpathSync3, readdirSync as readdirSync15, statSync as statSync19 } from "fs";
14053
14045
  import { basename as basename12, dirname as dirname13, isAbsolute, join as join22, resolve, sep } from "path";
14054
14046
  function getProjectsConfigPath() {
14055
14047
  return join22(getDataDir(), "projects.json");
@@ -14289,7 +14281,7 @@ function countGitChildren(dir) {
14289
14281
  let count = 0;
14290
14282
  let entries;
14291
14283
  try {
14292
- entries = readdirSync14(dir);
14284
+ entries = readdirSync15(dir);
14293
14285
  } catch {
14294
14286
  return 0;
14295
14287
  }
@@ -15112,7 +15104,7 @@ var init_session_source = __esm({
15112
15104
  });
15113
15105
 
15114
15106
  // ../engine/dist/core/utils.js
15115
- import { existsSync as existsSync22, readdirSync as readdirSync15 } from "fs";
15107
+ import { existsSync as existsSync22, readdirSync as readdirSync16 } from "fs";
15116
15108
  import { homedir as homedir6 } from "os";
15117
15109
  import { join as join23 } from "path";
15118
15110
  function splitByHeaders(markdown) {
@@ -15163,7 +15155,7 @@ function getClaudeDirs() {
15163
15155
  }
15164
15156
  add(join23(home, ".claude"));
15165
15157
  try {
15166
- const entries = readdirSync15(home, { withFileTypes: true });
15158
+ const entries = readdirSync16(home, { withFileTypes: true });
15167
15159
  for (const entry of entries) {
15168
15160
  if (entry.isDirectory() && entry.name.startsWith(".claude-") && entry.name !== ".claude-code") {
15169
15161
  const candidate = join23(home, entry.name);
@@ -15193,7 +15185,7 @@ var init_utils = __esm({
15193
15185
  });
15194
15186
 
15195
15187
  // ../engine/dist/parsers/plan-source.js
15196
- import { existsSync as existsSync23, readdirSync as readdirSync16, readFileSync as readFileSync16, statSync as statSync21 } from "fs";
15188
+ import { existsSync as existsSync23, readdirSync as readdirSync17, readFileSync as readFileSync16, statSync as statSync21 } from "fs";
15197
15189
  import { homedir as homedir7 } from "os";
15198
15190
  import { join as join24, basename as basename13 } from "path";
15199
15191
  import { createHash as createHash8 } from "crypto";
@@ -15220,7 +15212,7 @@ function parseFrontmatter(content) {
15220
15212
  }
15221
15213
  function safeReaddir(dir) {
15222
15214
  try {
15223
- return readdirSync16(dir);
15215
+ return readdirSync17(dir);
15224
15216
  } catch {
15225
15217
  return [];
15226
15218
  }
@@ -15256,11 +15248,11 @@ var init_plan_source = __esm({
15256
15248
  if (!existsSync23(projectsDir))
15257
15249
  return this._knownProjectDirs;
15258
15250
  try {
15259
- const entries = readdirSync16(projectsDir, { withFileTypes: true });
15251
+ const entries = readdirSync17(projectsDir, { withFileTypes: true });
15260
15252
  for (const entry of entries) {
15261
15253
  if (!entry.isDirectory() || entry.name.startsWith("."))
15262
15254
  continue;
15263
- const projectPath = decodeProjectDirName(entry.name);
15255
+ const projectPath = resolveProjectDirName(entry.name);
15264
15256
  if (existsSync23(projectPath)) {
15265
15257
  this._knownProjectDirs.push(projectPath);
15266
15258
  }
@@ -15288,7 +15280,7 @@ var init_plan_source = __esm({
15288
15280
  for (const plansDir of this.plansDirs) {
15289
15281
  if (!existsSync23(plansDir))
15290
15282
  continue;
15291
- const files = readdirSync16(plansDir).filter((f) => f.endsWith(".md"));
15283
+ const files = readdirSync17(plansDir).filter((f) => f.endsWith(".md"));
15292
15284
  for (const file of files) {
15293
15285
  if (seenClaude.has(file))
15294
15286
  continue;
@@ -15332,7 +15324,7 @@ var init_plan_source = __esm({
15332
15324
  return;
15333
15325
  let files;
15334
15326
  try {
15335
- files = readdirSync16(plansDir).filter((f) => f.endsWith(".md"));
15327
+ files = readdirSync17(plansDir).filter((f) => f.endsWith(".md"));
15336
15328
  } catch {
15337
15329
  return;
15338
15330
  }
@@ -15379,7 +15371,7 @@ var init_plan_source = __esm({
15379
15371
  }
15380
15372
  let projDirs;
15381
15373
  try {
15382
- projDirs = readdirSync16(tmpRoot);
15374
+ projDirs = readdirSync17(tmpRoot);
15383
15375
  } catch {
15384
15376
  return;
15385
15377
  }
@@ -15388,7 +15380,7 @@ var init_plan_source = __esm({
15388
15380
  const projRoot = join24(tmpRoot, projDir);
15389
15381
  let sessions;
15390
15382
  try {
15391
- sessions = readdirSync16(projRoot);
15383
+ sessions = readdirSync17(projRoot);
15392
15384
  } catch {
15393
15385
  continue;
15394
15386
  }
@@ -15398,7 +15390,7 @@ var init_plan_source = __esm({
15398
15390
  continue;
15399
15391
  let files;
15400
15392
  try {
15401
- files = readdirSync16(plansDir).filter((f) => f.endsWith(".md"));
15393
+ files = readdirSync17(plansDir).filter((f) => f.endsWith(".md"));
15402
15394
  } catch {
15403
15395
  continue;
15404
15396
  }
@@ -15607,7 +15599,7 @@ var init_plan_source = __esm({
15607
15599
  return;
15608
15600
  let sessionDirs;
15609
15601
  try {
15610
- sessionDirs = readdirSync16(brainDir);
15602
+ sessionDirs = readdirSync17(brainDir);
15611
15603
  } catch {
15612
15604
  return;
15613
15605
  }
@@ -15621,7 +15613,7 @@ var init_plan_source = __esm({
15621
15613
  }
15622
15614
  let files;
15623
15615
  try {
15624
- files = readdirSync16(sessionPath).filter((f) => f.endsWith(".md"));
15616
+ files = readdirSync17(sessionPath).filter((f) => f.endsWith(".md"));
15625
15617
  } catch {
15626
15618
  continue;
15627
15619
  }
@@ -15658,7 +15650,7 @@ var init_plan_source = __esm({
15658
15650
  });
15659
15651
 
15660
15652
  // ../engine/dist/parsers/task-source.js
15661
- import { existsSync as existsSync24, readdirSync as readdirSync17, readFileSync as readFileSync17, statSync as statSync22 } from "fs";
15653
+ import { existsSync as existsSync24, readdirSync as readdirSync18, readFileSync as readFileSync17, statSync as statSync22 } from "fs";
15662
15654
  import { join as join25 } from "path";
15663
15655
  var MAX_CHUNK_CHARS2, TaskSource;
15664
15656
  var init_task_source = __esm({
@@ -15692,7 +15684,7 @@ var init_task_source = __esm({
15692
15684
  return;
15693
15685
  let files;
15694
15686
  try {
15695
- files = readdirSync17(todosDir).filter((f) => f.endsWith(".json"));
15687
+ files = readdirSync18(todosDir).filter((f) => f.endsWith(".json"));
15696
15688
  } catch {
15697
15689
  return;
15698
15690
  }
@@ -15741,7 +15733,7 @@ var init_task_source = __esm({
15741
15733
  async *discoverInDir(tasksDir) {
15742
15734
  if (!existsSync24(tasksDir))
15743
15735
  return;
15744
- const entries = readdirSync17(tasksDir, { withFileTypes: true });
15736
+ const entries = readdirSync18(tasksDir, { withFileTypes: true });
15745
15737
  for (const entry of entries) {
15746
15738
  if (!entry.isDirectory())
15747
15739
  continue;
@@ -15749,7 +15741,7 @@ var init_task_source = __esm({
15749
15741
  const taskDir = join25(tasksDir, sessionUuid);
15750
15742
  try {
15751
15743
  const stat3 = statSync22(taskDir);
15752
- const taskFiles = readdirSync17(taskDir).filter((f) => f.endsWith(".json"));
15744
+ const taskFiles = readdirSync18(taskDir).filter((f) => f.endsWith(".json"));
15753
15745
  if (taskFiles.length === 0)
15754
15746
  continue;
15755
15747
  const tasks = this.readTasks(taskDir, taskFiles);
@@ -15783,7 +15775,7 @@ var init_task_source = __esm({
15783
15775
  const taskDir = item.filePath;
15784
15776
  if (!existsSync24(taskDir))
15785
15777
  return [];
15786
- const taskFiles = readdirSync17(taskDir).filter((f) => f.endsWith(".json"));
15778
+ const taskFiles = readdirSync18(taskDir).filter((f) => f.endsWith(".json"));
15787
15779
  const tasks = this.readTasks(taskDir, taskFiles);
15788
15780
  if (tasks.length === 0)
15789
15781
  return [];
@@ -15894,7 +15886,7 @@ ${task.description}`.slice(0, MAX_CHUNK_CHARS2);
15894
15886
  });
15895
15887
 
15896
15888
  // ../engine/dist/parsers/claude-md-source.js
15897
- import { existsSync as existsSync25, readFileSync as readFileSync18, readdirSync as readdirSync18, statSync as statSync23 } from "fs";
15889
+ import { existsSync as existsSync25, readFileSync as readFileSync18, readdirSync as readdirSync19, statSync as statSync23 } from "fs";
15898
15890
  import { homedir as homedir8 } from "os";
15899
15891
  import { join as join26, basename as basename14, dirname as dirname14 } from "path";
15900
15892
  import { createHash as createHash9 } from "crypto";
@@ -15911,11 +15903,11 @@ function discoverProjectDirs(claudeDir) {
15911
15903
  if (!existsSync25(projectsDir))
15912
15904
  return;
15913
15905
  try {
15914
- const entries = readdirSync18(projectsDir, { withFileTypes: true });
15906
+ const entries = readdirSync19(projectsDir, { withFileTypes: true });
15915
15907
  for (const entry of entries) {
15916
15908
  if (!entry.isDirectory() || entry.name.startsWith("."))
15917
15909
  continue;
15918
- const projectPath = decodeProjectDirName(entry.name);
15910
+ const projectPath = resolveProjectDirName(entry.name);
15919
15911
  addProject(projectPath);
15920
15912
  }
15921
15913
  } catch {
@@ -15928,7 +15920,7 @@ function discoverProjectDirs(claudeDir) {
15928
15920
  const home = homedir8();
15929
15921
  scanProjectsDir(claudeBackend.projectsDir());
15930
15922
  try {
15931
- for (const entry of readdirSync18(home, { withFileTypes: true })) {
15923
+ for (const entry of readdirSync19(home, { withFileTypes: true })) {
15932
15924
  if (entry.isDirectory() && entry.name.startsWith(".claude-") && entry.name !== ".claude-code") {
15933
15925
  scanProjectsDir(join26(home, entry.name, "projects"));
15934
15926
  }
@@ -16030,7 +16022,7 @@ var init_claude_md_source = __esm({
16030
16022
  }
16031
16023
  }
16032
16024
  try {
16033
- const entries = readdirSync18(searchDir, { withFileTypes: true });
16025
+ const entries = readdirSync19(searchDir, { withFileTypes: true });
16034
16026
  for (const entry of entries) {
16035
16027
  if (!entry.isDirectory())
16036
16028
  continue;
@@ -16120,7 +16112,7 @@ var init_claude_md_source = __esm({
16120
16112
  });
16121
16113
 
16122
16114
  // ../engine/dist/parsers/agent-memory-source.js
16123
- import { existsSync as existsSync26, readFileSync as readFileSync19, readdirSync as readdirSync19, statSync as statSync24 } from "fs";
16115
+ import { existsSync as existsSync26, readFileSync as readFileSync19, readdirSync as readdirSync20, statSync as statSync24 } from "fs";
16124
16116
  import { homedir as homedir9 } from "os";
16125
16117
  import { join as join27, basename as basename15 } from "path";
16126
16118
  function parseFrontmatter2(content) {
@@ -16148,7 +16140,7 @@ function parseFrontmatter2(content) {
16148
16140
  return { fm, body };
16149
16141
  }
16150
16142
  function projectHashToPath(hashDir) {
16151
- return decodeProjectDirName(hashDir);
16143
+ return resolveProjectDirName(hashDir);
16152
16144
  }
16153
16145
  function discoverMemoryDirs() {
16154
16146
  const out = [];
@@ -16162,7 +16154,7 @@ function discoverMemoryDirs() {
16162
16154
  const home = homedir9();
16163
16155
  const claudeRoots = [claudeBackend.projectsDir()];
16164
16156
  try {
16165
- for (const entry of readdirSync19(home, { withFileTypes: true })) {
16157
+ for (const entry of readdirSync20(home, { withFileTypes: true })) {
16166
16158
  if (entry.isDirectory() && entry.name.startsWith(".claude-") && entry.name !== ".claude-code") {
16167
16159
  claudeRoots.push(join27(home, entry.name, "projects"));
16168
16160
  }
@@ -16173,7 +16165,7 @@ function discoverMemoryDirs() {
16173
16165
  if (!existsSync26(projectsDir))
16174
16166
  continue;
16175
16167
  try {
16176
- for (const entry of readdirSync19(projectsDir, { withFileTypes: true })) {
16168
+ for (const entry of readdirSync20(projectsDir, { withFileTypes: true })) {
16177
16169
  if (!entry.isDirectory() || entry.name.startsWith("."))
16178
16170
  continue;
16179
16171
  add(join27(projectsDir, entry.name, "memory"), entry.name);
@@ -16202,7 +16194,7 @@ var init_agent_memory_source = __esm({
16202
16194
  for (const { memoryDir, projectHash } of discoverMemoryDirs()) {
16203
16195
  const projectPath = projectHashToPath(projectHash);
16204
16196
  try {
16205
- for (const entry of readdirSync19(memoryDir, { withFileTypes: true })) {
16197
+ for (const entry of readdirSync20(memoryDir, { withFileTypes: true })) {
16206
16198
  if (!entry.isFile() || !entry.name.endsWith(".md"))
16207
16199
  continue;
16208
16200
  const filePath = join27(memoryDir, entry.name);
@@ -16305,7 +16297,7 @@ var init_agent_memory_source = __esm({
16305
16297
  });
16306
16298
 
16307
16299
  // ../engine/dist/parsers/history-source.js
16308
- import { existsSync as existsSync27, readdirSync as readdirSync20, statSync as statSync25 } from "fs";
16300
+ import { existsSync as existsSync27, readdirSync as readdirSync21, statSync as statSync25 } from "fs";
16309
16301
  import { createReadStream as createReadStream3 } from "fs";
16310
16302
  import { createInterface as createInterface2 } from "readline";
16311
16303
  import { homedir as homedir10 } from "os";
@@ -16332,7 +16324,7 @@ var init_history_source = __esm({
16332
16324
  };
16333
16325
  tryAdd(claudeBackend.historyFile());
16334
16326
  try {
16335
- for (const entry of readdirSync20(home, { withFileTypes: true })) {
16327
+ for (const entry of readdirSync21(home, { withFileTypes: true })) {
16336
16328
  if (entry.isDirectory() && entry.name.startsWith(".claude-") && entry.name !== ".claude-code") {
16337
16329
  tryAdd(join28(home, entry.name, "history.jsonl"));
16338
16330
  }
@@ -16489,7 +16481,7 @@ var init_history_source = __esm({
16489
16481
  });
16490
16482
 
16491
16483
  // ../engine/dist/parsers/paste-source.js
16492
- import { existsSync as existsSync28, readdirSync as readdirSync21, readFileSync as readFileSync20, statSync as statSync26 } from "fs";
16484
+ import { existsSync as existsSync28, readdirSync as readdirSync22, readFileSync as readFileSync20, statSync as statSync26 } from "fs";
16493
16485
  import { homedir as homedir11 } from "os";
16494
16486
  import { join as join29, basename as basename16 } from "path";
16495
16487
  var MAX_CHUNK_CHARS6, MAX_FILE_SIZE, PasteSource;
@@ -16515,7 +16507,7 @@ var init_paste_source = __esm({
16515
16507
  };
16516
16508
  tryAdd(claudeBackend.pasteCacheDir());
16517
16509
  try {
16518
- for (const entry of readdirSync21(home, { withFileTypes: true })) {
16510
+ for (const entry of readdirSync22(home, { withFileTypes: true })) {
16519
16511
  if (entry.isDirectory() && entry.name.startsWith(".claude-") && entry.name !== ".claude-code") {
16520
16512
  tryAdd(join29(home, entry.name, "paste-cache"));
16521
16513
  }
@@ -16532,7 +16524,7 @@ var init_paste_source = __esm({
16532
16524
  for (const cacheDir of this.cacheDirs) {
16533
16525
  if (!existsSync28(cacheDir))
16534
16526
  continue;
16535
- const files = readdirSync21(cacheDir).filter((f) => f.endsWith(".txt"));
16527
+ const files = readdirSync22(cacheDir).filter((f) => f.endsWith(".txt"));
16536
16528
  for (const file of files) {
16537
16529
  if (seen.has(file))
16538
16530
  continue;
@@ -16589,7 +16581,7 @@ var init_paste_source = __esm({
16589
16581
  });
16590
16582
 
16591
16583
  // ../engine/dist/parsers/gemini-source.js
16592
- import { existsSync as existsSync29, readdirSync as readdirSync22, readFileSync as readFileSync21, statSync as statSync27 } from "fs";
16584
+ import { existsSync as existsSync29, readdirSync as readdirSync23, readFileSync as readFileSync21, statSync as statSync27 } from "fs";
16593
16585
  import { join as join30, basename as basename17 } from "path";
16594
16586
  import { createHash as createHash10 } from "crypto";
16595
16587
  function loadGeminiProjectMap2() {
@@ -16631,13 +16623,13 @@ var init_gemini_source = __esm({
16631
16623
  return;
16632
16624
  const seen = /* @__PURE__ */ new Set();
16633
16625
  try {
16634
- for (const projectDirEntry of readdirSync22(tmpDir, { withFileTypes: true })) {
16626
+ for (const projectDirEntry of readdirSync23(tmpDir, { withFileTypes: true })) {
16635
16627
  if (!projectDirEntry.isDirectory())
16636
16628
  continue;
16637
16629
  const chatsDir = join30(tmpDir, projectDirEntry.name, "chats");
16638
16630
  if (!existsSync29(chatsDir))
16639
16631
  continue;
16640
- for (const file of readdirSync22(chatsDir)) {
16632
+ for (const file of readdirSync23(chatsDir)) {
16641
16633
  if (!file.endsWith(".json") || !file.startsWith("session-"))
16642
16634
  continue;
16643
16635
  const filePath = join30(chatsDir, file);
@@ -16772,7 +16764,7 @@ var init_gemini_source = __esm({
16772
16764
  });
16773
16765
 
16774
16766
  // ../engine/dist/parsers/gemini-brain-source.js
16775
- import { existsSync as existsSync30, readdirSync as readdirSync23, readFileSync as readFileSync22, statSync as statSync28 } from "fs";
16767
+ import { existsSync as existsSync30, readdirSync as readdirSync24, readFileSync as readFileSync22, statSync as statSync28 } from "fs";
16776
16768
  import { join as join31 } from "path";
16777
16769
  var MAX_CHUNK_CHARS8, GeminiBrainSource;
16778
16770
  var init_gemini_brain_source = __esm({
@@ -16793,12 +16785,12 @@ var init_gemini_brain_source = __esm({
16793
16785
  return;
16794
16786
  if (!existsSync30(this.brainDir))
16795
16787
  return;
16796
- const sessions = readdirSync23(this.brainDir, { withFileTypes: true });
16788
+ const sessions = readdirSync24(this.brainDir, { withFileTypes: true });
16797
16789
  for (const entry of sessions) {
16798
16790
  if (!entry.isDirectory())
16799
16791
  continue;
16800
16792
  const sessionDir = join31(this.brainDir, entry.name);
16801
- const files = readdirSync23(sessionDir).filter((f) => f.endsWith(".md") && !f.includes(".resolved") && !f.includes(".metadata"));
16793
+ const files = readdirSync24(sessionDir).filter((f) => f.endsWith(".md") && !f.includes(".resolved") && !f.includes(".metadata"));
16802
16794
  if (files.length === 0)
16803
16795
  continue;
16804
16796
  for (const file of files) {
@@ -17186,7 +17178,7 @@ var init_opencode_todo_source = __esm({
17186
17178
  });
17187
17179
 
17188
17180
  // ../engine/dist/parsers/codex-session-source.js
17189
- import { existsSync as existsSync33, readdirSync as readdirSync24, readFileSync as readFileSync23, statSync as statSync29 } from "fs";
17181
+ import { existsSync as existsSync33, readdirSync as readdirSync25, readFileSync as readFileSync23, statSync as statSync29 } from "fs";
17190
17182
  import { join as join32, basename as basename18 } from "path";
17191
17183
  function getCodexSessionsDir() {
17192
17184
  return codexBackend.sessionsDir();
@@ -17407,7 +17399,7 @@ var init_codex_session_source = __esm({
17407
17399
  const results = [];
17408
17400
  if (!existsSync33(dir))
17409
17401
  return results;
17410
- for (const entry of readdirSync24(dir, { withFileTypes: true })) {
17402
+ for (const entry of readdirSync25(dir, { withFileTypes: true })) {
17411
17403
  const fullPath = join32(dir, entry.name);
17412
17404
  if (entry.isDirectory()) {
17413
17405
  results.push(...this.collectJsonlFiles(fullPath));
@@ -17422,7 +17414,7 @@ var init_codex_session_source = __esm({
17422
17414
  });
17423
17415
 
17424
17416
  // ../engine/dist/parsers/diary-source.js
17425
- import { existsSync as existsSync34, mkdirSync as mkdirSync5, readdirSync as readdirSync25, readFileSync as readFileSync24, writeFileSync as writeFileSync4, statSync as statSync30 } from "fs";
17417
+ import { existsSync as existsSync34, mkdirSync as mkdirSync5, readdirSync as readdirSync26, readFileSync as readFileSync24, writeFileSync as writeFileSync4, statSync as statSync30 } from "fs";
17426
17418
  import { join as join33, basename as basename19 } from "path";
17427
17419
  var MAX_CHUNK_CHARS11, DiarySource;
17428
17420
  var init_diary_source = __esm({
@@ -17440,10 +17432,10 @@ var init_diary_source = __esm({
17440
17432
  async *discover() {
17441
17433
  if (!existsSync34(this.diaryDir))
17442
17434
  return;
17443
- const agents = readdirSync25(this.diaryDir, { withFileTypes: true }).filter((d) => d.isDirectory());
17435
+ const agents = readdirSync26(this.diaryDir, { withFileTypes: true }).filter((d) => d.isDirectory());
17444
17436
  for (const agentDir of agents) {
17445
17437
  const agentPath2 = join33(this.diaryDir, agentDir.name);
17446
- const files = readdirSync25(agentPath2).filter((f) => f.endsWith(".json"));
17438
+ const files = readdirSync26(agentPath2).filter((f) => f.endsWith(".json"));
17447
17439
  for (const file of files) {
17448
17440
  const filePath = join33(agentPath2, file);
17449
17441
  try {
@@ -17534,7 +17526,7 @@ var init_diary_source = __esm({
17534
17526
  const agentDir = join33(dir, agentName.toLowerCase().replace(/[^a-z0-9_-]/g, "_"));
17535
17527
  if (!existsSync34(agentDir))
17536
17528
  return [];
17537
- const files = readdirSync25(agentDir).filter((f) => f.endsWith(".json")).sort().reverse().slice(0, lastN);
17529
+ const files = readdirSync26(agentDir).filter((f) => f.endsWith(".json")).sort().reverse().slice(0, lastN);
17538
17530
  const entries = [];
17539
17531
  for (const file of files) {
17540
17532
  try {
@@ -17583,7 +17575,7 @@ var init_redact_inline = __esm({
17583
17575
  });
17584
17576
 
17585
17577
  // ../engine/dist/parsers/skills-source.js
17586
- import { existsSync as existsSync35, readdirSync as readdirSync26, readFileSync as readFileSync25, statSync as statSync31 } from "fs";
17578
+ import { existsSync as existsSync35, readdirSync as readdirSync27, readFileSync as readFileSync25, statSync as statSync31 } from "fs";
17587
17579
  import { homedir as homedir12 } from "os";
17588
17580
  import { join as join34 } from "path";
17589
17581
  function rebuildBody(content) {
@@ -17664,7 +17656,7 @@ var init_skills_source = __esm({
17664
17656
  return;
17665
17657
  const codexPluginsDir = codexBackend.pluginsDir();
17666
17658
  if (existsSync35(codexPluginsDir)) {
17667
- for (const pluginName of readdirSync26(codexPluginsDir)) {
17659
+ for (const pluginName of readdirSync27(codexPluginsDir)) {
17668
17660
  const skillsDir = join34(codexPluginsDir, pluginName, "skills");
17669
17661
  if (!existsSync35(skillsDir))
17670
17662
  continue;
@@ -17675,7 +17667,7 @@ var init_skills_source = __esm({
17675
17667
  async *fromSkillRoot(root, pluginName) {
17676
17668
  let entries;
17677
17669
  try {
17678
- entries = readdirSync26(root.path);
17670
+ entries = readdirSync27(root.path);
17679
17671
  } catch {
17680
17672
  return;
17681
17673
  }
@@ -17709,14 +17701,14 @@ var init_skills_source = __esm({
17709
17701
  }
17710
17702
  const subdirs = {};
17711
17703
  try {
17712
- for (const sub of readdirSync26(skillDir)) {
17704
+ for (const sub of readdirSync27(skillDir)) {
17713
17705
  const subPath = join34(skillDir, sub);
17714
17706
  try {
17715
17707
  const ss = statSync31(subPath);
17716
17708
  if (ss.isDirectory()) {
17717
17709
  let count = 0;
17718
17710
  try {
17719
- count = readdirSync26(subPath).length;
17711
+ count = readdirSync27(subPath).length;
17720
17712
  } catch {
17721
17713
  }
17722
17714
  subdirs[sub] = count;
@@ -17782,7 +17774,7 @@ var init_skills_source = __esm({
17782
17774
  });
17783
17775
 
17784
17776
  // ../engine/dist/parsers/mcps-source.js
17785
- import { existsSync as existsSync36, readdirSync as readdirSync27, readFileSync as readFileSync26, statSync as statSync32 } from "fs";
17777
+ import { existsSync as existsSync36, readdirSync as readdirSync28, readFileSync as readFileSync26, statSync as statSync32 } from "fs";
17786
17778
  import { homedir as homedir13 } from "os";
17787
17779
  import { join as join35 } from "path";
17788
17780
  function readJson(path) {
@@ -17896,7 +17888,7 @@ var init_mcps_source = __esm({
17896
17888
  yield* this.fromCodexToml(codexBackend.configToml());
17897
17889
  const pluginsDir = codexBackend.pluginsDir();
17898
17890
  if (existsSync36(pluginsDir)) {
17899
- for (const plugin of readdirSync27(pluginsDir)) {
17891
+ for (const plugin of readdirSync28(pluginsDir)) {
17900
17892
  const mcpPath = join35(pluginsDir, plugin, ".mcp.json");
17901
17893
  yield* this.fromObject(readJson(mcpPath)?.mcpServers, {
17902
17894
  tool: "codex",
@@ -18120,7 +18112,7 @@ var init_toolkit_format = __esm({
18120
18112
  });
18121
18113
 
18122
18114
  // ../engine/dist/parsers/slash-commands-source.js
18123
- import { existsSync as existsSync37, readdirSync as readdirSync28, readFileSync as readFileSync27, statSync as statSync33 } from "fs";
18115
+ import { existsSync as existsSync37, readdirSync as readdirSync29, readFileSync as readFileSync27, statSync as statSync33 } from "fs";
18124
18116
  import { join as join36, basename as basename20 } from "path";
18125
18117
  function rebuildBody2(content) {
18126
18118
  const { text, redacted } = redactInlineSecrets(content);
@@ -18175,10 +18167,10 @@ var init_slash_commands_source = __esm({
18175
18167
  const projectsRoot = claudeBackend.projectsDir();
18176
18168
  if (existsSync37(projectsRoot)) {
18177
18169
  try {
18178
- for (const entry of readdirSync28(projectsRoot, { withFileTypes: true })) {
18170
+ for (const entry of readdirSync29(projectsRoot, { withFileTypes: true })) {
18179
18171
  if (!entry.isDirectory() || entry.name.startsWith("."))
18180
18172
  continue;
18181
- const projectPath = decodeProjectDirName(entry.name);
18173
+ const projectPath = resolveProjectDirName(entry.name);
18182
18174
  const cmdDir = join36(projectPath, ".claude", "commands");
18183
18175
  if (existsSync37(cmdDir))
18184
18176
  roots.push({ path: cmdDir, tool: "claude", scope: "project", projectPath, format: "md" });
@@ -18206,7 +18198,7 @@ var init_slash_commands_source = __esm({
18206
18198
  const ext = root.format === "toml" ? ".toml" : ".md";
18207
18199
  let files;
18208
18200
  try {
18209
- files = readdirSync28(root.path).filter((f) => f.endsWith(ext));
18201
+ files = readdirSync29(root.path).filter((f) => f.endsWith(ext));
18210
18202
  } catch {
18211
18203
  continue;
18212
18204
  }
@@ -18266,7 +18258,7 @@ var init_slash_commands_source = __esm({
18266
18258
  });
18267
18259
 
18268
18260
  // ../engine/dist/parsers/subagents-source.js
18269
- import { existsSync as existsSync38, readdirSync as readdirSync29, readFileSync as readFileSync28, statSync as statSync34 } from "fs";
18261
+ import { existsSync as existsSync38, readdirSync as readdirSync30, readFileSync as readFileSync28, statSync as statSync34 } from "fs";
18270
18262
  import { join as join37, basename as basename21 } from "path";
18271
18263
  function rebuildBody3(content) {
18272
18264
  const { text, redacted } = redactInlineSecrets(content);
@@ -18323,10 +18315,10 @@ var init_subagents_source = __esm({
18323
18315
  const projectsRoot = claudeBackend.projectsDir();
18324
18316
  if (existsSync38(projectsRoot)) {
18325
18317
  try {
18326
- for (const entry of readdirSync29(projectsRoot, { withFileTypes: true })) {
18318
+ for (const entry of readdirSync30(projectsRoot, { withFileTypes: true })) {
18327
18319
  if (!entry.isDirectory() || entry.name.startsWith("."))
18328
18320
  continue;
18329
- const projectPath = decodeProjectDirName(entry.name);
18321
+ const projectPath = resolveProjectDirName(entry.name);
18330
18322
  const agentDir = join37(projectPath, ".claude", "agents");
18331
18323
  if (existsSync38(agentDir))
18332
18324
  roots.push({ path: agentDir, tool: "claude", scope: "project", projectPath, format: "md" });
@@ -18354,7 +18346,7 @@ var init_subagents_source = __esm({
18354
18346
  const ext = root.format === "toml" ? ".toml" : ".md";
18355
18347
  let files;
18356
18348
  try {
18357
- files = readdirSync29(root.path).filter((f) => f.endsWith(ext));
18349
+ files = readdirSync30(root.path).filter((f) => f.endsWith(ext));
18358
18350
  } catch {
18359
18351
  continue;
18360
18352
  }
@@ -18415,7 +18407,7 @@ var init_subagents_source = __esm({
18415
18407
  });
18416
18408
 
18417
18409
  // ../engine/dist/parsers/hooks-source.js
18418
- import { existsSync as existsSync39, readFileSync as readFileSync29, readdirSync as readdirSync30, statSync as statSync35 } from "fs";
18410
+ import { existsSync as existsSync39, readFileSync as readFileSync29, readdirSync as readdirSync31, statSync as statSync35 } from "fs";
18419
18411
  import { join as join38 } from "path";
18420
18412
  function readJson2(path) {
18421
18413
  if (!existsSync39(path))
@@ -18442,10 +18434,10 @@ var init_hooks_source = __esm({
18442
18434
  const projectsRoot = claudeBackend.projectsDir();
18443
18435
  if (existsSync39(projectsRoot)) {
18444
18436
  try {
18445
- for (const entry of readdirSync30(projectsRoot, { withFileTypes: true })) {
18437
+ for (const entry of readdirSync31(projectsRoot, { withFileTypes: true })) {
18446
18438
  if (!entry.isDirectory() || entry.name.startsWith("."))
18447
18439
  continue;
18448
- const projectPath = decodeProjectDirName(entry.name);
18440
+ const projectPath = resolveProjectDirName(entry.name);
18449
18441
  const settingsPath2 = join38(projectPath, ".claude", "settings.json");
18450
18442
  if (existsSync39(settingsPath2)) {
18451
18443
  yield* this.fromSettings(settingsPath2, "project", projectPath);
@@ -18538,7 +18530,7 @@ var init_hooks_source = __esm({
18538
18530
  });
18539
18531
 
18540
18532
  // ../engine/dist/parsers/plugins-source.js
18541
- import { existsSync as existsSync40, readFileSync as readFileSync30, readdirSync as readdirSync31, statSync as statSync36 } from "fs";
18533
+ import { existsSync as existsSync40, readFileSync as readFileSync30, readdirSync as readdirSync32, statSync as statSync36 } from "fs";
18542
18534
  import { homedir as homedir14 } from "os";
18543
18535
  import { join as join39 } from "path";
18544
18536
  function readJson3(path) {
@@ -18600,7 +18592,7 @@ var init_plugins_source = __esm({
18600
18592
  if (isSourceEnabled("gemini", "extensions") && existsSync40(gemRoot)) {
18601
18593
  let entries;
18602
18594
  try {
18603
- entries = readdirSync31(gemRoot);
18595
+ entries = readdirSync32(gemRoot);
18604
18596
  } catch {
18605
18597
  entries = [];
18606
18598
  }
@@ -18648,7 +18640,7 @@ var init_plugins_source = __esm({
18648
18640
  if (isSourceEnabled("codex", "plugins") && existsSync40(codexPluginsRoot)) {
18649
18641
  let entries;
18650
18642
  try {
18651
- entries = readdirSync31(codexPluginsRoot);
18643
+ entries = readdirSync32(codexPluginsRoot);
18652
18644
  } catch {
18653
18645
  entries = [];
18654
18646
  }
@@ -18804,7 +18796,7 @@ var init_extractor_version = __esm({
18804
18796
  command: 1
18805
18797
  };
18806
18798
  TOOL_EXTRACTOR_BUMP = {
18807
- agy: 2,
18799
+ agy: 3,
18808
18800
  claude: 1,
18809
18801
  codex: 1
18810
18802
  };
@@ -19233,7 +19225,7 @@ var init_http = __esm({
19233
19225
  CLI_VERSION = JSON.parse(readFileSync33(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
19234
19226
  } catch {
19235
19227
  try {
19236
- if (true) CLI_VERSION = "0.5.30";
19228
+ if (true) CLI_VERSION = "0.5.32";
19237
19229
  } catch {
19238
19230
  }
19239
19231
  }
@@ -19579,9 +19571,9 @@ function cooldownFor(failures) {
19579
19571
  function breakerState(serverUrl, now = Date.now()) {
19580
19572
  const s = state.get(key(serverUrl));
19581
19573
  if (!s || s.openUntil <= now) {
19582
- return { open: false, retryInMs: 0, failures: s?.failures ?? 0, lastError: s?.lastError ?? "" };
19574
+ return { open: false, retryInMs: 0, failures: s?.failures ?? 0, lastError: s?.lastError ?? "", tripped: false };
19583
19575
  }
19584
- return { open: true, retryInMs: s.openUntil - now, failures: s.failures, lastError: s.lastError };
19576
+ return { open: true, retryInMs: s.openUntil - now, failures: s.failures, lastError: s.lastError, tripped: false };
19585
19577
  }
19586
19578
  function noteTargetSuccess(serverUrl) {
19587
19579
  state.delete(key(serverUrl));
@@ -19593,11 +19585,11 @@ function noteTargetFailure(serverUrl, error, now = Date.now()) {
19593
19585
  const lastError = error.slice(0, 200);
19594
19586
  if (failures < TRIP_AFTER_FAILURES) {
19595
19587
  state.set(k, { failures, openUntil: 0, lastError });
19596
- return { open: false, retryInMs: 0, failures, lastError };
19588
+ return { open: false, retryInMs: 0, failures, lastError, tripped: false };
19597
19589
  }
19598
19590
  const cooldown = cooldownFor(failures);
19599
19591
  state.set(k, { failures, openUntil: now + cooldown, lastError });
19600
- return { open: true, retryInMs: cooldown, failures, lastError };
19592
+ return { open: true, retryInMs: cooldown, failures, lastError, tripped: failures === TRIP_AFTER_FAILURES };
19601
19593
  }
19602
19594
  function breakerNotice(serverUrl, v) {
19603
19595
  if (!v.open) return null;
@@ -19724,6 +19716,14 @@ async function flush() {
19724
19716
  }
19725
19717
  }));
19726
19718
  }
19719
+ function stableMark(value) {
19720
+ try {
19721
+ const { createHash: createHash17 } = __require("node:crypto");
19722
+ return createHash17("sha256").update(value).digest("hex").slice(0, 12);
19723
+ } catch {
19724
+ return "";
19725
+ }
19726
+ }
19727
19727
  function hashHost() {
19728
19728
  try {
19729
19729
  const { createHash: createHash17 } = __require("node:crypto");
@@ -19741,7 +19741,7 @@ var init_telemetry = __esm({
19741
19741
  init_sync_client();
19742
19742
  cliVersion = () => {
19743
19743
  try {
19744
- return true ? "0.5.30" : "dev";
19744
+ return true ? "0.5.32" : "dev";
19745
19745
  } catch {
19746
19746
  return "dev";
19747
19747
  }
@@ -20024,7 +20024,7 @@ __export(auto_update_exports, {
20024
20024
  import { execSync as execSync2 } from "node:child_process";
20025
20025
  import { readFileSync as readFileSync36 } from "node:fs";
20026
20026
  import { fileURLToPath as fileURLToPath2 } from "node:url";
20027
- import { writeFileSync as writeFileSync8, mkdtempSync as mkdtempSync3, rmSync as rmSync5, readdirSync as readdirSync32, statSync as statSync38 } from "node:fs";
20027
+ import { writeFileSync as writeFileSync8, mkdtempSync as mkdtempSync3, rmSync as rmSync5, readdirSync as readdirSync33, statSync as statSync38 } from "node:fs";
20028
20028
  import { join as join43, dirname as dirname18, sep as sep2 } from "node:path";
20029
20029
  import { tmpdir as tmpdir2 } from "node:os";
20030
20030
  import { createHash as createHash11 } from "node:crypto";
@@ -20069,7 +20069,7 @@ function sweepStaleStaging(root = tmpdir2(), now = Date.now()) {
20069
20069
  let removed = 0;
20070
20070
  let entries;
20071
20071
  try {
20072
- entries = readdirSync32(root);
20072
+ entries = readdirSync33(root);
20073
20073
  } catch {
20074
20074
  return 0;
20075
20075
  }
@@ -20079,7 +20079,7 @@ function sweepStaleStaging(root = tmpdir2(), now = Date.now()) {
20079
20079
  try {
20080
20080
  const st = statSync38(dir);
20081
20081
  if (!st.isDirectory() || now - st.mtimeMs < COLD_MS) continue;
20082
- const inside = readdirSync32(dir);
20082
+ const inside = readdirSync33(dir);
20083
20083
  if (inside.length > 1 || inside.length === 1 && inside[0] !== "chat-recall.tgz") continue;
20084
20084
  rmSync5(dir, { recursive: true, force: true });
20085
20085
  removed++;
@@ -20168,7 +20168,17 @@ async function runAutoUpdate(base2, authHeaders, ownVersion3, deps) {
20168
20168
  }
20169
20169
  const effectiveOwn = newerOf(ownVersion3, installedVersion());
20170
20170
  const plan = planAutoUpdate(base2, caps, effectiveOwn, process.env.CHAT_RECALL_AUTO_UPDATE);
20171
- if (!plan.update) return { updated: false, reason: plan.reason };
20171
+ if (!plan.update) {
20172
+ if (/disabled|no CLI release/.test(plan.reason) && !reportedStandingSkip.has(base2)) {
20173
+ reportedStandingSkip.add(base2);
20174
+ try {
20175
+ const { reportClientEvent: reportClientEvent2 } = await Promise.resolve().then(() => (init_client_events(), client_events_exports));
20176
+ reportClientEvent2("auto_update_skipped", { message: `${plan.reason} (server offers ${caps.cli?.version ?? "?"}, this device runs ${effectiveOwn})` });
20177
+ } catch {
20178
+ }
20179
+ }
20180
+ return { updated: false, reason: plan.reason };
20181
+ }
20172
20182
  const result = await executeAutoUpdate(plan, {
20173
20183
  download: deps?.download ?? realDownload,
20174
20184
  install: deps?.install ?? realInstall,
@@ -20184,33 +20194,49 @@ async function runAutoUpdate(base2, authHeaders, ownVersion3, deps) {
20184
20194
  }
20185
20195
  return result;
20186
20196
  }
20187
- var tarballUrl;
20197
+ var tarballUrl, reportedStandingSkip;
20188
20198
  var init_auto_update = __esm({
20189
20199
  "src/auto-update.ts"() {
20190
20200
  "use strict";
20191
20201
  init_http();
20192
20202
  tarballUrl = (base2) => `${base2.replace(/\/+$/, "")}/install/chat-recall.tgz`;
20203
+ reportedStandingSkip = /* @__PURE__ */ new Set();
20193
20204
  }
20194
20205
  });
20195
20206
 
20196
20207
  // src/sync-client.ts
20197
20208
  import { join as join44, dirname as dirname19, basename as basename22 } from "node:path";
20198
- import { readFileSync as readFileSync37, writeFileSync as writeFileSync9, mkdirSync as mkdirSync9, mkdtempSync as mkdtempSync4, rmSync as rmSync6, chmodSync as chmodSync3, unlinkSync as unlinkSync2, readdirSync as readdirSync33, statSync as statSync39 } from "node:fs";
20209
+ import { readFileSync as readFileSync37, writeFileSync as writeFileSync9, mkdirSync as mkdirSync9, mkdtempSync as mkdtempSync4, rmSync as rmSync6, chmodSync as chmodSync3, unlinkSync as unlinkSync2, readdirSync as readdirSync34, statSync as statSync39 } from "node:fs";
20199
20210
  import { tmpdir as tmpdir3, hostname as hostname2 } from "node:os";
20200
20211
  import { createHash as createHash12 } from "node:crypto";
20201
20212
  import { fileURLToPath as fileURLToPath3 } from "node:url";
20202
20213
  import { gzipSync as gzipSync3 } from "zlib";
20203
- function classifyError(msg) {
20214
+ function classedError(errorClass, message) {
20215
+ const e = new Error(message);
20216
+ Object.defineProperty(e, ERROR_CLASS, { value: errorClass, enumerable: false });
20217
+ return e;
20218
+ }
20219
+ function taggedClass(err) {
20220
+ const v = err?.[ERROR_CLASS];
20221
+ return typeof v === "string" && v ? v : null;
20222
+ }
20223
+ function isStandingFailure(err) {
20224
+ const c = taggedClass(err);
20225
+ return c !== null && STANDING_FAILURE.has(c);
20226
+ }
20227
+ function classifyError(msg, err) {
20228
+ const tagged = taggedClass(err);
20229
+ if (tagged) return tagged;
20204
20230
  const m = msg.toLowerCase();
20205
20231
  if (m.includes("429")) return "rate_limited";
20206
20232
  if (m.includes("402")) return "payment_required";
20207
20233
  if (m.includes("401") || m.includes("403") || m.includes("token")) return "auth";
20208
- if (m.includes("timed out") || m.includes("etimedout")) return "timeout";
20234
+ if (m.includes("timed out") || m.includes("etimedout") || m.includes("aborted due to timeout")) return "timeout";
20209
20235
  if (m.includes("econnrefused")) return "refused";
20210
20236
  if (m.includes("enotfound") || m.includes("dns")) return "dns";
20211
20237
  if (m.includes("fetch failed") || m.includes("econnreset")) return "network";
20212
- if (m.includes("plain http") || m.includes("https")) return "insecure_transport";
20213
- if (/5\d\d/.test(m)) return "server_error";
20238
+ if (m.includes("over plain http") || m.includes("unsupported scheme")) return "insecure_transport";
20239
+ if (/\b5\d\d\b/.test(m)) return "server_error";
20214
20240
  return "other";
20215
20241
  }
20216
20242
  function loadAllCredentials() {
@@ -20397,17 +20423,23 @@ async function syncSessions(opts = {}) {
20397
20423
  let agg = null;
20398
20424
  const errors = [];
20399
20425
  const skippedTargets = [];
20426
+ const perTarget = {};
20400
20427
  for (const cred of targets) {
20401
20428
  const verdict = breakerState(cred.serverUrl);
20402
20429
  if (verdict.open) {
20403
20430
  const notice = breakerNotice(cred.serverUrl, verdict);
20404
20431
  if (notice) console.error(`[sync] ${notice}`);
20405
20432
  skippedTargets.push(cred.serverUrl);
20433
+ perTarget[cred.serverUrl] = {
20434
+ ok: false,
20435
+ error: notice ?? `in failure cooldown for ~${Math.max(1, Math.round(verdict.retryInMs / 6e4))}m`
20436
+ };
20406
20437
  continue;
20407
20438
  }
20408
20439
  try {
20409
20440
  const r = await syncToTarget(cred, opts);
20410
20441
  noteTargetSuccess(cred.serverUrl);
20442
+ perTarget[cred.serverUrl] = { ok: true };
20411
20443
  agg = agg ? {
20412
20444
  uploaded: agg.uploaded + r.uploaded,
20413
20445
  skipped: agg.skipped + r.skipped,
@@ -20424,14 +20456,20 @@ async function syncSessions(opts = {}) {
20424
20456
  } catch (e) {
20425
20457
  const msg = e instanceof Error ? e.message : String(e);
20426
20458
  errors.push(`${cred.serverUrl}: ${msg}`);
20459
+ perTarget[cred.serverUrl] = { ok: false, error: msg };
20427
20460
  const next = noteTargetFailure(cred.serverUrl, msg);
20428
20461
  const notice = breakerNotice(cred.serverUrl, next);
20429
20462
  if (notice) console.error(`[sync] ${notice}`);
20430
20463
  record({
20431
- kind: next.open ? "breaker_trip" : "target_failure",
20464
+ // `tripped`, not `open`: an open breaker re-opens on every attempt until
20465
+ // a success clears it, so `open` counted elapsed time. Every failure is
20466
+ // still reported — as `target_failure`, carrying the streak in
20467
+ // `failures` — so nothing becomes invisible, it just stops being counted
20468
+ // as a fresh incident.
20469
+ kind: next.tripped ? "breaker_trip" : "target_failure",
20432
20470
  failures: next.failures,
20433
20471
  retryInMs: next.retryInMs,
20434
- errorClass: classifyError(msg),
20472
+ errorClass: classifyError(msg, e),
20435
20473
  local: isLocalHost(cred.serverUrl) ? 1 : 0
20436
20474
  });
20437
20475
  }
@@ -20462,7 +20500,7 @@ async function syncSessions(opts = {}) {
20462
20500
  ${errors.join("\n ")}`);
20463
20501
  if (errors.length > 0) console.error(`[sync] ${errors.length} target(s) failed (others succeeded):
20464
20502
  ${errors.join("\n ")}`);
20465
- return agg;
20503
+ return { ...agg, perTarget };
20466
20504
  }
20467
20505
  async function postFieldBatch(base2, token, rows) {
20468
20506
  const headers = { "content-type": "application/json" };
@@ -20514,7 +20552,7 @@ function reapStaleScanDirs(dir = tmpdir3(), maxAgeMs = 6 * 36e5, now = Date.now(
20514
20552
  let reaped = 0;
20515
20553
  let names;
20516
20554
  try {
20517
- names = readdirSync33(dir);
20555
+ names = readdirSync34(dir);
20518
20556
  } catch {
20519
20557
  return 0;
20520
20558
  }
@@ -20622,7 +20660,7 @@ async function syncToTarget(cred, opts = {}) {
20622
20660
  }
20623
20661
  async function syncToTargetInScope(cred, opts = {}) {
20624
20662
  const risk = transportRisk(cred.serverUrl);
20625
- if (risk) throw new Error(risk);
20663
+ if (risk) throw classedError("insecure_transport", risk);
20626
20664
  const sync = loadSettings().sync;
20627
20665
  const serverCfg = await fetchTenantSyncConfig(cred);
20628
20666
  const excludeTools = /* @__PURE__ */ new Set([...sync?.excludeTools ?? [], ...serverCfg.excludeTools]);
@@ -20722,7 +20760,7 @@ async function syncToTargetInScope(cred, opts = {}) {
20722
20760
  const retryable = res.status === 429 || res.status >= 500;
20723
20761
  const text = await res.text().catch(() => "");
20724
20762
  if (res.status === 401 || res.status === 403) {
20725
- throw new Error(`server rejected this machine's device token (HTTP ${res.status} \u2014 revoked?). Reconnect with: chat-recall login ${base2}`);
20763
+ throw classedError("auth", `server rejected this machine's device token (HTTP ${res.status} \u2014 revoked?). Reconnect with: chat-recall login ${base2}`);
20726
20764
  }
20727
20765
  if (res.status === 402) {
20728
20766
  let detail = text;
@@ -20736,7 +20774,7 @@ async function syncToTargetInScope(cred, opts = {}) {
20736
20774
  ${body2.upgradeUrl}`;
20737
20775
  } catch {
20738
20776
  }
20739
- throw new Error(`sync paused by the server: ${detail}`);
20777
+ throw classedError("payment_required", `sync paused by the server: ${detail}`);
20740
20778
  }
20741
20779
  if (!retryable) throw new Error(`sync failed: HTTP ${res.status} ${text}`);
20742
20780
  if (attempt >= RETRY_DELAYS_MS.length) throw new Error(`sync failed after ${attempt + 1} attempts: HTTP ${res.status} ${text}`);
@@ -20746,7 +20784,7 @@ async function syncToTargetInScope(cred, opts = {}) {
20746
20784
  await sleep(waitMs);
20747
20785
  continue;
20748
20786
  } catch (err) {
20749
- const fatal = err instanceof Error && /HTTP 4\d\d|sync failed after/.test(err.message);
20787
+ const fatal = isStandingFailure(err) || err instanceof Error && /HTTP 4\d\d|sync failed after/.test(err.message);
20750
20788
  if (fatal || attempt >= RETRY_DELAYS_MS.length) throw err;
20751
20789
  console.error(`[sync] upload attempt ${attempt + 1} failed (${err instanceof Error ? err.message : err}) \u2014 retrying in ${RETRY_DELAYS_MS[attempt] / 1e3}s`);
20752
20790
  await sleep(RETRY_DELAYS_MS[attempt]);
@@ -21285,7 +21323,12 @@ async function buildConversationSync(ref, mtime, opts = {}) {
21285
21323
  const containerBytes = built ? built.files.reduce((n, f) => n + Buffer.byteLength(f.text), 0) : 0;
21286
21324
  if (containerBytes > FULL_BUILD_MAX_BYTES) {
21287
21325
  console.error(`[sync] ${ref.prefixedId} is ${(containerBytes / 1048576).toFixed(0)}MB (over the ${(FULL_BUILD_MAX_BYTES / 1048576).toFixed(0)}MB ceiling) \u2014 shipping without the raw archive and derived data to keep the walk in memory`);
21288
- record({ kind: "oversized_session", mb: Math.round(containerBytes / 1048576), tool: ref.toolId });
21326
+ record({
21327
+ kind: "oversized_session",
21328
+ mb: Math.round(containerBytes / 1048576),
21329
+ tool: ref.toolId,
21330
+ dedupeKey: stableMark(ref.prefixedId)
21331
+ });
21289
21332
  includeRaw = false;
21290
21333
  includeMeta = false;
21291
21334
  }
@@ -21596,7 +21639,7 @@ async function syncIncremental(opts = {}) {
21596
21639
  lock.release();
21597
21640
  }
21598
21641
  }
21599
- var ownVersion, walkProgressForUpload, lastServerPackSpec, credPath, _securityConfigCache, SECURITY_CONFIG_TTL_MS, _syncConfigCache, EMPTY_SYNC_CONFIG, SYNC_RULES_REFUSAL, hashPath, MAX_DERIVED_ROW_BYTES, isLocalHost, CAPS_TTL_MS, capsOk, advertisedIngestConc, advertisedGzipBody, FULL_BUILD_MAX_BYTES, FULL_BUILD_TAIL_BYTES, BATCH_SCAN_MAX_BYTES;
21642
+ var ownVersion, ERROR_CLASS, STANDING_FAILURE, walkProgressForUpload, lastServerPackSpec, credPath, _securityConfigCache, SECURITY_CONFIG_TTL_MS, _syncConfigCache, EMPTY_SYNC_CONFIG, SYNC_RULES_REFUSAL, hashPath, MAX_DERIVED_ROW_BYTES, isLocalHost, CAPS_TTL_MS, capsOk, advertisedIngestConc, advertisedGzipBody, FULL_BUILD_MAX_BYTES, FULL_BUILD_TAIL_BYTES, BATCH_SCAN_MAX_BYTES;
21600
21643
  var init_sync_client = __esm({
21601
21644
  "src/sync-client.ts"() {
21602
21645
  "use strict";
@@ -21642,10 +21685,16 @@ var init_sync_client = __esm({
21642
21685
  ownVersion = JSON.parse(readFileSync37(join44(dir, "../package.json"), "utf-8")).version || ownVersion;
21643
21686
  } catch {
21644
21687
  try {
21645
- if (true) ownVersion = "0.5.30";
21688
+ if (true) ownVersion = "0.5.32";
21646
21689
  } catch {
21647
21690
  }
21648
21691
  }
21692
+ ERROR_CLASS = "__chatRecallErrorClass";
21693
+ STANDING_FAILURE = /* @__PURE__ */ new Set([
21694
+ "auth",
21695
+ "payment_required",
21696
+ "insecure_transport"
21697
+ ]);
21649
21698
  walkProgressForUpload = null;
21650
21699
  lastServerPackSpec = null;
21651
21700
  credPath = () => join44(getDataDir(), "credentials.json");
@@ -22805,14 +22854,14 @@ __export(shadow_prune_exports, {
22805
22854
  DEFAULT_MAX_TOTAL_BYTES: () => DEFAULT_MAX_TOTAL_BYTES,
22806
22855
  pruneShadow: () => pruneShadow
22807
22856
  });
22808
- import { readdirSync as readdirSync34, statSync as statSync44, unlinkSync as unlinkSync3 } from "fs";
22857
+ import { readdirSync as readdirSync35, statSync as statSync44, unlinkSync as unlinkSync3 } from "fs";
22809
22858
  import { join as join52 } from "path";
22810
22859
  function listShadows(isFullyAcked) {
22811
22860
  const out = [];
22812
22861
  const root = shadowRoot();
22813
22862
  let tools;
22814
22863
  try {
22815
- tools = readdirSync34(root);
22864
+ tools = readdirSync35(root);
22816
22865
  } catch {
22817
22866
  return out;
22818
22867
  }
@@ -22820,7 +22869,7 @@ function listShadows(isFullyAcked) {
22820
22869
  const dir = join52(root, tool);
22821
22870
  let names;
22822
22871
  try {
22823
- names = readdirSync34(dir);
22872
+ names = readdirSync35(dir);
22824
22873
  } catch {
22825
22874
  continue;
22826
22875
  }
@@ -24430,7 +24479,7 @@ try {
24430
24479
  ownVersion2 = JSON.parse(readFileSync41(join50(dir, "../package.json"), "utf-8")).version || ownVersion2;
24431
24480
  } catch {
24432
24481
  try {
24433
- if (true) ownVersion2 = "0.5.30";
24482
+ if (true) ownVersion2 = "0.5.32";
24434
24483
  } catch {
24435
24484
  }
24436
24485
  }
@@ -24775,7 +24824,7 @@ async function runCollectorMigration(opts) {
24775
24824
  init_sync_ledger();
24776
24825
  init_collector_health();
24777
24826
  import { existsSync as existsSync50, readFileSync as readFileSync46 } from "fs";
24778
- var CLI_VERSION3 = true ? "0.5.30" : "0.0.0";
24827
+ var CLI_VERSION3 = true ? "0.5.32" : "0.0.0";
24779
24828
  var DEBOUNCE_MS = 5e3;
24780
24829
  var CLAUDE_DIR = claudeBackend.projectsDir();
24781
24830
  var PLANS_DIR = claudeBackend.plansDir();
@@ -24812,7 +24861,9 @@ async function shipToServer(trigger) {
24812
24861
  `Sync (${trigger}): ${result.uploaded} session(s) pushed, ${result.redactions} secret(s) redacted, ${result.skipped} skipped, ${result.items} items, ${result.links} links, ${result.derived} derived, ${result.kgEntities} KG entities, ${result.kgTriples} KG triples`
24813
24862
  );
24814
24863
  }
24815
- for (const server of syncTargetUrls()) noteSyncOutcome(server, true);
24864
+ for (const [server, outcome] of Object.entries(result.perTarget ?? {})) {
24865
+ noteSyncOutcome(server, outcome.ok, outcome.error);
24866
+ }
24816
24867
  } catch (err) {
24817
24868
  const msg = err instanceof Error ? err.message : String(err);
24818
24869
  daemonLog.error(`Sync failed (${trigger}, will retry next flush): ${msg.slice(0, 200)}`);