@askexenow/exe-os 0.8.85 → 0.8.87

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/bin/cleanup-stale-review-tasks.js +57 -19
  2. package/dist/bin/cli.js +510 -340
  3. package/dist/bin/exe-agent-config.js +242 -0
  4. package/dist/bin/exe-agent.js +3 -3
  5. package/dist/bin/exe-boot.js +344 -346
  6. package/dist/bin/exe-dispatch.js +375 -250
  7. package/dist/bin/exe-forget.js +5 -1
  8. package/dist/bin/exe-gateway.js +260 -135
  9. package/dist/bin/exe-healthcheck.js +133 -1
  10. package/dist/bin/exe-heartbeat.js +72 -31
  11. package/dist/bin/exe-link.js +25 -2
  12. package/dist/bin/exe-new-employee.js +22 -0
  13. package/dist/bin/exe-pending-messages.js +55 -17
  14. package/dist/bin/exe-pending-reviews.js +57 -19
  15. package/dist/bin/exe-search.js +6 -2
  16. package/dist/bin/exe-session-cleanup.js +260 -135
  17. package/dist/bin/exe-start-codex.js +2598 -0
  18. package/dist/bin/exe-start.sh +15 -3
  19. package/dist/bin/exe-status.js +57 -19
  20. package/dist/bin/git-sweep.js +391 -266
  21. package/dist/bin/install.js +22 -0
  22. package/dist/bin/scan-tasks.js +394 -269
  23. package/dist/bin/setup.js +50 -5
  24. package/dist/gateway/index.js +257 -132
  25. package/dist/hooks/bug-report-worker.js +242 -117
  26. package/dist/hooks/commit-complete.js +389 -264
  27. package/dist/hooks/error-recall.js +6 -2
  28. package/dist/hooks/ingest-worker.js +314 -193
  29. package/dist/hooks/post-compact.js +84 -46
  30. package/dist/hooks/pre-compact.js +272 -147
  31. package/dist/hooks/pre-tool-use.js +104 -66
  32. package/dist/hooks/prompt-submit.js +126 -66
  33. package/dist/hooks/session-end.js +277 -152
  34. package/dist/hooks/session-start.js +70 -28
  35. package/dist/hooks/stop.js +90 -52
  36. package/dist/hooks/subagent-stop.js +84 -46
  37. package/dist/hooks/summary-worker.js +175 -114
  38. package/dist/index.js +296 -171
  39. package/dist/lib/agent-config.js +167 -0
  40. package/dist/lib/cloud-sync.js +25 -2
  41. package/dist/lib/exe-daemon.js +338 -213
  42. package/dist/lib/hybrid-search.js +7 -2
  43. package/dist/lib/messaging.js +95 -39
  44. package/dist/lib/runtime-table.js +16 -0
  45. package/dist/lib/session-wrappers.js +22 -0
  46. package/dist/lib/tasks.js +242 -117
  47. package/dist/lib/tmux-routing.js +314 -189
  48. package/dist/mcp/server.js +573 -274
  49. package/dist/mcp/tools/create-task.js +260 -135
  50. package/dist/mcp/tools/list-tasks.js +68 -30
  51. package/dist/mcp/tools/send-message.js +100 -44
  52. package/dist/mcp/tools/update-task.js +123 -67
  53. package/dist/runtime/index.js +276 -151
  54. package/dist/tui/App.js +479 -354
  55. package/package.json +1 -1
  56. package/src/commands/exe/agent-config.md +27 -0
  57. package/src/commands/exe/cc-doctor.md +10 -0
package/dist/bin/cli.js CHANGED
@@ -4081,10 +4081,18 @@ function buildRosterBlob(paths) {
4081
4081
  } catch {
4082
4082
  }
4083
4083
  }
4084
+ let agentConfig;
4085
+ const agentConfigPath = path9.join(EXE_AI_DIR, "agent-config.json");
4086
+ if (existsSync9(agentConfigPath)) {
4087
+ try {
4088
+ agentConfig = JSON.parse(readFileSync7(agentConfigPath, "utf-8"));
4089
+ } catch {
4090
+ }
4091
+ }
4084
4092
  const deletedNames = consumeRosterDeletions();
4085
- const content = JSON.stringify({ roster, identities, config, deletedNames });
4093
+ const content = JSON.stringify({ roster, identities, config, agentConfig, deletedNames });
4086
4094
  const hash = crypto3.createHash("sha256").update(content).digest("hex").slice(0, 16);
4087
- return { roster, identities, config, deletedNames, version: hash };
4095
+ return { roster, identities, config, agentConfig, deletedNames, version: hash };
4088
4096
  }
4089
4097
  async function cloudPushRoster(config) {
4090
4098
  assertSecureEndpoint(config.endpoint);
@@ -4222,6 +4230,21 @@ async function mergeRosterFromRemote(remote, paths) {
4222
4230
  } catch {
4223
4231
  }
4224
4232
  }
4233
+ if (remote.agentConfig && Object.keys(remote.agentConfig).length > 0) {
4234
+ try {
4235
+ const agentConfigPath = path9.join(EXE_AI_DIR, "agent-config.json");
4236
+ let local = {};
4237
+ if (existsSync9(agentConfigPath)) {
4238
+ try {
4239
+ local = JSON.parse(readFileSync7(agentConfigPath, "utf-8"));
4240
+ } catch {
4241
+ }
4242
+ }
4243
+ const merged = { ...remote.agentConfig, ...local };
4244
+ writeFileSync5(agentConfigPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
4245
+ } catch {
4246
+ }
4247
+ }
4225
4248
  return { added, identitiesUpdated };
4226
4249
  });
4227
4250
  }
@@ -6717,9 +6740,9 @@ Unclassified: ${unclassified}
6717
6740
  }
