@askexenow/exe-os 0.8.83 → 0.8.86

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.
Files changed (103) hide show
  1. package/dist/bin/backfill-conversations.js +746 -595
  2. package/dist/bin/backfill-responses.js +745 -594
  3. package/dist/bin/backfill-vectors.js +312 -226
  4. package/dist/bin/cleanup-stale-review-tasks.js +154 -21
  5. package/dist/bin/cli.js +14678 -12676
  6. package/dist/bin/exe-agent-config.js +242 -0
  7. package/dist/bin/exe-agent.js +100 -91
  8. package/dist/bin/exe-assign.js +1003 -854
  9. package/dist/bin/exe-boot.js +1420 -485
  10. package/dist/bin/exe-call.js +10 -0
  11. package/dist/bin/exe-cloud.js +29 -6
  12. package/dist/bin/exe-dispatch.js +572 -271
  13. package/dist/bin/exe-doctor.js +403 -6
  14. package/dist/bin/exe-export-behaviors.js +175 -72
  15. package/dist/bin/exe-forget.js +102 -3
  16. package/dist/bin/exe-gateway.js +796 -292
  17. package/dist/bin/exe-healthcheck.js +134 -1
  18. package/dist/bin/exe-heartbeat.js +172 -36
  19. package/dist/bin/exe-kill.js +175 -72
  20. package/dist/bin/exe-launch-agent.js +189 -76
  21. package/dist/bin/exe-link.js +927 -82
  22. package/dist/bin/exe-new-employee.js +60 -8
  23. package/dist/bin/exe-pending-messages.js +151 -19
  24. package/dist/bin/exe-pending-notifications.js +97 -2
  25. package/dist/bin/exe-pending-reviews.js +155 -22
  26. package/dist/bin/exe-rename.js +564 -23
  27. package/dist/bin/exe-review.js +231 -73
  28. package/dist/bin/exe-search.js +995 -228
  29. package/dist/bin/exe-session-cleanup.js +4930 -1664
  30. package/dist/bin/exe-settings.js +20 -5
  31. package/dist/bin/exe-start-codex.js +2598 -0
  32. package/dist/bin/exe-start.sh +15 -3
  33. package/dist/bin/exe-status.js +154 -21
  34. package/dist/bin/exe-team.js +97 -2
  35. package/dist/bin/git-sweep.js +1180 -363
  36. package/dist/bin/graph-backfill.js +175 -72
  37. package/dist/bin/graph-export.js +175 -72
  38. package/dist/bin/install.js +60 -7
  39. package/dist/bin/list-providers.js +1 -0
  40. package/dist/bin/scan-tasks.js +1185 -367
  41. package/dist/bin/setup.js +914 -270
  42. package/dist/bin/shard-migrate.js +175 -72
  43. package/dist/bin/update.js +1 -0
  44. package/dist/bin/wiki-sync.js +175 -72
  45. package/dist/gateway/index.js +792 -285
  46. package/dist/hooks/bug-report-worker.js +445 -135
  47. package/dist/hooks/commit-complete.js +1178 -361
  48. package/dist/hooks/error-recall.js +994 -228
  49. package/dist/hooks/ingest-worker.js +1799 -1234
  50. package/dist/hooks/ingest.js +3 -0
  51. package/dist/hooks/instructions-loaded.js +707 -97
  52. package/dist/hooks/notification.js +699 -89
  53. package/dist/hooks/post-compact.js +757 -109
  54. package/dist/hooks/pre-compact.js +1061 -244
  55. package/dist/hooks/pre-tool-use.js +787 -130
  56. package/dist/hooks/prompt-ingest-worker.js +242 -101
  57. package/dist/hooks/prompt-submit.js +1121 -299
  58. package/dist/hooks/response-ingest-worker.js +242 -101
  59. package/dist/hooks/session-end.js +4063 -397
  60. package/dist/hooks/session-start.js +1071 -254
  61. package/dist/hooks/stop.js +768 -120
  62. package/dist/hooks/subagent-stop.js +757 -109
  63. package/dist/hooks/summary-worker.js +1706 -1011
  64. package/dist/index.js +1821 -1098
  65. package/dist/lib/agent-config.js +167 -0
  66. package/dist/lib/cloud-sync.js +932 -88
  67. package/dist/lib/consolidation.js +2 -1
  68. package/dist/lib/database.js +642 -87
  69. package/dist/lib/db-daemon-client.js +503 -0
  70. package/dist/lib/device-registry.js +547 -7
  71. package/dist/lib/embedder.js +14 -28
  72. package/dist/lib/employee-templates.js +84 -74
  73. package/dist/lib/employees.js +9 -0
  74. package/dist/lib/exe-daemon-client.js +16 -29
  75. package/dist/lib/exe-daemon.js +2733 -1575
  76. package/dist/lib/hybrid-search.js +995 -228
  77. package/dist/lib/identity.js +87 -67
  78. package/dist/lib/keychain.js +9 -1
  79. package/dist/lib/messaging.js +103 -40
  80. package/dist/lib/reminders.js +91 -74
  81. package/dist/lib/runtime-table.js +16 -0
  82. package/dist/lib/schedules.js +96 -2
  83. package/dist/lib/session-wrappers.js +22 -0
  84. package/dist/lib/skill-learning.js +103 -85
  85. package/dist/lib/store.js +234 -73
  86. package/dist/lib/tasks.js +348 -134
  87. package/dist/lib/tmux-routing.js +422 -208
  88. package/dist/lib/token-spend.js +273 -0
  89. package/dist/lib/ws-client.js +11 -0
  90. package/dist/mcp/server.js +5742 -696
  91. package/dist/mcp/tools/complete-reminder.js +94 -77
  92. package/dist/mcp/tools/create-reminder.js +94 -77
  93. package/dist/mcp/tools/create-task.js +375 -152
  94. package/dist/mcp/tools/deactivate-behavior.js +95 -77
  95. package/dist/mcp/tools/list-reminders.js +94 -77
  96. package/dist/mcp/tools/list-tasks.js +99 -31
  97. package/dist/mcp/tools/send-message.js +108 -45
  98. package/dist/mcp/tools/update-task.js +162 -77
  99. package/dist/runtime/index.js +1075 -258
  100. package/dist/tui/App.js +1333 -506
  101. package/package.json +6 -1
  102. package/src/commands/exe/agent-config.md +27 -0
  103. package/src/commands/exe/cc-doctor.md +10 -0
