memorix 1.9.5 → 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 (62) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/README.md +6 -1
  3. package/README.zh-CN.md +6 -1
  4. package/dist/cli/index.js +1647 -264
  5. package/dist/index.d.ts +12 -7
  6. package/dist/index.js +952 -182
  7. package/dist/maintenance-runner.js +243 -103
  8. package/dist/media-audio-runner.js +243 -103
  9. package/dist/media-video-runner.js +243 -103
  10. package/dist/memcode-runtime/CHANGELOG.md +42 -0
  11. package/dist/sdk.js +871 -157
  12. package/dist/vector-backfill-runner.js +243 -103
  13. package/docs/API_REFERENCE.md +36 -0
  14. package/docs/CONFIGURATION.md +43 -0
  15. package/docs/DEVELOPMENT.md +1 -1
  16. package/docs/KNOWN_ISSUES_AND_ROADMAP.md +49 -14
  17. package/docs/PERFORMANCE.md +46 -2
  18. package/docs/README.md +2 -1
  19. package/docs/SETUP.md +1 -1
  20. package/package.json +2 -1
  21. package/plugins/antigravity/memorix/plugin.json +1 -1
  22. package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
  23. package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
  24. package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
  25. package/plugins/copilot/memorix/plugin.json +1 -1
  26. package/plugins/gemini/memorix/gemini-extension.json +1 -1
  27. package/plugins/hermes/memorix/plugin.yaml +1 -1
  28. package/plugins/omp/memorix/package.json +1 -1
  29. package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
  30. package/plugins/pi/memorix/package.json +1 -1
  31. package/server.json +2 -2
  32. package/src/cli/capability-map.ts +1 -0
  33. package/src/cli/command-guide.ts +13 -1
  34. package/src/cli/commands/context.ts +2 -0
  35. package/src/cli/commands/continuity.ts +155 -0
  36. package/src/cli/commands/init.ts +5 -2
  37. package/src/cli/commands/serve-http.ts +242 -42
  38. package/src/cli/index.ts +3 -1
  39. package/src/cli/tui/ConfigureView.tsx +2 -0
  40. package/src/codegraph/auto-context.ts +17 -0
  41. package/src/config/legacy-loader.ts +2 -2
  42. package/src/config/resolved-config.ts +8 -5
  43. package/src/config/yaml-loader.ts +20 -10
  44. package/src/embedding/api-provider.ts +4 -2
  45. package/src/embedding/fastembed-provider.ts +47 -14
  46. package/src/embedding/transformers-provider.ts +29 -7
  47. package/src/evaluation/memory-quality-gate.ts +90 -0
  48. package/src/hooks/official-skills.ts +2 -0
  49. package/src/knowledge/context-assembly.ts +1 -0
  50. package/src/knowledge/context-receipt.ts +15 -0
  51. package/src/knowledge/task-continuity.ts +413 -0
  52. package/src/knowledge/workset.ts +77 -0
  53. package/src/llm/provider.ts +2 -1
  54. package/src/orchestrate/coordinator.ts +60 -0
  55. package/src/orchestrate/effect-ledger.ts +160 -0
  56. package/src/orchestrate/pipeline-trace.ts +40 -6
  57. package/src/runtime/maintenance-jobs.ts +12 -6
  58. package/src/server/modern-mcp-bridge.ts +153 -27
  59. package/src/server/tool-profile.ts +3 -2
  60. package/src/server.ts +129 -5
  61. package/src/store/sqlite-db.ts +144 -4
  62. package/src/team/team-store.ts +62 -27
