@askexenow/exe-os 0.8.32 → 0.8.36

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 (87) hide show
  1. package/dist/bin/backfill-conversations.js +332 -348
  2. package/dist/bin/backfill-responses.js +72 -12
  3. package/dist/bin/backfill-vectors.js +72 -12
  4. package/dist/bin/cleanup-stale-review-tasks.js +63 -3
  5. package/dist/bin/cli.js +1518 -1122
  6. package/dist/bin/exe-agent.js +4 -4
  7. package/dist/bin/exe-assign.js +80 -18
  8. package/dist/bin/exe-boot.js +408 -89
  9. package/dist/bin/exe-call.js +83 -24
  10. package/dist/bin/exe-dispatch.js +18 -10
  11. package/dist/bin/exe-doctor.js +63 -3
  12. package/dist/bin/exe-export-behaviors.js +64 -3
  13. package/dist/bin/exe-forget.js +69 -4
  14. package/dist/bin/exe-gateway.js +121 -36
  15. package/dist/bin/exe-heartbeat.js +77 -13
  16. package/dist/bin/exe-kill.js +64 -3
  17. package/dist/bin/exe-launch-agent.js +162 -35
  18. package/dist/bin/exe-link.js +946 -0
  19. package/dist/bin/exe-new-employee.js +121 -36
  20. package/dist/bin/exe-pending-messages.js +72 -7
  21. package/dist/bin/exe-pending-notifications.js +63 -3
  22. package/dist/bin/exe-pending-reviews.js +75 -10
  23. package/dist/bin/exe-rename.js +1287 -0
  24. package/dist/bin/exe-review.js +64 -4
  25. package/dist/bin/exe-search.js +79 -13
  26. package/dist/bin/exe-session-cleanup.js +91 -26
  27. package/dist/bin/exe-status.js +64 -4
  28. package/dist/bin/exe-team.js +64 -4
  29. package/dist/bin/git-sweep.js +71 -4
  30. package/dist/bin/graph-backfill.js +64 -3
  31. package/dist/bin/graph-export.js +64 -3
  32. package/dist/bin/install.js +3 -3
  33. package/dist/bin/scan-tasks.js +71 -4
  34. package/dist/bin/setup.js +156 -38
  35. package/dist/bin/shard-migrate.js +64 -3
  36. package/dist/bin/wiki-sync.js +64 -3
  37. package/dist/gateway/index.js +122 -37
  38. package/dist/hooks/bug-report-worker.js +209 -23
  39. package/dist/hooks/commit-complete.js +71 -4
  40. package/dist/hooks/error-recall.js +79 -13
  41. package/dist/hooks/ingest-worker.js +129 -43
  42. package/dist/hooks/instructions-loaded.js +71 -4
  43. package/dist/hooks/notification.js +71 -4
  44. package/dist/hooks/post-compact.js +71 -4
  45. package/dist/hooks/pre-compact.js +71 -4
  46. package/dist/hooks/pre-tool-use.js +413 -194
  47. package/dist/hooks/prompt-ingest-worker.js +82 -22
  48. package/dist/hooks/prompt-submit.js +103 -37
  49. package/dist/hooks/response-ingest-worker.js +87 -22
  50. package/dist/hooks/session-end.js +71 -4
  51. package/dist/hooks/session-start.js +79 -13
  52. package/dist/hooks/stop.js +71 -4
  53. package/dist/hooks/subagent-stop.js +71 -4
  54. package/dist/hooks/summary-worker.js +303 -50
  55. package/dist/index.js +134 -46
  56. package/dist/lib/cloud-sync.js +209 -15
  57. package/dist/lib/consolidation.js +4 -4
  58. package/dist/lib/database.js +64 -2
  59. package/dist/lib/device-registry.js +70 -3
  60. package/dist/lib/employee-templates.js +48 -22
  61. package/dist/lib/employees.js +34 -1
  62. package/dist/lib/exe-daemon.js +136 -53
  63. package/dist/lib/hybrid-search.js +79 -13
  64. package/dist/lib/identity-templates.js +57 -6
  65. package/dist/lib/identity.js +3 -3
  66. package/dist/lib/messaging.js +22 -14
  67. package/dist/lib/reminders.js +3 -3
  68. package/dist/lib/schedules.js +63 -3
  69. package/dist/lib/skill-learning.js +3 -3
  70. package/dist/lib/status-brief.js +63 -5
  71. package/dist/lib/store.js +64 -3
  72. package/dist/lib/task-router.js +4 -2
  73. package/dist/lib/tasks.js +48 -21
  74. package/dist/lib/tmux-routing.js +47 -20
  75. package/dist/mcp/server.js +727 -58
  76. package/dist/mcp/tools/complete-reminder.js +3 -3
  77. package/dist/mcp/tools/create-reminder.js +3 -3
  78. package/dist/mcp/tools/create-task.js +151 -24
  79. package/dist/mcp/tools/deactivate-behavior.js +3 -3
  80. package/dist/mcp/tools/list-reminders.js +3 -3
  81. package/dist/mcp/tools/list-tasks.js +17 -8
  82. package/dist/mcp/tools/send-message.js +24 -16
  83. package/dist/mcp/tools/update-task.js +25 -16
  84. package/dist/runtime/index.js +112 -24
  85. package/dist/tui/App.js +139 -36
  86. package/package.json +6 -2
  87. package/src/commands/exe/rename.md +12 -0
