@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.
@@ -3655,6 +3655,170 @@ var init_memory_write_governor = __esm({
3655
3655
  }
3656
3656
  });
3657
3657
 
3658
+ // src/lib/mcp-transport-health.ts
3659
+ import { appendFileSync, closeSync as closeSync2, existsSync as existsSync8, mkdirSync as mkdirSync2, openSync as openSync2, readFileSync as readFileSync7, readSync, statSync as statSync2, writeFileSync as writeFileSync5 } from "fs";
3660
+ import path8 from "path";
3661
+ import { fileURLToPath as fileURLToPath2 } from "url";
3662
+ function parsePositiveInt(value, fallback) {
3663
+ if (!value) return fallback;
3664
+ const parsed = Number.parseInt(value, 10);
3665
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
3666
+ }
3667
+ function readTailText(filePath, maxBytes) {
3668
+ const stats = statSync2(filePath);
3669
+ if (stats.size <= maxBytes) return readFileSync7(filePath, "utf8");
3670
+ const fd = openSync2(filePath, "r");
3671
+ try {
3672
+ const buffer = Buffer.allocUnsafe(maxBytes);
3673
+ readSync(fd, buffer, 0, maxBytes, stats.size - maxBytes);
3674
+ const text3 = buffer.toString("utf8");
3675
+ const firstNewline = text3.indexOf("\n");
3676
+ return firstNewline >= 0 ? text3.slice(firstNewline + 1) : text3;
3677
+ } finally {
3678
+ closeSync2(fd);
3679
+ }
3680
+ }
3681
+ function rotateMcpHttpEventLogIfNeeded() {
3682
+ if (!existsSync8(MCP_HTTP_EVENTS_PATH)) return;
3683
+ const stats = statSync2(MCP_HTTP_EVENTS_PATH);
3684
+ if (stats.size <= EVENT_MAX_BYTES) return;
3685
+ const keepBytes = Math.min(EVENT_READ_BYTES, EVENT_MAX_BYTES);
3686
+ const tail = readTailText(MCP_HTTP_EVENTS_PATH, keepBytes);
3687
+ writeFileSync5(MCP_HTTP_EVENTS_PATH, tail, "utf8");
3688
+ }
3689
+ function readPackageVersion() {
3690
+ let dir = path8.dirname(fileURLToPath2(import.meta.url));
3691
+ const { root } = path8.parse(dir);
3692
+ while (dir !== root) {
3693
+ const pkgPath = path8.join(dir, "package.json");
3694
+ if (existsSync8(pkgPath)) {
3695
+ try {
3696
+ const parsed = JSON.parse(readFileSync7(pkgPath, "utf8"));
3697
+ return parsed.version ?? "unknown";
3698
+ } catch {
3699
+ return "unknown";
3700
+ }
3701
+ }
3702
+ dir = path8.dirname(dir);
3703
+ }
3704
+ return "unknown";
3705
+ }
3706
+ function inferMcpRuntime(input) {
3707
+ const text3 = [input.runtimeHeader, input.userAgent, input.agentId, input.clientName].filter(Boolean).join(" ").toLowerCase();
3708
+ if (text3.includes("codex")) return "Codex";
3709
+ if (text3.includes("claude")) return "Claude";
3710
+ if (text3.includes("opencode") || text3.includes("open-code")) return "OpenCode";
3711
+ return "Unknown";
3712
+ }
3713
+ function getMcpToolFamily(toolName) {
3714
+ if (!toolName) return "unknown";
3715
+ if (/task|employee|review|checkpoint|resume/i.test(toolName)) return "task";
3716
+ if (/memory|consolidat|document|search_everything|get_session_context/i.test(toolName)) return "memory";
3717
+ if (/config|daemon|worker|auto_wake|license|trigger|starter|orchestration|cloud_sync|backup/i.test(toolName)) return "config";
3718
+ if (/message|whatsapp|conversation|gateway/i.test(toolName)) return "gateway";
3719
+ if (/wiki|crm|raw_data|person|people/i.test(toolName)) return "company-data";
3720
+ if (/graph|entity|relationship|trajectory/i.test(toolName)) return "graph";
3721
+ if (/identity|behavior|decision|procedure/i.test(toolName)) return "cognition";
3722
+ if (/ping|health/i.test(toolName)) return "health";
3723
+ return "other";
3724
+ }
3725
+ function parseMcpHttpEventLines(raw, limit = 200) {
3726
+ const lines = raw.trim().split("\n").filter(Boolean).slice(-limit);
3727
+ const events = [];
3728
+ for (const line of lines) {
3729
+ try {
3730
+ events.push(JSON.parse(line));
3731
+ } catch {
3732
+ }
3733
+ }
3734
+ return events;
3735
+ }
3736
+ function readMcpHttpEvents(limit = 200) {
3737
+ if (!existsSync8(MCP_HTTP_EVENTS_PATH)) return [];
3738
+ const raw = readTailText(MCP_HTTP_EVENTS_PATH, EVENT_READ_BYTES);
3739
+ return parseMcpHttpEventLines(raw, limit);
3740
+ }
3741
+ function summarizeMcpTransport(events = readMcpHttpEvents()) {
3742
+ const lastServerStartIndex = events.map((event) => event.message).lastIndexOf("server_started");
3743
+ const scopedEvents = lastServerStartIndex >= 0 ? events.slice(lastServerStartIndex) : events;
3744
+ const activeSessionEvent = [...scopedEvents].reverse().find((event) => typeof event.activeSessions === "number");
3745
+ const successfulToolCalls = scopedEvents.filter((event) => event.message === "tool_call_ok");
3746
+ const lastSuccessfulToolCall = successfulToolCalls.at(-1) ?? null;
3747
+ const summary = {
3748
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
3749
+ version: readPackageVersion(),
3750
+ scope: "local",
3751
+ privacy: "metadata_only",
3752
+ eventLogPath: MCP_HTTP_EVENTS_PATH,
3753
+ activeSessions: activeSessionEvent?.activeSessions ?? null,
3754
+ sessionsCreated: scopedEvents.filter((event) => event.message === "session_initialized").length,
3755
+ sessionsClosed: scopedEvents.filter((event) => event.message === "session_closed").length,
3756
+ missingSessionErrors: scopedEvents.filter((event) => event.message?.includes("missing MCP session")).length,
3757
+ staleSessionErrors: scopedEvents.filter((event) => event.message?.includes("stale or unknown")).length,
3758
+ transportErrors: scopedEvents.filter((event) => event.level === "warn" || event.level === "error").length,
3759
+ lastSuccessfulHandshake: scopedEvents.filter((event) => event.message === "session_initialized").at(-1)?.timestamp ?? null,
3760
+ lastSuccessfulToolCall: lastSuccessfulToolCall?.timestamp ?? null,
3761
+ lastSuccessfulToolCallByRuntime: {},
3762
+ lastSuccessfulToolCallByAgent: {},
3763
+ lastSuccessfulToolCallByFamily: {},
3764
+ activeSessionsByRuntime: {},
3765
+ recentWarnings: scopedEvents.filter((event) => event.level === "warn" || event.level === "error").slice(-10),
3766
+ remediation: [
3767
+ "If MCP tools fail with missing/stale session, reconnect the MCP client (/mcp or restart the runtime).",
3768
+ "Do not access the database directly; MCP is the only data interface.",
3769
+ "Check get_daemon_health or exe-healthcheck for daemon/MCP endpoint status before retrying work."
3770
+ ]
3771
+ };
3772
+ const createdBySession = /* @__PURE__ */ new Map();
3773
+ for (const event of scopedEvents) {
3774
+ if (event.message === "session_initialized" && event.sessionId) createdBySession.set(event.sessionId, event);
3775
+ if ((event.message === "session_closed" || event.message === "session_expired") && event.sessionId) {
3776
+ createdBySession.delete(event.sessionId);
3777
+ }
3778
+ }
3779
+ for (const event of createdBySession.values()) {
3780
+ const runtime = event.runtime ?? "Unknown";
3781
+ summary.activeSessionsByRuntime[runtime] = (summary.activeSessionsByRuntime[runtime] ?? 0) + 1;
3782
+ }
3783
+ for (const event of successfulToolCalls) {
3784
+ if (event.runtime) summary.lastSuccessfulToolCallByRuntime[event.runtime] = event.timestamp ?? "";
3785
+ if (event.agentId) summary.lastSuccessfulToolCallByAgent[event.agentId] = event.timestamp ?? "";
3786
+ if (event.toolFamily) summary.lastSuccessfulToolCallByFamily[event.toolFamily] = event.timestamp ?? "";
3787
+ }
3788
+ return summary;
3789
+ }
3790
+ function writeMcpTransportSummary(events) {
3791
+ try {
3792
+ mkdirSync2(MCP_MONITOR_DIR, { recursive: true });
3793
+ writeFileSync5(MCP_TRANSPORT_SUMMARY_PATH, JSON.stringify(summarizeMcpTransport(events), null, 2) + "\n");
3794
+ } catch {
3795
+ }
3796
+ }
3797
+ function recordMcpHttpEvent(event) {
3798
+ try {
3799
+ mkdirSync2(EXE_AI_DIR, { recursive: true });
3800
+ const enriched = { timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...event };
3801
+ appendFileSync(MCP_HTTP_EVENTS_PATH, JSON.stringify(enriched) + "\n");
3802
+ rotateMcpHttpEventLogIfNeeded();
3803
+ writeMcpTransportSummary(readMcpHttpEvents());
3804
+ } catch {
3805
+ }
3806
+ }
3807
+ var MCP_HTTP_EVENTS_PATH, MCP_MONITOR_DIR, MCP_TRANSPORT_SUMMARY_PATH, DEFAULT_EVENT_READ_BYTES, DEFAULT_EVENT_MAX_BYTES, EVENT_READ_BYTES, EVENT_MAX_BYTES;
3808
+ var init_mcp_transport_health = __esm({
3809
+ "src/lib/mcp-transport-health.ts"() {
3810
+ "use strict";
3811
+ init_config();
3812
+ MCP_HTTP_EVENTS_PATH = path8.join(EXE_AI_DIR, "mcp-http-events.jsonl");
3813
+ MCP_MONITOR_DIR = path8.join(EXE_AI_DIR, "monitor");
3814
+ MCP_TRANSPORT_SUMMARY_PATH = path8.join(MCP_MONITOR_DIR, "mcp-transport-summary.json");
3815
+ DEFAULT_EVENT_READ_BYTES = 256 * 1024;
3816
+ DEFAULT_EVENT_MAX_BYTES = 1024 * 1024;
3817
+ EVENT_READ_BYTES = parsePositiveInt(process.env.EXE_MCP_HTTP_EVENT_READ_BYTES, DEFAULT_EVENT_READ_BYTES);
3818
+ EVENT_MAX_BYTES = parsePositiveInt(process.env.EXE_MCP_HTTP_EVENT_MAX_BYTES, DEFAULT_EVENT_MAX_BYTES);
3819
+ }
3820
+ });
3821
+
3658
3822
  // src/lib/agentic-ontology.ts
3659
3823
  var agentic_ontology_exports = {};