@@ -295,6 +295,443 @@ var init_db_retry = __esm({
295
295
  }
296
296
  });
297
297
 
298
+ // src/lib/exe-daemon-client.ts
299
+ import net from "net";
300
+ import { spawn } from "child_process";
301
+ import { randomUUID } from "crypto";
302
+ import { existsSync as existsSync3, unlinkSync as unlinkSync3, readFileSync as readFileSync4, openSync, closeSync, statSync } from "fs";
303
+ import path4 from "path";
304
+ import { fileURLToPath } from "url";
305
+ function handleData(chunk) {
306
+ _buffer += chunk.toString();
307
+ if (_buffer.length > MAX_BUFFER) {
308
+ _buffer = "";
309
+ return;
310
+ }
311
+ let newlineIdx;
312
+ while ((newlineIdx = _buffer.indexOf("\n")) !== -1) {
313
+ const line = _buffer.slice(0, newlineIdx).trim();
314
+ _buffer = _buffer.slice(newlineIdx + 1);
315
+ if (!line) continue;
316
+ try {
317
+ const response = JSON.parse(line);
318
+ const id = response.id;
319
+ if (!id) continue;
320
+ const entry = _pending.get(id);
321
+ if (entry) {
322
+ clearTimeout(entry.timer);
323
+ _pending.delete(id);
324
+ entry.resolve(response);
325
+ }
326
+ } catch {
327
+ }
328
+ }
329
+ }
330
+ function cleanupStaleFiles() {
331
+ if (existsSync3(PID_PATH)) {
332
+ try {
333
+ const pid = parseInt(readFileSync4(PID_PATH, "utf8").trim(), 10);
334
+ if (pid > 0) {
335
+ try {
336
+ process.kill(pid, 0);
337
+ return;
338
+ } catch {
339
+ }
340
+ }
341
+ } catch {
342
+ }
343
+ try {
344
+ unlinkSync3(PID_PATH);
345
+ } catch {
346
+ }
347
+ try {
348
+ unlinkSync3(SOCKET_PATH);
349
+ } catch {
350
+ }
351
+ }
352
+ }
353
+ function findPackageRoot() {
354
+ let dir = path4.dirname(fileURLToPath(import.meta.url));
355
+ const { root } = path4.parse(dir);
356
+ while (dir !== root) {
357
+ if (existsSync3(path4.join(dir, "package.json"))) return dir;
358
+ dir = path4.dirname(dir);
359
+ }
360
+ return null;
361
+ }
362
+ function spawnDaemon() {
363
+ const pkgRoot = findPackageRoot();
364
+ if (!pkgRoot) {
365
+ process.stderr.write("[exed-client] WARN: cannot find package root\n");
366
+ return;
367
+ }
368
+ const daemonPath = path4.join(pkgRoot, "dist", "lib", "exe-daemon.js");
369
+ if (!existsSync3(daemonPath)) {
370
+ process.stderr.write(`[exed-client] WARN: daemon script not found at ${daemonPath}
371
+ `);
372
+ return;
373
+ }
374
+ const resolvedPath = daemonPath;
375
+ process.stderr.write(`[exed-client] Spawning daemon: ${resolvedPath}
376
+ `);
377
+ const logPath = path4.join(path4.dirname(SOCKET_PATH), "exed.log");
378
+ let stderrFd = "ignore";
379
+ try {
380
+ stderrFd = openSync(logPath, "a");
381
+ } catch {
382
+ }
383
+ const child = spawn(process.execPath, [resolvedPath], {
384
+ detached: true,
385
+ stdio: ["ignore", "ignore", stderrFd],
386
+ env: {
387
+ ...process.env,
388
+ TMUX: void 0,
389
+ // Daemon is global — must not inherit session scope
390
+ TMUX_PANE: void 0,
391
+ // Prevents resolveExeSession() from scoping to one session
392
+ EXE_DAEMON_SOCK: SOCKET_PATH,
393
+ EXE_DAEMON_PID: PID_PATH
394
+ }
395
+ });
396
+ child.unref();
397
+ if (typeof stderrFd === "number") {
398
+ try {
399
+ closeSync(stderrFd);
400
+ } catch {
401
+ }
402
+ }
403
+ }
404
+ function acquireSpawnLock() {
405
+ try {
406
+ const fd = openSync(SPAWN_LOCK_PATH, "wx");
407
+ closeSync(fd);
408
+ return true;
409
+ } catch {
410
+ try {
411
+ const stat = statSync(SPAWN_LOCK_PATH);
412
+ if (Date.now() - stat.mtimeMs > SPAWN_LOCK_STALE_MS) {
413
+ try {
414
+ unlinkSync3(SPAWN_LOCK_PATH);
415
+ } catch {
416
+ }
417
+ try {
418
+ const fd = openSync(SPAWN_LOCK_PATH, "wx");
419
+ closeSync(fd);
420
+ return true;
421
+ } catch {
422
+ }
423
+ }
424
+ } catch {
425
+ }
426
+ return false;
427
+ }
428
+ }
429
+ function releaseSpawnLock() {
430
+ try {
431
+ unlinkSync3(SPAWN_LOCK_PATH);
432
+ } catch {
433
+ }
434
+ }
435
+ function connectToSocket() {
436
+ return new Promise((resolve) => {
437
+ if (_socket && _connected) {
438
+ resolve(true);
439
+ return;
440
+ }
441
+ const socket = net.createConnection({ path: SOCKET_PATH });
442
+ const connectTimeout = setTimeout(() => {
443
+ socket.destroy();
444
+ resolve(false);
445
+ }, 2e3);
446
+ socket.on("connect", () => {
447
+ clearTimeout(connectTimeout);
448
+ _socket = socket;
449
+ _connected = true;
450
+ _buffer = "";
451
+ socket.on("data", handleData);
452
+ socket.on("close", () => {
453
+ _connected = false;
454
+ _socket = null;
455
+ for (const [id, entry] of _pending) {
456
+ clearTimeout(entry.timer);
457
+ _pending.delete(id);
458
+ entry.resolve({ error: "Connection closed" });
459
+ }
460
+ });
461
+ socket.on("error", () => {
462
+ _connected = false;
463
+ _socket = null;
464
+ });
465
+ resolve(true);
466
+ });
467
+ socket.on("error", () => {
468
+ clearTimeout(connectTimeout);
469
+ resolve(false);
470
+ });
471
+ });
472
+ }
473
+ async function connectEmbedDaemon() {
474
+ if (_socket && _connected) return true;
475
+ if (await connectToSocket()) return true;
476
+ if (acquireSpawnLock()) {
477
+ try {
478
+ cleanupStaleFiles();
479
+ spawnDaemon();
480
+ } finally {
481
+ releaseSpawnLock();
482
+ }
483
+ }
484
+ const start = Date.now();
485
+ let delay2 = 100;
486
+ while (Date.now() - start < CONNECT_TIMEOUT_MS) {
487
+ await new Promise((r) => setTimeout(r, delay2));
488
+ if (await connectToSocket()) return true;
489
+ delay2 = Math.min(delay2 * 2, 3e3);
490
+ }
491
+ return false;
492
+ }
493
+ function sendDaemonRequest(payload, timeoutMs = REQUEST_TIMEOUT_MS) {
494
+ return new Promise((resolve) => {
495
+ if (!_socket || !_connected) {
496
+ resolve({ error: "Not connected" });
497
+ return;
498
+ }
499
+ const id = randomUUID();
500
+ const timer = setTimeout(() => {
501
+ _pending.delete(id);
502
+ resolve({ error: "Request timeout" });
503
+ }, timeoutMs);
504
+ _pending.set(id, { resolve, timer });
505
+ try {
506
+ _socket.write(JSON.stringify({ id, ...payload }) + "\n");
507
+ } catch {
508
+ clearTimeout(timer);
509
+ _pending.delete(id);
510
+ resolve({ error: "Write failed" });
511
+ }
512
+ });
513
+ }
514
+ function isClientConnected() {
515
+ return _connected;
516
+ }
517
+ var SOCKET_PATH, PID_PATH, SPAWN_LOCK_PATH, SPAWN_LOCK_STALE_MS, CONNECT_TIMEOUT_MS, REQUEST_TIMEOUT_MS, _socket, _connected, _buffer, _pending, MAX_BUFFER;
518
+ var init_exe_daemon_client = __esm({
519
+ "src/lib/exe-daemon-client.ts"() {
520
+ "use strict";
521
+ init_config();
522
+ SOCKET_PATH = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ?? path4.join(EXE_AI_DIR, "exed.sock");
523
+ PID_PATH = process.env.EXE_DAEMON_PID ?? process.env.EXE_EMBED_PID ?? path4.join(EXE_AI_DIR, "exed.pid");
524
+ SPAWN_LOCK_PATH = path4.join(EXE_AI_DIR, "exed-spawn.lock");
525
+ SPAWN_LOCK_STALE_MS = 3e4;
526
+ CONNECT_TIMEOUT_MS = 15e3;
527
+ REQUEST_TIMEOUT_MS = 3e4;
528
+ _socket = null;
529
+ _connected = false;
530
+ _buffer = "";
531
+ _pending = /* @__PURE__ */ new Map();
532
+ MAX_BUFFER = 1e7;
533
+ }
534
+ });
535
+
536
+ // src/lib/daemon-protocol.ts
537
+ function serializeValue(v) {
538
+ if (v === null || v === void 0) return null;
539
+ if (typeof v === "bigint") return Number(v);
540
+ if (typeof v === "boolean") return v ? 1 : 0;
541
+ if (v instanceof Uint8Array) {
542
+ return { __blob: Buffer.from(v).toString("base64") };
543
+ }
544
+ if (ArrayBuffer.isView(v)) {
545
+ return { __blob: Buffer.from(v.buffer, v.byteOffset, v.byteLength).toString("base64") };
546
+ }
547
+ if (v instanceof ArrayBuffer) {
548
+ return { __blob: Buffer.from(v).toString("base64") };
549
+ }
550
+ if (typeof v === "string" || typeof v === "number") return v;
551
+ return String(v);
552
+ }
553
+ function deserializeValue(v) {
554
+ if (v === null) return null;
555
+ if (typeof v === "object" && v !== null && "__blob" in v) {
556
+ const buf = Buffer.from(v.__blob, "base64");
557
+ return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
558
+ }
559
+ return v;
560
+ }
561
+ function deserializeResultSet(srs) {
562
+ const rows = srs.rows.map((obj) => {
563
+ const values = srs.columns.map(
564
+ (col) => deserializeValue(obj[col] ?? null)
565
+ );
566
+ const row = values;
567
+ for (let i = 0; i < srs.columns.length; i++) {
568
+ const col = srs.columns[i];
569
+ if (col !== void 0) {
570
+ row[col] = values[i] ?? null;
571
+ }
572
+ }
573
+ Object.defineProperty(row, "length", {
574
+ value: values.length,
575
+ enumerable: false
576
+ });
577
+ return row;
578
+ });
579
+ return {
580
+ columns: srs.columns,
581
+ columnTypes: srs.columnTypes ?? [],
582
+ rows,
583
+ rowsAffected: srs.rowsAffected,
584
+ lastInsertRowid: srs.lastInsertRowid != null ? BigInt(srs.lastInsertRowid) : void 0,
585
+ toJSON: () => ({
586
+ columns: srs.columns,
587
+ columnTypes: srs.columnTypes ?? [],
588
+ rows: srs.rows,
589
+ rowsAffected: srs.rowsAffected,
590
+ lastInsertRowid: srs.lastInsertRowid
591
+ })
592
+ };
593
+ }
594
+ var init_daemon_protocol = __esm({
595
+ "src/lib/daemon-protocol.ts"() {
596
+ "use strict";
597
+ }
598
+ });
599
+
600
+ // src/lib/db-daemon-client.ts
601
+ var db_daemon_client_exports = {};
602
+ __export(db_daemon_client_exports, {
603
+ createDaemonDbClient: () => createDaemonDbClient,
604
+ initDaemonDbClient: () => initDaemonDbClient
605
+ });
606
+ function normalizeStatement(stmt) {
607
+ if (typeof stmt === "string") {
608
+ return { sql: stmt, args: [] };
609
+ }
610
+ const sql = stmt.sql;
611
+ let args = [];
612
+ if (Array.isArray(stmt.args)) {
613
+ args = stmt.args.map((v) => serializeValue(v));
614
+ } else if (stmt.args && typeof stmt.args === "object") {
615
+ const named = {};
616
+ for (const [key, val] of Object.entries(stmt.args)) {
617
+ named[key] = serializeValue(val);
618
+ }
619
+ return { sql, args: named };
620
+ }
621
+ return { sql, args };
622
+ }
623
+ function createDaemonDbClient(fallbackClient) {
624
+ let _useDaemon = false;
625
+ const client = {
626
+ async execute(stmt) {
627
+ if (!_useDaemon || !isClientConnected()) {
628
+ return fallbackClient.execute(stmt);
629
+ }
630
+ const { sql, args } = normalizeStatement(stmt);
631
+ const response = await sendDaemonRequest({
632
+ type: "db-execute",
633
+ sql,
634
+ args
635
+ });
636
+ if (response.error) {
637
+ const errMsg = String(response.error);
638
+ if (errMsg === "Not connected" || errMsg === "Request timeout" || errMsg === "Write failed") {
639
+ process.stderr.write(`[db-daemon] Transport error (${errMsg}), falling back to direct
640
+ `);
641
+ return fallbackClient.execute(stmt);
642
+ }
643
+ throw new Error(errMsg);
644
+ }
645
+ if (response.db) {
646
+ return deserializeResultSet(response.db);
647
+ }
648
+ process.stderr.write("[db-daemon] Unexpected response shape, falling back to direct\n");
649
+ return fallbackClient.execute(stmt);
650
+ },
651
+ async batch(stmts, mode) {
652
+ if (!_useDaemon || !isClientConnected()) {
653
+ return fallbackClient.batch(stmts, mode);
654
+ }
655
+ const statements = stmts.map(normalizeStatement);
656
+ const response = await sendDaemonRequest({
657
+ type: "db-batch",
658
+ statements,
659
+ mode: mode ?? "deferred"
660
+ });
661
+ if (response.error) {
662
+ const errMsg = String(response.error);
663
+ if (errMsg === "Not connected" || errMsg === "Request timeout" || errMsg === "Write failed") {
664
+ process.stderr.write(`[db-daemon] Batch transport error (${errMsg}), falling back to direct
665
+ `);
666
+ return fallbackClient.batch(stmts, mode);
667
+ }
668
+ throw new Error(errMsg);
669
+ }
670
+ const batchResults = response["db-batch"];
671
+ if (batchResults) {
672
+ return batchResults.map(deserializeResultSet);
673
+ }
674
+ process.stderr.write("[db-daemon] Unexpected batch response shape, falling back to direct\n");
675
+ return fallbackClient.batch(stmts, mode);
676
+ },
677
+ // Transaction support — delegate to fallback (transactions need direct connection)
678
+ async transaction(mode) {
679
+ return fallbackClient.transaction(mode);
680
+ },
681
+ // executeMultiple — delegate to fallback (used only for schema migrations)
682
+ async executeMultiple(sql) {
683
+ return fallbackClient.executeMultiple(sql);
684
+ },
685
+ // migrate — delegate to fallback
686
+ async migrate(stmts) {
687
+ return fallbackClient.migrate(stmts);
688
+ },
689
+ // Sync mode — delegate to fallback
690
+ sync() {
691
+ return fallbackClient.sync();
692
+ },
693
+ close() {
694
+ _useDaemon = false;
695
+ },
696
+ get closed() {
697
+ return fallbackClient.closed;
698
+ },
699
+ get protocol() {
700
+ return fallbackClient.protocol;
701
+ }
702
+ };
703
+ return {
704
+ ...client,
705
+ /** Enable daemon routing (call after confirming daemon is connected) */
706
+ _enableDaemon() {
707
+ _useDaemon = true;
708
+ },
709
+ /** Check if daemon routing is active */
710
+ _isDaemonActive() {
711
+ return _useDaemon && isClientConnected();
712
+ }
713
+ };
714
+ }
715
+ async function initDaemonDbClient(fallbackClient) {
716
+ if (process.env.EXE_IS_DAEMON === "1") return null;
717
+ const connected = await connectEmbedDaemon();
718
+ if (!connected) {
719
+ process.stderr.write("[db-daemon] Daemon unavailable \u2014 using direct SQLite\n");
720
+ return null;
721
+ }
722
+ const client = createDaemonDbClient(fallbackClient);
723
+ client._enableDaemon();
724
+ process.stderr.write("[db-daemon] DB routing through daemon (single-writer)\n");
725
+ return client;
726
+ }
727
+ var init_db_daemon_client = __esm({
728
+ "src/lib/db-daemon-client.ts"() {
729
+ "use strict";
730
+ init_exe_daemon_client();
731
+ init_daemon_protocol();
732
+ }
733
+ });
734
+
298
735
  // src/lib/database.ts
