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.
- package/CHANGELOG.md +75 -1
- package/README.md +12 -6
- package/README.zh-CN.md +12 -6
- package/dist/cli/index.js +2533 -585
- package/dist/index.d.ts +15 -8
- package/dist/index.js +1201 -284
- package/dist/maintenance-runner.js +387 -216
- package/dist/media-audio-runner.js +300 -129
- package/dist/media-video-runner.js +300 -129
- package/dist/memcode-runtime/CHANGELOG.md +75 -1
- package/dist/sdk.d.ts +1 -0
- package/dist/sdk.js +1882 -998
- package/dist/types.d.ts +1 -1
- package/dist/vector-backfill-runner.js +300 -129
- package/docs/AGENT_OPERATOR_PLAYBOOK.md +47 -3
- package/docs/API_REFERENCE.md +39 -1
- package/docs/CONFIGURATION.md +58 -1
- package/docs/DEVELOPMENT.md +1 -1
- package/docs/DOCKER.md +23 -3
- package/docs/INTEGRATIONS.md +1 -1
- package/docs/KNOWN_ISSUES_AND_ROADMAP.md +61 -1
- package/docs/MULTI-DEVICE-SYNC-RESEARCH.md +4 -0
- package/docs/PERFORMANCE.md +46 -2
- package/docs/README.md +2 -1
- package/docs/SETUP.md +56 -1
- package/package.json +3 -2
- package/plugins/antigravity/memorix/plugin.json +1 -1
- package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
- package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/copilot/memorix/plugin.json +1 -1
- package/plugins/gemini/memorix/gemini-extension.json +1 -1
- package/plugins/hermes/memorix/plugin.yaml +1 -1
- package/plugins/omp/memorix/package.json +1 -1
- package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/pi/memorix/package.json +1 -1
- package/server.json +2 -2
- package/src/cli/capability-map.ts +1 -0
- package/src/cli/command-guide.ts +15 -3
- package/src/cli/commands/agent-integrations.ts +57 -0
- package/src/cli/commands/background.ts +11 -2
- package/src/cli/commands/context.ts +2 -0
- package/src/cli/commands/continuity.ts +155 -0
- package/src/cli/commands/init.ts +5 -2
- package/src/cli/commands/serve-http.ts +435 -84
- package/src/cli/commands/setup.ts +77 -10
- package/src/cli/commands/sync-store.ts +47 -12
- package/src/cli/commands/sync.ts +26 -0
- package/src/cli/index.ts +3 -1
- package/src/cli/tui/ConfigureView.tsx +2 -0
- package/src/codegraph/auto-context.ts +17 -0
- package/src/config/legacy-loader.ts +2 -2
- package/src/config/resolved-config.ts +8 -5
- package/src/config/yaml-loader.ts +20 -10
- package/src/dashboard/server.ts +10 -12
- package/src/embedding/api-provider.ts +4 -2
- package/src/embedding/fastembed-provider.ts +47 -14
- package/src/embedding/transformers-provider.ts +29 -7
- package/src/evaluation/memory-quality-gate.ts +90 -0
- package/src/hooks/official-skills.ts +2 -0
- package/src/integrations/registry.ts +1 -1
- package/src/knowledge/context-assembly.ts +1 -0
- package/src/knowledge/context-receipt.ts +15 -0
- package/src/knowledge/task-continuity.ts +413 -0
- package/src/knowledge/workset.ts +77 -0
- package/src/llm/provider.ts +2 -1
- package/src/memory/graph.ts +10 -8
- package/src/memory/session.ts +1 -1
- package/src/orchestrate/coordinator.ts +60 -0
- package/src/orchestrate/effect-ledger.ts +160 -0
- package/src/orchestrate/pipeline-trace.ts +40 -6
- package/src/runtime/maintenance-jobs.ts +12 -6
- package/src/sdk.ts +24 -0
- package/src/server/mcp-binding-store.ts +14 -3
- package/src/server/modern-mcp-bridge.ts +153 -27
- package/src/server/tool-profile.ts +3 -2
- package/src/server.ts +131 -7
- package/src/store/file-lock.ts +28 -3
- package/src/store/graph-store.ts +178 -46
- package/src/store/persistence.ts +14 -9
- package/src/store/sqlite-db.ts +150 -7
- package/src/store/sqlite-store.ts +32 -27
- package/src/sync/engine.ts +9 -7
- package/src/sync/namespace.ts +23 -0
- package/src/sync/policy.ts +19 -4
- package/src/sync/store-port.ts +43 -13
- package/src/sync/types.ts +2 -0
- package/src/team/team-store.ts +62 -27
- package/src/types.ts +1 -1
- package/src/workspace/mcp-adapters/grok.ts +32 -0
|
@@ -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
|
|
168
|
+
const key = cacheKey(homeDir, resolvedRoot);
|
|
169
|
+
const cached = configCache.get(key);
|
|
165
170
|
if (cached) return cached;
|
|
166
|
-
const userYaml = getGlobalYamlPath(
|
|
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(
|
|
203
|
+
configCache.set(key, merged);
|
|
199
204
|
return merged;
|
|
200
205
|
}
|
|
201
206
|
function parseYaml(content) {
|
|
@@ -572,11 +577,21 @@ function applySchemaMigrations(db2) {
|
|
|
572
577
|
apply();
|
|
573
578
|
}
|
|
574
579
|
}
|
|
580
|
+
function normalizeDataDir(dataDir) {
|
|
581
|
+
return path3.resolve(dataDir);
|
|
582
|
+
}
|
|
583
|
+
function touchDatabase(normalized, db2) {
|
|
584
|
+
_dbCache.delete(normalized);
|
|
585
|
+
_dbCache.set(normalized, db2);
|
|
586
|
+
}
|
|
575
587
|
function getDatabase(dataDir) {
|
|
576
|
-
const normalized =
|
|
588
|
+
const normalized = normalizeDataDir(dataDir);
|
|
577
589
|
assertNotHomeDataDir(normalized);
|
|
578
590
|
const existing = _dbCache.get(normalized);
|
|
579
|
-
if (existing)
|
|
591
|
+
if (existing) {
|
|
592
|
+
touchDatabase(normalized, existing);
|
|
593
|
+
return existing;
|
|
594
|
+
}
|
|
580
595
|
loadBetterSqlite3();
|
|
581
596
|
fs.mkdirSync(dataDir, { recursive: true });
|
|
582
597
|
const dbPath = path3.join(dataDir, "memorix.db");
|
|
@@ -606,6 +621,8 @@ function getDatabase(dataDir) {
|
|
|
606
621
|
db2.exec(CREATE_MAINTENANCE_JOBS_TABLE);
|
|
607
622
|
db2.exec(CREATE_MAINTENANCE_TARGETS_TABLE);
|
|
608
623
|
db2.exec(CREATE_COMPACTION_CHECKPOINTS_TABLE);
|
|
624
|
+
db2.exec(CREATE_TASK_CONTINUITY_EVENTS_TABLE);
|
|
625
|
+
db2.exec(CREATE_AGENT_EFFECTS_TABLE);
|
|
609
626
|
try {
|
|
610
627
|
db2.exec(`ALTER TABLE mini_skills ADD COLUMN sourceSnapshot TEXT NOT NULL DEFAULT ''`);
|
|
611
628
|
} catch {
|
|
@@ -644,7 +661,7 @@ function getDatabase(dataDir) {
|
|
|
644
661
|
db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('storage_generation', '0')`).run();
|
|
645
662
|
db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('next_id', '1')`).run();
|
|
646
663
|
db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('mini_skills_generation', '0')`).run();
|
|
647
|
-
|
|
664
|
+
touchDatabase(normalized, db2);
|
|
648
665
|
return db2;
|
|
649
666
|
} catch (error) {
|
|
650
667
|
try {
|
|
@@ -662,8 +679,9 @@ function closeAllDatabases() {
|
|
|
662
679
|
}
|
|
663
680
|
_dbCache.delete(key);
|
|
664
681
|
}
|
|
682
|
+
_dbLeases.clear();
|
|
665
683
|
}
|
|
666
|
-
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;
|
|
684
|
+
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;
|
|
667
685
|
var init_sqlite_db = __esm({
|
|
668
686
|
"src/store/sqlite-db.ts"() {
|
|
669
687
|
"use strict";
|
|
@@ -835,18 +853,21 @@ CREATE TABLE IF NOT EXISTS chat_transcript (
|
|
|
835
853
|
`;
|
|
836
854
|
CREATE_GRAPH_ENTITIES_TABLE = `
|
|
837
855
|
CREATE TABLE IF NOT EXISTS graph_entities (
|
|
838
|
-
|
|
856
|
+
projectId TEXT NOT NULL,
|
|
857
|
+
name TEXT NOT NULL,
|
|
839
858
|
entityType TEXT NOT NULL DEFAULT '',
|
|
840
|
-
observations TEXT NOT NULL DEFAULT '[]'
|
|
859
|
+
observations TEXT NOT NULL DEFAULT '[]',
|
|
860
|
+
PRIMARY KEY (projectId, name)
|
|
841
861
|
);
|
|
842
862
|
`;
|
|
843
863
|
CREATE_GRAPH_RELATIONS_TABLE = `
|
|
844
864
|
CREATE TABLE IF NOT EXISTS graph_relations (
|
|
845
865
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
866
|
+
projectId TEXT NOT NULL,
|
|
846
867
|
from_entity TEXT NOT NULL,
|
|
847
868
|
to_entity TEXT NOT NULL,
|
|
848
869
|
relationType TEXT NOT NULL DEFAULT '',
|
|
849
|
-
UNIQUE(from_entity, to_entity, relationType)
|
|
870
|
+
UNIQUE(projectId, from_entity, to_entity, relationType)
|
|
850
871
|
);
|
|
851
872
|
`;
|
|
852
873
|
CREATE_CODE_FILES_TABLE = `
|
|
@@ -1377,6 +1398,43 @@ CREATE TABLE IF NOT EXISTS memory_feedback_events (
|
|
|
1377
1398
|
delta REAL NOT NULL DEFAULT 0,
|
|
1378
1399
|
observed_at TEXT NOT NULL
|
|
1379
1400
|
);
|
|
1401
|
+
`;
|
|
1402
|
+
CREATE_TASK_CONTINUITY_EVENTS_TABLE = `
|
|
1403
|
+
CREATE TABLE IF NOT EXISTS task_continuity_events (
|
|
1404
|
+
id TEXT PRIMARY KEY,
|
|
1405
|
+
project_id TEXT NOT NULL,
|
|
1406
|
+
task_id TEXT NOT NULL,
|
|
1407
|
+
task TEXT NOT NULL,
|
|
1408
|
+
kind TEXT NOT NULL,
|
|
1409
|
+
content TEXT NOT NULL,
|
|
1410
|
+
item_status TEXT,
|
|
1411
|
+
source_ref TEXT,
|
|
1412
|
+
evidence_json TEXT NOT NULL DEFAULT '[]',
|
|
1413
|
+
actor TEXT,
|
|
1414
|
+
created_at TEXT NOT NULL,
|
|
1415
|
+
event_key TEXT,
|
|
1416
|
+
item_key TEXT,
|
|
1417
|
+
supersedes_id TEXT
|
|
1418
|
+
);
|
|
1419
|
+
`;
|
|
1420
|
+
CREATE_AGENT_EFFECTS_TABLE = `
|
|
1421
|
+
CREATE TABLE IF NOT EXISTS agent_effects (
|
|
1422
|
+
id TEXT PRIMARY KEY,
|
|
1423
|
+
pipeline_id TEXT NOT NULL,
|
|
1424
|
+
task_id TEXT NOT NULL,
|
|
1425
|
+
attempt INTEGER NOT NULL,
|
|
1426
|
+
effect_key TEXT NOT NULL,
|
|
1427
|
+
tool TEXT NOT NULL,
|
|
1428
|
+
risk_tier TEXT NOT NULL,
|
|
1429
|
+
replay_policy TEXT NOT NULL,
|
|
1430
|
+
status TEXT NOT NULL,
|
|
1431
|
+
call_id TEXT,
|
|
1432
|
+
idempotency_key TEXT NOT NULL,
|
|
1433
|
+
input_fingerprint TEXT,
|
|
1434
|
+
detail TEXT,
|
|
1435
|
+
started_at INTEGER NOT NULL,
|
|
1436
|
+
finished_at INTEGER
|
|
1437
|
+
);
|
|
1380
1438
|
`;
|
|
1381
1439
|
CREATE_MCP_BINDINGS_TABLE = `
|
|
1382
1440
|
CREATE TABLE IF NOT EXISTS mcp_bindings (
|
|
@@ -1455,7 +1513,18 @@ CREATE INDEX IF NOT EXISTS idx_evidence_cards_candidate ON evidence_cards(projec
|
|
|
1455
1513
|
CREATE INDEX IF NOT EXISTS idx_evidence_card_events_card ON evidence_card_events(card_id, created_at);
|
|
1456
1514
|
CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC);
|
|
1457
1515
|
CREATE INDEX IF NOT EXISTS idx_memory_feedback_events_candidate ON memory_feedback_events(project_id, candidate_kind, candidate_id, observed_at DESC);
|
|
1516
|
+
CREATE INDEX IF NOT EXISTS idx_task_continuity_project_task ON task_continuity_events(project_id, task_id, created_at ASC);
|
|
1517
|
+
CREATE INDEX IF NOT EXISTS idx_task_continuity_project_recent ON task_continuity_events(project_id, created_at DESC);
|
|
1518
|
+
CREATE INDEX IF NOT EXISTS idx_task_continuity_item ON task_continuity_events(project_id, task_id, kind, item_key, created_at DESC);
|
|
1519
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_task_continuity_event_key
|
|
1520
|
+
ON task_continuity_events(project_id, task_id, event_key)
|
|
1521
|
+
WHERE event_key IS NOT NULL;
|
|
1522
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_agent_effect_identity
|
|
1523
|
+
ON agent_effects(pipeline_id, task_id, attempt, effect_key);
|
|
1524
|
+
CREATE INDEX IF NOT EXISTS idx_agent_effect_pipeline ON agent_effects(pipeline_id, started_at ASC);
|
|
1458
1525
|
CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC);
|
|
1526
|
+
CREATE INDEX IF NOT EXISTS idx_mcp_bindings_root ON mcp_bindings(project_root, last_used_at DESC);
|
|
1527
|
+
CREATE INDEX IF NOT EXISTS idx_mcp_bindings_expiry ON mcp_bindings(expires_at);
|
|
1459
1528
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
1460
1529
|
ON maintenance_jobs(project_id, kind, dedupe_key)
|
|
1461
1530
|
WHERE status IN ('pending', 'running', 'retry');
|
|
@@ -1626,6 +1695,8 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
|
1626
1695
|
db2.exec("CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC)");
|
|
1627
1696
|
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)");
|
|
1628
1697
|
db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC)");
|
|
1698
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_root ON mcp_bindings(project_root, last_used_at DESC)");
|
|
1699
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_expiry ON mcp_bindings(expires_at)");
|
|
1629
1700
|
}
|
|
1630
1701
|
},
|
|
1631
1702
|
{
|
|
@@ -1636,9 +1707,22 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
|
1636
1707
|
addColumnIfMissing(db2, "code_symbols", "source", "source TEXT");
|
|
1637
1708
|
addColumnIfMissing(db2, "code_edges", "source", "source TEXT");
|
|
1638
1709
|
}
|
|
1710
|
+
},
|
|
1711
|
+
{
|
|
1712
|
+
id: "1.9-continuity-v2",
|
|
1713
|
+
apply: (db2) => {
|
|
1714
|
+
addColumnIfMissing(db2, "task_continuity_events", "event_key", "event_key TEXT");
|
|
1715
|
+
addColumnIfMissing(db2, "task_continuity_events", "item_key", "item_key TEXT");
|
|
1716
|
+
addColumnIfMissing(db2, "task_continuity_events", "supersedes_id", "supersedes_id TEXT");
|
|
1717
|
+
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)");
|
|
1718
|
+
db2.exec(`CREATE UNIQUE INDEX IF NOT EXISTS idx_task_continuity_event_key
|
|
1719
|
+
ON task_continuity_events(project_id, task_id, event_key)
|
|
1720
|
+
WHERE event_key IS NOT NULL`);
|
|
1721
|
+
}
|
|
1639
1722
|
}
|
|
1640
1723
|
];
|
|
1641
1724
|
_dbCache = /* @__PURE__ */ new Map();
|
|
1725
|
+
_dbLeases = /* @__PURE__ */ new Map();
|
|
1642
1726
|
}
|
|
1643
1727
|
});
|
|
1644
1728
|
|
|
@@ -1714,6 +1798,21 @@ var init_sqlite_reliability = __esm({
|
|
|
1714
1798
|
import { promises as fs2 } from "fs";
|
|
1715
1799
|
import { randomUUID } from "crypto";
|
|
1716
1800
|
import path4 from "path";
|
|
1801
|
+
function canReclaimStaleLock(raw) {
|
|
1802
|
+
try {
|
|
1803
|
+
const parsed = JSON.parse(raw);
|
|
1804
|
+
const pid = Number(parsed.pid);
|
|
1805
|
+
if (!Number.isSafeInteger(pid) || pid < 1) return true;
|
|
1806
|
+
try {
|
|
1807
|
+
process.kill(pid, 0);
|
|
1808
|
+
return false;
|
|
1809
|
+
} catch (error) {
|
|
1810
|
+
return error.code !== "EPERM";
|
|
1811
|
+
}
|
|
1812
|
+
} catch {
|
|
1813
|
+
return true;
|
|
1814
|
+
}
|
|
1815
|
+
}
|
|
1717
1816
|
async function acquireLock(lockPath) {
|
|
1718
1817
|
for (let i2 = 0; i2 < MAX_RETRIES; i2++) {
|
|
1719
1818
|
try {
|
|
@@ -1727,9 +1826,12 @@ async function acquireLock(lockPath) {
|
|
|
1727
1826
|
try {
|
|
1728
1827
|
const stat5 = await fs2.stat(lockPath);
|
|
1729
1828
|
if (Date.now() - stat5.mtimeMs > LOCK_STALE_MS) {
|
|
1730
|
-
await fs2.
|
|
1731
|
-
|
|
1732
|
-
|
|
1829
|
+
const raw2 = await fs2.readFile(lockPath, "utf8").catch(() => "");
|
|
1830
|
+
if (canReclaimStaleLock(raw2)) {
|
|
1831
|
+
await fs2.unlink(lockPath).catch(() => {
|
|
1832
|
+
});
|
|
1833
|
+
continue;
|
|
1834
|
+
}
|
|
1733
1835
|
}
|
|
1734
1836
|
} catch {
|
|
1735
1837
|
continue;
|
|
@@ -1740,6 +1842,10 @@ async function acquireLock(lockPath) {
|
|
|
1740
1842
|
}
|
|
1741
1843
|
}
|
|
1742
1844
|
}
|
|
1845
|
+
const raw = await fs2.readFile(lockPath, "utf8").catch(() => "");
|
|
1846
|
+
if (!canReclaimStaleLock(raw)) {
|
|
1847
|
+
throw new Error(`Failed to acquire lock: ${lockPath} (owner is still running)`);
|
|
1848
|
+
}
|
|
1743
1849
|
await fs2.unlink(lockPath).catch(() => {
|
|
1744
1850
|
});
|
|
1745
1851
|
try {
|
|
@@ -2106,9 +2212,9 @@ var init_detector = __esm({
|
|
|
2106
2212
|
// src/config/legacy-loader.ts
|
|
2107
2213
|
import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
|
|
2108
2214
|
import { homedir as homedir3 } from "os";
|
|
2109
|
-
function loadFileConfig() {
|
|
2215
|
+
function loadFileConfig(homeDir = homedir3()) {
|
|
2110
2216
|
if (cachedConfig !== null) return cachedConfig;
|
|
2111
|
-
const configPath = getLegacyConfigJsonPath(
|
|
2217
|
+
const configPath = getLegacyConfigJsonPath(homeDir);
|
|
2112
2218
|
try {
|
|
2113
2219
|
if (existsSync5(configPath)) {
|
|
2114
2220
|
cachedConfig = JSON.parse(readFileSync5(configPath, "utf-8"));
|
|
@@ -2138,15 +2244,15 @@ import { homedir as homedir4 } from "os";
|
|
|
2138
2244
|
function loadTomlConfig(options = {}) {
|
|
2139
2245
|
const homeDir = options.homeDir ?? homedir4();
|
|
2140
2246
|
const projectRoot = options.projectRoot ?? null;
|
|
2141
|
-
const
|
|
2142
|
-
const cached = configCache2.get(
|
|
2247
|
+
const cacheKey3 = `${homeDir}\0${projectRoot ?? ""}`;
|
|
2248
|
+
const cached = configCache2.get(cacheKey3);
|
|
2143
2249
|
if (cached) return cached;
|
|
2144
2250
|
const userToml = getGlobalConfigTomlPath(homeDir);
|
|
2145
2251
|
const projectToml = projectRoot ? getProjectConfigTomlPath(projectRoot) : null;
|
|
2146
2252
|
const userConfig = existsSync6(userToml) ? parseTomlConfig(readFileSync6(userToml, "utf8"), userToml) : {};
|
|
2147
2253
|
const projectConfig = projectToml && existsSync6(projectToml) ? parseTomlConfig(readFileSync6(projectToml, "utf8"), projectToml) : {};
|
|
2148
2254
|
const merged = mergeTomlConfig(userConfig, projectConfig);
|
|
2149
|
-
configCache2.set(
|
|
2255
|
+
configCache2.set(cacheKey3, merged);
|
|
2150
2256
|
return merged;
|
|
2151
2257
|
}
|
|
2152
2258
|
function mergeTomlConfig(base, override) {
|
|
@@ -2267,8 +2373,8 @@ function getResolvedConfig(options = {}) {
|
|
|
2267
2373
|
const projectRoot = options.projectRoot === void 0 ? detectProject()?.rootPath ?? null : options.projectRoot;
|
|
2268
2374
|
loadDotenv(projectRoot === null ? void 0 : projectRoot ?? void 0, { userHomeDir: homeDir });
|
|
2269
2375
|
const toml = loadTomlConfig({ projectRoot: projectRoot ?? null, homeDir });
|
|
2270
|
-
const yaml = loadYamlConfig(projectRoot ?? null);
|
|
2271
|
-
const legacy = loadFileConfig();
|
|
2376
|
+
const yaml = loadYamlConfig(projectRoot ?? null, { homeDir });
|
|
2377
|
+
const legacy = loadFileConfig(homeDir);
|
|
2272
2378
|
const embeddingBaseUrl = first(process.env.MEMORIX_EMBEDDING_BASE_URL, toml.embedding?.base_url, yaml.embedding?.baseUrl, legacy.embeddingApi?.baseUrl);
|
|
2273
2379
|
const openRouterEmbeddingApiKey = isOpenRouterUrl(embeddingBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
|
|
2274
2380
|
const memoryLlmProvider = first(
|
|
@@ -2290,15 +2396,17 @@ function getResolvedConfig(options = {}) {
|
|
|
2290
2396
|
legacy.llm?.baseUrl
|
|
2291
2397
|
);
|
|
2292
2398
|
const openRouterMemoryLlmApiKey = isOpenRouterMemoryLane(memoryLlmProvider, memoryLlmBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
|
|
2399
|
+
const isAtlasCloud = memoryLlmProvider === "atlascloud";
|
|
2293
2400
|
const memoryLlmApiKey = first(
|
|
2294
2401
|
process.env.MEMORIX_LLM_API_KEY,
|
|
2295
2402
|
process.env.MEMORIX_API_KEY,
|
|
2296
2403
|
toml.memory?.llm?.api_key,
|
|
2297
2404
|
yaml.llm?.apiKey,
|
|
2298
2405
|
legacy.llm?.apiKey,
|
|
2299
|
-
|
|
2300
|
-
process.env.
|
|
2301
|
-
|
|
2406
|
+
// Never borrow another provider's credentials for the Atlas Cloud preset.
|
|
2407
|
+
isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : process.env.OPENAI_API_KEY,
|
|
2408
|
+
isAtlasCloud ? void 0 : process.env.ANTHROPIC_API_KEY,
|
|
2409
|
+
isAtlasCloud ? void 0 : openRouterMemoryLlmApiKey
|
|
2302
2410
|
);
|
|
2303
2411
|
const resolved = {
|
|
2304
2412
|
agent: {
|
|
@@ -2477,7 +2585,8 @@ function getEnvSourceNames() {
|
|
|
2477
2585
|
"MEMORIX_CODEGRAPH_EXTERNAL_CONTEXT",
|
|
2478
2586
|
"MEMORIX_CODEGRAPH_EXTERNAL_COMMAND",
|
|
2479
2587
|
"MEMORIX_CODEGRAPH_EXTERNAL_TIMEOUT_MS",
|
|
2480
|
-
"OPENROUTER_API_KEY"
|
|
2588
|
+
"OPENROUTER_API_KEY",
|
|
2589
|
+
"ATLASCLOUD_API_KEY"
|
|
2481
2590
|
].filter((name) => process.env[name]);
|
|
2482
2591
|
}
|
|
2483
2592
|
function isOpenRouterUrl(value) {
|
|
@@ -2696,12 +2805,45 @@ function textHash(text2) {
|
|
|
2696
2805
|
async function loadDiskCache() {
|
|
2697
2806
|
try {
|
|
2698
2807
|
const raw = await readFile(CACHE_FILE, "utf-8");
|
|
2808
|
+
if (Buffer.byteLength(raw, "utf8") > MAX_CACHE_FILE_BYTES) {
|
|
2809
|
+
console.error("[memorix] FastEmbed cache exceeds the disk load limit; starting with an empty cache");
|
|
2810
|
+
return;
|
|
2811
|
+
}
|
|
2699
2812
|
const entries = JSON.parse(raw);
|
|
2700
|
-
|
|
2701
|
-
|
|
2813
|
+
if (!Array.isArray(entries)) return;
|
|
2814
|
+
for (const entry of entries) {
|
|
2815
|
+
if (!Array.isArray(entry) || typeof entry[0] !== "string" || !isVector(entry[1])) continue;
|
|
2816
|
+
cacheSet(entry[0], entry[1], false);
|
|
2817
|
+
}
|
|
2818
|
+
console.error(`[memorix] Loaded ${cache.size} cached embeddings from disk`);
|
|
2702
2819
|
} catch {
|
|
2703
2820
|
}
|
|
2704
2821
|
}
|
|
2822
|
+
function isVector(value) {
|
|
2823
|
+
return Array.isArray(value) && value.every((entry) => typeof entry === "number");
|
|
2824
|
+
}
|
|
2825
|
+
function maxCachePayloadBytes() {
|
|
2826
|
+
const raw = Number.parseInt(process.env.MEMORIX_EMBEDDING_CACHE_MAX_BYTES ?? "", 10);
|
|
2827
|
+
return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_CACHE_PAYLOAD_BYTES;
|
|
2828
|
+
}
|
|
2829
|
+
function cacheSet(hash4, value, markDirty = true) {
|
|
2830
|
+
const incomingBytes = value.length * 8;
|
|
2831
|
+
if (incomingBytes > maxCachePayloadBytes()) return;
|
|
2832
|
+
const existing = cache.get(hash4);
|
|
2833
|
+
if (existing) cachePayloadBytes -= existing.length * 8;
|
|
2834
|
+
else {
|
|
2835
|
+
while (cache.size >= MAX_CACHE_SIZE || cachePayloadBytes + incomingBytes > maxCachePayloadBytes()) {
|
|
2836
|
+
const firstKey = cache.keys().next().value;
|
|
2837
|
+
if (firstKey === void 0) break;
|
|
2838
|
+
const old = cache.get(firstKey);
|
|
2839
|
+
cache.delete(firstKey);
|
|
2840
|
+
if (old) cachePayloadBytes -= old.length * 8;
|
|
2841
|
+
}
|
|
2842
|
+
}
|
|
2843
|
+
cache.set(hash4, value);
|
|
2844
|
+
cachePayloadBytes += incomingBytes;
|
|
2845
|
+
if (markDirty) diskCacheDirty = true;
|
|
2846
|
+
}
|
|
2705
2847
|
async function saveDiskCache() {
|
|
2706
2848
|
if (!diskCacheDirty) return;
|
|
2707
2849
|
try {
|
|
@@ -2712,7 +2854,7 @@ async function saveDiskCache() {
|
|
|
2712
2854
|
} catch {
|
|
2713
2855
|
}
|
|
2714
2856
|
}
|
|
2715
|
-
var CACHE_DIR, CACHE_FILE, cache, MAX_CACHE_SIZE, diskCacheDirty, FastEmbedProvider;
|
|
2857
|
+
var CACHE_DIR, CACHE_FILE, cache, MAX_CACHE_SIZE, DEFAULT_CACHE_PAYLOAD_BYTES, MAX_CACHE_FILE_BYTES, cachePayloadBytes, diskCacheDirty, FastEmbedProvider;
|
|
2716
2858
|
var init_fastembed_provider = __esm({
|
|
2717
2859
|
"src/embedding/fastembed-provider.ts"() {
|
|
2718
2860
|
"use strict";
|
|
@@ -2722,6 +2864,9 @@ var init_fastembed_provider = __esm({
|
|
|
2722
2864
|
CACHE_FILE = join2(CACHE_DIR, ".embedding-cache.json");
|
|
2723
2865
|
cache = /* @__PURE__ */ new Map();
|
|
2724
2866
|
MAX_CACHE_SIZE = 5e3;
|
|
2867
|
+
DEFAULT_CACHE_PAYLOAD_BYTES = 64 * 1024 * 1024;
|
|
2868
|
+
MAX_CACHE_FILE_BYTES = 128 * 1024 * 1024;
|
|
2869
|
+
cachePayloadBytes = 0;
|
|
2725
2870
|
diskCacheDirty = false;
|
|
2726
2871
|
FastEmbedProvider = class _FastEmbedProvider {
|
|
2727
2872
|
name = "fastembed-bge-small";
|
|
@@ -2763,7 +2908,7 @@ var init_fastembed_provider = __esm({
|
|
|
2763
2908
|
if (result.length !== this.dimensions) {
|
|
2764
2909
|
throw new Error(`Expected ${this.dimensions}d embedding, got ${result.length}d`);
|
|
2765
2910
|
}
|
|
2766
|
-
|
|
2911
|
+
cacheSet(hash4, result);
|
|
2767
2912
|
return result;
|
|
2768
2913
|
}
|
|
2769
2914
|
async embedBatch(texts) {
|
|
@@ -2788,7 +2933,7 @@ var init_fastembed_provider = __esm({
|
|
|
2788
2933
|
const originalIdx = uncachedIndices[batchIdx];
|
|
2789
2934
|
const plain = Array.from(vec);
|
|
2790
2935
|
results[originalIdx] = plain;
|
|
2791
|
-
|
|
2936
|
+
cacheSet(textHash(uncachedTexts[batchIdx]), plain);
|
|
2792
2937
|
batchIdx++;
|
|
2793
2938
|
}
|
|
2794
2939
|
}
|
|
@@ -2796,14 +2941,6 @@ var init_fastembed_provider = __esm({
|
|
|
2796
2941
|
}
|
|
2797
2942
|
return results;
|
|
2798
2943
|
}
|
|
2799
|
-
cacheSet(hash4, value) {
|
|
2800
|
-
if (cache.size >= MAX_CACHE_SIZE) {
|
|
2801
|
-
const firstKey = cache.keys().next().value;
|
|
2802
|
-
if (firstKey !== void 0) cache.delete(firstKey);
|
|
2803
|
-
}
|
|
2804
|
-
cache.set(hash4, value);
|
|
2805
|
-
diskCacheDirty = true;
|
|
2806
|
-
}
|
|
2807
2944
|
};
|
|
2808
2945
|
}
|
|
2809
2946
|
});
|
|
@@ -2813,7 +2950,15 @@ var transformers_provider_exports = {};
|
|
|
2813
2950
|
__export(transformers_provider_exports, {
|
|
2814
2951
|
TransformersProvider: () => TransformersProvider
|
|
2815
2952
|
});
|
|
2816
|
-
|
|
2953
|
+
import { createHash as createHash2 } from "crypto";
|
|
2954
|
+
function cacheKey2(text2) {
|
|
2955
|
+
return createHash2("sha256").update(text2).digest("hex");
|
|
2956
|
+
}
|
|
2957
|
+
function maxCachePayloadBytes2() {
|
|
2958
|
+
const raw = Number.parseInt(process.env.MEMORIX_EMBEDDING_CACHE_MAX_BYTES ?? "", 10);
|
|
2959
|
+
return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_CACHE_PAYLOAD_BYTES2;
|
|
2960
|
+
}
|
|
2961
|
+
var cache2, MAX_CACHE_SIZE2, DEFAULT_CACHE_PAYLOAD_BYTES2, cachePayloadBytes2, TransformersProvider;
|
|
2817
2962
|
var init_transformers_provider = __esm({
|
|
2818
2963
|
"src/embedding/transformers-provider.ts"() {
|
|
2819
2964
|
"use strict";
|
|
@@ -2821,6 +2966,8 @@ var init_transformers_provider = __esm({
|
|
|
2821
2966
|
init_provider();
|
|
2822
2967
|
cache2 = /* @__PURE__ */ new Map();
|
|
2823
2968
|
MAX_CACHE_SIZE2 = 5e3;
|
|
2969
|
+
DEFAULT_CACHE_PAYLOAD_BYTES2 = 64 * 1024 * 1024;
|
|
2970
|
+
cachePayloadBytes2 = 0;
|
|
2824
2971
|
TransformersProvider = class _TransformersProvider {
|
|
2825
2972
|
name = "transformers-minilm";
|
|
2826
2973
|
dimensions = 384;
|
|
@@ -2855,7 +3002,7 @@ var init_transformers_provider = __esm({
|
|
|
2855
3002
|
return Promise.all(inputs.map((input) => this.embedInput(input, options)));
|
|
2856
3003
|
}
|
|
2857
3004
|
async embed(text2) {
|
|
2858
|
-
const cached = cache2.get(text2);
|
|
3005
|
+
const cached = cache2.get(cacheKey2(text2));
|
|
2859
3006
|
if (cached) return cached;
|
|
2860
3007
|
const output = await this.extractor(text2, {
|
|
2861
3008
|
pooling: "mean",
|
|
@@ -2865,7 +3012,7 @@ var init_transformers_provider = __esm({
|
|
|
2865
3012
|
if (result.length !== this.dimensions) {
|
|
2866
3013
|
throw new Error(`Expected ${this.dimensions}d embedding, got ${result.length}d`);
|
|
2867
3014
|
}
|
|
2868
|
-
this.cacheSet(text2, result);
|
|
3015
|
+
this.cacheSet(cacheKey2(text2), result);
|
|
2869
3016
|
return result;
|
|
2870
3017
|
}
|
|
2871
3018
|
async embedBatch(texts) {
|
|
@@ -2873,7 +3020,7 @@ var init_transformers_provider = __esm({
|
|
|
2873
3020
|
const uncachedIndices = [];
|
|
2874
3021
|
const uncachedTexts = [];
|
|
2875
3022
|
for (let i2 = 0; i2 < texts.length; i2++) {
|
|
2876
|
-
const cached = cache2.get(texts[i2]);
|
|
3023
|
+
const cached = cache2.get(cacheKey2(texts[i2]));
|
|
2877
3024
|
if (cached) {
|
|
2878
3025
|
results[i2] = cached;
|
|
2879
3026
|
} else {
|
|
@@ -2891,17 +3038,27 @@ var init_transformers_provider = __esm({
|
|
|
2891
3038
|
const vec = Array.from(allVecs[i2]);
|
|
2892
3039
|
const originalIdx = uncachedIndices[i2];
|
|
2893
3040
|
results[originalIdx] = vec;
|
|
2894
|
-
this.cacheSet(uncachedTexts[i2], vec);
|
|
3041
|
+
this.cacheSet(cacheKey2(uncachedTexts[i2]), vec);
|
|
2895
3042
|
}
|
|
2896
3043
|
}
|
|
2897
3044
|
return results;
|
|
2898
3045
|
}
|
|
2899
3046
|
cacheSet(key, value) {
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
3047
|
+
const incomingBytes = value.length * 8;
|
|
3048
|
+
if (incomingBytes > maxCachePayloadBytes2()) return;
|
|
3049
|
+
const existing = cache2.get(key);
|
|
3050
|
+
if (existing) cachePayloadBytes2 -= existing.length * 8;
|
|
3051
|
+
else {
|
|
3052
|
+
while (cache2.size >= MAX_CACHE_SIZE2 || cachePayloadBytes2 + incomingBytes > maxCachePayloadBytes2()) {
|
|
3053
|
+
const firstKey = cache2.keys().next().value;
|
|
3054
|
+
if (firstKey === void 0) break;
|
|
3055
|
+
const old = cache2.get(firstKey);
|
|
3056
|
+
cache2.delete(firstKey);
|
|
3057
|
+
if (old) cachePayloadBytes2 -= old.length * 8;
|
|
3058
|
+
}
|
|
2903
3059
|
}
|
|
2904
3060
|
cache2.set(key, value);
|
|
3061
|
+
cachePayloadBytes2 += incomingBytes;
|
|
2905
3062
|
}
|
|
2906
3063
|
};
|
|
2907
3064
|
}
|
|
@@ -2923,7 +3080,7 @@ __export(api_provider_exports, {
|
|
|
2923
3080
|
saveDiskCacheNow: () => saveDiskCacheNow,
|
|
2924
3081
|
seedApiEmbeddingCacheForTests: () => seedApiEmbeddingCacheForTests
|
|
2925
3082
|
});
|
|
2926
|
-
import { createHash as
|
|
3083
|
+
import { createHash as createHash3 } from "crypto";
|
|
2927
3084
|
import { createReadStream, createWriteStream, constants as fsConstants } from "fs";
|
|
2928
3085
|
import { access, readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, rename, stat, unlink } from "fs/promises";
|
|
2929
3086
|
import { join as join3 } from "path";
|
|
@@ -2950,7 +3107,7 @@ function cacheStatFile() {
|
|
|
2950
3107
|
function payloadBytes(vector) {
|
|
2951
3108
|
return vector.length * BYTES_PER_DIM;
|
|
2952
3109
|
}
|
|
2953
|
-
function
|
|
3110
|
+
function maxCachePayloadBytes3() {
|
|
2954
3111
|
const raw = process.env.MEMORIX_EMBEDDING_CACHE_MAX_BYTES;
|
|
2955
3112
|
if (raw) {
|
|
2956
3113
|
const parsed = Number.parseInt(raw, 10);
|
|
@@ -2960,7 +3117,7 @@ function maxCachePayloadBytes() {
|
|
|
2960
3117
|
}
|
|
2961
3118
|
function maxEntriesForDimensions(dimensions) {
|
|
2962
3119
|
const dim = Math.max(1, Math.floor(dimensions));
|
|
2963
|
-
const byBytes = Math.floor(
|
|
3120
|
+
const byBytes = Math.floor(maxCachePayloadBytes3() / (dim * BYTES_PER_DIM));
|
|
2964
3121
|
return Math.max(1, Math.min(MAX_CACHE_ENTRIES, byBytes));
|
|
2965
3122
|
}
|
|
2966
3123
|
function rememberDimensions(vector) {
|
|
@@ -2973,13 +3130,15 @@ function evictOldest() {
|
|
|
2973
3130
|
if (firstKey === void 0) return;
|
|
2974
3131
|
const old = cache3.get(firstKey);
|
|
2975
3132
|
cache3.delete(firstKey);
|
|
2976
|
-
if (old)
|
|
3133
|
+
if (old) cachePayloadBytes3 -= payloadBytes(old);
|
|
2977
3134
|
}
|
|
2978
3135
|
function evictToFit(incomingBytes, incomingDims) {
|
|
3136
|
+
if (incomingBytes > maxCachePayloadBytes3()) return false;
|
|
2979
3137
|
const limit2 = maxEntriesForDimensions(incomingDims);
|
|
2980
|
-
while (cache3.size > 0 && (cache3.size >= limit2 ||
|
|
3138
|
+
while (cache3.size > 0 && (cache3.size >= limit2 || cachePayloadBytes3 + incomingBytes > maxCachePayloadBytes3())) {
|
|
2981
3139
|
evictOldest();
|
|
2982
3140
|
}
|
|
3141
|
+
return true;
|
|
2983
3142
|
}
|
|
2984
3143
|
function isNumberArray(value) {
|
|
2985
3144
|
return Array.isArray(value) && value.every((entry) => typeof entry === "number");
|
|
@@ -3006,12 +3165,12 @@ function cacheInsert(hash4, value, dirty) {
|
|
|
3006
3165
|
const incoming = payloadBytes(value);
|
|
3007
3166
|
const existing = cache3.get(hash4);
|
|
3008
3167
|
if (existing) {
|
|
3009
|
-
|
|
3168
|
+
cachePayloadBytes3 -= payloadBytes(existing);
|
|
3010
3169
|
cache3.delete(hash4);
|
|
3011
3170
|
}
|
|
3012
|
-
evictToFit(incoming, value.length || cacheDimensions || DEFAULT_ASSUMED_DIMENSIONS);
|
|
3171
|
+
if (!evictToFit(incoming, value.length || cacheDimensions || DEFAULT_ASSUMED_DIMENSIONS)) return;
|
|
3013
3172
|
cache3.set(hash4, value);
|
|
3014
|
-
|
|
3173
|
+
cachePayloadBytes3 += incoming;
|
|
3015
3174
|
if (dirty) diskCacheDirty2 = true;
|
|
3016
3175
|
}
|
|
3017
3176
|
async function readCacheStat() {
|
|
@@ -3047,7 +3206,7 @@ function cacheNamespace(config) {
|
|
|
3047
3206
|
].join("|");
|
|
3048
3207
|
}
|
|
3049
3208
|
function textHash2(text2, namespace) {
|
|
3050
|
-
return
|
|
3209
|
+
return createHash3("sha256").update(`${namespace}\0${text2}`).digest("hex").slice(0, 16);
|
|
3051
3210
|
}
|
|
3052
3211
|
function inputIdentity(input, options = {}) {
|
|
3053
3212
|
return JSON.stringify({
|
|
@@ -3389,7 +3548,7 @@ function getApiEmbeddingDiskCacheLoadCountForTests() {
|
|
|
3389
3548
|
}
|
|
3390
3549
|
function resetApiEmbeddingCacheForTests() {
|
|
3391
3550
|
cache3.clear();
|
|
3392
|
-
|
|
3551
|
+
cachePayloadBytes3 = 0;
|
|
3393
3552
|
cacheDimensions = null;
|
|
3394
3553
|
diskCacheEntryCount = 0;
|
|
3395
3554
|
diskCacheLoaded = false;
|
|
@@ -3400,14 +3559,14 @@ function resetApiEmbeddingCacheForTests() {
|
|
|
3400
3559
|
}
|
|
3401
3560
|
function seedApiEmbeddingCacheForTests(entries) {
|
|
3402
3561
|
cache3.clear();
|
|
3403
|
-
|
|
3562
|
+
cachePayloadBytes3 = 0;
|
|
3404
3563
|
cacheDimensions = null;
|
|
3405
3564
|
for (const [key, value] of entries) cacheInsert(key, value, true);
|
|
3406
3565
|
diskCacheLoaded = true;
|
|
3407
3566
|
diskCacheDirty2 = true;
|
|
3408
3567
|
}
|
|
3409
3568
|
function getApiEmbeddingCachePayloadBytesForTests() {
|
|
3410
|
-
return
|
|
3569
|
+
return cachePayloadBytes3;
|
|
3411
3570
|
}
|
|
3412
3571
|
function getApiEmbeddingJsonlLineCountCallsForTests() {
|
|
3413
3572
|
return jsonlLineCountCalls;
|
|
@@ -3581,7 +3740,7 @@ function scheduleDiskSave() {
|
|
|
3581
3740
|
diskSaveTimer = null;
|
|
3582
3741
|
}, DISK_SAVE_DEBOUNCE_MS);
|
|
3583
3742
|
}
|
|
3584
|
-
function
|
|
3743
|
+
function cacheSet2(hash4, value) {
|
|
3585
3744
|
cacheInsert(hash4, value, true);
|
|
3586
3745
|
}
|
|
3587
3746
|
function resolveEnvEmbeddingApiKey() {
|
|
@@ -3701,7 +3860,7 @@ async function waitForRetry(waitMs, signal) {
|
|
|
3701
3860
|
abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
3702
3861
|
});
|
|
3703
3862
|
}
|
|
3704
|
-
var cache3, MAX_CACHE_ENTRIES, MAX_CACHE_PAYLOAD_BYTES, BYTES_PER_DIM, DEFAULT_ASSUMED_DIMENSIONS, MAX_MIGRATION_VALUE_BYTES,
|
|
3863
|
+
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;
|
|
3705
3864
|
var init_api_provider = __esm({
|
|
3706
3865
|
"src/embedding/api-provider.ts"() {
|
|
3707
3866
|
"use strict";
|
|
@@ -3713,7 +3872,7 @@ var init_api_provider = __esm({
|
|
|
3713
3872
|
BYTES_PER_DIM = 8;
|
|
3714
3873
|
DEFAULT_ASSUMED_DIMENSIONS = 4096;
|
|
3715
3874
|
MAX_MIGRATION_VALUE_BYTES = 16 * 1024 * 1024;
|
|
3716
|
-
|
|
3875
|
+
cachePayloadBytes3 = 0;
|
|
3717
3876
|
cacheDimensions = null;
|
|
3718
3877
|
diskCacheEntryCount = 0;
|
|
3719
3878
|
diskCacheDirty2 = false;
|
|
@@ -3898,7 +4057,7 @@ var init_api_provider = __esm({
|
|
|
3898
4057
|
} else {
|
|
3899
4058
|
embedding = await apiCall();
|
|
3900
4059
|
}
|
|
3901
|
-
|
|
4060
|
+
cacheSet2(hash4, embedding);
|
|
3902
4061
|
scheduleDiskSave();
|
|
3903
4062
|
return embedding;
|
|
3904
4063
|
}
|
|
@@ -3946,7 +4105,7 @@ var init_api_provider = __esm({
|
|
|
3946
4105
|
for (const item of response.data) {
|
|
3947
4106
|
const originalIdx = chunkIndices[item.index];
|
|
3948
4107
|
results[originalIdx] = item.embedding;
|
|
3949
|
-
|
|
4108
|
+
cacheSet2(textHash2(normalizedTexts[originalIdx], this.cacheKeyNamespace), item.embedding);
|
|
3950
4109
|
}
|
|
3951
4110
|
} catch (error) {
|
|
3952
4111
|
const providerLimit = parseBatchLimit(error);
|
|
@@ -4024,7 +4183,7 @@ var init_api_provider = __esm({
|
|
|
4024
4183
|
throw new Error(`Expected ${this.dimensions}d, got ${embedding.length}d; dimension mismatch`);
|
|
4025
4184
|
}
|
|
4026
4185
|
this.trackUsage(response);
|
|
4027
|
-
|
|
4186
|
+
cacheSet2(hash4, embedding);
|
|
4028
4187
|
scheduleDiskSave();
|
|
4029
4188
|
return embedding;
|
|
4030
4189
|
}
|
|
@@ -5407,6 +5566,7 @@ var init_provider2 = __esm({
|
|
|
5407
5566
|
openai: { baseUrl: "https://api.openai.com/v1", model: "gpt-4.1-nano" },
|
|
5408
5567
|
anthropic: { baseUrl: "https://api.anthropic.com/v1", model: "claude-3-5-haiku-latest" },
|
|
5409
5568
|
openrouter: { baseUrl: "https://openrouter.ai/api/v1", model: "openai/gpt-4.1-nano" },
|
|
5569
|
+
atlascloud: { baseUrl: "https://api.atlascloud.ai/v1", model: "deepseek-ai/deepseek-v3.2" },
|
|
5410
5570
|
custom: { baseUrl: "http://localhost:11434/v1", model: "llama3" }
|
|
5411
5571
|
};
|
|
5412
5572
|
currentConfig = null;
|
|
@@ -5670,6 +5830,7 @@ var init_sqlite_store = __esm({
|
|
|
5670
5830
|
init_sqlite_db();
|
|
5671
5831
|
init_sqlite_reliability();
|
|
5672
5832
|
init_sqlite_fts();
|
|
5833
|
+
init_file_lock();
|
|
5673
5834
|
SqliteBackend = class {
|
|
5674
5835
|
db = null;
|
|
5675
5836
|
dataDir = "";
|
|
@@ -5833,38 +5994,43 @@ var init_sqlite_store = __esm({
|
|
|
5833
5994
|
}
|
|
5834
5995
|
// ── Migration ────────────────────────────────────────────────────
|
|
5835
5996
|
async migrateFromJsonIfNeeded() {
|
|
5836
|
-
const count2 = this.db.prepare(`SELECT COUNT(*) AS cnt FROM observations`).get();
|
|
5837
|
-
if (count2.cnt > 0) return;
|
|
5838
5997
|
const jsonPath = path7.join(this.dataDir, "observations.json");
|
|
5839
5998
|
if (!fs4.existsSync(jsonPath)) return;
|
|
5840
|
-
|
|
5999
|
+
await withFileLock(this.dataDir, async () => {
|
|
6000
|
+
const count2 = this.db.prepare(`SELECT COUNT(*) AS cnt FROM observations`).get();
|
|
6001
|
+
if (count2.cnt > 0) return;
|
|
5841
6002
|
const raw = fs4.readFileSync(jsonPath, "utf-8");
|
|
5842
|
-
const
|
|
6003
|
+
const parsed = JSON.parse(raw);
|
|
6004
|
+
if (!Array.isArray(parsed)) {
|
|
6005
|
+
throw new Error("[memorix] observations.json migration refused: expected a JSON array");
|
|
6006
|
+
}
|
|
6007
|
+
const observations2 = parsed;
|
|
5843
6008
|
if (observations2.length === 0) return;
|
|
6009
|
+
if (observations2.some((obs) => !obs || !Number.isSafeInteger(obs.id) || obs.id < 1 || typeof obs.projectId !== "string")) {
|
|
6010
|
+
throw new Error("[memorix] observations.json migration refused: invalid observation record");
|
|
6011
|
+
}
|
|
5844
6012
|
console.error(`[memorix] Migrating ${observations2.length} observations from JSON to SQLite...`);
|
|
5845
6013
|
const insertMany = this.db.transaction((obsList) => {
|
|
5846
6014
|
for (const obs of obsList) {
|
|
5847
6015
|
this.stmtInsert.run(obsToRow(obs));
|
|
5848
6016
|
}
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
if (fs4.existsSync(counterPath)) {
|
|
5853
|
-
try {
|
|
6017
|
+
const counterPath = path7.join(this.dataDir, "counter.json");
|
|
6018
|
+
let counterNextId;
|
|
6019
|
+
if (fs4.existsSync(counterPath)) {
|
|
5854
6020
|
const counterData = JSON.parse(fs4.readFileSync(counterPath, "utf-8"));
|
|
5855
|
-
const
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
6021
|
+
const candidate = counterData.nextId ?? counterData.next_id;
|
|
6022
|
+
if (candidate !== void 0 && (!Number.isSafeInteger(candidate) || Number(candidate) < 1)) {
|
|
6023
|
+
throw new Error("[memorix] counter.json migration refused: nextId must be a positive integer");
|
|
6024
|
+
}
|
|
6025
|
+
counterNextId = candidate === void 0 ? void 0 : Number(candidate);
|
|
5859
6026
|
}
|
|
5860
|
-
|
|
5861
|
-
this.rawSaveIdCounter(Math.max(
|
|
5862
|
-
|
|
5863
|
-
|
|
6027
|
+
const maxId = Math.max(...obsList.map((obs) => obs.id));
|
|
6028
|
+
this.rawSaveIdCounter(Math.max(counterNextId ?? 1, maxId + 1));
|
|
6029
|
+
this.bumpGeneration();
|
|
6030
|
+
});
|
|
6031
|
+
insertMany(observations2);
|
|
5864
6032
|
console.error(`[memorix] Migration complete. ${observations2.length} observations now in SQLite.`);
|
|
5865
|
-
}
|
|
5866
|
-
console.error(`[memorix] JSON\u2192SQLite migration failed (non-fatal, data preserved in JSON): ${err}`);
|
|
5867
|
-
}
|
|
6033
|
+
});
|
|
5868
6034
|
}
|
|
5869
6035
|
// ── Public read ──────────────────────────────────────────────────
|
|
5870
6036
|
async loadAll() {
|
|
@@ -6164,7 +6330,7 @@ var init_obs_store = __esm({
|
|
|
6164
6330
|
});
|
|
6165
6331
|
|
|
6166
6332
|
// src/search/semantic-index.ts
|
|
6167
|
-
import { createHash as
|
|
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 =
|
|
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
|
|
8424
|
-
*
|
|
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
|
-
|
|
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
|
|
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
|
|
8965
|
+
return createHash5("sha256").update(JSON.stringify({
|
|
8795
8966
|
projectId: observation.projectId,
|
|
8796
8967
|
id: observation.id,
|
|
8797
8968
|
title: observation.title,
|
|
@@ -9221,13 +9392,13 @@ __export(workspace_exports, {
|
|
|
9221
9392
|
loadKnowledgeWorkspace: () => loadKnowledgeWorkspace,
|
|
9222
9393
|
resolveKnowledgeWorkspaceFile: () => resolveKnowledgeWorkspaceFile
|
|
9223
9394
|
});
|
|
9224
|
-
import { createHash as
|
|
9395
|
+
import { createHash as createHash6 } from "crypto";
|
|
9225
9396
|
import { execFile } from "child_process";
|
|
9226
9397
|
import { promises as fs6 } from "fs";
|
|
9227
9398
|
import path10 from "path";
|
|
9228
9399
|
import { promisify } from "util";
|
|
9229
9400
|
function hash(value) {
|
|
9230
|
-
return
|
|
9401
|
+
return createHash6("sha256").update(value).digest("hex");
|
|
9231
9402
|
}
|
|
9232
9403
|
function workspaceId(projectId, mode) {
|
|
9233
9404
|
return "workspace:" + hash(projectId + ":" + mode).slice(0, 24);
|
|
@@ -10362,14 +10533,14 @@ var init_types2 = __esm({
|
|
|
10362
10533
|
});
|
|
10363
10534
|
|
|
10364
10535
|
// src/media/asset-store.ts
|
|
10365
|
-
import { createHash as
|
|
10536
|
+
import { createHash as createHash7, randomUUID as randomUUID6 } from "crypto";
|
|
10366
10537
|
import { copyFile, lstat, mkdir as mkdir3, open, readFile as readFile3, readdir, rename as rename2, rm, stat as stat2, writeFile as writeFile3 } from "fs/promises";
|
|
10367
10538
|
import path11 from "path";
|
|
10368
10539
|
function mediaRoot(dataDir) {
|
|
10369
10540
|
return path11.resolve(dataDir, "media");
|
|
10370
10541
|
}
|
|
10371
10542
|
function projectStorageKey(projectId) {
|
|
10372
|
-
return
|
|
10543
|
+
return createHash7("sha256").update(projectId).digest("hex").slice(0, 16);
|
|
10373
10544
|
}
|
|
10374
10545
|
function validateUnderRoot(root, candidate) {
|
|
10375
10546
|
const resolved = path11.resolve(candidate);
|
|
@@ -10478,7 +10649,7 @@ async function importMediaBuffer(input) {
|
|
|
10478
10649
|
if (input.bytes.length === 0) throw new Error("Media import rejects empty payloads");
|
|
10479
10650
|
if (input.bytes.length > maxBytes) throw new Error(`Media payload is too large (${input.bytes.length} bytes; limit ${maxBytes})`);
|
|
10480
10651
|
const detected = detectMedia(input.bytes.subarray(0, 32));
|
|
10481
|
-
const sha256 =
|
|
10652
|
+
const sha256 = createHash7("sha256").update(input.bytes).digest("hex");
|
|
10482
10653
|
return importKnownMedia({
|
|
10483
10654
|
dataDir: input.dataDir,
|
|
10484
10655
|
projectId: input.projectId,
|
|
@@ -10496,7 +10667,7 @@ async function readMediaAsset(dataDir, asset, maxBytes = DEFAULT_MAX_MEDIA_BYTES
|
|
|
10496
10667
|
if (asset.byteSize > maxBytes) throw new Error(`Media asset exceeds read limit (${asset.byteSize} bytes; limit ${maxBytes})`);
|
|
10497
10668
|
const bytes = await readFile3(getMediaAssetPath(dataDir, asset));
|
|
10498
10669
|
if (bytes.length !== asset.byteSize) throw new Error(`Media asset size no longer matches metadata: ${asset.id}`);
|
|
10499
|
-
const sha256 =
|
|
10670
|
+
const sha256 = createHash7("sha256").update(bytes).digest("hex");
|
|
10500
10671
|
if (sha256 !== asset.sha256) throw new Error(`Media asset hash no longer matches metadata: ${asset.id}`);
|
|
10501
10672
|
return bytes;
|
|
10502
10673
|
}
|
|
@@ -69192,16 +69363,16 @@ var require_jwtaccess = __commonJS({
|
|
|
69192
69363
|
* @returns A string that returns the cached key.
|
|
69193
69364
|
*/
|
|
69194
69365
|
getCachedKey(url, scopes) {
|
|
69195
|
-
let
|
|
69366
|
+
let cacheKey3 = url;
|
|
69196
69367
|
if (scopes && Array.isArray(scopes) && scopes.length) {
|
|
69197
|
-
|
|
69368
|
+
cacheKey3 = url ? `${url}_${scopes.join("_")}` : `${scopes.join("_")}`;
|
|
69198
69369
|
} else if (typeof scopes === "string") {
|
|
69199
|
-
|
|
69370
|
+
cacheKey3 = url ? `${url}_${scopes}` : scopes;
|
|
69200
69371
|
}
|
|
69201
|
-
if (!
|
|
69372
|
+
if (!cacheKey3) {
|
|
69202
69373
|
throw Error("Scopes or url must be provided");
|
|
69203
69374
|
}
|
|
69204
|
-
return
|
|
69375
|
+
return cacheKey3;
|
|
69205
69376
|
}
|
|
69206
69377
|
/**
|
|
69207
69378
|
* Get a non-expired access token, after refreshing if necessary.
|
|
@@ -75747,7 +75918,7 @@ var require_websocket = __commonJS({
|
|
|
75747
75918
|
var http3 = __require("http");
|
|
75748
75919
|
var net = __require("net");
|
|
75749
75920
|
var tls = __require("tls");
|
|
75750
|
-
var { randomBytes, createHash:
|
|
75921
|
+
var { randomBytes, createHash: createHash17 } = __require("crypto");
|
|
75751
75922
|
var { Duplex, Readable: Readable2 } = __require("stream");
|
|
75752
75923
|
var { URL: URL2 } = __require("url");
|
|
75753
75924
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -76415,7 +76586,7 @@ var require_websocket = __commonJS({
|
|
|
76415
76586
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
76416
76587
|
return;
|
|
76417
76588
|
}
|
|
76418
|
-
const digest2 =
|
|
76589
|
+
const digest2 = createHash17("sha1").update(key + GUID).digest("base64");
|
|
76419
76590
|
if (res.headers["sec-websocket-accept"] !== digest2) {
|
|
76420
76591
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
76421
76592
|
return;
|
|
@@ -76787,7 +76958,7 @@ var require_websocket_server = __commonJS({
|
|
|
76787
76958
|
var EventEmitter = __require("events");
|
|
76788
76959
|
var http3 = __require("http");
|
|
76789
76960
|
var { Duplex } = __require("stream");
|
|
76790
|
-
var { createHash:
|
|
76961
|
+
var { createHash: createHash17 } = __require("crypto");
|
|
76791
76962
|
var extension3 = require_extension();
|
|
76792
76963
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
76793
76964
|
var subprotocol2 = require_subprotocol();
|
|
@@ -77094,7 +77265,7 @@ var require_websocket_server = __commonJS({
|
|
|
77094
77265
|
);
|
|
77095
77266
|
}
|
|
77096
77267
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
77097
|
-
const digest2 =
|
|
77268
|
+
const digest2 = createHash17("sha1").update(key + GUID).digest("base64");
|
|
77098
77269
|
const headers = [
|
|
77099
77270
|
"HTTP/1.1 101 Switching Protocols",
|
|
77100
77271
|
"Upgrade: websocket",
|
|
@@ -145673,9 +145844,9 @@ var init_long_term = __esm({
|
|
|
145673
145844
|
});
|
|
145674
145845
|
|
|
145675
145846
|
// src/codegraph/ids.ts
|
|
145676
|
-
import { createHash as
|
|
145847
|
+
import { createHash as createHash8 } from "crypto";
|
|
145677
145848
|
function digest(input) {
|
|
145678
|
-
return
|
|
145849
|
+
return createHash8("sha256").update(input).digest("hex").slice(0, 16);
|
|
145679
145850
|
}
|
|
145680
145851
|
function normalizeCodePath(path23) {
|
|
145681
145852
|
return path23.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+/g, "/");
|
|
@@ -146723,7 +146894,7 @@ var init_store = __esm({
|
|
|
146723
146894
|
|
|
146724
146895
|
// src/codegraph/code-state.ts
|
|
146725
146896
|
import { execFile as execFile2 } from "child_process";
|
|
146726
|
-
import { createHash as
|
|
146897
|
+
import { createHash as createHash9 } from "crypto";
|
|
146727
146898
|
import { promisify as promisify3 } from "util";
|
|
146728
146899
|
async function runGit(rootPath, args) {
|
|
146729
146900
|
try {
|
|
@@ -146752,7 +146923,7 @@ function changedPathCount(status) {
|
|
|
146752
146923
|
return count2;
|
|
146753
146924
|
}
|
|
146754
146925
|
function fingerprint(baseRevision, status) {
|
|
146755
|
-
return
|
|
146926
|
+
return createHash9("sha256").update(baseRevision ?? "").update("\0").update(status).digest("hex");
|
|
146756
146927
|
}
|
|
146757
146928
|
async function collectCodeStateSnapshot(input) {
|
|
146758
146929
|
const [revision, status] = await Promise.all([
|
|
@@ -146846,12 +147017,12 @@ var init_exclude3 = __esm({
|
|
|
146846
147017
|
});
|
|
146847
147018
|
|
|
146848
147019
|
// src/codegraph/semantic-provider.ts
|
|
146849
|
-
import { createHash as
|
|
147020
|
+
import { createHash as createHash10 } from "crypto";
|
|
146850
147021
|
import "fs";
|
|
146851
147022
|
import { resolve } from "path";
|
|
146852
147023
|
import ts from "typescript";
|
|
146853
147024
|
function hashText(value) {
|
|
146854
|
-
return
|
|
147025
|
+
return createHash10("sha256").update(value).digest("hex");
|
|
146855
147026
|
}
|
|
146856
147027
|
function canonicalPath(value) {
|
|
146857
147028
|
const normalized = resolve(value).replace(/\\/g, "/");
|
|
@@ -147196,11 +147367,11 @@ __export(lite_provider_exports, {
|
|
|
147196
147367
|
indexProjectLite: () => indexProjectLite,
|
|
147197
147368
|
refreshProjectLite: () => refreshProjectLite
|
|
147198
147369
|
});
|
|
147199
|
-
import { createHash as
|
|
147370
|
+
import { createHash as createHash11 } from "crypto";
|
|
147200
147371
|
import { existsSync as existsSync11, readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
|
|
147201
147372
|
import { join as join4, relative as relative2 } from "path";
|
|
147202
147373
|
function hashText2(text2) {
|
|
147203
|
-
return
|
|
147374
|
+
return createHash11("sha256").update(text2).digest("hex");
|
|
147204
147375
|
}
|
|
147205
147376
|
function extension2(path23) {
|
|
147206
147377
|
const index = path23.lastIndexOf(".");
|
|
@@ -147833,7 +148004,7 @@ var claim_store_exports = {};
|
|
|
147833
148004
|
__export(claim_store_exports, {
|
|
147834
148005
|
ClaimStore: () => ClaimStore
|
|
147835
148006
|
});
|
|
147836
|
-
import { createHash as
|
|
148007
|
+
import { createHash as createHash12, randomUUID as randomUUID12 } from "crypto";
|
|
147837
148008
|
function optionalText3(value) {
|
|
147838
148009
|
return typeof value === "string" && value ? value : void 0;
|
|
147839
148010
|
}
|
|
@@ -147886,7 +148057,7 @@ function rowToEvent3(row) {
|
|
|
147886
148057
|
};
|
|
147887
148058
|
}
|
|
147888
148059
|
function evidenceKey(input) {
|
|
147889
|
-
return
|
|
148060
|
+
return createHash12("sha256").update(JSON.stringify([
|
|
147890
148061
|
input.evidenceKind,
|
|
147891
148062
|
input.evidenceId,
|
|
147892
148063
|
input.relation,
|
|
@@ -148084,7 +148255,7 @@ __export(claims_exports, {
|
|
|
148084
148255
|
supersedeClaim: () => supersedeClaim,
|
|
148085
148256
|
writeClaim: () => writeClaim
|
|
148086
148257
|
});
|
|
148087
|
-
import { createHash as
|
|
148258
|
+
import { createHash as createHash13, randomUUID as randomUUID13 } from "crypto";
|
|
148088
148259
|
function compactText2(value, field) {
|
|
148089
148260
|
if (typeof value !== "string") throw new Error("Claim " + field + " must be text");
|
|
148090
148261
|
const sanitized = sanitizeCredentials(value).trim().replace(/\s+/g, " ");
|
|
@@ -148096,7 +148267,7 @@ function normalizedTerm(value) {
|
|
|
148096
148267
|
return compactText2(value, "identity").toLocaleLowerCase("en-US");
|
|
148097
148268
|
}
|
|
148098
148269
|
function hashIdentity(parts) {
|
|
148099
|
-
return
|
|
148270
|
+
return createHash13("sha256").update(parts.join(String.fromCharCode(31))).digest("hex");
|
|
148100
148271
|
}
|
|
148101
148272
|
function buildClaimIdentity(input) {
|
|
148102
148273
|
const subject = normalizedTerm(input.subject);
|
|
@@ -148337,7 +148508,7 @@ function supersedeClaim(store, input) {
|
|
|
148337
148508
|
});
|
|
148338
148509
|
}
|
|
148339
148510
|
function hashObservation(observation) {
|
|
148340
|
-
return
|
|
148511
|
+
return createHash13("sha256").update(JSON.stringify([
|
|
148341
148512
|
observation.title,
|
|
148342
148513
|
observation.narrative,
|
|
148343
148514
|
observation.facts,
|
|
@@ -148581,11 +148752,11 @@ var init_frontmatter = __esm({
|
|
|
148581
148752
|
});
|
|
148582
148753
|
|
|
148583
148754
|
// src/knowledge/markdown.ts
|
|
148584
|
-
import { createHash as
|
|
148755
|
+
import { createHash as createHash14 } from "crypto";
|
|
148585
148756
|
import { promises as fs10 } from "fs";
|
|
148586
148757
|
import path18 from "path";
|
|
148587
148758
|
function hashContent(content) {
|
|
148588
|
-
return
|
|
148759
|
+
return createHash14("sha256").update(content).digest("hex");
|
|
148589
148760
|
}
|
|
148590
148761
|
function stringField(data, key) {
|
|
148591
148762
|
const value = data[key];
|
|
@@ -148711,11 +148882,11 @@ __export(wiki_exports, {
|
|
|
148711
148882
|
lintKnowledgeWorkspace: () => lintKnowledgeWorkspace,
|
|
148712
148883
|
readKnowledgePage: () => readKnowledgePage
|
|
148713
148884
|
});
|
|
148714
|
-
import { createHash as
|
|
148885
|
+
import { createHash as createHash15 } from "crypto";
|
|
148715
148886
|
import { promises as fs11 } from "fs";
|
|
148716
148887
|
import path19 from "path";
|
|
148717
148888
|
function hash2(value) {
|
|
148718
|
-
return
|
|
148889
|
+
return createHash15("sha256").update(value).digest("hex");
|
|
148719
148890
|
}
|
|
148720
148891
|
function now() {
|
|
148721
148892
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -149572,11 +149743,11 @@ __export(workflows_exports, {
|
|
|
149572
149743
|
syncCanonicalWorkflows: () => syncCanonicalWorkflows,
|
|
149573
149744
|
writeCanonicalWorkflow: () => writeCanonicalWorkflow
|
|
149574
149745
|
});
|
|
149575
|
-
import { createHash as
|
|
149746
|
+
import { createHash as createHash16 } from "crypto";
|
|
149576
149747
|
import { promises as fs12 } from "fs";
|
|
149577
149748
|
import path20 from "path";
|
|
149578
149749
|
function hash3(value) {
|
|
149579
|
-
return
|
|
149750
|
+
return createHash16("sha256").update(value).digest("hex");
|
|
149580
149751
|
}
|
|
149581
149752
|
function now2() {
|
|
149582
149753
|
return (/* @__PURE__ */ new Date()).toISOString();
|