@askexenow/exe-os 0.9.66 → 0.9.67

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 (99) hide show
  1. package/deploy/stack-manifests/v0.9.json +54 -5
  2. package/dist/bin/age-ontology-load.js +61 -0
  3. package/dist/bin/agentic-ontology-backfill.js +4708 -0
  4. package/dist/bin/agentic-reflection-backfill.js +4144 -0
  5. package/dist/bin/{exe-link.js → agentic-semantic-label.js} +1523 -2275
  6. package/dist/bin/backfill-conversations.js +506 -20
  7. package/dist/bin/backfill-responses.js +506 -20
  8. package/dist/bin/backfill-vectors.js +233 -20
  9. package/dist/bin/bulk-sync-postgres.js +4876 -0
  10. package/dist/bin/cleanup-stale-review-tasks.js +507 -21
  11. package/dist/bin/cli.js +2450 -1530
  12. package/dist/bin/exe-assign.js +506 -20
  13. package/dist/bin/exe-boot.js +410 -60
  14. package/dist/bin/exe-cloud.js +795 -105
  15. package/dist/bin/exe-dispatch.js +516 -22
  16. package/dist/bin/exe-doctor.js +587 -30
  17. package/dist/bin/exe-export-behaviors.js +518 -24
  18. package/dist/bin/exe-forget.js +507 -21
  19. package/dist/bin/exe-gateway.js +571 -25
  20. package/dist/bin/exe-heartbeat.js +518 -24
  21. package/dist/bin/exe-kill.js +507 -21
  22. package/dist/bin/exe-launch-agent.js +2312 -1069
  23. package/dist/bin/exe-new-employee.js +197 -165
  24. package/dist/bin/exe-pending-messages.js +507 -21
  25. package/dist/bin/exe-pending-notifications.js +507 -21
  26. package/dist/bin/exe-pending-reviews.js +507 -21
  27. package/dist/bin/exe-rename.js +507 -21
  28. package/dist/bin/exe-review.js +507 -21
  29. package/dist/bin/exe-search.js +518 -24
  30. package/dist/bin/exe-session-cleanup.js +516 -22
  31. package/dist/bin/exe-settings.js +4 -0
  32. package/dist/bin/exe-start-codex.js +682 -143
  33. package/dist/bin/exe-start-opencode.js +627 -79
  34. package/dist/bin/exe-status.js +507 -21
  35. package/dist/bin/exe-team.js +507 -21
  36. package/dist/bin/git-sweep.js +516 -22
  37. package/dist/bin/graph-backfill.js +558 -21
  38. package/dist/bin/graph-export.js +507 -21
  39. package/dist/bin/graph-layer-benchmark.js +109 -0
  40. package/dist/bin/install.js +305 -288
  41. package/dist/bin/intercom-check.js +516 -22
  42. package/dist/bin/postgres-agentic-reflection-backfill.js +187 -0
  43. package/dist/bin/postgres-agentic-semantic-backfill.js +237 -0
  44. package/dist/bin/scan-tasks.js +516 -22
  45. package/dist/bin/setup.js +412 -62
  46. package/dist/bin/shard-migrate.js +506 -20
  47. package/dist/gateway/index.js +569 -23
  48. package/dist/hooks/bug-report-worker.js +519 -25
  49. package/dist/hooks/codex-stop-task-finalizer.js +516 -22
  50. package/dist/hooks/commit-complete.js +516 -22
  51. package/dist/hooks/error-recall.js +518 -24
  52. package/dist/hooks/ingest.js +516 -22
  53. package/dist/hooks/instructions-loaded.js +507 -21
  54. package/dist/hooks/notification.js +507 -21
  55. package/dist/hooks/post-compact.js +507 -21
  56. package/dist/hooks/post-tool-combined.js +519 -25
  57. package/dist/hooks/pre-compact.js +516 -22
  58. package/dist/hooks/pre-tool-use.js +507 -21
  59. package/dist/hooks/prompt-submit.js +519 -25
  60. package/dist/hooks/session-end.js +516 -22
  61. package/dist/hooks/session-start.js +520 -26
  62. package/dist/hooks/stop.js +517 -23
  63. package/dist/hooks/subagent-stop.js +507 -21
  64. package/dist/hooks/summary-worker.js +411 -61
  65. package/dist/index.js +569 -23
  66. package/dist/lib/cloud-sync.js +391 -53
  67. package/dist/lib/config.js +13 -1
  68. package/dist/lib/consolidation.js +1 -1
  69. package/dist/lib/database.js +124 -0
  70. package/dist/lib/db.js +124 -0
  71. package/dist/lib/device-registry.js +124 -0
  72. package/dist/lib/embedder.js +13 -1
  73. package/dist/lib/exe-daemon.js +2184 -561
  74. package/dist/lib/hybrid-search.js +518 -24
  75. package/dist/lib/identity.js +3 -0
  76. package/dist/lib/keychain.js +178 -22
  77. package/dist/lib/messaging.js +3 -0
  78. package/dist/lib/reminders.js +3 -0
  79. package/dist/lib/schedules.js +233 -20
  80. package/dist/lib/skill-learning.js +16 -1
  81. package/dist/lib/store.js +506 -20
  82. package/dist/lib/tasks.js +16 -1
  83. package/dist/lib/tmux-routing.js +16 -1
  84. package/dist/lib/token-spend.js +3 -0
  85. package/dist/mcp/server.js +1757 -428
  86. package/dist/mcp/tools/complete-reminder.js +3 -0
  87. package/dist/mcp/tools/create-reminder.js +3 -0
  88. package/dist/mcp/tools/create-task.js +16 -1
  89. package/dist/mcp/tools/deactivate-behavior.js +3 -0
  90. package/dist/mcp/tools/list-reminders.js +3 -0
  91. package/dist/mcp/tools/list-tasks.js +3 -0
  92. package/dist/mcp/tools/send-message.js +3 -0
  93. package/dist/mcp/tools/update-task.js +16 -1
  94. package/dist/runtime/index.js +516 -22
  95. package/dist/tui/App.js +594 -29
  96. package/package.json +8 -5
  97. package/src/commands/exe/cloud.md +6 -10
  98. package/stack.release.json +3 -3
  99. package/src/commands/exe/link.md +0 -18
