@askexenow/exe-os 0.8.80 → 0.8.82

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 (110) hide show
  1. package/dist/bin/backfill-conversations.js +359 -267
  2. package/dist/bin/backfill-responses.js +357 -265
  3. package/dist/bin/backfill-vectors.js +339 -264
  4. package/dist/bin/cleanup-stale-review-tasks.js +315 -256
  5. package/dist/bin/cli.js +494 -240
  6. package/dist/bin/exe-agent.js +141 -46
  7. package/dist/bin/exe-assign.js +151 -63
  8. package/dist/bin/exe-boot.js +294 -115
  9. package/dist/bin/exe-call.js +76 -51
  10. package/dist/bin/exe-cloud.js +58 -45
  11. package/dist/bin/exe-dispatch.js +434 -277
  12. package/dist/bin/exe-doctor.js +317 -246
  13. package/dist/bin/exe-export-behaviors.js +328 -248
  14. package/dist/bin/exe-forget.js +314 -231
  15. package/dist/bin/exe-gateway.js +2676 -1402
  16. package/dist/bin/exe-heartbeat.js +329 -264
  17. package/dist/bin/exe-kill.js +324 -244
  18. package/dist/bin/exe-launch-agent.js +574 -463
  19. package/dist/bin/exe-link.js +1055 -95
  20. package/dist/bin/exe-new-employee.js +49 -54
  21. package/dist/bin/exe-pending-messages.js +310 -253
  22. package/dist/bin/exe-pending-notifications.js +299 -228
  23. package/dist/bin/exe-pending-reviews.js +314 -245
  24. package/dist/bin/exe-rename.js +259 -195
  25. package/dist/bin/exe-review.js +140 -64
  26. package/dist/bin/exe-search.js +543 -356
  27. package/dist/bin/exe-session-cleanup.js +463 -382
  28. package/dist/bin/exe-settings.js +129 -99
  29. package/dist/bin/exe-start.sh +6 -6
  30. package/dist/bin/exe-status.js +95 -36
  31. package/dist/bin/exe-team.js +116 -51
  32. package/dist/bin/git-sweep.js +482 -307
  33. package/dist/bin/graph-backfill.js +357 -245
  34. package/dist/bin/graph-export.js +324 -244
  35. package/dist/bin/install.js +33 -10
  36. package/dist/bin/scan-tasks.js +481 -307
  37. package/dist/bin/setup.js +1147 -140
  38. package/dist/bin/shard-migrate.js +321 -241
  39. package/dist/bin/update.js +1 -7
  40. package/dist/bin/wiki-sync.js +318 -238
  41. package/dist/gateway/index.js +2656 -1383
  42. package/dist/hooks/bug-report-worker.js +641 -472
  43. package/dist/hooks/commit-complete.js +482 -307
  44. package/dist/hooks/error-recall.js +363 -135
  45. package/dist/hooks/exe-heartbeat-hook.js +97 -27
  46. package/dist/hooks/ingest-worker.js +584 -397
  47. package/dist/hooks/ingest.js +123 -58
  48. package/dist/hooks/instructions-loaded.js +212 -82
  49. package/dist/hooks/notification.js +200 -70
  50. package/dist/hooks/post-compact.js +199 -81
  51. package/dist/hooks/pre-compact.js +352 -140
  52. package/dist/hooks/pre-tool-use.js +416 -278
  53. package/dist/hooks/prompt-ingest-worker.js +376 -299
  54. package/dist/hooks/prompt-submit.js +414 -188
  55. package/dist/hooks/response-ingest-worker.js +408 -338
  56. package/dist/hooks/session-end.js +209 -83
  57. package/dist/hooks/session-start.js +382 -158
  58. package/dist/hooks/stop.js +209 -83
  59. package/dist/hooks/subagent-stop.js +209 -85
  60. package/dist/hooks/summary-worker.js +606 -510
  61. package/dist/index.js +2133 -855
  62. package/dist/lib/cloud-sync.js +1175 -184
  63. package/dist/lib/config.js +1 -9
  64. package/dist/lib/consolidation.js +71 -34
  65. package/dist/lib/database.js +166 -14
  66. package/dist/lib/device-registry.js +189 -117
  67. package/dist/lib/embedder.js +6 -10
  68. package/dist/lib/employee-templates.js +134 -39
  69. package/dist/lib/employees.js +30 -7
  70. package/dist/lib/exe-daemon-client.js +5 -7
  71. package/dist/lib/exe-daemon.js +514 -152
  72. package/dist/lib/hybrid-search.js +543 -356
  73. package/dist/lib/identity-templates.js +15 -15
  74. package/dist/lib/identity.js +19 -15
  75. package/dist/lib/license.js +1 -7
  76. package/dist/lib/messaging.js +157 -135
  77. package/dist/lib/reminders.js +97 -0
  78. package/dist/lib/schedules.js +302 -231
  79. package/dist/lib/skill-learning.js +33 -27
  80. package/dist/lib/status-brief.js +11 -14
  81. package/dist/lib/store.js +326 -237
  82. package/dist/lib/task-router.js +105 -1
  83. package/dist/lib/tasks.js +233 -116
  84. package/dist/lib/tmux-routing.js +173 -56
  85. package/dist/lib/ws-client.js +13 -3
  86. package/dist/mcp/server.js +2009 -1015
  87. package/dist/mcp/tools/complete-reminder.js +97 -0
  88. package/dist/mcp/tools/create-reminder.js +97 -0
  89. package/dist/mcp/tools/create-task.js +426 -262
  90. package/dist/mcp/tools/deactivate-behavior.js +119 -44
  91. package/dist/mcp/tools/list-reminders.js +97 -0
  92. package/dist/mcp/tools/list-tasks.js +56 -57
  93. package/dist/mcp/tools/send-message.js +206 -143
  94. package/dist/mcp/tools/update-task.js +259 -85
  95. package/dist/runtime/index.js +495 -316
  96. package/dist/tui/App.js +1128 -919
  97. package/package.json +2 -10
  98. package/src/commands/exe/afk.md +8 -8
  99. package/src/commands/exe/assign.md +1 -1
  100. package/src/commands/exe/build-adv.md +1 -1
  101. package/src/commands/exe/call.md +10 -10
  102. package/src/commands/exe/employee-heartbeat.md +9 -6
  103. package/src/commands/exe/heartbeat.md +5 -5
  104. package/src/commands/exe/intercom.md +26 -15
  105. package/src/commands/exe/launch.md +2 -2
  106. package/src/commands/exe/new-employee.md +1 -1
  107. package/src/commands/exe/review.md +2 -2
  108. package/src/commands/exe/schedule.md +1 -1
  109. package/src/commands/exe/sessions.md +2 -2
  110. package/src/commands/exe.md +22 -20
