memorix 1.9.1 → 1.9.3
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 +22 -0
- package/README.md +17 -4
- package/README.zh-CN.md +8 -4
- package/dist/cli/index.js +448 -243
- package/dist/index.js +302 -165
- package/dist/maintenance-runner.js +194 -98
- package/dist/media-audio-runner.js +196 -100
- package/dist/media-video-runner.js +194 -98
- package/dist/memcode-runtime/CHANGELOG.md +22 -0
- package/dist/sdk.js +301 -164
- package/dist/vector-backfill-runner.js +194 -98
- package/docs/AGENT_OPERATOR_PLAYBOOK.md +15 -0
- package/docs/ARCHITECTURE.md +23 -0
- package/docs/DEVELOPMENT.md +1 -1
- package/docs/INTEGRATIONS.md +4 -0
- package/docs/PERFORMANCE.md +50 -0
- package/docs/README.md +1 -1
- package/docs/SETUP.md +5 -0
- package/package.json +1 -2
- 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/commands/doctor.ts +78 -17
- package/src/cli/commands/memory.ts +2 -1
- package/src/cli/default-mode.ts +15 -0
- package/src/cli/index.ts +10 -1
- package/src/codegraph/lite-provider.ts +10 -1
- package/src/dashboard/maintenance.ts +11 -2
- package/src/memory/consolidation.ts +15 -6
- package/src/store/mini-skill-store.ts +31 -22
- package/src/store/obs-store.ts +46 -30
- package/src/store/session-store.ts +35 -21
- package/src/store/sqlite-db.ts +16 -7
- package/src/store/sqlite-reliability.ts +87 -0
- package/src/store/sqlite-store.ts +4 -1
- package/assets/star-history-dark.svg +0 -30
- package/assets/star-history-light.svg +0 -30
- package/assets/star-history.json +0 -712
package/dist/index.js
CHANGED
|
@@ -452,70 +452,79 @@ function getDatabase(dataDir) {
|
|
|
452
452
|
loadBetterSqlite3();
|
|
453
453
|
fs.mkdirSync(dataDir, { recursive: true });
|
|
454
454
|
const dbPath = path3.join(dataDir, "memorix.db");
|
|
455
|
-
|
|
456
|
-
db2.pragma("journal_mode = WAL");
|
|
457
|
-
db2.pragma("busy_timeout = 5000");
|
|
458
|
-
db2.pragma("foreign_keys = ON");
|
|
459
|
-
db2.exec(CREATE_OBSERVATIONS_TABLE);
|
|
460
|
-
db2.exec(CREATE_MINI_SKILLS_TABLE);
|
|
461
|
-
db2.exec(CREATE_SESSIONS_TABLE);
|
|
462
|
-
db2.exec(CREATE_META_TABLE);
|
|
463
|
-
db2.exec(CREATE_TEAM_AGENTS_TABLE);
|
|
464
|
-
db2.exec(CREATE_TEAM_TASKS_TABLE);
|
|
465
|
-
db2.exec(CREATE_TEAM_TASK_DEPS_TABLE);
|
|
466
|
-
db2.exec(CREATE_TEAM_MESSAGES_TABLE);
|
|
467
|
-
db2.exec(CREATE_TEAM_LOCKS_TABLE);
|
|
468
|
-
db2.exec(CREATE_TEAM_ROLES_TABLE);
|
|
469
|
-
db2.exec(CREATE_GRAPH_ENTITIES_TABLE);
|
|
470
|
-
db2.exec(CREATE_GRAPH_RELATIONS_TABLE);
|
|
471
|
-
db2.exec(CREATE_CHAT_TRANSCRIPT_TABLE);
|
|
472
|
-
db2.exec(CREATE_CODE_FILES_TABLE);
|
|
473
|
-
db2.exec(CREATE_CODE_SYMBOLS_TABLE);
|
|
474
|
-
db2.exec(CREATE_CODE_EDGES_TABLE);
|
|
475
|
-
db2.exec(CREATE_OBSERVATION_CODE_REFS_TABLE);
|
|
476
|
-
db2.exec(CREATE_MAINTENANCE_JOBS_TABLE);
|
|
477
|
-
db2.exec(CREATE_MAINTENANCE_TARGETS_TABLE);
|
|
478
|
-
db2.exec(CREATE_COMPACTION_CHECKPOINTS_TABLE);
|
|
455
|
+
let db2;
|
|
479
456
|
try {
|
|
480
|
-
db2
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
db2.exec(
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
db2.exec(
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
db2.exec(
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
db2.exec(
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
db2.exec(
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
457
|
+
db2 = createDatabase(dbPath);
|
|
458
|
+
db2.pragma("busy_timeout = 5000");
|
|
459
|
+
db2.pragma("journal_mode = WAL");
|
|
460
|
+
db2.pragma("foreign_keys = ON");
|
|
461
|
+
db2.exec(CREATE_OBSERVATIONS_TABLE);
|
|
462
|
+
db2.exec(CREATE_MINI_SKILLS_TABLE);
|
|
463
|
+
db2.exec(CREATE_SESSIONS_TABLE);
|
|
464
|
+
db2.exec(CREATE_META_TABLE);
|
|
465
|
+
db2.exec(CREATE_TEAM_AGENTS_TABLE);
|
|
466
|
+
db2.exec(CREATE_TEAM_TASKS_TABLE);
|
|
467
|
+
db2.exec(CREATE_TEAM_TASK_DEPS_TABLE);
|
|
468
|
+
db2.exec(CREATE_TEAM_MESSAGES_TABLE);
|
|
469
|
+
db2.exec(CREATE_TEAM_LOCKS_TABLE);
|
|
470
|
+
db2.exec(CREATE_TEAM_ROLES_TABLE);
|
|
471
|
+
db2.exec(CREATE_GRAPH_ENTITIES_TABLE);
|
|
472
|
+
db2.exec(CREATE_GRAPH_RELATIONS_TABLE);
|
|
473
|
+
db2.exec(CREATE_CHAT_TRANSCRIPT_TABLE);
|
|
474
|
+
db2.exec(CREATE_CODE_FILES_TABLE);
|
|
475
|
+
db2.exec(CREATE_CODE_SYMBOLS_TABLE);
|
|
476
|
+
db2.exec(CREATE_CODE_EDGES_TABLE);
|
|
477
|
+
db2.exec(CREATE_OBSERVATION_CODE_REFS_TABLE);
|
|
478
|
+
db2.exec(CREATE_MAINTENANCE_JOBS_TABLE);
|
|
479
|
+
db2.exec(CREATE_MAINTENANCE_TARGETS_TABLE);
|
|
480
|
+
db2.exec(CREATE_COMPACTION_CHECKPOINTS_TABLE);
|
|
481
|
+
try {
|
|
482
|
+
db2.exec(`ALTER TABLE mini_skills ADD COLUMN sourceSnapshot TEXT NOT NULL DEFAULT ''`);
|
|
483
|
+
} catch {
|
|
484
|
+
}
|
|
485
|
+
try {
|
|
486
|
+
db2.exec(`ALTER TABLE mini_skills ADD COLUMN updatedAt TEXT`);
|
|
487
|
+
} catch {
|
|
488
|
+
}
|
|
489
|
+
try {
|
|
490
|
+
db2.exec(`ALTER TABLE observations ADD COLUMN createdByAgentId TEXT`);
|
|
491
|
+
} catch {
|
|
492
|
+
}
|
|
493
|
+
try {
|
|
494
|
+
db2.exec(`ALTER TABLE observations ADD COLUMN writeGeneration INTEGER DEFAULT 0`);
|
|
495
|
+
} catch {
|
|
496
|
+
}
|
|
497
|
+
try {
|
|
498
|
+
db2.exec(`ALTER TABLE team_tasks ADD COLUMN required_role TEXT`);
|
|
499
|
+
} catch {
|
|
500
|
+
}
|
|
501
|
+
try {
|
|
502
|
+
db2.exec(`ALTER TABLE team_tasks ADD COLUMN preferred_role TEXT`);
|
|
503
|
+
} catch {
|
|
504
|
+
}
|
|
505
|
+
try {
|
|
506
|
+
db2.exec(`ALTER TABLE team_messages ADD COLUMN to_role TEXT`);
|
|
507
|
+
} catch {
|
|
508
|
+
}
|
|
509
|
+
try {
|
|
510
|
+
db2.exec(`ALTER TABLE team_messages ADD COLUMN handoff_status TEXT`);
|
|
511
|
+
} catch {
|
|
512
|
+
}
|
|
513
|
+
applySchemaMigrations(db2);
|
|
514
|
+
db2.exec(CREATE_INDEXES);
|
|
515
|
+
initializeObservationLexicalIndex(db2);
|
|
516
|
+
db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('storage_generation', '0')`).run();
|
|
517
|
+
db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('next_id', '1')`).run();
|
|
518
|
+
db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('mini_skills_generation', '0')`).run();
|
|
519
|
+
_dbCache.set(normalized, db2);
|
|
520
|
+
return db2;
|
|
521
|
+
} catch (error) {
|
|
522
|
+
try {
|
|
523
|
+
db2?.close();
|
|
524
|
+
} catch {
|
|
525
|
+
}
|
|
526
|
+
throw error;
|
|
510
527
|
}
|
|
511
|
-
applySchemaMigrations(db2);
|
|
512
|
-
db2.exec(CREATE_INDEXES);
|
|
513
|
-
initializeObservationLexicalIndex(db2);
|
|
514
|
-
db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('storage_generation', '0')`).run();
|
|
515
|
-
db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('next_id', '1')`).run();
|
|
516
|
-
db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('mini_skills_generation', '0')`).run();
|
|
517
|
-
_dbCache.set(normalized, db2);
|
|
518
|
-
return db2;
|
|
519
528
|
}
|
|
520
529
|
function closeAllDatabases() {
|
|
521
530
|
for (const [key, db2] of _dbCache) {
|
|
@@ -2329,6 +2338,74 @@ var init_types = __esm({
|
|
|
2329
2338
|
}
|
|
2330
2339
|
});
|
|
2331
2340
|
|
|
2341
|
+
// src/store/sqlite-reliability.ts
|
|
2342
|
+
function isTransientSqliteError(error) {
|
|
2343
|
+
const code = error?.code;
|
|
2344
|
+
if (typeof code === "string") {
|
|
2345
|
+
return /^SQLITE_BUSY(?:_|$)/i.test(code);
|
|
2346
|
+
}
|
|
2347
|
+
return error instanceof Error && /\bdatabase is locked\b|\bdatabase is busy\b/i.test(error.message);
|
|
2348
|
+
}
|
|
2349
|
+
function isSqliteUnavailableError(error) {
|
|
2350
|
+
return error instanceof SqliteUnavailableError || error instanceof Error && /SQLite is not available|better-sqlite3.*failed|node:sqlite.*failed|bun:sqlite.*failed/i.test(error.message);
|
|
2351
|
+
}
|
|
2352
|
+
function degradedReadError(storeName) {
|
|
2353
|
+
return new Error(`[memorix] Cannot read ${storeName}: SQLite backend unavailable (memory is not loaded)`);
|
|
2354
|
+
}
|
|
2355
|
+
function degradedWriteError(storeName) {
|
|
2356
|
+
return new Error(`[memorix] Cannot write ${storeName}: SQLite backend unavailable (degraded mode; read-only)`);
|
|
2357
|
+
}
|
|
2358
|
+
function formatSqliteFailure(error) {
|
|
2359
|
+
return error instanceof Error && error.message ? error.message : String(error);
|
|
2360
|
+
}
|
|
2361
|
+
function delay(ms) {
|
|
2362
|
+
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
2363
|
+
}
|
|
2364
|
+
async function retrySqliteBusy(operation, label) {
|
|
2365
|
+
for (let attempt = 0; ; attempt++) {
|
|
2366
|
+
try {
|
|
2367
|
+
return await operation();
|
|
2368
|
+
} catch (error) {
|
|
2369
|
+
if (!isTransientSqliteError(error) || attempt >= SQLITE_BUSY_RETRY_DELAYS_MS.length) throw error;
|
|
2370
|
+
const waitMs = SQLITE_BUSY_RETRY_DELAYS_MS[attempt];
|
|
2371
|
+
console.error(
|
|
2372
|
+
`[memorix] ${label} SQLite busy (attempt ${attempt + 1}/${SQLITE_BUSY_RETRY_DELAYS_MS.length + 1}), retrying in ${waitMs}ms`
|
|
2373
|
+
);
|
|
2374
|
+
await delay(waitMs);
|
|
2375
|
+
}
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
async function initializeSqliteStore(factory, dataDir, label) {
|
|
2379
|
+
try {
|
|
2380
|
+
loadBetterSqlite3();
|
|
2381
|
+
} catch (error) {
|
|
2382
|
+
throw new SqliteUnavailableError(error);
|
|
2383
|
+
}
|
|
2384
|
+
return retrySqliteBusy(async () => {
|
|
2385
|
+
const store = factory();
|
|
2386
|
+
await store.init(dataDir);
|
|
2387
|
+
return store;
|
|
2388
|
+
}, label);
|
|
2389
|
+
}
|
|
2390
|
+
var SQLITE_BUSY_RETRY_DELAYS_MS, SqliteUnavailableError;
|
|
2391
|
+
var init_sqlite_reliability = __esm({
|
|
2392
|
+
"src/store/sqlite-reliability.ts"() {
|
|
2393
|
+
"use strict";
|
|
2394
|
+
init_esm_shims();
|
|
2395
|
+
init_sqlite_db();
|
|
2396
|
+
SQLITE_BUSY_RETRY_DELAYS_MS = [50, 150, 400, 1e3, 2500];
|
|
2397
|
+
SqliteUnavailableError = class extends Error {
|
|
2398
|
+
code = "MEMORIX_SQLITE_UNAVAILABLE";
|
|
2399
|
+
constructor(cause) {
|
|
2400
|
+
super(
|
|
2401
|
+
cause instanceof Error && cause.message ? cause.message : "[memorix] SQLite is unavailable (install a supported SQLite runtime)"
|
|
2402
|
+
);
|
|
2403
|
+
this.name = "SqliteUnavailableError";
|
|
2404
|
+
}
|
|
2405
|
+
};
|
|
2406
|
+
}
|
|
2407
|
+
});
|
|
2408
|
+
|
|
2332
2409
|
// src/store/mini-skill-store.ts
|
|
2333
2410
|
var mini_skill_store_exports = {};
|
|
2334
2411
|
__export(mini_skill_store_exports, {
|
|
@@ -2400,16 +2477,18 @@ async function initMiniSkillStore(dataDir) {
|
|
|
2400
2477
|
if (_store && _storeDataDir === dataDir) return _store;
|
|
2401
2478
|
_store = null;
|
|
2402
2479
|
_storeDataDir = null;
|
|
2480
|
+
let degradedReason = "SQLite runtime unavailable";
|
|
2403
2481
|
try {
|
|
2404
|
-
const store2 = new MiniSkillSqliteStore();
|
|
2405
|
-
await store2.init(dataDir);
|
|
2482
|
+
const store2 = await initializeSqliteStore(() => new MiniSkillSqliteStore(), dataDir, "Mini-skill store");
|
|
2406
2483
|
_store = store2;
|
|
2407
2484
|
_storeDataDir = dataDir;
|
|
2408
2485
|
return store2;
|
|
2409
2486
|
} catch (err) {
|
|
2410
|
-
|
|
2487
|
+
if (!isSqliteUnavailableError(err)) throw err;
|
|
2488
|
+
degradedReason = err instanceof Error ? err.message : String(err);
|
|
2489
|
+
console.error(`[memorix] MiniSkillSqliteStore unavailable, running in degraded read-only mode: ${degradedReason}`);
|
|
2411
2490
|
}
|
|
2412
|
-
const store = new MiniSkillGracefulDegrade();
|
|
2491
|
+
const store = new MiniSkillGracefulDegrade(degradedReason);
|
|
2413
2492
|
await store.init(dataDir);
|
|
2414
2493
|
_store = store;
|
|
2415
2494
|
_storeDataDir = dataDir;
|
|
@@ -2421,6 +2500,7 @@ var init_mini_skill_store = __esm({
|
|
|
2421
2500
|
"use strict";
|
|
2422
2501
|
init_esm_shims();
|
|
2423
2502
|
init_sqlite_db();
|
|
2503
|
+
init_sqlite_reliability();
|
|
2424
2504
|
MiniSkillSqliteStore = class {
|
|
2425
2505
|
db = null;
|
|
2426
2506
|
dataDir = "";
|
|
@@ -2529,7 +2609,7 @@ var init_mini_skill_store = __esm({
|
|
|
2529
2609
|
* SQLite serializes write transactions, so concurrent calls are safely sequenced.
|
|
2530
2610
|
*/
|
|
2531
2611
|
async atomicInsertWithId(skillWithoutId) {
|
|
2532
|
-
|
|
2612
|
+
return retrySqliteBusy(async () => this.db.transaction(() => {
|
|
2533
2613
|
const row = this.stmtGetMeta.get("mini_skills_next_id");
|
|
2534
2614
|
const nextId2 = row ? parseInt(row.value, 10) : 1;
|
|
2535
2615
|
const skill2 = { ...skillWithoutId, id: nextId2 };
|
|
@@ -2538,8 +2618,7 @@ var init_mini_skill_store = __esm({
|
|
|
2538
2618
|
this.stmtBumpGeneration.run();
|
|
2539
2619
|
this.knownGeneration = this.readGeneration();
|
|
2540
2620
|
return skill2;
|
|
2541
|
-
})();
|
|
2542
|
-
return result;
|
|
2621
|
+
})(), "Mini-skill promotion");
|
|
2543
2622
|
}
|
|
2544
2623
|
// ── Freshness ────────────────────────────────────────────────────
|
|
2545
2624
|
async ensureFresh() {
|
|
@@ -2558,10 +2637,17 @@ var init_mini_skill_store = __esm({
|
|
|
2558
2637
|
}
|
|
2559
2638
|
};
|
|
2560
2639
|
MiniSkillGracefulDegrade = class {
|
|
2640
|
+
constructor(reason = "SQLite runtime unavailable") {
|
|
2641
|
+
this.reason = reason;
|
|
2642
|
+
}
|
|
2643
|
+
reason;
|
|
2561
2644
|
warned = false;
|
|
2645
|
+
unavailableRead() {
|
|
2646
|
+
return degradedReadError("mini-skills");
|
|
2647
|
+
}
|
|
2562
2648
|
warn() {
|
|
2563
2649
|
if (!this.warned) {
|
|
2564
|
-
console.error("[memorix] MiniSkillStore: SQLite unavailable \u2014 mini-skills
|
|
2650
|
+
console.error("[memorix] MiniSkillStore: SQLite unavailable \u2014 mini-skills cannot be read or written. Install a supported SQLite runtime.");
|
|
2565
2651
|
this.warned = true;
|
|
2566
2652
|
}
|
|
2567
2653
|
}
|
|
@@ -2569,28 +2655,33 @@ var init_mini_skill_store = __esm({
|
|
|
2569
2655
|
this.warn();
|
|
2570
2656
|
}
|
|
2571
2657
|
async loadAll() {
|
|
2572
|
-
|
|
2658
|
+
throw this.unavailableRead();
|
|
2573
2659
|
}
|
|
2574
2660
|
async loadByProject(_projectId) {
|
|
2575
|
-
|
|
2661
|
+
throw this.unavailableRead();
|
|
2576
2662
|
}
|
|
2577
2663
|
async loadIdCounter() {
|
|
2578
|
-
|
|
2664
|
+
throw this.unavailableRead();
|
|
2579
2665
|
}
|
|
2580
2666
|
async insert(_skill) {
|
|
2581
2667
|
this.warn();
|
|
2668
|
+
throw degradedWriteError("mini-skills");
|
|
2582
2669
|
}
|
|
2583
2670
|
async update(_skill) {
|
|
2584
2671
|
this.warn();
|
|
2672
|
+
throw degradedWriteError("mini-skills");
|
|
2585
2673
|
}
|
|
2586
2674
|
async remove(_id) {
|
|
2587
2675
|
this.warn();
|
|
2676
|
+
throw degradedWriteError("mini-skills");
|
|
2588
2677
|
}
|
|
2589
2678
|
async saveIdCounter(_nextId) {
|
|
2679
|
+
this.warn();
|
|
2680
|
+
throw degradedWriteError("mini-skills");
|
|
2590
2681
|
}
|
|
2591
2682
|
async atomicInsertWithId(skillWithoutId) {
|
|
2592
2683
|
this.warn();
|
|
2593
|
-
|
|
2684
|
+
throw degradedWriteError("mini-skills");
|
|
2594
2685
|
}
|
|
2595
2686
|
async ensureFresh() {
|
|
2596
2687
|
return false;
|
|
@@ -2601,6 +2692,9 @@ var init_mini_skill_store = __esm({
|
|
|
2601
2692
|
getBackendName() {
|
|
2602
2693
|
return "degraded";
|
|
2603
2694
|
}
|
|
2695
|
+
getBackendReason() {
|
|
2696
|
+
return this.reason;
|
|
2697
|
+
}
|
|
2604
2698
|
};
|
|
2605
2699
|
_store = null;
|
|
2606
2700
|
_storeDataDir = null;
|
|
@@ -4855,10 +4949,10 @@ async function fetchWithRetry(url, apiKey, body, options = {}, attempt = 0, nati
|
|
|
4855
4949
|
);
|
|
4856
4950
|
}
|
|
4857
4951
|
if (options.retry !== false && (response.status === 429 || response.status >= 500) && attempt < MAX_RETRIES2) {
|
|
4858
|
-
const
|
|
4952
|
+
const delay3 = BASE_DELAY_MS * Math.pow(2, attempt);
|
|
4859
4953
|
const retryAfter = response.headers.get("retry-after");
|
|
4860
4954
|
const parsedRetryAfter = retryAfter ? parseInt(retryAfter, 10) * 1e3 : NaN;
|
|
4861
|
-
const waitMs = Number.isFinite(parsedRetryAfter) ? parsedRetryAfter :
|
|
4955
|
+
const waitMs = Number.isFinite(parsedRetryAfter) ? parsedRetryAfter : delay3;
|
|
4862
4956
|
console.error(`[memorix] Embedding API ${response.status}, retry ${attempt + 1}/${MAX_RETRIES2} in ${waitMs}ms`);
|
|
4863
4957
|
await waitForRetry(waitMs, options.signal);
|
|
4864
4958
|
return fetchWithRetry(url, apiKey, body, options, attempt + 1, nativeGemini);
|
|
@@ -6890,6 +6984,7 @@ var init_sqlite_store = __esm({
|
|
|
6890
6984
|
"use strict";
|
|
6891
6985
|
init_esm_shims();
|
|
6892
6986
|
init_sqlite_db();
|
|
6987
|
+
init_sqlite_reliability();
|
|
6893
6988
|
init_sqlite_fts();
|
|
6894
6989
|
SqliteBackend = class {
|
|
6895
6990
|
db = null;
|
|
@@ -7167,7 +7262,9 @@ var init_sqlite_store = __esm({
|
|
|
7167
7262
|
// ── Compound atomic operation ────────────────────────────────────
|
|
7168
7263
|
async atomic(fn) {
|
|
7169
7264
|
const run = this._atomicQueue.catch(() => void 0).then(async () => {
|
|
7170
|
-
|
|
7265
|
+
await retrySqliteBusy(async () => {
|
|
7266
|
+
this.db.prepare("BEGIN IMMEDIATE").run();
|
|
7267
|
+
}, "Observation atomic write");
|
|
7171
7268
|
try {
|
|
7172
7269
|
const tx = {
|
|
7173
7270
|
loadAll: async () => this.rawLoadAll(),
|
|
@@ -7266,15 +7363,15 @@ function resetObservationStore() {
|
|
|
7266
7363
|
async function createObservationStore(dataDir) {
|
|
7267
7364
|
try {
|
|
7268
7365
|
const { SqliteBackend: SqliteBackend2 } = await Promise.resolve().then(() => (init_sqlite_store(), sqlite_store_exports));
|
|
7269
|
-
|
|
7270
|
-
await store2.init(dataDir);
|
|
7271
|
-
return store2;
|
|
7366
|
+
return await initializeSqliteStore(() => new SqliteBackend2(), dataDir, "Observation store");
|
|
7272
7367
|
} catch (err) {
|
|
7273
|
-
|
|
7368
|
+
if (!isSqliteUnavailableError(err)) throw err;
|
|
7369
|
+
const reason = formatSqliteFailure(err);
|
|
7370
|
+
console.error(`[memorix] SQLite module unavailable \u2014 degraded mode (reads/writes disabled): ${reason}`);
|
|
7371
|
+
const degraded = new DegradedBackend(reason);
|
|
7372
|
+
await degraded.init(dataDir);
|
|
7373
|
+
return degraded;
|
|
7274
7374
|
}
|
|
7275
|
-
const store = new DegradedBackend();
|
|
7276
|
-
await store.init(dataDir);
|
|
7277
|
-
return store;
|
|
7278
7375
|
}
|
|
7279
7376
|
async function initObservationStore(dataDir) {
|
|
7280
7377
|
if (_store2 && _storeDataDir2 === dataDir) {
|
|
@@ -7298,36 +7395,44 @@ var init_obs_store = __esm({
|
|
|
7298
7395
|
"src/store/obs-store.ts"() {
|
|
7299
7396
|
"use strict";
|
|
7300
7397
|
init_esm_shims();
|
|
7398
|
+
init_sqlite_reliability();
|
|
7301
7399
|
_store2 = null;
|
|
7302
7400
|
_storeDataDir2 = null;
|
|
7303
7401
|
DegradedBackend = class {
|
|
7402
|
+
constructor(reason = "SQLite runtime unavailable") {
|
|
7403
|
+
this.reason = reason;
|
|
7404
|
+
}
|
|
7405
|
+
reason;
|
|
7304
7406
|
dataDir = "";
|
|
7407
|
+
unavailableRead() {
|
|
7408
|
+
return degradedReadError("observations");
|
|
7409
|
+
}
|
|
7305
7410
|
async init(dataDir) {
|
|
7306
7411
|
this.dataDir = dataDir;
|
|
7307
7412
|
}
|
|
7308
7413
|
async loadAll() {
|
|
7309
|
-
|
|
7414
|
+
throw this.unavailableRead();
|
|
7310
7415
|
}
|
|
7311
7416
|
async loadByProject(_projectId, _options) {
|
|
7312
|
-
|
|
7417
|
+
throw this.unavailableRead();
|
|
7313
7418
|
}
|
|
7314
7419
|
async countByProject(_projectId, _options) {
|
|
7315
|
-
|
|
7420
|
+
throw this.unavailableRead();
|
|
7316
7421
|
}
|
|
7317
7422
|
async getById(_id) {
|
|
7318
|
-
|
|
7423
|
+
throw this.unavailableRead();
|
|
7319
7424
|
}
|
|
7320
7425
|
async loadIdCounter() {
|
|
7321
|
-
|
|
7426
|
+
throw this.unavailableRead();
|
|
7322
7427
|
}
|
|
7323
7428
|
async countAll() {
|
|
7324
|
-
|
|
7429
|
+
throw this.unavailableRead();
|
|
7325
7430
|
}
|
|
7326
7431
|
async listProjectIds() {
|
|
7327
|
-
|
|
7432
|
+
throw this.unavailableRead();
|
|
7328
7433
|
}
|
|
7329
7434
|
async searchLexical(_options) {
|
|
7330
|
-
|
|
7435
|
+
throw this.unavailableRead();
|
|
7331
7436
|
}
|
|
7332
7437
|
hasLexicalIndex() {
|
|
7333
7438
|
return false;
|
|
@@ -7336,25 +7441,25 @@ var init_obs_store = __esm({
|
|
|
7336
7441
|
return false;
|
|
7337
7442
|
}
|
|
7338
7443
|
async insert(_obs) {
|
|
7339
|
-
throw
|
|
7444
|
+
throw degradedWriteError("observations");
|
|
7340
7445
|
}
|
|
7341
7446
|
async update(_obs) {
|
|
7342
|
-
throw
|
|
7447
|
+
throw degradedWriteError("observations");
|
|
7343
7448
|
}
|
|
7344
7449
|
async remove(_id) {
|
|
7345
|
-
throw
|
|
7450
|
+
throw degradedWriteError("observations");
|
|
7346
7451
|
}
|
|
7347
7452
|
async bulkReplace(_obs) {
|
|
7348
|
-
throw
|
|
7453
|
+
throw degradedWriteError("observations");
|
|
7349
7454
|
}
|
|
7350
7455
|
async bulkRemoveByIds(_ids) {
|
|
7351
|
-
throw
|
|
7456
|
+
throw degradedWriteError("observations");
|
|
7352
7457
|
}
|
|
7353
7458
|
async saveIdCounter(_nextId) {
|
|
7354
|
-
throw
|
|
7459
|
+
throw degradedWriteError("observations");
|
|
7355
7460
|
}
|
|
7356
7461
|
async atomic(_fn) {
|
|
7357
|
-
throw
|
|
7462
|
+
throw degradedWriteError("observations");
|
|
7358
7463
|
}
|
|
7359
7464
|
async ensureFresh() {
|
|
7360
7465
|
return false;
|
|
@@ -7367,6 +7472,9 @@ var init_obs_store = __esm({
|
|
|
7367
7472
|
getBackendName() {
|
|
7368
7473
|
return "degraded";
|
|
7369
7474
|
}
|
|
7475
|
+
getBackendReason() {
|
|
7476
|
+
return this.reason;
|
|
7477
|
+
}
|
|
7370
7478
|
};
|
|
7371
7479
|
}
|
|
7372
7480
|
});
|
|
@@ -10882,7 +10990,8 @@ function clampCursor(afterId) {
|
|
|
10882
10990
|
}
|
|
10883
10991
|
async function loadConsolidationPage(projectId, options) {
|
|
10884
10992
|
const limit2 = clampBatchSize(options.limit);
|
|
10885
|
-
const
|
|
10993
|
+
const store = options.store ?? getObservationStore();
|
|
10994
|
+
const page = await store.loadByProject(projectId, {
|
|
10886
10995
|
status: "active",
|
|
10887
10996
|
afterId: clampCursor(options.afterId),
|
|
10888
10997
|
limit: limit2 + 1
|
|
@@ -10942,7 +11051,7 @@ async function findConsolidationCandidates(_projectDir, projectId, opts) {
|
|
|
10942
11051
|
return findClusters(page.observations, threshold);
|
|
10943
11052
|
}
|
|
10944
11053
|
async function executeConsolidation(_projectDir, projectId, opts) {
|
|
10945
|
-
const store = getObservationStore();
|
|
11054
|
+
const store = opts?.store ?? getObservationStore();
|
|
10946
11055
|
const page = await loadConsolidationPage(projectId, opts ?? {});
|
|
10947
11056
|
const clusters = findClusters(page.observations, opts?.threshold ?? DEFAULT_SIMILARITY_THRESHOLD);
|
|
10948
11057
|
if (clusters.length === 0) {
|
|
@@ -56962,10 +57071,10 @@ var require_retry3 = __commonJS({
|
|
|
56962
57071
|
if (!await shouldRetryFn(err)) {
|
|
56963
57072
|
return { shouldRetry: false, config: err.config };
|
|
56964
57073
|
}
|
|
56965
|
-
const
|
|
57074
|
+
const delay3 = getNextRetryDelay(config);
|
|
56966
57075
|
err.config.retryConfig.currentRetryAttempt += 1;
|
|
56967
|
-
const backoff = config.retryBackoff ? config.retryBackoff(err,
|
|
56968
|
-
setTimeout(resolve5,
|
|
57076
|
+
const backoff = config.retryBackoff ? config.retryBackoff(err, delay3) : new Promise((resolve5) => {
|
|
57077
|
+
setTimeout(resolve5, delay3);
|
|
56969
57078
|
});
|
|
56970
57079
|
if (config.onRetryAttempt) {
|
|
56971
57080
|
await config.onRetryAttempt(err);
|
|
@@ -98751,7 +98860,7 @@ async function retryBackoff(fn, strategy) {
|
|
|
98751
98860
|
retryInterval = initialInterval * Math.pow(x2, exponent) + Math.random() * 1e3;
|
|
98752
98861
|
}
|
|
98753
98862
|
const d = Math.min(retryInterval, maxInterval);
|
|
98754
|
-
await
|
|
98863
|
+
await delay2(d);
|
|
98755
98864
|
x2++;
|
|
98756
98865
|
}
|
|
98757
98866
|
}
|
|
@@ -98772,8 +98881,8 @@ function retryIntervalFromResponse(res) {
|
|
|
98772
98881
|
}
|
|
98773
98882
|
return 0;
|
|
98774
98883
|
}
|
|
98775
|
-
async function
|
|
98776
|
-
return new Promise((resolve5) => setTimeout(resolve5,
|
|
98884
|
+
async function delay2(delay3) {
|
|
98885
|
+
return new Promise((resolve5) => setTimeout(resolve5, delay3));
|
|
98777
98886
|
}
|
|
98778
98887
|
var defaultBackoff, PermanentError, TemporaryError, codeRangeRE2;
|
|
98779
98888
|
var init_retries = __esm({
|
|
@@ -148882,7 +148991,7 @@ __export(lite_provider_exports, {
|
|
|
148882
148991
|
refreshProjectLite: () => refreshProjectLite
|
|
148883
148992
|
});
|
|
148884
148993
|
import { createHash as createHash10 } from "crypto";
|
|
148885
|
-
import { readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
|
|
148994
|
+
import { existsSync as existsSync12, readdirSync as readdirSync2, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
|
|
148886
148995
|
import { join as join4, relative as relative2 } from "path";
|
|
148887
148996
|
function hashText2(text3) {
|
|
148888
148997
|
return createHash10("sha256").update(text3).digest("hex");
|
|
@@ -148899,6 +149008,9 @@ function resolveMaxFileBytes(value) {
|
|
|
148899
149008
|
if (!Number.isFinite(value)) return DEFAULT_CODEGRAPH_MAX_FILE_BYTES;
|
|
148900
149009
|
return Math.max(1, Math.floor(value));
|
|
148901
149010
|
}
|
|
149011
|
+
function isPythonVirtualenvDir(dir) {
|
|
149012
|
+
return existsSync12(join4(dir, "pyvenv.cfg"));
|
|
149013
|
+
}
|
|
148902
149014
|
function walk(root, exclude, maxFiles) {
|
|
148903
149015
|
const out = [];
|
|
148904
149016
|
const visit = (dir) => {
|
|
@@ -148916,6 +149028,7 @@ function walk(root, exclude, maxFiles) {
|
|
|
148916
149028
|
if (entry.isDirectory()) {
|
|
148917
149029
|
if (entry.name === ".git" || entry.name === ".worktrees" || entry.name === ".tmp" || entry.name === "node_modules") continue;
|
|
148918
149030
|
if (rel === ".claude/worktrees" || rel.startsWith(".claude/worktrees/")) continue;
|
|
149031
|
+
if (isPythonVirtualenvDir(abs)) continue;
|
|
148919
149032
|
visit(abs);
|
|
148920
149033
|
if (out.length >= maxFiles) return;
|
|
148921
149034
|
continue;
|
|
@@ -152812,7 +152925,7 @@ __export(vector_backfill_runner_exports, {
|
|
|
152812
152925
|
import { spawn as spawn4 } from "child_process";
|
|
152813
152926
|
import {
|
|
152814
152927
|
closeSync,
|
|
152815
|
-
existsSync as
|
|
152928
|
+
existsSync as existsSync13,
|
|
152816
152929
|
mkdirSync as mkdirSync2,
|
|
152817
152930
|
openSync,
|
|
152818
152931
|
readFileSync as readFileSync9,
|
|
@@ -152940,7 +153053,7 @@ function releaseVectorBackfillLock(lockPath = process.env.MEMORIX_VECTOR_BACKFIL
|
|
|
152940
153053
|
}
|
|
152941
153054
|
function launchDetachedVectorBackfill(request, options = {}) {
|
|
152942
153055
|
const runnerPath = options.runnerPath ?? resolveVectorBackfillRunnerPath();
|
|
152943
|
-
const exists = options.exists ??
|
|
153056
|
+
const exists = options.exists ?? existsSync13;
|
|
152944
153057
|
if (!exists(runnerPath)) return false;
|
|
152945
153058
|
const lock = acquireVectorBackfillLock(request.dataDir, request.projectId, options.lockPath);
|
|
152946
153059
|
if (!lock) return false;
|
|
@@ -154225,16 +154338,18 @@ async function initSessionStore(dataDir) {
|
|
|
154225
154338
|
if (_store3 && _storeDataDir3 === dataDir) return _store3;
|
|
154226
154339
|
_store3 = null;
|
|
154227
154340
|
_storeDataDir3 = null;
|
|
154341
|
+
let degradedReason = "SQLite runtime unavailable";
|
|
154228
154342
|
try {
|
|
154229
|
-
const store2 = new SessionSqliteStore();
|
|
154230
|
-
await store2.init(dataDir);
|
|
154343
|
+
const store2 = await initializeSqliteStore(() => new SessionSqliteStore(), dataDir, "Session store");
|
|
154231
154344
|
_store3 = store2;
|
|
154232
154345
|
_storeDataDir3 = dataDir;
|
|
154233
154346
|
return store2;
|
|
154234
154347
|
} catch (err) {
|
|
154235
|
-
|
|
154348
|
+
if (!isSqliteUnavailableError(err)) throw err;
|
|
154349
|
+
degradedReason = formatSqliteFailure(err);
|
|
154350
|
+
console.error(`[memorix] SessionSqliteStore unavailable, running in degraded read-only mode: ${degradedReason}`);
|
|
154236
154351
|
}
|
|
154237
|
-
const store = new SessionGracefulDegrade();
|
|
154352
|
+
const store = new SessionGracefulDegrade(degradedReason);
|
|
154238
154353
|
await store.init(dataDir);
|
|
154239
154354
|
_store3 = store;
|
|
154240
154355
|
_storeDataDir3 = dataDir;
|
|
@@ -154246,6 +154361,7 @@ var init_session_store = __esm({
|
|
|
154246
154361
|
"use strict";
|
|
154247
154362
|
init_esm_shims();
|
|
154248
154363
|
init_sqlite_db();
|
|
154364
|
+
init_sqlite_reliability();
|
|
154249
154365
|
SessionSqliteStore = class {
|
|
154250
154366
|
db = null;
|
|
154251
154367
|
dataDir = "";
|
|
@@ -154334,7 +154450,7 @@ var init_session_store = __esm({
|
|
|
154334
154450
|
}
|
|
154335
154451
|
const stmtComplete = this._stmtCompleteActive;
|
|
154336
154452
|
const stmtIns = this.stmtInsert;
|
|
154337
|
-
|
|
154453
|
+
return retrySqliteBusy(async () => this.db.transaction(() => {
|
|
154338
154454
|
let completedCount = 0;
|
|
154339
154455
|
for (const pid of projectIds) {
|
|
154340
154456
|
const info = stmtComplete.run({ pid, now: now3 });
|
|
@@ -154342,18 +154458,24 @@ var init_session_store = __esm({
|
|
|
154342
154458
|
}
|
|
154343
154459
|
stmtIns.run(sessionToRow(newSession));
|
|
154344
154460
|
return completedCount;
|
|
154345
|
-
})();
|
|
154346
|
-
return result;
|
|
154461
|
+
})(), "Session rollover");
|
|
154347
154462
|
}
|
|
154348
154463
|
getBackendName() {
|
|
154349
154464
|
return "sqlite";
|
|
154350
154465
|
}
|
|
154351
154466
|
};
|
|
154352
154467
|
SessionGracefulDegrade = class {
|
|
154468
|
+
constructor(reason = "SQLite runtime unavailable") {
|
|
154469
|
+
this.reason = reason;
|
|
154470
|
+
}
|
|
154471
|
+
reason;
|
|
154353
154472
|
warned = false;
|
|
154473
|
+
unavailableRead() {
|
|
154474
|
+
return degradedReadError("sessions");
|
|
154475
|
+
}
|
|
154354
154476
|
warn() {
|
|
154355
154477
|
if (!this.warned) {
|
|
154356
|
-
console.error("[memorix] SessionStore: SQLite unavailable \u2014 sessions
|
|
154478
|
+
console.error("[memorix] SessionStore: SQLite unavailable \u2014 sessions cannot be read or written. Install a supported SQLite runtime.");
|
|
154357
154479
|
this.warned = true;
|
|
154358
154480
|
}
|
|
154359
154481
|
}
|
|
@@ -154361,33 +154483,39 @@ var init_session_store = __esm({
|
|
|
154361
154483
|
this.warn();
|
|
154362
154484
|
}
|
|
154363
154485
|
async loadAll() {
|
|
154364
|
-
|
|
154486
|
+
throw this.unavailableRead();
|
|
154365
154487
|
}
|
|
154366
154488
|
async getById(_id) {
|
|
154367
|
-
|
|
154489
|
+
throw this.unavailableRead();
|
|
154368
154490
|
}
|
|
154369
154491
|
async loadByProject(_projectId) {
|
|
154370
|
-
|
|
154492
|
+
throw this.unavailableRead();
|
|
154371
154493
|
}
|
|
154372
154494
|
async loadActive(_projectId) {
|
|
154373
|
-
|
|
154495
|
+
throw this.unavailableRead();
|
|
154374
154496
|
}
|
|
154375
154497
|
async insert(_session) {
|
|
154376
154498
|
this.warn();
|
|
154499
|
+
throw degradedWriteError("sessions");
|
|
154377
154500
|
}
|
|
154378
154501
|
async update(_session) {
|
|
154379
154502
|
this.warn();
|
|
154503
|
+
throw degradedWriteError("sessions");
|
|
154380
154504
|
}
|
|
154381
154505
|
async bulkUpdate(_sessions) {
|
|
154382
154506
|
this.warn();
|
|
154507
|
+
throw degradedWriteError("sessions");
|
|
154383
154508
|
}
|
|
154384
154509
|
async atomicRolloverInsert(_newSession, _projectIds, _now) {
|
|
154385
154510
|
this.warn();
|
|
154386
|
-
|
|
154511
|
+
throw degradedWriteError("sessions");
|
|
154387
154512
|
}
|
|
154388
154513
|
getBackendName() {
|
|
154389
154514
|
return "degraded";
|
|
154390
154515
|
}
|
|
154516
|
+
getBackendReason() {
|
|
154517
|
+
return this.reason;
|
|
154518
|
+
}
|
|
154391
154519
|
};
|
|
154392
154520
|
_store3 = null;
|
|
154393
154521
|
_storeDataDir3 = null;
|
|
@@ -157861,7 +157989,7 @@ var init_sanitizer = __esm({
|
|
|
157861
157989
|
});
|
|
157862
157990
|
|
|
157863
157991
|
// src/workspace/applier.ts
|
|
157864
|
-
import { existsSync as
|
|
157992
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync3, copyFileSync, writeFileSync as writeFileSync3, unlinkSync as unlinkSync2, renameSync } from "fs";
|
|
157865
157993
|
import { dirname } from "path";
|
|
157866
157994
|
var WorkspaceSyncApplier;
|
|
157867
157995
|
var init_applier = __esm({
|
|
@@ -157892,7 +158020,7 @@ var init_applier = __esm({
|
|
|
157892
158020
|
for (const file of files) {
|
|
157893
158021
|
try {
|
|
157894
158022
|
const dir = dirname(file.filePath);
|
|
157895
|
-
if (!
|
|
158023
|
+
if (!existsSync14(dir)) {
|
|
157896
158024
|
mkdirSync3(dir, { recursive: true });
|
|
157897
158025
|
}
|
|
157898
158026
|
} catch (err) {
|
|
@@ -157901,7 +158029,7 @@ var init_applier = __esm({
|
|
|
157901
158029
|
}
|
|
157902
158030
|
}
|
|
157903
158031
|
for (const file of files) {
|
|
157904
|
-
if (
|
|
158032
|
+
if (existsSync14(file.filePath)) {
|
|
157905
158033
|
try {
|
|
157906
158034
|
const backupPath = file.filePath + `.backup-${Date.now()}`;
|
|
157907
158035
|
copyFileSync(file.filePath, backupPath);
|
|
@@ -157952,7 +158080,7 @@ var init_applier = __esm({
|
|
|
157952
158080
|
cleanBackups(backups) {
|
|
157953
158081
|
for (const backup of backups) {
|
|
157954
158082
|
try {
|
|
157955
|
-
if (
|
|
158083
|
+
if (existsSync14(backup.backupPath)) {
|
|
157956
158084
|
unlinkSync2(backup.backupPath);
|
|
157957
158085
|
}
|
|
157958
158086
|
} catch {
|
|
@@ -157964,7 +158092,7 @@ var init_applier = __esm({
|
|
|
157964
158092
|
});
|
|
157965
158093
|
|
|
157966
158094
|
// src/workspace/engine.ts
|
|
157967
|
-
import { readFileSync as readFileSync10, readdirSync as readdirSync3, existsSync as
|
|
158095
|
+
import { readFileSync as readFileSync10, readdirSync as readdirSync3, existsSync as existsSync15, cpSync, mkdirSync as mkdirSync4 } from "fs";
|
|
157968
158096
|
import { join as join19 } from "path";
|
|
157969
158097
|
import { homedir as homedir21 } from "os";
|
|
157970
158098
|
var WorkspaceSyncEngine;
|
|
@@ -158044,7 +158172,7 @@ var init_engine4 = __esm({
|
|
|
158044
158172
|
}
|
|
158045
158173
|
const merged = /* @__PURE__ */ new Map();
|
|
158046
158174
|
for (const path38 of pathsToCheck) {
|
|
158047
|
-
if (
|
|
158175
|
+
if (existsSync15(path38)) {
|
|
158048
158176
|
try {
|
|
158049
158177
|
const content = readFileSync10(path38, "utf-8");
|
|
158050
158178
|
const servers = adapter.parse(content);
|
|
@@ -158098,7 +158226,7 @@ var init_engine4 = __esm({
|
|
|
158098
158226
|
const adapter = this.adapters.get(target);
|
|
158099
158227
|
const configPath = adapter.getConfigPath(this.projectRoot);
|
|
158100
158228
|
let configContent;
|
|
158101
|
-
if (target === "antigravity" &&
|
|
158229
|
+
if (target === "antigravity" && existsSync15(configPath)) {
|
|
158102
158230
|
try {
|
|
158103
158231
|
const existing = JSON.parse(readFileSync10(configPath, "utf-8"));
|
|
158104
158232
|
const generated = JSON.parse(adapter.generate(result.mcpServers.scanned));
|
|
@@ -158174,13 +158302,13 @@ var init_engine4 = __esm({
|
|
|
158174
158302
|
join19(home, dir)
|
|
158175
158303
|
];
|
|
158176
158304
|
for (const skillsRoot of paths) {
|
|
158177
|
-
if (!
|
|
158305
|
+
if (!existsSync15(skillsRoot)) continue;
|
|
158178
158306
|
try {
|
|
158179
158307
|
const entries = readdirSync3(skillsRoot, { withFileTypes: true });
|
|
158180
158308
|
for (const entry of entries) {
|
|
158181
158309
|
if (!entry.isDirectory()) continue;
|
|
158182
158310
|
const skillMd = join19(skillsRoot, entry.name, "SKILL.md");
|
|
158183
|
-
if (!
|
|
158311
|
+
if (!existsSync15(skillMd)) continue;
|
|
158184
158312
|
let description = "";
|
|
158185
158313
|
try {
|
|
158186
158314
|
const content = readFileSync10(skillMd, "utf-8");
|
|
@@ -158229,7 +158357,7 @@ var init_engine4 = __esm({
|
|
|
158229
158357
|
for (const skill2 of skills) {
|
|
158230
158358
|
if (skill2.sourceAgent === target) continue;
|
|
158231
158359
|
const dest = join19(targetDir, skill2.name);
|
|
158232
|
-
if (
|
|
158360
|
+
if (existsSync15(dest)) {
|
|
158233
158361
|
skipped.push(`${skill2.name} (already exists in ${target})`);
|
|
158234
158362
|
continue;
|
|
158235
158363
|
}
|
|
@@ -158245,7 +158373,7 @@ var init_engine4 = __esm({
|
|
|
158245
158373
|
scanWorkflows() {
|
|
158246
158374
|
const workflows = [];
|
|
158247
158375
|
const wfDir = join19(this.projectRoot, ".windsurf", "workflows");
|
|
158248
|
-
if (!
|
|
158376
|
+
if (!existsSync15(wfDir)) return workflows;
|
|
158249
158377
|
try {
|
|
158250
158378
|
const files = readdirSync3(wfDir).filter((f3) => f3.endsWith(".md"));
|
|
158251
158379
|
for (const file of files) {
|
|
@@ -159643,7 +159771,7 @@ var init_request_context = __esm({
|
|
|
159643
159771
|
function getMcpServerInfo() {
|
|
159644
159772
|
return {
|
|
159645
159773
|
name: "memorix",
|
|
159646
|
-
version: true ? "1.9.
|
|
159774
|
+
version: true ? "1.9.3" : "1.0.1"
|
|
159647
159775
|
};
|
|
159648
159776
|
}
|
|
159649
159777
|
function createMcpDiscoverResult(capabilities, serverInfo) {
|
|
@@ -159711,7 +159839,7 @@ __export(behavior_exports, {
|
|
|
159711
159839
|
getBehaviorConfig: () => getBehaviorConfig,
|
|
159712
159840
|
resetBehaviorConfigCache: () => resetBehaviorConfigCache
|
|
159713
159841
|
});
|
|
159714
|
-
import { existsSync as
|
|
159842
|
+
import { existsSync as existsSync16, readFileSync as readFileSync11 } from "fs";
|
|
159715
159843
|
import { homedir as homedir22 } from "os";
|
|
159716
159844
|
function isSessionInject(value) {
|
|
159717
159845
|
return value === "full" || value === "minimal" || value === "silent";
|
|
@@ -159722,7 +159850,7 @@ function isFormationMode(value) {
|
|
|
159722
159850
|
function legacyBehavior(homeDir) {
|
|
159723
159851
|
const configPath = getLegacyConfigJsonPath(homeDir);
|
|
159724
159852
|
try {
|
|
159725
|
-
if (!
|
|
159853
|
+
if (!existsSync16(configPath)) return {};
|
|
159726
159854
|
const parsed = JSON.parse(readFileSync11(configPath, "utf-8"));
|
|
159727
159855
|
return parsed.behavior && typeof parsed.behavior === "object" && !Array.isArray(parsed.behavior) ? parsed.behavior : {};
|
|
159728
159856
|
} catch {
|
|
@@ -161076,11 +161204,11 @@ __export(current_facts_exports, {
|
|
|
161076
161204
|
formatGitFact: () => formatGitFact
|
|
161077
161205
|
});
|
|
161078
161206
|
import { execFileSync } from "child_process";
|
|
161079
|
-
import { existsSync as
|
|
161207
|
+
import { existsSync as existsSync17, readFileSync as readFileSync12 } from "fs";
|
|
161080
161208
|
import path29 from "path";
|
|
161081
161209
|
function readTextIfExists(filePath) {
|
|
161082
161210
|
try {
|
|
161083
|
-
if (!
|
|
161211
|
+
if (!existsSync17(filePath)) return null;
|
|
161084
161212
|
return readFileSync12(filePath, "utf8");
|
|
161085
161213
|
} catch {
|
|
161086
161214
|
return null;
|
|
@@ -161371,7 +161499,7 @@ __export(external_provider_exports, {
|
|
|
161371
161499
|
runExternalCodeGraphLifecycle: () => runExternalCodeGraphLifecycle
|
|
161372
161500
|
});
|
|
161373
161501
|
import { spawn as spawn5 } from "child_process";
|
|
161374
|
-
import { existsSync as
|
|
161502
|
+
import { existsSync as existsSync18, readFileSync as readFileSync13 } from "fs";
|
|
161375
161503
|
import { delimiter, dirname as dirname2, extname, isAbsolute as isAbsolute3, join as join20, relative as relative4, resolve as resolve3, sep } from "path";
|
|
161376
161504
|
function boundedTimeout(value) {
|
|
161377
161505
|
if (!Number.isFinite(value)) return DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS;
|
|
@@ -161408,13 +161536,13 @@ function resolveCommandCandidates(command) {
|
|
|
161408
161536
|
}
|
|
161409
161537
|
function resolveLaunch(command) {
|
|
161410
161538
|
for (const candidate of resolveCommandCandidates(command)) {
|
|
161411
|
-
if (!
|
|
161539
|
+
if (!existsSync18(candidate)) continue;
|
|
161412
161540
|
const extension3 = extname(candidate).toLowerCase();
|
|
161413
161541
|
if (extension3 === ".cmd") {
|
|
161414
161542
|
const bundleRoot = resolve3(dirname2(candidate), "..");
|
|
161415
161543
|
const node = join20(bundleRoot, "node.exe");
|
|
161416
161544
|
const entry = join20(bundleRoot, "lib", "dist", "bin", "codegraph.js");
|
|
161417
|
-
if (
|
|
161545
|
+
if (existsSync18(node) && existsSync18(entry)) {
|
|
161418
161546
|
return { executable: node, prefixArgs: ["--liftoff-only", entry] };
|
|
161419
161547
|
}
|
|
161420
161548
|
try {
|
|
@@ -161423,7 +161551,7 @@ function resolveLaunch(command) {
|
|
|
161423
161551
|
if (match2?.[1]) {
|
|
161424
161552
|
const base = dirname2(candidate).endsWith(sep) ? dirname2(candidate) : dirname2(candidate) + sep;
|
|
161425
161553
|
const entry2 = resolve3(match2[1].replace(/%(?:~)?dp0%?/gi, base));
|
|
161426
|
-
if (
|
|
161554
|
+
if (existsSync18(entry2)) return { executable: process.execPath, prefixArgs: [entry2] };
|
|
161427
161555
|
}
|
|
161428
161556
|
} catch {
|
|
161429
161557
|
}
|
|
@@ -161571,7 +161699,7 @@ async function inspectExternalCodeGraph(input) {
|
|
|
161571
161699
|
const health2 = { state: "disabled", reason: "External CodeGraph is disabled by configuration." };
|
|
161572
161700
|
return { health: health2, quality: providerQuality({ mode, health: health2 }) };
|
|
161573
161701
|
}
|
|
161574
|
-
if (!
|
|
161702
|
+
if (!existsSync18(join20(input.projectRoot, ".codegraph"))) {
|
|
161575
161703
|
const health2 = { state: "not-detected", reason: "No local .codegraph index is present for this project." };
|
|
161576
161704
|
return { health: health2, quality: providerQuality({ mode, health: health2 }) };
|
|
161577
161705
|
}
|
|
@@ -161607,7 +161735,7 @@ async function runExternalCodeGraphLifecycle(input) {
|
|
|
161607
161735
|
};
|
|
161608
161736
|
}
|
|
161609
161737
|
const indexPath = join20(input.projectRoot, ".codegraph");
|
|
161610
|
-
if (input.action === "sync" && !
|
|
161738
|
+
if (input.action === "sync" && !existsSync18(indexPath)) {
|
|
161611
161739
|
const health = { state: "not-detected", reason: "No local .codegraph index is present for this project." };
|
|
161612
161740
|
return {
|
|
161613
161741
|
action: input.action,
|
|
@@ -161617,7 +161745,7 @@ async function runExternalCodeGraphLifecycle(input) {
|
|
|
161617
161745
|
quality: providerQuality({ mode, health })
|
|
161618
161746
|
};
|
|
161619
161747
|
}
|
|
161620
|
-
if (input.action === "init" &&
|
|
161748
|
+
if (input.action === "init" && existsSync18(indexPath)) {
|
|
161621
161749
|
const inspected2 = await inspectExternalCodeGraph(input);
|
|
161622
161750
|
return {
|
|
161623
161751
|
action: input.action,
|
|
@@ -162678,7 +162806,7 @@ __export(auto_context_exports, {
|
|
|
162678
162806
|
formatAutoProjectContextSummary: () => formatAutoProjectContextSummary,
|
|
162679
162807
|
formatLegacyAutoProjectContextPrompt: () => formatLegacyAutoProjectContextPrompt
|
|
162680
162808
|
});
|
|
162681
|
-
import { existsSync as
|
|
162809
|
+
import { existsSync as existsSync19, statSync as statSync5 } from "fs";
|
|
162682
162810
|
import path30 from "path";
|
|
162683
162811
|
function activeProjectObservations(observations2, projectId) {
|
|
162684
162812
|
return observations2.filter((obs) => obs.projectId === projectId && (obs.status ?? "active") === "active");
|
|
@@ -163024,7 +163152,7 @@ function existingLensCandidates(rootPath, lens) {
|
|
|
163024
163152
|
for (const candidate of lensPathCandidates(lens)) {
|
|
163025
163153
|
const absolute = path30.join(rootPath, candidate);
|
|
163026
163154
|
try {
|
|
163027
|
-
if (!
|
|
163155
|
+
if (!existsSync19(absolute)) continue;
|
|
163028
163156
|
const stat5 = statSync5(absolute);
|
|
163029
163157
|
if (stat5.isFile()) out.push(candidate);
|
|
163030
163158
|
if (stat5.isDirectory()) out.push(candidate.replace(/\\/g, "/"));
|
|
@@ -163558,7 +163686,7 @@ var engine_exports2 = {};
|
|
|
163558
163686
|
__export(engine_exports2, {
|
|
163559
163687
|
SkillsEngine: () => SkillsEngine
|
|
163560
163688
|
});
|
|
163561
|
-
import { existsSync as
|
|
163689
|
+
import { existsSync as existsSync20, readFileSync as readFileSync14, writeFileSync as writeFileSync4, mkdirSync as mkdirSync5, readdirSync as readdirSync4 } from "fs";
|
|
163562
163690
|
import { join as join21 } from "path";
|
|
163563
163691
|
import { homedir as homedir23 } from "os";
|
|
163564
163692
|
var SKILLS_DIRS, SKILL_WORTHY_TYPES, MIN_OBS_FOR_SKILL, MIN_SCORE_FOR_SKILL, LOW_SIGNAL_TITLE_PATTERNS, LOW_SIGNAL_ENTITY_PATTERNS, COMMAND_TRACE_PATTERNS2, SkillsEngine;
|
|
@@ -163639,7 +163767,7 @@ var init_engine5 = __esm({
|
|
|
163639
163767
|
paths.push(join21(home, dir));
|
|
163640
163768
|
}
|
|
163641
163769
|
for (const skillsRoot of paths) {
|
|
163642
|
-
if (!
|
|
163770
|
+
if (!existsSync20(skillsRoot)) continue;
|
|
163643
163771
|
try {
|
|
163644
163772
|
const entries = readdirSync4(skillsRoot, { withFileTypes: true });
|
|
163645
163773
|
for (const entry of entries) {
|
|
@@ -163647,7 +163775,7 @@ var init_engine5 = __esm({
|
|
|
163647
163775
|
const name = entry.name;
|
|
163648
163776
|
if (seen.has(name)) continue;
|
|
163649
163777
|
const skillMd = join21(skillsRoot, name, "SKILL.md");
|
|
163650
|
-
if (!
|
|
163778
|
+
if (!existsSync20(skillMd)) continue;
|
|
163651
163779
|
try {
|
|
163652
163780
|
const content = readFileSync14(skillMd, "utf-8");
|
|
163653
163781
|
const description = this.parseDescription(content);
|
|
@@ -165448,7 +165576,8 @@ async function executeDeduplicate(context, payload, token) {
|
|
|
165448
165576
|
async function previewConsolidate(context) {
|
|
165449
165577
|
const clusters = await findConsolidationCandidates(
|
|
165450
165578
|
context.projectRoot ?? context.dataDir,
|
|
165451
|
-
context.projectId
|
|
165579
|
+
context.projectId,
|
|
165580
|
+
{ store: context.store }
|
|
165452
165581
|
);
|
|
165453
165582
|
const payload = { clusterIds: normalizeClusters(clusters.map((cluster) => cluster.ids)) };
|
|
165454
165583
|
return {
|
|
@@ -165471,11 +165600,19 @@ async function executeConsolidate(context, payload, token) {
|
|
|
165471
165600
|
const clusterIds = record80.clusterIds.map((ids, index) => payloadIds(ids, `clusterIds[${index}]`));
|
|
165472
165601
|
const normalized = { clusterIds: normalizeClusters(clusterIds) };
|
|
165473
165602
|
verify("consolidate", context.projectId, normalized, token);
|
|
165474
|
-
const current = await findConsolidationCandidates(
|
|
165603
|
+
const current = await findConsolidationCandidates(
|
|
165604
|
+
context.projectRoot ?? context.dataDir,
|
|
165605
|
+
context.projectId,
|
|
165606
|
+
{ store: context.store }
|
|
165607
|
+
);
|
|
165475
165608
|
if (JSON.stringify(normalized.clusterIds) !== JSON.stringify(normalizeClusters(current.map((cluster) => cluster.ids)))) {
|
|
165476
165609
|
throw new DashboardMaintenanceError("Memory changed after the preview. Refresh before consolidating.", 409);
|
|
165477
165610
|
}
|
|
165478
|
-
const result = await executeConsolidation(
|
|
165611
|
+
const result = await executeConsolidation(
|
|
165612
|
+
context.projectRoot ?? context.dataDir,
|
|
165613
|
+
context.projectId,
|
|
165614
|
+
{ store: context.store }
|
|
165615
|
+
);
|
|
165479
165616
|
return { action: "consolidate", projectId: context.projectId, ...result };
|
|
165480
165617
|
}
|
|
165481
165618
|
async function retentionCandidates(context) {
|
|
@@ -166632,7 +166769,7 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
166632
166769
|
}
|
|
166633
166770
|
case "/config": {
|
|
166634
166771
|
const os6 = await import("os");
|
|
166635
|
-
const { existsSync:
|
|
166772
|
+
const { existsSync: existsSync23 } = await import("fs");
|
|
166636
166773
|
const { join: join26 } = await import("path");
|
|
166637
166774
|
const configProjectRoot = effectiveProjectRoot;
|
|
166638
166775
|
const resolved = getResolvedConfig({ projectRoot: configProjectRoot });
|
|
@@ -166660,7 +166797,7 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
166660
166797
|
if (fpath === null) {
|
|
166661
166798
|
files[key] = { exists: false, path: "unavailable", unavailable: true };
|
|
166662
166799
|
} else {
|
|
166663
|
-
files[key] = { exists:
|
|
166800
|
+
files[key] = { exists: existsSync23(fpath), path: fpath };
|
|
166664
166801
|
}
|
|
166665
166802
|
}
|
|
166666
166803
|
} catch {
|
|
@@ -167470,7 +167607,7 @@ var init_task_graph = __esm({
|
|
|
167470
167607
|
|
|
167471
167608
|
// src/orchestrate/context-collector.ts
|
|
167472
167609
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
167473
|
-
import { readFileSync as readFileSync15, existsSync as
|
|
167610
|
+
import { readFileSync as readFileSync15, existsSync as existsSync21 } from "fs";
|
|
167474
167611
|
import { join as join22 } from "path";
|
|
167475
167612
|
function normalizeEntryLimit(value, fallback) {
|
|
167476
167613
|
if (!Number.isSafeInteger(value) || value < 1) return fallback;
|
|
@@ -167547,7 +167684,7 @@ function collectFileTree(projectDir2, maxEntries) {
|
|
|
167547
167684
|
function collectDependencies(projectDir2) {
|
|
167548
167685
|
try {
|
|
167549
167686
|
const pkgPath = join22(projectDir2, "package.json");
|
|
167550
|
-
if (!
|
|
167687
|
+
if (!existsSync21(pkgPath)) return "";
|
|
167551
167688
|
const pkg = JSON.parse(readFileSync15(pkgPath, "utf-8"));
|
|
167552
167689
|
const parts = [];
|
|
167553
167690
|
if (pkg.dependencies && Object.keys(pkg.dependencies).length > 0) {
|
|
@@ -170048,11 +170185,11 @@ __export(hooks_path_exports, {
|
|
|
170048
170185
|
resolveGitDir: () => resolveGitDir,
|
|
170049
170186
|
resolveHooksDir: () => resolveHooksDir
|
|
170050
170187
|
});
|
|
170051
|
-
import { existsSync as
|
|
170188
|
+
import { existsSync as existsSync22, readFileSync as readFileSync16, statSync as statSync6, mkdirSync as mkdirSync6 } from "fs";
|
|
170052
170189
|
import path35 from "path";
|
|
170053
170190
|
function resolveGitDir(projectRoot) {
|
|
170054
170191
|
const dotGit = path35.join(projectRoot, ".git");
|
|
170055
|
-
if (!
|
|
170192
|
+
if (!existsSync22(dotGit)) return null;
|
|
170056
170193
|
const stat5 = statSync6(dotGit);
|
|
170057
170194
|
if (stat5.isDirectory()) {
|
|
170058
170195
|
return dotGit;
|
|
@@ -170064,7 +170201,7 @@ function resolveGitDir(projectRoot) {
|
|
|
170064
170201
|
if (match2) {
|
|
170065
170202
|
const gitdir = match2[1].trim();
|
|
170066
170203
|
const resolved = path35.isAbsolute(gitdir) ? gitdir : path35.resolve(projectRoot, gitdir);
|
|
170067
|
-
if (
|
|
170204
|
+
if (existsSync22(resolved)) {
|
|
170068
170205
|
return resolved;
|
|
170069
170206
|
}
|
|
170070
170207
|
}
|
|
@@ -174659,10 +174796,10 @@ Preview: ${analysis.description.slice(0, 300)}${analysis.description.length > 30
|
|
|
174659
174796
|
const { ensureHooksDir: ensureHooksDir2 } = await Promise.resolve().then(() => (init_hooks_path(), hooks_path_exports));
|
|
174660
174797
|
const resolved = ensureHooksDir2(project.rootPath);
|
|
174661
174798
|
if (resolved) {
|
|
174662
|
-
const { existsSync:
|
|
174799
|
+
const { existsSync: existsSync23, readFileSync: readFileSync17, writeFileSync: writeFileSync5, chmodSync } = await import("fs");
|
|
174663
174800
|
const { hookPath } = resolved;
|
|
174664
174801
|
const HOOK_MARKER = "# [memorix-git-hook]";
|
|
174665
|
-
const needsInstall = !
|
|
174802
|
+
const needsInstall = !existsSync23(hookPath) || !readFileSync17(hookPath, "utf-8").includes(HOOK_MARKER);
|
|
174666
174803
|
if (needsInstall) {
|
|
174667
174804
|
const hookScript = `#!/bin/sh
|
|
174668
174805
|
${HOOK_MARKER}
|
|
@@ -174671,7 +174808,7 @@ if command -v memorix >/dev/null 2>&1; then
|
|
|
174671
174808
|
memorix ingest commit --auto >/dev/null 2>&1 &
|
|
174672
174809
|
fi
|
|
174673
174810
|
`;
|
|
174674
|
-
if (
|
|
174811
|
+
if (existsSync23(hookPath)) {
|
|
174675
174812
|
const existing = readFileSync17(hookPath, "utf-8");
|
|
174676
174813
|
writeFileSync5(hookPath, existing.trimEnd() + `
|
|
174677
174814
|
|
|
@@ -175343,7 +175480,7 @@ var init_serve_shared = __esm({
|
|
|
175343
175480
|
|
|
175344
175481
|
// src/cli/version.ts
|
|
175345
175482
|
function getCliVersion() {
|
|
175346
|
-
return true ? "1.9.
|
|
175483
|
+
return true ? "1.9.3" : pkg.version;
|
|
175347
175484
|
}
|
|
175348
175485
|
var init_version3 = __esm({
|
|
175349
175486
|
"src/cli/version.ts"() {
|