@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
@@ -178,13 +178,144 @@ function checkWorkerSpawning(pkgRoot) {
178
178
  }
179
179
  return results;
180
180
  }
181
+ function checkClaudeCodeInstall() {
182
+ const results = [];
183
+ const execPath = process.env.CLAUDE_CODE_EXECPATH ?? "";
184
+ if (execPath.length > 0 && (execPath.includes("claude/versions/") || execPath.includes("claude.exe") || execPath.includes("claude-native"))) {
185
+ results.push({
186
+ name: "cc/execpath-clean",
187
+ pass: false,
188
+ detail: `CLAUDE_CODE_EXECPATH points to native binary: "${execPath}" \u2014 20K phantom billing risk. Unset it: unset CLAUDE_CODE_EXECPATH`
189
+ });
190
+ } else {
191
+ results.push({
192
+ name: "cc/execpath-clean",
193
+ pass: true,
194
+ detail: execPath ? `CLAUDE_CODE_EXECPATH=${execPath} (node runtime, OK)` : "CLAUDE_CODE_EXECPATH is unset"
195
+ });
196
+ }
197
+ try {
198
+ const claudePath = execSync("which claude 2>/dev/null || true", { encoding: "utf8", timeout: 5e3 }).trim();
199
+ if (!claudePath) {
200
+ results.push({
201
+ name: "cc/cli-binary",
202
+ pass: false,
203
+ detail: "claude not found in PATH"
204
+ });
205
+ } else {
206
+ let resolved = claudePath;
207
+ try {
208
+ resolved = execSync(`readlink -f "${claudePath}" 2>/dev/null || readlink "${claudePath}" 2>/dev/null || echo "${claudePath}"`, {
209
+ encoding: "utf8",
210
+ timeout: 5e3
211
+ }).trim();
212
+ } catch {
213
+ }
214
+ if (resolved.includes("bin/claude.exe") || resolved.includes("bin/claude-native")) {
215
+ results.push({
216
+ name: "cc/cli-binary",
217
+ pass: false,
218
+ detail: `claude resolves to native binary: ${resolved}. Should be cli.js. Run: npm install -g @anthropic-ai/claude-code@2.1.98`
219
+ });
220
+ } else {
221
+ results.push({
222
+ name: "cc/cli-binary",
223
+ pass: true,
224
+ detail: `claude resolves to: ${resolved}`
225
+ });
226
+ }
227
+ }
228
+ } catch {
229
+ results.push({
230
+ name: "cc/cli-binary",
231
+ pass: false,
232
+ detail: "Failed to check claude binary path"
233
+ });
234
+ }
235
+ const versionsDir = path.join(
236
+ process.env.HOME ?? process.env.USERPROFILE ?? "",
237
+ ".local",
238
+ "share",
239
+ "claude",
240
+ "versions"
241
+ );
242
+ if (existsSync(versionsDir)) {
243
+ try {
244
+ const entries = readdirSync(versionsDir);
245
+ if (entries.length > 0) {
246
+ results.push({
247
+ name: "cc/native-cache-clean",
248
+ pass: false,
249
+ detail: `${entries.length} cached native version(s) found in ${versionsDir}: ${entries.slice(0, 3).join(", ")}${entries.length > 3 ? "..." : ""}. Remove: rm -rf "${versionsDir}"`
250
+ });
251
+ } else {
252
+ results.push({
253
+ name: "cc/native-cache-clean",
254
+ pass: true,
255
+ detail: `${versionsDir} is empty`
256
+ });
257
+ }
258
+ } catch {
259
+ results.push({
260
+ name: "cc/native-cache-clean",
261
+ pass: true,
262
+ detail: `${versionsDir} not readable (OK)`
263
+ });
264
+ }
265
+ } else {
266
+ results.push({
267
+ name: "cc/native-cache-clean",
268
+ pass: true,
269
+ detail: `${versionsDir} does not exist`
270
+ });
271
+ }
272
+ const disableOld = process.env.DISABLE_AUTOUPDATER === "1";
273
+ const disableNew = process.env.CLAUDE_CODE_AUTOUPDATER_DISABLED === "1";
274
+ if (!disableOld && !disableNew) {
275
+ results.push({
276
+ name: "cc/autoupdater-disabled",
277
+ pass: false,
278
+ detail: "Neither DISABLE_AUTOUPDATER=1 nor CLAUDE_CODE_AUTOUPDATER_DISABLED=1 is set. Auto-updater may install infected native binary. Export both in your shell profile."
279
+ });
280
+ } else {
281
+ const which = [
282
+ disableOld ? "DISABLE_AUTOUPDATER=1" : null,
283
+ disableNew ? "CLAUDE_CODE_AUTOUPDATER_DISABLED=1" : null
284
+ ].filter(Boolean).join(" + ");
285
+ results.push({
286
+ name: "cc/autoupdater-disabled",
287
+ pass: true,
288
+ detail: `Auto-updater disabled via ${which}`
289
+ });
290
+ }
291
+ try {
292
+ const ccVersion = execSync("claude --version 2>/dev/null || echo unknown", {
293
+ encoding: "utf8",
294
+ timeout: 5e3
295
+ }).trim();
296
+ const versionMatch = ccVersion.match(/(\d+\.\d+\.\d+)/);
297
+ if (versionMatch) {
298
+ const ver = versionMatch[1];
299
+ const [, minor] = ver.split(".").map(Number);
300
+ const isRisky = minor !== void 0 && minor >= 1 && parseInt(ver.split(".")[2] ?? "0") >= 119;
301
+ results.push({
302
+ name: "cc/version",
303
+ pass: !isRisky,
304
+ detail: isRisky ? `CC version ${ver} \u2014 \u22652.1.119 ships native binary only. Pin: npm install -g @anthropic-ai/claude-code@2.1.98` : `CC version ${ver}`
305
+ });
306
+ }
307
+ } catch {
308
+ }
309
+ return results;
310
+ }
181
311
  function runHealthCheck() {
182
312
  const pkgRoot = findPackageRoot();
183
313
  const results = [
184
314
  ...checkBuildIntegrity(pkgRoot),
185
315
  ...checkEmbedPipeline(pkgRoot),
186
316
  ...checkTaskSystem(pkgRoot),
187
- ...checkWorkerSpawning(pkgRoot)
317
+ ...checkWorkerSpawning(pkgRoot),
318
+ ...checkClaudeCodeInstall()
188
319
  ];
189
320
  const passed = results.filter((r) => r.pass).length;
190
321
  const failed = results.filter((r) => !r.pass).length;
@@ -204,5 +335,6 @@ if (isMainModule(import.meta.url)) {
204
335
  process.exit(failed > 0 ? 1 : 0);
205
336
  }
206
337
  export {
338
+ checkClaudeCodeInstall,
207
339
  runHealthCheck
208
340
  };
@@ -1968,39 +1968,75 @@ var init_provider_table = __esm({
1968
1968
  }
1969
1969
  });
