@askexenow/exe-os 0.9.7 → 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 +953 -105
  2. package/dist/bin/backfill-responses.js +952 -104
  3. package/dist/bin/backfill-vectors.js +956 -108
  4. package/dist/bin/cleanup-stale-review-tasks.js +802 -58
  5. package/dist/bin/cli.js +2292 -1070
  6. package/dist/bin/exe-agent-config.js +157 -101
  7. package/dist/bin/exe-agent.js +55 -29
  8. package/dist/bin/exe-assign.js +940 -92
  9. package/dist/bin/exe-boot.js +1424 -442
  10. package/dist/bin/exe-call.js +240 -141
  11. package/dist/bin/exe-cloud.js +198 -70
  12. package/dist/bin/exe-dispatch.js +951 -192
  13. package/dist/bin/exe-doctor.js +791 -51
  14. package/dist/bin/exe-export-behaviors.js +790 -42
  15. package/dist/bin/exe-forget.js +771 -31
  16. package/dist/bin/exe-gateway.js +1592 -521
  17. package/dist/bin/exe-heartbeat.js +850 -109
  18. package/dist/bin/exe-kill.js +783 -35
  19. package/dist/bin/exe-launch-agent.js +1030 -107
  20. package/dist/bin/exe-link.js +916 -110
  21. package/dist/bin/exe-new-employee.js +526 -217
  22. package/dist/bin/exe-pending-messages.js +1046 -62
  23. package/dist/bin/exe-pending-notifications.js +1318 -111
  24. package/dist/bin/exe-pending-reviews.js +1040 -72
  25. package/dist/bin/exe-rename.js +772 -59
  26. package/dist/bin/exe-review.js +772 -32
  27. package/dist/bin/exe-search.js +982 -128
  28. package/dist/bin/exe-session-cleanup.js +1180 -306
  29. package/dist/bin/exe-settings.js +185 -105
  30. package/dist/bin/exe-start-codex.js +886 -132
  31. package/dist/bin/exe-start-opencode.js +873 -119
  32. package/dist/bin/exe-status.js +803 -59
  33. package/dist/bin/exe-team.js +772 -32
  34. package/dist/bin/git-sweep.js +1046 -223
  35. package/dist/bin/graph-backfill.js +779 -31
  36. package/dist/bin/graph-export.js +785 -37
  37. package/dist/bin/install.js +632 -200
  38. package/dist/bin/scan-tasks.js +1055 -232
  39. package/dist/bin/setup.js +1419 -320
  40. package/dist/bin/shard-migrate.js +783 -35
  41. package/dist/bin/update.js +138 -49
  42. package/dist/bin/wiki-sync.js +782 -34
  43. package/dist/gateway/index.js +1444 -449
  44. package/dist/hooks/bug-report-worker.js +1141 -269
  45. package/dist/hooks/codex-stop-task-finalizer.js +4678 -0
  46. package/dist/hooks/commit-complete.js +1044 -221
  47. package/dist/hooks/error-recall.js +989 -135
  48. package/dist/hooks/exe-heartbeat-hook.js +99 -75
  49. package/dist/hooks/ingest-worker.js +4176 -3226
  50. package/dist/hooks/ingest.js +920 -168
  51. package/dist/hooks/instructions-loaded.js +874 -70
  52. package/dist/hooks/notification.js +860 -56
  53. package/dist/hooks/post-compact.js +881 -73
  54. package/dist/hooks/pre-compact.js +1050 -227
  55. package/dist/hooks/pre-tool-use.js +1084 -159
  56. package/dist/hooks/prompt-ingest-worker.js +1089 -164
  57. package/dist/hooks/prompt-submit.js +1469 -515
  58. package/dist/hooks/response-ingest-worker.js +1104 -179
  59. package/dist/hooks/session-end.js +1085 -251
  60. package/dist/hooks/session-start.js +1241 -231
  61. package/dist/hooks/stop.js +935 -109
  62. package/dist/hooks/subagent-stop.js +881 -73
  63. package/dist/hooks/summary-worker.js +1323 -307
  64. package/dist/index.js +1449 -452
  65. package/dist/lib/agent-config.js +28 -6
  66. package/dist/lib/cloud-sync.js +909 -115
  67. package/dist/lib/config.js +30 -10
  68. package/dist/lib/consolidation.js +42 -9
  69. package/dist/lib/database.js +739 -33
  70. package/dist/lib/db-daemon-client.js +73 -19
  71. package/dist/lib/db.js +2359 -0
  72. package/dist/lib/device-registry.js +760 -47
  73. package/dist/lib/embedder.js +201 -73
  74. package/dist/lib/employee-templates.js +30 -4
  75. package/dist/lib/employees.js +290 -86
  76. package/dist/lib/exe-daemon-client.js +187 -83
  77. package/dist/lib/exe-daemon.js +1696 -616
  78. package/dist/lib/hybrid-search.js +982 -128
  79. package/dist/lib/identity.js +43 -13
  80. package/dist/lib/license.js +133 -48
  81. package/dist/lib/messaging.js +167 -80
  82. package/dist/lib/reminders.js +35 -5
  83. package/dist/lib/schedules.js +772 -32
  84. package/dist/lib/skill-learning.js +54 -7
  85. package/dist/lib/store.js +779 -31
  86. package/dist/lib/task-router.js +94 -73
  87. package/dist/lib/tasks.js +298 -225
  88. package/dist/lib/tmux-routing.js +246 -172
  89. package/dist/lib/token-spend.js +52 -14
  90. package/dist/mcp/server.js +2893 -850
  91. package/dist/mcp/tools/complete-reminder.js +35 -5
  92. package/dist/mcp/tools/create-reminder.js +35 -5
  93. package/dist/mcp/tools/create-task.js +507 -323
  94. package/dist/mcp/tools/deactivate-behavior.js +40 -10
  95. package/dist/mcp/tools/list-reminders.js +35 -5
  96. package/dist/mcp/tools/list-tasks.js +277 -104
  97. package/dist/mcp/tools/send-message.js +129 -56
  98. package/dist/mcp/tools/update-task.js +1864 -188
  99. package/dist/runtime/index.js +1083 -259
  100. package/dist/tui/App.js +1501 -434
  101. package/package.json +3 -2
@@ -15,9 +15,34 @@ var __export = (target, all) => {
15
15
  __defProp(target, name, { get: all[name], enumerable: true });
16
16
  };
17
17
 
18
+ // src/lib/secure-files.ts
19
+ import { chmodSync as chmodSync2, existsSync as existsSync2, mkdirSync as mkdirSync2 } from "fs";
20
+ import { chmod, mkdir } from "fs/promises";
21
+ function ensurePrivateDirSync(dirPath) {
22
+ mkdirSync2(dirPath, { recursive: true, mode: PRIVATE_DIR_MODE });
23
+ try {
24
+ chmodSync2(dirPath, PRIVATE_DIR_MODE);
25
+ } catch {
26
+ }
27
+ }
28
+ function enforcePrivateFileSync(filePath) {
29
+ try {
30
+ if (existsSync2(filePath)) chmodSync2(filePath, PRIVATE_FILE_MODE);
31
+ } catch {
32
+ }
33
+ }
34
+ var PRIVATE_DIR_MODE, PRIVATE_FILE_MODE;
35
+ var init_secure_files = __esm({
36
+ "src/lib/secure-files.ts"() {
37
+ "use strict";
38
+ PRIVATE_DIR_MODE = 448;
39
+ PRIVATE_FILE_MODE = 384;
40
+ }
41
+ });
42
+
18
43
  // src/lib/config.ts
19
- import { readFile, writeFile, mkdir, chmod } from "fs/promises";
20
- import { readFileSync as readFileSync2, existsSync as existsSync2, renameSync } from "fs";
44
+ import { readFile, writeFile } from "fs/promises";
45
+ import { readFileSync as readFileSync2, existsSync as existsSync3, renameSync } from "fs";
21
46
  import path2 from "path";
22
47
  import os from "os";
