memorix 1.9.2 → 1.9.4
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 +27 -0
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/cli/index.js +358 -146
- package/dist/index.js +281 -125
- package/dist/maintenance-runner.js +219 -97
- package/dist/media-audio-runner.js +219 -97
- package/dist/media-video-runner.js +219 -97
- package/dist/memcode-runtime/CHANGELOG.md +27 -0
- package/dist/sdk.js +280 -124
- package/dist/vector-backfill-runner.js +219 -97
- package/docs/AGENT_OPERATOR_PLAYBOOK.md +15 -0
- package/docs/ARCHITECTURE.md +23 -0
- package/docs/DEVELOPMENT.md +1 -1
- package/docs/PERFORMANCE.md +50 -0
- package/docs/README.md +1 -1
- package/package.json +1 -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/commands/doctor.ts +78 -17
- package/src/cli/commands/media.ts +2 -0
- package/src/media/minimax.ts +26 -2
- package/src/media/video-jobs.ts +9 -1
- package/src/server.ts +3 -1
- 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/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
|
});
|
|
@@ -56963,10 +57071,10 @@ var require_retry3 = __commonJS({
|
|
|
56963
57071
|
if (!await shouldRetryFn(err)) {
|
|
56964
57072
|
return { shouldRetry: false, config: err.config };
|
|
56965
57073
|
}
|
|
56966
|
-
const
|
|
57074
|
+
const delay3 = getNextRetryDelay(config);
|
|
56967
57075
|
err.config.retryConfig.currentRetryAttempt += 1;
|
|
56968
|
-
const backoff = config.retryBackoff ? config.retryBackoff(err,
|
|
56969
|
-
setTimeout(resolve5,
|
|
57076
|
+
const backoff = config.retryBackoff ? config.retryBackoff(err, delay3) : new Promise((resolve5) => {
|
|
57077
|
+
setTimeout(resolve5, delay3);
|
|
56970
57078
|
});
|
|
56971
57079
|
if (config.onRetryAttempt) {
|
|
56972
57080
|
await config.onRetryAttempt(err);
|
|
@@ -98752,7 +98860,7 @@ async function retryBackoff(fn, strategy) {
|
|
|
98752
98860
|
retryInterval = initialInterval * Math.pow(x2, exponent) + Math.random() * 1e3;
|
|
98753
98861
|
}
|
|
98754
98862
|
const d = Math.min(retryInterval, maxInterval);
|
|
98755
|
-
await
|
|
98863
|
+
await delay2(d);
|
|
98756
98864
|
x2++;
|
|
98757
98865
|
}
|
|
98758
98866
|
}
|
|
@@ -98773,8 +98881,8 @@ function retryIntervalFromResponse(res) {
|
|
|
98773
98881
|
}
|
|
98774
98882
|
return 0;
|
|
98775
98883
|
}
|
|
98776
|
-
async function
|
|
98777
|
-
return new Promise((resolve5) => setTimeout(resolve5,
|
|
98884
|
+
async function delay2(delay3) {
|
|
98885
|
+
return new Promise((resolve5) => setTimeout(resolve5, delay3));
|
|
98778
98886
|
}
|
|
98779
98887
|
var defaultBackoff, PermanentError, TemporaryError, codeRangeRE2;
|
|
98780
98888
|
var init_retries = __esm({
|
|
@@ -145080,7 +145188,20 @@ function normalizeMiniMaxVideoRequest(input) {
|
|
|
145080
145188
|
if (ratio !== "adaptive" && ratio !== "16:9" && ratio !== "9:16" && ratio !== "1:1") {
|
|
145081
145189
|
throw new Error("MiniMax video ratio must be adaptive, 16:9, 9:16, or 1:1");
|
|
145082
145190
|
}
|
|
145083
|
-
|
|
145191
|
+
let firstFrameImageUrl;
|
|
145192
|
+
if (input.firstFrameImageUrl !== void 0) {
|
|
145193
|
+
firstFrameImageUrl = input.firstFrameImageUrl.trim();
|
|
145194
|
+
let parsed;
|
|
145195
|
+
try {
|
|
145196
|
+
parsed = new URL(firstFrameImageUrl);
|
|
145197
|
+
} catch {
|
|
145198
|
+
throw new Error("MiniMax first-frame image must be a public HTTPS URL");
|
|
145199
|
+
}
|
|
145200
|
+
if (parsed.protocol !== "https:" || parsed.username || parsed.password || sanitizeCredentials(firstFrameImageUrl) !== firstFrameImageUrl) {
|
|
145201
|
+
throw new Error("MiniMax first-frame image must be an HTTPS URL without credentials");
|
|
145202
|
+
}
|
|
145203
|
+
}
|
|
145204
|
+
return { region, model, prompt, resolution, duration, ratio, ...firstFrameImageUrl ? { firstFrameImageUrl } : {} };
|
|
145084
145205
|
}
|
|
145085
145206
|
function videoRequestConfig(input) {
|
|
145086
145207
|
const normalized = normalizeMiniMaxVideoRequest(input);
|
|
@@ -145157,7 +145278,14 @@ async function createMiniMaxVideoTask(input, dependencies = {}) {
|
|
|
145157
145278
|
headers: videoHeaders(config.apiKey),
|
|
145158
145279
|
body: JSON.stringify({
|
|
145159
145280
|
model: config.model,
|
|
145160
|
-
content: [
|
|
145281
|
+
content: [
|
|
145282
|
+
{ type: "text", text: config.prompt },
|
|
145283
|
+
...config.firstFrameImageUrl ? [{
|
|
145284
|
+
type: "image_url",
|
|
145285
|
+
image_url: { url: config.firstFrameImageUrl },
|
|
145286
|
+
role: "first_frame"
|
|
145287
|
+
}] : []
|
|
145288
|
+
],
|
|
145161
145289
|
resolution: config.resolution,
|
|
145162
145290
|
duration: config.duration,
|
|
145163
145291
|
ratio: config.ratio
|
|
@@ -145405,10 +145533,19 @@ function parseStoredRequest(value) {
|
|
|
145405
145533
|
const duration = value.duration;
|
|
145406
145534
|
const ratio = value.ratio;
|
|
145407
145535
|
const maxBytes = value.maxBytes;
|
|
145408
|
-
if (provider2 !== "minimax" && provider2 !== "minimax-cn" || region !== "global" && region !== "cn" || model !== "MiniMax-H3" || typeof prompt !== "string" || resolution !== "2K" || duration !== 5 && duration !== 10 || ratio !== "adaptive" && ratio !== "16:9" && ratio !== "9:16" && ratio !== "1:1" || typeof maxBytes !== "number" || !Number.isSafeInteger(maxBytes) || maxBytes < 1) {
|
|
145536
|
+
if (provider2 !== "minimax" && provider2 !== "minimax-cn" || region !== "global" && region !== "cn" || model !== "MiniMax-H3" || typeof prompt !== "string" || value.firstFrameImageUrl !== void 0 && typeof value.firstFrameImageUrl !== "string" || resolution !== "2K" || duration !== 5 && duration !== 10 || ratio !== "adaptive" && ratio !== "16:9" && ratio !== "9:16" && ratio !== "1:1" || typeof maxBytes !== "number" || !Number.isSafeInteger(maxBytes) || maxBytes < 1) {
|
|
145409
145537
|
throw new Error("Media video job has an invalid request payload");
|
|
145410
145538
|
}
|
|
145411
|
-
|
|
145539
|
+
const normalized = normalizeMiniMaxVideoRequest({
|
|
145540
|
+
region,
|
|
145541
|
+
model,
|
|
145542
|
+
prompt,
|
|
145543
|
+
resolution,
|
|
145544
|
+
duration,
|
|
145545
|
+
ratio,
|
|
145546
|
+
firstFrameImageUrl: value.firstFrameImageUrl
|
|
145547
|
+
});
|
|
145548
|
+
return { provider: provider2, ...normalized, maxBytes };
|
|
145412
145549
|
}
|
|
145413
145550
|
function mediaJobIdFromMaintenance(job) {
|
|
145414
145551
|
const mediaJobId = job.payload.mediaJobId;
|
|
@@ -145420,6 +145557,7 @@ function mediaJobIdFromMaintenance(job) {
|
|
|
145420
145557
|
function toVideoRequest(request) {
|
|
145421
145558
|
return {
|
|
145422
145559
|
prompt: request.prompt,
|
|
145560
|
+
firstFrameImageUrl: request.firstFrameImageUrl,
|
|
145423
145561
|
model: request.model,
|
|
145424
145562
|
region: request.region,
|
|
145425
145563
|
resolution: request.resolution,
|
|
@@ -145511,6 +145649,7 @@ function queueMiniMaxVideoGeneration(input) {
|
|
|
145511
145649
|
region: normalized.region,
|
|
145512
145650
|
model: normalized.model,
|
|
145513
145651
|
prompt: normalized.prompt,
|
|
145652
|
+
...normalized.firstFrameImageUrl ? { firstFrameImageUrl: normalized.firstFrameImageUrl } : {},
|
|
145514
145653
|
resolution: normalized.resolution,
|
|
145515
145654
|
duration: normalized.duration,
|
|
145516
145655
|
ratio: normalized.ratio,
|
|
@@ -154230,16 +154369,18 @@ async function initSessionStore(dataDir) {
|
|
|
154230
154369
|
if (_store3 && _storeDataDir3 === dataDir) return _store3;
|
|
154231
154370
|
_store3 = null;
|
|
154232
154371
|
_storeDataDir3 = null;
|
|
154372
|
+
let degradedReason = "SQLite runtime unavailable";
|
|
154233
154373
|
try {
|
|
154234
|
-
const store2 = new SessionSqliteStore();
|
|
154235
|
-
await store2.init(dataDir);
|
|
154374
|
+
const store2 = await initializeSqliteStore(() => new SessionSqliteStore(), dataDir, "Session store");
|
|
154236
154375
|
_store3 = store2;
|
|
154237
154376
|
_storeDataDir3 = dataDir;
|
|
154238
154377
|
return store2;
|
|
154239
154378
|
} catch (err) {
|
|
154240
|
-
|
|
154379
|
+
if (!isSqliteUnavailableError(err)) throw err;
|
|
154380
|
+
degradedReason = formatSqliteFailure(err);
|
|
154381
|
+
console.error(`[memorix] SessionSqliteStore unavailable, running in degraded read-only mode: ${degradedReason}`);
|
|
154241
154382
|
}
|
|
154242
|
-
const store = new SessionGracefulDegrade();
|
|
154383
|
+
const store = new SessionGracefulDegrade(degradedReason);
|
|
154243
154384
|
await store.init(dataDir);
|
|
154244
154385
|
_store3 = store;
|
|
154245
154386
|
_storeDataDir3 = dataDir;
|
|
@@ -154251,6 +154392,7 @@ var init_session_store = __esm({
|
|
|
154251
154392
|
"use strict";
|
|
154252
154393
|
init_esm_shims();
|
|
154253
154394
|
init_sqlite_db();
|
|
154395
|
+
init_sqlite_reliability();
|
|
154254
154396
|
SessionSqliteStore = class {
|
|
154255
154397
|
db = null;
|
|
154256
154398
|
dataDir = "";
|
|
@@ -154339,7 +154481,7 @@ var init_session_store = __esm({
|
|
|
154339
154481
|
}
|
|
154340
154482
|
const stmtComplete = this._stmtCompleteActive;
|
|
154341
154483
|
const stmtIns = this.stmtInsert;
|
|
154342
|
-
|
|
154484
|
+
return retrySqliteBusy(async () => this.db.transaction(() => {
|
|
154343
154485
|
let completedCount = 0;
|
|
154344
154486
|
for (const pid of projectIds) {
|
|
154345
154487
|
const info = stmtComplete.run({ pid, now: now3 });
|
|
@@ -154347,18 +154489,24 @@ var init_session_store = __esm({
|
|
|
154347
154489
|
}
|
|
154348
154490
|
stmtIns.run(sessionToRow(newSession));
|
|
154349
154491
|
return completedCount;
|
|
154350
|
-
})();
|
|
154351
|
-
return result;
|
|
154492
|
+
})(), "Session rollover");
|
|
154352
154493
|
}
|
|
154353
154494
|
getBackendName() {
|
|
154354
154495
|
return "sqlite";
|
|
154355
154496
|
}
|
|
154356
154497
|
};
|
|
154357
154498
|
SessionGracefulDegrade = class {
|
|
154499
|
+
constructor(reason = "SQLite runtime unavailable") {
|
|
154500
|
+
this.reason = reason;
|
|
154501
|
+
}
|
|
154502
|
+
reason;
|
|
154358
154503
|
warned = false;
|
|
154504
|
+
unavailableRead() {
|
|
154505
|
+
return degradedReadError("sessions");
|
|
154506
|
+
}
|
|
154359
154507
|
warn() {
|
|
154360
154508
|
if (!this.warned) {
|
|
154361
|
-
console.error("[memorix] SessionStore: SQLite unavailable \u2014 sessions
|
|
154509
|
+
console.error("[memorix] SessionStore: SQLite unavailable \u2014 sessions cannot be read or written. Install a supported SQLite runtime.");
|
|
154362
154510
|
this.warned = true;
|
|
154363
154511
|
}
|
|
154364
154512
|
}
|
|
@@ -154366,33 +154514,39 @@ var init_session_store = __esm({
|
|
|
154366
154514
|
this.warn();
|
|
154367
154515
|
}
|
|
154368
154516
|
async loadAll() {
|
|
154369
|
-
|
|
154517
|
+
throw this.unavailableRead();
|
|
154370
154518
|
}
|
|
154371
154519
|
async getById(_id) {
|
|
154372
|
-
|
|
154520
|
+
throw this.unavailableRead();
|
|
154373
154521
|
}
|
|
154374
154522
|
async loadByProject(_projectId) {
|
|
154375
|
-
|
|
154523
|
+
throw this.unavailableRead();
|
|
154376
154524
|
}
|
|
154377
154525
|
async loadActive(_projectId) {
|
|
154378
|
-
|
|
154526
|
+
throw this.unavailableRead();
|
|
154379
154527
|
}
|
|
154380
154528
|
async insert(_session) {
|
|
154381
154529
|
this.warn();
|
|
154530
|
+
throw degradedWriteError("sessions");
|
|
154382
154531
|
}
|
|
154383
154532
|
async update(_session) {
|
|
154384
154533
|
this.warn();
|
|
154534
|
+
throw degradedWriteError("sessions");
|
|
154385
154535
|
}
|
|
154386
154536
|
async bulkUpdate(_sessions) {
|
|
154387
154537
|
this.warn();
|
|
154538
|
+
throw degradedWriteError("sessions");
|
|
154388
154539
|
}
|
|
154389
154540
|
async atomicRolloverInsert(_newSession, _projectIds, _now) {
|
|
154390
154541
|
this.warn();
|
|
154391
|
-
|
|
154542
|
+
throw degradedWriteError("sessions");
|
|
154392
154543
|
}
|
|
154393
154544
|
getBackendName() {
|
|
154394
154545
|
return "degraded";
|
|
154395
154546
|
}
|
|
154547
|
+
getBackendReason() {
|
|
154548
|
+
return this.reason;
|
|
154549
|
+
}
|
|
154396
154550
|
};
|
|
154397
154551
|
_store3 = null;
|
|
154398
154552
|
_storeDataDir3 = null;
|
|
@@ -159648,7 +159802,7 @@ var init_request_context = __esm({
|
|
|
159648
159802
|
function getMcpServerInfo() {
|
|
159649
159803
|
return {
|
|
159650
159804
|
name: "memorix",
|
|
159651
|
-
version: true ? "1.9.
|
|
159805
|
+
version: true ? "1.9.4" : "1.0.1"
|
|
159652
159806
|
};
|
|
159653
159807
|
}
|
|
159654
159808
|
function createMcpDiscoverResult(capabilities, serverInfo) {
|
|
@@ -174362,6 +174516,7 @@ ${lines.join("\n")}` }] };
|
|
|
174362
174516
|
} : {},
|
|
174363
174517
|
...mediaGenerationEnabled ? {
|
|
174364
174518
|
image: z627.string().optional().describe("Base64-encoded reference image for image-to-image generation."),
|
|
174519
|
+
firstFrameImageUrl: z627.string().optional().describe("Public HTTPS first-frame image URL for MiniMax video generation; stored with the queued job."),
|
|
174365
174520
|
region: z627.enum(["global", "cn"]).optional().describe("MiniMax deployment region."),
|
|
174366
174521
|
n: z627.number().int().min(1).max(4).optional().describe("Image output count."),
|
|
174367
174522
|
ratio: z627.enum(["adaptive", "1:1", "16:9", "4:3", "3:2", "2:3", "3:4", "9:16", "21:9"]).optional().describe("Image or video aspect ratio."),
|
|
@@ -174371,7 +174526,7 @@ ${lines.join("\n")}` }] };
|
|
|
174371
174526
|
} : {}
|
|
174372
174527
|
}
|
|
174373
174528
|
},
|
|
174374
|
-
async ({ action, path: assetPath, assetId, jobId, kind, limit: limit2, title, narrative, prompt, image, model, provider: provider2, language, region, n, ratio, width, height, duration, maxPages, maxChars, attach }) => {
|
|
174529
|
+
async ({ action, path: assetPath, assetId, jobId, kind, limit: limit2, title, narrative, prompt, image, firstFrameImageUrl, model, provider: provider2, language, region, n, ratio, width, height, duration, maxPages, maxChars, attach }) => {
|
|
174375
174530
|
const unresolved = requireResolvedProject("manage controlled media");
|
|
174376
174531
|
if (unresolved) return unresolved;
|
|
174377
174532
|
const safeError4 = (error) => sanitizeCredentials(
|
|
@@ -174541,6 +174696,7 @@ ${lines.join("\n")}` }] };
|
|
|
174541
174696
|
dataDir: projectDir2,
|
|
174542
174697
|
projectId: project.id,
|
|
174543
174698
|
prompt,
|
|
174699
|
+
firstFrameImageUrl,
|
|
174544
174700
|
...model === "MiniMax-H3" ? { model } : {},
|
|
174545
174701
|
...region ? { region } : {},
|
|
174546
174702
|
...videoRatio ? { ratio: videoRatio } : {},
|
|
@@ -175357,7 +175513,7 @@ var init_serve_shared = __esm({
|
|
|
175357
175513
|
|
|
175358
175514
|
// src/cli/version.ts
|
|
175359
175515
|
function getCliVersion() {
|
|
175360
|
-
return true ? "1.9.
|
|
175516
|
+
return true ? "1.9.4" : pkg.version;
|
|
175361
175517
|
}
|
|
175362
175518
|
var init_version3 = __esm({
|
|
175363
175519
|
"src/cli/version.ts"() {
|