@@ -266,12 +266,68 @@ var init_memory = __esm({
266
266
  }
267
267
  });
268
268
 
269
+ // src/lib/db-retry.ts
270
+ function isBusyError(err) {
271
+ if (err instanceof Error) {
272
+ const msg = err.message.toLowerCase();
273
+ return msg.includes("sqlite_busy") || msg.includes("database is locked");
274
+ }
275
+ return false;
276
+ }
277
+ function delay(ms) {
278
+ return new Promise((resolve) => setTimeout(resolve, ms));
279
+ }
280
+ async function retryOnBusy(fn, label) {
281
+ let lastError;
282
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
283
+ try {
284
+ return await fn();
285
+ } catch (err) {
286
+ lastError = err;
287
+ if (!isBusyError(err) || attempt === MAX_RETRIES) {
288
+ throw err;
289
+ }
290
+ const backoff = BASE_DELAY_MS * Math.pow(2, attempt);
291
+ const jitter = Math.floor(Math.random() * MAX_JITTER_MS);
292
+ process.stderr.write(
293
+ `[exe-os] SQLITE_BUSY ${label} retry ${attempt + 1}/${MAX_RETRIES} \u2014 waiting ${backoff + jitter}ms
294
+ `
295
+ );
296
+ await delay(backoff + jitter);
297
+ }
298
+ }
299
+ throw lastError;
300
+ }
301
+ function wrapWithRetry(client) {
302
+ return new Proxy(client, {
303
+ get(target, prop, receiver) {
304
+ if (prop === "execute") {
305
+ return (sql) => retryOnBusy(() => target.execute(sql), "execute");
306
+ }
307
+ if (prop === "batch") {
308
+ return (stmts) => retryOnBusy(() => target.batch(stmts), "batch");
309
+ }
310
+ return Reflect.get(target, prop, receiver);
311
+ }
312
+ });
313
+ }
314
+ var MAX_RETRIES, BASE_DELAY_MS, MAX_JITTER_MS;
315
+ var init_db_retry = __esm({
316
+ "src/lib/db-retry.ts"() {
317
+ "use strict";
318
+ MAX_RETRIES = 3;
319
+ BASE_DELAY_MS = 200;
320
+ MAX_JITTER_MS = 300;
321
+ }
322
+ });
323
+
269
324
  // src/lib/database.ts
270
325
  import { createClient } from "@libsql/client";