23
48
  function resolveDataDir() {
@@ -25,7 +50,7 @@ function resolveDataDir() {
25
50
  if (process.env.EXE_MEM_DIR) return process.env.EXE_MEM_DIR;
26
51
  const newDir = path2.join(os.homedir(), ".exe-os");
27
52
  const legacyDir = path2.join(os.homedir(), ".exe-mem");
28
- if (!existsSync2(newDir) && existsSync2(legacyDir)) {
53
+ if (!existsSync3(newDir) && existsSync3(legacyDir)) {
29
54
  try {
30
55
  renameSync(legacyDir, newDir);
31
56
  process.stderr.write(`[exe-os] Migrated data directory: ~/.exe-mem \u2192 ~/.exe-os
@@ -40,6 +65,7 @@ var EXE_AI_DIR, DB_PATH, MODELS_DIR, CONFIG_PATH, LEGACY_LANCE_PATH, CURRENT_CON
40
65
  var init_config = __esm({
41
66
  "src/lib/config.ts"() {
42
67
  "use strict";
68
+ init_secure_files();
43
69
  EXE_AI_DIR = resolveDataDir();
44
70
  DB_PATH = path2.join(EXE_AI_DIR, "memories.db");
45
71
  MODELS_DIR = path2.join(EXE_AI_DIR, "models");
@@ -106,12 +132,135 @@ var init_config = __esm({
106
132
  }
107
133
  });
108
134
 
135
+ // src/lib/runtime-table.ts
136
+ var RUNTIME_TABLE, DEFAULT_RUNTIME;
137
+ var init_runtime_table = __esm({
138
+ "src/lib/runtime-table.ts"() {
139
+ "use strict";
140
+ RUNTIME_TABLE = {
141
+ codex: {
142
+ binary: "codex",
143
+ launchMode: "interactive",
144
+ autoApproveFlag: "--dangerously-bypass-approvals-and-sandbox",
145
+ inlineFlag: "--no-alt-screen",
146
+ apiKeyEnv: "OPENAI_API_KEY",
147
+ defaultModel: "gpt-5.4"
148
+ },
149
+ opencode: {
150
+ binary: "opencode",
151
+ launchMode: "exec",
152
+ autoApproveFlag: "--dangerously-skip-permissions",
153
+ inlineFlag: "",
154
+ apiKeyEnv: "ANTHROPIC_API_KEY",
155
+ defaultModel: "anthropic/claude-sonnet-4-6"
156
+ }
157
+ };
158
+ DEFAULT_RUNTIME = "claude";
159
+ }
160
+ });
161
+
162
+ // src/lib/agent-config.ts
163
+ var agent_config_exports = {};
164
+ __export(agent_config_exports, {
165
+ AGENT_CONFIG_PATH: () => AGENT_CONFIG_PATH,
166
+ DEFAULT_MODELS: () => DEFAULT_MODELS,
167
+ KNOWN_RUNTIMES: () => KNOWN_RUNTIMES,
168
+ RUNTIME_LABELS: () => RUNTIME_LABELS,
169
+ clearAgentRuntime: () => clearAgentRuntime,
170
+ getAgentRuntime: () => getAgentRuntime,
171
+ loadAgentConfig: () => loadAgentConfig,
172
+ saveAgentConfig: () => saveAgentConfig,
173
+ setAgentRuntime: () => setAgentRuntime
174
+ });
175
+ import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync4 } from "fs";
176
+ import path3 from "path";
177
+ function loadAgentConfig() {
178
+ if (!existsSync4(AGENT_CONFIG_PATH)) return {};
179
+ try {
180
+ return JSON.parse(readFileSync3(AGENT_CONFIG_PATH, "utf-8"));
181
+ } catch {
182
+ return {};
183
+ }
184
+ }
185
+ function saveAgentConfig(config) {
186
+ const dir = path3.dirname(AGENT_CONFIG_PATH);
187
+ ensurePrivateDirSync(dir);
188
+ writeFileSync2(AGENT_CONFIG_PATH, JSON.stringify(config, null, 2) + "\n", "utf-8");
189
+ enforcePrivateFileSync(AGENT_CONFIG_PATH);
190
+ }
191
+ function getAgentRuntime(agentId) {
192
+ const config = loadAgentConfig();
193
+ const entry = config[agentId];
194
+ if (entry) return entry;
195
+ const orgDefault = config["default"];
196
+ if (orgDefault) return orgDefault;
197
+ return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
198
+ }
199
+ function setAgentRuntime(agentId, runtime, model) {
200
+ const knownModels = KNOWN_RUNTIMES[runtime];
201
+ if (!knownModels) {
202
+ return {
203
+ ok: false,
204
+ error: `Unknown runtime "${runtime}". Valid: ${Object.keys(KNOWN_RUNTIMES).join(", ")}`
205
+ };
206
+ }
207
+ if (!knownModels.includes(model)) {
208
+ return {
209
+ ok: false,
210
+ error: `Unknown model "${model}" for runtime "${runtime}". Valid: ${knownModels.join(", ")}`
211
+ };
212
+ }
213
+ const config = loadAgentConfig();
214
+ config[agentId] = { runtime, model };
215
+ saveAgentConfig(config);
216
+ return { ok: true };
217
+ }
218
+ function clearAgentRuntime(agentId) {
219
+ const config = loadAgentConfig();
220
+ delete config[agentId];
221
+ saveAgentConfig(config);
222
+ }
223
+ var AGENT_CONFIG_PATH, KNOWN_RUNTIMES, RUNTIME_LABELS, DEFAULT_MODELS;
224
+ var init_agent_config = __esm({
225
+ "src/lib/agent-config.ts"() {
226
+ "use strict";
227
+ init_config();
228
+ init_runtime_table();
229
+ init_secure_files();
230
+ AGENT_CONFIG_PATH = path3.join(EXE_AI_DIR, "agent-config.json");
231
+ KNOWN_RUNTIMES = {
232
+ claude: ["claude-opus-4", "claude-sonnet-4", "claude-haiku-4.5"],
233
+ codex: ["gpt-5.4", "gpt-5.5", "gpt-5.3-codex-spark", "o3", "o4-mini"],
234
+ opencode: ["anthropic/claude-sonnet-4-6", "openai/gpt-5.4", "google/gemini-2.5-pro", "deepseek/deepseek-r3", "minimax/minimax-m2.5"]
235
+ };
236
+ RUNTIME_LABELS = {
237
+ claude: "Claude Code (Anthropic)",
238
+ codex: "Codex (OpenAI)",
239
+ opencode: "OpenCode (open source)"
240
+ };
241
+ DEFAULT_MODELS = {
242
+ claude: "claude-opus-4",
243
+ codex: RUNTIME_TABLE.codex?.defaultModel ?? "gpt-5.4",
244
+ opencode: RUNTIME_TABLE.opencode?.defaultModel ?? "anthropic/claude-sonnet-4-6"
245
+ };
246
+ }
247
+ });
248
+
109
249
  // src/lib/employees.ts
110
250
  import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
111
- import { existsSync as existsSync3, symlinkSync, readlinkSync, readFileSync as readFileSync3, renameSync as renameSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2 } from "fs";
251
+ import { existsSync as existsSync5, symlinkSync, readlinkSync, readFileSync as readFileSync4, renameSync as renameSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "fs";
112
252
  import { execSync } from "child_process";
113
- import path3 from "path";
253
+ import path4 from "path";
114
254
  import os2 from "os";
255
+ function normalizeRole(role) {
256
+ return (role ?? "").trim().toLowerCase();
257
+ }
258
+ function isCoordinatorRole(role) {
259
+ return normalizeRole(role) === normalizeRole(COORDINATOR_ROLE);
260
+ }
261
+ function getCoordinatorEmployee(employees) {
262
+ return employees.find((e) => isCoordinatorRole(e.role));
263
+ }
115
264
  function validateEmployeeName(name) {
116
265
  if (!name) {
117
266
  return { valid: false, error: "Name is required" };
@@ -128,7 +277,7 @@ function validateEmployeeName(name) {
128
277
  return { valid: true };
129
278
  }
130
279
  async function loadEmployees(employeesPath = EMPLOYEES_PATH) {
131
- if (!existsSync3(employeesPath)) {
280
+ if (!existsSync5(employeesPath)) {
132
281
  return [];
133
282
  }
134
283
  const raw = await readFile2(employeesPath, "utf-8");
@@ -139,9 +288,17 @@ async function loadEmployees(employeesPath = EMPLOYEES_PATH) {
139
288
  }
140
289
  }
141
290
  async function saveEmployees(employees, employeesPath = EMPLOYEES_PATH) {
142
- await mkdir2(path3.dirname(employeesPath), { recursive: true });
291
+ await mkdir2(path4.dirname(employeesPath), { recursive: true });
143
292
  await writeFile2(employeesPath, JSON.stringify(employees, null, 2) + "\n", "utf-8");
144
293
  }
294
+ function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
295
+ if (!existsSync5(employeesPath)) return [];
296
+ try {
297
+ return JSON.parse(readFileSync4(employeesPath, "utf-8"));
298
+ } catch {
299
+ return [];
300
+ }
301
+ }
145
302
  function addEmployee(employees, employee) {
146
303
  const normalized = { ...employee, name: employee.name.toLowerCase() };
147
304
  if (employees.some((e) => e.name.toLowerCase() === normalized.name)) {
@@ -149,6 +306,52 @@ function addEmployee(employees, employee) {
149
306
  }
150
307
  return [...employees, normalized];
151
308
  }
309
+ function appendToCoordinatorTeam(employee) {
310
+ const coordinator = getCoordinatorEmployee(loadEmployeesSync());
311
+ if (!coordinator) return;
312
+ const idPath = path4.join(IDENTITY_DIR, `${coordinator.name}.md`);
313
+ if (!existsSync5(idPath)) return;
314
+ const content = readFileSync4(idPath, "utf-8");
315
+ if (content.includes(`**${capitalize(employee.name)}`)) return;
316
+ const teamMatch = content.match(TEAM_SECTION_RE);
317
+ if (!teamMatch || teamMatch.index === void 0) return;
318
+ const afterTeam = content.slice(teamMatch.index + teamMatch[0].length);
319
+ const nextHeading = afterTeam.match(/\n## /);
320
+ const entry = `
321
+ **${capitalize(employee.name)} (${employee.role}):** Newly hired. Update this description as the role develops.
322
+ `;
323
+ let updated;
324
+ if (nextHeading && nextHeading.index !== void 0) {
325
+ const insertAt = teamMatch.index + teamMatch[0].length + nextHeading.index;
326
+ updated = content.slice(0, insertAt) + entry + content.slice(insertAt);
327
+ } else {
328
+ updated = content.trimEnd() + "\n" + entry;
329
+ }
330
+ writeFileSync3(idPath, updated, "utf-8");
331
+ }
332
+ function capitalize(s) {
333
+ return s.charAt(0).toUpperCase() + s.slice(1);
334
+ }
335
+ async function hireEmployee(employee) {
336
+ const employees = await loadEmployees();
337
+ const updated = addEmployee(employees, employee);
338
+ await saveEmployees(updated);
339
+ try {
340
+ appendToCoordinatorTeam(employee);
341
+ } catch {
342
+ }
343
+ try {
344
+ const { loadAgentConfig: loadAgentConfig2, saveAgentConfig: saveAgentConfig2 } = await Promise.resolve().then(() => (init_agent_config(), agent_config_exports));
345
+ const config = loadAgentConfig2();
346
+ const name = employee.name.toLowerCase();
347
+ if (!config[name] && config["default"]) {
348
+ config[name] = { ...config["default"] };
349
+ saveAgentConfig2(config);
350
+ }
351
+ } catch {
352
+ }
353
+ return updated;
354
+ }
152
355
  function findExeBin() {
153
356
  try {
154
357
  return execSync(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
@@ -165,7 +368,7 @@ function registerBinSymlinks(name) {
165
368
  errors.push("Could not find 'exe-os' in PATH");
166
369
  return { created, skipped, errors };
167
370
  }
168
- const binDir = path3.dirname(exeBinPath);
371
+ const binDir = path4.dirname(exeBinPath);
169
372
  let target;
170
373
  try {
171
374
  target = readlinkSync(exeBinPath);
@@ -175,8 +378,8 @@ function registerBinSymlinks(name) {
175
378
  }
176
379
  for (const suffix of ["", "-opencode"]) {
177
380
  const linkName = `${name}${suffix}`;
178
- const linkPath = path3.join(binDir, linkName);
179
- if (existsSync3(linkPath)) {
381
+ const linkPath = path4.join(binDir, linkName);
382
+ if (existsSync5(linkPath)) {
180
383
  skipped.push(linkName);
181
384
  continue;
182
385
  }
@@ -189,12 +392,15 @@ function registerBinSymlinks(name) {
189
392
  }
190
393
  return { created, skipped, errors };
191
394
  }
192
- var EMPLOYEES_PATH;
395
+ var EMPLOYEES_PATH, COORDINATOR_ROLE, IDENTITY_DIR, TEAM_SECTION_RE;
193
396
  var init_employees = __esm({
194
397
  "src/lib/employees.ts"() {
195
398
  "use strict";
196
399
  init_config();
197
- EMPLOYEES_PATH = path3.join(EXE_AI_DIR, "exe-employees.json");
400
+ EMPLOYEES_PATH = path4.join(EXE_AI_DIR, "exe-employees.json");
401
+ COORDINATOR_ROLE = "COO";
402
+ IDENTITY_DIR = path4.join(EXE_AI_DIR, "identity");
403
+ TEAM_SECTION_RE = /^## Team\b.*$/m;
198
404
  }
199
405
  });
200
406
 
@@ -205,12 +411,36 @@ var init_db_retry = __esm({
205
411
  }
206
412
  });
207
413
 
414
+ // src/lib/database-adapter.ts
415
+ import os3 from "os";
416
+ import path5 from "path";
417
+ import { createRequire } from "module";
418
+ import { pathToFileURL } from "url";
419
+ var BOOLEAN_COLUMNS_BY_TABLE, BOOLEAN_COLUMN_NAMES;
420
+ var init_database_adapter = __esm({
421
+ "src/lib/database-adapter.ts"() {
422
+ "use strict";
423
+ BOOLEAN_COLUMNS_BY_TABLE = {
424
+ memories: /* @__PURE__ */ new Set(["has_error", "draft"]),
425
+ behaviors: /* @__PURE__ */ new Set(["active"]),
426
+ notifications: /* @__PURE__ */ new Set(["read"]),
427
+ users: /* @__PURE__ */ new Set(["has_personal_memory"])
428
+ };
429
+ BOOLEAN_COLUMN_NAMES = new Set(
430
+ Object.values(BOOLEAN_COLUMNS_BY_TABLE).flatMap((cols) => [...cols])
431
+ );
432
+ }
433
+ });
434
+
208
435
  // src/lib/database.ts
209
436
  import { createClient } from "@libsql/client";
210
437
  function getClient() {
211
- if (!_resilientClient) {
438
+ if (!_adapterClient) {
212
439
  throw new Error("Database client not initialized. Call initDatabase() first.");
213
440
  }
441
+ if (process.env.DATABASE_URL) {
442
+ return _adapterClient;
443
+ }
214
444
  if (process.env.EXE_IS_DAEMON === "1") {
215
445
  return _resilientClient;
216
446
  }
@@ -219,14 +449,16 @@ function getClient() {
219
449
  }
220
450
  return _resilientClient;
221
451
  }
222
- var _resilientClient, _daemonClient;
452
+ var _resilientClient, _daemonClient, _adapterClient;
223
453
  var init_database = __esm({
224
454
  "src/lib/database.ts"() {
225
455
  "use strict";
226
456
  init_db_retry();
227
457
  init_employees();
458
+ init_database_adapter();
228
459
  _resilientClient = null;
229
460
  _daemonClient = null;
461
+ _adapterClient = null;
230
462
  }
231
463
  });
232
464
 
@@ -780,17 +1012,17 @@ __export(identity_exports, {
780
1012
  listIdentities: () => listIdentities,
781
1013
  updateIdentity: () => updateIdentity
782
1014
  });
783
- import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
1015
+ import { existsSync as existsSync8, mkdirSync as mkdirSync4, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "fs";
784
1016
  import { readdirSync as readdirSync2 } from "fs";
785
- import path6 from "path";
1017
+ import path8 from "path";
786
1018
  import { createHash } from "crypto";
787
1019
  function ensureDir() {
788
- if (!existsSync6(IDENTITY_DIR)) {
789
- mkdirSync3(IDENTITY_DIR, { recursive: true });
1020
+ if (!existsSync8(IDENTITY_DIR2)) {
1021
+ mkdirSync4(IDENTITY_DIR2, { recursive: true });
790
1022
  }
791
1023
  }
792
1024
  function identityPath(agentId) {
793
- return path6.join(IDENTITY_DIR, `${agentId}.md`);
1025
+ return path8.join(IDENTITY_DIR2, `${agentId}.md`);
794
1026
  }
795
1027
  function parseFrontmatter(raw) {
796
1028
  const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
@@ -831,8 +1063,8 @@ function contentHash(content) {
831
1063
  }
832
1064
  function getIdentity(agentId) {
833
1065
  const filePath = identityPath(agentId);
834
- if (!existsSync6(filePath)) return null;
835
- const raw = readFileSync6(filePath, "utf-8");
1066
+ if (!existsSync8(filePath)) return null;
1067
+ const raw = readFileSync7(filePath, "utf-8");
836
1068
  const { frontmatter, body } = parseFrontmatter(raw);
837
1069
  return {
838
1070
  agentId,
@@ -846,7 +1078,7 @@ async function updateIdentity(agentId, content, updatedBy) {
846
1078
  ensureDir();
847
1079
  const filePath = identityPath(agentId);
848
1080
  const hash = contentHash(content);
849
- writeFileSync4(filePath, content, "utf-8");
1081
+ writeFileSync5(filePath, content, "utf-8");
850
1082
  try {
851
1083
  const client = getClient();
852
1084
  await client.execute({
@@ -863,7 +1095,7 @@ async function updateIdentity(agentId, content, updatedBy) {
863
1095
  }
864
1096
  function listIdentities() {
865
1097
  ensureDir();
866
- const files = readdirSync2(IDENTITY_DIR).filter((f) => f.endsWith(".md"));
1098
+ const files = readdirSync2(IDENTITY_DIR2).filter((f) => f.endsWith(".md"));
867
1099
  const results = [];
868
1100
  for (const file of files) {
869
1101
  const agentId = file.replace(".md", "");
@@ -896,40 +1128,40 @@ ${teamLines.join("\n")}`);
896
1128
  }
897
1129
  return parts.join("\n\n");
898
1130
  }
899
- var IDENTITY_DIR;
1131
+ var IDENTITY_DIR2;
900
1132
  var init_identity = __esm({
901
1133
  "src/lib/identity.ts"() {
902
1134
  "use strict";
903
1135
  init_config();
904
1136
  init_database();
905
- IDENTITY_DIR = path6.join(EXE_AI_DIR, "identity");
1137
+ IDENTITY_DIR2 = path8.join(EXE_AI_DIR, "identity");
906
1138
  }
907
1139
  });
908
1140
 
909
1141
  // src/lib/agent-symlinks.ts
910
- import os3 from "os";
911
- import path7 from "path";
1142
+ import os5 from "os";
1143
+ import path9 from "path";
912
1144
  import {
913
- existsSync as existsSync7,
1145
+ existsSync as existsSync9,
914
1146
  lstatSync,
915
- mkdirSync as mkdirSync4,
1147
+ mkdirSync as mkdirSync5,
916
1148
  readlinkSync as readlinkSync2,
917
1149
  symlinkSync as symlinkSync2
918
1150
  } from "fs";
919
1151
  function claudeAgentsDir(homeDir) {
920
- return path7.join(homeDir, ".claude", "agents");
1152
+ return path9.join(homeDir, ".claude", "agents");
921
1153
  }
922
1154
  function identitySourcePath(homeDir, agentId) {
923
- return path7.join(homeDir, ".exe-os", "identity", `${agentId}.md`);
1155
+ return path9.join(homeDir, ".exe-os", "identity", `${agentId}.md`);
924
1156
  }
925
1157
  function claudeAgentLinkPath(homeDir, agentId) {
926
- return path7.join(claudeAgentsDir(homeDir), `${agentId}.md`);
1158
+ return path9.join(claudeAgentsDir(homeDir), `${agentId}.md`);
927
1159
  }
928
- function ensureAgentSymlink(agentId, homeDir = os3.homedir()) {
1160
+ function ensureAgentSymlink(agentId, homeDir = os5.homedir()) {
929
1161
  const target = identitySourcePath(homeDir, agentId);
930
1162
  const link = claudeAgentLinkPath(homeDir, agentId);
931
- mkdirSync4(claudeAgentsDir(homeDir), { recursive: true });
932
- if (existsSync7(link)) {
1163
+ mkdirSync5(claudeAgentsDir(homeDir), { recursive: true });
1164
+ if (existsSync9(link)) {
933
1165
  let stat;
934
1166
  try {
935
1167
  stat = lstatSync(link);
@@ -963,7 +1195,7 @@ function ensureAgentSymlink(agentId, homeDir = os3.homedir()) {
963
1195
  }
964
1196
  return { agentId, action: "created", target, link };
965
1197
  }
966
- async function ensureAllAgentSymlinks(homeDir = os3.homedir()) {
1198
+ async function ensureAllAgentSymlinks(homeDir = os5.homedir()) {
967
1199
  const employees = await loadEmployees();
968
1200
  return employees.map((emp) => ensureAgentSymlink(emp.name, homeDir));
969
1201
  }
@@ -998,14 +1230,14 @@ var init_mcp_prefix = __esm({
998
1230
  });
999
1231
 
1000
1232
  // src/lib/preferences.ts
1001
- import { existsSync as existsSync8, readFileSync as readFileSync7, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5 } from "fs";
1002
- import path8 from "path";
1003
- import os4 from "os";
1004
- function loadPreferences(homeDir = os4.homedir()) {
1005
- const configPath = path8.join(homeDir, ".exe-os", "config.json");
1006
- if (!existsSync8(configPath)) return {};
1233
+ import { existsSync as existsSync10, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "fs";
1234
+ import path10 from "path";
1235
+ import os6 from "os";
1236
+ function loadPreferences(homeDir = os6.homedir()) {
1237
+ const configPath = path10.join(homeDir, ".exe-os", "config.json");
1238
+ if (!existsSync10(configPath)) return {};
1007
1239
  try {
1008
- const config = JSON.parse(readFileSync7(configPath, "utf-8"));
1240
+ const config = JSON.parse(readFileSync8(configPath, "utf-8"));
1009
1241
  return config.preferences ?? {};
1010
1242
  } catch {
1011
1243
  return {};
@@ -1014,6 +1246,7 @@ function loadPreferences(homeDir = os4.homedir()) {
1014
1246
  var init_preferences = __esm({
1015
1247
  "src/lib/preferences.ts"() {
1016
1248
  "use strict";
1249
+ init_secure_files();
1017
1250
  }
1018
1251
  });
1019
1252
 
@@ -1031,52 +1264,52 @@ __export(installer_exports, {
1031
1264
  setupTmux: () => setupTmux
1032
1265
  });
1033
1266
  import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3, readdir } from "fs/promises";
1034
- import { existsSync as existsSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync6, copyFileSync, mkdirSync as mkdirSync6 } from "fs";
1035
- import path9 from "path";
1036
- import os5 from "os";
1267
+ import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync7, copyFileSync, mkdirSync as mkdirSync6 } from "fs";
1268
+ import path11 from "path";
1269
+ import os7 from "os";
1037
1270
  import { execSync as execSync2 } from "child_process";
1038
1271
  import { fileURLToPath as fileURLToPath2 } from "url";
1039
1272
  function resolvePackageRoot() {
1040
1273
  const thisFile = fileURLToPath2(import.meta.url);
1041
- let dir = path9.dirname(thisFile);
1042
- const root = path9.parse(dir).root;
1274
+ let dir = path11.dirname(thisFile);
1275
+ const root = path11.parse(dir).root;
1043
1276
  while (dir !== root) {
1044
- const pkgPath = path9.join(dir, "package.json");
1045
- if (existsSync9(pkgPath)) {
1277
+ const pkgPath = path11.join(dir, "package.json");
1278
+ if (existsSync11(pkgPath)) {
1046
1279
  try {
1047
- const pkg = JSON.parse(readFileSync8(pkgPath, "utf-8"));
1280
+ const pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
1048
1281
  if (pkg.name === "@askexenow/exe-os" || pkg.name === "exe-os") return dir;
1049
1282
  } catch {
1050
1283
  }
1051
1284
  }
1052
- dir = path9.dirname(dir);
1285
+ dir = path11.dirname(dir);
1053
1286
  }
1054
- return path9.resolve(path9.dirname(thisFile), "..", "..", "..");
1287
+ return path11.resolve(path11.dirname(thisFile), "..", "..", "..");
1055
1288
  }
1056
- async function copySlashCommands(packageRoot, homeDir = os5.homedir()) {
1289
+ async function copySlashCommands(packageRoot, homeDir = os7.homedir()) {
1057
1290
  let copied = 0;
1058
1291
  let skipped = 0;
1059
- const skillsBase = path9.join(homeDir, ".claude", "skills");
1060
- const exeDir = path9.join(packageRoot, "src", "commands", "exe");
1061
- if (existsSync9(exeDir)) {
1292
+ const skillsBase = path11.join(homeDir, ".claude", "skills");
1293
+ const exeDir = path11.join(packageRoot, "src", "commands", "exe");
1294
+ if (existsSync11(exeDir)) {
1062
1295
  const entries = await readdir(exeDir);
1063
1296
  const mdFiles = entries.filter((f) => f.endsWith(".md"));
1064
1297
  for (const file of mdFiles) {
1065
1298
  const name = file.replace(".md", "");
1066
- const destDir = path9.join(skillsBase, `exe-${name}`);
1299
+ const destDir = path11.join(skillsBase, `exe-${name}`);
1067
1300
  await mkdir3(destDir, { recursive: true });
1068
- const srcPath = path9.join(exeDir, file);
1069
- const destPath = path9.join(destDir, "SKILL.md");
1301
+ const srcPath = path11.join(exeDir, file);
1302
+ const destPath = path11.join(destDir, "SKILL.md");
1070
1303
  const result = await copyAsSkill(srcPath, destPath, `exe-${name}`);
1071
1304
  if (result) copied++;
1072
1305
  else skipped++;
1073
1306
  }
1074
1307
  }
1075
- const topLevelSrc = path9.join(packageRoot, "src", "commands", "exe.md");
1076
- if (existsSync9(topLevelSrc)) {
1077
- const destDir = path9.join(skillsBase, "exe");
1308
+ const topLevelSrc = path11.join(packageRoot, "src", "commands", "exe.md");
1309
+ if (existsSync11(topLevelSrc)) {
1310
+ const destDir = path11.join(skillsBase, "exe");
1078
1311
  await mkdir3(destDir, { recursive: true });
1079
- const destPath = path9.join(destDir, "SKILL.md");
1312
+ const destPath = path11.join(destDir, "SKILL.md");
1080
1313
  const result = await copyAsSkill(topLevelSrc, destPath, "exe");
1081
1314
  if (result) copied++;
1082
1315
  else skipped++;
@@ -1099,17 +1332,17 @@ name: ${skillName}
1099
1332
  `);
1100
1333
  }
1101
1334
  }
1102
- if (existsSync9(destPath)) {
1335
+ if (existsSync11(destPath)) {
1103
1336
  const existing = await readFile3(destPath, "utf-8");
1104
1337
  if (existing === content) return false;
1105
1338
  }
1106
1339
  await writeFile3(destPath, content);
1107
1340
  return true;
1108
1341
  }
1109
- async function registerMcpServer(packageRoot, homeDir = os5.homedir()) {
1110
- const claudeJsonPath = path9.join(homeDir, ".claude.json");
1342
+ async function registerMcpServer(packageRoot, homeDir = os7.homedir()) {
1343
+ const claudeJsonPath = path11.join(homeDir, ".claude.json");
1111
1344
  let claudeJson = {};
1112
- if (existsSync9(claudeJsonPath)) {
1345
+ if (existsSync11(claudeJsonPath)) {
1113
1346
  try {
1114
1347
  claudeJson = JSON.parse(await readFile3(claudeJsonPath, "utf-8"));
1115
1348
  } catch {
@@ -1122,25 +1355,25 @@ async function registerMcpServer(packageRoot, homeDir = os5.homedir()) {
1122
1355
  const newEntry = {
1123
1356
  type: "stdio",
1124
1357
  command: "node",
1125
- args: [path9.join(packageRoot, "dist", "mcp", "server.js")],
1358
+ args: [path11.join(packageRoot, "dist", "mcp", "server.js")],
1126
1359
  env: {}
1127
1360
  };
1128
1361
  const currentMem = claudeJson.mcpServers[MCP_LEGACY_KEY];
1129
- const currentOs = claudeJson.mcpServers[MCP_PRIMARY_KEY];
1130
1362
  const memMatches = currentMem && JSON.stringify(currentMem) === JSON.stringify(newEntry);
1131
- const osMatches = currentOs && JSON.stringify(currentOs) === JSON.stringify(newEntry);
1132
- if (memMatches && osMatches) {
1133
- await cleanSettingsJsonMcp(path9.join(homeDir, ".claude", "settings.json"));
1363
+ if (claudeJson.mcpServers[MCP_PRIMARY_KEY]) {
1364
+ delete claudeJson.mcpServers[MCP_PRIMARY_KEY];
1365
+ }
1366
+ if (memMatches && !claudeJson.mcpServers[MCP_PRIMARY_KEY]) {
1367
+ await cleanSettingsJsonMcp(path11.join(homeDir, ".claude", "settings.json"));
1134
1368
  return false;
1135
1369
  }
1136
1370
  claudeJson.mcpServers[MCP_LEGACY_KEY] = newEntry;
1137
- claudeJson.mcpServers[MCP_PRIMARY_KEY] = newEntry;
1138
1371
  await writeFile3(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
1139
- await cleanSettingsJsonMcp(path9.join(homeDir, ".claude", "settings.json"));
1372
+ await cleanSettingsJsonMcp(path11.join(homeDir, ".claude", "settings.json"));
1140
1373
  return true;
1141
1374
  }
1142
1375
  async function cleanSettingsJsonMcp(settingsPath) {
1143
- if (!existsSync9(settingsPath)) return;
1376
+ if (!existsSync11(settingsPath)) return;
1144
1377
  try {
1145
1378
  const settings = JSON.parse(await readFile3(settingsPath, "utf-8"));
1146
1379
  const servers = settings.mcpServers;
@@ -1160,14 +1393,14 @@ async function cleanSettingsJsonMcp(settingsPath) {
1160
1393
  } catch {
1161
1394
  }
1162
1395
  }
1163
- async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1164
- const settingsPath = path9.join(homeDir, ".claude", "settings.json");
1165
- const logsDir = path9.join(homeDir, ".exe-os", "logs");
1166
- const hookLogPath = path9.join(logsDir, "hooks.log");
1396
+ async function mergeHooks(packageRoot, homeDir = os7.homedir()) {
1397
+ const settingsPath = path11.join(homeDir, ".claude", "settings.json");
1398
+ const logsDir = path11.join(homeDir, ".exe-os", "logs");
1399
+ const hookLogPath = path11.join(logsDir, "hooks.log");
1167
1400
  const logSuffix = ` 2>> "${hookLogPath}"`;
1168
1401
  await mkdir3(logsDir, { recursive: true });
1169
1402
  let settings = {};
1170
- if (existsSync9(settingsPath)) {
1403
+ if (existsSync11(settingsPath)) {
1171
1404
  try {
1172
1405
  settings = JSON.parse(await readFile3(settingsPath, "utf-8"));
1173
1406
  } catch {
@@ -1189,11 +1422,11 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1189
1422
  hooks: [
1190
1423
  {
1191
1424
  type: "command",
1192
- command: `node "${path9.join(packageRoot, "dist", "hooks", "ingest.js")}"${logSuffix}`
1425
+ command: `node "${path11.join(packageRoot, "dist", "hooks", "ingest.js")}"${logSuffix}`
1193
1426
  },
1194
1427
  {
1195
1428
  type: "command",
1196
- command: `node "${path9.join(packageRoot, "dist", "hooks", "error-recall.js")}"${logSuffix}`
1429
+ command: `node "${path11.join(packageRoot, "dist", "hooks", "error-recall.js")}"${logSuffix}`
1197
1430
  }
1198
1431
  ]
1199
1432
  },
@@ -1205,7 +1438,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1205
1438
  hooks: [
1206
1439
  {
1207
1440
  type: "command",
1208
- command: `node "${path9.join(packageRoot, "dist", "hooks", "session-start.js")}"${logSuffix}`,
1441
+ command: `node "${path11.join(packageRoot, "dist", "hooks", "session-start.js")}"${logSuffix}`,
1209
1442
  timeout: 1e4
1210
1443
  }
1211
1444
  ]
@@ -1218,7 +1451,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1218
1451
  hooks: [
1219
1452
  {
1220
1453
  type: "command",
1221
- command: `node "${path9.join(packageRoot, "dist", "hooks", "prompt-submit.js")}"${logSuffix}`
1454
+ command: `node "${path11.join(packageRoot, "dist", "hooks", "prompt-submit.js")}"${logSuffix}`
1222
1455
  }
1223
1456
  ]
1224
1457
  },
@@ -1230,7 +1463,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1230
1463
  hooks: [
1231
1464
  {
1232
1465
  type: "command",
1233
- command: `node "${path9.join(packageRoot, "dist", "hooks", "exe-heartbeat-hook.js")}"${logSuffix}`,
1466
+ command: `node "${path11.join(packageRoot, "dist", "hooks", "exe-heartbeat-hook.js")}"${logSuffix}`,
1234
1467
  timeout: 5e3
1235
1468
  }
1236
1469
  ]
@@ -1243,7 +1476,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1243
1476
  hooks: [
1244
1477
  {
1245
1478
  type: "command",
1246
- command: `node "${path9.join(packageRoot, "dist", "hooks", "stop.js")}"${logSuffix}`
1479
+ command: `node "${path11.join(packageRoot, "dist", "hooks", "stop.js")}"${logSuffix}`
1247
1480
  }
1248
1481
  ]
1249
1482
  },
@@ -1256,7 +1489,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1256
1489
  hooks: [
1257
1490
  {
1258
1491
  type: "command",
1259
- command: `node "${path9.join(packageRoot, "dist", "hooks", "pre-tool-use.js")}"${logSuffix}`
1492
+ command: `node "${path11.join(packageRoot, "dist", "hooks", "pre-tool-use.js")}"${logSuffix}`
1260
1493
  }
1261
1494
  ]
1262
1495
  },
@@ -1268,7 +1501,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1268
1501
  hooks: [
1269
1502
  {
1270
1503
  type: "command",
1271
- command: `node "${path9.join(packageRoot, "dist", "hooks", "subagent-stop.js")}"${logSuffix}`
1504
+ command: `node "${path11.join(packageRoot, "dist", "hooks", "subagent-stop.js")}"${logSuffix}`
1272
1505
  }
1273
1506
  ]
1274
1507
  },
@@ -1280,7 +1513,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1280
1513
  hooks: [
1281
1514
  {
1282
1515
  type: "command",
1283
- command: `node "${path9.join(packageRoot, "dist", "hooks", "pre-compact.js")}"${logSuffix}`,
1516
+ command: `node "${path11.join(packageRoot, "dist", "hooks", "pre-compact.js")}"${logSuffix}`,
1284
1517
  timeout: 1e4
1285
1518
  }
1286
1519
  ]
@@ -1293,7 +1526,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1293
1526
  hooks: [
1294
1527
  {
1295
1528
  type: "command",
1296
- command: `node "${path9.join(packageRoot, "dist", "hooks", "session-end.js")}"${logSuffix}`
1529
+ command: `node "${path11.join(packageRoot, "dist", "hooks", "session-end.js")}"${logSuffix}`
1297
1530
  }
1298
1531
  ]
1299
1532
  },
@@ -1305,7 +1538,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1305
1538
  hooks: [
1306
1539
  {
1307
1540
  type: "command",
1308
- command: `node "${path9.join(packageRoot, "dist", "hooks", "notification.js")}"${logSuffix}`
1541
+ command: `node "${path11.join(packageRoot, "dist", "hooks", "notification.js")}"${logSuffix}`
1309
1542
  }
1310
1543
  ]
1311
1544
  },
@@ -1317,7 +1550,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1317
1550
  hooks: [
1318
1551
  {
1319
1552
  type: "command",
1320
- command: `node "${path9.join(packageRoot, "dist", "hooks", "post-compact.js")}"${logSuffix}`,
1553
+ command: `node "${path11.join(packageRoot, "dist", "hooks", "post-compact.js")}"${logSuffix}`,
1321
1554
  timeout: 1e4
1322
1555
  }
1323
1556
  ]
@@ -1330,7 +1563,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1330
1563
  hooks: [
1331
1564
  {
1332
1565
  type: "command",
1333
- command: `node "${path9.join(packageRoot, "dist", "hooks", "instructions-loaded.js")}"${logSuffix}`
1566
+ command: `node "${path11.join(packageRoot, "dist", "hooks", "instructions-loaded.js")}"${logSuffix}`
1334
1567
  }
1335
1568
  ]
1336
1569
  },
@@ -1429,13 +1662,13 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
1429
1662
  allowList.push(tool);
1430
1663
  }
1431
1664
  }
1432
- await mkdir3(path9.dirname(settingsPath), { recursive: true });
1665
+ await mkdir3(path11.dirname(settingsPath), { recursive: true });
1433
1666
  await writeFile3(settingsPath, JSON.stringify(settings, null, 2) + "\n");
1434
1667
  return { added, skipped };
1435
1668
  }
1436
- async function cleanOldShellFunctions(homeDir = os5.homedir()) {
1437
- const rosterPath = path9.join(homeDir, ".exe-os", "exe-employees.json");
1438
- if (!existsSync9(rosterPath)) return 0;
1669
+ async function cleanOldShellFunctions(homeDir = os7.homedir()) {
1670
+ const rosterPath = path11.join(homeDir, ".exe-os", "exe-employees.json");
1671
+ if (!existsSync11(rosterPath)) return 0;
1439
1672
  let employees;
1440
1673
  try {
1441
1674
  employees = JSON.parse(await readFile3(rosterPath, "utf-8"));
@@ -1450,13 +1683,13 @@ async function cleanOldShellFunctions(homeDir = os5.homedir()) {
1450
1683
  return { name: n, funcDef, forLoop };
1451
1684
  });
1452
1685
  const rcFiles = [
1453
- path9.join(homeDir, ".zshrc"),
1454
- path9.join(homeDir, ".bashrc")
1686
+ path11.join(homeDir, ".zshrc"),
1687
+ path11.join(homeDir, ".bashrc")
1455
1688
  ];
1456
1689
  const REMOVED_MARKER = "# Removed by exe-os \u2014 wrappers now at ~/.exe-os/bin/";
1457
1690
  let totalRemoved = 0;
1458
1691
  for (const rcPath of rcFiles) {
1459
- if (!existsSync9(rcPath)) continue;
1692
+ if (!existsSync11(rcPath)) continue;
1460
1693
  let content;
1461
1694
  try {
1462
1695
  content = await readFile3(rcPath, "utf-8");
@@ -1560,8 +1793,8 @@ function escapeRegExp(s) {
1560
1793
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1561
1794
  }
1562
1795
  async function injectOrchestrationRules(homeDir) {
1563
- const claudeDir = path9.join(homeDir, ".claude");
1564
- const claudeMdPath = path9.join(claudeDir, "CLAUDE.md");
1796
+ const claudeDir = path11.join(homeDir, ".claude");
1797
+ const claudeMdPath = path11.join(claudeDir, "CLAUDE.md");
1565
1798
  await mkdir3(claudeDir, { recursive: true });
1566
1799
  let existing = "";
1567
1800
  try {
@@ -1583,19 +1816,19 @@ async function injectOrchestrationRules(homeDir) {
1583
1816
  await writeFile3(claudeMdPath, existing + separator + ORCHESTRATION_RULES + "\n", "utf-8");
1584
1817
  return "injected";
1585
1818
  }
1586
- async function installStatusLine(packageRoot, homeDir = os5.homedir()) {
1819
+ async function installStatusLine(packageRoot, homeDir = os7.homedir()) {
1587
1820
  const prefs = loadPreferences(homeDir);
1588
1821
  if (prefs.ccStatusLine === false) return "opted-out";
1589
- const claudeDir = path9.join(homeDir, ".claude");
1822
+ const claudeDir = path11.join(homeDir, ".claude");
1590
1823
  await mkdir3(claudeDir, { recursive: true });
1591
- const assetPath = path9.join(packageRoot, "dist", "assets", "statusline-command.sh");
1592
- if (!existsSync9(assetPath)) return "asset-missing";
1593
- const destScript = path9.join(claudeDir, "statusline-command.sh");
1824
+ const assetPath = path11.join(packageRoot, "dist", "assets", "statusline-command.sh");
1825
+ if (!existsSync11(assetPath)) return "asset-missing";
1826
+ const destScript = path11.join(claudeDir, "statusline-command.sh");
1594
1827
  const assetContent = await readFile3(assetPath, "utf-8");
1595
1828
  await writeFile3(destScript, assetContent, { mode: 493 });
1596
- const settingsPath = path9.join(claudeDir, "settings.json");
1829
+ const settingsPath = path11.join(claudeDir, "settings.json");
1597
1830
  let settings = {};
1598
- if (existsSync9(settingsPath)) {
1831
+ if (existsSync11(settingsPath)) {
1599
1832
  try {
1600
1833
  settings = JSON.parse(await readFile3(settingsPath, "utf-8"));
1601
1834
  } catch {
@@ -1632,13 +1865,13 @@ async function runInstaller(homeDir) {
1632
1865
  `Hooks: ${hookResult.added} added, ${hookResult.skipped} unchanged
1633
1866
  `
1634
1867
  );
1635
- const resolvedHome = homeDir ?? os5.homedir();
1636
- const exeWorkspace = path9.join(resolvedHome, "exe");
1637
- if (!existsSync9(exeWorkspace)) {
1868
+ const resolvedHome = homeDir ?? os7.homedir();
1869
+ const exeWorkspace = path11.join(resolvedHome, "exe");
1870
+ if (!existsSync11(exeWorkspace)) {
1638
1871
  try {
1639
- await mkdir3(path9.join(exeWorkspace, "content"), { recursive: true });
1640
- await mkdir3(path9.join(exeWorkspace, "operations"), { recursive: true });
1641
- await mkdir3(path9.join(exeWorkspace, "output"), { recursive: true });
1872
+ await mkdir3(path11.join(exeWorkspace, "content"), { recursive: true });
1873
+ await mkdir3(path11.join(exeWorkspace, "operations"), { recursive: true });
1874
+ await mkdir3(path11.join(exeWorkspace, "output"), { recursive: true });
1642
1875
  process.stderr.write(
1643
1876
  `Created ~/exe/ \u2014 your automation workspace for non-code projects
1644
1877
  `
@@ -1673,34 +1906,34 @@ exe-os installed successfully.
1673
1906
  `);
1674
1907
  }
1675
1908
  function setupTmux(home) {
1676
- const homeDir = home ?? os5.homedir();
1677
- const exeDir = path9.join(homeDir, ".exe-os");
1678
- const exeTmuxConf = path9.join(exeDir, "tmux.conf");
1679
- const userTmuxConf = path9.join(homeDir, ".tmux.conf");
1680
- const backupPath = path9.join(homeDir, ".tmux.conf.backup");
1909
+ const homeDir = home ?? os7.homedir();
1910
+ const exeDir = path11.join(homeDir, ".exe-os");
1911
+ const exeTmuxConf = path11.join(exeDir, "tmux.conf");
1912
+ const userTmuxConf = path11.join(homeDir, ".tmux.conf");
1913
+ const backupPath = path11.join(homeDir, ".tmux.conf.backup");
1681
1914
  const sourceLine = "source-file ~/.exe-os/tmux.conf";
1682
1915
  const pkgRoot = resolvePackageRoot();
1683
- const assetPath = path9.join(pkgRoot, "dist", "assets", "tmux.conf");
1684
- if (!existsSync9(assetPath)) {
1916
+ const assetPath = path11.join(pkgRoot, "dist", "assets", "tmux.conf");
1917
+ if (!existsSync11(assetPath)) {
1685
1918
  process.stderr.write(`exe-os: tmux.conf asset not found at ${assetPath} \u2014 skipping tmux setup
1686
1919
  `);
1687
1920
  return;
1688
1921
  }
1689
1922
  mkdirSync6(exeDir, { recursive: true });
1690
1923
  copyFileSync(assetPath, exeTmuxConf);
1691
- if (existsSync9(userTmuxConf)) {
1692
- const existing = readFileSync8(userTmuxConf, "utf8");
1924
+ if (existsSync11(userTmuxConf)) {
1925
+ const existing = readFileSync9(userTmuxConf, "utf8");
1693
1926
  if (!existing.includes(sourceLine)) {
1694
- if (!existsSync9(backupPath)) {
1927
+ if (!existsSync11(backupPath)) {
1695
1928
  copyFileSync(userTmuxConf, backupPath);
1696
1929
  process.stderr.write(`exe-os: backed up existing tmux config to ${backupPath}
1697
1930
  `);
1698
1931
  }
1699
- writeFileSync6(userTmuxConf, `${sourceLine}
1932
+ writeFileSync7(userTmuxConf, `${sourceLine}
1700
1933
  ${existing}`);
1701
1934
  }
1702
1935
  } else {
1703
- writeFileSync6(userTmuxConf, `# Exe OS tmux defaults \u2014 remove this line to use your own config
1936
+ writeFileSync7(userTmuxConf, `# Exe OS tmux defaults \u2014 remove this line to use your own config
1704
1937
  ${sourceLine}
1705
1938
  `);
1706
1939
  }
@@ -1711,10 +1944,10 @@ ${sourceLine}
1711
1944
  process.stderr.write("exe-os: tmux config installed\n");
1712
1945
  }
1713
1946
  function setupGhostty(home) {
1714
- const homeDir = home ?? os5.homedir();
1715
- const xdgConfig = path9.join(homeDir, ".config", "ghostty");
1716
- const macConfig = path9.join(homeDir, "Library", "Application Support", "com.mitchellh.ghostty");
1717
- const ghosttyInstalled = existsSync9(xdgConfig) || existsSync9(macConfig) || (() => {
1947
+ const homeDir = home ?? os7.homedir();
1948
+ const xdgConfig = path11.join(homeDir, ".config", "ghostty");
1949
+ const macConfig = path11.join(homeDir, "Library", "Application Support", "com.mitchellh.ghostty");
1950
+ const ghosttyInstalled = existsSync11(xdgConfig) || existsSync11(macConfig) || (() => {
1718
1951
  try {
1719
1952
  execSync2("which ghostty 2>/dev/null");
1720
1953
  return true;
@@ -1726,47 +1959,47 @@ function setupGhostty(home) {
1726
1959
  return;
1727
1960
  }
1728
1961
  const pkgRoot = resolvePackageRoot();
1729
- const assetPath = path9.join(pkgRoot, "dist", "assets", "ghostty.conf");
1730
- if (!existsSync9(assetPath)) {
1962
+ const assetPath = path11.join(pkgRoot, "dist", "assets", "ghostty.conf");
1963
+ if (!existsSync11(assetPath)) {
1731
1964
  process.stderr.write("exe-os: ghostty.conf asset not found \u2014 skipping Ghostty setup\n");
1732
1965
  return;
1733
1966
  }
1734
1967
  const configDir = xdgConfig;
1735
- const configPath = path9.join(configDir, "config");
1736
- const backupPath = path9.join(configDir, "config.backup");
1968
+ const configPath = path11.join(configDir, "config");
1969
+ const backupPath = path11.join(configDir, "config.backup");
1737
1970
  mkdirSync6(configDir, { recursive: true });
1738
1971
  const START_MARKER = "# \u2500\u2500 exe-os:ghostty-start \u2500\u2500";
1739
1972
  const END_MARKER = "# \u2500\u2500 exe-os:ghostty-end \u2500\u2500";
1740
- const assetContent = readFileSync8(assetPath, "utf8").trim();
1973
+ const assetContent = readFileSync9(assetPath, "utf8").trim();
1741
1974
  const markedSection = `${START_MARKER}
1742
1975
  ${assetContent}
1743
1976
  ${END_MARKER}`;
1744
- if (existsSync9(configPath)) {
1745
- const existing = readFileSync8(configPath, "utf8");
1977
+ if (existsSync11(configPath)) {
1978
+ const existing = readFileSync9(configPath, "utf8");
1746
1979
  if (existing.includes(START_MARKER) && existing.includes(END_MARKER)) {
1747
1980
  const before = existing.slice(0, existing.indexOf(START_MARKER));
1748
1981
  const after = existing.slice(existing.indexOf(END_MARKER) + END_MARKER.length);
1749
- writeFileSync6(configPath, `${before}${markedSection}${after}`);
1982
+ writeFileSync7(configPath, `${before}${markedSection}${after}`);
1750
1983
  } else if (existing.includes("Exe OS")) {
1751
- if (!existsSync9(backupPath)) {
1984
+ if (!existsSync11(backupPath)) {
1752
1985
  copyFileSync(configPath, backupPath);
1753
1986
  process.stderr.write(`exe-os: backed up existing Ghostty config to ${backupPath}
1754
1987
  `);
1755
1988
  }
1756
- writeFileSync6(configPath, `${markedSection}
1989
+ writeFileSync7(configPath, `${markedSection}
1757
1990
  `);
1758
1991
  } else {
1759
- if (!existsSync9(backupPath)) {
1992
+ if (!existsSync11(backupPath)) {
1760
1993
  copyFileSync(configPath, backupPath);
1761
1994
  process.stderr.write(`exe-os: backed up existing Ghostty config to ${backupPath}
1762
1995
  `);
1763
1996
  }
1764
- writeFileSync6(configPath, `${markedSection}
1997
+ writeFileSync7(configPath, `${markedSection}
1765
1998
 
1766
1999
  ${existing}`);
1767
2000
  }
1768
2001
  } else {
1769
- writeFileSync6(configPath, `${markedSection}
2002
+ writeFileSync7(configPath, `${markedSection}
1770
2003
  `);
1771
2004
  }
1772
2005
  process.stderr.write("exe-os: Ghostty config installed\n");
@@ -1807,8 +2040,8 @@ ${EXE_SECTION_END}`;
1807
2040
  });
1808
2041
 
1809
2042
  // src/bin/exe-new-employee.ts
1810
- import { existsSync as existsSync10, mkdirSync as mkdirSync7 } from "fs";
1811
- import path10 from "path";
2043
+ import { existsSync as existsSync12, mkdirSync as mkdirSync7 } from "fs";
2044
+ import path12 from "path";
1812
2045
 
1813
2046
  // src/lib/session-wrappers.ts
1814
2047
  import {
@@ -2400,18 +2633,21 @@ function isMainModule(importMetaUrl) {
2400
2633
  // src/lib/plan-limits.ts
2401
2634
  init_database();
2402
2635
  init_employees();
2403
- import { readFileSync as readFileSync5, existsSync as existsSync5 } from "fs";
2404
- import path5 from "path";
2636
+ import { readFileSync as readFileSync6, existsSync as existsSync7 } from "fs";
2637
+ import path7 from "path";
2405
2638
 
2406
2639
  // src/lib/license.ts
2407
2640
  init_config();
2408
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync4, mkdirSync as mkdirSync2 } from "fs";
2641
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
2409
2642
  import { randomUUID as randomUUID2 } from "crypto";
2410
- import path4 from "path";
2643
+ import { createRequire as createRequire2 } from "module";
2644
+ import { pathToFileURL as pathToFileURL2 } from "url";
2645
+ import os4 from "os";
2646
+ import path6 from "path";
2411
2647
  import { jwtVerify, importSPKI } from "jose";
2412
- var LICENSE_PATH = path4.join(EXE_AI_DIR, "license.key");
2413
- var CACHE_PATH = path4.join(EXE_AI_DIR, "license-cache.json");
2414
- var DEVICE_ID_PATH = path4.join(EXE_AI_DIR, "device-id");
2648
+ var LICENSE_PATH = path6.join(EXE_AI_DIR, "license.key");
2649
+ var CACHE_PATH = path6.join(EXE_AI_DIR, "license-cache.json");
2650
+ var DEVICE_ID_PATH = path6.join(EXE_AI_DIR, "device-id");
2415
2651
  var API_BASE = "https://askexe.com/cloud";
2416
2652
  var RETRY_DELAY_MS = 500;
2417
2653
  async function fetchRetry(url, init) {
@@ -2444,37 +2680,37 @@ var FREE_LICENSE = {
2444
2680
  memoryLimit: 5e3
2445
2681
  };
2446
2682
  function loadDeviceId() {
2447
- const deviceJsonPath = path4.join(EXE_AI_DIR, "device.json");
2683
+ const deviceJsonPath = path6.join(EXE_AI_DIR, "device.json");
2448
2684
  try {
2449
- if (existsSync4(deviceJsonPath)) {
2450
- const data = JSON.parse(readFileSync4(deviceJsonPath, "utf8"));
2685
+ if (existsSync6(deviceJsonPath)) {
2686
+ const data = JSON.parse(readFileSync5(deviceJsonPath, "utf8"));
2451
2687
  if (data.deviceId) return data.deviceId;
2452
2688
  }
2453
2689
  } catch {
2454
2690
  }
2455
2691
  try {
2456
- if (existsSync4(DEVICE_ID_PATH)) {
2457
- const id2 = readFileSync4(DEVICE_ID_PATH, "utf8").trim();
2692
+ if (existsSync6(DEVICE_ID_PATH)) {
2693
+ const id2 = readFileSync5(DEVICE_ID_PATH, "utf8").trim();
2458
2694
  if (id2) return id2;
2459
2695
  }
2460
2696
  } catch {
2461
2697
  }
2462
2698
  const id = randomUUID2();
2463
- mkdirSync2(EXE_AI_DIR, { recursive: true });
2464
- writeFileSync3(DEVICE_ID_PATH, id, "utf8");
2699
+ mkdirSync3(EXE_AI_DIR, { recursive: true });
2700
+ writeFileSync4(DEVICE_ID_PATH, id, "utf8");
2465
2701
  return id;
2466
2702
  }
2467
2703
  function loadLicense() {
2468
2704
  try {
2469
- if (!existsSync4(LICENSE_PATH)) return null;
2470
- return readFileSync4(LICENSE_PATH, "utf8").trim();
2705
+ if (!existsSync6(LICENSE_PATH)) return null;
2706
+ return readFileSync5(LICENSE_PATH, "utf8").trim();
2471
2707
  } catch {
2472
2708
  return null;
2473
2709
  }
2474
2710
  }
2475
2711
  function saveLicense(apiKey) {
2476
- mkdirSync2(EXE_AI_DIR, { recursive: true });
2477
- writeFileSync3(LICENSE_PATH, apiKey.trim(), { encoding: "utf8", mode: 384 });
2712
+ mkdirSync3(EXE_AI_DIR, { recursive: true });
2713
+ writeFileSync4(LICENSE_PATH, apiKey.trim(), { encoding: "utf8", mode: 384 });
2478
2714
  }
2479
2715
  async function verifyLicenseJwt(token) {
2480
2716
  try {
@@ -2500,8 +2736,8 @@ async function verifyLicenseJwt(token) {
2500
2736
  }
2501
2737
  async function getCachedLicense() {
2502
2738
  try {
2503
- if (!existsSync4(CACHE_PATH)) return null;
2504
- const raw = JSON.parse(readFileSync4(CACHE_PATH, "utf8"));
2739
+ if (!existsSync6(CACHE_PATH)) return null;
2740
+ const raw = JSON.parse(readFileSync5(CACHE_PATH, "utf8"));
2505
2741
  if (!raw.token || typeof raw.token !== "string") return null;
2506
2742
  return await verifyLicenseJwt(raw.token);
2507
2743
  } catch {
@@ -2510,8 +2746,8 @@ async function getCachedLicense() {
2510
2746
  }
2511
2747
  function readCachedToken() {
2512
2748
  try {
2513
- if (!existsSync4(CACHE_PATH)) return null;
2514
- const raw = JSON.parse(readFileSync4(CACHE_PATH, "utf8"));
2749
+ if (!existsSync6(CACHE_PATH)) return null;
2750
+ const raw = JSON.parse(readFileSync5(CACHE_PATH, "utf8"));
2515
2751
  return typeof raw.token === "string" ? raw.token : null;
2516
2752
  } catch {
2517
2753
  return null;
@@ -2545,56 +2781,132 @@ function getRawCachedPlan() {
2545
2781
  }
2546
2782
  function cacheResponse(token) {
2547
2783
  try {
2548
- writeFileSync3(CACHE_PATH, JSON.stringify({ token }), "utf8");
2784
+ writeFileSync4(CACHE_PATH, JSON.stringify({ token }), "utf8");
2549
2785
  } catch {
2550
2786
  }
2551
2787
  }
2552
- async function validateLicense(apiKey, deviceId) {
2553
- const did = deviceId ?? loadDeviceId();
2788
+ var _prismaPromise = null;
2789
+ var _prismaFailed = false;
2790
+ function loadPrismaForLicense() {
2791
+ if (_prismaFailed) return null;
2792
+ const dbUrl = process.env.DATABASE_URL;
2793
+ if (!dbUrl) {
2794
+ const exeDbRoot = process.env.EXE_DB_ROOT ?? path6.join(os4.homedir(), "exe-db");
2795
+ if (!existsSync6(path6.join(exeDbRoot, "package.json"))) {
2796
+ _prismaFailed = true;
2797
+ return null;
2798
+ }
2799
+ }
2800
+ if (!_prismaPromise) {
2801
+ _prismaPromise = (async () => {
2802
+ const explicitPath = process.env.EXE_OS_PRISMA_CLIENT_PATH;
2803
+ if (explicitPath) {
2804
+ const mod2 = await import(pathToFileURL2(explicitPath).href);
2805
+ const Ctor2 = mod2.PrismaClient ?? mod2.default?.PrismaClient;
2806
+ if (!Ctor2) throw new Error(`No PrismaClient at ${explicitPath}`);
2807
+ return new Ctor2();
2808
+ }
2809
+ const exeDbRoot = process.env.EXE_DB_ROOT ?? path6.join(os4.homedir(), "exe-db");
2810
+ const req = createRequire2(path6.join(exeDbRoot, "package.json"));
2811
+ const entry = req.resolve("@prisma/client");
2812
+ const mod = await import(pathToFileURL2(entry).href);
2813
+ const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
2814
+ if (!Ctor) throw new Error(`No PrismaClient in ${entry}`);
2815
+ return new Ctor();
2816
+ })().catch((err) => {
2817
+ _prismaFailed = true;
2818
+ _prismaPromise = null;
2819
+ throw err;
2820
+ });
2821
+ }
2822
+ return _prismaPromise;
2823
+ }
2824
+ async function validateViaPostgres(apiKey) {
2825
+ const loader = loadPrismaForLicense();
2826
+ if (!loader) return null;
2827
+ try {
2828
+ const prisma = await loader;
2829
+ const rows = await prisma.$queryRawUnsafe(
2830
+ `SELECT plan, email, status, device_limit, employee_limit, memory_limit, expires_at
2831
+ FROM billing.licenses WHERE key = $1 LIMIT 1`,
2832
+ apiKey
2833
+ );
2834
+ if (!rows || rows.length === 0) return null;
2835
+ const row = rows[0];
2836
+ if (row.status !== "active") return null;
2837
+ if (row.expires_at && new Date(row.expires_at) < /* @__PURE__ */ new Date()) return null;
2838
+ const plan = row.plan;
2839
+ const limits = PLAN_LIMITS[plan] ?? PLAN_LIMITS.free;
2840
+ return {
2841
+ valid: true,
2842
+ plan,
2843
+ email: row.email,
2844
+ expiresAt: row.expires_at ? new Date(row.expires_at).toISOString() : null,
2845
+ deviceLimit: row.device_limit ?? limits.devices,
2846
+ employeeLimit: row.employee_limit ?? limits.employees,
2847
+ memoryLimit: row.memory_limit ?? limits.memories
2848
+ };
2849
+ } catch {
2850
+ return null;
2851
+ }
2852
+ }
2853
+ async function validateViaCFWorker(apiKey, deviceId) {
2554
2854
  try {
2555
2855
  const res = await fetchRetry(`${API_BASE}/auth/activate`, {
2556
2856
  method: "POST",
2557
2857
  headers: { "Content-Type": "application/json" },
2558
- body: JSON.stringify({ apiKey, deviceId: did }),
2858
+ body: JSON.stringify({ apiKey, deviceId }),
2559
2859
  signal: AbortSignal.timeout(1e4)
2560
2860
  });
2561
- if (res.ok) {
2562
- const data = await res.json();
2563
- if (data.error === "device_limit_exceeded") {
2564
- const cached2 = await getCachedLicense();
2565
- if (cached2) return cached2;
2566
- const raw2 = getRawCachedPlan();
2567
- if (raw2) return { ...raw2, valid: false };
2568
- return { ...FREE_LICENSE, valid: false, plan: "free" };
2569
- }
2570
- if (data.token) {
2571
- cacheResponse(data.token);
2572
- const verified = await verifyLicenseJwt(data.token);
2573
- if (verified) return verified;
2861
+ if (!res.ok) return null;
2862
+ const data = await res.json();
2863
+ if (data.error === "device_limit_exceeded") return null;
2864
+ if (!data.valid) return null;
2865
+ if (data.token) {
2866
+ cacheResponse(data.token);
2867
+ const verified = await verifyLicenseJwt(data.token);
2868
+ if (verified) return verified;
2869
+ }
2870
+ const limits = PLAN_LIMITS[data.plan] ?? PLAN_LIMITS.free;
2871
+ return {
2872
+ valid: data.valid,
2873
+ plan: data.plan,
2874
+ email: data.email,
2875
+ expiresAt: data.expiresAt,
2876
+ deviceLimit: limits.devices,
2877
+ employeeLimit: limits.employees,
2878
+ memoryLimit: limits.memories
2879
+ };
2880
+ } catch {
2881
+ return null;
2882
+ }
2883
+ }
2884
+ async function validateLicense(apiKey, deviceId) {
2885
+ const did = deviceId ?? loadDeviceId();
2886
+ const pgResult = await validateViaPostgres(apiKey);
2887
+ if (pgResult) {
2888
+ try {
2889
+ writeFileSync4(CACHE_PATH, JSON.stringify({ pgLicense: pgResult, ts: Date.now() }), "utf8");
2890
+ } catch {
2891
+ }
2892
+ return pgResult;
2893
+ }
2894
+ const cfResult = await validateViaCFWorker(apiKey, did);
2895
+ if (cfResult) return cfResult;
2896
+ const cached = await getCachedLicense();
2897
+ if (cached) return cached;
2898
+ try {
2899
+ if (existsSync6(CACHE_PATH)) {
2900
+ const raw = JSON.parse(readFileSync5(CACHE_PATH, "utf8"));
2901
+ if (raw.pgLicense && raw.ts && Date.now() - raw.ts < 7 * 24 * 60 * 60 * 1e3) {
2902
+ return raw.pgLicense;
2574
2903
  }
2575
- const limits = PLAN_LIMITS[data.plan] ?? PLAN_LIMITS.free;
2576
- return {
2577
- valid: data.valid,
2578
- plan: data.plan,
2579
- email: data.email,
2580
- expiresAt: data.expiresAt,
2581
- deviceLimit: limits.devices,
2582
- employeeLimit: limits.employees,
2583
- memoryLimit: limits.memories
2584
- };
2585
2904
  }
2586
- const cached = await getCachedLicense();
2587
- if (cached) return cached;
2588
- const raw = getRawCachedPlan();
2589
- if (raw) return raw;
2590
- return { ...FREE_LICENSE, valid: false, plan: "free" };
2591
2905
  } catch {
2592
- const cached = await getCachedLicense();
2593
- if (cached) return cached;
2594
- const rawFallback = getRawCachedPlan();
2595
- if (rawFallback) return rawFallback;
2596
- return { ...FREE_LICENSE, valid: false, error: "offline" };
2597
2906
  }
2907
+ const rawFallback = getRawCachedPlan();
2908
+ if (rawFallback) return rawFallback;
2909
+ return { ...FREE_LICENSE, valid: false };
2598
2910
  }
2599
2911
  var CACHE_MAX_AGE_MS = 36e5;
2600
2912
  function getCacheAgeMs() {
@@ -2610,9 +2922,9 @@ async function checkLicense() {
2610
2922
  let key = loadLicense();
2611
2923
  if (!key) {
2612
2924
  try {
2613
- const configPath = path4.join(EXE_AI_DIR, "config.json");
2614
- if (existsSync4(configPath)) {
2615
- const raw = JSON.parse(readFileSync4(configPath, "utf8"));
2925
+ const configPath = path6.join(EXE_AI_DIR, "config.json");
2926
+ if (existsSync6(configPath)) {
2927
+ const raw = JSON.parse(readFileSync5(configPath, "utf8"));
2616
2928
  const cloud = raw.cloud;
2617
2929
  if (cloud?.apiKey) {
2618
2930
  key = cloud.apiKey;
@@ -2637,7 +2949,7 @@ var PlanLimitError = class extends Error {
2637
2949
  this.name = "PlanLimitError";
2638
2950
  }
2639
2951
  };
2640
- var CACHE_PATH2 = path5.join(EXE_AI_DIR, "license-cache.json");
2952
+ var CACHE_PATH2 = path7.join(EXE_AI_DIR, "license-cache.json");
2641
2953
  async function assertEmployeeLimit(license, rosterPath) {
2642
2954
  const lic = license ?? await checkLicense();
2643
2955
  if (lic.employeeLimit < 0) return;
@@ -2671,7 +2983,6 @@ async function main() {
2671
2983
  console.error(`Invalid name: ${validation.error}`);
2672
2984
  process.exit(1);
2673
2985
  }
2674
- const employees = await loadEmployees();
2675
2986
  let newEmployee;
2676
2987
  const effectiveTemplate = templateName ?? name;
2677
2988
  const template = getTemplate(effectiveTemplate);
@@ -2709,14 +3020,12 @@ async function main() {
2709
3020
  }
2710
3021
  throw err;
2711
3022
  }
2712
- let updated;
2713
3023
  try {
2714
- updated = addEmployee(employees, newEmployee);
3024
+ await hireEmployee(newEmployee);
2715
3025
  } catch (err) {
2716
3026
  console.error(err instanceof Error ? err.message : String(err));
2717
3027
  process.exit(1);
2718
3028
  }
2719
- await saveEmployees(updated);
2720
3029
  try {
2721
3030
  const { getTemplate: getIdentityTemplate } = await Promise.resolve().then(() => (init_identity_templates(), identity_templates_exports));
2722
3031
  const { identityPath: identityPath2 } = await Promise.resolve().then(() => (init_identity(), identity_exports));
@@ -2733,7 +3042,7 @@ async function main() {
2733
3042
  const identityTemplate = templateKey ? getIdentityTemplate(templateKey) : null;
2734
3043
  if (identityTemplate) {
2735
3044
  const idPath = identityPath2(name);
2736
- const dir = path10.dirname(idPath);
3045
+ const dir = path12.dirname(idPath);
2737
3046
  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
2738
3047
  const content = identityTemplate.replace(/^agent_id: \w+/m, `agent_id: ${name}`);
2739
3048
  fs.writeFileSync(idPath, content, "utf-8");
@@ -2741,8 +3050,8 @@ async function main() {
2741
3050
  }
2742
3051
  } catch {
2743
3052
  }
2744
- const taskDir = path10.join(process.cwd(), "exe", name);
2745
- if (!existsSync10(taskDir)) {
3053
+ const taskDir = path12.join(process.cwd(), "exe", name);
3054
+ if (!existsSync12(taskDir)) {
2746
3055
  mkdirSync7(taskDir, { recursive: true });
2747
3056
  }
2748
3057
  const bins = registerBinSymlinks(newEmployee.name);