1970
1970
 
1971
- // src/lib/intercom-queue.ts
1972
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, renameSync as renameSync3, existsSync as existsSync6, mkdirSync as mkdirSync2 } from "fs";
1971
+ // src/lib/runtime-table.ts
1972
+ var RUNTIME_TABLE;
1973
+ var init_runtime_table = __esm({
1974
+ "src/lib/runtime-table.ts"() {
1975
+ "use strict";
1976
+ RUNTIME_TABLE = {
1977
+ codex: {
1978
+ binary: "codex",
1979
+ launchMode: "exec",
1980
+ autoApproveFlag: "--full-auto",
1981
+ inlineFlag: "--no-alt-screen",
1982
+ apiKeyEnv: "OPENAI_API_KEY",
1983
+ defaultModel: "gpt-5.4"
1984
+ }
1985
+ };
1986
+ }
1987
+ });
1988
+
1989
+ // src/lib/agent-config.ts
1990
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, existsSync as existsSync6, mkdirSync as mkdirSync2 } from "fs";
1973
1991
  import path7 from "path";
1992
+ var AGENT_CONFIG_PATH, DEFAULT_MODELS;
1993
+ var init_agent_config = __esm({
1994
+ "src/lib/agent-config.ts"() {
1995
+ "use strict";
1996
+ init_config();
1997
+ init_runtime_table();
1998
+ AGENT_CONFIG_PATH = path7.join(EXE_AI_DIR, "agent-config.json");
1999
+ DEFAULT_MODELS = {
2000
+ claude: "claude-opus-4",
2001
+ codex: RUNTIME_TABLE.codex?.defaultModel ?? "gpt-5.4",
2002
+ opencode: "minimax-m2.7"
2003
+ };
2004
+ }
2005
+ });
2006
+
2007
+ // src/lib/intercom-queue.ts
2008
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, renameSync as renameSync3, existsSync as existsSync7, mkdirSync as mkdirSync3 } from "fs";
2009
+ import path8 from "path";
1974
2010
  import os6 from "os";
