@askexenow/exe-os 0.8.38 → 0.8.40

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 (91) hide show
  1. package/README.md +17 -8
  2. package/dist/bin/backfill-conversations.js +46 -10
  3. package/dist/bin/backfill-responses.js +46 -10
  4. package/dist/bin/backfill-vectors.js +42 -8
  5. package/dist/bin/cleanup-stale-review-tasks.js +37 -8
  6. package/dist/bin/cli.js +291 -162
  7. package/dist/bin/exe-agent.js +19 -4
  8. package/dist/bin/exe-assign.js +39 -5
  9. package/dist/bin/exe-boot.js +237 -111
  10. package/dist/bin/exe-call.js +11 -6
  11. package/dist/bin/exe-cloud.js +99 -28
  12. package/dist/bin/exe-dispatch.js +1 -1
  13. package/dist/bin/exe-doctor.js +37 -8
  14. package/dist/bin/exe-export-behaviors.js +39 -10
  15. package/dist/bin/exe-forget.js +38 -9
  16. package/dist/bin/exe-gateway.js +109 -42
  17. package/dist/bin/exe-heartbeat.js +49 -20
  18. package/dist/bin/exe-kill.js +39 -10
  19. package/dist/bin/exe-launch-agent.js +58 -22
  20. package/dist/bin/exe-link.js +184 -85
  21. package/dist/bin/exe-new-employee.js +21 -7
  22. package/dist/bin/exe-pending-messages.js +46 -17
  23. package/dist/bin/exe-pending-notifications.js +37 -8
  24. package/dist/bin/exe-pending-reviews.js +47 -18
  25. package/dist/bin/exe-rename.js +21 -7
  26. package/dist/bin/exe-review.js +34 -5
  27. package/dist/bin/exe-search.js +47 -10
  28. package/dist/bin/exe-session-cleanup.js +56 -19
  29. package/dist/bin/exe-settings.js +63 -2
  30. package/dist/bin/exe-status.js +34 -5
  31. package/dist/bin/exe-team.js +34 -5
  32. package/dist/bin/git-sweep.js +38 -9
  33. package/dist/bin/graph-backfill.js +37 -8
  34. package/dist/bin/graph-export.js +37 -8
  35. package/dist/bin/install.js +1 -1
  36. package/dist/bin/scan-tasks.js +40 -11
  37. package/dist/bin/setup.js +58 -24
  38. package/dist/bin/shard-migrate.js +37 -8
  39. package/dist/bin/wiki-sync.js +39 -9
  40. package/dist/gateway/index.js +102 -37
  41. package/dist/hooks/bug-report-worker.js +62 -28
  42. package/dist/hooks/commit-complete.js +38 -9
  43. package/dist/hooks/error-recall.js +49 -8
  44. package/dist/hooks/exe-heartbeat-hook.js +3 -2
  45. package/dist/hooks/ingest-worker.js +151 -37
  46. package/dist/hooks/ingest.js +74 -28
  47. package/dist/hooks/instructions-loaded.js +39 -9
  48. package/dist/hooks/notification.js +37 -7
  49. package/dist/hooks/post-compact.js +37 -7
  50. package/dist/hooks/pre-compact.js +35 -6
  51. package/dist/hooks/pre-tool-use.js +52 -14
  52. package/dist/hooks/prompt-ingest-worker.js +56 -10
  53. package/dist/hooks/prompt-submit.js +61 -23
  54. package/dist/hooks/response-ingest-worker.js +57 -11
  55. package/dist/hooks/session-end.js +43 -10
  56. package/dist/hooks/session-start.js +46 -8
  57. package/dist/hooks/stop.js +37 -7
  58. package/dist/hooks/subagent-stop.js +37 -7
  59. package/dist/hooks/summary-worker.js +317 -99
  60. package/dist/index.js +87 -22
  61. package/dist/lib/cloud-sync.js +172 -78
  62. package/dist/lib/config.js +4 -1
  63. package/dist/lib/consolidation.js +5 -4
  64. package/dist/lib/database.js +1 -0
  65. package/dist/lib/device-registry.js +2 -1
  66. package/dist/lib/embedder.js +9 -1
  67. package/dist/lib/employees.js +11 -6
  68. package/dist/lib/exe-daemon-client.js +6 -1
  69. package/dist/lib/exe-daemon.js +71 -28
  70. package/dist/lib/hybrid-search.js +47 -10
  71. package/dist/lib/identity.js +1 -1
  72. package/dist/lib/keychain.js +2 -1
  73. package/dist/lib/license.js +13 -4
  74. package/dist/lib/messaging.js +1 -1
  75. package/dist/lib/reminders.js +2 -2
  76. package/dist/lib/schedules.js +37 -8
  77. package/dist/lib/skill-learning.js +1 -1
  78. package/dist/lib/store.js +37 -8
  79. package/dist/lib/tasks.js +1 -1
  80. package/dist/lib/tmux-routing.js +1 -1
  81. package/dist/mcp/server.js +97 -43
  82. package/dist/mcp/tools/complete-reminder.js +1 -1
  83. package/dist/mcp/tools/create-task.js +14 -6
  84. package/dist/mcp/tools/deactivate-behavior.js +2 -2
  85. package/dist/mcp/tools/list-reminders.js +1 -1
  86. package/dist/mcp/tools/list-tasks.js +1 -1
  87. package/dist/mcp/tools/send-message.js +1 -1
  88. package/dist/mcp/tools/update-task.js +1 -1
  89. package/dist/runtime/index.js +35 -6
  90. package/dist/tui/App.js +187 -103
  91. package/package.json +3 -3
package/dist/bin/cli.js CHANGED
@@ -42,7 +42,7 @@ __export(config_exports, {
42
42
  migrateConfig: () => migrateConfig,
43
43
  saveConfig: () => saveConfig
44
44
  });
45
- import { readFile, writeFile, mkdir } from "fs/promises";
45
+ import { readFile, writeFile, mkdir, chmod } from "fs/promises";
46
46
  import { readFileSync, existsSync, renameSync } from "fs";
47
47
  import path from "path";
48
48
  import os from "os";
@@ -168,6 +168,9 @@ async function saveConfig(config) {
168
168
  await mkdir(dir, { recursive: true });
169
169
  const configPath = path.join(dir, "config.json");
170
170
  await writeFile(configPath, JSON.stringify(config, null, 2) + "\n");
171
+ if (config.cloud?.apiKey) {
172
+ await chmod(configPath, 384);
173
+ }
171
174
  }
172
175
  async function loadConfigFrom(configPath) {
173
176
  const raw = await readFile(configPath, "utf-8");
@@ -356,15 +359,20 @@ function addEmployee(employees, employee) {
356
359
  }
357
360
  return [...employees, normalized];
358
361
  }
