@askexenow/exe-os 0.9.102 → 0.9.104
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/dist/bin/agentic-ontology-backfill.js +334 -100
- package/dist/bin/agentic-reflection-backfill.js +328 -97
- package/dist/bin/agentic-semantic-label.js +328 -97
- package/dist/bin/backfill-conversations.js +332 -97
- package/dist/bin/backfill-responses.js +332 -97
- package/dist/bin/backfill-vectors.js +337 -106
- package/dist/bin/bulk-sync-postgres.js +335 -101
- package/dist/bin/cleanup-stale-review-tasks.js +356 -108
- package/dist/bin/cli.js +653 -405
- package/dist/bin/exe-agent.js +21 -3
- package/dist/bin/exe-assign.js +338 -94
- package/dist/bin/exe-boot.js +472 -239
- package/dist/bin/exe-call.js +22 -5
- package/dist/bin/exe-cloud.js +404 -158
- package/dist/bin/exe-dispatch.js +390 -142
- package/dist/bin/exe-doctor.js +349 -103
- package/dist/bin/exe-export-behaviors.js +351 -105
- package/dist/bin/exe-forget.js +352 -103
- package/dist/bin/exe-gateway.js +420 -172
- package/dist/bin/exe-heartbeat.js +361 -113
- package/dist/bin/exe-kill.js +344 -98
- package/dist/bin/exe-launch-agent.js +375 -129
- package/dist/bin/exe-new-employee.js +83 -67
- package/dist/bin/exe-pending-messages.js +356 -108
- package/dist/bin/exe-pending-notifications.js +358 -110
- package/dist/bin/exe-pending-reviews.js +359 -111
- package/dist/bin/exe-rename.js +354 -108
- package/dist/bin/exe-review.js +343 -97
- package/dist/bin/exe-search.js +363 -113
- package/dist/bin/exe-session-cleanup.js +403 -155
- package/dist/bin/exe-settings.js +14 -9
- package/dist/bin/exe-start-codex.js +365 -131
- package/dist/bin/exe-start-opencode.js +359 -125
- package/dist/bin/exe-status.js +356 -108
- package/dist/bin/exe-team.js +343 -97
- package/dist/bin/git-sweep.js +390 -142
- package/dist/bin/graph-backfill.js +334 -100
- package/dist/bin/graph-export.js +346 -100
- package/dist/bin/install.js +1 -0
- package/dist/bin/intercom-check.js +403 -155
- package/dist/bin/pre-publish.js +12 -0
- package/dist/bin/scan-tasks.js +393 -145
- package/dist/bin/setup.js +331 -159
- package/dist/bin/shard-migrate.js +328 -94
- package/dist/gateway/index.js +406 -158
- package/dist/hooks/bug-report-worker.js +396 -148
- package/dist/hooks/codex-stop-task-finalizer.js +374 -126
- package/dist/hooks/commit-complete.js +390 -142
- package/dist/hooks/error-recall.js +365 -115
- package/dist/hooks/ingest.js +357 -111
- package/dist/hooks/instructions-loaded.js +351 -105
- package/dist/hooks/notification.js +343 -97
- package/dist/hooks/post-compact.js +358 -110
- package/dist/hooks/post-tool-combined.js +384 -132
- package/dist/hooks/pre-compact.js +391 -143
- package/dist/hooks/pre-tool-use.js +362 -114
- package/dist/hooks/prompt-submit.js +422 -170
- package/dist/hooks/session-end.js +393 -145
- package/dist/hooks/session-start.js +390 -138
- package/dist/hooks/stop.js +361 -113
- package/dist/hooks/subagent-stop.js +354 -106
- package/dist/hooks/summary-worker.js +418 -185
- package/dist/index.js +400 -152
- package/dist/lib/cloud-sync.js +291 -131
- package/dist/lib/consolidation.js +8 -2
- package/dist/lib/database.js +233 -73
- package/dist/lib/db.js +233 -73
- package/dist/lib/device-registry.js +237 -77
- package/dist/lib/employee-templates.js +19 -1
- package/dist/lib/exe-daemon.js +705 -409
- package/dist/lib/hybrid-search.js +363 -113
- package/dist/lib/identity.js +9 -5
- package/dist/lib/messaging.js +26 -20
- package/dist/lib/reminders.js +5 -1
- package/dist/lib/schedules.js +320 -89
- package/dist/lib/skill-learning.js +28 -24
- package/dist/lib/store.js +342 -96
- package/dist/lib/tasks.js +82 -76
- package/dist/lib/tmux-routing.js +74 -68
- package/dist/lib/token-spend.js +5 -1
- package/dist/mcp/server.js +628 -355
- package/dist/mcp/tools/complete-reminder.js +5 -1
- package/dist/mcp/tools/create-reminder.js +5 -1
- package/dist/mcp/tools/create-task.js +89 -83
- package/dist/mcp/tools/deactivate-behavior.js +7 -3
- package/dist/mcp/tools/list-reminders.js +5 -1
- package/dist/mcp/tools/list-tasks.js +28 -21
- package/dist/mcp/tools/send-message.js +28 -22
- package/dist/mcp/tools/update-task.js +89 -83
- package/dist/runtime/index.js +390 -142
- package/dist/tui/App.js +437 -189
- package/package.json +1 -1
|
@@ -2261,9 +2261,79 @@ __export(database_exports, {
|
|
|
2261
2261
|
isInitialized: () => isInitialized,
|
|
2262
2262
|
setExternalClient: () => setExternalClient
|
|
2263
2263
|
});
|
|
2264
|
-
import { chmodSync as chmodSync2 } from "fs";
|
|
2264
|
+
import { chmodSync as chmodSync2, existsSync as existsSync9, statSync as statSync2, copyFileSync, unlinkSync as unlinkSync3, openSync as openSync2, closeSync as closeSync2, mkdirSync as mkdirSync4 } from "fs";
|
|
2265
2265
|
import { createClient } from "@libsql/client";
|
|
2266
|
+
import { homedir } from "os";
|
|
2267
|
+
import { join } from "path";
|
|
2268
|
+
function logCatchDebug(context, err) {
|
|
2269
|
+
if (_debugDb) {
|
|
2270
|
+
process.stderr.write(
|
|
2271
|
+
`[database] ${context}: ${err instanceof Error ? err.message : String(err)}
|
|
2272
|
+
`
|
|
2273
|
+
);
|
|
2274
|
+
}
|
|
2275
|
+
}
|
|
2276
|
+
function acquireDbLock() {
|
|
2277
|
+
mkdirSync4(join(homedir(), ".exe-os"), { recursive: true });
|
|
2278
|
+
try {
|
|
2279
|
+
_lockFd = openSync2(DB_LOCK_PATH, "wx");
|
|
2280
|
+
} catch (err) {
|
|
2281
|
+
if (err && typeof err === "object" && "code" in err && err.code === "EEXIST") {
|
|
2282
|
+
try {
|
|
2283
|
+
const lockStat = statSync2(DB_LOCK_PATH);
|
|
2284
|
+
if (Date.now() - lockStat.mtimeMs > 6e4) {
|
|
2285
|
+
unlinkSync3(DB_LOCK_PATH);
|
|
2286
|
+
_lockFd = openSync2(DB_LOCK_PATH, "wx");
|
|
2287
|
+
return;
|
|
2288
|
+
}
|
|
2289
|
+
} catch (e) {
|
|
2290
|
+
logCatchDebug("stale lock check", e);
|
|
2291
|
+
}
|
|
2292
|
+
process.stderr.write(
|
|
2293
|
+
"[database] WARN: Another process holds db.lock \u2014 waiting briefly then proceeding.\n"
|
|
2294
|
+
);
|
|
2295
|
+
return;
|
|
2296
|
+
}
|
|
2297
|
+
throw err;
|
|
2298
|
+
}
|
|
2299
|
+
}
|
|
2300
|
+
function releaseDbLock() {
|
|
2301
|
+
if (_lockFd !== null) {
|
|
2302
|
+
try {
|
|
2303
|
+
closeSync2(_lockFd);
|
|
2304
|
+
} catch (e) {
|
|
2305
|
+
logCatchDebug("lock close", e);
|
|
2306
|
+
}
|
|
2307
|
+
_lockFd = null;
|
|
2308
|
+
}
|
|
2309
|
+
try {
|
|
2310
|
+
unlinkSync3(DB_LOCK_PATH);
|
|
2311
|
+
} catch (e) {
|
|
2312
|
+
logCatchDebug("lock unlink", e);
|
|
2313
|
+
}
|
|
2314
|
+
}
|
|
2266
2315
|
async function initDatabase(config) {
|
|
2316
|
+
acquireDbLock();
|
|
2317
|
+
if (existsSync9(config.dbPath)) {
|
|
2318
|
+
const dbStat = statSync2(config.dbPath);
|
|
2319
|
+
if (dbStat.size === 0) {
|
|
2320
|
+
const walPath = config.dbPath + "-wal";
|
|
2321
|
+
if (existsSync9(walPath) && statSync2(walPath).size > 0) {
|
|
2322
|
+
const backupPath = config.dbPath + ".zeroed-" + Date.now();
|
|
2323
|
+
copyFileSync(config.dbPath, backupPath);
|
|
2324
|
+
unlinkSync3(config.dbPath);
|
|
2325
|
+
process.stderr.write(
|
|
2326
|
+
`[database] CRITICAL: DB was 0 bytes. Moved to ${backupPath}, attempting WAL recovery.
|
|
2327
|
+
`
|
|
2328
|
+
);
|
|
2329
|
+
} else {
|
|
2330
|
+
process.stderr.write(
|
|
2331
|
+
`[database] CRITICAL: DB is 0 bytes and no WAL available for recovery. Data may be lost. Check backups at ${config.dbPath}.bak
|
|
2332
|
+
`
|
|
2333
|
+
);
|
|
2334
|
+
}
|
|
2335
|
+
}
|
|
2336
|
+
}
|
|
2267
2337
|
if (_walCheckpointTimer) {
|
|
2268
2338
|
clearInterval(_walCheckpointTimer);
|
|
2269
2339
|
_walCheckpointTimer = null;
|
|
@@ -2290,10 +2360,8 @@ async function initDatabase(config) {
|
|
|
2290
2360
|
_client = createClient(opts);
|
|
2291
2361
|
_resilientClient = wrapWithRetry(_client);
|
|
2292
2362
|
_adapterClient = _resilientClient;
|
|
2293
|
-
_client.execute("PRAGMA busy_timeout = 30000")
|
|
2294
|
-
|
|
2295
|
-
_client.execute("PRAGMA journal_mode = WAL").catch(() => {
|
|
2296
|
-
});
|
|
2363
|
+
await _client.execute("PRAGMA busy_timeout = 30000");
|
|
2364
|
+
await _client.execute("PRAGMA journal_mode = WAL");
|
|
2297
2365
|
if (_walCheckpointTimer) clearInterval(_walCheckpointTimer);
|
|
2298
2366
|
_walCheckpointTimer = setInterval(() => {
|
|
2299
2367
|
_client?.execute("PRAGMA wal_checkpoint(PASSIVE)").catch(() => {
|
|
@@ -2308,11 +2376,16 @@ async function initDatabase(config) {
|
|
|
2308
2376
|
for (const suffix of ["-wal", "-shm"]) {
|
|
2309
2377
|
try {
|
|
2310
2378
|
chmodSync2(config.dbPath + suffix, 384);
|
|
2311
|
-
} catch {
|
|
2379
|
+
} catch (chmodErr) {
|
|
2380
|
+
process.stderr.write(`[database] chmod ${suffix} failed: ${chmodErr instanceof Error ? chmodErr.message : String(chmodErr)}
|
|
2381
|
+
`);
|
|
2312
2382
|
}
|
|
2313
2383
|
}
|
|
2314
|
-
} catch {
|
|
2384
|
+
} catch (chmodErr) {
|
|
2385
|
+
process.stderr.write(`[database] chmod db failed: ${chmodErr instanceof Error ? chmodErr.message : String(chmodErr)}
|
|
2386
|
+
`);
|
|
2315
2387
|
}
|
|
2388
|
+
releaseDbLock();
|
|
2316
2389
|
}
|
|
2317
2390
|
function isInitialized() {
|
|
2318
2391
|
return _adapterClient !== null || _client !== null;
|
|
@@ -2367,7 +2440,8 @@ async function ensureSchema() {
|
|
|
2367
2440
|
await client.execute("PRAGMA wal_autocheckpoint = 1000");
|
|
2368
2441
|
try {
|
|
2369
2442
|
await client.execute("PRAGMA libsql_vector_search_ef = 128");
|
|
2370
|
-
} catch {
|
|
2443
|
+
} catch (e) {
|
|
2444
|
+
logCatchDebug("migration", e);
|
|
2371
2445
|
}
|
|
2372
2446
|
await client.executeMultiple(`
|
|
2373
2447
|
CREATE TABLE IF NOT EXISTS memories (
|
|
@@ -2432,6 +2506,23 @@ async function ensureSchema() {
|
|
|
2432
2506
|
INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
|
|
2433
2507
|
END;
|
|
2434
2508
|
`);
|
|
2509
|
+
try {
|
|
2510
|
+
await client.execute("SELECT COUNT(*) FROM memories_fts LIMIT 1");
|
|
2511
|
+
} catch (ftsErr) {
|
|
2512
|
+
process.stderr.write(
|
|
2513
|
+
`[database] WARN: memories_fts corrupted (${ftsErr instanceof Error ? ftsErr.message : String(ftsErr)}) \u2014 rebuilding FTS index.
|
|
2514
|
+
`
|
|
2515
|
+
);
|
|
2516
|
+
try {
|
|
2517
|
+
await client.execute("INSERT INTO memories_fts(memories_fts) VALUES('rebuild')");
|
|
2518
|
+
process.stderr.write("[database] FTS index rebuilt successfully.\n");
|
|
2519
|
+
} catch (rebuildErr) {
|
|
2520
|
+
process.stderr.write(
|
|
2521
|
+
`[database] ERROR: FTS rebuild failed: ${rebuildErr instanceof Error ? rebuildErr.message : String(rebuildErr)}
|
|
2522
|
+
`
|
|
2523
|
+
);
|
|
2524
|
+
}
|
|
2525
|
+
}
|
|
2435
2526
|
await client.executeMultiple(`
|
|
2436
2527
|
CREATE TABLE IF NOT EXISTS sync_meta (
|
|
2437
2528
|
key TEXT PRIMARY KEY,
|
|
@@ -2490,35 +2581,40 @@ async function ensureSchema() {
|
|
|
2490
2581
|
});
|
|
2491
2582
|
}
|
|
2492
2583
|
}
|
|
2493
|
-
} catch {
|
|
2584
|
+
} catch (seedErr) {
|
|
2585
|
+
logCatchDebug("behavior seed", seedErr);
|
|
2494
2586
|
}
|
|
2495
2587
|
try {
|
|
2496
2588
|
await client.execute({
|
|
2497
2589
|
sql: `ALTER TABLE behaviors ADD COLUMN priority TEXT DEFAULT 'p1'`,
|
|
2498
2590
|
args: []
|
|
2499
2591
|
});
|
|
2500
|
-
} catch {
|
|
2592
|
+
} catch (e) {
|
|
2593
|
+
logCatchDebug("migration", e);
|
|
2501
2594
|
}
|
|
2502
2595
|
try {
|
|
2503
2596
|
await client.execute({
|
|
2504
2597
|
sql: `ALTER TABLE behaviors ADD COLUMN vector F32_BLOB(${EMBEDDING_DIM})`,
|
|
2505
2598
|
args: []
|
|
2506
2599
|
});
|
|
2507
|
-
} catch {
|
|
2600
|
+
} catch (e) {
|
|
2601
|
+
logCatchDebug("migration", e);
|
|
2508
2602
|
}
|
|
2509
2603
|
try {
|
|
2510
2604
|
await client.execute({
|
|
2511
2605
|
sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
|
|
2512
2606
|
args: []
|
|
2513
2607
|
});
|
|
2514
|
-
} catch {
|
|
2608
|
+
} catch (e) {
|
|
2609
|
+
logCatchDebug("migration", e);
|
|
2515
2610
|
}
|
|
2516
2611
|
try {
|
|
2517
2612
|
await client.execute({
|
|
2518
2613
|
sql: `ALTER TABLE tasks ADD COLUMN parent_task_id TEXT`,
|
|
2519
2614
|
args: []
|
|
2520
2615
|
});
|
|
2521
|
-
} catch {
|
|
2616
|
+
} catch (e) {
|
|
2617
|
+
logCatchDebug("migration", e);
|
|
2522
2618
|
}
|
|
2523
2619
|
try {
|
|
2524
2620
|
await client.execute({
|
|
@@ -2527,98 +2623,112 @@ async function ensureSchema() {
|
|
|
2527
2623
|
WHERE parent_task_id IS NOT NULL`,
|
|
2528
2624
|
args: []
|
|
2529
2625
|
});
|
|
2530
|
-
} catch {
|
|
2626
|
+
} catch (e) {
|
|
2627
|
+
logCatchDebug("migration", e);
|
|
2531
2628
|
}
|
|
2532
2629
|
try {
|
|
2533
2630
|
await client.execute({
|
|
2534
2631
|
sql: `UPDATE tasks SET status = 'done' WHERE status = 'completed'`,
|
|
2535
2632
|
args: []
|
|
2536
2633
|
});
|
|
2537
|
-
} catch {
|
|
2634
|
+
} catch (e) {
|
|
2635
|
+
logCatchDebug("migration", e);
|
|
2538
2636
|
}
|
|
2539
2637
|
try {
|
|
2540
2638
|
await client.execute({
|
|
2541
2639
|
sql: `ALTER TABLE tasks ADD COLUMN reviewer TEXT`,
|
|
2542
2640
|
args: []
|
|
2543
2641
|
});
|
|
2544
|
-
} catch {
|
|
2642
|
+
} catch (e) {
|
|
2643
|
+
logCatchDebug("migration", e);
|
|
2545
2644
|
}
|
|
2546
2645
|
try {
|
|
2547
2646
|
await client.execute({
|
|
2548
2647
|
sql: `ALTER TABLE tasks ADD COLUMN context TEXT`,
|
|
2549
2648
|
args: []
|
|
2550
2649
|
});
|
|
2551
|
-
} catch {
|
|
2650
|
+
} catch (e) {
|
|
2651
|
+
logCatchDebug("migration", e);
|
|
2552
2652
|
}
|
|
2553
2653
|
try {
|
|
2554
2654
|
await client.execute({
|
|
2555
2655
|
sql: `ALTER TABLE tasks ADD COLUMN result TEXT`,
|
|
2556
2656
|
args: []
|
|
2557
2657
|
});
|
|
2558
|
-
} catch {
|
|
2658
|
+
} catch (e) {
|
|
2659
|
+
logCatchDebug("migration", e);
|
|
2559
2660
|
}
|
|
2560
2661
|
try {
|
|
2561
2662
|
await client.execute({
|
|
2562
2663
|
sql: `ALTER TABLE tasks ADD COLUMN assigned_tmux TEXT`,
|
|
2563
2664
|
args: []
|
|
2564
2665
|
});
|
|
2565
|
-
} catch {
|
|
2666
|
+
} catch (e) {
|
|
2667
|
+
logCatchDebug("migration", e);
|
|
2566
2668
|
}
|
|
2567
2669
|
try {
|
|
2568
2670
|
await client.execute({
|
|
2569
2671
|
sql: `ALTER TABLE tasks ADD COLUMN checkpoint TEXT`,
|
|
2570
2672
|
args: []
|
|
2571
2673
|
});
|
|
2572
|
-
} catch {
|
|
2674
|
+
} catch (e) {
|
|
2675
|
+
logCatchDebug("migration", e);
|
|
2573
2676
|
}
|
|
2574
2677
|
try {
|
|
2575
2678
|
await client.execute({
|
|
2576
2679
|
sql: `ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER NOT NULL DEFAULT 0`,
|
|
2577
2680
|
args: []
|
|
2578
2681
|
});
|
|
2579
|
-
} catch {
|
|
2682
|
+
} catch (e) {
|
|
2683
|
+
logCatchDebug("migration", e);
|
|
2580
2684
|
}
|
|
2581
2685
|
try {
|
|
2582
2686
|
await client.execute({
|
|
2583
2687
|
sql: `ALTER TABLE tasks ADD COLUMN complexity TEXT NOT NULL DEFAULT 'standard'`,
|
|
2584
2688
|
args: []
|
|
2585
2689
|
});
|
|
2586
|
-
} catch {
|
|
2690
|
+
} catch (e) {
|
|
2691
|
+
logCatchDebug("migration", e);
|
|
2587
2692
|
}
|
|
2588
2693
|
try {
|
|
2589
2694
|
await client.execute({
|
|
2590
2695
|
sql: `ALTER TABLE tasks ADD COLUMN session_scope TEXT`,
|
|
2591
2696
|
args: []
|
|
2592
2697
|
});
|
|
2593
|
-
} catch {
|
|
2698
|
+
} catch (e) {
|
|
2699
|
+
logCatchDebug("migration", e);
|
|
2594
2700
|
}
|
|
2595
2701
|
try {
|
|
2596
2702
|
await client.execute({
|
|
2597
2703
|
sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
|
|
2598
2704
|
args: []
|
|
2599
2705
|
});
|
|
2600
|
-
} catch {
|
|
2706
|
+
} catch (e) {
|
|
2707
|
+
logCatchDebug("migration", e);
|
|
2601
2708
|
}
|
|
2602
2709
|
try {
|
|
2603
2710
|
await client.execute({
|
|
2604
2711
|
sql: `ALTER TABLE memories ADD COLUMN consolidated INTEGER NOT NULL DEFAULT 0`,
|
|
2605
2712
|
args: []
|
|
2606
2713
|
});
|
|
2607
|
-
} catch {
|
|
2714
|
+
} catch (e) {
|
|
2715
|
+
logCatchDebug("migration", e);
|
|
2608
2716
|
}
|
|
2609
2717
|
try {
|
|
2610
2718
|
await client.execute({
|
|
2611
2719
|
sql: `ALTER TABLE memories ADD COLUMN author_device_id TEXT`,
|
|
2612
2720
|
args: []
|
|
2613
2721
|
});
|
|
2614
|
-
} catch {
|
|
2722
|
+
} catch (e) {
|
|
2723
|
+
logCatchDebug("migration", e);
|
|
2615
2724
|
}
|
|
2616
2725
|
try {
|
|
2617
2726
|
await client.execute({
|
|
2618
2727
|
sql: `ALTER TABLE memories ADD COLUMN scope TEXT NOT NULL DEFAULT 'business'`,
|
|
2619
2728
|
args: []
|
|
2620
2729
|
});
|
|
2621
|
-
} catch {
|
|
2730
|
+
} catch (e) {
|
|
2731
|
+
logCatchDebug("migration", e);
|
|
2622
2732
|
}
|
|
2623
2733
|
await client.executeMultiple(`
|
|
2624
2734
|
CREATE TABLE IF NOT EXISTS consolidations (
|
|
@@ -2723,14 +2833,16 @@ async function ensureSchema() {
|
|
|
2723
2833
|
sql: `ALTER TABLE notifications ADD COLUMN session_scope TEXT`,
|
|
2724
2834
|
args: []
|
|
2725
2835
|
});
|
|
2726
|
-
} catch {
|
|
2836
|
+
} catch (e) {
|
|
2837
|
+
logCatchDebug("migration", e);
|
|
2727
2838
|
}
|
|
2728
2839
|
try {
|
|
2729
2840
|
await client.execute({
|
|
2730
2841
|
sql: `ALTER TABLE messages ADD COLUMN session_scope TEXT`,
|
|
2731
2842
|
args: []
|
|
2732
2843
|
});
|
|
2733
|
-
} catch {
|
|
2844
|
+
} catch (e) {
|
|
2845
|
+
logCatchDebug("migration", e);
|
|
2734
2846
|
}
|
|
2735
2847
|
await client.executeMultiple(`
|
|
2736
2848
|
CREATE INDEX IF NOT EXISTS idx_notifications_agent_scope_read
|
|
@@ -2756,7 +2868,8 @@ async function ensureSchema() {
|
|
|
2756
2868
|
sql: `UPDATE tasks SET project_name = 'exe-os' WHERE project_name = 'worker'`,
|
|
2757
2869
|
args: []
|
|
2758
2870
|
});
|
|
2759
|
-
} catch {
|
|
2871
|
+
} catch (e) {
|
|
2872
|
+
logCatchDebug("migration", e);
|
|
2760
2873
|
}
|
|
2761
2874
|
await client.executeMultiple(`
|
|
2762
2875
|
CREATE TABLE IF NOT EXISTS trajectories (
|
|
@@ -2780,7 +2893,8 @@ async function ensureSchema() {
|
|
|
2780
2893
|
`);
|
|
2781
2894
|
try {
|
|
2782
2895
|
await client.execute("ALTER TABLE trajectories ADD COLUMN skill_id TEXT");
|
|
2783
|
-
} catch {
|
|
2896
|
+
} catch (e) {
|
|
2897
|
+
logCatchDebug("migration", e);
|
|
2784
2898
|
}
|
|
2785
2899
|
await client.executeMultiple(`
|
|
2786
2900
|
CREATE TABLE IF NOT EXISTS consolidations (
|
|
@@ -2817,63 +2931,72 @@ async function ensureSchema() {
|
|
|
2817
2931
|
sql: `ALTER TABLE memories ADD COLUMN consolidated INTEGER NOT NULL DEFAULT 0`,
|
|
2818
2932
|
args: []
|
|
2819
2933
|
});
|
|
2820
|
-
} catch {
|
|
2934
|
+
} catch (e) {
|
|
2935
|
+
logCatchDebug("migration", e);
|
|
2821
2936
|
}
|
|
2822
2937
|
try {
|
|
2823
2938
|
await client.execute({
|
|
2824
2939
|
sql: `ALTER TABLE memories ADD COLUMN importance INTEGER DEFAULT 5`,
|
|
2825
2940
|
args: []
|
|
2826
2941
|
});
|
|
2827
|
-
} catch {
|
|
2942
|
+
} catch (e) {
|
|
2943
|
+
logCatchDebug("migration", e);
|
|
2828
2944
|
}
|
|
2829
2945
|
try {
|
|
2830
2946
|
await client.execute({
|
|
2831
2947
|
sql: `ALTER TABLE memories ADD COLUMN status TEXT DEFAULT 'active'`,
|
|
2832
2948
|
args: []
|
|
2833
2949
|
});
|
|
2834
|
-
} catch {
|
|
2950
|
+
} catch (e) {
|
|
2951
|
+
logCatchDebug("migration", e);
|
|
2835
2952
|
}
|
|
2836
2953
|
try {
|
|
2837
2954
|
await client.execute({
|
|
2838
2955
|
sql: `ALTER TABLE memories ADD COLUMN deleted_at TEXT`,
|
|
2839
2956
|
args: []
|
|
2840
2957
|
});
|
|
2841
|
-
} catch {
|
|
2958
|
+
} catch (e) {
|
|
2959
|
+
logCatchDebug("migration", e);
|
|
2842
2960
|
}
|
|
2843
2961
|
try {
|
|
2844
2962
|
await client.execute({
|
|
2845
2963
|
sql: `ALTER TABLE memories ADD COLUMN confidence REAL DEFAULT 0.7`,
|
|
2846
2964
|
args: []
|
|
2847
2965
|
});
|
|
2848
|
-
} catch {
|
|
2966
|
+
} catch (e) {
|
|
2967
|
+
logCatchDebug("migration", e);
|
|
2849
2968
|
}
|
|
2850
2969
|
try {
|
|
2851
2970
|
await client.execute({
|
|
2852
2971
|
sql: `ALTER TABLE memories ADD COLUMN last_accessed TEXT`,
|
|
2853
2972
|
args: []
|
|
2854
2973
|
});
|
|
2855
|
-
} catch {
|
|
2974
|
+
} catch (e) {
|
|
2975
|
+
logCatchDebug("migration", e);
|
|
2856
2976
|
}
|
|
2857
2977
|
try {
|
|
2858
2978
|
await client.execute({
|
|
2859
2979
|
sql: `UPDATE memories SET last_accessed = timestamp WHERE last_accessed IS NULL`,
|
|
2860
2980
|
args: []
|
|
2861
2981
|
});
|
|
2862
|
-
} catch {
|
|
2982
|
+
} catch (e) {
|
|
2983
|
+
logCatchDebug("migration", e);
|
|
2863
2984
|
}
|
|
2864
2985
|
try {
|
|
2865
2986
|
await client.execute({
|
|
2866
2987
|
sql: `ALTER TABLE memories ADD COLUMN wiki_synced INTEGER DEFAULT 0`,
|
|
2867
2988
|
args: []
|
|
2868
2989
|
});
|
|
2869
|
-
} catch {
|
|
2990
|
+
} catch (e) {
|
|
2991
|
+
logCatchDebug("migration", e);
|
|
2870
2992
|
}
|
|
2871
2993
|
try {
|
|
2872
2994
|
await client.execute({
|
|
2873
2995
|
sql: `ALTER TABLE memories ADD COLUMN graph_extracted INTEGER DEFAULT 0`,
|
|
2874
2996
|
args: []
|
|
2875
2997
|
});
|
|
2876
|
-
} catch {
|
|
2998
|
+
} catch (e) {
|
|
2999
|
+
logCatchDebug("migration", e);
|
|
2877
3000
|
}
|
|
2878
3001
|
for (const col of [
|
|
2879
3002
|
"ALTER TABLE memories ADD COLUMN content_hash TEXT",
|
|
@@ -2881,14 +3004,16 @@ async function ensureSchema() {
|
|
|
2881
3004
|
]) {
|
|
2882
3005
|
try {
|
|
2883
3006
|
await client.execute(col);
|
|
2884
|
-
} catch {
|
|
3007
|
+
} catch (e) {
|
|
3008
|
+
logCatchDebug("migration", e);
|
|
2885
3009
|
}
|
|
2886
3010
|
}
|
|
2887
3011
|
try {
|
|
2888
3012
|
await client.execute(
|
|
2889
3013
|
`CREATE INDEX IF NOT EXISTS idx_memories_content_hash ON memories(content_hash, agent_id)`
|
|
2890
3014
|
);
|
|
2891
|
-
} catch {
|
|
3015
|
+
} catch (e) {
|
|
3016
|
+
logCatchDebug("migration", e);
|
|
2892
3017
|
}
|
|
2893
3018
|
try {
|
|
2894
3019
|
await client.execute(
|
|
@@ -2896,7 +3021,8 @@ async function ensureSchema() {
|
|
|
2896
3021
|
ON memories(content_hash, agent_id, project_name, memory_type)
|
|
2897
3022
|
WHERE content_hash IS NOT NULL`
|
|
2898
3023
|
);
|
|
2899
|
-
} catch {
|
|
3024
|
+
} catch (e) {
|
|
3025
|
+
logCatchDebug("migration", e);
|
|
2900
3026
|
}
|
|
2901
3027
|
await client.executeMultiple(`
|
|
2902
3028
|
CREATE TABLE IF NOT EXISTS entities (
|
|
@@ -2972,7 +3098,8 @@ async function ensureSchema() {
|
|
|
2972
3098
|
`);
|
|
2973
3099
|
try {
|
|
2974
3100
|
await client.execute("INSERT INTO entities_fts(entities_fts) VALUES('rebuild')");
|
|
2975
|
-
} catch {
|
|
3101
|
+
} catch (e) {
|
|
3102
|
+
logCatchDebug("migration", e);
|
|
2976
3103
|
}
|
|
2977
3104
|
await client.executeMultiple(`
|
|
2978
3105
|
CREATE TABLE IF NOT EXISTS entity_aliases (
|
|
@@ -2987,14 +3114,16 @@ async function ensureSchema() {
|
|
|
2987
3114
|
]) {
|
|
2988
3115
|
try {
|
|
2989
3116
|
await client.execute(col);
|
|
2990
|
-
} catch {
|
|
3117
|
+
} catch (e) {
|
|
3118
|
+
logCatchDebug("migration", e);
|
|
2991
3119
|
}
|
|
2992
3120
|
}
|
|
2993
3121
|
try {
|
|
2994
3122
|
await client.execute(
|
|
2995
3123
|
`CREATE INDEX IF NOT EXISTS idx_memories_status ON memories(status)`
|
|
2996
3124
|
);
|
|
2997
|
-
} catch {
|
|
3125
|
+
} catch (e) {
|
|
3126
|
+
logCatchDebug("migration", e);
|
|
2998
3127
|
}
|
|
2999
3128
|
await client.executeMultiple(`
|
|
3000
3129
|
CREATE TABLE IF NOT EXISTS identity (
|
|
@@ -3093,7 +3222,8 @@ async function ensureSchema() {
|
|
|
3093
3222
|
sql: `ALTER TABLE memories ADD COLUMN ${column}`,
|
|
3094
3223
|
args: []
|
|
3095
3224
|
});
|
|
3096
|
-
} catch {
|
|
3225
|
+
} catch (e) {
|
|
3226
|
+
logCatchDebug("migration", e);
|
|
3097
3227
|
}
|
|
3098
3228
|
}
|
|
3099
3229
|
for (const col of [
|
|
@@ -3102,7 +3232,8 @@ async function ensureSchema() {
|
|
|
3102
3232
|
]) {
|
|
3103
3233
|
try {
|
|
3104
3234
|
await client.execute(col);
|
|
3105
|
-
} catch {
|
|
3235
|
+
} catch (e) {
|
|
3236
|
+
logCatchDebug("migration", e);
|
|
3106
3237
|
}
|
|
3107
3238
|
}
|
|
3108
3239
|
await client.executeMultiple(`
|
|
@@ -3287,56 +3418,64 @@ async function ensureSchema() {
|
|
|
3287
3418
|
args: []
|
|
3288
3419
|
});
|
|
3289
3420
|
}
|
|
3290
|
-
} catch {
|
|
3421
|
+
} catch (e) {
|
|
3422
|
+
logCatchDebug("session_agent_map backfill", e);
|
|
3291
3423
|
}
|
|
3292
3424
|
try {
|
|
3293
3425
|
await client.execute({
|
|
3294
3426
|
sql: `ALTER TABLE session_agent_map ADD COLUMN cache_cold_count INTEGER NOT NULL DEFAULT 0`,
|
|
3295
3427
|
args: []
|
|
3296
3428
|
});
|
|
3297
|
-
} catch {
|
|
3429
|
+
} catch (e) {
|
|
3430
|
+
logCatchDebug("migration", e);
|
|
3298
3431
|
}
|
|
3299
3432
|
try {
|
|
3300
3433
|
await client.execute({
|
|
3301
3434
|
sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
|
|
3302
3435
|
args: []
|
|
3303
3436
|
});
|
|
3304
|
-
} catch {
|
|
3437
|
+
} catch (e) {
|
|
3438
|
+
logCatchDebug("migration", e);
|
|
3305
3439
|
}
|
|
3306
3440
|
try {
|
|
3307
3441
|
await client.execute({
|
|
3308
3442
|
sql: `ALTER TABLE tasks ADD COLUMN budget_fallback_model TEXT`,
|
|
3309
3443
|
args: []
|
|
3310
3444
|
});
|
|
3311
|
-
} catch {
|
|
3445
|
+
} catch (e) {
|
|
3446
|
+
logCatchDebug("migration", e);
|
|
3312
3447
|
}
|
|
3313
3448
|
try {
|
|
3314
3449
|
await client.execute({
|
|
3315
3450
|
sql: `ALTER TABLE tasks ADD COLUMN tokens_used INTEGER DEFAULT 0`,
|
|
3316
3451
|
args: []
|
|
3317
3452
|
});
|
|
3318
|
-
} catch {
|
|
3453
|
+
} catch (e) {
|
|
3454
|
+
logCatchDebug("migration", e);
|
|
3319
3455
|
}
|
|
3320
3456
|
try {
|
|
3321
3457
|
await client.execute({
|
|
3322
3458
|
sql: `ALTER TABLE tasks ADD COLUMN tokens_warned_at INTEGER`,
|
|
3323
3459
|
args: []
|
|
3324
3460
|
});
|
|
3325
|
-
} catch {
|
|
3461
|
+
} catch (e) {
|
|
3462
|
+
logCatchDebug("migration", e);
|
|
3326
3463
|
}
|
|
3327
3464
|
try {
|
|
3328
3465
|
await client.execute({
|
|
3329
3466
|
sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
|
|
3330
3467
|
args: []
|
|
3331
3468
|
});
|
|
3332
|
-
} catch {
|
|
3469
|
+
} catch (e) {
|
|
3470
|
+
logCatchDebug("migration", e);
|
|
3333
3471
|
}
|
|
3334
3472
|
try {
|
|
3335
3473
|
await client.execute({
|
|
3336
3474
|
sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
|
|
3337
3475
|
args: []
|
|
3338
3476
|
});
|
|
3339
|
-
} catch {
|
|
3477
|
+
} catch (e) {
|
|
3478
|
+
logCatchDebug("migration", e);
|
|
3340
3479
|
}
|
|
3341
3480
|
await client.executeMultiple(`
|
|
3342
3481
|
CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
|
|
@@ -3535,13 +3674,15 @@ async function ensureSchema() {
|
|
|
3535
3674
|
sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
|
|
3536
3675
|
args: []
|
|
3537
3676
|
});
|
|
3538
|
-
} catch {
|
|
3677
|
+
} catch (e) {
|
|
3678
|
+
logCatchDebug("migration", e);
|
|
3539
3679
|
}
|
|
3540
3680
|
try {
|
|
3541
3681
|
await client.execute(
|
|
3542
3682
|
`CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)`
|
|
3543
3683
|
);
|
|
3544
|
-
} catch {
|
|
3684
|
+
} catch (e) {
|
|
3685
|
+
logCatchDebug("migration", e);
|
|
3545
3686
|
}
|
|
3546
3687
|
try {
|
|
3547
3688
|
await client.execute({
|
|
@@ -3552,20 +3693,23 @@ async function ensureSchema() {
|
|
|
3552
3693
|
sql: `UPDATE memories SET tier = 2 WHERE tool_name IN ('store_memory', 'manual') AND importance >= 5 AND tier = 3`,
|
|
3553
3694
|
args: []
|
|
3554
3695
|
});
|
|
3555
|
-
} catch {
|
|
3696
|
+
} catch (e) {
|
|
3697
|
+
logCatchDebug("migration", e);
|
|
3556
3698
|
}
|
|
3557
3699
|
try {
|
|
3558
3700
|
await client.execute({
|
|
3559
3701
|
sql: `ALTER TABLE memories ADD COLUMN supersedes_id TEXT`,
|
|
3560
3702
|
args: []
|
|
3561
3703
|
});
|
|
3562
|
-
} catch {
|
|
3704
|
+
} catch (e) {
|
|
3705
|
+
logCatchDebug("migration", e);
|
|
3563
3706
|
}
|
|
3564
3707
|
try {
|
|
3565
3708
|
await client.execute(
|
|
3566
3709
|
`CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL`
|
|
3567
3710
|
);
|
|
3568
|
-
} catch {
|
|
3711
|
+
} catch (e) {
|
|
3712
|
+
logCatchDebug("migration", e);
|
|
3569
3713
|
}
|
|
3570
3714
|
for (const col of [
|
|
3571
3715
|
"ALTER TABLE tasks ADD COLUMN checkpoint TEXT",
|
|
@@ -3573,7 +3717,8 @@ async function ensureSchema() {
|
|
|
3573
3717
|
]) {
|
|
3574
3718
|
try {
|
|
3575
3719
|
await client.execute(col);
|
|
3576
|
-
} catch {
|
|
3720
|
+
} catch (e) {
|
|
3721
|
+
logCatchDebug("migration", e);
|
|
3577
3722
|
}
|
|
3578
3723
|
}
|
|
3579
3724
|
try {
|
|
@@ -3581,13 +3726,15 @@ async function ensureSchema() {
|
|
|
3581
3726
|
sql: `ALTER TABLE memories ADD COLUMN draft INTEGER DEFAULT 0`,
|
|
3582
3727
|
args: []
|
|
3583
3728
|
});
|
|
3584
|
-
} catch {
|
|
3729
|
+
} catch (e) {
|
|
3730
|
+
logCatchDebug("migration", e);
|
|
3585
3731
|
}
|
|
3586
3732
|
try {
|
|
3587
3733
|
await client.execute(
|
|
3588
3734
|
`CREATE INDEX IF NOT EXISTS idx_memories_draft ON memories(draft) WHERE draft = 1`
|
|
3589
3735
|
);
|
|
3590
|
-
} catch {
|
|
3736
|
+
} catch (e) {
|
|
3737
|
+
logCatchDebug("migration", e);
|
|
3591
3738
|
}
|
|
3592
3739
|
for (const col of [
|
|
3593
3740
|
"ALTER TABLE memories ADD COLUMN valid_from TEXT",
|
|
@@ -3595,7 +3742,8 @@ async function ensureSchema() {
|
|
|
3595
3742
|
]) {
|
|
3596
3743
|
try {
|
|
3597
3744
|
await client.execute(col);
|
|
3598
|
-
} catch {
|
|
3745
|
+
} catch (e) {
|
|
3746
|
+
logCatchDebug("migration", e);
|
|
3599
3747
|
}
|
|
3600
3748
|
}
|
|
3601
3749
|
try {
|
|
@@ -3603,27 +3751,31 @@ async function ensureSchema() {
|
|
|
3603
3751
|
sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
|
|
3604
3752
|
args: []
|
|
3605
3753
|
});
|
|
3606
|
-
} catch {
|
|
3754
|
+
} catch (e) {
|
|
3755
|
+
logCatchDebug("migration", e);
|
|
3607
3756
|
}
|
|
3608
3757
|
try {
|
|
3609
3758
|
await client.execute({
|
|
3610
3759
|
sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
|
|
3611
3760
|
args: []
|
|
3612
3761
|
});
|
|
3613
|
-
} catch {
|
|
3762
|
+
} catch (e) {
|
|
3763
|
+
logCatchDebug("migration", e);
|
|
3614
3764
|
}
|
|
3615
3765
|
try {
|
|
3616
3766
|
await client.execute(
|
|
3617
3767
|
`CREATE INDEX IF NOT EXISTS idx_memories_type ON memories(memory_type)`
|
|
3618
3768
|
);
|
|
3619
|
-
} catch {
|
|
3769
|
+
} catch (e) {
|
|
3770
|
+
logCatchDebug("migration", e);
|
|
3620
3771
|
}
|
|
3621
3772
|
try {
|
|
3622
3773
|
await client.execute({
|
|
3623
3774
|
sql: `ALTER TABLE memories ADD COLUMN trajectory TEXT`,
|
|
3624
3775
|
args: []
|
|
3625
3776
|
});
|
|
3626
|
-
} catch {
|
|
3777
|
+
} catch (e) {
|
|
3778
|
+
logCatchDebug("migration", e);
|
|
3627
3779
|
}
|
|
3628
3780
|
for (const col of [
|
|
3629
3781
|
"ALTER TABLE memories ADD COLUMN intent TEXT",
|
|
@@ -3644,7 +3796,8 @@ async function ensureSchema() {
|
|
|
3644
3796
|
]) {
|
|
3645
3797
|
try {
|
|
3646
3798
|
await client.execute(col);
|
|
3647
|
-
} catch {
|
|
3799
|
+
} catch (e) {
|
|
3800
|
+
logCatchDebug("migration", e);
|
|
3648
3801
|
}
|
|
3649
3802
|
}
|
|
3650
3803
|
try {
|
|
@@ -3652,14 +3805,16 @@ async function ensureSchema() {
|
|
|
3652
3805
|
sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
|
|
3653
3806
|
args: []
|
|
3654
3807
|
});
|
|
3655
|
-
} catch {
|
|
3808
|
+
} catch (e) {
|
|
3809
|
+
logCatchDebug("migration", e);
|
|
3656
3810
|
}
|
|
3657
3811
|
try {
|
|
3658
3812
|
await client.execute({
|
|
3659
3813
|
sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
|
|
3660
3814
|
args: []
|
|
3661
3815
|
});
|
|
3662
|
-
} catch {
|
|
3816
|
+
} catch (e) {
|
|
3817
|
+
logCatchDebug("migration", e);
|
|
3663
3818
|
}
|
|
3664
3819
|
}
|
|
3665
3820
|
async function disposeDatabase() {
|
|
@@ -3670,7 +3825,8 @@ async function disposeDatabase() {
|
|
|
3670
3825
|
if (_client) {
|
|
3671
3826
|
try {
|
|
3672
3827
|
await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
3673
|
-
} catch {
|
|
3828
|
+
} catch (e) {
|
|
3829
|
+
logCatchDebug("WAL checkpoint", e);
|
|
3674
3830
|
}
|
|
3675
3831
|
}
|
|
3676
3832
|
if (_daemonClient) {
|
|
@@ -3686,8 +3842,9 @@ async function disposeDatabase() {
|
|
|
3686
3842
|
_client = null;
|
|
3687
3843
|
_resilientClient = null;
|
|
3688
3844
|
}
|
|
3845
|
+
releaseDbLock();
|
|
3689
3846
|
}
|
|
3690
|
-
var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
|
|
3847
|
+
var _debugDb, _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, _lockFd, DB_LOCK_PATH, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
|
|
3691
3848
|
var init_database = __esm({
|
|
3692
3849
|
"src/lib/database.ts"() {
|
|
3693
3850
|
"use strict";
|
|
@@ -3695,11 +3852,14 @@ var init_database = __esm({
|
|
|
3695
3852
|
init_employees();
|
|
3696
3853
|
init_database_adapter();
|
|
3697
3854
|
init_memory();
|
|
3855
|
+
_debugDb = process.env.EXE_DEBUG === "1";
|
|
3698
3856
|
_client = null;
|
|
3699
3857
|
_resilientClient = null;
|
|
3700
3858
|
_walCheckpointTimer = null;
|
|
3701
3859
|
_daemonClient = null;
|
|
3702
3860
|
_adapterClient = null;
|
|
3861
|
+
_lockFd = null;
|
|
3862
|
+
DB_LOCK_PATH = join(homedir(), ".exe-os", "db.lock");
|
|
3703
3863
|
initTurso = initDatabase;
|
|
3704
3864
|
SOFT_DELETE_RETENTION_DAYS = 7;
|
|
3705
3865
|
disposeTurso = disposeDatabase;
|
|
@@ -3707,7 +3867,7 @@ var init_database = __esm({
|
|
|
3707
3867
|
});
|
|
3708
3868
|
|
|
3709
3869
|
// src/lib/license.ts
|
|
3710
|
-
import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, existsSync as
|
|
3870
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, existsSync as existsSync10, mkdirSync as mkdirSync5 } from "fs";
|
|
3711
3871
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
3712
3872
|
import { createRequire as createRequire2 } from "module";
|
|
3713
3873
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
@@ -3734,11 +3894,11 @@ var init_license = __esm({
|
|
|
3734
3894
|
});
|
|
3735
3895
|
|
|
3736
3896
|
// src/lib/plan-limits.ts
|
|
3737
|
-
import { readFileSync as readFileSync9, existsSync as
|
|
3897
|
+
import { readFileSync as readFileSync9, existsSync as existsSync11 } from "fs";
|
|
3738
3898
|
import path10 from "path";
|
|
3739
3899
|
function getLicenseSync() {
|
|
3740
3900
|
try {
|
|
3741
|
-
if (!
|
|
3901
|
+
if (!existsSync11(CACHE_PATH2)) return freeLicense();
|
|
3742
3902
|
const raw = JSON.parse(readFileSync9(CACHE_PATH2, "utf8"));
|
|
3743
3903
|
if (!raw.token || typeof raw.token !== "string") return freeLicense();
|
|
3744
3904
|
const parts = raw.token.split(".");
|
|
@@ -3777,7 +3937,7 @@ function assertEmployeeLimitSync(rosterPath) {
|
|
|
3777
3937
|
const filePath = rosterPath ?? EMPLOYEES_PATH;
|
|
3778
3938
|
let count = 0;
|
|
3779
3939
|
try {
|
|
3780
|
-
if (
|
|
3940
|
+
if (existsSync11(filePath)) {
|
|
3781
3941
|
const raw = readFileSync9(filePath, "utf8");
|
|
3782
3942
|
const employees = JSON.parse(raw);
|
|
3783
3943
|
count = Array.isArray(employees) ? employees.length : 0;
|
|
@@ -3815,9 +3975,9 @@ var init_plan_limits = __esm({
|
|
|
3815
3975
|
import os8 from "os";
|
|
3816
3976
|
import path11 from "path";
|
|
3817
3977
|
import {
|
|
3818
|
-
existsSync as
|
|
3978
|
+
existsSync as existsSync12,
|
|
3819
3979
|
lstatSync,
|
|
3820
|
-
mkdirSync as
|
|
3980
|
+
mkdirSync as mkdirSync6,
|
|
3821
3981
|
readlinkSync as readlinkSync2,
|
|
3822
3982
|
symlinkSync as symlinkSync2
|
|
3823
3983
|
} from "fs";
|
|
@@ -3833,8 +3993,8 @@ function claudeAgentLinkPath(homeDir, agentId) {
|
|
|
3833
3993
|
function ensureAgentSymlink(agentId, homeDir = os8.homedir()) {
|
|
3834
3994
|
const target = identitySourcePath(homeDir, agentId);
|
|
3835
3995
|
const link = claudeAgentLinkPath(homeDir, agentId);
|
|
3836
|
-
|
|
3837
|
-
if (
|
|
3996
|
+
mkdirSync6(claudeAgentsDir(homeDir), { recursive: true });
|
|
3997
|
+
if (existsSync12(link)) {
|
|
3838
3998
|
let stat;
|
|
3839
3999
|
try {
|
|
3840
4000
|
stat = lstatSync(link);
|
|
@@ -3882,8 +4042,8 @@ import os9 from "os";
|
|
|
3882
4042
|
import {
|
|
3883
4043
|
readFileSync as readFileSync10,
|
|
3884
4044
|
readdirSync,
|
|
3885
|
-
unlinkSync as
|
|
3886
|
-
existsSync as
|
|
4045
|
+
unlinkSync as unlinkSync4,
|
|
4046
|
+
existsSync as existsSync13,
|
|
3887
4047
|
rmdirSync
|
|
3888
4048
|
} from "fs";
|
|
3889
4049
|
async function writeNotification(notification) {
|
|
@@ -4147,7 +4307,7 @@ import path14 from "path";
|
|
|
4147
4307
|
import os10 from "os";
|
|
4148
4308
|
import { execSync as execSync6 } from "child_process";
|
|
4149
4309
|
import { mkdir as mkdir3, writeFile as writeFile3, appendFile } from "fs/promises";
|
|
4150
|
-
import { existsSync as
|
|
4310
|
+
import { existsSync as existsSync14, readFileSync as readFileSync11 } from "fs";
|
|
4151
4311
|
async function writeCheckpoint(input) {
|
|
4152
4312
|
const client = getClient();
|
|
4153
4313
|
const row = await resolveTask(client, input.taskId);
|
|
@@ -4388,7 +4548,7 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
|
|
|
4388
4548
|
const EXE_OS_DIR = path14.join(os10.homedir(), ".exe-os");
|
|
4389
4549
|
const mdPath = path14.join(EXE_OS_DIR, taskFile);
|
|
4390
4550
|
const mdDir = path14.dirname(mdPath);
|
|
4391
|
-
if (!
|
|
4551
|
+
if (!existsSync14(mdDir)) await mkdir3(mdDir, { recursive: true });
|
|
4392
4552
|
const reviewer = input.reviewer ?? input.assignedBy;
|
|
4393
4553
|
const mdContent = `# ${input.title}
|
|
4394
4554
|
|
|
@@ -4694,7 +4854,7 @@ async function deleteTaskCore(taskId, _baseDir) {
|
|
|
4694
4854
|
async function ensureArchitectureDoc(baseDir, projectName) {
|
|
4695
4855
|
const archPath = path14.join(baseDir, "exe", "ARCHITECTURE.md");
|
|
4696
4856
|
try {
|
|
4697
|
-
if (
|
|
4857
|
+
if (existsSync14(archPath)) return;
|
|
4698
4858
|
const template = [
|
|
4699
4859
|
`# ${projectName} \u2014 System Architecture`,
|
|
4700
4860
|
"",
|
|
@@ -4729,7 +4889,7 @@ async function ensureArchitectureDoc(baseDir, projectName) {
|
|
|
4729
4889
|
async function ensureGitignoreExe(baseDir) {
|
|
4730
4890
|
const gitignorePath = path14.join(baseDir, ".gitignore");
|
|
4731
4891
|
try {
|
|
4732
|
-
if (
|
|
4892
|
+
if (existsSync14(gitignorePath)) {
|
|
4733
4893
|
const content = readFileSync11(gitignorePath, "utf-8");
|
|
4734
4894
|
if (/^\/?exe\/?$/m.test(content)) return;
|
|
4735
4895
|
await appendFile(gitignorePath, "\n# Employee task assignments (private)\n/exe/\n");
|
|
@@ -4774,7 +4934,7 @@ __export(tasks_review_exports, {
|
|
|
4774
4934
|
listPendingReviews: () => listPendingReviews
|
|
4775
4935
|
});
|
|
4776
4936
|
import path15 from "path";
|
|
4777
|
-
import { existsSync as
|
|
4937
|
+
import { existsSync as existsSync15, readdirSync as readdirSync2, unlinkSync as unlinkSync5 } from "fs";
|
|
4778
4938
|
function formatAge(isoTimestamp) {
|
|
4779
4939
|
if (!isoTimestamp) return "";
|
|
4780
4940
|
const ms = Date.now() - new Date(isoTimestamp).getTime();
|
|
@@ -5044,10 +5204,10 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
|
|
|
5044
5204
|
}
|
|
5045
5205
|
try {
|
|
5046
5206
|
const cacheDir = path15.join(EXE_AI_DIR, "session-cache");
|
|
5047
|
-
if (
|
|
5207
|
+
if (existsSync15(cacheDir)) {
|
|
5048
5208
|
for (const f of readdirSync2(cacheDir)) {
|
|
5049
5209
|
if (f.startsWith("review-notified-")) {
|
|
5050
|
-
|
|
5210
|
+
unlinkSync5(path15.join(cacheDir, f));
|
|
5051
5211
|
}
|
|
5052
5212
|
}
|
|
5053
5213
|
}
|
|
@@ -5270,10 +5430,10 @@ async function disposeEmbedder() {
|
|
|
5270
5430
|
async function embedDirect(text) {
|
|
5271
5431
|
const llamaCpp = await import("node-llama-cpp");
|
|
5272
5432
|
const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
5273
|
-
const { existsSync:
|
|
5433
|
+
const { existsSync: existsSync19 } = await import("fs");
|
|
5274
5434
|
const path21 = await import("path");
|
|
5275
5435
|
const modelPath = path21.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
|
|
5276
|
-
if (!
|
|
5436
|
+
if (!existsSync19(modelPath)) {
|
|
5277
5437
|
throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
|
|
5278
5438
|
}
|
|
5279
5439
|
const llama = await llamaCpp.getLlama();
|
|
@@ -5640,7 +5800,7 @@ __export(tasks_exports, {
|
|
|
5640
5800
|
writeCheckpoint: () => writeCheckpoint
|
|
5641
5801
|
});
|
|
5642
5802
|
import path17 from "path";
|
|
5643
|
-
import { writeFileSync as writeFileSync7, mkdirSync as
|
|
5803
|
+
import { writeFileSync as writeFileSync7, mkdirSync as mkdirSync7, unlinkSync as unlinkSync6 } from "fs";
|
|
5644
5804
|
async function createTask(input) {
|
|
5645
5805
|
const result = await createTaskCore(input);
|
|
5646
5806
|
if (!input.skipDispatch && result.status !== "blocked" && !process.env.VITEST) {
|
|
@@ -5662,11 +5822,11 @@ async function updateTask(input) {
|
|
|
5662
5822
|
const cacheDir = path17.join(EXE_AI_DIR, "session-cache");
|
|
5663
5823
|
const cachePath = path17.join(cacheDir, `current-task-${agent}.json`);
|
|
5664
5824
|
if (input.status === "in_progress") {
|
|
5665
|
-
|
|
5825
|
+
mkdirSync7(cacheDir, { recursive: true });
|
|
5666
5826
|
writeFileSync7(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
|
|
5667
5827
|
} else if (input.status === "done" || input.status === "blocked" || input.status === "cancelled" || input.status === "closed") {
|
|
5668
5828
|
try {
|
|
5669
|
-
|
|
5829
|
+
unlinkSync6(cachePath);
|
|
5670
5830
|
} catch {
|
|
5671
5831
|
}
|
|
5672
5832
|
}
|
|
@@ -6134,11 +6294,11 @@ __export(tmux_routing_exports, {
|
|
|
6134
6294
|
verifyPaneAtCapacity: () => verifyPaneAtCapacity
|
|
6135
6295
|
});
|
|
6136
6296
|
import { execFileSync as execFileSync2, execSync as execSync7 } from "child_process";
|
|
6137
|
-
import { readFileSync as readFileSync12, writeFileSync as writeFileSync8, mkdirSync as
|
|
6297
|
+
import { readFileSync as readFileSync12, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8, existsSync as existsSync16, appendFileSync, readdirSync as readdirSync3 } from "fs";
|
|
6138
6298
|
import path18 from "path";
|
|
6139
6299
|
import os11 from "os";
|
|
6140
6300
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
6141
|
-
import { unlinkSync as
|
|
6301
|
+
import { unlinkSync as unlinkSync7 } from "fs";
|
|
6142
6302
|
function spawnLockPath(sessionName) {
|
|
6143
6303
|
return path18.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
|
|
6144
6304
|
}
|
|
@@ -6151,11 +6311,11 @@ function isProcessAlive(pid) {
|
|
|
6151
6311
|
}
|
|
6152
6312
|
}
|
|
6153
6313
|
function acquireSpawnLock2(sessionName) {
|
|
6154
|
-
if (!
|
|
6155
|
-
|
|
6314
|
+
if (!existsSync16(SPAWN_LOCK_DIR)) {
|
|
6315
|
+
mkdirSync8(SPAWN_LOCK_DIR, { recursive: true });
|
|
6156
6316
|
}
|
|
6157
6317
|
const lockFile = spawnLockPath(sessionName);
|
|
6158
|
-
if (
|
|
6318
|
+
if (existsSync16(lockFile)) {
|
|
6159
6319
|
try {
|
|
6160
6320
|
const lock = JSON.parse(readFileSync12(lockFile, "utf8"));
|
|
6161
6321
|
const age = Date.now() - lock.timestamp;
|
|
@@ -6170,7 +6330,7 @@ function acquireSpawnLock2(sessionName) {
|
|
|
6170
6330
|
}
|
|
6171
6331
|
function releaseSpawnLock2(sessionName) {
|
|
6172
6332
|
try {
|
|
6173
|
-
|
|
6333
|
+
unlinkSync7(spawnLockPath(sessionName));
|
|
6174
6334
|
} catch {
|
|
6175
6335
|
}
|
|
6176
6336
|
}
|
|
@@ -6183,7 +6343,7 @@ function resolveBehaviorsExporterScript() {
|
|
|
6183
6343
|
"bin",
|
|
6184
6344
|
"exe-export-behaviors.js"
|
|
6185
6345
|
);
|
|
6186
|
-
return
|
|
6346
|
+
return existsSync16(scriptPath) ? scriptPath : null;
|
|
6187
6347
|
} catch {
|
|
6188
6348
|
return null;
|
|
6189
6349
|
}
|
|
@@ -6249,8 +6409,8 @@ function extractRootExe(name) {
|
|
|
6249
6409
|
return parts.length > 0 ? parts[parts.length - 1] : null;
|
|
6250
6410
|
}
|
|
6251
6411
|
function registerParentExe(sessionKey, parentExe, dispatchedBy) {
|
|
6252
|
-
if (!
|
|
6253
|
-
|
|
6412
|
+
if (!existsSync16(SESSION_CACHE)) {
|
|
6413
|
+
mkdirSync8(SESSION_CACHE, { recursive: true });
|
|
6254
6414
|
}
|
|
6255
6415
|
const rootExe = extractRootExe(parentExe) ?? parentExe;
|
|
6256
6416
|
const filePath = path18.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
|
|
@@ -6280,11 +6440,13 @@ function getDispatchedBy(sessionKey) {
|
|
|
6280
6440
|
}
|
|
6281
6441
|
}
|
|
6282
6442
|
function resolveExeSession() {
|
|
6283
|
-
if (process.env.EXE_SESSION_NAME) {
|
|
6284
|
-
return extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
|
|
6285
|
-
}
|
|
6286
6443
|
const mySession = getMySession();
|
|
6287
|
-
if (!mySession)
|
|
6444
|
+
if (!mySession) {
|
|
6445
|
+
if (process.env.EXE_SESSION_NAME) {
|
|
6446
|
+
return extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
|
|
6447
|
+
}
|
|
6448
|
+
return null;
|
|
6449
|
+
}
|
|
6288
6450
|
const fromSessionName = extractRootExe(mySession);
|
|
6289
6451
|
let candidate = null;
|
|
6290
6452
|
try {
|
|
@@ -6379,7 +6541,7 @@ async function verifyPaneAtCapacity(sessionName) {
|
|
|
6379
6541
|
}
|
|
6380
6542
|
function readDebounceState() {
|
|
6381
6543
|
try {
|
|
6382
|
-
if (!
|
|
6544
|
+
if (!existsSync16(DEBOUNCE_FILE)) return {};
|
|
6383
6545
|
const raw = JSON.parse(readFileSync12(DEBOUNCE_FILE, "utf8"));
|
|
6384
6546
|
const state = {};
|
|
6385
6547
|
for (const [key, val] of Object.entries(raw)) {
|
|
@@ -6396,7 +6558,7 @@ function readDebounceState() {
|
|
|
6396
6558
|
}
|
|
6397
6559
|
function writeDebounceState(state) {
|
|
6398
6560
|
try {
|
|
6399
|
-
if (!
|
|
6561
|
+
if (!existsSync16(SESSION_CACHE)) mkdirSync8(SESSION_CACHE, { recursive: true });
|
|
6400
6562
|
writeFileSync8(DEBOUNCE_FILE, JSON.stringify(state));
|
|
6401
6563
|
} catch {
|
|
6402
6564
|
}
|
|
@@ -6497,7 +6659,7 @@ function sendIntercom(targetSession) {
|
|
|
6497
6659
|
const rawAgent = targetSession.split("-")[0] ?? targetSession;
|
|
6498
6660
|
const agent = baseAgentName(rawAgent);
|
|
6499
6661
|
const markerPath = path18.join(SESSION_CACHE, `current-task-${agent}.json`);
|
|
6500
|
-
if (
|
|
6662
|
+
if (existsSync16(markerPath)) {
|
|
6501
6663
|
logIntercom(`SKIP \u2192 ${targetSession} (has in_progress task marker + not idle \u2014 will auto-chain)`);
|
|
6502
6664
|
return "debounced";
|
|
6503
6665
|
}
|
|
@@ -6508,7 +6670,7 @@ function sendIntercom(targetSession) {
|
|
|
6508
6670
|
const rawAgent = targetSession.split("-")[0] ?? targetSession;
|
|
6509
6671
|
const agent = baseAgentName(rawAgent);
|
|
6510
6672
|
const taskDir = path18.join(process.cwd(), "exe", agent);
|
|
6511
|
-
if (
|
|
6673
|
+
if (existsSync16(taskDir)) {
|
|
6512
6674
|
const files = readdirSync3(taskDir).filter(
|
|
6513
6675
|
(f) => f.endsWith(".md") && f !== "DONE.txt"
|
|
6514
6676
|
);
|
|
@@ -6669,15 +6831,15 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
6669
6831
|
const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
|
|
6670
6832
|
const logDir = path18.join(os11.homedir(), ".exe-os", "session-logs");
|
|
6671
6833
|
const logFile = path18.join(logDir, `${instanceLabel}-${Date.now()}.log`);
|
|
6672
|
-
if (!
|
|
6673
|
-
|
|
6834
|
+
if (!existsSync16(logDir)) {
|
|
6835
|
+
mkdirSync8(logDir, { recursive: true });
|
|
6674
6836
|
}
|
|
6675
6837
|
transport.kill(sessionName);
|
|
6676
6838
|
let cleanupSuffix = "";
|
|
6677
6839
|
try {
|
|
6678
6840
|
const thisFile = fileURLToPath2(import.meta.url);
|
|
6679
6841
|
const cleanupScript = path18.join(path18.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
|
|
6680
|
-
if (
|
|
6842
|
+
if (existsSync16(cleanupScript)) {
|
|
6681
6843
|
cleanupSuffix = `; ${process.execPath} "${cleanupScript}" "${employeeName}" "${exeSession}"`;
|
|
6682
6844
|
}
|
|
6683
6845
|
} catch {
|
|
@@ -6732,7 +6894,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
6732
6894
|
if (changed) {
|
|
6733
6895
|
perms.allow = allow;
|
|
6734
6896
|
settings.permissions = perms;
|
|
6735
|
-
|
|
6897
|
+
mkdirSync8(projSettingsDir, { recursive: true });
|
|
6736
6898
|
writeFileSync8(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
6737
6899
|
}
|
|
6738
6900
|
} catch {
|
|
@@ -6770,7 +6932,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
6770
6932
|
`
|
|
6771
6933
|
);
|
|
6772
6934
|
}
|
|
6773
|
-
} else if (
|
|
6935
|
+
} else if (existsSync16(identityPath)) {
|
|
6774
6936
|
identityFlag = ` --append-system-prompt-file ${identityPath}`;
|
|
6775
6937
|
legacyFallbackWarned = true;
|
|
6776
6938
|
}
|
|
@@ -6792,7 +6954,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
6792
6954
|
let sessionContextFlag = "";
|
|
6793
6955
|
try {
|
|
6794
6956
|
const ctxDir = path18.join(os11.homedir(), ".exe-os", "session-cache");
|
|
6795
|
-
|
|
6957
|
+
mkdirSync8(ctxDir, { recursive: true });
|
|
6796
6958
|
const ctxFile = path18.join(ctxDir, `session-context-${sessionName}.md`);
|
|
6797
6959
|
const ctxContent = [
|
|
6798
6960
|
`## Session Context`,
|
|
@@ -7008,7 +7170,7 @@ var init_task_scope = __esm({
|
|
|
7008
7170
|
|
|
7009
7171
|
// src/lib/keychain.ts
|
|
7010
7172
|
import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
|
|
7011
|
-
import { existsSync as
|
|
7173
|
+
import { existsSync as existsSync17, statSync as statSync3 } from "fs";
|
|
7012
7174
|
import { execSync as execSync9 } from "child_process";
|
|
7013
7175
|
import path19 from "path";
|
|
7014
7176
|
import os12 from "os";
|
|
@@ -7043,7 +7205,7 @@ function isRootOnlyTrustedServerKeyFile(keyPath) {
|
|
|
7043
7205
|
if (process.platform !== "linux") return false;
|
|
7044
7206
|
try {
|
|
7045
7207
|
const uid = typeof os12.userInfo().uid === "number" ? os12.userInfo().uid : -1;
|
|
7046
|
-
const st =
|
|
7208
|
+
const st = statSync3(keyPath);
|
|
7047
7209
|
if (!st.isFile() || (st.mode & 63) !== 0) return false;
|
|
7048
7210
|
if (uid === 0) return true;
|
|
7049
7211
|
const exeOsDir = process.env.EXE_OS_DIR;
|
|
@@ -7244,7 +7406,7 @@ async function getMasterKey() {
|
|
|
7244
7406
|
}
|
|
7245
7407
|
}
|
|
7246
7408
|
const keyPath = getKeyPath();
|
|
7247
|
-
if (!
|
|
7409
|
+
if (!existsSync17(keyPath)) {
|
|
7248
7410
|
process.stderr.write(
|
|
7249
7411
|
`[keychain] Key not found at ${keyPath} (HOME=${os12.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
|
|
7250
7412
|
`
|
|
@@ -7524,18 +7686,54 @@ __export(shard_manager_exports, {
|
|
|
7524
7686
|
shardExists: () => shardExists
|
|
7525
7687
|
});
|
|
7526
7688
|
import path20 from "path";
|
|
7527
|
-
import { existsSync as
|
|
7689
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync9, readdirSync as readdirSync4, renameSync as renameSync4, statSync as statSync4 } from "fs";
|
|
7528
7690
|
import { createClient as createClient2 } from "@libsql/client";
|
|
7529
7691
|
function initShardManager(encryptionKey) {
|
|
7530
7692
|
_encryptionKey = encryptionKey;
|
|
7531
|
-
|
|
7532
|
-
|
|
7693
|
+
_keyValidated = false;
|
|
7694
|
+
_keyValidationPromise = null;
|
|
7695
|
+
if (!existsSync18(SHARDS_DIR)) {
|
|
7696
|
+
mkdirSync9(SHARDS_DIR, { recursive: true });
|
|
7697
|
+
}
|
|
7698
|
+
const existingShards = readdirSync4(SHARDS_DIR).filter((f) => f.endsWith(".db"));
|
|
7699
|
+
if (existingShards.length === 0) {
|
|
7700
|
+
_keyValidated = true;
|
|
7533
7701
|
}
|
|
7534
7702
|
_shardingEnabled = true;
|
|
7535
7703
|
if (_evictionTimer) clearInterval(_evictionTimer);
|
|
7536
7704
|
_evictionTimer = setInterval(evictIdleShards, EVICTION_INTERVAL_MS);
|
|
7537
7705
|
_evictionTimer.unref();
|
|
7538
7706
|
}
|
|
7707
|
+
async function validateEncryptionKey() {
|
|
7708
|
+
if (_keyValidated) return true;
|
|
7709
|
+
if (!_encryptionKey) return false;
|
|
7710
|
+
const existingShards = readdirSync4(SHARDS_DIR).filter((f) => f.endsWith(".db"));
|
|
7711
|
+
if (existingShards.length === 0) {
|
|
7712
|
+
_keyValidated = true;
|
|
7713
|
+
return true;
|
|
7714
|
+
}
|
|
7715
|
+
for (const shardFile of existingShards.slice(0, 3)) {
|
|
7716
|
+
const dbPath = path20.join(SHARDS_DIR, shardFile);
|
|
7717
|
+
const testClient = createClient2({ url: `file:${dbPath}`, encryptionKey: _encryptionKey });
|
|
7718
|
+
try {
|
|
7719
|
+
await testClient.execute("SELECT COUNT(*) FROM sqlite_schema");
|
|
7720
|
+
testClient.close();
|
|
7721
|
+
_keyValidated = true;
|
|
7722
|
+
return true;
|
|
7723
|
+
} catch {
|
|
7724
|
+
try {
|
|
7725
|
+
testClient.close();
|
|
7726
|
+
} catch {
|
|
7727
|
+
}
|
|
7728
|
+
}
|
|
7729
|
+
}
|
|
7730
|
+
process.stderr.write(
|
|
7731
|
+
`[shard-manager] WARNING: encryption key cannot read any existing shards (${existingShards.length} found). New shard creation disabled to prevent stranded files. Run /exe-doctor to audit.
|
|
7732
|
+
`
|
|
7733
|
+
);
|
|
7734
|
+
_shardingEnabled = false;
|
|
7735
|
+
return false;
|
|
7736
|
+
}
|
|
7539
7737
|
function isShardingEnabled() {
|
|
7540
7738
|
return _shardingEnabled;
|
|
7541
7739
|
}
|
|
@@ -7569,13 +7767,13 @@ function getShardClient(projectName) {
|
|
|
7569
7767
|
}
|
|
7570
7768
|
function shardExists(projectName) {
|
|
7571
7769
|
const safeName = safeShardName(projectName);
|
|
7572
|
-
return
|
|
7770
|
+
return existsSync18(path20.join(SHARDS_DIR, `${safeName}.db`));
|
|
7573
7771
|
}
|
|
7574
7772
|
function safeShardName(projectName) {
|
|
7575
7773
|
return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
7576
7774
|
}
|
|
7577
7775
|
function listShards() {
|
|
7578
|
-
if (!
|
|
7776
|
+
if (!existsSync18(SHARDS_DIR)) return [];
|
|
7579
7777
|
return readdirSync4(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
7580
7778
|
}
|
|
7581
7779
|
async function auditShardHealth(options = {}) {
|
|
@@ -7588,7 +7786,7 @@ async function auditShardHealth(options = {}) {
|
|
|
7588
7786
|
const shards = [];
|
|
7589
7787
|
for (const name of names) {
|
|
7590
7788
|
const dbPath = path20.join(SHARDS_DIR, `${name}.db`);
|
|
7591
|
-
const stat =
|
|
7789
|
+
const stat = statSync4(dbPath);
|
|
7592
7790
|
const item = {
|
|
7593
7791
|
name,
|
|
7594
7792
|
path: dbPath,
|
|
@@ -7828,6 +8026,17 @@ async function ensureShardSchema(client) {
|
|
|
7828
8026
|
}
|
|
7829
8027
|
}
|
|
7830
8028
|
async function getReadyShardClient(projectName) {
|
|
8029
|
+
if (!_keyValidated) {
|
|
8030
|
+
if (!_keyValidationPromise) {
|
|
8031
|
+
_keyValidationPromise = validateEncryptionKey();
|
|
8032
|
+
}
|
|
8033
|
+
const valid = await _keyValidationPromise;
|
|
8034
|
+
if (!valid) {
|
|
8035
|
+
throw new Error(
|
|
8036
|
+
`Shard creation blocked: encryption key mismatch with existing shards. Run /exe-doctor to audit.`
|
|
8037
|
+
);
|
|
8038
|
+
}
|
|
8039
|
+
}
|
|
7831
8040
|
const safeName = safeShardName(projectName);
|
|
7832
8041
|
let client = getShardClient(projectName);
|
|
7833
8042
|
try {
|
|
@@ -7840,8 +8049,8 @@ async function getReadyShardClient(projectName) {
|
|
|
7840
8049
|
_shards.delete(safeName);
|
|
7841
8050
|
_shardLastAccess.delete(safeName);
|
|
7842
8051
|
const dbPath = path20.join(SHARDS_DIR, `${safeName}.db`);
|
|
7843
|
-
if (
|
|
7844
|
-
const stat =
|
|
8052
|
+
if (existsSync18(dbPath)) {
|
|
8053
|
+
const stat = statSync4(dbPath);
|
|
7845
8054
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
7846
8055
|
const archivedPath = path20.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
7847
8056
|
renameSync4(dbPath, archivedPath);
|
|
@@ -7906,7 +8115,7 @@ function disposeShards() {
|
|
|
7906
8115
|
_shardingEnabled = false;
|
|
7907
8116
|
_encryptionKey = null;
|
|
7908
8117
|
}
|
|
7909
|
-
var SHARDS_DIR, SHARD_IDLE_MS, MAX_OPEN_SHARDS, EVICTION_INTERVAL_MS, _shards, _shardLastAccess, _evictionTimer, _encryptionKey, _shardingEnabled;
|
|
8118
|
+
var SHARDS_DIR, SHARD_IDLE_MS, MAX_OPEN_SHARDS, EVICTION_INTERVAL_MS, _shards, _shardLastAccess, _evictionTimer, _encryptionKey, _shardingEnabled, _keyValidated, _keyValidationPromise;
|
|
7910
8119
|
var init_shard_manager = __esm({
|
|
7911
8120
|
"src/lib/shard-manager.ts"() {
|
|
7912
8121
|
"use strict";
|
|
@@ -7920,6 +8129,8 @@ var init_shard_manager = __esm({
|
|
|
7920
8129
|
_evictionTimer = null;
|
|
7921
8130
|
_encryptionKey = null;
|
|
7922
8131
|
_shardingEnabled = false;
|
|
8132
|
+
_keyValidated = false;
|
|
8133
|
+
_keyValidationPromise = null;
|
|
7923
8134
|
}
|
|
7924
8135
|
});
|
|
7925
8136
|
|
|
@@ -8115,6 +8326,18 @@ var init_platform_procedures = __esm({
|
|
|
8115
8326
|
priority: "p0",
|
|
8116
8327
|
content: "create_task is dispatch + delivery. Task lifecycle: open \u2192 in_progress (you start) \u2192 done (update_task when finished) \u2192 needs_review (reviewer nudged) \u2192 closed (COO only via close_task). DB is the reliable delivery \u2014 intercom is just a speedup nudge. If you finish a task, self-chain: check for next task immediately (step 7). Never wait for a nudge. Never say 'standing by.'"
|
|
8117
8328
|
},
|
|
8329
|
+
{
|
|
8330
|
+
title: "Review chain \u2014 managers must actively pull completed work, never wait for nudges",
|
|
8331
|
+
domain: "workflow",
|
|
8332
|
+
priority: "p0",
|
|
8333
|
+
content: "When you dispatch work, you OWN the review. Check list_tasks(status='needs_review') on EVERY prompt \u2014 don't wait for intercom nudges (they're unreliable). When a task shows needs_review: (1) read the deliverable (git diff in worktree, exe/output/ files, or task result summary), (2) verify it works (tsc, build, run), (3) close_task if good or create a fix task if not. Reviews sitting >30 minutes is a pipeline stall. The whole chain: worker calls update_task(done) \u2192 system flags needs_review \u2192 manager pulls and verifies \u2192 close_task \u2192 COO reviews manager's work \u2192 merge to main. Every level actively pulls \u2014 nobody waits."
|
|
8334
|
+
},
|
|
8335
|
+
{
|
|
8336
|
+
title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
|
|
8337
|
+
domain: "workflow",
|
|
8338
|
+
priority: "p0",
|
|
8339
|
+
content: "When a bug from support(action='list_bugs') is fixed and verified, the reviewer MUST triage it upstream: support(action='triage_bug', id='<bug-id>', notes='<what was fixed>', fixed_version='<version>', linked_commit='<hash>'). This closes the bug in the customer's view \u2014 their COO checks list_my_bugs and sees status change from open \u2192 closed with the fix version. Without triage, customers see 'open' forever even after the fix ships. Same for feature requests: support(action='triage_feature', ..., shipped_version='<version>'). Triage is part of the review gate \u2014 a fix is not done until the upstream report is closed."
|
|
8340
|
+
},
|
|
8118
8341
|
{
|
|
8119
8342
|
title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
|
|
8120
8343
|
domain: "architecture",
|
|
@@ -8712,6 +8935,20 @@ __export(store_exports, {
|
|
|
8712
8935
|
vectorToBlob: () => vectorToBlob,
|
|
8713
8936
|
writeMemory: () => writeMemory
|
|
8714
8937
|
});
|
|
8938
|
+
function logStoreDebug(context, err) {
|
|
8939
|
+
if (_debugStore) {
|
|
8940
|
+
process.stderr.write(
|
|
8941
|
+
`[store] ${context}: ${err instanceof Error ? err.message : String(err)}
|
|
8942
|
+
`
|
|
8943
|
+
);
|
|
8944
|
+
}
|
|
8945
|
+
}
|
|
8946
|
+
function logStoreWarn(context, err) {
|
|
8947
|
+
process.stderr.write(
|
|
8948
|
+
`[store] WARN ${context}: ${err instanceof Error ? err.message : String(err)}
|
|
8949
|
+
`
|
|
8950
|
+
);
|
|
8951
|
+
}
|
|
8715
8952
|
function isBusyError2(err) {
|
|
8716
8953
|
if (err instanceof Error) {
|
|
8717
8954
|
const msg = err.message.toLowerCase();
|
|
@@ -8766,13 +9003,15 @@ async function initStore(options) {
|
|
|
8766
9003
|
try {
|
|
8767
9004
|
const { initDaemonClient: initDaemonClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
8768
9005
|
await initDaemonClient2();
|
|
8769
|
-
} catch {
|
|
9006
|
+
} catch (e) {
|
|
9007
|
+
logStoreWarn("catch", e);
|
|
8770
9008
|
}
|
|
8771
9009
|
if (!options?.lightweight) {
|
|
8772
9010
|
try {
|
|
8773
9011
|
const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
8774
9012
|
initShardManager2(hexKey);
|
|
8775
|
-
} catch {
|
|
9013
|
+
} catch (e) {
|
|
9014
|
+
logStoreWarn("catch", e);
|
|
8776
9015
|
}
|
|
8777
9016
|
const client = getClient();
|
|
8778
9017
|
const vResult = await retryOnBusy2(
|
|
@@ -8783,7 +9022,8 @@ async function initStore(options) {
|
|
|
8783
9022
|
try {
|
|
8784
9023
|
const { loadGlobalProcedures: loadGlobalProcedures2 } = await Promise.resolve().then(() => (init_global_procedures(), global_procedures_exports));
|
|
8785
9024
|
await loadGlobalProcedures2();
|
|
8786
|
-
} catch {
|
|
9025
|
+
} catch (e) {
|
|
9026
|
+
logStoreWarn("catch", e);
|
|
8787
9027
|
}
|
|
8788
9028
|
}
|
|
8789
9029
|
}
|
|
@@ -8843,7 +9083,8 @@ async function writeMemory(record) {
|
|
|
8843
9083
|
memoryType
|
|
8844
9084
|
});
|
|
8845
9085
|
if (existing) return;
|
|
8846
|
-
} catch {
|
|
9086
|
+
} catch (e) {
|
|
9087
|
+
logStoreWarn("catch", e);
|
|
8847
9088
|
}
|
|
8848
9089
|
const dbRow = {
|
|
8849
9090
|
id: record.id,
|
|
@@ -9044,12 +9285,14 @@ async function flushBatch() {
|
|
|
9044
9285
|
try {
|
|
9045
9286
|
const { insertMemoryCardsForBatch: insertMemoryCardsForBatch2 } = await Promise.resolve().then(() => (init_memory_cards(), memory_cards_exports));
|
|
9046
9287
|
await insertMemoryCardsForBatch2(batch);
|
|
9047
|
-
} catch {
|
|
9288
|
+
} catch (e) {
|
|
9289
|
+
logStoreWarn("catch", e);
|
|
9048
9290
|
}
|
|
9049
9291
|
try {
|
|
9050
9292
|
const { insertOntologyForBatch: insertOntologyForBatch2 } = await Promise.resolve().then(() => (init_agentic_ontology(), agentic_ontology_exports));
|
|
9051
9293
|
await insertOntologyForBatch2(batch);
|
|
9052
|
-
} catch {
|
|
9294
|
+
} catch (e) {
|
|
9295
|
+
logStoreWarn("catch", e);
|
|
9053
9296
|
}
|
|
9054
9297
|
schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
|
|
9055
9298
|
_pendingRecords.splice(0, batch.length);
|
|
@@ -9088,7 +9331,8 @@ ${err.stack.split("\n").slice(1, 3).join("\n")}` : ""}` : String(err);
|
|
|
9088
9331
|
}
|
|
9089
9332
|
}
|
|
9090
9333
|
}
|
|
9091
|
-
} catch {
|
|
9334
|
+
} catch (e) {
|
|
9335
|
+
logStoreWarn("catch", e);
|
|
9092
9336
|
}
|
|
9093
9337
|
return batch.length;
|
|
9094
9338
|
} finally {
|
|
@@ -9130,7 +9374,8 @@ async function searchMemories(queryVector, agentId, options) {
|
|
|
9130
9374
|
} else {
|
|
9131
9375
|
client = getClient();
|
|
9132
9376
|
}
|
|
9133
|
-
} catch {
|
|
9377
|
+
} catch (e) {
|
|
9378
|
+
logStoreDebug("shard routing fallback", e);
|
|
9134
9379
|
client = getClient();
|
|
9135
9380
|
}
|
|
9136
9381
|
const limit = options?.limit ?? 10;
|
|
@@ -9246,7 +9491,8 @@ async function attachDocumentMetadata(records) {
|
|
|
9246
9491
|
if (!record.document_id) continue;
|
|
9247
9492
|
record.document_metadata = byId.get(record.document_id) ?? null;
|
|
9248
9493
|
}
|
|
9249
|
-
} catch {
|
|
9494
|
+
} catch (e) {
|
|
9495
|
+
logStoreWarn("catch", e);
|
|
9250
9496
|
}
|
|
9251
9497
|
return records;
|
|
9252
9498
|
}
|
|
@@ -9307,11 +9553,12 @@ async function getMemoryCardinality(agentId) {
|
|
|
9307
9553
|
args: [agentId]
|
|
9308
9554
|
});
|
|
9309
9555
|
return Number(result.rows[0]?.cnt) || 0;
|
|
9310
|
-
} catch {
|
|
9556
|
+
} catch (e) {
|
|
9557
|
+
logStoreWarn("getMemoryCardinality", e);
|
|
9311
9558
|
return 0;
|
|
9312
9559
|
}
|
|
9313
9560
|
}
|
|
9314
|
-
var INIT_MAX_RETRIES, INIT_RETRY_DELAY_MS, _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
|
|
9561
|
+
var _debugStore, INIT_MAX_RETRIES, INIT_RETRY_DELAY_MS, _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
|
|
9315
9562
|
var init_store = __esm({
|
|
9316
9563
|
"src/lib/store.ts"() {
|
|
9317
9564
|
"use strict";
|
|
@@ -9321,6 +9568,7 @@ var init_store = __esm({
|
|
|
9321
9568
|
init_config();
|
|
9322
9569
|
init_state_bus();
|
|
9323
9570
|
init_memory_write_governor();
|
|
9571
|
+
_debugStore = process.env.EXE_DEBUG === "1";
|
|
9324
9572
|
INIT_MAX_RETRIES = 3;
|
|
9325
9573
|
INIT_RETRY_DELAY_MS = 1e3;
|
|
9326
9574
|
_pendingRecords = [];
|