memorix 1.9.5 → 1.9.7
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 +53 -0
- package/README.md +6 -1
- package/README.zh-CN.md +6 -1
- package/dist/cli/index.js +1743 -348
- package/dist/index.d.ts +12 -7
- package/dist/index.js +1048 -266
- package/dist/maintenance-runner.js +339 -187
- package/dist/media-audio-runner.js +339 -187
- package/dist/media-video-runner.js +339 -187
- package/dist/memcode-runtime/CHANGELOG.md +53 -0
- package/dist/sdk.js +967 -241
- package/dist/vector-backfill-runner.js +339 -187
- package/docs/API_REFERENCE.md +36 -0
- package/docs/CONFIGURATION.md +43 -0
- package/docs/DEVELOPMENT.md +1 -1
- package/docs/KNOWN_ISSUES_AND_ROADMAP.md +49 -14
- package/docs/PERFORMANCE.md +46 -2
- package/docs/README.md +2 -1
- package/docs/SETUP.md +1 -1
- package/package.json +2 -1
- package/plugins/antigravity/memorix/plugin.json +1 -1
- package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
- package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/copilot/memorix/plugin.json +1 -1
- package/plugins/gemini/memorix/gemini-extension.json +1 -1
- package/plugins/hermes/memorix/plugin.yaml +1 -1
- package/plugins/omp/memorix/package.json +1 -1
- package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/pi/memorix/package.json +1 -1
- package/server.json +2 -2
- package/src/cli/capability-map.ts +1 -0
- package/src/cli/command-guide.ts +13 -1
- package/src/cli/commands/context.ts +2 -0
- package/src/cli/commands/continuity.ts +155 -0
- package/src/cli/commands/init.ts +5 -2
- package/src/cli/commands/serve-http.ts +242 -42
- package/src/cli/index.ts +3 -1
- package/src/cli/tui/ConfigureView.tsx +2 -0
- package/src/codegraph/auto-context.ts +17 -0
- package/src/config/legacy-loader.ts +2 -2
- package/src/config/resolved-config.ts +8 -5
- package/src/config/yaml-loader.ts +20 -10
- package/src/embedding/api-provider.ts +4 -2
- package/src/embedding/fastembed-provider.ts +47 -14
- package/src/embedding/transformers-provider.ts +29 -7
- package/src/evaluation/memory-quality-gate.ts +90 -0
- package/src/hooks/official-skills.ts +2 -0
- package/src/knowledge/context-assembly.ts +1 -0
- package/src/knowledge/context-receipt.ts +15 -0
- package/src/knowledge/task-continuity.ts +413 -0
- package/src/knowledge/workset.ts +77 -0
- package/src/llm/provider.ts +2 -1
- package/src/orchestrate/coordinator.ts +60 -0
- package/src/orchestrate/effect-ledger.ts +160 -0
- package/src/orchestrate/pipeline-trace.ts +40 -6
- package/src/runtime/maintenance-jobs.ts +12 -6
- package/src/server/modern-mcp-bridge.ts +153 -27
- package/src/server/tool-profile.ts +3 -2
- package/src/server.ts +129 -5
- package/src/store/orama-store.ts +16 -1
- package/src/store/sqlite-db.ts +144 -4
- package/src/store/sqlite-fts.ts +38 -16
- package/src/team/team-store.ts +62 -27
package/dist/index.js
CHANGED
|
@@ -286,6 +286,74 @@ var init_launch_root = __esm({
|
|
|
286
286
|
}
|
|
287
287
|
});
|
|
288
288
|
|
|
289
|
+
// src/store/sqlite-reliability.ts
|
|
290
|
+
function isTransientSqliteError(error) {
|
|
291
|
+
const code = error?.code;
|
|
292
|
+
if (typeof code === "string") {
|
|
293
|
+
return /^SQLITE_BUSY(?:_|$)/i.test(code);
|
|
294
|
+
}
|
|
295
|
+
return error instanceof Error && /\bdatabase is locked\b|\bdatabase is busy\b/i.test(error.message);
|
|
296
|
+
}
|
|
297
|
+
function isSqliteUnavailableError(error) {
|
|
298
|
+
return error instanceof SqliteUnavailableError || error instanceof Error && /SQLite is not available|better-sqlite3.*failed|node:sqlite.*failed|bun:sqlite.*failed/i.test(error.message);
|
|
299
|
+
}
|
|
300
|
+
function degradedReadError(storeName) {
|
|
301
|
+
return new Error(`[memorix] Cannot read ${storeName}: SQLite backend unavailable (memory is not loaded)`);
|
|
302
|
+
}
|
|
303
|
+
function degradedWriteError(storeName) {
|
|
304
|
+
return new Error(`[memorix] Cannot write ${storeName}: SQLite backend unavailable (degraded mode; read-only)`);
|
|
305
|
+
}
|
|
306
|
+
function formatSqliteFailure(error) {
|
|
307
|
+
return error instanceof Error && error.message ? error.message : String(error);
|
|
308
|
+
}
|
|
309
|
+
function delay(ms) {
|
|
310
|
+
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
311
|
+
}
|
|
312
|
+
async function retrySqliteBusy(operation, label) {
|
|
313
|
+
for (let attempt = 0; ; attempt++) {
|
|
314
|
+
try {
|
|
315
|
+
return await operation();
|
|
316
|
+
} catch (error) {
|
|
317
|
+
if (!isTransientSqliteError(error) || attempt >= SQLITE_BUSY_RETRY_DELAYS_MS.length) throw error;
|
|
318
|
+
const waitMs = SQLITE_BUSY_RETRY_DELAYS_MS[attempt];
|
|
319
|
+
console.error(
|
|
320
|
+
`[memorix] ${label} SQLite busy (attempt ${attempt + 1}/${SQLITE_BUSY_RETRY_DELAYS_MS.length + 1}), retrying in ${waitMs}ms`
|
|
321
|
+
);
|
|
322
|
+
await delay(waitMs);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
async function initializeSqliteStore(factory, dataDir, label) {
|
|
327
|
+
try {
|
|
328
|
+
loadBetterSqlite3();
|
|
329
|
+
} catch (error) {
|
|
330
|
+
throw new SqliteUnavailableError(error);
|
|
331
|
+
}
|
|
332
|
+
return retrySqliteBusy(async () => {
|
|
333
|
+
const store = factory();
|
|
334
|
+
await store.init(dataDir);
|
|
335
|
+
return store;
|
|
336
|
+
}, label);
|
|
337
|
+
}
|
|
338
|
+
var SQLITE_BUSY_RETRY_DELAYS_MS, SqliteUnavailableError;
|
|
339
|
+
var init_sqlite_reliability = __esm({
|
|
340
|
+
"src/store/sqlite-reliability.ts"() {
|
|
341
|
+
"use strict";
|
|
342
|
+
init_esm_shims();
|
|
343
|
+
init_sqlite_db();
|
|
344
|
+
SQLITE_BUSY_RETRY_DELAYS_MS = [50, 150, 400, 1e3, 2500];
|
|
345
|
+
SqliteUnavailableError = class extends Error {
|
|
346
|
+
code = "MEMORIX_SQLITE_UNAVAILABLE";
|
|
347
|
+
constructor(cause) {
|
|
348
|
+
super(
|
|
349
|
+
cause instanceof Error && cause.message ? cause.message : "[memorix] SQLite is unavailable (install a supported SQLite runtime)"
|
|
350
|
+
);
|
|
351
|
+
this.name = "SqliteUnavailableError";
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
|
|
289
357
|
// src/store/sqlite-fts.ts
|
|
290
358
|
function normalizeFtsToken(token) {
|
|
291
359
|
return token.replace(/"/g, '""');
|
|
@@ -299,22 +367,27 @@ function buildFtsQuery(query) {
|
|
|
299
367
|
function initializeObservationLexicalIndex(db2) {
|
|
300
368
|
const known = ftsAvailability.get(db2);
|
|
301
369
|
if (known !== void 0) return known;
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
db2.
|
|
370
|
+
let lastError;
|
|
371
|
+
for (let attempt = 1; attempt <= FTS_INIT_MAX_ATTEMPTS; attempt++) {
|
|
372
|
+
try {
|
|
373
|
+
db2.exec(CREATE_OBSERVATION_FTS);
|
|
374
|
+
const observationCount = Number(db2.prepare("SELECT COUNT(*) AS count FROM observations").get()?.count ?? 0);
|
|
375
|
+
const indexedCount = Number(db2.prepare(`SELECT COUNT(*) AS count FROM ${FTS_TABLE}`).get()?.count ?? 0);
|
|
376
|
+
if (observationCount !== indexedCount) {
|
|
377
|
+
db2.exec(`INSERT INTO ${FTS_TABLE}(${FTS_TABLE}) VALUES ('rebuild')`);
|
|
378
|
+
}
|
|
379
|
+
ftsAvailability.set(db2, true);
|
|
380
|
+
return true;
|
|
381
|
+
} catch (error) {
|
|
382
|
+
lastError = error;
|
|
383
|
+
if (!isTransientSqliteError(error) || attempt === FTS_INIT_MAX_ATTEMPTS) break;
|
|
308
384
|
}
|
|
309
|
-
ftsAvailability.set(db2, true);
|
|
310
|
-
return true;
|
|
311
|
-
} catch (error) {
|
|
312
|
-
ftsAvailability.set(db2, false);
|
|
313
|
-
console.warn(
|
|
314
|
-
`[memorix] SQLite FTS5 unavailable; using the existing search fallback: ${error instanceof Error ? error.message : String(error)}`
|
|
315
|
-
);
|
|
316
|
-
return false;
|
|
317
385
|
}
|
|
386
|
+
ftsAvailability.set(db2, false);
|
|
387
|
+
console.warn(
|
|
388
|
+
`[memorix] SQLite FTS5 unavailable; using the existing search fallback: ${lastError instanceof Error ? lastError.message : String(lastError)}`
|
|
389
|
+
);
|
|
390
|
+
return false;
|
|
318
391
|
}
|
|
319
392
|
function isObservationLexicalIndexEnabled(db2) {
|
|
320
393
|
return ftsAvailability.get(db2) === true;
|
|
@@ -368,11 +441,12 @@ function searchObservationLexically(db2, options) {
|
|
|
368
441
|
score: Math.max(0, Number(row.lexical_score ?? 0))
|
|
369
442
|
}));
|
|
370
443
|
}
|
|
371
|
-
var ftsAvailability, FTS_TABLE, CREATE_OBSERVATION_FTS;
|
|
444
|
+
var ftsAvailability, FTS_TABLE, CREATE_OBSERVATION_FTS, FTS_INIT_MAX_ATTEMPTS;
|
|
372
445
|
var init_sqlite_fts = __esm({
|
|
373
446
|
"src/store/sqlite-fts.ts"() {
|
|
374
447
|
"use strict";
|
|
375
448
|
init_esm_shims();
|
|
449
|
+
init_sqlite_reliability();
|
|
376
450
|
ftsAvailability = /* @__PURE__ */ new WeakMap();
|
|
377
451
|
FTS_TABLE = "observations_fts";
|
|
378
452
|
CREATE_OBSERVATION_FTS = `
|
|
@@ -406,6 +480,7 @@ CREATE TRIGGER IF NOT EXISTS observations_fts_au AFTER UPDATE ON observations BE
|
|
|
406
480
|
VALUES (new.id, new.entityName, new.title, new.narrative, new.facts, new.filesModified, new.concepts, new.attachments);
|
|
407
481
|
END;
|
|
408
482
|
`;
|
|
483
|
+
FTS_INIT_MAX_ATTEMPTS = 3;
|
|
409
484
|
}
|
|
410
485
|
});
|
|
411
486
|
|
|
@@ -444,11 +519,21 @@ function applySchemaMigrations(db2) {
|
|
|
444
519
|
apply();
|
|
445
520
|
}
|
|
446
521
|
}
|
|
522
|
+
function normalizeDataDir(dataDir) {
|
|
523
|
+
return path3.resolve(dataDir);
|
|
524
|
+
}
|
|
525
|
+
function touchDatabase(normalized, db2) {
|
|
526
|
+
_dbCache.delete(normalized);
|
|
527
|
+
_dbCache.set(normalized, db2);
|
|
528
|
+
}
|
|
447
529
|
function getDatabase(dataDir) {
|
|
448
|
-
const normalized =
|
|
530
|
+
const normalized = normalizeDataDir(dataDir);
|
|
449
531
|
assertNotHomeDataDir(normalized);
|
|
450
532
|
const existing = _dbCache.get(normalized);
|
|
451
|
-
if (existing)
|
|
533
|
+
if (existing) {
|
|
534
|
+
touchDatabase(normalized, existing);
|
|
535
|
+
return existing;
|
|
536
|
+
}
|
|
452
537
|
loadBetterSqlite3();
|
|
453
538
|
fs.mkdirSync(dataDir, { recursive: true });
|
|
454
539
|
const dbPath = path3.join(dataDir, "memorix.db");
|
|
@@ -478,6 +563,8 @@ function getDatabase(dataDir) {
|
|
|
478
563
|
db2.exec(CREATE_MAINTENANCE_JOBS_TABLE);
|
|
479
564
|
db2.exec(CREATE_MAINTENANCE_TARGETS_TABLE);
|
|
480
565
|
db2.exec(CREATE_COMPACTION_CHECKPOINTS_TABLE);
|
|
566
|
+
db2.exec(CREATE_TASK_CONTINUITY_EVENTS_TABLE);
|
|
567
|
+
db2.exec(CREATE_AGENT_EFFECTS_TABLE);
|
|
481
568
|
try {
|
|
482
569
|
db2.exec(`ALTER TABLE mini_skills ADD COLUMN sourceSnapshot TEXT NOT NULL DEFAULT ''`);
|
|
483
570
|
} catch {
|
|
@@ -516,7 +603,7 @@ function getDatabase(dataDir) {
|
|
|
516
603
|
db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('storage_generation', '0')`).run();
|
|
517
604
|
db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('next_id', '1')`).run();
|
|
518
605
|
db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('mini_skills_generation', '0')`).run();
|
|
519
|
-
|
|
606
|
+
touchDatabase(normalized, db2);
|
|
520
607
|
return db2;
|
|
521
608
|
} catch (error) {
|
|
522
609
|
try {
|
|
@@ -534,8 +621,9 @@ function closeAllDatabases() {
|
|
|
534
621
|
}
|
|
535
622
|
_dbCache.delete(key);
|
|
536
623
|
}
|
|
624
|
+
_dbLeases.clear();
|
|
537
625
|
}
|
|
538
|
-
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;
|
|
626
|
+
var BetterSqlite3, CREATE_OBSERVATIONS_TABLE, CREATE_MINI_SKILLS_TABLE, CREATE_SESSIONS_TABLE, CREATE_META_TABLE, CREATE_TEAM_AGENTS_TABLE, CREATE_TEAM_MESSAGES_TABLE, CREATE_TEAM_TASKS_TABLE, CREATE_TEAM_TASK_DEPS_TABLE, CREATE_TEAM_LOCKS_TABLE, CREATE_TEAM_ROLES_TABLE, CREATE_CHAT_TRANSCRIPT_TABLE, CREATE_GRAPH_ENTITIES_TABLE, CREATE_GRAPH_RELATIONS_TABLE, CREATE_CODE_FILES_TABLE, CREATE_CODE_SYMBOLS_TABLE, CREATE_CODE_EDGES_TABLE, CREATE_OBSERVATION_CODE_REFS_TABLE, CREATE_SCHEMA_MIGRATIONS_TABLE, CREATE_CODE_STATE_SNAPSHOTS_TABLE, CREATE_CODE_STATE_SNAPSHOT_FILES_TABLE, CREATE_KNOWLEDGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_CLAIM_EVIDENCE_TABLE, CREATE_KNOWLEDGE_CLAIM_EVENTS_TABLE, CREATE_KNOWLEDGE_WORKSPACES_TABLE, CREATE_KNOWLEDGE_PAGES_TABLE, CREATE_KNOWLEDGE_PAGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_PAGE_LINKS_TABLE, CREATE_KNOWLEDGE_PROPOSALS_TABLE, CREATE_KNOWLEDGE_WORKFLOWS_TABLE, CREATE_KNOWLEDGE_WORKFLOW_RUNS_TABLE, CREATE_LONG_TERM_MEMORIES_TABLE, CREATE_LONG_TERM_MEMORY_EVIDENCE_TABLE, CREATE_LONG_TERM_MEMORY_EVENTS_TABLE, CREATE_MEMORY_OUTCOME_SIGNALS_TABLE, CREATE_MEDIA_ASSETS_TABLE, CREATE_MEDIA_ASSET_LINKS_TABLE, CREATE_MEDIA_DERIVATIONS_TABLE, CREATE_MEDIA_EMBEDDING_PROFILES_TABLE, CREATE_MEDIA_EMBEDDINGS_TABLE, CREATE_MEDIA_JOBS_TABLE, CREATE_MAINTENANCE_JOBS_TABLE, CREATE_MAINTENANCE_TARGETS_TABLE, CREATE_COMPACTION_CHECKPOINTS_TABLE, CREATE_EVIDENCE_CARDS_TABLE, CREATE_EVIDENCE_CARD_EVENTS_TABLE, CREATE_MEMORY_FEEDBACK_STATES_TABLE, CREATE_MEMORY_FEEDBACK_EVENTS_TABLE, CREATE_TASK_CONTINUITY_EVENTS_TABLE, CREATE_AGENT_EFFECTS_TABLE, CREATE_MCP_BINDINGS_TABLE, CREATE_INDEXES, SCHEMA_MIGRATIONS, _dbCache, _dbLeases;
|
|
539
627
|
var init_sqlite_db = __esm({
|
|
540
628
|
"src/store/sqlite-db.ts"() {
|
|
541
629
|
"use strict";
|
|
@@ -1252,6 +1340,43 @@ CREATE TABLE IF NOT EXISTS memory_feedback_events (
|
|
|
1252
1340
|
delta REAL NOT NULL DEFAULT 0,
|
|
1253
1341
|
observed_at TEXT NOT NULL
|
|
1254
1342
|
);
|
|
1343
|
+
`;
|
|
1344
|
+
CREATE_TASK_CONTINUITY_EVENTS_TABLE = `
|
|
1345
|
+
CREATE TABLE IF NOT EXISTS task_continuity_events (
|
|
1346
|
+
id TEXT PRIMARY KEY,
|
|
1347
|
+
project_id TEXT NOT NULL,
|
|
1348
|
+
task_id TEXT NOT NULL,
|
|
1349
|
+
task TEXT NOT NULL,
|
|
1350
|
+
kind TEXT NOT NULL,
|
|
1351
|
+
content TEXT NOT NULL,
|
|
1352
|
+
item_status TEXT,
|
|
1353
|
+
source_ref TEXT,
|
|
1354
|
+
evidence_json TEXT NOT NULL DEFAULT '[]',
|
|
1355
|
+
actor TEXT,
|
|
1356
|
+
created_at TEXT NOT NULL,
|
|
1357
|
+
event_key TEXT,
|
|
1358
|
+
item_key TEXT,
|
|
1359
|
+
supersedes_id TEXT
|
|
1360
|
+
);
|
|
1361
|
+
`;
|
|
1362
|
+
CREATE_AGENT_EFFECTS_TABLE = `
|
|
1363
|
+
CREATE TABLE IF NOT EXISTS agent_effects (
|
|
1364
|
+
id TEXT PRIMARY KEY,
|
|
1365
|
+
pipeline_id TEXT NOT NULL,
|
|
1366
|
+
task_id TEXT NOT NULL,
|
|
1367
|
+
attempt INTEGER NOT NULL,
|
|
1368
|
+
effect_key TEXT NOT NULL,
|
|
1369
|
+
tool TEXT NOT NULL,
|
|
1370
|
+
risk_tier TEXT NOT NULL,
|
|
1371
|
+
replay_policy TEXT NOT NULL,
|
|
1372
|
+
status TEXT NOT NULL,
|
|
1373
|
+
call_id TEXT,
|
|
1374
|
+
idempotency_key TEXT NOT NULL,
|
|
1375
|
+
input_fingerprint TEXT,
|
|
1376
|
+
detail TEXT,
|
|
1377
|
+
started_at INTEGER NOT NULL,
|
|
1378
|
+
finished_at INTEGER
|
|
1379
|
+
);
|
|
1255
1380
|
`;
|
|
1256
1381
|
CREATE_MCP_BINDINGS_TABLE = `
|
|
1257
1382
|
CREATE TABLE IF NOT EXISTS mcp_bindings (
|
|
@@ -1330,7 +1455,18 @@ CREATE INDEX IF NOT EXISTS idx_evidence_cards_candidate ON evidence_cards(projec
|
|
|
1330
1455
|
CREATE INDEX IF NOT EXISTS idx_evidence_card_events_card ON evidence_card_events(card_id, created_at);
|
|
1331
1456
|
CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC);
|
|
1332
1457
|
CREATE INDEX IF NOT EXISTS idx_memory_feedback_events_candidate ON memory_feedback_events(project_id, candidate_kind, candidate_id, observed_at DESC);
|
|
1458
|
+
CREATE INDEX IF NOT EXISTS idx_task_continuity_project_task ON task_continuity_events(project_id, task_id, created_at ASC);
|
|
1459
|
+
CREATE INDEX IF NOT EXISTS idx_task_continuity_project_recent ON task_continuity_events(project_id, created_at DESC);
|
|
1460
|
+
CREATE INDEX IF NOT EXISTS idx_task_continuity_item ON task_continuity_events(project_id, task_id, kind, item_key, created_at DESC);
|
|
1461
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_task_continuity_event_key
|
|
1462
|
+
ON task_continuity_events(project_id, task_id, event_key)
|
|
1463
|
+
WHERE event_key IS NOT NULL;
|
|
1464
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_agent_effect_identity
|
|
1465
|
+
ON agent_effects(pipeline_id, task_id, attempt, effect_key);
|
|
1466
|
+
CREATE INDEX IF NOT EXISTS idx_agent_effect_pipeline ON agent_effects(pipeline_id, started_at ASC);
|
|
1333
1467
|
CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC);
|
|
1468
|
+
CREATE INDEX IF NOT EXISTS idx_mcp_bindings_root ON mcp_bindings(project_root, last_used_at DESC);
|
|
1469
|
+
CREATE INDEX IF NOT EXISTS idx_mcp_bindings_expiry ON mcp_bindings(expires_at);
|
|
1334
1470
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
1335
1471
|
ON maintenance_jobs(project_id, kind, dedupe_key)
|
|
1336
1472
|
WHERE status IN ('pending', 'running', 'retry');
|
|
@@ -1501,6 +1637,8 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
|
1501
1637
|
db2.exec("CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC)");
|
|
1502
1638
|
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)");
|
|
1503
1639
|
db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC)");
|
|
1640
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_root ON mcp_bindings(project_root, last_used_at DESC)");
|
|
1641
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_expiry ON mcp_bindings(expires_at)");
|
|
1504
1642
|
}
|
|
1505
1643
|
},
|
|
1506
1644
|
{
|
|
@@ -1511,9 +1649,22 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
|
1511
1649
|
addColumnIfMissing(db2, "code_symbols", "source", "source TEXT");
|
|
1512
1650
|
addColumnIfMissing(db2, "code_edges", "source", "source TEXT");
|
|
1513
1651
|
}
|
|
1652
|
+
},
|
|
1653
|
+
{
|
|
1654
|
+
id: "1.9-continuity-v2",
|
|
1655
|
+
apply: (db2) => {
|
|
1656
|
+
addColumnIfMissing(db2, "task_continuity_events", "event_key", "event_key TEXT");
|
|
1657
|
+
addColumnIfMissing(db2, "task_continuity_events", "item_key", "item_key TEXT");
|
|
1658
|
+
addColumnIfMissing(db2, "task_continuity_events", "supersedes_id", "supersedes_id TEXT");
|
|
1659
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_task_continuity_item ON task_continuity_events(project_id, task_id, kind, item_key, created_at DESC)");
|
|
1660
|
+
db2.exec(`CREATE UNIQUE INDEX IF NOT EXISTS idx_task_continuity_event_key
|
|
1661
|
+
ON task_continuity_events(project_id, task_id, event_key)
|
|
1662
|
+
WHERE event_key IS NOT NULL`);
|
|
1663
|
+
}
|
|
1514
1664
|
}
|
|
1515
1665
|
];
|
|
1516
1666
|
_dbCache = /* @__PURE__ */ new Map();
|
|
1667
|
+
_dbLeases = /* @__PURE__ */ new Map();
|
|
1517
1668
|
}
|
|
1518
1669
|
});
|
|
1519
1670
|
|
|
@@ -2481,74 +2632,6 @@ var init_types = __esm({
|
|
|
2481
2632
|
}
|
|
2482
2633
|
});
|
|
2483
2634
|
|
|
2484
|
-
// src/store/sqlite-reliability.ts
|
|
2485
|
-
function isTransientSqliteError(error) {
|
|
2486
|
-
const code = error?.code;
|
|
2487
|
-
if (typeof code === "string") {
|
|
2488
|
-
return /^SQLITE_BUSY(?:_|$)/i.test(code);
|
|
2489
|
-
}
|
|
2490
|
-
return error instanceof Error && /\bdatabase is locked\b|\bdatabase is busy\b/i.test(error.message);
|
|
2491
|
-
}
|
|
2492
|
-
function isSqliteUnavailableError(error) {
|
|
2493
|
-
return error instanceof SqliteUnavailableError || error instanceof Error && /SQLite is not available|better-sqlite3.*failed|node:sqlite.*failed|bun:sqlite.*failed/i.test(error.message);
|
|
2494
|
-
}
|
|
2495
|
-
function degradedReadError(storeName) {
|
|
2496
|
-
return new Error(`[memorix] Cannot read ${storeName}: SQLite backend unavailable (memory is not loaded)`);
|
|
2497
|
-
}
|
|
2498
|
-
function degradedWriteError(storeName) {
|
|
2499
|
-
return new Error(`[memorix] Cannot write ${storeName}: SQLite backend unavailable (degraded mode; read-only)`);
|
|
2500
|
-
}
|
|
2501
|
-
function formatSqliteFailure(error) {
|
|
2502
|
-
return error instanceof Error && error.message ? error.message : String(error);
|
|
2503
|
-
}
|
|
2504
|
-
function delay(ms) {
|
|
2505
|
-
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
2506
|
-
}
|
|
2507
|
-
async function retrySqliteBusy(operation, label) {
|
|
2508
|
-
for (let attempt = 0; ; attempt++) {
|
|
2509
|
-
try {
|
|
2510
|
-
return await operation();
|
|
2511
|
-
} catch (error) {
|
|
2512
|
-
if (!isTransientSqliteError(error) || attempt >= SQLITE_BUSY_RETRY_DELAYS_MS.length) throw error;
|
|
2513
|
-
const waitMs = SQLITE_BUSY_RETRY_DELAYS_MS[attempt];
|
|
2514
|
-
console.error(
|
|
2515
|
-
`[memorix] ${label} SQLite busy (attempt ${attempt + 1}/${SQLITE_BUSY_RETRY_DELAYS_MS.length + 1}), retrying in ${waitMs}ms`
|
|
2516
|
-
);
|
|
2517
|
-
await delay(waitMs);
|
|
2518
|
-
}
|
|
2519
|
-
}
|
|
2520
|
-
}
|
|
2521
|
-
async function initializeSqliteStore(factory, dataDir, label) {
|
|
2522
|
-
try {
|
|
2523
|
-
loadBetterSqlite3();
|
|
2524
|
-
} catch (error) {
|
|
2525
|
-
throw new SqliteUnavailableError(error);
|
|
2526
|
-
}
|
|
2527
|
-
return retrySqliteBusy(async () => {
|
|
2528
|
-
const store = factory();
|
|
2529
|
-
await store.init(dataDir);
|
|
2530
|
-
return store;
|
|
2531
|
-
}, label);
|
|
2532
|
-
}
|
|
2533
|
-
var SQLITE_BUSY_RETRY_DELAYS_MS, SqliteUnavailableError;
|
|
2534
|
-
var init_sqlite_reliability = __esm({
|
|
2535
|
-
"src/store/sqlite-reliability.ts"() {
|
|
2536
|
-
"use strict";
|
|
2537
|
-
init_esm_shims();
|
|
2538
|
-
init_sqlite_db();
|
|
2539
|
-
SQLITE_BUSY_RETRY_DELAYS_MS = [50, 150, 400, 1e3, 2500];
|
|
2540
|
-
SqliteUnavailableError = class extends Error {
|
|
2541
|
-
code = "MEMORIX_SQLITE_UNAVAILABLE";
|
|
2542
|
-
constructor(cause) {
|
|
2543
|
-
super(
|
|
2544
|
-
cause instanceof Error && cause.message ? cause.message : "[memorix] SQLite is unavailable (install a supported SQLite runtime)"
|
|
2545
|
-
);
|
|
2546
|
-
this.name = "SqliteUnavailableError";
|
|
2547
|
-
}
|
|
2548
|
-
};
|
|
2549
|
-
}
|
|
2550
|
-
});
|
|
2551
|
-
|
|
2552
2635
|
// src/store/mini-skill-store.ts
|
|
2553
2636
|
var mini_skill_store_exports = {};
|
|
2554
2637
|
__export(mini_skill_store_exports, {
|
|
@@ -3228,18 +3311,23 @@ __export(yaml_loader_exports, {
|
|
|
3228
3311
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
3229
3312
|
import { homedir } from "os";
|
|
3230
3313
|
import { parse as parseYamlDocument } from "yaml";
|
|
3314
|
+
function cacheKey(homeDir, projectRoot) {
|
|
3315
|
+
return `${homeDir}\0${projectRoot ?? ""}`;
|
|
3316
|
+
}
|
|
3231
3317
|
function initProjectRoot(root) {
|
|
3232
3318
|
globalProjectRoot = root;
|
|
3233
|
-
configCache.delete(root);
|
|
3319
|
+
configCache.delete(cacheKey(homedir(), root));
|
|
3234
3320
|
}
|
|
3235
3321
|
function clearProjectRoot() {
|
|
3236
3322
|
globalProjectRoot = null;
|
|
3237
3323
|
}
|
|
3238
|
-
function loadYamlConfig(projectRoot) {
|
|
3324
|
+
function loadYamlConfig(projectRoot, options = {}) {
|
|
3325
|
+
const homeDir = options.homeDir ?? homedir();
|
|
3239
3326
|
const resolvedRoot = projectRoot === null ? null : projectRoot ?? globalProjectRoot ?? null;
|
|
3240
|
-
const
|
|
3327
|
+
const key = cacheKey(homeDir, resolvedRoot);
|
|
3328
|
+
const cached = configCache.get(key);
|
|
3241
3329
|
if (cached) return cached;
|
|
3242
|
-
const userYaml = getGlobalYamlPath(
|
|
3330
|
+
const userYaml = getGlobalYamlPath(homeDir);
|
|
3243
3331
|
const projectYaml = resolvedRoot ? getProjectYamlPath(resolvedRoot) : null;
|
|
3244
3332
|
let userConfig = {};
|
|
3245
3333
|
let projectConfig = {};
|
|
@@ -3271,12 +3359,12 @@ function loadYamlConfig(projectRoot) {
|
|
|
3271
3359
|
server: { ...userConfig.server, ...projectConfig.server },
|
|
3272
3360
|
team: { ...userConfig.team, ...projectConfig.team }
|
|
3273
3361
|
};
|
|
3274
|
-
configCache.set(
|
|
3362
|
+
configCache.set(key, merged);
|
|
3275
3363
|
return merged;
|
|
3276
3364
|
}
|
|
3277
|
-
function resetYamlConfigCache(projectRoot) {
|
|
3365
|
+
function resetYamlConfigCache(projectRoot, homeDir = homedir()) {
|
|
3278
3366
|
if (projectRoot !== void 0) {
|
|
3279
|
-
configCache.delete(projectRoot ?? null);
|
|
3367
|
+
configCache.delete(cacheKey(homeDir, projectRoot ?? null));
|
|
3280
3368
|
} else {
|
|
3281
3369
|
configCache.clear();
|
|
3282
3370
|
}
|
|
@@ -3486,9 +3574,9 @@ var init_detector = __esm({
|
|
|
3486
3574
|
// src/config/legacy-loader.ts
|
|
3487
3575
|
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
|
|
3488
3576
|
import { homedir as homedir2 } from "os";
|
|
3489
|
-
function loadFileConfig() {
|
|
3577
|
+
function loadFileConfig(homeDir = homedir2()) {
|
|
3490
3578
|
if (cachedConfig !== null) return cachedConfig;
|
|
3491
|
-
const configPath = getLegacyConfigJsonPath(
|
|
3579
|
+
const configPath = getLegacyConfigJsonPath(homeDir);
|
|
3492
3580
|
try {
|
|
3493
3581
|
if (existsSync4(configPath)) {
|
|
3494
3582
|
cachedConfig = JSON.parse(readFileSync4(configPath, "utf-8"));
|
|
@@ -3518,15 +3606,15 @@ import { homedir as homedir3 } from "os";
|
|
|
3518
3606
|
function loadTomlConfig(options = {}) {
|
|
3519
3607
|
const homeDir = options.homeDir ?? homedir3();
|
|
3520
3608
|
const projectRoot = options.projectRoot ?? null;
|
|
3521
|
-
const
|
|
3522
|
-
const cached = configCache2.get(
|
|
3609
|
+
const cacheKey3 = `${homeDir}\0${projectRoot ?? ""}`;
|
|
3610
|
+
const cached = configCache2.get(cacheKey3);
|
|
3523
3611
|
if (cached) return cached;
|
|
3524
3612
|
const userToml = getGlobalConfigTomlPath(homeDir);
|
|
3525
3613
|
const projectToml = projectRoot ? getProjectConfigTomlPath(projectRoot) : null;
|
|
3526
3614
|
const userConfig = existsSync5(userToml) ? parseTomlConfig(readFileSync5(userToml, "utf8"), userToml) : {};
|
|
3527
3615
|
const projectConfig = projectToml && existsSync5(projectToml) ? parseTomlConfig(readFileSync5(projectToml, "utf8"), projectToml) : {};
|
|
3528
3616
|
const merged = mergeTomlConfig(userConfig, projectConfig);
|
|
3529
|
-
configCache2.set(
|
|
3617
|
+
configCache2.set(cacheKey3, merged);
|
|
3530
3618
|
return merged;
|
|
3531
3619
|
}
|
|
3532
3620
|
function mergeTomlConfig(base, override) {
|
|
@@ -3726,8 +3814,8 @@ function getResolvedConfig(options = {}) {
|
|
|
3726
3814
|
const projectRoot = options.projectRoot === void 0 ? detectProject()?.rootPath ?? null : options.projectRoot;
|
|
3727
3815
|
loadDotenv(projectRoot === null ? void 0 : projectRoot ?? void 0, { userHomeDir: homeDir });
|
|
3728
3816
|
const toml = loadTomlConfig({ projectRoot: projectRoot ?? null, homeDir });
|
|
3729
|
-
const yaml = loadYamlConfig(projectRoot ?? null);
|
|
3730
|
-
const legacy = loadFileConfig();
|
|
3817
|
+
const yaml = loadYamlConfig(projectRoot ?? null, { homeDir });
|
|
3818
|
+
const legacy = loadFileConfig(homeDir);
|
|
3731
3819
|
const embeddingBaseUrl = first(process.env.MEMORIX_EMBEDDING_BASE_URL, toml.embedding?.base_url, yaml.embedding?.baseUrl, legacy.embeddingApi?.baseUrl);
|
|
3732
3820
|
const openRouterEmbeddingApiKey = isOpenRouterUrl(embeddingBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
|
|
3733
3821
|
const memoryLlmProvider = first(
|
|
@@ -3749,15 +3837,17 @@ function getResolvedConfig(options = {}) {
|
|
|
3749
3837
|
legacy.llm?.baseUrl
|
|
3750
3838
|
);
|
|
3751
3839
|
const openRouterMemoryLlmApiKey = isOpenRouterMemoryLane(memoryLlmProvider, memoryLlmBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
|
|
3840
|
+
const isAtlasCloud = memoryLlmProvider === "atlascloud";
|
|
3752
3841
|
const memoryLlmApiKey = first(
|
|
3753
3842
|
process.env.MEMORIX_LLM_API_KEY,
|
|
3754
3843
|
process.env.MEMORIX_API_KEY,
|
|
3755
3844
|
toml.memory?.llm?.api_key,
|
|
3756
3845
|
yaml.llm?.apiKey,
|
|
3757
3846
|
legacy.llm?.apiKey,
|
|
3758
|
-
|
|
3759
|
-
process.env.
|
|
3760
|
-
|
|
3847
|
+
// Never borrow another provider's credentials for the Atlas Cloud preset.
|
|
3848
|
+
isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : process.env.OPENAI_API_KEY,
|
|
3849
|
+
isAtlasCloud ? void 0 : process.env.ANTHROPIC_API_KEY,
|
|
3850
|
+
isAtlasCloud ? void 0 : openRouterMemoryLlmApiKey
|
|
3761
3851
|
);
|
|
3762
3852
|
const resolved = {
|
|
3763
3853
|
agent: {
|
|
@@ -3936,7 +4026,8 @@ function getEnvSourceNames() {
|
|
|
3936
4026
|
"MEMORIX_CODEGRAPH_EXTERNAL_CONTEXT",
|
|
3937
4027
|
"MEMORIX_CODEGRAPH_EXTERNAL_COMMAND",
|
|
3938
4028
|
"MEMORIX_CODEGRAPH_EXTERNAL_TIMEOUT_MS",
|
|
3939
|
-
"OPENROUTER_API_KEY"
|
|
4029
|
+
"OPENROUTER_API_KEY",
|
|
4030
|
+
"ATLASCLOUD_API_KEY"
|
|
3940
4031
|
].filter((name) => process.env[name]);
|
|
3941
4032
|
}
|
|
3942
4033
|
function isOpenRouterUrl(value) {
|
|
@@ -4155,12 +4246,45 @@ function textHash(text3) {
|
|
|
4155
4246
|
async function loadDiskCache() {
|
|
4156
4247
|
try {
|
|
4157
4248
|
const raw = await readFile(CACHE_FILE, "utf-8");
|
|
4249
|
+
if (Buffer.byteLength(raw, "utf8") > MAX_CACHE_FILE_BYTES) {
|
|
4250
|
+
console.error("[memorix] FastEmbed cache exceeds the disk load limit; starting with an empty cache");
|
|
4251
|
+
return;
|
|
4252
|
+
}
|
|
4158
4253
|
const entries = JSON.parse(raw);
|
|
4159
|
-
|
|
4160
|
-
|
|
4254
|
+
if (!Array.isArray(entries)) return;
|
|
4255
|
+
for (const entry of entries) {
|
|
4256
|
+
if (!Array.isArray(entry) || typeof entry[0] !== "string" || !isVector(entry[1])) continue;
|
|
4257
|
+
cacheSet(entry[0], entry[1], false);
|
|
4258
|
+
}
|
|
4259
|
+
console.error(`[memorix] Loaded ${cache.size} cached embeddings from disk`);
|
|
4161
4260
|
} catch {
|
|
4162
4261
|
}
|
|
4163
4262
|
}
|
|
4263
|
+
function isVector(value) {
|
|
4264
|
+
return Array.isArray(value) && value.every((entry) => typeof entry === "number");
|
|
4265
|
+
}
|
|
4266
|
+
function maxCachePayloadBytes() {
|
|
4267
|
+
const raw = Number.parseInt(process.env.MEMORIX_EMBEDDING_CACHE_MAX_BYTES ?? "", 10);
|
|
4268
|
+
return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_CACHE_PAYLOAD_BYTES;
|
|
4269
|
+
}
|
|
4270
|
+
function cacheSet(hash4, value, markDirty = true) {
|
|
4271
|
+
const incomingBytes = value.length * 8;
|
|
4272
|
+
if (incomingBytes > maxCachePayloadBytes()) return;
|
|
4273
|
+
const existing = cache.get(hash4);
|
|
4274
|
+
if (existing) cachePayloadBytes -= existing.length * 8;
|
|
4275
|
+
else {
|
|
4276
|
+
while (cache.size >= MAX_CACHE_SIZE || cachePayloadBytes + incomingBytes > maxCachePayloadBytes()) {
|
|
4277
|
+
const firstKey = cache.keys().next().value;
|
|
4278
|
+
if (firstKey === void 0) break;
|
|
4279
|
+
const old = cache.get(firstKey);
|
|
4280
|
+
cache.delete(firstKey);
|
|
4281
|
+
if (old) cachePayloadBytes -= old.length * 8;
|
|
4282
|
+
}
|
|
4283
|
+
}
|
|
4284
|
+
cache.set(hash4, value);
|
|
4285
|
+
cachePayloadBytes += incomingBytes;
|
|
4286
|
+
if (markDirty) diskCacheDirty = true;
|
|
4287
|
+
}
|
|
4164
4288
|
async function saveDiskCache() {
|
|
4165
4289
|
if (!diskCacheDirty) return;
|
|
4166
4290
|
try {
|
|
@@ -4171,7 +4295,7 @@ async function saveDiskCache() {
|
|
|
4171
4295
|
} catch {
|
|
4172
4296
|
}
|
|
4173
4297
|
}
|
|
4174
|
-
var CACHE_DIR, CACHE_FILE, cache, MAX_CACHE_SIZE, diskCacheDirty, FastEmbedProvider;
|
|
4298
|
+
var CACHE_DIR, CACHE_FILE, cache, MAX_CACHE_SIZE, DEFAULT_CACHE_PAYLOAD_BYTES, MAX_CACHE_FILE_BYTES, cachePayloadBytes, diskCacheDirty, FastEmbedProvider;
|
|
4175
4299
|
var init_fastembed_provider = __esm({
|
|
4176
4300
|
"src/embedding/fastembed-provider.ts"() {
|
|
4177
4301
|
"use strict";
|
|
@@ -4181,6 +4305,9 @@ var init_fastembed_provider = __esm({
|
|
|
4181
4305
|
CACHE_FILE = join2(CACHE_DIR, ".embedding-cache.json");
|
|
4182
4306
|
cache = /* @__PURE__ */ new Map();
|
|
4183
4307
|
MAX_CACHE_SIZE = 5e3;
|
|
4308
|
+
DEFAULT_CACHE_PAYLOAD_BYTES = 64 * 1024 * 1024;
|
|
4309
|
+
MAX_CACHE_FILE_BYTES = 128 * 1024 * 1024;
|
|
4310
|
+
cachePayloadBytes = 0;
|
|
4184
4311
|
diskCacheDirty = false;
|
|
4185
4312
|
FastEmbedProvider = class _FastEmbedProvider {
|
|
4186
4313
|
name = "fastembed-bge-small";
|
|
@@ -4222,7 +4349,7 @@ var init_fastembed_provider = __esm({
|
|
|
4222
4349
|
if (result.length !== this.dimensions) {
|
|
4223
4350
|
throw new Error(`Expected ${this.dimensions}d embedding, got ${result.length}d`);
|
|
4224
4351
|
}
|
|
4225
|
-
|
|
4352
|
+
cacheSet(hash4, result);
|
|
4226
4353
|
return result;
|
|
4227
4354
|
}
|
|
4228
4355
|
async embedBatch(texts) {
|
|
@@ -4247,7 +4374,7 @@ var init_fastembed_provider = __esm({
|
|
|
4247
4374
|
const originalIdx = uncachedIndices[batchIdx];
|
|
4248
4375
|
const plain = Array.from(vec);
|
|
4249
4376
|
results[originalIdx] = plain;
|
|
4250
|
-
|
|
4377
|
+
cacheSet(textHash(uncachedTexts[batchIdx]), plain);
|
|
4251
4378
|
batchIdx++;
|
|
4252
4379
|
}
|
|
4253
4380
|
}
|
|
@@ -4255,14 +4382,6 @@ var init_fastembed_provider = __esm({
|
|
|
4255
4382
|
}
|
|
4256
4383
|
return results;
|
|
4257
4384
|
}
|
|
4258
|
-
cacheSet(hash4, value) {
|
|
4259
|
-
if (cache.size >= MAX_CACHE_SIZE) {
|
|
4260
|
-
const firstKey = cache.keys().next().value;
|
|
4261
|
-
if (firstKey !== void 0) cache.delete(firstKey);
|
|
4262
|
-
}
|
|
4263
|
-
cache.set(hash4, value);
|
|
4264
|
-
diskCacheDirty = true;
|
|
4265
|
-
}
|
|
4266
4385
|
};
|
|
4267
4386
|
}
|
|
4268
4387
|
});
|
|
@@ -4272,7 +4391,15 @@ var transformers_provider_exports = {};
|
|
|
4272
4391
|
__export(transformers_provider_exports, {
|
|
4273
4392
|
TransformersProvider: () => TransformersProvider
|
|
4274
4393
|
});
|
|
4275
|
-
|
|
4394
|
+
import { createHash as createHash2 } from "crypto";
|
|
4395
|
+
function cacheKey2(text3) {
|
|
4396
|
+
return createHash2("sha256").update(text3).digest("hex");
|
|
4397
|
+
}
|
|
4398
|
+
function maxCachePayloadBytes2() {
|
|
4399
|
+
const raw = Number.parseInt(process.env.MEMORIX_EMBEDDING_CACHE_MAX_BYTES ?? "", 10);
|
|
4400
|
+
return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_CACHE_PAYLOAD_BYTES2;
|
|
4401
|
+
}
|
|
4402
|
+
var cache2, MAX_CACHE_SIZE2, DEFAULT_CACHE_PAYLOAD_BYTES2, cachePayloadBytes2, TransformersProvider;
|
|
4276
4403
|
var init_transformers_provider = __esm({
|
|
4277
4404
|
"src/embedding/transformers-provider.ts"() {
|
|
4278
4405
|
"use strict";
|
|
@@ -4280,6 +4407,8 @@ var init_transformers_provider = __esm({
|
|
|
4280
4407
|
init_provider();
|
|
4281
4408
|
cache2 = /* @__PURE__ */ new Map();
|
|
4282
4409
|
MAX_CACHE_SIZE2 = 5e3;
|
|
4410
|
+
DEFAULT_CACHE_PAYLOAD_BYTES2 = 64 * 1024 * 1024;
|
|
4411
|
+
cachePayloadBytes2 = 0;
|
|
4283
4412
|
TransformersProvider = class _TransformersProvider {
|
|
4284
4413
|
name = "transformers-minilm";
|
|
4285
4414
|
dimensions = 384;
|
|
@@ -4314,7 +4443,7 @@ var init_transformers_provider = __esm({
|
|
|
4314
4443
|
return Promise.all(inputs.map((input) => this.embedInput(input, options)));
|
|
4315
4444
|
}
|
|
4316
4445
|
async embed(text3) {
|
|
4317
|
-
const cached = cache2.get(text3);
|
|
4446
|
+
const cached = cache2.get(cacheKey2(text3));
|
|
4318
4447
|
if (cached) return cached;
|
|
4319
4448
|
const output = await this.extractor(text3, {
|
|
4320
4449
|
pooling: "mean",
|
|
@@ -4324,7 +4453,7 @@ var init_transformers_provider = __esm({
|
|
|
4324
4453
|
if (result.length !== this.dimensions) {
|
|
4325
4454
|
throw new Error(`Expected ${this.dimensions}d embedding, got ${result.length}d`);
|
|
4326
4455
|
}
|
|
4327
|
-
this.cacheSet(text3, result);
|
|
4456
|
+
this.cacheSet(cacheKey2(text3), result);
|
|
4328
4457
|
return result;
|
|
4329
4458
|
}
|
|
4330
4459
|
async embedBatch(texts) {
|
|
@@ -4332,7 +4461,7 @@ var init_transformers_provider = __esm({
|
|
|
4332
4461
|
const uncachedIndices = [];
|
|
4333
4462
|
const uncachedTexts = [];
|
|
4334
4463
|
for (let i2 = 0; i2 < texts.length; i2++) {
|
|
4335
|
-
const cached = cache2.get(texts[i2]);
|
|
4464
|
+
const cached = cache2.get(cacheKey2(texts[i2]));
|
|
4336
4465
|
if (cached) {
|
|
4337
4466
|
results[i2] = cached;
|
|
4338
4467
|
} else {
|
|
@@ -4350,17 +4479,27 @@ var init_transformers_provider = __esm({
|
|
|
4350
4479
|
const vec = Array.from(allVecs[i2]);
|
|
4351
4480
|
const originalIdx = uncachedIndices[i2];
|
|
4352
4481
|
results[originalIdx] = vec;
|
|
4353
|
-
this.cacheSet(uncachedTexts[i2], vec);
|
|
4482
|
+
this.cacheSet(cacheKey2(uncachedTexts[i2]), vec);
|
|
4354
4483
|
}
|
|
4355
4484
|
}
|
|
4356
4485
|
return results;
|
|
4357
4486
|
}
|
|
4358
4487
|
cacheSet(key, value) {
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4488
|
+
const incomingBytes = value.length * 8;
|
|
4489
|
+
if (incomingBytes > maxCachePayloadBytes2()) return;
|
|
4490
|
+
const existing = cache2.get(key);
|
|
4491
|
+
if (existing) cachePayloadBytes2 -= existing.length * 8;
|
|
4492
|
+
else {
|
|
4493
|
+
while (cache2.size >= MAX_CACHE_SIZE2 || cachePayloadBytes2 + incomingBytes > maxCachePayloadBytes2()) {
|
|
4494
|
+
const firstKey = cache2.keys().next().value;
|
|
4495
|
+
if (firstKey === void 0) break;
|
|
4496
|
+
const old = cache2.get(firstKey);
|
|
4497
|
+
cache2.delete(firstKey);
|
|
4498
|
+
if (old) cachePayloadBytes2 -= old.length * 8;
|
|
4499
|
+
}
|
|
4362
4500
|
}
|
|
4363
4501
|
cache2.set(key, value);
|
|
4502
|
+
cachePayloadBytes2 += incomingBytes;
|
|
4364
4503
|
}
|
|
4365
4504
|
};
|
|
4366
4505
|
}
|
|
@@ -4382,7 +4521,7 @@ __export(api_provider_exports, {
|
|
|
4382
4521
|
saveDiskCacheNow: () => saveDiskCacheNow,
|
|
4383
4522
|
seedApiEmbeddingCacheForTests: () => seedApiEmbeddingCacheForTests
|
|
4384
4523
|
});
|
|
4385
|
-
import { createHash as
|
|
4524
|
+
import { createHash as createHash3 } from "crypto";
|
|
4386
4525
|
import { createReadStream, createWriteStream, constants as fsConstants } from "fs";
|
|
4387
4526
|
import { access, readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, rename, stat, unlink } from "fs/promises";
|
|
4388
4527
|
import { join as join3 } from "path";
|
|
@@ -4409,7 +4548,7 @@ function cacheStatFile() {
|
|
|
4409
4548
|
function payloadBytes(vector) {
|
|
4410
4549
|
return vector.length * BYTES_PER_DIM;
|
|
4411
4550
|
}
|
|
4412
|
-
function
|
|
4551
|
+
function maxCachePayloadBytes3() {
|
|
4413
4552
|
const raw = process.env.MEMORIX_EMBEDDING_CACHE_MAX_BYTES;
|
|
4414
4553
|
if (raw) {
|
|
4415
4554
|
const parsed = Number.parseInt(raw, 10);
|
|
@@ -4419,7 +4558,7 @@ function maxCachePayloadBytes() {
|
|
|
4419
4558
|
}
|
|
4420
4559
|
function maxEntriesForDimensions(dimensions) {
|
|
4421
4560
|
const dim = Math.max(1, Math.floor(dimensions));
|
|
4422
|
-
const byBytes = Math.floor(
|
|
4561
|
+
const byBytes = Math.floor(maxCachePayloadBytes3() / (dim * BYTES_PER_DIM));
|
|
4423
4562
|
return Math.max(1, Math.min(MAX_CACHE_ENTRIES, byBytes));
|
|
4424
4563
|
}
|
|
4425
4564
|
function rememberDimensions(vector) {
|
|
@@ -4432,13 +4571,15 @@ function evictOldest() {
|
|
|
4432
4571
|
if (firstKey === void 0) return;
|
|
4433
4572
|
const old = cache3.get(firstKey);
|
|
4434
4573
|
cache3.delete(firstKey);
|
|
4435
|
-
if (old)
|
|
4574
|
+
if (old) cachePayloadBytes3 -= payloadBytes(old);
|
|
4436
4575
|
}
|
|
4437
4576
|
function evictToFit(incomingBytes, incomingDims) {
|
|
4577
|
+
if (incomingBytes > maxCachePayloadBytes3()) return false;
|
|
4438
4578
|
const limit2 = maxEntriesForDimensions(incomingDims);
|
|
4439
|
-
while (cache3.size > 0 && (cache3.size >= limit2 ||
|
|
4579
|
+
while (cache3.size > 0 && (cache3.size >= limit2 || cachePayloadBytes3 + incomingBytes > maxCachePayloadBytes3())) {
|
|
4440
4580
|
evictOldest();
|
|
4441
4581
|
}
|
|
4582
|
+
return true;
|
|
4442
4583
|
}
|
|
4443
4584
|
function isNumberArray(value) {
|
|
4444
4585
|
return Array.isArray(value) && value.every((entry) => typeof entry === "number");
|
|
@@ -4465,12 +4606,12 @@ function cacheInsert(hash4, value, dirty) {
|
|
|
4465
4606
|
const incoming = payloadBytes(value);
|
|
4466
4607
|
const existing = cache3.get(hash4);
|
|
4467
4608
|
if (existing) {
|
|
4468
|
-
|
|
4609
|
+
cachePayloadBytes3 -= payloadBytes(existing);
|
|
4469
4610
|
cache3.delete(hash4);
|
|
4470
4611
|
}
|
|
4471
|
-
evictToFit(incoming, value.length || cacheDimensions || DEFAULT_ASSUMED_DIMENSIONS);
|
|
4612
|
+
if (!evictToFit(incoming, value.length || cacheDimensions || DEFAULT_ASSUMED_DIMENSIONS)) return;
|
|
4472
4613
|
cache3.set(hash4, value);
|
|
4473
|
-
|
|
4614
|
+
cachePayloadBytes3 += incoming;
|
|
4474
4615
|
if (dirty) diskCacheDirty2 = true;
|
|
4475
4616
|
}
|
|
4476
4617
|
async function readCacheStat() {
|
|
@@ -4506,7 +4647,7 @@ function cacheNamespace(config) {
|
|
|
4506
4647
|
].join("|");
|
|
4507
4648
|
}
|
|
4508
4649
|
function textHash2(text3, namespace) {
|
|
4509
|
-
return
|
|
4650
|
+
return createHash3("sha256").update(`${namespace}\0${text3}`).digest("hex").slice(0, 16);
|
|
4510
4651
|
}
|
|
4511
4652
|
function inputIdentity(input, options = {}) {
|
|
4512
4653
|
return JSON.stringify({
|
|
@@ -4848,7 +4989,7 @@ function getApiEmbeddingDiskCacheLoadCountForTests() {
|
|
|
4848
4989
|
}
|
|
4849
4990
|
function resetApiEmbeddingCacheForTests() {
|
|
4850
4991
|
cache3.clear();
|
|
4851
|
-
|
|
4992
|
+
cachePayloadBytes3 = 0;
|
|
4852
4993
|
cacheDimensions = null;
|
|
4853
4994
|
diskCacheEntryCount = 0;
|
|
4854
4995
|
diskCacheLoaded = false;
|
|
@@ -4859,14 +5000,14 @@ function resetApiEmbeddingCacheForTests() {
|
|
|
4859
5000
|
}
|
|
4860
5001
|
function seedApiEmbeddingCacheForTests(entries) {
|
|
4861
5002
|
cache3.clear();
|
|
4862
|
-
|
|
5003
|
+
cachePayloadBytes3 = 0;
|
|
4863
5004
|
cacheDimensions = null;
|
|
4864
5005
|
for (const [key, value] of entries) cacheInsert(key, value, true);
|
|
4865
5006
|
diskCacheLoaded = true;
|
|
4866
5007
|
diskCacheDirty2 = true;
|
|
4867
5008
|
}
|
|
4868
5009
|
function getApiEmbeddingCachePayloadBytesForTests() {
|
|
4869
|
-
return
|
|
5010
|
+
return cachePayloadBytes3;
|
|
4870
5011
|
}
|
|
4871
5012
|
function getApiEmbeddingJsonlLineCountCallsForTests() {
|
|
4872
5013
|
return jsonlLineCountCalls;
|
|
@@ -5040,7 +5181,7 @@ function scheduleDiskSave() {
|
|
|
5040
5181
|
diskSaveTimer = null;
|
|
5041
5182
|
}, DISK_SAVE_DEBOUNCE_MS);
|
|
5042
5183
|
}
|
|
5043
|
-
function
|
|
5184
|
+
function cacheSet2(hash4, value) {
|
|
5044
5185
|
cacheInsert(hash4, value, true);
|
|
5045
5186
|
}
|
|
5046
5187
|
function resolveEnvEmbeddingApiKey() {
|
|
@@ -5160,7 +5301,7 @@ async function waitForRetry(waitMs, signal) {
|
|
|
5160
5301
|
abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
5161
5302
|
});
|
|
5162
5303
|
}
|
|
5163
|
-
var cache3, MAX_CACHE_ENTRIES, MAX_CACHE_PAYLOAD_BYTES, BYTES_PER_DIM, DEFAULT_ASSUMED_DIMENSIONS, MAX_MIGRATION_VALUE_BYTES,
|
|
5304
|
+
var cache3, MAX_CACHE_ENTRIES, MAX_CACHE_PAYLOAD_BYTES, BYTES_PER_DIM, DEFAULT_ASSUMED_DIMENSIONS, MAX_MIGRATION_VALUE_BYTES, cachePayloadBytes3, cacheDimensions, diskCacheEntryCount, diskCacheDirty2, diskSaveTimer, diskCacheLoaded, diskCacheLoadPromise, diskCacheLoadCount, jsonlLineCountCalls, MAX_INPUT_CHARS, MAX_CONCURRENCY, DISK_SAVE_DEBOUNCE_MS, DEFAULT_MAX_BATCH_SIZE, DASHSCOPE_MAX_BATCH_SIZE, MAX_RETRIES2, BASE_DELAY_MS, EmbeddingAPIError, APIEmbeddingProvider;
|
|
5164
5305
|
var init_api_provider = __esm({
|
|
5165
5306
|
"src/embedding/api-provider.ts"() {
|
|
5166
5307
|
"use strict";
|
|
@@ -5172,7 +5313,7 @@ var init_api_provider = __esm({
|
|
|
5172
5313
|
BYTES_PER_DIM = 8;
|
|
5173
5314
|
DEFAULT_ASSUMED_DIMENSIONS = 4096;
|
|
5174
5315
|
MAX_MIGRATION_VALUE_BYTES = 16 * 1024 * 1024;
|
|
5175
|
-
|
|
5316
|
+
cachePayloadBytes3 = 0;
|
|
5176
5317
|
cacheDimensions = null;
|
|
5177
5318
|
diskCacheEntryCount = 0;
|
|
5178
5319
|
diskCacheDirty2 = false;
|
|
@@ -5357,7 +5498,7 @@ var init_api_provider = __esm({
|
|
|
5357
5498
|
} else {
|
|
5358
5499
|
embedding = await apiCall();
|
|
5359
5500
|
}
|
|
5360
|
-
|
|
5501
|
+
cacheSet2(hash4, embedding);
|
|
5361
5502
|
scheduleDiskSave();
|
|
5362
5503
|
return embedding;
|
|
5363
5504
|
}
|
|
@@ -5405,7 +5546,7 @@ var init_api_provider = __esm({
|
|
|
5405
5546
|
for (const item of response.data) {
|
|
5406
5547
|
const originalIdx = chunkIndices[item.index];
|
|
5407
5548
|
results[originalIdx] = item.embedding;
|
|
5408
|
-
|
|
5549
|
+
cacheSet2(textHash2(normalizedTexts[originalIdx], this.cacheKeyNamespace), item.embedding);
|
|
5409
5550
|
}
|
|
5410
5551
|
} catch (error) {
|
|
5411
5552
|
const providerLimit = parseBatchLimit(error);
|
|
@@ -5483,7 +5624,7 @@ var init_api_provider = __esm({
|
|
|
5483
5624
|
throw new Error(`Expected ${this.dimensions}d, got ${embedding.length}d; dimension mismatch`);
|
|
5484
5625
|
}
|
|
5485
5626
|
this.trackUsage(response);
|
|
5486
|
-
|
|
5627
|
+
cacheSet2(hash4, embedding);
|
|
5487
5628
|
scheduleDiskSave();
|
|
5488
5629
|
return embedding;
|
|
5489
5630
|
}
|
|
@@ -6866,6 +7007,7 @@ var init_provider2 = __esm({
|
|
|
6866
7007
|
openai: { baseUrl: "https://api.openai.com/v1", model: "gpt-4.1-nano" },
|
|
6867
7008
|
anthropic: { baseUrl: "https://api.anthropic.com/v1", model: "claude-3-5-haiku-latest" },
|
|
6868
7009
|
openrouter: { baseUrl: "https://openrouter.ai/api/v1", model: "openai/gpt-4.1-nano" },
|
|
7010
|
+
atlascloud: { baseUrl: "https://api.atlascloud.ai/v1", model: "deepseek-ai/deepseek-v3.2" },
|
|
6869
7011
|
custom: { baseUrl: "http://localhost:11434/v1", model: "llama3" }
|
|
6870
7012
|
};
|
|
6871
7013
|
currentConfig = null;
|
|
@@ -7629,7 +7771,7 @@ var init_obs_store = __esm({
|
|
|
7629
7771
|
});
|
|
7630
7772
|
|
|
7631
7773
|
// src/search/semantic-index.ts
|
|
7632
|
-
import { createHash as
|
|
7774
|
+
import { createHash as createHash4 } from "crypto";
|
|
7633
7775
|
import { createRequire as createRequire3 } from "module";
|
|
7634
7776
|
import path11 from "path";
|
|
7635
7777
|
function createSemanticIndexProfile(provider2) {
|
|
@@ -7643,7 +7785,7 @@ function stateKey(dataDir, profile) {
|
|
|
7643
7785
|
return `${path11.resolve(dataDir)}::${profile.key}`;
|
|
7644
7786
|
}
|
|
7645
7787
|
function tableName(profile) {
|
|
7646
|
-
const digest2 =
|
|
7788
|
+
const digest2 = createHash4("sha256").update(profile.key).digest("hex").slice(0, 20);
|
|
7647
7789
|
return `${TABLE_PREFIX}${digest2}`;
|
|
7648
7790
|
}
|
|
7649
7791
|
function indexRoot(dataDir) {
|
|
@@ -8985,6 +9127,7 @@ async function searchObservations(options) {
|
|
|
8985
9127
|
};
|
|
8986
9128
|
let queryVector = null;
|
|
8987
9129
|
let embeddingProviderForSearch = null;
|
|
9130
|
+
let embeddingUnavailable = false;
|
|
8988
9131
|
if (quality !== "fast" && embeddingEnabled && hasQuery && tier !== "fast") {
|
|
8989
9132
|
try {
|
|
8990
9133
|
const provider2 = await getEmbeddingProvider();
|
|
@@ -8992,6 +9135,7 @@ async function searchObservations(options) {
|
|
|
8992
9135
|
embeddingProviderForSearch = provider2;
|
|
8993
9136
|
const activeVectorDimensions = getVectorDimensions();
|
|
8994
9137
|
if (activeVectorDimensions !== null && provider2.dimensions !== activeVectorDimensions) {
|
|
9138
|
+
embeddingUnavailable = true;
|
|
8995
9139
|
rememberSearchMode(
|
|
8996
9140
|
modeKey,
|
|
8997
9141
|
`fulltext (embedding dimension mismatch: provider ${provider2.dimensions}d vs index ${activeVectorDimensions}d)`
|
|
@@ -9031,8 +9175,11 @@ async function searchObservations(options) {
|
|
|
9031
9175
|
hybridWeights: isCJKHeavy ? { text: 0.2, vector: 0.8 } : { text: 0.6, vector: 0.4 }
|
|
9032
9176
|
};
|
|
9033
9177
|
}
|
|
9178
|
+
} else {
|
|
9179
|
+
embeddingUnavailable = true;
|
|
9034
9180
|
}
|
|
9035
9181
|
} catch (error) {
|
|
9182
|
+
embeddingUnavailable = true;
|
|
9036
9183
|
rememberSearchMode(modeKey, "fulltext (embedding unavailable)");
|
|
9037
9184
|
console.error("[memorix] Embedding failed or timed out, falling back to fulltext search");
|
|
9038
9185
|
}
|
|
@@ -9040,7 +9187,7 @@ async function searchObservations(options) {
|
|
|
9040
9187
|
mark("preSearch");
|
|
9041
9188
|
let results;
|
|
9042
9189
|
const persistentCorpusEligible = await shouldUsePersistentSearch(projectIds, options.projectId);
|
|
9043
|
-
const canUsePersistentLexical = persistentCorpusEligible && Boolean(hasQuery) && !queryVector && (quality === "fast" || tier === "fast" || !embeddingEnabled);
|
|
9190
|
+
const canUsePersistentLexical = persistentCorpusEligible && Boolean(hasQuery) && !queryVector && (quality === "fast" || tier === "fast" || !embeddingEnabled || embeddingUnavailable);
|
|
9044
9191
|
let persistent = persistentCorpusEligible && queryVector && embeddingProviderForSearch ? await searchPersistentSemantically(options, projectIds, requestLimit, queryVector, embeddingProviderForSearch) : canUsePersistentLexical ? await searchPersistentLexically(options, projectIds, requestLimit) : null;
|
|
9045
9192
|
const durableStore = getOptionalObservationStore();
|
|
9046
9193
|
if (!persistent && queryVector && durableStore?.hasLexicalIndex?.() && count(database) === 0) {
|
|
@@ -9686,6 +9833,7 @@ var init_secret_filter = __esm({
|
|
|
9686
9833
|
// src/runtime/maintenance-jobs.ts
|
|
9687
9834
|
var maintenance_jobs_exports = {};
|
|
9688
9835
|
__export(maintenance_jobs_exports, {
|
|
9836
|
+
DEFAULT_FAILED_HISTORY_RETENTION_MS: () => DEFAULT_FAILED_HISTORY_RETENTION_MS,
|
|
9689
9837
|
MAINTENANCE_JOB_KINDS: () => MAINTENANCE_JOB_KINDS,
|
|
9690
9838
|
MaintenanceJobStore: () => MaintenanceJobStore,
|
|
9691
9839
|
MaintenanceJobWorker: () => MaintenanceJobWorker,
|
|
@@ -9735,7 +9883,7 @@ function normalizedKinds(kinds) {
|
|
|
9735
9883
|
function getMaintenanceRetryDelayMs(attempts) {
|
|
9736
9884
|
return Math.min(6e4, 1e3 * 2 ** Math.max(0, attempts - 1));
|
|
9737
9885
|
}
|
|
9738
|
-
var MAINTENANCE_JOB_KINDS, DEFAULT_MAX_ATTEMPTS, DEFAULT_LEASE_MS, DEFAULT_POLL_INTERVAL_MS, MAX_ERROR_LENGTH, DEFAULT_COMPLETED_HISTORY_RETENTION_MS, MaintenanceJobStore, MaintenanceJobWorker;
|
|
9886
|
+
var MAINTENANCE_JOB_KINDS, DEFAULT_MAX_ATTEMPTS, DEFAULT_LEASE_MS, DEFAULT_POLL_INTERVAL_MS, MAX_ERROR_LENGTH, DEFAULT_COMPLETED_HISTORY_RETENTION_MS, DEFAULT_FAILED_HISTORY_RETENTION_MS, MaintenanceJobStore, MaintenanceJobWorker;
|
|
9739
9887
|
var init_maintenance_jobs = __esm({
|
|
9740
9888
|
"src/runtime/maintenance-jobs.ts"() {
|
|
9741
9889
|
"use strict";
|
|
@@ -9762,6 +9910,7 @@ var init_maintenance_jobs = __esm({
|
|
|
9762
9910
|
DEFAULT_POLL_INTERVAL_MS = 2e3;
|
|
9763
9911
|
MAX_ERROR_LENGTH = 1e3;
|
|
9764
9912
|
DEFAULT_COMPLETED_HISTORY_RETENTION_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
9913
|
+
DEFAULT_FAILED_HISTORY_RETENTION_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
9765
9914
|
MaintenanceJobStore = class {
|
|
9766
9915
|
db;
|
|
9767
9916
|
constructor(dataDir) {
|
|
@@ -9888,18 +10037,21 @@ var init_maintenance_jobs = __esm({
|
|
|
9888
10037
|
}
|
|
9889
10038
|
/**
|
|
9890
10039
|
* Completed jobs are useful recent operator history, not permanent data.
|
|
9891
|
-
* Failed
|
|
9892
|
-
*
|
|
10040
|
+
* Failed diagnostics are retained longer, but are still bounded so a
|
|
10041
|
+
* permanently failing job kind cannot grow the database forever.
|
|
9893
10042
|
*/
|
|
9894
10043
|
pruneCompletedHistory(options = {}) {
|
|
9895
10044
|
const now3 = options.now ?? Date.now();
|
|
9896
10045
|
const maxAgeMs = Number.isFinite(options.maxAgeMs) ? Math.max(0, Math.floor(options.maxAgeMs)) : DEFAULT_COMPLETED_HISTORY_RETENTION_MS;
|
|
10046
|
+
const failedMaxAgeMs = Number.isFinite(options.failedMaxAgeMs) ? Math.max(0, Math.floor(options.failedMaxAgeMs)) : DEFAULT_FAILED_HISTORY_RETENTION_MS;
|
|
9897
10047
|
const result = this.db.prepare(`
|
|
9898
10048
|
DELETE FROM maintenance_jobs
|
|
9899
|
-
WHERE status = 'completed'
|
|
10049
|
+
WHERE (status = 'completed'
|
|
9900
10050
|
AND completed_at IS NOT NULL
|
|
9901
|
-
AND completed_at < ?
|
|
9902
|
-
|
|
10051
|
+
AND completed_at < ?)
|
|
10052
|
+
OR (status = 'failed'
|
|
10053
|
+
AND updated_at < ?)
|
|
10054
|
+
`).run(now3 - maxAgeMs, now3 - failedMaxAgeMs);
|
|
9903
10055
|
return Number(result.changes ?? 0);
|
|
9904
10056
|
}
|
|
9905
10057
|
claimNext(options) {
|
|
@@ -10253,7 +10405,7 @@ var init_lifecycle = __esm({
|
|
|
10253
10405
|
});
|
|
10254
10406
|
|
|
10255
10407
|
// src/store/evidence-store.ts
|
|
10256
|
-
import { createHash as
|
|
10408
|
+
import { createHash as createHash5, randomUUID as randomUUID3 } from "crypto";
|
|
10257
10409
|
function safeJson(value, fallback) {
|
|
10258
10410
|
if (typeof value !== "string" || value.length === 0) return fallback;
|
|
10259
10411
|
try {
|
|
@@ -10287,7 +10439,7 @@ function rowToCard(row) {
|
|
|
10287
10439
|
};
|
|
10288
10440
|
}
|
|
10289
10441
|
function observationHash(observation) {
|
|
10290
|
-
return
|
|
10442
|
+
return createHash5("sha256").update(JSON.stringify({
|
|
10291
10443
|
projectId: observation.projectId,
|
|
10292
10444
|
id: observation.id,
|
|
10293
10445
|
title: observation.title,
|
|
@@ -10881,13 +11033,13 @@ __export(workspace_exports, {
|
|
|
10881
11033
|
loadKnowledgeWorkspace: () => loadKnowledgeWorkspace,
|
|
10882
11034
|
resolveKnowledgeWorkspaceFile: () => resolveKnowledgeWorkspaceFile
|
|
10883
11035
|
});
|
|
10884
|
-
import { createHash as
|
|
11036
|
+
import { createHash as createHash6 } from "crypto";
|
|
10885
11037
|
import { execFile } from "child_process";
|
|
10886
11038
|
import { promises as fs9 } from "fs";
|
|
10887
11039
|
import path14 from "path";
|
|
10888
11040
|
import { promisify } from "util";
|
|
10889
11041
|
function hash(value) {
|
|
10890
|
-
return
|
|
11042
|
+
return createHash6("sha256").update(value).digest("hex");
|
|
10891
11043
|
}
|
|
10892
11044
|
function workspaceId(projectId, mode) {
|
|
10893
11045
|
return "workspace:" + hash(projectId + ":" + mode).slice(0, 24);
|
|
@@ -12040,14 +12192,14 @@ __export(asset_store_exports, {
|
|
|
12040
12192
|
readMediaAsset: () => readMediaAsset,
|
|
12041
12193
|
removeMediaAsset: () => removeMediaAsset
|
|
12042
12194
|
});
|
|
12043
|
-
import { createHash as
|
|
12195
|
+
import { createHash as createHash7, randomUUID as randomUUID6 } from "crypto";
|
|
12044
12196
|
import { copyFile, lstat, mkdir as mkdir3, open, readFile as readFile3, readdir, rename as rename2, rm, stat as stat2, writeFile as writeFile3 } from "fs/promises";
|
|
12045
12197
|
import path15 from "path";
|
|
12046
12198
|
function mediaRoot(dataDir) {
|
|
12047
12199
|
return path15.resolve(dataDir, "media");
|
|
12048
12200
|
}
|
|
12049
12201
|
function projectStorageKey(projectId) {
|
|
12050
|
-
return
|
|
12202
|
+
return createHash7("sha256").update(projectId).digest("hex").slice(0, 16);
|
|
12051
12203
|
}
|
|
12052
12204
|
function validateUnderRoot(root, candidate) {
|
|
12053
12205
|
const resolved = path15.resolve(candidate);
|
|
@@ -12107,7 +12259,7 @@ async function readHeader(filePath, bytes = 32) {
|
|
|
12107
12259
|
}
|
|
12108
12260
|
async function sha256File(filePath) {
|
|
12109
12261
|
const bytes = await readFile3(filePath);
|
|
12110
|
-
return
|
|
12262
|
+
return createHash7("sha256").update(bytes).digest("hex");
|
|
12111
12263
|
}
|
|
12112
12264
|
function destinationFor(root, projectId, sha256, extension3) {
|
|
12113
12265
|
const relative5 = path15.join("assets", projectStorageKey(projectId), sha256.slice(0, 2), `${sha256}${extension3}`);
|
|
@@ -12213,7 +12365,7 @@ async function importMediaBuffer(input) {
|
|
|
12213
12365
|
if (input.bytes.length === 0) throw new Error("Media import rejects empty payloads");
|
|
12214
12366
|
if (input.bytes.length > maxBytes) throw new Error(`Media payload is too large (${input.bytes.length} bytes; limit ${maxBytes})`);
|
|
12215
12367
|
const detected = detectMedia(input.bytes.subarray(0, 32));
|
|
12216
|
-
const sha256 =
|
|
12368
|
+
const sha256 = createHash7("sha256").update(input.bytes).digest("hex");
|
|
12217
12369
|
return importKnownMedia({
|
|
12218
12370
|
dataDir: input.dataDir,
|
|
12219
12371
|
projectId: input.projectId,
|
|
@@ -12231,7 +12383,7 @@ async function readMediaAsset(dataDir, asset, maxBytes = DEFAULT_MAX_MEDIA_BYTES
|
|
|
12231
12383
|
if (asset.byteSize > maxBytes) throw new Error(`Media asset exceeds read limit (${asset.byteSize} bytes; limit ${maxBytes})`);
|
|
12232
12384
|
const bytes = await readFile3(getMediaAssetPath(dataDir, asset));
|
|
12233
12385
|
if (bytes.length !== asset.byteSize) throw new Error(`Media asset size no longer matches metadata: ${asset.id}`);
|
|
12234
|
-
const sha256 =
|
|
12386
|
+
const sha256 = createHash7("sha256").update(bytes).digest("hex");
|
|
12235
12387
|
if (sha256 !== asset.sha256) throw new Error(`Media asset hash no longer matches metadata: ${asset.id}`);
|
|
12236
12388
|
return bytes;
|
|
12237
12389
|
}
|
|
@@ -65101,7 +65253,7 @@ var require_gaxios = __commonJS({
|
|
|
65101
65253
|
var retry_js_1 = require_retry3();
|
|
65102
65254
|
var stream_1 = __require("stream");
|
|
65103
65255
|
var interceptor_js_1 = require_interceptor();
|
|
65104
|
-
var
|
|
65256
|
+
var randomUUID20 = async () => globalThis.crypto?.randomUUID() || (await import("crypto")).randomUUID();
|
|
65105
65257
|
var HTTP_STATUS_NO_CONTENT = 204;
|
|
65106
65258
|
var Gaxios = class {
|
|
65107
65259
|
agentCache = /* @__PURE__ */ new Map();
|
|
@@ -65374,7 +65526,7 @@ var require_gaxios = __commonJS({
|
|
|
65374
65526
|
*/
|
|
65375
65527
|
["Blob", "File", "FormData"].includes(opts.data?.constructor?.name || "");
|
|
65376
65528
|
if (opts.multipart?.length) {
|
|
65377
|
-
const boundary = await
|
|
65529
|
+
const boundary = await randomUUID20();
|
|
65378
65530
|
preparedHeaders.set("content-type", `multipart/related; boundary=${boundary}`);
|
|
65379
65531
|
opts.body = stream_1.Readable.from(this.getMultipartRequest(opts.multipart, boundary));
|
|
65380
65532
|
} else if (shouldDirectlyPassData) {
|
|
@@ -71046,16 +71198,16 @@ var require_jwtaccess = __commonJS({
|
|
|
71046
71198
|
* @returns A string that returns the cached key.
|
|
71047
71199
|
*/
|
|
71048
71200
|
getCachedKey(url, scopes) {
|
|
71049
|
-
let
|
|
71201
|
+
let cacheKey3 = url;
|
|
71050
71202
|
if (scopes && Array.isArray(scopes) && scopes.length) {
|
|
71051
|
-
|
|
71203
|
+
cacheKey3 = url ? `${url}_${scopes.join("_")}` : `${scopes.join("_")}`;
|
|
71052
71204
|
} else if (typeof scopes === "string") {
|
|
71053
|
-
|
|
71205
|
+
cacheKey3 = url ? `${url}_${scopes}` : scopes;
|
|
71054
71206
|
}
|
|
71055
|
-
if (!
|
|
71207
|
+
if (!cacheKey3) {
|
|
71056
71208
|
throw Error("Scopes or url must be provided");
|
|
71057
71209
|
}
|
|
71058
|
-
return
|
|
71210
|
+
return cacheKey3;
|
|
71059
71211
|
}
|
|
71060
71212
|
/**
|
|
71061
71213
|
* Get a non-expired access token, after refreshing if necessary.
|
|
@@ -77601,7 +77753,7 @@ var require_websocket = __commonJS({
|
|
|
77601
77753
|
var http3 = __require("http");
|
|
77602
77754
|
var net = __require("net");
|
|
77603
77755
|
var tls = __require("tls");
|
|
77604
|
-
var { randomBytes: randomBytes2, createHash:
|
|
77756
|
+
var { randomBytes: randomBytes2, createHash: createHash20 } = __require("crypto");
|
|
77605
77757
|
var { Duplex, Readable: Readable2 } = __require("stream");
|
|
77606
77758
|
var { URL: URL2 } = __require("url");
|
|
77607
77759
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -78269,7 +78421,7 @@ var require_websocket = __commonJS({
|
|
|
78269
78421
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
78270
78422
|
return;
|
|
78271
78423
|
}
|
|
78272
|
-
const digest2 =
|
|
78424
|
+
const digest2 = createHash20("sha1").update(key + GUID).digest("base64");
|
|
78273
78425
|
if (res.headers["sec-websocket-accept"] !== digest2) {
|
|
78274
78426
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
78275
78427
|
return;
|
|
@@ -78641,7 +78793,7 @@ var require_websocket_server = __commonJS({
|
|
|
78641
78793
|
var EventEmitter2 = __require("events");
|
|
78642
78794
|
var http3 = __require("http");
|
|
78643
78795
|
var { Duplex } = __require("stream");
|
|
78644
|
-
var { createHash:
|
|
78796
|
+
var { createHash: createHash20 } = __require("crypto");
|
|
78645
78797
|
var extension3 = require_extension();
|
|
78646
78798
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
78647
78799
|
var subprotocol2 = require_subprotocol();
|
|
@@ -78948,7 +79100,7 @@ var require_websocket_server = __commonJS({
|
|
|
78948
79100
|
);
|
|
78949
79101
|
}
|
|
78950
79102
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
78951
|
-
const digest2 =
|
|
79103
|
+
const digest2 = createHash20("sha1").update(key + GUID).digest("base64");
|
|
78952
79104
|
const headers = [
|
|
78953
79105
|
"HTTP/1.1 101 Switching Protocols",
|
|
78954
79106
|
"Upgrade: websocket",
|
|
@@ -143007,9 +143159,9 @@ var init_union_priority_sort = __esm({
|
|
|
143007
143159
|
// node_modules/typebox/build/value/clean/from_union.mjs
|
|
143008
143160
|
function FromUnion9(context, type, value) {
|
|
143009
143161
|
for (const schema of UnionPrioritySort(type.anyOf)) {
|
|
143010
|
-
const
|
|
143011
|
-
if (Check2(context, schema,
|
|
143012
|
-
return
|
|
143162
|
+
const clean2 = FromType19(context, schema, Clone2(value));
|
|
143163
|
+
if (Check2(context, schema, clean2))
|
|
143164
|
+
return clean2;
|
|
143013
143165
|
}
|
|
143014
143166
|
return value;
|
|
143015
143167
|
}
|
|
@@ -147647,9 +147799,9 @@ var init_long_term = __esm({
|
|
|
147647
147799
|
});
|
|
147648
147800
|
|
|
147649
147801
|
// src/codegraph/ids.ts
|
|
147650
|
-
import { createHash as
|
|
147802
|
+
import { createHash as createHash8 } from "crypto";
|
|
147651
147803
|
function digest(input) {
|
|
147652
|
-
return
|
|
147804
|
+
return createHash8("sha256").update(input).digest("hex").slice(0, 16);
|
|
147653
147805
|
}
|
|
147654
147806
|
function normalizeCodePath(path38) {
|
|
147655
147807
|
return path38.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+/g, "/");
|
|
@@ -148697,7 +148849,7 @@ var init_store = __esm({
|
|
|
148697
148849
|
|
|
148698
148850
|
// src/codegraph/code-state.ts
|
|
148699
148851
|
import { execFile as execFile2 } from "child_process";
|
|
148700
|
-
import { createHash as
|
|
148852
|
+
import { createHash as createHash9 } from "crypto";
|
|
148701
148853
|
import { promisify as promisify3 } from "util";
|
|
148702
148854
|
async function runGit(rootPath, args) {
|
|
148703
148855
|
try {
|
|
@@ -148726,7 +148878,7 @@ function changedPathCount(status) {
|
|
|
148726
148878
|
return count2;
|
|
148727
148879
|
}
|
|
148728
148880
|
function fingerprint(baseRevision, status) {
|
|
148729
|
-
return
|
|
148881
|
+
return createHash9("sha256").update(baseRevision ?? "").update("\0").update(status).digest("hex");
|
|
148730
148882
|
}
|
|
148731
148883
|
async function collectCodeStateSnapshot(input) {
|
|
148732
148884
|
const [revision, status] = await Promise.all([
|
|
@@ -148820,12 +148972,12 @@ var init_exclude3 = __esm({
|
|
|
148820
148972
|
});
|
|
148821
148973
|
|
|
148822
148974
|
// src/codegraph/semantic-provider.ts
|
|
148823
|
-
import { createHash as
|
|
148975
|
+
import { createHash as createHash10 } from "crypto";
|
|
148824
148976
|
import "fs";
|
|
148825
148977
|
import { resolve } from "path";
|
|
148826
148978
|
import ts from "typescript";
|
|
148827
148979
|
function hashText(value) {
|
|
148828
|
-
return
|
|
148980
|
+
return createHash10("sha256").update(value).digest("hex");
|
|
148829
148981
|
}
|
|
148830
148982
|
function canonicalPath(value) {
|
|
148831
148983
|
const normalized = resolve(value).replace(/\\/g, "/");
|
|
@@ -149170,11 +149322,11 @@ __export(lite_provider_exports, {
|
|
|
149170
149322
|
indexProjectLite: () => indexProjectLite,
|
|
149171
149323
|
refreshProjectLite: () => refreshProjectLite
|
|
149172
149324
|
});
|
|
149173
|
-
import { createHash as
|
|
149325
|
+
import { createHash as createHash11 } from "crypto";
|
|
149174
149326
|
import { existsSync as existsSync12, readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
|
|
149175
149327
|
import { join as join4, relative as relative2 } from "path";
|
|
149176
149328
|
function hashText2(text3) {
|
|
149177
|
-
return
|
|
149329
|
+
return createHash11("sha256").update(text3).digest("hex");
|
|
149178
149330
|
}
|
|
149179
149331
|
function extension2(path38) {
|
|
149180
149332
|
const index = path38.lastIndexOf(".");
|
|
@@ -149807,7 +149959,7 @@ var claim_store_exports = {};
|
|
|
149807
149959
|
__export(claim_store_exports, {
|
|
149808
149960
|
ClaimStore: () => ClaimStore
|
|
149809
149961
|
});
|
|
149810
|
-
import { createHash as
|
|
149962
|
+
import { createHash as createHash12, randomUUID as randomUUID12 } from "crypto";
|
|
149811
149963
|
function optionalText3(value) {
|
|
149812
149964
|
return typeof value === "string" && value ? value : void 0;
|
|
149813
149965
|
}
|
|
@@ -149860,7 +150012,7 @@ function rowToEvent3(row) {
|
|
|
149860
150012
|
};
|
|
149861
150013
|
}
|
|
149862
150014
|
function evidenceKey(input) {
|
|
149863
|
-
return
|
|
150015
|
+
return createHash12("sha256").update(JSON.stringify([
|
|
149864
150016
|
input.evidenceKind,
|
|
149865
150017
|
input.evidenceId,
|
|
149866
150018
|
input.relation,
|
|
@@ -150058,7 +150210,7 @@ __export(claims_exports, {
|
|
|
150058
150210
|
supersedeClaim: () => supersedeClaim,
|
|
150059
150211
|
writeClaim: () => writeClaim
|
|
150060
150212
|
});
|
|
150061
|
-
import { createHash as
|
|
150213
|
+
import { createHash as createHash13, randomUUID as randomUUID13 } from "crypto";
|
|
150062
150214
|
function compactText2(value, field) {
|
|
150063
150215
|
if (typeof value !== "string") throw new Error("Claim " + field + " must be text");
|
|
150064
150216
|
const sanitized = sanitizeCredentials(value).trim().replace(/\s+/g, " ");
|
|
@@ -150070,7 +150222,7 @@ function normalizedTerm(value) {
|
|
|
150070
150222
|
return compactText2(value, "identity").toLocaleLowerCase("en-US");
|
|
150071
150223
|
}
|
|
150072
150224
|
function hashIdentity(parts) {
|
|
150073
|
-
return
|
|
150225
|
+
return createHash13("sha256").update(parts.join(String.fromCharCode(31))).digest("hex");
|
|
150074
150226
|
}
|
|
150075
150227
|
function buildClaimIdentity(input) {
|
|
150076
150228
|
const subject = normalizedTerm(input.subject);
|
|
@@ -150311,7 +150463,7 @@ function supersedeClaim(store, input) {
|
|
|
150311
150463
|
});
|
|
150312
150464
|
}
|
|
150313
150465
|
function hashObservation(observation) {
|
|
150314
|
-
return
|
|
150466
|
+
return createHash13("sha256").update(JSON.stringify([
|
|
150315
150467
|
observation.title,
|
|
150316
150468
|
observation.narrative,
|
|
150317
150469
|
observation.facts,
|
|
@@ -150555,11 +150707,11 @@ var init_frontmatter = __esm({
|
|
|
150555
150707
|
});
|
|
150556
150708
|
|
|
150557
150709
|
// src/knowledge/markdown.ts
|
|
150558
|
-
import { createHash as
|
|
150710
|
+
import { createHash as createHash14 } from "crypto";
|
|
150559
150711
|
import { promises as fs13 } from "fs";
|
|
150560
150712
|
import path22 from "path";
|
|
150561
150713
|
function hashContent(content) {
|
|
150562
|
-
return
|
|
150714
|
+
return createHash14("sha256").update(content).digest("hex");
|
|
150563
150715
|
}
|
|
150564
150716
|
function stringField(data, key) {
|
|
150565
150717
|
const value = data[key];
|
|
@@ -150685,11 +150837,11 @@ __export(wiki_exports, {
|
|
|
150685
150837
|
lintKnowledgeWorkspace: () => lintKnowledgeWorkspace,
|
|
150686
150838
|
readKnowledgePage: () => readKnowledgePage
|
|
150687
150839
|
});
|
|
150688
|
-
import { createHash as
|
|
150840
|
+
import { createHash as createHash15 } from "crypto";
|
|
150689
150841
|
import { promises as fs14 } from "fs";
|
|
150690
150842
|
import path23 from "path";
|
|
150691
150843
|
function hash2(value) {
|
|
150692
|
-
return
|
|
150844
|
+
return createHash15("sha256").update(value).digest("hex");
|
|
150693
150845
|
}
|
|
150694
150846
|
function now() {
|
|
150695
150847
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -151908,11 +152060,11 @@ __export(workflows_exports, {
|
|
|
151908
152060
|
syncCanonicalWorkflows: () => syncCanonicalWorkflows,
|
|
151909
152061
|
writeCanonicalWorkflow: () => writeCanonicalWorkflow
|
|
151910
152062
|
});
|
|
151911
|
-
import { createHash as
|
|
152063
|
+
import { createHash as createHash16 } from "crypto";
|
|
151912
152064
|
import { promises as fs15 } from "fs";
|
|
151913
152065
|
import path24 from "path";
|
|
151914
152066
|
function hash3(value) {
|
|
151915
|
-
return
|
|
152067
|
+
return createHash16("sha256").update(value).digest("hex");
|
|
151916
152068
|
}
|
|
151917
152069
|
function now2() {
|
|
151918
152070
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -156273,9 +156425,9 @@ var init_graph_context = __esm({
|
|
|
156273
156425
|
});
|
|
156274
156426
|
|
|
156275
156427
|
// src/rules/utils.ts
|
|
156276
|
-
import { createHash as
|
|
156428
|
+
import { createHash as createHash17 } from "crypto";
|
|
156277
156429
|
function hashContent2(content) {
|
|
156278
|
-
return
|
|
156430
|
+
return createHash17("sha256").update(content.trim()).digest("hex").substring(0, 16);
|
|
156279
156431
|
}
|
|
156280
156432
|
function generateRuleId(source, filePath) {
|
|
156281
156433
|
const sanitized = filePath.replace(/[\/\\]/g, "-").replace(/^\./, "");
|
|
@@ -158718,6 +158870,7 @@ var init_tool_profile = __esm({
|
|
|
158718
158870
|
// keep the default micro profile at its nine-tool token budget.
|
|
158719
158871
|
memorix_evidence: ["lite", "team", "full"],
|
|
158720
158872
|
memorix_feedback: ["lite", "team", "full"],
|
|
158873
|
+
memorix_continuity: ["lite", "team", "full"],
|
|
158721
158874
|
// ── lite: extended solo memory surface ────────────────────────────
|
|
158722
158875
|
memorix_graph_context: ["lite", "team", "full"],
|
|
158723
158876
|
memorix_timeline: ["lite", "team", "full"],
|
|
@@ -159951,7 +160104,7 @@ var init_request_context = __esm({
|
|
|
159951
160104
|
function getMcpServerInfo() {
|
|
159952
160105
|
return {
|
|
159953
160106
|
name: "memorix",
|
|
159954
|
-
version: true ? "1.9.
|
|
160107
|
+
version: true ? "1.9.7" : "1.0.1"
|
|
159955
160108
|
};
|
|
159956
160109
|
}
|
|
159957
160110
|
function createMcpDiscoverResult(capabilities, serverInfo) {
|
|
@@ -160040,8 +160193,8 @@ function legacyBehavior(homeDir) {
|
|
|
160040
160193
|
function getBehaviorConfig(options = {}) {
|
|
160041
160194
|
const homeDir = options.homeDir ?? homedir22();
|
|
160042
160195
|
const projectRoot = options.projectRoot === void 0 ? detectProject()?.rootPath ?? null : options.projectRoot;
|
|
160043
|
-
const
|
|
160044
|
-
const cached = cache4.get(
|
|
160196
|
+
const cacheKey3 = `${homeDir}\0${projectRoot ?? ""}`;
|
|
160197
|
+
const cached = cache4.get(cacheKey3);
|
|
160045
160198
|
if (cached) return cached;
|
|
160046
160199
|
const legacy = legacyBehavior(homeDir);
|
|
160047
160200
|
let resolved = {};
|
|
@@ -160055,7 +160208,7 @@ function getBehaviorConfig(options = {}) {
|
|
|
160055
160208
|
autoCleanup: typeof resolved.autoCleanup === "boolean" ? resolved.autoCleanup : typeof legacy.autoCleanup === "boolean" ? legacy.autoCleanup : DEFAULTS.autoCleanup,
|
|
160056
160209
|
formationMode: isFormationMode(resolved.formation) ? resolved.formation : isFormationMode(legacy.formationMode) ? legacy.formationMode : DEFAULTS.formationMode
|
|
160057
160210
|
};
|
|
160058
|
-
cache4.set(
|
|
160211
|
+
cache4.set(cacheKey3, config);
|
|
160059
160212
|
return config;
|
|
160060
160213
|
}
|
|
160061
160214
|
function resetBehaviorConfigCache() {
|
|
@@ -160660,6 +160813,7 @@ function freshnessForMemory(status) {
|
|
|
160660
160813
|
return "unknown";
|
|
160661
160814
|
}
|
|
160662
160815
|
function receiptOmissionKind(raw) {
|
|
160816
|
+
if (raw.includes("continuity")) return "continuity";
|
|
160663
160817
|
if (raw.includes("continuation")) return "continuation";
|
|
160664
160818
|
if (raw.includes("task")) return "task";
|
|
160665
160819
|
if (raw.includes("fact")) return "current-fact";
|
|
@@ -160770,6 +160924,77 @@ function renderTaskWorksetPrompt(input) {
|
|
|
160770
160924
|
trust: "source-backed"
|
|
160771
160925
|
});
|
|
160772
160926
|
appendLine(lines, "Task lens: " + input.lens, maxTokens, omitted, "lens");
|
|
160927
|
+
if (input.continuity) {
|
|
160928
|
+
const continuity = input.continuity;
|
|
160929
|
+
appendLine(lines, "", maxTokens, omitted, "continuity-heading");
|
|
160930
|
+
appendLine(lines, "Task continuity", maxTokens, omitted, "continuity-heading", selected, {
|
|
160931
|
+
kind: "continuity",
|
|
160932
|
+
id: "continuity:" + continuity.taskId,
|
|
160933
|
+
reason: "explicit task continuity ledger",
|
|
160934
|
+
trust: "source-backed"
|
|
160935
|
+
});
|
|
160936
|
+
appendLine(
|
|
160937
|
+
lines,
|
|
160938
|
+
"- Status: " + continuity.status + " | " + short(continuity.task, 30),
|
|
160939
|
+
maxTokens,
|
|
160940
|
+
omitted,
|
|
160941
|
+
"continuity-task"
|
|
160942
|
+
);
|
|
160943
|
+
appendLine(
|
|
160944
|
+
lines,
|
|
160945
|
+
"- Outcome: " + continuity.outcome.state,
|
|
160946
|
+
maxTokens,
|
|
160947
|
+
omitted,
|
|
160948
|
+
"continuity-outcome",
|
|
160949
|
+
selected,
|
|
160950
|
+
{
|
|
160951
|
+
kind: "continuity",
|
|
160952
|
+
id: "continuity:" + continuity.taskId,
|
|
160953
|
+
reason: "deterministic task outcome projection",
|
|
160954
|
+
trust: "derived"
|
|
160955
|
+
}
|
|
160956
|
+
);
|
|
160957
|
+
for (const requirement of continuity.requirements.slice(0, 3)) {
|
|
160958
|
+
appendLine(lines, "- Requirement: " + short(requirement, 24), maxTokens, omitted, "continuity-requirement", selected, {
|
|
160959
|
+
kind: "continuity",
|
|
160960
|
+
id: "continuity:" + continuity.taskId,
|
|
160961
|
+
reason: "explicit task requirement",
|
|
160962
|
+
trust: "source-backed"
|
|
160963
|
+
});
|
|
160964
|
+
}
|
|
160965
|
+
for (const decision of continuity.decisions.slice(0, 2)) {
|
|
160966
|
+
appendLine(lines, "- Decision: " + short(decision, 24), maxTokens, omitted, "continuity-decision", selected, {
|
|
160967
|
+
kind: "continuity",
|
|
160968
|
+
id: "continuity:" + continuity.taskId,
|
|
160969
|
+
reason: "explicit task decision",
|
|
160970
|
+
trust: "source-backed"
|
|
160971
|
+
});
|
|
160972
|
+
}
|
|
160973
|
+
for (const verification of continuity.verification.slice(-3)) {
|
|
160974
|
+
appendLine(
|
|
160975
|
+
lines,
|
|
160976
|
+
"- Verify [" + verification.status + "]: " + short(verification.content, 22),
|
|
160977
|
+
maxTokens,
|
|
160978
|
+
omitted,
|
|
160979
|
+
"continuity-verification",
|
|
160980
|
+
selected,
|
|
160981
|
+
{
|
|
160982
|
+
kind: "continuity",
|
|
160983
|
+
id: "continuity:" + continuity.taskId,
|
|
160984
|
+
reason: "task verification state",
|
|
160985
|
+
trust: "source-backed"
|
|
160986
|
+
}
|
|
160987
|
+
);
|
|
160988
|
+
}
|
|
160989
|
+
for (const risk of continuity.risks.slice(0, 2)) {
|
|
160990
|
+
appendLine(lines, "- Risk: " + short(risk, 22), maxTokens, omitted, "continuity-risk", selected, {
|
|
160991
|
+
kind: "continuity",
|
|
160992
|
+
id: "continuity:" + continuity.taskId,
|
|
160993
|
+
reason: "open task risk",
|
|
160994
|
+
trust: "source-backed"
|
|
160995
|
+
});
|
|
160996
|
+
}
|
|
160997
|
+
}
|
|
160773
160998
|
if (input.alwaysOn) {
|
|
160774
160999
|
const hasAlwaysOn = input.alwaysOn.profile.length > 0 || Boolean(input.alwaysOn.state) || input.alwaysOn.durable.length > 0;
|
|
160775
161000
|
if (hasAlwaysOn) {
|
|
@@ -161293,6 +161518,7 @@ async function buildTaskWorkset(input) {
|
|
|
161293
161518
|
version: "1.3",
|
|
161294
161519
|
task,
|
|
161295
161520
|
lens: input.lens,
|
|
161521
|
+
...input.continuity ? { continuity: input.continuity } : {},
|
|
161296
161522
|
...input.alwaysOn && (input.alwaysOn.profile.length > 0 || input.alwaysOn.state || input.alwaysOn.durable.length > 0) ? { alwaysOn: input.alwaysOn } : {},
|
|
161297
161523
|
currentFacts: input.currentFacts?.map((fact) => fact.startsWith("Historical note:") ? short(fact, 48) : short(fact, 28)).slice(0, 4) ?? [],
|
|
161298
161524
|
...continuation ? { continuation } : {},
|
|
@@ -162677,7 +162903,7 @@ var compaction_checkpoint_store_exports = {};
|
|
|
162677
162903
|
__export(compaction_checkpoint_store_exports, {
|
|
162678
162904
|
CompactionCheckpointStore: () => CompactionCheckpointStore
|
|
162679
162905
|
});
|
|
162680
|
-
import { createHash as
|
|
162906
|
+
import { createHash as createHash18, randomUUID as randomUUID16 } from "crypto";
|
|
162681
162907
|
function optionalText7(value) {
|
|
162682
162908
|
return typeof value === "string" && value ? value : void 0;
|
|
162683
162909
|
}
|
|
@@ -162719,7 +162945,7 @@ function sourceKeyFor(input, summary) {
|
|
|
162719
162945
|
input.tokensBefore ?? "",
|
|
162720
162946
|
input.firstKeptEntryId ?? ""
|
|
162721
162947
|
].join("\0");
|
|
162722
|
-
return `derived:${
|
|
162948
|
+
return `derived:${createHash18("sha256").update(material).digest("hex").slice(0, 32)}`;
|
|
162723
162949
|
}
|
|
162724
162950
|
function rowToCheckpoint(row) {
|
|
162725
162951
|
return {
|
|
@@ -162977,6 +163203,305 @@ var init_compaction_checkpoint_store = __esm({
|
|
|
162977
163203
|
}
|
|
162978
163204
|
});
|
|
162979
163205
|
|
|
163206
|
+
// src/knowledge/task-continuity.ts
|
|
163207
|
+
var task_continuity_exports = {};
|
|
163208
|
+
__export(task_continuity_exports, {
|
|
163209
|
+
TASK_CONTINUITY_EVENT_KINDS: () => TASK_CONTINUITY_EVENT_KINDS,
|
|
163210
|
+
TaskContinuityStore: () => TaskContinuityStore,
|
|
163211
|
+
evaluateTaskContinuity: () => evaluateTaskContinuity
|
|
163212
|
+
});
|
|
163213
|
+
import { randomUUID as randomUUID17 } from "crypto";
|
|
163214
|
+
function clean(value, maxLength = MAX_TEXT_LENGTH2) {
|
|
163215
|
+
return sanitizeCredentials(value).replace(/\s+/g, " ").trim().slice(0, maxLength);
|
|
163216
|
+
}
|
|
163217
|
+
function cleanList(values, maxLength = MAX_TEXT_LENGTH2) {
|
|
163218
|
+
return [...new Set((values ?? []).map((value) => clean(value, maxLength)).filter(Boolean))].slice(0, MAX_LIST_ITEMS2);
|
|
163219
|
+
}
|
|
163220
|
+
function parseRefs(value) {
|
|
163221
|
+
if (typeof value !== "string") return [];
|
|
163222
|
+
try {
|
|
163223
|
+
const parsed = JSON.parse(value);
|
|
163224
|
+
return Array.isArray(parsed) ? cleanList(parsed.filter((item) => typeof item === "string"), 500).slice(0, MAX_EVIDENCE_REFS) : [];
|
|
163225
|
+
} catch {
|
|
163226
|
+
return [];
|
|
163227
|
+
}
|
|
163228
|
+
}
|
|
163229
|
+
function evaluateTaskContinuity(ledger) {
|
|
163230
|
+
const verification = {
|
|
163231
|
+
passed: ledger.verification.filter((item) => item.status === "passed").length,
|
|
163232
|
+
failed: ledger.verification.filter((item) => item.status === "failed").length,
|
|
163233
|
+
pending: ledger.verification.filter((item) => item.status === "pending").length,
|
|
163234
|
+
skipped: ledger.verification.filter((item) => item.status === "skipped").length
|
|
163235
|
+
};
|
|
163236
|
+
const reasons = [];
|
|
163237
|
+
if (verification.failed > 0) reasons.push("verification-failed");
|
|
163238
|
+
if (verification.pending > 0) reasons.push("verification-pending");
|
|
163239
|
+
if (ledger.risks.length > 0) reasons.push("open-risks");
|
|
163240
|
+
if (ledger.status === "blocked") reasons.push("task-blocked");
|
|
163241
|
+
if (ledger.status === "abandoned") reasons.push("task-abandoned");
|
|
163242
|
+
if (ledger.status === "blocked" || ledger.status === "abandoned" || verification.failed > 0) {
|
|
163243
|
+
return {
|
|
163244
|
+
state: "at-risk",
|
|
163245
|
+
score: verification.passed > verification.failed ? 0.55 : 0.2,
|
|
163246
|
+
verification,
|
|
163247
|
+
reasons
|
|
163248
|
+
};
|
|
163249
|
+
}
|
|
163250
|
+
if (ledger.status === "completed") {
|
|
163251
|
+
if (verification.passed > 0 && verification.pending === 0 && verification.skipped === 0) {
|
|
163252
|
+
return {
|
|
163253
|
+
state: ledger.risks.length > 0 ? "validated-with-risks" : "validated",
|
|
163254
|
+
score: ledger.risks.length > 0 ? 0.8 : 1,
|
|
163255
|
+
verification,
|
|
163256
|
+
reasons: reasons.length > 0 ? reasons : ["verification-passed"]
|
|
163257
|
+
};
|
|
163258
|
+
}
|
|
163259
|
+
return {
|
|
163260
|
+
state: "unverified",
|
|
163261
|
+
score: 0.4,
|
|
163262
|
+
verification,
|
|
163263
|
+
reasons: reasons.length > 0 ? reasons : ["no-passing-verification"]
|
|
163264
|
+
};
|
|
163265
|
+
}
|
|
163266
|
+
return {
|
|
163267
|
+
state: "in-progress",
|
|
163268
|
+
score: verification.passed > 0 && verification.pending === 0 ? 0.75 : 0.5,
|
|
163269
|
+
verification,
|
|
163270
|
+
reasons: reasons.length > 0 ? reasons : ["task-open"]
|
|
163271
|
+
};
|
|
163272
|
+
}
|
|
163273
|
+
function rowToEvent4(row) {
|
|
163274
|
+
const status = row.item_status ? String(row.item_status) : void 0;
|
|
163275
|
+
return {
|
|
163276
|
+
id: String(row.id),
|
|
163277
|
+
projectId: String(row.project_id),
|
|
163278
|
+
taskId: String(row.task_id),
|
|
163279
|
+
task: clean(String(row.task), MAX_TASK_LENGTH),
|
|
163280
|
+
kind: row.kind,
|
|
163281
|
+
content: clean(String(row.content)),
|
|
163282
|
+
...status ? { status } : {},
|
|
163283
|
+
...row.source_ref ? { sourceRef: clean(String(row.source_ref), 500) } : {},
|
|
163284
|
+
evidenceRefs: parseRefs(row.evidence_json),
|
|
163285
|
+
...row.actor ? { actor: clean(String(row.actor), 200) } : {},
|
|
163286
|
+
at: String(row.created_at),
|
|
163287
|
+
...row.event_key ? { eventKey: clean(String(row.event_key), 200) } : {},
|
|
163288
|
+
...row.item_key ? { itemKey: clean(String(row.item_key), 120) } : {},
|
|
163289
|
+
...row.supersedes_id ? { supersedesId: clean(String(row.supersedes_id), 120) } : {}
|
|
163290
|
+
};
|
|
163291
|
+
}
|
|
163292
|
+
function aggregate(events) {
|
|
163293
|
+
const first2 = events.find((event) => event.kind === "task") ?? events[0];
|
|
163294
|
+
const latestOutcome = [...events].reverse().find((event) => event.kind === "outcome");
|
|
163295
|
+
const verificationByKey = /* @__PURE__ */ new Map();
|
|
163296
|
+
for (const event of events.filter((event2) => event2.kind === "verification")) {
|
|
163297
|
+
verificationByKey.set(event.itemKey ?? `event:${event.id}`, event);
|
|
163298
|
+
}
|
|
163299
|
+
const ledger = {
|
|
163300
|
+
taskId: first2.taskId,
|
|
163301
|
+
projectId: first2.projectId,
|
|
163302
|
+
task: first2.task,
|
|
163303
|
+
status: latestOutcome?.status ?? "open",
|
|
163304
|
+
requirements: events.filter((event) => event.kind === "requirement").map((event) => event.content),
|
|
163305
|
+
decisions: events.filter((event) => event.kind === "decision").map((event) => event.content),
|
|
163306
|
+
verification: [...verificationByKey.values()].map((event) => ({
|
|
163307
|
+
id: event.itemKey ?? event.id,
|
|
163308
|
+
content: event.content,
|
|
163309
|
+
status: event.status ?? "pending",
|
|
163310
|
+
...event.sourceRef ? { sourceRef: event.sourceRef } : {},
|
|
163311
|
+
evidenceRefs: event.evidenceRefs
|
|
163312
|
+
})),
|
|
163313
|
+
risks: events.filter((event) => event.kind === "risk").map((event) => event.content),
|
|
163314
|
+
outcomes: events.filter((event) => event.kind === "outcome").map((event) => event.content),
|
|
163315
|
+
updatedAt: events[events.length - 1].at,
|
|
163316
|
+
events
|
|
163317
|
+
};
|
|
163318
|
+
return { ...ledger, outcome: evaluateTaskContinuity(ledger) };
|
|
163319
|
+
}
|
|
163320
|
+
var TASK_CONTINUITY_EVENT_KINDS, MAX_TEXT_LENGTH2, MAX_TASK_LENGTH, MAX_LIST_ITEMS2, MAX_EVIDENCE_REFS, MAX_EVENTS_PER_TASK, TaskContinuityStore;
|
|
163321
|
+
var init_task_continuity = __esm({
|
|
163322
|
+
"src/knowledge/task-continuity.ts"() {
|
|
163323
|
+
"use strict";
|
|
163324
|
+
init_esm_shims();
|
|
163325
|
+
init_secret_filter();
|
|
163326
|
+
init_sqlite_db();
|
|
163327
|
+
TASK_CONTINUITY_EVENT_KINDS = [
|
|
163328
|
+
"task",
|
|
163329
|
+
"requirement",
|
|
163330
|
+
"decision",
|
|
163331
|
+
"verification",
|
|
163332
|
+
"risk",
|
|
163333
|
+
"outcome"
|
|
163334
|
+
];
|
|
163335
|
+
MAX_TEXT_LENGTH2 = 2e3;
|
|
163336
|
+
MAX_TASK_LENGTH = 1e3;
|
|
163337
|
+
MAX_LIST_ITEMS2 = 8;
|
|
163338
|
+
MAX_EVIDENCE_REFS = 8;
|
|
163339
|
+
MAX_EVENTS_PER_TASK = 200;
|
|
163340
|
+
TaskContinuityStore = class {
|
|
163341
|
+
db = null;
|
|
163342
|
+
async init(dataDir) {
|
|
163343
|
+
this.db = getDatabase(dataDir);
|
|
163344
|
+
}
|
|
163345
|
+
requireDb() {
|
|
163346
|
+
if (!this.db) throw new Error("TaskContinuityStore is not initialized.");
|
|
163347
|
+
return this.db;
|
|
163348
|
+
}
|
|
163349
|
+
insert(input) {
|
|
163350
|
+
const db2 = this.requireDb();
|
|
163351
|
+
const projectId = clean(input.projectId, 500);
|
|
163352
|
+
const taskId = clean(input.taskId, 120);
|
|
163353
|
+
const eventKey = input.eventKey ? clean(input.eventKey, 200) : void 0;
|
|
163354
|
+
if (eventKey) {
|
|
163355
|
+
const existing = db2.prepare(
|
|
163356
|
+
"SELECT * FROM task_continuity_events WHERE project_id = ? AND task_id = ? AND event_key = ?"
|
|
163357
|
+
).get(projectId, taskId, eventKey);
|
|
163358
|
+
if (existing) return rowToEvent4(existing);
|
|
163359
|
+
}
|
|
163360
|
+
const existingCount = db2.prepare(
|
|
163361
|
+
"SELECT COUNT(*) AS count FROM task_continuity_events WHERE project_id = ? AND task_id = ?"
|
|
163362
|
+
).get(projectId, taskId);
|
|
163363
|
+
if (Number(existingCount?.count ?? 0) >= MAX_EVENTS_PER_TASK) {
|
|
163364
|
+
throw new Error("Task continuity ledger reached its 200-event limit.");
|
|
163365
|
+
}
|
|
163366
|
+
const event = {
|
|
163367
|
+
id: randomUUID17(),
|
|
163368
|
+
projectId,
|
|
163369
|
+
taskId,
|
|
163370
|
+
task: clean(input.task, MAX_TASK_LENGTH),
|
|
163371
|
+
kind: input.kind,
|
|
163372
|
+
content: clean(input.content),
|
|
163373
|
+
...input.status ? { status: input.status } : {},
|
|
163374
|
+
...input.sourceRef ? { sourceRef: clean(input.sourceRef, 500) } : {},
|
|
163375
|
+
evidenceRefs: cleanList(input.evidenceRefs, 500).slice(0, MAX_EVIDENCE_REFS),
|
|
163376
|
+
...input.actor ? { actor: clean(input.actor, 200) } : {},
|
|
163377
|
+
at: input.at ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
163378
|
+
...eventKey ? { eventKey } : {},
|
|
163379
|
+
...input.itemKey ? { itemKey: clean(input.itemKey, 120) } : {},
|
|
163380
|
+
...input.supersedesId ? { supersedesId: clean(input.supersedesId, 120) } : {}
|
|
163381
|
+
};
|
|
163382
|
+
db2.prepare(`
|
|
163383
|
+
INSERT INTO task_continuity_events (
|
|
163384
|
+
id, project_id, task_id, task, kind, content, item_status,
|
|
163385
|
+
source_ref, evidence_json, actor, created_at, event_key, item_key, supersedes_id
|
|
163386
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
163387
|
+
`).run(
|
|
163388
|
+
event.id,
|
|
163389
|
+
event.projectId,
|
|
163390
|
+
event.taskId,
|
|
163391
|
+
event.task,
|
|
163392
|
+
event.kind,
|
|
163393
|
+
event.content,
|
|
163394
|
+
event.status ?? null,
|
|
163395
|
+
event.sourceRef ?? null,
|
|
163396
|
+
JSON.stringify(event.evidenceRefs),
|
|
163397
|
+
event.actor ?? null,
|
|
163398
|
+
event.at,
|
|
163399
|
+
event.eventKey ?? null,
|
|
163400
|
+
event.itemKey ?? null,
|
|
163401
|
+
event.supersedesId ?? null
|
|
163402
|
+
);
|
|
163403
|
+
return event;
|
|
163404
|
+
}
|
|
163405
|
+
start(input) {
|
|
163406
|
+
const task = clean(input.task, MAX_TASK_LENGTH);
|
|
163407
|
+
if (!task) throw new Error("A non-empty task is required.");
|
|
163408
|
+
const idempotencyKey = input.idempotencyKey ? clean(input.idempotencyKey, 200) : void 0;
|
|
163409
|
+
const taskId = clean(input.taskId ?? idempotencyKey ?? "", 120) || randomUUID17();
|
|
163410
|
+
const requirements = cleanList(input.requirements);
|
|
163411
|
+
const transaction = this.requireDb().transaction(() => {
|
|
163412
|
+
this.insert({
|
|
163413
|
+
projectId: input.projectId,
|
|
163414
|
+
taskId,
|
|
163415
|
+
task,
|
|
163416
|
+
kind: "task",
|
|
163417
|
+
content: task,
|
|
163418
|
+
status: "open",
|
|
163419
|
+
actor: input.actor,
|
|
163420
|
+
...idempotencyKey ? { eventKey: `start:${idempotencyKey}` } : {}
|
|
163421
|
+
});
|
|
163422
|
+
for (const requirement of requirements) {
|
|
163423
|
+
this.insert({
|
|
163424
|
+
projectId: input.projectId,
|
|
163425
|
+
taskId,
|
|
163426
|
+
task,
|
|
163427
|
+
kind: "requirement",
|
|
163428
|
+
content: requirement,
|
|
163429
|
+
actor: input.actor
|
|
163430
|
+
});
|
|
163431
|
+
}
|
|
163432
|
+
});
|
|
163433
|
+
transaction.immediate();
|
|
163434
|
+
return { taskId, ledger: this.get(input.projectId, taskId) };
|
|
163435
|
+
}
|
|
163436
|
+
record(input) {
|
|
163437
|
+
const projectId = clean(input.projectId, 500);
|
|
163438
|
+
const taskId = clean(input.taskId, 120);
|
|
163439
|
+
const existing = this.get(projectId, taskId);
|
|
163440
|
+
if (!existing) throw new Error("Task continuity ledger not found: " + taskId);
|
|
163441
|
+
const transaction = this.requireDb().transaction(() => this.insert({
|
|
163442
|
+
projectId,
|
|
163443
|
+
taskId,
|
|
163444
|
+
task: existing.task,
|
|
163445
|
+
kind: input.kind,
|
|
163446
|
+
content: input.content,
|
|
163447
|
+
...input.kind === "verification" && input.verificationStatus ? { status: input.verificationStatus } : {},
|
|
163448
|
+
sourceRef: input.sourceRef,
|
|
163449
|
+
evidenceRefs: input.evidenceRefs,
|
|
163450
|
+
actor: input.actor,
|
|
163451
|
+
at: input.at,
|
|
163452
|
+
...input.idempotencyKey ? { eventKey: input.idempotencyKey } : {},
|
|
163453
|
+
...input.verificationId ? { itemKey: input.verificationId } : {}
|
|
163454
|
+
}));
|
|
163455
|
+
const event = transaction.immediate();
|
|
163456
|
+
return { event, ledger: this.get(projectId, taskId) };
|
|
163457
|
+
}
|
|
163458
|
+
close(input) {
|
|
163459
|
+
const projectId = clean(input.projectId, 500);
|
|
163460
|
+
const taskId = clean(input.taskId, 120);
|
|
163461
|
+
const existing = this.get(projectId, taskId);
|
|
163462
|
+
if (!existing) throw new Error("Task continuity ledger not found: " + taskId);
|
|
163463
|
+
const transaction = this.requireDb().transaction(() => this.insert({
|
|
163464
|
+
projectId,
|
|
163465
|
+
taskId,
|
|
163466
|
+
task: existing.task,
|
|
163467
|
+
kind: "outcome",
|
|
163468
|
+
content: input.content,
|
|
163469
|
+
status: input.status,
|
|
163470
|
+
sourceRef: input.sourceRef,
|
|
163471
|
+
evidenceRefs: input.evidenceRefs,
|
|
163472
|
+
actor: input.actor,
|
|
163473
|
+
at: input.at,
|
|
163474
|
+
...input.idempotencyKey ? { eventKey: input.idempotencyKey } : {}
|
|
163475
|
+
}));
|
|
163476
|
+
const event = transaction.immediate();
|
|
163477
|
+
return { event, ledger: this.get(projectId, taskId) };
|
|
163478
|
+
}
|
|
163479
|
+
get(projectId, taskId) {
|
|
163480
|
+
const normalizedProjectId = clean(projectId, 500);
|
|
163481
|
+
const normalizedTaskId = clean(taskId, 120);
|
|
163482
|
+
const rows = this.requireDb().prepare(`
|
|
163483
|
+
SELECT * FROM task_continuity_events
|
|
163484
|
+
WHERE project_id = ? AND task_id = ?
|
|
163485
|
+
ORDER BY created_at ASC, rowid ASC
|
|
163486
|
+
`).all(normalizedProjectId, normalizedTaskId);
|
|
163487
|
+
if (rows.length === 0) return void 0;
|
|
163488
|
+
return aggregate(rows.map(rowToEvent4));
|
|
163489
|
+
}
|
|
163490
|
+
list(projectId, limit2 = 20) {
|
|
163491
|
+
const rows = this.requireDb().prepare(`
|
|
163492
|
+
SELECT task_id
|
|
163493
|
+
FROM task_continuity_events
|
|
163494
|
+
WHERE project_id = ?
|
|
163495
|
+
GROUP BY task_id
|
|
163496
|
+
ORDER BY MAX(created_at) DESC
|
|
163497
|
+
LIMIT ?
|
|
163498
|
+
`).all(projectId, Math.min(100, Math.max(1, Math.floor(limit2))));
|
|
163499
|
+
return rows.map((row) => this.get(projectId, String(row.task_id))).filter((ledger) => Boolean(ledger));
|
|
163500
|
+
}
|
|
163501
|
+
};
|
|
163502
|
+
}
|
|
163503
|
+
});
|
|
163504
|
+
|
|
162980
163505
|
// src/codegraph/auto-context.ts
|
|
162981
163506
|
var auto_context_exports = {};
|
|
162982
163507
|
__export(auto_context_exports, {
|
|
@@ -163233,6 +163758,16 @@ async function buildAutoProjectContext(input) {
|
|
|
163233
163758
|
};
|
|
163234
163759
|
}
|
|
163235
163760
|
}
|
|
163761
|
+
let continuity = input.continuity;
|
|
163762
|
+
if (!continuity && input.taskId) {
|
|
163763
|
+
try {
|
|
163764
|
+
const { TaskContinuityStore: TaskContinuityStore2 } = await Promise.resolve().then(() => (init_task_continuity(), task_continuity_exports));
|
|
163765
|
+
const continuityStore = new TaskContinuityStore2();
|
|
163766
|
+
await continuityStore.init(input.dataDir);
|
|
163767
|
+
continuity = continuityStore.get(input.project.id, input.taskId);
|
|
163768
|
+
} catch {
|
|
163769
|
+
}
|
|
163770
|
+
}
|
|
163236
163771
|
const alwaysOn = await buildAlwaysOnBlock({
|
|
163237
163772
|
dataDir: input.dataDir,
|
|
163238
163773
|
projectId: input.project.id,
|
|
@@ -163251,6 +163786,7 @@ async function buildAutoProjectContext(input) {
|
|
|
163251
163786
|
providerQuality: providerQuality2,
|
|
163252
163787
|
currentFacts: worksetFactLines(currentFacts),
|
|
163253
163788
|
...continuation ? { continuation } : {},
|
|
163789
|
+
...continuity ? { continuity } : {},
|
|
163254
163790
|
codeState: codeStateLine(overview),
|
|
163255
163791
|
...codeEvolution ? { codeEvolution } : {},
|
|
163256
163792
|
reliableMemory: sourceSets.reliableSources.slice(0, lens.sourceLimit).map((source) => ({
|
|
@@ -163298,6 +163834,7 @@ async function buildAutoProjectContext(input) {
|
|
|
163298
163834
|
refresh,
|
|
163299
163835
|
providerQuality: providerQuality2,
|
|
163300
163836
|
...continuationRequested && workset.continuation ? { continuation: workset.continuation } : {},
|
|
163837
|
+
...workset.continuity ? { continuity: workset.continuity } : {},
|
|
163301
163838
|
workset
|
|
163302
163839
|
};
|
|
163303
163840
|
}
|
|
@@ -163599,7 +164136,14 @@ function buildBoundedContextReceipt(input) {
|
|
|
163599
164136
|
externalState: provider2?.external.state ?? "not-detected",
|
|
163600
164137
|
...input.workset.provenance.snapshotId ? { snapshotId: input.workset.provenance.snapshotId } : {}
|
|
163601
164138
|
},
|
|
163602
|
-
...input.workset.agentLoadout ? { loadout: input.workset.agentLoadout } : {}
|
|
164139
|
+
...input.workset.agentLoadout ? { loadout: input.workset.agentLoadout } : {},
|
|
164140
|
+
...input.workset.continuity ? {
|
|
164141
|
+
continuity: {
|
|
164142
|
+
taskId: input.workset.continuity.taskId,
|
|
164143
|
+
status: input.workset.continuity.status,
|
|
164144
|
+
outcome: input.workset.continuity.outcome
|
|
164145
|
+
}
|
|
164146
|
+
} : {}
|
|
163603
164147
|
};
|
|
163604
164148
|
}
|
|
163605
164149
|
var init_context_receipt = __esm({
|
|
@@ -164231,15 +164775,21 @@ var team_store_exports = {};
|
|
|
164231
164775
|
__export(team_store_exports, {
|
|
164232
164776
|
AGENT_TYPE_ROLE_MAP: () => AGENT_TYPE_ROLE_MAP,
|
|
164233
164777
|
DEFAULT_ROLES: () => DEFAULT_ROLES,
|
|
164778
|
+
DEFAULT_TEAM_QUERY_LIMIT: () => DEFAULT_TEAM_QUERY_LIMIT,
|
|
164779
|
+
MAX_TEAM_QUERY_LIMIT: () => MAX_TEAM_QUERY_LIMIT,
|
|
164234
164780
|
TeamStore: () => TeamStore,
|
|
164235
164781
|
getTeamStore: () => getTeamStore,
|
|
164236
164782
|
initTeamStore: () => initTeamStore,
|
|
164237
164783
|
isTeamStoreInitialized: () => isTeamStoreInitialized,
|
|
164238
164784
|
resetTeamStore: () => resetTeamStore
|
|
164239
164785
|
});
|
|
164240
|
-
import { randomUUID as
|
|
164786
|
+
import { randomUUID as randomUUID18 } from "crypto";
|
|
164241
164787
|
import path31 from "path";
|
|
164242
164788
|
import fs18 from "fs";
|
|
164789
|
+
function clampTeamQueryLimit(limit2) {
|
|
164790
|
+
if (!Number.isFinite(limit2) || limit2 == null) return DEFAULT_TEAM_QUERY_LIMIT;
|
|
164791
|
+
return Math.min(MAX_TEAM_QUERY_LIMIT, Math.max(1, Math.floor(limit2)));
|
|
164792
|
+
}
|
|
164243
164793
|
function getTeamStore() {
|
|
164244
164794
|
if (!_teamStore) {
|
|
164245
164795
|
throw new Error("[memorix] TeamStore not initialized \u2014 call initTeamStore() first");
|
|
@@ -164263,12 +164813,14 @@ function resetTeamStore() {
|
|
|
164263
164813
|
_teamStore = null;
|
|
164264
164814
|
_teamStoreDataDir = null;
|
|
164265
164815
|
}
|
|
164266
|
-
var DEFAULT_ROLES, AGENT_TYPE_ROLE_MAP, TeamStore, _teamStore, _teamStoreDataDir;
|
|
164816
|
+
var DEFAULT_TEAM_QUERY_LIMIT, MAX_TEAM_QUERY_LIMIT, DEFAULT_ROLES, AGENT_TYPE_ROLE_MAP, TeamStore, _teamStore, _teamStoreDataDir;
|
|
164267
164817
|
var init_team_store = __esm({
|
|
164268
164818
|
"src/team/team-store.ts"() {
|
|
164269
164819
|
"use strict";
|
|
164270
164820
|
init_esm_shims();
|
|
164271
164821
|
init_sqlite_db();
|
|
164822
|
+
DEFAULT_TEAM_QUERY_LIMIT = 100;
|
|
164823
|
+
MAX_TEAM_QUERY_LIMIT = 500;
|
|
164272
164824
|
DEFAULT_ROLES = [
|
|
164273
164825
|
{ roleId: "planner", label: "Planner", description: "Breaks down requirements, creates tasks, defines dependencies", preferredAgentTypes: ["claude-code", "cursor", "codex"], maxConcurrent: 2 },
|
|
164274
164826
|
{ roleId: "researcher", label: "Researcher", description: "Investigates codebase, gathers context, answers questions", preferredAgentTypes: ["claude-code", "cursor", "gemini-cli"], maxConcurrent: 2 },
|
|
@@ -164526,7 +165078,7 @@ var init_team_store = __esm({
|
|
|
164526
165078
|
* reactivate it (preserving agent_id). Otherwise create a new one.
|
|
164527
165079
|
*/
|
|
164528
165080
|
registerAgent(input) {
|
|
164529
|
-
const instanceId = input.instanceId ||
|
|
165081
|
+
const instanceId = input.instanceId || randomUUID18();
|
|
164530
165082
|
const now3 = Date.now();
|
|
164531
165083
|
const existing = this.stmtAgentFindByInstance.get(
|
|
164532
165084
|
input.projectId,
|
|
@@ -164552,7 +165104,7 @@ var init_team_store = __esm({
|
|
|
164552
165104
|
this.eventBus?.emit("agent:joined", { agentId: row2.agent_id, projectId: input.projectId, agentType: input.agentType });
|
|
164553
165105
|
return row2;
|
|
164554
165106
|
}
|
|
164555
|
-
const agentId =
|
|
165107
|
+
const agentId = randomUUID18();
|
|
164556
165108
|
this.stmtAgentUpsert.run({
|
|
164557
165109
|
agent_id: agentId,
|
|
164558
165110
|
project_id: input.projectId,
|
|
@@ -164578,32 +165130,37 @@ var init_team_store = __esm({
|
|
|
164578
165130
|
return this.stmtAgentFindByInstance.get(projectId, agentType, instanceId);
|
|
164579
165131
|
}
|
|
164580
165132
|
listAgents(projectId, filter) {
|
|
164581
|
-
const
|
|
165133
|
+
const limit2 = clampTeamQueryLimit(filter?.limit);
|
|
164582
165134
|
if (filter?.status) {
|
|
164583
|
-
return
|
|
165135
|
+
return this.db.prepare(
|
|
165136
|
+
`SELECT * FROM team_agents WHERE project_id = ? AND status = ? ORDER BY joined_at DESC LIMIT ?`
|
|
165137
|
+
).all(projectId, filter.status, limit2);
|
|
164584
165138
|
}
|
|
164585
|
-
return
|
|
165139
|
+
return this.db.prepare(
|
|
165140
|
+
`SELECT * FROM team_agents WHERE project_id = ? ORDER BY joined_at DESC LIMIT ?`
|
|
165141
|
+
).all(projectId, limit2);
|
|
164586
165142
|
}
|
|
164587
165143
|
/** List agents across all projects (for global scope) */
|
|
164588
|
-
listAllAgents() {
|
|
165144
|
+
listAllAgents(limit2) {
|
|
164589
165145
|
if (!this.db) return [];
|
|
164590
|
-
return this.db.prepare("SELECT * FROM team_agents ORDER BY last_heartbeat DESC").all();
|
|
165146
|
+
return this.db.prepare("SELECT * FROM team_agents ORDER BY last_heartbeat DESC LIMIT ?").all(clampTeamQueryLimit(limit2));
|
|
164591
165147
|
}
|
|
164592
165148
|
/** List locks across all projects (for global scope) */
|
|
164593
|
-
listAllLocks() {
|
|
165149
|
+
listAllLocks(limit2) {
|
|
164594
165150
|
if (!this.db) return [];
|
|
164595
165151
|
this.db.prepare("DELETE FROM team_locks WHERE expires_at <= ?").run(Date.now());
|
|
164596
|
-
return this.db.prepare("SELECT * FROM team_locks WHERE expires_at > ? ORDER BY locked_at DESC").all(Date.now());
|
|
165152
|
+
return this.db.prepare("SELECT * FROM team_locks WHERE expires_at > ? ORDER BY locked_at DESC LIMIT ?").all(Date.now(), clampTeamQueryLimit(limit2));
|
|
164597
165153
|
}
|
|
164598
165154
|
/** List tasks across all projects (for global scope) */
|
|
164599
165155
|
listAllTasks(filter) {
|
|
164600
165156
|
if (!this.db) return [];
|
|
165157
|
+
const limit2 = clampTeamQueryLimit(filter?.limit);
|
|
164601
165158
|
if (filter?.available) {
|
|
164602
165159
|
return this.db.prepare(
|
|
164603
|
-
`SELECT t.* FROM team_tasks t WHERE t.status = 'pending' AND t.assignee_agent_id IS NULL ORDER BY t.created_at DESC
|
|
164604
|
-
).all();
|
|
165160
|
+
`SELECT t.* FROM team_tasks t WHERE t.status = 'pending' AND t.assignee_agent_id IS NULL ORDER BY t.created_at DESC LIMIT ?`
|
|
165161
|
+
).all(limit2);
|
|
164605
165162
|
}
|
|
164606
|
-
return this.db.prepare("SELECT * FROM team_tasks ORDER BY created_at DESC").all();
|
|
165163
|
+
return this.db.prepare("SELECT * FROM team_tasks ORDER BY created_at DESC LIMIT ?").all(limit2);
|
|
164607
165164
|
}
|
|
164608
165165
|
heartbeat(agentId) {
|
|
164609
165166
|
const info = this.stmtAgentUpdateHeartbeat.run(Date.now(), agentId);
|
|
@@ -164638,7 +165195,10 @@ var init_team_store = __esm({
|
|
|
164638
165195
|
return staleIds;
|
|
164639
165196
|
}
|
|
164640
165197
|
getActiveCount(projectId) {
|
|
164641
|
-
|
|
165198
|
+
const row = this.db.prepare(
|
|
165199
|
+
`SELECT COUNT(*) AS count FROM team_agents WHERE project_id = ? AND status = 'active'`
|
|
165200
|
+
).get(projectId);
|
|
165201
|
+
return Number(row?.count ?? 0);
|
|
164642
165202
|
}
|
|
164643
165203
|
// ═══════════════════════════════════════════════════════════════════
|
|
164644
165204
|
// Message Operations
|
|
@@ -164654,7 +165214,7 @@ var init_team_store = __esm({
|
|
|
164654
165214
|
return { error: `Recipient agent '${input.recipientAgentId}' not found \u2014 cannot send to unknown agent` };
|
|
164655
165215
|
}
|
|
164656
165216
|
}
|
|
164657
|
-
const id =
|
|
165217
|
+
const id = randomUUID18();
|
|
164658
165218
|
const now3 = Date.now();
|
|
164659
165219
|
const row = {
|
|
164660
165220
|
id,
|
|
@@ -164673,8 +165233,14 @@ var init_team_store = __esm({
|
|
|
164673
165233
|
this.stmtMsgInsert.run(row);
|
|
164674
165234
|
return row;
|
|
164675
165235
|
}
|
|
164676
|
-
getInbox(projectId, agentId) {
|
|
164677
|
-
return this.
|
|
165236
|
+
getInbox(projectId, agentId, limit2) {
|
|
165237
|
+
return this.db.prepare(`
|
|
165238
|
+
SELECT * FROM team_messages
|
|
165239
|
+
WHERE project_id = ?
|
|
165240
|
+
AND (recipient_agent_id = ? OR recipient_agent_id IS NULL)
|
|
165241
|
+
ORDER BY created_at ASC
|
|
165242
|
+
LIMIT ?
|
|
165243
|
+
`).all(projectId, agentId, clampTeamQueryLimit(limit2));
|
|
164678
165244
|
}
|
|
164679
165245
|
getUnreadCount(projectId, agentId) {
|
|
164680
165246
|
const row = this.stmtMsgUnreadCount.get(projectId, agentId);
|
|
@@ -164704,7 +165270,7 @@ var init_team_store = __esm({
|
|
|
164704
165270
|
// Task Operations (with atomic claim semantics)
|
|
164705
165271
|
// ═══════════════════════════════════════════════════════════════════
|
|
164706
165272
|
createTask(input) {
|
|
164707
|
-
const taskId =
|
|
165273
|
+
const taskId = randomUUID18();
|
|
164708
165274
|
const now3 = Date.now();
|
|
164709
165275
|
const row = {
|
|
164710
165276
|
task_id: taskId,
|
|
@@ -164831,17 +165397,22 @@ var init_team_store = __esm({
|
|
|
164831
165397
|
return info.changes;
|
|
164832
165398
|
}
|
|
164833
165399
|
listTasks(projectId, filter) {
|
|
164834
|
-
|
|
164835
|
-
|
|
164836
|
-
|
|
164837
|
-
const all = this.stmtTaskListByProject.all(projectId);
|
|
165400
|
+
const clauses = ["project_id = ?"];
|
|
165401
|
+
const values = [projectId];
|
|
165402
|
+
if (filter?.available) clauses.push("status = 'pending'", "assignee_agent_id IS NULL");
|
|
164838
165403
|
if (filter?.status) {
|
|
164839
|
-
|
|
165404
|
+
clauses.push("status = ?");
|
|
165405
|
+
values.push(filter.status);
|
|
164840
165406
|
}
|
|
164841
165407
|
if (filter?.assignee) {
|
|
164842
|
-
|
|
165408
|
+
clauses.push("assignee_agent_id = ?");
|
|
165409
|
+
values.push(filter.assignee);
|
|
164843
165410
|
}
|
|
164844
|
-
|
|
165411
|
+
values.push(clampTeamQueryLimit(filter?.limit));
|
|
165412
|
+
const orderBy = filter?.available ? "created_at ASC, rowid ASC" : "created_at DESC, rowid DESC";
|
|
165413
|
+
return this.db.prepare(
|
|
165414
|
+
`SELECT * FROM team_tasks WHERE ${clauses.join(" AND ")} ORDER BY ${orderBy} LIMIT ?`
|
|
165415
|
+
).all(...values);
|
|
164845
165416
|
}
|
|
164846
165417
|
/**
|
|
164847
165418
|
* List available tasks for a specific agent, sorted by role affinity.
|
|
@@ -164853,7 +165424,7 @@ var init_team_store = __esm({
|
|
|
164853
165424
|
const agent = this.stmtAgentFindById.get(agentId);
|
|
164854
165425
|
if (!agent) return [];
|
|
164855
165426
|
const agentRole = agent.role;
|
|
164856
|
-
const available = this.
|
|
165427
|
+
const available = this.listTasks(projectId, { available: true, limit: MAX_TEAM_QUERY_LIMIT });
|
|
164857
165428
|
const eligible = available.filter((t2) => !t2.required_role || t2.required_role === agentRole);
|
|
164858
165429
|
const score = (t2) => {
|
|
164859
165430
|
if (t2.preferred_role === agentRole) return 0;
|
|
@@ -164907,12 +165478,16 @@ var init_team_store = __esm({
|
|
|
164907
165478
|
const row = this.stmtLockGet.get(file, projectId);
|
|
164908
165479
|
return row ?? null;
|
|
164909
165480
|
}
|
|
164910
|
-
listLocks(projectId, agentId) {
|
|
165481
|
+
listLocks(projectId, agentId, limit2) {
|
|
164911
165482
|
this.stmtLockDeleteExpired.run(projectId, Date.now());
|
|
164912
165483
|
if (agentId) {
|
|
164913
|
-
return this.
|
|
165484
|
+
return this.db.prepare(
|
|
165485
|
+
`SELECT * FROM team_locks WHERE project_id = ? AND locked_by = ? ORDER BY locked_at DESC LIMIT ?`
|
|
165486
|
+
).all(projectId, agentId, clampTeamQueryLimit(limit2));
|
|
164914
165487
|
}
|
|
164915
|
-
return this.
|
|
165488
|
+
return this.db.prepare(
|
|
165489
|
+
`SELECT * FROM team_locks WHERE project_id = ? ORDER BY locked_at DESC LIMIT ?`
|
|
165490
|
+
).all(projectId, clampTeamQueryLimit(limit2));
|
|
164916
165491
|
}
|
|
164917
165492
|
releaseAllLocks(agentId) {
|
|
164918
165493
|
const info = this.stmtLockDeleteByAgent.run(agentId);
|
|
@@ -164976,7 +165551,7 @@ var init_team_store = __esm({
|
|
|
164976
165551
|
for (const [agentId, msgs] of Object.entries(snap.messages.inboxes)) {
|
|
164977
165552
|
for (const msg of msgs) {
|
|
164978
165553
|
this.stmtMsgInsert.run({
|
|
164979
|
-
id: msg.id ??
|
|
165554
|
+
id: msg.id ?? randomUUID18(),
|
|
164980
165555
|
project_id: "migrated",
|
|
164981
165556
|
sender_agent_id: msg.from ?? "unknown",
|
|
164982
165557
|
recipient_agent_id: msg.to === "__broadcast__" ? null : msg.to ?? agentId,
|
|
@@ -167934,7 +168509,7 @@ __export(planner_exports, {
|
|
|
167934
168509
|
materializeTaskGraph: () => materializeTaskGraph,
|
|
167935
168510
|
seedAutonomousPipeline: () => seedAutonomousPipeline
|
|
167936
168511
|
});
|
|
167937
|
-
import { randomUUID as
|
|
168512
|
+
import { randomUUID as randomUUID19 } from "crypto";
|
|
167938
168513
|
function isPlannerTask(metadata) {
|
|
167939
168514
|
if (!metadata) return null;
|
|
167940
168515
|
try {
|
|
@@ -167992,7 +168567,7 @@ function seedAutonomousPipeline(teamStore, projectId, config, opts) {
|
|
|
167992
168567
|
const maxIterations = config.maxIterations ?? 3;
|
|
167993
168568
|
const taskBudget = config.taskBudget ?? 15;
|
|
167994
168569
|
const structuredPlan = opts?.structuredPlan ?? true;
|
|
167995
|
-
const pipelineId =
|
|
168570
|
+
const pipelineId = randomUUID19();
|
|
167996
168571
|
const meta = {
|
|
167997
168572
|
plannerType: "plan",
|
|
167998
168573
|
pipelineId,
|
|
@@ -168673,6 +169248,7 @@ var init_official_skills = __esm({
|
|
|
168673
169248
|
"| Need the sequence around one memory | `memorix_timeline` | `memorix memory timeline --id <id>` |",
|
|
168674
169249
|
"| Check source and freshness for a memory | `memorix_evidence` | `memorix evidence list|get|events` |",
|
|
168675
169250
|
"| Record whether a memory helped, conflicted, or was corrected | `memorix_feedback` | `memorix feedback record|show|audit` |",
|
|
169251
|
+
"| Track task requirements, decisions, verification, and outcome | `memorix_continuity` | `memorix continuity start|record|show|close` |",
|
|
168676
169252
|
"| Inspect or import controlled media | `memorix_media` | `memorix media import|attach|list|show|status` |",
|
|
168677
169253
|
'| Learned reusable project knowledge | `memorix_store` | `memorix memory store --type <type> --entity <name> --title "<title>" "<text>"` |',
|
|
168678
169254
|
"| Task or bug is complete/outdated | `memorix_resolve` | `memorix memory resolve --ids <ids>` |",
|
|
@@ -168696,6 +169272,7 @@ var init_official_skills = __esm({
|
|
|
168696
169272
|
"3. Use stale or unbound memory only as a warning or search lead.",
|
|
168697
169273
|
"4. Store durable decisions, fixes, and gotchas after the project state changes.",
|
|
168698
169274
|
"5. Resolve completed or obsolete memories so future briefs stay small.",
|
|
169275
|
+
"6. For multi-step work, start a continuity ledger and pass its taskId back to memorix_project_context.",
|
|
168699
169276
|
"",
|
|
168700
169277
|
"## Store Rules",
|
|
168701
169278
|
"",
|
|
@@ -170417,7 +170994,7 @@ __export(server_exports2, {
|
|
|
170417
170994
|
createMemorixServer: () => createMemorixServer,
|
|
170418
170995
|
shouldAwaitProjectRuntime: () => shouldAwaitProjectRuntime
|
|
170419
170996
|
});
|
|
170420
|
-
import { createHash as
|
|
170997
|
+
import { createHash as createHash19 } from "crypto";
|
|
170421
170998
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
170422
170999
|
import { z as z627 } from "zod";
|
|
170423
171000
|
function formatFormationStageDurations(stageDurationsMs) {
|
|
@@ -170501,7 +171078,7 @@ function coerceObjectArray(val) {
|
|
|
170501
171078
|
return [];
|
|
170502
171079
|
}
|
|
170503
171080
|
function createDeterministicInstanceId(projectId, agentType, agentName) {
|
|
170504
|
-
const digest2 =
|
|
171081
|
+
const digest2 = createHash19("sha256").update(projectId).update("\n").update(agentType).update("\n").update(agentName ?? "").digest("hex").slice(0, 24);
|
|
170505
171082
|
return `auto-${digest2}`;
|
|
170506
171083
|
}
|
|
170507
171084
|
function shouldAwaitProjectRuntime(toolName) {
|
|
@@ -170708,6 +171285,22 @@ async function createMemorixServer(cwd, existingServer, sharedTeam, options = {}
|
|
|
170708
171285
|
}
|
|
170709
171286
|
await projectRuntimeInitPromise;
|
|
170710
171287
|
};
|
|
171288
|
+
const activateProjectRuntime = async () => {
|
|
171289
|
+
if (!projectResolved) return;
|
|
171290
|
+
await initObservationStore(projectDir2);
|
|
171291
|
+
await initMiniSkillStore(projectDir2);
|
|
171292
|
+
await initSessionStore(projectDir2);
|
|
171293
|
+
await initObservations(projectDir2, { skipCorpusLoad: true });
|
|
171294
|
+
try {
|
|
171295
|
+
const { initProjectRoot: initProjectRoot2 } = await Promise.resolve().then(() => (init_yaml_loader(), yaml_loader_exports));
|
|
171296
|
+
const { resetDotenv: resetDotenv2, loadDotenv: loadDotenv2 } = await Promise.resolve().then(() => (init_dotenv_loader(), dotenv_loader_exports));
|
|
171297
|
+
initProjectRoot2(project.rootPath);
|
|
171298
|
+
resetDotenv2();
|
|
171299
|
+
loadDotenv2(project.rootPath);
|
|
171300
|
+
} catch {
|
|
171301
|
+
}
|
|
171302
|
+
initLLM({ projectRoot: project.rootPath });
|
|
171303
|
+
};
|
|
170711
171304
|
let maintenanceWorker = null;
|
|
170712
171305
|
const startProjectMaintenanceWorker = async (autoCleanup = false) => {
|
|
170713
171306
|
maintenanceWorker?.stop();
|
|
@@ -171623,6 +172216,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
171623
172216
|
description: "Build a compact Memory Autopilot brief for the current coding task. Schedules Code Memory refresh when needed, includes Start here files, reliable code-bound memories, stale/suspect cautions, and verification hints. Use this at the start of a new coding turn or after switching tasks.",
|
|
171624
172217
|
inputSchema: {
|
|
171625
172218
|
task: z627.string().optional().describe("Current coding task or question"),
|
|
172219
|
+
taskId: z627.string().max(120).optional().describe("Optional task continuity ledger id to include in the brief"),
|
|
171626
172220
|
refresh: z627.enum(["auto", "always", "never"]).optional().default("auto").describe(
|
|
171627
172221
|
"Code Memory refresh policy. auto refreshes only when missing or stale."
|
|
171628
172222
|
),
|
|
@@ -171647,7 +172241,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
171647
172241
|
limit: z627.number().optional().describe("Reserved for future source limits; current prompt stays compact by default.")
|
|
171648
172242
|
}
|
|
171649
172243
|
},
|
|
171650
|
-
async ({ task, refresh, format, agent }) => {
|
|
172244
|
+
async ({ task, taskId, refresh, format, agent }) => {
|
|
171651
172245
|
const unresolved = requireResolvedProject("build project context for the current project");
|
|
171652
172246
|
if (unresolved) return unresolved;
|
|
171653
172247
|
const [
|
|
@@ -171677,6 +172271,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
171677
172271
|
dataDir: projectDir2,
|
|
171678
172272
|
observations: observations2,
|
|
171679
172273
|
task,
|
|
172274
|
+
taskId,
|
|
171680
172275
|
agent,
|
|
171681
172276
|
refresh: refresh ?? "auto",
|
|
171682
172277
|
reader: getObservationReader(),
|
|
@@ -174102,6 +174697,94 @@ ${json2}
|
|
|
174102
174697
|
}
|
|
174103
174698
|
}
|
|
174104
174699
|
);
|
|
174700
|
+
server.registerTool(
|
|
174701
|
+
"memorix_continuity",
|
|
174702
|
+
{
|
|
174703
|
+
title: "Task Continuity Ledger",
|
|
174704
|
+
description: "Maintain a bounded, append-only continuity ledger for a coding task. Use start for requirements, record for decisions/verification/risks, show or list to inspect, and close for the final outcome. Pass the returned taskId to memorix_project_context so the current brief includes this ledger.",
|
|
174705
|
+
inputSchema: {
|
|
174706
|
+
action: z627.enum(["start", "record", "show", "list", "close"]).describe("Continuity operation"),
|
|
174707
|
+
taskId: z627.string().max(120).optional().describe("Continuity task id"),
|
|
174708
|
+
task: z627.string().max(1e3).optional().describe("Task description for start"),
|
|
174709
|
+
requirements: z627.array(z627.string().max(2e3)).max(8).optional().describe("Requirements for start"),
|
|
174710
|
+
kind: z627.enum(["requirement", "decision", "verification", "risk"]).optional().describe("Entry kind for record"),
|
|
174711
|
+
content: z627.string().max(2e3).optional().describe("Requirement, decision, verification, risk, or outcome text"),
|
|
174712
|
+
verificationStatus: z627.enum(["pending", "passed", "failed", "skipped"]).optional(),
|
|
174713
|
+
verificationId: z627.string().max(120).optional().describe("Stable verification obligation id; reuse it to move pending to passed/failed"),
|
|
174714
|
+
idempotencyKey: z627.string().max(200).optional().describe("Stable retry key; repeating the same operation returns the original event"),
|
|
174715
|
+
status: z627.enum(["completed", "blocked", "abandoned"]).optional().describe("Outcome status for close"),
|
|
174716
|
+
sourceRef: z627.string().max(500).optional().describe("Evidence or source reference"),
|
|
174717
|
+
evidenceRefs: z627.array(z627.string().max(500)).max(8).optional(),
|
|
174718
|
+
actor: z627.string().max(200).optional(),
|
|
174719
|
+
limit: z627.number().int().positive().max(100).optional().default(20)
|
|
174720
|
+
}
|
|
174721
|
+
},
|
|
174722
|
+
async ({ action, taskId, task, requirements, kind, content, verificationStatus, verificationId, idempotencyKey, status, sourceRef, evidenceRefs: evidenceRefs2, actor, limit: limit2 }) => {
|
|
174723
|
+
const unresolved = requireResolvedProject("manage task continuity for the current project");
|
|
174724
|
+
if (unresolved) return unresolved;
|
|
174725
|
+
const { TaskContinuityStore: TaskContinuityStore2 } = await Promise.resolve().then(() => (init_task_continuity(), task_continuity_exports));
|
|
174726
|
+
const continuity = new TaskContinuityStore2();
|
|
174727
|
+
await continuity.init(projectDir2);
|
|
174728
|
+
const effectiveActor = actor ?? currentAgentId;
|
|
174729
|
+
try {
|
|
174730
|
+
if (action === "start") {
|
|
174731
|
+
if (!task?.trim()) return { content: [{ type: "text", text: "task is required for continuity start." }], isError: true };
|
|
174732
|
+
const result2 = continuity.start({
|
|
174733
|
+
projectId: project.id,
|
|
174734
|
+
task,
|
|
174735
|
+
...taskId ? { taskId } : {},
|
|
174736
|
+
requirements,
|
|
174737
|
+
...effectiveActor ? { actor: effectiveActor } : {},
|
|
174738
|
+
...idempotencyKey ? { idempotencyKey } : {}
|
|
174739
|
+
});
|
|
174740
|
+
return { content: [{ type: "text", text: JSON.stringify({ projectId: project.id, ...result2 }, null, 2) }] };
|
|
174741
|
+
}
|
|
174742
|
+
if (action === "list") {
|
|
174743
|
+
return { content: [{ type: "text", text: JSON.stringify({ projectId: project.id, ledgers: continuity.list(project.id, limit2) }, null, 2) }] };
|
|
174744
|
+
}
|
|
174745
|
+
if (!taskId?.trim()) return { content: [{ type: "text", text: "taskId is required for this continuity action." }], isError: true };
|
|
174746
|
+
if (action === "show") {
|
|
174747
|
+
const ledger = continuity.get(project.id, taskId);
|
|
174748
|
+
if (!ledger) return { content: [{ type: "text", text: "Task continuity ledger not found." }], isError: true };
|
|
174749
|
+
return { content: [{ type: "text", text: JSON.stringify({ projectId: project.id, ledger }, null, 2) }] };
|
|
174750
|
+
}
|
|
174751
|
+
if (action === "record") {
|
|
174752
|
+
if (!kind || !content?.trim()) {
|
|
174753
|
+
return { content: [{ type: "text", text: "record requires kind and content." }], isError: true };
|
|
174754
|
+
}
|
|
174755
|
+
const result2 = continuity.record({
|
|
174756
|
+
projectId: project.id,
|
|
174757
|
+
taskId,
|
|
174758
|
+
kind,
|
|
174759
|
+
content,
|
|
174760
|
+
...verificationStatus ? { verificationStatus } : {},
|
|
174761
|
+
...sourceRef ? { sourceRef } : {},
|
|
174762
|
+
...evidenceRefs2 ? { evidenceRefs: evidenceRefs2 } : {},
|
|
174763
|
+
...effectiveActor ? { actor: effectiveActor } : {},
|
|
174764
|
+
...verificationId ? { verificationId } : {},
|
|
174765
|
+
...idempotencyKey ? { idempotencyKey } : {}
|
|
174766
|
+
});
|
|
174767
|
+
return { content: [{ type: "text", text: JSON.stringify({ projectId: project.id, ...result2 }, null, 2) }] };
|
|
174768
|
+
}
|
|
174769
|
+
if (!status || !content?.trim()) {
|
|
174770
|
+
return { content: [{ type: "text", text: "close requires status and content." }], isError: true };
|
|
174771
|
+
}
|
|
174772
|
+
const result = continuity.close({
|
|
174773
|
+
projectId: project.id,
|
|
174774
|
+
taskId,
|
|
174775
|
+
status,
|
|
174776
|
+
content,
|
|
174777
|
+
...sourceRef ? { sourceRef } : {},
|
|
174778
|
+
...evidenceRefs2 ? { evidenceRefs: evidenceRefs2 } : {},
|
|
174779
|
+
...effectiveActor ? { actor: effectiveActor } : {},
|
|
174780
|
+
...idempotencyKey ? { idempotencyKey } : {}
|
|
174781
|
+
});
|
|
174782
|
+
return { content: [{ type: "text", text: JSON.stringify({ projectId: project.id, ...result }, null, 2) }] };
|
|
174783
|
+
} catch (error) {
|
|
174784
|
+
return { content: [{ type: "text", text: error instanceof Error ? error.message : String(error) }], isError: true };
|
|
174785
|
+
}
|
|
174786
|
+
}
|
|
174787
|
+
);
|
|
174105
174788
|
if (teamFeaturesEnabled) {
|
|
174106
174789
|
const { initTeamStore: initTeamStore2 } = await Promise.resolve().then(() => (init_team_store(), team_store_exports));
|
|
174107
174790
|
initTeamStoreForProject = initTeamStore2;
|
|
@@ -175129,7 +175812,9 @@ fi
|
|
|
175129
175812
|
graphManager,
|
|
175130
175813
|
projectId: project.id,
|
|
175131
175814
|
deferredInit,
|
|
175815
|
+
activateProjectRuntime,
|
|
175132
175816
|
switchProject,
|
|
175817
|
+
getProjectDataDir: () => projectDir2,
|
|
175133
175818
|
isExplicitlyBound: () => projectBinding.isExplicit(),
|
|
175134
175819
|
getRequestContext,
|
|
175135
175820
|
handleTransportClose
|
|
@@ -175480,7 +176165,10 @@ var init_mcp_root_path = __esm({
|
|
|
175480
176165
|
// src/server/modern-mcp-bridge.ts
|
|
175481
176166
|
var modern_mcp_bridge_exports = {};
|
|
175482
176167
|
__export(modern_mcp_bridge_exports, {
|
|
175483
|
-
|
|
176168
|
+
ModernMcpRuntimePool: () => ModernMcpRuntimePool,
|
|
176169
|
+
createModernMcpBridge: () => createModernMcpBridge,
|
|
176170
|
+
createModernMcpRuntime: () => createModernMcpRuntime,
|
|
176171
|
+
withBusinessRuntimeQueue: () => withBusinessRuntimeQueue
|
|
175484
176172
|
});
|
|
175485
176173
|
import {
|
|
175486
176174
|
fromJsonSchema,
|
|
@@ -175488,7 +176176,12 @@ import {
|
|
|
175488
176176
|
} from "@modelcontextprotocol/server";
|
|
175489
176177
|
import { Client as LegacyClient } from "@modelcontextprotocol/sdk/client/index.js";
|
|
175490
176178
|
import { InMemoryTransport as LegacyInMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
|
|
175491
|
-
|
|
176179
|
+
function withBusinessRuntimeQueue(work) {
|
|
176180
|
+
const result = businessRuntimeQueue.then(work);
|
|
176181
|
+
businessRuntimeQueue = result.catch(() => void 0);
|
|
176182
|
+
return result;
|
|
176183
|
+
}
|
|
176184
|
+
async function createModernMcpRuntime(options) {
|
|
175492
176185
|
const { createMemorixServer: createMemorixServer2 } = await Promise.resolve().then(() => (init_server2(), server_exports2));
|
|
175493
176186
|
const legacy = await createMemorixServer2(
|
|
175494
176187
|
options.projectRoot,
|
|
@@ -175509,46 +176202,135 @@ async function createModernMcpBridge(options) {
|
|
|
175509
176202
|
await legacy.server.connect(serverTransport);
|
|
175510
176203
|
await legacyClient.connect(clientTransport);
|
|
175511
176204
|
const listed = await legacyClient.listTools();
|
|
175512
|
-
const
|
|
175513
|
-
|
|
175514
|
-
|
|
175515
|
-
|
|
175516
|
-
|
|
175517
|
-
...tool.title ? { title: tool.title } : {},
|
|
175518
|
-
...tool.description ? { description: tool.description } : {},
|
|
175519
|
-
inputSchema: fromJsonSchema(tool.inputSchema)
|
|
175520
|
-
},
|
|
175521
|
-
async (args) => await legacyClient.callTool({
|
|
175522
|
-
name: tool.name,
|
|
175523
|
-
arguments: args
|
|
175524
|
-
})
|
|
175525
|
-
);
|
|
175526
|
-
}
|
|
175527
|
-
const bridge = modern;
|
|
175528
|
-
bridge.memorix = {
|
|
176205
|
+
const callTool = (name, args) => withBusinessRuntimeQueue(async () => {
|
|
176206
|
+
await legacy.activateProjectRuntime();
|
|
176207
|
+
return await legacyClient.callTool({ name, arguments: args });
|
|
176208
|
+
});
|
|
176209
|
+
const lifecycle = {
|
|
175529
176210
|
projectId: legacy.projectId,
|
|
175530
176211
|
deferredInit: legacy.deferredInit,
|
|
176212
|
+
activateProjectRuntime: legacy.activateProjectRuntime,
|
|
175531
176213
|
switchProject: legacy.switchProject,
|
|
176214
|
+
getProjectDataDir: legacy.getProjectDataDir,
|
|
175532
176215
|
isExplicitlyBound: legacy.isExplicitlyBound,
|
|
175533
176216
|
handleTransportClose: legacy.handleTransportClose
|
|
175534
176217
|
};
|
|
175535
176218
|
let closed = false;
|
|
175536
|
-
|
|
175537
|
-
|
|
176219
|
+
return {
|
|
176220
|
+
projectId: legacy.projectId,
|
|
176221
|
+
getProjectDataDir: legacy.getProjectDataDir,
|
|
176222
|
+
createBridge: () => {
|
|
176223
|
+
const requestServer = new ModernMcpServer(getMcpServerInfo());
|
|
176224
|
+
for (const tool of listed.tools) {
|
|
176225
|
+
requestServer.registerTool(
|
|
176226
|
+
tool.name,
|
|
176227
|
+
{
|
|
176228
|
+
...tool.title ? { title: tool.title } : {},
|
|
176229
|
+
...tool.description ? { description: tool.description } : {},
|
|
176230
|
+
inputSchema: fromJsonSchema(tool.inputSchema)
|
|
176231
|
+
},
|
|
176232
|
+
async (args) => await callTool(tool.name, args)
|
|
176233
|
+
);
|
|
176234
|
+
}
|
|
176235
|
+
requestServer.memorix = lifecycle;
|
|
176236
|
+
return requestServer;
|
|
176237
|
+
},
|
|
176238
|
+
close: async () => {
|
|
176239
|
+
if (closed) return;
|
|
176240
|
+
closed = true;
|
|
176241
|
+
await legacyClient.close().catch(() => void 0);
|
|
176242
|
+
await legacy.server.close().catch(() => void 0);
|
|
176243
|
+
legacy.handleTransportClose();
|
|
176244
|
+
}
|
|
176245
|
+
};
|
|
176246
|
+
}
|
|
176247
|
+
async function createModernMcpBridge(options) {
|
|
176248
|
+
const runtime = await createModernMcpRuntime(options);
|
|
176249
|
+
const bridge = runtime.createBridge();
|
|
176250
|
+
const close = bridge.close.bind(bridge);
|
|
176251
|
+
let closed = false;
|
|
176252
|
+
bridge.close = async () => {
|
|
175538
176253
|
if (closed) return;
|
|
175539
176254
|
closed = true;
|
|
175540
|
-
await
|
|
175541
|
-
await
|
|
175542
|
-
await legacy.server.close().catch(() => void 0);
|
|
175543
|
-
legacy.handleTransportClose();
|
|
176255
|
+
await close();
|
|
176256
|
+
await runtime.close();
|
|
175544
176257
|
};
|
|
175545
176258
|
return bridge;
|
|
175546
176259
|
}
|
|
176260
|
+
var businessRuntimeQueue, ModernMcpRuntimePool;
|
|
175547
176261
|
var init_modern_mcp_bridge = __esm({
|
|
175548
176262
|
"src/server/modern-mcp-bridge.ts"() {
|
|
175549
176263
|
"use strict";
|
|
175550
176264
|
init_esm_shims();
|
|
175551
176265
|
init_mcp_discovery();
|
|
176266
|
+
businessRuntimeQueue = Promise.resolve();
|
|
176267
|
+
ModernMcpRuntimePool = class {
|
|
176268
|
+
constructor(maxEntries = 32) {
|
|
176269
|
+
this.maxEntries = maxEntries;
|
|
176270
|
+
}
|
|
176271
|
+
maxEntries;
|
|
176272
|
+
entries = /* @__PURE__ */ new Map();
|
|
176273
|
+
pending = /* @__PURE__ */ new Map();
|
|
176274
|
+
async createBridge(key, create2) {
|
|
176275
|
+
let entry = this.entries.get(key);
|
|
176276
|
+
if (!entry) {
|
|
176277
|
+
let pending = this.pending.get(key);
|
|
176278
|
+
if (!pending) {
|
|
176279
|
+
pending = create2().then((runtime) => {
|
|
176280
|
+
const created = { runtime, refs: 0, lastUsedAt: Date.now() };
|
|
176281
|
+
this.entries.set(key, created);
|
|
176282
|
+
return created;
|
|
176283
|
+
});
|
|
176284
|
+
this.pending.set(key, pending);
|
|
176285
|
+
}
|
|
176286
|
+
try {
|
|
176287
|
+
entry = await pending;
|
|
176288
|
+
} finally {
|
|
176289
|
+
this.pending.delete(key);
|
|
176290
|
+
}
|
|
176291
|
+
}
|
|
176292
|
+
entry.refs++;
|
|
176293
|
+
entry.lastUsedAt = Date.now();
|
|
176294
|
+
const bridge = entry.runtime.createBridge();
|
|
176295
|
+
const close = bridge.close.bind(bridge);
|
|
176296
|
+
let released = false;
|
|
176297
|
+
bridge.close = async () => {
|
|
176298
|
+
try {
|
|
176299
|
+
await close();
|
|
176300
|
+
} finally {
|
|
176301
|
+
if (!released) {
|
|
176302
|
+
released = true;
|
|
176303
|
+
entry.refs = Math.max(0, entry.refs - 1);
|
|
176304
|
+
entry.lastUsedAt = Date.now();
|
|
176305
|
+
}
|
|
176306
|
+
}
|
|
176307
|
+
};
|
|
176308
|
+
return bridge;
|
|
176309
|
+
}
|
|
176310
|
+
async evictIdle() {
|
|
176311
|
+
let closed = 0;
|
|
176312
|
+
const idle = [...this.entries.entries()].filter(([, entry]) => entry.refs === 0).sort(([, left], [, right]) => left.lastUsedAt - right.lastUsedAt);
|
|
176313
|
+
for (const [key, entry] of idle) {
|
|
176314
|
+
if (this.entries.size <= this.maxEntries || entry.refs > 0) continue;
|
|
176315
|
+
this.entries.delete(key);
|
|
176316
|
+
await entry.runtime.close();
|
|
176317
|
+
closed++;
|
|
176318
|
+
}
|
|
176319
|
+
return closed;
|
|
176320
|
+
}
|
|
176321
|
+
async close() {
|
|
176322
|
+
const entries = [...this.entries.values()];
|
|
176323
|
+
this.entries.clear();
|
|
176324
|
+
await Promise.all(entries.map((entry) => entry.runtime.close().catch(() => void 0)));
|
|
176325
|
+
}
|
|
176326
|
+
stats() {
|
|
176327
|
+
return {
|
|
176328
|
+
entries: this.entries.size,
|
|
176329
|
+
activeRefs: [...this.entries.values()].reduce((sum, entry) => sum + entry.refs, 0),
|
|
176330
|
+
pending: this.pending.size
|
|
176331
|
+
};
|
|
176332
|
+
}
|
|
176333
|
+
};
|
|
175552
176334
|
}
|
|
175553
176335
|
});
|
|
175554
176336
|
|
|
@@ -175660,7 +176442,7 @@ var init_serve_shared = __esm({
|
|
|
175660
176442
|
|
|
175661
176443
|
// src/cli/version.ts
|
|
175662
176444
|
function getCliVersion() {
|
|
175663
|
-
return true ? "1.9.
|
|
176445
|
+
return true ? "1.9.7" : pkg.version;
|
|
175664
176446
|
}
|
|
175665
176447
|
var init_version3 = __esm({
|
|
175666
176448
|
"src/cli/version.ts"() {
|