chat-recall 0.7.7 → 0.7.9

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
@@ -4892,8 +4892,8 @@ function writeSecrets(secrets) {
4892
4892
  _secretsCache = null;
4893
4893
  const p = secretsPath();
4894
4894
  mkdirSync2(dirname2(p), { recursive: true });
4895
- const body = "# chat-recall secrets \u2014 NOT committed/synced. Mode 0600.\n" + Object.entries(secrets).filter(([, v]) => v).map(([k, v]) => `${k}=${v}`).join("\n") + "\n";
4896
- writeFileSync(p, body);
4895
+ const body2 = "# chat-recall secrets \u2014 NOT committed/synced. Mode 0600.\n" + Object.entries(secrets).filter(([, v]) => v).map(([k, v]) => `${k}=${v}`).join("\n") + "\n";
4896
+ writeFileSync(p, body2);
4897
4897
  try {
4898
4898
  chmodSync(p, 384);
4899
4899
  } catch {
@@ -5979,11 +5979,11 @@ async function parseSessionFile(sessionPath, maxMessages = 50) {
5979
5979
  }
5980
5980
  const toolResult = obj.toolUseResult;
5981
5981
  if (toolResult && typeof toolResult === "object" && toolCount < maxMessages) {
5982
- const resultText = toolResult.result;
5982
+ const resultText2 = toolResult.result;
5983
5983
  const query = toolResult.query;
5984
- if (resultText && typeof resultText === "string" && isValuableToolResult(resultText, "WebSearch")) {
5984
+ if (resultText2 && typeof resultText2 === "string" && isValuableToolResult(resultText2, "WebSearch")) {
5985
5985
  const searchText = query ? `Search: ${query}
5986
- ${resultText}` : resultText;
5986
+ ${resultText2}` : resultText2;
5987
5987
  content.toolResults.push({
5988
5988
  text: searchText.slice(0, 2e3),
5989
5989
  lineNumber: lineNum,
@@ -7002,7 +7002,7 @@ function gitLogRepo(repo, startIso, endIso) {
7002
7002
  const authorIso = seg.slice(fieldPositions[1] + 1, fieldPositions[2]);
7003
7003
  const authorName = seg.slice(fieldPositions[2] + 1, fieldPositions[3]);
7004
7004
  const subject = seg.slice(fieldPositions[3] + 1, fieldPositions[4]);
7005
- let body = seg.slice(fieldPositions[4] + 1);
7005
+ let body2 = seg.slice(fieldPositions[4] + 1);
7006
7006
  current = {
7007
7007
  sha,
7008
7008
  shortSha,
@@ -7016,11 +7016,11 @@ function gitLogRepo(repo, startIso, endIso) {
7016
7016
  };
7017
7017
  const recovered = [];
7018
7018
  let m;
7019
- while (m = TRAILING_NUMSTAT.exec(body)) {
7019
+ while (m = TRAILING_NUMSTAT.exec(body2)) {
7020
7020
  recovered.unshift(m[1]);
7021
- body = body.slice(0, body.length - m[0].length);
7021
+ body2 = body2.slice(0, body2.length - m[0].length);
7022
7022
  }
7023
- current.body = body.trim();
7023
+ current.body = body2.trim();
7024
7024
  for (const line of recovered)
7025
7025
  recordNumstat(line);
7026
7026
  } else if (NUMSTAT.test(seg)) {
@@ -7914,7 +7914,7 @@ var init_opencode = __esm({
7914
7914
  });
7915
7915
  const out = d?.state?.output;
7916
7916
  if (out !== void 0 && out !== null) {
7917
- const body = typeof out === "string" ? out : JSON.stringify(out);
7917
+ const body2 = typeof out === "string" ? out : JSON.stringify(out);
7918
7918
  events.push({
7919
7919
  kind: "tool_result",
7920
7920
  ts,
@@ -7922,9 +7922,9 @@ var init_opencode = __esm({
7922
7922
  line: lineNum,
7923
7923
  toolUseId: callId,
7924
7924
  toolName,
7925
- resultBody: body,
7925
+ resultBody: body2,
7926
7926
  resultIsError: d?.state?.status === "error",
7927
- resultBytes: body.length
7927
+ resultBytes: body2.length
7928
7928
  });
7929
7929
  }
7930
7930
  }
@@ -8699,13 +8699,13 @@ var init_codex2 = __esm({
8699
8699
  } else if (obj.type === "response_item" && payload.type === "function_call_output") {
8700
8700
  const callId = String(payload.call_id || "");
8701
8701
  const out = payload.output;
8702
- let body = "";
8702
+ let body2 = "";
8703
8703
  let isError = false;
8704
8704
  let exitCode;
8705
8705
  if (typeof out === "string")
8706
- body = out;
8706
+ body2 = out;
8707
8707
  else if (out && typeof out === "object") {
8708
- body = String(out.content ?? out.output ?? out.stdout ?? out.text ?? "");
8708
+ body2 = String(out.content ?? out.output ?? out.stdout ?? out.text ?? "");
8709
8709
  if (typeof out.exit_code === "number") {
8710
8710
  exitCode = out.exit_code;
8711
8711
  isError = exitCode !== 0;
@@ -8717,10 +8717,10 @@ var init_codex2 = __esm({
8717
8717
  tsIso,
8718
8718
  line: lineNum,
8719
8719
  toolUseId: callId,
8720
- resultBody: body,
8720
+ resultBody: body2,
8721
8721
  resultIsError: isError,
8722
8722
  resultExitCode: exitCode,
8723
- resultBytes: body.length
8723
+ resultBytes: body2.length
8724
8724
  });
8725
8725
  }
8726
8726
  }
@@ -9742,15 +9742,15 @@ function messagesToEvents(messages, createdAtMs, updatedAtMs) {
9742
9742
  const p = part;
9743
9743
  if (p.type !== "tool-result")
9744
9744
  continue;
9745
- const body = resultBodyOf(p);
9745
+ const body2 = resultBodyOf(p);
9746
9746
  events.push({
9747
9747
  kind: "tool_result",
9748
9748
  ts: clock,
9749
9749
  line: 0,
9750
9750
  toolUseId: typeof p.toolCallId === "string" ? p.toolCallId : void 0,
9751
- resultBody: body,
9751
+ resultBody: body2,
9752
9752
  resultIsError: isError,
9753
- resultBytes: Buffer.byteLength(body, "utf8")
9753
+ resultBytes: Buffer.byteLength(body2, "utf8")
9754
9754
  });
9755
9755
  }
9756
9756
  }
@@ -10613,11 +10613,11 @@ var init_cursor = __esm({
10613
10613
  const events = readComposerEvents(r.composer);
10614
10614
  if (events.length === 0)
10615
10615
  return null;
10616
- const body = events.map((e) => JSON.stringify(e)).join("\n") + "\n";
10616
+ const body2 = events.map((e) => JSON.stringify(e)).join("\n") + "\n";
10617
10617
  return {
10618
10618
  tool: "cursor",
10619
10619
  mtime: statSync9(r.composer.globalDbPath).mtimeMs,
10620
- files: [{ name: `${r.composer.composerId}.jsonl`, bytes: Buffer.from(body, "utf8") }]
10620
+ files: [{ name: `${r.composer.composerId}.jsonl`, bytes: Buffer.from(body2, "utf8") }]
10621
10621
  };
10622
10622
  } catch {
10623
10623
  return null;
@@ -10972,9 +10972,29 @@ function findSessionFile(sessionId) {
10972
10972
  function invalidateSessionFileIndex() {
10973
10973
  indexCache = null;
10974
10974
  }
10975
+ function indexStillValid(cache4) {
10976
+ const roots = claudeProjectDirs();
10977
+ if (roots.length !== cache4.roots.length || roots.some((r, i) => r !== cache4.roots[i]))
10978
+ return false;
10979
+ for (const [dir, mtime] of cache4.dirs) {
10980
+ if (dirMtime(dir) !== mtime)
10981
+ return false;
10982
+ }
10983
+ return true;
10984
+ }
10975
10985
  function sessionFileIndex() {
10976
- if (indexCache)
10977
- return indexCache;
10986
+ if (indexCache) {
10987
+ const now = Date.now();
10988
+ if (now - indexCache.checkedAt < INDEX_RECHECK_MS)
10989
+ return indexCache.byId;
10990
+ if (indexStillValid(indexCache)) {
10991
+ indexCache.checkedAt = now;
10992
+ return indexCache.byId;
10993
+ }
10994
+ indexCache = null;
10995
+ }
10996
+ const dirs = /* @__PURE__ */ new Map();
10997
+ const roots = claudeProjectDirs();
10978
10998
  const byId = /* @__PURE__ */ new Map();
10979
10999
  const seenRoots = /* @__PURE__ */ new Set();
10980
11000
  const projectPaths = /* @__PURE__ */ new Map();
@@ -10986,10 +11006,11 @@ function sessionFileIndex() {
10986
11006
  }
10987
11007
  return p;
10988
11008
  };
10989
- for (const root of claudeProjectDirs()) {
11009
+ for (const root of roots) {
10990
11010
  if (seenRoots.has(root) || !existsSync13(root))
10991
11011
  continue;
10992
11012
  seenRoots.add(root);
11013
+ dirs.set(root, dirMtime(root));
10993
11014
  let entries;
10994
11015
  try {
10995
11016
  entries = readdirSync10(root, { withFileTypes: true });
@@ -11000,6 +11021,7 @@ function sessionFileIndex() {
11000
11021
  if (!entry.isDirectory())
11001
11022
  continue;
11002
11023
  const dir = join15(root, entry.name);
11024
+ dirs.set(dir, dirMtime(dir));
11003
11025
  let names;
11004
11026
  try {
11005
11027
  names = readdirSync10(dir);
@@ -11024,7 +11046,7 @@ function sessionFileIndex() {
11024
11046
  }
11025
11047
  }
11026
11048
  if (scanScopeDepth > 0)
11027
- indexCache = byId;
11049
+ indexCache = { byId, dirs, roots, checkedAt: Date.now() };
11028
11050
  return byId;
11029
11051
  }
11030
11052
  function findSessionFiles(sessionId) {
@@ -11182,7 +11204,7 @@ function findCodexSessionFileIn(root, sessionId) {
11182
11204
  }
11183
11205
  return scanDir(root);
11184
11206
  }
11185
- var scanScopeDepth, indexCache, readScope, readScopeDepth, derivedScope, geminiCache, MAX_EVENT_LINE_BYTES;
11207
+ var scanScopeDepth, indexCache, INDEX_RECHECK_MS, dirMtime, readScope, readScopeDepth, derivedScope, geminiCache, MAX_EVENT_LINE_BYTES;
11186
11208
  var init_live_session_scan = __esm({
11187
11209
  "../engine/dist/core/live-session-scan.js"() {
11188
11210
  "use strict";
@@ -11194,6 +11216,14 @@ var init_live_session_scan = __esm({
11194
11216
  init_project_dir_name();
11195
11217
  scanScopeDepth = 0;
11196
11218
  indexCache = null;
11219
+ INDEX_RECHECK_MS = 1e3;
11220
+ dirMtime = (p) => {
11221
+ try {
11222
+ return statSync11(p).mtimeMs;
11223
+ } catch {
11224
+ return -1;
11225
+ }
11226
+ };
11197
11227
  readScope = null;
11198
11228
  readScopeDepth = 0;
11199
11229
  derivedScope = null;
@@ -11459,15 +11489,36 @@ var init_claude2 = __esm({
11459
11489
  listSessions(opts = {}) {
11460
11490
  const cutoff = opts.sinceMs ?? 0;
11461
11491
  const filter = opts.projectFilter?.toLowerCase();
11462
- const seen = /* @__PURE__ */ new Set();
11463
- const out = [];
11492
+ const byId = /* @__PURE__ */ new Map();
11464
11493
  for (const root of claudeProjectDirs()) {
11465
- this.collectSessionsFromRoot(root, cutoff, filter, seen, out, opts.previews !== false);
11494
+ this.collectSessionsFromRoot(root, filter, byId, opts.previews !== false);
11466
11495
  }
11496
+ const out = [...byId.values()].filter((r) => r.mtime >= cutoff);
11467
11497
  out.sort((a, b) => b.mtime - a.mtime);
11468
11498
  return opts.limit ? out.slice(0, opts.limit) : out;
11469
11499
  }
11470
- collectSessionsFromRoot(root, cutoff, filter, seen, out, previews) {
11500
+ /**
11501
+ * Add this root's sessions to `byId`. A session resumed under a second
11502
+ * profile has one file in each home under the same id. It is ONE session: the
11503
+ * first home keeps its path, and its mtime is the newest of all copies.
11504
+ *
11505
+ * Each copy was listed as its own ref before. Session 8da8d72b had a primary
11506
+ * copy frozen at 05:55 and a second-home copy growing until 12:00; the walk
11507
+ * handled both refs under one ledger row with two different mtimes, and the
11508
+ * row that shipped nothing stamped the other copy's mtime.
11509
+ */
11510
+ collectSessionsFromRoot(root, filter, byId, previews) {
11511
+ const add = (ref) => {
11512
+ const prior = byId.get(ref.rawId);
11513
+ if (!prior) {
11514
+ byId.set(ref.rawId, ref);
11515
+ return;
11516
+ }
11517
+ if (ref.mtime > prior.mtime) {
11518
+ prior.mtime = ref.mtime;
11519
+ prior.modified = ref.modified;
11520
+ }
11521
+ };
11471
11522
  if (!existsSync15(root))
11472
11523
  return;
11473
11524
  for (const proj of readdirSync11(root, { withFileTypes: true })) {
@@ -11478,6 +11529,7 @@ var init_claude2 = __esm({
11478
11529
  const projPath = join16(root, proj.name);
11479
11530
  const projectPath = resolveProjectDirName(proj.name);
11480
11531
  const indexPath = join16(projPath, "sessions-index.json");
11532
+ const indexed = /* @__PURE__ */ new Set();
11481
11533
  if (existsSync15(indexPath)) {
11482
11534
  try {
11483
11535
  const indexData = JSON.parse(readFileSync10(indexPath, "utf-8"));
@@ -11485,10 +11537,8 @@ var init_claude2 = __esm({
11485
11537
  for (const entry of entries) {
11486
11538
  if (!entry.fullPath || !existsSync15(entry.fullPath))
11487
11539
  continue;
11488
- if ((entry.fileMtime ?? 0) < cutoff)
11489
- continue;
11490
- seen.add(entry.sessionId);
11491
- out.push({
11540
+ indexed.add(entry.sessionId);
11541
+ add({
11492
11542
  toolId: "claude",
11493
11543
  rawId: entry.sessionId,
11494
11544
  prefixedId: entry.sessionId,
@@ -11515,7 +11565,7 @@ var init_claude2 = __esm({
11515
11565
  if (!f.endsWith(".jsonl") || f === "sessions-index.json")
11516
11566
  continue;
11517
11567
  const sessionId = basename10(f, ".jsonl");
11518
- if (seen.has(sessionId))
11568
+ if (indexed.has(sessionId))
11519
11569
  continue;
11520
11570
  const fullPath = join16(projPath, f);
11521
11571
  let stat3;
@@ -11524,10 +11574,13 @@ var init_claude2 = __esm({
11524
11574
  } catch {
11525
11575
  continue;
11526
11576
  }
11527
- if (stat3.mtimeMs < cutoff)
11577
+ const prior = byId.get(sessionId);
11578
+ if (prior) {
11579
+ add({ ...prior, mtime: stat3.mtimeMs, modified: stat3.mtime.toISOString() });
11528
11580
  continue;
11581
+ }
11529
11582
  const firstPrompt = previews ? extractFirstUserPromptSync(fullPath, { maxLength: 200 }) : "";
11530
- out.push({
11583
+ add({
11531
11584
  toolId: "claude",
11532
11585
  rawId: sessionId,
11533
11586
  prefixedId: sessionId,
@@ -11657,20 +11710,20 @@ var init_claude2 = __esm({
11657
11710
  text += (text ? "\n" : "") + it.text;
11658
11711
  } else if (it.type === "tool_result") {
11659
11712
  const id = typeof it.tool_use_id === "string" ? it.tool_use_id : "";
11660
- let body = "";
11713
+ let body2 = "";
11661
11714
  const c = it.content;
11662
11715
  if (typeof c === "string")
11663
- body = c;
11716
+ body2 = c;
11664
11717
  else if (Array.isArray(c)) {
11665
11718
  for (const sub of c) {
11666
11719
  if (sub && typeof sub === "object" && sub.type === "text") {
11667
11720
  const t = sub.text;
11668
11721
  if (typeof t === "string")
11669
- body += t;
11722
+ body2 += t;
11670
11723
  }
11671
11724
  }
11672
11725
  }
11673
- toolResults.push({ id, body, isError: it.is_error === true });
11726
+ toolResults.push({ id, body: body2, isError: it.is_error === true });
11674
11727
  }
11675
11728
  }
11676
11729
  }
@@ -12606,10 +12659,10 @@ function applyChunkPrivacy(text) {
12606
12659
  out = redactFilePaths(out);
12607
12660
  return out;
12608
12661
  }
12609
- function redactToolResultBody(toolName, body) {
12610
- if (!body)
12611
- return body;
12612
- return `[redacted: ${toolName} output, ${body.length} chars]`;
12662
+ function redactToolResultBody(toolName, body2) {
12663
+ if (!body2)
12664
+ return body2;
12665
+ return `[redacted: ${toolName} output, ${body2.length} chars]`;
12613
12666
  }
12614
12667
  var DEFAULT_REDACTION_RULES, SECRET_CONTEXT_RE, HIGH_ENTROPY_TOKEN_RE, cache, CANARY, MAX_PACK_RULES, MAX_PATTERN_LEN, serverPack, globalRegexCache, privacyCache, PATH_REGEX;
12615
12668
  var init_secret_redactor = __esm({
@@ -14839,8 +14892,8 @@ function parseFrontmatter(content) {
14839
14892
  return { body: content };
14840
14893
  const header = content.slice(3, close);
14841
14894
  const afterFence = content.indexOf("\n", close + 1);
14842
- const body = afterFence === -1 ? "" : content.slice(afterFence + 1);
14843
- const out = { body };
14895
+ const body2 = afterFence === -1 ? "" : content.slice(afterFence + 1);
14896
+ const out = { body: body2 };
14844
14897
  for (const line of header.split("\n")) {
14845
14898
  const m = line.match(/^\s*([A-Za-z_]+)\s*:\s*(.+?)\s*$/);
14846
14899
  if (!m)
@@ -14932,9 +14985,9 @@ var init_plan_source = __esm({
14932
14985
  const isAgentPlan = planName.includes("-agent-");
14933
14986
  const content = readFileSync15(filePath, "utf-8");
14934
14987
  const fm = parseFrontmatter(content);
14935
- const body = fm.body;
14936
- const firstLine = body.split("\n").find((l) => l.trim())?.replace(/^#+\s*/, "").trim() || planName;
14937
- const projectPath = fm.cwd || this.extractProjectPath(body);
14988
+ const body2 = fm.body;
14989
+ const firstLine = body2.split("\n").find((l) => l.trim())?.replace(/^#+\s*/, "").trim() || planName;
14990
+ const projectPath = fm.cwd || this.extractProjectPath(body2);
14938
14991
  const baseName = planName.replace(/-agent-[a-z0-9]+$/i, "");
14939
14992
  const claudeSessionId = fm.sessionId || (UUID_RE3.test(baseName) ? baseName : void 0);
14940
14993
  yield {
@@ -14944,7 +14997,7 @@ var init_plan_source = __esm({
14944
14997
  projectPath,
14945
14998
  filePath,
14946
14999
  mtime: stat3.mtimeMs,
14947
- contentPreview: body.slice(0, 300),
15000
+ contentPreview: body2.slice(0, 300),
14948
15001
  extra: {
14949
15002
  tool: "claude",
14950
15003
  isAgentPlan,
@@ -15051,8 +15104,8 @@ var init_plan_source = __esm({
15051
15104
  return [];
15052
15105
  const content = readFileSync15(item.filePath, "utf-8");
15053
15106
  const chunks = [];
15054
- const { body } = parseFrontmatter(content);
15055
- const sections = splitByHeaders(body);
15107
+ const { body: body2 } = parseFrontmatter(content);
15108
+ const sections = splitByHeaders(body2);
15056
15109
  for (let i = 0; i < sections.length; i++) {
15057
15110
  const section = sections[i];
15058
15111
  if (!section.text.trim() || section.text.trim().length < 20)
@@ -15685,10 +15738,10 @@ import { homedir as homedir9 } from "os";
15685
15738
  import { join as join26, basename as basename14 } from "path";
15686
15739
  function parseFrontmatter2(content) {
15687
15740
  const fm = {};
15688
- let body = content;
15741
+ let body2 = content;
15689
15742
  const m = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);
15690
15743
  if (m) {
15691
- body = m[2];
15744
+ body2 = m[2];
15692
15745
  for (const line of m[1].split(/\r?\n/)) {
15693
15746
  const t = line.trim();
15694
15747
  if (!t || t.startsWith("#"))
@@ -15705,7 +15758,7 @@ function parseFrontmatter2(content) {
15705
15758
  fm[k] = v;
15706
15759
  }
15707
15760
  }
15708
- return { fm, body };
15761
+ return { fm, body: body2 };
15709
15762
  }
15710
15763
  function projectHashToPath(hashDir) {
15711
15764
  return resolveProjectDirName(hashDir);
@@ -15782,9 +15835,9 @@ var init_agent_memory_source = __esm({
15782
15835
  if (!existsSync25(item.filePath))
15783
15836
  return [];
15784
15837
  const content = readFileSync18(item.filePath, "utf-8");
15785
- const { body } = parseFrontmatter2(content);
15838
+ const { body: body2 } = parseFrontmatter2(content);
15786
15839
  const chunks = [];
15787
- const sections = splitByHeaders(body);
15840
+ const sections = splitByHeaders(body2);
15788
15841
  for (let i = 0; i < sections.length; i++) {
15789
15842
  const section = sections[i];
15790
15843
  if (!section.text.trim() || section.text.trim().length < 20)
@@ -17428,13 +17481,13 @@ function parseFrontmatter4(text) {
17428
17481
  }
17429
17482
  return { fm, body: m[2] ?? "" };
17430
17483
  }
17431
- function stringifyFrontmatter(fm, body) {
17484
+ function stringifyFrontmatter(fm, body2) {
17432
17485
  const lines = Object.entries(fm).filter(([, v]) => v !== void 0 && v !== "").map(([k, v]) => `${k}: ${needsQuote(v) ? JSON.stringify(v) : v}`);
17433
17486
  return `---
17434
17487
  ${lines.join("\n")}
17435
17488
  ---
17436
17489
 
17437
- ${body.replace(/^\n+/, "")}`;
17490
+ ${body2.replace(/^\n+/, "")}`;
17438
17491
  }
17439
17492
  function needsQuote(v) {
17440
17493
  return /[:#]/.test(v) || /^\s|\s$/.test(v);
@@ -17521,11 +17574,11 @@ function parseCommand(content, fallbackName, format) {
17521
17574
  body: t.prompt || ""
17522
17575
  };
17523
17576
  }
17524
- const { fm, body } = parseFrontmatter4(content);
17577
+ const { fm, body: body2 } = parseFrontmatter4(content);
17525
17578
  return {
17526
17579
  name: fm.name || fallbackName,
17527
17580
  description: fm.description || "",
17528
- body: body.trim()
17581
+ body: body2.trim()
17529
17582
  };
17530
17583
  }
17531
17584
  var MAX_CHUNK_CHARS12, MAX_BODY_CHARS2, SlashCommandsSource;
@@ -17669,12 +17722,12 @@ function parseAgent(content, fallbackName, format) {
17669
17722
  body: t.developer_instructions || t.instructions || ""
17670
17723
  };
17671
17724
  }
17672
- const { fm, body } = parseFrontmatter4(content);
17725
+ const { fm, body: body2 } = parseFrontmatter4(content);
17673
17726
  return {
17674
17727
  name: fm.name || fallbackName,
17675
17728
  description: fm.description || "",
17676
17729
  tools: fm.tools || "",
17677
- body: body.trim()
17730
+ body: body2.trim()
17678
17731
  };
17679
17732
  }
17680
17733
  var MAX_CHUNK_CHARS13, MAX_BODY_CHARS3, SubagentsSource;
@@ -18587,7 +18640,7 @@ var init_http = __esm({
18587
18640
  CLI_VERSION = JSON.parse(readFileSync31(new URL("../package.json", import.meta.url), "utf-8")).version || CLI_VERSION;
18588
18641
  } catch {
18589
18642
  try {
18590
- if (true) CLI_VERSION = "0.7.7";
18643
+ if (true) CLI_VERSION = "0.7.9";
18591
18644
  } catch {
18592
18645
  }
18593
18646
  }
@@ -19086,7 +19139,7 @@ var init_telemetry = __esm({
19086
19139
  init_sync_client();
19087
19140
  cliVersion2 = () => {
19088
19141
  try {
19089
- return true ? "0.7.7" : "dev";
19142
+ return true ? "0.7.9" : "dev";
19090
19143
  } catch {
19091
19144
  return "dev";
19092
19145
  }
@@ -19103,9 +19156,12 @@ __export(collector_health_exports, {
19103
19156
  STALE_AFTER_MS: () => STALE_AFTER_MS,
19104
19157
  applySyncOutcome: () => applySyncOutcome,
19105
19158
  collectorHealthPath: () => collectorHealthPath,
19159
+ crashesAtBoot: () => crashesAtBoot,
19106
19160
  judgeHealth: () => judgeHealth,
19161
+ markCleanExit: () => markCleanExit,
19107
19162
  progressLine: () => progressLine,
19108
19163
  readCollectorHealth: () => readCollectorHealth,
19164
+ recentCrashes: () => recentCrashes,
19109
19165
  reportWalkProgress: () => reportWalkProgress,
19110
19166
  updateCollectorHealth: () => updateCollectorHealth,
19111
19167
  writeCollectorHealth: () => writeCollectorHealth
@@ -19174,6 +19230,20 @@ function reportWalkProgress(p) {
19174
19230
  lastProgressWrite = now;
19175
19231
  updateCollectorHealth({ progress: p });
19176
19232
  }
19233
+ function crashesAtBoot(prior, procStart) {
19234
+ const history = (prior?.crashes ?? []).filter((t) => typeof t === "number");
19235
+ if (!prior)
19236
+ return history;
19237
+ const leftOnPurpose = typeof prior.cleanExitAt === "number" && prior.cleanExitAt >= prior.startedAt;
19238
+ return leftOnPurpose ? history : [...history, procStart];
19239
+ }
19240
+ function recentCrashes(crashes, now = Date.now()) {
19241
+ const cutoff = now - 36e5;
19242
+ return [...new Set(crashes.filter((t) => t > cutoff))].sort((a, b) => a - b).slice(-20);
19243
+ }
19244
+ function markCleanExit(now = Date.now()) {
19245
+ updateCollectorHealth({ cleanExitAt: now });
19246
+ }
19177
19247
  function judgeHealth(h, now = Date.now()) {
19178
19248
  if (!h)
19179
19249
  return { ok: true, summary: null, reasons: [] };
@@ -19183,7 +19253,7 @@ function judgeHealth(h, now = Date.now()) {
19183
19253
  reasons.push(`the collector has not reported for ${ago(silent)} \u2014 it may not be running`);
19184
19254
  }
19185
19255
  if (h.restartsLastHour >= CRASHLOOP_RESTARTS) {
19186
- reasons.push(`it restarted ${h.restartsLastHour} times in the last hour`);
19256
+ reasons.push(`it crashed ${h.restartsLastHour} times in the last hour`);
19187
19257
  }
19188
19258
  const targets = Object.entries(h.targets ?? {});
19189
19259
  const stale = targets.filter(([, t]) => t.lastOkAt === null || now - t.lastOkAt > STALE_AFTER_MS);
@@ -19258,20 +19328,20 @@ async function probeServer(base3, opts = {}) {
19258
19328
  if (res.status === 404 || res.status === 410) return { kind: "moved", status: res.status };
19259
19329
  if (res.status >= 500) return { kind: "server_error", status: res.status };
19260
19330
  if (!res.ok) return { kind: "moved", status: res.status };
19261
- let body;
19331
+ let body2;
19262
19332
  try {
19263
- body = await res.text();
19333
+ body2 = await res.text();
19264
19334
  } catch (err) {
19265
19335
  return { kind: "unreachable", error: describeCause(err), reason: classifyUnreachable(err) };
19266
19336
  }
19267
19337
  let parsed;
19268
19338
  try {
19269
- parsed = JSON.parse(body);
19339
+ parsed = JSON.parse(body2);
19270
19340
  } catch {
19271
- return { kind: "not_api", status: res.status, snippet: body.trim().slice(0, 60) };
19341
+ return { kind: "not_api", status: res.status, snippet: body2.trim().slice(0, 60) };
19272
19342
  }
19273
19343
  if (typeof parsed?.apiVersion !== "number") {
19274
- return { kind: "not_api", status: res.status, snippet: body.trim().slice(0, 60) };
19344
+ return { kind: "not_api", status: res.status, snippet: body2.trim().slice(0, 60) };
19275
19345
  }
19276
19346
  return {
19277
19347
  kind: "ok",
@@ -19390,7 +19460,7 @@ function reportClientEvent(kind, opts = {}) {
19390
19460
  try {
19391
19461
  const targets = loadAllCredentials();
19392
19462
  if (!targets.length) return;
19393
- const body = JSON.stringify({
19463
+ const body2 = JSON.stringify({
19394
19464
  events: [{
19395
19465
  ts: Date.now(),
19396
19466
  kind: String(kind).slice(0, 64),
@@ -19407,7 +19477,7 @@ function reportClientEvent(kind, opts = {}) {
19407
19477
  void fetch(`${t.serverUrl.replace(/\/+$/, "")}/api/client-events`, {
19408
19478
  method: "POST",
19409
19479
  headers,
19410
- body,
19480
+ body: body2,
19411
19481
  signal: AbortSignal.timeout(3e3)
19412
19482
  }).catch(() => {
19413
19483
  });
@@ -19821,10 +19891,10 @@ async function fetchTenantSecurityConfig(cred) {
19821
19891
  let tenantRules = [];
19822
19892
  let rulePackVersion = null;
19823
19893
  if (rulesRes.ok) {
19824
- const body = await rulesRes.json().catch(() => ({}));
19825
- const enabled = (body.rules || []).filter((r) => r.enabled !== false);
19894
+ const body2 = await rulesRes.json().catch(() => ({}));
19895
+ const enabled = (body2.rules || []).filter((r) => r.enabled !== false);
19826
19896
  tenantRules = enabled;
19827
- const packSpec = body.pack?.rules ? { version: body.pack.version, rules: body.pack.rules.map((r) => ({ name: r.name, regex: r.regex, flags: r.flags, redact: true, source: r.source })) } : { version: body.version, rules: enabled.filter((r) => r.redact === true).map((r) => ({ name: r.name, regex: r.regex, redact: true, source: "tenant" })) };
19897
+ const packSpec = body2.pack?.rules ? { version: body2.pack.version, rules: body2.pack.rules.map((r) => ({ name: r.name, regex: r.regex, flags: r.flags, redact: true, source: r.source })) } : { version: body2.version, rules: enabled.filter((r) => r.redact === true).map((r) => ({ name: r.name, regex: r.regex, redact: true, source: "tenant" })) };
19828
19898
  lastServerPackSpec = { version: packSpec.version || "", rules: packSpec.rules };
19829
19899
  const pack = installServerRulePack(packSpec);
19830
19900
  rulePackVersion = serverRulePackVersion();
@@ -19832,20 +19902,20 @@ async function fetchTenantSecurityConfig(cred) {
19832
19902
  console.error(`[sync] server redaction rule "${r.name}" ignored: ${r.reason}`);
19833
19903
  }
19834
19904
  if (pack.accepted > 0) {
19835
- const rev = body.pack?.revision ? `, rev ${body.pack.revision}` : "";
19905
+ const rev = body2.pack?.revision ? `, rev ${body2.pack.revision}` : "";
19836
19906
  console.error(`[sync] ${pack.accepted} server redaction rule(s) active (pack ${rulePackVersion}${rev})`);
19837
19907
  }
19838
19908
  }
19839
19909
  let verifySecrets = true;
19840
19910
  if (settingsRes?.ok) {
19841
- const body = await settingsRes.json().catch(() => ({}));
19842
- if (typeof body.verifySecrets === "boolean") verifySecrets = body.verifySecrets;
19843
- if (typeof body.telemetry === "boolean") {
19844
- setTelemetryEligible(base3, body.telemetry);
19911
+ const body2 = await settingsRes.json().catch(() => ({}));
19912
+ if (typeof body2.verifySecrets === "boolean") verifySecrets = body2.verifySecrets;
19913
+ if (typeof body2.telemetry === "boolean") {
19914
+ setTelemetryEligible(base3, body2.telemetry);
19845
19915
  try {
19846
19916
  const prior = readCollectorHealth()?.telemetryEligible ?? {};
19847
19917
  updateCollectorHealth({
19848
- telemetryEligible: { ...prior, [base3]: { allowed: body.telemetry, at: Date.now() } }
19918
+ telemetryEligible: { ...prior, [base3]: { allowed: body2.telemetry, at: Date.now() } }
19849
19919
  });
19850
19920
  } catch {
19851
19921
  }
@@ -19904,14 +19974,14 @@ async function fetchTenantSyncConfig(cred) {
19904
19974
  return EMPTY_SYNC_CONFIG;
19905
19975
  }
19906
19976
  if (!res.ok) return lastKnownSyncConfig(base3, `HTTP ${res.status}`);
19907
- const body = await res.json().catch(() => ({}));
19977
+ const body2 = await res.json().catch(() => ({}));
19908
19978
  const config2 = {
19909
- excludeTools: Array.isArray(body.excludeTools) ? body.excludeTools.filter((t) => typeof t === "string") : [],
19910
- excludeProjects: Array.isArray(body.excludeProjects) ? body.excludeProjects.filter((p) => typeof p === "string") : [],
19979
+ excludeTools: Array.isArray(body2.excludeTools) ? body2.excludeTools.filter((t) => typeof t === "string") : [],
19980
+ excludeProjects: Array.isArray(body2.excludeProjects) ? body2.excludeProjects.filter((p) => typeof p === "string") : [],
19911
19981
  // Ids only — installSourceExclusions drops anything else, so a server
19912
19982
  // sending a path cannot make this collector read it.
19913
- excludeSources: Array.isArray(body.excludeSources) ? body.excludeSources.filter((x) => typeof x === "string") : [],
19914
- approveSources: Array.isArray(body.approveSources) ? body.approveSources.filter((x) => typeof x === "string") : []
19983
+ excludeSources: Array.isArray(body2.excludeSources) ? body2.excludeSources.filter((x) => typeof x === "string") : [],
19984
+ approveSources: Array.isArray(body2.approveSources) ? body2.approveSources.filter((x) => typeof x === "string") : []
19915
19985
  };
19916
19986
  const applied = installSourceExclusions(config2.excludeSources);
19917
19987
  if (applied.excluded > 0) {
@@ -20306,9 +20376,9 @@ async function syncToTargetInScope(cred, opts = {}) {
20306
20376
  const maxInflight = explicitThrottle ? 1 : isLocalHost(cred.serverUrl) ? Math.max(LOCAL_INFLIGHT, advertised ?? 0) : advertised ?? REMOTE_INFLIGHT_FALLBACK;
20307
20377
  const UPLOAD_TIMEOUT_MS = Number(process.env.CHAT_RECALL_UPLOAD_TIMEOUT_MS) || 9e4;
20308
20378
  const gzipBody = serverAcceptsGzipBody(cred.serverUrl);
20309
- const post = async (body) => {
20379
+ const post = async (body2) => {
20310
20380
  const payload = (() => {
20311
- const withProgress = walkProgressForUpload ? { ...body, progress: walkProgressForUpload } : body;
20381
+ const withProgress = walkProgressForUpload ? { ...body2, progress: walkProgressForUpload } : body2;
20312
20382
  const json = JSON.stringify(withProgress);
20313
20383
  const raw = Buffer.from(json, "utf8");
20314
20384
  return gzipBody ? gzipSync3(raw, { level: 6 }) : raw;
@@ -20332,25 +20402,25 @@ async function syncToTargetInScope(cred, opts = {}) {
20332
20402
  });
20333
20403
  if (res.ok) {
20334
20404
  acceptedUploads.set(cred.serverUrl, (acceptedUploads.get(cred.serverUrl) ?? 0) + 1);
20335
- const body2 = await res.json().catch(() => ({}));
20336
- if (typeof body2.telemetry === "boolean") {
20337
- setTelemetryEligible(base3, body2.telemetry);
20405
+ const body3 = await res.json().catch(() => ({}));
20406
+ if (typeof body3.telemetry === "boolean") {
20407
+ setTelemetryEligible(base3, body3.telemetry);
20338
20408
  try {
20339
20409
  const prior = readCollectorHealth()?.telemetryEligible ?? {};
20340
20410
  updateCollectorHealth({
20341
- telemetryEligible: { ...prior, [base3]: { allowed: body2.telemetry, at: Date.now() } }
20411
+ telemetryEligible: { ...prior, [base3]: { allowed: body3.telemetry, at: Date.now() } }
20342
20412
  });
20343
20413
  } catch {
20344
20414
  }
20345
20415
  }
20346
- const adv = body2.limits?.ingestConcurrencyPerTenant;
20416
+ const adv = body3.limits?.ingestConcurrencyPerTenant;
20347
20417
  if (typeof adv === "number" && Number.isFinite(adv) && adv >= 1) {
20348
20418
  setServerIngestConcurrency(base3, Math.floor(adv));
20349
20419
  }
20350
- if (body2.cli && body2.cli.version) {
20420
+ if (body3.cli && body3.cli.version) {
20351
20421
  const { planAutoUpdate: planAutoUpdate2, runAutoUpdate: runAutoUpdate2, sweepStaleStaging: sweepStaleStaging2 } = await Promise.resolve().then(() => (init_auto_update(), auto_update_exports));
20352
20422
  const authHeaders = cred.token ? { authorization: `Bearer ${cred.token}` } : {};
20353
- const plan = planAutoUpdate2(base3, { cli: body2.cli }, ownVersion, process.env.CHAT_RECALL_AUTO_UPDATE);
20423
+ const plan = planAutoUpdate2(base3, { cli: body3.cli }, ownVersion, process.env.CHAT_RECALL_AUTO_UPDATE);
20354
20424
  sweepStaleStaging2();
20355
20425
  if (plan.update) {
20356
20426
  void runAutoUpdate2(base3, authHeaders, ownVersion).catch(() => {
@@ -20367,13 +20437,13 @@ async function syncToTargetInScope(cred, opts = {}) {
20367
20437
  if (res.status === 402) {
20368
20438
  let detail = text;
20369
20439
  try {
20370
- const body2 = JSON.parse(text);
20371
- detail = body2.error ?? text;
20372
- if (body2.detail) detail += `
20373
- ${body2.detail}`;
20374
- if (body2.resetsAt) detail += ` (resets ${new Date(body2.resetsAt).toISOString().slice(0, 10)})`;
20375
- if (body2.upgradeUrl) detail += `
20376
- ${body2.upgradeUrl}`;
20440
+ const body3 = JSON.parse(text);
20441
+ detail = body3.error ?? text;
20442
+ if (body3.detail) detail += `
20443
+ ${body3.detail}`;
20444
+ if (body3.resetsAt) detail += ` (resets ${new Date(body3.resetsAt).toISOString().slice(0, 10)})`;
20445
+ if (body3.upgradeUrl) detail += `
20446
+ ${body3.upgradeUrl}`;
20377
20447
  } catch {
20378
20448
  }
20379
20449
  throw classedError("payment_required", `sync paused by the server: ${detail}`);
@@ -20402,7 +20472,7 @@ async function syncToTargetInScope(cred, opts = {}) {
20402
20472
  let poolError = null;
20403
20473
  const MAX_INFLIGHT_BYTES = (Number(process.env.CHAT_RECALL_MAX_INFLIGHT_MB) || 32) * 1024 * 1024;
20404
20474
  let inflightBytes = 0;
20405
- const submit = async (body, after, bytesHint = 0) => {
20475
+ const submit = async (body2, after, bytesHint = 0) => {
20406
20476
  while (inflight.size > 0 && (inflight.size >= maxInflight || inflightBytes + bytesHint > MAX_INFLIGHT_BYTES)) {
20407
20477
  await Promise.race(inflight);
20408
20478
  }
@@ -20410,7 +20480,7 @@ async function syncToTargetInScope(cred, opts = {}) {
20410
20480
  inflightBytes += bytesHint;
20411
20481
  let task;
20412
20482
  task = (async () => {
20413
- await post(body);
20483
+ await post(body2);
20414
20484
  after();
20415
20485
  })().catch((e) => {
20416
20486
  poolError = poolError ?? e;
@@ -20477,18 +20547,18 @@ async function syncToTargetInScope(cred, opts = {}) {
20477
20547
  signal: ac.signal
20478
20548
  });
20479
20549
  if (!res.ok) throw new Error(`append sync failed: HTTP ${res.status} ${await res.text().catch(() => "")}`);
20480
- const body = await res.json().catch(() => ({}));
20481
- if (body.cli && body.cli.version) {
20550
+ const body2 = await res.json().catch(() => ({}));
20551
+ if (body2.cli && body2.cli.version) {
20482
20552
  const { planAutoUpdate: planAutoUpdate2, runAutoUpdate: runAutoUpdate2, sweepStaleStaging: sweepStaleStaging2 } = await Promise.resolve().then(() => (init_auto_update(), auto_update_exports));
20483
20553
  const authHeaders = cred.token ? { authorization: `Bearer ${cred.token}` } : {};
20484
- const plan = planAutoUpdate2(base3, { cli: body.cli }, ownVersion, process.env.CHAT_RECALL_AUTO_UPDATE);
20554
+ const plan = planAutoUpdate2(base3, { cli: body2.cli }, ownVersion, process.env.CHAT_RECALL_AUTO_UPDATE);
20485
20555
  sweepStaleStaging2();
20486
20556
  if (plan.update) {
20487
20557
  void runAutoUpdate2(base3, authHeaders, ownVersion).catch(() => {
20488
20558
  });
20489
20559
  }
20490
20560
  }
20491
- const fullNeeded = new Set(body.full_resync_needed ?? []);
20561
+ const fullNeeded = new Set(body2.full_resync_needed ?? []);
20492
20562
  const acked = convs.filter((c) => !fullNeeded.has(c.session_id));
20493
20563
  if (acked.length > 0) {
20494
20564
  try {
@@ -20523,9 +20593,9 @@ async function syncToTargetInScope(cred, opts = {}) {
20523
20593
  signal: ac.signal
20524
20594
  });
20525
20595
  if (!res.ok) throw new Error(`chunked head sync failed: HTTP ${res.status} ${await res.text().catch(() => "")}`);
20526
- const body = await res.json().catch(() => ({}));
20596
+ const body2 = await res.json().catch(() => ({}));
20527
20597
  const id = conv.session_id;
20528
- const guarded = (body.shrink_guarded ?? []).find((g) => g.session_id === id);
20598
+ const guarded = (body2.shrink_guarded ?? []).find((g) => g.session_id === id);
20529
20599
  const mtime = conv.mtime;
20530
20600
  try {
20531
20601
  if (!guarded) {
@@ -21402,7 +21472,7 @@ var init_sync_client = __esm({
21402
21472
  ownVersion = JSON.parse(readFileSync35(join42(dir, "../package.json"), "utf-8")).version || ownVersion;
21403
21473
  } catch {
21404
21474
  try {
21405
- if (true) ownVersion = "0.7.7";
21475
+ if (true) ownVersion = "0.7.9";
21406
21476
  } catch {
21407
21477
  }
21408
21478
  }
@@ -21481,8 +21551,8 @@ async function fetchNpmLatest() {
21481
21551
  headers: { accept: "application/vnd.npm.install-v1+json" }
21482
21552
  }, 5e3);
21483
21553
  if (!res.ok) return null;
21484
- const body = await res.json();
21485
- const v = body["dist-tags"]?.latest;
21554
+ const body2 = await res.json();
21555
+ const v = body2["dist-tags"]?.latest;
21486
21556
  return typeof v === "string" && v ? v : null;
21487
21557
  } catch {
21488
21558
  return null;
@@ -21664,9 +21734,9 @@ function envHome(varName, fallback) {
21664
21734
  const v = process.env[varName];
21665
21735
  return v && v.trim() ? v.trim() : fallback;
21666
21736
  }
21667
- function writeFileMkdir(path, body) {
21737
+ function writeFileMkdir(path, body2) {
21668
21738
  mkdirSync12(dirname21(path), { recursive: true });
21669
- writeFileSync12(path, body);
21739
+ writeFileSync12(path, body2);
21670
21740
  }
21671
21741
  function readJsonObject(path) {
21672
21742
  const raw = readFileSync37(path, "utf-8");
@@ -21748,8 +21818,8 @@ function registerCodexToml(path, spec) {
21748
21818
  const lines = prev.length ? prev.split("\n") : [];
21749
21819
  const start = lines.findIndex((l) => l.trim() === CODEX_HEADER);
21750
21820
  if (start === -1) {
21751
- const body = prev.length ? prev.replace(/\n*$/, "\n") + "\n" + block : block;
21752
- writeFileMkdir(path, body);
21821
+ const body2 = prev.length ? prev.replace(/\n*$/, "\n") + "\n" + block : block;
21822
+ writeFileMkdir(path, body2);
21753
21823
  return { id, label, path, state: "created" };
21754
21824
  }
21755
21825
  let end = lines.length;
@@ -22290,8 +22360,8 @@ function parseCommandText(content, format, fallbackName) {
22290
22360
  const t = parseScalarToml(content);
22291
22361
  return { name: t.name || fallbackName, description: t.description || "", body: t.prompt || "" };
22292
22362
  }
22293
- const { fm, body } = parseFrontmatter4(content);
22294
- return { name: fm.name || fallbackName, description: fm.description || "", body: body.trim() };
22363
+ const { fm, body: body2 } = parseFrontmatter4(content);
22364
+ return { name: fm.name || fallbackName, description: fm.description || "", body: body2.trim() };
22295
22365
  }
22296
22366
  function parseAgentText(content, format, fallbackName) {
22297
22367
  if (format === "toml") {
@@ -22302,8 +22372,8 @@ function parseAgentText(content, format, fallbackName) {
22302
22372
  body: t.developer_instructions || t.instructions || ""
22303
22373
  };
22304
22374
  }
22305
- const { fm, body } = parseFrontmatter4(content);
22306
- return { name: fm.name || fallbackName, description: fm.description || "", tools: fm.tools, body: body.trim() };
22375
+ const { fm, body: body2 } = parseFrontmatter4(content);
22376
+ return { name: fm.name || fallbackName, description: fm.description || "", tools: fm.tools, body: body2.trim() };
22307
22377
  }
22308
22378
  function readCommand(filePath, format) {
22309
22379
  return parseCommandText(readFileSync40(filePath, "utf-8"), format, base(filePath));
@@ -22960,8 +23030,8 @@ function planPull(rows, opts = {}) {
22960
23030
  continue;
22961
23031
  const extra2 = parseExtra(row);
22962
23032
  const name2 = extra2.skillName || row.title;
22963
- const body = extra2.body;
22964
- if (!name2 || typeof body !== "string" || !body.trim()) {
23033
+ const body2 = extra2.body;
23034
+ if (!name2 || typeof body2 !== "string" || !body2.trim()) {
22965
23035
  seenUnsupported.set("skill", (seenUnsupported.get("skill") || 0) + 1);
22966
23036
  continue;
22967
23037
  }
@@ -22970,7 +23040,7 @@ function planPull(rows, opts = {}) {
22970
23040
  const prev2 = skillsByName.get(name2);
22971
23041
  if (!prev2 || rank >= 0 && (prev2.rank < 0 || rank < prev2.rank)) {
22972
23042
  skillsByName.set(name2, {
22973
- body,
23043
+ body: body2,
22974
23044
  rank,
22975
23045
  truncated: extra2.bodyTruncated === true,
22976
23046
  redacted: extra2.bodySecretsRedacted === true
@@ -22983,8 +23053,8 @@ function planPull(rows, opts = {}) {
22983
23053
  continue;
22984
23054
  const extra2 = parseExtra(row);
22985
23055
  const name2 = extra2[type === "agent" ? "agentName" : "commandName"] || row.title;
22986
- const body = extra2.body;
22987
- if (!name2 || typeof body !== "string" || !body.trim() || extra2.bodyTruncated === true) {
23056
+ const body2 = extra2.body;
23057
+ if (!name2 || typeof body2 !== "string" || !body2.trim() || extra2.bodyTruncated === true) {
22988
23058
  seenUnsupported.set(type, (seenUnsupported.get(type) || 0) + 1);
22989
23059
  continue;
22990
23060
  }
@@ -22994,7 +23064,7 @@ function planPull(rows, opts = {}) {
22994
23064
  const prev2 = bucket.get(name2);
22995
23065
  if (!prev2 || rank >= 0 && (prev2.rank < 0 || rank < prev2.rank)) {
22996
23066
  bucket.set(name2, {
22997
- body,
23067
+ body: body2,
22998
23068
  rank,
22999
23069
  format: extra2.format === "toml" ? "toml" : "md",
23000
23070
  redacted: extra2.bodySecretsRedacted === true
@@ -23063,7 +23133,7 @@ function executePull(rows, opts = {}) {
23063
23133
  const explicit = new Set(opts.explicit ?? []);
23064
23134
  const { mcps, skills, codecs, unsupported } = planPull(rows, opts);
23065
23135
  const outcomes = [];
23066
- for (const { name, body, truncated, redacted, tools } of skills) {
23136
+ for (const { name, body: body2, truncated, redacted, tools } of skills) {
23067
23137
  for (const tool of tools) {
23068
23138
  const dir = join51(skillsDirFor(tool), name);
23069
23139
  const file = join51(dir, "SKILL.md");
@@ -23081,17 +23151,17 @@ function executePull(rows, opts = {}) {
23081
23151
  }
23082
23152
  try {
23083
23153
  mkdirSync16(dir, { recursive: true });
23084
- writeFileSync16(file, body);
23154
+ writeFileSync16(file, body2);
23085
23155
  outcomes.push({ type: "skill", name, tool, status: "written", path: file, redactedContent: redacted });
23086
23156
  } catch (e) {
23087
23157
  outcomes.push({ type: "skill", name, tool, status: "failed", reason: e instanceof Error ? e.message : "write failed" });
23088
23158
  }
23089
23159
  }
23090
23160
  }
23091
- for (const { type, name, body, format, redacted, tools } of codecs) {
23161
+ for (const { type, name, body: body2, format, redacted, tools } of codecs) {
23092
23162
  let art;
23093
23163
  try {
23094
- art = type === "agent" ? parseAgentText(body, format, name) : parseCommandText(body, format, name);
23164
+ art = type === "agent" ? parseAgentText(body2, format, name) : parseCommandText(body2, format, name);
23095
23165
  } catch (e) {
23096
23166
  for (const tool of tools) {
23097
23167
  outcomes.push({ type, name, tool, status: "failed", reason: `could not parse the stored body: ${e instanceof Error ? e.message : "failed"}` });
@@ -24370,11 +24440,11 @@ async function collectCode(opts) {
24370
24440
  for (const block of log22.split("\0END\0")) {
24371
24441
  if (!block.includes("\0"))
24372
24442
  continue;
24373
- const [h, body] = [block.slice(0, block.indexOf("\0")).trim(), block.slice(block.indexOf("\0") + 1)];
24443
+ const [h, body2] = [block.slice(0, block.indexOf("\0")).trim(), block.slice(block.indexOf("\0") + 1)];
24374
24444
  if (!h)
24375
24445
  continue;
24376
24446
  totalCommits++;
24377
- if (AI_RE.test(body)) {
24447
+ if (AI_RE.test(body2)) {
24378
24448
  aiCommits++;
24379
24449
  try {
24380
24450
  const files2 = execSync4(`git -C "${ws}" show --format= --name-only ${h}`, { encoding: "utf8", timeout: 2e4, maxBuffer: 64 * 1024 * 1024, stdio: ["ignore", "pipe", "ignore"] });
@@ -25417,8 +25487,8 @@ async function runPull(base3, opts) {
25417
25487
  try {
25418
25488
  const res = await fetchWithTimeout(`${base3}/api/toolkit/browse/${type}?limit=1000`, { headers });
25419
25489
  if (!res.ok) continue;
25420
- const body = await res.json();
25421
- for (const it of body.items || []) rows.push(it);
25490
+ const body2 = await res.json();
25491
+ for (const it of body2.items || []) rows.push(it);
25422
25492
  } catch {
25423
25493
  }
25424
25494
  }
@@ -25563,7 +25633,7 @@ var init_intent_drain = __esm({
25563
25633
  ownVersion2 = JSON.parse(readFileSync45(join56(dir, "../package.json"), "utf-8")).version || ownVersion2;
25564
25634
  } catch {
25565
25635
  try {
25566
- if (true) ownVersion2 = "0.7.7";
25636
+ if (true) ownVersion2 = "0.7.9";
25567
25637
  } catch {
25568
25638
  }
25569
25639
  }
@@ -25604,7 +25674,7 @@ function context(opts = {}) {
25604
25674
  throw new TeamConfigError("Not joined to a team. Run `chat-recall team join <invite-token>`.");
25605
25675
  return { serverUrl: t.serverUrl, token, handle: t.memberHandle ?? "", teamId: t.teamId };
25606
25676
  }
25607
- async function http(ctx, method, path, body) {
25677
+ async function http(ctx, method, path, body2) {
25608
25678
  const url = ctx.serverUrl.replace(/\/+$/, "") + path;
25609
25679
  const r = await fetch(url, {
25610
25680
  method,
@@ -25613,7 +25683,7 @@ async function http(ctx, method, path, body) {
25613
25683
  "Content-Type": "application/json",
25614
25684
  "Accept": "application/json"
25615
25685
  },
25616
- body: body == null ? void 0 : JSON.stringify(body)
25686
+ body: body2 == null ? void 0 : JSON.stringify(body2)
25617
25687
  });
25618
25688
  const text = await r.text();
25619
25689
  let parsed = void 0;
@@ -25750,10 +25820,10 @@ var init_team_client = __esm({
25750
25820
  TeamHttpError = class extends Error {
25751
25821
  status;
25752
25822
  body;
25753
- constructor(msg, status, body) {
25823
+ constructor(msg, status, body2) {
25754
25824
  super(msg);
25755
25825
  this.status = status;
25756
- this.body = body;
25826
+ this.body = body2;
25757
25827
  }
25758
25828
  };
25759
25829
  }
@@ -25846,8 +25916,8 @@ async function mergePullResult(opts) {
25846
25916
  report.skipped.push({ artifactId: a.id, path: "(no installed target tool)", reason: "no-target-tool" });
25847
25917
  continue;
25848
25918
  }
25849
- const body = Buffer.from(a.bodyB64, "base64");
25850
- const sha = createHash14("sha256").update(body).digest("hex");
25919
+ const body2 = Buffer.from(a.bodyB64, "base64");
25920
+ const sha = createHash14("sha256").update(body2).digest("hex");
25851
25921
  for (const tool of targets) {
25852
25922
  const path = installPathFor(a, tool);
25853
25923
  if (!path)
@@ -25860,7 +25930,7 @@ async function mergePullResult(opts) {
25860
25930
  continue;
25861
25931
  }
25862
25932
  mkdirSync20(dirname27(path), { recursive: true });
25863
- writeFileSync20(path, body);
25933
+ writeFileSync20(path, body2);
25864
25934
  pending.push({ artifactId: a.id, tool, artifactType: a.type, artifactName: a.name, sha256: sha, installedAt: Date.now() });
25865
25935
  report.written.push({ artifactId: a.id, path });
25866
25936
  } catch (err) {
@@ -26166,7 +26236,7 @@ function context2() {
26166
26236
  throw new VaultConfigError(`Env var ${s.tokenRef} is not set.`);
26167
26237
  return { serverUrl: s.serverUrl, teamId: s.teamId, token };
26168
26238
  }
26169
- async function api(ctx, method, path, body) {
26239
+ async function api(ctx, method, path, body2) {
26170
26240
  const doFetch = () => fetch(ctx.serverUrl.replace(/\/+$/, "") + path, {
26171
26241
  method,
26172
26242
  headers: {
@@ -26174,7 +26244,7 @@ async function api(ctx, method, path, body) {
26174
26244
  "Content-Type": "application/json",
26175
26245
  "Accept": "application/json"
26176
26246
  },
26177
- body: body == null ? void 0 : JSON.stringify(body)
26247
+ body: body2 == null ? void 0 : JSON.stringify(body2)
26178
26248
  });
26179
26249
  let r;
26180
26250
  try {
@@ -26253,13 +26323,13 @@ async function vaultEnableWithRemote(passphrase, remote, opts = {}) {
26253
26323
  body: JSON.stringify({ saltHex: result.saltHex, keyId: result.keyId })
26254
26324
  });
26255
26325
  if (r.status === 409) {
26256
- const body = await r.json();
26257
- if (body.saltHex && body.saltHex !== result.saltHex) {
26258
- const redone = vaultEnable(passphrase, { existingSaltHex: body.saltHex });
26259
- if (body.keyId && body.keyId !== redone.keyId) {
26326
+ const body2 = await r.json();
26327
+ if (body2.saltHex && body2.saltHex !== result.saltHex) {
26328
+ const redone = vaultEnable(passphrase, { existingSaltHex: body2.saltHex });
26329
+ if (body2.keyId && body2.keyId !== redone.keyId) {
26260
26330
  throw new VaultPassphraseMismatchError("Another device published a vault with a different passphrase. Nothing was changed here.");
26261
26331
  }
26262
- return { ...redone, saltSource: "server", keyIdMatches: body.keyId ? true : void 0 };
26332
+ return { ...redone, saltSource: "server", keyIdMatches: body2.keyId ? true : void 0 };
26263
26333
  }
26264
26334
  }
26265
26335
  } catch (err) {
@@ -26421,10 +26491,10 @@ var init_vault_client = __esm({
26421
26491
  VaultHttpError = class extends Error {
26422
26492
  status;
26423
26493
  body;
26424
- constructor(msg, status, body) {
26494
+ constructor(msg, status, body2) {
26425
26495
  super(msg);
26426
26496
  this.status = status;
26427
- this.body = body;
26497
+ this.body = body2;
26428
26498
  }
26429
26499
  };
26430
26500
  uploadKey = (sessionId, tool) => `${sessionId}\0${tool}`;
@@ -27321,15 +27391,15 @@ async function deviceLogin(opts, onPrompt) {
27321
27391
  code_verifier: codeVerifier
27322
27392
  })
27323
27393
  });
27324
- const body = await res.json().catch(() => ({}));
27325
- if (res.ok && typeof body.access_token === "string") {
27394
+ const body2 = await res.json().catch(() => ({}));
27395
+ if (res.ok && typeof body2.access_token === "string") {
27326
27396
  return {
27327
- accessToken: body.access_token,
27328
- refreshToken: typeof body.refresh_token === "string" ? body.refresh_token : void 0,
27329
- expiresIn: typeof body.expires_in === "number" ? body.expires_in : 0
27397
+ accessToken: body2.access_token,
27398
+ refreshToken: typeof body2.refresh_token === "string" ? body2.refresh_token : void 0,
27399
+ expiresIn: typeof body2.expires_in === "number" ? body2.expires_in : 0
27330
27400
  };
27331
27401
  }
27332
- const err = body.error;
27402
+ const err = body2.error;
27333
27403
  if (err === "authorization_pending") continue;
27334
27404
  if (err === "slow_down") {
27335
27405
  interval += 5e3;
@@ -27369,14 +27439,14 @@ async function betterAuthDeviceLogin(serverUrl, onPrompt) {
27369
27439
  client_id: BETTER_AUTH_CLI_CLIENT_ID
27370
27440
  })
27371
27441
  });
27372
- const body = await res.json().catch(() => ({}));
27373
- if (res.ok && typeof body.access_token === "string") {
27442
+ const body2 = await res.json().catch(() => ({}));
27443
+ if (res.ok && typeof body2.access_token === "string") {
27374
27444
  return {
27375
- accessToken: body.access_token,
27376
- expiresIn: typeof body.expires_in === "number" ? body.expires_in : 0
27445
+ accessToken: body2.access_token,
27446
+ expiresIn: typeof body2.expires_in === "number" ? body2.expires_in : 0
27377
27447
  };
27378
27448
  }
27379
- const err = body.error;
27449
+ const err = body2.error;
27380
27450
  if (err === "authorization_pending") continue;
27381
27451
  if (err === "slow_down") {
27382
27452
  interval += 5e3;
@@ -27466,8 +27536,8 @@ async function selectSessions(target, opts, fetchImpl = fetch) {
27466
27536
  headers: { authorization: `Bearer ${target.token}` }
27467
27537
  });
27468
27538
  if (!res.ok) throw new Error(`list failed: HTTP ${res.status}`);
27469
- const body = await res.json();
27470
- const page = body.sessions ?? [];
27539
+ const body2 = await res.json();
27540
+ const page = body2.sessions ?? [];
27471
27541
  if (page.length === 0) break;
27472
27542
  for (const row of page) {
27473
27543
  if (!row.sessionId) continue;
@@ -27550,9 +27620,9 @@ async function restoreSessions(ids, opts = {}) {
27550
27620
  body: JSON.stringify({ session_ids: unique.slice(i, i + BATCH) })
27551
27621
  });
27552
27622
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
27553
- const body = await res.json();
27554
- restored += body.restored ?? 0;
27555
- notDeleted += (body.notDeleted ?? []).length;
27623
+ const body2 = await res.json();
27624
+ restored += body2.restored ?? 0;
27625
+ notDeleted += (body2.notDeleted ?? []).length;
27556
27626
  }
27557
27627
  out.perTarget[t.serverUrl] = { restored, notDeleted };
27558
27628
  best = Math.max(best, restored);
@@ -27618,6 +27688,104 @@ function resumeCommandFor(sessionId, tool) {
27618
27688
  }
27619
27689
  }
27620
27690
 
27691
+ // ../engine/dist/mcp/show-render.js
27692
+ var BODY_LIMIT = 2e3;
27693
+ var EDGE = 100;
27694
+ var INDENT = " ";
27695
+ var oneLine = (v) => String(v).replace(/\s*\n\s*/g, " \u23CE ");
27696
+ var indent = (text) => text.split("\n").map((l) => INDENT + l).join("\n");
27697
+ function safeSlice(s, start, end) {
27698
+ const lo = start > 0 && /[\uDC00-\uDFFF]/.test(s[start] ?? "") ? start - 1 : start;
27699
+ const hi = end < s.length && /[\uD800-\uDBFF]/.test(s[end - 1] ?? "") ? end + 1 : end;
27700
+ return s.slice(lo, hi);
27701
+ }
27702
+ function body(text, line, opts) {
27703
+ if (opts.full || text.length <= BODY_LIMIT)
27704
+ return indent(text);
27705
+ const lines = text.split("\n").length;
27706
+ const cut = text.length - 2 * EDGE;
27707
+ const how = opts.expandHint ? ` ${opts.expandHint(line)}` : "";
27708
+ return [
27709
+ indent(safeSlice(text, 0, EDGE)),
27710
+ `${INDENT}\u2026 ${cut} characters cut (${text.length} in all, ${lines} lines).${how} \u2026`,
27711
+ indent(safeSlice(text, text.length - EDGE, text.length))
27712
+ ].join("\n");
27713
+ }
27714
+ function resultText(result) {
27715
+ if (typeof result === "string")
27716
+ return result;
27717
+ if (Array.isArray(result)) {
27718
+ return result.map((b) => {
27719
+ if (b?.type === "text")
27720
+ return String(b.text ?? "");
27721
+ if (b?.type === "image")
27722
+ return "[image]";
27723
+ if (b?.type === "tool_reference")
27724
+ return `[tool_reference: ${b.tool_name ?? ""}]`;
27725
+ return JSON.stringify(b);
27726
+ }).join("\n");
27727
+ }
27728
+ return JSON.stringify(result);
27729
+ }
27730
+ function renderToolCall(tc, line, opts) {
27731
+ const inp = tc.input && typeof tc.input === "object" ? tc.input : {};
27732
+ const out = [];
27733
+ if (tc.name === "Bash" && inp.command !== void 0) {
27734
+ const desc = inp.description ? ` # ${oneLine(inp.description)}` : "";
27735
+ out.push(`[Bash]${desc}
27736
+ $ ${oneLine(inp.command)}`);
27737
+ } else if (inp.file_path !== void 0) {
27738
+ const inline = {};
27739
+ const blocks = [];
27740
+ for (const [k, v] of Object.entries(inp)) {
27741
+ if (k === "file_path")
27742
+ continue;
27743
+ if (typeof v === "string" && (v.includes("\n") || v.length > 120))
27744
+ blocks.push([k, v]);
27745
+ else
27746
+ inline[k] = v;
27747
+ }
27748
+ const opts_ = Object.keys(inline).length ? ` ${JSON.stringify(inline)}` : "";
27749
+ out.push(`[${tc.name}] ${inp.file_path}${opts_}`);
27750
+ for (const [k, v] of blocks)
27751
+ out.push(` ${k}:`, body(v, line, opts));
27752
+ } else if (typeof tc.input === "string") {
27753
+ out.push(`[${tc.name}]`, body(tc.input, line, opts));
27754
+ } else {
27755
+ const json = JSON.stringify(tc.input ?? {});
27756
+ if (opts.full || json.length <= BODY_LIMIT)
27757
+ out.push(`[${tc.name}] ${oneLine(json)}`);
27758
+ else
27759
+ out.push(`[${tc.name}]`, body(json, line, opts));
27760
+ }
27761
+ if (tc.result !== void 0) {
27762
+ out.push(tc.isError ? " \u2192 error:" : " \u2192 result:", body(resultText(tc.result), line, opts));
27763
+ }
27764
+ return out.join("\n");
27765
+ }
27766
+ function renderShowMessages(messages, opts = {}) {
27767
+ const out = [];
27768
+ for (const msg of messages) {
27769
+ const text = msg.content ?? "";
27770
+ const thinking = msg.thinking ?? "";
27771
+ const calls = msg.toolCalls ?? [];
27772
+ if (!text.trim() && !thinking.trim() && !calls.length && msg.thinking !== void 0)
27773
+ continue;
27774
+ out.push(`**${msg.role}** (line ${msg.line})`);
27775
+ if (thinking.trim())
27776
+ out.push(`_(thinking)_
27777
+ ${thinking}`);
27778
+ if (text.trim())
27779
+ out.push(text);
27780
+ for (const tc of calls)
27781
+ out.push(renderToolCall(tc, msg.line, opts));
27782
+ if (!text.trim() && !thinking.trim() && !calls.length)
27783
+ out.push("_(empty)_");
27784
+ out.push("");
27785
+ }
27786
+ return out;
27787
+ }
27788
+
27621
27789
  // src/cli.ts
27622
27790
  init_paths();
27623
27791
  init_claude2();
@@ -27850,38 +28018,38 @@ async function serverGetSoft(path) {
27850
28018
  const t = requireTarget();
27851
28019
  const res = await fetch(t.base + path, { headers: t.token ? { authorization: `Bearer ${t.token}` } : {} });
27852
28020
  if (res.status === 202 || res.status === 404) {
27853
- const body = await res.json().catch(() => ({}));
27854
- return { status: res.status, data: null, message: body.message };
28021
+ const body2 = await res.json().catch(() => ({}));
28022
+ return { status: res.status, data: null, message: body2.message };
27855
28023
  }
27856
28024
  if (!res.ok) throw new Error(`server ${path}: HTTP ${res.status} ${await res.text().catch(() => "")}`);
27857
28025
  return { status: res.status, data: await readJsonBody(res, t.base, `GET ${path}`) };
27858
28026
  }
27859
- async function serverPost(path, body) {
28027
+ async function serverPost(path, body2) {
27860
28028
  const t = requireTarget();
27861
28029
  const res = await fetch(t.base + path, {
27862
28030
  method: "POST",
27863
28031
  headers: t.token ? { "content-type": "application/json", authorization: `Bearer ${t.token}` } : { "content-type": "application/json" },
27864
- body: JSON.stringify(body)
28032
+ body: JSON.stringify(body2)
27865
28033
  });
27866
28034
  if (!res.ok) throw new Error(`server ${path}: HTTP ${res.status} ${await res.text().catch(() => "")}`);
27867
28035
  return readJsonBody(res, t.base, `POST ${path}`);
27868
28036
  }
27869
- async function serverPatch(path, body) {
28037
+ async function serverPatch(path, body2) {
27870
28038
  const t = requireTarget();
27871
28039
  const res = await fetch(t.base + path, {
27872
28040
  method: "PATCH",
27873
28041
  headers: t.token ? { "content-type": "application/json", authorization: `Bearer ${t.token}` } : { "content-type": "application/json" },
27874
- body: JSON.stringify(body)
28042
+ body: JSON.stringify(body2)
27875
28043
  });
27876
28044
  if (!res.ok) throw new Error(`server ${path}: HTTP ${res.status} ${await res.text().catch(() => "")}`);
27877
28045
  return readJsonBody(res, t.base, `PATCH ${path}`);
27878
28046
  }
27879
- async function serverDelete(path, body) {
28047
+ async function serverDelete(path, body2) {
27880
28048
  const t = requireTarget();
27881
28049
  const res = await fetch(t.base + path, {
27882
28050
  method: "DELETE",
27883
28051
  headers: t.token ? { "content-type": "application/json", authorization: `Bearer ${t.token}` } : { "content-type": "application/json" },
27884
- body: JSON.stringify(body)
28052
+ body: JSON.stringify(body2)
27885
28053
  });
27886
28054
  if (!res.ok) throw new Error(`server ${path}: HTTP ${res.status} ${await res.text().catch(() => "")}`);
27887
28055
  return readJsonBody(res, t.base, `DELETE ${path}`);
@@ -28168,15 +28336,15 @@ program.command("init").description("Set up chat-recall: connect to your server,
28168
28336
  continue;
28169
28337
  }
28170
28338
  const text = await res.text();
28171
- let body;
28339
+ let body2;
28172
28340
  try {
28173
- body = JSON.parse(text);
28341
+ body2 = JSON.parse(text);
28174
28342
  } catch {
28175
28343
  askFailed.push(`${t.serverUrl} (not JSON: ${JSON.stringify(text.trim().slice(0, 40))})`);
28176
28344
  continue;
28177
28345
  }
28178
28346
  answered++;
28179
- for (const it of body.items || []) rows.push(it);
28347
+ for (const it of body2.items || []) rows.push(it);
28180
28348
  } catch (e) {
28181
28349
  askFailed.push(`${t.serverUrl} (${describeProbeError(e)})`);
28182
28350
  }
@@ -28425,7 +28593,7 @@ program.command("optimize").description("Deprecated: storage is server-side now,
28425
28593
  console.log(chalk2.dim("Run `chat-recall sync` to ship sessions; the server manages its own storage."));
28426
28594
  process.exit(0);
28427
28595
  });
28428
- program.command("show <session_id>").description("Show conversation content from a session (requires login)").option("-m, --messages <number>", "Number of messages to show", "10").option("-f, --full", "Show full conversation (all messages)", false).action(async (sessionId, options) => {
28596
+ program.command("show <session_id>").description("Show conversation content from a session (requires login)").option("-m, --messages <number>", "Number of messages to show", "10").option("-f, --full", "Show full conversation (all messages)", false).option("-l, --line <number>", "Show only the message at this line, with every tool input and result whole").action(async (sessionId, options) => {
28429
28597
  try {
28430
28598
  const soft = await serverGetSoft(`/api/conversations/${encodeURIComponent(sessionId)}?limit=0`);
28431
28599
  if (!soft.data || soft.data.messages.length === 0) {
@@ -28435,20 +28603,21 @@ program.command("show <session_id>").description("Show conversation content from
28435
28603
  const messagesList = soft.data.messages;
28436
28604
  console.log(chalk2.bold("Session:"), sessionId);
28437
28605
  console.log();
28438
- const maxMessages = parseInt(options.messages, 10);
28439
- const displayMessages = options.full ? messagesList : messagesList.slice(0, maxMessages);
28440
- for (const msg of displayMessages) {
28441
- const text = msg.content;
28442
- if (msg.role === "user") {
28443
- console.log(`${chalk2.bold.blue("User")} ${chalk2.dim(`(line ${msg.line})`)}`);
28444
- } else if (msg.role === "assistant") {
28445
- console.log(`${chalk2.bold.green("Assistant")} ${chalk2.dim(`(line ${msg.line})`)}`);
28446
- } else {
28447
- console.log(chalk2.bold.yellow(msg.role));
28606
+ if (options.line !== void 0) {
28607
+ const line = parseInt(options.line, 10);
28608
+ const hit = messagesList.find((m) => m.line === line);
28609
+ if (!hit) {
28610
+ const lines = messagesList.map((m) => m.line);
28611
+ console.log(chalk2.yellow(`No message at line ${options.line}. Its lines run from ${Math.min(...lines)} to ${Math.max(...lines)}.`));
28612
+ process.exit(1);
28448
28613
  }
28449
- console.log(text);
28450
- console.log();
28614
+ console.log(renderShowMessages([hit], { full: true }).join("\n"));
28615
+ return;
28451
28616
  }
28617
+ const maxMessages = parseInt(options.messages, 10);
28618
+ const displayMessages = options.full ? messagesList : messagesList.slice(0, maxMessages);
28619
+ const expandHint = (line) => `Run chat-recall show ${sessionId} --line ${line} for the whole text.`;
28620
+ console.log(renderShowMessages(displayMessages, { expandHint }).join("\n"));
28452
28621
  console.log(chalk2.dim(`Showing ${displayMessages.length} of ${messagesList.length} messages. Use --full for the complete conversation.`));
28453
28622
  {
28454
28623
  const rc = resumeCommandFor(sessionId);
@@ -28661,8 +28830,8 @@ program.command("feedback").argument("<message...>", "what you want to say \u201
28661
28830
  signal: AbortSignal.timeout(1e4)
28662
28831
  });
28663
28832
  if (!res.ok) {
28664
- const body = await res.json().catch(() => ({}));
28665
- console.error(chalk2.red(`Could not send: ${body.error || res.status}`));
28833
+ const body2 = await res.json().catch(() => ({}));
28834
+ console.error(chalk2.red(`Could not send: ${body2.error || res.status}`));
28666
28835
  process.exitCode = 1;
28667
28836
  return;
28668
28837
  }
@@ -29079,8 +29248,8 @@ program.command("verify").description("Check that the server holds everything th
29079
29248
  if (token) headers.authorization = `Bearer ${token}`;
29080
29249
  const res = await fetchWithTimeout2(`${server}/api/status/archives`, { headers }, 12e4);
29081
29250
  if (!res.ok) throw new Error(`${server}: HTTP ${res.status} from /api/status/archives`);
29082
- const body = await res.json();
29083
- return new Map((body.archives || []).map((a) => [a.id, Number(a.size) || 0]));
29251
+ const body2 = await res.json();
29252
+ return new Map((body2.archives || []).map((a) => [a.id, Number(a.size) || 0]));
29084
29253
  }
29085
29254
  };
29086
29255
  let exitCode = 0;
@@ -29132,8 +29301,8 @@ ${t.serverUrl}`));
29132
29301
  console.log(` ${f.sessionId.slice(0, 8)} server records unavailable (HTTP ${res.status})`);
29133
29302
  continue;
29134
29303
  }
29135
- const body = await res.json();
29136
- serverIds = new Set(body.records || []);
29304
+ const body2 = await res.json();
29305
+ serverIds = new Set(body2.records || []);
29137
29306
  } catch (e) {
29138
29307
  console.log(` ${f.sessionId.slice(0, 8)} record fetch failed: ${e instanceof Error ? e.message : e}`);
29139
29308
  continue;
@@ -29453,8 +29622,8 @@ toolkit.command("pull").description("Install artifacts this device is missing, f
29453
29622
  headers: t.token ? { authorization: `Bearer ${t.token}` } : {}
29454
29623
  });
29455
29624
  if (!res.ok) continue;
29456
- const body = await res.json();
29457
- for (const it of body.items || []) rows.push(it);
29625
+ const body2 = await res.json();
29626
+ for (const it of body2.items || []) rows.push(it);
29458
29627
  } catch (err) {
29459
29628
  console.log(chalk2.dim(` (${t.serverUrl} ${type}: ${err instanceof Error ? err.message : err})`));
29460
29629
  }
@@ -29696,13 +29865,13 @@ team.command("publish <type> <name> <file>").description("Publish a local file a
29696
29865
  process.exit(1);
29697
29866
  }
29698
29867
  const { readFileSync: readFileSync50 } = await import("fs");
29699
- const body = readFileSync50(file);
29868
+ const body2 = readFileSync50(file);
29700
29869
  const { teamPublish: teamPublish2 } = await Promise.resolve().then(() => (init_team_client(), team_client_exports));
29701
29870
  const a = await teamPublish2({
29702
29871
  type,
29703
29872
  tool: opts.tool,
29704
29873
  name,
29705
- body,
29874
+ body: body2,
29706
29875
  pinnedTo: opts.pinnedTo
29707
29876
  });
29708
29877
  console.log(chalk2.green(`\u2713 Published ${chalk2.bold(type + "/" + name)} v${a.version}`));
@@ -29995,13 +30164,13 @@ program.command("task-hook").description("Move a board card when a prompt or a c
29995
30164
  4e3
29996
30165
  );
29997
30166
  if (!res.ok) return null;
29998
- const body = await res.json().catch(() => ({}));
29999
- return body.task ?? null;
30167
+ const body2 = await res.json().catch(() => ({}));
30168
+ return body2.task ?? null;
30000
30169
  };
30001
- const patchCard = async (id, body) => {
30170
+ const patchCard = async (id, body2) => {
30002
30171
  const res = await fetchWithTimeout2(
30003
30172
  `${target.base}/api/tasks/${encodeURIComponent(id)}`,
30004
- { method: "PATCH", headers, body: JSON.stringify(body) },
30173
+ { method: "PATCH", headers, body: JSON.stringify(body2) },
30005
30174
  6e3
30006
30175
  );
30007
30176
  return res.ok;
@@ -30166,8 +30335,8 @@ program.command("install-hooks").description("Install Claude Code hooks (Stop +
30166
30335
  for (const target of reg.guardTargets()) {
30167
30336
  if (!existsSync58(target.configPath)) continue;
30168
30337
  if (target.tool === "opencode") {
30169
- const body = readFileSync50(target.configPath, "utf-8");
30170
- if (!body.includes("chat-recall install-hooks")) continue;
30338
+ const body2 = readFileSync50(target.configPath, "utf-8");
30339
+ if (!body2.includes("chat-recall install-hooks")) continue;
30171
30340
  unlinkSync4(target.configPath);
30172
30341
  removed += 1;
30173
30342
  } else {