@askexenow/exe-os 0.9.102 → 0.9.104

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 (92) hide show
  1. package/dist/bin/agentic-ontology-backfill.js +334 -100
  2. package/dist/bin/agentic-reflection-backfill.js +328 -97
  3. package/dist/bin/agentic-semantic-label.js +328 -97
  4. package/dist/bin/backfill-conversations.js +332 -97
  5. package/dist/bin/backfill-responses.js +332 -97
  6. package/dist/bin/backfill-vectors.js +337 -106
  7. package/dist/bin/bulk-sync-postgres.js +335 -101
  8. package/dist/bin/cleanup-stale-review-tasks.js +356 -108
  9. package/dist/bin/cli.js +653 -405
  10. package/dist/bin/exe-agent.js +21 -3
  11. package/dist/bin/exe-assign.js +338 -94
  12. package/dist/bin/exe-boot.js +472 -239
  13. package/dist/bin/exe-call.js +22 -5
  14. package/dist/bin/exe-cloud.js +404 -158
  15. package/dist/bin/exe-dispatch.js +390 -142
  16. package/dist/bin/exe-doctor.js +349 -103
  17. package/dist/bin/exe-export-behaviors.js +351 -105
  18. package/dist/bin/exe-forget.js +352 -103
  19. package/dist/bin/exe-gateway.js +420 -172
  20. package/dist/bin/exe-heartbeat.js +361 -113
  21. package/dist/bin/exe-kill.js +344 -98
  22. package/dist/bin/exe-launch-agent.js +375 -129
  23. package/dist/bin/exe-new-employee.js +83 -67
  24. package/dist/bin/exe-pending-messages.js +356 -108
  25. package/dist/bin/exe-pending-notifications.js +358 -110
  26. package/dist/bin/exe-pending-reviews.js +359 -111
  27. package/dist/bin/exe-rename.js +354 -108
  28. package/dist/bin/exe-review.js +343 -97
  29. package/dist/bin/exe-search.js +363 -113
  30. package/dist/bin/exe-session-cleanup.js +403 -155
  31. package/dist/bin/exe-settings.js +14 -9
  32. package/dist/bin/exe-start-codex.js +365 -131
  33. package/dist/bin/exe-start-opencode.js +359 -125
  34. package/dist/bin/exe-status.js +356 -108
  35. package/dist/bin/exe-team.js +343 -97
  36. package/dist/bin/git-sweep.js +390 -142
  37. package/dist/bin/graph-backfill.js +334 -100
  38. package/dist/bin/graph-export.js +346 -100
  39. package/dist/bin/install.js +1 -0
  40. package/dist/bin/intercom-check.js +403 -155
  41. package/dist/bin/pre-publish.js +12 -0
  42. package/dist/bin/scan-tasks.js +393 -145
  43. package/dist/bin/setup.js +331 -159
  44. package/dist/bin/shard-migrate.js +328 -94
  45. package/dist/gateway/index.js +406 -158
  46. package/dist/hooks/bug-report-worker.js +396 -148
  47. package/dist/hooks/codex-stop-task-finalizer.js +374 -126
  48. package/dist/hooks/commit-complete.js +390 -142
  49. package/dist/hooks/error-recall.js +365 -115
  50. package/dist/hooks/ingest.js +357 -111
  51. package/dist/hooks/instructions-loaded.js +351 -105
  52. package/dist/hooks/notification.js +343 -97
  53. package/dist/hooks/post-compact.js +358 -110
  54. package/dist/hooks/post-tool-combined.js +384 -132
  55. package/dist/hooks/pre-compact.js +391 -143
  56. package/dist/hooks/pre-tool-use.js +362 -114
  57. package/dist/hooks/prompt-submit.js +422 -170
  58. package/dist/hooks/session-end.js +393 -145
  59. package/dist/hooks/session-start.js +390 -138
  60. package/dist/hooks/stop.js +361 -113
  61. package/dist/hooks/subagent-stop.js +354 -106
  62. package/dist/hooks/summary-worker.js +418 -185
  63. package/dist/index.js +400 -152
  64. package/dist/lib/cloud-sync.js +291 -131
  65. package/dist/lib/consolidation.js +8 -2
  66. package/dist/lib/database.js +233 -73
  67. package/dist/lib/db.js +233 -73
  68. package/dist/lib/device-registry.js +237 -77
  69. package/dist/lib/employee-templates.js +19 -1
  70. package/dist/lib/exe-daemon.js +705 -409
  71. package/dist/lib/hybrid-search.js +363 -113
  72. package/dist/lib/identity.js +9 -5
  73. package/dist/lib/messaging.js +26 -20
  74. package/dist/lib/reminders.js +5 -1
  75. package/dist/lib/schedules.js +320 -89
  76. package/dist/lib/skill-learning.js +28 -24
  77. package/dist/lib/store.js +342 -96
  78. package/dist/lib/tasks.js +82 -76
  79. package/dist/lib/tmux-routing.js +74 -68
  80. package/dist/lib/token-spend.js +5 -1
  81. package/dist/mcp/server.js +628 -355
  82. package/dist/mcp/tools/complete-reminder.js +5 -1
  83. package/dist/mcp/tools/create-reminder.js +5 -1
  84. package/dist/mcp/tools/create-task.js +89 -83
  85. package/dist/mcp/tools/deactivate-behavior.js +7 -3
  86. package/dist/mcp/tools/list-reminders.js +5 -1
  87. package/dist/mcp/tools/list-tasks.js +28 -21
  88. package/dist/mcp/tools/send-message.js +28 -22
  89. package/dist/mcp/tools/update-task.js +89 -83
  90. package/dist/runtime/index.js +390 -142
  91. package/dist/tui/App.js +437 -189
  92. package/package.json +1 -1