@@ -155,15 +155,20 @@ var init_dotenv_loader = __esm({
155
155
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
156
156
  import { homedir as homedir2 } from "os";
157
157
  import { parse as parseYamlDocument } from "yaml";
158
+ function cacheKey(homeDir, projectRoot) {
159
+ return `${homeDir}\0${projectRoot ?? ""}`;
160
+ }
158
161
  function initProjectRoot(root) {
159
162
  globalProjectRoot = root;
160
- configCache.delete(root);
163
+ configCache.delete(cacheKey(homedir2(), root));
161
164
  }
162
- function loadYamlConfig(projectRoot) {
165
+ function loadYamlConfig(projectRoot, options = {}) {
166
+ const homeDir = options.homeDir ?? homedir2();
163
167
  const resolvedRoot = projectRoot === null ? null : projectRoot ?? globalProjectRoot ?? null;
164
- const cached = configCache.get(resolvedRoot ?? null);
168
+ const key = cacheKey(homeDir, resolvedRoot);
169
+ const cached = configCache.get(key);
165
170
  if (cached) return cached;
166
- const userYaml = getGlobalYamlPath(homedir2());
171
+ const userYaml = getGlobalYamlPath(homeDir);
167
172
  const projectYaml = resolvedRoot ? getProjectYamlPath(resolvedRoot) : null;
168
173
  let userConfig = {};
169
174
  let projectConfig = {};
@@ -195,7 +200,7 @@ function loadYamlConfig(projectRoot) {
195
200
  server: { ...userConfig.server, ...projectConfig.server },
196
201
  team: { ...userConfig.team, ...projectConfig.team }
197
202
  };
198
- configCache.set(resolvedRoot ?? null, merged);
203
+ configCache.set(key, merged);
199
204
  return merged;
200
205
  }
201
206
  function parseYaml(content) {
@@ -542,11 +547,21 @@ function applySchemaMigrations(db2) {
542
547
  apply();
543
548
  }
544
549
  }
550
+ function normalizeDataDir(dataDir) {
551
+ return path3.resolve(dataDir);
552
+ }
553
+ function touchDatabase(normalized, db2) {
554
+ _dbCache.delete(normalized);
555
+ _dbCache.set(normalized, db2);
556
+ }
545
557
  function getDatabase(dataDir) {
546
- const normalized = path3.resolve(dataDir);
558
+ const normalized = normalizeDataDir(dataDir);
547
559
  assertNotHomeDataDir(normalized);
548
560
  const existing = _dbCache.get(normalized);
549
- if (existing) return existing;
561
+ if (existing) {
562
+ touchDatabase(normalized, existing);
563
+ return existing;
564
+ }
550
565
  loadBetterSqlite3();
551
566
  fs.mkdirSync(dataDir, { recursive: true });
552
567
  const dbPath = path3.join(dataDir, "memorix.db");
@@ -576,6 +591,8 @@ function getDatabase(dataDir) {
576
591
  db2.exec(CREATE_MAINTENANCE_JOBS_TABLE);
577
592
  db2.exec(CREATE_MAINTENANCE_TARGETS_TABLE);
578
593
  db2.exec(CREATE_COMPACTION_CHECKPOINTS_TABLE);
594
+ db2.exec(CREATE_TASK_CONTINUITY_EVENTS_TABLE);
595
+ db2.exec(CREATE_AGENT_EFFECTS_TABLE);
579
596
  try {
580
597
  db2.exec(`ALTER TABLE mini_skills ADD COLUMN sourceSnapshot TEXT NOT NULL DEFAULT ''`);
581
598
  } catch {
@@ -614,7 +631,7 @@ function getDatabase(dataDir) {
614
631
  db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('storage_generation', '0')`).run();
615
632
  db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('next_id', '1')`).run();
616
633
  db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('mini_skills_generation', '0')`).run();
617
- _dbCache.set(normalized, db2);
634
+ touchDatabase(normalized, db2);
618
635
  return db2;
619
636
  } catch (error) {
620
637
  try {
@@ -632,8 +649,9 @@ function closeAllDatabases() {
632
649
  }
633
650
  _dbCache.delete(key);
634
651
  }
652
+ _dbLeases.clear();
635
653
  }
636
- 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;
654
+ 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;
637
655
  var init_sqlite_db = __esm({
638
656
  "src/store/sqlite-db.ts"() {
639
657
  "use strict";
@@ -1350,6 +1368,43 @@ CREATE TABLE IF NOT EXISTS memory_feedback_events (
1350
1368
  delta REAL NOT NULL DEFAULT 0,
1351
1369
  observed_at TEXT NOT NULL
1352
1370
  );
1371
+ `;
1372
+ CREATE_TASK_CONTINUITY_EVENTS_TABLE = `
1373
+ CREATE TABLE IF NOT EXISTS task_continuity_events (
1374
+ id TEXT PRIMARY KEY,
1375
+ project_id TEXT NOT NULL,
1376
+ task_id TEXT NOT NULL,
1377
+ task TEXT NOT NULL,
1378
+ kind TEXT NOT NULL,
1379
+ content TEXT NOT NULL,
1380
+ item_status TEXT,
1381
+ source_ref TEXT,
1382
+ evidence_json TEXT NOT NULL DEFAULT '[]',
1383
+ actor TEXT,
1384
+ created_at TEXT NOT NULL,
1385
+ event_key TEXT,
1386
+ item_key TEXT,
1387
+ supersedes_id TEXT
1388
+ );
1389
+ `;
1390
+ CREATE_AGENT_EFFECTS_TABLE = `
1391
+ CREATE TABLE IF NOT EXISTS agent_effects (
1392
+ id TEXT PRIMARY KEY,
1393
+ pipeline_id TEXT NOT NULL,
1394
+ task_id TEXT NOT NULL,
1395
+ attempt INTEGER NOT NULL,
1396
+ effect_key TEXT NOT NULL,
1397
+ tool TEXT NOT NULL,
1398
+ risk_tier TEXT NOT NULL,
1399
+ replay_policy TEXT NOT NULL,
1400
+ status TEXT NOT NULL,
1401
+ call_id TEXT,
1402
+ idempotency_key TEXT NOT NULL,
1403
+ input_fingerprint TEXT,
1404
+ detail TEXT,
1405
+ started_at INTEGER NOT NULL,
1406
+ finished_at INTEGER
1407
+ );
1353
1408
  `;
1354
1409
  CREATE_MCP_BINDINGS_TABLE = `
1355
1410
  CREATE TABLE IF NOT EXISTS mcp_bindings (
@@ -1428,7 +1483,18 @@ CREATE INDEX IF NOT EXISTS idx_evidence_cards_candidate ON evidence_cards(projec
1428
1483
  CREATE INDEX IF NOT EXISTS idx_evidence_card_events_card ON evidence_card_events(card_id, created_at);
1429
1484
  CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC);
1430
1485
  CREATE INDEX IF NOT EXISTS idx_memory_feedback_events_candidate ON memory_feedback_events(project_id, candidate_kind, candidate_id, observed_at DESC);
1486
+ CREATE INDEX IF NOT EXISTS idx_task_continuity_project_task ON task_continuity_events(project_id, task_id, created_at ASC);
1487
+ CREATE INDEX IF NOT EXISTS idx_task_continuity_project_recent ON task_continuity_events(project_id, created_at DESC);
1488
+ CREATE INDEX IF NOT EXISTS idx_task_continuity_item ON task_continuity_events(project_id, task_id, kind, item_key, created_at DESC);
1489
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_task_continuity_event_key
1490
+ ON task_continuity_events(project_id, task_id, event_key)
1491
+ WHERE event_key IS NOT NULL;
1492
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_agent_effect_identity
1493
+ ON agent_effects(pipeline_id, task_id, attempt, effect_key);
1494
+ CREATE INDEX IF NOT EXISTS idx_agent_effect_pipeline ON agent_effects(pipeline_id, started_at ASC);
1431
1495
  CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC);
1496
+ CREATE INDEX IF NOT EXISTS idx_mcp_bindings_root ON mcp_bindings(project_root, last_used_at DESC);
1497
+ CREATE INDEX IF NOT EXISTS idx_mcp_bindings_expiry ON mcp_bindings(expires_at);
1432
1498
  CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
1433
1499
  ON maintenance_jobs(project_id, kind, dedupe_key)
1434
1500
  WHERE status IN ('pending', 'running', 'retry');
@@ -1599,6 +1665,8 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
1599
1665
  db2.exec("CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC)");
1600
1666
  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)");
1601
1667
  db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC)");
1668
+ db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_root ON mcp_bindings(project_root, last_used_at DESC)");
1669
+ db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_expiry ON mcp_bindings(expires_at)");
1602
1670
  }
1603
1671
  },
1604
1672
  {
@@ -1609,9 +1677,22 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
1609
1677
  addColumnIfMissing(db2, "code_symbols", "source", "source TEXT");
1610
1678
  addColumnIfMissing(db2, "code_edges", "source", "source TEXT");
1611
1679
  }
1680
+ },
1681
+ {
1682
+ id: "1.9-continuity-v2",
1683
+ apply: (db2) => {
1684
+ addColumnIfMissing(db2, "task_continuity_events", "event_key", "event_key TEXT");
1685
+ addColumnIfMissing(db2, "task_continuity_events", "item_key", "item_key TEXT");
1686
+ addColumnIfMissing(db2, "task_continuity_events", "supersedes_id", "supersedes_id TEXT");
1687
+ 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)");
1688
+ db2.exec(`CREATE UNIQUE INDEX IF NOT EXISTS idx_task_continuity_event_key
1689
+ ON task_continuity_events(project_id, task_id, event_key)
1690
+ WHERE event_key IS NOT NULL`);
1691
+ }
1612
1692
  }
1613
1693
  ];
1614
1694
  _dbCache = /* @__PURE__ */ new Map();
1695
+ _dbLeases = /* @__PURE__ */ new Map();
1615
1696
  }
1616
1697
  });
1617
1698
 
@@ -2127,6 +2208,7 @@ var init_media_store = __esm({
2127
2208
  // src/runtime/maintenance-jobs.ts
2128
2209
  var maintenance_jobs_exports = {};
2129
2210
  __export(maintenance_jobs_exports, {
2211
+ DEFAULT_FAILED_HISTORY_RETENTION_MS: () => DEFAULT_FAILED_HISTORY_RETENTION_MS,
2130
2212
  MAINTENANCE_JOB_KINDS: () => MAINTENANCE_JOB_KINDS,
2131
2213
  MaintenanceJobStore: () => MaintenanceJobStore,
2132
2214
  MaintenanceJobWorker: () => MaintenanceJobWorker,
@@ -2176,7 +2258,7 @@ function normalizedKinds(kinds) {
2176
2258
  function getMaintenanceRetryDelayMs(attempts) {
2177
2259
  return Math.min(6e4, 1e3 * 2 ** Math.max(0, attempts - 1));
2178
2260
  }
2179
- var MAINTENANCE_JOB_KINDS, DEFAULT_MAX_ATTEMPTS, DEFAULT_LEASE_MS, DEFAULT_POLL_INTERVAL_MS, MAX_ERROR_LENGTH, DEFAULT_COMPLETED_HISTORY_RETENTION_MS, MaintenanceJobStore, MaintenanceJobWorker;
2261
+ 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;
2180
2262
  var init_maintenance_jobs = __esm({
2181
2263
  "src/runtime/maintenance-jobs.ts"() {
2182
2264
  "use strict";
@@ -2203,6 +2285,7 @@ var init_maintenance_jobs = __esm({
2203
2285
  DEFAULT_POLL_INTERVAL_MS = 2e3;
2204
2286
  MAX_ERROR_LENGTH = 1e3;
2205
2287
  DEFAULT_COMPLETED_HISTORY_RETENTION_MS = 7 * 24 * 60 * 60 * 1e3;
2288
+ DEFAULT_FAILED_HISTORY_RETENTION_MS = 30 * 24 * 60 * 60 * 1e3;
2206
2289
  MaintenanceJobStore = class {
2207
2290
  db;
2208
2291
  constructor(dataDir) {
@@ -2329,18 +2412,21 @@ var init_maintenance_jobs = __esm({
2329
2412
  }
2330
2413
  /**
2331
2414
  * Completed jobs are useful recent operator history, not permanent data.
2332
- * Failed jobs stay available for diagnosis until an operator explicitly
2333
- * resolves them or clears the database.
2415
+ * Failed diagnostics are retained longer, but are still bounded so a
2416
+ * permanently failing job kind cannot grow the database forever.
2334
2417
  */
2335
2418
  pruneCompletedHistory(options = {}) {
2336
2419
  const now3 = options.now ?? Date.now();
2337
2420
  const maxAgeMs = Number.isFinite(options.maxAgeMs) ? Math.max(0, Math.floor(options.maxAgeMs)) : DEFAULT_COMPLETED_HISTORY_RETENTION_MS;
2421
+ const failedMaxAgeMs = Number.isFinite(options.failedMaxAgeMs) ? Math.max(0, Math.floor(options.failedMaxAgeMs)) : DEFAULT_FAILED_HISTORY_RETENTION_MS;
2338
2422
  const result = this.db.prepare(`
2339
2423
  DELETE FROM maintenance_jobs
2340
- WHERE status = 'completed'
2424
+ WHERE (status = 'completed'
2341
2425
  AND completed_at IS NOT NULL
2342
- AND completed_at < ?
2343
- `).run(now3 - maxAgeMs);
2426
+ AND completed_at < ?)
2427
+ OR (status = 'failed'
2428
+ AND updated_at < ?)
2429
+ `).run(now3 - maxAgeMs, now3 - failedMaxAgeMs);
2344
2430
  return Number(result.changes ?? 0);
2345
2431
  }
2346
2432
  claimNext(options) {
@@ -3114,9 +3200,9 @@ var init_detector = __esm({
3114
3200
  // src/config/legacy-loader.ts
3115
3201
  import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
3116
3202
  import { homedir as homedir3 } from "os";
3117
- function loadFileConfig() {
3203
+ function loadFileConfig(homeDir = homedir3()) {
3118
3204
  if (cachedConfig !== null) return cachedConfig;
3119
- const configPath = getLegacyConfigJsonPath(homedir3());
3205
+ const configPath = getLegacyConfigJsonPath(homeDir);
3120
3206
  try {
3121
3207
  if (existsSync5(configPath)) {
3122
3208
  cachedConfig = JSON.parse(readFileSync5(configPath, "utf-8"));
@@ -3146,15 +3232,15 @@ import { homedir as homedir4 } from "os";
3146
3232
  function loadTomlConfig(options = {}) {
3147
3233
  const homeDir = options.homeDir ?? homedir4();
3148
3234
  const projectRoot = options.projectRoot ?? null;
3149
- const cacheKey = `${homeDir}\0${projectRoot ?? ""}`;
3150
- const cached = configCache2.get(cacheKey);
3235
+ const cacheKey3 = `${homeDir}\0${projectRoot ?? ""}`;
3236
+ const cached = configCache2.get(cacheKey3);
3151
3237
  if (cached) return cached;
3152
3238
  const userToml = getGlobalConfigTomlPath(homeDir);
3153
3239
  const projectToml = projectRoot ? getProjectConfigTomlPath(projectRoot) : null;
3154
3240
  const userConfig = existsSync6(userToml) ? parseTomlConfig(readFileSync6(userToml, "utf8"), userToml) : {};
3155
3241
  const projectConfig = projectToml && existsSync6(projectToml) ? parseTomlConfig(readFileSync6(projectToml, "utf8"), projectToml) : {};
3156
3242
  const merged = mergeTomlConfig(userConfig, projectConfig);
3157
- configCache2.set(cacheKey, merged);
3243
+ configCache2.set(cacheKey3, merged);
3158
3244
  return merged;
3159
3245
  }
3160
3246
  function mergeTomlConfig(base, override) {
@@ -3275,8 +3361,8 @@ function getResolvedConfig(options = {}) {
3275
3361
  const projectRoot = options.projectRoot === void 0 ? detectProject()?.rootPath ?? null : options.projectRoot;
3276
3362
  loadDotenv(projectRoot === null ? void 0 : projectRoot ?? void 0, { userHomeDir: homeDir });
3277
3363
  const toml = loadTomlConfig({ projectRoot: projectRoot ?? null, homeDir });
3278
- const yaml = loadYamlConfig(projectRoot ?? null);
3279
- const legacy = loadFileConfig();
3364
+ const yaml = loadYamlConfig(projectRoot ?? null, { homeDir });
3365
+ const legacy = loadFileConfig(homeDir);
3280
3366
  const embeddingBaseUrl = first(process.env.MEMORIX_EMBEDDING_BASE_URL, toml.embedding?.base_url, yaml.embedding?.baseUrl, legacy.embeddingApi?.baseUrl);
3281
3367
  const openRouterEmbeddingApiKey = isOpenRouterUrl(embeddingBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
3282
3368
  const memoryLlmProvider = first(
@@ -3298,15 +3384,17 @@ function getResolvedConfig(options = {}) {
3298
3384
  legacy.llm?.baseUrl
3299
3385
  );
3300
3386
  const openRouterMemoryLlmApiKey = isOpenRouterMemoryLane(memoryLlmProvider, memoryLlmBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
3387
+ const isAtlasCloud = memoryLlmProvider === "atlascloud";
3301
3388
  const memoryLlmApiKey = first(
3302
3389
  process.env.MEMORIX_LLM_API_KEY,
3303
3390
  process.env.MEMORIX_API_KEY,
3304
3391
  toml.memory?.llm?.api_key,
3305
3392
  yaml.llm?.apiKey,
3306
3393
  legacy.llm?.apiKey,
3307
- process.env.OPENAI_API_KEY,
3308
- process.env.ANTHROPIC_API_KEY,
3309
- openRouterMemoryLlmApiKey
3394
+ // Never borrow another provider's credentials for the Atlas Cloud preset.
3395
+ isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : process.env.OPENAI_API_KEY,
3396
+ isAtlasCloud ? void 0 : process.env.ANTHROPIC_API_KEY,
3397
+ isAtlasCloud ? void 0 : openRouterMemoryLlmApiKey
3310
3398
  );
3311
3399
  const resolved = {
3312
3400
  agent: {
@@ -3485,7 +3573,8 @@ function getEnvSourceNames() {
3485
3573
  "MEMORIX_CODEGRAPH_EXTERNAL_CONTEXT",
3486
3574
  "MEMORIX_CODEGRAPH_EXTERNAL_COMMAND",
3487
3575
  "MEMORIX_CODEGRAPH_EXTERNAL_TIMEOUT_MS",
3488
- "OPENROUTER_API_KEY"
3576
+ "OPENROUTER_API_KEY",
3577
+ "ATLASCLOUD_API_KEY"
3489
3578
  ].filter((name) => process.env[name]);
3490
3579
  }
3491
3580
  function isOpenRouterUrl(value) {
@@ -3704,12 +3793,45 @@ function textHash(text2) {
3704
3793
  async function loadDiskCache() {
3705
3794
  try {
3706
3795
  const raw = await readFile(CACHE_FILE, "utf-8");
3796
+ if (Buffer.byteLength(raw, "utf8") > MAX_CACHE_FILE_BYTES) {
3797
+ console.error("[memorix] FastEmbed cache exceeds the disk load limit; starting with an empty cache");
3798
+ return;
3799
+ }
3707
3800
  const entries = JSON.parse(raw);
3708
- for (const [k, v] of entries) cache.set(k, v);
3709
- console.error(`[memorix] Loaded ${entries.length} cached embeddings from disk`);
3801
+ if (!Array.isArray(entries)) return;
3802
+ for (const entry of entries) {
3803
+ if (!Array.isArray(entry) || typeof entry[0] !== "string" || !isVector(entry[1])) continue;
3804
+ cacheSet(entry[0], entry[1], false);
3805
+ }
3806
+ console.error(`[memorix] Loaded ${cache.size} cached embeddings from disk`);
3710
3807
  } catch {
3711
3808
  }
3712
3809
  }
3810
+ function isVector(value) {
3811
+ return Array.isArray(value) && value.every((entry) => typeof entry === "number");
3812
+ }
3813
+ function maxCachePayloadBytes() {
3814
+ const raw = Number.parseInt(process.env.MEMORIX_EMBEDDING_CACHE_MAX_BYTES ?? "", 10);
3815
+ return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_CACHE_PAYLOAD_BYTES;
3816
+ }
3817
+ function cacheSet(hash4, value, markDirty = true) {
3818
+ const incomingBytes = value.length * 8;
3819
+ if (incomingBytes > maxCachePayloadBytes()) return;
3820
+ const existing = cache.get(hash4);
3821
+ if (existing) cachePayloadBytes -= existing.length * 8;
3822
+ else {
3823
+ while (cache.size >= MAX_CACHE_SIZE || cachePayloadBytes + incomingBytes > maxCachePayloadBytes()) {
3824
+ const firstKey = cache.keys().next().value;
3825
+ if (firstKey === void 0) break;
3826
+ const old = cache.get(firstKey);
3827
+ cache.delete(firstKey);
3828
+ if (old) cachePayloadBytes -= old.length * 8;
3829
+ }
3830
+ }
3831
+ cache.set(hash4, value);
3832
+ cachePayloadBytes += incomingBytes;
3833
+ if (markDirty) diskCacheDirty = true;
3834
+ }
3713
3835
  async function saveDiskCache() {
3714
3836
  if (!diskCacheDirty) return;
3715
3837
  try {
@@ -3720,7 +3842,7 @@ async function saveDiskCache() {
3720
3842
  } catch {
3721
3843
  }
3722
3844
  }
3723
- var CACHE_DIR, CACHE_FILE, cache, MAX_CACHE_SIZE, diskCacheDirty, FastEmbedProvider;
3845
+ var CACHE_DIR, CACHE_FILE, cache, MAX_CACHE_SIZE, DEFAULT_CACHE_PAYLOAD_BYTES, MAX_CACHE_FILE_BYTES, cachePayloadBytes, diskCacheDirty, FastEmbedProvider;
3724
3846
  var init_fastembed_provider = __esm({
3725
3847
  "src/embedding/fastembed-provider.ts"() {
3726
3848
  "use strict";
@@ -3730,6 +3852,9 @@ var init_fastembed_provider = __esm({
3730
3852
  CACHE_FILE = join2(CACHE_DIR, ".embedding-cache.json");
3731
3853
  cache = /* @__PURE__ */ new Map();
3732
3854
  MAX_CACHE_SIZE = 5e3;
3855
+ DEFAULT_CACHE_PAYLOAD_BYTES = 64 * 1024 * 1024;
3856
+ MAX_CACHE_FILE_BYTES = 128 * 1024 * 1024;
3857
+ cachePayloadBytes = 0;
3733
3858
  diskCacheDirty = false;
3734
3859
  FastEmbedProvider = class _FastEmbedProvider {
3735
3860
  name = "fastembed-bge-small";
@@ -3771,7 +3896,7 @@ var init_fastembed_provider = __esm({
3771
3896
  if (result.length !== this.dimensions) {
3772
3897
  throw new Error(`Expected ${this.dimensions}d embedding, got ${result.length}d`);
3773
3898
  }
3774
- this.cacheSet(hash4, result);
3899
+ cacheSet(hash4, result);
3775
3900
  return result;
3776
3901
  }
3777
3902
  async embedBatch(texts) {
@@ -3796,7 +3921,7 @@ var init_fastembed_provider = __esm({
3796
3921
  const originalIdx = uncachedIndices[batchIdx];
3797
3922
  const plain = Array.from(vec);
3798
3923
  results[originalIdx] = plain;
3799
- this.cacheSet(textHash(uncachedTexts[batchIdx]), plain);
3924
+ cacheSet(textHash(uncachedTexts[batchIdx]), plain);
3800
3925
  batchIdx++;
3801
3926
  }
3802
3927
  }
@@ -3804,14 +3929,6 @@ var init_fastembed_provider = __esm({
3804
3929
  }
3805
3930
  return results;
3806
3931
  }
3807
- cacheSet(hash4, value) {
3808
- if (cache.size >= MAX_CACHE_SIZE) {
3809
- const firstKey = cache.keys().next().value;
3810
- if (firstKey !== void 0) cache.delete(firstKey);
3811
- }
3812
- cache.set(hash4, value);
3813
- diskCacheDirty = true;
3814
- }
3815
3932
  };
3816
3933
  }
3817
3934
  });
@@ -3821,7 +3938,15 @@ var transformers_provider_exports = {};
3821
3938
  __export(transformers_provider_exports, {
3822
3939
  TransformersProvider: () => TransformersProvider
3823
3940
  });
3824
- var cache2, MAX_CACHE_SIZE2, TransformersProvider;
3941
+ import { createHash as createHash2 } from "crypto";
3942
+ function cacheKey2(text2) {
3943
+ return createHash2("sha256").update(text2).digest("hex");
3944
+ }
3945
+ function maxCachePayloadBytes2() {
3946
+ const raw = Number.parseInt(process.env.MEMORIX_EMBEDDING_CACHE_MAX_BYTES ?? "", 10);
3947
+ return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_CACHE_PAYLOAD_BYTES2;
3948
+ }
3949
+ var cache2, MAX_CACHE_SIZE2, DEFAULT_CACHE_PAYLOAD_BYTES2, cachePayloadBytes2, TransformersProvider;
3825
3950
  var init_transformers_provider = __esm({
3826
3951
  "src/embedding/transformers-provider.ts"() {
3827
3952
  "use strict";
@@ -3829,6 +3954,8 @@ var init_transformers_provider = __esm({
3829
3954
  init_provider();
3830
3955
  cache2 = /* @__PURE__ */ new Map();
3831
3956
  MAX_CACHE_SIZE2 = 5e3;
3957
+ DEFAULT_CACHE_PAYLOAD_BYTES2 = 64 * 1024 * 1024;
3958
+ cachePayloadBytes2 = 0;
3832
3959
  TransformersProvider = class _TransformersProvider {
3833
3960
  name = "transformers-minilm";
3834
3961
  dimensions = 384;
@@ -3863,7 +3990,7 @@ var init_transformers_provider = __esm({
3863
3990
  return Promise.all(inputs.map((input) => this.embedInput(input, options)));
3864
3991
  }
3865
3992
  async embed(text2) {
3866
- const cached = cache2.get(text2);
3993
+ const cached = cache2.get(cacheKey2(text2));
3867
3994
  if (cached) return cached;
3868
3995
  const output = await this.extractor(text2, {
3869
3996
  pooling: "mean",
@@ -3873,7 +4000,7 @@ var init_transformers_provider = __esm({
3873
4000
  if (result.length !== this.dimensions) {
3874
4001
  throw new Error(`Expected ${this.dimensions}d embedding, got ${result.length}d`);
3875
4002
  }
3876
- this.cacheSet(text2, result);
4003
+ this.cacheSet(cacheKey2(text2), result);
3877
4004
  return result;
3878
4005
  }
3879
4006
  async embedBatch(texts) {
@@ -3881,7 +4008,7 @@ var init_transformers_provider = __esm({
3881
4008
  const uncachedIndices = [];
3882
4009
  const uncachedTexts = [];
3883
4010
  for (let i2 = 0; i2 < texts.length; i2++) {
3884
- const cached = cache2.get(texts[i2]);
4011
+ const cached = cache2.get(cacheKey2(texts[i2]));
3885
4012
  if (cached) {
3886
4013
  results[i2] = cached;
3887
4014
  } else {
@@ -3899,17 +4026,27 @@ var init_transformers_provider = __esm({
3899
4026
  const vec = Array.from(allVecs[i2]);
3900
4027
  const originalIdx = uncachedIndices[i2];
3901
4028
  results[originalIdx] = vec;
3902
- this.cacheSet(uncachedTexts[i2], vec);
4029
+ this.cacheSet(cacheKey2(uncachedTexts[i2]), vec);
3903
4030
  }
3904
4031
  }
3905
4032
  return results;
3906
4033
  }
3907
4034
  cacheSet(key, value) {
3908
- if (cache2.size >= MAX_CACHE_SIZE2) {
3909
- const firstKey = cache2.keys().next().value;
3910
- if (firstKey !== void 0) cache2.delete(firstKey);
4035
+ const incomingBytes = value.length * 8;
4036
+ if (incomingBytes > maxCachePayloadBytes2()) return;
4037
+ const existing = cache2.get(key);
4038
+ if (existing) cachePayloadBytes2 -= existing.length * 8;
4039
+ else {
4040
+ while (cache2.size >= MAX_CACHE_SIZE2 || cachePayloadBytes2 + incomingBytes > maxCachePayloadBytes2()) {
4041
+ const firstKey = cache2.keys().next().value;
4042
+ if (firstKey === void 0) break;
4043
+ const old = cache2.get(firstKey);
4044
+ cache2.delete(firstKey);
4045
+ if (old) cachePayloadBytes2 -= old.length * 8;
4046
+ }
3911
4047
  }
3912
4048
  cache2.set(key, value);
4049
+ cachePayloadBytes2 += incomingBytes;
3913
4050
  }
3914
4051
  };
3915
4052
  }
@@ -3931,7 +4068,7 @@ __export(api_provider_exports, {
3931
4068
  saveDiskCacheNow: () => saveDiskCacheNow,
3932
4069
  seedApiEmbeddingCacheForTests: () => seedApiEmbeddingCacheForTests
3933
4070
  });
3934
- import { createHash as createHash2 } from "crypto";
4071
+ import { createHash as createHash3 } from "crypto";
3935
4072
  import { createReadStream, createWriteStream, constants as fsConstants } from "fs";
3936
4073
  import { access, readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, rename, stat, unlink } from "fs/promises";
3937
4074
  import { join as join3 } from "path";
@@ -3958,7 +4095,7 @@ function cacheStatFile() {
3958
4095
  function payloadBytes(vector) {
3959
4096
  return vector.length * BYTES_PER_DIM;
3960
4097
  }
3961
- function maxCachePayloadBytes() {
4098
+ function maxCachePayloadBytes3() {
3962
4099
  const raw = process.env.MEMORIX_EMBEDDING_CACHE_MAX_BYTES;
3963
4100
  if (raw) {
3964
4101
  const parsed = Number.parseInt(raw, 10);
@@ -3968,7 +4105,7 @@ function maxCachePayloadBytes() {
3968
4105
  }
3969
4106
  function maxEntriesForDimensions(dimensions) {
3970
4107
  const dim = Math.max(1, Math.floor(dimensions));
3971
- const byBytes = Math.floor(maxCachePayloadBytes() / (dim * BYTES_PER_DIM));
4108
+ const byBytes = Math.floor(maxCachePayloadBytes3() / (dim * BYTES_PER_DIM));
3972
4109
  return Math.max(1, Math.min(MAX_CACHE_ENTRIES, byBytes));
3973
4110
  }
3974
4111
  function rememberDimensions(vector) {
@@ -3981,13 +4118,15 @@ function evictOldest() {
3981
4118
  if (firstKey === void 0) return;
3982
4119
  const old = cache3.get(firstKey);
3983
4120
  cache3.delete(firstKey);
3984
- if (old) cachePayloadBytes -= payloadBytes(old);
4121
+ if (old) cachePayloadBytes3 -= payloadBytes(old);
3985
4122
  }
3986
4123
  function evictToFit(incomingBytes, incomingDims) {
4124
+ if (incomingBytes > maxCachePayloadBytes3()) return false;
3987
4125
  const limit2 = maxEntriesForDimensions(incomingDims);
3988
- while (cache3.size > 0 && (cache3.size >= limit2 || cachePayloadBytes + incomingBytes > maxCachePayloadBytes())) {
4126
+ while (cache3.size > 0 && (cache3.size >= limit2 || cachePayloadBytes3 + incomingBytes > maxCachePayloadBytes3())) {
3989
4127
  evictOldest();
3990
4128
  }
4129
+ return true;
3991
4130
  }
3992
4131
  function isNumberArray(value) {
3993
4132
  return Array.isArray(value) && value.every((entry) => typeof entry === "number");
@@ -4014,12 +4153,12 @@ function cacheInsert(hash4, value, dirty) {
4014
4153
  const incoming = payloadBytes(value);
4015
4154
  const existing = cache3.get(hash4);
4016
4155
  if (existing) {
4017
- cachePayloadBytes -= payloadBytes(existing);
4156
+ cachePayloadBytes3 -= payloadBytes(existing);
4018
4157
  cache3.delete(hash4);
4019
4158
  }
4020
- evictToFit(incoming, value.length || cacheDimensions || DEFAULT_ASSUMED_DIMENSIONS);
4159
+ if (!evictToFit(incoming, value.length || cacheDimensions || DEFAULT_ASSUMED_DIMENSIONS)) return;
4021
4160
  cache3.set(hash4, value);
4022
- cachePayloadBytes += incoming;
4161
+ cachePayloadBytes3 += incoming;
4023
4162
  if (dirty) diskCacheDirty2 = true;
4024
4163
  }
4025
4164
  async function readCacheStat() {
@@ -4055,7 +4194,7 @@ function cacheNamespace(config) {
4055
4194
  ].join("|");
4056
4195
  }
4057
4196
  function textHash2(text2, namespace) {
4058
- return createHash2("sha256").update(`${namespace}\0${text2}`).digest("hex").slice(0, 16);
4197
+ return createHash3("sha256").update(`${namespace}\0${text2}`).digest("hex").slice(0, 16);
4059
4198
  }
4060
4199
  function inputIdentity(input, options = {}) {
4061
4200
  return JSON.stringify({
@@ -4397,7 +4536,7 @@ function getApiEmbeddingDiskCacheLoadCountForTests() {
4397
4536
  }
4398
4537
  function resetApiEmbeddingCacheForTests() {
4399
4538
  cache3.clear();
4400
- cachePayloadBytes = 0;
4539
+ cachePayloadBytes3 = 0;
4401
4540
  cacheDimensions = null;
4402
4541
  diskCacheEntryCount = 0;
4403
4542
  diskCacheLoaded = false;
@@ -4408,14 +4547,14 @@ function resetApiEmbeddingCacheForTests() {
4408
4547
  }
4409
4548
  function seedApiEmbeddingCacheForTests(entries) {
4410
4549
  cache3.clear();
4411
- cachePayloadBytes = 0;
4550
+ cachePayloadBytes3 = 0;
4412
4551
  cacheDimensions = null;
4413
4552
  for (const [key, value] of entries) cacheInsert(key, value, true);
4414
4553
  diskCacheLoaded = true;
4415
4554
  diskCacheDirty2 = true;
4416
4555
  }
4417
4556
  function getApiEmbeddingCachePayloadBytesForTests() {
4418
- return cachePayloadBytes;
4557
+ return cachePayloadBytes3;
4419
4558
  }
4420
4559
  function getApiEmbeddingJsonlLineCountCallsForTests() {
4421
4560
  return jsonlLineCountCalls;
@@ -4589,7 +4728,7 @@ function scheduleDiskSave() {
4589
4728
  diskSaveTimer = null;
4590
4729
  }, DISK_SAVE_DEBOUNCE_MS);
4591
4730
  }
4592
- function cacheSet(hash4, value) {
4731
+ function cacheSet2(hash4, value) {
4593
4732
  cacheInsert(hash4, value, true);
4594
4733
  }
4595
4734
  function resolveEnvEmbeddingApiKey() {
@@ -4709,7 +4848,7 @@ async function waitForRetry(waitMs, signal) {
4709
4848
  abortSignal.addEventListener("abort", onAbort, { once: true });
4710
4849
  });
4711
4850
  }
4712
- 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;
4851
+ 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;
4713
4852
  var init_api_provider = __esm({
4714
4853
  "src/embedding/api-provider.ts"() {
4715
4854
  "use strict";
@@ -4721,7 +4860,7 @@ var init_api_provider = __esm({
4721
4860
  BYTES_PER_DIM = 8;
4722
4861
  DEFAULT_ASSUMED_DIMENSIONS = 4096;
4723
4862
  MAX_MIGRATION_VALUE_BYTES = 16 * 1024 * 1024;
4724
- cachePayloadBytes = 0;
4863
+ cachePayloadBytes3 = 0;
4725
4864
  cacheDimensions = null;
4726
4865
  diskCacheEntryCount = 0;
4727
4866
  diskCacheDirty2 = false;
@@ -4906,7 +5045,7 @@ var init_api_provider = __esm({
4906
5045
  } else {
4907
5046
  embedding = await apiCall();
4908
5047
  }
4909
- cacheSet(hash4, embedding);
5048
+ cacheSet2(hash4, embedding);
4910
5049
  scheduleDiskSave();
4911
5050
  return embedding;
4912
5051
  }
@@ -4954,7 +5093,7 @@ var init_api_provider = __esm({
4954
5093
  for (const item of response.data) {
4955
5094
  const originalIdx = chunkIndices[item.index];
4956
5095
  results[originalIdx] = item.embedding;
4957
- cacheSet(textHash2(normalizedTexts[originalIdx], this.cacheKeyNamespace), item.embedding);
5096
+ cacheSet2(textHash2(normalizedTexts[originalIdx], this.cacheKeyNamespace), item.embedding);
4958
5097
  }
4959
5098
  } catch (error) {
4960
5099
  const providerLimit = parseBatchLimit(error);
@@ -5032,7 +5171,7 @@ var init_api_provider = __esm({
5032
5171
  throw new Error(`Expected ${this.dimensions}d, got ${embedding.length}d; dimension mismatch`);
5033
5172
  }
5034
5173
  this.trackUsage(response);
5035
- cacheSet(hash4, embedding);
5174
+ cacheSet2(hash4, embedding);
5036
5175
  scheduleDiskSave();
5037
5176
  return embedding;
5038
5177
  }
@@ -6415,6 +6554,7 @@ var init_provider2 = __esm({
6415
6554
  openai: { baseUrl: "https://api.openai.com/v1", model: "gpt-4.1-nano" },
6416
6555
  anthropic: { baseUrl: "https://api.anthropic.com/v1", model: "claude-3-5-haiku-latest" },
6417
6556
  openrouter: { baseUrl: "https://openrouter.ai/api/v1", model: "openai/gpt-4.1-nano" },
6557
+ atlascloud: { baseUrl: "https://api.atlascloud.ai/v1", model: "deepseek-ai/deepseek-v3.2" },
6418
6558
  custom: { baseUrl: "http://localhost:11434/v1", model: "llama3" }
6419
6559
  };
6420
6560
  currentConfig = null;
@@ -7178,7 +7318,7 @@ var init_obs_store = __esm({
7178
7318
  });
7179
7319
 
7180
7320
  // src/search/semantic-index.ts
7181
- import { createHash as createHash3 } from "crypto";
7321
+ import { createHash as createHash4 } from "crypto";
7182
7322
  import { createRequire as createRequire3 } from "module";
7183
7323
  import path8 from "path";
7184
7324
  function createSemanticIndexProfile(provider2) {
@@ -7192,7 +7332,7 @@ function stateKey(dataDir, profile) {
7192
7332
  return `${path8.resolve(dataDir)}::${profile.key}`;
7193
7333
  }
7194
7334
  function tableName(profile) {
7195
- const digest2 = createHash3("sha256").update(profile.key).digest("hex").slice(0, 20);
7335
+ const digest2 = createHash4("sha256").update(profile.key).digest("hex").slice(0, 20);
7196
7336
  return `${TABLE_PREFIX}${digest2}`;
7197
7337
  }
7198
7338
  function indexRoot(dataDir) {
@@ -9270,7 +9410,7 @@ var init_lifecycle = __esm({
9270
9410
  });
9271
9411
 
9272
9412
  // src/store/evidence-store.ts
9273
- import { createHash as createHash4, randomUUID as randomUUID4 } from "crypto";
9413
+ import { createHash as createHash5, randomUUID as randomUUID4 } from "crypto";
9274
9414
  function safeJson(value, fallback) {
9275
9415
  if (typeof value !== "string" || value.length === 0) return fallback;
9276
9416
  try {
@@ -9304,7 +9444,7 @@ function rowToCard(row) {
9304
9444
  };
9305
9445
  }
9306
9446
  function observationHash(observation) {
9307
- return createHash4("sha256").update(JSON.stringify({
9447
+ return createHash5("sha256").update(JSON.stringify({
9308
9448
  projectId: observation.projectId,
9309
9449
  id: observation.id,
9310
9450
  title: observation.title,
@@ -9734,13 +9874,13 @@ __export(workspace_exports, {
9734
9874
  loadKnowledgeWorkspace: () => loadKnowledgeWorkspace,
9735
9875
  resolveKnowledgeWorkspaceFile: () => resolveKnowledgeWorkspaceFile
9736
9876
  });
9737
- import { createHash as createHash5 } from "crypto";
9877
+ import { createHash as createHash6 } from "crypto";
9738
9878
  import { execFile } from "child_process";
9739
9879
  import { promises as fs6 } from "fs";
9740
9880
  import path10 from "path";
9741
9881
  import { promisify } from "util";
9742
9882
  function hash(value) {
9743
- return createHash5("sha256").update(value).digest("hex");
9883
+ return createHash6("sha256").update(value).digest("hex");
9744
9884
  }
9745
9885
  function workspaceId(projectId, mode) {
9746
9886
  return "workspace:" + hash(projectId + ":" + mode).slice(0, 24);
@@ -10348,14 +10488,14 @@ var init_types2 = __esm({
10348
10488
  });
10349
10489
 
10350
10490
  // src/media/asset-store.ts
10351
- import { createHash as createHash6, randomUUID as randomUUID6 } from "crypto";
10491
+ import { createHash as createHash7, randomUUID as randomUUID6 } from "crypto";
10352
10492
  import { copyFile, lstat, mkdir as mkdir3, open, readFile as readFile3, readdir, rename as rename2, rm, stat as stat2, writeFile as writeFile3 } from "fs/promises";
10353
10493
  import path11 from "path";
10354
10494
  function mediaRoot(dataDir) {
10355
10495
  return path11.resolve(dataDir, "media");
10356
10496
  }
10357
10497
  function projectStorageKey(projectId) {
10358
- return createHash6("sha256").update(projectId).digest("hex").slice(0, 16);
10498
+ return createHash7("sha256").update(projectId).digest("hex").slice(0, 16);
10359
10499
  }
10360
10500
  function validateUnderRoot(root, candidate) {
10361
10501
  const resolved = path11.resolve(candidate);
@@ -10464,7 +10604,7 @@ async function importMediaBuffer(input) {
10464
10604
  if (input.bytes.length === 0) throw new Error("Media import rejects empty payloads");
10465
10605
  if (input.bytes.length > maxBytes) throw new Error(`Media payload is too large (${input.bytes.length} bytes; limit ${maxBytes})`);
10466
10606
  const detected = detectMedia(input.bytes.subarray(0, 32));
10467
- const sha256 = createHash6("sha256").update(input.bytes).digest("hex");
10607
+ const sha256 = createHash7("sha256").update(input.bytes).digest("hex");
10468
10608
  return importKnownMedia({
10469
10609
  dataDir: input.dataDir,
10470
10610
  projectId: input.projectId,
@@ -10482,7 +10622,7 @@ async function readMediaAsset(dataDir, asset, maxBytes = DEFAULT_MAX_MEDIA_BYTES
10482
10622
  if (asset.byteSize > maxBytes) throw new Error(`Media asset exceeds read limit (${asset.byteSize} bytes; limit ${maxBytes})`);
10483
10623
  const bytes = await readFile3(getMediaAssetPath(dataDir, asset));
10484
10624
  if (bytes.length !== asset.byteSize) throw new Error(`Media asset size no longer matches metadata: ${asset.id}`);
10485
- const sha256 = createHash6("sha256").update(bytes).digest("hex");
10625
+ const sha256 = createHash7("sha256").update(bytes).digest("hex");
10486
10626
  if (sha256 !== asset.sha256) throw new Error(`Media asset hash no longer matches metadata: ${asset.id}`);
10487
10627
  return bytes;
10488
10628
  }
@@ -69178,16 +69318,16 @@ var require_jwtaccess = __commonJS({
69178
69318
  * @returns A string that returns the cached key.
69179
69319
  */
69180
69320
  getCachedKey(url, scopes) {
69181
- let cacheKey = url;
69321
+ let cacheKey3 = url;
69182
69322
  if (scopes && Array.isArray(scopes) && scopes.length) {
69183
- cacheKey = url ? `${url}_${scopes.join("_")}` : `${scopes.join("_")}`;
69323
+ cacheKey3 = url ? `${url}_${scopes.join("_")}` : `${scopes.join("_")}`;
69184
69324
  } else if (typeof scopes === "string") {
69185
- cacheKey = url ? `${url}_${scopes}` : scopes;
69325
+ cacheKey3 = url ? `${url}_${scopes}` : scopes;
69186
69326
  }
69187
- if (!cacheKey) {
69327
+ if (!cacheKey3) {
69188
69328
  throw Error("Scopes or url must be provided");
69189
69329
  }
69190
- return cacheKey;
69330
+ return cacheKey3;
69191
69331
  }
69192
69332
  /**
69193
69333
  * Get a non-expired access token, after refreshing if necessary.
@@ -75733,7 +75873,7 @@ var require_websocket = __commonJS({
75733
75873
  var http3 = __require("http");
75734
75874
  var net = __require("net");
75735
75875
  var tls = __require("tls");
75736
- var { randomBytes, createHash: createHash16 } = __require("crypto");
75876
+ var { randomBytes, createHash: createHash17 } = __require("crypto");
75737
75877
  var { Duplex, Readable: Readable2 } = __require("stream");
75738
75878
  var { URL: URL2 } = __require("url");
75739
75879
  var PerMessageDeflate2 = require_permessage_deflate();
@@ -76401,7 +76541,7 @@ var require_websocket = __commonJS({
76401
76541
  abortHandshake(websocket, socket, "Invalid Upgrade header");
76402
76542
  return;
76403
76543
  }
76404
- const digest2 = createHash16("sha1").update(key + GUID).digest("base64");
76544
+ const digest2 = createHash17("sha1").update(key + GUID).digest("base64");
76405
76545
  if (res.headers["sec-websocket-accept"] !== digest2) {
76406
76546
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
76407
76547
  return;
@@ -76773,7 +76913,7 @@ var require_websocket_server = __commonJS({
76773
76913
  var EventEmitter = __require("events");
76774
76914
  var http3 = __require("http");
76775
76915
  var { Duplex } = __require("stream");
76776
- var { createHash: createHash16 } = __require("crypto");
76916
+ var { createHash: createHash17 } = __require("crypto");
76777
76917
  var extension3 = require_extension();
76778
76918
  var PerMessageDeflate2 = require_permessage_deflate();
76779
76919
  var subprotocol2 = require_subprotocol();
@@ -77080,7 +77220,7 @@ var require_websocket_server = __commonJS({
77080
77220
  );
77081
77221
  }
77082
77222
  if (this._state > RUNNING) return abortHandshake(socket, 503);
77083
- const digest2 = createHash16("sha1").update(key + GUID).digest("base64");
77223
+ const digest2 = createHash17("sha1").update(key + GUID).digest("base64");
77084
77224
  const headers = [
77085
77225
  "HTTP/1.1 101 Switching Protocols",
77086
77226
  "Upgrade: websocket",
@@ -145365,9 +145505,9 @@ var init_long_term = __esm({
145365
145505
  });
145366
145506
 
145367
145507
  // src/codegraph/ids.ts
145368
- import { createHash as createHash7 } from "crypto";
145508
+ import { createHash as createHash8 } from "crypto";
145369
145509
  function digest(input) {
145370
- return createHash7("sha256").update(input).digest("hex").slice(0, 16);
145510
+ return createHash8("sha256").update(input).digest("hex").slice(0, 16);
145371
145511
  }
145372
145512
  function normalizeCodePath(path23) {
145373
145513
  return path23.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+/g, "/");
@@ -146415,7 +146555,7 @@ var init_store = __esm({
146415
146555
 
146416
146556
  // src/codegraph/code-state.ts
146417
146557
  import { execFile as execFile2 } from "child_process";
146418
- import { createHash as createHash8 } from "crypto";
146558
+ import { createHash as createHash9 } from "crypto";
146419
146559
  import { promisify as promisify3 } from "util";
146420
146560
  async function runGit(rootPath, args) {
146421
146561
  try {
@@ -146444,7 +146584,7 @@ function changedPathCount(status) {
146444
146584
  return count2;
146445
146585
  }
146446
146586
  function fingerprint(baseRevision, status) {
146447
- return createHash8("sha256").update(baseRevision ?? "").update("\0").update(status).digest("hex");
146587
+ return createHash9("sha256").update(baseRevision ?? "").update("\0").update(status).digest("hex");
146448
146588
  }
146449
146589
  async function collectCodeStateSnapshot(input) {
146450
146590
  const [revision, status] = await Promise.all([
@@ -146538,12 +146678,12 @@ var init_exclude3 = __esm({
146538
146678
  });
146539
146679
 
146540
146680
  // src/codegraph/semantic-provider.ts
146541
- import { createHash as createHash9 } from "crypto";
146681
+ import { createHash as createHash10 } from "crypto";
146542
146682
  import "fs";
146543
146683
  import { resolve } from "path";
146544
146684
  import ts from "typescript";
146545
146685
  function hashText(value) {
146546
- return createHash9("sha256").update(value).digest("hex");
146686
+ return createHash10("sha256").update(value).digest("hex");
146547
146687
  }
146548
146688
  function canonicalPath(value) {
146549
146689
  const normalized = resolve(value).replace(/\\/g, "/");
@@ -146888,11 +147028,11 @@ __export(lite_provider_exports, {
146888
147028
  indexProjectLite: () => indexProjectLite,
146889
147029
  refreshProjectLite: () => refreshProjectLite
146890
147030
  });
146891
- import { createHash as createHash10 } from "crypto";
147031
+ import { createHash as createHash11 } from "crypto";
146892
147032
  import { existsSync as existsSync10, readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
146893
147033
  import { join as join4, relative as relative2 } from "path";
146894
147034
  function hashText2(text2) {
146895
- return createHash10("sha256").update(text2).digest("hex");
147035
+ return createHash11("sha256").update(text2).digest("hex");
146896
147036
  }
146897
147037
  function extension2(path23) {
146898
147038
  const index = path23.lastIndexOf(".");
@@ -147525,7 +147665,7 @@ var claim_store_exports = {};
147525
147665
  __export(claim_store_exports, {
147526
147666
  ClaimStore: () => ClaimStore
147527
147667
  });
147528
- import { createHash as createHash11, randomUUID as randomUUID12 } from "crypto";
147668
+ import { createHash as createHash12, randomUUID as randomUUID12 } from "crypto";
147529
147669
  function optionalText3(value) {
147530
147670
  return typeof value === "string" && value ? value : void 0;
147531
147671
  }
@@ -147578,7 +147718,7 @@ function rowToEvent3(row) {
147578
147718
  };
147579
147719
  }
147580
147720
  function evidenceKey(input) {
147581
- return createHash11("sha256").update(JSON.stringify([
147721
+ return createHash12("sha256").update(JSON.stringify([
147582
147722
  input.evidenceKind,
147583
147723
  input.evidenceId,
147584
147724
  input.relation,
@@ -147776,7 +147916,7 @@ __export(claims_exports, {
147776
147916
  supersedeClaim: () => supersedeClaim,
147777
147917
  writeClaim: () => writeClaim
147778
147918
  });
147779
- import { createHash as createHash12, randomUUID as randomUUID13 } from "crypto";
147919
+ import { createHash as createHash13, randomUUID as randomUUID13 } from "crypto";
147780
147920
  function compactText2(value, field) {
147781
147921
  if (typeof value !== "string") throw new Error("Claim " + field + " must be text");
147782
147922
  const sanitized = sanitizeCredentials(value).trim().replace(/\s+/g, " ");
@@ -147788,7 +147928,7 @@ function normalizedTerm(value) {
147788
147928
  return compactText2(value, "identity").toLocaleLowerCase("en-US");
147789
147929
  }
147790
147930
  function hashIdentity(parts) {
147791
- return createHash12("sha256").update(parts.join(String.fromCharCode(31))).digest("hex");
147931
+ return createHash13("sha256").update(parts.join(String.fromCharCode(31))).digest("hex");
147792
147932
  }
147793
147933
  function buildClaimIdentity(input) {
147794
147934
  const subject = normalizedTerm(input.subject);
@@ -148029,7 +148169,7 @@ function supersedeClaim(store, input) {
148029
148169
  });
148030
148170
  }
148031
148171
  function hashObservation(observation) {
148032
- return createHash12("sha256").update(JSON.stringify([
148172
+ return createHash13("sha256").update(JSON.stringify([
148033
148173
  observation.title,
148034
148174
  observation.narrative,
148035
148175
  observation.facts,
@@ -148273,11 +148413,11 @@ var init_frontmatter = __esm({
148273
148413
  });
148274
148414
 
148275
148415
  // src/knowledge/markdown.ts
148276
- import { createHash as createHash13 } from "crypto";
148416
+ import { createHash as createHash14 } from "crypto";
148277
148417
  import { promises as fs10 } from "fs";
148278
148418
  import path17 from "path";
148279
148419
  function hashContent(content) {
148280
- return createHash13("sha256").update(content).digest("hex");
148420
+ return createHash14("sha256").update(content).digest("hex");
148281
148421
  }
148282
148422
  function stringField(data, key) {
148283
148423
  const value = data[key];
@@ -148403,11 +148543,11 @@ __export(wiki_exports, {
148403
148543
  lintKnowledgeWorkspace: () => lintKnowledgeWorkspace,
148404
148544
  readKnowledgePage: () => readKnowledgePage
148405
148545
  });
148406
- import { createHash as createHash14 } from "crypto";
148546
+ import { createHash as createHash15 } from "crypto";
148407
148547
  import { promises as fs11 } from "fs";
148408
148548
  import path18 from "path";
148409
148549
  function hash2(value) {
148410
- return createHash14("sha256").update(value).digest("hex");
148550
+ return createHash15("sha256").update(value).digest("hex");
148411
148551
  }
148412
148552
  function now() {
148413
148553
  return (/* @__PURE__ */ new Date()).toISOString();
@@ -149264,11 +149404,11 @@ __export(workflows_exports, {
149264
149404
  syncCanonicalWorkflows: () => syncCanonicalWorkflows,
149265
149405
  writeCanonicalWorkflow: () => writeCanonicalWorkflow
149266
149406
  });
149267
- import { createHash as createHash15 } from "crypto";
149407
+ import { createHash as createHash16 } from "crypto";
149268
149408
  import { promises as fs12 } from "fs";
149269
149409
  import path19 from "path";
149270
149410
  function hash3(value) {
149271
- return createHash15("sha256").update(value).digest("hex");
149411
+ return createHash16("sha256").update(value).digest("hex");
149272
149412
  }
149273
149413
  function now2() {
149274
149414
  return (/* @__PURE__ */ new Date()).toISOString();