@@ -6,28 +6,13 @@ import crypto from "crypto";
6
6
 
7
7
  // src/lib/database.ts
8
8
  import { createClient } from "@libsql/client";
9
- var _resilientClient = null;
10
- function getClient() {
11
- if (!_resilientClient) {
12
- throw new Error("Database client not initialized. Call initDatabase() first.");
13
- }
14
- return _resilientClient;
15
- }
16
-
17
- // src/lib/behaviors.ts
18
- async function deactivateBehavior(id) {
19
- const client = getClient();
20
- const result = await client.execute({
21
- sql: `UPDATE behaviors SET active = 0, updated_at = ? WHERE id = ? AND active = 1`,
22
- args: [(/* @__PURE__ */ new Date()).toISOString(), id]
23
- });
24
- return (result.rowsAffected ?? 0) > 0;
25
- }
26
9
 
27
- // src/adapters/claude/active-agent.ts
28
- import { readFileSync as readFileSync2, writeFileSync, mkdirSync, unlinkSync, readdirSync } from "fs";
29
- import { execSync as execSync2 } from "child_process";
10
+ // src/lib/employees.ts
11
+ import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
12
+ import { existsSync as existsSync2, symlinkSync, readlinkSync, readFileSync as readFileSync2, renameSync as renameSync2, unlinkSync, writeFileSync } from "fs";
13
+ import { execSync } from "child_process";
30
14
  import path2 from "path";