362
+ function findExeBin() {
363
+ try {
364
+ return execSync(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
365
+ } catch {
366
+ return null;
367
+ }
368
+ }
359
369
  function registerBinSymlinks(name) {
360
370
  const created = [];
361
371
  const skipped = [];
362
372
  const errors = [];
363
- let exeBinPath;
364
- try {
365
- exeBinPath = execSync("which exe", { encoding: "utf-8" }).trim();
366
- } catch {
367
- errors.push("Could not find 'exe' in PATH");
373
+ const exeBinPath = findExeBin();
374
+ if (!exeBinPath) {
375
+ errors.push("Could not find 'exe-os' in PATH");
368
376
  return { created, skipped, errors };
369
377
  }
370
378
  const binDir = path2.dirname(exeBinPath);
@@ -1096,6 +1104,7 @@ async function ensureSchema() {
1096
1104
  const client = getRawClient();
1097
1105
  await client.execute("PRAGMA journal_mode = WAL");
1098
1106
  await client.execute("PRAGMA busy_timeout = 30000");
1107
+ await client.execute("PRAGMA wal_autocheckpoint = 1000");
1099
1108
  try {
1100
1109
  await client.execute("PRAGMA libsql_vector_search_ef = 128");
1101
1110
  } catch {
@@ -1912,12 +1921,13 @@ __export(keychain_exports, {
1912
1921
  importMnemonic: () => importMnemonic,
1913
1922
  setMasterKey: () => setMasterKey
1914
1923
  });
1915
- import { readFile as readFile4, writeFile as writeFile4, unlink, mkdir as mkdir4, chmod } from "fs/promises";
1924
+ import { readFile as readFile4, writeFile as writeFile4, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
1916
1925
  import { existsSync as existsSync5 } from "fs";
1917
1926
  import path5 from "path";
1927
+ import os4 from "os";
1918
1928
  import crypto from "crypto";
1919
1929
  function getKeyDir() {
1920
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path5.join(process.env.HOME ?? "/tmp", ".exe-os");
1930
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path5.join(os4.homedir(), ".exe-os");
1921
1931
  }
1922
1932
  function getKeyPath() {
1923
1933
  return path5.join(getKeyDir(), "master.key");
@@ -1965,7 +1975,7 @@ async function setMasterKey(key) {
1965
1975
  await mkdir4(dir, { recursive: true });
1966
1976
  const keyPath = getKeyPath();
1967
1977
  await writeFile4(keyPath, b64 + "\n", "utf-8");
1968
- await chmod(keyPath, 384);
1978
+ await chmod2(keyPath, 384);
1969
1979
  }
1970
1980
  async function deleteMasterKey() {
1971
1981
  const keytar = await tryKeytar();
@@ -2307,6 +2317,28 @@ __export(store_exports, {
2307
2317
  vectorToBlob: () => vectorToBlob,
2308
2318
  writeMemory: () => writeMemory
2309
2319
  });
2320
+ function isBusyError2(err) {
2321
+ if (err instanceof Error) {
2322
+ const msg = err.message.toLowerCase();
2323
+ return msg.includes("sqlite_busy") || msg.includes("database is locked");
2324
+ }
2325
+ return false;
2326
+ }
2327
+ async function retryOnBusy2(fn, label) {
2328
+ for (let attempt = 0; attempt <= INIT_MAX_RETRIES; attempt++) {
2329
+ try {
2330
+ return await fn();
2331
+ } catch (err) {
2332
+ if (!isBusyError2(err) || attempt === INIT_MAX_RETRIES) throw err;
2333
+ process.stderr.write(
2334
+ `[store] SQLITE_BUSY during ${label}, retry ${attempt + 1}/${INIT_MAX_RETRIES}
2335
+ `
2336
+ );
2337
+ await new Promise((r) => setTimeout(r, INIT_RETRY_DELAY_MS * (attempt + 1)));
2338
+ }
2339
+ }
2340
+ throw new Error("unreachable");
2341
+ }
2310
2342
  async function initStore(options) {
2311
2343
  if (_flushTimer !== null) {
2312
2344
  clearInterval(_flushTimer);
@@ -2335,14 +2367,17 @@ async function initStore(options) {
2335
2367
  dbPath,
2336
2368
  encryptionKey: hexKey
2337
2369
  });
2338
- await ensureSchema();
2370
+ await retryOnBusy2(() => ensureSchema(), "ensureSchema");
2339
2371
  try {
2340
2372
  const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
2341
2373
  initShardManager2(hexKey);
2342
2374
  } catch {
2343
2375
  }
2344
2376
  const client = getClient();
2345
- const vResult = await client.execute("SELECT MAX(version) as max_v FROM memories");
2377
+ const vResult = await retryOnBusy2(
2378
+ () => client.execute("SELECT MAX(version) as max_v FROM memories"),
2379
+ "version-query"
2380
+ );
2346
2381
  _nextVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
2347
2382
  }
2348
2383
  function classifyTier(record) {
@@ -2722,7 +2757,7 @@ async function getMemoryCardinality(agentId) {
2722
2757
  return 0;
2723
2758
  }
2724
2759
  }
2725
- var _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
2760
+ var INIT_MAX_RETRIES, INIT_RETRY_DELAY_MS, _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
2726
2761
  var init_store = __esm({
2727
2762
  "src/lib/store.ts"() {
2728
2763
  "use strict";
@@ -2730,6 +2765,8 @@ var init_store = __esm({
2730
2765
  init_database();
2731
2766
  init_keychain();
2732
2767
  init_config();
2768
+ INIT_MAX_RETRIES = 3;
2769
+ INIT_RETRY_DELAY_MS = 1e3;
2733
2770
  _pendingRecords = [];
2734
2771
  _batchSize = 20;
2735
2772
  _flushIntervalMs = 1e4;
@@ -2748,6 +2785,10 @@ import path7 from "path";
2748
2785
  import { fileURLToPath as fileURLToPath2 } from "url";
2749
2786
  function handleData(chunk) {
2750
2787
  _buffer += chunk.toString();
2788
+ if (_buffer.length > MAX_BUFFER) {
2789
+ _buffer = "";
2790
+ return;
2791
+ }
2751
2792
  let newlineIdx;
2752
2793
  while ((newlineIdx = _buffer.indexOf("\n")) !== -1) {
2753
2794
  const line = _buffer.slice(0, newlineIdx).trim();
@@ -3055,7 +3096,7 @@ function disconnectClient() {
3055
3096
  entry.resolve({ error: "Client disconnected" });
3056
3097
  }
3057
3098
  }
3058
- var SOCKET_PATH, PID_PATH, SPAWN_LOCK_PATH, SPAWN_LOCK_STALE_MS, CONNECT_TIMEOUT_MS, REQUEST_TIMEOUT_MS, _socket, _connected, _buffer, _requestCount, HEALTH_CHECK_INTERVAL, _pending;
3099
+ var SOCKET_PATH, PID_PATH, SPAWN_LOCK_PATH, SPAWN_LOCK_STALE_MS, CONNECT_TIMEOUT_MS, REQUEST_TIMEOUT_MS, _socket, _connected, _buffer, _requestCount, HEALTH_CHECK_INTERVAL, _pending, MAX_BUFFER;
3059
3100
  var init_exe_daemon_client = __esm({
3060
3101
  "src/lib/exe-daemon-client.ts"() {
3061
3102
  "use strict";
@@ -3072,6 +3113,7 @@ var init_exe_daemon_client = __esm({
3072
3113
  _requestCount = 0;
3073
3114
  HEALTH_CHECK_INTERVAL = 100;
3074
3115
  _pending = /* @__PURE__ */ new Map();
3116
+ MAX_BUFFER = 1e7;
3075
3117
  }
3076
3118
  });
3077
3119
 
@@ -3109,7 +3151,8 @@ import { parseArgs } from "util";
3109
3151
  async function findJsonlFiles(sinceDate, projectFilter) {
3110
3152
  const projectsDir = path8.join(homedir(), ".claude", "projects");
3111
3153
  const files = [];
3112
- async function walk(dir) {
3154
+ async function walk(dir, depth = 0) {
3155
+ if (depth > MAX_WALK_DEPTH) return;
3113
3156
  let entries;
3114
3157
  try {
3115
3158
  entries = await readdir2(dir, { withFileTypes: true });
@@ -3120,7 +3163,7 @@ async function findJsonlFiles(sinceDate, projectFilter) {
3120
3163
  const full = path8.join(dir, entry.name);
3121
3164
  if (entry.isDirectory()) {
3122
3165
  if (entry.name === "subagents" || entry.name === "tool-results") continue;
3123
- await walk(full);
3166
+ await walk(full, depth + 1);
3124
3167
  } else if (entry.name.endsWith(".jsonl")) {
3125
3168
  try {
3126
3169
  const s = await stat(full);
@@ -3438,7 +3481,7 @@ async function backfillConversations(options) {
3438
3481
  );
3439
3482
  return stats;
3440
3483
  }
3441
- var TOOL_NAME, MIN_MESSAGES, MAX_SUMMARY_LENGTH;
3484
+ var TOOL_NAME, MIN_MESSAGES, MAX_SUMMARY_LENGTH, MAX_WALK_DEPTH;
3442
3485
  var init_backfill_conversations = __esm({
3443
3486
  "src/bin/backfill-conversations.ts"() {
3444
3487
  "use strict";
@@ -3449,6 +3492,7 @@ var init_backfill_conversations = __esm({
3449
3492
  TOOL_NAME = "backfill-conversation";
3450
3493
  MIN_MESSAGES = 3;
3451
3494
  MAX_SUMMARY_LENGTH = 4e3;
3495
+ MAX_WALK_DEPTH = 10;
3452
3496
  if (isMainModule(import.meta.url)) {
3453
3497
  const { values } = parseArgs({
3454
3498
  options: {
@@ -4227,9 +4271,17 @@ async function renameEmployee(oldName, newName, opts = {}) {
4227
4271
  return { success: false, error: err instanceof Error ? err.message : String(err) };
4228
4272
  }
4229
4273
  }
4274
+ function findExeBin2() {
4275
+ try {
4276
+ return execSync2(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
4277
+ } catch {
4278
+ return null;
4279
+ }
4280
+ }
4230
4281
  function removeOldSymlinks(name) {
4231
4282
  try {
4232
- const exeBinPath = execSync2("which exe", { encoding: "utf-8" }).trim();
4283
+ const exeBinPath = findExeBin2();
4284
+ if (!exeBinPath) return;
4233
4285
  const binDir = path9.dirname(exeBinPath);
4234
4286
  for (const suffix of ["", "-opencode"]) {
4235
4287
  const linkPath = path9.join(binDir, `${name}${suffix}`);
@@ -4408,8 +4460,8 @@ async function embedDirect(text) {
4408
4460
  const llamaCpp = await import("node-llama-cpp");
4409
4461
  const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
4410
4462
  const { existsSync: existsSync22 } = await import("fs");
4411
- const path32 = await import("path");
4412
- const modelPath = path32.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
4463
+ const path34 = await import("path");
4464
+ const modelPath = path34.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
4413
4465
  if (!existsSync22(modelPath)) {
4414
4466
  throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
4415
4467
  }
@@ -4459,6 +4511,14 @@ import { readFileSync as readFileSync6, writeFileSync as writeFileSync2, existsS
4459
4511
  import { randomUUID as randomUUID2 } from "crypto";
4460
4512
  import path11 from "path";
4461
4513
  import { jwtVerify, importSPKI } from "jose";
4514
+ async function fetchRetry(url, init) {
4515
+ try {
4516
+ return await fetch(url, init);
4517
+ } catch {
4518
+ await new Promise((r) => setTimeout(r, RETRY_DELAY_MS));
4519
+ return fetch(url, { ...init, signal: AbortSignal.timeout(1e4) });
4520
+ }
4521
+ }
4462
4522
  function loadDeviceId() {
4463
4523
  const deviceJsonPath = path11.join(EXE_AI_DIR, "device.json");
4464
4524
  try {
@@ -4490,7 +4550,7 @@ function loadLicense() {
4490
4550
  }
4491
4551
  function saveLicense(apiKey) {
4492
4552
  mkdirSync3(EXE_AI_DIR, { recursive: true });
4493
- writeFileSync2(LICENSE_PATH, apiKey.trim(), "utf8");
4553
+ writeFileSync2(LICENSE_PATH, apiKey.trim(), { encoding: "utf8", mode: 384 });
4494
4554
  }
4495
4555
  async function verifyLicenseJwt(token) {
4496
4556
  try {
@@ -4542,7 +4602,7 @@ function cacheResponse(token) {
4542
4602
  async function validateLicense(apiKey, deviceId) {
4543
4603
  const did = deviceId ?? loadDeviceId();
4544
4604
  try {
4545
- const res = await fetch(`${API_BASE}/auth/activate`, {
4605
+ const res = await fetchRetry(`${API_BASE}/auth/activate`, {
4546
4606
  method: "POST",
4547
4607
  headers: { "Content-Type": "application/json" },
4548
4608
  body: JSON.stringify({ apiKey, deviceId: did }),
@@ -4633,7 +4693,7 @@ async function assertVpsLicense(opts) {
4633
4693
  let explicitRejection = false;
4634
4694
  let transientFailure = false;
4635
4695
  try {
4636
- const res = await fetch(`${API_BASE}/auth/activate`, {
4696
+ const res = await fetchRetry(`${API_BASE}/auth/activate`, {
4637
4697
  method: "POST",
4638
4698
  headers: { "Content-Type": "application/json" },
4639
4699
  body: JSON.stringify({ apiKey, deviceId }),
@@ -4735,7 +4795,7 @@ function stopLicenseRevalidation() {
4735
4795
  _revalTimer = null;
4736
4796
  }
4737
4797
  }
4738
- var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH, API_BASE, LICENSE_PUBLIC_KEY_PEM, LICENSE_JWT_ALG, PLAN_LIMITS, FREE_LICENSE, CACHE_MAX_AGE_MS, _revalTimer;
4798
+ var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH, API_BASE, RETRY_DELAY_MS, LICENSE_PUBLIC_KEY_PEM, LICENSE_JWT_ALG, PLAN_LIMITS, FREE_LICENSE, CACHE_MAX_AGE_MS, _revalTimer;
4739
4799
  var init_license = __esm({
4740
4800
  "src/lib/license.ts"() {
4741
4801
  "use strict";
@@ -4744,6 +4804,7 @@ var init_license = __esm({
4744
4804
  CACHE_PATH = path11.join(EXE_AI_DIR, "license-cache.json");
4745
4805
  DEVICE_ID_PATH = path11.join(EXE_AI_DIR, "device-id");
4746
4806
  API_BASE = "https://askexe.com/cloud";
4807
+ RETRY_DELAY_MS = 500;
4747
4808
  LICENSE_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----
4748
4809
  MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
4749
4810
  4uj+UqeKCcvtgNHKmOK278HJaJcANe9xAeji8AFYu27q3WtzCi04pHudow==
@@ -5443,7 +5504,7 @@ __export(setup_wizard_exports, {
5443
5504
  });
5444
5505
  import crypto3 from "crypto";
5445
5506
  import { existsSync as existsSync12, mkdirSync as mkdirSync5, readFileSync as readFileSync8, writeFileSync as writeFileSync4, unlinkSync as unlinkSync4 } from "fs";
5446
- import os4 from "os";
5507
+ import os5 from "os";
5447
5508
  import path13 from "path";
5448
5509
  import { createInterface as createInterface2 } from "readline";
5449
5510
  function loadSetupState() {
@@ -5536,12 +5597,23 @@ async function runSetupWizard(opts = {}) {
5536
5597
  try {
5537
5598
  const { loadDeviceId: loadDeviceId2 } = await Promise.resolve().then(() => (init_license(), license_exports));
5538
5599
  const deviceId = loadDeviceId2();
5539
- const res = await fetch("https://askexe.com/cloud/auth/auto-provision", {
5540
- method: "POST",
5541
- headers: { "Content-Type": "application/json" },
5542
- body: JSON.stringify({ deviceId }),
5543
- signal: AbortSignal.timeout(1e4)
5544
- });
5600
+ let res;
5601
+ try {
5602
+ res = await fetch("https://askexe.com/cloud/auth/auto-provision", {
5603
+ method: "POST",
5604
+ headers: { "Content-Type": "application/json" },
5605
+ body: JSON.stringify({ deviceId }),
5606
+ signal: AbortSignal.timeout(1e4)
5607
+ });
5608
+ } catch {
5609
+ await new Promise((r) => setTimeout(r, 500));
5610
+ res = await fetch("https://askexe.com/cloud/auth/auto-provision", {
5611
+ method: "POST",
5612
+ headers: { "Content-Type": "application/json" },
5613
+ body: JSON.stringify({ deviceId }),
5614
+ signal: AbortSignal.timeout(1e4)
5615
+ });
5616
+ }
5545
5617
  if (res.ok) {
5546
5618
  const data = await res.json();
5547
5619
  if (data.apiKey) {
@@ -5599,7 +5671,7 @@ async function runSetupWizard(opts = {}) {
5599
5671
  await saveConfig(config);
5600
5672
  log("");
5601
5673
  try {
5602
- const claudeJsonPath = path13.join(os4.homedir(), ".claude.json");
5674
+ const claudeJsonPath = path13.join(os5.homedir(), ".claude.json");
5603
5675
  let claudeJson = {};
5604
5676
  try {
5605
5677
  claudeJson = JSON.parse(readFileSync8(claudeJsonPath, "utf8"));
@@ -5607,7 +5679,7 @@ async function runSetupWizard(opts = {}) {
5607
5679
  }
5608
5680
  if (!claudeJson.projects) claudeJson.projects = {};
5609
5681
  const projects = claudeJson.projects;
5610
- for (const dir of [process.cwd(), os4.homedir()]) {
5682
+ for (const dir of [process.cwd(), os5.homedir()]) {
5611
5683
  if (!projects[dir]) projects[dir] = {};
5612
5684
  projects[dir].hasTrustDialogAccepted = true;
5613
5685
  }
@@ -5851,7 +5923,7 @@ var init_setup_wizard = __esm({
5851
5923
  init_config();
5852
5924
  init_keychain();
5853
5925
  init_model_downloader();
5854
- SETUP_STATE_PATH = path13.join(os4.homedir(), ".exe-os", "setup-state.json");
5926
+ SETUP_STATE_PATH = path13.join(os5.homedir(), ".exe-os", "setup-state.json");
5855
5927
  }
5856
5928
  });
5857
5929
 
@@ -10213,8 +10285,8 @@ var init_ErrorOverview = __esm({
10213
10285
  "use strict";
10214
10286
  init_Box();
10215
10287
  init_Text();
10216
- cleanupPath = (path32) => {
10217
- return path32?.replace(`file://${cwd()}/`, "");
10288
+ cleanupPath = (path34) => {
10289
+ return path34?.replace(`file://${cwd()}/`, "");
10218
10290
  };
10219
10291
  stackUtils = new StackUtils({
10220
10292
  cwd: cwd(),
@@ -12174,6 +12246,7 @@ var init_terminal = __esm({
12174
12246
  });
12175
12247
 
12176
12248
  // src/tui/Sidebar.tsx
12249
+ import React14 from "react";
12177
12250
  import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
12178
12251
  function Sidebar({
12179
12252
  active,
@@ -12504,7 +12577,7 @@ var init_tmux_status = __esm({
12504
12577
  });
12505
12578
 
12506
12579
  // src/tui/Footer.tsx
12507
- import { useState as useState4, useEffect as useEffect6 } from "react";
12580
+ import React15, { useState as useState4, useEffect as useEffect6 } from "react";
12508
12581
  import { Fragment, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
12509
12582
  function Footer() {
12510
12583
  const demo = useDemo();
@@ -12637,6 +12710,7 @@ var init_Footer = __esm({
12637
12710
  });
12638
12711
 
12639
12712
  // src/tui/components/StatusDot.tsx
12713
+ import React16 from "react";
12640
12714
  import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
12641
12715
  function StatusDot({ status, showLabel = true }) {
12642
12716
  const { char, dotColor, label, labelColor } = STATUS_CONFIG[status];
@@ -12668,7 +12742,7 @@ var init_demo_data = __esm({
12668
12742
  "src/tui/demo-data.ts"() {
12669
12743
  "use strict";
12670
12744
  DEMO_EMPLOYEES = [
12671
- { name: "exe", role: "COO", status: "active", activity: "Reviewing yoshi's task-aware behavior injection PR", memoryCount: 16409, projects: [
12745
+ { name: "exe", role: "COO", status: "active", activity: "Reviewing yoshi's task-aware behavior injection PR", memoryCount: 15e3, projects: [
12672
12746
  { name: "exe-os", status: "active" },
12673
12747
  { name: "exe-create", status: "has_tasks" },
12674
12748
  { name: "openclaw", status: "idle" }
@@ -12677,7 +12751,7 @@ var init_demo_data = __esm({
12677
12751
  "Dispatched behavior injection task",
12678
12752
  "Approved gateway Phase 4"
12679
12753
  ] },
12680
- { name: "yoshi", role: "CTO", status: "active", activity: "Implementing skill learning trajectory capture", memoryCount: 8164, projects: [
12754
+ { name: "yoshi", role: "CTO", status: "active", activity: "Implementing skill learning trajectory capture", memoryCount: 8e3, projects: [
12681
12755
  { name: "exe-os", status: "active" },
12682
12756
  { name: "exe-create", status: "idle" }
12683
12757
  ], recentTasks: [
@@ -12685,7 +12759,7 @@ var init_demo_data = __esm({
12685
12759
  "Fixed TUI mouse listener leak",
12686
12760
  "Built task-aware behavior injection"
12687
12761
  ] },
12688
- { name: "mari", role: "CMO", status: "idle", activity: "", memoryCount: 2158, projects: [
12762
+ { name: "mari", role: "CMO", status: "idle", activity: "", memoryCount: 2e3, projects: [
12689
12763
  { name: "exe-build-skills", status: "has_tasks" },
12690
12764
  { name: "exe-os", status: "idle" }
12691
12765
  ], recentTasks: [
@@ -12693,13 +12767,13 @@ var init_demo_data = __esm({
12693
12767
  "Designed exe-os UI system",
12694
12768
  "Fixed logo layouts"
12695
12769
  ] },
12696
- { name: "tom", role: "Principal Engineer", status: "idle", activity: "", memoryCount: 689, projects: [
12770
+ { name: "tom", role: "Principal Engineer", status: "idle", activity: "", memoryCount: 700, projects: [
12697
12771
  { name: "exe-os", status: "idle" }
12698
12772
  ], recentTasks: [
12699
12773
  "Implemented BashTool sandboxed execution",
12700
12774
  "Ported session scoping to exe-agent-memory"
12701
12775
  ] },
12702
- { name: "sasha", role: "Content Production", status: "offline", activity: "", memoryCount: 60, projects: [
12776
+ { name: "sasha", role: "Content Production", status: "offline", activity: "", memoryCount: 50, projects: [
12703
12777
  { name: "exe-build-skills", status: "idle" }
12704
12778
  ], recentTasks: [
12705
12779
  "Rendered carousel export prototype"
@@ -12712,7 +12786,7 @@ var init_demo_data = __esm({
12712
12786
  { time: "11:15", agent: "mari", action: "Completed exe-os UI design system" },
12713
12787
  { time: "10:50", agent: "exe", action: "Approved gateway Phase 4" }
12714
12788
  ];
12715
- DEMO_HEALTH = { memories: 27453, daemon: "running", cloud: "disabled" };
12789
+ DEMO_HEALTH = { memories: 25750, daemon: "running", cloud: "disabled" };
12716
12790
  DEMO_PROJECTS = [
12717
12791
  {
12718
12792
  projectName: "exe-os",
@@ -14580,7 +14654,7 @@ var init_hooks = __esm({
14580
14654
 
14581
14655
  // src/runtime/safety-checks.ts
14582
14656
  import path14 from "path";
14583
- import os5 from "os";
14657
+ import os6 from "os";
14584
14658
  function checkPathSafety(filePath) {
14585
14659
  const resolved = path14.resolve(filePath);
14586
14660
  for (const { pattern, reason } of BYPASS_IMMUNE_PATTERNS) {
@@ -14607,7 +14681,7 @@ var HOME, BYPASS_IMMUNE_PATTERNS;
14607
14681
  var init_safety_checks = __esm({
14608
14682
  "src/runtime/safety-checks.ts"() {
14609
14683
  "use strict";
14610
- HOME = os5.homedir();
14684
+ HOME = os6.homedir();
14611
14685
  BYPASS_IMMUNE_PATTERNS = [
14612
14686
  {
14613
14687
  pattern: /\/\.git\/hooks\//,
@@ -14839,8 +14913,13 @@ function runRipgrep(input, searchPath, context) {
14839
14913
  timeout: 3e4,
14840
14914
  stdio: ["ignore", "pipe", "pipe"]
14841
14915
  });
14916
+ const MAX_OUTPUT = 1e7;
14842
14917
  const chunks = [];
14843
- child.stdout.on("data", (chunk) => chunks.push(chunk));
14918
+ let totalSize = 0;
14919
+ child.stdout.on("data", (chunk) => {
14920
+ totalSize += chunk.length;
14921
+ if (totalSize <= MAX_OUTPUT) chunks.push(chunk);
14922
+ });
14844
14923
  const onAbort = () => child.kill("SIGTERM");
14845
14924
  context.abortSignal.addEventListener("abort", onAbort, { once: true });
14846
14925
  child.on("close", (code) => {
@@ -15224,10 +15303,19 @@ var init_bash = __esm({
15224
15303
  stdio: ["ignore", "pipe", "pipe"],
15225
15304
  env: { ...process.env }
15226
15305
  });
15306
+ const MAX_OUTPUT_SIZE = 5242880;
15227
15307
  const stdoutChunks = [];
15228
15308
  const stderrChunks = [];
15229
- child.stdout.on("data", (chunk) => stdoutChunks.push(chunk));
15230
- child.stderr.on("data", (chunk) => stderrChunks.push(chunk));
15309
+ let stdoutSize = 0;
15310
+ let stderrSize = 0;
15311
+ child.stdout.on("data", (chunk) => {
15312
+ if (stdoutSize < MAX_OUTPUT_SIZE) stdoutChunks.push(chunk);
15313
+ stdoutSize += chunk.length;
15314
+ });
15315
+ child.stderr.on("data", (chunk) => {
15316
+ if (stderrSize < MAX_OUTPUT_SIZE) stderrChunks.push(chunk);
15317
+ stderrSize += chunk.length;
15318
+ });
15231
15319
  const onAbort = () => {
15232
15320
  child.kill("SIGTERM");
15233
15321
  setTimeout(() => {
@@ -15270,7 +15358,7 @@ __export(session_registry_exports, {
15270
15358
  import { readFileSync as readFileSync10, writeFileSync as writeFileSync5, mkdirSync as mkdirSync6, existsSync as existsSync14 } from "fs";
15271
15359
  import { execSync as execSync4 } from "child_process";
15272
15360
  import path20 from "path";
15273
- import os6 from "os";
15361
+ import os7 from "os";
15274
15362
  function registerSession(entry) {
15275
15363
  const dir = path20.dirname(REGISTRY_PATH);
15276
15364
  if (!existsSync14(dir)) {
@@ -15316,13 +15404,15 @@ var REGISTRY_PATH;
15316
15404
  var init_session_registry = __esm({
15317
15405
  "src/lib/session-registry.ts"() {
15318
15406
  "use strict";
15319
- REGISTRY_PATH = path20.join(os6.homedir(), ".exe-os", "session-registry.json");
15407
+ REGISTRY_PATH = path20.join(os7.homedir(), ".exe-os", "session-registry.json");
15320
15408
  }
15321
15409
  });
15322
15410
 
15323
15411
  // src/tui/views/CommandCenter.tsx
15324
15412
  import { useState as useState6, useEffect as useEffect8, useMemo as useMemo4, useCallback as useCallback4, useRef as useRef4 } from "react";
15325
15413
  import TextInput from "ink-text-input";
15414
+ import path21 from "path";
15415
+ import { homedir as homedir3 } from "os";
15326
15416
  import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
15327
15417
  function CommandCenterView({
15328
15418
  onSelectProject,
@@ -15358,8 +15448,8 @@ function CommandCenterView({
15358
15448
  const { createDefaultHooks: createDefaultHooks2 } = await Promise.resolve().then(() => (init_hooks(), hooks_exports));
15359
15449
  const { readFileSync: readFileSync18, existsSync: existsSync22 } = await import("fs");
15360
15450
  const { join } = await import("path");
15361
- const { homedir: homedir3 } = await import("os");
15362
- const configPath = join(homedir3(), ".exe-os", "config.json");
15451
+ const { homedir: homedir5 } = await import("os");
15452
+ const configPath = join(homedir5(), ".exe-os", "config.json");
15363
15453
  let failoverChain = ["anthropic", "opencode", "gemini", "openai"];
15364
15454
  let providerConfigs = {};
15365
15455
  if (existsSync22(configPath)) {
@@ -15422,7 +15512,7 @@ function CommandCenterView({
15422
15512
  registry.register(BashTool2);
15423
15513
  let agentRole = "CTO";
15424
15514
  try {
15425
- const markerDir = join(homedir3(), ".exe-os", "session-cache");
15515
+ const markerDir = join(homedir5(), ".exe-os", "session-cache");
15426
15516
  const agentFiles = (await import("fs")).readdirSync(markerDir).filter((f) => f.startsWith("active-agent-"));
15427
15517
  for (const f of agentFiles) {
15428
15518
  const data = JSON.parse(readFileSync18(join(markerDir, f), "utf8"));
@@ -15562,10 +15652,10 @@ function CommandCenterView({
15562
15652
  const demoEntries = DEMO_PROJECTS.map((p) => ({
15563
15653
  projectName: p.projectName,
15564
15654
  exeSession: p.exeSession,
15565
- projectDir: `/Users/demo/${p.projectName}`,
15655
+ projectDir: path21.join(homedir3(), p.projectName),
15566
15656
  employeeCount: p.employees.length,
15567
15657
  activeCount: p.employees.filter((e) => e.status === "active").length,
15568
- memoryCount: p.projectName === "exe-os" ? 18331 : p.projectName === "exe-create" || p.projectName === "exe-build-skills" ? 2100 : 890,
15658
+ memoryCount: p.employees.length * 4e3,
15569
15659
  status: p.employees.some((e) => e.status === "active") ? "active" : "idle",
15570
15660
  type: p.projectName.startsWith("exe-") ? "code" : "automation",
15571
15661
  recentTasks: DEMO_RECENT_TASKS[p.projectName] ?? []
@@ -15972,7 +16062,7 @@ var init_CommandCenter = __esm({
15972
16062
  });
15973
16063
 
15974
16064
  // src/tui/components/TmuxPane.tsx
15975
- import { useState as useState7, useEffect as useEffect9 } from "react";
16065
+ import React18, { useState as useState7, useEffect as useEffect9 } from "react";
15976
16066
  import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
15977
16067
  function TmuxPane({ sessionName, employeeName, employeeRole, projectName, onDetach }) {
15978
16068
  const demo = useDemo();
@@ -16390,10 +16480,10 @@ var init_provider_table = __esm({
16390
16480
 
16391
16481
  // src/lib/intercom-queue.ts
16392
16482
  import { readFileSync as readFileSync11, writeFileSync as writeFileSync6, renameSync as renameSync4, existsSync as existsSync15, mkdirSync as mkdirSync7 } from "fs";
16393
- import path21 from "path";
16394
- import os7 from "os";
16483
+ import path22 from "path";
16484
+ import os8 from "os";
16395
16485
  function ensureDir2() {
16396
- const dir = path21.dirname(QUEUE_PATH);
16486
+ const dir = path22.dirname(QUEUE_PATH);
16397
16487
  if (!existsSync15(dir)) mkdirSync7(dir, { recursive: true });
16398
16488
  }
16399
16489
  function readQueue() {
@@ -16431,15 +16521,15 @@ var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
16431
16521
  var init_intercom_queue = __esm({
16432
16522
  "src/lib/intercom-queue.ts"() {
16433
16523
  "use strict";
16434
- QUEUE_PATH = path21.join(os7.homedir(), ".exe-os", "intercom-queue.json");
16524
+ QUEUE_PATH = path22.join(os8.homedir(), ".exe-os", "intercom-queue.json");
16435
16525
  TTL_MS = 60 * 60 * 1e3;
16436
- INTERCOM_LOG = path21.join(os7.homedir(), ".exe-os", "intercom.log");
16526
+ INTERCOM_LOG = path22.join(os8.homedir(), ".exe-os", "intercom.log");
16437
16527
  }
16438
16528
  });
16439
16529
 
16440
16530
  // src/lib/plan-limits.ts
16441
16531
  import { readFileSync as readFileSync12, existsSync as existsSync16 } from "fs";
16442
- import path22 from "path";
16532
+ import path23 from "path";
16443
16533
  function getLicenseSync() {
16444
16534
  try {
16445
16535
  if (!existsSync16(CACHE_PATH2)) return freeLicense();
@@ -16511,14 +16601,14 @@ var init_plan_limits = __esm({
16511
16601
  this.name = "PlanLimitError";
16512
16602
  }
16513
16603
  };
16514
- CACHE_PATH2 = path22.join(EXE_AI_DIR, "license-cache.json");
16604
+ CACHE_PATH2 = path23.join(EXE_AI_DIR, "license-cache.json");
16515
16605
  }
16516
16606
  });
16517
16607
 
16518
16608
  // src/lib/notifications.ts
16519
16609
  import crypto4 from "crypto";
16520
- import path23 from "path";
16521
- import os8 from "os";
16610
+ import path24 from "path";
16611
+ import os9 from "os";
16522
16612
  import {
16523
16613
  readFileSync as readFileSync13,
16524
16614
  readdirSync as readdirSync3,
@@ -16603,7 +16693,7 @@ var init_session_kill_telemetry = __esm({
16603
16693
 
16604
16694
  // src/lib/tasks-crud.ts
16605
16695
  import crypto6 from "crypto";
16606
- import path24 from "path";
16696
+ import path25 from "path";
16607
16697
  import { execSync as execSync7 } from "child_process";
16608
16698
  import { mkdir as mkdir6, writeFile as writeFile5, appendFile } from "fs/promises";
16609
16699
  import { existsSync as existsSync18, readFileSync as readFileSync14 } from "fs";
@@ -16736,8 +16826,8 @@ async function createTaskCore(input) {
16736
16826
  }
16737
16827
  if (input.baseDir) {
16738
16828
  try {
16739
- await mkdir6(path24.join(input.baseDir, "exe", "output"), { recursive: true });
16740
- await mkdir6(path24.join(input.baseDir, "exe", "research"), { recursive: true });
16829
+ await mkdir6(path25.join(input.baseDir, "exe", "output"), { recursive: true });
16830
+ await mkdir6(path25.join(input.baseDir, "exe", "research"), { recursive: true });
16741
16831
  await ensureArchitectureDoc(input.baseDir, input.projectName);
16742
16832
  await ensureGitignoreExe(input.baseDir);
16743
16833
  } catch {
@@ -16945,7 +17035,7 @@ async function deleteTaskCore(taskId, _baseDir) {
16945
17035
  return { taskFile, assignedTo, assignedBy, taskSlug };
16946
17036
  }
16947
17037
  async function ensureArchitectureDoc(baseDir, projectName) {
16948
- const archPath = path24.join(baseDir, "exe", "ARCHITECTURE.md");
17038
+ const archPath = path25.join(baseDir, "exe", "ARCHITECTURE.md");
16949
17039
  try {
16950
17040
  if (existsSync18(archPath)) return;
16951
17041
  const template = [
@@ -16980,7 +17070,7 @@ async function ensureArchitectureDoc(baseDir, projectName) {
16980
17070
  }
16981
17071
  }
16982
17072
  async function ensureGitignoreExe(baseDir) {
16983
- const gitignorePath = path24.join(baseDir, ".gitignore");
17073
+ const gitignorePath = path25.join(baseDir, ".gitignore");
16984
17074
  try {
16985
17075
  if (existsSync18(gitignorePath)) {
16986
17076
  const content = readFileSync14(gitignorePath, "utf-8");
@@ -17003,7 +17093,7 @@ var init_tasks_crud = __esm({
17003
17093
  });
17004
17094
 
17005
17095
  // src/lib/tasks-review.ts
17006
- import path25 from "path";
17096
+ import path26 from "path";
17007
17097
  import { existsSync as existsSync19, readdirSync as readdirSync4, unlinkSync as unlinkSync6 } from "fs";
17008
17098
  async function countPendingReviews() {
17009
17099
  const client = getClient();
@@ -17124,11 +17214,11 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
17124
17214
  );
17125
17215
  }
17126
17216
  try {
17127
- const cacheDir = path25.join(EXE_AI_DIR, "session-cache");
17217
+ const cacheDir = path26.join(EXE_AI_DIR, "session-cache");
17128
17218
  if (existsSync19(cacheDir)) {
17129
17219
  for (const f of readdirSync4(cacheDir)) {
17130
17220
  if (f.startsWith("review-notified-")) {
17131
- unlinkSync6(path25.join(cacheDir, f));
17221
+ unlinkSync6(path26.join(cacheDir, f));
17132
17222
  }
17133
17223
  }
17134
17224
  }
@@ -17149,7 +17239,7 @@ var init_tasks_review = __esm({
17149
17239
  });
17150
17240
 
17151
17241
  // src/lib/tasks-chain.ts
17152
- import path26 from "path";
17242
+ import path27 from "path";
17153
17243
  import { readFile as readFile5, writeFile as writeFile6 } from "fs/promises";
17154
17244
  async function cascadeUnblock(taskId, baseDir, now) {
17155
17245
  const client = getClient();
@@ -17165,7 +17255,7 @@ async function cascadeUnblock(taskId, baseDir, now) {
17165
17255
  });
17166
17256
  for (const ur of unblockedRows.rows) {
17167
17257
  try {
17168
- const ubFile = path26.join(baseDir, String(ur.task_file));
17258
+ const ubFile = path27.join(baseDir, String(ur.task_file));
17169
17259
  let ubContent = await readFile5(ubFile, "utf-8");
17170
17260
  ubContent = ubContent.replace(/\*\*Status:\*\* blocked/, "**Status:** open");
17171
17261
  ubContent = ubContent.replace(/\n\*\*Blocked by:\*\*.*\n/, "\n");
@@ -17231,7 +17321,7 @@ var init_tasks_chain = __esm({
17231
17321
 
17232
17322
  // src/lib/project-name.ts
17233
17323
  import { execSync as execSync8 } from "child_process";
17234
- import path27 from "path";
17324
+ import path28 from "path";
17235
17325
  function getProjectName(cwd2) {
17236
17326
  const dir = cwd2 ?? process.cwd();
17237
17327
  if (_cached2 && _cachedCwd === dir) return _cached2;
@@ -17244,7 +17334,7 @@ function getProjectName(cwd2) {
17244
17334
  timeout: 2e3,
17245
17335
  stdio: ["pipe", "pipe", "pipe"]
17246
17336
  }).trim();
17247
- repoRoot = path27.dirname(gitCommonDir);
17337
+ repoRoot = path28.dirname(gitCommonDir);
17248
17338
  } catch {
17249
17339
  repoRoot = execSync8("git rev-parse --show-toplevel", {
17250
17340
  cwd: dir,
@@ -17253,11 +17343,11 @@ function getProjectName(cwd2) {
17253
17343
  stdio: ["pipe", "pipe", "pipe"]
17254
17344
  }).trim();
17255
17345
  }
17256
- _cached2 = path27.basename(repoRoot);
17346
+ _cached2 = path28.basename(repoRoot);
17257
17347
  _cachedCwd = dir;
17258
17348
  return _cached2;
17259
17349
  } catch {
17260
- _cached2 = path27.basename(dir);
17350
+ _cached2 = path28.basename(dir);
17261
17351
  _cachedCwd = dir;
17262
17352
  return _cached2;
17263
17353
  }
@@ -17728,7 +17818,7 @@ __export(tasks_exports, {
17728
17818
  updateTaskStatus: () => updateTaskStatus,
17729
17819
  writeCheckpoint: () => writeCheckpoint
17730
17820
  });
17731
- import path28 from "path";
17821
+ import path29 from "path";
17732
17822
  import { writeFileSync as writeFileSync7, mkdirSync as mkdirSync8, unlinkSync as unlinkSync7 } from "fs";
17733
17823
  async function createTask(input) {
17734
17824
  const result = await createTaskCore(input);
@@ -17748,8 +17838,8 @@ async function updateTask(input) {
17748
17838
  const { row, taskFile, now, taskId } = await updateTaskStatus(input);
17749
17839
  try {
17750
17840
  const agent = String(row.assigned_to);
17751
- const cacheDir = path28.join(EXE_AI_DIR, "session-cache");
17752
- const cachePath = path28.join(cacheDir, `current-task-${agent}.json`);
17841
+ const cacheDir = path29.join(EXE_AI_DIR, "session-cache");
17842
+ const cachePath = path29.join(cacheDir, `current-task-${agent}.json`);
17753
17843
  if (input.status === "in_progress") {
17754
17844
  mkdirSync8(cacheDir, { recursive: true });
17755
17845
  writeFileSync7(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
@@ -18171,12 +18261,12 @@ __export(tmux_routing_exports, {
18171
18261
  });
18172
18262
  import { execFileSync as execFileSync3, execSync as execSync9 } from "child_process";
18173
18263
  import { readFileSync as readFileSync15, writeFileSync as writeFileSync8, mkdirSync as mkdirSync9, existsSync as existsSync20, appendFileSync } from "fs";
18174
- import path29 from "path";
18175
- import os9 from "os";
18264
+ import path30 from "path";
18265
+ import os10 from "os";
18176
18266
  import { fileURLToPath as fileURLToPath4 } from "url";
18177
18267
  import { unlinkSync as unlinkSync8 } from "fs";
18178
18268
  function spawnLockPath(sessionName) {
18179
- return path29.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
18269
+ return path30.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
18180
18270
  }
18181
18271
  function isProcessAlive(pid) {
18182
18272
  try {
@@ -18213,8 +18303,8 @@ function releaseSpawnLock2(sessionName) {
18213
18303
  function resolveBehaviorsExporterScript() {
18214
18304
  try {
18215
18305
  const thisFile = fileURLToPath4(import.meta.url);
18216
- const scriptPath = path29.join(
18217
- path29.dirname(thisFile),
18306
+ const scriptPath = path30.join(
18307
+ path30.dirname(thisFile),
18218
18308
  "..",
18219
18309
  "bin",
18220
18310
  "exe-export-behaviors.js"
@@ -18264,7 +18354,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
18264
18354
  mkdirSync9(SESSION_CACHE, { recursive: true });
18265
18355
  }
18266
18356
  const rootExe = extractRootExe(parentExe) ?? parentExe;
18267
- const filePath = path29.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
18357
+ const filePath = path30.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
18268
18358
  writeFileSync8(filePath, JSON.stringify({
18269
18359
  parentExe: rootExe,
18270
18360
  dispatchedBy: dispatchedBy || rootExe,
@@ -18273,7 +18363,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
18273
18363
  }
18274
18364
  function getParentExe(sessionKey) {
18275
18365
  try {
18276
- const data = JSON.parse(readFileSync15(path29.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
18366
+ const data = JSON.parse(readFileSync15(path30.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
18277
18367
  return data.parentExe || null;
18278
18368
  } catch {
18279
18369
  return null;
@@ -18282,7 +18372,7 @@ function getParentExe(sessionKey) {
18282
18372
  function getDispatchedBy(sessionKey) {
18283
18373
  try {
18284
18374
  const data = JSON.parse(readFileSync15(
18285
- path29.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
18375
+ path30.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
18286
18376
  "utf8"
18287
18377
  ));
18288
18378
  return data.dispatchedBy ?? data.parentExe ?? null;
@@ -18525,8 +18615,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
18525
18615
  const transport = getTransport();
18526
18616
  const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
18527
18617
  const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
18528
- const logDir = path29.join(os9.homedir(), ".exe-os", "session-logs");
18529
- const logFile = path29.join(logDir, `${instanceLabel}-${Date.now()}.log`);
18618
+ const logDir = path30.join(os10.homedir(), ".exe-os", "session-logs");
18619
+ const logFile = path30.join(logDir, `${instanceLabel}-${Date.now()}.log`);
18530
18620
  if (!existsSync20(logDir)) {
18531
18621
  mkdirSync9(logDir, { recursive: true });
18532
18622
  }
@@ -18534,14 +18624,14 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
18534
18624
  let cleanupSuffix = "";
18535
18625
  try {
18536
18626
  const thisFile = fileURLToPath4(import.meta.url);
18537
- const cleanupScript = path29.join(path29.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
18627
+ const cleanupScript = path30.join(path30.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
18538
18628
  if (existsSync20(cleanupScript)) {
18539
18629
  cleanupSuffix = `; ${process.execPath} "${cleanupScript}" "${employeeName}" "${exeSession}"`;
18540
18630
  }
18541
18631
  } catch {
18542
18632
  }
18543
18633
  try {
18544
- const claudeJsonPath = path29.join(os9.homedir(), ".claude.json");
18634
+ const claudeJsonPath = path30.join(os10.homedir(), ".claude.json");
18545
18635
  let claudeJson = {};
18546
18636
  try {
18547
18637
  claudeJson = JSON.parse(readFileSync15(claudeJsonPath, "utf8"));
@@ -18556,10 +18646,10 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
18556
18646
  } catch {
18557
18647
  }
18558
18648
  try {
18559
- const settingsDir = path29.join(os9.homedir(), ".claude", "projects");
18649
+ const settingsDir = path30.join(os10.homedir(), ".claude", "projects");
18560
18650
  const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
18561
- const projSettingsDir = path29.join(settingsDir, normalizedKey);
18562
- const settingsPath = path29.join(projSettingsDir, "settings.json");
18651
+ const projSettingsDir = path30.join(settingsDir, normalizedKey);
18652
+ const settingsPath = path30.join(projSettingsDir, "settings.json");
18563
18653
  let settings = {};
18564
18654
  try {
18565
18655
  settings = JSON.parse(readFileSync15(settingsPath, "utf8"));
@@ -18603,8 +18693,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
18603
18693
  let behaviorsFlag = "";
18604
18694
  let legacyFallbackWarned = false;
18605
18695
  if (!useExeAgent && !useBinSymlink) {
18606
- const identityPath2 = path29.join(
18607
- os9.homedir(),
18696
+ const identityPath2 = path30.join(
18697
+ os10.homedir(),
18608
18698
  ".exe-os",
18609
18699
  "identity",
18610
18700
  `${employeeName}.md`
@@ -18619,7 +18709,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
18619
18709
  }
18620
18710
  const behaviorsFile = exportBehaviorsSync(
18621
18711
  employeeName,
18622
- path29.basename(spawnCwd),
18712
+ path30.basename(spawnCwd),
18623
18713
  sessionName
18624
18714
  );
18625
18715
  if (behaviorsFile) {
@@ -18634,9 +18724,9 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
18634
18724
  }
18635
18725
  let sessionContextFlag = "";
18636
18726
  try {
18637
- const ctxDir = path29.join(os9.homedir(), ".exe-os", "session-cache");
18727
+ const ctxDir = path30.join(os10.homedir(), ".exe-os", "session-cache");
18638
18728
  mkdirSync9(ctxDir, { recursive: true });
18639
- const ctxFile = path29.join(ctxDir, `session-context-${sessionName}.md`);
18729
+ const ctxFile = path30.join(ctxDir, `session-context-${sessionName}.md`);
18640
18730
  const ctxContent = [
18641
18731
  `## Session Context`,
18642
18732
  `You are running in tmux session: ${sessionName}.`,
@@ -18681,7 +18771,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
18681
18771
  transport.pipeLog(sessionName, logFile);
18682
18772
  try {
18683
18773
  const mySession = getMySession();
18684
- const dispatchInfo = path29.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
18774
+ const dispatchInfo = path30.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
18685
18775
  writeFileSync8(dispatchInfo, JSON.stringify({
18686
18776
  dispatchedBy: mySession,
18687
18777
  rootExe: exeSession,
@@ -18745,13 +18835,13 @@ var init_tmux_routing = __esm({
18745
18835
  init_provider_table();
18746
18836
  init_intercom_queue();
18747
18837
  init_plan_limits();
18748
- SPAWN_LOCK_DIR = path29.join(os9.homedir(), ".exe-os", "spawn-locks");
18749
- SESSION_CACHE = path29.join(os9.homedir(), ".exe-os", "session-cache");
18838
+ SPAWN_LOCK_DIR = path30.join(os10.homedir(), ".exe-os", "spawn-locks");
18839
+ SESSION_CACHE = path30.join(os10.homedir(), ".exe-os", "session-cache");
18750
18840
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
18751
18841
  VERIFY_PANE_LINES = 200;
18752
18842
  INTERCOM_DEBOUNCE_MS = 3e4;
18753
- INTERCOM_LOG2 = path29.join(os9.homedir(), ".exe-os", "intercom.log");
18754
- DEBOUNCE_FILE = path29.join(SESSION_CACHE, "intercom-debounce.json");
18843
+ INTERCOM_LOG2 = path30.join(os10.homedir(), ".exe-os", "intercom.log");
18844
+ DEBOUNCE_FILE = path30.join(SESSION_CACHE, "intercom-debounce.json");
18755
18845
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
18756
18846
  BUSY_PATTERN = /[✻✽✶✳·].*…|Running…/;
18757
18847
  }
@@ -19138,7 +19228,9 @@ var init_useOrchestrator = __esm({
19138
19228
  });
19139
19229
 
19140
19230
  // src/tui/views/Sessions.tsx
19141
- import { useState as useState9, useEffect as useEffect11, useCallback as useCallback6 } from "react";
19231
+ import React19, { useState as useState9, useEffect as useEffect11, useCallback as useCallback6 } from "react";
19232
+ import path31 from "path";
19233
+ import { homedir as homedir4 } from "os";
19142
19234
  import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
19143
19235
  function SessionsView({
19144
19236
  initialProject,
@@ -19171,7 +19263,7 @@ function SessionsView({
19171
19263
  if (demo) {
19172
19264
  setProjects(DEMO_PROJECTS.map((p) => ({
19173
19265
  ...p,
19174
- projectDir: `/Users/demo/${p.projectName}`,
19266
+ projectDir: path31.join(homedir4(), p.projectName),
19175
19267
  employees: p.employees.map((e) => ({ ...e, attached: e.status === "active" }))
19176
19268
  })));
19177
19269
  return;
@@ -19571,7 +19663,7 @@ var init_Sessions = __esm({
19571
19663
  });
19572
19664
 
19573
19665
  // src/tui/views/Tasks.tsx
19574
- import { useState as useState10, useEffect as useEffect12, useMemo as useMemo5 } from "react";
19666
+ import React20, { useState as useState10, useEffect as useEffect12, useMemo as useMemo5 } from "react";
19575
19667
  import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
19576
19668
  function relativeTime(iso) {
19577
19669
  const now = Date.now();
@@ -20155,7 +20247,7 @@ var init_gateway_client = __esm({
20155
20247
  });
20156
20248
 
20157
20249
  // src/tui/views/Gateway.tsx
20158
- import { useState as useState11, useEffect as useEffect13, useRef as useRef6, useMemo as useMemo6 } from "react";
20250
+ import React21, { useState as useState11, useEffect as useEffect13, useRef as useRef6, useMemo as useMemo6 } from "react";
20159
20251
  import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
20160
20252
  function connectionStatusColor(status) {
20161
20253
  switch (status) {
@@ -20757,7 +20849,7 @@ var init_agent_status = __esm({
20757
20849
  });
20758
20850
 
20759
20851
  // src/tui/views/Team.tsx
20760
- import { useState as useState12, useEffect as useEffect14 } from "react";
20852
+ import React22, { useState as useState12, useEffect as useEffect14 } from "react";
20761
20853
  import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
20762
20854
  function TeamView({ onBack }) {
20763
20855
  const demo = useDemo();
@@ -21034,8 +21126,8 @@ __export(wiki_client_exports, {
21034
21126
  listDocuments: () => listDocuments,
21035
21127
  listWorkspaces: () => listWorkspaces
21036
21128
  });
21037
- async function wikiFetch(config, path32, method = "GET", body) {
21038
- const url = `${config.baseUrl}/api/v1${path32}`;
21129
+ async function wikiFetch(config, path34, method = "GET", body) {
21130
+ const url = `${config.baseUrl}/api/v1${path34}`;
21039
21131
  const headers = {
21040
21132
  Authorization: `Bearer ${config.apiKey}`,
21041
21133
  "Content-Type": "application/json"
@@ -21043,14 +21135,32 @@ async function wikiFetch(config, path32, method = "GET", body) {
21043
21135
  const controller = new AbortController();
21044
21136
  const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS2);
21045
21137
  try {
21046
- const response = await fetch(url, {
21047
- method,
21048
- headers,
21049
- body: body ? JSON.stringify(body) : void 0,
21050
- signal: controller.signal
21051
- });
21138
+ let response;
21139
+ try {
21140
+ response = await fetch(url, {
21141
+ method,
21142
+ headers,
21143
+ body: body ? JSON.stringify(body) : void 0,
21144
+ signal: controller.signal
21145
+ });
21146
+ } catch {
21147
+ clearTimeout(timeout);
21148
+ const retryController = new AbortController();
21149
+ const retryTimeout = setTimeout(() => retryController.abort(), REQUEST_TIMEOUT_MS2);
21150
+ try {
21151
+ await new Promise((r) => setTimeout(r, 500));
21152
+ response = await fetch(url, {
21153
+ method,
21154
+ headers,
21155
+ body: body ? JSON.stringify(body) : void 0,
21156
+ signal: retryController.signal
21157
+ });
21158
+ } finally {
21159
+ clearTimeout(retryTimeout);
21160
+ }
21161
+ }
21052
21162
  if (!response.ok) {
21053
- throw new Error(`Wiki API ${method} ${path32}: ${response.status} ${response.statusText}`);
21163
+ throw new Error(`Wiki API ${method} ${path34}: ${response.status} ${response.statusText}`);
21054
21164
  }
21055
21165
  return response.json();
21056
21166
  } finally {
@@ -21150,7 +21260,7 @@ var init_wiki_client = __esm({
21150
21260
  });
21151
21261
 
21152
21262
  // src/tui/views/Wiki.tsx
21153
- import { useState as useState13, useEffect as useEffect15 } from "react";
21263
+ import React23, { useState as useState13, useEffect as useEffect15 } from "react";
21154
21264
  import TextInput2 from "ink-text-input";
21155
21265
  import { Fragment as Fragment4, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
21156
21266
  function WikiView({ onBack }) {
@@ -21461,7 +21571,7 @@ var init_Wiki = __esm({
21461
21571
  });
21462
21572
 
21463
21573
  // src/tui/views/Settings.tsx
21464
- import { useState as useState14, useEffect as useEffect16 } from "react";
21574
+ import React24, { useState as useState14, useEffect as useEffect16 } from "react";
21465
21575
  import { Fragment as Fragment5, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
21466
21576
  function SettingsView({ onBack }) {
21467
21577
  const [providers, setProviders] = useState14([]);
@@ -21901,9 +22011,9 @@ var init_App2 = __esm({
21901
22011
  // src/lib/update-check.ts
21902
22012
  import { execSync as execSync11 } from "child_process";
21903
22013
  import { readFileSync as readFileSync16 } from "fs";
21904
- import path30 from "path";
22014
+ import path32 from "path";
21905
22015
  function getLocalVersion(packageRoot) {
21906
- const pkgPath = path30.join(packageRoot, "package.json");
22016
+ const pkgPath = path32.join(packageRoot, "package.json");
21907
22017
  const pkg = JSON.parse(readFileSync16(pkgPath, "utf-8"));
21908
22018
  return pkg.version;
21909
22019
  }
@@ -21995,8 +22105,8 @@ var init_update = __esm({
21995
22105
 
21996
22106
  // src/bin/cli.ts
21997
22107
  import { existsSync as existsSync21, readFileSync as readFileSync17, writeFileSync as writeFileSync9, readdirSync as readdirSync5, rmSync } from "fs";
21998
- import path31 from "path";
21999
- import os10 from "os";
22108
+ import path33 from "path";
22109
+ import os11 from "os";
22000
22110
  var args = process.argv.slice(2);
22001
22111
  if (args.includes("--global")) {
22002
22112
  process.stderr.write(
@@ -22069,9 +22179,9 @@ async function runClaudeInstall() {
22069
22179
  }
22070
22180
  }
22071
22181
  async function runClaudeCheck() {
22072
- const claudeDir = path31.join(os10.homedir(), ".claude");
22073
- const settingsPath = path31.join(claudeDir, "settings.json");
22074
- const claudeJsonPath = path31.join(os10.homedir(), ".claude.json");
22182
+ const claudeDir = path33.join(os11.homedir(), ".claude");
22183
+ const settingsPath = path33.join(claudeDir, "settings.json");
22184
+ const claudeJsonPath = path33.join(os11.homedir(), ".claude.json");
22075
22185
  let ok = true;
22076
22186
  if (existsSync21(settingsPath)) {
22077
22187
  let settings;
@@ -22124,7 +22234,7 @@ async function runClaudeCheck() {
22124
22234
  console.log("\x1B[31m\u2717\x1B[0m claude.json not found");
22125
22235
  ok = false;
22126
22236
  }
22127
- const skillsDir = path31.join(claudeDir, "skills");
22237
+ const skillsDir = path33.join(claudeDir, "skills");
22128
22238
  if (existsSync21(skillsDir)) {
22129
22239
  console.log("\x1B[32m\u2713\x1B[0m Slash skills directory exists");
22130
22240
  } else {
@@ -22141,11 +22251,11 @@ async function runClaudeCheck() {
22141
22251
  async function runClaudeUninstall(flags = []) {
22142
22252
  const dryRun = flags.includes("--dry-run");
22143
22253
  const purge = flags.includes("--purge");
22144
- const homeDir = os10.homedir();
22145
- const claudeDir = path31.join(homeDir, ".claude");
22146
- const settingsPath = path31.join(claudeDir, "settings.json");
22147
- const claudeJsonPath = path31.join(homeDir, ".claude.json");
22148
- const exeOsDir = path31.join(homeDir, ".exe-os");
22254
+ const homeDir = os11.homedir();
22255
+ const claudeDir = path33.join(homeDir, ".claude");
22256
+ const settingsPath = path33.join(claudeDir, "settings.json");
22257
+ const claudeJsonPath = path33.join(homeDir, ".claude.json");
22258
+ const exeOsDir = path33.join(homeDir, ".exe-os");
22149
22259
  let removed = 0;
22150
22260
  const log = (msg) => console.log(dryRun ? `[dry-run] ${msg}` : msg);
22151
22261
  let settings = {};
@@ -22197,32 +22307,43 @@ async function runClaudeUninstall(flags = []) {
22197
22307
  }
22198
22308
  }
22199
22309
  if (existsSync21(claudeJsonPath)) {
22200
- const claudeJson = JSON.parse(readFileSync17(claudeJsonPath, "utf8"));
22201
- if (claudeJson.mcpServers) {
22202
- let removedMcp = false;
22203
- for (const key of ["exe-mem", "exe-os"]) {
22204
- if (claudeJson.mcpServers[key]) {
22205
- if (!dryRun) delete claudeJson.mcpServers[key];
22206
- removedMcp = true;
22310
+ const raw = readFileSync17(claudeJsonPath, "utf8");
22311
+ if (raw.length > 1e6) {
22312
+ console.error("claude.json exceeds 1 MB \u2014 skipping parse.");
22313
+ } else {
22314
+ let claudeJson;
22315
+ try {
22316
+ claudeJson = JSON.parse(raw);
22317
+ } catch {
22318
+ console.error("claude.json is malformed JSON \u2014 skipping.");
22319
+ claudeJson = {};
22320
+ }
22321
+ if (claudeJson.mcpServers) {
22322
+ let removedMcp = false;
22323
+ for (const key of ["exe-mem", "exe-os"]) {
22324
+ if (claudeJson.mcpServers[key]) {
22325
+ if (!dryRun) delete claudeJson.mcpServers[key];
22326
+ removedMcp = true;
22327
+ }
22207
22328
  }
22208
- }
22209
- if (removedMcp) {
22210
- if (!dryRun) {
22211
- writeFileSync9(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
22329
+ if (removedMcp) {
22330
+ if (!dryRun) {
22331
+ writeFileSync9(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
22332
+ }
22333
+ log("\u2713 Removed exe-os MCP server from claude.json");
22334
+ removed++;
22212
22335
  }
22213
- log("\u2713 Removed exe-os MCP server from claude.json");
22214
- removed++;
22215
22336
  }
22216
22337
  }
22217
22338
  }
22218
- const skillsDir = path31.join(claudeDir, "skills");
22339
+ const skillsDir = path33.join(claudeDir, "skills");
22219
22340
  if (existsSync21(skillsDir)) {
22220
22341
  let skillCount = 0;
22221
22342
  try {
22222
22343
  const entries = readdirSync5(skillsDir);
22223
22344
  for (const entry of entries) {
22224
22345
  if (entry.startsWith("exe")) {
22225
- const fullPath = path31.join(skillsDir, entry);
22346
+ const fullPath = path33.join(skillsDir, entry);
22226
22347
  if (!dryRun) rmSync(fullPath, { recursive: true, force: true });
22227
22348
  skillCount++;
22228
22349
  }
@@ -22234,7 +22355,7 @@ async function runClaudeUninstall(flags = []) {
22234
22355
  removed++;
22235
22356
  }
22236
22357
  }
22237
- const claudeMdPath = path31.join(claudeDir, "CLAUDE.md");
22358
+ const claudeMdPath = path33.join(claudeDir, "CLAUDE.md");
22238
22359
  if (existsSync21(claudeMdPath)) {
22239
22360
  const content = readFileSync17(claudeMdPath, "utf8");
22240
22361
  const startMarker = "<!-- exe-os:orchestration-start -->";
@@ -22248,13 +22369,13 @@ async function runClaudeUninstall(flags = []) {
22248
22369
  removed++;
22249
22370
  }
22250
22371
  }
22251
- const agentsDir = path31.join(claudeDir, "agents");
22372
+ const agentsDir = path33.join(claudeDir, "agents");
22252
22373
  if (existsSync21(agentsDir)) {
22253
22374
  let agentCount = 0;
22254
22375
  try {
22255
22376
  const entries = readdirSync5(agentsDir).filter((f) => f.endsWith(".md"));
22256
22377
  let knownNames = /* @__PURE__ */ new Set();
22257
- const rosterPath = path31.join(exeOsDir, "exe-employees.json");
22378
+ const rosterPath = path33.join(exeOsDir, "exe-employees.json");
22258
22379
  if (existsSync21(rosterPath)) {
22259
22380
  try {
22260
22381
  const roster = JSON.parse(readFileSync17(rosterPath, "utf8"));
@@ -22265,7 +22386,7 @@ async function runClaudeUninstall(flags = []) {
22265
22386
  for (const entry of entries) {
22266
22387
  const name = entry.replace(/\.md$/, "");
22267
22388
  if (knownNames.has(name)) {
22268
- if (!dryRun) rmSync(path31.join(agentsDir, entry), { force: true });
22389
+ if (!dryRun) rmSync(path33.join(agentsDir, entry), { force: true });
22269
22390
  agentCount++;
22270
22391
  }
22271
22392
  }
@@ -22276,13 +22397,13 @@ async function runClaudeUninstall(flags = []) {
22276
22397
  removed++;
22277
22398
  }
22278
22399
  }
22279
- const projectsDir = path31.join(claudeDir, "projects");
22400
+ const projectsDir = path33.join(claudeDir, "projects");
22280
22401
  if (existsSync21(projectsDir)) {
22281
22402
  let projectCount = 0;
22282
22403
  try {
22283
22404
  const projects = readdirSync5(projectsDir);
22284
22405
  for (const proj of projects) {
22285
- const projSettings = path31.join(projectsDir, proj, "settings.json");
22406
+ const projSettings = path33.join(projectsDir, proj, "settings.json");
22286
22407
  if (!existsSync21(projSettings)) continue;
22287
22408
  try {
22288
22409
  const pSettings = JSON.parse(readFileSync17(projSettings, "utf8"));
@@ -22310,16 +22431,24 @@ async function runClaudeUninstall(flags = []) {
22310
22431
  }
22311
22432
  try {
22312
22433
  const { execSync: execSync13 } = await import("child_process");
22313
- const exeBinPath = execSync13("which exe", { encoding: "utf-8" }).trim();
22314
- const binDir = path31.dirname(exeBinPath);
22434
+ const findExeBin3 = () => {
22435
+ try {
22436
+ return execSync13(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
22437
+ } catch {
22438
+ return null;
22439
+ }
22440
+ };
22441
+ const exeBinPath = findExeBin3();
22442
+ if (!exeBinPath) throw new Error("exe-os not found in PATH");
22443
+ const binDir = path33.dirname(exeBinPath);
22315
22444
  let symlinkCount = 0;
22316
- const rosterPath = path31.join(exeOsDir, "exe-employees.json");
22445
+ const rosterPath = path33.join(exeOsDir, "exe-employees.json");
22317
22446
  if (existsSync21(rosterPath)) {
22318
22447
  const roster = JSON.parse(readFileSync17(rosterPath, "utf8"));
22319
22448
  for (const emp of roster) {
22320
22449
  if (emp.name === "exe") continue;
22321
22450
  for (const suffix of ["", "-opencode"]) {
22322
- const linkPath = path31.join(binDir, `${emp.name}${suffix}`);
22451
+ const linkPath = path33.join(binDir, `${emp.name}${suffix}`);
22323
22452
  if (existsSync21(linkPath)) {
22324
22453
  if (!dryRun) rmSync(linkPath, { force: true });
22325
22454
  symlinkCount++;
@@ -22358,7 +22487,7 @@ async function checkForUpdateOnBoot() {
22358
22487
  const config = await loadConfig2();
22359
22488
  if (!config.autoUpdate.checkOnBoot) return;
22360
22489
  const { checkForUpdate: checkForUpdate2 } = await init_update().then(() => update_exports);
22361
- const packageRoot = path31.resolve(
22490
+ const packageRoot = path33.resolve(
22362
22491
  new URL("../..", import.meta.url).pathname
22363
22492
  );
22364
22493
  const result = checkForUpdate2(packageRoot);
@@ -22417,7 +22546,7 @@ async function runActivate(key) {
22417
22546
  const idTemplate = getIdentityTemplate(identityKey);
22418
22547
  if (idTemplate) {
22419
22548
  const idPath = identityPath2(name);
22420
- const dir = path31.dirname(idPath);
22549
+ const dir = path33.dirname(idPath);
22421
22550
  if (!fs8.existsSync(dir)) fs8.mkdirSync(dir, { recursive: true });
22422
22551
  fs8.writeFileSync(idPath, idTemplate.replace(/^agent_id: \w+/m, `agent_id: ${name}`), "utf-8");
22423
22552
  }