6718
6741
  async function exportBatches(options) {
6719
6742
  const fs8 = await import("fs");
6720
- const path38 = await import("path");
6743
+ const path39 = await import("path");
6721
6744
  const client = getClient();
6722
- const outDir = path38.join(process.cwd(), "exe/output/classifications/input");
6745
+ const outDir = path39.join(process.cwd(), "exe/output/classifications/input");
6723
6746
  fs8.mkdirSync(outDir, { recursive: true });
6724
6747
  const countResult = await client.execute({
6725
6748
  sql: "SELECT COUNT(*) as cnt FROM memories WHERE intent IS NULL AND outcome IS NULL AND domain IS NULL",
@@ -6743,7 +6766,7 @@ async function exportBatches(options) {
6743
6766
  const text = String(row.text || "").replace(/\n/g, " ");
6744
6767
  return JSON.stringify({ id: row.id, text });
6745
6768
  });
6746
- const batchFile = path38.join(outDir, `batch-${String(batchNum).padStart(4, "0")}.jsonl`);
6769
+ const batchFile = path39.join(outDir, `batch-${String(batchNum).padStart(4, "0")}.jsonl`);
6747
6770
  fs8.writeFileSync(batchFile, lines.join("\n") + "\n");
6748
6771
  exported += batch.rows.length;
6749
6772
  offset += options.batchSize;
@@ -6759,7 +6782,7 @@ async function exportBatches(options) {
6759
6782
  }
6760
6783
  async function importClassifications(importDir) {
6761
6784
  const fs8 = await import("fs");
6762
- const path38 = await import("path");
6785
+ const path39 = await import("path");
6763
6786
  const client = getClient();
6764
6787
  const files = fs8.readdirSync(importDir).filter((f) => f.endsWith(".jsonl")).sort();
6765
6788
  process.stderr.write(`[backfill-metadata] Found ${files.length} JSONL files to import from ${importDir}
@@ -6767,7 +6790,7 @@ async function importClassifications(importDir) {
6767
6790
  let imported = 0;
6768
6791
  let invalid = 0;
6769
6792
  for (const file of files) {
6770
- const lines = fs8.readFileSync(path38.join(importDir, file), "utf-8").split("\n").filter(Boolean);
6793
+ const lines = fs8.readFileSync(path39.join(importDir, file), "utf-8").split("\n").filter(Boolean);
6771
6794
  for (const line of lines) {
6772
6795
  try {
6773
6796
  const rec = JSON.parse(line);
@@ -7156,18 +7179,69 @@ var init_provider_table = __esm({
7156
7179
  }
7157
7180
  });
7158
7181
 
7159
- // src/lib/intercom-queue.ts
7160
- import { readFileSync as readFileSync9, writeFileSync as writeFileSync7, renameSync as renameSync3, existsSync as existsSync12, mkdirSync as mkdirSync8 } from "fs";
7182
+ // src/lib/runtime-table.ts
7183
+ var RUNTIME_TABLE, DEFAULT_RUNTIME;
7184
+ var init_runtime_table = __esm({
7185
+ "src/lib/runtime-table.ts"() {
7186
+ "use strict";
7187
+ RUNTIME_TABLE = {
7188
+ codex: {
7189
+ binary: "codex",
7190
+ launchMode: "exec",
7191
+ autoApproveFlag: "--full-auto",
7192
+ inlineFlag: "--no-alt-screen",
7193
+ apiKeyEnv: "OPENAI_API_KEY",
7194
+ defaultModel: "gpt-5.4"
7195
+ }
7196
+ };
7197
+ DEFAULT_RUNTIME = "claude";
7198
+ }
7199
+ });
7200
+
7201
+ // src/lib/agent-config.ts
7202
+ import { readFileSync as readFileSync9, writeFileSync as writeFileSync7, existsSync as existsSync12, mkdirSync as mkdirSync8 } from "fs";
7161
7203
  import path13 from "path";
7204
+ function loadAgentConfig() {
7205
+ if (!existsSync12(AGENT_CONFIG_PATH)) return {};
7206
+ try {
7207
+ return JSON.parse(readFileSync9(AGENT_CONFIG_PATH, "utf-8"));
7208
+ } catch {
7209
+ return {};
7210
+ }
7211
+ }
7212
+ function getAgentRuntime(agentId) {
7213
+ const config = loadAgentConfig();
7214
+ const entry = config[agentId];
7215
+ if (entry) return entry;
7216
+ return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
7217
+ }
7218
+ var AGENT_CONFIG_PATH, DEFAULT_MODELS;
7219
+ var init_agent_config = __esm({
7220
+ "src/lib/agent-config.ts"() {
7221
+ "use strict";
7222
+ init_config();
7223
+ init_runtime_table();
7224
+ AGENT_CONFIG_PATH = path13.join(EXE_AI_DIR, "agent-config.json");
7225
+ DEFAULT_MODELS = {
7226
+ claude: "claude-opus-4",
7227
+ codex: RUNTIME_TABLE.codex?.defaultModel ?? "gpt-5.4",
7228
+ opencode: "minimax-m2.7"
7229
+ };
7230
+ }
7231
+ });
7232
+
7233
+ // src/lib/intercom-queue.ts
7234
+ import { readFileSync as readFileSync10, writeFileSync as writeFileSync8, renameSync as renameSync3, existsSync as existsSync13, mkdirSync as mkdirSync9 } from "fs";
7235
+ import path14 from "path";
7162
7236
  import os7 from "os";
7163
7237
  function ensureDir() {
7164
- const dir = path13.dirname(QUEUE_PATH);
7165
- if (!existsSync12(dir)) mkdirSync8(dir, { recursive: true });
7238
+ const dir = path14.dirname(QUEUE_PATH);
7239
+ if (!existsSync13(dir)) mkdirSync9(dir, { recursive: true });
7166
7240
  }
7167
7241
  function readQueue() {
7168
7242
  try {
7169
- if (!existsSync12(QUEUE_PATH)) return [];
7170
- return JSON.parse(readFileSync9(QUEUE_PATH, "utf8"));
7243
+ if (!existsSync13(QUEUE_PATH)) return [];
7244
+ return JSON.parse(readFileSync10(QUEUE_PATH, "utf8"));
7171
7245
  } catch {
7172
7246
  return [];
7173
7247
  }
@@ -7175,7 +7249,7 @@ function readQueue() {
7175
7249
  function writeQueue(queue) {
7176
7250
  ensureDir();
7177
7251
  const tmp = `${QUEUE_PATH}.tmp`;
7178
- writeFileSync7(tmp, JSON.stringify(queue, null, 2));
7252
+ writeFileSync8(tmp, JSON.stringify(queue, null, 2));
7179
7253
  renameSync3(tmp, QUEUE_PATH);
7180
7254
  }
7181
7255
  function queueIntercom(targetSession, reason) {
@@ -7199,19 +7273,19 @@ var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
7199
7273
  var init_intercom_queue = __esm({
7200
7274
  "src/lib/intercom-queue.ts"() {
7201
7275
  "use strict";
7202
- QUEUE_PATH = path13.join(os7.homedir(), ".exe-os", "intercom-queue.json");
7276
+ QUEUE_PATH = path14.join(os7.homedir(), ".exe-os", "intercom-queue.json");
7203
7277
  TTL_MS = 60 * 60 * 1e3;
7204
- INTERCOM_LOG = path13.join(os7.homedir(), ".exe-os", "intercom.log");
7278
+ INTERCOM_LOG = path14.join(os7.homedir(), ".exe-os", "intercom.log");
7205
7279
  }
7206
7280
  });
7207
7281
 
7208
7282
  // src/lib/plan-limits.ts
7209
- import { readFileSync as readFileSync10, existsSync as existsSync13 } from "fs";
7210
- import path14 from "path";
7283
+ import { readFileSync as readFileSync11, existsSync as existsSync14 } from "fs";
7284
+ import path15 from "path";
7211
7285
  function getLicenseSync() {
7212
7286
  try {
7213
- if (!existsSync13(CACHE_PATH2)) return freeLicense();
7214
- const raw = JSON.parse(readFileSync10(CACHE_PATH2, "utf8"));
7287
+ if (!existsSync14(CACHE_PATH2)) return freeLicense();
7288
+ const raw = JSON.parse(readFileSync11(CACHE_PATH2, "utf8"));
7215
7289
  if (!raw.token || typeof raw.token !== "string") return freeLicense();
7216
7290
  const parts = raw.token.split(".");
7217
7291
  if (parts.length !== 3) return freeLicense();
@@ -7249,8 +7323,8 @@ function assertEmployeeLimitSync(rosterPath) {
7249
7323
  const filePath = rosterPath ?? EMPLOYEES_PATH;
7250
7324
  let count = 0;
7251
7325
  try {
7252
- if (existsSync13(filePath)) {
7253
- const raw = readFileSync10(filePath, "utf8");
7326
+ if (existsSync14(filePath)) {
7327
+ const raw = readFileSync11(filePath, "utf8");
7254
7328
  const employees = JSON.parse(raw);
7255
7329
  count = Array.isArray(employees) ? employees.length : 0;
7256
7330
  }
@@ -7279,19 +7353,19 @@ var init_plan_limits = __esm({
7279
7353
  this.name = "PlanLimitError";
7280
7354
  }
7281
7355
  };
7282
- CACHE_PATH2 = path14.join(EXE_AI_DIR, "license-cache.json");
7356
+ CACHE_PATH2 = path15.join(EXE_AI_DIR, "license-cache.json");
7283
7357
  }
7284
7358
  });
7285
7359
 
7286
7360
  // src/lib/notifications.ts
7287
7361
  import crypto5 from "crypto";
7288
- import path15 from "path";
7362
+ import path16 from "path";
7289
7363
  import os8 from "os";
7290
7364
  import {
7291
- readFileSync as readFileSync11,
7365
+ readFileSync as readFileSync12,
7292
7366
  readdirSync as readdirSync3,
7293
7367
  unlinkSync as unlinkSync5,
7294
- existsSync as existsSync14,
7368
+ existsSync as existsSync15,
7295
7369
  rmdirSync
7296
7370
  } from "fs";
7297
7371
  async function writeNotification(notification) {
@@ -7416,11 +7490,11 @@ __export(tasks_crud_exports, {
7416
7490
  writeCheckpoint: () => writeCheckpoint
7417
7491
  });
7418
7492
  import crypto7 from "crypto";
7419
- import path16 from "path";
7493
+ import path17 from "path";
7420
7494
  import os9 from "os";
7421
7495
  import { execSync as execSync6 } from "child_process";
7422
7496
  import { mkdir as mkdir5, writeFile as writeFile5, appendFile } from "fs/promises";
7423
- import { existsSync as existsSync15, readFileSync as readFileSync12 } from "fs";
7497
+ import { existsSync as existsSync16, readFileSync as readFileSync13 } from "fs";
7424
7498
  async function writeCheckpoint(input) {
7425
7499
  const client = getClient();
7426
7500
  const row = await resolveTask(client, input.taskId);
@@ -7595,8 +7669,8 @@ ${laneWarning}` : laneWarning;
7595
7669
  }
7596
7670
  if (input.baseDir) {
7597
7671
  try {
7598
- await mkdir5(path16.join(input.baseDir, "exe", "output"), { recursive: true });
7599
- await mkdir5(path16.join(input.baseDir, "exe", "research"), { recursive: true });
7672
+ await mkdir5(path17.join(input.baseDir, "exe", "output"), { recursive: true });
7673
+ await mkdir5(path17.join(input.baseDir, "exe", "research"), { recursive: true });
7600
7674
  await ensureArchitectureDoc(input.baseDir, input.projectName);
7601
7675
  await ensureGitignoreExe(input.baseDir);
7602
7676
  } catch {
@@ -7632,10 +7706,10 @@ ${laneWarning}` : laneWarning;
7632
7706
  });
7633
7707
  if (input.baseDir) {
7634
7708
  try {
7635
- const EXE_OS_DIR = path16.join(os9.homedir(), ".exe-os");
7636
- const mdPath = path16.join(EXE_OS_DIR, taskFile);
7637
- const mdDir = path16.dirname(mdPath);
7638
- if (!existsSync15(mdDir)) await mkdir5(mdDir, { recursive: true });
7709
+ const EXE_OS_DIR = path17.join(os9.homedir(), ".exe-os");
7710
+ const mdPath = path17.join(EXE_OS_DIR, taskFile);
7711
+ const mdDir = path17.dirname(mdPath);
7712
+ if (!existsSync16(mdDir)) await mkdir5(mdDir, { recursive: true });
7639
7713
  const reviewer = input.reviewer ?? input.assignedBy;
7640
7714
  const mdContent = `# ${input.title}
7641
7715
 
@@ -7660,7 +7734,11 @@ If you skip this, your reviewer will not know you're done and your work won't be
7660
7734
  Do NOT let a failed commit or any error prevent you from calling update_task(done).
7661
7735
  `;
7662
7736
  await writeFile5(mdPath, mdContent, "utf-8");
7663
- } catch {
7737
+ } catch (err) {
7738
+ process.stderr.write(
7739
+ `[create-task] WARNING: .md file write failed for ${taskFile}: ${err instanceof Error ? err.message : String(err)}
7740
+ `
7741
+ );
7664
7742
  }
7665
7743
  }
7666
7744
  return {
@@ -7920,9 +7998,9 @@ async function deleteTaskCore(taskId, _baseDir) {
7920
7998
  return { taskFile, assignedTo, assignedBy, taskSlug };
7921
7999
  }
7922
8000
  async function ensureArchitectureDoc(baseDir, projectName) {
7923
- const archPath = path16.join(baseDir, "exe", "ARCHITECTURE.md");
8001
+ const archPath = path17.join(baseDir, "exe", "ARCHITECTURE.md");
7924
8002
  try {
7925
- if (existsSync15(archPath)) return;
8003
+ if (existsSync16(archPath)) return;
7926
8004
  const template = [
7927
8005
  `# ${projectName} \u2014 System Architecture`,
7928
8006
  "",
@@ -7955,10 +8033,10 @@ async function ensureArchitectureDoc(baseDir, projectName) {
7955
8033
  }
7956
8034
  }
7957
8035
  async function ensureGitignoreExe(baseDir) {
7958
- const gitignorePath = path16.join(baseDir, ".gitignore");
8036
+ const gitignorePath = path17.join(baseDir, ".gitignore");
7959
8037
  try {
7960
- if (existsSync15(gitignorePath)) {
7961
- const content = readFileSync12(gitignorePath, "utf-8");
8038
+ if (existsSync16(gitignorePath)) {
8039
+ const content = readFileSync13(gitignorePath, "utf-8");
7962
8040
  if (/^\/?exe\/?$/m.test(content)) return;
7963
8041
  await appendFile(gitignorePath, "\n# Employee task assignments (private)\n/exe/\n");
7964
8042
  } else {
@@ -7989,8 +8067,8 @@ var init_tasks_crud = __esm({
7989
8067
  });
7990
8068
 
7991
8069
  // src/lib/tasks-review.ts
7992
- import path17 from "path";
7993
- import { existsSync as existsSync16, readdirSync as readdirSync4, unlinkSync as unlinkSync6 } from "fs";
8070
+ import path18 from "path";
8071
+ import { existsSync as existsSync17, readdirSync as readdirSync4, unlinkSync as unlinkSync6 } from "fs";
7994
8072
  async function countPendingReviews(sessionScope) {
7995
8073
  const client = getClient();
7996
8074
  if (sessionScope) {
@@ -8171,11 +8249,11 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
8171
8249
  );
8172
8250
  }
8173
8251
  try {
8174
- const cacheDir = path17.join(EXE_AI_DIR, "session-cache");
8175
- if (existsSync16(cacheDir)) {
8252
+ const cacheDir = path18.join(EXE_AI_DIR, "session-cache");
8253
+ if (existsSync17(cacheDir)) {
8176
8254
  for (const f of readdirSync4(cacheDir)) {
8177
8255
  if (f.startsWith("review-notified-")) {
8178
- unlinkSync6(path17.join(cacheDir, f));
8256
+ unlinkSync6(path18.join(cacheDir, f));
8179
8257
  }
8180
8258
  }
8181
8259
  }
@@ -8196,7 +8274,7 @@ var init_tasks_review = __esm({
8196
8274
  });
8197
8275
 
8198
8276
  // src/lib/tasks-chain.ts
8199
- import path18 from "path";
8277
+ import path19 from "path";
8200
8278
  import { readFile as readFile5, writeFile as writeFile6 } from "fs/promises";
8201
8279
  async function cascadeUnblock(taskId, baseDir, now) {
8202
8280
  const client = getClient();
@@ -8213,7 +8291,7 @@ async function cascadeUnblock(taskId, baseDir, now) {
8213
8291
  });
8214
8292
  for (const ur of unblockedRows.rows) {
8215
8293
  try {
8216
- const ubFile = path18.join(baseDir, String(ur.task_file));
8294
+ const ubFile = path19.join(baseDir, String(ur.task_file));
8217
8295
  let ubContent = await readFile5(ubFile, "utf-8");
8218
8296
  ubContent = ubContent.replace(/\*\*Status:\*\* blocked/, "**Status:** open");
8219
8297
  ubContent = ubContent.replace(/\n\*\*Blocked by:\*\*.*\n/, "\n");
@@ -8282,7 +8360,7 @@ var init_tasks_chain = __esm({
8282
8360
 
8283
8361
  // src/lib/project-name.ts
8284
8362
  import { execSync as execSync7 } from "child_process";
8285
- import path19 from "path";
8363
+ import path20 from "path";
8286
8364
  function getProjectName(cwd2) {
8287
8365
  const dir = cwd2 ?? process.cwd();
8288
8366
  if (_cached2 && _cachedCwd === dir) return _cached2;
@@ -8295,7 +8373,7 @@ function getProjectName(cwd2) {
8295
8373
  timeout: 2e3,
8296
8374
  stdio: ["pipe", "pipe", "pipe"]
8297
8375
  }).trim();
8298
- repoRoot = path19.dirname(gitCommonDir);
8376
+ repoRoot = path20.dirname(gitCommonDir);
8299
8377
  } catch {
8300
8378
  repoRoot = execSync7("git rev-parse --show-toplevel", {
8301
8379
  cwd: dir,
@@ -8304,11 +8382,11 @@ function getProjectName(cwd2) {
8304
8382
  stdio: ["pipe", "pipe", "pipe"]
8305
8383
  }).trim();
8306
8384
  }
8307
- _cached2 = path19.basename(repoRoot);
8385
+ _cached2 = path20.basename(repoRoot);
8308
8386
  _cachedCwd = dir;
8309
8387
  return _cached2;
8310
8388
  } catch {
8311
- _cached2 = path19.basename(dir);
8389
+ _cached2 = path20.basename(dir);
8312
8390
  _cachedCwd = dir;
8313
8391
  return _cached2;
8314
8392
  }
@@ -8781,8 +8859,8 @@ __export(tasks_exports, {
8781
8859
  updateTaskStatus: () => updateTaskStatus,
8782
8860
  writeCheckpoint: () => writeCheckpoint
8783
8861
  });
8784
- import path20 from "path";
8785
- import { writeFileSync as writeFileSync8, mkdirSync as mkdirSync9, unlinkSync as unlinkSync7 } from "fs";
8862
+ import path21 from "path";
8863
+ import { writeFileSync as writeFileSync9, mkdirSync as mkdirSync10, unlinkSync as unlinkSync7 } from "fs";
8786
8864
  async function createTask(input) {
8787
8865
  const result = await createTaskCore(input);
8788
8866
  if (!input.skipDispatch && result.status !== "blocked" && !process.env.VITEST) {
@@ -8801,11 +8879,11 @@ async function updateTask(input) {
8801
8879
  const { row, taskFile, now, taskId } = await updateTaskStatus(input);
8802
8880
  try {
8803
8881
  const agent = String(row.assigned_to);
8804
- const cacheDir = path20.join(EXE_AI_DIR, "session-cache");
8805
- const cachePath = path20.join(cacheDir, `current-task-${agent}.json`);
8882
+ const cacheDir = path21.join(EXE_AI_DIR, "session-cache");
8883
+ const cachePath = path21.join(cacheDir, `current-task-${agent}.json`);
8806
8884
  if (input.status === "in_progress") {
8807
- mkdirSync9(cacheDir, { recursive: true });
8808
- writeFileSync8(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
8885
+ mkdirSync10(cacheDir, { recursive: true });
8886
+ writeFileSync9(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
8809
8887
  } else if (input.status === "done" || input.status === "blocked" || input.status === "cancelled") {
8810
8888
  try {
8811
8889
  unlinkSync7(cachePath);
@@ -9272,13 +9350,13 @@ __export(tmux_routing_exports, {
9272
9350
  verifyPaneAtCapacity: () => verifyPaneAtCapacity
9273
9351
  });
9274
9352
  import { execFileSync as execFileSync2, execSync as execSync8 } from "child_process";
9275
- import { readFileSync as readFileSync13, writeFileSync as writeFileSync9, mkdirSync as mkdirSync10, existsSync as existsSync17, appendFileSync as appendFileSync2 } from "fs";
9276
- import path21 from "path";
9353
+ import { readFileSync as readFileSync14, writeFileSync as writeFileSync10, mkdirSync as mkdirSync11, existsSync as existsSync18, appendFileSync as appendFileSync2 } from "fs";
9354
+ import path22 from "path";
9277
9355
  import os10 from "os";
9278
9356
  import { fileURLToPath as fileURLToPath4 } from "url";
9279
9357
  import { unlinkSync as unlinkSync8 } from "fs";
9280
9358
  function spawnLockPath(sessionName) {
9281
- return path21.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
9359
+ return path22.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
9282
9360
  }
9283
9361
  function isProcessAlive(pid) {
9284
9362
  try {
@@ -9289,13 +9367,13 @@ function isProcessAlive(pid) {
9289
9367
  }
9290
9368
  }
9291
9369
  function acquireSpawnLock2(sessionName) {
9292
- if (!existsSync17(SPAWN_LOCK_DIR)) {
9293
- mkdirSync10(SPAWN_LOCK_DIR, { recursive: true });
9370
+ if (!existsSync18(SPAWN_LOCK_DIR)) {
9371
+ mkdirSync11(SPAWN_LOCK_DIR, { recursive: true });
9294
9372
  }
9295
9373
  const lockFile = spawnLockPath(sessionName);
9296
- if (existsSync17(lockFile)) {
9374
+ if (existsSync18(lockFile)) {
9297
9375
  try {
9298
- const lock = JSON.parse(readFileSync13(lockFile, "utf8"));
9376
+ const lock = JSON.parse(readFileSync14(lockFile, "utf8"));
9299
9377
  const age = Date.now() - lock.timestamp;
9300
9378
  if (isProcessAlive(lock.pid) && age < 6e4) {
9301
9379
  return false;
@@ -9303,7 +9381,7 @@ function acquireSpawnLock2(sessionName) {
9303
9381
  } catch {
9304
9382
  }
9305
9383
  }
9306
- writeFileSync9(lockFile, JSON.stringify({ pid: process.pid, timestamp: Date.now() }));
9384
+ writeFileSync10(lockFile, JSON.stringify({ pid: process.pid, timestamp: Date.now() }));
9307
9385
  return true;
9308
9386
  }
9309
9387
  function releaseSpawnLock2(sessionName) {
@@ -9315,13 +9393,13 @@ function releaseSpawnLock2(sessionName) {
9315
9393
  function resolveBehaviorsExporterScript() {
9316
9394
  try {
9317
9395
  const thisFile = fileURLToPath4(import.meta.url);
9318
- const scriptPath = path21.join(
9319
- path21.dirname(thisFile),
9396
+ const scriptPath = path22.join(
9397
+ path22.dirname(thisFile),
9320
9398
  "..",
9321
9399
  "bin",
9322
9400
  "exe-export-behaviors.js"
9323
9401
  );
9324
- return existsSync17(scriptPath) ? scriptPath : null;
9402
+ return existsSync18(scriptPath) ? scriptPath : null;
9325
9403
  } catch {
9326
9404
  return null;
9327
9405
  }
@@ -9387,12 +9465,12 @@ function extractRootExe(name) {
9387
9465
  return parts.length > 0 ? parts[parts.length - 1] : null;
9388
9466
  }
9389
9467
  function registerParentExe(sessionKey, parentExe, dispatchedBy) {
9390
- if (!existsSync17(SESSION_CACHE)) {
9391
- mkdirSync10(SESSION_CACHE, { recursive: true });
9468
+ if (!existsSync18(SESSION_CACHE)) {
9469
+ mkdirSync11(SESSION_CACHE, { recursive: true });
9392
9470
  }
9393
9471
  const rootExe = extractRootExe(parentExe) ?? parentExe;
9394
- const filePath = path21.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
9395
- writeFileSync9(filePath, JSON.stringify({
9472
+ const filePath = path22.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
9473
+ writeFileSync10(filePath, JSON.stringify({
9396
9474
  parentExe: rootExe,
9397
9475
  dispatchedBy: dispatchedBy || rootExe,
9398
9476
  registeredAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -9400,7 +9478,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
9400
9478
  }
9401
9479
  function getParentExe(sessionKey) {
9402
9480
  try {
9403
- const data = JSON.parse(readFileSync13(path21.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
9481
+ const data = JSON.parse(readFileSync14(path22.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
9404
9482
  return data.parentExe || null;
9405
9483
  } catch {
9406
9484
  return null;
@@ -9408,8 +9486,8 @@ function getParentExe(sessionKey) {
9408
9486
  }
9409
9487
  function getDispatchedBy(sessionKey) {
9410
9488
  try {
9411
- const data = JSON.parse(readFileSync13(
9412
- path21.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
9489
+ const data = JSON.parse(readFileSync14(
9490
+ path22.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
9413
9491
  "utf8"
9414
9492
  ));
9415
9493
  return data.dispatchedBy ?? data.parentExe ?? null;
@@ -9470,32 +9548,50 @@ async function verifyPaneAtCapacity(sessionName) {
9470
9548
  }
9471
9549
  function readDebounceState() {
9472
9550
  try {
9473
- if (!existsSync17(DEBOUNCE_FILE)) return {};
9474
- return JSON.parse(readFileSync13(DEBOUNCE_FILE, "utf8"));
9551
+ if (!existsSync18(DEBOUNCE_FILE)) return {};
9552
+ const raw = JSON.parse(readFileSync14(DEBOUNCE_FILE, "utf8"));
9553
+ const state = {};
9554
+ for (const [key, val] of Object.entries(raw)) {
9555
+ if (typeof val === "number") {
9556
+ state[key] = { lastSent: val, pending: 0 };
9557
+ } else if (val && typeof val === "object" && "lastSent" in val) {
9558
+ state[key] = val;
9559
+ }
9560
+ }
9561
+ return state;
9475
9562
  } catch {
9476
9563
  return {};
9477
9564
  }
9478
9565
  }
9479
9566
  function writeDebounceState(state) {
9480
9567
  try {
9481
- if (!existsSync17(SESSION_CACHE)) mkdirSync10(SESSION_CACHE, { recursive: true });
9482
- writeFileSync9(DEBOUNCE_FILE, JSON.stringify(state));
9568
+ if (!existsSync18(SESSION_CACHE)) mkdirSync11(SESSION_CACHE, { recursive: true });
9569
+ writeFileSync10(DEBOUNCE_FILE, JSON.stringify(state));
9483
9570
  } catch {
9484
9571
  }
9485
9572
  }
9486
9573
  function isDebounced(targetSession) {
9487
9574
  const state = readDebounceState();
9488
- const lastSent = state[targetSession] ?? 0;
9489
- return Date.now() - lastSent < INTERCOM_DEBOUNCE_MS;
9575
+ const entry = state[targetSession];
9576
+ const lastSent = entry?.lastSent ?? 0;
9577
+ if (Date.now() - lastSent < INTERCOM_DEBOUNCE_MS) {
9578
+ if (!state[targetSession]) state[targetSession] = { lastSent, pending: 0 };
9579
+ state[targetSession].pending++;
9580
+ writeDebounceState(state);
9581
+ return true;
9582
+ }
9583
+ return false;
9490
9584
  }
9491
9585
  function recordDebounce(targetSession) {
9492
9586
  const state = readDebounceState();
9493
- state[targetSession] = Date.now();
9587
+ const batched = state[targetSession]?.pending ?? 0;
9588
+ state[targetSession] = { lastSent: Date.now(), pending: 0 };
9494
9589
  const cutoff = Date.now() - DEBOUNCE_CLEANUP_AGE_MS;
9495
9590
  for (const key of Object.keys(state)) {
9496
- if ((state[key] ?? 0) < cutoff) delete state[key];
9591
+ if ((state[key]?.lastSent ?? 0) < cutoff) delete state[key];
9497
9592
  }
9498
9593
  writeDebounceState(state);
9594
+ return batched;
9499
9595
  }
9500
9596
  function logIntercom(msg) {
9501
9597
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${msg}
@@ -9540,7 +9636,7 @@ function sendIntercom(targetSession) {
9540
9636
  return "skipped_exe";
9541
9637
  }
9542
9638
  if (isDebounced(targetSession)) {
9543
- logIntercom(`DEBOUNCE \u2192 ${targetSession} (cross-process file debounce)`);
9639
+ logIntercom(`DEBOUNCE \u2192 ${targetSession} (nudge batched, task safe in DB)`);
9544
9640
  return "debounced";
9545
9641
  }
9546
9642
  try {
@@ -9552,14 +9648,14 @@ function sendIntercom(targetSession) {
9552
9648
  const sessionState = getSessionState(targetSession);
9553
9649
  if (sessionState === "no_claude") {
9554
9650
  queueIntercom(targetSession, "claude not running in session");
9555
- recordDebounce(targetSession);
9556
- logIntercom(`QUEUED \u2192 ${targetSession} (no claude process \u2014 raw shell detected)`);
9651
+ const batched2 = recordDebounce(targetSession);
9652
+ logIntercom(`QUEUED \u2192 ${targetSession} (no claude process)${batched2 > 0 ? ` [${batched2} batched]` : ""}`);
9557
9653
  return "queued";
9558
9654
  }
9559
9655
  if (sessionState === "thinking" || sessionState === "tool") {
9560
9656
  queueIntercom(targetSession, "session busy at send time");
9561
- recordDebounce(targetSession);
9562
- logIntercom(`QUEUED \u2192 ${targetSession} (session busy, will retry from queue)`);
9657
+ const batched2 = recordDebounce(targetSession);
9658
+ logIntercom(`QUEUED \u2192 ${targetSession} (session busy)${batched2 > 0 ? ` [${batched2} batched]` : ""}`);
9563
9659
  return "queued";
9564
9660
  }
9565
9661
  if (transport.isPaneInCopyMode(targetSession)) {
@@ -9567,8 +9663,8 @@ function sendIntercom(targetSession) {
9567
9663
  transport.sendKeys(targetSession, "q");
9568
9664
  }
9569
9665
  transport.sendKeys(targetSession, "/exe-intercom");
9570
- recordDebounce(targetSession);
9571
- logIntercom(`DELIVERED \u2192 ${targetSession} (fire-and-forget)`);
9666
+ const batched = recordDebounce(targetSession);
9667
+ logIntercom(`DELIVERED \u2192 ${targetSession}${batched > 0 ? ` [${batched} nudges batched during debounce]` : ""} (fire-and-forget)`);
9572
9668
  return "delivered";
9573
9669
  } catch {
9574
9670
  logIntercom(`FAIL \u2192 ${targetSession}`);
@@ -9670,26 +9766,26 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
9670
9766
  const transport = getTransport();
9671
9767
  const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
9672
9768
  const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
9673
- const logDir = path21.join(os10.homedir(), ".exe-os", "session-logs");
9674
- const logFile = path21.join(logDir, `${instanceLabel}-${Date.now()}.log`);
9675
- if (!existsSync17(logDir)) {
9676
- mkdirSync10(logDir, { recursive: true });
9769
+ const logDir = path22.join(os10.homedir(), ".exe-os", "session-logs");
9770
+ const logFile = path22.join(logDir, `${instanceLabel}-${Date.now()}.log`);
9771
+ if (!existsSync18(logDir)) {
9772
+ mkdirSync11(logDir, { recursive: true });
9677
9773
  }
9678
9774
  transport.kill(sessionName);
9679
9775
  let cleanupSuffix = "";
9680
9776
  try {
9681
9777
  const thisFile = fileURLToPath4(import.meta.url);
9682
- const cleanupScript = path21.join(path21.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
9683
- if (existsSync17(cleanupScript)) {
9778
+ const cleanupScript = path22.join(path22.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
9779
+ if (existsSync18(cleanupScript)) {
9684
9780
  cleanupSuffix = `; ${process.execPath} "${cleanupScript}" "${employeeName}" "${exeSession}"`;
9685
9781
  }
9686
9782
  } catch {
9687
9783
  }
9688
9784
  try {
9689
- const claudeJsonPath = path21.join(os10.homedir(), ".claude.json");
9785
+ const claudeJsonPath = path22.join(os10.homedir(), ".claude.json");
9690
9786
  let claudeJson = {};
9691
9787
  try {
9692
- claudeJson = JSON.parse(readFileSync13(claudeJsonPath, "utf8"));
9788
+ claudeJson = JSON.parse(readFileSync14(claudeJsonPath, "utf8"));
9693
9789
  } catch {
9694
9790
  }
9695
9791
  if (!claudeJson.projects) claudeJson.projects = {};
@@ -9697,17 +9793,17 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
9697
9793
  const trustDir = opts?.cwd ?? projectDir;
9698
9794
  if (!projects[trustDir]) projects[trustDir] = {};
9699
9795
  projects[trustDir].hasTrustDialogAccepted = true;
9700
- writeFileSync9(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
9796
+ writeFileSync10(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
9701
9797
  } catch {
9702
9798
  }
9703
9799
  try {
9704
- const settingsDir = path21.join(os10.homedir(), ".claude", "projects");
9800
+ const settingsDir = path22.join(os10.homedir(), ".claude", "projects");
9705
9801
  const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
9706
- const projSettingsDir = path21.join(settingsDir, normalizedKey);
9707
- const settingsPath = path21.join(projSettingsDir, "settings.json");
9802
+ const projSettingsDir = path22.join(settingsDir, normalizedKey);
9803
+ const settingsPath = path22.join(projSettingsDir, "settings.json");
9708
9804
  let settings = {};
9709
9805
  try {
9710
- settings = JSON.parse(readFileSync13(settingsPath, "utf8"));
9806
+ settings = JSON.parse(readFileSync14(settingsPath, "utf8"));
9711
9807
  } catch {
9712
9808
  }
9713
9809
  const perms = settings.permissions ?? {};
@@ -9735,20 +9831,23 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
9735
9831
  if (changed) {
9736
9832
  perms.allow = allow;
9737
9833
  settings.permissions = perms;
9738
- mkdirSync10(projSettingsDir, { recursive: true });
9739
- writeFileSync9(settingsPath, JSON.stringify(settings, null, 2) + "\n");
9834
+ mkdirSync11(projSettingsDir, { recursive: true });
9835
+ writeFileSync10(settingsPath, JSON.stringify(settings, null, 2) + "\n");
9740
9836
  }
9741
9837
  } catch {
9742
9838
  }
9743
9839
  const spawnCwd = opts?.cwd ?? projectDir;
9744
9840
  const useExeAgent = !!(opts?.model && opts?.provider);
9745
- const ccProvider = useExeAgent ? DEFAULT_PROVIDER : detectActiveProvider();
9841
+ const agentRtConfig = getAgentRuntime(employeeName);
9842
+ const useCodex = !useExeAgent && agentRtConfig.runtime === "codex";
9843
+ const useOpencode = !useExeAgent && !useCodex && agentRtConfig.runtime === "opencode";
9844
+ const ccProvider = useExeAgent || useCodex || useOpencode ? DEFAULT_PROVIDER : detectActiveProvider();
9746
9845
  const useBinSymlink = ccProvider !== DEFAULT_PROVIDER;
9747
9846
  let identityFlag = "";
9748
9847
  let behaviorsFlag = "";
9749
9848
  let legacyFallbackWarned = false;
9750
9849
  if (!useExeAgent && !useBinSymlink) {
9751
- const identityPath2 = path21.join(
9850
+ const identityPath2 = path22.join(
9752
9851
  os10.homedir(),
9753
9852
  ".exe-os",
9754
9853
  "identity",
@@ -9758,13 +9857,13 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
9758
9857
  const hasAgentFlag = claudeSupportsAgentFlag();
9759
9858
  if (hasAgentFlag) {
9760
9859
  identityFlag = ` --agent ${employeeName}`;
9761
- } else if (existsSync17(identityPath2)) {
9860
+ } else if (existsSync18(identityPath2)) {
9762
9861
  identityFlag = ` --append-system-prompt-file ${identityPath2}`;
9763
9862
  legacyFallbackWarned = true;
9764
9863
  }
9765
9864
  const behaviorsFile = exportBehaviorsSync(
9766
9865
  employeeName,
9767
- path21.basename(spawnCwd),
9866
+ path22.basename(spawnCwd),
9768
9867
  sessionName
9769
9868
  );
9770
9869
  if (behaviorsFile) {
@@ -9779,16 +9878,16 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
9779
9878
  }
9780
9879
  let sessionContextFlag = "";
9781
9880
  try {
9782
- const ctxDir = path21.join(os10.homedir(), ".exe-os", "session-cache");
9783
- mkdirSync10(ctxDir, { recursive: true });
9784
- const ctxFile = path21.join(ctxDir, `session-context-${sessionName}.md`);
9881
+ const ctxDir = path22.join(os10.homedir(), ".exe-os", "session-cache");
9882
+ mkdirSync11(ctxDir, { recursive: true });
9883
+ const ctxFile = path22.join(ctxDir, `session-context-${sessionName}.md`);
9785
9884
  const ctxContent = [
9786
9885
  `## Session Context`,
9787
9886
  `You are running in tmux session: ${sessionName}.`,
9788
9887
  `Your parent coordinator session is ${exeSession}.`,
9789
9888
  `Your employees (if any) use the -${exeSession} suffix.`
9790
9889
  ].join("\n");
9791
- writeFileSync9(ctxFile, ctxContent);
9890
+ writeFileSync10(ctxFile, ctxContent);
9792
9891
  sessionContextFlag = ` --append-system-prompt-file ${ctxFile}`;
9793
9892
  } catch {
9794
9893
  }
@@ -9802,9 +9901,48 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
9802
9901
  }
9803
9902
  }
9804
9903
  }
9904
+ if (useCodex) {
9905
+ const codexCfg = RUNTIME_TABLE.codex;
9906
+ if (codexCfg?.apiKeyEnv) {
9907
+ const keyVal = process.env[codexCfg.apiKeyEnv];
9908
+ if (keyVal) {
9909
+ envPrefix = `${envPrefix} ${codexCfg.apiKeyEnv}=${keyVal}`;
9910
+ }
9911
+ }
9912
+ envPrefix = `${envPrefix} EXE_AGENT_MODEL=${agentRtConfig.model}`;
9913
+ }
9914
+ if (useOpencode) {
9915
+ const ocCfg = PROVIDER_TABLE.opencode;
9916
+ if (ocCfg?.apiKeyEnv) {
9917
+ const keyVal = process.env[ocCfg.apiKeyEnv];
9918
+ if (keyVal) {
9919
+ envPrefix = `${envPrefix} ${ocCfg.apiKeyEnv}=${keyVal}`;
9920
+ }
9921
+ }
9922
+ envPrefix = `${envPrefix} ANTHROPIC_MODEL=${agentRtConfig.model}`;
9923
+ }
9924
+ if (!useExeAgent && !useCodex && !useOpencode && !useBinSymlink) {
9925
+ const defaultClaudeModel = DEFAULT_MODELS.claude;
9926
+ if (agentRtConfig.runtime === "claude" && agentRtConfig.model !== defaultClaudeModel) {
9927
+ envPrefix = `${envPrefix} ANTHROPIC_MODEL=${agentRtConfig.model}`;
9928
+ }
9929
+ }
9805
9930
  let spawnCommand;
9806
9931
  if (useExeAgent) {
9807
9932
  spawnCommand = `${envPrefix} exe-agent --employee ${employeeName} --model ${opts.model} --provider ${opts.provider}${cleanupSuffix}`;
9933
+ } else if (useCodex) {
9934
+ process.stderr.write(
9935
+ `[tmux-routing] agent-config: ${employeeName} \u2192 codex (${agentRtConfig.model})
9936
+ `
9937
+ );
9938
+ spawnCommand = `${envPrefix} exe-start-codex --agent ${employeeName}${cleanupSuffix}`;
9939
+ } else if (useOpencode) {
9940
+ const binName = `${employeeName}-opencode`;
9941
+ process.stderr.write(
9942
+ `[tmux-routing] agent-config: ${employeeName} \u2192 opencode (${agentRtConfig.model})
9943
+ `
9944
+ );
9945
+ spawnCommand = `${envPrefix} ${binName}${cleanupSuffix}`;
9808
9946
  } else if (useBinSymlink) {
9809
9947
  const binName = `${employeeName}-${ccProvider}`;
9810
9948
  process.stderr.write(
@@ -9826,11 +9964,13 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
9826
9964
  transport.pipeLog(sessionName, logFile);
9827
9965
  try {
9828
9966
  const mySession = getMySession();
9829
- const dispatchInfo = path21.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
9830
- writeFileSync9(dispatchInfo, JSON.stringify({
9967
+ const dispatchInfo = path22.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
9968
+ writeFileSync10(dispatchInfo, JSON.stringify({
9831
9969
  dispatchedBy: mySession,
9832
9970
  rootExe: exeSession,
9833
- provider: useBinSymlink ? ccProvider : useExeAgent ? opts.provider : "anthropic",
9971
+ provider: useBinSymlink ? ccProvider : useExeAgent ? opts.provider : useCodex ? "openai" : useOpencode ? "opencode" : "anthropic",
9972
+ runtime: useCodex ? "codex" : useOpencode ? "opencode" : useExeAgent ? "exe-agent" : "claude",
9973
+ model: useCodex ? agentRtConfig.model : useOpencode ? agentRtConfig.model : void 0,
9834
9974
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
9835
9975
  }));
9836
9976
  } catch {
@@ -9848,6 +9988,11 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
9848
9988
  booted = true;
9849
9989
  break;
9850
9990
  }
9991
+ } else if (useCodex) {
9992
+ if (pane.includes("codex") || pane.includes("Codex") || pane.includes("exe-start-codex")) {
9993
+ booted = true;
9994
+ break;
9995
+ }
9851
9996
  } else {
9852
9997
  if (pane.includes("Claude Code") || pane.includes("\u276F")) {
9853
9998
  booted = true;
@@ -9859,9 +10004,10 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
9859
10004
  }
9860
10005
  if (!booted) {
9861
10006
  releaseSpawnLock2(sessionName);
9862
- return { sessionName, error: `${useExeAgent ? "exe-agent" : "claude"} did not boot within 15s` };
10007
+ const runtimeLabel = useExeAgent ? "exe-agent" : useCodex ? "codex" : "claude";
10008
+ return { sessionName, error: `${runtimeLabel} did not boot within 15s` };
9863
10009
  }
9864
- if (!useExeAgent) {
10010
+ if (!useExeAgent && !useCodex) {
9865
10011
  try {
9866
10012
  transport.sendKeys(sessionName, `/exe-call ${employeeName}`);
9867
10013
  } catch {
@@ -9888,17 +10034,19 @@ var init_tmux_routing = __esm({
9888
10034
  init_cc_agent_support();
9889
10035
  init_mcp_prefix();
9890
10036
  init_provider_table();
10037
+ init_agent_config();
10038
+ init_runtime_table();
9891
10039
  init_intercom_queue();
9892
10040
  init_plan_limits();
9893
10041
  init_employees();
9894
- SPAWN_LOCK_DIR = path21.join(os10.homedir(), ".exe-os", "spawn-locks");
9895
- SESSION_CACHE = path21.join(os10.homedir(), ".exe-os", "session-cache");
10042
+ SPAWN_LOCK_DIR = path22.join(os10.homedir(), ".exe-os", "spawn-locks");
10043
+ SESSION_CACHE = path22.join(os10.homedir(), ".exe-os", "session-cache");
9896
10044
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
9897
10045
  VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
9898
10046
  VERIFY_PANE_LINES = 200;
9899
10047
  INTERCOM_DEBOUNCE_MS = 3e4;
9900
- INTERCOM_LOG2 = path21.join(os10.homedir(), ".exe-os", "intercom.log");
9901
- DEBOUNCE_FILE = path21.join(SESSION_CACHE, "intercom-debounce.json");
10048
+ INTERCOM_LOG2 = path22.join(os10.homedir(), ".exe-os", "intercom.log");
10049
+ DEBOUNCE_FILE = path22.join(SESSION_CACHE, "intercom-debounce.json");
9902
10050
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
9903
10051
  BUSY_PATTERN = /[✻✽✶✳·].*…|Running…/;
9904
10052
  }
@@ -10173,9 +10321,9 @@ __export(active_agent_exports, {
10173
10321
  resolveActiveAgentFromTmuxSession: () => resolveActiveAgentFromTmuxSession,
10174
10322
  writeActiveAgent: () => writeActiveAgent
10175
10323
  });
10176
- import { readFileSync as readFileSync14, writeFileSync as writeFileSync10, mkdirSync as mkdirSync11, unlinkSync as unlinkSync9, readdirSync as readdirSync5 } from "fs";
10324
+ import { readFileSync as readFileSync15, writeFileSync as writeFileSync11, mkdirSync as mkdirSync12, unlinkSync as unlinkSync9, readdirSync as readdirSync5 } from "fs";
10177
10325
  import { execSync as execSync9 } from "child_process";
10178
- import path22 from "path";
10326
+ import path23 from "path";
10179
10327
  function isNameWithOptionalInstance(candidate, baseName) {
10180
10328
  if (candidate === baseName) return true;
10181
10329
  if (!candidate.startsWith(baseName)) return false;
@@ -10219,12 +10367,12 @@ function resolveActiveAgentFromTmuxSession(sessionName) {
10219
10367
  return null;
10220
10368
  }
10221
10369
  function getMarkerPath() {
10222
- return path22.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
10370
+ return path23.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
10223
10371
  }
10224
10372
  function writeActiveAgent(agentId, agentRole) {
10225
10373
  try {
10226
- mkdirSync11(CACHE_DIR, { recursive: true });
10227
- writeFileSync10(
10374
+ mkdirSync12(CACHE_DIR, { recursive: true });
10375
+ writeFileSync11(
10228
10376
  getMarkerPath(),
10229
10377
  JSON.stringify({ agentId, agentRole, startedAt: (/* @__PURE__ */ new Date()).toISOString() })
10230
10378
  );
@@ -10240,7 +10388,7 @@ function clearActiveAgent() {
10240
10388
  function getActiveAgent() {
10241
10389
  try {
10242
10390
  const markerPath = getMarkerPath();
10243
- const raw = readFileSync14(markerPath, "utf8");
10391
+ const raw = readFileSync15(markerPath, "utf8");
10244
10392
  const data = JSON.parse(raw);
10245
10393
  if (data.agentId) {
10246
10394
  if (data.startedAt) {
@@ -10288,14 +10436,14 @@ function getAllActiveAgents() {
10288
10436
  const key = file.slice("active-agent-".length, -".json".length);
10289
10437
  if (key === "undefined") continue;
10290
10438
  try {
10291
- const raw = readFileSync14(path22.join(CACHE_DIR, file), "utf8");
10439
+ const raw = readFileSync15(path23.join(CACHE_DIR, file), "utf8");
10292
10440
  const data = JSON.parse(raw);
10293
10441
  if (!data.agentId) continue;
10294
10442
  if (data.startedAt) {
10295
10443
  const age = Date.now() - new Date(data.startedAt).getTime();
10296
10444
  if (age > STALE_MS) {
10297
10445
  try {
10298
- unlinkSync9(path22.join(CACHE_DIR, file));
10446
+ unlinkSync9(path23.join(CACHE_DIR, file));
10299
10447
  } catch {
10300
10448
  }
10301
10449
  continue;
@@ -10318,11 +10466,11 @@ function getAllActiveAgents() {
10318
10466
  function cleanupSessionMarkers() {
10319
10467
  const key = getSessionKey();
10320
10468
  try {
10321
- unlinkSync9(path22.join(CACHE_DIR, `active-agent-${key}.json`));
10469
+ unlinkSync9(path23.join(CACHE_DIR, `active-agent-${key}.json`));
10322
10470
  } catch {
10323
10471
  }
10324
10472
  try {
10325
- unlinkSync9(path22.join(CACHE_DIR, "active-agent-undefined.json"));
10473
+ unlinkSync9(path23.join(CACHE_DIR, "active-agent-undefined.json"));
10326
10474
  } catch {
10327
10475
  }
10328
10476
  }
@@ -10333,7 +10481,7 @@ var init_active_agent = __esm({
10333
10481
  init_config();
10334
10482
  init_session_key2();
10335
10483
  init_employees();
10336
- CACHE_DIR = path22.join(EXE_AI_DIR, "session-cache");
10484
+ CACHE_DIR = path23.join(EXE_AI_DIR, "session-cache");
10337
10485
  STALE_MS = 24 * 60 * 60 * 1e3;
10338
10486
  }
10339
10487
  });
@@ -10961,14 +11109,14 @@ __export(exe_rename_exports, {
10961
11109
  main: () => main2,
10962
11110
  renameEmployee: () => renameEmployee
10963
11111
  });
10964
- import { readFileSync as readFileSync15, writeFileSync as writeFileSync11, renameSync as renameSync4, unlinkSync as unlinkSync10, existsSync as existsSync18 } from "fs";
11112
+ import { readFileSync as readFileSync16, writeFileSync as writeFileSync12, renameSync as renameSync4, unlinkSync as unlinkSync10, existsSync as existsSync19 } from "fs";
10965
11113
  import { execSync as execSync10 } from "child_process";
10966
- import path23 from "path";
11114
+ import path24 from "path";
10967
11115
  import { homedir as homedir4 } from "os";
10968
11116
  async function renameEmployee(oldName, newName, opts = {}) {
10969
- const rosterPath = opts.rosterPath ?? path23.join(homedir4(), ".exe-os", "exe-employees.json");
10970
- const identityDir = opts.identityDir ?? path23.join(homedir4(), ".exe-os", "identity");
10971
- const agentsDir = opts.agentsDir ?? path23.join(homedir4(), ".claude", "agents");
11117
+ const rosterPath = opts.rosterPath ?? path24.join(homedir4(), ".exe-os", "exe-employees.json");
11118
+ const identityDir = opts.identityDir ?? path24.join(homedir4(), ".exe-os", "identity");
11119
+ const agentsDir = opts.agentsDir ?? path24.join(homedir4(), ".claude", "agents");
10972
11120
  const validation = validateEmployeeName(newName);
10973
11121
  if (!validation.valid) {
10974
11122
  return { success: false, error: validation.error };
@@ -10997,40 +11145,40 @@ async function renameEmployee(oldName, newName, opts = {}) {
10997
11145
  undo: () => {
10998
11146
  employee.name = originalName;
10999
11147
  employee.systemPrompt = originalPrompt;
11000
- writeFileSync11(rosterPath, JSON.stringify(employees, null, 2) + "\n", "utf-8");
11148
+ writeFileSync12(rosterPath, JSON.stringify(employees, null, 2) + "\n", "utf-8");
11001
11149
  }
11002
11150
  });
11003
- const oldIdentityPath = path23.join(identityDir, `${rosterOldName}.md`);
11004
- const newIdentityPath = path23.join(identityDir, `${newName}.md`);
11005
- if (existsSync18(oldIdentityPath)) {
11006
- const content = readFileSync15(oldIdentityPath, "utf-8");
11151
+ const oldIdentityPath = path24.join(identityDir, `${rosterOldName}.md`);
11152
+ const newIdentityPath = path24.join(identityDir, `${newName}.md`);
11153
+ if (existsSync19(oldIdentityPath)) {
11154
+ const content = readFileSync16(oldIdentityPath, "utf-8");
11007
11155
  const updatedContent = content.replace(
11008
11156
  /^(agent_id:\s*)\S+/m,
11009
11157
  `$1${newName}`
11010
11158
  );
11011
11159
  renameSync4(oldIdentityPath, newIdentityPath);
11012
- writeFileSync11(newIdentityPath, updatedContent, "utf-8");
11160
+ writeFileSync12(newIdentityPath, updatedContent, "utf-8");
11013
11161
  rollbackStack.push({
11014
11162
  description: "restore identity file",
11015
11163
  undo: () => {
11016
- if (existsSync18(newIdentityPath)) {
11017
- writeFileSync11(newIdentityPath, content, "utf-8");
11164
+ if (existsSync19(newIdentityPath)) {
11165
+ writeFileSync12(newIdentityPath, content, "utf-8");
11018
11166
  renameSync4(newIdentityPath, oldIdentityPath);
11019
11167
  }
11020
11168
  }
11021
11169
  });
11022
11170
  }
11023
- const oldAgentPath = path23.join(agentsDir, `${rosterOldName}.md`);
11024
- const newAgentPath = path23.join(agentsDir, `${newName}.md`);
11025
- if (existsSync18(oldAgentPath)) {
11026
- const agentContent = readFileSync15(oldAgentPath, "utf-8");
11171
+ const oldAgentPath = path24.join(agentsDir, `${rosterOldName}.md`);
11172
+ const newAgentPath = path24.join(agentsDir, `${newName}.md`);
11173
+ if (existsSync19(oldAgentPath)) {
11174
+ const agentContent = readFileSync16(oldAgentPath, "utf-8");
11027
11175
  renameSync4(oldAgentPath, newAgentPath);
11028
11176
  rollbackStack.push({
11029
11177
  description: "restore agent file",
11030
11178
  undo: () => {
11031
- if (existsSync18(newAgentPath)) {
11179
+ if (existsSync19(newAgentPath)) {
11032
11180
  renameSync4(newAgentPath, oldAgentPath);
11033
- writeFileSync11(oldAgentPath, agentContent, "utf-8");
11181
+ writeFileSync12(oldAgentPath, agentContent, "utf-8");
11034
11182
  }
11035
11183
  }
11036
11184
  });
@@ -11108,10 +11256,10 @@ function removeOldSymlinks(name) {
11108
11256
  try {
11109
11257
  const exeBinPath = findExeBin2();
11110
11258
  if (!exeBinPath) return;
11111
- const binDir = path23.dirname(exeBinPath);
11259
+ const binDir = path24.dirname(exeBinPath);
11112
11260
  for (const suffix of ["", "-opencode"]) {
11113
- const linkPath = path23.join(binDir, `${name}${suffix}`);
11114
- if (existsSync18(linkPath)) {
11261
+ const linkPath = path24.join(binDir, `${name}${suffix}`);
11262
+ if (existsSync19(linkPath)) {
11115
11263
  try {
11116
11264
  unlinkSync10(linkPath);
11117
11265
  } catch {
@@ -11156,16 +11304,16 @@ var init_exe_rename = __esm({
11156
11304
  });
11157
11305
 
11158
11306
  // src/lib/model-downloader.ts
11159
- import { createWriteStream, createReadStream as createReadStream2, existsSync as existsSync19, unlinkSync as unlinkSync11, renameSync as renameSync5 } from "fs";
11307
+ import { createWriteStream, createReadStream as createReadStream2, existsSync as existsSync20, unlinkSync as unlinkSync11, renameSync as renameSync5 } from "fs";
11160
11308
  import { mkdir as mkdir6 } from "fs/promises";
11161
11309
  import { createHash as createHash2 } from "crypto";
11162
- import path24 from "path";
11310
+ import path25 from "path";
11163
11311
  async function downloadModel(opts) {
11164
11312
  const { destDir, onProgress, fetchFn = globalThis.fetch } = opts;
11165
- const destPath = path24.join(destDir, LOCAL_FILENAME);
11313
+ const destPath = path25.join(destDir, LOCAL_FILENAME);
11166
11314
  const tmpPath = destPath + ".tmp";
11167
11315
  await mkdir6(destDir, { recursive: true });
11168
- if (existsSync19(destPath)) {
11316
+ if (existsSync20(destPath)) {
11169
11317
  const hash = await fileHash(destPath);
11170
11318
  if (hash === EXPECTED_SHA256) {
11171
11319
  return destPath;
@@ -11177,7 +11325,7 @@ async function downloadModel(opts) {
11177
11325
  let downloaded = 0;
11178
11326
  for (let attempt = 1; attempt <= MAX_RETRIES3; attempt++) {
11179
11327
  try {
11180
- if (existsSync19(tmpPath)) unlinkSync11(tmpPath);
11328
+ if (existsSync20(tmpPath)) unlinkSync11(tmpPath);
11181
11329
  const response = await fetchFn(GGUF_URL, {
11182
11330
  redirect: "follow",
11183
11331
  signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS)
@@ -11222,7 +11370,7 @@ async function downloadModel(opts) {
11222
11370
  process.stderr.write(`
11223
11371
  Download attempt ${attempt} failed, retrying...
11224
11372
  `);
11225
- if (existsSync19(tmpPath)) unlinkSync11(tmpPath);
11373
+ if (existsSync20(tmpPath)) unlinkSync11(tmpPath);
11226
11374
  }
11227
11375
  }
11228
11376
  }
@@ -11285,10 +11433,10 @@ async function disposeEmbedder() {
11285
11433
  async function embedDirect(text) {
11286
11434
  const llamaCpp = await import("node-llama-cpp");
11287
11435
  const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
11288
- const { existsSync: existsSync25 } = await import("fs");
11289
- const path38 = await import("path");
11290
- const modelPath = path38.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
11291
- if (!existsSync25(modelPath)) {
11436
+ const { existsSync: existsSync26 } = await import("fs");
11437
+ const path39 = await import("path");
11438
+ const modelPath = path39.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
11439
+ if (!existsSync26(modelPath)) {
11292
11440
  throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
11293
11441
  }
11294
11442
  const llama = await llamaCpp.getLlama();
@@ -11325,17 +11473,17 @@ __export(identity_exports, {
11325
11473
  listIdentities: () => listIdentities,
11326
11474
  updateIdentity: () => updateIdentity
11327
11475
  });
11328
- import { existsSync as existsSync20, mkdirSync as mkdirSync12, readFileSync as readFileSync16, writeFileSync as writeFileSync12 } from "fs";
11476
+ import { existsSync as existsSync21, mkdirSync as mkdirSync13, readFileSync as readFileSync17, writeFileSync as writeFileSync13 } from "fs";
11329
11477
  import { readdirSync as readdirSync6 } from "fs";
11330
- import path25 from "path";
11478
+ import path26 from "path";
11331
11479
  import { createHash as createHash3 } from "crypto";
11332
11480
  function ensureDir2() {
11333
- if (!existsSync20(IDENTITY_DIR)) {
11334
- mkdirSync12(IDENTITY_DIR, { recursive: true });
11481
+ if (!existsSync21(IDENTITY_DIR)) {
11482
+ mkdirSync13(IDENTITY_DIR, { recursive: true });
11335
11483
  }
11336
11484
  }
11337
11485
  function identityPath(agentId) {
11338
- return path25.join(IDENTITY_DIR, `${agentId}.md`);
11486
+ return path26.join(IDENTITY_DIR, `${agentId}.md`);
11339
11487
  }
11340
11488
  function parseFrontmatter(raw) {
11341
11489
  const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
@@ -11376,8 +11524,8 @@ function contentHash(content) {
11376
11524
  }
11377
11525
  function getIdentity(agentId) {
11378
11526
  const filePath = identityPath(agentId);
11379
- if (!existsSync20(filePath)) return null;
11380
- const raw = readFileSync16(filePath, "utf-8");
11527
+ if (!existsSync21(filePath)) return null;
11528
+ const raw = readFileSync17(filePath, "utf-8");
11381
11529
  const { frontmatter, body } = parseFrontmatter(raw);
11382
11530
  return {
11383
11531
  agentId,
@@ -11391,7 +11539,7 @@ async function updateIdentity(agentId, content, updatedBy) {
11391
11539
  ensureDir2();
11392
11540
  const filePath = identityPath(agentId);
11393
11541
  const hash = contentHash(content);
11394
- writeFileSync12(filePath, content, "utf-8");
11542
+ writeFileSync13(filePath, content, "utf-8");
11395
11543
  try {
11396
11544
  const client = getClient();
11397
11545
  await client.execute({
@@ -11447,7 +11595,7 @@ var init_identity = __esm({
11447
11595
  "use strict";
11448
11596
  init_config();
11449
11597
  init_database();
11450
- IDENTITY_DIR = path25.join(EXE_AI_DIR, "identity");
11598
+ IDENTITY_DIR = path26.join(EXE_AI_DIR, "identity");
11451
11599
  }
11452
11600
  });
11453
11601
 
@@ -11987,36 +12135,36 @@ __export(session_wrappers_exports, {
11987
12135
  generateSessionWrappers: () => generateSessionWrappers
11988
12136
  });
11989
12137
  import {
11990
- existsSync as existsSync21,
11991
- readFileSync as readFileSync17,
11992
- writeFileSync as writeFileSync13,
11993
- mkdirSync as mkdirSync13,
12138
+ existsSync as existsSync22,
12139
+ readFileSync as readFileSync18,
12140
+ writeFileSync as writeFileSync14,
12141
+ mkdirSync as mkdirSync14,
11994
12142
  chmodSync,
11995
12143
  readdirSync as readdirSync7,
11996
12144
  unlinkSync as unlinkSync12
11997
12145
  } from "fs";
11998
- import path26 from "path";
12146
+ import path27 from "path";
11999
12147
  import { homedir as homedir5 } from "os";
12000
12148
  function generateSessionWrappers(packageRoot, homeDir) {
12001
12149
  const home = homeDir ?? homedir5();
12002
- const binDir = path26.join(home, ".exe-os", "bin");
12003
- const rosterPath = path26.join(home, ".exe-os", "exe-employees.json");
12004
- mkdirSync13(binDir, { recursive: true });
12005
- const exeStartDst = path26.join(binDir, "exe-start");
12150
+ const binDir = path27.join(home, ".exe-os", "bin");
12151
+ const rosterPath = path27.join(home, ".exe-os", "exe-employees.json");
12152
+ mkdirSync14(binDir, { recursive: true });
12153
+ const exeStartDst = path27.join(binDir, "exe-start");
12006
12154
  const candidates = [
12007
- path26.join(packageRoot, "dist", "bin", "exe-start.sh"),
12008
- path26.join(packageRoot, "src", "bin", "exe-start.sh")
12155
+ path27.join(packageRoot, "dist", "bin", "exe-start.sh"),
12156
+ path27.join(packageRoot, "src", "bin", "exe-start.sh")
12009
12157
  ];
12010
12158
  for (const src of candidates) {
12011
- if (existsSync21(src)) {
12012
- writeFileSync13(exeStartDst, readFileSync17(src));
12159
+ if (existsSync22(src)) {
12160
+ writeFileSync14(exeStartDst, readFileSync18(src));
12013
12161
  chmodSync(exeStartDst, 493);
12014
12162
  break;
12015
12163
  }
12016
12164
  }
12017
12165
  let employees = [];
12018
12166
  try {
12019
- employees = JSON.parse(readFileSync17(rosterPath, "utf8"));
12167
+ employees = JSON.parse(readFileSync18(rosterPath, "utf8"));
12020
12168
  } catch {
12021
12169
  return { created: 0, pathConfigured: false };
12022
12170
  }
@@ -12026,9 +12174,9 @@ function generateSessionWrappers(packageRoot, homeDir) {
12026
12174
  try {
12027
12175
  for (const f of readdirSync7(binDir)) {
12028
12176
  if (f === "exe-start") continue;
12029
- const fPath = path26.join(binDir, f);
12177
+ const fPath = path27.join(binDir, f);
12030
12178
  try {
12031
- const content = readFileSync17(fPath, "utf8");
12179
+ const content = readFileSync18(fPath, "utf8");
12032
12180
  if (content.includes("exe-start")) {
12033
12181
  unlinkSync12(fPath);
12034
12182
  }
@@ -12043,8 +12191,30 @@ exec "${exeStartDst}" "$0" "$@"
12043
12191
  `;
12044
12192
  for (const emp of employees) {
12045
12193
  for (let n = 1; n <= MAX_N; n++) {
12046
- const wrapperPath = path26.join(binDir, `${emp.name}${n}`);
12047
- writeFileSync13(wrapperPath, wrapperContent);
12194
+ const wrapperPath = path27.join(binDir, `${emp.name}${n}`);
12195
+ writeFileSync14(wrapperPath, wrapperContent);
12196
+ chmodSync(wrapperPath, 493);
12197
+ created++;
12198
+ }
12199
+ }
12200
+ const codexLauncherCandidates = [
12201
+ path27.join(packageRoot, "dist", "bin", "exe-start-codex.js"),
12202
+ path27.join(packageRoot, "src", "bin", "exe-start-codex.ts")
12203
+ ];
12204
+ let codexLauncher = null;
12205
+ for (const c of codexLauncherCandidates) {
12206
+ if (existsSync22(c)) {
12207
+ codexLauncher = c;
12208
+ break;
12209
+ }
12210
+ }
12211
+ if (codexLauncher) {
12212
+ for (const emp of employees) {
12213
+ const wrapperPath = path27.join(binDir, `${emp.name}-codex`);
12214
+ const content = `#!/bin/bash
12215
+ exec node "${codexLauncher}" --agent ${emp.name} "$@"
12216
+ `;
12217
+ writeFileSync14(wrapperPath, content);
12048
12218
  chmodSync(wrapperPath, 493);
12049
12219
  created++;
12050
12220
  }
@@ -12063,24 +12233,24 @@ export PATH="${binDir}:$PATH"
12063
12233
  const shell = process.env.SHELL ?? "/bin/bash";
12064
12234
  const profilePaths = [];
12065
12235
  if (shell.includes("zsh")) {
12066
- profilePaths.push(path26.join(home, ".zshrc"));
12236
+ profilePaths.push(path27.join(home, ".zshrc"));
12067
12237
  } else if (shell.includes("bash")) {
12068
- profilePaths.push(path26.join(home, ".bashrc"));
12069
- profilePaths.push(path26.join(home, ".bash_profile"));
12238
+ profilePaths.push(path27.join(home, ".bashrc"));
12239
+ profilePaths.push(path27.join(home, ".bash_profile"));
12070
12240
  } else {
12071
- profilePaths.push(path26.join(home, ".profile"));
12241
+ profilePaths.push(path27.join(home, ".profile"));
12072
12242
  }
12073
12243
  for (const profilePath of profilePaths) {
12074
12244
  try {
12075
12245
  let content = "";
12076
12246
  try {
12077
- content = readFileSync17(profilePath, "utf8");
12247
+ content = readFileSync18(profilePath, "utf8");
12078
12248
  } catch {
12079
12249
  }
12080
12250
  if (content.includes(".exe-os/bin")) {
12081
12251
  return false;
12082
12252
  }
12083
- writeFileSync13(profilePath, content + exportLine);
12253
+ writeFileSync14(profilePath, content + exportLine);
12084
12254
  return true;
12085
12255
  } catch {
12086
12256
  continue;
@@ -12103,36 +12273,36 @@ __export(setup_wizard_exports, {
12103
12273
  validateModel: () => validateModel
12104
12274
  });
12105
12275
  import crypto11 from "crypto";
12106
- import { existsSync as existsSync22, mkdirSync as mkdirSync14, readFileSync as readFileSync18, writeFileSync as writeFileSync14, unlinkSync as unlinkSync13 } from "fs";
12276
+ import { existsSync as existsSync23, mkdirSync as mkdirSync15, readFileSync as readFileSync19, writeFileSync as writeFileSync15, unlinkSync as unlinkSync13 } from "fs";
12107
12277
  import os11 from "os";
12108
- import path27 from "path";
12278
+ import path28 from "path";
12109
12279
  import { createInterface as createInterface3 } from "readline";
12110
12280
  function findPackageRoot2() {
12111
- let dir = path27.dirname(new URL(import.meta.url).pathname);
12112
- const root = path27.parse(dir).root;
12281
+ let dir = path28.dirname(new URL(import.meta.url).pathname);
12282
+ const root = path28.parse(dir).root;
12113
12283
  while (dir !== root) {
12114
- const pkgPath = path27.join(dir, "package.json");
12115
- if (existsSync22(pkgPath)) {
12284
+ const pkgPath = path28.join(dir, "package.json");
12285
+ if (existsSync23(pkgPath)) {
12116
12286
  try {
12117
- const pkg = JSON.parse(readFileSync18(pkgPath, "utf-8"));
12287
+ const pkg = JSON.parse(readFileSync19(pkgPath, "utf-8"));
12118
12288
  if (pkg.name === "@askexenow/exe-os" || pkg.name === "exe-os") return dir;
12119
12289
  } catch {
12120
12290
  }
12121
12291
  }
12122
- dir = path27.dirname(dir);
12292
+ dir = path28.dirname(dir);
12123
12293
  }
12124
12294
  return null;
12125
12295
  }
12126
12296
  function loadSetupState() {
12127
12297
  try {
12128
- return JSON.parse(readFileSync18(SETUP_STATE_PATH, "utf8"));
12298
+ return JSON.parse(readFileSync19(SETUP_STATE_PATH, "utf8"));
12129
12299
  } catch {
12130
12300
  return { completedSteps: [], startedAt: (/* @__PURE__ */ new Date()).toISOString() };
12131
12301
  }
12132
12302
  }
12133
12303
  function saveSetupState(state) {
12134
- mkdirSync14(path27.dirname(SETUP_STATE_PATH), { recursive: true });
12135
- writeFileSync14(SETUP_STATE_PATH, JSON.stringify(state, null, 2));
12304
+ mkdirSync15(path28.dirname(SETUP_STATE_PATH), { recursive: true });
12305
+ writeFileSync15(SETUP_STATE_PATH, JSON.stringify(state, null, 2));
12136
12306
  }
12137
12307
  function clearSetupState() {
12138
12308
  try {
@@ -12230,7 +12400,7 @@ async function runSetupWizard(opts = {}) {
12230
12400
  if (state.completedSteps.length > 0) {
12231
12401
  log(`Resuming setup from step ${Math.max(...state.completedSteps) + 1}...`);
12232
12402
  }
12233
- if (existsSync22(LEGACY_LANCE_PATH)) {
12403
+ if (existsSync23(LEGACY_LANCE_PATH)) {
12234
12404
  log("\u26A0 Found v1.0 LanceDB at ~/.exe-os/local.lance");
12235
12405
  log(" v1.1 uses libSQL (SQLite). Your existing memories are not automatically migrated.");
12236
12406
  log(" The old directory will not be modified or deleted.");
@@ -12266,7 +12436,7 @@ async function runSetupWizard(opts = {}) {
12266
12436
  log("backed up on Exe Cloud. Free for all plans. We can't read your data \u2014");
12267
12437
  log("only your encryption key can decrypt it.");
12268
12438
  log("");
12269
- const existingKey = await ask2(rl, "Do you have an existing API key? (paste it, or press Enter to skip): ");
12439
+ const existingKey = await ask2(rl, "Paste your Exe OS license key, or press Enter to start as a free user: ");
12270
12440
  if (existingKey && existingKey.startsWith("exe_sk_")) {
12271
12441
  const cloudEndpoint = "https://askexe.com/cloud";
12272
12442
  try {
@@ -12378,10 +12548,10 @@ async function runSetupWizard(opts = {}) {
12378
12548
  await saveConfig(config);
12379
12549
  log("");
12380
12550
  try {
12381
- const claudeJsonPath = path27.join(os11.homedir(), ".claude.json");
12551
+ const claudeJsonPath = path28.join(os11.homedir(), ".claude.json");
12382
12552
  let claudeJson = {};
12383
12553
  try {
12384
- claudeJson = JSON.parse(readFileSync18(claudeJsonPath, "utf8"));
12554
+ claudeJson = JSON.parse(readFileSync19(claudeJsonPath, "utf8"));
12385
12555
  } catch {
12386
12556
  }
12387
12557
  if (!claudeJson.projects) claudeJson.projects = {};
@@ -12390,7 +12560,7 @@ async function runSetupWizard(opts = {}) {
12390
12560
  if (!projects[dir]) projects[dir] = {};
12391
12561
  projects[dir].hasTrustDialogAccepted = true;
12392
12562
  }
12393
- writeFileSync14(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
12563
+ writeFileSync15(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
12394
12564
  } catch {
12395
12565
  }
12396
12566
  state.completedSteps.push(5);
@@ -12429,7 +12599,7 @@ async function runSetupWizard(opts = {}) {
12429
12599
  let missingIdentities = [];
12430
12600
  for (const emp of roster) {
12431
12601
  const idPath = identityPath2(emp.name);
12432
- if (!existsSync22(idPath)) {
12602
+ if (!existsSync23(idPath)) {
12433
12603
  missingIdentities.push(emp.name);
12434
12604
  }
12435
12605
  }
@@ -12461,7 +12631,7 @@ async function runSetupWizard(opts = {}) {
12461
12631
  }
12462
12632
  missingIdentities = [];
12463
12633
  for (const emp of roster) {
12464
- if (!existsSync22(identityPath2(emp.name))) {
12634
+ if (!existsSync23(identityPath2(emp.name))) {
12465
12635
  missingIdentities.push(emp.name);
12466
12636
  }
12467
12637
  }
@@ -12518,9 +12688,9 @@ async function runSetupWizard(opts = {}) {
12518
12688
  const cooIdentityContent = getIdentityTemplate("coo");
12519
12689
  if (cooIdentityContent) {
12520
12690
  const cooIdPath = identityPath2(cooName);
12521
- mkdirSync14(path27.dirname(cooIdPath), { recursive: true });
12691
+ mkdirSync15(path28.dirname(cooIdPath), { recursive: true });
12522
12692
  const replaced = cooIdentityContent.replace(/agent_id:\s*exe/g, `agent_id: ${cooName}`).replace(/\$\{agent_id\}/g, cooName);
12523
- writeFileSync14(cooIdPath, replaced, "utf-8");
12693
+ writeFileSync15(cooIdPath, replaced, "utf-8");
12524
12694
  }
12525
12695
  registerBinSymlinks2(cooName);
12526
12696
  createdEmployees.push({ name: cooName, role: "COO" });
@@ -12542,7 +12712,7 @@ async function runSetupWizard(opts = {}) {
12542
12712
  }
12543
12713
  let isLicensed = license.valid && license.plan !== "free";
12544
12714
  if (!isLicensed) {
12545
- let licenseInput = await ask2(rl, "Do you have an Exe OS license key? (press Enter to skip for free plan): ");
12715
+ let licenseInput = await ask2(rl, "Hire other employees with your Exe OS license key, or press Enter to continue as a free user (COO only): ");
12546
12716
  if (licenseInput && !licenseInput.startsWith("exe_sk_")) {
12547
12717
  log("That doesn't look like a license key (should start with exe_sk_).");
12548
12718
  licenseInput = await ask2(rl, "Try again (or press Enter to skip): ");
@@ -12614,9 +12784,9 @@ async function runSetupWizard(opts = {}) {
12614
12784
  const ctoIdentityContent = getIdentityTemplate("cto");
12615
12785
  if (ctoIdentityContent) {
12616
12786
  const ctoIdPath = identityPath2(ctoName);
12617
- mkdirSync14(path27.dirname(ctoIdPath), { recursive: true });
12787
+ mkdirSync15(path28.dirname(ctoIdPath), { recursive: true });
12618
12788
  const replaced = ctoIdentityContent.replace(/agent_id:\s*\w+/g, `agent_id: ${ctoName}`).replace(/\$\{agent_id\}/g, ctoName);
12619
- writeFileSync14(ctoIdPath, replaced, "utf-8");
12789
+ writeFileSync15(ctoIdPath, replaced, "utf-8");
12620
12790
  }
12621
12791
  registerBinSymlinks2(ctoName);
12622
12792
  createdEmployees.push({ name: ctoName, role: "CTO" });
@@ -12637,9 +12807,9 @@ async function runSetupWizard(opts = {}) {
12637
12807
  const cmoIdentityContent = getIdentityTemplate("cmo");
12638
12808
  if (cmoIdentityContent) {
12639
12809
  const cmoIdPath = identityPath2(cmoName);
12640
- mkdirSync14(path27.dirname(cmoIdPath), { recursive: true });
12810
+ mkdirSync15(path28.dirname(cmoIdPath), { recursive: true });
12641
12811
  const replaced = cmoIdentityContent.replace(/agent_id:\s*\w+/g, `agent_id: ${cmoName}`).replace(/\$\{agent_id\}/g, cmoName);
12642
- writeFileSync14(cmoIdPath, replaced, "utf-8");
12812
+ writeFileSync15(cmoIdPath, replaced, "utf-8");
12643
12813
  }
12644
12814
  registerBinSymlinks2(cmoName);
12645
12815
  createdEmployees.push({ name: cmoName, role: "CMO" });
@@ -12661,7 +12831,7 @@ async function runSetupWizard(opts = {}) {
12661
12831
  log(`Session shortcuts generated (${cooName}1, ${cooName}2, ...)`);
12662
12832
  }
12663
12833
  if (wrapResult.pathConfigured) {
12664
- const binDir = path27.join(os11.homedir(), ".exe-os", "bin");
12834
+ const binDir = path28.join(os11.homedir(), ".exe-os", "bin");
12665
12835
  process.env.PATH = `${binDir}:${process.env.PATH ?? ""}`;
12666
12836
  pathJustConfigured = true;
12667
12837
  }
@@ -12701,7 +12871,7 @@ async function runSetupWizard(opts = {}) {
12701
12871
  const pkgRoot2 = findPackageRoot2();
12702
12872
  if (pkgRoot2) {
12703
12873
  try {
12704
- version = JSON.parse(readFileSync18(path27.join(pkgRoot2, "package.json"), "utf-8")).version;
12874
+ version = JSON.parse(readFileSync19(path28.join(pkgRoot2, "package.json"), "utf-8")).version;
12705
12875
  } catch {
12706
12876
  }
12707
12877
  }
@@ -12712,7 +12882,7 @@ async function runSetupWizard(opts = {}) {
12712
12882
  };
12713
12883
  log("");
12714
12884
  log(` ${"\u2554" + "\u2550".repeat(W) + "\u2557"}`);
12715
- log(` ${"\u2551" + center("e x e O S") + "\u2551"}`);
12885
+ log(` ${"\u2551" + center("E X E O S") + "\u2551"}`);
12716
12886
  if (version) log(` ${"\u2551" + center(`v${version}`) + "\u2551"}`);
12717
12887
  log(` ${"\u255A" + "\u2550".repeat(W) + "\u255D"}`);
12718
12888
  log("");
@@ -12738,17 +12908,17 @@ var init_setup_wizard = __esm({
12738
12908
  init_config();
12739
12909
  init_keychain();
12740
12910
  init_model_downloader();
12741
- SETUP_STATE_PATH = path27.join(os11.homedir(), ".exe-os", "setup-state.json");
12911
+ SETUP_STATE_PATH = path28.join(os11.homedir(), ".exe-os", "setup-state.json");
12742
12912
  }
12743
12913
  });
12744
12914
 
12745
12915
  // src/lib/update-check.ts
12746
12916
  import { execSync as execSync11 } from "child_process";
12747
- import { readFileSync as readFileSync19 } from "fs";
12748
- import path28 from "path";
12917
+ import { readFileSync as readFileSync20 } from "fs";
12918
+ import path29 from "path";
12749
12919
  function getLocalVersion(packageRoot) {
12750
- const pkgPath = path28.join(packageRoot, "package.json");
12751
- const pkg = JSON.parse(readFileSync19(pkgPath, "utf-8"));
12920
+ const pkgPath = path29.join(packageRoot, "package.json");
12921
+ const pkg = JSON.parse(readFileSync20(pkgPath, "utf-8"));
12752
12922
  return pkg.version;
12753
12923
  }
12754
12924
  function getRemoteVersion() {
@@ -17271,8 +17441,8 @@ var init_ErrorOverview = __esm({
17271
17441
  "use strict";
17272
17442
  init_Box();
17273
17443
  init_Text();
17274
- cleanupPath = (path38) => {
17275
- return path38?.replace(`file://${cwd()}/`, "");
17444
+ cleanupPath = (path39) => {
17445
+ return path39?.replace(`file://${cwd()}/`, "");
17276
17446
  };
17277
17447
  stackUtils = new StackUtils({
17278
17448
  cwd: cwd(),
@@ -19680,11 +19850,11 @@ function Footer() {
19680
19850
  } catch {
19681
19851
  }
19682
19852
  try {
19683
- const { existsSync: existsSync25 } = await import("fs");
19853
+ const { existsSync: existsSync26 } = await import("fs");
19684
19854
  const { join } = await import("path");
19685
19855
  const home = process.env.HOME ?? "";
19686
19856
  const pidPath = join(home, ".exe-os", "exed.pid");
19687
- setDaemon(existsSync25(pidPath) ? "running" : "stopped");
19857
+ setDaemon(existsSync26(pidPath) ? "running" : "stopped");
19688
19858
  } catch {
19689
19859
  setDaemon("unknown");
19690
19860
  }
@@ -21715,10 +21885,10 @@ var init_hooks = __esm({
21715
21885
  });
21716
21886
 
21717
21887
  // src/runtime/safety-checks.ts
21718
- import path29 from "path";
21888
+ import path30 from "path";
21719
21889
  import os12 from "os";
21720
21890
  function checkPathSafety(filePath) {
21721
- const resolved = path29.resolve(filePath);
21891
+ const resolved = path30.resolve(filePath);
21722
21892
  for (const { pattern, reason } of BYPASS_IMMUNE_PATTERNS) {
21723
21893
  const matches = typeof pattern === "function" ? pattern(resolved) : pattern.test(resolved);
21724
21894
  if (matches) {
@@ -21728,7 +21898,7 @@ function checkPathSafety(filePath) {
21728
21898
  return { safe: true, bypassImmune: true };
21729
21899
  }
21730
21900
  function checkReadPathSafety(filePath) {
21731
- const resolved = path29.resolve(filePath);
21901
+ const resolved = path30.resolve(filePath);
21732
21902
  const credPatterns = BYPASS_IMMUNE_PATTERNS.filter(
21733
21903
  (p) => typeof p.pattern !== "function" && (p.reason.includes("secrets") || p.reason.includes("Private key") || p.reason.includes("Credential"))
21734
21904
  );
@@ -21754,11 +21924,11 @@ var init_safety_checks = __esm({
21754
21924
  reason: "Git config can set hooks and command execution"
21755
21925
  },
21756
21926
  {
21757
- pattern: (p) => p.startsWith(path29.join(HOME, ".claude")),
21927
+ pattern: (p) => p.startsWith(path30.join(HOME, ".claude")),
21758
21928
  reason: "Claude configuration files are protected"
21759
21929
  },
21760
21930
  {
21761
- pattern: (p) => p.startsWith(path29.join(HOME, ".exe-os")),
21931
+ pattern: (p) => p.startsWith(path30.join(HOME, ".exe-os")),
21762
21932
  reason: "exe-os configuration files are protected"
21763
21933
  },
21764
21934
  {
@@ -21775,7 +21945,7 @@ var init_safety_checks = __esm({
21775
21945
  },
21776
21946
  {
21777
21947
  pattern: (p) => {
21778
- const name = path29.basename(p);
21948
+ const name = path30.basename(p);
21779
21949
  return [".bashrc", ".zshrc", ".profile", ".bash_profile", ".zprofile", ".zshenv"].includes(name);
21780
21950
  },
21781
21951
  reason: "Shell configuration files can execute arbitrary code on login"
@@ -21802,7 +21972,7 @@ __export(file_read_exports, {
21802
21972
  FileReadTool: () => FileReadTool
21803
21973
  });
21804
21974
  import fs3 from "fs/promises";
21805
- import path30 from "path";
21975
+ import path31 from "path";
21806
21976
  import { z } from "zod";
21807
21977
  function isBinary(buf) {
21808
21978
  for (let i = 0; i < buf.length; i++) {
@@ -21838,7 +22008,7 @@ var init_file_read = __esm({
21838
22008
  return { behavior: "allow" };
21839
22009
  },
21840
22010
  async call(input, context) {
21841
- const filePath = path30.isAbsolute(input.file_path) ? input.file_path : path30.resolve(context.cwd, input.file_path);
22011
+ const filePath = path31.isAbsolute(input.file_path) ? input.file_path : path31.resolve(context.cwd, input.file_path);
21842
22012
  let stat2;
21843
22013
  try {
21844
22014
  stat2 = await fs3.stat(filePath);
@@ -21878,7 +22048,7 @@ __export(glob_exports, {
21878
22048
  GlobTool: () => GlobTool
21879
22049
  });
21880
22050
  import fs4 from "fs/promises";
21881
- import path31 from "path";
22051
+ import path32 from "path";
21882
22052
  import { z as z2 } from "zod";
21883
22053
  async function walkDir(dir, maxDepth = 10) {
21884
22054
  const results = [];
@@ -21894,7 +22064,7 @@ async function walkDir(dir, maxDepth = 10) {
21894
22064
  if (entry.isDirectory() && (entry.name === "node_modules" || entry.name === ".git")) {
21895
22065
  continue;
21896
22066
  }
21897
- const fullPath = path31.join(current, entry.name);
22067
+ const fullPath = path32.join(current, entry.name);
21898
22068
  if (entry.isDirectory()) {
21899
22069
  await walk(fullPath, depth + 1);
21900
22070
  } else {
@@ -21928,11 +22098,11 @@ var init_glob = __esm({
21928
22098
  inputSchema: inputSchema2,
21929
22099
  isReadOnly: true,
21930
22100
  async call(input, context) {
21931
- const baseDir = input.path ? path31.isAbsolute(input.path) ? input.path : path31.resolve(context.cwd, input.path) : context.cwd;
22101
+ const baseDir = input.path ? path32.isAbsolute(input.path) ? input.path : path32.resolve(context.cwd, input.path) : context.cwd;
21932
22102
  try {
21933
22103
  const entries = await walkDir(baseDir);
21934
22104
  const matched = entries.filter(
21935
- (e) => simpleGlobMatch(path31.relative(baseDir, e.path), input.pattern)
22105
+ (e) => simpleGlobMatch(path32.relative(baseDir, e.path), input.pattern)
21936
22106
  );
21937
22107
  matched.sort((a, b) => b.mtime - a.mtime);
21938
22108
  if (matched.length === 0) {
@@ -21958,7 +22128,7 @@ __export(grep_exports, {
21958
22128
  });
21959
22129
  import { spawn as spawn2 } from "child_process";
21960
22130
  import fs5 from "fs/promises";
21961
- import path32 from "path";
22131
+ import path33 from "path";
21962
22132
  import { z as z3 } from "zod";
21963
22133
  function runRipgrep(input, searchPath, context) {
21964
22134
  return new Promise((resolve, reject) => {
@@ -22012,7 +22182,7 @@ async function nodeGrep(input, searchPath) {
22012
22182
  }
22013
22183
  for (const entry of entries) {
22014
22184
  if (entry.name === "node_modules" || entry.name === ".git") continue;
22015
- const fullPath = path32.join(dir, entry.name);
22185
+ const fullPath = path33.join(dir, entry.name);
22016
22186
  if (entry.isDirectory()) {
22017
22187
  await walk(fullPath);
22018
22188
  } else {
@@ -22058,7 +22228,7 @@ var init_grep = __esm({
22058
22228
  inputSchema: inputSchema3,
22059
22229
  isReadOnly: true,
22060
22230
  async call(input, context) {
22061
- const searchPath = input.path ? path32.isAbsolute(input.path) ? input.path : path32.resolve(context.cwd, input.path) : context.cwd;
22231
+ const searchPath = input.path ? path33.isAbsolute(input.path) ? input.path : path33.resolve(context.cwd, input.path) : context.cwd;
22062
22232
  try {
22063
22233
  const result = await runRipgrep(input, searchPath, context);
22064
22234
  return result;
@@ -22083,7 +22253,7 @@ __export(file_write_exports, {
22083
22253
  FileWriteTool: () => FileWriteTool
22084
22254
  });
22085
22255
  import fs6 from "fs/promises";
22086
- import path33 from "path";
22256
+ import path34 from "path";
22087
22257
  import { z as z4 } from "zod";
22088
22258
  var inputSchema4, FileWriteTool;
22089
22259
  var init_file_write = __esm({
@@ -22111,8 +22281,8 @@ var init_file_write = __esm({
22111
22281
  return { behavior: "allow" };
22112
22282
  },
22113
22283
  async call(input, context) {
22114
- const filePath = path33.isAbsolute(input.file_path) ? input.file_path : path33.resolve(context.cwd, input.file_path);
22115
- const dir = path33.dirname(filePath);
22284
+ const filePath = path34.isAbsolute(input.file_path) ? input.file_path : path34.resolve(context.cwd, input.file_path);
22285
+ const dir = path34.dirname(filePath);
22116
22286
  await fs6.mkdir(dir, { recursive: true });
22117
22287
  await fs6.writeFile(filePath, input.content, "utf-8");
22118
22288
  return {
@@ -22130,7 +22300,7 @@ __export(file_edit_exports, {
22130
22300
  FileEditTool: () => FileEditTool
22131
22301
  });
22132
22302
  import fs7 from "fs/promises";
22133
- import path34 from "path";
22303
+ import path35 from "path";
22134
22304
  import { z as z5 } from "zod";
22135
22305
  function countOccurrences(haystack, needle) {
22136
22306
  let count = 0;
@@ -22171,7 +22341,7 @@ var init_file_edit = __esm({
22171
22341
  return { behavior: "allow" };
22172
22342
  },
22173
22343
  async call(input, context) {
22174
- const filePath = path34.isAbsolute(input.file_path) ? input.file_path : path34.resolve(context.cwd, input.file_path);
22344
+ const filePath = path35.isAbsolute(input.file_path) ? input.file_path : path35.resolve(context.cwd, input.file_path);
22175
22345
  let content;
22176
22346
  try {
22177
22347
  content = await fs7.readFile(filePath, "utf-8");
@@ -22413,7 +22583,7 @@ var init_bash = __esm({
22413
22583
  // src/tui/views/CommandCenter.tsx
22414
22584
  import { useState as useState6, useEffect as useEffect8, useMemo as useMemo4, useCallback as useCallback4, useRef as useRef4 } from "react";
22415
22585
  import TextInput from "ink-text-input";
22416
- import path35 from "path";
22586
+ import path36 from "path";
22417
22587
  import { homedir as homedir6 } from "os";
22418
22588
  import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
22419
22589
  function CommandCenterView({
@@ -22448,15 +22618,15 @@ function CommandCenterView({
22448
22618
  const { createPermissionsFromPreset: createPermissionsFromPreset2, EMPLOYEE_PERMISSIONS: EMPLOYEE_PERMISSIONS2 } = await Promise.resolve().then(() => (init_permissions(), permissions_exports));
22449
22619
  const { getPresetByRole: getPresetByRole2 } = await Promise.resolve().then(() => (init_permission_presets(), permission_presets_exports));
22450
22620
  const { createDefaultHooks: createDefaultHooks2 } = await Promise.resolve().then(() => (init_hooks(), hooks_exports));
22451
- const { readFileSync: readFileSync22, existsSync: existsSync25 } = await import("fs");
22621
+ const { readFileSync: readFileSync23, existsSync: existsSync26 } = await import("fs");
22452
22622
  const { join } = await import("path");
22453
22623
  const { homedir: homedir8 } = await import("os");
22454
22624
  const configPath = join(homedir8(), ".exe-os", "config.json");
22455
22625
  let failoverChain = ["anthropic", "opencode", "gemini", "openai"];
22456
22626
  let providerConfigs = {};
22457
- if (existsSync25(configPath)) {
22627
+ if (existsSync26(configPath)) {
22458
22628
  try {
22459
- const raw = JSON.parse(readFileSync22(configPath, "utf8"));
22629
+ const raw = JSON.parse(readFileSync23(configPath, "utf8"));
22460
22630
  if (Array.isArray(raw.failoverChain)) failoverChain = raw.failoverChain;
22461
22631
  if (raw.providers && typeof raw.providers === "object") {
22462
22632
  providerConfigs = raw.providers;
@@ -22517,7 +22687,7 @@ function CommandCenterView({
22517
22687
  const markerDir = join(homedir8(), ".exe-os", "session-cache");
22518
22688
  const agentFiles = (await import("fs")).readdirSync(markerDir).filter((f) => f.startsWith("active-agent-"));
22519
22689
  for (const f of agentFiles) {
22520
- const data = JSON.parse(readFileSync22(join(markerDir, f), "utf8"));
22690
+ const data = JSON.parse(readFileSync23(join(markerDir, f), "utf8"));
22521
22691
  if (data.agentRole) {
22522
22692
  agentRole = data.agentRole;
22523
22693
  break;
@@ -22662,7 +22832,7 @@ function CommandCenterView({
22662
22832
  const demoEntries = DEMO_PROJECTS.map((p) => ({
22663
22833
  projectName: p.projectName,
22664
22834
  exeSession: p.exeSession,
22665
- projectDir: path35.join(homedir6(), p.projectName),
22835
+ projectDir: path36.join(homedir6(), p.projectName),
22666
22836
  employeeCount: p.employees.length,
22667
22837
  activeCount: p.employees.filter((e) => e.status === "active").length,
22668
22838
  memoryCount: p.employees.length * 4e3,
@@ -22700,7 +22870,7 @@ function CommandCenterView({
22700
22870
  const { listSessions: listSessions2 } = await Promise.resolve().then(() => (init_session_registry(), session_registry_exports));
22701
22871
  const { listTmuxSessions: listTmuxSessions2, inTmux: inTmux2 } = await Promise.resolve().then(() => (init_tmux_status(), tmux_status_exports));
22702
22872
  const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
22703
- const { existsSync: existsSync25 } = await import("fs");
22873
+ const { existsSync: existsSync26 } = await import("fs");
22704
22874
  const { join } = await import("path");
22705
22875
  const client = getClient2();
22706
22876
  if (!client) {
@@ -22771,7 +22941,7 @@ function CommandCenterView({
22771
22941
  }
22772
22942
  const memoryCount = memoryCounts.get(name) ?? 0;
22773
22943
  const openTaskCount = openTaskCounts.get(name) ?? 0;
22774
- const hasGit = projectDir ? existsSync25(join(projectDir, ".git")) : false;
22944
+ const hasGit = projectDir ? existsSync26(join(projectDir, ".git")) : false;
22775
22945
  const type = hasGit ? "code" : memoryCount > 0 ? "code" : "automation";
22776
22946
  projectList.push({
22777
22947
  projectName: name,
@@ -22796,7 +22966,7 @@ function CommandCenterView({
22796
22966
  setHealth((h) => ({ ...h, memories: Number(totalResult.rows[0]?.cnt ?? 0) }));
22797
22967
  try {
22798
22968
  const pidPath = join(process.env.HOME ?? "", ".exe-os", "exed.pid");
22799
- setHealth((h) => ({ ...h, daemon: existsSync25(pidPath) ? "running" : "stopped" }));
22969
+ setHealth((h) => ({ ...h, daemon: existsSync26(pidPath) ? "running" : "stopped" }));
22800
22970
  } catch {
22801
22971
  }
22802
22972
  const activityResult = await client.execute(
@@ -23665,7 +23835,7 @@ var init_useOrchestrator = __esm({
23665
23835
 
23666
23836
  // src/tui/views/Sessions.tsx
23667
23837
  import React19, { useState as useState9, useEffect as useEffect11, useCallback as useCallback6 } from "react";
23668
- import path36 from "path";
23838
+ import path37 from "path";
23669
23839
  import { homedir as homedir7 } from "os";
23670
23840
  import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
23671
23841
  function isCoordinatorEntry(entry) {
@@ -23703,7 +23873,7 @@ function SessionsView({
23703
23873
  if (demo) {
23704
23874
  setProjects(DEMO_PROJECTS.map((p) => ({
23705
23875
  ...p,
23706
- projectDir: path36.join(homedir7(), p.projectName),
23876
+ projectDir: path37.join(homedir7(), p.projectName),
23707
23877
  employees: p.employees.map((e) => ({ ...e, attached: e.status === "active" }))
23708
23878
  })));
23709
23879
  return;
@@ -24807,12 +24977,12 @@ async function loadGatewayConfig() {
24807
24977
  state.running = false;
24808
24978
  }
24809
24979
  try {
24810
- const { existsSync: existsSync25, readFileSync: readFileSync22 } = await import("fs");
24980
+ const { existsSync: existsSync26, readFileSync: readFileSync23 } = await import("fs");
24811
24981
  const { join } = await import("path");
24812
24982
  const home = process.env.HOME ?? "";
24813
24983
  const configPath = join(home, ".exe-os", "gateway.json");
24814
- if (existsSync25(configPath)) {
24815
- const raw = JSON.parse(readFileSync22(configPath, "utf8"));
24984
+ if (existsSync26(configPath)) {
24985
+ const raw = JSON.parse(readFileSync23(configPath, "utf8"));
24816
24986
  state.port = raw.port ?? 3100;
24817
24987
  state.gatewayUrl = raw.gatewayUrl ?? "";
24818
24988
  if (raw.adapters) {
@@ -25435,12 +25605,12 @@ function TeamView({ onBack, onViewSessions }) {
25435
25605
  setMembers(teamData);
25436
25606
  setDbError(null);
25437
25607
  try {
25438
- const { existsSync: existsSync25, readFileSync: readFileSync22 } = await import("fs");
25608
+ const { existsSync: existsSync26, readFileSync: readFileSync23 } = await import("fs");
25439
25609
  const { join } = await import("path");
25440
25610
  const home = process.env.HOME ?? "";
25441
25611
  const gatewayConfig = join(home, ".exe-os", "gateway.json");
25442
- if (existsSync25(gatewayConfig)) {
25443
- const raw = JSON.parse(readFileSync22(gatewayConfig, "utf8"));
25612
+ if (existsSync26(gatewayConfig)) {
25613
+ const raw = JSON.parse(readFileSync23(gatewayConfig, "utf8"));
25444
25614
  if (raw.agents && raw.agents.length > 0) {
25445
25615
  setExternals(raw.agents.map((a) => ({
25446
25616
  name: a.name,
@@ -25621,8 +25791,8 @@ __export(wiki_client_exports, {
25621
25791
  listDocuments: () => listDocuments,
25622
25792
  listWorkspaces: () => listWorkspaces
25623
25793
  });
25624
- async function wikiFetch(config, path38, method = "GET", body) {
25625
- const url = `${config.baseUrl}/api/v1${path38}`;
25794
+ async function wikiFetch(config, path39, method = "GET", body) {
25795
+ const url = `${config.baseUrl}/api/v1${path39}`;
25626
25796
  const headers = {
25627
25797
  Authorization: `Bearer ${config.apiKey}`,
25628
25798
  "Content-Type": "application/json"
@@ -25655,7 +25825,7 @@ async function wikiFetch(config, path38, method = "GET", body) {
25655
25825
  }
25656
25826
  }
25657
25827
  if (!response.ok) {
25658
- throw new Error(`Wiki API ${method} ${path38}: ${response.status} ${response.statusText}`);
25828
+ throw new Error(`Wiki API ${method} ${path39}: ${response.status} ${response.statusText}`);
25659
25829
  }
25660
25830
  return response.json();
25661
25831
  } finally {
@@ -26265,12 +26435,12 @@ function SettingsView({ onBack }) {
26265
26435
  }
26266
26436
  setProviders(providerList);
26267
26437
  try {
26268
- const { existsSync: existsSync25 } = await import("fs");
26438
+ const { existsSync: existsSync26 } = await import("fs");
26269
26439
  const { join } = await import("path");
26270
26440
  const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
26271
26441
  const cfg = await loadConfig2();
26272
26442
  const home = process.env.HOME ?? "";
26273
- const hasKey = existsSync25(join(home, ".exe-os", "master.key"));
26443
+ const hasKey = existsSync26(join(home, ".exe-os", "master.key"));
26274
26444
  if (cfg.cloud) {
26275
26445
  setCloud({
26276
26446
  configured: true,
@@ -26283,22 +26453,22 @@ function SettingsView({ onBack }) {
26283
26453
  const pidPath = join(home, ".exe-os", "exed.pid");
26284
26454
  let daemon = "unknown";
26285
26455
  try {
26286
- daemon = existsSync25(pidPath) ? "running" : "stopped";
26456
+ daemon = existsSync26(pidPath) ? "running" : "stopped";
26287
26457
  } catch {
26288
26458
  }
26289
26459
  let version = "unknown";
26290
26460
  try {
26291
- const { readFileSync: readFileSync22 } = await import("fs");
26461
+ const { readFileSync: readFileSync23 } = await import("fs");
26292
26462
  const { createRequire } = await import("module");
26293
26463
  const require2 = createRequire(import.meta.url);
26294
26464
  const pkgPath = require2.resolve("@askexenow/exe-os/package.json");
26295
- const pkg = JSON.parse(readFileSync22(pkgPath, "utf8"));
26465
+ const pkg = JSON.parse(readFileSync23(pkgPath, "utf8"));
26296
26466
  version = pkg.version;
26297
26467
  } catch {
26298
26468
  try {
26299
- const { readFileSync: readFileSync22 } = await import("fs");
26469
+ const { readFileSync: readFileSync23 } = await import("fs");
26300
26470
  const { join: joinPath } = await import("path");
26301
- const pkg = JSON.parse(readFileSync22(joinPath(process.cwd(), "package.json"), "utf8"));
26471
+ const pkg = JSON.parse(readFileSync23(joinPath(process.cwd(), "package.json"), "utf8"));
26302
26472
  version = pkg.version;
26303
26473
  } catch {
26304
26474
  }
@@ -26907,14 +27077,14 @@ Unhandled rejection: ${reason}
26907
27077
  });
26908
27078
 
26909
27079
  // src/bin/cli.ts
26910
- import { existsSync as existsSync24, readFileSync as readFileSync21, writeFileSync as writeFileSync15, readdirSync as readdirSync8, rmSync } from "fs";
26911
- import path37 from "path";
27080
+ import { existsSync as existsSync25, readFileSync as readFileSync22, writeFileSync as writeFileSync16, readdirSync as readdirSync8, rmSync } from "fs";
27081
+ import path38 from "path";
26912
27082
  import os13 from "os";
26913
27083
  var args = process.argv.slice(2);
26914
27084
  if (args.includes("--version") || args.includes("-v")) {
26915
27085
  try {
26916
- const pkgPath = path37.join(path37.dirname(new URL(import.meta.url).pathname), "..", "..", "package.json");
26917
- const pkg = JSON.parse(readFileSync21(pkgPath, "utf8"));
27086
+ const pkgPath = path38.join(path38.dirname(new URL(import.meta.url).pathname), "..", "..", "package.json");
27087
+ const pkg = JSON.parse(readFileSync22(pkgPath, "utf8"));
26918
27088
  console.log(pkg.version);
26919
27089
  } catch {
26920
27090
  console.log("unknown");
@@ -27052,11 +27222,11 @@ ID: ${result.id}`);
27052
27222
  });
27053
27223
  await init_App2().then(() => App_exports);
27054
27224
  } else {
27055
- const claudeDir = path37.join(os13.homedir(), ".claude");
27056
- const settingsPath = path37.join(claudeDir, "settings.json");
27057
- const hasClaudeCode = existsSync24(settingsPath) && (() => {
27225
+ const claudeDir = path38.join(os13.homedir(), ".claude");
27226
+ const settingsPath = path38.join(claudeDir, "settings.json");
27227
+ const hasClaudeCode = existsSync25(settingsPath) && (() => {
27058
27228
  try {
27059
- const raw = readFileSync21(settingsPath, "utf8");
27229
+ const raw = readFileSync22(settingsPath, "utf8");
27060
27230
  return raw.includes("exe-os") || raw.includes("exe-mem");
27061
27231
  } catch {
27062
27232
  return false;
@@ -27065,9 +27235,9 @@ ID: ${result.id}`);
27065
27235
  if (hasClaudeCode) {
27066
27236
  let cooName = "exe";
27067
27237
  try {
27068
- const rosterPath = path37.join(os13.homedir(), ".exe-os", "exe-employees.json");
27069
- if (existsSync24(rosterPath)) {
27070
- const roster = JSON.parse(readFileSync21(rosterPath, "utf8"));
27238
+ const rosterPath = path38.join(os13.homedir(), ".exe-os", "exe-employees.json");
27239
+ if (existsSync25(rosterPath)) {
27240
+ const roster = JSON.parse(readFileSync22(rosterPath, "utf8"));
27071
27241
  const coo = roster.find((e) => e.role === "COO");
27072
27242
  if (coo) cooName = coo.name;
27073
27243
  }
@@ -27107,14 +27277,14 @@ async function runClaudeInstall() {
27107
27277
  }
27108
27278
  }
27109
27279
  async function runClaudeCheck() {
27110
- const claudeDir = path37.join(os13.homedir(), ".claude");
27111
- const settingsPath = path37.join(claudeDir, "settings.json");
27112
- const claudeJsonPath = path37.join(os13.homedir(), ".claude.json");
27280
+ const claudeDir = path38.join(os13.homedir(), ".claude");
27281
+ const settingsPath = path38.join(claudeDir, "settings.json");
27282
+ const claudeJsonPath = path38.join(os13.homedir(), ".claude.json");
27113
27283
  let ok = true;
27114
- if (existsSync24(settingsPath)) {
27284
+ if (existsSync25(settingsPath)) {
27115
27285
  let settings;
27116
27286
  try {
27117
- settings = JSON.parse(readFileSync21(settingsPath, "utf8"));
27287
+ settings = JSON.parse(readFileSync22(settingsPath, "utf8"));
27118
27288
  } catch {
27119
27289
  console.log("\x1B[31m\u2717\x1B[0m settings.json is malformed (invalid JSON)");
27120
27290
  ok = false;
@@ -27140,10 +27310,10 @@ async function runClaudeCheck() {
27140
27310
  console.log("\x1B[31m\u2717\x1B[0m settings.json not found");
27141
27311
  ok = false;
27142
27312
  }
27143
- if (existsSync24(claudeJsonPath)) {
27313
+ if (existsSync25(claudeJsonPath)) {
27144
27314
  let claudeJson;
27145
27315
  try {
27146
- claudeJson = JSON.parse(readFileSync21(claudeJsonPath, "utf8"));
27316
+ claudeJson = JSON.parse(readFileSync22(claudeJsonPath, "utf8"));
27147
27317
  } catch {
27148
27318
  console.log("\x1B[31m\u2717\x1B[0m claude.json is malformed (invalid JSON)");
27149
27319
  ok = false;
@@ -27162,8 +27332,8 @@ async function runClaudeCheck() {
27162
27332
  console.log("\x1B[31m\u2717\x1B[0m claude.json not found");
27163
27333
  ok = false;
27164
27334
  }
27165
- const skillsDir = path37.join(claudeDir, "skills");
27166
- if (existsSync24(skillsDir)) {
27335
+ const skillsDir = path38.join(claudeDir, "skills");
27336
+ if (existsSync25(skillsDir)) {
27167
27337
  console.log("\x1B[32m\u2713\x1B[0m Slash skills directory exists");
27168
27338
  } else {
27169
27339
  console.log("\x1B[31m\u2717\x1B[0m Slash skills directory missing");
@@ -27180,16 +27350,16 @@ async function runClaudeUninstall(flags = []) {
27180
27350
  const dryRun = flags.includes("--dry-run");
27181
27351
  const purge = flags.includes("--purge");
27182
27352
  const homeDir = os13.homedir();
27183
- const claudeDir = path37.join(homeDir, ".claude");
27184
- const settingsPath = path37.join(claudeDir, "settings.json");
27185
- const claudeJsonPath = path37.join(homeDir, ".claude.json");
27186
- const exeOsDir = path37.join(homeDir, ".exe-os");
27353
+ const claudeDir = path38.join(homeDir, ".claude");
27354
+ const settingsPath = path38.join(claudeDir, "settings.json");
27355
+ const claudeJsonPath = path38.join(homeDir, ".claude.json");
27356
+ const exeOsDir = path38.join(homeDir, ".exe-os");
27187
27357
  let removed = 0;
27188
27358
  const log = (msg) => console.log(dryRun ? `[dry-run] ${msg}` : msg);
27189
27359
  let settings = {};
27190
- if (existsSync24(settingsPath)) {
27360
+ if (existsSync25(settingsPath)) {
27191
27361
  try {
27192
- settings = JSON.parse(readFileSync21(settingsPath, "utf8"));
27362
+ settings = JSON.parse(readFileSync22(settingsPath, "utf8"));
27193
27363
  } catch {
27194
27364
  console.error("Your ~/.claude/settings.json appears malformed.");
27195
27365
  if (purge) {
@@ -27227,15 +27397,15 @@ async function runClaudeUninstall(flags = []) {
27227
27397
  permCount = before - settings.permissions.allow.length;
27228
27398
  }
27229
27399
  if (!dryRun) {
27230
- writeFileSync15(settingsPath, JSON.stringify(settings, null, 2) + "\n");
27400
+ writeFileSync16(settingsPath, JSON.stringify(settings, null, 2) + "\n");
27231
27401
  }
27232
27402
  log("\u2713 Removed exe-os hooks from settings.json");
27233
27403
  if (permCount > 0) log(`\u2713 Removed ${permCount} MCP permission entries`);
27234
27404
  removed++;
27235
27405
  }
27236
27406
  }
27237
- if (existsSync24(claudeJsonPath)) {
27238
- const raw = readFileSync21(claudeJsonPath, "utf8");
27407
+ if (existsSync25(claudeJsonPath)) {
27408
+ const raw = readFileSync22(claudeJsonPath, "utf8");
27239
27409
  if (raw.length > 1e6) {
27240
27410
  console.error("claude.json exceeds 1 MB \u2014 skipping parse.");
27241
27411
  } else {
@@ -27256,7 +27426,7 @@ async function runClaudeUninstall(flags = []) {
27256
27426
  }
27257
27427
  if (removedMcp) {
27258
27428
  if (!dryRun) {
27259
- writeFileSync15(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
27429
+ writeFileSync16(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
27260
27430
  }
27261
27431
  log("\u2713 Removed exe-os MCP server from claude.json");
27262
27432
  removed++;
@@ -27264,14 +27434,14 @@ async function runClaudeUninstall(flags = []) {
27264
27434
  }
27265
27435
  }
27266
27436
  }
27267
- const skillsDir = path37.join(claudeDir, "skills");
27268
- if (existsSync24(skillsDir)) {
27437
+ const skillsDir = path38.join(claudeDir, "skills");
27438
+ if (existsSync25(skillsDir)) {
27269
27439
  let skillCount = 0;
27270
27440
  try {
27271
27441
  const entries = readdirSync8(skillsDir);
27272
27442
  for (const entry of entries) {
27273
27443
  if (entry.startsWith("exe")) {
27274
- const fullPath = path37.join(skillsDir, entry);
27444
+ const fullPath = path38.join(skillsDir, entry);
27275
27445
  if (!dryRun) rmSync(fullPath, { recursive: true, force: true });
27276
27446
  skillCount++;
27277
27447
  }
@@ -27283,30 +27453,30 @@ async function runClaudeUninstall(flags = []) {
27283
27453
  removed++;
27284
27454
  }
27285
27455
  }
27286
- const claudeMdPath = path37.join(claudeDir, "CLAUDE.md");
27287
- if (existsSync24(claudeMdPath)) {
27288
- const content = readFileSync21(claudeMdPath, "utf8");
27456
+ const claudeMdPath = path38.join(claudeDir, "CLAUDE.md");
27457
+ if (existsSync25(claudeMdPath)) {
27458
+ const content = readFileSync22(claudeMdPath, "utf8");
27289
27459
  const startMarker = "<!-- exe-os:orchestration-start -->";
27290
27460
  const endMarker = "<!-- exe-os:orchestration-end -->";
27291
27461
  const startIdx = content.indexOf(startMarker);
27292
27462
  const endIdx = content.indexOf(endMarker);
27293
27463
  if (startIdx !== -1 && endIdx !== -1) {
27294
27464
  const cleaned = (content.slice(0, startIdx) + content.slice(endIdx + endMarker.length)).replace(/\n{3,}/g, "\n\n").trim() + "\n";
27295
- if (!dryRun) writeFileSync15(claudeMdPath, cleaned);
27465
+ if (!dryRun) writeFileSync16(claudeMdPath, cleaned);
27296
27466
  log("\u2713 Removed orchestration block from CLAUDE.md");
27297
27467
  removed++;
27298
27468
  }
27299
27469
  }
27300
- const agentsDir = path37.join(claudeDir, "agents");
27301
- if (existsSync24(agentsDir)) {
27470
+ const agentsDir = path38.join(claudeDir, "agents");
27471
+ if (existsSync25(agentsDir)) {
27302
27472
  let agentCount = 0;
27303
27473
  try {
27304
27474
  const entries = readdirSync8(agentsDir).filter((f) => f.endsWith(".md"));
27305
27475
  let knownNames = /* @__PURE__ */ new Set();
27306
- const rosterPath = path37.join(exeOsDir, "exe-employees.json");
27307
- if (existsSync24(rosterPath)) {
27476
+ const rosterPath = path38.join(exeOsDir, "exe-employees.json");
27477
+ if (existsSync25(rosterPath)) {
27308
27478
  try {
27309
- const roster = JSON.parse(readFileSync21(rosterPath, "utf8"));
27479
+ const roster = JSON.parse(readFileSync22(rosterPath, "utf8"));
27310
27480
  knownNames = new Set(roster.map((e) => e.name));
27311
27481
  } catch {
27312
27482
  }
@@ -27314,7 +27484,7 @@ async function runClaudeUninstall(flags = []) {
27314
27484
  for (const entry of entries) {
27315
27485
  const name = entry.replace(/\.md$/, "");
27316
27486
  if (knownNames.has(name)) {
27317
- if (!dryRun) rmSync(path37.join(agentsDir, entry), { force: true });
27487
+ if (!dryRun) rmSync(path38.join(agentsDir, entry), { force: true });
27318
27488
  agentCount++;
27319
27489
  }
27320
27490
  }
@@ -27325,16 +27495,16 @@ async function runClaudeUninstall(flags = []) {
27325
27495
  removed++;
27326
27496
  }
27327
27497
  }
27328
- const projectsDir = path37.join(claudeDir, "projects");
27329
- if (existsSync24(projectsDir)) {
27498
+ const projectsDir = path38.join(claudeDir, "projects");
27499
+ if (existsSync25(projectsDir)) {
27330
27500
  let projectCount = 0;
27331
27501
  try {
27332
27502
  const projects = readdirSync8(projectsDir);
27333
27503
  for (const proj of projects) {
27334
- const projSettings = path37.join(projectsDir, proj, "settings.json");
27335
- if (!existsSync24(projSettings)) continue;
27504
+ const projSettings = path38.join(projectsDir, proj, "settings.json");
27505
+ if (!existsSync25(projSettings)) continue;
27336
27506
  try {
27337
- const pSettings = JSON.parse(readFileSync21(projSettings, "utf8"));
27507
+ const pSettings = JSON.parse(readFileSync22(projSettings, "utf8"));
27338
27508
  let changed = false;
27339
27509
  if (Array.isArray(pSettings.permissions?.allow)) {
27340
27510
  const before = pSettings.permissions.allow.length;
@@ -27344,7 +27514,7 @@ async function runClaudeUninstall(flags = []) {
27344
27514
  if (pSettings.permissions.allow.length < before) changed = true;
27345
27515
  }
27346
27516
  if (changed && !dryRun) {
27347
- writeFileSync15(projSettings, JSON.stringify(pSettings, null, 2) + "\n");
27517
+ writeFileSync16(projSettings, JSON.stringify(pSettings, null, 2) + "\n");
27348
27518
  }
27349
27519
  if (changed) projectCount++;
27350
27520
  } catch {
@@ -27368,17 +27538,17 @@ async function runClaudeUninstall(flags = []) {
27368
27538
  };
27369
27539
  const exeBinPath = findExeBin3();
27370
27540
  if (!exeBinPath) throw new Error("exe-os not found in PATH");
27371
- const binDir = path37.dirname(exeBinPath);
27541
+ const binDir = path38.dirname(exeBinPath);
27372
27542
  let symlinkCount = 0;
27373
- const rosterPath = path37.join(exeOsDir, "exe-employees.json");
27374
- if (existsSync24(rosterPath)) {
27375
- const roster = JSON.parse(readFileSync21(rosterPath, "utf8"));
27543
+ const rosterPath = path38.join(exeOsDir, "exe-employees.json");
27544
+ if (existsSync25(rosterPath)) {
27545
+ const roster = JSON.parse(readFileSync22(rosterPath, "utf8"));
27376
27546
  const coordinatorName = roster.find((e) => e.role?.toLowerCase() === "coo")?.name ?? "exe";
27377
27547
  for (const emp of roster) {
27378
27548
  if (emp.name === coordinatorName) continue;
27379
27549
  for (const suffix of ["", "-opencode"]) {
27380
- const linkPath = path37.join(binDir, `${emp.name}${suffix}`);
27381
- if (existsSync24(linkPath)) {
27550
+ const linkPath = path38.join(binDir, `${emp.name}${suffix}`);
27551
+ if (existsSync25(linkPath)) {
27382
27552
  if (!dryRun) rmSync(linkPath, { force: true });
27383
27553
  symlinkCount++;
27384
27554
  }
@@ -27391,7 +27561,7 @@ async function runClaudeUninstall(flags = []) {
27391
27561
  }
27392
27562
  } catch {
27393
27563
  }
27394
- if (purge && existsSync24(exeOsDir)) {
27564
+ if (purge && existsSync25(exeOsDir)) {
27395
27565
  if (!dryRun) {
27396
27566
  process.stdout.write("\x1B[33m\u26A0 This will delete all memories, identities, and agent data.\x1B[0m\n");
27397
27567
  process.stdout.write(" Removing ~/.exe-os...\n");
@@ -27416,7 +27586,7 @@ async function checkForUpdateOnBoot() {
27416
27586
  const config = await loadConfig2();
27417
27587
  if (!config.autoUpdate.checkOnBoot) return;
27418
27588
  const { checkForUpdate: checkForUpdate2 } = await Promise.resolve().then(() => (init_update(), update_exports));
27419
- const packageRoot = path37.resolve(
27589
+ const packageRoot = path38.resolve(
27420
27590
  new URL("../..", import.meta.url).pathname
27421
27591
  );
27422
27592
  const result = checkForUpdate2(packageRoot);
@@ -27475,7 +27645,7 @@ async function runActivate(key) {
27475
27645
  const idTemplate = getIdentityTemplate(identityKey);
27476
27646
  if (idTemplate) {
27477
27647
  const idPath = identityPath2(name);
27478
- const dir = path37.dirname(idPath);
27648
+ const dir = path38.dirname(idPath);
27479
27649
  if (!fs8.existsSync(dir)) fs8.mkdirSync(dir, { recursive: true });
27480
27650
  fs8.writeFileSync(idPath, idTemplate.replace(/^agent_id: \w+/m, `agent_id: ${name}`), "utf-8");
27481
27651
  }