memorix 1.6.1 → 1.6.2

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.
Files changed (113) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/TEAM.md +86 -86
  3. package/dist/cli/index.js +1574 -1063
  4. package/dist/index.js +588 -107
  5. package/dist/maintenance-runner.js +565 -84
  6. package/dist/media-audio-runner.js +565 -84
  7. package/dist/media-video-runner.js +565 -84
  8. package/dist/memcode-runtime/CHANGELOG.md +22 -0
  9. package/dist/sdk.js +621 -111
  10. package/dist/vector-backfill-runner.js +565 -84
  11. package/docs/DESIGN_DECISIONS.md +357 -357
  12. package/docs/PERFORMANCE.md +15 -0
  13. package/package.json +2 -1
  14. package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
  15. package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
  16. package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
  17. package/plugins/copilot/memorix/plugin.json +1 -1
  18. package/plugins/gemini/memorix/gemini-extension.json +1 -1
  19. package/plugins/omp/memorix/package.json +1 -1
  20. package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
  21. package/plugins/pi/memorix/package.json +1 -1
  22. package/server.json +2 -2
  23. package/src/audit/index.ts +156 -156
  24. package/src/cli/commands/background.ts +34 -2
  25. package/src/cli/commands/formation.ts +48 -48
  26. package/src/cli/commands/git-hook-install.ts +111 -111
  27. package/src/cli/commands/handoff.ts +54 -54
  28. package/src/cli/commands/hooks-status.ts +63 -63
  29. package/src/cli/commands/ingest.ts +44 -44
  30. package/src/cli/commands/integrate-shared.ts +15 -15
  31. package/src/cli/commands/lock.ts +82 -82
  32. package/src/cli/commands/message.ts +104 -104
  33. package/src/cli/commands/operator-shared.ts +6 -3
  34. package/src/cli/commands/poll.ts +58 -58
  35. package/src/cli/commands/reasoning.ts +118 -118
  36. package/src/cli/commands/serve-http.ts +4 -0
  37. package/src/cli/commands/skills.ts +114 -114
  38. package/src/cli/commands/task.ts +167 -167
  39. package/src/cli/commands/transfer.ts +47 -47
  40. package/src/cli/index.ts +406 -406
  41. package/src/cli/tui/ChatView.tsx +234 -234
  42. package/src/cli/tui/CommandBar.tsx +312 -312
  43. package/src/cli/tui/ContextRail.tsx +118 -118
  44. package/src/cli/tui/HeaderBar.tsx +72 -72
  45. package/src/cli/tui/LogoBanner.tsx +51 -51
  46. package/src/cli/tui/index.ts +41 -41
  47. package/src/cli/version.ts +7 -7
  48. package/src/cli/workbench.ts +1 -1
  49. package/src/dashboard/project-classification.ts +64 -64
  50. package/src/embedding/api-provider.ts +503 -27
  51. package/src/embedding/provider.ts +20 -3
  52. package/src/git/hooks-path.ts +85 -85
  53. package/src/hooks/lifecycle.ts +1 -0
  54. package/src/hooks/pattern-detector.ts +173 -173
  55. package/src/hooks/significance-filter.ts +250 -250
  56. package/src/llm/memory-manager.ts +328 -328
  57. package/src/llm/quality.ts +248 -248
  58. package/src/memory/attribution-guard.ts +249 -249
  59. package/src/memory/disclosure-policy.ts +135 -135
  60. package/src/memory/entity-extractor.ts +197 -197
  61. package/src/memory/formation/evaluate.ts +217 -217
  62. package/src/memory/freshness.ts +122 -122
  63. package/src/memory/graph.ts +197 -197
  64. package/src/memory/observations.ts +68 -18
  65. package/src/memory/refs.ts +94 -94
  66. package/src/memory/secret-filter.ts +79 -79
  67. package/src/orchestrate/adapters/claude-stream.ts +192 -192
  68. package/src/orchestrate/adapters/claude.ts +111 -111
  69. package/src/orchestrate/adapters/codex-stream.ts +134 -134
  70. package/src/orchestrate/adapters/codex.ts +41 -41
  71. package/src/orchestrate/adapters/gemini-stream.ts +166 -166
  72. package/src/orchestrate/adapters/gemini.ts +42 -42
  73. package/src/orchestrate/adapters/index.ts +73 -73
  74. package/src/orchestrate/adapters/opencode-stream.ts +143 -143
  75. package/src/orchestrate/adapters/opencode.ts +47 -47
  76. package/src/orchestrate/adapters/types.ts +77 -77
  77. package/src/orchestrate/capability-router.ts +284 -284
  78. package/src/orchestrate/cost-tracker.ts +219 -219
  79. package/src/orchestrate/error-recovery.ts +191 -191
  80. package/src/orchestrate/evidence.ts +140 -140
  81. package/src/orchestrate/ledger.ts +110 -110
  82. package/src/orchestrate/memorix-bridge.ts +343 -343
  83. package/src/orchestrate/output-budget.ts +80 -80
  84. package/src/orchestrate/permission.ts +152 -152
  85. package/src/orchestrate/pipeline-trace.ts +131 -131
  86. package/src/orchestrate/prompt-builder.ts +155 -155
  87. package/src/orchestrate/ring-buffer.ts +37 -37
  88. package/src/orchestrate/task-graph.ts +389 -389
  89. package/src/project/aliases.ts +374 -374
  90. package/src/rules/adapters/trae.ts +56 -56
  91. package/src/rules/syncer.ts +235 -235
  92. package/src/sdk.ts +12 -8
  93. package/src/search/query-expansion.ts +52 -52
  94. package/src/server/formation-timeout.ts +27 -27
  95. package/src/skills/mini-skills.ts +386 -386
  96. package/src/store/chat-store.ts +119 -119
  97. package/src/store/graph-store.ts +249 -249
  98. package/src/store/mini-skill-store.ts +349 -349
  99. package/src/store/orama-store.ts +21 -3
  100. package/src/store/persistence-json.ts +212 -212
  101. package/src/store/persistence.ts +291 -291
  102. package/src/store/project-affinity.ts +195 -195
  103. package/src/team/event-bus.ts +76 -76
  104. package/src/team/handoff.ts +161 -161
  105. package/src/team/poll.ts +132 -132
  106. package/src/workspace/mcp-adapters/codex.ts +191 -191
  107. package/src/workspace/mcp-adapters/copilot.ts +105 -105
  108. package/src/workspace/mcp-adapters/cursor.ts +53 -53
  109. package/src/workspace/mcp-adapters/kiro.ts +64 -64
  110. package/src/workspace/mcp-adapters/opencode.ts +123 -123
  111. package/src/workspace/mcp-adapters/trae.ts +134 -134
  112. package/src/workspace/mcp-adapters/windsurf.ts +91 -91
  113. package/src/workspace/sanitizer.ts +60 -60