15
+ import os2 from "os";
31
16
 
32
17
  // src/lib/config.ts
33
18
  import { readFile, writeFile, mkdir, chmod } from "fs/promises";
@@ -89,13 +74,7 @@ var DEFAULT_CONFIG = {
89
74
  wikiUrl: "",
90
75
  wikiApiKey: "",
91
76
  wikiSyncIntervalMs: 30 * 60 * 1e3,
92
- wikiWorkspaceMapping: {
93
- exe: "Executive",
94
- yoshi: "Engineering",
95
- mari: "Marketing",
96
- tom: "Engineering",
97
- sasha: "Production"
98
- },
77
+ wikiWorkspaceMapping: {},
99
78
  wikiAutoUpdate: true,
100
79
  wikiAutoUpdateThreshold: 0.5,
101
80
  wikiAutoUpdateCreateNew: true,
@@ -120,15 +99,74 @@ var DEFAULT_CONFIG = {
120
99
  }
121
100
  };
122
101
 
102
+ // src/lib/employees.ts
103
+ var EMPLOYEES_PATH = path2.join(EXE_AI_DIR, "exe-employees.json");
104
+ var DEFAULT_COORDINATOR_TEMPLATE_NAME = "exe";
105
+ var COORDINATOR_ROLE = "COO";
106
+ function normalizeRole(role) {
107
+ return (role ?? "").trim().toLowerCase();
108
+ }
109
+ function isCoordinatorRole(role) {
110
+ return normalizeRole(role) === normalizeRole(COORDINATOR_ROLE);
111
+ }
112
+ function getCoordinatorEmployee(employees) {
113
+ return employees.find((e) => isCoordinatorRole(e.role));
114
+ }
115
+ function getCoordinatorName(employees = loadEmployeesSync()) {
116
+ return getCoordinatorEmployee(employees)?.name ?? DEFAULT_COORDINATOR_TEMPLATE_NAME;
117
+ }
118
+ function isCoordinatorName(agentName, employees = loadEmployeesSync()) {
119
+ if (!agentName) return false;
120
+ return agentName.toLowerCase() === getCoordinatorName(employees).toLowerCase();
121
+ }
122
+ function canCoordinate(agentName, agentRole, employees = loadEmployeesSync()) {
123
+ return agentName === "default" || isCoordinatorRole(agentRole) || isCoordinatorName(agentName, employees);
124
+ }
125
+ function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
126
+ if (!existsSync2(employeesPath)) return [];
127
+ try {
128
+ return JSON.parse(readFileSync2(employeesPath, "utf-8"));
129
+ } catch {
130
+ return [];
131
+ }
132
+ }
133
+ function getEmployee(employees, name) {
134
+ return employees.find((e) => e.name.toLowerCase() === name.toLowerCase());
135
+ }
136
+
137
+ // src/lib/database.ts
138
+ var _resilientClient = null;
139
+ function getClient() {
140
+ if (!_resilientClient) {
141
+ throw new Error("Database client not initialized. Call initDatabase() first.");
142
+ }
143
+ return _resilientClient;
144
+ }
145
+
146
+ // src/lib/behaviors.ts
147
+ async function deactivateBehavior(id) {
148
+ const client = getClient();
149
+ const result = await client.execute({
150
+ sql: `UPDATE behaviors SET active = 0, updated_at = ? WHERE id = ? AND active = 1`,
151
+ args: [(/* @__PURE__ */ new Date()).toISOString(), id]
152
+ });
153
+ return (result.rowsAffected ?? 0) > 0;
154
+ }
155
+
156
+ // src/adapters/claude/active-agent.ts
157
+ import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync, unlinkSync as unlinkSync2, readdirSync } from "fs";
158
+ import { execSync as execSync3 } from "child_process";
159
+ import path3 from "path";
160
+
123
161
  // src/lib/session-key.ts