1975
2011
  var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
1976
2012
  var init_intercom_queue = __esm({
1977
2013
  "src/lib/intercom-queue.ts"() {
1978
2014
  "use strict";
1979
- QUEUE_PATH = path7.join(os6.homedir(), ".exe-os", "intercom-queue.json");
2015
+ QUEUE_PATH = path8.join(os6.homedir(), ".exe-os", "intercom-queue.json");
1980
2016
  TTL_MS = 60 * 60 * 1e3;
1981
- INTERCOM_LOG = path7.join(os6.homedir(), ".exe-os", "intercom.log");
2017
+ INTERCOM_LOG = path8.join(os6.homedir(), ".exe-os", "intercom.log");
1982
2018
  }
1983
2019
  });
1984
2020
 
1985
2021
  // src/lib/license.ts
1986
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, existsSync as existsSync7, mkdirSync as mkdirSync3 } from "fs";
2022
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, existsSync as existsSync8, mkdirSync as mkdirSync4 } from "fs";
1987
2023
  import { randomUUID as randomUUID2 } from "crypto";
1988
- import path8 from "path";
2024
+ import path9 from "path";
1989
2025
  import { jwtVerify, importSPKI } from "jose";
1990
2026
  var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH;
1991
2027
  var init_license = __esm({
1992
2028
  "src/lib/license.ts"() {
1993
2029
  "use strict";
1994
2030
  init_config();
1995
- LICENSE_PATH = path8.join(EXE_AI_DIR, "license.key");
1996
- CACHE_PATH = path8.join(EXE_AI_DIR, "license-cache.json");
1997
- DEVICE_ID_PATH = path8.join(EXE_AI_DIR, "device-id");
2031
+ LICENSE_PATH = path9.join(EXE_AI_DIR, "license.key");
2032
+ CACHE_PATH = path9.join(EXE_AI_DIR, "license-cache.json");
2033
+ DEVICE_ID_PATH = path9.join(EXE_AI_DIR, "device-id");
1998
2034
  }
1999
2035
  });
2000
2036
 
2001
2037
  // src/lib/plan-limits.ts
2002
- import { readFileSync as readFileSync6, existsSync as existsSync8 } from "fs";
2003
- import path9 from "path";
2038
+ import { readFileSync as readFileSync7, existsSync as existsSync9 } from "fs";
2039
+ import path10 from "path";
2004
2040
  var CACHE_PATH2;
