@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
|
@@ -2083,9 +2083,79 @@ __export(database_exports, {
|
|
|
2083
2083
|
isInitialized: () => isInitialized,
|
|
2084
2084
|
setExternalClient: () => setExternalClient
|
|
2085
2085
|
});
|
|
2086
|
-
import { chmodSync as chmodSync2 } from "fs";
|
|
2086
|
+
import { chmodSync as chmodSync2, existsSync as existsSync7, statSync as statSync2, copyFileSync, unlinkSync as unlinkSync3, openSync as openSync2, closeSync as closeSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
2087
2087
|
import { createClient } from "@libsql/client";
|
|
2088
|
+
import { homedir } from "os";
|
|
2089
|
+
import { join } from "path";
|
|
2090
|
+
function logCatchDebug(context, err) {
|
|
2091
|
+
if (_debugDb) {
|
|
2092
|
+
process.stderr.write(
|
|
2093
|
+
`[database] ${context}: ${err instanceof Error ? err.message : String(err)}
|
|
2094
|
+
`
|
|
2095
|
+
);
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
function acquireDbLock() {
|
|
2099
|
+
mkdirSync2(join(homedir(), ".exe-os"), { recursive: true });
|
|
2100
|
+
try {
|
|
2101
|
+
_lockFd = openSync2(DB_LOCK_PATH, "wx");
|
|
2102
|
+
} catch (err) {
|
|
2103
|
+
if (err && typeof err === "object" && "code" in err && err.code === "EEXIST") {
|
|
2104
|
+
try {
|
|
2105
|
+
const lockStat = statSync2(DB_LOCK_PATH);
|
|
2106
|
+
if (Date.now() - lockStat.mtimeMs > 6e4) {
|
|
2107
|
+
unlinkSync3(DB_LOCK_PATH);
|
|
2108
|
+
_lockFd = openSync2(DB_LOCK_PATH, "wx");
|
|
2109
|
+
return;
|
|
2110
|
+
}
|
|
2111
|
+
} catch (e) {
|
|
2112
|
+
logCatchDebug("stale lock check", e);
|
|
2113
|
+
}
|
|
2114
|
+
process.stderr.write(
|
|
2115
|
+
"[database] WARN: Another process holds db.lock \u2014 waiting briefly then proceeding.\n"
|
|
2116
|
+
);
|
|
2117
|
+
return;
|
|
2118
|
+
}
|
|
2119
|
+
throw err;
|
|
2120
|
+
}
|
|
2121
|
+
}
|
|
2122
|
+
function releaseDbLock() {
|
|
2123
|
+
if (_lockFd !== null) {
|
|
2124
|
+
try {
|
|
2125
|
+
closeSync2(_lockFd);
|
|
2126
|
+
} catch (e) {
|
|
2127
|
+
logCatchDebug("lock close", e);
|
|
2128
|
+
}
|
|
2129
|
+
_lockFd = null;
|
|
2130
|
+
}
|
|
2131
|
+
try {
|
|
2132
|
+
unlinkSync3(DB_LOCK_PATH);
|
|
2133
|
+
} catch (e) {
|
|
2134
|
+
logCatchDebug("lock unlink", e);
|
|
2135
|
+
}
|
|
2136
|
+
}
|
|
2088
2137
|
async function initDatabase(config) {
|
|
2138
|
+
acquireDbLock();
|
|
2139
|
+
if (existsSync7(config.dbPath)) {
|
|
2140
|
+
const dbStat = statSync2(config.dbPath);
|
|
2141
|
+
if (dbStat.size === 0) {
|
|
2142
|
+
const walPath = config.dbPath + "-wal";
|
|
2143
|
+
if (existsSync7(walPath) && statSync2(walPath).size > 0) {
|
|
2144
|
+
const backupPath = config.dbPath + ".zeroed-" + Date.now();
|
|
2145
|
+
copyFileSync(config.dbPath, backupPath);
|
|
2146
|
+
unlinkSync3(config.dbPath);
|
|
2147
|
+
process.stderr.write(
|
|
2148
|
+
`[database] CRITICAL: DB was 0 bytes. Moved to ${backupPath}, attempting WAL recovery.
|
|
2149
|
+
`
|
|
2150
|
+
);
|
|
2151
|
+
} else {
|
|
2152
|
+
process.stderr.write(
|
|
2153
|
+
`[database] CRITICAL: DB is 0 bytes and no WAL available for recovery. Data may be lost. Check backups at ${config.dbPath}.bak
|
|
2154
|
+
`
|
|
2155
|
+
);
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
2089
2159
|
if (_walCheckpointTimer) {
|
|
2090
2160
|
clearInterval(_walCheckpointTimer);
|
|
2091
2161
|
_walCheckpointTimer = null;
|
|
@@ -2112,10 +2182,8 @@ async function initDatabase(config) {
|
|
|
2112
2182
|
_client = createClient(opts);
|
|
2113
2183
|
_resilientClient = wrapWithRetry(_client);
|
|
2114
2184
|
_adapterClient = _resilientClient;
|
|
2115
|
-
_client.execute("PRAGMA busy_timeout = 30000")
|
|
2116
|
-
|
|
2117
|
-
_client.execute("PRAGMA journal_mode = WAL").catch(() => {
|
|
2118
|
-
});
|
|
2185
|
+
await _client.execute("PRAGMA busy_timeout = 30000");
|
|
2186
|
+
await _client.execute("PRAGMA journal_mode = WAL");
|
|
2119
2187
|
if (_walCheckpointTimer) clearInterval(_walCheckpointTimer);
|
|
2120
2188
|
_walCheckpointTimer = setInterval(() => {
|
|
2121
2189
|
_client?.execute("PRAGMA wal_checkpoint(PASSIVE)").catch(() => {
|
|
@@ -2130,11 +2198,16 @@ async function initDatabase(config) {
|
|
|
2130
2198
|
for (const suffix of ["-wal", "-shm"]) {
|
|
2131
2199
|
try {
|
|
2132
2200
|
chmodSync2(config.dbPath + suffix, 384);
|
|
2133
|
-
} catch {
|
|
2201
|
+
} catch (chmodErr) {
|
|
2202
|
+
process.stderr.write(`[database] chmod ${suffix} failed: ${chmodErr instanceof Error ? chmodErr.message : String(chmodErr)}
|
|
2203
|
+
`);
|
|
2134
2204
|
}
|
|
2135
2205
|
}
|
|
2136
|
-
} catch {
|
|
2206
|
+
} catch (chmodErr) {
|
|
2207
|
+
process.stderr.write(`[database] chmod db failed: ${chmodErr instanceof Error ? chmodErr.message : String(chmodErr)}
|
|
2208
|
+
`);
|
|
2137
2209
|
}
|
|
2210
|
+
releaseDbLock();
|
|
2138
2211
|
}
|
|
2139
2212
|
function isInitialized() {
|
|
2140
2213
|
return _adapterClient !== null || _client !== null;
|
|
@@ -2189,7 +2262,8 @@ async function ensureSchema() {
|
|
|
2189
2262
|
await client.execute("PRAGMA wal_autocheckpoint = 1000");
|
|
2190
2263
|
try {
|
|
2191
2264
|
await client.execute("PRAGMA libsql_vector_search_ef = 128");
|
|
2192
|
-
} catch {
|
|
2265
|
+
} catch (e) {
|
|
2266
|
+
logCatchDebug("migration", e);
|
|
2193
2267
|
}
|
|
2194
2268
|
await client.executeMultiple(`
|
|
2195
2269
|
CREATE TABLE IF NOT EXISTS memories (
|
|
@@ -2254,6 +2328,23 @@ async function ensureSchema() {
|
|
|
2254
2328
|
INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
|
|
2255
2329
|
END;
|
|
2256
2330
|
`);
|
|
2331
|
+
try {
|
|
2332
|
+
await client.execute("SELECT COUNT(*) FROM memories_fts LIMIT 1");
|
|
2333
|
+
} catch (ftsErr) {
|
|
2334
|
+
process.stderr.write(
|
|
2335
|
+
`[database] WARN: memories_fts corrupted (${ftsErr instanceof Error ? ftsErr.message : String(ftsErr)}) \u2014 rebuilding FTS index.
|
|
2336
|
+
`
|
|
2337
|
+
);
|
|
2338
|
+
try {
|
|
2339
|
+
await client.execute("INSERT INTO memories_fts(memories_fts) VALUES('rebuild')");
|
|
2340
|
+
process.stderr.write("[database] FTS index rebuilt successfully.\n");
|
|
2341
|
+
} catch (rebuildErr) {
|
|
2342
|
+
process.stderr.write(
|
|
2343
|
+
`[database] ERROR: FTS rebuild failed: ${rebuildErr instanceof Error ? rebuildErr.message : String(rebuildErr)}
|
|
2344
|
+
`
|
|
2345
|
+
);
|
|
2346
|
+
}
|
|
2347
|
+
}
|
|
2257
2348
|
await client.executeMultiple(`
|
|
2258
2349
|
CREATE TABLE IF NOT EXISTS sync_meta (
|
|
2259
2350
|
key TEXT PRIMARY KEY,
|
|
@@ -2312,35 +2403,40 @@ async function ensureSchema() {
|
|
|
2312
2403
|
});
|
|
2313
2404
|
}
|
|
2314
2405
|
}
|
|
2315
|
-
} catch {
|
|
2406
|
+
} catch (seedErr) {
|
|
2407
|
+
logCatchDebug("behavior seed", seedErr);
|
|
2316
2408
|
}
|
|
2317
2409
|
try {
|
|
2318
2410
|
await client.execute({
|
|
2319
2411
|
sql: `ALTER TABLE behaviors ADD COLUMN priority TEXT DEFAULT 'p1'`,
|
|
2320
2412
|
args: []
|
|
2321
2413
|
});
|
|
2322
|
-
} catch {
|
|
2414
|
+
} catch (e) {
|
|
2415
|
+
logCatchDebug("migration", e);
|
|
2323
2416
|
}
|
|
2324
2417
|
try {
|
|
2325
2418
|
await client.execute({
|
|
2326
2419
|
sql: `ALTER TABLE behaviors ADD COLUMN vector F32_BLOB(${EMBEDDING_DIM})`,
|
|
2327
2420
|
args: []
|
|
2328
2421
|
});
|
|
2329
|
-
} catch {
|
|
2422
|
+
} catch (e) {
|
|
2423
|
+
logCatchDebug("migration", e);
|
|
2330
2424
|
}
|
|
2331
2425
|
try {
|
|
2332
2426
|
await client.execute({
|
|
2333
2427
|
sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
|
|
2334
2428
|
args: []
|
|
2335
2429
|
});
|
|
2336
|
-
} catch {
|
|
2430
|
+
} catch (e) {
|
|
2431
|
+
logCatchDebug("migration", e);
|
|
2337
2432
|
}
|
|
2338
2433
|
try {
|
|
2339
2434
|
await client.execute({
|
|
2340
2435
|
sql: `ALTER TABLE tasks ADD COLUMN parent_task_id TEXT`,
|
|
2341
2436
|
args: []
|
|
2342
2437
|
});
|
|
2343
|
-
} catch {
|
|
2438
|
+
} catch (e) {
|
|
2439
|
+
logCatchDebug("migration", e);
|
|
2344
2440
|
}
|
|
2345
2441
|
try {
|
|
2346
2442
|
await client.execute({
|
|
@@ -2349,98 +2445,112 @@ async function ensureSchema() {
|
|
|
2349
2445
|
WHERE parent_task_id IS NOT NULL`,
|
|
2350
2446
|
args: []
|
|
2351
2447
|
});
|
|
2352
|
-
} catch {
|
|
2448
|
+
} catch (e) {
|
|
2449
|
+
logCatchDebug("migration", e);
|
|
2353
2450
|
}
|
|
2354
2451
|
try {
|
|
2355
2452
|
await client.execute({
|
|
2356
2453
|
sql: `UPDATE tasks SET status = 'done' WHERE status = 'completed'`,
|
|
2357
2454
|
args: []
|
|
2358
2455
|
});
|
|
2359
|
-
} catch {
|
|
2456
|
+
} catch (e) {
|
|
2457
|
+
logCatchDebug("migration", e);
|
|
2360
2458
|
}
|
|
2361
2459
|
try {
|
|
2362
2460
|
await client.execute({
|
|
2363
2461
|
sql: `ALTER TABLE tasks ADD COLUMN reviewer TEXT`,
|
|
2364
2462
|
args: []
|
|
2365
2463
|
});
|
|
2366
|
-
} catch {
|
|
2464
|
+
} catch (e) {
|
|
2465
|
+
logCatchDebug("migration", e);
|
|
2367
2466
|
}
|
|
2368
2467
|
try {
|
|
2369
2468
|
await client.execute({
|
|
2370
2469
|
sql: `ALTER TABLE tasks ADD COLUMN context TEXT`,
|
|
2371
2470
|
args: []
|
|
2372
2471
|
});
|
|
2373
|
-
} catch {
|
|
2472
|
+
} catch (e) {
|
|
2473
|
+
logCatchDebug("migration", e);
|
|
2374
2474
|
}
|
|
2375
2475
|
try {
|
|
2376
2476
|
await client.execute({
|
|
2377
2477
|
sql: `ALTER TABLE tasks ADD COLUMN result TEXT`,
|
|
2378
2478
|
args: []
|
|
2379
2479
|
});
|
|
2380
|
-
} catch {
|
|
2480
|
+
} catch (e) {
|
|
2481
|
+
logCatchDebug("migration", e);
|
|
2381
2482
|
}
|
|
2382
2483
|
try {
|
|
2383
2484
|
await client.execute({
|
|
2384
2485
|
sql: `ALTER TABLE tasks ADD COLUMN assigned_tmux TEXT`,
|
|
2385
2486
|
args: []
|
|
2386
2487
|
});
|
|
2387
|
-
} catch {
|
|
2488
|
+
} catch (e) {
|
|
2489
|
+
logCatchDebug("migration", e);
|
|
2388
2490
|
}
|
|
2389
2491
|
try {
|
|
2390
2492
|
await client.execute({
|
|
2391
2493
|
sql: `ALTER TABLE tasks ADD COLUMN checkpoint TEXT`,
|
|
2392
2494
|
args: []
|
|
2393
2495
|
});
|
|
2394
|
-
} catch {
|
|
2496
|
+
} catch (e) {
|
|
2497
|
+
logCatchDebug("migration", e);
|
|
2395
2498
|
}
|
|
2396
2499
|
try {
|
|
2397
2500
|
await client.execute({
|
|
2398
2501
|
sql: `ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER NOT NULL DEFAULT 0`,
|
|
2399
2502
|
args: []
|
|
2400
2503
|
});
|
|
2401
|
-
} catch {
|
|
2504
|
+
} catch (e) {
|
|
2505
|
+
logCatchDebug("migration", e);
|
|
2402
2506
|
}
|
|
2403
2507
|
try {
|
|
2404
2508
|
await client.execute({
|
|
2405
2509
|
sql: `ALTER TABLE tasks ADD COLUMN complexity TEXT NOT NULL DEFAULT 'standard'`,
|
|
2406
2510
|
args: []
|
|
2407
2511
|
});
|
|
2408
|
-
} catch {
|
|
2512
|
+
} catch (e) {
|
|
2513
|
+
logCatchDebug("migration", e);
|
|
2409
2514
|
}
|
|
2410
2515
|
try {
|
|
2411
2516
|
await client.execute({
|
|
2412
2517
|
sql: `ALTER TABLE tasks ADD COLUMN session_scope TEXT`,
|
|
2413
2518
|
args: []
|
|
2414
2519
|
});
|
|
2415
|
-
} catch {
|
|
2520
|
+
} catch (e) {
|
|
2521
|
+
logCatchDebug("migration", e);
|
|
2416
2522
|
}
|
|
2417
2523
|
try {
|
|
2418
2524
|
await client.execute({
|
|
2419
2525
|
sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
|
|
2420
2526
|
args: []
|
|
2421
2527
|
});
|
|
2422
|
-
} catch {
|
|
2528
|
+
} catch (e) {
|
|
2529
|
+
logCatchDebug("migration", e);
|
|
2423
2530
|
}
|
|
2424
2531
|
try {
|
|
2425
2532
|
await client.execute({
|
|
2426
2533
|
sql: `ALTER TABLE memories ADD COLUMN consolidated INTEGER NOT NULL DEFAULT 0`,
|
|
2427
2534
|
args: []
|
|
2428
2535
|
});
|
|
2429
|
-
} catch {
|
|
2536
|
+
} catch (e) {
|
|
2537
|
+
logCatchDebug("migration", e);
|
|
2430
2538
|
}
|
|
2431
2539
|
try {
|
|
2432
2540
|
await client.execute({
|
|
2433
2541
|
sql: `ALTER TABLE memories ADD COLUMN author_device_id TEXT`,
|
|
2434
2542
|
args: []
|
|
2435
2543
|
});
|
|
2436
|
-
} catch {
|
|
2544
|
+
} catch (e) {
|
|
2545
|
+
logCatchDebug("migration", e);
|
|
2437
2546
|
}
|
|
2438
2547
|
try {
|
|
2439
2548
|
await client.execute({
|
|
2440
2549
|
sql: `ALTER TABLE memories ADD COLUMN scope TEXT NOT NULL DEFAULT 'business'`,
|
|
2441
2550
|
args: []
|
|
2442
2551
|
});
|
|
2443
|
-
} catch {
|
|
2552
|
+
} catch (e) {
|
|
2553
|
+
logCatchDebug("migration", e);
|
|
2444
2554
|
}
|
|
2445
2555
|
await client.executeMultiple(`
|
|
2446
2556
|
CREATE TABLE IF NOT EXISTS consolidations (
|
|
@@ -2545,14 +2655,16 @@ async function ensureSchema() {
|
|
|
2545
2655
|
sql: `ALTER TABLE notifications ADD COLUMN session_scope TEXT`,
|
|
2546
2656
|
args: []
|
|
2547
2657
|
});
|
|
2548
|
-
} catch {
|
|
2658
|
+
} catch (e) {
|
|
2659
|
+
logCatchDebug("migration", e);
|
|
2549
2660
|
}
|
|
2550
2661
|
try {
|
|
2551
2662
|
await client.execute({
|
|
2552
2663
|
sql: `ALTER TABLE messages ADD COLUMN session_scope TEXT`,
|
|
2553
2664
|
args: []
|
|
2554
2665
|
});
|
|
2555
|
-
} catch {
|
|
2666
|
+
} catch (e) {
|
|
2667
|
+
logCatchDebug("migration", e);
|
|
2556
2668
|
}
|
|
2557
2669
|
await client.executeMultiple(`
|
|
2558
2670
|
CREATE INDEX IF NOT EXISTS idx_notifications_agent_scope_read
|
|
@@ -2578,7 +2690,8 @@ async function ensureSchema() {
|
|
|
2578
2690
|
sql: `UPDATE tasks SET project_name = 'exe-os' WHERE project_name = 'worker'`,
|
|
2579
2691
|
args: []
|
|
2580
2692
|
});
|
|
2581
|
-
} catch {
|
|
2693
|
+
} catch (e) {
|
|
2694
|
+
logCatchDebug("migration", e);
|
|
2582
2695
|
}
|
|
2583
2696
|
await client.executeMultiple(`
|
|
2584
2697
|
CREATE TABLE IF NOT EXISTS trajectories (
|
|
@@ -2602,7 +2715,8 @@ async function ensureSchema() {
|
|
|
2602
2715
|
`);
|
|
2603
2716
|
try {
|
|
2604
2717
|
await client.execute("ALTER TABLE trajectories ADD COLUMN skill_id TEXT");
|
|
2605
|
-
} catch {
|
|
2718
|
+
} catch (e) {
|
|
2719
|
+
logCatchDebug("migration", e);
|
|
2606
2720
|
}
|
|
2607
2721
|
await client.executeMultiple(`
|
|
2608
2722
|
CREATE TABLE IF NOT EXISTS consolidations (
|
|
@@ -2639,63 +2753,72 @@ async function ensureSchema() {
|
|
|
2639
2753
|
sql: `ALTER TABLE memories ADD COLUMN consolidated INTEGER NOT NULL DEFAULT 0`,
|
|
2640
2754
|
args: []
|
|
2641
2755
|
});
|
|
2642
|
-
} catch {
|
|
2756
|
+
} catch (e) {
|
|
2757
|
+
logCatchDebug("migration", e);
|
|
2643
2758
|
}
|
|
2644
2759
|
try {
|
|
2645
2760
|
await client.execute({
|
|
2646
2761
|
sql: `ALTER TABLE memories ADD COLUMN importance INTEGER DEFAULT 5`,
|
|
2647
2762
|
args: []
|
|
2648
2763
|
});
|
|
2649
|
-
} catch {
|
|
2764
|
+
} catch (e) {
|
|
2765
|
+
logCatchDebug("migration", e);
|
|
2650
2766
|
}
|
|
2651
2767
|
try {
|
|
2652
2768
|
await client.execute({
|
|
2653
2769
|
sql: `ALTER TABLE memories ADD COLUMN status TEXT DEFAULT 'active'`,
|
|
2654
2770
|
args: []
|
|
2655
2771
|
});
|
|
2656
|
-
} catch {
|
|
2772
|
+
} catch (e) {
|
|
2773
|
+
logCatchDebug("migration", e);
|
|
2657
2774
|
}
|
|
2658
2775
|
try {
|
|
2659
2776
|
await client.execute({
|
|
2660
2777
|
sql: `ALTER TABLE memories ADD COLUMN deleted_at TEXT`,
|
|
2661
2778
|
args: []
|
|
2662
2779
|
});
|
|
2663
|
-
} catch {
|
|
2780
|
+
} catch (e) {
|
|
2781
|
+
logCatchDebug("migration", e);
|
|
2664
2782
|
}
|
|
2665
2783
|
try {
|
|
2666
2784
|
await client.execute({
|
|
2667
2785
|
sql: `ALTER TABLE memories ADD COLUMN confidence REAL DEFAULT 0.7`,
|
|
2668
2786
|
args: []
|
|
2669
2787
|
});
|
|
2670
|
-
} catch {
|
|
2788
|
+
} catch (e) {
|
|
2789
|
+
logCatchDebug("migration", e);
|
|
2671
2790
|
}
|
|
2672
2791
|
try {
|
|
2673
2792
|
await client.execute({
|
|
2674
2793
|
sql: `ALTER TABLE memories ADD COLUMN last_accessed TEXT`,
|
|
2675
2794
|
args: []
|
|
2676
2795
|
});
|
|
2677
|
-
} catch {
|
|
2796
|
+
} catch (e) {
|
|
2797
|
+
logCatchDebug("migration", e);
|
|
2678
2798
|
}
|
|
2679
2799
|
try {
|
|
2680
2800
|
await client.execute({
|
|
2681
2801
|
sql: `UPDATE memories SET last_accessed = timestamp WHERE last_accessed IS NULL`,
|
|
2682
2802
|
args: []
|
|
2683
2803
|
});
|
|
2684
|
-
} catch {
|
|
2804
|
+
} catch (e) {
|
|
2805
|
+
logCatchDebug("migration", e);
|
|
2685
2806
|
}
|
|
2686
2807
|
try {
|
|
2687
2808
|
await client.execute({
|
|
2688
2809
|
sql: `ALTER TABLE memories ADD COLUMN wiki_synced INTEGER DEFAULT 0`,
|
|
2689
2810
|
args: []
|
|
2690
2811
|
});
|
|
2691
|
-
} catch {
|
|
2812
|
+
} catch (e) {
|
|
2813
|
+
logCatchDebug("migration", e);
|
|
2692
2814
|
}
|
|
2693
2815
|
try {
|
|
2694
2816
|
await client.execute({
|
|
2695
2817
|
sql: `ALTER TABLE memories ADD COLUMN graph_extracted INTEGER DEFAULT 0`,
|
|
2696
2818
|
args: []
|
|
2697
2819
|
});
|
|
2698
|
-
} catch {
|
|
2820
|
+
} catch (e) {
|
|
2821
|
+
logCatchDebug("migration", e);
|
|
2699
2822
|
}
|
|
2700
2823
|
for (const col of [
|
|
2701
2824
|
"ALTER TABLE memories ADD COLUMN content_hash TEXT",
|
|
@@ -2703,14 +2826,16 @@ async function ensureSchema() {
|
|
|
2703
2826
|
]) {
|
|
2704
2827
|
try {
|
|
2705
2828
|
await client.execute(col);
|
|
2706
|
-
} catch {
|
|
2829
|
+
} catch (e) {
|
|
2830
|
+
logCatchDebug("migration", e);
|
|
2707
2831
|
}
|
|
2708
2832
|
}
|
|
2709
2833
|
try {
|
|
2710
2834
|
await client.execute(
|
|
2711
2835
|
`CREATE INDEX IF NOT EXISTS idx_memories_content_hash ON memories(content_hash, agent_id)`
|
|
2712
2836
|
);
|
|
2713
|
-
} catch {
|
|
2837
|
+
} catch (e) {
|
|
2838
|
+
logCatchDebug("migration", e);
|
|
2714
2839
|
}
|
|
2715
2840
|
try {
|
|
2716
2841
|
await client.execute(
|
|
@@ -2718,7 +2843,8 @@ async function ensureSchema() {
|
|
|
2718
2843
|
ON memories(content_hash, agent_id, project_name, memory_type)
|
|
2719
2844
|
WHERE content_hash IS NOT NULL`
|
|
2720
2845
|
);
|
|
2721
|
-
} catch {
|
|
2846
|
+
} catch (e) {
|
|
2847
|
+
logCatchDebug("migration", e);
|
|
2722
2848
|
}
|
|
2723
2849
|
await client.executeMultiple(`
|
|
2724
2850
|
CREATE TABLE IF NOT EXISTS entities (
|
|
@@ -2794,7 +2920,8 @@ async function ensureSchema() {
|
|
|
2794
2920
|
`);
|
|
2795
2921
|
try {
|
|
2796
2922
|
await client.execute("INSERT INTO entities_fts(entities_fts) VALUES('rebuild')");
|
|
2797
|
-
} catch {
|
|
2923
|
+
} catch (e) {
|
|
2924
|
+
logCatchDebug("migration", e);
|
|
2798
2925
|
}
|
|
2799
2926
|
await client.executeMultiple(`
|
|
2800
2927
|
CREATE TABLE IF NOT EXISTS entity_aliases (
|
|
@@ -2809,14 +2936,16 @@ async function ensureSchema() {
|
|
|
2809
2936
|
]) {
|
|
2810
2937
|
try {
|
|
2811
2938
|
await client.execute(col);
|
|
2812
|
-
} catch {
|
|
2939
|
+
} catch (e) {
|
|
2940
|
+
logCatchDebug("migration", e);
|
|
2813
2941
|
}
|
|
2814
2942
|
}
|
|
2815
2943
|
try {
|
|
2816
2944
|
await client.execute(
|
|
2817
2945
|
`CREATE INDEX IF NOT EXISTS idx_memories_status ON memories(status)`
|
|
2818
2946
|
);
|
|
2819
|
-
} catch {
|
|
2947
|
+
} catch (e) {
|
|
2948
|
+
logCatchDebug("migration", e);
|
|
2820
2949
|
}
|
|
2821
2950
|
await client.executeMultiple(`
|
|
2822
2951
|
CREATE TABLE IF NOT EXISTS identity (
|
|
@@ -2915,7 +3044,8 @@ async function ensureSchema() {
|
|
|
2915
3044
|
sql: `ALTER TABLE memories ADD COLUMN ${column}`,
|
|
2916
3045
|
args: []
|
|
2917
3046
|
});
|
|
2918
|
-
} catch {
|
|
3047
|
+
} catch (e) {
|
|
3048
|
+
logCatchDebug("migration", e);
|
|
2919
3049
|
}
|
|
2920
3050
|
}
|
|
2921
3051
|
for (const col of [
|
|
@@ -2924,7 +3054,8 @@ async function ensureSchema() {
|
|
|
2924
3054
|
]) {
|
|
2925
3055
|
try {
|
|
2926
3056
|
await client.execute(col);
|
|
2927
|
-
} catch {
|
|
3057
|
+
} catch (e) {
|
|
3058
|
+
logCatchDebug("migration", e);
|
|
2928
3059
|
}
|
|
2929
3060
|
}
|
|
2930
3061
|
await client.executeMultiple(`
|
|
@@ -3109,56 +3240,64 @@ async function ensureSchema() {
|
|
|
3109
3240
|
args: []
|
|
3110
3241
|
});
|
|
3111
3242
|
}
|
|
3112
|
-
} catch {
|
|
3243
|
+
} catch (e) {
|
|
3244
|
+
logCatchDebug("session_agent_map backfill", e);
|
|
3113
3245
|
}
|
|
3114
3246
|
try {
|
|
3115
3247
|
await client.execute({
|
|
3116
3248
|
sql: `ALTER TABLE session_agent_map ADD COLUMN cache_cold_count INTEGER NOT NULL DEFAULT 0`,
|
|
3117
3249
|
args: []
|
|
3118
3250
|
});
|
|
3119
|
-
} catch {
|
|
3251
|
+
} catch (e) {
|
|
3252
|
+
logCatchDebug("migration", e);
|
|
3120
3253
|
}
|
|
3121
3254
|
try {
|
|
3122
3255
|
await client.execute({
|
|
3123
3256
|
sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
|
|
3124
3257
|
args: []
|
|
3125
3258
|
});
|
|
3126
|
-
} catch {
|
|
3259
|
+
} catch (e) {
|
|
3260
|
+
logCatchDebug("migration", e);
|
|
3127
3261
|
}
|
|
3128
3262
|
try {
|
|
3129
3263
|
await client.execute({
|
|
3130
3264
|
sql: `ALTER TABLE tasks ADD COLUMN budget_fallback_model TEXT`,
|
|
3131
3265
|
args: []
|
|
3132
3266
|
});
|
|
3133
|
-
} catch {
|
|
3267
|
+
} catch (e) {
|
|
3268
|
+
logCatchDebug("migration", e);
|
|
3134
3269
|
}
|
|
3135
3270
|
try {
|
|
3136
3271
|
await client.execute({
|
|
3137
3272
|
sql: `ALTER TABLE tasks ADD COLUMN tokens_used INTEGER DEFAULT 0`,
|
|
3138
3273
|
args: []
|
|
3139
3274
|
});
|
|
3140
|
-
} catch {
|
|
3275
|
+
} catch (e) {
|
|
3276
|
+
logCatchDebug("migration", e);
|
|
3141
3277
|
}
|
|
3142
3278
|
try {
|
|
3143
3279
|
await client.execute({
|
|
3144
3280
|
sql: `ALTER TABLE tasks ADD COLUMN tokens_warned_at INTEGER`,
|
|
3145
3281
|
args: []
|
|
3146
3282
|
});
|
|
3147
|
-
} catch {
|
|
3283
|
+
} catch (e) {
|
|
3284
|
+
logCatchDebug("migration", e);
|
|
3148
3285
|
}
|
|
3149
3286
|
try {
|
|
3150
3287
|
await client.execute({
|
|
3151
3288
|
sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
|
|
3152
3289
|
args: []
|
|
3153
3290
|
});
|
|
3154
|
-
} catch {
|
|
3291
|
+
} catch (e) {
|
|
3292
|
+
logCatchDebug("migration", e);
|
|
3155
3293
|
}
|
|
3156
3294
|
try {
|
|
3157
3295
|
await client.execute({
|
|
3158
3296
|
sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
|
|
3159
3297
|
args: []
|
|
3160
3298
|
});
|
|
3161
|
-
} catch {
|
|
3299
|
+
} catch (e) {
|
|
3300
|
+
logCatchDebug("migration", e);
|
|
3162
3301
|
}
|
|
3163
3302
|
await client.executeMultiple(`
|
|
3164
3303
|
CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
|
|
@@ -3357,13 +3496,15 @@ async function ensureSchema() {
|
|
|
3357
3496
|
sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
|
|
3358
3497
|
args: []
|
|
3359
3498
|
});
|
|
3360
|
-
} catch {
|
|
3499
|
+
} catch (e) {
|
|
3500
|
+
logCatchDebug("migration", e);
|
|
3361
3501
|
}
|
|
3362
3502
|
try {
|
|
3363
3503
|
await client.execute(
|
|
3364
3504
|
`CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)`
|
|
3365
3505
|
);
|
|
3366
|
-
} catch {
|
|
3506
|
+
} catch (e) {
|
|
3507
|
+
logCatchDebug("migration", e);
|
|
3367
3508
|
}
|
|
3368
3509
|
try {
|
|
3369
3510
|
await client.execute({
|
|
@@ -3374,20 +3515,23 @@ async function ensureSchema() {
|
|
|
3374
3515
|
sql: `UPDATE memories SET tier = 2 WHERE tool_name IN ('store_memory', 'manual') AND importance >= 5 AND tier = 3`,
|
|
3375
3516
|
args: []
|
|
3376
3517
|
});
|
|
3377
|
-
} catch {
|
|
3518
|
+
} catch (e) {
|
|
3519
|
+
logCatchDebug("migration", e);
|
|
3378
3520
|
}
|
|
3379
3521
|
try {
|
|
3380
3522
|
await client.execute({
|
|
3381
3523
|
sql: `ALTER TABLE memories ADD COLUMN supersedes_id TEXT`,
|
|
3382
3524
|
args: []
|
|
3383
3525
|
});
|
|
3384
|
-
} catch {
|
|
3526
|
+
} catch (e) {
|
|
3527
|
+
logCatchDebug("migration", e);
|
|
3385
3528
|
}
|
|
3386
3529
|
try {
|
|
3387
3530
|
await client.execute(
|
|
3388
3531
|
`CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL`
|
|
3389
3532
|
);
|
|
3390
|
-
} catch {
|
|
3533
|
+
} catch (e) {
|
|
3534
|
+
logCatchDebug("migration", e);
|
|
3391
3535
|
}
|
|
3392
3536
|
for (const col of [
|
|
3393
3537
|
"ALTER TABLE tasks ADD COLUMN checkpoint TEXT",
|
|
@@ -3395,7 +3539,8 @@ async function ensureSchema() {
|
|
|
3395
3539
|
]) {
|
|
3396
3540
|
try {
|
|
3397
3541
|
await client.execute(col);
|
|
3398
|
-
} catch {
|
|
3542
|
+
} catch (e) {
|
|
3543
|
+
logCatchDebug("migration", e);
|
|
3399
3544
|
}
|
|
3400
3545
|
}
|
|
3401
3546
|
try {
|
|
@@ -3403,13 +3548,15 @@ async function ensureSchema() {
|
|
|
3403
3548
|
sql: `ALTER TABLE memories ADD COLUMN draft INTEGER DEFAULT 0`,
|
|
3404
3549
|
args: []
|
|
3405
3550
|
});
|
|
3406
|
-
} catch {
|
|
3551
|
+
} catch (e) {
|
|
3552
|
+
logCatchDebug("migration", e);
|
|
3407
3553
|
}
|
|
3408
3554
|
try {
|
|
3409
3555
|
await client.execute(
|
|
3410
3556
|
`CREATE INDEX IF NOT EXISTS idx_memories_draft ON memories(draft) WHERE draft = 1`
|
|
3411
3557
|
);
|
|
3412
|
-
} catch {
|
|
3558
|
+
} catch (e) {
|
|
3559
|
+
logCatchDebug("migration", e);
|
|
3413
3560
|
}
|
|
3414
3561
|
for (const col of [
|
|
3415
3562
|
"ALTER TABLE memories ADD COLUMN valid_from TEXT",
|
|
@@ -3417,7 +3564,8 @@ async function ensureSchema() {
|
|
|
3417
3564
|
]) {
|
|
3418
3565
|
try {
|
|
3419
3566
|
await client.execute(col);
|
|
3420
|
-
} catch {
|
|
3567
|
+
} catch (e) {
|
|
3568
|
+
logCatchDebug("migration", e);
|
|
3421
3569
|
}
|
|
3422
3570
|
}
|
|
3423
3571
|
try {
|
|
@@ -3425,27 +3573,31 @@ async function ensureSchema() {
|
|
|
3425
3573
|
sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
|
|
3426
3574
|
args: []
|
|
3427
3575
|
});
|
|
3428
|
-
} catch {
|
|
3576
|
+
} catch (e) {
|
|
3577
|
+
logCatchDebug("migration", e);
|
|
3429
3578
|
}
|
|
3430
3579
|
try {
|
|
3431
3580
|
await client.execute({
|
|
3432
3581
|
sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
|
|
3433
3582
|
args: []
|
|
3434
3583
|
});
|
|
3435
|
-
} catch {
|
|
3584
|
+
} catch (e) {
|
|
3585
|
+
logCatchDebug("migration", e);
|
|
3436
3586
|
}
|
|
3437
3587
|
try {
|
|
3438
3588
|
await client.execute(
|
|
3439
3589
|
`CREATE INDEX IF NOT EXISTS idx_memories_type ON memories(memory_type)`
|
|
3440
3590
|
);
|
|
3441
|
-
} catch {
|
|
3591
|
+
} catch (e) {
|
|
3592
|
+
logCatchDebug("migration", e);
|
|
3442
3593
|
}
|
|
3443
3594
|
try {
|
|
3444
3595
|
await client.execute({
|
|
3445
3596
|
sql: `ALTER TABLE memories ADD COLUMN trajectory TEXT`,
|
|
3446
3597
|
args: []
|
|
3447
3598
|
});
|
|
3448
|
-
} catch {
|
|
3599
|
+
} catch (e) {
|
|
3600
|
+
logCatchDebug("migration", e);
|
|
3449
3601
|
}
|
|
3450
3602
|
for (const col of [
|
|
3451
3603
|
"ALTER TABLE memories ADD COLUMN intent TEXT",
|
|
@@ -3466,7 +3618,8 @@ async function ensureSchema() {
|
|
|
3466
3618
|
]) {
|
|
3467
3619
|
try {
|
|
3468
3620
|
await client.execute(col);
|
|
3469
|
-
} catch {
|
|
3621
|
+
} catch (e) {
|
|
3622
|
+
logCatchDebug("migration", e);
|
|
3470
3623
|
}
|
|
3471
3624
|
}
|
|
3472
3625
|
try {
|
|
@@ -3474,14 +3627,16 @@ async function ensureSchema() {
|
|
|
3474
3627
|
sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
|
|
3475
3628
|
args: []
|
|
3476
3629
|
});
|
|
3477
|
-
} catch {
|
|
3630
|
+
} catch (e) {
|
|
3631
|
+
logCatchDebug("migration", e);
|
|
3478
3632
|
}
|
|
3479
3633
|
try {
|
|
3480
3634
|
await client.execute({
|
|
3481
3635
|
sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
|
|
3482
3636
|
args: []
|
|
3483
3637
|
});
|
|
3484
|
-
} catch {
|
|
3638
|
+
} catch (e) {
|
|
3639
|
+
logCatchDebug("migration", e);
|
|
3485
3640
|
}
|
|
3486
3641
|
}
|
|
3487
3642
|
async function disposeDatabase() {
|
|
@@ -3492,7 +3647,8 @@ async function disposeDatabase() {
|
|
|
3492
3647
|
if (_client) {
|
|
3493
3648
|
try {
|
|
3494
3649
|
await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
3495
|
-
} catch {
|
|
3650
|
+
} catch (e) {
|
|
3651
|
+
logCatchDebug("WAL checkpoint", e);
|
|
3496
3652
|
}
|
|
3497
3653
|
}
|
|
3498
3654
|
if (_daemonClient) {
|
|
@@ -3508,8 +3664,9 @@ async function disposeDatabase() {
|
|
|
3508
3664
|
_client = null;
|
|
3509
3665
|
_resilientClient = null;
|
|
3510
3666
|
}
|
|
3667
|
+
releaseDbLock();
|
|
3511
3668
|
}
|
|
3512
|
-
var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
|
|
3669
|
+
var _debugDb, _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, _lockFd, DB_LOCK_PATH, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
|
|
3513
3670
|
var init_database = __esm({
|
|
3514
3671
|
"src/lib/database.ts"() {
|
|
3515
3672
|
"use strict";
|
|
@@ -3517,11 +3674,14 @@ var init_database = __esm({
|
|
|
3517
3674
|
init_employees();
|
|
3518
3675
|
init_database_adapter();
|
|
3519
3676
|
init_memory();
|
|
3677
|
+
_debugDb = process.env.EXE_DEBUG === "1";
|
|
3520
3678
|
_client = null;
|
|
3521
3679
|
_resilientClient = null;
|
|
3522
3680
|
_walCheckpointTimer = null;
|
|
3523
3681
|
_daemonClient = null;
|
|
3524
3682
|
_adapterClient = null;
|
|
3683
|
+
_lockFd = null;
|
|
3684
|
+
DB_LOCK_PATH = join(homedir(), ".exe-os", "db.lock");
|
|
3525
3685
|
initTurso = initDatabase;
|
|
3526
3686
|
SOFT_DELETE_RETENTION_DAYS = 7;
|
|
3527
3687
|
disposeTurso = disposeDatabase;
|
|
@@ -3530,7 +3690,7 @@ var init_database = __esm({
|
|
|
3530
3690
|
|
|
3531
3691
|
// src/lib/keychain.ts
|
|
3532
3692
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
3533
|
-
import { existsSync as
|
|
3693
|
+
import { existsSync as existsSync8, statSync as statSync3 } from "fs";
|
|
3534
3694
|
import { execSync as execSync3 } from "child_process";
|
|
3535
3695
|
import path7 from "path";
|
|
3536
3696
|
import os5 from "os";
|
|
@@ -3565,7 +3725,7 @@ function isRootOnlyTrustedServerKeyFile(keyPath) {
|
|
|
3565
3725
|
if (process.platform !== "linux") return false;
|
|
3566
3726
|
try {
|
|
3567
3727
|
const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
|
|
3568
|
-
const st =
|
|
3728
|
+
const st = statSync3(keyPath);
|
|
3569
3729
|
if (!st.isFile() || (st.mode & 63) !== 0) return false;
|
|
3570
3730
|
if (uid === 0) return true;
|
|
3571
3731
|
const exeOsDir = process.env.EXE_OS_DIR;
|
|
@@ -3766,7 +3926,7 @@ async function getMasterKey() {
|
|
|
3766
3926
|
}
|
|
3767
3927
|
}
|
|
3768
3928
|
const keyPath = getKeyPath();
|
|
3769
|
-
if (!
|
|
3929
|
+
if (!existsSync8(keyPath)) {
|
|
3770
3930
|
process.stderr.write(
|
|
3771
3931
|
`[keychain] Key not found at ${keyPath} (HOME=${os5.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
|
|
3772
3932
|
`
|
|
@@ -4101,18 +4261,54 @@ __export(shard_manager_exports, {
|
|
|
4101
4261
|
shardExists: () => shardExists
|
|
4102
4262
|
});
|
|
4103
4263
|
import path8 from "path";
|
|
4104
|
-
import { existsSync as
|
|
4264
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync3, readdirSync, renameSync as renameSync3, statSync as statSync4 } from "fs";
|
|
4105
4265
|
import { createClient as createClient2 } from "@libsql/client";
|
|
4106
4266
|
function initShardManager(encryptionKey) {
|
|
4107
4267
|
_encryptionKey = encryptionKey;
|
|
4108
|
-
|
|
4109
|
-
|
|
4268
|
+
_keyValidated = false;
|
|
4269
|
+
_keyValidationPromise = null;
|
|
4270
|
+
if (!existsSync9(SHARDS_DIR)) {
|
|
4271
|
+
mkdirSync3(SHARDS_DIR, { recursive: true });
|
|
4272
|
+
}
|
|
4273
|
+
const existingShards = readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db"));
|
|
4274
|
+
if (existingShards.length === 0) {
|
|
4275
|
+
_keyValidated = true;
|
|
4110
4276
|
}
|
|
4111
4277
|
_shardingEnabled = true;
|
|
4112
4278
|
if (_evictionTimer) clearInterval(_evictionTimer);
|
|
4113
4279
|
_evictionTimer = setInterval(evictIdleShards, EVICTION_INTERVAL_MS);
|
|
4114
4280
|
_evictionTimer.unref();
|
|
4115
4281
|
}
|
|
4282
|
+
async function validateEncryptionKey() {
|
|
4283
|
+
if (_keyValidated) return true;
|
|
4284
|
+
if (!_encryptionKey) return false;
|
|
4285
|
+
const existingShards = readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db"));
|
|
4286
|
+
if (existingShards.length === 0) {
|
|
4287
|
+
_keyValidated = true;
|
|
4288
|
+
return true;
|
|
4289
|
+
}
|
|
4290
|
+
for (const shardFile of existingShards.slice(0, 3)) {
|
|
4291
|
+
const dbPath = path8.join(SHARDS_DIR, shardFile);
|
|
4292
|
+
const testClient = createClient2({ url: `file:${dbPath}`, encryptionKey: _encryptionKey });
|
|
4293
|
+
try {
|
|
4294
|
+
await testClient.execute("SELECT COUNT(*) FROM sqlite_schema");
|
|
4295
|
+
testClient.close();
|
|
4296
|
+
_keyValidated = true;
|
|
4297
|
+
return true;
|
|
4298
|
+
} catch {
|
|
4299
|
+
try {
|
|
4300
|
+
testClient.close();
|
|
4301
|
+
} catch {
|
|
4302
|
+
}
|
|
4303
|
+
}
|
|
4304
|
+
}
|
|
4305
|
+
process.stderr.write(
|
|
4306
|
+
`[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.
|
|
4307
|
+
`
|
|
4308
|
+
);
|
|
4309
|
+
_shardingEnabled = false;
|
|
4310
|
+
return false;
|
|
4311
|
+
}
|
|
4116
4312
|
function isShardingEnabled() {
|
|
4117
4313
|
return _shardingEnabled;
|
|
4118
4314
|
}
|
|
@@ -4146,13 +4342,13 @@ function getShardClient(projectName) {
|
|
|
4146
4342
|
}
|
|
4147
4343
|
function shardExists(projectName) {
|
|
4148
4344
|
const safeName = safeShardName(projectName);
|
|
4149
|
-
return
|
|
4345
|
+
return existsSync9(path8.join(SHARDS_DIR, `${safeName}.db`));
|
|
4150
4346
|
}
|
|
4151
4347
|
function safeShardName(projectName) {
|
|
4152
4348
|
return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
4153
4349
|
}
|
|
4154
4350
|
function listShards() {
|
|
4155
|
-
if (!
|
|
4351
|
+
if (!existsSync9(SHARDS_DIR)) return [];
|
|
4156
4352
|
return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
4157
4353
|
}
|
|
4158
4354
|
async function auditShardHealth(options = {}) {
|
|
@@ -4165,7 +4361,7 @@ async function auditShardHealth(options = {}) {
|
|
|
4165
4361
|
const shards = [];
|
|
4166
4362
|
for (const name of names) {
|
|
4167
4363
|
const dbPath = path8.join(SHARDS_DIR, `${name}.db`);
|
|
4168
|
-
const stat =
|
|
4364
|
+
const stat = statSync4(dbPath);
|
|
4169
4365
|
const item = {
|
|
4170
4366
|
name,
|
|
4171
4367
|
path: dbPath,
|
|
@@ -4405,6 +4601,17 @@ async function ensureShardSchema(client) {
|
|
|
4405
4601
|
}
|
|
4406
4602
|
}
|
|
4407
4603
|
async function getReadyShardClient(projectName) {
|
|
4604
|
+
if (!_keyValidated) {
|
|
4605
|
+
if (!_keyValidationPromise) {
|
|
4606
|
+
_keyValidationPromise = validateEncryptionKey();
|
|
4607
|
+
}
|
|
4608
|
+
const valid = await _keyValidationPromise;
|
|
4609
|
+
if (!valid) {
|
|
4610
|
+
throw new Error(
|
|
4611
|
+
`Shard creation blocked: encryption key mismatch with existing shards. Run /exe-doctor to audit.`
|
|
4612
|
+
);
|
|
4613
|
+
}
|
|
4614
|
+
}
|
|
4408
4615
|
const safeName = safeShardName(projectName);
|
|
4409
4616
|
let client = getShardClient(projectName);
|
|
4410
4617
|
try {
|
|
@@ -4417,8 +4624,8 @@ async function getReadyShardClient(projectName) {
|
|
|
4417
4624
|
_shards.delete(safeName);
|
|
4418
4625
|
_shardLastAccess.delete(safeName);
|
|
4419
4626
|
const dbPath = path8.join(SHARDS_DIR, `${safeName}.db`);
|
|
4420
|
-
if (
|
|
4421
|
-
const stat =
|
|
4627
|
+
if (existsSync9(dbPath)) {
|
|
4628
|
+
const stat = statSync4(dbPath);
|
|
4422
4629
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
4423
4630
|
const archivedPath = path8.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
4424
4631
|
renameSync3(dbPath, archivedPath);
|
|
@@ -4483,7 +4690,7 @@ function disposeShards() {
|
|
|
4483
4690
|
_shardingEnabled = false;
|
|
4484
4691
|
_encryptionKey = null;
|
|
4485
4692
|
}
|
|
4486
|
-
var SHARDS_DIR, SHARD_IDLE_MS, MAX_OPEN_SHARDS, EVICTION_INTERVAL_MS, _shards, _shardLastAccess, _evictionTimer, _encryptionKey, _shardingEnabled;
|
|
4693
|
+
var SHARDS_DIR, SHARD_IDLE_MS, MAX_OPEN_SHARDS, EVICTION_INTERVAL_MS, _shards, _shardLastAccess, _evictionTimer, _encryptionKey, _shardingEnabled, _keyValidated, _keyValidationPromise;
|
|
4487
4694
|
var init_shard_manager = __esm({
|
|
4488
4695
|
"src/lib/shard-manager.ts"() {
|
|
4489
4696
|
"use strict";
|
|
@@ -4497,6 +4704,8 @@ var init_shard_manager = __esm({
|
|
|
4497
4704
|
_evictionTimer = null;
|
|
4498
4705
|
_encryptionKey = null;
|
|
4499
4706
|
_shardingEnabled = false;
|
|
4707
|
+
_keyValidated = false;
|
|
4708
|
+
_keyValidationPromise = null;
|
|
4500
4709
|
}
|
|
4501
4710
|
});
|
|
4502
4711
|
|
|
@@ -4692,6 +4901,18 @@ var init_platform_procedures = __esm({
|
|
|
4692
4901
|
priority: "p0",
|
|
4693
4902
|
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.'"
|
|
4694
4903
|
},
|
|
4904
|
+
{
|
|
4905
|
+
title: "Review chain \u2014 managers must actively pull completed work, never wait for nudges",
|
|
4906
|
+
domain: "workflow",
|
|
4907
|
+
priority: "p0",
|
|
4908
|
+
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."
|
|
4909
|
+
},
|
|
4910
|
+
{
|
|
4911
|
+
title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
|
|
4912
|
+
domain: "workflow",
|
|
4913
|
+
priority: "p0",
|
|
4914
|
+
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."
|
|
4915
|
+
},
|
|
4695
4916
|
{
|
|
4696
4917
|
title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
|
|
4697
4918
|
domain: "architecture",
|
|
@@ -5289,6 +5510,20 @@ __export(store_exports, {
|
|
|
5289
5510
|
vectorToBlob: () => vectorToBlob,
|
|
5290
5511
|
writeMemory: () => writeMemory
|
|
5291
5512
|
});
|
|
5513
|
+
function logStoreDebug(context, err) {
|
|
5514
|
+
if (_debugStore) {
|
|
5515
|
+
process.stderr.write(
|
|
5516
|
+
`[store] ${context}: ${err instanceof Error ? err.message : String(err)}
|
|
5517
|
+
`
|
|
5518
|
+
);
|
|
5519
|
+
}
|
|
5520
|
+
}
|
|
5521
|
+
function logStoreWarn(context, err) {
|
|
5522
|
+
process.stderr.write(
|
|
5523
|
+
`[store] WARN ${context}: ${err instanceof Error ? err.message : String(err)}
|
|
5524
|
+
`
|
|
5525
|
+
);
|
|
5526
|
+
}
|
|
5292
5527
|
function isBusyError2(err) {
|
|
5293
5528
|
if (err instanceof Error) {
|
|
5294
5529
|
const msg = err.message.toLowerCase();
|
|
@@ -5343,13 +5578,15 @@ async function initStore(options) {
|
|
|
5343
5578
|
try {
|
|
5344
5579
|
const { initDaemonClient: initDaemonClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
5345
5580
|
await initDaemonClient2();
|
|
5346
|
-
} catch {
|
|
5581
|
+
} catch (e) {
|
|
5582
|
+
logStoreWarn("catch", e);
|
|
5347
5583
|
}
|
|
5348
5584
|
if (!options?.lightweight) {
|
|
5349
5585
|
try {
|
|
5350
5586
|
const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
5351
5587
|
initShardManager2(hexKey);
|
|
5352
|
-
} catch {
|
|
5588
|
+
} catch (e) {
|
|
5589
|
+
logStoreWarn("catch", e);
|
|
5353
5590
|
}
|
|
5354
5591
|
const client = getClient();
|
|
5355
5592
|
const vResult = await retryOnBusy2(
|
|
@@ -5360,7 +5597,8 @@ async function initStore(options) {
|
|
|
5360
5597
|
try {
|
|
5361
5598
|
const { loadGlobalProcedures: loadGlobalProcedures2 } = await Promise.resolve().then(() => (init_global_procedures(), global_procedures_exports));
|
|
5362
5599
|
await loadGlobalProcedures2();
|
|
5363
|
-
} catch {
|
|
5600
|
+
} catch (e) {
|
|
5601
|
+
logStoreWarn("catch", e);
|
|
5364
5602
|
}
|
|
5365
5603
|
}
|
|
5366
5604
|
}
|
|
@@ -5420,7 +5658,8 @@ async function writeMemory(record) {
|
|
|
5420
5658
|
memoryType
|
|
5421
5659
|
});
|
|
5422
5660
|
if (existing) return;
|
|
5423
|
-
} catch {
|
|
5661
|
+
} catch (e) {
|
|
5662
|
+
logStoreWarn("catch", e);
|
|
5424
5663
|
}
|
|
5425
5664
|
const dbRow = {
|
|
5426
5665
|
id: record.id,
|
|
@@ -5621,12 +5860,14 @@ async function flushBatch() {
|
|
|
5621
5860
|
try {
|
|
5622
5861
|
const { insertMemoryCardsForBatch: insertMemoryCardsForBatch2 } = await Promise.resolve().then(() => (init_memory_cards(), memory_cards_exports));
|
|
5623
5862
|
await insertMemoryCardsForBatch2(batch);
|
|
5624
|
-
} catch {
|
|
5863
|
+
} catch (e) {
|
|
5864
|
+
logStoreWarn("catch", e);
|
|
5625
5865
|
}
|
|
5626
5866
|
try {
|
|
5627
5867
|
const { insertOntologyForBatch: insertOntologyForBatch2 } = await Promise.resolve().then(() => (init_agentic_ontology(), agentic_ontology_exports));
|
|
5628
5868
|
await insertOntologyForBatch2(batch);
|
|
5629
|
-
} catch {
|
|
5869
|
+
} catch (e) {
|
|
5870
|
+
logStoreWarn("catch", e);
|
|
5630
5871
|
}
|
|
5631
5872
|
schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
|
|
5632
5873
|
_pendingRecords.splice(0, batch.length);
|
|
@@ -5665,7 +5906,8 @@ ${err.stack.split("\n").slice(1, 3).join("\n")}` : ""}` : String(err);
|
|
|
5665
5906
|
}
|
|
5666
5907
|
}
|
|
5667
5908
|
}
|
|
5668
|
-
} catch {
|
|
5909
|
+
} catch (e) {
|
|
5910
|
+
logStoreWarn("catch", e);
|
|
5669
5911
|
}
|
|
5670
5912
|
return batch.length;
|
|
5671
5913
|
} finally {
|
|
@@ -5707,7 +5949,8 @@ async function searchMemories(queryVector, agentId, options) {
|
|
|
5707
5949
|
} else {
|
|
5708
5950
|
client = getClient();
|
|
5709
5951
|
}
|
|
5710
|
-
} catch {
|
|
5952
|
+
} catch (e) {
|
|
5953
|
+
logStoreDebug("shard routing fallback", e);
|
|
5711
5954
|
client = getClient();
|
|
5712
5955
|
}
|
|
5713
5956
|
const limit = options?.limit ?? 10;
|
|
@@ -5823,7 +6066,8 @@ async function attachDocumentMetadata(records) {
|
|
|
5823
6066
|
if (!record.document_id) continue;
|
|
5824
6067
|
record.document_metadata = byId.get(record.document_id) ?? null;
|
|
5825
6068
|
}
|
|
5826
|
-
} catch {
|
|
6069
|
+
} catch (e) {
|
|
6070
|
+
logStoreWarn("catch", e);
|
|
5827
6071
|
}
|
|
5828
6072
|
return records;
|
|
5829
6073
|
}
|
|
@@ -5884,11 +6128,12 @@ async function getMemoryCardinality(agentId) {
|
|
|
5884
6128
|
args: [agentId]
|
|
5885
6129
|
});
|
|
5886
6130
|
return Number(result.rows[0]?.cnt) || 0;
|
|
5887
|
-
} catch {
|
|
6131
|
+
} catch (e) {
|
|
6132
|
+
logStoreWarn("getMemoryCardinality", e);
|
|
5888
6133
|
return 0;
|
|
5889
6134
|
}
|
|
5890
6135
|
}
|
|
5891
|
-
var INIT_MAX_RETRIES, INIT_RETRY_DELAY_MS, _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
|
|
6136
|
+
var _debugStore, INIT_MAX_RETRIES, INIT_RETRY_DELAY_MS, _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
|
|
5892
6137
|
var init_store = __esm({
|
|
5893
6138
|
"src/lib/store.ts"() {
|
|
5894
6139
|
"use strict";
|
|
@@ -5898,6 +6143,7 @@ var init_store = __esm({
|
|
|
5898
6143
|
init_config();
|
|
5899
6144
|
init_state_bus();
|
|
5900
6145
|
init_memory_write_governor();
|
|
6146
|
+
_debugStore = process.env.EXE_DEBUG === "1";
|
|
5901
6147
|
INIT_MAX_RETRIES = 3;
|
|
5902
6148
|
INIT_RETRY_DELAY_MS = 1e3;
|
|
5903
6149
|
_pendingRecords = [];
|
|
@@ -5910,13 +6156,13 @@ var init_store = __esm({
|
|
|
5910
6156
|
});
|
|
5911
6157
|
|
|
5912
6158
|
// src/lib/session-registry.ts
|
|
5913
|
-
import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, mkdirSync as
|
|
6159
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as existsSync10 } from "fs";
|
|
5914
6160
|
import path9 from "path";
|
|
5915
6161
|
import os6 from "os";
|
|
5916
6162
|
function registerSession(entry) {
|
|
5917
6163
|
const dir = path9.dirname(REGISTRY_PATH);
|
|
5918
|
-
if (!
|
|
5919
|
-
|
|
6164
|
+
if (!existsSync10(dir)) {
|
|
6165
|
+
mkdirSync4(dir, { recursive: true });
|
|
5920
6166
|
}
|
|
5921
6167
|
const sessions = listSessions();
|
|
5922
6168
|
const idx = sessions.findIndex((s) => s.windowName === entry.windowName);
|
|
@@ -6210,16 +6456,16 @@ __export(intercom_queue_exports, {
|
|
|
6210
6456
|
queueIntercom: () => queueIntercom,
|
|
6211
6457
|
readQueue: () => readQueue
|
|
6212
6458
|
});
|
|
6213
|
-
import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, renameSync as renameSync4, existsSync as
|
|
6459
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, renameSync as renameSync4, existsSync as existsSync11, mkdirSync as mkdirSync5 } from "fs";
|
|
6214
6460
|
import path10 from "path";
|
|
6215
6461
|
import os7 from "os";
|
|
6216
6462
|
function ensureDir() {
|
|
6217
6463
|
const dir = path10.dirname(QUEUE_PATH);
|
|
6218
|
-
if (!
|
|
6464
|
+
if (!existsSync11(dir)) mkdirSync5(dir, { recursive: true });
|
|
6219
6465
|
}
|
|
6220
6466
|
function readQueue() {
|
|
6221
6467
|
try {
|
|
6222
|
-
if (!
|
|
6468
|
+
if (!existsSync11(QUEUE_PATH)) return [];
|
|
6223
6469
|
return JSON.parse(readFileSync7(QUEUE_PATH, "utf8"));
|
|
6224
6470
|
} catch {
|
|
6225
6471
|
return [];
|
|
@@ -6328,7 +6574,7 @@ var init_intercom_queue = __esm({
|
|
|
6328
6574
|
});
|
|
6329
6575
|
|
|
6330
6576
|
// src/lib/license.ts
|
|
6331
|
-
import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, existsSync as
|
|
6577
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, existsSync as existsSync12, mkdirSync as mkdirSync6 } from "fs";
|
|
6332
6578
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
6333
6579
|
import { createRequire as createRequire2 } from "module";
|
|
6334
6580
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
@@ -6355,11 +6601,11 @@ var init_license = __esm({
|
|
|
6355
6601
|
});
|
|
6356
6602
|
|
|
6357
6603
|
// src/lib/plan-limits.ts
|
|
6358
|
-
import { readFileSync as readFileSync9, existsSync as
|
|
6604
|
+
import { readFileSync as readFileSync9, existsSync as existsSync13 } from "fs";
|
|
6359
6605
|
import path12 from "path";
|
|
6360
6606
|
function getLicenseSync() {
|
|
6361
6607
|
try {
|
|
6362
|
-
if (!
|
|
6608
|
+
if (!existsSync13(CACHE_PATH2)) return freeLicense();
|
|
6363
6609
|
const raw = JSON.parse(readFileSync9(CACHE_PATH2, "utf8"));
|
|
6364
6610
|
if (!raw.token || typeof raw.token !== "string") return freeLicense();
|
|
6365
6611
|
const parts = raw.token.split(".");
|
|
@@ -6398,7 +6644,7 @@ function assertEmployeeLimitSync(rosterPath) {
|
|
|
6398
6644
|
const filePath = rosterPath ?? EMPLOYEES_PATH;
|
|
6399
6645
|
let count = 0;
|
|
6400
6646
|
try {
|
|
6401
|
-
if (
|
|
6647
|
+
if (existsSync13(filePath)) {
|
|
6402
6648
|
const raw = readFileSync9(filePath, "utf8");
|
|
6403
6649
|
const employees = JSON.parse(raw);
|
|
6404
6650
|
count = Array.isArray(employees) ? employees.length : 0;
|
|
@@ -6436,9 +6682,9 @@ var init_plan_limits = __esm({
|
|
|
6436
6682
|
import os9 from "os";
|
|
6437
6683
|
import path13 from "path";
|
|
6438
6684
|
import {
|
|
6439
|
-
existsSync as
|
|
6685
|
+
existsSync as existsSync14,
|
|
6440
6686
|
lstatSync,
|
|
6441
|
-
mkdirSync as
|
|
6687
|
+
mkdirSync as mkdirSync7,
|
|
6442
6688
|
readlinkSync as readlinkSync2,
|
|
6443
6689
|
symlinkSync as symlinkSync2
|
|
6444
6690
|
} from "fs";
|
|
@@ -6454,8 +6700,8 @@ function claudeAgentLinkPath(homeDir, agentId) {
|
|
|
6454
6700
|
function ensureAgentSymlink(agentId, homeDir = os9.homedir()) {
|
|
6455
6701
|
const target = identitySourcePath(homeDir, agentId);
|
|
6456
6702
|
const link = claudeAgentLinkPath(homeDir, agentId);
|
|
6457
|
-
|
|
6458
|
-
if (
|
|
6703
|
+
mkdirSync7(claudeAgentsDir(homeDir), { recursive: true });
|
|
6704
|
+
if (existsSync14(link)) {
|
|
6459
6705
|
let stat;
|
|
6460
6706
|
try {
|
|
6461
6707
|
stat = lstatSync(link);
|
|
@@ -6829,7 +7075,7 @@ __export(tasks_review_exports, {
|
|
|
6829
7075
|
listPendingReviews: () => listPendingReviews
|
|
6830
7076
|
});
|
|
6831
7077
|
import path14 from "path";
|
|
6832
|
-
import { existsSync as
|
|
7078
|
+
import { existsSync as existsSync15, readdirSync as readdirSync2, unlinkSync as unlinkSync4 } from "fs";
|
|
6833
7079
|
function formatAge(isoTimestamp) {
|
|
6834
7080
|
if (!isoTimestamp) return "";
|
|
6835
7081
|
const ms = Date.now() - new Date(isoTimestamp).getTime();
|
|
@@ -7099,10 +7345,10 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
|
|
|
7099
7345
|
}
|
|
7100
7346
|
try {
|
|
7101
7347
|
const cacheDir = path14.join(EXE_AI_DIR, "session-cache");
|
|
7102
|
-
if (
|
|
7348
|
+
if (existsSync15(cacheDir)) {
|
|
7103
7349
|
for (const f of readdirSync2(cacheDir)) {
|
|
7104
7350
|
if (f.startsWith("review-notified-")) {
|
|
7105
|
-
|
|
7351
|
+
unlinkSync4(path14.join(cacheDir, f));
|
|
7106
7352
|
}
|
|
7107
7353
|
}
|
|
7108
7354
|
}
|
|
@@ -7149,11 +7395,11 @@ __export(tmux_routing_exports, {
|
|
|
7149
7395
|
verifyPaneAtCapacity: () => verifyPaneAtCapacity
|
|
7150
7396
|
});
|
|
7151
7397
|
import { execFileSync as execFileSync2, execSync as execSync6 } from "child_process";
|
|
7152
|
-
import { readFileSync as readFileSync10, writeFileSync as writeFileSync7, mkdirSync as
|
|
7398
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync7, mkdirSync as mkdirSync8, existsSync as existsSync16, appendFileSync, readdirSync as readdirSync3 } from "fs";
|
|
7153
7399
|
import path15 from "path";
|
|
7154
7400
|
import os10 from "os";
|
|
7155
7401
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
7156
|
-
import { unlinkSync as
|
|
7402
|
+
import { unlinkSync as unlinkSync5 } from "fs";
|
|
7157
7403
|
function spawnLockPath(sessionName) {
|
|
7158
7404
|
return path15.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
|
|
7159
7405
|
}
|
|
@@ -7166,11 +7412,11 @@ function isProcessAlive(pid) {
|
|
|
7166
7412
|
}
|
|
7167
7413
|
}
|
|
7168
7414
|
function acquireSpawnLock2(sessionName) {
|
|
7169
|
-
if (!
|
|
7170
|
-
|
|
7415
|
+
if (!existsSync16(SPAWN_LOCK_DIR)) {
|
|
7416
|
+
mkdirSync8(SPAWN_LOCK_DIR, { recursive: true });
|
|
7171
7417
|
}
|
|
7172
7418
|
const lockFile = spawnLockPath(sessionName);
|
|
7173
|
-
if (
|
|
7419
|
+
if (existsSync16(lockFile)) {
|
|
7174
7420
|
try {
|
|
7175
7421
|
const lock = JSON.parse(readFileSync10(lockFile, "utf8"));
|
|
7176
7422
|
const age = Date.now() - lock.timestamp;
|
|
@@ -7185,7 +7431,7 @@ function acquireSpawnLock2(sessionName) {
|
|
|
7185
7431
|
}
|
|
7186
7432
|
function releaseSpawnLock2(sessionName) {
|
|
7187
7433
|
try {
|
|
7188
|
-
|
|
7434
|
+
unlinkSync5(spawnLockPath(sessionName));
|
|
7189
7435
|
} catch {
|
|
7190
7436
|
}
|
|
7191
7437
|
}
|
|
@@ -7198,7 +7444,7 @@ function resolveBehaviorsExporterScript() {
|
|
|
7198
7444
|
"bin",
|
|
7199
7445
|
"exe-export-behaviors.js"
|
|
7200
7446
|
);
|
|
7201
|
-
return
|
|
7447
|
+
return existsSync16(scriptPath) ? scriptPath : null;
|
|
7202
7448
|
} catch {
|
|
7203
7449
|
return null;
|
|
7204
7450
|
}
|
|
@@ -7264,8 +7510,8 @@ function extractRootExe(name) {
|
|
|
7264
7510
|
return parts.length > 0 ? parts[parts.length - 1] : null;
|
|
7265
7511
|
}
|
|
7266
7512
|
function registerParentExe(sessionKey, parentExe, dispatchedBy) {
|
|
7267
|
-
if (!
|
|
7268
|
-
|
|
7513
|
+
if (!existsSync16(SESSION_CACHE)) {
|
|
7514
|
+
mkdirSync8(SESSION_CACHE, { recursive: true });
|
|
7269
7515
|
}
|
|
7270
7516
|
const rootExe = extractRootExe(parentExe) ?? parentExe;
|
|
7271
7517
|
const filePath = path15.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
|
|
@@ -7295,11 +7541,13 @@ function getDispatchedBy(sessionKey) {
|
|
|
7295
7541
|
}
|
|
7296
7542
|
}
|
|
7297
7543
|
function resolveExeSession() {
|
|
7298
|
-
if (process.env.EXE_SESSION_NAME) {
|
|
7299
|
-
return extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
|
|
7300
|
-
}
|
|
7301
7544
|
const mySession = getMySession();
|
|
7302
|
-
if (!mySession)
|
|
7545
|
+
if (!mySession) {
|
|
7546
|
+
if (process.env.EXE_SESSION_NAME) {
|
|
7547
|
+
return extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
|
|
7548
|
+
}
|
|
7549
|
+
return null;
|
|
7550
|
+
}
|
|
7303
7551
|
const fromSessionName = extractRootExe(mySession);
|
|
7304
7552
|
let candidate = null;
|
|
7305
7553
|
try {
|
|
@@ -7394,7 +7642,7 @@ async function verifyPaneAtCapacity(sessionName) {
|
|
|
7394
7642
|
}
|
|
7395
7643
|
function readDebounceState() {
|
|
7396
7644
|
try {
|
|
7397
|
-
if (!
|
|
7645
|
+
if (!existsSync16(DEBOUNCE_FILE)) return {};
|
|
7398
7646
|
const raw = JSON.parse(readFileSync10(DEBOUNCE_FILE, "utf8"));
|
|
7399
7647
|
const state = {};
|
|
7400
7648
|
for (const [key, val] of Object.entries(raw)) {
|
|
@@ -7411,7 +7659,7 @@ function readDebounceState() {
|
|
|
7411
7659
|
}
|
|
7412
7660
|
function writeDebounceState(state) {
|
|
7413
7661
|
try {
|
|
7414
|
-
if (!
|
|
7662
|
+
if (!existsSync16(SESSION_CACHE)) mkdirSync8(SESSION_CACHE, { recursive: true });
|
|
7415
7663
|
writeFileSync7(DEBOUNCE_FILE, JSON.stringify(state));
|
|
7416
7664
|
} catch {
|
|
7417
7665
|
}
|
|
@@ -7512,7 +7760,7 @@ function sendIntercom(targetSession) {
|
|
|
7512
7760
|
const rawAgent = targetSession.split("-")[0] ?? targetSession;
|
|
7513
7761
|
const agent = baseAgentName(rawAgent);
|
|
7514
7762
|
const markerPath = path15.join(SESSION_CACHE, `current-task-${agent}.json`);
|
|
7515
|
-
if (
|
|
7763
|
+
if (existsSync16(markerPath)) {
|
|
7516
7764
|
logIntercom(`SKIP \u2192 ${targetSession} (has in_progress task marker + not idle \u2014 will auto-chain)`);
|
|
7517
7765
|
return "debounced";
|
|
7518
7766
|
}
|
|
@@ -7523,7 +7771,7 @@ function sendIntercom(targetSession) {
|
|
|
7523
7771
|
const rawAgent = targetSession.split("-")[0] ?? targetSession;
|
|
7524
7772
|
const agent = baseAgentName(rawAgent);
|
|
7525
7773
|
const taskDir = path15.join(process.cwd(), "exe", agent);
|
|
7526
|
-
if (
|
|
7774
|
+
if (existsSync16(taskDir)) {
|
|
7527
7775
|
const files = readdirSync3(taskDir).filter(
|
|
7528
7776
|
(f) => f.endsWith(".md") && f !== "DONE.txt"
|
|
7529
7777
|
);
|
|
@@ -7684,15 +7932,15 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
7684
7932
|
const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
|
|
7685
7933
|
const logDir = path15.join(os10.homedir(), ".exe-os", "session-logs");
|
|
7686
7934
|
const logFile = path15.join(logDir, `${instanceLabel}-${Date.now()}.log`);
|
|
7687
|
-
if (!
|
|
7688
|
-
|
|
7935
|
+
if (!existsSync16(logDir)) {
|
|
7936
|
+
mkdirSync8(logDir, { recursive: true });
|
|
7689
7937
|
}
|
|
7690
7938
|
transport.kill(sessionName);
|
|
7691
7939
|
let cleanupSuffix = "";
|
|
7692
7940
|
try {
|
|
7693
7941
|
const thisFile = fileURLToPath2(import.meta.url);
|
|
7694
7942
|
const cleanupScript = path15.join(path15.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
|
|
7695
|
-
if (
|
|
7943
|
+
if (existsSync16(cleanupScript)) {
|
|
7696
7944
|
cleanupSuffix = `; ${process.execPath} "${cleanupScript}" "${employeeName}" "${exeSession}"`;
|
|
7697
7945
|
}
|
|
7698
7946
|
} catch {
|
|
@@ -7747,7 +7995,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
7747
7995
|
if (changed) {
|
|
7748
7996
|
perms.allow = allow;
|
|
7749
7997
|
settings.permissions = perms;
|
|
7750
|
-
|
|
7998
|
+
mkdirSync8(projSettingsDir, { recursive: true });
|
|
7751
7999
|
writeFileSync7(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
7752
8000
|
}
|
|
7753
8001
|
} catch {
|
|
@@ -7785,7 +8033,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
7785
8033
|
`
|
|
7786
8034
|
);
|
|
7787
8035
|
}
|
|
7788
|
-
} else if (
|
|
8036
|
+
} else if (existsSync16(identityPath)) {
|
|
7789
8037
|
identityFlag = ` --append-system-prompt-file ${identityPath}`;
|
|
7790
8038
|
legacyFallbackWarned = true;
|
|
7791
8039
|
}
|
|
@@ -7807,7 +8055,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
7807
8055
|
let sessionContextFlag = "";
|
|
7808
8056
|
try {
|
|
7809
8057
|
const ctxDir = path15.join(os10.homedir(), ".exe-os", "session-cache");
|
|
7810
|
-
|
|
8058
|
+
mkdirSync8(ctxDir, { recursive: true });
|
|
7811
8059
|
const ctxFile = path15.join(ctxDir, `session-context-${sessionName}.md`);
|
|
7812
8060
|
const ctxContent = [
|
|
7813
8061
|
`## Session Context`,
|
|
@@ -8028,8 +8276,8 @@ import os11 from "os";
|
|
|
8028
8276
|
import {
|
|
8029
8277
|
readFileSync as readFileSync11,
|
|
8030
8278
|
readdirSync as readdirSync4,
|
|
8031
|
-
unlinkSync as
|
|
8032
|
-
existsSync as
|
|
8279
|
+
unlinkSync as unlinkSync6,
|
|
8280
|
+
existsSync as existsSync17,
|
|
8033
8281
|
rmdirSync
|
|
8034
8282
|
} from "fs";
|
|
8035
8283
|
async function writeNotification(notification) {
|
|
@@ -8188,7 +8436,7 @@ import path18 from "path";
|
|
|
8188
8436
|
import os12 from "os";
|
|
8189
8437
|
import { execSync as execSync8 } from "child_process";
|
|
8190
8438
|
import { mkdir as mkdir4, writeFile as writeFile4, appendFile } from "fs/promises";
|
|
8191
|
-
import { existsSync as
|
|
8439
|
+
import { existsSync as existsSync18, readFileSync as readFileSync12 } from "fs";
|
|
8192
8440
|
async function writeCheckpoint(input) {
|
|
8193
8441
|
const client = getClient();
|
|
8194
8442
|
const row = await resolveTask(client, input.taskId);
|
|
@@ -8429,7 +8677,7 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
|
|
|
8429
8677
|
const EXE_OS_DIR = path18.join(os12.homedir(), ".exe-os");
|
|
8430
8678
|
const mdPath = path18.join(EXE_OS_DIR, taskFile);
|
|
8431
8679
|
const mdDir = path18.dirname(mdPath);
|
|
8432
|
-
if (!
|
|
8680
|
+
if (!existsSync18(mdDir)) await mkdir4(mdDir, { recursive: true });
|
|
8433
8681
|
const reviewer = input.reviewer ?? input.assignedBy;
|
|
8434
8682
|
const mdContent = `# ${input.title}
|
|
8435
8683
|
|
|
@@ -8735,7 +8983,7 @@ async function deleteTaskCore(taskId, _baseDir) {
|
|
|
8735
8983
|
async function ensureArchitectureDoc(baseDir, projectName) {
|
|
8736
8984
|
const archPath = path18.join(baseDir, "exe", "ARCHITECTURE.md");
|
|
8737
8985
|
try {
|
|
8738
|
-
if (
|
|
8986
|
+
if (existsSync18(archPath)) return;
|
|
8739
8987
|
const template = [
|
|
8740
8988
|
`# ${projectName} \u2014 System Architecture`,
|
|
8741
8989
|
"",
|
|
@@ -8770,7 +9018,7 @@ async function ensureArchitectureDoc(baseDir, projectName) {
|
|
|
8770
9018
|
async function ensureGitignoreExe(baseDir) {
|
|
8771
9019
|
const gitignorePath = path18.join(baseDir, ".gitignore");
|
|
8772
9020
|
try {
|
|
8773
|
-
if (
|
|
9021
|
+
if (existsSync18(gitignorePath)) {
|
|
8774
9022
|
const content = readFileSync12(gitignorePath, "utf-8");
|
|
8775
9023
|
if (/^\/?exe\/?$/m.test(content)) return;
|
|
8776
9024
|
await appendFile(gitignorePath, "\n# Employee task assignments (private)\n/exe/\n");
|
|
@@ -9003,10 +9251,10 @@ async function disposeEmbedder() {
|
|
|
9003
9251
|
async function embedDirect(text) {
|
|
9004
9252
|
const llamaCpp = await import("node-llama-cpp");
|
|
9005
9253
|
const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
9006
|
-
const { existsSync:
|
|
9254
|
+
const { existsSync: existsSync19 } = await import("fs");
|
|
9007
9255
|
const path21 = await import("path");
|
|
9008
9256
|
const modelPath = path21.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
|
|
9009
|
-
if (!
|
|
9257
|
+
if (!existsSync19(modelPath)) {
|
|
9010
9258
|
throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
|
|
9011
9259
|
}
|
|
9012
9260
|
const llama = await llamaCpp.getLlama();
|
|
@@ -9373,7 +9621,7 @@ __export(tasks_exports, {
|
|
|
9373
9621
|
writeCheckpoint: () => writeCheckpoint
|
|
9374
9622
|
});
|
|
9375
9623
|
import path20 from "path";
|
|
9376
|
-
import { writeFileSync as writeFileSync8, mkdirSync as
|
|
9624
|
+
import { writeFileSync as writeFileSync8, mkdirSync as mkdirSync9, unlinkSync as unlinkSync7 } from "fs";
|
|
9377
9625
|
async function createTask(input) {
|
|
9378
9626
|
const result = await createTaskCore(input);
|
|
9379
9627
|
if (!input.skipDispatch && result.status !== "blocked" && !process.env.VITEST) {
|
|
@@ -9395,11 +9643,11 @@ async function updateTask(input) {
|
|
|
9395
9643
|
const cacheDir = path20.join(EXE_AI_DIR, "session-cache");
|
|
9396
9644
|
const cachePath = path20.join(cacheDir, `current-task-${agent}.json`);
|
|
9397
9645
|
if (input.status === "in_progress") {
|
|
9398
|
-
|
|
9646
|
+
mkdirSync9(cacheDir, { recursive: true });
|
|
9399
9647
|
writeFileSync8(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
|
|
9400
9648
|
} else if (input.status === "done" || input.status === "blocked" || input.status === "cancelled" || input.status === "closed") {
|
|
9401
9649
|
try {
|
|
9402
|
-
|
|
9650
|
+
unlinkSync7(cachePath);
|
|
9403
9651
|
} catch {
|
|
9404
9652
|
}
|
|
9405
9653
|
}
|