124
- import { execSync } from "child_process";
162
+ import { execSync as execSync2 } from "child_process";
125
163
  var _cached = null;
126
164
  function getSessionKey() {
127
165
  if (_cached) return _cached;
128
166
  let pid = process.ppid;
129
167
  for (let i = 0; i < 10; i++) {
130
168
  try {
131
- const info = execSync(`ps -p ${pid} -o ppid=,comm=`, {
169
+ const info = execSync2(`ps -p ${pid} -o ppid=,comm=`, {
132
170
  encoding: "utf8",
133
171
  timeout: 2e3
134
172
  }).trim();
@@ -150,22 +188,64 @@ function getSessionKey() {
150
188
  }
151
189
 
152
190
  // src/adapters/claude/active-agent.ts
153
- var CACHE_DIR = path2.join(EXE_AI_DIR, "session-cache");
191
+ var CACHE_DIR = path3.join(EXE_AI_DIR, "session-cache");
154
192
  var STALE_MS = 24 * 60 * 60 * 1e3;
193
+ function isNameWithOptionalInstance(candidate, baseName) {
194
+ if (candidate === baseName) return true;
195
+ if (!candidate.startsWith(baseName)) return false;
196
+ return /^\d+$/.test(candidate.slice(baseName.length));
197
+ }
198
+ function resolveEmployeeFromSessionPrefix(prefix, employees) {
199
+ const sorted = [...employees].sort((a, b) => b.name.length - a.name.length);
200
+ for (const employee of sorted) {
201
+ if (isNameWithOptionalInstance(prefix, employee.name)) {
202
+ return { agentId: employee.name, agentRole: employee.role };
203
+ }
204
+ }
205
+ return null;
206
+ }
207
+ function resolveActiveAgentFromTmuxSession(sessionName) {
208
+ const employees = loadEmployeesSync();
209
+ const coordinator = getCoordinatorEmployee(employees);
210
+ const coordinatorName = coordinator?.name ?? DEFAULT_COORDINATOR_TEMPLATE_NAME;
211
+ if (isNameWithOptionalInstance(sessionName, coordinatorName)) {
212
+ return {
213
+ agentId: coordinatorName,
214
+ agentRole: coordinator?.role ?? "COO"
215
+ };
216
+ }
217
+ if (isNameWithOptionalInstance(sessionName, DEFAULT_COORDINATOR_TEMPLATE_NAME)) {
218
+ return {
219
+ agentId: coordinator?.name ?? DEFAULT_COORDINATOR_TEMPLATE_NAME,
220
+ agentRole: coordinator?.role ?? "COO"
221
+ };
222
+ }
223
+ if (sessionName.includes("-")) {
224
+ const prefix = sessionName.split("-")[0] ?? "";
225
+ const employee = resolveEmployeeFromSessionPrefix(prefix, employees);
226
+ if (employee) return employee;
227
+ const legacy = prefix.match(/^([a-zA-Z]+)\d*$/);
228
+ if (legacy?.[1] && legacy[1] !== DEFAULT_COORDINATOR_TEMPLATE_NAME) {
229
+ const emp = getEmployee(employees, legacy[1]);
230
+ return { agentId: emp?.name ?? legacy[1], agentRole: emp?.role ?? "employee" };
231
+ }
232
+ }
233
+ return null;
234
+ }
155
235
  function getMarkerPath() {
156
- return path2.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
236
+ return path3.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
157
237
  }
158
238
  function getActiveAgent() {
159
239
  try {
160
240
  const markerPath = getMarkerPath();
161
- const raw = readFileSync2(markerPath, "utf8");
241
+ const raw = readFileSync3(markerPath, "utf8");
162
242
  const data = JSON.parse(raw);
163
243
  if (data.agentId) {
164
244
  if (data.startedAt) {
165
245
  const age = Date.now() - new Date(data.startedAt).getTime();
166
246
  if (age > STALE_MS) {
167
247
  try {
168
- unlinkSync(markerPath);
248
+ unlinkSync2(markerPath);
169
249
  } catch {
170
250
  }
171
251
  } else {
@@ -184,17 +264,12 @@ function getActiveAgent() {
184
264
  } catch {
185
265
  }
186
266
  try {
187
- const sessionName = execSync2(
267
+ const sessionName = execSync3(
188
268
  "tmux display-message -p '#{session_name}' 2>/dev/null",
189
269
  { encoding: "utf8", timeout: 2e3 }
190
270
  ).trim();
191
- const empMatch = sessionName.match(/^([a-zA-Z]+)\d*-exe\d+$/);
192
- if (empMatch && empMatch[1] !== "exe") {
193
- return { agentId: empMatch[1], agentRole: "employee" };
194
- }
195
- if (/^exe\d+$/.test(sessionName)) {
196
- return { agentId: "exe", agentRole: "COO" };
197
- }
271
+ const resolved = resolveActiveAgentFromTmuxSession(sessionName);
272
+ if (resolved) return resolved;
198
273
  } catch {
199
274
  }
200
275
  return {
@@ -209,19 +284,19 @@ function registerDeactivateBehavior(server) {
209
284
  "deactivate_behavior",
210
285
  {
211
286
  title: "Deactivate Behavior",
212
- description: "Soft-delete a behavior by setting active = 0. RESTRICTED: only exe or founder sessions can use this. Use list_behaviors to find the behavior ID first.",
287
+ description: "Soft-delete a behavior by setting active = 0. RESTRICTED: only coordinator or founder sessions can use this. Use list_behaviors to find the behavior ID first.",
213
288
  inputSchema: {
214
289
  behavior_id: z.string().describe("UUID of the behavior to deactivate")
215
290
  }
216
291
  },
217
292
  async ({ behavior_id }) => {
218
293
  const caller = getActiveAgent();
219
- const allowed = caller.agentId === "default" || caller.agentRole === "COO";
294
+ const allowed = canCoordinate(caller.agentId, caller.agentRole);
220
295
  if (!allowed) {
221
296
  return {
222
297
  content: [{
223
298
  type: "text",
224
- text: `Permission denied. Only exe or founder sessions can deactivate behaviors. You are "${caller.agentId}".`
299
+ text: `Permission denied. Only the coordinator or founder sessions can deactivate behaviors. You are "${caller.agentId}".`
225
300
  }],
226
301
  isError: true
227
302
  };
@@ -6,6 +6,103 @@ import crypto from "crypto";
6
6
 
7
7
  // src/lib/database.ts
8
8
  import { createClient } from "@libsql/client";
9
+
10
+ // src/lib/employees.ts
11
+ import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
12
+ import { existsSync as existsSync2, symlinkSync, readlinkSync, readFileSync as readFileSync2, renameSync as renameSync2, unlinkSync, writeFileSync } from "fs";
13
+ import { execSync } from "child_process";
14
+ import path2 from "path";
15
+ import os2 from "os";
16
+
17
+ // src/lib/config.ts
18
+ import { readFile, writeFile, mkdir, chmod } from "fs/promises";
19
+ import { readFileSync, existsSync, renameSync } from "fs";
20
+ import path from "path";
21
+ import os from "os";
22
+ function resolveDataDir() {
23
+ if (process.env.EXE_OS_DIR) return process.env.EXE_OS_DIR;
24
+ if (process.env.EXE_MEM_DIR) return process.env.EXE_MEM_DIR;
25
+ const newDir = path.join(os.homedir(), ".exe-os");
26
+ const legacyDir = path.join(os.homedir(), ".exe-mem");
27
+ if (!existsSync(newDir) && existsSync(legacyDir)) {
28
+ try {
29
+ renameSync(legacyDir, newDir);
30
+ process.stderr.write(`[exe-os] Migrated data directory: ~/.exe-mem \u2192 ~/.exe-os
31
+ `);
32
+ } catch {
33
+ return legacyDir;
34
+ }
35
+ }
36
+ return newDir;
37
+ }
38
+ var EXE_AI_DIR = resolveDataDir();
39
+ var DB_PATH = path.join(EXE_AI_DIR, "memories.db");
40
+ var MODELS_DIR = path.join(EXE_AI_DIR, "models");
41
+ var CONFIG_PATH = path.join(EXE_AI_DIR, "config.json");
42
+ var LEGACY_LANCE_PATH = path.join(EXE_AI_DIR, "local.lance");
43
+ var CURRENT_CONFIG_VERSION = 1;
44
+ var DEFAULT_CONFIG = {
45
+ config_version: CURRENT_CONFIG_VERSION,
46
+ dbPath: DB_PATH,
47
+ modelFile: "jina-embeddings-v5-small-q4_k_m.gguf",
48
+ embeddingDim: 1024,
49
+ batchSize: 20,
50
+ flushIntervalMs: 1e4,
51
+ autoIngestion: true,
52
+ autoRetrieval: true,
53
+ searchMode: "hybrid",
54
+ hookSearchMode: "hybrid",
55
+ fileGrepEnabled: true,
56
+ splashEffect: true,
57
+ consolidationEnabled: true,
58
+ consolidationIntervalMs: 6 * 60 * 60 * 1e3,
59
+ consolidationModel: "claude-haiku-4-5-20251001",
60
+ consolidationMaxCallsPerRun: 20,
61
+ selfQueryRouter: true,
62
+ selfQueryModel: "claude-haiku-4-5-20251001",
63
+ rerankerEnabled: true,
64
+ scalingRoadmap: {
65
+ rerankerAutoTrigger: {
66
+ enabled: true,
67
+ broadQueryMinCardinality: 5e4,
68
+ fetchTopK: 150,
69
+ returnTopK: 5
70
+ }
71
+ },
72
+ graphRagEnabled: true,
73
+ wikiEnabled: false,
74
+ wikiUrl: "",
75
+ wikiApiKey: "",
76
+ wikiSyncIntervalMs: 30 * 60 * 1e3,
77
+ wikiWorkspaceMapping: {},
78
+ wikiAutoUpdate: true,
79
+ wikiAutoUpdateThreshold: 0.5,
80
+ wikiAutoUpdateCreateNew: true,
81
+ skillLearning: true,
82
+ skillThreshold: 3,
83
+ skillModel: "claude-haiku-4-5-20251001",
84
+ exeHeartbeat: {
85
+ enabled: true,
86
+ intervalSeconds: 60,
87
+ staleInProgressThresholdHours: 2
88
+ },
89
+ sessionLifecycle: {
90
+ idleKillEnabled: true,
91
+ idleKillTicksRequired: 3,
92
+ idleKillIntercomAckWindowMs: 1e4,
93
+ maxAutoInstances: 10
94
+ },
95
+ autoUpdate: {
96
+ checkOnBoot: true,
97
+ autoInstall: false,
98
+ checkIntervalMs: 24 * 60 * 60 * 1e3
99
+ }
100
+ };
101
+
102
+ // src/lib/employees.ts
103
+ var EMPLOYEES_PATH = path2.join(EXE_AI_DIR, "exe-employees.json");
104
+
105
+ // src/lib/database.ts
9
106
  var _resilientClient = null;
10
107
  function getClient() {
11
108
  if (!_resilientClient) {
@@ -26,23 +26,6 @@ var init_db_retry = __esm({
26
26
  }
27
27
  });
28
28
 
29
- // src/lib/database.ts
30
- import { createClient } from "@libsql/client";
31
- function getClient() {
32
- if (!_resilientClient) {
33
- throw new Error("Database client not initialized. Call initDatabase() first.");
34
- }
35
- return _resilientClient;
36
- }
37
- var _resilientClient;
38
- var init_database = __esm({
39
- "src/lib/database.ts"() {
40
- "use strict";
41
- init_db_retry();
42
- _resilientClient = null;
43
- }
44
- });
45
-
46
29
  // src/lib/config.ts
47
30
  import { readFile, writeFile, mkdir, chmod } from "fs/promises";
48
31
  import { readFileSync, existsSync, renameSync } from "fs";
@@ -107,13 +90,7 @@ var init_config = __esm({
107
90
  wikiUrl: "",
108
91
  wikiApiKey: "",
109
92
  wikiSyncIntervalMs: 30 * 60 * 1e3,
110
- wikiWorkspaceMapping: {
111
- exe: "Executive",
112
- yoshi: "Engineering",
113
- mari: "Marketing",
114
- tom: "Engineering",
115
- sasha: "Production"
116
- },
93
+ wikiWorkspaceMapping: {},
117
94
  wikiAutoUpdate: true,
118
95
  wikiAutoUpdateThreshold: 0.5,
119
96
  wikiAutoUpdateCreateNew: true,
@@ -140,15 +117,48 @@ var init_config = __esm({
140
117
  }
141
118
  });
142
119
 
143
- // src/lib/notifications.ts
144
- import crypto from "crypto";
120
+ // src/lib/employees.ts
121
+ import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
122
+ import { existsSync as existsSync2, symlinkSync, readlinkSync, readFileSync as readFileSync2, renameSync as renameSync2, unlinkSync, writeFileSync } from "fs";
123
+ import { execSync } from "child_process";
145
124
  import path2 from "path";
146
125
  import os2 from "os";
126
+ var EMPLOYEES_PATH;
127
+ var init_employees = __esm({
128
+ "src/lib/employees.ts"() {
129
+ "use strict";
130
+ init_config();
131
+ EMPLOYEES_PATH = path2.join(EXE_AI_DIR, "exe-employees.json");
132
+ }
133
+ });
134
+
135
+ // src/lib/database.ts
136
+ import { createClient } from "@libsql/client";
137
+ function getClient() {
138
+ if (!_resilientClient) {
139
+ throw new Error("Database client not initialized. Call initDatabase() first.");
140
+ }
141
+ return _resilientClient;
142
+ }
143
+ var _resilientClient;
144
+ var init_database = __esm({
145
+ "src/lib/database.ts"() {
146
+ "use strict";
147
+ init_db_retry();
148
+ init_employees();
149
+ _resilientClient = null;
150
+ }
151
+ });
152
+
153
+ // src/lib/notifications.ts
154
+ import crypto from "crypto";
155
+ import path3 from "path";
156
+ import os3 from "os";
147
157
  import {
148
- readFileSync as readFileSync2,
158
+ readFileSync as readFileSync3,
149
159
  readdirSync,
150
- unlinkSync,
151
- existsSync as existsSync2,
160
+ unlinkSync as unlinkSync2,
161
+ existsSync as existsSync3,
152
162
  rmdirSync
153
163
  } from "fs";
154
164
  var init_notifications = __esm({
@@ -214,24 +224,24 @@ var init_state_bus = __esm({
214
224
  });
215
225
 
216
226
  // src/lib/session-registry.ts
217
- import path3 from "path";
218
- import os3 from "os";
227
+ import path4 from "path";
228
+ import os4 from "os";
219
229
  var REGISTRY_PATH;
220
230
  var init_session_registry = __esm({
221
231
  "src/lib/session-registry.ts"() {
222
232
  "use strict";
223
- REGISTRY_PATH = path3.join(os3.homedir(), ".exe-os", "session-registry.json");
233
+ REGISTRY_PATH = path4.join(os4.homedir(), ".exe-os", "session-registry.json");
224
234
  }
225
235
  });
226
236
 
227
237
  // src/lib/session-key.ts
228
- import { execSync } from "child_process";
238
+ import { execSync as execSync2 } from "child_process";
229
239
  function getSessionKey() {
230
240
  if (_cached) return _cached;
231
241
  let pid = process.ppid;
232
242
  for (let i = 0; i < 10; i++) {
233
243
  try {
234
- const info = execSync(`ps -p ${pid} -o ppid=,comm=`, {
244
+ const info = execSync2(`ps -p ${pid} -o ppid=,comm=`, {
235
245
  encoding: "utf8",
236
246
  timeout: 2e3
237
247
  }).trim();
@@ -367,7 +377,7 @@ var init_transport = __esm({
367
377
  });
368
378
 
369
379
  // src/lib/cc-agent-support.ts
370
- import { execSync as execSync2 } from "child_process";
380
+ import { execSync as execSync3 } from "child_process";
371
381
  var init_cc_agent_support = __esm({
372
382
  "src/lib/cc-agent-support.ts"() {
373
383
  "use strict";
@@ -396,31 +406,16 @@ var init_provider_table = __esm({
396
406
  });
397
407
 
398
408
  // src/lib/intercom-queue.ts
399
- import { readFileSync as readFileSync3, writeFileSync, renameSync as renameSync2, existsSync as existsSync3, mkdirSync } from "fs";
400
- import path4 from "path";
401
- import os4 from "os";
409
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, renameSync as renameSync3, existsSync as existsSync4, mkdirSync } from "fs";
410
+ import path5 from "path";
411
+ import os5 from "os";
402
412
  var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
403
413
  var init_intercom_queue = __esm({
404
414
  "src/lib/intercom-queue.ts"() {
405
415
  "use strict";
406
- QUEUE_PATH = path4.join(os4.homedir(), ".exe-os", "intercom-queue.json");
416
+ QUEUE_PATH = path5.join(os5.homedir(), ".exe-os", "intercom-queue.json");
407
417
  TTL_MS = 60 * 60 * 1e3;
408
- INTERCOM_LOG = path4.join(os4.homedir(), ".exe-os", "intercom.log");
409
- }
410
- });
411
-
412
- // src/lib/employees.ts
413
- import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
414
- import { existsSync as existsSync4, symlinkSync, readlinkSync, readFileSync as readFileSync4, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2 } from "fs";
415
- import { execSync as execSync3 } from "child_process";
416
- import path5 from "path";
417
- import os5 from "os";
418
- var EMPLOYEES_PATH;
419
- var init_employees = __esm({
420
- "src/lib/employees.ts"() {
421
- "use strict";
422
- init_config();
423
- EMPLOYEES_PATH = path5.join(EXE_AI_DIR, "exe-employees.json");
418
+ INTERCOM_LOG = path5.join(os5.homedir(), ".exe-os", "intercom.log");
424
419
  }
425
420
  });
426
421
 
@@ -464,8 +459,10 @@ function getMySession() {
464
459
  return getTransport().getMySession();
465
460
  }
466
461
  function extractRootExe(name) {
467
- const match = name.match(/(exe\d+)$/);
468
- return match?.[1] ?? null;
462
+ if (!name) return null;
463
+ if (!name.includes("-")) return name;
464
+ const parts = name.split("-").filter(Boolean);
465
+ return parts.length > 0 ? parts[parts.length - 1] : null;
469
466
  }
470
467
  function getParentExe(sessionKey) {
471
468
  try {
@@ -500,6 +497,7 @@ var init_tmux_routing = __esm({
500
497
  init_provider_table();
501
498
  init_intercom_queue();
502
499
  init_plan_limits();
500
+ init_employees();
503
501
  SPAWN_LOCK_DIR = path8.join(os6.homedir(), ".exe-os", "spawn-locks");
504
502
  SESSION_CACHE = path8.join(os6.homedir(), ".exe-os", "session-cache");
505
503
  INTERCOM_LOG2 = path8.join(os6.homedir(), ".exe-os", "intercom.log");
@@ -646,6 +644,7 @@ var init_tasks = __esm({
646
644
  init_config();
647
645
  init_notifications();
648
646
  init_state_bus();
647
+ init_employees();
649
648
  init_tasks_crud();
650
649
  init_tasks_review();
651
650
  init_tasks_crud();