2005
2041
  var init_plan_limits = __esm({
2006
2042
  "src/lib/plan-limits.ts"() {
@@ -2009,13 +2045,13 @@ var init_plan_limits = __esm({
2009
2045
  init_employees();
2010
2046
  init_license();
2011
2047
  init_config();
2012
- CACHE_PATH2 = path9.join(EXE_AI_DIR, "license-cache.json");
2048
+ CACHE_PATH2 = path10.join(EXE_AI_DIR, "license-cache.json");
2013
2049
  }
2014
2050
  });
2015
2051
 
2016
2052
  // src/lib/tmux-routing.ts
2017
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as existsSync9, appendFileSync } from "fs";
2018
- import path10 from "path";
2053
+ import { readFileSync as readFileSync8, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, existsSync as existsSync10, appendFileSync } from "fs";
2054
+ import path11 from "path";
2019
2055
  import os7 from "os";
2020
2056
  import { fileURLToPath as fileURLToPath2 } from "url";
2021
2057
  function getMySession() {
@@ -2029,7 +2065,7 @@ function extractRootExe(name) {
2029
2065
  }
2030
2066
  function getParentExe(sessionKey) {
2031
2067
  try {
2032
- const data = JSON.parse(readFileSync7(path10.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
2068
+ const data = JSON.parse(readFileSync8(path11.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
2033
2069
  return data.parentExe || null;
2034
2070
  } catch {
2035
2071
  return null;
@@ -2063,20 +2099,22 @@ var init_tmux_routing = __esm({
2063
2099
  init_cc_agent_support();
2064
2100
  init_mcp_prefix();
2065
2101
  init_provider_table();
2102
+ init_agent_config();
2103
+ init_runtime_table();
2066
2104
  init_intercom_queue();
2067
2105
  init_plan_limits();
2068
2106
  init_employees();
2069
- SPAWN_LOCK_DIR = path10.join(os7.homedir(), ".exe-os", "spawn-locks");
2070
- SESSION_CACHE = path10.join(os7.homedir(), ".exe-os", "session-cache");
2071
- INTERCOM_LOG2 = path10.join(os7.homedir(), ".exe-os", "intercom.log");
2072
- DEBOUNCE_FILE = path10.join(SESSION_CACHE, "intercom-debounce.json");
2107
+ SPAWN_LOCK_DIR = path11.join(os7.homedir(), ".exe-os", "spawn-locks");
2108
+ SESSION_CACHE = path11.join(os7.homedir(), ".exe-os", "session-cache");
2109
+ INTERCOM_LOG2 = path11.join(os7.homedir(), ".exe-os", "intercom.log");
2110
+ DEBOUNCE_FILE = path11.join(SESSION_CACHE, "intercom-debounce.json");
2073
2111
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
2074
2112
  }
2075
2113
  });
2076
2114
 
2077
2115
  // src/lib/tasks-review.ts
2078
- import path11 from "path";
2079
- import { existsSync as existsSync10, readdirSync as readdirSync3, unlinkSync as unlinkSync3 } from "fs";
2116
+ import path12 from "path";
2117
+ import { existsSync as existsSync11, readdirSync as readdirSync3, unlinkSync as unlinkSync3 } from "fs";
2080
2118
  async function listPendingReviews(limit, sessionScope) {
2081
2119
  const client = getClient();
2082
2120
  if (sessionScope) {
@@ -2136,9 +2174,9 @@ var init_task_scope = __esm({
2136
2174
 
2137
2175
  // src/bin/exe-heartbeat.ts
2138
2176
  import { createHash as createHash2 } from "crypto";
2139
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5 } from "fs";
2177
+ import { readFileSync as readFileSync9, writeFileSync as writeFileSync6, mkdirSync as mkdirSync6 } from "fs";
2140
2178
  import os8 from "os";
2141
- import path12 from "path";
2179
+ import path13 from "path";
2142
2180
 
2143
2181
  // src/lib/store.ts
2144
2182
  import { createHash } from "crypto";
@@ -2309,18 +2347,18 @@ var MESSAGE_PREVIEW_CHARS = 80;
2309
2347
  var MARKER_FILENAME = "exe-heartbeat-marker.json";
2310
2348
  var SESSION_CACHE_SUBDIR = "session-cache";
2311
2349
  function resolveExeOsDir() {
2312
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path12.join(os8.homedir(), ".exe-os");
2350
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path13.join(os8.homedir(), ".exe-os");
2313
2351
  }
2314
2352
  function getMarkerDir() {
2315
- return path12.join(resolveExeOsDir(), SESSION_CACHE_SUBDIR);
2353
+ return path13.join(resolveExeOsDir(), SESSION_CACHE_SUBDIR);
2316
2354
  }
2317
2355
  function getMarkerPath() {
2318
- return path12.join(getMarkerDir(), MARKER_FILENAME);
2356
+ return path13.join(getMarkerDir(), MARKER_FILENAME);
2319
2357
  }
2320
2358
  var UNREAD_MESSAGE_STATUSES = ["pending", "delivered"];
2321
2359
  function readMarker() {
2322
2360
  try {
2323
- const raw = readFileSync8(getMarkerPath(), "utf8");
2361
+ const raw = readFileSync9(getMarkerPath(), "utf8");
2324
2362
  const parsed = JSON.parse(raw);
2325
2363
  if (typeof parsed.lastFiredAt !== "string" || typeof parsed.lastSurfaceHash !== "string") {
2326
2364
  return null;
@@ -2332,8 +2370,8 @@ function readMarker() {
2332
2370
  }
2333
2371
  function writeMarker(marker) {
2334
2372
  try {
2335
- mkdirSync5(getMarkerDir(), { recursive: true });
2336
- writeFileSync5(getMarkerPath(), JSON.stringify(marker));
2373
+ mkdirSync6(getMarkerDir(), { recursive: true });
2374
+ writeFileSync6(getMarkerPath(), JSON.stringify(marker));
2337
2375
  } catch {
2338
2376
  }
2339
2377
  }
@@ -2404,10 +2442,13 @@ async function queryStaleInProgress(thresholdHours) {
2404
2442
  }
2405
2443
  async function queryNewErrors(sinceIso) {
2406
2444
  const client = getClient();
2445
+ const erScope = sessionScopeFilter();
2407
2446
  const result = await client.execute({
2408
- sql: `SELECT COUNT(*) as cnt FROM memories
2447
+ sql: erScope.args.length > 0 ? `SELECT COUNT(*) as cnt FROM memories
2448
+ WHERE has_error = 1 AND timestamp > ?
2449
+ AND agent_id IN (SELECT DISTINCT assigned_to FROM tasks WHERE 1=1${erScope.sql})` : `SELECT COUNT(*) as cnt FROM memories
2409
2450
  WHERE has_error = 1 AND timestamp > ?`,
2410
- args: [sinceIso]
2451
+ args: erScope.args.length > 0 ? [sinceIso, ...erScope.args] : [sinceIso]
2411
2452
  });
2412
2453
  const count = Number(result.rows[0]?.cnt ?? 0);
2413
2454
  if (count === 0) return "";
@@ -2810,10 +2810,18 @@ function buildRosterBlob(paths) {
2810
2810
  } catch {
2811
2811
  }
2812
2812
  }
2813
+ let agentConfig;
2814
+ const agentConfigPath = path7.join(EXE_AI_DIR, "agent-config.json");
2815
+ if (existsSync7(agentConfigPath)) {
2816
+ try {
2817
+ agentConfig = JSON.parse(readFileSync6(agentConfigPath, "utf-8"));
2818
+ } catch {
2819
+ }
2820
+ }
2813
2821
  const deletedNames = consumeRosterDeletions();
2814
- const content = JSON.stringify({ roster, identities, config, deletedNames });
2822
+ const content = JSON.stringify({ roster, identities, config, agentConfig, deletedNames });
2815
2823
  const hash = crypto2.createHash("sha256").update(content).digest("hex").slice(0, 16);
2816
- return { roster, identities, config, deletedNames, version: hash };
2824
+ return { roster, identities, config, agentConfig, deletedNames, version: hash };
2817
2825
  }
2818
2826
  async function cloudPushRoster(config) {
2819
2827
  assertSecureEndpoint(config.endpoint);
@@ -2951,6 +2959,21 @@ async function mergeRosterFromRemote(remote, paths) {
2951
2959
  } catch {
2952
2960
  }
2953
2961
  }
2962
+ if (remote.agentConfig && Object.keys(remote.agentConfig).length > 0) {
2963
+ try {
2964
+ const agentConfigPath = path7.join(EXE_AI_DIR, "agent-config.json");
2965
+ let local = {};
2966
+ if (existsSync7(agentConfigPath)) {
2967
+ try {
2968
+ local = JSON.parse(readFileSync6(agentConfigPath, "utf-8"));
2969
+ } catch {
2970
+ }
2971
+ }
2972
+ const merged = { ...remote.agentConfig, ...local };
2973
+ writeFileSync4(agentConfigPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
2974
+ } catch {
2975
+ }
2976
+ }
2954
2977
  return { added, identitiesUpdated };
2955
2978
  });
2956
2979
  }
@@ -1610,6 +1610,28 @@ exec "${exeStartDst}" "$0" "$@"
1610
1610
  created++;
1611
1611
  }
1612
1612
  }
1613
+ const codexLauncherCandidates = [
1614
+ path.join(packageRoot, "dist", "bin", "exe-start-codex.js"),
1615
+ path.join(packageRoot, "src", "bin", "exe-start-codex.ts")
1616
+ ];
1617
+ let codexLauncher = null;
1618
+ for (const c of codexLauncherCandidates) {
1619
+ if (existsSync(c)) {
1620
+ codexLauncher = c;
1621
+ break;
1622
+ }
1623
+ }
1624
+ if (codexLauncher) {
1625
+ for (const emp of employees) {
1626
+ const wrapperPath = path.join(binDir, `${emp.name}-codex`);
1627
+ const content = `#!/bin/bash
1628
+ exec node "${codexLauncher}" --agent ${emp.name} "$@"
1629
+ `;
1630
+ writeFileSync(wrapperPath, content);
1631
+ chmodSync(wrapperPath, 493);
1632
+ created++;
1633
+ }
1634
+ }
1613
1635
  const pathConfigured = ensurePath(home, binDir);
1614
1636
  return { created, pathConfigured };
1615
1637
  }
@@ -1792,39 +1792,75 @@ var init_provider_table = __esm({
1792
1792
  }
1793
1793
  });
1794
1794
 
1795
- // src/lib/intercom-queue.ts
1796
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, renameSync as renameSync3, existsSync as existsSync5, mkdirSync as mkdirSync2 } from "fs";
1795
+ // src/lib/runtime-table.ts
1796
+ var RUNTIME_TABLE;
1797
+ var init_runtime_table = __esm({
1798
+ "src/lib/runtime-table.ts"() {
1799
+ "use strict";
1800
+ RUNTIME_TABLE = {
1801
+ codex: {
1802
+ binary: "codex",
1803
+ launchMode: "exec",
1804
+ autoApproveFlag: "--full-auto",
1805
+ inlineFlag: "--no-alt-screen",
1806
+ apiKeyEnv: "OPENAI_API_KEY",
1807
+ defaultModel: "gpt-5.4"
1808
+ }
1809
+ };
1810
+ }
1811
+ });
1812
+
1813
+ // src/lib/agent-config.ts
1814
+ import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync5, mkdirSync as mkdirSync2 } from "fs";
1797
1815
  import path6 from "path";
1816
+ var AGENT_CONFIG_PATH, DEFAULT_MODELS;
1817
+ var init_agent_config = __esm({
1818
+ "src/lib/agent-config.ts"() {
1819
+ "use strict";
1820
+ init_config();
1821
+ init_runtime_table();
1822
+ AGENT_CONFIG_PATH = path6.join(EXE_AI_DIR, "agent-config.json");
1823
+ DEFAULT_MODELS = {
1824
+ claude: "claude-opus-4",
1825
+ codex: RUNTIME_TABLE.codex?.defaultModel ?? "gpt-5.4",
1826
+ opencode: "minimax-m2.7"
1827
+ };
1828
+ }
1829
+ });
1830
+
1831
+ // src/lib/intercom-queue.ts
1832
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, renameSync as renameSync3, existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
1833
+ import path7 from "path";
1798
1834
  import os5 from "os";
1799
1835
  var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
1800
1836
  var init_intercom_queue = __esm({
1801
1837
  "src/lib/intercom-queue.ts"() {
1802
1838
  "use strict";
1803
- QUEUE_PATH = path6.join(os5.homedir(), ".exe-os", "intercom-queue.json");
1839
+ QUEUE_PATH = path7.join(os5.homedir(), ".exe-os", "intercom-queue.json");
1804
1840
  TTL_MS = 60 * 60 * 1e3;
1805
- INTERCOM_LOG = path6.join(os5.homedir(), ".exe-os", "intercom.log");
1841
+ INTERCOM_LOG = path7.join(os5.homedir(), ".exe-os", "intercom.log");
1806
1842
  }
1807
1843
  });
1808
1844
 
1809
1845
  // src/lib/license.ts
1810
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
1846
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, existsSync as existsSync7, mkdirSync as mkdirSync4 } from "fs";
1811
1847
  import { randomUUID as randomUUID2 } from "crypto";
1812
- import path7 from "path";
1848
+ import path8 from "path";
1813
1849
  import { jwtVerify, importSPKI } from "jose";
1814
1850
  var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH;
1815
1851
  var init_license = __esm({
1816
1852
  "src/lib/license.ts"() {
1817
1853
  "use strict";
1818
1854
  init_config();
1819
- LICENSE_PATH = path7.join(EXE_AI_DIR, "license.key");
1820
- CACHE_PATH = path7.join(EXE_AI_DIR, "license-cache.json");
1821
- DEVICE_ID_PATH = path7.join(EXE_AI_DIR, "device-id");
1855
+ LICENSE_PATH = path8.join(EXE_AI_DIR, "license.key");
1856
+ CACHE_PATH = path8.join(EXE_AI_DIR, "license-cache.json");
1857
+ DEVICE_ID_PATH = path8.join(EXE_AI_DIR, "device-id");
1822
1858
  }
1823
1859
  });
1824
1860
 
1825
1861
  // src/lib/plan-limits.ts
1826
- import { readFileSync as readFileSync5, existsSync as existsSync7 } from "fs";
1827
- import path8 from "path";
1862
+ import { readFileSync as readFileSync6, existsSync as existsSync8 } from "fs";
1863
+ import path9 from "path";
1828
1864
  var CACHE_PATH2;
1829
1865
  var init_plan_limits = __esm({
1830
1866
  "src/lib/plan-limits.ts"() {
@@ -1833,12 +1869,12 @@ var init_plan_limits = __esm({
1833
1869
  init_employees();
1834
1870
  init_license();
1835
1871
  init_config();
1836
- CACHE_PATH2 = path8.join(EXE_AI_DIR, "license-cache.json");
1872
+ CACHE_PATH2 = path9.join(EXE_AI_DIR, "license-cache.json");
1837
1873
  }
1838
1874
  });
1839
1875
 
1840
1876
  // src/lib/tmux-routing.ts
1841
- import path9 from "path";
1877
+ import path10 from "path";
1842
1878
  import os6 from "os";
1843
1879
  import { fileURLToPath } from "url";
1844
1880
  var SPAWN_LOCK_DIR, SESSION_CACHE, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS;
@@ -1851,13 +1887,15 @@ var init_tmux_routing = __esm({
1851
1887
  init_cc_agent_support();
1852
1888
  init_mcp_prefix();
1853
1889
  init_provider_table();
1890
+ init_agent_config();
1891
+ init_runtime_table();
1854
1892
  init_intercom_queue();
1855
1893
  init_plan_limits();
1856
1894
  init_employees();
1857
- SPAWN_LOCK_DIR = path9.join(os6.homedir(), ".exe-os", "spawn-locks");
1858
- SESSION_CACHE = path9.join(os6.homedir(), ".exe-os", "session-cache");
1859
- INTERCOM_LOG2 = path9.join(os6.homedir(), ".exe-os", "intercom.log");
1860
- DEBOUNCE_FILE = path9.join(SESSION_CACHE, "intercom-debounce.json");
1895
+ SPAWN_LOCK_DIR = path10.join(os6.homedir(), ".exe-os", "spawn-locks");
1896
+ SESSION_CACHE = path10.join(os6.homedir(), ".exe-os", "session-cache");
1897
+ INTERCOM_LOG2 = path10.join(os6.homedir(), ".exe-os", "intercom.log");
1898
+ DEBOUNCE_FILE = path10.join(SESSION_CACHE, "intercom-debounce.json");
1861
1899
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
1862
1900
  }
1863
1901
  });