memorix 1.7.2 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +59 -1
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/assets/star-history-dark.svg +4 -4
- package/assets/star-history-light.svg +4 -4
- package/assets/star-history.json +47 -3
- package/dist/cli/index.js +1801 -254
- package/dist/dashboard/static/app.js +88 -4
- package/dist/dashboard/static/index.html +10 -0
- package/dist/dashboard/static/style.css +86 -0
- package/dist/index.js +1241 -224
- package/dist/maintenance-runner.js +972 -126
- package/dist/media-audio-runner.js +967 -121
- package/dist/media-video-runner.js +972 -126
- package/dist/memcode-runtime/CHANGELOG.md +59 -1
- package/dist/sdk.js +1240 -223
- package/dist/types.d.ts +8 -0
- package/dist/vector-backfill-runner.js +972 -126
- package/docs/1.2.4-PERSISTENT-MEMORY-DELIVERY.md +1 -1
- package/docs/1.8.0-RELEASE-CANDIDATE-SPEC.md +75 -0
- package/docs/API_REFERENCE.md +37 -1
- package/docs/ARCHITECTURE.md +1 -1
- package/docs/CONFIGURATION.md +57 -1
- package/docs/DASHBOARD.md +10 -0
- package/docs/DEVELOPMENT.md +3 -2
- package/docs/INTEGRATIONS.md +1 -1
- package/docs/PERFORMANCE.md +3 -1
- package/docs/README.md +11 -1
- package/docs/SETUP.md +2 -1
- package/package.json +1 -1
- package/plugins/antigravity/memorix/rules/memorix.md +1 -1
- package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
- package/plugins/claude/memorix/SKILL.md +1 -1
- package/plugins/claude/memorix/skills/memorix-memory/SKILL.md +2 -2
- package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
- package/plugins/codebuddy/memorix/skills/memorix-memory/SKILL.md +2 -2
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/codex/memorix/skills/memorix-memory/SKILL.md +2 -2
- package/plugins/copilot/memorix/plugin.json +1 -1
- package/plugins/copilot/memorix/skills/memorix-memory/SKILL.md +2 -2
- package/plugins/cursor/memorix/skills/memorix-memory/SKILL.md +2 -2
- package/plugins/gemini/memorix/GEMINI.md +1 -1
- package/plugins/gemini/memorix/gemini-extension.json +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/plugins/pi/memorix/skills/memorix-memory/SKILL.md +2 -2
- package/server.json +2 -2
- package/src/cli/capability-map.ts +2 -0
- package/src/cli/commands/config-migrate.ts +7 -0
- package/src/cli/commands/context.ts +11 -0
- package/src/cli/commands/doctor.ts +5 -1
- package/src/cli/commands/evidence.ts +56 -0
- package/src/cli/commands/feedback.ts +58 -0
- package/src/cli/commands/init.ts +17 -0
- package/src/cli/commands/resume.ts +2 -0
- package/src/cli/commands/serve-http.ts +201 -12
- package/src/cli/commands/status.ts +2 -0
- package/src/cli/fallback-budget.ts +59 -0
- package/src/cli/index.ts +5 -1
- package/src/compact/engine.ts +26 -1
- package/src/config/dotenv-loader.ts +17 -0
- package/src/config/resolved-config.ts +110 -12
- package/src/config/toml-loader.ts +8 -0
- package/src/config/yaml-loader.ts +9 -0
- package/src/dashboard/config-provenance.ts +17 -0
- package/src/dashboard/evidence.ts +63 -0
- package/src/dashboard/server.ts +93 -68
- package/src/dashboard/static/index.html +10 -0
- package/src/dashboard/static/style.css +86 -0
- package/src/hooks/installers/index.ts +1 -1
- package/src/hooks/official-skills.ts +3 -3
- package/src/hooks/rules/memorix-agent-rules.md +1 -1
- package/src/llm/provider.ts +33 -7
- package/src/memory/feedback-model.ts +4 -0
- package/src/memory/feedback.ts +220 -0
- package/src/memory/observations.ts +19 -0
- package/src/memory/retention.ts +38 -5
- package/src/multimodal/image-loader.ts +6 -3
- package/src/rerank/http-provider.ts +125 -0
- package/src/rerank/index.ts +81 -0
- package/src/rerank/policy.ts +88 -0
- package/src/server/mcp-binding-store.ts +79 -0
- package/src/server/mcp-diagnostics.ts +40 -0
- package/src/server/tool-profile.ts +4 -0
- package/src/server.ts +121 -1
- package/src/store/evidence-store.ts +261 -0
- package/src/store/orama-store.ts +79 -53
- package/src/store/sqlite-db.ts +104 -0
- package/src/types.ts +8 -0
|
@@ -338,7 +338,7 @@ function closeAllDatabases() {
|
|
|
338
338
|
_dbCache.delete(key);
|
|
339
339
|
}
|
|
340
340
|
}
|
|
341
|
-
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_INDEXES, SCHEMA_MIGRATIONS, _dbCache;
|
|
341
|
+
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;
|
|
342
342
|
var init_sqlite_db = __esm({
|
|
343
343
|
"src/store/sqlite-db.ts"() {
|
|
344
344
|
"use strict";
|
|
@@ -984,6 +984,79 @@ CREATE TABLE IF NOT EXISTS compaction_checkpoints (
|
|
|
984
984
|
created_at TEXT NOT NULL,
|
|
985
985
|
updated_at TEXT NOT NULL
|
|
986
986
|
);
|
|
987
|
+
`;
|
|
988
|
+
CREATE_EVIDENCE_CARDS_TABLE = `
|
|
989
|
+
CREATE TABLE IF NOT EXISTS evidence_cards (
|
|
990
|
+
id TEXT PRIMARY KEY,
|
|
991
|
+
project_id TEXT NOT NULL,
|
|
992
|
+
candidate_kind TEXT NOT NULL,
|
|
993
|
+
candidate_id TEXT NOT NULL,
|
|
994
|
+
title TEXT NOT NULL,
|
|
995
|
+
summary TEXT NOT NULL DEFAULT '',
|
|
996
|
+
entity_name TEXT,
|
|
997
|
+
source_kind TEXT NOT NULL,
|
|
998
|
+
source_ref TEXT NOT NULL,
|
|
999
|
+
locator TEXT,
|
|
1000
|
+
captured_hash TEXT,
|
|
1001
|
+
session_id TEXT,
|
|
1002
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
1003
|
+
verification TEXT NOT NULL DEFAULT 'unverified',
|
|
1004
|
+
freshness TEXT NOT NULL DEFAULT 'current',
|
|
1005
|
+
stale_reason TEXT,
|
|
1006
|
+
files_json TEXT NOT NULL DEFAULT '[]',
|
|
1007
|
+
related_entities_json TEXT NOT NULL DEFAULT '[]',
|
|
1008
|
+
created_at TEXT NOT NULL,
|
|
1009
|
+
updated_at TEXT NOT NULL,
|
|
1010
|
+
UNIQUE(project_id, candidate_kind, candidate_id)
|
|
1011
|
+
);
|
|
1012
|
+
`;
|
|
1013
|
+
CREATE_EVIDENCE_CARD_EVENTS_TABLE = `
|
|
1014
|
+
CREATE TABLE IF NOT EXISTS evidence_card_events (
|
|
1015
|
+
id TEXT PRIMARY KEY,
|
|
1016
|
+
project_id TEXT NOT NULL,
|
|
1017
|
+
card_id TEXT NOT NULL,
|
|
1018
|
+
kind TEXT NOT NULL,
|
|
1019
|
+
detail TEXT,
|
|
1020
|
+
created_at TEXT NOT NULL,
|
|
1021
|
+
FOREIGN KEY (card_id) REFERENCES evidence_cards(id) ON DELETE CASCADE
|
|
1022
|
+
);
|
|
1023
|
+
`;
|
|
1024
|
+
CREATE_MEMORY_FEEDBACK_STATES_TABLE = `
|
|
1025
|
+
CREATE TABLE IF NOT EXISTS memory_feedback_states (
|
|
1026
|
+
project_id TEXT NOT NULL,
|
|
1027
|
+
candidate_kind TEXT NOT NULL,
|
|
1028
|
+
candidate_id TEXT NOT NULL,
|
|
1029
|
+
weight REAL NOT NULL DEFAULT 1.0,
|
|
1030
|
+
lifecycle_status TEXT NOT NULL DEFAULT 'active',
|
|
1031
|
+
updated_at TEXT NOT NULL,
|
|
1032
|
+
PRIMARY KEY (project_id, candidate_kind, candidate_id)
|
|
1033
|
+
);
|
|
1034
|
+
`;
|
|
1035
|
+
CREATE_MEMORY_FEEDBACK_EVENTS_TABLE = `
|
|
1036
|
+
CREATE TABLE IF NOT EXISTS memory_feedback_events (
|
|
1037
|
+
id TEXT PRIMARY KEY,
|
|
1038
|
+
project_id TEXT NOT NULL,
|
|
1039
|
+
candidate_kind TEXT NOT NULL,
|
|
1040
|
+
candidate_id TEXT NOT NULL,
|
|
1041
|
+
signal TEXT NOT NULL,
|
|
1042
|
+
actor TEXT,
|
|
1043
|
+
note TEXT,
|
|
1044
|
+
source_ref TEXT NOT NULL,
|
|
1045
|
+
target_event_id TEXT,
|
|
1046
|
+
delta REAL NOT NULL DEFAULT 0,
|
|
1047
|
+
observed_at TEXT NOT NULL
|
|
1048
|
+
);
|
|
1049
|
+
`;
|
|
1050
|
+
CREATE_MCP_BINDINGS_TABLE = `
|
|
1051
|
+
CREATE TABLE IF NOT EXISTS mcp_bindings (
|
|
1052
|
+
handle_id TEXT PRIMARY KEY,
|
|
1053
|
+
project_id TEXT NOT NULL,
|
|
1054
|
+
project_root TEXT NOT NULL,
|
|
1055
|
+
data_dir TEXT NOT NULL,
|
|
1056
|
+
created_at TEXT NOT NULL,
|
|
1057
|
+
last_used_at TEXT NOT NULL,
|
|
1058
|
+
expires_at TEXT
|
|
1059
|
+
);
|
|
987
1060
|
`;
|
|
988
1061
|
CREATE_INDEXES = `
|
|
989
1062
|
CREATE INDEX IF NOT EXISTS idx_observations_projectId ON observations(projectId);
|
|
@@ -1046,6 +1119,12 @@ CREATE INDEX IF NOT EXISTS idx_maintenance_targets_updated ON maintenance_target
|
|
|
1046
1119
|
CREATE INDEX IF NOT EXISTS idx_compaction_checkpoints_project_recent ON compaction_checkpoints(project_id, status, completed_at DESC, pre_captured_at DESC);
|
|
1047
1120
|
CREATE INDEX IF NOT EXISTS idx_compaction_checkpoints_session_pending ON compaction_checkpoints(project_id, session_id, agent, phase, status, pre_captured_at DESC);
|
|
1048
1121
|
CREATE INDEX IF NOT EXISTS idx_compaction_checkpoints_source ON compaction_checkpoints(project_id, source_key);
|
|
1122
|
+
CREATE INDEX IF NOT EXISTS idx_evidence_cards_project ON evidence_cards(project_id, status, updated_at DESC);
|
|
1123
|
+
CREATE INDEX IF NOT EXISTS idx_evidence_cards_candidate ON evidence_cards(project_id, candidate_kind, candidate_id);
|
|
1124
|
+
CREATE INDEX IF NOT EXISTS idx_evidence_card_events_card ON evidence_card_events(card_id, created_at);
|
|
1125
|
+
CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC);
|
|
1126
|
+
CREATE INDEX IF NOT EXISTS idx_memory_feedback_events_candidate ON memory_feedback_events(project_id, candidate_kind, candidate_id, observed_at DESC);
|
|
1127
|
+
CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC);
|
|
1049
1128
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
1050
1129
|
ON maintenance_jobs(project_id, kind, dedupe_key)
|
|
1051
1130
|
WHERE status IN ('pending', 'running', 'retry');
|
|
@@ -1201,6 +1280,22 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
|
1201
1280
|
}
|
|
1202
1281
|
db2.exec("CREATE INDEX IF NOT EXISTS idx_media_jobs_source_asset ON media_jobs(project_id, source_asset_id, status)");
|
|
1203
1282
|
}
|
|
1283
|
+
},
|
|
1284
|
+
{
|
|
1285
|
+
id: "1.8-context-control-plane",
|
|
1286
|
+
apply: (db2) => {
|
|
1287
|
+
db2.exec(CREATE_EVIDENCE_CARDS_TABLE);
|
|
1288
|
+
db2.exec(CREATE_EVIDENCE_CARD_EVENTS_TABLE);
|
|
1289
|
+
db2.exec(CREATE_MEMORY_FEEDBACK_STATES_TABLE);
|
|
1290
|
+
db2.exec(CREATE_MEMORY_FEEDBACK_EVENTS_TABLE);
|
|
1291
|
+
db2.exec(CREATE_MCP_BINDINGS_TABLE);
|
|
1292
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_evidence_cards_project ON evidence_cards(project_id, status, updated_at DESC)");
|
|
1293
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_evidence_cards_candidate ON evidence_cards(project_id, candidate_kind, candidate_id)");
|
|
1294
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_evidence_card_events_card ON evidence_card_events(card_id, created_at)");
|
|
1295
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC)");
|
|
1296
|
+
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)");
|
|
1297
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC)");
|
|
1298
|
+
}
|
|
1204
1299
|
}
|
|
1205
1300
|
];
|
|
1206
1301
|
_dbCache = /* @__PURE__ */ new Map();
|
|
@@ -1246,6 +1341,8 @@ function loadEnvFile(filePath) {
|
|
|
1246
1341
|
const parsed = parse(readFileSync2(filePath, "utf-8"));
|
|
1247
1342
|
for (const [key, value] of Object.entries(parsed)) {
|
|
1248
1343
|
if (!(key in process.env)) {
|
|
1344
|
+
loadedEnvKeys.add(key);
|
|
1345
|
+
loadedEnvValues.set(key, value);
|
|
1249
1346
|
process.env[key] = value;
|
|
1250
1347
|
injectedKeys.add(key);
|
|
1251
1348
|
}
|
|
@@ -1258,6 +1355,8 @@ function loadDotenv(projectRoot, options = {}) {
|
|
|
1258
1355
|
resetDotenv();
|
|
1259
1356
|
}
|
|
1260
1357
|
loadedEnvFiles.length = 0;
|
|
1358
|
+
loadedEnvKeys.clear();
|
|
1359
|
+
loadedEnvValues.clear();
|
|
1261
1360
|
if (projectRoot) {
|
|
1262
1361
|
loadEnvFile(getProjectDotenvPath(projectRoot));
|
|
1263
1362
|
}
|
|
@@ -1273,11 +1372,12 @@ function resetDotenv() {
|
|
|
1273
1372
|
dotenvLoaded = false;
|
|
1274
1373
|
dotenvProjectRoot = null;
|
|
1275
1374
|
loadedEnvFiles.length = 0;
|
|
1375
|
+
loadedEnvKeys.clear();
|
|
1276
1376
|
}
|
|
1277
1377
|
function getLoadedEnvFiles() {
|
|
1278
1378
|
return loadedEnvFiles;
|
|
1279
1379
|
}
|
|
1280
|
-
var dotenvLoaded, dotenvProjectRoot, loadedEnvFiles, injectedKeys;
|
|
1380
|
+
var dotenvLoaded, dotenvProjectRoot, loadedEnvFiles, loadedEnvKeys, loadedEnvValues, injectedKeys;
|
|
1281
1381
|
var init_dotenv_loader = __esm({
|
|
1282
1382
|
"src/config/dotenv-loader.ts"() {
|
|
1283
1383
|
"use strict";
|
|
@@ -1286,6 +1386,8 @@ var init_dotenv_loader = __esm({
|
|
|
1286
1386
|
dotenvLoaded = false;
|
|
1287
1387
|
dotenvProjectRoot = null;
|
|
1288
1388
|
loadedEnvFiles = [];
|
|
1389
|
+
loadedEnvKeys = /* @__PURE__ */ new Set();
|
|
1390
|
+
loadedEnvValues = /* @__PURE__ */ new Map();
|
|
1289
1391
|
injectedKeys = /* @__PURE__ */ new Set();
|
|
1290
1392
|
}
|
|
1291
1393
|
});
|
|
@@ -1327,6 +1429,7 @@ function loadYamlConfig(projectRoot) {
|
|
|
1327
1429
|
llm: { ...userConfig.llm, ...projectConfig.llm },
|
|
1328
1430
|
agent: { ...userConfig.agent, ...projectConfig.agent },
|
|
1329
1431
|
embedding: { ...userConfig.embedding, ...projectConfig.embedding },
|
|
1432
|
+
rerank: { ...userConfig.rerank, ...projectConfig.rerank },
|
|
1330
1433
|
git: { ...userConfig.git, ...projectConfig.git },
|
|
1331
1434
|
codegraph: { ...userConfig.codegraph, ...projectConfig.codegraph },
|
|
1332
1435
|
behavior: { ...userConfig.behavior, ...projectConfig.behavior },
|
|
@@ -1563,6 +1666,7 @@ function mergeTomlConfig(base, override) {
|
|
|
1563
1666
|
llm: { ...base.memory?.llm, ...override.memory?.llm }
|
|
1564
1667
|
},
|
|
1565
1668
|
embedding: { ...base.embedding, ...override.embedding },
|
|
1669
|
+
rerank: { ...base.rerank, ...override.rerank },
|
|
1566
1670
|
hooks: { ...base.hooks, ...override.hooks },
|
|
1567
1671
|
git: { ...base.git, ...override.git },
|
|
1568
1672
|
codegraph: { ...base.codegraph, ...override.codegraph },
|
|
@@ -1659,6 +1763,7 @@ __export(resolved_config_exports, {
|
|
|
1659
1763
|
getResolvedConfigForCwd: () => getResolvedConfigForCwd,
|
|
1660
1764
|
getResolvedEmbeddingLane: () => getResolvedEmbeddingLane,
|
|
1661
1765
|
getResolvedMemoryLane: () => getResolvedMemoryLane,
|
|
1766
|
+
getResolvedRerankLane: () => getResolvedRerankLane,
|
|
1662
1767
|
resetResolvedConfigCache: () => resetResolvedConfigCache
|
|
1663
1768
|
});
|
|
1664
1769
|
import { homedir as homedir5 } from "os";
|
|
@@ -1691,6 +1796,16 @@ function getResolvedConfig(options = {}) {
|
|
|
1691
1796
|
legacy.llm?.baseUrl
|
|
1692
1797
|
);
|
|
1693
1798
|
const openRouterMemoryLlmApiKey = isOpenRouterMemoryLane(memoryLlmProvider, memoryLlmBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
|
|
1799
|
+
const memoryLlmApiKey = first(
|
|
1800
|
+
process.env.MEMORIX_LLM_API_KEY,
|
|
1801
|
+
process.env.MEMORIX_API_KEY,
|
|
1802
|
+
toml.memory?.llm?.api_key,
|
|
1803
|
+
yaml.llm?.apiKey,
|
|
1804
|
+
legacy.llm?.apiKey,
|
|
1805
|
+
process.env.OPENAI_API_KEY,
|
|
1806
|
+
process.env.ANTHROPIC_API_KEY,
|
|
1807
|
+
openRouterMemoryLlmApiKey
|
|
1808
|
+
);
|
|
1694
1809
|
const resolved = {
|
|
1695
1810
|
agent: {
|
|
1696
1811
|
provider: first(
|
|
@@ -1731,16 +1846,7 @@ function getResolvedConfig(options = {}) {
|
|
|
1731
1846
|
provider: memoryLlmProvider,
|
|
1732
1847
|
model: memoryLlmModel,
|
|
1733
1848
|
baseUrl: memoryLlmBaseUrl,
|
|
1734
|
-
apiKey:
|
|
1735
|
-
process.env.MEMORIX_LLM_API_KEY,
|
|
1736
|
-
process.env.MEMORIX_API_KEY,
|
|
1737
|
-
toml.memory?.llm?.api_key,
|
|
1738
|
-
yaml.llm?.apiKey,
|
|
1739
|
-
legacy.llm?.apiKey,
|
|
1740
|
-
process.env.OPENAI_API_KEY,
|
|
1741
|
-
process.env.ANTHROPIC_API_KEY,
|
|
1742
|
-
openRouterMemoryLlmApiKey
|
|
1743
|
-
)
|
|
1849
|
+
apiKey: memoryLlmApiKey
|
|
1744
1850
|
}
|
|
1745
1851
|
},
|
|
1746
1852
|
embedding: {
|
|
@@ -1750,6 +1856,12 @@ function getResolvedConfig(options = {}) {
|
|
|
1750
1856
|
apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey),
|
|
1751
1857
|
dimensions: firstNumber(parseNumber(process.env.MEMORIX_EMBEDDING_DIMENSIONS), toml.embedding?.dimensions, yaml.embedding?.dimensions, legacy.embeddingApi?.dimensions)
|
|
1752
1858
|
},
|
|
1859
|
+
rerank: resolveRerankLane({
|
|
1860
|
+
toml,
|
|
1861
|
+
yaml,
|
|
1862
|
+
memoryLlmApiKey,
|
|
1863
|
+
memoryLlmBaseUrl
|
|
1864
|
+
}),
|
|
1753
1865
|
git: {
|
|
1754
1866
|
autoHook: firstBool(toml.git?.auto_hook, yaml.git?.autoHook),
|
|
1755
1867
|
ingestOnCommit: firstBool(toml.git?.ingest_on_commit, yaml.git?.ingestOnCommit),
|
|
@@ -1819,6 +1931,9 @@ function getResolvedMemoryLane(options = {}) {
|
|
|
1819
1931
|
function getResolvedEmbeddingLane(options = {}) {
|
|
1820
1932
|
return getResolvedConfig(options).embedding;
|
|
1821
1933
|
}
|
|
1934
|
+
function getResolvedRerankLane(options = {}) {
|
|
1935
|
+
return getResolvedConfig(options).rerank;
|
|
1936
|
+
}
|
|
1822
1937
|
function resetResolvedConfigCache() {
|
|
1823
1938
|
}
|
|
1824
1939
|
function first(...values) {
|
|
@@ -1861,6 +1976,10 @@ function getEnvSourceNames() {
|
|
|
1861
1976
|
"MEMORIX_EMBEDDING_BASE_URL",
|
|
1862
1977
|
"MEMORIX_EMBEDDING_MODEL",
|
|
1863
1978
|
"MEMORIX_EMBEDDING_DIMENSIONS",
|
|
1979
|
+
"MEMORIX_RERANK_PROVIDER",
|
|
1980
|
+
"MEMORIX_RERANK_MODEL",
|
|
1981
|
+
"MEMORIX_RERANK_BASE_URL",
|
|
1982
|
+
"MEMORIX_RERANK_API_KEY",
|
|
1864
1983
|
"MEMORIX_CODEGRAPH_EXTERNAL_CONTEXT",
|
|
1865
1984
|
"MEMORIX_CODEGRAPH_EXTERNAL_COMMAND",
|
|
1866
1985
|
"MEMORIX_CODEGRAPH_EXTERNAL_TIMEOUT_MS",
|
|
@@ -1884,6 +2003,63 @@ function normalizeExternalContext(value) {
|
|
|
1884
2003
|
if (normalized === "auto" || normalized === "off") return normalized;
|
|
1885
2004
|
return void 0;
|
|
1886
2005
|
}
|
|
2006
|
+
function normalizeRerankProvider(value) {
|
|
2007
|
+
const normalized = value?.trim().toLowerCase();
|
|
2008
|
+
if (normalized === "http") return "http";
|
|
2009
|
+
return "off";
|
|
2010
|
+
}
|
|
2011
|
+
function resolveRerankLane(args) {
|
|
2012
|
+
const provider2 = normalizeRerankProvider(first(
|
|
2013
|
+
process.env.MEMORIX_RERANK_PROVIDER,
|
|
2014
|
+
args.toml.rerank?.provider,
|
|
2015
|
+
args.yaml.rerank?.provider,
|
|
2016
|
+
"off"
|
|
2017
|
+
));
|
|
2018
|
+
const model = first(
|
|
2019
|
+
process.env.MEMORIX_RERANK_MODEL,
|
|
2020
|
+
args.toml.rerank?.model,
|
|
2021
|
+
args.yaml.rerank?.model
|
|
2022
|
+
);
|
|
2023
|
+
const explicitBaseUrl = first(
|
|
2024
|
+
process.env.MEMORIX_RERANK_BASE_URL,
|
|
2025
|
+
args.toml.rerank?.base_url,
|
|
2026
|
+
args.yaml.rerank?.baseUrl
|
|
2027
|
+
);
|
|
2028
|
+
const baseUrl = provider2 === "http" ? first(explicitBaseUrl, args.memoryLlmBaseUrl) : explicitBaseUrl;
|
|
2029
|
+
const dedicatedApiKey = first(
|
|
2030
|
+
process.env.MEMORIX_RERANK_API_KEY,
|
|
2031
|
+
args.toml.rerank?.api_key,
|
|
2032
|
+
args.yaml.rerank?.apiKey
|
|
2033
|
+
);
|
|
2034
|
+
const sameEndpoint = provider2 === "http" && sameTrustedEndpoint(baseUrl, args.memoryLlmBaseUrl);
|
|
2035
|
+
const inheritedApiKey = sameEndpoint ? args.memoryLlmApiKey : void 0;
|
|
2036
|
+
const apiKey = first(dedicatedApiKey, inheritedApiKey);
|
|
2037
|
+
const canSendRequest = provider2 === "http" && Boolean(baseUrl) && (Boolean(apiKey) || !args.memoryLlmApiKey || sameEndpoint);
|
|
2038
|
+
return { provider: provider2, model, baseUrl, apiKey, canSendRequest };
|
|
2039
|
+
}
|
|
2040
|
+
function sameTrustedEndpoint(left, right) {
|
|
2041
|
+
const a = normalizeTrustedEndpoint(left);
|
|
2042
|
+
const b = normalizeTrustedEndpoint(right);
|
|
2043
|
+
return Boolean(a && b && a === b);
|
|
2044
|
+
}
|
|
2045
|
+
function normalizeTrustedEndpoint(value) {
|
|
2046
|
+
const trimmed = value?.trim();
|
|
2047
|
+
if (!trimmed) return void 0;
|
|
2048
|
+
try {
|
|
2049
|
+
const url = new URL(trimmed);
|
|
2050
|
+
const protocol = url.protocol.toLowerCase();
|
|
2051
|
+
const hostname = url.hostname.toLowerCase();
|
|
2052
|
+
const port = url.port;
|
|
2053
|
+
let pathname = url.pathname.replace(/\/+$/, "");
|
|
2054
|
+
if (pathname.toLowerCase().endsWith("/rerank")) {
|
|
2055
|
+
pathname = pathname.slice(0, -"/rerank".length).replace(/\/+$/, "");
|
|
2056
|
+
}
|
|
2057
|
+
return `${protocol}//${hostname}${port ? `:${port}` : ""}${pathname}`;
|
|
2058
|
+
} catch {
|
|
2059
|
+
const fallback = trimmed.replace(/\/+$/, "").replace(/\/rerank$/i, "").replace(/\/+$/, "");
|
|
2060
|
+
return fallback.toLowerCase() || void 0;
|
|
2061
|
+
}
|
|
2062
|
+
}
|
|
1887
2063
|
var init_resolved_config = __esm({
|
|
1888
2064
|
"src/config/resolved-config.ts"() {
|
|
1889
2065
|
"use strict";
|
|
@@ -2020,9 +2196,27 @@ __export(provider_exports, {
|
|
|
2020
2196
|
getLLMConfig: () => getLLMConfig,
|
|
2021
2197
|
initLLM: () => initLLM,
|
|
2022
2198
|
isLLMEnabled: () => isLLMEnabled,
|
|
2199
|
+
normalizeOpenAICompatibleBaseUrl: () => normalizeOpenAICompatibleBaseUrl,
|
|
2023
2200
|
parseLLMTimeoutMs: () => parseLLMTimeoutMs,
|
|
2024
2201
|
setLLMConfig: () => setLLMConfig
|
|
2025
2202
|
});
|
|
2203
|
+
function normalizeOpenAICompatibleBaseUrl(baseUrl) {
|
|
2204
|
+
const base = baseUrl.trim().replace(/\/+$/, "");
|
|
2205
|
+
if (!base) return base;
|
|
2206
|
+
let pathname = "";
|
|
2207
|
+
try {
|
|
2208
|
+
pathname = new URL(base).pathname.replace(/\/+$/, "");
|
|
2209
|
+
} catch {
|
|
2210
|
+
pathname = base.split(/[?#]/, 1)[0].replace(/\/+$/, "");
|
|
2211
|
+
}
|
|
2212
|
+
const lastSegment = pathname.split("/").filter(Boolean).at(-1);
|
|
2213
|
+
if (lastSegment && OPENAI_API_VERSION_SEGMENT.test(lastSegment)) {
|
|
2214
|
+
return base;
|
|
2215
|
+
}
|
|
2216
|
+
const queryOrHash = base.match(/[?#].*$/)?.[0] ?? "";
|
|
2217
|
+
const pathWithoutQuery = base.slice(0, base.length - queryOrHash.length).replace(/\/+$/, "");
|
|
2218
|
+
return `${pathWithoutQuery}/v1${queryOrHash}`;
|
|
2219
|
+
}
|
|
2026
2220
|
function parseLLMTimeoutMs(raw) {
|
|
2027
2221
|
if (raw === void 0 || raw.trim() === "") return LLM_TIMEOUT_DEFAULT_MS;
|
|
2028
2222
|
const parsed = Number(raw);
|
|
@@ -2126,8 +2320,7 @@ async function callLLM(systemPrompt, userMessage, signal) {
|
|
|
2126
2320
|
}
|
|
2127
2321
|
async function callOpenAICompatible(systemPrompt, userMessage, signal) {
|
|
2128
2322
|
const config = currentConfig;
|
|
2129
|
-
|
|
2130
|
-
if (!base.endsWith("/v1")) base += "/v1";
|
|
2323
|
+
const base = normalizeOpenAICompatibleBaseUrl(config.baseUrl);
|
|
2131
2324
|
const url = `${base}/chat/completions`;
|
|
2132
2325
|
const fetchSignal = signal ? AbortSignal.any([signal, AbortSignal.timeout(LLM_CALL_TIMEOUT_MS)]) : AbortSignal.timeout(LLM_CALL_TIMEOUT_MS);
|
|
2133
2326
|
const response = await fetch(url, {
|
|
@@ -2206,8 +2399,7 @@ async function callLLMWithTools(messages, tools, signal) {
|
|
|
2206
2399
|
}
|
|
2207
2400
|
async function callOpenAIWithTools(messages, tools, signal) {
|
|
2208
2401
|
const config = currentConfig;
|
|
2209
|
-
|
|
2210
|
-
if (!base.endsWith("/v1")) base += "/v1";
|
|
2402
|
+
const base = normalizeOpenAICompatibleBaseUrl(config.baseUrl);
|
|
2211
2403
|
const url = `${base}/chat/completions`;
|
|
2212
2404
|
const openaiMessages = messages.map((msg) => {
|
|
2213
2405
|
if (msg.role === "tool") {
|
|
@@ -2357,8 +2549,7 @@ async function callAnthropicWithTools(messages, tools, signal) {
|
|
|
2357
2549
|
}
|
|
2358
2550
|
async function* callOpenAIWithToolsStream(messages, tools) {
|
|
2359
2551
|
const config = currentConfig;
|
|
2360
|
-
|
|
2361
|
-
if (!base.endsWith("/v1")) base += "/v1";
|
|
2552
|
+
const base = normalizeOpenAICompatibleBaseUrl(config.baseUrl);
|
|
2362
2553
|
const url = `${base}/chat/completions`;
|
|
2363
2554
|
const openaiMessages = messages.map((msg) => {
|
|
2364
2555
|
if (msg.role === "tool") {
|
|
@@ -2606,7 +2797,7 @@ async function* callAnthropicWithToolsStream(messages, tools) {
|
|
|
2606
2797
|
}
|
|
2607
2798
|
};
|
|
2608
2799
|
}
|
|
2609
|
-
var LLM_TIMEOUT_DEFAULT_MS, LLM_TIMEOUT_MIN_MS, LLM_TIMEOUT_MAX_MS, MAX_LLM_RESPONSE_BYTES, LLM_CALL_TIMEOUT_MS, PROVIDER_DEFAULTS, currentConfig;
|
|
2800
|
+
var LLM_TIMEOUT_DEFAULT_MS, LLM_TIMEOUT_MIN_MS, LLM_TIMEOUT_MAX_MS, MAX_LLM_RESPONSE_BYTES, OPENAI_API_VERSION_SEGMENT, LLM_CALL_TIMEOUT_MS, PROVIDER_DEFAULTS, currentConfig;
|
|
2610
2801
|
var init_provider = __esm({
|
|
2611
2802
|
"src/llm/provider.ts"() {
|
|
2612
2803
|
"use strict";
|
|
@@ -2616,6 +2807,7 @@ var init_provider = __esm({
|
|
|
2616
2807
|
LLM_TIMEOUT_MIN_MS = 1e3;
|
|
2617
2808
|
LLM_TIMEOUT_MAX_MS = 3e5;
|
|
2618
2809
|
MAX_LLM_RESPONSE_BYTES = 2 * 1024 * 1024;
|
|
2810
|
+
OPENAI_API_VERSION_SEGMENT = /^v\d+(?:[a-z][a-z0-9-]*)?$/i;
|
|
2619
2811
|
LLM_CALL_TIMEOUT_MS = parseLLMTimeoutMs(process.env.MEMORIX_LLM_TIMEOUT_MS);
|
|
2620
2812
|
PROVIDER_DEFAULTS = {
|
|
2621
2813
|
openai: { baseUrl: "https://api.openai.com/v1", model: "gpt-4.1-nano" },
|
|
@@ -5544,6 +5736,48 @@ Rules:
|
|
|
5544
5736
|
}
|
|
5545
5737
|
});
|
|
5546
5738
|
|
|
5739
|
+
// src/rerank/policy.ts
|
|
5740
|
+
function parseRerankTimeoutMs(raw) {
|
|
5741
|
+
const value = raw?.trim();
|
|
5742
|
+
if (!value) return DEFAULT_RERANK_TIMEOUT_MS;
|
|
5743
|
+
const parsed = Number(value);
|
|
5744
|
+
if (!Number.isInteger(parsed) || Number.isNaN(parsed)) {
|
|
5745
|
+
console.warn(
|
|
5746
|
+
`[memorix] MEMORIX_RERANK_TIMEOUT_MS="${raw}" is invalid (must be a positive integer between ${RERANK_TIMEOUT_MIN_MS}-${RERANK_TIMEOUT_MAX_MS}ms). Using default ${DEFAULT_RERANK_TIMEOUT_MS}ms.`
|
|
5747
|
+
);
|
|
5748
|
+
return DEFAULT_RERANK_TIMEOUT_MS;
|
|
5749
|
+
}
|
|
5750
|
+
if (parsed < RERANK_TIMEOUT_MIN_MS) return RERANK_TIMEOUT_MIN_MS;
|
|
5751
|
+
if (parsed > RERANK_TIMEOUT_MAX_MS) return RERANK_TIMEOUT_MAX_MS;
|
|
5752
|
+
return parsed;
|
|
5753
|
+
}
|
|
5754
|
+
function resolveRerankTimeoutMs(explicitTimeoutMs) {
|
|
5755
|
+
if (typeof explicitTimeoutMs === "number" && Number.isFinite(explicitTimeoutMs) && explicitTimeoutMs > 0) {
|
|
5756
|
+
return explicitTimeoutMs;
|
|
5757
|
+
}
|
|
5758
|
+
return parseRerankTimeoutMs(process.env.MEMORIX_RERANK_TIMEOUT_MS);
|
|
5759
|
+
}
|
|
5760
|
+
function shouldAttemptHttpRerank(input) {
|
|
5761
|
+
return input.quality === "thorough" && input.hasQuery && input.candidateCount >= MIN_RERANK_CANDIDATES;
|
|
5762
|
+
}
|
|
5763
|
+
function shouldAttemptLlmRerank(input) {
|
|
5764
|
+
if (input.httpRerankConfigured) return false;
|
|
5765
|
+
if (input.quality !== "thorough" || input.tier !== "heavy" || !input.hasQuery) return false;
|
|
5766
|
+
if (input.candidateCount < MIN_RERANK_CANDIDATES) return false;
|
|
5767
|
+
return input.topScore > 0 && input.secondScore / input.topScore > 0.7;
|
|
5768
|
+
}
|
|
5769
|
+
var DEFAULT_RERANK_TIMEOUT_MS, RERANK_TIMEOUT_MIN_MS, RERANK_TIMEOUT_MAX_MS, MIN_RERANK_CANDIDATES;
|
|
5770
|
+
var init_policy = __esm({
|
|
5771
|
+
"src/rerank/policy.ts"() {
|
|
5772
|
+
"use strict";
|
|
5773
|
+
init_esm_shims();
|
|
5774
|
+
DEFAULT_RERANK_TIMEOUT_MS = 3e4;
|
|
5775
|
+
RERANK_TIMEOUT_MIN_MS = 1e3;
|
|
5776
|
+
RERANK_TIMEOUT_MAX_MS = 3e5;
|
|
5777
|
+
MIN_RERANK_CANDIDATES = 3;
|
|
5778
|
+
}
|
|
5779
|
+
});
|
|
5780
|
+
|
|
5547
5781
|
// src/timeout.ts
|
|
5548
5782
|
function withTimeout(promise, ms, label) {
|
|
5549
5783
|
return new Promise((resolve, reject) => {
|
|
@@ -5829,6 +6063,148 @@ var init_aliases = __esm({
|
|
|
5829
6063
|
}
|
|
5830
6064
|
});
|
|
5831
6065
|
|
|
6066
|
+
// src/rerank/http-provider.ts
|
|
6067
|
+
function buildRerankUrl(baseUrl) {
|
|
6068
|
+
const trimmed = baseUrl.trim().replace(/\/+$/, "");
|
|
6069
|
+
if (trimmed.endsWith("/rerank")) return trimmed;
|
|
6070
|
+
return `${trimmed}/rerank`;
|
|
6071
|
+
}
|
|
6072
|
+
function parseRerankResponse(payload) {
|
|
6073
|
+
const rows = extractRows(payload);
|
|
6074
|
+
if (rows.length === 0) {
|
|
6075
|
+
throw new Error("Neural rerank response contained no ranked results");
|
|
6076
|
+
}
|
|
6077
|
+
return rows.sort((a, b) => b.score - a.score);
|
|
6078
|
+
}
|
|
6079
|
+
function extractRows(payload) {
|
|
6080
|
+
if (Array.isArray(payload)) {
|
|
6081
|
+
return payload.map(rowFromUnknown).filter((row) => row !== null);
|
|
6082
|
+
}
|
|
6083
|
+
if (payload && typeof payload === "object" && "results" in payload) {
|
|
6084
|
+
const results = payload.results;
|
|
6085
|
+
if (Array.isArray(results)) {
|
|
6086
|
+
return results.map(rowFromUnknown).filter((row) => row !== null);
|
|
6087
|
+
}
|
|
6088
|
+
}
|
|
6089
|
+
throw new Error("Neural rerank response was not Cohere or TEI shaped");
|
|
6090
|
+
}
|
|
6091
|
+
function rowFromUnknown(value) {
|
|
6092
|
+
if (!value || typeof value !== "object") return null;
|
|
6093
|
+
const row = value;
|
|
6094
|
+
if (typeof row.index !== "number" || !Number.isFinite(row.index)) return null;
|
|
6095
|
+
const score = typeof row.relevance_score === "number" ? row.relevance_score : typeof row.score === "number" ? row.score : null;
|
|
6096
|
+
if (score === null || !Number.isFinite(score)) return null;
|
|
6097
|
+
return { index: row.index, score };
|
|
6098
|
+
}
|
|
6099
|
+
function buildRerankBody(query, documents, model) {
|
|
6100
|
+
const body = {
|
|
6101
|
+
query,
|
|
6102
|
+
documents,
|
|
6103
|
+
top_n: documents.length,
|
|
6104
|
+
return_documents: false
|
|
6105
|
+
};
|
|
6106
|
+
const trimmed = model?.trim();
|
|
6107
|
+
if (trimmed) body.model = trimmed;
|
|
6108
|
+
return body;
|
|
6109
|
+
}
|
|
6110
|
+
async function rerankViaHttp(query, documents, config) {
|
|
6111
|
+
if (documents.length === 0) return [];
|
|
6112
|
+
const url = buildRerankUrl(config.baseUrl);
|
|
6113
|
+
const headers = {
|
|
6114
|
+
"content-type": "application/json"
|
|
6115
|
+
};
|
|
6116
|
+
if (config.apiKey) {
|
|
6117
|
+
headers.authorization = `Bearer ${config.apiKey}`;
|
|
6118
|
+
}
|
|
6119
|
+
const controller = new AbortController();
|
|
6120
|
+
const timeoutMs = resolveRerankTimeoutMs(config.timeoutMs);
|
|
6121
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
6122
|
+
try {
|
|
6123
|
+
const fetchImpl = config.fetchImpl ?? fetch;
|
|
6124
|
+
const response = await fetchImpl(url, {
|
|
6125
|
+
method: "POST",
|
|
6126
|
+
headers,
|
|
6127
|
+
signal: controller.signal,
|
|
6128
|
+
body: JSON.stringify(buildRerankBody(query, documents, config.model))
|
|
6129
|
+
});
|
|
6130
|
+
if (!response.ok) {
|
|
6131
|
+
throw new Error(`Neural rerank HTTP ${response.status} from ${url}`);
|
|
6132
|
+
}
|
|
6133
|
+
return parseRerankResponse(await response.json());
|
|
6134
|
+
} finally {
|
|
6135
|
+
clearTimeout(timer);
|
|
6136
|
+
}
|
|
6137
|
+
}
|
|
6138
|
+
var init_http_provider = __esm({
|
|
6139
|
+
"src/rerank/http-provider.ts"() {
|
|
6140
|
+
"use strict";
|
|
6141
|
+
init_esm_shims();
|
|
6142
|
+
init_policy();
|
|
6143
|
+
}
|
|
6144
|
+
});
|
|
6145
|
+
|
|
6146
|
+
// src/rerank/index.ts
|
|
6147
|
+
var rerank_exports = {};
|
|
6148
|
+
__export(rerank_exports, {
|
|
6149
|
+
DEFAULT_RERANK_TIMEOUT_MS: () => DEFAULT_RERANK_TIMEOUT_MS,
|
|
6150
|
+
MIN_RERANK_CANDIDATES: () => MIN_RERANK_CANDIDATES,
|
|
6151
|
+
isNeuralRerankEnabled: () => isNeuralRerankEnabled,
|
|
6152
|
+
neuralRerankCandidates: () => neuralRerankCandidates,
|
|
6153
|
+
parseRerankTimeoutMs: () => parseRerankTimeoutMs,
|
|
6154
|
+
resolveRerankTimeoutMs: () => resolveRerankTimeoutMs,
|
|
6155
|
+
shouldAttemptHttpRerank: () => shouldAttemptHttpRerank,
|
|
6156
|
+
shouldAttemptLlmRerank: () => shouldAttemptLlmRerank
|
|
6157
|
+
});
|
|
6158
|
+
function isNeuralRerankEnabled(options = {}) {
|
|
6159
|
+
const lane = getResolvedRerankLane(options);
|
|
6160
|
+
return lane.provider === "http" && Boolean(lane.baseUrl);
|
|
6161
|
+
}
|
|
6162
|
+
async function neuralRerankCandidates(query, candidates, options = {}) {
|
|
6163
|
+
if (!isNeuralRerankEnabled(options) || candidates.length === 0) return null;
|
|
6164
|
+
const lane = getResolvedRerankLane(options);
|
|
6165
|
+
if (!lane.canSendRequest || !lane.baseUrl) return null;
|
|
6166
|
+
const toRerank = candidates.slice(0, MAX_RERANK);
|
|
6167
|
+
const rest = candidates.slice(MAX_RERANK);
|
|
6168
|
+
const documents = toRerank.map((candidate) => candidateText(candidate));
|
|
6169
|
+
const ranked = await rerankViaHttp(query, documents, {
|
|
6170
|
+
provider: "http",
|
|
6171
|
+
model: lane.model,
|
|
6172
|
+
baseUrl: lane.baseUrl,
|
|
6173
|
+
apiKey: lane.apiKey,
|
|
6174
|
+
timeoutMs: resolveRerankTimeoutMs()
|
|
6175
|
+
});
|
|
6176
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6177
|
+
const reranked = [];
|
|
6178
|
+
for (const row of ranked) {
|
|
6179
|
+
const candidate = toRerank[row.index];
|
|
6180
|
+
if (!candidate || seen.has(row.index)) continue;
|
|
6181
|
+
reranked.push(candidate);
|
|
6182
|
+
seen.add(row.index);
|
|
6183
|
+
}
|
|
6184
|
+
for (const [index, candidate] of toRerank.entries()) {
|
|
6185
|
+
if (!seen.has(index)) reranked.push(candidate);
|
|
6186
|
+
}
|
|
6187
|
+
reranked.push(...rest);
|
|
6188
|
+
return reranked;
|
|
6189
|
+
}
|
|
6190
|
+
function candidateText(candidate) {
|
|
6191
|
+
const narrative = candidate.narrative?.trim();
|
|
6192
|
+
if (narrative) return `${candidate.title} \u2014 ${narrative.slice(0, 200)}`;
|
|
6193
|
+
return candidate.title;
|
|
6194
|
+
}
|
|
6195
|
+
var MAX_RERANK;
|
|
6196
|
+
var init_rerank = __esm({
|
|
6197
|
+
"src/rerank/index.ts"() {
|
|
6198
|
+
"use strict";
|
|
6199
|
+
init_esm_shims();
|
|
6200
|
+
init_resolved_config();
|
|
6201
|
+
init_http_provider();
|
|
6202
|
+
init_policy();
|
|
6203
|
+
init_policy();
|
|
6204
|
+
MAX_RERANK = 10;
|
|
6205
|
+
}
|
|
6206
|
+
});
|
|
6207
|
+
|
|
5832
6208
|
// src/llm/quality.ts
|
|
5833
6209
|
var quality_exports = {};
|
|
5834
6210
|
__export(quality_exports, {
|
|
@@ -5868,9 +6244,9 @@ async function rerankResults(query, candidates) {
|
|
|
5868
6244
|
if (!isLLMEnabled() || candidates.length <= 2) {
|
|
5869
6245
|
return { reranked: candidates, usedLLM: false };
|
|
5870
6246
|
}
|
|
5871
|
-
const
|
|
5872
|
-
const toRerank = candidates.slice(0,
|
|
5873
|
-
const rest = candidates.slice(
|
|
6247
|
+
const MAX_RERANK2 = 10;
|
|
6248
|
+
const toRerank = candidates.slice(0, MAX_RERANK2);
|
|
6249
|
+
const rest = candidates.slice(MAX_RERANK2);
|
|
5874
6250
|
try {
|
|
5875
6251
|
const candidateList = toRerank.map(
|
|
5876
6252
|
(c) => `[ID: ${c.id}] (${c.type}) ${c.title}${c.narrative ? ` \u2014 ${c.narrative.substring(0, 100)}` : ""}`
|
|
@@ -6763,46 +7139,78 @@ async function searchObservations(options) {
|
|
|
6763
7139
|
}
|
|
6764
7140
|
}
|
|
6765
7141
|
}
|
|
6766
|
-
const
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
|
|
6770
|
-
})
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
|
|
6781
|
-
|
|
6782
|
-
|
|
6783
|
-
|
|
6784
|
-
|
|
6785
|
-
|
|
6786
|
-
|
|
6787
|
-
|
|
6788
|
-
|
|
6789
|
-
|
|
6790
|
-
|
|
6791
|
-
|
|
6792
|
-
|
|
6793
|
-
|
|
6794
|
-
|
|
6795
|
-
|
|
6796
|
-
|
|
6797
|
-
|
|
6798
|
-
|
|
6799
|
-
|
|
6800
|
-
|
|
6801
|
-
|
|
7142
|
+
const httpGate = shouldAttemptHttpRerank({
|
|
7143
|
+
quality,
|
|
7144
|
+
hasQuery: Boolean(hasQuery),
|
|
7145
|
+
candidateCount: intermediate.length
|
|
7146
|
+
});
|
|
7147
|
+
const llmGateWithoutHttp = shouldAttemptLlmRerank({
|
|
7148
|
+
quality,
|
|
7149
|
+
tier,
|
|
7150
|
+
hasQuery: Boolean(hasQuery),
|
|
7151
|
+
candidateCount: intermediate.length,
|
|
7152
|
+
topScore: intermediate[0]?.score ?? 0,
|
|
7153
|
+
secondScore: intermediate[1]?.score ?? 0,
|
|
7154
|
+
httpRerankConfigured: false
|
|
7155
|
+
});
|
|
7156
|
+
if (httpGate || llmGateWithoutHttp) {
|
|
7157
|
+
const narrativeMap = /* @__PURE__ */ new Map();
|
|
7158
|
+
for (const hit of results.hits) {
|
|
7159
|
+
const doc = hit.document;
|
|
7160
|
+
narrativeMap.set(makeEntryKey(doc.projectId, doc.observationId), doc.narrative);
|
|
7161
|
+
}
|
|
7162
|
+
const RERANK_TOP_K = 5;
|
|
7163
|
+
const toRerank = intermediate.slice(0, RERANK_TOP_K);
|
|
7164
|
+
const candidates = toRerank.map((e2, index) => ({
|
|
7165
|
+
id: `r${index + 1}`,
|
|
7166
|
+
title: e2.title,
|
|
7167
|
+
type: e2.type,
|
|
7168
|
+
score: e2.score,
|
|
7169
|
+
narrative: narrativeMap.get(makeEntryKey(e2.projectId, e2.id))
|
|
7170
|
+
}));
|
|
7171
|
+
const RERANK_TIMEOUT_MS = parseRerankTimeoutMs(process.env.MEMORIX_RERANK_TIMEOUT_MS);
|
|
7172
|
+
const candidateMap = new Map(candidates.map((candidate, index) => [candidate.id, toRerank[index]]));
|
|
7173
|
+
const { isNeuralRerankEnabled: isNeuralRerankEnabled2, neuralRerankCandidates: neuralRerankCandidates2 } = await Promise.resolve().then(() => (init_rerank(), rerank_exports));
|
|
7174
|
+
const httpConfigured = isNeuralRerankEnabled2();
|
|
7175
|
+
if (httpConfigured && httpGate) {
|
|
7176
|
+
try {
|
|
7177
|
+
const neural = await withTimeout(
|
|
7178
|
+
neuralRerankCandidates2(originalQuery, candidates),
|
|
7179
|
+
RERANK_TIMEOUT_MS,
|
|
7180
|
+
"neural rerank"
|
|
7181
|
+
);
|
|
7182
|
+
if (neural && neural.length > 0) {
|
|
7183
|
+
const rerankedTop = neural.map((row) => candidateMap.get(row.id)).filter((entry) => entry != null);
|
|
7184
|
+
if (rerankedTop.length > 0) {
|
|
7185
|
+
intermediate = [...rerankedTop, ...intermediate.slice(RERANK_TOP_K)];
|
|
7186
|
+
lastSearchModeByProject.set(modeKey, (lastSearchModeByProject.get(modeKey) ?? "fulltext") + " + neural rerank");
|
|
7187
|
+
mark("rerank(usedNeural=true)");
|
|
7188
|
+
}
|
|
6802
7189
|
}
|
|
7190
|
+
} catch {
|
|
7191
|
+
console.error("[memorix] neural rerank failed or timed out; keeping original order");
|
|
6803
7192
|
}
|
|
6804
|
-
}
|
|
6805
|
-
|
|
7193
|
+
} else if (!httpConfigured && llmGateWithoutHttp) {
|
|
7194
|
+
try {
|
|
7195
|
+
const { rerankResults: rerankResults2 } = await Promise.resolve().then(() => (init_quality(), quality_exports));
|
|
7196
|
+
const { reranked, usedLLM } = await withTimeout(
|
|
7197
|
+
rerankResults2(originalQuery, candidates),
|
|
7198
|
+
RERANK_TIMEOUT_MS,
|
|
7199
|
+
"LLM rerank"
|
|
7200
|
+
);
|
|
7201
|
+
mark(`rerank(usedLLM=${usedLLM})`);
|
|
7202
|
+
if (usedLLM) {
|
|
7203
|
+
lastSearchModeByProject.set(modeKey, (lastSearchModeByProject.get(modeKey) ?? "fulltext") + " + LLM rerank");
|
|
7204
|
+
const rerankedTop = reranked.map((row) => candidateMap.get(row.id)).filter((entry) => entry != null);
|
|
7205
|
+
if (rerankedTop.length > 0) {
|
|
7206
|
+
intermediate = [...rerankedTop, ...intermediate.slice(RERANK_TOP_K)];
|
|
7207
|
+
}
|
|
7208
|
+
}
|
|
7209
|
+
} catch {
|
|
7210
|
+
console.error("[memorix] LLM rerank failed or timed out, using original order");
|
|
7211
|
+
}
|
|
7212
|
+
} else {
|
|
7213
|
+
mark(`rerank(skipped,tier=${tier})`);
|
|
6806
7214
|
}
|
|
6807
7215
|
} else {
|
|
6808
7216
|
mark(`rerank(skipped,tier=${tier})`);
|
|
@@ -6983,6 +7391,7 @@ var init_orama_store = __esm({
|
|
|
6983
7391
|
init_project_affinity();
|
|
6984
7392
|
init_intent_detector();
|
|
6985
7393
|
init_query_expansion();
|
|
7394
|
+
init_policy();
|
|
6986
7395
|
init_timeout();
|
|
6987
7396
|
db = null;
|
|
6988
7397
|
dbInitPromise = null;
|
|
@@ -7674,6 +8083,226 @@ var init_lifecycle = __esm({
|
|
|
7674
8083
|
}
|
|
7675
8084
|
});
|
|
7676
8085
|
|
|
8086
|
+
// src/store/evidence-store.ts
|
|
8087
|
+
import { createHash as createHash3, randomUUID as randomUUID3 } from "crypto";
|
|
8088
|
+
function safeJson(value, fallback) {
|
|
8089
|
+
if (typeof value !== "string" || value.length === 0) return fallback;
|
|
8090
|
+
try {
|
|
8091
|
+
return JSON.parse(value);
|
|
8092
|
+
} catch {
|
|
8093
|
+
return fallback;
|
|
8094
|
+
}
|
|
8095
|
+
}
|
|
8096
|
+
function rowToCard(row) {
|
|
8097
|
+
return {
|
|
8098
|
+
id: String(row.id),
|
|
8099
|
+
projectId: String(row.project_id),
|
|
8100
|
+
candidateKind: row.candidate_kind,
|
|
8101
|
+
candidateId: String(row.candidate_id),
|
|
8102
|
+
title: String(row.title),
|
|
8103
|
+
summary: String(row.summary ?? ""),
|
|
8104
|
+
...row.entity_name ? { entityName: String(row.entity_name) } : {},
|
|
8105
|
+
sourceKind: String(row.source_kind),
|
|
8106
|
+
sourceRef: String(row.source_ref),
|
|
8107
|
+
...row.locator ? { locator: String(row.locator) } : {},
|
|
8108
|
+
...row.captured_hash ? { capturedHash: String(row.captured_hash) } : {},
|
|
8109
|
+
...row.session_id ? { sessionId: String(row.session_id) } : {},
|
|
8110
|
+
status: String(row.status ?? "active"),
|
|
8111
|
+
verification: row.verification,
|
|
8112
|
+
freshness: row.freshness,
|
|
8113
|
+
...row.stale_reason ? { staleReason: String(row.stale_reason) } : {},
|
|
8114
|
+
files: safeJson(row.files_json, []),
|
|
8115
|
+
relatedEntities: safeJson(row.related_entities_json, []),
|
|
8116
|
+
createdAt: String(row.created_at),
|
|
8117
|
+
updatedAt: String(row.updated_at)
|
|
8118
|
+
};
|
|
8119
|
+
}
|
|
8120
|
+
function observationHash(observation) {
|
|
8121
|
+
return createHash3("sha256").update(JSON.stringify({
|
|
8122
|
+
projectId: observation.projectId,
|
|
8123
|
+
id: observation.id,
|
|
8124
|
+
title: observation.title,
|
|
8125
|
+
narrative: observation.narrative,
|
|
8126
|
+
facts: observation.facts,
|
|
8127
|
+
files: observation.filesModified,
|
|
8128
|
+
relatedEntities: observation.relatedEntities
|
|
8129
|
+
})).digest("hex");
|
|
8130
|
+
}
|
|
8131
|
+
function sourceKind(observation) {
|
|
8132
|
+
if (observation.source === "git" || observation.sourceDetail === "git-ingest") return "git";
|
|
8133
|
+
if (observation.sourceDetail === "hook") return "hook";
|
|
8134
|
+
return observation.source ?? "agent";
|
|
8135
|
+
}
|
|
8136
|
+
var EvidenceCardStore;
|
|
8137
|
+
var init_evidence_store = __esm({
|
|
8138
|
+
"src/store/evidence-store.ts"() {
|
|
8139
|
+
"use strict";
|
|
8140
|
+
init_esm_shims();
|
|
8141
|
+
init_sqlite_db();
|
|
8142
|
+
EvidenceCardStore = class {
|
|
8143
|
+
db = null;
|
|
8144
|
+
async init(dataDir) {
|
|
8145
|
+
this.db = getDatabase(dataDir);
|
|
8146
|
+
}
|
|
8147
|
+
requireDb() {
|
|
8148
|
+
if (!this.db) throw new Error("EvidenceCardStore is not initialized.");
|
|
8149
|
+
return this.db;
|
|
8150
|
+
}
|
|
8151
|
+
upsertObservation(observation) {
|
|
8152
|
+
const db2 = this.requireDb();
|
|
8153
|
+
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
8154
|
+
const card = {
|
|
8155
|
+
id: `evidence:observation:${observation.projectId}:${observation.id}`,
|
|
8156
|
+
projectId: observation.projectId,
|
|
8157
|
+
candidateKind: "observation",
|
|
8158
|
+
candidateId: String(observation.id),
|
|
8159
|
+
title: observation.title,
|
|
8160
|
+
summary: observation.narrative.slice(0, 500),
|
|
8161
|
+
entityName: observation.entityName,
|
|
8162
|
+
sourceKind: sourceKind(observation),
|
|
8163
|
+
sourceRef: `observation:${observation.id}`,
|
|
8164
|
+
locator: observation.filesModified?.join(", ") || `observation:${observation.id}`,
|
|
8165
|
+
capturedHash: observationHash(observation),
|
|
8166
|
+
...observation.sessionId ? { sessionId: observation.sessionId } : {},
|
|
8167
|
+
status: observation.status ?? "active",
|
|
8168
|
+
verification: observation.status === "resolved" ? "verified" : "unverified",
|
|
8169
|
+
freshness: "current",
|
|
8170
|
+
files: observation.filesModified ?? [],
|
|
8171
|
+
relatedEntities: observation.relatedEntities ?? [],
|
|
8172
|
+
createdAt: observation.createdAt,
|
|
8173
|
+
updatedAt: now3
|
|
8174
|
+
};
|
|
8175
|
+
db2.prepare(`
|
|
8176
|
+
INSERT INTO evidence_cards (
|
|
8177
|
+
id, project_id, candidate_kind, candidate_id, title, summary, entity_name,
|
|
8178
|
+
source_kind, source_ref, locator, captured_hash, session_id, status,
|
|
8179
|
+
verification, freshness, stale_reason, files_json, related_entities_json,
|
|
8180
|
+
created_at, updated_at
|
|
8181
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?)
|
|
8182
|
+
ON CONFLICT(project_id, candidate_kind, candidate_id) DO UPDATE SET
|
|
8183
|
+
title = excluded.title,
|
|
8184
|
+
summary = excluded.summary,
|
|
8185
|
+
entity_name = excluded.entity_name,
|
|
8186
|
+
source_kind = excluded.source_kind,
|
|
8187
|
+
source_ref = excluded.source_ref,
|
|
8188
|
+
locator = excluded.locator,
|
|
8189
|
+
captured_hash = excluded.captured_hash,
|
|
8190
|
+
session_id = excluded.session_id,
|
|
8191
|
+
status = excluded.status,
|
|
8192
|
+
freshness = 'current',
|
|
8193
|
+
stale_reason = NULL,
|
|
8194
|
+
files_json = excluded.files_json,
|
|
8195
|
+
related_entities_json = excluded.related_entities_json,
|
|
8196
|
+
updated_at = excluded.updated_at
|
|
8197
|
+
`).run(
|
|
8198
|
+
card.id,
|
|
8199
|
+
card.projectId,
|
|
8200
|
+
card.candidateKind,
|
|
8201
|
+
card.candidateId,
|
|
8202
|
+
card.title,
|
|
8203
|
+
card.summary,
|
|
8204
|
+
card.entityName ?? null,
|
|
8205
|
+
card.sourceKind,
|
|
8206
|
+
card.sourceRef,
|
|
8207
|
+
card.locator ?? null,
|
|
8208
|
+
card.capturedHash ?? null,
|
|
8209
|
+
card.sessionId ?? null,
|
|
8210
|
+
card.status,
|
|
8211
|
+
card.verification,
|
|
8212
|
+
card.freshness,
|
|
8213
|
+
JSON.stringify(card.files),
|
|
8214
|
+
JSON.stringify(card.relatedEntities),
|
|
8215
|
+
card.createdAt,
|
|
8216
|
+
card.updatedAt
|
|
8217
|
+
);
|
|
8218
|
+
return this.get(card.projectId, card.candidateKind, card.candidateId) ?? card;
|
|
8219
|
+
}
|
|
8220
|
+
get(projectId, candidateKind, candidateId) {
|
|
8221
|
+
const row = this.requireDb().prepare(`
|
|
8222
|
+
SELECT * FROM evidence_cards WHERE project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
8223
|
+
`).get(projectId, candidateKind, candidateId);
|
|
8224
|
+
return row ? rowToCard(row) : void 0;
|
|
8225
|
+
}
|
|
8226
|
+
list(projectId, options = {}) {
|
|
8227
|
+
const limit2 = Math.min(100, Math.max(1, Math.floor(options.limit ?? 20)));
|
|
8228
|
+
const clauses = ["project_id = ?"];
|
|
8229
|
+
const args = [projectId];
|
|
8230
|
+
if (options.freshness) {
|
|
8231
|
+
clauses.push("freshness = ?");
|
|
8232
|
+
args.push(options.freshness);
|
|
8233
|
+
}
|
|
8234
|
+
if (options.status) {
|
|
8235
|
+
clauses.push("status = ?");
|
|
8236
|
+
args.push(options.status);
|
|
8237
|
+
}
|
|
8238
|
+
args.push(limit2);
|
|
8239
|
+
const rows = this.requireDb().prepare(`
|
|
8240
|
+
SELECT * FROM evidence_cards WHERE ${clauses.join(" AND ")} ORDER BY updated_at DESC, id DESC LIMIT ?
|
|
8241
|
+
`).all(...args);
|
|
8242
|
+
return rows.map(rowToCard);
|
|
8243
|
+
}
|
|
8244
|
+
syncObservations(observations2) {
|
|
8245
|
+
return observations2.map((observation) => this.upsertObservation(observation));
|
|
8246
|
+
}
|
|
8247
|
+
markStaleForPaths(projectId, paths, reason = "source file changed") {
|
|
8248
|
+
const normalized = new Set(paths.map((value) => value.replace(/\\/g, "/").toLowerCase()));
|
|
8249
|
+
if (normalized.size === 0) return 0;
|
|
8250
|
+
const db2 = this.requireDb();
|
|
8251
|
+
const rows = db2.prepare(`SELECT * FROM evidence_cards WHERE project_id = ? AND freshness != 'stale'`).all(projectId);
|
|
8252
|
+
const update2 = db2.prepare(`
|
|
8253
|
+
UPDATE evidence_cards SET freshness = 'stale', stale_reason = ?, updated_at = ?
|
|
8254
|
+
WHERE id = ?
|
|
8255
|
+
`);
|
|
8256
|
+
let changed = 0;
|
|
8257
|
+
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
8258
|
+
const run = db2.transaction(() => {
|
|
8259
|
+
for (const row of rows) {
|
|
8260
|
+
const files = safeJson(row.files_json, []);
|
|
8261
|
+
if (!files.some((file) => normalized.has(file.replace(/\\/g, "/").toLowerCase()))) continue;
|
|
8262
|
+
update2.run(reason, now3, row.id);
|
|
8263
|
+
changed++;
|
|
8264
|
+
}
|
|
8265
|
+
});
|
|
8266
|
+
run();
|
|
8267
|
+
return changed;
|
|
8268
|
+
}
|
|
8269
|
+
setVerification(projectId, cardId, verification) {
|
|
8270
|
+
this.requireDb().prepare(`
|
|
8271
|
+
UPDATE evidence_cards SET verification = ?, updated_at = ? WHERE project_id = ? AND id = ?
|
|
8272
|
+
`).run(verification, (/* @__PURE__ */ new Date()).toISOString(), projectId, cardId);
|
|
8273
|
+
}
|
|
8274
|
+
recordEvent(projectId, cardId, kind, detail) {
|
|
8275
|
+
const event = {
|
|
8276
|
+
id: randomUUID3(),
|
|
8277
|
+
projectId,
|
|
8278
|
+
cardId,
|
|
8279
|
+
kind,
|
|
8280
|
+
...detail ? { detail: detail.slice(0, 2e3) } : {},
|
|
8281
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8282
|
+
};
|
|
8283
|
+
this.requireDb().prepare(`
|
|
8284
|
+
INSERT INTO evidence_card_events (id, project_id, card_id, kind, detail, created_at)
|
|
8285
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
8286
|
+
`).run(event.id, event.projectId, event.cardId, event.kind, event.detail ?? null, event.createdAt);
|
|
8287
|
+
return event;
|
|
8288
|
+
}
|
|
8289
|
+
listEvents(cardId, limit2 = 50) {
|
|
8290
|
+
const rows = this.requireDb().prepare(`
|
|
8291
|
+
SELECT * FROM evidence_card_events WHERE card_id = ? ORDER BY created_at DESC LIMIT ?
|
|
8292
|
+
`).all(cardId, Math.min(200, Math.max(1, Math.floor(limit2))));
|
|
8293
|
+
return rows.map((row) => ({
|
|
8294
|
+
id: String(row.id),
|
|
8295
|
+
projectId: String(row.project_id),
|
|
8296
|
+
cardId: String(row.card_id),
|
|
8297
|
+
kind: String(row.kind),
|
|
8298
|
+
...row.detail ? { detail: String(row.detail) } : {},
|
|
8299
|
+
createdAt: String(row.created_at)
|
|
8300
|
+
}));
|
|
8301
|
+
}
|
|
8302
|
+
};
|
|
8303
|
+
}
|
|
8304
|
+
});
|
|
8305
|
+
|
|
7677
8306
|
// src/runtime/isolated-maintenance.ts
|
|
7678
8307
|
import { spawn } from "child_process";
|
|
7679
8308
|
import { existsSync as existsSync8 } from "fs";
|
|
@@ -7705,7 +8334,7 @@ var init_isolated_maintenance = __esm({
|
|
|
7705
8334
|
});
|
|
7706
8335
|
|
|
7707
8336
|
// src/knowledge/workspace-store.ts
|
|
7708
|
-
import { randomUUID as
|
|
8337
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
7709
8338
|
function arrayValue(raw) {
|
|
7710
8339
|
if (typeof raw !== "string" || !raw) return [];
|
|
7711
8340
|
try {
|
|
@@ -7846,7 +8475,7 @@ var init_workspace_store = __esm({
|
|
|
7846
8475
|
}
|
|
7847
8476
|
createProposal(input) {
|
|
7848
8477
|
const proposal = {
|
|
7849
|
-
id: input.id ??
|
|
8478
|
+
id: input.id ?? randomUUID4(),
|
|
7850
8479
|
...input,
|
|
7851
8480
|
status: input.status ?? "pending",
|
|
7852
8481
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -7899,13 +8528,13 @@ __export(workspace_exports, {
|
|
|
7899
8528
|
loadKnowledgeWorkspace: () => loadKnowledgeWorkspace,
|
|
7900
8529
|
resolveKnowledgeWorkspaceFile: () => resolveKnowledgeWorkspaceFile
|
|
7901
8530
|
});
|
|
7902
|
-
import { createHash as
|
|
8531
|
+
import { createHash as createHash4 } from "crypto";
|
|
7903
8532
|
import { execFile } from "child_process";
|
|
7904
8533
|
import { promises as fs6 } from "fs";
|
|
7905
8534
|
import path10 from "path";
|
|
7906
8535
|
import { promisify } from "util";
|
|
7907
8536
|
function hash(value) {
|
|
7908
|
-
return
|
|
8537
|
+
return createHash4("sha256").update(value).digest("hex");
|
|
7909
8538
|
}
|
|
7910
8539
|
function workspaceId(projectId, mode) {
|
|
7911
8540
|
return "workspace:" + hash(projectId + ":" + mode).slice(0, 24);
|
|
@@ -8501,7 +9130,7 @@ Respond in JSON only:
|
|
|
8501
9130
|
});
|
|
8502
9131
|
|
|
8503
9132
|
// src/media/media-store.ts
|
|
8504
|
-
import { randomUUID as
|
|
9133
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
8505
9134
|
function asOptionalText(value) {
|
|
8506
9135
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
8507
9136
|
}
|
|
@@ -8671,7 +9300,7 @@ var init_media_store = __esm({
|
|
|
8671
9300
|
return { asset: this.getAsset(input.projectId, existing.id), deduplicated: true };
|
|
8672
9301
|
}
|
|
8673
9302
|
const asset = {
|
|
8674
|
-
id:
|
|
9303
|
+
id: randomUUID5(),
|
|
8675
9304
|
...input,
|
|
8676
9305
|
createdAt: now3,
|
|
8677
9306
|
updatedAt: now3
|
|
@@ -8751,7 +9380,7 @@ var init_media_store = __esm({
|
|
|
8751
9380
|
`).get(input.assetId, input.observationId ?? null, input.role);
|
|
8752
9381
|
if (existing) return rowToLink(existing);
|
|
8753
9382
|
const link = {
|
|
8754
|
-
id:
|
|
9383
|
+
id: randomUUID5(),
|
|
8755
9384
|
assetId: input.assetId,
|
|
8756
9385
|
projectId: input.projectId,
|
|
8757
9386
|
...input.observationId !== void 0 ? { observationId: input.observationId } : {},
|
|
@@ -8790,7 +9419,7 @@ var init_media_store = __esm({
|
|
|
8790
9419
|
return rowToDerivation(this.db.prepare("SELECT * FROM media_derivations WHERE id = ?").get(existing.id));
|
|
8791
9420
|
}
|
|
8792
9421
|
const derivation = {
|
|
8793
|
-
id:
|
|
9422
|
+
id: randomUUID5(),
|
|
8794
9423
|
...input,
|
|
8795
9424
|
content,
|
|
8796
9425
|
...error ? { error } : {},
|
|
@@ -8877,7 +9506,7 @@ var init_media_store = __esm({
|
|
|
8877
9506
|
createJob(input) {
|
|
8878
9507
|
const now3 = Date.now();
|
|
8879
9508
|
const job = {
|
|
8880
|
-
id:
|
|
9509
|
+
id: randomUUID5(),
|
|
8881
9510
|
projectId: input.projectId,
|
|
8882
9511
|
kind: input.kind,
|
|
8883
9512
|
status: "queued",
|
|
@@ -9039,14 +9668,14 @@ var init_types2 = __esm({
|
|
|
9039
9668
|
});
|
|
9040
9669
|
|
|
9041
9670
|
// src/media/asset-store.ts
|
|
9042
|
-
import { createHash as
|
|
9671
|
+
import { createHash as createHash5, randomUUID as randomUUID6 } from "crypto";
|
|
9043
9672
|
import { copyFile, lstat, mkdir as mkdir3, open, readFile as readFile3, readdir, rename as rename2, rm, stat as stat2, writeFile as writeFile3 } from "fs/promises";
|
|
9044
9673
|
import path11 from "path";
|
|
9045
9674
|
function mediaRoot(dataDir) {
|
|
9046
9675
|
return path11.resolve(dataDir, "media");
|
|
9047
9676
|
}
|
|
9048
9677
|
function projectStorageKey(projectId) {
|
|
9049
|
-
return
|
|
9678
|
+
return createHash5("sha256").update(projectId).digest("hex").slice(0, 16);
|
|
9050
9679
|
}
|
|
9051
9680
|
function validateUnderRoot(root, candidate) {
|
|
9052
9681
|
const resolved = path11.resolve(candidate);
|
|
@@ -9110,7 +9739,7 @@ async function destinationExists(destination) {
|
|
|
9110
9739
|
async function persistBuffer(bytes, destination) {
|
|
9111
9740
|
await mkdir3(path11.dirname(destination), { recursive: true });
|
|
9112
9741
|
if (await destinationExists(destination)) return false;
|
|
9113
|
-
const temporary = `${destination}.${
|
|
9742
|
+
const temporary = `${destination}.${randomUUID6()}.tmp`;
|
|
9114
9743
|
try {
|
|
9115
9744
|
await writeFile3(temporary, bytes, { flag: "wx" });
|
|
9116
9745
|
await rename2(temporary, destination);
|
|
@@ -9155,7 +9784,7 @@ async function importMediaBuffer(input) {
|
|
|
9155
9784
|
if (input.bytes.length === 0) throw new Error("Media import rejects empty payloads");
|
|
9156
9785
|
if (input.bytes.length > maxBytes) throw new Error(`Media payload is too large (${input.bytes.length} bytes; limit ${maxBytes})`);
|
|
9157
9786
|
const detected = detectMedia(input.bytes.subarray(0, 32));
|
|
9158
|
-
const sha256 =
|
|
9787
|
+
const sha256 = createHash5("sha256").update(input.bytes).digest("hex");
|
|
9159
9788
|
return importKnownMedia({
|
|
9160
9789
|
dataDir: input.dataDir,
|
|
9161
9790
|
projectId: input.projectId,
|
|
@@ -9173,7 +9802,7 @@ async function readMediaAsset(dataDir, asset, maxBytes = DEFAULT_MAX_MEDIA_BYTES
|
|
|
9173
9802
|
if (asset.byteSize > maxBytes) throw new Error(`Media asset exceeds read limit (${asset.byteSize} bytes; limit ${maxBytes})`);
|
|
9174
9803
|
const bytes = await readFile3(getMediaAssetPath(dataDir, asset));
|
|
9175
9804
|
if (bytes.length !== asset.byteSize) throw new Error(`Media asset size no longer matches metadata: ${asset.id}`);
|
|
9176
|
-
const sha256 =
|
|
9805
|
+
const sha256 = createHash5("sha256").update(bytes).digest("hex");
|
|
9177
9806
|
if (sha256 !== asset.sha256) throw new Error(`Media asset hash no longer matches metadata: ${asset.id}`);
|
|
9178
9807
|
return bytes;
|
|
9179
9808
|
}
|
|
@@ -61924,7 +62553,7 @@ var require_gaxios = __commonJS({
|
|
|
61924
62553
|
var retry_js_1 = require_retry3();
|
|
61925
62554
|
var stream_1 = __require("stream");
|
|
61926
62555
|
var interceptor_js_1 = require_interceptor();
|
|
61927
|
-
var
|
|
62556
|
+
var randomUUID16 = async () => globalThis.crypto?.randomUUID() || (await import("crypto")).randomUUID();
|
|
61928
62557
|
var HTTP_STATUS_NO_CONTENT = 204;
|
|
61929
62558
|
var Gaxios = class {
|
|
61930
62559
|
agentCache = /* @__PURE__ */ new Map();
|
|
@@ -62197,7 +62826,7 @@ var require_gaxios = __commonJS({
|
|
|
62197
62826
|
*/
|
|
62198
62827
|
["Blob", "File", "FormData"].includes(opts.data?.constructor?.name || "");
|
|
62199
62828
|
if (opts.multipart?.length) {
|
|
62200
|
-
const boundary = await
|
|
62829
|
+
const boundary = await randomUUID16();
|
|
62201
62830
|
preparedHeaders.set("content-type", `multipart/related; boundary=${boundary}`);
|
|
62202
62831
|
opts.body = stream_1.Readable.from(this.getMultipartRequest(opts.multipart, boundary));
|
|
62203
62832
|
} else if (shouldDirectlyPassData) {
|
|
@@ -74424,7 +75053,7 @@ var require_websocket = __commonJS({
|
|
|
74424
75053
|
var http3 = __require("http");
|
|
74425
75054
|
var net = __require("net");
|
|
74426
75055
|
var tls = __require("tls");
|
|
74427
|
-
var { randomBytes, createHash:
|
|
75056
|
+
var { randomBytes, createHash: createHash14 } = __require("crypto");
|
|
74428
75057
|
var { Duplex, Readable: Readable2 } = __require("stream");
|
|
74429
75058
|
var { URL: URL2 } = __require("url");
|
|
74430
75059
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -75092,7 +75721,7 @@ var require_websocket = __commonJS({
|
|
|
75092
75721
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
75093
75722
|
return;
|
|
75094
75723
|
}
|
|
75095
|
-
const digest2 =
|
|
75724
|
+
const digest2 = createHash14("sha1").update(key + GUID).digest("base64");
|
|
75096
75725
|
if (res.headers["sec-websocket-accept"] !== digest2) {
|
|
75097
75726
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
75098
75727
|
return;
|
|
@@ -75464,7 +76093,7 @@ var require_websocket_server = __commonJS({
|
|
|
75464
76093
|
var EventEmitter = __require("events");
|
|
75465
76094
|
var http3 = __require("http");
|
|
75466
76095
|
var { Duplex } = __require("stream");
|
|
75467
|
-
var { createHash:
|
|
76096
|
+
var { createHash: createHash14 } = __require("crypto");
|
|
75468
76097
|
var extension3 = require_extension();
|
|
75469
76098
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
75470
76099
|
var subprotocol2 = require_subprotocol();
|
|
@@ -75771,7 +76400,7 @@ var require_websocket_server = __commonJS({
|
|
|
75771
76400
|
);
|
|
75772
76401
|
}
|
|
75773
76402
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
75774
|
-
const digest2 =
|
|
76403
|
+
const digest2 = createHash14("sha1").update(key + GUID).digest("base64");
|
|
75775
76404
|
const headers = [
|
|
75776
76405
|
"HTTP/1.1 101 Switching Protocols",
|
|
75777
76406
|
"Upgrade: websocket",
|
|
@@ -142909,6 +143538,186 @@ var init_audio_jobs = __esm({
|
|
|
142909
143538
|
}
|
|
142910
143539
|
});
|
|
142911
143540
|
|
|
143541
|
+
// src/memory/feedback-model.ts
|
|
143542
|
+
function feedbackWeightMultiplier(weight) {
|
|
143543
|
+
return Math.max(0.35, Math.min(1.4, 0.35 + Math.max(0, Math.min(2, weight)) * 0.525));
|
|
143544
|
+
}
|
|
143545
|
+
var init_feedback_model = __esm({
|
|
143546
|
+
"src/memory/feedback-model.ts"() {
|
|
143547
|
+
"use strict";
|
|
143548
|
+
init_esm_shims();
|
|
143549
|
+
}
|
|
143550
|
+
});
|
|
143551
|
+
|
|
143552
|
+
// src/memory/feedback.ts
|
|
143553
|
+
var feedback_exports = {};
|
|
143554
|
+
__export(feedback_exports, {
|
|
143555
|
+
FEEDBACK_DELTAS: () => FEEDBACK_DELTAS,
|
|
143556
|
+
MemoryFeedbackStore: () => MemoryFeedbackStore,
|
|
143557
|
+
applyMemoryFeedback: () => applyMemoryFeedback,
|
|
143558
|
+
feedbackWeightMultiplier: () => feedbackWeightMultiplier
|
|
143559
|
+
});
|
|
143560
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
143561
|
+
function applyMemoryFeedback(current, event) {
|
|
143562
|
+
const delta = event.signal === "revoke" ? 0 : FEEDBACK_DELTAS[event.signal];
|
|
143563
|
+
const weight = Math.max(0, Math.min(2, current.weight + delta));
|
|
143564
|
+
const status = (event.signal === "code-conflict" || event.signal === "user-correction" || event.signal === "weaken") && weight < 0.5 ? "archived" : current.status;
|
|
143565
|
+
return { weight, status, audit: [...current.audit, { ...event }] };
|
|
143566
|
+
}
|
|
143567
|
+
function rowToEvent(row) {
|
|
143568
|
+
return {
|
|
143569
|
+
id: String(row.id),
|
|
143570
|
+
projectId: String(row.project_id),
|
|
143571
|
+
candidateKind: row.candidate_kind,
|
|
143572
|
+
candidateId: String(row.candidate_id),
|
|
143573
|
+
signal: row.signal,
|
|
143574
|
+
...row.observed_at ? { at: String(row.observed_at) } : { at: (/* @__PURE__ */ new Date()).toISOString() },
|
|
143575
|
+
...row.actor ? { actor: String(row.actor) } : {},
|
|
143576
|
+
...row.note ? { note: String(row.note) } : {},
|
|
143577
|
+
...row.source_ref ? { sourceRef: String(row.source_ref) } : {},
|
|
143578
|
+
...row.target_event_id ? { targetEventId: String(row.target_event_id) } : {},
|
|
143579
|
+
delta: Number(row.delta ?? 0)
|
|
143580
|
+
};
|
|
143581
|
+
}
|
|
143582
|
+
var FEEDBACK_DELTAS, MemoryFeedbackStore;
|
|
143583
|
+
var init_feedback = __esm({
|
|
143584
|
+
"src/memory/feedback.ts"() {
|
|
143585
|
+
"use strict";
|
|
143586
|
+
init_esm_shims();
|
|
143587
|
+
init_sqlite_db();
|
|
143588
|
+
init_feedback_model();
|
|
143589
|
+
FEEDBACK_DELTAS = {
|
|
143590
|
+
"user-correction": -0.35,
|
|
143591
|
+
"verification-success": 0.25,
|
|
143592
|
+
"verification-failure": -0.25,
|
|
143593
|
+
"code-change": -0.15,
|
|
143594
|
+
used: 0.1,
|
|
143595
|
+
"not-used": -0.05,
|
|
143596
|
+
"code-conflict": -0.4,
|
|
143597
|
+
strengthen: 0.2,
|
|
143598
|
+
weaken: -0.2
|
|
143599
|
+
};
|
|
143600
|
+
MemoryFeedbackStore = class {
|
|
143601
|
+
db = null;
|
|
143602
|
+
async init(dataDir) {
|
|
143603
|
+
this.db = getDatabase(dataDir);
|
|
143604
|
+
}
|
|
143605
|
+
requireDb() {
|
|
143606
|
+
if (!this.db) throw new Error("MemoryFeedbackStore is not initialized.");
|
|
143607
|
+
return this.db;
|
|
143608
|
+
}
|
|
143609
|
+
loadEvents(projectId, candidateKind, candidateId) {
|
|
143610
|
+
return this.requireDb().prepare(`
|
|
143611
|
+
SELECT * FROM memory_feedback_events
|
|
143612
|
+
WHERE project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
143613
|
+
ORDER BY observed_at ASC, rowid ASC
|
|
143614
|
+
`).all(projectId, candidateKind, candidateId).map(rowToEvent);
|
|
143615
|
+
}
|
|
143616
|
+
rebuild(projectId, candidateKind, candidateId) {
|
|
143617
|
+
const events = this.loadEvents(projectId, candidateKind, candidateId);
|
|
143618
|
+
const revoked = new Set(events.filter((event) => event.signal === "revoke" && event.targetEventId).map((event) => event.targetEventId));
|
|
143619
|
+
let state = { weight: 1, status: "active", audit: [] };
|
|
143620
|
+
for (const event of events) {
|
|
143621
|
+
if (event.signal === "revoke" || revoked.has(event.id)) {
|
|
143622
|
+
state.audit.push(event);
|
|
143623
|
+
continue;
|
|
143624
|
+
}
|
|
143625
|
+
state = applyMemoryFeedback(state, event);
|
|
143626
|
+
}
|
|
143627
|
+
this.requireDb().prepare(`
|
|
143628
|
+
INSERT INTO memory_feedback_states (project_id, candidate_kind, candidate_id, weight, lifecycle_status, updated_at)
|
|
143629
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
143630
|
+
ON CONFLICT(project_id, candidate_kind, candidate_id) DO UPDATE SET
|
|
143631
|
+
weight = excluded.weight, lifecycle_status = excluded.lifecycle_status, updated_at = excluded.updated_at
|
|
143632
|
+
`).run(projectId, candidateKind, candidateId, state.weight, state.status, (/* @__PURE__ */ new Date()).toISOString());
|
|
143633
|
+
return state;
|
|
143634
|
+
}
|
|
143635
|
+
getState(projectId, candidateKind, candidateId) {
|
|
143636
|
+
const row = this.requireDb().prepare(`
|
|
143637
|
+
SELECT weight, lifecycle_status FROM memory_feedback_states
|
|
143638
|
+
WHERE project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
143639
|
+
`).get(projectId, candidateKind, candidateId);
|
|
143640
|
+
if (!row) return { weight: 1, status: "active", audit: [] };
|
|
143641
|
+
return {
|
|
143642
|
+
weight: Number(row.weight ?? 1),
|
|
143643
|
+
status: row.lifecycle_status ?? "active",
|
|
143644
|
+
audit: this.loadEvents(projectId, candidateKind, candidateId)
|
|
143645
|
+
};
|
|
143646
|
+
}
|
|
143647
|
+
listStates(projectId, candidateKind = "observation") {
|
|
143648
|
+
return this.requireDb().prepare(`
|
|
143649
|
+
SELECT candidate_id, weight, lifecycle_status, updated_at
|
|
143650
|
+
FROM memory_feedback_states WHERE project_id = ? AND candidate_kind = ?
|
|
143651
|
+
ORDER BY updated_at DESC
|
|
143652
|
+
`).all(projectId, candidateKind).map((row) => ({
|
|
143653
|
+
candidateId: String(row.candidate_id),
|
|
143654
|
+
weight: Number(row.weight),
|
|
143655
|
+
status: row.lifecycle_status,
|
|
143656
|
+
updatedAt: String(row.updated_at)
|
|
143657
|
+
}));
|
|
143658
|
+
}
|
|
143659
|
+
weights(projectId, candidateKind = "observation") {
|
|
143660
|
+
const states = /* @__PURE__ */ new Map();
|
|
143661
|
+
for (const row of this.listStates(projectId, candidateKind)) {
|
|
143662
|
+
states.set(row.candidateId, this.getState(projectId, candidateKind, row.candidateId));
|
|
143663
|
+
}
|
|
143664
|
+
return states;
|
|
143665
|
+
}
|
|
143666
|
+
record(input) {
|
|
143667
|
+
if (input.signal === "revoke" && !input.targetEventId) {
|
|
143668
|
+
throw new Error("A revoke feedback event requires targetEventId.");
|
|
143669
|
+
}
|
|
143670
|
+
if (input.signal === "revoke") {
|
|
143671
|
+
const target = this.requireDb().prepare(`
|
|
143672
|
+
SELECT 1 FROM memory_feedback_events
|
|
143673
|
+
WHERE id = ? AND project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
143674
|
+
`).get(input.targetEventId, input.projectId, input.candidateKind, input.candidateId);
|
|
143675
|
+
if (!target) throw new Error("The feedback event to revoke was not found in the same candidate scope.");
|
|
143676
|
+
}
|
|
143677
|
+
const event = {
|
|
143678
|
+
id: randomUUID7(),
|
|
143679
|
+
projectId: input.projectId,
|
|
143680
|
+
candidateKind: input.candidateKind,
|
|
143681
|
+
candidateId: input.candidateId,
|
|
143682
|
+
signal: input.signal,
|
|
143683
|
+
sourceRef: input.sourceRef,
|
|
143684
|
+
...input.actor ? { actor: input.actor } : {},
|
|
143685
|
+
...input.note ? { note: input.note.slice(0, 2e3) } : {},
|
|
143686
|
+
...input.targetEventId ? { targetEventId: input.targetEventId } : {},
|
|
143687
|
+
at: input.at ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
143688
|
+
delta: input.signal === "revoke" ? 0 : FEEDBACK_DELTAS[input.signal]
|
|
143689
|
+
};
|
|
143690
|
+
this.requireDb().prepare(`
|
|
143691
|
+
INSERT INTO memory_feedback_events (
|
|
143692
|
+
id, project_id, candidate_kind, candidate_id, signal, actor, note,
|
|
143693
|
+
source_ref, target_event_id, delta, observed_at
|
|
143694
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
143695
|
+
`).run(
|
|
143696
|
+
event.id,
|
|
143697
|
+
event.projectId,
|
|
143698
|
+
event.candidateKind,
|
|
143699
|
+
event.candidateId,
|
|
143700
|
+
event.signal,
|
|
143701
|
+
event.actor ?? null,
|
|
143702
|
+
event.note ?? null,
|
|
143703
|
+
event.sourceRef,
|
|
143704
|
+
event.targetEventId ?? null,
|
|
143705
|
+
event.delta,
|
|
143706
|
+
event.at
|
|
143707
|
+
);
|
|
143708
|
+
return { event, state: this.rebuild(input.projectId, input.candidateKind, input.candidateId) };
|
|
143709
|
+
}
|
|
143710
|
+
audit(projectId, candidateKind, candidateId, limit2 = 100) {
|
|
143711
|
+
return this.requireDb().prepare(`
|
|
143712
|
+
SELECT * FROM memory_feedback_events
|
|
143713
|
+
WHERE project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
143714
|
+
ORDER BY observed_at DESC, rowid DESC LIMIT ?
|
|
143715
|
+
`).all(projectId, candidateKind, candidateId, Math.min(200, Math.max(1, Math.floor(limit2)))).map(rowToEvent);
|
|
143716
|
+
}
|
|
143717
|
+
};
|
|
143718
|
+
}
|
|
143719
|
+
});
|
|
143720
|
+
|
|
142912
143721
|
// src/memory/retention.ts
|
|
142913
143722
|
var retention_exports = {};
|
|
142914
143723
|
__export(retention_exports, {
|
|
@@ -142950,6 +143759,7 @@ function getEffectiveRetentionDays(doc) {
|
|
|
142950
143759
|
}
|
|
142951
143760
|
function isImmune(doc) {
|
|
142952
143761
|
if (doc.type === "probe") return false;
|
|
143762
|
+
if (doc.feedbackStatus === "archived") return false;
|
|
142953
143763
|
if (doc.admissionState === "candidate" || doc.admissionState === "ephemeral") return false;
|
|
142954
143764
|
if (doc.valueCategory === "core") return true;
|
|
142955
143765
|
const importance = getImportanceLevel(doc);
|
|
@@ -142982,7 +143792,8 @@ function calculateRelevance(doc, referenceTime) {
|
|
|
142982
143792
|
const decayFactor = Math.exp(-ageDays / retention);
|
|
142983
143793
|
const accessCount = doc.accessCount ?? 0;
|
|
142984
143794
|
const accessBoost = Math.min(2, 1 + 0.1 * accessCount);
|
|
142985
|
-
|
|
143795
|
+
const feedbackMultiplier = doc.feedbackWeight === void 0 ? 1 : feedbackWeightMultiplier(doc.feedbackWeight);
|
|
143796
|
+
let totalScore = base * decayFactor * accessBoost * feedbackMultiplier;
|
|
142986
143797
|
const immune = isImmune(doc);
|
|
142987
143798
|
if (immune) {
|
|
142988
143799
|
totalScore = Math.max(totalScore, 0.5);
|
|
@@ -142994,7 +143805,8 @@ function calculateRelevance(doc, referenceTime) {
|
|
|
142994
143805
|
decayFactor,
|
|
142995
143806
|
accessBoost,
|
|
142996
143807
|
ageDays,
|
|
142997
|
-
isImmune: immune
|
|
143808
|
+
isImmune: immune,
|
|
143809
|
+
feedbackMultiplier
|
|
142998
143810
|
};
|
|
142999
143811
|
}
|
|
143000
143812
|
function rankByRelevance(docs, referenceTime) {
|
|
@@ -143002,6 +143814,7 @@ function rankByRelevance(docs, referenceTime) {
|
|
|
143002
143814
|
}
|
|
143003
143815
|
function getRetentionZone(doc, referenceTime) {
|
|
143004
143816
|
const now3 = referenceTime ?? /* @__PURE__ */ new Date();
|
|
143817
|
+
if (doc.feedbackStatus === "archived") return "archive-candidate";
|
|
143005
143818
|
const importance = getImportanceLevel(doc);
|
|
143006
143819
|
const retention = getEffectiveRetentionDays(doc);
|
|
143007
143820
|
const createdAt = new Date(doc.createdAt);
|
|
@@ -143073,7 +143886,7 @@ function explainRetention(doc, referenceTime) {
|
|
|
143073
143886
|
summary: parts.join(" ; ")
|
|
143074
143887
|
};
|
|
143075
143888
|
}
|
|
143076
|
-
function toRetentionDocument(obs, accessMap) {
|
|
143889
|
+
function toRetentionDocument(obs, accessMap, feedback) {
|
|
143077
143890
|
const access2 = accessMap?.get(obs.id);
|
|
143078
143891
|
return {
|
|
143079
143892
|
id: `obs-${obs.id}`,
|
|
@@ -143095,11 +143908,12 @@ function toRetentionDocument(obs, accessMap) {
|
|
|
143095
143908
|
sourceDetail: obs.sourceDetail ?? "",
|
|
143096
143909
|
valueCategory: obs.valueCategory ?? "",
|
|
143097
143910
|
admissionState: obs.admissionState ?? "",
|
|
143098
|
-
admissionReason: obs.admissionReason ?? ""
|
|
143911
|
+
admissionReason: obs.admissionReason ?? "",
|
|
143912
|
+
...feedback ? { feedbackWeight: feedback.weight, feedbackStatus: feedback.status } : {}
|
|
143099
143913
|
};
|
|
143100
143914
|
}
|
|
143101
143915
|
function projectObservationRetention(observation, options = {}) {
|
|
143102
|
-
const document2 = toRetentionDocument(observation, options.accessMap);
|
|
143916
|
+
const document2 = toRetentionDocument(observation, options.accessMap, options.feedback);
|
|
143103
143917
|
const relevance = calculateRelevance(document2, options.referenceTime);
|
|
143104
143918
|
const explanation = explainRetention(document2, options.referenceTime);
|
|
143105
143919
|
return {
|
|
@@ -143124,7 +143938,17 @@ function summarizeRetentionProjections(projections) {
|
|
|
143124
143938
|
}
|
|
143125
143939
|
return { active, stale, archiveCandidates, immune };
|
|
143126
143940
|
}
|
|
143127
|
-
async function
|
|
143941
|
+
async function loadFeedbackStore(dataDir) {
|
|
143942
|
+
try {
|
|
143943
|
+
const { MemoryFeedbackStore: MemoryFeedbackStore2 } = await Promise.resolve().then(() => (init_feedback(), feedback_exports));
|
|
143944
|
+
const store = new MemoryFeedbackStore2();
|
|
143945
|
+
await store.init(dataDir);
|
|
143946
|
+
return store;
|
|
143947
|
+
} catch {
|
|
143948
|
+
return void 0;
|
|
143949
|
+
}
|
|
143950
|
+
}
|
|
143951
|
+
async function archiveExpiredBatch(projectDir2, options) {
|
|
143128
143952
|
const store = getObservationStore();
|
|
143129
143953
|
const limit2 = Math.min(500, Math.max(1, Math.floor(options.limit ?? 100)));
|
|
143130
143954
|
const afterId = Math.max(0, Math.floor(options.afterId ?? 0));
|
|
@@ -143133,11 +143957,13 @@ async function archiveExpiredBatch(_projectDir, options) {
|
|
|
143133
143957
|
afterId,
|
|
143134
143958
|
limit: limit2 + 1
|
|
143135
143959
|
});
|
|
143960
|
+
const feedback = await loadFeedbackStore(projectDir2);
|
|
143136
143961
|
const hasMore = page.length > limit2;
|
|
143137
143962
|
const scanned = hasMore ? page.slice(0, limit2) : page;
|
|
143138
143963
|
const candidateIds = scanned.filter((observation) => !options.reader || canManageObservation(observation, options.reader)).filter((observation) => projectObservationRetention(observation, {
|
|
143139
143964
|
accessMap: options.accessMap,
|
|
143140
|
-
referenceTime: options.referenceTime
|
|
143965
|
+
referenceTime: options.referenceTime,
|
|
143966
|
+
...feedback ? { feedback: feedback.getState(options.projectId, "observation", String(observation.id)) } : {}
|
|
143141
143967
|
}).zone === "archive-candidate").map((observation) => observation.id);
|
|
143142
143968
|
const archived = candidateIds.length === 0 ? 0 : await store.atomic(async (tx) => {
|
|
143143
143969
|
const updates = await Promise.all(
|
|
@@ -143168,6 +143994,7 @@ async function archiveExpired(projectDir2, referenceTime, accessMap, projectId,
|
|
|
143168
143994
|
const remaining = reader ? remainingObservations.filter((observation) => canManageObservation(observation, reader)).length : remainingObservations.length;
|
|
143169
143995
|
return { archived, remaining };
|
|
143170
143996
|
}
|
|
143997
|
+
const feedback = await loadFeedbackStore(projectDir2);
|
|
143171
143998
|
return await store.atomic(async (tx) => {
|
|
143172
143999
|
const allObs = await tx.loadAll();
|
|
143173
144000
|
const activeObs = allObs.filter(
|
|
@@ -143175,7 +144002,11 @@ async function archiveExpired(projectDir2, referenceTime, accessMap, projectId,
|
|
|
143175
144002
|
);
|
|
143176
144003
|
const archivedIds = [];
|
|
143177
144004
|
for (const obs of activeObs) {
|
|
143178
|
-
const retention = projectObservationRetention(obs, {
|
|
144005
|
+
const retention = projectObservationRetention(obs, {
|
|
144006
|
+
accessMap,
|
|
144007
|
+
referenceTime,
|
|
144008
|
+
...feedback ? { feedback: feedback.getState(obs.projectId, "observation", String(obs.id)) } : {}
|
|
144009
|
+
});
|
|
143179
144010
|
if (retention.zone === "archive-candidate") {
|
|
143180
144011
|
archivedIds.push(obs.id);
|
|
143181
144012
|
}
|
|
@@ -143195,6 +144026,7 @@ var init_retention = __esm({
|
|
|
143195
144026
|
init_esm_shims();
|
|
143196
144027
|
init_obs_store();
|
|
143197
144028
|
init_visibility();
|
|
144029
|
+
init_feedback_model();
|
|
143198
144030
|
RETENTION_DAYS = {
|
|
143199
144031
|
critical: 365,
|
|
143200
144032
|
high: 180,
|
|
@@ -143231,7 +144063,7 @@ var init_retention = __esm({
|
|
|
143231
144063
|
});
|
|
143232
144064
|
|
|
143233
144065
|
// src/memory/owner.ts
|
|
143234
|
-
import { randomUUID as
|
|
144066
|
+
import { randomUUID as randomUUID8 } from "crypto";
|
|
143235
144067
|
import { promises as fs9 } from "fs";
|
|
143236
144068
|
import path17 from "path";
|
|
143237
144069
|
function ownerPath(dataDir) {
|
|
@@ -143261,7 +144093,7 @@ async function resolveLocalMemoryOwner(dataDir, options = {}) {
|
|
|
143261
144093
|
await fs9.mkdir(path17.dirname(filePath), { recursive: true });
|
|
143262
144094
|
const created = {
|
|
143263
144095
|
version: 1,
|
|
143264
|
-
id: "local-" +
|
|
144096
|
+
id: "local-" + randomUUID8(),
|
|
143265
144097
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
143266
144098
|
};
|
|
143267
144099
|
try {
|
|
@@ -143284,7 +144116,7 @@ var init_owner = __esm({
|
|
|
143284
144116
|
});
|
|
143285
144117
|
|
|
143286
144118
|
// src/memory/long-term-store.ts
|
|
143287
|
-
import { randomUUID as
|
|
144119
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
143288
144120
|
function optionalText2(value) {
|
|
143289
144121
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
143290
144122
|
}
|
|
@@ -143335,7 +144167,7 @@ function rowToEvidence(row) {
|
|
|
143335
144167
|
createdAt: row.createdAt
|
|
143336
144168
|
};
|
|
143337
144169
|
}
|
|
143338
|
-
function
|
|
144170
|
+
function rowToEvent2(row) {
|
|
143339
144171
|
return {
|
|
143340
144172
|
id: row.id,
|
|
143341
144173
|
memoryId: row.memoryId,
|
|
@@ -143444,7 +144276,7 @@ var init_long_term_store = __esm({
|
|
|
143444
144276
|
}
|
|
143445
144277
|
insertEvidence(input) {
|
|
143446
144278
|
const evidence = {
|
|
143447
|
-
id:
|
|
144279
|
+
id: randomUUID9(),
|
|
143448
144280
|
...input,
|
|
143449
144281
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
143450
144282
|
};
|
|
@@ -143471,7 +144303,7 @@ var init_long_term_store = __esm({
|
|
|
143471
144303
|
}
|
|
143472
144304
|
recordEvent(input) {
|
|
143473
144305
|
const event = {
|
|
143474
|
-
id:
|
|
144306
|
+
id: randomUUID9(),
|
|
143475
144307
|
...input,
|
|
143476
144308
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
143477
144309
|
};
|
|
@@ -143492,7 +144324,7 @@ var init_long_term_store = __esm({
|
|
|
143492
144324
|
listEvents(memoryId) {
|
|
143493
144325
|
return this.db.prepare(`
|
|
143494
144326
|
SELECT * FROM long_term_memory_events WHERE memoryId = ? ORDER BY createdAt ASC, rowid ASC
|
|
143495
|
-
`).all(memoryId).map(
|
|
144327
|
+
`).all(memoryId).map(rowToEvent2);
|
|
143496
144328
|
}
|
|
143497
144329
|
markAccess(ids, at = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
143498
144330
|
const unique = [...new Set(ids.filter(Boolean))];
|
|
@@ -143561,7 +144393,7 @@ __export(long_term_exports, {
|
|
|
143561
144393
|
selectLongTermMemoriesForTask: () => selectLongTermMemoriesForTask,
|
|
143562
144394
|
supersedeLongTermMemory: () => supersedeLongTermMemory
|
|
143563
144395
|
});
|
|
143564
|
-
import { randomUUID as
|
|
144396
|
+
import { randomUUID as randomUUID10 } from "crypto";
|
|
143565
144397
|
function isOneOf(value, values) {
|
|
143566
144398
|
return typeof value === "string" && values.includes(value);
|
|
143567
144399
|
}
|
|
@@ -143743,7 +144575,7 @@ async function createManualLongTermMemory(input) {
|
|
|
143743
144575
|
const owner = await resolveLocalMemoryOwner(input.dataDir, { create: true });
|
|
143744
144576
|
if (!owner) throw new Error("Memorix could not resolve a local memory owner.");
|
|
143745
144577
|
assertScope(input.scope);
|
|
143746
|
-
const evidence = input.scope === "user" ? [{ kind: "user", referenceId: owner.id, relation: "user-confirmed" }] : [{ kind: "manual", referenceId: "manual:" +
|
|
144578
|
+
const evidence = input.scope === "user" ? [{ kind: "user", referenceId: owner.id, relation: "user-confirmed" }] : [{ kind: "manual", referenceId: "manual:" + randomUUID10(), relation: "supports" }];
|
|
143747
144579
|
return createLongTermMemoryWithDataDir({
|
|
143748
144580
|
dataDir: input.dataDir,
|
|
143749
144581
|
originProjectId: input.projectId,
|
|
@@ -143798,7 +144630,7 @@ async function createLongTermMemoryWithDataDir(input) {
|
|
|
143798
144630
|
assertPortableEvidence(input.scope, portability, evidenceInputs);
|
|
143799
144631
|
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
143800
144632
|
const memory = {
|
|
143801
|
-
id:
|
|
144633
|
+
id: randomUUID10(),
|
|
143802
144634
|
originProjectId: compactText(input.originProjectId, "origin project id", 1e3),
|
|
143803
144635
|
ownerId: compactText(input.ownerId, "owner id", 160),
|
|
143804
144636
|
scope: input.scope,
|
|
@@ -144116,9 +144948,9 @@ var init_long_term = __esm({
|
|
|
144116
144948
|
});
|
|
144117
144949
|
|
|
144118
144950
|
// src/codegraph/ids.ts
|
|
144119
|
-
import { createHash as
|
|
144951
|
+
import { createHash as createHash6 } from "crypto";
|
|
144120
144952
|
function digest(input) {
|
|
144121
|
-
return
|
|
144953
|
+
return createHash6("sha256").update(input).digest("hex").slice(0, 16);
|
|
144122
144954
|
}
|
|
144123
144955
|
function normalizeCodePath(path22) {
|
|
144124
144956
|
return path22.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+/g, "/");
|
|
@@ -144153,7 +144985,7 @@ var store_exports = {};
|
|
|
144153
144985
|
__export(store_exports, {
|
|
144154
144986
|
CodeGraphStore: () => CodeGraphStore
|
|
144155
144987
|
});
|
|
144156
|
-
import { randomUUID as
|
|
144988
|
+
import { randomUUID as randomUUID11 } from "crypto";
|
|
144157
144989
|
import { posix as pathPosix } from "path";
|
|
144158
144990
|
function rowToFile(row) {
|
|
144159
144991
|
return {
|
|
@@ -144870,7 +145702,7 @@ var init_store = __esm({
|
|
|
144870
145702
|
* so an interrupted scan cannot be advertised as complete.
|
|
144871
145703
|
*/
|
|
144872
145704
|
recordCodeStateSnapshot(input) {
|
|
144873
|
-
const id =
|
|
145705
|
+
const id = randomUUID11();
|
|
144874
145706
|
let snapshot;
|
|
144875
145707
|
const tx = this.db.transaction(() => {
|
|
144876
145708
|
const previous = this.db.prepare(
|
|
@@ -144948,7 +145780,7 @@ var init_store = __esm({
|
|
|
144948
145780
|
|
|
144949
145781
|
// src/codegraph/code-state.ts
|
|
144950
145782
|
import { execFile as execFile2 } from "child_process";
|
|
144951
|
-
import { createHash as
|
|
145783
|
+
import { createHash as createHash7 } from "crypto";
|
|
144952
145784
|
import { promisify as promisify3 } from "util";
|
|
144953
145785
|
async function runGit(rootPath, args) {
|
|
144954
145786
|
try {
|
|
@@ -144977,7 +145809,7 @@ function changedPathCount(status) {
|
|
|
144977
145809
|
return count2;
|
|
144978
145810
|
}
|
|
144979
145811
|
function fingerprint(baseRevision, status) {
|
|
144980
|
-
return
|
|
145812
|
+
return createHash7("sha256").update(baseRevision ?? "").update("\0").update(status).digest("hex");
|
|
144981
145813
|
}
|
|
144982
145814
|
async function collectCodeStateSnapshot(input) {
|
|
144983
145815
|
const [revision, status] = await Promise.all([
|
|
@@ -145077,11 +145909,11 @@ __export(lite_provider_exports, {
|
|
|
145077
145909
|
indexProjectLite: () => indexProjectLite,
|
|
145078
145910
|
refreshProjectLite: () => refreshProjectLite
|
|
145079
145911
|
});
|
|
145080
|
-
import { createHash as
|
|
145912
|
+
import { createHash as createHash8 } from "crypto";
|
|
145081
145913
|
import { readdirSync as readdirSync2, readFileSync as readFileSync7, statSync as statSync3 } from "fs";
|
|
145082
145914
|
import { join as join4, relative } from "path";
|
|
145083
145915
|
function hashText(text2) {
|
|
145084
|
-
return
|
|
145916
|
+
return createHash8("sha256").update(text2).digest("hex");
|
|
145085
145917
|
}
|
|
145086
145918
|
function extension2(path22) {
|
|
145087
145919
|
const index = path22.lastIndexOf(".");
|
|
@@ -145648,7 +146480,7 @@ var claim_store_exports = {};
|
|
|
145648
146480
|
__export(claim_store_exports, {
|
|
145649
146481
|
ClaimStore: () => ClaimStore
|
|
145650
146482
|
});
|
|
145651
|
-
import { createHash as
|
|
146483
|
+
import { createHash as createHash9, randomUUID as randomUUID12 } from "crypto";
|
|
145652
146484
|
function optionalText3(value) {
|
|
145653
146485
|
return typeof value === "string" && value ? value : void 0;
|
|
145654
146486
|
}
|
|
@@ -145687,7 +146519,7 @@ function rowToEvidence2(row) {
|
|
|
145687
146519
|
createdAt: row.createdAt
|
|
145688
146520
|
};
|
|
145689
146521
|
}
|
|
145690
|
-
function
|
|
146522
|
+
function rowToEvent3(row) {
|
|
145691
146523
|
return {
|
|
145692
146524
|
id: row.id,
|
|
145693
146525
|
projectId: row.projectId,
|
|
@@ -145701,7 +146533,7 @@ function rowToEvent2(row) {
|
|
|
145701
146533
|
};
|
|
145702
146534
|
}
|
|
145703
146535
|
function evidenceKey(input) {
|
|
145704
|
-
return
|
|
146536
|
+
return createHash9("sha256").update(JSON.stringify([
|
|
145705
146537
|
input.evidenceKind,
|
|
145706
146538
|
input.evidenceId,
|
|
145707
146539
|
input.relation,
|
|
@@ -145832,7 +146664,7 @@ var init_claim_store = __esm({
|
|
|
145832
146664
|
locator, capturedHash, evidenceKey, createdAt
|
|
145833
146665
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
145834
146666
|
`).run(
|
|
145835
|
-
|
|
146667
|
+
randomUUID12(),
|
|
145836
146668
|
input.claimId,
|
|
145837
146669
|
input.evidenceKind,
|
|
145838
146670
|
input.evidenceId,
|
|
@@ -145854,7 +146686,7 @@ var init_claim_store = __esm({
|
|
|
145854
146686
|
}
|
|
145855
146687
|
recordEvent(input) {
|
|
145856
146688
|
const event = {
|
|
145857
|
-
id:
|
|
146689
|
+
id: randomUUID12(),
|
|
145858
146690
|
...input,
|
|
145859
146691
|
...input.detail ? { detail: sanitizeCredentials(input.detail) } : {},
|
|
145860
146692
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -145882,7 +146714,7 @@ var init_claim_store = __esm({
|
|
|
145882
146714
|
SELECT * FROM knowledge_claim_events
|
|
145883
146715
|
WHERE claimId = ?
|
|
145884
146716
|
ORDER BY createdAt ASC, id
|
|
145885
|
-
`).all(claimId).map(
|
|
146717
|
+
`).all(claimId).map(rowToEvent3);
|
|
145886
146718
|
}
|
|
145887
146719
|
};
|
|
145888
146720
|
}
|
|
@@ -145899,7 +146731,7 @@ __export(claims_exports, {
|
|
|
145899
146731
|
supersedeClaim: () => supersedeClaim,
|
|
145900
146732
|
writeClaim: () => writeClaim
|
|
145901
146733
|
});
|
|
145902
|
-
import { createHash as
|
|
146734
|
+
import { createHash as createHash10, randomUUID as randomUUID13 } from "crypto";
|
|
145903
146735
|
function compactText2(value, field) {
|
|
145904
146736
|
if (typeof value !== "string") throw new Error("Claim " + field + " must be text");
|
|
145905
146737
|
const sanitized = sanitizeCredentials(value).trim().replace(/\s+/g, " ");
|
|
@@ -145911,7 +146743,7 @@ function normalizedTerm(value) {
|
|
|
145911
146743
|
return compactText2(value, "identity").toLocaleLowerCase("en-US");
|
|
145912
146744
|
}
|
|
145913
146745
|
function hashIdentity(parts) {
|
|
145914
|
-
return
|
|
146746
|
+
return createHash10("sha256").update(parts.join(String.fromCharCode(31))).digest("hex");
|
|
145915
146747
|
}
|
|
145916
146748
|
function buildClaimIdentity(input) {
|
|
145917
146749
|
const subject = normalizedTerm(input.subject);
|
|
@@ -145985,7 +146817,7 @@ function normalizeClaimInput(input) {
|
|
|
145985
146817
|
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
145986
146818
|
return {
|
|
145987
146819
|
claim: {
|
|
145988
|
-
id:
|
|
146820
|
+
id: randomUUID13(),
|
|
145989
146821
|
projectId,
|
|
145990
146822
|
subject,
|
|
145991
146823
|
predicate,
|
|
@@ -146152,7 +146984,7 @@ function supersedeClaim(store, input) {
|
|
|
146152
146984
|
});
|
|
146153
146985
|
}
|
|
146154
146986
|
function hashObservation(observation) {
|
|
146155
|
-
return
|
|
146987
|
+
return createHash10("sha256").update(JSON.stringify([
|
|
146156
146988
|
observation.title,
|
|
146157
146989
|
observation.narrative,
|
|
146158
146990
|
observation.facts,
|
|
@@ -146396,11 +147228,11 @@ var init_frontmatter = __esm({
|
|
|
146396
147228
|
});
|
|
146397
147229
|
|
|
146398
147230
|
// src/knowledge/markdown.ts
|
|
146399
|
-
import { createHash as
|
|
147231
|
+
import { createHash as createHash11 } from "crypto";
|
|
146400
147232
|
import { promises as fs10 } from "fs";
|
|
146401
147233
|
import path18 from "path";
|
|
146402
147234
|
function hashContent(content) {
|
|
146403
|
-
return
|
|
147235
|
+
return createHash11("sha256").update(content).digest("hex");
|
|
146404
147236
|
}
|
|
146405
147237
|
function stringField(data, key) {
|
|
146406
147238
|
const value = data[key];
|
|
@@ -146526,11 +147358,11 @@ __export(wiki_exports, {
|
|
|
146526
147358
|
lintKnowledgeWorkspace: () => lintKnowledgeWorkspace,
|
|
146527
147359
|
readKnowledgePage: () => readKnowledgePage
|
|
146528
147360
|
});
|
|
146529
|
-
import { createHash as
|
|
147361
|
+
import { createHash as createHash12 } from "crypto";
|
|
146530
147362
|
import { promises as fs11 } from "fs";
|
|
146531
147363
|
import path19 from "path";
|
|
146532
147364
|
function hash2(value) {
|
|
146533
|
-
return
|
|
147365
|
+
return createHash12("sha256").update(value).digest("hex");
|
|
146534
147366
|
}
|
|
146535
147367
|
function now() {
|
|
146536
147368
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -147070,7 +147902,7 @@ var init_workflow_sync = __esm({
|
|
|
147070
147902
|
});
|
|
147071
147903
|
|
|
147072
147904
|
// src/knowledge/workflow-store.ts
|
|
147073
|
-
import { randomUUID as
|
|
147905
|
+
import { randomUUID as randomUUID14 } from "crypto";
|
|
147074
147906
|
function parseJson(value, fallback) {
|
|
147075
147907
|
if (typeof value !== "string" || !value) return fallback;
|
|
147076
147908
|
try {
|
|
@@ -147170,7 +148002,7 @@ var init_workflow_store = __esm({
|
|
|
147170
148002
|
}
|
|
147171
148003
|
recordRun(input) {
|
|
147172
148004
|
const run = {
|
|
147173
|
-
id:
|
|
148005
|
+
id: randomUUID14(),
|
|
147174
148006
|
workflowId: input.workflowId,
|
|
147175
148007
|
projectId: input.projectId,
|
|
147176
148008
|
task: input.task.trim(),
|
|
@@ -147238,7 +148070,7 @@ var init_outcome_types = __esm({
|
|
|
147238
148070
|
});
|
|
147239
148071
|
|
|
147240
148072
|
// src/knowledge/outcome-store.ts
|
|
147241
|
-
import { randomUUID as
|
|
148073
|
+
import { randomUUID as randomUUID15 } from "crypto";
|
|
147242
148074
|
function optionalText5(value) {
|
|
147243
148075
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
147244
148076
|
}
|
|
@@ -147282,7 +148114,7 @@ var init_outcome_store = __esm({
|
|
|
147282
148114
|
}
|
|
147283
148115
|
record(input) {
|
|
147284
148116
|
const signal = {
|
|
147285
|
-
id:
|
|
148117
|
+
id: randomUUID15(),
|
|
147286
148118
|
projectId: text(input.projectId, "project id"),
|
|
147287
148119
|
candidateKind: oneOf(input.candidateKind, MEMORY_OUTCOME_CANDIDATE_KINDS, "candidate kind"),
|
|
147288
148120
|
candidateId: text(input.candidateId, "candidate id"),
|
|
@@ -147387,11 +148219,11 @@ __export(workflows_exports, {
|
|
|
147387
148219
|
syncCanonicalWorkflows: () => syncCanonicalWorkflows,
|
|
147388
148220
|
writeCanonicalWorkflow: () => writeCanonicalWorkflow
|
|
147389
148221
|
});
|
|
147390
|
-
import { createHash as
|
|
148222
|
+
import { createHash as createHash13 } from "crypto";
|
|
147391
148223
|
import { promises as fs12 } from "fs";
|
|
147392
148224
|
import path20 from "path";
|
|
147393
148225
|
function hash3(value) {
|
|
147394
|
-
return
|
|
148226
|
+
return createHash13("sha256").update(value).digest("hex");
|
|
147395
148227
|
}
|
|
147396
148228
|
function now2() {
|
|
147397
148229
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -148773,6 +149605,16 @@ async function bindObservationCodeRefsBestEffort(observation) {
|
|
|
148773
149605
|
} catch {
|
|
148774
149606
|
}
|
|
148775
149607
|
}
|
|
149608
|
+
async function persistEvidenceCard(observation) {
|
|
149609
|
+
if (!projectDir) return;
|
|
149610
|
+
try {
|
|
149611
|
+
const evidence = new EvidenceCardStore();
|
|
149612
|
+
await evidence.init(projectDir);
|
|
149613
|
+
evidence.upsertObservation(observation);
|
|
149614
|
+
} catch (error) {
|
|
149615
|
+
console.error(`[memorix] Evidence card projection failed for obs-${observation.id}: ${error instanceof Error ? error.message : String(error)}`);
|
|
149616
|
+
}
|
|
149617
|
+
}
|
|
148776
149618
|
function queueClaimDerivation(observation) {
|
|
148777
149619
|
const dataDir = projectDir;
|
|
148778
149620
|
const isExplicit = observation.sourceDetail === "explicit";
|
|
@@ -149119,6 +149961,7 @@ async function storeObservation(input) {
|
|
|
149119
149961
|
}
|
|
149120
149962
|
if (!persistedCallbackInvoked) await input.onPersisted?.(observation);
|
|
149121
149963
|
await bindObservationCodeRefsBestEffort(observation);
|
|
149964
|
+
await persistEvidenceCard(observation);
|
|
149122
149965
|
queueObservationQualification(observation);
|
|
149123
149966
|
if (resolveObservationVisibility(observation) === "project") {
|
|
149124
149967
|
queueClaimDerivation(observation);
|
|
@@ -149211,6 +150054,7 @@ async function upsertObservation(existing, input, now3) {
|
|
|
149211
150054
|
await store.update(existing);
|
|
149212
150055
|
}
|
|
149213
150056
|
await bindObservationCodeRefsBestEffort(existing);
|
|
150057
|
+
await persistEvidenceCard(existing);
|
|
149214
150058
|
queueObservationQualification(existing);
|
|
149215
150059
|
if (resolveObservationVisibility(existing) === "project") {
|
|
149216
150060
|
queueClaimDerivation(existing);
|
|
@@ -149344,6 +150188,7 @@ async function resolveObservations(ids, status = "resolved") {
|
|
|
149344
150188
|
await Promise.all(changed.map((observation) => tx.update(observation)));
|
|
149345
150189
|
});
|
|
149346
150190
|
}
|
|
150191
|
+
for (const observation of changed) await persistEvidenceCard(observation);
|
|
149347
150192
|
return { resolved, notFound };
|
|
149348
150193
|
}
|
|
149349
150194
|
function getProjectObservations(projectId) {
|
|
@@ -149681,6 +150526,7 @@ var init_observations = __esm({
|
|
|
149681
150526
|
init_secret_filter();
|
|
149682
150527
|
init_lifecycle();
|
|
149683
150528
|
init_visibility();
|
|
150529
|
+
init_evidence_store();
|
|
149684
150530
|
observations = [];
|
|
149685
150531
|
nextId = 1;
|
|
149686
150532
|
projectDir = null;
|