299
736
  var database_exports = {};
300
737
  __export(database_exports, {
@@ -303,6 +740,7 @@ __export(database_exports, {
303
740
  ensureSchema: () => ensureSchema,
304
741
  getClient: () => getClient,
305
742
  getRawClient: () => getRawClient,
743
+ initDaemonClient: () => initDaemonClient,
306
744
  initDatabase: () => initDatabase,
307
745
  initTurso: () => initTurso,
308
746
  isInitialized: () => isInitialized
@@ -330,8 +768,27 @@ function getClient() {
330
768
  if (!_resilientClient) {
331
769
  throw new Error("Database client not initialized. Call initDatabase() first.");
332
770
  }
771
+ if (process.env.EXE_IS_DAEMON === "1") {
772
+ return _resilientClient;
773
+ }
774
+ if (_daemonClient && _daemonClient._isDaemonActive()) {
775
+ return _daemonClient;
776
+ }
333
777
  return _resilientClient;
334
778
  }
779
+ async function initDaemonClient() {
780
+ if (process.env.EXE_IS_DAEMON === "1") return;
781
+ if (!_resilientClient) return;
782
+ try {
783
+ const { initDaemonDbClient: initDaemonDbClient2 } = await Promise.resolve().then(() => (init_db_daemon_client(), db_daemon_client_exports));
784
+ _daemonClient = await initDaemonDbClient2(_resilientClient);
785
+ } catch (err) {
786
+ process.stderr.write(
787
+ `[database] Daemon client init failed (non-fatal): ${err instanceof Error ? err.message : String(err)}
788
+ `
789
+ );
790
+ }
791
+ }
335
792
  function getRawClient() {
336
793
  if (!_client) {
337
794
  throw new Error("Database client not initialized. Call initDatabase() first.");
@@ -818,6 +1275,12 @@ async function ensureSchema() {
818
1275
  } catch {
819
1276
  }
820
1277
  }
1278
+ try {
1279
+ await client.execute(
1280
+ `CREATE INDEX IF NOT EXISTS idx_memories_content_hash ON memories(content_hash, agent_id)`
1281
+ );
1282
+ } catch {
1283
+ }
821
1284
  await client.executeMultiple(`
822
1285
  CREATE TABLE IF NOT EXISTS entities (
823
1286
  id TEXT PRIMARY KEY,
@@ -870,7 +1333,30 @@ async function ensureSchema() {
870
1333
  entity_id TEXT NOT NULL,
871
1334
  PRIMARY KEY (hyperedge_id, entity_id)
872
1335
  );
1336
+
1337
+ CREATE VIRTUAL TABLE IF NOT EXISTS entities_fts USING fts5(
1338
+ name,
1339
+ content=entities,
1340
+ content_rowid=rowid
1341
+ );
1342
+
1343
+ CREATE TRIGGER IF NOT EXISTS entities_fts_ai AFTER INSERT ON entities BEGIN
1344
+ INSERT INTO entities_fts(rowid, name) VALUES (new.rowid, new.name);
1345
+ END;
1346
+
1347
+ CREATE TRIGGER IF NOT EXISTS entities_fts_ad AFTER DELETE ON entities BEGIN
1348
+ INSERT INTO entities_fts(entities_fts, rowid, name) VALUES('delete', old.rowid, old.name);
1349
+ END;
1350
+
1351
+ CREATE TRIGGER IF NOT EXISTS entities_fts_au AFTER UPDATE ON entities BEGIN
1352
+ INSERT INTO entities_fts(entities_fts, rowid, name) VALUES('delete', old.rowid, old.name);
1353
+ INSERT INTO entities_fts(rowid, name) VALUES (new.rowid, new.name);
1354
+ END;
873
1355
  `);
1356
+ try {
1357
+ await client.execute("INSERT INTO entities_fts(entities_fts) VALUES('rebuild')");
1358
+ } catch {
1359
+ }
874
1360
  await client.executeMultiple(`
875
1361
  CREATE TABLE IF NOT EXISTS entity_aliases (
876
1362
  alias TEXT NOT NULL PRIMARY KEY,
@@ -1051,6 +1537,33 @@ async function ensureSchema() {
1051
1537
  CREATE INDEX IF NOT EXISTS idx_conversations_channel
1052
1538
  ON conversations(channel_id);
1053
1539
  `);
1540
+ await client.executeMultiple(`
1541
+ CREATE TABLE IF NOT EXISTS session_agent_map (
1542
+ session_uuid TEXT PRIMARY KEY,
1543
+ agent_id TEXT NOT NULL,
1544
+ session_name TEXT,
1545
+ task_id TEXT,
1546
+ project_name TEXT,
1547
+ started_at TEXT NOT NULL
1548
+ );
1549
+
1550
+ CREATE INDEX IF NOT EXISTS idx_session_agent_map_agent
1551
+ ON session_agent_map(agent_id);
1552
+ `);
1553
+ try {
1554
+ const mapCount = await client.execute({ sql: `SELECT COUNT(*) as cnt FROM session_agent_map`, args: [] });
1555
+ if (Number(mapCount.rows[0]?.cnt ?? 0) === 0) {
1556
+ await client.execute({
1557
+ sql: `INSERT OR IGNORE INTO session_agent_map (session_uuid, agent_id, session_name, started_at)
1558
+ SELECT session_id, agent_id, '', MIN(timestamp)
1559
+ FROM memories
1560
+ WHERE session_id IS NOT NULL AND session_id != '' AND agent_id IS NOT NULL AND agent_id != ''
1561
+ GROUP BY session_id, agent_id`,
1562
+ args: []
1563
+ });
1564
+ }
1565
+ } catch {
1566
+ }
1054
1567
  try {
1055
1568
  await client.execute({
1056
1569
  sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
@@ -1184,15 +1697,41 @@ async function ensureSchema() {
1184
1697
  });
1185
1698
  } catch {
1186
1699
  }
1700
+ for (const col of [
1701
+ "ALTER TABLE memories ADD COLUMN intent TEXT",
1702
+ "ALTER TABLE memories ADD COLUMN outcome TEXT",
1703
+ "ALTER TABLE memories ADD COLUMN domain TEXT",
1704
+ "ALTER TABLE memories ADD COLUMN referenced_entities TEXT",
1705
+ "ALTER TABLE memories ADD COLUMN retrieval_count INTEGER DEFAULT 0",
1706
+ "ALTER TABLE memories ADD COLUMN chain_position TEXT",
1707
+ "ALTER TABLE memories ADD COLUMN review_status TEXT",
1708
+ "ALTER TABLE memories ADD COLUMN context_window_pct INTEGER",
1709
+ "ALTER TABLE memories ADD COLUMN file_paths TEXT",
1710
+ "ALTER TABLE memories ADD COLUMN commit_hash TEXT",
1711
+ "ALTER TABLE memories ADD COLUMN duration_ms INTEGER",
1712
+ "ALTER TABLE memories ADD COLUMN token_cost REAL",
1713
+ "ALTER TABLE memories ADD COLUMN audience TEXT",
1714
+ "ALTER TABLE memories ADD COLUMN language_type TEXT",
1715
+ "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
1716
+ ]) {
1717
+ try {
1718
+ await client.execute(col);
1719
+ } catch {
1720
+ }
1721
+ }
1187
1722
  }
1188
1723
  async function disposeDatabase() {
1724
+ if (_daemonClient) {
1725
+ _daemonClient.close();
1726
+ _daemonClient = null;
1727
+ }
1189
1728
  if (_client) {
1190
1729
  _client.close();
1191
1730
  _client = null;
1192
1731
  _resilientClient = null;
1193
1732
  }
1194
1733
  }
1195
- var _client, _resilientClient, initTurso, disposeTurso;
1734
+ var _client, _resilientClient, _daemonClient, initTurso, disposeTurso;
1196
1735
  var init_database = __esm({
1197
1736
  "src/lib/database.ts"() {
1198
1737
  "use strict";
@@ -1200,6 +1739,7 @@ var init_database = __esm({
1200
1739
  init_employees();
1201
1740
  _client = null;
1202
1741
  _resilientClient = null;
1742
+ _daemonClient = null;
1203
1743
  initTurso = initDatabase;
1204
1744
  disposeTurso = disposeDatabase;
1205
1745
  }
@@ -1207,14 +1747,14 @@ var init_database = __esm({
1207
1747
 
1208
1748
  // src/lib/keychain.ts
1209
1749
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
1210
- import { existsSync as existsSync3 } from "fs";
1211
- import path4 from "path";
1750
+ import { existsSync as existsSync4 } from "fs";
1751
+ import path5 from "path";
1212
1752
  import os3 from "os";
1213
1753
  function getKeyDir() {
1214
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path4.join(os3.homedir(), ".exe-os");
1754
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path5.join(os3.homedir(), ".exe-os");
1215
1755
  }
1216
1756
  function getKeyPath() {
1217
- return path4.join(getKeyDir(), "master.key");
1757
+ return path5.join(getKeyDir(), "master.key");
1218
1758
  }
1219
1759
  async function tryKeytar() {
1220
1760
  try {
@@ -1235,13 +1775,21 @@ async function getMasterKey() {
1235
1775
  }
1236
1776
  }
1237
1777
  const keyPath = getKeyPath();
1238
- if (!existsSync3(keyPath)) {
1778
+ if (!existsSync4(keyPath)) {
1779
+ process.stderr.write(
1780
+ `[keychain] Key not found at ${keyPath} (HOME=${os3.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
1781
+ `
1782
+ );
1239
1783
  return null;
1240
1784
  }
1241
1785
  try {
1242
1786
  const content = await readFile3(keyPath, "utf-8");
1243
1787
  return Buffer.from(content.trim(), "base64");
1244
- } catch {
1788
+ } catch (err) {
1789
+ process.stderr.write(
1790
+ `[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}
1791
+ `
1792
+ );
1245
1793
  return null;
1246
1794
  }
1247
1795
  }
@@ -1322,12 +1870,12 @@ __export(shard_manager_exports, {
1322
1870
  listShards: () => listShards,
1323
1871
  shardExists: () => shardExists
1324
1872
  });
1325
- import path5 from "path";
1326
- import { existsSync as existsSync4, mkdirSync as mkdirSync2, readdirSync as readdirSync2 } from "fs";
1873
+ import path6 from "path";
1874
+ import { existsSync as existsSync5, mkdirSync as mkdirSync2, readdirSync as readdirSync2 } from "fs";
1327
1875
  import { createClient as createClient2 } from "@libsql/client";
1328
1876
  function initShardManager(encryptionKey) {
1329
1877
  _encryptionKey = encryptionKey;
1330
- if (!existsSync4(SHARDS_DIR)) {
1878
+ if (!existsSync5(SHARDS_DIR)) {
1331
1879
  mkdirSync2(SHARDS_DIR, { recursive: true });
1332
1880
  }
1333
1881
  _shardingEnabled = true;
@@ -1348,7 +1896,7 @@ function getShardClient(projectName) {
1348
1896
  }
1349
1897
  const cached = _shards.get(safeName);
1350
1898
  if (cached) return cached;
1351
- const dbPath = path5.join(SHARDS_DIR, `${safeName}.db`);
1899
+ const dbPath = path6.join(SHARDS_DIR, `${safeName}.db`);
1352
1900
  const client = createClient2({
1353
1901
  url: `file:${dbPath}`,
1354
1902
  encryptionKey: _encryptionKey
@@ -1358,10 +1906,10 @@ function getShardClient(projectName) {
1358
1906
  }
1359
1907
  function shardExists(projectName) {
1360
1908
  const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
1361
- return existsSync4(path5.join(SHARDS_DIR, `${safeName}.db`));
1909
+ return existsSync5(path6.join(SHARDS_DIR, `${safeName}.db`));
1362
1910
  }
1363
1911
  function listShards() {
1364
- if (!existsSync4(SHARDS_DIR)) return [];
1912
+ if (!existsSync5(SHARDS_DIR)) return [];
1365
1913
  return readdirSync2(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
1366
1914
  }
1367
1915
  async function ensureShardSchema(client) {
@@ -1547,7 +2095,7 @@ var init_shard_manager = __esm({
1547
2095
  "src/lib/shard-manager.ts"() {
1548
2096
  "use strict";
1549
2097
  init_config();
1550
- SHARDS_DIR = path5.join(EXE_AI_DIR, "shards");
2098
+ SHARDS_DIR = path6.join(EXE_AI_DIR, "shards");
1551
2099
  _shards = /* @__PURE__ */ new Map();
1552
2100
  _encryptionKey = null;
1553
2101
  _shardingEnabled = false;
@@ -1672,7 +2220,7 @@ __export(global_procedures_exports, {
1672
2220
  loadGlobalProcedures: () => loadGlobalProcedures,
1673
2221
  storeGlobalProcedure: () => storeGlobalProcedure
1674
2222
  });
1675
- import { randomUUID } from "crypto";
2223
+ import { randomUUID as randomUUID2 } from "crypto";
1676
2224
  async function loadGlobalProcedures() {
1677
2225
  const client = getClient();
1678
2226
  const result = await client.execute({
@@ -1701,7 +2249,7 @@ ${sections.join("\n\n")}
1701
2249
  `;
1702
2250
  }
1703
2251
  async function storeGlobalProcedure(input2) {
1704
- const id = randomUUID();
2252
+ const id = randomUUID2();
1705
2253
  const now = (/* @__PURE__ */ new Date()).toISOString();
1706
2254
  const client = getClient();
1707
2255
  await client.execute({
@@ -1752,6 +2300,7 @@ __export(store_exports, {
1752
2300
  vectorToBlob: () => vectorToBlob,
1753
2301
  writeMemory: () => writeMemory
1754
2302
  });
2303
+ import { createHash } from "crypto";
1755
2304
  function isBusyError2(err) {
1756
2305
  if (err instanceof Error) {
1757
2306
  const msg = err.message.toLowerCase();
@@ -1825,12 +2374,52 @@ function classifyTier(record) {
1825
2374
  if (["store_memory", "manual"].includes(record.tool_name ?? "") && (record.importance ?? 0) >= 5) return 2;
1826
2375
  return 3;
1827
2376
  }
2377
+ function inferFilePaths(record) {
2378
+ if (!["Read", "Write", "Edit"].includes(record.tool_name)) return null;
2379
+ const firstLine = record.raw_text.split("\n")[0] ?? "";
2380
+ const match = firstLine.match(/(\/[\w./-]+\.\w+)/);
2381
+ return match ? JSON.stringify([match[1]]) : null;
2382
+ }
2383
+ function inferCommitHash(record) {
2384
+ if (record.tool_name !== "Bash") return null;
2385
+ const match = record.raw_text.match(/\b([a-f0-9]{7,40})\b/);
2386
+ return match ? match[1] : null;
2387
+ }
2388
+ function inferLanguageType(record) {
2389
+ const text = record.raw_text;
2390
+ if (!text || text.length < 10) return null;
2391
+ const trimmed = text.trimStart();
2392
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) return "json";
2393
+ if (/\b(SELECT|INSERT|UPDATE|DELETE|CREATE TABLE|ALTER TABLE)\b/i.test(text)) return "sql";
2394
+ if (/\b(function |const |import |export |class |def |async |=>)\b/.test(text)) return "code";
2395
+ if (trimmed.startsWith("#") || trimmed.startsWith("*")) return "prose";
2396
+ return "mixed";
2397
+ }
2398
+ function inferDomain(record) {
2399
+ const proj = (record.project_name ?? "").toLowerCase();
2400
+ if (proj.includes("marketing") || proj.includes("content")) return "marketing";
2401
+ if (proj.includes("crm") || proj.includes("customer")) return "customer";
2402
+ return null;
2403
+ }
1828
2404
  async function writeMemory(record) {
1829
2405
  if (record.vector !== null && record.vector.length !== EMBEDDING_DIM) {
1830
2406
  throw new Error(
1831
2407
  `Expected ${EMBEDDING_DIM}-dim vector, got ${record.vector.length}`
1832
2408
  );
1833
2409
  }
2410
+ const contentHash = createHash("md5").update(record.raw_text).digest("hex");
2411
+ if (_pendingRecords.some((r) => r.content_hash === contentHash && r.agent_id === record.agent_id)) {
2412
+ return;
2413
+ }
2414
+ try {
2415
+ const client = getClient();
2416
+ const existing = await client.execute({
2417
+ sql: "SELECT id FROM memories WHERE content_hash = ? AND agent_id = ? LIMIT 1",
2418
+ args: [contentHash, record.agent_id]
2419
+ });
2420
+ if (existing.rows.length > 0) return;
2421
+ } catch {
2422
+ }
1834
2423
  const dbRow = {
1835
2424
  id: record.id,
1836
2425
  agent_id: record.agent_id,
@@ -1860,7 +2449,23 @@ async function writeMemory(record) {
1860
2449
  supersedes_id: record.supersedes_id ?? null,
1861
2450
  draft: record.draft ? 1 : 0,
1862
2451
  memory_type: record.memory_type ?? "raw",
1863
- trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null
2452
+ trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null,
2453
+ content_hash: contentHash,
2454
+ intent: record.intent ?? null,
2455
+ outcome: record.outcome ?? null,
2456
+ domain: record.domain ?? inferDomain(record),
2457
+ referenced_entities: record.referenced_entities ?? null,
2458
+ retrieval_count: record.retrieval_count ?? 0,
2459
+ chain_position: record.chain_position ?? null,
2460
+ review_status: record.review_status ?? null,
2461
+ context_window_pct: record.context_window_pct ?? null,
2462
+ file_paths: record.file_paths ?? inferFilePaths(record),
2463
+ commit_hash: record.commit_hash ?? inferCommitHash(record),
2464
+ duration_ms: record.duration_ms ?? null,
2465
+ token_cost: record.token_cost ?? null,
2466
+ audience: record.audience ?? null,
2467
+ language_type: record.language_type ?? inferLanguageType(record),
2468
+ parent_memory_id: record.parent_memory_id ?? null
1864
2469
  };
1865
2470
  _pendingRecords.push(dbRow);
1866
2471
  orgBus.emit({
@@ -1918,80 +2523,85 @@ async function flushBatch() {
1918
2523
  const draft = row.draft ? 1 : 0;
1919
2524
  const memoryType = row.memory_type ?? "raw";
1920
2525
  const trajectory = row.trajectory ?? null;
1921
- return {
1922
- sql: hasVector ? `INSERT OR IGNORE INTO memories
1923
- (id, agent_id, agent_role, session_id, timestamp,
2526
+ const contentHash = row.content_hash ?? null;
2527
+ const intent = row.intent ?? null;
2528
+ const outcome = row.outcome ?? null;
2529
+ const domain = row.domain ?? null;
2530
+ const referencedEntities = row.referenced_entities ?? null;
2531
+ const retrievalCount = row.retrieval_count ?? 0;
2532
+ const chainPosition = row.chain_position ?? null;
2533
+ const reviewStatus = row.review_status ?? null;
2534
+ const contextWindowPct = row.context_window_pct ?? null;
2535
+ const filePaths = row.file_paths ?? null;
2536
+ const commitHash = row.commit_hash ?? null;
2537
+ const durationMs = row.duration_ms ?? null;
2538
+ const tokenCost = row.token_cost ?? null;
2539
+ const audience = row.audience ?? null;
2540
+ const languageType = row.language_type ?? null;
2541
+ const parentMemoryId = row.parent_memory_id ?? null;
2542
+ const cols = `id, agent_id, agent_role, session_id, timestamp,
1924
2543
  tool_name, project_name,
1925
2544
  has_error, raw_text, vector, version, task_id, importance, status,
1926
2545
  confidence, last_accessed,
1927
2546
  workspace_id, document_id, user_id, char_offset, page_number,
1928
- source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory)
1929
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories
1930
- (id, agent_id, agent_role, session_id, timestamp,
1931
- tool_name, project_name,
1932
- has_error, raw_text, vector, version, task_id, importance, status,
1933
- confidence, last_accessed,
1934
- workspace_id, document_id, user_id, char_offset, page_number,
1935
- source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory)
1936
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
1937
- args: hasVector ? [
1938
- row.id,
1939
- row.agent_id,
1940
- row.agent_role,
1941
- row.session_id,
1942
- row.timestamp,
1943
- row.tool_name,
1944
- row.project_name,
1945
- row.has_error,
1946
- row.raw_text,
1947
- vectorToBlob(row.vector),
1948
- row.version,
1949
- taskId,
1950
- importance,
1951
- status,
1952
- confidence,
1953
- lastAccessed,
1954
- workspaceId,
1955
- documentId,
1956
- userId,
1957
- charOffset,
1958
- pageNumber,
1959
- sourcePath,
1960
- sourceType,
1961
- tier,
1962
- supersedesId,
1963
- draft,
1964
- memoryType,
1965
- trajectory
1966
- ] : [
1967
- row.id,
1968
- row.agent_id,
1969
- row.agent_role,
1970
- row.session_id,
1971
- row.timestamp,
1972
- row.tool_name,
1973
- row.project_name,
1974
- row.has_error,
1975
- row.raw_text,
1976
- row.version,
1977
- taskId,
1978
- importance,
1979
- status,
1980
- confidence,
1981
- lastAccessed,
1982
- workspaceId,
1983
- documentId,
1984
- userId,
1985
- charOffset,
1986
- pageNumber,
1987
- sourcePath,
1988
- sourceType,
1989
- tier,
1990
- supersedesId,
1991
- draft,
1992
- memoryType,
1993
- trajectory
1994
- ]
2547
+ source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory, content_hash,
2548
+ intent, outcome, domain, referenced_entities, retrieval_count,
2549
+ chain_position, review_status, context_window_pct, file_paths, commit_hash,
2550
+ duration_ms, token_cost, audience, language_type, parent_memory_id`;
2551
+ const metaArgs = [
2552
+ intent,
2553
+ outcome,
2554
+ domain,
2555
+ referencedEntities,
2556
+ retrievalCount,
2557
+ chainPosition,
2558
+ reviewStatus,
2559
+ contextWindowPct,
2560
+ filePaths,
2561
+ commitHash,
2562
+ durationMs,
2563
+ tokenCost,
2564
+ audience,
2565
+ languageType,
2566
+ parentMemoryId
2567
+ ];
2568
+ const baseArgs = [
2569
+ row.id,
2570
+ row.agent_id,
2571
+ row.agent_role,
2572
+ row.session_id,
2573
+ row.timestamp,
2574
+ row.tool_name,
2575
+ row.project_name,
2576
+ row.has_error,
2577
+ row.raw_text
2578
+ ];
2579
+ const sharedArgs = [
2580
+ row.version,
2581
+ taskId,
2582
+ importance,
2583
+ status,
2584
+ confidence,
2585
+ lastAccessed,
2586
+ workspaceId,
2587
+ documentId,
2588
+ userId,
2589
+ charOffset,
2590
+ pageNumber,
2591
+ sourcePath,
2592
+ sourceType,
2593
+ tier,
2594
+ supersedesId,
2595
+ draft,
2596
+ memoryType,
2597
+ trajectory,
2598
+ contentHash
2599
+ ];
2600
+ return {
2601
+ sql: hasVector ? `INSERT OR IGNORE INTO memories (${cols})
2602
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
2603
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
2604
+ args: hasVector ? [...baseArgs, vectorToBlob(row.vector), ...sharedArgs, ...metaArgs] : [...baseArgs, ...sharedArgs, ...metaArgs]
1995
2605
  };
1996
2606
  };
1997
2607
  const globalClient = getClient();
@@ -2394,13 +3004,13 @@ process.stdin.on("end", async () => {
2394
3004
  const { initStore: initStore2 } = await Promise.resolve().then(() => (init_store(), store_exports));
2395
3005
  await initStore2();
2396
3006
  const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
2397
- const { randomUUID: randomUUID2 } = await import("crypto");
3007
+ const { randomUUID: randomUUID3 } = await import("crypto");
2398
3008
  const client = getClient2();
2399
3009
  await client.execute({
2400
3010
  sql: `INSERT OR IGNORE INTO notifications (id, type, source_agent, message, task_file, created_at, read)
2401
3011
  VALUES (?, 'system', ?, ?, NULL, ?, 0)`,
2402
3012
  args: [
2403
- randomUUID2(),
3013
+ randomUUID3(),
2404
3014
  agent.agentId,
2405
3015
  data.message.slice(0, 500),
2406
3016
  (/* @__PURE__ */ new Date()).toISOString()