memorix 1.9.4 → 1.9.6

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 (90) hide show
  1. package/CHANGELOG.md +75 -1
  2. package/README.md +12 -6
  3. package/README.zh-CN.md +12 -6
  4. package/dist/cli/index.js +2533 -585
  5. package/dist/index.d.ts +15 -8
  6. package/dist/index.js +1201 -284
  7. package/dist/maintenance-runner.js +387 -216
  8. package/dist/media-audio-runner.js +300 -129
  9. package/dist/media-video-runner.js +300 -129
  10. package/dist/memcode-runtime/CHANGELOG.md +75 -1
  11. package/dist/sdk.d.ts +1 -0
  12. package/dist/sdk.js +1882 -998
  13. package/dist/types.d.ts +1 -1
  14. package/dist/vector-backfill-runner.js +300 -129
  15. package/docs/AGENT_OPERATOR_PLAYBOOK.md +47 -3
  16. package/docs/API_REFERENCE.md +39 -1
  17. package/docs/CONFIGURATION.md +58 -1
  18. package/docs/DEVELOPMENT.md +1 -1
  19. package/docs/DOCKER.md +23 -3
  20. package/docs/INTEGRATIONS.md +1 -1
  21. package/docs/KNOWN_ISSUES_AND_ROADMAP.md +61 -1
  22. package/docs/MULTI-DEVICE-SYNC-RESEARCH.md +4 -0
  23. package/docs/PERFORMANCE.md +46 -2
  24. package/docs/README.md +2 -1
  25. package/docs/SETUP.md +56 -1
  26. package/package.json +3 -2
  27. package/plugins/antigravity/memorix/plugin.json +1 -1
  28. package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
  29. package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
  30. package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
  31. package/plugins/copilot/memorix/plugin.json +1 -1
  32. package/plugins/gemini/memorix/gemini-extension.json +1 -1
  33. package/plugins/hermes/memorix/plugin.yaml +1 -1
  34. package/plugins/omp/memorix/package.json +1 -1
  35. package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
  36. package/plugins/pi/memorix/package.json +1 -1
  37. package/server.json +2 -2
  38. package/src/cli/capability-map.ts +1 -0
  39. package/src/cli/command-guide.ts +15 -3
  40. package/src/cli/commands/agent-integrations.ts +57 -0
  41. package/src/cli/commands/background.ts +11 -2
  42. package/src/cli/commands/context.ts +2 -0
  43. package/src/cli/commands/continuity.ts +155 -0
  44. package/src/cli/commands/init.ts +5 -2
  45. package/src/cli/commands/serve-http.ts +435 -84
  46. package/src/cli/commands/setup.ts +77 -10
  47. package/src/cli/commands/sync-store.ts +47 -12
  48. package/src/cli/commands/sync.ts +26 -0
  49. package/src/cli/index.ts +3 -1
  50. package/src/cli/tui/ConfigureView.tsx +2 -0
  51. package/src/codegraph/auto-context.ts +17 -0
  52. package/src/config/legacy-loader.ts +2 -2
  53. package/src/config/resolved-config.ts +8 -5
  54. package/src/config/yaml-loader.ts +20 -10
  55. package/src/dashboard/server.ts +10 -12
  56. package/src/embedding/api-provider.ts +4 -2
  57. package/src/embedding/fastembed-provider.ts +47 -14
  58. package/src/embedding/transformers-provider.ts +29 -7
  59. package/src/evaluation/memory-quality-gate.ts +90 -0
  60. package/src/hooks/official-skills.ts +2 -0
  61. package/src/integrations/registry.ts +1 -1
  62. package/src/knowledge/context-assembly.ts +1 -0
  63. package/src/knowledge/context-receipt.ts +15 -0
  64. package/src/knowledge/task-continuity.ts +413 -0
  65. package/src/knowledge/workset.ts +77 -0
  66. package/src/llm/provider.ts +2 -1
  67. package/src/memory/graph.ts +10 -8
  68. package/src/memory/session.ts +1 -1
  69. package/src/orchestrate/coordinator.ts +60 -0
  70. package/src/orchestrate/effect-ledger.ts +160 -0
  71. package/src/orchestrate/pipeline-trace.ts +40 -6
  72. package/src/runtime/maintenance-jobs.ts +12 -6
  73. package/src/sdk.ts +24 -0
  74. package/src/server/mcp-binding-store.ts +14 -3
  75. package/src/server/modern-mcp-bridge.ts +153 -27
  76. package/src/server/tool-profile.ts +3 -2
  77. package/src/server.ts +131 -7
  78. package/src/store/file-lock.ts +28 -3
  79. package/src/store/graph-store.ts +178 -46
  80. package/src/store/persistence.ts +14 -9
  81. package/src/store/sqlite-db.ts +150 -7
  82. package/src/store/sqlite-store.ts +32 -27
  83. package/src/sync/engine.ts +9 -7
  84. package/src/sync/namespace.ts +23 -0
  85. package/src/sync/policy.ts +19 -4
  86. package/src/sync/store-port.ts +43 -13
  87. package/src/sync/types.ts +2 -0
  88. package/src/team/team-store.ts +62 -27
  89. package/src/types.ts +1 -1
  90. package/src/workspace/mcp-adapters/grok.ts +32 -0
@@ -380,11 +380,21 @@ function applySchemaMigrations(db2) {
380
380
  apply();
381
381
  }
382
382
  }
