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
|
@@ -95,6 +95,8 @@ function loadEnvFile(filePath) {
|
|
|
95
95
|
const parsed = parse(readFileSync(filePath, "utf-8"));
|
|
96
96
|
for (const [key, value] of Object.entries(parsed)) {
|
|
97
97
|
if (!(key in process.env)) {
|
|
98
|
+
loadedEnvKeys.add(key);
|
|
99
|
+
loadedEnvValues.set(key, value);
|
|
98
100
|
process.env[key] = value;
|
|
99
101
|
injectedKeys.add(key);
|
|
100
102
|
}
|
|
@@ -107,6 +109,8 @@ function loadDotenv(projectRoot, options = {}) {
|
|
|
107
109
|
resetDotenv();
|
|
108
110
|
}
|
|
109
111
|
loadedEnvFiles.length = 0;
|
|
112
|
+
loadedEnvKeys.clear();
|
|
113
|
+
loadedEnvValues.clear();
|
|
110
114
|
if (projectRoot) {
|
|
111
115
|
loadEnvFile(getProjectDotenvPath(projectRoot));
|
|
112
116
|
}
|
|
@@ -122,11 +126,12 @@ function resetDotenv() {
|
|
|
122
126
|
dotenvLoaded = false;
|
|
123
127
|
dotenvProjectRoot = null;
|
|
124
128
|
loadedEnvFiles.length = 0;
|
|
129
|
+
loadedEnvKeys.clear();
|
|
125
130
|
}
|
|
126
131
|
function getLoadedEnvFiles() {
|
|
127
132
|
return loadedEnvFiles;
|
|
128
133
|
}
|
|
129
|
-
var dotenvLoaded, dotenvProjectRoot, loadedEnvFiles, injectedKeys;
|
|
134
|
+
var dotenvLoaded, dotenvProjectRoot, loadedEnvFiles, loadedEnvKeys, loadedEnvValues, injectedKeys;
|
|
130
135
|
var init_dotenv_loader = __esm({
|
|
131
136
|
"src/config/dotenv-loader.ts"() {
|
|
132
137
|
"use strict";
|
|
@@ -135,6 +140,8 @@ var init_dotenv_loader = __esm({
|
|
|
135
140
|
dotenvLoaded = false;
|
|
136
141
|
dotenvProjectRoot = null;
|
|
137
142
|
loadedEnvFiles = [];
|
|
143
|
+
loadedEnvKeys = /* @__PURE__ */ new Set();
|
|
144
|
+
loadedEnvValues = /* @__PURE__ */ new Map();
|
|
138
145
|
injectedKeys = /* @__PURE__ */ new Set();
|
|
139
146
|
}
|
|
140
147
|
});
|
|
@@ -176,6 +183,7 @@ function loadYamlConfig(projectRoot) {
|
|
|
176
183
|
llm: { ...userConfig.llm, ...projectConfig.llm },
|
|
177
184
|
agent: { ...userConfig.agent, ...projectConfig.agent },
|
|
178
185
|
embedding: { ...userConfig.embedding, ...projectConfig.embedding },
|
|
186
|
+
rerank: { ...userConfig.rerank, ...projectConfig.rerank },
|
|
179
187
|
git: { ...userConfig.git, ...projectConfig.git },
|
|
180
188
|
codegraph: { ...userConfig.codegraph, ...projectConfig.codegraph },
|
|
181
189
|
behavior: { ...userConfig.behavior, ...projectConfig.behavior },
|
|
@@ -517,7 +525,7 @@ function closeAllDatabases() {
|
|
|
517
525
|
_dbCache.delete(key);
|
|
518
526
|
}
|
|
519
527
|
}
|
|
520
|
-
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;
|
|
528
|
+
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;
|
|
521
529
|
var init_sqlite_db = __esm({
|
|
522
530
|
"src/store/sqlite-db.ts"() {
|
|
523
531
|
"use strict";
|
|
@@ -1163,6 +1171,79 @@ CREATE TABLE IF NOT EXISTS compaction_checkpoints (
|
|
|
1163
1171
|
created_at TEXT NOT NULL,
|
|
1164
1172
|
updated_at TEXT NOT NULL
|
|
1165
1173
|
);
|
|
1174
|
+
`;
|
|
1175
|
+
CREATE_EVIDENCE_CARDS_TABLE = `
|
|
1176
|
+
CREATE TABLE IF NOT EXISTS evidence_cards (
|
|
1177
|
+
id TEXT PRIMARY KEY,
|
|
1178
|
+
project_id TEXT NOT NULL,
|
|
1179
|
+
candidate_kind TEXT NOT NULL,
|
|
1180
|
+
candidate_id TEXT NOT NULL,
|
|
1181
|
+
title TEXT NOT NULL,
|
|
1182
|
+
summary TEXT NOT NULL DEFAULT '',
|
|
1183
|
+
entity_name TEXT,
|
|
1184
|
+
source_kind TEXT NOT NULL,
|
|
1185
|
+
source_ref TEXT NOT NULL,
|
|
1186
|
+
locator TEXT,
|
|
1187
|
+
captured_hash TEXT,
|
|
1188
|
+
session_id TEXT,
|
|
1189
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
1190
|
+
verification TEXT NOT NULL DEFAULT 'unverified',
|
|
1191
|
+
freshness TEXT NOT NULL DEFAULT 'current',
|
|
1192
|
+
stale_reason TEXT,
|
|
1193
|
+
files_json TEXT NOT NULL DEFAULT '[]',
|
|
1194
|
+
related_entities_json TEXT NOT NULL DEFAULT '[]',
|
|
1195
|
+
created_at TEXT NOT NULL,
|
|
1196
|
+
updated_at TEXT NOT NULL,
|
|
1197
|
+
UNIQUE(project_id, candidate_kind, candidate_id)
|
|
1198
|
+
);
|
|
1199
|
+
`;
|
|
1200
|
+
CREATE_EVIDENCE_CARD_EVENTS_TABLE = `
|
|
1201
|
+
CREATE TABLE IF NOT EXISTS evidence_card_events (
|
|
1202
|
+
id TEXT PRIMARY KEY,
|
|
1203
|
+
project_id TEXT NOT NULL,
|
|
1204
|
+
card_id TEXT NOT NULL,
|
|
1205
|
+
kind TEXT NOT NULL,
|
|
1206
|
+
detail TEXT,
|
|
1207
|
+
created_at TEXT NOT NULL,
|
|
1208
|
+
FOREIGN KEY (card_id) REFERENCES evidence_cards(id) ON DELETE CASCADE
|
|
1209
|
+
);
|
|
1210
|
+
`;
|
|
1211
|
+
CREATE_MEMORY_FEEDBACK_STATES_TABLE = `
|
|
1212
|
+
CREATE TABLE IF NOT EXISTS memory_feedback_states (
|
|
1213
|
+
project_id TEXT NOT NULL,
|
|
1214
|
+
candidate_kind TEXT NOT NULL,
|
|
1215
|
+
candidate_id TEXT NOT NULL,
|
|
1216
|
+
weight REAL NOT NULL DEFAULT 1.0,
|
|
1217
|
+
lifecycle_status TEXT NOT NULL DEFAULT 'active',
|
|
1218
|
+
updated_at TEXT NOT NULL,
|
|
1219
|
+
PRIMARY KEY (project_id, candidate_kind, candidate_id)
|
|
1220
|
+
);
|
|
1221
|
+
`;
|
|
1222
|
+
CREATE_MEMORY_FEEDBACK_EVENTS_TABLE = `
|
|
1223
|
+
CREATE TABLE IF NOT EXISTS memory_feedback_events (
|
|
1224
|
+
id TEXT PRIMARY KEY,
|
|
1225
|
+
project_id TEXT NOT NULL,
|
|
1226
|
+
candidate_kind TEXT NOT NULL,
|
|
1227
|
+
candidate_id TEXT NOT NULL,
|
|
1228
|
+
signal TEXT NOT NULL,
|
|
1229
|
+
actor TEXT,
|
|
1230
|
+
note TEXT,
|
|
1231
|
+
source_ref TEXT NOT NULL,
|
|
1232
|
+
target_event_id TEXT,
|
|
1233
|
+
delta REAL NOT NULL DEFAULT 0,
|
|
1234
|
+
observed_at TEXT NOT NULL
|
|
1235
|
+
);
|
|
1236
|
+
`;
|
|
1237
|
+
CREATE_MCP_BINDINGS_TABLE = `
|
|
1238
|
+
CREATE TABLE IF NOT EXISTS mcp_bindings (
|
|
1239
|
+
handle_id TEXT PRIMARY KEY,
|
|
1240
|
+
project_id TEXT NOT NULL,
|
|
1241
|
+
project_root TEXT NOT NULL,
|
|
1242
|
+
data_dir TEXT NOT NULL,
|
|
1243
|
+
created_at TEXT NOT NULL,
|
|
1244
|
+
last_used_at TEXT NOT NULL,
|
|
1245
|
+
expires_at TEXT
|
|
1246
|
+
);
|
|
1166
1247
|
`;
|
|
1167
1248
|
CREATE_INDEXES = `
|
|
1168
1249
|
CREATE INDEX IF NOT EXISTS idx_observations_projectId ON observations(projectId);
|
|
@@ -1225,6 +1306,12 @@ CREATE INDEX IF NOT EXISTS idx_maintenance_targets_updated ON maintenance_target
|
|
|
1225
1306
|
CREATE INDEX IF NOT EXISTS idx_compaction_checkpoints_project_recent ON compaction_checkpoints(project_id, status, completed_at DESC, pre_captured_at DESC);
|
|
1226
1307
|
CREATE INDEX IF NOT EXISTS idx_compaction_checkpoints_session_pending ON compaction_checkpoints(project_id, session_id, agent, phase, status, pre_captured_at DESC);
|
|
1227
1308
|
CREATE INDEX IF NOT EXISTS idx_compaction_checkpoints_source ON compaction_checkpoints(project_id, source_key);
|
|
1309
|
+
CREATE INDEX IF NOT EXISTS idx_evidence_cards_project ON evidence_cards(project_id, status, updated_at DESC);
|
|
1310
|
+
CREATE INDEX IF NOT EXISTS idx_evidence_cards_candidate ON evidence_cards(project_id, candidate_kind, candidate_id);
|
|
1311
|
+
CREATE INDEX IF NOT EXISTS idx_evidence_card_events_card ON evidence_card_events(card_id, created_at);
|
|
1312
|
+
CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC);
|
|
1313
|
+
CREATE INDEX IF NOT EXISTS idx_memory_feedback_events_candidate ON memory_feedback_events(project_id, candidate_kind, candidate_id, observed_at DESC);
|
|
1314
|
+
CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC);
|
|
1228
1315
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
1229
1316
|
ON maintenance_jobs(project_id, kind, dedupe_key)
|
|
1230
1317
|
WHERE status IN ('pending', 'running', 'retry');
|
|
@@ -1380,6 +1467,22 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
|
1380
1467
|
}
|
|
1381
1468
|
db2.exec("CREATE INDEX IF NOT EXISTS idx_media_jobs_source_asset ON media_jobs(project_id, source_asset_id, status)");
|
|
1382
1469
|
}
|
|
1470
|
+
},
|
|
1471
|
+
{
|
|
1472
|
+
id: "1.8-context-control-plane",
|
|
1473
|
+
apply: (db2) => {
|
|
1474
|
+
db2.exec(CREATE_EVIDENCE_CARDS_TABLE);
|
|
1475
|
+
db2.exec(CREATE_EVIDENCE_CARD_EVENTS_TABLE);
|
|
1476
|
+
db2.exec(CREATE_MEMORY_FEEDBACK_STATES_TABLE);
|
|
1477
|
+
db2.exec(CREATE_MEMORY_FEEDBACK_EVENTS_TABLE);
|
|
1478
|
+
db2.exec(CREATE_MCP_BINDINGS_TABLE);
|
|
1479
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_evidence_cards_project ON evidence_cards(project_id, status, updated_at DESC)");
|
|
1480
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_evidence_cards_candidate ON evidence_cards(project_id, candidate_kind, candidate_id)");
|
|
1481
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_evidence_card_events_card ON evidence_card_events(card_id, created_at)");
|
|
1482
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC)");
|
|
1483
|
+
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)");
|
|
1484
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC)");
|
|
1485
|
+
}
|
|
1383
1486
|
}
|
|
1384
1487
|
];
|
|
1385
1488
|
_dbCache = /* @__PURE__ */ new Map();
|
|
@@ -1836,6 +1939,7 @@ function mergeTomlConfig(base, override) {
|
|
|
1836
1939
|
llm: { ...base.memory?.llm, ...override.memory?.llm }
|
|
1837
1940
|
},
|
|
1838
1941
|
embedding: { ...base.embedding, ...override.embedding },
|
|
1942
|
+
rerank: { ...base.rerank, ...override.rerank },
|
|
1839
1943
|
hooks: { ...base.hooks, ...override.hooks },
|
|
1840
1944
|
git: { ...base.git, ...override.git },
|
|
1841
1945
|
codegraph: { ...base.codegraph, ...override.codegraph },
|
|
@@ -1932,6 +2036,7 @@ __export(resolved_config_exports, {
|
|
|
1932
2036
|
getResolvedConfigForCwd: () => getResolvedConfigForCwd,
|
|
1933
2037
|
getResolvedEmbeddingLane: () => getResolvedEmbeddingLane,
|
|
1934
2038
|
getResolvedMemoryLane: () => getResolvedMemoryLane,
|
|
2039
|
+
getResolvedRerankLane: () => getResolvedRerankLane,
|
|
1935
2040
|
resetResolvedConfigCache: () => resetResolvedConfigCache
|
|
1936
2041
|
});
|
|
1937
2042
|
import { homedir as homedir5 } from "os";
|
|
@@ -1964,6 +2069,16 @@ function getResolvedConfig(options = {}) {
|
|
|
1964
2069
|
legacy.llm?.baseUrl
|
|
1965
2070
|
);
|
|
1966
2071
|
const openRouterMemoryLlmApiKey = isOpenRouterMemoryLane(memoryLlmProvider, memoryLlmBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
|
|
2072
|
+
const memoryLlmApiKey = first(
|
|
2073
|
+
process.env.MEMORIX_LLM_API_KEY,
|
|
2074
|
+
process.env.MEMORIX_API_KEY,
|
|
2075
|
+
toml.memory?.llm?.api_key,
|
|
2076
|
+
yaml.llm?.apiKey,
|
|
2077
|
+
legacy.llm?.apiKey,
|
|
2078
|
+
process.env.OPENAI_API_KEY,
|
|
2079
|
+
process.env.ANTHROPIC_API_KEY,
|
|
2080
|
+
openRouterMemoryLlmApiKey
|
|
2081
|
+
);
|
|
1967
2082
|
const resolved = {
|
|
1968
2083
|
agent: {
|
|
1969
2084
|
provider: first(
|
|
@@ -2004,16 +2119,7 @@ function getResolvedConfig(options = {}) {
|
|
|
2004
2119
|
provider: memoryLlmProvider,
|
|
2005
2120
|
model: memoryLlmModel,
|
|
2006
2121
|
baseUrl: memoryLlmBaseUrl,
|
|
2007
|
-
apiKey:
|
|
2008
|
-
process.env.MEMORIX_LLM_API_KEY,
|
|
2009
|
-
process.env.MEMORIX_API_KEY,
|
|
2010
|
-
toml.memory?.llm?.api_key,
|
|
2011
|
-
yaml.llm?.apiKey,
|
|
2012
|
-
legacy.llm?.apiKey,
|
|
2013
|
-
process.env.OPENAI_API_KEY,
|
|
2014
|
-
process.env.ANTHROPIC_API_KEY,
|
|
2015
|
-
openRouterMemoryLlmApiKey
|
|
2016
|
-
)
|
|
2122
|
+
apiKey: memoryLlmApiKey
|
|
2017
2123
|
}
|
|
2018
2124
|
},
|
|
2019
2125
|
embedding: {
|
|
@@ -2023,6 +2129,12 @@ function getResolvedConfig(options = {}) {
|
|
|
2023
2129
|
apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey),
|
|
2024
2130
|
dimensions: firstNumber(parseNumber(process.env.MEMORIX_EMBEDDING_DIMENSIONS), toml.embedding?.dimensions, yaml.embedding?.dimensions, legacy.embeddingApi?.dimensions)
|
|
2025
2131
|
},
|
|
2132
|
+
rerank: resolveRerankLane({
|
|
2133
|
+
toml,
|
|
2134
|
+
yaml,
|
|
2135
|
+
memoryLlmApiKey,
|
|
2136
|
+
memoryLlmBaseUrl
|
|
2137
|
+
}),
|
|
2026
2138
|
git: {
|
|
2027
2139
|
autoHook: firstBool(toml.git?.auto_hook, yaml.git?.autoHook),
|
|
2028
2140
|
ingestOnCommit: firstBool(toml.git?.ingest_on_commit, yaml.git?.ingestOnCommit),
|
|
@@ -2092,6 +2204,9 @@ function getResolvedMemoryLane(options = {}) {
|
|
|
2092
2204
|
function getResolvedEmbeddingLane(options = {}) {
|
|
2093
2205
|
return getResolvedConfig(options).embedding;
|
|
2094
2206
|
}
|
|
2207
|
+
function getResolvedRerankLane(options = {}) {
|
|
2208
|
+
return getResolvedConfig(options).rerank;
|
|
2209
|
+
}
|
|
2095
2210
|
function resetResolvedConfigCache() {
|
|
2096
2211
|
}
|
|
2097
2212
|
function first(...values) {
|
|
@@ -2134,6 +2249,10 @@ function getEnvSourceNames() {
|
|
|
2134
2249
|
"MEMORIX_EMBEDDING_BASE_URL",
|
|
2135
2250
|
"MEMORIX_EMBEDDING_MODEL",
|
|
2136
2251
|
"MEMORIX_EMBEDDING_DIMENSIONS",
|
|
2252
|
+
"MEMORIX_RERANK_PROVIDER",
|
|
2253
|
+
"MEMORIX_RERANK_MODEL",
|
|
2254
|
+
"MEMORIX_RERANK_BASE_URL",
|
|
2255
|
+
"MEMORIX_RERANK_API_KEY",
|
|
2137
2256
|
"MEMORIX_CODEGRAPH_EXTERNAL_CONTEXT",
|
|
2138
2257
|
"MEMORIX_CODEGRAPH_EXTERNAL_COMMAND",
|
|
2139
2258
|
"MEMORIX_CODEGRAPH_EXTERNAL_TIMEOUT_MS",
|
|
@@ -2157,6 +2276,63 @@ function normalizeExternalContext(value) {
|
|
|
2157
2276
|
if (normalized === "auto" || normalized === "off") return normalized;
|
|
2158
2277
|
return void 0;
|
|
2159
2278
|
}
|
|
2279
|
+
function normalizeRerankProvider(value) {
|
|
2280
|
+
const normalized = value?.trim().toLowerCase();
|
|
2281
|
+
if (normalized === "http") return "http";
|
|
2282
|
+
return "off";
|
|
2283
|
+
}
|
|
2284
|
+
function resolveRerankLane(args) {
|
|
2285
|
+
const provider2 = normalizeRerankProvider(first(
|
|
2286
|
+
process.env.MEMORIX_RERANK_PROVIDER,
|
|
2287
|
+
args.toml.rerank?.provider,
|
|
2288
|
+
args.yaml.rerank?.provider,
|
|
2289
|
+
"off"
|
|
2290
|
+
));
|
|
2291
|
+
const model = first(
|
|
2292
|
+
process.env.MEMORIX_RERANK_MODEL,
|
|
2293
|
+
args.toml.rerank?.model,
|
|
2294
|
+
args.yaml.rerank?.model
|
|
2295
|
+
);
|
|
2296
|
+
const explicitBaseUrl = first(
|
|
2297
|
+
process.env.MEMORIX_RERANK_BASE_URL,
|
|
2298
|
+
args.toml.rerank?.base_url,
|
|
2299
|
+
args.yaml.rerank?.baseUrl
|
|
2300
|
+
);
|
|
2301
|
+
const baseUrl = provider2 === "http" ? first(explicitBaseUrl, args.memoryLlmBaseUrl) : explicitBaseUrl;
|
|
2302
|
+
const dedicatedApiKey = first(
|
|
2303
|
+
process.env.MEMORIX_RERANK_API_KEY,
|
|
2304
|
+
args.toml.rerank?.api_key,
|
|
2305
|
+
args.yaml.rerank?.apiKey
|
|
2306
|
+
);
|
|
2307
|
+
const sameEndpoint = provider2 === "http" && sameTrustedEndpoint(baseUrl, args.memoryLlmBaseUrl);
|
|
2308
|
+
const inheritedApiKey = sameEndpoint ? args.memoryLlmApiKey : void 0;
|
|
2309
|
+
const apiKey = first(dedicatedApiKey, inheritedApiKey);
|
|
2310
|
+
const canSendRequest = provider2 === "http" && Boolean(baseUrl) && (Boolean(apiKey) || !args.memoryLlmApiKey || sameEndpoint);
|
|
2311
|
+
return { provider: provider2, model, baseUrl, apiKey, canSendRequest };
|
|
2312
|
+
}
|
|
2313
|
+
function sameTrustedEndpoint(left, right) {
|
|
2314
|
+
const a = normalizeTrustedEndpoint(left);
|
|
2315
|
+
const b = normalizeTrustedEndpoint(right);
|
|
2316
|
+
return Boolean(a && b && a === b);
|
|
2317
|
+
}
|
|
2318
|
+
function normalizeTrustedEndpoint(value) {
|
|
2319
|
+
const trimmed = value?.trim();
|
|
2320
|
+
if (!trimmed) return void 0;
|
|
2321
|
+
try {
|
|
2322
|
+
const url = new URL(trimmed);
|
|
2323
|
+
const protocol = url.protocol.toLowerCase();
|
|
2324
|
+
const hostname = url.hostname.toLowerCase();
|
|
2325
|
+
const port = url.port;
|
|
2326
|
+
let pathname = url.pathname.replace(/\/+$/, "");
|
|
2327
|
+
if (pathname.toLowerCase().endsWith("/rerank")) {
|
|
2328
|
+
pathname = pathname.slice(0, -"/rerank".length).replace(/\/+$/, "");
|
|
2329
|
+
}
|
|
2330
|
+
return `${protocol}//${hostname}${port ? `:${port}` : ""}${pathname}`;
|
|
2331
|
+
} catch {
|
|
2332
|
+
const fallback = trimmed.replace(/\/+$/, "").replace(/\/rerank$/i, "").replace(/\/+$/, "");
|
|
2333
|
+
return fallback.toLowerCase() || void 0;
|
|
2334
|
+
}
|
|
2335
|
+
}
|
|
2160
2336
|
var init_resolved_config = __esm({
|
|
2161
2337
|
"src/config/resolved-config.ts"() {
|
|
2162
2338
|
"use strict";
|
|
@@ -4392,9 +4568,27 @@ __export(provider_exports2, {
|
|
|
4392
4568
|
getLLMConfig: () => getLLMConfig,
|
|
4393
4569
|
initLLM: () => initLLM,
|
|
4394
4570
|
isLLMEnabled: () => isLLMEnabled,
|
|
4571
|
+
normalizeOpenAICompatibleBaseUrl: () => normalizeOpenAICompatibleBaseUrl,
|
|
4395
4572
|
parseLLMTimeoutMs: () => parseLLMTimeoutMs,
|
|
4396
4573
|
setLLMConfig: () => setLLMConfig
|
|
4397
4574
|
});
|
|
4575
|
+
function normalizeOpenAICompatibleBaseUrl(baseUrl) {
|
|
4576
|
+
const base = baseUrl.trim().replace(/\/+$/, "");
|
|
4577
|
+
if (!base) return base;
|
|
4578
|
+
let pathname = "";
|
|
4579
|
+
try {
|
|
4580
|
+
pathname = new URL(base).pathname.replace(/\/+$/, "");
|
|
4581
|
+
} catch {
|
|
4582
|
+
pathname = base.split(/[?#]/, 1)[0].replace(/\/+$/, "");
|
|
4583
|
+
}
|
|
4584
|
+
const lastSegment = pathname.split("/").filter(Boolean).at(-1);
|
|
4585
|
+
if (lastSegment && OPENAI_API_VERSION_SEGMENT.test(lastSegment)) {
|
|
4586
|
+
return base;
|
|
4587
|
+
}
|
|
4588
|
+
const queryOrHash = base.match(/[?#].*$/)?.[0] ?? "";
|
|
4589
|
+
const pathWithoutQuery = base.slice(0, base.length - queryOrHash.length).replace(/\/+$/, "");
|
|
4590
|
+
return `${pathWithoutQuery}/v1${queryOrHash}`;
|
|
4591
|
+
}
|
|
4398
4592
|
function parseLLMTimeoutMs(raw) {
|
|
4399
4593
|
if (raw === void 0 || raw.trim() === "") return LLM_TIMEOUT_DEFAULT_MS;
|
|
4400
4594
|
const parsed = Number(raw);
|
|
@@ -4498,8 +4692,7 @@ async function callLLM(systemPrompt, userMessage, signal) {
|
|
|
4498
4692
|
}
|
|
4499
4693
|
async function callOpenAICompatible(systemPrompt, userMessage, signal) {
|
|
4500
4694
|
const config = currentConfig;
|
|
4501
|
-
|
|
4502
|
-
if (!base.endsWith("/v1")) base += "/v1";
|
|
4695
|
+
const base = normalizeOpenAICompatibleBaseUrl(config.baseUrl);
|
|
4503
4696
|
const url = `${base}/chat/completions`;
|
|
4504
4697
|
const fetchSignal = signal ? AbortSignal.any([signal, AbortSignal.timeout(LLM_CALL_TIMEOUT_MS)]) : AbortSignal.timeout(LLM_CALL_TIMEOUT_MS);
|
|
4505
4698
|
const response = await fetch(url, {
|
|
@@ -4578,8 +4771,7 @@ async function callLLMWithTools(messages, tools, signal) {
|
|
|
4578
4771
|
}
|
|
4579
4772
|
async function callOpenAIWithTools(messages, tools, signal) {
|
|
4580
4773
|
const config = currentConfig;
|
|
4581
|
-
|
|
4582
|
-
if (!base.endsWith("/v1")) base += "/v1";
|
|
4774
|
+
const base = normalizeOpenAICompatibleBaseUrl(config.baseUrl);
|
|
4583
4775
|
const url = `${base}/chat/completions`;
|
|
4584
4776
|
const openaiMessages = messages.map((msg) => {
|
|
4585
4777
|
if (msg.role === "tool") {
|
|
@@ -4729,8 +4921,7 @@ async function callAnthropicWithTools(messages, tools, signal) {
|
|
|
4729
4921
|
}
|
|
4730
4922
|
async function* callOpenAIWithToolsStream(messages, tools) {
|
|
4731
4923
|
const config = currentConfig;
|
|
4732
|
-
|
|
4733
|
-
if (!base.endsWith("/v1")) base += "/v1";
|
|
4924
|
+
const base = normalizeOpenAICompatibleBaseUrl(config.baseUrl);
|
|
4734
4925
|
const url = `${base}/chat/completions`;
|
|
4735
4926
|
const openaiMessages = messages.map((msg) => {
|
|
4736
4927
|
if (msg.role === "tool") {
|
|
@@ -4978,7 +5169,7 @@ async function* callAnthropicWithToolsStream(messages, tools) {
|
|
|
4978
5169
|
}
|
|
4979
5170
|
};
|
|
4980
5171
|
}
|
|
4981
|
-
var LLM_TIMEOUT_DEFAULT_MS, LLM_TIMEOUT_MIN_MS, LLM_TIMEOUT_MAX_MS, MAX_LLM_RESPONSE_BYTES, LLM_CALL_TIMEOUT_MS, PROVIDER_DEFAULTS, currentConfig;
|
|
5172
|
+
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;
|
|
4982
5173
|
var init_provider2 = __esm({
|
|
4983
5174
|
"src/llm/provider.ts"() {
|
|
4984
5175
|
"use strict";
|
|
@@ -4988,6 +5179,7 @@ var init_provider2 = __esm({
|
|
|
4988
5179
|
LLM_TIMEOUT_MIN_MS = 1e3;
|
|
4989
5180
|
LLM_TIMEOUT_MAX_MS = 3e5;
|
|
4990
5181
|
MAX_LLM_RESPONSE_BYTES = 2 * 1024 * 1024;
|
|
5182
|
+
OPENAI_API_VERSION_SEGMENT = /^v\d+(?:[a-z][a-z0-9-]*)?$/i;
|
|
4991
5183
|
LLM_CALL_TIMEOUT_MS = parseLLMTimeoutMs(process.env.MEMORIX_LLM_TIMEOUT_MS);
|
|
4992
5184
|
PROVIDER_DEFAULTS = {
|
|
4993
5185
|
openai: { baseUrl: "https://api.openai.com/v1", model: "gpt-4.1-nano" },
|
|
@@ -5047,6 +5239,48 @@ Rules:
|
|
|
5047
5239
|
}
|
|
5048
5240
|
});
|
|
5049
5241
|
|
|
5242
|
+
// src/rerank/policy.ts
|
|
5243
|
+
function parseRerankTimeoutMs(raw) {
|
|
5244
|
+
const value = raw?.trim();
|
|
5245
|
+
if (!value) return DEFAULT_RERANK_TIMEOUT_MS;
|
|
5246
|
+
const parsed = Number(value);
|
|
5247
|
+
if (!Number.isInteger(parsed) || Number.isNaN(parsed)) {
|
|
5248
|
+
console.warn(
|
|
5249
|
+
`[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.`
|
|
5250
|
+
);
|
|
5251
|
+
return DEFAULT_RERANK_TIMEOUT_MS;
|
|
5252
|
+
}
|
|
5253
|
+
if (parsed < RERANK_TIMEOUT_MIN_MS) return RERANK_TIMEOUT_MIN_MS;
|
|
5254
|
+
if (parsed > RERANK_TIMEOUT_MAX_MS) return RERANK_TIMEOUT_MAX_MS;
|
|
5255
|
+
return parsed;
|
|
5256
|
+
}
|
|
5257
|
+
function resolveRerankTimeoutMs(explicitTimeoutMs) {
|
|
5258
|
+
if (typeof explicitTimeoutMs === "number" && Number.isFinite(explicitTimeoutMs) && explicitTimeoutMs > 0) {
|
|
5259
|
+
return explicitTimeoutMs;
|
|
5260
|
+
}
|
|
5261
|
+
return parseRerankTimeoutMs(process.env.MEMORIX_RERANK_TIMEOUT_MS);
|
|
5262
|
+
}
|
|
5263
|
+
function shouldAttemptHttpRerank(input) {
|
|
5264
|
+
return input.quality === "thorough" && input.hasQuery && input.candidateCount >= MIN_RERANK_CANDIDATES;
|
|
5265
|
+
}
|
|
5266
|
+
function shouldAttemptLlmRerank(input) {
|
|
5267
|
+
if (input.httpRerankConfigured) return false;
|
|
5268
|
+
if (input.quality !== "thorough" || input.tier !== "heavy" || !input.hasQuery) return false;
|
|
5269
|
+
if (input.candidateCount < MIN_RERANK_CANDIDATES) return false;
|
|
5270
|
+
return input.topScore > 0 && input.secondScore / input.topScore > 0.7;
|
|
5271
|
+
}
|
|
5272
|
+
var DEFAULT_RERANK_TIMEOUT_MS, RERANK_TIMEOUT_MIN_MS, RERANK_TIMEOUT_MAX_MS, MIN_RERANK_CANDIDATES;
|
|
5273
|
+
var init_policy = __esm({
|
|
5274
|
+
"src/rerank/policy.ts"() {
|
|
5275
|
+
"use strict";
|
|
5276
|
+
init_esm_shims();
|
|
5277
|
+
DEFAULT_RERANK_TIMEOUT_MS = 3e4;
|
|
5278
|
+
RERANK_TIMEOUT_MIN_MS = 1e3;
|
|
5279
|
+
RERANK_TIMEOUT_MAX_MS = 3e5;
|
|
5280
|
+
MIN_RERANK_CANDIDATES = 3;
|
|
5281
|
+
}
|
|
5282
|
+
});
|
|
5283
|
+
|
|
5050
5284
|
// src/timeout.ts
|
|
5051
5285
|
function withTimeout(promise, ms, label) {
|
|
5052
5286
|
return new Promise((resolve, reject) => {
|
|
@@ -5332,6 +5566,148 @@ var init_aliases = __esm({
|
|
|
5332
5566
|
}
|
|
5333
5567
|
});
|
|
5334
5568
|
|
|
5569
|
+
// src/rerank/http-provider.ts
|
|
5570
|
+
function buildRerankUrl(baseUrl) {
|
|
5571
|
+
const trimmed = baseUrl.trim().replace(/\/+$/, "");
|
|
5572
|
+
if (trimmed.endsWith("/rerank")) return trimmed;
|
|
5573
|
+
return `${trimmed}/rerank`;
|
|
5574
|
+
}
|
|
5575
|
+
function parseRerankResponse(payload) {
|
|
5576
|
+
const rows = extractRows(payload);
|
|
5577
|
+
if (rows.length === 0) {
|
|
5578
|
+
throw new Error("Neural rerank response contained no ranked results");
|
|
5579
|
+
}
|
|
5580
|
+
return rows.sort((a, b) => b.score - a.score);
|
|
5581
|
+
}
|
|
5582
|
+
function extractRows(payload) {
|
|
5583
|
+
if (Array.isArray(payload)) {
|
|
5584
|
+
return payload.map(rowFromUnknown).filter((row) => row !== null);
|
|
5585
|
+
}
|
|
5586
|
+
if (payload && typeof payload === "object" && "results" in payload) {
|
|
5587
|
+
const results = payload.results;
|
|
5588
|
+
if (Array.isArray(results)) {
|
|
5589
|
+
return results.map(rowFromUnknown).filter((row) => row !== null);
|
|
5590
|
+
}
|
|
5591
|
+
}
|
|
5592
|
+
throw new Error("Neural rerank response was not Cohere or TEI shaped");
|
|
5593
|
+
}
|
|
5594
|
+
function rowFromUnknown(value) {
|
|
5595
|
+
if (!value || typeof value !== "object") return null;
|
|
5596
|
+
const row = value;
|
|
5597
|
+
if (typeof row.index !== "number" || !Number.isFinite(row.index)) return null;
|
|
5598
|
+
const score = typeof row.relevance_score === "number" ? row.relevance_score : typeof row.score === "number" ? row.score : null;
|
|
5599
|
+
if (score === null || !Number.isFinite(score)) return null;
|
|
5600
|
+
return { index: row.index, score };
|
|
5601
|
+
}
|
|
5602
|
+
function buildRerankBody(query, documents, model) {
|
|
5603
|
+
const body = {
|
|
5604
|
+
query,
|
|
5605
|
+
documents,
|
|
5606
|
+
top_n: documents.length,
|
|
5607
|
+
return_documents: false
|
|
5608
|
+
};
|
|
5609
|
+
const trimmed = model?.trim();
|
|
5610
|
+
if (trimmed) body.model = trimmed;
|
|
5611
|
+
return body;
|
|
5612
|
+
}
|
|
5613
|
+
async function rerankViaHttp(query, documents, config) {
|
|
5614
|
+
if (documents.length === 0) return [];
|
|
5615
|
+
const url = buildRerankUrl(config.baseUrl);
|
|
5616
|
+
const headers = {
|
|
5617
|
+
"content-type": "application/json"
|
|
5618
|
+
};
|
|
5619
|
+
if (config.apiKey) {
|
|
5620
|
+
headers.authorization = `Bearer ${config.apiKey}`;
|
|
5621
|
+
}
|
|
5622
|
+
const controller = new AbortController();
|
|
5623
|
+
const timeoutMs = resolveRerankTimeoutMs(config.timeoutMs);
|
|
5624
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
5625
|
+
try {
|
|
5626
|
+
const fetchImpl = config.fetchImpl ?? fetch;
|
|
5627
|
+
const response = await fetchImpl(url, {
|
|
5628
|
+
method: "POST",
|
|
5629
|
+
headers,
|
|
5630
|
+
signal: controller.signal,
|
|
5631
|
+
body: JSON.stringify(buildRerankBody(query, documents, config.model))
|
|
5632
|
+
});
|
|
5633
|
+
if (!response.ok) {
|
|
5634
|
+
throw new Error(`Neural rerank HTTP ${response.status} from ${url}`);
|
|
5635
|
+
}
|
|
5636
|
+
return parseRerankResponse(await response.json());
|
|
5637
|
+
} finally {
|
|
5638
|
+
clearTimeout(timer);
|
|
5639
|
+
}
|
|
5640
|
+
}
|
|
5641
|
+
var init_http_provider = __esm({
|
|
5642
|
+
"src/rerank/http-provider.ts"() {
|
|
5643
|
+
"use strict";
|
|
5644
|
+
init_esm_shims();
|
|
5645
|
+
init_policy();
|
|
5646
|
+
}
|
|
5647
|
+
});
|
|
5648
|
+
|
|
5649
|
+
// src/rerank/index.ts
|
|
5650
|
+
var rerank_exports = {};
|
|
5651
|
+
__export(rerank_exports, {
|
|
5652
|
+
DEFAULT_RERANK_TIMEOUT_MS: () => DEFAULT_RERANK_TIMEOUT_MS,
|
|
5653
|
+
MIN_RERANK_CANDIDATES: () => MIN_RERANK_CANDIDATES,
|
|
5654
|
+
isNeuralRerankEnabled: () => isNeuralRerankEnabled,
|
|
5655
|
+
neuralRerankCandidates: () => neuralRerankCandidates,
|
|
5656
|
+
parseRerankTimeoutMs: () => parseRerankTimeoutMs,
|
|
5657
|
+
resolveRerankTimeoutMs: () => resolveRerankTimeoutMs,
|
|
5658
|
+
shouldAttemptHttpRerank: () => shouldAttemptHttpRerank,
|
|
5659
|
+
shouldAttemptLlmRerank: () => shouldAttemptLlmRerank
|
|
5660
|
+
});
|
|
5661
|
+
function isNeuralRerankEnabled(options = {}) {
|
|
5662
|
+
const lane = getResolvedRerankLane(options);
|
|
5663
|
+
return lane.provider === "http" && Boolean(lane.baseUrl);
|
|
5664
|
+
}
|
|
5665
|
+
async function neuralRerankCandidates(query, candidates, options = {}) {
|
|
5666
|
+
if (!isNeuralRerankEnabled(options) || candidates.length === 0) return null;
|
|
5667
|
+
const lane = getResolvedRerankLane(options);
|
|
5668
|
+
if (!lane.canSendRequest || !lane.baseUrl) return null;
|
|
5669
|
+
const toRerank = candidates.slice(0, MAX_RERANK);
|
|
5670
|
+
const rest = candidates.slice(MAX_RERANK);
|
|
5671
|
+
const documents = toRerank.map((candidate) => candidateText(candidate));
|
|
5672
|
+
const ranked = await rerankViaHttp(query, documents, {
|
|
5673
|
+
provider: "http",
|
|
5674
|
+
model: lane.model,
|
|
5675
|
+
baseUrl: lane.baseUrl,
|
|
5676
|
+
apiKey: lane.apiKey,
|
|
5677
|
+
timeoutMs: resolveRerankTimeoutMs()
|
|
5678
|
+
});
|
|
5679
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5680
|
+
const reranked = [];
|
|
5681
|
+
for (const row of ranked) {
|
|
5682
|
+
const candidate = toRerank[row.index];
|
|
5683
|
+
if (!candidate || seen.has(row.index)) continue;
|
|
5684
|
+
reranked.push(candidate);
|
|
5685
|
+
seen.add(row.index);
|
|
5686
|
+
}
|
|
5687
|
+
for (const [index, candidate] of toRerank.entries()) {
|
|
5688
|
+
if (!seen.has(index)) reranked.push(candidate);
|
|
5689
|
+
}
|
|
5690
|
+
reranked.push(...rest);
|
|
5691
|
+
return reranked;
|
|
5692
|
+
}
|
|
5693
|
+
function candidateText(candidate) {
|
|
5694
|
+
const narrative = candidate.narrative?.trim();
|
|
5695
|
+
if (narrative) return `${candidate.title} \u2014 ${narrative.slice(0, 200)}`;
|
|
5696
|
+
return candidate.title;
|
|
5697
|
+
}
|
|
5698
|
+
var MAX_RERANK;
|
|
5699
|
+
var init_rerank = __esm({
|
|
5700
|
+
"src/rerank/index.ts"() {
|
|
5701
|
+
"use strict";
|
|
5702
|
+
init_esm_shims();
|
|
5703
|
+
init_resolved_config();
|
|
5704
|
+
init_http_provider();
|
|
5705
|
+
init_policy();
|
|
5706
|
+
init_policy();
|
|
5707
|
+
MAX_RERANK = 10;
|
|
5708
|
+
}
|
|
5709
|
+
});
|
|
5710
|
+
|
|
5335
5711
|
// src/llm/quality.ts
|
|
5336
5712
|
var quality_exports = {};
|
|
5337
5713
|
__export(quality_exports, {
|
|
@@ -5371,9 +5747,9 @@ async function rerankResults(query, candidates) {
|
|
|
5371
5747
|
if (!isLLMEnabled() || candidates.length <= 2) {
|
|
5372
5748
|
return { reranked: candidates, usedLLM: false };
|
|
5373
5749
|
}
|
|
5374
|
-
const
|
|
5375
|
-
const toRerank = candidates.slice(0,
|
|
5376
|
-
const rest = candidates.slice(
|
|
5750
|
+
const MAX_RERANK2 = 10;
|
|
5751
|
+
const toRerank = candidates.slice(0, MAX_RERANK2);
|
|
5752
|
+
const rest = candidates.slice(MAX_RERANK2);
|
|
5377
5753
|
try {
|
|
5378
5754
|
const candidateList = toRerank.map(
|
|
5379
5755
|
(c) => `[ID: ${c.id}] (${c.type}) ${c.title}${c.narrative ? ` \u2014 ${c.narrative.substring(0, 100)}` : ""}`
|
|
@@ -6266,46 +6642,78 @@ async function searchObservations(options) {
|
|
|
6266
6642
|
}
|
|
6267
6643
|
}
|
|
6268
6644
|
}
|
|
6269
|
-
const
|
|
6270
|
-
|
|
6271
|
-
|
|
6272
|
-
|
|
6273
|
-
})
|
|
6274
|
-
|
|
6275
|
-
|
|
6276
|
-
|
|
6277
|
-
|
|
6278
|
-
|
|
6279
|
-
|
|
6280
|
-
|
|
6281
|
-
|
|
6282
|
-
|
|
6283
|
-
|
|
6284
|
-
|
|
6285
|
-
|
|
6286
|
-
|
|
6287
|
-
|
|
6288
|
-
|
|
6289
|
-
|
|
6290
|
-
|
|
6291
|
-
|
|
6292
|
-
|
|
6293
|
-
|
|
6294
|
-
|
|
6295
|
-
|
|
6296
|
-
|
|
6297
|
-
|
|
6298
|
-
|
|
6299
|
-
|
|
6300
|
-
|
|
6301
|
-
|
|
6302
|
-
|
|
6303
|
-
|
|
6304
|
-
|
|
6645
|
+
const httpGate = shouldAttemptHttpRerank({
|
|
6646
|
+
quality,
|
|
6647
|
+
hasQuery: Boolean(hasQuery),
|
|
6648
|
+
candidateCount: intermediate.length
|
|
6649
|
+
});
|
|
6650
|
+
const llmGateWithoutHttp = shouldAttemptLlmRerank({
|
|
6651
|
+
quality,
|
|
6652
|
+
tier,
|
|
6653
|
+
hasQuery: Boolean(hasQuery),
|
|
6654
|
+
candidateCount: intermediate.length,
|
|
6655
|
+
topScore: intermediate[0]?.score ?? 0,
|
|
6656
|
+
secondScore: intermediate[1]?.score ?? 0,
|
|
6657
|
+
httpRerankConfigured: false
|
|
6658
|
+
});
|
|
6659
|
+
if (httpGate || llmGateWithoutHttp) {
|
|
6660
|
+
const narrativeMap = /* @__PURE__ */ new Map();
|
|
6661
|
+
for (const hit of results.hits) {
|
|
6662
|
+
const doc = hit.document;
|
|
6663
|
+
narrativeMap.set(makeEntryKey(doc.projectId, doc.observationId), doc.narrative);
|
|
6664
|
+
}
|
|
6665
|
+
const RERANK_TOP_K = 5;
|
|
6666
|
+
const toRerank = intermediate.slice(0, RERANK_TOP_K);
|
|
6667
|
+
const candidates = toRerank.map((e2, index) => ({
|
|
6668
|
+
id: `r${index + 1}`,
|
|
6669
|
+
title: e2.title,
|
|
6670
|
+
type: e2.type,
|
|
6671
|
+
score: e2.score,
|
|
6672
|
+
narrative: narrativeMap.get(makeEntryKey(e2.projectId, e2.id))
|
|
6673
|
+
}));
|
|
6674
|
+
const RERANK_TIMEOUT_MS = parseRerankTimeoutMs(process.env.MEMORIX_RERANK_TIMEOUT_MS);
|
|
6675
|
+
const candidateMap = new Map(candidates.map((candidate, index) => [candidate.id, toRerank[index]]));
|
|
6676
|
+
const { isNeuralRerankEnabled: isNeuralRerankEnabled2, neuralRerankCandidates: neuralRerankCandidates2 } = await Promise.resolve().then(() => (init_rerank(), rerank_exports));
|
|
6677
|
+
const httpConfigured = isNeuralRerankEnabled2();
|
|
6678
|
+
if (httpConfigured && httpGate) {
|
|
6679
|
+
try {
|
|
6680
|
+
const neural = await withTimeout(
|
|
6681
|
+
neuralRerankCandidates2(originalQuery, candidates),
|
|
6682
|
+
RERANK_TIMEOUT_MS,
|
|
6683
|
+
"neural rerank"
|
|
6684
|
+
);
|
|
6685
|
+
if (neural && neural.length > 0) {
|
|
6686
|
+
const rerankedTop = neural.map((row) => candidateMap.get(row.id)).filter((entry) => entry != null);
|
|
6687
|
+
if (rerankedTop.length > 0) {
|
|
6688
|
+
intermediate = [...rerankedTop, ...intermediate.slice(RERANK_TOP_K)];
|
|
6689
|
+
lastSearchModeByProject.set(modeKey, (lastSearchModeByProject.get(modeKey) ?? "fulltext") + " + neural rerank");
|
|
6690
|
+
mark("rerank(usedNeural=true)");
|
|
6691
|
+
}
|
|
6305
6692
|
}
|
|
6693
|
+
} catch {
|
|
6694
|
+
console.error("[memorix] neural rerank failed or timed out; keeping original order");
|
|
6306
6695
|
}
|
|
6307
|
-
}
|
|
6308
|
-
|
|
6696
|
+
} else if (!httpConfigured && llmGateWithoutHttp) {
|
|
6697
|
+
try {
|
|
6698
|
+
const { rerankResults: rerankResults2 } = await Promise.resolve().then(() => (init_quality(), quality_exports));
|
|
6699
|
+
const { reranked, usedLLM } = await withTimeout(
|
|
6700
|
+
rerankResults2(originalQuery, candidates),
|
|
6701
|
+
RERANK_TIMEOUT_MS,
|
|
6702
|
+
"LLM rerank"
|
|
6703
|
+
);
|
|
6704
|
+
mark(`rerank(usedLLM=${usedLLM})`);
|
|
6705
|
+
if (usedLLM) {
|
|
6706
|
+
lastSearchModeByProject.set(modeKey, (lastSearchModeByProject.get(modeKey) ?? "fulltext") + " + LLM rerank");
|
|
6707
|
+
const rerankedTop = reranked.map((row) => candidateMap.get(row.id)).filter((entry) => entry != null);
|
|
6708
|
+
if (rerankedTop.length > 0) {
|
|
6709
|
+
intermediate = [...rerankedTop, ...intermediate.slice(RERANK_TOP_K)];
|
|
6710
|
+
}
|
|
6711
|
+
}
|
|
6712
|
+
} catch {
|
|
6713
|
+
console.error("[memorix] LLM rerank failed or timed out, using original order");
|
|
6714
|
+
}
|
|
6715
|
+
} else {
|
|
6716
|
+
mark(`rerank(skipped,tier=${tier})`);
|
|
6309
6717
|
}
|
|
6310
6718
|
} else {
|
|
6311
6719
|
mark(`rerank(skipped,tier=${tier})`);
|
|
@@ -6486,6 +6894,7 @@ var init_orama_store = __esm({
|
|
|
6486
6894
|
init_project_affinity();
|
|
6487
6895
|
init_intent_detector();
|
|
6488
6896
|
init_query_expansion();
|
|
6897
|
+
init_policy();
|
|
6489
6898
|
init_timeout();
|
|
6490
6899
|
db = null;
|
|
6491
6900
|
dbInitPromise = null;
|
|
@@ -7674,10 +8083,230 @@ 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/codegraph/ids.ts
|
|
7678
|
-
import { createHash as
|
|
8307
|
+
import { createHash as createHash4 } from "crypto";
|
|
7679
8308
|
function digest(input) {
|
|
7680
|
-
return
|
|
8309
|
+
return createHash4("sha256").update(input).digest("hex").slice(0, 16);
|
|
7681
8310
|
}
|
|
7682
8311
|
function normalizeCodePath(path21) {
|
|
7683
8312
|
return path21.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+/g, "/");
|
|
@@ -7712,7 +8341,7 @@ var store_exports = {};
|
|
|
7712
8341
|
__export(store_exports, {
|
|
7713
8342
|
CodeGraphStore: () => CodeGraphStore
|
|
7714
8343
|
});
|
|
7715
|
-
import { randomUUID as
|
|
8344
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
7716
8345
|
import { posix as pathPosix } from "path";
|
|
7717
8346
|
function rowToFile(row) {
|
|
7718
8347
|
return {
|
|
@@ -8429,7 +9058,7 @@ var init_store = __esm({
|
|
|
8429
9058
|
* so an interrupted scan cannot be advertised as complete.
|
|
8430
9059
|
*/
|
|
8431
9060
|
recordCodeStateSnapshot(input) {
|
|
8432
|
-
const id =
|
|
9061
|
+
const id = randomUUID4();
|
|
8433
9062
|
let snapshot;
|
|
8434
9063
|
const tx = this.db.transaction(() => {
|
|
8435
9064
|
const previous = this.db.prepare(
|
|
@@ -8761,6 +9390,16 @@ async function bindObservationCodeRefsBestEffort(observation) {
|
|
|
8761
9390
|
} catch {
|
|
8762
9391
|
}
|
|
8763
9392
|
}
|
|
9393
|
+
async function persistEvidenceCard(observation) {
|
|
9394
|
+
if (!projectDir) return;
|
|
9395
|
+
try {
|
|
9396
|
+
const evidence = new EvidenceCardStore();
|
|
9397
|
+
await evidence.init(projectDir);
|
|
9398
|
+
evidence.upsertObservation(observation);
|
|
9399
|
+
} catch (error) {
|
|
9400
|
+
console.error(`[memorix] Evidence card projection failed for obs-${observation.id}: ${error instanceof Error ? error.message : String(error)}`);
|
|
9401
|
+
}
|
|
9402
|
+
}
|
|
8764
9403
|
function queueClaimDerivation(observation) {
|
|
8765
9404
|
const dataDir = projectDir;
|
|
8766
9405
|
const isExplicit = observation.sourceDetail === "explicit";
|
|
@@ -9107,6 +9746,7 @@ async function storeObservation(input) {
|
|
|
9107
9746
|
}
|
|
9108
9747
|
if (!persistedCallbackInvoked) await input.onPersisted?.(observation);
|
|
9109
9748
|
await bindObservationCodeRefsBestEffort(observation);
|
|
9749
|
+
await persistEvidenceCard(observation);
|
|
9110
9750
|
queueObservationQualification(observation);
|
|
9111
9751
|
if (resolveObservationVisibility(observation) === "project") {
|
|
9112
9752
|
queueClaimDerivation(observation);
|
|
@@ -9199,6 +9839,7 @@ async function upsertObservation(existing, input, now3) {
|
|
|
9199
9839
|
await store.update(existing);
|
|
9200
9840
|
}
|
|
9201
9841
|
await bindObservationCodeRefsBestEffort(existing);
|
|
9842
|
+
await persistEvidenceCard(existing);
|
|
9202
9843
|
queueObservationQualification(existing);
|
|
9203
9844
|
if (resolveObservationVisibility(existing) === "project") {
|
|
9204
9845
|
queueClaimDerivation(existing);
|
|
@@ -9332,6 +9973,7 @@ async function resolveObservations(ids, status = "resolved") {
|
|
|
9332
9973
|
await Promise.all(changed.map((observation) => tx.update(observation)));
|
|
9333
9974
|
});
|
|
9334
9975
|
}
|
|
9976
|
+
for (const observation of changed) await persistEvidenceCard(observation);
|
|
9335
9977
|
return { resolved, notFound };
|
|
9336
9978
|
}
|
|
9337
9979
|
function getProjectObservations(projectId) {
|
|
@@ -9669,6 +10311,7 @@ var init_observations = __esm({
|
|
|
9669
10311
|
init_secret_filter();
|
|
9670
10312
|
init_lifecycle();
|
|
9671
10313
|
init_visibility();
|
|
10314
|
+
init_evidence_store();
|
|
9672
10315
|
observations = [];
|
|
9673
10316
|
nextId = 1;
|
|
9674
10317
|
projectDir = null;
|
|
@@ -9686,7 +10329,7 @@ var init_observations = __esm({
|
|
|
9686
10329
|
});
|
|
9687
10330
|
|
|
9688
10331
|
// src/knowledge/workspace-store.ts
|
|
9689
|
-
import { randomUUID as
|
|
10332
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
9690
10333
|
function arrayValue(raw) {
|
|
9691
10334
|
if (typeof raw !== "string" || !raw) return [];
|
|
9692
10335
|
try {
|
|
@@ -9827,7 +10470,7 @@ var init_workspace_store = __esm({
|
|
|
9827
10470
|
}
|
|
9828
10471
|
createProposal(input) {
|
|
9829
10472
|
const proposal = {
|
|
9830
|
-
id: input.id ??
|
|
10473
|
+
id: input.id ?? randomUUID5(),
|
|
9831
10474
|
...input,
|
|
9832
10475
|
status: input.status ?? "pending",
|
|
9833
10476
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -9880,13 +10523,13 @@ __export(workspace_exports, {
|
|
|
9880
10523
|
loadKnowledgeWorkspace: () => loadKnowledgeWorkspace,
|
|
9881
10524
|
resolveKnowledgeWorkspaceFile: () => resolveKnowledgeWorkspaceFile
|
|
9882
10525
|
});
|
|
9883
|
-
import { createHash as
|
|
10526
|
+
import { createHash as createHash5 } from "crypto";
|
|
9884
10527
|
import { execFile } from "child_process";
|
|
9885
10528
|
import { promises as fs6 } from "fs";
|
|
9886
10529
|
import path9 from "path";
|
|
9887
10530
|
import { promisify } from "util";
|
|
9888
10531
|
function hash(value) {
|
|
9889
|
-
return
|
|
10532
|
+
return createHash5("sha256").update(value).digest("hex");
|
|
9890
10533
|
}
|
|
9891
10534
|
function workspaceId(projectId, mode) {
|
|
9892
10535
|
return "workspace:" + hash(projectId + ":" + mode).slice(0, 24);
|
|
@@ -10482,7 +11125,7 @@ Respond in JSON only:
|
|
|
10482
11125
|
});
|
|
10483
11126
|
|
|
10484
11127
|
// src/media/media-store.ts
|
|
10485
|
-
import { randomUUID as
|
|
11128
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
10486
11129
|
function asOptionalText(value) {
|
|
10487
11130
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
10488
11131
|
}
|
|
@@ -10652,7 +11295,7 @@ var init_media_store = __esm({
|
|
|
10652
11295
|
return { asset: this.getAsset(input.projectId, existing.id), deduplicated: true };
|
|
10653
11296
|
}
|
|
10654
11297
|
const asset = {
|
|
10655
|
-
id:
|
|
11298
|
+
id: randomUUID6(),
|
|
10656
11299
|
...input,
|
|
10657
11300
|
createdAt: now3,
|
|
10658
11301
|
updatedAt: now3
|
|
@@ -10732,7 +11375,7 @@ var init_media_store = __esm({
|
|
|
10732
11375
|
`).get(input.assetId, input.observationId ?? null, input.role);
|
|
10733
11376
|
if (existing) return rowToLink(existing);
|
|
10734
11377
|
const link = {
|
|
10735
|
-
id:
|
|
11378
|
+
id: randomUUID6(),
|
|
10736
11379
|
assetId: input.assetId,
|
|
10737
11380
|
projectId: input.projectId,
|
|
10738
11381
|
...input.observationId !== void 0 ? { observationId: input.observationId } : {},
|
|
@@ -10771,7 +11414,7 @@ var init_media_store = __esm({
|
|
|
10771
11414
|
return rowToDerivation(this.db.prepare("SELECT * FROM media_derivations WHERE id = ?").get(existing.id));
|
|
10772
11415
|
}
|
|
10773
11416
|
const derivation = {
|
|
10774
|
-
id:
|
|
11417
|
+
id: randomUUID6(),
|
|
10775
11418
|
...input,
|
|
10776
11419
|
content,
|
|
10777
11420
|
...error ? { error } : {},
|
|
@@ -10858,7 +11501,7 @@ var init_media_store = __esm({
|
|
|
10858
11501
|
createJob(input) {
|
|
10859
11502
|
const now3 = Date.now();
|
|
10860
11503
|
const job = {
|
|
10861
|
-
id:
|
|
11504
|
+
id: randomUUID6(),
|
|
10862
11505
|
projectId: input.projectId,
|
|
10863
11506
|
kind: input.kind,
|
|
10864
11507
|
status: "queued",
|
|
@@ -11020,14 +11663,14 @@ var init_types2 = __esm({
|
|
|
11020
11663
|
});
|
|
11021
11664
|
|
|
11022
11665
|
// src/media/asset-store.ts
|
|
11023
|
-
import { createHash as
|
|
11666
|
+
import { createHash as createHash6, randomUUID as randomUUID7 } from "crypto";
|
|
11024
11667
|
import { copyFile, lstat, mkdir as mkdir3, open, readFile as readFile3, readdir, rename as rename2, rm, stat as stat2, writeFile as writeFile3 } from "fs/promises";
|
|
11025
11668
|
import path10 from "path";
|
|
11026
11669
|
function mediaRoot(dataDir) {
|
|
11027
11670
|
return path10.resolve(dataDir, "media");
|
|
11028
11671
|
}
|
|
11029
11672
|
function projectStorageKey(projectId) {
|
|
11030
|
-
return
|
|
11673
|
+
return createHash6("sha256").update(projectId).digest("hex").slice(0, 16);
|
|
11031
11674
|
}
|
|
11032
11675
|
function validateUnderRoot(root, candidate) {
|
|
11033
11676
|
const resolved = path10.resolve(candidate);
|
|
@@ -11091,7 +11734,7 @@ async function destinationExists(destination) {
|
|
|
11091
11734
|
async function persistBuffer(bytes, destination) {
|
|
11092
11735
|
await mkdir3(path10.dirname(destination), { recursive: true });
|
|
11093
11736
|
if (await destinationExists(destination)) return false;
|
|
11094
|
-
const temporary = `${destination}.${
|
|
11737
|
+
const temporary = `${destination}.${randomUUID7()}.tmp`;
|
|
11095
11738
|
try {
|
|
11096
11739
|
await writeFile3(temporary, bytes, { flag: "wx" });
|
|
11097
11740
|
await rename2(temporary, destination);
|
|
@@ -11136,7 +11779,7 @@ async function importMediaBuffer(input) {
|
|
|
11136
11779
|
if (input.bytes.length === 0) throw new Error("Media import rejects empty payloads");
|
|
11137
11780
|
if (input.bytes.length > maxBytes) throw new Error(`Media payload is too large (${input.bytes.length} bytes; limit ${maxBytes})`);
|
|
11138
11781
|
const detected = detectMedia(input.bytes.subarray(0, 32));
|
|
11139
|
-
const sha256 =
|
|
11782
|
+
const sha256 = createHash6("sha256").update(input.bytes).digest("hex");
|
|
11140
11783
|
return importKnownMedia({
|
|
11141
11784
|
dataDir: input.dataDir,
|
|
11142
11785
|
projectId: input.projectId,
|
|
@@ -11154,7 +11797,7 @@ async function readMediaAsset(dataDir, asset, maxBytes = DEFAULT_MAX_MEDIA_BYTES
|
|
|
11154
11797
|
if (asset.byteSize > maxBytes) throw new Error(`Media asset exceeds read limit (${asset.byteSize} bytes; limit ${maxBytes})`);
|
|
11155
11798
|
const bytes = await readFile3(getMediaAssetPath(dataDir, asset));
|
|
11156
11799
|
if (bytes.length !== asset.byteSize) throw new Error(`Media asset size no longer matches metadata: ${asset.id}`);
|
|
11157
|
-
const sha256 =
|
|
11800
|
+
const sha256 = createHash6("sha256").update(bytes).digest("hex");
|
|
11158
11801
|
if (sha256 !== asset.sha256) throw new Error(`Media asset hash no longer matches metadata: ${asset.id}`);
|
|
11159
11802
|
return bytes;
|
|
11160
11803
|
}
|
|
@@ -63905,7 +64548,7 @@ var require_gaxios = __commonJS({
|
|
|
63905
64548
|
var retry_js_1 = require_retry3();
|
|
63906
64549
|
var stream_1 = __require("stream");
|
|
63907
64550
|
var interceptor_js_1 = require_interceptor();
|
|
63908
|
-
var
|
|
64551
|
+
var randomUUID16 = async () => globalThis.crypto?.randomUUID() || (await import("crypto")).randomUUID();
|
|
63909
64552
|
var HTTP_STATUS_NO_CONTENT = 204;
|
|
63910
64553
|
var Gaxios = class {
|
|
63911
64554
|
agentCache = /* @__PURE__ */ new Map();
|
|
@@ -64178,7 +64821,7 @@ var require_gaxios = __commonJS({
|
|
|
64178
64821
|
*/
|
|
64179
64822
|
["Blob", "File", "FormData"].includes(opts.data?.constructor?.name || "");
|
|
64180
64823
|
if (opts.multipart?.length) {
|
|
64181
|
-
const boundary = await
|
|
64824
|
+
const boundary = await randomUUID16();
|
|
64182
64825
|
preparedHeaders.set("content-type", `multipart/related; boundary=${boundary}`);
|
|
64183
64826
|
opts.body = stream_1.Readable.from(this.getMultipartRequest(opts.multipart, boundary));
|
|
64184
64827
|
} else if (shouldDirectlyPassData) {
|
|
@@ -76405,7 +77048,7 @@ var require_websocket = __commonJS({
|
|
|
76405
77048
|
var http3 = __require("http");
|
|
76406
77049
|
var net = __require("net");
|
|
76407
77050
|
var tls = __require("tls");
|
|
76408
|
-
var { randomBytes, createHash:
|
|
77051
|
+
var { randomBytes, createHash: createHash14 } = __require("crypto");
|
|
76409
77052
|
var { Duplex, Readable: Readable2 } = __require("stream");
|
|
76410
77053
|
var { URL: URL2 } = __require("url");
|
|
76411
77054
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -77073,7 +77716,7 @@ var require_websocket = __commonJS({
|
|
|
77073
77716
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
77074
77717
|
return;
|
|
77075
77718
|
}
|
|
77076
|
-
const digest2 =
|
|
77719
|
+
const digest2 = createHash14("sha1").update(key + GUID).digest("base64");
|
|
77077
77720
|
if (res.headers["sec-websocket-accept"] !== digest2) {
|
|
77078
77721
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
77079
77722
|
return;
|
|
@@ -77445,7 +78088,7 @@ var require_websocket_server = __commonJS({
|
|
|
77445
78088
|
var EventEmitter = __require("events");
|
|
77446
78089
|
var http3 = __require("http");
|
|
77447
78090
|
var { Duplex } = __require("stream");
|
|
77448
|
-
var { createHash:
|
|
78091
|
+
var { createHash: createHash14 } = __require("crypto");
|
|
77449
78092
|
var extension3 = require_extension();
|
|
77450
78093
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
77451
78094
|
var subprotocol2 = require_subprotocol();
|
|
@@ -77752,7 +78395,7 @@ var require_websocket_server = __commonJS({
|
|
|
77752
78395
|
);
|
|
77753
78396
|
}
|
|
77754
78397
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
77755
|
-
const digest2 =
|
|
78398
|
+
const digest2 = createHash14("sha1").update(key + GUID).digest("base64");
|
|
77756
78399
|
const headers = [
|
|
77757
78400
|
"HTTP/1.1 101 Switching Protocols",
|
|
77758
78401
|
"Upgrade: websocket",
|
|
@@ -144890,6 +145533,186 @@ var init_audio_jobs = __esm({
|
|
|
144890
145533
|
}
|
|
144891
145534
|
});
|
|
144892
145535
|
|
|
145536
|
+
// src/memory/feedback-model.ts
|
|
145537
|
+
function feedbackWeightMultiplier(weight) {
|
|
145538
|
+
return Math.max(0.35, Math.min(1.4, 0.35 + Math.max(0, Math.min(2, weight)) * 0.525));
|
|
145539
|
+
}
|
|
145540
|
+
var init_feedback_model = __esm({
|
|
145541
|
+
"src/memory/feedback-model.ts"() {
|
|
145542
|
+
"use strict";
|
|
145543
|
+
init_esm_shims();
|
|
145544
|
+
}
|
|
145545
|
+
});
|
|
145546
|
+
|
|
145547
|
+
// src/memory/feedback.ts
|
|
145548
|
+
var feedback_exports = {};
|
|
145549
|
+
__export(feedback_exports, {
|
|
145550
|
+
FEEDBACK_DELTAS: () => FEEDBACK_DELTAS,
|
|
145551
|
+
MemoryFeedbackStore: () => MemoryFeedbackStore,
|
|
145552
|
+
applyMemoryFeedback: () => applyMemoryFeedback,
|
|
145553
|
+
feedbackWeightMultiplier: () => feedbackWeightMultiplier
|
|
145554
|
+
});
|
|
145555
|
+
import { randomUUID as randomUUID8 } from "crypto";
|
|
145556
|
+
function applyMemoryFeedback(current, event) {
|
|
145557
|
+
const delta = event.signal === "revoke" ? 0 : FEEDBACK_DELTAS[event.signal];
|
|
145558
|
+
const weight = Math.max(0, Math.min(2, current.weight + delta));
|
|
145559
|
+
const status = (event.signal === "code-conflict" || event.signal === "user-correction" || event.signal === "weaken") && weight < 0.5 ? "archived" : current.status;
|
|
145560
|
+
return { weight, status, audit: [...current.audit, { ...event }] };
|
|
145561
|
+
}
|
|
145562
|
+
function rowToEvent(row) {
|
|
145563
|
+
return {
|
|
145564
|
+
id: String(row.id),
|
|
145565
|
+
projectId: String(row.project_id),
|
|
145566
|
+
candidateKind: row.candidate_kind,
|
|
145567
|
+
candidateId: String(row.candidate_id),
|
|
145568
|
+
signal: row.signal,
|
|
145569
|
+
...row.observed_at ? { at: String(row.observed_at) } : { at: (/* @__PURE__ */ new Date()).toISOString() },
|
|
145570
|
+
...row.actor ? { actor: String(row.actor) } : {},
|
|
145571
|
+
...row.note ? { note: String(row.note) } : {},
|
|
145572
|
+
...row.source_ref ? { sourceRef: String(row.source_ref) } : {},
|
|
145573
|
+
...row.target_event_id ? { targetEventId: String(row.target_event_id) } : {},
|
|
145574
|
+
delta: Number(row.delta ?? 0)
|
|
145575
|
+
};
|
|
145576
|
+
}
|
|
145577
|
+
var FEEDBACK_DELTAS, MemoryFeedbackStore;
|
|
145578
|
+
var init_feedback = __esm({
|
|
145579
|
+
"src/memory/feedback.ts"() {
|
|
145580
|
+
"use strict";
|
|
145581
|
+
init_esm_shims();
|
|
145582
|
+
init_sqlite_db();
|
|
145583
|
+
init_feedback_model();
|
|
145584
|
+
FEEDBACK_DELTAS = {
|
|
145585
|
+
"user-correction": -0.35,
|
|
145586
|
+
"verification-success": 0.25,
|
|
145587
|
+
"verification-failure": -0.25,
|
|
145588
|
+
"code-change": -0.15,
|
|
145589
|
+
used: 0.1,
|
|
145590
|
+
"not-used": -0.05,
|
|
145591
|
+
"code-conflict": -0.4,
|
|
145592
|
+
strengthen: 0.2,
|
|
145593
|
+
weaken: -0.2
|
|
145594
|
+
};
|
|
145595
|
+
MemoryFeedbackStore = class {
|
|
145596
|
+
db = null;
|
|
145597
|
+
async init(dataDir) {
|
|
145598
|
+
this.db = getDatabase(dataDir);
|
|
145599
|
+
}
|
|
145600
|
+
requireDb() {
|
|
145601
|
+
if (!this.db) throw new Error("MemoryFeedbackStore is not initialized.");
|
|
145602
|
+
return this.db;
|
|
145603
|
+
}
|
|
145604
|
+
loadEvents(projectId, candidateKind, candidateId) {
|
|
145605
|
+
return this.requireDb().prepare(`
|
|
145606
|
+
SELECT * FROM memory_feedback_events
|
|
145607
|
+
WHERE project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
145608
|
+
ORDER BY observed_at ASC, rowid ASC
|
|
145609
|
+
`).all(projectId, candidateKind, candidateId).map(rowToEvent);
|
|
145610
|
+
}
|
|
145611
|
+
rebuild(projectId, candidateKind, candidateId) {
|
|
145612
|
+
const events = this.loadEvents(projectId, candidateKind, candidateId);
|
|
145613
|
+
const revoked = new Set(events.filter((event) => event.signal === "revoke" && event.targetEventId).map((event) => event.targetEventId));
|
|
145614
|
+
let state = { weight: 1, status: "active", audit: [] };
|
|
145615
|
+
for (const event of events) {
|
|
145616
|
+
if (event.signal === "revoke" || revoked.has(event.id)) {
|
|
145617
|
+
state.audit.push(event);
|
|
145618
|
+
continue;
|
|
145619
|
+
}
|
|
145620
|
+
state = applyMemoryFeedback(state, event);
|
|
145621
|
+
}
|
|
145622
|
+
this.requireDb().prepare(`
|
|
145623
|
+
INSERT INTO memory_feedback_states (project_id, candidate_kind, candidate_id, weight, lifecycle_status, updated_at)
|
|
145624
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
145625
|
+
ON CONFLICT(project_id, candidate_kind, candidate_id) DO UPDATE SET
|
|
145626
|
+
weight = excluded.weight, lifecycle_status = excluded.lifecycle_status, updated_at = excluded.updated_at
|
|
145627
|
+
`).run(projectId, candidateKind, candidateId, state.weight, state.status, (/* @__PURE__ */ new Date()).toISOString());
|
|
145628
|
+
return state;
|
|
145629
|
+
}
|
|
145630
|
+
getState(projectId, candidateKind, candidateId) {
|
|
145631
|
+
const row = this.requireDb().prepare(`
|
|
145632
|
+
SELECT weight, lifecycle_status FROM memory_feedback_states
|
|
145633
|
+
WHERE project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
145634
|
+
`).get(projectId, candidateKind, candidateId);
|
|
145635
|
+
if (!row) return { weight: 1, status: "active", audit: [] };
|
|
145636
|
+
return {
|
|
145637
|
+
weight: Number(row.weight ?? 1),
|
|
145638
|
+
status: row.lifecycle_status ?? "active",
|
|
145639
|
+
audit: this.loadEvents(projectId, candidateKind, candidateId)
|
|
145640
|
+
};
|
|
145641
|
+
}
|
|
145642
|
+
listStates(projectId, candidateKind = "observation") {
|
|
145643
|
+
return this.requireDb().prepare(`
|
|
145644
|
+
SELECT candidate_id, weight, lifecycle_status, updated_at
|
|
145645
|
+
FROM memory_feedback_states WHERE project_id = ? AND candidate_kind = ?
|
|
145646
|
+
ORDER BY updated_at DESC
|
|
145647
|
+
`).all(projectId, candidateKind).map((row) => ({
|
|
145648
|
+
candidateId: String(row.candidate_id),
|
|
145649
|
+
weight: Number(row.weight),
|
|
145650
|
+
status: row.lifecycle_status,
|
|
145651
|
+
updatedAt: String(row.updated_at)
|
|
145652
|
+
}));
|
|
145653
|
+
}
|
|
145654
|
+
weights(projectId, candidateKind = "observation") {
|
|
145655
|
+
const states = /* @__PURE__ */ new Map();
|
|
145656
|
+
for (const row of this.listStates(projectId, candidateKind)) {
|
|
145657
|
+
states.set(row.candidateId, this.getState(projectId, candidateKind, row.candidateId));
|
|
145658
|
+
}
|
|
145659
|
+
return states;
|
|
145660
|
+
}
|
|
145661
|
+
record(input) {
|
|
145662
|
+
if (input.signal === "revoke" && !input.targetEventId) {
|
|
145663
|
+
throw new Error("A revoke feedback event requires targetEventId.");
|
|
145664
|
+
}
|
|
145665
|
+
if (input.signal === "revoke") {
|
|
145666
|
+
const target = this.requireDb().prepare(`
|
|
145667
|
+
SELECT 1 FROM memory_feedback_events
|
|
145668
|
+
WHERE id = ? AND project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
145669
|
+
`).get(input.targetEventId, input.projectId, input.candidateKind, input.candidateId);
|
|
145670
|
+
if (!target) throw new Error("The feedback event to revoke was not found in the same candidate scope.");
|
|
145671
|
+
}
|
|
145672
|
+
const event = {
|
|
145673
|
+
id: randomUUID8(),
|
|
145674
|
+
projectId: input.projectId,
|
|
145675
|
+
candidateKind: input.candidateKind,
|
|
145676
|
+
candidateId: input.candidateId,
|
|
145677
|
+
signal: input.signal,
|
|
145678
|
+
sourceRef: input.sourceRef,
|
|
145679
|
+
...input.actor ? { actor: input.actor } : {},
|
|
145680
|
+
...input.note ? { note: input.note.slice(0, 2e3) } : {},
|
|
145681
|
+
...input.targetEventId ? { targetEventId: input.targetEventId } : {},
|
|
145682
|
+
at: input.at ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
145683
|
+
delta: input.signal === "revoke" ? 0 : FEEDBACK_DELTAS[input.signal]
|
|
145684
|
+
};
|
|
145685
|
+
this.requireDb().prepare(`
|
|
145686
|
+
INSERT INTO memory_feedback_events (
|
|
145687
|
+
id, project_id, candidate_kind, candidate_id, signal, actor, note,
|
|
145688
|
+
source_ref, target_event_id, delta, observed_at
|
|
145689
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
145690
|
+
`).run(
|
|
145691
|
+
event.id,
|
|
145692
|
+
event.projectId,
|
|
145693
|
+
event.candidateKind,
|
|
145694
|
+
event.candidateId,
|
|
145695
|
+
event.signal,
|
|
145696
|
+
event.actor ?? null,
|
|
145697
|
+
event.note ?? null,
|
|
145698
|
+
event.sourceRef,
|
|
145699
|
+
event.targetEventId ?? null,
|
|
145700
|
+
event.delta,
|
|
145701
|
+
event.at
|
|
145702
|
+
);
|
|
145703
|
+
return { event, state: this.rebuild(input.projectId, input.candidateKind, input.candidateId) };
|
|
145704
|
+
}
|
|
145705
|
+
audit(projectId, candidateKind, candidateId, limit2 = 100) {
|
|
145706
|
+
return this.requireDb().prepare(`
|
|
145707
|
+
SELECT * FROM memory_feedback_events
|
|
145708
|
+
WHERE project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
145709
|
+
ORDER BY observed_at DESC, rowid DESC LIMIT ?
|
|
145710
|
+
`).all(projectId, candidateKind, candidateId, Math.min(200, Math.max(1, Math.floor(limit2)))).map(rowToEvent);
|
|
145711
|
+
}
|
|
145712
|
+
};
|
|
145713
|
+
}
|
|
145714
|
+
});
|
|
145715
|
+
|
|
144893
145716
|
// src/memory/retention.ts
|
|
144894
145717
|
var retention_exports = {};
|
|
144895
145718
|
__export(retention_exports, {
|
|
@@ -144931,6 +145754,7 @@ function getEffectiveRetentionDays(doc) {
|
|
|
144931
145754
|
}
|
|
144932
145755
|
function isImmune(doc) {
|
|
144933
145756
|
if (doc.type === "probe") return false;
|
|
145757
|
+
if (doc.feedbackStatus === "archived") return false;
|
|
144934
145758
|
if (doc.admissionState === "candidate" || doc.admissionState === "ephemeral") return false;
|
|
144935
145759
|
if (doc.valueCategory === "core") return true;
|
|
144936
145760
|
const importance = getImportanceLevel(doc);
|
|
@@ -144963,7 +145787,8 @@ function calculateRelevance(doc, referenceTime) {
|
|
|
144963
145787
|
const decayFactor = Math.exp(-ageDays / retention);
|
|
144964
145788
|
const accessCount = doc.accessCount ?? 0;
|
|
144965
145789
|
const accessBoost = Math.min(2, 1 + 0.1 * accessCount);
|
|
144966
|
-
|
|
145790
|
+
const feedbackMultiplier = doc.feedbackWeight === void 0 ? 1 : feedbackWeightMultiplier(doc.feedbackWeight);
|
|
145791
|
+
let totalScore = base * decayFactor * accessBoost * feedbackMultiplier;
|
|
144967
145792
|
const immune = isImmune(doc);
|
|
144968
145793
|
if (immune) {
|
|
144969
145794
|
totalScore = Math.max(totalScore, 0.5);
|
|
@@ -144975,7 +145800,8 @@ function calculateRelevance(doc, referenceTime) {
|
|
|
144975
145800
|
decayFactor,
|
|
144976
145801
|
accessBoost,
|
|
144977
145802
|
ageDays,
|
|
144978
|
-
isImmune: immune
|
|
145803
|
+
isImmune: immune,
|
|
145804
|
+
feedbackMultiplier
|
|
144979
145805
|
};
|
|
144980
145806
|
}
|
|
144981
145807
|
function rankByRelevance(docs, referenceTime) {
|
|
@@ -144983,6 +145809,7 @@ function rankByRelevance(docs, referenceTime) {
|
|
|
144983
145809
|
}
|
|
144984
145810
|
function getRetentionZone(doc, referenceTime) {
|
|
144985
145811
|
const now3 = referenceTime ?? /* @__PURE__ */ new Date();
|
|
145812
|
+
if (doc.feedbackStatus === "archived") return "archive-candidate";
|
|
144986
145813
|
const importance = getImportanceLevel(doc);
|
|
144987
145814
|
const retention = getEffectiveRetentionDays(doc);
|
|
144988
145815
|
const createdAt = new Date(doc.createdAt);
|
|
@@ -145054,7 +145881,7 @@ function explainRetention(doc, referenceTime) {
|
|
|
145054
145881
|
summary: parts.join(" ; ")
|
|
145055
145882
|
};
|
|
145056
145883
|
}
|
|
145057
|
-
function toRetentionDocument(obs, accessMap) {
|
|
145884
|
+
function toRetentionDocument(obs, accessMap, feedback) {
|
|
145058
145885
|
const access2 = accessMap?.get(obs.id);
|
|
145059
145886
|
return {
|
|
145060
145887
|
id: `obs-${obs.id}`,
|
|
@@ -145076,11 +145903,12 @@ function toRetentionDocument(obs, accessMap) {
|
|
|
145076
145903
|
sourceDetail: obs.sourceDetail ?? "",
|
|
145077
145904
|
valueCategory: obs.valueCategory ?? "",
|
|
145078
145905
|
admissionState: obs.admissionState ?? "",
|
|
145079
|
-
admissionReason: obs.admissionReason ?? ""
|
|
145906
|
+
admissionReason: obs.admissionReason ?? "",
|
|
145907
|
+
...feedback ? { feedbackWeight: feedback.weight, feedbackStatus: feedback.status } : {}
|
|
145080
145908
|
};
|
|
145081
145909
|
}
|
|
145082
145910
|
function projectObservationRetention(observation, options = {}) {
|
|
145083
|
-
const document2 = toRetentionDocument(observation, options.accessMap);
|
|
145911
|
+
const document2 = toRetentionDocument(observation, options.accessMap, options.feedback);
|
|
145084
145912
|
const relevance = calculateRelevance(document2, options.referenceTime);
|
|
145085
145913
|
const explanation = explainRetention(document2, options.referenceTime);
|
|
145086
145914
|
return {
|
|
@@ -145105,7 +145933,17 @@ function summarizeRetentionProjections(projections) {
|
|
|
145105
145933
|
}
|
|
145106
145934
|
return { active, stale, archiveCandidates, immune };
|
|
145107
145935
|
}
|
|
145108
|
-
async function
|
|
145936
|
+
async function loadFeedbackStore(dataDir) {
|
|
145937
|
+
try {
|
|
145938
|
+
const { MemoryFeedbackStore: MemoryFeedbackStore2 } = await Promise.resolve().then(() => (init_feedback(), feedback_exports));
|
|
145939
|
+
const store = new MemoryFeedbackStore2();
|
|
145940
|
+
await store.init(dataDir);
|
|
145941
|
+
return store;
|
|
145942
|
+
} catch {
|
|
145943
|
+
return void 0;
|
|
145944
|
+
}
|
|
145945
|
+
}
|
|
145946
|
+
async function archiveExpiredBatch(projectDir2, options) {
|
|
145109
145947
|
const store = getObservationStore();
|
|
145110
145948
|
const limit2 = Math.min(500, Math.max(1, Math.floor(options.limit ?? 100)));
|
|
145111
145949
|
const afterId = Math.max(0, Math.floor(options.afterId ?? 0));
|
|
@@ -145114,11 +145952,13 @@ async function archiveExpiredBatch(_projectDir, options) {
|
|
|
145114
145952
|
afterId,
|
|
145115
145953
|
limit: limit2 + 1
|
|
145116
145954
|
});
|
|
145955
|
+
const feedback = await loadFeedbackStore(projectDir2);
|
|
145117
145956
|
const hasMore = page.length > limit2;
|
|
145118
145957
|
const scanned = hasMore ? page.slice(0, limit2) : page;
|
|
145119
145958
|
const candidateIds = scanned.filter((observation) => !options.reader || canManageObservation(observation, options.reader)).filter((observation) => projectObservationRetention(observation, {
|
|
145120
145959
|
accessMap: options.accessMap,
|
|
145121
|
-
referenceTime: options.referenceTime
|
|
145960
|
+
referenceTime: options.referenceTime,
|
|
145961
|
+
...feedback ? { feedback: feedback.getState(options.projectId, "observation", String(observation.id)) } : {}
|
|
145122
145962
|
}).zone === "archive-candidate").map((observation) => observation.id);
|
|
145123
145963
|
const archived = candidateIds.length === 0 ? 0 : await store.atomic(async (tx) => {
|
|
145124
145964
|
const updates = await Promise.all(
|
|
@@ -145149,6 +145989,7 @@ async function archiveExpired(projectDir2, referenceTime, accessMap, projectId,
|
|
|
145149
145989
|
const remaining = reader ? remainingObservations.filter((observation) => canManageObservation(observation, reader)).length : remainingObservations.length;
|
|
145150
145990
|
return { archived, remaining };
|
|
145151
145991
|
}
|
|
145992
|
+
const feedback = await loadFeedbackStore(projectDir2);
|
|
145152
145993
|
return await store.atomic(async (tx) => {
|
|
145153
145994
|
const allObs = await tx.loadAll();
|
|
145154
145995
|
const activeObs = allObs.filter(
|
|
@@ -145156,7 +145997,11 @@ async function archiveExpired(projectDir2, referenceTime, accessMap, projectId,
|
|
|
145156
145997
|
);
|
|
145157
145998
|
const archivedIds = [];
|
|
145158
145999
|
for (const obs of activeObs) {
|
|
145159
|
-
const retention = projectObservationRetention(obs, {
|
|
146000
|
+
const retention = projectObservationRetention(obs, {
|
|
146001
|
+
accessMap,
|
|
146002
|
+
referenceTime,
|
|
146003
|
+
...feedback ? { feedback: feedback.getState(obs.projectId, "observation", String(obs.id)) } : {}
|
|
146004
|
+
});
|
|
145160
146005
|
if (retention.zone === "archive-candidate") {
|
|
145161
146006
|
archivedIds.push(obs.id);
|
|
145162
146007
|
}
|
|
@@ -145176,6 +146021,7 @@ var init_retention = __esm({
|
|
|
145176
146021
|
init_esm_shims();
|
|
145177
146022
|
init_obs_store();
|
|
145178
146023
|
init_visibility();
|
|
146024
|
+
init_feedback_model();
|
|
145179
146025
|
RETENTION_DAYS = {
|
|
145180
146026
|
critical: 365,
|
|
145181
146027
|
high: 180,
|
|
@@ -145212,7 +146058,7 @@ var init_retention = __esm({
|
|
|
145212
146058
|
});
|
|
145213
146059
|
|
|
145214
146060
|
// src/memory/owner.ts
|
|
145215
|
-
import { randomUUID as
|
|
146061
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
145216
146062
|
import { promises as fs9 } from "fs";
|
|
145217
146063
|
import path16 from "path";
|
|
145218
146064
|
function ownerPath(dataDir) {
|
|
@@ -145242,7 +146088,7 @@ async function resolveLocalMemoryOwner(dataDir, options = {}) {
|
|
|
145242
146088
|
await fs9.mkdir(path16.dirname(filePath), { recursive: true });
|
|
145243
146089
|
const created = {
|
|
145244
146090
|
version: 1,
|
|
145245
|
-
id: "local-" +
|
|
146091
|
+
id: "local-" + randomUUID9(),
|
|
145246
146092
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
145247
146093
|
};
|
|
145248
146094
|
try {
|
|
@@ -145265,7 +146111,7 @@ var init_owner = __esm({
|
|
|
145265
146111
|
});
|
|
145266
146112
|
|
|
145267
146113
|
// src/memory/long-term-store.ts
|
|
145268
|
-
import { randomUUID as
|
|
146114
|
+
import { randomUUID as randomUUID10 } from "crypto";
|
|
145269
146115
|
function optionalText2(value) {
|
|
145270
146116
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
145271
146117
|
}
|
|
@@ -145316,7 +146162,7 @@ function rowToEvidence(row) {
|
|
|
145316
146162
|
createdAt: row.createdAt
|
|
145317
146163
|
};
|
|
145318
146164
|
}
|
|
145319
|
-
function
|
|
146165
|
+
function rowToEvent2(row) {
|
|
145320
146166
|
return {
|
|
145321
146167
|
id: row.id,
|
|
145322
146168
|
memoryId: row.memoryId,
|
|
@@ -145425,7 +146271,7 @@ var init_long_term_store = __esm({
|
|
|
145425
146271
|
}
|
|
145426
146272
|
insertEvidence(input) {
|
|
145427
146273
|
const evidence = {
|
|
145428
|
-
id:
|
|
146274
|
+
id: randomUUID10(),
|
|
145429
146275
|
...input,
|
|
145430
146276
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
145431
146277
|
};
|
|
@@ -145452,7 +146298,7 @@ var init_long_term_store = __esm({
|
|
|
145452
146298
|
}
|
|
145453
146299
|
recordEvent(input) {
|
|
145454
146300
|
const event = {
|
|
145455
|
-
id:
|
|
146301
|
+
id: randomUUID10(),
|
|
145456
146302
|
...input,
|
|
145457
146303
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
145458
146304
|
};
|
|
@@ -145473,7 +146319,7 @@ var init_long_term_store = __esm({
|
|
|
145473
146319
|
listEvents(memoryId) {
|
|
145474
146320
|
return this.db.prepare(`
|
|
145475
146321
|
SELECT * FROM long_term_memory_events WHERE memoryId = ? ORDER BY createdAt ASC, rowid ASC
|
|
145476
|
-
`).all(memoryId).map(
|
|
146322
|
+
`).all(memoryId).map(rowToEvent2);
|
|
145477
146323
|
}
|
|
145478
146324
|
markAccess(ids, at = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
145479
146325
|
const unique = [...new Set(ids.filter(Boolean))];
|
|
@@ -145542,7 +146388,7 @@ __export(long_term_exports, {
|
|
|
145542
146388
|
selectLongTermMemoriesForTask: () => selectLongTermMemoriesForTask,
|
|
145543
146389
|
supersedeLongTermMemory: () => supersedeLongTermMemory
|
|
145544
146390
|
});
|
|
145545
|
-
import { randomUUID as
|
|
146391
|
+
import { randomUUID as randomUUID11 } from "crypto";
|
|
145546
146392
|
function isOneOf(value, values) {
|
|
145547
146393
|
return typeof value === "string" && values.includes(value);
|
|
145548
146394
|
}
|
|
@@ -145724,7 +146570,7 @@ async function createManualLongTermMemory(input) {
|
|
|
145724
146570
|
const owner = await resolveLocalMemoryOwner(input.dataDir, { create: true });
|
|
145725
146571
|
if (!owner) throw new Error("Memorix could not resolve a local memory owner.");
|
|
145726
146572
|
assertScope(input.scope);
|
|
145727
|
-
const evidence = input.scope === "user" ? [{ kind: "user", referenceId: owner.id, relation: "user-confirmed" }] : [{ kind: "manual", referenceId: "manual:" +
|
|
146573
|
+
const evidence = input.scope === "user" ? [{ kind: "user", referenceId: owner.id, relation: "user-confirmed" }] : [{ kind: "manual", referenceId: "manual:" + randomUUID11(), relation: "supports" }];
|
|
145728
146574
|
return createLongTermMemoryWithDataDir({
|
|
145729
146575
|
dataDir: input.dataDir,
|
|
145730
146576
|
originProjectId: input.projectId,
|
|
@@ -145779,7 +146625,7 @@ async function createLongTermMemoryWithDataDir(input) {
|
|
|
145779
146625
|
assertPortableEvidence(input.scope, portability, evidenceInputs);
|
|
145780
146626
|
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
145781
146627
|
const memory = {
|
|
145782
|
-
id:
|
|
146628
|
+
id: randomUUID11(),
|
|
145783
146629
|
originProjectId: compactText(input.originProjectId, "origin project id", 1e3),
|
|
145784
146630
|
ownerId: compactText(input.ownerId, "owner id", 160),
|
|
145785
146631
|
scope: input.scope,
|
|
@@ -146098,7 +146944,7 @@ var init_long_term = __esm({
|
|
|
146098
146944
|
|
|
146099
146945
|
// src/codegraph/code-state.ts
|
|
146100
146946
|
import { execFile as execFile2 } from "child_process";
|
|
146101
|
-
import { createHash as
|
|
146947
|
+
import { createHash as createHash7 } from "crypto";
|
|
146102
146948
|
import { promisify as promisify3 } from "util";
|
|
146103
146949
|
async function runGit(rootPath, args) {
|
|
146104
146950
|
try {
|
|
@@ -146127,7 +146973,7 @@ function changedPathCount(status) {
|
|
|
146127
146973
|
return count2;
|
|
146128
146974
|
}
|
|
146129
146975
|
function fingerprint(baseRevision, status) {
|
|
146130
|
-
return
|
|
146976
|
+
return createHash7("sha256").update(baseRevision ?? "").update("\0").update(status).digest("hex");
|
|
146131
146977
|
}
|
|
146132
146978
|
async function collectCodeStateSnapshot(input) {
|
|
146133
146979
|
const [revision, status] = await Promise.all([
|
|
@@ -146227,11 +147073,11 @@ __export(lite_provider_exports, {
|
|
|
146227
147073
|
indexProjectLite: () => indexProjectLite,
|
|
146228
147074
|
refreshProjectLite: () => refreshProjectLite
|
|
146229
147075
|
});
|
|
146230
|
-
import { createHash as
|
|
147076
|
+
import { createHash as createHash8 } from "crypto";
|
|
146231
147077
|
import { readdirSync as readdirSync2, readFileSync as readFileSync7, statSync as statSync3 } from "fs";
|
|
146232
147078
|
import { join as join4, relative } from "path";
|
|
146233
147079
|
function hashText(text2) {
|
|
146234
|
-
return
|
|
147080
|
+
return createHash8("sha256").update(text2).digest("hex");
|
|
146235
147081
|
}
|
|
146236
147082
|
function extension2(path21) {
|
|
146237
147083
|
const index = path21.lastIndexOf(".");
|
|
@@ -146641,7 +147487,7 @@ var claim_store_exports = {};
|
|
|
146641
147487
|
__export(claim_store_exports, {
|
|
146642
147488
|
ClaimStore: () => ClaimStore
|
|
146643
147489
|
});
|
|
146644
|
-
import { createHash as
|
|
147490
|
+
import { createHash as createHash9, randomUUID as randomUUID12 } from "crypto";
|
|
146645
147491
|
function optionalText3(value) {
|
|
146646
147492
|
return typeof value === "string" && value ? value : void 0;
|
|
146647
147493
|
}
|
|
@@ -146680,7 +147526,7 @@ function rowToEvidence2(row) {
|
|
|
146680
147526
|
createdAt: row.createdAt
|
|
146681
147527
|
};
|
|
146682
147528
|
}
|
|
146683
|
-
function
|
|
147529
|
+
function rowToEvent3(row) {
|
|
146684
147530
|
return {
|
|
146685
147531
|
id: row.id,
|
|
146686
147532
|
projectId: row.projectId,
|
|
@@ -146694,7 +147540,7 @@ function rowToEvent2(row) {
|
|
|
146694
147540
|
};
|
|
146695
147541
|
}
|
|
146696
147542
|
function evidenceKey(input) {
|
|
146697
|
-
return
|
|
147543
|
+
return createHash9("sha256").update(JSON.stringify([
|
|
146698
147544
|
input.evidenceKind,
|
|
146699
147545
|
input.evidenceId,
|
|
146700
147546
|
input.relation,
|
|
@@ -146825,7 +147671,7 @@ var init_claim_store = __esm({
|
|
|
146825
147671
|
locator, capturedHash, evidenceKey, createdAt
|
|
146826
147672
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
146827
147673
|
`).run(
|
|
146828
|
-
|
|
147674
|
+
randomUUID12(),
|
|
146829
147675
|
input.claimId,
|
|
146830
147676
|
input.evidenceKind,
|
|
146831
147677
|
input.evidenceId,
|
|
@@ -146847,7 +147693,7 @@ var init_claim_store = __esm({
|
|
|
146847
147693
|
}
|
|
146848
147694
|
recordEvent(input) {
|
|
146849
147695
|
const event = {
|
|
146850
|
-
id:
|
|
147696
|
+
id: randomUUID12(),
|
|
146851
147697
|
...input,
|
|
146852
147698
|
...input.detail ? { detail: sanitizeCredentials(input.detail) } : {},
|
|
146853
147699
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -146875,7 +147721,7 @@ var init_claim_store = __esm({
|
|
|
146875
147721
|
SELECT * FROM knowledge_claim_events
|
|
146876
147722
|
WHERE claimId = ?
|
|
146877
147723
|
ORDER BY createdAt ASC, id
|
|
146878
|
-
`).all(claimId).map(
|
|
147724
|
+
`).all(claimId).map(rowToEvent3);
|
|
146879
147725
|
}
|
|
146880
147726
|
};
|
|
146881
147727
|
}
|
|
@@ -146892,7 +147738,7 @@ __export(claims_exports, {
|
|
|
146892
147738
|
supersedeClaim: () => supersedeClaim,
|
|
146893
147739
|
writeClaim: () => writeClaim
|
|
146894
147740
|
});
|
|
146895
|
-
import { createHash as
|
|
147741
|
+
import { createHash as createHash10, randomUUID as randomUUID13 } from "crypto";
|
|
146896
147742
|
function compactText2(value, field) {
|
|
146897
147743
|
if (typeof value !== "string") throw new Error("Claim " + field + " must be text");
|
|
146898
147744
|
const sanitized = sanitizeCredentials(value).trim().replace(/\s+/g, " ");
|
|
@@ -146904,7 +147750,7 @@ function normalizedTerm(value) {
|
|
|
146904
147750
|
return compactText2(value, "identity").toLocaleLowerCase("en-US");
|
|
146905
147751
|
}
|
|
146906
147752
|
function hashIdentity(parts) {
|
|
146907
|
-
return
|
|
147753
|
+
return createHash10("sha256").update(parts.join(String.fromCharCode(31))).digest("hex");
|
|
146908
147754
|
}
|
|
146909
147755
|
function buildClaimIdentity(input) {
|
|
146910
147756
|
const subject = normalizedTerm(input.subject);
|
|
@@ -146978,7 +147824,7 @@ function normalizeClaimInput(input) {
|
|
|
146978
147824
|
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
146979
147825
|
return {
|
|
146980
147826
|
claim: {
|
|
146981
|
-
id:
|
|
147827
|
+
id: randomUUID13(),
|
|
146982
147828
|
projectId,
|
|
146983
147829
|
subject,
|
|
146984
147830
|
predicate,
|
|
@@ -147145,7 +147991,7 @@ function supersedeClaim(store, input) {
|
|
|
147145
147991
|
});
|
|
147146
147992
|
}
|
|
147147
147993
|
function hashObservation(observation) {
|
|
147148
|
-
return
|
|
147994
|
+
return createHash10("sha256").update(JSON.stringify([
|
|
147149
147995
|
observation.title,
|
|
147150
147996
|
observation.narrative,
|
|
147151
147997
|
observation.facts,
|
|
@@ -147389,11 +148235,11 @@ var init_frontmatter = __esm({
|
|
|
147389
148235
|
});
|
|
147390
148236
|
|
|
147391
148237
|
// src/knowledge/markdown.ts
|
|
147392
|
-
import { createHash as
|
|
148238
|
+
import { createHash as createHash11 } from "crypto";
|
|
147393
148239
|
import { promises as fs10 } from "fs";
|
|
147394
148240
|
import path17 from "path";
|
|
147395
148241
|
function hashContent(content) {
|
|
147396
|
-
return
|
|
148242
|
+
return createHash11("sha256").update(content).digest("hex");
|
|
147397
148243
|
}
|
|
147398
148244
|
function stringField(data, key) {
|
|
147399
148245
|
const value = data[key];
|
|
@@ -147519,11 +148365,11 @@ __export(wiki_exports, {
|
|
|
147519
148365
|
lintKnowledgeWorkspace: () => lintKnowledgeWorkspace,
|
|
147520
148366
|
readKnowledgePage: () => readKnowledgePage
|
|
147521
148367
|
});
|
|
147522
|
-
import { createHash as
|
|
148368
|
+
import { createHash as createHash12 } from "crypto";
|
|
147523
148369
|
import { promises as fs11 } from "fs";
|
|
147524
148370
|
import path18 from "path";
|
|
147525
148371
|
function hash2(value) {
|
|
147526
|
-
return
|
|
148372
|
+
return createHash12("sha256").update(value).digest("hex");
|
|
147527
148373
|
}
|
|
147528
148374
|
function now() {
|
|
147529
148375
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -148063,7 +148909,7 @@ var init_workflow_sync = __esm({
|
|
|
148063
148909
|
});
|
|
148064
148910
|
|
|
148065
148911
|
// src/knowledge/workflow-store.ts
|
|
148066
|
-
import { randomUUID as
|
|
148912
|
+
import { randomUUID as randomUUID14 } from "crypto";
|
|
148067
148913
|
function parseJson(value, fallback) {
|
|
148068
148914
|
if (typeof value !== "string" || !value) return fallback;
|
|
148069
148915
|
try {
|
|
@@ -148163,7 +149009,7 @@ var init_workflow_store = __esm({
|
|
|
148163
149009
|
}
|
|
148164
149010
|
recordRun(input) {
|
|
148165
149011
|
const run = {
|
|
148166
|
-
id:
|
|
149012
|
+
id: randomUUID14(),
|
|
148167
149013
|
workflowId: input.workflowId,
|
|
148168
149014
|
projectId: input.projectId,
|
|
148169
149015
|
task: input.task.trim(),
|
|
@@ -148231,7 +149077,7 @@ var init_outcome_types = __esm({
|
|
|
148231
149077
|
});
|
|
148232
149078
|
|
|
148233
149079
|
// src/knowledge/outcome-store.ts
|
|
148234
|
-
import { randomUUID as
|
|
149080
|
+
import { randomUUID as randomUUID15 } from "crypto";
|
|
148235
149081
|
function optionalText5(value) {
|
|
148236
149082
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
148237
149083
|
}
|
|
@@ -148275,7 +149121,7 @@ var init_outcome_store = __esm({
|
|
|
148275
149121
|
}
|
|
148276
149122
|
record(input) {
|
|
148277
149123
|
const signal = {
|
|
148278
|
-
id:
|
|
149124
|
+
id: randomUUID15(),
|
|
148279
149125
|
projectId: text(input.projectId, "project id"),
|
|
148280
149126
|
candidateKind: oneOf(input.candidateKind, MEMORY_OUTCOME_CANDIDATE_KINDS, "candidate kind"),
|
|
148281
149127
|
candidateId: text(input.candidateId, "candidate id"),
|
|
@@ -148380,11 +149226,11 @@ __export(workflows_exports, {
|
|
|
148380
149226
|
syncCanonicalWorkflows: () => syncCanonicalWorkflows,
|
|
148381
149227
|
writeCanonicalWorkflow: () => writeCanonicalWorkflow
|
|
148382
149228
|
});
|
|
148383
|
-
import { createHash as
|
|
149229
|
+
import { createHash as createHash13 } from "crypto";
|
|
148384
149230
|
import { promises as fs12 } from "fs";
|
|
148385
149231
|
import path19 from "path";
|
|
148386
149232
|
function hash3(value) {
|
|
148387
|
-
return
|
|
149233
|
+
return createHash13("sha256").update(value).digest("hex");
|
|
148388
149234
|
}
|
|
148389
149235
|
function now2() {
|
|
148390
149236
|
return (/* @__PURE__ */ new Date()).toISOString();
|