3660
3824
  __export(agentic_ontology_exports, {
@@ -3936,8 +4100,8 @@ __export(projection_worker_exports, {
3936
4100
  stopProjectionWorker: () => stopProjectionWorker
3937
4101
  });
3938
4102
  import os5 from "os";
3939
- import path8 from "path";
3940
- import { existsSync as existsSync8 } from "fs";
4103
+ import path9 from "path";
4104
+ import { existsSync as existsSync9 } from "fs";
3941
4105
  import { createRequire as createRequire2 } from "module";
3942
4106
  import { pathToFileURL as pathToFileURL2 } from "url";
3943
4107
  function loadPrisma() {
@@ -3950,9 +4114,9 @@ function loadPrisma() {
3950
4114
  if (!Ctor) throw new Error(`No PrismaClient at ${explicitPath}`);
3951
4115
  return new Ctor();
3952
4116
  }
3953
- const exeDbRoot = process.env.EXE_DB_ROOT ?? path8.join(os5.homedir(), "exe-db");
3954
- const packagePath = path8.join(exeDbRoot, "package.json");
3955
- if (existsSync8(packagePath)) {
4117
+ const exeDbRoot = process.env.EXE_DB_ROOT ?? path9.join(os5.homedir(), "exe-db");
4118
+ const packagePath = path9.join(exeDbRoot, "package.json");
4119
+ if (existsSync9(packagePath)) {
3956
4120
  const req = createRequire2(packagePath);
3957
4121
  const entry = req.resolve("@prisma/client");
3958
4122
  const mod = await import(pathToFileURL2(entry).href);
@@ -4386,8 +4550,8 @@ async function shouldStartProjectionWorker() {
4386
4550
  if (!process.env.DATABASE_URL) {
4387
4551
  return { start: false, reason: "DATABASE_URL is not set" };
4388
4552
  }
4389
- const exeDbRoot = process.env.EXE_DB_ROOT ?? path8.join(os5.homedir(), "exe-db");
4390
- if (!existsSync8(path8.join(exeDbRoot, "package.json")) && !process.env.EXE_OS_PRISMA_CLIENT_PATH) {
4553
+ const exeDbRoot = process.env.EXE_DB_ROOT ?? path9.join(os5.homedir(), "exe-db");
4554
+ if (!existsSync9(path9.join(exeDbRoot, "package.json")) && !process.env.EXE_OS_PRISMA_CLIENT_PATH) {
4391
4555
  try {
4392
4556
  await import("pg");
4393
4557
  } catch {
@@ -4592,13 +4756,13 @@ __export(shard_manager_exports, {
4592
4756
  listShards: () => listShards,
4593
4757
  shardExists: () => shardExists
4594
4758
  });
4595
- import path9 from "path";
4596
- import { existsSync as existsSync9, mkdirSync as mkdirSync2, readdirSync, renameSync as renameSync3, statSync as statSync2 } from "fs";
4759
+ import path10 from "path";
4760
+ import { existsSync as existsSync10, mkdirSync as mkdirSync3, readdirSync, renameSync as renameSync3, statSync as statSync3 } from "fs";
4597
4761
  import { createClient as createClient2 } from "@libsql/client";
4598
4762
  function initShardManager(encryptionKey) {
4599
4763
  _encryptionKey = encryptionKey;
4600
- if (!existsSync9(SHARDS_DIR)) {
4601
- mkdirSync2(SHARDS_DIR, { recursive: true });
4764
+ if (!existsSync10(SHARDS_DIR)) {
4765
+ mkdirSync3(SHARDS_DIR, { recursive: true });
4602
4766
  }
4603
4767
  _shardingEnabled = true;
4604
4768
  if (_evictionTimer) clearInterval(_evictionTimer);
@@ -4627,7 +4791,7 @@ function getShardClient(projectName) {
4627
4791
  while (_shards.size >= MAX_OPEN_SHARDS) {
4628
4792
  evictLRU();
4629
4793
  }
4630
- const dbPath = path9.join(SHARDS_DIR, `${safeName}.db`);
4794
+ const dbPath = path10.join(SHARDS_DIR, `${safeName}.db`);
4631
4795
  const client = createClient2({
4632
4796
  url: `file:${dbPath}`,
4633
4797
  encryptionKey: _encryptionKey
@@ -4638,13 +4802,13 @@ function getShardClient(projectName) {
4638
4802
  }
4639
4803
  function shardExists(projectName) {
4640
4804
  const safeName = safeShardName(projectName);
4641
- return existsSync9(path9.join(SHARDS_DIR, `${safeName}.db`));
4805
+ return existsSync10(path10.join(SHARDS_DIR, `${safeName}.db`));
4642
4806
  }
4643
4807
  function safeShardName(projectName) {
4644
4808
  return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
4645
4809
  }
4646
4810
  function listShards() {
4647
- if (!existsSync9(SHARDS_DIR)) return [];
4811
+ if (!existsSync10(SHARDS_DIR)) return [];
4648
4812
  return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
4649
4813
  }
4650
4814
  async function auditShardHealth(options = {}) {
@@ -4656,8 +4820,8 @@ async function auditShardHealth(options = {}) {
4656
4820
  const names = listShards();
4657
4821
  const shards = [];
4658
4822
  for (const name of names) {
4659
- const dbPath = path9.join(SHARDS_DIR, `${name}.db`);
4660
- const stat = statSync2(dbPath);
4823
+ const dbPath = path10.join(SHARDS_DIR, `${name}.db`);
4824
+ const stat = statSync3(dbPath);
4661
4825
  const item = {
4662
4826
  name,
4663
4827
  path: dbPath,
@@ -4691,7 +4855,7 @@ async function auditShardHealth(options = {}) {
4691
4855
  _shards.delete(name);
4692
4856
  _shardLastAccess.delete(name);
4693
4857
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
4694
- const archivedPath = path9.join(SHARDS_DIR, `${name}.db.broken-${stamp}`);
4858
+ const archivedPath = path10.join(SHARDS_DIR, `${name}.db.broken-${stamp}`);
4695
4859
  renameSync3(dbPath, archivedPath);
4696
4860
  item.archivedPath = archivedPath;
4697
4861
  }
@@ -4908,11 +5072,11 @@ async function getReadyShardClient(projectName) {
4908
5072
  client.close();
4909
5073
  _shards.delete(safeName);
4910
5074
  _shardLastAccess.delete(safeName);
4911
- const dbPath = path9.join(SHARDS_DIR, `${safeName}.db`);
4912
- if (existsSync9(dbPath)) {
4913
- const stat = statSync2(dbPath);
5075
+ const dbPath = path10.join(SHARDS_DIR, `${safeName}.db`);
5076
+ if (existsSync10(dbPath)) {
5077
+ const stat = statSync3(dbPath);
4914
5078
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
4915
- const archivedPath = path9.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
5079
+ const archivedPath = path10.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
4916
5080
  renameSync3(dbPath, archivedPath);
4917
5081
  process.stderr.write(
4918
5082
  `[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
@@ -4980,7 +5144,7 @@ var init_shard_manager = __esm({
4980
5144
  "src/lib/shard-manager.ts"() {
4981
5145
  "use strict";
4982
5146
  init_config();
4983
- SHARDS_DIR = path9.join(EXE_AI_DIR, "shards");
5147
+ SHARDS_DIR = path10.join(EXE_AI_DIR, "shards");
4984
5148
  SHARD_IDLE_MS = 5 * 60 * 1e3;
4985
5149
  MAX_OPEN_SHARDS = 10;
4986
5150
  EVICTION_INTERVAL_MS = 60 * 1e3;
@@ -5003,15 +5167,15 @@ __export(keychain_exports, {
5003
5167
  setMasterKey: () => setMasterKey
5004
5168
  });
5005
5169
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
5006
- import { existsSync as existsSync10, statSync as statSync3 } from "fs";
5170
+ import { existsSync as existsSync11, statSync as statSync4 } from "fs";
5007
5171
  import { execSync as execSync2 } from "child_process";
5008
- import path10 from "path";
5172
+ import path11 from "path";
5009
5173
  import os6 from "os";
5010
5174
  function getKeyDir() {
5011
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path10.join(os6.homedir(), ".exe-os");
5175
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path11.join(os6.homedir(), ".exe-os");
5012
5176
  }
5013
5177
  function getKeyPath() {
5014
- return path10.join(getKeyDir(), "master.key");
5178
+ return path11.join(getKeyDir(), "master.key");
5015
5179
  }
5016
5180
  function nativeKeychainAllowed() {
5017
5181
  return process.env.EXE_OS_DISABLE_NATIVE_KEYCHAIN !== "1";
@@ -5038,11 +5202,11 @@ function isRootOnlyTrustedServerKeyFile(keyPath) {
5038
5202
  if (process.platform !== "linux") return false;
5039
5203
  try {
5040
5204
  const uid = typeof os6.userInfo().uid === "number" ? os6.userInfo().uid : -1;
5041
- const st = statSync3(keyPath);
5205
+ const st = statSync4(keyPath);
5042
5206
  if (!st.isFile() || (st.mode & 63) !== 0) return false;
5043
5207
  if (uid === 0) return true;
5044
5208
  const exeOsDir = process.env.EXE_OS_DIR;
5045
- return Boolean(exeOsDir && path10.resolve(keyPath).startsWith(path10.resolve(exeOsDir) + path10.sep));
5209
+ return Boolean(exeOsDir && path11.resolve(keyPath).startsWith(path11.resolve(exeOsDir) + path11.sep));
5046
5210
  } catch {
5047
5211
  return false;
5048
5212
  }
@@ -5154,8 +5318,8 @@ function deriveMachineKey() {
5154
5318
  }
5155
5319
  function readMachineId() {
5156
5320
  try {
5157
- const { readFileSync: readFileSync38 } = __require("fs");
5158
- return readFileSync38("/etc/machine-id", "utf-8").trim();
5321
+ const { readFileSync: readFileSync40 } = __require("fs");
5322
+ return readFileSync40("/etc/machine-id", "utf-8").trim();
5159
5323
  } catch {
5160
5324
  return "";
5161
5325
  }
@@ -5239,7 +5403,7 @@ async function getMasterKey() {
5239
5403
  }
5240
5404
  }
5241
5405
  const keyPath = getKeyPath();
5242
- if (!existsSync10(keyPath)) {
5406
+ if (!existsSync11(keyPath)) {
5243
5407
  process.stderr.write(
5244
5408
  `[keychain] Key not found at ${keyPath} (HOME=${os6.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
5245
5409
  `
@@ -5347,7 +5511,7 @@ async function getKeyStorageInfo() {
5347
5511
  }
5348
5512
  }
5349
5513
  const keyPath = getKeyPath();
5350
- if (!existsSync10(keyPath)) {
5514
+ if (!existsSync11(keyPath)) {
5351
5515
  return {
5352
5516
  kind: "missing",
5353
5517
  secure: false,
@@ -5424,7 +5588,7 @@ async function deleteMasterKey() {
5424
5588
  }
5425
5589
  }
5426
5590
  const keyPath = getKeyPath();
5427
- if (existsSync10(keyPath)) {
5591
+ if (existsSync11(keyPath)) {
5428
5592
  await unlink(keyPath);
5429
5593
  }
5430
5594
  }
@@ -6579,23 +6743,23 @@ __export(memory_queue_exports, {
6579
6743
  enqueueMemory: () => enqueueMemory,
6580
6744
  queueDepth: () => queueDepth
6581
6745
  });
6582
- import { appendFileSync, readFileSync as readFileSync7, renameSync as renameSync4, unlinkSync as unlinkSync3, existsSync as existsSync11, statSync as statSync4 } from "fs";
6583
- import path11 from "path";
6746
+ import { appendFileSync as appendFileSync2, readFileSync as readFileSync8, renameSync as renameSync4, unlinkSync as unlinkSync3, existsSync as existsSync12, statSync as statSync5 } from "fs";
6747
+ import path12 from "path";
6584
6748
  function enqueueMemory(entry) {
6585
- appendFileSync(QUEUE_PATH, JSON.stringify(entry) + "\n");
6749
+ appendFileSync2(QUEUE_PATH, JSON.stringify(entry) + "\n");
6586
6750
  }
6587
6751
  function drainQueue() {
6588
6752
  const entries = [];
6589
- if (existsSync11(PROCESSING_PATH)) {
6753
+ if (existsSync12(PROCESSING_PATH)) {
6590
6754
  entries.push(...parseQueueFile(PROCESSING_PATH));
6591
6755
  try {
6592
6756
  unlinkSync3(PROCESSING_PATH);
6593
6757
  } catch {
6594
6758
  }
6595
6759
  }
6596
- if (!existsSync11(QUEUE_PATH)) return entries;
6760
+ if (!existsSync12(QUEUE_PATH)) return entries;
6597
6761
  try {
6598
- const stat = statSync4(QUEUE_PATH);
6762
+ const stat = statSync5(QUEUE_PATH);
6599
6763
  if (stat.size === 0) return entries;
6600
6764
  } catch {
6601
6765
  return entries;
@@ -6613,9 +6777,9 @@ function drainQueue() {
6613
6777
  return entries;
6614
6778
  }
6615
6779
  function queueDepth() {
6616
- if (!existsSync11(QUEUE_PATH)) return 0;
6780
+ if (!existsSync12(QUEUE_PATH)) return 0;
6617
6781
  try {
6618
- const content = readFileSync7(QUEUE_PATH, "utf8");
6782
+ const content = readFileSync8(QUEUE_PATH, "utf8");
6619
6783
  return content.split("\n").filter((line) => line.trim().length > 0).length;
6620
6784
  } catch {
6621
6785
  return 0;
@@ -6626,7 +6790,7 @@ function parseQueueFile(filePath) {
6626
6790
  const entries = [];
6627
6791
  let content;
6628
6792
  try {
6629
- content = readFileSync7(filePath, "utf8");
6793
+ content = readFileSync8(filePath, "utf8");
6630
6794
  } catch {
6631
6795
  return entries;
6632
6796
  }
@@ -6652,7 +6816,7 @@ var init_memory_queue = __esm({
6652
6816
  "src/lib/memory-queue.ts"() {
6653
6817
  "use strict";
6654
6818
  init_config();
6655
- QUEUE_PATH = path11.join(EXE_AI_DIR, "memory-queue.jsonl");
6819
+ QUEUE_PATH = path12.join(EXE_AI_DIR, "memory-queue.jsonl");
6656
6820
  PROCESSING_PATH = QUEUE_PATH + ".processing";
6657
6821
  TTL_MS = 24 * 60 * 60 * 1e3;
6658
6822
  }
@@ -6818,8 +6982,8 @@ __export(reranker_exports, {
6818
6982
  rerankWithContext: () => rerankWithContext,
6819
6983
  rerankWithScores: () => rerankWithScores
6820
6984
  });
6821
- import path12 from "path";
6822
- import { existsSync as existsSync12 } from "fs";
6985
+ import path13 from "path";
6986
+ import { existsSync as existsSync13 } from "fs";
6823
6987
  function resetIdleTimer() {
6824
6988
  if (_idleTimer) clearTimeout(_idleTimer);
6825
6989
  _idleTimer = setTimeout(() => {
@@ -6830,18 +6994,18 @@ function resetIdleTimer() {
6830
6994
  }
6831
6995
  }
6832
6996
  function isRerankerAvailable() {
6833
- return existsSync12(path12.join(MODELS_DIR, RERANKER_MODEL_FILE));
6997
+ return existsSync13(path13.join(MODELS_DIR, RERANKER_MODEL_FILE));
6834
6998
  }
6835
6999
  function getRerankerModelPath() {
6836
- return path12.join(MODELS_DIR, RERANKER_MODEL_FILE);
7000
+ return path13.join(MODELS_DIR, RERANKER_MODEL_FILE);
6837
7001
  }
6838
7002
  async function ensureLoaded() {
6839
7003
  if (_rerankerContext) {
6840
7004
  resetIdleTimer();
6841
7005
  return;
6842
7006
  }
6843
- const modelPath = path12.join(MODELS_DIR, RERANKER_MODEL_FILE);
6844
- if (!existsSync12(modelPath)) {
7007
+ const modelPath = path13.join(MODELS_DIR, RERANKER_MODEL_FILE);
7008
+ if (!existsSync13(modelPath)) {
6845
7009
  throw new Error(
6846
7010
  `Reranker model not found at ${modelPath}. Run /exe-setup to download it.`
6847
7011
  );
@@ -6974,10 +7138,10 @@ async function disposeEmbedder() {
6974
7138
  async function embedDirect(text3) {
6975
7139
  const llamaCpp = await import("node-llama-cpp");
6976
7140
  const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
6977
- const { existsSync: existsSync45 } = await import("fs");
6978
- const path58 = await import("path");
6979
- const modelPath = path58.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
6980
- if (!existsSync45(modelPath)) {
7141
+ const { existsSync: existsSync47 } = await import("fs");
7142
+ const path60 = await import("path");
7143
+ const modelPath = path60.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
7144
+ if (!existsSync47(modelPath)) {
6981
7145
  throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
6982
7146
  }
6983
7147
  const llama = await llamaCpp.getLlama();
@@ -7012,7 +7176,7 @@ __export(project_name_exports, {
7012
7176
  getProjectName: () => getProjectName
7013
7177
  });
7014
7178
  import { execSync as execSync3 } from "child_process";
7015
- import path13 from "path";
7179
+ import path14 from "path";
7016
7180
  function getProjectName(cwd) {
7017
7181
  const dir = cwd ?? process.cwd();
7018
7182
  if (_cached && _cachedCwd === dir) return _cached;
@@ -7025,7 +7189,7 @@ function getProjectName(cwd) {
7025
7189
  timeout: 2e3,
7026
7190
  stdio: ["pipe", "pipe", "pipe"]
7027
7191
  }).trim();
7028
- repoRoot = path13.dirname(gitCommonDir);
7192
+ repoRoot = path14.dirname(gitCommonDir);
7029
7193
  } catch {
7030
7194
  repoRoot = execSync3("git rev-parse --show-toplevel", {
7031
7195
  cwd: dir,
@@ -7034,11 +7198,11 @@ function getProjectName(cwd) {
7034
7198
  stdio: ["pipe", "pipe", "pipe"]
7035
7199
  }).trim();
7036
7200
  }
7037
- _cached = path13.basename(repoRoot);
7201
+ _cached = path14.basename(repoRoot);
7038
7202
  _cachedCwd = dir;
7039
7203
  return _cached;
7040
7204
  } catch {
7041
- _cached = path13.basename(dir);
7205
+ _cached = path14.basename(dir);
7042
7206
  _cachedCwd = dir;
7043
7207
  return _cached;
7044
7208
  }
@@ -7062,8 +7226,8 @@ __export(file_grep_exports, {
7062
7226
  grepProjectFiles: () => grepProjectFiles
7063
7227
  });
7064
7228
  import { execSync as execSync4 } from "child_process";
7065
- import { readFileSync as readFileSync8, readdirSync as readdirSync2, statSync as statSync5, existsSync as existsSync13 } from "fs";
7066
- import path14 from "path";
7229
+ import { readFileSync as readFileSync9, readdirSync as readdirSync2, statSync as statSync6, existsSync as existsSync14 } from "fs";
7230
+ import path15 from "path";
7067
7231
  import crypto3 from "crypto";
7068
7232
  function hasRipgrep() {
7069
7233
  if (_hasRg === null) {
@@ -7103,7 +7267,7 @@ async function grepProjectFiles(query, projectRoot, options) {
7103
7267
  session_id: "file-grep",
7104
7268
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
7105
7269
  tool_name: "file_grep",
7106
- project_name: path14.basename(projectRoot),
7270
+ project_name: path15.basename(projectRoot),
7107
7271
  has_error: false,
7108
7272
  raw_text: `${prefix} ${buildSnippet(hit, projectRoot)}`,
7109
7273
  vector: null,
@@ -7115,7 +7279,7 @@ function getChunkContext(filePath, lineNumber) {
7115
7279
  try {
7116
7280
  const ext = filePath.split(".").pop()?.toLowerCase();
7117
7281
  if (ext !== "ts" && ext !== "tsx" && ext !== "js" && ext !== "jsx") return "";
7118
- const source = readFileSync8(filePath, "utf8");
7282
+ const source = readFileSync9(filePath, "utf8");
7119
7283
  const lines = source.split("\n");
7120
7284
  for (let i = Math.min(lineNumber - 1, lines.length - 1); i >= 0; i--) {
7121
7285
  const line = lines[i];
@@ -7177,11 +7341,11 @@ function grepWithNodeFs(pattern, projectRoot, patterns) {
7177
7341
  const files = collectFiles(projectRoot, patterns ?? DEFAULT_PATTERNS);
7178
7342
  const hits = [];
7179
7343
  for (const filePath of files.slice(0, MAX_FILES)) {
7180
- const absPath = path14.join(projectRoot, filePath);
7344
+ const absPath = path15.join(projectRoot, filePath);
7181
7345
  try {
7182
- const stat = statSync5(absPath);
7346
+ const stat = statSync6(absPath);
7183
7347
  if (stat.size > MAX_FILE_SIZE) continue;
7184
- const content = readFileSync8(absPath, "utf8");
7348
+ const content = readFileSync9(absPath, "utf8");
7185
7349
  const lines = content.split("\n");
7186
7350
  const matches = content.match(regex);
7187
7351
  if (!matches || matches.length === 0) continue;
@@ -7204,15 +7368,15 @@ function collectFiles(root, patterns) {
7204
7368
  const files = [];
7205
7369
  function walk(dir, relative) {
7206
7370
  if (files.length >= MAX_FILES) return;
7207
- const basename = path14.basename(dir);
7371
+ const basename = path15.basename(dir);
7208
7372
  if (EXCLUDE_DIRS.includes(basename)) return;
7209
7373
  try {
7210
7374
  const entries = readdirSync2(dir, { withFileTypes: true });
7211
7375
  for (const entry of entries) {
7212
7376
  if (files.length >= MAX_FILES) return;
7213
- const rel = path14.join(relative, entry.name);
7377
+ const rel = path15.join(relative, entry.name);
7214
7378
  if (entry.isDirectory()) {
7215
- walk(path14.join(dir, entry.name), rel);
7379
+ walk(path15.join(dir, entry.name), rel);
7216
7380
  } else if (entry.isFile()) {
7217
7381
  for (const pat of patterns) {
7218
7382
  if (matchGlob(rel, pat)) {
@@ -7244,7 +7408,7 @@ function matchGlob(filePath, pattern) {
7244
7408
  if (slashIdx !== -1) {
7245
7409
  const dir = pattern.slice(0, slashIdx);
7246
7410
  const ext2 = pattern.slice(slashIdx + 1).replace("*", "");
7247
- const fileDir = path14.dirname(filePath);
7411
+ const fileDir = path15.dirname(filePath);
7248
7412
  return fileDir === dir && filePath.endsWith(ext2);
7249
7413
  }
7250
7414
  const ext = pattern.replace("*", "");
@@ -7252,9 +7416,9 @@ function matchGlob(filePath, pattern) {
7252
7416
  }
7253
7417
  function buildSnippet(hit, projectRoot) {
7254
7418
  try {
7255
- const absPath = path14.join(projectRoot, hit.filePath);
7256
- if (!existsSync13(absPath)) return hit.matchLine;
7257
- const lines = readFileSync8(absPath, "utf8").split("\n");
7419
+ const absPath = path15.join(projectRoot, hit.filePath);
7420
+ if (!existsSync14(absPath)) return hit.matchLine;
7421
+ const lines = readFileSync9(absPath, "utf8").split("\n");
7258
7422
  const start = Math.max(0, hit.lineNumber - 3);
7259
7423
  const end = Math.min(lines.length, hit.lineNumber + 2);
7260
7424
  return lines.slice(start, end).join("\n").slice(0, 500);
@@ -8068,10 +8232,10 @@ async function hybridSearch(queryText, agentId, options) {
8068
8232
  };
8069
8233
  try {
8070
8234
  const fs = await import("fs");
8071
- const path58 = await import("path");
8235
+ const path60 = await import("path");
8072
8236
  const os25 = await import("os");
8073
- const logPath = path58.join(os25.homedir(), ".exe-os", "search-quality.jsonl");
8074
- fs.mkdirSync(path58.dirname(logPath), { recursive: true });
8237
+ const logPath = path60.join(os25.homedir(), ".exe-os", "search-quality.jsonl");
8238
+ fs.mkdirSync(path60.dirname(logPath), { recursive: true });
8075
8239
  fs.appendFileSync(logPath, JSON.stringify(logEntry) + "\n");
8076
8240
  } catch {
8077
8241
  }
@@ -8603,9 +8767,9 @@ __export(active_agent_exports, {
8603
8767
  resolveActiveAgentFromTmuxSession: () => resolveActiveAgentFromTmuxSession,
8604
8768
  writeActiveAgent: () => writeActiveAgent
8605
8769
  });
8606
- import { readFileSync as readFileSync9, writeFileSync as writeFileSync5, mkdirSync as mkdirSync3, unlinkSync as unlinkSync4, readdirSync as readdirSync3 } from "fs";
8770
+ import { readFileSync as readFileSync10, writeFileSync as writeFileSync6, mkdirSync as mkdirSync4, unlinkSync as unlinkSync4, readdirSync as readdirSync3 } from "fs";
8607
8771
  import { execSync as execSync6 } from "child_process";
8608
- import path15 from "path";
8772
+ import path16 from "path";
8609
8773
  function isNameWithOptionalInstance(candidate, baseName) {
8610
8774
  if (candidate === baseName) return true;
8611
8775
  if (!candidate.startsWith(baseName)) return false;
@@ -8649,12 +8813,12 @@ function resolveActiveAgentFromTmuxSession(sessionName) {
8649
8813
  return null;
8650
8814
  }
8651
8815
  function getMarkerPath() {
8652
- return path15.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
8816
+ return path16.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
8653
8817
  }
8654
8818
  function writeActiveAgent(agentId, agentRole) {
8655
8819
  try {
8656
- mkdirSync3(CACHE_DIR, { recursive: true });
8657
- writeFileSync5(
8820
+ mkdirSync4(CACHE_DIR, { recursive: true });
8821
+ writeFileSync6(
8658
8822
  getMarkerPath(),
8659
8823
  JSON.stringify({ agentId, agentRole, startedAt: (/* @__PURE__ */ new Date()).toISOString() })
8660
8824
  );
@@ -8672,7 +8836,7 @@ function getActiveAgent() {
8672
8836
  if (httpCtx) return httpCtx;
8673
8837
  try {
8674
8838
  const markerPath = getMarkerPath();
8675
- const raw = readFileSync9(markerPath, "utf8");
8839
+ const raw = readFileSync10(markerPath, "utf8");
8676
8840
  const data = JSON.parse(raw);
8677
8841
  if (data.agentId) {
8678
8842
  if (data.startedAt) {
@@ -8720,14 +8884,14 @@ function getAllActiveAgents() {
8720
8884
  const key = file.slice("active-agent-".length, -".json".length);
8721
8885
  if (key === "undefined") continue;
8722
8886
  try {
8723
- const raw = readFileSync9(path15.join(CACHE_DIR, file), "utf8");
8887
+ const raw = readFileSync10(path16.join(CACHE_DIR, file), "utf8");
8724
8888
  const data = JSON.parse(raw);
8725
8889
  if (!data.agentId) continue;
8726
8890
  if (data.startedAt) {
8727
8891
  const age = Date.now() - new Date(data.startedAt).getTime();
8728
8892
  if (age > STALE_MS) {
8729
8893
  try {
8730
- unlinkSync4(path15.join(CACHE_DIR, file));
8894
+ unlinkSync4(path16.join(CACHE_DIR, file));
8731
8895
  } catch {
8732
8896
  }
8733
8897
  continue;
@@ -8750,11 +8914,11 @@ function getAllActiveAgents() {
8750
8914
  function cleanupSessionMarkers() {
8751
8915
  const key = getSessionKey();
8752
8916
  try {
8753
- unlinkSync4(path15.join(CACHE_DIR, `active-agent-${key}.json`));
8917
+ unlinkSync4(path16.join(CACHE_DIR, `active-agent-${key}.json`));
8754
8918
  } catch {
8755
8919
  }
8756
8920
  try {
8757
- unlinkSync4(path15.join(CACHE_DIR, "active-agent-undefined.json"));
8921
+ unlinkSync4(path16.join(CACHE_DIR, "active-agent-undefined.json"));
8758
8922
  } catch {
8759
8923
  }
8760
8924
  }
@@ -8766,7 +8930,7 @@ var init_active_agent = __esm({
8766
8930
  init_session_key();
8767
8931
  init_agent_context();
8768
8932
  init_employees();
8769
- CACHE_DIR = path15.join(EXE_AI_DIR, "session-cache");
8933
+ CACHE_DIR = path16.join(EXE_AI_DIR, "session-cache");
8770
8934
  STALE_MS = 24 * 60 * 60 * 1e3;
8771
8935
  }
8772
8936
  });
@@ -9031,12 +9195,12 @@ var init_ask_team_memory = __esm({
9031
9195
  });
9032
9196
 
9033
9197
  // src/lib/license.ts
9034
- import { readFileSync as readFileSync10, writeFileSync as writeFileSync6, existsSync as existsSync14, mkdirSync as mkdirSync4 } from "fs";
9198
+ import { readFileSync as readFileSync11, writeFileSync as writeFileSync7, existsSync as existsSync15, mkdirSync as mkdirSync5 } from "fs";
9035
9199
  import { randomUUID as randomUUID3 } from "crypto";
9036
9200
  import { createRequire as createRequire3 } from "module";
9037
9201
  import { pathToFileURL as pathToFileURL3 } from "url";
9038
9202
  import os7 from "os";
9039
- import path16 from "path";
9203
+ import path17 from "path";
9040
9204
  import { jwtVerify, importSPKI } from "jose";
9041
9205
  async function fetchRetry(url, init) {
9042
9206
  try {
@@ -9047,37 +9211,37 @@ async function fetchRetry(url, init) {
9047
9211
  }
9048
9212
  }
9049
9213
  function loadDeviceId() {
9050
- const deviceJsonPath = path16.join(EXE_AI_DIR, "device.json");
9214
+ const deviceJsonPath = path17.join(EXE_AI_DIR, "device.json");
9051
9215
  try {
9052
- if (existsSync14(deviceJsonPath)) {
9053
- const data = JSON.parse(readFileSync10(deviceJsonPath, "utf8"));
9216
+ if (existsSync15(deviceJsonPath)) {
9217
+ const data = JSON.parse(readFileSync11(deviceJsonPath, "utf8"));
9054
9218
  if (data.deviceId) return data.deviceId;
9055
9219
  }
9056
9220
  } catch {
9057
9221
  }
9058
9222
  try {
9059
- if (existsSync14(DEVICE_ID_PATH)) {
9060
- const id2 = readFileSync10(DEVICE_ID_PATH, "utf8").trim();
9223
+ if (existsSync15(DEVICE_ID_PATH)) {
9224
+ const id2 = readFileSync11(DEVICE_ID_PATH, "utf8").trim();
9061
9225
  if (id2) return id2;
9062
9226
  }
9063
9227
  } catch {
9064
9228
  }
9065
9229
  const id = randomUUID3();
9066
- mkdirSync4(EXE_AI_DIR, { recursive: true });
9067
- writeFileSync6(DEVICE_ID_PATH, id, "utf8");
9230
+ mkdirSync5(EXE_AI_DIR, { recursive: true });
9231
+ writeFileSync7(DEVICE_ID_PATH, id, "utf8");
9068
9232
  return id;
9069
9233
  }
9070
9234
  function loadLicense() {
9071
9235
  try {
9072
- if (!existsSync14(LICENSE_PATH)) return null;
9073
- return readFileSync10(LICENSE_PATH, "utf8").trim();
9236
+ if (!existsSync15(LICENSE_PATH)) return null;
9237
+ return readFileSync11(LICENSE_PATH, "utf8").trim();
9074
9238
  } catch {
9075
9239
  return null;
9076
9240
  }
9077
9241
  }
9078
9242
  function saveLicense(apiKey) {
9079
- mkdirSync4(EXE_AI_DIR, { recursive: true });
9080
- writeFileSync6(LICENSE_PATH, apiKey.trim(), { encoding: "utf8", mode: 384 });
9243
+ mkdirSync5(EXE_AI_DIR, { recursive: true });
9244
+ writeFileSync7(LICENSE_PATH, apiKey.trim(), { encoding: "utf8", mode: 384 });
9081
9245
  }
9082
9246
  async function verifyLicenseJwt(token) {
9083
9247
  try {
@@ -9103,8 +9267,8 @@ async function verifyLicenseJwt(token) {
9103
9267
  }
9104
9268
  async function getCachedLicense() {
9105
9269
  try {
9106
- if (!existsSync14(CACHE_PATH)) return null;
9107
- const raw = JSON.parse(readFileSync10(CACHE_PATH, "utf8"));
9270
+ if (!existsSync15(CACHE_PATH)) return null;
9271
+ const raw = JSON.parse(readFileSync11(CACHE_PATH, "utf8"));
9108
9272
  if (!raw.token || typeof raw.token !== "string") return null;
9109
9273
  return await verifyLicenseJwt(raw.token);
9110
9274
  } catch {
@@ -9113,8 +9277,8 @@ async function getCachedLicense() {
9113
9277
  }
9114
9278
  function readCachedToken() {
9115
9279
  try {
9116
- if (!existsSync14(CACHE_PATH)) return null;
9117
- const raw = JSON.parse(readFileSync10(CACHE_PATH, "utf8"));
9280
+ if (!existsSync15(CACHE_PATH)) return null;
9281
+ const raw = JSON.parse(readFileSync11(CACHE_PATH, "utf8"));
9118
9282
  return typeof raw.token === "string" ? raw.token : null;
9119
9283
  } catch {
9120
9284
  return null;
@@ -9148,7 +9312,7 @@ function getRawCachedPlan() {
9148
9312
  }
9149
9313
  function cacheResponse(token) {
9150
9314
  try {
9151
- writeFileSync6(CACHE_PATH, JSON.stringify({ token }), "utf8");
9315
+ writeFileSync7(CACHE_PATH, JSON.stringify({ token }), "utf8");
9152
9316
  } catch {
9153
9317
  }
9154
9318
  }
@@ -9156,8 +9320,8 @@ function loadPrismaForLicense() {
9156
9320
  if (_prismaFailed) return null;
9157
9321
  const dbUrl = process.env.DATABASE_URL;
9158
9322
  if (!dbUrl) {
9159
- const exeDbRoot = process.env.EXE_DB_ROOT ?? path16.join(os7.homedir(), "exe-db");
9160
- if (!existsSync14(path16.join(exeDbRoot, "package.json"))) {
9323
+ const exeDbRoot = process.env.EXE_DB_ROOT ?? path17.join(os7.homedir(), "exe-db");
9324
+ if (!existsSync15(path17.join(exeDbRoot, "package.json"))) {
9161
9325
  _prismaFailed = true;
9162
9326
  return null;
9163
9327
  }
@@ -9171,8 +9335,8 @@ function loadPrismaForLicense() {
9171
9335
  if (!Ctor2) throw new Error(`No PrismaClient at ${explicitPath}`);
9172
9336
  return new Ctor2();
9173
9337
  }
9174
- const exeDbRoot = process.env.EXE_DB_ROOT ?? path16.join(os7.homedir(), "exe-db");
9175
- const req = createRequire3(path16.join(exeDbRoot, "package.json"));
9338
+ const exeDbRoot = process.env.EXE_DB_ROOT ?? path17.join(os7.homedir(), "exe-db");
9339
+ const req = createRequire3(path17.join(exeDbRoot, "package.json"));
9176
9340
  const entry = req.resolve("@prisma/client");
9177
9341
  const mod = await import(pathToFileURL3(entry).href);
9178
9342
  const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
@@ -9251,7 +9415,7 @@ async function validateLicense(apiKey, deviceId) {
9251
9415
  const pgResult = await validateViaPostgres(apiKey);
9252
9416
  if (pgResult) {
9253
9417
  try {
9254
- writeFileSync6(CACHE_PATH, JSON.stringify({ pgLicense: pgResult, ts: Date.now() }), "utf8");
9418
+ writeFileSync7(CACHE_PATH, JSON.stringify({ pgLicense: pgResult, ts: Date.now() }), "utf8");
9255
9419
  } catch {
9256
9420
  }
9257
9421
  return pgResult;
@@ -9261,8 +9425,8 @@ async function validateLicense(apiKey, deviceId) {
9261
9425
  const cached = await getCachedLicense();
9262
9426
  if (cached) return cached;
9263
9427
  try {
9264
- if (existsSync14(CACHE_PATH)) {
9265
- const raw = JSON.parse(readFileSync10(CACHE_PATH, "utf8"));
9428
+ if (existsSync15(CACHE_PATH)) {
9429
+ const raw = JSON.parse(readFileSync11(CACHE_PATH, "utf8"));
9266
9430
  if (raw.pgLicense && raw.ts && Date.now() - raw.ts < 7 * 24 * 60 * 60 * 1e3) {
9267
9431
  return raw.pgLicense;
9268
9432
  }
@@ -9275,8 +9439,8 @@ async function validateLicense(apiKey, deviceId) {
9275
9439
  }
9276
9440
  function getCacheAgeMs() {
9277
9441
  try {
9278
- const { statSync: statSync10 } = __require("fs");
9279
- const s = statSync10(CACHE_PATH);
9442
+ const { statSync: statSync11 } = __require("fs");
9443
+ const s = statSync11(CACHE_PATH);
9280
9444
  return Date.now() - s.mtimeMs;
9281
9445
  } catch {
9282
9446
  return Infinity;
@@ -9286,9 +9450,9 @@ async function checkLicense() {
9286
9450
  let key = loadLicense();
9287
9451
  if (!key) {
9288
9452
  try {
9289
- const configPath = path16.join(EXE_AI_DIR, "config.json");
9290
- if (existsSync14(configPath)) {
9291
- const raw = JSON.parse(readFileSync10(configPath, "utf8"));
9453
+ const configPath = path17.join(EXE_AI_DIR, "config.json");
9454
+ if (existsSync15(configPath)) {
9455
+ const raw = JSON.parse(readFileSync11(configPath, "utf8"));
9292
9456
  const cloud = raw.cloud;
9293
9457
  if (cloud?.apiKey) {
9294
9458
  key = cloud.apiKey;
@@ -9319,9 +9483,9 @@ var init_license = __esm({
9319
9483
  "src/lib/license.ts"() {
9320
9484
  "use strict";
9321
9485
  init_config();
9322
- LICENSE_PATH = path16.join(EXE_AI_DIR, "license.key");
9323
- CACHE_PATH = path16.join(EXE_AI_DIR, "license-cache.json");
9324
- DEVICE_ID_PATH = path16.join(EXE_AI_DIR, "device-id");
9486
+ LICENSE_PATH = path17.join(EXE_AI_DIR, "license.key");
9487
+ CACHE_PATH = path17.join(EXE_AI_DIR, "license-cache.json");
9488
+ DEVICE_ID_PATH = path17.join(EXE_AI_DIR, "device-id");
9325
9489
  API_BASE = "https://askexe.com/cloud";
9326
9490
  RETRY_DELAY_MS = 500;
9327
9491
  LICENSE_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----
@@ -9362,12 +9526,12 @@ __export(plan_limits_exports, {
9362
9526
  countActiveMemories: () => countActiveMemories,
9363
9527
  getLicenseSync: () => getLicenseSync
9364
9528
  });
9365
- import { readFileSync as readFileSync11, existsSync as existsSync15 } from "fs";
9366
- import path17 from "path";
9529
+ import { readFileSync as readFileSync12, existsSync as existsSync16 } from "fs";
9530
+ import path18 from "path";
9367
9531
  function getLicenseSync() {
9368
9532
  try {
9369
- if (!existsSync15(CACHE_PATH2)) return freeLicense();
9370
- const raw = JSON.parse(readFileSync11(CACHE_PATH2, "utf8"));
9533
+ if (!existsSync16(CACHE_PATH2)) return freeLicense();
9534
+ const raw = JSON.parse(readFileSync12(CACHE_PATH2, "utf8"));
9371
9535
  if (!raw.token || typeof raw.token !== "string") return freeLicense();
9372
9536
  const parts = raw.token.split(".");
9373
9537
  if (parts.length !== 3) return freeLicense();
@@ -9434,8 +9598,8 @@ function assertEmployeeLimitSync(rosterPath) {
9434
9598
  const filePath = rosterPath ?? EMPLOYEES_PATH;
9435
9599
  let count = 0;
9436
9600
  try {
9437
- if (existsSync15(filePath)) {
9438
- const raw = readFileSync11(filePath, "utf8");
9601
+ if (existsSync16(filePath)) {
9602
+ const raw = readFileSync12(filePath, "utf8");
9439
9603
  const employees = JSON.parse(raw);
9440
9604
  count = Array.isArray(employees) ? employees.length : 0;
9441
9605
  }
@@ -9472,15 +9636,15 @@ var init_plan_limits = __esm({
9472
9636
  this.name = "PlanLimitError";
9473
9637
  }
9474
9638
  };
9475
- CACHE_PATH2 = path17.join(EXE_AI_DIR, "license-cache.json");
9639
+ CACHE_PATH2 = path18.join(EXE_AI_DIR, "license-cache.json");
9476
9640
  }
9477
9641
  });
9478
9642
 
9479
9643
  // src/mcp/tools/store-memory.ts
9480
9644
  import { z as z3 } from "zod";
9481
9645
  import crypto4 from "crypto";
9482
- import { writeFileSync as writeFileSync7 } from "fs";
9483
- import path18 from "path";
9646
+ import { writeFileSync as writeFileSync8 } from "fs";
9647
+ import path19 from "path";
9484
9648
  function registerStoreMemory(server) {
9485
9649
  server.registerTool(
9486
9650
  "store_memory",
@@ -9548,8 +9712,8 @@ function registerStoreMemory(server) {
9548
9712
  if (needsBackfill) {
9549
9713
  try {
9550
9714
  const { EXE_AI_DIR: exeDir } = await Promise.resolve().then(() => (init_config(), config_exports));
9551
- const flagPath = path18.join(exeDir, "session-cache", "needs-backfill");
9552
- writeFileSync7(flagPath, "1");
9715
+ const flagPath = path19.join(exeDir, "session-cache", "needs-backfill");
9716
+ writeFileSync8(flagPath, "1");
9553
9717
  } catch {
9554
9718
  }
9555
9719
  }
@@ -9577,8 +9741,8 @@ var init_store_memory = __esm({
9577
9741
  // src/mcp/tools/commit-memory.ts
9578
9742
  import { z as z4 } from "zod";
9579
9743
  import crypto5 from "crypto";
9580
- import { writeFileSync as writeFileSync8 } from "fs";
9581
- import path19 from "path";
9744
+ import { writeFileSync as writeFileSync9 } from "fs";
9745
+ import path20 from "path";
9582
9746
  function registerCommitMemory(server) {
9583
9747
  server.registerTool(
9584
9748
  "commit_to_long_term_memory",
@@ -9668,8 +9832,8 @@ function registerCommitMemory(server) {
9668
9832
  if (needsBackfill) {
9669
9833
  try {
9670
9834
  const { EXE_AI_DIR: exeDir } = await Promise.resolve().then(() => (init_config(), config_exports));
9671
- const flagPath = path19.join(exeDir, "session-cache", "needs-backfill");
9672
- writeFileSync8(flagPath, "1");
9835
+ const flagPath = path20.join(exeDir, "session-cache", "needs-backfill");
9836
+ writeFileSync9(flagPath, "1");
9673
9837
  } catch {
9674
9838
  }
9675
9839
  }
@@ -9704,8 +9868,8 @@ __export(wiki_client_exports, {
9704
9868
  listDocuments: () => listDocuments,
9705
9869
  listWorkspaces: () => listWorkspaces
9706
9870
  });
9707
- async function wikiFetch(config2, path58, method = "GET", body) {
9708
- const url = `${config2.baseUrl}/api/v1${path58}`;
9871
+ async function wikiFetch(config2, path60, method = "GET", body) {
9872
+ const url = `${config2.baseUrl}/api/v1${path60}`;
9709
9873
  const headers = {
9710
9874
  Authorization: `Bearer ${config2.apiKey}`,
9711
9875
  "Content-Type": "application/json"
@@ -9738,7 +9902,7 @@ async function wikiFetch(config2, path58, method = "GET", body) {
9738
9902
  }
9739
9903
  }
9740
9904
  if (!response.ok) {
9741
- throw new Error(`Wiki API ${method} ${path58}: ${response.status} ${response.statusText}`);
9905
+ throw new Error(`Wiki API ${method} ${path60}: ${response.status} ${response.statusText}`);
9742
9906
  }
9743
9907
  return response.json();
9744
9908
  } finally {
@@ -11107,14 +11271,14 @@ __export(session_registry_exports, {
11107
11271
  refreshSessionProject: () => refreshSessionProject,
11108
11272
  registerSession: () => registerSession
11109
11273
  });
11110
- import { readFileSync as readFileSync12, writeFileSync as writeFileSync9, mkdirSync as mkdirSync5, existsSync as existsSync16 } from "fs";
11274
+ import { readFileSync as readFileSync13, writeFileSync as writeFileSync10, mkdirSync as mkdirSync6, existsSync as existsSync17 } from "fs";
11111
11275
  import { execSync as execSync7 } from "child_process";
11112
- import path20 from "path";
11276
+ import path21 from "path";
11113
11277
  import os8 from "os";
11114
11278
  function registerSession(entry) {
11115
- const dir = path20.dirname(REGISTRY_PATH);
11116
- if (!existsSync16(dir)) {
11117
- mkdirSync5(dir, { recursive: true });
11279
+ const dir = path21.dirname(REGISTRY_PATH);
11280
+ if (!existsSync17(dir)) {
11281
+ mkdirSync6(dir, { recursive: true });
11118
11282
  }
11119
11283
  const sessions = listSessions();
11120
11284
  const idx = sessions.findIndex((s) => s.windowName === entry.windowName);
@@ -11123,7 +11287,7 @@ function registerSession(entry) {
11123
11287
  } else {
11124
11288
  sessions.push(entry);
11125
11289
  }
11126
- writeFileSync9(REGISTRY_PATH, JSON.stringify(sessions, null, 2));
11290
+ writeFileSync10(REGISTRY_PATH, JSON.stringify(sessions, null, 2));
11127
11291
  }
11128
11292
  function refreshSessionProject(windowName, projectDir) {
11129
11293
  const sessions = listSessions();
@@ -11131,13 +11295,13 @@ function refreshSessionProject(windowName, projectDir) {
11131
11295
  if (!entry || entry.projectDir === projectDir) return;
11132
11296
  entry.projectDir = projectDir;
11133
11297
  try {
11134
- writeFileSync9(REGISTRY_PATH, JSON.stringify(sessions, null, 2));
11298
+ writeFileSync10(REGISTRY_PATH, JSON.stringify(sessions, null, 2));
11135
11299
  } catch {
11136
11300
  }
11137
11301
  }
11138
11302
  function listSessions() {
11139
11303
  try {
11140
- const raw = readFileSync12(REGISTRY_PATH, "utf8");
11304
+ const raw = readFileSync13(REGISTRY_PATH, "utf8");
11141
11305
  return JSON.parse(raw);
11142
11306
  } catch {
11143
11307
  return [];
@@ -11158,7 +11322,7 @@ function pruneStaleSessions() {
11158
11322
  const alive = sessions.filter((s) => liveSet.has(s.windowName));
11159
11323
  const pruned = sessions.length - alive.length;
11160
11324
  if (pruned > 0) {
11161
- writeFileSync9(REGISTRY_PATH, JSON.stringify(alive, null, 2));
11325
+ writeFileSync10(REGISTRY_PATH, JSON.stringify(alive, null, 2));
11162
11326
  }
11163
11327
  return pruned;
11164
11328
  }
@@ -11166,7 +11330,7 @@ var REGISTRY_PATH;
11166
11330
  var init_session_registry = __esm({
11167
11331
  "src/lib/session-registry.ts"() {
11168
11332
  "use strict";
11169
- REGISTRY_PATH = path20.join(os8.homedir(), ".exe-os", "session-registry.json");
11333
+ REGISTRY_PATH = path21.join(os8.homedir(), ".exe-os", "session-registry.json");
11170
11334
  }
11171
11335
  });
11172
11336
 
@@ -11377,17 +11541,17 @@ __export(intercom_queue_exports, {
11377
11541
  queueIntercom: () => queueIntercom,
11378
11542
  readQueue: () => readQueue
11379
11543
  });
11380
- import { readFileSync as readFileSync13, writeFileSync as writeFileSync10, renameSync as renameSync5, existsSync as existsSync17, mkdirSync as mkdirSync6 } from "fs";
11381
- import path21 from "path";
11544
+ import { readFileSync as readFileSync14, writeFileSync as writeFileSync11, renameSync as renameSync5, existsSync as existsSync18, mkdirSync as mkdirSync7 } from "fs";
11545
+ import path22 from "path";
11382
11546
  import os9 from "os";
11383
11547
  function ensureDir() {
11384
- const dir = path21.dirname(QUEUE_PATH2);
11385
- if (!existsSync17(dir)) mkdirSync6(dir, { recursive: true });
11548
+ const dir = path22.dirname(QUEUE_PATH2);
11549
+ if (!existsSync18(dir)) mkdirSync7(dir, { recursive: true });
11386
11550
  }
11387
11551
  function readQueue() {
11388
11552
  try {
11389
- if (!existsSync17(QUEUE_PATH2)) return [];
11390
- return JSON.parse(readFileSync13(QUEUE_PATH2, "utf8"));
11553
+ if (!existsSync18(QUEUE_PATH2)) return [];
11554
+ return JSON.parse(readFileSync14(QUEUE_PATH2, "utf8"));
11391
11555
  } catch {
11392
11556
  return [];
11393
11557
  }
@@ -11395,7 +11559,7 @@ function readQueue() {
11395
11559
  function writeQueue(queue) {
11396
11560
  ensureDir();
11397
11561
  const tmp = `${QUEUE_PATH2}.tmp`;
11398
- writeFileSync10(tmp, JSON.stringify(queue, null, 2));
11562
+ writeFileSync11(tmp, JSON.stringify(queue, null, 2));
11399
11563
  renameSync5(tmp, QUEUE_PATH2);
11400
11564
  }
11401
11565
  function queueIntercom(targetSession, reason) {
@@ -11487,37 +11651,37 @@ var QUEUE_PATH2, MAX_RETRIES2, TTL_MS2, INTERCOM_LOG;
11487
11651
  var init_intercom_queue = __esm({
11488
11652
  "src/lib/intercom-queue.ts"() {
11489
11653
  "use strict";
11490
- QUEUE_PATH2 = path21.join(os9.homedir(), ".exe-os", "intercom-queue.json");
11654
+ QUEUE_PATH2 = path22.join(os9.homedir(), ".exe-os", "intercom-queue.json");
11491
11655
  MAX_RETRIES2 = 5;
11492
11656
  TTL_MS2 = 60 * 60 * 1e3;
11493
- INTERCOM_LOG = path21.join(os9.homedir(), ".exe-os", "intercom.log");
11657
+ INTERCOM_LOG = path22.join(os9.homedir(), ".exe-os", "intercom.log");
11494
11658
  }
11495
11659
  });
11496
11660
 
11497
11661
  // src/lib/agent-symlinks.ts
11498
11662
  import os10 from "os";
11499
- import path22 from "path";
11663
+ import path23 from "path";
11500
11664
  import {
11501
- existsSync as existsSync18,
11665
+ existsSync as existsSync19,
11502
11666
  lstatSync,
11503
- mkdirSync as mkdirSync7,
11667
+ mkdirSync as mkdirSync8,
11504
11668
  readlinkSync as readlinkSync2,
11505
11669
  symlinkSync as symlinkSync2
11506
11670
  } from "fs";
11507
11671
  function claudeAgentsDir(homeDir) {
11508
- return path22.join(homeDir, ".claude", "agents");
11672
+ return path23.join(homeDir, ".claude", "agents");
11509
11673
  }
11510
11674
  function identitySourcePath(homeDir, agentId) {
11511
- return path22.join(homeDir, ".exe-os", "identity", `${agentId}.md`);
11675
+ return path23.join(homeDir, ".exe-os", "identity", `${agentId}.md`);
11512
11676
  }
11513
11677
  function claudeAgentLinkPath(homeDir, agentId) {
11514
- return path22.join(claudeAgentsDir(homeDir), `${agentId}.md`);
11678
+ return path23.join(claudeAgentsDir(homeDir), `${agentId}.md`);
11515
11679
  }
11516
11680
  function ensureAgentSymlink(agentId, homeDir = os10.homedir()) {
11517
11681
  const target = identitySourcePath(homeDir, agentId);
11518
11682
  const link = claudeAgentLinkPath(homeDir, agentId);
11519
- mkdirSync7(claudeAgentsDir(homeDir), { recursive: true });
11520
- if (existsSync18(link)) {
11683
+ mkdirSync8(claudeAgentsDir(homeDir), { recursive: true });
11684
+ if (existsSync19(link)) {
11521
11685
  let stat;
11522
11686
  try {
11523
11687
  stat = lstatSync(link);
@@ -11960,8 +12124,8 @@ __export(tasks_review_exports, {
11960
12124
  isStale: () => isStale,
11961
12125
  listPendingReviews: () => listPendingReviews
11962
12126
  });
11963
- import path23 from "path";
11964
- import { existsSync as existsSync19, readdirSync as readdirSync4, unlinkSync as unlinkSync5 } from "fs";
12127
+ import path24 from "path";
12128
+ import { existsSync as existsSync20, readdirSync as readdirSync4, unlinkSync as unlinkSync5 } from "fs";
11965
12129
  function formatAge(isoTimestamp) {
11966
12130
  if (!isoTimestamp) return "";
11967
12131
  const ms = Date.now() - new Date(isoTimestamp).getTime();
@@ -12230,11 +12394,11 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
12230
12394
  );
12231
12395
  }
12232
12396
  try {
12233
- const cacheDir = path23.join(EXE_AI_DIR, "session-cache");
12234
- if (existsSync19(cacheDir)) {
12397
+ const cacheDir = path24.join(EXE_AI_DIR, "session-cache");
12398
+ if (existsSync20(cacheDir)) {
12235
12399
  for (const f of readdirSync4(cacheDir)) {
12236
12400
  if (f.startsWith("review-notified-")) {
12237
- unlinkSync5(path23.join(cacheDir, f));
12401
+ unlinkSync5(path24.join(cacheDir, f));
12238
12402
  }
12239
12403
  }
12240
12404
  }
@@ -12281,13 +12445,13 @@ __export(tmux_routing_exports, {
12281
12445
  verifyPaneAtCapacity: () => verifyPaneAtCapacity
12282
12446
  });
12283
12447
  import { execFileSync as execFileSync2, execSync as execSync9 } from "child_process";
12284
- import { readFileSync as readFileSync14, writeFileSync as writeFileSync11, mkdirSync as mkdirSync8, existsSync as existsSync20, appendFileSync as appendFileSync2, readdirSync as readdirSync5 } from "fs";
12285
- import path24 from "path";
12448
+ import { readFileSync as readFileSync15, writeFileSync as writeFileSync12, mkdirSync as mkdirSync9, existsSync as existsSync21, appendFileSync as appendFileSync3, readdirSync as readdirSync5 } from "fs";
12449
+ import path25 from "path";
12286
12450
  import os11 from "os";
12287
- import { fileURLToPath as fileURLToPath2 } from "url";
12451
+ import { fileURLToPath as fileURLToPath3 } from "url";
12288
12452
  import { unlinkSync as unlinkSync6 } from "fs";
12289
12453
  function spawnLockPath(sessionName) {
12290
- return path24.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
12454
+ return path25.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
12291
12455
  }
12292
12456
  function isProcessAlive(pid) {
12293
12457
  try {
@@ -12298,13 +12462,13 @@ function isProcessAlive(pid) {
12298
12462
  }
12299
12463
  }
12300
12464
  function acquireSpawnLock2(sessionName) {
12301
- if (!existsSync20(SPAWN_LOCK_DIR)) {
12302
- mkdirSync8(SPAWN_LOCK_DIR, { recursive: true });
12465
+ if (!existsSync21(SPAWN_LOCK_DIR)) {
12466
+ mkdirSync9(SPAWN_LOCK_DIR, { recursive: true });
12303
12467
  }
12304
12468
  const lockFile = spawnLockPath(sessionName);
12305
- if (existsSync20(lockFile)) {
12469
+ if (existsSync21(lockFile)) {
12306
12470
  try {
12307
- const lock = JSON.parse(readFileSync14(lockFile, "utf8"));
12471
+ const lock = JSON.parse(readFileSync15(lockFile, "utf8"));
12308
12472
  const age = Date.now() - lock.timestamp;
12309
12473
  if (isProcessAlive(lock.pid) && age < 6e4) {
12310
12474
  return false;
@@ -12312,7 +12476,7 @@ function acquireSpawnLock2(sessionName) {
12312
12476
  } catch {
12313
12477
  }
12314
12478
  }
12315
- writeFileSync11(lockFile, JSON.stringify({ pid: process.pid, timestamp: Date.now() }));
12479
+ writeFileSync12(lockFile, JSON.stringify({ pid: process.pid, timestamp: Date.now() }));
12316
12480
  return true;
12317
12481
  }
12318
12482
  function releaseSpawnLock2(sessionName) {
@@ -12323,14 +12487,14 @@ function releaseSpawnLock2(sessionName) {
12323
12487
  }
12324
12488
  function resolveBehaviorsExporterScript() {
12325
12489
  try {
12326
- const thisFile = fileURLToPath2(import.meta.url);
12327
- const scriptPath = path24.join(
12328
- path24.dirname(thisFile),
12490
+ const thisFile = fileURLToPath3(import.meta.url);
12491
+ const scriptPath = path25.join(
12492
+ path25.dirname(thisFile),
12329
12493
  "..",
12330
12494
  "bin",
12331
12495
  "exe-export-behaviors.js"
12332
12496
  );
12333
- return existsSync20(scriptPath) ? scriptPath : null;
12497
+ return existsSync21(scriptPath) ? scriptPath : null;
12334
12498
  } catch {
12335
12499
  return null;
12336
12500
  }
@@ -12396,12 +12560,12 @@ function extractRootExe(name) {
12396
12560
  return parts.length > 0 ? parts[parts.length - 1] : null;
12397
12561
  }
12398
12562
  function registerParentExe(sessionKey, parentExe, dispatchedBy) {
12399
- if (!existsSync20(SESSION_CACHE)) {
12400
- mkdirSync8(SESSION_CACHE, { recursive: true });
12563
+ if (!existsSync21(SESSION_CACHE)) {
12564
+ mkdirSync9(SESSION_CACHE, { recursive: true });
12401
12565
  }
12402
12566
  const rootExe = extractRootExe(parentExe) ?? parentExe;
12403
- const filePath = path24.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
12404
- writeFileSync11(filePath, JSON.stringify({
12567
+ const filePath = path25.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
12568
+ writeFileSync12(filePath, JSON.stringify({
12405
12569
  parentExe: rootExe,
12406
12570
  dispatchedBy: dispatchedBy || rootExe,
12407
12571
  registeredAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -12409,7 +12573,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
12409
12573
  }
12410
12574
  function getParentExe(sessionKey) {
12411
12575
  try {
12412
- const data = JSON.parse(readFileSync14(path24.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
12576
+ const data = JSON.parse(readFileSync15(path25.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
12413
12577
  return data.parentExe || null;
12414
12578
  } catch {
12415
12579
  return null;
@@ -12417,8 +12581,8 @@ function getParentExe(sessionKey) {
12417
12581
  }
12418
12582
  function getDispatchedBy(sessionKey) {
12419
12583
  try {
12420
- const data = JSON.parse(readFileSync14(
12421
- path24.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
12584
+ const data = JSON.parse(readFileSync15(
12585
+ path25.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
12422
12586
  "utf8"
12423
12587
  ));
12424
12588
  return data.dispatchedBy ?? data.parentExe ?? null;
@@ -12488,8 +12652,8 @@ async function verifyPaneAtCapacity(sessionName) {
12488
12652
  }
12489
12653
  function readDebounceState() {
12490
12654
  try {
12491
- if (!existsSync20(DEBOUNCE_FILE)) return {};
12492
- const raw = JSON.parse(readFileSync14(DEBOUNCE_FILE, "utf8"));
12655
+ if (!existsSync21(DEBOUNCE_FILE)) return {};
12656
+ const raw = JSON.parse(readFileSync15(DEBOUNCE_FILE, "utf8"));
12493
12657
  const state = {};
12494
12658
  for (const [key, val] of Object.entries(raw)) {
12495
12659
  if (typeof val === "number") {
@@ -12505,8 +12669,8 @@ function readDebounceState() {
12505
12669
  }
12506
12670
  function writeDebounceState(state) {
12507
12671
  try {
12508
- if (!existsSync20(SESSION_CACHE)) mkdirSync8(SESSION_CACHE, { recursive: true });
12509
- writeFileSync11(DEBOUNCE_FILE, JSON.stringify(state));
12672
+ if (!existsSync21(SESSION_CACHE)) mkdirSync9(SESSION_CACHE, { recursive: true });
12673
+ writeFileSync12(DEBOUNCE_FILE, JSON.stringify(state));
12510
12674
  } catch {
12511
12675
  }
12512
12676
  }
@@ -12542,7 +12706,7 @@ function logIntercom(msg) {
12542
12706
  process.stderr.write(`[intercom] ${msg}
12543
12707
  `);
12544
12708
  try {
12545
- appendFileSync2(INTERCOM_LOG2, line);
12709
+ appendFileSync3(INTERCOM_LOG2, line);
12546
12710
  } catch {
12547
12711
  }
12548
12712
  }
@@ -12605,8 +12769,8 @@ function sendIntercom(targetSession) {
12605
12769
  try {
12606
12770
  const rawAgent = targetSession.split("-")[0] ?? targetSession;
12607
12771
  const agent = baseAgentName(rawAgent);
12608
- const markerPath = path24.join(SESSION_CACHE, `current-task-${agent}.json`);
12609
- if (existsSync20(markerPath)) {
12772
+ const markerPath = path25.join(SESSION_CACHE, `current-task-${agent}.json`);
12773
+ if (existsSync21(markerPath)) {
12610
12774
  logIntercom(`SKIP \u2192 ${targetSession} (has in_progress task marker + not idle \u2014 will auto-chain)`);
12611
12775
  return "debounced";
12612
12776
  }
@@ -12616,8 +12780,8 @@ function sendIntercom(targetSession) {
12616
12780
  try {
12617
12781
  const rawAgent = targetSession.split("-")[0] ?? targetSession;
12618
12782
  const agent = baseAgentName(rawAgent);
12619
- const taskDir = path24.join(process.cwd(), "exe", agent);
12620
- if (existsSync20(taskDir)) {
12783
+ const taskDir = path25.join(process.cwd(), "exe", agent);
12784
+ if (existsSync21(taskDir)) {
12621
12785
  const files = readdirSync5(taskDir).filter(
12622
12786
  (f) => f.endsWith(".md") && f !== "DONE.txt"
12623
12787
  );
@@ -12776,26 +12940,26 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
12776
12940
  const transport = getTransport();
12777
12941
  const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
12778
12942
  const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
12779
- const logDir = path24.join(os11.homedir(), ".exe-os", "session-logs");
12780
- const logFile = path24.join(logDir, `${instanceLabel}-${Date.now()}.log`);
12781
- if (!existsSync20(logDir)) {
12782
- mkdirSync8(logDir, { recursive: true });
12943
+ const logDir = path25.join(os11.homedir(), ".exe-os", "session-logs");
12944
+ const logFile = path25.join(logDir, `${instanceLabel}-${Date.now()}.log`);
12945
+ if (!existsSync21(logDir)) {
12946
+ mkdirSync9(logDir, { recursive: true });
12783
12947
  }
12784
12948
  transport.kill(sessionName);
12785
12949
  let cleanupSuffix = "";
12786
12950
  try {
12787
- const thisFile = fileURLToPath2(import.meta.url);
12788
- const cleanupScript = path24.join(path24.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
12789
- if (existsSync20(cleanupScript)) {
12951
+ const thisFile = fileURLToPath3(import.meta.url);
12952
+ const cleanupScript = path25.join(path25.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
12953
+ if (existsSync21(cleanupScript)) {
12790
12954
  cleanupSuffix = `; ${process.execPath} "${cleanupScript}" "${employeeName}" "${exeSession}"`;
12791
12955
  }
12792
12956
  } catch {
12793
12957
  }
12794
12958
  try {
12795
- const claudeJsonPath = path24.join(os11.homedir(), ".claude.json");
12959
+ const claudeJsonPath = path25.join(os11.homedir(), ".claude.json");
12796
12960
  let claudeJson = {};
12797
12961
  try {
12798
- claudeJson = JSON.parse(readFileSync14(claudeJsonPath, "utf8"));
12962
+ claudeJson = JSON.parse(readFileSync15(claudeJsonPath, "utf8"));
12799
12963
  } catch {
12800
12964
  }
12801
12965
  if (!claudeJson.projects) claudeJson.projects = {};
@@ -12803,17 +12967,17 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
12803
12967
  const trustDir = opts?.cwd ?? projectDir;
12804
12968
  if (!projects[trustDir]) projects[trustDir] = {};
12805
12969
  projects[trustDir].hasTrustDialogAccepted = true;
12806
- writeFileSync11(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
12970
+ writeFileSync12(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
12807
12971
  } catch {
12808
12972
  }
12809
12973
  try {
12810
- const settingsDir = path24.join(os11.homedir(), ".claude", "projects");
12974
+ const settingsDir = path25.join(os11.homedir(), ".claude", "projects");
12811
12975
  const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
12812
- const projSettingsDir = path24.join(settingsDir, normalizedKey);
12813
- const settingsPath = path24.join(projSettingsDir, "settings.json");
12976
+ const projSettingsDir = path25.join(settingsDir, normalizedKey);
12977
+ const settingsPath = path25.join(projSettingsDir, "settings.json");
12814
12978
  let settings = {};
12815
12979
  try {
12816
- settings = JSON.parse(readFileSync14(settingsPath, "utf8"));
12980
+ settings = JSON.parse(readFileSync15(settingsPath, "utf8"));
12817
12981
  } catch {
12818
12982
  }
12819
12983
  const perms = settings.permissions ?? {};
@@ -12841,8 +13005,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
12841
13005
  if (changed) {
12842
13006
  perms.allow = allow;
12843
13007
  settings.permissions = perms;
12844
- mkdirSync8(projSettingsDir, { recursive: true });
12845
- writeFileSync11(settingsPath, JSON.stringify(settings, null, 2) + "\n");
13008
+ mkdirSync9(projSettingsDir, { recursive: true });
13009
+ writeFileSync12(settingsPath, JSON.stringify(settings, null, 2) + "\n");
12846
13010
  }
12847
13011
  } catch {
12848
13012
  }
@@ -12857,7 +13021,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
12857
13021
  let behaviorsFlag = "";
12858
13022
  let legacyFallbackWarned = false;
12859
13023
  if (!useExeAgent && !useBinSymlink) {
12860
- const identityPath2 = path24.join(
13024
+ const identityPath2 = path25.join(
12861
13025
  os11.homedir(),
12862
13026
  ".exe-os",
12863
13027
  "identity",
@@ -12874,13 +13038,13 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
12874
13038
  `
12875
13039
  );
12876
13040
  }
12877
- } else if (existsSync20(identityPath2)) {
13041
+ } else if (existsSync21(identityPath2)) {
12878
13042
  identityFlag = ` --append-system-prompt-file ${identityPath2}`;
12879
13043
  legacyFallbackWarned = true;
12880
13044
  }
12881
13045
  const behaviorsFile = exportBehaviorsSync(
12882
13046
  employeeName,
12883
- path24.basename(spawnCwd),
13047
+ path25.basename(spawnCwd),
12884
13048
  sessionName
12885
13049
  );
12886
13050
  if (behaviorsFile) {
@@ -12895,16 +13059,16 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
12895
13059
  }
12896
13060
  let sessionContextFlag = "";
12897
13061
  try {
12898
- const ctxDir = path24.join(os11.homedir(), ".exe-os", "session-cache");
12899
- mkdirSync8(ctxDir, { recursive: true });
12900
- const ctxFile = path24.join(ctxDir, `session-context-${sessionName}.md`);
13062
+ const ctxDir = path25.join(os11.homedir(), ".exe-os", "session-cache");
13063
+ mkdirSync9(ctxDir, { recursive: true });
13064
+ const ctxFile = path25.join(ctxDir, `session-context-${sessionName}.md`);
12901
13065
  const ctxContent = [
12902
13066
  `## Session Context`,
12903
13067
  `You are running in tmux session: ${sessionName}.`,
12904
13068
  `Your parent coordinator session is ${exeSession}.`,
12905
13069
  `Your employees (if any) use the -${exeSession} suffix.`
12906
13070
  ].join("\n");
12907
- writeFileSync11(ctxFile, ctxContent);
13071
+ writeFileSync12(ctxFile, ctxContent);
12908
13072
  sessionContextFlag = ` --append-system-prompt-file ${ctxFile}`;
12909
13073
  } catch {
12910
13074
  }
@@ -12987,8 +13151,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
12987
13151
  transport.pipeLog(sessionName, logFile);
12988
13152
  try {
12989
13153
  const mySession = getMySession();
12990
- const dispatchInfo = path24.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
12991
- writeFileSync11(dispatchInfo, JSON.stringify({
13154
+ const dispatchInfo = path25.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
13155
+ writeFileSync12(dispatchInfo, JSON.stringify({
12992
13156
  dispatchedBy: mySession,
12993
13157
  rootExe: exeSession,
12994
13158
  provider: useBinSymlink ? ccProvider : useExeAgent ? opts.provider : useCodex ? "openai" : useOpencode ? "opencode" : "anthropic",
@@ -13063,15 +13227,15 @@ var init_tmux_routing = __esm({
13063
13227
  init_plan_limits();
13064
13228
  init_employees();
13065
13229
  init_agent_symlinks();
13066
- SPAWN_LOCK_DIR = path24.join(os11.homedir(), ".exe-os", "spawn-locks");
13067
- SESSION_CACHE = path24.join(os11.homedir(), ".exe-os", "session-cache");
13230
+ SPAWN_LOCK_DIR = path25.join(os11.homedir(), ".exe-os", "spawn-locks");
13231
+ SESSION_CACHE = path25.join(os11.homedir(), ".exe-os", "session-cache");
13068
13232
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
13069
13233
  VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
13070
13234
  VERIFY_PANE_LINES = 200;
13071
13235
  INTERCOM_DEBOUNCE_MS = 3e4;
13072
13236
  CODEX_DEBOUNCE_MS = 12e4;
13073
- INTERCOM_LOG2 = path24.join(os11.homedir(), ".exe-os", "intercom.log");
13074
- DEBOUNCE_FILE = path24.join(SESSION_CACHE, "intercom-debounce.json");
13237
+ INTERCOM_LOG2 = path25.join(os11.homedir(), ".exe-os", "intercom.log");
13238
+ DEBOUNCE_FILE = path25.join(SESSION_CACHE, "intercom-debounce.json");
13075
13239
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
13076
13240
  BUSY_PATTERN = /[✻✽✶✳·].*…|Running…|• Working|• Ran |• Explored|• Called|esc to interrupt/;
13077
13241
  }
@@ -13118,13 +13282,13 @@ var init_task_scope = __esm({
13118
13282
 
13119
13283
  // src/lib/notifications.ts
13120
13284
  import crypto7 from "crypto";
13121
- import path25 from "path";
13285
+ import path26 from "path";
13122
13286
  import os12 from "os";
13123
13287
  import {
13124
- readFileSync as readFileSync15,
13288
+ readFileSync as readFileSync16,
13125
13289
  readdirSync as readdirSync6,
13126
13290
  unlinkSync as unlinkSync7,
13127
- existsSync as existsSync21,
13291
+ existsSync as existsSync22,
13128
13292
  rmdirSync
13129
13293
  } from "fs";
13130
13294
  async function writeNotification(notification) {
@@ -13253,11 +13417,11 @@ __export(tasks_crud_exports, {
13253
13417
  writeCheckpoint: () => writeCheckpoint
13254
13418
  });
13255
13419
  import crypto8 from "crypto";
13256
- import path26 from "path";
13420
+ import path27 from "path";
13257
13421
  import os13 from "os";
13258
13422
  import { execSync as execSync10 } from "child_process";
13259
13423
  import { mkdir as mkdir4, writeFile as writeFile4, appendFile } from "fs/promises";
13260
- import { existsSync as existsSync22, readFileSync as readFileSync16 } from "fs";
13424
+ import { existsSync as existsSync23, readFileSync as readFileSync17 } from "fs";
13261
13425
  async function writeCheckpoint(input) {
13262
13426
  const client = getClient();
13263
13427
  const row = await resolveTask(client, input.taskId);
@@ -13456,8 +13620,8 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
13456
13620
  }
13457
13621
  if (input.baseDir) {
13458
13622
  try {
13459
- await mkdir4(path26.join(input.baseDir, "exe", "output"), { recursive: true });
13460
- await mkdir4(path26.join(input.baseDir, "exe", "research"), { recursive: true });
13623
+ await mkdir4(path27.join(input.baseDir, "exe", "output"), { recursive: true });
13624
+ await mkdir4(path27.join(input.baseDir, "exe", "research"), { recursive: true });
13461
13625
  await ensureArchitectureDoc(input.baseDir, input.projectName);
13462
13626
  await ensureGitignoreExe(input.baseDir);
13463
13627
  } catch {
@@ -13493,10 +13657,10 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
13493
13657
  });
13494
13658
  if (input.baseDir) {
13495
13659
  try {
13496
- const EXE_OS_DIR = path26.join(os13.homedir(), ".exe-os");
13497
- const mdPath = path26.join(EXE_OS_DIR, taskFile);
13498
- const mdDir = path26.dirname(mdPath);
13499
- if (!existsSync22(mdDir)) await mkdir4(mdDir, { recursive: true });
13660
+ const EXE_OS_DIR = path27.join(os13.homedir(), ".exe-os");
13661
+ const mdPath = path27.join(EXE_OS_DIR, taskFile);
13662
+ const mdDir = path27.dirname(mdPath);
13663
+ if (!existsSync23(mdDir)) await mkdir4(mdDir, { recursive: true });
13500
13664
  const reviewer = input.reviewer ?? input.assignedBy;
13501
13665
  const mdContent = `# ${input.title}
13502
13666
 
@@ -13796,9 +13960,9 @@ async function deleteTaskCore(taskId, _baseDir) {
13796
13960
  return { taskFile, assignedTo, assignedBy, taskSlug };
13797
13961
  }
13798
13962
  async function ensureArchitectureDoc(baseDir, projectName) {
13799
- const archPath = path26.join(baseDir, "exe", "ARCHITECTURE.md");
13963
+ const archPath = path27.join(baseDir, "exe", "ARCHITECTURE.md");
13800
13964
  try {
13801
- if (existsSync22(archPath)) return;
13965
+ if (existsSync23(archPath)) return;
13802
13966
  const template = [
13803
13967
  `# ${projectName} \u2014 System Architecture`,
13804
13968
  "",
@@ -13831,10 +13995,10 @@ async function ensureArchitectureDoc(baseDir, projectName) {
13831
13995
  }
13832
13996
  }
13833
13997
  async function ensureGitignoreExe(baseDir) {
13834
- const gitignorePath = path26.join(baseDir, ".gitignore");
13998
+ const gitignorePath = path27.join(baseDir, ".gitignore");
13835
13999
  try {
13836
- if (existsSync22(gitignorePath)) {
13837
- const content = readFileSync16(gitignorePath, "utf-8");
14000
+ if (existsSync23(gitignorePath)) {
14001
+ const content = readFileSync17(gitignorePath, "utf-8");
13838
14002
  if (/^\/?exe\/?$/m.test(content)) return;
13839
14003
  await appendFile(gitignorePath, "\n# Employee task assignments (private)\n/exe/\n");
13840
14004
  } else {
@@ -13865,7 +14029,7 @@ var init_tasks_crud = __esm({
13865
14029
  });
13866
14030
 
13867
14031
  // src/lib/tasks-chain.ts
13868
- import path27 from "path";
14032
+ import path28 from "path";
13869
14033
  import { readFile as readFile4, writeFile as writeFile5 } from "fs/promises";
13870
14034
  async function cascadeUnblock(taskId, baseDir, now2) {
13871
14035
  const client = getClient();
@@ -13882,7 +14046,7 @@ async function cascadeUnblock(taskId, baseDir, now2) {
13882
14046
  });
13883
14047
  for (const ur of unblockedRows.rows) {
13884
14048
  try {
13885
- const ubFile = path27.join(baseDir, String(ur.task_file));
14049
+ const ubFile = path28.join(baseDir, String(ur.task_file));
13886
14050
  let ubContent = await readFile4(ubFile, "utf-8");
13887
14051
  ubContent = ubContent.replace(/\*\*Status:\*\* blocked/, "**Status:** open");
13888
14052
  ubContent = ubContent.replace(/\n\*\*Blocked by:\*\*.*\n/, "\n");
@@ -14396,8 +14560,8 @@ __export(tasks_exports, {
14396
14560
  updateTaskStatus: () => updateTaskStatus,
14397
14561
  writeCheckpoint: () => writeCheckpoint
14398
14562
  });
14399
- import path28 from "path";
14400
- import { writeFileSync as writeFileSync12, mkdirSync as mkdirSync9, unlinkSync as unlinkSync8 } from "fs";
14563
+ import path29 from "path";
14564
+ import { writeFileSync as writeFileSync13, mkdirSync as mkdirSync10, unlinkSync as unlinkSync8 } from "fs";
14401
14565
  async function createTask(input) {
14402
14566
  const result2 = await createTaskCore(input);
14403
14567
  if (!input.skipDispatch && result2.status !== "blocked" && !process.env.VITEST) {
@@ -14416,11 +14580,11 @@ async function updateTask(input) {
14416
14580
  const { row, taskFile, now: now2, taskId } = await updateTaskStatus(input);
14417
14581
  try {
14418
14582
  const agent = String(row.assigned_to);
14419
- const cacheDir = path28.join(EXE_AI_DIR, "session-cache");
14420
- const cachePath = path28.join(cacheDir, `current-task-${agent}.json`);
14583
+ const cacheDir = path29.join(EXE_AI_DIR, "session-cache");
14584
+ const cachePath = path29.join(cacheDir, `current-task-${agent}.json`);
14421
14585
  if (input.status === "in_progress") {
14422
- mkdirSync9(cacheDir, { recursive: true });
14423
- writeFileSync12(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
14586
+ mkdirSync10(cacheDir, { recursive: true });
14587
+ writeFileSync13(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
14424
14588
  } else if (input.status === "done" || input.status === "blocked" || input.status === "cancelled" || input.status === "closed") {
14425
14589
  try {
14426
14590
  unlinkSync8(cachePath);
@@ -14587,17 +14751,17 @@ __export(identity_exports, {
14587
14751
  listIdentities: () => listIdentities,
14588
14752
  updateIdentity: () => updateIdentity
14589
14753
  });
14590
- import { existsSync as existsSync23, mkdirSync as mkdirSync10, readFileSync as readFileSync17, writeFileSync as writeFileSync13 } from "fs";
14754
+ import { existsSync as existsSync24, mkdirSync as mkdirSync11, readFileSync as readFileSync18, writeFileSync as writeFileSync14 } from "fs";
14591
14755
  import { readdirSync as readdirSync7 } from "fs";
14592
- import path29 from "path";
14756
+ import path30 from "path";
14593
14757
  import { createHash as createHash4 } from "crypto";
14594
14758
  function ensureDir2() {
14595
- if (!existsSync23(IDENTITY_DIR2)) {
14596
- mkdirSync10(IDENTITY_DIR2, { recursive: true });
14759
+ if (!existsSync24(IDENTITY_DIR2)) {
14760
+ mkdirSync11(IDENTITY_DIR2, { recursive: true });
14597
14761
  }
14598
14762
  }
14599
14763
  function identityPath(agentId) {
14600
- return path29.join(IDENTITY_DIR2, `${agentId}.md`);
14764
+ return path30.join(IDENTITY_DIR2, `${agentId}.md`);
14601
14765
  }
14602
14766
  function sanitizeIdentityBody(body) {
14603
14767
  return body.replace(/<!--[\s\S]*?-->/g, "").trim();
@@ -14641,8 +14805,8 @@ function contentHash(content) {
14641
14805
  }
14642
14806
  function getIdentity(agentId) {
14643
14807
  const filePath = identityPath(agentId);
14644
- if (!existsSync23(filePath)) return null;
14645
- const raw = readFileSync17(filePath, "utf-8");
14808
+ if (!existsSync24(filePath)) return null;
14809
+ const raw = readFileSync18(filePath, "utf-8");
14646
14810
  const { frontmatter, body } = parseFrontmatter(raw);
14647
14811
  return {
14648
14812
  agentId,
@@ -14656,7 +14820,7 @@ async function updateIdentity(agentId, content, updatedBy) {
14656
14820
  ensureDir2();
14657
14821
  const filePath = identityPath(agentId);
14658
14822
  const hash = contentHash(content);
14659
- writeFileSync13(filePath, content, "utf-8");
14823
+ writeFileSync14(filePath, content, "utf-8");
14660
14824
  try {
14661
14825
  const client = getClient();
14662
14826
  await client.execute({
@@ -14714,7 +14878,7 @@ var init_identity = __esm({
14714
14878
  "use strict";
14715
14879
  init_config();
14716
14880
  init_database();
14717
- IDENTITY_DIR2 = path29.join(EXE_AI_DIR, "identity");
14881
+ IDENTITY_DIR2 = path30.join(EXE_AI_DIR, "identity");
14718
14882
  }
14719
14883
  });
14720
14884
 
@@ -15316,10 +15480,10 @@ function registerCreateTask(server) {
15316
15480
  skipDispatch: true
15317
15481
  });
15318
15482
  try {
15319
- const { existsSync: existsSync45, mkdirSync: mkdirSync24, writeFileSync: writeFileSync28 } = await import("fs");
15483
+ const { existsSync: existsSync47, mkdirSync: mkdirSync25, writeFileSync: writeFileSync29 } = await import("fs");
15320
15484
  const { identityPath: identityPath2 } = await Promise.resolve().then(() => (init_identity(), identity_exports));
15321
15485
  const idPath = identityPath2(assigned_to);
15322
- if (!existsSync45(idPath)) {
15486
+ if (!existsSync47(idPath)) {
15323
15487
  const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
15324
15488
  const employees = await loadEmployees2();
15325
15489
  const emp = employees.find((e) => e.name === assigned_to);
@@ -15328,8 +15492,8 @@ function registerCreateTask(server) {
15328
15492
  const template = getTemplateForTitle2(emp.role);
15329
15493
  if (template) {
15330
15494
  const dir = (await import("path")).dirname(idPath);
15331
- if (!existsSync45(dir)) mkdirSync24(dir, { recursive: true });
15332
- writeFileSync28(idPath, template.replace(/^agent_id: \w+/m, `agent_id: ${assigned_to}`), "utf-8");
15495
+ if (!existsSync47(dir)) mkdirSync25(dir, { recursive: true });
15496
+ writeFileSync29(idPath, template.replace(/^agent_id: \w+/m, `agent_id: ${assigned_to}`), "utf-8");
15333
15497
  }
15334
15498
  }
15335
15499
  }
@@ -17632,13 +17796,13 @@ var init_document = __esm({
17632
17796
  });
17633
17797
 
17634
17798
  // src/gateway/whatsapp-accounts.ts
17635
- import { readFileSync as readFileSync18 } from "fs";
17799
+ import { readFileSync as readFileSync19 } from "fs";
17636
17800
  import { join } from "path";
17637
17801
  import { homedir } from "os";
17638
17802
  function loadAccounts() {
17639
17803
  if (cachedAccounts !== null) return cachedAccounts;
17640
17804
  try {
17641
- const raw = readFileSync18(CONFIG_PATH2, "utf8");
17805
+ const raw = readFileSync19(CONFIG_PATH2, "utf8");
17642
17806
  const parsed = JSON.parse(raw);
17643
17807
  if (!Array.isArray(parsed)) {
17644
17808
  console.warn("[whatsapp] Config is not an array, ignoring");
@@ -17816,7 +17980,7 @@ var init_crm_bridge = __esm({
17816
17980
 
17817
17981
  // src/mcp/tools/send-whatsapp.ts
17818
17982
  import { z as z37 } from "zod";
17819
- import { existsSync as existsSync24, readFileSync as readFileSync19 } from "fs";
17983
+ import { existsSync as existsSync25, readFileSync as readFileSync20 } from "fs";
17820
17984
  import { homedir as homedir2 } from "os";
17821
17985
  import { join as join2 } from "path";
17822
17986
  async function lookupPhoneByName(name) {
@@ -17871,9 +18035,9 @@ function normalizeGatewaySendUrl(value) {
17871
18035
  }
17872
18036
  function loadGatewayJson() {
17873
18037
  const configPath = process.env.EXE_GATEWAY_CONFIG?.trim() || process.env.EXE_GATEWAY_CONFIG_PATH?.trim() || join2(homedir2(), ".exe-os", "gateway.json");
17874
- if (!existsSync24(configPath)) return {};
18038
+ if (!existsSync25(configPath)) return {};
17875
18039
  try {
17876
- return JSON.parse(readFileSync19(configPath, "utf8"));
18040
+ return JSON.parse(readFileSync20(configPath, "utf8"));
17877
18041
  } catch {
17878
18042
  return {};
17879
18043
  }
@@ -18813,12 +18977,12 @@ function registerExportGraph(server) {
18813
18977
  }
18814
18978
  const html = await exportGraphHTML(client);
18815
18979
  const fs = await import("fs");
18816
- const path58 = await import("path");
18980
+ const path60 = await import("path");
18817
18981
  const os25 = await import("os");
18818
- const outDir = path58.join(os25.homedir(), ".exe-os", "exports");
18982
+ const outDir = path60.join(os25.homedir(), ".exe-os", "exports");
18819
18983
  fs.mkdirSync(outDir, { recursive: true });
18820
18984
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
18821
- const filePath = path58.join(outDir, `graph-${timestamp}.html`);
18985
+ const filePath = path60.join(outDir, `graph-${timestamp}.html`);
18822
18986
  fs.writeFileSync(filePath, html, "utf-8");
18823
18987
  return {
18824
18988
  content: [
@@ -20056,7 +20220,7 @@ __export(token_spend_exports, {
20056
20220
  import { readdir } from "fs/promises";
20057
20221
  import { createReadStream } from "fs";
20058
20222
  import { createInterface } from "readline";
20059
- import path30 from "path";
20223
+ import path31 from "path";
20060
20224
  import os14 from "os";
20061
20225
  function getPricing(model) {
20062
20226
  if (MODEL_PRICING[model]) return MODEL_PRICING[model];
@@ -20084,18 +20248,18 @@ async function getAgentSpend(period = "7d") {
20084
20248
  for (const row of dbResult.rows) {
20085
20249
  sessionAgent.set(row.session_uuid, row.agent_id);
20086
20250
  }
20087
- const claudeDir = path30.join(os14.homedir(), ".claude", "projects");
20251
+ const claudeDir = path31.join(os14.homedir(), ".claude", "projects");
20088
20252
  let projectDirs = [];
20089
20253
  try {
20090
20254
  const entries = await readdir(claudeDir);
20091
- projectDirs = entries.map((e) => path30.join(claudeDir, e));
20255
+ projectDirs = entries.map((e) => path31.join(claudeDir, e));
20092
20256
  } catch {
20093
20257
  return [];
20094
20258
  }
20095
20259
  const agentTotals = /* @__PURE__ */ new Map();
20096
20260
  for (const [sessionUuid, agentId] of sessionAgent) {
20097
20261
  for (const dir of projectDirs) {
20098
- const jsonlPath = path30.join(dir, `${sessionUuid}.jsonl`);
20262
+ const jsonlPath = path31.join(dir, `${sessionUuid}.jsonl`);
20099
20263
  try {
20100
20264
  const usage = await extractSessionUsage(jsonlPath);
20101
20265
  if (usage.input === 0 && usage.output === 0) continue;
@@ -20421,8 +20585,8 @@ var init_get_session_kills = __esm({
20421
20585
 
20422
20586
  // src/mcp/tools/get-daemon-health.ts
20423
20587
  import { z as z53 } from "zod";
20424
- import { existsSync as existsSync25, readFileSync as readFileSync20 } from "fs";
20425
- import path31 from "path";
20588
+ import { existsSync as existsSync26, readFileSync as readFileSync21 } from "fs";
20589
+ import path32 from "path";
20426
20590
  import { homedir as homedir3 } from "os";
20427
20591
  function formatUptime(seconds) {
20428
20592
  const h = Math.floor(seconds / 3600);
@@ -20434,8 +20598,8 @@ function formatUptime(seconds) {
20434
20598
  }
20435
20599
  function isDaemonAlive() {
20436
20600
  try {
20437
- if (!existsSync25(PID_PATH2)) return { alive: false, pid: null };
20438
- const pid = parseInt(readFileSync20(PID_PATH2, "utf8").trim(), 10);
20601
+ if (!existsSync26(PID_PATH2)) return { alive: false, pid: null };
20602
+ const pid = parseInt(readFileSync21(PID_PATH2, "utf8").trim(), 10);
20439
20603
  if (isNaN(pid) || pid <= 0) return { alive: false, pid: null };
20440
20604
  process.kill(pid, 0);
20441
20605
  return { alive: true, pid };
@@ -20482,6 +20646,27 @@ function registerGetDaemonHealth(server) {
20482
20646
  lines.push(`| Uptime | ${formatUptime(health.uptime)} |`);
20483
20647
  lines.push(`| Requests served | ${health.requests_served.toLocaleString()} |`);
20484
20648
  }
20649
+ const events = readMcpHttpEvents(50);
20650
+ const summary = summarizeMcpTransport(events);
20651
+ const lastEvent = events.at(-1);
20652
+ lines.push(`| MCP HTTP events | ${events.length > 0 ? `${events.length} recent` : "none recorded"} |`);
20653
+ lines.push(`| MCP HTTP active sessions | ${summary.activeSessions ?? "unknown"} |`);
20654
+ lines.push(`| Last MCP handshake | ${summary.lastSuccessfulHandshake ?? "none"} |`);
20655
+ lines.push(`| Last MCP tool call | ${summary.lastSuccessfulToolCall ?? "none"} |`);
20656
+ lines.push(`| MCP monitor summary | ${summary.eventLogPath.replace("mcp-http-events.jsonl", "monitor/mcp-transport-summary.json")} |`);
20657
+ if (lastEvent) {
20658
+ lines.push(`| Last MCP HTTP event | ${lastEvent.timestamp ?? "unknown"} ${lastEvent.message ?? "unknown"} |`);
20659
+ }
20660
+ if (summary.recentWarnings.length > 0) {
20661
+ lines.push("\n### Recent MCP HTTP warnings");
20662
+ for (const event of summary.recentWarnings.slice(-5)) {
20663
+ lines.push(
20664
+ `- ${event.timestamp ?? "unknown"} \u2014 ${event.message ?? "unknown"} (agent=${event.agentId ?? "unknown"}, session=${event.sessionId ?? "none"})`
20665
+ );
20666
+ }
20667
+ }
20668
+ lines.push("\n### Agent remediation");
20669
+ for (const item of summary.remediation) lines.push(`- ${item}`);
20485
20670
  return {
20486
20671
  content: [{ type: "text", text: lines.join("\n") }]
20487
20672
  };
@@ -20502,7 +20687,64 @@ var PID_PATH2;
20502
20687
  var init_get_daemon_health = __esm({
20503
20688
  "src/mcp/tools/get-daemon-health.ts"() {
20504
20689
  "use strict";
20505
- PID_PATH2 = path31.join(homedir3(), ".exe-os", "exed.pid");
20690
+ init_mcp_transport_health();
20691
+ PID_PATH2 = path32.join(homedir3(), ".exe-os", "exed.pid");
20692
+ }
20693
+ });
20694
+
20695
+ // src/mcp/tools/mcp-ping.ts
20696
+ import { existsSync as existsSync27, readFileSync as readFileSync22 } from "fs";
20697
+ import path33 from "path";
20698
+ import { homedir as homedir4 } from "os";
20699
+ import { z as z54 } from "zod";
20700
+ function isDaemonAlive2() {
20701
+ try {
20702
+ if (!existsSync27(PID_PATH3)) return { alive: false, pid: null };
20703
+ const pid = parseInt(readFileSync22(PID_PATH3, "utf8").trim(), 10);
20704
+ if (!Number.isFinite(pid) || pid <= 0) return { alive: false, pid: null };
20705
+ process.kill(pid, 0);
20706
+ return { alive: true, pid };
20707
+ } catch {
20708
+ return { alive: false, pid: null };
20709
+ }
20710
+ }
20711
+ function registerMcpPing(server) {
20712
+ server.registerTool(
20713
+ "mcp_ping",
20714
+ {
20715
+ title: "MCP Ping",
20716
+ description: "Safe local MCP synthetic probe: daemon liveness plus privacy-safe transport/session summary.",
20717
+ inputSchema: {
20718
+ _placeholder: z54.string().optional().describe("No input required")
20719
+ }
20720
+ },
20721
+ async () => {
20722
+ const daemon = isDaemonAlive2();
20723
+ const summary = summarizeMcpTransport();
20724
+ writeMcpTransportSummary();
20725
+ const status = daemon.alive ? "ok" : "degraded";
20726
+ return {
20727
+ content: [
20728
+ {
20729
+ type: "text",
20730
+ text: JSON.stringify({
20731
+ status,
20732
+ daemon,
20733
+ mcpTransport: summary,
20734
+ 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."
20735
+ }, null, 2)
20736
+ }
20737
+ ]
20738
+ };
20739
+ }
20740
+ );
20741
+ }
20742
+ var PID_PATH3;
20743
+ var init_mcp_ping = __esm({
20744
+ "src/mcp/tools/mcp-ping.ts"() {
20745
+ "use strict";
20746
+ init_mcp_transport_health();
20747
+ PID_PATH3 = path33.join(homedir4(), ".exe-os", "exed.pid");
20506
20748
  }
20507
20749
  });
20508
20750
 
@@ -20784,9 +21026,9 @@ __export(agent_signals_exports, {
20784
21026
  hasOpenTasks: () => hasOpenTasks,
20785
21027
  hasUnreadInbox: () => hasUnreadInbox
20786
21028
  });
20787
- import { readFileSync as readFileSync21, existsSync as existsSync26 } from "fs";
21029
+ import { readFileSync as readFileSync23, existsSync as existsSync28 } from "fs";
20788
21030
  import os15 from "os";
20789
- import path32 from "path";
21031
+ import path34 from "path";
20790
21032
  async function hasOpenTasks(client, agentId) {
20791
21033
  try {
20792
21034
  const scope = sessionScopeFilter(null);
@@ -20828,10 +21070,10 @@ async function hasUnreadInbox(client, agentId) {
20828
21070
  return CONSERVATIVE_ON_ERROR;
20829
21071
  }
20830
21072
  }
20831
- function hadRecentIntercomAck(sessionName, windowMs, nowMs = Date.now(), intercomLog = path32.join(os15.homedir(), ".exe-os", "intercom.log")) {
20832
- if (!existsSync26(intercomLog)) return false;
21073
+ function hadRecentIntercomAck(sessionName, windowMs, nowMs = Date.now(), intercomLog = path34.join(os15.homedir(), ".exe-os", "intercom.log")) {
21074
+ if (!existsSync28(intercomLog)) return false;
20833
21075
  try {
20834
- const raw = readFileSync21(intercomLog, "utf8");
21076
+ const raw = readFileSync23(intercomLog, "utf8");
20835
21077
  const lines = raw.split("\n");
20836
21078
  for (let i = lines.length - 1; i >= 0; i--) {
20837
21079
  const line = lines[i];
@@ -20904,8 +21146,8 @@ __export(daemon_orchestration_exports, {
20904
21146
  shouldNudgeEmployee: () => shouldNudgeEmployee
20905
21147
  });
20906
21148
  import { execSync as execSync12 } from "child_process";
20907
- import { existsSync as existsSync27, readFileSync as readFileSync22, writeFileSync as writeFileSync14 } from "fs";
20908
- import { homedir as homedir4 } from "os";
21149
+ import { existsSync as existsSync29, readFileSync as readFileSync24, writeFileSync as writeFileSync15 } from "fs";
21150
+ import { homedir as homedir5 } from "os";
20909
21151
  import { join as join3 } from "path";
20910
21152
  function shouldNudgeEmployee(sessionState, hasOpenTasks2, lastNudgeMs, nowMs, dedupMs) {
20911
21153
  if (sessionState !== "idle") return false;
@@ -21131,8 +21373,8 @@ async function pollReviewNudge(deps, state) {
21131
21373
  function loadNudgeState() {
21132
21374
  const state = { lastNudge: /* @__PURE__ */ new Map() };
21133
21375
  try {
21134
- if (!existsSync27(NUDGE_STATE_PATH)) return state;
21135
- const raw = JSON.parse(readFileSync22(NUDGE_STATE_PATH, "utf8"));
21376
+ if (!existsSync29(NUDGE_STATE_PATH)) return state;
21377
+ const raw = JSON.parse(readFileSync24(NUDGE_STATE_PATH, "utf8"));
21136
21378
  if (Array.isArray(raw)) {
21137
21379
  for (const [key, val] of raw) {
21138
21380
  if (key && typeof val?.at === "number" && typeof val?.count === "number") {
@@ -21146,7 +21388,7 @@ function loadNudgeState() {
21146
21388
  }
21147
21389
  function saveNudgeState(state) {
21148
21390
  const entries = Array.from(state.lastNudge.entries());
21149
- writeFileSync14(NUDGE_STATE_PATH, JSON.stringify(entries), "utf8");
21391
+ writeFileSync15(NUDGE_STATE_PATH, JSON.stringify(entries), "utf8");
21150
21392
  }
21151
21393
  function createReviewNudgeRealDeps(getClient2) {
21152
21394
  return {
@@ -21480,7 +21722,7 @@ var init_daemon_orchestration = __esm({
21480
21722
  SESSION_CONTEXT_THRESHOLD_PCT = Number(process.env.EXE_CONTEXT_KILL_PCT) || 50;
21481
21723
  IDLE_KILL_INTERCOM_ACK_WINDOW_MS = Number(process.env.EXE_INTERCOM_ACK_WINDOW_MS) || 1e4;
21482
21724
  REVIEW_NUDGE_COOLDOWN_MS = 3e5;
21483
- NUDGE_STATE_PATH = join3(homedir4(), ".exe-os", "review-nudge-state.json");
21725
+ NUDGE_STATE_PATH = join3(homedir5(), ".exe-os", "review-nudge-state.json");
21484
21726
  AUTO_WAKE_COOLDOWN_MS = 5 * 60 * 1e3;
21485
21727
  AUTO_WAKE_MAX_RETRIES = 3;
21486
21728
  _autoWakeLastSpawn = /* @__PURE__ */ new Map();
@@ -21496,7 +21738,7 @@ var init_daemon_orchestration = __esm({
21496
21738
  });
21497
21739
 
21498
21740
  // src/mcp/tools/get-auto-wake-status.ts
21499
- import { z as z54 } from "zod";
21741
+ import { z as z55 } from "zod";
21500
21742
  function registerGetAutoWakeStatus(server) {
21501
21743
  server.registerTool(
21502
21744
  "get_auto_wake_status",
@@ -21504,7 +21746,7 @@ function registerGetAutoWakeStatus(server) {
21504
21746
  title: "Get Auto-Wake Status",
21505
21747
  description: "Check auto-wake status: orphaned tasks (assigned agent has no running session), tasks blocked by auto-wake retry limit, and session activity.",
21506
21748
  inputSchema: {
21507
- _placeholder: z54.string().optional().describe("No input required")
21749
+ _placeholder: z55.string().optional().describe("No input required")
21508
21750
  }
21509
21751
  },
21510
21752
  async () => {
@@ -21602,14 +21844,14 @@ __export(worker_gate_exports, {
21602
21844
  tryAcquireBackfillLock: () => tryAcquireBackfillLock,
21603
21845
  tryAcquireWorkerSlot: () => tryAcquireWorkerSlot
21604
21846
  });
21605
- import { readdirSync as readdirSync8, writeFileSync as writeFileSync15, unlinkSync as unlinkSync9, mkdirSync as mkdirSync11, existsSync as existsSync28 } from "fs";
21606
- import path33 from "path";
21847
+ import { readdirSync as readdirSync8, writeFileSync as writeFileSync16, unlinkSync as unlinkSync9, mkdirSync as mkdirSync12, existsSync as existsSync30 } from "fs";
21848
+ import path35 from "path";
21607
21849
  function tryAcquireWorkerSlot() {
21608
21850
  try {
21609
- mkdirSync11(WORKER_PID_DIR, { recursive: true });
21851
+ mkdirSync12(WORKER_PID_DIR, { recursive: true });
21610
21852
  const reservationId = `res-${process.pid}-${Date.now()}`;
21611
- const reservationPath = path33.join(WORKER_PID_DIR, `${reservationId}.pid`);
21612
- writeFileSync15(reservationPath, String(process.pid));
21853
+ const reservationPath = path35.join(WORKER_PID_DIR, `${reservationId}.pid`);
21854
+ writeFileSync16(reservationPath, String(process.pid));
21613
21855
  const files = readdirSync8(WORKER_PID_DIR);
21614
21856
  let alive = 0;
21615
21857
  for (const f of files) {
@@ -21626,7 +21868,7 @@ function tryAcquireWorkerSlot() {
21626
21868
  alive++;
21627
21869
  } catch {
21628
21870
  try {
21629
- unlinkSync9(path33.join(WORKER_PID_DIR, f));
21871
+ unlinkSync9(path35.join(WORKER_PID_DIR, f));
21630
21872
  } catch {
21631
21873
  }
21632
21874
  }
@@ -21649,21 +21891,21 @@ function tryAcquireWorkerSlot() {
21649
21891
  }
21650
21892
  function registerWorkerPid(pid) {
21651
21893
  try {
21652
- mkdirSync11(WORKER_PID_DIR, { recursive: true });
21653
- writeFileSync15(path33.join(WORKER_PID_DIR, `worker-${pid}.pid`), String(pid));
21894
+ mkdirSync12(WORKER_PID_DIR, { recursive: true });
21895
+ writeFileSync16(path35.join(WORKER_PID_DIR, `worker-${pid}.pid`), String(pid));
21654
21896
  } catch {
21655
21897
  }
21656
21898
  }
21657
21899
  function cleanupWorkerPid() {
21658
21900
  try {
21659
- unlinkSync9(path33.join(WORKER_PID_DIR, `worker-${process.pid}.pid`));
21901
+ unlinkSync9(path35.join(WORKER_PID_DIR, `worker-${process.pid}.pid`));
21660
21902
  } catch {
21661
21903
  }
21662
21904
  }
21663
21905
  function tryAcquireBackfillLock() {
21664
21906
  try {
21665
- mkdirSync11(WORKER_PID_DIR, { recursive: true });
21666
- if (existsSync28(BACKFILL_LOCK)) {
21907
+ mkdirSync12(WORKER_PID_DIR, { recursive: true });
21908
+ if (existsSync30(BACKFILL_LOCK)) {
21667
21909
  try {
21668
21910
  const pid = parseInt(
21669
21911
  __require("fs").readFileSync(BACKFILL_LOCK, "utf8").trim(),
@@ -21679,7 +21921,7 @@ function tryAcquireBackfillLock() {
21679
21921
  } catch {
21680
21922
  }
21681
21923
  }
21682
- writeFileSync15(BACKFILL_LOCK, String(process.pid));
21924
+ writeFileSync16(BACKFILL_LOCK, String(process.pid));
21683
21925
  return true;
21684
21926
  } catch {
21685
21927
  return true;
@@ -21696,22 +21938,22 @@ var init_worker_gate = __esm({
21696
21938
  "src/lib/worker-gate.ts"() {
21697
21939
  "use strict";
21698
21940
  init_config();
21699
- WORKER_PID_DIR = path33.join(EXE_AI_DIR, "worker-pids");
21941
+ WORKER_PID_DIR = path35.join(EXE_AI_DIR, "worker-pids");
21700
21942
  MAX_CONCURRENT_WORKERS = 3;
21701
- BACKFILL_LOCK = path33.join(WORKER_PID_DIR, "backfill.lock");
21943
+ BACKFILL_LOCK = path35.join(WORKER_PID_DIR, "backfill.lock");
21702
21944
  }
21703
21945
  });
21704
21946
 
21705
21947
  // src/mcp/tools/get-worker-gate.ts
21706
- import { z as z55 } from "zod";
21707
- import { readdirSync as readdirSync9, existsSync as existsSync29 } from "fs";
21708
- import path34 from "path";
21948
+ import { z as z56 } from "zod";
21949
+ import { readdirSync as readdirSync9, existsSync as existsSync31 } from "fs";
21950
+ import path36 from "path";
21709
21951
  function countAliveWorkers() {
21710
21952
  let alive = 0;
21711
21953
  let stale = 0;
21712
21954
  let reservations = 0;
21713
21955
  try {
21714
- if (!existsSync29(WORKER_PID_DIR2)) return { alive: 0, stale: 0, reservations: 0 };
21956
+ if (!existsSync31(WORKER_PID_DIR2)) return { alive: 0, stale: 0, reservations: 0 };
21715
21957
  const files = readdirSync9(WORKER_PID_DIR2);
21716
21958
  for (const f of files) {
21717
21959
  if (!f.endsWith(".pid")) continue;
@@ -21740,7 +21982,7 @@ function registerGetWorkerGate(server) {
21740
21982
  title: "Get Worker Gate",
21741
21983
  description: "Check worker concurrency gate status: how many worker slots are in use, the maximum allowed, and whether new workers can spawn.",
21742
21984
  inputSchema: {
21743
- _placeholder: z55.string().optional().describe("No input required")
21985
+ _placeholder: z56.string().optional().describe("No input required")
21744
21986
  }
21745
21987
  },
21746
21988
  async () => {
@@ -21779,19 +22021,19 @@ var init_get_worker_gate = __esm({
21779
22021
  "use strict";
21780
22022
  init_worker_gate();
21781
22023
  init_config();
21782
- WORKER_PID_DIR2 = path34.join(EXE_AI_DIR, "worker-pids");
22024
+ WORKER_PID_DIR2 = path36.join(EXE_AI_DIR, "worker-pids");
21783
22025
  }
21784
22026
  });
21785
22027
 
21786
22028
  // src/lib/is-main.ts
21787
22029
  import { realpathSync } from "fs";
21788
- import { fileURLToPath as fileURLToPath3 } from "url";
22030
+ import { fileURLToPath as fileURLToPath4 } from "url";
21789
22031
  function isMainModule(importMetaUrl) {
21790
22032
  if (process.argv[1] == null) return false;
21791
22033
  if (process.argv[1].includes("mcp/server")) return false;
21792
22034
  try {
21793
22035
  const scriptPath = realpathSync(process.argv[1]);
21794
- const modulePath = realpathSync(fileURLToPath3(importMetaUrl));
22036
+ const modulePath = realpathSync(fileURLToPath4(importMetaUrl));
21795
22037
  return scriptPath === modulePath;
21796
22038
  } catch {
21797
22039
  return importMetaUrl === `file://${process.argv[1]}` || importMetaUrl === new URL(process.argv[1], "file://").href;
@@ -22216,16 +22458,16 @@ __export(key_backup_status_exports, {
22216
22458
  keyBackupMarkerPath: () => keyBackupMarkerPath,
22217
22459
  markKeyBackupConfirmed: () => markKeyBackupConfirmed
22218
22460
  });
22219
- import { existsSync as existsSync30, mkdirSync as mkdirSync12, readFileSync as readFileSync23, writeFileSync as writeFileSync16 } from "fs";
22220
- import path35 from "path";
22461
+ import { existsSync as existsSync32, mkdirSync as mkdirSync13, readFileSync as readFileSync25, writeFileSync as writeFileSync17 } from "fs";
22462
+ import path37 from "path";
22221
22463
  function keyBackupMarkerPath() {
22222
- return path35.join(EXE_AI_DIR, "key-backup-confirmed.json");
22464
+ return path37.join(EXE_AI_DIR, "key-backup-confirmed.json");
22223
22465
  }
22224
22466
  function getKeyBackupStatus() {
22225
22467
  const marker = keyBackupMarkerPath();
22226
- if (!existsSync30(marker)) return { exists: false };
22468
+ if (!existsSync32(marker)) return { exists: false };
22227
22469
  try {
22228
- const parsed = JSON.parse(readFileSync23(marker, "utf8"));
22470
+ const parsed = JSON.parse(readFileSync25(marker, "utf8"));
22229
22471
  return {
22230
22472
  exists: true,
22231
22473
  confirmedAt: parsed.confirmedAt,
@@ -22236,8 +22478,8 @@ function getKeyBackupStatus() {
22236
22478
  }
22237
22479
  }
22238
22480
  function markKeyBackupConfirmed(source) {
22239
- mkdirSync12(EXE_AI_DIR, { recursive: true, mode: 448 });
22240
- writeFileSync16(
22481
+ mkdirSync13(EXE_AI_DIR, { recursive: true, mode: 448 });
22482
+ writeFileSync17(
22241
22483
  keyBackupMarkerPath(),
22242
22484
  JSON.stringify({ confirmedAt: (/* @__PURE__ */ new Date()).toISOString(), source }, null, 2) + "\n",
22243
22485
  { mode: 384 }
@@ -22333,33 +22575,33 @@ __export(db_backup_exports, {
22333
22575
  listBackups: () => listBackups,
22334
22576
  rotateBackups: () => rotateBackups
22335
22577
  });
22336
- import { copyFileSync, existsSync as existsSync31, mkdirSync as mkdirSync13, readdirSync as readdirSync10, unlinkSync as unlinkSync10, statSync as statSync6 } from "fs";
22337
- import path36 from "path";
22578
+ import { copyFileSync, existsSync as existsSync33, mkdirSync as mkdirSync14, readdirSync as readdirSync10, unlinkSync as unlinkSync10, statSync as statSync7 } from "fs";
22579
+ import path38 from "path";
22338
22580
  function findActiveDb() {
22339
22581
  for (const name of DB_NAMES) {
22340
- const p = path36.join(EXE_AI_DIR, name);
22341
- if (existsSync31(p)) return p;
22582
+ const p = path38.join(EXE_AI_DIR, name);
22583
+ if (existsSync33(p)) return p;
22342
22584
  }
22343
22585
  return null;
22344
22586
  }
22345
22587
  function createBackup(reason = "manual") {
22346
22588
  const dbPath = findActiveDb();
22347
22589
  if (!dbPath) return null;
22348
- mkdirSync13(BACKUP_DIR, { recursive: true });
22349
- const dbName = path36.basename(dbPath, ".db");
22590
+ mkdirSync14(BACKUP_DIR, { recursive: true });
22591
+ const dbName = path38.basename(dbPath, ".db");
22350
22592
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
22351
22593
  const backupName = `${dbName}-${reason}-${timestamp}.db`;
22352
- const backupPath = path36.join(BACKUP_DIR, backupName);
22594
+ const backupPath = path38.join(BACKUP_DIR, backupName);
22353
22595
  copyFileSync(dbPath, backupPath);
22354
22596
  const walPath = dbPath + "-wal";
22355
- if (existsSync31(walPath)) {
22597
+ if (existsSync33(walPath)) {
22356
22598
  try {
22357
22599
  copyFileSync(walPath, backupPath + "-wal");
22358
22600
  } catch {
22359
22601
  }
22360
22602
  }
22361
22603
  const shmPath = dbPath + "-shm";
22362
- if (existsSync31(shmPath)) {
22604
+ if (existsSync33(shmPath)) {
22363
22605
  try {
22364
22606
  copyFileSync(shmPath, backupPath + "-shm");
22365
22607
  } catch {
@@ -22368,16 +22610,16 @@ function createBackup(reason = "manual") {
22368
22610
  return backupPath;
22369
22611
  }
22370
22612
  function rotateBackups(keepDays = DEFAULT_KEEP_DAYS) {
22371
- if (!existsSync31(BACKUP_DIR)) return 0;
22613
+ if (!existsSync33(BACKUP_DIR)) return 0;
22372
22614
  const cutoff = Date.now() - keepDays * 24 * 60 * 60 * 1e3;
22373
22615
  let deleted = 0;
22374
22616
  try {
22375
22617
  const files = readdirSync10(BACKUP_DIR);
22376
22618
  for (const file of files) {
22377
22619
  if (!file.endsWith(".db") && !file.endsWith(".db-wal") && !file.endsWith(".db-shm")) continue;
22378
- const filePath = path36.join(BACKUP_DIR, file);
22620
+ const filePath = path38.join(BACKUP_DIR, file);
22379
22621
  try {
22380
- const stat = statSync6(filePath);
22622
+ const stat = statSync7(filePath);
22381
22623
  if (stat.mtimeMs < cutoff) {
22382
22624
  unlinkSync10(filePath);
22383
22625
  deleted++;
@@ -22390,12 +22632,12 @@ function rotateBackups(keepDays = DEFAULT_KEEP_DAYS) {
22390
22632
  return deleted;
22391
22633
  }
22392
22634
  function listBackups() {
22393
- if (!existsSync31(BACKUP_DIR)) return [];
22635
+ if (!existsSync33(BACKUP_DIR)) return [];
22394
22636
  try {
22395
22637
  const files = readdirSync10(BACKUP_DIR).filter((f) => f.endsWith(".db") && !f.endsWith("-wal") && !f.endsWith("-shm"));
22396
22638
  return files.map((name) => {
22397
- const p = path36.join(BACKUP_DIR, name);
22398
- const stat = statSync6(p);
22639
+ const p = path38.join(BACKUP_DIR, name);
22640
+ const stat = statSync7(p);
22399
22641
  return { path: p, name, size: stat.size, date: stat.mtime };
22400
22642
  }).sort((a, b) => b.date.getTime() - a.date.getTime());
22401
22643
  } catch {
@@ -22419,7 +22661,7 @@ var init_db_backup = __esm({
22419
22661
  "src/lib/db-backup.ts"() {
22420
22662
  "use strict";
22421
22663
  init_config();
22422
- BACKUP_DIR = path36.join(EXE_AI_DIR, "backups");
22664
+ BACKUP_DIR = path38.join(EXE_AI_DIR, "backups");
22423
22665
  DEFAULT_KEEP_DAYS = 3;
22424
22666
  DB_NAMES = ["memories.db", "exe-mem.db", "exe-os.db", "exe.db"];
22425
22667
  }
@@ -22427,9 +22669,9 @@ var init_db_backup = __esm({
22427
22669
 
22428
22670
  // src/bin/exe-doctor.ts
22429
22671
  import os16 from "os";
22430
- import { existsSync as existsSync32, readFileSync as readFileSync24 } from "fs";
22672
+ import { existsSync as existsSync34, readFileSync as readFileSync26 } from "fs";
22431
22673
  import { spawn as spawn2 } from "child_process";
22432
- import path37 from "path";
22674
+ import path39 from "path";
22433
22675
  import { randomUUID as randomUUID5 } from "crypto";
22434
22676
  function parseFlags(argv) {
22435
22677
  const flags = { fix: false, dryRun: false, verbose: false, conflicts: false };
@@ -22581,7 +22823,7 @@ async function auditOrphanedProjects(client) {
22581
22823
  for (const row of result2.rows) {
22582
22824
  const name = row.project_name;
22583
22825
  const count = Number(row.cnt);
22584
- const exists = existsSync32(path37.join(home, name)) || existsSync32(path37.join(home, "..", name)) || existsSync32(path37.join(process.cwd(), "..", name));
22826
+ const exists = existsSync34(path39.join(home, name)) || existsSync34(path39.join(home, "..", name)) || existsSync34(path39.join(process.cwd(), "..", name));
22585
22827
  if (!exists) {
22586
22828
  orphans.push({ project_name: name, count });
22587
22829
  }
@@ -22589,18 +22831,18 @@ async function auditOrphanedProjects(client) {
22589
22831
  return orphans;
22590
22832
  }
22591
22833
  function auditHookHealth() {
22592
- const logPath = path37.join(
22834
+ const logPath = path39.join(
22593
22835
  process.env.HOME ?? process.env.USERPROFILE ?? "",
22594
22836
  ".exe-os",
22595
22837
  "logs",
22596
22838
  "hooks.log"
22597
22839
  );
22598
- if (!existsSync32(logPath)) {
22840
+ if (!existsSync34(logPath)) {
22599
22841
  return { logExists: false, totalLines: 0, errorsLastHour: 0, topPatterns: [] };
22600
22842
  }
22601
22843
  let content;
22602
22844
  try {
22603
- content = readFileSync24(logPath, "utf-8");
22845
+ content = readFileSync26(logPath, "utf-8");
22604
22846
  } catch {
22605
22847
  return { logExists: false, totalLines: 0, errorsLastHour: 0, topPatterns: [] };
22606
22848
  }
@@ -22629,9 +22871,9 @@ function auditHookHealth() {
22629
22871
  return { logExists: true, totalLines, errorsLastHour, topPatterns };
22630
22872
  }
22631
22873
  function safeReadJson(filePath) {
22632
- if (!existsSync32(filePath)) return null;
22874
+ if (!existsSync34(filePath)) return null;
22633
22875
  try {
22634
- return JSON.parse(readFileSync24(filePath, "utf-8"));
22876
+ return JSON.parse(readFileSync26(filePath, "utf-8"));
22635
22877
  } catch {
22636
22878
  return null;
22637
22879
  }
@@ -22725,13 +22967,13 @@ function auditHookOwnership() {
22725
22967
  const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
22726
22968
  const checkedFiles = [];
22727
22969
  const issues = [];
22728
- const claudeSettingsPath = path37.join(home, ".claude", "settings.json");
22970
+ const claudeSettingsPath = path39.join(home, ".claude", "settings.json");
22729
22971
  const claudeSettings = safeReadJson(claudeSettingsPath);
22730
22972
  if (claudeSettings) {
22731
22973
  checkedFiles.push(claudeSettingsPath);
22732
22974
  issues.push(...buildHookOwnershipIssues("claude", collectHookCommandsFromClaudeSettings(claudeSettings)));
22733
22975
  }
22734
- const codexHooksPath = path37.join(home, ".codex", "hooks.json");
22976
+ const codexHooksPath = path39.join(home, ".codex", "hooks.json");
22735
22977
  const codexHooks = safeReadJson(codexHooksPath);
22736
22978
  if (codexHooks) {
22737
22979
  checkedFiles.push(codexHooksPath);
@@ -22995,7 +23237,7 @@ async function fixNullVectors() {
22995
23237
  }
22996
23238
  }
22997
23239
  const npmRoot = (await import("child_process")).execSync("npm root -g", { encoding: "utf8" }).trim();
22998
- const backfillPath = path37.join(npmRoot, "exe-os", "dist", "bin", "backfill-vectors.js");
23240
+ const backfillPath = path39.join(npmRoot, "exe-os", "dist", "bin", "backfill-vectors.js");
22999
23241
  return new Promise((resolve, reject) => {
23000
23242
  const child = spawn2("node", [backfillPath], { stdio: "inherit" });
23001
23243
  if (child.pid) registerWorkerPid2(child.pid);
@@ -23181,7 +23423,7 @@ var init_exe_doctor = __esm({
23181
23423
  });
23182
23424
 
23183
23425
  // src/mcp/tools/run-memory-audit.ts
23184
- import { z as z56 } from "zod";
23426
+ import { z as z57 } from "zod";
23185
23427
  function registerRunMemoryAudit(server) {
23186
23428
  server.registerTool(
23187
23429
  "run_memory_audit",
@@ -23189,8 +23431,8 @@ function registerRunMemoryAudit(server) {
23189
23431
  title: "Run Memory Audit",
23190
23432
  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).",
23191
23433
  inputSchema: {
23192
- agent_id: z56.string().optional().describe("Filter audit to a specific agent"),
23193
- project_name: z56.string().optional().describe("Filter audit to a specific project")
23434
+ agent_id: z57.string().optional().describe("Filter audit to a specific agent"),
23435
+ project_name: z57.string().optional().describe("Filter audit to a specific project")
23194
23436
  }
23195
23437
  },
23196
23438
  async ({ agent_id, project_name }) => {
@@ -23232,7 +23474,7 @@ var init_run_memory_audit = __esm({
23232
23474
  });
23233
23475
 
23234
23476
  // src/mcp/tools/run-consolidation.ts
23235
- import { z as z57 } from "zod";
23477
+ import { z as z58 } from "zod";
23236
23478
  function registerRunConsolidation(server) {
23237
23479
  server.registerTool(
23238
23480
  "run_consolidation",
@@ -23240,7 +23482,7 @@ function registerRunConsolidation(server) {
23240
23482
  title: "Run Consolidation",
23241
23483
  description: "Run memory consolidation \u2014 synthesizes unconsolidated memories into meta-insights. Use dry_run=true (default) to preview without executing.",
23242
23484
  inputSchema: {
23243
- dry_run: z57.boolean().default(true).describe("Preview mode \u2014 show what would be consolidated without doing it")
23485
+ dry_run: z58.boolean().default(true).describe("Preview mode \u2014 show what would be consolidated without doing it")
23244
23486
  }
23245
23487
  },
23246
23488
  async ({ dry_run }) => {
@@ -23406,9 +23648,9 @@ __export(crdt_sync_exports, {
23406
23648
  rebuildFromDb: () => rebuildFromDb
23407
23649
  });
23408
23650
  import * as Y from "yjs";
23409
- import { readFileSync as readFileSync25, writeFileSync as writeFileSync17, existsSync as existsSync33, mkdirSync as mkdirSync14, unlinkSync as unlinkSync11 } from "fs";
23410
- import path38 from "path";
23411
- import { homedir as homedir5 } from "os";
23651
+ import { readFileSync as readFileSync27, writeFileSync as writeFileSync18, existsSync as existsSync35, mkdirSync as mkdirSync15, unlinkSync as unlinkSync11 } from "fs";
23652
+ import path40 from "path";
23653
+ import { homedir as homedir6 } from "os";
23412
23654
  function getStatePath() {
23413
23655
  return _statePathOverride ?? DEFAULT_STATE_PATH;
23414
23656
  }
@@ -23419,9 +23661,9 @@ function initCrdtDoc() {
23419
23661
  if (doc) return doc;
23420
23662
  doc = new Y.Doc();
23421
23663
  const sp = getStatePath();
23422
- if (existsSync33(sp)) {
23664
+ if (existsSync35(sp)) {
23423
23665
  try {
23424
- const state = readFileSync25(sp);
23666
+ const state = readFileSync27(sp);
23425
23667
  Y.applyUpdate(doc, new Uint8Array(state));
23426
23668
  } catch {
23427
23669
  console.warn("[crdt-sync] WARN: corrupted state file, rebuilding from DB");
@@ -23563,10 +23805,10 @@ function persistState() {
23563
23805
  if (!doc) return;
23564
23806
  try {
23565
23807
  const sp = getStatePath();
23566
- const dir = path38.dirname(sp);
23567
- if (!existsSync33(dir)) mkdirSync14(dir, { recursive: true });
23808
+ const dir = path40.dirname(sp);
23809
+ if (!existsSync35(dir)) mkdirSync15(dir, { recursive: true });
23568
23810
  const state = Y.encodeStateAsUpdate(doc);
23569
- writeFileSync17(sp, Buffer.from(state));
23811
+ writeFileSync18(sp, Buffer.from(state));
23570
23812
  } catch {
23571
23813
  }
23572
23814
  }
@@ -23607,7 +23849,7 @@ var DEFAULT_STATE_PATH, _statePathOverride, doc;
23607
23849
  var init_crdt_sync = __esm({
23608
23850
  "src/lib/crdt-sync.ts"() {
23609
23851
  "use strict";
23610
- DEFAULT_STATE_PATH = path38.join(homedir5(), ".exe-os", "crdt-state.bin");
23852
+ DEFAULT_STATE_PATH = path40.join(homedir6(), ".exe-os", "crdt-state.bin");
23611
23853
  _statePathOverride = null;
23612
23854
  doc = null;
23613
23855
  }
@@ -23647,17 +23889,17 @@ __export(cloud_sync_exports, {
23647
23889
  pushToPostgres: () => pushToPostgres,
23648
23890
  recordRosterDeletion: () => recordRosterDeletion
23649
23891
  });
23650
- import { readFileSync as readFileSync26, writeFileSync as writeFileSync18, existsSync as existsSync34, readdirSync as readdirSync11, mkdirSync as mkdirSync15, appendFileSync as appendFileSync3, unlinkSync as unlinkSync12, openSync as openSync2, closeSync as closeSync2, statSync as statSync7 } from "fs";
23892
+ import { readFileSync as readFileSync28, writeFileSync as writeFileSync19, existsSync as existsSync36, readdirSync as readdirSync11, mkdirSync as mkdirSync16, appendFileSync as appendFileSync4, unlinkSync as unlinkSync12, openSync as openSync3, closeSync as closeSync3, statSync as statSync8 } from "fs";
23651
23893
  import crypto16 from "crypto";
23652
- import path39 from "path";
23653
- import { homedir as homedir6 } from "os";
23894
+ import path41 from "path";
23895
+ import { homedir as homedir7 } from "os";
23654
23896
  function sqlSafe(v) {
23655
23897
  return v === void 0 ? null : v;
23656
23898
  }
23657
23899
  function logError(msg) {
23658
23900
  try {
23659
- const logPath = path39.join(homedir6(), ".exe-os", "workers.log");
23660
- appendFileSync3(logPath, `${(/* @__PURE__ */ new Date()).toISOString()} ${msg}
23901
+ const logPath = path41.join(homedir7(), ".exe-os", "workers.log");
23902
+ appendFileSync4(logPath, `${(/* @__PURE__ */ new Date()).toISOString()} ${msg}
23661
23903
  `);
23662
23904
  } catch {
23663
23905
  }
@@ -23667,12 +23909,12 @@ function isTruthyEnv2(value) {
23667
23909
  }
23668
23910
  function loadPgClient() {
23669
23911
  if (_pgFailed) return null;
23670
- const configPath = path39.join(EXE_AI_DIR, "config.json");
23912
+ const configPath = path41.join(EXE_AI_DIR, "config.json");
23671
23913
  let cloudPostgresUrl;
23672
23914
  let configEnabled = false;
23673
23915
  try {
23674
- if (existsSync34(configPath)) {
23675
- const cfg = JSON.parse(readFileSync26(configPath, "utf8"));
23916
+ if (existsSync36(configPath)) {
23917
+ const cfg = JSON.parse(readFileSync28(configPath, "utf8"));
23676
23918
  cloudPostgresUrl = cfg.cloud?.postgresUrl;
23677
23919
  configEnabled = cfg.cloud?.syncToPostgres === true;
23678
23920
  }
@@ -23699,9 +23941,9 @@ function loadPgClient() {
23699
23941
  if (!Ctor) throw new Error(`No PrismaClient at ${explicitPath}`);
23700
23942
  return new Ctor();
23701
23943
  }
23702
- const exeDbRoot = process.env.EXE_DB_ROOT ?? path39.join(homedir6(), "exe-db");
23703
- const packagePath = path39.join(exeDbRoot, "package.json");
23704
- if (existsSync34(packagePath)) {
23944
+ const exeDbRoot = process.env.EXE_DB_ROOT ?? path41.join(homedir7(), "exe-db");
23945
+ const packagePath = path41.join(exeDbRoot, "package.json");
23946
+ if (existsSync36(packagePath)) {
23705
23947
  const req = createRequire7(packagePath);
23706
23948
  const entry = req.resolve("@prisma/client");
23707
23949
  const mod = await import(pathToFileURL7(entry).href);
@@ -23761,20 +24003,20 @@ async function pushToPostgres(records) {
23761
24003
  }
23762
24004
  async function withRosterLock(fn) {
23763
24005
  try {
23764
- const fd = openSync2(ROSTER_LOCK_PATH, "wx");
23765
- closeSync2(fd);
23766
- writeFileSync18(ROSTER_LOCK_PATH, String(Date.now()));
24006
+ const fd = openSync3(ROSTER_LOCK_PATH, "wx");
24007
+ closeSync3(fd);
24008
+ writeFileSync19(ROSTER_LOCK_PATH, String(Date.now()));
23767
24009
  } catch (err) {
23768
24010
  if (err.code === "EEXIST") {
23769
24011
  try {
23770
- const ts2 = parseInt(readFileSync26(ROSTER_LOCK_PATH, "utf-8"), 10);
24012
+ const ts2 = parseInt(readFileSync28(ROSTER_LOCK_PATH, "utf-8"), 10);
23771
24013
  if (Date.now() - ts2 < LOCK_STALE_MS) {
23772
24014
  throw new Error("Roster merge already in progress \u2014 another sync is running");
23773
24015
  }
23774
24016
  unlinkSync12(ROSTER_LOCK_PATH);
23775
- const fd = openSync2(ROSTER_LOCK_PATH, "wx");
23776
- closeSync2(fd);
23777
- writeFileSync18(ROSTER_LOCK_PATH, String(Date.now()));
24017
+ const fd = openSync3(ROSTER_LOCK_PATH, "wx");
24018
+ closeSync3(fd);
24019
+ writeFileSync19(ROSTER_LOCK_PATH, String(Date.now()));
23778
24020
  } catch (retryErr) {
23779
24021
  if (retryErr instanceof Error && retryErr.message.includes("already in progress")) throw retryErr;
23780
24022
  throw new Error("Roster merge already in progress \u2014 another sync is running");
@@ -24220,8 +24462,8 @@ async function cloudSync(config2) {
24220
24462
  try {
24221
24463
  const employees = await loadEmployees();
24222
24464
  rosterResult.employees = employees.length;
24223
- const idDir = path39.join(EXE_AI_DIR, "identity");
24224
- if (existsSync34(idDir)) {
24465
+ const idDir = path41.join(EXE_AI_DIR, "identity");
24466
+ if (existsSync36(idDir)) {
24225
24467
  rosterResult.identities = readdirSync11(idDir).filter((f) => f.endsWith(".md")).length;
24226
24468
  }
24227
24469
  } catch {
@@ -24231,10 +24473,10 @@ async function cloudSync(config2) {
24231
24473
  const { getLatestBackup: getLatestBackup2 } = await Promise.resolve().then(() => (init_db_backup(), db_backup_exports));
24232
24474
  const latestBackup = getLatestBackup2();
24233
24475
  if (latestBackup) {
24234
- const backupSize = statSync7(latestBackup).size;
24476
+ const backupSize = statSync8(latestBackup).size;
24235
24477
  const MAX_CLOUD_BACKUP_BYTES = 50 * 1024 * 1024;
24236
24478
  if (backupSize <= MAX_CLOUD_BACKUP_BYTES) {
24237
- const backupData = readFileSync26(latestBackup);
24479
+ const backupData = readFileSync28(latestBackup);
24238
24480
  const deviceId = loadDeviceId() ?? "unknown";
24239
24481
  const encrypted = encryptSyncBlob(backupData);
24240
24482
  const backupRes = await fetchWithRetry(`${config2.endpoint}/sync/push-db-backup`, {
@@ -24242,7 +24484,7 @@ async function cloudSync(config2) {
24242
24484
  headers: { "Content-Type": "application/json", Authorization: `Bearer ${config2.apiKey}` },
24243
24485
  body: JSON.stringify({
24244
24486
  device_id: deviceId,
24245
- filename: path39.basename(latestBackup),
24487
+ filename: path41.basename(latestBackup),
24246
24488
  blob: encrypted,
24247
24489
  size: backupData.length
24248
24490
  })
@@ -24270,56 +24512,56 @@ async function cloudSync(config2) {
24270
24512
  function recordRosterDeletion(name) {
24271
24513
  let deletions = [];
24272
24514
  try {
24273
- if (existsSync34(ROSTER_DELETIONS_PATH)) {
24274
- deletions = JSON.parse(readFileSync26(ROSTER_DELETIONS_PATH, "utf-8"));
24515
+ if (existsSync36(ROSTER_DELETIONS_PATH)) {
24516
+ deletions = JSON.parse(readFileSync28(ROSTER_DELETIONS_PATH, "utf-8"));
24275
24517
  }
24276
24518
  } catch {
24277
24519
  }
24278
24520
  if (!deletions.includes(name)) deletions.push(name);
24279
- writeFileSync18(ROSTER_DELETIONS_PATH, JSON.stringify(deletions));
24521
+ writeFileSync19(ROSTER_DELETIONS_PATH, JSON.stringify(deletions));
24280
24522
  }
24281
24523
  function consumeRosterDeletions() {
24282
24524
  try {
24283
- if (!existsSync34(ROSTER_DELETIONS_PATH)) return [];
24284
- const deletions = JSON.parse(readFileSync26(ROSTER_DELETIONS_PATH, "utf-8"));
24285
- writeFileSync18(ROSTER_DELETIONS_PATH, "[]");
24525
+ if (!existsSync36(ROSTER_DELETIONS_PATH)) return [];
24526
+ const deletions = JSON.parse(readFileSync28(ROSTER_DELETIONS_PATH, "utf-8"));
24527
+ writeFileSync19(ROSTER_DELETIONS_PATH, "[]");
24286
24528
  return deletions;
24287
24529
  } catch {
24288
24530
  return [];
24289
24531
  }
24290
24532
  }
24291
24533
  function buildRosterBlob(paths) {
24292
- const rosterPath = paths?.rosterPath ?? path39.join(EXE_AI_DIR, "exe-employees.json");
24293
- const identityDir = paths?.identityDir ?? path39.join(EXE_AI_DIR, "identity");
24294
- const configPath = paths?.configPath ?? path39.join(EXE_AI_DIR, "config.json");
24534
+ const rosterPath = paths?.rosterPath ?? path41.join(EXE_AI_DIR, "exe-employees.json");
24535
+ const identityDir = paths?.identityDir ?? path41.join(EXE_AI_DIR, "identity");
24536
+ const configPath = paths?.configPath ?? path41.join(EXE_AI_DIR, "config.json");
24295
24537
  let roster = [];
24296
- if (existsSync34(rosterPath)) {
24538
+ if (existsSync36(rosterPath)) {
24297
24539
  try {
24298
- roster = JSON.parse(readFileSync26(rosterPath, "utf-8"));
24540
+ roster = JSON.parse(readFileSync28(rosterPath, "utf-8"));
24299
24541
  } catch {
24300
24542
  }
24301
24543
  }
24302
24544
  const identities = {};
24303
- if (existsSync34(identityDir)) {
24545
+ if (existsSync36(identityDir)) {
24304
24546
  for (const file of readdirSync11(identityDir).filter((f) => f.endsWith(".md"))) {
24305
24547
  try {
24306
- identities[file] = readFileSync26(path39.join(identityDir, file), "utf-8");
24548
+ identities[file] = readFileSync28(path41.join(identityDir, file), "utf-8");
24307
24549
  } catch {
24308
24550
  }
24309
24551
  }
24310
24552
  }
24311
24553
  let config2;
24312
- if (existsSync34(configPath)) {
24554
+ if (existsSync36(configPath)) {
24313
24555
  try {
24314
- config2 = JSON.parse(readFileSync26(configPath, "utf-8"));
24556
+ config2 = JSON.parse(readFileSync28(configPath, "utf-8"));
24315
24557
  } catch {
24316
24558
  }
24317
24559
  }
24318
24560
  let agentConfig;
24319
- const agentConfigPath = path39.join(EXE_AI_DIR, "agent-config.json");
24320
- if (existsSync34(agentConfigPath)) {
24561
+ const agentConfigPath = path41.join(EXE_AI_DIR, "agent-config.json");
24562
+ if (existsSync36(agentConfigPath)) {
24321
24563
  try {
24322
- agentConfig = JSON.parse(readFileSync26(agentConfigPath, "utf-8"));
24564
+ agentConfig = JSON.parse(readFileSync28(agentConfigPath, "utf-8"));
24323
24565
  } catch {
24324
24566
  }
24325
24567
  }
@@ -24395,24 +24637,24 @@ async function cloudPullRoster(config2) {
24395
24637
  }
24396
24638
  }
24397
24639
  function mergeConfig(remoteConfig, configPath) {
24398
- const cfgPath = configPath ?? path39.join(EXE_AI_DIR, "config.json");
24640
+ const cfgPath = configPath ?? path41.join(EXE_AI_DIR, "config.json");
24399
24641
  let local = {};
24400
- if (existsSync34(cfgPath)) {
24642
+ if (existsSync36(cfgPath)) {
24401
24643
  try {
24402
- local = JSON.parse(readFileSync26(cfgPath, "utf-8"));
24644
+ local = JSON.parse(readFileSync28(cfgPath, "utf-8"));
24403
24645
  } catch {
24404
24646
  }
24405
24647
  }
24406
24648
  const merged = { ...remoteConfig, ...local };
24407
- const dir = path39.dirname(cfgPath);
24649
+ const dir = path41.dirname(cfgPath);
24408
24650
  ensurePrivateDirSync(dir);
24409
- writeFileSync18(cfgPath, JSON.stringify(merged, null, 2), "utf-8");
24651
+ writeFileSync19(cfgPath, JSON.stringify(merged, null, 2), "utf-8");
24410
24652
  enforcePrivateFileSync(cfgPath);
24411
24653
  }
24412
24654
  async function mergeRosterFromRemote(remote, paths) {
24413
24655
  return withRosterLock(async () => {
24414
24656
  const rosterPath = paths?.rosterPath ?? void 0;
24415
- const identityDir = paths?.identityDir ?? path39.join(EXE_AI_DIR, "identity");
24657
+ const identityDir = paths?.identityDir ?? path41.join(EXE_AI_DIR, "identity");
24416
24658
  const localEmployees = await loadEmployees(rosterPath);
24417
24659
  const localNames = new Set(localEmployees.map((e) => e.name));
24418
24660
  let added = 0;
@@ -24433,15 +24675,15 @@ async function mergeRosterFromRemote(remote, paths) {
24433
24675
  ) ?? lookupKey;
24434
24676
  const remoteIdentity = remote.identities[matchedKey];
24435
24677
  if (remoteIdentity) {
24436
- if (!existsSync34(identityDir)) mkdirSync15(identityDir, { recursive: true });
24437
- const idPath = path39.join(identityDir, `${remoteEmp.name}.md`);
24678
+ if (!existsSync36(identityDir)) mkdirSync16(identityDir, { recursive: true });
24679
+ const idPath = path41.join(identityDir, `${remoteEmp.name}.md`);
24438
24680
  let localIdentity = null;
24439
24681
  try {
24440
- localIdentity = existsSync34(idPath) ? readFileSync26(idPath, "utf-8") : null;
24682
+ localIdentity = existsSync36(idPath) ? readFileSync28(idPath, "utf-8") : null;
24441
24683
  } catch {
24442
24684
  }
24443
24685
  if (localIdentity !== remoteIdentity) {
24444
- writeFileSync18(idPath, remoteIdentity, "utf-8");
24686
+ writeFileSync19(idPath, remoteIdentity, "utf-8");
24445
24687
  identitiesUpdated++;
24446
24688
  }
24447
24689
  }
@@ -24467,17 +24709,17 @@ async function mergeRosterFromRemote(remote, paths) {
24467
24709
  }
24468
24710
  if (remote.agentConfig && Object.keys(remote.agentConfig).length > 0) {
24469
24711
  try {
24470
- const agentConfigPath = path39.join(EXE_AI_DIR, "agent-config.json");
24712
+ const agentConfigPath = path41.join(EXE_AI_DIR, "agent-config.json");
24471
24713
  let local = {};
24472
- if (existsSync34(agentConfigPath)) {
24714
+ if (existsSync36(agentConfigPath)) {
24473
24715
  try {
24474
- local = JSON.parse(readFileSync26(agentConfigPath, "utf-8"));
24716
+ local = JSON.parse(readFileSync28(agentConfigPath, "utf-8"));
24475
24717
  } catch {
24476
24718
  }
24477
24719
  }
24478
24720
  const merged = { ...remote.agentConfig, ...local };
24479
- ensurePrivateDirSync(path39.dirname(agentConfigPath));
24480
- writeFileSync18(agentConfigPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
24721
+ ensurePrivateDirSync(path41.dirname(agentConfigPath));
24722
+ writeFileSync19(agentConfigPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
24481
24723
  enforcePrivateFileSync(agentConfigPath);
24482
24724
  } catch {
24483
24725
  }
@@ -24917,17 +25159,17 @@ var init_cloud_sync = __esm({
24917
25159
  LOCALHOST_PATTERNS = /^(localhost|127\.0\.0\.1|\[::1\])$/i;
24918
25160
  FETCH_TIMEOUT_MS2 = 3e4;
24919
25161
  PUSH_BATCH_SIZE = 5e3;
24920
- ROSTER_LOCK_PATH = path39.join(EXE_AI_DIR, "roster-merge.lock");
25162
+ ROSTER_LOCK_PATH = path41.join(EXE_AI_DIR, "roster-merge.lock");
24921
25163
  LOCK_STALE_MS = 3e4;
24922
25164
  _pgPromise = null;
24923
25165
  _pgFailed = false;
24924
25166
  CLOUD_REUPLOAD_REQUIRED_MESSAGE = "Cloud sync is blocked because this device rotated its memory encryption key. Run `exe-os cloud reupload` first to re-upload the cloud backup with the new key.";
24925
- ROSTER_DELETIONS_PATH = path39.join(EXE_AI_DIR, "roster-deletions.json");
25167
+ ROSTER_DELETIONS_PATH = path41.join(EXE_AI_DIR, "roster-deletions.json");
24926
25168
  }
24927
25169
  });
24928
25170
 
24929
25171
  // src/mcp/tools/cloud-sync.ts
24930
- import { z as z58 } from "zod";
25172
+ import { z as z59 } from "zod";
24931
25173
  function result(text3, isError = false) {
24932
25174
  return { content: [{ type: "text", text: text3 }], ...isError ? { isError: true } : {} };
24933
25175
  }
@@ -25008,9 +25250,9 @@ function registerCloudSync(server) {
25008
25250
  title: "Cloud Sync",
25009
25251
  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.",
25010
25252
  inputSchema: {
25011
- 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."),
25012
- force: z58.boolean().default(false).describe("Reserved for sync compatibility; normal cloud sync already runs when requested."),
25013
- confirm_local_db_source_of_truth: z58.string().optional().describe('Required for action=reupload. Must exactly equal "LOCAL DB IS SOURCE OF TRUTH".')
25253
+ 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."),
25254
+ force: z59.boolean().default(false).describe("Reserved for sync compatibility; normal cloud sync already runs when requested."),
25255
+ confirm_local_db_source_of_truth: z59.string().optional().describe('Required for action=reupload. Must exactly equal "LOCAL DB IS SOURCE OF TRUTH".')
25014
25256
  }
25015
25257
  },
25016
25258
  async ({ action = "sync", confirm_local_db_source_of_truth }) => {
@@ -25163,7 +25405,7 @@ var init_orchestration_phase = __esm({
25163
25405
  });
25164
25406
 
25165
25407
  // src/mcp/tools/orchestration-phase.ts
25166
- import { z as z59 } from "zod";
25408
+ import { z as z60 } from "zod";
25167
25409
  function render(info, prefix) {
25168
25410
  return [
25169
25411
  prefix,
@@ -25182,8 +25424,8 @@ function registerOrchestrationPhase(server) {
25182
25424
  title: "Orchestration Phase",
25183
25425
  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.",
25184
25426
  inputSchema: {
25185
- action: z59.enum(["status", "set", "unlock_executives", "unlock_parallel"]).default("status"),
25186
- phase: z59.enum(["phase_1_coo", "phase_2_executives", "phase_3_parallel_org", "1", "2", "3"]).optional().describe("Phase to set when action='set'.")
25427
+ action: z60.enum(["status", "set", "unlock_executives", "unlock_parallel"]).default("status"),
25428
+ phase: z60.enum(["phase_1_coo", "phase_2_executives", "phase_3_parallel_org", "1", "2", "3"]).optional().describe("Phase to set when action='set'.")
25187
25429
  }
25188
25430
  },
25189
25431
  async ({ action = "status", phase }) => {
@@ -25551,50 +25793,50 @@ var init_vps_backup = __esm({
25551
25793
  });
25552
25794
 
25553
25795
  // src/mcp/tools/backup-vps.ts
25554
- import { z as z60 } from "zod";
25796
+ import { z as z61 } from "zod";
25555
25797
  function registerBackupVps(server) {
25556
25798
  server.registerTool(
25557
25799
  "backup_vps",
25558
25800
  {
25559
25801
  title: "VPS Backup",
25560
25802
  description: "Run VPS Postgres backup/restore workflows and check status.",
25561
- inputSchema: z60.discriminatedUnion("action", [
25562
- z60.object({
25563
- action: z60.literal("backup"),
25564
- databaseUrl: z60.string().min(1).describe("Postgres DATABASE_URL to dump from"),
25565
- encryptionKeyB64: z60.string().min(1).max(4096).optional().describe(
25803
+ inputSchema: z61.discriminatedUnion("action", [
25804
+ z61.object({
25805
+ action: z61.literal("backup"),
25806
+ databaseUrl: z61.string().min(1).describe("Postgres DATABASE_URL to dump from"),
25807
+ encryptionKeyB64: z61.string().min(1).max(4096).optional().describe(
25566
25808
  "Base64 AES-256 key (defaults to local master key if omitted)"
25567
25809
  ),
25568
- r2Bucket: z60.string().min(1).describe("R2 bucket name"),
25569
- r2Endpoint: z60.string().min(1).describe("R2 endpoint URL"),
25570
- r2AccessKeyId: z60.string().min(1).describe("R2 access key ID"),
25571
- r2SecretAccessKey: z60.string().min(1).describe("R2 secret access key")
25810
+ r2Bucket: z61.string().min(1).describe("R2 bucket name"),
25811
+ r2Endpoint: z61.string().min(1).describe("R2 endpoint URL"),
25812
+ r2AccessKeyId: z61.string().min(1).describe("R2 access key ID"),
25813
+ r2SecretAccessKey: z61.string().min(1).describe("R2 secret access key")
25572
25814
  }),
25573
- z60.object({
25574
- action: z60.literal("restore"),
25575
- databaseUrl: z60.string().min(1).describe("Target Postgres DATABASE_URL for restore"),
25576
- backupKey: z60.string().min(1).describe("R2 object key to restore from"),
25577
- encryptionKeyB64: z60.string().min(1).max(4096).optional().describe(
25815
+ z61.object({
25816
+ action: z61.literal("restore"),
25817
+ databaseUrl: z61.string().min(1).describe("Target Postgres DATABASE_URL for restore"),
25818
+ backupKey: z61.string().min(1).describe("R2 object key to restore from"),
25819
+ encryptionKeyB64: z61.string().min(1).max(4096).optional().describe(
25578
25820
  "Base64 AES-256 key (defaults to local master key if omitted)"
25579
25821
  ),
25580
- r2Bucket: z60.string().min(1).describe("R2 bucket name"),
25581
- r2Endpoint: z60.string().min(1).describe("R2 endpoint URL"),
25582
- r2AccessKeyId: z60.string().min(1).describe("R2 access key ID"),
25583
- r2SecretAccessKey: z60.string().min(1).describe("R2 secret access key")
25822
+ r2Bucket: z61.string().min(1).describe("R2 bucket name"),
25823
+ r2Endpoint: z61.string().min(1).describe("R2 endpoint URL"),
25824
+ r2AccessKeyId: z61.string().min(1).describe("R2 access key ID"),
25825
+ r2SecretAccessKey: z61.string().min(1).describe("R2 secret access key")
25584
25826
  }),
25585
- z60.object({
25586
- action: z60.literal("list"),
25587
- r2Bucket: z60.string().min(1).describe("R2 bucket name"),
25588
- r2Endpoint: z60.string().min(1).describe("R2 endpoint URL"),
25589
- r2AccessKeyId: z60.string().min(1).describe("R2 access key ID"),
25590
- r2SecretAccessKey: z60.string().min(1).describe("R2 secret access key")
25827
+ z61.object({
25828
+ action: z61.literal("list"),
25829
+ r2Bucket: z61.string().min(1).describe("R2 bucket name"),
25830
+ r2Endpoint: z61.string().min(1).describe("R2 endpoint URL"),
25831
+ r2AccessKeyId: z61.string().min(1).describe("R2 access key ID"),
25832
+ r2SecretAccessKey: z61.string().min(1).describe("R2 secret access key")
25591
25833
  }),
25592
- z60.object({
25593
- action: z60.literal("health"),
25594
- r2Bucket: z60.string().min(1).describe("R2 bucket name"),
25595
- r2Endpoint: z60.string().min(1).describe("R2 endpoint URL"),
25596
- r2AccessKeyId: z60.string().min(1).describe("R2 access key ID"),
25597
- r2SecretAccessKey: z60.string().min(1).describe("R2 secret access key")
25834
+ z61.object({
25835
+ action: z61.literal("health"),
25836
+ r2Bucket: z61.string().min(1).describe("R2 bucket name"),
25837
+ r2Endpoint: z61.string().min(1).describe("R2 endpoint URL"),
25838
+ r2AccessKeyId: z61.string().min(1).describe("R2 access key ID"),
25839
+ r2SecretAccessKey: z61.string().min(1).describe("R2 secret access key")
25598
25840
  })
25599
25841
  ])
25600
25842
  },
@@ -25788,9 +26030,9 @@ var init_hostinger_api = __esm({
25788
26030
  }
25789
26031
  this.lastRequestTime = Date.now();
25790
26032
  }
25791
- async request(method, path58, body) {
26033
+ async request(method, path60, body) {
25792
26034
  await this.rateLimit();
25793
- const url = `${this.baseUrl}${path58}`;
26035
+ const url = `${this.baseUrl}${path60}`;
25794
26036
  const headers = {
25795
26037
  Authorization: `Bearer ${this.apiKey}`,
25796
26038
  "Content-Type": "application/json",
@@ -25859,8 +26101,8 @@ async function requestCloudflare(cfApiToken, zoneId, options) {
25859
26101
  }
25860
26102
  return envelope.result;
25861
26103
  }
25862
- function buildUrl(zoneId, path58 = "/dns_records", query) {
25863
- const normalizedPath = path58.startsWith("/") ? path58 : `/${path58}`;
26104
+ function buildUrl(zoneId, path60 = "/dns_records", query) {
26105
+ const normalizedPath = path60.startsWith("/") ? path60 : `/${path60}`;
25864
26106
  const url = new URL(
25865
26107
  `${CLOUDFLARE_API_BASE_URL}/zones/${zoneId}${normalizedPath}`
25866
26108
  );
@@ -25931,11 +26173,11 @@ var init_cloudflare_dns = __esm({
25931
26173
  });
25932
26174
 
25933
26175
  // src/mcp/tools/deploy-client.ts
25934
- import { z as z61 } from "zod";
26176
+ import { z as z62 } from "zod";
25935
26177
  import { execFile } from "child_process";
25936
26178
  import { promisify } from "util";
25937
- import path40 from "path";
25938
- import { existsSync as existsSync35 } from "fs";
26179
+ import path42 from "path";
26180
+ import { existsSync as existsSync37 } from "fs";
25939
26181
  async function executeDeployment(params, client) {
25940
26182
  const {
25941
26183
  client_name,
@@ -26007,12 +26249,12 @@ function registerDeployClient(server) {
26007
26249
  title: "Deploy Client",
26008
26250
  description: "Provision a Hostinger VPS and deploy exe-os for a client. Creates VPS, waits for ready state, runs Ansible playbook, verifies health.",
26009
26251
  inputSchema: {
26010
- client_name: z61.string().min(1).describe("Client name (used for hostname and identification)"),
26011
- domain: z61.string().min(1).describe("Domain name for the deployment (e.g., client.exe.ai)"),
26012
- region: z61.string().default("jakarta").describe("VPS region (default: jakarta)"),
26013
- plan: z61.string().default("kvm-2").describe("Hostinger VPS plan (default: kvm-2)"),
26014
- ssl_email: z61.string().email().describe("Email for Let's Encrypt SSL certificate"),
26015
- user_id: z61.string().min(1).describe("User/customer ID for inventory tracking")
26252
+ client_name: z62.string().min(1).describe("Client name (used for hostname and identification)"),
26253
+ domain: z62.string().min(1).describe("Domain name for the deployment (e.g., client.exe.ai)"),
26254
+ region: z62.string().default("jakarta").describe("VPS region (default: jakarta)"),
26255
+ plan: z62.string().default("kvm-2").describe("Hostinger VPS plan (default: kvm-2)"),
26256
+ ssl_email: z62.string().email().describe("Email for Let's Encrypt SSL certificate"),
26257
+ user_id: z62.string().min(1).describe("User/customer ID for inventory tracking")
26016
26258
  }
26017
26259
  },
26018
26260
  async ({ client_name, domain, region, plan, ssl_email, user_id }) => {
@@ -26080,12 +26322,12 @@ async function waitForReady(client, vpsId) {
26080
26322
  }
26081
26323
  async function runAnsiblePlaybook(vpsIp, domain, sslEmail, clientName) {
26082
26324
  const safeClientName = clientName.replace(/[^a-zA-Z0-9_-]/g, "-");
26083
- const playbookDir = path40.resolve(process.cwd(), "infrastructure", "ansible");
26084
- const playbookPath = path40.join(playbookDir, "deploy.yml");
26085
- const inventoryPath = path40.join(playbookDir, "inventory", "hosts.yml");
26086
- const clientVarsPath = path40.join(playbookDir, "vars", `${safeClientName}.yml`);
26087
- const varsDir = path40.join(playbookDir, "vars");
26088
- if (!path40.resolve(clientVarsPath).startsWith(path40.resolve(varsDir))) {
26325
+ const playbookDir = path42.resolve(process.cwd(), "infrastructure", "ansible");
26326
+ const playbookPath = path42.join(playbookDir, "deploy.yml");
26327
+ const inventoryPath = path42.join(playbookDir, "inventory", "hosts.yml");
26328
+ const clientVarsPath = path42.join(playbookDir, "vars", `${safeClientName}.yml`);
26329
+ const varsDir = path42.join(playbookDir, "vars");
26330
+ if (!path42.resolve(clientVarsPath).startsWith(path42.resolve(varsDir))) {
26089
26331
  throw new Error(`Invalid client name for vars path: ${clientName}`);
26090
26332
  }
26091
26333
  const args = [
@@ -26101,7 +26343,7 @@ async function runAnsiblePlaybook(vpsIp, domain, sslEmail, clientName) {
26101
26343
  "-e",
26102
26344
  `client_name=${safeClientName}`
26103
26345
  ];
26104
- if (existsSync35(clientVarsPath)) {
26346
+ if (existsSync37(clientVarsPath)) {
26105
26347
  args.push("-e", `@${clientVarsPath}`);
26106
26348
  }
26107
26349
  try {
@@ -26191,7 +26433,7 @@ var init_deploy_client = __esm({
26191
26433
  });
26192
26434
 
26193
26435
  // src/mcp/tools/get-license-status.ts
26194
- import { z as z62 } from "zod";
26436
+ import { z as z63 } from "zod";
26195
26437
  function registerGetLicenseStatus(server) {
26196
26438
  server.registerTool(
26197
26439
  "get_license_status",
@@ -26199,7 +26441,7 @@ function registerGetLicenseStatus(server) {
26199
26441
  title: "Get License Status",
26200
26442
  description: "Get current license status: plan, validity, feature gates, limits, and expiry.",
26201
26443
  inputSchema: {
26202
- _dummy: z62.string().optional().describe("Unused \u2014 no input required")
26444
+ _dummy: z63.string().optional().describe("Unused \u2014 no input required")
26203
26445
  }
26204
26446
  },
26205
26447
  async () => {
@@ -26265,11 +26507,11 @@ var init_get_license_status = __esm({
26265
26507
 
26266
26508
  // src/mcp/tools/create-license.ts
26267
26509
  import os17 from "os";
26268
- import path41 from "path";
26510
+ import path43 from "path";
26269
26511
  import { randomBytes as randomBytes2, randomUUID as randomUUID6 } from "crypto";
26270
26512
  import { createRequire as createRequire4 } from "module";
26271
26513
  import { pathToFileURL as pathToFileURL4 } from "url";
26272
- import { z as z63 } from "zod";
26514
+ import { z as z64 } from "zod";
26273
26515
  function loadPrisma2() {
26274
26516
  if (!prismaPromise2) {
26275
26517
  prismaPromise2 = (async () => {
@@ -26280,8 +26522,8 @@ function loadPrisma2() {
26280
26522
  if (!Ctor2) throw new Error(`No PrismaClient at ${explicitPath}`);
26281
26523
  return new Ctor2();
26282
26524
  }
26283
- const exeDbRoot = process.env.EXE_DB_ROOT ?? path41.join(os17.homedir(), "exe-db");
26284
- const req = createRequire4(path41.join(exeDbRoot, "package.json"));
26525
+ const exeDbRoot = process.env.EXE_DB_ROOT ?? path43.join(os17.homedir(), "exe-db");
26526
+ const req = createRequire4(path43.join(exeDbRoot, "package.json"));
26285
26527
  const entry = req.resolve("@prisma/client");
26286
26528
  const mod = await import(pathToFileURL4(entry).href);
26287
26529
  const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
@@ -26301,10 +26543,10 @@ function registerCreateLicense(server) {
26301
26543
  title: "Create License",
26302
26544
  description: "Generate an exe_sk_* license key for a user. Stores in billing.licenses. Returns the key to give to the customer.",
26303
26545
  inputSchema: {
26304
- email: z63.string().email().describe("Customer email address"),
26305
- name: z63.string().optional().describe("Customer name"),
26306
- plan: z63.enum(["free", "pro", "team", "agency", "enterprise"]).default("pro").describe("License plan tier"),
26307
- expires_in_days: z63.number().int().positive().default(365).describe("Days until expiration (default 365)")
26546
+ email: z64.string().email().describe("Customer email address"),
26547
+ name: z64.string().optional().describe("Customer name"),
26548
+ plan: z64.enum(["free", "pro", "team", "agency", "enterprise"]).default("pro").describe("License plan tier"),
26549
+ expires_in_days: z64.number().int().positive().default(365).describe("Days until expiration (default 365)")
26308
26550
  }
26309
26551
  },
26310
26552
  async ({ email, name, plan, expires_in_days }) => {
@@ -26364,10 +26606,10 @@ var init_create_license = __esm({
26364
26606
 
26365
26607
  // src/mcp/tools/list-licenses.ts
26366
26608
  import os18 from "os";
26367
- import path42 from "path";
26609
+ import path44 from "path";
26368
26610
  import { createRequire as createRequire5 } from "module";
26369
26611
  import { pathToFileURL as pathToFileURL5 } from "url";
26370
- import { z as z64 } from "zod";
26612
+ import { z as z65 } from "zod";
26371
26613
  function loadPrisma3() {
26372
26614
  if (!prismaPromise3) {
26373
26615
  prismaPromise3 = (async () => {
@@ -26378,8 +26620,8 @@ function loadPrisma3() {
26378
26620
  if (!Ctor2) throw new Error(`No PrismaClient at ${explicitPath}`);
26379
26621
  return new Ctor2();
26380
26622
  }
26381
- const exeDbRoot = process.env.EXE_DB_ROOT ?? path42.join(os18.homedir(), "exe-db");
26382
- const req = createRequire5(path42.join(exeDbRoot, "package.json"));
26623
+ const exeDbRoot = process.env.EXE_DB_ROOT ?? path44.join(os18.homedir(), "exe-db");
26624
+ const req = createRequire5(path44.join(exeDbRoot, "package.json"));
26383
26625
  const entry = req.resolve("@prisma/client");
26384
26626
  const mod = await import(pathToFileURL5(entry).href);
26385
26627
  const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
@@ -26396,7 +26638,7 @@ function registerListLicenses(server) {
26396
26638
  title: "List Licenses",
26397
26639
  description: "List all issued licenses with status (active/expired/revoked). Optionally filter by plan.",
26398
26640
  inputSchema: {
26399
- plan: z64.enum(["free", "pro", "team", "agency", "enterprise"]).optional().describe("Filter by plan tier (omit for all)")
26641
+ plan: z65.enum(["free", "pro", "team", "agency", "enterprise"]).optional().describe("Filter by plan tier (omit for all)")
26400
26642
  }
26401
26643
  },
26402
26644
  async ({ plan }) => {
@@ -26453,7 +26695,7 @@ var init_list_licenses = __esm({
26453
26695
  });
26454
26696
 
26455
26697
  // src/mcp/tools/activate-license.ts
26456
- import { z as z65 } from "zod";
26698
+ import { z as z66 } from "zod";
26457
26699
  function registerActivateLicense(server) {
26458
26700
  server.registerTool(
26459
26701
  "activate_license",
@@ -26461,7 +26703,7 @@ function registerActivateLicense(server) {
26461
26703
  title: "Activate License",
26462
26704
  description: "Activate an exe_sk_* license key on this device. Writes to ~/.exe-os/license.key, validates against Postgres, and caches the result.",
26463
26705
  inputSchema: {
26464
- key: z65.string().startsWith("exe_sk_").describe("License key (exe_sk_*)")
26706
+ key: z66.string().startsWith("exe_sk_").describe("License key (exe_sk_*)")
26465
26707
  }
26466
26708
  },
26467
26709
  async ({ key }) => {
@@ -26513,14 +26755,14 @@ var init_activate_license = __esm({
26513
26755
  });
26514
26756
 
26515
26757
  // src/automation/trigger-engine.ts
26516
- import { readFileSync as readFileSync27, writeFileSync as writeFileSync19, existsSync as existsSync36, mkdirSync as mkdirSync16 } from "fs";
26758
+ import { readFileSync as readFileSync29, writeFileSync as writeFileSync20, existsSync as existsSync38, mkdirSync as mkdirSync17 } from "fs";
26517
26759
  import { randomUUID as randomUUID7 } from "crypto";
26518
- import path43 from "path";
26760
+ import path45 from "path";
26519
26761
  import os19 from "os";
26520
26762
  function loadTriggers(project) {
26521
- if (!existsSync36(TRIGGERS_PATH)) return [];
26763
+ if (!existsSync38(TRIGGERS_PATH)) return [];
26522
26764
  try {
26523
- const raw = readFileSync27(TRIGGERS_PATH, "utf-8");
26765
+ const raw = readFileSync29(TRIGGERS_PATH, "utf-8");
26524
26766
  const all = JSON.parse(raw);
26525
26767
  if (!Array.isArray(all)) return [];
26526
26768
  if (project) {
@@ -26532,9 +26774,9 @@ function loadTriggers(project) {
26532
26774
  }
26533
26775
  }
26534
26776
  function saveTriggers(triggers) {
26535
- const dir = path43.dirname(TRIGGERS_PATH);
26536
- if (!existsSync36(dir)) mkdirSync16(dir, { recursive: true });
26537
- writeFileSync19(TRIGGERS_PATH, JSON.stringify(triggers, null, 2), "utf-8");
26777
+ const dir = path45.dirname(TRIGGERS_PATH);
26778
+ if (!existsSync38(dir)) mkdirSync17(dir, { recursive: true });
26779
+ writeFileSync20(TRIGGERS_PATH, JSON.stringify(triggers, null, 2), "utf-8");
26538
26780
  }
26539
26781
  function createNewTrigger(input) {
26540
26782
  const triggers = loadTriggers();
@@ -26553,7 +26795,7 @@ var TRIGGERS_PATH;
26553
26795
  var init_trigger_engine = __esm({
26554
26796
  "src/automation/trigger-engine.ts"() {
26555
26797
  "use strict";
26556
- TRIGGERS_PATH = path43.join(os19.homedir(), ".exe-os", "triggers.json");
26798
+ TRIGGERS_PATH = path45.join(os19.homedir(), ".exe-os", "triggers.json");
26557
26799
  }
26558
26800
  });
26559
26801
 
@@ -26703,7 +26945,7 @@ var init_schedules = __esm({
26703
26945
  });
26704
26946
 
26705
26947
  // src/mcp/tools/create-trigger.ts
26706
- import { z as z66 } from "zod";
26948
+ import { z as z67 } from "zod";
26707
26949
  function registerCreateTrigger(server) {
26708
26950
  server.registerTool(
26709
26951
  "create_trigger",
@@ -26711,18 +26953,18 @@ function registerCreateTrigger(server) {
26711
26953
  title: "Create Trigger",
26712
26954
  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.).",
26713
26955
  inputSchema: {
26714
- name: z66.string().describe("Human-readable trigger name"),
26715
- event: z66.string().describe(
26956
+ name: z67.string().describe("Human-readable trigger name"),
26957
+ event: z67.string().describe(
26716
26958
  'CRM event to match, e.g., "Deal.updated", "Order.created", "*" for all'
26717
26959
  ),
26718
- conditions: z66.array(conditionSchema).default([]).describe("Conditions that must all match (AND logic)"),
26719
- actions: z66.array(actionSchema).min(1).describe("Actions to execute when trigger fires"),
26720
- project: z66.string().optional().describe("Scope trigger to a specific project"),
26721
- enabled: z66.boolean().default(true).describe("Whether trigger is active"),
26722
- schedule: z66.string().optional().describe(
26960
+ conditions: z67.array(conditionSchema).default([]).describe("Conditions that must all match (AND logic)"),
26961
+ actions: z67.array(actionSchema).min(1).describe("Actions to execute when trigger fires"),
26962
+ project: z67.string().optional().describe("Scope trigger to a specific project"),
26963
+ enabled: z67.boolean().default(true).describe("Whether trigger is active"),
26964
+ schedule: z67.string().optional().describe(
26723
26965
  'Cron schedule for time-based triggers, e.g., "0 9 * * *" or "Monday 9am"'
26724
26966
  ),
26725
- query: z66.string().optional().describe(
26967
+ query: z67.string().optional().describe(
26726
26968
  "CRM GraphQL query to run on schedule (required if schedule is set)"
26727
26969
  )
26728
26970
  }
@@ -26799,14 +27041,14 @@ var init_create_trigger = __esm({
26799
27041
  "use strict";
26800
27042
  init_trigger_engine();
26801
27043
  init_schedules();
26802
- conditionSchema = z66.object({
26803
- field: z66.string().describe("Dot-path field to evaluate, e.g., 'stage' or 'amount'"),
26804
- op: z66.enum(["eq", "neq", "gt", "lt", "gte", "lte", "contains", "not_contains"]).describe("Comparison operator"),
26805
- value: z66.string().or(z66.number()).or(z66.boolean()).describe("Value to compare against")
27044
+ conditionSchema = z67.object({
27045
+ field: z67.string().describe("Dot-path field to evaluate, e.g., 'stage' or 'amount'"),
27046
+ op: z67.enum(["eq", "neq", "gt", "lt", "gte", "lte", "contains", "not_contains"]).describe("Comparison operator"),
27047
+ value: z67.string().or(z67.number()).or(z67.boolean()).describe("Value to compare against")
26806
27048
  });
26807
- actionSchema = z66.object({
26808
- type: z66.enum(["send_whatsapp", "send_message", "create_task", "mcp_tool"]).describe("Action type to execute"),
26809
- params: z66.record(z66.string(), z66.string()).describe(
27049
+ actionSchema = z67.object({
27050
+ type: z67.enum(["send_whatsapp", "send_message", "create_task", "mcp_tool"]).describe("Action type to execute"),
27051
+ params: z67.record(z67.string(), z67.string()).describe(
26810
27052
  "Action parameters. Supports {{record.field}} templates for dynamic values."
26811
27053
  )
26812
27054
  });
@@ -26814,7 +27056,7 @@ var init_create_trigger = __esm({
26814
27056
  });
26815
27057
 
26816
27058
  // src/mcp/tools/list-triggers.ts
26817
- import { z as z67 } from "zod";
27059
+ import { z as z68 } from "zod";
26818
27060
  function registerListTriggers(server) {
26819
27061
  server.registerTool(
26820
27062
  "list_triggers",
@@ -26822,7 +27064,7 @@ function registerListTriggers(server) {
26822
27064
  title: "List Triggers",
26823
27065
  description: "List configured CRM event triggers and scheduled automations.",
26824
27066
  inputSchema: {
26825
- project: z67.string().optional().describe("Filter triggers by project name")
27067
+ project: z68.string().optional().describe("Filter triggers by project name")
26826
27068
  }
26827
27069
  },
26828
27070
  async ({ project }) => {
@@ -26863,47 +27105,47 @@ var init_list_triggers = __esm({
26863
27105
  });
26864
27106
 
26865
27107
  // src/automation/starter-packs/index.ts
26866
- import { readFileSync as readFileSync28, readdirSync as readdirSync12, existsSync as existsSync37 } from "fs";
26867
- import path44 from "path";
26868
- import { fileURLToPath as fileURLToPath4 } from "url";
27108
+ import { readFileSync as readFileSync30, readdirSync as readdirSync12, existsSync as existsSync39 } from "fs";
27109
+ import path46 from "path";
27110
+ import { fileURLToPath as fileURLToPath5 } from "url";
26869
27111
  function listPacks() {
26870
- const packsDir = path44.join(__dirname, ".");
26871
- if (!existsSync37(packsDir)) return [];
27112
+ const packsDir = path46.join(__dirname, ".");
27113
+ if (!existsSync39(packsDir)) return [];
26872
27114
  return readdirSync12(packsDir, { withFileTypes: true }).filter(
26873
- (d) => d.isDirectory() && existsSync37(path44.join(packsDir, d.name, "custom-objects.json"))
27115
+ (d) => d.isDirectory() && existsSync39(path46.join(packsDir, d.name, "custom-objects.json"))
26874
27116
  ).map((d) => d.name);
26875
27117
  }
26876
27118
  function loadPack(industry) {
26877
- const packDir = path44.join(__dirname, industry);
26878
- const objectsPath = path44.join(packDir, "custom-objects.json");
26879
- const triggersPath = path44.join(packDir, "triggers.json");
26880
- const wikiDir = path44.join(packDir, "wiki-seeds");
26881
- const manifestPath = path44.join(packDir, "pack.json");
26882
- const identityContextPath = path44.join(packDir, "identity-context.md");
26883
- if (!existsSync37(objectsPath)) return null;
27119
+ const packDir = path46.join(__dirname, industry);
27120
+ const objectsPath = path46.join(packDir, "custom-objects.json");
27121
+ const triggersPath = path46.join(packDir, "triggers.json");
27122
+ const wikiDir = path46.join(packDir, "wiki-seeds");
27123
+ const manifestPath = path46.join(packDir, "pack.json");
27124
+ const identityContextPath = path46.join(packDir, "identity-context.md");
27125
+ if (!existsSync39(objectsPath)) return null;
26884
27126
  let customObjects = [];
26885
27127
  try {
26886
27128
  customObjects = JSON.parse(
26887
- readFileSync28(objectsPath, "utf-8")
27129
+ readFileSync30(objectsPath, "utf-8")
26888
27130
  );
26889
27131
  } catch {
26890
27132
  customObjects = [];
26891
27133
  }
26892
27134
  let triggers = [];
26893
- if (existsSync37(triggersPath)) {
27135
+ if (existsSync39(triggersPath)) {
26894
27136
  try {
26895
27137
  triggers = JSON.parse(
26896
- readFileSync28(triggersPath, "utf-8")
27138
+ readFileSync30(triggersPath, "utf-8")
26897
27139
  );
26898
27140
  } catch {
26899
27141
  triggers = [];
26900
27142
  }
26901
27143
  }
26902
27144
  const wikiSeeds = [];
26903
- if (existsSync37(wikiDir)) {
27145
+ if (existsSync39(wikiDir)) {
26904
27146
  const files = readdirSync12(wikiDir).filter((f) => f.endsWith(".md"));
26905
27147
  for (const file of files) {
26906
- const content = readFileSync28(path44.join(wikiDir, file), "utf-8");
27148
+ const content = readFileSync30(path46.join(wikiDir, file), "utf-8");
26907
27149
  const titleMatch = content.match(/^#\s+(.+)/m);
26908
27150
  wikiSeeds.push({
26909
27151
  filename: file,
@@ -26913,17 +27155,17 @@ function loadPack(industry) {
26913
27155
  }
26914
27156
  }
26915
27157
  let manifest = {};
26916
- if (existsSync37(manifestPath)) {
27158
+ if (existsSync39(manifestPath)) {
26917
27159
  try {
26918
- manifest = JSON.parse(readFileSync28(manifestPath, "utf-8"));
27160
+ manifest = JSON.parse(readFileSync30(manifestPath, "utf-8"));
26919
27161
  } catch {
26920
27162
  manifest = {};
26921
27163
  }
26922
27164
  }
26923
27165
  let identityContext = null;
26924
- if (existsSync37(identityContextPath)) {
27166
+ if (existsSync39(identityContextPath)) {
26925
27167
  try {
26926
- identityContext = readFileSync28(identityContextPath, "utf-8");
27168
+ identityContext = readFileSync30(identityContextPath, "utf-8");
26927
27169
  } catch {
26928
27170
  identityContext = null;
26929
27171
  }
@@ -26982,7 +27224,7 @@ var init_starter_packs = __esm({
26982
27224
  "src/automation/starter-packs/index.ts"() {
26983
27225
  "use strict";
26984
27226
  init_trigger_engine();
26985
- __dirname = path44.dirname(fileURLToPath4(import.meta.url));
27227
+ __dirname = path46.dirname(fileURLToPath5(import.meta.url));
26986
27228
  }
26987
27229
  });
26988
27230
 
@@ -27114,21 +27356,21 @@ All memory, tasks, behaviors, documents, and wiki content belonging to {{company
27114
27356
  });
27115
27357
 
27116
27358
  // src/lib/client-coo.ts
27117
- import { existsSync as existsSync38, mkdirSync as mkdirSync17, writeFileSync as writeFileSync20 } from "fs";
27118
- import path45 from "path";
27359
+ import { existsSync as existsSync40, mkdirSync as mkdirSync18, writeFileSync as writeFileSync21 } from "fs";
27360
+ import path47 from "path";
27119
27361
  async function provisionClientCOO(vars, opts = {}) {
27120
- const identityDir = opts.identityDir ?? path45.join(EXE_AI_DIR, "identity");
27362
+ const identityDir = opts.identityDir ?? path47.join(EXE_AI_DIR, "identity");
27121
27363
  const rosterPath = opts.employeesPath ?? EMPLOYEES_PATH;
27122
27364
  const storeFeedbackBehavior = opts.storeFeedbackBehavior ?? true;
27123
- const identityPath2 = path45.join(identityDir, `${vars.agent_name}.md`);
27124
- if (existsSync38(identityPath2)) {
27365
+ const identityPath2 = path47.join(identityDir, `${vars.agent_name}.md`);
27366
+ if (existsSync40(identityPath2)) {
27125
27367
  throw new ClientCOOClobberError(vars.agent_name, identityPath2);
27126
27368
  }
27127
27369
  const body = renderClientCOOTemplate(vars);
27128
- if (!existsSync38(identityDir)) {
27129
- mkdirSync17(identityDir, { recursive: true });
27370
+ if (!existsSync40(identityDir)) {
27371
+ mkdirSync18(identityDir, { recursive: true });
27130
27372
  }
27131
- writeFileSync20(identityPath2, body, "utf-8");
27373
+ writeFileSync21(identityPath2, body, "utf-8");
27132
27374
  const employees = await loadEmployees(rosterPath);
27133
27375
  const existing = employees.find((e) => e.name === vars.agent_name);
27134
27376
  let addedToRoster = false;
@@ -27180,7 +27422,7 @@ var init_client_coo = __esm({
27180
27422
  });
27181
27423
 
27182
27424
  // src/mcp/tools/apply-starter-pack.ts
27183
- import { z as z68 } from "zod";
27425
+ import { z as z69 } from "zod";
27184
27426
  function registerApplyStarterPack(server) {
27185
27427
  server.registerTool(
27186
27428
  "apply_starter_pack",
@@ -27188,17 +27430,17 @@ function registerApplyStarterPack(server) {
27188
27430
  title: "Apply Starter Pack",
27189
27431
  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.",
27190
27432
  inputSchema: {
27191
- industry: z68.string().describe(
27433
+ industry: z69.string().describe(
27192
27434
  'Industry pack to apply (e.g., "distribution"). Use without args to list available packs.'
27193
27435
  ),
27194
- project: z68.string().describe("Project name to scope the triggers to"),
27195
- agent_name: z68.string().optional().describe(
27436
+ project: z69.string().describe("Project name to scope the triggers to"),
27437
+ agent_name: z69.string().optional().describe(
27196
27438
  "Optional. Lowercase alphanumeric name for the Client COO agent. Required (alongside company_name and founder_name) to provision a COO."
27197
27439
  ),
27198
- company_name: z68.string().optional().describe(
27440
+ company_name: z69.string().optional().describe(
27199
27441
  "Optional. The client company the COO serves. Required to provision a COO."
27200
27442
  ),
27201
- founder_name: z68.string().optional().describe(
27443
+ founder_name: z69.string().optional().describe(
27202
27444
  "Optional. The founder the COO reports to. Required to provision a COO."
27203
27445
  )
27204
27446
  }
@@ -27350,19 +27592,19 @@ var init_apply_starter_pack = __esm({
27350
27592
  });
27351
27593
 
27352
27594
  // src/mcp/tools/load-skill.ts
27353
- import { z as z69 } from "zod";
27354
- import { readFileSync as readFileSync29, readdirSync as readdirSync13, statSync as statSync8 } from "fs";
27355
- import path46 from "path";
27356
- import { homedir as homedir7 } from "os";
27595
+ import { z as z70 } from "zod";
27596
+ import { readFileSync as readFileSync31, readdirSync as readdirSync13, statSync as statSync9 } from "fs";
27597
+ import path48 from "path";
27598
+ import { homedir as homedir8 } from "os";
27357
27599
  function listAvailableSkills() {
27358
27600
  try {
27359
27601
  const entries = readdirSync13(SKILLS_DIR);
27360
27602
  return entries.filter((entry) => {
27361
27603
  try {
27362
- const entryPath = path46.join(SKILLS_DIR, entry);
27363
- if (!statSync8(entryPath).isDirectory()) return false;
27364
- const skillFile = path46.join(entryPath, "SKILL.md");
27365
- statSync8(skillFile);
27604
+ const entryPath = path48.join(SKILLS_DIR, entry);
27605
+ if (!statSync9(entryPath).isDirectory()) return false;
27606
+ const skillFile = path48.join(entryPath, "SKILL.md");
27607
+ statSync9(skillFile);
27366
27608
  return true;
27367
27609
  } catch {
27368
27610
  return false;
@@ -27379,7 +27621,7 @@ function registerLoadSkill(server) {
27379
27621
  title: "Load Skill",
27380
27622
  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.",
27381
27623
  inputSchema: {
27382
- skill_name: z69.string().describe(
27624
+ skill_name: z70.string().describe(
27383
27625
  "Skill to load (e.g. 'seo', 'code-reviewer', 'frontend-design'). Pass 'list' to see all available skills."
27384
27626
  )
27385
27627
  }
@@ -27404,10 +27646,10 @@ ${skills.map((s) => `- ${s}`).join("\n")}`
27404
27646
  }]
27405
27647
  };
27406
27648
  }
27407
- const sanitized = path46.basename(skill_name);
27408
- const skillFile = path46.join(SKILLS_DIR, sanitized, "SKILL.md");
27649
+ const sanitized = path48.basename(skill_name);
27650
+ const skillFile = path48.join(SKILLS_DIR, sanitized, "SKILL.md");
27409
27651
  try {
27410
- const content = readFileSync29(skillFile, "utf-8");
27652
+ const content = readFileSync31(skillFile, "utf-8");
27411
27653
  return {
27412
27654
  content: [{
27413
27655
  type: "text",
@@ -27436,15 +27678,15 @@ var SKILLS_DIR;
27436
27678
  var init_load_skill = __esm({
27437
27679
  "src/mcp/tools/load-skill.ts"() {
27438
27680
  "use strict";
27439
- SKILLS_DIR = path46.join(homedir7(), ".claude", "skills");
27681
+ SKILLS_DIR = path48.join(homedir8(), ".claude", "skills");
27440
27682
  }
27441
27683
  });
27442
27684
 
27443
27685
  // src/lib/orchestration-package.ts
27444
27686
  import { randomUUID as randomUUID8 } from "crypto";
27445
- import { copyFileSync as copyFileSync2, existsSync as existsSync39, mkdirSync as mkdirSync18, readFileSync as readFileSync30, writeFileSync as writeFileSync21 } from "fs";
27687
+ import { copyFileSync as copyFileSync2, existsSync as existsSync41, mkdirSync as mkdirSync19, readFileSync as readFileSync32, writeFileSync as writeFileSync22 } from "fs";
27446
27688
  import os20 from "os";
27447
- import path47 from "path";
27689
+ import path49 from "path";
27448
27690
  function ensureObject(value, label) {
27449
27691
  if (value == null || Array.isArray(value) || typeof value !== "object") {
27450
27692
  throw new Error(`${label} must be an object`);
@@ -27503,15 +27745,15 @@ function validateProcedureEntry(value, index) {
27503
27745
  };
27504
27746
  }
27505
27747
  function getRosterPath() {
27506
- return path47.join(os20.homedir(), EXE_OS_DIRNAME, ROSTER_FILENAME);
27748
+ return path49.join(os20.homedir(), EXE_OS_DIRNAME, ROSTER_FILENAME);
27507
27749
  }
27508
27750
  function getBackupPath() {
27509
- return path47.join(os20.homedir(), EXE_OS_DIRNAME, ROSTER_BACKUP_FILENAME);
27751
+ return path49.join(os20.homedir(), EXE_OS_DIRNAME, ROSTER_BACKUP_FILENAME);
27510
27752
  }
27511
27753
  function readRosterFile() {
27512
27754
  const rosterPath = getRosterPath();
27513
- if (!existsSync39(rosterPath)) return [];
27514
- const raw = readFileSync30(rosterPath, "utf-8");
27755
+ if (!existsSync41(rosterPath)) return [];
27756
+ const raw = readFileSync32(rosterPath, "utf-8");
27515
27757
  const parsed = JSON.parse(raw);
27516
27758
  if (!Array.isArray(parsed)) {
27517
27759
  throw new Error("Roster file must contain a JSON array");
@@ -27523,8 +27765,8 @@ function writeRosterFile(roster) {
27523
27765
  throw new Error("Refusing to write empty roster \u2014 this would delete all employees");
27524
27766
  }
27525
27767
  const rosterPath = getRosterPath();
27526
- mkdirSync18(path47.dirname(rosterPath), { recursive: true });
27527
- if (existsSync39(rosterPath)) {
27768
+ mkdirSync19(path49.dirname(rosterPath), { recursive: true });
27769
+ if (existsSync41(rosterPath)) {
27528
27770
  const currentRoster = readRosterFile();
27529
27771
  if (roster.length < currentRoster.length) {
27530
27772
  throw new Error(
@@ -27533,7 +27775,7 @@ function writeRosterFile(roster) {
27533
27775
  }
27534
27776
  copyFileSync2(rosterPath, getBackupPath());
27535
27777
  }
27536
- writeFileSync21(rosterPath, `${JSON.stringify(roster, null, 2)}
27778
+ writeFileSync22(rosterPath, `${JSON.stringify(roster, null, 2)}
27537
27779
  `, "utf-8");
27538
27780
  }
27539
27781
  function buildImportedRosterEntries(roster, timestamp) {
@@ -27796,9 +28038,9 @@ var init_orchestration_package = __esm({
27796
28038
  });
27797
28039
 
27798
28040
  // src/mcp/tools/export-orchestration.ts
27799
- import { mkdirSync as mkdirSync19, writeFileSync as writeFileSync22 } from "fs";
27800
- import path48 from "path";
27801
- import { z as z70 } from "zod";
28041
+ import { mkdirSync as mkdirSync20, writeFileSync as writeFileSync23 } from "fs";
28042
+ import path50 from "path";
28043
+ import { z as z71 } from "zod";
27802
28044
  function registerExportOrchestration(server) {
27803
28045
  server.registerTool(
27804
28046
  "export_orchestration",
@@ -27806,15 +28048,15 @@ function registerExportOrchestration(server) {
27806
28048
  title: "Export Orchestration",
27807
28049
  description: "Export roster, identities, behaviors, and customer procedures to a JSON package.",
27808
28050
  inputSchema: {
27809
- output_path: z70.string().describe("File path to write the JSON package")
28051
+ output_path: z71.string().describe("File path to write the JSON package")
27810
28052
  }
27811
28053
  },
27812
28054
  async ({ output_path }) => {
27813
28055
  try {
27814
28056
  await initStore();
27815
28057
  const pkg = await exportOrchestration(getActiveAgent().agentId);
27816
- mkdirSync19(path48.dirname(output_path), { recursive: true });
27817
- writeFileSync22(output_path, `${JSON.stringify(pkg, null, 2)}
28058
+ mkdirSync20(path50.dirname(output_path), { recursive: true });
28059
+ writeFileSync23(output_path, `${JSON.stringify(pkg, null, 2)}
27818
28060
  `, "utf-8");
27819
28061
  return {
27820
28062
  content: [{
@@ -27844,8 +28086,8 @@ var init_export_orchestration = __esm({
27844
28086
  });
27845
28087
 
27846
28088
  // src/mcp/tools/import-orchestration.ts
27847
- import { readFileSync as readFileSync31 } from "fs";
27848
- import { z as z71 } from "zod";
28089
+ import { readFileSync as readFileSync33 } from "fs";
28090
+ import { z as z72 } from "zod";
27849
28091
  function registerImportOrchestration(server) {
27850
28092
  server.registerTool(
27851
28093
  "import_orchestration",
@@ -27853,8 +28095,8 @@ function registerImportOrchestration(server) {
27853
28095
  title: "Import Orchestration",
27854
28096
  description: "Import roster, identities, behaviors, and procedures from an orchestration package. Restricted to coordinator/founder.",
27855
28097
  inputSchema: {
27856
- package_path: z71.string().describe("Path to the orchestration package JSON file"),
27857
- 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")
28098
+ package_path: z72.string().describe("Path to the orchestration package JSON file"),
28099
+ 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")
27858
28100
  }
27859
28101
  },
27860
28102
  async ({ package_path, merge_strategy }) => {
@@ -27871,7 +28113,7 @@ function registerImportOrchestration(server) {
27871
28113
  };
27872
28114
  }
27873
28115
  await initStore();
27874
- const raw = readFileSync31(package_path, "utf-8");
28116
+ const raw = readFileSync33(package_path, "utf-8");
27875
28117
  const pkg = validatePackage(JSON.parse(raw));
27876
28118
  const result2 = await importOrchestration(pkg, merge_strategy);
27877
28119
  return {
@@ -27903,7 +28145,7 @@ var init_import_orchestration = __esm({
27903
28145
  });
27904
28146
 
27905
28147
  // src/mcp/tools/global-procedure.ts
27906
- import { z as z72 } from "zod";
28148
+ import { z as z73 } from "zod";
27907
28149
  function registerCompanyProcedureTool(server, toolName) {
27908
28150
  server.registerTool(
27909
28151
  toolName,
@@ -27911,12 +28153,12 @@ function registerCompanyProcedureTool(server, toolName) {
27911
28153
  title: "Company Procedure",
27912
28154
  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).",
27913
28155
  inputSchema: {
27914
- action: z72.enum(["store", "list", "deactivate"]).describe("Action to perform"),
27915
- title: z72.string().optional().describe("Short title for the procedure (store)"),
27916
- content: z72.string().max(500).optional().describe("The procedure content \u2014 clear, actionable instruction (store)"),
27917
- priority: z72.enum(["p0", "p1", "p2"]).optional().describe("Priority tier. p0 = always (default). p1 = standard. p2 = nice-to-have."),
27918
- domain: z72.string().optional().describe("Category: workflow, code-style, communication, architecture, testing, security"),
27919
- procedure_id: z72.string().optional().describe("UUID of the company procedure (deactivate)")
28156
+ action: z73.enum(["store", "list", "deactivate"]).describe("Action to perform"),
28157
+ title: z73.string().optional().describe("Short title for the procedure (store)"),
28158
+ content: z73.string().max(500).optional().describe("The procedure content \u2014 clear, actionable instruction (store)"),
28159
+ priority: z73.enum(["p0", "p1", "p2"]).optional().describe("Priority tier. p0 = always (default). p1 = standard. p2 = nice-to-have."),
28160
+ domain: z73.string().optional().describe("Category: workflow, code-style, communication, architecture, testing, security"),
28161
+ procedure_id: z73.string().optional().describe("UUID of the company procedure (deactivate)")
27920
28162
  }
27921
28163
  },
27922
28164
  async ({ action, title, content, priority, domain, procedure_id }) => {
@@ -28047,7 +28289,7 @@ var init_global_procedure = __esm({
28047
28289
  });
28048
28290
 
28049
28291
  // src/mcp/tools/config.ts
28050
- import { z as z73 } from "zod";
28292
+ import { z as z74 } from "zod";
28051
28293
  function errorResult8(text3) {
28052
28294
  return { content: [{ type: "text", text: text3 }], isError: true };
28053
28295
  }
@@ -28064,6 +28306,7 @@ function buildHandlers5() {
28064
28306
  registerListAgentSessions(localServer);
28065
28307
  registerGetSessionKills(localServer);
28066
28308
  registerGetDaemonHealth(localServer);
28309
+ registerMcpPing(localServer);
28067
28310
  registerGetAutoWakeStatus(localServer);
28068
28311
  registerGetWorkerGate(localServer);
28069
28312
  registerRunMemoryAudit(localServer);
@@ -28092,44 +28335,44 @@ function registerConfig(server) {
28092
28335
  title: "Config",
28093
28336
  description: "Consolidated COO/admin tool for runtime config, system health, licensing, triggers, orchestration import/export, and company procedures.",
28094
28337
  inputSchema: {
28095
- action: z73.enum(Object.keys(ACTION_TO_TOOL2)).describe("Admin/config operation"),
28096
- agent_id: z73.string().optional().describe("Agent id for set_agent_config/agent_spend/session queries"),
28097
- runtime: z73.string().optional().describe("Runtime for set_agent_config"),
28098
- model: z73.string().optional().describe("Model for set_agent_config"),
28099
- reasoning_effort: z73.string().optional().describe("Reasoning effort for Codex agents"),
28100
- dry_run: z73.boolean().optional().describe("Preview without applying where supported"),
28101
- fix: z73.boolean().optional().describe("Apply fixes for memory_audit where supported"),
28102
- verbose: z73.boolean().optional().describe("Verbose output where supported"),
28103
- project_name: z73.string().optional().describe("Project filter/name"),
28104
- since: z73.string().optional().describe("ISO lower-bound timestamp"),
28105
- limit: z73.coerce.number().optional().describe("Result limit"),
28106
- output_path: z73.string().optional().describe("Output path for export/backup"),
28107
- input_path: z73.string().optional().describe("Input path for import_orchestration"),
28108
- strategy: z73.enum(["merge", "replace"]).optional().describe("Import strategy; replace must still be additive-only per platform rules"),
28109
- license_key: z73.string().optional().describe("License key for activation/status"),
28110
- email: z73.string().optional().describe("Customer email for license creation"),
28111
- plan: z73.string().optional().describe("License plan"),
28112
- name: z73.string().optional().describe("Trigger/starter pack/procedure/client name"),
28113
- event: z73.string().optional().describe("Trigger event"),
28114
- conditions: z73.array(z73.record(z73.string(), z73.unknown())).optional().describe("Trigger conditions"),
28115
- actions: z73.array(z73.record(z73.string(), z73.unknown())).optional().describe("Trigger actions"),
28116
- enabled: z73.boolean().optional().describe("Trigger enabled flag"),
28117
- schedule: z73.string().optional().describe("Trigger schedule"),
28118
- query: z73.string().optional().describe("Trigger query or filter"),
28119
- skill_name: z73.string().optional().describe("Skill name for load_skill"),
28120
- pack_name: z73.string().optional().describe("Starter pack name"),
28121
- title: z73.string().optional().describe("Procedure title"),
28122
- content: z73.string().optional().describe("Procedure content"),
28123
- priority: z73.enum(["p0", "p1", "p2"]).optional().describe("Procedure priority"),
28124
- domain: z73.string().optional().describe("Procedure domain"),
28125
- procedure_id: z73.string().optional().describe("Procedure id for deactivate"),
28126
- subaction: z73.enum(["store", "list", "deactivate"]).optional().describe("Nested action for company_procedure/global_procedure"),
28127
- max_clusters: z73.coerce.number().optional().describe("Consolidation max clusters"),
28128
- force: z73.boolean().optional().describe("Force operation where supported"),
28129
- cloud_action: z73.enum(["status", "sync", "reupload"]).optional().describe("Nested operation for action=cloud_sync"),
28130
- confirm_local_db_source_of_truth: z73.string().optional().describe("Required for cloud_action=reupload; must exactly equal LOCAL DB IS SOURCE OF TRUTH"),
28131
- domain_name: z73.string().optional().describe("Client deployment domain"),
28132
- phase: z73.enum(["phase_1_coo", "phase_2_executives", "phase_3_parallel_org", "1", "2", "3"]).optional().describe("Orchestration phase for orchestration_phase action")
28338
+ action: z74.enum(Object.keys(ACTION_TO_TOOL2)).describe("Admin/config operation"),
28339
+ agent_id: z74.string().optional().describe("Agent id for set_agent_config/agent_spend/session queries"),
28340
+ runtime: z74.string().optional().describe("Runtime for set_agent_config"),
28341
+ model: z74.string().optional().describe("Model for set_agent_config"),
28342
+ reasoning_effort: z74.string().optional().describe("Reasoning effort for Codex agents"),
28343
+ dry_run: z74.boolean().optional().describe("Preview without applying where supported"),
28344
+ fix: z74.boolean().optional().describe("Apply fixes for memory_audit where supported"),
28345
+ verbose: z74.boolean().optional().describe("Verbose output where supported"),
28346
+ project_name: z74.string().optional().describe("Project filter/name"),
28347
+ since: z74.string().optional().describe("ISO lower-bound timestamp"),
28348
+ limit: z74.coerce.number().optional().describe("Result limit"),
28349
+ output_path: z74.string().optional().describe("Output path for export/backup"),
28350
+ input_path: z74.string().optional().describe("Input path for import_orchestration"),
28351
+ strategy: z74.enum(["merge", "replace"]).optional().describe("Import strategy; replace must still be additive-only per platform rules"),
28352
+ license_key: z74.string().optional().describe("License key for activation/status"),
28353
+ email: z74.string().optional().describe("Customer email for license creation"),
28354
+ plan: z74.string().optional().describe("License plan"),
28355
+ name: z74.string().optional().describe("Trigger/starter pack/procedure/client name"),
28356
+ event: z74.string().optional().describe("Trigger event"),
28357
+ conditions: z74.array(z74.record(z74.string(), z74.unknown())).optional().describe("Trigger conditions"),
28358
+ actions: z74.array(z74.record(z74.string(), z74.unknown())).optional().describe("Trigger actions"),
28359
+ enabled: z74.boolean().optional().describe("Trigger enabled flag"),
28360
+ schedule: z74.string().optional().describe("Trigger schedule"),
28361
+ query: z74.string().optional().describe("Trigger query or filter"),
28362
+ skill_name: z74.string().optional().describe("Skill name for load_skill"),
28363
+ pack_name: z74.string().optional().describe("Starter pack name"),
28364
+ title: z74.string().optional().describe("Procedure title"),
28365
+ content: z74.string().optional().describe("Procedure content"),
28366
+ priority: z74.enum(["p0", "p1", "p2"]).optional().describe("Procedure priority"),
28367
+ domain: z74.string().optional().describe("Procedure domain"),
28368
+ procedure_id: z74.string().optional().describe("Procedure id for deactivate"),
28369
+ subaction: z74.enum(["store", "list", "deactivate"]).optional().describe("Nested action for company_procedure/global_procedure"),
28370
+ max_clusters: z74.coerce.number().optional().describe("Consolidation max clusters"),
28371
+ force: z74.boolean().optional().describe("Force operation where supported"),
28372
+ cloud_action: z74.enum(["status", "sync", "reupload"]).optional().describe("Nested operation for action=cloud_sync"),
28373
+ confirm_local_db_source_of_truth: z74.string().optional().describe("Required for cloud_action=reupload; must exactly equal LOCAL DB IS SOURCE OF TRUTH"),
28374
+ domain_name: z74.string().optional().describe("Client deployment domain"),
28375
+ phase: z74.enum(["phase_1_coo", "phase_2_executives", "phase_3_parallel_org", "1", "2", "3"]).optional().describe("Orchestration phase for orchestration_phase action")
28133
28376
  }
28134
28377
  }, async (input, extra) => {
28135
28378
  const action = input.action;
@@ -28161,6 +28404,7 @@ var init_config2 = __esm({
28161
28404
  init_list_agent_sessions();
28162
28405
  init_get_session_kills();
28163
28406
  init_get_daemon_health();
28407
+ init_mcp_ping();
28164
28408
  init_get_auto_wake_status();
28165
28409
  init_get_worker_gate();
28166
28410
  init_run_memory_audit();
@@ -28187,6 +28431,7 @@ var init_config2 = __esm({
28187
28431
  list_agent_sessions: "list_agent_sessions",
28188
28432
  session_kills: "get_session_kills",
28189
28433
  daemon_health: "get_daemon_health",
28434
+ mcp_ping: "mcp_ping",
28190
28435
  auto_wake_status: "get_auto_wake_status",
28191
28436
  worker_gate: "get_worker_gate",
28192
28437
  memory_audit: "run_memory_audit",
@@ -28212,7 +28457,7 @@ var init_config2 = __esm({
28212
28457
  });
28213
28458
 
28214
28459
  // src/mcp/tools/list-wiki-pages.ts
28215
- import { z as z74 } from "zod";
28460
+ import { z as z75 } from "zod";
28216
28461
  function registerListWikiPages(server) {
28217
28462
  server.registerTool(
28218
28463
  "list_wiki_pages",
@@ -28220,8 +28465,8 @@ function registerListWikiPages(server) {
28220
28465
  title: "List Wiki Pages",
28221
28466
  description: "List documents in an exe-wiki workspace. Optionally filter by folder.",
28222
28467
  inputSchema: {
28223
- workspace: z74.string().describe('Wiki workspace slug (e.g., "hygo")'),
28224
- folder: z74.string().optional().describe("Filter by folder path")
28468
+ workspace: z75.string().describe('Wiki workspace slug (e.g., "hygo")'),
28469
+ folder: z75.string().optional().describe("Filter by folder path")
28225
28470
  }
28226
28471
  },
28227
28472
  async ({ workspace, folder }) => {
@@ -28317,7 +28562,7 @@ var init_list_wiki_pages = __esm({
28317
28562
  });
28318
28563
 
28319
28564
  // src/mcp/tools/get-wiki-page.ts
28320
- import { z as z75 } from "zod";
28565
+ import { z as z76 } from "zod";
28321
28566
  function registerGetWikiPage(server) {
28322
28567
  server.registerTool(
28323
28568
  "get_wiki_page",
@@ -28325,9 +28570,9 @@ function registerGetWikiPage(server) {
28325
28570
  title: "Get Wiki Page",
28326
28571
  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.",
28327
28572
  inputSchema: {
28328
- workspace: z75.string().describe('Wiki workspace slug (e.g., "hygo")'),
28329
- document_id: z75.string().optional().describe("Specific document ID (exact lookup)"),
28330
- title: z75.string().optional().describe("Search by title (fuzzy match)")
28573
+ workspace: z76.string().describe('Wiki workspace slug (e.g., "hygo")'),
28574
+ document_id: z76.string().optional().describe("Specific document ID (exact lookup)"),
28575
+ title: z76.string().optional().describe("Search by title (fuzzy match)")
28331
28576
  }
28332
28577
  },
28333
28578
  async ({ workspace, document_id, title }) => {
@@ -28483,7 +28728,7 @@ var init_get_wiki_page = __esm({
28483
28728
  });
28484
28729
 
28485
28730
  // src/mcp/tools/wiki.ts
28486
- import { z as z76 } from "zod";
28731
+ import { z as z77 } from "zod";
28487
28732
  function errorResult9(text3) {
28488
28733
  return { content: [{ type: "text", text: text3 }], isError: true };
28489
28734
  }
@@ -28509,14 +28754,14 @@ function registerWiki(server) {
28509
28754
  title: "Wiki",
28510
28755
  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.",
28511
28756
  inputSchema: {
28512
- action: z76.enum(["list", "get"]).describe("Wiki read operation. Writes use raw-data ingestion/projection, not direct MCP writes."),
28513
- workspace: z76.string().optional().describe("Wiki workspace slug"),
28514
- title: z76.string().optional().describe("Fuzzy page title lookup for get"),
28515
- content: z76.string().optional().describe("Reserved; wiki writes use raw-data ingestion/projection"),
28516
- folder: z76.string().optional().describe("Optional folder path for list"),
28517
- document_id: z76.string().optional().describe("Document ID for get"),
28518
- mode: z76.enum(["replace", "append"]).optional().describe("Reserved; direct wiki updates are removed"),
28519
- section: z76.string().optional().describe("Reserved; direct wiki updates are removed")
28757
+ action: z77.enum(["list", "get"]).describe("Wiki read operation. Writes use raw-data ingestion/projection, not direct MCP writes."),
28758
+ workspace: z77.string().optional().describe("Wiki workspace slug"),
28759
+ title: z77.string().optional().describe("Fuzzy page title lookup for get"),
28760
+ content: z77.string().optional().describe("Reserved; wiki writes use raw-data ingestion/projection"),
28761
+ folder: z77.string().optional().describe("Optional folder path for list"),
28762
+ document_id: z77.string().optional().describe("Document ID for get"),
28763
+ mode: z77.enum(["replace", "append"]).optional().describe("Reserved; direct wiki updates are removed"),
28764
+ section: z77.string().optional().describe("Reserved; direct wiki updates are removed")
28520
28765
  }
28521
28766
  },
28522
28767
  async (input, extra) => {
@@ -28555,7 +28800,7 @@ var init_wiki = __esm({
28555
28800
  });
28556
28801
 
28557
28802
  // src/mcp/tools/behavior.ts
28558
- import { z as z77 } from "zod";
28803
+ import { z as z78 } from "zod";
28559
28804
  function rowToBehavior2(r) {
28560
28805
  return {
28561
28806
  id: String(r.id),
@@ -28577,13 +28822,13 @@ function registerBehavior(server) {
28577
28822
  title: "Behavior",
28578
28823
  description: "Manage behavioral patterns, corrections, and reusable procedures for employees. Actions: store (create new), list (query existing), deactivate (soft-delete, restricted).",
28579
28824
  inputSchema: {
28580
- action: z77.enum(["store", "list", "deactivate"]).describe("Action to perform"),
28581
- content: z77.string().max(500).optional().describe("The behavioral instruction \u2014 one clear sentence (store)"),
28582
- domain: z77.string().optional().describe("Category: workflow, code-style, tool-use, communication, architecture, testing"),
28583
- priority: z77.enum(["p0", "p1", "p2"]).optional().describe("Priority tier. p0 = always included. p1 = standard (default). p2 = nice-to-have."),
28584
- agent_id: z77.string().optional().describe("Employee name. Defaults to current agent. Pass 'all' to list everyone's (list only)."),
28585
- project_name: z77.string().optional().describe("Defaults to current project. Pass 'global' for a behavior that applies everywhere (store)."),
28586
- behavior_id: z77.string().optional().describe("UUID of the behavior (deactivate)")
28825
+ action: z78.enum(["store", "list", "deactivate"]).describe("Action to perform"),
28826
+ content: z78.string().max(500).optional().describe("The behavioral instruction \u2014 one clear sentence (store)"),
28827
+ domain: z78.string().optional().describe("Category: workflow, code-style, tool-use, communication, architecture, testing"),
28828
+ priority: z78.enum(["p0", "p1", "p2"]).optional().describe("Priority tier. p0 = always included. p1 = standard (default). p2 = nice-to-have."),
28829
+ agent_id: z78.string().optional().describe("Employee name. Defaults to current agent. Pass 'all' to list everyone's (list only)."),
28830
+ project_name: z78.string().optional().describe("Defaults to current project. Pass 'global' for a behavior that applies everywhere (store)."),
28831
+ behavior_id: z78.string().optional().describe("UUID of the behavior (deactivate)")
28587
28832
  }
28588
28833
  },
28589
28834
  async ({ action, content, domain, priority, agent_id, project_name, behavior_id }) => {
@@ -28764,7 +29009,7 @@ var init_behavior = __esm({
28764
29009
  });
28765
29010
 
28766
29011
  // src/mcp/tools/reminder.ts
28767
- import { z as z78 } from "zod";
29012
+ import { z as z79 } from "zod";
28768
29013
  function registerReminder(server) {
28769
29014
  server.registerTool(
28770
29015
  "reminder",
@@ -28772,11 +29017,11 @@ function registerReminder(server) {
28772
29017
  title: "Reminder",
28773
29018
  description: "Manage reminders for the founder. Shown in the boot brief every session. Actions: create (set new), list (view active), complete (mark done).",
28774
29019
  inputSchema: {
28775
- action: z78.enum(["create", "list", "complete"]).describe("Action to perform"),
28776
- text: z78.string().optional().describe("What to remind about (create)"),
28777
- due_date: z78.string().optional().describe("Optional due date \u2014 ISO date (2026-04-01) or null for persistent (create)"),
28778
- reminder_id: z78.string().optional().describe("Reminder UUID or text substring to match (complete)"),
28779
- include_completed: z78.boolean().optional().default(false).describe("Include completed reminders (list)")
29020
+ action: z79.enum(["create", "list", "complete"]).describe("Action to perform"),
29021
+ text: z79.string().optional().describe("What to remind about (create)"),
29022
+ due_date: z79.string().optional().describe("Optional due date \u2014 ISO date (2026-04-01) or null for persistent (create)"),
29023
+ reminder_id: z79.string().optional().describe("Reminder UUID or text substring to match (complete)"),
29024
+ include_completed: z79.boolean().optional().default(false).describe("Include completed reminders (list)")
28780
29025
  }
28781
29026
  },
28782
29027
  async ({ action, text: text3, due_date, reminder_id, include_completed }) => {
@@ -28835,7 +29080,7 @@ var init_reminder = __esm({
28835
29080
  });
28836
29081
 
28837
29082
  // src/mcp/tools/store-global-procedure.ts
28838
- import { z as z79 } from "zod";
29083
+ import { z as z80 } from "zod";
28839
29084
  function registerStoreGlobalProcedure(server) {
28840
29085
  server.registerTool(
28841
29086
  "store_global_procedure",
@@ -28843,10 +29088,10 @@ function registerStoreGlobalProcedure(server) {
28843
29088
  title: "Store Company Procedure (use global_procedure instead)",
28844
29089
  description: "DEPRECATED \u2014 use global_procedure with action='store'. Create a company procedure (customer-owned Layer 0 rule). RESTRICTED: only coordinator or founder sessions.",
28845
29090
  inputSchema: {
28846
- title: z79.string().describe("Short title for the procedure"),
28847
- content: z79.string().max(500).describe("The procedure content \u2014 clear, actionable instruction"),
28848
- priority: z79.enum(["p0", "p1", "p2"]).optional().describe("Priority tier. p0 = always (default)."),
28849
- domain: z79.string().optional().describe("Category: workflow, code-style, communication, architecture, testing, security")
29091
+ title: z80.string().describe("Short title for the procedure"),
29092
+ content: z80.string().max(500).describe("The procedure content \u2014 clear, actionable instruction"),
29093
+ priority: z80.enum(["p0", "p1", "p2"]).optional().describe("Priority tier. p0 = always (default)."),
29094
+ domain: z80.string().optional().describe("Category: workflow, code-style, communication, architecture, testing, security")
28850
29095
  }
28851
29096
  },
28852
29097
  async ({ title, content, priority, domain }) => {
@@ -28933,7 +29178,7 @@ var init_list_global_procedures = __esm({
28933
29178
  });
28934
29179
 
28935
29180
  // src/mcp/tools/deactivate-global-procedure.ts
28936
- import { z as z80 } from "zod";
29181
+ import { z as z81 } from "zod";
28937
29182
  function registerDeactivateGlobalProcedure(server) {
28938
29183
  server.registerTool(
28939
29184
  "deactivate_global_procedure",
@@ -28941,7 +29186,7 @@ function registerDeactivateGlobalProcedure(server) {
28941
29186
  title: "Deactivate Company Procedure (use global_procedure instead)",
28942
29187
  description: "DEPRECATED \u2014 use global_procedure with action='deactivate'. Soft-delete a company procedure. RESTRICTED: only coordinator or founder sessions.",
28943
29188
  inputSchema: {
28944
- procedure_id: z80.string().describe("UUID of the company procedure to deactivate")
29189
+ procedure_id: z81.string().describe("UUID of the company procedure to deactivate")
28945
29190
  }
28946
29191
  },
28947
29192
  async ({ procedure_id }) => {
@@ -29005,7 +29250,7 @@ var init_deactivate_global_procedure = __esm({
29005
29250
  });
29006
29251
 
29007
29252
  // src/mcp/tools/store-decision.ts
29008
- import { z as z81 } from "zod";
29253
+ import { z as z82 } from "zod";
29009
29254
  import crypto18 from "crypto";
29010
29255
  function registerStoreDecision(server) {
29011
29256
  server.registerTool(
@@ -29014,13 +29259,13 @@ function registerStoreDecision(server) {
29014
29259
  title: "Store Decision",
29015
29260
  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.",
29016
29261
  inputSchema: {
29017
- domain: z81.string().describe(
29262
+ domain: z82.string().describe(
29018
29263
  "Domain key, e.g. 'auth-strategy', 'db-migration-approach', 'api-versioning'"
29019
29264
  ),
29020
- decision: z81.string().describe("The decision text \u2014 what was decided"),
29021
- rationale: z81.string().optional().describe("Why this decision was made \u2014 constraints, trade-offs, context"),
29022
- supersedes: z81.string().optional().describe("UUID of the decision this supersedes (previous decision for this domain)"),
29023
- project_name: z81.string().optional().describe("Project name")
29265
+ decision: z82.string().describe("The decision text \u2014 what was decided"),
29266
+ rationale: z82.string().optional().describe("Why this decision was made \u2014 constraints, trade-offs, context"),
29267
+ supersedes: z82.string().optional().describe("UUID of the decision this supersedes (previous decision for this domain)"),
29268
+ project_name: z82.string().optional().describe("Project name")
29024
29269
  }
29025
29270
  },
29026
29271
  async ({ domain, decision, rationale, supersedes, project_name }) => {
@@ -29097,7 +29342,7 @@ var init_store_decision = __esm({
29097
29342
  });
29098
29343
 
29099
29344
  // src/mcp/tools/get-decision.ts
29100
- import { z as z82 } from "zod";
29345
+ import { z as z83 } from "zod";
29101
29346
  function registerGetDecision(server) {
29102
29347
  server.registerTool(
29103
29348
  "get_decision",
@@ -29105,7 +29350,7 @@ function registerGetDecision(server) {
29105
29350
  title: "Get Decision",
29106
29351
  description: "Retrieve the latest authoritative decision for a domain. Returns the current active decision and the supersession history.",
29107
29352
  inputSchema: {
29108
- domain: z82.string().describe(
29353
+ domain: z83.string().describe(
29109
29354
  "Domain key to look up, e.g. 'auth-strategy', 'db-migration-approach'"
29110
29355
  )
29111
29356
  }
@@ -29175,10 +29420,10 @@ var init_get_decision = __esm({
29175
29420
 
29176
29421
  // src/lib/people.ts
29177
29422
  import { readFile as readFile5, writeFile as writeFile6, mkdir as mkdir5 } from "fs/promises";
29178
- import { existsSync as existsSync40, readFileSync as readFileSync32 } from "fs";
29179
- import path49 from "path";
29423
+ import { existsSync as existsSync42, readFileSync as readFileSync34 } from "fs";
29424
+ import path51 from "path";
29180
29425
  async function loadPeople() {
29181
- if (!existsSync40(PEOPLE_PATH)) return [];
29426
+ if (!existsSync42(PEOPLE_PATH)) return [];
29182
29427
  try {
29183
29428
  const raw = await readFile5(PEOPLE_PATH, "utf-8");
29184
29429
  return JSON.parse(raw);
@@ -29187,7 +29432,7 @@ async function loadPeople() {
29187
29432
  }
29188
29433
  }
29189
29434
  async function savePeople(people) {
29190
- await mkdir5(path49.dirname(PEOPLE_PATH), { recursive: true });
29435
+ await mkdir5(path51.dirname(PEOPLE_PATH), { recursive: true });
29191
29436
  await writeFile6(PEOPLE_PATH, JSON.stringify(people, null, 2) + "\n", "utf-8");
29192
29437
  }
29193
29438
  async function addPerson(person) {
@@ -29213,12 +29458,12 @@ var init_people = __esm({
29213
29458
  "src/lib/people.ts"() {
29214
29459
  "use strict";
29215
29460
  init_config();
29216
- PEOPLE_PATH = path49.join(EXE_AI_DIR, "people.json");
29461
+ PEOPLE_PATH = path51.join(EXE_AI_DIR, "people.json");
29217
29462
  }
29218
29463
  });
29219
29464
 
29220
29465
  // src/mcp/tools/people-roster.ts
29221
- import { z as z83 } from "zod";
29466
+ import { z as z84 } from "zod";
29222
29467
  function registerAddPerson(server) {
29223
29468
  server.registerTool(
29224
29469
  "add_person",
@@ -29226,10 +29471,10 @@ function registerAddPerson(server) {
29226
29471
  title: "Add Person",
29227
29472
  description: "Add or update a key human in the people roster. Used for co-founders, partners, customers \u2014 anyone agents need to know about.",
29228
29473
  inputSchema: {
29229
- name: z83.string().describe("Person's name"),
29230
- role: z83.string().describe("Their role (e.g. co-founder, customer, partner)"),
29231
- relationship: z83.string().describe("Relationship to the organization (e.g. co-founder, early adopter, investor)"),
29232
- notes: z83.string().optional().describe("Additional context about this person")
29474
+ name: z84.string().describe("Person's name"),
29475
+ role: z84.string().describe("Their role (e.g. co-founder, customer, partner)"),
29476
+ relationship: z84.string().describe("Relationship to the organization (e.g. co-founder, early adopter, investor)"),
29477
+ notes: z84.string().optional().describe("Additional context about this person")
29233
29478
  }
29234
29479
  },
29235
29480
  async ({ name, role, relationship, notes }) => {
@@ -29275,7 +29520,7 @@ function registerGetPerson(server) {
29275
29520
  title: "Get Person",
29276
29521
  description: "Look up a specific person by name from the people roster.",
29277
29522
  inputSchema: {
29278
- name: z83.string().describe("Person's name to look up")
29523
+ name: z84.string().describe("Person's name to look up")
29279
29524
  }
29280
29525
  },
29281
29526
  async ({ name }) => {
@@ -29305,7 +29550,7 @@ var init_people_roster = __esm({
29305
29550
  });
29306
29551
 
29307
29552
  // src/lib/exe-db-read.ts
29308
- import path50 from "path";
29553
+ import path52 from "path";
29309
29554
  import os21 from "os";
29310
29555
  import { createRequire as createRequire6 } from "module";
29311
29556
  import { pathToFileURL as pathToFileURL6 } from "url";
@@ -29322,8 +29567,8 @@ async function getExeDbReadClient() {
29322
29567
  if (!Ctor2) throw new Error(`No PrismaClient export found at ${explicitPath}`);
29323
29568
  return new Ctor2();
29324
29569
  }
29325
- const exeDbRoot = process.env.EXE_DB_ROOT ?? path50.join(os21.homedir(), "exe-db");
29326
- const req = createRequire6(path50.join(exeDbRoot, "package.json"));
29570
+ const exeDbRoot = process.env.EXE_DB_ROOT ?? path52.join(os21.homedir(), "exe-db");
29571
+ const req = createRequire6(path52.join(exeDbRoot, "package.json"));
29327
29572
  const entry = req.resolve("@prisma/client");
29328
29573
  const mod = await import(pathToFileURL6(entry).href);
29329
29574
  const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
@@ -29350,7 +29595,7 @@ var init_exe_db_read = __esm({
29350
29595
  });
29351
29596
 
29352
29597
  // src/mcp/tools/crm.ts
29353
- import { z as z84 } from "zod";
29598
+ import { z as z85 } from "zod";
29354
29599
  function text(content, isError = false) {
29355
29600
  return { content: [{ type: "text", text: content }], ...isError ? { isError: true } : {} };
29356
29601
  }
@@ -29364,12 +29609,12 @@ function registerCrm(server) {
29364
29609
  title: "CRM",
29365
29610
  description: "Read-only CRM access from exe-db crm schema. Actions: list_people, get_person, list_tables, describe_table.",
29366
29611
  inputSchema: {
29367
- action: z84.enum(["list_people", "get_person", "list_tables", "describe_table"]).describe("CRM read operation"),
29368
- id: z84.string().optional().describe("CRM row/person id for get_person"),
29369
- query: z84.string().optional().describe("Text search for list_people/get_person"),
29370
- table: z84.string().optional().describe("crm schema table name for describe_table"),
29371
- limit: z84.coerce.number().int().min(1).max(50).optional().describe("Max rows, capped at 50"),
29372
- offset: z84.coerce.number().int().min(0).optional().describe("Rows to skip")
29612
+ action: z85.enum(["list_people", "get_person", "list_tables", "describe_table"]).describe("CRM read operation"),
29613
+ id: z85.string().optional().describe("CRM row/person id for get_person"),
29614
+ query: z85.string().optional().describe("Text search for list_people/get_person"),
29615
+ table: z85.string().optional().describe("crm schema table name for describe_table"),
29616
+ limit: z85.coerce.number().int().min(1).max(50).optional().describe("Max rows, capped at 50"),
29617
+ offset: z85.coerce.number().int().min(0).optional().describe("Rows to skip")
29373
29618
  }
29374
29619
  }, async ({ action, id, query, table, limit, offset }) => {
29375
29620
  try {
@@ -29434,7 +29679,7 @@ var init_crm = __esm({
29434
29679
  });
29435
29680
 
29436
29681
  // src/mcp/tools/raw-data.ts
29437
- import { z as z85 } from "zod";
29682
+ import { z as z86 } from "zod";
29438
29683
  function text2(content, isError = false) {
29439
29684
  return { content: [{ type: "text", text: content }], ...isError ? { isError: true } : {} };
29440
29685
  }
@@ -29443,15 +29688,15 @@ function registerRawData(server) {
29443
29688
  title: "Raw Data",
29444
29689
  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.",
29445
29690
  inputSchema: {
29446
- action: z85.enum(["list_sources", "query", "get"]).describe("Raw data read operation"),
29447
- id: z85.string().optional().describe("raw.raw_events id for action=get"),
29448
- source: z85.string().optional().describe("Filter by raw source"),
29449
- event_type: z85.string().optional().describe("Filter by event_type"),
29450
- query: z85.string().optional().describe("Search payload/metadata text"),
29451
- processed: z85.boolean().optional().describe("Filter processed_at IS NULL/NOT NULL"),
29452
- limit: z85.coerce.number().int().min(1).max(50).optional().describe("Max rows, capped at 50"),
29453
- offset: z85.coerce.number().int().min(0).optional().describe("Rows to skip"),
29454
- include_payload: z85.boolean().optional().describe("Include full payload JSON. Default false to save tokens.")
29691
+ action: z86.enum(["list_sources", "query", "get"]).describe("Raw data read operation"),
29692
+ id: z86.string().optional().describe("raw.raw_events id for action=get"),
29693
+ source: z86.string().optional().describe("Filter by raw source"),
29694
+ event_type: z86.string().optional().describe("Filter by event_type"),
29695
+ query: z86.string().optional().describe("Search payload/metadata text"),
29696
+ processed: z86.boolean().optional().describe("Filter processed_at IS NULL/NOT NULL"),
29697
+ limit: z86.coerce.number().int().min(1).max(50).optional().describe("Max rows, capped at 50"),
29698
+ offset: z86.coerce.number().int().min(0).optional().describe("Rows to skip"),
29699
+ include_payload: z86.boolean().optional().describe("Include full payload JSON. Default false to save tokens.")
29455
29700
  }
29456
29701
  }, async ({ action, id, source, event_type, query, processed, limit, offset, include_payload }) => {
29457
29702
  try {
@@ -29519,10 +29764,10 @@ var init_raw_data = __esm({
29519
29764
  });
29520
29765
 
29521
29766
  // src/mcp/tools/create-bug-report.ts
29522
- import { z as z86 } from "zod";
29767
+ import { z as z87 } from "zod";
29523
29768
  import crypto19 from "crypto";
29524
29769
  import { mkdir as mkdir6, writeFile as writeFile7 } from "fs/promises";
29525
- import path51 from "path";
29770
+ import path53 from "path";
29526
29771
  function slugify2(input) {
29527
29772
  return input.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80) || "bug-report";
29528
29773
  }
@@ -29600,22 +29845,22 @@ function registerCreateBugReport(server) {
29600
29845
  title: "Create Bug Report",
29601
29846
  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.",
29602
29847
  inputSchema: {
29603
- title: z86.string().min(3).describe("Short descriptive title"),
29848
+ title: z87.string().min(3).describe("Short descriptive title"),
29604
29849
  classification: CLASSIFICATION.describe(
29605
29850
  "upstream_bug = platform defect; customer_customization = local preference; emergency_hotfix = temporary local patch; unclear = needs maintainer triage"
29606
29851
  ),
29607
29852
  severity: SEVERITY.default("p2").describe("p0 critical \u2192 p3 low"),
29608
- summary: z86.string().min(10).describe("What happened and why it matters"),
29609
- customer_impact: z86.string().optional().describe("How this affects the customer/founder"),
29610
- reproduction_steps: z86.array(z86.string()).optional().describe("Steps to reproduce"),
29611
- expected: z86.string().optional().describe("Expected behavior"),
29612
- actual: z86.string().optional().describe("Actual behavior"),
29613
- files_changed: z86.array(z86.string()).optional().describe("Files changed or suspected"),
29614
- workaround: z86.string().optional().describe("Temporary local workaround/hotfix, if any"),
29615
- local_patch_diff: z86.string().optional().describe("Small local diff or patch summary"),
29616
- package_version: z86.string().optional().describe("Installed @askexenow/exe-os version"),
29617
- project_name: z86.string().optional().describe("Project/customer context"),
29618
- send_upstream: z86.boolean().default(true).describe("Attempt to POST to configured AskExe support endpoint")
29853
+ summary: z87.string().min(10).describe("What happened and why it matters"),
29854
+ customer_impact: z87.string().optional().describe("How this affects the customer/founder"),
29855
+ reproduction_steps: z87.array(z87.string()).optional().describe("Steps to reproduce"),
29856
+ expected: z87.string().optional().describe("Expected behavior"),
29857
+ actual: z87.string().optional().describe("Actual behavior"),
29858
+ files_changed: z87.array(z87.string()).optional().describe("Files changed or suspected"),
29859
+ workaround: z87.string().optional().describe("Temporary local workaround/hotfix, if any"),
29860
+ local_patch_diff: z87.string().optional().describe("Small local diff or patch summary"),
29861
+ package_version: z87.string().optional().describe("Installed @askexenow/exe-os version"),
29862
+ project_name: z87.string().optional().describe("Project/customer context"),
29863
+ send_upstream: z87.boolean().default(true).describe("Attempt to POST to configured AskExe support endpoint")
29619
29864
  }
29620
29865
  },
29621
29866
  async ({
@@ -29655,9 +29900,9 @@ function registerCreateBugReport(server) {
29655
29900
  filesChanged: files_changed,
29656
29901
  projectName: project_name
29657
29902
  });
29658
- const outDir = path51.join(EXE_AI_DIR, "bug-reports");
29903
+ const outDir = path53.join(EXE_AI_DIR, "bug-reports");
29659
29904
  await mkdir6(outDir, { recursive: true });
29660
- const reportPath = path51.join(outDir, `${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}-${slugify2(title)}-${id.slice(0, 8)}.md`);
29905
+ const reportPath = path53.join(outDir, `${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}-${slugify2(title)}-${id.slice(0, 8)}.md`);
29661
29906
  await writeFile7(reportPath, markdown, "utf-8");
29662
29907
  let vector = null;
29663
29908
  try {
@@ -29731,36 +29976,36 @@ var init_create_bug_report = __esm({
29731
29976
  init_config();
29732
29977
  init_license();
29733
29978
  init_store();
29734
- CLASSIFICATION = z86.enum([
29979
+ CLASSIFICATION = z87.enum([
29735
29980
  "upstream_bug",
29736
29981
  "customer_customization",
29737
29982
  "emergency_hotfix",
29738
29983
  "unclear"
29739
29984
  ]);
29740
- SEVERITY = z86.enum(["p0", "p1", "p2", "p3"]);
29985
+ SEVERITY = z87.enum(["p0", "p1", "p2", "p3"]);
29741
29986
  }
29742
29987
  });
29743
29988
 
29744
29989
  // src/lib/code-context-index.ts
29745
29990
  import crypto20 from "crypto";
29746
- import path52 from "path";
29747
- import { existsSync as existsSync41, mkdirSync as mkdirSync20, readFileSync as readFileSync33, statSync as statSync9, writeFileSync as writeFileSync23 } from "fs";
29991
+ import path54 from "path";
29992
+ import { existsSync as existsSync43, mkdirSync as mkdirSync21, readFileSync as readFileSync35, statSync as statSync10, writeFileSync as writeFileSync24 } from "fs";
29748
29993
  import { spawnSync } from "child_process";
29749
29994
  function normalizeProjectRoot(projectRoot) {
29750
- return path52.resolve(projectRoot || process.cwd());
29995
+ return path54.resolve(projectRoot || process.cwd());
29751
29996
  }
29752
29997
  function hashText(text3) {
29753
29998
  return crypto20.createHash("sha256").update(text3).digest("hex");
29754
29999
  }
29755
30000
  function indexDir() {
29756
- const dir = path52.join(EXE_AI_DIR, "code-context");
29757
- mkdirSync20(dir, { recursive: true });
30001
+ const dir = path54.join(EXE_AI_DIR, "code-context");
30002
+ mkdirSync21(dir, { recursive: true });
29758
30003
  return dir;
29759
30004
  }
29760
30005
  function getCodeContextIndexPath(projectRoot) {
29761
30006
  const root = normalizeProjectRoot(projectRoot);
29762
30007
  const rootHash = hashText(root).slice(0, 16);
29763
- return path52.join(indexDir(), `${rootHash}.json`);
30008
+ return path54.join(indexDir(), `${rootHash}.json`);
29764
30009
  }
29765
30010
  function currentBranch(projectRoot) {
29766
30011
  const result2 = spawnSync("git", ["branch", "--show-current"], {
@@ -29772,11 +30017,11 @@ function currentBranch(projectRoot) {
29772
30017
  return branch || "detached-or-unknown";
29773
30018
  }
29774
30019
  function shouldIgnore(relPath) {
29775
- const parts = relPath.split(path52.sep);
30020
+ const parts = relPath.split(path54.sep);
29776
30021
  return parts.some((part) => IGNORE_SEGMENTS.has(part));
29777
30022
  }
29778
30023
  function isCodeFile(relPath) {
29779
- return CODE_EXTENSIONS.has(path52.extname(relPath).toLowerCase());
30024
+ return CODE_EXTENSIONS.has(path54.extname(relPath).toLowerCase());
29780
30025
  }
29781
30026
  function listCodeFiles(projectRoot, maxFiles) {
29782
30027
  const git = spawnSync("git", ["ls-files", "*.ts", "*.tsx", "*.js", "*.jsx"], {
@@ -29818,7 +30063,7 @@ function parseImportPaths2(importText) {
29818
30063
  }
29819
30064
  function resolveImport(fromFile, importPath, allFiles) {
29820
30065
  if (!importPath.startsWith(".")) return null;
29821
- const base = path52.posix.normalize(path52.posix.join(path52.posix.dirname(fromFile.replaceAll(path52.sep, "/")), importPath));
30066
+ const base = path54.posix.normalize(path54.posix.join(path54.posix.dirname(fromFile.replaceAll(path54.sep, "/")), importPath));
29822
30067
  const withoutKnownExt = base.replace(/\.(?:js|jsx|ts|tsx)$/, "");
29823
30068
  const candidates = [
29824
30069
  base,
@@ -29830,10 +30075,10 @@ function resolveImport(fromFile, importPath, allFiles) {
29830
30075
  `${base}.tsx`,
29831
30076
  `${base}.js`,
29832
30077
  `${base}.jsx`,
29833
- path52.posix.join(base, "index.ts"),
29834
- path52.posix.join(base, "index.tsx"),
29835
- path52.posix.join(base, "index.js"),
29836
- path52.posix.join(base, "index.jsx")
30078
+ path54.posix.join(base, "index.ts"),
30079
+ path54.posix.join(base, "index.tsx"),
30080
+ path54.posix.join(base, "index.js"),
30081
+ path54.posix.join(base, "index.jsx")
29837
30082
  ];
29838
30083
  return candidates.find((candidate) => allFiles.has(candidate)) ?? null;
29839
30084
  }
@@ -29842,9 +30087,9 @@ function symbolId(filePath, chunk) {
29842
30087
  }
29843
30088
  function loadIndex(projectRoot) {
29844
30089
  const file = getCodeContextIndexPath(projectRoot);
29845
- if (!existsSync41(file)) return null;
30090
+ if (!existsSync43(file)) return null;
29846
30091
  try {
29847
- const parsed = JSON.parse(readFileSync33(file, "utf8"));
30092
+ const parsed = JSON.parse(readFileSync35(file, "utf8"));
29848
30093
  if (parsed.version !== INDEX_VERSION || parsed.projectRoot !== projectRoot) return null;
29849
30094
  return parsed;
29850
30095
  } catch {
@@ -29852,18 +30097,18 @@ function loadIndex(projectRoot) {
29852
30097
  }
29853
30098
  }
29854
30099
  function saveIndex(index) {
29855
- writeFileSync23(getCodeContextIndexPath(index.projectRoot), JSON.stringify(index, null, 2));
30100
+ writeFileSync24(getCodeContextIndexPath(index.projectRoot), JSON.stringify(index, null, 2));
29856
30101
  }
29857
30102
  function buildFileRecord(projectRoot, relPath, allFiles, previous) {
29858
- const absPath = path52.join(projectRoot, relPath);
30103
+ const absPath = path54.join(projectRoot, relPath);
29859
30104
  let stat;
29860
30105
  try {
29861
- stat = statSync9(absPath);
30106
+ stat = statSync10(absPath);
29862
30107
  } catch {
29863
30108
  return null;
29864
30109
  }
29865
30110
  if (!stat.isFile()) return null;
29866
- const source = readFileSync33(absPath, "utf8");
30111
+ const source = readFileSync35(absPath, "utf8");
29867
30112
  const hash = hashText(source);
29868
30113
  if (previous && previous.hash === hash && previous.mtimeMs === stat.mtimeMs && previous.size === stat.size) {
29869
30114
  return previous;
@@ -29900,10 +30145,10 @@ function buildCodeContextIndex(options = {}) {
29900
30145
  const branch = currentBranch(projectRoot);
29901
30146
  const previous = options.force ? null : loadIndex(projectRoot);
29902
30147
  const files = listCodeFiles(projectRoot, maxFiles);
29903
- const allFiles = new Set(files.map((file) => file.replaceAll(path52.sep, "/")));
30148
+ const allFiles = new Set(files.map((file) => file.replaceAll(path54.sep, "/")));
29904
30149
  const fileRecords = {};
29905
30150
  for (const rel of files) {
29906
- const normalized = rel.replaceAll(path52.sep, "/");
30151
+ const normalized = rel.replaceAll(path54.sep, "/");
29907
30152
  const record = buildFileRecord(projectRoot, normalized, allFiles, previous?.files[normalized]);
29908
30153
  if (record) fileRecords[normalized] = record;
29909
30154
  }
@@ -29925,11 +30170,11 @@ function loadOrBuildCodeContextIndex(options = {}) {
29925
30170
  if (loaded) {
29926
30171
  const currentFiles = listCodeFiles(projectRoot, options.maxFiles ?? DEFAULT_MAX_FILES);
29927
30172
  const unchanged = currentFiles.every((rel) => {
29928
- const normalized = rel.replaceAll(path52.sep, "/");
30173
+ const normalized = rel.replaceAll(path54.sep, "/");
29929
30174
  const existing = loaded.files[normalized];
29930
30175
  if (!existing) return false;
29931
30176
  try {
29932
- const stat = statSync9(path52.join(projectRoot, normalized));
30177
+ const stat = statSync10(path54.join(projectRoot, normalized));
29933
30178
  return stat.mtimeMs === existing.mtimeMs && stat.size === existing.size;
29934
30179
  } catch {
29935
30180
  return false;
@@ -30032,7 +30277,7 @@ function traceCodeSymbol(symbolName, options = {}) {
30032
30277
  }
30033
30278
  function resolveTargetFile(index, input) {
30034
30279
  if (input.filePath) {
30035
- const normalized = input.filePath.replaceAll(path52.sep, "/").replace(/^\.\//, "");
30280
+ const normalized = input.filePath.replaceAll(path54.sep, "/").replace(/^\.\//, "");
30036
30281
  if (index.files[normalized]) return { filePath: normalized, target: normalized };
30037
30282
  const suffix = Object.keys(index.files).find((file) => file.endsWith(normalized));
30038
30283
  if (suffix) return { filePath: suffix, target: input.filePath };
@@ -30062,7 +30307,7 @@ function analyzeBlastRadius(input) {
30062
30307
  }
30063
30308
  }
30064
30309
  }
30065
- const targetBase = path52.basename(target.filePath).replace(/\.[^.]+$/, "").toLowerCase();
30310
+ const targetBase = path54.basename(target.filePath).replace(/\.[^.]+$/, "").toLowerCase();
30066
30311
  const symbolLower = input.symbol?.toLowerCase();
30067
30312
  const tests = Object.keys(index.files).filter((file) => {
30068
30313
  const lower = file.toLowerCase();
@@ -30109,7 +30354,7 @@ var init_code_context_index = __esm({
30109
30354
  });
30110
30355
 
30111
30356
  // src/mcp/tools/code-context.ts
30112
- import { z as z87 } from "zod";
30357
+ import { z as z88 } from "zod";
30113
30358
  function errorResult10(text3) {
30114
30359
  return { content: [{ type: "text", text: text3 }], isError: true };
30115
30360
  }
@@ -30121,15 +30366,15 @@ function registerCodeContext(server) {
30121
30366
  title: "Code Context",
30122
30367
  description: "Persistent codebase context engine. One consolidated tool to avoid MCP bloat. Actions: index, search, trace, blast_radius, stats.",
30123
30368
  inputSchema: {
30124
- action: z87.enum(["index", "search", "trace", "blast_radius", "stats"]).describe("Code context operation"),
30125
- project_root: z87.string().optional().describe("Repository root. Defaults to current working directory."),
30126
- query: z87.string().optional().describe("Search query for action=search"),
30127
- symbol: z87.string().optional().describe("Symbol/function/class/type name for trace or blast_radius"),
30128
- file_path: z87.string().optional().describe("File path for blast_radius"),
30129
- force: z87.boolean().optional().describe("Force rebuild before answering"),
30130
- limit: z87.coerce.number().int().min(1).max(100).optional().describe("Max results"),
30131
- depth: z87.coerce.number().int().min(1).max(5).optional().describe("Dependent traversal depth for blast_radius"),
30132
- max_files: z87.coerce.number().int().min(1).max(1e4).optional().describe("Max code files to index")
30369
+ action: z88.enum(["index", "search", "trace", "blast_radius", "stats"]).describe("Code context operation"),
30370
+ project_root: z88.string().optional().describe("Repository root. Defaults to current working directory."),
30371
+ query: z88.string().optional().describe("Search query for action=search"),
30372
+ symbol: z88.string().optional().describe("Symbol/function/class/type name for trace or blast_radius"),
30373
+ file_path: z88.string().optional().describe("File path for blast_radius"),
30374
+ force: z88.boolean().optional().describe("Force rebuild before answering"),
30375
+ limit: z88.coerce.number().int().min(1).max(100).optional().describe("Max results"),
30376
+ depth: z88.coerce.number().int().min(1).max(5).optional().describe("Dependent traversal depth for blast_radius"),
30377
+ max_files: z88.coerce.number().int().min(1).max(1e4).optional().describe("Max code files to index")
30133
30378
  }
30134
30379
  }, async ({ action, project_root, query, symbol, file_path, force, limit, depth, max_files }) => {
30135
30380
  const opts = { projectRoot: project_root, force, maxFiles: max_files };
@@ -30172,7 +30417,7 @@ var init_code_context = __esm({
30172
30417
  });
30173
30418
 
30174
30419
  // src/mcp/tools/support-inbox.ts
30175
- import { z as z88 } from "zod";
30420
+ import { z as z89 } from "zod";
30176
30421
  function adminToken() {
30177
30422
  return process.env.ASKEXE_SUPPORT_ADMIN_TOKEN || process.env.EXE_SUPPORT_ADMIN_TOKEN;
30178
30423
  }
@@ -30211,9 +30456,9 @@ function registerListBugReports(server) {
30211
30456
  title: "List Bug Reports",
30212
30457
  description: "AskExe-internal only: list incoming customer bug reports from the support inbox.",
30213
30458
  inputSchema: {
30214
- status: z88.enum(["all", "open", "triaged", "fixed", "closed", "wontfix"]).default("open"),
30215
- severity: z88.enum(["p0", "p1", "p2", "p3"]).optional(),
30216
- limit: z88.number().int().min(1).max(100).default(25)
30459
+ status: z89.enum(["all", "open", "triaged", "fixed", "closed", "wontfix"]).default("open"),
30460
+ severity: z89.enum(["p0", "p1", "p2", "p3"]).optional(),
30461
+ limit: z89.number().int().min(1).max(100).default(25)
30217
30462
  }
30218
30463
  },
30219
30464
  async ({ status, severity, limit }) => {
@@ -30232,7 +30477,7 @@ function registerGetBugReport(server) {
30232
30477
  {
30233
30478
  title: "Get Bug Report",
30234
30479
  description: "AskExe-internal only: fetch one customer bug report with full markdown payload.",
30235
- inputSchema: { id: z88.string().min(8) }
30480
+ inputSchema: { id: z89.string().min(8) }
30236
30481
  },
30237
30482
  async ({ id }) => {
30238
30483
  const data = await requestJson(`${endpoint()}/${encodeURIComponent(id)}`);
@@ -30247,12 +30492,12 @@ function registerTriageBugReport(server) {
30247
30492
  title: "Triage Bug Report",
30248
30493
  description: "AskExe-internal only: update bug report status and link task/commit/release metadata.",
30249
30494
  inputSchema: {
30250
- id: z88.string().min(8),
30495
+ id: z89.string().min(8),
30251
30496
  status: STATUS.optional(),
30252
- triage_notes: z88.string().optional(),
30253
- linked_task_id: z88.string().optional(),
30254
- linked_commit: z88.string().optional(),
30255
- fixed_version: z88.string().optional()
30497
+ triage_notes: z89.string().optional(),
30498
+ linked_task_id: z89.string().optional(),
30499
+ linked_commit: z89.string().optional(),
30500
+ fixed_version: z89.string().optional()
30256
30501
  }
30257
30502
  },
30258
30503
  async ({ id, status, triage_notes, linked_task_id, linked_commit, fixed_version }) => {
@@ -30269,7 +30514,7 @@ var init_support_inbox = __esm({
30269
30514
  "src/mcp/tools/support-inbox.ts"() {
30270
30515
  "use strict";
30271
30516
  DEFAULT_ENDPOINT = "https://askexe.com/admin/support/bug-reports";
30272
- STATUS = z88.enum(["open", "triaged", "fixed", "closed", "wontfix"]);
30517
+ STATUS = z89.enum(["open", "triaged", "fixed", "closed", "wontfix"]);
30273
30518
  }
30274
30519
  });
30275
30520
 
@@ -30406,6 +30651,7 @@ var init_tool_gates = __esm({
30406
30651
  registerDeployClient: "admin",
30407
30652
  registerBackupVps: "admin",
30408
30653
  registerGetDaemonHealth: "admin",
30654
+ registerMcpPing: "core",
30409
30655
  registerGetAutoWakeStatus: "admin",
30410
30656
  registerGetWorkerGate: "admin",
30411
30657
  registerRunMemoryAudit: "admin",
@@ -30443,6 +30689,7 @@ var init_tool_gates = __esm({
30443
30689
  "registerSearchEverything",
30444
30690
  "registerGetDecision",
30445
30691
  "registerGetIdentity",
30692
+ "registerMcpPing",
30446
30693
  "registerListTasks",
30447
30694
  "registerGetTask",
30448
30695
  "registerListReminders",
@@ -30605,6 +30852,7 @@ function registerAllTools(server) {
30605
30852
  if (exposeLegacyConfig) {
30606
30853
  gate("registerGetAgentSpend", registerGetAgentSpend);
30607
30854
  }
30855
+ gate("registerMcpPing", registerMcpPing);
30608
30856
  if (exposeLegacyGraph) {
30609
30857
  gate("registerGetGraphStats", registerGetGraphStats);
30610
30858
  gate("registerGetEntityNeighbors", registerGetEntityNeighbors);
@@ -30720,6 +30968,7 @@ var init_register_tools = __esm({
30720
30968
  init_get_session_kills();
30721
30969
  init_list_agent_sessions();
30722
30970
  init_get_daemon_health();
30971
+ init_mcp_ping();
30723
30972
  init_get_auto_wake_status();
30724
30973
  init_get_worker_gate();
30725
30974
  init_run_memory_audit();
@@ -30965,12 +31214,12 @@ __export(task_enforcement_exports, {
30965
31214
  runTaskEnforcementTick: () => runTaskEnforcementTick,
30966
31215
  sendNudge: () => sendNudge
30967
31216
  });
30968
- import { writeFileSync as writeFileSync24 } from "fs";
30969
- import path53 from "path";
31217
+ import { writeFileSync as writeFileSync25 } from "fs";
31218
+ import path55 from "path";
30970
31219
  function writeAuditEntry(entry) {
30971
31220
  try {
30972
31221
  const line = JSON.stringify(entry) + "\n";
30973
- writeFileSync24(AUDIT_LOG_PATH, line, { flag: "a" });
31222
+ writeFileSync25(AUDIT_LOG_PATH, line, { flag: "a" });
30974
31223
  } catch {
30975
31224
  }
30976
31225
  }
@@ -31141,7 +31390,7 @@ var init_task_enforcement = __esm({
31141
31390
  "What do you need?"
31142
31391
  ];
31143
31392
  MANAGER_ROLES = ["COO", "CTO"];
31144
- AUDIT_LOG_PATH = path53.join(
31393
+ AUDIT_LOG_PATH = path55.join(
31145
31394
  process.env.HOME ?? process.env.USERPROFILE ?? "/tmp",
31146
31395
  ".exe-os",
31147
31396
  "enforcement-audit.jsonl"
@@ -31163,12 +31412,12 @@ __export(background_jobs_exports, {
31163
31412
  reniceCurrentProcess: () => reniceCurrentProcess,
31164
31413
  startManagedJob: () => startManagedJob
31165
31414
  });
31166
- import { existsSync as existsSync42, mkdirSync as mkdirSync21, readFileSync as readFileSync34, writeFileSync as writeFileSync25, unlinkSync as unlinkSync13 } from "fs";
31415
+ import { existsSync as existsSync44, mkdirSync as mkdirSync22, readFileSync as readFileSync36, writeFileSync as writeFileSync26, unlinkSync as unlinkSync13 } from "fs";
31167
31416
  import { execFileSync as execFileSync3 } from "child_process";
31168
31417
  import os22 from "os";
31169
- import path54 from "path";
31418
+ import path56 from "path";
31170
31419
  function ensureDirs() {
31171
- mkdirSync21(LOCK_DIR, { recursive: true });
31420
+ mkdirSync22(LOCK_DIR, { recursive: true });
31172
31421
  }
31173
31422
  function now() {
31174
31423
  return (/* @__PURE__ */ new Date()).toISOString();
@@ -31184,9 +31433,9 @@ function isAlive(pid) {
31184
31433
  }
31185
31434
  function readJobsRaw() {
31186
31435
  ensureDirs();
31187
- if (!existsSync42(JOBS_FILE)) return [];
31436
+ if (!existsSync44(JOBS_FILE)) return [];
31188
31437
  try {
31189
- const parsed = JSON.parse(readFileSync34(JOBS_FILE, "utf8"));
31438
+ const parsed = JSON.parse(readFileSync36(JOBS_FILE, "utf8"));
31190
31439
  return Array.isArray(parsed) ? parsed : [];
31191
31440
  } catch {
31192
31441
  return [];
@@ -31196,7 +31445,7 @@ function writeJobsRaw(jobs) {
31196
31445
  ensureDirs();
31197
31446
  const running2 = jobs.filter((j) => j.status === "running");
31198
31447
  const rest = jobs.filter((j) => j.status !== "running").slice(-MAX_HISTORY);
31199
- writeFileSync25(JOBS_FILE, JSON.stringify([...rest, ...running2], null, 2) + "\n");
31448
+ writeFileSync26(JOBS_FILE, JSON.stringify([...rest, ...running2], null, 2) + "\n");
31200
31449
  }
31201
31450
  function listBackgroundJobs() {
31202
31451
  const jobs = readJobsRaw();
@@ -31212,14 +31461,14 @@ function listBackgroundJobs() {
31212
31461
  return jobs;
31213
31462
  }
31214
31463
  function lockPath(type) {
31215
- return path54.join(LOCK_DIR, `${type.replace(/[^a-zA-Z0-9_.-]/g, "_")}.lock`);
31464
+ return path56.join(LOCK_DIR, `${type.replace(/[^a-zA-Z0-9_.-]/g, "_")}.lock`);
31216
31465
  }
31217
31466
  function acquireJobLock(type, ttlMs = DEFAULT_LOCK_TTL_MS) {
31218
31467
  ensureDirs();
31219
31468
  const file = lockPath(type);
31220
- if (existsSync42(file)) {
31469
+ if (existsSync44(file)) {
31221
31470
  try {
31222
- const lock = JSON.parse(readFileSync34(file, "utf8"));
31471
+ const lock = JSON.parse(readFileSync36(file, "utf8"));
31223
31472
  const age = Date.now() - Date.parse(lock.updatedAt ?? "");
31224
31473
  if (lock.pid && isAlive(lock.pid) && Number.isFinite(age) && age < ttlMs) return false;
31225
31474
  } catch {
@@ -31230,7 +31479,7 @@ function acquireJobLock(type, ttlMs = DEFAULT_LOCK_TTL_MS) {
31230
31479
  }
31231
31480
  }
31232
31481
  try {
31233
- writeFileSync25(file, JSON.stringify({ pid: process.pid, updatedAt: now() }, null, 2) + "\n", { flag: "wx" });
31482
+ writeFileSync26(file, JSON.stringify({ pid: process.pid, updatedAt: now() }, null, 2) + "\n", { flag: "wx" });
31234
31483
  return true;
31235
31484
  } catch {
31236
31485
  return false;
@@ -31239,8 +31488,8 @@ function acquireJobLock(type, ttlMs = DEFAULT_LOCK_TTL_MS) {
31239
31488
  function releaseJobLock(type) {
31240
31489
  const file = lockPath(type);
31241
31490
  try {
31242
- if (!existsSync42(file)) return;
31243
- const lock = JSON.parse(readFileSync34(file, "utf8"));
31491
+ if (!existsSync44(file)) return;
31492
+ const lock = JSON.parse(readFileSync36(file, "utf8"));
31244
31493
  if (lock.pid === process.pid || !lock.pid || !isAlive(lock.pid)) unlinkSync13(file);
31245
31494
  } catch {
31246
31495
  try {
@@ -31279,7 +31528,7 @@ function startManagedJob(options) {
31279
31528
  writeJobsRaw([...jobs, record]);
31280
31529
  const file = lockPath(options.type);
31281
31530
  try {
31282
- writeFileSync25(file, JSON.stringify({ pid: process.pid, jobId: id, updatedAt: record.updatedAt }, null, 2) + "\n");
31531
+ writeFileSync26(file, JSON.stringify({ pid: process.pid, jobId: id, updatedAt: record.updatedAt }, null, 2) + "\n");
31283
31532
  } catch {
31284
31533
  }
31285
31534
  };
@@ -31439,9 +31688,9 @@ var init_background_jobs = __esm({
31439
31688
  "src/lib/background-jobs.ts"() {
31440
31689
  "use strict";
31441
31690
  init_config();
31442
- JOB_DIR = path54.join(EXE_AI_DIR, "jobs");
31443
- JOBS_FILE = path54.join(JOB_DIR, "jobs.json");
31444
- LOCK_DIR = path54.join(JOB_DIR, "locks");
31691
+ JOB_DIR = path56.join(EXE_AI_DIR, "jobs");
31692
+ JOBS_FILE = path56.join(JOB_DIR, "jobs.json");
31693
+ LOCK_DIR = path56.join(JOB_DIR, "locks");
31445
31694
  DEFAULT_LOCK_TTL_MS = 6 * 60 * 60 * 1e3;
31446
31695
  MAX_HISTORY = 200;
31447
31696
  }
@@ -31455,11 +31704,11 @@ __export(update_check_exports, {
31455
31704
  getRemoteVersion: () => getRemoteVersion
31456
31705
  });
31457
31706
  import { execSync as execSync15 } from "child_process";
31458
- import { readFileSync as readFileSync35 } from "fs";
31459
- import path55 from "path";
31707
+ import { readFileSync as readFileSync37 } from "fs";
31708
+ import path57 from "path";
31460
31709
  function getLocalVersion(packageRoot) {
31461
- const pkgPath = path55.join(packageRoot, "package.json");
31462
- const pkg = JSON.parse(readFileSync35(pkgPath, "utf-8"));
31710
+ const pkgPath = path57.join(packageRoot, "package.json");
31711
+ const pkg = JSON.parse(readFileSync37(pkgPath, "utf-8"));
31463
31712
  return pkg.version;
31464
31713
  }
31465
31714
  function getRemoteVersion() {
@@ -31531,12 +31780,12 @@ __export(device_registry_exports, {
31531
31780
  });
31532
31781
  import crypto22 from "crypto";
31533
31782
  import os23 from "os";
31534
- import { readFileSync as readFileSync36, writeFileSync as writeFileSync26, mkdirSync as mkdirSync22, existsSync as existsSync43 } from "fs";
31535
- import path56 from "path";
31783
+ import { readFileSync as readFileSync38, writeFileSync as writeFileSync27, mkdirSync as mkdirSync23, existsSync as existsSync45 } from "fs";
31784
+ import path58 from "path";
31536
31785
  function getDeviceInfo() {
31537
- if (existsSync43(DEVICE_JSON_PATH)) {
31786
+ if (existsSync45(DEVICE_JSON_PATH)) {
31538
31787
  try {
31539
- const raw = readFileSync36(DEVICE_JSON_PATH, "utf8");
31788
+ const raw = readFileSync38(DEVICE_JSON_PATH, "utf8");
31540
31789
  const data = JSON.parse(raw);
31541
31790
  if (data.deviceId && data.friendlyName && data.hostname) {
31542
31791
  return data;
@@ -31550,14 +31799,14 @@ function getDeviceInfo() {
31550
31799
  friendlyName: hostname.replace(/\./g, "-").toLowerCase(),
31551
31800
  hostname
31552
31801
  };
31553
- mkdirSync22(path56.dirname(DEVICE_JSON_PATH), { recursive: true });
31554
- writeFileSync26(DEVICE_JSON_PATH, JSON.stringify(info, null, 2));
31802
+ mkdirSync23(path58.dirname(DEVICE_JSON_PATH), { recursive: true });
31803
+ writeFileSync27(DEVICE_JSON_PATH, JSON.stringify(info, null, 2));
31555
31804
  return info;
31556
31805
  }
31557
31806
  function setFriendlyName(name) {
31558
31807
  const info = getDeviceInfo();
31559
31808
  info.friendlyName = name;
31560
- writeFileSync26(DEVICE_JSON_PATH, JSON.stringify(info, null, 2));
31809
+ writeFileSync27(DEVICE_JSON_PATH, JSON.stringify(info, null, 2));
31561
31810
  }
31562
31811
  async function resolveTargetDevice(targetAgent, targetProject) {
31563
31812
  const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
@@ -31591,7 +31840,7 @@ var init_device_registry = __esm({
31591
31840
  "src/lib/device-registry.ts"() {
31592
31841
  "use strict";
31593
31842
  init_config();
31594
- DEVICE_JSON_PATH = path56.join(EXE_AI_DIR, "device.json");
31843
+ DEVICE_JSON_PATH = path58.join(EXE_AI_DIR, "device.json");
31595
31844
  }
31596
31845
  });
31597
31846
 
@@ -31807,8 +32056,8 @@ import os24 from "os";
31807
32056
  import net2 from "net";
31808
32057
  import { createServer as createHttpServer } from "http";
31809
32058
  import { randomUUID as randomUUID9 } from "crypto";
31810
- import { appendFileSync as appendFileSync4, writeFileSync as writeFileSync27, unlinkSync as unlinkSync14, mkdirSync as mkdirSync23, existsSync as existsSync44, readFileSync as readFileSync37, chmodSync as chmodSync2 } from "fs";
31811
- import path57 from "path";
32059
+ import { writeFileSync as writeFileSync28, unlinkSync as unlinkSync14, mkdirSync as mkdirSync24, existsSync as existsSync46, readFileSync as readFileSync39, chmodSync as chmodSync2 } from "fs";
32060
+ import path59 from "path";
31812
32061
 
31813
32062
  // src/lib/orchestration-metrics.ts
31814
32063
  init_config();
@@ -31880,8 +32129,9 @@ function initMetrics() {
31880
32129
 
31881
32130
  // src/lib/exe-daemon.ts
31882
32131
  init_memory_write_governor();
31883
- var SOCKET_PATH2 = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ?? path57.join(EXE_AI_DIR, "exed.sock");
31884
- var PID_PATH3 = process.env.EXE_DAEMON_PID ?? process.env.EXE_EMBED_PID ?? path57.join(EXE_AI_DIR, "exed.pid");
32132
+ init_mcp_transport_health();
32133
+ var SOCKET_PATH2 = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ?? path59.join(EXE_AI_DIR, "exed.sock");
32134
+ var PID_PATH4 = process.env.EXE_DAEMON_PID ?? process.env.EXE_EMBED_PID ?? path59.join(EXE_AI_DIR, "exed.pid");
31885
32135
  var MODEL_FILE = "jina-embeddings-v5-small-q4_k_m.gguf";
31886
32136
  var IDLE_TIMEOUT_MS2 = parseInt(process.env.EXE_DAEMON_IDLE_TIMEOUT_MS || "0", 10);
31887
32137
  var REVIEW_POLL_INTERVAL_MS = 60 * 1e3;
@@ -31909,8 +32159,8 @@ function enqueue(queue, entry) {
31909
32159
  queue.push(entry);
31910
32160
  }
31911
32161
  async function loadModel() {
31912
- const modelPath = path57.join(MODELS_DIR, MODEL_FILE);
31913
- if (!existsSync44(modelPath)) {
32162
+ const modelPath = path59.join(MODELS_DIR, MODEL_FILE);
32163
+ if (!existsSync46(modelPath)) {
31914
32164
  process.stderr.write(`[exed] No model at ${modelPath} \u2014 running without embeddings (VPS mode).
31915
32165
  `);
31916
32166
  return;
@@ -32022,7 +32272,7 @@ async function shutdown() {
32022
32272
  } catch {
32023
32273
  }
32024
32274
  try {
32025
- unlinkSync14(PID_PATH3);
32275
+ unlinkSync14(PID_PATH4);
32026
32276
  } catch {
32027
32277
  }
32028
32278
  process.stderr.write("[exed] Shutdown complete.\n");
@@ -32330,17 +32580,17 @@ function startMemoryQueueDrain() {
32330
32580
  `);
32331
32581
  }
32332
32582
  function startServer() {
32333
- mkdirSync23(path57.dirname(SOCKET_PATH2), { recursive: true });
32583
+ mkdirSync24(path59.dirname(SOCKET_PATH2), { recursive: true });
32334
32584
  try {
32335
- chmodSync2(path57.dirname(SOCKET_PATH2), 448);
32585
+ chmodSync2(path59.dirname(SOCKET_PATH2), 448);
32336
32586
  } catch {
32337
32587
  }
32338
32588
  _daemonToken = ensureDaemonToken(process.env[DAEMON_TOKEN_ENV2] ?? null);
32339
32589
  for (const oldFile of ["embed.sock", "embed.pid"]) {
32340
- const oldPath = path57.join(path57.dirname(SOCKET_PATH2), oldFile);
32590
+ const oldPath = path59.join(path59.dirname(SOCKET_PATH2), oldFile);
32341
32591
  try {
32342
32592
  if (oldFile.endsWith(".pid")) {
32343
- const pid = parseInt(readFileSync37(oldPath, "utf8").trim(), 10);
32593
+ const pid = parseInt(readFileSync39(oldPath, "utf8").trim(), 10);
32344
32594
  if (pid > 0) try {
32345
32595
  process.kill(pid, "SIGKILL");
32346
32596
  } catch {
@@ -32463,11 +32713,38 @@ function startServer() {
32463
32713
  }
32464
32714
  async function startMcpHttpServer() {
32465
32715
  try {
32466
- let recordMcpHttpEvent2 = function(event) {
32716
+ let parseDurationMs2 = function(value, fallback, options = {}) {
32717
+ if (!value) return fallback;
32718
+ const parsed = Number.parseInt(value, 10);
32719
+ if (!Number.isFinite(parsed)) return fallback;
32720
+ if (parsed === 0 && options.allowZero) return 0;
32721
+ return parsed > 0 ? parsed : fallback;
32722
+ }, closeMcpSession2 = function(sid, reason) {
32723
+ const transport = transports.get(sid);
32724
+ if (!transport) return;
32725
+ transports.delete(sid);
32726
+ sessionLastSeen.delete(sid);
32727
+ const details = sessionDetails.get(sid);
32728
+ sessionDetails.delete(sid);
32467
32729
  try {
32468
- appendFileSync4(MCP_HTTP_EVENTS_PATH, JSON.stringify({ timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...event }) + "\n");
32730
+ void transport.close();
32469
32731
  } catch {
32470
32732
  }
32733
+ recordMcpHttpEvent({
32734
+ level: reason === "session_expired" ? "warn" : "info",
32735
+ message: reason,
32736
+ sessionId: sid,
32737
+ agentId: details?.agentId,
32738
+ agentRole: details?.agentRole,
32739
+ runtime: details?.runtime,
32740
+ activeSessions: transports.size
32741
+ });
32742
+ }, sweepStaleMcpSessions2 = function() {
32743
+ if (MCP_SESSION_TTL_MS <= 0) return;
32744
+ const now2 = Date.now();
32745
+ for (const [sid, lastSeen] of sessionLastSeen.entries()) {
32746
+ if (now2 - lastSeen > MCP_SESSION_TTL_MS) closeMcpSession2(sid, "session_expired");
32747
+ }
32471
32748
  }, sendJsonRpcError2 = function(res, status, message, extra) {
32472
32749
  res.writeHead(status, { "Content-Type": "application/json" });
32473
32750
  res.end(JSON.stringify({
@@ -32475,9 +32752,9 @@ async function startMcpHttpServer() {
32475
32752
  error: { code: -32e3, message },
32476
32753
  id: null
32477
32754
  }));
32478
- recordMcpHttpEvent2({ level: "warn", message, status, ...extra });
32755
+ recordMcpHttpEvent({ level: "warn", message, status, ...extra });
32479
32756
  };
32480
- var recordMcpHttpEvent = recordMcpHttpEvent2, sendJsonRpcError = sendJsonRpcError2;
32757
+ var parseDurationMs = parseDurationMs2, closeMcpSession = closeMcpSession2, sweepStaleMcpSessions = sweepStaleMcpSessions2, sendJsonRpcError = sendJsonRpcError2;
32481
32758
  const { McpServer } = await import("@modelcontextprotocol/sdk/server/mcp.js");
32482
32759
  const { StreamableHTTPServerTransport } = await import("@modelcontextprotocol/sdk/server/streamableHttp.js");
32483
32760
  const { isInitializeRequest } = await import("@modelcontextprotocol/sdk/types.js");
@@ -32487,7 +32764,12 @@ async function startMcpHttpServer() {
32487
32764
  await initStore2();
32488
32765
  const transports = /* @__PURE__ */ new Map();
32489
32766
  const MCP_HTTP_PORT = parseInt(process.env.EXE_MCP_PORT || "48739", 10);
32490
- const MCP_HTTP_EVENTS_PATH = path57.join(EXE_AI_DIR, "mcp-http-events.jsonl");
32767
+ const MCP_SESSION_TTL_MS = parseDurationMs2(process.env.EXE_MCP_SESSION_TTL_MS, 4 * 60 * 60 * 1e3, { allowZero: true });
32768
+ const MCP_SESSION_SWEEP_MS = parseDurationMs2(process.env.EXE_MCP_SESSION_SWEEP_MS, 60 * 1e3);
32769
+ const sessionLastSeen = /* @__PURE__ */ new Map();
32770
+ const sessionDetails = /* @__PURE__ */ new Map();
32771
+ const sessionSweepTimer = setInterval(sweepStaleMcpSessions2, MCP_SESSION_SWEEP_MS);
32772
+ sessionSweepTimer.unref();
32491
32773
  const httpServer = createHttpServer(async (req, res) => {
32492
32774
  res.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1");
32493
32775
  res.setHeader("Access-Control-Allow-Methods", "POST, GET, DELETE, OPTIONS");
@@ -32498,20 +32780,29 @@ async function startMcpHttpServer() {
32498
32780
  res.end();
32499
32781
  return;
32500
32782
  }
32783
+ const url = new URL(req.url || "/", `http://127.0.0.1:${MCP_HTTP_PORT}`);
32501
32784
  const authHeader = req.headers.authorization;
32502
32785
  if (!authHeader || authHeader !== `Bearer ${_daemonToken}`) {
32503
- res.writeHead(401, { "Content-Type": "text/plain" });
32504
- res.end("Unauthorized");
32786
+ sendJsonRpcError2(res, 401, "Unauthorized: invalid or missing daemon token", {
32787
+ method: req.method,
32788
+ path: url.pathname
32789
+ });
32505
32790
  return;
32506
32791
  }
32507
- const url = new URL(req.url || "/", `http://127.0.0.1:${MCP_HTTP_PORT}`);
32508
32792
  if (url.pathname !== "/mcp") {
32509
- res.writeHead(404, { "Content-Type": "text/plain" });
32510
- res.end("Not Found");
32793
+ sendJsonRpcError2(res, 404, "Not Found: MCP endpoint is /mcp", {
32794
+ method: req.method,
32795
+ path: url.pathname
32796
+ });
32511
32797
  return;
32512
32798
  }
32513
32799
  const agentId = req.headers["x-agent-id"] || "default";
32514
32800
  const agentRole = req.headers["x-agent-role"] || "employee";
32801
+ const runtime = inferMcpRuntime({
32802
+ runtimeHeader: req.headers["x-agent-runtime"] || req.headers["x-runtime"],
32803
+ userAgent: req.headers["user-agent"],
32804
+ agentId
32805
+ });
32515
32806
  let parsedBody;
32516
32807
  try {
32517
32808
  const body = await new Promise((resolve) => {
@@ -32525,6 +32816,9 @@ async function startMcpHttpServer() {
32525
32816
  } catch (err) {
32526
32817
  sendJsonRpcError2(res, 400, "Bad Request: invalid JSON body", {
32527
32818
  method: req.method,
32819
+ agentId,
32820
+ agentRole,
32821
+ runtime,
32528
32822
  error: err instanceof Error ? err.message : String(err)
32529
32823
  });
32530
32824
  return;
@@ -32533,34 +32827,28 @@ async function startMcpHttpServer() {
32533
32827
  let transport;
32534
32828
  if (sessionId && transports.has(sessionId)) {
32535
32829
  transport = transports.get(sessionId);
32830
+ sessionLastSeen.set(sessionId, Date.now());
32536
32831
  } else if (!sessionId && req.method === "POST" && isInitializeRequest(parsedBody)) {
32537
32832
  transport = new StreamableHTTPServerTransport({
32538
32833
  sessionIdGenerator: () => randomUUID9(),
32539
32834
  onsessioninitialized: (sid) => {
32540
32835
  transports.set(sid, transport);
32541
- recordMcpHttpEvent2({
32836
+ sessionLastSeen.set(sid, Date.now());
32837
+ sessionDetails.set(sid, { agentId, agentRole, runtime });
32838
+ recordMcpHttpEvent({
32542
32839
  level: "info",
32543
32840
  message: "session_initialized",
32544
32841
  sessionId: sid,
32545
32842
  agentId,
32546
32843
  agentRole,
32844
+ runtime,
32547
32845
  activeSessions: transports.size
32548
32846
  });
32549
32847
  }
32550
32848
  });
32551
32849
  transport.onclose = () => {
32552
32850
  const sid = Array.from(transports.entries()).find(([, t]) => t === transport)?.[0];
32553
- if (sid) {
32554
- transports.delete(sid);
32555
- recordMcpHttpEvent2({
32556
- level: "info",
32557
- message: "session_closed",
32558
- sessionId: sid,
32559
- agentId,
32560
- agentRole,
32561
- activeSessions: transports.size
32562
- });
32563
- }
32851
+ if (sid) closeMcpSession2(sid, "session_closed");
32564
32852
  };
32565
32853
  const sessionMcp = new McpServer({ name: "exe-os", version: "1.3.0" });
32566
32854
  registerAllTools2(sessionMcp);
@@ -32573,30 +32861,56 @@ async function startMcpHttpServer() {
32573
32861
  sessionId,
32574
32862
  agentId,
32575
32863
  agentRole,
32864
+ runtime,
32576
32865
  activeSessions: transports.size
32577
32866
  });
32578
32867
  return;
32579
32868
  }
32869
+ const startedAt = Date.now();
32870
+ const parsedRequest = parsedBody;
32871
+ const toolName = parsedRequest?.method === "tools/call" ? parsedRequest.params?.name : void 0;
32580
32872
  try {
32581
32873
  await runWithAgent2({ agentId, agentRole }, async () => {
32582
32874
  await transport.handleRequest(req, res, parsedBody);
32583
32875
  });
32584
- recordMcpHttpEvent2({
32876
+ const latencyMs = Date.now() - startedAt;
32877
+ if (sessionId) sessionLastSeen.set(sessionId, Date.now());
32878
+ recordMcpHttpEvent({
32585
32879
  level: "info",
32586
32880
  message: "request_ok",
32587
32881
  method: req.method,
32588
32882
  sessionId: sessionId ?? "new",
32589
32883
  agentId,
32590
- agentRole
32884
+ agentRole,
32885
+ runtime,
32886
+ latencyMs
32591
32887
  });
32888
+ if (toolName) {
32889
+ recordMcpHttpEvent({
32890
+ level: "info",
32891
+ message: "tool_call_ok",
32892
+ method: req.method,
32893
+ sessionId,
32894
+ agentId,
32895
+ agentRole,
32896
+ runtime,
32897
+ toolName,
32898
+ toolFamily: getMcpToolFamily(toolName),
32899
+ latencyMs
32900
+ });
32901
+ }
32592
32902
  } catch (err) {
32593
- recordMcpHttpEvent2({
32903
+ recordMcpHttpEvent({
32594
32904
  level: "error",
32595
32905
  message: "request_failed",
32596
32906
  method: req.method,
32597
32907
  sessionId,
32598
32908
  agentId,
32599
32909
  agentRole,
32910
+ runtime,
32911
+ toolName,
32912
+ toolFamily: getMcpToolFamily(toolName),
32913
+ latencyMs: Date.now() - startedAt,
32600
32914
  error: err instanceof Error ? err.message : String(err)
32601
32915
  });
32602
32916
  if (!res.headersSent) {
@@ -32604,7 +32918,8 @@ async function startMcpHttpServer() {
32604
32918
  method: req.method,
32605
32919
  sessionId,
32606
32920
  agentId,
32607
- agentRole
32921
+ agentRole,
32922
+ runtime
32608
32923
  });
32609
32924
  }
32610
32925
  }
@@ -32612,6 +32927,14 @@ async function startMcpHttpServer() {
32612
32927
  httpServer.listen(MCP_HTTP_PORT, "127.0.0.1", () => {
32613
32928
  process.stderr.write(`[exed] MCP HTTP listening on 127.0.0.1:${MCP_HTTP_PORT}
32614
32929
  `);
32930
+ recordMcpHttpEvent({
32931
+ level: "info",
32932
+ message: "server_started",
32933
+ activeSessions: transports.size
32934
+ });
32935
+ });
32936
+ httpServer.on("close", () => {
32937
+ clearInterval(sessionSweepTimer);
32615
32938
  });
32616
32939
  httpServer.on("error", (err) => {
32617
32940
  if (err.code === "EADDRINUSE") {
@@ -32892,7 +33215,7 @@ function startGraphExtraction() {
32892
33215
  `);
32893
33216
  }
32894
33217
  var AGENT_STATS_INTERVAL_MS = 60 * 1e3;
32895
- var AGENT_STATS_PATH = path57.join(EXE_AI_DIR, "agent-stats.json");
33218
+ var AGENT_STATS_PATH = path59.join(EXE_AI_DIR, "agent-stats.json");
32896
33219
  async function writeAgentStats() {
32897
33220
  fired("agent_stats");
32898
33221
  if (!await ensureStoreForPolling()) return;
@@ -32952,7 +33275,7 @@ async function writeAgentStats() {
32952
33275
  pid: process.pid
32953
33276
  }
32954
33277
  };
32955
- writeFileSync27(AGENT_STATS_PATH, JSON.stringify(stats, null, 2), "utf8");
33278
+ writeFileSync28(AGENT_STATS_PATH, JSON.stringify(stats, null, 2), "utf8");
32956
33279
  } catch (err) {
32957
33280
  process.stderr.write(`[exed] Agent stats error: ${err instanceof Error ? err.message : String(err)}
32958
33281
  `);
@@ -33069,12 +33392,12 @@ function startIntercomQueueDrain() {
33069
33392
  const hasInProgressTask = (session) => {
33070
33393
  try {
33071
33394
  const { baseAgentName: ban } = (init_employees(), __toCommonJS(employees_exports));
33072
- const path58 = __require("path");
33073
- const { existsSync: existsSync45 } = __require("fs");
33395
+ const path60 = __require("path");
33396
+ const { existsSync: existsSync47 } = __require("fs");
33074
33397
  const os25 = __require("os");
33075
33398
  const agent = ban(session.split("-")[0] ?? session);
33076
- const markerPath = path58.join(os25.homedir(), ".exe-os", "session-cache", `current-task-${agent}.json`);
33077
- return existsSync45(markerPath);
33399
+ const markerPath = path60.join(os25.homedir(), ".exe-os", "session-cache", `current-task-${agent}.json`);
33400
+ return existsSync47(markerPath);
33078
33401
  } catch {
33079
33402
  return false;
33080
33403
  }
@@ -33263,12 +33586,12 @@ process.on("SIGINT", () => void shutdown());
33263
33586
  process.on("SIGTERM", () => void shutdown());
33264
33587
  function checkExistingDaemon() {
33265
33588
  try {
33266
- if (!existsSync44(PID_PATH3)) return false;
33267
- const pid = parseInt(readFileSync37(PID_PATH3, "utf8").trim(), 10);
33589
+ if (!existsSync46(PID_PATH4)) return false;
33590
+ const pid = parseInt(readFileSync39(PID_PATH4, "utf8").trim(), 10);
33268
33591
  if (!pid || isNaN(pid)) return false;
33269
33592
  if (pid === process.pid) {
33270
33593
  try {
33271
- unlinkSync14(PID_PATH3);
33594
+ unlinkSync14(PID_PATH4);
33272
33595
  } catch {
33273
33596
  }
33274
33597
  return false;
@@ -33284,7 +33607,7 @@ function checkExistingDaemon() {
33284
33607
  return true;
33285
33608
  }
33286
33609
  try {
33287
- unlinkSync14(PID_PATH3);
33610
+ unlinkSync14(PID_PATH4);
33288
33611
  } catch {
33289
33612
  }
33290
33613
  return false;
@@ -33341,9 +33664,9 @@ function startAutoUpdateCheck() {
33341
33664
  if (checkExistingDaemon()) {
33342
33665
  process.exit(0);
33343
33666
  }
33344
- writeFileSync27(PID_PATH3, String(process.pid));
33667
+ writeFileSync28(PID_PATH4, String(process.pid));
33345
33668
  try {
33346
- chmodSync2(PID_PATH3, 384);
33669
+ chmodSync2(PID_PATH4, 384);
33347
33670
  } catch {
33348
33671
  }
33349
33672
  process.env.EXE_IS_DAEMON = "1";
@@ -33469,7 +33792,7 @@ try {
33469
33792
  } catch {
33470
33793
  }
33471
33794
  try {
33472
- unlinkSync14(PID_PATH3);
33795
+ unlinkSync14(PID_PATH4);
33473
33796
  } catch {
33474
33797
  }
33475
33798
  process.exit(1);