@askexenow/exe-os 0.9.8 → 0.9.9

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 (101) hide show
  1. package/dist/bin/backfill-conversations.js +222 -49
  2. package/dist/bin/backfill-responses.js +221 -48
  3. package/dist/bin/backfill-vectors.js +225 -52
  4. package/dist/bin/cleanup-stale-review-tasks.js +150 -28
  5. package/dist/bin/cli.js +1295 -856
  6. package/dist/bin/exe-agent-config.js +36 -8
  7. package/dist/bin/exe-agent.js +14 -4
  8. package/dist/bin/exe-assign.js +221 -48
  9. package/dist/bin/exe-boot.js +778 -427
  10. package/dist/bin/exe-call.js +41 -13
  11. package/dist/bin/exe-cloud.js +163 -58
  12. package/dist/bin/exe-dispatch.js +276 -139
  13. package/dist/bin/exe-doctor.js +145 -27
  14. package/dist/bin/exe-export-behaviors.js +141 -23
  15. package/dist/bin/exe-forget.js +137 -19
  16. package/dist/bin/exe-gateway.js +677 -388
  17. package/dist/bin/exe-heartbeat.js +227 -108
  18. package/dist/bin/exe-kill.js +138 -20
  19. package/dist/bin/exe-launch-agent.js +172 -39
  20. package/dist/bin/exe-link.js +291 -100
  21. package/dist/bin/exe-new-employee.js +214 -106
  22. package/dist/bin/exe-pending-messages.js +395 -33
  23. package/dist/bin/exe-pending-notifications.js +684 -99
  24. package/dist/bin/exe-pending-reviews.js +420 -74
  25. package/dist/bin/exe-rename.js +147 -49
  26. package/dist/bin/exe-review.js +138 -20
  27. package/dist/bin/exe-search.js +240 -69
  28. package/dist/bin/exe-session-cleanup.js +440 -250
  29. package/dist/bin/exe-settings.js +61 -17
  30. package/dist/bin/exe-start-codex.js +158 -39
  31. package/dist/bin/exe-start-opencode.js +157 -38
  32. package/dist/bin/exe-status.js +151 -29
  33. package/dist/bin/exe-team.js +138 -20
  34. package/dist/bin/git-sweep.js +404 -212
  35. package/dist/bin/graph-backfill.js +137 -19
  36. package/dist/bin/graph-export.js +140 -22
  37. package/dist/bin/install.js +90 -61
  38. package/dist/bin/scan-tasks.js +412 -220
  39. package/dist/bin/setup.js +564 -293
  40. package/dist/bin/shard-migrate.js +139 -21
  41. package/dist/bin/update.js +138 -49
  42. package/dist/bin/wiki-sync.js +137 -19
  43. package/dist/gateway/index.js +533 -320
  44. package/dist/hooks/bug-report-worker.js +344 -193
  45. package/dist/hooks/codex-stop-task-finalizer.js +4678 -0
  46. package/dist/hooks/commit-complete.js +402 -210
  47. package/dist/hooks/error-recall.js +245 -74
  48. package/dist/hooks/exe-heartbeat-hook.js +16 -6
  49. package/dist/hooks/ingest-worker.js +3423 -3157
  50. package/dist/hooks/ingest.js +832 -97
  51. package/dist/hooks/instructions-loaded.js +227 -54
  52. package/dist/hooks/notification.js +216 -43
  53. package/dist/hooks/post-compact.js +239 -62
  54. package/dist/hooks/pre-compact.js +408 -216
  55. package/dist/hooks/pre-tool-use.js +268 -90
  56. package/dist/hooks/prompt-ingest-worker.js +352 -102
  57. package/dist/hooks/prompt-submit.js +541 -328
  58. package/dist/hooks/response-ingest-worker.js +372 -122
  59. package/dist/hooks/session-end.js +443 -240
  60. package/dist/hooks/session-start.js +313 -127
  61. package/dist/hooks/stop.js +293 -98
  62. package/dist/hooks/subagent-stop.js +239 -62
  63. package/dist/hooks/summary-worker.js +568 -236
  64. package/dist/index.js +538 -324
  65. package/dist/lib/agent-config.js +28 -6
  66. package/dist/lib/cloud-sync.js +284 -105
  67. package/dist/lib/config.js +30 -10
  68. package/dist/lib/consolidation.js +16 -6
  69. package/dist/lib/database.js +123 -25
  70. package/dist/lib/db-daemon-client.js +73 -19
  71. package/dist/lib/db.js +123 -25
  72. package/dist/lib/device-registry.js +133 -35
  73. package/dist/lib/embedder.js +107 -32
  74. package/dist/lib/employee-templates.js +14 -4
  75. package/dist/lib/employees.js +41 -13
  76. package/dist/lib/exe-daemon-client.js +88 -22
  77. package/dist/lib/exe-daemon.js +935 -587
  78. package/dist/lib/hybrid-search.js +240 -69
  79. package/dist/lib/identity.js +18 -8
  80. package/dist/lib/license.js +133 -48
  81. package/dist/lib/messaging.js +116 -56
  82. package/dist/lib/reminders.js +14 -4
  83. package/dist/lib/schedules.js +137 -19
  84. package/dist/lib/skill-learning.js +33 -6
  85. package/dist/lib/store.js +137 -19
  86. package/dist/lib/task-router.js +14 -4
  87. package/dist/lib/tasks.js +280 -234
  88. package/dist/lib/tmux-routing.js +172 -125
  89. package/dist/lib/token-spend.js +26 -8
  90. package/dist/mcp/server.js +1326 -609
  91. package/dist/mcp/tools/complete-reminder.js +14 -4
  92. package/dist/mcp/tools/create-reminder.js +14 -4
  93. package/dist/mcp/tools/create-task.js +306 -248
  94. package/dist/mcp/tools/deactivate-behavior.js +16 -6
  95. package/dist/mcp/tools/list-reminders.js +14 -4
  96. package/dist/mcp/tools/list-tasks.js +123 -107
  97. package/dist/mcp/tools/send-message.js +75 -29
  98. package/dist/mcp/tools/update-task.js +1848 -199
  99. package/dist/runtime/index.js +441 -248
  100. package/dist/tui/App.js +761 -424
  101. package/package.json +1 -1
