@askexenow/exe-os 0.8.37 → 0.8.39

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 (93) hide show
  1. package/README.md +17 -8
  2. package/dist/bin/backfill-conversations.js +112 -70
  3. package/dist/bin/backfill-responses.js +53 -18
  4. package/dist/bin/backfill-vectors.js +43 -16
  5. package/dist/bin/cleanup-stale-review-tasks.js +38 -16
  6. package/dist/bin/cli.js +790 -468
  7. package/dist/bin/exe-agent.js +19 -4
  8. package/dist/bin/exe-assign.js +46 -13
  9. package/dist/bin/exe-boot.js +288 -129
  10. package/dist/bin/exe-call.js +20 -10
  11. package/dist/bin/exe-cloud.js +135 -30
  12. package/dist/bin/exe-dispatch.js +1 -1
  13. package/dist/bin/exe-doctor.js +38 -16
  14. package/dist/bin/exe-export-behaviors.js +43 -21
  15. package/dist/bin/exe-forget.js +39 -17
  16. package/dist/bin/exe-gateway.js +159 -50
  17. package/dist/bin/exe-heartbeat.js +53 -31
  18. package/dist/bin/exe-kill.js +40 -18
  19. package/dist/bin/exe-launch-agent.js +109 -36
  20. package/dist/bin/exe-link.js +196 -87
  21. package/dist/bin/exe-new-employee.js +56 -17
  22. package/dist/bin/exe-pending-messages.js +47 -25
  23. package/dist/bin/exe-pending-notifications.js +38 -16
  24. package/dist/bin/exe-pending-reviews.js +51 -29
  25. package/dist/bin/exe-rename.js +21 -7
  26. package/dist/bin/exe-review.js +41 -13
  27. package/dist/bin/exe-search.js +57 -21
  28. package/dist/bin/exe-session-cleanup.js +67 -31
  29. package/dist/bin/exe-settings.js +63 -2
  30. package/dist/bin/exe-status.js +35 -13
  31. package/dist/bin/exe-team.js +35 -13
  32. package/dist/bin/git-sweep.js +45 -17
  33. package/dist/bin/graph-backfill.js +38 -16
  34. package/dist/bin/graph-export.js +38 -16
  35. package/dist/bin/install.js +10 -1
  36. package/dist/bin/scan-tasks.js +47 -19
  37. package/dist/bin/setup.js +444 -259
  38. package/dist/bin/shard-migrate.js +38 -16
  39. package/dist/bin/wiki-sync.js +40 -17
  40. package/dist/gateway/index.js +113 -48
  41. package/dist/hooks/bug-report-worker.js +66 -39
  42. package/dist/hooks/commit-complete.js +45 -17
  43. package/dist/hooks/error-recall.js +60 -20
  44. package/dist/hooks/exe-heartbeat-hook.js +3 -2
  45. package/dist/hooks/ingest-worker.js +174 -45
  46. package/dist/hooks/ingest.js +74 -28
  47. package/dist/hooks/instructions-loaded.js +46 -17
  48. package/dist/hooks/notification.js +44 -15
  49. package/dist/hooks/post-compact.js +44 -15
  50. package/dist/hooks/pre-compact.js +42 -14
  51. package/dist/hooks/pre-tool-use.js +59 -22
  52. package/dist/hooks/prompt-ingest-worker.js +75 -14
  53. package/dist/hooks/prompt-submit.js +75 -32
  54. package/dist/hooks/response-ingest-worker.js +76 -15
  55. package/dist/hooks/session-end.js +54 -22
  56. package/dist/hooks/session-start.js +57 -20
  57. package/dist/hooks/stop.js +44 -15
  58. package/dist/hooks/subagent-stop.js +44 -15
  59. package/dist/hooks/summary-worker.js +339 -106
  60. package/dist/index.js +94 -23
  61. package/dist/lib/cloud-sync.js +191 -80
  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/employee-templates.js +5 -0
  68. package/dist/lib/employees.js +11 -6
  69. package/dist/lib/exe-daemon-client.js +6 -1
  70. package/dist/lib/exe-daemon.js +95 -36
  71. package/dist/lib/hybrid-search.js +57 -21
  72. package/dist/lib/identity-templates.js +16 -7
  73. package/dist/lib/identity.js +1 -1
  74. package/dist/lib/keychain.js +2 -1
  75. package/dist/lib/license.js +56 -6
  76. package/dist/lib/messaging.js +1 -1
  77. package/dist/lib/reminders.js +2 -2
  78. package/dist/lib/schedules.js +38 -16
  79. package/dist/lib/skill-learning.js +1 -1
  80. package/dist/lib/store.js +44 -16
  81. package/dist/lib/tasks.js +1 -1
  82. package/dist/lib/tmux-routing.js +1 -1
  83. package/dist/mcp/server.js +280 -155
  84. package/dist/mcp/tools/complete-reminder.js +1 -1
  85. package/dist/mcp/tools/create-task.js +14 -6
  86. package/dist/mcp/tools/deactivate-behavior.js +2 -2
  87. package/dist/mcp/tools/list-reminders.js +1 -1
  88. package/dist/mcp/tools/list-tasks.js +36 -28
  89. package/dist/mcp/tools/send-message.js +1 -1
  90. package/dist/mcp/tools/update-task.js +1 -1
  91. package/dist/runtime/index.js +42 -8
  92. package/dist/tui/App.js +220 -99
  93. package/package.json +5 -3
