memorix 1.9.5 → 1.9.6
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 +42 -0
- package/README.md +6 -1
- package/README.zh-CN.md +6 -1
- package/dist/cli/index.js +1647 -264
- package/dist/index.d.ts +12 -7
- package/dist/index.js +952 -182
- package/dist/maintenance-runner.js +243 -103
- package/dist/media-audio-runner.js +243 -103
- package/dist/media-video-runner.js +243 -103
- package/dist/memcode-runtime/CHANGELOG.md +42 -0
- package/dist/sdk.js +871 -157
- package/dist/vector-backfill-runner.js +243 -103
- 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/sqlite-db.ts +144 -4
- package/src/team/team-store.ts +62 -27
package/dist/cli/index.js
CHANGED
|
@@ -3232,7 +3232,7 @@ ${import_picocolors.default.gray(m3)} ${s4}
|
|
|
3232
3232
|
|
|
3233
3233
|
// src/cli/version.ts
|
|
3234
3234
|
function getCliVersion() {
|
|
3235
|
-
return true ? "1.9.
|
|
3235
|
+
return true ? "1.9.6" : pkg.version;
|
|
3236
3236
|
}
|
|
3237
3237
|
var init_version = __esm({
|
|
3238
3238
|
"src/cli/version.ts"() {
|
|
@@ -9475,9 +9475,12 @@ END;
|
|
|
9475
9475
|
// src/store/sqlite-db.ts
|
|
9476
9476
|
var sqlite_db_exports = {};
|
|
9477
9477
|
__export(sqlite_db_exports, {
|
|
9478
|
+
acquireDatabase: () => acquireDatabase,
|
|
9478
9479
|
closeAllDatabases: () => closeAllDatabases,
|
|
9479
9480
|
closeDatabase: () => closeDatabase,
|
|
9481
|
+
evictIdleDatabases: () => evictIdleDatabases,
|
|
9480
9482
|
getDatabase: () => getDatabase,
|
|
9483
|
+
getDatabaseStats: () => getDatabaseStats,
|
|
9481
9484
|
isSqliteAvailable: () => isSqliteAvailable,
|
|
9482
9485
|
loadBetterSqlite3: () => loadBetterSqlite3
|
|
9483
9486
|
});
|
|
@@ -9515,11 +9518,21 @@ function applySchemaMigrations(db2) {
|
|
|
9515
9518
|
apply();
|
|
9516
9519
|
}
|
|
9517
9520
|
}
|
|
9521
|
+
function normalizeDataDir(dataDir) {
|
|
9522
|
+
return path3.resolve(dataDir);
|
|
9523
|
+
}
|
|
9524
|
+
function touchDatabase(normalized, db2) {
|
|
9525
|
+
_dbCache.delete(normalized);
|
|
9526
|
+
_dbCache.set(normalized, db2);
|
|
9527
|
+
}
|
|
9518
9528
|
function getDatabase(dataDir) {
|
|
9519
|
-
const normalized =
|
|
9529
|
+
const normalized = normalizeDataDir(dataDir);
|
|
9520
9530
|
assertNotHomeDataDir(normalized);
|
|
9521
9531
|
const existing = _dbCache.get(normalized);
|
|
9522
|
-
if (existing)
|
|
9532
|
+
if (existing) {
|
|
9533
|
+
touchDatabase(normalized, existing);
|
|
9534
|
+
return existing;
|
|
9535
|
+
}
|
|
9523
9536
|
loadBetterSqlite3();
|
|
9524
9537
|
fs.mkdirSync(dataDir, { recursive: true });
|
|
9525
9538
|
const dbPath = path3.join(dataDir, "memorix.db");
|
|
@@ -9549,6 +9562,8 @@ function getDatabase(dataDir) {
|
|
|
9549
9562
|
db2.exec(CREATE_MAINTENANCE_JOBS_TABLE);
|
|
9550
9563
|
db2.exec(CREATE_MAINTENANCE_TARGETS_TABLE);
|
|
9551
9564
|
db2.exec(CREATE_COMPACTION_CHECKPOINTS_TABLE);
|
|
9565
|
+
db2.exec(CREATE_TASK_CONTINUITY_EVENTS_TABLE);
|
|
9566
|
+
db2.exec(CREATE_AGENT_EFFECTS_TABLE);
|
|
9552
9567
|
try {
|
|
9553
9568
|
db2.exec(`ALTER TABLE mini_skills ADD COLUMN sourceSnapshot TEXT NOT NULL DEFAULT ''`);
|
|
9554
9569
|
} catch {
|
|
@@ -9587,7 +9602,7 @@ function getDatabase(dataDir) {
|
|
|
9587
9602
|
db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('storage_generation', '0')`).run();
|
|
9588
9603
|
db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('next_id', '1')`).run();
|
|
9589
9604
|
db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('mini_skills_generation', '0')`).run();
|
|
9590
|
-
|
|
9605
|
+
touchDatabase(normalized, db2);
|
|
9591
9606
|
return db2;
|
|
9592
9607
|
} catch (error40) {
|
|
9593
9608
|
try {
|
|
@@ -9597,8 +9612,46 @@ function getDatabase(dataDir) {
|
|
|
9597
9612
|
throw error40;
|
|
9598
9613
|
}
|
|
9599
9614
|
}
|
|
9615
|
+
function acquireDatabase(dataDir) {
|
|
9616
|
+
const normalized = normalizeDataDir(dataDir);
|
|
9617
|
+
const db2 = getDatabase(normalized);
|
|
9618
|
+
_dbLeases.set(normalized, (_dbLeases.get(normalized) ?? 0) + 1);
|
|
9619
|
+
let released = false;
|
|
9620
|
+
return {
|
|
9621
|
+
dataDir: normalized,
|
|
9622
|
+
db: db2,
|
|
9623
|
+
release: () => {
|
|
9624
|
+
if (released) return;
|
|
9625
|
+
released = true;
|
|
9626
|
+
const count3 = (_dbLeases.get(normalized) ?? 0) - 1;
|
|
9627
|
+
if (count3 > 0) _dbLeases.set(normalized, count3);
|
|
9628
|
+
else _dbLeases.delete(normalized);
|
|
9629
|
+
}
|
|
9630
|
+
};
|
|
9631
|
+
}
|
|
9632
|
+
function getDatabaseStats() {
|
|
9633
|
+
let leased = 0;
|
|
9634
|
+
for (const count3 of _dbLeases.values()) leased += count3;
|
|
9635
|
+
return { cached: _dbCache.size, leased, leasedDataDirs: _dbLeases.size };
|
|
9636
|
+
}
|
|
9637
|
+
function evictIdleDatabases(maxCached) {
|
|
9638
|
+
const target = Math.max(0, Math.floor(maxCached));
|
|
9639
|
+
let evicted = 0;
|
|
9640
|
+
for (const [normalized, db2] of [..._dbCache]) {
|
|
9641
|
+
if (_dbCache.size <= target) break;
|
|
9642
|
+
if ((_dbLeases.get(normalized) ?? 0) > 0) continue;
|
|
9643
|
+
try {
|
|
9644
|
+
db2.close();
|
|
9645
|
+
} catch {
|
|
9646
|
+
}
|
|
9647
|
+
_dbCache.delete(normalized);
|
|
9648
|
+
evicted++;
|
|
9649
|
+
}
|
|
9650
|
+
return evicted;
|
|
9651
|
+
}
|
|
9600
9652
|
function closeDatabase(dataDir) {
|
|
9601
|
-
const normalized =
|
|
9653
|
+
const normalized = normalizeDataDir(dataDir);
|
|
9654
|
+
if ((_dbLeases.get(normalized) ?? 0) > 0) return;
|
|
9602
9655
|
const db2 = _dbCache.get(normalized);
|
|
9603
9656
|
if (db2) {
|
|
9604
9657
|
try {
|
|
@@ -9616,6 +9669,7 @@ function closeAllDatabases() {
|
|
|
9616
9669
|
}
|
|
9617
9670
|
_dbCache.delete(key);
|
|
9618
9671
|
}
|
|
9672
|
+
_dbLeases.clear();
|
|
9619
9673
|
}
|
|
9620
9674
|
function isSqliteAvailable() {
|
|
9621
9675
|
try {
|
|
@@ -9625,7 +9679,7 @@ function isSqliteAvailable() {
|
|
|
9625
9679
|
return false;
|
|
9626
9680
|
}
|
|
9627
9681
|
}
|
|
9628
|
-
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;
|
|
9682
|
+
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;
|
|
9629
9683
|
var init_sqlite_db = __esm({
|
|
9630
9684
|
"src/store/sqlite-db.ts"() {
|
|
9631
9685
|
"use strict";
|
|
@@ -10342,6 +10396,43 @@ CREATE TABLE IF NOT EXISTS memory_feedback_events (
|
|
|
10342
10396
|
delta REAL NOT NULL DEFAULT 0,
|
|
10343
10397
|
observed_at TEXT NOT NULL
|
|
10344
10398
|
);
|
|
10399
|
+
`;
|
|
10400
|
+
CREATE_TASK_CONTINUITY_EVENTS_TABLE = `
|
|
10401
|
+
CREATE TABLE IF NOT EXISTS task_continuity_events (
|
|
10402
|
+
id TEXT PRIMARY KEY,
|
|
10403
|
+
project_id TEXT NOT NULL,
|
|
10404
|
+
task_id TEXT NOT NULL,
|
|
10405
|
+
task TEXT NOT NULL,
|
|
10406
|
+
kind TEXT NOT NULL,
|
|
10407
|
+
content TEXT NOT NULL,
|
|
10408
|
+
item_status TEXT,
|
|
10409
|
+
source_ref TEXT,
|
|
10410
|
+
evidence_json TEXT NOT NULL DEFAULT '[]',
|
|
10411
|
+
actor TEXT,
|
|
10412
|
+
created_at TEXT NOT NULL,
|
|
10413
|
+
event_key TEXT,
|
|
10414
|
+
item_key TEXT,
|
|
10415
|
+
supersedes_id TEXT
|
|
10416
|
+
);
|
|
10417
|
+
`;
|
|
10418
|
+
CREATE_AGENT_EFFECTS_TABLE = `
|
|
10419
|
+
CREATE TABLE IF NOT EXISTS agent_effects (
|
|
10420
|
+
id TEXT PRIMARY KEY,
|
|
10421
|
+
pipeline_id TEXT NOT NULL,
|
|
10422
|
+
task_id TEXT NOT NULL,
|
|
10423
|
+
attempt INTEGER NOT NULL,
|
|
10424
|
+
effect_key TEXT NOT NULL,
|
|
10425
|
+
tool TEXT NOT NULL,
|
|
10426
|
+
risk_tier TEXT NOT NULL,
|
|
10427
|
+
replay_policy TEXT NOT NULL,
|
|
10428
|
+
status TEXT NOT NULL,
|
|
10429
|
+
call_id TEXT,
|
|
10430
|
+
idempotency_key TEXT NOT NULL,
|
|
10431
|
+
input_fingerprint TEXT,
|
|
10432
|
+
detail TEXT,
|
|
10433
|
+
started_at INTEGER NOT NULL,
|
|
10434
|
+
finished_at INTEGER
|
|
10435
|
+
);
|
|
10345
10436
|
`;
|
|
10346
10437
|
CREATE_MCP_BINDINGS_TABLE = `
|
|
10347
10438
|
CREATE TABLE IF NOT EXISTS mcp_bindings (
|
|
@@ -10420,7 +10511,18 @@ CREATE INDEX IF NOT EXISTS idx_evidence_cards_candidate ON evidence_cards(projec
|
|
|
10420
10511
|
CREATE INDEX IF NOT EXISTS idx_evidence_card_events_card ON evidence_card_events(card_id, created_at);
|
|
10421
10512
|
CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC);
|
|
10422
10513
|
CREATE INDEX IF NOT EXISTS idx_memory_feedback_events_candidate ON memory_feedback_events(project_id, candidate_kind, candidate_id, observed_at DESC);
|
|
10514
|
+
CREATE INDEX IF NOT EXISTS idx_task_continuity_project_task ON task_continuity_events(project_id, task_id, created_at ASC);
|
|
10515
|
+
CREATE INDEX IF NOT EXISTS idx_task_continuity_project_recent ON task_continuity_events(project_id, created_at DESC);
|
|
10516
|
+
CREATE INDEX IF NOT EXISTS idx_task_continuity_item ON task_continuity_events(project_id, task_id, kind, item_key, created_at DESC);
|
|
10517
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_task_continuity_event_key
|
|
10518
|
+
ON task_continuity_events(project_id, task_id, event_key)
|
|
10519
|
+
WHERE event_key IS NOT NULL;
|
|
10520
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_agent_effect_identity
|
|
10521
|
+
ON agent_effects(pipeline_id, task_id, attempt, effect_key);
|
|
10522
|
+
CREATE INDEX IF NOT EXISTS idx_agent_effect_pipeline ON agent_effects(pipeline_id, started_at ASC);
|
|
10423
10523
|
CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC);
|
|
10524
|
+
CREATE INDEX IF NOT EXISTS idx_mcp_bindings_root ON mcp_bindings(project_root, last_used_at DESC);
|
|
10525
|
+
CREATE INDEX IF NOT EXISTS idx_mcp_bindings_expiry ON mcp_bindings(expires_at);
|
|
10424
10526
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
10425
10527
|
ON maintenance_jobs(project_id, kind, dedupe_key)
|
|
10426
10528
|
WHERE status IN ('pending', 'running', 'retry');
|
|
@@ -10591,6 +10693,8 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
|
10591
10693
|
db2.exec("CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC)");
|
|
10592
10694
|
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)");
|
|
10593
10695
|
db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC)");
|
|
10696
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_root ON mcp_bindings(project_root, last_used_at DESC)");
|
|
10697
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_expiry ON mcp_bindings(expires_at)");
|
|
10594
10698
|
}
|
|
10595
10699
|
},
|
|
10596
10700
|
{
|
|
@@ -10601,9 +10705,22 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
|
10601
10705
|
addColumnIfMissing(db2, "code_symbols", "source", "source TEXT");
|
|
10602
10706
|
addColumnIfMissing(db2, "code_edges", "source", "source TEXT");
|
|
10603
10707
|
}
|
|
10708
|
+
},
|
|
10709
|
+
{
|
|
10710
|
+
id: "1.9-continuity-v2",
|
|
10711
|
+
apply: (db2) => {
|
|
10712
|
+
addColumnIfMissing(db2, "task_continuity_events", "event_key", "event_key TEXT");
|
|
10713
|
+
addColumnIfMissing(db2, "task_continuity_events", "item_key", "item_key TEXT");
|
|
10714
|
+
addColumnIfMissing(db2, "task_continuity_events", "supersedes_id", "supersedes_id TEXT");
|
|
10715
|
+
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)");
|
|
10716
|
+
db2.exec(`CREATE UNIQUE INDEX IF NOT EXISTS idx_task_continuity_event_key
|
|
10717
|
+
ON task_continuity_events(project_id, task_id, event_key)
|
|
10718
|
+
WHERE event_key IS NOT NULL`);
|
|
10719
|
+
}
|
|
10604
10720
|
}
|
|
10605
10721
|
];
|
|
10606
10722
|
_dbCache = /* @__PURE__ */ new Map();
|
|
10723
|
+
_dbLeases = /* @__PURE__ */ new Map();
|
|
10607
10724
|
}
|
|
10608
10725
|
});
|
|
10609
10726
|
|
|
@@ -21094,18 +21211,23 @@ __export(yaml_loader_exports, {
|
|
|
21094
21211
|
});
|
|
21095
21212
|
import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
|
|
21096
21213
|
import { homedir } from "os";
|
|
21214
|
+
function cacheKey(homeDir, projectRoot) {
|
|
21215
|
+
return `${homeDir}\0${projectRoot ?? ""}`;
|
|
21216
|
+
}
|
|
21097
21217
|
function initProjectRoot(root) {
|
|
21098
21218
|
globalProjectRoot = root;
|
|
21099
|
-
configCache.delete(root);
|
|
21219
|
+
configCache.delete(cacheKey(homedir(), root));
|
|
21100
21220
|
}
|
|
21101
21221
|
function clearProjectRoot() {
|
|
21102
21222
|
globalProjectRoot = null;
|
|
21103
21223
|
}
|
|
21104
|
-
function loadYamlConfig(projectRoot) {
|
|
21224
|
+
function loadYamlConfig(projectRoot, options = {}) {
|
|
21225
|
+
const homeDir = options.homeDir ?? homedir();
|
|
21105
21226
|
const resolvedRoot = projectRoot === null ? null : projectRoot ?? globalProjectRoot ?? null;
|
|
21106
|
-
const
|
|
21227
|
+
const key = cacheKey(homeDir, resolvedRoot);
|
|
21228
|
+
const cached2 = configCache.get(key);
|
|
21107
21229
|
if (cached2) return cached2;
|
|
21108
|
-
const userYaml = getGlobalYamlPath(
|
|
21230
|
+
const userYaml = getGlobalYamlPath(homeDir);
|
|
21109
21231
|
const projectYaml = resolvedRoot ? getProjectYamlPath(resolvedRoot) : null;
|
|
21110
21232
|
let userConfig = {};
|
|
21111
21233
|
let projectConfig = {};
|
|
@@ -21137,12 +21259,12 @@ function loadYamlConfig(projectRoot) {
|
|
|
21137
21259
|
server: { ...userConfig.server, ...projectConfig.server },
|
|
21138
21260
|
team: { ...userConfig.team, ...projectConfig.team }
|
|
21139
21261
|
};
|
|
21140
|
-
configCache.set(
|
|
21262
|
+
configCache.set(key, merged);
|
|
21141
21263
|
return merged;
|
|
21142
21264
|
}
|
|
21143
|
-
function resetYamlConfigCache(projectRoot) {
|
|
21265
|
+
function resetYamlConfigCache(projectRoot, homeDir = homedir()) {
|
|
21144
21266
|
if (projectRoot !== void 0) {
|
|
21145
|
-
configCache.delete(projectRoot ?? null);
|
|
21267
|
+
configCache.delete(cacheKey(homeDir, projectRoot ?? null));
|
|
21146
21268
|
} else {
|
|
21147
21269
|
configCache.clear();
|
|
21148
21270
|
}
|
|
@@ -21353,9 +21475,9 @@ var init_detector = __esm({
|
|
|
21353
21475
|
// src/config/legacy-loader.ts
|
|
21354
21476
|
import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
|
|
21355
21477
|
import { homedir as homedir2 } from "os";
|
|
21356
|
-
function loadFileConfig() {
|
|
21478
|
+
function loadFileConfig(homeDir = homedir2()) {
|
|
21357
21479
|
if (cachedConfig !== null) return cachedConfig;
|
|
21358
|
-
const configPath = getLegacyConfigJsonPath(
|
|
21480
|
+
const configPath = getLegacyConfigJsonPath(homeDir);
|
|
21359
21481
|
try {
|
|
21360
21482
|
if (existsSync6(configPath)) {
|
|
21361
21483
|
cachedConfig = JSON.parse(readFileSync5(configPath, "utf-8"));
|
|
@@ -21385,15 +21507,15 @@ import { homedir as homedir3 } from "os";
|
|
|
21385
21507
|
function loadTomlConfig(options = {}) {
|
|
21386
21508
|
const homeDir = options.homeDir ?? homedir3();
|
|
21387
21509
|
const projectRoot = options.projectRoot ?? null;
|
|
21388
|
-
const
|
|
21389
|
-
const cached2 = configCache2.get(
|
|
21510
|
+
const cacheKey4 = `${homeDir}\0${projectRoot ?? ""}`;
|
|
21511
|
+
const cached2 = configCache2.get(cacheKey4);
|
|
21390
21512
|
if (cached2) return cached2;
|
|
21391
21513
|
const userToml = getGlobalConfigTomlPath(homeDir);
|
|
21392
21514
|
const projectToml = projectRoot ? getProjectConfigTomlPath(projectRoot) : null;
|
|
21393
21515
|
const userConfig = existsSync7(userToml) ? parseTomlConfig(readFileSync6(userToml, "utf8"), userToml) : {};
|
|
21394
21516
|
const projectConfig = projectToml && existsSync7(projectToml) ? parseTomlConfig(readFileSync6(projectToml, "utf8"), projectToml) : {};
|
|
21395
21517
|
const merged = mergeTomlConfig(userConfig, projectConfig);
|
|
21396
|
-
configCache2.set(
|
|
21518
|
+
configCache2.set(cacheKey4, merged);
|
|
21397
21519
|
return merged;
|
|
21398
21520
|
}
|
|
21399
21521
|
function mergeTomlConfig(base, override) {
|
|
@@ -21989,8 +22111,8 @@ function getResolvedConfig(options = {}) {
|
|
|
21989
22111
|
const projectRoot = options.projectRoot === void 0 ? detectProject()?.rootPath ?? null : options.projectRoot;
|
|
21990
22112
|
loadDotenv(projectRoot === null ? void 0 : projectRoot ?? void 0, { userHomeDir: homeDir });
|
|
21991
22113
|
const toml = loadTomlConfig({ projectRoot: projectRoot ?? null, homeDir });
|
|
21992
|
-
const yaml = loadYamlConfig(projectRoot ?? null);
|
|
21993
|
-
const legacy = loadFileConfig();
|
|
22114
|
+
const yaml = loadYamlConfig(projectRoot ?? null, { homeDir });
|
|
22115
|
+
const legacy = loadFileConfig(homeDir);
|
|
21994
22116
|
const embeddingBaseUrl = first(process.env.MEMORIX_EMBEDDING_BASE_URL, toml.embedding?.base_url, yaml.embedding?.baseUrl, legacy.embeddingApi?.baseUrl);
|
|
21995
22117
|
const openRouterEmbeddingApiKey = isOpenRouterUrl(embeddingBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
|
|
21996
22118
|
const memoryLlmProvider = first(
|
|
@@ -22012,15 +22134,17 @@ function getResolvedConfig(options = {}) {
|
|
|
22012
22134
|
legacy.llm?.baseUrl
|
|
22013
22135
|
);
|
|
22014
22136
|
const openRouterMemoryLlmApiKey = isOpenRouterMemoryLane(memoryLlmProvider, memoryLlmBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
|
|
22137
|
+
const isAtlasCloud = memoryLlmProvider === "atlascloud";
|
|
22015
22138
|
const memoryLlmApiKey = first(
|
|
22016
22139
|
process.env.MEMORIX_LLM_API_KEY,
|
|
22017
22140
|
process.env.MEMORIX_API_KEY,
|
|
22018
22141
|
toml.memory?.llm?.api_key,
|
|
22019
22142
|
yaml.llm?.apiKey,
|
|
22020
22143
|
legacy.llm?.apiKey,
|
|
22021
|
-
|
|
22022
|
-
process.env.
|
|
22023
|
-
|
|
22144
|
+
// Never borrow another provider's credentials for the Atlas Cloud preset.
|
|
22145
|
+
isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : process.env.OPENAI_API_KEY,
|
|
22146
|
+
isAtlasCloud ? void 0 : process.env.ANTHROPIC_API_KEY,
|
|
22147
|
+
isAtlasCloud ? void 0 : openRouterMemoryLlmApiKey
|
|
22024
22148
|
);
|
|
22025
22149
|
const resolved = {
|
|
22026
22150
|
agent: {
|
|
@@ -22199,7 +22323,8 @@ function getEnvSourceNames() {
|
|
|
22199
22323
|
"MEMORIX_CODEGRAPH_EXTERNAL_CONTEXT",
|
|
22200
22324
|
"MEMORIX_CODEGRAPH_EXTERNAL_COMMAND",
|
|
22201
22325
|
"MEMORIX_CODEGRAPH_EXTERNAL_TIMEOUT_MS",
|
|
22202
|
-
"OPENROUTER_API_KEY"
|
|
22326
|
+
"OPENROUTER_API_KEY",
|
|
22327
|
+
"ATLASCLOUD_API_KEY"
|
|
22203
22328
|
].filter((name) => process.env[name]);
|
|
22204
22329
|
}
|
|
22205
22330
|
function isOpenRouterUrl(value) {
|
|
@@ -22418,12 +22543,45 @@ function textHash(text3) {
|
|
|
22418
22543
|
async function loadDiskCache() {
|
|
22419
22544
|
try {
|
|
22420
22545
|
const raw = await readFile(CACHE_FILE, "utf-8");
|
|
22546
|
+
if (Buffer.byteLength(raw, "utf8") > MAX_CACHE_FILE_BYTES) {
|
|
22547
|
+
console.error("[memorix] FastEmbed cache exceeds the disk load limit; starting with an empty cache");
|
|
22548
|
+
return;
|
|
22549
|
+
}
|
|
22421
22550
|
const entries = JSON.parse(raw);
|
|
22422
|
-
|
|
22423
|
-
|
|
22551
|
+
if (!Array.isArray(entries)) return;
|
|
22552
|
+
for (const entry of entries) {
|
|
22553
|
+
if (!Array.isArray(entry) || typeof entry[0] !== "string" || !isVector(entry[1])) continue;
|
|
22554
|
+
cacheSet(entry[0], entry[1], false);
|
|
22555
|
+
}
|
|
22556
|
+
console.error(`[memorix] Loaded ${cache.size} cached embeddings from disk`);
|
|
22424
22557
|
} catch {
|
|
22425
22558
|
}
|
|
22426
22559
|
}
|
|
22560
|
+
function isVector(value) {
|
|
22561
|
+
return Array.isArray(value) && value.every((entry) => typeof entry === "number");
|
|
22562
|
+
}
|
|
22563
|
+
function maxCachePayloadBytes() {
|
|
22564
|
+
const raw = Number.parseInt(process.env.MEMORIX_EMBEDDING_CACHE_MAX_BYTES ?? "", 10);
|
|
22565
|
+
return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_CACHE_PAYLOAD_BYTES;
|
|
22566
|
+
}
|
|
22567
|
+
function cacheSet(hash4, value, markDirty = true) {
|
|
22568
|
+
const incomingBytes = value.length * 8;
|
|
22569
|
+
if (incomingBytes > maxCachePayloadBytes()) return;
|
|
22570
|
+
const existing = cache.get(hash4);
|
|
22571
|
+
if (existing) cachePayloadBytes -= existing.length * 8;
|
|
22572
|
+
else {
|
|
22573
|
+
while (cache.size >= MAX_CACHE_SIZE || cachePayloadBytes + incomingBytes > maxCachePayloadBytes()) {
|
|
22574
|
+
const firstKey = cache.keys().next().value;
|
|
22575
|
+
if (firstKey === void 0) break;
|
|
22576
|
+
const old = cache.get(firstKey);
|
|
22577
|
+
cache.delete(firstKey);
|
|
22578
|
+
if (old) cachePayloadBytes -= old.length * 8;
|
|
22579
|
+
}
|
|
22580
|
+
}
|
|
22581
|
+
cache.set(hash4, value);
|
|
22582
|
+
cachePayloadBytes += incomingBytes;
|
|
22583
|
+
if (markDirty) diskCacheDirty = true;
|
|
22584
|
+
}
|
|
22427
22585
|
async function saveDiskCache() {
|
|
22428
22586
|
if (!diskCacheDirty) return;
|
|
22429
22587
|
try {
|
|
@@ -22434,7 +22592,7 @@ async function saveDiskCache() {
|
|
|
22434
22592
|
} catch {
|
|
22435
22593
|
}
|
|
22436
22594
|
}
|
|
22437
|
-
var CACHE_DIR, CACHE_FILE, cache, MAX_CACHE_SIZE, diskCacheDirty, FastEmbedProvider;
|
|
22595
|
+
var CACHE_DIR, CACHE_FILE, cache, MAX_CACHE_SIZE, DEFAULT_CACHE_PAYLOAD_BYTES, MAX_CACHE_FILE_BYTES, cachePayloadBytes, diskCacheDirty, FastEmbedProvider;
|
|
22438
22596
|
var init_fastembed_provider = __esm({
|
|
22439
22597
|
"src/embedding/fastembed-provider.ts"() {
|
|
22440
22598
|
"use strict";
|
|
@@ -22444,6 +22602,9 @@ var init_fastembed_provider = __esm({
|
|
|
22444
22602
|
CACHE_FILE = join3(CACHE_DIR, ".embedding-cache.json");
|
|
22445
22603
|
cache = /* @__PURE__ */ new Map();
|
|
22446
22604
|
MAX_CACHE_SIZE = 5e3;
|
|
22605
|
+
DEFAULT_CACHE_PAYLOAD_BYTES = 64 * 1024 * 1024;
|
|
22606
|
+
MAX_CACHE_FILE_BYTES = 128 * 1024 * 1024;
|
|
22607
|
+
cachePayloadBytes = 0;
|
|
22447
22608
|
diskCacheDirty = false;
|
|
22448
22609
|
FastEmbedProvider = class _FastEmbedProvider {
|
|
22449
22610
|
name = "fastembed-bge-small";
|
|
@@ -22485,7 +22646,7 @@ var init_fastembed_provider = __esm({
|
|
|
22485
22646
|
if (result.length !== this.dimensions) {
|
|
22486
22647
|
throw new Error(`Expected ${this.dimensions}d embedding, got ${result.length}d`);
|
|
22487
22648
|
}
|
|
22488
|
-
|
|
22649
|
+
cacheSet(hash4, result);
|
|
22489
22650
|
return result;
|
|
22490
22651
|
}
|
|
22491
22652
|
async embedBatch(texts) {
|
|
@@ -22510,7 +22671,7 @@ var init_fastembed_provider = __esm({
|
|
|
22510
22671
|
const originalIdx = uncachedIndices[batchIdx];
|
|
22511
22672
|
const plain = Array.from(vec2);
|
|
22512
22673
|
results[originalIdx] = plain;
|
|
22513
|
-
|
|
22674
|
+
cacheSet(textHash(uncachedTexts[batchIdx]), plain);
|
|
22514
22675
|
batchIdx++;
|
|
22515
22676
|
}
|
|
22516
22677
|
}
|
|
@@ -22518,14 +22679,6 @@ var init_fastembed_provider = __esm({
|
|
|
22518
22679
|
}
|
|
22519
22680
|
return results;
|
|
22520
22681
|
}
|
|
22521
|
-
cacheSet(hash4, value) {
|
|
22522
|
-
if (cache.size >= MAX_CACHE_SIZE) {
|
|
22523
|
-
const firstKey = cache.keys().next().value;
|
|
22524
|
-
if (firstKey !== void 0) cache.delete(firstKey);
|
|
22525
|
-
}
|
|
22526
|
-
cache.set(hash4, value);
|
|
22527
|
-
diskCacheDirty = true;
|
|
22528
|
-
}
|
|
22529
22682
|
};
|
|
22530
22683
|
}
|
|
22531
22684
|
});
|
|
@@ -22535,7 +22688,15 @@ var transformers_provider_exports = {};
|
|
|
22535
22688
|
__export(transformers_provider_exports, {
|
|
22536
22689
|
TransformersProvider: () => TransformersProvider
|
|
22537
22690
|
});
|
|
22538
|
-
|
|
22691
|
+
import { createHash as createHash2 } from "crypto";
|
|
22692
|
+
function cacheKey2(text3) {
|
|
22693
|
+
return createHash2("sha256").update(text3).digest("hex");
|
|
22694
|
+
}
|
|
22695
|
+
function maxCachePayloadBytes2() {
|
|
22696
|
+
const raw = Number.parseInt(process.env.MEMORIX_EMBEDDING_CACHE_MAX_BYTES ?? "", 10);
|
|
22697
|
+
return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_CACHE_PAYLOAD_BYTES2;
|
|
22698
|
+
}
|
|
22699
|
+
var cache2, MAX_CACHE_SIZE2, DEFAULT_CACHE_PAYLOAD_BYTES2, cachePayloadBytes2, TransformersProvider;
|
|
22539
22700
|
var init_transformers_provider = __esm({
|
|
22540
22701
|
"src/embedding/transformers-provider.ts"() {
|
|
22541
22702
|
"use strict";
|
|
@@ -22543,6 +22704,8 @@ var init_transformers_provider = __esm({
|
|
|
22543
22704
|
init_provider();
|
|
22544
22705
|
cache2 = /* @__PURE__ */ new Map();
|
|
22545
22706
|
MAX_CACHE_SIZE2 = 5e3;
|
|
22707
|
+
DEFAULT_CACHE_PAYLOAD_BYTES2 = 64 * 1024 * 1024;
|
|
22708
|
+
cachePayloadBytes2 = 0;
|
|
22546
22709
|
TransformersProvider = class _TransformersProvider {
|
|
22547
22710
|
name = "transformers-minilm";
|
|
22548
22711
|
dimensions = 384;
|
|
@@ -22577,7 +22740,7 @@ var init_transformers_provider = __esm({
|
|
|
22577
22740
|
return Promise.all(inputs.map((input) => this.embedInput(input, options)));
|
|
22578
22741
|
}
|
|
22579
22742
|
async embed(text3) {
|
|
22580
|
-
const cached2 = cache2.get(text3);
|
|
22743
|
+
const cached2 = cache2.get(cacheKey2(text3));
|
|
22581
22744
|
if (cached2) return cached2;
|
|
22582
22745
|
const output = await this.extractor(text3, {
|
|
22583
22746
|
pooling: "mean",
|
|
@@ -22587,7 +22750,7 @@ var init_transformers_provider = __esm({
|
|
|
22587
22750
|
if (result.length !== this.dimensions) {
|
|
22588
22751
|
throw new Error(`Expected ${this.dimensions}d embedding, got ${result.length}d`);
|
|
22589
22752
|
}
|
|
22590
|
-
this.cacheSet(text3, result);
|
|
22753
|
+
this.cacheSet(cacheKey2(text3), result);
|
|
22591
22754
|
return result;
|
|
22592
22755
|
}
|
|
22593
22756
|
async embedBatch(texts) {
|
|
@@ -22595,7 +22758,7 @@ var init_transformers_provider = __esm({
|
|
|
22595
22758
|
const uncachedIndices = [];
|
|
22596
22759
|
const uncachedTexts = [];
|
|
22597
22760
|
for (let i4 = 0; i4 < texts.length; i4++) {
|
|
22598
|
-
const cached2 = cache2.get(texts[i4]);
|
|
22761
|
+
const cached2 = cache2.get(cacheKey2(texts[i4]));
|
|
22599
22762
|
if (cached2) {
|
|
22600
22763
|
results[i4] = cached2;
|
|
22601
22764
|
} else {
|
|
@@ -22613,17 +22776,27 @@ var init_transformers_provider = __esm({
|
|
|
22613
22776
|
const vec2 = Array.from(allVecs[i4]);
|
|
22614
22777
|
const originalIdx = uncachedIndices[i4];
|
|
22615
22778
|
results[originalIdx] = vec2;
|
|
22616
|
-
this.cacheSet(uncachedTexts[i4], vec2);
|
|
22779
|
+
this.cacheSet(cacheKey2(uncachedTexts[i4]), vec2);
|
|
22617
22780
|
}
|
|
22618
22781
|
}
|
|
22619
22782
|
return results;
|
|
22620
22783
|
}
|
|
22621
22784
|
cacheSet(key, value) {
|
|
22622
|
-
|
|
22623
|
-
|
|
22624
|
-
|
|
22785
|
+
const incomingBytes = value.length * 8;
|
|
22786
|
+
if (incomingBytes > maxCachePayloadBytes2()) return;
|
|
22787
|
+
const existing = cache2.get(key);
|
|
22788
|
+
if (existing) cachePayloadBytes2 -= existing.length * 8;
|
|
22789
|
+
else {
|
|
22790
|
+
while (cache2.size >= MAX_CACHE_SIZE2 || cachePayloadBytes2 + incomingBytes > maxCachePayloadBytes2()) {
|
|
22791
|
+
const firstKey = cache2.keys().next().value;
|
|
22792
|
+
if (firstKey === void 0) break;
|
|
22793
|
+
const old = cache2.get(firstKey);
|
|
22794
|
+
cache2.delete(firstKey);
|
|
22795
|
+
if (old) cachePayloadBytes2 -= old.length * 8;
|
|
22796
|
+
}
|
|
22625
22797
|
}
|
|
22626
22798
|
cache2.set(key, value);
|
|
22799
|
+
cachePayloadBytes2 += incomingBytes;
|
|
22627
22800
|
}
|
|
22628
22801
|
};
|
|
22629
22802
|
}
|
|
@@ -22645,7 +22818,7 @@ __export(api_provider_exports, {
|
|
|
22645
22818
|
saveDiskCacheNow: () => saveDiskCacheNow,
|
|
22646
22819
|
seedApiEmbeddingCacheForTests: () => seedApiEmbeddingCacheForTests
|
|
22647
22820
|
});
|
|
22648
|
-
import { createHash as
|
|
22821
|
+
import { createHash as createHash3 } from "crypto";
|
|
22649
22822
|
import { createReadStream, createWriteStream, constants as fsConstants } from "fs";
|
|
22650
22823
|
import { access, readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, rename, stat, unlink } from "fs/promises";
|
|
22651
22824
|
import { join as join4 } from "path";
|
|
@@ -22672,7 +22845,7 @@ function cacheStatFile() {
|
|
|
22672
22845
|
function payloadBytes(vector) {
|
|
22673
22846
|
return vector.length * BYTES_PER_DIM;
|
|
22674
22847
|
}
|
|
22675
|
-
function
|
|
22848
|
+
function maxCachePayloadBytes3() {
|
|
22676
22849
|
const raw = process.env.MEMORIX_EMBEDDING_CACHE_MAX_BYTES;
|
|
22677
22850
|
if (raw) {
|
|
22678
22851
|
const parsed = Number.parseInt(raw, 10);
|
|
@@ -22682,7 +22855,7 @@ function maxCachePayloadBytes() {
|
|
|
22682
22855
|
}
|
|
22683
22856
|
function maxEntriesForDimensions(dimensions) {
|
|
22684
22857
|
const dim = Math.max(1, Math.floor(dimensions));
|
|
22685
|
-
const byBytes = Math.floor(
|
|
22858
|
+
const byBytes = Math.floor(maxCachePayloadBytes3() / (dim * BYTES_PER_DIM));
|
|
22686
22859
|
return Math.max(1, Math.min(MAX_CACHE_ENTRIES, byBytes));
|
|
22687
22860
|
}
|
|
22688
22861
|
function rememberDimensions(vector) {
|
|
@@ -22695,13 +22868,15 @@ function evictOldest() {
|
|
|
22695
22868
|
if (firstKey === void 0) return;
|
|
22696
22869
|
const old = cache3.get(firstKey);
|
|
22697
22870
|
cache3.delete(firstKey);
|
|
22698
|
-
if (old)
|
|
22871
|
+
if (old) cachePayloadBytes3 -= payloadBytes(old);
|
|
22699
22872
|
}
|
|
22700
22873
|
function evictToFit(incomingBytes, incomingDims) {
|
|
22874
|
+
if (incomingBytes > maxCachePayloadBytes3()) return false;
|
|
22701
22875
|
const limit2 = maxEntriesForDimensions(incomingDims);
|
|
22702
|
-
while (cache3.size > 0 && (cache3.size >= limit2 ||
|
|
22876
|
+
while (cache3.size > 0 && (cache3.size >= limit2 || cachePayloadBytes3 + incomingBytes > maxCachePayloadBytes3())) {
|
|
22703
22877
|
evictOldest();
|
|
22704
22878
|
}
|
|
22879
|
+
return true;
|
|
22705
22880
|
}
|
|
22706
22881
|
function isNumberArray(value) {
|
|
22707
22882
|
return Array.isArray(value) && value.every((entry) => typeof entry === "number");
|
|
@@ -22728,12 +22903,12 @@ function cacheInsert(hash4, value, dirty) {
|
|
|
22728
22903
|
const incoming = payloadBytes(value);
|
|
22729
22904
|
const existing = cache3.get(hash4);
|
|
22730
22905
|
if (existing) {
|
|
22731
|
-
|
|
22906
|
+
cachePayloadBytes3 -= payloadBytes(existing);
|
|
22732
22907
|
cache3.delete(hash4);
|
|
22733
22908
|
}
|
|
22734
|
-
evictToFit(incoming, value.length || cacheDimensions || DEFAULT_ASSUMED_DIMENSIONS);
|
|
22909
|
+
if (!evictToFit(incoming, value.length || cacheDimensions || DEFAULT_ASSUMED_DIMENSIONS)) return;
|
|
22735
22910
|
cache3.set(hash4, value);
|
|
22736
|
-
|
|
22911
|
+
cachePayloadBytes3 += incoming;
|
|
22737
22912
|
if (dirty) diskCacheDirty2 = true;
|
|
22738
22913
|
}
|
|
22739
22914
|
async function readCacheStat() {
|
|
@@ -22769,7 +22944,7 @@ function cacheNamespace(config2) {
|
|
|
22769
22944
|
].join("|");
|
|
22770
22945
|
}
|
|
22771
22946
|
function textHash2(text3, namespace) {
|
|
22772
|
-
return
|
|
22947
|
+
return createHash3("sha256").update(`${namespace}\0${text3}`).digest("hex").slice(0, 16);
|
|
22773
22948
|
}
|
|
22774
22949
|
function inputIdentity(input, options = {}) {
|
|
22775
22950
|
return JSON.stringify({
|
|
@@ -23111,7 +23286,7 @@ function getApiEmbeddingDiskCacheLoadCountForTests() {
|
|
|
23111
23286
|
}
|
|
23112
23287
|
function resetApiEmbeddingCacheForTests() {
|
|
23113
23288
|
cache3.clear();
|
|
23114
|
-
|
|
23289
|
+
cachePayloadBytes3 = 0;
|
|
23115
23290
|
cacheDimensions = null;
|
|
23116
23291
|
diskCacheEntryCount = 0;
|
|
23117
23292
|
diskCacheLoaded = false;
|
|
@@ -23122,14 +23297,14 @@ function resetApiEmbeddingCacheForTests() {
|
|
|
23122
23297
|
}
|
|
23123
23298
|
function seedApiEmbeddingCacheForTests(entries) {
|
|
23124
23299
|
cache3.clear();
|
|
23125
|
-
|
|
23300
|
+
cachePayloadBytes3 = 0;
|
|
23126
23301
|
cacheDimensions = null;
|
|
23127
23302
|
for (const [key, value] of entries) cacheInsert(key, value, true);
|
|
23128
23303
|
diskCacheLoaded = true;
|
|
23129
23304
|
diskCacheDirty2 = true;
|
|
23130
23305
|
}
|
|
23131
23306
|
function getApiEmbeddingCachePayloadBytesForTests() {
|
|
23132
|
-
return
|
|
23307
|
+
return cachePayloadBytes3;
|
|
23133
23308
|
}
|
|
23134
23309
|
function getApiEmbeddingJsonlLineCountCallsForTests() {
|
|
23135
23310
|
return jsonlLineCountCalls;
|
|
@@ -23303,7 +23478,7 @@ function scheduleDiskSave() {
|
|
|
23303
23478
|
diskSaveTimer = null;
|
|
23304
23479
|
}, DISK_SAVE_DEBOUNCE_MS);
|
|
23305
23480
|
}
|
|
23306
|
-
function
|
|
23481
|
+
function cacheSet2(hash4, value) {
|
|
23307
23482
|
cacheInsert(hash4, value, true);
|
|
23308
23483
|
}
|
|
23309
23484
|
function resolveEnvEmbeddingApiKey() {
|
|
@@ -23423,7 +23598,7 @@ async function waitForRetry(waitMs, signal) {
|
|
|
23423
23598
|
abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
23424
23599
|
});
|
|
23425
23600
|
}
|
|
23426
|
-
var cache3, MAX_CACHE_ENTRIES, MAX_CACHE_PAYLOAD_BYTES, BYTES_PER_DIM, DEFAULT_ASSUMED_DIMENSIONS, MAX_MIGRATION_VALUE_BYTES,
|
|
23601
|
+
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;
|
|
23427
23602
|
var init_api_provider = __esm({
|
|
23428
23603
|
"src/embedding/api-provider.ts"() {
|
|
23429
23604
|
"use strict";
|
|
@@ -23435,7 +23610,7 @@ var init_api_provider = __esm({
|
|
|
23435
23610
|
BYTES_PER_DIM = 8;
|
|
23436
23611
|
DEFAULT_ASSUMED_DIMENSIONS = 4096;
|
|
23437
23612
|
MAX_MIGRATION_VALUE_BYTES = 16 * 1024 * 1024;
|
|
23438
|
-
|
|
23613
|
+
cachePayloadBytes3 = 0;
|
|
23439
23614
|
cacheDimensions = null;
|
|
23440
23615
|
diskCacheEntryCount = 0;
|
|
23441
23616
|
diskCacheDirty2 = false;
|
|
@@ -23620,7 +23795,7 @@ var init_api_provider = __esm({
|
|
|
23620
23795
|
} else {
|
|
23621
23796
|
embedding = await apiCall();
|
|
23622
23797
|
}
|
|
23623
|
-
|
|
23798
|
+
cacheSet2(hash4, embedding);
|
|
23624
23799
|
scheduleDiskSave();
|
|
23625
23800
|
return embedding;
|
|
23626
23801
|
}
|
|
@@ -23668,7 +23843,7 @@ var init_api_provider = __esm({
|
|
|
23668
23843
|
for (const item of response.data) {
|
|
23669
23844
|
const originalIdx = chunkIndices[item.index];
|
|
23670
23845
|
results[originalIdx] = item.embedding;
|
|
23671
|
-
|
|
23846
|
+
cacheSet2(textHash2(normalizedTexts[originalIdx], this.cacheKeyNamespace), item.embedding);
|
|
23672
23847
|
}
|
|
23673
23848
|
} catch (error40) {
|
|
23674
23849
|
const providerLimit = parseBatchLimit(error40);
|
|
@@ -23746,7 +23921,7 @@ var init_api_provider = __esm({
|
|
|
23746
23921
|
throw new Error(`Expected ${this.dimensions}d, got ${embedding.length}d; dimension mismatch`);
|
|
23747
23922
|
}
|
|
23748
23923
|
this.trackUsage(response);
|
|
23749
|
-
|
|
23924
|
+
cacheSet2(hash4, embedding);
|
|
23750
23925
|
scheduleDiskSave();
|
|
23751
23926
|
return embedding;
|
|
23752
23927
|
}
|
|
@@ -25129,6 +25304,7 @@ var init_provider2 = __esm({
|
|
|
25129
25304
|
openai: { baseUrl: "https://api.openai.com/v1", model: "gpt-4.1-nano" },
|
|
25130
25305
|
anthropic: { baseUrl: "https://api.anthropic.com/v1", model: "claude-3-5-haiku-latest" },
|
|
25131
25306
|
openrouter: { baseUrl: "https://openrouter.ai/api/v1", model: "openai/gpt-4.1-nano" },
|
|
25307
|
+
atlascloud: { baseUrl: "https://api.atlascloud.ai/v1", model: "deepseek-ai/deepseek-v3.2" },
|
|
25132
25308
|
custom: { baseUrl: "http://localhost:11434/v1", model: "llama3" }
|
|
25133
25309
|
};
|
|
25134
25310
|
currentConfig = null;
|
|
@@ -25892,7 +26068,7 @@ var init_obs_store = __esm({
|
|
|
25892
26068
|
});
|
|
25893
26069
|
|
|
25894
26070
|
// src/search/semantic-index.ts
|
|
25895
|
-
import { createHash as
|
|
26071
|
+
import { createHash as createHash4 } from "crypto";
|
|
25896
26072
|
import { createRequire as createRequire3 } from "module";
|
|
25897
26073
|
import path10 from "path";
|
|
25898
26074
|
function createSemanticIndexProfile(provider2) {
|
|
@@ -25906,7 +26082,7 @@ function stateKey(dataDir, profile) {
|
|
|
25906
26082
|
return `${path10.resolve(dataDir)}::${profile.key}`;
|
|
25907
26083
|
}
|
|
25908
26084
|
function tableName(profile) {
|
|
25909
|
-
const digest2 =
|
|
26085
|
+
const digest2 = createHash4("sha256").update(profile.key).digest("hex").slice(0, 20);
|
|
25910
26086
|
return `${TABLE_PREFIX}${digest2}`;
|
|
25911
26087
|
}
|
|
25912
26088
|
function indexRoot(dataDir) {
|
|
@@ -26205,6 +26381,7 @@ var init_secret_filter = __esm({
|
|
|
26205
26381
|
// src/runtime/maintenance-jobs.ts
|
|
26206
26382
|
var maintenance_jobs_exports = {};
|
|
26207
26383
|
__export(maintenance_jobs_exports, {
|
|
26384
|
+
DEFAULT_FAILED_HISTORY_RETENTION_MS: () => DEFAULT_FAILED_HISTORY_RETENTION_MS,
|
|
26208
26385
|
MAINTENANCE_JOB_KINDS: () => MAINTENANCE_JOB_KINDS,
|
|
26209
26386
|
MaintenanceJobStore: () => MaintenanceJobStore,
|
|
26210
26387
|
MaintenanceJobWorker: () => MaintenanceJobWorker,
|
|
@@ -26254,7 +26431,7 @@ function normalizedKinds(kinds) {
|
|
|
26254
26431
|
function getMaintenanceRetryDelayMs(attempts) {
|
|
26255
26432
|
return Math.min(6e4, 1e3 * 2 ** Math.max(0, attempts - 1));
|
|
26256
26433
|
}
|
|
26257
|
-
var MAINTENANCE_JOB_KINDS, DEFAULT_MAX_ATTEMPTS, DEFAULT_LEASE_MS, DEFAULT_POLL_INTERVAL_MS, MAX_ERROR_LENGTH, DEFAULT_COMPLETED_HISTORY_RETENTION_MS, MaintenanceJobStore, MaintenanceJobWorker;
|
|
26434
|
+
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;
|
|
26258
26435
|
var init_maintenance_jobs = __esm({
|
|
26259
26436
|
"src/runtime/maintenance-jobs.ts"() {
|
|
26260
26437
|
"use strict";
|
|
@@ -26281,6 +26458,7 @@ var init_maintenance_jobs = __esm({
|
|
|
26281
26458
|
DEFAULT_POLL_INTERVAL_MS = 2e3;
|
|
26282
26459
|
MAX_ERROR_LENGTH = 1e3;
|
|
26283
26460
|
DEFAULT_COMPLETED_HISTORY_RETENTION_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
26461
|
+
DEFAULT_FAILED_HISTORY_RETENTION_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
26284
26462
|
MaintenanceJobStore = class {
|
|
26285
26463
|
db;
|
|
26286
26464
|
constructor(dataDir) {
|
|
@@ -26407,18 +26585,21 @@ var init_maintenance_jobs = __esm({
|
|
|
26407
26585
|
}
|
|
26408
26586
|
/**
|
|
26409
26587
|
* Completed jobs are useful recent operator history, not permanent data.
|
|
26410
|
-
* Failed
|
|
26411
|
-
*
|
|
26588
|
+
* Failed diagnostics are retained longer, but are still bounded so a
|
|
26589
|
+
* permanently failing job kind cannot grow the database forever.
|
|
26412
26590
|
*/
|
|
26413
26591
|
pruneCompletedHistory(options = {}) {
|
|
26414
26592
|
const now3 = options.now ?? Date.now();
|
|
26415
26593
|
const maxAgeMs = Number.isFinite(options.maxAgeMs) ? Math.max(0, Math.floor(options.maxAgeMs)) : DEFAULT_COMPLETED_HISTORY_RETENTION_MS;
|
|
26594
|
+
const failedMaxAgeMs = Number.isFinite(options.failedMaxAgeMs) ? Math.max(0, Math.floor(options.failedMaxAgeMs)) : DEFAULT_FAILED_HISTORY_RETENTION_MS;
|
|
26416
26595
|
const result = this.db.prepare(`
|
|
26417
26596
|
DELETE FROM maintenance_jobs
|
|
26418
|
-
WHERE status = 'completed'
|
|
26597
|
+
WHERE (status = 'completed'
|
|
26419
26598
|
AND completed_at IS NOT NULL
|
|
26420
|
-
AND completed_at < ?
|
|
26421
|
-
|
|
26599
|
+
AND completed_at < ?)
|
|
26600
|
+
OR (status = 'failed'
|
|
26601
|
+
AND updated_at < ?)
|
|
26602
|
+
`).run(now3 - maxAgeMs, now3 - failedMaxAgeMs);
|
|
26422
26603
|
return Number(result.changes ?? 0);
|
|
26423
26604
|
}
|
|
26424
26605
|
claimNext(options) {
|
|
@@ -26777,7 +26958,7 @@ __export(evidence_store_exports, {
|
|
|
26777
26958
|
EvidenceCardStore: () => EvidenceCardStore,
|
|
26778
26959
|
buildEvidenceCardId: () => buildEvidenceCardId
|
|
26779
26960
|
});
|
|
26780
|
-
import { createHash as
|
|
26961
|
+
import { createHash as createHash5, randomUUID as randomUUID3 } from "crypto";
|
|
26781
26962
|
function safeJson(value, fallback) {
|
|
26782
26963
|
if (typeof value !== "string" || value.length === 0) return fallback;
|
|
26783
26964
|
try {
|
|
@@ -26811,7 +26992,7 @@ function rowToCard(row) {
|
|
|
26811
26992
|
};
|
|
26812
26993
|
}
|
|
26813
26994
|
function observationHash(observation) {
|
|
26814
|
-
return
|
|
26995
|
+
return createHash5("sha256").update(JSON.stringify({
|
|
26815
26996
|
projectId: observation.projectId,
|
|
26816
26997
|
id: observation.id,
|
|
26817
26998
|
title: observation.title,
|
|
@@ -27408,13 +27589,13 @@ __export(workspace_exports, {
|
|
|
27408
27589
|
loadKnowledgeWorkspace: () => loadKnowledgeWorkspace,
|
|
27409
27590
|
resolveKnowledgeWorkspaceFile: () => resolveKnowledgeWorkspaceFile
|
|
27410
27591
|
});
|
|
27411
|
-
import { createHash as
|
|
27592
|
+
import { createHash as createHash6 } from "crypto";
|
|
27412
27593
|
import { execFile } from "child_process";
|
|
27413
27594
|
import { promises as fs7 } from "fs";
|
|
27414
27595
|
import path12 from "path";
|
|
27415
27596
|
import { promisify } from "util";
|
|
27416
27597
|
function hash(value) {
|
|
27417
|
-
return
|
|
27598
|
+
return createHash6("sha256").update(value).digest("hex");
|
|
27418
27599
|
}
|
|
27419
27600
|
function workspaceId(projectId, mode) {
|
|
27420
27601
|
return "workspace:" + hash(projectId + ":" + mode).slice(0, 24);
|
|
@@ -28567,14 +28748,14 @@ __export(asset_store_exports, {
|
|
|
28567
28748
|
readMediaAsset: () => readMediaAsset,
|
|
28568
28749
|
removeMediaAsset: () => removeMediaAsset
|
|
28569
28750
|
});
|
|
28570
|
-
import { createHash as
|
|
28751
|
+
import { createHash as createHash7, randomUUID as randomUUID6 } from "crypto";
|
|
28571
28752
|
import { copyFile, lstat, mkdir as mkdir3, open, readFile as readFile3, readdir, rename as rename2, rm, stat as stat2, writeFile as writeFile3 } from "fs/promises";
|
|
28572
28753
|
import path13 from "path";
|
|
28573
28754
|
function mediaRoot(dataDir) {
|
|
28574
28755
|
return path13.resolve(dataDir, "media");
|
|
28575
28756
|
}
|
|
28576
28757
|
function projectStorageKey(projectId) {
|
|
28577
|
-
return
|
|
28758
|
+
return createHash7("sha256").update(projectId).digest("hex").slice(0, 16);
|
|
28578
28759
|
}
|
|
28579
28760
|
function validateUnderRoot(root, candidate2) {
|
|
28580
28761
|
const resolved = path13.resolve(candidate2);
|
|
@@ -28634,7 +28815,7 @@ async function readHeader(filePath, bytes = 32) {
|
|
|
28634
28815
|
}
|
|
28635
28816
|
async function sha256File(filePath) {
|
|
28636
28817
|
const bytes = await readFile3(filePath);
|
|
28637
|
-
return
|
|
28818
|
+
return createHash7("sha256").update(bytes).digest("hex");
|
|
28638
28819
|
}
|
|
28639
28820
|
function destinationFor(root, projectId, sha2562, extension3) {
|
|
28640
28821
|
const relative5 = path13.join("assets", projectStorageKey(projectId), sha2562.slice(0, 2), `${sha2562}${extension3}`);
|
|
@@ -28740,7 +28921,7 @@ async function importMediaBuffer(input) {
|
|
|
28740
28921
|
if (input.bytes.length === 0) throw new Error("Media import rejects empty payloads");
|
|
28741
28922
|
if (input.bytes.length > maxBytes) throw new Error(`Media payload is too large (${input.bytes.length} bytes; limit ${maxBytes})`);
|
|
28742
28923
|
const detected = detectMedia(input.bytes.subarray(0, 32));
|
|
28743
|
-
const sha2562 =
|
|
28924
|
+
const sha2562 = createHash7("sha256").update(input.bytes).digest("hex");
|
|
28744
28925
|
return importKnownMedia({
|
|
28745
28926
|
dataDir: input.dataDir,
|
|
28746
28927
|
projectId: input.projectId,
|
|
@@ -28758,7 +28939,7 @@ async function readMediaAsset(dataDir, asset, maxBytes = DEFAULT_MAX_MEDIA_BYTES
|
|
|
28758
28939
|
if (asset.byteSize > maxBytes) throw new Error(`Media asset exceeds read limit (${asset.byteSize} bytes; limit ${maxBytes})`);
|
|
28759
28940
|
const bytes = await readFile3(getMediaAssetPath(dataDir, asset));
|
|
28760
28941
|
if (bytes.length !== asset.byteSize) throw new Error(`Media asset size no longer matches metadata: ${asset.id}`);
|
|
28761
|
-
const sha2562 =
|
|
28942
|
+
const sha2562 = createHash7("sha256").update(bytes).digest("hex");
|
|
28762
28943
|
if (sha2562 !== asset.sha256) throw new Error(`Media asset hash no longer matches metadata: ${asset.id}`);
|
|
28763
28944
|
return bytes;
|
|
28764
28945
|
}
|
|
@@ -81628,7 +81809,7 @@ var require_gaxios = __commonJS({
|
|
|
81628
81809
|
var retry_js_1 = require_retry3();
|
|
81629
81810
|
var stream_1 = __require("stream");
|
|
81630
81811
|
var interceptor_js_1 = require_interceptor();
|
|
81631
|
-
var
|
|
81812
|
+
var randomUUID23 = async () => globalThis.crypto?.randomUUID() || (await import("crypto")).randomUUID();
|
|
81632
81813
|
var HTTP_STATUS_NO_CONTENT = 204;
|
|
81633
81814
|
var Gaxios = class {
|
|
81634
81815
|
agentCache = /* @__PURE__ */ new Map();
|
|
@@ -81901,7 +82082,7 @@ var require_gaxios = __commonJS({
|
|
|
81901
82082
|
*/
|
|
81902
82083
|
["Blob", "File", "FormData"].includes(opts.data?.constructor?.name || "");
|
|
81903
82084
|
if (opts.multipart?.length) {
|
|
81904
|
-
const boundary = await
|
|
82085
|
+
const boundary = await randomUUID23();
|
|
81905
82086
|
preparedHeaders.set("content-type", `multipart/related; boundary=${boundary}`);
|
|
81906
82087
|
opts.body = stream_1.Readable.from(this.getMultipartRequest(opts.multipart, boundary));
|
|
81907
82088
|
} else if (shouldDirectlyPassData) {
|
|
@@ -87573,16 +87754,16 @@ var require_jwtaccess = __commonJS({
|
|
|
87573
87754
|
* @returns A string that returns the cached key.
|
|
87574
87755
|
*/
|
|
87575
87756
|
getCachedKey(url2, scopes) {
|
|
87576
|
-
let
|
|
87757
|
+
let cacheKey4 = url2;
|
|
87577
87758
|
if (scopes && Array.isArray(scopes) && scopes.length) {
|
|
87578
|
-
|
|
87759
|
+
cacheKey4 = url2 ? `${url2}_${scopes.join("_")}` : `${scopes.join("_")}`;
|
|
87579
87760
|
} else if (typeof scopes === "string") {
|
|
87580
|
-
|
|
87761
|
+
cacheKey4 = url2 ? `${url2}_${scopes}` : scopes;
|
|
87581
87762
|
}
|
|
87582
|
-
if (!
|
|
87763
|
+
if (!cacheKey4) {
|
|
87583
87764
|
throw Error("Scopes or url must be provided");
|
|
87584
87765
|
}
|
|
87585
|
-
return
|
|
87766
|
+
return cacheKey4;
|
|
87586
87767
|
}
|
|
87587
87768
|
/**
|
|
87588
87769
|
* Get a non-expired access token, after refreshing if necessary.
|
|
@@ -94128,7 +94309,7 @@ var require_websocket = __commonJS({
|
|
|
94128
94309
|
var http3 = __require("http");
|
|
94129
94310
|
var net = __require("net");
|
|
94130
94311
|
var tls = __require("tls");
|
|
94131
|
-
var { randomBytes: randomBytes3, createHash:
|
|
94312
|
+
var { randomBytes: randomBytes3, createHash: createHash29 } = __require("crypto");
|
|
94132
94313
|
var { Duplex, Readable: Readable3 } = __require("stream");
|
|
94133
94314
|
var { URL: URL2 } = __require("url");
|
|
94134
94315
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -94796,7 +94977,7 @@ var require_websocket = __commonJS({
|
|
|
94796
94977
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
94797
94978
|
return;
|
|
94798
94979
|
}
|
|
94799
|
-
const digest2 =
|
|
94980
|
+
const digest2 = createHash29("sha1").update(key + GUID).digest("base64");
|
|
94800
94981
|
if (res.headers["sec-websocket-accept"] !== digest2) {
|
|
94801
94982
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
94802
94983
|
return;
|
|
@@ -95168,7 +95349,7 @@ var require_websocket_server = __commonJS({
|
|
|
95168
95349
|
var EventEmitter2 = __require("events");
|
|
95169
95350
|
var http3 = __require("http");
|
|
95170
95351
|
var { Duplex } = __require("stream");
|
|
95171
|
-
var { createHash:
|
|
95352
|
+
var { createHash: createHash29 } = __require("crypto");
|
|
95172
95353
|
var extension3 = require_extension();
|
|
95173
95354
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
95174
95355
|
var subprotocol2 = require_subprotocol();
|
|
@@ -95475,7 +95656,7 @@ var require_websocket_server = __commonJS({
|
|
|
95475
95656
|
);
|
|
95476
95657
|
}
|
|
95477
95658
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
95478
|
-
const digest2 =
|
|
95659
|
+
const digest2 = createHash29("sha1").update(key + GUID).digest("base64");
|
|
95479
95660
|
const headers = [
|
|
95480
95661
|
"HTTP/1.1 101 Switching Protocols",
|
|
95481
95662
|
"Upgrade: websocket",
|
|
@@ -175397,9 +175578,9 @@ var init_union_priority_sort = __esm({
|
|
|
175397
175578
|
// node_modules/typebox/build/value/clean/from_union.mjs
|
|
175398
175579
|
function FromUnion9(context, type, value) {
|
|
175399
175580
|
for (const schema of UnionPrioritySort(type.anyOf)) {
|
|
175400
|
-
const
|
|
175401
|
-
if (Check2(context, schema,
|
|
175402
|
-
return
|
|
175581
|
+
const clean2 = FromType19(context, schema, Clone2(value));
|
|
175582
|
+
if (Check2(context, schema, clean2))
|
|
175583
|
+
return clean2;
|
|
175403
175584
|
}
|
|
175404
175585
|
return value;
|
|
175405
175586
|
}
|
|
@@ -180041,9 +180222,9 @@ var init_long_term = __esm({
|
|
|
180041
180222
|
});
|
|
180042
180223
|
|
|
180043
180224
|
// src/codegraph/ids.ts
|
|
180044
|
-
import { createHash as
|
|
180225
|
+
import { createHash as createHash8 } from "crypto";
|
|
180045
180226
|
function digest(input) {
|
|
180046
|
-
return
|
|
180227
|
+
return createHash8("sha256").update(input).digest("hex").slice(0, 16);
|
|
180047
180228
|
}
|
|
180048
180229
|
function normalizeCodePath(path50) {
|
|
180049
180230
|
return path50.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+/g, "/");
|
|
@@ -181091,7 +181272,7 @@ var init_store = __esm({
|
|
|
181091
181272
|
|
|
181092
181273
|
// src/codegraph/code-state.ts
|
|
181093
181274
|
import { execFile as execFile2 } from "child_process";
|
|
181094
|
-
import { createHash as
|
|
181275
|
+
import { createHash as createHash9 } from "crypto";
|
|
181095
181276
|
import { promisify as promisify3 } from "util";
|
|
181096
181277
|
async function runGit(rootPath, args) {
|
|
181097
181278
|
try {
|
|
@@ -181120,7 +181301,7 @@ function changedPathCount(status) {
|
|
|
181120
181301
|
return count3;
|
|
181121
181302
|
}
|
|
181122
181303
|
function fingerprint(baseRevision, status) {
|
|
181123
|
-
return
|
|
181304
|
+
return createHash9("sha256").update(baseRevision ?? "").update("\0").update(status).digest("hex");
|
|
181124
181305
|
}
|
|
181125
181306
|
async function collectCodeStateSnapshot(input) {
|
|
181126
181307
|
const [revision, status] = await Promise.all([
|
|
@@ -181214,12 +181395,12 @@ var init_exclude3 = __esm({
|
|
|
181214
181395
|
});
|
|
181215
181396
|
|
|
181216
181397
|
// src/codegraph/semantic-provider.ts
|
|
181217
|
-
import { createHash as
|
|
181398
|
+
import { createHash as createHash10 } from "crypto";
|
|
181218
181399
|
import "fs";
|
|
181219
181400
|
import { resolve as resolve3 } from "path";
|
|
181220
181401
|
import ts from "typescript";
|
|
181221
181402
|
function hashText(value) {
|
|
181222
|
-
return
|
|
181403
|
+
return createHash10("sha256").update(value).digest("hex");
|
|
181223
181404
|
}
|
|
181224
181405
|
function canonicalPath(value) {
|
|
181225
181406
|
const normalized = resolve3(value).replace(/\\/g, "/");
|
|
@@ -181564,11 +181745,11 @@ __export(lite_provider_exports, {
|
|
|
181564
181745
|
indexProjectLite: () => indexProjectLite,
|
|
181565
181746
|
refreshProjectLite: () => refreshProjectLite
|
|
181566
181747
|
});
|
|
181567
|
-
import { createHash as
|
|
181748
|
+
import { createHash as createHash11 } from "crypto";
|
|
181568
181749
|
import { existsSync as existsSync14, readdirSync as readdirSync2, readFileSync as readFileSync9, statSync as statSync4 } from "fs";
|
|
181569
181750
|
import { join as join5, relative as relative2 } from "path";
|
|
181570
181751
|
function hashText2(text3) {
|
|
181571
|
-
return
|
|
181752
|
+
return createHash11("sha256").update(text3).digest("hex");
|
|
181572
181753
|
}
|
|
181573
181754
|
function extension2(path50) {
|
|
181574
181755
|
const index = path50.lastIndexOf(".");
|
|
@@ -182201,7 +182382,7 @@ var claim_store_exports = {};
|
|
|
182201
182382
|
__export(claim_store_exports, {
|
|
182202
182383
|
ClaimStore: () => ClaimStore
|
|
182203
182384
|
});
|
|
182204
|
-
import { createHash as
|
|
182385
|
+
import { createHash as createHash12, randomUUID as randomUUID12 } from "crypto";
|
|
182205
182386
|
function optionalText3(value) {
|
|
182206
182387
|
return typeof value === "string" && value ? value : void 0;
|
|
182207
182388
|
}
|
|
@@ -182254,7 +182435,7 @@ function rowToEvent3(row) {
|
|
|
182254
182435
|
};
|
|
182255
182436
|
}
|
|
182256
182437
|
function evidenceKey(input) {
|
|
182257
|
-
return
|
|
182438
|
+
return createHash12("sha256").update(JSON.stringify([
|
|
182258
182439
|
input.evidenceKind,
|
|
182259
182440
|
input.evidenceId,
|
|
182260
182441
|
input.relation,
|
|
@@ -182452,7 +182633,7 @@ __export(claims_exports, {
|
|
|
182452
182633
|
supersedeClaim: () => supersedeClaim,
|
|
182453
182634
|
writeClaim: () => writeClaim
|
|
182454
182635
|
});
|
|
182455
|
-
import { createHash as
|
|
182636
|
+
import { createHash as createHash13, randomUUID as randomUUID13 } from "crypto";
|
|
182456
182637
|
function compactText2(value, field) {
|
|
182457
182638
|
if (typeof value !== "string") throw new Error("Claim " + field + " must be text");
|
|
182458
182639
|
const sanitized = sanitizeCredentials(value).trim().replace(/\s+/g, " ");
|
|
@@ -182464,7 +182645,7 @@ function normalizedTerm(value) {
|
|
|
182464
182645
|
return compactText2(value, "identity").toLocaleLowerCase("en-US");
|
|
182465
182646
|
}
|
|
182466
182647
|
function hashIdentity(parts) {
|
|
182467
|
-
return
|
|
182648
|
+
return createHash13("sha256").update(parts.join(String.fromCharCode(31))).digest("hex");
|
|
182468
182649
|
}
|
|
182469
182650
|
function buildClaimIdentity(input) {
|
|
182470
182651
|
const subject = normalizedTerm(input.subject);
|
|
@@ -182705,7 +182886,7 @@ function supersedeClaim(store2, input) {
|
|
|
182705
182886
|
});
|
|
182706
182887
|
}
|
|
182707
182888
|
function hashObservation(observation) {
|
|
182708
|
-
return
|
|
182889
|
+
return createHash13("sha256").update(JSON.stringify([
|
|
182709
182890
|
observation.title,
|
|
182710
182891
|
observation.narrative,
|
|
182711
182892
|
observation.facts,
|
|
@@ -182949,11 +183130,11 @@ var init_frontmatter = __esm({
|
|
|
182949
183130
|
});
|
|
182950
183131
|
|
|
182951
183132
|
// src/knowledge/markdown.ts
|
|
182952
|
-
import { createHash as
|
|
183133
|
+
import { createHash as createHash14 } from "crypto";
|
|
182953
183134
|
import { promises as fs11 } from "fs";
|
|
182954
183135
|
import path20 from "path";
|
|
182955
183136
|
function hashContent(content) {
|
|
182956
|
-
return
|
|
183137
|
+
return createHash14("sha256").update(content).digest("hex");
|
|
182957
183138
|
}
|
|
182958
183139
|
function stringField(data, key) {
|
|
182959
183140
|
const value = data[key];
|
|
@@ -183079,11 +183260,11 @@ __export(wiki_exports, {
|
|
|
183079
183260
|
lintKnowledgeWorkspace: () => lintKnowledgeWorkspace,
|
|
183080
183261
|
readKnowledgePage: () => readKnowledgePage
|
|
183081
183262
|
});
|
|
183082
|
-
import { createHash as
|
|
183263
|
+
import { createHash as createHash15 } from "crypto";
|
|
183083
183264
|
import { promises as fs12 } from "fs";
|
|
183084
183265
|
import path21 from "path";
|
|
183085
183266
|
function hash2(value) {
|
|
183086
|
-
return
|
|
183267
|
+
return createHash15("sha256").update(value).digest("hex");
|
|
183087
183268
|
}
|
|
183088
183269
|
function now() {
|
|
183089
183270
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -184302,11 +184483,11 @@ __export(workflows_exports, {
|
|
|
184302
184483
|
syncCanonicalWorkflows: () => syncCanonicalWorkflows,
|
|
184303
184484
|
writeCanonicalWorkflow: () => writeCanonicalWorkflow
|
|
184304
184485
|
});
|
|
184305
|
-
import { createHash as
|
|
184486
|
+
import { createHash as createHash16 } from "crypto";
|
|
184306
184487
|
import { promises as fs13 } from "fs";
|
|
184307
184488
|
import path22 from "path";
|
|
184308
184489
|
function hash3(value) {
|
|
184309
|
-
return
|
|
184490
|
+
return createHash16("sha256").update(value).digest("hex");
|
|
184310
184491
|
}
|
|
184311
184492
|
function now2() {
|
|
184312
184493
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -189337,6 +189518,8 @@ var team_store_exports = {};
|
|
|
189337
189518
|
__export(team_store_exports, {
|
|
189338
189519
|
AGENT_TYPE_ROLE_MAP: () => AGENT_TYPE_ROLE_MAP,
|
|
189339
189520
|
DEFAULT_ROLES: () => DEFAULT_ROLES,
|
|
189521
|
+
DEFAULT_TEAM_QUERY_LIMIT: () => DEFAULT_TEAM_QUERY_LIMIT,
|
|
189522
|
+
MAX_TEAM_QUERY_LIMIT: () => MAX_TEAM_QUERY_LIMIT,
|
|
189340
189523
|
TeamStore: () => TeamStore,
|
|
189341
189524
|
getTeamStore: () => getTeamStore,
|
|
189342
189525
|
initTeamStore: () => initTeamStore,
|
|
@@ -189346,6 +189529,10 @@ __export(team_store_exports, {
|
|
|
189346
189529
|
import { randomUUID as randomUUID16 } from "crypto";
|
|
189347
189530
|
import path25 from "path";
|
|
189348
189531
|
import fs15 from "fs";
|
|
189532
|
+
function clampTeamQueryLimit(limit2) {
|
|
189533
|
+
if (!Number.isFinite(limit2) || limit2 == null) return DEFAULT_TEAM_QUERY_LIMIT;
|
|
189534
|
+
return Math.min(MAX_TEAM_QUERY_LIMIT, Math.max(1, Math.floor(limit2)));
|
|
189535
|
+
}
|
|
189349
189536
|
function getTeamStore() {
|
|
189350
189537
|
if (!_teamStore) {
|
|
189351
189538
|
throw new Error("[memorix] TeamStore not initialized \u2014 call initTeamStore() first");
|
|
@@ -189369,12 +189556,14 @@ function resetTeamStore() {
|
|
|
189369
189556
|
_teamStore = null;
|
|
189370
189557
|
_teamStoreDataDir = null;
|
|
189371
189558
|
}
|
|
189372
|
-
var DEFAULT_ROLES, AGENT_TYPE_ROLE_MAP, TeamStore, _teamStore, _teamStoreDataDir;
|
|
189559
|
+
var DEFAULT_TEAM_QUERY_LIMIT, MAX_TEAM_QUERY_LIMIT, DEFAULT_ROLES, AGENT_TYPE_ROLE_MAP, TeamStore, _teamStore, _teamStoreDataDir;
|
|
189373
189560
|
var init_team_store = __esm({
|
|
189374
189561
|
"src/team/team-store.ts"() {
|
|
189375
189562
|
"use strict";
|
|
189376
189563
|
init_esm_shims();
|
|
189377
189564
|
init_sqlite_db();
|
|
189565
|
+
DEFAULT_TEAM_QUERY_LIMIT = 100;
|
|
189566
|
+
MAX_TEAM_QUERY_LIMIT = 500;
|
|
189378
189567
|
DEFAULT_ROLES = [
|
|
189379
189568
|
{ roleId: "planner", label: "Planner", description: "Breaks down requirements, creates tasks, defines dependencies", preferredAgentTypes: ["claude-code", "cursor", "codex"], maxConcurrent: 2 },
|
|
189380
189569
|
{ roleId: "researcher", label: "Researcher", description: "Investigates codebase, gathers context, answers questions", preferredAgentTypes: ["claude-code", "cursor", "gemini-cli"], maxConcurrent: 2 },
|
|
@@ -189684,32 +189873,37 @@ var init_team_store = __esm({
|
|
|
189684
189873
|
return this.stmtAgentFindByInstance.get(projectId, agentType, instanceId);
|
|
189685
189874
|
}
|
|
189686
189875
|
listAgents(projectId, filter) {
|
|
189687
|
-
const
|
|
189876
|
+
const limit2 = clampTeamQueryLimit(filter?.limit);
|
|
189688
189877
|
if (filter?.status) {
|
|
189689
|
-
return
|
|
189878
|
+
return this.db.prepare(
|
|
189879
|
+
`SELECT * FROM team_agents WHERE project_id = ? AND status = ? ORDER BY joined_at DESC LIMIT ?`
|
|
189880
|
+
).all(projectId, filter.status, limit2);
|
|
189690
189881
|
}
|
|
189691
|
-
return
|
|
189882
|
+
return this.db.prepare(
|
|
189883
|
+
`SELECT * FROM team_agents WHERE project_id = ? ORDER BY joined_at DESC LIMIT ?`
|
|
189884
|
+
).all(projectId, limit2);
|
|
189692
189885
|
}
|
|
189693
189886
|
/** List agents across all projects (for global scope) */
|
|
189694
|
-
listAllAgents() {
|
|
189887
|
+
listAllAgents(limit2) {
|
|
189695
189888
|
if (!this.db) return [];
|
|
189696
|
-
return this.db.prepare("SELECT * FROM team_agents ORDER BY last_heartbeat DESC").all();
|
|
189889
|
+
return this.db.prepare("SELECT * FROM team_agents ORDER BY last_heartbeat DESC LIMIT ?").all(clampTeamQueryLimit(limit2));
|
|
189697
189890
|
}
|
|
189698
189891
|
/** List locks across all projects (for global scope) */
|
|
189699
|
-
listAllLocks() {
|
|
189892
|
+
listAllLocks(limit2) {
|
|
189700
189893
|
if (!this.db) return [];
|
|
189701
189894
|
this.db.prepare("DELETE FROM team_locks WHERE expires_at <= ?").run(Date.now());
|
|
189702
|
-
return this.db.prepare("SELECT * FROM team_locks WHERE expires_at > ? ORDER BY locked_at DESC").all(Date.now());
|
|
189895
|
+
return this.db.prepare("SELECT * FROM team_locks WHERE expires_at > ? ORDER BY locked_at DESC LIMIT ?").all(Date.now(), clampTeamQueryLimit(limit2));
|
|
189703
189896
|
}
|
|
189704
189897
|
/** List tasks across all projects (for global scope) */
|
|
189705
189898
|
listAllTasks(filter) {
|
|
189706
189899
|
if (!this.db) return [];
|
|
189900
|
+
const limit2 = clampTeamQueryLimit(filter?.limit);
|
|
189707
189901
|
if (filter?.available) {
|
|
189708
189902
|
return this.db.prepare(
|
|
189709
|
-
`SELECT t.* FROM team_tasks t WHERE t.status = 'pending' AND t.assignee_agent_id IS NULL ORDER BY t.created_at DESC
|
|
189710
|
-
).all();
|
|
189903
|
+
`SELECT t.* FROM team_tasks t WHERE t.status = 'pending' AND t.assignee_agent_id IS NULL ORDER BY t.created_at DESC LIMIT ?`
|
|
189904
|
+
).all(limit2);
|
|
189711
189905
|
}
|
|
189712
|
-
return this.db.prepare("SELECT * FROM team_tasks ORDER BY created_at DESC").all();
|
|
189906
|
+
return this.db.prepare("SELECT * FROM team_tasks ORDER BY created_at DESC LIMIT ?").all(limit2);
|
|
189713
189907
|
}
|
|
189714
189908
|
heartbeat(agentId) {
|
|
189715
189909
|
const info2 = this.stmtAgentUpdateHeartbeat.run(Date.now(), agentId);
|
|
@@ -189744,7 +189938,10 @@ var init_team_store = __esm({
|
|
|
189744
189938
|
return staleIds;
|
|
189745
189939
|
}
|
|
189746
189940
|
getActiveCount(projectId) {
|
|
189747
|
-
|
|
189941
|
+
const row = this.db.prepare(
|
|
189942
|
+
`SELECT COUNT(*) AS count FROM team_agents WHERE project_id = ? AND status = 'active'`
|
|
189943
|
+
).get(projectId);
|
|
189944
|
+
return Number(row?.count ?? 0);
|
|
189748
189945
|
}
|
|
189749
189946
|
// ═══════════════════════════════════════════════════════════════════
|
|
189750
189947
|
// Message Operations
|
|
@@ -189779,8 +189976,14 @@ var init_team_store = __esm({
|
|
|
189779
189976
|
this.stmtMsgInsert.run(row);
|
|
189780
189977
|
return row;
|
|
189781
189978
|
}
|
|
189782
|
-
getInbox(projectId, agentId) {
|
|
189783
|
-
return this.
|
|
189979
|
+
getInbox(projectId, agentId, limit2) {
|
|
189980
|
+
return this.db.prepare(`
|
|
189981
|
+
SELECT * FROM team_messages
|
|
189982
|
+
WHERE project_id = ?
|
|
189983
|
+
AND (recipient_agent_id = ? OR recipient_agent_id IS NULL)
|
|
189984
|
+
ORDER BY created_at ASC
|
|
189985
|
+
LIMIT ?
|
|
189986
|
+
`).all(projectId, agentId, clampTeamQueryLimit(limit2));
|
|
189784
189987
|
}
|
|
189785
189988
|
getUnreadCount(projectId, agentId) {
|
|
189786
189989
|
const row = this.stmtMsgUnreadCount.get(projectId, agentId);
|
|
@@ -189937,17 +190140,22 @@ var init_team_store = __esm({
|
|
|
189937
190140
|
return info2.changes;
|
|
189938
190141
|
}
|
|
189939
190142
|
listTasks(projectId, filter) {
|
|
189940
|
-
|
|
189941
|
-
|
|
189942
|
-
|
|
189943
|
-
const all = this.stmtTaskListByProject.all(projectId);
|
|
190143
|
+
const clauses = ["project_id = ?"];
|
|
190144
|
+
const values = [projectId];
|
|
190145
|
+
if (filter?.available) clauses.push("status = 'pending'", "assignee_agent_id IS NULL");
|
|
189944
190146
|
if (filter?.status) {
|
|
189945
|
-
|
|
190147
|
+
clauses.push("status = ?");
|
|
190148
|
+
values.push(filter.status);
|
|
189946
190149
|
}
|
|
189947
190150
|
if (filter?.assignee) {
|
|
189948
|
-
|
|
190151
|
+
clauses.push("assignee_agent_id = ?");
|
|
190152
|
+
values.push(filter.assignee);
|
|
189949
190153
|
}
|
|
189950
|
-
|
|
190154
|
+
values.push(clampTeamQueryLimit(filter?.limit));
|
|
190155
|
+
const orderBy = filter?.available ? "created_at ASC, rowid ASC" : "created_at DESC, rowid DESC";
|
|
190156
|
+
return this.db.prepare(
|
|
190157
|
+
`SELECT * FROM team_tasks WHERE ${clauses.join(" AND ")} ORDER BY ${orderBy} LIMIT ?`
|
|
190158
|
+
).all(...values);
|
|
189951
190159
|
}
|
|
189952
190160
|
/**
|
|
189953
190161
|
* List available tasks for a specific agent, sorted by role affinity.
|
|
@@ -189959,7 +190167,7 @@ var init_team_store = __esm({
|
|
|
189959
190167
|
const agent = this.stmtAgentFindById.get(agentId);
|
|
189960
190168
|
if (!agent) return [];
|
|
189961
190169
|
const agentRole = agent.role;
|
|
189962
|
-
const available = this.
|
|
190170
|
+
const available = this.listTasks(projectId, { available: true, limit: MAX_TEAM_QUERY_LIMIT });
|
|
189963
190171
|
const eligible = available.filter((t4) => !t4.required_role || t4.required_role === agentRole);
|
|
189964
190172
|
const score = (t4) => {
|
|
189965
190173
|
if (t4.preferred_role === agentRole) return 0;
|
|
@@ -190013,12 +190221,16 @@ var init_team_store = __esm({
|
|
|
190013
190221
|
const row = this.stmtLockGet.get(file2, projectId);
|
|
190014
190222
|
return row ?? null;
|
|
190015
190223
|
}
|
|
190016
|
-
listLocks(projectId, agentId) {
|
|
190224
|
+
listLocks(projectId, agentId, limit2) {
|
|
190017
190225
|
this.stmtLockDeleteExpired.run(projectId, Date.now());
|
|
190018
190226
|
if (agentId) {
|
|
190019
|
-
return this.
|
|
190227
|
+
return this.db.prepare(
|
|
190228
|
+
`SELECT * FROM team_locks WHERE project_id = ? AND locked_by = ? ORDER BY locked_at DESC LIMIT ?`
|
|
190229
|
+
).all(projectId, agentId, clampTeamQueryLimit(limit2));
|
|
190020
190230
|
}
|
|
190021
|
-
return this.
|
|
190231
|
+
return this.db.prepare(
|
|
190232
|
+
`SELECT * FROM team_locks WHERE project_id = ? ORDER BY locked_at DESC LIMIT ?`
|
|
190233
|
+
).all(projectId, clampTeamQueryLimit(limit2));
|
|
190022
190234
|
}
|
|
190023
190235
|
releaseAllLocks(agentId) {
|
|
190024
190236
|
const info2 = this.stmtLockDeleteByAgent.run(agentId);
|
|
@@ -192869,6 +193081,8 @@ function buildInitTomlConfig(options) {
|
|
|
192869
193081
|
lines.push('model = "claude-3-haiku-20240307"');
|
|
192870
193082
|
} else if (options.llmProvider === "openrouter") {
|
|
192871
193083
|
lines.push('# model = "openai/gpt-4o-mini"');
|
|
193084
|
+
} else if (options.llmProvider === "atlascloud") {
|
|
193085
|
+
lines.push('model = "deepseek-ai/deepseek-v3.2"');
|
|
192872
193086
|
}
|
|
192873
193087
|
if (options.llmProvider === "custom") {
|
|
192874
193088
|
lines.push("# OpenAI-compatible endpoint, for example DashScope, DeepSeek, Ollama, or an internal gateway.");
|
|
@@ -193001,6 +193215,7 @@ var init_init = __esm({
|
|
|
193001
193215
|
{ value: "openai", label: "OpenAI", hint: "gpt-4o-mini" },
|
|
193002
193216
|
{ value: "anthropic", label: "Anthropic", hint: "claude-3-haiku" },
|
|
193003
193217
|
{ value: "openrouter", label: "OpenRouter", hint: "multi-provider" },
|
|
193218
|
+
{ value: "atlascloud", label: "Atlas Cloud", hint: "DeepSeek V3.2" },
|
|
193004
193219
|
{ value: "custom", label: "Custom", hint: "OpenAI-compatible endpoint" }
|
|
193005
193220
|
]
|
|
193006
193221
|
});
|
|
@@ -193054,7 +193269,7 @@ var init_init = __esm({
|
|
|
193054
193269
|
];
|
|
193055
193270
|
if (llmProvider !== "none") {
|
|
193056
193271
|
envLines.push("# LLM API key");
|
|
193057
|
-
if (llmProvider === "openai" || llmProvider === "custom") {
|
|
193272
|
+
if (llmProvider === "openai" || llmProvider === "custom" || llmProvider === "atlascloud") {
|
|
193058
193273
|
envLines.push("MEMORIX_LLM_API_KEY=sk-your-key-here");
|
|
193059
193274
|
} else if (llmProvider === "anthropic") {
|
|
193060
193275
|
envLines.push("MEMORIX_LLM_API_KEY=sk-ant-your-key-here");
|
|
@@ -194595,6 +194810,7 @@ var init_official_skills = __esm({
|
|
|
194595
194810
|
"| Need the sequence around one memory | `memorix_timeline` | `memorix memory timeline --id <id>` |",
|
|
194596
194811
|
"| Check source and freshness for a memory | `memorix_evidence` | `memorix evidence list|get|events` |",
|
|
194597
194812
|
"| Record whether a memory helped, conflicted, or was corrected | `memorix_feedback` | `memorix feedback record|show|audit` |",
|
|
194813
|
+
"| Track task requirements, decisions, verification, and outcome | `memorix_continuity` | `memorix continuity start|record|show|close` |",
|
|
194598
194814
|
"| Inspect or import controlled media | `memorix_media` | `memorix media import|attach|list|show|status` |",
|
|
194599
194815
|
'| Learned reusable project knowledge | `memorix_store` | `memorix memory store --type <type> --entity <name> --title "<title>" "<text>"` |',
|
|
194600
194816
|
"| Task or bug is complete/outdated | `memorix_resolve` | `memorix memory resolve --ids <ids>` |",
|
|
@@ -194618,6 +194834,7 @@ var init_official_skills = __esm({
|
|
|
194618
194834
|
"3. Use stale or unbound memory only as a warning or search lead.",
|
|
194619
194835
|
"4. Store durable decisions, fixes, and gotchas after the project state changes.",
|
|
194620
194836
|
"5. Resolve completed or obsolete memories so future briefs stay small.",
|
|
194837
|
+
"6. For multi-step work, start a continuity ledger and pass its taskId back to memorix_project_context.",
|
|
194621
194838
|
"",
|
|
194622
194839
|
"## Store Rules",
|
|
194623
194840
|
"",
|
|
@@ -198185,6 +198402,7 @@ function freshnessForMemory(status) {
|
|
|
198185
198402
|
return "unknown";
|
|
198186
198403
|
}
|
|
198187
198404
|
function receiptOmissionKind(raw) {
|
|
198405
|
+
if (raw.includes("continuity")) return "continuity";
|
|
198188
198406
|
if (raw.includes("continuation")) return "continuation";
|
|
198189
198407
|
if (raw.includes("task")) return "task";
|
|
198190
198408
|
if (raw.includes("fact")) return "current-fact";
|
|
@@ -198295,6 +198513,77 @@ function renderTaskWorksetPrompt(input) {
|
|
|
198295
198513
|
trust: "source-backed"
|
|
198296
198514
|
});
|
|
198297
198515
|
appendLine(lines, "Task lens: " + input.lens, maxTokens, omitted, "lens");
|
|
198516
|
+
if (input.continuity) {
|
|
198517
|
+
const continuity = input.continuity;
|
|
198518
|
+
appendLine(lines, "", maxTokens, omitted, "continuity-heading");
|
|
198519
|
+
appendLine(lines, "Task continuity", maxTokens, omitted, "continuity-heading", selected, {
|
|
198520
|
+
kind: "continuity",
|
|
198521
|
+
id: "continuity:" + continuity.taskId,
|
|
198522
|
+
reason: "explicit task continuity ledger",
|
|
198523
|
+
trust: "source-backed"
|
|
198524
|
+
});
|
|
198525
|
+
appendLine(
|
|
198526
|
+
lines,
|
|
198527
|
+
"- Status: " + continuity.status + " | " + short(continuity.task, 30),
|
|
198528
|
+
maxTokens,
|
|
198529
|
+
omitted,
|
|
198530
|
+
"continuity-task"
|
|
198531
|
+
);
|
|
198532
|
+
appendLine(
|
|
198533
|
+
lines,
|
|
198534
|
+
"- Outcome: " + continuity.outcome.state,
|
|
198535
|
+
maxTokens,
|
|
198536
|
+
omitted,
|
|
198537
|
+
"continuity-outcome",
|
|
198538
|
+
selected,
|
|
198539
|
+
{
|
|
198540
|
+
kind: "continuity",
|
|
198541
|
+
id: "continuity:" + continuity.taskId,
|
|
198542
|
+
reason: "deterministic task outcome projection",
|
|
198543
|
+
trust: "derived"
|
|
198544
|
+
}
|
|
198545
|
+
);
|
|
198546
|
+
for (const requirement of continuity.requirements.slice(0, 3)) {
|
|
198547
|
+
appendLine(lines, "- Requirement: " + short(requirement, 24), maxTokens, omitted, "continuity-requirement", selected, {
|
|
198548
|
+
kind: "continuity",
|
|
198549
|
+
id: "continuity:" + continuity.taskId,
|
|
198550
|
+
reason: "explicit task requirement",
|
|
198551
|
+
trust: "source-backed"
|
|
198552
|
+
});
|
|
198553
|
+
}
|
|
198554
|
+
for (const decision of continuity.decisions.slice(0, 2)) {
|
|
198555
|
+
appendLine(lines, "- Decision: " + short(decision, 24), maxTokens, omitted, "continuity-decision", selected, {
|
|
198556
|
+
kind: "continuity",
|
|
198557
|
+
id: "continuity:" + continuity.taskId,
|
|
198558
|
+
reason: "explicit task decision",
|
|
198559
|
+
trust: "source-backed"
|
|
198560
|
+
});
|
|
198561
|
+
}
|
|
198562
|
+
for (const verification of continuity.verification.slice(-3)) {
|
|
198563
|
+
appendLine(
|
|
198564
|
+
lines,
|
|
198565
|
+
"- Verify [" + verification.status + "]: " + short(verification.content, 22),
|
|
198566
|
+
maxTokens,
|
|
198567
|
+
omitted,
|
|
198568
|
+
"continuity-verification",
|
|
198569
|
+
selected,
|
|
198570
|
+
{
|
|
198571
|
+
kind: "continuity",
|
|
198572
|
+
id: "continuity:" + continuity.taskId,
|
|
198573
|
+
reason: "task verification state",
|
|
198574
|
+
trust: "source-backed"
|
|
198575
|
+
}
|
|
198576
|
+
);
|
|
198577
|
+
}
|
|
198578
|
+
for (const risk of continuity.risks.slice(0, 2)) {
|
|
198579
|
+
appendLine(lines, "- Risk: " + short(risk, 22), maxTokens, omitted, "continuity-risk", selected, {
|
|
198580
|
+
kind: "continuity",
|
|
198581
|
+
id: "continuity:" + continuity.taskId,
|
|
198582
|
+
reason: "open task risk",
|
|
198583
|
+
trust: "source-backed"
|
|
198584
|
+
});
|
|
198585
|
+
}
|
|
198586
|
+
}
|
|
198298
198587
|
if (input.alwaysOn) {
|
|
198299
198588
|
const hasAlwaysOn = input.alwaysOn.profile.length > 0 || Boolean(input.alwaysOn.state) || input.alwaysOn.durable.length > 0;
|
|
198300
198589
|
if (hasAlwaysOn) {
|
|
@@ -198818,6 +199107,7 @@ async function buildTaskWorkset(input) {
|
|
|
198818
199107
|
version: "1.3",
|
|
198819
199108
|
task,
|
|
198820
199109
|
lens: input.lens,
|
|
199110
|
+
...input.continuity ? { continuity: input.continuity } : {},
|
|
198821
199111
|
...input.alwaysOn && (input.alwaysOn.profile.length > 0 || input.alwaysOn.state || input.alwaysOn.durable.length > 0) ? { alwaysOn: input.alwaysOn } : {},
|
|
198822
199112
|
currentFacts: input.currentFacts?.map((fact) => fact.startsWith("Historical note:") ? short(fact, 48) : short(fact, 28)).slice(0, 4) ?? [],
|
|
198823
199113
|
...continuation ? { continuation } : {},
|
|
@@ -201226,7 +201516,7 @@ var compaction_checkpoint_store_exports = {};
|
|
|
201226
201516
|
__export(compaction_checkpoint_store_exports, {
|
|
201227
201517
|
CompactionCheckpointStore: () => CompactionCheckpointStore
|
|
201228
201518
|
});
|
|
201229
|
-
import { createHash as
|
|
201519
|
+
import { createHash as createHash17, randomUUID as randomUUID17 } from "crypto";
|
|
201230
201520
|
function optionalText7(value) {
|
|
201231
201521
|
return typeof value === "string" && value ? value : void 0;
|
|
201232
201522
|
}
|
|
@@ -201268,7 +201558,7 @@ function sourceKeyFor(input, summary) {
|
|
|
201268
201558
|
input.tokensBefore ?? "",
|
|
201269
201559
|
input.firstKeptEntryId ?? ""
|
|
201270
201560
|
].join("\0");
|
|
201271
|
-
return `derived:${
|
|
201561
|
+
return `derived:${createHash17("sha256").update(material).digest("hex").slice(0, 32)}`;
|
|
201272
201562
|
}
|
|
201273
201563
|
function rowToCheckpoint(row) {
|
|
201274
201564
|
return {
|
|
@@ -201526,6 +201816,305 @@ var init_compaction_checkpoint_store = __esm({
|
|
|
201526
201816
|
}
|
|
201527
201817
|
});
|
|
201528
201818
|
|
|
201819
|
+
// src/knowledge/task-continuity.ts
|
|
201820
|
+
var task_continuity_exports = {};
|
|
201821
|
+
__export(task_continuity_exports, {
|
|
201822
|
+
TASK_CONTINUITY_EVENT_KINDS: () => TASK_CONTINUITY_EVENT_KINDS,
|
|
201823
|
+
TaskContinuityStore: () => TaskContinuityStore,
|
|
201824
|
+
evaluateTaskContinuity: () => evaluateTaskContinuity
|
|
201825
|
+
});
|
|
201826
|
+
import { randomUUID as randomUUID18 } from "crypto";
|
|
201827
|
+
function clean(value, maxLength = MAX_TEXT_LENGTH2) {
|
|
201828
|
+
return sanitizeCredentials(value).replace(/\s+/g, " ").trim().slice(0, maxLength);
|
|
201829
|
+
}
|
|
201830
|
+
function cleanList(values, maxLength = MAX_TEXT_LENGTH2) {
|
|
201831
|
+
return [...new Set((values ?? []).map((value) => clean(value, maxLength)).filter(Boolean))].slice(0, MAX_LIST_ITEMS2);
|
|
201832
|
+
}
|
|
201833
|
+
function parseRefs(value) {
|
|
201834
|
+
if (typeof value !== "string") return [];
|
|
201835
|
+
try {
|
|
201836
|
+
const parsed = JSON.parse(value);
|
|
201837
|
+
return Array.isArray(parsed) ? cleanList(parsed.filter((item) => typeof item === "string"), 500).slice(0, MAX_EVIDENCE_REFS) : [];
|
|
201838
|
+
} catch {
|
|
201839
|
+
return [];
|
|
201840
|
+
}
|
|
201841
|
+
}
|
|
201842
|
+
function evaluateTaskContinuity(ledger) {
|
|
201843
|
+
const verification = {
|
|
201844
|
+
passed: ledger.verification.filter((item) => item.status === "passed").length,
|
|
201845
|
+
failed: ledger.verification.filter((item) => item.status === "failed").length,
|
|
201846
|
+
pending: ledger.verification.filter((item) => item.status === "pending").length,
|
|
201847
|
+
skipped: ledger.verification.filter((item) => item.status === "skipped").length
|
|
201848
|
+
};
|
|
201849
|
+
const reasons = [];
|
|
201850
|
+
if (verification.failed > 0) reasons.push("verification-failed");
|
|
201851
|
+
if (verification.pending > 0) reasons.push("verification-pending");
|
|
201852
|
+
if (ledger.risks.length > 0) reasons.push("open-risks");
|
|
201853
|
+
if (ledger.status === "blocked") reasons.push("task-blocked");
|
|
201854
|
+
if (ledger.status === "abandoned") reasons.push("task-abandoned");
|
|
201855
|
+
if (ledger.status === "blocked" || ledger.status === "abandoned" || verification.failed > 0) {
|
|
201856
|
+
return {
|
|
201857
|
+
state: "at-risk",
|
|
201858
|
+
score: verification.passed > verification.failed ? 0.55 : 0.2,
|
|
201859
|
+
verification,
|
|
201860
|
+
reasons
|
|
201861
|
+
};
|
|
201862
|
+
}
|
|
201863
|
+
if (ledger.status === "completed") {
|
|
201864
|
+
if (verification.passed > 0 && verification.pending === 0 && verification.skipped === 0) {
|
|
201865
|
+
return {
|
|
201866
|
+
state: ledger.risks.length > 0 ? "validated-with-risks" : "validated",
|
|
201867
|
+
score: ledger.risks.length > 0 ? 0.8 : 1,
|
|
201868
|
+
verification,
|
|
201869
|
+
reasons: reasons.length > 0 ? reasons : ["verification-passed"]
|
|
201870
|
+
};
|
|
201871
|
+
}
|
|
201872
|
+
return {
|
|
201873
|
+
state: "unverified",
|
|
201874
|
+
score: 0.4,
|
|
201875
|
+
verification,
|
|
201876
|
+
reasons: reasons.length > 0 ? reasons : ["no-passing-verification"]
|
|
201877
|
+
};
|
|
201878
|
+
}
|
|
201879
|
+
return {
|
|
201880
|
+
state: "in-progress",
|
|
201881
|
+
score: verification.passed > 0 && verification.pending === 0 ? 0.75 : 0.5,
|
|
201882
|
+
verification,
|
|
201883
|
+
reasons: reasons.length > 0 ? reasons : ["task-open"]
|
|
201884
|
+
};
|
|
201885
|
+
}
|
|
201886
|
+
function rowToEvent4(row) {
|
|
201887
|
+
const status = row.item_status ? String(row.item_status) : void 0;
|
|
201888
|
+
return {
|
|
201889
|
+
id: String(row.id),
|
|
201890
|
+
projectId: String(row.project_id),
|
|
201891
|
+
taskId: String(row.task_id),
|
|
201892
|
+
task: clean(String(row.task), MAX_TASK_LENGTH),
|
|
201893
|
+
kind: row.kind,
|
|
201894
|
+
content: clean(String(row.content)),
|
|
201895
|
+
...status ? { status } : {},
|
|
201896
|
+
...row.source_ref ? { sourceRef: clean(String(row.source_ref), 500) } : {},
|
|
201897
|
+
evidenceRefs: parseRefs(row.evidence_json),
|
|
201898
|
+
...row.actor ? { actor: clean(String(row.actor), 200) } : {},
|
|
201899
|
+
at: String(row.created_at),
|
|
201900
|
+
...row.event_key ? { eventKey: clean(String(row.event_key), 200) } : {},
|
|
201901
|
+
...row.item_key ? { itemKey: clean(String(row.item_key), 120) } : {},
|
|
201902
|
+
...row.supersedes_id ? { supersedesId: clean(String(row.supersedes_id), 120) } : {}
|
|
201903
|
+
};
|
|
201904
|
+
}
|
|
201905
|
+
function aggregate(events) {
|
|
201906
|
+
const first2 = events.find((event) => event.kind === "task") ?? events[0];
|
|
201907
|
+
const latestOutcome = [...events].reverse().find((event) => event.kind === "outcome");
|
|
201908
|
+
const verificationByKey = /* @__PURE__ */ new Map();
|
|
201909
|
+
for (const event of events.filter((event2) => event2.kind === "verification")) {
|
|
201910
|
+
verificationByKey.set(event.itemKey ?? `event:${event.id}`, event);
|
|
201911
|
+
}
|
|
201912
|
+
const ledger = {
|
|
201913
|
+
taskId: first2.taskId,
|
|
201914
|
+
projectId: first2.projectId,
|
|
201915
|
+
task: first2.task,
|
|
201916
|
+
status: latestOutcome?.status ?? "open",
|
|
201917
|
+
requirements: events.filter((event) => event.kind === "requirement").map((event) => event.content),
|
|
201918
|
+
decisions: events.filter((event) => event.kind === "decision").map((event) => event.content),
|
|
201919
|
+
verification: [...verificationByKey.values()].map((event) => ({
|
|
201920
|
+
id: event.itemKey ?? event.id,
|
|
201921
|
+
content: event.content,
|
|
201922
|
+
status: event.status ?? "pending",
|
|
201923
|
+
...event.sourceRef ? { sourceRef: event.sourceRef } : {},
|
|
201924
|
+
evidenceRefs: event.evidenceRefs
|
|
201925
|
+
})),
|
|
201926
|
+
risks: events.filter((event) => event.kind === "risk").map((event) => event.content),
|
|
201927
|
+
outcomes: events.filter((event) => event.kind === "outcome").map((event) => event.content),
|
|
201928
|
+
updatedAt: events[events.length - 1].at,
|
|
201929
|
+
events
|
|
201930
|
+
};
|
|
201931
|
+
return { ...ledger, outcome: evaluateTaskContinuity(ledger) };
|
|
201932
|
+
}
|
|
201933
|
+
var TASK_CONTINUITY_EVENT_KINDS, MAX_TEXT_LENGTH2, MAX_TASK_LENGTH, MAX_LIST_ITEMS2, MAX_EVIDENCE_REFS, MAX_EVENTS_PER_TASK, TaskContinuityStore;
|
|
201934
|
+
var init_task_continuity = __esm({
|
|
201935
|
+
"src/knowledge/task-continuity.ts"() {
|
|
201936
|
+
"use strict";
|
|
201937
|
+
init_esm_shims();
|
|
201938
|
+
init_secret_filter();
|
|
201939
|
+
init_sqlite_db();
|
|
201940
|
+
TASK_CONTINUITY_EVENT_KINDS = [
|
|
201941
|
+
"task",
|
|
201942
|
+
"requirement",
|
|
201943
|
+
"decision",
|
|
201944
|
+
"verification",
|
|
201945
|
+
"risk",
|
|
201946
|
+
"outcome"
|
|
201947
|
+
];
|
|
201948
|
+
MAX_TEXT_LENGTH2 = 2e3;
|
|
201949
|
+
MAX_TASK_LENGTH = 1e3;
|
|
201950
|
+
MAX_LIST_ITEMS2 = 8;
|
|
201951
|
+
MAX_EVIDENCE_REFS = 8;
|
|
201952
|
+
MAX_EVENTS_PER_TASK = 200;
|
|
201953
|
+
TaskContinuityStore = class {
|
|
201954
|
+
db = null;
|
|
201955
|
+
async init(dataDir) {
|
|
201956
|
+
this.db = getDatabase(dataDir);
|
|
201957
|
+
}
|
|
201958
|
+
requireDb() {
|
|
201959
|
+
if (!this.db) throw new Error("TaskContinuityStore is not initialized.");
|
|
201960
|
+
return this.db;
|
|
201961
|
+
}
|
|
201962
|
+
insert(input) {
|
|
201963
|
+
const db2 = this.requireDb();
|
|
201964
|
+
const projectId = clean(input.projectId, 500);
|
|
201965
|
+
const taskId = clean(input.taskId, 120);
|
|
201966
|
+
const eventKey = input.eventKey ? clean(input.eventKey, 200) : void 0;
|
|
201967
|
+
if (eventKey) {
|
|
201968
|
+
const existing = db2.prepare(
|
|
201969
|
+
"SELECT * FROM task_continuity_events WHERE project_id = ? AND task_id = ? AND event_key = ?"
|
|
201970
|
+
).get(projectId, taskId, eventKey);
|
|
201971
|
+
if (existing) return rowToEvent4(existing);
|
|
201972
|
+
}
|
|
201973
|
+
const existingCount = db2.prepare(
|
|
201974
|
+
"SELECT COUNT(*) AS count FROM task_continuity_events WHERE project_id = ? AND task_id = ?"
|
|
201975
|
+
).get(projectId, taskId);
|
|
201976
|
+
if (Number(existingCount?.count ?? 0) >= MAX_EVENTS_PER_TASK) {
|
|
201977
|
+
throw new Error("Task continuity ledger reached its 200-event limit.");
|
|
201978
|
+
}
|
|
201979
|
+
const event = {
|
|
201980
|
+
id: randomUUID18(),
|
|
201981
|
+
projectId,
|
|
201982
|
+
taskId,
|
|
201983
|
+
task: clean(input.task, MAX_TASK_LENGTH),
|
|
201984
|
+
kind: input.kind,
|
|
201985
|
+
content: clean(input.content),
|
|
201986
|
+
...input.status ? { status: input.status } : {},
|
|
201987
|
+
...input.sourceRef ? { sourceRef: clean(input.sourceRef, 500) } : {},
|
|
201988
|
+
evidenceRefs: cleanList(input.evidenceRefs, 500).slice(0, MAX_EVIDENCE_REFS),
|
|
201989
|
+
...input.actor ? { actor: clean(input.actor, 200) } : {},
|
|
201990
|
+
at: input.at ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
201991
|
+
...eventKey ? { eventKey } : {},
|
|
201992
|
+
...input.itemKey ? { itemKey: clean(input.itemKey, 120) } : {},
|
|
201993
|
+
...input.supersedesId ? { supersedesId: clean(input.supersedesId, 120) } : {}
|
|
201994
|
+
};
|
|
201995
|
+
db2.prepare(`
|
|
201996
|
+
INSERT INTO task_continuity_events (
|
|
201997
|
+
id, project_id, task_id, task, kind, content, item_status,
|
|
201998
|
+
source_ref, evidence_json, actor, created_at, event_key, item_key, supersedes_id
|
|
201999
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
202000
|
+
`).run(
|
|
202001
|
+
event.id,
|
|
202002
|
+
event.projectId,
|
|
202003
|
+
event.taskId,
|
|
202004
|
+
event.task,
|
|
202005
|
+
event.kind,
|
|
202006
|
+
event.content,
|
|
202007
|
+
event.status ?? null,
|
|
202008
|
+
event.sourceRef ?? null,
|
|
202009
|
+
JSON.stringify(event.evidenceRefs),
|
|
202010
|
+
event.actor ?? null,
|
|
202011
|
+
event.at,
|
|
202012
|
+
event.eventKey ?? null,
|
|
202013
|
+
event.itemKey ?? null,
|
|
202014
|
+
event.supersedesId ?? null
|
|
202015
|
+
);
|
|
202016
|
+
return event;
|
|
202017
|
+
}
|
|
202018
|
+
start(input) {
|
|
202019
|
+
const task = clean(input.task, MAX_TASK_LENGTH);
|
|
202020
|
+
if (!task) throw new Error("A non-empty task is required.");
|
|
202021
|
+
const idempotencyKey = input.idempotencyKey ? clean(input.idempotencyKey, 200) : void 0;
|
|
202022
|
+
const taskId = clean(input.taskId ?? idempotencyKey ?? "", 120) || randomUUID18();
|
|
202023
|
+
const requirements = cleanList(input.requirements);
|
|
202024
|
+
const transaction = this.requireDb().transaction(() => {
|
|
202025
|
+
this.insert({
|
|
202026
|
+
projectId: input.projectId,
|
|
202027
|
+
taskId,
|
|
202028
|
+
task,
|
|
202029
|
+
kind: "task",
|
|
202030
|
+
content: task,
|
|
202031
|
+
status: "open",
|
|
202032
|
+
actor: input.actor,
|
|
202033
|
+
...idempotencyKey ? { eventKey: `start:${idempotencyKey}` } : {}
|
|
202034
|
+
});
|
|
202035
|
+
for (const requirement of requirements) {
|
|
202036
|
+
this.insert({
|
|
202037
|
+
projectId: input.projectId,
|
|
202038
|
+
taskId,
|
|
202039
|
+
task,
|
|
202040
|
+
kind: "requirement",
|
|
202041
|
+
content: requirement,
|
|
202042
|
+
actor: input.actor
|
|
202043
|
+
});
|
|
202044
|
+
}
|
|
202045
|
+
});
|
|
202046
|
+
transaction.immediate();
|
|
202047
|
+
return { taskId, ledger: this.get(input.projectId, taskId) };
|
|
202048
|
+
}
|
|
202049
|
+
record(input) {
|
|
202050
|
+
const projectId = clean(input.projectId, 500);
|
|
202051
|
+
const taskId = clean(input.taskId, 120);
|
|
202052
|
+
const existing = this.get(projectId, taskId);
|
|
202053
|
+
if (!existing) throw new Error("Task continuity ledger not found: " + taskId);
|
|
202054
|
+
const transaction = this.requireDb().transaction(() => this.insert({
|
|
202055
|
+
projectId,
|
|
202056
|
+
taskId,
|
|
202057
|
+
task: existing.task,
|
|
202058
|
+
kind: input.kind,
|
|
202059
|
+
content: input.content,
|
|
202060
|
+
...input.kind === "verification" && input.verificationStatus ? { status: input.verificationStatus } : {},
|
|
202061
|
+
sourceRef: input.sourceRef,
|
|
202062
|
+
evidenceRefs: input.evidenceRefs,
|
|
202063
|
+
actor: input.actor,
|
|
202064
|
+
at: input.at,
|
|
202065
|
+
...input.idempotencyKey ? { eventKey: input.idempotencyKey } : {},
|
|
202066
|
+
...input.verificationId ? { itemKey: input.verificationId } : {}
|
|
202067
|
+
}));
|
|
202068
|
+
const event = transaction.immediate();
|
|
202069
|
+
return { event, ledger: this.get(projectId, taskId) };
|
|
202070
|
+
}
|
|
202071
|
+
close(input) {
|
|
202072
|
+
const projectId = clean(input.projectId, 500);
|
|
202073
|
+
const taskId = clean(input.taskId, 120);
|
|
202074
|
+
const existing = this.get(projectId, taskId);
|
|
202075
|
+
if (!existing) throw new Error("Task continuity ledger not found: " + taskId);
|
|
202076
|
+
const transaction = this.requireDb().transaction(() => this.insert({
|
|
202077
|
+
projectId,
|
|
202078
|
+
taskId,
|
|
202079
|
+
task: existing.task,
|
|
202080
|
+
kind: "outcome",
|
|
202081
|
+
content: input.content,
|
|
202082
|
+
status: input.status,
|
|
202083
|
+
sourceRef: input.sourceRef,
|
|
202084
|
+
evidenceRefs: input.evidenceRefs,
|
|
202085
|
+
actor: input.actor,
|
|
202086
|
+
at: input.at,
|
|
202087
|
+
...input.idempotencyKey ? { eventKey: input.idempotencyKey } : {}
|
|
202088
|
+
}));
|
|
202089
|
+
const event = transaction.immediate();
|
|
202090
|
+
return { event, ledger: this.get(projectId, taskId) };
|
|
202091
|
+
}
|
|
202092
|
+
get(projectId, taskId) {
|
|
202093
|
+
const normalizedProjectId = clean(projectId, 500);
|
|
202094
|
+
const normalizedTaskId = clean(taskId, 120);
|
|
202095
|
+
const rows = this.requireDb().prepare(`
|
|
202096
|
+
SELECT * FROM task_continuity_events
|
|
202097
|
+
WHERE project_id = ? AND task_id = ?
|
|
202098
|
+
ORDER BY created_at ASC, rowid ASC
|
|
202099
|
+
`).all(normalizedProjectId, normalizedTaskId);
|
|
202100
|
+
if (rows.length === 0) return void 0;
|
|
202101
|
+
return aggregate(rows.map(rowToEvent4));
|
|
202102
|
+
}
|
|
202103
|
+
list(projectId, limit2 = 20) {
|
|
202104
|
+
const rows = this.requireDb().prepare(`
|
|
202105
|
+
SELECT task_id
|
|
202106
|
+
FROM task_continuity_events
|
|
202107
|
+
WHERE project_id = ?
|
|
202108
|
+
GROUP BY task_id
|
|
202109
|
+
ORDER BY MAX(created_at) DESC
|
|
202110
|
+
LIMIT ?
|
|
202111
|
+
`).all(projectId, Math.min(100, Math.max(1, Math.floor(limit2))));
|
|
202112
|
+
return rows.map((row) => this.get(projectId, String(row.task_id))).filter((ledger) => Boolean(ledger));
|
|
202113
|
+
}
|
|
202114
|
+
};
|
|
202115
|
+
}
|
|
202116
|
+
});
|
|
202117
|
+
|
|
201529
202118
|
// src/codegraph/auto-context.ts
|
|
201530
202119
|
var auto_context_exports = {};
|
|
201531
202120
|
__export(auto_context_exports, {
|
|
@@ -201782,6 +202371,16 @@ async function buildAutoProjectContext(input) {
|
|
|
201782
202371
|
};
|
|
201783
202372
|
}
|
|
201784
202373
|
}
|
|
202374
|
+
let continuity = input.continuity;
|
|
202375
|
+
if (!continuity && input.taskId) {
|
|
202376
|
+
try {
|
|
202377
|
+
const { TaskContinuityStore: TaskContinuityStore2 } = await Promise.resolve().then(() => (init_task_continuity(), task_continuity_exports));
|
|
202378
|
+
const continuityStore = new TaskContinuityStore2();
|
|
202379
|
+
await continuityStore.init(input.dataDir);
|
|
202380
|
+
continuity = continuityStore.get(input.project.id, input.taskId);
|
|
202381
|
+
} catch {
|
|
202382
|
+
}
|
|
202383
|
+
}
|
|
201785
202384
|
const alwaysOn = await buildAlwaysOnBlock({
|
|
201786
202385
|
dataDir: input.dataDir,
|
|
201787
202386
|
projectId: input.project.id,
|
|
@@ -201800,6 +202399,7 @@ async function buildAutoProjectContext(input) {
|
|
|
201800
202399
|
providerQuality: providerQuality2,
|
|
201801
202400
|
currentFacts: worksetFactLines(currentFacts),
|
|
201802
202401
|
...continuation ? { continuation } : {},
|
|
202402
|
+
...continuity ? { continuity } : {},
|
|
201803
202403
|
codeState: codeStateLine(overview),
|
|
201804
202404
|
...codeEvolution ? { codeEvolution } : {},
|
|
201805
202405
|
reliableMemory: sourceSets.reliableSources.slice(0, lens.sourceLimit).map((source) => ({
|
|
@@ -201847,6 +202447,7 @@ async function buildAutoProjectContext(input) {
|
|
|
201847
202447
|
refresh,
|
|
201848
202448
|
providerQuality: providerQuality2,
|
|
201849
202449
|
...continuationRequested && workset.continuation ? { continuation: workset.continuation } : {},
|
|
202450
|
+
...workset.continuity ? { continuity: workset.continuity } : {},
|
|
201850
202451
|
workset
|
|
201851
202452
|
};
|
|
201852
202453
|
}
|
|
@@ -202148,7 +202749,14 @@ function buildBoundedContextReceipt(input) {
|
|
|
202148
202749
|
externalState: provider2?.external.state ?? "not-detected",
|
|
202149
202750
|
...input.workset.provenance.snapshotId ? { snapshotId: input.workset.provenance.snapshotId } : {}
|
|
202150
202751
|
},
|
|
202151
|
-
...input.workset.agentLoadout ? { loadout: input.workset.agentLoadout } : {}
|
|
202752
|
+
...input.workset.agentLoadout ? { loadout: input.workset.agentLoadout } : {},
|
|
202753
|
+
...input.workset.continuity ? {
|
|
202754
|
+
continuity: {
|
|
202755
|
+
taskId: input.workset.continuity.taskId,
|
|
202756
|
+
status: input.workset.continuity.status,
|
|
202757
|
+
outcome: input.workset.continuity.outcome
|
|
202758
|
+
}
|
|
202759
|
+
} : {}
|
|
202152
202760
|
};
|
|
202153
202761
|
}
|
|
202154
202762
|
var init_context_receipt = __esm({
|
|
@@ -202159,10 +202767,10 @@ var init_context_receipt = __esm({
|
|
|
202159
202767
|
});
|
|
202160
202768
|
|
|
202161
202769
|
// src/cli/fallback-budget.ts
|
|
202162
|
-
import { createHash as
|
|
202770
|
+
import { createHash as createHash18 } from "crypto";
|
|
202163
202771
|
function fallbackRequestKey(projectId, task) {
|
|
202164
202772
|
const normalized = (task ?? "").trim().toLowerCase().replace(/\s+/g, " ");
|
|
202165
|
-
return
|
|
202773
|
+
return createHash18("sha256").update(`${projectId}
|
|
202166
202774
|
${normalized}`).digest("hex").slice(0, 32);
|
|
202167
202775
|
}
|
|
202168
202776
|
var DEFAULT_FALLBACK_TTL_MS, CliFallbackBudget;
|
|
@@ -202247,6 +202855,7 @@ var init_context2 = __esm({
|
|
|
202247
202855
|
},
|
|
202248
202856
|
args: {
|
|
202249
202857
|
task: { type: "string", description: "Current task for context shaping" },
|
|
202858
|
+
taskId: { type: "string", description: "Optional task continuity ledger id to include" },
|
|
202250
202859
|
input: {
|
|
202251
202860
|
type: "positional",
|
|
202252
202861
|
description: "Current task for context shaping (ergonomic positional form)",
|
|
@@ -202278,6 +202887,7 @@ var init_context2 = __esm({
|
|
|
202278
202887
|
dataDir,
|
|
202279
202888
|
observations: filterReadableObservations(getAllObservations(), reader2),
|
|
202280
202889
|
task,
|
|
202890
|
+
taskId: args.taskId?.trim() || void 0,
|
|
202281
202891
|
agent: coerceAgentTarget(args.agent),
|
|
202282
202892
|
refresh: coerceRefreshMode(args.refresh),
|
|
202283
202893
|
reader: reader2,
|
|
@@ -203780,6 +204390,158 @@ var init_feedback2 = __esm({
|
|
|
203780
204390
|
}
|
|
203781
204391
|
});
|
|
203782
204392
|
|
|
204393
|
+
// src/cli/commands/continuity.ts
|
|
204394
|
+
var continuity_exports = {};
|
|
204395
|
+
__export(continuity_exports, {
|
|
204396
|
+
default: () => continuity_default
|
|
204397
|
+
});
|
|
204398
|
+
var recordKinds, continuity_default;
|
|
204399
|
+
var init_continuity = __esm({
|
|
204400
|
+
"src/cli/commands/continuity.ts"() {
|
|
204401
|
+
"use strict";
|
|
204402
|
+
init_esm_shims();
|
|
204403
|
+
init_dist2();
|
|
204404
|
+
init_task_continuity();
|
|
204405
|
+
init_operator_shared();
|
|
204406
|
+
recordKinds = [
|
|
204407
|
+
"requirement",
|
|
204408
|
+
"decision",
|
|
204409
|
+
"verification",
|
|
204410
|
+
"risk"
|
|
204411
|
+
];
|
|
204412
|
+
continuity_default = defineCommand({
|
|
204413
|
+
meta: {
|
|
204414
|
+
name: "continuity",
|
|
204415
|
+
description: "Track task requirements, decisions, verification, risks, and outcomes"
|
|
204416
|
+
},
|
|
204417
|
+
args: {
|
|
204418
|
+
taskId: { type: "string", description: "Continuity task id" },
|
|
204419
|
+
task: { type: "string", description: "Task description for start" },
|
|
204420
|
+
requirements: { type: "string", description: "Comma-separated requirements for start" },
|
|
204421
|
+
kind: { type: "string", description: "requirement, decision, verification, or risk" },
|
|
204422
|
+
content: { type: "string", description: "Entry or outcome text" },
|
|
204423
|
+
verificationStatus: { type: "string", description: "pending, passed, failed, or skipped" },
|
|
204424
|
+
verificationId: { type: "string", description: "Stable verification obligation id for status transitions" },
|
|
204425
|
+
idempotencyKey: { type: "string", description: "Stable retry key for idempotent writes" },
|
|
204426
|
+
status: { type: "string", description: "completed, blocked, or abandoned for close" },
|
|
204427
|
+
source: { type: "string", description: "Source or evidence reference" },
|
|
204428
|
+
evidence: { type: "string", description: "Comma-separated evidence references" },
|
|
204429
|
+
actor: { type: "string", description: "Actor id or label" },
|
|
204430
|
+
limit: { type: "string", description: "Maximum ledgers for list" },
|
|
204431
|
+
json: { type: "boolean", description: "Emit machine-readable JSON output" }
|
|
204432
|
+
},
|
|
204433
|
+
run: async ({ args }) => {
|
|
204434
|
+
const action = args._?.[0] || "";
|
|
204435
|
+
const asJson = !!args.json;
|
|
204436
|
+
try {
|
|
204437
|
+
const { project, dataDir, identity } = await getCliProjectContext({ searchIndex: false });
|
|
204438
|
+
const store2 = new TaskContinuityStore();
|
|
204439
|
+
await store2.init(dataDir);
|
|
204440
|
+
const actor = String(args.actor || identity?.agentId || "").trim() || void 0;
|
|
204441
|
+
if (action === "start") {
|
|
204442
|
+
if (!args.task) {
|
|
204443
|
+
emitError('task is required for "memorix continuity start"', asJson);
|
|
204444
|
+
return;
|
|
204445
|
+
}
|
|
204446
|
+
const result = store2.start({
|
|
204447
|
+
projectId: project.id,
|
|
204448
|
+
task: String(args.task),
|
|
204449
|
+
...args.taskId ? { taskId: String(args.taskId) } : {},
|
|
204450
|
+
requirements: parseCsvList(args.requirements),
|
|
204451
|
+
...actor ? { actor } : {},
|
|
204452
|
+
...args.idempotencyKey ? { idempotencyKey: String(args.idempotencyKey) } : {}
|
|
204453
|
+
});
|
|
204454
|
+
emitResult({ project, ...result }, "Continuity started: " + result.taskId, asJson);
|
|
204455
|
+
return;
|
|
204456
|
+
}
|
|
204457
|
+
if (action === "list") {
|
|
204458
|
+
const ledgers = store2.list(project.id, Number(args.limit || 20));
|
|
204459
|
+
emitResult(
|
|
204460
|
+
{ project, ledgers },
|
|
204461
|
+
ledgers.length ? ledgers.map((item) => item.status + ": " + item.taskId + " " + item.task).join("\n") : "No continuity ledgers found.",
|
|
204462
|
+
asJson
|
|
204463
|
+
);
|
|
204464
|
+
return;
|
|
204465
|
+
}
|
|
204466
|
+
const taskId = String(args.taskId || "").trim();
|
|
204467
|
+
if (!taskId) {
|
|
204468
|
+
emitError("taskId is required for this continuity action.", asJson);
|
|
204469
|
+
return;
|
|
204470
|
+
}
|
|
204471
|
+
if (action === "show") {
|
|
204472
|
+
const ledger = store2.get(project.id, taskId);
|
|
204473
|
+
if (!ledger) {
|
|
204474
|
+
emitError("Task continuity ledger not found.", asJson);
|
|
204475
|
+
return;
|
|
204476
|
+
}
|
|
204477
|
+
emitResult({ project, ledger }, JSON.stringify(ledger, null, 2), asJson);
|
|
204478
|
+
return;
|
|
204479
|
+
}
|
|
204480
|
+
if (action === "record") {
|
|
204481
|
+
const kind = String(args.kind || "").trim();
|
|
204482
|
+
const content = String(args.content || "").trim();
|
|
204483
|
+
if (!recordKinds.includes(kind) || !content) {
|
|
204484
|
+
emitError("record requires --kind (requirement, decision, verification, risk) and --content.", asJson);
|
|
204485
|
+
return;
|
|
204486
|
+
}
|
|
204487
|
+
const verificationStatus = args.verificationStatus ? String(args.verificationStatus).trim() : void 0;
|
|
204488
|
+
if (verificationStatus && !["pending", "passed", "failed", "skipped"].includes(verificationStatus)) {
|
|
204489
|
+
emitError("verificationStatus must be pending, passed, failed, or skipped.", asJson);
|
|
204490
|
+
return;
|
|
204491
|
+
}
|
|
204492
|
+
const result = store2.record({
|
|
204493
|
+
projectId: project.id,
|
|
204494
|
+
taskId,
|
|
204495
|
+
kind,
|
|
204496
|
+
content,
|
|
204497
|
+
...verificationStatus ? { verificationStatus } : {},
|
|
204498
|
+
...args.source ? { sourceRef: String(args.source) } : {},
|
|
204499
|
+
evidenceRefs: parseCsvList(args.evidence),
|
|
204500
|
+
...actor ? { actor } : {},
|
|
204501
|
+
...args.verificationId ? { verificationId: String(args.verificationId) } : {},
|
|
204502
|
+
...args.idempotencyKey ? { idempotencyKey: String(args.idempotencyKey) } : {}
|
|
204503
|
+
});
|
|
204504
|
+
emitResult({ project, ...result }, "Continuity recorded: " + kind, asJson);
|
|
204505
|
+
return;
|
|
204506
|
+
}
|
|
204507
|
+
if (action === "close") {
|
|
204508
|
+
const status = String(args.status || "").trim();
|
|
204509
|
+
const content = String(args.content || "").trim();
|
|
204510
|
+
if (!["completed", "blocked", "abandoned"].includes(status) || !content) {
|
|
204511
|
+
emitError("close requires --status (completed, blocked, abandoned) and --content.", asJson);
|
|
204512
|
+
return;
|
|
204513
|
+
}
|
|
204514
|
+
const result = store2.close({
|
|
204515
|
+
projectId: project.id,
|
|
204516
|
+
taskId,
|
|
204517
|
+
status,
|
|
204518
|
+
content,
|
|
204519
|
+
...args.source ? { sourceRef: String(args.source) } : {},
|
|
204520
|
+
evidenceRefs: parseCsvList(args.evidence),
|
|
204521
|
+
...actor ? { actor } : {},
|
|
204522
|
+
...args.idempotencyKey ? { idempotencyKey: String(args.idempotencyKey) } : {}
|
|
204523
|
+
});
|
|
204524
|
+
emitResult({ project, ...result }, "Continuity closed: " + status, asJson);
|
|
204525
|
+
return;
|
|
204526
|
+
}
|
|
204527
|
+
console.log("Memorix Task Continuity");
|
|
204528
|
+
console.log("");
|
|
204529
|
+
console.log("Usage:");
|
|
204530
|
+
console.log(' memorix continuity start --task "..." [--requirements "a,b"]');
|
|
204531
|
+
console.log(' memorix continuity record --taskId <id> --kind decision --content "..."');
|
|
204532
|
+
console.log(' memorix continuity record --taskId <id> --kind verification --verificationStatus passed --content "..."');
|
|
204533
|
+
console.log(" Use --verificationId <id> to transition an existing verification obligation.");
|
|
204534
|
+
console.log(" memorix continuity show --taskId <id>");
|
|
204535
|
+
console.log(" memorix continuity list [--limit 20]");
|
|
204536
|
+
console.log(' memorix continuity close --taskId <id> --status completed --content "..."');
|
|
204537
|
+
} catch (error40) {
|
|
204538
|
+
emitError(error40 instanceof Error ? error40.message : String(error40), asJson);
|
|
204539
|
+
}
|
|
204540
|
+
}
|
|
204541
|
+
});
|
|
204542
|
+
}
|
|
204543
|
+
});
|
|
204544
|
+
|
|
203783
204545
|
// src/cli/commands/reasoning.ts
|
|
203784
204546
|
var reasoning_exports = {};
|
|
203785
204547
|
__export(reasoning_exports, {
|
|
@@ -206980,7 +207742,7 @@ __export(planner_exports, {
|
|
|
206980
207742
|
materializeTaskGraph: () => materializeTaskGraph,
|
|
206981
207743
|
seedAutonomousPipeline: () => seedAutonomousPipeline
|
|
206982
207744
|
});
|
|
206983
|
-
import { randomUUID as
|
|
207745
|
+
import { randomUUID as randomUUID19 } from "crypto";
|
|
206984
207746
|
function isPlannerTask(metadata) {
|
|
206985
207747
|
if (!metadata) return null;
|
|
206986
207748
|
try {
|
|
@@ -207038,7 +207800,7 @@ function seedAutonomousPipeline(teamStore, projectId, config2, opts) {
|
|
|
207038
207800
|
const maxIterations = config2.maxIterations ?? 3;
|
|
207039
207801
|
const taskBudget = config2.taskBudget ?? 15;
|
|
207040
207802
|
const structuredPlan = opts?.structuredPlan ?? true;
|
|
207041
|
-
const pipelineId =
|
|
207803
|
+
const pipelineId = randomUUID19();
|
|
207042
207804
|
const meta = {
|
|
207043
207805
|
plannerType: "plan",
|
|
207044
207806
|
pipelineId,
|
|
@@ -207957,11 +208719,11 @@ __export(receipt_service_exports, {
|
|
|
207957
208719
|
buildHandoffReceipt: () => buildHandoffReceipt,
|
|
207958
208720
|
formatHandoffReceipt: () => formatHandoffReceipt
|
|
207959
208721
|
});
|
|
207960
|
-
import { createHash as
|
|
208722
|
+
import { createHash as createHash19 } from "crypto";
|
|
207961
208723
|
import { existsSync as existsSync23, readFileSync as readFileSync15 } from "fs";
|
|
207962
208724
|
import path37 from "path";
|
|
207963
208725
|
function sha256(value) {
|
|
207964
|
-
return `sha256:${
|
|
208726
|
+
return `sha256:${createHash19("sha256").update(value).digest("hex")}`;
|
|
207965
208727
|
}
|
|
207966
208728
|
function hashId(projectId, id) {
|
|
207967
208729
|
return sha256(`${projectId}:obs:${id}`);
|
|
@@ -208194,6 +208956,7 @@ var init_tool_profile = __esm({
|
|
|
208194
208956
|
// keep the default micro profile at its nine-tool token budget.
|
|
208195
208957
|
memorix_evidence: ["lite", "team", "full"],
|
|
208196
208958
|
memorix_feedback: ["lite", "team", "full"],
|
|
208959
|
+
memorix_continuity: ["lite", "team", "full"],
|
|
208197
208960
|
// ── lite: extended solo memory surface ────────────────────────────
|
|
208198
208961
|
memorix_graph_context: ["lite", "team", "full"],
|
|
208199
208962
|
memorix_timeline: ["lite", "team", "full"],
|
|
@@ -208244,7 +209007,7 @@ var init_tool_profile = __esm({
|
|
|
208244
209007
|
function getMcpServerInfo() {
|
|
208245
209008
|
return {
|
|
208246
209009
|
name: "memorix",
|
|
208247
|
-
version: true ? "1.9.
|
|
209010
|
+
version: true ? "1.9.6" : "1.0.1"
|
|
208248
209011
|
};
|
|
208249
209012
|
}
|
|
208250
209013
|
function createMcpDiscoverResult(capabilities, serverInfo) {
|
|
@@ -215850,8 +216613,8 @@ var require_core = __commonJS({
|
|
|
215850
216613
|
return this;
|
|
215851
216614
|
}
|
|
215852
216615
|
case "object": {
|
|
215853
|
-
const
|
|
215854
|
-
this._cache.delete(
|
|
216616
|
+
const cacheKey4 = schemaKeyRef;
|
|
216617
|
+
this._cache.delete(cacheKey4);
|
|
215855
216618
|
let id = schemaKeyRef[this.opts.schemaId];
|
|
215856
216619
|
if (id) {
|
|
215857
216620
|
id = (0, resolve_1.normalizeId)(id);
|
|
@@ -221039,9 +221802,9 @@ var init_graph_scope = __esm({
|
|
|
221039
221802
|
});
|
|
221040
221803
|
|
|
221041
221804
|
// src/rules/utils.ts
|
|
221042
|
-
import { createHash as
|
|
221805
|
+
import { createHash as createHash20 } from "crypto";
|
|
221043
221806
|
function hashContent2(content) {
|
|
221044
|
-
return
|
|
221807
|
+
return createHash20("sha256").update(content.trim()).digest("hex").substring(0, 16);
|
|
221045
221808
|
}
|
|
221046
221809
|
function generateRuleId(source, filePath) {
|
|
221047
221810
|
const sanitized = filePath.replace(/[\/\\]/g, "-").replace(/^\./, "");
|
|
@@ -222630,8 +223393,8 @@ function legacyBehavior(homeDir) {
|
|
|
222630
223393
|
function getBehaviorConfig(options = {}) {
|
|
222631
223394
|
const homeDir = options.homeDir ?? homedir34();
|
|
222632
223395
|
const projectRoot = options.projectRoot === void 0 ? detectProject()?.rootPath ?? null : options.projectRoot;
|
|
222633
|
-
const
|
|
222634
|
-
const cached2 = cache4.get(
|
|
223396
|
+
const cacheKey4 = `${homeDir}\0${projectRoot ?? ""}`;
|
|
223397
|
+
const cached2 = cache4.get(cacheKey4);
|
|
222635
223398
|
if (cached2) return cached2;
|
|
222636
223399
|
const legacy = legacyBehavior(homeDir);
|
|
222637
223400
|
let resolved = {};
|
|
@@ -222645,7 +223408,7 @@ function getBehaviorConfig(options = {}) {
|
|
|
222645
223408
|
autoCleanup: typeof resolved.autoCleanup === "boolean" ? resolved.autoCleanup : typeof legacy.autoCleanup === "boolean" ? legacy.autoCleanup : DEFAULTS.autoCleanup,
|
|
222646
223409
|
formationMode: isFormationMode(resolved.formation) ? resolved.formation : isFormationMode(legacy.formationMode) ? legacy.formationMode : DEFAULTS.formationMode
|
|
222647
223410
|
};
|
|
222648
|
-
cache4.set(
|
|
223411
|
+
cache4.set(cacheKey4, config2);
|
|
222649
223412
|
return config2;
|
|
222650
223413
|
}
|
|
222651
223414
|
function resetBehaviorConfigCache() {
|
|
@@ -264676,7 +265439,7 @@ __export(server_exports2, {
|
|
|
264676
265439
|
createMemorixServer: () => createMemorixServer,
|
|
264677
265440
|
shouldAwaitProjectRuntime: () => shouldAwaitProjectRuntime
|
|
264678
265441
|
});
|
|
264679
|
-
import { createHash as
|
|
265442
|
+
import { createHash as createHash21 } from "crypto";
|
|
264680
265443
|
function formatFormationStageDurations(stageDurationsMs) {
|
|
264681
265444
|
const orderedStages = ["extract", "resolve", "evaluate"];
|
|
264682
265445
|
const parts = orderedStages.filter((stage) => stageDurationsMs[stage] !== void 0).map((stage) => `${stage}=${stageDurationsMs[stage]}ms`);
|
|
@@ -264758,7 +265521,7 @@ function coerceObjectArray(val) {
|
|
|
264758
265521
|
return [];
|
|
264759
265522
|
}
|
|
264760
265523
|
function createDeterministicInstanceId(projectId, agentType, agentName) {
|
|
264761
|
-
const digest2 =
|
|
265524
|
+
const digest2 = createHash21("sha256").update(projectId).update("\n").update(agentType).update("\n").update(agentName ?? "").digest("hex").slice(0, 24);
|
|
264762
265525
|
return `auto-${digest2}`;
|
|
264763
265526
|
}
|
|
264764
265527
|
function shouldAwaitProjectRuntime(toolName) {
|
|
@@ -264965,6 +265728,22 @@ async function createMemorixServer(cwd, existingServer, sharedTeam, options = {}
|
|
|
264965
265728
|
}
|
|
264966
265729
|
await projectRuntimeInitPromise;
|
|
264967
265730
|
};
|
|
265731
|
+
const activateProjectRuntime = async () => {
|
|
265732
|
+
if (!projectResolved) return;
|
|
265733
|
+
await initObservationStore(projectDir2);
|
|
265734
|
+
await initMiniSkillStore(projectDir2);
|
|
265735
|
+
await initSessionStore(projectDir2);
|
|
265736
|
+
await initObservations(projectDir2, { skipCorpusLoad: true });
|
|
265737
|
+
try {
|
|
265738
|
+
const { initProjectRoot: initProjectRoot2 } = await Promise.resolve().then(() => (init_yaml_loader(), yaml_loader_exports));
|
|
265739
|
+
const { resetDotenv: resetDotenv2, loadDotenv: loadDotenv2 } = await Promise.resolve().then(() => (init_dotenv_loader(), dotenv_loader_exports));
|
|
265740
|
+
initProjectRoot2(project.rootPath);
|
|
265741
|
+
resetDotenv2();
|
|
265742
|
+
loadDotenv2(project.rootPath);
|
|
265743
|
+
} catch {
|
|
265744
|
+
}
|
|
265745
|
+
initLLM({ projectRoot: project.rootPath });
|
|
265746
|
+
};
|
|
264968
265747
|
let maintenanceWorker = null;
|
|
264969
265748
|
const startProjectMaintenanceWorker = async (autoCleanup = false) => {
|
|
264970
265749
|
maintenanceWorker?.stop();
|
|
@@ -265880,6 +266659,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
265880
266659
|
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.",
|
|
265881
266660
|
inputSchema: {
|
|
265882
266661
|
task: external_exports2.string().optional().describe("Current coding task or question"),
|
|
266662
|
+
taskId: external_exports2.string().max(120).optional().describe("Optional task continuity ledger id to include in the brief"),
|
|
265883
266663
|
refresh: external_exports2.enum(["auto", "always", "never"]).optional().default("auto").describe(
|
|
265884
266664
|
"Code Memory refresh policy. auto refreshes only when missing or stale."
|
|
265885
266665
|
),
|
|
@@ -265904,7 +266684,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
265904
266684
|
limit: external_exports2.number().optional().describe("Reserved for future source limits; current prompt stays compact by default.")
|
|
265905
266685
|
}
|
|
265906
266686
|
},
|
|
265907
|
-
async ({ task, refresh, format, agent }) => {
|
|
266687
|
+
async ({ task, taskId, refresh, format, agent }) => {
|
|
265908
266688
|
const unresolved = requireResolvedProject("build project context for the current project");
|
|
265909
266689
|
if (unresolved) return unresolved;
|
|
265910
266690
|
const [
|
|
@@ -265934,6 +266714,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
265934
266714
|
dataDir: projectDir2,
|
|
265935
266715
|
observations: observations2,
|
|
265936
266716
|
task,
|
|
266717
|
+
taskId,
|
|
265937
266718
|
agent,
|
|
265938
266719
|
refresh: refresh ?? "auto",
|
|
265939
266720
|
reader: getObservationReader(),
|
|
@@ -268359,6 +269140,94 @@ ${json4}
|
|
|
268359
269140
|
}
|
|
268360
269141
|
}
|
|
268361
269142
|
);
|
|
269143
|
+
server.registerTool(
|
|
269144
|
+
"memorix_continuity",
|
|
269145
|
+
{
|
|
269146
|
+
title: "Task Continuity Ledger",
|
|
269147
|
+
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.",
|
|
269148
|
+
inputSchema: {
|
|
269149
|
+
action: external_exports2.enum(["start", "record", "show", "list", "close"]).describe("Continuity operation"),
|
|
269150
|
+
taskId: external_exports2.string().max(120).optional().describe("Continuity task id"),
|
|
269151
|
+
task: external_exports2.string().max(1e3).optional().describe("Task description for start"),
|
|
269152
|
+
requirements: external_exports2.array(external_exports2.string().max(2e3)).max(8).optional().describe("Requirements for start"),
|
|
269153
|
+
kind: external_exports2.enum(["requirement", "decision", "verification", "risk"]).optional().describe("Entry kind for record"),
|
|
269154
|
+
content: external_exports2.string().max(2e3).optional().describe("Requirement, decision, verification, risk, or outcome text"),
|
|
269155
|
+
verificationStatus: external_exports2.enum(["pending", "passed", "failed", "skipped"]).optional(),
|
|
269156
|
+
verificationId: external_exports2.string().max(120).optional().describe("Stable verification obligation id; reuse it to move pending to passed/failed"),
|
|
269157
|
+
idempotencyKey: external_exports2.string().max(200).optional().describe("Stable retry key; repeating the same operation returns the original event"),
|
|
269158
|
+
status: external_exports2.enum(["completed", "blocked", "abandoned"]).optional().describe("Outcome status for close"),
|
|
269159
|
+
sourceRef: external_exports2.string().max(500).optional().describe("Evidence or source reference"),
|
|
269160
|
+
evidenceRefs: external_exports2.array(external_exports2.string().max(500)).max(8).optional(),
|
|
269161
|
+
actor: external_exports2.string().max(200).optional(),
|
|
269162
|
+
limit: external_exports2.number().int().positive().max(100).optional().default(20)
|
|
269163
|
+
}
|
|
269164
|
+
},
|
|
269165
|
+
async ({ action, taskId, task, requirements, kind, content, verificationStatus, verificationId, idempotencyKey, status, sourceRef, evidenceRefs: evidenceRefs2, actor, limit: limit2 }) => {
|
|
269166
|
+
const unresolved = requireResolvedProject("manage task continuity for the current project");
|
|
269167
|
+
if (unresolved) return unresolved;
|
|
269168
|
+
const { TaskContinuityStore: TaskContinuityStore2 } = await Promise.resolve().then(() => (init_task_continuity(), task_continuity_exports));
|
|
269169
|
+
const continuity = new TaskContinuityStore2();
|
|
269170
|
+
await continuity.init(projectDir2);
|
|
269171
|
+
const effectiveActor = actor ?? currentAgentId;
|
|
269172
|
+
try {
|
|
269173
|
+
if (action === "start") {
|
|
269174
|
+
if (!task?.trim()) return { content: [{ type: "text", text: "task is required for continuity start." }], isError: true };
|
|
269175
|
+
const result2 = continuity.start({
|
|
269176
|
+
projectId: project.id,
|
|
269177
|
+
task,
|
|
269178
|
+
...taskId ? { taskId } : {},
|
|
269179
|
+
requirements,
|
|
269180
|
+
...effectiveActor ? { actor: effectiveActor } : {},
|
|
269181
|
+
...idempotencyKey ? { idempotencyKey } : {}
|
|
269182
|
+
});
|
|
269183
|
+
return { content: [{ type: "text", text: JSON.stringify({ projectId: project.id, ...result2 }, null, 2) }] };
|
|
269184
|
+
}
|
|
269185
|
+
if (action === "list") {
|
|
269186
|
+
return { content: [{ type: "text", text: JSON.stringify({ projectId: project.id, ledgers: continuity.list(project.id, limit2) }, null, 2) }] };
|
|
269187
|
+
}
|
|
269188
|
+
if (!taskId?.trim()) return { content: [{ type: "text", text: "taskId is required for this continuity action." }], isError: true };
|
|
269189
|
+
if (action === "show") {
|
|
269190
|
+
const ledger = continuity.get(project.id, taskId);
|
|
269191
|
+
if (!ledger) return { content: [{ type: "text", text: "Task continuity ledger not found." }], isError: true };
|
|
269192
|
+
return { content: [{ type: "text", text: JSON.stringify({ projectId: project.id, ledger }, null, 2) }] };
|
|
269193
|
+
}
|
|
269194
|
+
if (action === "record") {
|
|
269195
|
+
if (!kind || !content?.trim()) {
|
|
269196
|
+
return { content: [{ type: "text", text: "record requires kind and content." }], isError: true };
|
|
269197
|
+
}
|
|
269198
|
+
const result2 = continuity.record({
|
|
269199
|
+
projectId: project.id,
|
|
269200
|
+
taskId,
|
|
269201
|
+
kind,
|
|
269202
|
+
content,
|
|
269203
|
+
...verificationStatus ? { verificationStatus } : {},
|
|
269204
|
+
...sourceRef ? { sourceRef } : {},
|
|
269205
|
+
...evidenceRefs2 ? { evidenceRefs: evidenceRefs2 } : {},
|
|
269206
|
+
...effectiveActor ? { actor: effectiveActor } : {},
|
|
269207
|
+
...verificationId ? { verificationId } : {},
|
|
269208
|
+
...idempotencyKey ? { idempotencyKey } : {}
|
|
269209
|
+
});
|
|
269210
|
+
return { content: [{ type: "text", text: JSON.stringify({ projectId: project.id, ...result2 }, null, 2) }] };
|
|
269211
|
+
}
|
|
269212
|
+
if (!status || !content?.trim()) {
|
|
269213
|
+
return { content: [{ type: "text", text: "close requires status and content." }], isError: true };
|
|
269214
|
+
}
|
|
269215
|
+
const result = continuity.close({
|
|
269216
|
+
projectId: project.id,
|
|
269217
|
+
taskId,
|
|
269218
|
+
status,
|
|
269219
|
+
content,
|
|
269220
|
+
...sourceRef ? { sourceRef } : {},
|
|
269221
|
+
...evidenceRefs2 ? { evidenceRefs: evidenceRefs2 } : {},
|
|
269222
|
+
...effectiveActor ? { actor: effectiveActor } : {},
|
|
269223
|
+
...idempotencyKey ? { idempotencyKey } : {}
|
|
269224
|
+
});
|
|
269225
|
+
return { content: [{ type: "text", text: JSON.stringify({ projectId: project.id, ...result }, null, 2) }] };
|
|
269226
|
+
} catch (error40) {
|
|
269227
|
+
return { content: [{ type: "text", text: error40 instanceof Error ? error40.message : String(error40) }], isError: true };
|
|
269228
|
+
}
|
|
269229
|
+
}
|
|
269230
|
+
);
|
|
268362
269231
|
if (teamFeaturesEnabled) {
|
|
268363
269232
|
const { initTeamStore: initTeamStore2 } = await Promise.resolve().then(() => (init_team_store(), team_store_exports));
|
|
268364
269233
|
initTeamStoreForProject = initTeamStore2;
|
|
@@ -269386,7 +270255,9 @@ fi
|
|
|
269386
270255
|
graphManager,
|
|
269387
270256
|
projectId: project.id,
|
|
269388
270257
|
deferredInit,
|
|
270258
|
+
activateProjectRuntime,
|
|
269389
270259
|
switchProject,
|
|
270260
|
+
getProjectDataDir: () => projectDir2,
|
|
269390
270261
|
isExplicitlyBound: () => projectBinding.isExplicit(),
|
|
269391
270262
|
getRequestContext,
|
|
269392
270263
|
handleTransportClose
|
|
@@ -269462,13 +270333,21 @@ var init_server4 = __esm({
|
|
|
269462
270333
|
// src/server/modern-mcp-bridge.ts
|
|
269463
270334
|
var modern_mcp_bridge_exports = {};
|
|
269464
270335
|
__export(modern_mcp_bridge_exports, {
|
|
269465
|
-
|
|
270336
|
+
ModernMcpRuntimePool: () => ModernMcpRuntimePool,
|
|
270337
|
+
createModernMcpBridge: () => createModernMcpBridge,
|
|
270338
|
+
createModernMcpRuntime: () => createModernMcpRuntime,
|
|
270339
|
+
withBusinessRuntimeQueue: () => withBusinessRuntimeQueue
|
|
269466
270340
|
});
|
|
269467
270341
|
import {
|
|
269468
270342
|
fromJsonSchema,
|
|
269469
270343
|
McpServer as ModernMcpServer
|
|
269470
270344
|
} from "@modelcontextprotocol/server";
|
|
269471
|
-
|
|
270345
|
+
function withBusinessRuntimeQueue(work) {
|
|
270346
|
+
const result = businessRuntimeQueue.then(work);
|
|
270347
|
+
businessRuntimeQueue = result.catch(() => void 0);
|
|
270348
|
+
return result;
|
|
270349
|
+
}
|
|
270350
|
+
async function createModernMcpRuntime(options) {
|
|
269472
270351
|
const { createMemorixServer: createMemorixServer2 } = await Promise.resolve().then(() => (init_server4(), server_exports2));
|
|
269473
270352
|
const legacy = await createMemorixServer2(
|
|
269474
270353
|
options.projectRoot,
|
|
@@ -269489,41 +270368,62 @@ async function createModernMcpBridge(options) {
|
|
|
269489
270368
|
await legacy.server.connect(serverTransport);
|
|
269490
270369
|
await legacyClient.connect(clientTransport);
|
|
269491
270370
|
const listed = await legacyClient.listTools();
|
|
269492
|
-
const
|
|
269493
|
-
|
|
269494
|
-
|
|
269495
|
-
|
|
269496
|
-
|
|
269497
|
-
...tool.title ? { title: tool.title } : {},
|
|
269498
|
-
...tool.description ? { description: tool.description } : {},
|
|
269499
|
-
inputSchema: fromJsonSchema(tool.inputSchema)
|
|
269500
|
-
},
|
|
269501
|
-
async (args) => await legacyClient.callTool({
|
|
269502
|
-
name: tool.name,
|
|
269503
|
-
arguments: args
|
|
269504
|
-
})
|
|
269505
|
-
);
|
|
269506
|
-
}
|
|
269507
|
-
const bridge = modern;
|
|
269508
|
-
bridge.memorix = {
|
|
270371
|
+
const callTool = (name, args) => withBusinessRuntimeQueue(async () => {
|
|
270372
|
+
await legacy.activateProjectRuntime();
|
|
270373
|
+
return await legacyClient.callTool({ name, arguments: args });
|
|
270374
|
+
});
|
|
270375
|
+
const lifecycle = {
|
|
269509
270376
|
projectId: legacy.projectId,
|
|
269510
270377
|
deferredInit: legacy.deferredInit,
|
|
270378
|
+
activateProjectRuntime: legacy.activateProjectRuntime,
|
|
269511
270379
|
switchProject: legacy.switchProject,
|
|
270380
|
+
getProjectDataDir: legacy.getProjectDataDir,
|
|
269512
270381
|
isExplicitlyBound: legacy.isExplicitlyBound,
|
|
269513
270382
|
handleTransportClose: legacy.handleTransportClose
|
|
269514
270383
|
};
|
|
269515
270384
|
let closed = false;
|
|
269516
|
-
|
|
269517
|
-
|
|
270385
|
+
return {
|
|
270386
|
+
projectId: legacy.projectId,
|
|
270387
|
+
getProjectDataDir: legacy.getProjectDataDir,
|
|
270388
|
+
createBridge: () => {
|
|
270389
|
+
const requestServer = new ModernMcpServer(getMcpServerInfo());
|
|
270390
|
+
for (const tool of listed.tools) {
|
|
270391
|
+
requestServer.registerTool(
|
|
270392
|
+
tool.name,
|
|
270393
|
+
{
|
|
270394
|
+
...tool.title ? { title: tool.title } : {},
|
|
270395
|
+
...tool.description ? { description: tool.description } : {},
|
|
270396
|
+
inputSchema: fromJsonSchema(tool.inputSchema)
|
|
270397
|
+
},
|
|
270398
|
+
async (args) => await callTool(tool.name, args)
|
|
270399
|
+
);
|
|
270400
|
+
}
|
|
270401
|
+
requestServer.memorix = lifecycle;
|
|
270402
|
+
return requestServer;
|
|
270403
|
+
},
|
|
270404
|
+
close: async () => {
|
|
270405
|
+
if (closed) return;
|
|
270406
|
+
closed = true;
|
|
270407
|
+
await legacyClient.close().catch(() => void 0);
|
|
270408
|
+
await legacy.server.close().catch(() => void 0);
|
|
270409
|
+
legacy.handleTransportClose();
|
|
270410
|
+
}
|
|
270411
|
+
};
|
|
270412
|
+
}
|
|
270413
|
+
async function createModernMcpBridge(options) {
|
|
270414
|
+
const runtime = await createModernMcpRuntime(options);
|
|
270415
|
+
const bridge = runtime.createBridge();
|
|
270416
|
+
const close = bridge.close.bind(bridge);
|
|
270417
|
+
let closed = false;
|
|
270418
|
+
bridge.close = async () => {
|
|
269518
270419
|
if (closed) return;
|
|
269519
270420
|
closed = true;
|
|
269520
|
-
await
|
|
269521
|
-
await
|
|
269522
|
-
await legacy.server.close().catch(() => void 0);
|
|
269523
|
-
legacy.handleTransportClose();
|
|
270421
|
+
await close();
|
|
270422
|
+
await runtime.close();
|
|
269524
270423
|
};
|
|
269525
270424
|
return bridge;
|
|
269526
270425
|
}
|
|
270426
|
+
var businessRuntimeQueue, ModernMcpRuntimePool;
|
|
269527
270427
|
var init_modern_mcp_bridge = __esm({
|
|
269528
270428
|
"src/server/modern-mcp-bridge.ts"() {
|
|
269529
270429
|
"use strict";
|
|
@@ -269531,6 +270431,74 @@ var init_modern_mcp_bridge = __esm({
|
|
|
269531
270431
|
init_client4();
|
|
269532
270432
|
init_inMemory();
|
|
269533
270433
|
init_mcp_discovery();
|
|
270434
|
+
businessRuntimeQueue = Promise.resolve();
|
|
270435
|
+
ModernMcpRuntimePool = class {
|
|
270436
|
+
constructor(maxEntries = 32) {
|
|
270437
|
+
this.maxEntries = maxEntries;
|
|
270438
|
+
}
|
|
270439
|
+
maxEntries;
|
|
270440
|
+
entries = /* @__PURE__ */ new Map();
|
|
270441
|
+
pending = /* @__PURE__ */ new Map();
|
|
270442
|
+
async createBridge(key, create6) {
|
|
270443
|
+
let entry = this.entries.get(key);
|
|
270444
|
+
if (!entry) {
|
|
270445
|
+
let pending = this.pending.get(key);
|
|
270446
|
+
if (!pending) {
|
|
270447
|
+
pending = create6().then((runtime) => {
|
|
270448
|
+
const created = { runtime, refs: 0, lastUsedAt: Date.now() };
|
|
270449
|
+
this.entries.set(key, created);
|
|
270450
|
+
return created;
|
|
270451
|
+
});
|
|
270452
|
+
this.pending.set(key, pending);
|
|
270453
|
+
}
|
|
270454
|
+
try {
|
|
270455
|
+
entry = await pending;
|
|
270456
|
+
} finally {
|
|
270457
|
+
this.pending.delete(key);
|
|
270458
|
+
}
|
|
270459
|
+
}
|
|
270460
|
+
entry.refs++;
|
|
270461
|
+
entry.lastUsedAt = Date.now();
|
|
270462
|
+
const bridge = entry.runtime.createBridge();
|
|
270463
|
+
const close = bridge.close.bind(bridge);
|
|
270464
|
+
let released = false;
|
|
270465
|
+
bridge.close = async () => {
|
|
270466
|
+
try {
|
|
270467
|
+
await close();
|
|
270468
|
+
} finally {
|
|
270469
|
+
if (!released) {
|
|
270470
|
+
released = true;
|
|
270471
|
+
entry.refs = Math.max(0, entry.refs - 1);
|
|
270472
|
+
entry.lastUsedAt = Date.now();
|
|
270473
|
+
}
|
|
270474
|
+
}
|
|
270475
|
+
};
|
|
270476
|
+
return bridge;
|
|
270477
|
+
}
|
|
270478
|
+
async evictIdle() {
|
|
270479
|
+
let closed = 0;
|
|
270480
|
+
const idle = [...this.entries.entries()].filter(([, entry]) => entry.refs === 0).sort(([, left], [, right]) => left.lastUsedAt - right.lastUsedAt);
|
|
270481
|
+
for (const [key, entry] of idle) {
|
|
270482
|
+
if (this.entries.size <= this.maxEntries || entry.refs > 0) continue;
|
|
270483
|
+
this.entries.delete(key);
|
|
270484
|
+
await entry.runtime.close();
|
|
270485
|
+
closed++;
|
|
270486
|
+
}
|
|
270487
|
+
return closed;
|
|
270488
|
+
}
|
|
270489
|
+
async close() {
|
|
270490
|
+
const entries = [...this.entries.values()];
|
|
270491
|
+
this.entries.clear();
|
|
270492
|
+
await Promise.all(entries.map((entry) => entry.runtime.close().catch(() => void 0)));
|
|
270493
|
+
}
|
|
270494
|
+
stats() {
|
|
270495
|
+
return {
|
|
270496
|
+
entries: this.entries.size,
|
|
270497
|
+
activeRefs: [...this.entries.values()].reduce((sum, entry) => sum + entry.refs, 0),
|
|
270498
|
+
pending: this.pending.size
|
|
270499
|
+
};
|
|
270500
|
+
}
|
|
270501
|
+
};
|
|
269534
270502
|
}
|
|
269535
270503
|
});
|
|
269536
270504
|
|
|
@@ -270159,7 +271127,7 @@ function writeFromReadableStream(stream2, writable) {
|
|
|
270159
271127
|
else if (writable.destroyed) return;
|
|
270160
271128
|
return writeFromReadableStreamDefaultReader(stream2.getReader(), writable);
|
|
270161
271129
|
}
|
|
270162
|
-
var RequestError, reValidRequestUrl, reDotSegment, reValidHost, buildUrl, toRequestError, GlobalRequest, Request$1, newHeadersFromIncoming, wrapBodyStream, byteExactEncodings, isByteExactEncoding, bodyBufferedBeforeDisconnectKey, bodyBufferedLengthBeforeDisconnectKey, toBufferChunk, isRecoverableDisconnectedIncoming, recordBodyBufferedBeforeDisconnect, readBodyBufferedBeforeDisconnect, enqueueBufferedBody, newRequestFromIncoming, getRequestCache, requestCache, incomingKey, urlKey, methodKey, headersKey, abortControllerKey, getAbortController, abortRequest, bodyBufferKey, bodyReadPromiseKey, bodyConsumedDirectlyKey, bodyLockReaderKey, abortReasonKey, newBodyUnusableError, rejectBodyUnusable, textDecoder2, consumeBodyDirectOnce, toArrayBuffer, contentType, methodTokenRegExp, normalizeIncomingMethod, validateDirectReadMethod, readBodyWithFastPath, readRawBodyIfAvailable, normalizeAbortError, readBodyDirect, requestPrototype, newRequest, defaultContentType, responseCache, getResponseCache,
|
|
271130
|
+
var RequestError, reValidRequestUrl, reDotSegment, reValidHost, buildUrl, toRequestError, GlobalRequest, Request$1, newHeadersFromIncoming, wrapBodyStream, byteExactEncodings, isByteExactEncoding, bodyBufferedBeforeDisconnectKey, bodyBufferedLengthBeforeDisconnectKey, toBufferChunk, isRecoverableDisconnectedIncoming, recordBodyBufferedBeforeDisconnect, readBodyBufferedBeforeDisconnect, enqueueBufferedBody, newRequestFromIncoming, getRequestCache, requestCache, incomingKey, urlKey, methodKey, headersKey, abortControllerKey, getAbortController, abortRequest, bodyBufferKey, bodyReadPromiseKey, bodyConsumedDirectlyKey, bodyLockReaderKey, abortReasonKey, newBodyUnusableError, rejectBodyUnusable, textDecoder2, consumeBodyDirectOnce, toArrayBuffer, contentType, methodTokenRegExp, normalizeIncomingMethod, validateDirectReadMethod, readBodyWithFastPath, readRawBodyIfAvailable, normalizeAbortError, readBodyDirect, requestPrototype, newRequest, defaultContentType, responseCache, getResponseCache, cacheKey3, GlobalResponse, Response$1, validRedirectUrl, parseRedirectUrl, validRedirectStatuses, buildOutgoingHttpHeaders, outgoingEnded, incomingDraining, DRAIN_TIMEOUT_MS, MAX_DRAIN_BYTES, drainIncoming, makeCloseHandler, isImmediateCacheableResponse, handleRequestError, handleFetchError, handleResponseError, flushHeaders, responseViaCache, isPromise, responseViaResponseObject, getRequestListener, CloseEvent, ErrorEvent, generateConnectionSymbol, CONNECTION_SYMBOL_KEY, WAIT_FOR_WEBSOCKET_SYMBOL, upgradeWebSocket;
|
|
270163
271131
|
var init_dist8 = __esm({
|
|
270164
271132
|
"node_modules/@hono/node-server/dist/index.mjs"() {
|
|
270165
271133
|
"use strict";
|
|
@@ -270630,15 +271598,15 @@ var init_dist8 = __esm({
|
|
|
270630
271598
|
defaultContentType = "text/plain; charset=UTF-8";
|
|
270631
271599
|
responseCache = /* @__PURE__ */ Symbol("responseCache");
|
|
270632
271600
|
getResponseCache = /* @__PURE__ */ Symbol("getResponseCache");
|
|
270633
|
-
|
|
271601
|
+
cacheKey3 = /* @__PURE__ */ Symbol("cache");
|
|
270634
271602
|
GlobalResponse = global.Response;
|
|
270635
271603
|
Response$1 = class Response$12 {
|
|
270636
271604
|
#body;
|
|
270637
271605
|
#init;
|
|
270638
271606
|
[getResponseCache]() {
|
|
270639
|
-
const cache5 = this[
|
|
271607
|
+
const cache5 = this[cacheKey3];
|
|
270640
271608
|
const liveHeaders = cache5 && cache5[2] instanceof Headers ? cache5[2] : void 0;
|
|
270641
|
-
delete this[
|
|
271609
|
+
delete this[cacheKey3];
|
|
270642
271610
|
return this[responseCache] ||= new GlobalResponse(this.#body, liveHeaders ? {
|
|
270643
271611
|
status: this.#init?.status,
|
|
270644
271612
|
statusText: this.#init?.statusText,
|
|
@@ -270658,14 +271626,14 @@ var init_dist8 = __esm({
|
|
|
270658
271626
|
this.#init = init2 instanceof Response$12 ? init2.#init : init2;
|
|
270659
271627
|
headers = new Headers(init2.headers);
|
|
270660
271628
|
} else this.#init = init2;
|
|
270661
|
-
if (body == null || typeof body === "string" || typeof body?.getReader !== "undefined" || body instanceof Blob || body instanceof Uint8Array) this[
|
|
271629
|
+
if (body == null || typeof body === "string" || typeof body?.getReader !== "undefined" || body instanceof Blob || body instanceof Uint8Array) this[cacheKey3] = [
|
|
270662
271630
|
init2?.status || 200,
|
|
270663
271631
|
body ?? null,
|
|
270664
271632
|
headers || init2?.headers
|
|
270665
271633
|
];
|
|
270666
271634
|
}
|
|
270667
271635
|
get headers() {
|
|
270668
|
-
const cache5 = this[
|
|
271636
|
+
const cache5 = this[cacheKey3];
|
|
270669
271637
|
if (cache5) {
|
|
270670
271638
|
if (!(cache5[2] instanceof Headers)) cache5[2] = new Headers(cache5[2] || (cache5[1] === null ? void 0 : { "content-type": defaultContentType }));
|
|
270671
271639
|
return cache5[2];
|
|
@@ -270673,7 +271641,7 @@ var init_dist8 = __esm({
|
|
|
270673
271641
|
return this[getResponseCache]().headers;
|
|
270674
271642
|
}
|
|
270675
271643
|
get status() {
|
|
270676
|
-
return this[
|
|
271644
|
+
return this[cacheKey3]?.[0] ?? this[getResponseCache]().status;
|
|
270677
271645
|
}
|
|
270678
271646
|
get ok() {
|
|
270679
271647
|
const status = this.status;
|
|
@@ -270826,8 +271794,8 @@ var init_dist8 = __esm({
|
|
|
270826
271794
|
});
|
|
270827
271795
|
};
|
|
270828
271796
|
isImmediateCacheableResponse = (res) => {
|
|
270829
|
-
if (!(
|
|
270830
|
-
const body = res[
|
|
271797
|
+
if (!(cacheKey3 in res)) return false;
|
|
271798
|
+
const body = res[cacheKey3][1];
|
|
270831
271799
|
return body === null || typeof body === "string" || body instanceof Uint8Array;
|
|
270832
271800
|
};
|
|
270833
271801
|
handleRequestError = () => new Response(null, { status: 400 });
|
|
@@ -270846,7 +271814,7 @@ var init_dist8 = __esm({
|
|
|
270846
271814
|
if ("flushHeaders" in outgoing && outgoing.writable) outgoing.flushHeaders();
|
|
270847
271815
|
};
|
|
270848
271816
|
responseViaCache = async (res, outgoing) => {
|
|
270849
|
-
let [status, body, header] = res[
|
|
271817
|
+
let [status, body, header] = res[cacheKey3];
|
|
270850
271818
|
if (!header) {
|
|
270851
271819
|
if (body === null) {
|
|
270852
271820
|
outgoing.writeHead(status);
|
|
@@ -270914,7 +271882,7 @@ var init_dist8 = __esm({
|
|
|
270914
271882
|
res = errRes;
|
|
270915
271883
|
}
|
|
270916
271884
|
else res = await res.catch(handleFetchError);
|
|
270917
|
-
if (
|
|
271885
|
+
if (cacheKey3 in res) return responseViaCache(res, outgoing);
|
|
270918
271886
|
const resHeaderRecord = buildOutgoingHttpHeaders(res.headers, res.body === null ? void 0 : defaultContentType);
|
|
270919
271887
|
if (res.body) {
|
|
270920
271888
|
const reader2 = res.body.getReader();
|
|
@@ -272151,7 +273119,7 @@ __export(mcp_binding_store_exports, {
|
|
|
272151
273119
|
DEFAULT_MCP_BINDING_TTL_MS: () => DEFAULT_MCP_BINDING_TTL_MS,
|
|
272152
273120
|
McpBindingStore: () => McpBindingStore
|
|
272153
273121
|
});
|
|
272154
|
-
import { randomUUID as
|
|
273122
|
+
import { randomUUID as randomUUID20 } from "crypto";
|
|
272155
273123
|
function rowToBinding(row) {
|
|
272156
273124
|
return {
|
|
272157
273125
|
handleId: String(row.handle_id),
|
|
@@ -272183,7 +273151,7 @@ var init_mcp_binding_store = __esm({
|
|
|
272183
273151
|
const now3 = /* @__PURE__ */ new Date();
|
|
272184
273152
|
const ttlMs = input.ttlMs ?? DEFAULT_MCP_BINDING_TTL_MS;
|
|
272185
273153
|
const binding = {
|
|
272186
|
-
handleId: `mxh_${
|
|
273154
|
+
handleId: `mxh_${randomUUID20().replace(/-/g, "")}`,
|
|
272187
273155
|
projectId: input.projectId,
|
|
272188
273156
|
projectRoot: input.projectRoot,
|
|
272189
273157
|
dataDir: input.dataDir,
|
|
@@ -272310,10 +273278,14 @@ var init_control_plane_maintenance = __esm({
|
|
|
272310
273278
|
var serve_http_exports = {};
|
|
272311
273279
|
__export(serve_http_exports, {
|
|
272312
273280
|
DEFAULT_HTTP_BODY_LIMIT_BYTES: () => DEFAULT_HTTP_BODY_LIMIT_BYTES,
|
|
273281
|
+
DEFAULT_MAX_HTTP_SESSIONS: () => DEFAULT_MAX_HTTP_SESSIONS,
|
|
272313
273282
|
DEFAULT_SESSION_TIMEOUT_MS: () => DEFAULT_SESSION_TIMEOUT_MS,
|
|
272314
273283
|
EXPIRED_SESSION_TTL_MS: () => EXPIRED_SESSION_TTL_MS,
|
|
272315
273284
|
HttpPayloadTooLargeError: () => HttpPayloadTooLargeError,
|
|
272316
273285
|
MAX_HTTP_BODY_LIMIT_BYTES: () => MAX_HTTP_BODY_LIMIT_BYTES,
|
|
273286
|
+
MAX_HTTP_SESSIONS_LIMIT: () => MAX_HTTP_SESSIONS_LIMIT,
|
|
273287
|
+
MAX_PROJECT_CACHE_ENTRIES: () => MAX_PROJECT_CACHE_ENTRIES,
|
|
273288
|
+
MAX_STORE_CACHE_ENTRIES: () => MAX_STORE_CACHE_ENTRIES,
|
|
272317
273289
|
MCP_SDK_COMPAT_PROTOCOL_VERSION: () => MCP_SDK_COMPAT_PROTOCOL_VERSION,
|
|
272318
273290
|
MIN_HTTP_BODY_LIMIT_BYTES: () => MIN_HTTP_BODY_LIMIT_BYTES,
|
|
272319
273291
|
_testing: () => _testing2,
|
|
@@ -272322,11 +273294,13 @@ __export(serve_http_exports, {
|
|
|
272322
273294
|
isServerDiscoverRequest: () => isServerDiscoverRequest,
|
|
272323
273295
|
parseHttpBodyLimit: () => parseHttpBodyLimit,
|
|
272324
273296
|
parseJsonBody: () => parseJsonBody,
|
|
273297
|
+
parseMaxHttpSessions: () => parseMaxHttpSessions,
|
|
272325
273298
|
parseSessionTimeoutMs: () => parseSessionTimeoutMs,
|
|
272326
273299
|
resolveServeHttpDefaults: () => resolveServeHttpDefaults,
|
|
272327
273300
|
validateHttpBindSecurity: () => validateHttpBindSecurity
|
|
272328
273301
|
});
|
|
272329
273302
|
import { getHeapStatistics } from "v8";
|
|
273303
|
+
import { monitorEventLoopDelay } from "perf_hooks";
|
|
272330
273304
|
import { timingSafeEqual as timingSafeEqual2 } from "crypto";
|
|
272331
273305
|
function isServerDiscoverRequest(body) {
|
|
272332
273306
|
return Boolean(body && typeof body === "object" && !Array.isArray(body) && body.method === "server/discover");
|
|
@@ -272347,6 +273321,13 @@ function parseHttpBodyLimit(raw) {
|
|
|
272347
273321
|
}
|
|
272348
273322
|
return Math.min(parsed, MAX_HTTP_BODY_LIMIT_BYTES);
|
|
272349
273323
|
}
|
|
273324
|
+
function parseMaxHttpSessions(raw) {
|
|
273325
|
+
const value = raw?.trim();
|
|
273326
|
+
if (!value) return DEFAULT_MAX_HTTP_SESSIONS;
|
|
273327
|
+
const parsed = Number(value);
|
|
273328
|
+
if (!Number.isSafeInteger(parsed) || parsed < 1) return DEFAULT_MAX_HTTP_SESSIONS;
|
|
273329
|
+
return Math.min(parsed, MAX_HTTP_SESSIONS_LIMIT);
|
|
273330
|
+
}
|
|
272350
273331
|
function isLoopbackHost(host) {
|
|
272351
273332
|
const normalized = host.trim().toLowerCase();
|
|
272352
273333
|
return normalized === "localhost" || normalized === "127.0.0.1" || normalized === "::1" || normalized === "[::1]";
|
|
@@ -272419,7 +273400,7 @@ function resolveServeHttpDefaults(argsPort, configured) {
|
|
|
272419
273400
|
const transportNotice = configured.transport === "stdio" ? '[memorix] config server.transport = "stdio"; serve-http continues on HTTP (the explicit command wins).' : void 0;
|
|
272420
273401
|
return { port, transportNotice };
|
|
272421
273402
|
}
|
|
272422
|
-
var DEFAULT_SESSION_TIMEOUT_MS, EXPIRED_SESSION_TTL_MS, DEFAULT_HTTP_BODY_LIMIT_BYTES, MAX_HTTP_BODY_LIMIT_BYTES, MIN_HTTP_BODY_LIMIT_BYTES, MCP_SDK_COMPAT_PROTOCOL_VERSION, HttpPayloadTooLargeError, serve_http_default, _testing2;
|
|
273403
|
+
var DEFAULT_SESSION_TIMEOUT_MS, EXPIRED_SESSION_TTL_MS, DEFAULT_HTTP_BODY_LIMIT_BYTES, MAX_HTTP_BODY_LIMIT_BYTES, MIN_HTTP_BODY_LIMIT_BYTES, MAX_PROJECT_CACHE_ENTRIES, MAX_STORE_CACHE_ENTRIES, DEFAULT_MAX_HTTP_SESSIONS, MAX_HTTP_SESSIONS_LIMIT, MCP_SDK_COMPAT_PROTOCOL_VERSION, HttpPayloadTooLargeError, serve_http_default, _testing2;
|
|
272423
273404
|
var init_serve_http = __esm({
|
|
272424
273405
|
"src/cli/commands/serve-http.ts"() {
|
|
272425
273406
|
"use strict";
|
|
@@ -272438,6 +273419,10 @@ var init_serve_http = __esm({
|
|
|
272438
273419
|
DEFAULT_HTTP_BODY_LIMIT_BYTES = 10 * 1024 * 1024;
|
|
272439
273420
|
MAX_HTTP_BODY_LIMIT_BYTES = 64 * 1024 * 1024;
|
|
272440
273421
|
MIN_HTTP_BODY_LIMIT_BYTES = 64 * 1024;
|
|
273422
|
+
MAX_PROJECT_CACHE_ENTRIES = 256;
|
|
273423
|
+
MAX_STORE_CACHE_ENTRIES = 32;
|
|
273424
|
+
DEFAULT_MAX_HTTP_SESSIONS = 64;
|
|
273425
|
+
MAX_HTTP_SESSIONS_LIMIT = 512;
|
|
272441
273426
|
MCP_SDK_COMPAT_PROTOCOL_VERSION = "2025-11-25";
|
|
272442
273427
|
HttpPayloadTooLargeError = class extends Error {
|
|
272443
273428
|
statusCode = 413;
|
|
@@ -272475,7 +273460,7 @@ var init_serve_http = __esm({
|
|
|
272475
273460
|
},
|
|
272476
273461
|
run: async ({ args }) => {
|
|
272477
273462
|
const { createServer: createServer3 } = await import("http");
|
|
272478
|
-
const { randomUUID:
|
|
273463
|
+
const { randomUUID: randomUUID23 } = await import("crypto");
|
|
272479
273464
|
const { StreamableHTTPServerTransport: StreamableHTTPServerTransport2 } = await Promise.resolve().then(() => (init_streamableHttp(), streamableHttp_exports));
|
|
272480
273465
|
const { isInitializeRequest: isInitializeRequest2 } = await Promise.resolve().then(() => (init_types8(), types_exports3));
|
|
272481
273466
|
const { createMemorixServer: createMemorixServer2 } = await Promise.resolve().then(() => (init_server4(), server_exports2));
|
|
@@ -272485,7 +273470,8 @@ var init_serve_http = __esm({
|
|
|
272485
273470
|
const { homedir: homedir38 } = await import("os");
|
|
272486
273471
|
const { McpBindingStore: McpBindingStore2 } = await Promise.resolve().then(() => (init_mcp_binding_store(), mcp_binding_store_exports));
|
|
272487
273472
|
const { MemoryFeedbackStore: MemoryFeedbackStore2 } = await Promise.resolve().then(() => (init_feedback(), feedback_exports));
|
|
272488
|
-
const {
|
|
273473
|
+
const { createModernMcpRuntime: createModernMcpRuntime2, ModernMcpRuntimePool: ModernMcpRuntimePool2, withBusinessRuntimeQueue: withBusinessRuntimeQueue2 } = await Promise.resolve().then(() => (init_modern_mcp_bridge(), modern_mcp_bridge_exports));
|
|
273474
|
+
const { acquireDatabase: acquireDatabase2, evictIdleDatabases: evictIdleDatabases2, getDatabaseStats: getDatabaseStats2 } = await Promise.resolve().then(() => (init_sqlite_db(), sqlite_db_exports));
|
|
272489
273475
|
const { createMcpHandler } = await import("@modelcontextprotocol/server");
|
|
272490
273476
|
const { toNodeHandler } = await import("@modelcontextprotocol/node");
|
|
272491
273477
|
let configuredDefaults = {};
|
|
@@ -272537,42 +273523,108 @@ var init_serve_http = __esm({
|
|
|
272537
273523
|
console.error(`[memorix] Project root: ${projectRoot}`);
|
|
272538
273524
|
const sessionTimeoutMs = parseSessionTimeoutMs(process.env.MEMORIX_SESSION_TIMEOUT_MS);
|
|
272539
273525
|
const httpBodyLimitBytes = parseHttpBodyLimit(process.env.MEMORIX_HTTP_MAX_BODY_BYTES);
|
|
273526
|
+
const maxHttpSessions = parseMaxHttpSessions(process.env.MEMORIX_MAX_HTTP_SESSIONS);
|
|
273527
|
+
const eventLoopDelay = monitorEventLoopDelay({ resolution: 20 });
|
|
273528
|
+
eventLoopDelay.enable();
|
|
272540
273529
|
console.error(
|
|
272541
273530
|
sessionTimeoutMs === 0 ? "[memorix] HTTP session idle timeout: disabled" : `[memorix] HTTP session idle timeout: ${Math.round(sessionTimeoutMs / 6e4)}min (${sessionTimeoutMs}ms)`
|
|
272542
273531
|
);
|
|
273532
|
+
console.error(`[memorix] HTTP session limit: ${maxHttpSessions}`);
|
|
272543
273533
|
const teamStoreCache = /* @__PURE__ */ new Map();
|
|
273534
|
+
const teamStoreLeases = /* @__PURE__ */ new Map();
|
|
272544
273535
|
const { initTeamStore: initTeamStore2 } = await Promise.resolve().then(() => (init_team_store(), team_store_exports));
|
|
273536
|
+
function cacheSet3(cache5, key, value, limit2, onEvict) {
|
|
273537
|
+
cache5.delete(key);
|
|
273538
|
+
cache5.set(key, value);
|
|
273539
|
+
while (cache5.size > limit2) {
|
|
273540
|
+
const oldest = cache5.keys().next().value;
|
|
273541
|
+
if (oldest === void 0) break;
|
|
273542
|
+
const oldValue = cache5.get(oldest);
|
|
273543
|
+
cache5.delete(oldest);
|
|
273544
|
+
if (oldValue !== void 0) onEvict?.(oldest, oldValue);
|
|
273545
|
+
}
|
|
273546
|
+
}
|
|
272545
273547
|
async function getTeamStore2(dataDir) {
|
|
272546
273548
|
const existing = teamStoreCache.get(dataDir);
|
|
272547
|
-
if (existing)
|
|
272548
|
-
|
|
272549
|
-
|
|
272550
|
-
|
|
273549
|
+
if (existing) {
|
|
273550
|
+
cacheSet3(teamStoreCache, dataDir, existing, MAX_STORE_CACHE_ENTRIES);
|
|
273551
|
+
return existing;
|
|
273552
|
+
}
|
|
273553
|
+
const lease = acquireDatabase2(dataDir);
|
|
273554
|
+
try {
|
|
273555
|
+
const store2 = await initTeamStore2(dataDir);
|
|
273556
|
+
teamStoreLeases.set(dataDir, lease);
|
|
273557
|
+
cacheSet3(teamStoreCache, dataDir, store2, MAX_STORE_CACHE_ENTRIES, (evictedDataDir) => {
|
|
273558
|
+
teamStoreLeases.get(evictedDataDir)?.release();
|
|
273559
|
+
teamStoreLeases.delete(evictedDataDir);
|
|
273560
|
+
evictIdleDatabases2(MAX_STORE_CACHE_ENTRIES);
|
|
273561
|
+
});
|
|
273562
|
+
return store2;
|
|
273563
|
+
} catch (error40) {
|
|
273564
|
+
lease.release();
|
|
273565
|
+
throw error40;
|
|
273566
|
+
}
|
|
272551
273567
|
}
|
|
273568
|
+
const controlPlaneBaseDir = persistMod.getBaseDataDir();
|
|
273569
|
+
const controlPlaneBaseLease = acquireDatabase2(controlPlaneBaseDir);
|
|
272552
273570
|
const statelessBindingStore = new McpBindingStore2();
|
|
272553
|
-
await statelessBindingStore.init(
|
|
273571
|
+
await statelessBindingStore.init(controlPlaneBaseDir);
|
|
273572
|
+
const modernRuntimePool = new ModernMcpRuntimePool2(MAX_STORE_CACHE_ENTRIES);
|
|
273573
|
+
async function resolveModernDataDir(root, persisted) {
|
|
273574
|
+
if (persisted?.dataDir) return persisted.dataDir;
|
|
273575
|
+
const detected = detectorMod.detectProject(root);
|
|
273576
|
+
return detected ? persistMod.getProjectDataDir(detected.id) : controlPlaneBaseDir;
|
|
273577
|
+
}
|
|
272554
273578
|
const modernMcpHandler = createMcpHandler(async ({ requestInfo }) => {
|
|
272555
273579
|
const handleId = requestInfo?.headers.get("mcp-project-handle") ?? void 0;
|
|
272556
273580
|
const persisted = handleId ? statelessBindingStore.touch(handleId) : void 0;
|
|
272557
273581
|
const requestedRoot = requestInfo?.headers.get("mcp-project-root") ?? void 0;
|
|
272558
273582
|
const root = persisted?.projectRoot ?? requestedRoot ?? projectRoot;
|
|
272559
|
-
|
|
272560
|
-
|
|
272561
|
-
|
|
272562
|
-
|
|
272563
|
-
|
|
272564
|
-
|
|
272565
|
-
|
|
272566
|
-
|
|
272567
|
-
|
|
273583
|
+
const dataDir = await resolveModernDataDir(root, persisted);
|
|
273584
|
+
const runtimeKey = JSON.stringify([dataDir, root]);
|
|
273585
|
+
return modernRuntimePool.createBridge(runtimeKey, () => withBusinessRuntimeQueue2(async () => {
|
|
273586
|
+
const lease = acquireDatabase2(dataDir);
|
|
273587
|
+
try {
|
|
273588
|
+
const runtime = await createModernMcpRuntime2({
|
|
273589
|
+
projectRoot: root,
|
|
273590
|
+
allowUntrackedFallback: false,
|
|
273591
|
+
deferProjectInitUntilBound: true,
|
|
273592
|
+
deferProjectRuntimeInit: true,
|
|
273593
|
+
dashboardMode: "control-plane",
|
|
273594
|
+
dashboardPort: port,
|
|
273595
|
+
toolProfile
|
|
273596
|
+
});
|
|
273597
|
+
const close = runtime.close.bind(runtime);
|
|
273598
|
+
return {
|
|
273599
|
+
...runtime,
|
|
273600
|
+
close: async () => {
|
|
273601
|
+
try {
|
|
273602
|
+
await close();
|
|
273603
|
+
} finally {
|
|
273604
|
+
lease.release();
|
|
273605
|
+
}
|
|
273606
|
+
}
|
|
273607
|
+
};
|
|
273608
|
+
} catch (error40) {
|
|
273609
|
+
lease.release();
|
|
273610
|
+
throw error40;
|
|
273611
|
+
}
|
|
273612
|
+
}));
|
|
272568
273613
|
}, {
|
|
272569
273614
|
// Legacy requests are routed to the existing sessionful implementation
|
|
272570
273615
|
// below; this handler is strict modern-only by construction.
|
|
272571
273616
|
legacy: "reject",
|
|
272572
|
-
responseMode: "auto"
|
|
273617
|
+
responseMode: "auto",
|
|
273618
|
+
onerror: (error40) => {
|
|
273619
|
+
const message = error40 instanceof Error ? error40.message : String(error40);
|
|
273620
|
+
const stack = error40 instanceof Error ? error40.stack : void 0;
|
|
273621
|
+
console.error(`[memorix] modern MCP request failed: ${message}${stack ? `
|
|
273622
|
+
${stack}` : ""}`);
|
|
273623
|
+
}
|
|
272573
273624
|
});
|
|
272574
273625
|
const modernNodeHandler = toNodeHandler(modernMcpHandler);
|
|
272575
273626
|
const sessions = /* @__PURE__ */ new Map();
|
|
273627
|
+
let pendingSessionInitializations = 0;
|
|
272576
273628
|
const sessionLastActivity = /* @__PURE__ */ new Map();
|
|
272577
273629
|
const expiredSessions = /* @__PURE__ */ new Map();
|
|
272578
273630
|
let suppressedProbeCount = 0;
|
|
@@ -272747,7 +273799,11 @@ var init_serve_http = __esm({
|
|
|
272747
273799
|
if (sessionId && sessions.has(sessionId)) {
|
|
272748
273800
|
sessionLastActivity.set(sessionId, Date.now());
|
|
272749
273801
|
patchMcpResponse(res);
|
|
272750
|
-
|
|
273802
|
+
const session = sessions.get(sessionId);
|
|
273803
|
+
await withBusinessRuntimeQueue2(async () => {
|
|
273804
|
+
await session.activateProjectRuntime();
|
|
273805
|
+
await session.transport.handleRequest(req, res, body);
|
|
273806
|
+
});
|
|
272751
273807
|
return;
|
|
272752
273808
|
}
|
|
272753
273809
|
if (sessionId) {
|
|
@@ -272755,11 +273811,32 @@ var init_serve_http = __esm({
|
|
|
272755
273811
|
return;
|
|
272756
273812
|
}
|
|
272757
273813
|
if (!sessionId && isInitializeRequest2(body)) {
|
|
273814
|
+
if (sessions.size + pendingSessionInitializations >= maxHttpSessions) {
|
|
273815
|
+
res.writeHead(429, {
|
|
273816
|
+
"Content-Type": "application/json",
|
|
273817
|
+
"Retry-After": "5"
|
|
273818
|
+
});
|
|
273819
|
+
res.end(JSON.stringify({
|
|
273820
|
+
jsonrpc: "2.0",
|
|
273821
|
+
error: { code: -32029, message: `HTTP session limit reached (${maxHttpSessions}). Retry after an existing session closes.` },
|
|
273822
|
+
id: body.id ?? null
|
|
273823
|
+
}));
|
|
273824
|
+
return;
|
|
273825
|
+
}
|
|
273826
|
+
pendingSessionInitializations++;
|
|
273827
|
+
let pendingReservationReleased = false;
|
|
273828
|
+
const releasePendingReservation = () => {
|
|
273829
|
+
if (pendingReservationReleased) return;
|
|
273830
|
+
pendingReservationReleased = true;
|
|
273831
|
+
pendingSessionInitializations = Math.max(0, pendingSessionInitializations - 1);
|
|
273832
|
+
};
|
|
272758
273833
|
let createdState = null;
|
|
273834
|
+
const sessionLeases = [acquireDatabase2(defaultDataDir)];
|
|
272759
273835
|
const transport = new StreamableHTTPServerTransport2({
|
|
272760
|
-
sessionIdGenerator: () =>
|
|
273836
|
+
sessionIdGenerator: () => randomUUID23(),
|
|
272761
273837
|
enableJsonResponse: true,
|
|
272762
273838
|
onsessioninitialized: (sid) => {
|
|
273839
|
+
releasePendingReservation();
|
|
272763
273840
|
if (createdState) sessions.set(sid, createdState);
|
|
272764
273841
|
sessionLastActivity.set(sid, Date.now());
|
|
272765
273842
|
const timer = setTimeout(() => {
|
|
@@ -272770,6 +273847,7 @@ var init_serve_http = __esm({
|
|
|
272770
273847
|
}
|
|
272771
273848
|
});
|
|
272772
273849
|
transport.onclose = () => {
|
|
273850
|
+
releasePendingReservation();
|
|
272773
273851
|
const sid = transport.sessionId;
|
|
272774
273852
|
if (sid) {
|
|
272775
273853
|
const pending = pendingLogTimers.get(sid);
|
|
@@ -272785,26 +273863,49 @@ var init_serve_http = __esm({
|
|
|
272785
273863
|
sessionLastActivity.delete(sid);
|
|
272786
273864
|
}
|
|
272787
273865
|
handleTransportClose();
|
|
273866
|
+
for (const lease of sessionLeases) lease.release();
|
|
273867
|
+
evictIdleDatabases2(MAX_STORE_CACHE_ENTRIES);
|
|
272788
273868
|
};
|
|
272789
273869
|
const binding = createProjectBindingController2(projectRoot);
|
|
272790
|
-
|
|
272791
|
-
|
|
272792
|
-
|
|
272793
|
-
|
|
272794
|
-
|
|
272795
|
-
|
|
272796
|
-
|
|
272797
|
-
|
|
272798
|
-
|
|
272799
|
-
|
|
272800
|
-
|
|
272801
|
-
|
|
272802
|
-
|
|
272803
|
-
|
|
272804
|
-
|
|
273870
|
+
let server;
|
|
273871
|
+
let activateProjectRuntime;
|
|
273872
|
+
let handleTransportClose;
|
|
273873
|
+
let getProjectDataDirForSession;
|
|
273874
|
+
let switchProject;
|
|
273875
|
+
try {
|
|
273876
|
+
({ server, activateProjectRuntime, switchProject, handleTransportClose, getProjectDataDir: getProjectDataDirForSession } = await createMemorixServer2(
|
|
273877
|
+
projectRoot,
|
|
273878
|
+
void 0,
|
|
273879
|
+
void 0,
|
|
273880
|
+
{
|
|
273881
|
+
allowUntrackedFallback: false,
|
|
273882
|
+
deferProjectInitUntilBound: true,
|
|
273883
|
+
// Same as stdio: initialize/tools/list must not hydrate 40k+
|
|
273884
|
+
// observations on the HTTP thread. /health and the LaunchAgent
|
|
273885
|
+
// watchdog die if createMemorixServer blocks here.
|
|
273886
|
+
deferProjectRuntimeInit: true,
|
|
273887
|
+
dashboardMode: "control-plane",
|
|
273888
|
+
dashboardPort: port,
|
|
273889
|
+
toolProfile,
|
|
273890
|
+
projectBinding: binding
|
|
273891
|
+
}
|
|
273892
|
+
));
|
|
273893
|
+
} catch (error40) {
|
|
273894
|
+
releasePendingReservation();
|
|
273895
|
+
for (const lease of sessionLeases) lease.release();
|
|
273896
|
+
throw error40;
|
|
273897
|
+
}
|
|
273898
|
+
const switchProjectWithLease = async (newCwd, source) => {
|
|
273899
|
+
const before = getProjectDataDirForSession();
|
|
273900
|
+
const changed = await switchProject(newCwd, source);
|
|
273901
|
+
const after = getProjectDataDirForSession();
|
|
273902
|
+
if (changed && after !== before) {
|
|
273903
|
+
sessionLeases[0].release();
|
|
273904
|
+
sessionLeases[0] = acquireDatabase2(after);
|
|
272805
273905
|
}
|
|
272806
|
-
|
|
272807
|
-
|
|
273906
|
+
return changed;
|
|
273907
|
+
};
|
|
273908
|
+
createdState = { transport, server, activateProjectRuntime, switchProject: switchProjectWithLease, binding, leases: sessionLeases };
|
|
272808
273909
|
await server.connect(transport);
|
|
272809
273910
|
const tryRootsSwitch = async () => {
|
|
272810
273911
|
try {
|
|
@@ -272843,7 +273944,14 @@ var init_serve_http = __esm({
|
|
|
272843
273944
|
} catch {
|
|
272844
273945
|
}
|
|
272845
273946
|
patchMcpResponse(res);
|
|
272846
|
-
|
|
273947
|
+
try {
|
|
273948
|
+
await withBusinessRuntimeQueue2(async () => {
|
|
273949
|
+
await activateProjectRuntime();
|
|
273950
|
+
await transport.handleRequest(req, res, body);
|
|
273951
|
+
});
|
|
273952
|
+
} finally {
|
|
273953
|
+
if (!transport.sessionId) releasePendingReservation();
|
|
273954
|
+
}
|
|
272847
273955
|
return;
|
|
272848
273956
|
}
|
|
272849
273957
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
@@ -272877,7 +273985,7 @@ var init_serve_http = __esm({
|
|
|
272877
273985
|
sendUnknownSession(res, sessionId);
|
|
272878
273986
|
return;
|
|
272879
273987
|
}
|
|
272880
|
-
await sessions.get(sessionId).transport.handleRequest(req, res);
|
|
273988
|
+
await withBusinessRuntimeQueue2(() => sessions.get(sessionId).transport.handleRequest(req, res));
|
|
272881
273989
|
}
|
|
272882
273990
|
const { detectProject: detectProject2 } = await Promise.resolve().then(() => (init_detector(), detector_exports));
|
|
272883
273991
|
const { getProjectDataDir: getProjectDataDir2, getBaseDataDir: getBaseDataDir2 } = await Promise.resolve().then(() => (init_persistence(), persistence_exports));
|
|
@@ -272898,8 +274006,9 @@ var init_serve_http = __esm({
|
|
|
272898
274006
|
});
|
|
272899
274007
|
controlPlaneMaintenanceWorker.start();
|
|
272900
274008
|
const projectDataDirCache = /* @__PURE__ */ new Map();
|
|
272901
|
-
projectDataDirCache
|
|
274009
|
+
cacheSet3(projectDataDirCache, defaultProject.id, defaultDataDir, MAX_PROJECT_CACHE_ENTRIES);
|
|
272902
274010
|
const dashboardObservationStores = /* @__PURE__ */ new Map();
|
|
274011
|
+
const dashboardStoreLeases = /* @__PURE__ */ new Map();
|
|
272903
274012
|
async function resolveRequestProject(url2) {
|
|
272904
274013
|
const requestedId = url2.searchParams.get("project");
|
|
272905
274014
|
if (!requestedId || requestedId === defaultProject.id) {
|
|
@@ -272908,18 +274017,36 @@ var init_serve_http = __esm({
|
|
|
272908
274017
|
let dataDir = projectDataDirCache.get(requestedId);
|
|
272909
274018
|
if (!dataDir) {
|
|
272910
274019
|
dataDir = await getProjectDataDir2(requestedId);
|
|
272911
|
-
projectDataDirCache
|
|
274020
|
+
cacheSet3(projectDataDirCache, requestedId, dataDir, MAX_PROJECT_CACHE_ENTRIES);
|
|
272912
274021
|
}
|
|
272913
274022
|
const name = requestedId.split("/").pop() || requestedId;
|
|
272914
274023
|
return { projectId: requestedId, projectName: name, dataDir };
|
|
272915
274024
|
}
|
|
272916
274025
|
async function getDashboardObservationStore(dataDir) {
|
|
272917
274026
|
const cached2 = dashboardObservationStores.get(dataDir);
|
|
272918
|
-
if (cached2)
|
|
274027
|
+
if (cached2) {
|
|
274028
|
+
cacheSet3(dashboardObservationStores, dataDir, cached2, MAX_STORE_CACHE_ENTRIES);
|
|
274029
|
+
return cached2;
|
|
274030
|
+
}
|
|
272919
274031
|
const { createObservationStore: createObservationStore2 } = await Promise.resolve().then(() => (init_obs_store(), obs_store_exports));
|
|
272920
|
-
const
|
|
272921
|
-
|
|
272922
|
-
|
|
274032
|
+
const lease = acquireDatabase2(dataDir);
|
|
274033
|
+
try {
|
|
274034
|
+
const store2 = await createObservationStore2(dataDir);
|
|
274035
|
+
dashboardStoreLeases.set(dataDir, lease);
|
|
274036
|
+
cacheSet3(dashboardObservationStores, dataDir, store2, MAX_STORE_CACHE_ENTRIES, (evictedDataDir, evictedStore) => {
|
|
274037
|
+
try {
|
|
274038
|
+
evictedStore.close();
|
|
274039
|
+
} catch {
|
|
274040
|
+
}
|
|
274041
|
+
dashboardStoreLeases.get(evictedDataDir)?.release();
|
|
274042
|
+
dashboardStoreLeases.delete(evictedDataDir);
|
|
274043
|
+
evictIdleDatabases2(MAX_STORE_CACHE_ENTRIES);
|
|
274044
|
+
});
|
|
274045
|
+
return store2;
|
|
274046
|
+
} catch (error40) {
|
|
274047
|
+
lease.release();
|
|
274048
|
+
throw error40;
|
|
274049
|
+
}
|
|
272923
274050
|
}
|
|
272924
274051
|
async function loadDashboardObservations(dataDir) {
|
|
272925
274052
|
const store2 = await getDashboardObservationStore(dataDir);
|
|
@@ -273749,6 +274876,18 @@ var init_serve_http = __esm({
|
|
|
273749
274876
|
arrayBuffers: memory.arrayBuffers,
|
|
273750
274877
|
heapLimit: heap.heap_size_limit
|
|
273751
274878
|
},
|
|
274879
|
+
sqlite: getDatabaseStats2(),
|
|
274880
|
+
sessions: {
|
|
274881
|
+
active: sessions.size,
|
|
274882
|
+
pending: pendingSessionInitializations,
|
|
274883
|
+
limit: maxHttpSessions
|
|
274884
|
+
},
|
|
274885
|
+
modernRuntime: modernRuntimePool.stats(),
|
|
274886
|
+
eventLoop: {
|
|
274887
|
+
meanMs: Number.isFinite(eventLoopDelay.mean) ? eventLoopDelay.mean / 1e6 : null,
|
|
274888
|
+
p95Ms: eventLoopDelay.percentile(95) / 1e6,
|
|
274889
|
+
maxMs: eventLoopDelay.max / 1e6
|
|
274890
|
+
},
|
|
273752
274891
|
embedding: getEmbeddingRuntimeHealth2()
|
|
273753
274892
|
}));
|
|
273754
274893
|
return;
|
|
@@ -273865,6 +275004,13 @@ var init_serve_http = __esm({
|
|
|
273865
275004
|
}
|
|
273866
275005
|
}
|
|
273867
275006
|
dashboardObservationStores.clear();
|
|
275007
|
+
for (const lease of dashboardStoreLeases.values()) lease.release();
|
|
275008
|
+
dashboardStoreLeases.clear();
|
|
275009
|
+
for (const lease of teamStoreLeases.values()) lease.release();
|
|
275010
|
+
teamStoreLeases.clear();
|
|
275011
|
+
controlPlaneBaseLease.release();
|
|
275012
|
+
await modernRuntimePool.close();
|
|
275013
|
+
eventLoopDelay.disable();
|
|
273868
275014
|
const { closeAllDatabases: closeAllDatabases2 } = await Promise.resolve().then(() => (init_sqlite_db(), sqlite_db_exports));
|
|
273869
275015
|
closeAllDatabases2();
|
|
273870
275016
|
throw error40;
|
|
@@ -273875,6 +275021,8 @@ var init_serve_http = __esm({
|
|
|
273875
275021
|
const now3 = Date.now();
|
|
273876
275022
|
forgetExpiredSessions(now3);
|
|
273877
275023
|
statelessBindingStore.cleanupExpired(now3);
|
|
275024
|
+
evictIdleDatabases2(MAX_STORE_CACHE_ENTRIES);
|
|
275025
|
+
void modernRuntimePool.evictIdle();
|
|
273878
275026
|
if (SESSION_TIMEOUT_MS === 0) return;
|
|
273879
275027
|
for (const [sid, state] of sessions) {
|
|
273880
275028
|
const lastActive = sessionLastActivity.get(sid) ?? 0;
|
|
@@ -273918,6 +275066,10 @@ var init_serve_http = __esm({
|
|
|
273918
275066
|
}
|
|
273919
275067
|
}
|
|
273920
275068
|
dashboardObservationStores.clear();
|
|
275069
|
+
for (const lease of dashboardStoreLeases.values()) lease.release();
|
|
275070
|
+
dashboardStoreLeases.clear();
|
|
275071
|
+
for (const lease of teamStoreLeases.values()) lease.release();
|
|
275072
|
+
teamStoreLeases.clear();
|
|
273921
275073
|
for (const [sid, state] of sessions) {
|
|
273922
275074
|
try {
|
|
273923
275075
|
await state.transport.close();
|
|
@@ -273926,8 +275078,10 @@ var init_serve_http = __esm({
|
|
|
273926
275078
|
console.error(`[memorix] Error closing session ${sid}:`, err);
|
|
273927
275079
|
}
|
|
273928
275080
|
}
|
|
275081
|
+
await modernRuntimePool.close();
|
|
273929
275082
|
clearInterval(gcInterval);
|
|
273930
275083
|
clearInterval(heartbeatInterval);
|
|
275084
|
+
eventLoopDelay.disable();
|
|
273931
275085
|
await new Promise((resolve9) => {
|
|
273932
275086
|
if (!httpServer.listening) {
|
|
273933
275087
|
resolve9();
|
|
@@ -273936,6 +275090,7 @@ var init_serve_http = __esm({
|
|
|
273936
275090
|
httpServer.close(() => resolve9());
|
|
273937
275091
|
});
|
|
273938
275092
|
const { closeAllDatabases: closeAllDatabases2 } = await Promise.resolve().then(() => (init_sqlite_db(), sqlite_db_exports));
|
|
275093
|
+
controlPlaneBaseLease.release();
|
|
273939
275094
|
closeAllDatabases2();
|
|
273940
275095
|
process.exit(0);
|
|
273941
275096
|
};
|
|
@@ -273979,6 +275134,7 @@ var init_serve_http = __esm({
|
|
|
273979
275134
|
MAX_HTTP_BODY_LIMIT_BYTES,
|
|
273980
275135
|
MIN_HTTP_BODY_LIMIT_BYTES,
|
|
273981
275136
|
parseSessionTimeoutMs,
|
|
275137
|
+
parseMaxHttpSessions,
|
|
273982
275138
|
parseHttpBodyLimit,
|
|
273983
275139
|
isLoopbackHost,
|
|
273984
275140
|
validateHttpBindSecurity,
|
|
@@ -274328,7 +275484,7 @@ var init_merge = __esm({
|
|
|
274328
275484
|
});
|
|
274329
275485
|
|
|
274330
275486
|
// src/sync/journal.ts
|
|
274331
|
-
import { createHash as
|
|
275487
|
+
import { createHash as createHash22 } from "crypto";
|
|
274332
275488
|
function nowIso() {
|
|
274333
275489
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
274334
275490
|
}
|
|
@@ -274340,7 +275496,7 @@ function deriveSyncKey(obs, originDevice) {
|
|
|
274340
275496
|
function contentHash(obs) {
|
|
274341
275497
|
const { id: _id, writeGeneration: _wg, ...rest } = obs;
|
|
274342
275498
|
const stable = stableJson(rest);
|
|
274343
|
-
return
|
|
275499
|
+
return createHash22("sha256").update(stable).digest("hex");
|
|
274344
275500
|
}
|
|
274345
275501
|
function stableJson(value) {
|
|
274346
275502
|
if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
|
|
@@ -274463,9 +275619,9 @@ var init_policy2 = __esm({
|
|
|
274463
275619
|
});
|
|
274464
275620
|
|
|
274465
275621
|
// src/sync/namespace.ts
|
|
274466
|
-
import { createHash as
|
|
275622
|
+
import { createHash as createHash23 } from "crypto";
|
|
274467
275623
|
function syncNamespace(projectId) {
|
|
274468
|
-
return `project-${
|
|
275624
|
+
return `project-${createHash23("sha256").update(projectId).digest("hex").slice(0, 32)}`;
|
|
274469
275625
|
}
|
|
274470
275626
|
function userSyncNamespace(env3 = process.env) {
|
|
274471
275627
|
const override = env3.MEMORIX_SYNC_USER_NAMESPACE?.trim();
|
|
@@ -274491,7 +275647,7 @@ var init_namespace = __esm({
|
|
|
274491
275647
|
});
|
|
274492
275648
|
|
|
274493
275649
|
// src/sync/engine.ts
|
|
274494
|
-
import { createHash as
|
|
275650
|
+
import { createHash as createHash24 } from "crypto";
|
|
274495
275651
|
async function runSync(store2, remote, opts) {
|
|
274496
275652
|
const report = {
|
|
274497
275653
|
remote: remote.kind,
|
|
@@ -274695,7 +275851,7 @@ async function recordConcurrentConflict(store2, report, local, incoming, localRo
|
|
|
274695
275851
|
const incomingWins = compareVersion(incoming.version, { revision: local.revision, writer: local.writer }) > 0;
|
|
274696
275852
|
const loser = incomingWins ? { revision: local.revision, writer: local.writer } : incoming.version;
|
|
274697
275853
|
const loserRow = incomingWins ? localRow : incoming.row;
|
|
274698
|
-
const id =
|
|
275854
|
+
const id = createHash24("sha256").update(`${store2.projectId()}|${incoming.syncKey}|${local.revision}|${local.writer}|${incoming.version.revision}|${incoming.version.writer}`).digest("hex");
|
|
274699
275855
|
await store2.recordConflict({
|
|
274700
275856
|
id,
|
|
274701
275857
|
projectId: store2.projectId(),
|
|
@@ -274734,7 +275890,7 @@ var init_engine6 = __esm({
|
|
|
274734
275890
|
|
|
274735
275891
|
// src/sync/store-port.ts
|
|
274736
275892
|
import os7 from "os";
|
|
274737
|
-
import { randomUUID as
|
|
275893
|
+
import { randomUUID as randomUUID21 } from "crypto";
|
|
274738
275894
|
function createSqliteSyncStore(dataDir, store2, projectId, options = {}) {
|
|
274739
275895
|
const db2 = getDatabase(dataDir);
|
|
274740
275896
|
const scope = options.scope ?? "project";
|
|
@@ -274784,7 +275940,7 @@ function createSqliteSyncStore(dataDir, store2, projectId, options = {}) {
|
|
|
274784
275940
|
function ensureDevice() {
|
|
274785
275941
|
const row = getMeta.get(DEVICE_KEY);
|
|
274786
275942
|
if (row?.value) return row.value;
|
|
274787
|
-
const id = `dev_${
|
|
275943
|
+
const id = `dev_${randomUUID21().replaceAll("-", "")}`;
|
|
274788
275944
|
setMeta.run(DEVICE_KEY, id);
|
|
274789
275945
|
setMeta.run(FINGERPRINT_KEY, deviceFingerprint);
|
|
274790
275946
|
return id;
|
|
@@ -274814,7 +275970,7 @@ function createSqliteSyncStore(dataDir, store2, projectId, options = {}) {
|
|
|
274814
275970
|
assertCanPublish,
|
|
274815
275971
|
rotateDevice: () => {
|
|
274816
275972
|
const previous = ensureDevice();
|
|
274817
|
-
const id = `dev_${
|
|
275973
|
+
const id = `dev_${randomUUID21().replaceAll("-", "")}`;
|
|
274818
275974
|
const pending = pendingForDevice.all(previous);
|
|
274819
275975
|
const rotate = db2.transaction(() => {
|
|
274820
275976
|
setMeta.run(DEVICE_KEY, id);
|
|
@@ -277591,10 +278747,10 @@ __export(handler_exports, {
|
|
|
277591
278747
|
resetCooldowns: () => resetCooldowns,
|
|
277592
278748
|
runHook: () => runHook
|
|
277593
278749
|
});
|
|
277594
|
-
import { createHash as
|
|
278750
|
+
import { createHash as createHash25 } from "crypto";
|
|
277595
278751
|
function deriveHookActorId(input) {
|
|
277596
278752
|
const material = `${input.agent ?? "unknown"}\0${input.sessionId ?? "unknown"}`;
|
|
277597
|
-
return `hook:${
|
|
278753
|
+
return `hook:${createHash25("sha256").update(material).digest("hex").slice(0, 24)}`;
|
|
277598
278754
|
}
|
|
277599
278755
|
function classifyTool(input) {
|
|
277600
278756
|
if (input.event === "post_edit") return "file_modify";
|
|
@@ -279556,10 +280712,10 @@ var init_ingest = __esm({
|
|
|
279556
280712
|
});
|
|
279557
280713
|
|
|
279558
280714
|
// src/media/embedding.ts
|
|
279559
|
-
import { createHash as
|
|
280715
|
+
import { createHash as createHash26 } from "crypto";
|
|
279560
280716
|
function profileKey(provider2, asset) {
|
|
279561
280717
|
const identity = `${provider2.name}\0${provider2.dimensions}\0${asset.kind}`;
|
|
279562
|
-
return `media:${
|
|
280718
|
+
return `media:${createHash26("sha256").update(identity).digest("hex").slice(0, 20)}`;
|
|
279563
280719
|
}
|
|
279564
280720
|
function supportsAsset(provider2, asset) {
|
|
279565
280721
|
return !!provider2.embedInput && (provider2.supportedModalities?.includes(asset.kind) ?? false);
|
|
@@ -284751,13 +285907,21 @@ var init_capability_router = __esm({
|
|
|
284751
285907
|
// src/orchestrate/pipeline-trace.ts
|
|
284752
285908
|
function initTraceTable(db2) {
|
|
284753
285909
|
db2.exec(CREATE_TABLE_SQL);
|
|
285910
|
+
for (const column of ["attempt INTEGER", "risk_tier TEXT", "effect_key TEXT", "memory_refs TEXT"]) {
|
|
285911
|
+
try {
|
|
285912
|
+
db2.exec(`ALTER TABLE pipeline_traces ADD COLUMN ${column}`);
|
|
285913
|
+
} catch {
|
|
285914
|
+
}
|
|
285915
|
+
}
|
|
284754
285916
|
db2.exec(CREATE_INDEX_SQL);
|
|
284755
285917
|
}
|
|
284756
285918
|
function writeTrace(db2, event) {
|
|
284757
285919
|
if (!_insertStmt) {
|
|
284758
285920
|
_insertStmt = db2.prepare(`
|
|
284759
|
-
INSERT INTO pipeline_traces (
|
|
284760
|
-
|
|
285921
|
+
INSERT INTO pipeline_traces (
|
|
285922
|
+
pipeline_id, timestamp, type, task_id, agent, detail, duration_ms,
|
|
285923
|
+
attempt, risk_tier, effect_key, memory_refs
|
|
285924
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
284761
285925
|
`);
|
|
284762
285926
|
}
|
|
284763
285927
|
_insertStmt.run(
|
|
@@ -284766,8 +285930,12 @@ function writeTrace(db2, event) {
|
|
|
284766
285930
|
event.type,
|
|
284767
285931
|
event.taskId ?? null,
|
|
284768
285932
|
event.agent ?? null,
|
|
284769
|
-
event.detail,
|
|
284770
|
-
event.durationMs ?? null
|
|
285933
|
+
sanitizeCredentials(event.detail).slice(0, 2e3),
|
|
285934
|
+
event.durationMs ?? null,
|
|
285935
|
+
event.attempt ?? null,
|
|
285936
|
+
event.riskTier ?? null,
|
|
285937
|
+
event.effectKey ?? null,
|
|
285938
|
+
event.memoryRefs ? JSON.stringify(event.memoryRefs.slice(0, 16)) : null
|
|
284771
285939
|
);
|
|
284772
285940
|
}
|
|
284773
285941
|
function pruneOldTraces(db2, keepPipelines = 20) {
|
|
@@ -284796,6 +285964,7 @@ var init_pipeline_trace = __esm({
|
|
|
284796
285964
|
"src/orchestrate/pipeline-trace.ts"() {
|
|
284797
285965
|
"use strict";
|
|
284798
285966
|
init_esm_shims();
|
|
285967
|
+
init_secret_filter();
|
|
284799
285968
|
CREATE_TABLE_SQL = `
|
|
284800
285969
|
CREATE TABLE IF NOT EXISTS pipeline_traces (
|
|
284801
285970
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
@@ -284805,7 +285974,11 @@ var init_pipeline_trace = __esm({
|
|
|
284805
285974
|
task_id TEXT,
|
|
284806
285975
|
agent TEXT,
|
|
284807
285976
|
detail TEXT NOT NULL,
|
|
284808
|
-
duration_ms INTEGER
|
|
285977
|
+
duration_ms INTEGER,
|
|
285978
|
+
attempt INTEGER,
|
|
285979
|
+
risk_tier TEXT,
|
|
285980
|
+
effect_key TEXT,
|
|
285981
|
+
memory_refs TEXT
|
|
284809
285982
|
)
|
|
284810
285983
|
`;
|
|
284811
285984
|
CREATE_INDEX_SQL = `
|
|
@@ -285568,8 +286741,140 @@ var init_permission = __esm({
|
|
|
285568
286741
|
}
|
|
285569
286742
|
});
|
|
285570
286743
|
|
|
286744
|
+
// src/orchestrate/effect-ledger.ts
|
|
286745
|
+
import { createHash as createHash27, randomUUID as randomUUID22 } from "crypto";
|
|
286746
|
+
function fingerprintEffectInput(input) {
|
|
286747
|
+
if (input === void 0) return void 0;
|
|
286748
|
+
try {
|
|
286749
|
+
const safe = sanitizeCredentials(JSON.stringify(input));
|
|
286750
|
+
return createHash27("sha256").update(safe).digest("hex").slice(0, 24);
|
|
286751
|
+
} catch {
|
|
286752
|
+
return void 0;
|
|
286753
|
+
}
|
|
286754
|
+
}
|
|
286755
|
+
function rowToEffect(row) {
|
|
286756
|
+
return {
|
|
286757
|
+
id: String(row.id),
|
|
286758
|
+
pipelineId: String(row.pipeline_id),
|
|
286759
|
+
taskId: String(row.task_id),
|
|
286760
|
+
attempt: Number(row.attempt),
|
|
286761
|
+
effectKey: String(row.effect_key),
|
|
286762
|
+
tool: String(row.tool),
|
|
286763
|
+
riskTier: row.risk_tier,
|
|
286764
|
+
replayPolicy: row.replay_policy,
|
|
286765
|
+
status: row.status,
|
|
286766
|
+
...row.call_id ? { callId: String(row.call_id) } : {},
|
|
286767
|
+
idempotencyKey: String(row.idempotency_key),
|
|
286768
|
+
...row.input_fingerprint ? { inputFingerprint: String(row.input_fingerprint) } : {},
|
|
286769
|
+
...row.detail ? { detail: String(row.detail) } : {},
|
|
286770
|
+
startedAt: Number(row.started_at),
|
|
286771
|
+
...row.finished_at ? { finishedAt: Number(row.finished_at) } : {}
|
|
286772
|
+
};
|
|
286773
|
+
}
|
|
286774
|
+
var AgentEffectLedger;
|
|
286775
|
+
var init_effect_ledger = __esm({
|
|
286776
|
+
"src/orchestrate/effect-ledger.ts"() {
|
|
286777
|
+
"use strict";
|
|
286778
|
+
init_esm_shims();
|
|
286779
|
+
init_secret_filter();
|
|
286780
|
+
init_permission();
|
|
286781
|
+
AgentEffectLedger = class {
|
|
286782
|
+
constructor(db2) {
|
|
286783
|
+
this.db = db2;
|
|
286784
|
+
}
|
|
286785
|
+
db;
|
|
286786
|
+
observe(input) {
|
|
286787
|
+
const existing = this.db.prepare(`
|
|
286788
|
+
SELECT * FROM agent_effects
|
|
286789
|
+
WHERE pipeline_id = ? AND task_id = ? AND attempt = ? AND effect_key = ?
|
|
286790
|
+
`).get(input.pipelineId, input.taskId, input.attempt, input.effectKey);
|
|
286791
|
+
if (existing) return rowToEffect(existing);
|
|
286792
|
+
const riskTier = classifyTool2(input.tool);
|
|
286793
|
+
const replayPolicy = riskTier === "safe" ? "safe" : "requires-idempotency-key";
|
|
286794
|
+
const idempotencyKey = `${input.pipelineId}:${input.taskId}:${input.attempt}:${input.effectKey}`;
|
|
286795
|
+
const now3 = Date.now();
|
|
286796
|
+
const record2 = {
|
|
286797
|
+
id: randomUUID22(),
|
|
286798
|
+
pipelineId: input.pipelineId,
|
|
286799
|
+
taskId: input.taskId,
|
|
286800
|
+
attempt: input.attempt,
|
|
286801
|
+
effectKey: input.effectKey,
|
|
286802
|
+
tool: input.tool.slice(0, 200),
|
|
286803
|
+
riskTier,
|
|
286804
|
+
replayPolicy,
|
|
286805
|
+
status: "observed",
|
|
286806
|
+
...input.callId ? { callId: input.callId.slice(0, 200) } : {},
|
|
286807
|
+
idempotencyKey,
|
|
286808
|
+
...fingerprintEffectInput(input.input) ? { inputFingerprint: fingerprintEffectInput(input.input) } : {},
|
|
286809
|
+
startedAt: now3
|
|
286810
|
+
};
|
|
286811
|
+
this.db.prepare(`
|
|
286812
|
+
INSERT OR IGNORE INTO agent_effects (
|
|
286813
|
+
id, pipeline_id, task_id, attempt, effect_key, tool, risk_tier,
|
|
286814
|
+
replay_policy, status, call_id, idempotency_key, input_fingerprint,
|
|
286815
|
+
detail, started_at, finished_at
|
|
286816
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
286817
|
+
`).run(
|
|
286818
|
+
record2.id,
|
|
286819
|
+
record2.pipelineId,
|
|
286820
|
+
record2.taskId,
|
|
286821
|
+
record2.attempt,
|
|
286822
|
+
record2.effectKey,
|
|
286823
|
+
record2.tool,
|
|
286824
|
+
record2.riskTier,
|
|
286825
|
+
record2.replayPolicy,
|
|
286826
|
+
record2.status,
|
|
286827
|
+
record2.callId ?? null,
|
|
286828
|
+
record2.idempotencyKey,
|
|
286829
|
+
record2.inputFingerprint ?? null,
|
|
286830
|
+
null,
|
|
286831
|
+
record2.startedAt,
|
|
286832
|
+
null
|
|
286833
|
+
);
|
|
286834
|
+
return rowToEffect(this.db.prepare(`
|
|
286835
|
+
SELECT * FROM agent_effects
|
|
286836
|
+
WHERE pipeline_id = ? AND task_id = ? AND attempt = ? AND effect_key = ?
|
|
286837
|
+
`).get(input.pipelineId, input.taskId, input.attempt, input.effectKey));
|
|
286838
|
+
}
|
|
286839
|
+
settle(input) {
|
|
286840
|
+
const detail = input.detail ? sanitizeCredentials(input.detail).slice(0, 500) : void 0;
|
|
286841
|
+
this.db.prepare(`
|
|
286842
|
+
UPDATE agent_effects
|
|
286843
|
+
SET status = ?, detail = ?, finished_at = ?
|
|
286844
|
+
WHERE pipeline_id = ? AND task_id = ? AND attempt = ? AND effect_key = ?
|
|
286845
|
+
`).run(
|
|
286846
|
+
input.status,
|
|
286847
|
+
detail ?? null,
|
|
286848
|
+
Date.now(),
|
|
286849
|
+
input.pipelineId,
|
|
286850
|
+
input.taskId,
|
|
286851
|
+
input.attempt,
|
|
286852
|
+
input.effectKey
|
|
286853
|
+
);
|
|
286854
|
+
const row = this.db.prepare(`
|
|
286855
|
+
SELECT * FROM agent_effects
|
|
286856
|
+
WHERE pipeline_id = ? AND task_id = ? AND attempt = ? AND effect_key = ?
|
|
286857
|
+
`).get(input.pipelineId, input.taskId, input.attempt, input.effectKey);
|
|
286858
|
+
return row ? rowToEffect(row) : void 0;
|
|
286859
|
+
}
|
|
286860
|
+
markAttemptUnknown(pipelineId, taskId, attempt) {
|
|
286861
|
+
const result = this.db.prepare(`
|
|
286862
|
+
UPDATE agent_effects
|
|
286863
|
+
SET status = 'unknown', detail = COALESCE(detail, 'No matching tool result observed'), finished_at = ?
|
|
286864
|
+
WHERE pipeline_id = ? AND task_id = ? AND attempt = ? AND status = 'observed'
|
|
286865
|
+
`).run(Date.now(), pipelineId, taskId, attempt);
|
|
286866
|
+
return Number(result.changes ?? 0);
|
|
286867
|
+
}
|
|
286868
|
+
list(pipelineId, taskId) {
|
|
286869
|
+
const rows = taskId ? this.db.prepare("SELECT * FROM agent_effects WHERE pipeline_id = ? AND task_id = ? ORDER BY started_at ASC, rowid ASC").all(pipelineId, taskId) : this.db.prepare("SELECT * FROM agent_effects WHERE pipeline_id = ? ORDER BY started_at ASC, rowid ASC").all(pipelineId);
|
|
286870
|
+
return rows.map(rowToEffect);
|
|
286871
|
+
}
|
|
286872
|
+
};
|
|
286873
|
+
}
|
|
286874
|
+
});
|
|
286875
|
+
|
|
285571
286876
|
// src/orchestrate/memorix-bridge.ts
|
|
285572
|
-
import { createHash as
|
|
286877
|
+
import { createHash as createHash28 } from "crypto";
|
|
285573
286878
|
async function getStoreObservation() {
|
|
285574
286879
|
if (!_storeObservation) {
|
|
285575
286880
|
const mod = await Promise.resolve().then(() => (init_observations(), observations_exports));
|
|
@@ -285585,7 +286890,7 @@ async function getSearchObservations() {
|
|
|
285585
286890
|
return _searchObservations;
|
|
285586
286891
|
}
|
|
285587
286892
|
function automaticActorId(...parts) {
|
|
285588
|
-
return `orchestrator:${
|
|
286893
|
+
return `orchestrator:${createHash28("sha256").update(parts.join("\0")).digest("hex").slice(0, 24)}`;
|
|
285589
286894
|
}
|
|
285590
286895
|
function isEligibleAutomaticLesson(entry) {
|
|
285591
286896
|
return entry.admissionState !== "candidate" && entry.admissionState !== "ephemeral";
|
|
@@ -285732,7 +287037,7 @@ function sanitizeErrorPattern(text3) {
|
|
|
285732
287037
|
}
|
|
285733
287038
|
function hashErrorPattern(errorOutput) {
|
|
285734
287039
|
const sanitized = sanitizeErrorPattern(errorOutput).slice(0, 500);
|
|
285735
|
-
return
|
|
287040
|
+
return createHash28("sha256").update(sanitized).digest("hex").slice(0, 12);
|
|
285736
287041
|
}
|
|
285737
287042
|
function sleep6(ms2) {
|
|
285738
287043
|
return new Promise((resolve9) => setTimeout(() => resolve9([]), ms2));
|
|
@@ -285843,10 +287148,12 @@ async function runCoordinationLoop(config2) {
|
|
|
285843
287148
|
const dispatchedAdapterNames = /* @__PURE__ */ new Set();
|
|
285844
287149
|
const routingDecisions = [];
|
|
285845
287150
|
let traceDb = null;
|
|
287151
|
+
let effectLedger = null;
|
|
285846
287152
|
try {
|
|
285847
287153
|
traceDb = teamStore.getDb();
|
|
285848
287154
|
resetTraceCache();
|
|
285849
287155
|
initTraceTable(traceDb);
|
|
287156
|
+
if (pipelineId) effectLedger = new AgentEffectLedger(traceDb);
|
|
285850
287157
|
} catch {
|
|
285851
287158
|
}
|
|
285852
287159
|
if (useWorktrees) {
|
|
@@ -286147,6 +287454,32 @@ ${formatCostSummary(costSummary)}`);
|
|
|
286147
287454
|
for await (const msg of agentProcess.messages) {
|
|
286148
287455
|
if (msg.type === "tool_use") {
|
|
286149
287456
|
dispatch.toolCount++;
|
|
287457
|
+
const effectKey = msg.callId ?? `seq:${dispatch.toolCount}`;
|
|
287458
|
+
const effect = effectLedger?.observe({
|
|
287459
|
+
pipelineId,
|
|
287460
|
+
taskId: dispatch.taskId,
|
|
287461
|
+
attempt: dispatch.attempt,
|
|
287462
|
+
effectKey,
|
|
287463
|
+
tool: msg.tool ?? "unknown",
|
|
287464
|
+
...msg.callId ? { callId: msg.callId } : {},
|
|
287465
|
+
...msg.input ? { input: msg.input } : {}
|
|
287466
|
+
});
|
|
287467
|
+
if (effect && traceDb && pipelineId) {
|
|
287468
|
+
try {
|
|
287469
|
+
writeTrace(traceDb, {
|
|
287470
|
+
pipelineId,
|
|
287471
|
+
timestamp: Date.now(),
|
|
287472
|
+
type: "effect",
|
|
287473
|
+
taskId: dispatch.taskId,
|
|
287474
|
+
agent: dispatch.adapterName,
|
|
287475
|
+
detail: `observed tool=${effect.tool} risk=${effect.riskTier} replay=${effect.replayPolicy} effect=${effect.effectKey}`,
|
|
287476
|
+
attempt: dispatch.attempt,
|
|
287477
|
+
riskTier: effect.riskTier,
|
|
287478
|
+
effectKey: effect.effectKey
|
|
287479
|
+
});
|
|
287480
|
+
} catch {
|
|
287481
|
+
}
|
|
287482
|
+
}
|
|
286150
287483
|
if (msg.tool) tracker.record(msg.tool);
|
|
286151
287484
|
emit("agent:tool_use", `[${adapter.name}] tool #${dispatch.toolCount}: ${msg.tool ?? "unknown"}`, {
|
|
286152
287485
|
taskId: task.task_id,
|
|
@@ -286166,6 +287499,16 @@ ${formatCostSummary(costSummary)}`);
|
|
|
286166
287499
|
}
|
|
286167
287500
|
}
|
|
286168
287501
|
}
|
|
287502
|
+
if (msg.type === "tool_result" && msg.callId && effectLedger && pipelineId) {
|
|
287503
|
+
effectLedger.settle({
|
|
287504
|
+
pipelineId,
|
|
287505
|
+
taskId: dispatch.taskId,
|
|
287506
|
+
attempt: dispatch.attempt,
|
|
287507
|
+
effectKey: msg.callId,
|
|
287508
|
+
status: "succeeded",
|
|
287509
|
+
detail: "tool result observed"
|
|
287510
|
+
});
|
|
287511
|
+
}
|
|
286169
287512
|
if (msg.type === "text" && msg.content) {
|
|
286170
287513
|
dispatch.accumulatedText += msg.content;
|
|
286171
287514
|
}
|
|
@@ -286248,6 +287591,9 @@ ${formatCostSummary(costSummary)}`);
|
|
|
286248
287591
|
if (result.sessionId) {
|
|
286249
287592
|
taskSessionIds.set(dispatch.taskId, result.sessionId);
|
|
286250
287593
|
}
|
|
287594
|
+
if (effectLedger && pipelineId) {
|
|
287595
|
+
effectLedger.markAttemptUnknown(pipelineId, dispatch.taskId, dispatch.attempt);
|
|
287596
|
+
}
|
|
286251
287597
|
const taskState = teamStore.getTask(dispatch.taskId);
|
|
286252
287598
|
const taskDesc = taskState?.description ?? dispatch.taskId;
|
|
286253
287599
|
if (!result.killed && result.exitCode === 0) {
|
|
@@ -286311,6 +287657,25 @@ ${formatCostSummary(costSummary)}`);
|
|
|
286311
287657
|
for await (const msg of fixProcess.messages) {
|
|
286312
287658
|
if (msg.type === "tool_use") {
|
|
286313
287659
|
fixDispatch.toolCount++;
|
|
287660
|
+
effectLedger?.observe({
|
|
287661
|
+
pipelineId,
|
|
287662
|
+
taskId: fixDispatch.taskId,
|
|
287663
|
+
attempt: fixDispatch.attempt,
|
|
287664
|
+
effectKey: msg.callId ?? `seq:${fixDispatch.toolCount}`,
|
|
287665
|
+
tool: msg.tool ?? "unknown",
|
|
287666
|
+
...msg.callId ? { callId: msg.callId } : {},
|
|
287667
|
+
...msg.input ? { input: msg.input } : {}
|
|
287668
|
+
});
|
|
287669
|
+
}
|
|
287670
|
+
if (msg.type === "tool_result" && msg.callId && effectLedger && pipelineId) {
|
|
287671
|
+
effectLedger.settle({
|
|
287672
|
+
pipelineId,
|
|
287673
|
+
taskId: fixDispatch.taskId,
|
|
287674
|
+
attempt: fixDispatch.attempt,
|
|
287675
|
+
effectKey: msg.callId,
|
|
287676
|
+
status: "succeeded",
|
|
287677
|
+
detail: "tool result observed"
|
|
287678
|
+
});
|
|
286314
287679
|
}
|
|
286315
287680
|
if (msg.type === "text" && msg.content) {
|
|
286316
287681
|
fixDispatch.accumulatedText += msg.content;
|
|
@@ -286740,6 +288105,7 @@ var init_coordinator = __esm({
|
|
|
286740
288105
|
init_cost_tracker();
|
|
286741
288106
|
init_evidence2();
|
|
286742
288107
|
init_permission();
|
|
288108
|
+
init_effect_ledger();
|
|
286743
288109
|
init_memorix_bridge();
|
|
286744
288110
|
}
|
|
286745
288111
|
});
|
|
@@ -288149,6 +289515,7 @@ function ConfigureView({ onBack }) {
|
|
|
288149
289515
|
{ key: "openai", label: "OpenAI", hint: "gpt-4o-mini" },
|
|
288150
289516
|
{ key: "anthropic", label: "Anthropic", hint: "claude-3-haiku" },
|
|
288151
289517
|
{ key: "openrouter", label: "OpenRouter", hint: "multi-provider" },
|
|
289518
|
+
{ key: "atlascloud", label: "Atlas Cloud", hint: "DeepSeek V3.2" },
|
|
288152
289519
|
{ key: "custom", label: "Custom endpoint", hint: "OpenAI-compatible" },
|
|
288153
289520
|
{ key: "disable", label: "Disable LLM", hint: "free heuristic mode", color: COLORS.warning },
|
|
288154
289521
|
{ key: "back", label: "Back", hint: "", color: COLORS.muted }
|
|
@@ -288441,6 +289808,7 @@ function ConfigureView({ onBack }) {
|
|
|
288441
289808
|
function getDefaultModel(provider2) {
|
|
288442
289809
|
if (provider2 === "anthropic") return "claude-3-haiku-20240307";
|
|
288443
289810
|
if (provider2 === "openrouter") return "openai/gpt-4o-mini";
|
|
289811
|
+
if (provider2 === "atlascloud") return "deepseek-ai/deepseek-v3.2";
|
|
288444
289812
|
return "gpt-4o-mini";
|
|
288445
289813
|
}
|
|
288446
289814
|
var init_ConfigureView = __esm({
|
|
@@ -291646,10 +293014,22 @@ var GUIDES = {
|
|
|
291646
293014
|
context: {
|
|
291647
293015
|
summary: "Build the bounded task Workset used to resume or begin real work.",
|
|
291648
293016
|
usage: [
|
|
291649
|
-
'memorix context "continue the release fix" [--refresh auto|always|never]',
|
|
293017
|
+
'memorix context "continue the release fix" [--task-id <continuity-id>] [--refresh auto|always|never]',
|
|
291650
293018
|
'memorix resume "continue the release fix" [--refresh auto|always|never]'
|
|
291651
293019
|
]
|
|
291652
293020
|
},
|
|
293021
|
+
continuity: {
|
|
293022
|
+
summary: "Track task requirements, decisions, verification, risks, and outcomes.",
|
|
293023
|
+
usage: [
|
|
293024
|
+
'memorix continuity start --task "Harden the release path" [--requirements "a,b"]',
|
|
293025
|
+
'memorix continuity record --task-id <id> --kind decision --content "..."',
|
|
293026
|
+
'memorix continuity record --task-id <id> --kind verification --verification-status passed --content "..."',
|
|
293027
|
+
"memorix continuity show --task-id <id>",
|
|
293028
|
+
'memorix continuity close --task-id <id> --status completed --content "..."',
|
|
293029
|
+
"memorix continuity list"
|
|
293030
|
+
],
|
|
293031
|
+
notes: ["Pass the returned task id to memorix context --task-id so the bounded brief includes the ledger."]
|
|
293032
|
+
},
|
|
291653
293033
|
explain: {
|
|
291654
293034
|
summary: "Show why a task context contains its current facts and memory evidence.",
|
|
291655
293035
|
usage: ["memorix explain [--refresh auto|always|never]"]
|
|
@@ -292058,6 +293438,7 @@ var main2 = defineCommand({
|
|
|
292058
293438
|
knowledge: () => Promise.resolve().then(() => (init_knowledge(), knowledge_exports)).then((m6) => m6.default),
|
|
292059
293439
|
evidence: () => Promise.resolve().then(() => (init_evidence(), evidence_exports)).then((m6) => m6.default),
|
|
292060
293440
|
feedback: () => Promise.resolve().then(() => (init_feedback2(), feedback_exports2)).then((m6) => m6.default),
|
|
293441
|
+
continuity: () => Promise.resolve().then(() => (init_continuity(), continuity_exports)).then((m6) => m6.default),
|
|
292061
293442
|
reasoning: () => Promise.resolve().then(() => (init_reasoning(), reasoning_exports)).then((m6) => m6.default),
|
|
292062
293443
|
retention: () => Promise.resolve().then(() => (init_retention2(), retention_exports2)).then((m6) => m6.default),
|
|
292063
293444
|
formation: () => Promise.resolve().then(() => (init_formation2(), formation_exports2)).then((m6) => m6.default),
|
|
@@ -292158,6 +293539,7 @@ var main2 = defineCommand({
|
|
|
292158
293539
|
"poll",
|
|
292159
293540
|
"evidence",
|
|
292160
293541
|
"feedback",
|
|
293542
|
+
"continuity",
|
|
292161
293543
|
"receipt",
|
|
292162
293544
|
"serve",
|
|
292163
293545
|
"serve-http",
|
|
@@ -292222,6 +293604,7 @@ var main2 = defineCommand({
|
|
|
292222
293604
|
console.error(" knowledge Review source-backed knowledge pages and project workflows");
|
|
292223
293605
|
console.error(" evidence Inspect source-backed evidence cards");
|
|
292224
293606
|
console.error(" feedback Record or audit memory feedback");
|
|
293607
|
+
console.error(" continuity Record task requirements, decisions, verification, and outcome");
|
|
292225
293608
|
console.error(" reasoning Store/search decision rationale");
|
|
292226
293609
|
console.error(" retention Inspect stale/archive status");
|
|
292227
293610
|
console.error(" formation Inspect Memory Formation metrics");
|