@@ -9,9 +9,34 @@ var __export = (target, all) => {
9
9
  __defProp(target, name, { get: all[name], enumerable: true });
10
10
  };
11
11
 
12
+ // src/lib/secure-files.ts
13
+ import { chmodSync, existsSync, mkdirSync } from "fs";
14
+ import { chmod, mkdir } from "fs/promises";
15
+ function ensurePrivateDirSync(dirPath) {
16
+ mkdirSync(dirPath, { recursive: true, mode: PRIVATE_DIR_MODE });
17
+ try {
18
+ chmodSync(dirPath, PRIVATE_DIR_MODE);
19
+ } catch {
20
+ }
21
+ }
22
+ function enforcePrivateFileSync(filePath) {
23
+ try {
24
+ if (existsSync(filePath)) chmodSync(filePath, PRIVATE_FILE_MODE);
25
+ } catch {
26
+ }
27
+ }
28
+ var PRIVATE_DIR_MODE, PRIVATE_FILE_MODE;
29
+ var init_secure_files = __esm({
30
+ "src/lib/secure-files.ts"() {
31
+ "use strict";
32
+ PRIVATE_DIR_MODE = 448;
33
+ PRIVATE_FILE_MODE = 384;
34
+ }
35
+ });
36
+
12
37
  // src/lib/config.ts
13
- import { readFile, writeFile, mkdir, chmod } from "fs/promises";
14
- import { readFileSync, existsSync, renameSync } from "fs";
38
+ import { readFile, writeFile } from "fs/promises";
39
+ import { readFileSync, existsSync as existsSync2, renameSync } from "fs";
15
40
  import path from "path";
16
41
  import os from "os";