@@ -1369,8 +1369,8 @@ async function acquireLock(lockPath) {
1369
1369
  const code = err instanceof Error && "code" in err ? err.code : void 0;
1370
1370
  if (code === "EEXIST" || code === "EPERM") {
1371
1371
  try {
1372
- const stat4 = await fs2.stat(lockPath);
1373
- if (Date.now() - stat4.mtimeMs > LOCK_STALE_MS) {
1372
+ const stat5 = await fs2.stat(lockPath);
1373
+ if (Date.now() - stat5.mtimeMs > LOCK_STALE_MS) {
1374
1374
  await fs2.unlink(lockPath).catch(() => {
1375
1375
  });
1376
1376
  continue;
@@ -2481,24 +2481,131 @@ var init_transformers_provider = __esm({
2481
2481
  // src/embedding/api-provider.ts
2482
2482
  var api_provider_exports = {};
2483
2483
  __export(api_provider_exports, {
2484
- APIEmbeddingProvider: () => APIEmbeddingProvider
2484
+ APIEmbeddingProvider: () => APIEmbeddingProvider,
2485
+ convertArrayCacheToJsonl: () => convertArrayCacheToJsonl,
2486
+ ensureDiskCacheLoaded: () => ensureDiskCacheLoaded,
2487
+ getApiEmbeddingCachePayloadBytesForTests: () => getApiEmbeddingCachePayloadBytesForTests,
2488
+ getApiEmbeddingDiskCacheLoadCountForTests: () => getApiEmbeddingDiskCacheLoadCountForTests,
2489
+ getApiEmbeddingJsonlLineCountCallsForTests: () => getApiEmbeddingJsonlLineCountCallsForTests,
2490
+ getApiEmbeddingMaxEntriesForDimensionsForTests: () => getApiEmbeddingMaxEntriesForDimensionsForTests,
2491
+ migrateJsonArrayCacheToJsonl: () => migrateJsonArrayCacheToJsonl,
2492
+ parseCacheJsonInWorker: () => parseCacheJsonInWorker,
2493
+ resetApiEmbeddingCacheForTests: () => resetApiEmbeddingCacheForTests,
2494
+ saveDiskCacheNow: () => saveDiskCacheNow,
2495
+ seedApiEmbeddingCacheForTests: () => seedApiEmbeddingCacheForTests
2485
2496
  });
2486
2497
  import { createHash as createHash2 } from "crypto";
2487
- import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
2498
+ import { createReadStream, createWriteStream, constants as fsConstants } from "fs";
2499
+ import { access, readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, rename, stat, unlink } from "fs/promises";
2488
2500
  import { join as join3 } from "path";
2489
2501
  import { homedir as homedir7 } from "os";
2502
+ import { createInterface } from "readline";
2490
2503
  function cacheDir() {
2491
2504
  return process.env.MEMORIX_DATA_DIR || join3(homedir7(), ".memorix", "data");
2492
2505
  }
2493
2506
  function cacheFile() {
2494
2507
  return join3(cacheDir(), ".embedding-api-cache.json");
2495
2508
  }
2509
+ function cacheJsonlFile() {
2510
+ return join3(cacheDir(), ".embedding-api-cache.jsonl");
2511
+ }
2496
2512
  function dimsCacheFile() {
2497
2513
  return join3(cacheDir(), ".embedding-dims-cache.json");
2498
2514
  }
2499
2515
  function cacheMetaFile() {
2500
2516
  return join3(cacheDir(), ".embedding-api-cache-meta.json");
2501
2517
  }
2518
+ function cacheStatFile() {
2519
+ return join3(cacheDir(), ".embedding-api-cache-stat.json");
2520
+ }
2521
+ function payloadBytes(vector) {
2522
+ return vector.length * BYTES_PER_DIM;
2523
+ }
2524
+ function maxCachePayloadBytes() {
2525
+ const raw = process.env.MEMORIX_EMBEDDING_CACHE_MAX_BYTES;
2526
+ if (raw) {
2527
+ const parsed = Number.parseInt(raw, 10);
2528
+ if (Number.isFinite(parsed) && parsed > 0) return parsed;
2529
+ }
2530
+ return MAX_CACHE_PAYLOAD_BYTES;
2531
+ }
2532
+ function maxEntriesForDimensions(dimensions) {
2533
+ const dim = Math.max(1, Math.floor(dimensions));
2534
+ const byBytes = Math.floor(maxCachePayloadBytes() / (dim * BYTES_PER_DIM));
2535
+ return Math.max(1, Math.min(MAX_CACHE_ENTRIES, byBytes));
2536
+ }
2537
+ function rememberDimensions(vector) {
2538
+ if (vector.length > 0 && (cacheDimensions === null || vector.length > cacheDimensions)) {
2539
+ cacheDimensions = vector.length;
2540
+ }
2541
+ }
2542
+ function evictOldest() {
2543
+ const firstKey = cache3.keys().next().value;
2544
+ if (firstKey === void 0) return;
2545
+ const old = cache3.get(firstKey);
2546
+ cache3.delete(firstKey);
2547
+ if (old) cachePayloadBytes -= payloadBytes(old);
2548
+ }
2549
+ function evictToFit(incomingBytes, incomingDims) {
2550
+ const limit2 = maxEntriesForDimensions(incomingDims);
2551
+ while (cache3.size > 0 && (cache3.size >= limit2 || cachePayloadBytes + incomingBytes > maxCachePayloadBytes())) {
2552
+ evictOldest();
2553
+ }
2554
+ }
2555
+ function isNumberArray(value) {
2556
+ return Array.isArray(value) && value.every((entry) => typeof entry === "number");
2557
+ }
2558
+ function parseCacheRow(raw) {
2559
+ if (Array.isArray(raw)) {
2560
+ const hash4 = raw[0];
2561
+ const vector = raw[1];
2562
+ if (typeof hash4 === "string" && isNumberArray(vector)) {
2563
+ return { hash: hash4, vector };
2564
+ }
2565
+ return null;
2566
+ }
2567
+ if (raw && typeof raw === "object") {
2568
+ const row = raw;
2569
+ if (typeof row.h === "string" && isNumberArray(row.v)) {
2570
+ return { hash: row.h, vector: row.v };
2571
+ }
2572
+ }
2573
+ return null;
2574
+ }
2575
+ function cacheInsert(hash4, value, dirty) {
2576
+ rememberDimensions(value);
2577
+ const incoming = payloadBytes(value);
2578
+ const existing = cache3.get(hash4);
2579
+ if (existing) {
2580
+ cachePayloadBytes -= payloadBytes(existing);
2581
+ cache3.delete(hash4);
2582
+ }
2583
+ evictToFit(incoming, value.length || cacheDimensions || DEFAULT_ASSUMED_DIMENSIONS);
2584
+ cache3.set(hash4, value);
2585
+ cachePayloadBytes += incoming;
2586
+ if (dirty) diskCacheDirty2 = true;
2587
+ }
2588
+ async function readCacheStat() {
2589
+ try {
2590
+ const data = JSON.parse(await readFile2(cacheStatFile(), "utf-8"));
2591
+ if (typeof data.entryCount === "number" && Number.isFinite(data.entryCount) && data.entryCount >= 0) {
2592
+ return {
2593
+ version: 1,
2594
+ entryCount: Math.floor(data.entryCount),
2595
+ dimensions: isValidDimension(data.dimensions) ? data.dimensions : null
2596
+ };
2597
+ }
2598
+ } catch {
2599
+ }
2600
+ return null;
2601
+ }
2602
+ async function writeCacheStat(stat5) {
2603
+ try {
2604
+ await mkdir2(cacheDir(), { recursive: true });
2605
+ await writeFile2(cacheStatFile(), JSON.stringify(stat5));
2606
+ } catch {
2607
+ }
2608
+ }
2502
2609
  function normalizeText(text2) {
2503
2610
  return text2.replace(/\s+/g, " ").trim().slice(0, MAX_INPUT_CHARS);
2504
2611
  }
@@ -2584,29 +2691,300 @@ function toProviderInput(input, baseUrl) {
2584
2691
  }
2585
2692
  return { type: input.modality, url: input.url };
2586
2693
  }
2694
+ function parseCacheJsonInWorker(filePath) {
2695
+ return new Promise((resolve, reject) => {
2696
+ void import("worker_threads").then(({ Worker }) => {
2697
+ const worker = new Worker(
2698
+ `
2699
+ const { parentPort, workerData } = require('node:worker_threads');
2700
+ const { readFileSync } = require('node:fs');
2701
+ try {
2702
+ const raw = readFileSync(workerData.filePath, 'utf8');
2703
+ parentPort.postMessage({ ok: true, entries: JSON.parse(raw) });
2704
+ } catch (err) {
2705
+ parentPort.postMessage({
2706
+ ok: false,
2707
+ error: err instanceof Error ? err.message : String(err),
2708
+ });
2709
+ }
2710
+ `,
2711
+ { eval: true, workerData: { filePath } }
2712
+ );
2713
+ worker.once("message", (msg) => {
2714
+ void worker.terminate();
2715
+ if (msg?.ok && Array.isArray(msg.entries)) {
2716
+ resolve(msg.entries);
2717
+ return;
2718
+ }
2719
+ reject(new Error(msg?.error || "embedding cache worker parse failed"));
2720
+ });
2721
+ worker.once("error", reject);
2722
+ }).catch(reject);
2723
+ });
2724
+ }
2725
+ function findJsonValueEnd(source) {
2726
+ let i2 = 0;
2727
+ while (i2 < source.length && /\s/.test(source[i2])) i2 += 1;
2728
+ if (i2 >= source.length) return -1;
2729
+ const start = source[i2];
2730
+ if (start === '"') {
2731
+ i2 += 1;
2732
+ while (i2 < source.length) {
2733
+ if (source[i2] === "\\") {
2734
+ i2 += 2;
2735
+ continue;
2736
+ }
2737
+ if (source[i2] === '"') return i2 + 1;
2738
+ i2 += 1;
2739
+ }
2740
+ return -1;
2741
+ }
2742
+ if (start === "{" || start === "[") {
2743
+ const close = start === "{" ? "}" : "]";
2744
+ let depth = 0;
2745
+ let inString = false;
2746
+ for (; i2 < source.length; i2 += 1) {
2747
+ const ch = source[i2];
2748
+ if (inString) {
2749
+ if (ch === "\\") {
2750
+ i2 += 1;
2751
+ continue;
2752
+ }
2753
+ if (ch === '"') inString = false;
2754
+ continue;
2755
+ }
2756
+ if (ch === '"') {
2757
+ inString = true;
2758
+ continue;
2759
+ }
2760
+ if (ch === start) depth += 1;
2761
+ else if (ch === close) {
2762
+ depth -= 1;
2763
+ if (depth === 0) return i2 + 1;
2764
+ }
2765
+ }
2766
+ return -1;
2767
+ }
2768
+ const rest = source.slice(i2);
2769
+ const match2 = rest.match(/^(?:-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?|true|false|null)/);
2770
+ return match2 ? i2 + match2[0].length : -1;
2771
+ }
2772
+ async function streamJsonArrayToJsonl(filePath, tmpPath) {
2773
+ const input = createReadStream(filePath, { encoding: "utf8" });
2774
+ const out = createWriteStream(tmpPath);
2775
+ let buf = "";
2776
+ let started = false;
2777
+ let count2 = 0;
2778
+ const writeLine = async (line) => {
2779
+ if (!out.write(line)) {
2780
+ await new Promise((resolve, reject) => {
2781
+ out.once("drain", resolve);
2782
+ out.once("error", reject);
2783
+ });
2784
+ }
2785
+ };
2786
+ try {
2787
+ for await (const chunk of input) {
2788
+ buf += chunk;
2789
+ if (!started) {
2790
+ const idx = buf.search(/\S/);
2791
+ if (idx < 0) continue;
2792
+ if (buf[idx] !== "[") throw new Error("embedding cache is not a JSON array");
2793
+ buf = buf.slice(idx + 1);
2794
+ started = true;
2795
+ }
2796
+ while (true) {
2797
+ buf = buf.replace(/^\s*,?\s*/, "");
2798
+ if (!buf) break;
2799
+ if (buf[0] === "]") {
2800
+ buf = "";
2801
+ break;
2802
+ }
2803
+ const end = findJsonValueEnd(buf);
2804
+ if (end < 0) break;
2805
+ const value = JSON.parse(buf.slice(0, end));
2806
+ buf = buf.slice(end);
2807
+ const row = parseCacheRow(value);
2808
+ if (row) {
2809
+ await writeLine(`${JSON.stringify({ h: row.hash, v: row.vector })}
2810
+ `);
2811
+ count2 += 1;
2812
+ if (count2 % 50 === 0) {
2813
+ await new Promise((resolve) => setImmediate(resolve));
2814
+ }
2815
+ }
2816
+ }
2817
+ if (buf.length > MAX_MIGRATION_VALUE_BYTES) {
2818
+ throw new Error("embedding cache entry too large to migrate safely");
2819
+ }
2820
+ }
2821
+ } finally {
2822
+ await new Promise((resolve, reject) => {
2823
+ out.end(() => resolve());
2824
+ out.once("error", reject);
2825
+ });
2826
+ }
2827
+ return count2;
2828
+ }
2829
+ async function migrateJsonArrayCacheToJsonl(filePath, jsonlPath) {
2830
+ const tmpPath = `${jsonlPath}.tmp`;
2831
+ try {
2832
+ const count2 = await streamJsonArrayToJsonl(filePath, tmpPath);
2833
+ await rename(tmpPath, jsonlPath);
2834
+ diskCacheEntryCount = count2;
2835
+ await writeCacheStat({
2836
+ version: 1,
2837
+ entryCount: count2,
2838
+ dimensions: cacheDimensions
2839
+ });
2840
+ return count2;
2841
+ } catch (err) {
2842
+ await unlink(tmpPath).catch(() => void 0);
2843
+ throw err;
2844
+ }
2845
+ }
2846
+ function convertArrayCacheToJsonl(filePath, jsonlPath) {
2847
+ return migrateJsonArrayCacheToJsonl(filePath, jsonlPath);
2848
+ }
2849
+ async function loadCacheJsonl(filePath) {
2850
+ const rl = createInterface({
2851
+ input: createReadStream(filePath, { encoding: "utf8" }),
2852
+ crlfDelay: Infinity
2853
+ });
2854
+ let loaded = 0;
2855
+ let onDiskCount = 0;
2856
+ for await (const line of rl) {
2857
+ const trimmed = line.trim();
2858
+ if (!trimmed) continue;
2859
+ try {
2860
+ const row = parseCacheRow(JSON.parse(trimmed));
2861
+ if (!row) continue;
2862
+ onDiskCount += 1;
2863
+ cacheInsert(row.hash, row.vector, false);
2864
+ loaded = cache3.size;
2865
+ } catch {
2866
+ }
2867
+ if (onDiskCount % 250 === 0) {
2868
+ await new Promise((resolve) => setImmediate(resolve));
2869
+ }
2870
+ }
2871
+ diskCacheEntryCount = onDiskCount;
2872
+ await writeCacheStat({
2873
+ version: 1,
2874
+ entryCount: onDiskCount,
2875
+ dimensions: cacheDimensions
2876
+ });
2877
+ return loaded;
2878
+ }
2879
+ async function countJsonlLines(filePath) {
2880
+ jsonlLineCountCalls += 1;
2881
+ try {
2882
+ const rl = createInterface({
2883
+ input: createReadStream(filePath, { encoding: "utf8" }),
2884
+ crlfDelay: Infinity
2885
+ });
2886
+ let count2 = 0;
2887
+ for await (const line of rl) {
2888
+ if (line.trim()) count2 += 1;
2889
+ }
2890
+ return count2;
2891
+ } catch {
2892
+ return 0;
2893
+ }
2894
+ }
2895
+ async function resolveOnDiskCount(jsonlPath) {
2896
+ if (diskCacheEntryCount > 0) return diskCacheEntryCount;
2897
+ const sidecar = await readCacheStat();
2898
+ if (sidecar) {
2899
+ diskCacheEntryCount = sidecar.entryCount;
2900
+ if (sidecar.dimensions && cacheDimensions === null) cacheDimensions = sidecar.dimensions;
2901
+ return sidecar.entryCount;
2902
+ }
2903
+ try {
2904
+ await access(jsonlPath, fsConstants.R_OK);
2905
+ } catch {
2906
+ return 0;
2907
+ }
2908
+ const counted = await countJsonlLines(jsonlPath);
2909
+ diskCacheEntryCount = counted;
2910
+ await writeCacheStat({
2911
+ version: 1,
2912
+ entryCount: counted,
2913
+ dimensions: cacheDimensions
2914
+ });
2915
+ return counted;
2916
+ }
2587
2917
  async function loadDiskCache2() {
2588
- if (diskCacheLoaded) return;
2918
+ if (diskCacheLoaded) return cache3.size;
2919
+ let loaded = 0;
2589
2920
  try {
2590
- const raw = await readFile2(cacheFile(), "utf-8");
2591
- const entries = JSON.parse(raw);
2592
- for (const [k, v] of entries) cache3.set(k, v);
2593
- console.error(`[memorix] Loaded ${entries.length} cached API embeddings from disk`);
2921
+ const jsonlPath = cacheJsonlFile();
2922
+ let hasJsonl = false;
2923
+ try {
2924
+ await access(jsonlPath, fsConstants.R_OK);
2925
+ hasJsonl = true;
2926
+ } catch {
2927
+ hasJsonl = false;
2928
+ }
2929
+ if (hasJsonl) {
2930
+ loaded = await loadCacheJsonl(jsonlPath);
2931
+ } else {
2932
+ const filePath = cacheFile();
2933
+ await stat(filePath);
2934
+ await migrateJsonArrayCacheToJsonl(filePath, jsonlPath);
2935
+ loaded = await loadCacheJsonl(jsonlPath);
2936
+ }
2937
+ diskCacheLoadCount += 1;
2938
+ console.error(`[memorix] Loaded ${loaded} cached API embeddings from disk`);
2594
2939
  } catch {
2595
2940
  }
2596
2941
  diskCacheLoaded = true;
2942
+ return loaded;
2597
2943
  }
2598
2944
  function startDiskCacheLoad() {
2599
2945
  if (diskCacheLoaded || diskCacheLoadPromise) return;
2600
- diskCacheLoadPromise = loadDiskCache2().catch(() => {
2946
+ diskCacheLoadPromise = loadDiskCache2().then(() => void 0).catch(() => {
2601
2947
  });
2602
2948
  }
2603
2949
  async function ensureDiskCacheLoaded() {
2604
- if (diskCacheLoaded) return;
2605
- if (diskCacheLoadPromise) {
2606
- await diskCacheLoadPromise;
2607
- return;
2608
- }
2609
- await loadDiskCache2();
2950
+ if (diskCacheLoaded) return cache3.size;
2951
+ if (!diskCacheLoadPromise) {
2952
+ diskCacheLoadPromise = loadDiskCache2().then(() => void 0).catch(() => {
2953
+ });
2954
+ }
2955
+ await diskCacheLoadPromise;
2956
+ return cache3.size;
2957
+ }
2958
+ function getApiEmbeddingDiskCacheLoadCountForTests() {
2959
+ return diskCacheLoadCount;
2960
+ }
2961
+ function resetApiEmbeddingCacheForTests() {
2962
+ cache3.clear();
2963
+ cachePayloadBytes = 0;
2964
+ cacheDimensions = null;
2965
+ diskCacheEntryCount = 0;
2966
+ diskCacheLoaded = false;
2967
+ diskCacheLoadPromise = null;
2968
+ diskCacheLoadCount = 0;
2969
+ diskCacheDirty2 = false;
2970
+ jsonlLineCountCalls = 0;
2971
+ }
2972
+ function seedApiEmbeddingCacheForTests(entries) {
2973
+ cache3.clear();
2974
+ cachePayloadBytes = 0;
2975
+ cacheDimensions = null;
2976
+ for (const [key, value] of entries) cacheInsert(key, value, true);
2977
+ diskCacheLoaded = true;
2978
+ diskCacheDirty2 = true;
2979
+ }
2980
+ function getApiEmbeddingCachePayloadBytesForTests() {
2981
+ return cachePayloadBytes;
2982
+ }
2983
+ function getApiEmbeddingJsonlLineCountCallsForTests() {
2984
+ return jsonlLineCountCalls;
2985
+ }
2986
+ function getApiEmbeddingMaxEntriesForDimensionsForTests(dimensions) {
2987
+ return maxEntriesForDimensions(dimensions);
2610
2988
  }
2611
2989
  function dimsCacheKey(config) {
2612
2990
  return [
@@ -2722,8 +3100,46 @@ async function saveDiskCacheNow() {
2722
3100
  if (!diskCacheDirty2) return;
2723
3101
  try {
2724
3102
  await mkdir2(cacheDir(), { recursive: true });
2725
- const entries = Array.from(cache3.entries());
2726
- await writeFile2(cacheFile(), JSON.stringify(entries));
3103
+ const jsonlPath = cacheJsonlFile();
3104
+ const existing = await resolveOnDiskCount(jsonlPath);
3105
+ if (existing > 0 && cache3.size < Math.ceil(existing * 0.5)) {
3106
+ console.error(
3107
+ `[memorix] Refusing to overwrite embedding cache (${existing} on disk vs ${cache3.size} in memory)`
3108
+ );
3109
+ diskCacheDirty2 = false;
3110
+ return;
3111
+ }
3112
+ const tmpPath = `${jsonlPath}.tmp`;
3113
+ await new Promise((resolve, reject) => {
3114
+ const out = createWriteStream(tmpPath);
3115
+ const entries = cache3.entries();
3116
+ const writeBatch = () => {
3117
+ for (let i2 = 0; i2 < 50; i2++) {
3118
+ const next = entries.next();
3119
+ if (next.done) {
3120
+ out.end();
3121
+ return;
3122
+ }
3123
+ const [hash4, vector] = next.value;
3124
+ if (!out.write(`${JSON.stringify({ h: hash4, v: vector })}
3125
+ `)) {
3126
+ out.once("drain", writeBatch);
3127
+ return;
3128
+ }
3129
+ }
3130
+ setImmediate(writeBatch);
3131
+ };
3132
+ out.on("finish", resolve);
3133
+ out.on("error", reject);
3134
+ writeBatch();
3135
+ });
3136
+ await rename(tmpPath, jsonlPath);
3137
+ diskCacheEntryCount = cache3.size;
3138
+ await writeCacheStat({
3139
+ version: 1,
3140
+ entryCount: cache3.size,
3141
+ dimensions: cacheDimensions
3142
+ });
2727
3143
  diskCacheDirty2 = false;
2728
3144
  } catch {
2729
3145
  }
@@ -2737,12 +3153,7 @@ function scheduleDiskSave() {
2737
3153
  }, DISK_SAVE_DEBOUNCE_MS);
2738
3154
  }
2739
3155
  function cacheSet(hash4, value) {
2740
- if (cache3.size >= MAX_CACHE_SIZE3) {
2741
- const firstKey = cache3.keys().next().value;
2742
- if (firstKey !== void 0) cache3.delete(firstKey);
2743
- }
2744
- cache3.set(hash4, value);
2745
- diskCacheDirty2 = true;
3156
+ cacheInsert(hash4, value, true);
2746
3157
  }
2747
3158
  function resolveEnvEmbeddingApiKey() {
2748
3159
  return process.env.MEMORIX_EMBEDDING_API_KEY;
@@ -2861,18 +3272,27 @@ async function waitForRetry(waitMs, signal) {
2861
3272
  abortSignal.addEventListener("abort", onAbort, { once: true });
2862
3273
  });
2863
3274
  }
2864
- var cache3, MAX_CACHE_SIZE3, diskCacheDirty2, diskSaveTimer, diskCacheLoaded, diskCacheLoadPromise, MAX_INPUT_CHARS, MAX_CONCURRENCY, DISK_SAVE_DEBOUNCE_MS, DEFAULT_MAX_BATCH_SIZE, DASHSCOPE_MAX_BATCH_SIZE, MAX_RETRIES2, BASE_DELAY_MS, EmbeddingAPIError, APIEmbeddingProvider;
3275
+ var cache3, MAX_CACHE_ENTRIES, MAX_CACHE_PAYLOAD_BYTES, BYTES_PER_DIM, DEFAULT_ASSUMED_DIMENSIONS, MAX_MIGRATION_VALUE_BYTES, cachePayloadBytes, cacheDimensions, diskCacheEntryCount, diskCacheDirty2, diskSaveTimer, diskCacheLoaded, diskCacheLoadPromise, diskCacheLoadCount, jsonlLineCountCalls, MAX_INPUT_CHARS, MAX_CONCURRENCY, DISK_SAVE_DEBOUNCE_MS, DEFAULT_MAX_BATCH_SIZE, DASHSCOPE_MAX_BATCH_SIZE, MAX_RETRIES2, BASE_DELAY_MS, EmbeddingAPIError, APIEmbeddingProvider;
2865
3276
  var init_api_provider = __esm({
2866
3277
  "src/embedding/api-provider.ts"() {
2867
3278
  "use strict";
2868
3279
  init_esm_shims();
2869
3280
  init_provider();
2870
3281
  cache3 = /* @__PURE__ */ new Map();
2871
- MAX_CACHE_SIZE3 = 1e4;
3282
+ MAX_CACHE_ENTRIES = 2e5;
3283
+ MAX_CACHE_PAYLOAD_BYTES = 256 * 1024 * 1024;
3284
+ BYTES_PER_DIM = 8;
3285
+ DEFAULT_ASSUMED_DIMENSIONS = 4096;
3286
+ MAX_MIGRATION_VALUE_BYTES = 16 * 1024 * 1024;
3287
+ cachePayloadBytes = 0;
3288
+ cacheDimensions = null;
3289
+ diskCacheEntryCount = 0;
2872
3290
  diskCacheDirty2 = false;
2873
3291
  diskSaveTimer = null;
2874
3292
  diskCacheLoaded = false;
2875
3293
  diskCacheLoadPromise = null;
3294
+ diskCacheLoadCount = 0;
3295
+ jsonlLineCountCalls = 0;
2876
3296
  MAX_INPUT_CHARS = 32e3;
2877
3297
  MAX_CONCURRENCY = 4;
2878
3298
  DISK_SAVE_DEBOUNCE_MS = 5e3;
@@ -2930,7 +3350,9 @@ var init_api_provider = __esm({
2930
3350
  if (config.requestedDimensions) {
2931
3351
  console.error(`[memorix] Dimension shortening: ${config.requestedDimensions}d requested`);
2932
3352
  }
2933
- startDiskCacheLoad();
3353
+ if (allowNetworkProbe) {
3354
+ startDiskCacheLoad();
3355
+ }
2934
3356
  return new _APIEmbeddingProvider(config, probeDimensions);
2935
3357
  }
2936
3358
  static resolveConfig() {
@@ -3268,7 +3690,12 @@ function warnOnce(message) {
3268
3690
  lastEmbeddingWarningAt = now3;
3269
3691
  console.error(message);
3270
3692
  }
3693
+ function embeddingModeToken() {
3694
+ return process.env.MEMORIX_EMBEDDING?.toLowerCase()?.trim() ?? "";
3695
+ }
3271
3696
  function getEmbeddingMode2() {
3697
+ const token = embeddingModeToken();
3698
+ if (cachedEmbeddingMode && cachedEmbeddingModeToken === token) return cachedEmbeddingMode;
3272
3699
  try {
3273
3700
  let cfg;
3274
3701
  try {
@@ -3277,10 +3704,17 @@ function getEmbeddingMode2() {
3277
3704
  cfg = (init_config(), __toCommonJS(config_exports));
3278
3705
  }
3279
3706
  const { getEmbeddingMode: cfgMode } = cfg;
3280
- return cfgMode();
3707
+ cachedEmbeddingMode = cfgMode();
3708
+ cachedEmbeddingModeToken = token;
3709
+ return cachedEmbeddingMode;
3281
3710
  } catch {
3282
- const env2 = process.env.MEMORIX_EMBEDDING?.toLowerCase()?.trim();
3283
- if (env2 === "fastembed" || env2 === "transformers" || env2 === "api" || env2 === "auto") return env2;
3711
+ if (token === "fastembed" || token === "transformers" || token === "api" || token === "auto") {
3712
+ cachedEmbeddingMode = token;
3713
+ cachedEmbeddingModeToken = token;
3714
+ return token;
3715
+ }
3716
+ cachedEmbeddingMode = "off";
3717
+ cachedEmbeddingModeToken = token;
3284
3718
  return "off";
3285
3719
  }
3286
3720
  }
@@ -3536,13 +3970,15 @@ function isEmbeddingExplicitlyDisabled() {
3536
3970
  function resetProvider() {
3537
3971
  provider = null;
3538
3972
  initPromise = null;
3973
+ cachedEmbeddingMode = null;
3974
+ cachedEmbeddingModeToken = null;
3539
3975
  lastInitWasTemporaryFailure = false;
3540
3976
  lastFailureTimestamp = 0;
3541
3977
  lastEmbeddingFailure = null;
3542
3978
  lastEmbeddingWarning = "";
3543
3979
  lastEmbeddingWarningAt = 0;
3544
3980
  }
3545
- var EmbeddingInputError, UnsupportedEmbeddingModalityError, MAX_INLINE_EMBEDDING_BYTES, provider, initPromise, lastInitWasTemporaryFailure, lastEmbeddingFailure, lastEmbeddingWarning, lastEmbeddingWarningAt, WARNING_COOLDOWN_MS, RETRY_COOLDOWN_MS, lastFailureTimestamp;
3981
+ var EmbeddingInputError, UnsupportedEmbeddingModalityError, MAX_INLINE_EMBEDDING_BYTES, provider, initPromise, cachedEmbeddingMode, cachedEmbeddingModeToken, lastInitWasTemporaryFailure, lastEmbeddingFailure, lastEmbeddingWarning, lastEmbeddingWarningAt, WARNING_COOLDOWN_MS, RETRY_COOLDOWN_MS, lastFailureTimestamp;
3546
3982
  var init_provider = __esm({
3547
3983
  "src/embedding/provider.ts"() {
3548
3984
  "use strict";
@@ -3566,6 +4002,8 @@ var init_provider = __esm({
3566
4002
  MAX_INLINE_EMBEDDING_BYTES = 5 * 1024 * 1024;
3567
4003
  provider = null;
3568
4004
  initPromise = null;
4005
+ cachedEmbeddingMode = null;
4006
+ cachedEmbeddingModeToken = null;
3569
4007
  lastInitWasTemporaryFailure = false;
3570
4008
  lastEmbeddingFailure = null;
3571
4009
  lastEmbeddingWarning = "";
@@ -5323,6 +5761,9 @@ async function attachCachedVectors(database, candidates) {
5323
5761
  await update(database, candidates[index].id, { ...existing, embedding: vector });
5324
5762
  } catch {
5325
5763
  }
5764
+ if (index % 50 === 0) {
5765
+ await new Promise((resolve) => setImmediate(resolve));
5766
+ }
5326
5767
  }
5327
5768
  }
5328
5769
  async function hydrateIndex(observations2, options = {}) {
@@ -5373,17 +5814,24 @@ async function hydrateIndex(observations2, options = {}) {
5373
5814
  await insert2(database, doc);
5374
5815
  rememberObservationDoc(doc);
5375
5816
  inserted++;
5817
+ if (inserted % 50 === 0) {
5818
+ await new Promise((resolve) => setImmediate(resolve));
5819
+ }
5820
+ if (inserted % 200 === 0) {
5821
+ await new Promise((resolve) => setTimeout(resolve, 0));
5822
+ }
5376
5823
  } catch {
5377
5824
  }
5378
5825
  }
5379
- deferredCachedVectorHydration = deferCachedVectors ? attachCachedVectors(database, candidates).catch(() => {
5826
+ deferredCachedVectorHydration = options.skipCachedVectors ? null : deferCachedVectors ? attachCachedVectors(database, candidates).catch(() => {
5380
5827
  }) : null;
5381
5828
  return inserted;
5382
5829
  }
5383
- async function hydrateIndexForStartup(observations2) {
5830
+ async function hydrateIndexForStartup(observations2, options = {}) {
5384
5831
  return hydrateIndex(observations2, {
5385
5832
  allowNetworkProbe: false,
5386
- deferCachedVectors: true
5833
+ deferCachedVectors: true,
5834
+ skipCachedVectors: options.skipCachedVectors
5387
5835
  });
5388
5836
  }
5389
5837
  function getDeferredCachedVectorHydration() {
@@ -8171,12 +8619,25 @@ __export(observations_exports, {
8171
8619
  prepareSearchIndex: () => prepareSearchIndex,
8172
8620
  probeSearchIndex: () => probeSearchIndex,
8173
8621
  reindexObservations: () => reindexObservations,
8622
+ resetObservationRuntime: () => resetObservationRuntime,
8174
8623
  resolveObservations: () => resolveObservations,
8175
8624
  storeObservation: () => storeObservation,
8176
8625
  suggestTopicKey: () => suggestTopicKey,
8177
8626
  updateObservationAdmission: () => updateObservationAdmission,
8178
8627
  withFreshObservations: () => withFreshObservations
8179
8628
  });
8629
+ function resetObservationRuntime() {
8630
+ observations = [];
8631
+ nextId = 1;
8632
+ projectDir = null;
8633
+ searchIndexPrepared = false;
8634
+ corpusLoaded = false;
8635
+ loadedObservationStore = null;
8636
+ embeddingWriteMode = "background";
8637
+ embeddingWorkerProjectRoot = void 0;
8638
+ vectorMissingIds.clear();
8639
+ vectorSchemaUpgradePromise = null;
8640
+ }
8180
8641
  function logEmbeddingFailureOnce(key, message) {
8181
8642
  const now3 = Date.now();
8182
8643
  const last = embeddingFailureLogTimestamps.get(key) ?? 0;
@@ -8285,23 +8746,33 @@ async function upgradeVectorSchemaAfterFirstEmbedding(embedding) {
8285
8746
  async function initObservations(dir, options = {}) {
8286
8747
  embeddingWriteMode = options.embeddingWriteMode ?? "background";
8287
8748
  embeddingWorkerProjectRoot = options.projectRoot;
8288
- if (projectDir === dir) return;
8289
8749
  await initObservationStore(dir);
8290
8750
  const store = getObservationStore();
8291
- observations = await store.loadAll();
8751
+ if (projectDir === dir && loadedObservationStore === store) {
8752
+ if (options.skipCorpusLoad || corpusLoaded) return;
8753
+ }
8292
8754
  nextId = await store.loadIdCounter();
8293
8755
  projectDir = dir;
8294
8756
  searchIndexPrepared = false;
8295
8757
  vectorSchemaUpgradePromise = null;
8758
+ if (options.skipCorpusLoad) {
8759
+ observations = [];
8760
+ corpusLoaded = false;
8761
+ loadedObservationStore = store;
8762
+ return;
8763
+ }
8764
+ observations = await store.loadAll();
8765
+ corpusLoaded = true;
8766
+ loadedObservationStore = store;
8296
8767
  }
8297
8768
  function scheduleObservationEmbedding(input) {
8298
8769
  const { observationId: observationId2, projectId, searchableText, doc } = input;
8299
8770
  vectorMissingIds.add(observationId2);
8771
+ if (isEmbeddingExplicitlyDisabled()) {
8772
+ vectorMissingIds.delete(observationId2);
8773
+ return;
8774
+ }
8300
8775
  if (embeddingWriteMode === "deferred") {
8301
- if (isEmbeddingExplicitlyDisabled()) {
8302
- vectorMissingIds.delete(observationId2);
8303
- return;
8304
- }
8305
8776
  queueVectorBackfill(projectId, {
8306
8777
  detachedWorker: true,
8307
8778
  projectRoot: embeddingWorkerProjectRoot
@@ -8348,7 +8819,7 @@ function scheduleObservationEmbedding(input) {
8348
8819
  });
8349
8820
  }
8350
8821
  async function ensureFreshObservations() {
8351
- if (!projectDir) return false;
8822
+ if (!projectDir || !corpusLoaded) return false;
8352
8823
  try {
8353
8824
  const store = getObservationStore();
8354
8825
  const wasStale = await store.ensureFresh();
@@ -8389,7 +8860,7 @@ async function storeObservation(input) {
8389
8860
  });
8390
8861
  if (safeAttachments) input = { ...input, attachments: safeAttachments };
8391
8862
  await ensureFreshObservations();
8392
- if (input.topicKey) {
8863
+ if (input.topicKey && corpusLoaded) {
8393
8864
  const existing = observations.find(
8394
8865
  (o) => o.topicKey === input.topicKey && o.projectId === input.projectId
8395
8866
  );
@@ -8486,13 +8957,17 @@ async function storeObservation(input) {
8486
8957
  });
8487
8958
  observation.writeGeneration = store.getGeneration();
8488
8959
  if (upsertedInsideLock || reloadCacheAfterCommit) {
8489
- observations = await store.loadAll();
8490
- nextId = await store.loadIdCounter();
8491
- if (upsertedInsideLock) {
8492
- observation = observations.find((candidate) => candidate.id === observation.id) ?? observation;
8960
+ if (corpusLoaded) {
8961
+ observations = await store.loadAll();
8962
+ nextId = await store.loadIdCounter();
8963
+ if (upsertedInsideLock) {
8964
+ observation = observations.find((candidate) => candidate.id === observation.id) ?? observation;
8965
+ }
8966
+ } else {
8967
+ nextId = await store.loadIdCounter();
8493
8968
  }
8494
8969
  } else {
8495
- observations.push(observation);
8970
+ if (corpusLoaded) observations.push(observation);
8496
8971
  nextId = observation.id + 1;
8497
8972
  }
8498
8973
  if (upsertedInsideLock) return;
@@ -8560,7 +9035,9 @@ async function storeObservation(input) {
8560
9035
  createdByAgentId: input.createdByAgentId ?? "",
8561
9036
  sharedWithAgentIds: JSON.stringify(input.sharedWithAgentIds ?? [])
8562
9037
  };
8563
- await insertObservation(doc);
9038
+ if (corpusLoaded) {
9039
+ await insertObservation(doc);
9040
+ }
8564
9041
  };
8565
9042
  await assignAndPersist();
8566
9043
  if (upsertedInsideLock) {
@@ -8922,9 +9399,11 @@ async function reindexObservations() {
8922
9399
  searchIndexPrepared = true;
8923
9400
  return count2;
8924
9401
  }
8925
- async function prepareSearchIndex() {
9402
+ async function prepareSearchIndex(options = {}) {
8926
9403
  if (searchIndexPrepared) return 0;
8927
- const count2 = await hydrateIndexForStartup(observations);
9404
+ const count2 = await hydrateIndexForStartup(observations, {
9405
+ skipCachedVectors: options.skipCachedVectors
9406
+ });
8928
9407
  if (count2 === 0) {
8929
9408
  searchIndexPrepared = true;
8930
9409
  return 0;
@@ -9116,7 +9595,7 @@ async function backfillVectorEmbeddings(options = {}) {
9116
9595
  ...lastFailure ? { lastError: lastFailure } : {}
9117
9596
  };
9118
9597
  }
9119
- var observations, nextId, projectDir, searchIndexPrepared, embeddingWriteMode, embeddingWorkerProjectRoot, vectorMissingIds, vectorBackfillRunning, vectorSchemaUpgradePromise, lastVectorBackfill, embeddingFailureLogTimestamps, EMBEDDING_FAILURE_LOG_COOLDOWN_MS;
9598
+ var observations, nextId, projectDir, searchIndexPrepared, embeddingWriteMode, embeddingWorkerProjectRoot, corpusLoaded, loadedObservationStore, vectorMissingIds, vectorBackfillRunning, vectorSchemaUpgradePromise, lastVectorBackfill, embeddingFailureLogTimestamps, EMBEDDING_FAILURE_LOG_COOLDOWN_MS;
9120
9599
  var init_observations = __esm({
9121
9600
  "src/memory/observations.ts"() {
9122
9601
  "use strict";
@@ -9135,6 +9614,8 @@ var init_observations = __esm({
9135
9614
  projectDir = null;
9136
9615
  searchIndexPrepared = false;
9137
9616
  embeddingWriteMode = "background";
9617
+ corpusLoaded = false;
9618
+ loadedObservationStore = null;
9138
9619
  vectorMissingIds = /* @__PURE__ */ new Set();
9139
9620
  vectorBackfillRunning = false;
9140
9621
  vectorSchemaUpgradePromise = null;
@@ -10480,7 +10961,7 @@ var init_types2 = __esm({
10480
10961
 
10481
10962
  // src/media/asset-store.ts
10482
10963
  import { createHash as createHash5, randomUUID as randomUUID6 } from "crypto";
10483
- import { copyFile, lstat, mkdir as mkdir3, open, readFile as readFile3, readdir, rename, rm, stat, writeFile as writeFile3 } from "fs/promises";
10964
+ import { copyFile, lstat, mkdir as mkdir3, open, readFile as readFile3, readdir, rename as rename2, rm, stat as stat2, writeFile as writeFile3 } from "fs/promises";
10484
10965
  import path9 from "path";
10485
10966
  function mediaRoot(dataDir) {
10486
10967
  return path9.resolve(dataDir, "media");
@@ -10553,7 +11034,7 @@ async function persistBuffer(bytes, destination) {
10553
11034
  const temporary = `${destination}.${randomUUID6()}.tmp`;
10554
11035
  try {
10555
11036
  await writeFile3(temporary, bytes, { flag: "wx" });
10556
- await rename(temporary, destination);
11037
+ await rename2(temporary, destination);
10557
11038
  return true;
10558
11039
  } catch (error) {
10559
11040
  if (error?.code === "EEXIST" && await destinationExists(destination)) return false;
@@ -61633,9 +62114,9 @@ var require_node_domexception = __commonJS({
61633
62114
  });
61634
62115
 
61635
62116
  // node_modules/fetch-blob/from.js
61636
- import { statSync as statSync2, createReadStream, promises as fs7 } from "fs";
62117
+ import { statSync as statSync2, createReadStream as createReadStream2, promises as fs7 } from "fs";
61637
62118
  import { basename } from "path";
61638
- var import_node_domexception, stat2, blobFromSync, blobFrom, fileFrom, fileFromSync, fromBlob, fromFile, BlobDataItem;
62119
+ var import_node_domexception, stat3, blobFromSync, blobFrom, fileFrom, fileFromSync, fromBlob, fromFile, BlobDataItem;
61639
62120
  var init_from = __esm({
61640
62121
  "node_modules/fetch-blob/from.js"() {
61641
62122
  "use strict";
@@ -61643,23 +62124,23 @@ var init_from = __esm({
61643
62124
  import_node_domexception = __toESM(require_node_domexception(), 1);
61644
62125
  init_file();
61645
62126
  init_fetch_blob();
61646
- ({ stat: stat2 } = fs7);
62127
+ ({ stat: stat3 } = fs7);
61647
62128
  blobFromSync = (path20, type) => fromBlob(statSync2(path20), path20, type);
61648
- blobFrom = (path20, type) => stat2(path20).then((stat4) => fromBlob(stat4, path20, type));
61649
- fileFrom = (path20, type) => stat2(path20).then((stat4) => fromFile(stat4, path20, type));
62129
+ blobFrom = (path20, type) => stat3(path20).then((stat5) => fromBlob(stat5, path20, type));
62130
+ fileFrom = (path20, type) => stat3(path20).then((stat5) => fromFile(stat5, path20, type));
61650
62131
  fileFromSync = (path20, type) => fromFile(statSync2(path20), path20, type);
61651
- fromBlob = (stat4, path20, type = "") => new fetch_blob_default([new BlobDataItem({
62132
+ fromBlob = (stat5, path20, type = "") => new fetch_blob_default([new BlobDataItem({
61652
62133
  path: path20,
61653
- size: stat4.size,
61654
- lastModified: stat4.mtimeMs,
62134
+ size: stat5.size,
62135
+ lastModified: stat5.mtimeMs,
61655
62136
  start: 0
61656
62137
  })], { type });
61657
- fromFile = (stat4, path20, type = "") => new file_default([new BlobDataItem({
62138
+ fromFile = (stat5, path20, type = "") => new file_default([new BlobDataItem({
61658
62139
  path: path20,
61659
- size: stat4.size,
61660
- lastModified: stat4.mtimeMs,
62140
+ size: stat5.size,
62141
+ lastModified: stat5.mtimeMs,
61661
62142
  start: 0
61662
- })], basename(path20), { type, lastModified: stat4.mtimeMs });
62143
+ })], basename(path20), { type, lastModified: stat5.mtimeMs });
61663
62144
  BlobDataItem = class _BlobDataItem {
61664
62145
  #path;
61665
62146
  #start;
@@ -61682,11 +62163,11 @@ var init_from = __esm({
61682
62163
  });
61683
62164
  }
61684
62165
  async *stream() {
61685
- const { mtimeMs } = await stat2(this.#path);
62166
+ const { mtimeMs } = await stat3(this.#path);
61686
62167
  if (mtimeMs > this.lastModified) {
61687
62168
  throw new import_node_domexception.default("The requested file could not be read, typically due to permission problems that have occurred after a reference to a file was acquired.", "NotReadableError");
61688
62169
  }
61689
- yield* createReadStream(this.#path, {
62170
+ yield* createReadStream2(this.#path, {
61690
62171
  start: this.#start,
61691
62172
  end: this.#start + this.size - 1
61692
62173
  });
@@ -77316,7 +77797,7 @@ var init_wrapper = __esm({
77316
77797
  });
77317
77798
 
77318
77799
  // node_modules/@google/genai/dist/node/index.mjs
77319
- import { createWriteStream } from "fs";
77800
+ import { createWriteStream as createWriteStream2 } from "fs";
77320
77801
  import * as fs8 from "fs/promises";
77321
77802
  import { writeFile as writeFile4 } from "fs/promises";
77322
77803
  import { Readable } from "stream";
@@ -94596,7 +95077,7 @@ ${underline}`);
94596
95077
  if (params.downloadPath) {
94597
95078
  const response = await downloadFile(params, apiClient);
94598
95079
  if (response instanceof HttpResponse) {
94599
- const writer = createWriteStream(params.downloadPath);
95080
+ const writer = createWriteStream2(params.downloadPath);
94600
95081
  const body = Readable.fromWeb(response.responseInternal.body);
94601
95082
  body.pipe(writer);
94602
95083
  await finished(writer);
@@ -144514,7 +144995,7 @@ function explainRetention(doc, referenceTime) {
144514
144995
  };
144515
144996
  }
144516
144997
  function toRetentionDocument(obs, accessMap) {
144517
- const access = accessMap?.get(obs.id);
144998
+ const access2 = accessMap?.get(obs.id);
144518
144999
  return {
144519
145000
  id: `obs-${obs.id}`,
144520
145001
  observationId: obs.id,
@@ -144528,8 +145009,8 @@ function toRetentionDocument(obs, accessMap) {
144528
145009
  tokens: obs.tokens,
144529
145010
  createdAt: obs.createdAt,
144530
145011
  projectId: obs.projectId,
144531
- accessCount: access?.accessCount ?? 0,
144532
- lastAccessedAt: access?.lastAccessedAt ?? "",
145012
+ accessCount: access2?.accessCount ?? 0,
145013
+ lastAccessedAt: access2?.lastAccessedAt ?? "",
144533
145014
  status: obs.status ?? "active",
144534
145015
  source: obs.source ?? "agent",
144535
145016
  sourceDetail: obs.sourceDetail ?? "",
@@ -145808,7 +146289,7 @@ function indexFileLite(projectId, projectRoot, abs, indexedAt, fileStat) {
145808
146289
  const rel = normalizeCodePath(relative(projectRoot, abs));
145809
146290
  try {
145810
146291
  const text2 = readFileSync6(abs, "utf-8");
145811
- const stat4 = fileStat ?? statSync3(abs);
146292
+ const stat5 = fileStat ?? statSync3(abs);
145812
146293
  const file = {
145813
146294
  id: makeCodeFileId(projectId, rel),
145814
146295
  projectId,
@@ -145817,8 +146298,8 @@ function indexFileLite(projectId, projectRoot, abs, indexedAt, fileStat) {
145817
146298
  contentHash: hashText(text2),
145818
146299
  // Preserve filesystem precision. Rounding here made same-size edits in
145819
146300
  // a short Windows timestamp window indistinguishable to refresh.
145820
- mtimeMs: Number(stat4.mtimeMs),
145821
- sizeBytes: Number(stat4.size),
146301
+ mtimeMs: Number(stat5.mtimeMs),
146302
+ sizeBytes: Number(stat5.size),
145822
146303
  indexedAt
145823
146304
  };
145824
146305
  return {
@@ -145845,18 +146326,18 @@ async function indexProjectLite(options) {
145845
146326
  let skippedOversizedFiles = 0;
145846
146327
  let unreadableFiles = 0;
145847
146328
  for (const abs of paths) {
145848
- let stat4;
146329
+ let stat5;
145849
146330
  try {
145850
- stat4 = statSync3(abs);
146331
+ stat5 = statSync3(abs);
145851
146332
  } catch {
145852
146333
  unreadableFiles++;
145853
146334
  continue;
145854
146335
  }
145855
- if (Number(stat4.size) > maxFileBytes) {
146336
+ if (Number(stat5.size) > maxFileBytes) {
145856
146337
  skippedOversizedFiles++;
145857
146338
  continue;
145858
146339
  }
145859
- const attempt = indexFileLite(options.projectId, options.projectRoot, abs, indexedAt, stat4);
146340
+ const attempt = indexFileLite(options.projectId, options.projectRoot, abs, indexedAt, stat5);
145860
146341
  if (!attempt.delta) {
145861
146342
  if (attempt.unreadable) unreadableFiles++;
145862
146343
  continue;
@@ -145884,16 +146365,16 @@ async function refreshProjectLite(store, options) {
145884
146365
  for (const abs of paths) {
145885
146366
  const rel = normalizeCodePath(relative(options.projectRoot, abs));
145886
146367
  seenPaths.add(rel);
145887
- let stat4;
146368
+ let stat5;
145888
146369
  try {
145889
- stat4 = statSync3(abs);
146370
+ stat5 = statSync3(abs);
145890
146371
  } catch {
145891
146372
  unreadableFiles++;
145892
146373
  continue;
145893
146374
  }
145894
146375
  const existing = existingByPath.get(rel);
145895
- const mtimeMs = Number(stat4.mtimeMs);
145896
- const sizeBytes = Number(stat4.size);
146376
+ const mtimeMs = Number(stat5.mtimeMs);
146377
+ const sizeBytes = Number(stat5.size);
145897
146378
  if (sizeBytes > maxFileBytes) {
145898
146379
  skippedOversizedFiles++;
145899
146380
  if (existing) oversizedExistingFileIds.add(existing.id);
@@ -145903,7 +146384,7 @@ async function refreshProjectLite(store, options) {
145903
146384
  unchangedFiles++;
145904
146385
  continue;
145905
146386
  }
145906
- const attempt = indexFileLite(options.projectId, options.projectRoot, abs, indexedAt, stat4);
146387
+ const attempt = indexFileLite(options.projectId, options.projectRoot, abs, indexedAt, stat5);
145907
146388
  if (!attempt.delta) {
145908
146389
  if (attempt.unreadable) unreadableFiles++;
145909
146390
  continue;