@askexenow/exe-os 0.9.68 → 0.9.69

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.
@@ -873,10 +873,10 @@ async function disposeEmbedder() {
873
873
  async function embedDirect(text3) {
874
874
  const llamaCpp = await import("node-llama-cpp");
875
875
  const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
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)) {
876
+ const { existsSync: existsSync41 } = await import("fs");
877
+ const path52 = await import("path");
878
+ const modelPath = path52.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
879
+ if (!existsSync41(modelPath)) {
880
880
  throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
881
881
  }
882
882
  const llama = await llamaCpp.getLlama();
@@ -3691,8 +3691,8 @@ function deriveMachineKey() {
3691
3691
  }
3692
3692
  function readMachineId() {
3693
3693
  try {
3694
- const { readFileSync: readFileSync32 } = __require("fs");
3695
- return readFileSync32("/etc/machine-id", "utf-8").trim();
3694
+ const { readFileSync: readFileSync34 } = __require("fs");
3695
+ return readFileSync34("/etc/machine-id", "utf-8").trim();
3696
3696
  } catch {
3697
3697
  return "";
3698
3698
  }
@@ -7267,10 +7267,10 @@ async function hybridSearch(queryText, agentId, options) {
7267
7267
  };
7268
7268
  try {
7269
7269
  const fs = await import("fs");
7270
- const path50 = await import("path");
7270
+ const path52 = await import("path");
7271
7271
  const os21 = await import("os");
7272
- const logPath = path50.join(os21.homedir(), ".exe-os", "search-quality.jsonl");
7273
- fs.mkdirSync(path50.dirname(logPath), { recursive: true });
7272
+ const logPath = path52.join(os21.homedir(), ".exe-os", "search-quality.jsonl");
7273
+ fs.mkdirSync(path52.dirname(logPath), { recursive: true });
7274
7274
  fs.appendFileSync(logPath, JSON.stringify(logEntry) + "\n");
7275
7275
  } catch {
7276
7276
  }
@@ -8223,8 +8223,8 @@ async function validateLicense(apiKey, deviceId) {
8223
8223
  }
8224
8224
  function getCacheAgeMs() {
8225
8225
  try {
8226
- const { statSync: statSync9 } = __require("fs");
8227
- const s = statSync9(CACHE_PATH);
8226
+ const { statSync: statSync10 } = __require("fs");
8227
+ const s = statSync10(CACHE_PATH);
8228
8228
  return Date.now() - s.mtimeMs;
8229
8229
  } catch {
8230
8230
  return Infinity;
@@ -8562,8 +8562,8 @@ __export(wiki_client_exports, {
8562
8562
  listDocuments: () => listDocuments,
8563
8563
  listWorkspaces: () => listWorkspaces
8564
8564
  });
8565
- async function wikiFetch(config2, path50, method = "GET", body) {
8566
- const url = `${config2.baseUrl}/api/v1${path50}`;
8565
+ async function wikiFetch(config2, path52, method = "GET", body) {
8566
+ const url = `${config2.baseUrl}/api/v1${path52}`;
8567
8567
  const headers = {
8568
8568
  Authorization: `Bearer ${config2.apiKey}`,
8569
8569
  "Content-Type": "application/json"
@@ -8596,7 +8596,7 @@ async function wikiFetch(config2, path50, method = "GET", body) {
8596
8596
  }
8597
8597
  }
8598
8598
  if (!response.ok) {
8599
- throw new Error(`Wiki API ${method} ${path50}: ${response.status} ${response.statusText}`);
8599
+ throw new Error(`Wiki API ${method} ${path52}: ${response.status} ${response.statusText}`);
8600
8600
  }
8601
8601
  return response.json();
8602
8602
  } finally {
@@ -9436,8 +9436,8 @@ function logQueue(msg) {
9436
9436
  process.stderr.write(`[intercom-queue] ${msg}
9437
9437
  `);
9438
9438
  try {
9439
- const { appendFileSync: appendFileSync3 } = __require("fs");
9440
- appendFileSync3(INTERCOM_LOG, line);
9439
+ const { appendFileSync: appendFileSync4 } = __require("fs");
9440
+ appendFileSync4(INTERCOM_LOG, line);
9441
9441
  } catch {
9442
9442
  }
9443
9443
  }
@@ -13377,14 +13377,14 @@ __export(worker_gate_exports, {
13377
13377
  tryAcquireBackfillLock: () => tryAcquireBackfillLock,
13378
13378
  tryAcquireWorkerSlot: () => tryAcquireWorkerSlot
13379
13379
  });
13380
- import { readdirSync as readdirSync8, writeFileSync as writeFileSync14, unlinkSync as unlinkSync8, mkdirSync as mkdirSync11, existsSync as existsSync24 } from "fs";
13381
- import path29 from "path";
13380
+ import { readdirSync as readdirSync8, writeFileSync as writeFileSync15, unlinkSync as unlinkSync8, mkdirSync as mkdirSync12, existsSync as existsSync26 } from "fs";
13381
+ import path31 from "path";
13382
13382
  function tryAcquireWorkerSlot() {
13383
13383
  try {
13384
- mkdirSync11(WORKER_PID_DIR, { recursive: true });
13384
+ mkdirSync12(WORKER_PID_DIR, { recursive: true });
13385
13385
  const reservationId = `res-${process.pid}-${Date.now()}`;
13386
- const reservationPath = path29.join(WORKER_PID_DIR, `${reservationId}.pid`);
13387
- writeFileSync14(reservationPath, String(process.pid));
13386
+ const reservationPath = path31.join(WORKER_PID_DIR, `${reservationId}.pid`);
13387
+ writeFileSync15(reservationPath, String(process.pid));
13388
13388
  const files = readdirSync8(WORKER_PID_DIR);
13389
13389
  let alive = 0;
13390
13390
  for (const f of files) {
@@ -13401,7 +13401,7 @@ function tryAcquireWorkerSlot() {
13401
13401
  alive++;
13402
13402
  } catch {
13403
13403
  try {
13404
- unlinkSync8(path29.join(WORKER_PID_DIR, f));
13404
+ unlinkSync8(path31.join(WORKER_PID_DIR, f));
13405
13405
  } catch {
13406
13406
  }
13407
13407
  }
@@ -13424,21 +13424,21 @@ function tryAcquireWorkerSlot() {
13424
13424
  }
13425
13425
  function registerWorkerPid(pid) {
13426
13426
  try {
13427
- mkdirSync11(WORKER_PID_DIR, { recursive: true });
13428
- writeFileSync14(path29.join(WORKER_PID_DIR, `worker-${pid}.pid`), String(pid));
13427
+ mkdirSync12(WORKER_PID_DIR, { recursive: true });
13428
+ writeFileSync15(path31.join(WORKER_PID_DIR, `worker-${pid}.pid`), String(pid));
13429
13429
  } catch {
13430
13430
  }
13431
13431
  }
13432
13432
  function cleanupWorkerPid() {
13433
13433
  try {
13434
- unlinkSync8(path29.join(WORKER_PID_DIR, `worker-${process.pid}.pid`));
13434
+ unlinkSync8(path31.join(WORKER_PID_DIR, `worker-${process.pid}.pid`));
13435
13435
  } catch {
13436
13436
  }
13437
13437
  }
13438
13438
  function tryAcquireBackfillLock() {
13439
13439
  try {
13440
- mkdirSync11(WORKER_PID_DIR, { recursive: true });
13441
- if (existsSync24(BACKFILL_LOCK)) {
13440
+ mkdirSync12(WORKER_PID_DIR, { recursive: true });
13441
+ if (existsSync26(BACKFILL_LOCK)) {
13442
13442
  try {
13443
13443
  const pid = parseInt(
13444
13444
  __require("fs").readFileSync(BACKFILL_LOCK, "utf8").trim(),
@@ -13454,7 +13454,7 @@ function tryAcquireBackfillLock() {
13454
13454
  } catch {
13455
13455
  }
13456
13456
  }
13457
- writeFileSync14(BACKFILL_LOCK, String(process.pid));
13457
+ writeFileSync15(BACKFILL_LOCK, String(process.pid));
13458
13458
  return true;
13459
13459
  } catch {
13460
13460
  return true;
@@ -13471,9 +13471,9 @@ var init_worker_gate = __esm({
13471
13471
  "src/lib/worker-gate.ts"() {
13472
13472
  "use strict";
13473
13473
  init_config();
13474
- WORKER_PID_DIR = path29.join(EXE_AI_DIR, "worker-pids");
13474
+ WORKER_PID_DIR = path31.join(EXE_AI_DIR, "worker-pids");
13475
13475
  MAX_CONCURRENT_WORKERS = 3;
13476
- BACKFILL_LOCK = path29.join(WORKER_PID_DIR, "backfill.lock");
13476
+ BACKFILL_LOCK = path31.join(WORKER_PID_DIR, "backfill.lock");
13477
13477
  }
13478
13478
  });
13479
13479
 
@@ -13484,16 +13484,16 @@ __export(key_backup_status_exports, {
13484
13484
  keyBackupMarkerPath: () => keyBackupMarkerPath,
13485
13485
  markKeyBackupConfirmed: () => markKeyBackupConfirmed
13486
13486
  });
13487
- import { existsSync as existsSync26, mkdirSync as mkdirSync12, readFileSync as readFileSync20, writeFileSync as writeFileSync15 } from "fs";
13488
- import path31 from "path";
13487
+ import { existsSync as existsSync28, mkdirSync as mkdirSync13, readFileSync as readFileSync22, writeFileSync as writeFileSync16 } from "fs";
13488
+ import path33 from "path";
13489
13489
  function keyBackupMarkerPath() {
13490
- return path31.join(EXE_AI_DIR, "key-backup-confirmed.json");
13490
+ return path33.join(EXE_AI_DIR, "key-backup-confirmed.json");
13491
13491
  }
13492
13492
  function getKeyBackupStatus() {
13493
13493
  const marker = keyBackupMarkerPath();
13494
- if (!existsSync26(marker)) return { exists: false };
13494
+ if (!existsSync28(marker)) return { exists: false };
13495
13495
  try {
13496
- const parsed = JSON.parse(readFileSync20(marker, "utf8"));
13496
+ const parsed = JSON.parse(readFileSync22(marker, "utf8"));
13497
13497
  return {
13498
13498
  exists: true,
13499
13499
  confirmedAt: parsed.confirmedAt,
@@ -13504,8 +13504,8 @@ function getKeyBackupStatus() {
13504
13504
  }
13505
13505
  }
13506
13506
  function markKeyBackupConfirmed(source) {
13507
- mkdirSync12(EXE_AI_DIR, { recursive: true, mode: 448 });
13508
- writeFileSync15(
13507
+ mkdirSync13(EXE_AI_DIR, { recursive: true, mode: 448 });
13508
+ writeFileSync16(
13509
13509
  keyBackupMarkerPath(),
13510
13510
  JSON.stringify({ confirmedAt: (/* @__PURE__ */ new Date()).toISOString(), source }, null, 2) + "\n",
13511
13511
  { mode: 384 }
@@ -13601,33 +13601,33 @@ __export(db_backup_exports, {
13601
13601
  listBackups: () => listBackups,
13602
13602
  rotateBackups: () => rotateBackups
13603
13603
  });
13604
- import { copyFileSync, existsSync as existsSync27, mkdirSync as mkdirSync13, readdirSync as readdirSync10, unlinkSync as unlinkSync9, statSync as statSync5 } from "fs";
13605
- import path32 from "path";
13604
+ import { copyFileSync, existsSync as existsSync29, mkdirSync as mkdirSync14, readdirSync as readdirSync10, unlinkSync as unlinkSync9, statSync as statSync6 } from "fs";
13605
+ import path34 from "path";
13606
13606
  function findActiveDb() {
13607
13607
  for (const name of DB_NAMES) {
13608
- const p = path32.join(EXE_AI_DIR, name);
13609
- if (existsSync27(p)) return p;
13608
+ const p = path34.join(EXE_AI_DIR, name);
13609
+ if (existsSync29(p)) return p;
13610
13610
  }
13611
13611
  return null;
13612
13612
  }
13613
13613
  function createBackup(reason = "manual") {
13614
13614
  const dbPath = findActiveDb();
13615
13615
  if (!dbPath) return null;
13616
- mkdirSync13(BACKUP_DIR, { recursive: true });
13617
- const dbName = path32.basename(dbPath, ".db");
13616
+ mkdirSync14(BACKUP_DIR, { recursive: true });
13617
+ const dbName = path34.basename(dbPath, ".db");
13618
13618
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
13619
13619
  const backupName = `${dbName}-${reason}-${timestamp}.db`;
13620
- const backupPath = path32.join(BACKUP_DIR, backupName);
13620
+ const backupPath = path34.join(BACKUP_DIR, backupName);
13621
13621
  copyFileSync(dbPath, backupPath);
13622
13622
  const walPath = dbPath + "-wal";
13623
- if (existsSync27(walPath)) {
13623
+ if (existsSync29(walPath)) {
13624
13624
  try {
13625
13625
  copyFileSync(walPath, backupPath + "-wal");
13626
13626
  } catch {
13627
13627
  }
13628
13628
  }
13629
13629
  const shmPath = dbPath + "-shm";
13630
- if (existsSync27(shmPath)) {
13630
+ if (existsSync29(shmPath)) {
13631
13631
  try {
13632
13632
  copyFileSync(shmPath, backupPath + "-shm");
13633
13633
  } catch {
@@ -13636,16 +13636,16 @@ function createBackup(reason = "manual") {
13636
13636
  return backupPath;
13637
13637
  }
13638
13638
  function rotateBackups(keepDays = DEFAULT_KEEP_DAYS) {
13639
- if (!existsSync27(BACKUP_DIR)) return 0;
13639
+ if (!existsSync29(BACKUP_DIR)) return 0;
13640
13640
  const cutoff = Date.now() - keepDays * 24 * 60 * 60 * 1e3;
13641
13641
  let deleted = 0;
13642
13642
  try {
13643
13643
  const files = readdirSync10(BACKUP_DIR);
13644
13644
  for (const file of files) {
13645
13645
  if (!file.endsWith(".db") && !file.endsWith(".db-wal") && !file.endsWith(".db-shm")) continue;
13646
- const filePath = path32.join(BACKUP_DIR, file);
13646
+ const filePath = path34.join(BACKUP_DIR, file);
13647
13647
  try {
13648
- const stat = statSync5(filePath);
13648
+ const stat = statSync6(filePath);
13649
13649
  if (stat.mtimeMs < cutoff) {
13650
13650
  unlinkSync9(filePath);
13651
13651
  deleted++;
@@ -13658,12 +13658,12 @@ function rotateBackups(keepDays = DEFAULT_KEEP_DAYS) {
13658
13658
  return deleted;
13659
13659
  }
13660
13660
  function listBackups() {
13661
- if (!existsSync27(BACKUP_DIR)) return [];
13661
+ if (!existsSync29(BACKUP_DIR)) return [];
13662
13662
  try {
13663
13663
  const files = readdirSync10(BACKUP_DIR).filter((f) => f.endsWith(".db") && !f.endsWith("-wal") && !f.endsWith("-shm"));
13664
13664
  return files.map((name) => {
13665
- const p = path32.join(BACKUP_DIR, name);
13666
- const stat = statSync5(p);
13665
+ const p = path34.join(BACKUP_DIR, name);
13666
+ const stat = statSync6(p);
13667
13667
  return { path: p, name, size: stat.size, date: stat.mtime };
13668
13668
  }).sort((a, b) => b.date.getTime() - a.date.getTime());
13669
13669
  } catch {
@@ -13687,7 +13687,7 @@ var init_db_backup = __esm({
13687
13687
  "src/lib/db-backup.ts"() {
13688
13688
  "use strict";
13689
13689
  init_config();
13690
- BACKUP_DIR = path32.join(EXE_AI_DIR, "backups");
13690
+ BACKUP_DIR = path34.join(EXE_AI_DIR, "backups");
13691
13691
  DEFAULT_KEEP_DAYS = 3;
13692
13692
  DB_NAMES = ["memories.db", "exe-mem.db", "exe-os.db", "exe.db"];
13693
13693
  }
@@ -13712,9 +13712,9 @@ __export(crdt_sync_exports, {
13712
13712
  rebuildFromDb: () => rebuildFromDb
13713
13713
  });
13714
13714
  import * as Y from "yjs";
13715
- import { readFileSync as readFileSync22, writeFileSync as writeFileSync16, existsSync as existsSync29, mkdirSync as mkdirSync14, unlinkSync as unlinkSync10 } from "fs";
13716
- import path34 from "path";
13717
- import { homedir as homedir5 } from "os";
13715
+ import { readFileSync as readFileSync24, writeFileSync as writeFileSync17, existsSync as existsSync31, mkdirSync as mkdirSync15, unlinkSync as unlinkSync10 } from "fs";
13716
+ import path36 from "path";
13717
+ import { homedir as homedir6 } from "os";
13718
13718
  function getStatePath() {
13719
13719
  return _statePathOverride ?? DEFAULT_STATE_PATH;
13720
13720
  }
@@ -13725,9 +13725,9 @@ function initCrdtDoc() {
13725
13725
  if (doc) return doc;
13726
13726
  doc = new Y.Doc();
13727
13727
  const sp = getStatePath();
13728
- if (existsSync29(sp)) {
13728
+ if (existsSync31(sp)) {
13729
13729
  try {
13730
- const state = readFileSync22(sp);
13730
+ const state = readFileSync24(sp);
13731
13731
  Y.applyUpdate(doc, new Uint8Array(state));
13732
13732
  } catch {
13733
13733
  console.warn("[crdt-sync] WARN: corrupted state file, rebuilding from DB");
@@ -13869,10 +13869,10 @@ function persistState() {
13869
13869
  if (!doc) return;
13870
13870
  try {
13871
13871
  const sp = getStatePath();
13872
- const dir = path34.dirname(sp);
13873
- if (!existsSync29(dir)) mkdirSync14(dir, { recursive: true });
13872
+ const dir = path36.dirname(sp);
13873
+ if (!existsSync31(dir)) mkdirSync15(dir, { recursive: true });
13874
13874
  const state = Y.encodeStateAsUpdate(doc);
13875
- writeFileSync16(sp, Buffer.from(state));
13875
+ writeFileSync17(sp, Buffer.from(state));
13876
13876
  } catch {
13877
13877
  }
13878
13878
  }
@@ -13913,7 +13913,7 @@ var DEFAULT_STATE_PATH, _statePathOverride, doc;
13913
13913
  var init_crdt_sync = __esm({
13914
13914
  "src/lib/crdt-sync.ts"() {
13915
13915
  "use strict";
13916
- DEFAULT_STATE_PATH = path34.join(homedir5(), ".exe-os", "crdt-state.bin");
13916
+ DEFAULT_STATE_PATH = path36.join(homedir6(), ".exe-os", "crdt-state.bin");
13917
13917
  _statePathOverride = null;
13918
13918
  doc = null;
13919
13919
  }
@@ -13926,10 +13926,10 @@ init_database();
13926
13926
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
13927
13927
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
13928
13928
  import { spawn as spawn4 } from "child_process";
13929
- import { existsSync as existsSync38, openSync as openSync3, mkdirSync as mkdirSync21, closeSync as closeSync3, readFileSync as readFileSync31 } from "fs";
13930
- import path49 from "path";
13929
+ import { existsSync as existsSync40, openSync as openSync4, mkdirSync as mkdirSync22, closeSync as closeSync4, readFileSync as readFileSync33 } from "fs";
13930
+ import path51 from "path";
13931
13931
  import os20 from "os";
13932
- import { fileURLToPath as fileURLToPath5 } from "url";
13932
+ import { fileURLToPath as fileURLToPath6 } from "url";
13933
13933
 
13934
13934
  // src/mcp/tools/memory.ts
13935
13935
  import { z as z10 } from "zod";
@@ -15313,10 +15313,10 @@ function registerCreateTask(server2) {
15313
15313
  skipDispatch: true
15314
15314
  });
15315
15315
  try {
15316
- const { existsSync: existsSync39, mkdirSync: mkdirSync22, writeFileSync: writeFileSync23 } = await import("fs");
15316
+ const { existsSync: existsSync41, mkdirSync: mkdirSync23, writeFileSync: writeFileSync24 } = await import("fs");
15317
15317
  const { identityPath: identityPath2 } = await Promise.resolve().then(() => (init_identity(), identity_exports));
15318
15318
  const idPath = identityPath2(assigned_to);
15319
- if (!existsSync39(idPath)) {
15319
+ if (!existsSync41(idPath)) {
15320
15320
  const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
15321
15321
  const employees = await loadEmployees2();
15322
15322
  const emp = employees.find((e) => e.name === assigned_to);
@@ -15325,8 +15325,8 @@ function registerCreateTask(server2) {
15325
15325
  const template = getTemplateForTitle2(emp.role);
15326
15326
  if (template) {
15327
15327
  const dir = (await import("path")).dirname(idPath);
15328
- if (!existsSync39(dir)) mkdirSync22(dir, { recursive: true });
15329
- writeFileSync23(idPath, template.replace(/^agent_id: \w+/m, `agent_id: ${assigned_to}`), "utf-8");
15328
+ if (!existsSync41(dir)) mkdirSync23(dir, { recursive: true });
15329
+ writeFileSync24(idPath, template.replace(/^agent_id: \w+/m, `agent_id: ${assigned_to}`), "utf-8");
15330
15330
  }
15331
15331
  }
15332
15332
  }
@@ -18288,12 +18288,12 @@ function registerExportGraph(server2) {
18288
18288
  }
18289
18289
  const html = await exportGraphHTML(client);
18290
18290
  const fs = await import("fs");
18291
- const path50 = await import("path");
18291
+ const path52 = await import("path");
18292
18292
  const os21 = await import("os");
18293
- const outDir = path50.join(os21.homedir(), ".exe-os", "exports");
18293
+ const outDir = path52.join(os21.homedir(), ".exe-os", "exports");
18294
18294
  fs.mkdirSync(outDir, { recursive: true });
18295
18295
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
18296
- const filePath = path50.join(outDir, `graph-${timestamp}.html`);
18296
+ const filePath = path52.join(outDir, `graph-${timestamp}.html`);
18297
18297
  fs.writeFileSync(filePath, html, "utf-8");
18298
18298
  return {
18299
18299
  content: [
@@ -18808,7 +18808,7 @@ function registerGraph(server2) {
18808
18808
  }
18809
18809
 
18810
18810
  // src/mcp/tools/config.ts
18811
- import { z as z73 } from "zod";
18811
+ import { z as z74 } from "zod";
18812
18812
 
18813
18813
  // src/mcp/tools/set-agent-config.ts
18814
18814
  init_active_agent();
@@ -19346,10 +19346,133 @@ function registerGetSessionKills(server2) {
19346
19346
 
19347
19347
  // src/mcp/tools/get-daemon-health.ts
19348
19348
  import { z as z53 } from "zod";
19349
- import { existsSync as existsSync22, readFileSync as readFileSync18 } from "fs";
19350
- import path28 from "path";
19349
+ import { existsSync as existsSync23, readFileSync as readFileSync19 } from "fs";
19350
+ import path29 from "path";
19351
19351
  import { homedir as homedir3 } from "os";
19352
- var PID_PATH2 = path28.join(homedir3(), ".exe-os", "exed.pid");
19352
+
19353
+ // src/lib/mcp-transport-health.ts
19354
+ init_config();
19355
+ import { appendFileSync as appendFileSync2, closeSync as closeSync2, existsSync as existsSync22, mkdirSync as mkdirSync11, openSync as openSync2, readFileSync as readFileSync18, readSync, statSync as statSync5, writeFileSync as writeFileSync13 } from "fs";
19356
+ import path28 from "path";
19357
+ import { fileURLToPath as fileURLToPath3 } from "url";
19358
+ var MCP_HTTP_EVENTS_PATH = path28.join(EXE_AI_DIR, "mcp-http-events.jsonl");
19359
+ var MCP_MONITOR_DIR = path28.join(EXE_AI_DIR, "monitor");
19360
+ var MCP_TRANSPORT_SUMMARY_PATH = path28.join(MCP_MONITOR_DIR, "mcp-transport-summary.json");
19361
+ var DEFAULT_EVENT_READ_BYTES = 256 * 1024;
19362
+ var DEFAULT_EVENT_MAX_BYTES = 1024 * 1024;
19363
+ var EVENT_READ_BYTES = parsePositiveInt(process.env.EXE_MCP_HTTP_EVENT_READ_BYTES, DEFAULT_EVENT_READ_BYTES);
19364
+ var EVENT_MAX_BYTES = parsePositiveInt(process.env.EXE_MCP_HTTP_EVENT_MAX_BYTES, DEFAULT_EVENT_MAX_BYTES);
19365
+ function parsePositiveInt(value, fallback) {
19366
+ if (!value) return fallback;
19367
+ const parsed = Number.parseInt(value, 10);
19368
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
19369
+ }
19370
+ function readTailText(filePath, maxBytes) {
19371
+ const stats = statSync5(filePath);
19372
+ if (stats.size <= maxBytes) return readFileSync18(filePath, "utf8");
19373
+ const fd = openSync2(filePath, "r");
19374
+ try {
19375
+ const buffer = Buffer.allocUnsafe(maxBytes);
19376
+ readSync(fd, buffer, 0, maxBytes, stats.size - maxBytes);
19377
+ const text3 = buffer.toString("utf8");
19378
+ const firstNewline = text3.indexOf("\n");
19379
+ return firstNewline >= 0 ? text3.slice(firstNewline + 1) : text3;
19380
+ } finally {
19381
+ closeSync2(fd);
19382
+ }
19383
+ }
19384
+ function readPackageVersion() {
19385
+ let dir = path28.dirname(fileURLToPath3(import.meta.url));
19386
+ const { root } = path28.parse(dir);
19387
+ while (dir !== root) {
19388
+ const pkgPath = path28.join(dir, "package.json");
19389
+ if (existsSync22(pkgPath)) {
19390
+ try {
19391
+ const parsed = JSON.parse(readFileSync18(pkgPath, "utf8"));
19392
+ return parsed.version ?? "unknown";
19393
+ } catch {
19394
+ return "unknown";
19395
+ }
19396
+ }
19397
+ dir = path28.dirname(dir);
19398
+ }
19399
+ return "unknown";
19400
+ }
19401
+ function parseMcpHttpEventLines(raw, limit = 200) {
19402
+ const lines = raw.trim().split("\n").filter(Boolean).slice(-limit);
19403
+ const events = [];
19404
+ for (const line of lines) {
19405
+ try {
19406
+ events.push(JSON.parse(line));
19407
+ } catch {
19408
+ }
19409
+ }
19410
+ return events;
19411
+ }
19412
+ function readMcpHttpEvents(limit = 200) {
19413
+ if (!existsSync22(MCP_HTTP_EVENTS_PATH)) return [];
19414
+ const raw = readTailText(MCP_HTTP_EVENTS_PATH, EVENT_READ_BYTES);
19415
+ return parseMcpHttpEventLines(raw, limit);
19416
+ }
19417
+ function summarizeMcpTransport(events = readMcpHttpEvents()) {
19418
+ const lastServerStartIndex = events.map((event) => event.message).lastIndexOf("server_started");
19419
+ const scopedEvents = lastServerStartIndex >= 0 ? events.slice(lastServerStartIndex) : events;
19420
+ const activeSessionEvent = [...scopedEvents].reverse().find((event) => typeof event.activeSessions === "number");
19421
+ const successfulToolCalls = scopedEvents.filter((event) => event.message === "tool_call_ok");
19422
+ const lastSuccessfulToolCall = successfulToolCalls.at(-1) ?? null;
19423
+ const summary = {
19424
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
19425
+ version: readPackageVersion(),
19426
+ scope: "local",
19427
+ privacy: "metadata_only",
19428
+ eventLogPath: MCP_HTTP_EVENTS_PATH,
19429
+ activeSessions: activeSessionEvent?.activeSessions ?? null,
19430
+ sessionsCreated: scopedEvents.filter((event) => event.message === "session_initialized").length,
19431
+ sessionsClosed: scopedEvents.filter((event) => event.message === "session_closed").length,
19432
+ missingSessionErrors: scopedEvents.filter((event) => event.message?.includes("missing MCP session")).length,
19433
+ staleSessionErrors: scopedEvents.filter((event) => event.message?.includes("stale or unknown")).length,
19434
+ transportErrors: scopedEvents.filter((event) => event.level === "warn" || event.level === "error").length,
19435
+ lastSuccessfulHandshake: scopedEvents.filter((event) => event.message === "session_initialized").at(-1)?.timestamp ?? null,
19436
+ lastSuccessfulToolCall: lastSuccessfulToolCall?.timestamp ?? null,
19437
+ lastSuccessfulToolCallByRuntime: {},
19438
+ lastSuccessfulToolCallByAgent: {},
19439
+ lastSuccessfulToolCallByFamily: {},
19440
+ activeSessionsByRuntime: {},
19441
+ recentWarnings: scopedEvents.filter((event) => event.level === "warn" || event.level === "error").slice(-10),
19442
+ remediation: [
19443
+ "If MCP tools fail with missing/stale session, reconnect the MCP client (/mcp or restart the runtime).",
19444
+ "Do not access the database directly; MCP is the only data interface.",
19445
+ "Check get_daemon_health or exe-healthcheck for daemon/MCP endpoint status before retrying work."
19446
+ ]
19447
+ };
19448
+ const createdBySession = /* @__PURE__ */ new Map();
19449
+ for (const event of scopedEvents) {
19450
+ if (event.message === "session_initialized" && event.sessionId) createdBySession.set(event.sessionId, event);
19451
+ if ((event.message === "session_closed" || event.message === "session_expired") && event.sessionId) {
19452
+ createdBySession.delete(event.sessionId);
19453
+ }
19454
+ }
19455
+ for (const event of createdBySession.values()) {
19456
+ const runtime = event.runtime ?? "Unknown";
19457
+ summary.activeSessionsByRuntime[runtime] = (summary.activeSessionsByRuntime[runtime] ?? 0) + 1;
19458
+ }
19459
+ for (const event of successfulToolCalls) {
19460
+ if (event.runtime) summary.lastSuccessfulToolCallByRuntime[event.runtime] = event.timestamp ?? "";
19461
+ if (event.agentId) summary.lastSuccessfulToolCallByAgent[event.agentId] = event.timestamp ?? "";
19462
+ if (event.toolFamily) summary.lastSuccessfulToolCallByFamily[event.toolFamily] = event.timestamp ?? "";
19463
+ }
19464
+ return summary;
19465
+ }
19466
+ function writeMcpTransportSummary(events) {
19467
+ try {
19468
+ mkdirSync11(MCP_MONITOR_DIR, { recursive: true });
19469
+ writeFileSync13(MCP_TRANSPORT_SUMMARY_PATH, JSON.stringify(summarizeMcpTransport(events), null, 2) + "\n");
19470
+ } catch {
19471
+ }
19472
+ }
19473
+
19474
+ // src/mcp/tools/get-daemon-health.ts
19475
+ var PID_PATH2 = path29.join(homedir3(), ".exe-os", "exed.pid");
19353
19476
  function formatUptime(seconds) {
19354
19477
  const h = Math.floor(seconds / 3600);
19355
19478
  const m = Math.floor(seconds % 3600 / 60);
@@ -19360,8 +19483,8 @@ function formatUptime(seconds) {
19360
19483
  }
19361
19484
  function isDaemonAlive() {
19362
19485
  try {
19363
- if (!existsSync22(PID_PATH2)) return { alive: false, pid: null };
19364
- const pid = parseInt(readFileSync18(PID_PATH2, "utf8").trim(), 10);
19486
+ if (!existsSync23(PID_PATH2)) return { alive: false, pid: null };
19487
+ const pid = parseInt(readFileSync19(PID_PATH2, "utf8").trim(), 10);
19365
19488
  if (isNaN(pid) || pid <= 0) return { alive: false, pid: null };
19366
19489
  process.kill(pid, 0);
19367
19490
  return { alive: true, pid };
@@ -19408,6 +19531,27 @@ function registerGetDaemonHealth(server2) {
19408
19531
  lines.push(`| Uptime | ${formatUptime(health.uptime)} |`);
19409
19532
  lines.push(`| Requests served | ${health.requests_served.toLocaleString()} |`);
19410
19533
  }
19534
+ const events = readMcpHttpEvents(50);
19535
+ const summary = summarizeMcpTransport(events);
19536
+ const lastEvent = events.at(-1);
19537
+ lines.push(`| MCP HTTP events | ${events.length > 0 ? `${events.length} recent` : "none recorded"} |`);
19538
+ lines.push(`| MCP HTTP active sessions | ${summary.activeSessions ?? "unknown"} |`);
19539
+ lines.push(`| Last MCP handshake | ${summary.lastSuccessfulHandshake ?? "none"} |`);
19540
+ lines.push(`| Last MCP tool call | ${summary.lastSuccessfulToolCall ?? "none"} |`);
19541
+ lines.push(`| MCP monitor summary | ${summary.eventLogPath.replace("mcp-http-events.jsonl", "monitor/mcp-transport-summary.json")} |`);
19542
+ if (lastEvent) {
19543
+ lines.push(`| Last MCP HTTP event | ${lastEvent.timestamp ?? "unknown"} ${lastEvent.message ?? "unknown"} |`);
19544
+ }
19545
+ if (summary.recentWarnings.length > 0) {
19546
+ lines.push("\n### Recent MCP HTTP warnings");
19547
+ for (const event of summary.recentWarnings.slice(-5)) {
19548
+ lines.push(
19549
+ `- ${event.timestamp ?? "unknown"} \u2014 ${event.message ?? "unknown"} (agent=${event.agentId ?? "unknown"}, session=${event.sessionId ?? "none"})`
19550
+ );
19551
+ }
19552
+ }
19553
+ lines.push("\n### Agent remediation");
19554
+ for (const item of summary.remediation) lines.push(`- ${item}`);
19411
19555
  return {
19412
19556
  content: [{ type: "text", text: lines.join("\n") }]
19413
19557
  };
@@ -19425,24 +19569,73 @@ function registerGetDaemonHealth(server2) {
19425
19569
  );
19426
19570
  }
19427
19571
 
19572
+ // src/mcp/tools/mcp-ping.ts
19573
+ import { existsSync as existsSync24, readFileSync as readFileSync20 } from "fs";
19574
+ import path30 from "path";
19575
+ import { homedir as homedir4 } from "os";
19576
+ import { z as z54 } from "zod";
19577
+ var PID_PATH3 = path30.join(homedir4(), ".exe-os", "exed.pid");
19578
+ function isDaemonAlive2() {
19579
+ try {
19580
+ if (!existsSync24(PID_PATH3)) return { alive: false, pid: null };
19581
+ const pid = parseInt(readFileSync20(PID_PATH3, "utf8").trim(), 10);
19582
+ if (!Number.isFinite(pid) || pid <= 0) return { alive: false, pid: null };
19583
+ process.kill(pid, 0);
19584
+ return { alive: true, pid };
19585
+ } catch {
19586
+ return { alive: false, pid: null };
19587
+ }
19588
+ }
19589
+ function registerMcpPing(server2) {
19590
+ server2.registerTool(
19591
+ "mcp_ping",
19592
+ {
19593
+ title: "MCP Ping",
19594
+ description: "Safe local MCP synthetic probe: daemon liveness plus privacy-safe transport/session summary.",
19595
+ inputSchema: {
19596
+ _placeholder: z54.string().optional().describe("No input required")
19597
+ }
19598
+ },
19599
+ async () => {
19600
+ const daemon = isDaemonAlive2();
19601
+ const summary = summarizeMcpTransport();
19602
+ writeMcpTransportSummary();
19603
+ const status = daemon.alive ? "ok" : "degraded";
19604
+ return {
19605
+ content: [
19606
+ {
19607
+ type: "text",
19608
+ text: JSON.stringify({
19609
+ status,
19610
+ daemon,
19611
+ mcpTransport: summary,
19612
+ remediation: daemon.alive ? "MCP transport probe reached the server. If tools still fail, reconnect the MCP client." : "Daemon is offline. Restart exe-os/exed; do not bypass MCP or access the DB directly."
19613
+ }, null, 2)
19614
+ }
19615
+ ]
19616
+ };
19617
+ }
19618
+ );
19619
+ }
19620
+
19428
19621
  // src/mcp/tools/get-auto-wake-status.ts
19429
19622
  init_database();
19430
19623
  init_session_registry();
19431
- import { z as z54 } from "zod";
19624
+ import { z as z55 } from "zod";
19432
19625
 
19433
19626
  // src/lib/daemon-orchestration.ts
19434
19627
  init_tmux_routing();
19435
19628
  init_task_scope();
19436
19629
  init_employees();
19437
19630
  import { execSync as execSync10 } from "child_process";
19438
- import { existsSync as existsSync23, readFileSync as readFileSync19, writeFileSync as writeFileSync13 } from "fs";
19439
- import { homedir as homedir4 } from "os";
19631
+ import { existsSync as existsSync25, readFileSync as readFileSync21, writeFileSync as writeFileSync14 } from "fs";
19632
+ import { homedir as homedir5 } from "os";
19440
19633
  import { join as join3 } from "path";
19441
19634
  var IDLE_NUDGE_DEDUP_MS = Number(process.env.EXE_NUDGE_INTERVAL_MS) || 6e4;
19442
19635
  var SESSION_TTL_HOURS = Number(process.env.EXE_SESSION_TTL_HOURS) || 4;
19443
19636
  var SESSION_CONTEXT_THRESHOLD_PCT = Number(process.env.EXE_CONTEXT_KILL_PCT) || 50;
19444
19637
  var IDLE_KILL_INTERCOM_ACK_WINDOW_MS = Number(process.env.EXE_INTERCOM_ACK_WINDOW_MS) || 1e4;
19445
- var NUDGE_STATE_PATH = join3(homedir4(), ".exe-os", "review-nudge-state.json");
19638
+ var NUDGE_STATE_PATH = join3(homedir5(), ".exe-os", "review-nudge-state.json");
19446
19639
  var AUTO_WAKE_COOLDOWN_MS = 5 * 60 * 1e3;
19447
19640
  var AUTO_WAKE_MAX_RETRIES = 3;
19448
19641
 
@@ -19456,7 +19649,7 @@ function registerGetAutoWakeStatus(server2) {
19456
19649
  title: "Get Auto-Wake Status",
19457
19650
  description: "Check auto-wake status: orphaned tasks (assigned agent has no running session), tasks blocked by auto-wake retry limit, and session activity.",
19458
19651
  inputSchema: {
19459
- _placeholder: z54.string().optional().describe("No input required")
19652
+ _placeholder: z55.string().optional().describe("No input required")
19460
19653
  }
19461
19654
  },
19462
19655
  async () => {
@@ -19537,16 +19730,16 @@ function registerGetAutoWakeStatus(server2) {
19537
19730
  // src/mcp/tools/get-worker-gate.ts
19538
19731
  init_worker_gate();
19539
19732
  init_config();
19540
- import { z as z55 } from "zod";
19541
- import { readdirSync as readdirSync9, existsSync as existsSync25 } from "fs";
19542
- import path30 from "path";
19543
- var WORKER_PID_DIR2 = path30.join(EXE_AI_DIR, "worker-pids");
19733
+ import { z as z56 } from "zod";
19734
+ import { readdirSync as readdirSync9, existsSync as existsSync27 } from "fs";
19735
+ import path32 from "path";
19736
+ var WORKER_PID_DIR2 = path32.join(EXE_AI_DIR, "worker-pids");
19544
19737
  function countAliveWorkers() {
19545
19738
  let alive = 0;
19546
19739
  let stale = 0;
19547
19740
  let reservations = 0;
19548
19741
  try {
19549
- if (!existsSync25(WORKER_PID_DIR2)) return { alive: 0, stale: 0, reservations: 0 };
19742
+ if (!existsSync27(WORKER_PID_DIR2)) return { alive: 0, stale: 0, reservations: 0 };
19550
19743
  const files = readdirSync9(WORKER_PID_DIR2);
19551
19744
  for (const f of files) {
19552
19745
  if (!f.endsWith(".pid")) continue;
@@ -19575,7 +19768,7 @@ function registerGetWorkerGate(server2) {
19575
19768
  title: "Get Worker Gate",
19576
19769
  description: "Check worker concurrency gate status: how many worker slots are in use, the maximum allowed, and whether new workers can spawn.",
19577
19770
  inputSchema: {
19578
- _placeholder: z55.string().optional().describe("No input required")
19771
+ _placeholder: z56.string().optional().describe("No input required")
19579
19772
  }
19580
19773
  },
19581
19774
  async () => {
@@ -19611,20 +19804,20 @@ function registerGetWorkerGate(server2) {
19611
19804
 
19612
19805
  // src/mcp/tools/run-memory-audit.ts
19613
19806
  init_database();
19614
- import { z as z56 } from "zod";
19807
+ import { z as z57 } from "zod";
19615
19808
 
19616
19809
  // src/bin/exe-doctor.ts
19617
19810
  import os14 from "os";
19618
19811
 
19619
19812
  // src/lib/is-main.ts
19620
19813
  import { realpathSync } from "fs";
19621
- import { fileURLToPath as fileURLToPath3 } from "url";
19814
+ import { fileURLToPath as fileURLToPath4 } from "url";
19622
19815
  function isMainModule(importMetaUrl) {
19623
19816
  if (process.argv[1] == null) return false;
19624
19817
  if (process.argv[1].includes("mcp/server")) return false;
19625
19818
  try {
19626
19819
  const scriptPath = realpathSync(process.argv[1]);
19627
- const modulePath = realpathSync(fileURLToPath3(importMetaUrl));
19820
+ const modulePath = realpathSync(fileURLToPath4(importMetaUrl));
19628
19821
  return scriptPath === modulePath;
19629
19822
  } catch {
19630
19823
  return importMetaUrl === `file://${process.argv[1]}` || importMetaUrl === new URL(process.argv[1], "file://").href;
@@ -19632,9 +19825,9 @@ function isMainModule(importMetaUrl) {
19632
19825
  }
19633
19826
 
19634
19827
  // src/bin/exe-doctor.ts
19635
- import { existsSync as existsSync28, readFileSync as readFileSync21 } from "fs";
19828
+ import { existsSync as existsSync30, readFileSync as readFileSync23 } from "fs";
19636
19829
  import { spawn as spawn2 } from "child_process";
19637
- import path33 from "path";
19830
+ import path35 from "path";
19638
19831
  import { randomUUID as randomUUID5 } from "crypto";
19639
19832
 
19640
19833
  // src/lib/conflict-detector.ts
@@ -20182,7 +20375,7 @@ async function auditOrphanedProjects(client) {
20182
20375
  for (const row of result2.rows) {
20183
20376
  const name = row.project_name;
20184
20377
  const count = Number(row.cnt);
20185
- const exists = existsSync28(path33.join(home, name)) || existsSync28(path33.join(home, "..", name)) || existsSync28(path33.join(process.cwd(), "..", name));
20378
+ const exists = existsSync30(path35.join(home, name)) || existsSync30(path35.join(home, "..", name)) || existsSync30(path35.join(process.cwd(), "..", name));
20186
20379
  if (!exists) {
20187
20380
  orphans.push({ project_name: name, count });
20188
20381
  }
@@ -20190,18 +20383,18 @@ async function auditOrphanedProjects(client) {
20190
20383
  return orphans;
20191
20384
  }
20192
20385
  function auditHookHealth() {
20193
- const logPath = path33.join(
20386
+ const logPath = path35.join(
20194
20387
  process.env.HOME ?? process.env.USERPROFILE ?? "",
20195
20388
  ".exe-os",
20196
20389
  "logs",
20197
20390
  "hooks.log"
20198
20391
  );
20199
- if (!existsSync28(logPath)) {
20392
+ if (!existsSync30(logPath)) {
20200
20393
  return { logExists: false, totalLines: 0, errorsLastHour: 0, topPatterns: [] };
20201
20394
  }
20202
20395
  let content;
20203
20396
  try {
20204
- content = readFileSync21(logPath, "utf-8");
20397
+ content = readFileSync23(logPath, "utf-8");
20205
20398
  } catch {
20206
20399
  return { logExists: false, totalLines: 0, errorsLastHour: 0, topPatterns: [] };
20207
20400
  }
@@ -20230,9 +20423,9 @@ function auditHookHealth() {
20230
20423
  return { logExists: true, totalLines, errorsLastHour, topPatterns };
20231
20424
  }
20232
20425
  function safeReadJson(filePath) {
20233
- if (!existsSync28(filePath)) return null;
20426
+ if (!existsSync30(filePath)) return null;
20234
20427
  try {
20235
- return JSON.parse(readFileSync21(filePath, "utf-8"));
20428
+ return JSON.parse(readFileSync23(filePath, "utf-8"));
20236
20429
  } catch {
20237
20430
  return null;
20238
20431
  }
@@ -20326,13 +20519,13 @@ function auditHookOwnership() {
20326
20519
  const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
20327
20520
  const checkedFiles = [];
20328
20521
  const issues = [];
20329
- const claudeSettingsPath = path33.join(home, ".claude", "settings.json");
20522
+ const claudeSettingsPath = path35.join(home, ".claude", "settings.json");
20330
20523
  const claudeSettings = safeReadJson(claudeSettingsPath);
20331
20524
  if (claudeSettings) {
20332
20525
  checkedFiles.push(claudeSettingsPath);
20333
20526
  issues.push(...buildHookOwnershipIssues("claude", collectHookCommandsFromClaudeSettings(claudeSettings)));
20334
20527
  }
20335
- const codexHooksPath = path33.join(home, ".codex", "hooks.json");
20528
+ const codexHooksPath = path35.join(home, ".codex", "hooks.json");
20336
20529
  const codexHooks = safeReadJson(codexHooksPath);
20337
20530
  if (codexHooks) {
20338
20531
  checkedFiles.push(codexHooksPath);
@@ -20596,7 +20789,7 @@ async function fixNullVectors() {
20596
20789
  }
20597
20790
  }
20598
20791
  const npmRoot = (await import("child_process")).execSync("npm root -g", { encoding: "utf8" }).trim();
20599
- const backfillPath = path33.join(npmRoot, "exe-os", "dist", "bin", "backfill-vectors.js");
20792
+ const backfillPath = path35.join(npmRoot, "exe-os", "dist", "bin", "backfill-vectors.js");
20600
20793
  return new Promise((resolve, reject) => {
20601
20794
  const child = spawn2("node", [backfillPath], { stdio: "inherit" });
20602
20795
  if (child.pid) registerWorkerPid2(child.pid);
@@ -20781,8 +20974,8 @@ function registerRunMemoryAudit(server2) {
20781
20974
  title: "Run Memory Audit",
20782
20975
  description: "Run a memory health audit: total counts, per-agent breakdown, null vectors, duplicates, FTS sync status, bloated records, and conflict detection (contradictory/superseded memories).",
20783
20976
  inputSchema: {
20784
- agent_id: z56.string().optional().describe("Filter audit to a specific agent"),
20785
- project_name: z56.string().optional().describe("Filter audit to a specific project")
20977
+ agent_id: z57.string().optional().describe("Filter audit to a specific agent"),
20978
+ project_name: z57.string().optional().describe("Filter audit to a specific project")
20786
20979
  }
20787
20980
  },
20788
20981
  async ({ agent_id, project_name }) => {
@@ -20820,7 +21013,7 @@ function registerRunMemoryAudit(server2) {
20820
21013
  init_database();
20821
21014
  init_consolidation();
20822
21015
  init_config();
20823
- import { z as z57 } from "zod";
21016
+ import { z as z58 } from "zod";
20824
21017
  function registerRunConsolidation(server2) {
20825
21018
  server2.registerTool(
20826
21019
  "run_consolidation",
@@ -20828,7 +21021,7 @@ function registerRunConsolidation(server2) {
20828
21021
  title: "Run Consolidation",
20829
21022
  description: "Run memory consolidation \u2014 synthesizes unconsolidated memories into meta-insights. Use dry_run=true (default) to preview without executing.",
20830
21023
  inputSchema: {
20831
- dry_run: z57.boolean().default(true).describe("Preview mode \u2014 show what would be consolidated without doing it")
21024
+ dry_run: z58.boolean().default(true).describe("Preview mode \u2014 show what would be consolidated without doing it")
20832
21025
  }
20833
21026
  },
20834
21027
  async ({ dry_run }) => {
@@ -20896,14 +21089,14 @@ function registerRunConsolidation(server2) {
20896
21089
  }
20897
21090
 
20898
21091
  // src/mcp/tools/cloud-sync.ts
20899
- import { z as z58 } from "zod";
21092
+ import { z as z59 } from "zod";
20900
21093
 
20901
21094
  // src/lib/cloud-sync.ts
20902
21095
  init_database();
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";
21096
+ import { readFileSync as readFileSync25, writeFileSync as writeFileSync18, existsSync as existsSync32, readdirSync as readdirSync11, mkdirSync as mkdirSync16, appendFileSync as appendFileSync3, unlinkSync as unlinkSync11, openSync as openSync3, closeSync as closeSync3, statSync as statSync7 } from "fs";
20904
21097
  import crypto15 from "crypto";
20905
- import path35 from "path";
20906
- import { homedir as homedir6 } from "os";
21098
+ import path37 from "path";
21099
+ import { homedir as homedir7 } from "os";
20907
21100
 
20908
21101
  // src/lib/crypto.ts
20909
21102
  import crypto14 from "crypto";
@@ -20977,8 +21170,8 @@ function sqlSafe(v) {
20977
21170
  }
20978
21171
  function logError(msg) {
20979
21172
  try {
20980
- const logPath = path35.join(homedir6(), ".exe-os", "workers.log");
20981
- appendFileSync2(logPath, `${(/* @__PURE__ */ new Date()).toISOString()} ${msg}
21173
+ const logPath = path37.join(homedir7(), ".exe-os", "workers.log");
21174
+ appendFileSync3(logPath, `${(/* @__PURE__ */ new Date()).toISOString()} ${msg}
20982
21175
  `);
20983
21176
  } catch {
20984
21177
  }
@@ -20986,7 +21179,7 @@ function logError(msg) {
20986
21179
  var LOCALHOST_PATTERNS = /^(localhost|127\.0\.0\.1|\[::1\])$/i;
20987
21180
  var FETCH_TIMEOUT_MS2 = 3e4;
20988
21181
  var PUSH_BATCH_SIZE = 5e3;
20989
- var ROSTER_LOCK_PATH = path35.join(EXE_AI_DIR, "roster-merge.lock");
21182
+ var ROSTER_LOCK_PATH = path37.join(EXE_AI_DIR, "roster-merge.lock");
20990
21183
  var LOCK_STALE_MS = 3e4;
20991
21184
  var _pgPromise = null;
20992
21185
  var _pgFailed = false;
@@ -20995,12 +21188,12 @@ function isTruthyEnv(value) {
20995
21188
  }
20996
21189
  function loadPgClient() {
20997
21190
  if (_pgFailed) return null;
20998
- const configPath = path35.join(EXE_AI_DIR, "config.json");
21191
+ const configPath = path37.join(EXE_AI_DIR, "config.json");
20999
21192
  let cloudPostgresUrl;
21000
21193
  let configEnabled = false;
21001
21194
  try {
21002
- if (existsSync30(configPath)) {
21003
- const cfg = JSON.parse(readFileSync23(configPath, "utf8"));
21195
+ if (existsSync32(configPath)) {
21196
+ const cfg = JSON.parse(readFileSync25(configPath, "utf8"));
21004
21197
  cloudPostgresUrl = cfg.cloud?.postgresUrl;
21005
21198
  configEnabled = cfg.cloud?.syncToPostgres === true;
21006
21199
  }
@@ -21027,9 +21220,9 @@ function loadPgClient() {
21027
21220
  if (!Ctor) throw new Error(`No PrismaClient at ${explicitPath}`);
21028
21221
  return new Ctor();
21029
21222
  }
21030
- const exeDbRoot = process.env.EXE_DB_ROOT ?? path35.join(homedir6(), "exe-db");
21031
- const packagePath = path35.join(exeDbRoot, "package.json");
21032
- if (existsSync30(packagePath)) {
21223
+ const exeDbRoot = process.env.EXE_DB_ROOT ?? path37.join(homedir7(), "exe-db");
21224
+ const packagePath = path37.join(exeDbRoot, "package.json");
21225
+ if (existsSync32(packagePath)) {
21033
21226
  const req = createRequire6(packagePath);
21034
21227
  const entry = req.resolve("@prisma/client");
21035
21228
  const mod = await import(pathToFileURL6(entry).href);
@@ -21089,20 +21282,20 @@ async function pushToPostgres(records) {
21089
21282
  }
21090
21283
  async function withRosterLock(fn) {
21091
21284
  try {
21092
- const fd = openSync2(ROSTER_LOCK_PATH, "wx");
21093
- closeSync2(fd);
21094
- writeFileSync17(ROSTER_LOCK_PATH, String(Date.now()));
21285
+ const fd = openSync3(ROSTER_LOCK_PATH, "wx");
21286
+ closeSync3(fd);
21287
+ writeFileSync18(ROSTER_LOCK_PATH, String(Date.now()));
21095
21288
  } catch (err) {
21096
21289
  if (err.code === "EEXIST") {
21097
21290
  try {
21098
- const ts2 = parseInt(readFileSync23(ROSTER_LOCK_PATH, "utf-8"), 10);
21291
+ const ts2 = parseInt(readFileSync25(ROSTER_LOCK_PATH, "utf-8"), 10);
21099
21292
  if (Date.now() - ts2 < LOCK_STALE_MS) {
21100
21293
  throw new Error("Roster merge already in progress \u2014 another sync is running");
21101
21294
  }
21102
21295
  unlinkSync11(ROSTER_LOCK_PATH);
21103
- const fd = openSync2(ROSTER_LOCK_PATH, "wx");
21104
- closeSync2(fd);
21105
- writeFileSync17(ROSTER_LOCK_PATH, String(Date.now()));
21296
+ const fd = openSync3(ROSTER_LOCK_PATH, "wx");
21297
+ closeSync3(fd);
21298
+ writeFileSync18(ROSTER_LOCK_PATH, String(Date.now()));
21106
21299
  } catch (retryErr) {
21107
21300
  if (retryErr instanceof Error && retryErr.message.includes("already in progress")) throw retryErr;
21108
21301
  throw new Error("Roster merge already in progress \u2014 another sync is running");
@@ -21532,8 +21725,8 @@ async function cloudSync(config2) {
21532
21725
  try {
21533
21726
  const employees = await loadEmployees();
21534
21727
  rosterResult.employees = employees.length;
21535
- const idDir = path35.join(EXE_AI_DIR, "identity");
21536
- if (existsSync30(idDir)) {
21728
+ const idDir = path37.join(EXE_AI_DIR, "identity");
21729
+ if (existsSync32(idDir)) {
21537
21730
  rosterResult.identities = readdirSync11(idDir).filter((f) => f.endsWith(".md")).length;
21538
21731
  }
21539
21732
  } catch {
@@ -21543,10 +21736,10 @@ async function cloudSync(config2) {
21543
21736
  const { getLatestBackup: getLatestBackup2 } = await Promise.resolve().then(() => (init_db_backup(), db_backup_exports));
21544
21737
  const latestBackup = getLatestBackup2();
21545
21738
  if (latestBackup) {
21546
- const backupSize = statSync6(latestBackup).size;
21739
+ const backupSize = statSync7(latestBackup).size;
21547
21740
  const MAX_CLOUD_BACKUP_BYTES = 50 * 1024 * 1024;
21548
21741
  if (backupSize <= MAX_CLOUD_BACKUP_BYTES) {
21549
- const backupData = readFileSync23(latestBackup);
21742
+ const backupData = readFileSync25(latestBackup);
21550
21743
  const deviceId = loadDeviceId() ?? "unknown";
21551
21744
  const encrypted = encryptSyncBlob(backupData);
21552
21745
  const backupRes = await fetchWithRetry(`${config2.endpoint}/sync/push-db-backup`, {
@@ -21554,7 +21747,7 @@ async function cloudSync(config2) {
21554
21747
  headers: { "Content-Type": "application/json", Authorization: `Bearer ${config2.apiKey}` },
21555
21748
  body: JSON.stringify({
21556
21749
  device_id: deviceId,
21557
- filename: path35.basename(latestBackup),
21750
+ filename: path37.basename(latestBackup),
21558
21751
  blob: encrypted,
21559
21752
  size: backupData.length
21560
21753
  })
@@ -21579,49 +21772,49 @@ async function cloudSync(config2) {
21579
21772
  roster: rosterResult
21580
21773
  };
21581
21774
  }
21582
- var ROSTER_DELETIONS_PATH = path35.join(EXE_AI_DIR, "roster-deletions.json");
21775
+ var ROSTER_DELETIONS_PATH = path37.join(EXE_AI_DIR, "roster-deletions.json");
21583
21776
  function consumeRosterDeletions() {
21584
21777
  try {
21585
- if (!existsSync30(ROSTER_DELETIONS_PATH)) return [];
21586
- const deletions = JSON.parse(readFileSync23(ROSTER_DELETIONS_PATH, "utf-8"));
21587
- writeFileSync17(ROSTER_DELETIONS_PATH, "[]");
21778
+ if (!existsSync32(ROSTER_DELETIONS_PATH)) return [];
21779
+ const deletions = JSON.parse(readFileSync25(ROSTER_DELETIONS_PATH, "utf-8"));
21780
+ writeFileSync18(ROSTER_DELETIONS_PATH, "[]");
21588
21781
  return deletions;
21589
21782
  } catch {
21590
21783
  return [];
21591
21784
  }
21592
21785
  }
21593
21786
  function buildRosterBlob(paths) {
21594
- const rosterPath = paths?.rosterPath ?? path35.join(EXE_AI_DIR, "exe-employees.json");
21595
- const identityDir = paths?.identityDir ?? path35.join(EXE_AI_DIR, "identity");
21596
- const configPath = paths?.configPath ?? path35.join(EXE_AI_DIR, "config.json");
21787
+ const rosterPath = paths?.rosterPath ?? path37.join(EXE_AI_DIR, "exe-employees.json");
21788
+ const identityDir = paths?.identityDir ?? path37.join(EXE_AI_DIR, "identity");
21789
+ const configPath = paths?.configPath ?? path37.join(EXE_AI_DIR, "config.json");
21597
21790
  let roster = [];
21598
- if (existsSync30(rosterPath)) {
21791
+ if (existsSync32(rosterPath)) {
21599
21792
  try {
21600
- roster = JSON.parse(readFileSync23(rosterPath, "utf-8"));
21793
+ roster = JSON.parse(readFileSync25(rosterPath, "utf-8"));
21601
21794
  } catch {
21602
21795
  }
21603
21796
  }
21604
21797
  const identities = {};
21605
- if (existsSync30(identityDir)) {
21798
+ if (existsSync32(identityDir)) {
21606
21799
  for (const file of readdirSync11(identityDir).filter((f) => f.endsWith(".md"))) {
21607
21800
  try {
21608
- identities[file] = readFileSync23(path35.join(identityDir, file), "utf-8");
21801
+ identities[file] = readFileSync25(path37.join(identityDir, file), "utf-8");
21609
21802
  } catch {
21610
21803
  }
21611
21804
  }
21612
21805
  }
21613
21806
  let config2;
21614
- if (existsSync30(configPath)) {
21807
+ if (existsSync32(configPath)) {
21615
21808
  try {
21616
- config2 = JSON.parse(readFileSync23(configPath, "utf-8"));
21809
+ config2 = JSON.parse(readFileSync25(configPath, "utf-8"));
21617
21810
  } catch {
21618
21811
  }
21619
21812
  }
21620
21813
  let agentConfig;
21621
- const agentConfigPath = path35.join(EXE_AI_DIR, "agent-config.json");
21622
- if (existsSync30(agentConfigPath)) {
21814
+ const agentConfigPath = path37.join(EXE_AI_DIR, "agent-config.json");
21815
+ if (existsSync32(agentConfigPath)) {
21623
21816
  try {
21624
- agentConfig = JSON.parse(readFileSync23(agentConfigPath, "utf-8"));
21817
+ agentConfig = JSON.parse(readFileSync25(agentConfigPath, "utf-8"));
21625
21818
  } catch {
21626
21819
  }
21627
21820
  }
@@ -21697,24 +21890,24 @@ async function cloudPullRoster(config2) {
21697
21890
  }
21698
21891
  }
21699
21892
  function mergeConfig(remoteConfig, configPath) {
21700
- const cfgPath = configPath ?? path35.join(EXE_AI_DIR, "config.json");
21893
+ const cfgPath = configPath ?? path37.join(EXE_AI_DIR, "config.json");
21701
21894
  let local = {};
21702
- if (existsSync30(cfgPath)) {
21895
+ if (existsSync32(cfgPath)) {
21703
21896
  try {
21704
- local = JSON.parse(readFileSync23(cfgPath, "utf-8"));
21897
+ local = JSON.parse(readFileSync25(cfgPath, "utf-8"));
21705
21898
  } catch {
21706
21899
  }
21707
21900
  }
21708
21901
  const merged = { ...remoteConfig, ...local };
21709
- const dir = path35.dirname(cfgPath);
21902
+ const dir = path37.dirname(cfgPath);
21710
21903
  ensurePrivateDirSync(dir);
21711
- writeFileSync17(cfgPath, JSON.stringify(merged, null, 2), "utf-8");
21904
+ writeFileSync18(cfgPath, JSON.stringify(merged, null, 2), "utf-8");
21712
21905
  enforcePrivateFileSync(cfgPath);
21713
21906
  }
21714
21907
  async function mergeRosterFromRemote(remote, paths) {
21715
21908
  return withRosterLock(async () => {
21716
21909
  const rosterPath = paths?.rosterPath ?? void 0;
21717
- const identityDir = paths?.identityDir ?? path35.join(EXE_AI_DIR, "identity");
21910
+ const identityDir = paths?.identityDir ?? path37.join(EXE_AI_DIR, "identity");
21718
21911
  const localEmployees = await loadEmployees(rosterPath);
21719
21912
  const localNames = new Set(localEmployees.map((e) => e.name));
21720
21913
  let added = 0;
@@ -21735,15 +21928,15 @@ async function mergeRosterFromRemote(remote, paths) {
21735
21928
  ) ?? lookupKey;
21736
21929
  const remoteIdentity = remote.identities[matchedKey];
21737
21930
  if (remoteIdentity) {
21738
- if (!existsSync30(identityDir)) mkdirSync15(identityDir, { recursive: true });
21739
- const idPath = path35.join(identityDir, `${remoteEmp.name}.md`);
21931
+ if (!existsSync32(identityDir)) mkdirSync16(identityDir, { recursive: true });
21932
+ const idPath = path37.join(identityDir, `${remoteEmp.name}.md`);
21740
21933
  let localIdentity = null;
21741
21934
  try {
21742
- localIdentity = existsSync30(idPath) ? readFileSync23(idPath, "utf-8") : null;
21935
+ localIdentity = existsSync32(idPath) ? readFileSync25(idPath, "utf-8") : null;
21743
21936
  } catch {
21744
21937
  }
21745
21938
  if (localIdentity !== remoteIdentity) {
21746
- writeFileSync17(idPath, remoteIdentity, "utf-8");
21939
+ writeFileSync18(idPath, remoteIdentity, "utf-8");
21747
21940
  identitiesUpdated++;
21748
21941
  }
21749
21942
  }
@@ -21769,17 +21962,17 @@ async function mergeRosterFromRemote(remote, paths) {
21769
21962
  }
21770
21963
  if (remote.agentConfig && Object.keys(remote.agentConfig).length > 0) {
21771
21964
  try {
21772
- const agentConfigPath = path35.join(EXE_AI_DIR, "agent-config.json");
21965
+ const agentConfigPath = path37.join(EXE_AI_DIR, "agent-config.json");
21773
21966
  let local = {};
21774
- if (existsSync30(agentConfigPath)) {
21967
+ if (existsSync32(agentConfigPath)) {
21775
21968
  try {
21776
- local = JSON.parse(readFileSync23(agentConfigPath, "utf-8"));
21969
+ local = JSON.parse(readFileSync25(agentConfigPath, "utf-8"));
21777
21970
  } catch {
21778
21971
  }
21779
21972
  }
21780
21973
  const merged = { ...remote.agentConfig, ...local };
21781
- ensurePrivateDirSync(path35.dirname(agentConfigPath));
21782
- writeFileSync17(agentConfigPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
21974
+ ensurePrivateDirSync(path37.dirname(agentConfigPath));
21975
+ writeFileSync18(agentConfigPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
21783
21976
  enforcePrivateFileSync(agentConfigPath);
21784
21977
  } catch {
21785
21978
  }
@@ -22290,9 +22483,9 @@ function registerCloudSync(server2) {
22290
22483
  title: "Cloud Sync",
22291
22484
  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.",
22292
22485
  inputSchema: {
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".')
22486
+ action: z59.enum(["status", "sync", "reupload"]).default("sync").describe("Cloud operation. status is read-only; sync is normal sync-now; reupload repairs cloud after key rotation."),
22487
+ force: z59.boolean().default(false).describe("Reserved for sync compatibility; normal cloud sync already runs when requested."),
22488
+ confirm_local_db_source_of_truth: z59.string().optional().describe('Required for action=reupload. Must exactly equal "LOCAL DB IS SOURCE OF TRUTH".')
22296
22489
  }
22297
22490
  },
22298
22491
  async ({ action = "sync", confirm_local_db_source_of_truth }) => {
@@ -22364,7 +22557,7 @@ function registerCloudSync(server2) {
22364
22557
  }
22365
22558
 
22366
22559
  // src/mcp/tools/orchestration-phase.ts
22367
- import { z as z59 } from "zod";
22560
+ import { z as z60 } from "zod";
22368
22561
 
22369
22562
  // src/lib/orchestration-phase.ts
22370
22563
  init_config();
@@ -22450,8 +22643,8 @@ function registerOrchestrationPhase(server2) {
22450
22643
  title: "Orchestration Phase",
22451
22644
  description: "View or change the customer-owned orchestration maturity phase. MCP parity for `exe-os org phase`, `exe-os org unlock executives`, and `exe-os org unlock parallel`. This is a recommendation layer, not a blocker; it never exposes recovery phrases or secrets.",
22452
22645
  inputSchema: {
22453
- action: z59.enum(["status", "set", "unlock_executives", "unlock_parallel"]).default("status"),
22454
- phase: z59.enum(["phase_1_coo", "phase_2_executives", "phase_3_parallel_org", "1", "2", "3"]).optional().describe("Phase to set when action='set'.")
22646
+ action: z60.enum(["status", "set", "unlock_executives", "unlock_parallel"]).default("status"),
22647
+ phase: z60.enum(["phase_1_coo", "phase_2_executives", "phase_3_parallel_org", "1", "2", "3"]).optional().describe("Phase to set when action='set'.")
22455
22648
  }
22456
22649
  },
22457
22650
  async ({ action = "status", phase }) => {
@@ -22492,7 +22685,7 @@ function registerOrchestrationPhase(server2) {
22492
22685
 
22493
22686
  // src/mcp/tools/backup-vps.ts
22494
22687
  init_keychain();
22495
- import { z as z60 } from "zod";
22688
+ import { z as z61 } from "zod";
22496
22689
 
22497
22690
  // src/lib/vps-backup.ts
22498
22691
  import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
@@ -22817,43 +23010,43 @@ function registerBackupVps(server2) {
22817
23010
  {
22818
23011
  title: "VPS Backup",
22819
23012
  description: "Run VPS Postgres backup/restore workflows and check status.",
22820
- inputSchema: z60.discriminatedUnion("action", [
22821
- z60.object({
22822
- action: z60.literal("backup"),
22823
- databaseUrl: z60.string().min(1).describe("Postgres DATABASE_URL to dump from"),
22824
- encryptionKeyB64: z60.string().min(1).max(4096).optional().describe(
23013
+ inputSchema: z61.discriminatedUnion("action", [
23014
+ z61.object({
23015
+ action: z61.literal("backup"),
23016
+ databaseUrl: z61.string().min(1).describe("Postgres DATABASE_URL to dump from"),
23017
+ encryptionKeyB64: z61.string().min(1).max(4096).optional().describe(
22825
23018
  "Base64 AES-256 key (defaults to local master key if omitted)"
22826
23019
  ),
22827
- r2Bucket: z60.string().min(1).describe("R2 bucket name"),
22828
- r2Endpoint: z60.string().min(1).describe("R2 endpoint URL"),
22829
- r2AccessKeyId: z60.string().min(1).describe("R2 access key ID"),
22830
- r2SecretAccessKey: z60.string().min(1).describe("R2 secret access key")
23020
+ r2Bucket: z61.string().min(1).describe("R2 bucket name"),
23021
+ r2Endpoint: z61.string().min(1).describe("R2 endpoint URL"),
23022
+ r2AccessKeyId: z61.string().min(1).describe("R2 access key ID"),
23023
+ r2SecretAccessKey: z61.string().min(1).describe("R2 secret access key")
22831
23024
  }),
22832
- z60.object({
22833
- action: z60.literal("restore"),
22834
- databaseUrl: z60.string().min(1).describe("Target Postgres DATABASE_URL for restore"),
22835
- backupKey: z60.string().min(1).describe("R2 object key to restore from"),
22836
- encryptionKeyB64: z60.string().min(1).max(4096).optional().describe(
23025
+ z61.object({
23026
+ action: z61.literal("restore"),
23027
+ databaseUrl: z61.string().min(1).describe("Target Postgres DATABASE_URL for restore"),
23028
+ backupKey: z61.string().min(1).describe("R2 object key to restore from"),
23029
+ encryptionKeyB64: z61.string().min(1).max(4096).optional().describe(
22837
23030
  "Base64 AES-256 key (defaults to local master key if omitted)"
22838
23031
  ),
22839
- r2Bucket: z60.string().min(1).describe("R2 bucket name"),
22840
- r2Endpoint: z60.string().min(1).describe("R2 endpoint URL"),
22841
- r2AccessKeyId: z60.string().min(1).describe("R2 access key ID"),
22842
- r2SecretAccessKey: z60.string().min(1).describe("R2 secret access key")
23032
+ r2Bucket: z61.string().min(1).describe("R2 bucket name"),
23033
+ r2Endpoint: z61.string().min(1).describe("R2 endpoint URL"),
23034
+ r2AccessKeyId: z61.string().min(1).describe("R2 access key ID"),
23035
+ r2SecretAccessKey: z61.string().min(1).describe("R2 secret access key")
22843
23036
  }),
22844
- z60.object({
22845
- action: z60.literal("list"),
22846
- r2Bucket: z60.string().min(1).describe("R2 bucket name"),
22847
- r2Endpoint: z60.string().min(1).describe("R2 endpoint URL"),
22848
- r2AccessKeyId: z60.string().min(1).describe("R2 access key ID"),
22849
- r2SecretAccessKey: z60.string().min(1).describe("R2 secret access key")
23037
+ z61.object({
23038
+ action: z61.literal("list"),
23039
+ r2Bucket: z61.string().min(1).describe("R2 bucket name"),
23040
+ r2Endpoint: z61.string().min(1).describe("R2 endpoint URL"),
23041
+ r2AccessKeyId: z61.string().min(1).describe("R2 access key ID"),
23042
+ r2SecretAccessKey: z61.string().min(1).describe("R2 secret access key")
22850
23043
  }),
22851
- z60.object({
22852
- action: z60.literal("health"),
22853
- r2Bucket: z60.string().min(1).describe("R2 bucket name"),
22854
- r2Endpoint: z60.string().min(1).describe("R2 endpoint URL"),
22855
- r2AccessKeyId: z60.string().min(1).describe("R2 access key ID"),
22856
- r2SecretAccessKey: z60.string().min(1).describe("R2 secret access key")
23044
+ z61.object({
23045
+ action: z61.literal("health"),
23046
+ r2Bucket: z61.string().min(1).describe("R2 bucket name"),
23047
+ r2Endpoint: z61.string().min(1).describe("R2 endpoint URL"),
23048
+ r2AccessKeyId: z61.string().min(1).describe("R2 access key ID"),
23049
+ r2SecretAccessKey: z61.string().min(1).describe("R2 secret access key")
22857
23050
  })
22858
23051
  ])
22859
23052
  },
@@ -22991,11 +23184,11 @@ async function resolveEncryptionKey(providedB64) {
22991
23184
  }
22992
23185
 
22993
23186
  // src/mcp/tools/deploy-client.ts
22994
- import { z as z61 } from "zod";
23187
+ import { z as z62 } from "zod";
22995
23188
  import { execFile } from "child_process";
22996
23189
  import { promisify } from "util";
22997
- import path36 from "path";
22998
- import { existsSync as existsSync31 } from "fs";
23190
+ import path38 from "path";
23191
+ import { existsSync as existsSync33 } from "fs";
22999
23192
 
23000
23193
  // src/lib/hostinger-api.ts
23001
23194
  var DEFAULT_BASE_URL = "https://developers.hostinger.com/api/vps/v1";
@@ -23043,9 +23236,9 @@ var HostingerApiClient = class {
23043
23236
  }
23044
23237
  this.lastRequestTime = Date.now();
23045
23238
  }
23046
- async request(method, path50, body) {
23239
+ async request(method, path52, body) {
23047
23240
  await this.rateLimit();
23048
- const url = `${this.baseUrl}${path50}`;
23241
+ const url = `${this.baseUrl}${path52}`;
23049
23242
  const headers = {
23050
23243
  Authorization: `Bearer ${this.apiKey}`,
23051
23244
  "Content-Type": "application/json",
@@ -23118,8 +23311,8 @@ async function requestCloudflare(cfApiToken, zoneId, options) {
23118
23311
  }
23119
23312
  return envelope.result;
23120
23313
  }
23121
- function buildUrl(zoneId, path50 = "/dns_records", query) {
23122
- const normalizedPath = path50.startsWith("/") ? path50 : `/${path50}`;
23314
+ function buildUrl(zoneId, path52 = "/dns_records", query) {
23315
+ const normalizedPath = path52.startsWith("/") ? path52 : `/${path52}`;
23123
23316
  const url = new URL(
23124
23317
  `${CLOUDFLARE_API_BASE_URL}/zones/${zoneId}${normalizedPath}`
23125
23318
  );
@@ -23259,12 +23452,12 @@ function registerDeployClient(server2) {
23259
23452
  title: "Deploy Client",
23260
23453
  description: "Provision a Hostinger VPS and deploy exe-os for a client. Creates VPS, waits for ready state, runs Ansible playbook, verifies health.",
23261
23454
  inputSchema: {
23262
- client_name: z61.string().min(1).describe("Client name (used for hostname and identification)"),
23263
- domain: z61.string().min(1).describe("Domain name for the deployment (e.g., client.exe.ai)"),
23264
- region: z61.string().default("jakarta").describe("VPS region (default: jakarta)"),
23265
- plan: z61.string().default("kvm-2").describe("Hostinger VPS plan (default: kvm-2)"),
23266
- ssl_email: z61.string().email().describe("Email for Let's Encrypt SSL certificate"),
23267
- user_id: z61.string().min(1).describe("User/customer ID for inventory tracking")
23455
+ client_name: z62.string().min(1).describe("Client name (used for hostname and identification)"),
23456
+ domain: z62.string().min(1).describe("Domain name for the deployment (e.g., client.exe.ai)"),
23457
+ region: z62.string().default("jakarta").describe("VPS region (default: jakarta)"),
23458
+ plan: z62.string().default("kvm-2").describe("Hostinger VPS plan (default: kvm-2)"),
23459
+ ssl_email: z62.string().email().describe("Email for Let's Encrypt SSL certificate"),
23460
+ user_id: z62.string().min(1).describe("User/customer ID for inventory tracking")
23268
23461
  }
23269
23462
  },
23270
23463
  async ({ client_name, domain, region, plan, ssl_email, user_id }) => {
@@ -23332,12 +23525,12 @@ async function waitForReady(client, vpsId) {
23332
23525
  }
23333
23526
  async function runAnsiblePlaybook(vpsIp, domain, sslEmail, clientName) {
23334
23527
  const safeClientName = clientName.replace(/[^a-zA-Z0-9_-]/g, "-");
23335
- const playbookDir = path36.resolve(process.cwd(), "infrastructure", "ansible");
23336
- const playbookPath = path36.join(playbookDir, "deploy.yml");
23337
- const inventoryPath = path36.join(playbookDir, "inventory", "hosts.yml");
23338
- const clientVarsPath = path36.join(playbookDir, "vars", `${safeClientName}.yml`);
23339
- const varsDir = path36.join(playbookDir, "vars");
23340
- if (!path36.resolve(clientVarsPath).startsWith(path36.resolve(varsDir))) {
23528
+ const playbookDir = path38.resolve(process.cwd(), "infrastructure", "ansible");
23529
+ const playbookPath = path38.join(playbookDir, "deploy.yml");
23530
+ const inventoryPath = path38.join(playbookDir, "inventory", "hosts.yml");
23531
+ const clientVarsPath = path38.join(playbookDir, "vars", `${safeClientName}.yml`);
23532
+ const varsDir = path38.join(playbookDir, "vars");
23533
+ if (!path38.resolve(clientVarsPath).startsWith(path38.resolve(varsDir))) {
23341
23534
  throw new Error(`Invalid client name for vars path: ${clientName}`);
23342
23535
  }
23343
23536
  const args = [
@@ -23353,7 +23546,7 @@ async function runAnsiblePlaybook(vpsIp, domain, sslEmail, clientName) {
23353
23546
  "-e",
23354
23547
  `client_name=${safeClientName}`
23355
23548
  ];
23356
- if (existsSync31(clientVarsPath)) {
23549
+ if (existsSync33(clientVarsPath)) {
23357
23550
  args.push("-e", `@${clientVarsPath}`);
23358
23551
  }
23359
23552
  try {
@@ -23426,7 +23619,7 @@ function buildInventoryRecord(params) {
23426
23619
 
23427
23620
  // src/mcp/tools/get-license-status.ts
23428
23621
  init_license();
23429
- import { z as z62 } from "zod";
23622
+ import { z as z63 } from "zod";
23430
23623
  var FEATURES = [
23431
23624
  "cloud_sync",
23432
23625
  "external_agents",
@@ -23440,7 +23633,7 @@ function registerGetLicenseStatus(server2) {
23440
23633
  title: "Get License Status",
23441
23634
  description: "Get current license status: plan, validity, feature gates, limits, and expiry.",
23442
23635
  inputSchema: {
23443
- _dummy: z62.string().optional().describe("Unused \u2014 no input required")
23636
+ _dummy: z63.string().optional().describe("Unused \u2014 no input required")
23444
23637
  }
23445
23638
  },
23446
23639
  async () => {
@@ -23494,11 +23687,11 @@ function registerGetLicenseStatus(server2) {
23494
23687
  // src/mcp/tools/create-license.ts
23495
23688
  init_license();
23496
23689
  import os15 from "os";
23497
- import path37 from "path";
23690
+ import path39 from "path";
23498
23691
  import { randomBytes as randomBytes2, randomUUID as randomUUID6 } from "crypto";
23499
23692
  import { createRequire as createRequire3 } from "module";
23500
23693
  import { pathToFileURL as pathToFileURL3 } from "url";
23501
- import { z as z63 } from "zod";
23694
+ import { z as z64 } from "zod";
23502
23695
  var prismaPromise = null;
23503
23696
  function loadPrisma() {
23504
23697
  if (!prismaPromise) {
@@ -23510,8 +23703,8 @@ function loadPrisma() {
23510
23703
  if (!Ctor2) throw new Error(`No PrismaClient at ${explicitPath}`);
23511
23704
  return new Ctor2();
23512
23705
  }
23513
- const exeDbRoot = process.env.EXE_DB_ROOT ?? path37.join(os15.homedir(), "exe-db");
23514
- const req = createRequire3(path37.join(exeDbRoot, "package.json"));
23706
+ const exeDbRoot = process.env.EXE_DB_ROOT ?? path39.join(os15.homedir(), "exe-db");
23707
+ const req = createRequire3(path39.join(exeDbRoot, "package.json"));
23515
23708
  const entry = req.resolve("@prisma/client");
23516
23709
  const mod = await import(pathToFileURL3(entry).href);
23517
23710
  const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
@@ -23531,10 +23724,10 @@ function registerCreateLicense(server2) {
23531
23724
  title: "Create License",
23532
23725
  description: "Generate an exe_sk_* license key for a user. Stores in billing.licenses. Returns the key to give to the customer.",
23533
23726
  inputSchema: {
23534
- email: z63.string().email().describe("Customer email address"),
23535
- name: z63.string().optional().describe("Customer name"),
23536
- plan: z63.enum(["free", "pro", "team", "agency", "enterprise"]).default("pro").describe("License plan tier"),
23537
- expires_in_days: z63.number().int().positive().default(365).describe("Days until expiration (default 365)")
23727
+ email: z64.string().email().describe("Customer email address"),
23728
+ name: z64.string().optional().describe("Customer name"),
23729
+ plan: z64.enum(["free", "pro", "team", "agency", "enterprise"]).default("pro").describe("License plan tier"),
23730
+ expires_in_days: z64.number().int().positive().default(365).describe("Days until expiration (default 365)")
23538
23731
  }
23539
23732
  },
23540
23733
  async ({ email, name, plan, expires_in_days }) => {
@@ -23586,10 +23779,10 @@ Give this key to the customer. They paste it during \`exe-os setup\`.`);
23586
23779
 
23587
23780
  // src/mcp/tools/list-licenses.ts
23588
23781
  import os16 from "os";
23589
- import path38 from "path";
23782
+ import path40 from "path";
23590
23783
  import { createRequire as createRequire4 } from "module";
23591
23784
  import { pathToFileURL as pathToFileURL4 } from "url";
23592
- import { z as z64 } from "zod";
23785
+ import { z as z65 } from "zod";
23593
23786
  var prismaPromise2 = null;
23594
23787
  function loadPrisma2() {
23595
23788
  if (!prismaPromise2) {
@@ -23601,8 +23794,8 @@ function loadPrisma2() {
23601
23794
  if (!Ctor2) throw new Error(`No PrismaClient at ${explicitPath}`);
23602
23795
  return new Ctor2();
23603
23796
  }
23604
- const exeDbRoot = process.env.EXE_DB_ROOT ?? path38.join(os16.homedir(), "exe-db");
23605
- const req = createRequire4(path38.join(exeDbRoot, "package.json"));
23797
+ const exeDbRoot = process.env.EXE_DB_ROOT ?? path40.join(os16.homedir(), "exe-db");
23798
+ const req = createRequire4(path40.join(exeDbRoot, "package.json"));
23606
23799
  const entry = req.resolve("@prisma/client");
23607
23800
  const mod = await import(pathToFileURL4(entry).href);
23608
23801
  const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
@@ -23619,7 +23812,7 @@ function registerListLicenses(server2) {
23619
23812
  title: "List Licenses",
23620
23813
  description: "List all issued licenses with status (active/expired/revoked). Optionally filter by plan.",
23621
23814
  inputSchema: {
23622
- plan: z64.enum(["free", "pro", "team", "agency", "enterprise"]).optional().describe("Filter by plan tier (omit for all)")
23815
+ plan: z65.enum(["free", "pro", "team", "agency", "enterprise"]).optional().describe("Filter by plan tier (omit for all)")
23623
23816
  }
23624
23817
  },
23625
23818
  async ({ plan }) => {
@@ -23670,7 +23863,7 @@ function registerListLicenses(server2) {
23670
23863
 
23671
23864
  // src/mcp/tools/activate-license.ts
23672
23865
  init_license();
23673
- import { z as z65 } from "zod";
23866
+ import { z as z66 } from "zod";
23674
23867
  function registerActivateLicense(server2) {
23675
23868
  server2.registerTool(
23676
23869
  "activate_license",
@@ -23678,7 +23871,7 @@ function registerActivateLicense(server2) {
23678
23871
  title: "Activate License",
23679
23872
  description: "Activate an exe_sk_* license key on this device. Writes to ~/.exe-os/license.key, validates against Postgres, and caches the result.",
23680
23873
  inputSchema: {
23681
- key: z65.string().startsWith("exe_sk_").describe("License key (exe_sk_*)")
23874
+ key: z66.string().startsWith("exe_sk_").describe("License key (exe_sk_*)")
23682
23875
  }
23683
23876
  },
23684
23877
  async ({ key }) => {
@@ -23724,18 +23917,18 @@ Key saved to ~/.exe-os/license.key. Device ID: ${deviceId}`);
23724
23917
  }
23725
23918
 
23726
23919
  // src/mcp/tools/create-trigger.ts
23727
- import { z as z66 } from "zod";
23920
+ import { z as z67 } from "zod";
23728
23921
 
23729
23922
  // src/automation/trigger-engine.ts
23730
- import { readFileSync as readFileSync24, writeFileSync as writeFileSync18, existsSync as existsSync32, mkdirSync as mkdirSync16 } from "fs";
23923
+ import { readFileSync as readFileSync26, writeFileSync as writeFileSync19, existsSync as existsSync34, mkdirSync as mkdirSync17 } from "fs";
23731
23924
  import { randomUUID as randomUUID7 } from "crypto";
23732
- import path39 from "path";
23925
+ import path41 from "path";
23733
23926
  import os17 from "os";
23734
- var TRIGGERS_PATH = path39.join(os17.homedir(), ".exe-os", "triggers.json");
23927
+ var TRIGGERS_PATH = path41.join(os17.homedir(), ".exe-os", "triggers.json");
23735
23928
  function loadTriggers(project) {
23736
- if (!existsSync32(TRIGGERS_PATH)) return [];
23929
+ if (!existsSync34(TRIGGERS_PATH)) return [];
23737
23930
  try {
23738
- const raw = readFileSync24(TRIGGERS_PATH, "utf-8");
23931
+ const raw = readFileSync26(TRIGGERS_PATH, "utf-8");
23739
23932
  const all = JSON.parse(raw);
23740
23933
  if (!Array.isArray(all)) return [];
23741
23934
  if (project) {
@@ -23747,9 +23940,9 @@ function loadTriggers(project) {
23747
23940
  }
23748
23941
  }
23749
23942
  function saveTriggers(triggers) {
23750
- const dir = path39.dirname(TRIGGERS_PATH);
23751
- if (!existsSync32(dir)) mkdirSync16(dir, { recursive: true });
23752
- writeFileSync18(TRIGGERS_PATH, JSON.stringify(triggers, null, 2), "utf-8");
23943
+ const dir = path41.dirname(TRIGGERS_PATH);
23944
+ if (!existsSync34(dir)) mkdirSync17(dir, { recursive: true });
23945
+ writeFileSync19(TRIGGERS_PATH, JSON.stringify(triggers, null, 2), "utf-8");
23753
23946
  }
23754
23947
  function createNewTrigger(input) {
23755
23948
  const triggers = loadTriggers();
@@ -23905,14 +24098,14 @@ function addToCrontab(id, cron, prompt, projectDir) {
23905
24098
  }
23906
24099
 
23907
24100
  // src/mcp/tools/create-trigger.ts
23908
- var conditionSchema = z66.object({
23909
- field: z66.string().describe("Dot-path field to evaluate, e.g., 'stage' or 'amount'"),
23910
- op: z66.enum(["eq", "neq", "gt", "lt", "gte", "lte", "contains", "not_contains"]).describe("Comparison operator"),
23911
- value: z66.string().or(z66.number()).or(z66.boolean()).describe("Value to compare against")
24101
+ var conditionSchema = z67.object({
24102
+ field: z67.string().describe("Dot-path field to evaluate, e.g., 'stage' or 'amount'"),
24103
+ op: z67.enum(["eq", "neq", "gt", "lt", "gte", "lte", "contains", "not_contains"]).describe("Comparison operator"),
24104
+ value: z67.string().or(z67.number()).or(z67.boolean()).describe("Value to compare against")
23912
24105
  });
23913
- var actionSchema = z66.object({
23914
- type: z66.enum(["send_whatsapp", "send_message", "create_task", "mcp_tool"]).describe("Action type to execute"),
23915
- params: z66.record(z66.string(), z66.string()).describe(
24106
+ var actionSchema = z67.object({
24107
+ type: z67.enum(["send_whatsapp", "send_message", "create_task", "mcp_tool"]).describe("Action type to execute"),
24108
+ params: z67.record(z67.string(), z67.string()).describe(
23916
24109
  "Action parameters. Supports {{record.field}} templates for dynamic values."
23917
24110
  )
23918
24111
  });
@@ -23923,18 +24116,18 @@ function registerCreateTrigger(server2) {
23923
24116
  title: "Create Trigger",
23924
24117
  description: "Create a CRM event trigger or scheduled automation. When matching events occur (e.g., Deal.updated with stage=won), configured actions fire automatically (send_whatsapp, create_task, etc.).",
23925
24118
  inputSchema: {
23926
- name: z66.string().describe("Human-readable trigger name"),
23927
- event: z66.string().describe(
24119
+ name: z67.string().describe("Human-readable trigger name"),
24120
+ event: z67.string().describe(
23928
24121
  'CRM event to match, e.g., "Deal.updated", "Order.created", "*" for all'
23929
24122
  ),
23930
- conditions: z66.array(conditionSchema).default([]).describe("Conditions that must all match (AND logic)"),
23931
- actions: z66.array(actionSchema).min(1).describe("Actions to execute when trigger fires"),
23932
- project: z66.string().optional().describe("Scope trigger to a specific project"),
23933
- enabled: z66.boolean().default(true).describe("Whether trigger is active"),
23934
- schedule: z66.string().optional().describe(
24123
+ conditions: z67.array(conditionSchema).default([]).describe("Conditions that must all match (AND logic)"),
24124
+ actions: z67.array(actionSchema).min(1).describe("Actions to execute when trigger fires"),
24125
+ project: z67.string().optional().describe("Scope trigger to a specific project"),
24126
+ enabled: z67.boolean().default(true).describe("Whether trigger is active"),
24127
+ schedule: z67.string().optional().describe(
23935
24128
  'Cron schedule for time-based triggers, e.g., "0 9 * * *" or "Monday 9am"'
23936
24129
  ),
23937
- query: z66.string().optional().describe(
24130
+ query: z67.string().optional().describe(
23938
24131
  "CRM GraphQL query to run on schedule (required if schedule is set)"
23939
24132
  )
23940
24133
  }
@@ -24007,7 +24200,7 @@ Enabled: ${trigger.enabled}` + scheduleInfo;
24007
24200
  }
24008
24201
 
24009
24202
  // src/mcp/tools/list-triggers.ts
24010
- import { z as z67 } from "zod";
24203
+ import { z as z68 } from "zod";
24011
24204
  function registerListTriggers(server2) {
24012
24205
  server2.registerTool(
24013
24206
  "list_triggers",
@@ -24015,7 +24208,7 @@ function registerListTriggers(server2) {
24015
24208
  title: "List Triggers",
24016
24209
  description: "List configured CRM event triggers and scheduled automations.",
24017
24210
  inputSchema: {
24018
- project: z67.string().optional().describe("Filter triggers by project name")
24211
+ project: z68.string().optional().describe("Filter triggers by project name")
24019
24212
  }
24020
24213
  },
24021
24214
  async ({ project }) => {
@@ -24050,51 +24243,51 @@ function registerListTriggers(server2) {
24050
24243
  }
24051
24244
 
24052
24245
  // src/mcp/tools/apply-starter-pack.ts
24053
- import { z as z68 } from "zod";
24246
+ import { z as z69 } from "zod";
24054
24247
 
24055
24248
  // src/automation/starter-packs/index.ts
24056
- import { readFileSync as readFileSync25, readdirSync as readdirSync12, existsSync as existsSync33 } from "fs";
24057
- import path40 from "path";
24058
- import { fileURLToPath as fileURLToPath4 } from "url";
24059
- var __dirname = path40.dirname(fileURLToPath4(import.meta.url));
24249
+ import { readFileSync as readFileSync27, readdirSync as readdirSync12, existsSync as existsSync35 } from "fs";
24250
+ import path42 from "path";
24251
+ import { fileURLToPath as fileURLToPath5 } from "url";
24252
+ var __dirname = path42.dirname(fileURLToPath5(import.meta.url));
24060
24253
  function listPacks() {
24061
- const packsDir = path40.join(__dirname, ".");
24062
- if (!existsSync33(packsDir)) return [];
24254
+ const packsDir = path42.join(__dirname, ".");
24255
+ if (!existsSync35(packsDir)) return [];
24063
24256
  return readdirSync12(packsDir, { withFileTypes: true }).filter(
24064
- (d) => d.isDirectory() && existsSync33(path40.join(packsDir, d.name, "custom-objects.json"))
24257
+ (d) => d.isDirectory() && existsSync35(path42.join(packsDir, d.name, "custom-objects.json"))
24065
24258
  ).map((d) => d.name);
24066
24259
  }
24067
24260
  function loadPack(industry) {
24068
- const packDir = path40.join(__dirname, industry);
24069
- const objectsPath = path40.join(packDir, "custom-objects.json");
24070
- const triggersPath = path40.join(packDir, "triggers.json");
24071
- const wikiDir = path40.join(packDir, "wiki-seeds");
24072
- const manifestPath = path40.join(packDir, "pack.json");
24073
- const identityContextPath = path40.join(packDir, "identity-context.md");
24074
- if (!existsSync33(objectsPath)) return null;
24261
+ const packDir = path42.join(__dirname, industry);
24262
+ const objectsPath = path42.join(packDir, "custom-objects.json");
24263
+ const triggersPath = path42.join(packDir, "triggers.json");
24264
+ const wikiDir = path42.join(packDir, "wiki-seeds");
24265
+ const manifestPath = path42.join(packDir, "pack.json");
24266
+ const identityContextPath = path42.join(packDir, "identity-context.md");
24267
+ if (!existsSync35(objectsPath)) return null;
24075
24268
  let customObjects = [];
24076
24269
  try {
24077
24270
  customObjects = JSON.parse(
24078
- readFileSync25(objectsPath, "utf-8")
24271
+ readFileSync27(objectsPath, "utf-8")
24079
24272
  );
24080
24273
  } catch {
24081
24274
  customObjects = [];
24082
24275
  }
24083
24276
  let triggers = [];
24084
- if (existsSync33(triggersPath)) {
24277
+ if (existsSync35(triggersPath)) {
24085
24278
  try {
24086
24279
  triggers = JSON.parse(
24087
- readFileSync25(triggersPath, "utf-8")
24280
+ readFileSync27(triggersPath, "utf-8")
24088
24281
  );
24089
24282
  } catch {
24090
24283
  triggers = [];
24091
24284
  }
24092
24285
  }
24093
24286
  const wikiSeeds = [];
24094
- if (existsSync33(wikiDir)) {
24287
+ if (existsSync35(wikiDir)) {
24095
24288
  const files = readdirSync12(wikiDir).filter((f) => f.endsWith(".md"));
24096
24289
  for (const file of files) {
24097
- const content = readFileSync25(path40.join(wikiDir, file), "utf-8");
24290
+ const content = readFileSync27(path42.join(wikiDir, file), "utf-8");
24098
24291
  const titleMatch = content.match(/^#\s+(.+)/m);
24099
24292
  wikiSeeds.push({
24100
24293
  filename: file,
@@ -24104,17 +24297,17 @@ function loadPack(industry) {
24104
24297
  }
24105
24298
  }
24106
24299
  let manifest = {};
24107
- if (existsSync33(manifestPath)) {
24300
+ if (existsSync35(manifestPath)) {
24108
24301
  try {
24109
- manifest = JSON.parse(readFileSync25(manifestPath, "utf-8"));
24302
+ manifest = JSON.parse(readFileSync27(manifestPath, "utf-8"));
24110
24303
  } catch {
24111
24304
  manifest = {};
24112
24305
  }
24113
24306
  }
24114
24307
  let identityContext = null;
24115
- if (existsSync33(identityContextPath)) {
24308
+ if (existsSync35(identityContextPath)) {
24116
24309
  try {
24117
- identityContext = readFileSync25(identityContextPath, "utf-8");
24310
+ identityContext = readFileSync27(identityContextPath, "utf-8");
24118
24311
  } catch {
24119
24312
  identityContext = null;
24120
24313
  }
@@ -24171,8 +24364,8 @@ function applyPack(industry, project) {
24171
24364
 
24172
24365
  // src/lib/client-coo.ts
24173
24366
  init_config();
24174
- import { existsSync as existsSync34, mkdirSync as mkdirSync17, writeFileSync as writeFileSync19 } from "fs";
24175
- import path41 from "path";
24367
+ import { existsSync as existsSync36, mkdirSync as mkdirSync18, writeFileSync as writeFileSync20 } from "fs";
24368
+ import path43 from "path";
24176
24369
 
24177
24370
  // src/lib/employee-templates.ts
24178
24371
  init_global_procedures();
@@ -24312,18 +24505,18 @@ var ClientCOOClobberError = class extends Error {
24312
24505
  var COO_ROLE = "Chief Operating Officer";
24313
24506
  var FEEDBACK_BEHAVIOR_CONTENT = "Tag exe-os issues with needs_improvement \u2014 this is the feedback loop that surfaces bugs, gaps, and friction to the founder each Monday.";
24314
24507
  async function provisionClientCOO(vars, opts = {}) {
24315
- const identityDir = opts.identityDir ?? path41.join(EXE_AI_DIR, "identity");
24508
+ const identityDir = opts.identityDir ?? path43.join(EXE_AI_DIR, "identity");
24316
24509
  const rosterPath = opts.employeesPath ?? EMPLOYEES_PATH;
24317
24510
  const storeFeedbackBehavior = opts.storeFeedbackBehavior ?? true;
24318
- const identityPath2 = path41.join(identityDir, `${vars.agent_name}.md`);
24319
- if (existsSync34(identityPath2)) {
24511
+ const identityPath2 = path43.join(identityDir, `${vars.agent_name}.md`);
24512
+ if (existsSync36(identityPath2)) {
24320
24513
  throw new ClientCOOClobberError(vars.agent_name, identityPath2);
24321
24514
  }
24322
24515
  const body = renderClientCOOTemplate(vars);
24323
- if (!existsSync34(identityDir)) {
24324
- mkdirSync17(identityDir, { recursive: true });
24516
+ if (!existsSync36(identityDir)) {
24517
+ mkdirSync18(identityDir, { recursive: true });
24325
24518
  }
24326
- writeFileSync19(identityPath2, body, "utf-8");
24519
+ writeFileSync20(identityPath2, body, "utf-8");
24327
24520
  const employees = await loadEmployees(rosterPath);
24328
24521
  const existing = employees.find((e) => e.name === vars.agent_name);
24329
24522
  let addedToRoster = false;
@@ -24359,17 +24552,17 @@ function registerApplyStarterPack(server2) {
24359
24552
  title: "Apply Starter Pack",
24360
24553
  description: "Apply an industry starter pack to a project. Sets up CRM custom objects, pre-wired automation triggers, and wiki seed content. When the pack creates a Client COO (e.g. distribution) and agent_name, company_name, founder_name are all provided, also provisions the COO identity, roster entry, and feedback-loop behavior. Available packs: distribution. More coming.",
24361
24554
  inputSchema: {
24362
- industry: z68.string().describe(
24555
+ industry: z69.string().describe(
24363
24556
  'Industry pack to apply (e.g., "distribution"). Use without args to list available packs.'
24364
24557
  ),
24365
- project: z68.string().describe("Project name to scope the triggers to"),
24366
- agent_name: z68.string().optional().describe(
24558
+ project: z69.string().describe("Project name to scope the triggers to"),
24559
+ agent_name: z69.string().optional().describe(
24367
24560
  "Optional. Lowercase alphanumeric name for the Client COO agent. Required (alongside company_name and founder_name) to provision a COO."
24368
24561
  ),
24369
- company_name: z68.string().optional().describe(
24562
+ company_name: z69.string().optional().describe(
24370
24563
  "Optional. The client company the COO serves. Required to provision a COO."
24371
24564
  ),
24372
- founder_name: z68.string().optional().describe(
24565
+ founder_name: z69.string().optional().describe(
24373
24566
  "Optional. The founder the COO reports to. Required to provision a COO."
24374
24567
  )
24375
24568
  }
@@ -24514,20 +24707,20 @@ ${err.message}`
24514
24707
  }
24515
24708
 
24516
24709
  // src/mcp/tools/load-skill.ts
24517
- import { z as z69 } from "zod";
24518
- import { readFileSync as readFileSync26, readdirSync as readdirSync13, statSync as statSync7 } from "fs";
24519
- import path42 from "path";
24520
- import { homedir as homedir7 } from "os";
24521
- var SKILLS_DIR = path42.join(homedir7(), ".claude", "skills");
24710
+ import { z as z70 } from "zod";
24711
+ import { readFileSync as readFileSync28, readdirSync as readdirSync13, statSync as statSync8 } from "fs";
24712
+ import path44 from "path";
24713
+ import { homedir as homedir8 } from "os";
24714
+ var SKILLS_DIR = path44.join(homedir8(), ".claude", "skills");
24522
24715
  function listAvailableSkills() {
24523
24716
  try {
24524
24717
  const entries = readdirSync13(SKILLS_DIR);
24525
24718
  return entries.filter((entry) => {
24526
24719
  try {
24527
- const entryPath = path42.join(SKILLS_DIR, entry);
24528
- if (!statSync7(entryPath).isDirectory()) return false;
24529
- const skillFile = path42.join(entryPath, "SKILL.md");
24530
- statSync7(skillFile);
24720
+ const entryPath = path44.join(SKILLS_DIR, entry);
24721
+ if (!statSync8(entryPath).isDirectory()) return false;
24722
+ const skillFile = path44.join(entryPath, "SKILL.md");
24723
+ statSync8(skillFile);
24531
24724
  return true;
24532
24725
  } catch {
24533
24726
  return false;
@@ -24544,7 +24737,7 @@ function registerLoadSkill(server2) {
24544
24737
  title: "Load Skill",
24545
24738
  description: "Load domain-specific guidance into your context. Use when you need specialized knowledge for a task (e.g., load_skill('seo') before doing SEO work, load_skill('code-reviewer') before reviewing code). Pass skill_name='list' to see all available skills.",
24546
24739
  inputSchema: {
24547
- skill_name: z69.string().describe(
24740
+ skill_name: z70.string().describe(
24548
24741
  "Skill to load (e.g. 'seo', 'code-reviewer', 'frontend-design'). Pass 'list' to see all available skills."
24549
24742
  )
24550
24743
  }
@@ -24569,10 +24762,10 @@ ${skills.map((s) => `- ${s}`).join("\n")}`
24569
24762
  }]
24570
24763
  };
24571
24764
  }
24572
- const sanitized = path42.basename(skill_name);
24573
- const skillFile = path42.join(SKILLS_DIR, sanitized, "SKILL.md");
24765
+ const sanitized = path44.basename(skill_name);
24766
+ const skillFile = path44.join(SKILLS_DIR, sanitized, "SKILL.md");
24574
24767
  try {
24575
- const content = readFileSync26(skillFile, "utf-8");
24768
+ const content = readFileSync28(skillFile, "utf-8");
24576
24769
  return {
24577
24770
  content: [{
24578
24771
  type: "text",
@@ -24600,18 +24793,18 @@ ${available.map((s) => `- ${s}`).join("\n")}` : "\n\nNo skills found in ~/.claud
24600
24793
 
24601
24794
  // src/mcp/tools/export-orchestration.ts
24602
24795
  init_active_agent();
24603
- import { mkdirSync as mkdirSync19, writeFileSync as writeFileSync21 } from "fs";
24604
- import path44 from "path";
24605
- import { z as z70 } from "zod";
24796
+ import { mkdirSync as mkdirSync20, writeFileSync as writeFileSync22 } from "fs";
24797
+ import path46 from "path";
24798
+ import { z as z71 } from "zod";
24606
24799
 
24607
24800
  // src/lib/orchestration-package.ts
24608
24801
  init_database();
24609
24802
  init_identity();
24610
24803
  init_platform_procedures();
24611
24804
  import { randomUUID as randomUUID8 } from "crypto";
24612
- import { copyFileSync as copyFileSync2, existsSync as existsSync35, mkdirSync as mkdirSync18, readFileSync as readFileSync27, writeFileSync as writeFileSync20 } from "fs";
24805
+ import { copyFileSync as copyFileSync2, existsSync as existsSync37, mkdirSync as mkdirSync19, readFileSync as readFileSync29, writeFileSync as writeFileSync21 } from "fs";
24613
24806
  import os18 from "os";
24614
- import path43 from "path";
24807
+ import path45 from "path";
24615
24808
  var PACKAGE_VERSION = "1.0";
24616
24809
  var ROSTER_FILENAME = "exe-employees.json";
24617
24810
  var ROSTER_BACKUP_FILENAME = "exe-employees.json.bak";
@@ -24677,15 +24870,15 @@ function validateProcedureEntry(value, index) {
24677
24870
  };
24678
24871
  }
24679
24872
  function getRosterPath() {
24680
- return path43.join(os18.homedir(), EXE_OS_DIRNAME, ROSTER_FILENAME);
24873
+ return path45.join(os18.homedir(), EXE_OS_DIRNAME, ROSTER_FILENAME);
24681
24874
  }
24682
24875
  function getBackupPath() {
24683
- return path43.join(os18.homedir(), EXE_OS_DIRNAME, ROSTER_BACKUP_FILENAME);
24876
+ return path45.join(os18.homedir(), EXE_OS_DIRNAME, ROSTER_BACKUP_FILENAME);
24684
24877
  }
24685
24878
  function readRosterFile() {
24686
24879
  const rosterPath = getRosterPath();
24687
- if (!existsSync35(rosterPath)) return [];
24688
- const raw = readFileSync27(rosterPath, "utf-8");
24880
+ if (!existsSync37(rosterPath)) return [];
24881
+ const raw = readFileSync29(rosterPath, "utf-8");
24689
24882
  const parsed = JSON.parse(raw);
24690
24883
  if (!Array.isArray(parsed)) {
24691
24884
  throw new Error("Roster file must contain a JSON array");
@@ -24697,8 +24890,8 @@ function writeRosterFile(roster) {
24697
24890
  throw new Error("Refusing to write empty roster \u2014 this would delete all employees");
24698
24891
  }
24699
24892
  const rosterPath = getRosterPath();
24700
- mkdirSync18(path43.dirname(rosterPath), { recursive: true });
24701
- if (existsSync35(rosterPath)) {
24893
+ mkdirSync19(path45.dirname(rosterPath), { recursive: true });
24894
+ if (existsSync37(rosterPath)) {
24702
24895
  const currentRoster = readRosterFile();
24703
24896
  if (roster.length < currentRoster.length) {
24704
24897
  throw new Error(
@@ -24707,7 +24900,7 @@ function writeRosterFile(roster) {
24707
24900
  }
24708
24901
  copyFileSync2(rosterPath, getBackupPath());
24709
24902
  }
24710
- writeFileSync20(rosterPath, `${JSON.stringify(roster, null, 2)}
24903
+ writeFileSync21(rosterPath, `${JSON.stringify(roster, null, 2)}
24711
24904
  `, "utf-8");
24712
24905
  }
24713
24906
  function buildImportedRosterEntries(roster, timestamp) {
@@ -24962,15 +25155,15 @@ function registerExportOrchestration(server2) {
24962
25155
  title: "Export Orchestration",
24963
25156
  description: "Export roster, identities, behaviors, and customer procedures to a JSON package.",
24964
25157
  inputSchema: {
24965
- output_path: z70.string().describe("File path to write the JSON package")
25158
+ output_path: z71.string().describe("File path to write the JSON package")
24966
25159
  }
24967
25160
  },
24968
25161
  async ({ output_path }) => {
24969
25162
  try {
24970
25163
  await initStore();
24971
25164
  const pkg = await exportOrchestration(getActiveAgent().agentId);
24972
- mkdirSync19(path44.dirname(output_path), { recursive: true });
24973
- writeFileSync21(output_path, `${JSON.stringify(pkg, null, 2)}
25165
+ mkdirSync20(path46.dirname(output_path), { recursive: true });
25166
+ writeFileSync22(output_path, `${JSON.stringify(pkg, null, 2)}
24974
25167
  `, "utf-8");
24975
25168
  return {
24976
25169
  content: [{
@@ -24992,8 +25185,8 @@ function registerExportOrchestration(server2) {
24992
25185
  }
24993
25186
 
24994
25187
  // src/mcp/tools/import-orchestration.ts
24995
- import { readFileSync as readFileSync28 } from "fs";
24996
- import { z as z71 } from "zod";
25188
+ import { readFileSync as readFileSync30 } from "fs";
25189
+ import { z as z72 } from "zod";
24997
25190
  init_store();
24998
25191
  init_active_agent();
24999
25192
  init_employees();
@@ -25004,8 +25197,8 @@ function registerImportOrchestration(server2) {
25004
25197
  title: "Import Orchestration",
25005
25198
  description: "Import roster, identities, behaviors, and procedures from an orchestration package. Restricted to coordinator/founder.",
25006
25199
  inputSchema: {
25007
- package_path: z71.string().describe("Path to the orchestration package JSON file"),
25008
- merge_strategy: z71.enum(["replace", "merge"]).default("merge").describe("How to apply the package: both strategies are additive-only \u2014 existing data is never deleted or overwritten")
25200
+ package_path: z72.string().describe("Path to the orchestration package JSON file"),
25201
+ merge_strategy: z72.enum(["replace", "merge"]).default("merge").describe("How to apply the package: both strategies are additive-only \u2014 existing data is never deleted or overwritten")
25009
25202
  }
25010
25203
  },
25011
25204
  async ({ package_path, merge_strategy }) => {
@@ -25022,7 +25215,7 @@ function registerImportOrchestration(server2) {
25022
25215
  };
25023
25216
  }
25024
25217
  await initStore();
25025
- const raw = readFileSync28(package_path, "utf-8");
25218
+ const raw = readFileSync30(package_path, "utf-8");
25026
25219
  const pkg = validatePackage(JSON.parse(raw));
25027
25220
  const result2 = await importOrchestration(pkg, merge_strategy);
25028
25221
  return {
@@ -25050,7 +25243,7 @@ init_platform_procedures();
25050
25243
  init_active_agent();
25051
25244
  init_database();
25052
25245
  init_employees();
25053
- import { z as z72 } from "zod";
25246
+ import { z as z73 } from "zod";
25054
25247
  function registerCompanyProcedureTool(server2, toolName) {
25055
25248
  server2.registerTool(
25056
25249
  toolName,
@@ -25058,12 +25251,12 @@ function registerCompanyProcedureTool(server2, toolName) {
25058
25251
  title: "Company Procedure",
25059
25252
  description: "Manage company procedures (customer-owned Layer 0 rules) that supersede identity, expertise, and experience. Actions: store (create new, restricted), list (view all, open), deactivate (soft-delete, restricted).",
25060
25253
  inputSchema: {
25061
- action: z72.enum(["store", "list", "deactivate"]).describe("Action to perform"),
25062
- title: z72.string().optional().describe("Short title for the procedure (store)"),
25063
- content: z72.string().max(500).optional().describe("The procedure content \u2014 clear, actionable instruction (store)"),
25064
- priority: z72.enum(["p0", "p1", "p2"]).optional().describe("Priority tier. p0 = always (default). p1 = standard. p2 = nice-to-have."),
25065
- domain: z72.string().optional().describe("Category: workflow, code-style, communication, architecture, testing, security"),
25066
- procedure_id: z72.string().optional().describe("UUID of the company procedure (deactivate)")
25254
+ action: z73.enum(["store", "list", "deactivate"]).describe("Action to perform"),
25255
+ title: z73.string().optional().describe("Short title for the procedure (store)"),
25256
+ content: z73.string().max(500).optional().describe("The procedure content \u2014 clear, actionable instruction (store)"),
25257
+ priority: z73.enum(["p0", "p1", "p2"]).optional().describe("Priority tier. p0 = always (default). p1 = standard. p2 = nice-to-have."),
25258
+ domain: z73.string().optional().describe("Category: workflow, code-style, communication, architecture, testing, security"),
25259
+ procedure_id: z73.string().optional().describe("UUID of the company procedure (deactivate)")
25067
25260
  }
25068
25261
  },
25069
25262
  async ({ action, title, content, priority, domain, procedure_id }) => {
@@ -25191,6 +25384,7 @@ var ACTION_TO_TOOL2 = {
25191
25384
  list_agent_sessions: "list_agent_sessions",
25192
25385
  session_kills: "get_session_kills",
25193
25386
  daemon_health: "get_daemon_health",
25387
+ mcp_ping: "mcp_ping",
25194
25388
  auto_wake_status: "get_auto_wake_status",
25195
25389
  worker_gate: "get_worker_gate",
25196
25390
  memory_audit: "run_memory_audit",
@@ -25228,6 +25422,7 @@ function buildHandlers5() {
25228
25422
  registerListAgentSessions(localServer);
25229
25423
  registerGetSessionKills(localServer);
25230
25424
  registerGetDaemonHealth(localServer);
25425
+ registerMcpPing(localServer);
25231
25426
  registerGetAutoWakeStatus(localServer);
25232
25427
  registerGetWorkerGate(localServer);
25233
25428
  registerRunMemoryAudit(localServer);
@@ -25256,44 +25451,44 @@ function registerConfig(server2) {
25256
25451
  title: "Config",
25257
25452
  description: "Consolidated COO/admin tool for runtime config, system health, licensing, triggers, orchestration import/export, and company procedures.",
25258
25453
  inputSchema: {
25259
- action: z73.enum(Object.keys(ACTION_TO_TOOL2)).describe("Admin/config operation"),
25260
- agent_id: z73.string().optional().describe("Agent id for set_agent_config/agent_spend/session queries"),
25261
- runtime: z73.string().optional().describe("Runtime for set_agent_config"),
25262
- model: z73.string().optional().describe("Model for set_agent_config"),
25263
- reasoning_effort: z73.string().optional().describe("Reasoning effort for Codex agents"),
25264
- dry_run: z73.boolean().optional().describe("Preview without applying where supported"),
25265
- fix: z73.boolean().optional().describe("Apply fixes for memory_audit where supported"),
25266
- verbose: z73.boolean().optional().describe("Verbose output where supported"),
25267
- project_name: z73.string().optional().describe("Project filter/name"),
25268
- since: z73.string().optional().describe("ISO lower-bound timestamp"),
25269
- limit: z73.coerce.number().optional().describe("Result limit"),
25270
- output_path: z73.string().optional().describe("Output path for export/backup"),
25271
- input_path: z73.string().optional().describe("Input path for import_orchestration"),
25272
- strategy: z73.enum(["merge", "replace"]).optional().describe("Import strategy; replace must still be additive-only per platform rules"),
25273
- license_key: z73.string().optional().describe("License key for activation/status"),
25274
- email: z73.string().optional().describe("Customer email for license creation"),
25275
- plan: z73.string().optional().describe("License plan"),
25276
- name: z73.string().optional().describe("Trigger/starter pack/procedure/client name"),
25277
- event: z73.string().optional().describe("Trigger event"),
25278
- conditions: z73.array(z73.record(z73.string(), z73.unknown())).optional().describe("Trigger conditions"),
25279
- actions: z73.array(z73.record(z73.string(), z73.unknown())).optional().describe("Trigger actions"),
25280
- enabled: z73.boolean().optional().describe("Trigger enabled flag"),
25281
- schedule: z73.string().optional().describe("Trigger schedule"),
25282
- query: z73.string().optional().describe("Trigger query or filter"),
25283
- skill_name: z73.string().optional().describe("Skill name for load_skill"),
25284
- pack_name: z73.string().optional().describe("Starter pack name"),
25285
- title: z73.string().optional().describe("Procedure title"),
25286
- content: z73.string().optional().describe("Procedure content"),
25287
- priority: z73.enum(["p0", "p1", "p2"]).optional().describe("Procedure priority"),
25288
- domain: z73.string().optional().describe("Procedure domain"),
25289
- procedure_id: z73.string().optional().describe("Procedure id for deactivate"),
25290
- subaction: z73.enum(["store", "list", "deactivate"]).optional().describe("Nested action for company_procedure/global_procedure"),
25291
- max_clusters: z73.coerce.number().optional().describe("Consolidation max clusters"),
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"),
25295
- domain_name: z73.string().optional().describe("Client deployment domain"),
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")
25454
+ action: z74.enum(Object.keys(ACTION_TO_TOOL2)).describe("Admin/config operation"),
25455
+ agent_id: z74.string().optional().describe("Agent id for set_agent_config/agent_spend/session queries"),
25456
+ runtime: z74.string().optional().describe("Runtime for set_agent_config"),
25457
+ model: z74.string().optional().describe("Model for set_agent_config"),
25458
+ reasoning_effort: z74.string().optional().describe("Reasoning effort for Codex agents"),
25459
+ dry_run: z74.boolean().optional().describe("Preview without applying where supported"),
25460
+ fix: z74.boolean().optional().describe("Apply fixes for memory_audit where supported"),
25461
+ verbose: z74.boolean().optional().describe("Verbose output where supported"),
25462
+ project_name: z74.string().optional().describe("Project filter/name"),
25463
+ since: z74.string().optional().describe("ISO lower-bound timestamp"),
25464
+ limit: z74.coerce.number().optional().describe("Result limit"),
25465
+ output_path: z74.string().optional().describe("Output path for export/backup"),
25466
+ input_path: z74.string().optional().describe("Input path for import_orchestration"),
25467
+ strategy: z74.enum(["merge", "replace"]).optional().describe("Import strategy; replace must still be additive-only per platform rules"),
25468
+ license_key: z74.string().optional().describe("License key for activation/status"),
25469
+ email: z74.string().optional().describe("Customer email for license creation"),
25470
+ plan: z74.string().optional().describe("License plan"),
25471
+ name: z74.string().optional().describe("Trigger/starter pack/procedure/client name"),
25472
+ event: z74.string().optional().describe("Trigger event"),
25473
+ conditions: z74.array(z74.record(z74.string(), z74.unknown())).optional().describe("Trigger conditions"),
25474
+ actions: z74.array(z74.record(z74.string(), z74.unknown())).optional().describe("Trigger actions"),
25475
+ enabled: z74.boolean().optional().describe("Trigger enabled flag"),
25476
+ schedule: z74.string().optional().describe("Trigger schedule"),
25477
+ query: z74.string().optional().describe("Trigger query or filter"),
25478
+ skill_name: z74.string().optional().describe("Skill name for load_skill"),
25479
+ pack_name: z74.string().optional().describe("Starter pack name"),
25480
+ title: z74.string().optional().describe("Procedure title"),
25481
+ content: z74.string().optional().describe("Procedure content"),
25482
+ priority: z74.enum(["p0", "p1", "p2"]).optional().describe("Procedure priority"),
25483
+ domain: z74.string().optional().describe("Procedure domain"),
25484
+ procedure_id: z74.string().optional().describe("Procedure id for deactivate"),
25485
+ subaction: z74.enum(["store", "list", "deactivate"]).optional().describe("Nested action for company_procedure/global_procedure"),
25486
+ max_clusters: z74.coerce.number().optional().describe("Consolidation max clusters"),
25487
+ force: z74.boolean().optional().describe("Force operation where supported"),
25488
+ cloud_action: z74.enum(["status", "sync", "reupload"]).optional().describe("Nested operation for action=cloud_sync"),
25489
+ confirm_local_db_source_of_truth: z74.string().optional().describe("Required for cloud_action=reupload; must exactly equal LOCAL DB IS SOURCE OF TRUTH"),
25490
+ domain_name: z74.string().optional().describe("Client deployment domain"),
25491
+ phase: z74.enum(["phase_1_coo", "phase_2_executives", "phase_3_parallel_org", "1", "2", "3"]).optional().describe("Orchestration phase for orchestration_phase action")
25297
25492
  }
25298
25493
  }, async (input, extra) => {
25299
25494
  const action = input.action;
@@ -25317,10 +25512,10 @@ function registerConfig(server2) {
25317
25512
  }
25318
25513
 
25319
25514
  // src/mcp/tools/wiki.ts
25320
- import { z as z76 } from "zod";
25515
+ import { z as z77 } from "zod";
25321
25516
 
25322
25517
  // src/mcp/tools/list-wiki-pages.ts
25323
- import { z as z74 } from "zod";
25518
+ import { z as z75 } from "zod";
25324
25519
  var FETCH_TIMEOUT_MS3 = 1e4;
25325
25520
  function registerListWikiPages(server2) {
25326
25521
  server2.registerTool(
@@ -25329,8 +25524,8 @@ function registerListWikiPages(server2) {
25329
25524
  title: "List Wiki Pages",
25330
25525
  description: "List documents in an exe-wiki workspace. Optionally filter by folder.",
25331
25526
  inputSchema: {
25332
- workspace: z74.string().describe('Wiki workspace slug (e.g., "hygo")'),
25333
- folder: z74.string().optional().describe("Filter by folder path")
25527
+ workspace: z75.string().describe('Wiki workspace slug (e.g., "hygo")'),
25528
+ folder: z75.string().optional().describe("Filter by folder path")
25334
25529
  }
25335
25530
  },
25336
25531
  async ({ workspace, folder }) => {
@@ -25419,7 +25614,7 @@ function registerListWikiPages(server2) {
25419
25614
  }
25420
25615
 
25421
25616
  // src/mcp/tools/get-wiki-page.ts
25422
- import { z as z75 } from "zod";
25617
+ import { z as z76 } from "zod";
25423
25618
  var FETCH_TIMEOUT_MS4 = 1e4;
25424
25619
  function registerGetWikiPage(server2) {
25425
25620
  server2.registerTool(
@@ -25428,9 +25623,9 @@ function registerGetWikiPage(server2) {
25428
25623
  title: "Get Wiki Page",
25429
25624
  description: "Read a wiki page by document ID or title. Returns content, metadata, and folder path. Use title search when you know the page name but not the ID.",
25430
25625
  inputSchema: {
25431
- workspace: z75.string().describe('Wiki workspace slug (e.g., "hygo")'),
25432
- document_id: z75.string().optional().describe("Specific document ID (exact lookup)"),
25433
- title: z75.string().optional().describe("Search by title (fuzzy match)")
25626
+ workspace: z76.string().describe('Wiki workspace slug (e.g., "hygo")'),
25627
+ document_id: z76.string().optional().describe("Specific document ID (exact lookup)"),
25628
+ title: z76.string().optional().describe("Search by title (fuzzy match)")
25434
25629
  }
25435
25630
  },
25436
25631
  async ({ workspace, document_id, title }) => {
@@ -25612,14 +25807,14 @@ function registerWiki(server2) {
25612
25807
  title: "Wiki",
25613
25808
  description: "Consolidated wiki domain tool. Actions: list, get. Wiki writes flow through raw data ingestion/projection into the curated wiki store; direct create/update MCP tools have been removed.",
25614
25809
  inputSchema: {
25615
- action: z76.enum(["list", "get"]).describe("Wiki read operation. Writes use raw-data ingestion/projection, not direct MCP writes."),
25616
- workspace: z76.string().optional().describe("Wiki workspace slug"),
25617
- title: z76.string().optional().describe("Fuzzy page title lookup for get"),
25618
- content: z76.string().optional().describe("Reserved; wiki writes use raw-data ingestion/projection"),
25619
- folder: z76.string().optional().describe("Optional folder path for list"),
25620
- document_id: z76.string().optional().describe("Document ID for get"),
25621
- mode: z76.enum(["replace", "append"]).optional().describe("Reserved; direct wiki updates are removed"),
25622
- section: z76.string().optional().describe("Reserved; direct wiki updates are removed")
25810
+ action: z77.enum(["list", "get"]).describe("Wiki read operation. Writes use raw-data ingestion/projection, not direct MCP writes."),
25811
+ workspace: z77.string().optional().describe("Wiki workspace slug"),
25812
+ title: z77.string().optional().describe("Fuzzy page title lookup for get"),
25813
+ content: z77.string().optional().describe("Reserved; wiki writes use raw-data ingestion/projection"),
25814
+ folder: z77.string().optional().describe("Optional folder path for list"),
25815
+ document_id: z77.string().optional().describe("Document ID for get"),
25816
+ mode: z77.enum(["replace", "append"]).optional().describe("Reserved; direct wiki updates are removed"),
25817
+ section: z77.string().optional().describe("Reserved; direct wiki updates are removed")
25623
25818
  }
25624
25819
  },
25625
25820
  async (input, extra) => {
@@ -25647,7 +25842,7 @@ init_active_agent();
25647
25842
  init_project_name();
25648
25843
  init_database();
25649
25844
  init_employees();
25650
- import { z as z77 } from "zod";
25845
+ import { z as z78 } from "zod";
25651
25846
  function rowToBehavior2(r) {
25652
25847
  return {
25653
25848
  id: String(r.id),
@@ -25669,13 +25864,13 @@ function registerBehavior(server2) {
25669
25864
  title: "Behavior",
25670
25865
  description: "Manage behavioral patterns, corrections, and reusable procedures for employees. Actions: store (create new), list (query existing), deactivate (soft-delete, restricted).",
25671
25866
  inputSchema: {
25672
- action: z77.enum(["store", "list", "deactivate"]).describe("Action to perform"),
25673
- content: z77.string().max(500).optional().describe("The behavioral instruction \u2014 one clear sentence (store)"),
25674
- domain: z77.string().optional().describe("Category: workflow, code-style, tool-use, communication, architecture, testing"),
25675
- priority: z77.enum(["p0", "p1", "p2"]).optional().describe("Priority tier. p0 = always included. p1 = standard (default). p2 = nice-to-have."),
25676
- agent_id: z77.string().optional().describe("Employee name. Defaults to current agent. Pass 'all' to list everyone's (list only)."),
25677
- project_name: z77.string().optional().describe("Defaults to current project. Pass 'global' for a behavior that applies everywhere (store)."),
25678
- behavior_id: z77.string().optional().describe("UUID of the behavior (deactivate)")
25867
+ action: z78.enum(["store", "list", "deactivate"]).describe("Action to perform"),
25868
+ content: z78.string().max(500).optional().describe("The behavioral instruction \u2014 one clear sentence (store)"),
25869
+ domain: z78.string().optional().describe("Category: workflow, code-style, tool-use, communication, architecture, testing"),
25870
+ priority: z78.enum(["p0", "p1", "p2"]).optional().describe("Priority tier. p0 = always included. p1 = standard (default). p2 = nice-to-have."),
25871
+ agent_id: z78.string().optional().describe("Employee name. Defaults to current agent. Pass 'all' to list everyone's (list only)."),
25872
+ project_name: z78.string().optional().describe("Defaults to current project. Pass 'global' for a behavior that applies everywhere (store)."),
25873
+ behavior_id: z78.string().optional().describe("UUID of the behavior (deactivate)")
25679
25874
  }
25680
25875
  },
25681
25876
  async ({ action, content, domain, priority, agent_id, project_name, behavior_id }) => {
@@ -25846,7 +26041,7 @@ Content: ${row.content}`
25846
26041
  }
25847
26042
 
25848
26043
  // src/mcp/tools/reminder.ts
25849
- import { z as z78 } from "zod";
26044
+ import { z as z79 } from "zod";
25850
26045
  function registerReminder(server2) {
25851
26046
  server2.registerTool(
25852
26047
  "reminder",
@@ -25854,11 +26049,11 @@ function registerReminder(server2) {
25854
26049
  title: "Reminder",
25855
26050
  description: "Manage reminders for the founder. Shown in the boot brief every session. Actions: create (set new), list (view active), complete (mark done).",
25856
26051
  inputSchema: {
25857
- action: z78.enum(["create", "list", "complete"]).describe("Action to perform"),
25858
- text: z78.string().optional().describe("What to remind about (create)"),
25859
- due_date: z78.string().optional().describe("Optional due date \u2014 ISO date (2026-04-01) or null for persistent (create)"),
25860
- reminder_id: z78.string().optional().describe("Reminder UUID or text substring to match (complete)"),
25861
- include_completed: z78.boolean().optional().default(false).describe("Include completed reminders (list)")
26052
+ action: z79.enum(["create", "list", "complete"]).describe("Action to perform"),
26053
+ text: z79.string().optional().describe("What to remind about (create)"),
26054
+ due_date: z79.string().optional().describe("Optional due date \u2014 ISO date (2026-04-01) or null for persistent (create)"),
26055
+ reminder_id: z79.string().optional().describe("Reminder UUID or text substring to match (complete)"),
26056
+ include_completed: z79.boolean().optional().default(false).describe("Include completed reminders (list)")
25862
26057
  }
25863
26058
  },
25864
26059
  async ({ action, text: text3, due_date, reminder_id, include_completed }) => {
@@ -25914,7 +26109,7 @@ function registerReminder(server2) {
25914
26109
  init_global_procedures();
25915
26110
  init_active_agent();
25916
26111
  init_employees();
25917
- import { z as z79 } from "zod";
26112
+ import { z as z80 } from "zod";
25918
26113
  function registerStoreGlobalProcedure(server2) {
25919
26114
  server2.registerTool(
25920
26115
  "store_global_procedure",
@@ -25922,10 +26117,10 @@ function registerStoreGlobalProcedure(server2) {
25922
26117
  title: "Store Company Procedure (use global_procedure instead)",
25923
26118
  description: "DEPRECATED \u2014 use global_procedure with action='store'. Create a company procedure (customer-owned Layer 0 rule). RESTRICTED: only coordinator or founder sessions.",
25924
26119
  inputSchema: {
25925
- title: z79.string().describe("Short title for the procedure"),
25926
- content: z79.string().max(500).describe("The procedure content \u2014 clear, actionable instruction"),
25927
- priority: z79.enum(["p0", "p1", "p2"]).optional().describe("Priority tier. p0 = always (default)."),
25928
- domain: z79.string().optional().describe("Category: workflow, code-style, communication, architecture, testing, security")
26120
+ title: z80.string().describe("Short title for the procedure"),
26121
+ content: z80.string().max(500).describe("The procedure content \u2014 clear, actionable instruction"),
26122
+ priority: z80.enum(["p0", "p1", "p2"]).optional().describe("Priority tier. p0 = always (default)."),
26123
+ domain: z80.string().optional().describe("Category: workflow, code-style, communication, architecture, testing, security")
25929
26124
  }
25930
26125
  },
25931
26126
  async ({ title, content, priority, domain }) => {
@@ -26003,7 +26198,7 @@ init_global_procedures();
26003
26198
  init_active_agent();
26004
26199
  init_database();
26005
26200
  init_employees();
26006
- import { z as z80 } from "zod";
26201
+ import { z as z81 } from "zod";
26007
26202
  function registerDeactivateGlobalProcedure(server2) {
26008
26203
  server2.registerTool(
26009
26204
  "deactivate_global_procedure",
@@ -26011,7 +26206,7 @@ function registerDeactivateGlobalProcedure(server2) {
26011
26206
  title: "Deactivate Company Procedure (use global_procedure instead)",
26012
26207
  description: "DEPRECATED \u2014 use global_procedure with action='deactivate'. Soft-delete a company procedure. RESTRICTED: only coordinator or founder sessions.",
26013
26208
  inputSchema: {
26014
- procedure_id: z80.string().describe("UUID of the company procedure to deactivate")
26209
+ procedure_id: z81.string().describe("UUID of the company procedure to deactivate")
26015
26210
  }
26016
26211
  },
26017
26212
  async ({ procedure_id }) => {
@@ -26071,7 +26266,7 @@ init_store();
26071
26266
  init_active_agent();
26072
26267
  init_database();
26073
26268
  init_plan_limits();
26074
- import { z as z81 } from "zod";
26269
+ import { z as z82 } from "zod";
26075
26270
  import crypto17 from "crypto";
26076
26271
  function registerStoreDecision(server2) {
26077
26272
  server2.registerTool(
@@ -26080,13 +26275,13 @@ function registerStoreDecision(server2) {
26080
26275
  title: "Store Decision",
26081
26276
  description: "Store an authoritative decision keyed by domain. Use this when a decision is made that should be canonical \u2014 future lookups via get_decision return the latest decision for that domain. Supports supersession chains.",
26082
26277
  inputSchema: {
26083
- domain: z81.string().describe(
26278
+ domain: z82.string().describe(
26084
26279
  "Domain key, e.g. 'auth-strategy', 'db-migration-approach', 'api-versioning'"
26085
26280
  ),
26086
- decision: z81.string().describe("The decision text \u2014 what was decided"),
26087
- rationale: z81.string().optional().describe("Why this decision was made \u2014 constraints, trade-offs, context"),
26088
- supersedes: z81.string().optional().describe("UUID of the decision this supersedes (previous decision for this domain)"),
26089
- project_name: z81.string().optional().describe("Project name")
26281
+ decision: z82.string().describe("The decision text \u2014 what was decided"),
26282
+ rationale: z82.string().optional().describe("Why this decision was made \u2014 constraints, trade-offs, context"),
26283
+ supersedes: z82.string().optional().describe("UUID of the decision this supersedes (previous decision for this domain)"),
26284
+ project_name: z82.string().optional().describe("Project name")
26090
26285
  }
26091
26286
  },
26092
26287
  async ({ domain, decision, rationale, supersedes, project_name }) => {
@@ -26154,7 +26349,7 @@ Supersedes: ${supersedes}` : ""}`
26154
26349
 
26155
26350
  // src/mcp/tools/get-decision.ts
26156
26351
  init_database();
26157
- import { z as z82 } from "zod";
26352
+ import { z as z83 } from "zod";
26158
26353
  function registerGetDecision(server2) {
26159
26354
  server2.registerTool(
26160
26355
  "get_decision",
@@ -26162,7 +26357,7 @@ function registerGetDecision(server2) {
26162
26357
  title: "Get Decision",
26163
26358
  description: "Retrieve the latest authoritative decision for a domain. Returns the current active decision and the supersession history.",
26164
26359
  inputSchema: {
26165
- domain: z82.string().describe(
26360
+ domain: z83.string().describe(
26166
26361
  "Domain key to look up, e.g. 'auth-strategy', 'db-migration-approach'"
26167
26362
  )
26168
26363
  }
@@ -26225,16 +26420,16 @@ function registerGetDecision(server2) {
26225
26420
  }
26226
26421
 
26227
26422
  // src/mcp/tools/people-roster.ts
26228
- import { z as z83 } from "zod";
26423
+ import { z as z84 } from "zod";
26229
26424
 
26230
26425
  // src/lib/people.ts
26231
26426
  init_config();
26232
26427
  import { readFile as readFile5, writeFile as writeFile6, mkdir as mkdir5 } from "fs/promises";
26233
- import { existsSync as existsSync36, readFileSync as readFileSync29 } from "fs";
26234
- import path45 from "path";
26235
- var PEOPLE_PATH = path45.join(EXE_AI_DIR, "people.json");
26428
+ import { existsSync as existsSync38, readFileSync as readFileSync31 } from "fs";
26429
+ import path47 from "path";
26430
+ var PEOPLE_PATH = path47.join(EXE_AI_DIR, "people.json");
26236
26431
  async function loadPeople() {
26237
- if (!existsSync36(PEOPLE_PATH)) return [];
26432
+ if (!existsSync38(PEOPLE_PATH)) return [];
26238
26433
  try {
26239
26434
  const raw = await readFile5(PEOPLE_PATH, "utf-8");
26240
26435
  return JSON.parse(raw);
@@ -26243,7 +26438,7 @@ async function loadPeople() {
26243
26438
  }
26244
26439
  }
26245
26440
  async function savePeople(people) {
26246
- await mkdir5(path45.dirname(PEOPLE_PATH), { recursive: true });
26441
+ await mkdir5(path47.dirname(PEOPLE_PATH), { recursive: true });
26247
26442
  await writeFile6(PEOPLE_PATH, JSON.stringify(people, null, 2) + "\n", "utf-8");
26248
26443
  }
26249
26444
  async function addPerson(person) {
@@ -26273,10 +26468,10 @@ function registerAddPerson(server2) {
26273
26468
  title: "Add Person",
26274
26469
  description: "Add or update a key human in the people roster. Used for co-founders, partners, customers \u2014 anyone agents need to know about.",
26275
26470
  inputSchema: {
26276
- name: z83.string().describe("Person's name"),
26277
- role: z83.string().describe("Their role (e.g. co-founder, customer, partner)"),
26278
- relationship: z83.string().describe("Relationship to the organization (e.g. co-founder, early adopter, investor)"),
26279
- notes: z83.string().optional().describe("Additional context about this person")
26471
+ name: z84.string().describe("Person's name"),
26472
+ role: z84.string().describe("Their role (e.g. co-founder, customer, partner)"),
26473
+ relationship: z84.string().describe("Relationship to the organization (e.g. co-founder, early adopter, investor)"),
26474
+ notes: z84.string().optional().describe("Additional context about this person")
26280
26475
  }
26281
26476
  },
26282
26477
  async ({ name, role, relationship, notes }) => {
@@ -26322,7 +26517,7 @@ function registerGetPerson(server2) {
26322
26517
  title: "Get Person",
26323
26518
  description: "Look up a specific person by name from the people roster.",
26324
26519
  inputSchema: {
26325
- name: z83.string().describe("Person's name to look up")
26520
+ name: z84.string().describe("Person's name to look up")
26326
26521
  }
26327
26522
  },
26328
26523
  async ({ name }) => {
@@ -26346,10 +26541,10 @@ Notes: ${person.notes}` : ""}`
26346
26541
  }
26347
26542
 
26348
26543
  // src/mcp/tools/crm.ts
26349
- import { z as z84 } from "zod";
26544
+ import { z as z85 } from "zod";
26350
26545
 
26351
26546
  // src/lib/exe-db-read.ts
26352
- import path46 from "path";
26547
+ import path48 from "path";
26353
26548
  import os19 from "os";
26354
26549
  import { createRequire as createRequire5 } from "module";
26355
26550
  import { pathToFileURL as pathToFileURL5 } from "url";
@@ -26367,8 +26562,8 @@ async function getExeDbReadClient() {
26367
26562
  if (!Ctor2) throw new Error(`No PrismaClient export found at ${explicitPath}`);
26368
26563
  return new Ctor2();
26369
26564
  }
26370
- const exeDbRoot = process.env.EXE_DB_ROOT ?? path46.join(os19.homedir(), "exe-db");
26371
- const req = createRequire5(path46.join(exeDbRoot, "package.json"));
26565
+ const exeDbRoot = process.env.EXE_DB_ROOT ?? path48.join(os19.homedir(), "exe-db");
26566
+ const req = createRequire5(path48.join(exeDbRoot, "package.json"));
26372
26567
  const entry = req.resolve("@prisma/client");
26373
26568
  const mod = await import(pathToFileURL5(entry).href);
26374
26569
  const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
@@ -26401,12 +26596,12 @@ function registerCrm(server2) {
26401
26596
  title: "CRM",
26402
26597
  description: "Read-only CRM access from exe-db crm schema. Actions: list_people, get_person, list_tables, describe_table.",
26403
26598
  inputSchema: {
26404
- action: z84.enum(["list_people", "get_person", "list_tables", "describe_table"]).describe("CRM read operation"),
26405
- id: z84.string().optional().describe("CRM row/person id for get_person"),
26406
- query: z84.string().optional().describe("Text search for list_people/get_person"),
26407
- table: z84.string().optional().describe("crm schema table name for describe_table"),
26408
- limit: z84.coerce.number().int().min(1).max(50).optional().describe("Max rows, capped at 50"),
26409
- offset: z84.coerce.number().int().min(0).optional().describe("Rows to skip")
26599
+ action: z85.enum(["list_people", "get_person", "list_tables", "describe_table"]).describe("CRM read operation"),
26600
+ id: z85.string().optional().describe("CRM row/person id for get_person"),
26601
+ query: z85.string().optional().describe("Text search for list_people/get_person"),
26602
+ table: z85.string().optional().describe("crm schema table name for describe_table"),
26603
+ limit: z85.coerce.number().int().min(1).max(50).optional().describe("Max rows, capped at 50"),
26604
+ offset: z85.coerce.number().int().min(0).optional().describe("Rows to skip")
26410
26605
  }
26411
26606
  }, async ({ action, id, query, table, limit, offset }) => {
26412
26607
  try {
@@ -26465,7 +26660,7 @@ function registerCrm(server2) {
26465
26660
  }
26466
26661
 
26467
26662
  // src/mcp/tools/raw-data.ts
26468
- import { z as z85 } from "zod";
26663
+ import { z as z86 } from "zod";
26469
26664
  function text2(content, isError = false) {
26470
26665
  return { content: [{ type: "text", text: content }], ...isError ? { isError: true } : {} };
26471
26666
  }
@@ -26474,15 +26669,15 @@ function registerRawData(server2) {
26474
26669
  title: "Raw Data",
26475
26670
  description: "Read-only access to exe-db raw.raw_events landing pad. Actions: list_sources, query, get. Results are capped because raw payloads can consume many tokens.",
26476
26671
  inputSchema: {
26477
- action: z85.enum(["list_sources", "query", "get"]).describe("Raw data read operation"),
26478
- id: z85.string().optional().describe("raw.raw_events id for action=get"),
26479
- source: z85.string().optional().describe("Filter by raw source"),
26480
- event_type: z85.string().optional().describe("Filter by event_type"),
26481
- query: z85.string().optional().describe("Search payload/metadata text"),
26482
- processed: z85.boolean().optional().describe("Filter processed_at IS NULL/NOT NULL"),
26483
- limit: z85.coerce.number().int().min(1).max(50).optional().describe("Max rows, capped at 50"),
26484
- offset: z85.coerce.number().int().min(0).optional().describe("Rows to skip"),
26485
- include_payload: z85.boolean().optional().describe("Include full payload JSON. Default false to save tokens.")
26672
+ action: z86.enum(["list_sources", "query", "get"]).describe("Raw data read operation"),
26673
+ id: z86.string().optional().describe("raw.raw_events id for action=get"),
26674
+ source: z86.string().optional().describe("Filter by raw source"),
26675
+ event_type: z86.string().optional().describe("Filter by event_type"),
26676
+ query: z86.string().optional().describe("Search payload/metadata text"),
26677
+ processed: z86.boolean().optional().describe("Filter processed_at IS NULL/NOT NULL"),
26678
+ limit: z86.coerce.number().int().min(1).max(50).optional().describe("Max rows, capped at 50"),
26679
+ offset: z86.coerce.number().int().min(0).optional().describe("Rows to skip"),
26680
+ include_payload: z86.boolean().optional().describe("Include full payload JSON. Default false to save tokens.")
26486
26681
  }
26487
26682
  }, async ({ action, id, source, event_type, query, processed, limit, offset, include_payload }) => {
26488
26683
  try {
@@ -26549,17 +26744,17 @@ init_active_agent();
26549
26744
  init_config();
26550
26745
  init_license();
26551
26746
  init_store();
26552
- import { z as z86 } from "zod";
26747
+ import { z as z87 } from "zod";
26553
26748
  import crypto18 from "crypto";
26554
26749
  import { mkdir as mkdir6, writeFile as writeFile7 } from "fs/promises";
26555
- import path47 from "path";
26556
- var CLASSIFICATION = z86.enum([
26750
+ import path49 from "path";
26751
+ var CLASSIFICATION = z87.enum([
26557
26752
  "upstream_bug",
26558
26753
  "customer_customization",
26559
26754
  "emergency_hotfix",
26560
26755
  "unclear"
26561
26756
  ]);
26562
- var SEVERITY = z86.enum(["p0", "p1", "p2", "p3"]);
26757
+ var SEVERITY = z87.enum(["p0", "p1", "p2", "p3"]);
26563
26758
  function slugify2(input) {
26564
26759
  return input.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80) || "bug-report";
26565
26760
  }
@@ -26637,22 +26832,22 @@ function registerCreateBugReport(server2) {
26637
26832
  title: "Create Bug Report",
26638
26833
  description: "Classify and file an exe-os issue as upstream_bug, customer_customization, emergency_hotfix, or unclear. Writes a local report, stores memory, and optionally sends to AskExe support when a support endpoint is configured.",
26639
26834
  inputSchema: {
26640
- title: z86.string().min(3).describe("Short descriptive title"),
26835
+ title: z87.string().min(3).describe("Short descriptive title"),
26641
26836
  classification: CLASSIFICATION.describe(
26642
26837
  "upstream_bug = platform defect; customer_customization = local preference; emergency_hotfix = temporary local patch; unclear = needs maintainer triage"
26643
26838
  ),
26644
26839
  severity: SEVERITY.default("p2").describe("p0 critical \u2192 p3 low"),
26645
- summary: z86.string().min(10).describe("What happened and why it matters"),
26646
- customer_impact: z86.string().optional().describe("How this affects the customer/founder"),
26647
- reproduction_steps: z86.array(z86.string()).optional().describe("Steps to reproduce"),
26648
- expected: z86.string().optional().describe("Expected behavior"),
26649
- actual: z86.string().optional().describe("Actual behavior"),
26650
- files_changed: z86.array(z86.string()).optional().describe("Files changed or suspected"),
26651
- workaround: z86.string().optional().describe("Temporary local workaround/hotfix, if any"),
26652
- local_patch_diff: z86.string().optional().describe("Small local diff or patch summary"),
26653
- package_version: z86.string().optional().describe("Installed @askexenow/exe-os version"),
26654
- project_name: z86.string().optional().describe("Project/customer context"),
26655
- send_upstream: z86.boolean().default(true).describe("Attempt to POST to configured AskExe support endpoint")
26840
+ summary: z87.string().min(10).describe("What happened and why it matters"),
26841
+ customer_impact: z87.string().optional().describe("How this affects the customer/founder"),
26842
+ reproduction_steps: z87.array(z87.string()).optional().describe("Steps to reproduce"),
26843
+ expected: z87.string().optional().describe("Expected behavior"),
26844
+ actual: z87.string().optional().describe("Actual behavior"),
26845
+ files_changed: z87.array(z87.string()).optional().describe("Files changed or suspected"),
26846
+ workaround: z87.string().optional().describe("Temporary local workaround/hotfix, if any"),
26847
+ local_patch_diff: z87.string().optional().describe("Small local diff or patch summary"),
26848
+ package_version: z87.string().optional().describe("Installed @askexenow/exe-os version"),
26849
+ project_name: z87.string().optional().describe("Project/customer context"),
26850
+ send_upstream: z87.boolean().default(true).describe("Attempt to POST to configured AskExe support endpoint")
26656
26851
  }
26657
26852
  },
26658
26853
  async ({
@@ -26692,9 +26887,9 @@ function registerCreateBugReport(server2) {
26692
26887
  filesChanged: files_changed,
26693
26888
  projectName: project_name
26694
26889
  });
26695
- const outDir = path47.join(EXE_AI_DIR, "bug-reports");
26890
+ const outDir = path49.join(EXE_AI_DIR, "bug-reports");
26696
26891
  await mkdir6(outDir, { recursive: true });
26697
- const reportPath = path47.join(outDir, `${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}-${slugify2(title)}-${id.slice(0, 8)}.md`);
26892
+ const reportPath = path49.join(outDir, `${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}-${slugify2(title)}-${id.slice(0, 8)}.md`);
26698
26893
  await writeFile7(reportPath, markdown, "utf-8");
26699
26894
  let vector = null;
26700
26895
  try {
@@ -26761,33 +26956,33 @@ Upstream status: ${upstreamStatus}`
26761
26956
  }
26762
26957
 
26763
26958
  // src/mcp/tools/code-context.ts
26764
- import { z as z87 } from "zod";
26959
+ import { z as z88 } from "zod";
26765
26960
 
26766
26961
  // src/lib/code-context-index.ts
26767
26962
  init_config();
26768
26963
  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";
26964
+ import path50 from "path";
26965
+ import { existsSync as existsSync39, mkdirSync as mkdirSync21, readFileSync as readFileSync32, statSync as statSync9, writeFileSync as writeFileSync23 } from "fs";
26771
26966
  import { spawnSync } from "child_process";
26772
26967
  var INDEX_VERSION = 1;
26773
26968
  var DEFAULT_MAX_FILES = 2e3;
26774
26969
  var CODE_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx"]);
26775
26970
  var IGNORE_SEGMENTS = /* @__PURE__ */ new Set(["node_modules", "dist", ".git", "coverage", ".worktrees", ".next", "build"]);
26776
26971
  function normalizeProjectRoot(projectRoot) {
26777
- return path48.resolve(projectRoot || process.cwd());
26972
+ return path50.resolve(projectRoot || process.cwd());
26778
26973
  }
26779
26974
  function hashText(text3) {
26780
26975
  return crypto19.createHash("sha256").update(text3).digest("hex");
26781
26976
  }
26782
26977
  function indexDir() {
26783
- const dir = path48.join(EXE_AI_DIR, "code-context");
26784
- mkdirSync20(dir, { recursive: true });
26978
+ const dir = path50.join(EXE_AI_DIR, "code-context");
26979
+ mkdirSync21(dir, { recursive: true });
26785
26980
  return dir;
26786
26981
  }
26787
26982
  function getCodeContextIndexPath(projectRoot) {
26788
26983
  const root = normalizeProjectRoot(projectRoot);
26789
26984
  const rootHash = hashText(root).slice(0, 16);
26790
- return path48.join(indexDir(), `${rootHash}.json`);
26985
+ return path50.join(indexDir(), `${rootHash}.json`);
26791
26986
  }
26792
26987
  function currentBranch(projectRoot) {
26793
26988
  const result2 = spawnSync("git", ["branch", "--show-current"], {
@@ -26799,11 +26994,11 @@ function currentBranch(projectRoot) {
26799
26994
  return branch || "detached-or-unknown";
26800
26995
  }
26801
26996
  function shouldIgnore(relPath) {
26802
- const parts = relPath.split(path48.sep);
26997
+ const parts = relPath.split(path50.sep);
26803
26998
  return parts.some((part) => IGNORE_SEGMENTS.has(part));
26804
26999
  }
26805
27000
  function isCodeFile(relPath) {
26806
- return CODE_EXTENSIONS.has(path48.extname(relPath).toLowerCase());
27001
+ return CODE_EXTENSIONS.has(path50.extname(relPath).toLowerCase());
26807
27002
  }
26808
27003
  function listCodeFiles(projectRoot, maxFiles) {
26809
27004
  const git = spawnSync("git", ["ls-files", "*.ts", "*.tsx", "*.js", "*.jsx"], {
@@ -26845,7 +27040,7 @@ function parseImportPaths(importText) {
26845
27040
  }
26846
27041
  function resolveImport(fromFile, importPath, allFiles) {
26847
27042
  if (!importPath.startsWith(".")) return null;
26848
- const base = path48.posix.normalize(path48.posix.join(path48.posix.dirname(fromFile.replaceAll(path48.sep, "/")), importPath));
27043
+ const base = path50.posix.normalize(path50.posix.join(path50.posix.dirname(fromFile.replaceAll(path50.sep, "/")), importPath));
26849
27044
  const withoutKnownExt = base.replace(/\.(?:js|jsx|ts|tsx)$/, "");
26850
27045
  const candidates = [
26851
27046
  base,
@@ -26857,10 +27052,10 @@ function resolveImport(fromFile, importPath, allFiles) {
26857
27052
  `${base}.tsx`,
26858
27053
  `${base}.js`,
26859
27054
  `${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")
27055
+ path50.posix.join(base, "index.ts"),
27056
+ path50.posix.join(base, "index.tsx"),
27057
+ path50.posix.join(base, "index.js"),
27058
+ path50.posix.join(base, "index.jsx")
26864
27059
  ];
26865
27060
  return candidates.find((candidate) => allFiles.has(candidate)) ?? null;
26866
27061
  }
@@ -26869,9 +27064,9 @@ function symbolId(filePath, chunk) {
26869
27064
  }
26870
27065
  function loadIndex(projectRoot) {
26871
27066
  const file = getCodeContextIndexPath(projectRoot);
26872
- if (!existsSync37(file)) return null;
27067
+ if (!existsSync39(file)) return null;
26873
27068
  try {
26874
- const parsed = JSON.parse(readFileSync30(file, "utf8"));
27069
+ const parsed = JSON.parse(readFileSync32(file, "utf8"));
26875
27070
  if (parsed.version !== INDEX_VERSION || parsed.projectRoot !== projectRoot) return null;
26876
27071
  return parsed;
26877
27072
  } catch {
@@ -26879,18 +27074,18 @@ function loadIndex(projectRoot) {
26879
27074
  }
26880
27075
  }
26881
27076
  function saveIndex(index) {
26882
- writeFileSync22(getCodeContextIndexPath(index.projectRoot), JSON.stringify(index, null, 2));
27077
+ writeFileSync23(getCodeContextIndexPath(index.projectRoot), JSON.stringify(index, null, 2));
26883
27078
  }
26884
27079
  function buildFileRecord(projectRoot, relPath, allFiles, previous) {
26885
- const absPath = path48.join(projectRoot, relPath);
27080
+ const absPath = path50.join(projectRoot, relPath);
26886
27081
  let stat;
26887
27082
  try {
26888
- stat = statSync8(absPath);
27083
+ stat = statSync9(absPath);
26889
27084
  } catch {
26890
27085
  return null;
26891
27086
  }
26892
27087
  if (!stat.isFile()) return null;
26893
- const source = readFileSync30(absPath, "utf8");
27088
+ const source = readFileSync32(absPath, "utf8");
26894
27089
  const hash = hashText(source);
26895
27090
  if (previous && previous.hash === hash && previous.mtimeMs === stat.mtimeMs && previous.size === stat.size) {
26896
27091
  return previous;
@@ -26927,10 +27122,10 @@ function buildCodeContextIndex(options = {}) {
26927
27122
  const branch = currentBranch(projectRoot);
26928
27123
  const previous = options.force ? null : loadIndex(projectRoot);
26929
27124
  const files = listCodeFiles(projectRoot, maxFiles);
26930
- const allFiles = new Set(files.map((file) => file.replaceAll(path48.sep, "/")));
27125
+ const allFiles = new Set(files.map((file) => file.replaceAll(path50.sep, "/")));
26931
27126
  const fileRecords = {};
26932
27127
  for (const rel of files) {
26933
- const normalized = rel.replaceAll(path48.sep, "/");
27128
+ const normalized = rel.replaceAll(path50.sep, "/");
26934
27129
  const record = buildFileRecord(projectRoot, normalized, allFiles, previous?.files[normalized]);
26935
27130
  if (record) fileRecords[normalized] = record;
26936
27131
  }
@@ -26952,11 +27147,11 @@ function loadOrBuildCodeContextIndex(options = {}) {
26952
27147
  if (loaded) {
26953
27148
  const currentFiles = listCodeFiles(projectRoot, options.maxFiles ?? DEFAULT_MAX_FILES);
26954
27149
  const unchanged = currentFiles.every((rel) => {
26955
- const normalized = rel.replaceAll(path48.sep, "/");
27150
+ const normalized = rel.replaceAll(path50.sep, "/");
26956
27151
  const existing = loaded.files[normalized];
26957
27152
  if (!existing) return false;
26958
27153
  try {
26959
- const stat = statSync8(path48.join(projectRoot, normalized));
27154
+ const stat = statSync9(path50.join(projectRoot, normalized));
26960
27155
  return stat.mtimeMs === existing.mtimeMs && stat.size === existing.size;
26961
27156
  } catch {
26962
27157
  return false;
@@ -27059,7 +27254,7 @@ function traceCodeSymbol(symbolName, options = {}) {
27059
27254
  }
27060
27255
  function resolveTargetFile(index, input) {
27061
27256
  if (input.filePath) {
27062
- const normalized = input.filePath.replaceAll(path48.sep, "/").replace(/^\.\//, "");
27257
+ const normalized = input.filePath.replaceAll(path50.sep, "/").replace(/^\.\//, "");
27063
27258
  if (index.files[normalized]) return { filePath: normalized, target: normalized };
27064
27259
  const suffix = Object.keys(index.files).find((file) => file.endsWith(normalized));
27065
27260
  if (suffix) return { filePath: suffix, target: input.filePath };
@@ -27089,7 +27284,7 @@ function analyzeBlastRadius(input) {
27089
27284
  }
27090
27285
  }
27091
27286
  }
27092
- const targetBase = path48.basename(target.filePath).replace(/\.[^.]+$/, "").toLowerCase();
27287
+ const targetBase = path50.basename(target.filePath).replace(/\.[^.]+$/, "").toLowerCase();
27093
27288
  const symbolLower = input.symbol?.toLowerCase();
27094
27289
  const tests = Object.keys(index.files).filter((file) => {
27095
27290
  const lower = file.toLowerCase();
@@ -27135,15 +27330,15 @@ function registerCodeContext(server2) {
27135
27330
  title: "Code Context",
27136
27331
  description: "Persistent codebase context engine. One consolidated tool to avoid MCP bloat. Actions: index, search, trace, blast_radius, stats.",
27137
27332
  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")
27333
+ action: z88.enum(["index", "search", "trace", "blast_radius", "stats"]).describe("Code context operation"),
27334
+ project_root: z88.string().optional().describe("Repository root. Defaults to current working directory."),
27335
+ query: z88.string().optional().describe("Search query for action=search"),
27336
+ symbol: z88.string().optional().describe("Symbol/function/class/type name for trace or blast_radius"),
27337
+ file_path: z88.string().optional().describe("File path for blast_radius"),
27338
+ force: z88.boolean().optional().describe("Force rebuild before answering"),
27339
+ limit: z88.coerce.number().int().min(1).max(100).optional().describe("Max results"),
27340
+ depth: z88.coerce.number().int().min(1).max(5).optional().describe("Dependent traversal depth for blast_radius"),
27341
+ max_files: z88.coerce.number().int().min(1).max(1e4).optional().describe("Max code files to index")
27147
27342
  }
27148
27343
  }, async ({ action, project_root, query, symbol, file_path, force, limit, depth, max_files }) => {
27149
27344
  const opts = { projectRoot: project_root, force, maxFiles: max_files };
@@ -27180,9 +27375,9 @@ function registerCodeContext(server2) {
27180
27375
  }
27181
27376
 
27182
27377
  // src/mcp/tools/support-inbox.ts
27183
- import { z as z88 } from "zod";
27378
+ import { z as z89 } from "zod";
27184
27379
  var DEFAULT_ENDPOINT = "https://askexe.com/admin/support/bug-reports";
27185
- var STATUS = z88.enum(["open", "triaged", "fixed", "closed", "wontfix"]);
27380
+ var STATUS = z89.enum(["open", "triaged", "fixed", "closed", "wontfix"]);
27186
27381
  function adminToken() {
27187
27382
  return process.env.ASKEXE_SUPPORT_ADMIN_TOKEN || process.env.EXE_SUPPORT_ADMIN_TOKEN;
27188
27383
  }
@@ -27221,9 +27416,9 @@ function registerListBugReports(server2) {
27221
27416
  title: "List Bug Reports",
27222
27417
  description: "AskExe-internal only: list incoming customer bug reports from the support inbox.",
27223
27418
  inputSchema: {
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)
27419
+ status: z89.enum(["all", "open", "triaged", "fixed", "closed", "wontfix"]).default("open"),
27420
+ severity: z89.enum(["p0", "p1", "p2", "p3"]).optional(),
27421
+ limit: z89.number().int().min(1).max(100).default(25)
27227
27422
  }
27228
27423
  },
27229
27424
  async ({ status, severity, limit }) => {
@@ -27242,7 +27437,7 @@ function registerGetBugReport(server2) {
27242
27437
  {
27243
27438
  title: "Get Bug Report",
27244
27439
  description: "AskExe-internal only: fetch one customer bug report with full markdown payload.",
27245
- inputSchema: { id: z88.string().min(8) }
27440
+ inputSchema: { id: z89.string().min(8) }
27246
27441
  },
27247
27442
  async ({ id }) => {
27248
27443
  const data = await requestJson(`${endpoint()}/${encodeURIComponent(id)}`);
@@ -27257,12 +27452,12 @@ function registerTriageBugReport(server2) {
27257
27452
  title: "Triage Bug Report",
27258
27453
  description: "AskExe-internal only: update bug report status and link task/commit/release metadata.",
27259
27454
  inputSchema: {
27260
- id: z88.string().min(8),
27455
+ id: z89.string().min(8),
27261
27456
  status: STATUS.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()
27457
+ triage_notes: z89.string().optional(),
27458
+ linked_task_id: z89.string().optional(),
27459
+ linked_commit: z89.string().optional(),
27460
+ fixed_version: z89.string().optional()
27266
27461
  }
27267
27462
  },
27268
27463
  async ({ id, status, triage_notes, linked_task_id, linked_commit, fixed_version }) => {
@@ -27388,6 +27583,7 @@ var TOOL_CATEGORIES = {
27388
27583
  registerDeployClient: "admin",
27389
27584
  registerBackupVps: "admin",
27390
27585
  registerGetDaemonHealth: "admin",
27586
+ registerMcpPing: "core",
27391
27587
  registerGetAutoWakeStatus: "admin",
27392
27588
  registerGetWorkerGate: "admin",
27393
27589
  registerRunMemoryAudit: "admin",
@@ -27425,6 +27621,7 @@ var CHIEF_OF_STAFF_READ_TOOLS = /* @__PURE__ */ new Set([
27425
27621
  "registerSearchEverything",
27426
27622
  "registerGetDecision",
27427
27623
  "registerGetIdentity",
27624
+ "registerMcpPing",
27428
27625
  "registerListTasks",
27429
27626
  "registerGetTask",
27430
27627
  "registerListReminders",
@@ -27597,6 +27794,7 @@ function registerAllTools(server2) {
27597
27794
  if (exposeLegacyConfig) {
27598
27795
  gate("registerGetAgentSpend", registerGetAgentSpend);
27599
27796
  }
27797
+ gate("registerMcpPing", registerMcpPing);
27600
27798
  if (exposeLegacyGraph) {
27601
27799
  gate("registerGetGraphStats", registerGetGraphStats);
27602
27800
  gate("registerGetEntityNeighbors", registerGetEntityNeighbors);
@@ -27758,16 +27956,16 @@ try {
27758
27956
  }
27759
27957
  }, 3e4);
27760
27958
  _ppidWatchdog.unref();
27761
- const MCP_VERSION_PATH = path49.join(os20.homedir(), ".exe-os", "mcp-version");
27959
+ const MCP_VERSION_PATH = path51.join(os20.homedir(), ".exe-os", "mcp-version");
27762
27960
  let _currentMcpVersion = null;
27763
27961
  try {
27764
- _currentMcpVersion = existsSync38(MCP_VERSION_PATH) ? readFileSync31(MCP_VERSION_PATH, "utf8").trim() : null;
27962
+ _currentMcpVersion = existsSync40(MCP_VERSION_PATH) ? readFileSync33(MCP_VERSION_PATH, "utf8").trim() : null;
27765
27963
  } catch {
27766
27964
  }
27767
27965
  const _versionWatchdog = setInterval(() => {
27768
27966
  try {
27769
- if (!existsSync38(MCP_VERSION_PATH)) return;
27770
- const diskVersion = readFileSync31(MCP_VERSION_PATH, "utf8").trim();
27967
+ if (!existsSync40(MCP_VERSION_PATH)) return;
27968
+ const diskVersion = readFileSync33(MCP_VERSION_PATH, "utf8").trim();
27771
27969
  if (_currentMcpVersion && diskVersion !== _currentMcpVersion) {
27772
27970
  process.stderr.write(
27773
27971
  `[exe-os] MCP version changed (${_currentMcpVersion} \u2192 ${diskVersion}). Hot-reloading...
@@ -27799,18 +27997,18 @@ try {
27799
27997
  `[exe-os] Periodic backfill: ${nullCount} NULL vectors \u2014 spawning job
27800
27998
  `
27801
27999
  );
27802
- const thisFile = fileURLToPath5(import.meta.url);
27803
- const backfillPath = path49.resolve(
27804
- path49.dirname(thisFile),
28000
+ const thisFile = fileURLToPath6(import.meta.url);
28001
+ const backfillPath = path51.resolve(
28002
+ path51.dirname(thisFile),
27805
28003
  "../bin/backfill-vectors.js"
27806
28004
  );
27807
- if (existsSync38(backfillPath)) {
28005
+ if (existsSync40(backfillPath)) {
27808
28006
  const { EXE_AI_DIR: exeDir } = await Promise.resolve().then(() => (init_config(), config_exports));
27809
- const logPath = path49.join(exeDir, "workers.log");
27810
- mkdirSync21(path49.dirname(logPath), { recursive: true });
28007
+ const logPath = path51.join(exeDir, "workers.log");
28008
+ mkdirSync22(path51.dirname(logPath), { recursive: true });
27811
28009
  let logFd = "ignore";
27812
28010
  try {
27813
- logFd = openSync3(logPath, "a");
28011
+ logFd = openSync4(logPath, "a");
27814
28012
  } catch {
27815
28013
  }
27816
28014
  const child = spawn4(process.execPath, [backfillPath], {
@@ -27820,7 +28018,7 @@ try {
27820
28018
  child.unref();
27821
28019
  if (child.pid) registerWorkerPid2(child.pid);
27822
28020
  if (typeof logFd === "number") try {
27823
- closeSync3(logFd);
28021
+ closeSync4(logFd);
27824
28022
  } catch {
27825
28023
  }
27826
28024
  } else {