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/index.js
CHANGED
|
@@ -444,11 +444,21 @@ function applySchemaMigrations(db2) {
|
|
|
444
444
|
apply();
|
|
445
445
|
}
|
|
446
446
|
}
|
|
447
|
+
function normalizeDataDir(dataDir) {
|
|
448
|
+
return path3.resolve(dataDir);
|
|
449
|
+
}
|
|
450
|
+
function touchDatabase(normalized, db2) {
|
|
451
|
+
_dbCache.delete(normalized);
|
|
452
|
+
_dbCache.set(normalized, db2);
|
|
453
|
+
}
|
|
447
454
|
function getDatabase(dataDir) {
|
|
448
|
-
const normalized =
|
|
455
|
+
const normalized = normalizeDataDir(dataDir);
|
|
449
456
|
assertNotHomeDataDir(normalized);
|
|
450
457
|
const existing = _dbCache.get(normalized);
|
|
451
|
-
if (existing)
|
|
458
|
+
if (existing) {
|
|
459
|
+
touchDatabase(normalized, existing);
|
|
460
|
+
return existing;
|
|
461
|
+
}
|
|
452
462
|
loadBetterSqlite3();
|
|
453
463
|
fs.mkdirSync(dataDir, { recursive: true });
|
|
454
464
|
const dbPath = path3.join(dataDir, "memorix.db");
|
|
@@ -478,6 +488,8 @@ function getDatabase(dataDir) {
|
|
|
478
488
|
db2.exec(CREATE_MAINTENANCE_JOBS_TABLE);
|
|
479
489
|
db2.exec(CREATE_MAINTENANCE_TARGETS_TABLE);
|
|
480
490
|
db2.exec(CREATE_COMPACTION_CHECKPOINTS_TABLE);
|
|
491
|
+
db2.exec(CREATE_TASK_CONTINUITY_EVENTS_TABLE);
|
|
492
|
+
db2.exec(CREATE_AGENT_EFFECTS_TABLE);
|
|
481
493
|
try {
|
|
482
494
|
db2.exec(`ALTER TABLE mini_skills ADD COLUMN sourceSnapshot TEXT NOT NULL DEFAULT ''`);
|
|
483
495
|
} catch {
|
|
@@ -516,7 +528,7 @@ function getDatabase(dataDir) {
|
|
|
516
528
|
db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('storage_generation', '0')`).run();
|
|
517
529
|
db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('next_id', '1')`).run();
|
|
518
530
|
db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('mini_skills_generation', '0')`).run();
|
|
519
|
-
|
|
531
|
+
touchDatabase(normalized, db2);
|
|
520
532
|
return db2;
|
|
521
533
|
} catch (error) {
|
|
522
534
|
try {
|
|
@@ -534,8 +546,9 @@ function closeAllDatabases() {
|
|
|
534
546
|
}
|
|
535
547
|
_dbCache.delete(key);
|
|
536
548
|
}
|
|
549
|
+
_dbLeases.clear();
|
|
537
550
|
}
|
|
538
|
-
var BetterSqlite3, CREATE_OBSERVATIONS_TABLE, CREATE_MINI_SKILLS_TABLE, CREATE_SESSIONS_TABLE, CREATE_META_TABLE, CREATE_TEAM_AGENTS_TABLE, CREATE_TEAM_MESSAGES_TABLE, CREATE_TEAM_TASKS_TABLE, CREATE_TEAM_TASK_DEPS_TABLE, CREATE_TEAM_LOCKS_TABLE, CREATE_TEAM_ROLES_TABLE, CREATE_CHAT_TRANSCRIPT_TABLE, CREATE_GRAPH_ENTITIES_TABLE, CREATE_GRAPH_RELATIONS_TABLE, CREATE_CODE_FILES_TABLE, CREATE_CODE_SYMBOLS_TABLE, CREATE_CODE_EDGES_TABLE, CREATE_OBSERVATION_CODE_REFS_TABLE, CREATE_SCHEMA_MIGRATIONS_TABLE, CREATE_CODE_STATE_SNAPSHOTS_TABLE, CREATE_CODE_STATE_SNAPSHOT_FILES_TABLE, CREATE_KNOWLEDGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_CLAIM_EVIDENCE_TABLE, CREATE_KNOWLEDGE_CLAIM_EVENTS_TABLE, CREATE_KNOWLEDGE_WORKSPACES_TABLE, CREATE_KNOWLEDGE_PAGES_TABLE, CREATE_KNOWLEDGE_PAGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_PAGE_LINKS_TABLE, CREATE_KNOWLEDGE_PROPOSALS_TABLE, CREATE_KNOWLEDGE_WORKFLOWS_TABLE, CREATE_KNOWLEDGE_WORKFLOW_RUNS_TABLE, CREATE_LONG_TERM_MEMORIES_TABLE, CREATE_LONG_TERM_MEMORY_EVIDENCE_TABLE, CREATE_LONG_TERM_MEMORY_EVENTS_TABLE, CREATE_MEMORY_OUTCOME_SIGNALS_TABLE, CREATE_MEDIA_ASSETS_TABLE, CREATE_MEDIA_ASSET_LINKS_TABLE, CREATE_MEDIA_DERIVATIONS_TABLE, CREATE_MEDIA_EMBEDDING_PROFILES_TABLE, CREATE_MEDIA_EMBEDDINGS_TABLE, CREATE_MEDIA_JOBS_TABLE, CREATE_MAINTENANCE_JOBS_TABLE, CREATE_MAINTENANCE_TARGETS_TABLE, CREATE_COMPACTION_CHECKPOINTS_TABLE, CREATE_EVIDENCE_CARDS_TABLE, CREATE_EVIDENCE_CARD_EVENTS_TABLE, CREATE_MEMORY_FEEDBACK_STATES_TABLE, CREATE_MEMORY_FEEDBACK_EVENTS_TABLE, CREATE_MCP_BINDINGS_TABLE, CREATE_INDEXES, SCHEMA_MIGRATIONS, _dbCache;
|
|
551
|
+
var BetterSqlite3, CREATE_OBSERVATIONS_TABLE, CREATE_MINI_SKILLS_TABLE, CREATE_SESSIONS_TABLE, CREATE_META_TABLE, CREATE_TEAM_AGENTS_TABLE, CREATE_TEAM_MESSAGES_TABLE, CREATE_TEAM_TASKS_TABLE, CREATE_TEAM_TASK_DEPS_TABLE, CREATE_TEAM_LOCKS_TABLE, CREATE_TEAM_ROLES_TABLE, CREATE_CHAT_TRANSCRIPT_TABLE, CREATE_GRAPH_ENTITIES_TABLE, CREATE_GRAPH_RELATIONS_TABLE, CREATE_CODE_FILES_TABLE, CREATE_CODE_SYMBOLS_TABLE, CREATE_CODE_EDGES_TABLE, CREATE_OBSERVATION_CODE_REFS_TABLE, CREATE_SCHEMA_MIGRATIONS_TABLE, CREATE_CODE_STATE_SNAPSHOTS_TABLE, CREATE_CODE_STATE_SNAPSHOT_FILES_TABLE, CREATE_KNOWLEDGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_CLAIM_EVIDENCE_TABLE, CREATE_KNOWLEDGE_CLAIM_EVENTS_TABLE, CREATE_KNOWLEDGE_WORKSPACES_TABLE, CREATE_KNOWLEDGE_PAGES_TABLE, CREATE_KNOWLEDGE_PAGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_PAGE_LINKS_TABLE, CREATE_KNOWLEDGE_PROPOSALS_TABLE, CREATE_KNOWLEDGE_WORKFLOWS_TABLE, CREATE_KNOWLEDGE_WORKFLOW_RUNS_TABLE, CREATE_LONG_TERM_MEMORIES_TABLE, CREATE_LONG_TERM_MEMORY_EVIDENCE_TABLE, CREATE_LONG_TERM_MEMORY_EVENTS_TABLE, CREATE_MEMORY_OUTCOME_SIGNALS_TABLE, CREATE_MEDIA_ASSETS_TABLE, CREATE_MEDIA_ASSET_LINKS_TABLE, CREATE_MEDIA_DERIVATIONS_TABLE, CREATE_MEDIA_EMBEDDING_PROFILES_TABLE, CREATE_MEDIA_EMBEDDINGS_TABLE, CREATE_MEDIA_JOBS_TABLE, CREATE_MAINTENANCE_JOBS_TABLE, CREATE_MAINTENANCE_TARGETS_TABLE, CREATE_COMPACTION_CHECKPOINTS_TABLE, CREATE_EVIDENCE_CARDS_TABLE, CREATE_EVIDENCE_CARD_EVENTS_TABLE, CREATE_MEMORY_FEEDBACK_STATES_TABLE, CREATE_MEMORY_FEEDBACK_EVENTS_TABLE, CREATE_TASK_CONTINUITY_EVENTS_TABLE, CREATE_AGENT_EFFECTS_TABLE, CREATE_MCP_BINDINGS_TABLE, CREATE_INDEXES, SCHEMA_MIGRATIONS, _dbCache, _dbLeases;
|
|
539
552
|
var init_sqlite_db = __esm({
|
|
540
553
|
"src/store/sqlite-db.ts"() {
|
|
541
554
|
"use strict";
|
|
@@ -1252,6 +1265,43 @@ CREATE TABLE IF NOT EXISTS memory_feedback_events (
|
|
|
1252
1265
|
delta REAL NOT NULL DEFAULT 0,
|
|
1253
1266
|
observed_at TEXT NOT NULL
|
|
1254
1267
|
);
|
|
1268
|
+
`;
|
|
1269
|
+
CREATE_TASK_CONTINUITY_EVENTS_TABLE = `
|
|
1270
|
+
CREATE TABLE IF NOT EXISTS task_continuity_events (
|
|
1271
|
+
id TEXT PRIMARY KEY,
|
|
1272
|
+
project_id TEXT NOT NULL,
|
|
1273
|
+
task_id TEXT NOT NULL,
|
|
1274
|
+
task TEXT NOT NULL,
|
|
1275
|
+
kind TEXT NOT NULL,
|
|
1276
|
+
content TEXT NOT NULL,
|
|
1277
|
+
item_status TEXT,
|
|
1278
|
+
source_ref TEXT,
|
|
1279
|
+
evidence_json TEXT NOT NULL DEFAULT '[]',
|
|
1280
|
+
actor TEXT,
|
|
1281
|
+
created_at TEXT NOT NULL,
|
|
1282
|
+
event_key TEXT,
|
|
1283
|
+
item_key TEXT,
|
|
1284
|
+
supersedes_id TEXT
|
|
1285
|
+
);
|
|
1286
|
+
`;
|
|
1287
|
+
CREATE_AGENT_EFFECTS_TABLE = `
|
|
1288
|
+
CREATE TABLE IF NOT EXISTS agent_effects (
|
|
1289
|
+
id TEXT PRIMARY KEY,
|
|
1290
|
+
pipeline_id TEXT NOT NULL,
|
|
1291
|
+
task_id TEXT NOT NULL,
|
|
1292
|
+
attempt INTEGER NOT NULL,
|
|
1293
|
+
effect_key TEXT NOT NULL,
|
|
1294
|
+
tool TEXT NOT NULL,
|
|
1295
|
+
risk_tier TEXT NOT NULL,
|
|
1296
|
+
replay_policy TEXT NOT NULL,
|
|
1297
|
+
status TEXT NOT NULL,
|
|
1298
|
+
call_id TEXT,
|
|
1299
|
+
idempotency_key TEXT NOT NULL,
|
|
1300
|
+
input_fingerprint TEXT,
|
|
1301
|
+
detail TEXT,
|
|
1302
|
+
started_at INTEGER NOT NULL,
|
|
1303
|
+
finished_at INTEGER
|
|
1304
|
+
);
|
|
1255
1305
|
`;
|
|
1256
1306
|
CREATE_MCP_BINDINGS_TABLE = `
|
|
1257
1307
|
CREATE TABLE IF NOT EXISTS mcp_bindings (
|
|
@@ -1330,7 +1380,18 @@ CREATE INDEX IF NOT EXISTS idx_evidence_cards_candidate ON evidence_cards(projec
|
|
|
1330
1380
|
CREATE INDEX IF NOT EXISTS idx_evidence_card_events_card ON evidence_card_events(card_id, created_at);
|
|
1331
1381
|
CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC);
|
|
1332
1382
|
CREATE INDEX IF NOT EXISTS idx_memory_feedback_events_candidate ON memory_feedback_events(project_id, candidate_kind, candidate_id, observed_at DESC);
|
|
1383
|
+
CREATE INDEX IF NOT EXISTS idx_task_continuity_project_task ON task_continuity_events(project_id, task_id, created_at ASC);
|
|
1384
|
+
CREATE INDEX IF NOT EXISTS idx_task_continuity_project_recent ON task_continuity_events(project_id, created_at DESC);
|
|
1385
|
+
CREATE INDEX IF NOT EXISTS idx_task_continuity_item ON task_continuity_events(project_id, task_id, kind, item_key, created_at DESC);
|
|
1386
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_task_continuity_event_key
|
|
1387
|
+
ON task_continuity_events(project_id, task_id, event_key)
|
|
1388
|
+
WHERE event_key IS NOT NULL;
|
|
1389
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_agent_effect_identity
|
|
1390
|
+
ON agent_effects(pipeline_id, task_id, attempt, effect_key);
|
|
1391
|
+
CREATE INDEX IF NOT EXISTS idx_agent_effect_pipeline ON agent_effects(pipeline_id, started_at ASC);
|
|
1333
1392
|
CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC);
|
|
1393
|
+
CREATE INDEX IF NOT EXISTS idx_mcp_bindings_root ON mcp_bindings(project_root, last_used_at DESC);
|
|
1394
|
+
CREATE INDEX IF NOT EXISTS idx_mcp_bindings_expiry ON mcp_bindings(expires_at);
|
|
1334
1395
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
1335
1396
|
ON maintenance_jobs(project_id, kind, dedupe_key)
|
|
1336
1397
|
WHERE status IN ('pending', 'running', 'retry');
|
|
@@ -1501,6 +1562,8 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
|
1501
1562
|
db2.exec("CREATE INDEX IF NOT EXISTS idx_memory_feedback_states_project ON memory_feedback_states(project_id, candidate_kind, updated_at DESC)");
|
|
1502
1563
|
db2.exec("CREATE INDEX IF NOT EXISTS idx_memory_feedback_events_candidate ON memory_feedback_events(project_id, candidate_kind, candidate_id, observed_at DESC)");
|
|
1503
1564
|
db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_project ON mcp_bindings(project_id, last_used_at DESC)");
|
|
1565
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_root ON mcp_bindings(project_root, last_used_at DESC)");
|
|
1566
|
+
db2.exec("CREATE INDEX IF NOT EXISTS idx_mcp_bindings_expiry ON mcp_bindings(expires_at)");
|
|
1504
1567
|
}
|
|
1505
1568
|
},
|
|
1506
1569
|
{
|
|
@@ -1511,9 +1574,22 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
|
|
|
1511
1574
|
addColumnIfMissing(db2, "code_symbols", "source", "source TEXT");
|
|
1512
1575
|
addColumnIfMissing(db2, "code_edges", "source", "source TEXT");
|
|
1513
1576
|
}
|
|
1577
|
+
},
|
|
1578
|
+
{
|
|
1579
|
+
id: "1.9-continuity-v2",
|
|
1580
|
+
apply: (db2) => {
|
|
1581
|
+
addColumnIfMissing(db2, "task_continuity_events", "event_key", "event_key TEXT");
|
|
1582
|
+
addColumnIfMissing(db2, "task_continuity_events", "item_key", "item_key TEXT");
|
|
1583
|
+
addColumnIfMissing(db2, "task_continuity_events", "supersedes_id", "supersedes_id TEXT");
|
|
1584
|
+
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)");
|
|
1585
|
+
db2.exec(`CREATE UNIQUE INDEX IF NOT EXISTS idx_task_continuity_event_key
|
|
1586
|
+
ON task_continuity_events(project_id, task_id, event_key)
|
|
1587
|
+
WHERE event_key IS NOT NULL`);
|
|
1588
|
+
}
|
|
1514
1589
|
}
|
|
1515
1590
|
];
|
|
1516
1591
|
_dbCache = /* @__PURE__ */ new Map();
|
|
1592
|
+
_dbLeases = /* @__PURE__ */ new Map();
|
|
1517
1593
|
}
|
|
1518
1594
|
});
|
|
1519
1595
|
|
|
@@ -3228,18 +3304,23 @@ __export(yaml_loader_exports, {
|
|
|
3228
3304
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
3229
3305
|
import { homedir } from "os";
|
|
3230
3306
|
import { parse as parseYamlDocument } from "yaml";
|
|
3307
|
+
function cacheKey(homeDir, projectRoot) {
|
|
3308
|
+
return `${homeDir}\0${projectRoot ?? ""}`;
|
|
3309
|
+
}
|
|
3231
3310
|
function initProjectRoot(root) {
|
|
3232
3311
|
globalProjectRoot = root;
|
|
3233
|
-
configCache.delete(root);
|
|
3312
|
+
configCache.delete(cacheKey(homedir(), root));
|
|
3234
3313
|
}
|
|
3235
3314
|
function clearProjectRoot() {
|
|
3236
3315
|
globalProjectRoot = null;
|
|
3237
3316
|
}
|
|
3238
|
-
function loadYamlConfig(projectRoot) {
|
|
3317
|
+
function loadYamlConfig(projectRoot, options = {}) {
|
|
3318
|
+
const homeDir = options.homeDir ?? homedir();
|
|
3239
3319
|
const resolvedRoot = projectRoot === null ? null : projectRoot ?? globalProjectRoot ?? null;
|
|
3240
|
-
const
|
|
3320
|
+
const key = cacheKey(homeDir, resolvedRoot);
|
|
3321
|
+
const cached = configCache.get(key);
|
|
3241
3322
|
if (cached) return cached;
|
|
3242
|
-
const userYaml = getGlobalYamlPath(
|
|
3323
|
+
const userYaml = getGlobalYamlPath(homeDir);
|
|
3243
3324
|
const projectYaml = resolvedRoot ? getProjectYamlPath(resolvedRoot) : null;
|
|
3244
3325
|
let userConfig = {};
|
|
3245
3326
|
let projectConfig = {};
|
|
@@ -3271,12 +3352,12 @@ function loadYamlConfig(projectRoot) {
|
|
|
3271
3352
|
server: { ...userConfig.server, ...projectConfig.server },
|
|
3272
3353
|
team: { ...userConfig.team, ...projectConfig.team }
|
|
3273
3354
|
};
|
|
3274
|
-
configCache.set(
|
|
3355
|
+
configCache.set(key, merged);
|
|
3275
3356
|
return merged;
|
|
3276
3357
|
}
|
|
3277
|
-
function resetYamlConfigCache(projectRoot) {
|
|
3358
|
+
function resetYamlConfigCache(projectRoot, homeDir = homedir()) {
|
|
3278
3359
|
if (projectRoot !== void 0) {
|
|
3279
|
-
configCache.delete(projectRoot ?? null);
|
|
3360
|
+
configCache.delete(cacheKey(homeDir, projectRoot ?? null));
|
|
3280
3361
|
} else {
|
|
3281
3362
|
configCache.clear();
|
|
3282
3363
|
}
|
|
@@ -3486,9 +3567,9 @@ var init_detector = __esm({
|
|
|
3486
3567
|
// src/config/legacy-loader.ts
|
|
3487
3568
|
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
|
|
3488
3569
|
import { homedir as homedir2 } from "os";
|
|
3489
|
-
function loadFileConfig() {
|
|
3570
|
+
function loadFileConfig(homeDir = homedir2()) {
|
|
3490
3571
|
if (cachedConfig !== null) return cachedConfig;
|
|
3491
|
-
const configPath = getLegacyConfigJsonPath(
|
|
3572
|
+
const configPath = getLegacyConfigJsonPath(homeDir);
|
|
3492
3573
|
try {
|
|
3493
3574
|
if (existsSync4(configPath)) {
|
|
3494
3575
|
cachedConfig = JSON.parse(readFileSync4(configPath, "utf-8"));
|
|
@@ -3518,15 +3599,15 @@ import { homedir as homedir3 } from "os";
|
|
|
3518
3599
|
function loadTomlConfig(options = {}) {
|
|
3519
3600
|
const homeDir = options.homeDir ?? homedir3();
|
|
3520
3601
|
const projectRoot = options.projectRoot ?? null;
|
|
3521
|
-
const
|
|
3522
|
-
const cached = configCache2.get(
|
|
3602
|
+
const cacheKey3 = `${homeDir}\0${projectRoot ?? ""}`;
|
|
3603
|
+
const cached = configCache2.get(cacheKey3);
|
|
3523
3604
|
if (cached) return cached;
|
|
3524
3605
|
const userToml = getGlobalConfigTomlPath(homeDir);
|
|
3525
3606
|
const projectToml = projectRoot ? getProjectConfigTomlPath(projectRoot) : null;
|
|
3526
3607
|
const userConfig = existsSync5(userToml) ? parseTomlConfig(readFileSync5(userToml, "utf8"), userToml) : {};
|
|
3527
3608
|
const projectConfig = projectToml && existsSync5(projectToml) ? parseTomlConfig(readFileSync5(projectToml, "utf8"), projectToml) : {};
|
|
3528
3609
|
const merged = mergeTomlConfig(userConfig, projectConfig);
|
|
3529
|
-
configCache2.set(
|
|
3610
|
+
configCache2.set(cacheKey3, merged);
|
|
3530
3611
|
return merged;
|
|
3531
3612
|
}
|
|
3532
3613
|
function mergeTomlConfig(base, override) {
|
|
@@ -3726,8 +3807,8 @@ function getResolvedConfig(options = {}) {
|
|
|
3726
3807
|
const projectRoot = options.projectRoot === void 0 ? detectProject()?.rootPath ?? null : options.projectRoot;
|
|
3727
3808
|
loadDotenv(projectRoot === null ? void 0 : projectRoot ?? void 0, { userHomeDir: homeDir });
|
|
3728
3809
|
const toml = loadTomlConfig({ projectRoot: projectRoot ?? null, homeDir });
|
|
3729
|
-
const yaml = loadYamlConfig(projectRoot ?? null);
|
|
3730
|
-
const legacy = loadFileConfig();
|
|
3810
|
+
const yaml = loadYamlConfig(projectRoot ?? null, { homeDir });
|
|
3811
|
+
const legacy = loadFileConfig(homeDir);
|
|
3731
3812
|
const embeddingBaseUrl = first(process.env.MEMORIX_EMBEDDING_BASE_URL, toml.embedding?.base_url, yaml.embedding?.baseUrl, legacy.embeddingApi?.baseUrl);
|
|
3732
3813
|
const openRouterEmbeddingApiKey = isOpenRouterUrl(embeddingBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
|
|
3733
3814
|
const memoryLlmProvider = first(
|
|
@@ -3749,15 +3830,17 @@ function getResolvedConfig(options = {}) {
|
|
|
3749
3830
|
legacy.llm?.baseUrl
|
|
3750
3831
|
);
|
|
3751
3832
|
const openRouterMemoryLlmApiKey = isOpenRouterMemoryLane(memoryLlmProvider, memoryLlmBaseUrl) ? process.env.OPENROUTER_API_KEY : void 0;
|
|
3833
|
+
const isAtlasCloud = memoryLlmProvider === "atlascloud";
|
|
3752
3834
|
const memoryLlmApiKey = first(
|
|
3753
3835
|
process.env.MEMORIX_LLM_API_KEY,
|
|
3754
3836
|
process.env.MEMORIX_API_KEY,
|
|
3755
3837
|
toml.memory?.llm?.api_key,
|
|
3756
3838
|
yaml.llm?.apiKey,
|
|
3757
3839
|
legacy.llm?.apiKey,
|
|
3758
|
-
|
|
3759
|
-
process.env.
|
|
3760
|
-
|
|
3840
|
+
// Never borrow another provider's credentials for the Atlas Cloud preset.
|
|
3841
|
+
isAtlasCloud ? process.env.ATLASCLOUD_API_KEY : process.env.OPENAI_API_KEY,
|
|
3842
|
+
isAtlasCloud ? void 0 : process.env.ANTHROPIC_API_KEY,
|
|
3843
|
+
isAtlasCloud ? void 0 : openRouterMemoryLlmApiKey
|
|
3761
3844
|
);
|
|
3762
3845
|
const resolved = {
|
|
3763
3846
|
agent: {
|
|
@@ -3936,7 +4019,8 @@ function getEnvSourceNames() {
|
|
|
3936
4019
|
"MEMORIX_CODEGRAPH_EXTERNAL_CONTEXT",
|
|
3937
4020
|
"MEMORIX_CODEGRAPH_EXTERNAL_COMMAND",
|
|
3938
4021
|
"MEMORIX_CODEGRAPH_EXTERNAL_TIMEOUT_MS",
|
|
3939
|
-
"OPENROUTER_API_KEY"
|
|
4022
|
+
"OPENROUTER_API_KEY",
|
|
4023
|
+
"ATLASCLOUD_API_KEY"
|
|
3940
4024
|
].filter((name) => process.env[name]);
|
|
3941
4025
|
}
|
|
3942
4026
|
function isOpenRouterUrl(value) {
|
|
@@ -4155,12 +4239,45 @@ function textHash(text3) {
|
|
|
4155
4239
|
async function loadDiskCache() {
|
|
4156
4240
|
try {
|
|
4157
4241
|
const raw = await readFile(CACHE_FILE, "utf-8");
|
|
4242
|
+
if (Buffer.byteLength(raw, "utf8") > MAX_CACHE_FILE_BYTES) {
|
|
4243
|
+
console.error("[memorix] FastEmbed cache exceeds the disk load limit; starting with an empty cache");
|
|
4244
|
+
return;
|
|
4245
|
+
}
|
|
4158
4246
|
const entries = JSON.parse(raw);
|
|
4159
|
-
|
|
4160
|
-
|
|
4247
|
+
if (!Array.isArray(entries)) return;
|
|
4248
|
+
for (const entry of entries) {
|
|
4249
|
+
if (!Array.isArray(entry) || typeof entry[0] !== "string" || !isVector(entry[1])) continue;
|
|
4250
|
+
cacheSet(entry[0], entry[1], false);
|
|
4251
|
+
}
|
|
4252
|
+
console.error(`[memorix] Loaded ${cache.size} cached embeddings from disk`);
|
|
4161
4253
|
} catch {
|
|
4162
4254
|
}
|
|
4163
4255
|
}
|
|
4256
|
+
function isVector(value) {
|
|
4257
|
+
return Array.isArray(value) && value.every((entry) => typeof entry === "number");
|
|
4258
|
+
}
|
|
4259
|
+
function maxCachePayloadBytes() {
|
|
4260
|
+
const raw = Number.parseInt(process.env.MEMORIX_EMBEDDING_CACHE_MAX_BYTES ?? "", 10);
|
|
4261
|
+
return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_CACHE_PAYLOAD_BYTES;
|
|
4262
|
+
}
|
|
4263
|
+
function cacheSet(hash4, value, markDirty = true) {
|
|
4264
|
+
const incomingBytes = value.length * 8;
|
|
4265
|
+
if (incomingBytes > maxCachePayloadBytes()) return;
|
|
4266
|
+
const existing = cache.get(hash4);
|
|
4267
|
+
if (existing) cachePayloadBytes -= existing.length * 8;
|
|
4268
|
+
else {
|
|
4269
|
+
while (cache.size >= MAX_CACHE_SIZE || cachePayloadBytes + incomingBytes > maxCachePayloadBytes()) {
|
|
4270
|
+
const firstKey = cache.keys().next().value;
|
|
4271
|
+
if (firstKey === void 0) break;
|
|
4272
|
+
const old = cache.get(firstKey);
|
|
4273
|
+
cache.delete(firstKey);
|
|
4274
|
+
if (old) cachePayloadBytes -= old.length * 8;
|
|
4275
|
+
}
|
|
4276
|
+
}
|
|
4277
|
+
cache.set(hash4, value);
|
|
4278
|
+
cachePayloadBytes += incomingBytes;
|
|
4279
|
+
if (markDirty) diskCacheDirty = true;
|
|
4280
|
+
}
|
|
4164
4281
|
async function saveDiskCache() {
|
|
4165
4282
|
if (!diskCacheDirty) return;
|
|
4166
4283
|
try {
|
|
@@ -4171,7 +4288,7 @@ async function saveDiskCache() {
|
|
|
4171
4288
|
} catch {
|
|
4172
4289
|
}
|
|
4173
4290
|
}
|
|
4174
|
-
var CACHE_DIR, CACHE_FILE, cache, MAX_CACHE_SIZE, diskCacheDirty, FastEmbedProvider;
|
|
4291
|
+
var CACHE_DIR, CACHE_FILE, cache, MAX_CACHE_SIZE, DEFAULT_CACHE_PAYLOAD_BYTES, MAX_CACHE_FILE_BYTES, cachePayloadBytes, diskCacheDirty, FastEmbedProvider;
|
|
4175
4292
|
var init_fastembed_provider = __esm({
|
|
4176
4293
|
"src/embedding/fastembed-provider.ts"() {
|
|
4177
4294
|
"use strict";
|
|
@@ -4181,6 +4298,9 @@ var init_fastembed_provider = __esm({
|
|
|
4181
4298
|
CACHE_FILE = join2(CACHE_DIR, ".embedding-cache.json");
|
|
4182
4299
|
cache = /* @__PURE__ */ new Map();
|
|
4183
4300
|
MAX_CACHE_SIZE = 5e3;
|
|
4301
|
+
DEFAULT_CACHE_PAYLOAD_BYTES = 64 * 1024 * 1024;
|
|
4302
|
+
MAX_CACHE_FILE_BYTES = 128 * 1024 * 1024;
|
|
4303
|
+
cachePayloadBytes = 0;
|
|
4184
4304
|
diskCacheDirty = false;
|
|
4185
4305
|
FastEmbedProvider = class _FastEmbedProvider {
|
|
4186
4306
|
name = "fastembed-bge-small";
|
|
@@ -4222,7 +4342,7 @@ var init_fastembed_provider = __esm({
|
|
|
4222
4342
|
if (result.length !== this.dimensions) {
|
|
4223
4343
|
throw new Error(`Expected ${this.dimensions}d embedding, got ${result.length}d`);
|
|
4224
4344
|
}
|
|
4225
|
-
|
|
4345
|
+
cacheSet(hash4, result);
|
|
4226
4346
|
return result;
|
|
4227
4347
|
}
|
|
4228
4348
|
async embedBatch(texts) {
|
|
@@ -4247,7 +4367,7 @@ var init_fastembed_provider = __esm({
|
|
|
4247
4367
|
const originalIdx = uncachedIndices[batchIdx];
|
|
4248
4368
|
const plain = Array.from(vec);
|
|
4249
4369
|
results[originalIdx] = plain;
|
|
4250
|
-
|
|
4370
|
+
cacheSet(textHash(uncachedTexts[batchIdx]), plain);
|
|
4251
4371
|
batchIdx++;
|
|
4252
4372
|
}
|
|
4253
4373
|
}
|
|
@@ -4255,14 +4375,6 @@ var init_fastembed_provider = __esm({
|
|
|
4255
4375
|
}
|
|
4256
4376
|
return results;
|
|
4257
4377
|
}
|
|
4258
|
-
cacheSet(hash4, value) {
|
|
4259
|
-
if (cache.size >= MAX_CACHE_SIZE) {
|
|
4260
|
-
const firstKey = cache.keys().next().value;
|
|
4261
|
-
if (firstKey !== void 0) cache.delete(firstKey);
|
|
4262
|
-
}
|
|
4263
|
-
cache.set(hash4, value);
|
|
4264
|
-
diskCacheDirty = true;
|
|
4265
|
-
}
|
|
4266
4378
|
};
|
|
4267
4379
|
}
|
|
4268
4380
|
});
|
|
@@ -4272,7 +4384,15 @@ var transformers_provider_exports = {};
|
|
|
4272
4384
|
__export(transformers_provider_exports, {
|
|
4273
4385
|
TransformersProvider: () => TransformersProvider
|
|
4274
4386
|
});
|
|
4275
|
-
|
|
4387
|
+
import { createHash as createHash2 } from "crypto";
|
|
4388
|
+
function cacheKey2(text3) {
|
|
4389
|
+
return createHash2("sha256").update(text3).digest("hex");
|
|
4390
|
+
}
|
|
4391
|
+
function maxCachePayloadBytes2() {
|
|
4392
|
+
const raw = Number.parseInt(process.env.MEMORIX_EMBEDDING_CACHE_MAX_BYTES ?? "", 10);
|
|
4393
|
+
return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_CACHE_PAYLOAD_BYTES2;
|
|
4394
|
+
}
|
|
4395
|
+
var cache2, MAX_CACHE_SIZE2, DEFAULT_CACHE_PAYLOAD_BYTES2, cachePayloadBytes2, TransformersProvider;
|
|
4276
4396
|
var init_transformers_provider = __esm({
|
|
4277
4397
|
"src/embedding/transformers-provider.ts"() {
|
|
4278
4398
|
"use strict";
|
|
@@ -4280,6 +4400,8 @@ var init_transformers_provider = __esm({
|
|
|
4280
4400
|
init_provider();
|
|
4281
4401
|
cache2 = /* @__PURE__ */ new Map();
|
|
4282
4402
|
MAX_CACHE_SIZE2 = 5e3;
|
|
4403
|
+
DEFAULT_CACHE_PAYLOAD_BYTES2 = 64 * 1024 * 1024;
|
|
4404
|
+
cachePayloadBytes2 = 0;
|
|
4283
4405
|
TransformersProvider = class _TransformersProvider {
|
|
4284
4406
|
name = "transformers-minilm";
|
|
4285
4407
|
dimensions = 384;
|
|
@@ -4314,7 +4436,7 @@ var init_transformers_provider = __esm({
|
|
|
4314
4436
|
return Promise.all(inputs.map((input) => this.embedInput(input, options)));
|
|
4315
4437
|
}
|
|
4316
4438
|
async embed(text3) {
|
|
4317
|
-
const cached = cache2.get(text3);
|
|
4439
|
+
const cached = cache2.get(cacheKey2(text3));
|
|
4318
4440
|
if (cached) return cached;
|
|
4319
4441
|
const output = await this.extractor(text3, {
|
|
4320
4442
|
pooling: "mean",
|
|
@@ -4324,7 +4446,7 @@ var init_transformers_provider = __esm({
|
|
|
4324
4446
|
if (result.length !== this.dimensions) {
|
|
4325
4447
|
throw new Error(`Expected ${this.dimensions}d embedding, got ${result.length}d`);
|
|
4326
4448
|
}
|
|
4327
|
-
this.cacheSet(text3, result);
|
|
4449
|
+
this.cacheSet(cacheKey2(text3), result);
|
|
4328
4450
|
return result;
|
|
4329
4451
|
}
|
|
4330
4452
|
async embedBatch(texts) {
|
|
@@ -4332,7 +4454,7 @@ var init_transformers_provider = __esm({
|
|
|
4332
4454
|
const uncachedIndices = [];
|
|
4333
4455
|
const uncachedTexts = [];
|
|
4334
4456
|
for (let i2 = 0; i2 < texts.length; i2++) {
|
|
4335
|
-
const cached = cache2.get(texts[i2]);
|
|
4457
|
+
const cached = cache2.get(cacheKey2(texts[i2]));
|
|
4336
4458
|
if (cached) {
|
|
4337
4459
|
results[i2] = cached;
|
|
4338
4460
|
} else {
|
|
@@ -4350,17 +4472,27 @@ var init_transformers_provider = __esm({
|
|
|
4350
4472
|
const vec = Array.from(allVecs[i2]);
|
|
4351
4473
|
const originalIdx = uncachedIndices[i2];
|
|
4352
4474
|
results[originalIdx] = vec;
|
|
4353
|
-
this.cacheSet(uncachedTexts[i2], vec);
|
|
4475
|
+
this.cacheSet(cacheKey2(uncachedTexts[i2]), vec);
|
|
4354
4476
|
}
|
|
4355
4477
|
}
|
|
4356
4478
|
return results;
|
|
4357
4479
|
}
|
|
4358
4480
|
cacheSet(key, value) {
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4481
|
+
const incomingBytes = value.length * 8;
|
|
4482
|
+
if (incomingBytes > maxCachePayloadBytes2()) return;
|
|
4483
|
+
const existing = cache2.get(key);
|
|
4484
|
+
if (existing) cachePayloadBytes2 -= existing.length * 8;
|
|
4485
|
+
else {
|
|
4486
|
+
while (cache2.size >= MAX_CACHE_SIZE2 || cachePayloadBytes2 + incomingBytes > maxCachePayloadBytes2()) {
|
|
4487
|
+
const firstKey = cache2.keys().next().value;
|
|
4488
|
+
if (firstKey === void 0) break;
|
|
4489
|
+
const old = cache2.get(firstKey);
|
|
4490
|
+
cache2.delete(firstKey);
|
|
4491
|
+
if (old) cachePayloadBytes2 -= old.length * 8;
|
|
4492
|
+
}
|
|
4362
4493
|
}
|
|
4363
4494
|
cache2.set(key, value);
|
|
4495
|
+
cachePayloadBytes2 += incomingBytes;
|
|
4364
4496
|
}
|
|
4365
4497
|
};
|
|
4366
4498
|
}
|
|
@@ -4382,7 +4514,7 @@ __export(api_provider_exports, {
|
|
|
4382
4514
|
saveDiskCacheNow: () => saveDiskCacheNow,
|
|
4383
4515
|
seedApiEmbeddingCacheForTests: () => seedApiEmbeddingCacheForTests
|
|
4384
4516
|
});
|
|
4385
|
-
import { createHash as
|
|
4517
|
+
import { createHash as createHash3 } from "crypto";
|
|
4386
4518
|
import { createReadStream, createWriteStream, constants as fsConstants } from "fs";
|
|
4387
4519
|
import { access, readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, rename, stat, unlink } from "fs/promises";
|
|
4388
4520
|
import { join as join3 } from "path";
|
|
@@ -4409,7 +4541,7 @@ function cacheStatFile() {
|
|
|
4409
4541
|
function payloadBytes(vector) {
|
|
4410
4542
|
return vector.length * BYTES_PER_DIM;
|
|
4411
4543
|
}
|
|
4412
|
-
function
|
|
4544
|
+
function maxCachePayloadBytes3() {
|
|
4413
4545
|
const raw = process.env.MEMORIX_EMBEDDING_CACHE_MAX_BYTES;
|
|
4414
4546
|
if (raw) {
|
|
4415
4547
|
const parsed = Number.parseInt(raw, 10);
|
|
@@ -4419,7 +4551,7 @@ function maxCachePayloadBytes() {
|
|
|
4419
4551
|
}
|
|
4420
4552
|
function maxEntriesForDimensions(dimensions) {
|
|
4421
4553
|
const dim = Math.max(1, Math.floor(dimensions));
|
|
4422
|
-
const byBytes = Math.floor(
|
|
4554
|
+
const byBytes = Math.floor(maxCachePayloadBytes3() / (dim * BYTES_PER_DIM));
|
|
4423
4555
|
return Math.max(1, Math.min(MAX_CACHE_ENTRIES, byBytes));
|
|
4424
4556
|
}
|
|
4425
4557
|
function rememberDimensions(vector) {
|
|
@@ -4432,13 +4564,15 @@ function evictOldest() {
|
|
|
4432
4564
|
if (firstKey === void 0) return;
|
|
4433
4565
|
const old = cache3.get(firstKey);
|
|
4434
4566
|
cache3.delete(firstKey);
|
|
4435
|
-
if (old)
|
|
4567
|
+
if (old) cachePayloadBytes3 -= payloadBytes(old);
|
|
4436
4568
|
}
|
|
4437
4569
|
function evictToFit(incomingBytes, incomingDims) {
|
|
4570
|
+
if (incomingBytes > maxCachePayloadBytes3()) return false;
|
|
4438
4571
|
const limit2 = maxEntriesForDimensions(incomingDims);
|
|
4439
|
-
while (cache3.size > 0 && (cache3.size >= limit2 ||
|
|
4572
|
+
while (cache3.size > 0 && (cache3.size >= limit2 || cachePayloadBytes3 + incomingBytes > maxCachePayloadBytes3())) {
|
|
4440
4573
|
evictOldest();
|
|
4441
4574
|
}
|
|
4575
|
+
return true;
|
|
4442
4576
|
}
|
|
4443
4577
|
function isNumberArray(value) {
|
|
4444
4578
|
return Array.isArray(value) && value.every((entry) => typeof entry === "number");
|
|
@@ -4465,12 +4599,12 @@ function cacheInsert(hash4, value, dirty) {
|
|
|
4465
4599
|
const incoming = payloadBytes(value);
|
|
4466
4600
|
const existing = cache3.get(hash4);
|
|
4467
4601
|
if (existing) {
|
|
4468
|
-
|
|
4602
|
+
cachePayloadBytes3 -= payloadBytes(existing);
|
|
4469
4603
|
cache3.delete(hash4);
|
|
4470
4604
|
}
|
|
4471
|
-
evictToFit(incoming, value.length || cacheDimensions || DEFAULT_ASSUMED_DIMENSIONS);
|
|
4605
|
+
if (!evictToFit(incoming, value.length || cacheDimensions || DEFAULT_ASSUMED_DIMENSIONS)) return;
|
|
4472
4606
|
cache3.set(hash4, value);
|
|
4473
|
-
|
|
4607
|
+
cachePayloadBytes3 += incoming;
|
|
4474
4608
|
if (dirty) diskCacheDirty2 = true;
|
|
4475
4609
|
}
|
|
4476
4610
|
async function readCacheStat() {
|
|
@@ -4506,7 +4640,7 @@ function cacheNamespace(config) {
|
|
|
4506
4640
|
].join("|");
|
|
4507
4641
|
}
|
|
4508
4642
|
function textHash2(text3, namespace) {
|
|
4509
|
-
return
|
|
4643
|
+
return createHash3("sha256").update(`${namespace}\0${text3}`).digest("hex").slice(0, 16);
|
|
4510
4644
|
}
|
|
4511
4645
|
function inputIdentity(input, options = {}) {
|
|
4512
4646
|
return JSON.stringify({
|
|
@@ -4848,7 +4982,7 @@ function getApiEmbeddingDiskCacheLoadCountForTests() {
|
|
|
4848
4982
|
}
|
|
4849
4983
|
function resetApiEmbeddingCacheForTests() {
|
|
4850
4984
|
cache3.clear();
|
|
4851
|
-
|
|
4985
|
+
cachePayloadBytes3 = 0;
|
|
4852
4986
|
cacheDimensions = null;
|
|
4853
4987
|
diskCacheEntryCount = 0;
|
|
4854
4988
|
diskCacheLoaded = false;
|
|
@@ -4859,14 +4993,14 @@ function resetApiEmbeddingCacheForTests() {
|
|
|
4859
4993
|
}
|
|
4860
4994
|
function seedApiEmbeddingCacheForTests(entries) {
|
|
4861
4995
|
cache3.clear();
|
|
4862
|
-
|
|
4996
|
+
cachePayloadBytes3 = 0;
|
|
4863
4997
|
cacheDimensions = null;
|
|
4864
4998
|
for (const [key, value] of entries) cacheInsert(key, value, true);
|
|
4865
4999
|
diskCacheLoaded = true;
|
|
4866
5000
|
diskCacheDirty2 = true;
|
|
4867
5001
|
}
|
|
4868
5002
|
function getApiEmbeddingCachePayloadBytesForTests() {
|
|
4869
|
-
return
|
|
5003
|
+
return cachePayloadBytes3;
|
|
4870
5004
|
}
|
|
4871
5005
|
function getApiEmbeddingJsonlLineCountCallsForTests() {
|
|
4872
5006
|
return jsonlLineCountCalls;
|
|
@@ -5040,7 +5174,7 @@ function scheduleDiskSave() {
|
|
|
5040
5174
|
diskSaveTimer = null;
|
|
5041
5175
|
}, DISK_SAVE_DEBOUNCE_MS);
|
|
5042
5176
|
}
|
|
5043
|
-
function
|
|
5177
|
+
function cacheSet2(hash4, value) {
|
|
5044
5178
|
cacheInsert(hash4, value, true);
|
|
5045
5179
|
}
|
|
5046
5180
|
function resolveEnvEmbeddingApiKey() {
|
|
@@ -5160,7 +5294,7 @@ async function waitForRetry(waitMs, signal) {
|
|
|
5160
5294
|
abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
5161
5295
|
});
|
|
5162
5296
|
}
|
|
5163
|
-
var cache3, MAX_CACHE_ENTRIES, MAX_CACHE_PAYLOAD_BYTES, BYTES_PER_DIM, DEFAULT_ASSUMED_DIMENSIONS, MAX_MIGRATION_VALUE_BYTES,
|
|
5297
|
+
var cache3, MAX_CACHE_ENTRIES, MAX_CACHE_PAYLOAD_BYTES, BYTES_PER_DIM, DEFAULT_ASSUMED_DIMENSIONS, MAX_MIGRATION_VALUE_BYTES, cachePayloadBytes3, cacheDimensions, diskCacheEntryCount, diskCacheDirty2, diskSaveTimer, diskCacheLoaded, diskCacheLoadPromise, diskCacheLoadCount, jsonlLineCountCalls, MAX_INPUT_CHARS, MAX_CONCURRENCY, DISK_SAVE_DEBOUNCE_MS, DEFAULT_MAX_BATCH_SIZE, DASHSCOPE_MAX_BATCH_SIZE, MAX_RETRIES2, BASE_DELAY_MS, EmbeddingAPIError, APIEmbeddingProvider;
|
|
5164
5298
|
var init_api_provider = __esm({
|
|
5165
5299
|
"src/embedding/api-provider.ts"() {
|
|
5166
5300
|
"use strict";
|
|
@@ -5172,7 +5306,7 @@ var init_api_provider = __esm({
|
|
|
5172
5306
|
BYTES_PER_DIM = 8;
|
|
5173
5307
|
DEFAULT_ASSUMED_DIMENSIONS = 4096;
|
|
5174
5308
|
MAX_MIGRATION_VALUE_BYTES = 16 * 1024 * 1024;
|
|
5175
|
-
|
|
5309
|
+
cachePayloadBytes3 = 0;
|
|
5176
5310
|
cacheDimensions = null;
|
|
5177
5311
|
diskCacheEntryCount = 0;
|
|
5178
5312
|
diskCacheDirty2 = false;
|
|
@@ -5357,7 +5491,7 @@ var init_api_provider = __esm({
|
|
|
5357
5491
|
} else {
|
|
5358
5492
|
embedding = await apiCall();
|
|
5359
5493
|
}
|
|
5360
|
-
|
|
5494
|
+
cacheSet2(hash4, embedding);
|
|
5361
5495
|
scheduleDiskSave();
|
|
5362
5496
|
return embedding;
|
|
5363
5497
|
}
|
|
@@ -5405,7 +5539,7 @@ var init_api_provider = __esm({
|
|
|
5405
5539
|
for (const item of response.data) {
|
|
5406
5540
|
const originalIdx = chunkIndices[item.index];
|
|
5407
5541
|
results[originalIdx] = item.embedding;
|
|
5408
|
-
|
|
5542
|
+
cacheSet2(textHash2(normalizedTexts[originalIdx], this.cacheKeyNamespace), item.embedding);
|
|
5409
5543
|
}
|
|
5410
5544
|
} catch (error) {
|
|
5411
5545
|
const providerLimit = parseBatchLimit(error);
|
|
@@ -5483,7 +5617,7 @@ var init_api_provider = __esm({
|
|
|
5483
5617
|
throw new Error(`Expected ${this.dimensions}d, got ${embedding.length}d; dimension mismatch`);
|
|
5484
5618
|
}
|
|
5485
5619
|
this.trackUsage(response);
|
|
5486
|
-
|
|
5620
|
+
cacheSet2(hash4, embedding);
|
|
5487
5621
|
scheduleDiskSave();
|
|
5488
5622
|
return embedding;
|
|
5489
5623
|
}
|
|
@@ -6866,6 +7000,7 @@ var init_provider2 = __esm({
|
|
|
6866
7000
|
openai: { baseUrl: "https://api.openai.com/v1", model: "gpt-4.1-nano" },
|
|
6867
7001
|
anthropic: { baseUrl: "https://api.anthropic.com/v1", model: "claude-3-5-haiku-latest" },
|
|
6868
7002
|
openrouter: { baseUrl: "https://openrouter.ai/api/v1", model: "openai/gpt-4.1-nano" },
|
|
7003
|
+
atlascloud: { baseUrl: "https://api.atlascloud.ai/v1", model: "deepseek-ai/deepseek-v3.2" },
|
|
6869
7004
|
custom: { baseUrl: "http://localhost:11434/v1", model: "llama3" }
|
|
6870
7005
|
};
|
|
6871
7006
|
currentConfig = null;
|
|
@@ -7629,7 +7764,7 @@ var init_obs_store = __esm({
|
|
|
7629
7764
|
});
|
|
7630
7765
|
|
|
7631
7766
|
// src/search/semantic-index.ts
|
|
7632
|
-
import { createHash as
|
|
7767
|
+
import { createHash as createHash4 } from "crypto";
|
|
7633
7768
|
import { createRequire as createRequire3 } from "module";
|
|
7634
7769
|
import path11 from "path";
|
|
7635
7770
|
function createSemanticIndexProfile(provider2) {
|
|
@@ -7643,7 +7778,7 @@ function stateKey(dataDir, profile) {
|
|
|
7643
7778
|
return `${path11.resolve(dataDir)}::${profile.key}`;
|
|
7644
7779
|
}
|
|
7645
7780
|
function tableName(profile) {
|
|
7646
|
-
const digest2 =
|
|
7781
|
+
const digest2 = createHash4("sha256").update(profile.key).digest("hex").slice(0, 20);
|
|
7647
7782
|
return `${TABLE_PREFIX}${digest2}`;
|
|
7648
7783
|
}
|
|
7649
7784
|
function indexRoot(dataDir) {
|
|
@@ -9686,6 +9821,7 @@ var init_secret_filter = __esm({
|
|
|
9686
9821
|
// src/runtime/maintenance-jobs.ts
|
|
9687
9822
|
var maintenance_jobs_exports = {};
|
|
9688
9823
|
__export(maintenance_jobs_exports, {
|
|
9824
|
+
DEFAULT_FAILED_HISTORY_RETENTION_MS: () => DEFAULT_FAILED_HISTORY_RETENTION_MS,
|
|
9689
9825
|
MAINTENANCE_JOB_KINDS: () => MAINTENANCE_JOB_KINDS,
|
|
9690
9826
|
MaintenanceJobStore: () => MaintenanceJobStore,
|
|
9691
9827
|
MaintenanceJobWorker: () => MaintenanceJobWorker,
|
|
@@ -9735,7 +9871,7 @@ function normalizedKinds(kinds) {
|
|
|
9735
9871
|
function getMaintenanceRetryDelayMs(attempts) {
|
|
9736
9872
|
return Math.min(6e4, 1e3 * 2 ** Math.max(0, attempts - 1));
|
|
9737
9873
|
}
|
|
9738
|
-
var MAINTENANCE_JOB_KINDS, DEFAULT_MAX_ATTEMPTS, DEFAULT_LEASE_MS, DEFAULT_POLL_INTERVAL_MS, MAX_ERROR_LENGTH, DEFAULT_COMPLETED_HISTORY_RETENTION_MS, MaintenanceJobStore, MaintenanceJobWorker;
|
|
9874
|
+
var MAINTENANCE_JOB_KINDS, DEFAULT_MAX_ATTEMPTS, DEFAULT_LEASE_MS, DEFAULT_POLL_INTERVAL_MS, MAX_ERROR_LENGTH, DEFAULT_COMPLETED_HISTORY_RETENTION_MS, DEFAULT_FAILED_HISTORY_RETENTION_MS, MaintenanceJobStore, MaintenanceJobWorker;
|
|
9739
9875
|
var init_maintenance_jobs = __esm({
|
|
9740
9876
|
"src/runtime/maintenance-jobs.ts"() {
|
|
9741
9877
|
"use strict";
|
|
@@ -9762,6 +9898,7 @@ var init_maintenance_jobs = __esm({
|
|
|
9762
9898
|
DEFAULT_POLL_INTERVAL_MS = 2e3;
|
|
9763
9899
|
MAX_ERROR_LENGTH = 1e3;
|
|
9764
9900
|
DEFAULT_COMPLETED_HISTORY_RETENTION_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
9901
|
+
DEFAULT_FAILED_HISTORY_RETENTION_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
9765
9902
|
MaintenanceJobStore = class {
|
|
9766
9903
|
db;
|
|
9767
9904
|
constructor(dataDir) {
|
|
@@ -9888,18 +10025,21 @@ var init_maintenance_jobs = __esm({
|
|
|
9888
10025
|
}
|
|
9889
10026
|
/**
|
|
9890
10027
|
* Completed jobs are useful recent operator history, not permanent data.
|
|
9891
|
-
* Failed
|
|
9892
|
-
*
|
|
10028
|
+
* Failed diagnostics are retained longer, but are still bounded so a
|
|
10029
|
+
* permanently failing job kind cannot grow the database forever.
|
|
9893
10030
|
*/
|
|
9894
10031
|
pruneCompletedHistory(options = {}) {
|
|
9895
10032
|
const now3 = options.now ?? Date.now();
|
|
9896
10033
|
const maxAgeMs = Number.isFinite(options.maxAgeMs) ? Math.max(0, Math.floor(options.maxAgeMs)) : DEFAULT_COMPLETED_HISTORY_RETENTION_MS;
|
|
10034
|
+
const failedMaxAgeMs = Number.isFinite(options.failedMaxAgeMs) ? Math.max(0, Math.floor(options.failedMaxAgeMs)) : DEFAULT_FAILED_HISTORY_RETENTION_MS;
|
|
9897
10035
|
const result = this.db.prepare(`
|
|
9898
10036
|
DELETE FROM maintenance_jobs
|
|
9899
|
-
WHERE status = 'completed'
|
|
10037
|
+
WHERE (status = 'completed'
|
|
9900
10038
|
AND completed_at IS NOT NULL
|
|
9901
|
-
AND completed_at < ?
|
|
9902
|
-
|
|
10039
|
+
AND completed_at < ?)
|
|
10040
|
+
OR (status = 'failed'
|
|
10041
|
+
AND updated_at < ?)
|
|
10042
|
+
`).run(now3 - maxAgeMs, now3 - failedMaxAgeMs);
|
|
9903
10043
|
return Number(result.changes ?? 0);
|
|
9904
10044
|
}
|
|
9905
10045
|
claimNext(options) {
|
|
@@ -10253,7 +10393,7 @@ var init_lifecycle = __esm({
|
|
|
10253
10393
|
});
|
|
10254
10394
|
|
|
10255
10395
|
// src/store/evidence-store.ts
|
|
10256
|
-
import { createHash as
|
|
10396
|
+
import { createHash as createHash5, randomUUID as randomUUID3 } from "crypto";
|
|
10257
10397
|
function safeJson(value, fallback) {
|
|
10258
10398
|
if (typeof value !== "string" || value.length === 0) return fallback;
|
|
10259
10399
|
try {
|
|
@@ -10287,7 +10427,7 @@ function rowToCard(row) {
|
|
|
10287
10427
|
};
|
|
10288
10428
|
}
|
|
10289
10429
|
function observationHash(observation) {
|
|
10290
|
-
return
|
|
10430
|
+
return createHash5("sha256").update(JSON.stringify({
|
|
10291
10431
|
projectId: observation.projectId,
|
|
10292
10432
|
id: observation.id,
|
|
10293
10433
|
title: observation.title,
|
|
@@ -10881,13 +11021,13 @@ __export(workspace_exports, {
|
|
|
10881
11021
|
loadKnowledgeWorkspace: () => loadKnowledgeWorkspace,
|
|
10882
11022
|
resolveKnowledgeWorkspaceFile: () => resolveKnowledgeWorkspaceFile
|
|
10883
11023
|
});
|
|
10884
|
-
import { createHash as
|
|
11024
|
+
import { createHash as createHash6 } from "crypto";
|
|
10885
11025
|
import { execFile } from "child_process";
|
|
10886
11026
|
import { promises as fs9 } from "fs";
|
|
10887
11027
|
import path14 from "path";
|
|
10888
11028
|
import { promisify } from "util";
|
|
10889
11029
|
function hash(value) {
|
|
10890
|
-
return
|
|
11030
|
+
return createHash6("sha256").update(value).digest("hex");
|
|
10891
11031
|
}
|
|
10892
11032
|
function workspaceId(projectId, mode) {
|
|
10893
11033
|
return "workspace:" + hash(projectId + ":" + mode).slice(0, 24);
|
|
@@ -12040,14 +12180,14 @@ __export(asset_store_exports, {
|
|
|
12040
12180
|
readMediaAsset: () => readMediaAsset,
|
|
12041
12181
|
removeMediaAsset: () => removeMediaAsset
|
|
12042
12182
|
});
|
|
12043
|
-
import { createHash as
|
|
12183
|
+
import { createHash as createHash7, randomUUID as randomUUID6 } from "crypto";
|
|
12044
12184
|
import { copyFile, lstat, mkdir as mkdir3, open, readFile as readFile3, readdir, rename as rename2, rm, stat as stat2, writeFile as writeFile3 } from "fs/promises";
|
|
12045
12185
|
import path15 from "path";
|
|
12046
12186
|
function mediaRoot(dataDir) {
|
|
12047
12187
|
return path15.resolve(dataDir, "media");
|
|
12048
12188
|
}
|
|
12049
12189
|
function projectStorageKey(projectId) {
|
|
12050
|
-
return
|
|
12190
|
+
return createHash7("sha256").update(projectId).digest("hex").slice(0, 16);
|
|
12051
12191
|
}
|
|
12052
12192
|
function validateUnderRoot(root, candidate) {
|
|
12053
12193
|
const resolved = path15.resolve(candidate);
|
|
@@ -12107,7 +12247,7 @@ async function readHeader(filePath, bytes = 32) {
|
|
|
12107
12247
|
}
|
|
12108
12248
|
async function sha256File(filePath) {
|
|
12109
12249
|
const bytes = await readFile3(filePath);
|
|
12110
|
-
return
|
|
12250
|
+
return createHash7("sha256").update(bytes).digest("hex");
|
|
12111
12251
|
}
|
|
12112
12252
|
function destinationFor(root, projectId, sha256, extension3) {
|
|
12113
12253
|
const relative5 = path15.join("assets", projectStorageKey(projectId), sha256.slice(0, 2), `${sha256}${extension3}`);
|
|
@@ -12213,7 +12353,7 @@ async function importMediaBuffer(input) {
|
|
|
12213
12353
|
if (input.bytes.length === 0) throw new Error("Media import rejects empty payloads");
|
|
12214
12354
|
if (input.bytes.length > maxBytes) throw new Error(`Media payload is too large (${input.bytes.length} bytes; limit ${maxBytes})`);
|
|
12215
12355
|
const detected = detectMedia(input.bytes.subarray(0, 32));
|
|
12216
|
-
const sha256 =
|
|
12356
|
+
const sha256 = createHash7("sha256").update(input.bytes).digest("hex");
|
|
12217
12357
|
return importKnownMedia({
|
|
12218
12358
|
dataDir: input.dataDir,
|
|
12219
12359
|
projectId: input.projectId,
|
|
@@ -12231,7 +12371,7 @@ async function readMediaAsset(dataDir, asset, maxBytes = DEFAULT_MAX_MEDIA_BYTES
|
|
|
12231
12371
|
if (asset.byteSize > maxBytes) throw new Error(`Media asset exceeds read limit (${asset.byteSize} bytes; limit ${maxBytes})`);
|
|
12232
12372
|
const bytes = await readFile3(getMediaAssetPath(dataDir, asset));
|
|
12233
12373
|
if (bytes.length !== asset.byteSize) throw new Error(`Media asset size no longer matches metadata: ${asset.id}`);
|
|
12234
|
-
const sha256 =
|
|
12374
|
+
const sha256 = createHash7("sha256").update(bytes).digest("hex");
|
|
12235
12375
|
if (sha256 !== asset.sha256) throw new Error(`Media asset hash no longer matches metadata: ${asset.id}`);
|
|
12236
12376
|
return bytes;
|
|
12237
12377
|
}
|
|
@@ -65101,7 +65241,7 @@ var require_gaxios = __commonJS({
|
|
|
65101
65241
|
var retry_js_1 = require_retry3();
|
|
65102
65242
|
var stream_1 = __require("stream");
|
|
65103
65243
|
var interceptor_js_1 = require_interceptor();
|
|
65104
|
-
var
|
|
65244
|
+
var randomUUID20 = async () => globalThis.crypto?.randomUUID() || (await import("crypto")).randomUUID();
|
|
65105
65245
|
var HTTP_STATUS_NO_CONTENT = 204;
|
|
65106
65246
|
var Gaxios = class {
|
|
65107
65247
|
agentCache = /* @__PURE__ */ new Map();
|
|
@@ -65374,7 +65514,7 @@ var require_gaxios = __commonJS({
|
|
|
65374
65514
|
*/
|
|
65375
65515
|
["Blob", "File", "FormData"].includes(opts.data?.constructor?.name || "");
|
|
65376
65516
|
if (opts.multipart?.length) {
|
|
65377
|
-
const boundary = await
|
|
65517
|
+
const boundary = await randomUUID20();
|
|
65378
65518
|
preparedHeaders.set("content-type", `multipart/related; boundary=${boundary}`);
|
|
65379
65519
|
opts.body = stream_1.Readable.from(this.getMultipartRequest(opts.multipart, boundary));
|
|
65380
65520
|
} else if (shouldDirectlyPassData) {
|
|
@@ -71046,16 +71186,16 @@ var require_jwtaccess = __commonJS({
|
|
|
71046
71186
|
* @returns A string that returns the cached key.
|
|
71047
71187
|
*/
|
|
71048
71188
|
getCachedKey(url, scopes) {
|
|
71049
|
-
let
|
|
71189
|
+
let cacheKey3 = url;
|
|
71050
71190
|
if (scopes && Array.isArray(scopes) && scopes.length) {
|
|
71051
|
-
|
|
71191
|
+
cacheKey3 = url ? `${url}_${scopes.join("_")}` : `${scopes.join("_")}`;
|
|
71052
71192
|
} else if (typeof scopes === "string") {
|
|
71053
|
-
|
|
71193
|
+
cacheKey3 = url ? `${url}_${scopes}` : scopes;
|
|
71054
71194
|
}
|
|
71055
|
-
if (!
|
|
71195
|
+
if (!cacheKey3) {
|
|
71056
71196
|
throw Error("Scopes or url must be provided");
|
|
71057
71197
|
}
|
|
71058
|
-
return
|
|
71198
|
+
return cacheKey3;
|
|
71059
71199
|
}
|
|
71060
71200
|
/**
|
|
71061
71201
|
* Get a non-expired access token, after refreshing if necessary.
|
|
@@ -77601,7 +77741,7 @@ var require_websocket = __commonJS({
|
|
|
77601
77741
|
var http3 = __require("http");
|
|
77602
77742
|
var net = __require("net");
|
|
77603
77743
|
var tls = __require("tls");
|
|
77604
|
-
var { randomBytes: randomBytes2, createHash:
|
|
77744
|
+
var { randomBytes: randomBytes2, createHash: createHash20 } = __require("crypto");
|
|
77605
77745
|
var { Duplex, Readable: Readable2 } = __require("stream");
|
|
77606
77746
|
var { URL: URL2 } = __require("url");
|
|
77607
77747
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -78269,7 +78409,7 @@ var require_websocket = __commonJS({
|
|
|
78269
78409
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
78270
78410
|
return;
|
|
78271
78411
|
}
|
|
78272
|
-
const digest2 =
|
|
78412
|
+
const digest2 = createHash20("sha1").update(key + GUID).digest("base64");
|
|
78273
78413
|
if (res.headers["sec-websocket-accept"] !== digest2) {
|
|
78274
78414
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
78275
78415
|
return;
|
|
@@ -78641,7 +78781,7 @@ var require_websocket_server = __commonJS({
|
|
|
78641
78781
|
var EventEmitter2 = __require("events");
|
|
78642
78782
|
var http3 = __require("http");
|
|
78643
78783
|
var { Duplex } = __require("stream");
|
|
78644
|
-
var { createHash:
|
|
78784
|
+
var { createHash: createHash20 } = __require("crypto");
|
|
78645
78785
|
var extension3 = require_extension();
|
|
78646
78786
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
78647
78787
|
var subprotocol2 = require_subprotocol();
|
|
@@ -78948,7 +79088,7 @@ var require_websocket_server = __commonJS({
|
|
|
78948
79088
|
);
|
|
78949
79089
|
}
|
|
78950
79090
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
78951
|
-
const digest2 =
|
|
79091
|
+
const digest2 = createHash20("sha1").update(key + GUID).digest("base64");
|
|
78952
79092
|
const headers = [
|
|
78953
79093
|
"HTTP/1.1 101 Switching Protocols",
|
|
78954
79094
|
"Upgrade: websocket",
|
|
@@ -143007,9 +143147,9 @@ var init_union_priority_sort = __esm({
|
|
|
143007
143147
|
// node_modules/typebox/build/value/clean/from_union.mjs
|
|
143008
143148
|
function FromUnion9(context, type, value) {
|
|
143009
143149
|
for (const schema of UnionPrioritySort(type.anyOf)) {
|
|
143010
|
-
const
|
|
143011
|
-
if (Check2(context, schema,
|
|
143012
|
-
return
|
|
143150
|
+
const clean2 = FromType19(context, schema, Clone2(value));
|
|
143151
|
+
if (Check2(context, schema, clean2))
|
|
143152
|
+
return clean2;
|
|
143013
143153
|
}
|
|
143014
143154
|
return value;
|
|
143015
143155
|
}
|
|
@@ -147647,9 +147787,9 @@ var init_long_term = __esm({
|
|
|
147647
147787
|
});
|
|
147648
147788
|
|
|
147649
147789
|
// src/codegraph/ids.ts
|
|
147650
|
-
import { createHash as
|
|
147790
|
+
import { createHash as createHash8 } from "crypto";
|
|
147651
147791
|
function digest(input) {
|
|
147652
|
-
return
|
|
147792
|
+
return createHash8("sha256").update(input).digest("hex").slice(0, 16);
|
|
147653
147793
|
}
|
|
147654
147794
|
function normalizeCodePath(path38) {
|
|
147655
147795
|
return path38.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+/g, "/");
|
|
@@ -148697,7 +148837,7 @@ var init_store = __esm({
|
|
|
148697
148837
|
|
|
148698
148838
|
// src/codegraph/code-state.ts
|
|
148699
148839
|
import { execFile as execFile2 } from "child_process";
|
|
148700
|
-
import { createHash as
|
|
148840
|
+
import { createHash as createHash9 } from "crypto";
|
|
148701
148841
|
import { promisify as promisify3 } from "util";
|
|
148702
148842
|
async function runGit(rootPath, args) {
|
|
148703
148843
|
try {
|
|
@@ -148726,7 +148866,7 @@ function changedPathCount(status) {
|
|
|
148726
148866
|
return count2;
|
|
148727
148867
|
}
|
|
148728
148868
|
function fingerprint(baseRevision, status) {
|
|
148729
|
-
return
|
|
148869
|
+
return createHash9("sha256").update(baseRevision ?? "").update("\0").update(status).digest("hex");
|
|
148730
148870
|
}
|
|
148731
148871
|
async function collectCodeStateSnapshot(input) {
|
|
148732
148872
|
const [revision, status] = await Promise.all([
|
|
@@ -148820,12 +148960,12 @@ var init_exclude3 = __esm({
|
|
|
148820
148960
|
});
|
|
148821
148961
|
|
|
148822
148962
|
// src/codegraph/semantic-provider.ts
|
|
148823
|
-
import { createHash as
|
|
148963
|
+
import { createHash as createHash10 } from "crypto";
|
|
148824
148964
|
import "fs";
|
|
148825
148965
|
import { resolve } from "path";
|
|
148826
148966
|
import ts from "typescript";
|
|
148827
148967
|
function hashText(value) {
|
|
148828
|
-
return
|
|
148968
|
+
return createHash10("sha256").update(value).digest("hex");
|
|
148829
148969
|
}
|
|
148830
148970
|
function canonicalPath(value) {
|
|
148831
148971
|
const normalized = resolve(value).replace(/\\/g, "/");
|
|
@@ -149170,11 +149310,11 @@ __export(lite_provider_exports, {
|
|
|
149170
149310
|
indexProjectLite: () => indexProjectLite,
|
|
149171
149311
|
refreshProjectLite: () => refreshProjectLite
|
|
149172
149312
|
});
|
|
149173
|
-
import { createHash as
|
|
149313
|
+
import { createHash as createHash11 } from "crypto";
|
|
149174
149314
|
import { existsSync as existsSync12, readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
|
|
149175
149315
|
import { join as join4, relative as relative2 } from "path";
|
|
149176
149316
|
function hashText2(text3) {
|
|
149177
|
-
return
|
|
149317
|
+
return createHash11("sha256").update(text3).digest("hex");
|
|
149178
149318
|
}
|
|
149179
149319
|
function extension2(path38) {
|
|
149180
149320
|
const index = path38.lastIndexOf(".");
|
|
@@ -149807,7 +149947,7 @@ var claim_store_exports = {};
|
|
|
149807
149947
|
__export(claim_store_exports, {
|
|
149808
149948
|
ClaimStore: () => ClaimStore
|
|
149809
149949
|
});
|
|
149810
|
-
import { createHash as
|
|
149950
|
+
import { createHash as createHash12, randomUUID as randomUUID12 } from "crypto";
|
|
149811
149951
|
function optionalText3(value) {
|
|
149812
149952
|
return typeof value === "string" && value ? value : void 0;
|
|
149813
149953
|
}
|
|
@@ -149860,7 +150000,7 @@ function rowToEvent3(row) {
|
|
|
149860
150000
|
};
|
|
149861
150001
|
}
|
|
149862
150002
|
function evidenceKey(input) {
|
|
149863
|
-
return
|
|
150003
|
+
return createHash12("sha256").update(JSON.stringify([
|
|
149864
150004
|
input.evidenceKind,
|
|
149865
150005
|
input.evidenceId,
|
|
149866
150006
|
input.relation,
|
|
@@ -150058,7 +150198,7 @@ __export(claims_exports, {
|
|
|
150058
150198
|
supersedeClaim: () => supersedeClaim,
|
|
150059
150199
|
writeClaim: () => writeClaim
|
|
150060
150200
|
});
|
|
150061
|
-
import { createHash as
|
|
150201
|
+
import { createHash as createHash13, randomUUID as randomUUID13 } from "crypto";
|
|
150062
150202
|
function compactText2(value, field) {
|
|
150063
150203
|
if (typeof value !== "string") throw new Error("Claim " + field + " must be text");
|
|
150064
150204
|
const sanitized = sanitizeCredentials(value).trim().replace(/\s+/g, " ");
|
|
@@ -150070,7 +150210,7 @@ function normalizedTerm(value) {
|
|
|
150070
150210
|
return compactText2(value, "identity").toLocaleLowerCase("en-US");
|
|
150071
150211
|
}
|
|
150072
150212
|
function hashIdentity(parts) {
|
|
150073
|
-
return
|
|
150213
|
+
return createHash13("sha256").update(parts.join(String.fromCharCode(31))).digest("hex");
|
|
150074
150214
|
}
|
|
150075
150215
|
function buildClaimIdentity(input) {
|
|
150076
150216
|
const subject = normalizedTerm(input.subject);
|
|
@@ -150311,7 +150451,7 @@ function supersedeClaim(store, input) {
|
|
|
150311
150451
|
});
|
|
150312
150452
|
}
|
|
150313
150453
|
function hashObservation(observation) {
|
|
150314
|
-
return
|
|
150454
|
+
return createHash13("sha256").update(JSON.stringify([
|
|
150315
150455
|
observation.title,
|
|
150316
150456
|
observation.narrative,
|
|
150317
150457
|
observation.facts,
|
|
@@ -150555,11 +150695,11 @@ var init_frontmatter = __esm({
|
|
|
150555
150695
|
});
|
|
150556
150696
|
|
|
150557
150697
|
// src/knowledge/markdown.ts
|
|
150558
|
-
import { createHash as
|
|
150698
|
+
import { createHash as createHash14 } from "crypto";
|
|
150559
150699
|
import { promises as fs13 } from "fs";
|
|
150560
150700
|
import path22 from "path";
|
|
150561
150701
|
function hashContent(content) {
|
|
150562
|
-
return
|
|
150702
|
+
return createHash14("sha256").update(content).digest("hex");
|
|
150563
150703
|
}
|
|
150564
150704
|
function stringField(data, key) {
|
|
150565
150705
|
const value = data[key];
|
|
@@ -150685,11 +150825,11 @@ __export(wiki_exports, {
|
|
|
150685
150825
|
lintKnowledgeWorkspace: () => lintKnowledgeWorkspace,
|
|
150686
150826
|
readKnowledgePage: () => readKnowledgePage
|
|
150687
150827
|
});
|
|
150688
|
-
import { createHash as
|
|
150828
|
+
import { createHash as createHash15 } from "crypto";
|
|
150689
150829
|
import { promises as fs14 } from "fs";
|
|
150690
150830
|
import path23 from "path";
|
|
150691
150831
|
function hash2(value) {
|
|
150692
|
-
return
|
|
150832
|
+
return createHash15("sha256").update(value).digest("hex");
|
|
150693
150833
|
}
|
|
150694
150834
|
function now() {
|
|
150695
150835
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -151908,11 +152048,11 @@ __export(workflows_exports, {
|
|
|
151908
152048
|
syncCanonicalWorkflows: () => syncCanonicalWorkflows,
|
|
151909
152049
|
writeCanonicalWorkflow: () => writeCanonicalWorkflow
|
|
151910
152050
|
});
|
|
151911
|
-
import { createHash as
|
|
152051
|
+
import { createHash as createHash16 } from "crypto";
|
|
151912
152052
|
import { promises as fs15 } from "fs";
|
|
151913
152053
|
import path24 from "path";
|
|
151914
152054
|
function hash3(value) {
|
|
151915
|
-
return
|
|
152055
|
+
return createHash16("sha256").update(value).digest("hex");
|
|
151916
152056
|
}
|
|
151917
152057
|
function now2() {
|
|
151918
152058
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -156273,9 +156413,9 @@ var init_graph_context = __esm({
|
|
|
156273
156413
|
});
|
|
156274
156414
|
|
|
156275
156415
|
// src/rules/utils.ts
|
|
156276
|
-
import { createHash as
|
|
156416
|
+
import { createHash as createHash17 } from "crypto";
|
|
156277
156417
|
function hashContent2(content) {
|
|
156278
|
-
return
|
|
156418
|
+
return createHash17("sha256").update(content.trim()).digest("hex").substring(0, 16);
|
|
156279
156419
|
}
|
|
156280
156420
|
function generateRuleId(source, filePath) {
|
|
156281
156421
|
const sanitized = filePath.replace(/[\/\\]/g, "-").replace(/^\./, "");
|
|
@@ -158718,6 +158858,7 @@ var init_tool_profile = __esm({
|
|
|
158718
158858
|
// keep the default micro profile at its nine-tool token budget.
|
|
158719
158859
|
memorix_evidence: ["lite", "team", "full"],
|
|
158720
158860
|
memorix_feedback: ["lite", "team", "full"],
|
|
158861
|
+
memorix_continuity: ["lite", "team", "full"],
|
|
158721
158862
|
// ── lite: extended solo memory surface ────────────────────────────
|
|
158722
158863
|
memorix_graph_context: ["lite", "team", "full"],
|
|
158723
158864
|
memorix_timeline: ["lite", "team", "full"],
|
|
@@ -159951,7 +160092,7 @@ var init_request_context = __esm({
|
|
|
159951
160092
|
function getMcpServerInfo() {
|
|
159952
160093
|
return {
|
|
159953
160094
|
name: "memorix",
|
|
159954
|
-
version: true ? "1.9.
|
|
160095
|
+
version: true ? "1.9.6" : "1.0.1"
|
|
159955
160096
|
};
|
|
159956
160097
|
}
|
|
159957
160098
|
function createMcpDiscoverResult(capabilities, serverInfo) {
|
|
@@ -160040,8 +160181,8 @@ function legacyBehavior(homeDir) {
|
|
|
160040
160181
|
function getBehaviorConfig(options = {}) {
|
|
160041
160182
|
const homeDir = options.homeDir ?? homedir22();
|
|
160042
160183
|
const projectRoot = options.projectRoot === void 0 ? detectProject()?.rootPath ?? null : options.projectRoot;
|
|
160043
|
-
const
|
|
160044
|
-
const cached = cache4.get(
|
|
160184
|
+
const cacheKey3 = `${homeDir}\0${projectRoot ?? ""}`;
|
|
160185
|
+
const cached = cache4.get(cacheKey3);
|
|
160045
160186
|
if (cached) return cached;
|
|
160046
160187
|
const legacy = legacyBehavior(homeDir);
|
|
160047
160188
|
let resolved = {};
|
|
@@ -160055,7 +160196,7 @@ function getBehaviorConfig(options = {}) {
|
|
|
160055
160196
|
autoCleanup: typeof resolved.autoCleanup === "boolean" ? resolved.autoCleanup : typeof legacy.autoCleanup === "boolean" ? legacy.autoCleanup : DEFAULTS.autoCleanup,
|
|
160056
160197
|
formationMode: isFormationMode(resolved.formation) ? resolved.formation : isFormationMode(legacy.formationMode) ? legacy.formationMode : DEFAULTS.formationMode
|
|
160057
160198
|
};
|
|
160058
|
-
cache4.set(
|
|
160199
|
+
cache4.set(cacheKey3, config);
|
|
160059
160200
|
return config;
|
|
160060
160201
|
}
|
|
160061
160202
|
function resetBehaviorConfigCache() {
|
|
@@ -160660,6 +160801,7 @@ function freshnessForMemory(status) {
|
|
|
160660
160801
|
return "unknown";
|
|
160661
160802
|
}
|
|
160662
160803
|
function receiptOmissionKind(raw) {
|
|
160804
|
+
if (raw.includes("continuity")) return "continuity";
|
|
160663
160805
|
if (raw.includes("continuation")) return "continuation";
|
|
160664
160806
|
if (raw.includes("task")) return "task";
|
|
160665
160807
|
if (raw.includes("fact")) return "current-fact";
|
|
@@ -160770,6 +160912,77 @@ function renderTaskWorksetPrompt(input) {
|
|
|
160770
160912
|
trust: "source-backed"
|
|
160771
160913
|
});
|
|
160772
160914
|
appendLine(lines, "Task lens: " + input.lens, maxTokens, omitted, "lens");
|
|
160915
|
+
if (input.continuity) {
|
|
160916
|
+
const continuity = input.continuity;
|
|
160917
|
+
appendLine(lines, "", maxTokens, omitted, "continuity-heading");
|
|
160918
|
+
appendLine(lines, "Task continuity", maxTokens, omitted, "continuity-heading", selected, {
|
|
160919
|
+
kind: "continuity",
|
|
160920
|
+
id: "continuity:" + continuity.taskId,
|
|
160921
|
+
reason: "explicit task continuity ledger",
|
|
160922
|
+
trust: "source-backed"
|
|
160923
|
+
});
|
|
160924
|
+
appendLine(
|
|
160925
|
+
lines,
|
|
160926
|
+
"- Status: " + continuity.status + " | " + short(continuity.task, 30),
|
|
160927
|
+
maxTokens,
|
|
160928
|
+
omitted,
|
|
160929
|
+
"continuity-task"
|
|
160930
|
+
);
|
|
160931
|
+
appendLine(
|
|
160932
|
+
lines,
|
|
160933
|
+
"- Outcome: " + continuity.outcome.state,
|
|
160934
|
+
maxTokens,
|
|
160935
|
+
omitted,
|
|
160936
|
+
"continuity-outcome",
|
|
160937
|
+
selected,
|
|
160938
|
+
{
|
|
160939
|
+
kind: "continuity",
|
|
160940
|
+
id: "continuity:" + continuity.taskId,
|
|
160941
|
+
reason: "deterministic task outcome projection",
|
|
160942
|
+
trust: "derived"
|
|
160943
|
+
}
|
|
160944
|
+
);
|
|
160945
|
+
for (const requirement of continuity.requirements.slice(0, 3)) {
|
|
160946
|
+
appendLine(lines, "- Requirement: " + short(requirement, 24), maxTokens, omitted, "continuity-requirement", selected, {
|
|
160947
|
+
kind: "continuity",
|
|
160948
|
+
id: "continuity:" + continuity.taskId,
|
|
160949
|
+
reason: "explicit task requirement",
|
|
160950
|
+
trust: "source-backed"
|
|
160951
|
+
});
|
|
160952
|
+
}
|
|
160953
|
+
for (const decision of continuity.decisions.slice(0, 2)) {
|
|
160954
|
+
appendLine(lines, "- Decision: " + short(decision, 24), maxTokens, omitted, "continuity-decision", selected, {
|
|
160955
|
+
kind: "continuity",
|
|
160956
|
+
id: "continuity:" + continuity.taskId,
|
|
160957
|
+
reason: "explicit task decision",
|
|
160958
|
+
trust: "source-backed"
|
|
160959
|
+
});
|
|
160960
|
+
}
|
|
160961
|
+
for (const verification of continuity.verification.slice(-3)) {
|
|
160962
|
+
appendLine(
|
|
160963
|
+
lines,
|
|
160964
|
+
"- Verify [" + verification.status + "]: " + short(verification.content, 22),
|
|
160965
|
+
maxTokens,
|
|
160966
|
+
omitted,
|
|
160967
|
+
"continuity-verification",
|
|
160968
|
+
selected,
|
|
160969
|
+
{
|
|
160970
|
+
kind: "continuity",
|
|
160971
|
+
id: "continuity:" + continuity.taskId,
|
|
160972
|
+
reason: "task verification state",
|
|
160973
|
+
trust: "source-backed"
|
|
160974
|
+
}
|
|
160975
|
+
);
|
|
160976
|
+
}
|
|
160977
|
+
for (const risk of continuity.risks.slice(0, 2)) {
|
|
160978
|
+
appendLine(lines, "- Risk: " + short(risk, 22), maxTokens, omitted, "continuity-risk", selected, {
|
|
160979
|
+
kind: "continuity",
|
|
160980
|
+
id: "continuity:" + continuity.taskId,
|
|
160981
|
+
reason: "open task risk",
|
|
160982
|
+
trust: "source-backed"
|
|
160983
|
+
});
|
|
160984
|
+
}
|
|
160985
|
+
}
|
|
160773
160986
|
if (input.alwaysOn) {
|
|
160774
160987
|
const hasAlwaysOn = input.alwaysOn.profile.length > 0 || Boolean(input.alwaysOn.state) || input.alwaysOn.durable.length > 0;
|
|
160775
160988
|
if (hasAlwaysOn) {
|
|
@@ -161293,6 +161506,7 @@ async function buildTaskWorkset(input) {
|
|
|
161293
161506
|
version: "1.3",
|
|
161294
161507
|
task,
|
|
161295
161508
|
lens: input.lens,
|
|
161509
|
+
...input.continuity ? { continuity: input.continuity } : {},
|
|
161296
161510
|
...input.alwaysOn && (input.alwaysOn.profile.length > 0 || input.alwaysOn.state || input.alwaysOn.durable.length > 0) ? { alwaysOn: input.alwaysOn } : {},
|
|
161297
161511
|
currentFacts: input.currentFacts?.map((fact) => fact.startsWith("Historical note:") ? short(fact, 48) : short(fact, 28)).slice(0, 4) ?? [],
|
|
161298
161512
|
...continuation ? { continuation } : {},
|
|
@@ -162677,7 +162891,7 @@ var compaction_checkpoint_store_exports = {};
|
|
|
162677
162891
|
__export(compaction_checkpoint_store_exports, {
|
|
162678
162892
|
CompactionCheckpointStore: () => CompactionCheckpointStore
|
|
162679
162893
|
});
|
|
162680
|
-
import { createHash as
|
|
162894
|
+
import { createHash as createHash18, randomUUID as randomUUID16 } from "crypto";
|
|
162681
162895
|
function optionalText7(value) {
|
|
162682
162896
|
return typeof value === "string" && value ? value : void 0;
|
|
162683
162897
|
}
|
|
@@ -162719,7 +162933,7 @@ function sourceKeyFor(input, summary) {
|
|
|
162719
162933
|
input.tokensBefore ?? "",
|
|
162720
162934
|
input.firstKeptEntryId ?? ""
|
|
162721
162935
|
].join("\0");
|
|
162722
|
-
return `derived:${
|
|
162936
|
+
return `derived:${createHash18("sha256").update(material).digest("hex").slice(0, 32)}`;
|
|
162723
162937
|
}
|
|
162724
162938
|
function rowToCheckpoint(row) {
|
|
162725
162939
|
return {
|
|
@@ -162977,6 +163191,305 @@ var init_compaction_checkpoint_store = __esm({
|
|
|
162977
163191
|
}
|
|
162978
163192
|
});
|
|
162979
163193
|
|
|
163194
|
+
// src/knowledge/task-continuity.ts
|
|
163195
|
+
var task_continuity_exports = {};
|
|
163196
|
+
__export(task_continuity_exports, {
|
|
163197
|
+
TASK_CONTINUITY_EVENT_KINDS: () => TASK_CONTINUITY_EVENT_KINDS,
|
|
163198
|
+
TaskContinuityStore: () => TaskContinuityStore,
|
|
163199
|
+
evaluateTaskContinuity: () => evaluateTaskContinuity
|
|
163200
|
+
});
|
|
163201
|
+
import { randomUUID as randomUUID17 } from "crypto";
|
|
163202
|
+
function clean(value, maxLength = MAX_TEXT_LENGTH2) {
|
|
163203
|
+
return sanitizeCredentials(value).replace(/\s+/g, " ").trim().slice(0, maxLength);
|
|
163204
|
+
}
|
|
163205
|
+
function cleanList(values, maxLength = MAX_TEXT_LENGTH2) {
|
|
163206
|
+
return [...new Set((values ?? []).map((value) => clean(value, maxLength)).filter(Boolean))].slice(0, MAX_LIST_ITEMS2);
|
|
163207
|
+
}
|
|
163208
|
+
function parseRefs(value) {
|
|
163209
|
+
if (typeof value !== "string") return [];
|
|
163210
|
+
try {
|
|
163211
|
+
const parsed = JSON.parse(value);
|
|
163212
|
+
return Array.isArray(parsed) ? cleanList(parsed.filter((item) => typeof item === "string"), 500).slice(0, MAX_EVIDENCE_REFS) : [];
|
|
163213
|
+
} catch {
|
|
163214
|
+
return [];
|
|
163215
|
+
}
|
|
163216
|
+
}
|
|
163217
|
+
function evaluateTaskContinuity(ledger) {
|
|
163218
|
+
const verification = {
|
|
163219
|
+
passed: ledger.verification.filter((item) => item.status === "passed").length,
|
|
163220
|
+
failed: ledger.verification.filter((item) => item.status === "failed").length,
|
|
163221
|
+
pending: ledger.verification.filter((item) => item.status === "pending").length,
|
|
163222
|
+
skipped: ledger.verification.filter((item) => item.status === "skipped").length
|
|
163223
|
+
};
|
|
163224
|
+
const reasons = [];
|
|
163225
|
+
if (verification.failed > 0) reasons.push("verification-failed");
|
|
163226
|
+
if (verification.pending > 0) reasons.push("verification-pending");
|
|
163227
|
+
if (ledger.risks.length > 0) reasons.push("open-risks");
|
|
163228
|
+
if (ledger.status === "blocked") reasons.push("task-blocked");
|
|
163229
|
+
if (ledger.status === "abandoned") reasons.push("task-abandoned");
|
|
163230
|
+
if (ledger.status === "blocked" || ledger.status === "abandoned" || verification.failed > 0) {
|
|
163231
|
+
return {
|
|
163232
|
+
state: "at-risk",
|
|
163233
|
+
score: verification.passed > verification.failed ? 0.55 : 0.2,
|
|
163234
|
+
verification,
|
|
163235
|
+
reasons
|
|
163236
|
+
};
|
|
163237
|
+
}
|
|
163238
|
+
if (ledger.status === "completed") {
|
|
163239
|
+
if (verification.passed > 0 && verification.pending === 0 && verification.skipped === 0) {
|
|
163240
|
+
return {
|
|
163241
|
+
state: ledger.risks.length > 0 ? "validated-with-risks" : "validated",
|
|
163242
|
+
score: ledger.risks.length > 0 ? 0.8 : 1,
|
|
163243
|
+
verification,
|
|
163244
|
+
reasons: reasons.length > 0 ? reasons : ["verification-passed"]
|
|
163245
|
+
};
|
|
163246
|
+
}
|
|
163247
|
+
return {
|
|
163248
|
+
state: "unverified",
|
|
163249
|
+
score: 0.4,
|
|
163250
|
+
verification,
|
|
163251
|
+
reasons: reasons.length > 0 ? reasons : ["no-passing-verification"]
|
|
163252
|
+
};
|
|
163253
|
+
}
|
|
163254
|
+
return {
|
|
163255
|
+
state: "in-progress",
|
|
163256
|
+
score: verification.passed > 0 && verification.pending === 0 ? 0.75 : 0.5,
|
|
163257
|
+
verification,
|
|
163258
|
+
reasons: reasons.length > 0 ? reasons : ["task-open"]
|
|
163259
|
+
};
|
|
163260
|
+
}
|
|
163261
|
+
function rowToEvent4(row) {
|
|
163262
|
+
const status = row.item_status ? String(row.item_status) : void 0;
|
|
163263
|
+
return {
|
|
163264
|
+
id: String(row.id),
|
|
163265
|
+
projectId: String(row.project_id),
|
|
163266
|
+
taskId: String(row.task_id),
|
|
163267
|
+
task: clean(String(row.task), MAX_TASK_LENGTH),
|
|
163268
|
+
kind: row.kind,
|
|
163269
|
+
content: clean(String(row.content)),
|
|
163270
|
+
...status ? { status } : {},
|
|
163271
|
+
...row.source_ref ? { sourceRef: clean(String(row.source_ref), 500) } : {},
|
|
163272
|
+
evidenceRefs: parseRefs(row.evidence_json),
|
|
163273
|
+
...row.actor ? { actor: clean(String(row.actor), 200) } : {},
|
|
163274
|
+
at: String(row.created_at),
|
|
163275
|
+
...row.event_key ? { eventKey: clean(String(row.event_key), 200) } : {},
|
|
163276
|
+
...row.item_key ? { itemKey: clean(String(row.item_key), 120) } : {},
|
|
163277
|
+
...row.supersedes_id ? { supersedesId: clean(String(row.supersedes_id), 120) } : {}
|
|
163278
|
+
};
|
|
163279
|
+
}
|
|
163280
|
+
function aggregate(events) {
|
|
163281
|
+
const first2 = events.find((event) => event.kind === "task") ?? events[0];
|
|
163282
|
+
const latestOutcome = [...events].reverse().find((event) => event.kind === "outcome");
|
|
163283
|
+
const verificationByKey = /* @__PURE__ */ new Map();
|
|
163284
|
+
for (const event of events.filter((event2) => event2.kind === "verification")) {
|
|
163285
|
+
verificationByKey.set(event.itemKey ?? `event:${event.id}`, event);
|
|
163286
|
+
}
|
|
163287
|
+
const ledger = {
|
|
163288
|
+
taskId: first2.taskId,
|
|
163289
|
+
projectId: first2.projectId,
|
|
163290
|
+
task: first2.task,
|
|
163291
|
+
status: latestOutcome?.status ?? "open",
|
|
163292
|
+
requirements: events.filter((event) => event.kind === "requirement").map((event) => event.content),
|
|
163293
|
+
decisions: events.filter((event) => event.kind === "decision").map((event) => event.content),
|
|
163294
|
+
verification: [...verificationByKey.values()].map((event) => ({
|
|
163295
|
+
id: event.itemKey ?? event.id,
|
|
163296
|
+
content: event.content,
|
|
163297
|
+
status: event.status ?? "pending",
|
|
163298
|
+
...event.sourceRef ? { sourceRef: event.sourceRef } : {},
|
|
163299
|
+
evidenceRefs: event.evidenceRefs
|
|
163300
|
+
})),
|
|
163301
|
+
risks: events.filter((event) => event.kind === "risk").map((event) => event.content),
|
|
163302
|
+
outcomes: events.filter((event) => event.kind === "outcome").map((event) => event.content),
|
|
163303
|
+
updatedAt: events[events.length - 1].at,
|
|
163304
|
+
events
|
|
163305
|
+
};
|
|
163306
|
+
return { ...ledger, outcome: evaluateTaskContinuity(ledger) };
|
|
163307
|
+
}
|
|
163308
|
+
var TASK_CONTINUITY_EVENT_KINDS, MAX_TEXT_LENGTH2, MAX_TASK_LENGTH, MAX_LIST_ITEMS2, MAX_EVIDENCE_REFS, MAX_EVENTS_PER_TASK, TaskContinuityStore;
|
|
163309
|
+
var init_task_continuity = __esm({
|
|
163310
|
+
"src/knowledge/task-continuity.ts"() {
|
|
163311
|
+
"use strict";
|
|
163312
|
+
init_esm_shims();
|
|
163313
|
+
init_secret_filter();
|
|
163314
|
+
init_sqlite_db();
|
|
163315
|
+
TASK_CONTINUITY_EVENT_KINDS = [
|
|
163316
|
+
"task",
|
|
163317
|
+
"requirement",
|
|
163318
|
+
"decision",
|
|
163319
|
+
"verification",
|
|
163320
|
+
"risk",
|
|
163321
|
+
"outcome"
|
|
163322
|
+
];
|
|
163323
|
+
MAX_TEXT_LENGTH2 = 2e3;
|
|
163324
|
+
MAX_TASK_LENGTH = 1e3;
|
|
163325
|
+
MAX_LIST_ITEMS2 = 8;
|
|
163326
|
+
MAX_EVIDENCE_REFS = 8;
|
|
163327
|
+
MAX_EVENTS_PER_TASK = 200;
|
|
163328
|
+
TaskContinuityStore = class {
|
|
163329
|
+
db = null;
|
|
163330
|
+
async init(dataDir) {
|
|
163331
|
+
this.db = getDatabase(dataDir);
|
|
163332
|
+
}
|
|
163333
|
+
requireDb() {
|
|
163334
|
+
if (!this.db) throw new Error("TaskContinuityStore is not initialized.");
|
|
163335
|
+
return this.db;
|
|
163336
|
+
}
|
|
163337
|
+
insert(input) {
|
|
163338
|
+
const db2 = this.requireDb();
|
|
163339
|
+
const projectId = clean(input.projectId, 500);
|
|
163340
|
+
const taskId = clean(input.taskId, 120);
|
|
163341
|
+
const eventKey = input.eventKey ? clean(input.eventKey, 200) : void 0;
|
|
163342
|
+
if (eventKey) {
|
|
163343
|
+
const existing = db2.prepare(
|
|
163344
|
+
"SELECT * FROM task_continuity_events WHERE project_id = ? AND task_id = ? AND event_key = ?"
|
|
163345
|
+
).get(projectId, taskId, eventKey);
|
|
163346
|
+
if (existing) return rowToEvent4(existing);
|
|
163347
|
+
}
|
|
163348
|
+
const existingCount = db2.prepare(
|
|
163349
|
+
"SELECT COUNT(*) AS count FROM task_continuity_events WHERE project_id = ? AND task_id = ?"
|
|
163350
|
+
).get(projectId, taskId);
|
|
163351
|
+
if (Number(existingCount?.count ?? 0) >= MAX_EVENTS_PER_TASK) {
|
|
163352
|
+
throw new Error("Task continuity ledger reached its 200-event limit.");
|
|
163353
|
+
}
|
|
163354
|
+
const event = {
|
|
163355
|
+
id: randomUUID17(),
|
|
163356
|
+
projectId,
|
|
163357
|
+
taskId,
|
|
163358
|
+
task: clean(input.task, MAX_TASK_LENGTH),
|
|
163359
|
+
kind: input.kind,
|
|
163360
|
+
content: clean(input.content),
|
|
163361
|
+
...input.status ? { status: input.status } : {},
|
|
163362
|
+
...input.sourceRef ? { sourceRef: clean(input.sourceRef, 500) } : {},
|
|
163363
|
+
evidenceRefs: cleanList(input.evidenceRefs, 500).slice(0, MAX_EVIDENCE_REFS),
|
|
163364
|
+
...input.actor ? { actor: clean(input.actor, 200) } : {},
|
|
163365
|
+
at: input.at ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
163366
|
+
...eventKey ? { eventKey } : {},
|
|
163367
|
+
...input.itemKey ? { itemKey: clean(input.itemKey, 120) } : {},
|
|
163368
|
+
...input.supersedesId ? { supersedesId: clean(input.supersedesId, 120) } : {}
|
|
163369
|
+
};
|
|
163370
|
+
db2.prepare(`
|
|
163371
|
+
INSERT INTO task_continuity_events (
|
|
163372
|
+
id, project_id, task_id, task, kind, content, item_status,
|
|
163373
|
+
source_ref, evidence_json, actor, created_at, event_key, item_key, supersedes_id
|
|
163374
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
163375
|
+
`).run(
|
|
163376
|
+
event.id,
|
|
163377
|
+
event.projectId,
|
|
163378
|
+
event.taskId,
|
|
163379
|
+
event.task,
|
|
163380
|
+
event.kind,
|
|
163381
|
+
event.content,
|
|
163382
|
+
event.status ?? null,
|
|
163383
|
+
event.sourceRef ?? null,
|
|
163384
|
+
JSON.stringify(event.evidenceRefs),
|
|
163385
|
+
event.actor ?? null,
|
|
163386
|
+
event.at,
|
|
163387
|
+
event.eventKey ?? null,
|
|
163388
|
+
event.itemKey ?? null,
|
|
163389
|
+
event.supersedesId ?? null
|
|
163390
|
+
);
|
|
163391
|
+
return event;
|
|
163392
|
+
}
|
|
163393
|
+
start(input) {
|
|
163394
|
+
const task = clean(input.task, MAX_TASK_LENGTH);
|
|
163395
|
+
if (!task) throw new Error("A non-empty task is required.");
|
|
163396
|
+
const idempotencyKey = input.idempotencyKey ? clean(input.idempotencyKey, 200) : void 0;
|
|
163397
|
+
const taskId = clean(input.taskId ?? idempotencyKey ?? "", 120) || randomUUID17();
|
|
163398
|
+
const requirements = cleanList(input.requirements);
|
|
163399
|
+
const transaction = this.requireDb().transaction(() => {
|
|
163400
|
+
this.insert({
|
|
163401
|
+
projectId: input.projectId,
|
|
163402
|
+
taskId,
|
|
163403
|
+
task,
|
|
163404
|
+
kind: "task",
|
|
163405
|
+
content: task,
|
|
163406
|
+
status: "open",
|
|
163407
|
+
actor: input.actor,
|
|
163408
|
+
...idempotencyKey ? { eventKey: `start:${idempotencyKey}` } : {}
|
|
163409
|
+
});
|
|
163410
|
+
for (const requirement of requirements) {
|
|
163411
|
+
this.insert({
|
|
163412
|
+
projectId: input.projectId,
|
|
163413
|
+
taskId,
|
|
163414
|
+
task,
|
|
163415
|
+
kind: "requirement",
|
|
163416
|
+
content: requirement,
|
|
163417
|
+
actor: input.actor
|
|
163418
|
+
});
|
|
163419
|
+
}
|
|
163420
|
+
});
|
|
163421
|
+
transaction.immediate();
|
|
163422
|
+
return { taskId, ledger: this.get(input.projectId, taskId) };
|
|
163423
|
+
}
|
|
163424
|
+
record(input) {
|
|
163425
|
+
const projectId = clean(input.projectId, 500);
|
|
163426
|
+
const taskId = clean(input.taskId, 120);
|
|
163427
|
+
const existing = this.get(projectId, taskId);
|
|
163428
|
+
if (!existing) throw new Error("Task continuity ledger not found: " + taskId);
|
|
163429
|
+
const transaction = this.requireDb().transaction(() => this.insert({
|
|
163430
|
+
projectId,
|
|
163431
|
+
taskId,
|
|
163432
|
+
task: existing.task,
|
|
163433
|
+
kind: input.kind,
|
|
163434
|
+
content: input.content,
|
|
163435
|
+
...input.kind === "verification" && input.verificationStatus ? { status: input.verificationStatus } : {},
|
|
163436
|
+
sourceRef: input.sourceRef,
|
|
163437
|
+
evidenceRefs: input.evidenceRefs,
|
|
163438
|
+
actor: input.actor,
|
|
163439
|
+
at: input.at,
|
|
163440
|
+
...input.idempotencyKey ? { eventKey: input.idempotencyKey } : {},
|
|
163441
|
+
...input.verificationId ? { itemKey: input.verificationId } : {}
|
|
163442
|
+
}));
|
|
163443
|
+
const event = transaction.immediate();
|
|
163444
|
+
return { event, ledger: this.get(projectId, taskId) };
|
|
163445
|
+
}
|
|
163446
|
+
close(input) {
|
|
163447
|
+
const projectId = clean(input.projectId, 500);
|
|
163448
|
+
const taskId = clean(input.taskId, 120);
|
|
163449
|
+
const existing = this.get(projectId, taskId);
|
|
163450
|
+
if (!existing) throw new Error("Task continuity ledger not found: " + taskId);
|
|
163451
|
+
const transaction = this.requireDb().transaction(() => this.insert({
|
|
163452
|
+
projectId,
|
|
163453
|
+
taskId,
|
|
163454
|
+
task: existing.task,
|
|
163455
|
+
kind: "outcome",
|
|
163456
|
+
content: input.content,
|
|
163457
|
+
status: input.status,
|
|
163458
|
+
sourceRef: input.sourceRef,
|
|
163459
|
+
evidenceRefs: input.evidenceRefs,
|
|
163460
|
+
actor: input.actor,
|
|
163461
|
+
at: input.at,
|
|
163462
|
+
...input.idempotencyKey ? { eventKey: input.idempotencyKey } : {}
|
|
163463
|
+
}));
|
|
163464
|
+
const event = transaction.immediate();
|
|
163465
|
+
return { event, ledger: this.get(projectId, taskId) };
|
|
163466
|
+
}
|
|
163467
|
+
get(projectId, taskId) {
|
|
163468
|
+
const normalizedProjectId = clean(projectId, 500);
|
|
163469
|
+
const normalizedTaskId = clean(taskId, 120);
|
|
163470
|
+
const rows = this.requireDb().prepare(`
|
|
163471
|
+
SELECT * FROM task_continuity_events
|
|
163472
|
+
WHERE project_id = ? AND task_id = ?
|
|
163473
|
+
ORDER BY created_at ASC, rowid ASC
|
|
163474
|
+
`).all(normalizedProjectId, normalizedTaskId);
|
|
163475
|
+
if (rows.length === 0) return void 0;
|
|
163476
|
+
return aggregate(rows.map(rowToEvent4));
|
|
163477
|
+
}
|
|
163478
|
+
list(projectId, limit2 = 20) {
|
|
163479
|
+
const rows = this.requireDb().prepare(`
|
|
163480
|
+
SELECT task_id
|
|
163481
|
+
FROM task_continuity_events
|
|
163482
|
+
WHERE project_id = ?
|
|
163483
|
+
GROUP BY task_id
|
|
163484
|
+
ORDER BY MAX(created_at) DESC
|
|
163485
|
+
LIMIT ?
|
|
163486
|
+
`).all(projectId, Math.min(100, Math.max(1, Math.floor(limit2))));
|
|
163487
|
+
return rows.map((row) => this.get(projectId, String(row.task_id))).filter((ledger) => Boolean(ledger));
|
|
163488
|
+
}
|
|
163489
|
+
};
|
|
163490
|
+
}
|
|
163491
|
+
});
|
|
163492
|
+
|
|
162980
163493
|
// src/codegraph/auto-context.ts
|
|
162981
163494
|
var auto_context_exports = {};
|
|
162982
163495
|
__export(auto_context_exports, {
|
|
@@ -163233,6 +163746,16 @@ async function buildAutoProjectContext(input) {
|
|
|
163233
163746
|
};
|
|
163234
163747
|
}
|
|
163235
163748
|
}
|
|
163749
|
+
let continuity = input.continuity;
|
|
163750
|
+
if (!continuity && input.taskId) {
|
|
163751
|
+
try {
|
|
163752
|
+
const { TaskContinuityStore: TaskContinuityStore2 } = await Promise.resolve().then(() => (init_task_continuity(), task_continuity_exports));
|
|
163753
|
+
const continuityStore = new TaskContinuityStore2();
|
|
163754
|
+
await continuityStore.init(input.dataDir);
|
|
163755
|
+
continuity = continuityStore.get(input.project.id, input.taskId);
|
|
163756
|
+
} catch {
|
|
163757
|
+
}
|
|
163758
|
+
}
|
|
163236
163759
|
const alwaysOn = await buildAlwaysOnBlock({
|
|
163237
163760
|
dataDir: input.dataDir,
|
|
163238
163761
|
projectId: input.project.id,
|
|
@@ -163251,6 +163774,7 @@ async function buildAutoProjectContext(input) {
|
|
|
163251
163774
|
providerQuality: providerQuality2,
|
|
163252
163775
|
currentFacts: worksetFactLines(currentFacts),
|
|
163253
163776
|
...continuation ? { continuation } : {},
|
|
163777
|
+
...continuity ? { continuity } : {},
|
|
163254
163778
|
codeState: codeStateLine(overview),
|
|
163255
163779
|
...codeEvolution ? { codeEvolution } : {},
|
|
163256
163780
|
reliableMemory: sourceSets.reliableSources.slice(0, lens.sourceLimit).map((source) => ({
|
|
@@ -163298,6 +163822,7 @@ async function buildAutoProjectContext(input) {
|
|
|
163298
163822
|
refresh,
|
|
163299
163823
|
providerQuality: providerQuality2,
|
|
163300
163824
|
...continuationRequested && workset.continuation ? { continuation: workset.continuation } : {},
|
|
163825
|
+
...workset.continuity ? { continuity: workset.continuity } : {},
|
|
163301
163826
|
workset
|
|
163302
163827
|
};
|
|
163303
163828
|
}
|
|
@@ -163599,7 +164124,14 @@ function buildBoundedContextReceipt(input) {
|
|
|
163599
164124
|
externalState: provider2?.external.state ?? "not-detected",
|
|
163600
164125
|
...input.workset.provenance.snapshotId ? { snapshotId: input.workset.provenance.snapshotId } : {}
|
|
163601
164126
|
},
|
|
163602
|
-
...input.workset.agentLoadout ? { loadout: input.workset.agentLoadout } : {}
|
|
164127
|
+
...input.workset.agentLoadout ? { loadout: input.workset.agentLoadout } : {},
|
|
164128
|
+
...input.workset.continuity ? {
|
|
164129
|
+
continuity: {
|
|
164130
|
+
taskId: input.workset.continuity.taskId,
|
|
164131
|
+
status: input.workset.continuity.status,
|
|
164132
|
+
outcome: input.workset.continuity.outcome
|
|
164133
|
+
}
|
|
164134
|
+
} : {}
|
|
163603
164135
|
};
|
|
163604
164136
|
}
|
|
163605
164137
|
var init_context_receipt = __esm({
|
|
@@ -164231,15 +164763,21 @@ var team_store_exports = {};
|
|
|
164231
164763
|
__export(team_store_exports, {
|
|
164232
164764
|
AGENT_TYPE_ROLE_MAP: () => AGENT_TYPE_ROLE_MAP,
|
|
164233
164765
|
DEFAULT_ROLES: () => DEFAULT_ROLES,
|
|
164766
|
+
DEFAULT_TEAM_QUERY_LIMIT: () => DEFAULT_TEAM_QUERY_LIMIT,
|
|
164767
|
+
MAX_TEAM_QUERY_LIMIT: () => MAX_TEAM_QUERY_LIMIT,
|
|
164234
164768
|
TeamStore: () => TeamStore,
|
|
164235
164769
|
getTeamStore: () => getTeamStore,
|
|
164236
164770
|
initTeamStore: () => initTeamStore,
|
|
164237
164771
|
isTeamStoreInitialized: () => isTeamStoreInitialized,
|
|
164238
164772
|
resetTeamStore: () => resetTeamStore
|
|
164239
164773
|
});
|
|
164240
|
-
import { randomUUID as
|
|
164774
|
+
import { randomUUID as randomUUID18 } from "crypto";
|
|
164241
164775
|
import path31 from "path";
|
|
164242
164776
|
import fs18 from "fs";
|
|
164777
|
+
function clampTeamQueryLimit(limit2) {
|
|
164778
|
+
if (!Number.isFinite(limit2) || limit2 == null) return DEFAULT_TEAM_QUERY_LIMIT;
|
|
164779
|
+
return Math.min(MAX_TEAM_QUERY_LIMIT, Math.max(1, Math.floor(limit2)));
|
|
164780
|
+
}
|
|
164243
164781
|
function getTeamStore() {
|
|
164244
164782
|
if (!_teamStore) {
|
|
164245
164783
|
throw new Error("[memorix] TeamStore not initialized \u2014 call initTeamStore() first");
|
|
@@ -164263,12 +164801,14 @@ function resetTeamStore() {
|
|
|
164263
164801
|
_teamStore = null;
|
|
164264
164802
|
_teamStoreDataDir = null;
|
|
164265
164803
|
}
|
|
164266
|
-
var DEFAULT_ROLES, AGENT_TYPE_ROLE_MAP, TeamStore, _teamStore, _teamStoreDataDir;
|
|
164804
|
+
var DEFAULT_TEAM_QUERY_LIMIT, MAX_TEAM_QUERY_LIMIT, DEFAULT_ROLES, AGENT_TYPE_ROLE_MAP, TeamStore, _teamStore, _teamStoreDataDir;
|
|
164267
164805
|
var init_team_store = __esm({
|
|
164268
164806
|
"src/team/team-store.ts"() {
|
|
164269
164807
|
"use strict";
|
|
164270
164808
|
init_esm_shims();
|
|
164271
164809
|
init_sqlite_db();
|
|
164810
|
+
DEFAULT_TEAM_QUERY_LIMIT = 100;
|
|
164811
|
+
MAX_TEAM_QUERY_LIMIT = 500;
|
|
164272
164812
|
DEFAULT_ROLES = [
|
|
164273
164813
|
{ roleId: "planner", label: "Planner", description: "Breaks down requirements, creates tasks, defines dependencies", preferredAgentTypes: ["claude-code", "cursor", "codex"], maxConcurrent: 2 },
|
|
164274
164814
|
{ roleId: "researcher", label: "Researcher", description: "Investigates codebase, gathers context, answers questions", preferredAgentTypes: ["claude-code", "cursor", "gemini-cli"], maxConcurrent: 2 },
|
|
@@ -164526,7 +165066,7 @@ var init_team_store = __esm({
|
|
|
164526
165066
|
* reactivate it (preserving agent_id). Otherwise create a new one.
|
|
164527
165067
|
*/
|
|
164528
165068
|
registerAgent(input) {
|
|
164529
|
-
const instanceId = input.instanceId ||
|
|
165069
|
+
const instanceId = input.instanceId || randomUUID18();
|
|
164530
165070
|
const now3 = Date.now();
|
|
164531
165071
|
const existing = this.stmtAgentFindByInstance.get(
|
|
164532
165072
|
input.projectId,
|
|
@@ -164552,7 +165092,7 @@ var init_team_store = __esm({
|
|
|
164552
165092
|
this.eventBus?.emit("agent:joined", { agentId: row2.agent_id, projectId: input.projectId, agentType: input.agentType });
|
|
164553
165093
|
return row2;
|
|
164554
165094
|
}
|
|
164555
|
-
const agentId =
|
|
165095
|
+
const agentId = randomUUID18();
|
|
164556
165096
|
this.stmtAgentUpsert.run({
|
|
164557
165097
|
agent_id: agentId,
|
|
164558
165098
|
project_id: input.projectId,
|
|
@@ -164578,32 +165118,37 @@ var init_team_store = __esm({
|
|
|
164578
165118
|
return this.stmtAgentFindByInstance.get(projectId, agentType, instanceId);
|
|
164579
165119
|
}
|
|
164580
165120
|
listAgents(projectId, filter) {
|
|
164581
|
-
const
|
|
165121
|
+
const limit2 = clampTeamQueryLimit(filter?.limit);
|
|
164582
165122
|
if (filter?.status) {
|
|
164583
|
-
return
|
|
165123
|
+
return this.db.prepare(
|
|
165124
|
+
`SELECT * FROM team_agents WHERE project_id = ? AND status = ? ORDER BY joined_at DESC LIMIT ?`
|
|
165125
|
+
).all(projectId, filter.status, limit2);
|
|
164584
165126
|
}
|
|
164585
|
-
return
|
|
165127
|
+
return this.db.prepare(
|
|
165128
|
+
`SELECT * FROM team_agents WHERE project_id = ? ORDER BY joined_at DESC LIMIT ?`
|
|
165129
|
+
).all(projectId, limit2);
|
|
164586
165130
|
}
|
|
164587
165131
|
/** List agents across all projects (for global scope) */
|
|
164588
|
-
listAllAgents() {
|
|
165132
|
+
listAllAgents(limit2) {
|
|
164589
165133
|
if (!this.db) return [];
|
|
164590
|
-
return this.db.prepare("SELECT * FROM team_agents ORDER BY last_heartbeat DESC").all();
|
|
165134
|
+
return this.db.prepare("SELECT * FROM team_agents ORDER BY last_heartbeat DESC LIMIT ?").all(clampTeamQueryLimit(limit2));
|
|
164591
165135
|
}
|
|
164592
165136
|
/** List locks across all projects (for global scope) */
|
|
164593
|
-
listAllLocks() {
|
|
165137
|
+
listAllLocks(limit2) {
|
|
164594
165138
|
if (!this.db) return [];
|
|
164595
165139
|
this.db.prepare("DELETE FROM team_locks WHERE expires_at <= ?").run(Date.now());
|
|
164596
|
-
return this.db.prepare("SELECT * FROM team_locks WHERE expires_at > ? ORDER BY locked_at DESC").all(Date.now());
|
|
165140
|
+
return this.db.prepare("SELECT * FROM team_locks WHERE expires_at > ? ORDER BY locked_at DESC LIMIT ?").all(Date.now(), clampTeamQueryLimit(limit2));
|
|
164597
165141
|
}
|
|
164598
165142
|
/** List tasks across all projects (for global scope) */
|
|
164599
165143
|
listAllTasks(filter) {
|
|
164600
165144
|
if (!this.db) return [];
|
|
165145
|
+
const limit2 = clampTeamQueryLimit(filter?.limit);
|
|
164601
165146
|
if (filter?.available) {
|
|
164602
165147
|
return this.db.prepare(
|
|
164603
|
-
`SELECT t.* FROM team_tasks t WHERE t.status = 'pending' AND t.assignee_agent_id IS NULL ORDER BY t.created_at DESC
|
|
164604
|
-
).all();
|
|
165148
|
+
`SELECT t.* FROM team_tasks t WHERE t.status = 'pending' AND t.assignee_agent_id IS NULL ORDER BY t.created_at DESC LIMIT ?`
|
|
165149
|
+
).all(limit2);
|
|
164605
165150
|
}
|
|
164606
|
-
return this.db.prepare("SELECT * FROM team_tasks ORDER BY created_at DESC").all();
|
|
165151
|
+
return this.db.prepare("SELECT * FROM team_tasks ORDER BY created_at DESC LIMIT ?").all(limit2);
|
|
164607
165152
|
}
|
|
164608
165153
|
heartbeat(agentId) {
|
|
164609
165154
|
const info = this.stmtAgentUpdateHeartbeat.run(Date.now(), agentId);
|
|
@@ -164638,7 +165183,10 @@ var init_team_store = __esm({
|
|
|
164638
165183
|
return staleIds;
|
|
164639
165184
|
}
|
|
164640
165185
|
getActiveCount(projectId) {
|
|
164641
|
-
|
|
165186
|
+
const row = this.db.prepare(
|
|
165187
|
+
`SELECT COUNT(*) AS count FROM team_agents WHERE project_id = ? AND status = 'active'`
|
|
165188
|
+
).get(projectId);
|
|
165189
|
+
return Number(row?.count ?? 0);
|
|
164642
165190
|
}
|
|
164643
165191
|
// ═══════════════════════════════════════════════════════════════════
|
|
164644
165192
|
// Message Operations
|
|
@@ -164654,7 +165202,7 @@ var init_team_store = __esm({
|
|
|
164654
165202
|
return { error: `Recipient agent '${input.recipientAgentId}' not found \u2014 cannot send to unknown agent` };
|
|
164655
165203
|
}
|
|
164656
165204
|
}
|
|
164657
|
-
const id =
|
|
165205
|
+
const id = randomUUID18();
|
|
164658
165206
|
const now3 = Date.now();
|
|
164659
165207
|
const row = {
|
|
164660
165208
|
id,
|
|
@@ -164673,8 +165221,14 @@ var init_team_store = __esm({
|
|
|
164673
165221
|
this.stmtMsgInsert.run(row);
|
|
164674
165222
|
return row;
|
|
164675
165223
|
}
|
|
164676
|
-
getInbox(projectId, agentId) {
|
|
164677
|
-
return this.
|
|
165224
|
+
getInbox(projectId, agentId, limit2) {
|
|
165225
|
+
return this.db.prepare(`
|
|
165226
|
+
SELECT * FROM team_messages
|
|
165227
|
+
WHERE project_id = ?
|
|
165228
|
+
AND (recipient_agent_id = ? OR recipient_agent_id IS NULL)
|
|
165229
|
+
ORDER BY created_at ASC
|
|
165230
|
+
LIMIT ?
|
|
165231
|
+
`).all(projectId, agentId, clampTeamQueryLimit(limit2));
|
|
164678
165232
|
}
|
|
164679
165233
|
getUnreadCount(projectId, agentId) {
|
|
164680
165234
|
const row = this.stmtMsgUnreadCount.get(projectId, agentId);
|
|
@@ -164704,7 +165258,7 @@ var init_team_store = __esm({
|
|
|
164704
165258
|
// Task Operations (with atomic claim semantics)
|
|
164705
165259
|
// ═══════════════════════════════════════════════════════════════════
|
|
164706
165260
|
createTask(input) {
|
|
164707
|
-
const taskId =
|
|
165261
|
+
const taskId = randomUUID18();
|
|
164708
165262
|
const now3 = Date.now();
|
|
164709
165263
|
const row = {
|
|
164710
165264
|
task_id: taskId,
|
|
@@ -164831,17 +165385,22 @@ var init_team_store = __esm({
|
|
|
164831
165385
|
return info.changes;
|
|
164832
165386
|
}
|
|
164833
165387
|
listTasks(projectId, filter) {
|
|
164834
|
-
|
|
164835
|
-
|
|
164836
|
-
|
|
164837
|
-
const all = this.stmtTaskListByProject.all(projectId);
|
|
165388
|
+
const clauses = ["project_id = ?"];
|
|
165389
|
+
const values = [projectId];
|
|
165390
|
+
if (filter?.available) clauses.push("status = 'pending'", "assignee_agent_id IS NULL");
|
|
164838
165391
|
if (filter?.status) {
|
|
164839
|
-
|
|
165392
|
+
clauses.push("status = ?");
|
|
165393
|
+
values.push(filter.status);
|
|
164840
165394
|
}
|
|
164841
165395
|
if (filter?.assignee) {
|
|
164842
|
-
|
|
165396
|
+
clauses.push("assignee_agent_id = ?");
|
|
165397
|
+
values.push(filter.assignee);
|
|
164843
165398
|
}
|
|
164844
|
-
|
|
165399
|
+
values.push(clampTeamQueryLimit(filter?.limit));
|
|
165400
|
+
const orderBy = filter?.available ? "created_at ASC, rowid ASC" : "created_at DESC, rowid DESC";
|
|
165401
|
+
return this.db.prepare(
|
|
165402
|
+
`SELECT * FROM team_tasks WHERE ${clauses.join(" AND ")} ORDER BY ${orderBy} LIMIT ?`
|
|
165403
|
+
).all(...values);
|
|
164845
165404
|
}
|
|
164846
165405
|
/**
|
|
164847
165406
|
* List available tasks for a specific agent, sorted by role affinity.
|
|
@@ -164853,7 +165412,7 @@ var init_team_store = __esm({
|
|
|
164853
165412
|
const agent = this.stmtAgentFindById.get(agentId);
|
|
164854
165413
|
if (!agent) return [];
|
|
164855
165414
|
const agentRole = agent.role;
|
|
164856
|
-
const available = this.
|
|
165415
|
+
const available = this.listTasks(projectId, { available: true, limit: MAX_TEAM_QUERY_LIMIT });
|
|
164857
165416
|
const eligible = available.filter((t2) => !t2.required_role || t2.required_role === agentRole);
|
|
164858
165417
|
const score = (t2) => {
|
|
164859
165418
|
if (t2.preferred_role === agentRole) return 0;
|
|
@@ -164907,12 +165466,16 @@ var init_team_store = __esm({
|
|
|
164907
165466
|
const row = this.stmtLockGet.get(file, projectId);
|
|
164908
165467
|
return row ?? null;
|
|
164909
165468
|
}
|
|
164910
|
-
listLocks(projectId, agentId) {
|
|
165469
|
+
listLocks(projectId, agentId, limit2) {
|
|
164911
165470
|
this.stmtLockDeleteExpired.run(projectId, Date.now());
|
|
164912
165471
|
if (agentId) {
|
|
164913
|
-
return this.
|
|
165472
|
+
return this.db.prepare(
|
|
165473
|
+
`SELECT * FROM team_locks WHERE project_id = ? AND locked_by = ? ORDER BY locked_at DESC LIMIT ?`
|
|
165474
|
+
).all(projectId, agentId, clampTeamQueryLimit(limit2));
|
|
164914
165475
|
}
|
|
164915
|
-
return this.
|
|
165476
|
+
return this.db.prepare(
|
|
165477
|
+
`SELECT * FROM team_locks WHERE project_id = ? ORDER BY locked_at DESC LIMIT ?`
|
|
165478
|
+
).all(projectId, clampTeamQueryLimit(limit2));
|
|
164916
165479
|
}
|
|
164917
165480
|
releaseAllLocks(agentId) {
|
|
164918
165481
|
const info = this.stmtLockDeleteByAgent.run(agentId);
|
|
@@ -164976,7 +165539,7 @@ var init_team_store = __esm({
|
|
|
164976
165539
|
for (const [agentId, msgs] of Object.entries(snap.messages.inboxes)) {
|
|
164977
165540
|
for (const msg of msgs) {
|
|
164978
165541
|
this.stmtMsgInsert.run({
|
|
164979
|
-
id: msg.id ??
|
|
165542
|
+
id: msg.id ?? randomUUID18(),
|
|
164980
165543
|
project_id: "migrated",
|
|
164981
165544
|
sender_agent_id: msg.from ?? "unknown",
|
|
164982
165545
|
recipient_agent_id: msg.to === "__broadcast__" ? null : msg.to ?? agentId,
|
|
@@ -167934,7 +168497,7 @@ __export(planner_exports, {
|
|
|
167934
168497
|
materializeTaskGraph: () => materializeTaskGraph,
|
|
167935
168498
|
seedAutonomousPipeline: () => seedAutonomousPipeline
|
|
167936
168499
|
});
|
|
167937
|
-
import { randomUUID as
|
|
168500
|
+
import { randomUUID as randomUUID19 } from "crypto";
|
|
167938
168501
|
function isPlannerTask(metadata) {
|
|
167939
168502
|
if (!metadata) return null;
|
|
167940
168503
|
try {
|
|
@@ -167992,7 +168555,7 @@ function seedAutonomousPipeline(teamStore, projectId, config, opts) {
|
|
|
167992
168555
|
const maxIterations = config.maxIterations ?? 3;
|
|
167993
168556
|
const taskBudget = config.taskBudget ?? 15;
|
|
167994
168557
|
const structuredPlan = opts?.structuredPlan ?? true;
|
|
167995
|
-
const pipelineId =
|
|
168558
|
+
const pipelineId = randomUUID19();
|
|
167996
168559
|
const meta = {
|
|
167997
168560
|
plannerType: "plan",
|
|
167998
168561
|
pipelineId,
|
|
@@ -168673,6 +169236,7 @@ var init_official_skills = __esm({
|
|
|
168673
169236
|
"| Need the sequence around one memory | `memorix_timeline` | `memorix memory timeline --id <id>` |",
|
|
168674
169237
|
"| Check source and freshness for a memory | `memorix_evidence` | `memorix evidence list|get|events` |",
|
|
168675
169238
|
"| Record whether a memory helped, conflicted, or was corrected | `memorix_feedback` | `memorix feedback record|show|audit` |",
|
|
169239
|
+
"| Track task requirements, decisions, verification, and outcome | `memorix_continuity` | `memorix continuity start|record|show|close` |",
|
|
168676
169240
|
"| Inspect or import controlled media | `memorix_media` | `memorix media import|attach|list|show|status` |",
|
|
168677
169241
|
'| Learned reusable project knowledge | `memorix_store` | `memorix memory store --type <type> --entity <name> --title "<title>" "<text>"` |',
|
|
168678
169242
|
"| Task or bug is complete/outdated | `memorix_resolve` | `memorix memory resolve --ids <ids>` |",
|
|
@@ -168696,6 +169260,7 @@ var init_official_skills = __esm({
|
|
|
168696
169260
|
"3. Use stale or unbound memory only as a warning or search lead.",
|
|
168697
169261
|
"4. Store durable decisions, fixes, and gotchas after the project state changes.",
|
|
168698
169262
|
"5. Resolve completed or obsolete memories so future briefs stay small.",
|
|
169263
|
+
"6. For multi-step work, start a continuity ledger and pass its taskId back to memorix_project_context.",
|
|
168699
169264
|
"",
|
|
168700
169265
|
"## Store Rules",
|
|
168701
169266
|
"",
|
|
@@ -170417,7 +170982,7 @@ __export(server_exports2, {
|
|
|
170417
170982
|
createMemorixServer: () => createMemorixServer,
|
|
170418
170983
|
shouldAwaitProjectRuntime: () => shouldAwaitProjectRuntime
|
|
170419
170984
|
});
|
|
170420
|
-
import { createHash as
|
|
170985
|
+
import { createHash as createHash19 } from "crypto";
|
|
170421
170986
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
170422
170987
|
import { z as z627 } from "zod";
|
|
170423
170988
|
function formatFormationStageDurations(stageDurationsMs) {
|
|
@@ -170501,7 +171066,7 @@ function coerceObjectArray(val) {
|
|
|
170501
171066
|
return [];
|
|
170502
171067
|
}
|
|
170503
171068
|
function createDeterministicInstanceId(projectId, agentType, agentName) {
|
|
170504
|
-
const digest2 =
|
|
171069
|
+
const digest2 = createHash19("sha256").update(projectId).update("\n").update(agentType).update("\n").update(agentName ?? "").digest("hex").slice(0, 24);
|
|
170505
171070
|
return `auto-${digest2}`;
|
|
170506
171071
|
}
|
|
170507
171072
|
function shouldAwaitProjectRuntime(toolName) {
|
|
@@ -170708,6 +171273,22 @@ async function createMemorixServer(cwd, existingServer, sharedTeam, options = {}
|
|
|
170708
171273
|
}
|
|
170709
171274
|
await projectRuntimeInitPromise;
|
|
170710
171275
|
};
|
|
171276
|
+
const activateProjectRuntime = async () => {
|
|
171277
|
+
if (!projectResolved) return;
|
|
171278
|
+
await initObservationStore(projectDir2);
|
|
171279
|
+
await initMiniSkillStore(projectDir2);
|
|
171280
|
+
await initSessionStore(projectDir2);
|
|
171281
|
+
await initObservations(projectDir2, { skipCorpusLoad: true });
|
|
171282
|
+
try {
|
|
171283
|
+
const { initProjectRoot: initProjectRoot2 } = await Promise.resolve().then(() => (init_yaml_loader(), yaml_loader_exports));
|
|
171284
|
+
const { resetDotenv: resetDotenv2, loadDotenv: loadDotenv2 } = await Promise.resolve().then(() => (init_dotenv_loader(), dotenv_loader_exports));
|
|
171285
|
+
initProjectRoot2(project.rootPath);
|
|
171286
|
+
resetDotenv2();
|
|
171287
|
+
loadDotenv2(project.rootPath);
|
|
171288
|
+
} catch {
|
|
171289
|
+
}
|
|
171290
|
+
initLLM({ projectRoot: project.rootPath });
|
|
171291
|
+
};
|
|
170711
171292
|
let maintenanceWorker = null;
|
|
170712
171293
|
const startProjectMaintenanceWorker = async (autoCleanup = false) => {
|
|
170713
171294
|
maintenanceWorker?.stop();
|
|
@@ -171623,6 +172204,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
171623
172204
|
description: "Build a compact Memory Autopilot brief for the current coding task. Schedules Code Memory refresh when needed, includes Start here files, reliable code-bound memories, stale/suspect cautions, and verification hints. Use this at the start of a new coding turn or after switching tasks.",
|
|
171624
172205
|
inputSchema: {
|
|
171625
172206
|
task: z627.string().optional().describe("Current coding task or question"),
|
|
172207
|
+
taskId: z627.string().max(120).optional().describe("Optional task continuity ledger id to include in the brief"),
|
|
171626
172208
|
refresh: z627.enum(["auto", "always", "never"]).optional().default("auto").describe(
|
|
171627
172209
|
"Code Memory refresh policy. auto refreshes only when missing or stale."
|
|
171628
172210
|
),
|
|
@@ -171647,7 +172229,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
171647
172229
|
limit: z627.number().optional().describe("Reserved for future source limits; current prompt stays compact by default.")
|
|
171648
172230
|
}
|
|
171649
172231
|
},
|
|
171650
|
-
async ({ task, refresh, format, agent }) => {
|
|
172232
|
+
async ({ task, taskId, refresh, format, agent }) => {
|
|
171651
172233
|
const unresolved = requireResolvedProject("build project context for the current project");
|
|
171652
172234
|
if (unresolved) return unresolved;
|
|
171653
172235
|
const [
|
|
@@ -171677,6 +172259,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
171677
172259
|
dataDir: projectDir2,
|
|
171678
172260
|
observations: observations2,
|
|
171679
172261
|
task,
|
|
172262
|
+
taskId,
|
|
171680
172263
|
agent,
|
|
171681
172264
|
refresh: refresh ?? "auto",
|
|
171682
172265
|
reader: getObservationReader(),
|
|
@@ -174102,6 +174685,94 @@ ${json2}
|
|
|
174102
174685
|
}
|
|
174103
174686
|
}
|
|
174104
174687
|
);
|
|
174688
|
+
server.registerTool(
|
|
174689
|
+
"memorix_continuity",
|
|
174690
|
+
{
|
|
174691
|
+
title: "Task Continuity Ledger",
|
|
174692
|
+
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.",
|
|
174693
|
+
inputSchema: {
|
|
174694
|
+
action: z627.enum(["start", "record", "show", "list", "close"]).describe("Continuity operation"),
|
|
174695
|
+
taskId: z627.string().max(120).optional().describe("Continuity task id"),
|
|
174696
|
+
task: z627.string().max(1e3).optional().describe("Task description for start"),
|
|
174697
|
+
requirements: z627.array(z627.string().max(2e3)).max(8).optional().describe("Requirements for start"),
|
|
174698
|
+
kind: z627.enum(["requirement", "decision", "verification", "risk"]).optional().describe("Entry kind for record"),
|
|
174699
|
+
content: z627.string().max(2e3).optional().describe("Requirement, decision, verification, risk, or outcome text"),
|
|
174700
|
+
verificationStatus: z627.enum(["pending", "passed", "failed", "skipped"]).optional(),
|
|
174701
|
+
verificationId: z627.string().max(120).optional().describe("Stable verification obligation id; reuse it to move pending to passed/failed"),
|
|
174702
|
+
idempotencyKey: z627.string().max(200).optional().describe("Stable retry key; repeating the same operation returns the original event"),
|
|
174703
|
+
status: z627.enum(["completed", "blocked", "abandoned"]).optional().describe("Outcome status for close"),
|
|
174704
|
+
sourceRef: z627.string().max(500).optional().describe("Evidence or source reference"),
|
|
174705
|
+
evidenceRefs: z627.array(z627.string().max(500)).max(8).optional(),
|
|
174706
|
+
actor: z627.string().max(200).optional(),
|
|
174707
|
+
limit: z627.number().int().positive().max(100).optional().default(20)
|
|
174708
|
+
}
|
|
174709
|
+
},
|
|
174710
|
+
async ({ action, taskId, task, requirements, kind, content, verificationStatus, verificationId, idempotencyKey, status, sourceRef, evidenceRefs: evidenceRefs2, actor, limit: limit2 }) => {
|
|
174711
|
+
const unresolved = requireResolvedProject("manage task continuity for the current project");
|
|
174712
|
+
if (unresolved) return unresolved;
|
|
174713
|
+
const { TaskContinuityStore: TaskContinuityStore2 } = await Promise.resolve().then(() => (init_task_continuity(), task_continuity_exports));
|
|
174714
|
+
const continuity = new TaskContinuityStore2();
|
|
174715
|
+
await continuity.init(projectDir2);
|
|
174716
|
+
const effectiveActor = actor ?? currentAgentId;
|
|
174717
|
+
try {
|
|
174718
|
+
if (action === "start") {
|
|
174719
|
+
if (!task?.trim()) return { content: [{ type: "text", text: "task is required for continuity start." }], isError: true };
|
|
174720
|
+
const result2 = continuity.start({
|
|
174721
|
+
projectId: project.id,
|
|
174722
|
+
task,
|
|
174723
|
+
...taskId ? { taskId } : {},
|
|
174724
|
+
requirements,
|
|
174725
|
+
...effectiveActor ? { actor: effectiveActor } : {},
|
|
174726
|
+
...idempotencyKey ? { idempotencyKey } : {}
|
|
174727
|
+
});
|
|
174728
|
+
return { content: [{ type: "text", text: JSON.stringify({ projectId: project.id, ...result2 }, null, 2) }] };
|
|
174729
|
+
}
|
|
174730
|
+
if (action === "list") {
|
|
174731
|
+
return { content: [{ type: "text", text: JSON.stringify({ projectId: project.id, ledgers: continuity.list(project.id, limit2) }, null, 2) }] };
|
|
174732
|
+
}
|
|
174733
|
+
if (!taskId?.trim()) return { content: [{ type: "text", text: "taskId is required for this continuity action." }], isError: true };
|
|
174734
|
+
if (action === "show") {
|
|
174735
|
+
const ledger = continuity.get(project.id, taskId);
|
|
174736
|
+
if (!ledger) return { content: [{ type: "text", text: "Task continuity ledger not found." }], isError: true };
|
|
174737
|
+
return { content: [{ type: "text", text: JSON.stringify({ projectId: project.id, ledger }, null, 2) }] };
|
|
174738
|
+
}
|
|
174739
|
+
if (action === "record") {
|
|
174740
|
+
if (!kind || !content?.trim()) {
|
|
174741
|
+
return { content: [{ type: "text", text: "record requires kind and content." }], isError: true };
|
|
174742
|
+
}
|
|
174743
|
+
const result2 = continuity.record({
|
|
174744
|
+
projectId: project.id,
|
|
174745
|
+
taskId,
|
|
174746
|
+
kind,
|
|
174747
|
+
content,
|
|
174748
|
+
...verificationStatus ? { verificationStatus } : {},
|
|
174749
|
+
...sourceRef ? { sourceRef } : {},
|
|
174750
|
+
...evidenceRefs2 ? { evidenceRefs: evidenceRefs2 } : {},
|
|
174751
|
+
...effectiveActor ? { actor: effectiveActor } : {},
|
|
174752
|
+
...verificationId ? { verificationId } : {},
|
|
174753
|
+
...idempotencyKey ? { idempotencyKey } : {}
|
|
174754
|
+
});
|
|
174755
|
+
return { content: [{ type: "text", text: JSON.stringify({ projectId: project.id, ...result2 }, null, 2) }] };
|
|
174756
|
+
}
|
|
174757
|
+
if (!status || !content?.trim()) {
|
|
174758
|
+
return { content: [{ type: "text", text: "close requires status and content." }], isError: true };
|
|
174759
|
+
}
|
|
174760
|
+
const result = continuity.close({
|
|
174761
|
+
projectId: project.id,
|
|
174762
|
+
taskId,
|
|
174763
|
+
status,
|
|
174764
|
+
content,
|
|
174765
|
+
...sourceRef ? { sourceRef } : {},
|
|
174766
|
+
...evidenceRefs2 ? { evidenceRefs: evidenceRefs2 } : {},
|
|
174767
|
+
...effectiveActor ? { actor: effectiveActor } : {},
|
|
174768
|
+
...idempotencyKey ? { idempotencyKey } : {}
|
|
174769
|
+
});
|
|
174770
|
+
return { content: [{ type: "text", text: JSON.stringify({ projectId: project.id, ...result }, null, 2) }] };
|
|
174771
|
+
} catch (error) {
|
|
174772
|
+
return { content: [{ type: "text", text: error instanceof Error ? error.message : String(error) }], isError: true };
|
|
174773
|
+
}
|
|
174774
|
+
}
|
|
174775
|
+
);
|
|
174105
174776
|
if (teamFeaturesEnabled) {
|
|
174106
174777
|
const { initTeamStore: initTeamStore2 } = await Promise.resolve().then(() => (init_team_store(), team_store_exports));
|
|
174107
174778
|
initTeamStoreForProject = initTeamStore2;
|
|
@@ -175129,7 +175800,9 @@ fi
|
|
|
175129
175800
|
graphManager,
|
|
175130
175801
|
projectId: project.id,
|
|
175131
175802
|
deferredInit,
|
|
175803
|
+
activateProjectRuntime,
|
|
175132
175804
|
switchProject,
|
|
175805
|
+
getProjectDataDir: () => projectDir2,
|
|
175133
175806
|
isExplicitlyBound: () => projectBinding.isExplicit(),
|
|
175134
175807
|
getRequestContext,
|
|
175135
175808
|
handleTransportClose
|
|
@@ -175480,7 +176153,10 @@ var init_mcp_root_path = __esm({
|
|
|
175480
176153
|
// src/server/modern-mcp-bridge.ts
|
|
175481
176154
|
var modern_mcp_bridge_exports = {};
|
|
175482
176155
|
__export(modern_mcp_bridge_exports, {
|
|
175483
|
-
|
|
176156
|
+
ModernMcpRuntimePool: () => ModernMcpRuntimePool,
|
|
176157
|
+
createModernMcpBridge: () => createModernMcpBridge,
|
|
176158
|
+
createModernMcpRuntime: () => createModernMcpRuntime,
|
|
176159
|
+
withBusinessRuntimeQueue: () => withBusinessRuntimeQueue
|
|
175484
176160
|
});
|
|
175485
176161
|
import {
|
|
175486
176162
|
fromJsonSchema,
|
|
@@ -175488,7 +176164,12 @@ import {
|
|
|
175488
176164
|
} from "@modelcontextprotocol/server";
|
|
175489
176165
|
import { Client as LegacyClient } from "@modelcontextprotocol/sdk/client/index.js";
|
|
175490
176166
|
import { InMemoryTransport as LegacyInMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
|
|
175491
|
-
|
|
176167
|
+
function withBusinessRuntimeQueue(work) {
|
|
176168
|
+
const result = businessRuntimeQueue.then(work);
|
|
176169
|
+
businessRuntimeQueue = result.catch(() => void 0);
|
|
176170
|
+
return result;
|
|
176171
|
+
}
|
|
176172
|
+
async function createModernMcpRuntime(options) {
|
|
175492
176173
|
const { createMemorixServer: createMemorixServer2 } = await Promise.resolve().then(() => (init_server2(), server_exports2));
|
|
175493
176174
|
const legacy = await createMemorixServer2(
|
|
175494
176175
|
options.projectRoot,
|
|
@@ -175509,46 +176190,135 @@ async function createModernMcpBridge(options) {
|
|
|
175509
176190
|
await legacy.server.connect(serverTransport);
|
|
175510
176191
|
await legacyClient.connect(clientTransport);
|
|
175511
176192
|
const listed = await legacyClient.listTools();
|
|
175512
|
-
const
|
|
175513
|
-
|
|
175514
|
-
|
|
175515
|
-
|
|
175516
|
-
|
|
175517
|
-
...tool.title ? { title: tool.title } : {},
|
|
175518
|
-
...tool.description ? { description: tool.description } : {},
|
|
175519
|
-
inputSchema: fromJsonSchema(tool.inputSchema)
|
|
175520
|
-
},
|
|
175521
|
-
async (args) => await legacyClient.callTool({
|
|
175522
|
-
name: tool.name,
|
|
175523
|
-
arguments: args
|
|
175524
|
-
})
|
|
175525
|
-
);
|
|
175526
|
-
}
|
|
175527
|
-
const bridge = modern;
|
|
175528
|
-
bridge.memorix = {
|
|
176193
|
+
const callTool = (name, args) => withBusinessRuntimeQueue(async () => {
|
|
176194
|
+
await legacy.activateProjectRuntime();
|
|
176195
|
+
return await legacyClient.callTool({ name, arguments: args });
|
|
176196
|
+
});
|
|
176197
|
+
const lifecycle = {
|
|
175529
176198
|
projectId: legacy.projectId,
|
|
175530
176199
|
deferredInit: legacy.deferredInit,
|
|
176200
|
+
activateProjectRuntime: legacy.activateProjectRuntime,
|
|
175531
176201
|
switchProject: legacy.switchProject,
|
|
176202
|
+
getProjectDataDir: legacy.getProjectDataDir,
|
|
175532
176203
|
isExplicitlyBound: legacy.isExplicitlyBound,
|
|
175533
176204
|
handleTransportClose: legacy.handleTransportClose
|
|
175534
176205
|
};
|
|
175535
176206
|
let closed = false;
|
|
175536
|
-
|
|
175537
|
-
|
|
176207
|
+
return {
|
|
176208
|
+
projectId: legacy.projectId,
|
|
176209
|
+
getProjectDataDir: legacy.getProjectDataDir,
|
|
176210
|
+
createBridge: () => {
|
|
176211
|
+
const requestServer = new ModernMcpServer(getMcpServerInfo());
|
|
176212
|
+
for (const tool of listed.tools) {
|
|
176213
|
+
requestServer.registerTool(
|
|
176214
|
+
tool.name,
|
|
176215
|
+
{
|
|
176216
|
+
...tool.title ? { title: tool.title } : {},
|
|
176217
|
+
...tool.description ? { description: tool.description } : {},
|
|
176218
|
+
inputSchema: fromJsonSchema(tool.inputSchema)
|
|
176219
|
+
},
|
|
176220
|
+
async (args) => await callTool(tool.name, args)
|
|
176221
|
+
);
|
|
176222
|
+
}
|
|
176223
|
+
requestServer.memorix = lifecycle;
|
|
176224
|
+
return requestServer;
|
|
176225
|
+
},
|
|
176226
|
+
close: async () => {
|
|
176227
|
+
if (closed) return;
|
|
176228
|
+
closed = true;
|
|
176229
|
+
await legacyClient.close().catch(() => void 0);
|
|
176230
|
+
await legacy.server.close().catch(() => void 0);
|
|
176231
|
+
legacy.handleTransportClose();
|
|
176232
|
+
}
|
|
176233
|
+
};
|
|
176234
|
+
}
|
|
176235
|
+
async function createModernMcpBridge(options) {
|
|
176236
|
+
const runtime = await createModernMcpRuntime(options);
|
|
176237
|
+
const bridge = runtime.createBridge();
|
|
176238
|
+
const close = bridge.close.bind(bridge);
|
|
176239
|
+
let closed = false;
|
|
176240
|
+
bridge.close = async () => {
|
|
175538
176241
|
if (closed) return;
|
|
175539
176242
|
closed = true;
|
|
175540
|
-
await
|
|
175541
|
-
await
|
|
175542
|
-
await legacy.server.close().catch(() => void 0);
|
|
175543
|
-
legacy.handleTransportClose();
|
|
176243
|
+
await close();
|
|
176244
|
+
await runtime.close();
|
|
175544
176245
|
};
|
|
175545
176246
|
return bridge;
|
|
175546
176247
|
}
|
|
176248
|
+
var businessRuntimeQueue, ModernMcpRuntimePool;
|
|
175547
176249
|
var init_modern_mcp_bridge = __esm({
|
|
175548
176250
|
"src/server/modern-mcp-bridge.ts"() {
|
|
175549
176251
|
"use strict";
|
|
175550
176252
|
init_esm_shims();
|
|
175551
176253
|
init_mcp_discovery();
|
|
176254
|
+
businessRuntimeQueue = Promise.resolve();
|
|
176255
|
+
ModernMcpRuntimePool = class {
|
|
176256
|
+
constructor(maxEntries = 32) {
|
|
176257
|
+
this.maxEntries = maxEntries;
|
|
176258
|
+
}
|
|
176259
|
+
maxEntries;
|
|
176260
|
+
entries = /* @__PURE__ */ new Map();
|
|
176261
|
+
pending = /* @__PURE__ */ new Map();
|
|
176262
|
+
async createBridge(key, create2) {
|
|
176263
|
+
let entry = this.entries.get(key);
|
|
176264
|
+
if (!entry) {
|
|
176265
|
+
let pending = this.pending.get(key);
|
|
176266
|
+
if (!pending) {
|
|
176267
|
+
pending = create2().then((runtime) => {
|
|
176268
|
+
const created = { runtime, refs: 0, lastUsedAt: Date.now() };
|
|
176269
|
+
this.entries.set(key, created);
|
|
176270
|
+
return created;
|
|
176271
|
+
});
|
|
176272
|
+
this.pending.set(key, pending);
|
|
176273
|
+
}
|
|
176274
|
+
try {
|
|
176275
|
+
entry = await pending;
|
|
176276
|
+
} finally {
|
|
176277
|
+
this.pending.delete(key);
|
|
176278
|
+
}
|
|
176279
|
+
}
|
|
176280
|
+
entry.refs++;
|
|
176281
|
+
entry.lastUsedAt = Date.now();
|
|
176282
|
+
const bridge = entry.runtime.createBridge();
|
|
176283
|
+
const close = bridge.close.bind(bridge);
|
|
176284
|
+
let released = false;
|
|
176285
|
+
bridge.close = async () => {
|
|
176286
|
+
try {
|
|
176287
|
+
await close();
|
|
176288
|
+
} finally {
|
|
176289
|
+
if (!released) {
|
|
176290
|
+
released = true;
|
|
176291
|
+
entry.refs = Math.max(0, entry.refs - 1);
|
|
176292
|
+
entry.lastUsedAt = Date.now();
|
|
176293
|
+
}
|
|
176294
|
+
}
|
|
176295
|
+
};
|
|
176296
|
+
return bridge;
|
|
176297
|
+
}
|
|
176298
|
+
async evictIdle() {
|
|
176299
|
+
let closed = 0;
|
|
176300
|
+
const idle = [...this.entries.entries()].filter(([, entry]) => entry.refs === 0).sort(([, left], [, right]) => left.lastUsedAt - right.lastUsedAt);
|
|
176301
|
+
for (const [key, entry] of idle) {
|
|
176302
|
+
if (this.entries.size <= this.maxEntries || entry.refs > 0) continue;
|
|
176303
|
+
this.entries.delete(key);
|
|
176304
|
+
await entry.runtime.close();
|
|
176305
|
+
closed++;
|
|
176306
|
+
}
|
|
176307
|
+
return closed;
|
|
176308
|
+
}
|
|
176309
|
+
async close() {
|
|
176310
|
+
const entries = [...this.entries.values()];
|
|
176311
|
+
this.entries.clear();
|
|
176312
|
+
await Promise.all(entries.map((entry) => entry.runtime.close().catch(() => void 0)));
|
|
176313
|
+
}
|
|
176314
|
+
stats() {
|
|
176315
|
+
return {
|
|
176316
|
+
entries: this.entries.size,
|
|
176317
|
+
activeRefs: [...this.entries.values()].reduce((sum, entry) => sum + entry.refs, 0),
|
|
176318
|
+
pending: this.pending.size
|
|
176319
|
+
};
|
|
176320
|
+
}
|
|
176321
|
+
};
|
|
175552
176322
|
}
|
|
175553
176323
|
});
|
|
175554
176324
|
|
|
@@ -175660,7 +176430,7 @@ var init_serve_shared = __esm({
|
|
|
175660
176430
|
|
|
175661
176431
|
// src/cli/version.ts
|
|
175662
176432
|
function getCliVersion() {
|
|
175663
|
-
return true ? "1.9.
|
|
176433
|
+
return true ? "1.9.6" : pkg.version;
|
|
175664
176434
|
}
|
|
175665
176435
|
var init_version3 = __esm({
|
|
175666
176436
|
"src/cli/version.ts"() {
|