271
326
  async function initDatabase(config) {
272
327
  if (_client) {
273
328
  _client.close();
274
329
  _client = null;
330
+ _resilientClient = null;
275
331
  }
276
332
  const opts = {
277
333
  url: `file:${config.dbPath}`
@@ -280,17 +336,24 @@ async function initDatabase(config) {
280
336
  opts.encryptionKey = config.encryptionKey;
281
337
  }
282
338
  _client = createClient(opts);
339
+ _resilientClient = wrapWithRetry(_client);
283
340
  }
284
341
  function getClient() {
342
+ if (!_resilientClient) {
343
+ throw new Error("Database client not initialized. Call initDatabase() first.");
344
+ }
345
+ return _resilientClient;
346
+ }
347
+ function getRawClient() {
285
348
  if (!_client) {
286
349
  throw new Error("Database client not initialized. Call initDatabase() first.");
287
350
  }
288
351
  return _client;
289
352
  }
290
353
  async function ensureSchema() {
291
- const client = getClient();
354
+ const client = getRawClient();
292
355
  await client.execute("PRAGMA journal_mode = WAL");
293
- await client.execute("PRAGMA busy_timeout = 5000");
356
+ await client.execute("PRAGMA busy_timeout = 30000");
294
357
  try {
295
358
  await client.execute("PRAGMA libsql_vector_search_ef = 128");
296
359
  } catch {
@@ -1083,13 +1146,16 @@ async function disposeDatabase() {
1083
1146
  if (_client) {
1084
1147
  _client.close();
1085
1148
  _client = null;
1149
+ _resilientClient = null;
1086
1150
  }
1087
1151
  }
1088
- var _client, initTurso, disposeTurso;
1152
+ var _client, _resilientClient, initTurso, disposeTurso;
1089
1153
  var init_database = __esm({
1090
1154
  "src/lib/database.ts"() {
1091
1155
  "use strict";
1156
+ init_db_retry();
1092
1157
  _client = null;
1158
+ _resilientClient = null;
1093
1159
  initTurso = initDatabase;
1094
1160
  disposeTurso = disposeDatabase;
1095
1161
  }
@@ -1202,7 +1268,7 @@ function listShards() {
1202
1268
  }
1203
1269
  async function ensureShardSchema(client) {
1204
1270
  await client.execute("PRAGMA journal_mode = WAL");
1205
- await client.execute("PRAGMA busy_timeout = 5000");
1271
+ await client.execute("PRAGMA busy_timeout = 30000");
1206
1272
  try {
1207
1273
  await client.execute("PRAGMA libsql_vector_search_ef = 128");
1208
1274
  } catch {
@@ -2087,11 +2153,11 @@ async function connectEmbedDaemon() {
2087
2153
  }
2088
2154
  }
2089
2155
  const start = Date.now();
2090
- let delay = 100;
2156
+ let delay2 = 100;
2091
2157
  while (Date.now() - start < CONNECT_TIMEOUT_MS) {
2092
- await new Promise((r) => setTimeout(r, delay));
2158
+ await new Promise((r) => setTimeout(r, delay2));
2093
2159
  if (await connectToSocket()) return true;
2094
- delay = Math.min(delay * 2, 3e3);
2160
+ delay2 = Math.min(delay2 * 2, 3e3);
2095
2161
  }
2096
2162
  return false;
2097
2163
  }
@@ -2183,11 +2249,11 @@ async function embedViaClient(text, priority = "high") {
2183
2249
  `);
2184
2250
  killAndRespawnDaemon();
2185
2251
  const start = Date.now();
2186
- let delay = 200;
2252
+ let delay2 = 200;
2187
2253
  while (Date.now() - start < CONNECT_TIMEOUT_MS) {
2188
- await new Promise((r) => setTimeout(r, delay));
2254
+ await new Promise((r) => setTimeout(r, delay2));
2189
2255
  if (await connectToSocket()) break;
2190
- delay = Math.min(delay * 2, 3e3);
2256
+ delay2 = Math.min(delay2 * 2, 3e3);
2191
2257
  }
2192
2258
  if (!_connected) return null;
2193
2259
  }
@@ -2199,11 +2265,11 @@ async function embedViaClient(text, priority = "high") {
2199
2265
  `);
2200
2266
  killAndRespawnDaemon();
2201
2267
  const start = Date.now();
2202
- let delay = 200;
2268
+ let delay2 = 200;
2203
2269
  while (Date.now() - start < CONNECT_TIMEOUT_MS) {
2204
- await new Promise((r) => setTimeout(r, delay));
2270
+ await new Promise((r) => setTimeout(r, delay2));
2205
2271
  if (await connectToSocket()) break;
2206
- delay = Math.min(delay * 2, 3e3);
2272
+ delay2 = Math.min(delay2 * 2, 3e3);
2207
2273
  }
2208
2274
  if (!_connected) return null;
2209
2275
  const retry = await sendRequest([text], priority);
@@ -109,6 +109,61 @@ var init_memory = __esm({
109
109
  }
110
110
  });
111
111
 
112
+ // src/lib/db-retry.ts
113
+ function isBusyError(err) {
114
+ if (err instanceof Error) {
115
+ const msg = err.message.toLowerCase();
116
+ return msg.includes("sqlite_busy") || msg.includes("database is locked");
117
+ }
118
+ return false;
119
+ }
120
+ function delay(ms) {
121
+ return new Promise((resolve) => setTimeout(resolve, ms));
122
+ }
123
+ async function retryOnBusy(fn, label) {
124
+ let lastError;
125
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
126
+ try {
127
+ return await fn();
128
+ } catch (err) {
129
+ lastError = err;
130
+ if (!isBusyError(err) || attempt === MAX_RETRIES) {
131
+ throw err;
132
+ }
133
+ const backoff = BASE_DELAY_MS * Math.pow(2, attempt);
134
+ const jitter = Math.floor(Math.random() * MAX_JITTER_MS);
135
+ process.stderr.write(
136
+ `[exe-os] SQLITE_BUSY ${label} retry ${attempt + 1}/${MAX_RETRIES} \u2014 waiting ${backoff + jitter}ms
137
+ `
138
+ );
139
+ await delay(backoff + jitter);
140
+ }
141
+ }
142
+ throw lastError;
143
+ }
144
+ function wrapWithRetry(client) {
145
+ return new Proxy(client, {
146
+ get(target, prop, receiver) {
147
+ if (prop === "execute") {
148
+ return (sql) => retryOnBusy(() => target.execute(sql), "execute");
149
+ }
150
+ if (prop === "batch") {
151
+ return (stmts) => retryOnBusy(() => target.batch(stmts), "batch");
152
+ }
153
+ return Reflect.get(target, prop, receiver);
154
+ }
155
+ });
156
+ }
157
+ var MAX_RETRIES, BASE_DELAY_MS, MAX_JITTER_MS;
158
+ var init_db_retry = __esm({
159
+ "src/lib/db-retry.ts"() {
160
+ "use strict";
161
+ MAX_RETRIES = 3;
162
+ BASE_DELAY_MS = 200;
163
+ MAX_JITTER_MS = 300;
164
+ }
165
+ });
166
+
112
167
  // src/lib/database.ts
113
168
  var database_exports = {};
114
169
  __export(database_exports, {
@@ -116,6 +171,7 @@ __export(database_exports, {
116
171
  disposeTurso: () => disposeTurso,
117
172
  ensureSchema: () => ensureSchema,
118
173
  getClient: () => getClient,
174
+ getRawClient: () => getRawClient,
119
175
  initDatabase: () => initDatabase,
120
176
  initTurso: () => initTurso,
121
177
  isInitialized: () => isInitialized
@@ -125,6 +181,7 @@ async function initDatabase(config) {
125
181
  if (_client) {
126
182
  _client.close();
127
183
  _client = null;
184
+ _resilientClient = null;
128
185
  }
129
186
  const opts = {
130
187
  url: `file:${config.dbPath}`
@@ -133,20 +190,27 @@ async function initDatabase(config) {
133
190
  opts.encryptionKey = config.encryptionKey;
134
191
  }
135
192
  _client = createClient(opts);
193
+ _resilientClient = wrapWithRetry(_client);
136
194
  }
137
195
  function isInitialized() {
138
196
  return _client !== null;
139
197
  }
140
198
  function getClient() {
199
+ if (!_resilientClient) {
200
+ throw new Error("Database client not initialized. Call initDatabase() first.");
201
+ }
202
+ return _resilientClient;
203
+ }
204
+ function getRawClient() {
141
205
  if (!_client) {
142
206
  throw new Error("Database client not initialized. Call initDatabase() first.");
143
207
  }
144
208
  return _client;
145
209
  }
146
210
  async function ensureSchema() {
147
- const client = getClient();
211
+ const client = getRawClient();
148
212
  await client.execute("PRAGMA journal_mode = WAL");
149
- await client.execute("PRAGMA busy_timeout = 5000");
213
+ await client.execute("PRAGMA busy_timeout = 30000");
150
214
  try {
151
215
  await client.execute("PRAGMA libsql_vector_search_ef = 128");
152
216
  } catch {
@@ -939,13 +1003,16 @@ async function disposeDatabase() {
939
1003
  if (_client) {
940
1004
  _client.close();
941
1005
  _client = null;
1006
+ _resilientClient = null;
942
1007
  }
943
1008
  }
944
- var _client, initTurso, disposeTurso;
1009
+ var _client, _resilientClient, initTurso, disposeTurso;
945
1010
  var init_database = __esm({
946
1011
  "src/lib/database.ts"() {
947
1012
  "use strict";
1013
+ init_db_retry();
948
1014
  _client = null;
1015
+ _resilientClient = null;
949
1016
  initTurso = initDatabase;
950
1017
  disposeTurso = disposeDatabase;
951
1018
  }
@@ -1252,7 +1319,7 @@ function listShards() {
1252
1319
  }
1253
1320
  async function ensureShardSchema(client) {
1254
1321
  await client.execute("PRAGMA journal_mode = WAL");
1255
- await client.execute("PRAGMA busy_timeout = 5000");
1322
+ await client.execute("PRAGMA busy_timeout = 30000");
1256
1323
  try {
1257
1324
  await client.execute("PRAGMA libsql_vector_search_ef = 128");
1258
1325
  } catch {
@@ -1490,20 +1557,38 @@ var init_notifications = __esm({
1490
1557
 
1491
1558
  // src/lib/employees.ts
1492
1559
  import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
1493
- import { existsSync as existsSync6, symlinkSync, readlinkSync } from "fs";
1560
+ import { existsSync as existsSync6, symlinkSync, readlinkSync, readFileSync as readFileSync4 } from "fs";
1494
1561
  import { execSync as execSync3 } from "child_process";
1495
1562
  import path7 from "path";
1496
- var EMPLOYEES_PATH;
1563
+ function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
1564
+ if (!existsSync6(employeesPath)) return [];
1565
+ try {
1566
+ return JSON.parse(readFileSync4(employeesPath, "utf-8"));
1567
+ } catch {
1568
+ return [];
1569
+ }
1570
+ }
1571
+ function getEmployee(employees, name) {
1572
+ return employees.find((e) => e.name.toLowerCase() === name.toLowerCase());
1573
+ }
1574
+ function isMultiInstance(agentName, employees) {
1575
+ const roster = employees ?? loadEmployeesSync();
1576
+ const emp = getEmployee(roster, agentName);
1577
+ if (!emp) return false;
1578
+ return MULTI_INSTANCE_ROLES.has(emp.role.toLowerCase());
1579
+ }
1580
+ var EMPLOYEES_PATH, MULTI_INSTANCE_ROLES;
1497
1581
  var init_employees = __esm({
1498
1582
  "src/lib/employees.ts"() {
1499
1583
  "use strict";
1500
1584
  init_config();
1501
1585
  EMPLOYEES_PATH = path7.join(EXE_AI_DIR, "exe-employees.json");
1586
+ MULTI_INSTANCE_ROLES = /* @__PURE__ */ new Set(["principal engineer", "content production specialist", "staff code reviewer"]);
1502
1587
  }
1503
1588
  });
1504
1589
 
1505
1590
  // src/lib/license.ts
1506
- import { readFileSync as readFileSync4, writeFileSync, existsSync as existsSync7, mkdirSync as mkdirSync2 } from "fs";
1591
+ import { readFileSync as readFileSync5, writeFileSync, existsSync as existsSync7, mkdirSync as mkdirSync2 } from "fs";
1507
1592
  import { randomUUID } from "crypto";
1508
1593
  import path8 from "path";
1509
1594
  import { jwtVerify, importSPKI } from "jose";
@@ -1511,14 +1596,14 @@ function loadDeviceId() {
1511
1596
  const deviceJsonPath = path8.join(EXE_AI_DIR, "device.json");
1512
1597
  try {
1513
1598
  if (existsSync7(deviceJsonPath)) {
1514
- const data = JSON.parse(readFileSync4(deviceJsonPath, "utf8"));
1599
+ const data = JSON.parse(readFileSync5(deviceJsonPath, "utf8"));
1515
1600
  if (data.deviceId) return data.deviceId;
1516
1601
  }
1517
1602
  } catch {
1518
1603
  }
1519
1604
  try {
1520
1605
  if (existsSync7(DEVICE_ID_PATH)) {
1521
- const id2 = readFileSync4(DEVICE_ID_PATH, "utf8").trim();
1606
+ const id2 = readFileSync5(DEVICE_ID_PATH, "utf8").trim();
1522
1607
  if (id2) return id2;
1523
1608
  }
1524
1609
  } catch {
@@ -1531,7 +1616,7 @@ function loadDeviceId() {
1531
1616
  function loadLicense() {
1532
1617
  try {
1533
1618
  if (!existsSync7(LICENSE_PATH)) return null;
1534
- return readFileSync4(LICENSE_PATH, "utf8").trim();
1619
+ return readFileSync5(LICENSE_PATH, "utf8").trim();
1535
1620
  } catch {
1536
1621
  return null;
1537
1622
  }
@@ -1561,7 +1646,7 @@ async function verifyLicenseJwt(token) {
1561
1646
  async function getCachedLicense() {
1562
1647
  try {
1563
1648
  if (!existsSync7(CACHE_PATH)) return null;
1564
- const raw = JSON.parse(readFileSync4(CACHE_PATH, "utf8"));
1649
+ const raw = JSON.parse(readFileSync5(CACHE_PATH, "utf8"));
1565
1650
  if (!raw.token || typeof raw.token !== "string") return null;
1566
1651
  return await verifyLicenseJwt(raw.token);
1567
1652
  } catch {
@@ -1657,12 +1742,12 @@ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
1657
1742
  });
1658
1743
 
1659
1744
  // src/lib/plan-limits.ts
1660
- import { readFileSync as readFileSync5, existsSync as existsSync8 } from "fs";
1745
+ import { readFileSync as readFileSync6, existsSync as existsSync8 } from "fs";
1661
1746
  import path9 from "path";
1662
1747
  function getLicenseSync() {
1663
1748
  try {
1664
1749
  if (!existsSync8(CACHE_PATH2)) return freeLicense();
1665
- const raw = JSON.parse(readFileSync5(CACHE_PATH2, "utf8"));
1750
+ const raw = JSON.parse(readFileSync6(CACHE_PATH2, "utf8"));
1666
1751
  if (!raw.token || typeof raw.token !== "string") return freeLicense();
1667
1752
  const parts = raw.token.split(".");
1668
1753
  if (parts.length !== 3) return freeLicense();
@@ -1720,7 +1805,7 @@ function assertEmployeeLimitSync(rosterPath) {
1720
1805
  let count = 0;
1721
1806
  try {
1722
1807
  if (existsSync8(filePath)) {
1723
- const raw = readFileSync5(filePath, "utf8");
1808
+ const raw = readFileSync6(filePath, "utf8");
1724
1809
  const employees = JSON.parse(raw);
1725
1810
  count = Array.isArray(employees) ? employees.length : 0;
1726
1811
  }
@@ -1757,7 +1842,7 @@ var init_plan_limits = __esm({
1757
1842
  import net from "net";
1758
1843
  import { spawn } from "child_process";
1759
1844
  import { randomUUID as randomUUID2 } from "crypto";
1760
- import { existsSync as existsSync9, unlinkSync as unlinkSync2, readFileSync as readFileSync6, openSync, closeSync, statSync as statSync2 } from "fs";
1845
+ import { existsSync as existsSync9, unlinkSync as unlinkSync2, readFileSync as readFileSync7, openSync, closeSync, statSync as statSync2 } from "fs";
1761
1846
  import path10 from "path";
1762
1847
  import { fileURLToPath } from "url";
1763
1848
  function handleData(chunk) {
@@ -1782,7 +1867,7 @@ function handleData(chunk) {
1782
1867
  function cleanupStaleFiles() {
1783
1868
  if (existsSync9(PID_PATH)) {
1784
1869
  try {
1785
- const pid = parseInt(readFileSync6(PID_PATH, "utf8").trim(), 10);
1870
+ const pid = parseInt(readFileSync7(PID_PATH, "utf8").trim(), 10);
1786
1871
  if (pid > 0) {
1787
1872
  try {
1788
1873
  process.kill(pid, 0);
@@ -1930,11 +2015,11 @@ async function connectEmbedDaemon() {
1930
2015
  }
1931
2016
  }
1932
2017
  const start = Date.now();
1933
- let delay = 100;
2018
+ let delay2 = 100;
1934
2019
  while (Date.now() - start < CONNECT_TIMEOUT_MS) {
1935
- await new Promise((r) => setTimeout(r, delay));
2020
+ await new Promise((r) => setTimeout(r, delay2));
1936
2021
  if (await connectToSocket()) return true;
1937
- delay = Math.min(delay * 2, 3e3);
2022
+ delay2 = Math.min(delay2 * 2, 3e3);
1938
2023
  }
1939
2024
  return false;
1940
2025
  }
@@ -1990,7 +2075,7 @@ function killAndRespawnDaemon() {
1990
2075
  process.stderr.write("[exed-client] Killing daemon for restart...\n");
1991
2076
  if (existsSync9(PID_PATH)) {
1992
2077
  try {
1993
- const pid = parseInt(readFileSync6(PID_PATH, "utf8").trim(), 10);
2078
+ const pid = parseInt(readFileSync7(PID_PATH, "utf8").trim(), 10);
1994
2079
  if (pid > 0) {
1995
2080
  try {
1996
2081
  process.kill(pid, "SIGKILL");
@@ -2026,11 +2111,11 @@ async function embedViaClient(text, priority = "high") {
2026
2111
  `);
2027
2112
  killAndRespawnDaemon();
2028
2113
  const start = Date.now();
2029
- let delay = 200;
2114
+ let delay2 = 200;
2030
2115
  while (Date.now() - start < CONNECT_TIMEOUT_MS) {
2031
- await new Promise((r) => setTimeout(r, delay));
2116
+ await new Promise((r) => setTimeout(r, delay2));
2032
2117
  if (await connectToSocket()) break;
2033
- delay = Math.min(delay * 2, 3e3);
2118
+ delay2 = Math.min(delay2 * 2, 3e3);
2034
2119
  }
2035
2120
  if (!_connected) return null;
2036
2121
  }
@@ -2042,11 +2127,11 @@ async function embedViaClient(text, priority = "high") {
2042
2127
  `);
2043
2128
  killAndRespawnDaemon();
2044
2129
  const start = Date.now();
2045
- let delay = 200;
2130
+ let delay2 = 200;
2046
2131
  while (Date.now() - start < CONNECT_TIMEOUT_MS) {
2047
- await new Promise((r) => setTimeout(r, delay));
2132
+ await new Promise((r) => setTimeout(r, delay2));
2048
2133
  if (await connectToSocket()) break;
2049
- delay = Math.min(delay * 2, 3e3);
2134
+ delay2 = Math.min(delay2 * 2, 3e3);
2050
2135
  }
2051
2136
  if (!_connected) return null;
2052
2137
  const retry = await sendRequest([text], priority);
@@ -2162,7 +2247,7 @@ import crypto4 from "crypto";
2162
2247
  import path11 from "path";
2163
2248
  import { execSync as execSync4 } from "child_process";
2164
2249
  import { mkdir as mkdir4, writeFile as writeFile4, appendFile } from "fs/promises";
2165
- import { existsSync as existsSync10, readFileSync as readFileSync7 } from "fs";
2250
+ import { existsSync as existsSync10, readFileSync as readFileSync8 } from "fs";
2166
2251
  async function writeCheckpoint(input2) {
2167
2252
  const client = getClient();
2168
2253
  const row = await resolveTask(client, input2.taskId);
@@ -2539,7 +2624,7 @@ async function ensureGitignoreExe(baseDir) {
2539
2624
  const gitignorePath = path11.join(baseDir, ".gitignore");
2540
2625
  try {
2541
2626
  if (existsSync10(gitignorePath)) {
2542
- const content = readFileSync7(gitignorePath, "utf-8");
2627
+ const content = readFileSync8(gitignorePath, "utf-8");
2543
2628
  if (/^\/?exe\/?$/m.test(content)) return;
2544
2629
  await appendFile(gitignorePath, "\n# Employee task assignments (private)\n/exe/\n");
2545
2630
  } else {
@@ -2559,7 +2644,7 @@ var init_tasks_crud = __esm({
2559
2644
  });
2560
2645
 
2561
2646
  // src/lib/session-registry.ts
2562
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3, existsSync as existsSync11 } from "fs";
2647
+ import { readFileSync as readFileSync9, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3, existsSync as existsSync11 } from "fs";
2563
2648
  import path12 from "path";
2564
2649
  import os3 from "os";
2565
2650
  function registerSession(entry) {
@@ -2578,7 +2663,7 @@ function registerSession(entry) {
2578
2663
  }
2579
2664
  function listSessions() {
2580
2665
  try {
2581
- const raw = readFileSync8(REGISTRY_PATH, "utf8");
2666
+ const raw = readFileSync9(REGISTRY_PATH, "utf8");
2582
2667
  return JSON.parse(raw);
2583
2668
  } catch {
2584
2669
  return [];
@@ -2785,7 +2870,7 @@ var init_provider_table = __esm({
2785
2870
  });
2786
2871
 
2787
2872
  // src/lib/intercom-queue.ts
2788
- import { readFileSync as readFileSync9, writeFileSync as writeFileSync3, renameSync as renameSync2, existsSync as existsSync12, mkdirSync as mkdirSync4 } from "fs";
2873
+ import { readFileSync as readFileSync10, writeFileSync as writeFileSync3, renameSync as renameSync2, existsSync as existsSync12, mkdirSync as mkdirSync4 } from "fs";
2789
2874
  import path13 from "path";
2790
2875
  import os4 from "os";
2791
2876
  function ensureDir() {
@@ -2795,7 +2880,7 @@ function ensureDir() {
2795
2880
  function readQueue() {
2796
2881
  try {
2797
2882
  if (!existsSync12(QUEUE_PATH)) return [];
2798
- return JSON.parse(readFileSync9(QUEUE_PATH, "utf8"));
2883
+ return JSON.parse(readFileSync10(QUEUE_PATH, "utf8"));
2799
2884
  } catch {
2800
2885
  return [];
2801
2886
  }
@@ -2835,7 +2920,7 @@ var init_intercom_queue = __esm({
2835
2920
 
2836
2921
  // src/lib/tmux-routing.ts
2837
2922
  import { execFileSync as execFileSync2, execSync as execSync7 } from "child_process";
2838
- import { readFileSync as readFileSync10, writeFileSync as writeFileSync4, mkdirSync as mkdirSync5, existsSync as existsSync13, appendFileSync } from "fs";
2923
+ import { readFileSync as readFileSync11, writeFileSync as writeFileSync4, mkdirSync as mkdirSync5, existsSync as existsSync13, appendFileSync } from "fs";
2839
2924
  import path14 from "path";
2840
2925
  import os5 from "os";
2841
2926
  import { fileURLToPath as fileURLToPath2 } from "url";
@@ -2884,7 +2969,7 @@ function extractRootExe(name) {
2884
2969
  }
2885
2970
  function getParentExe(sessionKey) {
2886
2971
  try {
2887
- const data = JSON.parse(readFileSync10(path14.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
2972
+ const data = JSON.parse(readFileSync11(path14.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
2888
2973
  return data.parentExe || null;
2889
2974
  } catch {
2890
2975
  return null;
@@ -2892,7 +2977,7 @@ function getParentExe(sessionKey) {
2892
2977
  }
2893
2978
  function getDispatchedBy(sessionKey) {
2894
2979
  try {
2895
- const data = JSON.parse(readFileSync10(
2980
+ const data = JSON.parse(readFileSync11(
2896
2981
  path14.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
2897
2982
  "utf8"
2898
2983
  ));
@@ -2929,7 +3014,7 @@ function findFreeInstance(employeeName, exeSession, maxInstances = 10, isAlive =
2929
3014
  function readDebounceState() {
2930
3015
  try {
2931
3016
  if (!existsSync13(DEBOUNCE_FILE)) return {};
2932
- return JSON.parse(readFileSync10(DEBOUNCE_FILE, "utf8"));
3017
+ return JSON.parse(readFileSync11(DEBOUNCE_FILE, "utf8"));
2933
3018
  } catch {
2934
3019
  return {};
2935
3020
  }
@@ -3125,7 +3210,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
3125
3210
  const claudeJsonPath = path14.join(os5.homedir(), ".claude.json");
3126
3211
  let claudeJson = {};
3127
3212
  try {
3128
- claudeJson = JSON.parse(readFileSync10(claudeJsonPath, "utf8"));
3213
+ claudeJson = JSON.parse(readFileSync11(claudeJsonPath, "utf8"));
3129
3214
  } catch {
3130
3215
  }
3131
3216
  if (!claudeJson.projects) claudeJson.projects = {};
@@ -3143,7 +3228,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
3143
3228
  const settingsPath = path14.join(projSettingsDir, "settings.json");
3144
3229
  let settings = {};
3145
3230
  try {
3146
- settings = JSON.parse(readFileSync10(settingsPath, "utf8"));
3231
+ settings = JSON.parse(readFileSync11(settingsPath, "utf8"));
3147
3232
  } catch {
3148
3233
  }
3149
3234
  const perms = settings.permissions ?? {};
@@ -3648,7 +3733,7 @@ async function dispatchTaskToEmployee(input2) {
3648
3733
  } else {
3649
3734
  const projectDir = input2.projectDir ?? process.cwd();
3650
3735
  const result = ensureEmployee(input2.assignedTo, exeSession, projectDir, {
3651
- autoInstance: input2.assignedTo === "tom" || input2.assignedTo === "sasha"
3736
+ autoInstance: isMultiInstance(input2.assignedTo)
3652
3737
  });
3653
3738
  if (result.status === "failed") {
3654
3739
  process.stderr.write(
@@ -3683,6 +3768,7 @@ var init_tasks_notify = __esm({
3683
3768
  init_session_key();
3684
3769
  init_notifications();
3685
3770
  init_transport();
3771
+ init_employees();
3686
3772
  }
3687
3773
  });
3688
3774
 
@@ -4571,8 +4657,8 @@ function findContainingChunk(filePath, snippet) {
4571
4657
  try {
4572
4658
  const ext = filePath.split(".").pop()?.toLowerCase();
4573
4659
  if (ext !== "ts" && ext !== "tsx" && ext !== "js" && ext !== "jsx") return "";
4574
- const { readFileSync: readFileSync11 } = __require("fs");
4575
- const source = readFileSync11(filePath, "utf8");
4660
+ const { readFileSync: readFileSync12 } = __require("fs");
4661
+ const source = readFileSync12(filePath, "utf8");
4576
4662
  const lines = source.split("\n");
4577
4663
  const lowerSnippet = snippet.toLowerCase().slice(0, 80);
4578
4664
  let matchLine = -1;
@@ -4853,8 +4939,8 @@ process.stdin.on("end", async () => {
4853
4939
  fileContent = data.tool_input?.content ?? "";
4854
4940
  } else {
4855
4941
  try {
4856
- const { readFileSync: readFileSync11 } = await import("fs");
4857
- fileContent = readFileSync11(filePath, "utf8");
4942
+ const { readFileSync: readFileSync12 } = await import("fs");
4943
+ fileContent = readFileSync12(filePath, "utf8");
4858
4944
  } catch (err) {
4859
4945
  process.stderr.write(`[ingest-worker] file read failed (${filePath}): ${err instanceof Error ? err.message : String(err)}
4860
4946
  `);