@@ -192,6 +192,10 @@ async function loadConfig() {
192
192
  if (config2.dbPath.startsWith("~")) {
193
193
  config2.dbPath = config2.dbPath.replace(/^~/, os.homedir());
194
194
  }
195
+ const envDbPath = path.join(dir, "memories.db");
196
+ if (process.env.EXE_OS_DIR && config2.dbPath !== envDbPath && !existsSync2(config2.dbPath) && existsSync2(envDbPath)) {
197
+ config2.dbPath = envDbPath;
198
+ }
195
199
  return config2;
196
200
  } catch {
197
201
  return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
@@ -212,7 +216,15 @@ function loadConfigSync() {
212
216
  normalizeSessionLifecycle(migratedCfg);
213
217
  normalizeAutoUpdate(migratedCfg);
214
218
  normalizeOrchestration(migratedCfg);
215
- return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
219
+ const config2 = { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
220
+ if (config2.dbPath.startsWith("~")) {
221
+ config2.dbPath = config2.dbPath.replace(/^~/, os.homedir());
222
+ }
223
+ const envDbPath = path.join(dir, "memories.db");
224
+ if (process.env.EXE_OS_DIR && config2.dbPath !== envDbPath && !existsSync2(config2.dbPath) && existsSync2(envDbPath)) {
225
+ config2.dbPath = envDbPath;
226
+ }
227
+ return config2;
216
228
  } catch {
217
229
  return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
218
230
  }
@@ -695,15 +707,15 @@ function isDaemonTooYoung() {
695
707
  }
696
708
  }
697
709
  async function retryThenRestart(doRequest, label) {
698
- const result = await doRequest();
699
- if (!result.error) {
710
+ const result2 = await doRequest();
711
+ if (!result2.error) {
700
712
  _consecutiveFailures = 0;
701
- return result;
713
+ return result2;
702
714
  }
703
715
  _consecutiveFailures++;
704
716
  for (let i = 0; i < MAX_RETRIES_BEFORE_RESTART; i++) {
705
717
  const delayMs = RETRY_DELAYS_MS[i] ?? 5e3;
706
- process.stderr.write(`[exed-client] ${label} failed (${result.error}), retry ${i + 1}/${MAX_RETRIES_BEFORE_RESTART} in ${delayMs}ms
718
+ process.stderr.write(`[exed-client] ${label} failed (${result2.error}), retry ${i + 1}/${MAX_RETRIES_BEFORE_RESTART} in ${delayMs}ms
707
719
  `);
708
720
  await new Promise((r) => setTimeout(r, delayMs));
709
721
  if (!_connected) {
@@ -719,7 +731,7 @@ async function retryThenRestart(doRequest, label) {
719
731
  if (isDaemonTooYoung()) {
720
732
  process.stderr.write(`[exed-client] ${label}: daemon too young (< ${MIN_DAEMON_AGE_MS / 1e3}s) \u2014 skipping restart
721
733
  `);
722
- return { error: result.error };
734
+ return { error: result2.error };
723
735
  }
724
736
  process.stderr.write(`[exed-client] ${label}: ${_consecutiveFailures} consecutive failures \u2014 restarting daemon
725
737
  `);
@@ -755,20 +767,20 @@ async function embedViaClient(text3, priority = "high") {
755
767
  if (!_connected) return null;
756
768
  }
757
769
  }
758
- const result = await retryThenRestart(
770
+ const result2 = await retryThenRestart(
759
771
  () => sendRequest([text3], priority),
760
772
  "Embed"
761
773
  );
762
- return !result.error && result.vectors?.[0] ? result.vectors[0] : null;
774
+ return !result2.error && result2.vectors?.[0] ? result2.vectors[0] : null;
763
775
  }
764
776
  async function embedBatchViaClient(texts, priority = "high") {
765
777
  if (!_connected && !await connectEmbedDaemon()) return null;
766
778
  _requestCount++;
767
- const result = await retryThenRestart(
779
+ const result2 = await retryThenRestart(
768
780
  () => sendRequest(texts, priority),
769
781
  "Batch embed"
770
782
  );
771
- return !result.error && result.vectors ? result.vectors : null;
783
+ return !result2.error && result2.vectors ? result2.vectors : null;
772
784
  }
773
785
  function disconnectClient() {
774
786
  if (_socket) {
@@ -861,10 +873,10 @@ async function disposeEmbedder() {
861
873
  async function embedDirect(text3) {
862
874
  const llamaCpp = await import("node-llama-cpp");
863
875
  const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
864
- const { existsSync: existsSync38 } = await import("fs");
865
- const path49 = await import("path");
866
- const modelPath = path49.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
867
- if (!existsSync38(modelPath)) {
876
+ const { existsSync: existsSync39 } = await import("fs");
877
+ const path50 = await import("path");
878
+ const modelPath = path50.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
879
+ if (!existsSync39(modelPath)) {
868
880
  throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
869
881
  }
870
882
  const llama = await llamaCpp.getLlama();
@@ -2214,6 +2226,9 @@ function getClient() {
2214
2226
  if (_daemonClient && _daemonClient._isDaemonActive()) {
2215
2227
  return _daemonClient;
2216
2228
  }
2229
+ if (!_resilientClient) {
2230
+ return _adapterClient;
2231
+ }
2217
2232
  return _resilientClient;
2218
2233
  }
2219
2234
  async function initDaemonClient() {
@@ -3246,6 +3261,127 @@ async function ensureSchema() {
3246
3261
  VALUES (new.rowid, new.content, new.subject, new.predicate, new.object);
3247
3262
  END;
3248
3263
  `);
3264
+ await client.executeMultiple(`
3265
+ CREATE TABLE IF NOT EXISTS agent_sessions (
3266
+ id TEXT PRIMARY KEY,
3267
+ agent_id TEXT NOT NULL,
3268
+ project_name TEXT,
3269
+ started_at TEXT NOT NULL,
3270
+ last_event_at TEXT NOT NULL,
3271
+ event_count INTEGER NOT NULL DEFAULT 0,
3272
+ properties TEXT DEFAULT '{}'
3273
+ );
3274
+
3275
+ CREATE INDEX IF NOT EXISTS idx_agent_sessions_agent_time
3276
+ ON agent_sessions(agent_id, started_at);
3277
+
3278
+ CREATE TABLE IF NOT EXISTS agent_goals (
3279
+ id TEXT PRIMARY KEY,
3280
+ statement TEXT NOT NULL,
3281
+ owner_agent_id TEXT,
3282
+ project_name TEXT,
3283
+ status TEXT NOT NULL DEFAULT 'open',
3284
+ priority INTEGER NOT NULL DEFAULT 5,
3285
+ success_criteria TEXT,
3286
+ parent_goal_id TEXT,
3287
+ due_at TEXT,
3288
+ achieved_at TEXT,
3289
+ supersedes_id TEXT,
3290
+ created_at TEXT NOT NULL,
3291
+ updated_at TEXT NOT NULL,
3292
+ source_memory_id TEXT
3293
+ );
3294
+
3295
+ CREATE INDEX IF NOT EXISTS idx_agent_goals_project_status
3296
+ ON agent_goals(project_name, status, priority);
3297
+
3298
+ CREATE TABLE IF NOT EXISTS agent_events (
3299
+ id TEXT PRIMARY KEY,
3300
+ event_type TEXT NOT NULL,
3301
+ occurred_at TEXT NOT NULL,
3302
+ sequence_index INTEGER NOT NULL,
3303
+ actor_agent_id TEXT,
3304
+ agent_role TEXT,
3305
+ project_name TEXT,
3306
+ session_id TEXT,
3307
+ task_id TEXT,
3308
+ goal_id TEXT,
3309
+ parent_event_id TEXT,
3310
+ intention TEXT,
3311
+ outcome TEXT,
3312
+ evidence_memory_id TEXT,
3313
+ impact TEXT,
3314
+ payload TEXT DEFAULT '{}',
3315
+ created_at TEXT NOT NULL
3316
+ );
3317
+
3318
+ CREATE INDEX IF NOT EXISTS idx_agent_events_time
3319
+ ON agent_events(occurred_at, sequence_index);
3320
+
3321
+ CREATE INDEX IF NOT EXISTS idx_agent_events_session_seq
3322
+ ON agent_events(session_id, sequence_index);
3323
+
3324
+ CREATE INDEX IF NOT EXISTS idx_agent_events_goal_time
3325
+ ON agent_events(goal_id, occurred_at);
3326
+
3327
+ CREATE INDEX IF NOT EXISTS idx_agent_events_memory
3328
+ ON agent_events(evidence_memory_id);
3329
+
3330
+ CREATE TABLE IF NOT EXISTS agent_goal_links (
3331
+ id TEXT PRIMARY KEY,
3332
+ goal_id TEXT NOT NULL,
3333
+ link_type TEXT NOT NULL,
3334
+ target_id TEXT NOT NULL,
3335
+ target_type TEXT NOT NULL,
3336
+ created_at TEXT NOT NULL
3337
+ );
3338
+
3339
+ CREATE INDEX IF NOT EXISTS idx_agent_goal_links_goal
3340
+ ON agent_goal_links(goal_id, target_type);
3341
+
3342
+ CREATE TABLE IF NOT EXISTS agent_semantic_labels (
3343
+ id TEXT PRIMARY KEY,
3344
+ source_memory_id TEXT NOT NULL,
3345
+ event_id TEXT,
3346
+ labeler TEXT NOT NULL,
3347
+ schema_version INTEGER NOT NULL DEFAULT 1,
3348
+ confidence REAL NOT NULL DEFAULT 0,
3349
+ labels TEXT NOT NULL,
3350
+ created_at TEXT NOT NULL,
3351
+ updated_at TEXT NOT NULL
3352
+ );
3353
+
3354
+ CREATE INDEX IF NOT EXISTS idx_agent_semantic_labels_memory
3355
+ ON agent_semantic_labels(source_memory_id, labeler);
3356
+
3357
+ CREATE INDEX IF NOT EXISTS idx_agent_semantic_labels_event
3358
+ ON agent_semantic_labels(event_id);
3359
+
3360
+ CREATE TABLE IF NOT EXISTS agent_reflection_checkpoints (
3361
+ id TEXT PRIMARY KEY,
3362
+ project_name TEXT,
3363
+ session_id TEXT,
3364
+ window_start_at TEXT NOT NULL,
3365
+ window_end_at TEXT NOT NULL,
3366
+ event_count INTEGER NOT NULL DEFAULT 0,
3367
+ goal_count INTEGER NOT NULL DEFAULT 0,
3368
+ success_count INTEGER NOT NULL DEFAULT 0,
3369
+ failure_count INTEGER NOT NULL DEFAULT 0,
3370
+ risk_count INTEGER NOT NULL DEFAULT 0,
3371
+ summary TEXT NOT NULL,
3372
+ learnings TEXT NOT NULL DEFAULT '[]',
3373
+ next_actions TEXT NOT NULL DEFAULT '[]',
3374
+ evidence_event_ids TEXT NOT NULL DEFAULT '[]',
3375
+ confidence REAL NOT NULL DEFAULT 0,
3376
+ created_at TEXT NOT NULL
3377
+ );
3378
+
3379
+ CREATE INDEX IF NOT EXISTS idx_agent_reflection_project_time
3380
+ ON agent_reflection_checkpoints(project_name, window_end_at);
3381
+
3382
+ CREATE INDEX IF NOT EXISTS idx_agent_reflection_session_time
3383
+ ON agent_reflection_checkpoints(session_id, window_end_at);
3384
+ `);
3249
3385
  try {
3250
3386
  await client.execute({
3251
3387
  sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
@@ -3398,12 +3534,13 @@ var keychain_exports = {};
3398
3534
  __export(keychain_exports, {
3399
3535
  deleteMasterKey: () => deleteMasterKey,
3400
3536
  exportMnemonic: () => exportMnemonic,
3537
+ getKeyStorageInfo: () => getKeyStorageInfo,
3401
3538
  getMasterKey: () => getMasterKey,
3402
3539
  importMnemonic: () => importMnemonic,
3403
3540
  setMasterKey: () => setMasterKey
3404
3541
  });
3405
3542
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3406
- import { existsSync as existsSync7 } from "fs";
3543
+ import { existsSync as existsSync7, statSync as statSync2 } from "fs";
3407
3544
  import { execSync as execSync2 } from "child_process";
3408
3545
  import path7 from "path";
3409
3546
  import os5 from "os";
@@ -3413,29 +3550,65 @@ function getKeyDir() {
3413
3550
  function getKeyPath() {
3414
3551
  return path7.join(getKeyDir(), "master.key");
3415
3552
  }
3416
- function macKeychainGet() {
3553
+ function nativeKeychainAllowed() {
3554
+ return process.env.EXE_OS_DISABLE_NATIVE_KEYCHAIN !== "1";
3555
+ }
3556
+ function linuxSecretAvailable() {
3557
+ if (!nativeKeychainAllowed()) return false;
3558
+ if (process.platform !== "linux") return false;
3559
+ if (linuxSecretAvailability !== null) return linuxSecretAvailability;
3560
+ try {
3561
+ execSync2("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
3562
+ } catch {
3563
+ linuxSecretAvailability = false;
3564
+ return false;
3565
+ }
3566
+ try {
3567
+ execSync2("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
3568
+ linuxSecretAvailability = true;
3569
+ } catch {
3570
+ linuxSecretAvailability = false;
3571
+ }
3572
+ return linuxSecretAvailability;
3573
+ }
3574
+ function isRootOnlyTrustedServerKeyFile(keyPath) {
3575
+ if (process.platform !== "linux") return false;
3576
+ try {
3577
+ const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
3578
+ const st = statSync2(keyPath);
3579
+ if (!st.isFile() || (st.mode & 63) !== 0) return false;
3580
+ if (uid === 0) return true;
3581
+ const exeOsDir = process.env.EXE_OS_DIR;
3582
+ return Boolean(exeOsDir && path7.resolve(keyPath).startsWith(path7.resolve(exeOsDir) + path7.sep));
3583
+ } catch {
3584
+ return false;
3585
+ }
3586
+ }
3587
+ function macKeychainGet(service = SERVICE) {
3588
+ if (!nativeKeychainAllowed()) return null;
3417
3589
  if (process.platform !== "darwin") return null;
3418
3590
  try {
3419
3591
  return execSync2(
3420
- `security find-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w 2>/dev/null`,
3592
+ `security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
3421
3593
  { encoding: "utf-8", timeout: 5e3 }
3422
3594
  ).trim();
3423
3595
  } catch {
3424
3596
  return null;
3425
3597
  }
3426
3598
  }
3427
- function macKeychainSet(value) {
3599
+ function macKeychainSet(value, service = SERVICE) {
3600
+ if (!nativeKeychainAllowed()) return false;
3428
3601
  if (process.platform !== "darwin") return false;
3429
3602
  try {
3430
3603
  try {
3431
3604
  execSync2(
3432
- `security delete-generic-password -s "${SERVICE}" -a "${ACCOUNT}" 2>/dev/null`,
3605
+ `security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
3433
3606
  { timeout: 5e3 }
3434
3607
  );
3435
3608
  } catch {
3436
3609
  }
3437
3610
  execSync2(
3438
- `security add-generic-password -s "${SERVICE}" -a "${ACCOUNT}" -w "${value}"`,
3611
+ `security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
3439
3612
  { timeout: 5e3 }
3440
3613
  );
3441
3614
  return true;
@@ -3443,11 +3616,12 @@ function macKeychainSet(value) {
3443
3616
  return false;
3444
3617
  }
3445
3618
  }
3446
- function macKeychainDelete() {
3619
+ function macKeychainDelete(service = SERVICE) {
3620
+ if (!nativeKeychainAllowed()) return false;
3447
3621
  if (process.platform !== "darwin") return false;
3448
3622
  try {
3449
3623
  execSync2(
3450
- `security delete-generic-password -s "${SERVICE}" -a "${ACCOUNT}" 2>/dev/null`,
3624
+ `security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
3451
3625
  { timeout: 5e3 }
3452
3626
  );
3453
3627
  return true;
@@ -3455,22 +3629,22 @@ function macKeychainDelete() {
3455
3629
  return false;
3456
3630
  }
3457
3631
  }
3458
- function linuxSecretGet() {
3459
- if (process.platform !== "linux") return null;
3632
+ function linuxSecretGet(service = SERVICE) {
3633
+ if (!linuxSecretAvailable()) return null;
3460
3634
  try {
3461
3635
  return execSync2(
3462
- `secret-tool lookup service "${SERVICE}" account "${ACCOUNT}" 2>/dev/null`,
3636
+ `secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
3463
3637
  { encoding: "utf-8", timeout: 5e3 }
3464
3638
  ).trim();
3465
3639
  } catch {
3466
3640
  return null;
3467
3641
  }
3468
3642
  }
3469
- function linuxSecretSet(value) {
3470
- if (process.platform !== "linux") return false;
3643
+ function linuxSecretSet(value, service = SERVICE) {
3644
+ if (!linuxSecretAvailable()) return false;
3471
3645
  try {
3472
3646
  execSync2(
3473
- `echo -n "${value}" | secret-tool store --label="exe-os master key" service "${SERVICE}" account "${ACCOUNT}"`,
3647
+ `echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
3474
3648
  { timeout: 5e3 }
3475
3649
  );
3476
3650
  return true;
@@ -3478,11 +3652,12 @@ function linuxSecretSet(value) {
3478
3652
  return false;
3479
3653
  }
3480
3654
  }
3481
- function linuxSecretDelete() {
3655
+ function linuxSecretDelete(service = SERVICE) {
3656
+ if (!nativeKeychainAllowed()) return false;
3482
3657
  if (process.platform !== "linux") return false;
3483
3658
  try {
3484
3659
  execSync2(
3485
- `secret-tool clear service "${SERVICE}" account "${ACCOUNT}" 2>/dev/null`,
3660
+ `secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
3486
3661
  { timeout: 5e3 }
3487
3662
  );
3488
3663
  return true;
@@ -3491,6 +3666,7 @@ function linuxSecretDelete() {
3491
3666
  }
3492
3667
  }
3493
3668
  async function tryKeytar() {
3669
+ if (!nativeKeychainAllowed()) return null;
3494
3670
  try {
3495
3671
  return await import("keytar");
3496
3672
  } catch {
@@ -3499,7 +3675,7 @@ async function tryKeytar() {
3499
3675
  }
3500
3676
  function deriveMachineKey() {
3501
3677
  try {
3502
- const crypto19 = __require("crypto");
3678
+ const crypto20 = __require("crypto");
3503
3679
  const material = [
3504
3680
  os5.hostname(),
3505
3681
  os5.userInfo().username,
@@ -3508,23 +3684,23 @@ function deriveMachineKey() {
3508
3684
  // Machine ID on Linux (stable across reboots)
3509
3685
  process.platform === "linux" ? readMachineId() : ""
3510
3686
  ].join("|");
3511
- return crypto19.createHash("sha256").update(material).digest();
3687
+ return crypto20.createHash("sha256").update(material).digest();
3512
3688
  } catch {
3513
3689
  return null;
3514
3690
  }
3515
3691
  }
3516
3692
  function readMachineId() {
3517
3693
  try {
3518
- const { readFileSync: readFileSync31 } = __require("fs");
3519
- return readFileSync31("/etc/machine-id", "utf-8").trim();
3694
+ const { readFileSync: readFileSync32 } = __require("fs");
3695
+ return readFileSync32("/etc/machine-id", "utf-8").trim();
3520
3696
  } catch {
3521
3697
  return "";
3522
3698
  }
3523
3699
  }
3524
3700
  function encryptWithMachineKey(plaintext, machineKey) {
3525
- const crypto19 = __require("crypto");
3526
- const iv = crypto19.randomBytes(12);
3527
- const cipher = crypto19.createCipheriv("aes-256-gcm", machineKey, iv);
3701
+ const crypto20 = __require("crypto");
3702
+ const iv = crypto20.randomBytes(12);
3703
+ const cipher = crypto20.createCipheriv("aes-256-gcm", machineKey, iv);
3528
3704
  let encrypted = cipher.update(plaintext, "utf-8", "base64");
3529
3705
  encrypted += cipher.final("base64");
3530
3706
  const authTag = cipher.getAuthTag().toString("base64");
@@ -3533,13 +3709,13 @@ function encryptWithMachineKey(plaintext, machineKey) {
3533
3709
  function decryptWithMachineKey(encrypted, machineKey) {
3534
3710
  if (!encrypted.startsWith(ENCRYPTED_PREFIX)) return null;
3535
3711
  try {
3536
- const crypto19 = __require("crypto");
3712
+ const crypto20 = __require("crypto");
3537
3713
  const parts = encrypted.slice(ENCRYPTED_PREFIX.length).split(":");
3538
3714
  if (parts.length !== 3) return null;
3539
3715
  const [ivB64, tagB64, cipherB64] = parts;
3540
3716
  const iv = Buffer.from(ivB64, "base64");
3541
3717
  const authTag = Buffer.from(tagB64, "base64");
3542
- const decipher = crypto19.createDecipheriv("aes-256-gcm", machineKey, iv);
3718
+ const decipher = crypto20.createDecipheriv("aes-256-gcm", machineKey, iv);
3543
3719
  decipher.setAuthTag(authTag);
3544
3720
  let decrypted = decipher.update(cipherB64, "base64", "utf-8");
3545
3721
  decrypted += decipher.final("utf-8");
@@ -3564,7 +3740,19 @@ async function writeMachineBoundFileFallback(b64) {
3564
3740
  return "plaintext";
3565
3741
  }
3566
3742
  async function getMasterKey() {
3567
- const nativeValue = macKeychainGet() ?? linuxSecretGet();
3743
+ let nativeValue = macKeychainGet() ?? linuxSecretGet();
3744
+ if (!nativeValue) {
3745
+ const legacyValue = macKeychainGet(LEGACY_SERVICE) ?? linuxSecretGet(LEGACY_SERVICE);
3746
+ if (legacyValue) {
3747
+ const migrated = macKeychainSet(legacyValue) || linuxSecretSet(legacyValue);
3748
+ if (migrated) {
3749
+ macKeychainDelete(LEGACY_SERVICE);
3750
+ linuxSecretDelete(LEGACY_SERVICE);
3751
+ process.stderr.write("[keychain] Migrated keychain service from exe-mem to exe-os.\n");
3752
+ }
3753
+ nativeValue = legacyValue;
3754
+ }
3755
+ }
3568
3756
  if (nativeValue) {
3569
3757
  return Buffer.from(nativeValue, "base64");
3570
3758
  }
@@ -3572,12 +3760,17 @@ async function getMasterKey() {
3572
3760
  if (keytar) {
3573
3761
  try {
3574
3762
  const keytarValue = await keytar.getPassword(SERVICE, ACCOUNT);
3575
- if (keytarValue) {
3576
- const migrated = macKeychainSet(keytarValue) || linuxSecretSet(keytarValue);
3763
+ const legacyKeytarValue = keytarValue ?? await keytar.getPassword(LEGACY_SERVICE, ACCOUNT);
3764
+ if (legacyKeytarValue) {
3765
+ const migrated = macKeychainSet(legacyKeytarValue) || linuxSecretSet(legacyKeytarValue);
3577
3766
  if (migrated) {
3578
3767
  process.stderr.write("[keychain] Migrated key from keytar to native keychain.\n");
3768
+ try {
3769
+ await keytar.deletePassword(LEGACY_SERVICE, ACCOUNT);
3770
+ } catch {
3771
+ }
3579
3772
  }
3580
- return Buffer.from(keytarValue, "base64");
3773
+ return Buffer.from(legacyKeytarValue, "base64");
3581
3774
  }
3582
3775
  } catch {
3583
3776
  }
@@ -3602,7 +3795,7 @@ async function getMasterKey() {
3602
3795
  const decrypted = decryptWithMachineKey(content, machineKey);
3603
3796
  if (!decrypted) {
3604
3797
  process.stderr.write(
3605
- "[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase: exe-os link import\n"
3798
+ "[keychain] Key decryption failed \u2014 machine may have changed.\n Use your 24-word recovery phrase during setup: exe-os setup\n"
3606
3799
  );
3607
3800
  return null;
3608
3801
  }
@@ -3611,6 +3804,9 @@ async function getMasterKey() {
3611
3804
  b64Value = content;
3612
3805
  }
3613
3806
  const key = Buffer.from(b64Value, "base64");
3807
+ if (!content.startsWith(ENCRYPTED_PREFIX) && isRootOnlyTrustedServerKeyFile(keyPath)) {
3808
+ return key;
3809
+ }
3614
3810
  const migrated = macKeychainSet(b64Value) || linuxSecretSet(b64Value);
3615
3811
  if (migrated) {
3616
3812
  process.stderr.write("[keychain] Migrated key from file to native keychain.\n");
@@ -3638,6 +3834,97 @@ async function getMasterKey() {
3638
3834
  return null;
3639
3835
  }
3640
3836
  }
3837
+ async function getKeyStorageInfo() {
3838
+ if (macKeychainGet()) {
3839
+ return {
3840
+ kind: "macos-keychain",
3841
+ secure: true,
3842
+ note: "stored in macOS Keychain via built-in security CLI"
3843
+ };
3844
+ }
3845
+ if (macKeychainGet(LEGACY_SERVICE)) {
3846
+ return {
3847
+ kind: "macos-keychain",
3848
+ secure: true,
3849
+ note: "stored in legacy macOS Keychain service exe-mem; next key read migrates it to exe-os"
3850
+ };
3851
+ }
3852
+ if (linuxSecretGet()) {
3853
+ return {
3854
+ kind: "linux-secret-service",
3855
+ secure: true,
3856
+ note: "stored in Linux Secret Service via secret-tool"
3857
+ };
3858
+ }
3859
+ if (linuxSecretGet(LEGACY_SERVICE)) {
3860
+ return {
3861
+ kind: "linux-secret-service",
3862
+ secure: true,
3863
+ note: "stored in legacy Linux Secret Service service exe-mem; next key read migrates it to exe-os"
3864
+ };
3865
+ }
3866
+ const keytar = await tryKeytar();
3867
+ if (keytar) {
3868
+ try {
3869
+ if (await keytar.getPassword(SERVICE, ACCOUNT)) {
3870
+ return {
3871
+ kind: "legacy-keytar",
3872
+ secure: true,
3873
+ note: "stored in legacy keytar backend; will migrate to native keychain when possible"
3874
+ };
3875
+ }
3876
+ if (await keytar.getPassword(LEGACY_SERVICE, ACCOUNT)) {
3877
+ return {
3878
+ kind: "legacy-keytar",
3879
+ secure: true,
3880
+ note: "stored in legacy keytar service exe-mem; will migrate to native exe-os keychain when possible"
3881
+ };
3882
+ }
3883
+ } catch {
3884
+ }
3885
+ }
3886
+ const keyPath = getKeyPath();
3887
+ if (!existsSync7(keyPath)) {
3888
+ return {
3889
+ kind: "missing",
3890
+ secure: false,
3891
+ path: keyPath,
3892
+ note: "no key found in OS keychain, legacy keytar, or file fallback"
3893
+ };
3894
+ }
3895
+ try {
3896
+ const content = (await readFile3(keyPath, "utf-8")).trim();
3897
+ if (content.startsWith(ENCRYPTED_PREFIX)) {
3898
+ return {
3899
+ kind: "encrypted-file",
3900
+ secure: true,
3901
+ path: keyPath,
3902
+ note: "stored in machine-bound encrypted file fallback"
3903
+ };
3904
+ }
3905
+ if (isRootOnlyTrustedServerKeyFile(keyPath)) {
3906
+ return {
3907
+ kind: "server-secret-file",
3908
+ secure: true,
3909
+ path: keyPath,
3910
+ note: "stored as root-only trusted server secret file"
3911
+ };
3912
+ }
3913
+ return {
3914
+ kind: "plaintext-file",
3915
+ secure: false,
3916
+ path: keyPath,
3917
+ note: "stored in legacy plaintext file; reading it will migrate or encrypt it"
3918
+ };
3919
+ } catch {
3920
+ return {
3921
+ kind: "missing",
3922
+ secure: false,
3923
+ path: keyPath,
3924
+ note: "key file exists but could not be read"
3925
+ };
3926
+ }
3927
+ }
3641
3928
  async function setMasterKey(key) {
3642
3929
  const b64 = key.toString("base64");
3643
3930
  if (macKeychainSet(b64) || linuxSecretSet(b64)) {
@@ -3663,10 +3950,13 @@ async function setMasterKey(key) {
3663
3950
  async function deleteMasterKey() {
3664
3951
  macKeychainDelete();
3665
3952
  linuxSecretDelete();
3953
+ macKeychainDelete(LEGACY_SERVICE);
3954
+ linuxSecretDelete(LEGACY_SERVICE);
3666
3955
  const keytar = await tryKeytar();
3667
3956
  if (keytar) {
3668
3957
  try {
3669
3958
  await keytar.deletePassword(SERVICE, ACCOUNT);
3959
+ await keytar.deletePassword(LEGACY_SERVICE, ACCOUNT);
3670
3960
  } catch {
3671
3961
  }
3672
3962
  }
@@ -3704,12 +3994,14 @@ async function importMnemonic(mnemonic) {
3704
3994
  const entropy = mnemonicToEntropy(trimmed);
3705
3995
  return Buffer.from(entropy, "hex");
3706
3996
  }
3707
- var SERVICE, ACCOUNT, ENCRYPTED_PREFIX;
3997
+ var SERVICE, LEGACY_SERVICE, ACCOUNT, linuxSecretAvailability, ENCRYPTED_PREFIX;
3708
3998
  var init_keychain = __esm({
3709
3999
  "src/lib/keychain.ts"() {
3710
4000
  "use strict";
3711
- SERVICE = "exe-mem";
4001
+ SERVICE = "exe-os";
4002
+ LEGACY_SERVICE = "exe-mem";
3712
4003
  ACCOUNT = "master-key";
4004
+ linuxSecretAvailability = null;
3713
4005
  ENCRYPTED_PREFIX = "enc:";
3714
4006
  }
3715
4007
  });
@@ -3859,8 +4151,8 @@ async function findScopedDuplicate(input) {
3859
4151
  args.push(input.excludeId);
3860
4152
  }
3861
4153
  sql += " ORDER BY timestamp DESC LIMIT 1";
3862
- const result = await client.execute({ sql, args });
3863
- return result.rows[0]?.id ? String(result.rows[0].id) : null;
4154
+ const result2 = await client.execute({ sql, args });
4155
+ return result2.rows[0]?.id ? String(result2.rows[0].id) : null;
3864
4156
  }
3865
4157
  async function runPostWriteMemoryHygiene(memoryId) {
3866
4158
  try {
@@ -3979,7 +4271,7 @@ __export(shard_manager_exports, {
3979
4271
  shardExists: () => shardExists
3980
4272
  });
3981
4273
  import path8 from "path";
3982
- import { existsSync as existsSync8, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync2 } from "fs";
4274
+ import { existsSync as existsSync8, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync3 } from "fs";
3983
4275
  import { createClient as createClient2 } from "@libsql/client";
3984
4276
  function initShardManager(encryptionKey) {
3985
4277
  _encryptionKey = encryptionKey;
@@ -4043,7 +4335,7 @@ async function auditShardHealth(options = {}) {
4043
4335
  const shards = [];
4044
4336
  for (const name of names) {
4045
4337
  const dbPath = path8.join(SHARDS_DIR, `${name}.db`);
4046
- const stat = statSync2(dbPath);
4338
+ const stat = statSync3(dbPath);
4047
4339
  const item = {
4048
4340
  name,
4049
4341
  path: dbPath,
@@ -4296,7 +4588,7 @@ async function getReadyShardClient(projectName) {
4296
4588
  _shardLastAccess.delete(safeName);
4297
4589
  const dbPath = path8.join(SHARDS_DIR, `${safeName}.db`);
4298
4590
  if (existsSync8(dbPath)) {
4299
- const stat = statSync2(dbPath);
4591
+ const stat = statSync3(dbPath);
4300
4592
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
4301
4593
  const archivedPath = path8.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
4302
4594
  renameSync3(dbPath, archivedPath);
@@ -4585,11 +4877,11 @@ __export(global_procedures_exports, {
4585
4877
  import { randomUUID as randomUUID2 } from "crypto";
4586
4878
  async function loadGlobalProcedures() {
4587
4879
  const client = getClient();
4588
- const result = await client.execute({
4880
+ const result2 = await client.execute({
4589
4881
  sql: "SELECT * FROM company_procedures WHERE active = 1 ORDER BY priority ASC, created_at ASC",
4590
4882
  args: []
4591
4883
  });
4592
- const allRows = result.rows;
4884
+ const allRows = result2.rows;
4593
4885
  const customerOnly = allRows.filter((p) => !PLATFORM_PROCEDURE_TITLES.has(p.title));
4594
4886
  if (customerOnly.length > 0) {
4595
4887
  _customerCache = customerOnly.map((p) => `### ${p.title}
@@ -4625,12 +4917,12 @@ async function storeGlobalProcedure(input) {
4625
4917
  async function deactivateGlobalProcedure(id) {
4626
4918
  const now = (/* @__PURE__ */ new Date()).toISOString();
4627
4919
  const client = getClient();
4628
- const result = await client.execute({
4920
+ const result2 = await client.execute({
4629
4921
  sql: "UPDATE company_procedures SET active = 0, updated_at = ? WHERE id = ?",
4630
4922
  args: [now, id]
4631
4923
  });
4632
4924
  await loadGlobalProcedures();
4633
- return result.rowsAffected > 0;
4925
+ return result2.rowsAffected > 0;
4634
4926
  }
4635
4927
  var _customerCache, _cacheLoaded, _platformCache;
4636
4928
  var init_global_procedures = __esm({
@@ -4774,8 +5066,8 @@ async function searchMemoryCards(queryText, agentId, options) {
4774
5066
  }
4775
5067
  sql += ` ORDER BY rank LIMIT ?`;
4776
5068
  args.push(limit);
4777
- const result = await getClient().execute({ sql, args });
4778
- return result.rows.map((row) => ({
5069
+ const result2 = await getClient().execute({ sql, args });
5070
+ return result2.rows.map((row) => ({
4779
5071
  id: `card:${String(row.id)}`,
4780
5072
  agent_id: String(row.agent_id),
4781
5073
  agent_role: "memory_card",
@@ -4803,6 +5095,274 @@ var init_memory_cards = __esm({
4803
5095
  }
4804
5096
  });
4805
5097
 
5098
+ // src/lib/agentic-ontology.ts
5099
+ var agentic_ontology_exports = {};
5100
+ __export(agentic_ontology_exports, {
5101
+ clean: () => clean,
5102
+ extractGoalCandidates: () => extractGoalCandidates,
5103
+ inferIntention: () => inferIntention,
5104
+ inferOntologyEventType: () => inferOntologyEventType,
5105
+ inferOutcome: () => inferOutcome,
5106
+ inferSemanticLabel: () => inferSemanticLabel,
5107
+ insertOntologyForBatch: () => insertOntologyForBatch,
5108
+ insertOntologyForMemory: () => insertOntologyForMemory,
5109
+ ontologyPayload: () => ontologyPayload,
5110
+ stableId: () => stableId2
5111
+ });
5112
+ import { createHash as createHash3 } from "crypto";
5113
+ function stableId2(...parts) {
5114
+ return createHash3("sha256").update(parts.map((p) => String(p ?? "")).join("::")).digest("hex").slice(0, 32);
5115
+ }
5116
+ function clean(text3, max = 240) {
5117
+ return text3.replace(/\u0000/g, "").replace(/```[\s\S]*?```/g, " ").replace(/\s+/g, " ").trim().slice(0, max);
5118
+ }
5119
+ function inferOntologyEventType(row) {
5120
+ const lower = row.raw_text.toLowerCase();
5121
+ if (row.has_error) return "error";
5122
+ if (/\b(done|complete|completed|fixed|resolved|shipped|deployed|pushed|published)\b/.test(lower)) return "milestone";
5123
+ if (/\b(blocked|failed|error|bug|regression|broken)\b/.test(lower)) return "problem";
5124
+ if (/\b(decided|decision|adr|we chose|approved|rejected)\b/.test(lower)) return "decision";
5125
+ if (/\b(goal|need to|we need|want to|trying to|objective)\b/.test(lower)) return "goal_signal";
5126
+ if (["Bash", "Read", "Edit", "Write", "Grep", "Glob"].includes(row.tool_name)) return "tool_action";
5127
+ if (row.tool_name.startsWith("memory_card")) return "memory_card";
5128
+ return "memory_observation";
5129
+ }
5130
+ function inferIntention(row) {
5131
+ if (row.intent) return clean(row.intent, 220);
5132
+ const text3 = clean(row.raw_text, 1e3);
5133
+ const patterns = [
5134
+ /(?:we need to|need to|let'?s|i want to|we should|goal is to|objective is to|trying to)\s+([^.!?\n]{8,220})/i,
5135
+ /(?:so that|in order to)\s+([^.!?\n]{8,220})/i,
5136
+ /(?:task|plan):\s*([^.!?\n]{8,220})/i
5137
+ ];
5138
+ for (const p of patterns) {
5139
+ const m = text3.match(p);
5140
+ if (m?.[1]) return clean(m[1], 220);
5141
+ }
5142
+ if (["Bash", "Read", "Edit", "Write", "Grep", "Glob"].includes(row.tool_name)) {
5143
+ return `${row.tool_name} during ${row.project_name}`;
5144
+ }
5145
+ return null;
5146
+ }
5147
+ function inferOutcome(row) {
5148
+ if (row.outcome) return clean(row.outcome, 220);
5149
+ if (row.has_error) return "error";
5150
+ const lower = row.raw_text.toLowerCase();
5151
+ if (/\b(done|complete|completed|fixed|resolved|shipped|deployed|pushed|published|passed)\b/.test(lower)) return "success_signal";
5152
+ if (/\b(blocked|failed|error|regression|broken|not working|could not)\b/.test(lower)) return "failure_signal";
5153
+ if (/\b(warning|risk|concern|caveat)\b/.test(lower)) return "risk_signal";
5154
+ return null;
5155
+ }
5156
+ function extractGoalCandidates(row) {
5157
+ const text3 = clean(row.raw_text, 1600);
5158
+ const patterns = [
5159
+ /(?:we need to|need to|i want to|we should|goal is to|objective is to|trying to|let'?s)\s+([^.!?\n]{12,220})/gi,
5160
+ /(?:success means|success criteria|so that)\s+([^.!?\n]{12,220})/gi
5161
+ ];
5162
+ const out = [];
5163
+ for (const pattern of patterns) {
5164
+ for (const m of text3.matchAll(pattern)) {
5165
+ const candidate = clean(m[1] ?? "", 220);
5166
+ if (candidate.length >= 12 && !out.some((x) => x.toLowerCase() === candidate.toLowerCase())) out.push(candidate);
5167
+ if (out.length >= 3) return out;
5168
+ }
5169
+ }
5170
+ return out;
5171
+ }
5172
+ function uniq(values, max = 6) {
5173
+ const out = [];
5174
+ for (const value of values.map((v) => clean(v, 220)).filter(Boolean)) {
5175
+ if (!out.some((x) => x.toLowerCase() === value.toLowerCase())) out.push(value);
5176
+ if (out.length >= max) break;
5177
+ }
5178
+ return out;
5179
+ }
5180
+ function extractMatches(text3, patterns, max = 5) {
5181
+ const out = [];
5182
+ for (const pattern of patterns) {
5183
+ for (const match of text3.matchAll(pattern)) {
5184
+ const value = match[1] ?? match[0];
5185
+ if (value) out.push(value);
5186
+ if (out.length >= max) return uniq(out, max);
5187
+ }
5188
+ }
5189
+ return uniq(out, max);
5190
+ }
5191
+ function inferSemanticLabel(row) {
5192
+ const text3 = clean(row.raw_text, 2400);
5193
+ const eventType = inferOntologyEventType(row);
5194
+ const intention = inferIntention(row);
5195
+ const outcome = inferOutcome(row);
5196
+ const goals = extractGoalCandidates(row);
5197
+ const milestones = extractMatches(text3, [
5198
+ /\b(?:completed|finished|fixed|resolved|shipped|deployed|published|pushed|passed)\b([^.!?\n]{0,180})/gi,
5199
+ /(?:milestone|done):\s*([^.!?\n]{8,220})/gi
5200
+ ]);
5201
+ const problems = extractMatches(text3, [
5202
+ /\b(?:blocked by|failed because|bug|regression|broken|not working|error)\b([^.!?\n]{0,180})/gi,
5203
+ /(?:problem|issue|risk):\s*([^.!?\n]{8,220})/gi
5204
+ ]);
5205
+ const decisions = extractMatches(text3, [
5206
+ /(?:decided|decision|adr|we chose|approved|rejected)\s+([^.!?\n]{8,220})/gi
5207
+ ]);
5208
+ const temporalAnchors = extractMatches(text3, [
5209
+ /\b(\d{4}-\d{2}-\d{2}(?:[T ][0-9:.+-Z]+)?)\b/g,
5210
+ /\b(today|yesterday|tomorrow|this week|next week|last week|morning|afternoon|tonight)\b/gi
5211
+ ], 8);
5212
+ const nextActions = extractMatches(text3, [
5213
+ /(?:next|todo|follow[- ]?up|remaining|need to)\s*:?\s*([^.!?\n]{8,220})/gi
5214
+ ]);
5215
+ const actors = uniq([
5216
+ row.agent_id,
5217
+ ...extractMatches(text3, [/\b(?:agent|employee|owner|assignee)[:= ]+([a-zA-Z][a-zA-Z0-9_-]{1,40})/gi], 5)
5218
+ ], 6);
5219
+ const successSignals = milestones.length ? milestones : outcome === "success_signal" ? [clean(text3, 180)] : [];
5220
+ const failureSignals = problems.length ? problems : outcome === "failure_signal" || row.has_error ? [clean(text3, 180)] : [];
5221
+ const impact = successSignals.length && failureSignals.length ? "mixed" : failureSignals.length ? "negative" : successSignals.length ? "positive" : "neutral";
5222
+ const signalCount = goals.length + milestones.length + problems.length + decisions.length + nextActions.length;
5223
+ return {
5224
+ labeler: "deterministic",
5225
+ schemaVersion: 1,
5226
+ eventType,
5227
+ intention,
5228
+ outcome,
5229
+ impact,
5230
+ confidence: Math.min(0.95, 0.45 + signalCount * 0.08 + (intention ? 0.1 : 0) + (outcome ? 0.1 : 0)),
5231
+ goals,
5232
+ milestones,
5233
+ problems,
5234
+ decisions,
5235
+ actors,
5236
+ temporalAnchors,
5237
+ successSignals,
5238
+ failureSignals,
5239
+ nextActions,
5240
+ summary: clean(text3, 280)
5241
+ };
5242
+ }
5243
+ function ontologyPayload(row) {
5244
+ const semantic = inferSemanticLabel(row);
5245
+ return {
5246
+ tool_name: row.tool_name,
5247
+ memory_version: row.version ?? null,
5248
+ domain: row.domain ?? null,
5249
+ trajectory: row.trajectory ? safeJson(row.trajectory) : null,
5250
+ semantic
5251
+ };
5252
+ }
5253
+ function safeJson(value) {
5254
+ try {
5255
+ return JSON.parse(value);
5256
+ } catch {
5257
+ return value.slice(0, 1e3);
5258
+ }
5259
+ }
5260
+ async function resolveClient(client) {
5261
+ if (client) return client;
5262
+ const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
5263
+ return getClient2();
5264
+ }
5265
+ async function insertOntologyForMemory(row, client) {
5266
+ const db = await resolveClient(client);
5267
+ const occurredAt = row.timestamp;
5268
+ const sequence = Number(row.version ?? 0) || Math.floor(new Date(occurredAt).getTime() / 1e3);
5269
+ const eventType = inferOntologyEventType(row);
5270
+ const intention = inferIntention(row);
5271
+ const outcome = inferOutcome(row);
5272
+ const eventId = stableId2("event", row.id);
5273
+ const now = (/* @__PURE__ */ new Date()).toISOString();
5274
+ await db.execute({
5275
+ sql: `INSERT INTO agent_sessions (id, agent_id, project_name, started_at, last_event_at, event_count, properties)
5276
+ VALUES (?, ?, ?, ?, ?, 1, ?)
5277
+ ON CONFLICT(id) DO UPDATE SET last_event_at = MAX(last_event_at, excluded.last_event_at),
5278
+ event_count = event_count + 1`,
5279
+ args: [row.session_id, row.agent_id, row.project_name, occurredAt, occurredAt, JSON.stringify({ agent_role: row.agent_role })]
5280
+ });
5281
+ await db.execute({
5282
+ sql: `INSERT OR IGNORE INTO agent_events
5283
+ (id, event_type, occurred_at, sequence_index, actor_agent_id, agent_role, project_name,
5284
+ session_id, task_id, goal_id, parent_event_id, intention, outcome, evidence_memory_id,
5285
+ impact, payload, created_at)
5286
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, ?, ?, ?, ?, ?, ?)`,
5287
+ args: [
5288
+ eventId,
5289
+ eventType,
5290
+ occurredAt,
5291
+ sequence,
5292
+ row.agent_id,
5293
+ row.agent_role,
5294
+ row.project_name,
5295
+ row.session_id,
5296
+ row.task_id ?? null,
5297
+ intention,
5298
+ outcome,
5299
+ row.id,
5300
+ row.has_error ? "negative" : outcome === "success_signal" ? "positive" : "neutral",
5301
+ JSON.stringify(ontologyPayload(row)),
5302
+ now
5303
+ ]
5304
+ });
5305
+ const semantic = inferSemanticLabel(row);
5306
+ await db.execute({
5307
+ sql: `INSERT INTO agent_semantic_labels
5308
+ (id, source_memory_id, event_id, labeler, schema_version, confidence, labels, created_at, updated_at)
5309
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
5310
+ ON CONFLICT(id) DO UPDATE SET confidence = excluded.confidence,
5311
+ labels = excluded.labels, updated_at = excluded.updated_at`,
5312
+ args: [
5313
+ stableId2("semantic", row.id, semantic.labeler, semantic.schemaVersion),
5314
+ row.id,
5315
+ eventId,
5316
+ semantic.labeler,
5317
+ semantic.schemaVersion,
5318
+ semantic.confidence,
5319
+ JSON.stringify(semantic),
5320
+ now,
5321
+ now
5322
+ ]
5323
+ });
5324
+ for (const statement of extractGoalCandidates(row)) {
5325
+ const goalId = stableId2("goal", row.project_name, statement.toLowerCase());
5326
+ await db.execute({
5327
+ sql: `INSERT INTO agent_goals
5328
+ (id, statement, owner_agent_id, project_name, status, priority, success_criteria,
5329
+ parent_goal_id, due_at, achieved_at, supersedes_id, created_at, updated_at, source_memory_id)
5330
+ VALUES (?, ?, ?, ?, 'open', 5, NULL, NULL, NULL, NULL, NULL, ?, ?, ?)
5331
+ ON CONFLICT(id) DO UPDATE SET updated_at = excluded.updated_at`,
5332
+ args: [goalId, statement, row.agent_id, row.project_name, now, now, row.id]
5333
+ });
5334
+ await db.execute({
5335
+ sql: `INSERT OR IGNORE INTO agent_goal_links
5336
+ (id, goal_id, link_type, target_id, target_type, created_at)
5337
+ VALUES (?, ?, 'evidence', ?, 'memory', ?)`,
5338
+ args: [stableId2("goal_link", goalId, row.id, "memory"), goalId, row.id, now]
5339
+ });
5340
+ await db.execute({
5341
+ sql: `INSERT OR IGNORE INTO agent_goal_links
5342
+ (id, goal_id, link_type, target_id, target_type, created_at)
5343
+ VALUES (?, ?, 'event', ?, 'event', ?)`,
5344
+ args: [stableId2("goal_link", goalId, eventId, "event"), goalId, eventId, now]
5345
+ });
5346
+ }
5347
+ }
5348
+ async function insertOntologyForBatch(rows, client) {
5349
+ const db = await resolveClient(client);
5350
+ let count = 0;
5351
+ for (const row of rows) {
5352
+ try {
5353
+ await insertOntologyForMemory(row, db);
5354
+ count++;
5355
+ } catch {
5356
+ }
5357
+ }
5358
+ return count;
5359
+ }
5360
+ var init_agentic_ontology = __esm({
5361
+ "src/lib/agentic-ontology.ts"() {
5362
+ "use strict";
5363
+ }
5364
+ });
5365
+
4806
5366
  // src/lib/store.ts
4807
5367
  var store_exports = {};
4808
5368
  __export(store_exports, {
@@ -5146,6 +5706,11 @@ async function flushBatch() {
5146
5706
  await insertMemoryCardsForBatch2(batch);
5147
5707
  } catch {
5148
5708
  }
5709
+ try {
5710
+ const { insertOntologyForBatch: insertOntologyForBatch2 } = await Promise.resolve().then(() => (init_agentic_ontology(), agentic_ontology_exports));
5711
+ await insertOntologyForBatch2(batch);
5712
+ } catch {
5713
+ }
5149
5714
  schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
5150
5715
  _pendingRecords.splice(0, batch.length);
5151
5716
  try {
@@ -5279,8 +5844,8 @@ async function searchMemories(queryVector, agentId, options) {
5279
5844
  args.push(vectorToBlob(queryVector));
5280
5845
  sql += ` LIMIT ?`;
5281
5846
  args.push(limit);
5282
- const result = await client.execute({ sql, args });
5283
- return result.rows.map((row) => ({
5847
+ const result2 = await client.execute({ sql, args });
5848
+ return result2.rows.map((row) => ({
5284
5849
  id: row.id,
5285
5850
  agent_id: row.agent_id,
5286
5851
  agent_role: row.agent_role,
@@ -5314,14 +5879,14 @@ async function attachDocumentMetadata(records) {
5314
5879
  try {
5315
5880
  const client = getClient();
5316
5881
  const placeholders = docIds.map(() => "?").join(",");
5317
- const result = await client.execute({
5882
+ const result2 = await client.execute({
5318
5883
  sql: `SELECT id, filename, mime, source_type, uploaded_at
5319
5884
  FROM documents
5320
5885
  WHERE id IN (${placeholders})`,
5321
5886
  args: docIds
5322
5887
  });
5323
5888
  const byId = /* @__PURE__ */ new Map();
5324
- for (const row of result.rows) {
5889
+ for (const row of result2.rows) {
5325
5890
  const id = row.id;
5326
5891
  byId.set(id, {
5327
5892
  document_id: id,
@@ -5344,19 +5909,19 @@ async function flushTier3(agentId, options) {
5344
5909
  const maxAge = options?.maxAgeHours ?? 72;
5345
5910
  const cutoff = new Date(Date.now() - maxAge * 36e5).toISOString();
5346
5911
  if (options?.dryRun) {
5347
- const result2 = await client.execute({
5912
+ const result3 = await client.execute({
5348
5913
  sql: `SELECT COUNT(*) as cnt FROM memories
5349
5914
  WHERE agent_id = ? AND tier = 3 AND status = 'active' AND timestamp < ?`,
5350
5915
  args: [agentId, cutoff]
5351
5916
  });
5352
- return { archived: Number(result2.rows[0]?.cnt ?? 0) };
5917
+ return { archived: Number(result3.rows[0]?.cnt ?? 0) };
5353
5918
  }
5354
- const result = await client.execute({
5919
+ const result2 = await client.execute({
5355
5920
  sql: `UPDATE memories SET status = 'archived'
5356
5921
  WHERE agent_id = ? AND tier = 3 AND status = 'active' AND timestamp < ?`,
5357
5922
  args: [agentId, cutoff]
5358
5923
  });
5359
- return { archived: result.rowsAffected };
5924
+ return { archived: result2.rowsAffected };
5360
5925
  }
5361
5926
  async function disposeStore() {
5362
5927
  if (_flushTimer !== null) {
@@ -5391,11 +5956,11 @@ function reserveVersions(count) {
5391
5956
  async function getMemoryCardinality(agentId) {
5392
5957
  try {
5393
5958
  const client = getClient();
5394
- const result = await client.execute({
5959
+ const result2 = await client.execute({
5395
5960
  sql: `SELECT COUNT(*) as cnt FROM memories WHERE agent_id = ? AND COALESCE(status, 'active') = 'active'`,
5396
5961
  args: [agentId]
5397
5962
  });
5398
- return Number(result.rows[0]?.cnt) || 0;
5963
+ return Number(result2.rows[0]?.cnt) || 0;
5399
5964
  } catch {
5400
5965
  return 0;
5401
5966
  }
@@ -5696,7 +6261,7 @@ __export(file_grep_exports, {
5696
6261
  grepProjectFiles: () => grepProjectFiles
5697
6262
  });
5698
6263
  import { execSync as execSync4 } from "child_process";
5699
- import { readFileSync as readFileSync6, readdirSync as readdirSync2, statSync as statSync3, existsSync as existsSync10 } from "fs";
6264
+ import { readFileSync as readFileSync6, readdirSync as readdirSync2, statSync as statSync4, existsSync as existsSync10 } from "fs";
5700
6265
  import path11 from "path";
5701
6266
  import crypto2 from "crypto";
5702
6267
  function hasRipgrep() {
@@ -5813,7 +6378,7 @@ function grepWithNodeFs(pattern, projectRoot, patterns) {
5813
6378
  for (const filePath of files.slice(0, MAX_FILES)) {
5814
6379
  const absPath = path11.join(projectRoot, filePath);
5815
6380
  try {
5816
- const stat = statSync3(absPath);
6381
+ const stat = statSync4(absPath);
5817
6382
  if (stat.size > MAX_FILE_SIZE) continue;
5818
6383
  const content = readFileSync6(absPath, "utf8");
5819
6384
  const lines = content.split("\n");
@@ -5930,9 +6495,9 @@ __export(graph_query_exports, {
5930
6495
  async function getEntityByName(client, name, type) {
5931
6496
  const sql = type ? `SELECT * FROM entities WHERE LOWER(name) = LOWER(?) AND type = ? LIMIT 1` : `SELECT * FROM entities WHERE LOWER(name) = LOWER(?) LIMIT 1`;
5932
6497
  const args = type ? [name, type] : [name];
5933
- const result = await client.execute({ sql, args });
5934
- if (result.rows.length === 0) return null;
5935
- const row = result.rows[0];
6498
+ const result2 = await client.execute({ sql, args });
6499
+ if (result2.rows.length === 0) return null;
6500
+ const row = result2.rows[0];
5936
6501
  return {
5937
6502
  id: String(row.id),
5938
6503
  name: String(row.name),
@@ -5943,11 +6508,11 @@ async function getEntityByName(client, name, type) {
5943
6508
  };
5944
6509
  }
5945
6510
  async function searchEntities(client, query, limit = 10) {
5946
- const result = await client.execute({
6511
+ const result2 = await client.execute({
5947
6512
  sql: `SELECT * FROM entities WHERE LOWER(name) LIKE ? ORDER BY last_seen DESC LIMIT ?`,
5948
6513
  args: [`%${query.toLowerCase()}%`, limit]
5949
6514
  });
5950
- return result.rows.map((row) => ({
6515
+ return result2.rows.map((row) => ({
5951
6516
  id: String(row.id),
5952
6517
  name: String(row.name),
5953
6518
  type: String(row.type),
@@ -5987,8 +6552,8 @@ async function getRelationships(client, entityId2, options) {
5987
6552
  args.push(options.type);
5988
6553
  }
5989
6554
  sql += ` ORDER BY r.weight DESC, r.timestamp DESC`;
5990
- const result = await client.execute({ sql, args });
5991
- return result.rows.map((row) => ({
6555
+ const result2 = await client.execute({ sql, args });
6556
+ return result2.rows.map((row) => ({
5992
6557
  id: String(row.id),
5993
6558
  sourceEntityId: String(row.source_entity_id),
5994
6559
  targetEntityId: String(row.target_entity_id),
@@ -6003,7 +6568,7 @@ async function getRelationships(client, entityId2, options) {
6003
6568
  }));
6004
6569
  }
6005
6570
  async function traverseChain(client, startEntityId, relationshipType, maxDepth = 3) {
6006
- const result = await client.execute({
6571
+ const result2 = await client.execute({
6007
6572
  sql: `WITH RECURSIVE chain(entity_id, depth, rel_type) AS (
6008
6573
  SELECT ?, 0, ''
6009
6574
  UNION ALL
@@ -6018,7 +6583,7 @@ async function traverseChain(client, startEntityId, relationshipType, maxDepth =
6018
6583
  ORDER BY chain.depth ASC`,
6019
6584
  args: [startEntityId, relationshipType, maxDepth]
6020
6585
  });
6021
- return result.rows.map((row) => ({
6586
+ return result2.rows.map((row) => ({
6022
6587
  entity: {
6023
6588
  id: String(row.id),
6024
6589
  name: String(row.name),
@@ -6032,7 +6597,7 @@ async function traverseChain(client, startEntityId, relationshipType, maxDepth =
6032
6597
  }));
6033
6598
  }
6034
6599
  async function getEntityNeighbors(client, entityId2, maxHops = 2) {
6035
- const result = await client.execute({
6600
+ const result2 = await client.execute({
6036
6601
  sql: `WITH RECURSIVE neighborhood(entity_id, depth, rel_type, rel_confidence) AS (
6037
6602
  SELECT ?, 0, '', 1.0
6038
6603
  UNION ALL
@@ -6054,7 +6619,7 @@ async function getEntityNeighbors(client, entityId2, maxHops = 2) {
6054
6619
  LIMIT 50`,
6055
6620
  args: [entityId2, maxHops]
6056
6621
  });
6057
- return result.rows.map((row) => ({
6622
+ return result2.rows.map((row) => ({
6058
6623
  entity: {
6059
6624
  id: String(row.id),
6060
6625
  name: String(row.name),
@@ -6091,7 +6656,7 @@ async function getEntityTimeline(client, entityId2, since) {
6091
6656
  sinceClause = " AND r.timestamp >= ?";
6092
6657
  args.push(since.toISOString());
6093
6658
  }
6094
- const result = await client.execute({
6659
+ const result2 = await client.execute({
6095
6660
  sql: `SELECT r.*, s.name as source_name, t.name as target_name
6096
6661
  FROM relationships r
6097
6662
  JOIN entities s ON r.source_entity_id = s.id
@@ -6100,7 +6665,7 @@ async function getEntityTimeline(client, entityId2, since) {
6100
6665
  ORDER BY r.timestamp DESC`,
6101
6666
  args
6102
6667
  });
6103
- return result.rows.map((row) => ({
6668
+ return result2.rows.map((row) => ({
6104
6669
  relationship: {
6105
6670
  id: String(row.id),
6106
6671
  sourceEntityId: String(row.source_entity_id),
@@ -6134,7 +6699,7 @@ async function getRelationshipFrequency(client, entityId2, options) {
6134
6699
  default:
6135
6700
  bucketExpr = `strftime('%Y-%m-%d', r.timestamp)`;
6136
6701
  }
6137
- const result = await client.execute({
6702
+ const result2 = await client.execute({
6138
6703
  sql: `SELECT ${bucketExpr} as bucket, COUNT(*) as cnt, r.type as rel_type
6139
6704
  FROM relationships r
6140
6705
  WHERE (r.source_entity_id = ? OR r.target_entity_id = ?)${typeClause}
@@ -6142,7 +6707,7 @@ async function getRelationshipFrequency(client, entityId2, options) {
6142
6707
  ORDER BY bucket DESC`,
6143
6708
  args
6144
6709
  });
6145
- return result.rows.map((row) => ({
6710
+ return result2.rows.map((row) => ({
6146
6711
  bucket: String(row.bucket),
6147
6712
  count: Number(row.cnt),
6148
6713
  relationshipType: options?.type ? options.type : String(row.rel_type)
@@ -6155,7 +6720,7 @@ async function getConversationPartners(client, contactEntityId, since) {
6155
6720
  sinceClause = " AND r.timestamp >= ?";
6156
6721
  args.push(since.toISOString());
6157
6722
  }
6158
- const result = await client.execute({
6723
+ const result2 = await client.execute({
6159
6724
  sql: `SELECT
6160
6725
  CASE
6161
6726
  WHEN r.source_entity_id = ? THEN r.target_entity_id
@@ -6170,7 +6735,7 @@ async function getConversationPartners(client, contactEntityId, since) {
6170
6735
  args: [contactEntityId, ...args]
6171
6736
  });
6172
6737
  const partners = [];
6173
- for (const row of result.rows) {
6738
+ for (const row of result2.rows) {
6174
6739
  const partnerId = String(row.partner_id);
6175
6740
  const entityResult = await client.execute({
6176
6741
  sql: "SELECT * FROM entities WHERE id = ?",
@@ -6195,7 +6760,7 @@ async function getConversationPartners(client, contactEntityId, since) {
6195
6760
  }
6196
6761
  async function getHotEntities(client, since, limit = 10) {
6197
6762
  const sinceISO = since.toISOString();
6198
- const result = await client.execute({
6763
+ const result2 = await client.execute({
6199
6764
  sql: `SELECT entity_id, COUNT(*) as rel_count
6200
6765
  FROM (
6201
6766
  SELECT source_entity_id as entity_id FROM relationships WHERE timestamp >= ?
@@ -6208,7 +6773,7 @@ async function getHotEntities(client, since, limit = 10) {
6208
6773
  args: [sinceISO, sinceISO, limit]
6209
6774
  });
6210
6775
  const hotEntities = [];
6211
- for (const row of result.rows) {
6776
+ for (const row of result2.rows) {
6212
6777
  const eid = String(row.entity_id);
6213
6778
  const entityResult = await client.execute({
6214
6779
  sql: "SELECT * FROM entities WHERE id = ?",
@@ -6255,7 +6820,7 @@ async function matchEntities(query, client) {
6255
6820
  if (words.length === 0) return [];
6256
6821
  try {
6257
6822
  const matchExpr = words.map((w) => `${w}*`).join(" OR ");
6258
- const result = await client.execute({
6823
+ const result2 = await client.execute({
6259
6824
  sql: `SELECT e.id, e.name FROM entities e
6260
6825
  JOIN entities_fts fts ON e.rowid = fts.rowid
6261
6826
  WHERE entities_fts MATCH ?
@@ -6263,8 +6828,8 @@ async function matchEntities(query, client) {
6263
6828
  LIMIT ?`,
6264
6829
  args: [matchExpr, MAX_ENTITY_MATCHES]
6265
6830
  });
6266
- if (result.rows.length > 0) {
6267
- return result.rows.map((row) => ({
6831
+ if (result2.rows.length > 0) {
6832
+ return result2.rows.map((row) => ({
6268
6833
  entityId: String(row.id),
6269
6834
  name: String(row.name)
6270
6835
  }));
@@ -6274,13 +6839,13 @@ async function matchEntities(query, client) {
6274
6839
  const conditions = words.map(() => `LOWER(name) LIKE ?`);
6275
6840
  const args = words.map((w) => `%${w}%`);
6276
6841
  try {
6277
- const result = await client.execute({
6842
+ const result2 = await client.execute({
6278
6843
  sql: `SELECT id, name FROM entities
6279
6844
  WHERE ${conditions.join(" OR ")}
6280
6845
  LIMIT ?`,
6281
6846
  args: [...args, MAX_ENTITY_MATCHES]
6282
6847
  });
6283
- return result.rows.map((row) => ({
6848
+ return result2.rows.map((row) => ({
6284
6849
  entityId: String(row.id),
6285
6850
  name: String(row.name)
6286
6851
  }));
@@ -6293,12 +6858,12 @@ async function getLinkedMemories(entityIds, client) {
6293
6858
  if (entityIds.length === 0) return linked;
6294
6859
  const placeholders = entityIds.map(() => "?").join(",");
6295
6860
  try {
6296
- const result = await client.execute({
6861
+ const result2 = await client.execute({
6297
6862
  sql: `SELECT entity_id, memory_id FROM entity_memories
6298
6863
  WHERE entity_id IN (${placeholders})`,
6299
6864
  args: entityIds
6300
6865
  });
6301
- for (const row of result.rows) {
6866
+ for (const row of result2.rows) {
6302
6867
  const entityId2 = String(row.entity_id);
6303
6868
  const memoryId = String(row.memory_id);
6304
6869
  const entry = linked.get(entityId2) ?? {
@@ -6371,13 +6936,13 @@ async function applyHyperedgeBoost(entities, client, boostMap, resultIds) {
6371
6936
  const entityIds = entities.map((e) => e.entityId);
6372
6937
  const placeholders = entityIds.map(() => "?").join(",");
6373
6938
  try {
6374
- const result = await client.execute({
6939
+ const result2 = await client.execute({
6375
6940
  sql: `SELECT hyperedge_id, entity_id FROM hyperedge_nodes
6376
6941
  WHERE entity_id IN (${placeholders})`,
6377
6942
  args: entityIds
6378
6943
  });
6379
6944
  const hyperedgeEntities = /* @__PURE__ */ new Map();
6380
- for (const row of result.rows) {
6945
+ for (const row of result2.rows) {
6381
6946
  const hid = String(row.hyperedge_id);
6382
6947
  const eid = String(row.entity_id);
6383
6948
  const set = hyperedgeEntities.get(hid) ?? /* @__PURE__ */ new Set();
@@ -6702,10 +7267,10 @@ async function hybridSearch(queryText, agentId, options) {
6702
7267
  };
6703
7268
  try {
6704
7269
  const fs = await import("fs");
6705
- const path49 = await import("path");
7270
+ const path50 = await import("path");
6706
7271
  const os21 = await import("os");
6707
- const logPath = path49.join(os21.homedir(), ".exe-os", "search-quality.jsonl");
6708
- fs.mkdirSync(path49.dirname(logPath), { recursive: true });
7272
+ const logPath = path50.join(os21.homedir(), ".exe-os", "search-quality.jsonl");
7273
+ fs.mkdirSync(path50.dirname(logPath), { recursive: true });
6709
7274
  fs.appendFileSync(logPath, JSON.stringify(logEntry) + "\n");
6710
7275
  } catch {
6711
7276
  }
@@ -6754,8 +7319,8 @@ async function estimateCardinality(agentId, options) {
6754
7319
  }
6755
7320
  sql = appendMemoryTypeFilter(sql, args, "memory_type", options);
6756
7321
  try {
6757
- const result = await client.execute({ sql, args });
6758
- return Number(result.rows[0]?.cnt) || 0;
7322
+ const result2 = await client.execute({ sql, args });
7323
+ return Number(result2.rows[0]?.cnt) || 0;
6759
7324
  } catch {
6760
7325
  return 0;
6761
7326
  }
@@ -6886,8 +7451,8 @@ async function ftsQuery(client, matchExpr, agentId, options, limit) {
6886
7451
  sql = appendMemoryTypeFilter(sql, args, "m.memory_type", options);
6887
7452
  sql += ` ORDER BY rank LIMIT ?`;
6888
7453
  args.push(limit);
6889
- const result = await client.execute({ sql, args });
6890
- return result.rows.map((row) => ({
7454
+ const result2 = await client.execute({ sql, args });
7455
+ return result2.rows.map((row) => ({
6891
7456
  id: row.id,
6892
7457
  agent_id: row.agent_id,
6893
7458
  agent_role: row.agent_role,
@@ -7002,8 +7567,8 @@ async function recentRecords(agentId, options, limit, textFilter) {
7002
7567
  }
7003
7568
  sql += ` ORDER BY timestamp DESC LIMIT ?`;
7004
7569
  args.push(limit);
7005
- const result = await client.execute({ sql, args });
7006
- const recentResults = result.rows.map((row) => rowToMemoryRecord(row));
7570
+ const result2 = await client.execute({ sql, args });
7571
+ const recentResults = result2.rows.map((row) => rowToMemoryRecord(row));
7007
7572
  if (sessionBoundaryMemories.length > 0) {
7008
7573
  const seenIds = new Set(recentResults.map((r) => r.id));
7009
7574
  for (const bm of sessionBoundaryMemories) {
@@ -7086,9 +7651,9 @@ async function trajectoryBypass(queryText, agentId, options, limit) {
7086
7651
  }
7087
7652
  sql += ` ORDER BY timestamp DESC LIMIT ?`;
7088
7653
  args.push(limit);
7089
- const result = await client.execute({ sql, args });
7090
- if (result.rows.length < 3) return null;
7091
- return result.rows.map((row) => ({
7654
+ const result2 = await client.execute({ sql, args });
7655
+ if (result2.rows.length < 3) return null;
7656
+ return result2.rows.map((row) => ({
7092
7657
  id: row.id,
7093
7658
  agent_id: row.agent_id,
7094
7659
  agent_role: row.agent_role,
@@ -7658,8 +8223,8 @@ async function validateLicense(apiKey, deviceId) {
7658
8223
  }
7659
8224
  function getCacheAgeMs() {
7660
8225
  try {
7661
- const { statSync: statSync7 } = __require("fs");
7662
- const s = statSync7(CACHE_PATH);
8226
+ const { statSync: statSync9 } = __require("fs");
8227
+ const s = statSync9(CACHE_PATH);
7663
8228
  return Date.now() - s.mtimeMs;
7664
8229
  } catch {
7665
8230
  return Infinity;
@@ -7914,10 +8479,10 @@ function freeLicense() {
7914
8479
  async function countActiveMemories() {
7915
8480
  if (!isInitialized()) return 0;
7916
8481
  const client = getClient();
7917
- const result = await client.execute(
8482
+ const result2 = await client.execute(
7918
8483
  "SELECT COUNT(*) as cnt FROM memories WHERE status = 'active' OR status IS NULL"
7919
8484
  );
7920
- const row = result.rows[0];
8485
+ const row = result2.rows[0];
7921
8486
  return Number(row?.cnt ?? 0);
7922
8487
  }
7923
8488
  async function assertMemoryLimit() {
@@ -7997,8 +8562,8 @@ __export(wiki_client_exports, {
7997
8562
  listDocuments: () => listDocuments,
7998
8563
  listWorkspaces: () => listWorkspaces
7999
8564
  });
8000
- async function wikiFetch(config2, path49, method = "GET", body) {
8001
- const url = `${config2.baseUrl}/api/v1${path49}`;
8565
+ async function wikiFetch(config2, path50, method = "GET", body) {
8566
+ const url = `${config2.baseUrl}/api/v1${path50}`;
8002
8567
  const headers = {
8003
8568
  Authorization: `Bearer ${config2.apiKey}`,
8004
8569
  "Content-Type": "application/json"
@@ -8031,7 +8596,7 @@ async function wikiFetch(config2, path49, method = "GET", body) {
8031
8596
  }
8032
8597
  }
8033
8598
  if (!response.ok) {
8034
- throw new Error(`Wiki API ${method} ${path49}: ${response.status} ${response.statusText}`);
8599
+ throw new Error(`Wiki API ${method} ${path50}: ${response.status} ${response.statusText}`);
8035
8600
  }
8036
8601
  return response.json();
8037
8602
  } finally {
@@ -8145,7 +8710,7 @@ __export(consolidation_exports, {
8145
8710
  });
8146
8711
  import { randomUUID as randomUUID4 } from "crypto";
8147
8712
  async function selectUnconsolidated(client, limit = 200) {
8148
- const result = await client.execute({
8713
+ const result2 = await client.execute({
8149
8714
  sql: `SELECT id, agent_id, project_name, tool_name, raw_text, timestamp
8150
8715
  FROM memories
8151
8716
  WHERE consolidated = 0
@@ -8153,7 +8718,7 @@ async function selectUnconsolidated(client, limit = 200) {
8153
8718
  LIMIT ?`,
8154
8719
  args: [limit]
8155
8720
  });
8156
- return result.rows.map((row) => ({
8721
+ return result2.rows.map((row) => ({
8157
8722
  id: row.id,
8158
8723
  agent_id: row.agent_id,
8159
8724
  project_name: row.project_name,
@@ -8393,10 +8958,10 @@ async function runConsolidation(client, options) {
8393
8958
  if (dedupCount > 0) clustersProcessed++;
8394
8959
  continue;
8395
8960
  }
8396
- const result = await storeConsolidation(client, cluster, synthesis, options.embedFn);
8961
+ const result2 = await storeConsolidation(client, cluster, synthesis, options.embedFn);
8397
8962
  if (isCoordinator && options.wikiConfig) {
8398
8963
  await pushToWiki(
8399
- { ...result, projectName: cluster.projectName },
8964
+ { ...result2, projectName: cluster.projectName },
8400
8965
  options.wikiConfig
8401
8966
  ).catch((err) => {
8402
8967
  process.stderr.write(
@@ -8406,7 +8971,7 @@ async function runConsolidation(client, options) {
8406
8971
  });
8407
8972
  }
8408
8973
  if (isCoordinator) {
8409
- const sourceIds = result.sourceIds;
8974
+ const sourceIds = result2.sourceIds;
8410
8975
  if (sourceIds.length > 0) {
8411
8976
  const placeholders = sourceIds.map(() => "?").join(",");
8412
8977
  await client.execute({
@@ -8476,26 +9041,26 @@ function cosineSimilarity(a, b) {
8476
9041
  return denom === 0 ? 0 : dot / denom;
8477
9042
  }
8478
9043
  async function isUserIdle(client, idleMinutes = 30) {
8479
- const result = await client.execute({
9044
+ const result2 = await client.execute({
8480
9045
  sql: `SELECT MAX(timestamp) as last_activity
8481
9046
  FROM memories
8482
9047
  WHERE tool_name != 'consolidation'
8483
9048
  AND timestamp >= datetime('now', '-1 day')`,
8484
9049
  args: []
8485
9050
  });
8486
- const lastActivity = result.rows[0]?.last_activity;
9051
+ const lastActivity = result2.rows[0]?.last_activity;
8487
9052
  if (!lastActivity) return true;
8488
9053
  const lastMs = new Date(lastActivity).getTime();
8489
9054
  const now = Date.now();
8490
9055
  return now - lastMs >= idleMinutes * 60 * 1e3;
8491
9056
  }
8492
9057
  async function countUnconsolidated(client) {
8493
- const result = await client.execute({
9058
+ const result2 = await client.execute({
8494
9059
  sql: `SELECT COUNT(*) as cnt FROM memories
8495
9060
  WHERE consolidated = 0`,
8496
9061
  args: []
8497
9062
  });
8498
- return Number(result.rows[0]?.cnt ?? 0);
9063
+ return Number(result2.rows[0]?.cnt ?? 0);
8499
9064
  }
8500
9065
  var ROLE_PROMPTS, DEFAULT_ROLE_PROMPT, WIKI_FETCH_TIMEOUT_MS;
8501
9066
  var init_consolidation = __esm({
@@ -8634,12 +9199,12 @@ var init_tmux_transport = __esm({
8634
9199
  }
8635
9200
  isPaneInCopyMode(target) {
8636
9201
  try {
8637
- const result = execFileSync(
9202
+ const result2 = execFileSync(
8638
9203
  "tmux",
8639
9204
  ["display-message", "-p", "-t", target, "#{pane_in_mode}"],
8640
9205
  { ...QUIET, timeout: 3e3 }
8641
9206
  ).trim();
8642
- return result === "1";
9207
+ return result2 === "1";
8643
9208
  } catch {
8644
9209
  return false;
8645
9210
  }
@@ -8981,11 +9546,11 @@ async function recordSessionKill(input) {
8981
9546
  async function countKillsSince(sinceISO) {
8982
9547
  try {
8983
9548
  const client = getClient();
8984
- const result = await client.execute({
9549
+ const result2 = await client.execute({
8985
9550
  sql: `SELECT COUNT(*) AS n FROM session_kills WHERE killed_at >= ?`,
8986
9551
  args: [sinceISO]
8987
9552
  });
8988
- const row = result.rows[0];
9553
+ const row = result2.rows[0];
8989
9554
  return row ? Number(row.n) : 0;
8990
9555
  } catch {
8991
9556
  return 0;
@@ -8994,13 +9559,13 @@ async function countKillsSince(sinceISO) {
8994
9559
  async function sumTokensSavedSince(sinceISO) {
8995
9560
  try {
8996
9561
  const client = getClient();
8997
- const result = await client.execute({
9562
+ const result2 = await client.execute({
8998
9563
  sql: `SELECT COALESCE(SUM(estimated_tokens_saved), 0) AS total
8999
9564
  FROM session_kills
9000
9565
  WHERE killed_at >= ?`,
9001
9566
  args: [sinceISO]
9002
9567
  });
9003
- const row = result.rows[0];
9568
+ const row = result2.rows[0];
9004
9569
  return row ? Number(row.total) : 0;
9005
9570
  } catch {
9006
9571
  return 0;
@@ -9092,13 +9657,13 @@ function _resetLastRelaunchCache() {
9092
9657
  async function lastResumeCreatedAtMs(agentId) {
9093
9658
  const client = getClient();
9094
9659
  const cmScope = sessionScopeFilter(null);
9095
- const result = await client.execute({
9660
+ const result2 = await client.execute({
9096
9661
  sql: `SELECT MAX(created_at) AS last_created_at
9097
9662
  FROM tasks
9098
9663
  WHERE assigned_to = ? AND title LIKE ?${cmScope.sql}`,
9099
9664
  args: [agentId, `${RESUME_TITLE_PREFIX} %`, ...cmScope.args]
9100
9665
  });
9101
- const raw = result.rows[0]?.last_created_at;
9666
+ const raw = result2.rows[0]?.last_created_at;
9102
9667
  if (raw === null || raw === void 0) return null;
9103
9668
  const parsed = Date.parse(String(raw));
9104
9669
  return Number.isNaN(parsed) ? null : parsed;
@@ -9335,37 +9900,37 @@ async function countPendingReviews(sessionScope) {
9335
9900
  const scope = strictSessionScopeFilter(
9336
9901
  sessionScope === void 0 ? getCurrentSessionScope() : sessionScope
9337
9902
  );
9338
- const result = await client.execute({
9903
+ const result2 = await client.execute({
9339
9904
  sql: `SELECT COUNT(*) as cnt FROM tasks
9340
9905
  WHERE status = 'needs_review'${scope.sql}`,
9341
9906
  args: [...scope.args]
9342
9907
  });
9343
- return Number(result.rows[0]?.cnt) || 0;
9908
+ return Number(result2.rows[0]?.cnt) || 0;
9344
9909
  }
9345
9910
  async function countNewPendingReviewsSince(sinceIso, sessionScope) {
9346
9911
  const client = getClient();
9347
9912
  const scope = strictSessionScopeFilter(
9348
9913
  sessionScope === void 0 ? getCurrentSessionScope() : sessionScope
9349
9914
  );
9350
- const result = await client.execute({
9915
+ const result2 = await client.execute({
9351
9916
  sql: `SELECT COUNT(*) as cnt FROM tasks
9352
9917
  WHERE status = 'needs_review' AND updated_at > ?${scope.sql}`,
9353
9918
  args: [sinceIso, ...scope.args]
9354
9919
  });
9355
- return Number(result.rows[0]?.cnt) || 0;
9920
+ return Number(result2.rows[0]?.cnt) || 0;
9356
9921
  }
9357
9922
  async function listPendingReviews(limit, sessionScope) {
9358
9923
  const client = getClient();
9359
9924
  const scope = strictSessionScopeFilter(
9360
9925
  sessionScope === void 0 ? getCurrentSessionScope() : sessionScope
9361
9926
  );
9362
- const result = await client.execute({
9927
+ const result2 = await client.execute({
9363
9928
  sql: `SELECT title, assigned_to, project_name, updated_at FROM tasks
9364
9929
  WHERE status = 'needs_review'${scope.sql}
9365
9930
  ORDER BY updated_at ASC LIMIT ?`,
9366
9931
  args: [...scope.args, limit]
9367
9932
  });
9368
- return result.rows;
9933
+ return result2.rows;
9369
9934
  }
9370
9935
  async function cleanupOrphanedReviews() {
9371
9936
  const client = getClient();
@@ -9450,7 +10015,7 @@ function getReviewChecklist(role, agent, taskSlug) {
9450
10015
  ]
9451
10016
  };
9452
10017
  }
9453
- async function createReviewForCompletedTask(row, result, _baseDir, now) {
10018
+ async function createReviewForCompletedTask(row, result2, _baseDir, now) {
9454
10019
  const taskFile = String(row.task_file);
9455
10020
  const employees = await loadEmployees();
9456
10021
  const coordinatorName = getCoordinatorName(employees);
@@ -9495,7 +10060,7 @@ async function createReviewForCompletedTask(row, result, _baseDir, now) {
9495
10060
  "- **Needs work:** re-open with notes"
9496
10061
  ].join("\n");
9497
10062
  const originalTaskId = String(row.id);
9498
- const updatedResult = (result ?? "No result summary provided") + reviewNotes;
10063
+ const updatedResult = (result2 ?? "No result summary provided") + reviewNotes;
9499
10064
  await client.execute({
9500
10065
  sql: `UPDATE tasks SET result = ?, status = 'needs_review', updated_at = ?
9501
10066
  WHERE id = ?`,
@@ -9517,7 +10082,7 @@ async function createReviewForCompletedTask(row, result, _baseDir, now) {
9517
10082
  taskFile
9518
10083
  });
9519
10084
  const originalPriority = String(row.priority).toLowerCase();
9520
- const autoApprove = originalPriority === "p2" && result?.toLowerCase().includes("tests pass");
10085
+ const autoApprove = originalPriority === "p2" && result2?.toLowerCase().includes("tests pass");
9521
10086
  if (!autoApprove) {
9522
10087
  try {
9523
10088
  const key = getSessionKey();
@@ -9546,11 +10111,11 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
9546
10111
  const now = (/* @__PURE__ */ new Date()).toISOString();
9547
10112
  const parentId = row.parent_task_id ? String(row.parent_task_id) : null;
9548
10113
  if (parentId) {
9549
- const result = await client.execute({
10114
+ const result2 = await client.execute({
9550
10115
  sql: "UPDATE tasks SET status = 'done', updated_at = ? WHERE id = ? AND status = 'needs_review'",
9551
10116
  args: [now, parentId]
9552
10117
  });
9553
- if (result.rowsAffected > 0) {
10118
+ if (result2.rowsAffected > 0) {
9554
10119
  process.stderr.write(
9555
10120
  `[review-cleanup] Cascaded original task to done via parent_task_id: ${parentId}
9556
10121
  `
@@ -9564,11 +10129,11 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
9564
10129
  const agent = parts[1];
9565
10130
  const slug = parts.slice(2).join("-");
9566
10131
  const legacyTaskFile = `exe/${agent}/${slug}.md`;
9567
- const result = await client.execute({
10132
+ const result2 = await client.execute({
9568
10133
  sql: "UPDATE tasks SET status = 'done', updated_at = ? WHERE (task_file = ? OR task_file LIKE ?) AND status = 'needs_review'",
9569
10134
  args: [now, legacyTaskFile, `tasks/%/${agent}/${slug}.md`]
9570
10135
  });
9571
- if (result.rowsAffected > 0) {
10136
+ if (result2.rowsAffected > 0) {
9572
10137
  process.stderr.write(
9573
10138
  `[review-cleanup] Cascaded original task to done: ${agent}/${slug}.md
9574
10139
  `
@@ -10018,8 +10583,8 @@ function notifyParentExe(sessionKey) {
10018
10583
  }
10019
10584
  process.stderr.write(`[intercom] notifyParentExe \u2192 ${target}
10020
10585
  `);
10021
- const result = sendIntercom(target);
10022
- if (result === "failed") {
10586
+ const result2 = sendIntercom(target);
10587
+ if (result2 === "failed") {
10023
10588
  const rootExe = resolveExeSession();
10024
10589
  if (rootExe && rootExe !== target) {
10025
10590
  process.stderr.write(`[intercom] notifyParentExe: dispatcher ${target} dead, falling back to root coordinator session ${rootExe}
@@ -10109,19 +10674,19 @@ function ensureEmployee(employeeName, exeSession, projectDir, opts) {
10109
10674
  }
10110
10675
  const sessionName = employeeSessionName(employeeName, exeSession, effectiveInstance);
10111
10676
  if (isEmployeeAlive(sessionName)) {
10112
- const result2 = sendIntercom(sessionName);
10113
- if (result2 === "acknowledged" || result2 === "skipped_exe" || result2 === "debounced" || result2 === "queued") {
10677
+ const result3 = sendIntercom(sessionName);
10678
+ if (result3 === "acknowledged" || result3 === "skipped_exe" || result3 === "debounced" || result3 === "queued") {
10114
10679
  return { status: "intercom_sent", sessionName };
10115
10680
  }
10116
- if (result2 === "delivered") {
10681
+ if (result3 === "delivered") {
10117
10682
  return { status: "intercom_unprocessed", sessionName };
10118
10683
  }
10119
10684
  return { status: "failed", sessionName, error: "intercom delivery failed" };
10120
10685
  }
10121
10686
  const spawnOpts = { ...opts, instance: effectiveInstance };
10122
- const result = spawnEmployee(employeeName, exeSession, projectDir, spawnOpts);
10123
- if (result.error) {
10124
- return { status: "failed", sessionName, error: result.error };
10687
+ const result2 = spawnEmployee(employeeName, exeSession, projectDir, spawnOpts);
10688
+ if (result2.error) {
10689
+ return { status: "failed", sessionName, error: result2.error };
10125
10690
  }
10126
10691
  return { status: "spawned", sessionName };
10127
10692
  }
@@ -10621,11 +11186,11 @@ async function writeCheckpoint(input) {
10621
11186
  blocked_by_ids: blockedByIds,
10622
11187
  last_checkpoint_at: now
10623
11188
  };
10624
- const result = await client.execute({
11189
+ const result2 = await client.execute({
10625
11190
  sql: `UPDATE tasks SET checkpoint = ?, checkpoint_count = checkpoint_count + 1, updated_at = ? WHERE id = ?`,
10626
11191
  args: [JSON.stringify(checkpoint), now, taskId]
10627
11192
  });
10628
- if (result.rowsAffected === 0) {
11193
+ if (result2.rowsAffected === 0) {
10629
11194
  throw new Error(`Checkpoint write failed: task ${taskId} not found`);
10630
11195
  }
10631
11196
  const countResult = await client.execute({
@@ -10676,22 +11241,22 @@ function checkLaneAffinity(title, context, assigneeName) {
10676
11241
  }
10677
11242
  async function resolveTask(client, identifier, scopeSession) {
10678
11243
  const scope = sessionScopeFilter(scopeSession);
10679
- let result = await client.execute({
11244
+ let result2 = await client.execute({
10680
11245
  sql: `SELECT * FROM tasks WHERE id = ?${scope.sql}`,
10681
11246
  args: [identifier, ...scope.args]
10682
11247
  });
10683
- if (result.rows.length === 1) return result.rows[0];
10684
- result = await client.execute({
11248
+ if (result2.rows.length === 1) return result2.rows[0];
11249
+ result2 = await client.execute({
10685
11250
  sql: `SELECT * FROM tasks WHERE task_file LIKE ?${scope.sql}`,
10686
11251
  args: [`%${identifier}%`, ...scope.args]
10687
11252
  });
10688
- if (result.rows.length === 1) return result.rows[0];
10689
- if (result.rows.length > 1) {
10690
- const exact = result.rows.filter(
11253
+ if (result2.rows.length === 1) return result2.rows[0];
11254
+ if (result2.rows.length > 1) {
11255
+ const exact = result2.rows.filter(
10691
11256
  (r) => String(r.task_file).endsWith(`/${identifier}.md`)
10692
11257
  );
10693
11258
  if (exact.length === 1) return exact[0];
10694
- const candidates = exact.length > 1 ? exact : result.rows;
11259
+ const candidates = exact.length > 1 ? exact : result2.rows;
10695
11260
  const active = candidates.filter(
10696
11261
  (r) => !["done", "cancelled"].includes(String(r.status))
10697
11262
  );
@@ -10701,17 +11266,17 @@ async function resolveTask(client, identifier, scopeSession) {
10701
11266
  `Multiple tasks match "${identifier}": ${matches}. Use a UUID to disambiguate.`
10702
11267
  );
10703
11268
  }
10704
- result = await client.execute({
11269
+ result2 = await client.execute({
10705
11270
  sql: `SELECT * FROM tasks WHERE title LIKE ?${scope.sql}`,
10706
11271
  args: [`%${identifier}%`, ...scope.args]
10707
11272
  });
10708
- if (result.rows.length === 1) return result.rows[0];
10709
- if (result.rows.length > 1) {
10710
- const active = result.rows.filter(
11273
+ if (result2.rows.length === 1) return result2.rows[0];
11274
+ if (result2.rows.length > 1) {
11275
+ const active = result2.rows.filter(
10711
11276
  (r) => !["done", "cancelled"].includes(String(r.status))
10712
11277
  );
10713
11278
  if (active.length === 1) return active[0];
10714
- const matches = (active.length > 1 ? active : result.rows).map((r) => `"${String(r.title)}" (${String(r.status)}, ${String(r.id)})`).join(", ");
11279
+ const matches = (active.length > 1 ? active : result2.rows).map((r) => `"${String(r.title)}" (${String(r.status)}, ${String(r.id)})`).join(", ");
10715
11280
  throw new Error(
10716
11281
  `Multiple tasks match "${identifier}": ${matches}. Use a UUID to disambiguate.`
10717
11282
  );
@@ -10921,11 +11486,11 @@ async function listTasks(input) {
10921
11486
  args.push(...scope.args);
10922
11487
  }
10923
11488
  const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
10924
- const result = await client.execute({
11489
+ const result2 = await client.execute({
10925
11490
  sql: `SELECT * FROM tasks ${where} ORDER BY CASE status WHEN 'blocked' THEN 0 WHEN 'in_progress' THEN 1 WHEN 'open' THEN 2 ELSE 3 END, priority ASC, created_at DESC LIMIT 1000`,
10926
11491
  args
10927
11492
  });
10928
- return result.rows.map((r) => ({
11493
+ return result2.rows.map((r) => ({
10929
11494
  id: String(r.id),
10930
11495
  title: String(r.title),
10931
11496
  assignedTo: String(r.assigned_to),
@@ -11317,30 +11882,30 @@ async function dispatchTaskToEmployee(input) {
11317
11882
  if (!exeSession) return { dispatched: "session_missing" };
11318
11883
  const sessionName = employeeSessionName(input.assignedTo, exeSession);
11319
11884
  if (transport.isAlive(sessionName)) {
11320
- const result = sendIntercom(sessionName);
11321
- const dispatched = result === "acknowledged" || result === "debounced" || result === "queued" ? "verified" : result === "delivered" ? "sent_unverified" : "session_dead";
11885
+ const result2 = sendIntercom(sessionName);
11886
+ const dispatched = result2 === "acknowledged" || result2 === "debounced" || result2 === "queued" ? "verified" : result2 === "delivered" ? "sent_unverified" : "session_dead";
11322
11887
  process.stderr.write(
11323
- `[dispatch-audit] intercom \u2192 ${sessionName} | task="${input.title}" [${input.priority}] | result=${dispatched} (sendIntercom=${result})
11888
+ `[dispatch-audit] intercom \u2192 ${sessionName} | task="${input.title}" [${input.priority}] | result=${dispatched} (sendIntercom=${result2})
11324
11889
  `
11325
11890
  );
11326
11891
  return { dispatched, session: sessionName, crossProject };
11327
11892
  } else {
11328
11893
  const projectDir = input.projectDir ?? process.cwd();
11329
- const result = ensureEmployee(input.assignedTo, exeSession, projectDir, {
11894
+ const result2 = ensureEmployee(input.assignedTo, exeSession, projectDir, {
11330
11895
  autoInstance: isMultiInstance(input.assignedTo)
11331
11896
  });
11332
- if (result.status === "failed") {
11897
+ if (result2.status === "failed") {
11333
11898
  process.stderr.write(
11334
- `[dispatch-audit] SPAWN FAILED \u2192 ${input.assignedTo} | task="${input.title}" [${input.priority}] | error=${result.error}
11899
+ `[dispatch-audit] SPAWN FAILED \u2192 ${input.assignedTo} | task="${input.title}" [${input.priority}] | error=${result2.error}
11335
11900
  `
11336
11901
  );
11337
11902
  return { dispatched: "session_missing" };
11338
11903
  }
11339
11904
  process.stderr.write(
11340
- `[dispatch-audit] SPAWNED \u2192 ${result.sessionName} | task="${input.title}" [${input.priority}]
11905
+ `[dispatch-audit] SPAWNED \u2192 ${result2.sessionName} | task="${input.title}" [${input.priority}]
11341
11906
  `
11342
11907
  );
11343
- return { dispatched: "spawned", session: result.sessionName, crossProject };
11908
+ return { dispatched: "spawned", session: result2.sessionName, crossProject };
11344
11909
  }
11345
11910
  } catch {
11346
11911
  return { dispatched: "session_missing" };
@@ -11398,13 +11963,13 @@ async function storeBehavior(opts) {
11398
11963
  }
11399
11964
  async function listBehaviorsByDomain(agentId, domain) {
11400
11965
  const client = getClient();
11401
- const result = await client.execute({
11966
+ const result2 = await client.execute({
11402
11967
  sql: `SELECT id, agent_id, project_name, domain, priority, content, active, created_at, updated_at, vector
11403
11968
  FROM behaviors
11404
11969
  WHERE agent_id = ? AND domain = ? AND active = 1`,
11405
11970
  args: [agentId, domain]
11406
11971
  });
11407
- return result.rows.map((r) => ({
11972
+ return result2.rows.map((r) => ({
11408
11973
  id: String(r.id),
11409
11974
  agent_id: String(r.agent_id),
11410
11975
  project_name: r.project_name ? String(r.project_name) : null,
@@ -11419,11 +11984,11 @@ async function listBehaviorsByDomain(agentId, domain) {
11419
11984
  }
11420
11985
  async function deactivateBehavior(id) {
11421
11986
  const client = getClient();
11422
- const result = await client.execute({
11987
+ const result2 = await client.execute({
11423
11988
  sql: `UPDATE behaviors SET active = 0, updated_at = ? WHERE id = ? AND active = 1`,
11424
11989
  args: [(/* @__PURE__ */ new Date()).toISOString(), id]
11425
11990
  });
11426
- return (result.rowsAffected ?? 0) > 0;
11991
+ return (result2.rowsAffected ?? 0) > 0;
11427
11992
  }
11428
11993
  var init_behaviors = __esm({
11429
11994
  "src/lib/behaviors.ts"() {
@@ -11448,15 +12013,15 @@ __export(skill_learning_exports, {
11448
12013
  import crypto9 from "crypto";
11449
12014
  async function extractTrajectory(taskId, agentId) {
11450
12015
  const client = getClient();
11451
- const result = await client.execute({
12016
+ const result2 = await client.execute({
11452
12017
  sql: `SELECT tool_name, raw_text
11453
12018
  FROM memories
11454
12019
  WHERE task_id = ? AND agent_id = ?
11455
12020
  ORDER BY timestamp ASC`,
11456
12021
  args: [taskId, agentId]
11457
12022
  });
11458
- if (result.rows.length === 0) return [];
11459
- const rawTools = result.rows.map((r) => {
12023
+ if (result2.rows.length === 0) return [];
12024
+ const rawTools = result2.rows.map((r) => {
11460
12025
  const toolName = String(r.tool_name);
11461
12026
  if (toolName === "Bash") {
11462
12027
  const text3 = String(r.raw_text);
@@ -11501,7 +12066,7 @@ async function storeTrajectory(opts) {
11501
12066
  async function findSimilarTrajectories(signature, threshold = DEFAULT_SKILL_THRESHOLD) {
11502
12067
  const client = getClient();
11503
12068
  const hash = hashSignature(signature);
11504
- const result = await client.execute({
12069
+ const result2 = await client.execute({
11505
12070
  sql: `SELECT id, task_id, agent_id, project_name, task_title, signature, signature_hash, tool_count, skill_id, created_at
11506
12071
  FROM trajectories
11507
12072
  WHERE signature_hash = ?
@@ -11521,7 +12086,7 @@ async function findSimilarTrajectories(signature, threshold = DEFAULT_SKILL_THRE
11521
12086
  skillId: r.skill_id ? String(r.skill_id) : null,
11522
12087
  createdAt: String(r.created_at)
11523
12088
  });
11524
- const matches = result.rows.map(mapRow);
12089
+ const matches = result2.rows.map(mapRow);
11525
12090
  if (matches.length >= threshold) return matches;
11526
12091
  const nearResult = await client.execute({
11527
12092
  sql: `SELECT id, task_id, agent_id, project_name, task_title, signature, signature_hash, tool_count, skill_id, created_at
@@ -11651,7 +12216,7 @@ async function sweepTrajectories(threshold, model) {
11651
12216
  if (!config2.skillLearning) return { clustersProcessed: 0, skillsExtracted: 0 };
11652
12217
  const t = threshold ?? config2.skillThreshold;
11653
12218
  const client = getClient();
11654
- const result = await client.execute({
12219
+ const result2 = await client.execute({
11655
12220
  sql: `SELECT signature_hash, COUNT(*) as cnt
11656
12221
  FROM trajectories
11657
12222
  WHERE skill_id IS NULL
@@ -11663,7 +12228,7 @@ async function sweepTrajectories(threshold, model) {
11663
12228
  });
11664
12229
  let clustersProcessed = 0;
11665
12230
  let skillsExtracted = 0;
11666
- for (const row of result.rows) {
12231
+ for (const row of result2.rows) {
11667
12232
  const hash = String(row.signature_hash);
11668
12233
  const trajResult = await client.execute({
11669
12234
  sql: `SELECT id, task_id, agent_id, project_name, task_title, signature, signature_hash, tool_count, created_at
@@ -11746,18 +12311,18 @@ __export(tasks_exports, {
11746
12311
  import path25 from "path";
11747
12312
  import { writeFileSync as writeFileSync11, mkdirSync as mkdirSync9, unlinkSync as unlinkSync7 } from "fs";
11748
12313
  async function createTask(input) {
11749
- const result = await createTaskCore(input);
11750
- if (!input.skipDispatch && result.status !== "blocked" && !process.env.VITEST) {
12314
+ const result2 = await createTaskCore(input);
12315
+ if (!input.skipDispatch && result2.status !== "blocked" && !process.env.VITEST) {
11751
12316
  dispatchTaskToEmployee({
11752
12317
  assignedTo: input.assignedTo,
11753
12318
  title: input.title,
11754
12319
  priority: input.priority,
11755
- taskFile: result.taskFile,
11756
- initialStatus: result.status,
12320
+ taskFile: result2.taskFile,
12321
+ initialStatus: result2.status,
11757
12322
  projectName: input.projectName
11758
12323
  });
11759
12324
  }
11760
- return result;
12325
+ return result2;
11761
12326
  }
11762
12327
  async function updateTask(input) {
11763
12328
  const { row, taskFile, now, taskId } = await updateTaskStatus(input);
@@ -11937,7 +12502,7 @@ __export(identity_exports, {
11937
12502
  import { existsSync as existsSync20, mkdirSync as mkdirSync10, readFileSync as readFileSync15, writeFileSync as writeFileSync12 } from "fs";
11938
12503
  import { readdirSync as readdirSync7 } from "fs";
11939
12504
  import path26 from "path";
11940
- import { createHash as createHash3 } from "crypto";
12505
+ import { createHash as createHash4 } from "crypto";
11941
12506
  function ensureDir2() {
11942
12507
  if (!existsSync20(IDENTITY_DIR2)) {
11943
12508
  mkdirSync10(IDENTITY_DIR2, { recursive: true });
@@ -11984,7 +12549,7 @@ function parseFrontmatter(raw) {
11984
12549
  };
11985
12550
  }
11986
12551
  function contentHash(content) {
11987
- return createHash3("sha256").update(content).digest("hex").slice(0, 16);
12552
+ return createHash4("sha256").update(content).digest("hex").slice(0, 16);
11988
12553
  }
11989
12554
  function getIdentity(agentId) {
11990
12555
  const filePath = identityPath(agentId);
@@ -12664,20 +13229,20 @@ async function sendMessage(input) {
12664
13229
  } catch {
12665
13230
  }
12666
13231
  const sentScope = strictSessionScopeFilter(sessionScope);
12667
- const result = await client.execute({
13232
+ const result2 = await client.execute({
12668
13233
  sql: `SELECT * FROM messages WHERE id = ?${sentScope.sql}`,
12669
13234
  args: [id, ...sentScope.args]
12670
13235
  });
12671
- return rowToMessage(result.rows[0]);
13236
+ return rowToMessage(result2.rows[0]);
12672
13237
  }
12673
13238
  async function deliverCrossMachineMessage(messageId, targetDevice) {
12674
13239
  const client = getClient();
12675
- const result = await client.execute({
13240
+ const result2 = await client.execute({
12676
13241
  sql: "SELECT * FROM messages WHERE id = ?",
12677
13242
  args: [messageId]
12678
13243
  });
12679
- if (result.rows.length === 0) return false;
12680
- const msg = rowToMessage(result.rows[0]);
13244
+ if (result2.rows.length === 0) return false;
13245
+ const msg = rowToMessage(result2.rows[0]);
12681
13246
  if (msg.status !== "pending") return false;
12682
13247
  if (!_wsClientSend) {
12683
13248
  return false;
@@ -12704,12 +13269,12 @@ async function deliverCrossMachineMessage(messageId, targetDevice) {
12704
13269
  }
12705
13270
  async function deliverLocalMessage(messageId) {
12706
13271
  const client = getClient();
12707
- const result = await client.execute({
13272
+ const result2 = await client.execute({
12708
13273
  sql: "SELECT * FROM messages WHERE id = ?",
12709
13274
  args: [messageId]
12710
13275
  });
12711
- if (result.rows.length === 0) return false;
12712
- const msg = rowToMessage(result.rows[0]);
13276
+ if (result2.rows.length === 0) return false;
13277
+ const msg = rowToMessage(result2.rows[0]);
12713
13278
  if (msg.status !== "pending") return false;
12714
13279
  const targetAgent = msg.targetAgent;
12715
13280
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -13036,7 +13601,7 @@ __export(db_backup_exports, {
13036
13601
  listBackups: () => listBackups,
13037
13602
  rotateBackups: () => rotateBackups
13038
13603
  });
13039
- import { copyFileSync, existsSync as existsSync27, mkdirSync as mkdirSync13, readdirSync as readdirSync10, unlinkSync as unlinkSync9, statSync as statSync4 } from "fs";
13604
+ import { copyFileSync, existsSync as existsSync27, mkdirSync as mkdirSync13, readdirSync as readdirSync10, unlinkSync as unlinkSync9, statSync as statSync5 } from "fs";
13040
13605
  import path32 from "path";
13041
13606
  function findActiveDb() {
13042
13607
  for (const name of DB_NAMES) {
@@ -13080,7 +13645,7 @@ function rotateBackups(keepDays = DEFAULT_KEEP_DAYS) {
13080
13645
  if (!file.endsWith(".db") && !file.endsWith(".db-wal") && !file.endsWith(".db-shm")) continue;
13081
13646
  const filePath = path32.join(BACKUP_DIR, file);
13082
13647
  try {
13083
- const stat = statSync4(filePath);
13648
+ const stat = statSync5(filePath);
13084
13649
  if (stat.mtimeMs < cutoff) {
13085
13650
  unlinkSync9(filePath);
13086
13651
  deleted++;
@@ -13098,7 +13663,7 @@ function listBackups() {
13098
13663
  const files = readdirSync10(BACKUP_DIR).filter((f) => f.endsWith(".db") && !f.endsWith("-wal") && !f.endsWith("-shm"));
13099
13664
  return files.map((name) => {
13100
13665
  const p = path32.join(BACKUP_DIR, name);
13101
- const stat = statSync4(p);
13666
+ const stat = statSync5(p);
13102
13667
  return { path: p, name, size: stat.size, date: stat.mtime };
13103
13668
  }).sort((a, b) => b.date.getTime() - a.date.getTime());
13104
13669
  } catch {
@@ -13317,10 +13882,10 @@ function isCrdtSyncEnabled() {
13317
13882
  async function rebuildFromDb() {
13318
13883
  const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
13319
13884
  const client = getClient2();
13320
- const result = await client.execute(
13885
+ const result2 = await client.execute(
13321
13886
  "SELECT id, agent_id, agent_role, session_id, timestamp, tool_name, project_name, has_error, raw_text, version, author_device_id, scope FROM memories"
13322
13887
  );
13323
- const memories = result.rows.map((row) => ({
13888
+ const memories = result2.rows.map((row) => ({
13324
13889
  id: String(row.id),
13325
13890
  agent_id: row.agent_id,
13326
13891
  agent_role: row.agent_role,
@@ -13361,8 +13926,8 @@ init_database();
13361
13926
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
13362
13927
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
13363
13928
  import { spawn as spawn4 } from "child_process";
13364
- import { existsSync as existsSync37, openSync as openSync3, mkdirSync as mkdirSync20, closeSync as closeSync3, readFileSync as readFileSync30 } from "fs";
13365
- import path48 from "path";
13929
+ import { existsSync as existsSync38, openSync as openSync3, mkdirSync as mkdirSync21, closeSync as closeSync3, readFileSync as readFileSync31 } from "fs";
13930
+ import path49 from "path";
13366
13931
  import os20 from "os";
13367
13932
  import { fileURLToPath as fileURLToPath5 } from "url";
13368
13933
 
@@ -13915,7 +14480,7 @@ async function searchConversations(query, limit) {
13915
14480
  try {
13916
14481
  const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
13917
14482
  const client = getClient2();
13918
- const result = await client.execute({
14483
+ const result2 = await client.execute({
13919
14484
  sql: `SELECT c.id, c.platform, c.sender_id, c.sender_name,
13920
14485
  c.content_text, c.agent_response, c.agent_name, c.timestamp
13921
14486
  FROM conversations c
@@ -13924,9 +14489,9 @@ async function searchConversations(query, limit) {
13924
14489
  LIMIT ?`,
13925
14490
  args: [query, limit]
13926
14491
  });
13927
- return result.rows.map((row, i) => ({
14492
+ return result2.rows.map((row, i) => ({
13928
14493
  source: "conversations",
13929
- score: 1 - i / Math.max(result.rows.length, 1),
14494
+ score: 1 - i / Math.max(result2.rows.length, 1),
13930
14495
  timestamp: row.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
13931
14496
  snippet: truncate(
13932
14497
  (row.content_text ?? "") + (row.agent_response ? ` \u2192 ${row.agent_response}` : ""),
@@ -14138,7 +14703,7 @@ function registerGetSessionContext(server2) {
14138
14703
  },
14139
14704
  async ({ session_id, target_timestamp, window_size, max_chars, body_chars }) => {
14140
14705
  const client = getClient();
14141
- const result = await client.execute({
14706
+ const result2 = await client.execute({
14142
14707
  sql: `SELECT id, agent_id, agent_role, session_id, timestamp,
14143
14708
  tool_name, project_name,
14144
14709
  has_error, raw_text, vector, task_id
@@ -14148,7 +14713,7 @@ function registerGetSessionContext(server2) {
14148
14713
  LIMIT 500`,
14149
14714
  args: [session_id]
14150
14715
  });
14151
- if (result.rows.length === 0) {
14716
+ if (result2.rows.length === 0) {
14152
14717
  return {
14153
14718
  content: [
14154
14719
  {
@@ -14158,7 +14723,7 @@ function registerGetSessionContext(server2) {
14158
14723
  ]
14159
14724
  };
14160
14725
  }
14161
- const sorted = result.rows.map((row) => ({
14726
+ const sorted = result2.rows.map((row) => ({
14162
14727
  id: row.id,
14163
14728
  agent_id: row.agent_id,
14164
14729
  agent_role: row.agent_role,
@@ -14225,7 +14790,7 @@ function registerGetMemoryById(server2) {
14225
14790
  const canReadOtherAgent = agentRole === "COO" || agentRole === "CTO";
14226
14791
  const ownerAgent = requestedAgent && canReadOtherAgent ? requestedAgent : agentId;
14227
14792
  const client = getClient();
14228
- const result = await client.execute({
14793
+ const result2 = await client.execute({
14229
14794
  sql: `SELECT id, agent_id, agent_role, session_id, timestamp,
14230
14795
  tool_name, project_name, has_error, raw_text, task_id,
14231
14796
  importance, status, memory_type, source_path, source_type
@@ -14234,14 +14799,14 @@ function registerGetMemoryById(server2) {
14234
14799
  LIMIT 1`,
14235
14800
  args: [id, ownerAgent]
14236
14801
  });
14237
- if (result.rows.length === 0) {
14802
+ if (result2.rows.length === 0) {
14238
14803
  const extra = requestedAgent && !canReadOtherAgent ? " Non-COO/CTO agents may only fetch their own memories." : "";
14239
14804
  return {
14240
14805
  content: [{ type: "text", text: `No memory found for id '${id}'.${extra}` }],
14241
14806
  isError: true
14242
14807
  };
14243
14808
  }
14244
- const row = result.rows[0];
14809
+ const row = result2.rows[0];
14245
14810
  const lines = [
14246
14811
  `id: ${asString(row.id)}`,
14247
14812
  `agent_id: ${asString(row.agent_id)}`,
@@ -14301,12 +14866,12 @@ function registerConsolidateMemories(server2) {
14301
14866
  embedFn = embed2;
14302
14867
  } catch {
14303
14868
  }
14304
- const result = await runConsolidation2(client, {
14869
+ const result2 = await runConsolidation2(client, {
14305
14870
  model: consolidationModel,
14306
14871
  maxCalls: max_clusters,
14307
14872
  embedFn
14308
14873
  });
14309
- if (result.clustersProcessed === 0) {
14874
+ if (result2.clustersProcessed === 0) {
14310
14875
  return {
14311
14876
  content: [{
14312
14877
  type: "text",
@@ -14318,8 +14883,8 @@ function registerConsolidateMemories(server2) {
14318
14883
  content: [{
14319
14884
  type: "text",
14320
14885
  text: `Consolidation complete:
14321
- - Clusters processed: ${result.clustersProcessed}
14322
- - Memories consolidated: ${result.memoriesConsolidated}
14886
+ - Clusters processed: ${result2.clustersProcessed}
14887
+ - Memories consolidated: ${result2.memoriesConsolidated}
14323
14888
 
14324
14889
  Consolidated summaries stored as tier-1 (importance=9) memories.`
14325
14890
  }]
@@ -14748,10 +15313,10 @@ function registerCreateTask(server2) {
14748
15313
  skipDispatch: true
14749
15314
  });
14750
15315
  try {
14751
- const { existsSync: existsSync38, mkdirSync: mkdirSync21, writeFileSync: writeFileSync22 } = await import("fs");
15316
+ const { existsSync: existsSync39, mkdirSync: mkdirSync22, writeFileSync: writeFileSync23 } = await import("fs");
14752
15317
  const { identityPath: identityPath2 } = await Promise.resolve().then(() => (init_identity(), identity_exports));
14753
15318
  const idPath = identityPath2(assigned_to);
14754
- if (!existsSync38(idPath)) {
15319
+ if (!existsSync39(idPath)) {
14755
15320
  const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
14756
15321
  const employees = await loadEmployees2();
14757
15322
  const emp = employees.find((e) => e.name === assigned_to);
@@ -14760,8 +15325,8 @@ function registerCreateTask(server2) {
14760
15325
  const template = getTemplateForTitle2(emp.role);
14761
15326
  if (template) {
14762
15327
  const dir = (await import("path")).dirname(idPath);
14763
- if (!existsSync38(dir)) mkdirSync21(dir, { recursive: true });
14764
- writeFileSync22(idPath, template.replace(/^agent_id: \w+/m, `agent_id: ${assigned_to}`), "utf-8");
15328
+ if (!existsSync39(dir)) mkdirSync22(dir, { recursive: true });
15329
+ writeFileSync23(idPath, template.replace(/^agent_id: \w+/m, `agent_id: ${assigned_to}`), "utf-8");
14765
15330
  }
14766
15331
  }
14767
15332
  }
@@ -14776,22 +15341,22 @@ function registerCreateTask(server2) {
14776
15341
  const useAutoInstance = isMultiInstance2(assigned_to);
14777
15342
  const { loadConfigSync: loadConfigSync2 } = await Promise.resolve().then(() => (init_config(), config_exports));
14778
15343
  const cfg = loadConfigSync2();
14779
- const result = ensureEmployee(assigned_to, exeSession, process.cwd(), {
15344
+ const result2 = ensureEmployee(assigned_to, exeSession, process.cwd(), {
14780
15345
  autoInstance: useAutoInstance,
14781
15346
  maxAutoInstances: useAutoInstance ? cfg.sessionLifecycle.maxAutoInstances : void 0
14782
15347
  });
14783
- switch (result.status) {
15348
+ switch (result2.status) {
14784
15349
  case "intercom_sent":
14785
15350
  dispatchStatus = `
14786
- Dispatched: intercom sent to ${result.sessionName}`;
15351
+ Dispatched: intercom sent to ${result2.sessionName}`;
14787
15352
  break;
14788
15353
  case "spawned":
14789
15354
  dispatchStatus = `
14790
- Dispatched: spawned ${result.sessionName}`;
15355
+ Dispatched: spawned ${result2.sessionName}`;
14791
15356
  break;
14792
15357
  case "failed":
14793
15358
  dispatchStatus = `
14794
- Dispatch failed: ${result.error ?? "unknown"}`;
15359
+ Dispatch failed: ${result2.error ?? "unknown"}`;
14795
15360
  break;
14796
15361
  }
14797
15362
  }
@@ -14909,7 +15474,7 @@ async function diagnoseMissingTask(client, identifier) {
14909
15474
  args.push(`%${identifier}%`);
14910
15475
  clauses.push("title LIKE ?");
14911
15476
  args.push(`%${identifier}%`);
14912
- const result = await client.execute({
15477
+ const result2 = await client.execute({
14913
15478
  sql: `SELECT id, title, status, assigned_to, project_name, session_scope, task_file
14914
15479
  FROM tasks
14915
15480
  WHERE ${clauses.map((c) => `(${c})`).join(" OR ")}
@@ -14917,10 +15482,10 @@ async function diagnoseMissingTask(client, identifier) {
14917
15482
  LIMIT 10`,
14918
15483
  args
14919
15484
  });
14920
- if (result.rows.length === 0) return null;
15485
+ if (result2.rows.length === 0) return null;
14921
15486
  const scoped = sessionScopeFilter();
14922
15487
  const scopeNote = scoped.args.length > 0 ? `Current session scope appears to be ${String(scoped.args[0])}. get_task is session-scoped by default.` : "No current session scope detected.";
14923
- const matches = result.rows.map((r) => {
15488
+ const matches = result2.rows.map((r) => {
14924
15489
  const id = String(r.id);
14925
15490
  return `- ${id.slice(0, 8)} ${String(r.title)} [${String(r.status)}] assigned_to=${String(r.assigned_to)} project=${String(r.project_name)} session_scope=${String(r.session_scope ?? "NULL")}`;
14926
15491
  }).join("\n");
@@ -15062,7 +15627,7 @@ function registerUpdateTask(server2) {
15062
15627
  result: z15.string().optional().describe("Result summary (include when status=done)")
15063
15628
  }
15064
15629
  },
15065
- async ({ task_id, status: rawStatus, result }) => {
15630
+ async ({ task_id, status: rawStatus, result: result2 }) => {
15066
15631
  let status = rawStatus;
15067
15632
  if (status === "done") {
15068
15633
  try {
@@ -15129,7 +15694,7 @@ function registerUpdateTask(server2) {
15129
15694
  task = await updateTask({
15130
15695
  taskId: task_id,
15131
15696
  status,
15132
- result,
15697
+ result: result2,
15133
15698
  baseDir: process.cwd(),
15134
15699
  callerAgentId
15135
15700
  });
@@ -15205,7 +15770,7 @@ function registerCloseTask(server2) {
15205
15770
  status: z16.enum(["closed", "done", "blocked", "cancelled"]).optional().default("closed").describe("Completion status (default: closed \u2014 terminal archive state)")
15206
15771
  }
15207
15772
  },
15208
- async ({ task_id, result, status }) => {
15773
+ async ({ task_id, result: result2, status }) => {
15209
15774
  const agent = getActiveAgent();
15210
15775
  const canClose = canCoordinate(agent.agentId, agent.agentRole) || CLOSE_TASK_ALLOWED_ROLES.has(agent.agentRole ?? "");
15211
15776
  if (agent.agentId && !canClose) {
@@ -15243,7 +15808,7 @@ function registerCloseTask(server2) {
15243
15808
  const task = await updateTask({
15244
15809
  taskId: task_id,
15245
15810
  status,
15246
- result,
15811
+ result: result2,
15247
15812
  baseDir,
15248
15813
  skipReviewCreation: true
15249
15814
  });
@@ -15613,7 +16178,7 @@ function registerAcknowledgeMessages(server2) {
15613
16178
  const agentId = agent.agentId || "default";
15614
16179
  const client = getClient();
15615
16180
  const scope = strictSessionScopeFilter();
15616
- const result = await client.execute({
16181
+ const result2 = await client.execute({
15617
16182
  sql: `UPDATE messages SET status = 'acknowledged', processed_at = datetime('now')
15618
16183
  WHERE target_agent = ? AND status IN ('pending', 'delivered')${scope.sql}`,
15619
16184
  args: [agentId, ...scope.args]
@@ -15622,7 +16187,7 @@ function registerAcknowledgeMessages(server2) {
15622
16187
  content: [
15623
16188
  {
15624
16189
  type: "text",
15625
- text: `Acknowledged ${result.rowsAffected} message(s) for ${agentId}.`
16190
+ text: `Acknowledged ${result2.rowsAffected} message(s) for ${agentId}.`
15626
16191
  }
15627
16192
  ]
15628
16193
  };
@@ -15689,8 +16254,8 @@ async function createReminder(text3, dueDate) {
15689
16254
  async function listReminders(includeCompleted = false) {
15690
16255
  const client = getClient();
15691
16256
  const sql = includeCompleted ? `SELECT id, text, created_at, due_date, completed_at FROM reminders ORDER BY due_date ASC NULLS LAST LIMIT 500` : `SELECT id, text, created_at, due_date, completed_at FROM reminders WHERE completed_at IS NULL ORDER BY due_date ASC NULLS LAST LIMIT 500`;
15692
- const result = await client.execute(sql);
15693
- return result.rows.map((row) => ({
16257
+ const result2 = await client.execute(sql);
16258
+ return result2.rows.map((row) => ({
15694
16259
  id: String(row.id),
15695
16260
  text: String(row.text),
15696
16261
  createdAt: String(row.created_at),
@@ -15701,18 +16266,18 @@ async function listReminders(includeCompleted = false) {
15701
16266
  async function completeReminder(idOrText) {
15702
16267
  const client = getClient();
15703
16268
  const now = (/* @__PURE__ */ new Date()).toISOString();
15704
- let result = await client.execute({
16269
+ let result2 = await client.execute({
15705
16270
  sql: `SELECT id, text FROM reminders WHERE id = ? AND completed_at IS NULL`,
15706
16271
  args: [idOrText]
15707
16272
  });
15708
- if (result.rows.length === 0) {
15709
- result = await client.execute({
16273
+ if (result2.rows.length === 0) {
16274
+ result2 = await client.execute({
15710
16275
  sql: `SELECT id, text FROM reminders WHERE completed_at IS NULL AND text LIKE '%' || ? || '%' LIMIT 1`,
15711
16276
  args: [idOrText]
15712
16277
  });
15713
16278
  }
15714
- if (result.rows.length === 0) return null;
15715
- const row = result.rows[0];
16279
+ if (result2.rows.length === 0) return null;
16280
+ const row = result2.rows[0];
15716
16281
  const id = String(row.id);
15717
16282
  await client.execute({
15718
16283
  sql: `UPDATE reminders SET completed_at = ? WHERE id = ?`,
@@ -15854,7 +16419,7 @@ function registerListBehaviors(server2) {
15854
16419
  args.push(proj);
15855
16420
  }
15856
16421
  const where = conditions.join(" AND ");
15857
- const result = await client.execute({
16422
+ const result2 = await client.execute({
15858
16423
  sql: `SELECT id, agent_id, project_name, domain, content, active, created_at, updated_at
15859
16424
  FROM behaviors
15860
16425
  WHERE ${where}
@@ -15862,7 +16427,7 @@ function registerListBehaviors(server2) {
15862
16427
  LIMIT 50`,
15863
16428
  args
15864
16429
  });
15865
- const behaviors = result.rows.map((r) => rowToBehavior(r));
16430
+ const behaviors = result2.rows.map((r) => rowToBehavior(r));
15866
16431
  if (behaviors.length === 0) {
15867
16432
  return {
15868
16433
  content: [{ type: "text", text: "No behaviors found." }]
@@ -16059,11 +16624,11 @@ function registerDeactivateBehavior(server2) {
16059
16624
  };
16060
16625
  }
16061
16626
  const client = getClient();
16062
- const result = await client.execute({
16627
+ const result2 = await client.execute({
16063
16628
  sql: `SELECT id, agent_id, content, domain, priority FROM behaviors WHERE id = ?`,
16064
16629
  args: [behavior_id]
16065
16630
  });
16066
- if (result.rows.length === 0) {
16631
+ if (result2.rows.length === 0) {
16067
16632
  return {
16068
16633
  content: [{
16069
16634
  type: "text",
@@ -16072,7 +16637,7 @@ function registerDeactivateBehavior(server2) {
16072
16637
  isError: true
16073
16638
  };
16074
16639
  }
16075
- const row = result.rows[0];
16640
+ const row = result2.rows[0];
16076
16641
  const wasActive = await deactivateBehavior(behavior_id);
16077
16642
  if (!wasActive) {
16078
16643
  return {
@@ -16186,7 +16751,7 @@ async function embedTexts(texts) {
16186
16751
  );
16187
16752
  results.push(
16188
16753
  ...settled.map(
16189
- (result) => result.status === "fulfilled" ? result.value : null
16754
+ (result2) => result2.status === "fulfilled" ? result2.value : null
16190
16755
  )
16191
16756
  );
16192
16757
  }
@@ -16304,7 +16869,7 @@ var MIN_IMPORTANCE = 1;
16304
16869
  var MAX_IMPORTANCE = 10;
16305
16870
  async function listDocumentsByWorkspace(workspace_id, limit = DEFAULT_LIST_LIMIT, offset = 0) {
16306
16871
  const client = getClient();
16307
- const result = await client.execute({
16872
+ const result2 = await client.execute({
16308
16873
  sql: `SELECT d.*, COUNT(m.id) AS chunk_count
16309
16874
  FROM documents d
16310
16875
  LEFT JOIN memories m ON m.document_id = d.id
@@ -16314,7 +16879,7 @@ async function listDocumentsByWorkspace(workspace_id, limit = DEFAULT_LIST_LIMIT
16314
16879
  LIMIT ? OFFSET ?`,
16315
16880
  args: [workspace_id, limit, offset]
16316
16881
  });
16317
- return result.rows.map((row) => {
16882
+ return result2.rows.map((row) => {
16318
16883
  const r = row;
16319
16884
  return {
16320
16885
  ...rowToDocument(r),
@@ -16346,11 +16911,11 @@ async function updateChunksImportance(document_id, importance) {
16346
16911
  );
16347
16912
  }
16348
16913
  const client = getClient();
16349
- const result = await client.execute({
16914
+ const result2 = await client.execute({
16350
16915
  sql: "UPDATE memories SET importance = ? WHERE document_id = ?",
16351
16916
  args: [importance, document_id]
16352
16917
  });
16353
- return Number(result.rowsAffected) || 0;
16918
+ return Number(result2.rowsAffected) || 0;
16354
16919
  }
16355
16920
 
16356
16921
  // src/mcp/tools/ingest-document.ts
@@ -16381,11 +16946,11 @@ function registerIngestDocument(server2) {
16381
16946
  const { assertMemoryLimit: assertMemoryLimit2 } = await Promise.resolve().then(() => (init_plan_limits(), plan_limits_exports));
16382
16947
  await assertFeature2("wiki");
16383
16948
  await assertMemoryLimit2();
16384
- const result = await ingestDocument(input);
16949
+ const result2 = await ingestDocument(input);
16385
16950
  return {
16386
16951
  content: [{
16387
16952
  type: "text",
16388
- text: JSON.stringify(result)
16953
+ text: JSON.stringify(result2)
16389
16954
  }]
16390
16955
  };
16391
16956
  } catch (err) {
@@ -17046,7 +17611,7 @@ function registerQueryConversations(server2) {
17046
17611
  const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
17047
17612
  const limit = params.limit ?? 25;
17048
17613
  args.push(limit);
17049
- const result = await client.execute({
17614
+ const result2 = await client.execute({
17050
17615
  sql: `SELECT c.id, c.platform, c.sender_id, c.sender_name, c.sender_phone,
17051
17616
  c.sender_email, c.channel_id, c.thread_id, c.content_text,
17052
17617
  c.agent_response, c.agent_name, c.timestamp
@@ -17056,7 +17621,7 @@ function registerQueryConversations(server2) {
17056
17621
  LIMIT ?`,
17057
17622
  args
17058
17623
  });
17059
- const conversations = result.rows.map((row) => ({
17624
+ const conversations = result2.rows.map((row) => ({
17060
17625
  id: row.id,
17061
17626
  platform: row.platform,
17062
17627
  sender: {
@@ -17668,8 +18233,8 @@ async function generateGraphReport(client, projectName) {
17668
18233
  }).slice(0, 10);
17669
18234
  let hyperedgeCount = 0;
17670
18235
  try {
17671
- const result = await client.execute("SELECT COUNT(*) as cnt FROM hyperedges");
17672
- hyperedgeCount = Number(result.rows[0]?.cnt ?? 0);
18236
+ const result2 = await client.execute("SELECT COUNT(*) as cnt FROM hyperedges");
18237
+ hyperedgeCount = Number(result2.rows[0]?.cnt ?? 0);
17673
18238
  } catch {
17674
18239
  }
17675
18240
  const nodeLabels = new Map(nodes.map((n) => [n.id, n.label]));
@@ -17723,12 +18288,12 @@ function registerExportGraph(server2) {
17723
18288
  }
17724
18289
  const html = await exportGraphHTML(client);
17725
18290
  const fs = await import("fs");
17726
- const path49 = await import("path");
18291
+ const path50 = await import("path");
17727
18292
  const os21 = await import("os");
17728
- const outDir = path49.join(os21.homedir(), ".exe-os", "exports");
18293
+ const outDir = path50.join(os21.homedir(), ".exe-os", "exports");
17729
18294
  fs.mkdirSync(outDir, { recursive: true });
17730
18295
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
17731
- const filePath = path49.join(outDir, `graph-${timestamp}.html`);
18296
+ const filePath = path50.join(outDir, `graph-${timestamp}.html`);
17732
18297
  fs.writeFileSync(filePath, html, "utf-8");
17733
18298
  return {
17734
18299
  content: [
@@ -17766,6 +18331,198 @@ import crypto13 from "crypto";
17766
18331
 
17767
18332
  // src/lib/code-chunker.ts
17768
18333
  import ts from "typescript";
18334
+ function chunkSourceFile(source, fileName = "file.ts") {
18335
+ const sourceFile = ts.createSourceFile(
18336
+ fileName,
18337
+ source,
18338
+ ts.ScriptTarget.Latest,
18339
+ true,
18340
+ // setParentNodes
18341
+ fileName.endsWith(".tsx") || fileName.endsWith(".jsx") ? ts.ScriptKind.TSX : ts.ScriptKind.TS
18342
+ );
18343
+ const chunks = [];
18344
+ const lines = source.split("\n");
18345
+ const importLines = [];
18346
+ function getLineNumber(pos) {
18347
+ return sourceFile.getLineAndCharacterOfPosition(pos).line + 1;
18348
+ }
18349
+ function getLeadingComment(node) {
18350
+ const fullText = sourceFile.getFullText();
18351
+ const ranges = ts.getLeadingCommentRanges(fullText, node.getFullStart());
18352
+ if (!ranges || ranges.length === 0) return void 0;
18353
+ return ranges.map((r) => fullText.slice(r.pos, r.end)).join("\n");
18354
+ }
18355
+ function getNodeText(node) {
18356
+ return node.getText(sourceFile);
18357
+ }
18358
+ function getName(node) {
18359
+ if (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node)) {
18360
+ return node.name?.getText(sourceFile) ?? "(anonymous)";
18361
+ }
18362
+ if (ts.isClassDeclaration(node)) {
18363
+ return node.name?.getText(sourceFile) ?? "(anonymous class)";
18364
+ }
18365
+ if (ts.isInterfaceDeclaration(node)) {
18366
+ return node.name.getText(sourceFile);
18367
+ }
18368
+ if (ts.isTypeAliasDeclaration(node)) {
18369
+ return node.name.getText(sourceFile);
18370
+ }
18371
+ if (ts.isEnumDeclaration(node)) {
18372
+ return node.name.getText(sourceFile);
18373
+ }
18374
+ if (ts.isVariableStatement(node)) {
18375
+ const decls = node.declarationList.declarations;
18376
+ return decls.map((d) => d.name.getText(sourceFile)).join(", ");
18377
+ }
18378
+ if (ts.isExportAssignment(node)) {
18379
+ return "default export";
18380
+ }
18381
+ return "(unknown)";
18382
+ }
18383
+ function visitTopLevel(node) {
18384
+ if (ts.isImportDeclaration(node)) {
18385
+ importLines.push({
18386
+ start: getLineNumber(node.getStart(sourceFile)),
18387
+ end: getLineNumber(node.getEnd())
18388
+ });
18389
+ return;
18390
+ }
18391
+ if (ts.isFunctionDeclaration(node)) {
18392
+ chunks.push({
18393
+ kind: "function",
18394
+ name: getName(node),
18395
+ text: getNodeText(node),
18396
+ startLine: getLineNumber(node.getStart(sourceFile)),
18397
+ endLine: getLineNumber(node.getEnd()),
18398
+ comment: getLeadingComment(node)
18399
+ });
18400
+ return;
18401
+ }
18402
+ if (ts.isClassDeclaration(node)) {
18403
+ chunks.push({
18404
+ kind: "class",
18405
+ name: getName(node),
18406
+ text: getNodeText(node),
18407
+ startLine: getLineNumber(node.getStart(sourceFile)),
18408
+ endLine: getLineNumber(node.getEnd()),
18409
+ comment: getLeadingComment(node)
18410
+ });
18411
+ return;
18412
+ }
18413
+ if (ts.isInterfaceDeclaration(node)) {
18414
+ chunks.push({
18415
+ kind: "type",
18416
+ name: getName(node),
18417
+ text: getNodeText(node),
18418
+ startLine: getLineNumber(node.getStart(sourceFile)),
18419
+ endLine: getLineNumber(node.getEnd()),
18420
+ comment: getLeadingComment(node)
18421
+ });
18422
+ return;
18423
+ }
18424
+ if (ts.isTypeAliasDeclaration(node)) {
18425
+ chunks.push({
18426
+ kind: "type",
18427
+ name: getName(node),
18428
+ text: getNodeText(node),
18429
+ startLine: getLineNumber(node.getStart(sourceFile)),
18430
+ endLine: getLineNumber(node.getEnd()),
18431
+ comment: getLeadingComment(node)
18432
+ });
18433
+ return;
18434
+ }
18435
+ if (ts.isEnumDeclaration(node)) {
18436
+ chunks.push({
18437
+ kind: "type",
18438
+ name: getName(node),
18439
+ text: getNodeText(node),
18440
+ startLine: getLineNumber(node.getStart(sourceFile)),
18441
+ endLine: getLineNumber(node.getEnd()),
18442
+ comment: getLeadingComment(node)
18443
+ });
18444
+ return;
18445
+ }
18446
+ if (ts.isVariableStatement(node)) {
18447
+ const decls = node.declarationList.declarations;
18448
+ const isFnLike = decls.some(
18449
+ (d) => d.initializer && (ts.isArrowFunction(d.initializer) || ts.isFunctionExpression(d.initializer))
18450
+ );
18451
+ chunks.push({
18452
+ kind: isFnLike ? "function" : "variable",
18453
+ name: getName(node),
18454
+ text: getNodeText(node),
18455
+ startLine: getLineNumber(node.getStart(sourceFile)),
18456
+ endLine: getLineNumber(node.getEnd()),
18457
+ comment: getLeadingComment(node)
18458
+ });
18459
+ return;
18460
+ }
18461
+ if (ts.isExportAssignment(node)) {
18462
+ chunks.push({
18463
+ kind: "export",
18464
+ name: "default export",
18465
+ text: getNodeText(node),
18466
+ startLine: getLineNumber(node.getStart(sourceFile)),
18467
+ endLine: getLineNumber(node.getEnd()),
18468
+ comment: getLeadingComment(node)
18469
+ });
18470
+ return;
18471
+ }
18472
+ if (ts.isExpressionStatement(node)) {
18473
+ const text3 = getNodeText(node);
18474
+ if (text3.length > 10) {
18475
+ chunks.push({
18476
+ kind: "other",
18477
+ name: text3.slice(0, 40).replace(/\n/g, " "),
18478
+ text: text3,
18479
+ startLine: getLineNumber(node.getStart(sourceFile)),
18480
+ endLine: getLineNumber(node.getEnd())
18481
+ });
18482
+ }
18483
+ return;
18484
+ }
18485
+ }
18486
+ sourceFile.statements.forEach(visitTopLevel);
18487
+ if (importLines.length > 0) {
18488
+ const startLine = importLines[0].start;
18489
+ const endLine = importLines[importLines.length - 1].end;
18490
+ const importText = lines.slice(startLine - 1, endLine).join("\n");
18491
+ chunks.unshift({
18492
+ kind: "import",
18493
+ name: `${importLines.length} imports`,
18494
+ text: importText,
18495
+ startLine,
18496
+ endLine
18497
+ });
18498
+ }
18499
+ chunks.sort((a, b) => a.startLine - b.startLine);
18500
+ return chunks;
18501
+ }
18502
+ function summarizeChunk(chunk, filePath) {
18503
+ const location = `${filePath}:${chunk.startLine}-${chunk.endLine}`;
18504
+ const comment = chunk.comment ? chunk.comment.replace(/\/\*\*|\*\/|\*\s?/g, "").trim().split("\n")[0] : "";
18505
+ switch (chunk.kind) {
18506
+ case "function":
18507
+ return `Function ${chunk.name} in ${location}${comment ? ` \u2014 ${comment}` : ""}`;
18508
+ case "class":
18509
+ return `Class ${chunk.name} in ${location}${comment ? ` \u2014 ${comment}` : ""}`;
18510
+ case "type":
18511
+ return `Type ${chunk.name} in ${location}`;
18512
+ case "import":
18513
+ return `Imports (${chunk.name}) in ${filePath}`;
18514
+ case "variable":
18515
+ return `Variable ${chunk.name} in ${location}`;
18516
+ case "export":
18517
+ return `Default export in ${location}`;
18518
+ default:
18519
+ return `${chunk.kind} in ${location}`;
18520
+ }
18521
+ }
18522
+ function isChunkable(filePath) {
18523
+ const ext = filePath.split(".").pop()?.toLowerCase();
18524
+ return ext === "ts" || ext === "tsx" || ext === "js" || ext === "jsx";
18525
+ }
17769
18526
 
17770
18527
  // src/lib/graph-rag.ts
17771
18528
  function normalizeEntityName(name) {
@@ -17869,14 +18626,14 @@ function registerMergeEntities(server2) {
17869
18626
  };
17870
18627
  }
17871
18628
  try {
17872
- const result = await mergeEntities(client, sourceId, targetId);
18629
+ const result2 = await mergeEntities(client, sourceId, targetId);
17873
18630
  return {
17874
18631
  content: [
17875
18632
  {
17876
18633
  type: "text",
17877
18634
  text: `Merged "${source_name}" \u2192 "${target_name}":
17878
- - ${result.relationshipsMoved} relationships moved
17879
- - ${result.memoriesMoved} memory links moved
18635
+ - ${result2.relationshipsMoved} relationships moved
18636
+ - ${result2.memoriesMoved} memory links moved
17880
18637
  - "${source_name}" registered as alias for "${target_name}"`
17881
18638
  }
17882
18639
  ]
@@ -18159,10 +18916,10 @@ function registerSetAgentConfig(server2) {
18159
18916
  isError: true
18160
18917
  };
18161
18918
  }
18162
- const result = setAgentRuntime(agent_id, runtime, model, reasoning_effort);
18163
- if (!result.ok) {
18919
+ const result2 = setAgentRuntime(agent_id, runtime, model, reasoning_effort);
18920
+ if (!result2.ok) {
18164
18921
  return {
18165
- content: [{ type: "text", text: result.error }],
18922
+ content: [{ type: "text", text: result2.error }],
18166
18923
  isError: true
18167
18924
  };
18168
18925
  }
@@ -18339,7 +19096,7 @@ async function getAgentSpend(period = "7d") {
18339
19096
  }
18340
19097
  }
18341
19098
  }
18342
- const result = Array.from(agentTotals.entries()).map(([agentId, t]) => ({
19099
+ const result2 = Array.from(agentTotals.entries()).map(([agentId, t]) => ({
18343
19100
  agentId,
18344
19101
  inputTokens: t.input,
18345
19102
  outputTokens: t.output,
@@ -18349,8 +19106,8 @@ async function getAgentSpend(period = "7d") {
18349
19106
  sessions: t.sessions.size,
18350
19107
  period
18351
19108
  })).sort((a, b) => b.costUSD - a.costUSD);
18352
- _spendCache.set(period, { result, expires: Date.now() + CACHE_TTL_MS });
18353
- return result;
19109
+ _spendCache.set(period, { result: result2, expires: Date.now() + CACHE_TTL_MS });
19110
+ return result2;
18354
19111
  }
18355
19112
  async function extractSessionUsage(jsonlPath) {
18356
19113
  let input = 0;
@@ -18914,14 +19671,14 @@ async function fetchMemoriesWithVectors(client, projectFilter, agentFilter2) {
18914
19671
  args.push(agentFilter2);
18915
19672
  }
18916
19673
  const where = " WHERE " + clauses.join(" AND ");
18917
- const result = await client.execute({
19674
+ const result2 = await client.execute({
18918
19675
  sql: `SELECT id, agent_id, raw_text, timestamp, project_name, vector
18919
19676
  FROM memories${where}
18920
19677
  ORDER BY project_name, timestamp DESC`,
18921
19678
  args
18922
19679
  });
18923
19680
  const byProject = /* @__PURE__ */ new Map();
18924
- for (const row of result.rows) {
19681
+ for (const row of result2.rows) {
18925
19682
  const project = row.project_name;
18926
19683
  const vec = row.vector == null ? null : Array.isArray(row.vector) ? row.vector : Array.from(row.vector);
18927
19684
  if (!vec || vec.length === 0) continue;
@@ -19338,11 +20095,11 @@ async function auditStats(client, flags) {
19338
20095
  async function auditNullVectors(client, flags) {
19339
20096
  const { clause, args } = agentFilter(flags);
19340
20097
  const where = clause ? clause + " AND vector IS NULL" : " WHERE vector IS NULL";
19341
- const result = await client.execute({
20098
+ const result2 = await client.execute({
19342
20099
  sql: `SELECT COUNT(*) as cnt FROM memories${where}`,
19343
20100
  args
19344
20101
  });
19345
- return Number(result.rows[0].cnt);
20102
+ return Number(result2.rows[0].cnt);
19346
20103
  }
19347
20104
  async function auditDuplicates(client, flags) {
19348
20105
  const { clause, args } = agentFilter(flags);
@@ -19391,14 +20148,14 @@ async function auditDuplicates(client, flags) {
19391
20148
  async function auditBloated(client, flags) {
19392
20149
  const { clause, args } = agentFilter(flags);
19393
20150
  const where = clause ? clause + " AND LENGTH(raw_text) > 5120 AND tool_name != 'ConversationBackfill'" : " WHERE LENGTH(raw_text) > 5120 AND tool_name != 'ConversationBackfill'";
19394
- const result = await client.execute({
20151
+ const result2 = await client.execute({
19395
20152
  sql: `SELECT id, agent_id, LENGTH(raw_text) as size, tool_name
19396
20153
  FROM memories${where}
19397
20154
  ORDER BY size DESC
19398
20155
  LIMIT 100`,
19399
20156
  args
19400
20157
  });
19401
- return result.rows.map((r) => ({
20158
+ return result2.rows.map((r) => ({
19402
20159
  id: r.id,
19403
20160
  agent_id: r.agent_id,
19404
20161
  size: Number(r.size),
@@ -19413,7 +20170,7 @@ async function auditFts(client) {
19413
20170
  return { memoryCount: mc, ftsCount: fc, inSync: mc === fc };
19414
20171
  }
19415
20172
  async function auditOrphanedProjects(client) {
19416
- const result = await client.execute(
20173
+ const result2 = await client.execute(
19417
20174
  `SELECT project_name, COUNT(*) as cnt
19418
20175
  FROM memories
19419
20176
  WHERE tool_name != 'ConversationBackfill'
@@ -19422,7 +20179,7 @@ async function auditOrphanedProjects(client) {
19422
20179
  );
19423
20180
  const orphans = [];
19424
20181
  const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
19425
- for (const row of result.rows) {
20182
+ for (const row of result2.rows) {
19426
20183
  const name = row.project_name;
19427
20184
  const count = Number(row.cnt);
19428
20185
  const exists = existsSync28(path33.join(home, name)) || existsSync28(path33.join(home, "..", name)) || existsSync28(path33.join(process.cwd(), "..", name));
@@ -19701,7 +20458,7 @@ function formatReport(report, flags) {
19701
20458
  if (!kh.masterKeyPresent) {
19702
20459
  lines.push("\u{1F534} Recovery key: master key missing \u2014 import phrase or run setup before syncing");
19703
20460
  } else if (!kh.recoveryBackupMarked) {
19704
- lines.push("\u{1F534} Recovery backup: not confirmed \u2014 run `exe-os link export --local-terminal-only` and save the 24-word phrase");
20461
+ lines.push("\u{1F534} Recovery backup: not confirmed \u2014 run `exe-os cloud link --show-full` in your local Terminal and save the 24-word phrase");
19705
20462
  } else {
19706
20463
  const suffix = kh.recoveryBackupConfirmedAt ? ` (${kh.recoveryBackupConfirmedAt.slice(0, 10)}${kh.recoveryBackupSource ? ` via ${kh.recoveryBackupSource}` : ""})` : "";
19707
20464
  lines.push(`\u{1F7E2} Recovery backup: confirmed${suffix}`);
@@ -19873,12 +20630,12 @@ async function fixBloated(client, bloated, dryRun) {
19873
20630
  let chunksCreated = 0;
19874
20631
  const CHUNK_SIZE = 2048;
19875
20632
  for (const b of bloated) {
19876
- const result = await client.execute({
20633
+ const result2 = await client.execute({
19877
20634
  sql: `SELECT * FROM memories WHERE id = ?`,
19878
20635
  args: [b.id]
19879
20636
  });
19880
- if (result.rows.length === 0) continue;
19881
- const row = result.rows[0];
20637
+ if (result2.rows.length === 0) continue;
20638
+ const row = result2.rows[0];
19882
20639
  const text3 = row.raw_text;
19883
20640
  const chunks = splitAtSentences(text3, CHUNK_SIZE);
19884
20641
  if (chunks.length <= 1) continue;
@@ -20112,15 +20869,15 @@ function registerRunConsolidation(server2) {
20112
20869
  };
20113
20870
  }
20114
20871
  const config2 = await loadConfig();
20115
- const result = await runConsolidation(client, {
20872
+ const result2 = await runConsolidation(client, {
20116
20873
  model: config2.consolidationModel || "claude-haiku-4-5-20251001",
20117
20874
  maxCalls: 10
20118
20875
  });
20119
20876
  const lines = [];
20120
20877
  lines.push("## Consolidation Complete\n");
20121
- lines.push(`- **Clusters processed:** ${result.clustersProcessed}`);
20122
- lines.push(`- **Memories consolidated:** ${result.memoriesConsolidated}`);
20123
- lines.push(`- **Remaining unconsolidated:** ${(pending - result.memoriesConsolidated).toLocaleString()}`);
20878
+ lines.push(`- **Clusters processed:** ${result2.clustersProcessed}`);
20879
+ lines.push(`- **Memories consolidated:** ${result2.memoriesConsolidated}`);
20880
+ lines.push(`- **Remaining unconsolidated:** ${(pending - result2.memoriesConsolidated).toLocaleString()}`);
20124
20881
  return {
20125
20882
  content: [{ type: "text", text: lines.join("\n") }]
20126
20883
  };
@@ -20143,7 +20900,7 @@ import { z as z58 } from "zod";
20143
20900
 
20144
20901
  // src/lib/cloud-sync.ts
20145
20902
  init_database();
20146
- import { readFileSync as readFileSync23, writeFileSync as writeFileSync17, existsSync as existsSync30, readdirSync as readdirSync11, mkdirSync as mkdirSync15, appendFileSync as appendFileSync2, unlinkSync as unlinkSync11, openSync as openSync2, closeSync as closeSync2, statSync as statSync5 } from "fs";
20903
+ import { readFileSync as readFileSync23, writeFileSync as writeFileSync17, existsSync as existsSync30, readdirSync as readdirSync11, mkdirSync as mkdirSync15, appendFileSync as appendFileSync2, unlinkSync as unlinkSync11, openSync as openSync2, closeSync as closeSync2, statSync as statSync6 } from "fs";
20147
20904
  import crypto15 from "crypto";
20148
20905
  import path35 from "path";
20149
20906
  import { homedir as homedir6 } from "os";
@@ -20265,18 +21022,36 @@ function loadPgClient() {
20265
21022
  const { pathToFileURL: pathToFileURL6 } = await import("url");
20266
21023
  const explicitPath = process.env.EXE_OS_PRISMA_CLIENT_PATH;
20267
21024
  if (explicitPath) {
20268
- const mod2 = await import(pathToFileURL6(explicitPath).href);
20269
- const Ctor2 = mod2.PrismaClient ?? mod2.default?.PrismaClient;
20270
- if (!Ctor2) throw new Error(`No PrismaClient at ${explicitPath}`);
20271
- return new Ctor2();
21025
+ const mod = await import(pathToFileURL6(explicitPath).href);
21026
+ const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
21027
+ if (!Ctor) throw new Error(`No PrismaClient at ${explicitPath}`);
21028
+ return new Ctor();
20272
21029
  }
20273
21030
  const exeDbRoot = process.env.EXE_DB_ROOT ?? path35.join(homedir6(), "exe-db");
20274
- const req = createRequire6(path35.join(exeDbRoot, "package.json"));
20275
- const entry = req.resolve("@prisma/client");
20276
- const mod = await import(pathToFileURL6(entry).href);
20277
- const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
20278
- if (!Ctor) throw new Error("No PrismaClient");
20279
- return new Ctor();
21031
+ const packagePath = path35.join(exeDbRoot, "package.json");
21032
+ if (existsSync30(packagePath)) {
21033
+ const req = createRequire6(packagePath);
21034
+ const entry = req.resolve("@prisma/client");
21035
+ const mod = await import(pathToFileURL6(entry).href);
21036
+ const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
21037
+ if (!Ctor) throw new Error("No PrismaClient");
21038
+ return new Ctor();
21039
+ }
21040
+ const { Pool } = await import("pg");
21041
+ const pool = new Pool({ connectionString: process.env.DATABASE_URL });
21042
+ return {
21043
+ async $queryRawUnsafe(query, ...values) {
21044
+ const result2 = await pool.query(query, values);
21045
+ return result2.rows;
21046
+ },
21047
+ async $executeRawUnsafe(query, ...values) {
21048
+ const result2 = await pool.query(query, values);
21049
+ return result2.rowCount ?? 0;
21050
+ },
21051
+ async $disconnect() {
21052
+ await pool.end();
21053
+ }
21054
+ };
20280
21055
  })().catch(() => {
20281
21056
  _pgFailed = true;
20282
21057
  _pgPromise = null;
@@ -20297,7 +21072,7 @@ async function pushToPostgres(records) {
20297
21072
  let inserted = 0;
20298
21073
  for (const rec of records) {
20299
21074
  try {
20300
- await prisma.$executeRawUnsafe(
21075
+ const changed = await prisma.$executeRawUnsafe(
20301
21076
  `INSERT INTO raw.raw_events (id, source, source_id, event_type, payload, metadata, timestamp)
20302
21077
  VALUES (gen_random_uuid(), 'cloud_sync', $1, 'memory', $2::jsonb, $3::jsonb, $4)
20303
21078
  ON CONFLICT (source, source_id, event_type) DO NOTHING`,
@@ -20306,7 +21081,7 @@ async function pushToPostgres(records) {
20306
21081
  JSON.stringify({ agent_id: rec.agent_id, project_name: rec.project_name, tool_name: rec.tool_name }),
20307
21082
  rec.timestamp ? new Date(String(rec.timestamp)) : /* @__PURE__ */ new Date()
20308
21083
  );
20309
- inserted++;
21084
+ inserted += Number(changed ?? 0);
20310
21085
  } catch {
20311
21086
  }
20312
21087
  }
@@ -20430,32 +21205,62 @@ async function cloudPull(sinceVersion, config2) {
20430
21205
  if (!response.ok) return { records: [], maxVersion: sinceVersion };
20431
21206
  const data = await response.json();
20432
21207
  const allRecords = [];
20433
- for (const { blob } of data.blobs ?? []) {
21208
+ let maxReadableVersion = sinceVersion;
21209
+ let skippedBlobs = 0;
21210
+ for (const { version, blob } of data.blobs ?? []) {
20434
21211
  try {
20435
21212
  const compressed = decryptSyncBlob(blob);
20436
21213
  const json = decompress(compressed).toString("utf8");
20437
21214
  const records = JSON.parse(json);
20438
21215
  allRecords.push(...records);
21216
+ const recordMax = records.reduce((max, rec) => {
21217
+ const v = Number(rec.version ?? 0);
21218
+ return Number.isFinite(v) ? Math.max(max, v) : max;
21219
+ }, 0);
21220
+ const blobVersion = Number(version ?? 0);
21221
+ maxReadableVersion = Math.max(
21222
+ maxReadableVersion,
21223
+ Number.isFinite(blobVersion) ? blobVersion : 0,
21224
+ recordMax
21225
+ );
20439
21226
  } catch {
21227
+ skippedBlobs++;
20440
21228
  continue;
20441
21229
  }
20442
21230
  }
20443
- return { records: allRecords, maxVersion: data.max_version ?? sinceVersion };
21231
+ if (skippedBlobs > 0) {
21232
+ logError(`[cloud-sync] PULL skipped ${skippedBlobs} undecryptable blob(s); pull cursor advanced only to last readable version ${maxReadableVersion}`);
21233
+ }
21234
+ return { records: allRecords, maxVersion: maxReadableVersion };
20444
21235
  } catch (err) {
20445
21236
  logError(`[cloud-sync] PULL FAILED: ${err instanceof Error ? err.message : String(err)}`);
20446
21237
  return { records: [], maxVersion: sinceVersion };
20447
21238
  }
20448
21239
  }
20449
- var CLOUD_RELINK_REQUIRED_MESSAGE = "[cloud-sync] Paused after key rotation. Run `exe-os cloud relink --dry-run` for the safe relink checklist.";
20450
- async function getCloudRelinkRequired(client = getClient()) {
21240
+ var CLOUD_REUPLOAD_REQUIRED_MESSAGE = "Cloud sync is blocked because this device rotated its memory encryption key. Run `exe-os cloud reupload` first to re-upload the cloud backup with the new key.";
21241
+ async function getCloudReuploadRequired(client = getClient()) {
20451
21242
  try {
20452
21243
  await client.execute("CREATE TABLE IF NOT EXISTS sync_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)");
20453
- const relink = await client.execute("SELECT value FROM sync_meta WHERE key = 'cloud_relink_required' LIMIT 1");
20454
- return String(relink.rows[0]?.value ?? "") === "1";
21244
+ const result2 = await client.execute("SELECT key, value FROM sync_meta WHERE key IN ('cloud_reupload_required', 'cloud_relink_required')");
21245
+ return result2.rows.some((row) => String(row.value ?? "") === "1");
20455
21246
  } catch {
20456
21247
  return false;
20457
21248
  }
20458
21249
  }
21250
+ async function clearCloudReuploadRequired(client = getClient()) {
21251
+ await client.execute("CREATE TABLE IF NOT EXISTS sync_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)");
21252
+ await client.execute("INSERT OR REPLACE INTO sync_meta (key, value) VALUES ('cloud_reupload_required', '0')");
21253
+ await client.execute("INSERT OR REPLACE INTO sync_meta (key, value) VALUES ('cloud_relink_required', '0')");
21254
+ await client.execute({
21255
+ sql: "INSERT OR REPLACE INTO sync_meta (key, value) VALUES ('cloud_reuploaded_at', ?)",
21256
+ args: [(/* @__PURE__ */ new Date()).toISOString()]
21257
+ });
21258
+ await client.execute("DELETE FROM sync_meta WHERE key IN ('last_cloud_pull_version', 'last_cloud_push_version')");
21259
+ }
21260
+ async function markCloudReuploadRequired(client = getClient()) {
21261
+ await client.execute("CREATE TABLE IF NOT EXISTS sync_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)");
21262
+ await client.execute("INSERT OR REPLACE INTO sync_meta (key, value) VALUES ('cloud_reupload_required', '1')");
21263
+ }
20459
21264
  async function cloudSync(config2) {
20460
21265
  if (!isSyncCryptoInitialized()) {
20461
21266
  try {
@@ -20477,10 +21282,10 @@ async function cloudSync(config2) {
20477
21282
  throw new Error("[cloud-sync] Database not initialized. Call initStore() before cloudSync().");
20478
21283
  }
20479
21284
  try {
20480
- if (await getCloudRelinkRequired(client)) throw new Error(CLOUD_RELINK_REQUIRED_MESSAGE);
21285
+ if (await getCloudReuploadRequired(client)) throw new Error(CLOUD_REUPLOAD_REQUIRED_MESSAGE);
20481
21286
  } catch (err) {
20482
21287
  const msg = err instanceof Error ? err.message : String(err);
20483
- if (msg.includes("Paused after key rotation")) throw err;
21288
+ if (msg === CLOUD_REUPLOAD_REQUIRED_MESSAGE || msg.includes("key rotation")) throw err;
20484
21289
  }
20485
21290
  try {
20486
21291
  const { getRawClient: getRawClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
@@ -20738,7 +21543,7 @@ async function cloudSync(config2) {
20738
21543
  const { getLatestBackup: getLatestBackup2 } = await Promise.resolve().then(() => (init_db_backup(), db_backup_exports));
20739
21544
  const latestBackup = getLatestBackup2();
20740
21545
  if (latestBackup) {
20741
- const backupSize = statSync5(latestBackup).size;
21546
+ const backupSize = statSync6(latestBackup).size;
20742
21547
  const MAX_CLOUD_BACKUP_BYTES = 50 * 1024 * 1024;
20743
21548
  if (backupSize <= MAX_CLOUD_BACKUP_BYTES) {
20744
21549
  const backupData = readFileSync23(latestBackup);
@@ -21048,8 +21853,8 @@ async function cloudPullBlob(route, config2) {
21048
21853
  }
21049
21854
  async function cloudPushGlobalProcedures(config2) {
21050
21855
  const client = getClient();
21051
- const result = await client.execute("SELECT * FROM company_procedures LIMIT 1000");
21052
- const rows = result.rows;
21856
+ const result2 = await client.execute("SELECT * FROM company_procedures LIMIT 1000");
21857
+ const rows = result2.rows;
21053
21858
  const { ok } = await cloudPushBlob(
21054
21859
  "/sync/push-global-procedures",
21055
21860
  rows,
@@ -21093,8 +21898,8 @@ async function cloudPullGlobalProcedures(config2) {
21093
21898
  }
21094
21899
  async function cloudPushBehaviors(config2) {
21095
21900
  const client = getClient();
21096
- const result = await client.execute("SELECT * FROM behaviors LIMIT 10000");
21097
- const rows = result.rows;
21901
+ const result2 = await client.execute("SELECT * FROM behaviors LIMIT 10000");
21902
+ const rows = result2.rows;
21098
21903
  const { ok } = await cloudPushBlob(
21099
21904
  "/sync/push-behaviors",
21100
21905
  rows,
@@ -21249,8 +22054,8 @@ async function cloudPullGraphRAG(config2) {
21249
22054
  }
21250
22055
  async function cloudPushTasks(config2) {
21251
22056
  const client = getClient();
21252
- const result = await client.execute("SELECT * FROM tasks LIMIT 10000");
21253
- const rows = result.rows;
22057
+ const result2 = await client.execute("SELECT * FROM tasks LIMIT 10000");
22058
+ const rows = result2.rows;
21254
22059
  const { ok } = await cloudPushBlob(
21255
22060
  "/sync/push-tasks",
21256
22061
  rows,
@@ -21295,8 +22100,8 @@ async function cloudPullTasks(config2) {
21295
22100
  }
21296
22101
  async function cloudPushConversations(config2) {
21297
22102
  const client = getClient();
21298
- const result = await client.execute("SELECT * FROM conversations LIMIT 50000");
21299
- const rows = result.rows;
22103
+ const result2 = await client.execute("SELECT * FROM conversations LIMIT 50000");
22104
+ const rows = result2.rows;
21300
22105
  const { ok } = await cloudPushBlob(
21301
22106
  "/sync/push-conversations",
21302
22107
  rows,
@@ -21402,31 +22207,138 @@ async function cloudPullDocuments(config2) {
21402
22207
 
21403
22208
  // src/mcp/tools/cloud-sync.ts
21404
22209
  init_config();
22210
+ init_keychain();
22211
+ init_store();
22212
+ init_database();
22213
+ function result(text3, isError = false) {
22214
+ return { content: [{ type: "text", text: text3 }], ...isError ? { isError: true } : {} };
22215
+ }
22216
+ function shortKeyFingerprint(key) {
22217
+ if (!key) return "missing";
22218
+ return `${key.toString("hex").slice(0, 8)}...`;
22219
+ }
22220
+ async function cloudStatusText() {
22221
+ const config2 = await loadConfig();
22222
+ const key = await getMasterKey();
22223
+ const cloud = config2.cloud;
22224
+ let reuploadRequired = false;
22225
+ let localMemoryVersion = 0;
22226
+ let lastPushedMemoryVersion = 0;
22227
+ let lastPullVersion = 0;
22228
+ let pendingMemoryCount = 0;
22229
+ let lastReuploadedAt = null;
22230
+ try {
22231
+ await initStore({ lightweight: true });
22232
+ const client = getClient();
22233
+ reuploadRequired = await getCloudReuploadRequired(client);
22234
+ const maxVersion = await client.execute("SELECT COALESCE(MAX(version), 0) as version FROM memories WHERE scope IS NULL OR scope != 'personal'");
22235
+ localMemoryVersion = Number(maxVersion.rows[0]?.version ?? 0);
22236
+ const meta = await client.execute("SELECT key, value FROM sync_meta WHERE key IN ('last_cloud_push_version', 'last_cloud_pull_version', 'cloud_reuploaded_at', 'cloud_relinked_at')");
22237
+ for (const row of meta.rows) {
22238
+ const keyName = String(row.key ?? "");
22239
+ const value = String(row.value ?? "");
22240
+ if (keyName === "last_cloud_push_version") lastPushedMemoryVersion = Number(value || 0);
22241
+ if (keyName === "last_cloud_pull_version") lastPullVersion = Number(value || 0);
22242
+ if (keyName === "cloud_reuploaded_at" || keyName === "cloud_relinked_at") lastReuploadedAt = value;
22243
+ }
22244
+ const pending = await client.execute({
22245
+ sql: "SELECT COUNT(*) as cnt FROM memories WHERE (scope IS NULL OR scope != 'personal') AND version > ?",
22246
+ args: [lastPushedMemoryVersion]
22247
+ });
22248
+ pendingMemoryCount = Number(pending.rows[0]?.cnt ?? 0);
22249
+ } catch (err) {
22250
+ pendingMemoryCount = -1;
22251
+ }
22252
+ const lines = [];
22253
+ lines.push("## Exe Cloud Status");
22254
+ lines.push("");
22255
+ lines.push(`- Encryption key: ${key ? `present (${shortKeyFingerprint(key)})` : "missing"}`);
22256
+ if (cloud?.apiKey && cloud?.endpoint) {
22257
+ lines.push(`- Cloud account: connected (${cloud.apiKey.slice(0, 10)}...${cloud.apiKey.slice(-4)})`);
22258
+ lines.push(`- Endpoint: ${cloud.endpoint}`);
22259
+ } else {
22260
+ lines.push("- Cloud account: not configured");
22261
+ }
22262
+ lines.push("- Status check: read-only; no data was uploaded or downloaded");
22263
+ lines.push("");
22264
+ if (!cloud?.apiKey || !cloud?.endpoint) {
22265
+ lines.push("**Sync status:** NOT CONFIGURED");
22266
+ lines.push("Run `exe-os cloud` in Terminal to set up Exe Cloud.");
22267
+ } else if (reuploadRequired) {
22268
+ lines.push("**Sync status:** NOT SYNCING \u2014 blocked for safety");
22269
+ lines.push("**Why:** this device changed its memory encryption key.");
22270
+ lines.push('**Required fix:** run MCP `cloud_sync` with `action="reupload"` and confirmation, or run `exe-os cloud reupload` in Terminal.');
22271
+ lines.push("After re-upload, automatic background sync will resume.");
22272
+ } else if (pendingMemoryCount > 0) {
22273
+ lines.push("**Sync status:** SYNC ENABLED \u2014 waiting for background sync");
22274
+ lines.push(`**Pending upload:** ${pendingMemoryCount.toLocaleString()} local memor${pendingMemoryCount === 1 ? "y" : "ies"}`);
22275
+ lines.push('To sync now, run MCP `cloud_sync` with `action="sync"` or Terminal `exe-os cloud sync`.');
22276
+ } else {
22277
+ lines.push("**Sync status:** SYNC ENABLED \u2014 no obvious memory backlog");
22278
+ }
22279
+ lines.push("");
22280
+ lines.push(`- Memory cursor: local=${localMemoryVersion} last pushed=${lastPushedMemoryVersion} last pulled=${lastPullVersion}`);
22281
+ if (lastReuploadedAt) lines.push(`- Last re-upload: ${lastReuploadedAt}`);
22282
+ lines.push("");
22283
+ lines.push("Terminal-only safety rule: full recovery phrases are never returned by MCP. To reveal the phrase, the user must run `exe-os cloud link --show-full` directly in their local Terminal.");
22284
+ return lines.join("\n");
22285
+ }
21405
22286
  function registerCloudSync(server2) {
21406
22287
  server2.registerTool(
21407
22288
  "cloud_sync",
21408
22289
  {
21409
22290
  title: "Cloud Sync",
21410
- description: "Trigger a cloud sync cycle \u2014 pulls remote changes then pushes local. Reports pushed/pulled counts for memories, behaviors, graph, tasks, and more.",
22291
+ description: "Consolidated Exe Cloud tool. Supports read-only status, normal sync-now, and explicitly confirmed post-key-rotation re-upload. Does not reveal recovery phrases and does not rotate keys.",
21411
22292
  inputSchema: {
21412
- force: z58.boolean().default(false).describe("Force sync even if recently synced")
22293
+ action: z58.enum(["status", "sync", "reupload"]).default("sync").describe("Cloud operation. status is read-only; sync is normal sync-now; reupload repairs cloud after key rotation."),
22294
+ force: z58.boolean().default(false).describe("Reserved for sync compatibility; normal cloud sync already runs when requested."),
22295
+ confirm_local_db_source_of_truth: z58.string().optional().describe('Required for action=reupload. Must exactly equal "LOCAL DB IS SOURCE OF TRUTH".')
21413
22296
  }
21414
22297
  },
21415
- async () => {
22298
+ async ({ action = "sync", confirm_local_db_source_of_truth }) => {
21416
22299
  try {
22300
+ if (action === "status") {
22301
+ return result(await cloudStatusText());
22302
+ }
21417
22303
  const config2 = await loadConfig();
21418
22304
  const cloud = config2.cloud;
21419
22305
  if (!cloud?.apiKey || !cloud?.endpoint) {
21420
- return {
21421
- content: [
21422
- {
21423
- type: "text",
21424
- text: "Cloud sync not configured. Run `/exe-cloud` to set up Exe Cloud."
21425
- }
21426
- ]
21427
- };
22306
+ return result("Cloud sync not configured. Run `exe-os cloud` in Terminal to set up Exe Cloud.", true);
22307
+ }
22308
+ if (action === "reupload") {
22309
+ await initStore({ lightweight: true });
22310
+ const client = getClient();
22311
+ const required = await getCloudReuploadRequired(client);
22312
+ if (!required) {
22313
+ return result("Cloud re-upload is not currently required. Normal cloud sync is safe to run.");
22314
+ }
22315
+ if (confirm_local_db_source_of_truth !== "LOCAL DB IS SOURCE OF TRUTH") {
22316
+ return result(
22317
+ 'Cloud re-upload is blocked until explicitly confirmed. This operation treats the local DB as source of truth and re-uploads cloud data encrypted with the current key. Retry with confirm_local_db_source_of_truth="LOCAL DB IS SOURCE OF TRUTH", or run `exe-os cloud reupload` in Terminal.',
22318
+ true
22319
+ );
22320
+ }
22321
+ await clearCloudReuploadRequired(client);
22322
+ let syncResult2;
22323
+ try {
22324
+ syncResult2 = await cloudSync({ apiKey: cloud.apiKey, endpoint: cloud.endpoint });
22325
+ } catch (err) {
22326
+ await markCloudReuploadRequired(client);
22327
+ throw err;
22328
+ }
22329
+ return result([
22330
+ "## Cloud Re-upload Complete",
22331
+ "",
22332
+ "Normal cloud sync is safe again. Other devices must reconnect using the current 24-word recovery phrase.",
22333
+ "",
22334
+ `- Active memories: ${syncResult2.totalMemories.toLocaleString()} (\u2191 ${syncResult2.pushed.toLocaleString()} syncable rows pushed, \u2193 ${syncResult2.pulled.toLocaleString()} pulled)`,
22335
+ `- Behaviors: \u2191 ${syncResult2.behaviors.pushed.toLocaleString()}, \u2193 ${syncResult2.behaviors.pulled.toLocaleString()}`,
22336
+ `- GraphRAG: \u2191 ${syncResult2.graphrag.pushed.toLocaleString()}, \u2193 ${syncResult2.graphrag.pulled.toLocaleString()}`,
22337
+ `- Tasks: \u2191 ${syncResult2.tasks.pushed.toLocaleString()}, \u2193 ${syncResult2.tasks.pulled.toLocaleString()}`,
22338
+ `- Documents: \u2191 ${syncResult2.documents.pushed.toLocaleString()}, \u2193 ${syncResult2.documents.pulled.toLocaleString()}`
22339
+ ].join("\n"));
21428
22340
  }
21429
- const result = await cloudSync({
22341
+ const syncResult = await cloudSync({
21430
22342
  apiKey: cloud.apiKey,
21431
22343
  endpoint: cloud.endpoint
21432
22344
  });
@@ -21434,27 +22346,18 @@ function registerCloudSync(server2) {
21434
22346
  lines.push("## Cloud Sync Complete\n");
21435
22347
  lines.push("| Category | Pushed | Pulled |");
21436
22348
  lines.push("|----------|--------|--------|");
21437
- lines.push(`| Memories | ${result.pushed.toLocaleString()} | ${result.pulled.toLocaleString()} |`);
21438
- lines.push(`| Behaviors | ${result.behaviors.pushed.toLocaleString()} | ${result.behaviors.pulled.toLocaleString()} |`);
21439
- lines.push(`| GraphRAG | ${result.graphrag.pushed.toLocaleString()} | ${result.graphrag.pulled.toLocaleString()} |`);
21440
- lines.push(`| Tasks | ${result.tasks.pushed.toLocaleString()} | ${result.tasks.pulled.toLocaleString()} |`);
21441
- lines.push(`| Conversations | ${result.conversations.pushed.toLocaleString()} | ${result.conversations.pulled.toLocaleString()} |`);
21442
- lines.push(`| Documents | ${result.documents.pushed.toLocaleString()} | ${result.documents.pulled.toLocaleString()} |`);
22349
+ lines.push(`| Memories | ${syncResult.pushed.toLocaleString()} | ${syncResult.pulled.toLocaleString()} |`);
22350
+ lines.push(`| Behaviors | ${syncResult.behaviors.pushed.toLocaleString()} | ${syncResult.behaviors.pulled.toLocaleString()} |`);
22351
+ lines.push(`| GraphRAG | ${syncResult.graphrag.pushed.toLocaleString()} | ${syncResult.graphrag.pulled.toLocaleString()} |`);
22352
+ lines.push(`| Tasks | ${syncResult.tasks.pushed.toLocaleString()} | ${syncResult.tasks.pulled.toLocaleString()} |`);
22353
+ lines.push(`| Conversations | ${syncResult.conversations.pushed.toLocaleString()} | ${syncResult.conversations.pulled.toLocaleString()} |`);
22354
+ lines.push(`| Documents | ${syncResult.documents.pushed.toLocaleString()} | ${syncResult.documents.pulled.toLocaleString()} |`);
21443
22355
  lines.push("");
21444
- lines.push(`**Total memories:** ${result.totalMemories.toLocaleString()}`);
21445
- lines.push(`**Roster:** ${result.roster.employees} employees, ${result.roster.identities} identities`);
21446
- return {
21447
- content: [{ type: "text", text: lines.join("\n") }]
21448
- };
22356
+ lines.push(`**Active memories:** ${syncResult.totalMemories.toLocaleString()}`);
22357
+ lines.push(`**Roster:** ${syncResult.roster.employees} employees, ${syncResult.roster.identities} identities`);
22358
+ return result(lines.join("\n"));
21449
22359
  } catch (err) {
21450
- return {
21451
- content: [
21452
- {
21453
- type: "text",
21454
- text: `Cloud sync failed: ${err instanceof Error ? err.message : String(err)}`
21455
- }
21456
- ]
21457
- };
22360
+ return result(`Cloud operation failed: ${err instanceof Error ? err.message : String(err)}`, true);
21458
22361
  }
21459
22362
  }
21460
22363
  );
@@ -21967,14 +22870,14 @@ function registerBackupVps(server2) {
21967
22870
  r2AccessKeyId: input.r2AccessKeyId,
21968
22871
  r2SecretAccessKey: input.r2SecretAccessKey
21969
22872
  };
21970
- const result = await createBackup2(options);
22873
+ const result2 = await createBackup2(options);
21971
22874
  return {
21972
22875
  content: [
21973
22876
  {
21974
22877
  type: "text",
21975
- text: `Backup complete: ${result.key}
21976
- ${result.sizeBytes} bytes
21977
- ${result.timestamp}`
22878
+ text: `Backup complete: ${result2.key}
22879
+ ${result2.sizeBytes} bytes
22880
+ ${result2.timestamp}`
21978
22881
  }
21979
22882
  ]
21980
22883
  };
@@ -22007,18 +22910,18 @@ ${result.timestamp}`
22007
22910
  r2AccessKeyId: input.r2AccessKeyId,
22008
22911
  r2SecretAccessKey: input.r2SecretAccessKey
22009
22912
  };
22010
- const result = await listBackups2(options);
22913
+ const result2 = await listBackups2(options);
22011
22914
  return {
22012
22915
  content: [
22013
22916
  {
22014
22917
  type: "text",
22015
- text: formatBackups(result)
22918
+ text: formatBackups(result2)
22016
22919
  }
22017
22920
  ]
22018
22921
  };
22019
22922
  }
22020
22923
  case "health": {
22021
- const result = await backupHealth({
22924
+ const result2 = await backupHealth({
22022
22925
  r2Bucket: input.r2Bucket,
22023
22926
  r2Endpoint: input.r2Endpoint,
22024
22927
  r2AccessKeyId: input.r2AccessKeyId,
@@ -22029,10 +22932,10 @@ ${result.timestamp}`
22029
22932
  {
22030
22933
  type: "text",
22031
22934
  text: [
22032
- `last_backup: ${result.lastBackup ?? "none"}`,
22033
- `backup_count: ${result.backupCount}`,
22034
- `total_size_bytes: ${result.totalSizeBytes}`,
22035
- `oldest_backup: ${result.oldestBackup ?? "none"}`
22935
+ `last_backup: ${result2.lastBackup ?? "none"}`,
22936
+ `backup_count: ${result2.backupCount}`,
22937
+ `total_size_bytes: ${result2.totalSizeBytes}`,
22938
+ `oldest_backup: ${result2.oldestBackup ?? "none"}`
22036
22939
  ].join("\n")
22037
22940
  }
22038
22941
  ]
@@ -22140,9 +23043,9 @@ var HostingerApiClient = class {
22140
23043
  }
22141
23044
  this.lastRequestTime = Date.now();
22142
23045
  }
22143
- async request(method, path49, body) {
23046
+ async request(method, path50, body) {
22144
23047
  await this.rateLimit();
22145
- const url = `${this.baseUrl}${path49}`;
23048
+ const url = `${this.baseUrl}${path50}`;
22146
23049
  const headers = {
22147
23050
  Authorization: `Bearer ${this.apiKey}`,
22148
23051
  "Content-Type": "application/json",
@@ -22215,8 +23118,8 @@ async function requestCloudflare(cfApiToken, zoneId, options) {
22215
23118
  }
22216
23119
  return envelope.result;
22217
23120
  }
22218
- function buildUrl(zoneId, path49 = "/dns_records", query) {
22219
- const normalizedPath = path49.startsWith("/") ? path49 : `/${path49}`;
23121
+ function buildUrl(zoneId, path50 = "/dns_records", query) {
23122
+ const normalizedPath = path50.startsWith("/") ? path50 : `/${path50}`;
22220
23123
  const url = new URL(
22221
23124
  `${CLOUDFLARE_API_BASE_URL}/zones/${zoneId}${normalizedPath}`
22222
23125
  );
@@ -22380,7 +23283,7 @@ function registerDeployClient(server2) {
22380
23283
  };
22381
23284
  }
22382
23285
  try {
22383
- const result = await executeDeployment({
23286
+ const result2 = await executeDeployment({
22384
23287
  client_name,
22385
23288
  domain,
22386
23289
  region,
@@ -22395,7 +23298,7 @@ function registerDeployClient(server2) {
22395
23298
  content: [
22396
23299
  {
22397
23300
  type: "text",
22398
- text: JSON.stringify(result, null, 2)
23301
+ text: JSON.stringify(result2, null, 2)
22399
23302
  }
22400
23303
  ]
22401
23304
  };
@@ -23507,8 +24410,8 @@ Available: ${available.length > 0 ? available.join(", ") : "none"}`
23507
24410
  ]
23508
24411
  };
23509
24412
  }
23510
- const result = applyPack(industry, project);
23511
- if (!result) {
24413
+ const result2 = applyPack(industry, project);
24414
+ if (!result2) {
23512
24415
  return {
23513
24416
  content: [
23514
24417
  {
@@ -23521,22 +24424,22 @@ Available: ${available.length > 0 ? available.join(", ") : "none"}`
23521
24424
  const lines = [
23522
24425
  `Applied "${industry}" starter pack to project "${project}":
23523
24426
  `,
23524
- `**CRM Custom Objects** (${result.customObjects.count}):`,
23525
- ...result.customObjects.names.map((n) => ` - ${n}`),
24427
+ `**CRM Custom Objects** (${result2.customObjects.count}):`,
24428
+ ...result2.customObjects.names.map((n) => ` - ${n}`),
23526
24429
  "",
23527
- `**Triggers Created** (${result.triggers.created}):`,
23528
- ...result.triggers.ids.map((id, i) => {
24430
+ `**Triggers Created** (${result2.triggers.created}):`,
24431
+ ...result2.triggers.ids.map((id, i) => {
23529
24432
  const t = pack.triggers[i];
23530
24433
  return ` - ${t?.name ?? "Unknown"} (${id})`;
23531
24434
  }),
23532
24435
  "",
23533
- `**Wiki Seeds** (${result.wikiSeeds.count}):`,
23534
- ...result.wikiSeeds.titles.map((t) => ` - ${t}`)
24436
+ `**Wiki Seeds** (${result2.wikiSeeds.count}):`,
24437
+ ...result2.wikiSeeds.titles.map((t) => ` - ${t}`)
23535
24438
  ];
23536
- if (result.pendingVariables.length > 0) {
24439
+ if (result2.pendingVariables.length > 0) {
23537
24440
  lines.push("");
23538
24441
  lines.push("**Requires manual configuration:**");
23539
- for (const pv of result.pendingVariables) {
24442
+ for (const pv of result2.pendingVariables) {
23540
24443
  const vars = Object.entries(pv.variables).map(([k, v]) => ` - {{${k}}}: ${v}`).join("\n");
23541
24444
  lines.push(` ${pv.trigger}:
23542
24445
  ${vars}`);
@@ -23612,7 +24515,7 @@ ${err.message}`
23612
24515
 
23613
24516
  // src/mcp/tools/load-skill.ts
23614
24517
  import { z as z69 } from "zod";
23615
- import { readFileSync as readFileSync26, readdirSync as readdirSync13, statSync as statSync6 } from "fs";
24518
+ import { readFileSync as readFileSync26, readdirSync as readdirSync13, statSync as statSync7 } from "fs";
23616
24519
  import path42 from "path";
23617
24520
  import { homedir as homedir7 } from "os";
23618
24521
  var SKILLS_DIR = path42.join(homedir7(), ".claude", "skills");
@@ -23622,9 +24525,9 @@ function listAvailableSkills() {
23622
24525
  return entries.filter((entry) => {
23623
24526
  try {
23624
24527
  const entryPath = path42.join(SKILLS_DIR, entry);
23625
- if (!statSync6(entryPath).isDirectory()) return false;
24528
+ if (!statSync7(entryPath).isDirectory()) return false;
23626
24529
  const skillFile = path42.join(entryPath, "SKILL.md");
23627
- statSync6(skillFile);
24530
+ statSync7(skillFile);
23628
24531
  return true;
23629
24532
  } catch {
23630
24533
  return false;
@@ -23927,11 +24830,11 @@ async function importIdentities(identities, updatedBy) {
23927
24830
  }
23928
24831
  async function getActiveProcedureTitles() {
23929
24832
  const client = getClient();
23930
- const result = await client.execute({
24833
+ const result2 = await client.execute({
23931
24834
  sql: "SELECT title FROM company_procedures WHERE active = 1",
23932
24835
  args: []
23933
24836
  });
23934
- return new Set(result.rows.map((row) => String(row.title)));
24837
+ return new Set(result2.rows.map((row) => String(row.title)));
23935
24838
  }
23936
24839
  async function exportOrchestration(createdBy) {
23937
24840
  const client = getClient();
@@ -24121,11 +25024,11 @@ function registerImportOrchestration(server2) {
24121
25024
  await initStore();
24122
25025
  const raw = readFileSync28(package_path, "utf-8");
24123
25026
  const pkg = validatePackage(JSON.parse(raw));
24124
- const result = await importOrchestration(pkg, merge_strategy);
25027
+ const result2 = await importOrchestration(pkg, merge_strategy);
24125
25028
  return {
24126
25029
  content: [{
24127
25030
  type: "text",
24128
- text: `Imported ${result.imported.roster} roster entries, ${result.imported.identities} identities, ${result.imported.behaviors} behaviors, ${result.imported.procedures} procedures using ${merge_strategy} strategy`
25031
+ text: `Imported ${result2.imported.roster} roster entries, ${result2.imported.identities} identities, ${result2.imported.behaviors} behaviors, ${result2.imported.procedures} procedures using ${merge_strategy} strategy`
24129
25032
  }]
24130
25033
  };
24131
25034
  } catch (err) {
@@ -24236,11 +25139,11 @@ Domain: ${domain ?? "none"}`
24236
25139
  };
24237
25140
  }
24238
25141
  const client = getClient();
24239
- const result = await client.execute({
25142
+ const result2 = await client.execute({
24240
25143
  sql: "SELECT id, title, content, priority, domain FROM company_procedures WHERE id = ?",
24241
25144
  args: [procedure_id]
24242
25145
  });
24243
- if (result.rows.length === 0) {
25146
+ if (result2.rows.length === 0) {
24244
25147
  return {
24245
25148
  content: [{
24246
25149
  type: "text",
@@ -24249,7 +25152,7 @@ Domain: ${domain ?? "none"}`
24249
25152
  isError: true
24250
25153
  };
24251
25154
  }
24252
- const row = result.rows[0];
25155
+ const row = result2.rows[0];
24253
25156
  const wasActive = await deactivateGlobalProcedure(procedure_id);
24254
25157
  if (!wasActive) {
24255
25158
  return {
@@ -24387,15 +25290,20 @@ function registerConfig(server2) {
24387
25290
  subaction: z73.enum(["store", "list", "deactivate"]).optional().describe("Nested action for company_procedure/global_procedure"),
24388
25291
  max_clusters: z73.coerce.number().optional().describe("Consolidation max clusters"),
24389
25292
  force: z73.boolean().optional().describe("Force operation where supported"),
25293
+ cloud_action: z73.enum(["status", "sync", "reupload"]).optional().describe("Nested operation for action=cloud_sync"),
25294
+ confirm_local_db_source_of_truth: z73.string().optional().describe("Required for cloud_action=reupload; must exactly equal LOCAL DB IS SOURCE OF TRUTH"),
24390
25295
  domain_name: z73.string().optional().describe("Client deployment domain"),
24391
25296
  phase: z73.enum(["phase_1_coo", "phase_2_executives", "phase_3_parallel_org", "1", "2", "3"]).optional().describe("Orchestration phase for orchestration_phase action")
24392
25297
  }
24393
25298
  }, async (input, extra) => {
24394
25299
  const action = input.action;
24395
- const { action: _action, subaction, ...args } = input;
25300
+ const { action: _action, subaction, cloud_action, ...args } = input;
24396
25301
  if (action === "company_procedure" || action === "global_procedure") {
24397
25302
  args.action = subaction ?? "list";
24398
25303
  }
25304
+ if (action === "cloud_sync" && cloud_action) {
25305
+ args.action = cloud_action;
25306
+ }
24399
25307
  if (action === "export_orchestration" && !args.output_path) return errorResult8('config action "export_orchestration" requires output_path');
24400
25308
  if (action === "import_orchestration" && !args.input_path) return errorResult8('config action "import_orchestration" requires input_path');
24401
25309
  if (action === "activate_license" && !args.license_key) return errorResult8('config action "activate_license" requires license_key');
@@ -24793,7 +25701,7 @@ function registerBehavior(server2) {
24793
25701
  args.push(proj);
24794
25702
  }
24795
25703
  const where = conditions.join(" AND ");
24796
- const result2 = await client2.execute({
25704
+ const result3 = await client2.execute({
24797
25705
  sql: `SELECT id, agent_id, project_name, domain, content, active, created_at, updated_at
24798
25706
  FROM behaviors
24799
25707
  WHERE ${where}
@@ -24801,7 +25709,7 @@ function registerBehavior(server2) {
24801
25709
  LIMIT 50`,
24802
25710
  args
24803
25711
  });
24804
- const behaviors = result2.rows.map((r) => rowToBehavior2(r));
25712
+ const behaviors = result3.rows.map((r) => rowToBehavior2(r));
24805
25713
  if (behaviors.length === 0) {
24806
25714
  return {
24807
25715
  content: [{ type: "text", text: "No behaviors found." }]
@@ -24900,11 +25808,11 @@ Use /exe-forget to remove any that this supersedes.`;
24900
25808
  };
24901
25809
  }
24902
25810
  const client = getClient();
24903
- const result = await client.execute({
25811
+ const result2 = await client.execute({
24904
25812
  sql: "SELECT id, agent_id, content, domain, priority FROM behaviors WHERE id = ?",
24905
25813
  args: [behavior_id]
24906
25814
  });
24907
- if (result.rows.length === 0) {
25815
+ if (result2.rows.length === 0) {
24908
25816
  return {
24909
25817
  content: [{
24910
25818
  type: "text",
@@ -24913,7 +25821,7 @@ Use /exe-forget to remove any that this supersedes.`;
24913
25821
  isError: true
24914
25822
  };
24915
25823
  }
24916
- const row = result.rows[0];
25824
+ const row = result2.rows[0];
24917
25825
  const wasActive = await deactivateBehavior(behavior_id);
24918
25826
  if (!wasActive) {
24919
25827
  return {
@@ -25119,11 +26027,11 @@ function registerDeactivateGlobalProcedure(server2) {
25119
26027
  };
25120
26028
  }
25121
26029
  const client = getClient();
25122
- const result = await client.execute({
26030
+ const result2 = await client.execute({
25123
26031
  sql: "SELECT id, title, content, priority, domain FROM company_procedures WHERE id = ?",
25124
26032
  args: [procedure_id]
25125
26033
  });
25126
- if (result.rows.length === 0) {
26034
+ if (result2.rows.length === 0) {
25127
26035
  return {
25128
26036
  content: [{
25129
26037
  type: "text",
@@ -25132,7 +26040,7 @@ function registerDeactivateGlobalProcedure(server2) {
25132
26040
  isError: true
25133
26041
  };
25134
26042
  }
25135
- const row = result.rows[0];
26043
+ const row = result2.rows[0];
25136
26044
  const wasActive = await deactivateGlobalProcedure(procedure_id);
25137
26045
  if (!wasActive) {
25138
26046
  return {
@@ -25261,14 +26169,14 @@ function registerGetDecision(server2) {
25261
26169
  },
25262
26170
  async ({ domain }) => {
25263
26171
  const client = getClient();
25264
- const result = await client.execute({
26172
+ const result2 = await client.execute({
25265
26173
  sql: `SELECT id, agent_id, timestamp, raw_text, status, supersedes_id, project_name
25266
26174
  FROM memories
25267
26175
  WHERE memory_type = 'decision' AND source_path = ?
25268
26176
  ORDER BY timestamp DESC`,
25269
26177
  args: [domain]
25270
26178
  });
25271
- if (result.rows.length === 0) {
26179
+ if (result2.rows.length === 0) {
25272
26180
  return {
25273
26181
  content: [
25274
26182
  {
@@ -25278,7 +26186,7 @@ function registerGetDecision(server2) {
25278
26186
  ]
25279
26187
  };
25280
26188
  }
25281
- const decisions = result.rows.map((r) => ({
26189
+ const decisions = result2.rows.map((r) => ({
25282
26190
  id: String(r.id),
25283
26191
  agent_id: String(r.agent_id),
25284
26192
  timestamp: String(r.timestamp),
@@ -25852,10 +26760,429 @@ Upstream status: ${upstreamStatus}`
25852
26760
  );
25853
26761
  }
25854
26762
 
25855
- // src/mcp/tools/support-inbox.ts
26763
+ // src/mcp/tools/code-context.ts
25856
26764
  import { z as z87 } from "zod";
26765
+
26766
+ // src/lib/code-context-index.ts
26767
+ init_config();
26768
+ import crypto19 from "crypto";
26769
+ import path48 from "path";
26770
+ import { existsSync as existsSync37, mkdirSync as mkdirSync20, readFileSync as readFileSync30, statSync as statSync8, writeFileSync as writeFileSync22 } from "fs";
26771
+ import { spawnSync } from "child_process";
26772
+ var INDEX_VERSION = 1;
26773
+ var DEFAULT_MAX_FILES = 2e3;
26774
+ var CODE_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx"]);
26775
+ var IGNORE_SEGMENTS = /* @__PURE__ */ new Set(["node_modules", "dist", ".git", "coverage", ".worktrees", ".next", "build"]);
26776
+ function normalizeProjectRoot(projectRoot) {
26777
+ return path48.resolve(projectRoot || process.cwd());
26778
+ }
26779
+ function hashText(text3) {
26780
+ return crypto19.createHash("sha256").update(text3).digest("hex");
26781
+ }
26782
+ function indexDir() {
26783
+ const dir = path48.join(EXE_AI_DIR, "code-context");
26784
+ mkdirSync20(dir, { recursive: true });
26785
+ return dir;
26786
+ }
26787
+ function getCodeContextIndexPath(projectRoot) {
26788
+ const root = normalizeProjectRoot(projectRoot);
26789
+ const rootHash = hashText(root).slice(0, 16);
26790
+ return path48.join(indexDir(), `${rootHash}.json`);
26791
+ }
26792
+ function currentBranch(projectRoot) {
26793
+ const result2 = spawnSync("git", ["branch", "--show-current"], {
26794
+ cwd: projectRoot,
26795
+ encoding: "utf8",
26796
+ timeout: 2e3
26797
+ });
26798
+ const branch = result2.status === 0 ? result2.stdout.trim() : "";
26799
+ return branch || "detached-or-unknown";
26800
+ }
26801
+ function shouldIgnore(relPath) {
26802
+ const parts = relPath.split(path48.sep);
26803
+ return parts.some((part) => IGNORE_SEGMENTS.has(part));
26804
+ }
26805
+ function isCodeFile(relPath) {
26806
+ return CODE_EXTENSIONS.has(path48.extname(relPath).toLowerCase());
26807
+ }
26808
+ function listCodeFiles(projectRoot, maxFiles) {
26809
+ const git = spawnSync("git", ["ls-files", "*.ts", "*.tsx", "*.js", "*.jsx"], {
26810
+ cwd: projectRoot,
26811
+ encoding: "utf8",
26812
+ timeout: 5e3,
26813
+ maxBuffer: 1024 * 1024 * 8
26814
+ });
26815
+ let files = [];
26816
+ if (git.status === 0 && git.stdout.trim()) {
26817
+ files = git.stdout.split("\n").map((s) => s.trim()).filter(Boolean);
26818
+ } else {
26819
+ const rg = spawnSync("rg", ["--files", "-g", "*.ts", "-g", "*.tsx", "-g", "*.js", "-g", "*.jsx"], {
26820
+ cwd: projectRoot,
26821
+ encoding: "utf8",
26822
+ timeout: 5e3,
26823
+ maxBuffer: 1024 * 1024 * 8
26824
+ });
26825
+ if (rg.status === 0 && rg.stdout.trim()) {
26826
+ files = rg.stdout.split("\n").map((s) => s.trim()).filter(Boolean);
26827
+ }
26828
+ }
26829
+ return files.filter((file) => isCodeFile(file) && !shouldIgnore(file)).slice(0, maxFiles).sort();
26830
+ }
26831
+ function parseImportPaths(importText) {
26832
+ const paths = [];
26833
+ const fromRegex = /from\s+["']([^"']+)["']/g;
26834
+ let match;
26835
+ while ((match = fromRegex.exec(importText)) !== null) paths.push(match[1]);
26836
+ const bareRegex = /^import\s+["']([^"']+)["']/gm;
26837
+ while ((match = bareRegex.exec(importText)) !== null) {
26838
+ if (!paths.includes(match[1])) paths.push(match[1]);
26839
+ }
26840
+ const requireRegex = /require\(["']([^"']+)["']\)/g;
26841
+ while ((match = requireRegex.exec(importText)) !== null) {
26842
+ if (!paths.includes(match[1])) paths.push(match[1]);
26843
+ }
26844
+ return paths;
26845
+ }
26846
+ function resolveImport(fromFile, importPath, allFiles) {
26847
+ if (!importPath.startsWith(".")) return null;
26848
+ const base = path48.posix.normalize(path48.posix.join(path48.posix.dirname(fromFile.replaceAll(path48.sep, "/")), importPath));
26849
+ const withoutKnownExt = base.replace(/\.(?:js|jsx|ts|tsx)$/, "");
26850
+ const candidates = [
26851
+ base,
26852
+ `${withoutKnownExt}.ts`,
26853
+ `${withoutKnownExt}.tsx`,
26854
+ `${withoutKnownExt}.js`,
26855
+ `${withoutKnownExt}.jsx`,
26856
+ `${base}.ts`,
26857
+ `${base}.tsx`,
26858
+ `${base}.js`,
26859
+ `${base}.jsx`,
26860
+ path48.posix.join(base, "index.ts"),
26861
+ path48.posix.join(base, "index.tsx"),
26862
+ path48.posix.join(base, "index.js"),
26863
+ path48.posix.join(base, "index.jsx")
26864
+ ];
26865
+ return candidates.find((candidate) => allFiles.has(candidate)) ?? null;
26866
+ }
26867
+ function symbolId(filePath, chunk) {
26868
+ return hashText(`${filePath}:${chunk.kind}:${chunk.name}:${chunk.startLine}:${chunk.endLine}`).slice(0, 24);
26869
+ }
26870
+ function loadIndex(projectRoot) {
26871
+ const file = getCodeContextIndexPath(projectRoot);
26872
+ if (!existsSync37(file)) return null;
26873
+ try {
26874
+ const parsed = JSON.parse(readFileSync30(file, "utf8"));
26875
+ if (parsed.version !== INDEX_VERSION || parsed.projectRoot !== projectRoot) return null;
26876
+ return parsed;
26877
+ } catch {
26878
+ return null;
26879
+ }
26880
+ }
26881
+ function saveIndex(index) {
26882
+ writeFileSync22(getCodeContextIndexPath(index.projectRoot), JSON.stringify(index, null, 2));
26883
+ }
26884
+ function buildFileRecord(projectRoot, relPath, allFiles, previous) {
26885
+ const absPath = path48.join(projectRoot, relPath);
26886
+ let stat;
26887
+ try {
26888
+ stat = statSync8(absPath);
26889
+ } catch {
26890
+ return null;
26891
+ }
26892
+ if (!stat.isFile()) return null;
26893
+ const source = readFileSync30(absPath, "utf8");
26894
+ const hash = hashText(source);
26895
+ if (previous && previous.hash === hash && previous.mtimeMs === stat.mtimeMs && previous.size === stat.size) {
26896
+ return previous;
26897
+ }
26898
+ if (!isChunkable(relPath)) return null;
26899
+ const chunks = chunkSourceFile(source, relPath);
26900
+ const imports = chunks.filter((chunk) => chunk.kind === "import").flatMap((chunk) => parseImportPaths(chunk.text));
26901
+ const resolvedImports = imports.map((importPath) => resolveImport(relPath, importPath, allFiles)).filter((file) => Boolean(file));
26902
+ const symbols = chunks.filter((chunk) => chunk.kind !== "import" && chunk.name !== "(unknown)").map((chunk) => ({
26903
+ id: symbolId(relPath, chunk),
26904
+ name: chunk.name,
26905
+ kind: chunk.kind,
26906
+ filePath: relPath,
26907
+ startLine: chunk.startLine,
26908
+ endLine: chunk.endLine,
26909
+ summary: summarizeChunk(chunk, relPath),
26910
+ text: chunk.text.slice(0, 6e3),
26911
+ comment: chunk.comment
26912
+ }));
26913
+ return {
26914
+ path: relPath,
26915
+ absPath,
26916
+ hash,
26917
+ mtimeMs: stat.mtimeMs,
26918
+ size: stat.size,
26919
+ imports,
26920
+ resolvedImports,
26921
+ symbols
26922
+ };
26923
+ }
26924
+ function buildCodeContextIndex(options = {}) {
26925
+ const projectRoot = normalizeProjectRoot(options.projectRoot);
26926
+ const maxFiles = options.maxFiles ?? DEFAULT_MAX_FILES;
26927
+ const branch = currentBranch(projectRoot);
26928
+ const previous = options.force ? null : loadIndex(projectRoot);
26929
+ const files = listCodeFiles(projectRoot, maxFiles);
26930
+ const allFiles = new Set(files.map((file) => file.replaceAll(path48.sep, "/")));
26931
+ const fileRecords = {};
26932
+ for (const rel of files) {
26933
+ const normalized = rel.replaceAll(path48.sep, "/");
26934
+ const record = buildFileRecord(projectRoot, normalized, allFiles, previous?.files[normalized]);
26935
+ if (record) fileRecords[normalized] = record;
26936
+ }
26937
+ const index = {
26938
+ version: INDEX_VERSION,
26939
+ projectRoot,
26940
+ rootHash: hashText(projectRoot).slice(0, 16),
26941
+ branch,
26942
+ indexedAt: (/* @__PURE__ */ new Date()).toISOString(),
26943
+ files: fileRecords
26944
+ };
26945
+ saveIndex(index);
26946
+ return index;
26947
+ }
26948
+ function loadOrBuildCodeContextIndex(options = {}) {
26949
+ const projectRoot = normalizeProjectRoot(options.projectRoot);
26950
+ if (!options.force) {
26951
+ const loaded = loadIndex(projectRoot);
26952
+ if (loaded) {
26953
+ const currentFiles = listCodeFiles(projectRoot, options.maxFiles ?? DEFAULT_MAX_FILES);
26954
+ const unchanged = currentFiles.every((rel) => {
26955
+ const normalized = rel.replaceAll(path48.sep, "/");
26956
+ const existing = loaded.files[normalized];
26957
+ if (!existing) return false;
26958
+ try {
26959
+ const stat = statSync8(path48.join(projectRoot, normalized));
26960
+ return stat.mtimeMs === existing.mtimeMs && stat.size === existing.size;
26961
+ } catch {
26962
+ return false;
26963
+ }
26964
+ });
26965
+ if (unchanged && Object.keys(loaded.files).length === currentFiles.length) return loaded;
26966
+ }
26967
+ }
26968
+ return buildCodeContextIndex(options);
26969
+ }
26970
+ function tokenize(query) {
26971
+ return query.toLowerCase().split(/[^a-z0-9_.$/-]+/).map((s) => s.trim()).filter((s) => s.length >= 2);
26972
+ }
26973
+ function scoreSymbol(symbol, terms) {
26974
+ const haystacks = {
26975
+ name: symbol.name.toLowerCase(),
26976
+ path: symbol.filePath.toLowerCase(),
26977
+ summary: symbol.summary.toLowerCase(),
26978
+ text: symbol.text.toLowerCase()
26979
+ };
26980
+ let score = 0;
26981
+ const matches = [];
26982
+ for (const term of terms) {
26983
+ if (haystacks.name === term) {
26984
+ score += 80;
26985
+ matches.push(`name=${term}`);
26986
+ continue;
26987
+ }
26988
+ if (haystacks.name.includes(term)) {
26989
+ score += 40;
26990
+ matches.push(`name~${term}`);
26991
+ }
26992
+ if (haystacks.path.includes(term)) {
26993
+ score += 15;
26994
+ matches.push(`path~${term}`);
26995
+ }
26996
+ if (haystacks.summary.includes(term)) {
26997
+ score += 12;
26998
+ matches.push(`summary~${term}`);
26999
+ }
27000
+ if (haystacks.text.includes(term)) {
27001
+ score += 4;
27002
+ matches.push(`text~${term}`);
27003
+ }
27004
+ }
27005
+ return { score, matches };
27006
+ }
27007
+ function searchCodeContext(query, options = {}) {
27008
+ const terms = tokenize(query);
27009
+ if (terms.length === 0) return [];
27010
+ const index = loadOrBuildCodeContextIndex(options);
27011
+ const results = [];
27012
+ for (const file of Object.values(index.files)) {
27013
+ for (const symbol of file.symbols) {
27014
+ const scored = scoreSymbol(symbol, terms);
27015
+ if (scored.score > 0) results.push({ symbol, score: scored.score, matches: scored.matches });
27016
+ }
27017
+ }
27018
+ return results.sort((a, b) => b.score - a.score || a.symbol.filePath.localeCompare(b.symbol.filePath)).slice(0, options.limit ?? 20);
27019
+ }
27020
+ function dependentsMap(index) {
27021
+ const map = /* @__PURE__ */ new Map();
27022
+ for (const file of Object.values(index.files)) {
27023
+ for (const dep of file.resolvedImports) {
27024
+ if (!map.has(dep)) map.set(dep, /* @__PURE__ */ new Set());
27025
+ map.get(dep).add(file.path);
27026
+ }
27027
+ }
27028
+ return map;
27029
+ }
27030
+ function findSymbols(index, symbolName, limit = 20) {
27031
+ const q = symbolName.toLowerCase();
27032
+ const exact = [];
27033
+ const fuzzy = [];
27034
+ for (const file of Object.values(index.files)) {
27035
+ for (const symbol of file.symbols) {
27036
+ if (symbol.name.toLowerCase() === q) exact.push(symbol);
27037
+ else if (symbol.name.toLowerCase().includes(q) || symbol.summary.toLowerCase().includes(q)) fuzzy.push(symbol);
27038
+ }
27039
+ }
27040
+ return [...exact, ...fuzzy].slice(0, limit);
27041
+ }
27042
+ function traceCodeSymbol(symbolName, options = {}) {
27043
+ const index = loadOrBuildCodeContextIndex(options);
27044
+ const matches = findSymbols(index, symbolName, options.limit ?? 20);
27045
+ const dependents = dependentsMap(index);
27046
+ return {
27047
+ query: symbolName,
27048
+ matches,
27049
+ definitions: matches.map((symbol) => {
27050
+ const file = index.files[symbol.filePath];
27051
+ return {
27052
+ symbol,
27053
+ imports: file.resolvedImports,
27054
+ dependents: [...dependents.get(symbol.filePath) ?? /* @__PURE__ */ new Set()].sort(),
27055
+ relatedSymbols: file.symbols.filter((s) => s.id !== symbol.id).slice(0, 20)
27056
+ };
27057
+ })
27058
+ };
27059
+ }
27060
+ function resolveTargetFile(index, input) {
27061
+ if (input.filePath) {
27062
+ const normalized = input.filePath.replaceAll(path48.sep, "/").replace(/^\.\//, "");
27063
+ if (index.files[normalized]) return { filePath: normalized, target: normalized };
27064
+ const suffix = Object.keys(index.files).find((file) => file.endsWith(normalized));
27065
+ if (suffix) return { filePath: suffix, target: input.filePath };
27066
+ }
27067
+ if (input.symbol) {
27068
+ const match = findSymbols(index, input.symbol, 1)[0];
27069
+ if (match) return { filePath: match.filePath, target: input.symbol };
27070
+ }
27071
+ return null;
27072
+ }
27073
+ function analyzeBlastRadius(input) {
27074
+ const index = loadOrBuildCodeContextIndex({ projectRoot: input.projectRoot, force: input.force });
27075
+ const target = resolveTargetFile(index, { filePath: input.filePath, symbol: input.symbol });
27076
+ if (!target) return null;
27077
+ const dependents = dependentsMap(index);
27078
+ const maxDepth = input.depth ?? 2;
27079
+ const impacted = /* @__PURE__ */ new Map();
27080
+ const queue = [{ filePath: target.filePath, distance: 0 }];
27081
+ impacted.set(target.filePath, { distance: 0, reason: "target" });
27082
+ while (queue.length > 0) {
27083
+ const item = queue.shift();
27084
+ if (item.distance >= maxDepth) continue;
27085
+ for (const dep of dependents.get(item.filePath) ?? []) {
27086
+ if (!impacted.has(dep)) {
27087
+ impacted.set(dep, { distance: item.distance + 1, reason: `imports ${item.filePath}` });
27088
+ queue.push({ filePath: dep, distance: item.distance + 1 });
27089
+ }
27090
+ }
27091
+ }
27092
+ const targetBase = path48.basename(target.filePath).replace(/\.[^.]+$/, "").toLowerCase();
27093
+ const symbolLower = input.symbol?.toLowerCase();
27094
+ const tests = Object.keys(index.files).filter((file) => {
27095
+ const lower = file.toLowerCase();
27096
+ return (lower.includes("test") || lower.includes("spec")) && (lower.includes(targetBase) || (symbolLower ? index.files[file].symbols.some((s) => s.text.toLowerCase().includes(symbolLower)) : false));
27097
+ });
27098
+ for (const test of tests) {
27099
+ if (!impacted.has(test)) impacted.set(test, { distance: 1, reason: "related test/spec" });
27100
+ }
27101
+ const impactedFiles = [...impacted.entries()].map(([filePath, value]) => ({ filePath, distance: value.distance, reason: value.reason })).sort((a, b) => a.distance - b.distance || a.filePath.localeCompare(b.filePath));
27102
+ const nonTestImpacted = impactedFiles.filter((f) => !f.filePath.match(/(test|spec)\./i)).length;
27103
+ const riskLevel = nonTestImpacted >= 8 ? "high" : nonTestImpacted >= 4 ? "medium" : "low";
27104
+ return {
27105
+ target: target.target,
27106
+ targetFile: target.filePath,
27107
+ impactedFiles,
27108
+ tests,
27109
+ symbolsInTarget: index.files[target.filePath]?.symbols ?? [],
27110
+ riskLevel
27111
+ };
27112
+ }
27113
+ function getCodeContextStats(options = {}) {
27114
+ const index = loadOrBuildCodeContextIndex(options);
27115
+ return {
27116
+ projectRoot: index.projectRoot,
27117
+ branch: index.branch,
27118
+ indexedAt: index.indexedAt,
27119
+ files: Object.keys(index.files).length,
27120
+ symbols: Object.values(index.files).reduce((sum, file) => sum + file.symbols.length, 0),
27121
+ imports: Object.values(index.files).reduce((sum, file) => sum + file.resolvedImports.length, 0),
27122
+ indexPath: getCodeContextIndexPath(index.projectRoot)
27123
+ };
27124
+ }
27125
+
27126
+ // src/mcp/tools/code-context.ts
27127
+ function errorResult10(text3) {
27128
+ return { content: [{ type: "text", text: text3 }], isError: true };
27129
+ }
27130
+ function jsonResult(value) {
27131
+ return { content: [{ type: "text", text: JSON.stringify(value, null, 2) }] };
27132
+ }
27133
+ function registerCodeContext(server2) {
27134
+ server2.registerTool("code_context", {
27135
+ title: "Code Context",
27136
+ description: "Persistent codebase context engine. One consolidated tool to avoid MCP bloat. Actions: index, search, trace, blast_radius, stats.",
27137
+ inputSchema: {
27138
+ action: z87.enum(["index", "search", "trace", "blast_radius", "stats"]).describe("Code context operation"),
27139
+ project_root: z87.string().optional().describe("Repository root. Defaults to current working directory."),
27140
+ query: z87.string().optional().describe("Search query for action=search"),
27141
+ symbol: z87.string().optional().describe("Symbol/function/class/type name for trace or blast_radius"),
27142
+ file_path: z87.string().optional().describe("File path for blast_radius"),
27143
+ force: z87.boolean().optional().describe("Force rebuild before answering"),
27144
+ limit: z87.coerce.number().int().min(1).max(100).optional().describe("Max results"),
27145
+ depth: z87.coerce.number().int().min(1).max(5).optional().describe("Dependent traversal depth for blast_radius"),
27146
+ max_files: z87.coerce.number().int().min(1).max(1e4).optional().describe("Max code files to index")
27147
+ }
27148
+ }, async ({ action, project_root, query, symbol, file_path, force, limit, depth, max_files }) => {
27149
+ const opts = { projectRoot: project_root, force, maxFiles: max_files };
27150
+ if (action === "index") {
27151
+ const index = buildCodeContextIndex(opts);
27152
+ return jsonResult({
27153
+ projectRoot: index.projectRoot,
27154
+ branch: index.branch,
27155
+ indexedAt: index.indexedAt,
27156
+ files: Object.keys(index.files).length,
27157
+ symbols: Object.values(index.files).reduce((sum, file) => sum + file.symbols.length, 0),
27158
+ imports: Object.values(index.files).reduce((sum, file) => sum + file.resolvedImports.length, 0)
27159
+ });
27160
+ }
27161
+ if (action === "stats") {
27162
+ return jsonResult(getCodeContextStats(opts));
27163
+ }
27164
+ if (action === "search") {
27165
+ if (!query) return errorResult10('code_context action "search" requires query');
27166
+ return jsonResult({ query, results: searchCodeContext(query, { ...opts, limit }) });
27167
+ }
27168
+ if (action === "trace") {
27169
+ if (!symbol) return errorResult10('code_context action "trace" requires symbol');
27170
+ return jsonResult(traceCodeSymbol(symbol, { ...opts, limit }));
27171
+ }
27172
+ if (action === "blast_radius") {
27173
+ if (!symbol && !file_path) return errorResult10('code_context action "blast_radius" requires symbol or file_path');
27174
+ const result2 = analyzeBlastRadius({ projectRoot: project_root, force, symbol, filePath: file_path, depth });
27175
+ if (!result2) return errorResult10(`No code context target found for ${symbol || file_path}`);
27176
+ return jsonResult(result2);
27177
+ }
27178
+ return errorResult10(`Unknown code_context action: ${String(action)}`);
27179
+ });
27180
+ }
27181
+
27182
+ // src/mcp/tools/support-inbox.ts
27183
+ import { z as z88 } from "zod";
25857
27184
  var DEFAULT_ENDPOINT = "https://askexe.com/admin/support/bug-reports";
25858
- var STATUS = z87.enum(["open", "triaged", "fixed", "closed", "wontfix"]);
27185
+ var STATUS = z88.enum(["open", "triaged", "fixed", "closed", "wontfix"]);
25859
27186
  function adminToken() {
25860
27187
  return process.env.ASKEXE_SUPPORT_ADMIN_TOKEN || process.env.EXE_SUPPORT_ADMIN_TOKEN;
25861
27188
  }
@@ -25894,9 +27221,9 @@ function registerListBugReports(server2) {
25894
27221
  title: "List Bug Reports",
25895
27222
  description: "AskExe-internal only: list incoming customer bug reports from the support inbox.",
25896
27223
  inputSchema: {
25897
- status: z87.enum(["all", "open", "triaged", "fixed", "closed", "wontfix"]).default("open"),
25898
- severity: z87.enum(["p0", "p1", "p2", "p3"]).optional(),
25899
- limit: z87.number().int().min(1).max(100).default(25)
27224
+ status: z88.enum(["all", "open", "triaged", "fixed", "closed", "wontfix"]).default("open"),
27225
+ severity: z88.enum(["p0", "p1", "p2", "p3"]).optional(),
27226
+ limit: z88.number().int().min(1).max(100).default(25)
25900
27227
  }
25901
27228
  },
25902
27229
  async ({ status, severity, limit }) => {
@@ -25915,7 +27242,7 @@ function registerGetBugReport(server2) {
25915
27242
  {
25916
27243
  title: "Get Bug Report",
25917
27244
  description: "AskExe-internal only: fetch one customer bug report with full markdown payload.",
25918
- inputSchema: { id: z87.string().min(8) }
27245
+ inputSchema: { id: z88.string().min(8) }
25919
27246
  },
25920
27247
  async ({ id }) => {
25921
27248
  const data = await requestJson(`${endpoint()}/${encodeURIComponent(id)}`);
@@ -25930,12 +27257,12 @@ function registerTriageBugReport(server2) {
25930
27257
  title: "Triage Bug Report",
25931
27258
  description: "AskExe-internal only: update bug report status and link task/commit/release metadata.",
25932
27259
  inputSchema: {
25933
- id: z87.string().min(8),
27260
+ id: z88.string().min(8),
25934
27261
  status: STATUS.optional(),
25935
- triage_notes: z87.string().optional(),
25936
- linked_task_id: z87.string().optional(),
25937
- linked_commit: z87.string().optional(),
25938
- fixed_version: z87.string().optional()
27262
+ triage_notes: z88.string().optional(),
27263
+ linked_task_id: z88.string().optional(),
27264
+ linked_commit: z88.string().optional(),
27265
+ fixed_version: z88.string().optional()
25939
27266
  }
25940
27267
  },
25941
27268
  async ({ id, status, triage_notes, linked_task_id, linked_commit, fixed_version }) => {
@@ -25959,7 +27286,7 @@ var TOOL_GATES = {
25959
27286
  reminders: [],
25960
27287
  // all agents — create, list, complete, reminder
25961
27288
  "graph-read": [],
25962
- // all agents — query_relationships, get_entity_neighbors, get_hot_entities, get_graph_stats, find_similar_trajectories
27289
+ // all agents — query_relationships, get_entity_neighbors, get_hot_entities, get_graph_stats, find_similar_trajectories, code_context
25963
27290
  "graph-write": ["COO", "CTO"],
25964
27291
  // merge_entities, export_graph
25965
27292
  wiki: ["COO", "Wiki Agent"],
@@ -25998,6 +27325,7 @@ var TOOL_CATEGORIES = {
25998
27325
  registerStoreDecision: "core",
25999
27326
  registerGetDecision: "core",
26000
27327
  registerCreateBugReport: "core",
27328
+ registerCodeContext: "graph-read",
26001
27329
  registerListBugReports: "admin",
26002
27330
  registerGetBugReport: "admin",
26003
27331
  registerTriageBugReport: "admin",
@@ -26260,6 +27588,7 @@ function registerAllTools(server2) {
26260
27588
  gate("registerStoreDecision", registerStoreDecision);
26261
27589
  gate("registerGetDecision", registerGetDecision);
26262
27590
  gate("registerCreateBugReport", registerCreateBugReport);
27591
+ gate("registerCodeContext", registerCodeContext);
26263
27592
  if (process.env.ASKEXE_SUPPORT_ADMIN_TOKEN || process.env.EXE_SUPPORT_ADMIN_TOKEN) {
26264
27593
  gate("registerListBugReports", registerListBugReports);
26265
27594
  gate("registerGetBugReport", registerGetBugReport);
@@ -26342,9 +27671,9 @@ async function withTrace(toolName, fn) {
26342
27671
  return tracer.startActiveSpan(`mcp.tool.${toolName}`, async (span) => {
26343
27672
  span.setAttribute("mcp.tool.name", toolName);
26344
27673
  try {
26345
- const result = await fn();
27674
+ const result2 = await fn();
26346
27675
  span.setStatus({ code: SpanStatusCode.OK });
26347
- return result;
27676
+ return result2;
26348
27677
  } catch (err) {
26349
27678
  span.setStatus({
26350
27679
  code: SpanStatusCode.ERROR,
@@ -26429,16 +27758,16 @@ try {
26429
27758
  }
26430
27759
  }, 3e4);
26431
27760
  _ppidWatchdog.unref();
26432
- const MCP_VERSION_PATH = path48.join(os20.homedir(), ".exe-os", "mcp-version");
27761
+ const MCP_VERSION_PATH = path49.join(os20.homedir(), ".exe-os", "mcp-version");
26433
27762
  let _currentMcpVersion = null;
26434
27763
  try {
26435
- _currentMcpVersion = existsSync37(MCP_VERSION_PATH) ? readFileSync30(MCP_VERSION_PATH, "utf8").trim() : null;
27764
+ _currentMcpVersion = existsSync38(MCP_VERSION_PATH) ? readFileSync31(MCP_VERSION_PATH, "utf8").trim() : null;
26436
27765
  } catch {
26437
27766
  }
26438
27767
  const _versionWatchdog = setInterval(() => {
26439
27768
  try {
26440
- if (!existsSync37(MCP_VERSION_PATH)) return;
26441
- const diskVersion = readFileSync30(MCP_VERSION_PATH, "utf8").trim();
27769
+ if (!existsSync38(MCP_VERSION_PATH)) return;
27770
+ const diskVersion = readFileSync31(MCP_VERSION_PATH, "utf8").trim();
26442
27771
  if (_currentMcpVersion && diskVersion !== _currentMcpVersion) {
26443
27772
  process.stderr.write(
26444
27773
  `[exe-os] MCP version changed (${_currentMcpVersion} \u2192 ${diskVersion}). Hot-reloading...
@@ -26455,10 +27784,10 @@ try {
26455
27784
  _backfillTimer = setInterval(async () => {
26456
27785
  try {
26457
27786
  const client = getClient();
26458
- const result = await client.execute(
27787
+ const result2 = await client.execute(
26459
27788
  "SELECT COUNT(*) as cnt FROM memories WHERE vector IS NULL"
26460
27789
  );
26461
- const nullCount = Number(result.rows[0]?.cnt) || 0;
27790
+ const nullCount = Number(result2.rows[0]?.cnt) || 0;
26462
27791
  if (nullCount === 0) return;
26463
27792
  const { tryAcquireWorkerSlot: tryAcquireWorkerSlot2, registerWorkerPid: registerWorkerPid2 } = await Promise.resolve().then(() => (init_worker_gate(), worker_gate_exports));
26464
27793
  if (!tryAcquireWorkerSlot2()) {
@@ -26471,14 +27800,14 @@ try {
26471
27800
  `
26472
27801
  );
26473
27802
  const thisFile = fileURLToPath5(import.meta.url);
26474
- const backfillPath = path48.resolve(
26475
- path48.dirname(thisFile),
27803
+ const backfillPath = path49.resolve(
27804
+ path49.dirname(thisFile),
26476
27805
  "../bin/backfill-vectors.js"
26477
27806
  );
26478
- if (existsSync37(backfillPath)) {
27807
+ if (existsSync38(backfillPath)) {
26479
27808
  const { EXE_AI_DIR: exeDir } = await Promise.resolve().then(() => (init_config(), config_exports));
26480
- const logPath = path48.join(exeDir, "workers.log");
26481
- mkdirSync20(path48.dirname(logPath), { recursive: true });
27809
+ const logPath = path49.join(exeDir, "workers.log");
27810
+ mkdirSync21(path49.dirname(logPath), { recursive: true });
26482
27811
  let logFd = "ignore";
26483
27812
  try {
26484
27813
  logFd = openSync3(logPath, "a");