@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.
- package/dist/bin/backfill-conversations.js +359 -267
- package/dist/bin/backfill-responses.js +357 -265
- package/dist/bin/backfill-vectors.js +339 -264
- package/dist/bin/cleanup-stale-review-tasks.js +315 -256
- package/dist/bin/cli.js +494 -240
- package/dist/bin/exe-agent.js +141 -46
- package/dist/bin/exe-assign.js +151 -63
- package/dist/bin/exe-boot.js +294 -115
- package/dist/bin/exe-call.js +76 -51
- package/dist/bin/exe-cloud.js +58 -45
- package/dist/bin/exe-dispatch.js +434 -277
- package/dist/bin/exe-doctor.js +317 -246
- package/dist/bin/exe-export-behaviors.js +328 -248
- package/dist/bin/exe-forget.js +314 -231
- package/dist/bin/exe-gateway.js +2676 -1402
- package/dist/bin/exe-heartbeat.js +329 -264
- package/dist/bin/exe-kill.js +324 -244
- package/dist/bin/exe-launch-agent.js +574 -463
- package/dist/bin/exe-link.js +1055 -95
- package/dist/bin/exe-new-employee.js +49 -54
- package/dist/bin/exe-pending-messages.js +310 -253
- package/dist/bin/exe-pending-notifications.js +299 -228
- package/dist/bin/exe-pending-reviews.js +314 -245
- package/dist/bin/exe-rename.js +259 -195
- package/dist/bin/exe-review.js +140 -64
- package/dist/bin/exe-search.js +543 -356
- package/dist/bin/exe-session-cleanup.js +463 -382
- package/dist/bin/exe-settings.js +129 -99
- package/dist/bin/exe-start.sh +6 -6
- package/dist/bin/exe-status.js +95 -36
- package/dist/bin/exe-team.js +116 -51
- package/dist/bin/git-sweep.js +482 -307
- package/dist/bin/graph-backfill.js +357 -245
- package/dist/bin/graph-export.js +324 -244
- package/dist/bin/install.js +33 -10
- package/dist/bin/scan-tasks.js +481 -307
- package/dist/bin/setup.js +1147 -140
- package/dist/bin/shard-migrate.js +321 -241
- package/dist/bin/update.js +1 -7
- package/dist/bin/wiki-sync.js +318 -238
- package/dist/gateway/index.js +2656 -1383
- package/dist/hooks/bug-report-worker.js +641 -472
- package/dist/hooks/commit-complete.js +482 -307
- package/dist/hooks/error-recall.js +363 -135
- package/dist/hooks/exe-heartbeat-hook.js +97 -27
- package/dist/hooks/ingest-worker.js +584 -397
- package/dist/hooks/ingest.js +123 -58
- package/dist/hooks/instructions-loaded.js +212 -82
- package/dist/hooks/notification.js +200 -70
- package/dist/hooks/post-compact.js +199 -81
- package/dist/hooks/pre-compact.js +352 -140
- package/dist/hooks/pre-tool-use.js +416 -278
- package/dist/hooks/prompt-ingest-worker.js +376 -299
- package/dist/hooks/prompt-submit.js +414 -188
- package/dist/hooks/response-ingest-worker.js +408 -338
- package/dist/hooks/session-end.js +209 -83
- package/dist/hooks/session-start.js +382 -158
- package/dist/hooks/stop.js +209 -83
- package/dist/hooks/subagent-stop.js +209 -85
- package/dist/hooks/summary-worker.js +606 -510
- package/dist/index.js +2133 -855
- package/dist/lib/cloud-sync.js +1175 -184
- package/dist/lib/config.js +1 -9
- package/dist/lib/consolidation.js +71 -34
- package/dist/lib/database.js +166 -14
- package/dist/lib/device-registry.js +189 -117
- package/dist/lib/embedder.js +6 -10
- package/dist/lib/employee-templates.js +134 -39
- package/dist/lib/employees.js +30 -7
- package/dist/lib/exe-daemon-client.js +5 -7
- package/dist/lib/exe-daemon.js +514 -152
- package/dist/lib/hybrid-search.js +543 -356
- package/dist/lib/identity-templates.js +15 -15
- package/dist/lib/identity.js +19 -15
- package/dist/lib/license.js +1 -7
- package/dist/lib/messaging.js +157 -135
- package/dist/lib/reminders.js +97 -0
- package/dist/lib/schedules.js +302 -231
- package/dist/lib/skill-learning.js +33 -27
- package/dist/lib/status-brief.js +11 -14
- package/dist/lib/store.js +326 -237
- package/dist/lib/task-router.js +105 -1
- package/dist/lib/tasks.js +233 -116
- package/dist/lib/tmux-routing.js +173 -56
- package/dist/lib/ws-client.js +13 -3
- package/dist/mcp/server.js +2009 -1015
- package/dist/mcp/tools/complete-reminder.js +97 -0
- package/dist/mcp/tools/create-reminder.js +97 -0
- package/dist/mcp/tools/create-task.js +426 -262
- package/dist/mcp/tools/deactivate-behavior.js +119 -44
- package/dist/mcp/tools/list-reminders.js +97 -0
- package/dist/mcp/tools/list-tasks.js +56 -57
- package/dist/mcp/tools/send-message.js +206 -143
- package/dist/mcp/tools/update-task.js +259 -85
- package/dist/runtime/index.js +495 -316
- package/dist/tui/App.js +1128 -919
- package/package.json +2 -10
- package/src/commands/exe/afk.md +8 -8
- package/src/commands/exe/assign.md +1 -1
- package/src/commands/exe/build-adv.md +1 -1
- package/src/commands/exe/call.md +10 -10
- package/src/commands/exe/employee-heartbeat.md +9 -6
- package/src/commands/exe/heartbeat.md +5 -5
- package/src/commands/exe/intercom.md +26 -15
- package/src/commands/exe/launch.md +2 -2
- package/src/commands/exe/new-employee.md +1 -1
- package/src/commands/exe/review.md +2 -2
- package/src/commands/exe/schedule.md +1 -1
- package/src/commands/exe/sessions.md +2 -2
- package/src/commands/exe.md +22 -20
|
@@ -26,6 +26,137 @@ var init_db_retry = __esm({
|
|
|
26
26
|
}
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
+
// src/lib/config.ts
|
|
30
|
+
import { readFile, writeFile, mkdir, chmod } from "fs/promises";
|
|
31
|
+
import { readFileSync, existsSync, renameSync } from "fs";
|
|
32
|
+
import path from "path";
|
|
33
|
+
import os from "os";
|
|
34
|
+
function resolveDataDir() {
|
|
35
|
+
if (process.env.EXE_OS_DIR) return process.env.EXE_OS_DIR;
|
|
36
|
+
if (process.env.EXE_MEM_DIR) return process.env.EXE_MEM_DIR;
|
|
37
|
+
const newDir = path.join(os.homedir(), ".exe-os");
|
|
38
|
+
const legacyDir = path.join(os.homedir(), ".exe-mem");
|
|
39
|
+
if (!existsSync(newDir) && existsSync(legacyDir)) {
|
|
40
|
+
try {
|
|
41
|
+
renameSync(legacyDir, newDir);
|
|
42
|
+
process.stderr.write(`[exe-os] Migrated data directory: ~/.exe-mem \u2192 ~/.exe-os
|
|
43
|
+
`);
|
|
44
|
+
} catch {
|
|
45
|
+
return legacyDir;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return newDir;
|
|
49
|
+
}
|
|
50
|
+
var EXE_AI_DIR, DB_PATH, MODELS_DIR, CONFIG_PATH, LEGACY_LANCE_PATH, CURRENT_CONFIG_VERSION, DEFAULT_CONFIG;
|
|
51
|
+
var init_config = __esm({
|
|
52
|
+
"src/lib/config.ts"() {
|
|
53
|
+
"use strict";
|
|
54
|
+
EXE_AI_DIR = resolveDataDir();
|
|
55
|
+
DB_PATH = path.join(EXE_AI_DIR, "memories.db");
|
|
56
|
+
MODELS_DIR = path.join(EXE_AI_DIR, "models");
|
|
57
|
+
CONFIG_PATH = path.join(EXE_AI_DIR, "config.json");
|
|
58
|
+
LEGACY_LANCE_PATH = path.join(EXE_AI_DIR, "local.lance");
|
|
59
|
+
CURRENT_CONFIG_VERSION = 1;
|
|
60
|
+
DEFAULT_CONFIG = {
|
|
61
|
+
config_version: CURRENT_CONFIG_VERSION,
|
|
62
|
+
dbPath: DB_PATH,
|
|
63
|
+
modelFile: "jina-embeddings-v5-small-q4_k_m.gguf",
|
|
64
|
+
embeddingDim: 1024,
|
|
65
|
+
batchSize: 20,
|
|
66
|
+
flushIntervalMs: 1e4,
|
|
67
|
+
autoIngestion: true,
|
|
68
|
+
autoRetrieval: true,
|
|
69
|
+
searchMode: "hybrid",
|
|
70
|
+
hookSearchMode: "hybrid",
|
|
71
|
+
fileGrepEnabled: true,
|
|
72
|
+
splashEffect: true,
|
|
73
|
+
consolidationEnabled: true,
|
|
74
|
+
consolidationIntervalMs: 6 * 60 * 60 * 1e3,
|
|
75
|
+
consolidationModel: "claude-haiku-4-5-20251001",
|
|
76
|
+
consolidationMaxCallsPerRun: 20,
|
|
77
|
+
selfQueryRouter: true,
|
|
78
|
+
selfQueryModel: "claude-haiku-4-5-20251001",
|
|
79
|
+
rerankerEnabled: true,
|
|
80
|
+
scalingRoadmap: {
|
|
81
|
+
rerankerAutoTrigger: {
|
|
82
|
+
enabled: true,
|
|
83
|
+
broadQueryMinCardinality: 5e4,
|
|
84
|
+
fetchTopK: 150,
|
|
85
|
+
returnTopK: 5
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
graphRagEnabled: true,
|
|
89
|
+
wikiEnabled: false,
|
|
90
|
+
wikiUrl: "",
|
|
91
|
+
wikiApiKey: "",
|
|
92
|
+
wikiSyncIntervalMs: 30 * 60 * 1e3,
|
|
93
|
+
wikiWorkspaceMapping: {},
|
|
94
|
+
wikiAutoUpdate: true,
|
|
95
|
+
wikiAutoUpdateThreshold: 0.5,
|
|
96
|
+
wikiAutoUpdateCreateNew: true,
|
|
97
|
+
skillLearning: true,
|
|
98
|
+
skillThreshold: 3,
|
|
99
|
+
skillModel: "claude-haiku-4-5-20251001",
|
|
100
|
+
exeHeartbeat: {
|
|
101
|
+
enabled: true,
|
|
102
|
+
intervalSeconds: 60,
|
|
103
|
+
staleInProgressThresholdHours: 2
|
|
104
|
+
},
|
|
105
|
+
sessionLifecycle: {
|
|
106
|
+
idleKillEnabled: true,
|
|
107
|
+
idleKillTicksRequired: 3,
|
|
108
|
+
idleKillIntercomAckWindowMs: 1e4,
|
|
109
|
+
maxAutoInstances: 10
|
|
110
|
+
},
|
|
111
|
+
autoUpdate: {
|
|
112
|
+
checkOnBoot: true,
|
|
113
|
+
autoInstall: false,
|
|
114
|
+
checkIntervalMs: 24 * 60 * 60 * 1e3
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
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";
|
|
124
|
+
import path2 from "path";
|
|
125
|
+
import os2 from "os";
|
|
126
|
+
function normalizeRole(role) {
|
|
127
|
+
return (role ?? "").trim().toLowerCase();
|
|
128
|
+
}
|
|
129
|
+
function isCoordinatorRole(role) {
|
|
130
|
+
return normalizeRole(role) === normalizeRole(COORDINATOR_ROLE);
|
|
131
|
+
}
|
|
132
|
+
function getCoordinatorEmployee(employees) {
|
|
133
|
+
return employees.find((e) => isCoordinatorRole(e.role));
|
|
134
|
+
}
|
|
135
|
+
function getCoordinatorName(employees = loadEmployeesSync()) {
|
|
136
|
+
return getCoordinatorEmployee(employees)?.name ?? DEFAULT_COORDINATOR_TEMPLATE_NAME;
|
|
137
|
+
}
|
|
138
|
+
function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
|
|
139
|
+
if (!existsSync2(employeesPath)) return [];
|
|
140
|
+
try {
|
|
141
|
+
return JSON.parse(readFileSync2(employeesPath, "utf-8"));
|
|
142
|
+
} catch {
|
|
143
|
+
return [];
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function getEmployee(employees, name) {
|
|
147
|
+
return employees.find((e) => e.name.toLowerCase() === name.toLowerCase());
|
|
148
|
+
}
|
|
149
|
+
var EMPLOYEES_PATH, DEFAULT_COORDINATOR_TEMPLATE_NAME, COORDINATOR_ROLE;
|
|
150
|
+
var init_employees = __esm({
|
|
151
|
+
"src/lib/employees.ts"() {
|
|
152
|
+
"use strict";
|
|
153
|
+
init_config();
|
|
154
|
+
EMPLOYEES_PATH = path2.join(EXE_AI_DIR, "exe-employees.json");
|
|
155
|
+
DEFAULT_COORDINATOR_TEMPLATE_NAME = "exe";
|
|
156
|
+
COORDINATOR_ROLE = "COO";
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
|
|
29
160
|
// src/lib/database.ts
|
|
30
161
|
import { createClient } from "@libsql/client";
|
|
31
162
|
function getClient() {
|
|
@@ -39,29 +170,30 @@ var init_database = __esm({
|
|
|
39
170
|
"src/lib/database.ts"() {
|
|
40
171
|
"use strict";
|
|
41
172
|
init_db_retry();
|
|
173
|
+
init_employees();
|
|
42
174
|
_resilientClient = null;
|
|
43
175
|
}
|
|
44
176
|
});
|
|
45
177
|
|
|
46
178
|
// src/lib/session-registry.ts
|
|
47
|
-
import
|
|
48
|
-
import
|
|
179
|
+
import path3 from "path";
|
|
180
|
+
import os3 from "os";
|
|
49
181
|
var REGISTRY_PATH;
|
|
50
182
|
var init_session_registry = __esm({
|
|
51
183
|
"src/lib/session-registry.ts"() {
|
|
52
184
|
"use strict";
|
|
53
|
-
REGISTRY_PATH =
|
|
185
|
+
REGISTRY_PATH = path3.join(os3.homedir(), ".exe-os", "session-registry.json");
|
|
54
186
|
}
|
|
55
187
|
});
|
|
56
188
|
|
|
57
189
|
// src/lib/session-key.ts
|
|
58
|
-
import { execSync } from "child_process";
|
|
190
|
+
import { execSync as execSync2 } from "child_process";
|
|
59
191
|
function getSessionKey() {
|
|
60
192
|
if (_cached) return _cached;
|
|
61
193
|
let pid = process.ppid;
|
|
62
194
|
for (let i = 0; i < 10; i++) {
|
|
63
195
|
try {
|
|
64
|
-
const info =
|
|
196
|
+
const info = execSync2(`ps -p ${pid} -o ppid=,comm=`, {
|
|
65
197
|
encoding: "utf8",
|
|
66
198
|
timeout: 2e3
|
|
67
199
|
}).trim();
|
|
@@ -197,7 +329,7 @@ var init_transport = __esm({
|
|
|
197
329
|
});
|
|
198
330
|
|
|
199
331
|
// src/lib/cc-agent-support.ts
|
|
200
|
-
import { execSync as
|
|
332
|
+
import { execSync as execSync3 } from "child_process";
|
|
201
333
|
var init_cc_agent_support = __esm({
|
|
202
334
|
"src/lib/cc-agent-support.ts"() {
|
|
203
335
|
"use strict";
|
|
@@ -226,17 +358,17 @@ var init_provider_table = __esm({
|
|
|
226
358
|
});
|
|
227
359
|
|
|
228
360
|
// src/lib/intercom-queue.ts
|
|
229
|
-
import { readFileSync, writeFileSync, renameSync, existsSync, mkdirSync } from "fs";
|
|
230
|
-
import
|
|
231
|
-
import
|
|
361
|
+
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, renameSync as renameSync3, existsSync as existsSync3, mkdirSync } from "fs";
|
|
362
|
+
import path4 from "path";
|
|
363
|
+
import os4 from "os";
|
|
232
364
|
function ensureDir() {
|
|
233
|
-
const dir =
|
|
234
|
-
if (!
|
|
365
|
+
const dir = path4.dirname(QUEUE_PATH);
|
|
366
|
+
if (!existsSync3(dir)) mkdirSync(dir, { recursive: true });
|
|
235
367
|
}
|
|
236
368
|
function readQueue() {
|
|
237
369
|
try {
|
|
238
|
-
if (!
|
|
239
|
-
return JSON.parse(
|
|
370
|
+
if (!existsSync3(QUEUE_PATH)) return [];
|
|
371
|
+
return JSON.parse(readFileSync3(QUEUE_PATH, "utf8"));
|
|
240
372
|
} catch {
|
|
241
373
|
return [];
|
|
242
374
|
}
|
|
@@ -244,8 +376,8 @@ function readQueue() {
|
|
|
244
376
|
function writeQueue(queue) {
|
|
245
377
|
ensureDir();
|
|
246
378
|
const tmp = `${QUEUE_PATH}.tmp`;
|
|
247
|
-
|
|
248
|
-
|
|
379
|
+
writeFileSync2(tmp, JSON.stringify(queue, null, 2));
|
|
380
|
+
renameSync3(tmp, QUEUE_PATH);
|
|
249
381
|
}
|
|
250
382
|
function queueIntercom(targetSession, reason) {
|
|
251
383
|
const queue = readQueue();
|
|
@@ -268,121 +400,9 @@ var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
|
|
|
268
400
|
var init_intercom_queue = __esm({
|
|
269
401
|
"src/lib/intercom-queue.ts"() {
|
|
270
402
|
"use strict";
|
|
271
|
-
QUEUE_PATH =
|
|
403
|
+
QUEUE_PATH = path4.join(os4.homedir(), ".exe-os", "intercom-queue.json");
|
|
272
404
|
TTL_MS = 60 * 60 * 1e3;
|
|
273
|
-
INTERCOM_LOG =
|
|
274
|
-
}
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
// src/lib/config.ts
|
|
278
|
-
import { readFile, writeFile, mkdir, chmod } from "fs/promises";
|
|
279
|
-
import { readFileSync as readFileSync2, existsSync as existsSync2, renameSync as renameSync2 } from "fs";
|
|
280
|
-
import path3 from "path";
|
|
281
|
-
import os3 from "os";
|
|
282
|
-
function resolveDataDir() {
|
|
283
|
-
if (process.env.EXE_OS_DIR) return process.env.EXE_OS_DIR;
|
|
284
|
-
if (process.env.EXE_MEM_DIR) return process.env.EXE_MEM_DIR;
|
|
285
|
-
const newDir = path3.join(os3.homedir(), ".exe-os");
|
|
286
|
-
const legacyDir = path3.join(os3.homedir(), ".exe-mem");
|
|
287
|
-
if (!existsSync2(newDir) && existsSync2(legacyDir)) {
|
|
288
|
-
try {
|
|
289
|
-
renameSync2(legacyDir, newDir);
|
|
290
|
-
process.stderr.write(`[exe-os] Migrated data directory: ~/.exe-mem \u2192 ~/.exe-os
|
|
291
|
-
`);
|
|
292
|
-
} catch {
|
|
293
|
-
return legacyDir;
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
return newDir;
|
|
297
|
-
}
|
|
298
|
-
var EXE_AI_DIR, DB_PATH, MODELS_DIR, CONFIG_PATH, LEGACY_LANCE_PATH, CURRENT_CONFIG_VERSION, DEFAULT_CONFIG;
|
|
299
|
-
var init_config = __esm({
|
|
300
|
-
"src/lib/config.ts"() {
|
|
301
|
-
"use strict";
|
|
302
|
-
EXE_AI_DIR = resolveDataDir();
|
|
303
|
-
DB_PATH = path3.join(EXE_AI_DIR, "memories.db");
|
|
304
|
-
MODELS_DIR = path3.join(EXE_AI_DIR, "models");
|
|
305
|
-
CONFIG_PATH = path3.join(EXE_AI_DIR, "config.json");
|
|
306
|
-
LEGACY_LANCE_PATH = path3.join(EXE_AI_DIR, "local.lance");
|
|
307
|
-
CURRENT_CONFIG_VERSION = 1;
|
|
308
|
-
DEFAULT_CONFIG = {
|
|
309
|
-
config_version: CURRENT_CONFIG_VERSION,
|
|
310
|
-
dbPath: DB_PATH,
|
|
311
|
-
modelFile: "jina-embeddings-v5-small-q4_k_m.gguf",
|
|
312
|
-
embeddingDim: 1024,
|
|
313
|
-
batchSize: 20,
|
|
314
|
-
flushIntervalMs: 1e4,
|
|
315
|
-
autoIngestion: true,
|
|
316
|
-
autoRetrieval: true,
|
|
317
|
-
searchMode: "hybrid",
|
|
318
|
-
hookSearchMode: "hybrid",
|
|
319
|
-
fileGrepEnabled: true,
|
|
320
|
-
splashEffect: true,
|
|
321
|
-
consolidationEnabled: true,
|
|
322
|
-
consolidationIntervalMs: 6 * 60 * 60 * 1e3,
|
|
323
|
-
consolidationModel: "claude-haiku-4-5-20251001",
|
|
324
|
-
consolidationMaxCallsPerRun: 20,
|
|
325
|
-
selfQueryRouter: true,
|
|
326
|
-
selfQueryModel: "claude-haiku-4-5-20251001",
|
|
327
|
-
rerankerEnabled: true,
|
|
328
|
-
scalingRoadmap: {
|
|
329
|
-
rerankerAutoTrigger: {
|
|
330
|
-
enabled: true,
|
|
331
|
-
broadQueryMinCardinality: 5e4,
|
|
332
|
-
fetchTopK: 150,
|
|
333
|
-
returnTopK: 5
|
|
334
|
-
}
|
|
335
|
-
},
|
|
336
|
-
graphRagEnabled: true,
|
|
337
|
-
wikiEnabled: false,
|
|
338
|
-
wikiUrl: "",
|
|
339
|
-
wikiApiKey: "",
|
|
340
|
-
wikiSyncIntervalMs: 30 * 60 * 1e3,
|
|
341
|
-
wikiWorkspaceMapping: {
|
|
342
|
-
exe: "Executive",
|
|
343
|
-
yoshi: "Engineering",
|
|
344
|
-
mari: "Marketing",
|
|
345
|
-
tom: "Engineering",
|
|
346
|
-
sasha: "Production"
|
|
347
|
-
},
|
|
348
|
-
wikiAutoUpdate: true,
|
|
349
|
-
wikiAutoUpdateThreshold: 0.5,
|
|
350
|
-
wikiAutoUpdateCreateNew: true,
|
|
351
|
-
skillLearning: true,
|
|
352
|
-
skillThreshold: 3,
|
|
353
|
-
skillModel: "claude-haiku-4-5-20251001",
|
|
354
|
-
exeHeartbeat: {
|
|
355
|
-
enabled: true,
|
|
356
|
-
intervalSeconds: 60,
|
|
357
|
-
staleInProgressThresholdHours: 2
|
|
358
|
-
},
|
|
359
|
-
sessionLifecycle: {
|
|
360
|
-
idleKillEnabled: true,
|
|
361
|
-
idleKillTicksRequired: 3,
|
|
362
|
-
idleKillIntercomAckWindowMs: 1e4,
|
|
363
|
-
maxAutoInstances: 10
|
|
364
|
-
},
|
|
365
|
-
autoUpdate: {
|
|
366
|
-
checkOnBoot: true,
|
|
367
|
-
autoInstall: false,
|
|
368
|
-
checkIntervalMs: 24 * 60 * 60 * 1e3
|
|
369
|
-
}
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
// src/lib/employees.ts
|
|
375
|
-
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
376
|
-
import { existsSync as existsSync3, symlinkSync, readlinkSync, readFileSync as readFileSync3, renameSync as renameSync3, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
|
|
377
|
-
import { execSync as execSync3 } from "child_process";
|
|
378
|
-
import path4 from "path";
|
|
379
|
-
import os4 from "os";
|
|
380
|
-
var EMPLOYEES_PATH;
|
|
381
|
-
var init_employees = __esm({
|
|
382
|
-
"src/lib/employees.ts"() {
|
|
383
|
-
"use strict";
|
|
384
|
-
init_config();
|
|
385
|
-
EMPLOYEES_PATH = path4.join(EXE_AI_DIR, "exe-employees.json");
|
|
405
|
+
INTERCOM_LOG = path4.join(os4.homedir(), ".exe-os", "intercom.log");
|
|
386
406
|
}
|
|
387
407
|
});
|
|
388
408
|
|
|
@@ -439,7 +459,7 @@ function employeeSessionName(employee, exeSession, instance) {
|
|
|
439
459
|
exeSession = root;
|
|
440
460
|
} else {
|
|
441
461
|
throw new Error(
|
|
442
|
-
`Invalid
|
|
462
|
+
`Invalid coordinator session "${exeSession}" \u2014 contains a dash but no recognizable root session. Pass a root session name.`
|
|
443
463
|
);
|
|
444
464
|
}
|
|
445
465
|
}
|
|
@@ -453,8 +473,10 @@ function employeeSessionName(employee, exeSession, instance) {
|
|
|
453
473
|
return name;
|
|
454
474
|
}
|
|
455
475
|
function extractRootExe(name) {
|
|
456
|
-
|
|
457
|
-
|
|
476
|
+
if (!name) return null;
|
|
477
|
+
if (!name.includes("-")) return name;
|
|
478
|
+
const parts = name.split("-").filter(Boolean);
|
|
479
|
+
return parts.length > 0 ? parts[parts.length - 1] : null;
|
|
458
480
|
}
|
|
459
481
|
function getParentExe(sessionKey) {
|
|
460
482
|
try {
|
|
@@ -537,12 +559,14 @@ function getSessionState(sessionName) {
|
|
|
537
559
|
}
|
|
538
560
|
}
|
|
539
561
|
function isExeSession(sessionName) {
|
|
540
|
-
|
|
562
|
+
const matchesBaseWithInstance = (baseName) => sessionName === baseName || sessionName.startsWith(baseName) && /^\d+$/.test(sessionName.slice(baseName.length));
|
|
563
|
+
const coordinatorName = getCoordinatorName();
|
|
564
|
+
return matchesBaseWithInstance(coordinatorName) || matchesBaseWithInstance("exe");
|
|
541
565
|
}
|
|
542
566
|
function sendIntercom(targetSession) {
|
|
543
567
|
const transport = getTransport();
|
|
544
568
|
if (isExeSession(targetSession)) {
|
|
545
|
-
logIntercom(`
|
|
569
|
+
logIntercom(`SKIP_COORDINATOR \u2192 ${targetSession} (coordinator sessions use prompt-submit hook)`);
|
|
546
570
|
return "skipped_exe";
|
|
547
571
|
}
|
|
548
572
|
if (isDebounced(targetSession)) {
|
|
@@ -593,6 +617,7 @@ var init_tmux_routing = __esm({
|
|
|
593
617
|
init_provider_table();
|
|
594
618
|
init_intercom_queue();
|
|
595
619
|
init_plan_limits();
|
|
620
|
+
init_employees();
|
|
596
621
|
SPAWN_LOCK_DIR = path7.join(os5.homedir(), ".exe-os", "spawn-locks");
|
|
597
622
|
SESSION_CACHE = path7.join(os5.homedir(), ".exe-os", "session-cache");
|
|
598
623
|
VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
|
|
@@ -716,7 +741,7 @@ async function deliverLocalMessage(messageId) {
|
|
|
716
741
|
try {
|
|
717
742
|
const exeSession = resolveExeSession();
|
|
718
743
|
if (!exeSession) {
|
|
719
|
-
throw new Error("No
|
|
744
|
+
throw new Error("No coordinator session found");
|
|
720
745
|
}
|
|
721
746
|
const sessionName = employeeSessionName(targetAgent, exeSession);
|
|
722
747
|
if (!isEmployeeAlive(sessionName)) {
|
|
@@ -759,8 +784,51 @@ import path8 from "path";
|
|
|
759
784
|
init_session_key();
|
|
760
785
|
|
|
761
786
|
// src/adapters/claude/active-agent.ts
|
|
787
|
+
init_employees();
|
|
762
788
|
var CACHE_DIR = path8.join(EXE_AI_DIR, "session-cache");
|
|
763
789
|
var STALE_MS = 24 * 60 * 60 * 1e3;
|
|
790
|
+
function isNameWithOptionalInstance(candidate, baseName) {
|
|
791
|
+
if (candidate === baseName) return true;
|
|
792
|
+
if (!candidate.startsWith(baseName)) return false;
|
|
793
|
+
return /^\d+$/.test(candidate.slice(baseName.length));
|
|
794
|
+
}
|
|
795
|
+
function resolveEmployeeFromSessionPrefix(prefix, employees) {
|
|
796
|
+
const sorted = [...employees].sort((a, b) => b.name.length - a.name.length);
|
|
797
|
+
for (const employee of sorted) {
|
|
798
|
+
if (isNameWithOptionalInstance(prefix, employee.name)) {
|
|
799
|
+
return { agentId: employee.name, agentRole: employee.role };
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
return null;
|
|
803
|
+
}
|
|
804
|
+
function resolveActiveAgentFromTmuxSession(sessionName) {
|
|
805
|
+
const employees = loadEmployeesSync();
|
|
806
|
+
const coordinator = getCoordinatorEmployee(employees);
|
|
807
|
+
const coordinatorName = coordinator?.name ?? DEFAULT_COORDINATOR_TEMPLATE_NAME;
|
|
808
|
+
if (isNameWithOptionalInstance(sessionName, coordinatorName)) {
|
|
809
|
+
return {
|
|
810
|
+
agentId: coordinatorName,
|
|
811
|
+
agentRole: coordinator?.role ?? "COO"
|
|
812
|
+
};
|
|
813
|
+
}
|
|
814
|
+
if (isNameWithOptionalInstance(sessionName, DEFAULT_COORDINATOR_TEMPLATE_NAME)) {
|
|
815
|
+
return {
|
|
816
|
+
agentId: coordinator?.name ?? DEFAULT_COORDINATOR_TEMPLATE_NAME,
|
|
817
|
+
agentRole: coordinator?.role ?? "COO"
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
if (sessionName.includes("-")) {
|
|
821
|
+
const prefix = sessionName.split("-")[0] ?? "";
|
|
822
|
+
const employee = resolveEmployeeFromSessionPrefix(prefix, employees);
|
|
823
|
+
if (employee) return employee;
|
|
824
|
+
const legacy = prefix.match(/^([a-zA-Z]+)\d*$/);
|
|
825
|
+
if (legacy?.[1] && legacy[1] !== DEFAULT_COORDINATOR_TEMPLATE_NAME) {
|
|
826
|
+
const emp = getEmployee(employees, legacy[1]);
|
|
827
|
+
return { agentId: emp?.name ?? legacy[1], agentRole: emp?.role ?? "employee" };
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
return null;
|
|
831
|
+
}
|
|
764
832
|
function getMarkerPath() {
|
|
765
833
|
return path8.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
|
|
766
834
|
}
|
|
@@ -797,13 +865,8 @@ function getActiveAgent() {
|
|
|
797
865
|
"tmux display-message -p '#{session_name}' 2>/dev/null",
|
|
798
866
|
{ encoding: "utf8", timeout: 2e3 }
|
|
799
867
|
).trim();
|
|
800
|
-
const
|
|
801
|
-
if (
|
|
802
|
-
return { agentId: empMatch[1], agentRole: "employee" };
|
|
803
|
-
}
|
|
804
|
-
if (/^exe\d+$/.test(sessionName)) {
|
|
805
|
-
return { agentId: "exe", agentRole: "COO" };
|
|
806
|
-
}
|
|
868
|
+
const resolved = resolveActiveAgentFromTmuxSession(sessionName);
|
|
869
|
+
if (resolved) return resolved;
|
|
807
870
|
} catch {
|
|
808
871
|
}
|
|
809
872
|
return {
|
|
@@ -820,7 +883,7 @@ function registerSendMessage(server) {
|
|
|
820
883
|
title: "Send Message",
|
|
821
884
|
description: "Send a structured message to another agent. Messages are queued and delivered via intercom. NOTE: messages are fire-and-forget \u2014 do NOT use for actionable work dispatch. Use create_task instead to assign work to employees.",
|
|
822
885
|
inputSchema: {
|
|
823
|
-
target_agent: z.string().describe("Recipient agent name
|
|
886
|
+
target_agent: z.string().describe("Recipient agent name"),
|
|
824
887
|
content: z.string().describe("Message content"),
|
|
825
888
|
target_project: z.string().optional().describe("Project context (optional)"),
|
|
826
889
|
priority: z.enum(["normal", "urgent"]).default("normal").describe("Message priority (default: normal)"),
|