@@ -118,8 +118,10 @@ import { z } from "zod";
118
118
  import crypto from "crypto";
119
119
 
120
120
  // src/lib/database.ts
121
- import { chmodSync as chmodSync2 } from "fs";
121
+ import { chmodSync as chmodSync2, existsSync as existsSync4, statSync, copyFileSync, unlinkSync as unlinkSync2, openSync, closeSync, mkdirSync as mkdirSync2 } from "fs";
122
122
  import { createClient } from "@libsql/client";
123
+ import { homedir } from "os";
124
+ import { join } from "path";
123
125
 
124
126
  // src/lib/employees.ts
125
127
  init_config();
@@ -147,9 +149,11 @@ var BOOLEAN_COLUMN_NAMES = new Set(
147
149
  );
148
150
 
149
151
  // src/lib/database.ts
152
+ var _debugDb = process.env.EXE_DEBUG === "1";
150
153
  var _resilientClient = null;
151
154
  var _daemonClient = null;
152
155
  var _adapterClient = null;
156
+ var DB_LOCK_PATH = join(homedir(), ".exe-os", "db.lock");
153
157
  function getClient() {
154
158
  if (!_adapterClient) {
155
159
  throw new Error("Database client not initialized. Call initDatabase() first.");
@@ -118,8 +118,10 @@ import { z } from "zod";
118
118
  import crypto from "crypto";
119
119
 
120
120
  // src/lib/database.ts
121
- import { chmodSync as chmodSync2 } from "fs";
121
+ import { chmodSync as chmodSync2, existsSync as existsSync4, statSync, copyFileSync, unlinkSync as unlinkSync2, openSync, closeSync, mkdirSync as mkdirSync2 } from "fs";
122
122
  import { createClient } from "@libsql/client";
123
+ import { homedir } from "os";
124
+ import { join } from "path";
123
125
 
124
126
  // src/lib/employees.ts
125
127
  init_config();
@@ -147,9 +149,11 @@ var BOOLEAN_COLUMN_NAMES = new Set(
147
149
  );
148
150
 
149
151
  // src/lib/database.ts
152
+ var _debugDb = process.env.EXE_DEBUG === "1";
150
153
  var _resilientClient = null;
151
154
  var _daemonClient = null;
152
155
  var _adapterClient = null;
156
+ var DB_LOCK_PATH = join(homedir(), ".exe-os", "db.lock");
153
157
  function getClient() {
154
158
  if (!_adapterClient) {
155
159
  throw new Error("Database client not initialized. Call initDatabase() first.");
@@ -741,8 +741,10 @@ var init_memory = __esm({
741
741
  });
742
742
 
743
743
  // src/lib/database.ts
744
- import { chmodSync as chmodSync2 } from "fs";
744
+ import { chmodSync as chmodSync2, existsSync as existsSync5, statSync, copyFileSync, unlinkSync as unlinkSync2, openSync, closeSync, mkdirSync as mkdirSync2 } from "fs";
745
745
  import { createClient } from "@libsql/client";
746
+ import { homedir } from "os";
747
+ import { join } from "path";
746
748
  function getClient() {
747
749
  if (!_adapterClient) {
748
750
  throw new Error("Database client not initialized. Call initDatabase() first.");
@@ -761,7 +763,7 @@ function getClient() {
761
763
  }
762
764
  return _resilientClient;
763
765
  }
764
- var _resilientClient, _daemonClient, _adapterClient;
766
+ var _debugDb, _resilientClient, _daemonClient, _adapterClient, DB_LOCK_PATH;
765
767
  var init_database = __esm({
766
768
  "src/lib/database.ts"() {
767
769
  "use strict";
@@ -769,20 +771,22 @@ var init_database = __esm({
769
771
  init_employees();
770
772
  init_database_adapter();
771
773
  init_memory();
774
+ _debugDb = process.env.EXE_DEBUG === "1";
772
775
  _resilientClient = null;
773
776
  _daemonClient = null;
774
777
  _adapterClient = null;
778
+ DB_LOCK_PATH = join(homedir(), ".exe-os", "db.lock");
775
779
  }
776
780
  });
777
781
 
778
782
  // src/lib/session-registry.ts
779
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync2, existsSync as existsSync5 } from "fs";
783
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, existsSync as existsSync6 } from "fs";
780
784
  import path5 from "path";
781
785
  import os4 from "os";
782
786
  function registerSession(entry) {
783
787
  const dir = path5.dirname(REGISTRY_PATH);
784
- if (!existsSync5(dir)) {
785
- mkdirSync2(dir, { recursive: true });
788
+ if (!existsSync6(dir)) {
789
+ mkdirSync3(dir, { recursive: true });
786
790
  }
787
791
  const sessions = listSessions();
788
792
  const idx = sessions.findIndex((s) => s.windowName === entry.windowName);
@@ -1076,16 +1080,16 @@ __export(intercom_queue_exports, {
1076
1080
  queueIntercom: () => queueIntercom,
1077
1081
  readQueue: () => readQueue
1078
1082
  });
1079
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, renameSync as renameSync3, existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
1083
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, renameSync as renameSync3, existsSync as existsSync7, mkdirSync as mkdirSync4 } from "fs";
1080
1084
  import path6 from "path";
1081
1085
  import os5 from "os";
1082
1086
  function ensureDir() {
1083
1087
  const dir = path6.dirname(QUEUE_PATH);
1084
- if (!existsSync6(dir)) mkdirSync3(dir, { recursive: true });
1088
+ if (!existsSync7(dir)) mkdirSync4(dir, { recursive: true });
1085
1089
  }
1086
1090
  function readQueue() {
1087
1091
  try {
1088
- if (!existsSync6(QUEUE_PATH)) return [];
1092
+ if (!existsSync7(QUEUE_PATH)) return [];
1089
1093
  return JSON.parse(readFileSync5(QUEUE_PATH, "utf8"));
1090
1094
  } catch {
1091
1095
  return [];
@@ -1194,7 +1198,7 @@ var init_intercom_queue = __esm({
1194
1198
  });
1195
1199
 
1196
1200
  // src/lib/license.ts
1197
- import { readFileSync as readFileSync6, writeFileSync as writeFileSync5, existsSync as existsSync7, mkdirSync as mkdirSync4 } from "fs";
1201
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync5, existsSync as existsSync8, mkdirSync as mkdirSync5 } from "fs";
1198
1202
  import { randomUUID } from "crypto";
1199
1203
  import { createRequire as createRequire2 } from "module";
1200
1204
  import { pathToFileURL as pathToFileURL2 } from "url";
@@ -1221,11 +1225,11 @@ var init_license = __esm({
1221
1225
  });
1222
1226
 
1223
1227
  // src/lib/plan-limits.ts
1224
- import { readFileSync as readFileSync7, existsSync as existsSync8 } from "fs";
1228
+ import { readFileSync as readFileSync7, existsSync as existsSync9 } from "fs";
1225
1229
  import path8 from "path";
1226
1230
  function getLicenseSync() {
1227
1231
  try {
1228
- if (!existsSync8(CACHE_PATH2)) return freeLicense();
1232
+ if (!existsSync9(CACHE_PATH2)) return freeLicense();
1229
1233
  const raw = JSON.parse(readFileSync7(CACHE_PATH2, "utf8"));
1230
1234
  if (!raw.token || typeof raw.token !== "string") return freeLicense();
1231
1235
  const parts = raw.token.split(".");
@@ -1264,7 +1268,7 @@ function assertEmployeeLimitSync(rosterPath) {
1264
1268
  const filePath = rosterPath ?? EMPLOYEES_PATH;
1265
1269
  let count = 0;
1266
1270
  try {
1267
- if (existsSync8(filePath)) {
1271
+ if (existsSync9(filePath)) {
1268
1272
  const raw = readFileSync7(filePath, "utf8");
1269
1273
  const employees = JSON.parse(raw);
1270
1274
  count = Array.isArray(employees) ? employees.length : 0;
@@ -1302,9 +1306,9 @@ var init_plan_limits = __esm({
1302
1306
  import os7 from "os";
1303
1307
  import path9 from "path";
1304
1308
  import {
1305
- existsSync as existsSync9,
1309
+ existsSync as existsSync10,
1306
1310
  lstatSync,
1307
- mkdirSync as mkdirSync5,
1311
+ mkdirSync as mkdirSync6,
1308
1312
  readlinkSync as readlinkSync2,
1309
1313
  symlinkSync as symlinkSync2
1310
1314
  } from "fs";
@@ -1320,8 +1324,8 @@ function claudeAgentLinkPath(homeDir, agentId) {
1320
1324
  function ensureAgentSymlink(agentId, homeDir = os7.homedir()) {
1321
1325
  const target = identitySourcePath(homeDir, agentId);
1322
1326
  const link = claudeAgentLinkPath(homeDir, agentId);
1323
- mkdirSync5(claudeAgentsDir(homeDir), { recursive: true });
1324
- if (existsSync9(link)) {
1327
+ mkdirSync6(claudeAgentsDir(homeDir), { recursive: true });
1328
+ if (existsSync10(link)) {
1325
1329
  let stat;
1326
1330
  try {
1327
1331
  stat = lstatSync(link);
@@ -1750,7 +1754,7 @@ __export(tasks_review_exports, {
1750
1754
  listPendingReviews: () => listPendingReviews
1751
1755
  });
1752
1756
  import path10 from "path";
1753
- import { existsSync as existsSync10, readdirSync, unlinkSync as unlinkSync2 } from "fs";
1757
+ import { existsSync as existsSync11, readdirSync, unlinkSync as unlinkSync3 } from "fs";
1754
1758
  function formatAge(isoTimestamp) {
1755
1759
  if (!isoTimestamp) return "";
1756
1760
  const ms = Date.now() - new Date(isoTimestamp).getTime();
@@ -2020,10 +2024,10 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
2020
2024
  }
2021
2025
  try {
2022
2026
  const cacheDir = path10.join(EXE_AI_DIR, "session-cache");
2023
- if (existsSync10(cacheDir)) {
2027
+ if (existsSync11(cacheDir)) {
2024
2028
  for (const f of readdirSync(cacheDir)) {
2025
2029
  if (f.startsWith("review-notified-")) {
2026
- unlinkSync2(path10.join(cacheDir, f));
2030
+ unlinkSync3(path10.join(cacheDir, f));
2027
2031
  }
2028
2032
  }
2029
2033
  }
@@ -2070,11 +2074,11 @@ __export(tmux_routing_exports, {
2070
2074
  verifyPaneAtCapacity: () => verifyPaneAtCapacity
2071
2075
  });
2072
2076
  import { execFileSync as execFileSync2, execSync as execSync4 } from "child_process";
2073
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, mkdirSync as mkdirSync6, existsSync as existsSync11, appendFileSync, readdirSync as readdirSync2 } from "fs";
2077
+ import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, mkdirSync as mkdirSync7, existsSync as existsSync12, appendFileSync, readdirSync as readdirSync2 } from "fs";
2074
2078
  import path11 from "path";
2075
2079
  import os8 from "os";
2076
2080
  import { fileURLToPath } from "url";
2077
- import { unlinkSync as unlinkSync3 } from "fs";
2081
+ import { unlinkSync as unlinkSync4 } from "fs";
2078
2082
  function spawnLockPath(sessionName) {
2079
2083
  return path11.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
2080
2084
  }
@@ -2087,11 +2091,11 @@ function isProcessAlive(pid) {
2087
2091
  }
2088
2092
  }
2089
2093
  function acquireSpawnLock(sessionName) {
2090
- if (!existsSync11(SPAWN_LOCK_DIR)) {
2091
- mkdirSync6(SPAWN_LOCK_DIR, { recursive: true });
2094
+ if (!existsSync12(SPAWN_LOCK_DIR)) {
2095
+ mkdirSync7(SPAWN_LOCK_DIR, { recursive: true });
2092
2096
  }
2093
2097
  const lockFile = spawnLockPath(sessionName);
2094
- if (existsSync11(lockFile)) {
2098
+ if (existsSync12(lockFile)) {
2095
2099
  try {
2096
2100
  const lock = JSON.parse(readFileSync8(lockFile, "utf8"));
2097
2101
  const age = Date.now() - lock.timestamp;
@@ -2106,7 +2110,7 @@ function acquireSpawnLock(sessionName) {
2106
2110
  }
2107
2111
  function releaseSpawnLock(sessionName) {
2108
2112
  try {
2109
- unlinkSync3(spawnLockPath(sessionName));
2113
+ unlinkSync4(spawnLockPath(sessionName));
2110
2114
  } catch {
2111
2115
  }
2112
2116
  }
@@ -2119,7 +2123,7 @@ function resolveBehaviorsExporterScript() {
2119
2123
  "bin",
2120
2124
  "exe-export-behaviors.js"
2121
2125
  );
2122
- return existsSync11(scriptPath) ? scriptPath : null;
2126
+ return existsSync12(scriptPath) ? scriptPath : null;
2123
2127
  } catch {
2124
2128
  return null;
2125
2129
  }
@@ -2185,8 +2189,8 @@ function extractRootExe(name) {
2185
2189
  return parts.length > 0 ? parts[parts.length - 1] : null;
2186
2190
  }
2187
2191
  function registerParentExe(sessionKey, parentExe, dispatchedBy) {
2188
- if (!existsSync11(SESSION_CACHE)) {
2189
- mkdirSync6(SESSION_CACHE, { recursive: true });
2192
+ if (!existsSync12(SESSION_CACHE)) {
2193
+ mkdirSync7(SESSION_CACHE, { recursive: true });
2190
2194
  }
2191
2195
  const rootExe = extractRootExe(parentExe) ?? parentExe;
2192
2196
  const filePath = path11.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
@@ -2216,11 +2220,13 @@ function getDispatchedBy(sessionKey) {
2216
2220
  }
2217
2221
  }
2218
2222
  function resolveExeSession() {
2219
- if (process.env.EXE_SESSION_NAME) {
2220
- return extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
2221
- }
2222
2223
  const mySession = getMySession();
2223
- if (!mySession) return null;
2224
+ if (!mySession) {
2225
+ if (process.env.EXE_SESSION_NAME) {
2226
+ return extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
2227
+ }
2228
+ return null;
2229
+ }
2224
2230
  const fromSessionName = extractRootExe(mySession);
2225
2231
  let candidate = null;
2226
2232
  try {
@@ -2315,7 +2321,7 @@ async function verifyPaneAtCapacity(sessionName) {
2315
2321
  }
2316
2322
  function readDebounceState() {
2317
2323
  try {
2318
- if (!existsSync11(DEBOUNCE_FILE)) return {};
2324
+ if (!existsSync12(DEBOUNCE_FILE)) return {};
2319
2325
  const raw = JSON.parse(readFileSync8(DEBOUNCE_FILE, "utf8"));
2320
2326
  const state = {};
2321
2327
  for (const [key, val] of Object.entries(raw)) {
@@ -2332,7 +2338,7 @@ function readDebounceState() {
2332
2338
  }
2333
2339
  function writeDebounceState(state) {
2334
2340
  try {
2335
- if (!existsSync11(SESSION_CACHE)) mkdirSync6(SESSION_CACHE, { recursive: true });
2341
+ if (!existsSync12(SESSION_CACHE)) mkdirSync7(SESSION_CACHE, { recursive: true });
2336
2342
  writeFileSync6(DEBOUNCE_FILE, JSON.stringify(state));
2337
2343
  } catch {
2338
2344
  }
@@ -2433,7 +2439,7 @@ function sendIntercom(targetSession) {
2433
2439
  const rawAgent = targetSession.split("-")[0] ?? targetSession;
2434
2440
  const agent = baseAgentName(rawAgent);
2435
2441
  const markerPath = path11.join(SESSION_CACHE, `current-task-${agent}.json`);
2436
- if (existsSync11(markerPath)) {
2442
+ if (existsSync12(markerPath)) {
2437
2443
  logIntercom(`SKIP \u2192 ${targetSession} (has in_progress task marker + not idle \u2014 will auto-chain)`);
2438
2444
  return "debounced";
2439
2445
  }
@@ -2444,7 +2450,7 @@ function sendIntercom(targetSession) {
2444
2450
  const rawAgent = targetSession.split("-")[0] ?? targetSession;
2445
2451
  const agent = baseAgentName(rawAgent);
2446
2452
  const taskDir = path11.join(process.cwd(), "exe", agent);
2447
- if (existsSync11(taskDir)) {
2453
+ if (existsSync12(taskDir)) {
2448
2454
  const files = readdirSync2(taskDir).filter(
2449
2455
  (f) => f.endsWith(".md") && f !== "DONE.txt"
2450
2456
  );
@@ -2605,15 +2611,15 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
2605
2611
  const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
2606
2612
  const logDir = path11.join(os8.homedir(), ".exe-os", "session-logs");
2607
2613
  const logFile = path11.join(logDir, `${instanceLabel}-${Date.now()}.log`);
2608
- if (!existsSync11(logDir)) {
2609
- mkdirSync6(logDir, { recursive: true });
2614
+ if (!existsSync12(logDir)) {
2615
+ mkdirSync7(logDir, { recursive: true });
2610
2616
  }
2611
2617
  transport.kill(sessionName);
2612
2618
  let cleanupSuffix = "";
2613
2619
  try {
2614
2620
  const thisFile = fileURLToPath(import.meta.url);
2615
2621
  const cleanupScript = path11.join(path11.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
2616
- if (existsSync11(cleanupScript)) {
2622
+ if (existsSync12(cleanupScript)) {
2617
2623
  cleanupSuffix = `; ${process.execPath} "${cleanupScript}" "${employeeName}" "${exeSession}"`;
2618
2624
  }
2619
2625
  } catch {
@@ -2668,7 +2674,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
2668
2674
  if (changed) {
2669
2675
  perms.allow = allow;
2670
2676
  settings.permissions = perms;
2671
- mkdirSync6(projSettingsDir, { recursive: true });
2677
+ mkdirSync7(projSettingsDir, { recursive: true });
2672
2678
  writeFileSync6(settingsPath, JSON.stringify(settings, null, 2) + "\n");
2673
2679
  }
2674
2680
  } catch {
@@ -2706,7 +2712,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
2706
2712
  `
2707
2713
  );
2708
2714
  }
2709
- } else if (existsSync11(identityPath2)) {
2715
+ } else if (existsSync12(identityPath2)) {
2710
2716
  identityFlag = ` --append-system-prompt-file ${identityPath2}`;
2711
2717
  legacyFallbackWarned = true;
2712
2718
  }
@@ -2728,7 +2734,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
2728
2734
  let sessionContextFlag = "";
2729
2735
  try {
2730
2736
  const ctxDir = path11.join(os8.homedir(), ".exe-os", "session-cache");
2731
- mkdirSync6(ctxDir, { recursive: true });
2737
+ mkdirSync7(ctxDir, { recursive: true });
2732
2738
  const ctxFile = path11.join(ctxDir, `session-context-${sessionName}.md`);
2733
2739
  const ctxContent = [
2734
2740
  `## Session Context`,
@@ -2949,8 +2955,8 @@ import os9 from "os";
2949
2955
  import {
2950
2956
  readFileSync as readFileSync9,
2951
2957
  readdirSync as readdirSync3,
2952
- unlinkSync as unlinkSync4,
2953
- existsSync as existsSync12,
2958
+ unlinkSync as unlinkSync5,
2959
+ existsSync as existsSync13,
2954
2960
  rmdirSync
2955
2961
  } from "fs";
2956
2962
  async function writeNotification(notification) {
@@ -3109,7 +3115,7 @@ import path14 from "path";
3109
3115
  import os10 from "os";
3110
3116
  import { execSync as execSync6 } from "child_process";
3111
3117
  import { mkdir as mkdir3, writeFile as writeFile3, appendFile } from "fs/promises";
3112
- import { existsSync as existsSync13, readFileSync as readFileSync10 } from "fs";
3118
+ import { existsSync as existsSync14, readFileSync as readFileSync10 } from "fs";
3113
3119
  async function writeCheckpoint(input) {
3114
3120
  const client = getClient();
3115
3121
  const row = await resolveTask(client, input.taskId);
@@ -3350,7 +3356,7 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
3350
3356
  const EXE_OS_DIR = path14.join(os10.homedir(), ".exe-os");
3351
3357
  const mdPath = path14.join(EXE_OS_DIR, taskFile);
3352
3358
  const mdDir = path14.dirname(mdPath);
3353
- if (!existsSync13(mdDir)) await mkdir3(mdDir, { recursive: true });
3359
+ if (!existsSync14(mdDir)) await mkdir3(mdDir, { recursive: true });
3354
3360
  const reviewer = input.reviewer ?? input.assignedBy;
3355
3361
  const mdContent = `# ${input.title}
3356
3362
 
@@ -3656,7 +3662,7 @@ async function deleteTaskCore(taskId, _baseDir) {
3656
3662
  async function ensureArchitectureDoc(baseDir, projectName) {
3657
3663
  const archPath = path14.join(baseDir, "exe", "ARCHITECTURE.md");
3658
3664
  try {
3659
- if (existsSync13(archPath)) return;
3665
+ if (existsSync14(archPath)) return;
3660
3666
  const template = [
3661
3667
  `# ${projectName} \u2014 System Architecture`,
3662
3668
  "",
@@ -3691,7 +3697,7 @@ async function ensureArchitectureDoc(baseDir, projectName) {
3691
3697
  async function ensureGitignoreExe(baseDir) {
3692
3698
  const gitignorePath = path14.join(baseDir, ".gitignore");
3693
3699
  try {
3694
- if (existsSync13(gitignorePath)) {
3700
+ if (existsSync14(gitignorePath)) {
3695
3701
  const content = readFileSync10(gitignorePath, "utf-8");
3696
3702
  if (/^\/?exe\/?$/m.test(content)) return;
3697
3703
  await appendFile(gitignorePath, "\n# Employee task assignments (private)\n/exe/\n");
@@ -3890,7 +3896,7 @@ var init_tasks_notify = __esm({
3890
3896
  // src/lib/daemon-auth.ts
3891
3897
  import crypto4 from "crypto";
3892
3898
  import path16 from "path";
3893
- import { existsSync as existsSync14, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "fs";
3899
+ import { existsSync as existsSync15, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "fs";
3894
3900
  function normalizeToken(token) {
3895
3901
  if (!token) return null;
3896
3902
  const trimmed = token.trim();
@@ -3898,7 +3904,7 @@ function normalizeToken(token) {
3898
3904
  }
3899
3905
  function readDaemonToken() {
3900
3906
  try {
3901
- if (!existsSync14(DAEMON_TOKEN_PATH)) return null;
3907
+ if (!existsSync15(DAEMON_TOKEN_PATH)) return null;
3902
3908
  return normalizeToken(readFileSync11(DAEMON_TOKEN_PATH, "utf8"));
3903
3909
  } catch {
3904
3910
  return null;
@@ -3929,7 +3935,7 @@ import net from "net";
3929
3935
  import os11 from "os";
3930
3936
  import { spawn, execSync as execSync7 } from "child_process";
3931
3937
  import { randomUUID as randomUUID2 } from "crypto";
3932
- import { existsSync as existsSync15, unlinkSync as unlinkSync5, readFileSync as readFileSync12, openSync, closeSync, statSync } from "fs";
3938
+ import { existsSync as existsSync16, unlinkSync as unlinkSync6, readFileSync as readFileSync12, openSync as openSync2, closeSync as closeSync2, statSync as statSync2 } from "fs";
3933
3939
  import path17 from "path";
3934
3940
  import { fileURLToPath as fileURLToPath2 } from "url";
3935
3941
  function handleData(chunk) {
@@ -3966,7 +3972,7 @@ function isZombie(pid) {
3966
3972
  }
3967
3973
  }
3968
3974
  function cleanupStaleFiles() {
3969
- if (existsSync15(PID_PATH)) {
3975
+ if (existsSync16(PID_PATH)) {
3970
3976
  try {
3971
3977
  const pid = parseInt(readFileSync12(PID_PATH, "utf8").trim(), 10);
3972
3978
  if (pid > 0) {
@@ -3983,11 +3989,11 @@ function cleanupStaleFiles() {
3983
3989
  } catch {
3984
3990
  }
3985
3991
  try {
3986
- unlinkSync5(PID_PATH);
3992
+ unlinkSync6(PID_PATH);
3987
3993
  } catch {
3988
3994
  }
3989
3995
  try {
3990
- unlinkSync5(SOCKET_PATH);
3996
+ unlinkSync6(SOCKET_PATH);
3991
3997
  } catch {
3992
3998
  }
3993
3999
  }
@@ -3996,7 +4002,7 @@ function findPackageRoot() {
3996
4002
  let dir = path17.dirname(fileURLToPath2(import.meta.url));
3997
4003
  const { root } = path17.parse(dir);
3998
4004
  while (dir !== root) {
3999
- if (existsSync15(path17.join(dir, "package.json"))) return dir;
4005
+ if (existsSync16(path17.join(dir, "package.json"))) return dir;
4000
4006
  dir = path17.dirname(dir);
4001
4007
  }
4002
4008
  return null;
@@ -4016,7 +4022,7 @@ function spawnDaemon() {
4016
4022
  return;
4017
4023
  }
4018
4024
  const daemonPath = path17.join(pkgRoot, "dist", "lib", "exe-daemon.js");
4019
- if (!existsSync15(daemonPath)) {
4025
+ if (!existsSync16(daemonPath)) {
4020
4026
  process.stderr.write(`[exed-client] WARN: daemon script not found at ${daemonPath}
4021
4027
  `);
4022
4028
  return;
@@ -4028,7 +4034,7 @@ function spawnDaemon() {
4028
4034
  const logPath = path17.join(path17.dirname(SOCKET_PATH), "exed.log");
4029
4035
  let stderrFd = "ignore";
4030
4036
  try {
4031
- stderrFd = openSync(logPath, "a");
4037
+ stderrFd = openSync2(logPath, "a");
4032
4038
  } catch {
4033
4039
  }
4034
4040
  const heapCapMB = totalGB <= 8 ? 256 : 512;
@@ -4050,27 +4056,27 @@ function spawnDaemon() {
4050
4056
  child.unref();
4051
4057
  if (typeof stderrFd === "number") {
4052
4058
  try {
4053
- closeSync(stderrFd);
4059
+ closeSync2(stderrFd);
4054
4060
  } catch {
4055
4061
  }
4056
4062
  }
4057
4063
  }
4058
4064
  function acquireSpawnLock2() {
4059
4065
  try {
4060
- const fd = openSync(SPAWN_LOCK_PATH, "wx");
4061
- closeSync(fd);
4066
+ const fd = openSync2(SPAWN_LOCK_PATH, "wx");
4067
+ closeSync2(fd);
4062
4068
  return true;
4063
4069
  } catch {
4064
4070
  try {
4065
- const stat = statSync(SPAWN_LOCK_PATH);
4071
+ const stat = statSync2(SPAWN_LOCK_PATH);
4066
4072
  if (Date.now() - stat.mtimeMs > SPAWN_LOCK_STALE_MS) {
4067
4073
  try {
4068
- unlinkSync5(SPAWN_LOCK_PATH);
4074
+ unlinkSync6(SPAWN_LOCK_PATH);
4069
4075
  } catch {
4070
4076
  }
4071
4077
  try {
4072
- const fd = openSync(SPAWN_LOCK_PATH, "wx");
4073
- closeSync(fd);
4078
+ const fd = openSync2(SPAWN_LOCK_PATH, "wx");
4079
+ closeSync2(fd);
4074
4080
  return true;
4075
4081
  } catch {
4076
4082
  }
@@ -4082,7 +4088,7 @@ function acquireSpawnLock2() {
4082
4088
  }
4083
4089
  function releaseSpawnLock2() {
4084
4090
  try {
4085
- unlinkSync5(SPAWN_LOCK_PATH);
4091
+ unlinkSync6(SPAWN_LOCK_PATH);
4086
4092
  } catch {
4087
4093
  }
4088
4094
  }
@@ -4190,7 +4196,7 @@ function killAndRespawnDaemon() {
4190
4196
  }
4191
4197
  try {
4192
4198
  process.stderr.write("[exed-client] Killing daemon for restart...\n");
4193
- if (existsSync15(PID_PATH)) {
4199
+ if (existsSync16(PID_PATH)) {
4194
4200
  try {
4195
4201
  const pid = parseInt(readFileSync12(PID_PATH, "utf8").trim(), 10);
4196
4202
  if (pid > 0) {
@@ -4209,11 +4215,11 @@ function killAndRespawnDaemon() {
4209
4215
  _connected = false;
4210
4216
  _buffer = "";
4211
4217
  try {
4212
- unlinkSync5(PID_PATH);
4218
+ unlinkSync6(PID_PATH);
4213
4219
  } catch {
4214
4220
  }
4215
4221
  try {
4216
- unlinkSync5(SOCKET_PATH);
4222
+ unlinkSync6(SOCKET_PATH);
4217
4223
  } catch {
4218
4224
  }
4219
4225
  spawnDaemon();
@@ -4223,7 +4229,7 @@ function killAndRespawnDaemon() {
4223
4229
  }
4224
4230
  function isDaemonTooYoung() {
4225
4231
  try {
4226
- const stat = statSync(PID_PATH);
4232
+ const stat = statSync2(PID_PATH);
4227
4233
  return Date.now() - stat.mtimeMs < MIN_DAEMON_AGE_MS;
4228
4234
  } catch {
4229
4235
  return false;
@@ -4373,10 +4379,10 @@ async function disposeEmbedder() {
4373
4379
  async function embedDirect(text) {
4374
4380
  const llamaCpp = await import("node-llama-cpp");
4375
4381
  const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
4376
- const { existsSync: existsSync17 } = await import("fs");
4382
+ const { existsSync: existsSync18 } = await import("fs");
4377
4383
  const path21 = await import("path");
4378
4384
  const modelPath = path21.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
4379
- if (!existsSync17(modelPath)) {
4385
+ if (!existsSync18(modelPath)) {
4380
4386
  throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
4381
4387
  }
4382
4388
  const llama = await llamaCpp.getLlama();
@@ -4743,7 +4749,7 @@ __export(tasks_exports, {
4743
4749
  writeCheckpoint: () => writeCheckpoint
4744
4750
  });
4745
4751
  import path18 from "path";
4746
- import { writeFileSync as writeFileSync8, mkdirSync as mkdirSync7, unlinkSync as unlinkSync6 } from "fs";
4752
+ import { writeFileSync as writeFileSync8, mkdirSync as mkdirSync8, unlinkSync as unlinkSync7 } from "fs";
4747
4753
  async function createTask(input) {
4748
4754
  const result = await createTaskCore(input);
4749
4755
  if (!input.skipDispatch && result.status !== "blocked" && !process.env.VITEST) {
@@ -4765,11 +4771,11 @@ async function updateTask(input) {
4765
4771
  const cacheDir = path18.join(EXE_AI_DIR, "session-cache");
4766
4772
  const cachePath = path18.join(cacheDir, `current-task-${agent}.json`);
4767
4773
  if (input.status === "in_progress") {
4768
- mkdirSync7(cacheDir, { recursive: true });
4774
+ mkdirSync8(cacheDir, { recursive: true });
4769
4775
  writeFileSync8(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
4770
4776
  } else if (input.status === "done" || input.status === "blocked" || input.status === "cancelled" || input.status === "closed") {
4771
4777
  try {
4772
- unlinkSync6(cachePath);
4778
+ unlinkSync7(cachePath);
4773
4779
  } catch {
4774
4780
  }
4775
4781
  }
@@ -4935,13 +4941,13 @@ __export(identity_exports, {
4935
4941
  listIdentities: () => listIdentities,
4936
4942
  updateIdentity: () => updateIdentity
4937
4943
  });
4938
- import { existsSync as existsSync16, mkdirSync as mkdirSync9, readFileSync as readFileSync14, writeFileSync as writeFileSync10 } from "fs";
4944
+ import { existsSync as existsSync17, mkdirSync as mkdirSync10, readFileSync as readFileSync14, writeFileSync as writeFileSync10 } from "fs";
4939
4945
  import { readdirSync as readdirSync5 } from "fs";
4940
4946
  import path20 from "path";
4941
4947
  import { createHash } from "crypto";
4942
4948
  function ensureDir2() {
4943
- if (!existsSync16(IDENTITY_DIR2)) {
4944
- mkdirSync9(IDENTITY_DIR2, { recursive: true });
4949
+ if (!existsSync17(IDENTITY_DIR2)) {
4950
+ mkdirSync10(IDENTITY_DIR2, { recursive: true });
4945
4951
  }
4946
4952
  }
4947
4953
  function identityPath(agentId) {
@@ -4989,7 +4995,7 @@ function contentHash(content) {
4989
4995
  }
4990
4996
  function getIdentity(agentId) {
4991
4997
  const filePath = identityPath(agentId);
4992
- if (!existsSync16(filePath)) return null;
4998
+ if (!existsSync17(filePath)) return null;
4993
4999
  const raw = readFileSync14(filePath, "utf-8");
4994
5000
  const { frontmatter, body } = parseFrontmatter(raw);
4995
5001
  return {
@@ -5618,7 +5624,7 @@ import { z } from "zod";
5618
5624
  // src/lib/active-agent.ts
5619
5625
  init_config();
5620
5626
  init_session_key();
5621
- import { readFileSync as readFileSync13, writeFileSync as writeFileSync9, mkdirSync as mkdirSync8, unlinkSync as unlinkSync7, readdirSync as readdirSync4 } from "fs";
5627
+ import { readFileSync as readFileSync13, writeFileSync as writeFileSync9, mkdirSync as mkdirSync9, unlinkSync as unlinkSync8, readdirSync as readdirSync4 } from "fs";
5622
5628
  import { execSync as execSync8 } from "child_process";
5623
5629
  import path19 from "path";
5624
5630
 
@@ -5690,7 +5696,7 @@ function getActiveAgent() {
5690
5696
  const age = Date.now() - new Date(data.startedAt).getTime();
5691
5697
  if (age > STALE_MS) {
5692
5698
  try {
5693
- unlinkSync7(markerPath);
5699
+ unlinkSync8(markerPath);
5694
5700
  } catch {
5695
5701
  }
5696
5702
  } else {
@@ -5786,10 +5792,10 @@ function registerCreateTask(server) {
5786
5792
  skipDispatch: true
5787
5793
  });
5788
5794
  try {
5789
- const { existsSync: existsSync17, mkdirSync: mkdirSync10, writeFileSync: writeFileSync11 } = await import("fs");
5795
+ const { existsSync: existsSync18, mkdirSync: mkdirSync11, writeFileSync: writeFileSync11 } = await import("fs");
5790
5796
  const { identityPath: identityPath2 } = await Promise.resolve().then(() => (init_identity(), identity_exports));
5791
5797
  const idPath = identityPath2(assigned_to);
5792
- if (!existsSync17(idPath)) {
5798
+ if (!existsSync18(idPath)) {
5793
5799
  const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
5794
5800
  const employees = await loadEmployees2();
5795
5801
  const emp = employees.find((e) => e.name === assigned_to);
@@ -5798,7 +5804,7 @@ function registerCreateTask(server) {
5798
5804
  const template = getTemplateForTitle2(emp.role);
5799
5805
  if (template) {
5800
5806
  const dir = (await import("path")).dirname(idPath);
5801
- if (!existsSync17(dir)) mkdirSync10(dir, { recursive: true });
5807
+ if (!existsSync18(dir)) mkdirSync11(dir, { recursive: true });
5802
5808
  writeFileSync11(idPath, template.replace(/^agent_id: \w+/m, `agent_id: ${assigned_to}`), "utf-8");
5803
5809
  }
5804
5810
  }
@@ -125,8 +125,10 @@ import { z } from "zod";
125
125
  import crypto from "crypto";
126
126
 
127
127
  // src/lib/database.ts
128
- import { chmodSync as chmodSync2 } from "fs";
128
+ import { chmodSync as chmodSync2, existsSync as existsSync4, statSync, copyFileSync, unlinkSync as unlinkSync2, openSync, closeSync, mkdirSync as mkdirSync2 } from "fs";
129
129
  import { createClient } from "@libsql/client";
130
+ import { homedir } from "os";
131
+ import { join } from "path";
130
132
 
131
133
  // src/lib/employees.ts
132
134
  init_config();
@@ -187,9 +189,11 @@ var BOOLEAN_COLUMN_NAMES = new Set(
187
189
 
188
190
  // src/lib/database.ts
189
191
  init_memory();
192
+ var _debugDb = process.env.EXE_DEBUG === "1";
190
193
  var _resilientClient = null;
191
194
  var _daemonClient = null;
192
195
  var _adapterClient = null;
196
+ var DB_LOCK_PATH = join(homedir(), ".exe-os", "db.lock");
193
197
  function getClient() {
194
198
  if (!_adapterClient) {
195
199
  throw new Error("Database client not initialized. Call initDatabase() first.");
@@ -221,7 +225,7 @@ async function deactivateBehavior(id) {
221
225
 
222
226
  // src/lib/active-agent.ts
223
227
  init_config();
224
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, unlinkSync as unlinkSync2, readdirSync } from "fs";
228
+ import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3, unlinkSync as unlinkSync3, readdirSync } from "fs";
225
229
  import { execSync as execSync3 } from "child_process";
226
230
  import path4 from "path";
227
231
 
@@ -354,7 +358,7 @@ function getActiveAgent() {
354
358
  const age = Date.now() - new Date(data.startedAt).getTime();
355
359
  if (age > STALE_MS) {
356
360
  try {
357
- unlinkSync2(markerPath);
361
+ unlinkSync3(markerPath);
358
362
  } catch {
359
363
  }
360
364
  } else {