17
42
  function resolveDataDir() {
@@ -19,7 +44,7 @@ function resolveDataDir() {
19
44
  if (process.env.EXE_MEM_DIR) return process.env.EXE_MEM_DIR;
20
45
  const newDir = path.join(os.homedir(), ".exe-os");
21
46
  const legacyDir = path.join(os.homedir(), ".exe-mem");
22
- if (!existsSync(newDir) && existsSync(legacyDir)) {
47
+ if (!existsSync2(newDir) && existsSync2(legacyDir)) {
23
48
  try {
24
49
  renameSync(legacyDir, newDir);
25
50
  process.stderr.write(`[exe-os] Migrated data directory: ~/.exe-mem \u2192 ~/.exe-os
@@ -34,6 +59,7 @@ var EXE_AI_DIR, DB_PATH, MODELS_DIR, CONFIG_PATH, LEGACY_LANCE_PATH, CURRENT_CON
34
59
  var init_config = __esm({
35
60
  "src/lib/config.ts"() {
36
61
  "use strict";
62
+ init_secure_files();
37
63
  EXE_AI_DIR = resolveDataDir();
38
64
  DB_PATH = path.join(EXE_AI_DIR, "memories.db");
39
65
  MODELS_DIR = path.join(EXE_AI_DIR, "models");
@@ -102,7 +128,7 @@ var init_config = __esm({
102
128
 
103
129
  // src/lib/employees.ts
104
130
  import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
105
- import { existsSync as existsSync2, symlinkSync, readlinkSync, readFileSync as readFileSync2, renameSync as renameSync2, unlinkSync, writeFileSync } from "fs";
131
+ import { existsSync as existsSync3, symlinkSync, readlinkSync, readFileSync as readFileSync2, renameSync as renameSync2, unlinkSync, writeFileSync } from "fs";
106
132
  import { execSync } from "child_process";
107
133
  import path2 from "path";
108
134
  import os2 from "os";
@@ -134,7 +160,7 @@ function validateEmployeeName(name) {
134
160
  return { valid: true };
135
161
  }
136
162
  async function loadEmployees(employeesPath = EMPLOYEES_PATH) {
137
- if (!existsSync2(employeesPath)) {
163
+ if (!existsSync3(employeesPath)) {
138
164
  return [];
139
165
  }
140
166
  const raw = await readFile2(employeesPath, "utf-8");
@@ -149,7 +175,7 @@ async function saveEmployees(employees, employeesPath = EMPLOYEES_PATH) {
149
175
  await writeFile2(employeesPath, JSON.stringify(employees, null, 2) + "\n", "utf-8");
150
176
  }
151
177
  function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
152
- if (!existsSync2(employeesPath)) return [];
178
+ if (!existsSync3(employeesPath)) return [];
153
179
  try {
154
180
  return JSON.parse(readFileSync2(employeesPath, "utf-8"));
155
181
  } catch {
@@ -183,7 +209,7 @@ function registerBinSymlinks(name) {
183
209
  for (const suffix of ["", "-opencode"]) {
184
210
  const linkName = `${name}${suffix}`;
185
211
  const linkPath = path2.join(binDir, linkName);
186
- if (existsSync2(linkPath)) {
212
+ if (existsSync3(linkPath)) {
187
213
  skipped.push(linkName);
188
214
  continue;
189
215
  }
@@ -847,13 +873,50 @@ var init_database_adapter = __esm({
847
873
  }
848
874
  });
849
875
 
876
+ // src/lib/daemon-auth.ts
877
+ import crypto from "crypto";
878
+ import path4 from "path";
879
+ import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
880
+ function normalizeToken(token) {
881
+ if (!token) return null;
882
+ const trimmed = token.trim();
883
+ return trimmed.length > 0 ? trimmed : null;
884
+ }
885
+ function readDaemonToken() {
886
+ try {
887
+ if (!existsSync4(DAEMON_TOKEN_PATH)) return null;
888
+ return normalizeToken(readFileSync3(DAEMON_TOKEN_PATH, "utf8"));
889
+ } catch {
890
+ return null;
891
+ }
892
+ }
893
+ function ensureDaemonToken(seed) {
894
+ const existing = readDaemonToken();
895
+ if (existing) return existing;
896
+ const token = normalizeToken(seed) ?? crypto.randomBytes(32).toString("hex");
897
+ ensurePrivateDirSync(EXE_AI_DIR);
898
+ writeFileSync2(DAEMON_TOKEN_PATH, `${token}
899
+ `, "utf8");
900
+ enforcePrivateFileSync(DAEMON_TOKEN_PATH);
901
+ return token;
902
+ }
903
+ var DAEMON_TOKEN_PATH;
904
+ var init_daemon_auth = __esm({
905
+ "src/lib/daemon-auth.ts"() {
906
+ "use strict";
907
+ init_config();
908
+ init_secure_files();
909
+ DAEMON_TOKEN_PATH = path4.join(EXE_AI_DIR, "exed.token");
910
+ }
911
+ });
912
+
850
913
  // src/lib/exe-daemon-client.ts
851
914
  import net from "net";
852
915
  import os4 from "os";
853
916
  import { spawn } from "child_process";
854
917
  import { randomUUID } from "crypto";
855
- import { existsSync as existsSync3, unlinkSync as unlinkSync2, readFileSync as readFileSync3, openSync, closeSync, statSync } from "fs";
856
- import path4 from "path";
918
+ import { existsSync as existsSync5, unlinkSync as unlinkSync2, readFileSync as readFileSync4, openSync, closeSync, statSync } from "fs";
919
+ import path5 from "path";
857
920
  import { fileURLToPath } from "url";
858
921
  function handleData(chunk) {
859
922
  _buffer += chunk.toString();
@@ -881,9 +944,9 @@ function handleData(chunk) {
881
944
  }
882
945
  }
883
946
  function cleanupStaleFiles() {
884
- if (existsSync3(PID_PATH)) {
947
+ if (existsSync5(PID_PATH)) {
885
948
  try {
886
- const pid = parseInt(readFileSync3(PID_PATH, "utf8").trim(), 10);
949
+ const pid = parseInt(readFileSync4(PID_PATH, "utf8").trim(), 10);
887
950
  if (pid > 0) {
888
951
  try {
889
952
  process.kill(pid, 0);
@@ -904,11 +967,11 @@ function cleanupStaleFiles() {
904
967
  }
905
968
  }
906
969
  function findPackageRoot() {
907
- let dir = path4.dirname(fileURLToPath(import.meta.url));
908
- const { root } = path4.parse(dir);
970
+ let dir = path5.dirname(fileURLToPath(import.meta.url));
971
+ const { root } = path5.parse(dir);
909
972
  while (dir !== root) {
910
- if (existsSync3(path4.join(dir, "package.json"))) return dir;
911
- dir = path4.dirname(dir);
973
+ if (existsSync5(path5.join(dir, "package.json"))) return dir;
974
+ dir = path5.dirname(dir);
912
975
  }
913
976
  return null;
914
977
  }
@@ -934,16 +997,17 @@ function spawnDaemon() {
934
997
  process.stderr.write("[exed-client] WARN: cannot find package root\n");
935
998
  return;
936
999
  }
937
- const daemonPath = path4.join(pkgRoot, "dist", "lib", "exe-daemon.js");
938
- if (!existsSync3(daemonPath)) {
1000
+ const daemonPath = path5.join(pkgRoot, "dist", "lib", "exe-daemon.js");
1001
+ if (!existsSync5(daemonPath)) {
939
1002
  process.stderr.write(`[exed-client] WARN: daemon script not found at ${daemonPath}
940
1003
  `);
941
1004
  return;
942
1005
  }
943
1006
  const resolvedPath = daemonPath;
1007
+ const daemonToken = ensureDaemonToken(process.env[DAEMON_TOKEN_ENV] ?? null);
944
1008
  process.stderr.write(`[exed-client] Spawning daemon: ${resolvedPath}
945
1009
  `);
946
- const logPath = path4.join(path4.dirname(SOCKET_PATH), "exed.log");
1010
+ const logPath = path5.join(path5.dirname(SOCKET_PATH), "exed.log");
947
1011
  let stderrFd = "ignore";
948
1012
  try {
949
1013
  stderrFd = openSync(logPath, "a");
@@ -961,7 +1025,8 @@ function spawnDaemon() {
961
1025
  TMUX_PANE: void 0,
962
1026
  // Prevents resolveExeSession() from scoping to one session
963
1027
  EXE_DAEMON_SOCK: SOCKET_PATH,
964
- EXE_DAEMON_PID: PID_PATH
1028
+ EXE_DAEMON_PID: PID_PATH,
1029
+ [DAEMON_TOKEN_ENV]: daemonToken
965
1030
  }
966
1031
  });
967
1032
  child.unref();
@@ -1068,13 +1133,14 @@ function sendDaemonRequest(payload, timeoutMs = REQUEST_TIMEOUT_MS) {
1068
1133
  return;
1069
1134
  }
1070
1135
  const id = randomUUID();
1136
+ const token = process.env[DAEMON_TOKEN_ENV] ?? readDaemonToken();
1071
1137
  const timer = setTimeout(() => {
1072
1138
  _pending.delete(id);
1073
1139
  resolve({ error: "Request timeout" });
1074
1140
  }, timeoutMs);
1075
1141
  _pending.set(id, { resolve, timer });
1076
1142
  try {
1077
- _socket.write(JSON.stringify({ id, ...payload }) + "\n");
1143
+ _socket.write(JSON.stringify({ id, token, ...payload }) + "\n");
1078
1144
  } catch {
1079
1145
  clearTimeout(timer);
1080
1146
  _pending.delete(id);
@@ -1085,17 +1151,19 @@ function sendDaemonRequest(payload, timeoutMs = REQUEST_TIMEOUT_MS) {
1085
1151
  function isClientConnected() {
1086
1152
  return _connected;
1087
1153
  }
1088
- var SOCKET_PATH, PID_PATH, SPAWN_LOCK_PATH, SPAWN_LOCK_STALE_MS, CONNECT_TIMEOUT_MS, REQUEST_TIMEOUT_MS, _socket, _connected, _buffer, _pending, MAX_BUFFER;
1154
+ var SOCKET_PATH, PID_PATH, SPAWN_LOCK_PATH, SPAWN_LOCK_STALE_MS, CONNECT_TIMEOUT_MS, REQUEST_TIMEOUT_MS, DAEMON_TOKEN_ENV, _socket, _connected, _buffer, _pending, MAX_BUFFER;
1089
1155
  var init_exe_daemon_client = __esm({
1090
1156
  "src/lib/exe-daemon-client.ts"() {
1091
1157
  "use strict";
1092
1158
  init_config();
1093
- SOCKET_PATH = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ?? path4.join(EXE_AI_DIR, "exed.sock");
1094
- PID_PATH = process.env.EXE_DAEMON_PID ?? process.env.EXE_EMBED_PID ?? path4.join(EXE_AI_DIR, "exed.pid");
1095
- SPAWN_LOCK_PATH = path4.join(EXE_AI_DIR, "exed-spawn.lock");
1159
+ init_daemon_auth();
1160
+ SOCKET_PATH = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ?? path5.join(EXE_AI_DIR, "exed.sock");
1161
+ PID_PATH = process.env.EXE_DAEMON_PID ?? process.env.EXE_EMBED_PID ?? path5.join(EXE_AI_DIR, "exed.pid");
1162
+ SPAWN_LOCK_PATH = path5.join(EXE_AI_DIR, "exed-spawn.lock");
1096
1163
  SPAWN_LOCK_STALE_MS = 3e4;
1097
1164
  CONNECT_TIMEOUT_MS = 15e3;
1098
1165
  REQUEST_TIMEOUT_MS = 3e4;
1166
+ DAEMON_TOKEN_ENV = "EXE_DAEMON_TOKEN";
1099
1167
  _socket = null;
1100
1168
  _connected = false;
1101
1169
  _buffer = "";
@@ -1674,6 +1742,7 @@ async function ensureSchema() {
1674
1742
  project TEXT NOT NULL,
1675
1743
  summary TEXT NOT NULL,
1676
1744
  task_file TEXT,
1745
+ session_scope TEXT,
1677
1746
  read INTEGER NOT NULL DEFAULT 0,
1678
1747
  created_at TEXT NOT NULL
1679
1748
  );
@@ -1682,7 +1751,7 @@ async function ensureSchema() {
1682
1751
  ON notifications(read);
1683
1752
 
1684
1753
  CREATE INDEX IF NOT EXISTS idx_notifications_agent
1685
- ON notifications(agent_id);
1754
+ ON notifications(agent_id, session_scope);
1686
1755
 
1687
1756
  CREATE INDEX IF NOT EXISTS idx_notifications_task_file
1688
1757
  ON notifications(task_file);
@@ -1720,6 +1789,7 @@ async function ensureSchema() {
1720
1789
  target_agent TEXT NOT NULL,
1721
1790
  target_project TEXT,
1722
1791
  target_device TEXT NOT NULL DEFAULT 'local',
1792
+ session_scope TEXT,
1723
1793
  content TEXT NOT NULL,
1724
1794
  priority TEXT DEFAULT 'normal',
1725
1795
  status TEXT DEFAULT 'pending',
@@ -1733,10 +1803,31 @@ async function ensureSchema() {
1733
1803
  );
1734
1804
 
1735
1805
  CREATE INDEX IF NOT EXISTS idx_messages_target
1736
- ON messages(target_agent, status);
1806
+ ON messages(target_agent, session_scope, status);
1737
1807
 
1738
1808
  CREATE INDEX IF NOT EXISTS idx_messages_conversation_order
1739
- ON messages(target_agent, from_agent, server_seq);
1809
+ ON messages(target_agent, session_scope, from_agent, server_seq);
1810
+ `);
1811
+ try {
1812
+ await client.execute({
1813
+ sql: `ALTER TABLE notifications ADD COLUMN session_scope TEXT`,
1814
+ args: []
1815
+ });
1816
+ } catch {
1817
+ }
1818
+ try {
1819
+ await client.execute({
1820
+ sql: `ALTER TABLE messages ADD COLUMN session_scope TEXT`,
1821
+ args: []
1822
+ });
1823
+ } catch {
1824
+ }
1825
+ await client.executeMultiple(`
1826
+ CREATE INDEX IF NOT EXISTS idx_notifications_agent_scope_read
1827
+ ON notifications(agent_id, session_scope, read, created_at);
1828
+
1829
+ CREATE INDEX IF NOT EXISTS idx_messages_target_scope_status
1830
+ ON messages(target_agent, session_scope, status, created_at);
1740
1831
  `);
1741
1832
  try {
1742
1833
  await client.execute({
@@ -2320,6 +2411,13 @@ async function ensureSchema() {
2320
2411
  } catch {
2321
2412
  }
2322
2413
  }
2414
+ try {
2415
+ await client.execute({
2416
+ sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
2417
+ args: []
2418
+ });
2419
+ } catch {
2420
+ }
2323
2421
  }
2324
2422
  async function disposeDatabase() {
2325
2423
  if (_walCheckpointTimer) {
@@ -2359,9 +2457,9 @@ var init_database = __esm({
2359
2457
 
2360
2458
  // src/bin/exe-rename.ts
2361
2459
  init_employees();
2362
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, renameSync as renameSync3, unlinkSync as unlinkSync3, existsSync as existsSync4 } from "fs";
2460
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, renameSync as renameSync3, unlinkSync as unlinkSync3, existsSync as existsSync6 } from "fs";
2363
2461
  import { execSync as execSync2 } from "child_process";
2364
- import path5 from "path";
2462
+ import path6 from "path";
2365
2463
  import { homedir } from "os";
2366
2464
 
2367
2465
  // src/lib/global-procedures.ts
@@ -2506,9 +2604,9 @@ function isMainModule(importMetaUrl) {
2506
2604
 
2507
2605
  // src/bin/exe-rename.ts
2508
2606
  async function renameEmployee(oldName, newName, opts = {}) {
2509
- const rosterPath = opts.rosterPath ?? path5.join(homedir(), ".exe-os", "exe-employees.json");
2510
- const identityDir = opts.identityDir ?? path5.join(homedir(), ".exe-os", "identity");
2511
- const agentsDir = opts.agentsDir ?? path5.join(homedir(), ".claude", "agents");
2607
+ const rosterPath = opts.rosterPath ?? path6.join(homedir(), ".exe-os", "exe-employees.json");
2608
+ const identityDir = opts.identityDir ?? path6.join(homedir(), ".exe-os", "identity");
2609
+ const agentsDir = opts.agentsDir ?? path6.join(homedir(), ".claude", "agents");
2512
2610
  const validation = validateEmployeeName(newName);
2513
2611
  if (!validation.valid) {
2514
2612
  return { success: false, error: validation.error };
@@ -2537,40 +2635,40 @@ async function renameEmployee(oldName, newName, opts = {}) {
2537
2635
  undo: () => {
2538
2636
  employee.name = originalName;
2539
2637
  employee.systemPrompt = originalPrompt;
2540
- writeFileSync2(rosterPath, JSON.stringify(employees, null, 2) + "\n", "utf-8");
2638
+ writeFileSync3(rosterPath, JSON.stringify(employees, null, 2) + "\n", "utf-8");
2541
2639
  }
2542
2640
  });
2543
- const oldIdentityPath = path5.join(identityDir, `${rosterOldName}.md`);
2544
- const newIdentityPath = path5.join(identityDir, `${newName}.md`);
2545
- if (existsSync4(oldIdentityPath)) {
2546
- const content = readFileSync4(oldIdentityPath, "utf-8");
2641
+ const oldIdentityPath = path6.join(identityDir, `${rosterOldName}.md`);
2642
+ const newIdentityPath = path6.join(identityDir, `${newName}.md`);
2643
+ if (existsSync6(oldIdentityPath)) {
2644
+ const content = readFileSync5(oldIdentityPath, "utf-8");
2547
2645
  const updatedContent = content.replace(
2548
2646
  /^(agent_id:\s*)\S+/m,
2549
2647
  `$1${newName}`
2550
2648
  );
2551
2649
  renameSync3(oldIdentityPath, newIdentityPath);
2552
- writeFileSync2(newIdentityPath, updatedContent, "utf-8");
2650
+ writeFileSync3(newIdentityPath, updatedContent, "utf-8");
2553
2651
  rollbackStack.push({
2554
2652
  description: "restore identity file",
2555
2653
  undo: () => {
2556
- if (existsSync4(newIdentityPath)) {
2557
- writeFileSync2(newIdentityPath, content, "utf-8");
2654
+ if (existsSync6(newIdentityPath)) {
2655
+ writeFileSync3(newIdentityPath, content, "utf-8");
2558
2656
  renameSync3(newIdentityPath, oldIdentityPath);
2559
2657
  }
2560
2658
  }
2561
2659
  });
2562
2660
  }
2563
- const oldAgentPath = path5.join(agentsDir, `${rosterOldName}.md`);
2564
- const newAgentPath = path5.join(agentsDir, `${newName}.md`);
2565
- if (existsSync4(oldAgentPath)) {
2566
- const agentContent = readFileSync4(oldAgentPath, "utf-8");
2661
+ const oldAgentPath = path6.join(agentsDir, `${rosterOldName}.md`);
2662
+ const newAgentPath = path6.join(agentsDir, `${newName}.md`);
2663
+ if (existsSync6(oldAgentPath)) {
2664
+ const agentContent = readFileSync5(oldAgentPath, "utf-8");
2567
2665
  renameSync3(oldAgentPath, newAgentPath);
2568
2666
  rollbackStack.push({
2569
2667
  description: "restore agent file",
2570
2668
  undo: () => {
2571
- if (existsSync4(newAgentPath)) {
2669
+ if (existsSync6(newAgentPath)) {
2572
2670
  renameSync3(newAgentPath, oldAgentPath);
2573
- writeFileSync2(oldAgentPath, agentContent, "utf-8");
2671
+ writeFileSync3(oldAgentPath, agentContent, "utf-8");
2574
2672
  }
2575
2673
  }
2576
2674
  });
@@ -2648,10 +2746,10 @@ function removeOldSymlinks(name) {
2648
2746
  try {
2649
2747
  const exeBinPath = findExeBin2();
2650
2748
  if (!exeBinPath) return;
2651
- const binDir = path5.dirname(exeBinPath);
2749
+ const binDir = path6.dirname(exeBinPath);
2652
2750
  for (const suffix of ["", "-opencode"]) {
2653
- const linkPath = path5.join(binDir, `${name}${suffix}`);
2654
- if (existsSync4(linkPath)) {
2751
+ const linkPath = path6.join(binDir, `${name}${suffix}`);
2752
+ if (existsSync6(linkPath)) {
2655
2753
  try {
2656
2754
  unlinkSync3(linkPath);
2657
2755
  } catch {