@askexenow/exe-os 0.9.16 → 0.9.18
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 +1242 -909
- package/dist/bin/backfill-responses.js +1245 -912
- package/dist/bin/backfill-vectors.js +1244 -906
- package/dist/bin/cleanup-stale-review-tasks.js +1870 -417
- package/dist/bin/cli.js +217 -107
- package/dist/bin/exe-agent-config.js +2 -2
- package/dist/bin/exe-agent.js +62 -0
- package/dist/bin/exe-assign.js +346 -10
- package/dist/bin/exe-boot.js +387 -32
- package/dist/bin/exe-call.js +72 -2
- package/dist/bin/exe-cloud.js +8 -0
- package/dist/bin/exe-dispatch.js +1821 -225
- package/dist/bin/exe-doctor.js +720 -52
- package/dist/bin/exe-export-behaviors.js +1429 -148
- package/dist/bin/exe-forget.js +1408 -34
- package/dist/bin/exe-gateway.js +1629 -1295
- package/dist/bin/exe-heartbeat.js +1899 -448
- package/dist/bin/exe-kill.js +1624 -346
- package/dist/bin/exe-launch-agent.js +726 -90
- package/dist/bin/exe-link.js +27 -8
- package/dist/bin/exe-new-employee.js +75 -9
- package/dist/bin/exe-pending-messages.js +2769 -1316
- package/dist/bin/exe-pending-notifications.js +2829 -1376
- package/dist/bin/exe-pending-reviews.js +2847 -1392
- package/dist/bin/exe-rename.js +89 -8
- package/dist/bin/exe-review.js +1494 -312
- package/dist/bin/exe-search.js +1608 -1300
- package/dist/bin/exe-session-cleanup.js +194 -91
- package/dist/bin/exe-settings.js +10 -2
- package/dist/bin/exe-start-codex.js +769 -120
- package/dist/bin/exe-start-opencode.js +763 -108
- package/dist/bin/exe-status.js +1887 -434
- package/dist/bin/exe-team.js +1782 -324
- package/dist/bin/git-sweep.js +408 -33
- package/dist/bin/graph-backfill.js +681 -27
- package/dist/bin/graph-export.js +1419 -141
- package/dist/bin/install.js +4 -8
- package/dist/bin/intercom-check.js +8641 -0
- package/dist/bin/scan-tasks.js +553 -38
- package/dist/bin/setup.js +82 -10
- package/dist/bin/shard-migrate.js +682 -28
- package/dist/gateway/index.js +1629 -1295
- package/dist/hooks/bug-report-worker.js +1136 -183
- package/dist/hooks/codex-stop-task-finalizer.js +1060 -107
- package/dist/hooks/commit-complete.js +408 -33
- package/dist/hooks/error-recall.js +1608 -1300
- package/dist/hooks/ingest-worker.js +250 -7966
- package/dist/hooks/ingest.js +707 -119
- package/dist/hooks/instructions-loaded.js +383 -20
- package/dist/hooks/notification.js +383 -20
- package/dist/hooks/post-compact.js +384 -21
- package/dist/hooks/{response-ingest-worker.js → post-tool-combined.js} +4157 -1716
- package/dist/hooks/pre-compact.js +486 -45
- package/dist/hooks/pre-tool-use.js +385 -22
- package/dist/hooks/prompt-submit.js +291 -96
- package/dist/hooks/session-end.js +490 -48
- package/dist/hooks/session-start.js +236 -22
- package/dist/hooks/stop.js +192 -50
- package/dist/hooks/subagent-stop.js +95 -18
- package/dist/hooks/summary-worker.js +205 -361
- package/dist/index.js +221 -105
- package/dist/lib/agent-config.js +2 -2
- package/dist/lib/cloud-sync.js +27 -8
- package/dist/lib/consolidation.js +437 -41
- package/dist/lib/database.js +20 -8
- package/dist/lib/db-daemon-client.js +2 -2
- package/dist/lib/db.js +20 -8
- package/dist/lib/device-registry.js +27 -8
- package/dist/lib/employee-templates.js +62 -0
- package/dist/lib/employees.js +2 -2
- package/dist/lib/exe-daemon.js +6703 -6259
- package/dist/lib/hybrid-search.js +1608 -1300
- package/dist/lib/identity.js +1 -1
- package/dist/lib/messaging.js +11 -3
- package/dist/lib/reminders.js +1 -1
- package/dist/lib/schedules.js +718 -26
- package/dist/lib/session-registry.js +11 -0
- package/dist/lib/skill-learning.js +639 -9
- package/dist/lib/store.js +676 -27
- package/dist/lib/tasks.js +665 -27
- package/dist/lib/tmux-routing.js +732 -94
- package/dist/lib/token-spend.js +1 -1
- package/dist/mcp/server.js +856 -383
- package/dist/mcp/tools/complete-reminder.js +1 -1
- package/dist/mcp/tools/create-reminder.js +1 -1
- package/dist/mcp/tools/create-task.js +616 -46
- package/dist/mcp/tools/deactivate-behavior.js +9 -1
- package/dist/mcp/tools/list-reminders.js +1 -1
- package/dist/mcp/tools/list-tasks.js +10 -2
- package/dist/mcp/tools/send-message.js +11 -3
- package/dist/mcp/tools/update-task.js +677 -39
- package/dist/runtime/index.js +425 -37
- package/dist/tui/App.js +365 -34
- package/package.json +5 -2
- package/src/commands/exe/intercom.md +6 -17
- package/dist/bin/wiki-sync.js +0 -2991
- package/dist/hooks/prompt-ingest-worker.js +0 -3979
package/dist/hooks/ingest.js
CHANGED
|
@@ -355,7 +355,7 @@ var init_agent_config = __esm({
|
|
|
355
355
|
init_secure_files();
|
|
356
356
|
AGENT_CONFIG_PATH = path2.join(EXE_AI_DIR, "agent-config.json");
|
|
357
357
|
KNOWN_RUNTIMES = {
|
|
358
|
-
claude: ["claude-opus-4", "claude-sonnet-4", "claude-haiku-4.5"],
|
|
358
|
+
claude: ["claude-opus-4.6", "claude-opus-4", "claude-sonnet-4.6", "claude-sonnet-4", "claude-haiku-4.5"],
|
|
359
359
|
codex: ["gpt-5.4", "gpt-5.5", "gpt-5.3-codex-spark", "o3", "o4-mini"],
|
|
360
360
|
opencode: ["anthropic/claude-sonnet-4-6", "openai/gpt-5.4", "google/gemini-2.5-pro", "deepseek/deepseek-r3", "minimax/minimax-m2.5"]
|
|
361
361
|
};
|
|
@@ -365,7 +365,7 @@ var init_agent_config = __esm({
|
|
|
365
365
|
opencode: "OpenCode (open source)"
|
|
366
366
|
};
|
|
367
367
|
DEFAULT_MODELS = {
|
|
368
|
-
claude: "claude-opus-4",
|
|
368
|
+
claude: "claude-opus-4.6",
|
|
369
369
|
codex: RUNTIME_TABLE.codex?.defaultModel ?? "gpt-5.4",
|
|
370
370
|
opencode: RUNTIME_TABLE.opencode?.defaultModel ?? "anthropic/claude-sonnet-4-6"
|
|
371
371
|
};
|
|
@@ -710,9 +710,9 @@ var MAX_RETRIES, BASE_DELAY_MS, MAX_JITTER_MS;
|
|
|
710
710
|
var init_db_retry = __esm({
|
|
711
711
|
"src/lib/db-retry.ts"() {
|
|
712
712
|
"use strict";
|
|
713
|
-
MAX_RETRIES =
|
|
714
|
-
BASE_DELAY_MS =
|
|
715
|
-
MAX_JITTER_MS =
|
|
713
|
+
MAX_RETRIES = 5;
|
|
714
|
+
BASE_DELAY_MS = 250;
|
|
715
|
+
MAX_JITTER_MS = 400;
|
|
716
716
|
}
|
|
717
717
|
});
|
|
718
718
|
|
|
@@ -1300,7 +1300,544 @@ var init_database_adapter = __esm({
|
|
|
1300
1300
|
}
|
|
1301
1301
|
});
|
|
1302
1302
|
|
|
1303
|
+
// src/lib/daemon-auth.ts
|
|
1304
|
+
var daemon_auth_exports = {};
|
|
1305
|
+
__export(daemon_auth_exports, {
|
|
1306
|
+
DAEMON_TOKEN_PATH: () => DAEMON_TOKEN_PATH,
|
|
1307
|
+
ensureDaemonToken: () => ensureDaemonToken,
|
|
1308
|
+
readDaemonToken: () => readDaemonToken
|
|
1309
|
+
});
|
|
1310
|
+
import crypto2 from "crypto";
|
|
1311
|
+
import path8 from "path";
|
|
1312
|
+
import { existsSync as existsSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync6 } from "fs";
|
|
1313
|
+
function normalizeToken(token) {
|
|
1314
|
+
if (!token) return null;
|
|
1315
|
+
const trimmed = token.trim();
|
|
1316
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
1317
|
+
}
|
|
1318
|
+
function readDaemonToken() {
|
|
1319
|
+
try {
|
|
1320
|
+
if (!existsSync7(DAEMON_TOKEN_PATH)) return null;
|
|
1321
|
+
return normalizeToken(readFileSync6(DAEMON_TOKEN_PATH, "utf8"));
|
|
1322
|
+
} catch {
|
|
1323
|
+
return null;
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
function ensureDaemonToken(seed) {
|
|
1327
|
+
const existing = readDaemonToken();
|
|
1328
|
+
if (existing) return existing;
|
|
1329
|
+
const token = normalizeToken(seed) ?? crypto2.randomBytes(32).toString("hex");
|
|
1330
|
+
ensurePrivateDirSync(EXE_AI_DIR);
|
|
1331
|
+
writeFileSync6(DAEMON_TOKEN_PATH, `${token}
|
|
1332
|
+
`, "utf8");
|
|
1333
|
+
enforcePrivateFileSync(DAEMON_TOKEN_PATH);
|
|
1334
|
+
return token;
|
|
1335
|
+
}
|
|
1336
|
+
var DAEMON_TOKEN_PATH;
|
|
1337
|
+
var init_daemon_auth = __esm({
|
|
1338
|
+
"src/lib/daemon-auth.ts"() {
|
|
1339
|
+
"use strict";
|
|
1340
|
+
init_config();
|
|
1341
|
+
init_secure_files();
|
|
1342
|
+
DAEMON_TOKEN_PATH = path8.join(EXE_AI_DIR, "exed.token");
|
|
1343
|
+
}
|
|
1344
|
+
});
|
|
1345
|
+
|
|
1346
|
+
// src/lib/exe-daemon-client.ts
|
|
1347
|
+
import net from "net";
|
|
1348
|
+
import os5 from "os";
|
|
1349
|
+
import { spawn } from "child_process";
|
|
1350
|
+
import { randomUUID } from "crypto";
|
|
1351
|
+
import { existsSync as existsSync8, unlinkSync as unlinkSync5, readFileSync as readFileSync7, openSync, closeSync, statSync } from "fs";
|
|
1352
|
+
import path9 from "path";
|
|
1353
|
+
import { fileURLToPath } from "url";
|
|
1354
|
+
function handleData(chunk) {
|
|
1355
|
+
_buffer += chunk.toString();
|
|
1356
|
+
if (_buffer.length > MAX_BUFFER) {
|
|
1357
|
+
_buffer = "";
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1360
|
+
let newlineIdx;
|
|
1361
|
+
while ((newlineIdx = _buffer.indexOf("\n")) !== -1) {
|
|
1362
|
+
const line = _buffer.slice(0, newlineIdx).trim();
|
|
1363
|
+
_buffer = _buffer.slice(newlineIdx + 1);
|
|
1364
|
+
if (!line) continue;
|
|
1365
|
+
try {
|
|
1366
|
+
const response = JSON.parse(line);
|
|
1367
|
+
const id = response.id;
|
|
1368
|
+
if (!id) continue;
|
|
1369
|
+
const entry = _pending.get(id);
|
|
1370
|
+
if (entry) {
|
|
1371
|
+
clearTimeout(entry.timer);
|
|
1372
|
+
_pending.delete(id);
|
|
1373
|
+
entry.resolve(response);
|
|
1374
|
+
}
|
|
1375
|
+
} catch {
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
function cleanupStaleFiles() {
|
|
1380
|
+
if (existsSync8(PID_PATH)) {
|
|
1381
|
+
try {
|
|
1382
|
+
const pid = parseInt(readFileSync7(PID_PATH, "utf8").trim(), 10);
|
|
1383
|
+
if (pid > 0) {
|
|
1384
|
+
try {
|
|
1385
|
+
process.kill(pid, 0);
|
|
1386
|
+
return;
|
|
1387
|
+
} catch {
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
} catch {
|
|
1391
|
+
}
|
|
1392
|
+
try {
|
|
1393
|
+
unlinkSync5(PID_PATH);
|
|
1394
|
+
} catch {
|
|
1395
|
+
}
|
|
1396
|
+
try {
|
|
1397
|
+
unlinkSync5(SOCKET_PATH);
|
|
1398
|
+
} catch {
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
function findPackageRoot() {
|
|
1403
|
+
let dir = path9.dirname(fileURLToPath(import.meta.url));
|
|
1404
|
+
const { root } = path9.parse(dir);
|
|
1405
|
+
while (dir !== root) {
|
|
1406
|
+
if (existsSync8(path9.join(dir, "package.json"))) return dir;
|
|
1407
|
+
dir = path9.dirname(dir);
|
|
1408
|
+
}
|
|
1409
|
+
return null;
|
|
1410
|
+
}
|
|
1411
|
+
function getAvailableMemoryGB() {
|
|
1412
|
+
if (process.platform === "darwin") {
|
|
1413
|
+
try {
|
|
1414
|
+
const { execSync: execSync6 } = __require("child_process");
|
|
1415
|
+
const vmstat = execSync6("vm_stat", { encoding: "utf8" });
|
|
1416
|
+
const pageSize = 16384;
|
|
1417
|
+
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
1418
|
+
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
1419
|
+
const free = vmstat.match(/Pages free:\s+(\d+)/);
|
|
1420
|
+
const inactive = vmstat.match(/Pages inactive:\s+(\d+)/);
|
|
1421
|
+
const speculative = vmstat.match(/Pages speculative:\s+(\d+)/);
|
|
1422
|
+
const freePages = free ? parseInt(free[1], 10) : 0;
|
|
1423
|
+
const inactivePages = inactive ? parseInt(inactive[1], 10) : 0;
|
|
1424
|
+
const speculativePages = speculative ? parseInt(speculative[1], 10) : 0;
|
|
1425
|
+
return (freePages + inactivePages + speculativePages) * actualPageSize / (1024 * 1024 * 1024);
|
|
1426
|
+
} catch {
|
|
1427
|
+
return os5.freemem() / (1024 * 1024 * 1024);
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
return os5.freemem() / (1024 * 1024 * 1024);
|
|
1431
|
+
}
|
|
1432
|
+
function spawnDaemon() {
|
|
1433
|
+
const freeGB = getAvailableMemoryGB();
|
|
1434
|
+
const totalGB = os5.totalmem() / (1024 * 1024 * 1024);
|
|
1435
|
+
if (totalGB <= 8) {
|
|
1436
|
+
process.stderr.write(
|
|
1437
|
+
`[exed-client] SKIP: ${totalGB.toFixed(0)}GB system \u2014 embedding daemon disabled. Using keyword search only. Minimum 16GB recommended for vector search.
|
|
1438
|
+
`
|
|
1439
|
+
);
|
|
1440
|
+
return;
|
|
1441
|
+
}
|
|
1442
|
+
if (totalGB <= 16 && freeGB < 2) {
|
|
1443
|
+
process.stderr.write(
|
|
1444
|
+
`[exed-client] SKIP: low memory (${freeGB.toFixed(1)}GB available / ${totalGB.toFixed(0)}GB total). Embedding daemon not started \u2014 using keyword search only.
|
|
1445
|
+
`
|
|
1446
|
+
);
|
|
1447
|
+
return;
|
|
1448
|
+
}
|
|
1449
|
+
const pkgRoot = findPackageRoot();
|
|
1450
|
+
if (!pkgRoot) {
|
|
1451
|
+
process.stderr.write("[exed-client] WARN: cannot find package root\n");
|
|
1452
|
+
return;
|
|
1453
|
+
}
|
|
1454
|
+
const daemonPath = path9.join(pkgRoot, "dist", "lib", "exe-daemon.js");
|
|
1455
|
+
if (!existsSync8(daemonPath)) {
|
|
1456
|
+
process.stderr.write(`[exed-client] WARN: daemon script not found at ${daemonPath}
|
|
1457
|
+
`);
|
|
1458
|
+
return;
|
|
1459
|
+
}
|
|
1460
|
+
const resolvedPath = daemonPath;
|
|
1461
|
+
const daemonToken = ensureDaemonToken(process.env[DAEMON_TOKEN_ENV] ?? null);
|
|
1462
|
+
process.stderr.write(`[exed-client] Spawning daemon: ${resolvedPath}
|
|
1463
|
+
`);
|
|
1464
|
+
const logPath = path9.join(path9.dirname(SOCKET_PATH), "exed.log");
|
|
1465
|
+
let stderrFd = "ignore";
|
|
1466
|
+
try {
|
|
1467
|
+
stderrFd = openSync(logPath, "a");
|
|
1468
|
+
} catch {
|
|
1469
|
+
}
|
|
1470
|
+
const heapCapMB = totalGB <= 8 ? 256 : 512;
|
|
1471
|
+
const nodeArgs = [`--max-old-space-size=${heapCapMB}`, resolvedPath];
|
|
1472
|
+
const child = spawn(process.execPath, nodeArgs, {
|
|
1473
|
+
detached: true,
|
|
1474
|
+
stdio: ["ignore", "ignore", stderrFd],
|
|
1475
|
+
env: {
|
|
1476
|
+
...process.env,
|
|
1477
|
+
TMUX: void 0,
|
|
1478
|
+
// Daemon is global — must not inherit session scope
|
|
1479
|
+
TMUX_PANE: void 0,
|
|
1480
|
+
// Prevents resolveExeSession() from scoping to one session
|
|
1481
|
+
EXE_DAEMON_SOCK: SOCKET_PATH,
|
|
1482
|
+
EXE_DAEMON_PID: PID_PATH,
|
|
1483
|
+
[DAEMON_TOKEN_ENV]: daemonToken
|
|
1484
|
+
}
|
|
1485
|
+
});
|
|
1486
|
+
child.unref();
|
|
1487
|
+
if (typeof stderrFd === "number") {
|
|
1488
|
+
try {
|
|
1489
|
+
closeSync(stderrFd);
|
|
1490
|
+
} catch {
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
function acquireSpawnLock() {
|
|
1495
|
+
try {
|
|
1496
|
+
const fd = openSync(SPAWN_LOCK_PATH, "wx");
|
|
1497
|
+
closeSync(fd);
|
|
1498
|
+
return true;
|
|
1499
|
+
} catch {
|
|
1500
|
+
try {
|
|
1501
|
+
const stat = statSync(SPAWN_LOCK_PATH);
|
|
1502
|
+
if (Date.now() - stat.mtimeMs > SPAWN_LOCK_STALE_MS) {
|
|
1503
|
+
try {
|
|
1504
|
+
unlinkSync5(SPAWN_LOCK_PATH);
|
|
1505
|
+
} catch {
|
|
1506
|
+
}
|
|
1507
|
+
try {
|
|
1508
|
+
const fd = openSync(SPAWN_LOCK_PATH, "wx");
|
|
1509
|
+
closeSync(fd);
|
|
1510
|
+
return true;
|
|
1511
|
+
} catch {
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
} catch {
|
|
1515
|
+
}
|
|
1516
|
+
return false;
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
function releaseSpawnLock() {
|
|
1520
|
+
try {
|
|
1521
|
+
unlinkSync5(SPAWN_LOCK_PATH);
|
|
1522
|
+
} catch {
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
function connectToSocket() {
|
|
1526
|
+
return new Promise((resolve) => {
|
|
1527
|
+
if (_socket && _connected) {
|
|
1528
|
+
resolve(true);
|
|
1529
|
+
return;
|
|
1530
|
+
}
|
|
1531
|
+
const socket = net.createConnection({ path: SOCKET_PATH });
|
|
1532
|
+
const connectTimeout = setTimeout(() => {
|
|
1533
|
+
socket.destroy();
|
|
1534
|
+
resolve(false);
|
|
1535
|
+
}, 2e3);
|
|
1536
|
+
socket.on("connect", () => {
|
|
1537
|
+
clearTimeout(connectTimeout);
|
|
1538
|
+
_socket = socket;
|
|
1539
|
+
_connected = true;
|
|
1540
|
+
_buffer = "";
|
|
1541
|
+
socket.on("data", handleData);
|
|
1542
|
+
socket.on("close", () => {
|
|
1543
|
+
_connected = false;
|
|
1544
|
+
_socket = null;
|
|
1545
|
+
for (const [id, entry] of _pending) {
|
|
1546
|
+
clearTimeout(entry.timer);
|
|
1547
|
+
_pending.delete(id);
|
|
1548
|
+
entry.resolve({ error: "Connection closed" });
|
|
1549
|
+
}
|
|
1550
|
+
});
|
|
1551
|
+
socket.on("error", () => {
|
|
1552
|
+
_connected = false;
|
|
1553
|
+
_socket = null;
|
|
1554
|
+
});
|
|
1555
|
+
resolve(true);
|
|
1556
|
+
});
|
|
1557
|
+
socket.on("error", () => {
|
|
1558
|
+
clearTimeout(connectTimeout);
|
|
1559
|
+
resolve(false);
|
|
1560
|
+
});
|
|
1561
|
+
});
|
|
1562
|
+
}
|
|
1563
|
+
async function connectEmbedDaemon() {
|
|
1564
|
+
if (_socket && _connected) return true;
|
|
1565
|
+
if (await connectToSocket()) return true;
|
|
1566
|
+
if (acquireSpawnLock()) {
|
|
1567
|
+
try {
|
|
1568
|
+
cleanupStaleFiles();
|
|
1569
|
+
spawnDaemon();
|
|
1570
|
+
} finally {
|
|
1571
|
+
releaseSpawnLock();
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
const start = Date.now();
|
|
1575
|
+
let delay2 = 100;
|
|
1576
|
+
while (Date.now() - start < CONNECT_TIMEOUT_MS) {
|
|
1577
|
+
await new Promise((r) => setTimeout(r, delay2));
|
|
1578
|
+
if (await connectToSocket()) return true;
|
|
1579
|
+
delay2 = Math.min(delay2 * 2, 3e3);
|
|
1580
|
+
}
|
|
1581
|
+
return false;
|
|
1582
|
+
}
|
|
1583
|
+
function sendDaemonRequest(payload, timeoutMs = REQUEST_TIMEOUT_MS) {
|
|
1584
|
+
return new Promise((resolve) => {
|
|
1585
|
+
if (!_socket || !_connected) {
|
|
1586
|
+
resolve({ error: "Not connected" });
|
|
1587
|
+
return;
|
|
1588
|
+
}
|
|
1589
|
+
const id = randomUUID();
|
|
1590
|
+
const token = process.env[DAEMON_TOKEN_ENV] ?? readDaemonToken();
|
|
1591
|
+
const timer = setTimeout(() => {
|
|
1592
|
+
_pending.delete(id);
|
|
1593
|
+
resolve({ error: "Request timeout" });
|
|
1594
|
+
}, timeoutMs);
|
|
1595
|
+
_pending.set(id, { resolve, timer });
|
|
1596
|
+
try {
|
|
1597
|
+
_socket.write(JSON.stringify({ id, token, ...payload }) + "\n");
|
|
1598
|
+
} catch {
|
|
1599
|
+
clearTimeout(timer);
|
|
1600
|
+
_pending.delete(id);
|
|
1601
|
+
resolve({ error: "Write failed" });
|
|
1602
|
+
}
|
|
1603
|
+
});
|
|
1604
|
+
}
|
|
1605
|
+
function isClientConnected() {
|
|
1606
|
+
return _connected;
|
|
1607
|
+
}
|
|
1608
|
+
var SOCKET_PATH, PID_PATH, SPAWN_LOCK_PATH, SPAWN_LOCK_STALE_MS, CONNECT_TIMEOUT_MS, REQUEST_TIMEOUT_MS, DAEMON_TOKEN_ENV, _socket, _connected, _buffer, _pending, MAX_BUFFER;
|
|
1609
|
+
var init_exe_daemon_client = __esm({
|
|
1610
|
+
"src/lib/exe-daemon-client.ts"() {
|
|
1611
|
+
"use strict";
|
|
1612
|
+
init_config();
|
|
1613
|
+
init_daemon_auth();
|
|
1614
|
+
SOCKET_PATH = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ?? path9.join(EXE_AI_DIR, "exed.sock");
|
|
1615
|
+
PID_PATH = process.env.EXE_DAEMON_PID ?? process.env.EXE_EMBED_PID ?? path9.join(EXE_AI_DIR, "exed.pid");
|
|
1616
|
+
SPAWN_LOCK_PATH = path9.join(EXE_AI_DIR, "exed-spawn.lock");
|
|
1617
|
+
SPAWN_LOCK_STALE_MS = 3e4;
|
|
1618
|
+
CONNECT_TIMEOUT_MS = 15e3;
|
|
1619
|
+
REQUEST_TIMEOUT_MS = 3e4;
|
|
1620
|
+
DAEMON_TOKEN_ENV = "EXE_DAEMON_TOKEN";
|
|
1621
|
+
_socket = null;
|
|
1622
|
+
_connected = false;
|
|
1623
|
+
_buffer = "";
|
|
1624
|
+
_pending = /* @__PURE__ */ new Map();
|
|
1625
|
+
MAX_BUFFER = 1e7;
|
|
1626
|
+
}
|
|
1627
|
+
});
|
|
1628
|
+
|
|
1629
|
+
// src/lib/daemon-protocol.ts
|
|
1630
|
+
function serializeValue(v) {
|
|
1631
|
+
if (v === null || v === void 0) return null;
|
|
1632
|
+
if (typeof v === "bigint") return Number(v);
|
|
1633
|
+
if (typeof v === "boolean") return v ? 1 : 0;
|
|
1634
|
+
if (v instanceof Uint8Array) {
|
|
1635
|
+
return { __blob: Buffer.from(v).toString("base64") };
|
|
1636
|
+
}
|
|
1637
|
+
if (ArrayBuffer.isView(v)) {
|
|
1638
|
+
return { __blob: Buffer.from(v.buffer, v.byteOffset, v.byteLength).toString("base64") };
|
|
1639
|
+
}
|
|
1640
|
+
if (v instanceof ArrayBuffer) {
|
|
1641
|
+
return { __blob: Buffer.from(v).toString("base64") };
|
|
1642
|
+
}
|
|
1643
|
+
if (typeof v === "string" || typeof v === "number") return v;
|
|
1644
|
+
return String(v);
|
|
1645
|
+
}
|
|
1646
|
+
function deserializeValue(v) {
|
|
1647
|
+
if (v === null) return null;
|
|
1648
|
+
if (typeof v === "object" && v !== null && "__blob" in v) {
|
|
1649
|
+
const buf = Buffer.from(v.__blob, "base64");
|
|
1650
|
+
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
|
|
1651
|
+
}
|
|
1652
|
+
return v;
|
|
1653
|
+
}
|
|
1654
|
+
function deserializeResultSet(srs) {
|
|
1655
|
+
const rows = srs.rows.map((obj) => {
|
|
1656
|
+
const values = srs.columns.map(
|
|
1657
|
+
(col) => deserializeValue(obj[col] ?? null)
|
|
1658
|
+
);
|
|
1659
|
+
const row = values;
|
|
1660
|
+
for (let i = 0; i < srs.columns.length; i++) {
|
|
1661
|
+
const col = srs.columns[i];
|
|
1662
|
+
if (col !== void 0) {
|
|
1663
|
+
row[col] = values[i] ?? null;
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
Object.defineProperty(row, "length", {
|
|
1667
|
+
value: values.length,
|
|
1668
|
+
enumerable: false
|
|
1669
|
+
});
|
|
1670
|
+
return row;
|
|
1671
|
+
});
|
|
1672
|
+
return {
|
|
1673
|
+
columns: srs.columns,
|
|
1674
|
+
columnTypes: srs.columnTypes ?? [],
|
|
1675
|
+
rows,
|
|
1676
|
+
rowsAffected: srs.rowsAffected,
|
|
1677
|
+
lastInsertRowid: srs.lastInsertRowid != null ? BigInt(srs.lastInsertRowid) : void 0,
|
|
1678
|
+
toJSON: () => ({
|
|
1679
|
+
columns: srs.columns,
|
|
1680
|
+
columnTypes: srs.columnTypes ?? [],
|
|
1681
|
+
rows: srs.rows,
|
|
1682
|
+
rowsAffected: srs.rowsAffected,
|
|
1683
|
+
lastInsertRowid: srs.lastInsertRowid
|
|
1684
|
+
})
|
|
1685
|
+
};
|
|
1686
|
+
}
|
|
1687
|
+
var init_daemon_protocol = __esm({
|
|
1688
|
+
"src/lib/daemon-protocol.ts"() {
|
|
1689
|
+
"use strict";
|
|
1690
|
+
}
|
|
1691
|
+
});
|
|
1692
|
+
|
|
1693
|
+
// src/lib/db-daemon-client.ts
|
|
1694
|
+
var db_daemon_client_exports = {};
|
|
1695
|
+
__export(db_daemon_client_exports, {
|
|
1696
|
+
createDaemonDbClient: () => createDaemonDbClient,
|
|
1697
|
+
initDaemonDbClient: () => initDaemonDbClient
|
|
1698
|
+
});
|
|
1699
|
+
function normalizeStatement2(stmt) {
|
|
1700
|
+
if (typeof stmt === "string") {
|
|
1701
|
+
return { sql: stmt, args: [] };
|
|
1702
|
+
}
|
|
1703
|
+
const sql = stmt.sql;
|
|
1704
|
+
let args = [];
|
|
1705
|
+
if (Array.isArray(stmt.args)) {
|
|
1706
|
+
args = stmt.args.map((v) => serializeValue(v));
|
|
1707
|
+
} else if (stmt.args && typeof stmt.args === "object") {
|
|
1708
|
+
const named = {};
|
|
1709
|
+
for (const [key, val] of Object.entries(stmt.args)) {
|
|
1710
|
+
named[key] = serializeValue(val);
|
|
1711
|
+
}
|
|
1712
|
+
return { sql, args: named };
|
|
1713
|
+
}
|
|
1714
|
+
return { sql, args };
|
|
1715
|
+
}
|
|
1716
|
+
function createDaemonDbClient(fallbackClient) {
|
|
1717
|
+
let _useDaemon = false;
|
|
1718
|
+
const client = {
|
|
1719
|
+
async execute(stmt) {
|
|
1720
|
+
if (!_useDaemon || !isClientConnected()) {
|
|
1721
|
+
return fallbackClient.execute(stmt);
|
|
1722
|
+
}
|
|
1723
|
+
const { sql, args } = normalizeStatement2(stmt);
|
|
1724
|
+
const response = await sendDaemonRequest({
|
|
1725
|
+
type: "db-execute",
|
|
1726
|
+
sql,
|
|
1727
|
+
args
|
|
1728
|
+
});
|
|
1729
|
+
if (response.error) {
|
|
1730
|
+
const errMsg = String(response.error);
|
|
1731
|
+
if (errMsg === "Not connected" || errMsg === "Request timeout" || errMsg === "Write failed" || errMsg === "DB not initialized") {
|
|
1732
|
+
process.stderr.write(`[db-daemon] Transport error (${errMsg}), falling back to direct
|
|
1733
|
+
`);
|
|
1734
|
+
return fallbackClient.execute(stmt);
|
|
1735
|
+
}
|
|
1736
|
+
throw new Error(errMsg);
|
|
1737
|
+
}
|
|
1738
|
+
if (response.db) {
|
|
1739
|
+
return deserializeResultSet(response.db);
|
|
1740
|
+
}
|
|
1741
|
+
process.stderr.write("[db-daemon] Unexpected response shape, falling back to direct\n");
|
|
1742
|
+
return fallbackClient.execute(stmt);
|
|
1743
|
+
},
|
|
1744
|
+
async batch(stmts, mode) {
|
|
1745
|
+
if (!_useDaemon || !isClientConnected()) {
|
|
1746
|
+
return fallbackClient.batch(stmts, mode);
|
|
1747
|
+
}
|
|
1748
|
+
const statements = stmts.map(normalizeStatement2);
|
|
1749
|
+
const response = await sendDaemonRequest({
|
|
1750
|
+
type: "db-batch",
|
|
1751
|
+
statements,
|
|
1752
|
+
mode: mode ?? "deferred"
|
|
1753
|
+
});
|
|
1754
|
+
if (response.error) {
|
|
1755
|
+
const errMsg = String(response.error);
|
|
1756
|
+
if (errMsg === "Not connected" || errMsg === "Request timeout" || errMsg === "Write failed" || errMsg === "DB not initialized") {
|
|
1757
|
+
process.stderr.write(`[db-daemon] Batch transport error (${errMsg}), falling back to direct
|
|
1758
|
+
`);
|
|
1759
|
+
return fallbackClient.batch(stmts, mode);
|
|
1760
|
+
}
|
|
1761
|
+
throw new Error(errMsg);
|
|
1762
|
+
}
|
|
1763
|
+
const batchResults = response["db-batch"];
|
|
1764
|
+
if (batchResults) {
|
|
1765
|
+
return batchResults.map(deserializeResultSet);
|
|
1766
|
+
}
|
|
1767
|
+
process.stderr.write("[db-daemon] Unexpected batch response shape, falling back to direct\n");
|
|
1768
|
+
return fallbackClient.batch(stmts, mode);
|
|
1769
|
+
},
|
|
1770
|
+
// Transaction support — delegate to fallback (transactions need direct connection)
|
|
1771
|
+
async transaction(mode) {
|
|
1772
|
+
return fallbackClient.transaction(mode);
|
|
1773
|
+
},
|
|
1774
|
+
// executeMultiple — delegate to fallback (used only for schema migrations)
|
|
1775
|
+
async executeMultiple(sql) {
|
|
1776
|
+
return fallbackClient.executeMultiple(sql);
|
|
1777
|
+
},
|
|
1778
|
+
// migrate — delegate to fallback
|
|
1779
|
+
async migrate(stmts) {
|
|
1780
|
+
return fallbackClient.migrate(stmts);
|
|
1781
|
+
},
|
|
1782
|
+
// Sync mode — delegate to fallback
|
|
1783
|
+
sync() {
|
|
1784
|
+
return fallbackClient.sync();
|
|
1785
|
+
},
|
|
1786
|
+
close() {
|
|
1787
|
+
_useDaemon = false;
|
|
1788
|
+
},
|
|
1789
|
+
get closed() {
|
|
1790
|
+
return fallbackClient.closed;
|
|
1791
|
+
},
|
|
1792
|
+
get protocol() {
|
|
1793
|
+
return fallbackClient.protocol;
|
|
1794
|
+
}
|
|
1795
|
+
};
|
|
1796
|
+
return {
|
|
1797
|
+
...client,
|
|
1798
|
+
/** Enable daemon routing (call after confirming daemon is connected) */
|
|
1799
|
+
_enableDaemon() {
|
|
1800
|
+
_useDaemon = true;
|
|
1801
|
+
},
|
|
1802
|
+
/** Check if daemon routing is active */
|
|
1803
|
+
_isDaemonActive() {
|
|
1804
|
+
return _useDaemon && isClientConnected();
|
|
1805
|
+
}
|
|
1806
|
+
};
|
|
1807
|
+
}
|
|
1808
|
+
async function initDaemonDbClient(fallbackClient) {
|
|
1809
|
+
if (process.env.EXE_IS_DAEMON === "1") return null;
|
|
1810
|
+
const connected = await connectEmbedDaemon();
|
|
1811
|
+
if (!connected) {
|
|
1812
|
+
process.stderr.write("[db-daemon] Daemon unavailable \u2014 using direct SQLite\n");
|
|
1813
|
+
return null;
|
|
1814
|
+
}
|
|
1815
|
+
const client = createDaemonDbClient(fallbackClient);
|
|
1816
|
+
client._enableDaemon();
|
|
1817
|
+
process.stderr.write("[db-daemon] DB routing through daemon (single-writer)\n");
|
|
1818
|
+
return client;
|
|
1819
|
+
}
|
|
1820
|
+
var init_db_daemon_client = __esm({
|
|
1821
|
+
"src/lib/db-daemon-client.ts"() {
|
|
1822
|
+
"use strict";
|
|
1823
|
+
init_exe_daemon_client();
|
|
1824
|
+
init_daemon_protocol();
|
|
1825
|
+
}
|
|
1826
|
+
});
|
|
1827
|
+
|
|
1303
1828
|
// src/lib/database.ts
|
|
1829
|
+
var database_exports = {};
|
|
1830
|
+
__export(database_exports, {
|
|
1831
|
+
disposeDatabase: () => disposeDatabase,
|
|
1832
|
+
disposeTurso: () => disposeTurso,
|
|
1833
|
+
ensureSchema: () => ensureSchema,
|
|
1834
|
+
getClient: () => getClient,
|
|
1835
|
+
getRawClient: () => getRawClient,
|
|
1836
|
+
initDaemonClient: () => initDaemonClient,
|
|
1837
|
+
initDatabase: () => initDatabase,
|
|
1838
|
+
initTurso: () => initTurso,
|
|
1839
|
+
isInitialized: () => isInitialized
|
|
1840
|
+
});
|
|
1304
1841
|
import { createClient } from "@libsql/client";
|
|
1305
1842
|
async function initDatabase(config) {
|
|
1306
1843
|
if (_walCheckpointTimer) {
|
|
@@ -1339,15 +1876,18 @@ async function initDatabase(config) {
|
|
|
1339
1876
|
});
|
|
1340
1877
|
}, 3e4);
|
|
1341
1878
|
_walCheckpointTimer.unref();
|
|
1342
|
-
if (process.env.DATABASE_URL) {
|
|
1879
|
+
if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") {
|
|
1343
1880
|
_adapterClient = await createPrismaDbAdapter(_resilientClient);
|
|
1344
1881
|
}
|
|
1345
1882
|
}
|
|
1883
|
+
function isInitialized() {
|
|
1884
|
+
return _adapterClient !== null || _client !== null;
|
|
1885
|
+
}
|
|
1346
1886
|
function getClient() {
|
|
1347
1887
|
if (!_adapterClient) {
|
|
1348
1888
|
throw new Error("Database client not initialized. Call initDatabase() first.");
|
|
1349
1889
|
}
|
|
1350
|
-
if (process.env.DATABASE_URL) {
|
|
1890
|
+
if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") {
|
|
1351
1891
|
return _adapterClient;
|
|
1352
1892
|
}
|
|
1353
1893
|
if (process.env.EXE_IS_DAEMON === "1") {
|
|
@@ -1358,6 +1898,22 @@ function getClient() {
|
|
|
1358
1898
|
}
|
|
1359
1899
|
return _resilientClient;
|
|
1360
1900
|
}
|
|
1901
|
+
async function initDaemonClient() {
|
|
1902
|
+
if (process.env.DATABASE_URL && process.env.EXE_USE_POSTGRES === "1") return;
|
|
1903
|
+
if (process.env.EXE_IS_DAEMON === "1") return;
|
|
1904
|
+
if (process.env.VITEST) return;
|
|
1905
|
+
if (!_resilientClient) return;
|
|
1906
|
+
if (_daemonClient) return;
|
|
1907
|
+
try {
|
|
1908
|
+
const { initDaemonDbClient: initDaemonDbClient2 } = await Promise.resolve().then(() => (init_db_daemon_client(), db_daemon_client_exports));
|
|
1909
|
+
_daemonClient = await initDaemonDbClient2(_resilientClient);
|
|
1910
|
+
} catch (err) {
|
|
1911
|
+
process.stderr.write(
|
|
1912
|
+
`[database] Daemon client init failed (non-fatal): ${err instanceof Error ? err.message : String(err)}
|
|
1913
|
+
`
|
|
1914
|
+
);
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1361
1917
|
function getRawClient() {
|
|
1362
1918
|
if (!_client) {
|
|
1363
1919
|
throw new Error("Database client not initialized. Call initDatabase() first.");
|
|
@@ -1496,6 +2052,13 @@ async function ensureSchema() {
|
|
|
1496
2052
|
});
|
|
1497
2053
|
} catch {
|
|
1498
2054
|
}
|
|
2055
|
+
try {
|
|
2056
|
+
await client.execute({
|
|
2057
|
+
sql: `ALTER TABLE behaviors ADD COLUMN vector F32_BLOB(${EMBEDDING_DIM})`,
|
|
2058
|
+
args: []
|
|
2059
|
+
});
|
|
2060
|
+
} catch {
|
|
2061
|
+
}
|
|
1499
2062
|
try {
|
|
1500
2063
|
await client.execute({
|
|
1501
2064
|
sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
|
|
@@ -2366,6 +2929,7 @@ var init_database = __esm({
|
|
|
2366
2929
|
init_db_retry();
|
|
2367
2930
|
init_employees();
|
|
2368
2931
|
init_database_adapter();
|
|
2932
|
+
init_memory();
|
|
2369
2933
|
_client = null;
|
|
2370
2934
|
_resilientClient = null;
|
|
2371
2935
|
_walCheckpointTimer = null;
|
|
@@ -2378,14 +2942,14 @@ var init_database = __esm({
|
|
|
2378
2942
|
|
|
2379
2943
|
// src/lib/keychain.ts
|
|
2380
2944
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
2381
|
-
import { existsSync as
|
|
2382
|
-
import
|
|
2383
|
-
import
|
|
2945
|
+
import { existsSync as existsSync9 } from "fs";
|
|
2946
|
+
import path10 from "path";
|
|
2947
|
+
import os6 from "os";
|
|
2384
2948
|
function getKeyDir() {
|
|
2385
|
-
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ??
|
|
2949
|
+
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path10.join(os6.homedir(), ".exe-os");
|
|
2386
2950
|
}
|
|
2387
2951
|
function getKeyPath() {
|
|
2388
|
-
return
|
|
2952
|
+
return path10.join(getKeyDir(), "master.key");
|
|
2389
2953
|
}
|
|
2390
2954
|
async function tryKeytar() {
|
|
2391
2955
|
try {
|
|
@@ -2406,9 +2970,9 @@ async function getMasterKey() {
|
|
|
2406
2970
|
}
|
|
2407
2971
|
}
|
|
2408
2972
|
const keyPath = getKeyPath();
|
|
2409
|
-
if (!
|
|
2973
|
+
if (!existsSync9(keyPath)) {
|
|
2410
2974
|
process.stderr.write(
|
|
2411
|
-
`[keychain] Key not found at ${keyPath} (HOME=${
|
|
2975
|
+
`[keychain] Key not found at ${keyPath} (HOME=${os6.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
|
|
2412
2976
|
`
|
|
2413
2977
|
);
|
|
2414
2978
|
return null;
|
|
@@ -2502,12 +3066,12 @@ __export(shard_manager_exports, {
|
|
|
2502
3066
|
listShards: () => listShards,
|
|
2503
3067
|
shardExists: () => shardExists
|
|
2504
3068
|
});
|
|
2505
|
-
import
|
|
2506
|
-
import { existsSync as
|
|
3069
|
+
import path11 from "path";
|
|
3070
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync5, readdirSync as readdirSync3 } from "fs";
|
|
2507
3071
|
import { createClient as createClient2 } from "@libsql/client";
|
|
2508
3072
|
function initShardManager(encryptionKey) {
|
|
2509
3073
|
_encryptionKey = encryptionKey;
|
|
2510
|
-
if (!
|
|
3074
|
+
if (!existsSync10(SHARDS_DIR)) {
|
|
2511
3075
|
mkdirSync5(SHARDS_DIR, { recursive: true });
|
|
2512
3076
|
}
|
|
2513
3077
|
_shardingEnabled = true;
|
|
@@ -2537,7 +3101,7 @@ function getShardClient(projectName) {
|
|
|
2537
3101
|
while (_shards.size >= MAX_OPEN_SHARDS) {
|
|
2538
3102
|
evictLRU();
|
|
2539
3103
|
}
|
|
2540
|
-
const dbPath =
|
|
3104
|
+
const dbPath = path11.join(SHARDS_DIR, `${safeName}.db`);
|
|
2541
3105
|
const client = createClient2({
|
|
2542
3106
|
url: `file:${dbPath}`,
|
|
2543
3107
|
encryptionKey: _encryptionKey
|
|
@@ -2548,10 +3112,10 @@ function getShardClient(projectName) {
|
|
|
2548
3112
|
}
|
|
2549
3113
|
function shardExists(projectName) {
|
|
2550
3114
|
const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
2551
|
-
return
|
|
3115
|
+
return existsSync10(path11.join(SHARDS_DIR, `${safeName}.db`));
|
|
2552
3116
|
}
|
|
2553
3117
|
function listShards() {
|
|
2554
|
-
if (!
|
|
3118
|
+
if (!existsSync10(SHARDS_DIR)) return [];
|
|
2555
3119
|
return readdirSync3(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
2556
3120
|
}
|
|
2557
3121
|
async function ensureShardSchema(client) {
|
|
@@ -2798,7 +3362,7 @@ var init_shard_manager = __esm({
|
|
|
2798
3362
|
"src/lib/shard-manager.ts"() {
|
|
2799
3363
|
"use strict";
|
|
2800
3364
|
init_config();
|
|
2801
|
-
SHARDS_DIR =
|
|
3365
|
+
SHARDS_DIR = path11.join(EXE_AI_DIR, "shards");
|
|
2802
3366
|
SHARD_IDLE_MS = 5 * 60 * 1e3;
|
|
2803
3367
|
MAX_OPEN_SHARDS = 10;
|
|
2804
3368
|
EVICTION_INTERVAL_MS = 60 * 1e3;
|
|
@@ -2918,6 +3482,68 @@ var init_platform_procedures = __esm({
|
|
|
2918
3482
|
domain: "architecture",
|
|
2919
3483
|
priority: "p0",
|
|
2920
3484
|
content: "Tasks live in the DB. Intercom (tmux send-keys) is fire-and-forget \u2014 it may fail, get garbled, or arrive mid-work. Never rely on intercom for task delivery. The UserPromptSubmit hook checks the DB for new tasks on every prompt. Your operating procedures step 7 says check for next work. The daemon nudges idle agents as a speedup. If you have no tasks, you found them all."
|
|
3485
|
+
},
|
|
3486
|
+
// --- MCP is the ONLY data interface ---
|
|
3487
|
+
{
|
|
3488
|
+
title: "MCP disconnect \u2014 ask the user, never work around it",
|
|
3489
|
+
domain: "workflow",
|
|
3490
|
+
priority: "p0",
|
|
3491
|
+
content: "If MCP tools are unavailable, disconnected, or returning connection errors: STOP. Tell the user clearly: 'MCP server is disconnected. Please run /mcp to reconnect.' Do NOT attempt workarounds \u2014 no raw Node imports, no direct DB access, no CLI hacks, no daemon socket calls. MCP is the ONLY data interface. Working around it wastes time, hits bundling issues, and bypasses the contract boundary. Ask once, wait, proceed when reconnected."
|
|
3492
|
+
},
|
|
3493
|
+
// --- MCP Tool Catalog (Layer 0 — every agent knows what tools exist) ---
|
|
3494
|
+
{
|
|
3495
|
+
title: "MCP tools \u2014 memory and search",
|
|
3496
|
+
domain: "tool-use",
|
|
3497
|
+
priority: "p1",
|
|
3498
|
+
content: "recall_my_memory: search your own memories (semantic + FTS). ask_team_memory: search a colleague's memories by agent name. store_memory: persist a memory (decisions, summaries, context). commit_memory: high-importance memory that survives consolidation. search_everything: unified search across memories, tasks, entities, conversations. get_session_context: temporal window of memories around a timestamp. consolidate_memories: merge duplicate/related memories into insights. get_memory_cardinality: count memories per agent (health check)."
|
|
3499
|
+
},
|
|
3500
|
+
{
|
|
3501
|
+
title: "MCP tools \u2014 task orchestration",
|
|
3502
|
+
domain: "tool-use",
|
|
3503
|
+
priority: "p1",
|
|
3504
|
+
content: "create_task: dispatch work to an employee (auto-spawns session). The ONLY dispatch path. list_tasks: query tasks by status, assignee, project. get_task: fetch full task details by ID. update_task: change status (in_progress, done, blocked, cancelled) + add result summary. close_task: finalize a reviewed task (COO only). checkpoint_task: save progress state for crash recovery. resume_employee: re-spawn an employee session for an existing task."
|
|
3505
|
+
},
|
|
3506
|
+
{
|
|
3507
|
+
title: "MCP tools \u2014 knowledge graph (GraphRAG)",
|
|
3508
|
+
domain: "tool-use",
|
|
3509
|
+
priority: "p1",
|
|
3510
|
+
content: "query_relationships: find connections between entities in the knowledge graph. get_entity_neighbors: explore an entity's direct connections. get_hot_entities: find most-referenced entities (trending topics). get_graph_stats: graph health \u2014 entity/relationship counts, density. export_graph: export graph data for visualization. merge_entities: deduplicate entities (alias resolution). find_similar_trajectories: match tool-call patterns to past task solutions."
|
|
3511
|
+
},
|
|
3512
|
+
{
|
|
3513
|
+
title: "MCP tools \u2014 identity, behavior, and decisions",
|
|
3514
|
+
domain: "tool-use",
|
|
3515
|
+
priority: "p1",
|
|
3516
|
+
content: "get_identity: read an agent's exe.md (Layer 1 identity). update_identity: write an agent's exe.md. Identity > behavior \u2014 use for permanent rules. store_behavior: record a correction or pattern for an agent (Layer 2 expertise). list_behaviors: view an agent's active behaviors. deactivate_behavior: soft-delete a stale or conflicting behavior. store_decision: record an ADR (architectural decision record). get_decision: retrieve a past decision by query."
|
|
3517
|
+
},
|
|
3518
|
+
{
|
|
3519
|
+
title: "MCP tools \u2014 communication and messaging",
|
|
3520
|
+
domain: "tool-use",
|
|
3521
|
+
priority: "p1",
|
|
3522
|
+
content: "send_message: send supplementary context to another agent (NOT for actionable work \u2014 use create_task). acknowledge_messages: mark messages as read. send_whatsapp: send WhatsApp message via gateway (customer-facing alerts). query_conversations: search ingested conversations across all channels (WhatsApp, email, etc.)."
|
|
3523
|
+
},
|
|
3524
|
+
{
|
|
3525
|
+
title: "MCP tools \u2014 wiki, documents, and content",
|
|
3526
|
+
domain: "tool-use",
|
|
3527
|
+
priority: "p1",
|
|
3528
|
+
content: "create_wiki_page: create a wiki page in exe-wiki. list_wiki_pages: browse wiki pages. get_wiki_page: read a wiki page. update_wiki_page: edit a wiki page. ingest_document: import a file (PDF, MD, etc.) into memory as chunks. list_documents: browse ingested documents by workspace. purge_document: remove a document and its memory chunks. set_document_importance: adjust chunk importance scores. rerank_documents: re-score document relevance for a query."
|
|
3529
|
+
},
|
|
3530
|
+
{
|
|
3531
|
+
title: "MCP tools \u2014 system, operations, and admin",
|
|
3532
|
+
domain: "tool-use",
|
|
3533
|
+
priority: "p1",
|
|
3534
|
+
content: "get_agent_spend: token usage per agent/session (cost tracking). list_agent_sessions: view agent session history. get_session_kills: audit log of killed sessions. get_daemon_health: check exed daemon status. get_auto_wake_status: daemon auto-wake configuration. get_worker_gate: check worker deployment gates. run_memory_audit: health check \u2014 duplicates, null vectors, orphaned rows. run_consolidation: trigger sleep-time memory consolidation. cloud_sync: force a cloud sync cycle. backup_vps: trigger VPS backup."
|
|
3535
|
+
},
|
|
3536
|
+
{
|
|
3537
|
+
title: "MCP tools \u2014 config, licensing, and team",
|
|
3538
|
+
domain: "tool-use",
|
|
3539
|
+
priority: "p1",
|
|
3540
|
+
content: "set_agent_config: view/change per-agent runtime and model settings. list_employees: view the employee roster. add_person: add a person to the CRM contacts roster. list_people: browse CRM contacts. get_person: fetch contact details. get_license_status: check license validity. create_license: generate a new license key (admin). list_licenses: view all issued licenses. activate_license: activate a license on a device."
|
|
3541
|
+
},
|
|
3542
|
+
{
|
|
3543
|
+
title: "MCP tools \u2014 advanced (triggers, skills, orchestration)",
|
|
3544
|
+
domain: "tool-use",
|
|
3545
|
+
priority: "p1",
|
|
3546
|
+
content: "create_trigger: set up a scheduled recurring agent job (cron). list_triggers: view active triggers. load_skill: load a slash-command skill dynamically. apply_starter_pack: import a pre-built behavior + identity pack for a role. export_orchestration: export full org state (tasks, behaviors, identities) as portable JSON. import_orchestration: import org state into a new instance. deploy_client: deploy a customer client instance. query_company_brain: unified RAG query across all company knowledge. create_reminder: set a text reminder (shown in boot brief). list_reminders: view pending reminders. complete_reminder: mark a reminder done. global_procedure: manage Layer 0 procedures (actions: store, list, deactivate). Legacy aliases: store_global_procedure, list_global_procedures, deactivate_global_procedure."
|
|
2921
3547
|
}
|
|
2922
3548
|
];
|
|
2923
3549
|
PLATFORM_PROCEDURE_TITLES = new Set(
|
|
@@ -2934,7 +3560,7 @@ __export(global_procedures_exports, {
|
|
|
2934
3560
|
loadGlobalProcedures: () => loadGlobalProcedures,
|
|
2935
3561
|
storeGlobalProcedure: () => storeGlobalProcedure
|
|
2936
3562
|
});
|
|
2937
|
-
import { randomUUID } from "crypto";
|
|
3563
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
2938
3564
|
async function loadGlobalProcedures() {
|
|
2939
3565
|
const client = getClient();
|
|
2940
3566
|
const result = await client.execute({
|
|
@@ -2963,7 +3589,7 @@ ${sections.join("\n\n")}
|
|
|
2963
3589
|
`;
|
|
2964
3590
|
}
|
|
2965
3591
|
async function storeGlobalProcedure(input2) {
|
|
2966
|
-
const id =
|
|
3592
|
+
const id = randomUUID2();
|
|
2967
3593
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2968
3594
|
const client = getClient();
|
|
2969
3595
|
await client.execute({
|
|
@@ -3067,6 +3693,11 @@ async function initStore(options) {
|
|
|
3067
3693
|
encryptionKey: hexKey
|
|
3068
3694
|
});
|
|
3069
3695
|
await retryOnBusy2(() => ensureSchema(), "ensureSchema");
|
|
3696
|
+
try {
|
|
3697
|
+
const { initDaemonClient: initDaemonClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
3698
|
+
await initDaemonClient2();
|
|
3699
|
+
} catch {
|
|
3700
|
+
}
|
|
3070
3701
|
if (!options?.lightweight) {
|
|
3071
3702
|
try {
|
|
3072
3703
|
const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
@@ -3588,7 +4219,7 @@ __export(git_staleness_exports, {
|
|
|
3588
4219
|
recordFileRead: () => recordFileRead
|
|
3589
4220
|
});
|
|
3590
4221
|
import { execSync as execSync4 } from "child_process";
|
|
3591
|
-
import
|
|
4222
|
+
import path12 from "path";
|
|
3592
4223
|
function getHeadCommit(cwd) {
|
|
3593
4224
|
try {
|
|
3594
4225
|
return execSync4("git rev-parse --short HEAD", {
|
|
@@ -3601,9 +4232,9 @@ function getHeadCommit(cwd) {
|
|
|
3601
4232
|
}
|
|
3602
4233
|
}
|
|
3603
4234
|
function normalizeTrackedPath(cwd, filePath) {
|
|
3604
|
-
const resolved =
|
|
3605
|
-
const relative =
|
|
3606
|
-
if (!relative || relative.startsWith("..") ||
|
|
4235
|
+
const resolved = path12.resolve(cwd, filePath);
|
|
4236
|
+
const relative = path12.relative(cwd, resolved);
|
|
4237
|
+
if (!relative || relative.startsWith("..") || path12.isAbsolute(relative)) {
|
|
3607
4238
|
return null;
|
|
3608
4239
|
}
|
|
3609
4240
|
return relative;
|
|
@@ -3722,8 +4353,8 @@ function findContainingChunk(filePath, snippet) {
|
|
|
3722
4353
|
try {
|
|
3723
4354
|
const ext = filePath.split(".").pop()?.toLowerCase();
|
|
3724
4355
|
if (ext !== "ts" && ext !== "tsx" && ext !== "js" && ext !== "jsx") return "";
|
|
3725
|
-
const { readFileSync:
|
|
3726
|
-
const source =
|
|
4356
|
+
const { readFileSync: readFileSync9 } = __require("fs");
|
|
4357
|
+
const source = readFileSync9(filePath, "utf8");
|
|
3727
4358
|
const lines = source.split("\n");
|
|
3728
4359
|
const lowerSnippet = snippet.toLowerCase().slice(0, 80);
|
|
3729
4360
|
let matchLine = -1;
|
|
@@ -3789,9 +4420,9 @@ function extractBash(input2, response) {
|
|
|
3789
4420
|
}
|
|
3790
4421
|
function extractGrep(input2, response) {
|
|
3791
4422
|
const pattern = String(input2.pattern ?? "");
|
|
3792
|
-
const
|
|
4423
|
+
const path15 = input2.path ? String(input2.path) : "";
|
|
3793
4424
|
const output = String(response.text ?? response.content ?? JSON.stringify(response).slice(0, MAX_OUTPUT));
|
|
3794
|
-
return `Searched for "${pattern}"${
|
|
4425
|
+
return `Searched for "${pattern}"${path15 ? ` in ${path15}` : ""}
|
|
3795
4426
|
${output.slice(0, MAX_OUTPUT)}`;
|
|
3796
4427
|
}
|
|
3797
4428
|
function extractGlob(input2, response) {
|
|
@@ -3892,7 +4523,7 @@ __export(project_name_exports, {
|
|
|
3892
4523
|
getProjectName: () => getProjectName
|
|
3893
4524
|
});
|
|
3894
4525
|
import { execSync as execSync5 } from "child_process";
|
|
3895
|
-
import
|
|
4526
|
+
import path13 from "path";
|
|
3896
4527
|
function getProjectName(cwd) {
|
|
3897
4528
|
const dir = cwd ?? process.cwd();
|
|
3898
4529
|
if (_cached2 && _cachedCwd === dir) return _cached2;
|
|
@@ -3905,7 +4536,7 @@ function getProjectName(cwd) {
|
|
|
3905
4536
|
timeout: 2e3,
|
|
3906
4537
|
stdio: ["pipe", "pipe", "pipe"]
|
|
3907
4538
|
}).trim();
|
|
3908
|
-
repoRoot =
|
|
4539
|
+
repoRoot = path13.dirname(gitCommonDir);
|
|
3909
4540
|
} catch {
|
|
3910
4541
|
repoRoot = execSync5("git rev-parse --show-toplevel", {
|
|
3911
4542
|
cwd: dir,
|
|
@@ -3914,11 +4545,11 @@ function getProjectName(cwd) {
|
|
|
3914
4545
|
stdio: ["pipe", "pipe", "pipe"]
|
|
3915
4546
|
}).trim();
|
|
3916
4547
|
}
|
|
3917
|
-
_cached2 =
|
|
4548
|
+
_cached2 = path13.basename(repoRoot);
|
|
3918
4549
|
_cachedCwd = dir;
|
|
3919
4550
|
return _cached2;
|
|
3920
4551
|
} catch {
|
|
3921
|
-
_cached2 =
|
|
4552
|
+
_cached2 = path13.basename(dir);
|
|
3922
4553
|
_cachedCwd = dir;
|
|
3923
4554
|
return _cached2;
|
|
3924
4555
|
}
|
|
@@ -3936,56 +4567,13 @@ var init_project_name = __esm({
|
|
|
3936
4567
|
}
|
|
3937
4568
|
});
|
|
3938
4569
|
|
|
3939
|
-
// src/lib/daemon-auth.ts
|
|
3940
|
-
var daemon_auth_exports = {};
|
|
3941
|
-
__export(daemon_auth_exports, {
|
|
3942
|
-
DAEMON_TOKEN_PATH: () => DAEMON_TOKEN_PATH,
|
|
3943
|
-
ensureDaemonToken: () => ensureDaemonToken,
|
|
3944
|
-
readDaemonToken: () => readDaemonToken
|
|
3945
|
-
});
|
|
3946
|
-
import crypto2 from "crypto";
|
|
3947
|
-
import path12 from "path";
|
|
3948
|
-
import { existsSync as existsSync9, readFileSync as readFileSync6, writeFileSync as writeFileSync6 } from "fs";
|
|
3949
|
-
function normalizeToken(token) {
|
|
3950
|
-
if (!token) return null;
|
|
3951
|
-
const trimmed = token.trim();
|
|
3952
|
-
return trimmed.length > 0 ? trimmed : null;
|
|
3953
|
-
}
|
|
3954
|
-
function readDaemonToken() {
|
|
3955
|
-
try {
|
|
3956
|
-
if (!existsSync9(DAEMON_TOKEN_PATH)) return null;
|
|
3957
|
-
return normalizeToken(readFileSync6(DAEMON_TOKEN_PATH, "utf8"));
|
|
3958
|
-
} catch {
|
|
3959
|
-
return null;
|
|
3960
|
-
}
|
|
3961
|
-
}
|
|
3962
|
-
function ensureDaemonToken(seed) {
|
|
3963
|
-
const existing = readDaemonToken();
|
|
3964
|
-
if (existing) return existing;
|
|
3965
|
-
const token = normalizeToken(seed) ?? crypto2.randomBytes(32).toString("hex");
|
|
3966
|
-
ensurePrivateDirSync(EXE_AI_DIR);
|
|
3967
|
-
writeFileSync6(DAEMON_TOKEN_PATH, `${token}
|
|
3968
|
-
`, "utf8");
|
|
3969
|
-
enforcePrivateFileSync(DAEMON_TOKEN_PATH);
|
|
3970
|
-
return token;
|
|
3971
|
-
}
|
|
3972
|
-
var DAEMON_TOKEN_PATH;
|
|
3973
|
-
var init_daemon_auth = __esm({
|
|
3974
|
-
"src/lib/daemon-auth.ts"() {
|
|
3975
|
-
"use strict";
|
|
3976
|
-
init_config();
|
|
3977
|
-
init_secure_files();
|
|
3978
|
-
DAEMON_TOKEN_PATH = path12.join(EXE_AI_DIR, "exed.token");
|
|
3979
|
-
}
|
|
3980
|
-
});
|
|
3981
|
-
|
|
3982
4570
|
// src/adapters/claude/hooks/ingest.ts
|
|
3983
4571
|
init_config();
|
|
3984
4572
|
init_config();
|
|
3985
|
-
import { spawn } from "child_process";
|
|
3986
|
-
import { readFileSync as
|
|
3987
|
-
import
|
|
3988
|
-
import { fileURLToPath } from "url";
|
|
4573
|
+
import { spawn as spawn2 } from "child_process";
|
|
4574
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync7, mkdirSync as mkdirSync6, existsSync as existsSync11, openSync as openSync2, closeSync as closeSync2 } from "fs";
|
|
4575
|
+
import path14 from "path";
|
|
4576
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3989
4577
|
|
|
3990
4578
|
// src/lib/active-agent.ts
|
|
3991
4579
|
init_config();
|
|
@@ -4379,10 +4967,10 @@ if (!loadConfigSync().autoIngestion) {
|
|
|
4379
4967
|
if (!process.env.EXE_OS_DIR) {
|
|
4380
4968
|
process.env.EXE_OS_DIR = EXE_AI_DIR;
|
|
4381
4969
|
}
|
|
4382
|
-
var WORKER_LOG_PATH =
|
|
4970
|
+
var WORKER_LOG_PATH = path14.join(EXE_AI_DIR, "workers.log");
|
|
4383
4971
|
function openWorkerLog() {
|
|
4384
4972
|
try {
|
|
4385
|
-
return
|
|
4973
|
+
return openSync2(WORKER_LOG_PATH, "a");
|
|
4386
4974
|
} catch {
|
|
4387
4975
|
return "ignore";
|
|
4388
4976
|
}
|
|
@@ -4391,13 +4979,13 @@ var ALLOWED_TOOL_RE = /^(Bash|Edit|Write|Read|Glob|Grep|Agent|apply_patch|mcp__.
|
|
|
4391
4979
|
var WRITE_TOOL_RE = /^(Bash|Edit|Write|apply_patch)$/;
|
|
4392
4980
|
var SUMMARY_INTERVAL = 25;
|
|
4393
4981
|
var MIN_WRITES_FOR_SUMMARY = 3;
|
|
4394
|
-
var COUNTER_DIR =
|
|
4982
|
+
var COUNTER_DIR = path14.join(EXE_AI_DIR, "session-cache");
|
|
4395
4983
|
function getCounterPath(sessionId) {
|
|
4396
|
-
return
|
|
4984
|
+
return path14.join(COUNTER_DIR, `counter-${sessionId}.json`);
|
|
4397
4985
|
}
|
|
4398
4986
|
function loadCounter(sessionId) {
|
|
4399
4987
|
try {
|
|
4400
|
-
const raw =
|
|
4988
|
+
const raw = readFileSync8(getCounterPath(sessionId), "utf8");
|
|
4401
4989
|
return JSON.parse(raw);
|
|
4402
4990
|
} catch {
|
|
4403
4991
|
return { total: 0, writes: 0, pipelineWrites: 0, lastSummaryAt: 0, pipelineDetected: false };
|
|
@@ -4422,8 +5010,8 @@ process.stdin.on("end", async () => {
|
|
|
4422
5010
|
try {
|
|
4423
5011
|
if (process.env.EXE_DEBUG_HOOKS) {
|
|
4424
5012
|
try {
|
|
4425
|
-
const debugPath =
|
|
4426
|
-
mkdirSync6(
|
|
5013
|
+
const debugPath = path14.join(EXE_AI_DIR, "logs", "hook-stdin-ingest.log");
|
|
5014
|
+
mkdirSync6(path14.dirname(debugPath), { recursive: true });
|
|
4427
5015
|
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
4428
5016
|
const snippet = input.length > 2e3 ? input.slice(0, 2e3) + "...[truncated]" : input;
|
|
4429
5017
|
writeFileSync7(debugPath, `[${ts}] ${snippet}
|
|
@@ -4511,14 +5099,14 @@ Your output files must start with: exe/output/${agent.agentId}-`
|
|
|
4511
5099
|
const classification = classifyError(errorText);
|
|
4512
5100
|
if (classification === "system" && data.session_id) {
|
|
4513
5101
|
const fp = errorFingerprint(data.tool_name, errorText);
|
|
4514
|
-
const fpFilePath =
|
|
5102
|
+
const fpFilePath = path14.join(COUNTER_DIR, `bug-fingerprints-${data.session_id}.json`);
|
|
4515
5103
|
let fpData = {
|
|
4516
5104
|
seen: {},
|
|
4517
5105
|
taskCount: 0,
|
|
4518
5106
|
lastTaskAt: ""
|
|
4519
5107
|
};
|
|
4520
5108
|
try {
|
|
4521
|
-
fpData = JSON.parse(
|
|
5109
|
+
fpData = JSON.parse(readFileSync8(fpFilePath, "utf8"));
|
|
4522
5110
|
} catch {
|
|
4523
5111
|
}
|
|
4524
5112
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -4536,15 +5124,15 @@ Your output files must start with: exe/output/${agent.agentId}-`
|
|
|
4536
5124
|
fpData.seen[fp] = { count: 1, firstAt: now, lastAt: now };
|
|
4537
5125
|
fpData.taskCount++;
|
|
4538
5126
|
fpData.lastTaskAt = now;
|
|
4539
|
-
const bugWorkerPath =
|
|
4540
|
-
|
|
5127
|
+
const bugWorkerPath = path14.resolve(
|
|
5128
|
+
path14.dirname(fileURLToPath2(import.meta.url)),
|
|
4541
5129
|
"bug-report-worker.js"
|
|
4542
5130
|
);
|
|
4543
|
-
if (
|
|
5131
|
+
if (existsSync11(bugWorkerPath) && tryAcquireWorkerSlot()) {
|
|
4544
5132
|
const stderrFd2 = openWorkerLog();
|
|
4545
|
-
const projectName = process.cwd().split(
|
|
5133
|
+
const projectName = process.cwd().split(path14.sep).pop() ?? "unknown";
|
|
4546
5134
|
const bugToolInput = data.tool_input ?? {};
|
|
4547
|
-
const bugWorker =
|
|
5135
|
+
const bugWorker = spawn2(process.execPath, [bugWorkerPath], {
|
|
4548
5136
|
detached: true,
|
|
4549
5137
|
stdio: ["ignore", "ignore", stderrFd2],
|
|
4550
5138
|
env: {
|
|
@@ -4561,7 +5149,7 @@ Your output files must start with: exe/output/${agent.agentId}-`
|
|
|
4561
5149
|
if (bugWorker.pid) registerWorkerPid(bugWorker.pid);
|
|
4562
5150
|
bugWorker.unref();
|
|
4563
5151
|
if (typeof stderrFd2 === "number") try {
|
|
4564
|
-
|
|
5152
|
+
closeSync2(stderrFd2);
|
|
4565
5153
|
} catch {
|
|
4566
5154
|
}
|
|
4567
5155
|
} else {
|
|
@@ -4588,13 +5176,13 @@ Your output files must start with: exe/output/${agent.agentId}-`
|
|
|
4588
5176
|
}
|
|
4589
5177
|
const callsSinceLastSummary = counter.total - counter.lastSummaryAt;
|
|
4590
5178
|
if (callsSinceLastSummary >= SUMMARY_INTERVAL && counter.writes >= MIN_WRITES_FOR_SUMMARY) {
|
|
4591
|
-
const summaryWorkerPath =
|
|
4592
|
-
|
|
5179
|
+
const summaryWorkerPath = path14.resolve(
|
|
5180
|
+
path14.dirname(fileURLToPath2(import.meta.url)),
|
|
4593
5181
|
"summary-worker.js"
|
|
4594
5182
|
);
|
|
4595
|
-
if (
|
|
5183
|
+
if (existsSync11(summaryWorkerPath) && tryAcquireWorkerSlot()) {
|
|
4596
5184
|
const stderrFd2 = openWorkerLog();
|
|
4597
|
-
const summaryWorker =
|
|
5185
|
+
const summaryWorker = spawn2(process.execPath, [summaryWorkerPath], {
|
|
4598
5186
|
detached: true,
|
|
4599
5187
|
stdio: ["ignore", "ignore", stderrFd2],
|
|
4600
5188
|
env: {
|
|
@@ -4609,7 +5197,7 @@ Your output files must start with: exe/output/${agent.agentId}-`
|
|
|
4609
5197
|
if (summaryWorker.pid) registerWorkerPid(summaryWorker.pid);
|
|
4610
5198
|
summaryWorker.unref();
|
|
4611
5199
|
if (typeof stderrFd2 === "number") try {
|
|
4612
|
-
|
|
5200
|
+
closeSync2(stderrFd2);
|
|
4613
5201
|
} catch {
|
|
4614
5202
|
}
|
|
4615
5203
|
} else {
|
|
@@ -4638,14 +5226,14 @@ WARNING: You are writing code without running the build pipeline. If this task a
|
|
|
4638
5226
|
const bashOutput = typeof data.tool_response === "string" ? data.tool_response : JSON.stringify(data.tool_response ?? "");
|
|
4639
5227
|
const commitMatch = bashOutput.match(/\[(\S+)\s+([a-f0-9]{7,40})\]\s+(.+)/);
|
|
4640
5228
|
if (commitMatch) {
|
|
4641
|
-
const commitWorkerPath =
|
|
4642
|
-
|
|
5229
|
+
const commitWorkerPath = path14.resolve(
|
|
5230
|
+
path14.dirname(fileURLToPath2(import.meta.url)),
|
|
4643
5231
|
"commit-complete.js"
|
|
4644
5232
|
);
|
|
4645
|
-
if (
|
|
5233
|
+
if (existsSync11(commitWorkerPath) && tryAcquireWorkerSlot()) {
|
|
4646
5234
|
const stderrFd2 = openWorkerLog();
|
|
4647
|
-
const projectName = process.cwd().split(
|
|
4648
|
-
const commitWorker =
|
|
5235
|
+
const projectName = process.cwd().split(path14.sep).pop() ?? "unknown";
|
|
5236
|
+
const commitWorker = spawn2(process.execPath, [commitWorkerPath], {
|
|
4649
5237
|
detached: true,
|
|
4650
5238
|
stdio: ["ignore", "ignore", stderrFd2],
|
|
4651
5239
|
env: {
|
|
@@ -4659,7 +5247,7 @@ WARNING: You are writing code without running the build pipeline. If this task a
|
|
|
4659
5247
|
if (commitWorker.pid) registerWorkerPid(commitWorker.pid);
|
|
4660
5248
|
commitWorker.unref();
|
|
4661
5249
|
if (typeof stderrFd2 === "number") try {
|
|
4662
|
-
|
|
5250
|
+
closeSync2(stderrFd2);
|
|
4663
5251
|
} catch {
|
|
4664
5252
|
}
|
|
4665
5253
|
}
|
|
@@ -4670,8 +5258,8 @@ WARNING: You are writing code without running the build pipeline. If this task a
|
|
|
4670
5258
|
}
|
|
4671
5259
|
let sentViaDaemon = false;
|
|
4672
5260
|
try {
|
|
4673
|
-
const socketPath = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ??
|
|
4674
|
-
if (
|
|
5261
|
+
const socketPath = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ?? path14.join(EXE_AI_DIR, "exed.sock");
|
|
5262
|
+
if (existsSync11(socketPath)) {
|
|
4675
5263
|
const { extractSemanticText: extractSemanticText2 } = await Promise.resolve().then(() => (init_content_extractor(), content_extractor_exports));
|
|
4676
5264
|
const { getProjectName: getProjectName2 } = await Promise.resolve().then(() => (init_project_name(), project_name_exports));
|
|
4677
5265
|
const { canCoordinate: canCoordinate2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
@@ -4680,9 +5268,9 @@ WARNING: You are writing code without running the build pipeline. If this task a
|
|
|
4680
5268
|
if (rawText.length >= 50) {
|
|
4681
5269
|
let taskId = null;
|
|
4682
5270
|
try {
|
|
4683
|
-
const cachePath =
|
|
4684
|
-
if (
|
|
4685
|
-
const cached = JSON.parse(
|
|
5271
|
+
const cachePath = path14.join(EXE_AI_DIR, "session-cache", `current-task-${agent.agentId}.json`);
|
|
5272
|
+
if (existsSync11(cachePath)) {
|
|
5273
|
+
const cached = JSON.parse(readFileSync8(cachePath, "utf8"));
|
|
4686
5274
|
taskId = cached.taskId ?? null;
|
|
4687
5275
|
}
|
|
4688
5276
|
} catch {
|
|
@@ -4710,8 +5298,8 @@ WARNING: You are writing code without running the build pipeline. If this task a
|
|
|
4710
5298
|
draft: isDraft,
|
|
4711
5299
|
trajectory: { input: toolInputStr, tool: data.tool_name, output: toolOutputStr, result_type: hasError ? "error" : "success" }
|
|
4712
5300
|
}) + "\n";
|
|
4713
|
-
const
|
|
4714
|
-
const sock =
|
|
5301
|
+
const net2 = await import("net");
|
|
5302
|
+
const sock = net2.connect(socketPath);
|
|
4715
5303
|
sock.on("error", () => {
|
|
4716
5304
|
});
|
|
4717
5305
|
sock.write(payload, () => {
|
|
@@ -4728,8 +5316,8 @@ WARNING: You are writing code without running the build pipeline. If this task a
|
|
|
4728
5316
|
setTimeout(() => process.exit(0), 10);
|
|
4729
5317
|
return;
|
|
4730
5318
|
}
|
|
4731
|
-
const workerPath =
|
|
4732
|
-
|
|
5319
|
+
const workerPath = path14.resolve(
|
|
5320
|
+
path14.dirname(fileURLToPath2(import.meta.url)),
|
|
4733
5321
|
"ingest-worker.js"
|
|
4734
5322
|
);
|
|
4735
5323
|
if (!tryAcquireWorkerSlot()) {
|
|
@@ -4737,7 +5325,7 @@ WARNING: You are writing code without running the build pipeline. If this task a
|
|
|
4737
5325
|
process.exit(0);
|
|
4738
5326
|
}
|
|
4739
5327
|
const stderrFd = openWorkerLog();
|
|
4740
|
-
const worker =
|
|
5328
|
+
const worker = spawn2(process.execPath, [workerPath], {
|
|
4741
5329
|
detached: true,
|
|
4742
5330
|
stdio: ["pipe", "ignore", stderrFd],
|
|
4743
5331
|
env: { ...process.env, AGENT_ID: agent.agentId, AGENT_ROLE: agent.agentRole }
|
|
@@ -4747,7 +5335,7 @@ WARNING: You are writing code without running the build pipeline. If this task a
|
|
|
4747
5335
|
worker.stdin.end();
|
|
4748
5336
|
worker.unref();
|
|
4749
5337
|
if (typeof stderrFd === "number") try {
|
|
4750
|
-
|
|
5338
|
+
closeSync2(stderrFd);
|
|
4751
5339
|
} catch {
|
|
4752
5340
|
}
|
|
4753
5341
|
} catch {
|