chat-recall 0.6.8 → 0.7.0

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.
@@ -5196,11 +5196,10 @@ var init_secret_redactor = __esm({
5196
5196
  }
5197
5197
  });
5198
5198
 
5199
- // ../engine/dist/parsers/chunker.js
5200
- var init_chunker = __esm({
5201
- "../engine/dist/parsers/chunker.js"() {
5199
+ // ../engine/dist/parsers/banners.js
5200
+ var init_banners = __esm({
5201
+ "../engine/dist/parsers/banners.js"() {
5202
5202
  "use strict";
5203
- init_secret_redactor();
5204
5203
  }
5205
5204
  });
5206
5205
 
@@ -5435,6 +5434,10 @@ function applyDecisions(roots, includeExcluded) {
5435
5434
  function applyExclusions(roots, includeExcluded) {
5436
5435
  return applyDecisions(roots, includeExcluded);
5437
5436
  }
5437
+ function geminiTmpDirs(opts = {}) {
5438
+ const overridden = !!(process.env.CHAT_RECALL_GEMINI_HOME || sources().geminiHome);
5439
+ return applyExclusions(siblingHomes(geminiHomeDir(), overridden, "tmp"), opts.includeExcluded);
5440
+ }
5438
5441
  function codexSessionDirs(opts = {}) {
5439
5442
  const overridden = !!(process.env.CHAT_RECALL_CODEX_HOME || sources().codexHome);
5440
5443
  return applyExclusions(siblingHomes(codexHomeDir(), overridden, "sessions"), opts.includeExcluded);
@@ -5790,6 +5793,10 @@ function ensureBootstrapped() {
5790
5793
  _bootstrapper();
5791
5794
  }
5792
5795
  }
5796
+ function listAvailableBackends() {
5797
+ ensureBootstrapped();
5798
+ return [...REGISTRY.values()].filter((b) => b.isAvailable());
5799
+ }
5793
5800
  var REGISTRY, _bootstrapper, _bootstrapped;
5794
5801
  var init_tool_backend = __esm({
5795
5802
  "../engine/dist/core/tool-backend.js"() {
@@ -9151,6 +9158,28 @@ var init_backends = __esm({
9151
9158
  }
9152
9159
  });
9153
9160
 
9161
+ // ../engine/dist/core/session-multi-tool.js
9162
+ function extractTurnsAny(sessionId, opts = {}) {
9163
+ const backend = getBackendForId(sessionId);
9164
+ if (!backend)
9165
+ return { sessionId, found: false, turns: [], startMs: 0, endMs: 0 };
9166
+ return memoInSessionScope(`turns:${sessionId}:${opts.maxTurns ?? ""}:${opts.assistantMax ?? ""}`, () => backend.extractTurns(sessionId, opts));
9167
+ }
9168
+ function replaySessionAny(sessionId) {
9169
+ const backend = getBackendForId(sessionId);
9170
+ if (!backend)
9171
+ return { sessionId, found: false, projectPath: "", files: [], totalLinesAdded: 0, totalLinesRemoved: 0 };
9172
+ return memoInSessionScope(`replay:${sessionId}`, () => backend.replay(sessionId));
9173
+ }
9174
+ var init_session_multi_tool = __esm({
9175
+ "../engine/dist/core/session-multi-tool.js"() {
9176
+ "use strict";
9177
+ init_tool_backend();
9178
+ init_live_session_scan();
9179
+ init_backends();
9180
+ }
9181
+ });
9182
+
9154
9183
  // ../engine/dist/core/session-outcome.js
9155
9184
  function extractDecisionsFromTurn(turn) {
9156
9185
  if (turn.kind !== "assistant_text" || !turn.text)
@@ -9247,7 +9276,7 @@ function computeOutcome(sessionId, opts = {}) {
9247
9276
  };
9248
9277
  if (!backend)
9249
9278
  return notFound;
9250
- const turnsRes = backend.extractTurns(sessionId, { assistantMax: 2e3 });
9279
+ const turnsRes = extractTurnsAny(sessionId, { assistantMax: 2e3 });
9251
9280
  if (!turnsRes.found)
9252
9281
  return notFound;
9253
9282
  const decisions = [];
@@ -9286,7 +9315,7 @@ function computeOutcome(sessionId, opts = {}) {
9286
9315
  totalLinesAdded = fast.totalLinesAdded;
9287
9316
  totalLinesRemoved = fast.totalLinesRemoved;
9288
9317
  } else {
9289
- const replay = backend.replay(sessionId);
9318
+ const replay = replaySessionAny(sessionId);
9290
9319
  filesChanged = replay.files.map((f) => f.file);
9291
9320
  totalLinesAdded = replay.totalLinesAdded;
9292
9321
  totalLinesRemoved = replay.totalLinesRemoved;
@@ -9325,6 +9354,7 @@ var init_session_outcome = __esm({
9325
9354
  init_session_sentiment();
9326
9355
  init_session_git();
9327
9356
  init_tool_backend();
9357
+ init_session_multi_tool();
9328
9358
  init_backends();
9329
9359
  DECISION_PATTERNS = [
9330
9360
  /\b(?:I'?ll|I will|I'?m going to|Going to|Let me|We'?ll|We will|We should|Let'?s|I'?m about to|I'?m going to)\b[^\n.!?]*[.!?]/i,
@@ -9517,6 +9547,7 @@ var UUID_RE, ClaudeBackend, claudeBackend;
9517
9547
  var init_claude = __esm({
9518
9548
  "../engine/dist/core/backends/claude.js"() {
9519
9549
  "use strict";
9550
+ init_live_session_scan();
9520
9551
  init_tool_paths();
9521
9552
  init_live_session_scan();
9522
9553
  init_session_outcome();
@@ -9779,6 +9810,9 @@ var init_claude = __esm({
9779
9810
  * splits show up alongside the parent.
9780
9811
  */
9781
9812
  readEvents(rawId) {
9813
+ return memoInSessionScope(`events:claude:${rawId}`, () => this.#readEventsUncached(rawId));
9814
+ }
9815
+ #readEventsUncached(rawId) {
9782
9816
  const groups = resolveSessionContentGroups(rawId);
9783
9817
  if (groups.length === 0)
9784
9818
  return [];
@@ -10106,7 +10140,7 @@ function hasSubagentsDir(sessionPath) {
10106
10140
  var init_session = __esm({
10107
10141
  "../engine/dist/parsers/session.js"() {
10108
10142
  "use strict";
10109
- init_chunker();
10143
+ init_banners();
10110
10144
  init_claude();
10111
10145
  init_tool_paths();
10112
10146
  init_project_dir_name();
@@ -10215,11 +10249,54 @@ var init_shadow = __esm({
10215
10249
  });
10216
10250
 
10217
10251
  // ../engine/dist/core/live-session-scan.js
10252
+ var live_session_scan_exports = {};
10253
+ __export(live_session_scan_exports, {
10254
+ MAX_EVENT_LINE_BYTES: () => MAX_EVENT_LINE_BYTES,
10255
+ detectTool: () => detectTool,
10256
+ findCodexSessionFile: () => findCodexSessionFile,
10257
+ findGeminiSessionFile: () => findGeminiSessionFile,
10258
+ findSessionFile: () => findSessionFile,
10259
+ findSessionFiles: () => findSessionFiles,
10260
+ invalidateGeminiSessionIndex: () => invalidateGeminiSessionIndex,
10261
+ invalidateSessionFileIndex: () => invalidateSessionFileIndex,
10262
+ liveScanModifiedFiles: () => liveScanModifiedFiles,
10263
+ liveScanRecentEdits: () => liveScanRecentEdits,
10264
+ liveScanSessionEdits: () => liveScanSessionEdits,
10265
+ memoInSessionScope: () => memoInSessionScope,
10266
+ readGeminiMessages: () => readGeminiMessages,
10267
+ readHeadSync: () => readHeadSync,
10268
+ readSessionGroupText: () => readSessionGroupText,
10269
+ resolveSessionContentGroups: () => resolveSessionContentGroups,
10270
+ resolveSessionContentPaths: () => resolveSessionContentPaths,
10271
+ withSessionReadCache: () => withSessionReadCache,
10272
+ withSessionScanScope: () => withSessionScanScope
10273
+ });
10218
10274
  import { existsSync as existsSync13, readdirSync as readdirSync10, readFileSync as readFileSync9, statSync as statSync11, openSync as openSync6, readSync as readSync6, closeSync as closeSync6 } from "fs";
10219
10275
  import { join as join13, basename as basename8 } from "path";
10276
+ import { createHash as createHash2 } from "crypto";
10277
+ function lazyGeminiProjectsJson() {
10278
+ return join13(geminiHomeDir(), "projects.json");
10279
+ }
10280
+ function detectTool(sessionId) {
10281
+ return getBackendForId(sessionId)?.id ?? "claude";
10282
+ }
10283
+ async function withSessionScanScope(fn) {
10284
+ scanScopeDepth++;
10285
+ try {
10286
+ return await fn();
10287
+ } finally {
10288
+ if (--scanScopeDepth === 0) {
10289
+ invalidateSessionFileIndex();
10290
+ invalidateGeminiSessionIndex();
10291
+ }
10292
+ }
10293
+ }
10220
10294
  function findSessionFile(sessionId) {
10221
10295
  return sessionFileIndex().get(sessionId)?.[0] ?? null;
10222
10296
  }
10297
+ function invalidateSessionFileIndex() {
10298
+ indexCache = null;
10299
+ }
10223
10300
  function sessionFileIndex() {
10224
10301
  if (indexCache)
10225
10302
  return indexCache;
@@ -10290,13 +10367,26 @@ function resolveSessionContentGroups(sessionId) {
10290
10367
  }
10291
10368
  function withSessionReadCache(fn) {
10292
10369
  readScopeDepth++;
10370
+ if (readScopeDepth === 1)
10371
+ derivedScope = /* @__PURE__ */ new Map();
10293
10372
  try {
10294
10373
  return fn();
10295
10374
  } finally {
10296
- if (--readScopeDepth === 0)
10375
+ if (--readScopeDepth === 0) {
10297
10376
  readScope = null;
10377
+ derivedScope = null;
10378
+ }
10298
10379
  }
10299
10380
  }
10381
+ function memoInSessionScope(key, compute) {
10382
+ if (!derivedScope)
10383
+ return compute();
10384
+ if (derivedScope.has(key))
10385
+ return derivedScope.get(key);
10386
+ const value = compute();
10387
+ derivedScope.set(key, value);
10388
+ return value;
10389
+ }
10300
10390
  function readSessionGroupText(group) {
10301
10391
  let key = "";
10302
10392
  if (readScopeDepth > 0) {
@@ -10342,6 +10432,178 @@ function resolveSessionContentPaths(sessionFile) {
10342
10432
  const subPaths = readdirSync10(subDir).filter((f) => f.endsWith(".jsonl")).sort().map((f) => join13(subDir, f));
10343
10433
  return [sessionFile, ...subPaths];
10344
10434
  }
10435
+ function liveScanSessionEdits(sessionId) {
10436
+ const backend = getBackendForId(sessionId);
10437
+ if (backend)
10438
+ return backend.liveScanEdits(sessionId);
10439
+ const tool = detectTool(sessionId);
10440
+ return { found: false, projectPath: "", projectDir: "", edits: [], fileMtime: 0, tool };
10441
+ }
10442
+ function loadGeminiProjectMap() {
10443
+ if (geminiProjectMapCache)
10444
+ return geminiProjectMapCache;
10445
+ const map = /* @__PURE__ */ new Map();
10446
+ const projectsPath = lazyGeminiProjectsJson();
10447
+ if (existsSync13(projectsPath)) {
10448
+ try {
10449
+ const data = JSON.parse(readFileSync9(projectsPath, "utf-8"));
10450
+ for (const path of Object.keys(data.projects || {})) {
10451
+ map.set(createHash2("sha256").update(path).digest("hex"), path);
10452
+ }
10453
+ } catch {
10454
+ }
10455
+ }
10456
+ geminiProjectMapCache = map;
10457
+ return map;
10458
+ }
10459
+ function findGeminiSessionFile(sessionIdOrFileBase) {
10460
+ const idx = geminiIndex();
10461
+ const exact = idx.byBase.get(sessionIdOrFileBase);
10462
+ if (exact)
10463
+ return exact;
10464
+ for (let len = Math.min(sessionIdOrFileBase.length, 64); len >= 4; len--) {
10465
+ const hit = idx.byTail.get(sessionIdOrFileBase.slice(0, len));
10466
+ if (hit)
10467
+ return hit;
10468
+ }
10469
+ return geminiInnerIdIndex(idx).get(sessionIdOrFileBase) ?? null;
10470
+ }
10471
+ function invalidateGeminiSessionIndex() {
10472
+ geminiCache = null;
10473
+ }
10474
+ function geminiIndex() {
10475
+ if (geminiCache)
10476
+ return geminiCache;
10477
+ const byBase = /* @__PURE__ */ new Map();
10478
+ const byTail = /* @__PURE__ */ new Map();
10479
+ const all = [];
10480
+ const projMap = loadGeminiProjectMap();
10481
+ const isGeminiChat = (f) => f.startsWith("session-") && (f.endsWith(".json") || f.endsWith(".jsonl"));
10482
+ for (const tmpRoot of geminiTmpDirs()) {
10483
+ if (!existsSync13(tmpRoot))
10484
+ continue;
10485
+ let projs;
10486
+ try {
10487
+ projs = readdirSync10(tmpRoot, { withFileTypes: true });
10488
+ } catch {
10489
+ continue;
10490
+ }
10491
+ for (const proj of projs) {
10492
+ if (!proj.isDirectory())
10493
+ continue;
10494
+ const chats = join13(tmpRoot, proj.name, "chats");
10495
+ if (!existsSync13(chats))
10496
+ continue;
10497
+ let files;
10498
+ try {
10499
+ files = readdirSync10(chats);
10500
+ } catch {
10501
+ continue;
10502
+ }
10503
+ for (const f of files) {
10504
+ if (!isGeminiChat(f))
10505
+ continue;
10506
+ const base = f.replace(/\.jsonl?$/, "");
10507
+ const located = {
10508
+ path: join13(chats, f),
10509
+ projectDir: proj.name,
10510
+ projectPath: projMap.get(proj.name) || "",
10511
+ format: f.endsWith(".jsonl") ? "jsonl" : "json"
10512
+ };
10513
+ all.push(located);
10514
+ if (!byBase.has(base))
10515
+ byBase.set(base, located);
10516
+ const tail = base.split("-").pop() || "";
10517
+ if (tail.length >= 4 && !byTail.has(tail))
10518
+ byTail.set(tail, located);
10519
+ }
10520
+ }
10521
+ }
10522
+ const built = { byBase, byTail, all, byInnerId: null };
10523
+ if (scanScopeDepth > 0)
10524
+ geminiCache = built;
10525
+ return built;
10526
+ }
10527
+ function geminiInnerIdIndex(idx) {
10528
+ if (idx.byInnerId)
10529
+ return idx.byInnerId;
10530
+ const byInnerId = /* @__PURE__ */ new Map();
10531
+ for (const located of idx.all) {
10532
+ try {
10533
+ const innerId = readGeminiSessionIdFromFile(located.path, located.format);
10534
+ if (innerId && !byInnerId.has(innerId))
10535
+ byInnerId.set(innerId, located);
10536
+ } catch {
10537
+ }
10538
+ }
10539
+ idx.byInnerId = byInnerId;
10540
+ return byInnerId;
10541
+ }
10542
+ function readHeadSync(path, bytes = 65536) {
10543
+ const fd = openSync6(path, "r");
10544
+ try {
10545
+ const buf = Buffer.alloc(bytes);
10546
+ const n = readSync6(fd, buf, 0, buf.length, 0);
10547
+ return buf.toString("utf-8", 0, n);
10548
+ } finally {
10549
+ closeSync6(fd);
10550
+ }
10551
+ }
10552
+ function readGeminiSessionIdFromFile(path, format) {
10553
+ if (format === "json") {
10554
+ try {
10555
+ return JSON.parse(readFileSync9(path, "utf-8"))?.sessionId ?? null;
10556
+ } catch {
10557
+ return null;
10558
+ }
10559
+ }
10560
+ try {
10561
+ const head = readHeadSync(path).split("\n", 1)[0] || "";
10562
+ return JSON.parse(head)?.sessionId ?? null;
10563
+ } catch {
10564
+ return null;
10565
+ }
10566
+ }
10567
+ function readGeminiMessages(path, format) {
10568
+ if (format === "json") {
10569
+ try {
10570
+ const json = JSON.parse(readFileSync9(path, "utf-8"));
10571
+ return Array.isArray(json.messages) ? json.messages : [];
10572
+ } catch {
10573
+ return [];
10574
+ }
10575
+ }
10576
+ const out = [];
10577
+ let raw;
10578
+ try {
10579
+ raw = readFileSync9(path, "utf-8");
10580
+ } catch {
10581
+ return out;
10582
+ }
10583
+ let isFirst = true;
10584
+ for (const line of raw.split("\n")) {
10585
+ if (!line.trim())
10586
+ continue;
10587
+ if (isFirst) {
10588
+ isFirst = false;
10589
+ continue;
10590
+ }
10591
+ if (line.length > MAX_EVENT_LINE_BYTES)
10592
+ continue;
10593
+ let obj;
10594
+ try {
10595
+ obj = JSON.parse(line);
10596
+ } catch {
10597
+ continue;
10598
+ }
10599
+ if (!obj || typeof obj !== "object")
10600
+ continue;
10601
+ if (!obj.type)
10602
+ continue;
10603
+ out.push(obj);
10604
+ }
10605
+ return out;
10606
+ }
10345
10607
  function findCodexSessionFile(sessionId) {
10346
10608
  for (const root of codexSessionDirs()) {
10347
10609
  const found = findCodexSessionFileIn(root, sessionId);
@@ -10405,7 +10667,53 @@ function findCodexSessionFileIn(root, sessionId) {
10405
10667
  }
10406
10668
  return scanDir(root);
10407
10669
  }
10408
- var scanScopeDepth, indexCache, readScope, readScopeDepth, MAX_EVENT_LINE_BYTES;
10670
+ function liveScanModifiedFiles(sessionId) {
10671
+ const scan = liveScanSessionEdits(sessionId);
10672
+ const writeOps = /* @__PURE__ */ new Set(["edit", "write", "multi_edit", "notebook_edit"]);
10673
+ const files = /* @__PURE__ */ new Set();
10674
+ const reads = /* @__PURE__ */ new Set();
10675
+ for (const e of scan.edits) {
10676
+ if (writeOps.has(e.op))
10677
+ files.add(e.file);
10678
+ else if (e.op === "read")
10679
+ reads.add(e.file);
10680
+ }
10681
+ return {
10682
+ found: scan.found,
10683
+ files: [...files],
10684
+ reads: [...reads],
10685
+ edits: scan.edits,
10686
+ projectPath: scan.projectPath,
10687
+ tool: scan.tool
10688
+ };
10689
+ }
10690
+ function liveScanRecentEdits(opts) {
10691
+ const enabled = opts.tools ? new Set(opts.tools) : null;
10692
+ const needle = opts.pattern?.toLowerCase();
10693
+ const accept = (e) => {
10694
+ if (e.ts < opts.sinceMs)
10695
+ return false;
10696
+ if (needle && !e.file.toLowerCase().includes(needle))
10697
+ return false;
10698
+ return true;
10699
+ };
10700
+ const allEdits = [];
10701
+ for (const backend of listAvailableBackends()) {
10702
+ if (enabled && !enabled.has(backend.id))
10703
+ continue;
10704
+ const backendEdits = backend.collectRecentEdits({
10705
+ sinceMs: opts.sinceMs,
10706
+ projectFilter: opts.projectFilter,
10707
+ limitSessions: opts.limitSessions
10708
+ });
10709
+ for (const e of backendEdits)
10710
+ if (accept(e))
10711
+ allEdits.push(e);
10712
+ }
10713
+ allEdits.sort((a, b) => b.ts - a.ts);
10714
+ return allEdits;
10715
+ }
10716
+ var scanScopeDepth, indexCache, readScope, readScopeDepth, derivedScope, geminiProjectMapCache, geminiCache, MAX_EVENT_LINE_BYTES;
10409
10717
  var init_live_session_scan = __esm({
10410
10718
  "../engine/dist/core/live-session-scan.js"() {
10411
10719
  "use strict";
@@ -10419,31 +10727,13 @@ var init_live_session_scan = __esm({
10419
10727
  indexCache = null;
10420
10728
  readScope = null;
10421
10729
  readScopeDepth = 0;
10730
+ derivedScope = null;
10731
+ geminiProjectMapCache = null;
10732
+ geminiCache = null;
10422
10733
  MAX_EVENT_LINE_BYTES = 8 * 1024 * 1024;
10423
10734
  }
10424
10735
  });
10425
10736
 
10426
- // ../engine/dist/core/session-multi-tool.js
10427
- function extractTurnsAny(sessionId, opts = {}) {
10428
- const backend = getBackendForId(sessionId);
10429
- if (!backend)
10430
- return { sessionId, found: false, turns: [], startMs: 0, endMs: 0 };
10431
- return backend.extractTurns(sessionId, opts);
10432
- }
10433
- function replaySessionAny(sessionId) {
10434
- const backend = getBackendForId(sessionId);
10435
- if (!backend)
10436
- return { sessionId, found: false, projectPath: "", files: [], totalLinesAdded: 0, totalLinesRemoved: 0 };
10437
- return backend.replay(sessionId);
10438
- }
10439
- var init_session_multi_tool = __esm({
10440
- "../engine/dist/core/session-multi-tool.js"() {
10441
- "use strict";
10442
- init_tool_backend();
10443
- init_backends();
10444
- }
10445
- });
10446
-
10447
10737
  // src/redact-deep.ts
10448
10738
  function redactDeep(v, count) {
10449
10739
  if (typeof v === "string") return redactSecrets(v, { force: true, count });
@@ -10574,12 +10864,21 @@ function runTask(task) {
10574
10864
  }
10575
10865
  return { id: task.id, findings, redactions: count.redactions, rawB64, rawSize };
10576
10866
  }
10867
+ var scanScopeOpen = false;
10868
+ async function holdScanScopeOpen() {
10869
+ if (scanScopeOpen) return;
10870
+ scanScopeOpen = true;
10871
+ const { withSessionScanScope: withSessionScanScope2 } = await Promise.resolve().then(() => (init_live_session_scan(), live_session_scan_exports));
10872
+ void withSessionScanScope2(() => new Promise(() => {
10873
+ }));
10874
+ }
10577
10875
  async function runDerived(task) {
10578
10876
  if (task.pack && task.packVersion !== installedPackVersion) {
10579
10877
  installServerRulePack(task.pack);
10580
10878
  installedPackVersion = task.packVersion;
10581
10879
  }
10582
10880
  const { collectDerivedRows: collectDerivedRows2 } = await Promise.resolve().then(() => (init_derived(), derived_exports));
10881
+ await holdScanScopeOpen();
10583
10882
  const count = { redactions: 0 };
10584
10883
  const rows = collectDerivedRows2(
10585
10884
  { prefixedId: task.prefixedId, toolId: task.toolId, mtime: task.mtime },
@@ -1 +1 @@
1
- {"version":3,"file":"scan-worker.js","sourceRoot":"","sources":["../src/scan-worker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EACL,mBAAmB,EAAE,aAAa,EAAE,qBAAqB,GAE1D,MAAM,6CAA6C,CAAC;AA4DrD,IAAI,oBAAoB,GAAG,EAAE,CAAC;AAE9B,SAAS,OAAO,CAAC,IAAc;IAC7B,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,WAAW,KAAK,oBAAoB,EAAE,CAAC;QAC3D,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,oBAAoB,GAAG,IAAI,CAAC,WAAW,CAAC;IAC1C,CAAC;IAED,2EAA2E;IAC3E,wEAAwE;IACxE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxD,IAAI,QAAQ,GAAsB,EAAE,CAAC;IACrC,IAAI,CAAC;QAAC,QAAQ,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,4BAA4B,CAAC,CAAC;IAEtF,iEAAiE;IACjE,MAAM,KAAK,GAAG,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;IAChC,IAAI,MAA0B,CAAC;IAC/B,IAAI,OAA2B,CAAC;IAChC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACtC,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;KACpD,CAAC,CAAC,CAAC;IAEJ,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YACpE,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;YACxC,IAAI,EAAE,CAAC,MAAM,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBAClC,MAAM,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;gBAC/B,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAC,4DAA4D,CAAC,CAAC;IAC1E,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAClF,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,IAAiB;IACzC,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,WAAW,KAAK,oBAAoB,EAAE,CAAC;QAC3D,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,oBAAoB,GAAG,IAAI,CAAC,WAAW,CAAC;IAC1C,CAAC;IACD,6EAA6E;IAC7E,uEAAuE;IACvE,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;IAC5D,MAAM,KAAK,GAAG,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;IAChC,MAAM,IAAI,GAAG,kBAAkB,CAC7B,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,EACvE,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,WAAW,CACpC,CAAC;IACF,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC;AAC7D,CAAC;AAED,UAAU,EAAE,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,IAA4B,EAAE,EAAE;IAC/D,IAAK,IAAoB,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC7C,IAAI,CAAC;YACH,UAAU,EAAE,WAAW,CAAC,MAAM,UAAU,CAAC,IAAmB,CAAC,CAAC,CAAC;QACjE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,UAAU,EAAE,WAAW,CAAC;gBACtB,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;gBACtC,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aAChC,CAAC,CAAC;QAC7B,CAAC;QACD,OAAO;IACT,CAAC;IACD,IAAI,MAAkB,CAAC;IACvB,IAAI,CAAC;QACH,MAAM,GAAG,OAAO,CAAC,IAAgB,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,4EAA4E;QAC5E,kEAAkE;QAClE,MAAM,GAAG;YACP,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC;YACxC,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SACxD,CAAC;IACJ,CAAC;IACD,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;AAClC,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"scan-worker.js","sourceRoot":"","sources":["../src/scan-worker.ts"],"names":[],"mappings":"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"}
@@ -81,7 +81,20 @@ export interface TargetOutcome {
81
81
  ok: boolean;
82
82
  /** Why it failed, or why it was not attempted. Absent when ok. */
83
83
  error?: string;
84
+ /**
85
+ * Uploads this target ACCEPTED during the walk, whether or not the walk then
86
+ * failed.
87
+ *
88
+ * `ok` alone answers "did the whole walk finish", which is not the question a
89
+ * user asks. A walk that delivered 38 batches and then hit one fatal error
90
+ * was recorded as a plain failure, so `lastOkAt` never moved and doctor said
91
+ * "nothing has synced in 7h" about a machine whose rows were landing as it
92
+ * spoke. Data arriving and a walk completing are two different facts and the
93
+ * health file needs both.
94
+ */
95
+ accepted?: number;
84
96
  }
97
+ export declare function _acceptedUploads(url: string): number;
85
98
  export declare function syncSessions(opts?: {
86
99
  sinceMs?: number;
87
100
  cleartextPaths?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"sync-client.d.ts","sourceRoot":"","sources":["../src/sync-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sync-client.d.ts","sourceRoot":"","sources":["../src/sync-client.ts"],"names":[],"mappings":"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"}
@@ -500,6 +500,15 @@ export function removeCredentials(serverUrl) {
500
500
  /** Tokenize an absolute project path so the server can group by project
501
501
  * without learning the developer's filesystem layout. */
502
502
  const hashPath = (p) => (p ? 'p_' + createHash('sha256').update(p).digest('hex').slice(0, 12) : '');
503
+ /**
504
+ * Uploads accepted per target during the CURRENT walk.
505
+ *
506
+ * Module-level because the count is made deep inside the upload pool and read
507
+ * in the outer catch, where the thrown error is all that survives of a failed
508
+ * walk. Reset when a target's sync starts.
509
+ */
510
+ const acceptedUploads = new Map();
511
+ export function _acceptedUploads(url) { return acceptedUploads.get(url) ?? 0; }
503
512
  /** compute_cache kinds shipped to the server. Must stay in step with the
504
513
  * kinds the server's conversation routes read (heavyCacheGet keys). */
505
514
  const COMPUTE_KINDS = ['diff', 'outcome', 'commits', 'markers'];
@@ -555,10 +564,11 @@ export async function syncSessions(opts = {}) {
555
564
  };
556
565
  continue;
557
566
  }
567
+ acceptedUploads.set(cred.serverUrl, 0);
558
568
  try {
559
569
  const r = await syncToTarget(cred, opts);
560
570
  noteTargetSuccess(cred.serverUrl);
561
- perTarget[cred.serverUrl] = { ok: true };
571
+ perTarget[cred.serverUrl] = { ok: true, accepted: acceptedUploads.get(cred.serverUrl) ?? 0 };
562
572
  agg = agg ? {
563
573
  uploaded: agg.uploaded + r.uploaded, skipped: agg.skipped + r.skipped, redactions: agg.redactions + r.redactions,
564
574
  items: agg.items + r.items, links: agg.links + r.links, findings: agg.findings + r.findings,
@@ -569,7 +579,9 @@ export async function syncSessions(opts = {}) {
569
579
  catch (e) {
570
580
  const msg = e instanceof Error ? e.message : String(e);
571
581
  errors.push(`${cred.serverUrl}: ${msg}`);
572
- perTarget[cred.serverUrl] = { ok: false, error: msg };
582
+ // What this target took before the walk died. Without it, a walk that
583
+ // delivered thousands of rows and then failed reads as "never synced".
584
+ perTarget[cred.serverUrl] = { ok: false, error: msg, accepted: acceptedUploads.get(cred.serverUrl) ?? 0 };
573
585
  // Report the NEXT attempt in the same breath as the failure, so the log
574
586
  // says what will happen rather than leaving the user to infer it.
575
587
  const next = noteTargetFailure(cred.serverUrl, msg);
@@ -1069,7 +1081,22 @@ async function syncToTargetInScope(cred, opts = {}) {
1069
1081
  // this politeness (you own the box) → higher cap, zero pacing. An explicit
1070
1082
  // --throttle (opts.throttleMs>0) forces the old serial+sleep mode for a
1071
1083
  // known-fragile server.
1072
- const MAX_BATCH_BYTES = 4 * 1024 * 1024;
1084
+ // BATCH SIZE IS A DEADLINE, NOT A MEMORY BUDGET.
1085
+ //
1086
+ // The server's work is proportional to what a batch contains, and a hosted
1087
+ // target sits behind a proxy that gives the origin a fixed window — Cloudflare
1088
+ // ends the request at 100s with a 524, whatever either end is doing. Measured
1089
+ // against the hosted service: a 4 MB batch took the origin ~125s. So every
1090
+ // full batch died, the client's own 90s ceiling fired first and called it a
1091
+ // failure, and the retry sent the SAME oversized payload into the same wall.
1092
+ // The server logged 200 at 125s, having done the work twice, for a batch the
1093
+ // client had already given up on.
1094
+ //
1095
+ // 1 MB lands near 30s against the same server, which leaves room for a slow
1096
+ // day without touching the proxy's limit. A local target has no proxy and is
1097
+ // your own box, so it keeps the larger batch.
1098
+ const MAX_BATCH_BYTES = Number(process.env.CHAT_RECALL_MAX_BATCH_BYTES)
1099
+ || (isLocalHost(cred.serverUrl) ? 4 * 1024 * 1024 : 1024 * 1024);
1073
1100
  const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
1074
1101
  const explicitThrottle = typeof opts.throttleMs === 'number' && opts.throttleMs > 0;
1075
1102
  const throttleMs = explicitThrottle ? opts.throttleMs : 0;
@@ -1149,6 +1176,7 @@ async function syncToTargetInScope(cred, opts = {}) {
1149
1176
  signal: ac.signal,
1150
1177
  });
1151
1178
  if (res.ok) {
1179
+ acceptedUploads.set(cred.serverUrl, (acceptedUploads.get(cred.serverUrl) ?? 0) + 1);
1152
1180
  const body = await res.json().catch(() => ({}));
1153
1181
  // The server owns the plan answer; the user's opt-out is checked
1154
1182
  // separately and wins over it.
@@ -1224,7 +1252,13 @@ async function syncToTargetInScope(cred, opts = {}) {
1224
1252
  // belongs — on the server that knows its own load.
1225
1253
  const retryAfterS = Number(res.headers.get('retry-after'));
1226
1254
  const waitMs = res.status === 429 && retryAfterS > 0 ? retryAfterS * 1000 : RETRY_DELAYS_MS[attempt];
1227
- console.error(`[sync] HTTP ${res.status} from ${base} — backing off ${Math.round(waitMs / 1000)}s (attempt ${attempt + 1})`);
1255
+ // 524 is the proxy ending the request, not the server rejecting it: the
1256
+ // origin is still working and will finish. Retrying the same payload
1257
+ // cannot beat the same clock, so say what would.
1258
+ const why = res.status === 524
1259
+ ? ` — the proxy cut the request at its time limit; the batch is too big for one request`
1260
+ : '';
1261
+ console.error(`[sync] HTTP ${res.status} from ${base}${why} — backing off ${Math.round(waitMs / 1000)}s (attempt ${attempt + 1})`);
1228
1262
  await sleep(waitMs);
1229
1263
  continue;
1230
1264
  }