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 },
|
|
@@ -487,7 +495,7 @@ function closeAllDatabases() {
|
|
|
487
495
|
_dbCache.delete(key);
|
|
488
496
|
}
|
|
489
497
|
}
|
|
490
|
-
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;
|
|
498
|
+
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;
|
|
491
499
|
var init_sqlite_db = __esm({
|
|
492
500
|
"src/store/sqlite-db.ts"() {
|
|
493
501
|
"use strict";
|
|
@@ -1133,6 +1141,79 @@ CREATE TABLE IF NOT EXISTS compaction_checkpoints (
|
|
|
1133
1141
|
created_at TEXT NOT NULL,
|
|
1134
1142
|
updated_at TEXT NOT NULL
|
|
1135
1143
|
);
|
|
1144
|
+
`;
|
|
1145
|
+
CREATE_EVIDENCE_CARDS_TABLE = `
|
|
1146
|
+
CREATE TABLE IF NOT EXISTS evidence_cards (
|
|
1147
|
+
id TEXT PRIMARY KEY,
|
|
1148
|
+
project_id TEXT NOT NULL,
|
|
1149
|
+
candidate_kind TEXT NOT NULL,
|
|
1150
|
+
candidate_id TEXT NOT NULL,
|
|
1151
|
+
title TEXT NOT NULL,
|
|
1152
|
+
summary TEXT NOT NULL DEFAULT '',
|
|
1153
|
+
entity_name TEXT,
|
|
1154
|
+
source_kind TEXT NOT NULL,
|
|
1155
|
+
source_ref TEXT NOT NULL,
|
|
1156
|
+
locator TEXT,
|
|
1157
|
+
captured_hash TEXT,
|
|
1158
|
+
session_id TEXT,
|
|
1159
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
1160
|
+
verification TEXT NOT NULL DEFAULT 'unverified',
|
|
1161
|
+
freshness TEXT NOT NULL DEFAULT 'current',
|
|
1162
|
+
stale_reason TEXT,
|
|
1163
|
+
files_json TEXT NOT NULL DEFAULT '[]',
|
|
1164
|
+
related_entities_json TEXT NOT NULL DEFAULT '[]',
|
|
1165
|
+
created_at TEXT NOT NULL,
|
|
1166
|
+
updated_at TEXT NOT NULL,
|
|
1167
|
+
UNIQUE(project_id, candidate_kind, candidate_id)
|
|
1168
|
+
);
|
|
1169
|
+
`;
|
|
1170
|
+
CREATE_EVIDENCE_CARD_EVENTS_TABLE = `
|
|
1171
|
+
CREATE TABLE IF NOT EXISTS evidence_card_events (
|
|
1172
|
+
id TEXT PRIMARY KEY,
|
|
1173
|
+
project_id TEXT NOT NULL,
|
|
1174
|
+
card_id TEXT NOT NULL,
|
|
1175
|
+
kind TEXT NOT NULL,
|
|
1176
|
+
detail TEXT,
|
|
1177
|
+
created_at TEXT NOT NULL,
|
|
1178
|
+
FOREIGN KEY (card_id) REFERENCES evidence_cards(id) ON DELETE CASCADE
|
|
1179
|
+
);
|
|
1180
|
+
`;
|
|
1181
|
+
CREATE_MEMORY_FEEDBACK_STATES_TABLE = `
|
|
1182
|
+
CREATE TABLE IF NOT EXISTS memory_feedback_states (
|
|
1183
|
+
project_id TEXT NOT NULL,
|
|
1184
|
+
candidate_kind TEXT NOT NULL,
|
|
1185
|
+
candidate_id TEXT NOT NULL,
|
|
1186
|
+
weight REAL NOT NULL DEFAULT 1.0,
|
|
1187
|
+
lifecycle_status TEXT NOT NULL DEFAULT 'active',
|
|
1188
|
+
updated_at TEXT NOT NULL,
|
|
1189
|
+
PRIMARY KEY (project_id, candidate_kind, candidate_id)
|
|
1190
|
+
);
|
|
1191
|
+
`;
|
|
1192
|
+
CREATE_MEMORY_FEEDBACK_EVENTS_TABLE = `
|
|
1193
|
+
CREATE TABLE IF NOT EXISTS memory_feedback_events (
|
|
1194
|
+
id TEXT PRIMARY KEY,
|
|
1195
|
+
project_id TEXT NOT NULL,
|
|
1196
|
+
candidate_kind TEXT NOT NULL,
|
|
1197
|
+
candidate_id TEXT NOT NULL,
|
|
1198
|
+
signal TEXT NOT NULL,
|
|
1199
|
+
actor TEXT,
|
|
1200
|
+
note TEXT,
|
|
1201
|
+
source_ref TEXT NOT NULL,
|
|
1202
|
+
target_event_id TEXT,
|
|
1203
|
+
delta REAL NOT NULL DEFAULT 0,
|
|
1204
|
+
observed_at TEXT NOT NULL
|
|
1205
|
+
);
|
|
1206
|
+
`;
|
|
1207
|
+
CREATE_MCP_BINDINGS_TABLE = `
|
|
1208
|
+
CREATE TABLE IF NOT EXISTS mcp_bindings (
|
|
1209
|
+
handle_id TEXT PRIMARY KEY,
|
|
1210
|
+
project_id TEXT NOT NULL,
|
|
1211
|
+
project_root TEXT NOT NULL,
|
|
1212
|
+
data_dir TEXT NOT NULL,
|
|
1213
|
+
created_at TEXT NOT NULL,
|
|
1214
|
+
last_used_at TEXT NOT NULL,
|
|
1215
|
+
expires_at TEXT
|
|
1216
|
+
);
|
|
1136
1217
|
`;
|
|
1137
1218
|
CREATE_INDEXES = `
|
|
1138
1219
|
CREATE INDEX IF NOT EXISTS idx_observations_projectId ON observations(projectId);
|
|
@@ -1195,6 +1276,12 @@ CREATE INDEX IF NOT EXISTS idx_maintenance_targets_updated ON maintenance_target
|
|
|
1195
1276
|
CREATE INDEX IF NOT EXISTS idx_compaction_checkpoints_project_recent ON compaction_checkpoints(project_id, status, completed_at DESC, pre_captured_at DESC);
|
|
1196
1277
|
CREATE INDEX IF NOT EXISTS idx_compaction_checkpoints_session_pending ON compaction_checkpoints(project_id, session_id, agent, phase, status, pre_captured_at DESC);
|
|
1197
1278
|
CREATE INDEX IF NOT EXISTS idx_compaction_checkpoints_source ON compaction_checkpoints(project_id, source_key);
|
|
1279
|
+
CREATE INDEX IF NOT EXISTS idx_evidence_cards_project ON evidence_cards(project_id, status, updated_at DESC);
|
|
1280
|
+
CREATE INDEX IF NOT EXISTS idx_evidence_cards_candidate ON evidence_cards(project_id, candidate_kind, candidate_id);
|
|
1281
|
+
CREATE INDEX IF NOT EXISTS idx_evidence_card_events_card ON evidence_card_events(card_id, created_at);
|
|
1282
|
+
CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC);
|
|
1283
|
+
CREATE INDEX IF NOT EXISTS idx_memory_feedback_events_candidate ON memory_feedback_events(project_id, candidate_kind, candidate_id, observed_at DESC);
|
|
1284
|
+
CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC);
|
|
1198
1285
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
1199
1286
|
ON maintenance_jobs(project_id, kind, dedupe_key)
|
|
1200
1287
|
WHERE status IN ('pending', 'running', 'retry');
|
|
@@ -1350,6 +1437,22 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
|
1350
1437
|
}
|
|
1351
1438
|
db2.exec("CREATE INDEX IF NOT EXISTS idx_media_jobs_source_asset ON media_jobs(project_id, source_asset_id, status)");
|
|
1352
1439
|
}
|
|
1440
|
+
},
|
|
1441
|
+
{
|
|
1442
|
+
id: "1.8-context-control-plane",
|
|
1443
|
+
apply: (db2) => {
|
|
1444
|
+
db2.exec(CREATE_EVIDENCE_CARDS_TABLE);
|
|
1445
|
+
db2.exec(CREATE_EVIDENCE_CARD_EVENTS_TABLE);
|
|
1446
|
+
db2.exec(CREATE_MEMORY_FEEDBACK_STATES_TABLE);
|
|
1447
|
+
db2.exec(CREATE_MEMORY_FEEDBACK_EVENTS_TABLE);
|
|
1448
|
+
db2.exec(CREATE_MCP_BINDINGS_TABLE);
|
|
1449
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_evidence_cards_project ON evidence_cards(project_id, status, updated_at DESC)");
|
|
1450
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_evidence_cards_candidate ON evidence_cards(project_id, candidate_kind, candidate_id)");
|
|
1451
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_evidence_card_events_card ON evidence_card_events(card_id, created_at)");
|
|
1452
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC)");
|
|
1453
|
+
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)");
|
|
1454
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC)");
|
|
1455
|
+
}
|
|
1353
1456
|
}
|
|
1354
1457
|
];
|
|
1355
1458
|
_dbCache = /* @__PURE__ */ new Map();
|
|
@@ -2819,6 +2922,7 @@ function mergeTomlConfig(base, override) {
|
|
|
2819
2922
|
llm: { ...base.memory?.llm, ...override.memory?.llm }
|
|
2820
2923
|
},
|
|
2821
2924
|
embedding: { ...base.embedding, ...override.embedding },
|
|
2925
|
+
rerank: { ...base.rerank, ...override.rerank },
|
|
2822
2926
|
hooks: { ...base.hooks, ...override.hooks },
|
|
2823
2927
|
git: { ...base.git, ...override.git },
|
|
2824
2928
|
codegraph: { ...base.codegraph, ...override.codegraph },
|
|
@@ -2915,6 +3019,7 @@ __export(resolved_config_exports, {
|
|
|
2915
3019
|
getResolvedConfigForCwd: () => getResolvedConfigForCwd,
|
|
2916
3020
|
getResolvedEmbeddingLane: () => getResolvedEmbeddingLane,
|
|
2917
3021
|
getResolvedMemoryLane: () => getResolvedMemoryLane,
|
|
3022
|
+
getResolvedRerankLane: () => getResolvedRerankLane,
|
|
2918
3023
|
resetResolvedConfigCache: () => resetResolvedConfigCache
|
|
2919
3024
|
});
|
|
2920
3025
|
import { homedir as homedir5 } from "os";
|
|
@@ -2947,6 +3052,16 @@ function getResolvedConfig(options = {}) {
|
|
|
2947
3052
|
legacy.llm?.baseUrl
|
|
2948
3053
|
);
|
|
2949
3054
|
const openRouterMemoryLlmApiKey = isOpenRouterMemoryLane(memoryLlmProvider, memoryLlmBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
|
|
3055
|
+
const memoryLlmApiKey = first(
|
|
3056
|
+
process.env.MEMORIX_LLM_API_KEY,
|
|
3057
|
+
process.env.MEMORIX_API_KEY,
|
|
3058
|
+
toml.memory?.llm?.api_key,
|
|
3059
|
+
yaml.llm?.apiKey,
|
|
3060
|
+
legacy.llm?.apiKey,
|
|
3061
|
+
process.env.OPENAI_API_KEY,
|
|
3062
|
+
process.env.ANTHROPIC_API_KEY,
|
|
3063
|
+
openRouterMemoryLlmApiKey
|
|
3064
|
+
);
|
|
2950
3065
|
const resolved = {
|
|
2951
3066
|
agent: {
|
|
2952
3067
|
provider: first(
|
|
@@ -2987,16 +3102,7 @@ function getResolvedConfig(options = {}) {
|
|
|
2987
3102
|
provider: memoryLlmProvider,
|
|
2988
3103
|
model: memoryLlmModel,
|
|
2989
3104
|
baseUrl: memoryLlmBaseUrl,
|
|
2990
|
-
apiKey:
|
|
2991
|
-
process.env.MEMORIX_LLM_API_KEY,
|
|
2992
|
-
process.env.MEMORIX_API_KEY,
|
|
2993
|
-
toml.memory?.llm?.api_key,
|
|
2994
|
-
yaml.llm?.apiKey,
|
|
2995
|
-
legacy.llm?.apiKey,
|
|
2996
|
-
process.env.OPENAI_API_KEY,
|
|
2997
|
-
process.env.ANTHROPIC_API_KEY,
|
|
2998
|
-
openRouterMemoryLlmApiKey
|
|
2999
|
-
)
|
|
3105
|
+
apiKey: memoryLlmApiKey
|
|
3000
3106
|
}
|
|
3001
3107
|
},
|
|
3002
3108
|
embedding: {
|
|
@@ -3006,6 +3112,12 @@ function getResolvedConfig(options = {}) {
|
|
|
3006
3112
|
apiKey: first(process.env.MEMORIX_EMBEDDING_API_KEY, toml.embedding?.api_key, yaml.embedding?.apiKey, legacy.embeddingApi?.apiKey, openRouterEmbeddingApiKey),
|
|
3007
3113
|
dimensions: firstNumber(parseNumber(process.env.MEMORIX_EMBEDDING_DIMENSIONS), toml.embedding?.dimensions, yaml.embedding?.dimensions, legacy.embeddingApi?.dimensions)
|
|
3008
3114
|
},
|
|
3115
|
+
rerank: resolveRerankLane({
|
|
3116
|
+
toml,
|
|
3117
|
+
yaml,
|
|
3118
|
+
memoryLlmApiKey,
|
|
3119
|
+
memoryLlmBaseUrl
|
|
3120
|
+
}),
|
|
3009
3121
|
git: {
|
|
3010
3122
|
autoHook: firstBool(toml.git?.auto_hook, yaml.git?.autoHook),
|
|
3011
3123
|
ingestOnCommit: firstBool(toml.git?.ingest_on_commit, yaml.git?.ingestOnCommit),
|
|
@@ -3075,6 +3187,9 @@ function getResolvedMemoryLane(options = {}) {
|
|
|
3075
3187
|
function getResolvedEmbeddingLane(options = {}) {
|
|
3076
3188
|
return getResolvedConfig(options).embedding;
|
|
3077
3189
|
}
|
|
3190
|
+
function getResolvedRerankLane(options = {}) {
|
|
3191
|
+
return getResolvedConfig(options).rerank;
|
|
3192
|
+
}
|
|
3078
3193
|
function resetResolvedConfigCache() {
|
|
3079
3194
|
}
|
|
3080
3195
|
function first(...values) {
|
|
@@ -3117,6 +3232,10 @@ function getEnvSourceNames() {
|
|
|
3117
3232
|
"MEMORIX_EMBEDDING_BASE_URL",
|
|
3118
3233
|
"MEMORIX_EMBEDDING_MODEL",
|
|
3119
3234
|
"MEMORIX_EMBEDDING_DIMENSIONS",
|
|
3235
|
+
"MEMORIX_RERANK_PROVIDER",
|
|
3236
|
+
"MEMORIX_RERANK_MODEL",
|
|
3237
|
+
"MEMORIX_RERANK_BASE_URL",
|
|
3238
|
+
"MEMORIX_RERANK_API_KEY",
|
|
3120
3239
|
"MEMORIX_CODEGRAPH_EXTERNAL_CONTEXT",
|
|
3121
3240
|
"MEMORIX_CODEGRAPH_EXTERNAL_COMMAND",
|
|
3122
3241
|
"MEMORIX_CODEGRAPH_EXTERNAL_TIMEOUT_MS",
|
|
@@ -3140,6 +3259,63 @@ function normalizeExternalContext(value) {
|
|
|
3140
3259
|
if (normalized === "auto" || normalized === "off") return normalized;
|
|
3141
3260
|
return void 0;
|
|
3142
3261
|
}
|
|
3262
|
+
function normalizeRerankProvider(value) {
|
|
3263
|
+
const normalized = value?.trim().toLowerCase();
|
|
3264
|
+
if (normalized === "http") return "http";
|
|
3265
|
+
return "off";
|
|
3266
|
+
}
|
|
3267
|
+
function resolveRerankLane(args) {
|
|
3268
|
+
const provider2 = normalizeRerankProvider(first(
|
|
3269
|
+
process.env.MEMORIX_RERANK_PROVIDER,
|
|
3270
|
+
args.toml.rerank?.provider,
|
|
3271
|
+
args.yaml.rerank?.provider,
|
|
3272
|
+
"off"
|
|
3273
|
+
));
|
|
3274
|
+
const model = first(
|
|
3275
|
+
process.env.MEMORIX_RERANK_MODEL,
|
|
3276
|
+
args.toml.rerank?.model,
|
|
3277
|
+
args.yaml.rerank?.model
|
|
3278
|
+
);
|
|
3279
|
+
const explicitBaseUrl = first(
|
|
3280
|
+
process.env.MEMORIX_RERANK_BASE_URL,
|
|
3281
|
+
args.toml.rerank?.base_url,
|
|
3282
|
+
args.yaml.rerank?.baseUrl
|
|
3283
|
+
);
|
|
3284
|
+
const baseUrl = provider2 === "http" ? first(explicitBaseUrl, args.memoryLlmBaseUrl) : explicitBaseUrl;
|
|
3285
|
+
const dedicatedApiKey = first(
|
|
3286
|
+
process.env.MEMORIX_RERANK_API_KEY,
|
|
3287
|
+
args.toml.rerank?.api_key,
|
|
3288
|
+
args.yaml.rerank?.apiKey
|
|
3289
|
+
);
|
|
3290
|
+
const sameEndpoint = provider2 === "http" && sameTrustedEndpoint(baseUrl, args.memoryLlmBaseUrl);
|
|
3291
|
+
const inheritedApiKey = sameEndpoint ? args.memoryLlmApiKey : void 0;
|
|
3292
|
+
const apiKey = first(dedicatedApiKey, inheritedApiKey);
|
|
3293
|
+
const canSendRequest = provider2 === "http" && Boolean(baseUrl) && (Boolean(apiKey) || !args.memoryLlmApiKey || sameEndpoint);
|
|
3294
|
+
return { provider: provider2, model, baseUrl, apiKey, canSendRequest };
|
|
3295
|
+
}
|
|
3296
|
+
function sameTrustedEndpoint(left, right) {
|
|
3297
|
+
const a = normalizeTrustedEndpoint(left);
|
|
3298
|
+
const b = normalizeTrustedEndpoint(right);
|
|
3299
|
+
return Boolean(a && b && a === b);
|
|
3300
|
+
}
|
|
3301
|
+
function normalizeTrustedEndpoint(value) {
|
|
3302
|
+
const trimmed = value?.trim();
|
|
3303
|
+
if (!trimmed) return void 0;
|
|
3304
|
+
try {
|
|
3305
|
+
const url = new URL(trimmed);
|
|
3306
|
+
const protocol = url.protocol.toLowerCase();
|
|
3307
|
+
const hostname = url.hostname.toLowerCase();
|
|
3308
|
+
const port = url.port;
|
|
3309
|
+
let pathname = url.pathname.replace(/\/+$/, "");
|
|
3310
|
+
if (pathname.toLowerCase().endsWith("/rerank")) {
|
|
3311
|
+
pathname = pathname.slice(0, -"/rerank".length).replace(/\/+$/, "");
|
|
3312
|
+
}
|
|
3313
|
+
return `${protocol}//${hostname}${port ? `:${port}` : ""}${pathname}`;
|
|
3314
|
+
} catch {
|
|
3315
|
+
const fallback = trimmed.replace(/\/+$/, "").replace(/\/rerank$/i, "").replace(/\/+$/, "");
|
|
3316
|
+
return fallback.toLowerCase() || void 0;
|
|
3317
|
+
}
|
|
3318
|
+
}
|
|
3143
3319
|
var init_resolved_config = __esm({
|
|
3144
3320
|
"src/config/resolved-config.ts"() {
|
|
3145
3321
|
"use strict";
|
|
@@ -5375,9 +5551,27 @@ __export(provider_exports2, {
|
|
|
5375
5551
|
getLLMConfig: () => getLLMConfig,
|
|
5376
5552
|
initLLM: () => initLLM,
|
|
5377
5553
|
isLLMEnabled: () => isLLMEnabled,
|
|
5554
|
+
normalizeOpenAICompatibleBaseUrl: () => normalizeOpenAICompatibleBaseUrl,
|
|
5378
5555
|
parseLLMTimeoutMs: () => parseLLMTimeoutMs,
|
|
5379
5556
|
setLLMConfig: () => setLLMConfig
|
|
5380
5557
|
});
|
|
5558
|
+
function normalizeOpenAICompatibleBaseUrl(baseUrl) {
|
|
5559
|
+
const base = baseUrl.trim().replace(/\/+$/, "");
|
|
5560
|
+
if (!base) return base;
|
|
5561
|
+
let pathname = "";
|
|
5562
|
+
try {
|
|
5563
|
+
pathname = new URL(base).pathname.replace(/\/+$/, "");
|
|
5564
|
+
} catch {
|
|
5565
|
+
pathname = base.split(/[?#]/, 1)[0].replace(/\/+$/, "");
|
|
5566
|
+
}
|
|
5567
|
+
const lastSegment = pathname.split("/").filter(Boolean).at(-1);
|
|
5568
|
+
if (lastSegment && OPENAI_API_VERSION_SEGMENT.test(lastSegment)) {
|
|
5569
|
+
return base;
|
|
5570
|
+
}
|
|
5571
|
+
const queryOrHash = base.match(/[?#].*$/)?.[0] ?? "";
|
|
5572
|
+
const pathWithoutQuery = base.slice(0, base.length - queryOrHash.length).replace(/\/+$/, "");
|
|
5573
|
+
return `${pathWithoutQuery}/v1${queryOrHash}`;
|
|
5574
|
+
}
|
|
5381
5575
|
function parseLLMTimeoutMs(raw) {
|
|
5382
5576
|
if (raw === void 0 || raw.trim() === "") return LLM_TIMEOUT_DEFAULT_MS;
|
|
5383
5577
|
const parsed = Number(raw);
|
|
@@ -5481,8 +5675,7 @@ async function callLLM(systemPrompt, userMessage, signal) {
|
|
|
5481
5675
|
}
|
|
5482
5676
|
async function callOpenAICompatible(systemPrompt, userMessage, signal) {
|
|
5483
5677
|
const config = currentConfig;
|
|
5484
|
-
|
|
5485
|
-
if (!base.endsWith("/v1")) base += "/v1";
|
|
5678
|
+
const base = normalizeOpenAICompatibleBaseUrl(config.baseUrl);
|
|
5486
5679
|
const url = `${base}/chat/completions`;
|
|
5487
5680
|
const fetchSignal = signal ? AbortSignal.any([signal, AbortSignal.timeout(LLM_CALL_TIMEOUT_MS)]) : AbortSignal.timeout(LLM_CALL_TIMEOUT_MS);
|
|
5488
5681
|
const response = await fetch(url, {
|
|
@@ -5561,8 +5754,7 @@ async function callLLMWithTools(messages, tools, signal) {
|
|
|
5561
5754
|
}
|
|
5562
5755
|
async function callOpenAIWithTools(messages, tools, signal) {
|
|
5563
5756
|
const config = currentConfig;
|
|
5564
|
-
|
|
5565
|
-
if (!base.endsWith("/v1")) base += "/v1";
|
|
5757
|
+
const base = normalizeOpenAICompatibleBaseUrl(config.baseUrl);
|
|
5566
5758
|
const url = `${base}/chat/completions`;
|
|
5567
5759
|
const openaiMessages = messages.map((msg) => {
|
|
5568
5760
|
if (msg.role === "tool") {
|
|
@@ -5712,8 +5904,7 @@ async function callAnthropicWithTools(messages, tools, signal) {
|
|
|
5712
5904
|
}
|
|
5713
5905
|
async function* callOpenAIWithToolsStream(messages, tools) {
|
|
5714
5906
|
const config = currentConfig;
|
|
5715
|
-
|
|
5716
|
-
if (!base.endsWith("/v1")) base += "/v1";
|
|
5907
|
+
const base = normalizeOpenAICompatibleBaseUrl(config.baseUrl);
|
|
5717
5908
|
const url = `${base}/chat/completions`;
|
|
5718
5909
|
const openaiMessages = messages.map((msg) => {
|
|
5719
5910
|
if (msg.role === "tool") {
|
|
@@ -5961,7 +6152,7 @@ async function* callAnthropicWithToolsStream(messages, tools) {
|
|
|
5961
6152
|
}
|
|
5962
6153
|
};
|
|
5963
6154
|
}
|
|
5964
|
-
var LLM_TIMEOUT_DEFAULT_MS, LLM_TIMEOUT_MIN_MS, LLM_TIMEOUT_MAX_MS, MAX_LLM_RESPONSE_BYTES, LLM_CALL_TIMEOUT_MS, PROVIDER_DEFAULTS, currentConfig;
|
|
6155
|
+
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;
|
|
5965
6156
|
var init_provider2 = __esm({
|
|
5966
6157
|
"src/llm/provider.ts"() {
|
|
5967
6158
|
"use strict";
|
|
@@ -5971,6 +6162,7 @@ var init_provider2 = __esm({
|
|
|
5971
6162
|
LLM_TIMEOUT_MIN_MS = 1e3;
|
|
5972
6163
|
LLM_TIMEOUT_MAX_MS = 3e5;
|
|
5973
6164
|
MAX_LLM_RESPONSE_BYTES = 2 * 1024 * 1024;
|
|
6165
|
+
OPENAI_API_VERSION_SEGMENT = /^v\d+(?:[a-z][a-z0-9-]*)?$/i;
|
|
5974
6166
|
LLM_CALL_TIMEOUT_MS = parseLLMTimeoutMs(process.env.MEMORIX_LLM_TIMEOUT_MS);
|
|
5975
6167
|
PROVIDER_DEFAULTS = {
|
|
5976
6168
|
openai: { baseUrl: "https://api.openai.com/v1", model: "gpt-4.1-nano" },
|
|
@@ -6030,6 +6222,48 @@ Rules:
|
|
|
6030
6222
|
}
|
|
6031
6223
|
});
|
|
6032
6224
|
|
|
6225
|
+
// src/rerank/policy.ts
|
|
6226
|
+
function parseRerankTimeoutMs(raw) {
|
|
6227
|
+
const value = raw?.trim();
|
|
6228
|
+
if (!value) return DEFAULT_RERANK_TIMEOUT_MS;
|
|
6229
|
+
const parsed = Number(value);
|
|
6230
|
+
if (!Number.isInteger(parsed) || Number.isNaN(parsed)) {
|
|
6231
|
+
console.warn(
|
|
6232
|
+
`[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.`
|
|
6233
|
+
);
|
|
6234
|
+
return DEFAULT_RERANK_TIMEOUT_MS;
|
|
6235
|
+
}
|
|
6236
|
+
if (parsed < RERANK_TIMEOUT_MIN_MS) return RERANK_TIMEOUT_MIN_MS;
|
|
6237
|
+
if (parsed > RERANK_TIMEOUT_MAX_MS) return RERANK_TIMEOUT_MAX_MS;
|
|
6238
|
+
return parsed;
|
|
6239
|
+
}
|
|
6240
|
+
function resolveRerankTimeoutMs(explicitTimeoutMs) {
|
|
6241
|
+
if (typeof explicitTimeoutMs === "number" && Number.isFinite(explicitTimeoutMs) && explicitTimeoutMs > 0) {
|
|
6242
|
+
return explicitTimeoutMs;
|
|
6243
|
+
}
|
|
6244
|
+
return parseRerankTimeoutMs(process.env.MEMORIX_RERANK_TIMEOUT_MS);
|
|
6245
|
+
}
|
|
6246
|
+
function shouldAttemptHttpRerank(input) {
|
|
6247
|
+
return input.quality === "thorough" && input.hasQuery && input.candidateCount >= MIN_RERANK_CANDIDATES;
|
|
6248
|
+
}
|
|
6249
|
+
function shouldAttemptLlmRerank(input) {
|
|
6250
|
+
if (input.httpRerankConfigured) return false;
|
|
6251
|
+
if (input.quality !== "thorough" || input.tier !== "heavy" || !input.hasQuery) return false;
|
|
6252
|
+
if (input.candidateCount < MIN_RERANK_CANDIDATES) return false;
|
|
6253
|
+
return input.topScore > 0 && input.secondScore / input.topScore > 0.7;
|
|
6254
|
+
}
|
|
6255
|
+
var DEFAULT_RERANK_TIMEOUT_MS, RERANK_TIMEOUT_MIN_MS, RERANK_TIMEOUT_MAX_MS, MIN_RERANK_CANDIDATES;
|
|
6256
|
+
var init_policy = __esm({
|
|
6257
|
+
"src/rerank/policy.ts"() {
|
|
6258
|
+
"use strict";
|
|
6259
|
+
init_esm_shims();
|
|
6260
|
+
DEFAULT_RERANK_TIMEOUT_MS = 3e4;
|
|
6261
|
+
RERANK_TIMEOUT_MIN_MS = 1e3;
|
|
6262
|
+
RERANK_TIMEOUT_MAX_MS = 3e5;
|
|
6263
|
+
MIN_RERANK_CANDIDATES = 3;
|
|
6264
|
+
}
|
|
6265
|
+
});
|
|
6266
|
+
|
|
6033
6267
|
// src/timeout.ts
|
|
6034
6268
|
function withTimeout(promise, ms, label) {
|
|
6035
6269
|
return new Promise((resolve, reject) => {
|
|
@@ -6315,6 +6549,148 @@ var init_aliases = __esm({
|
|
|
6315
6549
|
}
|
|
6316
6550
|
});
|
|
6317
6551
|
|
|
6552
|
+
// src/rerank/http-provider.ts
|
|
6553
|
+
function buildRerankUrl(baseUrl) {
|
|
6554
|
+
const trimmed = baseUrl.trim().replace(/\/+$/, "");
|
|
6555
|
+
if (trimmed.endsWith("/rerank")) return trimmed;
|
|
6556
|
+
return `${trimmed}/rerank`;
|
|
6557
|
+
}
|
|
6558
|
+
function parseRerankResponse(payload) {
|
|
6559
|
+
const rows = extractRows(payload);
|
|
6560
|
+
if (rows.length === 0) {
|
|
6561
|
+
throw new Error("Neural rerank response contained no ranked results");
|
|
6562
|
+
}
|
|
6563
|
+
return rows.sort((a, b) => b.score - a.score);
|
|
6564
|
+
}
|
|
6565
|
+
function extractRows(payload) {
|
|
6566
|
+
if (Array.isArray(payload)) {
|
|
6567
|
+
return payload.map(rowFromUnknown).filter((row) => row !== null);
|
|
6568
|
+
}
|
|
6569
|
+
if (payload && typeof payload === "object" && "results" in payload) {
|
|
6570
|
+
const results = payload.results;
|
|
6571
|
+
if (Array.isArray(results)) {
|
|
6572
|
+
return results.map(rowFromUnknown).filter((row) => row !== null);
|
|
6573
|
+
}
|
|
6574
|
+
}
|
|
6575
|
+
throw new Error("Neural rerank response was not Cohere or TEI shaped");
|
|
6576
|
+
}
|
|
6577
|
+
function rowFromUnknown(value) {
|
|
6578
|
+
if (!value || typeof value !== "object") return null;
|
|
6579
|
+
const row = value;
|
|
6580
|
+
if (typeof row.index !== "number" || !Number.isFinite(row.index)) return null;
|
|
6581
|
+
const score = typeof row.relevance_score === "number" ? row.relevance_score : typeof row.score === "number" ? row.score : null;
|
|
6582
|
+
if (score === null || !Number.isFinite(score)) return null;
|
|
6583
|
+
return { index: row.index, score };
|
|
6584
|
+
}
|
|
6585
|
+
function buildRerankBody(query, documents, model) {
|
|
6586
|
+
const body = {
|
|
6587
|
+
query,
|
|
6588
|
+
documents,
|
|
6589
|
+
top_n: documents.length,
|
|
6590
|
+
return_documents: false
|
|
6591
|
+
};
|
|
6592
|
+
const trimmed = model?.trim();
|
|
6593
|
+
if (trimmed) body.model = trimmed;
|
|
6594
|
+
return body;
|
|
6595
|
+
}
|
|
6596
|
+
async function rerankViaHttp(query, documents, config) {
|
|
6597
|
+
if (documents.length === 0) return [];
|
|
6598
|
+
const url = buildRerankUrl(config.baseUrl);
|
|
6599
|
+
const headers = {
|
|
6600
|
+
"content-type": "application/json"
|
|
6601
|
+
};
|
|
6602
|
+
if (config.apiKey) {
|
|
6603
|
+
headers.authorization = `Bearer ${config.apiKey}`;
|
|
6604
|
+
}
|
|
6605
|
+
const controller = new AbortController();
|
|
6606
|
+
const timeoutMs = resolveRerankTimeoutMs(config.timeoutMs);
|
|
6607
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
6608
|
+
try {
|
|
6609
|
+
const fetchImpl = config.fetchImpl ?? fetch;
|
|
6610
|
+
const response = await fetchImpl(url, {
|
|
6611
|
+
method: "POST",
|
|
6612
|
+
headers,
|
|
6613
|
+
signal: controller.signal,
|
|
6614
|
+
body: JSON.stringify(buildRerankBody(query, documents, config.model))
|
|
6615
|
+
});
|
|
6616
|
+
if (!response.ok) {
|
|
6617
|
+
throw new Error(`Neural rerank HTTP ${response.status} from ${url}`);
|
|
6618
|
+
}
|
|
6619
|
+
return parseRerankResponse(await response.json());
|
|
6620
|
+
} finally {
|
|
6621
|
+
clearTimeout(timer);
|
|
6622
|
+
}
|
|
6623
|
+
}
|
|
6624
|
+
var init_http_provider = __esm({
|
|
6625
|
+
"src/rerank/http-provider.ts"() {
|
|
6626
|
+
"use strict";
|
|
6627
|
+
init_esm_shims();
|
|
6628
|
+
init_policy();
|
|
6629
|
+
}
|
|
6630
|
+
});
|
|
6631
|
+
|
|
6632
|
+
// src/rerank/index.ts
|
|
6633
|
+
var rerank_exports = {};
|
|
6634
|
+
__export(rerank_exports, {
|
|
6635
|
+
DEFAULT_RERANK_TIMEOUT_MS: () => DEFAULT_RERANK_TIMEOUT_MS,
|
|
6636
|
+
MIN_RERANK_CANDIDATES: () => MIN_RERANK_CANDIDATES,
|
|
6637
|
+
isNeuralRerankEnabled: () => isNeuralRerankEnabled,
|
|
6638
|
+
neuralRerankCandidates: () => neuralRerankCandidates,
|
|
6639
|
+
parseRerankTimeoutMs: () => parseRerankTimeoutMs,
|
|
6640
|
+
resolveRerankTimeoutMs: () => resolveRerankTimeoutMs,
|
|
6641
|
+
shouldAttemptHttpRerank: () => shouldAttemptHttpRerank,
|
|
6642
|
+
shouldAttemptLlmRerank: () => shouldAttemptLlmRerank
|
|
6643
|
+
});
|
|
6644
|
+
function isNeuralRerankEnabled(options = {}) {
|
|
6645
|
+
const lane = getResolvedRerankLane(options);
|
|
6646
|
+
return lane.provider === "http" && Boolean(lane.baseUrl);
|
|
6647
|
+
}
|
|
6648
|
+
async function neuralRerankCandidates(query, candidates, options = {}) {
|
|
6649
|
+
if (!isNeuralRerankEnabled(options) || candidates.length === 0) return null;
|
|
6650
|
+
const lane = getResolvedRerankLane(options);
|
|
6651
|
+
if (!lane.canSendRequest || !lane.baseUrl) return null;
|
|
6652
|
+
const toRerank = candidates.slice(0, MAX_RERANK);
|
|
6653
|
+
const rest = candidates.slice(MAX_RERANK);
|
|
6654
|
+
const documents = toRerank.map((candidate) => candidateText(candidate));
|
|
6655
|
+
const ranked = await rerankViaHttp(query, documents, {
|
|
6656
|
+
provider: "http",
|
|
6657
|
+
model: lane.model,
|
|
6658
|
+
baseUrl: lane.baseUrl,
|
|
6659
|
+
apiKey: lane.apiKey,
|
|
6660
|
+
timeoutMs: resolveRerankTimeoutMs()
|
|
6661
|
+
});
|
|
6662
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6663
|
+
const reranked = [];
|
|
6664
|
+
for (const row of ranked) {
|
|
6665
|
+
const candidate = toRerank[row.index];
|
|
6666
|
+
if (!candidate || seen.has(row.index)) continue;
|
|
6667
|
+
reranked.push(candidate);
|
|
6668
|
+
seen.add(row.index);
|
|
6669
|
+
}
|
|
6670
|
+
for (const [index, candidate] of toRerank.entries()) {
|
|
6671
|
+
if (!seen.has(index)) reranked.push(candidate);
|
|
6672
|
+
}
|
|
6673
|
+
reranked.push(...rest);
|
|
6674
|
+
return reranked;
|
|
6675
|
+
}
|
|
6676
|
+
function candidateText(candidate) {
|
|
6677
|
+
const narrative = candidate.narrative?.trim();
|
|
6678
|
+
if (narrative) return `${candidate.title} \u2014 ${narrative.slice(0, 200)}`;
|
|
6679
|
+
return candidate.title;
|
|
6680
|
+
}
|
|
6681
|
+
var MAX_RERANK;
|
|
6682
|
+
var init_rerank = __esm({
|
|
6683
|
+
"src/rerank/index.ts"() {
|
|
6684
|
+
"use strict";
|
|
6685
|
+
init_esm_shims();
|
|
6686
|
+
init_resolved_config();
|
|
6687
|
+
init_http_provider();
|
|
6688
|
+
init_policy();
|
|
6689
|
+
init_policy();
|
|
6690
|
+
MAX_RERANK = 10;
|
|
6691
|
+
}
|
|
6692
|
+
});
|
|
6693
|
+
|
|
6318
6694
|
// src/llm/quality.ts
|
|
6319
6695
|
var quality_exports = {};
|
|
6320
6696
|
__export(quality_exports, {
|
|
@@ -6354,9 +6730,9 @@ async function rerankResults(query, candidates) {
|
|
|
6354
6730
|
if (!isLLMEnabled() || candidates.length <= 2) {
|
|
6355
6731
|
return { reranked: candidates, usedLLM: false };
|
|
6356
6732
|
}
|
|
6357
|
-
const
|
|
6358
|
-
const toRerank = candidates.slice(0,
|
|
6359
|
-
const rest = candidates.slice(
|
|
6733
|
+
const MAX_RERANK2 = 10;
|
|
6734
|
+
const toRerank = candidates.slice(0, MAX_RERANK2);
|
|
6735
|
+
const rest = candidates.slice(MAX_RERANK2);
|
|
6360
6736
|
try {
|
|
6361
6737
|
const candidateList = toRerank.map(
|
|
6362
6738
|
(c) => `[ID: ${c.id}] (${c.type}) ${c.title}${c.narrative ? ` \u2014 ${c.narrative.substring(0, 100)}` : ""}`
|
|
@@ -7249,46 +7625,78 @@ async function searchObservations(options) {
|
|
|
7249
7625
|
}
|
|
7250
7626
|
}
|
|
7251
7627
|
}
|
|
7252
|
-
const
|
|
7253
|
-
|
|
7254
|
-
|
|
7255
|
-
|
|
7256
|
-
})
|
|
7257
|
-
|
|
7258
|
-
|
|
7259
|
-
|
|
7260
|
-
|
|
7261
|
-
|
|
7262
|
-
|
|
7263
|
-
|
|
7264
|
-
|
|
7265
|
-
|
|
7266
|
-
|
|
7267
|
-
|
|
7268
|
-
|
|
7269
|
-
|
|
7270
|
-
|
|
7271
|
-
|
|
7272
|
-
|
|
7273
|
-
|
|
7274
|
-
|
|
7275
|
-
|
|
7276
|
-
|
|
7277
|
-
|
|
7278
|
-
|
|
7279
|
-
|
|
7280
|
-
|
|
7281
|
-
|
|
7282
|
-
|
|
7283
|
-
|
|
7284
|
-
|
|
7285
|
-
|
|
7286
|
-
|
|
7287
|
-
|
|
7628
|
+
const httpGate = shouldAttemptHttpRerank({
|
|
7629
|
+
quality,
|
|
7630
|
+
hasQuery: Boolean(hasQuery),
|
|
7631
|
+
candidateCount: intermediate.length
|
|
7632
|
+
});
|
|
7633
|
+
const llmGateWithoutHttp = shouldAttemptLlmRerank({
|
|
7634
|
+
quality,
|
|
7635
|
+
tier,
|
|
7636
|
+
hasQuery: Boolean(hasQuery),
|
|
7637
|
+
candidateCount: intermediate.length,
|
|
7638
|
+
topScore: intermediate[0]?.score ?? 0,
|
|
7639
|
+
secondScore: intermediate[1]?.score ?? 0,
|
|
7640
|
+
httpRerankConfigured: false
|
|
7641
|
+
});
|
|
7642
|
+
if (httpGate || llmGateWithoutHttp) {
|
|
7643
|
+
const narrativeMap = /* @__PURE__ */ new Map();
|
|
7644
|
+
for (const hit of results.hits) {
|
|
7645
|
+
const doc = hit.document;
|
|
7646
|
+
narrativeMap.set(makeEntryKey(doc.projectId, doc.observationId), doc.narrative);
|
|
7647
|
+
}
|
|
7648
|
+
const RERANK_TOP_K = 5;
|
|
7649
|
+
const toRerank = intermediate.slice(0, RERANK_TOP_K);
|
|
7650
|
+
const candidates = toRerank.map((e2, index) => ({
|
|
7651
|
+
id: `r${index + 1}`,
|
|
7652
|
+
title: e2.title,
|
|
7653
|
+
type: e2.type,
|
|
7654
|
+
score: e2.score,
|
|
7655
|
+
narrative: narrativeMap.get(makeEntryKey(e2.projectId, e2.id))
|
|
7656
|
+
}));
|
|
7657
|
+
const RERANK_TIMEOUT_MS = parseRerankTimeoutMs(process.env.MEMORIX_RERANK_TIMEOUT_MS);
|
|
7658
|
+
const candidateMap = new Map(candidates.map((candidate, index) => [candidate.id, toRerank[index]]));
|
|
7659
|
+
const { isNeuralRerankEnabled: isNeuralRerankEnabled2, neuralRerankCandidates: neuralRerankCandidates2 } = await Promise.resolve().then(() => (init_rerank(), rerank_exports));
|
|
7660
|
+
const httpConfigured = isNeuralRerankEnabled2();
|
|
7661
|
+
if (httpConfigured && httpGate) {
|
|
7662
|
+
try {
|
|
7663
|
+
const neural = await withTimeout(
|
|
7664
|
+
neuralRerankCandidates2(originalQuery, candidates),
|
|
7665
|
+
RERANK_TIMEOUT_MS,
|
|
7666
|
+
"neural rerank"
|
|
7667
|
+
);
|
|
7668
|
+
if (neural && neural.length > 0) {
|
|
7669
|
+
const rerankedTop = neural.map((row) => candidateMap.get(row.id)).filter((entry) => entry != null);
|
|
7670
|
+
if (rerankedTop.length > 0) {
|
|
7671
|
+
intermediate = [...rerankedTop, ...intermediate.slice(RERANK_TOP_K)];
|
|
7672
|
+
lastSearchModeByProject.set(modeKey, (lastSearchModeByProject.get(modeKey) ?? "fulltext") + " + neural rerank");
|
|
7673
|
+
mark("rerank(usedNeural=true)");
|
|
7674
|
+
}
|
|
7288
7675
|
}
|
|
7676
|
+
} catch {
|
|
7677
|
+
console.error("[memorix] neural rerank failed or timed out; keeping original order");
|
|
7289
7678
|
}
|
|
7290
|
-
}
|
|
7291
|
-
|
|
7679
|
+
} else if (!httpConfigured && llmGateWithoutHttp) {
|
|
7680
|
+
try {
|
|
7681
|
+
const { rerankResults: rerankResults2 } = await Promise.resolve().then(() => (init_quality(), quality_exports));
|
|
7682
|
+
const { reranked, usedLLM } = await withTimeout(
|
|
7683
|
+
rerankResults2(originalQuery, candidates),
|
|
7684
|
+
RERANK_TIMEOUT_MS,
|
|
7685
|
+
"LLM rerank"
|
|
7686
|
+
);
|
|
7687
|
+
mark(`rerank(usedLLM=${usedLLM})`);
|
|
7688
|
+
if (usedLLM) {
|
|
7689
|
+
lastSearchModeByProject.set(modeKey, (lastSearchModeByProject.get(modeKey) ?? "fulltext") + " + LLM rerank");
|
|
7690
|
+
const rerankedTop = reranked.map((row) => candidateMap.get(row.id)).filter((entry) => entry != null);
|
|
7691
|
+
if (rerankedTop.length > 0) {
|
|
7692
|
+
intermediate = [...rerankedTop, ...intermediate.slice(RERANK_TOP_K)];
|
|
7693
|
+
}
|
|
7694
|
+
}
|
|
7695
|
+
} catch {
|
|
7696
|
+
console.error("[memorix] LLM rerank failed or timed out, using original order");
|
|
7697
|
+
}
|
|
7698
|
+
} else {
|
|
7699
|
+
mark(`rerank(skipped,tier=${tier})`);
|
|
7292
7700
|
}
|
|
7293
7701
|
} else {
|
|
7294
7702
|
mark(`rerank(skipped,tier=${tier})`);
|
|
@@ -7469,6 +7877,7 @@ var init_orama_store = __esm({
|
|
|
7469
7877
|
init_project_affinity();
|
|
7470
7878
|
init_intent_detector();
|
|
7471
7879
|
init_query_expansion();
|
|
7880
|
+
init_policy();
|
|
7472
7881
|
init_timeout();
|
|
7473
7882
|
db = null;
|
|
7474
7883
|
dbInitPromise = null;
|
|
@@ -8156,8 +8565,228 @@ var init_lifecycle = __esm({
|
|
|
8156
8565
|
}
|
|
8157
8566
|
});
|
|
8158
8567
|
|
|
8568
|
+
// src/store/evidence-store.ts
|
|
8569
|
+
import { createHash as createHash3, randomUUID as randomUUID4 } from "crypto";
|
|
8570
|
+
function safeJson(value, fallback) {
|
|
8571
|
+
if (typeof value !== "string" || value.length === 0) return fallback;
|
|
8572
|
+
try {
|
|
8573
|
+
return JSON.parse(value);
|
|
8574
|
+
} catch {
|
|
8575
|
+
return fallback;
|
|
8576
|
+
}
|
|
8577
|
+
}
|
|
8578
|
+
function rowToCard(row) {
|
|
8579
|
+
return {
|
|
8580
|
+
id: String(row.id),
|
|
8581
|
+
projectId: String(row.project_id),
|
|
8582
|
+
candidateKind: row.candidate_kind,
|
|
8583
|
+
candidateId: String(row.candidate_id),
|
|
8584
|
+
title: String(row.title),
|
|
8585
|
+
summary: String(row.summary ?? ""),
|
|
8586
|
+
...row.entity_name ? { entityName: String(row.entity_name) } : {},
|
|
8587
|
+
sourceKind: String(row.source_kind),
|
|
8588
|
+
sourceRef: String(row.source_ref),
|
|
8589
|
+
...row.locator ? { locator: String(row.locator) } : {},
|
|
8590
|
+
...row.captured_hash ? { capturedHash: String(row.captured_hash) } : {},
|
|
8591
|
+
...row.session_id ? { sessionId: String(row.session_id) } : {},
|
|
8592
|
+
status: String(row.status ?? "active"),
|
|
8593
|
+
verification: row.verification,
|
|
8594
|
+
freshness: row.freshness,
|
|
8595
|
+
...row.stale_reason ? { staleReason: String(row.stale_reason) } : {},
|
|
8596
|
+
files: safeJson(row.files_json, []),
|
|
8597
|
+
relatedEntities: safeJson(row.related_entities_json, []),
|
|
8598
|
+
createdAt: String(row.created_at),
|
|
8599
|
+
updatedAt: String(row.updated_at)
|
|
8600
|
+
};
|
|
8601
|
+
}
|
|
8602
|
+
function observationHash(observation) {
|
|
8603
|
+
return createHash3("sha256").update(JSON.stringify({
|
|
8604
|
+
projectId: observation.projectId,
|
|
8605
|
+
id: observation.id,
|
|
8606
|
+
title: observation.title,
|
|
8607
|
+
narrative: observation.narrative,
|
|
8608
|
+
facts: observation.facts,
|
|
8609
|
+
files: observation.filesModified,
|
|
8610
|
+
relatedEntities: observation.relatedEntities
|
|
8611
|
+
})).digest("hex");
|
|
8612
|
+
}
|
|
8613
|
+
function sourceKind(observation) {
|
|
8614
|
+
if (observation.source === "git" || observation.sourceDetail === "git-ingest") return "git";
|
|
8615
|
+
if (observation.sourceDetail === "hook") return "hook";
|
|
8616
|
+
return observation.source ?? "agent";
|
|
8617
|
+
}
|
|
8618
|
+
var EvidenceCardStore;
|
|
8619
|
+
var init_evidence_store = __esm({
|
|
8620
|
+
"src/store/evidence-store.ts"() {
|
|
8621
|
+
"use strict";
|
|
8622
|
+
init_esm_shims();
|
|
8623
|
+
init_sqlite_db();
|
|
8624
|
+
EvidenceCardStore = class {
|
|
8625
|
+
db = null;
|
|
8626
|
+
async init(dataDir) {
|
|
8627
|
+
this.db = getDatabase(dataDir);
|
|
8628
|
+
}
|
|
8629
|
+
requireDb() {
|
|
8630
|
+
if (!this.db) throw new Error("EvidenceCardStore is not initialized.");
|
|
8631
|
+
return this.db;
|
|
8632
|
+
}
|
|
8633
|
+
upsertObservation(observation) {
|
|
8634
|
+
const db2 = this.requireDb();
|
|
8635
|
+
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
8636
|
+
const card = {
|
|
8637
|
+
id: `evidence:observation:${observation.projectId}:${observation.id}`,
|
|
8638
|
+
projectId: observation.projectId,
|
|
8639
|
+
candidateKind: "observation",
|
|
8640
|
+
candidateId: String(observation.id),
|
|
8641
|
+
title: observation.title,
|
|
8642
|
+
summary: observation.narrative.slice(0, 500),
|
|
8643
|
+
entityName: observation.entityName,
|
|
8644
|
+
sourceKind: sourceKind(observation),
|
|
8645
|
+
sourceRef: `observation:${observation.id}`,
|
|
8646
|
+
locator: observation.filesModified?.join(", ") || `observation:${observation.id}`,
|
|
8647
|
+
capturedHash: observationHash(observation),
|
|
8648
|
+
...observation.sessionId ? { sessionId: observation.sessionId } : {},
|
|
8649
|
+
status: observation.status ?? "active",
|
|
8650
|
+
verification: observation.status === "resolved" ? "verified" : "unverified",
|
|
8651
|
+
freshness: "current",
|
|
8652
|
+
files: observation.filesModified ?? [],
|
|
8653
|
+
relatedEntities: observation.relatedEntities ?? [],
|
|
8654
|
+
createdAt: observation.createdAt,
|
|
8655
|
+
updatedAt: now3
|
|
8656
|
+
};
|
|
8657
|
+
db2.prepare(`
|
|
8658
|
+
INSERT INTO evidence_cards (
|
|
8659
|
+
id, project_id, candidate_kind, candidate_id, title, summary, entity_name,
|
|
8660
|
+
source_kind, source_ref, locator, captured_hash, session_id, status,
|
|
8661
|
+
verification, freshness, stale_reason, files_json, related_entities_json,
|
|
8662
|
+
created_at, updated_at
|
|
8663
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?)
|
|
8664
|
+
ON CONFLICT(project_id, candidate_kind, candidate_id) DO UPDATE SET
|
|
8665
|
+
title = excluded.title,
|
|
8666
|
+
summary = excluded.summary,
|
|
8667
|
+
entity_name = excluded.entity_name,
|
|
8668
|
+
source_kind = excluded.source_kind,
|
|
8669
|
+
source_ref = excluded.source_ref,
|
|
8670
|
+
locator = excluded.locator,
|
|
8671
|
+
captured_hash = excluded.captured_hash,
|
|
8672
|
+
session_id = excluded.session_id,
|
|
8673
|
+
status = excluded.status,
|
|
8674
|
+
freshness = 'current',
|
|
8675
|
+
stale_reason = NULL,
|
|
8676
|
+
files_json = excluded.files_json,
|
|
8677
|
+
related_entities_json = excluded.related_entities_json,
|
|
8678
|
+
updated_at = excluded.updated_at
|
|
8679
|
+
`).run(
|
|
8680
|
+
card.id,
|
|
8681
|
+
card.projectId,
|
|
8682
|
+
card.candidateKind,
|
|
8683
|
+
card.candidateId,
|
|
8684
|
+
card.title,
|
|
8685
|
+
card.summary,
|
|
8686
|
+
card.entityName ?? null,
|
|
8687
|
+
card.sourceKind,
|
|
8688
|
+
card.sourceRef,
|
|
8689
|
+
card.locator ?? null,
|
|
8690
|
+
card.capturedHash ?? null,
|
|
8691
|
+
card.sessionId ?? null,
|
|
8692
|
+
card.status,
|
|
8693
|
+
card.verification,
|
|
8694
|
+
card.freshness,
|
|
8695
|
+
JSON.stringify(card.files),
|
|
8696
|
+
JSON.stringify(card.relatedEntities),
|
|
8697
|
+
card.createdAt,
|
|
8698
|
+
card.updatedAt
|
|
8699
|
+
);
|
|
8700
|
+
return this.get(card.projectId, card.candidateKind, card.candidateId) ?? card;
|
|
8701
|
+
}
|
|
8702
|
+
get(projectId, candidateKind, candidateId) {
|
|
8703
|
+
const row = this.requireDb().prepare(`
|
|
8704
|
+
SELECT * FROM evidence_cards WHERE project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
8705
|
+
`).get(projectId, candidateKind, candidateId);
|
|
8706
|
+
return row ? rowToCard(row) : void 0;
|
|
8707
|
+
}
|
|
8708
|
+
list(projectId, options = {}) {
|
|
8709
|
+
const limit2 = Math.min(100, Math.max(1, Math.floor(options.limit ?? 20)));
|
|
8710
|
+
const clauses = ["project_id = ?"];
|
|
8711
|
+
const args = [projectId];
|
|
8712
|
+
if (options.freshness) {
|
|
8713
|
+
clauses.push("freshness = ?");
|
|
8714
|
+
args.push(options.freshness);
|
|
8715
|
+
}
|
|
8716
|
+
if (options.status) {
|
|
8717
|
+
clauses.push("status = ?");
|
|
8718
|
+
args.push(options.status);
|
|
8719
|
+
}
|
|
8720
|
+
args.push(limit2);
|
|
8721
|
+
const rows = this.requireDb().prepare(`
|
|
8722
|
+
SELECT * FROM evidence_cards WHERE ${clauses.join(" AND ")} ORDER BY updated_at DESC, id DESC LIMIT ?
|
|
8723
|
+
`).all(...args);
|
|
8724
|
+
return rows.map(rowToCard);
|
|
8725
|
+
}
|
|
8726
|
+
syncObservations(observations2) {
|
|
8727
|
+
return observations2.map((observation) => this.upsertObservation(observation));
|
|
8728
|
+
}
|
|
8729
|
+
markStaleForPaths(projectId, paths, reason = "source file changed") {
|
|
8730
|
+
const normalized = new Set(paths.map((value) => value.replace(/\\/g, "/").toLowerCase()));
|
|
8731
|
+
if (normalized.size === 0) return 0;
|
|
8732
|
+
const db2 = this.requireDb();
|
|
8733
|
+
const rows = db2.prepare(`SELECT * FROM evidence_cards WHERE project_id = ? AND freshness != 'stale'`).all(projectId);
|
|
8734
|
+
const update2 = db2.prepare(`
|
|
8735
|
+
UPDATE evidence_cards SET freshness = 'stale', stale_reason = ?, updated_at = ?
|
|
8736
|
+
WHERE id = ?
|
|
8737
|
+
`);
|
|
8738
|
+
let changed = 0;
|
|
8739
|
+
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
8740
|
+
const run = db2.transaction(() => {
|
|
8741
|
+
for (const row of rows) {
|
|
8742
|
+
const files = safeJson(row.files_json, []);
|
|
8743
|
+
if (!files.some((file) => normalized.has(file.replace(/\\/g, "/").toLowerCase()))) continue;
|
|
8744
|
+
update2.run(reason, now3, row.id);
|
|
8745
|
+
changed++;
|
|
8746
|
+
}
|
|
8747
|
+
});
|
|
8748
|
+
run();
|
|
8749
|
+
return changed;
|
|
8750
|
+
}
|
|
8751
|
+
setVerification(projectId, cardId, verification) {
|
|
8752
|
+
this.requireDb().prepare(`
|
|
8753
|
+
UPDATE evidence_cards SET verification = ?, updated_at = ? WHERE project_id = ? AND id = ?
|
|
8754
|
+
`).run(verification, (/* @__PURE__ */ new Date()).toISOString(), projectId, cardId);
|
|
8755
|
+
}
|
|
8756
|
+
recordEvent(projectId, cardId, kind, detail) {
|
|
8757
|
+
const event = {
|
|
8758
|
+
id: randomUUID4(),
|
|
8759
|
+
projectId,
|
|
8760
|
+
cardId,
|
|
8761
|
+
kind,
|
|
8762
|
+
...detail ? { detail: detail.slice(0, 2e3) } : {},
|
|
8763
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8764
|
+
};
|
|
8765
|
+
this.requireDb().prepare(`
|
|
8766
|
+
INSERT INTO evidence_card_events (id, project_id, card_id, kind, detail, created_at)
|
|
8767
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
8768
|
+
`).run(event.id, event.projectId, event.cardId, event.kind, event.detail ?? null, event.createdAt);
|
|
8769
|
+
return event;
|
|
8770
|
+
}
|
|
8771
|
+
listEvents(cardId, limit2 = 50) {
|
|
8772
|
+
const rows = this.requireDb().prepare(`
|
|
8773
|
+
SELECT * FROM evidence_card_events WHERE card_id = ? ORDER BY created_at DESC LIMIT ?
|
|
8774
|
+
`).all(cardId, Math.min(200, Math.max(1, Math.floor(limit2))));
|
|
8775
|
+
return rows.map((row) => ({
|
|
8776
|
+
id: String(row.id),
|
|
8777
|
+
projectId: String(row.project_id),
|
|
8778
|
+
cardId: String(row.card_id),
|
|
8779
|
+
kind: String(row.kind),
|
|
8780
|
+
...row.detail ? { detail: String(row.detail) } : {},
|
|
8781
|
+
createdAt: String(row.created_at)
|
|
8782
|
+
}));
|
|
8783
|
+
}
|
|
8784
|
+
};
|
|
8785
|
+
}
|
|
8786
|
+
});
|
|
8787
|
+
|
|
8159
8788
|
// src/knowledge/workspace-store.ts
|
|
8160
|
-
import { randomUUID as
|
|
8789
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
8161
8790
|
function arrayValue(raw) {
|
|
8162
8791
|
if (typeof raw !== "string" || !raw) return [];
|
|
8163
8792
|
try {
|
|
@@ -8298,7 +8927,7 @@ var init_workspace_store = __esm({
|
|
|
8298
8927
|
}
|
|
8299
8928
|
createProposal(input) {
|
|
8300
8929
|
const proposal = {
|
|
8301
|
-
id: input.id ??
|
|
8930
|
+
id: input.id ?? randomUUID5(),
|
|
8302
8931
|
...input,
|
|
8303
8932
|
status: input.status ?? "pending",
|
|
8304
8933
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -8351,13 +8980,13 @@ __export(workspace_exports, {
|
|
|
8351
8980
|
loadKnowledgeWorkspace: () => loadKnowledgeWorkspace,
|
|
8352
8981
|
resolveKnowledgeWorkspaceFile: () => resolveKnowledgeWorkspaceFile
|
|
8353
8982
|
});
|
|
8354
|
-
import { createHash as
|
|
8983
|
+
import { createHash as createHash4 } from "crypto";
|
|
8355
8984
|
import { execFile } from "child_process";
|
|
8356
8985
|
import { promises as fs6 } from "fs";
|
|
8357
8986
|
import path9 from "path";
|
|
8358
8987
|
import { promisify } from "util";
|
|
8359
8988
|
function hash(value) {
|
|
8360
|
-
return
|
|
8989
|
+
return createHash4("sha256").update(value).digest("hex");
|
|
8361
8990
|
}
|
|
8362
8991
|
function workspaceId(projectId, mode) {
|
|
8363
8992
|
return "workspace:" + hash(projectId + ":" + mode).slice(0, 24);
|
|
@@ -8964,14 +9593,14 @@ var init_types2 = __esm({
|
|
|
8964
9593
|
});
|
|
8965
9594
|
|
|
8966
9595
|
// src/media/asset-store.ts
|
|
8967
|
-
import { createHash as
|
|
9596
|
+
import { createHash as createHash5, randomUUID as randomUUID6 } from "crypto";
|
|
8968
9597
|
import { copyFile, lstat, mkdir as mkdir3, open, readFile as readFile3, readdir, rename as rename2, rm, stat as stat2, writeFile as writeFile3 } from "fs/promises";
|
|
8969
9598
|
import path10 from "path";
|
|
8970
9599
|
function mediaRoot(dataDir) {
|
|
8971
9600
|
return path10.resolve(dataDir, "media");
|
|
8972
9601
|
}
|
|
8973
9602
|
function projectStorageKey(projectId) {
|
|
8974
|
-
return
|
|
9603
|
+
return createHash5("sha256").update(projectId).digest("hex").slice(0, 16);
|
|
8975
9604
|
}
|
|
8976
9605
|
function validateUnderRoot(root, candidate) {
|
|
8977
9606
|
const resolved = path10.resolve(candidate);
|
|
@@ -9035,7 +9664,7 @@ async function destinationExists(destination) {
|
|
|
9035
9664
|
async function persistBuffer(bytes, destination) {
|
|
9036
9665
|
await mkdir3(path10.dirname(destination), { recursive: true });
|
|
9037
9666
|
if (await destinationExists(destination)) return false;
|
|
9038
|
-
const temporary = `${destination}.${
|
|
9667
|
+
const temporary = `${destination}.${randomUUID6()}.tmp`;
|
|
9039
9668
|
try {
|
|
9040
9669
|
await writeFile3(temporary, bytes, { flag: "wx" });
|
|
9041
9670
|
await rename2(temporary, destination);
|
|
@@ -9080,7 +9709,7 @@ async function importMediaBuffer(input) {
|
|
|
9080
9709
|
if (input.bytes.length === 0) throw new Error("Media import rejects empty payloads");
|
|
9081
9710
|
if (input.bytes.length > maxBytes) throw new Error(`Media payload is too large (${input.bytes.length} bytes; limit ${maxBytes})`);
|
|
9082
9711
|
const detected = detectMedia(input.bytes.subarray(0, 32));
|
|
9083
|
-
const sha256 =
|
|
9712
|
+
const sha256 = createHash5("sha256").update(input.bytes).digest("hex");
|
|
9084
9713
|
return importKnownMedia({
|
|
9085
9714
|
dataDir: input.dataDir,
|
|
9086
9715
|
projectId: input.projectId,
|
|
@@ -9098,7 +9727,7 @@ async function readMediaAsset(dataDir, asset, maxBytes = DEFAULT_MAX_MEDIA_BYTES
|
|
|
9098
9727
|
if (asset.byteSize > maxBytes) throw new Error(`Media asset exceeds read limit (${asset.byteSize} bytes; limit ${maxBytes})`);
|
|
9099
9728
|
const bytes = await readFile3(getMediaAssetPath(dataDir, asset));
|
|
9100
9729
|
if (bytes.length !== asset.byteSize) throw new Error(`Media asset size no longer matches metadata: ${asset.id}`);
|
|
9101
|
-
const sha256 =
|
|
9730
|
+
const sha256 = createHash5("sha256").update(bytes).digest("hex");
|
|
9102
9731
|
if (sha256 !== asset.sha256) throw new Error(`Media asset hash no longer matches metadata: ${asset.id}`);
|
|
9103
9732
|
return bytes;
|
|
9104
9733
|
}
|
|
@@ -61849,7 +62478,7 @@ var require_gaxios = __commonJS({
|
|
|
61849
62478
|
var retry_js_1 = require_retry3();
|
|
61850
62479
|
var stream_1 = __require("stream");
|
|
61851
62480
|
var interceptor_js_1 = require_interceptor();
|
|
61852
|
-
var
|
|
62481
|
+
var randomUUID16 = async () => globalThis.crypto?.randomUUID() || (await import("crypto")).randomUUID();
|
|
61853
62482
|
var HTTP_STATUS_NO_CONTENT = 204;
|
|
61854
62483
|
var Gaxios = class {
|
|
61855
62484
|
agentCache = /* @__PURE__ */ new Map();
|
|
@@ -62122,7 +62751,7 @@ var require_gaxios = __commonJS({
|
|
|
62122
62751
|
*/
|
|
62123
62752
|
["Blob", "File", "FormData"].includes(opts.data?.constructor?.name || "");
|
|
62124
62753
|
if (opts.multipart?.length) {
|
|
62125
|
-
const boundary = await
|
|
62754
|
+
const boundary = await randomUUID16();
|
|
62126
62755
|
preparedHeaders.set("content-type", `multipart/related; boundary=${boundary}`);
|
|
62127
62756
|
opts.body = stream_1.Readable.from(this.getMultipartRequest(opts.multipart, boundary));
|
|
62128
62757
|
} else if (shouldDirectlyPassData) {
|
|
@@ -74349,7 +74978,7 @@ var require_websocket = __commonJS({
|
|
|
74349
74978
|
var http3 = __require("http");
|
|
74350
74979
|
var net = __require("net");
|
|
74351
74980
|
var tls = __require("tls");
|
|
74352
|
-
var { randomBytes, createHash:
|
|
74981
|
+
var { randomBytes, createHash: createHash14 } = __require("crypto");
|
|
74353
74982
|
var { Duplex, Readable: Readable2 } = __require("stream");
|
|
74354
74983
|
var { URL: URL2 } = __require("url");
|
|
74355
74984
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -75017,7 +75646,7 @@ var require_websocket = __commonJS({
|
|
|
75017
75646
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
75018
75647
|
return;
|
|
75019
75648
|
}
|
|
75020
|
-
const digest2 =
|
|
75649
|
+
const digest2 = createHash14("sha1").update(key + GUID).digest("base64");
|
|
75021
75650
|
if (res.headers["sec-websocket-accept"] !== digest2) {
|
|
75022
75651
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
75023
75652
|
return;
|
|
@@ -75389,7 +76018,7 @@ var require_websocket_server = __commonJS({
|
|
|
75389
76018
|
var EventEmitter = __require("events");
|
|
75390
76019
|
var http3 = __require("http");
|
|
75391
76020
|
var { Duplex } = __require("stream");
|
|
75392
|
-
var { createHash:
|
|
76021
|
+
var { createHash: createHash14 } = __require("crypto");
|
|
75393
76022
|
var extension3 = require_extension();
|
|
75394
76023
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
75395
76024
|
var subprotocol2 = require_subprotocol();
|
|
@@ -75696,7 +76325,7 @@ var require_websocket_server = __commonJS({
|
|
|
75696
76325
|
);
|
|
75697
76326
|
}
|
|
75698
76327
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
75699
|
-
const digest2 =
|
|
76328
|
+
const digest2 = createHash14("sha1").update(key + GUID).digest("base64");
|
|
75700
76329
|
const headers = [
|
|
75701
76330
|
"HTTP/1.1 101 Switching Protocols",
|
|
75702
76331
|
"Upgrade: websocket",
|
|
@@ -142540,6 +143169,186 @@ var init_video_jobs = __esm({
|
|
|
142540
143169
|
}
|
|
142541
143170
|
});
|
|
142542
143171
|
|
|
143172
|
+
// src/memory/feedback-model.ts
|
|
143173
|
+
function feedbackWeightMultiplier(weight) {
|
|
143174
|
+
return Math.max(0.35, Math.min(1.4, 0.35 + Math.max(0, Math.min(2, weight)) * 0.525));
|
|
143175
|
+
}
|
|
143176
|
+
var init_feedback_model = __esm({
|
|
143177
|
+
"src/memory/feedback-model.ts"() {
|
|
143178
|
+
"use strict";
|
|
143179
|
+
init_esm_shims();
|
|
143180
|
+
}
|
|
143181
|
+
});
|
|
143182
|
+
|
|
143183
|
+
// src/memory/feedback.ts
|
|
143184
|
+
var feedback_exports = {};
|
|
143185
|
+
__export(feedback_exports, {
|
|
143186
|
+
FEEDBACK_DELTAS: () => FEEDBACK_DELTAS,
|
|
143187
|
+
MemoryFeedbackStore: () => MemoryFeedbackStore,
|
|
143188
|
+
applyMemoryFeedback: () => applyMemoryFeedback,
|
|
143189
|
+
feedbackWeightMultiplier: () => feedbackWeightMultiplier
|
|
143190
|
+
});
|
|
143191
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
143192
|
+
function applyMemoryFeedback(current, event) {
|
|
143193
|
+
const delta = event.signal === "revoke" ? 0 : FEEDBACK_DELTAS[event.signal];
|
|
143194
|
+
const weight = Math.max(0, Math.min(2, current.weight + delta));
|
|
143195
|
+
const status = (event.signal === "code-conflict" || event.signal === "user-correction" || event.signal === "weaken") && weight < 0.5 ? "archived" : current.status;
|
|
143196
|
+
return { weight, status, audit: [...current.audit, { ...event }] };
|
|
143197
|
+
}
|
|
143198
|
+
function rowToEvent(row) {
|
|
143199
|
+
return {
|
|
143200
|
+
id: String(row.id),
|
|
143201
|
+
projectId: String(row.project_id),
|
|
143202
|
+
candidateKind: row.candidate_kind,
|
|
143203
|
+
candidateId: String(row.candidate_id),
|
|
143204
|
+
signal: row.signal,
|
|
143205
|
+
...row.observed_at ? { at: String(row.observed_at) } : { at: (/* @__PURE__ */ new Date()).toISOString() },
|
|
143206
|
+
...row.actor ? { actor: String(row.actor) } : {},
|
|
143207
|
+
...row.note ? { note: String(row.note) } : {},
|
|
143208
|
+
...row.source_ref ? { sourceRef: String(row.source_ref) } : {},
|
|
143209
|
+
...row.target_event_id ? { targetEventId: String(row.target_event_id) } : {},
|
|
143210
|
+
delta: Number(row.delta ?? 0)
|
|
143211
|
+
};
|
|
143212
|
+
}
|
|
143213
|
+
var FEEDBACK_DELTAS, MemoryFeedbackStore;
|
|
143214
|
+
var init_feedback = __esm({
|
|
143215
|
+
"src/memory/feedback.ts"() {
|
|
143216
|
+
"use strict";
|
|
143217
|
+
init_esm_shims();
|
|
143218
|
+
init_sqlite_db();
|
|
143219
|
+
init_feedback_model();
|
|
143220
|
+
FEEDBACK_DELTAS = {
|
|
143221
|
+
"user-correction": -0.35,
|
|
143222
|
+
"verification-success": 0.25,
|
|
143223
|
+
"verification-failure": -0.25,
|
|
143224
|
+
"code-change": -0.15,
|
|
143225
|
+
used: 0.1,
|
|
143226
|
+
"not-used": -0.05,
|
|
143227
|
+
"code-conflict": -0.4,
|
|
143228
|
+
strengthen: 0.2,
|
|
143229
|
+
weaken: -0.2
|
|
143230
|
+
};
|
|
143231
|
+
MemoryFeedbackStore = class {
|
|
143232
|
+
db = null;
|
|
143233
|
+
async init(dataDir) {
|
|
143234
|
+
this.db = getDatabase(dataDir);
|
|
143235
|
+
}
|
|
143236
|
+
requireDb() {
|
|
143237
|
+
if (!this.db) throw new Error("MemoryFeedbackStore is not initialized.");
|
|
143238
|
+
return this.db;
|
|
143239
|
+
}
|
|
143240
|
+
loadEvents(projectId, candidateKind, candidateId) {
|
|
143241
|
+
return this.requireDb().prepare(`
|
|
143242
|
+
SELECT * FROM memory_feedback_events
|
|
143243
|
+
WHERE project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
143244
|
+
ORDER BY observed_at ASC, rowid ASC
|
|
143245
|
+
`).all(projectId, candidateKind, candidateId).map(rowToEvent);
|
|
143246
|
+
}
|
|
143247
|
+
rebuild(projectId, candidateKind, candidateId) {
|
|
143248
|
+
const events = this.loadEvents(projectId, candidateKind, candidateId);
|
|
143249
|
+
const revoked = new Set(events.filter((event) => event.signal === "revoke" && event.targetEventId).map((event) => event.targetEventId));
|
|
143250
|
+
let state = { weight: 1, status: "active", audit: [] };
|
|
143251
|
+
for (const event of events) {
|
|
143252
|
+
if (event.signal === "revoke" || revoked.has(event.id)) {
|
|
143253
|
+
state.audit.push(event);
|
|
143254
|
+
continue;
|
|
143255
|
+
}
|
|
143256
|
+
state = applyMemoryFeedback(state, event);
|
|
143257
|
+
}
|
|
143258
|
+
this.requireDb().prepare(`
|
|
143259
|
+
INSERT INTO memory_feedback_states (project_id, candidate_kind, candidate_id, weight, lifecycle_status, updated_at)
|
|
143260
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
143261
|
+
ON CONFLICT(project_id, candidate_kind, candidate_id) DO UPDATE SET
|
|
143262
|
+
weight = excluded.weight, lifecycle_status = excluded.lifecycle_status, updated_at = excluded.updated_at
|
|
143263
|
+
`).run(projectId, candidateKind, candidateId, state.weight, state.status, (/* @__PURE__ */ new Date()).toISOString());
|
|
143264
|
+
return state;
|
|
143265
|
+
}
|
|
143266
|
+
getState(projectId, candidateKind, candidateId) {
|
|
143267
|
+
const row = this.requireDb().prepare(`
|
|
143268
|
+
SELECT weight, lifecycle_status FROM memory_feedback_states
|
|
143269
|
+
WHERE project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
143270
|
+
`).get(projectId, candidateKind, candidateId);
|
|
143271
|
+
if (!row) return { weight: 1, status: "active", audit: [] };
|
|
143272
|
+
return {
|
|
143273
|
+
weight: Number(row.weight ?? 1),
|
|
143274
|
+
status: row.lifecycle_status ?? "active",
|
|
143275
|
+
audit: this.loadEvents(projectId, candidateKind, candidateId)
|
|
143276
|
+
};
|
|
143277
|
+
}
|
|
143278
|
+
listStates(projectId, candidateKind = "observation") {
|
|
143279
|
+
return this.requireDb().prepare(`
|
|
143280
|
+
SELECT candidate_id, weight, lifecycle_status, updated_at
|
|
143281
|
+
FROM memory_feedback_states WHERE project_id = ? AND candidate_kind = ?
|
|
143282
|
+
ORDER BY updated_at DESC
|
|
143283
|
+
`).all(projectId, candidateKind).map((row) => ({
|
|
143284
|
+
candidateId: String(row.candidate_id),
|
|
143285
|
+
weight: Number(row.weight),
|
|
143286
|
+
status: row.lifecycle_status,
|
|
143287
|
+
updatedAt: String(row.updated_at)
|
|
143288
|
+
}));
|
|
143289
|
+
}
|
|
143290
|
+
weights(projectId, candidateKind = "observation") {
|
|
143291
|
+
const states = /* @__PURE__ */ new Map();
|
|
143292
|
+
for (const row of this.listStates(projectId, candidateKind)) {
|
|
143293
|
+
states.set(row.candidateId, this.getState(projectId, candidateKind, row.candidateId));
|
|
143294
|
+
}
|
|
143295
|
+
return states;
|
|
143296
|
+
}
|
|
143297
|
+
record(input) {
|
|
143298
|
+
if (input.signal === "revoke" && !input.targetEventId) {
|
|
143299
|
+
throw new Error("A revoke feedback event requires targetEventId.");
|
|
143300
|
+
}
|
|
143301
|
+
if (input.signal === "revoke") {
|
|
143302
|
+
const target = this.requireDb().prepare(`
|
|
143303
|
+
SELECT 1 FROM memory_feedback_events
|
|
143304
|
+
WHERE id = ? AND project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
143305
|
+
`).get(input.targetEventId, input.projectId, input.candidateKind, input.candidateId);
|
|
143306
|
+
if (!target) throw new Error("The feedback event to revoke was not found in the same candidate scope.");
|
|
143307
|
+
}
|
|
143308
|
+
const event = {
|
|
143309
|
+
id: randomUUID7(),
|
|
143310
|
+
projectId: input.projectId,
|
|
143311
|
+
candidateKind: input.candidateKind,
|
|
143312
|
+
candidateId: input.candidateId,
|
|
143313
|
+
signal: input.signal,
|
|
143314
|
+
sourceRef: input.sourceRef,
|
|
143315
|
+
...input.actor ? { actor: input.actor } : {},
|
|
143316
|
+
...input.note ? { note: input.note.slice(0, 2e3) } : {},
|
|
143317
|
+
...input.targetEventId ? { targetEventId: input.targetEventId } : {},
|
|
143318
|
+
at: input.at ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
143319
|
+
delta: input.signal === "revoke" ? 0 : FEEDBACK_DELTAS[input.signal]
|
|
143320
|
+
};
|
|
143321
|
+
this.requireDb().prepare(`
|
|
143322
|
+
INSERT INTO memory_feedback_events (
|
|
143323
|
+
id, project_id, candidate_kind, candidate_id, signal, actor, note,
|
|
143324
|
+
source_ref, target_event_id, delta, observed_at
|
|
143325
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
143326
|
+
`).run(
|
|
143327
|
+
event.id,
|
|
143328
|
+
event.projectId,
|
|
143329
|
+
event.candidateKind,
|
|
143330
|
+
event.candidateId,
|
|
143331
|
+
event.signal,
|
|
143332
|
+
event.actor ?? null,
|
|
143333
|
+
event.note ?? null,
|
|
143334
|
+
event.sourceRef,
|
|
143335
|
+
event.targetEventId ?? null,
|
|
143336
|
+
event.delta,
|
|
143337
|
+
event.at
|
|
143338
|
+
);
|
|
143339
|
+
return { event, state: this.rebuild(input.projectId, input.candidateKind, input.candidateId) };
|
|
143340
|
+
}
|
|
143341
|
+
audit(projectId, candidateKind, candidateId, limit2 = 100) {
|
|
143342
|
+
return this.requireDb().prepare(`
|
|
143343
|
+
SELECT * FROM memory_feedback_events
|
|
143344
|
+
WHERE project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
143345
|
+
ORDER BY observed_at DESC, rowid DESC LIMIT ?
|
|
143346
|
+
`).all(projectId, candidateKind, candidateId, Math.min(200, Math.max(1, Math.floor(limit2)))).map(rowToEvent);
|
|
143347
|
+
}
|
|
143348
|
+
};
|
|
143349
|
+
}
|
|
143350
|
+
});
|
|
143351
|
+
|
|
142543
143352
|
// src/memory/retention.ts
|
|
142544
143353
|
var retention_exports = {};
|
|
142545
143354
|
__export(retention_exports, {
|
|
@@ -142581,6 +143390,7 @@ function getEffectiveRetentionDays(doc) {
|
|
|
142581
143390
|
}
|
|
142582
143391
|
function isImmune(doc) {
|
|
142583
143392
|
if (doc.type === "probe") return false;
|
|
143393
|
+
if (doc.feedbackStatus === "archived") return false;
|
|
142584
143394
|
if (doc.admissionState === "candidate" || doc.admissionState === "ephemeral") return false;
|
|
142585
143395
|
if (doc.valueCategory === "core") return true;
|
|
142586
143396
|
const importance = getImportanceLevel(doc);
|
|
@@ -142613,7 +143423,8 @@ function calculateRelevance(doc, referenceTime) {
|
|
|
142613
143423
|
const decayFactor = Math.exp(-ageDays / retention);
|
|
142614
143424
|
const accessCount = doc.accessCount ?? 0;
|
|
142615
143425
|
const accessBoost = Math.min(2, 1 + 0.1 * accessCount);
|
|
142616
|
-
|
|
143426
|
+
const feedbackMultiplier = doc.feedbackWeight === void 0 ? 1 : feedbackWeightMultiplier(doc.feedbackWeight);
|
|
143427
|
+
let totalScore = base * decayFactor * accessBoost * feedbackMultiplier;
|
|
142617
143428
|
const immune = isImmune(doc);
|
|
142618
143429
|
if (immune) {
|
|
142619
143430
|
totalScore = Math.max(totalScore, 0.5);
|
|
@@ -142625,7 +143436,8 @@ function calculateRelevance(doc, referenceTime) {
|
|
|
142625
143436
|
decayFactor,
|
|
142626
143437
|
accessBoost,
|
|
142627
143438
|
ageDays,
|
|
142628
|
-
isImmune: immune
|
|
143439
|
+
isImmune: immune,
|
|
143440
|
+
feedbackMultiplier
|
|
142629
143441
|
};
|
|
142630
143442
|
}
|
|
142631
143443
|
function rankByRelevance(docs, referenceTime) {
|
|
@@ -142633,6 +143445,7 @@ function rankByRelevance(docs, referenceTime) {
|
|
|
142633
143445
|
}
|
|
142634
143446
|
function getRetentionZone(doc, referenceTime) {
|
|
142635
143447
|
const now3 = referenceTime ?? /* @__PURE__ */ new Date();
|
|
143448
|
+
if (doc.feedbackStatus === "archived") return "archive-candidate";
|
|
142636
143449
|
const importance = getImportanceLevel(doc);
|
|
142637
143450
|
const retention = getEffectiveRetentionDays(doc);
|
|
142638
143451
|
const createdAt = new Date(doc.createdAt);
|
|
@@ -142704,7 +143517,7 @@ function explainRetention(doc, referenceTime) {
|
|
|
142704
143517
|
summary: parts.join(" ; ")
|
|
142705
143518
|
};
|
|
142706
143519
|
}
|
|
142707
|
-
function toRetentionDocument(obs, accessMap) {
|
|
143520
|
+
function toRetentionDocument(obs, accessMap, feedback) {
|
|
142708
143521
|
const access2 = accessMap?.get(obs.id);
|
|
142709
143522
|
return {
|
|
142710
143523
|
id: `obs-${obs.id}`,
|
|
@@ -142726,11 +143539,12 @@ function toRetentionDocument(obs, accessMap) {
|
|
|
142726
143539
|
sourceDetail: obs.sourceDetail ?? "",
|
|
142727
143540
|
valueCategory: obs.valueCategory ?? "",
|
|
142728
143541
|
admissionState: obs.admissionState ?? "",
|
|
142729
|
-
admissionReason: obs.admissionReason ?? ""
|
|
143542
|
+
admissionReason: obs.admissionReason ?? "",
|
|
143543
|
+
...feedback ? { feedbackWeight: feedback.weight, feedbackStatus: feedback.status } : {}
|
|
142730
143544
|
};
|
|
142731
143545
|
}
|
|
142732
143546
|
function projectObservationRetention(observation, options = {}) {
|
|
142733
|
-
const document2 = toRetentionDocument(observation, options.accessMap);
|
|
143547
|
+
const document2 = toRetentionDocument(observation, options.accessMap, options.feedback);
|
|
142734
143548
|
const relevance = calculateRelevance(document2, options.referenceTime);
|
|
142735
143549
|
const explanation = explainRetention(document2, options.referenceTime);
|
|
142736
143550
|
return {
|
|
@@ -142755,7 +143569,17 @@ function summarizeRetentionProjections(projections) {
|
|
|
142755
143569
|
}
|
|
142756
143570
|
return { active, stale, archiveCandidates, immune };
|
|
142757
143571
|
}
|
|
142758
|
-
async function
|
|
143572
|
+
async function loadFeedbackStore(dataDir) {
|
|
143573
|
+
try {
|
|
143574
|
+
const { MemoryFeedbackStore: MemoryFeedbackStore2 } = await Promise.resolve().then(() => (init_feedback(), feedback_exports));
|
|
143575
|
+
const store = new MemoryFeedbackStore2();
|
|
143576
|
+
await store.init(dataDir);
|
|
143577
|
+
return store;
|
|
143578
|
+
} catch {
|
|
143579
|
+
return void 0;
|
|
143580
|
+
}
|
|
143581
|
+
}
|
|
143582
|
+
async function archiveExpiredBatch(projectDir2, options) {
|
|
142759
143583
|
const store = getObservationStore();
|
|
142760
143584
|
const limit2 = Math.min(500, Math.max(1, Math.floor(options.limit ?? 100)));
|
|
142761
143585
|
const afterId = Math.max(0, Math.floor(options.afterId ?? 0));
|
|
@@ -142764,11 +143588,13 @@ async function archiveExpiredBatch(_projectDir, options) {
|
|
|
142764
143588
|
afterId,
|
|
142765
143589
|
limit: limit2 + 1
|
|
142766
143590
|
});
|
|
143591
|
+
const feedback = await loadFeedbackStore(projectDir2);
|
|
142767
143592
|
const hasMore = page.length > limit2;
|
|
142768
143593
|
const scanned = hasMore ? page.slice(0, limit2) : page;
|
|
142769
143594
|
const candidateIds = scanned.filter((observation) => !options.reader || canManageObservation(observation, options.reader)).filter((observation) => projectObservationRetention(observation, {
|
|
142770
143595
|
accessMap: options.accessMap,
|
|
142771
|
-
referenceTime: options.referenceTime
|
|
143596
|
+
referenceTime: options.referenceTime,
|
|
143597
|
+
...feedback ? { feedback: feedback.getState(options.projectId, "observation", String(observation.id)) } : {}
|
|
142772
143598
|
}).zone === "archive-candidate").map((observation) => observation.id);
|
|
142773
143599
|
const archived = candidateIds.length === 0 ? 0 : await store.atomic(async (tx) => {
|
|
142774
143600
|
const updates = await Promise.all(
|
|
@@ -142799,6 +143625,7 @@ async function archiveExpired(projectDir2, referenceTime, accessMap, projectId,
|
|
|
142799
143625
|
const remaining = reader ? remainingObservations.filter((observation) => canManageObservation(observation, reader)).length : remainingObservations.length;
|
|
142800
143626
|
return { archived, remaining };
|
|
142801
143627
|
}
|
|
143628
|
+
const feedback = await loadFeedbackStore(projectDir2);
|
|
142802
143629
|
return await store.atomic(async (tx) => {
|
|
142803
143630
|
const allObs = await tx.loadAll();
|
|
142804
143631
|
const activeObs = allObs.filter(
|
|
@@ -142806,7 +143633,11 @@ async function archiveExpired(projectDir2, referenceTime, accessMap, projectId,
|
|
|
142806
143633
|
);
|
|
142807
143634
|
const archivedIds = [];
|
|
142808
143635
|
for (const obs of activeObs) {
|
|
142809
|
-
const retention = projectObservationRetention(obs, {
|
|
143636
|
+
const retention = projectObservationRetention(obs, {
|
|
143637
|
+
accessMap,
|
|
143638
|
+
referenceTime,
|
|
143639
|
+
...feedback ? { feedback: feedback.getState(obs.projectId, "observation", String(obs.id)) } : {}
|
|
143640
|
+
});
|
|
142810
143641
|
if (retention.zone === "archive-candidate") {
|
|
142811
143642
|
archivedIds.push(obs.id);
|
|
142812
143643
|
}
|
|
@@ -142826,6 +143657,7 @@ var init_retention = __esm({
|
|
|
142826
143657
|
init_esm_shims();
|
|
142827
143658
|
init_obs_store();
|
|
142828
143659
|
init_visibility();
|
|
143660
|
+
init_feedback_model();
|
|
142829
143661
|
RETENTION_DAYS = {
|
|
142830
143662
|
critical: 365,
|
|
142831
143663
|
high: 180,
|
|
@@ -142862,7 +143694,7 @@ var init_retention = __esm({
|
|
|
142862
143694
|
});
|
|
142863
143695
|
|
|
142864
143696
|
// src/memory/owner.ts
|
|
142865
|
-
import { randomUUID as
|
|
143697
|
+
import { randomUUID as randomUUID8 } from "crypto";
|
|
142866
143698
|
import { promises as fs9 } from "fs";
|
|
142867
143699
|
import path15 from "path";
|
|
142868
143700
|
function ownerPath(dataDir) {
|
|
@@ -142892,7 +143724,7 @@ async function resolveLocalMemoryOwner(dataDir, options = {}) {
|
|
|
142892
143724
|
await fs9.mkdir(path15.dirname(filePath), { recursive: true });
|
|
142893
143725
|
const created = {
|
|
142894
143726
|
version: 1,
|
|
142895
|
-
id: "local-" +
|
|
143727
|
+
id: "local-" + randomUUID8(),
|
|
142896
143728
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
142897
143729
|
};
|
|
142898
143730
|
try {
|
|
@@ -142915,7 +143747,7 @@ var init_owner = __esm({
|
|
|
142915
143747
|
});
|
|
142916
143748
|
|
|
142917
143749
|
// src/memory/long-term-store.ts
|
|
142918
|
-
import { randomUUID as
|
|
143750
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
142919
143751
|
function optionalText2(value) {
|
|
142920
143752
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
142921
143753
|
}
|
|
@@ -142966,7 +143798,7 @@ function rowToEvidence(row) {
|
|
|
142966
143798
|
createdAt: row.createdAt
|
|
142967
143799
|
};
|
|
142968
143800
|
}
|
|
142969
|
-
function
|
|
143801
|
+
function rowToEvent2(row) {
|
|
142970
143802
|
return {
|
|
142971
143803
|
id: row.id,
|
|
142972
143804
|
memoryId: row.memoryId,
|
|
@@ -143075,7 +143907,7 @@ var init_long_term_store = __esm({
|
|
|
143075
143907
|
}
|
|
143076
143908
|
insertEvidence(input) {
|
|
143077
143909
|
const evidence = {
|
|
143078
|
-
id:
|
|
143910
|
+
id: randomUUID9(),
|
|
143079
143911
|
...input,
|
|
143080
143912
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
143081
143913
|
};
|
|
@@ -143102,7 +143934,7 @@ var init_long_term_store = __esm({
|
|
|
143102
143934
|
}
|
|
143103
143935
|
recordEvent(input) {
|
|
143104
143936
|
const event = {
|
|
143105
|
-
id:
|
|
143937
|
+
id: randomUUID9(),
|
|
143106
143938
|
...input,
|
|
143107
143939
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
143108
143940
|
};
|
|
@@ -143123,7 +143955,7 @@ var init_long_term_store = __esm({
|
|
|
143123
143955
|
listEvents(memoryId) {
|
|
143124
143956
|
return this.db.prepare(`
|
|
143125
143957
|
SELECT * FROM long_term_memory_events WHERE memoryId = ? ORDER BY createdAt ASC, rowid ASC
|
|
143126
|
-
`).all(memoryId).map(
|
|
143958
|
+
`).all(memoryId).map(rowToEvent2);
|
|
143127
143959
|
}
|
|
143128
143960
|
markAccess(ids, at = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
143129
143961
|
const unique = [...new Set(ids.filter(Boolean))];
|
|
@@ -143192,7 +144024,7 @@ __export(long_term_exports, {
|
|
|
143192
144024
|
selectLongTermMemoriesForTask: () => selectLongTermMemoriesForTask,
|
|
143193
144025
|
supersedeLongTermMemory: () => supersedeLongTermMemory
|
|
143194
144026
|
});
|
|
143195
|
-
import { randomUUID as
|
|
144027
|
+
import { randomUUID as randomUUID10 } from "crypto";
|
|
143196
144028
|
function isOneOf(value, values) {
|
|
143197
144029
|
return typeof value === "string" && values.includes(value);
|
|
143198
144030
|
}
|
|
@@ -143374,7 +144206,7 @@ async function createManualLongTermMemory(input) {
|
|
|
143374
144206
|
const owner = await resolveLocalMemoryOwner(input.dataDir, { create: true });
|
|
143375
144207
|
if (!owner) throw new Error("Memorix could not resolve a local memory owner.");
|
|
143376
144208
|
assertScope(input.scope);
|
|
143377
|
-
const evidence = input.scope === "user" ? [{ kind: "user", referenceId: owner.id, relation: "user-confirmed" }] : [{ kind: "manual", referenceId: "manual:" +
|
|
144209
|
+
const evidence = input.scope === "user" ? [{ kind: "user", referenceId: owner.id, relation: "user-confirmed" }] : [{ kind: "manual", referenceId: "manual:" + randomUUID10(), relation: "supports" }];
|
|
143378
144210
|
return createLongTermMemoryWithDataDir({
|
|
143379
144211
|
dataDir: input.dataDir,
|
|
143380
144212
|
originProjectId: input.projectId,
|
|
@@ -143429,7 +144261,7 @@ async function createLongTermMemoryWithDataDir(input) {
|
|
|
143429
144261
|
assertPortableEvidence(input.scope, portability, evidenceInputs);
|
|
143430
144262
|
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
143431
144263
|
const memory = {
|
|
143432
|
-
id:
|
|
144264
|
+
id: randomUUID10(),
|
|
143433
144265
|
originProjectId: compactText(input.originProjectId, "origin project id", 1e3),
|
|
143434
144266
|
ownerId: compactText(input.ownerId, "owner id", 160),
|
|
143435
144267
|
scope: input.scope,
|
|
@@ -143747,9 +144579,9 @@ var init_long_term = __esm({
|
|
|
143747
144579
|
});
|
|
143748
144580
|
|
|
143749
144581
|
// src/codegraph/ids.ts
|
|
143750
|
-
import { createHash as
|
|
144582
|
+
import { createHash as createHash6 } from "crypto";
|
|
143751
144583
|
function digest(input) {
|
|
143752
|
-
return
|
|
144584
|
+
return createHash6("sha256").update(input).digest("hex").slice(0, 16);
|
|
143753
144585
|
}
|
|
143754
144586
|
function normalizeCodePath(path22) {
|
|
143755
144587
|
return path22.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+/g, "/");
|
|
@@ -143784,7 +144616,7 @@ var store_exports = {};
|
|
|
143784
144616
|
__export(store_exports, {
|
|
143785
144617
|
CodeGraphStore: () => CodeGraphStore
|
|
143786
144618
|
});
|
|
143787
|
-
import { randomUUID as
|
|
144619
|
+
import { randomUUID as randomUUID11 } from "crypto";
|
|
143788
144620
|
import { posix as pathPosix } from "path";
|
|
143789
144621
|
function rowToFile(row) {
|
|
143790
144622
|
return {
|
|
@@ -144501,7 +145333,7 @@ var init_store = __esm({
|
|
|
144501
145333
|
* so an interrupted scan cannot be advertised as complete.
|
|
144502
145334
|
*/
|
|
144503
145335
|
recordCodeStateSnapshot(input) {
|
|
144504
|
-
const id =
|
|
145336
|
+
const id = randomUUID11();
|
|
144505
145337
|
let snapshot;
|
|
144506
145338
|
const tx = this.db.transaction(() => {
|
|
144507
145339
|
const previous = this.db.prepare(
|
|
@@ -144579,7 +145411,7 @@ var init_store = __esm({
|
|
|
144579
145411
|
|
|
144580
145412
|
// src/codegraph/code-state.ts
|
|
144581
145413
|
import { execFile as execFile2 } from "child_process";
|
|
144582
|
-
import { createHash as
|
|
145414
|
+
import { createHash as createHash7 } from "crypto";
|
|
144583
145415
|
import { promisify as promisify3 } from "util";
|
|
144584
145416
|
async function runGit(rootPath, args) {
|
|
144585
145417
|
try {
|
|
@@ -144608,7 +145440,7 @@ function changedPathCount(status) {
|
|
|
144608
145440
|
return count2;
|
|
144609
145441
|
}
|
|
144610
145442
|
function fingerprint(baseRevision, status) {
|
|
144611
|
-
return
|
|
145443
|
+
return createHash7("sha256").update(baseRevision ?? "").update("\0").update(status).digest("hex");
|
|
144612
145444
|
}
|
|
144613
145445
|
async function collectCodeStateSnapshot(input) {
|
|
144614
145446
|
const [revision, status] = await Promise.all([
|
|
@@ -144708,11 +145540,11 @@ __export(lite_provider_exports, {
|
|
|
144708
145540
|
indexProjectLite: () => indexProjectLite,
|
|
144709
145541
|
refreshProjectLite: () => refreshProjectLite
|
|
144710
145542
|
});
|
|
144711
|
-
import { createHash as
|
|
145543
|
+
import { createHash as createHash8 } from "crypto";
|
|
144712
145544
|
import { readdirSync as readdirSync2, readFileSync as readFileSync7, statSync as statSync3 } from "fs";
|
|
144713
145545
|
import { join as join4, relative } from "path";
|
|
144714
145546
|
function hashText(text2) {
|
|
144715
|
-
return
|
|
145547
|
+
return createHash8("sha256").update(text2).digest("hex");
|
|
144716
145548
|
}
|
|
144717
145549
|
function extension2(path22) {
|
|
144718
145550
|
const index = path22.lastIndexOf(".");
|
|
@@ -145279,7 +146111,7 @@ var claim_store_exports = {};
|
|
|
145279
146111
|
__export(claim_store_exports, {
|
|
145280
146112
|
ClaimStore: () => ClaimStore
|
|
145281
146113
|
});
|
|
145282
|
-
import { createHash as
|
|
146114
|
+
import { createHash as createHash9, randomUUID as randomUUID12 } from "crypto";
|
|
145283
146115
|
function optionalText3(value) {
|
|
145284
146116
|
return typeof value === "string" && value ? value : void 0;
|
|
145285
146117
|
}
|
|
@@ -145318,7 +146150,7 @@ function rowToEvidence2(row) {
|
|
|
145318
146150
|
createdAt: row.createdAt
|
|
145319
146151
|
};
|
|
145320
146152
|
}
|
|
145321
|
-
function
|
|
146153
|
+
function rowToEvent3(row) {
|
|
145322
146154
|
return {
|
|
145323
146155
|
id: row.id,
|
|
145324
146156
|
projectId: row.projectId,
|
|
@@ -145332,7 +146164,7 @@ function rowToEvent2(row) {
|
|
|
145332
146164
|
};
|
|
145333
146165
|
}
|
|
145334
146166
|
function evidenceKey(input) {
|
|
145335
|
-
return
|
|
146167
|
+
return createHash9("sha256").update(JSON.stringify([
|
|
145336
146168
|
input.evidenceKind,
|
|
145337
146169
|
input.evidenceId,
|
|
145338
146170
|
input.relation,
|
|
@@ -145463,7 +146295,7 @@ var init_claim_store = __esm({
|
|
|
145463
146295
|
locator, capturedHash, evidenceKey, createdAt
|
|
145464
146296
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
145465
146297
|
`).run(
|
|
145466
|
-
|
|
146298
|
+
randomUUID12(),
|
|
145467
146299
|
input.claimId,
|
|
145468
146300
|
input.evidenceKind,
|
|
145469
146301
|
input.evidenceId,
|
|
@@ -145485,7 +146317,7 @@ var init_claim_store = __esm({
|
|
|
145485
146317
|
}
|
|
145486
146318
|
recordEvent(input) {
|
|
145487
146319
|
const event = {
|
|
145488
|
-
id:
|
|
146320
|
+
id: randomUUID12(),
|
|
145489
146321
|
...input,
|
|
145490
146322
|
...input.detail ? { detail: sanitizeCredentials(input.detail) } : {},
|
|
145491
146323
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -145513,7 +146345,7 @@ var init_claim_store = __esm({
|
|
|
145513
146345
|
SELECT * FROM knowledge_claim_events
|
|
145514
146346
|
WHERE claimId = ?
|
|
145515
146347
|
ORDER BY createdAt ASC, id
|
|
145516
|
-
`).all(claimId).map(
|
|
146348
|
+
`).all(claimId).map(rowToEvent3);
|
|
145517
146349
|
}
|
|
145518
146350
|
};
|
|
145519
146351
|
}
|
|
@@ -145530,7 +146362,7 @@ __export(claims_exports, {
|
|
|
145530
146362
|
supersedeClaim: () => supersedeClaim,
|
|
145531
146363
|
writeClaim: () => writeClaim
|
|
145532
146364
|
});
|
|
145533
|
-
import { createHash as
|
|
146365
|
+
import { createHash as createHash10, randomUUID as randomUUID13 } from "crypto";
|
|
145534
146366
|
function compactText2(value, field) {
|
|
145535
146367
|
if (typeof value !== "string") throw new Error("Claim " + field + " must be text");
|
|
145536
146368
|
const sanitized = sanitizeCredentials(value).trim().replace(/\s+/g, " ");
|
|
@@ -145542,7 +146374,7 @@ function normalizedTerm(value) {
|
|
|
145542
146374
|
return compactText2(value, "identity").toLocaleLowerCase("en-US");
|
|
145543
146375
|
}
|
|
145544
146376
|
function hashIdentity(parts) {
|
|
145545
|
-
return
|
|
146377
|
+
return createHash10("sha256").update(parts.join(String.fromCharCode(31))).digest("hex");
|
|
145546
146378
|
}
|
|
145547
146379
|
function buildClaimIdentity(input) {
|
|
145548
146380
|
const subject = normalizedTerm(input.subject);
|
|
@@ -145616,7 +146448,7 @@ function normalizeClaimInput(input) {
|
|
|
145616
146448
|
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
145617
146449
|
return {
|
|
145618
146450
|
claim: {
|
|
145619
|
-
id:
|
|
146451
|
+
id: randomUUID13(),
|
|
145620
146452
|
projectId,
|
|
145621
146453
|
subject,
|
|
145622
146454
|
predicate,
|
|
@@ -145783,7 +146615,7 @@ function supersedeClaim(store, input) {
|
|
|
145783
146615
|
});
|
|
145784
146616
|
}
|
|
145785
146617
|
function hashObservation(observation) {
|
|
145786
|
-
return
|
|
146618
|
+
return createHash10("sha256").update(JSON.stringify([
|
|
145787
146619
|
observation.title,
|
|
145788
146620
|
observation.narrative,
|
|
145789
146621
|
observation.facts,
|
|
@@ -146027,11 +146859,11 @@ var init_frontmatter = __esm({
|
|
|
146027
146859
|
});
|
|
146028
146860
|
|
|
146029
146861
|
// src/knowledge/markdown.ts
|
|
146030
|
-
import { createHash as
|
|
146862
|
+
import { createHash as createHash11 } from "crypto";
|
|
146031
146863
|
import { promises as fs10 } from "fs";
|
|
146032
146864
|
import path16 from "path";
|
|
146033
146865
|
function hashContent(content) {
|
|
146034
|
-
return
|
|
146866
|
+
return createHash11("sha256").update(content).digest("hex");
|
|
146035
146867
|
}
|
|
146036
146868
|
function stringField(data, key) {
|
|
146037
146869
|
const value = data[key];
|
|
@@ -146157,11 +146989,11 @@ __export(wiki_exports, {
|
|
|
146157
146989
|
lintKnowledgeWorkspace: () => lintKnowledgeWorkspace,
|
|
146158
146990
|
readKnowledgePage: () => readKnowledgePage
|
|
146159
146991
|
});
|
|
146160
|
-
import { createHash as
|
|
146992
|
+
import { createHash as createHash12 } from "crypto";
|
|
146161
146993
|
import { promises as fs11 } from "fs";
|
|
146162
146994
|
import path17 from "path";
|
|
146163
146995
|
function hash2(value) {
|
|
146164
|
-
return
|
|
146996
|
+
return createHash12("sha256").update(value).digest("hex");
|
|
146165
146997
|
}
|
|
146166
146998
|
function now() {
|
|
146167
146999
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -146701,7 +147533,7 @@ var init_workflow_sync = __esm({
|
|
|
146701
147533
|
});
|
|
146702
147534
|
|
|
146703
147535
|
// src/knowledge/workflow-store.ts
|
|
146704
|
-
import { randomUUID as
|
|
147536
|
+
import { randomUUID as randomUUID14 } from "crypto";
|
|
146705
147537
|
function parseJson(value, fallback) {
|
|
146706
147538
|
if (typeof value !== "string" || !value) return fallback;
|
|
146707
147539
|
try {
|
|
@@ -146801,7 +147633,7 @@ var init_workflow_store = __esm({
|
|
|
146801
147633
|
}
|
|
146802
147634
|
recordRun(input) {
|
|
146803
147635
|
const run = {
|
|
146804
|
-
id:
|
|
147636
|
+
id: randomUUID14(),
|
|
146805
147637
|
workflowId: input.workflowId,
|
|
146806
147638
|
projectId: input.projectId,
|
|
146807
147639
|
task: input.task.trim(),
|
|
@@ -146869,7 +147701,7 @@ var init_outcome_types = __esm({
|
|
|
146869
147701
|
});
|
|
146870
147702
|
|
|
146871
147703
|
// src/knowledge/outcome-store.ts
|
|
146872
|
-
import { randomUUID as
|
|
147704
|
+
import { randomUUID as randomUUID15 } from "crypto";
|
|
146873
147705
|
function optionalText5(value) {
|
|
146874
147706
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
146875
147707
|
}
|
|
@@ -146913,7 +147745,7 @@ var init_outcome_store = __esm({
|
|
|
146913
147745
|
}
|
|
146914
147746
|
record(input) {
|
|
146915
147747
|
const signal = {
|
|
146916
|
-
id:
|
|
147748
|
+
id: randomUUID15(),
|
|
146917
147749
|
projectId: text(input.projectId, "project id"),
|
|
146918
147750
|
candidateKind: oneOf(input.candidateKind, MEMORY_OUTCOME_CANDIDATE_KINDS, "candidate kind"),
|
|
146919
147751
|
candidateId: text(input.candidateId, "candidate id"),
|
|
@@ -147018,11 +147850,11 @@ __export(workflows_exports, {
|
|
|
147018
147850
|
syncCanonicalWorkflows: () => syncCanonicalWorkflows,
|
|
147019
147851
|
writeCanonicalWorkflow: () => writeCanonicalWorkflow
|
|
147020
147852
|
});
|
|
147021
|
-
import { createHash as
|
|
147853
|
+
import { createHash as createHash13 } from "crypto";
|
|
147022
147854
|
import { promises as fs12 } from "fs";
|
|
147023
147855
|
import path18 from "path";
|
|
147024
147856
|
function hash3(value) {
|
|
147025
|
-
return
|
|
147857
|
+
return createHash13("sha256").update(value).digest("hex");
|
|
147026
147858
|
}
|
|
147027
147859
|
function now2() {
|
|
147028
147860
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -148404,6 +149236,16 @@ async function bindObservationCodeRefsBestEffort(observation) {
|
|
|
148404
149236
|
} catch {
|
|
148405
149237
|
}
|
|
148406
149238
|
}
|
|
149239
|
+
async function persistEvidenceCard(observation) {
|
|
149240
|
+
if (!projectDir) return;
|
|
149241
|
+
try {
|
|
149242
|
+
const evidence = new EvidenceCardStore();
|
|
149243
|
+
await evidence.init(projectDir);
|
|
149244
|
+
evidence.upsertObservation(observation);
|
|
149245
|
+
} catch (error) {
|
|
149246
|
+
console.error(`[memorix] Evidence card projection failed for obs-${observation.id}: ${error instanceof Error ? error.message : String(error)}`);
|
|
149247
|
+
}
|
|
149248
|
+
}
|
|
148407
149249
|
function queueClaimDerivation(observation) {
|
|
148408
149250
|
const dataDir = projectDir;
|
|
148409
149251
|
const isExplicit = observation.sourceDetail === "explicit";
|
|
@@ -148750,6 +149592,7 @@ async function storeObservation(input) {
|
|
|
148750
149592
|
}
|
|
148751
149593
|
if (!persistedCallbackInvoked) await input.onPersisted?.(observation);
|
|
148752
149594
|
await bindObservationCodeRefsBestEffort(observation);
|
|
149595
|
+
await persistEvidenceCard(observation);
|
|
148753
149596
|
queueObservationQualification(observation);
|
|
148754
149597
|
if (resolveObservationVisibility(observation) === "project") {
|
|
148755
149598
|
queueClaimDerivation(observation);
|
|
@@ -148842,6 +149685,7 @@ async function upsertObservation(existing, input, now3) {
|
|
|
148842
149685
|
await store.update(existing);
|
|
148843
149686
|
}
|
|
148844
149687
|
await bindObservationCodeRefsBestEffort(existing);
|
|
149688
|
+
await persistEvidenceCard(existing);
|
|
148845
149689
|
queueObservationQualification(existing);
|
|
148846
149690
|
if (resolveObservationVisibility(existing) === "project") {
|
|
148847
149691
|
queueClaimDerivation(existing);
|
|
@@ -148975,6 +149819,7 @@ async function resolveObservations(ids, status = "resolved") {
|
|
|
148975
149819
|
await Promise.all(changed.map((observation) => tx.update(observation)));
|
|
148976
149820
|
});
|
|
148977
149821
|
}
|
|
149822
|
+
for (const observation of changed) await persistEvidenceCard(observation);
|
|
148978
149823
|
return { resolved, notFound };
|
|
148979
149824
|
}
|
|
148980
149825
|
function getProjectObservations(projectId) {
|
|
@@ -149312,6 +150157,7 @@ var init_observations = __esm({
|
|
|
149312
150157
|
init_secret_filter();
|
|
149313
150158
|
init_lifecycle();
|
|
149314
150159
|
init_visibility();
|
|
150160
|
+
init_evidence_store();
|
|
149315
150161
|
observations = [];
|
|
149316
150162
|
nextId = 1;
|
|
149317
150163
|
projectDir = null;
|