383
+ function normalizeDataDir(dataDir) {
384
+ return path3.resolve(dataDir);
385
+ }
386
+ function touchDatabase(normalized, db2) {
387
+ _dbCache.delete(normalized);
388
+ _dbCache.set(normalized, db2);
389
+ }
383
390
  function getDatabase(dataDir) {
384
- const normalized = path3.resolve(dataDir);
391
+ const normalized = normalizeDataDir(dataDir);
385
392
  assertNotHomeDataDir(normalized);
386
393
  const existing = _dbCache.get(normalized);
387
- if (existing) return existing;
394
+ if (existing) {
395
+ touchDatabase(normalized, existing);
396
+ return existing;
397
+ }
388
398
  loadBetterSqlite3();
389
399
  fs.mkdirSync(dataDir, { recursive: true });
390
400
  const dbPath = path3.join(dataDir, "memorix.db");
@@ -414,6 +424,8 @@ function getDatabase(dataDir) {
414
424
  db2.exec(CREATE_MAINTENANCE_JOBS_TABLE);
415
425
  db2.exec(CREATE_MAINTENANCE_TARGETS_TABLE);
416
426
  db2.exec(CREATE_COMPACTION_CHECKPOINTS_TABLE);
427
+ db2.exec(CREATE_TASK_CONTINUITY_EVENTS_TABLE);
428
+ db2.exec(CREATE_AGENT_EFFECTS_TABLE);
417
429
  try {
418
430
  db2.exec(`ALTER TABLE mini_skills ADD COLUMN sourceSnapshot TEXT NOT NULL DEFAULT ''`);
419
431
  } catch {
@@ -452,7 +464,7 @@ function getDatabase(dataDir) {
452
464
  db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('storage_generation', '0')`).run();
453
465
  db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('next_id', '1')`).run();
454
466
  db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('mini_skills_generation', '0')`).run();
455
- _dbCache.set(normalized, db2);
467
+ touchDatabase(normalized, db2);
456
468
  return db2;
457
469
  } catch (error) {
458
470
  try {
@@ -470,8 +482,9 @@ function closeAllDatabases() {
470
482
  }
471
483
  _dbCache.delete(key);
472
484
  }
485
+ _dbLeases.clear();
473
486
  }
474
- var BetterSqlite3, CREATE_OBSERVATIONS_TABLE, CREATE_MINI_SKILLS_TABLE, CREATE_SESSIONS_TABLE, CREATE_META_TABLE, CREATE_TEAM_AGENTS_TABLE, CREATE_TEAM_MESSAGES_TABLE, CREATE_TEAM_TASKS_TABLE, CREATE_TEAM_TASK_DEPS_TABLE, CREATE_TEAM_LOCKS_TABLE, CREATE_TEAM_ROLES_TABLE, CREATE_CHAT_TRANSCRIPT_TABLE, CREATE_GRAPH_ENTITIES_TABLE, CREATE_GRAPH_RELATIONS_TABLE, CREATE_CODE_FILES_TABLE, CREATE_CODE_SYMBOLS_TABLE, CREATE_CODE_EDGES_TABLE, CREATE_OBSERVATION_CODE_REFS_TABLE, CREATE_SCHEMA_MIGRATIONS_TABLE, CREATE_CODE_STATE_SNAPSHOTS_TABLE, CREATE_CODE_STATE_SNAPSHOT_FILES_TABLE, CREATE_KNOWLEDGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_CLAIM_EVIDENCE_TABLE, CREATE_KNOWLEDGE_CLAIM_EVENTS_TABLE, CREATE_KNOWLEDGE_WORKSPACES_TABLE, CREATE_KNOWLEDGE_PAGES_TABLE, CREATE_KNOWLEDGE_PAGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_PAGE_LINKS_TABLE, CREATE_KNOWLEDGE_PROPOSALS_TABLE, CREATE_KNOWLEDGE_WORKFLOWS_TABLE, CREATE_KNOWLEDGE_WORKFLOW_RUNS_TABLE, CREATE_LONG_TERM_MEMORIES_TABLE, CREATE_LONG_TERM_MEMORY_EVIDENCE_TABLE, CREATE_LONG_TERM_MEMORY_EVENTS_TABLE, CREATE_MEMORY_OUTCOME_SIGNALS_TABLE, CREATE_MEDIA_ASSETS_TABLE, CREATE_MEDIA_ASSET_LINKS_TABLE, CREATE_MEDIA_DERIVATIONS_TABLE, CREATE_MEDIA_EMBEDDING_PROFILES_TABLE, CREATE_MEDIA_EMBEDDINGS_TABLE, CREATE_MEDIA_JOBS_TABLE, CREATE_MAINTENANCE_JOBS_TABLE, CREATE_MAINTENANCE_TARGETS_TABLE, CREATE_COMPACTION_CHECKPOINTS_TABLE, CREATE_EVIDENCE_CARDS_TABLE, CREATE_EVIDENCE_CARD_EVENTS_TABLE, CREATE_MEMORY_FEEDBACK_STATES_TABLE, CREATE_MEMORY_FEEDBACK_EVENTS_TABLE, CREATE_MCP_BINDINGS_TABLE, CREATE_INDEXES, SCHEMA_MIGRATIONS, _dbCache;
487
+ var BetterSqlite3, CREATE_OBSERVATIONS_TABLE, CREATE_MINI_SKILLS_TABLE, CREATE_SESSIONS_TABLE, CREATE_META_TABLE, CREATE_TEAM_AGENTS_TABLE, CREATE_TEAM_MESSAGES_TABLE, CREATE_TEAM_TASKS_TABLE, CREATE_TEAM_TASK_DEPS_TABLE, CREATE_TEAM_LOCKS_TABLE, CREATE_TEAM_ROLES_TABLE, CREATE_CHAT_TRANSCRIPT_TABLE, CREATE_GRAPH_ENTITIES_TABLE, CREATE_GRAPH_RELATIONS_TABLE, CREATE_CODE_FILES_TABLE, CREATE_CODE_SYMBOLS_TABLE, CREATE_CODE_EDGES_TABLE, CREATE_OBSERVATION_CODE_REFS_TABLE, CREATE_SCHEMA_MIGRATIONS_TABLE, CREATE_CODE_STATE_SNAPSHOTS_TABLE, CREATE_CODE_STATE_SNAPSHOT_FILES_TABLE, CREATE_KNOWLEDGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_CLAIM_EVIDENCE_TABLE, CREATE_KNOWLEDGE_CLAIM_EVENTS_TABLE, CREATE_KNOWLEDGE_WORKSPACES_TABLE, CREATE_KNOWLEDGE_PAGES_TABLE, CREATE_KNOWLEDGE_PAGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_PAGE_LINKS_TABLE, CREATE_KNOWLEDGE_PROPOSALS_TABLE, CREATE_KNOWLEDGE_WORKFLOWS_TABLE, CREATE_KNOWLEDGE_WORKFLOW_RUNS_TABLE, CREATE_LONG_TERM_MEMORIES_TABLE, CREATE_LONG_TERM_MEMORY_EVIDENCE_TABLE, CREATE_LONG_TERM_MEMORY_EVENTS_TABLE, CREATE_MEMORY_OUTCOME_SIGNALS_TABLE, CREATE_MEDIA_ASSETS_TABLE, CREATE_MEDIA_ASSET_LINKS_TABLE, CREATE_MEDIA_DERIVATIONS_TABLE, CREATE_MEDIA_EMBEDDING_PROFILES_TABLE, CREATE_MEDIA_EMBEDDINGS_TABLE, CREATE_MEDIA_JOBS_TABLE, CREATE_MAINTENANCE_JOBS_TABLE, CREATE_MAINTENANCE_TARGETS_TABLE, CREATE_COMPACTION_CHECKPOINTS_TABLE, CREATE_EVIDENCE_CARDS_TABLE, CREATE_EVIDENCE_CARD_EVENTS_TABLE, CREATE_MEMORY_FEEDBACK_STATES_TABLE, CREATE_MEMORY_FEEDBACK_EVENTS_TABLE, CREATE_TASK_CONTINUITY_EVENTS_TABLE, CREATE_AGENT_EFFECTS_TABLE, CREATE_MCP_BINDINGS_TABLE, CREATE_INDEXES, SCHEMA_MIGRATIONS, _dbCache, _dbLeases;
475
488
  var init_sqlite_db = __esm({
476
489
  "src/store/sqlite-db.ts"() {
477
490
  "use strict";
@@ -643,18 +656,21 @@ CREATE TABLE IF NOT EXISTS chat_transcript (
643
656
  `;
644
657
  CREATE_GRAPH_ENTITIES_TABLE = `
645
658
  CREATE TABLE IF NOT EXISTS graph_entities (
646
- name TEXT PRIMARY KEY,
659
+ projectId TEXT NOT NULL,
660
+ name TEXT NOT NULL,
647
661
  entityType TEXT NOT NULL DEFAULT '',
648
- observations TEXT NOT NULL DEFAULT '[]'
662
+ observations TEXT NOT NULL DEFAULT '[]',
663
+ PRIMARY KEY (projectId, name)
649
664
  );
650
665
  `;
651
666
  CREATE_GRAPH_RELATIONS_TABLE = `
652
667
  CREATE TABLE IF NOT EXISTS graph_relations (
653
668
  id INTEGER PRIMARY KEY AUTOINCREMENT,
669
+ projectId TEXT NOT NULL,
654
670
  from_entity TEXT NOT NULL,
655
671
  to_entity TEXT NOT NULL,
656
672
  relationType TEXT NOT NULL DEFAULT '',
657
- UNIQUE(from_entity, to_entity, relationType)
673
+ UNIQUE(projectId, from_entity, to_entity, relationType)
658
674
  );
659
675
  `;
660
676
  CREATE_CODE_FILES_TABLE = `
@@ -1185,6 +1201,43 @@ CREATE TABLE IF NOT EXISTS memory_feedback_events (
1185
1201
  delta REAL NOT NULL DEFAULT 0,
1186
1202
  observed_at TEXT NOT NULL
1187
1203
  );
1204
+ `;
1205
+ CREATE_TASK_CONTINUITY_EVENTS_TABLE = `
1206
+ CREATE TABLE IF NOT EXISTS task_continuity_events (
1207
+ id TEXT PRIMARY KEY,
1208
+ project_id TEXT NOT NULL,
1209
+ task_id TEXT NOT NULL,
1210
+ task TEXT NOT NULL,
1211
+ kind TEXT NOT NULL,
1212
+ content TEXT NOT NULL,
1213
+ item_status TEXT,
1214
+ source_ref TEXT,
1215
+ evidence_json TEXT NOT NULL DEFAULT '[]',
1216
+ actor TEXT,
1217
+ created_at TEXT NOT NULL,
1218
+ event_key TEXT,
1219
+ item_key TEXT,
1220
+ supersedes_id TEXT
1221
+ );
1222
+ `;
1223
+ CREATE_AGENT_EFFECTS_TABLE = `
1224
+ CREATE TABLE IF NOT EXISTS agent_effects (
1225
+ id TEXT PRIMARY KEY,
1226
+ pipeline_id TEXT NOT NULL,
1227
+ task_id TEXT NOT NULL,
1228
+ attempt INTEGER NOT NULL,
1229
+ effect_key TEXT NOT NULL,
1230
+ tool TEXT NOT NULL,
1231
+ risk_tier TEXT NOT NULL,
1232
+ replay_policy TEXT NOT NULL,
1233
+ status TEXT NOT NULL,
1234
+ call_id TEXT,
1235
+ idempotency_key TEXT NOT NULL,
1236
+ input_fingerprint TEXT,
1237
+ detail TEXT,
1238
+ started_at INTEGER NOT NULL,
1239
+ finished_at INTEGER
1240
+ );
1188
1241
  `;
1189
1242
  CREATE_MCP_BINDINGS_TABLE = `
1190
1243
  CREATE TABLE IF NOT EXISTS mcp_bindings (
@@ -1263,7 +1316,18 @@ CREATE INDEX IF NOT EXISTS idx_evidence_cards_candidate ON evidence_cards(projec
1263
1316
  CREATE INDEX IF NOT EXISTS idx_evidence_card_events_card ON evidence_card_events(card_id, created_at);
1264
1317
  CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC);
1265
1318
  CREATE INDEX IF NOT EXISTS idx_memory_feedback_events_candidate ON memory_feedback_events(project_id, candidate_kind, candidate_id, observed_at DESC);
1319
+ CREATE INDEX IF NOT EXISTS idx_task_continuity_project_task ON task_continuity_events(project_id, task_id, created_at ASC);
1320
+ CREATE INDEX IF NOT EXISTS idx_task_continuity_project_recent ON task_continuity_events(project_id, created_at DESC);
1321
+ CREATE INDEX IF NOT EXISTS idx_task_continuity_item ON task_continuity_events(project_id, task_id, kind, item_key, created_at DESC);
1322
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_task_continuity_event_key
1323
+ ON task_continuity_events(project_id, task_id, event_key)
1324
+ WHERE event_key IS NOT NULL;
1325
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_agent_effect_identity
1326
+ ON agent_effects(pipeline_id, task_id, attempt, effect_key);
1327
+ CREATE INDEX IF NOT EXISTS idx_agent_effect_pipeline ON agent_effects(pipeline_id, started_at ASC);
1266
1328
  CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC);
1329
+ CREATE INDEX IF NOT EXISTS idx_mcp_bindings_root ON mcp_bindings(project_root, last_used_at DESC);
1330
+ CREATE INDEX IF NOT EXISTS idx_mcp_bindings_expiry ON mcp_bindings(expires_at);
1267
1331
  CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
1268
1332
  ON maintenance_jobs(project_id, kind, dedupe_key)
1269
1333
  WHERE status IN ('pending', 'running', 'retry');
@@ -1434,6 +1498,8 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
1434
1498
  db2.exec("CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC)");
1435
1499
  db2.exec("CREATE INDEX IF NOT EXISTS idx_memory_feedback_events_candidate ON memory_feedback_events(project_id, candidate_kind, candidate_id, observed_at DESC)");
1436
1500
  db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC)");
1501
+ db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_root ON mcp_bindings(project_root, last_used_at DESC)");
1502
+ db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_expiry ON mcp_bindings(expires_at)");
1437
1503
  }
1438
1504
  },
1439
1505
  {
@@ -1444,9 +1510,22 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
1444
1510
  addColumnIfMissing(db2, "code_symbols", "source", "source TEXT");
1445
1511
  addColumnIfMissing(db2, "code_edges", "source", "source TEXT");
1446
1512
  }
1513
+ },
1514
+ {
1515
+ id: "1.9-continuity-v2",
1516
+ apply: (db2) => {
1517
+ addColumnIfMissing(db2, "task_continuity_events", "event_key", "event_key TEXT");
1518
+ addColumnIfMissing(db2, "task_continuity_events", "item_key", "item_key TEXT");
1519
+ addColumnIfMissing(db2, "task_continuity_events", "supersedes_id", "supersedes_id TEXT");
1520
+ db2.exec("CREATE INDEX IF NOT EXISTS idx_task_continuity_item ON task_continuity_events(project_id, task_id, kind, item_key, created_at DESC)");
1521
+ db2.exec(`CREATE UNIQUE INDEX IF NOT EXISTS idx_task_continuity_event_key
1522
+ ON task_continuity_events(project_id, task_id, event_key)
1523
+ WHERE event_key IS NOT NULL`);
1524
+ }
1447
1525
  }
1448
1526
  ];
1449
1527
  _dbCache = /* @__PURE__ */ new Map();
1528
+ _dbLeases = /* @__PURE__ */ new Map();
1450
1529
  }
1451
1530
  });
1452
1531
 
@@ -1549,15 +1628,20 @@ var init_dotenv_loader = __esm({
1549
1628
  import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
1550
1629
  import { homedir as homedir2 } from "os";
1551
1630
  import { parse as parseYamlDocument } from "yaml";
1631
+ function cacheKey(homeDir, projectRoot) {
1632
+ return `${homeDir}\0${projectRoot ?? ""}`;
1633
+ }
1552
1634
  function initProjectRoot(root) {
1553
1635
  globalProjectRoot = root;
1554
- configCache.delete(root);
1636
+ configCache.delete(cacheKey(homedir2(), root));
1555
1637
  }
1556
- function loadYamlConfig(projectRoot) {
1638
+ function loadYamlConfig(projectRoot, options = {}) {
1639
+ const homeDir = options.homeDir ?? homedir2();
1557
1640
  const resolvedRoot = projectRoot === null ? null : projectRoot ?? globalProjectRoot ?? null;
1558
- const cached = configCache.get(resolvedRoot ?? null);
1641
+ const key = cacheKey(homeDir, resolvedRoot);
1642
+ const cached = configCache.get(key);
1559
1643
  if (cached) return cached;
1560
- const userYaml = getGlobalYamlPath(homedir2());
1644
+ const userYaml = getGlobalYamlPath(homeDir);
1561
1645
  const projectYaml = resolvedRoot ? getProjectYamlPath(resolvedRoot) : null;
1562
1646
  let userConfig = {};
1563
1647
  let projectConfig = {};
@@ -1589,7 +1673,7 @@ function loadYamlConfig(projectRoot) {
1589
1673
  server: { ...userConfig.server, ...projectConfig.server },
1590
1674
  team: { ...userConfig.team, ...projectConfig.team }
1591
1675
  };
1592
- configCache.set(resolvedRoot ?? null, merged);
1676
+ configCache.set(key, merged);
1593
1677
  return merged;
1594
1678
  }
1595
1679
  function parseYaml(content) {
@@ -1765,9 +1849,9 @@ var init_detector = __esm({
1765
1849
  // src/config/legacy-loader.ts
1766
1850
  import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
1767
1851
  import { homedir as homedir3 } from "os";
1768
- function loadFileConfig() {
1852
+ function loadFileConfig(homeDir = homedir3()) {
1769
1853
  if (cachedConfig !== null) return cachedConfig;
1770
- const configPath = getLegacyConfigJsonPath(homedir3());
1854
+ const configPath = getLegacyConfigJsonPath(homeDir);
1771
1855
  try {
1772
1856
  if (existsSync5(configPath)) {
1773
1857
  cachedConfig = JSON.parse(readFileSync5(configPath, "utf-8"));
@@ -1797,15 +1881,15 @@ import { homedir as homedir4 } from "os";
1797
1881
  function loadTomlConfig(options = {}) {
1798
1882
  const homeDir = options.homeDir ?? homedir4();
1799
1883
  const projectRoot = options.projectRoot ?? null;
1800
- const cacheKey = `${homeDir}\0${projectRoot ?? ""}`;
1801
- const cached = configCache2.get(cacheKey);
1884
+ const cacheKey3 = `${homeDir}\0${projectRoot ?? ""}`;
1885
+ const cached = configCache2.get(cacheKey3);
1802
1886
  if (cached) return cached;
1803
1887
  const userToml = getGlobalConfigTomlPath(homeDir);
1804
1888
  const projectToml = projectRoot ? getProjectConfigTomlPath(projectRoot) : null;
1805
1889
  const userConfig = existsSync6(userToml) ? parseTomlConfig(readFileSync6(userToml, "utf8"), userToml) : {};
1806
1890
  const projectConfig = projectToml && existsSync6(projectToml) ? parseTomlConfig(readFileSync6(projectToml, "utf8"), projectToml) : {};
1807
1891
  const merged = mergeTomlConfig(userConfig, projectConfig);
1808
- configCache2.set(cacheKey, merged);
1892
+ configCache2.set(cacheKey3, merged);
1809
1893
  return merged;
1810
1894
  }
1811
1895
  function mergeTomlConfig(base, override) {
@@ -1926,8 +2010,8 @@ function getResolvedConfig(options = {}) {
1926
2010
  const projectRoot = options.projectRoot === void 0 ? detectProject()?.rootPath ?? null : options.projectRoot;
1927
2011
  loadDotenv(projectRoot === null ? void 0 : projectRoot ?? void 0, { userHomeDir: homeDir });
1928
2012
  const toml = loadTomlConfig({ projectRoot: projectRoot ?? null, homeDir });
1929
- const yaml = loadYamlConfig(projectRoot ?? null);
1930
- const legacy = loadFileConfig();
2013
+ const yaml = loadYamlConfig(projectRoot ?? null, { homeDir });
2014
+ const legacy = loadFileConfig(homeDir);
1931
2015
  const embeddingBaseUrl = first(process.env.MEMORIX_EMBEDDING_BASE_URL, toml.embedding?.base_url, yaml.embedding?.baseUrl, legacy.embeddingApi?.baseUrl);
1932
2016
  const openRouterEmbeddingApiKey = isOpenRouterUrl(embeddingBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
1933
2017
  const memoryLlmProvider = first(
@@ -1949,15 +2033,17 @@ function getResolvedConfig(options = {}) {
1949
2033
  legacy.llm?.baseUrl
1950
2034
  );
1951
2035
  const openRouterMemoryLlmApiKey = isOpenRouterMemoryLane(memoryLlmProvider, memoryLlmBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
2036
+ const isAtlasCloud = memoryLlmProvider === "atlascloud";
1952
2037
  const memoryLlmApiKey = first(
1953
2038
  process.env.MEMORIX_LLM_API_KEY,
1954
2039
  process.env.MEMORIX_API_KEY,
1955
2040
  toml.memory?.llm?.api_key,
1956
2041
  yaml.llm?.apiKey,
1957
2042
  legacy.llm?.apiKey,
1958
- process.env.OPENAI_API_KEY,
1959
- process.env.ANTHROPIC_API_KEY,
1960
- openRouterMemoryLlmApiKey
2043
+ // Never borrow another provider's credentials for the Atlas Cloud preset.
2044
+ isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : process.env.OPENAI_API_KEY,
2045
+ isAtlasCloud ? void 0 : process.env.ANTHROPIC_API_KEY,
2046
+ isAtlasCloud ? void 0 : openRouterMemoryLlmApiKey
1961
2047
  );
1962
2048
  const resolved = {
1963
2049
  agent: {
@@ -2136,7 +2222,8 @@ function getEnvSourceNames() {
2136
2222
  "MEMORIX_CODEGRAPH_EXTERNAL_CONTEXT",
2137
2223
  "MEMORIX_CODEGRAPH_EXTERNAL_COMMAND",
2138
2224
  "MEMORIX_CODEGRAPH_EXTERNAL_TIMEOUT_MS",
2139
- "OPENROUTER_API_KEY"
2225
+ "OPENROUTER_API_KEY",
2226
+ "ATLASCLOUD_API_KEY"
2140
2227
  ].filter((name) => process.env[name]);
2141
2228
  }
2142
2229
  function isOpenRouterUrl(value) {
@@ -2967,6 +3054,7 @@ var init_provider = __esm({
2967
3054
  openai: { baseUrl: "https://api.openai.com/v1", model: "gpt-4.1-nano" },
2968
3055
  anthropic: { baseUrl: "https://api.anthropic.com/v1", model: "claude-3-5-haiku-latest" },
2969
3056
  openrouter: { baseUrl: "https://openrouter.ai/api/v1", model: "openai/gpt-4.1-nano" },
3057
+ atlascloud: { baseUrl: "https://api.atlascloud.ai/v1", model: "deepseek-ai/deepseek-v3.2" },
2970
3058
  custom: { baseUrl: "http://localhost:11434/v1", model: "llama3" }
2971
3059
  };
2972
3060
  currentConfig = null;
@@ -3041,13 +3129,120 @@ var init_sqlite_reliability = __esm({
3041
3129
  }
3042
3130
  });
3043
3131
 
3132
+ // src/store/file-lock.ts
3133
+ import { promises as fs2 } from "fs";
3134
+ import { randomUUID } from "crypto";
3135
+ import path5 from "path";
3136
+ function canReclaimStaleLock(raw) {
3137
+ try {
3138
+ const parsed = JSON.parse(raw);
3139
+ const pid = Number(parsed.pid);
3140
+ if (!Number.isSafeInteger(pid) || pid < 1) return true;
3141
+ try {
3142
+ process.kill(pid, 0);
3143
+ return false;
3144
+ } catch (error) {
3145
+ return error.code !== "EPERM";
3146
+ }
3147
+ } catch {
3148
+ return true;
3149
+ }
3150
+ }
3151
+ async function acquireLock(lockPath) {
3152
+ for (let i2 = 0; i2 < MAX_RETRIES; i2++) {
3153
+ try {
3154
+ const fd = await fs2.open(lockPath, "wx");
3155
+ await fd.writeFile(JSON.stringify({ pid: process.pid, time: Date.now() }));
3156
+ await fd.close();
3157
+ return;
3158
+ } catch (err) {
3159
+ const code = err instanceof Error && "code" in err ? err.code : void 0;
3160
+ if (code === "EEXIST" || code === "EPERM") {
3161
+ try {
3162
+ const stat5 = await fs2.stat(lockPath);
3163
+ if (Date.now() - stat5.mtimeMs > LOCK_STALE_MS) {
3164
+ const raw2 = await fs2.readFile(lockPath, "utf8").catch(() => "");
3165
+ if (canReclaimStaleLock(raw2)) {
3166
+ await fs2.unlink(lockPath).catch(() => {
3167
+ });
3168
+ continue;
3169
+ }
3170
+ }
3171
+ } catch {
3172
+ continue;
3173
+ }
3174
+ await new Promise((r2) => setTimeout(r2, RETRY_INTERVAL_MS));
3175
+ } else {
3176
+ throw err;
3177
+ }
3178
+ }
3179
+ }
3180
+ const raw = await fs2.readFile(lockPath, "utf8").catch(() => "");
3181
+ if (!canReclaimStaleLock(raw)) {
3182
+ throw new Error(`Failed to acquire lock: ${lockPath} (owner is still running)`);
3183
+ }
3184
+ await fs2.unlink(lockPath).catch(() => {
3185
+ });
3186
+ try {
3187
+ const fd = await fs2.open(lockPath, "wx");
3188
+ await fd.writeFile(JSON.stringify({ pid: process.pid, time: Date.now() }));
3189
+ await fd.close();
3190
+ return;
3191
+ } catch {
3192
+ throw new Error(`Failed to acquire lock: ${lockPath} (timeout after ${MAX_RETRIES * RETRY_INTERVAL_MS}ms)`);
3193
+ }
3194
+ }
3195
+ async function releaseLock(lockPath) {
3196
+ await fs2.unlink(lockPath).catch(() => {
3197
+ });
3198
+ }
3199
+ async function withFileLock(projectDir2, fn) {
3200
+ const lockPath = path5.join(projectDir2, ".memorix.lock");
3201
+ await acquireLock(lockPath);
3202
+ try {
3203
+ return await fn();
3204
+ } finally {
3205
+ await releaseLock(lockPath);
3206
+ }
3207
+ }
3208
+ async function atomicWriteFileOnce(filePath, data) {
3209
+ const tmpPath = filePath + `.tmp.${process.pid}.${randomUUID()}`;
3210
+ try {
3211
+ await fs2.writeFile(tmpPath, data, "utf-8");
3212
+ await fs2.rename(tmpPath, filePath);
3213
+ } catch (error) {
3214
+ await fs2.unlink(tmpPath).catch(() => {
3215
+ });
3216
+ throw error;
3217
+ }
3218
+ }
3219
+ function atomicWriteFile(filePath, data) {
3220
+ const previous = atomicWriteTails.get(filePath) ?? Promise.resolve();
3221
+ const next = previous.catch(() => void 0).then(() => atomicWriteFileOnce(filePath, data));
3222
+ atomicWriteTails.set(filePath, next);
3223
+ return next.finally(() => {
3224
+ if (atomicWriteTails.get(filePath) === next) atomicWriteTails.delete(filePath);
3225
+ });
3226
+ }
3227
+ var LOCK_STALE_MS, RETRY_INTERVAL_MS, MAX_RETRIES, atomicWriteTails;
3228
+ var init_file_lock = __esm({
3229
+ "src/store/file-lock.ts"() {
3230
+ "use strict";
3231
+ init_esm_shims();
3232
+ LOCK_STALE_MS = 1e4;
3233
+ RETRY_INTERVAL_MS = 50;
3234
+ MAX_RETRIES = 60;
3235
+ atomicWriteTails = /* @__PURE__ */ new Map();
3236
+ }
3237
+ });
3238
+
3044
3239
  // src/store/sqlite-store.ts
3045
3240
  var sqlite_store_exports = {};
3046
3241
  __export(sqlite_store_exports, {
3047
3242
  SqliteBackend: () => SqliteBackend
3048
3243
  });
3049
- import path5 from "path";
3050
- import fs2 from "fs";
3244
+ import path6 from "path";
3245
+ import fs3 from "fs";
3051
3246
  function obsToRow(obs) {
3052
3247
  return {
3053
3248
  id: obs.id,
@@ -3134,6 +3329,7 @@ var init_sqlite_store = __esm({
3134
3329
  init_sqlite_db();
3135
3330
  init_sqlite_reliability();
3136
3331
  init_sqlite_fts();
3332
+ init_file_lock();
3137
3333
  SqliteBackend = class {
3138
3334
  db = null;
3139
3335
  dataDir = "";
@@ -3297,38 +3493,43 @@ var init_sqlite_store = __esm({
3297
3493
  }
3298
3494
  // ── Migration ────────────────────────────────────────────────────
3299
3495
  async migrateFromJsonIfNeeded() {
3300
- const count2 = this.db.prepare(`SELECT COUNT(*) AS cnt FROM observations`).get();
3301
- if (count2.cnt > 0) return;
3302
- const jsonPath = path5.join(this.dataDir, "observations.json");
3303
- if (!fs2.existsSync(jsonPath)) return;
3304
- try {
3305
- const raw = fs2.readFileSync(jsonPath, "utf-8");
3306
- const observations2 = JSON.parse(raw);
3496
+ const jsonPath = path6.join(this.dataDir, "observations.json");
3497
+ if (!fs3.existsSync(jsonPath)) return;
3498
+ await withFileLock(this.dataDir, async () => {
3499
+ const count2 = this.db.prepare(`SELECT COUNT(*) AS cnt FROM observations`).get();
3500
+ if (count2.cnt > 0) return;
3501
+ const raw = fs3.readFileSync(jsonPath, "utf-8");
3502
+ const parsed = JSON.parse(raw);
3503
+ if (!Array.isArray(parsed)) {
3504
+ throw new Error("[memorix] observations.json migration refused: expected a JSON array");
3505
+ }
3506
+ const observations2 = parsed;
3307
3507
  if (observations2.length === 0) return;
3508
+ if (observations2.some((obs) => !obs || !Number.isSafeInteger(obs.id) || obs.id < 1 || typeof obs.projectId !== "string")) {
3509
+ throw new Error("[memorix] observations.json migration refused: invalid observation record");
3510
+ }
3308
3511
  console.error(`[memorix] Migrating ${observations2.length} observations from JSON to SQLite...`);
3309
3512
  const insertMany = this.db.transaction((obsList) => {
3310
3513
  for (const obs of obsList) {
3311
3514
  this.stmtInsert.run(obsToRow(obs));
3312
3515
  }
3516
+ const counterPath = path6.join(this.dataDir, "counter.json");
3517
+ let counterNextId;
3518
+ if (fs3.existsSync(counterPath)) {
3519
+ const counterData = JSON.parse(fs3.readFileSync(counterPath, "utf-8"));
3520
+ const candidate = counterData.nextId ?? counterData.next_id;
3521
+ if (candidate !== void 0 && (!Number.isSafeInteger(candidate) || Number(candidate) < 1)) {
3522
+ throw new Error("[memorix] counter.json migration refused: nextId must be a positive integer");
3523
+ }
3524
+ counterNextId = candidate === void 0 ? void 0 : Number(candidate);
3525
+ }
3526
+ const maxId = Math.max(...obsList.map((obs) => obs.id));
3527
+ this.rawSaveIdCounter(Math.max(counterNextId ?? 1, maxId + 1));
3528
+ this.bumpGeneration();
3313
3529
  });
3314
3530
  insertMany(observations2);
3315
- const counterPath = path5.join(this.dataDir, "counter.json");
3316
- if (fs2.existsSync(counterPath)) {
3317
- try {
3318
- const counterData = JSON.parse(fs2.readFileSync(counterPath, "utf-8"));
3319
- const nextId2 = counterData.nextId ?? counterData.next_id ?? Math.max(...observations2.map((o) => o.id)) + 1;
3320
- this.rawSaveIdCounter(nextId2);
3321
- } catch {
3322
- this.rawSaveIdCounter(Math.max(...observations2.map((o) => o.id)) + 1);
3323
- }
3324
- } else {
3325
- this.rawSaveIdCounter(Math.max(...observations2.map((o) => o.id)) + 1);
3326
- }
3327
- this.bumpGeneration();
3328
3531
  console.error(`[memorix] Migration complete. ${observations2.length} observations now in SQLite.`);
3329
- } catch (err) {
3330
- console.error(`[memorix] JSON\u2192SQLite migration failed (non-fatal, data preserved in JSON): ${err}`);
3331
- }
3532
+ });
3332
3533
  }
3333
3534
  // ── Public read ──────────────────────────────────────────────────
3334
3535
  async loadAll() {
@@ -3657,91 +3858,6 @@ var init_types = __esm({
3657
3858
  }
3658
3859
  });
3659
3860
 
3660
- // src/store/file-lock.ts
3661
- import { promises as fs3 } from "fs";
3662
- import { randomUUID } from "crypto";
3663
- import path6 from "path";
3664
- async function acquireLock(lockPath) {
3665
- for (let i2 = 0; i2 < MAX_RETRIES; i2++) {
3666
- try {
3667
- const fd = await fs3.open(lockPath, "wx");
3668
- await fd.writeFile(JSON.stringify({ pid: process.pid, time: Date.now() }));
3669
- await fd.close();
3670
- return;
3671
- } catch (err) {
3672
- const code = err instanceof Error && "code" in err ? err.code : void 0;
3673
- if (code === "EEXIST" || code === "EPERM") {
3674
- try {
3675
- const stat5 = await fs3.stat(lockPath);
3676
- if (Date.now() - stat5.mtimeMs > LOCK_STALE_MS) {
3677
- await fs3.unlink(lockPath).catch(() => {
3678
- });
3679
- continue;
3680
- }
3681
- } catch {
3682
- continue;
3683
- }
3684
- await new Promise((r2) => setTimeout(r2, RETRY_INTERVAL_MS));
3685
- } else {
3686
- throw err;
3687
- }
3688
- }
3689
- }
3690
- await fs3.unlink(lockPath).catch(() => {
3691
- });
3692
- try {
3693
- const fd = await fs3.open(lockPath, "wx");
3694
- await fd.writeFile(JSON.stringify({ pid: process.pid, time: Date.now() }));
3695
- await fd.close();
3696
- return;
3697
- } catch {
3698
- throw new Error(`Failed to acquire lock: ${lockPath} (timeout after ${MAX_RETRIES * RETRY_INTERVAL_MS}ms)`);
3699
- }
3700
- }
3701
- async function releaseLock(lockPath) {
3702
- await fs3.unlink(lockPath).catch(() => {
3703
- });
3704
- }
3705
- async function withFileLock(projectDir2, fn) {
3706
- const lockPath = path6.join(projectDir2, ".memorix.lock");
3707
- await acquireLock(lockPath);
3708
- try {
3709
- return await fn();
3710
- } finally {
3711
- await releaseLock(lockPath);
3712
- }
3713
- }
3714
- async function atomicWriteFileOnce(filePath, data) {
3715
- const tmpPath = filePath + `.tmp.${process.pid}.${randomUUID()}`;
3716
- try {
3717
- await fs3.writeFile(tmpPath, data, "utf-8");
3718
- await fs3.rename(tmpPath, filePath);
3719
- } catch (error) {
3720
- await fs3.unlink(tmpPath).catch(() => {
3721
- });
3722
- throw error;
3723
- }
3724
- }
3725
- function atomicWriteFile(filePath, data) {
3726
- const previous = atomicWriteTails.get(filePath) ?? Promise.resolve();
3727
- const next = previous.catch(() => void 0).then(() => atomicWriteFileOnce(filePath, data));
3728
- atomicWriteTails.set(filePath, next);
3729
- return next.finally(() => {
3730
- if (atomicWriteTails.get(filePath) === next) atomicWriteTails.delete(filePath);
3731
- });
3732
- }
3733
- var LOCK_STALE_MS, RETRY_INTERVAL_MS, MAX_RETRIES, atomicWriteTails;
3734
- var init_file_lock = __esm({
3735
- "src/store/file-lock.ts"() {
3736
- "use strict";
3737
- init_esm_shims();
3738
- LOCK_STALE_MS = 1e4;
3739
- RETRY_INTERVAL_MS = 50;
3740
- MAX_RETRIES = 60;
3741
- atomicWriteTails = /* @__PURE__ */ new Map();
3742
- }
3743
- });
3744
-
3745
3861
  // src/store/mini-skill-store.ts
3746
3862
  import path7 from "path";
3747
3863
  import fs4 from "fs";
@@ -3915,12 +4031,45 @@ function textHash(text2) {
3915
4031
  async function loadDiskCache() {
3916
4032
  try {
3917
4033
  const raw = await readFile(CACHE_FILE, "utf-8");
4034
+ if (Buffer.byteLength(raw, "utf8") > MAX_CACHE_FILE_BYTES) {
4035
+ console.error("[memorix] FastEmbed cache exceeds the disk load limit; starting with an empty cache");
4036
+ return;
4037
+ }
3918
4038
  const entries = JSON.parse(raw);
3919
- for (const [k, v] of entries) cache.set(k, v);
3920
- console.error(`[memorix] Loaded ${entries.length} cached embeddings from disk`);
4039
+ if (!Array.isArray(entries)) return;
4040
+ for (const entry of entries) {
4041
+ if (!Array.isArray(entry) || typeof entry[0] !== "string" || !isVector(entry[1])) continue;
4042
+ cacheSet(entry[0], entry[1], false);
4043
+ }
4044
+ console.error(`[memorix] Loaded ${cache.size} cached embeddings from disk`);
3921
4045
  } catch {
3922
4046
  }
3923
4047
  }
4048
+ function isVector(value) {
4049
+ return Array.isArray(value) && value.every((entry) => typeof entry === "number");
4050
+ }
4051
+ function maxCachePayloadBytes() {
4052
+ const raw = Number.parseInt(process.env.MEMORIX_EMBEDDING_CACHE_MAX_BYTES ?? "", 10);
4053
+ return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_CACHE_PAYLOAD_BYTES;
4054
+ }
4055
+ function cacheSet(hash4, value, markDirty = true) {
4056
+ const incomingBytes = value.length * 8;
4057
+ if (incomingBytes > maxCachePayloadBytes()) return;
4058
+ const existing = cache.get(hash4);
4059
+ if (existing) cachePayloadBytes -= existing.length * 8;
4060
+ else {
4061
+ while (cache.size >= MAX_CACHE_SIZE || cachePayloadBytes + incomingBytes > maxCachePayloadBytes()) {
4062
+ const firstKey = cache.keys().next().value;
4063
+ if (firstKey === void 0) break;
4064
+ const old = cache.get(firstKey);
4065
+ cache.delete(firstKey);
4066
+ if (old) cachePayloadBytes -= old.length * 8;
4067
+ }
4068
+ }
4069
+ cache.set(hash4, value);
4070
+ cachePayloadBytes += incomingBytes;
4071
+ if (markDirty) diskCacheDirty = true;
4072
+ }
3924
4073
  async function saveDiskCache() {
3925
4074
  if (!diskCacheDirty) return;
3926
4075
  try {
@@ -3931,7 +4080,7 @@ async function saveDiskCache() {
3931
4080
  } catch {
3932
4081
  }
3933
4082
  }
3934
- var CACHE_DIR, CACHE_FILE, cache, MAX_CACHE_SIZE, diskCacheDirty, FastEmbedProvider;
4083
+ var CACHE_DIR, CACHE_FILE, cache, MAX_CACHE_SIZE, DEFAULT_CACHE_PAYLOAD_BYTES, MAX_CACHE_FILE_BYTES, cachePayloadBytes, diskCacheDirty, FastEmbedProvider;
3935
4084
  var init_fastembed_provider = __esm({
3936
4085
  "src/embedding/fastembed-provider.ts"() {
3937
4086
  "use strict";
@@ -3941,6 +4090,9 @@ var init_fastembed_provider = __esm({
3941
4090
  CACHE_FILE = join2(CACHE_DIR, ".embedding-cache.json");
3942
4091
  cache = /* @__PURE__ */ new Map();
3943
4092
  MAX_CACHE_SIZE = 5e3;
4093
+ DEFAULT_CACHE_PAYLOAD_BYTES = 64 * 1024 * 1024;
4094
+ MAX_CACHE_FILE_BYTES = 128 * 1024 * 1024;
4095
+ cachePayloadBytes = 0;
3944
4096
  diskCacheDirty = false;
3945
4097
  FastEmbedProvider = class _FastEmbedProvider {
3946
4098
  name = "fastembed-bge-small";
@@ -3982,7 +4134,7 @@ var init_fastembed_provider = __esm({
3982
4134
  if (result.length !== this.dimensions) {
3983
4135
  throw new Error(`Expected ${this.dimensions}d embedding, got ${result.length}d`);
3984
4136
  }
3985
- this.cacheSet(hash4, result);
4137
+ cacheSet(hash4, result);
3986
4138
  return result;
3987
4139
  }
3988
4140
  async embedBatch(texts) {
@@ -4007,7 +4159,7 @@ var init_fastembed_provider = __esm({
4007
4159
  const originalIdx = uncachedIndices[batchIdx];
4008
4160
  const plain = Array.from(vec);
4009
4161
  results[originalIdx] = plain;
4010
- this.cacheSet(textHash(uncachedTexts[batchIdx]), plain);
4162
+ cacheSet(textHash(uncachedTexts[batchIdx]), plain);
4011
4163
  batchIdx++;
4012
4164
  }
4013
4165
  }
@@ -4015,14 +4167,6 @@ var init_fastembed_provider = __esm({
4015
4167
  }
4016
4168
  return results;
4017
4169
  }
4018
- cacheSet(hash4, value) {
4019
- if (cache.size >= MAX_CACHE_SIZE) {
4020
- const firstKey = cache.keys().next().value;
4021
- if (firstKey !== void 0) cache.delete(firstKey);
4022
- }
4023
- cache.set(hash4, value);
4024
- diskCacheDirty = true;
4025
- }
4026
4170
  };
4027
4171
  }
4028
4172
  });
@@ -4032,7 +4176,15 @@ var transformers_provider_exports = {};
4032
4176
  __export(transformers_provider_exports, {
4033
4177
  TransformersProvider: () => TransformersProvider
4034
4178
  });
4035
- var cache2, MAX_CACHE_SIZE2, TransformersProvider;
4179
+ import { createHash as createHash2 } from "crypto";
4180
+ function cacheKey2(text2) {
4181
+ return createHash2("sha256").update(text2).digest("hex");
4182
+ }
4183
+ function maxCachePayloadBytes2() {
4184
+ const raw = Number.parseInt(process.env.MEMORIX_EMBEDDING_CACHE_MAX_BYTES ?? "", 10);
4185
+ return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_CACHE_PAYLOAD_BYTES2;
4186
+ }
4187
+ var cache2, MAX_CACHE_SIZE2, DEFAULT_CACHE_PAYLOAD_BYTES2, cachePayloadBytes2, TransformersProvider;
4036
4188
  var init_transformers_provider = __esm({
4037
4189
  "src/embedding/transformers-provider.ts"() {
4038
4190
  "use strict";
@@ -4040,6 +4192,8 @@ var init_transformers_provider = __esm({
4040
4192
  init_provider2();
4041
4193
  cache2 = /* @__PURE__ */ new Map();
4042
4194
  MAX_CACHE_SIZE2 = 5e3;
4195
+ DEFAULT_CACHE_PAYLOAD_BYTES2 = 64 * 1024 * 1024;
4196
+ cachePayloadBytes2 = 0;
4043
4197
  TransformersProvider = class _TransformersProvider {
4044
4198
  name = "transformers-minilm";
4045
4199
  dimensions = 384;
@@ -4074,7 +4228,7 @@ var init_transformers_provider = __esm({
4074
4228
  return Promise.all(inputs.map((input) => this.embedInput(input, options)));
4075
4229
  }
4076
4230
  async embed(text2) {
4077
- const cached = cache2.get(text2);
4231
+ const cached = cache2.get(cacheKey2(text2));
4078
4232
  if (cached) return cached;
4079
4233
  const output = await this.extractor(text2, {
4080
4234
  pooling: "mean",
@@ -4084,7 +4238,7 @@ var init_transformers_provider = __esm({
4084
4238
  if (result.length !== this.dimensions) {
4085
4239
  throw new Error(`Expected ${this.dimensions}d embedding, got ${result.length}d`);
4086
4240
  }
4087
- this.cacheSet(text2, result);
4241
+ this.cacheSet(cacheKey2(text2), result);
4088
4242
  return result;
4089
4243
  }
4090
4244
  async embedBatch(texts) {
@@ -4092,7 +4246,7 @@ var init_transformers_provider = __esm({
4092
4246
  const uncachedIndices = [];
4093
4247
  const uncachedTexts = [];
4094
4248
  for (let i2 = 0; i2 < texts.length; i2++) {
4095
- const cached = cache2.get(texts[i2]);
4249
+ const cached = cache2.get(cacheKey2(texts[i2]));
4096
4250
  if (cached) {
4097
4251
  results[i2] = cached;
4098
4252
  } else {
@@ -4110,17 +4264,27 @@ var init_transformers_provider = __esm({
4110
4264
  const vec = Array.from(allVecs[i2]);
4111
4265
  const originalIdx = uncachedIndices[i2];
4112
4266
  results[originalIdx] = vec;
4113
- this.cacheSet(uncachedTexts[i2], vec);
4267
+ this.cacheSet(cacheKey2(uncachedTexts[i2]), vec);
4114
4268
  }
4115
4269
  }
4116
4270
  return results;
4117
4271
  }
4118
4272
  cacheSet(key, value) {
4119
- if (cache2.size >= MAX_CACHE_SIZE2) {
4120
- const firstKey = cache2.keys().next().value;
4121
- if (firstKey !== void 0) cache2.delete(firstKey);
4273
+ const incomingBytes = value.length * 8;
4274
+ if (incomingBytes > maxCachePayloadBytes2()) return;
4275
+ const existing = cache2.get(key);
4276
+ if (existing) cachePayloadBytes2 -= existing.length * 8;
4277
+ else {
4278
+ while (cache2.size >= MAX_CACHE_SIZE2 || cachePayloadBytes2 + incomingBytes > maxCachePayloadBytes2()) {
4279
+ const firstKey = cache2.keys().next().value;
4280
+ if (firstKey === void 0) break;
4281
+ const old = cache2.get(firstKey);
4282
+ cache2.delete(firstKey);
4283
+ if (old) cachePayloadBytes2 -= old.length * 8;
4284
+ }
4122
4285
  }
4123
4286
  cache2.set(key, value);
4287
+ cachePayloadBytes2 += incomingBytes;
4124
4288
  }
4125
4289
  };
4126
4290
  }
@@ -4142,7 +4306,7 @@ __export(api_provider_exports, {
4142
4306
  saveDiskCacheNow: () => saveDiskCacheNow,
4143
4307
  seedApiEmbeddingCacheForTests: () => seedApiEmbeddingCacheForTests
4144
4308
  });
4145
- import { createHash as createHash2 } from "crypto";
4309
+ import { createHash as createHash3 } from "crypto";
4146
4310
  import { createReadStream, createWriteStream, constants as fsConstants } from "fs";
4147
4311
  import { access, readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, rename, stat, unlink } from "fs/promises";
4148
4312
  import { join as join3 } from "path";
@@ -4169,7 +4333,7 @@ function cacheStatFile() {
4169
4333
  function payloadBytes(vector) {
4170
4334
  return vector.length * BYTES_PER_DIM;
4171
4335
  }
4172
- function maxCachePayloadBytes() {
4336
+ function maxCachePayloadBytes3() {
4173
4337
  const raw = process.env.MEMORIX_EMBEDDING_CACHE_MAX_BYTES;
4174
4338
  if (raw) {
4175
4339
  const parsed = Number.parseInt(raw, 10);
@@ -4179,7 +4343,7 @@ function maxCachePayloadBytes() {
4179
4343
  }
4180
4344
  function maxEntriesForDimensions(dimensions) {
4181
4345
  const dim = Math.max(1, Math.floor(dimensions));
4182
- const byBytes = Math.floor(maxCachePayloadBytes() / (dim * BYTES_PER_DIM));
4346
+ const byBytes = Math.floor(maxCachePayloadBytes3() / (dim * BYTES_PER_DIM));
4183
4347
  return Math.max(1, Math.min(MAX_CACHE_ENTRIES, byBytes));
4184
4348
  }
4185
4349
  function rememberDimensions(vector) {
@@ -4192,13 +4356,15 @@ function evictOldest() {
4192
4356
  if (firstKey === void 0) return;
4193
4357
  const old = cache3.get(firstKey);
4194
4358
  cache3.delete(firstKey);
4195
- if (old) cachePayloadBytes -= payloadBytes(old);
4359
+ if (old) cachePayloadBytes3 -= payloadBytes(old);
4196
4360
  }
4197
4361
  function evictToFit(incomingBytes, incomingDims) {
4362
+ if (incomingBytes > maxCachePayloadBytes3()) return false;
4198
4363
  const limit2 = maxEntriesForDimensions(incomingDims);
4199
- while (cache3.size > 0 && (cache3.size >= limit2 || cachePayloadBytes + incomingBytes > maxCachePayloadBytes())) {
4364
+ while (cache3.size > 0 && (cache3.size >= limit2 || cachePayloadBytes3 + incomingBytes > maxCachePayloadBytes3())) {
4200
4365
  evictOldest();
4201
4366
  }
4367
+ return true;
4202
4368
  }
4203
4369
  function isNumberArray(value) {
4204
4370
  return Array.isArray(value) && value.every((entry) => typeof entry === "number");
@@ -4225,12 +4391,12 @@ function cacheInsert(hash4, value, dirty) {
4225
4391
  const incoming = payloadBytes(value);
4226
4392
  const existing = cache3.get(hash4);
4227
4393
  if (existing) {
4228
- cachePayloadBytes -= payloadBytes(existing);
4394
+ cachePayloadBytes3 -= payloadBytes(existing);
4229
4395
  cache3.delete(hash4);
4230
4396
  }
4231
- evictToFit(incoming, value.length || cacheDimensions || DEFAULT_ASSUMED_DIMENSIONS);
4397
+ if (!evictToFit(incoming, value.length || cacheDimensions || DEFAULT_ASSUMED_DIMENSIONS)) return;
4232
4398
  cache3.set(hash4, value);
4233
- cachePayloadBytes += incoming;
4399
+ cachePayloadBytes3 += incoming;
4234
4400
  if (dirty) diskCacheDirty2 = true;
4235
4401
  }
4236
4402
  async function readCacheStat() {
@@ -4266,7 +4432,7 @@ function cacheNamespace(config) {
4266
4432
  ].join("|");
4267
4433
  }
4268
4434
  function textHash2(text2, namespace) {
4269
- return createHash2("sha256").update(`${namespace}\0${text2}`).digest("hex").slice(0, 16);
4435
+ return createHash3("sha256").update(`${namespace}\0${text2}`).digest("hex").slice(0, 16);
4270
4436
  }
4271
4437
  function inputIdentity(input, options = {}) {
4272
4438
  return JSON.stringify({
@@ -4608,7 +4774,7 @@ function getApiEmbeddingDiskCacheLoadCountForTests() {
4608
4774
  }
4609
4775
  function resetApiEmbeddingCacheForTests() {
4610
4776
  cache3.clear();
4611
- cachePayloadBytes = 0;
4777
+ cachePayloadBytes3 = 0;
4612
4778
  cacheDimensions = null;
4613
4779
  diskCacheEntryCount = 0;
4614
4780
  diskCacheLoaded = false;
@@ -4619,14 +4785,14 @@ function resetApiEmbeddingCacheForTests() {
4619
4785
  }
4620
4786
  function seedApiEmbeddingCacheForTests(entries) {
4621
4787
  cache3.clear();
4622
- cachePayloadBytes = 0;
4788
+ cachePayloadBytes3 = 0;
4623
4789
  cacheDimensions = null;
4624
4790
  for (const [key, value] of entries) cacheInsert(key, value, true);
4625
4791
  diskCacheLoaded = true;
4626
4792
  diskCacheDirty2 = true;
4627
4793
  }
4628
4794
  function getApiEmbeddingCachePayloadBytesForTests() {
4629
- return cachePayloadBytes;
4795
+ return cachePayloadBytes3;
4630
4796
  }
4631
4797
  function getApiEmbeddingJsonlLineCountCallsForTests() {
4632
4798
  return jsonlLineCountCalls;
@@ -4800,7 +4966,7 @@ function scheduleDiskSave() {
4800
4966
  diskSaveTimer = null;
4801
4967
  }, DISK_SAVE_DEBOUNCE_MS);
4802
4968
  }
4803
- function cacheSet(hash4, value) {
4969
+ function cacheSet2(hash4, value) {
4804
4970
  cacheInsert(hash4, value, true);
4805
4971
  }
4806
4972
  function resolveEnvEmbeddingApiKey() {
@@ -4920,7 +5086,7 @@ async function waitForRetry(waitMs, signal) {
4920
5086
  abortSignal.addEventListener("abort", onAbort, { once: true });
4921
5087
  });
4922
5088
  }
4923
- 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;
5089
+ var cache3, MAX_CACHE_ENTRIES, MAX_CACHE_PAYLOAD_BYTES, BYTES_PER_DIM, DEFAULT_ASSUMED_DIMENSIONS, MAX_MIGRATION_VALUE_BYTES, cachePayloadBytes3, 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;
4924
5090
  var init_api_provider = __esm({
4925
5091
  "src/embedding/api-provider.ts"() {
4926
5092
  "use strict";
@@ -4932,7 +5098,7 @@ var init_api_provider = __esm({
4932
5098
  BYTES_PER_DIM = 8;
4933
5099
  DEFAULT_ASSUMED_DIMENSIONS = 4096;
4934
5100
  MAX_MIGRATION_VALUE_BYTES = 16 * 1024 * 1024;
4935
- cachePayloadBytes = 0;
5101
+ cachePayloadBytes3 = 0;
4936
5102
  cacheDimensions = null;
4937
5103
  diskCacheEntryCount = 0;
4938
5104
  diskCacheDirty2 = false;
@@ -5117,7 +5283,7 @@ var init_api_provider = __esm({
5117
5283
  } else {
5118
5284
  embedding = await apiCall();
5119
5285
  }
5120
- cacheSet(hash4, embedding);
5286
+ cacheSet2(hash4, embedding);
5121
5287
  scheduleDiskSave();
5122
5288
  return embedding;
5123
5289
  }
@@ -5165,7 +5331,7 @@ var init_api_provider = __esm({
5165
5331
  for (const item of response.data) {
5166
5332
  const originalIdx = chunkIndices[item.index];
5167
5333
  results[originalIdx] = item.embedding;
5168
- cacheSet(textHash2(normalizedTexts[originalIdx], this.cacheKeyNamespace), item.embedding);
5334
+ cacheSet2(textHash2(normalizedTexts[originalIdx], this.cacheKeyNamespace), item.embedding);
5169
5335
  }
5170
5336
  } catch (error) {
5171
5337
  const providerLimit = parseBatchLimit(error);
@@ -5243,7 +5409,7 @@ var init_api_provider = __esm({
5243
5409
  throw new Error(`Expected ${this.dimensions}d, got ${embedding.length}d; dimension mismatch`);
5244
5410
  }
5245
5411
  this.trackUsage(response);
5246
- cacheSet(hash4, embedding);
5412
+ cacheSet2(hash4, embedding);
5247
5413
  scheduleDiskSave();
5248
5414
  return embedding;
5249
5415
  }
@@ -6164,7 +6330,7 @@ var init_timeout = __esm({
6164
6330
  });
6165
6331
 
6166
6332
  // src/search/semantic-index.ts
6167
- import { createHash as createHash3 } from "crypto";
6333
+ import { createHash as createHash4 } from "crypto";
6168
6334
  import { createRequire as createRequire3 } from "module";
6169
6335
  import path8 from "path";
6170
6336
  function createSemanticIndexProfile(provider2) {
@@ -6178,7 +6344,7 @@ function stateKey(dataDir, profile) {
6178
6344
  return `${path8.resolve(dataDir)}::${profile.key}`;
6179
6345
  }
6180
6346
  function tableName(profile) {
6181
- const digest2 = createHash3("sha256").update(profile.key).digest("hex").slice(0, 20);
6347
+ const digest2 = createHash4("sha256").update(profile.key).digest("hex").slice(0, 20);
6182
6348
  return `${TABLE_PREFIX}${digest2}`;
6183
6349
  }
6184
6350
  function indexRoot(dataDir) {
@@ -8218,6 +8384,7 @@ var init_secret_filter = __esm({
8218
8384
  // src/runtime/maintenance-jobs.ts
8219
8385
  var maintenance_jobs_exports = {};
8220
8386
  __export(maintenance_jobs_exports, {
8387
+ DEFAULT_FAILED_HISTORY_RETENTION_MS: () => DEFAULT_FAILED_HISTORY_RETENTION_MS,
8221
8388
  MAINTENANCE_JOB_KINDS: () => MAINTENANCE_JOB_KINDS,
8222
8389
  MaintenanceJobStore: () => MaintenanceJobStore,
8223
8390
  MaintenanceJobWorker: () => MaintenanceJobWorker,
@@ -8267,7 +8434,7 @@ function normalizedKinds(kinds) {
8267
8434
  function getMaintenanceRetryDelayMs(attempts) {
8268
8435
  return Math.min(6e4, 1e3 * 2 ** Math.max(0, attempts - 1));
8269
8436
  }
8270
- var MAINTENANCE_JOB_KINDS, DEFAULT_MAX_ATTEMPTS, DEFAULT_LEASE_MS, DEFAULT_POLL_INTERVAL_MS, MAX_ERROR_LENGTH, DEFAULT_COMPLETED_HISTORY_RETENTION_MS, MaintenanceJobStore, MaintenanceJobWorker;
8437
+ var MAINTENANCE_JOB_KINDS, DEFAULT_MAX_ATTEMPTS, DEFAULT_LEASE_MS, DEFAULT_POLL_INTERVAL_MS, MAX_ERROR_LENGTH, DEFAULT_COMPLETED_HISTORY_RETENTION_MS, DEFAULT_FAILED_HISTORY_RETENTION_MS, MaintenanceJobStore, MaintenanceJobWorker;
8271
8438
  var init_maintenance_jobs = __esm({
8272
8439
  "src/runtime/maintenance-jobs.ts"() {
8273
8440
  "use strict";
@@ -8294,6 +8461,7 @@ var init_maintenance_jobs = __esm({
8294
8461
  DEFAULT_POLL_INTERVAL_MS = 2e3;
8295
8462
  MAX_ERROR_LENGTH = 1e3;
8296
8463
  DEFAULT_COMPLETED_HISTORY_RETENTION_MS = 7 * 24 * 60 * 60 * 1e3;
8464
+ DEFAULT_FAILED_HISTORY_RETENTION_MS = 30 * 24 * 60 * 60 * 1e3;
8297
8465
  MaintenanceJobStore = class {
8298
8466
  db;
8299
8467
  constructor(dataDir) {
@@ -8420,18 +8588,21 @@ var init_maintenance_jobs = __esm({
8420
8588
  }
8421
8589
  /**
8422
8590
  * Completed jobs are useful recent operator history, not permanent data.
8423
- * Failed jobs stay available for diagnosis until an operator explicitly
8424
- * resolves them or clears the database.
8591
+ * Failed diagnostics are retained longer, but are still bounded so a
8592
+ * permanently failing job kind cannot grow the database forever.
8425
8593
  */
8426
8594
  pruneCompletedHistory(options = {}) {
8427
8595
  const now3 = options.now ?? Date.now();
8428
8596
  const maxAgeMs = Number.isFinite(options.maxAgeMs) ? Math.max(0, Math.floor(options.maxAgeMs)) : DEFAULT_COMPLETED_HISTORY_RETENTION_MS;
8597
+ const failedMaxAgeMs = Number.isFinite(options.failedMaxAgeMs) ? Math.max(0, Math.floor(options.failedMaxAgeMs)) : DEFAULT_FAILED_HISTORY_RETENTION_MS;
8429
8598
  const result = this.db.prepare(`
8430
8599
  DELETE FROM maintenance_jobs
8431
- WHERE status = 'completed'
8600
+ WHERE (status = 'completed'
8432
8601
  AND completed_at IS NOT NULL
8433
- AND completed_at < ?
8434
- `).run(now3 - maxAgeMs);
8602
+ AND completed_at < ?)
8603
+ OR (status = 'failed'
8604
+ AND updated_at < ?)
8605
+ `).run(now3 - maxAgeMs, now3 - failedMaxAgeMs);
8435
8606
  return Number(result.changes ?? 0);
8436
8607
  }
8437
8608
  claimNext(options) {
@@ -8757,7 +8928,7 @@ var init_lifecycle = __esm({
8757
8928
  });
8758
8929
 
8759
8930
  // src/store/evidence-store.ts
8760
- import { createHash as createHash4, randomUUID as randomUUID3 } from "crypto";
8931
+ import { createHash as createHash5, randomUUID as randomUUID3 } from "crypto";
8761
8932
  function safeJson(value, fallback) {
8762
8933
  if (typeof value !== "string" || value.length === 0) return fallback;
8763
8934
  try {
@@ -8791,7 +8962,7 @@ function rowToCard(row) {
8791
8962
  };
8792
8963
  }
8793
8964
  function observationHash(observation) {
8794
- return createHash4("sha256").update(JSON.stringify({
8965
+ return createHash5("sha256").update(JSON.stringify({
8795
8966
  projectId: observation.projectId,
8796
8967
  id: observation.id,
8797
8968
  title: observation.title,
@@ -9251,13 +9422,13 @@ __export(workspace_exports, {
9251
9422
  loadKnowledgeWorkspace: () => loadKnowledgeWorkspace,
9252
9423
  resolveKnowledgeWorkspaceFile: () => resolveKnowledgeWorkspaceFile
9253
9424
  });
9254
- import { createHash as createHash5 } from "crypto";
9425
+ import { createHash as createHash6 } from "crypto";
9255
9426
  import { execFile } from "child_process";
9256
9427
  import { promises as fs6 } from "fs";
9257
9428
  import path11 from "path";
9258
9429
  import { promisify } from "util";
9259
9430
  function hash(value) {
9260
- return createHash5("sha256").update(value).digest("hex");
9431
+ return createHash6("sha256").update(value).digest("hex");
9261
9432
  }
9262
9433
  function workspaceId(projectId, mode) {
9263
9434
  return "workspace:" + hash(projectId + ":" + mode).slice(0, 24);
@@ -10392,14 +10563,14 @@ var init_types2 = __esm({
10392
10563
  });
10393
10564
 
10394
10565
  // src/media/asset-store.ts
10395
- import { createHash as createHash6, randomUUID as randomUUID6 } from "crypto";
10566
+ import { createHash as createHash7, randomUUID as randomUUID6 } from "crypto";
10396
10567
  import { copyFile, lstat, mkdir as mkdir3, open, readFile as readFile3, readdir, rename as rename2, rm, stat as stat2, writeFile as writeFile3 } from "fs/promises";
10397
10568
  import path12 from "path";
10398
10569
  function mediaRoot(dataDir) {
10399
10570
  return path12.resolve(dataDir, "media");
10400
10571
  }
10401
10572
  function projectStorageKey(projectId) {
10402
- return createHash6("sha256").update(projectId).digest("hex").slice(0, 16);
10573
+ return createHash7("sha256").update(projectId).digest("hex").slice(0, 16);
10403
10574
  }
10404
10575
  function validateUnderRoot(root, candidate) {
10405
10576
  const resolved = path12.resolve(candidate);
@@ -10508,7 +10679,7 @@ async function importMediaBuffer(input) {
10508
10679
  if (input.bytes.length === 0) throw new Error("Media import rejects empty payloads");
10509
10680
  if (input.bytes.length > maxBytes) throw new Error(`Media payload is too large (${input.bytes.length} bytes; limit ${maxBytes})`);
10510
10681
  const detected = detectMedia(input.bytes.subarray(0, 32));
10511
- const sha256 = createHash6("sha256").update(input.bytes).digest("hex");
10682
+ const sha256 = createHash7("sha256").update(input.bytes).digest("hex");
10512
10683
  return importKnownMedia({
10513
10684
  dataDir: input.dataDir,
10514
10685
  projectId: input.projectId,
@@ -10526,7 +10697,7 @@ async function readMediaAsset(dataDir, asset, maxBytes = DEFAULT_MAX_MEDIA_BYTES
10526
10697
  if (asset.byteSize > maxBytes) throw new Error(`Media asset exceeds read limit (${asset.byteSize} bytes; limit ${maxBytes})`);
10527
10698
  const bytes = await readFile3(getMediaAssetPath(dataDir, asset));
10528
10699
  if (bytes.length !== asset.byteSize) throw new Error(`Media asset size no longer matches metadata: ${asset.id}`);
10529
- const sha256 = createHash6("sha256").update(bytes).digest("hex");
10700
+ const sha256 = createHash7("sha256").update(bytes).digest("hex");
10530
10701
  if (sha256 !== asset.sha256) throw new Error(`Media asset hash no longer matches metadata: ${asset.id}`);
10531
10702
  return bytes;
10532
10703
  }
@@ -69222,16 +69393,16 @@ var require_jwtaccess = __commonJS({
69222
69393
  * @returns A string that returns the cached key.
69223
69394
  */
69224
69395
  getCachedKey(url, scopes) {
69225
- let cacheKey = url;
69396
+ let cacheKey3 = url;
69226
69397
  if (scopes && Array.isArray(scopes) && scopes.length) {
69227
- cacheKey = url ? `${url}_${scopes.join("_")}` : `${scopes.join("_")}`;
69398
+ cacheKey3 = url ? `${url}_${scopes.join("_")}` : `${scopes.join("_")}`;
69228
69399
  } else if (typeof scopes === "string") {
69229
- cacheKey = url ? `${url}_${scopes}` : scopes;
69400
+ cacheKey3 = url ? `${url}_${scopes}` : scopes;
69230
69401
  }
69231
- if (!cacheKey) {
69402
+ if (!cacheKey3) {
69232
69403
  throw Error("Scopes or url must be provided");
69233
69404
  }
69234
- return cacheKey;
69405
+ return cacheKey3;
69235
69406
  }
69236
69407
  /**
69237
69408
  * Get a non-expired access token, after refreshing if necessary.
@@ -75777,7 +75948,7 @@ var require_websocket = __commonJS({
75777
75948
  var http3 = __require("http");
75778
75949
  var net = __require("net");
75779
75950
  var tls = __require("tls");
75780
- var { randomBytes, createHash: createHash16 } = __require("crypto");
75951
+ var { randomBytes, createHash: createHash17 } = __require("crypto");
75781
75952
  var { Duplex, Readable: Readable2 } = __require("stream");
75782
75953
  var { URL: URL2 } = __require("url");
75783
75954
  var PerMessageDeflate2 = require_permessage_deflate();
@@ -76445,7 +76616,7 @@ var require_websocket = __commonJS({
76445
76616
  abortHandshake(websocket, socket, "Invalid Upgrade header");
76446
76617
  return;
76447
76618
  }
76448
- const digest2 = createHash16("sha1").update(key + GUID).digest("base64");
76619
+ const digest2 = createHash17("sha1").update(key + GUID).digest("base64");
76449
76620
  if (res.headers["sec-websocket-accept"] !== digest2) {
76450
76621
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
76451
76622
  return;
@@ -76817,7 +76988,7 @@ var require_websocket_server = __commonJS({
76817
76988
  var EventEmitter = __require("events");
76818
76989
  var http3 = __require("http");
76819
76990
  var { Duplex } = __require("stream");
76820
- var { createHash: createHash16 } = __require("crypto");
76991
+ var { createHash: createHash17 } = __require("crypto");
76821
76992
  var extension3 = require_extension();
76822
76993
  var PerMessageDeflate2 = require_permessage_deflate();
76823
76994
  var subprotocol2 = require_subprotocol();
@@ -77124,7 +77295,7 @@ var require_websocket_server = __commonJS({
77124
77295
  );
77125
77296
  }
77126
77297
  if (this._state > RUNNING) return abortHandshake(socket, 503);
77127
- const digest2 = createHash16("sha1").update(key + GUID).digest("base64");
77298
+ const digest2 = createHash17("sha1").update(key + GUID).digest("base64");
77128
77299
  const headers = [
77129
77300
  "HTTP/1.1 101 Switching Protocols",
77130
77301
  "Upgrade: websocket",
@@ -145703,9 +145874,9 @@ var init_long_term = __esm({
145703
145874
  });
145704
145875
 
145705
145876
  // src/codegraph/ids.ts
145706
- import { createHash as createHash7 } from "crypto";
145877
+ import { createHash as createHash8 } from "crypto";
145707
145878
  function digest(input) {
145708
- return createHash7("sha256").update(input).digest("hex").slice(0, 16);
145879
+ return createHash8("sha256").update(input).digest("hex").slice(0, 16);
145709
145880
  }
145710
145881
  function normalizeCodePath(path23) {
145711
145882
  return path23.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+/g, "/");
@@ -146753,7 +146924,7 @@ var init_store = __esm({
146753
146924
 
146754
146925
  // src/codegraph/code-state.ts
146755
146926
  import { execFile as execFile2 } from "child_process";
146756
- import { createHash as createHash8 } from "crypto";
146927
+ import { createHash as createHash9 } from "crypto";
146757
146928
  import { promisify as promisify3 } from "util";
146758
146929
  async function runGit(rootPath, args) {
146759
146930
  try {
@@ -146782,7 +146953,7 @@ function changedPathCount(status) {
146782
146953
  return count2;
146783
146954
  }
146784
146955
  function fingerprint(baseRevision, status) {
146785
- return createHash8("sha256").update(baseRevision ?? "").update("\0").update(status).digest("hex");
146956
+ return createHash9("sha256").update(baseRevision ?? "").update("\0").update(status).digest("hex");
146786
146957
  }
146787
146958
  async function collectCodeStateSnapshot(input) {
146788
146959
  const [revision, status] = await Promise.all([
@@ -146876,12 +147047,12 @@ var init_exclude3 = __esm({
146876
147047
  });
146877
147048
 
146878
147049
  // src/codegraph/semantic-provider.ts
146879
- import { createHash as createHash9 } from "crypto";
147050
+ import { createHash as createHash10 } from "crypto";
146880
147051
  import "fs";
146881
147052
  import { resolve } from "path";
146882
147053
  import ts from "typescript";
146883
147054
  function hashText(value) {
146884
- return createHash9("sha256").update(value).digest("hex");
147055
+ return createHash10("sha256").update(value).digest("hex");
146885
147056
  }
146886
147057
  function canonicalPath(value) {
146887
147058
  const normalized = resolve(value).replace(/\\/g, "/");
@@ -147226,11 +147397,11 @@ __export(lite_provider_exports, {
147226
147397
  indexProjectLite: () => indexProjectLite,
147227
147398
  refreshProjectLite: () => refreshProjectLite
147228
147399
  });
147229
- import { createHash as createHash10 } from "crypto";
147400
+ import { createHash as createHash11 } from "crypto";
147230
147401
  import { existsSync as existsSync12, readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
147231
147402
  import { join as join4, relative as relative2 } from "path";
147232
147403
  function hashText2(text2) {
147233
- return createHash10("sha256").update(text2).digest("hex");
147404
+ return createHash11("sha256").update(text2).digest("hex");
147234
147405
  }
147235
147406
  function extension2(path23) {
147236
147407
  const index = path23.lastIndexOf(".");
@@ -147863,7 +148034,7 @@ var claim_store_exports = {};
147863
148034
  __export(claim_store_exports, {
147864
148035
  ClaimStore: () => ClaimStore
147865
148036
  });
147866
- import { createHash as createHash11, randomUUID as randomUUID12 } from "crypto";
148037
+ import { createHash as createHash12, randomUUID as randomUUID12 } from "crypto";
147867
148038
  function optionalText3(value) {
147868
148039
  return typeof value === "string" && value ? value : void 0;
147869
148040
  }
@@ -147916,7 +148087,7 @@ function rowToEvent3(row) {
147916
148087
  };
147917
148088
  }
147918
148089
  function evidenceKey(input) {
147919
- return createHash11("sha256").update(JSON.stringify([
148090
+ return createHash12("sha256").update(JSON.stringify([
147920
148091
  input.evidenceKind,
147921
148092
  input.evidenceId,
147922
148093
  input.relation,
@@ -148114,7 +148285,7 @@ __export(claims_exports, {
148114
148285
  supersedeClaim: () => supersedeClaim,
148115
148286
  writeClaim: () => writeClaim
148116
148287
  });
148117
- import { createHash as createHash12, randomUUID as randomUUID13 } from "crypto";
148288
+ import { createHash as createHash13, randomUUID as randomUUID13 } from "crypto";
148118
148289
  function compactText2(value, field) {
148119
148290
  if (typeof value !== "string") throw new Error("Claim " + field + " must be text");
148120
148291
  const sanitized = sanitizeCredentials(value).trim().replace(/\s+/g, " ");
@@ -148126,7 +148297,7 @@ function normalizedTerm(value) {
148126
148297
  return compactText2(value, "identity").toLocaleLowerCase("en-US");
148127
148298
  }
148128
148299
  function hashIdentity(parts) {
148129
- return createHash12("sha256").update(parts.join(String.fromCharCode(31))).digest("hex");
148300
+ return createHash13("sha256").update(parts.join(String.fromCharCode(31))).digest("hex");
148130
148301
  }
148131
148302
  function buildClaimIdentity(input) {
148132
148303
  const subject = normalizedTerm(input.subject);
@@ -148367,7 +148538,7 @@ function supersedeClaim(store, input) {
148367
148538
  });
148368
148539
  }
148369
148540
  function hashObservation(observation) {
148370
- return createHash12("sha256").update(JSON.stringify([
148541
+ return createHash13("sha256").update(JSON.stringify([
148371
148542
  observation.title,
148372
148543
  observation.narrative,
148373
148544
  observation.facts,
@@ -148611,11 +148782,11 @@ var init_frontmatter = __esm({
148611
148782
  });
148612
148783
 
148613
148784
  // src/knowledge/markdown.ts
148614
- import { createHash as createHash13 } from "crypto";
148785
+ import { createHash as createHash14 } from "crypto";
148615
148786
  import { promises as fs10 } from "fs";
148616
148787
  import path19 from "path";
148617
148788
  function hashContent(content) {
148618
- return createHash13("sha256").update(content).digest("hex");
148789
+ return createHash14("sha256").update(content).digest("hex");
148619
148790
  }
148620
148791
  function stringField(data, key) {
148621
148792
  const value = data[key];
@@ -148741,11 +148912,11 @@ __export(wiki_exports, {
148741
148912
  lintKnowledgeWorkspace: () => lintKnowledgeWorkspace,
148742
148913
  readKnowledgePage: () => readKnowledgePage
148743
148914
  });
148744
- import { createHash as createHash14 } from "crypto";
148915
+ import { createHash as createHash15 } from "crypto";
148745
148916
  import { promises as fs11 } from "fs";
148746
148917
  import path20 from "path";
148747
148918
  function hash2(value) {
148748
- return createHash14("sha256").update(value).digest("hex");
148919
+ return createHash15("sha256").update(value).digest("hex");
148749
148920
  }
148750
148921
  function now() {
148751
148922
  return (/* @__PURE__ */ new Date()).toISOString();
@@ -149602,11 +149773,11 @@ __export(workflows_exports, {
149602
149773
  syncCanonicalWorkflows: () => syncCanonicalWorkflows,
149603
149774
  writeCanonicalWorkflow: () => writeCanonicalWorkflow
149604
149775
  });
149605
- import { createHash as createHash15 } from "crypto";
149776
+ import { createHash as createHash16 } from "crypto";
149606
149777
  import { promises as fs12 } from "fs";
149607
149778
  import path21 from "path";
149608
149779
  function hash3(value) {
149609
- return createHash15("sha256").update(value).digest("hex");
149780
+ return createHash16("sha256").update(value).digest("hex");
149610
149781
  }
149611
149782
  function now2() {
149612
149783
  return (/* @__PURE__ */ new Date()).toISOString();