package/dist/tui/App.js CHANGED
@@ -141,6 +141,7 @@ async function ensureSchema() {
141
141
  const client = getRawClient();
142
142
  await client.execute("PRAGMA journal_mode = WAL");
143
143
  await client.execute("PRAGMA busy_timeout = 30000");
144
+ await client.execute("PRAGMA wal_autocheckpoint = 1000");
144
145
  try {
145
146
  await client.execute("PRAGMA libsql_vector_search_ef = 128");
146
147
  } catch {
@@ -964,7 +965,7 @@ __export(config_exports, {
964
965
  migrateConfig: () => migrateConfig,
965
966
  saveConfig: () => saveConfig
966
967
  });
967
- import { readFile, writeFile, mkdir } from "fs/promises";
968
+ import { readFile, writeFile, mkdir, chmod } from "fs/promises";
968
969
  import { readFileSync as readFileSync2, existsSync as existsSync2, renameSync } from "fs";
969
970
  import path from "path";
970
971
  import os from "os";
@@ -1090,6 +1091,9 @@ async function saveConfig(config) {
1090
1091
  await mkdir(dir, { recursive: true });
1091
1092
  const configPath = path.join(dir, "config.json");
1092
1093
  await writeFile(configPath, JSON.stringify(config, null, 2) + "\n");
1094
+ if (config.cloud?.apiKey) {
1095
+ await chmod(configPath, 384);
1096
+ }
1093
1097
  }
1094
1098
  async function loadConfigFrom(configPath) {
1095
1099
  const raw = await readFile(configPath, "utf-8");
@@ -1204,12 +1208,22 @@ __export(license_exports, {
1204
1208
  loadLicense: () => loadLicense,
1205
1209
  mirrorLicenseKey: () => mirrorLicenseKey,
1206
1210
  saveLicense: () => saveLicense,
1211
+ startLicenseRevalidation: () => startLicenseRevalidation,
1212
+ stopLicenseRevalidation: () => stopLicenseRevalidation,
1207
1213
  validateLicense: () => validateLicense
1208
1214
  });
1209
1215
  import { readFileSync as readFileSync3, writeFileSync, existsSync as existsSync3, mkdirSync } from "fs";
1210
1216
  import { randomUUID } from "crypto";
1211
1217
  import path2 from "path";
1212
1218
  import { jwtVerify, importSPKI } from "jose";
1219
+ async function fetchRetry(url, init) {
1220
+ try {
1221
+ return await fetch(url, init);
1222
+ } catch {
1223
+ await new Promise((r) => setTimeout(r, RETRY_DELAY_MS));
1224
+ return fetch(url, { ...init, signal: AbortSignal.timeout(1e4) });
1225
+ }
1226
+ }
1213
1227
  function loadDeviceId() {
1214
1228
  const deviceJsonPath = path2.join(EXE_AI_DIR, "device.json");
1215
1229
  try {
@@ -1241,7 +1255,7 @@ function loadLicense() {
1241
1255
  }
1242
1256
  function saveLicense(apiKey) {
1243
1257
  mkdirSync(EXE_AI_DIR, { recursive: true });
1244
- writeFileSync(LICENSE_PATH, apiKey.trim(), "utf8");
1258
+ writeFileSync(LICENSE_PATH, apiKey.trim(), { encoding: "utf8", mode: 384 });
1245
1259
  }
1246
1260
  async function verifyLicenseJwt(token) {
1247
1261
  try {
@@ -1293,7 +1307,7 @@ function cacheResponse(token) {
1293
1307
  async function validateLicense(apiKey, deviceId) {
1294
1308
  const did = deviceId ?? loadDeviceId();
1295
1309
  try {
1296
- const res = await fetch(`${API_BASE}/auth/activate`, {
1310
+ const res = await fetchRetry(`${API_BASE}/auth/activate`, {
1297
1311
  method: "POST",
1298
1312
  headers: { "Content-Type": "application/json" },
1299
1313
  body: JSON.stringify({ apiKey, deviceId: did }),
@@ -1328,14 +1342,23 @@ async function validateLicense(apiKey, deviceId) {
1328
1342
  } catch {
1329
1343
  const cached = await getCachedLicense();
1330
1344
  if (cached) return cached;
1331
- return FREE_LICENSE;
1345
+ return { ...FREE_LICENSE, valid: false, error: "offline" };
1346
+ }
1347
+ }
1348
+ function getCacheAgeMs() {
1349
+ try {
1350
+ const { statSync } = __require("fs");
1351
+ const s = statSync(CACHE_PATH);
1352
+ return Date.now() - s.mtimeMs;
1353
+ } catch {
1354
+ return Infinity;
1332
1355
  }
1333
1356
  }
1334
1357
  async function checkLicense() {
1335
1358
  const key = loadLicense();
1336
1359
  if (!key) return FREE_LICENSE;
1337
1360
  const cached = await getCachedLicense();
1338
- if (cached) return cached;
1361
+ if (cached && getCacheAgeMs() < CACHE_MAX_AGE_MS) return cached;
1339
1362
  const deviceId = loadDeviceId();
1340
1363
  return validateLicense(key, deviceId);
1341
1364
  }
@@ -1375,7 +1398,7 @@ async function assertVpsLicense(opts) {
1375
1398
  let explicitRejection = false;
1376
1399
  let transientFailure = false;
1377
1400
  try {
1378
- const res = await fetch(`${API_BASE}/auth/activate`, {
1401
+ const res = await fetchRetry(`${API_BASE}/auth/activate`, {
1379
1402
  method: "POST",
1380
1403
  headers: { "Content-Type": "application/json" },
1381
1404
  body: JSON.stringify({ apiKey, deviceId }),
@@ -1456,7 +1479,28 @@ async function assertVpsLicense(opts) {
1456
1479
  `License validation unreachable for more than ${graceDays} days. Restore network connectivity to https://askexe.com/cloud and retry. This VPS image refuses to boot after the offline grace window.`
1457
1480
  );
1458
1481
  }
1459
- var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH, API_BASE, LICENSE_PUBLIC_KEY_PEM, LICENSE_JWT_ALG, PLAN_LIMITS, FREE_LICENSE;
1482
+ function startLicenseRevalidation(intervalMs = 36e5) {
1483
+ if (_revalTimer) return;
1484
+ _revalTimer = setInterval(async () => {
1485
+ try {
1486
+ const license = await checkLicense();
1487
+ if (!license.valid) {
1488
+ process.stderr.write("[exe-os] License expired or invalid \u2014 features may be restricted\n");
1489
+ }
1490
+ } catch {
1491
+ }
1492
+ }, intervalMs);
1493
+ if (_revalTimer && typeof _revalTimer === "object" && "unref" in _revalTimer) {
1494
+ _revalTimer.unref();
1495
+ }
1496
+ }
1497
+ function stopLicenseRevalidation() {
1498
+ if (_revalTimer) {
1499
+ clearInterval(_revalTimer);
1500
+ _revalTimer = null;
1501
+ }
1502
+ }
1503
+ 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;
1460
1504
  var init_license = __esm({
1461
1505
  "src/lib/license.ts"() {
1462
1506
  "use strict";
@@ -1465,6 +1509,7 @@ var init_license = __esm({
1465
1509
  CACHE_PATH = path2.join(EXE_AI_DIR, "license-cache.json");
1466
1510
  DEVICE_ID_PATH = path2.join(EXE_AI_DIR, "device-id");
1467
1511
  API_BASE = "https://askexe.com/cloud";
1512
+ RETRY_DELAY_MS = 500;
1468
1513
  LICENSE_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----
1469
1514
  MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
1470
1515
  4uj+UqeKCcvtgNHKmOK278HJaJcANe9xAeji8AFYu27q3WtzCi04pHudow==
@@ -1486,6 +1531,8 @@ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
1486
1531
  employeeLimit: 1,
1487
1532
  memoryLimit: 5e3
1488
1533
  };
1534
+ CACHE_MAX_AGE_MS = 36e5;
1535
+ _revalTimer = null;
1489
1536
  }
1490
1537
  });
1491
1538
 
@@ -3335,8 +3382,13 @@ function runRipgrep(input, searchPath, context) {
3335
3382
  timeout: 3e4,
3336
3383
  stdio: ["ignore", "pipe", "pipe"]
3337
3384
  });
3385
+ const MAX_OUTPUT = 1e7;
3338
3386
  const chunks = [];
3339
- child.stdout.on("data", (chunk) => chunks.push(chunk));
3387
+ let totalSize = 0;
3388
+ child.stdout.on("data", (chunk) => {
3389
+ totalSize += chunk.length;
3390
+ if (totalSize <= MAX_OUTPUT) chunks.push(chunk);
3391
+ });
3340
3392
  const onAbort = () => child.kill("SIGTERM");
3341
3393
  context.abortSignal.addEventListener("abort", onAbort, { once: true });
3342
3394
  child.on("close", (code) => {
@@ -3720,10 +3772,19 @@ var init_bash = __esm({
3720
3772
  stdio: ["ignore", "pipe", "pipe"],
3721
3773
  env: { ...process.env }
3722
3774
  });
3775
+ const MAX_OUTPUT_SIZE = 5242880;
3723
3776
  const stdoutChunks = [];
3724
3777
  const stderrChunks = [];
3725
- child.stdout.on("data", (chunk) => stdoutChunks.push(chunk));
3726
- child.stderr.on("data", (chunk) => stderrChunks.push(chunk));
3778
+ let stdoutSize = 0;
3779
+ let stderrSize = 0;
3780
+ child.stdout.on("data", (chunk) => {
3781
+ if (stdoutSize < MAX_OUTPUT_SIZE) stdoutChunks.push(chunk);
3782
+ stdoutSize += chunk.length;
3783
+ });
3784
+ child.stderr.on("data", (chunk) => {
3785
+ if (stderrSize < MAX_OUTPUT_SIZE) stderrChunks.push(chunk);
3786
+ stderrSize += chunk.length;
3787
+ });
3727
3788
  const onAbort = () => {
3728
3789
  child.kill("SIGTERM");
3729
3790
  setTimeout(() => {
@@ -3903,15 +3964,20 @@ function addEmployee(employees, employee) {
3903
3964
  }
3904
3965
  return [...employees, normalized];
3905
3966
  }
3967
+ function findExeBin() {
3968
+ try {
3969
+ return execSync3(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
3970
+ } catch {
3971
+ return null;
3972
+ }
3973
+ }
3906
3974
  function registerBinSymlinks(name) {
3907
3975
  const created = [];
3908
3976
  const skipped = [];
3909
3977
  const errors = [];
3910
- let exeBinPath;
3911
- try {
3912
- exeBinPath = execSync3("which exe", { encoding: "utf-8" }).trim();
3913
- } catch {
3914
- errors.push("Could not find 'exe' in PATH");
3978
+ const exeBinPath = findExeBin();
3979
+ if (!exeBinPath) {
3980
+ errors.push("Could not find 'exe-os' in PATH");
3915
3981
  return { created, skipped, errors };
3916
3982
  }
3917
3983
  const binDir = path10.dirname(exeBinPath);
@@ -4270,10 +4336,10 @@ var init_provider_table = __esm({
4270
4336
 
4271
4337
  // src/lib/intercom-queue.ts
4272
4338
  import { readFileSync as readFileSync6, writeFileSync as writeFileSync3, renameSync as renameSync2, existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
4273
- import path11 from "path";
4339
+ import path12 from "path";
4274
4340
  import os4 from "os";
4275
4341
  function ensureDir() {
4276
- const dir = path11.dirname(QUEUE_PATH);
4342
+ const dir = path12.dirname(QUEUE_PATH);
4277
4343
  if (!existsSync6(dir)) mkdirSync3(dir, { recursive: true });
4278
4344
  }
4279
4345
  function readQueue() {
@@ -4311,15 +4377,15 @@ var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
4311
4377
  var init_intercom_queue = __esm({
4312
4378
  "src/lib/intercom-queue.ts"() {
4313
4379
  "use strict";
4314
- QUEUE_PATH = path11.join(os4.homedir(), ".exe-os", "intercom-queue.json");
4380
+ QUEUE_PATH = path12.join(os4.homedir(), ".exe-os", "intercom-queue.json");
4315
4381
  TTL_MS = 60 * 60 * 1e3;
4316
- INTERCOM_LOG = path11.join(os4.homedir(), ".exe-os", "intercom.log");
4382
+ INTERCOM_LOG = path12.join(os4.homedir(), ".exe-os", "intercom.log");
4317
4383
  }
4318
4384
  });
4319
4385
 
4320
4386
  // src/lib/plan-limits.ts
4321
4387
  import { readFileSync as readFileSync7, existsSync as existsSync7 } from "fs";
4322
- import path12 from "path";
4388
+ import path13 from "path";
4323
4389
  function getLicenseSync() {
4324
4390
  try {
4325
4391
  if (!existsSync7(CACHE_PATH2)) return freeLicense();
@@ -4391,13 +4457,13 @@ var init_plan_limits = __esm({
4391
4457
  this.name = "PlanLimitError";
4392
4458
  }
4393
4459
  };
4394
- CACHE_PATH2 = path12.join(EXE_AI_DIR, "license-cache.json");
4460
+ CACHE_PATH2 = path13.join(EXE_AI_DIR, "license-cache.json");
4395
4461
  }
4396
4462
  });
4397
4463
 
4398
4464
  // src/lib/notifications.ts
4399
4465
  import crypto from "crypto";
4400
- import path13 from "path";
4466
+ import path14 from "path";
4401
4467
  import os5 from "os";
4402
4468
  import {
4403
4469
  readFileSync as readFileSync8,
@@ -4483,7 +4549,7 @@ var init_session_kill_telemetry = __esm({
4483
4549
 
4484
4550
  // src/lib/tasks-crud.ts
4485
4551
  import crypto3 from "crypto";
4486
- import path14 from "path";
4552
+ import path15 from "path";
4487
4553
  import { execSync as execSync6 } from "child_process";
4488
4554
  import { mkdir as mkdir3, writeFile as writeFile3, appendFile } from "fs/promises";
4489
4555
  import { existsSync as existsSync9, readFileSync as readFileSync9 } from "fs";
@@ -4616,8 +4682,8 @@ async function createTaskCore(input) {
4616
4682
  }
4617
4683
  if (input.baseDir) {
4618
4684
  try {
4619
- await mkdir3(path14.join(input.baseDir, "exe", "output"), { recursive: true });
4620
- await mkdir3(path14.join(input.baseDir, "exe", "research"), { recursive: true });
4685
+ await mkdir3(path15.join(input.baseDir, "exe", "output"), { recursive: true });
4686
+ await mkdir3(path15.join(input.baseDir, "exe", "research"), { recursive: true });
4621
4687
  await ensureArchitectureDoc(input.baseDir, input.projectName);
4622
4688
  await ensureGitignoreExe(input.baseDir);
4623
4689
  } catch {
@@ -4825,7 +4891,7 @@ async function deleteTaskCore(taskId, _baseDir) {
4825
4891
  return { taskFile, assignedTo, assignedBy, taskSlug };
4826
4892
  }
4827
4893
  async function ensureArchitectureDoc(baseDir, projectName) {
4828
- const archPath = path14.join(baseDir, "exe", "ARCHITECTURE.md");
4894
+ const archPath = path15.join(baseDir, "exe", "ARCHITECTURE.md");
4829
4895
  try {
4830
4896
  if (existsSync9(archPath)) return;
4831
4897
  const template = [
@@ -4860,7 +4926,7 @@ async function ensureArchitectureDoc(baseDir, projectName) {
4860
4926
  }
4861
4927
  }
4862
4928
  async function ensureGitignoreExe(baseDir) {
4863
- const gitignorePath = path14.join(baseDir, ".gitignore");
4929
+ const gitignorePath = path15.join(baseDir, ".gitignore");
4864
4930
  try {
4865
4931
  if (existsSync9(gitignorePath)) {
4866
4932
  const content = readFileSync9(gitignorePath, "utf-8");
@@ -4883,7 +4949,7 @@ var init_tasks_crud = __esm({
4883
4949
  });
4884
4950
 
4885
4951
  // src/lib/tasks-review.ts
4886
- import path15 from "path";
4952
+ import path16 from "path";
4887
4953
  import { existsSync as existsSync10, readdirSync as readdirSync2, unlinkSync as unlinkSync2 } from "fs";
4888
4954
  async function countPendingReviews() {
4889
4955
  const client = getClient();
@@ -5004,11 +5070,11 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
5004
5070
  );
5005
5071
  }
5006
5072
  try {
5007
- const cacheDir = path15.join(EXE_AI_DIR, "session-cache");
5073
+ const cacheDir = path16.join(EXE_AI_DIR, "session-cache");
5008
5074
  if (existsSync10(cacheDir)) {
5009
5075
  for (const f of readdirSync2(cacheDir)) {
5010
5076
  if (f.startsWith("review-notified-")) {
5011
- unlinkSync2(path15.join(cacheDir, f));
5077
+ unlinkSync2(path16.join(cacheDir, f));
5012
5078
  }
5013
5079
  }
5014
5080
  }
@@ -5029,7 +5095,7 @@ var init_tasks_review = __esm({
5029
5095
  });
5030
5096
 
5031
5097
  // src/lib/tasks-chain.ts
5032
- import path16 from "path";
5098
+ import path17 from "path";
5033
5099
  import { readFile as readFile3, writeFile as writeFile4 } from "fs/promises";
5034
5100
  async function cascadeUnblock(taskId, baseDir, now) {
5035
5101
  const client = getClient();
@@ -5045,7 +5111,7 @@ async function cascadeUnblock(taskId, baseDir, now) {
5045
5111
  });
5046
5112
  for (const ur of unblockedRows.rows) {
5047
5113
  try {
5048
- const ubFile = path16.join(baseDir, String(ur.task_file));
5114
+ const ubFile = path17.join(baseDir, String(ur.task_file));
5049
5115
  let ubContent = await readFile3(ubFile, "utf-8");
5050
5116
  ubContent = ubContent.replace(/\*\*Status:\*\* blocked/, "**Status:** open");
5051
5117
  ubContent = ubContent.replace(/\n\*\*Blocked by:\*\*.*\n/, "\n");
@@ -5111,7 +5177,7 @@ var init_tasks_chain = __esm({
5111
5177
 
5112
5178
  // src/lib/project-name.ts
5113
5179
  import { execSync as execSync7 } from "child_process";
5114
- import path17 from "path";
5180
+ import path18 from "path";
5115
5181
  function getProjectName(cwd2) {
5116
5182
  const dir = cwd2 ?? process.cwd();
5117
5183
  if (_cached2 && _cachedCwd === dir) return _cached2;
@@ -5124,7 +5190,7 @@ function getProjectName(cwd2) {
5124
5190
  timeout: 2e3,
5125
5191
  stdio: ["pipe", "pipe", "pipe"]
5126
5192
  }).trim();
5127
- repoRoot = path17.dirname(gitCommonDir);
5193
+ repoRoot = path18.dirname(gitCommonDir);
5128
5194
  } catch {
5129
5195
  repoRoot = execSync7("git rev-parse --show-toplevel", {
5130
5196
  cwd: dir,
@@ -5133,11 +5199,11 @@ function getProjectName(cwd2) {
5133
5199
  stdio: ["pipe", "pipe", "pipe"]
5134
5200
  }).trim();
5135
5201
  }
5136
- _cached2 = path17.basename(repoRoot);
5202
+ _cached2 = path18.basename(repoRoot);
5137
5203
  _cachedCwd = dir;
5138
5204
  return _cached2;
5139
5205
  } catch {
5140
- _cached2 = path17.basename(dir);
5206
+ _cached2 = path18.basename(dir);
5141
5207
  _cachedCwd = dir;
5142
5208
  return _cached2;
5143
5209
  }
@@ -5608,7 +5674,7 @@ __export(tasks_exports, {
5608
5674
  updateTaskStatus: () => updateTaskStatus,
5609
5675
  writeCheckpoint: () => writeCheckpoint
5610
5676
  });
5611
- import path18 from "path";
5677
+ import path19 from "path";
5612
5678
  import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, unlinkSync as unlinkSync3 } from "fs";
5613
5679
  async function createTask(input) {
5614
5680
  const result = await createTaskCore(input);
@@ -5628,8 +5694,8 @@ async function updateTask(input) {
5628
5694
  const { row, taskFile, now, taskId } = await updateTaskStatus(input);
5629
5695
  try {
5630
5696
  const agent = String(row.assigned_to);
5631
- const cacheDir = path18.join(EXE_AI_DIR, "session-cache");
5632
- const cachePath = path18.join(cacheDir, `current-task-${agent}.json`);
5697
+ const cacheDir = path19.join(EXE_AI_DIR, "session-cache");
5698
+ const cachePath = path19.join(cacheDir, `current-task-${agent}.json`);
5633
5699
  if (input.status === "in_progress") {
5634
5700
  mkdirSync4(cacheDir, { recursive: true });
5635
5701
  writeFileSync4(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
@@ -6051,12 +6117,12 @@ __export(tmux_routing_exports, {
6051
6117
  });
6052
6118
  import { execFileSync as execFileSync3, execSync as execSync8 } from "child_process";
6053
6119
  import { readFileSync as readFileSync10, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, existsSync as existsSync11, appendFileSync } from "fs";
6054
- import path19 from "path";
6120
+ import path20 from "path";
6055
6121
  import os6 from "os";
6056
6122
  import { fileURLToPath } from "url";
6057
6123
  import { unlinkSync as unlinkSync4 } from "fs";
6058
6124
  function spawnLockPath(sessionName) {
6059
- return path19.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
6125
+ return path20.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
6060
6126
  }
6061
6127
  function isProcessAlive(pid) {
6062
6128
  try {
@@ -6093,8 +6159,8 @@ function releaseSpawnLock(sessionName) {
6093
6159
  function resolveBehaviorsExporterScript() {
6094
6160
  try {
6095
6161
  const thisFile = fileURLToPath(import.meta.url);
6096
- const scriptPath = path19.join(
6097
- path19.dirname(thisFile),
6162
+ const scriptPath = path20.join(
6163
+ path20.dirname(thisFile),
6098
6164
  "..",
6099
6165
  "bin",
6100
6166
  "exe-export-behaviors.js"
@@ -6144,7 +6210,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
6144
6210
  mkdirSync5(SESSION_CACHE, { recursive: true });
6145
6211
  }
6146
6212
  const rootExe = extractRootExe(parentExe) ?? parentExe;
6147
- const filePath = path19.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
6213
+ const filePath = path20.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
6148
6214
  writeFileSync5(filePath, JSON.stringify({
6149
6215
  parentExe: rootExe,
6150
6216
  dispatchedBy: dispatchedBy || rootExe,
@@ -6153,7 +6219,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
6153
6219
  }
6154
6220
  function getParentExe(sessionKey) {
6155
6221
  try {
6156
- const data = JSON.parse(readFileSync10(path19.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
6222
+ const data = JSON.parse(readFileSync10(path20.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
6157
6223
  return data.parentExe || null;
6158
6224
  } catch {
6159
6225
  return null;
@@ -6162,7 +6228,7 @@ function getParentExe(sessionKey) {
6162
6228
  function getDispatchedBy(sessionKey) {
6163
6229
  try {
6164
6230
  const data = JSON.parse(readFileSync10(
6165
- path19.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
6231
+ path20.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
6166
6232
  "utf8"
6167
6233
  ));
6168
6234
  return data.dispatchedBy ?? data.parentExe ?? null;
@@ -6405,8 +6471,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
6405
6471
  const transport = getTransport();
6406
6472
  const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
6407
6473
  const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
6408
- const logDir = path19.join(os6.homedir(), ".exe-os", "session-logs");
6409
- const logFile = path19.join(logDir, `${instanceLabel}-${Date.now()}.log`);
6474
+ const logDir = path20.join(os6.homedir(), ".exe-os", "session-logs");
6475
+ const logFile = path20.join(logDir, `${instanceLabel}-${Date.now()}.log`);
6410
6476
  if (!existsSync11(logDir)) {
6411
6477
  mkdirSync5(logDir, { recursive: true });
6412
6478
  }
@@ -6414,14 +6480,14 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
6414
6480
  let cleanupSuffix = "";
6415
6481
  try {
6416
6482
  const thisFile = fileURLToPath(import.meta.url);
6417
- const cleanupScript = path19.join(path19.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
6483
+ const cleanupScript = path20.join(path20.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
6418
6484
  if (existsSync11(cleanupScript)) {
6419
6485
  cleanupSuffix = `; ${process.execPath} "${cleanupScript}" "${employeeName}" "${exeSession}"`;
6420
6486
  }
6421
6487
  } catch {
6422
6488
  }
6423
6489
  try {
6424
- const claudeJsonPath = path19.join(os6.homedir(), ".claude.json");
6490
+ const claudeJsonPath = path20.join(os6.homedir(), ".claude.json");
6425
6491
  let claudeJson = {};
6426
6492
  try {
6427
6493
  claudeJson = JSON.parse(readFileSync10(claudeJsonPath, "utf8"));
@@ -6436,10 +6502,10 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
6436
6502
  } catch {
6437
6503
  }
6438
6504
  try {
6439
- const settingsDir = path19.join(os6.homedir(), ".claude", "projects");
6505
+ const settingsDir = path20.join(os6.homedir(), ".claude", "projects");
6440
6506
  const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
6441
- const projSettingsDir = path19.join(settingsDir, normalizedKey);
6442
- const settingsPath = path19.join(projSettingsDir, "settings.json");
6507
+ const projSettingsDir = path20.join(settingsDir, normalizedKey);
6508
+ const settingsPath = path20.join(projSettingsDir, "settings.json");
6443
6509
  let settings = {};
6444
6510
  try {
6445
6511
  settings = JSON.parse(readFileSync10(settingsPath, "utf8"));
@@ -6483,7 +6549,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
6483
6549
  let behaviorsFlag = "";
6484
6550
  let legacyFallbackWarned = false;
6485
6551
  if (!useExeAgent && !useBinSymlink) {
6486
- const identityPath = path19.join(
6552
+ const identityPath = path20.join(
6487
6553
  os6.homedir(),
6488
6554
  ".exe-os",
6489
6555
  "identity",
@@ -6499,7 +6565,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
6499
6565
  }
6500
6566
  const behaviorsFile = exportBehaviorsSync(
6501
6567
  employeeName,
6502
- path19.basename(spawnCwd),
6568
+ path20.basename(spawnCwd),
6503
6569
  sessionName
6504
6570
  );
6505
6571
  if (behaviorsFile) {
@@ -6514,9 +6580,9 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
6514
6580
  }
6515
6581
  let sessionContextFlag = "";
6516
6582
  try {
6517
- const ctxDir = path19.join(os6.homedir(), ".exe-os", "session-cache");
6583
+ const ctxDir = path20.join(os6.homedir(), ".exe-os", "session-cache");
6518
6584
  mkdirSync5(ctxDir, { recursive: true });
6519
- const ctxFile = path19.join(ctxDir, `session-context-${sessionName}.md`);
6585
+ const ctxFile = path20.join(ctxDir, `session-context-${sessionName}.md`);
6520
6586
  const ctxContent = [
6521
6587
  `## Session Context`,
6522
6588
  `You are running in tmux session: ${sessionName}.`,
@@ -6561,7 +6627,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
6561
6627
  transport.pipeLog(sessionName, logFile);
6562
6628
  try {
6563
6629
  const mySession = getMySession();
6564
- const dispatchInfo = path19.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
6630
+ const dispatchInfo = path20.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
6565
6631
  writeFileSync5(dispatchInfo, JSON.stringify({
6566
6632
  dispatchedBy: mySession,
6567
6633
  rootExe: exeSession,
@@ -6625,13 +6691,13 @@ var init_tmux_routing = __esm({
6625
6691
  init_provider_table();
6626
6692
  init_intercom_queue();
6627
6693
  init_plan_limits();
6628
- SPAWN_LOCK_DIR = path19.join(os6.homedir(), ".exe-os", "spawn-locks");
6629
- SESSION_CACHE = path19.join(os6.homedir(), ".exe-os", "session-cache");
6694
+ SPAWN_LOCK_DIR = path20.join(os6.homedir(), ".exe-os", "spawn-locks");
6695
+ SESSION_CACHE = path20.join(os6.homedir(), ".exe-os", "session-cache");
6630
6696
  BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
6631
6697
  VERIFY_PANE_LINES = 200;
6632
6698
  INTERCOM_DEBOUNCE_MS = 3e4;
6633
- INTERCOM_LOG2 = path19.join(os6.homedir(), ".exe-os", "intercom.log");
6634
- DEBOUNCE_FILE = path19.join(SESSION_CACHE, "intercom-debounce.json");
6699
+ INTERCOM_LOG2 = path20.join(os6.homedir(), ".exe-os", "intercom.log");
6700
+ DEBOUNCE_FILE = path20.join(SESSION_CACHE, "intercom-debounce.json");
6635
6701
  DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
6636
6702
  BUSY_PATTERN = /[✻✽✶✳·].*…|Running…/;
6637
6703
  }
@@ -6938,15 +7004,16 @@ __export(keychain_exports, {
6938
7004
  importMnemonic: () => importMnemonic,
6939
7005
  setMasterKey: () => setMasterKey
6940
7006
  });
6941
- import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod } from "fs/promises";
7007
+ import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
6942
7008
  import { existsSync as existsSync12 } from "fs";
6943
- import path20 from "path";
7009
+ import path22 from "path";
7010
+ import os7 from "os";
6944
7011
  import crypto6 from "crypto";
6945
7012
  function getKeyDir() {
6946
- return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path20.join(process.env.HOME ?? "/tmp", ".exe-os");
7013
+ return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path22.join(os7.homedir(), ".exe-os");
6947
7014
  }
6948
7015
  function getKeyPath() {
6949
- return path20.join(getKeyDir(), "master.key");
7016
+ return path22.join(getKeyDir(), "master.key");
6950
7017
  }
6951
7018
  async function tryKeytar() {
6952
7019
  try {
@@ -6991,7 +7058,7 @@ async function setMasterKey(key) {
6991
7058
  await mkdir4(dir, { recursive: true });
6992
7059
  const keyPath = getKeyPath();
6993
7060
  await writeFile5(keyPath, b64 + "\n", "utf-8");
6994
- await chmod(keyPath, 384);
7061
+ await chmod2(keyPath, 384);
6995
7062
  }
6996
7063
  async function deleteMasterKey() {
6997
7064
  const keytar = await tryKeytar();
@@ -7333,8 +7400,8 @@ __export(wiki_client_exports, {
7333
7400
  listDocuments: () => listDocuments,
7334
7401
  listWorkspaces: () => listWorkspaces
7335
7402
  });
7336
- async function wikiFetch(config, path22, method = "GET", body) {
7337
- const url = `${config.baseUrl}/api/v1${path22}`;
7403
+ async function wikiFetch(config, path24, method = "GET", body) {
7404
+ const url = `${config.baseUrl}/api/v1${path24}`;
7338
7405
  const headers = {
7339
7406
  Authorization: `Bearer ${config.apiKey}`,
7340
7407
  "Content-Type": "application/json"
@@ -7342,14 +7409,32 @@ async function wikiFetch(config, path22, method = "GET", body) {
7342
7409
  const controller = new AbortController();
7343
7410
  const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
7344
7411
  try {
7345
- const response = await fetch(url, {
7346
- method,
7347
- headers,
7348
- body: body ? JSON.stringify(body) : void 0,
7349
- signal: controller.signal
7350
- });
7412
+ let response;
7413
+ try {
7414
+ response = await fetch(url, {
7415
+ method,
7416
+ headers,
7417
+ body: body ? JSON.stringify(body) : void 0,
7418
+ signal: controller.signal
7419
+ });
7420
+ } catch {
7421
+ clearTimeout(timeout);
7422
+ const retryController = new AbortController();
7423
+ const retryTimeout = setTimeout(() => retryController.abort(), REQUEST_TIMEOUT_MS);
7424
+ try {
7425
+ await new Promise((r) => setTimeout(r, 500));
7426
+ response = await fetch(url, {
7427
+ method,
7428
+ headers,
7429
+ body: body ? JSON.stringify(body) : void 0,
7430
+ signal: retryController.signal
7431
+ });
7432
+ } finally {
7433
+ clearTimeout(retryTimeout);
7434
+ }
7435
+ }
7351
7436
  if (!response.ok) {
7352
- throw new Error(`Wiki API ${method} ${path22}: ${response.status} ${response.statusText}`);
7437
+ throw new Error(`Wiki API ${method} ${path24}: ${response.status} ${response.statusText}`);
7353
7438
  }
7354
7439
  return response.json();
7355
7440
  } finally {
@@ -7470,8 +7555,8 @@ __export(shard_manager_exports, {
7470
7555
  listShards: () => listShards,
7471
7556
  shardExists: () => shardExists
7472
7557
  });
7473
- import path21 from "path";
7474
- import { existsSync as existsSync13, mkdirSync as mkdirSync6 } from "fs";
7558
+ import path23 from "path";
7559
+ import { existsSync as existsSync13, mkdirSync as mkdirSync6, readdirSync as readdirSync3 } from "fs";
7475
7560
  import { createClient as createClient2 } from "@libsql/client";
7476
7561
  function initShardManager(encryptionKey) {
7477
7562
  _encryptionKey = encryptionKey;
@@ -7496,7 +7581,7 @@ function getShardClient(projectName) {
7496
7581
  }
7497
7582
  const cached = _shards.get(safeName);
7498
7583
  if (cached) return cached;
7499
- const dbPath = path21.join(SHARDS_DIR, `${safeName}.db`);
7584
+ const dbPath = path23.join(SHARDS_DIR, `${safeName}.db`);
7500
7585
  const client = createClient2({
7501
7586
  url: `file:${dbPath}`,
7502
7587
  encryptionKey: _encryptionKey
@@ -7506,11 +7591,10 @@ function getShardClient(projectName) {
7506
7591
  }
7507
7592
  function shardExists(projectName) {
7508
7593
  const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
7509
- return existsSync13(path21.join(SHARDS_DIR, `${safeName}.db`));
7594
+ return existsSync13(path23.join(SHARDS_DIR, `${safeName}.db`));
7510
7595
  }
7511
7596
  function listShards() {
7512
7597
  if (!existsSync13(SHARDS_DIR)) return [];
7513
- const { readdirSync: readdirSync3 } = __require("fs");
7514
7598
  return readdirSync3(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
7515
7599
  }
7516
7600
  async function ensureShardSchema(client) {
@@ -7692,7 +7776,7 @@ var init_shard_manager = __esm({
7692
7776
  "src/lib/shard-manager.ts"() {
7693
7777
  "use strict";
7694
7778
  init_config();
7695
- SHARDS_DIR = path21.join(EXE_AI_DIR, "shards");
7779
+ SHARDS_DIR = path23.join(EXE_AI_DIR, "shards");
7696
7780
  _shards = /* @__PURE__ */ new Map();
7697
7781
  _encryptionKey = null;
7698
7782
  _shardingEnabled = false;
@@ -7716,6 +7800,28 @@ __export(store_exports, {
7716
7800
  vectorToBlob: () => vectorToBlob,
7717
7801
  writeMemory: () => writeMemory
7718
7802
  });
7803
+ function isBusyError2(err) {
7804
+ if (err instanceof Error) {
7805
+ const msg = err.message.toLowerCase();
7806
+ return msg.includes("sqlite_busy") || msg.includes("database is locked");
7807
+ }
7808
+ return false;
7809
+ }
7810
+ async function retryOnBusy2(fn, label) {
7811
+ for (let attempt = 0; attempt <= INIT_MAX_RETRIES; attempt++) {
7812
+ try {
7813
+ return await fn();
7814
+ } catch (err) {
7815
+ if (!isBusyError2(err) || attempt === INIT_MAX_RETRIES) throw err;
7816
+ process.stderr.write(
7817
+ `[store] SQLITE_BUSY during ${label}, retry ${attempt + 1}/${INIT_MAX_RETRIES}
7818
+ `
7819
+ );
7820
+ await new Promise((r) => setTimeout(r, INIT_RETRY_DELAY_MS * (attempt + 1)));
7821
+ }
7822
+ }
7823
+ throw new Error("unreachable");
7824
+ }
7719
7825
  async function initStore(options) {
7720
7826
  if (_flushTimer !== null) {
7721
7827
  clearInterval(_flushTimer);
@@ -7744,14 +7850,17 @@ async function initStore(options) {
7744
7850
  dbPath,
7745
7851
  encryptionKey: hexKey
7746
7852
  });
7747
- await ensureSchema();
7853
+ await retryOnBusy2(() => ensureSchema(), "ensureSchema");
7748
7854
  try {
7749
7855
  const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
7750
7856
  initShardManager2(hexKey);
7751
7857
  } catch {
7752
7858
  }
7753
7859
  const client = getClient();
7754
- const vResult = await client.execute("SELECT MAX(version) as max_v FROM memories");
7860
+ const vResult = await retryOnBusy2(
7861
+ () => client.execute("SELECT MAX(version) as max_v FROM memories"),
7862
+ "version-query"
7863
+ );
7755
7864
  _nextVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
7756
7865
  }
7757
7866
  function classifyTier(record) {
@@ -7794,6 +7903,12 @@ async function writeMemory(record) {
7794
7903
  supersedes_id: record.supersedes_id ?? null
7795
7904
  };
7796
7905
  _pendingRecords.push(dbRow);
7906
+ const MAX_PENDING = 1e3;
7907
+ if (_pendingRecords.length > MAX_PENDING) {
7908
+ const dropped = _pendingRecords.length - MAX_PENDING;
7909
+ _pendingRecords = _pendingRecords.slice(-MAX_PENDING);
7910
+ console.warn(`[store] Dropped ${dropped} oldest pending records (overflow)`);
7911
+ }
7797
7912
  if (_flushTimer === null) {
7798
7913
  _flushTimer = setInterval(() => {
7799
7914
  void flushBatch();
@@ -8125,7 +8240,7 @@ async function getMemoryCardinality(agentId) {
8125
8240
  return 0;
8126
8241
  }
8127
8242
  }
8128
- var _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
8243
+ var INIT_MAX_RETRIES, INIT_RETRY_DELAY_MS, _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
8129
8244
  var init_store = __esm({
8130
8245
  "src/lib/store.ts"() {
8131
8246
  "use strict";
@@ -8133,6 +8248,8 @@ var init_store = __esm({
8133
8248
  init_database();
8134
8249
  init_keychain();
8135
8250
  init_config();
8251
+ INIT_MAX_RETRIES = 3;
8252
+ INIT_RETRY_DELAY_MS = 1e3;
8136
8253
  _pendingRecords = [];
8137
8254
  _batchSize = 20;
8138
8255
  _flushIntervalMs = 1e4;
@@ -12137,8 +12254,8 @@ function Text({ color, backgroundColor, dimColor = false, bold = false, italic =
12137
12254
  }
12138
12255
 
12139
12256
  // src/tui/ink/components/ErrorOverview.js
12140
- var cleanupPath = (path22) => {
12141
- return path22?.replace(`file://${cwd()}/`, "");
12257
+ var cleanupPath = (path24) => {
12258
+ return path24?.replace(`file://${cwd()}/`, "");
12142
12259
  };
12143
12260
  var stackUtils = new StackUtils({
12144
12261
  cwd: cwd(),
@@ -14146,6 +14263,8 @@ function Footer() {
14146
14263
  // src/tui/views/CommandCenter.tsx
14147
14264
  import { useState as useState6, useEffect as useEffect8, useMemo as useMemo4, useCallback as useCallback4, useRef as useRef4 } from "react";
14148
14265
  import TextInput from "ink-text-input";
14266
+ import path11 from "path";
14267
+ import { homedir } from "os";
14149
14268
 
14150
14269
  // src/tui/components/StatusDot.tsx
14151
14270
  import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
@@ -14168,7 +14287,7 @@ function StatusDot({ status, showLabel = true }) {
14168
14287
 
14169
14288
  // src/tui/demo-data.ts
14170
14289
  var DEMO_EMPLOYEES = [
14171
- { name: "exe", role: "COO", status: "active", activity: "Reviewing yoshi's task-aware behavior injection PR", memoryCount: 16409, projects: [
14290
+ { name: "exe", role: "COO", status: "active", activity: "Reviewing yoshi's task-aware behavior injection PR", memoryCount: 15e3, projects: [
14172
14291
  { name: "exe-os", status: "active" },
14173
14292
  { name: "exe-create", status: "has_tasks" },
14174
14293
  { name: "openclaw", status: "idle" }
@@ -14177,7 +14296,7 @@ var DEMO_EMPLOYEES = [
14177
14296
  "Dispatched behavior injection task",
14178
14297
  "Approved gateway Phase 4"
14179
14298
  ] },
14180
- { name: "yoshi", role: "CTO", status: "active", activity: "Implementing skill learning trajectory capture", memoryCount: 8164, projects: [
14299
+ { name: "yoshi", role: "CTO", status: "active", activity: "Implementing skill learning trajectory capture", memoryCount: 8e3, projects: [
14181
14300
  { name: "exe-os", status: "active" },
14182
14301
  { name: "exe-create", status: "idle" }
14183
14302
  ], recentTasks: [
@@ -14185,7 +14304,7 @@ var DEMO_EMPLOYEES = [
14185
14304
  "Fixed TUI mouse listener leak",
14186
14305
  "Built task-aware behavior injection"
14187
14306
  ] },
14188
- { name: "mari", role: "CMO", status: "idle", activity: "", memoryCount: 2158, projects: [
14307
+ { name: "mari", role: "CMO", status: "idle", activity: "", memoryCount: 2e3, projects: [
14189
14308
  { name: "exe-build-skills", status: "has_tasks" },
14190
14309
  { name: "exe-os", status: "idle" }
14191
14310
  ], recentTasks: [
@@ -14193,13 +14312,13 @@ var DEMO_EMPLOYEES = [
14193
14312
  "Designed exe-os UI system",
14194
14313
  "Fixed logo layouts"
14195
14314
  ] },
14196
- { name: "tom", role: "Principal Engineer", status: "idle", activity: "", memoryCount: 689, projects: [
14315
+ { name: "tom", role: "Principal Engineer", status: "idle", activity: "", memoryCount: 700, projects: [
14197
14316
  { name: "exe-os", status: "idle" }
14198
14317
  ], recentTasks: [
14199
14318
  "Implemented BashTool sandboxed execution",
14200
14319
  "Ported session scoping to exe-agent-memory"
14201
14320
  ] },
14202
- { name: "sasha", role: "Content Production", status: "offline", activity: "", memoryCount: 60, projects: [
14321
+ { name: "sasha", role: "Content Production", status: "offline", activity: "", memoryCount: 50, projects: [
14203
14322
  { name: "exe-build-skills", status: "idle" }
14204
14323
  ], recentTasks: [
14205
14324
  "Rendered carousel export prototype"
@@ -14212,7 +14331,7 @@ var DEMO_ACTIVITY = [
14212
14331
  { time: "11:15", agent: "mari", action: "Completed exe-os UI design system" },
14213
14332
  { time: "10:50", agent: "exe", action: "Approved gateway Phase 4" }
14214
14333
  ];
14215
- var DEMO_HEALTH = { memories: 27453, daemon: "running", cloud: "disabled" };
14334
+ var DEMO_HEALTH = { memories: 25750, daemon: "running", cloud: "disabled" };
14216
14335
  var DEMO_PROJECTS = [
14217
14336
  {
14218
14337
  projectName: "exe-os",
@@ -14790,8 +14909,8 @@ function CommandCenterView({
14790
14909
  const { createDefaultHooks: createDefaultHooks2 } = await Promise.resolve().then(() => (init_hooks(), hooks_exports));
14791
14910
  const { readFileSync: readFileSync11, existsSync: existsSync14 } = await import("fs");
14792
14911
  const { join } = await import("path");
14793
- const { homedir } = await import("os");
14794
- const configPath = join(homedir(), ".exe-os", "config.json");
14912
+ const { homedir: homedir3 } = await import("os");
14913
+ const configPath = join(homedir3(), ".exe-os", "config.json");
14795
14914
  let failoverChain = ["anthropic", "opencode", "gemini", "openai"];
14796
14915
  let providerConfigs = {};
14797
14916
  if (existsSync14(configPath)) {
@@ -14854,7 +14973,7 @@ function CommandCenterView({
14854
14973
  registry.register(BashTool2);
14855
14974
  let agentRole = "CTO";
14856
14975
  try {
14857
- const markerDir = join(homedir(), ".exe-os", "session-cache");
14976
+ const markerDir = join(homedir3(), ".exe-os", "session-cache");
14858
14977
  const agentFiles = (await import("fs")).readdirSync(markerDir).filter((f) => f.startsWith("active-agent-"));
14859
14978
  for (const f of agentFiles) {
14860
14979
  const data = JSON.parse(readFileSync11(join(markerDir, f), "utf8"));
@@ -14994,10 +15113,10 @@ function CommandCenterView({
14994
15113
  const demoEntries = DEMO_PROJECTS.map((p) => ({
14995
15114
  projectName: p.projectName,
14996
15115
  exeSession: p.exeSession,
14997
- projectDir: `/Users/demo/${p.projectName}`,
15116
+ projectDir: path11.join(homedir(), p.projectName),
14998
15117
  employeeCount: p.employees.length,
14999
15118
  activeCount: p.employees.filter((e) => e.status === "active").length,
15000
- memoryCount: p.projectName === "exe-os" ? 18331 : p.projectName === "exe-create" || p.projectName === "exe-build-skills" ? 2100 : 890,
15119
+ memoryCount: p.employees.length * 4e3,
15001
15120
  status: p.employees.some((e) => e.status === "active") ? "active" : "idle",
15002
15121
  type: p.projectName.startsWith("exe-") ? "code" : "automation",
15003
15122
  recentTasks: DEMO_RECENT_TASKS[p.projectName] ?? []
@@ -15395,6 +15514,8 @@ function ChatMessageRow({ msg }) {
15395
15514
 
15396
15515
  // src/tui/views/Sessions.tsx
15397
15516
  import { useState as useState9, useEffect as useEffect11, useCallback as useCallback6 } from "react";
15517
+ import path21 from "path";
15518
+ import { homedir as homedir2 } from "os";
15398
15519
 
15399
15520
  // src/tui/components/TmuxPane.tsx
15400
15521
  import { useState as useState7, useEffect as useEffect9 } from "react";
@@ -15673,7 +15794,7 @@ function SessionsView({
15673
15794
  if (demo) {
15674
15795
  setProjects(DEMO_PROJECTS.map((p) => ({
15675
15796
  ...p,
15676
- projectDir: `/Users/demo/${p.projectName}`,
15797
+ projectDir: path21.join(homedir2(), p.projectName),
15677
15798
  employees: p.employees.map((e) => ({ ...e, attached: e.status === "active" }))
15678
15799
  })));
15679
15800
  return;