memorix 1.7.3 → 1.8.1
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 +41 -0
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/cli/index.js +1488 -270
- package/dist/dashboard/static/app.js +125 -27
- package/dist/dashboard/static/index.html +11 -1
- package/dist/dashboard/static/style.css +86 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +927 -240
- package/dist/maintenance-runner.js +607 -68
- package/dist/media-audio-runner.js +602 -63
- package/dist/media-video-runner.js +607 -68
- package/dist/memcode-runtime/CHANGELOG.md +41 -0
- package/dist/sdk.js +926 -239
- package/dist/types.d.ts +8 -0
- package/dist/vector-backfill-runner.js +607 -68
- 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 +39 -1
- package/docs/ARCHITECTURE.md +3 -1
- package/docs/DASHBOARD.md +16 -0
- package/docs/DEVELOPMENT.md +3 -2
- package/docs/INTEGRATIONS.md +1 -1
- package/docs/README.md +15 -2
- 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/context.ts +11 -0
- package/src/cli/commands/dashboard.ts +1 -1
- package/src/cli/commands/evidence.ts +56 -0
- package/src/cli/commands/feedback.ts +58 -0
- package/src/cli/commands/resume.ts +2 -0
- package/src/cli/commands/serve-http.ts +229 -13
- 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/dashboard/config-provenance.ts +17 -0
- package/src/dashboard/evidence.ts +63 -0
- package/src/dashboard/server.ts +178 -154
- package/src/dashboard/static/index.html +11 -1
- 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/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/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 +125 -5
- package/src/store/evidence-store.ts +261 -0
- package/src/store/sqlite-db.ts +104 -0
- package/src/types.ts +8 -0
package/dist/index.js
CHANGED
|
@@ -402,7 +402,7 @@ function closeAllDatabases() {
|
|
|
402
402
|
_dbCache.delete(key);
|
|
403
403
|
}
|
|
404
404
|
}
|
|
405
|
-
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;
|
|
405
|
+
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;
|
|
406
406
|
var init_sqlite_db = __esm({
|
|
407
407
|
"src/store/sqlite-db.ts"() {
|
|
408
408
|
"use strict";
|
|
@@ -1048,6 +1048,79 @@ CREATE TABLE IF NOT EXISTS compaction_checkpoints (
|
|
|
1048
1048
|
created_at TEXT NOT NULL,
|
|
1049
1049
|
updated_at TEXT NOT NULL
|
|
1050
1050
|
);
|
|
1051
|
+
`;
|
|
1052
|
+
CREATE_EVIDENCE_CARDS_TABLE = `
|
|
1053
|
+
CREATE TABLE IF NOT EXISTS evidence_cards (
|
|
1054
|
+
id TEXT PRIMARY KEY,
|
|
1055
|
+
project_id TEXT NOT NULL,
|
|
1056
|
+
candidate_kind TEXT NOT NULL,
|
|
1057
|
+
candidate_id TEXT NOT NULL,
|
|
1058
|
+
title TEXT NOT NULL,
|
|
1059
|
+
summary TEXT NOT NULL DEFAULT '',
|
|
1060
|
+
entity_name TEXT,
|
|
1061
|
+
source_kind TEXT NOT NULL,
|
|
1062
|
+
source_ref TEXT NOT NULL,
|
|
1063
|
+
locator TEXT,
|
|
1064
|
+
captured_hash TEXT,
|
|
1065
|
+
session_id TEXT,
|
|
1066
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
1067
|
+
verification TEXT NOT NULL DEFAULT 'unverified',
|
|
1068
|
+
freshness TEXT NOT NULL DEFAULT 'current',
|
|
1069
|
+
stale_reason TEXT,
|
|
1070
|
+
files_json TEXT NOT NULL DEFAULT '[]',
|
|
1071
|
+
related_entities_json TEXT NOT NULL DEFAULT '[]',
|
|
1072
|
+
created_at TEXT NOT NULL,
|
|
1073
|
+
updated_at TEXT NOT NULL,
|
|
1074
|
+
UNIQUE(project_id, candidate_kind, candidate_id)
|
|
1075
|
+
);
|
|
1076
|
+
`;
|
|
1077
|
+
CREATE_EVIDENCE_CARD_EVENTS_TABLE = `
|
|
1078
|
+
CREATE TABLE IF NOT EXISTS evidence_card_events (
|
|
1079
|
+
id TEXT PRIMARY KEY,
|
|
1080
|
+
project_id TEXT NOT NULL,
|
|
1081
|
+
card_id TEXT NOT NULL,
|
|
1082
|
+
kind TEXT NOT NULL,
|
|
1083
|
+
detail TEXT,
|
|
1084
|
+
created_at TEXT NOT NULL,
|
|
1085
|
+
FOREIGN KEY (card_id) REFERENCES evidence_cards(id) ON DELETE CASCADE
|
|
1086
|
+
);
|
|
1087
|
+
`;
|
|
1088
|
+
CREATE_MEMORY_FEEDBACK_STATES_TABLE = `
|
|
1089
|
+
CREATE TABLE IF NOT EXISTS memory_feedback_states (
|
|
1090
|
+
project_id TEXT NOT NULL,
|
|
1091
|
+
candidate_kind TEXT NOT NULL,
|
|
1092
|
+
candidate_id TEXT NOT NULL,
|
|
1093
|
+
weight REAL NOT NULL DEFAULT 1.0,
|
|
1094
|
+
lifecycle_status TEXT NOT NULL DEFAULT 'active',
|
|
1095
|
+
updated_at TEXT NOT NULL,
|
|
1096
|
+
PRIMARY KEY (project_id, candidate_kind, candidate_id)
|
|
1097
|
+
);
|
|
1098
|
+
`;
|
|
1099
|
+
CREATE_MEMORY_FEEDBACK_EVENTS_TABLE = `
|
|
1100
|
+
CREATE TABLE IF NOT EXISTS memory_feedback_events (
|
|
1101
|
+
id TEXT PRIMARY KEY,
|
|
1102
|
+
project_id TEXT NOT NULL,
|
|
1103
|
+
candidate_kind TEXT NOT NULL,
|
|
1104
|
+
candidate_id TEXT NOT NULL,
|
|
1105
|
+
signal TEXT NOT NULL,
|
|
1106
|
+
actor TEXT,
|
|
1107
|
+
note TEXT,
|
|
1108
|
+
source_ref TEXT NOT NULL,
|
|
1109
|
+
target_event_id TEXT,
|
|
1110
|
+
delta REAL NOT NULL DEFAULT 0,
|
|
1111
|
+
observed_at TEXT NOT NULL
|
|
1112
|
+
);
|
|
1113
|
+
`;
|
|
1114
|
+
CREATE_MCP_BINDINGS_TABLE = `
|
|
1115
|
+
CREATE TABLE IF NOT EXISTS mcp_bindings (
|
|
1116
|
+
handle_id TEXT PRIMARY KEY,
|
|
1117
|
+
project_id TEXT NOT NULL,
|
|
1118
|
+
project_root TEXT NOT NULL,
|
|
1119
|
+
data_dir TEXT NOT NULL,
|
|
1120
|
+
created_at TEXT NOT NULL,
|
|
1121
|
+
last_used_at TEXT NOT NULL,
|
|
1122
|
+
expires_at TEXT
|
|
1123
|
+
);
|
|
1051
1124
|
`;
|
|
1052
1125
|
CREATE_INDEXES = `
|
|
1053
1126
|
CREATE INDEX IF NOT EXISTS idx_observations_projectId ON observations(projectId);
|
|
@@ -1110,6 +1183,12 @@ CREATE INDEX IF NOT EXISTS idx_maintenance_targets_updated ON maintenance_target
|
|
|
1110
1183
|
CREATE INDEX IF NOT EXISTS idx_compaction_checkpoints_project_recent ON compaction_checkpoints(project_id, status, completed_at DESC, pre_captured_at DESC);
|
|
1111
1184
|
CREATE INDEX IF NOT EXISTS idx_compaction_checkpoints_session_pending ON compaction_checkpoints(project_id, session_id, agent, phase, status, pre_captured_at DESC);
|
|
1112
1185
|
CREATE INDEX IF NOT EXISTS idx_compaction_checkpoints_source ON compaction_checkpoints(project_id, source_key);
|
|
1186
|
+
CREATE INDEX IF NOT EXISTS idx_evidence_cards_project ON evidence_cards(project_id, status, updated_at DESC);
|
|
1187
|
+
CREATE INDEX IF NOT EXISTS idx_evidence_cards_candidate ON evidence_cards(project_id, candidate_kind, candidate_id);
|
|
1188
|
+
CREATE INDEX IF NOT EXISTS idx_evidence_card_events_card ON evidence_card_events(card_id, created_at);
|
|
1189
|
+
CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC);
|
|
1190
|
+
CREATE INDEX IF NOT EXISTS idx_memory_feedback_events_candidate ON memory_feedback_events(project_id, candidate_kind, candidate_id, observed_at DESC);
|
|
1191
|
+
CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC);
|
|
1113
1192
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
1114
1193
|
ON maintenance_jobs(project_id, kind, dedupe_key)
|
|
1115
1194
|
WHERE status IN ('pending', 'running', 'retry');
|
|
@@ -1265,6 +1344,22 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
|
1265
1344
|
}
|
|
1266
1345
|
db2.exec("CREATE INDEX IF NOT EXISTS idx_media_jobs_source_asset ON media_jobs(project_id, source_asset_id, status)");
|
|
1267
1346
|
}
|
|
1347
|
+
},
|
|
1348
|
+
{
|
|
1349
|
+
id: "1.8-context-control-plane",
|
|
1350
|
+
apply: (db2) => {
|
|
1351
|
+
db2.exec(CREATE_EVIDENCE_CARDS_TABLE);
|
|
1352
|
+
db2.exec(CREATE_EVIDENCE_CARD_EVENTS_TABLE);
|
|
1353
|
+
db2.exec(CREATE_MEMORY_FEEDBACK_STATES_TABLE);
|
|
1354
|
+
db2.exec(CREATE_MEMORY_FEEDBACK_EVENTS_TABLE);
|
|
1355
|
+
db2.exec(CREATE_MCP_BINDINGS_TABLE);
|
|
1356
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_evidence_cards_project ON evidence_cards(project_id, status, updated_at DESC)");
|
|
1357
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_evidence_cards_candidate ON evidence_cards(project_id, candidate_kind, candidate_id)");
|
|
1358
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_evidence_card_events_card ON evidence_card_events(card_id, created_at)");
|
|
1359
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC)");
|
|
1360
|
+
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)");
|
|
1361
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC)");
|
|
1362
|
+
}
|
|
1268
1363
|
}
|
|
1269
1364
|
];
|
|
1270
1365
|
_dbCache = /* @__PURE__ */ new Map();
|
|
@@ -3162,6 +3257,8 @@ var init_toml_loader = __esm({
|
|
|
3162
3257
|
var dotenv_loader_exports = {};
|
|
3163
3258
|
__export(dotenv_loader_exports, {
|
|
3164
3259
|
getLoadedEnvFiles: () => getLoadedEnvFiles,
|
|
3260
|
+
getLoadedEnvKeys: () => getLoadedEnvKeys,
|
|
3261
|
+
getLoadedEnvValue: () => getLoadedEnvValue,
|
|
3165
3262
|
loadDotenv: () => loadDotenv,
|
|
3166
3263
|
resetDotenv: () => resetDotenv
|
|
3167
3264
|
});
|
|
@@ -3173,6 +3270,8 @@ function loadEnvFile(filePath) {
|
|
|
3173
3270
|
const parsed = parse(readFileSync6(filePath, "utf-8"));
|
|
3174
3271
|
for (const [key, value] of Object.entries(parsed)) {
|
|
3175
3272
|
if (!(key in process.env)) {
|
|
3273
|
+
loadedEnvKeys.add(key);
|
|
3274
|
+
loadedEnvValues.set(key, value);
|
|
3176
3275
|
process.env[key] = value;
|
|
3177
3276
|
injectedKeys.add(key);
|
|
3178
3277
|
}
|
|
@@ -3185,6 +3284,8 @@ function loadDotenv(projectRoot, options = {}) {
|
|
|
3185
3284
|
resetDotenv();
|
|
3186
3285
|
}
|
|
3187
3286
|
loadedEnvFiles.length = 0;
|
|
3287
|
+
loadedEnvKeys.clear();
|
|
3288
|
+
loadedEnvValues.clear();
|
|
3188
3289
|
if (projectRoot) {
|
|
3189
3290
|
loadEnvFile(getProjectDotenvPath(projectRoot));
|
|
3190
3291
|
}
|
|
@@ -3200,11 +3301,18 @@ function resetDotenv() {
|
|
|
3200
3301
|
dotenvLoaded = false;
|
|
3201
3302
|
dotenvProjectRoot = null;
|
|
3202
3303
|
loadedEnvFiles.length = 0;
|
|
3304
|
+
loadedEnvKeys.clear();
|
|
3203
3305
|
}
|
|
3204
3306
|
function getLoadedEnvFiles() {
|
|
3205
3307
|
return loadedEnvFiles;
|
|
3206
3308
|
}
|
|
3207
|
-
|
|
3309
|
+
function getLoadedEnvKeys() {
|
|
3310
|
+
return loadedEnvKeys;
|
|
3311
|
+
}
|
|
3312
|
+
function getLoadedEnvValue(key) {
|
|
3313
|
+
return loadedEnvValues.get(key);
|
|
3314
|
+
}
|
|
3315
|
+
var dotenvLoaded, dotenvProjectRoot, loadedEnvFiles, loadedEnvKeys, loadedEnvValues, injectedKeys;
|
|
3208
3316
|
var init_dotenv_loader = __esm({
|
|
3209
3317
|
"src/config/dotenv-loader.ts"() {
|
|
3210
3318
|
"use strict";
|
|
@@ -3213,6 +3321,8 @@ var init_dotenv_loader = __esm({
|
|
|
3213
3321
|
dotenvLoaded = false;
|
|
3214
3322
|
dotenvProjectRoot = null;
|
|
3215
3323
|
loadedEnvFiles = [];
|
|
3324
|
+
loadedEnvKeys = /* @__PURE__ */ new Set();
|
|
3325
|
+
loadedEnvValues = /* @__PURE__ */ new Map();
|
|
3216
3326
|
injectedKeys = /* @__PURE__ */ new Set();
|
|
3217
3327
|
}
|
|
3218
3328
|
});
|
|
@@ -9303,6 +9413,226 @@ var init_lifecycle = __esm({
|
|
|
9303
9413
|
}
|
|
9304
9414
|
});
|
|
9305
9415
|
|
|
9416
|
+
// src/store/evidence-store.ts
|
|
9417
|
+
import { createHash as createHash3, randomUUID as randomUUID3 } from "crypto";
|
|
9418
|
+
function safeJson(value, fallback) {
|
|
9419
|
+
if (typeof value !== "string" || value.length === 0) return fallback;
|
|
9420
|
+
try {
|
|
9421
|
+
return JSON.parse(value);
|
|
9422
|
+
} catch {
|
|
9423
|
+
return fallback;
|
|
9424
|
+
}
|
|
9425
|
+
}
|
|
9426
|
+
function rowToCard(row) {
|
|
9427
|
+
return {
|
|
9428
|
+
id: String(row.id),
|
|
9429
|
+
projectId: String(row.project_id),
|
|
9430
|
+
candidateKind: row.candidate_kind,
|
|
9431
|
+
candidateId: String(row.candidate_id),
|
|
9432
|
+
title: String(row.title),
|
|
9433
|
+
summary: String(row.summary ?? ""),
|
|
9434
|
+
...row.entity_name ? { entityName: String(row.entity_name) } : {},
|
|
9435
|
+
sourceKind: String(row.source_kind),
|
|
9436
|
+
sourceRef: String(row.source_ref),
|
|
9437
|
+
...row.locator ? { locator: String(row.locator) } : {},
|
|
9438
|
+
...row.captured_hash ? { capturedHash: String(row.captured_hash) } : {},
|
|
9439
|
+
...row.session_id ? { sessionId: String(row.session_id) } : {},
|
|
9440
|
+
status: String(row.status ?? "active"),
|
|
9441
|
+
verification: row.verification,
|
|
9442
|
+
freshness: row.freshness,
|
|
9443
|
+
...row.stale_reason ? { staleReason: String(row.stale_reason) } : {},
|
|
9444
|
+
files: safeJson(row.files_json, []),
|
|
9445
|
+
relatedEntities: safeJson(row.related_entities_json, []),
|
|
9446
|
+
createdAt: String(row.created_at),
|
|
9447
|
+
updatedAt: String(row.updated_at)
|
|
9448
|
+
};
|
|
9449
|
+
}
|
|
9450
|
+
function observationHash(observation) {
|
|
9451
|
+
return createHash3("sha256").update(JSON.stringify({
|
|
9452
|
+
projectId: observation.projectId,
|
|
9453
|
+
id: observation.id,
|
|
9454
|
+
title: observation.title,
|
|
9455
|
+
narrative: observation.narrative,
|
|
9456
|
+
facts: observation.facts,
|
|
9457
|
+
files: observation.filesModified,
|
|
9458
|
+
relatedEntities: observation.relatedEntities
|
|
9459
|
+
})).digest("hex");
|
|
9460
|
+
}
|
|
9461
|
+
function sourceKind(observation) {
|
|
9462
|
+
if (observation.source === "git" || observation.sourceDetail === "git-ingest") return "git";
|
|
9463
|
+
if (observation.sourceDetail === "hook") return "hook";
|
|
9464
|
+
return observation.source ?? "agent";
|
|
9465
|
+
}
|
|
9466
|
+
var EvidenceCardStore;
|
|
9467
|
+
var init_evidence_store = __esm({
|
|
9468
|
+
"src/store/evidence-store.ts"() {
|
|
9469
|
+
"use strict";
|
|
9470
|
+
init_esm_shims();
|
|
9471
|
+
init_sqlite_db();
|
|
9472
|
+
EvidenceCardStore = class {
|
|
9473
|
+
db = null;
|
|
9474
|
+
async init(dataDir) {
|
|
9475
|
+
this.db = getDatabase(dataDir);
|
|
9476
|
+
}
|
|
9477
|
+
requireDb() {
|
|
9478
|
+
if (!this.db) throw new Error("EvidenceCardStore is not initialized.");
|
|
9479
|
+
return this.db;
|
|
9480
|
+
}
|
|
9481
|
+
upsertObservation(observation) {
|
|
9482
|
+
const db2 = this.requireDb();
|
|
9483
|
+
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
9484
|
+
const card = {
|
|
9485
|
+
id: `evidence:observation:${observation.projectId}:${observation.id}`,
|
|
9486
|
+
projectId: observation.projectId,
|
|
9487
|
+
candidateKind: "observation",
|
|
9488
|
+
candidateId: String(observation.id),
|
|
9489
|
+
title: observation.title,
|
|
9490
|
+
summary: observation.narrative.slice(0, 500),
|
|
9491
|
+
entityName: observation.entityName,
|
|
9492
|
+
sourceKind: sourceKind(observation),
|
|
9493
|
+
sourceRef: `observation:${observation.id}`,
|
|
9494
|
+
locator: observation.filesModified?.join(", ") || `observation:${observation.id}`,
|
|
9495
|
+
capturedHash: observationHash(observation),
|
|
9496
|
+
...observation.sessionId ? { sessionId: observation.sessionId } : {},
|
|
9497
|
+
status: observation.status ?? "active",
|
|
9498
|
+
verification: observation.status === "resolved" ? "verified" : "unverified",
|
|
9499
|
+
freshness: "current",
|
|
9500
|
+
files: observation.filesModified ?? [],
|
|
9501
|
+
relatedEntities: observation.relatedEntities ?? [],
|
|
9502
|
+
createdAt: observation.createdAt,
|
|
9503
|
+
updatedAt: now3
|
|
9504
|
+
};
|
|
9505
|
+
db2.prepare(`
|
|
9506
|
+
INSERT INTO evidence_cards (
|
|
9507
|
+
id, project_id, candidate_kind, candidate_id, title, summary, entity_name,
|
|
9508
|
+
source_kind, source_ref, locator, captured_hash, session_id, status,
|
|
9509
|
+
verification, freshness, stale_reason, files_json, related_entities_json,
|
|
9510
|
+
created_at, updated_at
|
|
9511
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?)
|
|
9512
|
+
ON CONFLICT(project_id, candidate_kind, candidate_id) DO UPDATE SET
|
|
9513
|
+
title = excluded.title,
|
|
9514
|
+
summary = excluded.summary,
|
|
9515
|
+
entity_name = excluded.entity_name,
|
|
9516
|
+
source_kind = excluded.source_kind,
|
|
9517
|
+
source_ref = excluded.source_ref,
|
|
9518
|
+
locator = excluded.locator,
|
|
9519
|
+
captured_hash = excluded.captured_hash,
|
|
9520
|
+
session_id = excluded.session_id,
|
|
9521
|
+
status = excluded.status,
|
|
9522
|
+
freshness = 'current',
|
|
9523
|
+
stale_reason = NULL,
|
|
9524
|
+
files_json = excluded.files_json,
|
|
9525
|
+
related_entities_json = excluded.related_entities_json,
|
|
9526
|
+
updated_at = excluded.updated_at
|
|
9527
|
+
`).run(
|
|
9528
|
+
card.id,
|
|
9529
|
+
card.projectId,
|
|
9530
|
+
card.candidateKind,
|
|
9531
|
+
card.candidateId,
|
|
9532
|
+
card.title,
|
|
9533
|
+
card.summary,
|
|
9534
|
+
card.entityName ?? null,
|
|
9535
|
+
card.sourceKind,
|
|
9536
|
+
card.sourceRef,
|
|
9537
|
+
card.locator ?? null,
|
|
9538
|
+
card.capturedHash ?? null,
|
|
9539
|
+
card.sessionId ?? null,
|
|
9540
|
+
card.status,
|
|
9541
|
+
card.verification,
|
|
9542
|
+
card.freshness,
|
|
9543
|
+
JSON.stringify(card.files),
|
|
9544
|
+
JSON.stringify(card.relatedEntities),
|
|
9545
|
+
card.createdAt,
|
|
9546
|
+
card.updatedAt
|
|
9547
|
+
);
|
|
9548
|
+
return this.get(card.projectId, card.candidateKind, card.candidateId) ?? card;
|
|
9549
|
+
}
|
|
9550
|
+
get(projectId, candidateKind, candidateId) {
|
|
9551
|
+
const row = this.requireDb().prepare(`
|
|
9552
|
+
SELECT * FROM evidence_cards WHERE project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
9553
|
+
`).get(projectId, candidateKind, candidateId);
|
|
9554
|
+
return row ? rowToCard(row) : void 0;
|
|
9555
|
+
}
|
|
9556
|
+
list(projectId, options = {}) {
|
|
9557
|
+
const limit2 = Math.min(100, Math.max(1, Math.floor(options.limit ?? 20)));
|
|
9558
|
+
const clauses = ["project_id = ?"];
|
|
9559
|
+
const args = [projectId];
|
|
9560
|
+
if (options.freshness) {
|
|
9561
|
+
clauses.push("freshness = ?");
|
|
9562
|
+
args.push(options.freshness);
|
|
9563
|
+
}
|
|
9564
|
+
if (options.status) {
|
|
9565
|
+
clauses.push("status = ?");
|
|
9566
|
+
args.push(options.status);
|
|
9567
|
+
}
|
|
9568
|
+
args.push(limit2);
|
|
9569
|
+
const rows = this.requireDb().prepare(`
|
|
9570
|
+
SELECT * FROM evidence_cards WHERE ${clauses.join(" AND ")} ORDER BY updated_at DESC, id DESC LIMIT ?
|
|
9571
|
+
`).all(...args);
|
|
9572
|
+
return rows.map(rowToCard);
|
|
9573
|
+
}
|
|
9574
|
+
syncObservations(observations2) {
|
|
9575
|
+
return observations2.map((observation) => this.upsertObservation(observation));
|
|
9576
|
+
}
|
|
9577
|
+
markStaleForPaths(projectId, paths, reason = "source file changed") {
|
|
9578
|
+
const normalized = new Set(paths.map((value) => value.replace(/\\/g, "/").toLowerCase()));
|
|
9579
|
+
if (normalized.size === 0) return 0;
|
|
9580
|
+
const db2 = this.requireDb();
|
|
9581
|
+
const rows = db2.prepare(`SELECT * FROM evidence_cards WHERE project_id = ? AND freshness != 'stale'`).all(projectId);
|
|
9582
|
+
const update2 = db2.prepare(`
|
|
9583
|
+
UPDATE evidence_cards SET freshness = 'stale', stale_reason = ?, updated_at = ?
|
|
9584
|
+
WHERE id = ?
|
|
9585
|
+
`);
|
|
9586
|
+
let changed = 0;
|
|
9587
|
+
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
9588
|
+
const run = db2.transaction(() => {
|
|
9589
|
+
for (const row of rows) {
|
|
9590
|
+
const files = safeJson(row.files_json, []);
|
|
9591
|
+
if (!files.some((file) => normalized.has(file.replace(/\\/g, "/").toLowerCase()))) continue;
|
|
9592
|
+
update2.run(reason, now3, row.id);
|
|
9593
|
+
changed++;
|
|
9594
|
+
}
|
|
9595
|
+
});
|
|
9596
|
+
run();
|
|
9597
|
+
return changed;
|
|
9598
|
+
}
|
|
9599
|
+
setVerification(projectId, cardId, verification) {
|
|
9600
|
+
this.requireDb().prepare(`
|
|
9601
|
+
UPDATE evidence_cards SET verification = ?, updated_at = ? WHERE project_id = ? AND id = ?
|
|
9602
|
+
`).run(verification, (/* @__PURE__ */ new Date()).toISOString(), projectId, cardId);
|
|
9603
|
+
}
|
|
9604
|
+
recordEvent(projectId, cardId, kind, detail) {
|
|
9605
|
+
const event = {
|
|
9606
|
+
id: randomUUID3(),
|
|
9607
|
+
projectId,
|
|
9608
|
+
cardId,
|
|
9609
|
+
kind,
|
|
9610
|
+
...detail ? { detail: detail.slice(0, 2e3) } : {},
|
|
9611
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
9612
|
+
};
|
|
9613
|
+
this.requireDb().prepare(`
|
|
9614
|
+
INSERT INTO evidence_card_events (id, project_id, card_id, kind, detail, created_at)
|
|
9615
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
9616
|
+
`).run(event.id, event.projectId, event.cardId, event.kind, event.detail ?? null, event.createdAt);
|
|
9617
|
+
return event;
|
|
9618
|
+
}
|
|
9619
|
+
listEvents(cardId, limit2 = 50) {
|
|
9620
|
+
const rows = this.requireDb().prepare(`
|
|
9621
|
+
SELECT * FROM evidence_card_events WHERE card_id = ? ORDER BY created_at DESC LIMIT ?
|
|
9622
|
+
`).all(cardId, Math.min(200, Math.max(1, Math.floor(limit2))));
|
|
9623
|
+
return rows.map((row) => ({
|
|
9624
|
+
id: String(row.id),
|
|
9625
|
+
projectId: String(row.project_id),
|
|
9626
|
+
cardId: String(row.card_id),
|
|
9627
|
+
kind: String(row.kind),
|
|
9628
|
+
...row.detail ? { detail: String(row.detail) } : {},
|
|
9629
|
+
createdAt: String(row.created_at)
|
|
9630
|
+
}));
|
|
9631
|
+
}
|
|
9632
|
+
};
|
|
9633
|
+
}
|
|
9634
|
+
});
|
|
9635
|
+
|
|
9306
9636
|
// src/runtime/isolated-maintenance.ts
|
|
9307
9637
|
import { spawn } from "child_process";
|
|
9308
9638
|
import { existsSync as existsSync8 } from "fs";
|
|
@@ -9464,7 +9794,7 @@ var workspace_store_exports = {};
|
|
|
9464
9794
|
__export(workspace_store_exports, {
|
|
9465
9795
|
KnowledgeWorkspaceStore: () => KnowledgeWorkspaceStore
|
|
9466
9796
|
});
|
|
9467
|
-
import { randomUUID as
|
|
9797
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
9468
9798
|
function arrayValue(raw) {
|
|
9469
9799
|
if (typeof raw !== "string" || !raw) return [];
|
|
9470
9800
|
try {
|
|
@@ -9605,7 +9935,7 @@ var init_workspace_store = __esm({
|
|
|
9605
9935
|
}
|
|
9606
9936
|
createProposal(input) {
|
|
9607
9937
|
const proposal = {
|
|
9608
|
-
id: input.id ??
|
|
9938
|
+
id: input.id ?? randomUUID4(),
|
|
9609
9939
|
...input,
|
|
9610
9940
|
status: input.status ?? "pending",
|
|
9611
9941
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -9658,13 +9988,13 @@ __export(workspace_exports, {
|
|
|
9658
9988
|
loadKnowledgeWorkspace: () => loadKnowledgeWorkspace,
|
|
9659
9989
|
resolveKnowledgeWorkspaceFile: () => resolveKnowledgeWorkspaceFile
|
|
9660
9990
|
});
|
|
9661
|
-
import { createHash as
|
|
9991
|
+
import { createHash as createHash4 } from "crypto";
|
|
9662
9992
|
import { execFile } from "child_process";
|
|
9663
9993
|
import { promises as fs9 } from "fs";
|
|
9664
9994
|
import path13 from "path";
|
|
9665
9995
|
import { promisify } from "util";
|
|
9666
9996
|
function hash(value) {
|
|
9667
|
-
return
|
|
9997
|
+
return createHash4("sha256").update(value).digest("hex");
|
|
9668
9998
|
}
|
|
9669
9999
|
function workspaceId(projectId, mode) {
|
|
9670
10000
|
return "workspace:" + hash(projectId + ":" + mode).slice(0, 24);
|
|
@@ -10264,7 +10594,7 @@ var media_store_exports = {};
|
|
|
10264
10594
|
__export(media_store_exports, {
|
|
10265
10595
|
MediaStore: () => MediaStore
|
|
10266
10596
|
});
|
|
10267
|
-
import { randomUUID as
|
|
10597
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
10268
10598
|
function asOptionalText(value) {
|
|
10269
10599
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
10270
10600
|
}
|
|
@@ -10434,7 +10764,7 @@ var init_media_store = __esm({
|
|
|
10434
10764
|
return { asset: this.getAsset(input.projectId, existing.id), deduplicated: true };
|
|
10435
10765
|
}
|
|
10436
10766
|
const asset = {
|
|
10437
|
-
id:
|
|
10767
|
+
id: randomUUID5(),
|
|
10438
10768
|
...input,
|
|
10439
10769
|
createdAt: now3,
|
|
10440
10770
|
updatedAt: now3
|
|
@@ -10514,7 +10844,7 @@ var init_media_store = __esm({
|
|
|
10514
10844
|
`).get(input.assetId, input.observationId ?? null, input.role);
|
|
10515
10845
|
if (existing) return rowToLink(existing);
|
|
10516
10846
|
const link = {
|
|
10517
|
-
id:
|
|
10847
|
+
id: randomUUID5(),
|
|
10518
10848
|
assetId: input.assetId,
|
|
10519
10849
|
projectId: input.projectId,
|
|
10520
10850
|
...input.observationId !== void 0 ? { observationId: input.observationId } : {},
|
|
@@ -10553,7 +10883,7 @@ var init_media_store = __esm({
|
|
|
10553
10883
|
return rowToDerivation(this.db.prepare("SELECT * FROM media_derivations WHERE id = ?").get(existing.id));
|
|
10554
10884
|
}
|
|
10555
10885
|
const derivation = {
|
|
10556
|
-
id:
|
|
10886
|
+
id: randomUUID5(),
|
|
10557
10887
|
...input,
|
|
10558
10888
|
content,
|
|
10559
10889
|
...error ? { error } : {},
|
|
@@ -10640,7 +10970,7 @@ var init_media_store = __esm({
|
|
|
10640
10970
|
createJob(input) {
|
|
10641
10971
|
const now3 = Date.now();
|
|
10642
10972
|
const job = {
|
|
10643
|
-
id:
|
|
10973
|
+
id: randomUUID5(),
|
|
10644
10974
|
projectId: input.projectId,
|
|
10645
10975
|
kind: input.kind,
|
|
10646
10976
|
status: "queued",
|
|
@@ -10816,14 +11146,14 @@ __export(asset_store_exports, {
|
|
|
10816
11146
|
readMediaAsset: () => readMediaAsset,
|
|
10817
11147
|
removeMediaAsset: () => removeMediaAsset
|
|
10818
11148
|
});
|
|
10819
|
-
import { createHash as
|
|
11149
|
+
import { createHash as createHash5, randomUUID as randomUUID6 } from "crypto";
|
|
10820
11150
|
import { copyFile, lstat, mkdir as mkdir3, open, readFile as readFile3, readdir, rename as rename2, rm, stat as stat2, writeFile as writeFile3 } from "fs/promises";
|
|
10821
11151
|
import path14 from "path";
|
|
10822
11152
|
function mediaRoot(dataDir) {
|
|
10823
11153
|
return path14.resolve(dataDir, "media");
|
|
10824
11154
|
}
|
|
10825
11155
|
function projectStorageKey(projectId) {
|
|
10826
|
-
return
|
|
11156
|
+
return createHash5("sha256").update(projectId).digest("hex").slice(0, 16);
|
|
10827
11157
|
}
|
|
10828
11158
|
function validateUnderRoot(root, candidate) {
|
|
10829
11159
|
const resolved = path14.resolve(candidate);
|
|
@@ -10883,14 +11213,14 @@ async function readHeader(filePath, bytes = 32) {
|
|
|
10883
11213
|
}
|
|
10884
11214
|
async function sha256File(filePath) {
|
|
10885
11215
|
const bytes = await readFile3(filePath);
|
|
10886
|
-
return
|
|
11216
|
+
return createHash5("sha256").update(bytes).digest("hex");
|
|
10887
11217
|
}
|
|
10888
11218
|
function destinationFor(root, projectId, sha256, extension3) {
|
|
10889
11219
|
const relative3 = path14.join("assets", projectStorageKey(projectId), sha256.slice(0, 2), `${sha256}${extension3}`);
|
|
10890
11220
|
return { relative: relative3, absolute: validateUnderRoot(root, path14.join(root, relative3)) };
|
|
10891
11221
|
}
|
|
10892
11222
|
function deletionStagingPath(root, assetId) {
|
|
10893
|
-
return validateUnderRoot(root, path14.join(root, ".trash", `${assetId}.${
|
|
11223
|
+
return validateUnderRoot(root, path14.join(root, ".trash", `${assetId}.${randomUUID6()}.pending-delete`));
|
|
10894
11224
|
}
|
|
10895
11225
|
async function destinationExists(destination) {
|
|
10896
11226
|
try {
|
|
@@ -10904,7 +11234,7 @@ async function destinationExists(destination) {
|
|
|
10904
11234
|
async function persistFile(source, destination) {
|
|
10905
11235
|
await mkdir3(path14.dirname(destination), { recursive: true });
|
|
10906
11236
|
if (await destinationExists(destination)) return false;
|
|
10907
|
-
const temporary = `${destination}.${
|
|
11237
|
+
const temporary = `${destination}.${randomUUID6()}.tmp`;
|
|
10908
11238
|
try {
|
|
10909
11239
|
await copyFile(source, temporary);
|
|
10910
11240
|
await rename2(temporary, destination);
|
|
@@ -10920,7 +11250,7 @@ async function persistFile(source, destination) {
|
|
|
10920
11250
|
async function persistBuffer(bytes, destination) {
|
|
10921
11251
|
await mkdir3(path14.dirname(destination), { recursive: true });
|
|
10922
11252
|
if (await destinationExists(destination)) return false;
|
|
10923
|
-
const temporary = `${destination}.${
|
|
11253
|
+
const temporary = `${destination}.${randomUUID6()}.tmp`;
|
|
10924
11254
|
try {
|
|
10925
11255
|
await writeFile3(temporary, bytes, { flag: "wx" });
|
|
10926
11256
|
await rename2(temporary, destination);
|
|
@@ -10989,7 +11319,7 @@ async function importMediaBuffer(input) {
|
|
|
10989
11319
|
if (input.bytes.length === 0) throw new Error("Media import rejects empty payloads");
|
|
10990
11320
|
if (input.bytes.length > maxBytes) throw new Error(`Media payload is too large (${input.bytes.length} bytes; limit ${maxBytes})`);
|
|
10991
11321
|
const detected = detectMedia(input.bytes.subarray(0, 32));
|
|
10992
|
-
const sha256 =
|
|
11322
|
+
const sha256 = createHash5("sha256").update(input.bytes).digest("hex");
|
|
10993
11323
|
return importKnownMedia({
|
|
10994
11324
|
dataDir: input.dataDir,
|
|
10995
11325
|
projectId: input.projectId,
|
|
@@ -11007,7 +11337,7 @@ async function readMediaAsset(dataDir, asset, maxBytes = DEFAULT_MAX_MEDIA_BYTES
|
|
|
11007
11337
|
if (asset.byteSize > maxBytes) throw new Error(`Media asset exceeds read limit (${asset.byteSize} bytes; limit ${maxBytes})`);
|
|
11008
11338
|
const bytes = await readFile3(getMediaAssetPath(dataDir, asset));
|
|
11009
11339
|
if (bytes.length !== asset.byteSize) throw new Error(`Media asset size no longer matches metadata: ${asset.id}`);
|
|
11010
|
-
const sha256 =
|
|
11340
|
+
const sha256 = createHash5("sha256").update(bytes).digest("hex");
|
|
11011
11341
|
if (sha256 !== asset.sha256) throw new Error(`Media asset hash no longer matches metadata: ${asset.id}`);
|
|
11012
11342
|
return bytes;
|
|
11013
11343
|
}
|
|
@@ -63877,7 +64207,7 @@ var require_gaxios = __commonJS({
|
|
|
63877
64207
|
var retry_js_1 = require_retry3();
|
|
63878
64208
|
var stream_1 = __require("stream");
|
|
63879
64209
|
var interceptor_js_1 = require_interceptor();
|
|
63880
|
-
var
|
|
64210
|
+
var randomUUID19 = async () => globalThis.crypto?.randomUUID() || (await import("crypto")).randomUUID();
|
|
63881
64211
|
var HTTP_STATUS_NO_CONTENT = 204;
|
|
63882
64212
|
var Gaxios = class {
|
|
63883
64213
|
agentCache = /* @__PURE__ */ new Map();
|
|
@@ -64150,7 +64480,7 @@ var require_gaxios = __commonJS({
|
|
|
64150
64480
|
*/
|
|
64151
64481
|
["Blob", "File", "FormData"].includes(opts.data?.constructor?.name || "");
|
|
64152
64482
|
if (opts.multipart?.length) {
|
|
64153
|
-
const boundary = await
|
|
64483
|
+
const boundary = await randomUUID19();
|
|
64154
64484
|
preparedHeaders.set("content-type", `multipart/related; boundary=${boundary}`);
|
|
64155
64485
|
opts.body = stream_1.Readable.from(this.getMultipartRequest(opts.multipart, boundary));
|
|
64156
64486
|
} else if (shouldDirectlyPassData) {
|
|
@@ -76377,7 +76707,7 @@ var require_websocket = __commonJS({
|
|
|
76377
76707
|
var http3 = __require("http");
|
|
76378
76708
|
var net = __require("net");
|
|
76379
76709
|
var tls = __require("tls");
|
|
76380
|
-
var { randomBytes: randomBytes2, createHash:
|
|
76710
|
+
var { randomBytes: randomBytes2, createHash: createHash17 } = __require("crypto");
|
|
76381
76711
|
var { Duplex, Readable: Readable2 } = __require("stream");
|
|
76382
76712
|
var { URL: URL2 } = __require("url");
|
|
76383
76713
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -77045,7 +77375,7 @@ var require_websocket = __commonJS({
|
|
|
77045
77375
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
77046
77376
|
return;
|
|
77047
77377
|
}
|
|
77048
|
-
const digest2 =
|
|
77378
|
+
const digest2 = createHash17("sha1").update(key + GUID).digest("base64");
|
|
77049
77379
|
if (res.headers["sec-websocket-accept"] !== digest2) {
|
|
77050
77380
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
77051
77381
|
return;
|
|
@@ -77417,7 +77747,7 @@ var require_websocket_server = __commonJS({
|
|
|
77417
77747
|
var EventEmitter2 = __require("events");
|
|
77418
77748
|
var http3 = __require("http");
|
|
77419
77749
|
var { Duplex } = __require("stream");
|
|
77420
|
-
var { createHash:
|
|
77750
|
+
var { createHash: createHash17 } = __require("crypto");
|
|
77421
77751
|
var extension3 = require_extension();
|
|
77422
77752
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
77423
77753
|
var subprotocol2 = require_subprotocol();
|
|
@@ -77724,7 +78054,7 @@ var require_websocket_server = __commonJS({
|
|
|
77724
78054
|
);
|
|
77725
78055
|
}
|
|
77726
78056
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
77727
|
-
const digest2 =
|
|
78057
|
+
const digest2 = createHash17("sha1").update(key + GUID).digest("base64");
|
|
77728
78058
|
const headers = [
|
|
77729
78059
|
"HTTP/1.1 101 Switching Protocols",
|
|
77730
78060
|
"Upgrade: websocket",
|
|
@@ -144978,6 +145308,186 @@ var init_audio_jobs = __esm({
|
|
|
144978
145308
|
}
|
|
144979
145309
|
});
|
|
144980
145310
|
|
|
145311
|
+
// src/memory/feedback-model.ts
|
|
145312
|
+
function feedbackWeightMultiplier(weight) {
|
|
145313
|
+
return Math.max(0.35, Math.min(1.4, 0.35 + Math.max(0, Math.min(2, weight)) * 0.525));
|
|
145314
|
+
}
|
|
145315
|
+
var init_feedback_model = __esm({
|
|
145316
|
+
"src/memory/feedback-model.ts"() {
|
|
145317
|
+
"use strict";
|
|
145318
|
+
init_esm_shims();
|
|
145319
|
+
}
|
|
145320
|
+
});
|
|
145321
|
+
|
|
145322
|
+
// src/memory/feedback.ts
|
|
145323
|
+
var feedback_exports = {};
|
|
145324
|
+
__export(feedback_exports, {
|
|
145325
|
+
FEEDBACK_DELTAS: () => FEEDBACK_DELTAS,
|
|
145326
|
+
MemoryFeedbackStore: () => MemoryFeedbackStore,
|
|
145327
|
+
applyMemoryFeedback: () => applyMemoryFeedback,
|
|
145328
|
+
feedbackWeightMultiplier: () => feedbackWeightMultiplier
|
|
145329
|
+
});
|
|
145330
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
145331
|
+
function applyMemoryFeedback(current, event) {
|
|
145332
|
+
const delta = event.signal === "revoke" ? 0 : FEEDBACK_DELTAS[event.signal];
|
|
145333
|
+
const weight = Math.max(0, Math.min(2, current.weight + delta));
|
|
145334
|
+
const status = (event.signal === "code-conflict" || event.signal === "user-correction" || event.signal === "weaken") && weight < 0.5 ? "archived" : current.status;
|
|
145335
|
+
return { weight, status, audit: [...current.audit, { ...event }] };
|
|
145336
|
+
}
|
|
145337
|
+
function rowToEvent(row) {
|
|
145338
|
+
return {
|
|
145339
|
+
id: String(row.id),
|
|
145340
|
+
projectId: String(row.project_id),
|
|
145341
|
+
candidateKind: row.candidate_kind,
|
|
145342
|
+
candidateId: String(row.candidate_id),
|
|
145343
|
+
signal: row.signal,
|
|
145344
|
+
...row.observed_at ? { at: String(row.observed_at) } : { at: (/* @__PURE__ */ new Date()).toISOString() },
|
|
145345
|
+
...row.actor ? { actor: String(row.actor) } : {},
|
|
145346
|
+
...row.note ? { note: String(row.note) } : {},
|
|
145347
|
+
...row.source_ref ? { sourceRef: String(row.source_ref) } : {},
|
|
145348
|
+
...row.target_event_id ? { targetEventId: String(row.target_event_id) } : {},
|
|
145349
|
+
delta: Number(row.delta ?? 0)
|
|
145350
|
+
};
|
|
145351
|
+
}
|
|
145352
|
+
var FEEDBACK_DELTAS, MemoryFeedbackStore;
|
|
145353
|
+
var init_feedback = __esm({
|
|
145354
|
+
"src/memory/feedback.ts"() {
|
|
145355
|
+
"use strict";
|
|
145356
|
+
init_esm_shims();
|
|
145357
|
+
init_sqlite_db();
|
|
145358
|
+
init_feedback_model();
|
|
145359
|
+
FEEDBACK_DELTAS = {
|
|
145360
|
+
"user-correction": -0.35,
|
|
145361
|
+
"verification-success": 0.25,
|
|
145362
|
+
"verification-failure": -0.25,
|
|
145363
|
+
"code-change": -0.15,
|
|
145364
|
+
used: 0.1,
|
|
145365
|
+
"not-used": -0.05,
|
|
145366
|
+
"code-conflict": -0.4,
|
|
145367
|
+
strengthen: 0.2,
|
|
145368
|
+
weaken: -0.2
|
|
145369
|
+
};
|
|
145370
|
+
MemoryFeedbackStore = class {
|
|
145371
|
+
db = null;
|
|
145372
|
+
async init(dataDir) {
|
|
145373
|
+
this.db = getDatabase(dataDir);
|
|
145374
|
+
}
|
|
145375
|
+
requireDb() {
|
|
145376
|
+
if (!this.db) throw new Error("MemoryFeedbackStore is not initialized.");
|
|
145377
|
+
return this.db;
|
|
145378
|
+
}
|
|
145379
|
+
loadEvents(projectId, candidateKind, candidateId) {
|
|
145380
|
+
return this.requireDb().prepare(`
|
|
145381
|
+
SELECT * FROM memory_feedback_events
|
|
145382
|
+
WHERE project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
145383
|
+
ORDER BY observed_at ASC, rowid ASC
|
|
145384
|
+
`).all(projectId, candidateKind, candidateId).map(rowToEvent);
|
|
145385
|
+
}
|
|
145386
|
+
rebuild(projectId, candidateKind, candidateId) {
|
|
145387
|
+
const events = this.loadEvents(projectId, candidateKind, candidateId);
|
|
145388
|
+
const revoked = new Set(events.filter((event) => event.signal === "revoke" && event.targetEventId).map((event) => event.targetEventId));
|
|
145389
|
+
let state = { weight: 1, status: "active", audit: [] };
|
|
145390
|
+
for (const event of events) {
|
|
145391
|
+
if (event.signal === "revoke" || revoked.has(event.id)) {
|
|
145392
|
+
state.audit.push(event);
|
|
145393
|
+
continue;
|
|
145394
|
+
}
|
|
145395
|
+
state = applyMemoryFeedback(state, event);
|
|
145396
|
+
}
|
|
145397
|
+
this.requireDb().prepare(`
|
|
145398
|
+
INSERT INTO memory_feedback_states (project_id, candidate_kind, candidate_id, weight, lifecycle_status, updated_at)
|
|
145399
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
145400
|
+
ON CONFLICT(project_id, candidate_kind, candidate_id) DO UPDATE SET
|
|
145401
|
+
weight = excluded.weight, lifecycle_status = excluded.lifecycle_status, updated_at = excluded.updated_at
|
|
145402
|
+
`).run(projectId, candidateKind, candidateId, state.weight, state.status, (/* @__PURE__ */ new Date()).toISOString());
|
|
145403
|
+
return state;
|
|
145404
|
+
}
|
|
145405
|
+
getState(projectId, candidateKind, candidateId) {
|
|
145406
|
+
const row = this.requireDb().prepare(`
|
|
145407
|
+
SELECT weight, lifecycle_status FROM memory_feedback_states
|
|
145408
|
+
WHERE project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
145409
|
+
`).get(projectId, candidateKind, candidateId);
|
|
145410
|
+
if (!row) return { weight: 1, status: "active", audit: [] };
|
|
145411
|
+
return {
|
|
145412
|
+
weight: Number(row.weight ?? 1),
|
|
145413
|
+
status: row.lifecycle_status ?? "active",
|
|
145414
|
+
audit: this.loadEvents(projectId, candidateKind, candidateId)
|
|
145415
|
+
};
|
|
145416
|
+
}
|
|
145417
|
+
listStates(projectId, candidateKind = "observation") {
|
|
145418
|
+
return this.requireDb().prepare(`
|
|
145419
|
+
SELECT candidate_id, weight, lifecycle_status, updated_at
|
|
145420
|
+
FROM memory_feedback_states WHERE project_id = ? AND candidate_kind = ?
|
|
145421
|
+
ORDER BY updated_at DESC
|
|
145422
|
+
`).all(projectId, candidateKind).map((row) => ({
|
|
145423
|
+
candidateId: String(row.candidate_id),
|
|
145424
|
+
weight: Number(row.weight),
|
|
145425
|
+
status: row.lifecycle_status,
|
|
145426
|
+
updatedAt: String(row.updated_at)
|
|
145427
|
+
}));
|
|
145428
|
+
}
|
|
145429
|
+
weights(projectId, candidateKind = "observation") {
|
|
145430
|
+
const states = /* @__PURE__ */ new Map();
|
|
145431
|
+
for (const row of this.listStates(projectId, candidateKind)) {
|
|
145432
|
+
states.set(row.candidateId, this.getState(projectId, candidateKind, row.candidateId));
|
|
145433
|
+
}
|
|
145434
|
+
return states;
|
|
145435
|
+
}
|
|
145436
|
+
record(input) {
|
|
145437
|
+
if (input.signal === "revoke" && !input.targetEventId) {
|
|
145438
|
+
throw new Error("A revoke feedback event requires targetEventId.");
|
|
145439
|
+
}
|
|
145440
|
+
if (input.signal === "revoke") {
|
|
145441
|
+
const target = this.requireDb().prepare(`
|
|
145442
|
+
SELECT 1 FROM memory_feedback_events
|
|
145443
|
+
WHERE id = ? AND project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
145444
|
+
`).get(input.targetEventId, input.projectId, input.candidateKind, input.candidateId);
|
|
145445
|
+
if (!target) throw new Error("The feedback event to revoke was not found in the same candidate scope.");
|
|
145446
|
+
}
|
|
145447
|
+
const event = {
|
|
145448
|
+
id: randomUUID7(),
|
|
145449
|
+
projectId: input.projectId,
|
|
145450
|
+
candidateKind: input.candidateKind,
|
|
145451
|
+
candidateId: input.candidateId,
|
|
145452
|
+
signal: input.signal,
|
|
145453
|
+
sourceRef: input.sourceRef,
|
|
145454
|
+
...input.actor ? { actor: input.actor } : {},
|
|
145455
|
+
...input.note ? { note: input.note.slice(0, 2e3) } : {},
|
|
145456
|
+
...input.targetEventId ? { targetEventId: input.targetEventId } : {},
|
|
145457
|
+
at: input.at ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
145458
|
+
delta: input.signal === "revoke" ? 0 : FEEDBACK_DELTAS[input.signal]
|
|
145459
|
+
};
|
|
145460
|
+
this.requireDb().prepare(`
|
|
145461
|
+
INSERT INTO memory_feedback_events (
|
|
145462
|
+
id, project_id, candidate_kind, candidate_id, signal, actor, note,
|
|
145463
|
+
source_ref, target_event_id, delta, observed_at
|
|
145464
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
145465
|
+
`).run(
|
|
145466
|
+
event.id,
|
|
145467
|
+
event.projectId,
|
|
145468
|
+
event.candidateKind,
|
|
145469
|
+
event.candidateId,
|
|
145470
|
+
event.signal,
|
|
145471
|
+
event.actor ?? null,
|
|
145472
|
+
event.note ?? null,
|
|
145473
|
+
event.sourceRef,
|
|
145474
|
+
event.targetEventId ?? null,
|
|
145475
|
+
event.delta,
|
|
145476
|
+
event.at
|
|
145477
|
+
);
|
|
145478
|
+
return { event, state: this.rebuild(input.projectId, input.candidateKind, input.candidateId) };
|
|
145479
|
+
}
|
|
145480
|
+
audit(projectId, candidateKind, candidateId, limit2 = 100) {
|
|
145481
|
+
return this.requireDb().prepare(`
|
|
145482
|
+
SELECT * FROM memory_feedback_events
|
|
145483
|
+
WHERE project_id = ? AND candidate_kind = ? AND candidate_id = ?
|
|
145484
|
+
ORDER BY observed_at DESC, rowid DESC LIMIT ?
|
|
145485
|
+
`).all(projectId, candidateKind, candidateId, Math.min(200, Math.max(1, Math.floor(limit2)))).map(rowToEvent);
|
|
145486
|
+
}
|
|
145487
|
+
};
|
|
145488
|
+
}
|
|
145489
|
+
});
|
|
145490
|
+
|
|
144981
145491
|
// src/memory/retention.ts
|
|
144982
145492
|
var retention_exports = {};
|
|
144983
145493
|
__export(retention_exports, {
|
|
@@ -145019,6 +145529,7 @@ function getEffectiveRetentionDays(doc) {
|
|
|
145019
145529
|
}
|
|
145020
145530
|
function isImmune(doc) {
|
|
145021
145531
|
if (doc.type === "probe") return false;
|
|
145532
|
+
if (doc.feedbackStatus === "archived") return false;
|
|
145022
145533
|
if (doc.admissionState === "candidate" || doc.admissionState === "ephemeral") return false;
|
|
145023
145534
|
if (doc.valueCategory === "core") return true;
|
|
145024
145535
|
const importance = getImportanceLevel(doc);
|
|
@@ -145051,7 +145562,8 @@ function calculateRelevance(doc, referenceTime) {
|
|
|
145051
145562
|
const decayFactor = Math.exp(-ageDays / retention);
|
|
145052
145563
|
const accessCount = doc.accessCount ?? 0;
|
|
145053
145564
|
const accessBoost = Math.min(2, 1 + 0.1 * accessCount);
|
|
145054
|
-
|
|
145565
|
+
const feedbackMultiplier = doc.feedbackWeight === void 0 ? 1 : feedbackWeightMultiplier(doc.feedbackWeight);
|
|
145566
|
+
let totalScore = base * decayFactor * accessBoost * feedbackMultiplier;
|
|
145055
145567
|
const immune = isImmune(doc);
|
|
145056
145568
|
if (immune) {
|
|
145057
145569
|
totalScore = Math.max(totalScore, 0.5);
|
|
@@ -145063,7 +145575,8 @@ function calculateRelevance(doc, referenceTime) {
|
|
|
145063
145575
|
decayFactor,
|
|
145064
145576
|
accessBoost,
|
|
145065
145577
|
ageDays,
|
|
145066
|
-
isImmune: immune
|
|
145578
|
+
isImmune: immune,
|
|
145579
|
+
feedbackMultiplier
|
|
145067
145580
|
};
|
|
145068
145581
|
}
|
|
145069
145582
|
function rankByRelevance(docs, referenceTime) {
|
|
@@ -145071,6 +145584,7 @@ function rankByRelevance(docs, referenceTime) {
|
|
|
145071
145584
|
}
|
|
145072
145585
|
function getRetentionZone(doc, referenceTime) {
|
|
145073
145586
|
const now3 = referenceTime ?? /* @__PURE__ */ new Date();
|
|
145587
|
+
if (doc.feedbackStatus === "archived") return "archive-candidate";
|
|
145074
145588
|
const importance = getImportanceLevel(doc);
|
|
145075
145589
|
const retention = getEffectiveRetentionDays(doc);
|
|
145076
145590
|
const createdAt = new Date(doc.createdAt);
|
|
@@ -145142,7 +145656,7 @@ function explainRetention(doc, referenceTime) {
|
|
|
145142
145656
|
summary: parts.join(" ; ")
|
|
145143
145657
|
};
|
|
145144
145658
|
}
|
|
145145
|
-
function toRetentionDocument(obs, accessMap) {
|
|
145659
|
+
function toRetentionDocument(obs, accessMap, feedback) {
|
|
145146
145660
|
const access3 = accessMap?.get(obs.id);
|
|
145147
145661
|
return {
|
|
145148
145662
|
id: `obs-${obs.id}`,
|
|
@@ -145164,11 +145678,12 @@ function toRetentionDocument(obs, accessMap) {
|
|
|
145164
145678
|
sourceDetail: obs.sourceDetail ?? "",
|
|
145165
145679
|
valueCategory: obs.valueCategory ?? "",
|
|
145166
145680
|
admissionState: obs.admissionState ?? "",
|
|
145167
|
-
admissionReason: obs.admissionReason ?? ""
|
|
145681
|
+
admissionReason: obs.admissionReason ?? "",
|
|
145682
|
+
...feedback ? { feedbackWeight: feedback.weight, feedbackStatus: feedback.status } : {}
|
|
145168
145683
|
};
|
|
145169
145684
|
}
|
|
145170
145685
|
function projectObservationRetention(observation, options = {}) {
|
|
145171
|
-
const document2 = toRetentionDocument(observation, options.accessMap);
|
|
145686
|
+
const document2 = toRetentionDocument(observation, options.accessMap, options.feedback);
|
|
145172
145687
|
const relevance = calculateRelevance(document2, options.referenceTime);
|
|
145173
145688
|
const explanation = explainRetention(document2, options.referenceTime);
|
|
145174
145689
|
return {
|
|
@@ -145193,7 +145708,17 @@ function summarizeRetentionProjections(projections) {
|
|
|
145193
145708
|
}
|
|
145194
145709
|
return { active, stale, archiveCandidates, immune };
|
|
145195
145710
|
}
|
|
145196
|
-
async function
|
|
145711
|
+
async function loadFeedbackStore(dataDir) {
|
|
145712
|
+
try {
|
|
145713
|
+
const { MemoryFeedbackStore: MemoryFeedbackStore2 } = await Promise.resolve().then(() => (init_feedback(), feedback_exports));
|
|
145714
|
+
const store = new MemoryFeedbackStore2();
|
|
145715
|
+
await store.init(dataDir);
|
|
145716
|
+
return store;
|
|
145717
|
+
} catch {
|
|
145718
|
+
return void 0;
|
|
145719
|
+
}
|
|
145720
|
+
}
|
|
145721
|
+
async function archiveExpiredBatch(projectDir2, options) {
|
|
145197
145722
|
const store = getObservationStore();
|
|
145198
145723
|
const limit2 = Math.min(500, Math.max(1, Math.floor(options.limit ?? 100)));
|
|
145199
145724
|
const afterId = Math.max(0, Math.floor(options.afterId ?? 0));
|
|
@@ -145202,11 +145727,13 @@ async function archiveExpiredBatch(_projectDir, options) {
|
|
|
145202
145727
|
afterId,
|
|
145203
145728
|
limit: limit2 + 1
|
|
145204
145729
|
});
|
|
145730
|
+
const feedback = await loadFeedbackStore(projectDir2);
|
|
145205
145731
|
const hasMore = page.length > limit2;
|
|
145206
145732
|
const scanned = hasMore ? page.slice(0, limit2) : page;
|
|
145207
145733
|
const candidateIds = scanned.filter((observation) => !options.reader || canManageObservation(observation, options.reader)).filter((observation) => projectObservationRetention(observation, {
|
|
145208
145734
|
accessMap: options.accessMap,
|
|
145209
|
-
referenceTime: options.referenceTime
|
|
145735
|
+
referenceTime: options.referenceTime,
|
|
145736
|
+
...feedback ? { feedback: feedback.getState(options.projectId, "observation", String(observation.id)) } : {}
|
|
145210
145737
|
}).zone === "archive-candidate").map((observation) => observation.id);
|
|
145211
145738
|
const archived = candidateIds.length === 0 ? 0 : await store.atomic(async (tx) => {
|
|
145212
145739
|
const updates = await Promise.all(
|
|
@@ -145237,6 +145764,7 @@ async function archiveExpired(projectDir2, referenceTime, accessMap, projectId,
|
|
|
145237
145764
|
const remaining = reader2 ? remainingObservations.filter((observation) => canManageObservation(observation, reader2)).length : remainingObservations.length;
|
|
145238
145765
|
return { archived, remaining };
|
|
145239
145766
|
}
|
|
145767
|
+
const feedback = await loadFeedbackStore(projectDir2);
|
|
145240
145768
|
return await store.atomic(async (tx) => {
|
|
145241
145769
|
const allObs = await tx.loadAll();
|
|
145242
145770
|
const activeObs = allObs.filter(
|
|
@@ -145244,7 +145772,11 @@ async function archiveExpired(projectDir2, referenceTime, accessMap, projectId,
|
|
|
145244
145772
|
);
|
|
145245
145773
|
const archivedIds = [];
|
|
145246
145774
|
for (const obs of activeObs) {
|
|
145247
|
-
const retention = projectObservationRetention(obs, {
|
|
145775
|
+
const retention = projectObservationRetention(obs, {
|
|
145776
|
+
accessMap,
|
|
145777
|
+
referenceTime,
|
|
145778
|
+
...feedback ? { feedback: feedback.getState(obs.projectId, "observation", String(obs.id)) } : {}
|
|
145779
|
+
});
|
|
145248
145780
|
if (retention.zone === "archive-candidate") {
|
|
145249
145781
|
archivedIds.push(obs.id);
|
|
145250
145782
|
}
|
|
@@ -145264,6 +145796,7 @@ var init_retention = __esm({
|
|
|
145264
145796
|
init_esm_shims();
|
|
145265
145797
|
init_obs_store();
|
|
145266
145798
|
init_visibility();
|
|
145799
|
+
init_feedback_model();
|
|
145267
145800
|
RETENTION_DAYS = {
|
|
145268
145801
|
critical: 365,
|
|
145269
145802
|
high: 180,
|
|
@@ -145304,7 +145837,7 @@ var owner_exports = {};
|
|
|
145304
145837
|
__export(owner_exports, {
|
|
145305
145838
|
resolveLocalMemoryOwner: () => resolveLocalMemoryOwner
|
|
145306
145839
|
});
|
|
145307
|
-
import { randomUUID as
|
|
145840
|
+
import { randomUUID as randomUUID8 } from "crypto";
|
|
145308
145841
|
import { promises as fs12 } from "fs";
|
|
145309
145842
|
import path20 from "path";
|
|
145310
145843
|
function ownerPath(dataDir) {
|
|
@@ -145334,7 +145867,7 @@ async function resolveLocalMemoryOwner(dataDir, options = {}) {
|
|
|
145334
145867
|
await fs12.mkdir(path20.dirname(filePath), { recursive: true });
|
|
145335
145868
|
const created = {
|
|
145336
145869
|
version: 1,
|
|
145337
|
-
id: "local-" +
|
|
145870
|
+
id: "local-" + randomUUID8(),
|
|
145338
145871
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
145339
145872
|
};
|
|
145340
145873
|
try {
|
|
@@ -145357,7 +145890,7 @@ var init_owner = __esm({
|
|
|
145357
145890
|
});
|
|
145358
145891
|
|
|
145359
145892
|
// src/memory/long-term-store.ts
|
|
145360
|
-
import { randomUUID as
|
|
145893
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
145361
145894
|
function optionalText2(value) {
|
|
145362
145895
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
145363
145896
|
}
|
|
@@ -145408,7 +145941,7 @@ function rowToEvidence(row) {
|
|
|
145408
145941
|
createdAt: row.createdAt
|
|
145409
145942
|
};
|
|
145410
145943
|
}
|
|
145411
|
-
function
|
|
145944
|
+
function rowToEvent2(row) {
|
|
145412
145945
|
return {
|
|
145413
145946
|
id: row.id,
|
|
145414
145947
|
memoryId: row.memoryId,
|
|
@@ -145517,7 +146050,7 @@ var init_long_term_store = __esm({
|
|
|
145517
146050
|
}
|
|
145518
146051
|
insertEvidence(input) {
|
|
145519
146052
|
const evidence = {
|
|
145520
|
-
id:
|
|
146053
|
+
id: randomUUID9(),
|
|
145521
146054
|
...input,
|
|
145522
146055
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
145523
146056
|
};
|
|
@@ -145544,7 +146077,7 @@ var init_long_term_store = __esm({
|
|
|
145544
146077
|
}
|
|
145545
146078
|
recordEvent(input) {
|
|
145546
146079
|
const event = {
|
|
145547
|
-
id:
|
|
146080
|
+
id: randomUUID9(),
|
|
145548
146081
|
...input,
|
|
145549
146082
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
145550
146083
|
};
|
|
@@ -145565,7 +146098,7 @@ var init_long_term_store = __esm({
|
|
|
145565
146098
|
listEvents(memoryId) {
|
|
145566
146099
|
return this.db.prepare(`
|
|
145567
146100
|
SELECT * FROM long_term_memory_events WHERE memoryId = ? ORDER BY createdAt ASC, rowid ASC
|
|
145568
|
-
`).all(memoryId).map(
|
|
146101
|
+
`).all(memoryId).map(rowToEvent2);
|
|
145569
146102
|
}
|
|
145570
146103
|
markAccess(ids, at = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
145571
146104
|
const unique2 = [...new Set(ids.filter(Boolean))];
|
|
@@ -145634,7 +146167,7 @@ __export(long_term_exports, {
|
|
|
145634
146167
|
selectLongTermMemoriesForTask: () => selectLongTermMemoriesForTask,
|
|
145635
146168
|
supersedeLongTermMemory: () => supersedeLongTermMemory
|
|
145636
146169
|
});
|
|
145637
|
-
import { randomUUID as
|
|
146170
|
+
import { randomUUID as randomUUID10 } from "crypto";
|
|
145638
146171
|
function isOneOf(value, values) {
|
|
145639
146172
|
return typeof value === "string" && values.includes(value);
|
|
145640
146173
|
}
|
|
@@ -145816,7 +146349,7 @@ async function createManualLongTermMemory(input) {
|
|
|
145816
146349
|
const owner = await resolveLocalMemoryOwner(input.dataDir, { create: true });
|
|
145817
146350
|
if (!owner) throw new Error("Memorix could not resolve a local memory owner.");
|
|
145818
146351
|
assertScope(input.scope);
|
|
145819
|
-
const evidence = input.scope === "user" ? [{ kind: "user", referenceId: owner.id, relation: "user-confirmed" }] : [{ kind: "manual", referenceId: "manual:" +
|
|
146352
|
+
const evidence = input.scope === "user" ? [{ kind: "user", referenceId: owner.id, relation: "user-confirmed" }] : [{ kind: "manual", referenceId: "manual:" + randomUUID10(), relation: "supports" }];
|
|
145820
146353
|
return createLongTermMemoryWithDataDir({
|
|
145821
146354
|
dataDir: input.dataDir,
|
|
145822
146355
|
originProjectId: input.projectId,
|
|
@@ -145871,7 +146404,7 @@ async function createLongTermMemoryWithDataDir(input) {
|
|
|
145871
146404
|
assertPortableEvidence(input.scope, portability, evidenceInputs);
|
|
145872
146405
|
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
145873
146406
|
const memory = {
|
|
145874
|
-
id:
|
|
146407
|
+
id: randomUUID10(),
|
|
145875
146408
|
originProjectId: compactText(input.originProjectId, "origin project id", 1e3),
|
|
145876
146409
|
ownerId: compactText(input.ownerId, "owner id", 160),
|
|
145877
146410
|
scope: input.scope,
|
|
@@ -146189,9 +146722,9 @@ var init_long_term = __esm({
|
|
|
146189
146722
|
});
|
|
146190
146723
|
|
|
146191
146724
|
// src/codegraph/ids.ts
|
|
146192
|
-
import { createHash as
|
|
146725
|
+
import { createHash as createHash6 } from "crypto";
|
|
146193
146726
|
function digest(input) {
|
|
146194
|
-
return
|
|
146727
|
+
return createHash6("sha256").update(input).digest("hex").slice(0, 16);
|
|
146195
146728
|
}
|
|
146196
146729
|
function normalizeCodePath(path37) {
|
|
146197
146730
|
return path37.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+/g, "/");
|
|
@@ -146226,7 +146759,7 @@ var store_exports = {};
|
|
|
146226
146759
|
__export(store_exports, {
|
|
146227
146760
|
CodeGraphStore: () => CodeGraphStore
|
|
146228
146761
|
});
|
|
146229
|
-
import { randomUUID as
|
|
146762
|
+
import { randomUUID as randomUUID11 } from "crypto";
|
|
146230
146763
|
import { posix as pathPosix } from "path";
|
|
146231
146764
|
function rowToFile(row) {
|
|
146232
146765
|
return {
|
|
@@ -146943,7 +147476,7 @@ var init_store = __esm({
|
|
|
146943
147476
|
* so an interrupted scan cannot be advertised as complete.
|
|
146944
147477
|
*/
|
|
146945
147478
|
recordCodeStateSnapshot(input) {
|
|
146946
|
-
const id =
|
|
147479
|
+
const id = randomUUID11();
|
|
146947
147480
|
let snapshot;
|
|
146948
147481
|
const tx = this.db.transaction(() => {
|
|
146949
147482
|
const previous = this.db.prepare(
|
|
@@ -147021,7 +147554,7 @@ var init_store = __esm({
|
|
|
147021
147554
|
|
|
147022
147555
|
// src/codegraph/code-state.ts
|
|
147023
147556
|
import { execFile as execFile2 } from "child_process";
|
|
147024
|
-
import { createHash as
|
|
147557
|
+
import { createHash as createHash7 } from "crypto";
|
|
147025
147558
|
import { promisify as promisify3 } from "util";
|
|
147026
147559
|
async function runGit(rootPath, args) {
|
|
147027
147560
|
try {
|
|
@@ -147050,7 +147583,7 @@ function changedPathCount(status) {
|
|
|
147050
147583
|
return count2;
|
|
147051
147584
|
}
|
|
147052
147585
|
function fingerprint(baseRevision, status) {
|
|
147053
|
-
return
|
|
147586
|
+
return createHash7("sha256").update(baseRevision ?? "").update("\0").update(status).digest("hex");
|
|
147054
147587
|
}
|
|
147055
147588
|
async function collectCodeStateSnapshot(input) {
|
|
147056
147589
|
const [revision, status] = await Promise.all([
|
|
@@ -147150,11 +147683,11 @@ __export(lite_provider_exports, {
|
|
|
147150
147683
|
indexProjectLite: () => indexProjectLite,
|
|
147151
147684
|
refreshProjectLite: () => refreshProjectLite
|
|
147152
147685
|
});
|
|
147153
|
-
import { createHash as
|
|
147686
|
+
import { createHash as createHash8 } from "crypto";
|
|
147154
147687
|
import { readdirSync as readdirSync2, readFileSync as readFileSync7, statSync as statSync3 } from "fs";
|
|
147155
147688
|
import { join as join4, relative } from "path";
|
|
147156
147689
|
function hashText(text2) {
|
|
147157
|
-
return
|
|
147690
|
+
return createHash8("sha256").update(text2).digest("hex");
|
|
147158
147691
|
}
|
|
147159
147692
|
function extension2(path37) {
|
|
147160
147693
|
const index = path37.lastIndexOf(".");
|
|
@@ -147721,7 +148254,7 @@ var claim_store_exports = {};
|
|
|
147721
148254
|
__export(claim_store_exports, {
|
|
147722
148255
|
ClaimStore: () => ClaimStore
|
|
147723
148256
|
});
|
|
147724
|
-
import { createHash as
|
|
148257
|
+
import { createHash as createHash9, randomUUID as randomUUID12 } from "crypto";
|
|
147725
148258
|
function optionalText3(value) {
|
|
147726
148259
|
return typeof value === "string" && value ? value : void 0;
|
|
147727
148260
|
}
|
|
@@ -147760,7 +148293,7 @@ function rowToEvidence2(row) {
|
|
|
147760
148293
|
createdAt: row.createdAt
|
|
147761
148294
|
};
|
|
147762
148295
|
}
|
|
147763
|
-
function
|
|
148296
|
+
function rowToEvent3(row) {
|
|
147764
148297
|
return {
|
|
147765
148298
|
id: row.id,
|
|
147766
148299
|
projectId: row.projectId,
|
|
@@ -147774,7 +148307,7 @@ function rowToEvent2(row) {
|
|
|
147774
148307
|
};
|
|
147775
148308
|
}
|
|
147776
148309
|
function evidenceKey(input) {
|
|
147777
|
-
return
|
|
148310
|
+
return createHash9("sha256").update(JSON.stringify([
|
|
147778
148311
|
input.evidenceKind,
|
|
147779
148312
|
input.evidenceId,
|
|
147780
148313
|
input.relation,
|
|
@@ -147905,7 +148438,7 @@ var init_claim_store = __esm({
|
|
|
147905
148438
|
locator, capturedHash, evidenceKey, createdAt
|
|
147906
148439
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
147907
148440
|
`).run(
|
|
147908
|
-
|
|
148441
|
+
randomUUID12(),
|
|
147909
148442
|
input.claimId,
|
|
147910
148443
|
input.evidenceKind,
|
|
147911
148444
|
input.evidenceId,
|
|
@@ -147927,7 +148460,7 @@ var init_claim_store = __esm({
|
|
|
147927
148460
|
}
|
|
147928
148461
|
recordEvent(input) {
|
|
147929
148462
|
const event = {
|
|
147930
|
-
id:
|
|
148463
|
+
id: randomUUID12(),
|
|
147931
148464
|
...input,
|
|
147932
148465
|
...input.detail ? { detail: sanitizeCredentials(input.detail) } : {},
|
|
147933
148466
|
createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -147955,7 +148488,7 @@ var init_claim_store = __esm({
|
|
|
147955
148488
|
SELECT * FROM knowledge_claim_events
|
|
147956
148489
|
WHERE claimId = ?
|
|
147957
148490
|
ORDER BY createdAt ASC, id
|
|
147958
|
-
`).all(claimId).map(
|
|
148491
|
+
`).all(claimId).map(rowToEvent3);
|
|
147959
148492
|
}
|
|
147960
148493
|
};
|
|
147961
148494
|
}
|
|
@@ -147972,7 +148505,7 @@ __export(claims_exports, {
|
|
|
147972
148505
|
supersedeClaim: () => supersedeClaim,
|
|
147973
148506
|
writeClaim: () => writeClaim
|
|
147974
148507
|
});
|
|
147975
|
-
import { createHash as
|
|
148508
|
+
import { createHash as createHash10, randomUUID as randomUUID13 } from "crypto";
|
|
147976
148509
|
function compactText2(value, field) {
|
|
147977
148510
|
if (typeof value !== "string") throw new Error("Claim " + field + " must be text");
|
|
147978
148511
|
const sanitized = sanitizeCredentials(value).trim().replace(/\s+/g, " ");
|
|
@@ -147984,7 +148517,7 @@ function normalizedTerm(value) {
|
|
|
147984
148517
|
return compactText2(value, "identity").toLocaleLowerCase("en-US");
|
|
147985
148518
|
}
|
|
147986
148519
|
function hashIdentity(parts) {
|
|
147987
|
-
return
|
|
148520
|
+
return createHash10("sha256").update(parts.join(String.fromCharCode(31))).digest("hex");
|
|
147988
148521
|
}
|
|
147989
148522
|
function buildClaimIdentity(input) {
|
|
147990
148523
|
const subject = normalizedTerm(input.subject);
|
|
@@ -148058,7 +148591,7 @@ function normalizeClaimInput(input) {
|
|
|
148058
148591
|
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
148059
148592
|
return {
|
|
148060
148593
|
claim: {
|
|
148061
|
-
id:
|
|
148594
|
+
id: randomUUID13(),
|
|
148062
148595
|
projectId,
|
|
148063
148596
|
subject,
|
|
148064
148597
|
predicate,
|
|
@@ -148225,7 +148758,7 @@ function supersedeClaim(store, input) {
|
|
|
148225
148758
|
});
|
|
148226
148759
|
}
|
|
148227
148760
|
function hashObservation(observation) {
|
|
148228
|
-
return
|
|
148761
|
+
return createHash10("sha256").update(JSON.stringify([
|
|
148229
148762
|
observation.title,
|
|
148230
148763
|
observation.narrative,
|
|
148231
148764
|
observation.facts,
|
|
@@ -148469,11 +149002,11 @@ var init_frontmatter = __esm({
|
|
|
148469
149002
|
});
|
|
148470
149003
|
|
|
148471
149004
|
// src/knowledge/markdown.ts
|
|
148472
|
-
import { createHash as
|
|
149005
|
+
import { createHash as createHash11 } from "crypto";
|
|
148473
149006
|
import { promises as fs13 } from "fs";
|
|
148474
149007
|
import path21 from "path";
|
|
148475
149008
|
function hashContent(content) {
|
|
148476
|
-
return
|
|
149009
|
+
return createHash11("sha256").update(content).digest("hex");
|
|
148477
149010
|
}
|
|
148478
149011
|
function stringField(data, key) {
|
|
148479
149012
|
const value = data[key];
|
|
@@ -148599,11 +149132,11 @@ __export(wiki_exports, {
|
|
|
148599
149132
|
lintKnowledgeWorkspace: () => lintKnowledgeWorkspace,
|
|
148600
149133
|
readKnowledgePage: () => readKnowledgePage
|
|
148601
149134
|
});
|
|
148602
|
-
import { createHash as
|
|
149135
|
+
import { createHash as createHash12 } from "crypto";
|
|
148603
149136
|
import { promises as fs14 } from "fs";
|
|
148604
149137
|
import path22 from "path";
|
|
148605
149138
|
function hash2(value) {
|
|
148606
|
-
return
|
|
149139
|
+
return createHash12("sha256").update(value).digest("hex");
|
|
148607
149140
|
}
|
|
148608
149141
|
function now() {
|
|
148609
149142
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -149147,7 +149680,7 @@ var workflow_store_exports = {};
|
|
|
149147
149680
|
__export(workflow_store_exports, {
|
|
149148
149681
|
WorkflowStore: () => WorkflowStore
|
|
149149
149682
|
});
|
|
149150
|
-
import { randomUUID as
|
|
149683
|
+
import { randomUUID as randomUUID14 } from "crypto";
|
|
149151
149684
|
function parseJson(value, fallback) {
|
|
149152
149685
|
if (typeof value !== "string" || !value) return fallback;
|
|
149153
149686
|
try {
|
|
@@ -149247,7 +149780,7 @@ var init_workflow_store = __esm({
|
|
|
149247
149780
|
}
|
|
149248
149781
|
recordRun(input) {
|
|
149249
149782
|
const run = {
|
|
149250
|
-
id:
|
|
149783
|
+
id: randomUUID14(),
|
|
149251
149784
|
workflowId: input.workflowId,
|
|
149252
149785
|
projectId: input.projectId,
|
|
149253
149786
|
task: input.task.trim(),
|
|
@@ -149325,7 +149858,7 @@ var init_outcome_types = __esm({
|
|
|
149325
149858
|
});
|
|
149326
149859
|
|
|
149327
149860
|
// src/knowledge/outcome-store.ts
|
|
149328
|
-
import { randomUUID as
|
|
149861
|
+
import { randomUUID as randomUUID15 } from "crypto";
|
|
149329
149862
|
function optionalText5(value) {
|
|
149330
149863
|
return typeof value === "string" && value.trim() ? value : void 0;
|
|
149331
149864
|
}
|
|
@@ -149369,7 +149902,7 @@ var init_outcome_store = __esm({
|
|
|
149369
149902
|
}
|
|
149370
149903
|
record(input) {
|
|
149371
149904
|
const signal = {
|
|
149372
|
-
id:
|
|
149905
|
+
id: randomUUID15(),
|
|
149373
149906
|
projectId: text(input.projectId, "project id"),
|
|
149374
149907
|
candidateKind: oneOf(input.candidateKind, MEMORY_OUTCOME_CANDIDATE_KINDS, "candidate kind"),
|
|
149375
149908
|
candidateId: text(input.candidateId, "candidate id"),
|
|
@@ -149796,11 +150329,11 @@ __export(workflows_exports, {
|
|
|
149796
150329
|
syncCanonicalWorkflows: () => syncCanonicalWorkflows,
|
|
149797
150330
|
writeCanonicalWorkflow: () => writeCanonicalWorkflow
|
|
149798
150331
|
});
|
|
149799
|
-
import { createHash as
|
|
150332
|
+
import { createHash as createHash13 } from "crypto";
|
|
149800
150333
|
import { promises as fs15 } from "fs";
|
|
149801
150334
|
import path23 from "path";
|
|
149802
150335
|
function hash3(value) {
|
|
149803
|
-
return
|
|
150336
|
+
return createHash13("sha256").update(value).digest("hex");
|
|
149804
150337
|
}
|
|
149805
150338
|
function now2() {
|
|
149806
150339
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -151197,6 +151730,16 @@ async function bindObservationCodeRefsBestEffort(observation) {
|
|
|
151197
151730
|
} catch {
|
|
151198
151731
|
}
|
|
151199
151732
|
}
|
|
151733
|
+
async function persistEvidenceCard(observation) {
|
|
151734
|
+
if (!projectDir) return;
|
|
151735
|
+
try {
|
|
151736
|
+
const evidence = new EvidenceCardStore();
|
|
151737
|
+
await evidence.init(projectDir);
|
|
151738
|
+
evidence.upsertObservation(observation);
|
|
151739
|
+
} catch (error) {
|
|
151740
|
+
console.error(`[memorix] Evidence card projection failed for obs-${observation.id}: ${error instanceof Error ? error.message : String(error)}`);
|
|
151741
|
+
}
|
|
151742
|
+
}
|
|
151200
151743
|
function queueClaimDerivation(observation) {
|
|
151201
151744
|
const dataDir = projectDir;
|
|
151202
151745
|
const isExplicit = observation.sourceDetail === "explicit";
|
|
@@ -151543,6 +152086,7 @@ async function storeObservation(input) {
|
|
|
151543
152086
|
}
|
|
151544
152087
|
if (!persistedCallbackInvoked) await input.onPersisted?.(observation);
|
|
151545
152088
|
await bindObservationCodeRefsBestEffort(observation);
|
|
152089
|
+
await persistEvidenceCard(observation);
|
|
151546
152090
|
queueObservationQualification(observation);
|
|
151547
152091
|
if (resolveObservationVisibility(observation) === "project") {
|
|
151548
152092
|
queueClaimDerivation(observation);
|
|
@@ -151635,6 +152179,7 @@ async function upsertObservation(existing, input, now3) {
|
|
|
151635
152179
|
await store.update(existing);
|
|
151636
152180
|
}
|
|
151637
152181
|
await bindObservationCodeRefsBestEffort(existing);
|
|
152182
|
+
await persistEvidenceCard(existing);
|
|
151638
152183
|
queueObservationQualification(existing);
|
|
151639
152184
|
if (resolveObservationVisibility(existing) === "project") {
|
|
151640
152185
|
queueClaimDerivation(existing);
|
|
@@ -151768,6 +152313,7 @@ async function resolveObservations(ids, status = "resolved") {
|
|
|
151768
152313
|
await Promise.all(changed.map((observation) => tx.update(observation)));
|
|
151769
152314
|
});
|
|
151770
152315
|
}
|
|
152316
|
+
for (const observation of changed) await persistEvidenceCard(observation);
|
|
151771
152317
|
return { resolved, notFound };
|
|
151772
152318
|
}
|
|
151773
152319
|
function getProjectObservations(projectId) {
|
|
@@ -152105,6 +152651,7 @@ var init_observations = __esm({
|
|
|
152105
152651
|
init_secret_filter();
|
|
152106
152652
|
init_lifecycle();
|
|
152107
152653
|
init_visibility();
|
|
152654
|
+
init_evidence_store();
|
|
152108
152655
|
observations = [];
|
|
152109
152656
|
nextId = 1;
|
|
152110
152657
|
projectDir = null;
|
|
@@ -152936,9 +153483,27 @@ function normalizeMemoryBrowseQuery(query) {
|
|
|
152936
153483
|
async function compactSearch(options, surface = "mcp") {
|
|
152937
153484
|
await ensureFreshIndex();
|
|
152938
153485
|
const searchOptions = { ...options, query: normalizeMemoryBrowseQuery(options.query) };
|
|
152939
|
-
|
|
153486
|
+
let entries = (await searchObservations(searchOptions)).map(
|
|
152940
153487
|
(entry) => entry.projectId || !options.projectId ? entry : { ...entry, projectId: options.projectId }
|
|
152941
153488
|
);
|
|
153489
|
+
if (options.projectId) {
|
|
153490
|
+
try {
|
|
153491
|
+
const feedback = new MemoryFeedbackStore();
|
|
153492
|
+
await feedback.init(await getProjectDataDir(options.projectId));
|
|
153493
|
+
const states = feedback.weights(options.projectId, "observation");
|
|
153494
|
+
entries = entries.map((entry) => {
|
|
153495
|
+
const state = states.get(String(entry.id));
|
|
153496
|
+
if (!state) return entry;
|
|
153497
|
+
return {
|
|
153498
|
+
...entry,
|
|
153499
|
+
score: (entry.score ?? 0) * feedbackWeightMultiplier(state.weight),
|
|
153500
|
+
feedbackWeight: state.weight,
|
|
153501
|
+
feedbackStatus: state.status
|
|
153502
|
+
};
|
|
153503
|
+
}).filter((entry) => entry.feedbackStatus !== "archived" || options.status === "all").sort((a, b) => (b.score ?? 0) - (a.score ?? 0));
|
|
153504
|
+
} catch {
|
|
153505
|
+
}
|
|
153506
|
+
}
|
|
152942
153507
|
let formatted = formatIndexTable(entries, searchOptions.query, !options.projectId, surface);
|
|
152943
153508
|
if (entries.length === 0 && options.projectId) {
|
|
152944
153509
|
const allObservations = filterReadableObservations(getAllObservations(), options.reader);
|
|
@@ -153257,6 +153822,8 @@ var init_engine3 = __esm({
|
|
|
153257
153822
|
init_mini_skills();
|
|
153258
153823
|
init_secret_filter();
|
|
153259
153824
|
init_visibility();
|
|
153825
|
+
init_persistence();
|
|
153826
|
+
init_feedback();
|
|
153260
153827
|
}
|
|
153261
153828
|
});
|
|
153262
153829
|
|
|
@@ -153878,9 +154445,9 @@ var init_graph_context = __esm({
|
|
|
153878
154445
|
});
|
|
153879
154446
|
|
|
153880
154447
|
// src/rules/utils.ts
|
|
153881
|
-
import { createHash as
|
|
154448
|
+
import { createHash as createHash14 } from "crypto";
|
|
153882
154449
|
function hashContent2(content) {
|
|
153883
|
-
return
|
|
154450
|
+
return createHash14("sha256").update(content.trim()).digest("hex").substring(0, 16);
|
|
153884
154451
|
}
|
|
153885
154452
|
function generateRuleId(source, filePath) {
|
|
153886
154453
|
const sanitized = filePath.replace(/[\/\\]/g, "-").replace(/^\./, "");
|
|
@@ -156311,6 +156878,10 @@ var init_tool_profile = __esm({
|
|
|
156311
156878
|
// multimodal support to one additional schema rather than enabling lite.
|
|
156312
156879
|
memorix_session_start: ["micro", "lite", "team", "full"],
|
|
156313
156880
|
memorix_media: ["micro", "lite", "team", "full"],
|
|
156881
|
+
// Evidence and feedback are deliberate operator/context-control surfaces;
|
|
156882
|
+
// keep the default micro profile at its nine-tool token budget.
|
|
156883
|
+
memorix_evidence: ["lite", "team", "full"],
|
|
156884
|
+
memorix_feedback: ["lite", "team", "full"],
|
|
156314
156885
|
// ── lite: extended solo memory surface ────────────────────────────
|
|
156315
156886
|
memorix_graph_context: ["lite", "team", "full"],
|
|
156316
156887
|
memorix_timeline: ["lite", "team", "full"],
|
|
@@ -159769,7 +160340,7 @@ var compaction_checkpoint_store_exports = {};
|
|
|
159769
160340
|
__export(compaction_checkpoint_store_exports, {
|
|
159770
160341
|
CompactionCheckpointStore: () => CompactionCheckpointStore
|
|
159771
160342
|
});
|
|
159772
|
-
import { createHash as
|
|
160343
|
+
import { createHash as createHash15, randomUUID as randomUUID16 } from "crypto";
|
|
159773
160344
|
function optionalText7(value) {
|
|
159774
160345
|
return typeof value === "string" && value ? value : void 0;
|
|
159775
160346
|
}
|
|
@@ -159811,7 +160382,7 @@ function sourceKeyFor(input, summary) {
|
|
|
159811
160382
|
input.tokensBefore ?? "",
|
|
159812
160383
|
input.firstKeptEntryId ?? ""
|
|
159813
160384
|
].join("\0");
|
|
159814
|
-
return `derived:${
|
|
160385
|
+
return `derived:${createHash15("sha256").update(material).digest("hex").slice(0, 32)}`;
|
|
159815
160386
|
}
|
|
159816
160387
|
function rowToCheckpoint(row) {
|
|
159817
160388
|
return {
|
|
@@ -159870,7 +160441,7 @@ var init_compaction_checkpoint_store = __esm({
|
|
|
159870
160441
|
if (pending) return rowToCheckpoint(pending);
|
|
159871
160442
|
const now3 = input.capturedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
159872
160443
|
const checkpoint = {
|
|
159873
|
-
id:
|
|
160444
|
+
id: randomUUID16(),
|
|
159874
160445
|
projectId: input.projectId,
|
|
159875
160446
|
sessionId: input.sessionId,
|
|
159876
160447
|
agent: input.agent,
|
|
@@ -159878,7 +160449,7 @@ var init_compaction_checkpoint_store = __esm({
|
|
|
159878
160449
|
captureKind: "preflight",
|
|
159879
160450
|
reason: safeReason(input.reason),
|
|
159880
160451
|
sourceEvent: input.sourceEvent,
|
|
159881
|
-
sourceKey: `pre:${
|
|
160452
|
+
sourceKey: `pre:${randomUUID16()}`,
|
|
159882
160453
|
transcriptAvailable: Boolean(input.transcriptAvailable),
|
|
159883
160454
|
status: "active",
|
|
159884
160455
|
preCapturedAt: now3,
|
|
@@ -159944,7 +160515,7 @@ var init_compaction_checkpoint_store = __esm({
|
|
|
159944
160515
|
return this.get(checkpoint2.id);
|
|
159945
160516
|
}
|
|
159946
160517
|
const checkpoint = {
|
|
159947
|
-
id:
|
|
160518
|
+
id: randomUUID16(),
|
|
159948
160519
|
projectId: input.projectId,
|
|
159949
160520
|
sessionId: input.sessionId,
|
|
159950
160521
|
agent: input.agent,
|
|
@@ -161308,7 +161879,7 @@ __export(team_store_exports, {
|
|
|
161308
161879
|
isTeamStoreInitialized: () => isTeamStoreInitialized,
|
|
161309
161880
|
resetTeamStore: () => resetTeamStore
|
|
161310
161881
|
});
|
|
161311
|
-
import { randomUUID as
|
|
161882
|
+
import { randomUUID as randomUUID17 } from "crypto";
|
|
161312
161883
|
import path30 from "path";
|
|
161313
161884
|
import fs18 from "fs";
|
|
161314
161885
|
function getTeamStore() {
|
|
@@ -161597,7 +162168,7 @@ var init_team_store = __esm({
|
|
|
161597
162168
|
* reactivate it (preserving agent_id). Otherwise create a new one.
|
|
161598
162169
|
*/
|
|
161599
162170
|
registerAgent(input) {
|
|
161600
|
-
const instanceId = input.instanceId ||
|
|
162171
|
+
const instanceId = input.instanceId || randomUUID17();
|
|
161601
162172
|
const now3 = Date.now();
|
|
161602
162173
|
const existing = this.stmtAgentFindByInstance.get(
|
|
161603
162174
|
input.projectId,
|
|
@@ -161623,7 +162194,7 @@ var init_team_store = __esm({
|
|
|
161623
162194
|
this.eventBus?.emit("agent:joined", { agentId: row2.agent_id, projectId: input.projectId, agentType: input.agentType });
|
|
161624
162195
|
return row2;
|
|
161625
162196
|
}
|
|
161626
|
-
const agentId =
|
|
162197
|
+
const agentId = randomUUID17();
|
|
161627
162198
|
this.stmtAgentUpsert.run({
|
|
161628
162199
|
agent_id: agentId,
|
|
161629
162200
|
project_id: input.projectId,
|
|
@@ -161725,7 +162296,7 @@ var init_team_store = __esm({
|
|
|
161725
162296
|
return { error: `Recipient agent '${input.recipientAgentId}' not found \u2014 cannot send to unknown agent` };
|
|
161726
162297
|
}
|
|
161727
162298
|
}
|
|
161728
|
-
const id =
|
|
162299
|
+
const id = randomUUID17();
|
|
161729
162300
|
const now3 = Date.now();
|
|
161730
162301
|
const row = {
|
|
161731
162302
|
id,
|
|
@@ -161775,7 +162346,7 @@ var init_team_store = __esm({
|
|
|
161775
162346
|
// Task Operations (with atomic claim semantics)
|
|
161776
162347
|
// ═══════════════════════════════════════════════════════════════════
|
|
161777
162348
|
createTask(input) {
|
|
161778
|
-
const taskId =
|
|
162349
|
+
const taskId = randomUUID17();
|
|
161779
162350
|
const now3 = Date.now();
|
|
161780
162351
|
const row = {
|
|
161781
162352
|
task_id: taskId,
|
|
@@ -162047,7 +162618,7 @@ var init_team_store = __esm({
|
|
|
162047
162618
|
for (const [agentId, msgs] of Object.entries(snap.messages.inboxes)) {
|
|
162048
162619
|
for (const msg of msgs) {
|
|
162049
162620
|
this.stmtMsgInsert.run({
|
|
162050
|
-
id: msg.id ??
|
|
162621
|
+
id: msg.id ?? randomUUID17(),
|
|
162051
162622
|
project_id: "migrated",
|
|
162052
162623
|
sender_agent_id: msg.from ?? "unknown",
|
|
162053
162624
|
recipient_agent_id: msg.to === "__broadcast__" ? null : msg.to ?? agentId,
|
|
@@ -162918,6 +163489,23 @@ var init_maintenance = __esm({
|
|
|
162918
163489
|
}
|
|
162919
163490
|
});
|
|
162920
163491
|
|
|
163492
|
+
// src/dashboard/config-provenance.ts
|
|
163493
|
+
function resolveDashboardKeySource({ value, envKeys, configSource }) {
|
|
163494
|
+
for (const envKey of envKeys) {
|
|
163495
|
+
const envValue = process.env[envKey];
|
|
163496
|
+
if (envValue !== value) continue;
|
|
163497
|
+
return getLoadedEnvValue(envKey) === envValue ? ".env" : `env:${envKey}`;
|
|
163498
|
+
}
|
|
163499
|
+
return configSource;
|
|
163500
|
+
}
|
|
163501
|
+
var init_config_provenance = __esm({
|
|
163502
|
+
"src/dashboard/config-provenance.ts"() {
|
|
163503
|
+
"use strict";
|
|
163504
|
+
init_esm_shims();
|
|
163505
|
+
init_dotenv_loader();
|
|
163506
|
+
}
|
|
163507
|
+
});
|
|
163508
|
+
|
|
162921
163509
|
// src/dashboard/project-classification.ts
|
|
162922
163510
|
var project_classification_exports = {};
|
|
162923
163511
|
__export(project_classification_exports, {
|
|
@@ -163697,6 +164285,20 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
163697
164285
|
sendJson(res, observations2);
|
|
163698
164286
|
break;
|
|
163699
164287
|
}
|
|
164288
|
+
case "/evidence": {
|
|
164289
|
+
const observations2 = filterDashboardObservations(
|
|
164290
|
+
await getObservationStore().loadByProject(effectiveProjectId, { status: "active" }),
|
|
164291
|
+
effectiveProjectId
|
|
164292
|
+
);
|
|
164293
|
+
const evidenceStore = new EvidenceCardStore();
|
|
164294
|
+
await evidenceStore.init(effectiveDataDir);
|
|
164295
|
+
evidenceStore.syncObservations(observations2);
|
|
164296
|
+
const query = url.searchParams.get("q") || "";
|
|
164297
|
+
const limit2 = Number(url.searchParams.get("limit") || 20);
|
|
164298
|
+
const cards = evidenceStore.list(effectiveProjectId, { limit: Math.min(100, Math.max(1, limit2)) }).filter((card) => !query || [card.title, card.summary, card.sourceRef, card.locator ?? ""].join(" ").toLowerCase().includes(query.toLowerCase()));
|
|
164299
|
+
sendJson(res, { cards, projectId: effectiveProjectId });
|
|
164300
|
+
break;
|
|
164301
|
+
}
|
|
163700
164302
|
case "/sessions": {
|
|
163701
164303
|
const allSessions = await getSessionStore().loadAll();
|
|
163702
164304
|
const sessions = filterByProject(allSessions, effectiveProjectId);
|
|
@@ -163744,8 +164346,13 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
163744
164346
|
filesModified: o.filesModified
|
|
163745
164347
|
}));
|
|
163746
164348
|
const retentionReferenceTime = new Date(now3);
|
|
164349
|
+
const feedback = new MemoryFeedbackStore();
|
|
164350
|
+
await feedback.init(effectiveDataDir).catch(() => void 0);
|
|
163747
164351
|
const retention = summarizeRetentionProjections(
|
|
163748
|
-
observations2.filter((observation) => observation.type !== "probe").map((observation) => projectObservationRetention(observation, {
|
|
164352
|
+
observations2.filter((observation) => observation.type !== "probe").map((observation) => projectObservationRetention(observation, {
|
|
164353
|
+
referenceTime: retentionReferenceTime,
|
|
164354
|
+
feedback: feedback.getState(effectiveProjectId, "observation", String(observation.id))
|
|
164355
|
+
}))
|
|
163749
164356
|
);
|
|
163750
164357
|
const retentionSummary = {
|
|
163751
164358
|
active: retention.active,
|
|
@@ -163839,9 +164446,14 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
163839
164446
|
effectiveProjectId
|
|
163840
164447
|
);
|
|
163841
164448
|
const referenceTime = /* @__PURE__ */ new Date();
|
|
164449
|
+
const feedback = new MemoryFeedbackStore();
|
|
164450
|
+
await feedback.init(effectiveDataDir).catch(() => void 0);
|
|
163842
164451
|
const rows = observations2.filter((observation) => observation.type !== "probe").map((observation) => ({
|
|
163843
164452
|
observation,
|
|
163844
|
-
retention: projectObservationRetention(observation, {
|
|
164453
|
+
retention: projectObservationRetention(observation, {
|
|
164454
|
+
referenceTime,
|
|
164455
|
+
feedback: feedback.getState(effectiveProjectId, "observation", String(observation.id))
|
|
164456
|
+
})
|
|
163845
164457
|
})).sort((a, b) => b.retention.displayScore - a.retention.displayScore);
|
|
163846
164458
|
const summary = summarizeRetentionProjections(rows.map((row) => row.retention));
|
|
163847
164459
|
const scored = rows.map(({ observation, retention }) => ({
|
|
@@ -163912,23 +164524,13 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
163912
164524
|
const os6 = await import("os");
|
|
163913
164525
|
const { existsSync: existsSync21 } = await import("fs");
|
|
163914
164526
|
const { join: join26 } = await import("path");
|
|
163915
|
-
let yml = {};
|
|
163916
164527
|
const configProjectRoot = effectiveProjectRoot;
|
|
163917
|
-
|
|
163918
|
-
const { loadYamlConfig: loadYamlConfig2 } = await Promise.resolve().then(() => (init_yaml_loader(), yaml_loader_exports));
|
|
163919
|
-
yml = configProjectRoot ? loadYamlConfig2(configProjectRoot) : loadYamlConfig2(null);
|
|
163920
|
-
} catch {
|
|
163921
|
-
}
|
|
163922
|
-
if (configProjectRoot) {
|
|
163923
|
-
try {
|
|
163924
|
-
const { loadDotenv: loadDotenv2 } = await Promise.resolve().then(() => (init_dotenv_loader(), dotenv_loader_exports));
|
|
163925
|
-
loadDotenv2(configProjectRoot);
|
|
163926
|
-
} catch {
|
|
163927
|
-
}
|
|
163928
|
-
}
|
|
164528
|
+
const resolved = getResolvedConfig({ projectRoot: configProjectRoot });
|
|
163929
164529
|
const files = {
|
|
163930
164530
|
"project memorix.yml": { exists: false, path: "", unavailable: !configProjectRoot },
|
|
163931
164531
|
"user memorix.yml": { exists: false, path: "" },
|
|
164532
|
+
"project memorix.toml": { exists: false, path: "", unavailable: !configProjectRoot },
|
|
164533
|
+
"user config.toml": { exists: false, path: "" },
|
|
163932
164534
|
"project .env": { exists: false, path: "", unavailable: !configProjectRoot },
|
|
163933
164535
|
"user .env": { exists: false, path: "" },
|
|
163934
164536
|
"legacy config.json": { exists: false, path: "" }
|
|
@@ -163938,6 +164540,8 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
163938
164540
|
const paths = {
|
|
163939
164541
|
"project memorix.yml": configProjectRoot ? join26(configProjectRoot, "memorix.yml") : null,
|
|
163940
164542
|
"user memorix.yml": join26(home, ".memorix", "memorix.yml"),
|
|
164543
|
+
"project memorix.toml": configProjectRoot ? join26(configProjectRoot, "memorix.toml") : null,
|
|
164544
|
+
"user config.toml": join26(home, ".memorix", "config.toml"),
|
|
163941
164545
|
"project .env": configProjectRoot ? join26(configProjectRoot, ".env") : null,
|
|
163942
164546
|
"user .env": join26(home, ".memorix", ".env"),
|
|
163943
164547
|
"legacy config.json": join26(home, ".memorix", "config.json")
|
|
@@ -163952,67 +164556,61 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
163952
164556
|
} catch {
|
|
163953
164557
|
}
|
|
163954
164558
|
const values = [];
|
|
163955
|
-
const
|
|
163956
|
-
|
|
163957
|
-
|
|
163958
|
-
|
|
163959
|
-
|
|
163960
|
-
|
|
163961
|
-
|
|
163962
|
-
|
|
163963
|
-
|
|
163964
|
-
|
|
163965
|
-
|
|
163966
|
-
|
|
163967
|
-
|
|
163968
|
-
|
|
163969
|
-
|
|
163970
|
-
|
|
163971
|
-
|
|
164559
|
+
const tomlSource = configProjectRoot && files["project memorix.toml"].exists ? "memorix.toml" : files["user config.toml"].exists ? "config.toml" : "default";
|
|
164560
|
+
const legacySource = files["project memorix.yml"].exists || files["user memorix.yml"].exists ? "memorix.yml" : files["legacy config.json"].exists ? "config.json" : "default";
|
|
164561
|
+
const configSource = resolved.sources.toml.length > 0 ? tomlSource : resolved.sources.legacy.length > 0 ? legacySource : "default";
|
|
164562
|
+
const source = (envKey) => resolveDashboardKeySource({
|
|
164563
|
+
value: process.env[envKey] ?? "",
|
|
164564
|
+
envKeys: [envKey],
|
|
164565
|
+
configSource
|
|
164566
|
+
});
|
|
164567
|
+
if (resolved.memory.llm.provider) values.push({ key: "llm.provider", value: resolved.memory.llm.provider, source: source("MEMORIX_LLM_PROVIDER") });
|
|
164568
|
+
if (resolved.memory.llm.model) values.push({ key: "llm.model", value: resolved.memory.llm.model, source: source("MEMORIX_LLM_MODEL") });
|
|
164569
|
+
const llmKey = resolved.memory.llm.apiKey;
|
|
164570
|
+
const memoryKeyEnv = [
|
|
164571
|
+
"MEMORIX_LLM_API_KEY",
|
|
164572
|
+
"MEMORIX_API_KEY",
|
|
164573
|
+
"OPENAI_API_KEY",
|
|
164574
|
+
"ANTHROPIC_API_KEY",
|
|
164575
|
+
...resolved.memory.llm.provider === "openrouter" || resolved.memory.llm.baseUrl?.includes("openrouter.ai") ? ["OPENROUTER_API_KEY"] : []
|
|
164576
|
+
];
|
|
163972
164577
|
if (llmKey) {
|
|
163973
|
-
|
|
163974
|
-
if (process.env.MEMORIX_LLM_API_KEY) src = await getEnvSource("MEMORIX_LLM_API_KEY");
|
|
163975
|
-
else if (process.env.MEMORIX_API_KEY) src = await getEnvSource("MEMORIX_API_KEY");
|
|
163976
|
-
else if (yml.llm?.apiKey) src = "memorix.yml (move to .env!)";
|
|
163977
|
-
else if (process.env.OPENAI_API_KEY) src = await getEnvSource("OPENAI_API_KEY");
|
|
164578
|
+
const src = resolveDashboardKeySource({ value: llmKey, envKeys: memoryKeyEnv, configSource });
|
|
163978
164579
|
values.push({ key: "llm.apiKey", value: "****" + llmKey.slice(-4), source: src, sensitive: true });
|
|
163979
164580
|
} else {
|
|
163980
164581
|
values.push({ key: "llm.apiKey", value: "not set", source: "none" });
|
|
163981
164582
|
}
|
|
163982
|
-
|
|
163983
|
-
|
|
163984
|
-
|
|
163985
|
-
|
|
163986
|
-
|
|
163987
|
-
|
|
163988
|
-
|
|
163989
|
-
}
|
|
163990
|
-
const agentModel = process.env.MEMORIX_AGENT_MODEL || process.env.MEMORIX_AGENT_LLM_MODEL || yml.agent?.model;
|
|
163991
|
-
if (agentModel) {
|
|
163992
|
-
let source;
|
|
163993
|
-
if (process.env.MEMORIX_AGENT_MODEL) source = await getEnvSource("MEMORIX_AGENT_MODEL");
|
|
163994
|
-
else if (process.env.MEMORIX_AGENT_LLM_MODEL) source = `${await getEnvSource("MEMORIX_AGENT_LLM_MODEL")} (legacy)`;
|
|
163995
|
-
else source = yml.agent?.model ? "memorix.yml" : "default";
|
|
163996
|
-
values.push({ key: "agent.model", value: agentModel, source });
|
|
163997
|
-
}
|
|
163998
|
-
const agentKey = process.env.MEMORIX_AGENT_API_KEY || process.env.MEMORIX_AGENT_LLM_API_KEY || yml.agent?.apiKey;
|
|
164583
|
+
if (resolved.agent.provider) {
|
|
164584
|
+
values.push({ key: "agent.provider", value: resolved.agent.provider, source: source("MEMORIX_AGENT_PROVIDER") });
|
|
164585
|
+
}
|
|
164586
|
+
if (resolved.agent.model) {
|
|
164587
|
+
values.push({ key: "agent.model", value: resolved.agent.model, source: source("MEMORIX_AGENT_MODEL") });
|
|
164588
|
+
}
|
|
164589
|
+
const agentKey = resolved.agent.apiKey;
|
|
163999
164590
|
if (agentKey) {
|
|
164000
|
-
|
|
164001
|
-
|
|
164002
|
-
|
|
164003
|
-
|
|
164591
|
+
const src = resolveDashboardKeySource({
|
|
164592
|
+
value: agentKey,
|
|
164593
|
+
envKeys: ["MEMORIX_AGENT_API_KEY", "MEMORIX_AGENT_LLM_API_KEY"],
|
|
164594
|
+
configSource
|
|
164595
|
+
});
|
|
164004
164596
|
values.push({ key: "agent.apiKey", value: "****" + agentKey.slice(-4), source: src, sensitive: true });
|
|
164005
164597
|
} else {
|
|
164006
|
-
values.push({
|
|
164007
|
-
|
|
164008
|
-
|
|
164009
|
-
|
|
164010
|
-
|
|
164011
|
-
|
|
164012
|
-
|
|
164013
|
-
if (
|
|
164014
|
-
|
|
164015
|
-
|
|
164598
|
+
values.push({
|
|
164599
|
+
key: "agent.apiKey",
|
|
164600
|
+
value: "fallback to llm.apiKey",
|
|
164601
|
+
source: llmKey ? resolveDashboardKeySource({ value: llmKey, envKeys: memoryKeyEnv, configSource }) : "default"
|
|
164602
|
+
});
|
|
164603
|
+
}
|
|
164604
|
+
values.push({ key: "embedding.provider", value: resolved.embedding.provider || "off", source: source("MEMORIX_EMBEDDING") });
|
|
164605
|
+
if (resolved.embedding.model) values.push({ key: "embedding.model", value: resolved.embedding.model, source: source("MEMORIX_EMBEDDING_MODEL") });
|
|
164606
|
+
if (resolved.rerank.provider !== "off") {
|
|
164607
|
+
values.push({ key: "rerank.provider", value: resolved.rerank.provider, source: source("MEMORIX_RERANK_PROVIDER") });
|
|
164608
|
+
if (resolved.rerank.model) values.push({ key: "rerank.model", value: resolved.rerank.model, source: source("MEMORIX_RERANK_MODEL") });
|
|
164609
|
+
}
|
|
164610
|
+
values.push({ key: "git.autoHook", value: String(resolved.git.autoHook ?? false), source: configSource });
|
|
164611
|
+
values.push({ key: "git.skipMergeCommits", value: String(resolved.git.skipMergeCommits ?? true), source: configSource });
|
|
164612
|
+
values.push({ key: "server.transport", value: resolved.server.transport || "stdio", source: configSource });
|
|
164613
|
+
values.push({ key: "server.dashboard", value: String(resolved.server.dashboard ?? true), source: configSource });
|
|
164016
164614
|
sendJson(res, { files, values });
|
|
164017
164615
|
break;
|
|
164018
164616
|
}
|
|
@@ -164247,6 +164845,37 @@ function normalizeDashboardTask(task) {
|
|
|
164247
164845
|
preferredRole: task.preferred_role ?? task.preferredRole ?? null
|
|
164248
164846
|
};
|
|
164249
164847
|
}
|
|
164848
|
+
function emptyTeamSnapshot(mode, scope, status) {
|
|
164849
|
+
return {
|
|
164850
|
+
status,
|
|
164851
|
+
mode,
|
|
164852
|
+
readOnly: true,
|
|
164853
|
+
scope,
|
|
164854
|
+
agents: [],
|
|
164855
|
+
activeCount: 0,
|
|
164856
|
+
recentCount: 0,
|
|
164857
|
+
historicalCount: 0,
|
|
164858
|
+
totalAgents: 0,
|
|
164859
|
+
recentWindowDays: 7,
|
|
164860
|
+
locks: [],
|
|
164861
|
+
tasks: [],
|
|
164862
|
+
availableTasks: 0,
|
|
164863
|
+
sessions: 0,
|
|
164864
|
+
roles: [],
|
|
164865
|
+
roleOccupancy: [],
|
|
164866
|
+
handoffs: [],
|
|
164867
|
+
openTasks: 0,
|
|
164868
|
+
openHandoffs: 0,
|
|
164869
|
+
totalUnread: 0,
|
|
164870
|
+
activeSessions: 0,
|
|
164871
|
+
error: status === "error" ? "Coordination state unavailable" : "Coordination state is incomplete",
|
|
164872
|
+
errorCode: status === "error" ? "COORDINATION_STATE_UNAVAILABLE" : "COORDINATION_STATE_DEGRADED"
|
|
164873
|
+
};
|
|
164874
|
+
}
|
|
164875
|
+
function logTeamSnapshotFailure(scope, status) {
|
|
164876
|
+
const safeScope = scope === "global" ? "global" : "project";
|
|
164877
|
+
console.error("[dashboard] coordination snapshot unavailable", { status, scope: safeScope });
|
|
164878
|
+
}
|
|
164250
164879
|
async function buildTeamSnapshot(dataDir, projectId, scope, mode) {
|
|
164251
164880
|
try {
|
|
164252
164881
|
const { initTeamStore: initTeamStore2 } = await Promise.resolve().then(() => (init_team_store(), team_store_exports));
|
|
@@ -164273,8 +164902,9 @@ async function buildTeamSnapshot(dataDir, projectId, scope, mode) {
|
|
|
164273
164902
|
const roleOccupancy = effectiveProjectId ? teamStore.getRoleOccupancy(effectiveProjectId) : [];
|
|
164274
164903
|
const handoffs = effectiveProjectId ? teamStore.listHandoffs(effectiveProjectId) : [];
|
|
164275
164904
|
return {
|
|
164905
|
+
status: "ok",
|
|
164276
164906
|
mode,
|
|
164277
|
-
readOnly:
|
|
164907
|
+
readOnly: true,
|
|
164278
164908
|
scope,
|
|
164279
164909
|
agents: withTier,
|
|
164280
164910
|
activeCount,
|
|
@@ -164295,28 +164925,8 @@ async function buildTeamSnapshot(dataDir, projectId, scope, mode) {
|
|
|
164295
164925
|
activeSessions: activeCount
|
|
164296
164926
|
};
|
|
164297
164927
|
} catch {
|
|
164298
|
-
|
|
164299
|
-
|
|
164300
|
-
readOnly: mode === "standalone",
|
|
164301
|
-
scope,
|
|
164302
|
-
agents: [],
|
|
164303
|
-
activeCount: 0,
|
|
164304
|
-
recentCount: 0,
|
|
164305
|
-
historicalCount: 0,
|
|
164306
|
-
totalAgents: 0,
|
|
164307
|
-
recentWindowDays: 7,
|
|
164308
|
-
locks: [],
|
|
164309
|
-
tasks: [],
|
|
164310
|
-
availableTasks: 0,
|
|
164311
|
-
sessions: 0,
|
|
164312
|
-
roles: [],
|
|
164313
|
-
roleOccupancy: [],
|
|
164314
|
-
handoffs: [],
|
|
164315
|
-
openTasks: 0,
|
|
164316
|
-
openHandoffs: 0,
|
|
164317
|
-
totalUnread: 0,
|
|
164318
|
-
activeSessions: 0
|
|
164319
|
-
};
|
|
164928
|
+
logTeamSnapshotFailure(scope, "error");
|
|
164929
|
+
return emptyTeamSnapshot(mode, scope, "error");
|
|
164320
164930
|
}
|
|
164321
164931
|
}
|
|
164322
164932
|
function readBody(req) {
|
|
@@ -164335,13 +164945,12 @@ function readBody(req) {
|
|
|
164335
164945
|
req.on("error", reject);
|
|
164336
164946
|
});
|
|
164337
164947
|
}
|
|
164338
|
-
async function startDashboard(dataDir, port, staticDir, projectId, projectName, autoOpen = true,
|
|
164948
|
+
async function startDashboard(dataDir, port, staticDir, projectId, projectName, autoOpen = true, projectRoot = null, projectResolved = true) {
|
|
164339
164949
|
await initObservationStore(dataDir);
|
|
164340
164950
|
await initSessionStore(dataDir);
|
|
164341
164951
|
const resolvedStaticDir = staticDir;
|
|
164342
164952
|
const baseDir = getBaseDataDir();
|
|
164343
|
-
const
|
|
164344
|
-
const state = { projectId, projectName, dataDir, projectRoot, projectResolved, mode: isControlPlane ? "control-plane" : "standalone", port };
|
|
164953
|
+
const state = { projectId, projectName, dataDir, projectRoot, projectResolved, mode: "standalone", port };
|
|
164345
164954
|
const server = createServer(async (req, res) => {
|
|
164346
164955
|
const url = req.url || "/";
|
|
164347
164956
|
if (url.startsWith("/api/set-current-project") && req.method === "POST") {
|
|
@@ -164363,54 +164972,20 @@ async function startDashboard(dataDir, port, staticDir, projectId, projectName,
|
|
|
164363
164972
|
}
|
|
164364
164973
|
return;
|
|
164365
164974
|
}
|
|
164366
|
-
|
|
164367
|
-
|
|
164368
|
-
|
|
164369
|
-
const scope = parsedUrl.searchParams.get("scope") || "project";
|
|
164370
|
-
sendJson(res, await buildTeamSnapshot(state.dataDir, state.projectId, scope, state.mode));
|
|
164371
|
-
return;
|
|
164372
|
-
}
|
|
164373
|
-
try {
|
|
164374
|
-
teamInstances.fileLocks.cleanExpired();
|
|
164375
|
-
const agents = teamInstances.registry.listAgents();
|
|
164376
|
-
const locks = teamInstances.fileLocks.listLocks();
|
|
164377
|
-
const tasks = teamInstances.taskManager.list();
|
|
164378
|
-
const available = teamInstances.taskManager.getAvailable();
|
|
164379
|
-
let roles = [];
|
|
164380
|
-
let roleOccupancy = [];
|
|
164381
|
-
let handoffs = [];
|
|
164382
|
-
try {
|
|
164383
|
-
const { getTeamStore: getTeamStore2, isTeamStoreInitialized: isTeamStoreInitialized2 } = await Promise.resolve().then(() => (init_team_store(), team_store_exports));
|
|
164384
|
-
if (isTeamStoreInitialized2()) {
|
|
164385
|
-
const teamStore = getTeamStore2();
|
|
164386
|
-
const projectId2 = state.projectId;
|
|
164387
|
-
roles = teamStore.listRoles(projectId2);
|
|
164388
|
-
roleOccupancy = teamStore.getRoleOccupancy(projectId2);
|
|
164389
|
-
handoffs = teamStore.listHandoffs(projectId2);
|
|
164390
|
-
}
|
|
164391
|
-
} catch {
|
|
164392
|
-
}
|
|
164975
|
+
const parsedUrl = new URL(url, `http://127.0.0.1:${port}`);
|
|
164976
|
+
if (parsedUrl.pathname === "/api/team") {
|
|
164977
|
+
if (req.method !== "GET") {
|
|
164393
164978
|
sendJson(res, {
|
|
164394
|
-
|
|
164395
|
-
|
|
164396
|
-
|
|
164397
|
-
|
|
164398
|
-
|
|
164399
|
-
|
|
164400
|
-
tasks,
|
|
164401
|
-
availableTasks: available.length,
|
|
164402
|
-
roles,
|
|
164403
|
-
roleOccupancy,
|
|
164404
|
-
handoffs,
|
|
164405
|
-
// Resume data for "Continue this project" area
|
|
164406
|
-
openTasks: tasks.filter((t2) => t2.status === "pending" || t2.status === "in_progress").length,
|
|
164407
|
-
openHandoffs: handoffs.filter((h2) => h2.handoff_status === "open" || h2.handoffStatus === "open").length,
|
|
164408
|
-
totalUnread: agents.reduce((sum, a) => sum + teamInstances.messageBus.getUnreadCount(a.id), 0),
|
|
164409
|
-
activeSessions: agents.filter((a) => a.status === "active").length
|
|
164410
|
-
});
|
|
164411
|
-
} catch {
|
|
164412
|
-
sendJson(res, { agents: [], activeCount: 0, locks: [], tasks: [], availableTasks: 0, roles: [], roleOccupancy: [], handoffs: [] });
|
|
164979
|
+
status: "error",
|
|
164980
|
+
readOnly: true,
|
|
164981
|
+
error: "Coordination status is read-only",
|
|
164982
|
+
errorCode: "COORDINATION_STATUS_READ_ONLY"
|
|
164983
|
+
}, 405);
|
|
164984
|
+
return;
|
|
164413
164985
|
}
|
|
164986
|
+
const scope = parsedUrl.searchParams.get("scope") || "project";
|
|
164987
|
+
const snapshot = await buildTeamSnapshot(state.dataDir, state.projectId, scope, state.mode);
|
|
164988
|
+
sendJson(res, snapshot, snapshot.status === "error" ? 503 : 200);
|
|
164414
164989
|
return;
|
|
164415
164990
|
}
|
|
164416
164991
|
if (url.startsWith("/api/")) {
|
|
@@ -164431,13 +165006,12 @@ async function startDashboard(dataDir, port, staticDir, projectId, projectName,
|
|
|
164431
165006
|
server.listen(port, "127.0.0.1", () => {
|
|
164432
165007
|
const url = `http://127.0.0.1:${port}`;
|
|
164433
165008
|
const resolvedLabel = projectResolved ? "resolved" : "unresolved";
|
|
164434
|
-
const modeLabel =
|
|
165009
|
+
const modeLabel = "Standalone";
|
|
164435
165010
|
console.error(` Memorix Dashboard [${modeLabel}]`);
|
|
164436
165011
|
console.error(` \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);
|
|
164437
165012
|
console.error(` Mode: ${modeLabel}`);
|
|
164438
165013
|
console.error(` Project: ${projectName} (${projectId}) [${resolvedLabel}]`);
|
|
164439
165014
|
console.error(` Local: ${url}`);
|
|
164440
|
-
if (isControlPlane) console.error(` MCP: ${url}/mcp`);
|
|
164441
165015
|
console.error(` Data dir: ${dataDir}`);
|
|
164442
165016
|
console.error(`
|
|
164443
165017
|
Press Ctrl+C to stop
|
|
@@ -164460,10 +165034,14 @@ var init_server = __esm({
|
|
|
164460
165034
|
init_dotenv_loader();
|
|
164461
165035
|
init_yaml_loader();
|
|
164462
165036
|
init_yaml_loader();
|
|
165037
|
+
init_resolved_config();
|
|
164463
165038
|
init_graph_scope();
|
|
164464
165039
|
init_retention();
|
|
164465
165040
|
init_visibility();
|
|
165041
|
+
init_evidence_store();
|
|
165042
|
+
init_feedback();
|
|
164466
165043
|
init_maintenance();
|
|
165044
|
+
init_config_provenance();
|
|
164467
165045
|
MIME_TYPES = {
|
|
164468
165046
|
".html": "text/html; charset=utf-8",
|
|
164469
165047
|
".css": "text/css; charset=utf-8",
|
|
@@ -164931,7 +165509,7 @@ __export(planner_exports, {
|
|
|
164931
165509
|
materializeTaskGraph: () => materializeTaskGraph,
|
|
164932
165510
|
seedAutonomousPipeline: () => seedAutonomousPipeline
|
|
164933
165511
|
});
|
|
164934
|
-
import { randomUUID as
|
|
165512
|
+
import { randomUUID as randomUUID18 } from "crypto";
|
|
164935
165513
|
function isPlannerTask(metadata) {
|
|
164936
165514
|
if (!metadata) return null;
|
|
164937
165515
|
try {
|
|
@@ -164989,7 +165567,7 @@ function seedAutonomousPipeline(teamStore, projectId, config, opts) {
|
|
|
164989
165567
|
const maxIterations = config.maxIterations ?? 3;
|
|
164990
165568
|
const taskBudget = config.taskBudget ?? 15;
|
|
164991
165569
|
const structuredPlan = opts?.structuredPlan ?? true;
|
|
164992
|
-
const pipelineId =
|
|
165570
|
+
const pipelineId = randomUUID18();
|
|
164993
165571
|
const meta = {
|
|
164994
165572
|
plannerType: "plan",
|
|
164995
165573
|
pipelineId,
|
|
@@ -165661,8 +166239,8 @@ var init_official_skills = __esm({
|
|
|
165661
166239
|
"",
|
|
165662
166240
|
"| Situation | Prefer | CLI fallback |",
|
|
165663
166241
|
"|---|---|---|",
|
|
165664
|
-
'| Starting a coding task and needing the best task-lensed project map | `memorix_project_context` with the user\'s task | `memorix context "<task>" --brief-json` |',
|
|
165665
|
-
'| Continuing prior project work | `memorix_project_context` with the user\'s task | `memorix resume "<task>" --brief-json` |',
|
|
166242
|
+
'| Starting a coding task and needing the best task-lensed project map | `memorix_project_context` with the user\'s task | `memorix context "<task>" --fallback --brief-json` |',
|
|
166243
|
+
'| Continuing prior project work | `memorix_project_context` with the user\'s task | `memorix resume "<task>" --fallback --brief-json` |',
|
|
165666
166244
|
'| Need structured refs/freshness for code-bound memories | `memorix_context_pack` | `memorix codegraph context-pack --task "<topic>"` |',
|
|
165667
166245
|
'| Explicit memory graph question | `memorix_graph_context` | `memorix memory graph-context --query "<topic>"` |',
|
|
165668
166246
|
'| Specific past decision, bug, file, or change | `memorix_search` | `memorix memory search --query "<topic>"` |',
|
|
@@ -165675,7 +166253,7 @@ var init_official_skills = __esm({
|
|
|
165675
166253
|
"",
|
|
165676
166254
|
"- Default first step for non-trivial coding work: call `memorix_project_context` before progress files, dev-log reads, ad-hoc file reads, or git archaeology. Pass the user's actual task so Memorix can choose a bugfix, feature, release, onboarding, refactor, docs, test, or general brief. Start by reading its suggested files.",
|
|
165677
166255
|
"- In Claude Code headless/print-mode, an initial MCP `pending` status is not a failure by itself. Prefer MCP first: use the client's tool discovery/dynamic loading to find `memorix_project_context` when it is not in the first visible tool list.",
|
|
165678
|
-
'- Continuation fallback is mandatory: when the user asks to continue, resume, take over, or explain prior work and MCP cannot be called in this turn, run `memorix resume "<task>" --brief-json` exactly once before inspecting files, Git history, progress notes, or guessing. The absence of `.memorix` or visible memory files never proves project memory is empty. For a new task, use `memorix context "<task>" --brief-json` instead. Use `--json` only when a diagnostic needs the detailed legacy payload. If that one command fails, report it and proceed normally; do not probe help, enumerate commands, or chain broad searches.',
|
|
166256
|
+
'- Continuation fallback is mandatory: when the user asks to continue, resume, take over, or explain prior work and MCP cannot be called in this turn, run `memorix resume "<task>" --fallback --brief-json` exactly once before inspecting files, Git history, progress notes, or guessing. The absence of `.memorix` or visible memory files never proves project memory is empty. For a new task, use `memorix context "<task>" --fallback --brief-json` instead. Use `--json` only when a diagnostic needs the detailed legacy payload. If that one command fails, report it and proceed normally; do not probe help, enumerate commands, or chain broad searches.',
|
|
165679
166257
|
"- After a successful `memorix_project_context`, the brief is the default retrieval boundary. Do not call more Memorix retrieval tools after a complete brief. Use Context Pack, search, or detail only when the brief lacks a specific reference, freshness field, or fact needed for the task, or when the user explicitly asks for deeper history. In MCP, name that missing fact in `purpose` when intentionally expanding beyond the brief. Do not retrieve the same decision twice just to confirm an already-complete brief.",
|
|
165680
166258
|
"- If the user asks for read-only work or says not to modify files, do not call `memorix_store` just to record an assessment. Store only when the user explicitly asks to preserve it.",
|
|
165681
166259
|
"- Use `memorix_search` for a specific decision, bug, file, or prior change that the project context did not answer. Fetch detail only for a result you still need after the brief.",
|
|
@@ -166934,7 +167512,7 @@ alwaysApply: true
|
|
|
166934
167512
|
"",
|
|
166935
167513
|
`Default first step for non-trivial coding work: call \`memorix_project_context\` with the user's actual task before progress files, dev-log reads, ad-hoc file reads, or git archaeology. Memorix will choose a task-lensed brief (bugfix, feature, release, onboarding, refactor, docs, test, or general). When the task is continuing prior work, the same brief also includes a bounded prior-work projection. Treat its "Start here" files as the first ${contextNoun} files to inspect.`,
|
|
166936
167514
|
"",
|
|
166937
|
-
'If the MCP tool is not visible yet but the client supports tool discovery or dynamic loading, search/select `memorix_project_context` first. Continuation fallback is mandatory: when the user asks to continue, resume, take over, or explain prior work and MCP cannot be called in this turn, run exactly one CLI brief with the user\'s real task before inspecting files, Git history, progress notes, or guessing: `memorix resume "<task>" --brief-json`. For a new task, use `memorix context "<task>" --brief-json` instead. The absence of `.memorix` or visible memory files never proves project memory is empty. Use `--json` only when a diagnostic needs the detailed legacy payload. If that one command fails, report it and proceed normally. Do not probe help, enumerate commands, chain broad searches, wait indefinitely on MCP startup, or hand-write tool-call syntax.',
|
|
167515
|
+
'If the MCP tool is not visible yet but the client supports tool discovery or dynamic loading, search/select `memorix_project_context` first. Continuation fallback is mandatory: when the user asks to continue, resume, take over, or explain prior work and MCP cannot be called in this turn, run exactly one CLI brief with the user\'s real task before inspecting files, Git history, progress notes, or guessing: `memorix resume "<task>" --fallback --brief-json`. For a new task, use `memorix context "<task>" --fallback --brief-json` instead. The absence of `.memorix` or visible memory files never proves project memory is empty. Use `--json` only when a diagnostic needs the detailed legacy payload. If that one command fails, report it and proceed normally. Do not probe help, enumerate commands, chain broad searches, wait indefinitely on MCP startup, or hand-write tool-call syntax.',
|
|
166938
167516
|
"",
|
|
166939
167517
|
"After a successful `memorix_project_context` result, the brief is the default retrieval boundary. Do not call more Memorix retrieval tools after a complete brief. Use `memorix_context_pack`, `memorix_search`, or `memorix_detail` only when the brief lacks a specific reference, freshness field, or fact needed for the task, or when the user explicitly asks for deeper history. In MCP, name that missing fact in `purpose` when intentionally expanding beyond the brief. Do not retrieve the same decision twice just to confirm an already-complete brief.",
|
|
166940
167518
|
"If the user asks for read-only work or says not to modify files, do not call `memorix_store` just to record an assessment. Store only when the user explicitly asks to preserve it.",
|
|
@@ -167232,7 +167810,7 @@ __export(server_exports2, {
|
|
|
167232
167810
|
createMemorixServer: () => createMemorixServer,
|
|
167233
167811
|
shouldAwaitProjectRuntime: () => shouldAwaitProjectRuntime
|
|
167234
167812
|
});
|
|
167235
|
-
import { createHash as
|
|
167813
|
+
import { createHash as createHash16 } from "crypto";
|
|
167236
167814
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
167237
167815
|
import { z as z626 } from "zod";
|
|
167238
167816
|
function formatFormationStageDurations(stageDurationsMs) {
|
|
@@ -167316,7 +167894,7 @@ function coerceObjectArray(val) {
|
|
|
167316
167894
|
return [];
|
|
167317
167895
|
}
|
|
167318
167896
|
function createDeterministicInstanceId(projectId, agentType, agentName) {
|
|
167319
|
-
const digest2 =
|
|
167897
|
+
const digest2 = createHash16("sha256").update(projectId).update("\n").update(agentType).update("\n").update(agentName ?? "").digest("hex").slice(0, 24);
|
|
167320
167898
|
return `auto-${digest2}`;
|
|
167321
167899
|
}
|
|
167322
167900
|
function shouldAwaitProjectRuntime(toolName) {
|
|
@@ -167608,7 +168186,7 @@ The path should point to a directory containing a .git folder.`
|
|
|
167608
168186
|
};
|
|
167609
168187
|
const server = existingServer ?? new McpServer({
|
|
167610
168188
|
name: "memorix",
|
|
167611
|
-
version: true ? "1.
|
|
168189
|
+
version: true ? "1.8.1" : "1.0.1"
|
|
167612
168190
|
});
|
|
167613
168191
|
const originalRegisterTool = server.registerTool.bind(server);
|
|
167614
168192
|
server.registerTool = ((name, ...args) => {
|
|
@@ -170761,7 +171339,7 @@ ${json2}
|
|
|
170761
171339
|
}
|
|
170762
171340
|
}
|
|
170763
171341
|
console.error(`[memorix] Dashboard staticDir: ${staticDir}`);
|
|
170764
|
-
startDashboard2(projectDir2, portNum, staticDir, project.id, project.name, false,
|
|
171342
|
+
startDashboard2(projectDir2, portNum, staticDir, project.id, project.name, false, project.rootPath, projectResolved).then(() => {
|
|
170765
171343
|
dashboardRunning = true;
|
|
170766
171344
|
}).catch((err) => {
|
|
170767
171345
|
console.error("[memorix] Dashboard error:", err);
|
|
@@ -170787,7 +171365,7 @@ ${json2}
|
|
|
170787
171365
|
dashboardRunning = true;
|
|
170788
171366
|
const { exec: execCmd } = await import("child_process");
|
|
170789
171367
|
const openCmd = process.platform === "win32" ? `start "" "${url}"` : process.platform === "darwin" ? `open "${url}"` : `xdg-open "${url}"`;
|
|
170790
|
-
execCmd(openCmd, () => {
|
|
171368
|
+
execCmd(openCmd, { windowsHide: true }, () => {
|
|
170791
171369
|
});
|
|
170792
171370
|
return {
|
|
170793
171371
|
content: [{
|
|
@@ -170811,6 +171389,113 @@ ${json2}
|
|
|
170811
171389
|
}
|
|
170812
171390
|
}
|
|
170813
171391
|
);
|
|
171392
|
+
server.registerTool(
|
|
171393
|
+
"memorix_evidence",
|
|
171394
|
+
{
|
|
171395
|
+
title: "Evidence Cards",
|
|
171396
|
+
description: "Inspect the bounded, project-scoped provenance cards behind Memorix context. Use list for a compact index, get/events for one source, sync to repair the projection, and stale when known source files changed. Cards expose sourceRef, locator, capturedHash, and freshness.",
|
|
171397
|
+
inputSchema: {
|
|
171398
|
+
action: z626.enum(["list", "get", "sync", "stale", "events"]).describe("Evidence operation"),
|
|
171399
|
+
candidateKind: z626.enum(["observation", "code", "git", "test", "document", "workflow", "graph"]).optional().default("observation"),
|
|
171400
|
+
candidateId: z626.string().optional().describe("Candidate id, usually an observation id"),
|
|
171401
|
+
query: z626.string().optional().describe("Optional title/source query for list"),
|
|
171402
|
+
paths: z626.array(z626.string()).max(200).optional().describe("Changed source paths for stale"),
|
|
171403
|
+
reason: z626.string().max(500).optional().describe("Why evidence became stale"),
|
|
171404
|
+
limit: z626.number().int().positive().max(100).optional().default(20)
|
|
171405
|
+
}
|
|
171406
|
+
},
|
|
171407
|
+
async ({ action, candidateKind, candidateId, query, paths, reason, limit: limit2 }) => {
|
|
171408
|
+
const unresolved = requireResolvedProject("inspect evidence cards for the current project");
|
|
171409
|
+
if (unresolved) return unresolved;
|
|
171410
|
+
const cards = new EvidenceCardStore();
|
|
171411
|
+
await cards.init(projectDir2);
|
|
171412
|
+
if (action === "sync") {
|
|
171413
|
+
const observations2 = await getObservationStore().loadByProject(project.id);
|
|
171414
|
+
const synced = cards.syncObservations(observations2);
|
|
171415
|
+
return { content: [{ type: "text", text: JSON.stringify({ projectId: project.id, synced: synced.length, cards: synced.slice(0, limit2 ?? 20) }, null, 2) }] };
|
|
171416
|
+
}
|
|
171417
|
+
if (action === "stale") {
|
|
171418
|
+
const changed = cards.markStaleForPaths(project.id, paths ?? [], reason ?? "source file changed");
|
|
171419
|
+
return { content: [{ type: "text", text: JSON.stringify({ projectId: project.id, staleMarked: changed, paths: paths ?? [] }, null, 2) }] };
|
|
171420
|
+
}
|
|
171421
|
+
if (action === "get") {
|
|
171422
|
+
if (!candidateId?.trim()) return { content: [{ type: "text", text: "candidateId is required for evidence get." }], isError: true };
|
|
171423
|
+
const card = cards.get(project.id, candidateKind ?? "observation", candidateId.trim());
|
|
171424
|
+
if (!card) return { content: [{ type: "text", text: "Evidence card not found." }], isError: true };
|
|
171425
|
+
return { content: [{ type: "text", text: JSON.stringify({ card, events: cards.listEvents(card.id), projectId: project.id }, null, 2) }] };
|
|
171426
|
+
}
|
|
171427
|
+
if (action === "events") {
|
|
171428
|
+
if (!candidateId?.trim()) return { content: [{ type: "text", text: "candidateId is required for evidence events." }], isError: true };
|
|
171429
|
+
const card = cards.get(project.id, candidateKind ?? "observation", candidateId.trim());
|
|
171430
|
+
if (!card) return { content: [{ type: "text", text: "Evidence card not found." }], isError: true };
|
|
171431
|
+
return { content: [{ type: "text", text: JSON.stringify(cards.listEvents(card.id, limit2), null, 2) }] };
|
|
171432
|
+
}
|
|
171433
|
+
const needle = query?.trim().toLowerCase();
|
|
171434
|
+
const listed = cards.list(project.id, { limit: Math.max(limit2 ?? 20, 100) }).filter((card) => !needle || [card.title, card.summary, card.sourceRef, card.locator ?? ""].join(" ").toLowerCase().includes(needle)).slice(0, limit2 ?? 20);
|
|
171435
|
+
return { content: [{ type: "text", text: JSON.stringify({ projectId: project.id, cards: listed }, null, 2) }] };
|
|
171436
|
+
}
|
|
171437
|
+
);
|
|
171438
|
+
server.registerTool(
|
|
171439
|
+
"memorix_feedback",
|
|
171440
|
+
{
|
|
171441
|
+
title: "Memory Feedback",
|
|
171442
|
+
description: "Record or inspect auditable memory outcomes. Positive verification/use strengthens recall; correction, conflict, source change, or weaken lowers it. Use revoke with targetEventId to undo one prior signal without deleting audit history.",
|
|
171443
|
+
inputSchema: {
|
|
171444
|
+
action: z626.enum(["record", "show", "audit"]).describe("Feedback operation"),
|
|
171445
|
+
candidateKind: z626.enum(["observation", "claim", "durable-memory", "workflow"]).optional().default("observation"),
|
|
171446
|
+
candidateId: z626.string().describe("Memory or knowledge candidate id"),
|
|
171447
|
+
signal: z626.enum(["user-correction", "verification-success", "verification-failure", "code-change", "used", "not-used", "code-conflict", "strengthen", "weaken", "revoke"]).optional(),
|
|
171448
|
+
sourceRef: z626.string().max(500).optional().describe("Source of this feedback, such as test:run-42 or user:chat"),
|
|
171449
|
+
actor: z626.string().max(200).optional(),
|
|
171450
|
+
note: z626.string().max(2e3).optional(),
|
|
171451
|
+
targetEventId: z626.string().optional().describe("Existing event id when action=record and signal=revoke"),
|
|
171452
|
+
limit: z626.number().int().positive().max(200).optional().default(100)
|
|
171453
|
+
}
|
|
171454
|
+
},
|
|
171455
|
+
async ({ action, candidateKind, candidateId, signal, sourceRef, actor, note, targetEventId, limit: limit2 }) => {
|
|
171456
|
+
const unresolved = requireResolvedProject("record memory feedback for the current project");
|
|
171457
|
+
if (unresolved) return unresolved;
|
|
171458
|
+
const feedback = new MemoryFeedbackStore();
|
|
171459
|
+
await feedback.init(projectDir2);
|
|
171460
|
+
const kind = candidateKind ?? "observation";
|
|
171461
|
+
if (action === "show") {
|
|
171462
|
+
return { content: [{ type: "text", text: JSON.stringify(feedback.getState(project.id, kind, candidateId), null, 2) }] };
|
|
171463
|
+
}
|
|
171464
|
+
if (action === "audit") {
|
|
171465
|
+
return { content: [{ type: "text", text: JSON.stringify(feedback.audit(project.id, kind, candidateId, limit2), null, 2) }] };
|
|
171466
|
+
}
|
|
171467
|
+
if (!signal || !sourceRef?.trim()) {
|
|
171468
|
+
return { content: [{ type: "text", text: "record requires signal and sourceRef." }], isError: true };
|
|
171469
|
+
}
|
|
171470
|
+
try {
|
|
171471
|
+
const result = feedback.record({
|
|
171472
|
+
projectId: project.id,
|
|
171473
|
+
candidateKind: kind,
|
|
171474
|
+
candidateId,
|
|
171475
|
+
signal,
|
|
171476
|
+
sourceRef,
|
|
171477
|
+
...actor || currentAgentId ? { actor: actor ?? currentAgentId } : {},
|
|
171478
|
+
...note ? { note } : {},
|
|
171479
|
+
...targetEventId ? { targetEventId } : {}
|
|
171480
|
+
});
|
|
171481
|
+
if (kind === "observation") {
|
|
171482
|
+
const cards = new EvidenceCardStore();
|
|
171483
|
+
await cards.init(projectDir2);
|
|
171484
|
+
const card = cards.get(project.id, "observation", candidateId);
|
|
171485
|
+
if (card) {
|
|
171486
|
+
const verification = signal === "verification-success" || signal === "strengthen" ? "verified" : signal === "user-correction" || signal === "code-conflict" || signal === "weaken" ? "conflicted" : card.verification;
|
|
171487
|
+
cards.recordEvent(project.id, card.id, `feedback:${signal}`, note);
|
|
171488
|
+
if (verification !== card.verification) {
|
|
171489
|
+
cards.setVerification(project.id, card.id, verification);
|
|
171490
|
+
}
|
|
171491
|
+
}
|
|
171492
|
+
}
|
|
171493
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
171494
|
+
} catch (error) {
|
|
171495
|
+
return { content: [{ type: "text", text: error instanceof Error ? error.message : String(error) }], isError: true };
|
|
171496
|
+
}
|
|
171497
|
+
}
|
|
171498
|
+
);
|
|
170814
171499
|
if (teamFeaturesEnabled) {
|
|
170815
171500
|
const { initTeamStore: initTeamStore2 } = await Promise.resolve().then(() => (init_team_store(), team_store_exports));
|
|
170816
171501
|
initTeamStoreForProject = initTeamStore2;
|
|
@@ -170996,7 +171681,7 @@ ${lines.join("\n")}` }] };
|
|
|
170996
171681
|
server.registerTool(
|
|
170997
171682
|
"team_task",
|
|
170998
171683
|
{
|
|
170999
|
-
title: "Task
|
|
171684
|
+
title: "Task Status",
|
|
171000
171685
|
description: 'Create, claim, complete, or list tasks in the team task board. Supports dependencies. Action "create": create a task. Action "claim": assign to yourself (atomic, race-safe). Action "complete": mark done with result. Action "list": show tasks.',
|
|
171001
171686
|
inputSchema: {
|
|
171002
171687
|
action: z626.enum(["create", "claim", "complete", "list"]).describe("Operation to perform"),
|
|
@@ -171864,6 +172549,8 @@ var init_server2 = __esm({
|
|
|
171864
172549
|
init_launch_root();
|
|
171865
172550
|
init_aliases();
|
|
171866
172551
|
init_persistence();
|
|
172552
|
+
init_evidence_store();
|
|
172553
|
+
init_feedback();
|
|
171867
172554
|
init_syncer();
|
|
171868
172555
|
init_engine4();
|
|
171869
172556
|
init_tool_profile();
|
|
@@ -172048,7 +172735,7 @@ var init_serve_shared = __esm({
|
|
|
172048
172735
|
|
|
172049
172736
|
// src/cli/version.ts
|
|
172050
172737
|
function getCliVersion() {
|
|
172051
|
-
return true ? "1.
|
|
172738
|
+
return true ? "1.8.1" : pkg.version;
|
|
172052
172739
|
}
|
|
172053
172740
|
var init_version3 = __esm({
|
|
172054
172741
|
"src/cli/version.ts"() {
|