@askexenow/exe-os 0.9.8 → 0.9.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/backfill-conversations.js +222 -49
- package/dist/bin/backfill-responses.js +221 -48
- package/dist/bin/backfill-vectors.js +225 -52
- package/dist/bin/cleanup-stale-review-tasks.js +150 -28
- package/dist/bin/cli.js +1295 -856
- package/dist/bin/exe-agent-config.js +36 -8
- package/dist/bin/exe-agent.js +14 -4
- package/dist/bin/exe-assign.js +221 -48
- package/dist/bin/exe-boot.js +778 -427
- package/dist/bin/exe-call.js +41 -13
- package/dist/bin/exe-cloud.js +163 -58
- package/dist/bin/exe-dispatch.js +276 -139
- package/dist/bin/exe-doctor.js +145 -27
- package/dist/bin/exe-export-behaviors.js +141 -23
- package/dist/bin/exe-forget.js +137 -19
- package/dist/bin/exe-gateway.js +677 -388
- package/dist/bin/exe-heartbeat.js +227 -108
- package/dist/bin/exe-kill.js +138 -20
- package/dist/bin/exe-launch-agent.js +172 -39
- package/dist/bin/exe-link.js +291 -100
- package/dist/bin/exe-new-employee.js +214 -106
- package/dist/bin/exe-pending-messages.js +395 -33
- package/dist/bin/exe-pending-notifications.js +684 -99
- package/dist/bin/exe-pending-reviews.js +420 -74
- package/dist/bin/exe-rename.js +147 -49
- package/dist/bin/exe-review.js +138 -20
- package/dist/bin/exe-search.js +240 -69
- package/dist/bin/exe-session-cleanup.js +440 -250
- package/dist/bin/exe-settings.js +61 -17
- package/dist/bin/exe-start-codex.js +158 -39
- package/dist/bin/exe-start-opencode.js +157 -38
- package/dist/bin/exe-status.js +151 -29
- package/dist/bin/exe-team.js +138 -20
- package/dist/bin/git-sweep.js +404 -212
- package/dist/bin/graph-backfill.js +137 -19
- package/dist/bin/graph-export.js +140 -22
- package/dist/bin/install.js +90 -61
- package/dist/bin/scan-tasks.js +412 -220
- package/dist/bin/setup.js +564 -293
- package/dist/bin/shard-migrate.js +139 -21
- package/dist/bin/update.js +138 -49
- package/dist/bin/wiki-sync.js +137 -19
- package/dist/gateway/index.js +533 -320
- package/dist/hooks/bug-report-worker.js +344 -193
- package/dist/hooks/codex-stop-task-finalizer.js +4678 -0
- package/dist/hooks/commit-complete.js +402 -210
- package/dist/hooks/error-recall.js +245 -74
- package/dist/hooks/exe-heartbeat-hook.js +16 -6
- package/dist/hooks/ingest-worker.js +3423 -3157
- package/dist/hooks/ingest.js +832 -97
- package/dist/hooks/instructions-loaded.js +227 -54
- package/dist/hooks/notification.js +216 -43
- package/dist/hooks/post-compact.js +239 -62
- package/dist/hooks/pre-compact.js +408 -216
- package/dist/hooks/pre-tool-use.js +268 -90
- package/dist/hooks/prompt-ingest-worker.js +352 -102
- package/dist/hooks/prompt-submit.js +541 -328
- package/dist/hooks/response-ingest-worker.js +372 -122
- package/dist/hooks/session-end.js +443 -240
- package/dist/hooks/session-start.js +313 -127
- package/dist/hooks/stop.js +293 -98
- package/dist/hooks/subagent-stop.js +239 -62
- package/dist/hooks/summary-worker.js +568 -236
- package/dist/index.js +538 -324
- package/dist/lib/agent-config.js +28 -6
- package/dist/lib/cloud-sync.js +284 -105
- package/dist/lib/config.js +30 -10
- package/dist/lib/consolidation.js +16 -6
- package/dist/lib/database.js +123 -25
- package/dist/lib/db-daemon-client.js +73 -19
- package/dist/lib/db.js +123 -25
- package/dist/lib/device-registry.js +133 -35
- package/dist/lib/embedder.js +107 -32
- package/dist/lib/employee-templates.js +14 -4
- package/dist/lib/employees.js +41 -13
- package/dist/lib/exe-daemon-client.js +88 -22
- package/dist/lib/exe-daemon.js +935 -587
- package/dist/lib/hybrid-search.js +240 -69
- package/dist/lib/identity.js +18 -8
- package/dist/lib/license.js +133 -48
- package/dist/lib/messaging.js +116 -56
- package/dist/lib/reminders.js +14 -4
- package/dist/lib/schedules.js +137 -19
- package/dist/lib/skill-learning.js +33 -6
- package/dist/lib/store.js +137 -19
- package/dist/lib/task-router.js +14 -4
- package/dist/lib/tasks.js +280 -234
- package/dist/lib/tmux-routing.js +172 -125
- package/dist/lib/token-spend.js +26 -8
- package/dist/mcp/server.js +1326 -609
- package/dist/mcp/tools/complete-reminder.js +14 -4
- package/dist/mcp/tools/create-reminder.js +14 -4
- package/dist/mcp/tools/create-task.js +306 -248
- package/dist/mcp/tools/deactivate-behavior.js +16 -6
- package/dist/mcp/tools/list-reminders.js +14 -4
- package/dist/mcp/tools/list-tasks.js +123 -107
- package/dist/mcp/tools/send-message.js +75 -29
- package/dist/mcp/tools/update-task.js +1848 -199
- package/dist/runtime/index.js +441 -248
- package/dist/tui/App.js +761 -424
- package/package.json +1 -1
|
@@ -19,9 +19,47 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
19
19
|
};
|
|
20
20
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
21
|
|
|
22
|
+
// src/lib/secure-files.ts
|
|
23
|
+
import { chmodSync, existsSync, mkdirSync } from "fs";
|
|
24
|
+
import { chmod, mkdir } from "fs/promises";
|
|
25
|
+
async function ensurePrivateDir(dirPath) {
|
|
26
|
+
await mkdir(dirPath, { recursive: true, mode: PRIVATE_DIR_MODE });
|
|
27
|
+
try {
|
|
28
|
+
await chmod(dirPath, PRIVATE_DIR_MODE);
|
|
29
|
+
} catch {
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function ensurePrivateDirSync(dirPath) {
|
|
33
|
+
mkdirSync(dirPath, { recursive: true, mode: PRIVATE_DIR_MODE });
|
|
34
|
+
try {
|
|
35
|
+
chmodSync(dirPath, PRIVATE_DIR_MODE);
|
|
36
|
+
} catch {
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async function enforcePrivateFile(filePath) {
|
|
40
|
+
try {
|
|
41
|
+
await chmod(filePath, PRIVATE_FILE_MODE);
|
|
42
|
+
} catch {
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function enforcePrivateFileSync(filePath) {
|
|
46
|
+
try {
|
|
47
|
+
if (existsSync(filePath)) chmodSync(filePath, PRIVATE_FILE_MODE);
|
|
48
|
+
} catch {
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
var PRIVATE_DIR_MODE, PRIVATE_FILE_MODE;
|
|
52
|
+
var init_secure_files = __esm({
|
|
53
|
+
"src/lib/secure-files.ts"() {
|
|
54
|
+
"use strict";
|
|
55
|
+
PRIVATE_DIR_MODE = 448;
|
|
56
|
+
PRIVATE_FILE_MODE = 384;
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
22
60
|
// src/lib/config.ts
|
|
23
|
-
import { readFile, writeFile
|
|
24
|
-
import { readFileSync, existsSync, renameSync } from "fs";
|
|
61
|
+
import { readFile, writeFile } from "fs/promises";
|
|
62
|
+
import { readFileSync, existsSync as existsSync2, renameSync } from "fs";
|
|
25
63
|
import path from "path";
|
|
26
64
|
import os from "os";
|
|
27
65
|
function resolveDataDir() {
|
|
@@ -29,7 +67,7 @@ function resolveDataDir() {
|
|
|
29
67
|
if (process.env.EXE_MEM_DIR) return process.env.EXE_MEM_DIR;
|
|
30
68
|
const newDir = path.join(os.homedir(), ".exe-os");
|
|
31
69
|
const legacyDir = path.join(os.homedir(), ".exe-mem");
|
|
32
|
-
if (!
|
|
70
|
+
if (!existsSync2(newDir) && existsSync2(legacyDir)) {
|
|
33
71
|
try {
|
|
34
72
|
renameSync(legacyDir, newDir);
|
|
35
73
|
process.stderr.write(`[exe-os] Migrated data directory: ~/.exe-mem \u2192 ~/.exe-os
|
|
@@ -92,9 +130,9 @@ function normalizeAutoUpdate(raw) {
|
|
|
92
130
|
}
|
|
93
131
|
async function loadConfig() {
|
|
94
132
|
const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
|
|
95
|
-
await
|
|
133
|
+
await ensurePrivateDir(dir);
|
|
96
134
|
const configPath = path.join(dir, "config.json");
|
|
97
|
-
if (!
|
|
135
|
+
if (!existsSync2(configPath)) {
|
|
98
136
|
return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
|
|
99
137
|
}
|
|
100
138
|
const raw = await readFile(configPath, "utf-8");
|
|
@@ -107,6 +145,7 @@ async function loadConfig() {
|
|
|
107
145
|
`);
|
|
108
146
|
try {
|
|
109
147
|
await writeFile(configPath, JSON.stringify(migratedCfg, null, 2) + "\n");
|
|
148
|
+
await enforcePrivateFile(configPath);
|
|
110
149
|
} catch {
|
|
111
150
|
}
|
|
112
151
|
}
|
|
@@ -126,6 +165,7 @@ var EXE_AI_DIR, DB_PATH, MODELS_DIR, CONFIG_PATH, LEGACY_LANCE_PATH, CURRENT_CON
|
|
|
126
165
|
var init_config = __esm({
|
|
127
166
|
"src/lib/config.ts"() {
|
|
128
167
|
"use strict";
|
|
168
|
+
init_secure_files();
|
|
129
169
|
EXE_AI_DIR = resolveDataDir();
|
|
130
170
|
DB_PATH = path.join(EXE_AI_DIR, "memories.db");
|
|
131
171
|
MODELS_DIR = path.join(EXE_AI_DIR, "models");
|
|
@@ -310,10 +350,10 @@ __export(agent_config_exports, {
|
|
|
310
350
|
saveAgentConfig: () => saveAgentConfig,
|
|
311
351
|
setAgentRuntime: () => setAgentRuntime
|
|
312
352
|
});
|
|
313
|
-
import { readFileSync as readFileSync2, writeFileSync, existsSync as
|
|
353
|
+
import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync3 } from "fs";
|
|
314
354
|
import path2 from "path";
|
|
315
355
|
function loadAgentConfig() {
|
|
316
|
-
if (!
|
|
356
|
+
if (!existsSync3(AGENT_CONFIG_PATH)) return {};
|
|
317
357
|
try {
|
|
318
358
|
return JSON.parse(readFileSync2(AGENT_CONFIG_PATH, "utf-8"));
|
|
319
359
|
} catch {
|
|
@@ -322,8 +362,9 @@ function loadAgentConfig() {
|
|
|
322
362
|
}
|
|
323
363
|
function saveAgentConfig(config) {
|
|
324
364
|
const dir = path2.dirname(AGENT_CONFIG_PATH);
|
|
325
|
-
|
|
365
|
+
ensurePrivateDirSync(dir);
|
|
326
366
|
writeFileSync(AGENT_CONFIG_PATH, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
367
|
+
enforcePrivateFileSync(AGENT_CONFIG_PATH);
|
|
327
368
|
}
|
|
328
369
|
function getAgentRuntime(agentId) {
|
|
329
370
|
const config = loadAgentConfig();
|
|
@@ -363,6 +404,7 @@ var init_agent_config = __esm({
|
|
|
363
404
|
"use strict";
|
|
364
405
|
init_config();
|
|
365
406
|
init_runtime_table();
|
|
407
|
+
init_secure_files();
|
|
366
408
|
AGENT_CONFIG_PATH = path2.join(EXE_AI_DIR, "agent-config.json");
|
|
367
409
|
KNOWN_RUNTIMES = {
|
|
368
410
|
claude: ["claude-opus-4", "claude-sonnet-4", "claude-haiku-4.5"],
|
|
@@ -410,7 +452,7 @@ __export(employees_exports, {
|
|
|
410
452
|
validateEmployeeName: () => validateEmployeeName
|
|
411
453
|
});
|
|
412
454
|
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
413
|
-
import { existsSync as
|
|
455
|
+
import { existsSync as existsSync4, symlinkSync, readlinkSync, readFileSync as readFileSync3, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
|
|
414
456
|
import { execSync as execSync2 } from "child_process";
|
|
415
457
|
import path3 from "path";
|
|
416
458
|
import os2 from "os";
|
|
@@ -449,7 +491,7 @@ function validateEmployeeName(name) {
|
|
|
449
491
|
return { valid: true };
|
|
450
492
|
}
|
|
451
493
|
async function loadEmployees(employeesPath = EMPLOYEES_PATH) {
|
|
452
|
-
if (!
|
|
494
|
+
if (!existsSync4(employeesPath)) {
|
|
453
495
|
return [];
|
|
454
496
|
}
|
|
455
497
|
const raw = await readFile2(employeesPath, "utf-8");
|
|
@@ -464,7 +506,7 @@ async function saveEmployees(employees, employeesPath = EMPLOYEES_PATH) {
|
|
|
464
506
|
await writeFile2(employeesPath, JSON.stringify(employees, null, 2) + "\n", "utf-8");
|
|
465
507
|
}
|
|
466
508
|
function loadEmployeesSync(employeesPath = EMPLOYEES_PATH) {
|
|
467
|
-
if (!
|
|
509
|
+
if (!existsSync4(employeesPath)) return [];
|
|
468
510
|
try {
|
|
469
511
|
return JSON.parse(readFileSync3(employeesPath, "utf-8"));
|
|
470
512
|
} catch {
|
|
@@ -512,7 +554,7 @@ function appendToCoordinatorTeam(employee) {
|
|
|
512
554
|
const coordinator = getCoordinatorEmployee(loadEmployeesSync());
|
|
513
555
|
if (!coordinator) return;
|
|
514
556
|
const idPath = path3.join(IDENTITY_DIR, `${coordinator.name}.md`);
|
|
515
|
-
if (!
|
|
557
|
+
if (!existsSync4(idPath)) return;
|
|
516
558
|
const content = readFileSync3(idPath, "utf-8");
|
|
517
559
|
if (content.includes(`**${capitalize(employee.name)}`)) return;
|
|
518
560
|
const teamMatch = content.match(TEAM_SECTION_RE);
|
|
@@ -566,9 +608,9 @@ async function normalizeRosterCase(rosterPath) {
|
|
|
566
608
|
const identityDir = path3.join(os2.homedir(), ".exe-os", "identity");
|
|
567
609
|
const oldPath = path3.join(identityDir, `${oldName}.md`);
|
|
568
610
|
const newPath = path3.join(identityDir, `${emp.name}.md`);
|
|
569
|
-
if (
|
|
611
|
+
if (existsSync4(oldPath) && !existsSync4(newPath)) {
|
|
570
612
|
renameSync2(oldPath, newPath);
|
|
571
|
-
} else if (
|
|
613
|
+
} else if (existsSync4(oldPath) && oldPath !== newPath) {
|
|
572
614
|
const content = readFileSync3(oldPath, "utf-8");
|
|
573
615
|
writeFileSync2(newPath, content, "utf-8");
|
|
574
616
|
if (oldPath.toLowerCase() !== newPath.toLowerCase()) {
|
|
@@ -611,7 +653,7 @@ function registerBinSymlinks(name) {
|
|
|
611
653
|
for (const suffix of ["", "-opencode"]) {
|
|
612
654
|
const linkName = `${name}${suffix}`;
|
|
613
655
|
const linkPath = path3.join(binDir, linkName);
|
|
614
|
-
if (
|
|
656
|
+
if (existsSync4(linkPath)) {
|
|
615
657
|
skipped.push(linkName);
|
|
616
658
|
continue;
|
|
617
659
|
}
|
|
@@ -786,7 +828,7 @@ var init_provider_table = __esm({
|
|
|
786
828
|
});
|
|
787
829
|
|
|
788
830
|
// src/lib/intercom-queue.ts
|
|
789
|
-
import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, renameSync as renameSync3, existsSync as
|
|
831
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, renameSync as renameSync3, existsSync as existsSync5, mkdirSync as mkdirSync3 } from "fs";
|
|
790
832
|
import path6 from "path";
|
|
791
833
|
import os4 from "os";
|
|
792
834
|
var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
|
|
@@ -1438,13 +1480,50 @@ var init_database_adapter = __esm({
|
|
|
1438
1480
|
}
|
|
1439
1481
|
});
|
|
1440
1482
|
|
|
1483
|
+
// src/lib/daemon-auth.ts
|
|
1484
|
+
import crypto from "crypto";
|
|
1485
|
+
import path8 from "path";
|
|
1486
|
+
import { existsSync as existsSync6, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
|
|
1487
|
+
function normalizeToken(token) {
|
|
1488
|
+
if (!token) return null;
|
|
1489
|
+
const trimmed = token.trim();
|
|
1490
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
1491
|
+
}
|
|
1492
|
+
function readDaemonToken() {
|
|
1493
|
+
try {
|
|
1494
|
+
if (!existsSync6(DAEMON_TOKEN_PATH)) return null;
|
|
1495
|
+
return normalizeToken(readFileSync6(DAEMON_TOKEN_PATH, "utf8"));
|
|
1496
|
+
} catch {
|
|
1497
|
+
return null;
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
function ensureDaemonToken(seed) {
|
|
1501
|
+
const existing = readDaemonToken();
|
|
1502
|
+
if (existing) return existing;
|
|
1503
|
+
const token = normalizeToken(seed) ?? crypto.randomBytes(32).toString("hex");
|
|
1504
|
+
ensurePrivateDirSync(EXE_AI_DIR);
|
|
1505
|
+
writeFileSync5(DAEMON_TOKEN_PATH, `${token}
|
|
1506
|
+
`, "utf8");
|
|
1507
|
+
enforcePrivateFileSync(DAEMON_TOKEN_PATH);
|
|
1508
|
+
return token;
|
|
1509
|
+
}
|
|
1510
|
+
var DAEMON_TOKEN_PATH;
|
|
1511
|
+
var init_daemon_auth = __esm({
|
|
1512
|
+
"src/lib/daemon-auth.ts"() {
|
|
1513
|
+
"use strict";
|
|
1514
|
+
init_config();
|
|
1515
|
+
init_secure_files();
|
|
1516
|
+
DAEMON_TOKEN_PATH = path8.join(EXE_AI_DIR, "exed.token");
|
|
1517
|
+
}
|
|
1518
|
+
});
|
|
1519
|
+
|
|
1441
1520
|
// src/lib/exe-daemon-client.ts
|
|
1442
1521
|
import net from "net";
|
|
1443
1522
|
import os6 from "os";
|
|
1444
1523
|
import { spawn } from "child_process";
|
|
1445
1524
|
import { randomUUID } from "crypto";
|
|
1446
|
-
import { existsSync as
|
|
1447
|
-
import
|
|
1525
|
+
import { existsSync as existsSync7, unlinkSync as unlinkSync3, readFileSync as readFileSync7, openSync, closeSync, statSync } from "fs";
|
|
1526
|
+
import path9 from "path";
|
|
1448
1527
|
import { fileURLToPath } from "url";
|
|
1449
1528
|
function handleData(chunk) {
|
|
1450
1529
|
_buffer += chunk.toString();
|
|
@@ -1472,9 +1551,9 @@ function handleData(chunk) {
|
|
|
1472
1551
|
}
|
|
1473
1552
|
}
|
|
1474
1553
|
function cleanupStaleFiles() {
|
|
1475
|
-
if (
|
|
1554
|
+
if (existsSync7(PID_PATH)) {
|
|
1476
1555
|
try {
|
|
1477
|
-
const pid = parseInt(
|
|
1556
|
+
const pid = parseInt(readFileSync7(PID_PATH, "utf8").trim(), 10);
|
|
1478
1557
|
if (pid > 0) {
|
|
1479
1558
|
try {
|
|
1480
1559
|
process.kill(pid, 0);
|
|
@@ -1495,11 +1574,11 @@ function cleanupStaleFiles() {
|
|
|
1495
1574
|
}
|
|
1496
1575
|
}
|
|
1497
1576
|
function findPackageRoot() {
|
|
1498
|
-
let dir =
|
|
1499
|
-
const { root } =
|
|
1577
|
+
let dir = path9.dirname(fileURLToPath(import.meta.url));
|
|
1578
|
+
const { root } = path9.parse(dir);
|
|
1500
1579
|
while (dir !== root) {
|
|
1501
|
-
if (
|
|
1502
|
-
dir =
|
|
1580
|
+
if (existsSync7(path9.join(dir, "package.json"))) return dir;
|
|
1581
|
+
dir = path9.dirname(dir);
|
|
1503
1582
|
}
|
|
1504
1583
|
return null;
|
|
1505
1584
|
}
|
|
@@ -1525,16 +1604,17 @@ function spawnDaemon() {
|
|
|
1525
1604
|
process.stderr.write("[exed-client] WARN: cannot find package root\n");
|
|
1526
1605
|
return;
|
|
1527
1606
|
}
|
|
1528
|
-
const daemonPath =
|
|
1529
|
-
if (!
|
|
1607
|
+
const daemonPath = path9.join(pkgRoot, "dist", "lib", "exe-daemon.js");
|
|
1608
|
+
if (!existsSync7(daemonPath)) {
|
|
1530
1609
|
process.stderr.write(`[exed-client] WARN: daemon script not found at ${daemonPath}
|
|
1531
1610
|
`);
|
|
1532
1611
|
return;
|
|
1533
1612
|
}
|
|
1534
1613
|
const resolvedPath = daemonPath;
|
|
1614
|
+
const daemonToken = ensureDaemonToken(process.env[DAEMON_TOKEN_ENV] ?? null);
|
|
1535
1615
|
process.stderr.write(`[exed-client] Spawning daemon: ${resolvedPath}
|
|
1536
1616
|
`);
|
|
1537
|
-
const logPath =
|
|
1617
|
+
const logPath = path9.join(path9.dirname(SOCKET_PATH), "exed.log");
|
|
1538
1618
|
let stderrFd = "ignore";
|
|
1539
1619
|
try {
|
|
1540
1620
|
stderrFd = openSync(logPath, "a");
|
|
@@ -1552,7 +1632,8 @@ function spawnDaemon() {
|
|
|
1552
1632
|
TMUX_PANE: void 0,
|
|
1553
1633
|
// Prevents resolveExeSession() from scoping to one session
|
|
1554
1634
|
EXE_DAEMON_SOCK: SOCKET_PATH,
|
|
1555
|
-
EXE_DAEMON_PID: PID_PATH
|
|
1635
|
+
EXE_DAEMON_PID: PID_PATH,
|
|
1636
|
+
[DAEMON_TOKEN_ENV]: daemonToken
|
|
1556
1637
|
}
|
|
1557
1638
|
});
|
|
1558
1639
|
child.unref();
|
|
@@ -1659,13 +1740,14 @@ function sendDaemonRequest(payload, timeoutMs = REQUEST_TIMEOUT_MS) {
|
|
|
1659
1740
|
return;
|
|
1660
1741
|
}
|
|
1661
1742
|
const id = randomUUID();
|
|
1743
|
+
const token = process.env[DAEMON_TOKEN_ENV] ?? readDaemonToken();
|
|
1662
1744
|
const timer = setTimeout(() => {
|
|
1663
1745
|
_pending.delete(id);
|
|
1664
1746
|
resolve({ error: "Request timeout" });
|
|
1665
1747
|
}, timeoutMs);
|
|
1666
1748
|
_pending.set(id, { resolve, timer });
|
|
1667
1749
|
try {
|
|
1668
|
-
_socket.write(JSON.stringify({ id, ...payload }) + "\n");
|
|
1750
|
+
_socket.write(JSON.stringify({ id, token, ...payload }) + "\n");
|
|
1669
1751
|
} catch {
|
|
1670
1752
|
clearTimeout(timer);
|
|
1671
1753
|
_pending.delete(id);
|
|
@@ -1676,17 +1758,19 @@ function sendDaemonRequest(payload, timeoutMs = REQUEST_TIMEOUT_MS) {
|
|
|
1676
1758
|
function isClientConnected() {
|
|
1677
1759
|
return _connected;
|
|
1678
1760
|
}
|
|
1679
|
-
var SOCKET_PATH, PID_PATH, SPAWN_LOCK_PATH, SPAWN_LOCK_STALE_MS, CONNECT_TIMEOUT_MS, REQUEST_TIMEOUT_MS, _socket, _connected, _buffer, _pending, MAX_BUFFER;
|
|
1761
|
+
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;
|
|
1680
1762
|
var init_exe_daemon_client = __esm({
|
|
1681
1763
|
"src/lib/exe-daemon-client.ts"() {
|
|
1682
1764
|
"use strict";
|
|
1683
1765
|
init_config();
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1766
|
+
init_daemon_auth();
|
|
1767
|
+
SOCKET_PATH = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ?? path9.join(EXE_AI_DIR, "exed.sock");
|
|
1768
|
+
PID_PATH = process.env.EXE_DAEMON_PID ?? process.env.EXE_EMBED_PID ?? path9.join(EXE_AI_DIR, "exed.pid");
|
|
1769
|
+
SPAWN_LOCK_PATH = path9.join(EXE_AI_DIR, "exed-spawn.lock");
|
|
1687
1770
|
SPAWN_LOCK_STALE_MS = 3e4;
|
|
1688
1771
|
CONNECT_TIMEOUT_MS = 15e3;
|
|
1689
1772
|
REQUEST_TIMEOUT_MS = 3e4;
|
|
1773
|
+
DAEMON_TOKEN_ENV = "EXE_DAEMON_TOKEN";
|
|
1690
1774
|
_socket = null;
|
|
1691
1775
|
_connected = false;
|
|
1692
1776
|
_buffer = "";
|
|
@@ -2265,6 +2349,7 @@ async function ensureSchema() {
|
|
|
2265
2349
|
project TEXT NOT NULL,
|
|
2266
2350
|
summary TEXT NOT NULL,
|
|
2267
2351
|
task_file TEXT,
|
|
2352
|
+
session_scope TEXT,
|
|
2268
2353
|
read INTEGER NOT NULL DEFAULT 0,
|
|
2269
2354
|
created_at TEXT NOT NULL
|
|
2270
2355
|
);
|
|
@@ -2273,7 +2358,7 @@ async function ensureSchema() {
|
|
|
2273
2358
|
ON notifications(read);
|
|
2274
2359
|
|
|
2275
2360
|
CREATE INDEX IF NOT EXISTS idx_notifications_agent
|
|
2276
|
-
ON notifications(agent_id);
|
|
2361
|
+
ON notifications(agent_id, session_scope);
|
|
2277
2362
|
|
|
2278
2363
|
CREATE INDEX IF NOT EXISTS idx_notifications_task_file
|
|
2279
2364
|
ON notifications(task_file);
|
|
@@ -2311,6 +2396,7 @@ async function ensureSchema() {
|
|
|
2311
2396
|
target_agent TEXT NOT NULL,
|
|
2312
2397
|
target_project TEXT,
|
|
2313
2398
|
target_device TEXT NOT NULL DEFAULT 'local',
|
|
2399
|
+
session_scope TEXT,
|
|
2314
2400
|
content TEXT NOT NULL,
|
|
2315
2401
|
priority TEXT DEFAULT 'normal',
|
|
2316
2402
|
status TEXT DEFAULT 'pending',
|
|
@@ -2324,10 +2410,31 @@ async function ensureSchema() {
|
|
|
2324
2410
|
);
|
|
2325
2411
|
|
|
2326
2412
|
CREATE INDEX IF NOT EXISTS idx_messages_target
|
|
2327
|
-
ON messages(target_agent, status);
|
|
2413
|
+
ON messages(target_agent, session_scope, status);
|
|
2328
2414
|
|
|
2329
2415
|
CREATE INDEX IF NOT EXISTS idx_messages_conversation_order
|
|
2330
|
-
ON messages(target_agent, from_agent, server_seq);
|
|
2416
|
+
ON messages(target_agent, session_scope, from_agent, server_seq);
|
|
2417
|
+
`);
|
|
2418
|
+
try {
|
|
2419
|
+
await client.execute({
|
|
2420
|
+
sql: `ALTER TABLE notifications ADD COLUMN session_scope TEXT`,
|
|
2421
|
+
args: []
|
|
2422
|
+
});
|
|
2423
|
+
} catch {
|
|
2424
|
+
}
|
|
2425
|
+
try {
|
|
2426
|
+
await client.execute({
|
|
2427
|
+
sql: `ALTER TABLE messages ADD COLUMN session_scope TEXT`,
|
|
2428
|
+
args: []
|
|
2429
|
+
});
|
|
2430
|
+
} catch {
|
|
2431
|
+
}
|
|
2432
|
+
await client.executeMultiple(`
|
|
2433
|
+
CREATE INDEX IF NOT EXISTS idx_notifications_agent_scope_read
|
|
2434
|
+
ON notifications(agent_id, session_scope, read, created_at);
|
|
2435
|
+
|
|
2436
|
+
CREATE INDEX IF NOT EXISTS idx_messages_target_scope_status
|
|
2437
|
+
ON messages(target_agent, session_scope, status, created_at);
|
|
2331
2438
|
`);
|
|
2332
2439
|
try {
|
|
2333
2440
|
await client.execute({
|
|
@@ -2911,6 +3018,13 @@ async function ensureSchema() {
|
|
|
2911
3018
|
} catch {
|
|
2912
3019
|
}
|
|
2913
3020
|
}
|
|
3021
|
+
try {
|
|
3022
|
+
await client.execute({
|
|
3023
|
+
sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
|
|
3024
|
+
args: []
|
|
3025
|
+
});
|
|
3026
|
+
} catch {
|
|
3027
|
+
}
|
|
2914
3028
|
}
|
|
2915
3029
|
async function disposeDatabase() {
|
|
2916
3030
|
if (_walCheckpointTimer) {
|
|
@@ -2949,24 +3063,27 @@ var init_database = __esm({
|
|
|
2949
3063
|
});
|
|
2950
3064
|
|
|
2951
3065
|
// src/lib/license.ts
|
|
2952
|
-
import { readFileSync as
|
|
3066
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, existsSync as existsSync8, mkdirSync as mkdirSync4 } from "fs";
|
|
2953
3067
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
2954
|
-
import
|
|
3068
|
+
import { createRequire as createRequire2 } from "module";
|
|
3069
|
+
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
3070
|
+
import os7 from "os";
|
|
3071
|
+
import path10 from "path";
|
|
2955
3072
|
import { jwtVerify, importSPKI } from "jose";
|
|
2956
3073
|
var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH;
|
|
2957
3074
|
var init_license = __esm({
|
|
2958
3075
|
"src/lib/license.ts"() {
|
|
2959
3076
|
"use strict";
|
|
2960
3077
|
init_config();
|
|
2961
|
-
LICENSE_PATH =
|
|
2962
|
-
CACHE_PATH =
|
|
2963
|
-
DEVICE_ID_PATH =
|
|
3078
|
+
LICENSE_PATH = path10.join(EXE_AI_DIR, "license.key");
|
|
3079
|
+
CACHE_PATH = path10.join(EXE_AI_DIR, "license-cache.json");
|
|
3080
|
+
DEVICE_ID_PATH = path10.join(EXE_AI_DIR, "device-id");
|
|
2964
3081
|
}
|
|
2965
3082
|
});
|
|
2966
3083
|
|
|
2967
3084
|
// src/lib/plan-limits.ts
|
|
2968
|
-
import { readFileSync as
|
|
2969
|
-
import
|
|
3085
|
+
import { readFileSync as readFileSync9, existsSync as existsSync9 } from "fs";
|
|
3086
|
+
import path11 from "path";
|
|
2970
3087
|
var CACHE_PATH2;
|
|
2971
3088
|
var init_plan_limits = __esm({
|
|
2972
3089
|
"src/lib/plan-limits.ts"() {
|
|
@@ -2975,14 +3092,14 @@ var init_plan_limits = __esm({
|
|
|
2975
3092
|
init_employees();
|
|
2976
3093
|
init_license();
|
|
2977
3094
|
init_config();
|
|
2978
|
-
CACHE_PATH2 =
|
|
3095
|
+
CACHE_PATH2 = path11.join(EXE_AI_DIR, "license-cache.json");
|
|
2979
3096
|
}
|
|
2980
3097
|
});
|
|
2981
3098
|
|
|
2982
3099
|
// src/lib/tmux-routing.ts
|
|
2983
|
-
import { readFileSync as
|
|
2984
|
-
import
|
|
2985
|
-
import
|
|
3100
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync7, mkdirSync as mkdirSync5, existsSync as existsSync10, appendFileSync, readdirSync as readdirSync2 } from "fs";
|
|
3101
|
+
import path12 from "path";
|
|
3102
|
+
import os8 from "os";
|
|
2986
3103
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
2987
3104
|
function getMySession() {
|
|
2988
3105
|
return getTransport().getMySession();
|
|
@@ -2995,7 +3112,7 @@ function extractRootExe(name) {
|
|
|
2995
3112
|
}
|
|
2996
3113
|
function getParentExe(sessionKey) {
|
|
2997
3114
|
try {
|
|
2998
|
-
const data = JSON.parse(
|
|
3115
|
+
const data = JSON.parse(readFileSync10(path12.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
|
|
2999
3116
|
return data.parentExe || null;
|
|
3000
3117
|
} catch {
|
|
3001
3118
|
return null;
|
|
@@ -3038,10 +3155,10 @@ var init_tmux_routing = __esm({
|
|
|
3038
3155
|
init_intercom_queue();
|
|
3039
3156
|
init_plan_limits();
|
|
3040
3157
|
init_employees();
|
|
3041
|
-
SPAWN_LOCK_DIR =
|
|
3042
|
-
SESSION_CACHE =
|
|
3043
|
-
INTERCOM_LOG2 =
|
|
3044
|
-
DEBOUNCE_FILE =
|
|
3158
|
+
SPAWN_LOCK_DIR = path12.join(os8.homedir(), ".exe-os", "spawn-locks");
|
|
3159
|
+
SESSION_CACHE = path12.join(os8.homedir(), ".exe-os", "session-cache");
|
|
3160
|
+
INTERCOM_LOG2 = path12.join(os8.homedir(), ".exe-os", "intercom.log");
|
|
3161
|
+
DEBOUNCE_FILE = path12.join(SESSION_CACHE, "intercom-debounce.json");
|
|
3045
3162
|
DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
|
|
3046
3163
|
}
|
|
3047
3164
|
});
|
|
@@ -3083,9 +3200,9 @@ __export(cto_delegation_gate_exports, {
|
|
|
3083
3200
|
hasValidScratchpadEscape: () => hasValidScratchpadEscape,
|
|
3084
3201
|
scratchpadPath: () => scratchpadPath
|
|
3085
3202
|
});
|
|
3086
|
-
import
|
|
3087
|
-
import
|
|
3088
|
-
import { existsSync as
|
|
3203
|
+
import os9 from "os";
|
|
3204
|
+
import path13 from "path";
|
|
3205
|
+
import { existsSync as existsSync11, readFileSync as readFileSync11, statSync as statSync2 } from "fs";
|
|
3089
3206
|
function resolveGatedAgent() {
|
|
3090
3207
|
try {
|
|
3091
3208
|
const employees = loadEmployeesSync();
|
|
@@ -3099,12 +3216,12 @@ function getGatedAgent() {
|
|
|
3099
3216
|
return resolveGatedAgent() || GATED_AGENT;
|
|
3100
3217
|
}
|
|
3101
3218
|
function toWorkspaceRelative(filePath, cwd = process.cwd()) {
|
|
3102
|
-
const normalized =
|
|
3103
|
-
if (normalized.startsWith(cwd +
|
|
3219
|
+
const normalized = path13.normalize(filePath);
|
|
3220
|
+
if (normalized.startsWith(cwd + path13.sep)) {
|
|
3104
3221
|
return normalized.slice(cwd.length + 1);
|
|
3105
3222
|
}
|
|
3106
|
-
if (
|
|
3107
|
-
return
|
|
3223
|
+
if (path13.isAbsolute(normalized)) {
|
|
3224
|
+
return path13.basename(normalized);
|
|
3108
3225
|
}
|
|
3109
3226
|
return normalized;
|
|
3110
3227
|
}
|
|
@@ -3113,8 +3230,8 @@ function isDockerfile(basename) {
|
|
|
3113
3230
|
}
|
|
3114
3231
|
function classifyPath(filePath, cwd) {
|
|
3115
3232
|
const rel = toWorkspaceRelative(filePath, cwd);
|
|
3116
|
-
const basename =
|
|
3117
|
-
const ext =
|
|
3233
|
+
const basename = path13.basename(rel);
|
|
3234
|
+
const ext = path13.extname(rel).toLowerCase();
|
|
3118
3235
|
if (ext === ".md") {
|
|
3119
3236
|
for (const prefix of EXEMPT_MD_DIR_PREFIXES) {
|
|
3120
3237
|
if (rel.startsWith(prefix)) return "exempt";
|
|
@@ -3156,22 +3273,22 @@ async function hasRecentEngineerDispatch(now = Date.now()) {
|
|
|
3156
3273
|
return false;
|
|
3157
3274
|
}
|
|
3158
3275
|
}
|
|
3159
|
-
function scratchpadPath(sessionId, homeDir =
|
|
3160
|
-
return
|
|
3276
|
+
function scratchpadPath(sessionId, homeDir = os9.homedir()) {
|
|
3277
|
+
return path13.join(
|
|
3161
3278
|
homeDir,
|
|
3162
3279
|
".exe-os",
|
|
3163
3280
|
"session-cache",
|
|
3164
3281
|
`cto-scratchpad-${sessionId}.txt`
|
|
3165
3282
|
);
|
|
3166
3283
|
}
|
|
3167
|
-
function hasValidScratchpadEscape(sessionId, now = Date.now(), homeDir =
|
|
3284
|
+
function hasValidScratchpadEscape(sessionId, now = Date.now(), homeDir = os9.homedir()) {
|
|
3168
3285
|
const paths = [scratchpadPath(sessionId, homeDir)];
|
|
3169
3286
|
for (const filePath of paths) {
|
|
3170
|
-
if (!
|
|
3287
|
+
if (!existsSync11(filePath)) continue;
|
|
3171
3288
|
try {
|
|
3172
3289
|
const stat = statSync2(filePath);
|
|
3173
3290
|
if (now - stat.mtimeMs > SCRATCHPAD_MAX_AGE_MS) continue;
|
|
3174
|
-
const body =
|
|
3291
|
+
const body = readFileSync11(filePath, "utf-8");
|
|
3175
3292
|
if (SCRATCHPAD_ESCAPE_PATTERN.test(body)) return true;
|
|
3176
3293
|
} catch {
|
|
3177
3294
|
}
|
|
@@ -3262,14 +3379,14 @@ var init_memory = __esm({
|
|
|
3262
3379
|
|
|
3263
3380
|
// src/lib/keychain.ts
|
|
3264
3381
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
3265
|
-
import { existsSync as
|
|
3266
|
-
import
|
|
3267
|
-
import
|
|
3382
|
+
import { existsSync as existsSync12 } from "fs";
|
|
3383
|
+
import path14 from "path";
|
|
3384
|
+
import os10 from "os";
|
|
3268
3385
|
function getKeyDir() {
|
|
3269
|
-
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ??
|
|
3386
|
+
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path14.join(os10.homedir(), ".exe-os");
|
|
3270
3387
|
}
|
|
3271
3388
|
function getKeyPath() {
|
|
3272
|
-
return
|
|
3389
|
+
return path14.join(getKeyDir(), "master.key");
|
|
3273
3390
|
}
|
|
3274
3391
|
async function tryKeytar() {
|
|
3275
3392
|
try {
|
|
@@ -3290,9 +3407,9 @@ async function getMasterKey() {
|
|
|
3290
3407
|
}
|
|
3291
3408
|
}
|
|
3292
3409
|
const keyPath = getKeyPath();
|
|
3293
|
-
if (!
|
|
3410
|
+
if (!existsSync12(keyPath)) {
|
|
3294
3411
|
process.stderr.write(
|
|
3295
|
-
`[keychain] Key not found at ${keyPath} (HOME=${
|
|
3412
|
+
`[keychain] Key not found at ${keyPath} (HOME=${os10.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
|
|
3296
3413
|
`
|
|
3297
3414
|
);
|
|
3298
3415
|
return null;
|
|
@@ -3377,6 +3494,7 @@ var shard_manager_exports = {};
|
|
|
3377
3494
|
__export(shard_manager_exports, {
|
|
3378
3495
|
disposeShards: () => disposeShards,
|
|
3379
3496
|
ensureShardSchema: () => ensureShardSchema,
|
|
3497
|
+
getOpenShardCount: () => getOpenShardCount,
|
|
3380
3498
|
getReadyShardClient: () => getReadyShardClient,
|
|
3381
3499
|
getShardClient: () => getShardClient,
|
|
3382
3500
|
getShardsDir: () => getShardsDir,
|
|
@@ -3385,15 +3503,18 @@ __export(shard_manager_exports, {
|
|
|
3385
3503
|
listShards: () => listShards,
|
|
3386
3504
|
shardExists: () => shardExists
|
|
3387
3505
|
});
|
|
3388
|
-
import
|
|
3389
|
-
import { existsSync as
|
|
3506
|
+
import path15 from "path";
|
|
3507
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync6, readdirSync as readdirSync3 } from "fs";
|
|
3390
3508
|
import { createClient as createClient2 } from "@libsql/client";
|
|
3391
3509
|
function initShardManager(encryptionKey) {
|
|
3392
3510
|
_encryptionKey = encryptionKey;
|
|
3393
|
-
if (!
|
|
3511
|
+
if (!existsSync13(SHARDS_DIR)) {
|
|
3394
3512
|
mkdirSync6(SHARDS_DIR, { recursive: true });
|
|
3395
3513
|
}
|
|
3396
3514
|
_shardingEnabled = true;
|
|
3515
|
+
if (_evictionTimer) clearInterval(_evictionTimer);
|
|
3516
|
+
_evictionTimer = setInterval(evictIdleShards, EVICTION_INTERVAL_MS);
|
|
3517
|
+
_evictionTimer.unref();
|
|
3397
3518
|
}
|
|
3398
3519
|
function isShardingEnabled() {
|
|
3399
3520
|
return _shardingEnabled;
|
|
@@ -3410,21 +3531,28 @@ function getShardClient(projectName) {
|
|
|
3410
3531
|
throw new Error(`Invalid project name for shard: "${projectName}"`);
|
|
3411
3532
|
}
|
|
3412
3533
|
const cached = _shards.get(safeName);
|
|
3413
|
-
if (cached)
|
|
3414
|
-
|
|
3534
|
+
if (cached) {
|
|
3535
|
+
_shardLastAccess.set(safeName, Date.now());
|
|
3536
|
+
return cached;
|
|
3537
|
+
}
|
|
3538
|
+
while (_shards.size >= MAX_OPEN_SHARDS) {
|
|
3539
|
+
evictLRU();
|
|
3540
|
+
}
|
|
3541
|
+
const dbPath = path15.join(SHARDS_DIR, `${safeName}.db`);
|
|
3415
3542
|
const client = createClient2({
|
|
3416
3543
|
url: `file:${dbPath}`,
|
|
3417
3544
|
encryptionKey: _encryptionKey
|
|
3418
3545
|
});
|
|
3419
3546
|
_shards.set(safeName, client);
|
|
3547
|
+
_shardLastAccess.set(safeName, Date.now());
|
|
3420
3548
|
return client;
|
|
3421
3549
|
}
|
|
3422
3550
|
function shardExists(projectName) {
|
|
3423
3551
|
const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
3424
|
-
return
|
|
3552
|
+
return existsSync13(path15.join(SHARDS_DIR, `${safeName}.db`));
|
|
3425
3553
|
}
|
|
3426
3554
|
function listShards() {
|
|
3427
|
-
if (!
|
|
3555
|
+
if (!existsSync13(SHARDS_DIR)) return [];
|
|
3428
3556
|
return readdirSync3(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
3429
3557
|
}
|
|
3430
3558
|
async function ensureShardSchema(client) {
|
|
@@ -3476,6 +3604,8 @@ async function ensureShardSchema(client) {
|
|
|
3476
3604
|
for (const col of [
|
|
3477
3605
|
"ALTER TABLE memories ADD COLUMN task_id TEXT",
|
|
3478
3606
|
"ALTER TABLE memories ADD COLUMN consolidated INTEGER NOT NULL DEFAULT 0",
|
|
3607
|
+
"ALTER TABLE memories ADD COLUMN author_device_id TEXT",
|
|
3608
|
+
"ALTER TABLE memories ADD COLUMN scope TEXT NOT NULL DEFAULT 'business'",
|
|
3479
3609
|
"ALTER TABLE memories ADD COLUMN importance INTEGER DEFAULT 5",
|
|
3480
3610
|
"ALTER TABLE memories ADD COLUMN status TEXT DEFAULT 'active'",
|
|
3481
3611
|
"ALTER TABLE memories ADD COLUMN wiki_synced INTEGER DEFAULT 0",
|
|
@@ -3613,21 +3743,69 @@ async function getReadyShardClient(projectName) {
|
|
|
3613
3743
|
await ensureShardSchema(client);
|
|
3614
3744
|
return client;
|
|
3615
3745
|
}
|
|
3746
|
+
function evictLRU() {
|
|
3747
|
+
let oldest = null;
|
|
3748
|
+
let oldestTime = Infinity;
|
|
3749
|
+
for (const [name, time] of _shardLastAccess) {
|
|
3750
|
+
if (time < oldestTime) {
|
|
3751
|
+
oldestTime = time;
|
|
3752
|
+
oldest = name;
|
|
3753
|
+
}
|
|
3754
|
+
}
|
|
3755
|
+
if (oldest) {
|
|
3756
|
+
const client = _shards.get(oldest);
|
|
3757
|
+
if (client) {
|
|
3758
|
+
client.close();
|
|
3759
|
+
}
|
|
3760
|
+
_shards.delete(oldest);
|
|
3761
|
+
_shardLastAccess.delete(oldest);
|
|
3762
|
+
}
|
|
3763
|
+
}
|
|
3764
|
+
function evictIdleShards() {
|
|
3765
|
+
const now = Date.now();
|
|
3766
|
+
const toEvict = [];
|
|
3767
|
+
for (const [name, lastAccess] of _shardLastAccess) {
|
|
3768
|
+
if (now - lastAccess > SHARD_IDLE_MS) {
|
|
3769
|
+
toEvict.push(name);
|
|
3770
|
+
}
|
|
3771
|
+
}
|
|
3772
|
+
for (const name of toEvict) {
|
|
3773
|
+
const client = _shards.get(name);
|
|
3774
|
+
if (client) {
|
|
3775
|
+
client.close();
|
|
3776
|
+
}
|
|
3777
|
+
_shards.delete(name);
|
|
3778
|
+
_shardLastAccess.delete(name);
|
|
3779
|
+
}
|
|
3780
|
+
}
|
|
3781
|
+
function getOpenShardCount() {
|
|
3782
|
+
return _shards.size;
|
|
3783
|
+
}
|
|
3616
3784
|
function disposeShards() {
|
|
3785
|
+
if (_evictionTimer) {
|
|
3786
|
+
clearInterval(_evictionTimer);
|
|
3787
|
+
_evictionTimer = null;
|
|
3788
|
+
}
|
|
3617
3789
|
for (const [, client] of _shards) {
|
|
3618
3790
|
client.close();
|
|
3619
3791
|
}
|
|
3620
3792
|
_shards.clear();
|
|
3793
|
+
_shardLastAccess.clear();
|
|
3621
3794
|
_shardingEnabled = false;
|
|
3622
3795
|
_encryptionKey = null;
|
|
3623
3796
|
}
|
|
3624
|
-
var SHARDS_DIR, _shards, _encryptionKey, _shardingEnabled;
|
|
3797
|
+
var SHARDS_DIR, SHARD_IDLE_MS, MAX_OPEN_SHARDS, EVICTION_INTERVAL_MS, _shards, _shardLastAccess, _evictionTimer, _encryptionKey, _shardingEnabled;
|
|
3625
3798
|
var init_shard_manager = __esm({
|
|
3626
3799
|
"src/lib/shard-manager.ts"() {
|
|
3627
3800
|
"use strict";
|
|
3628
3801
|
init_config();
|
|
3629
|
-
SHARDS_DIR =
|
|
3802
|
+
SHARDS_DIR = path15.join(EXE_AI_DIR, "shards");
|
|
3803
|
+
SHARD_IDLE_MS = 5 * 60 * 1e3;
|
|
3804
|
+
MAX_OPEN_SHARDS = 10;
|
|
3805
|
+
EVICTION_INTERVAL_MS = 60 * 1e3;
|
|
3630
3806
|
_shards = /* @__PURE__ */ new Map();
|
|
3807
|
+
_shardLastAccess = /* @__PURE__ */ new Map();
|
|
3808
|
+
_evictionTimer = null;
|
|
3631
3809
|
_encryptionKey = null;
|
|
3632
3810
|
_shardingEnabled = false;
|
|
3633
3811
|
}
|
|
@@ -4400,7 +4578,7 @@ __export(review_gate_exports, {
|
|
|
4400
4578
|
runReviewGate: () => runReviewGate
|
|
4401
4579
|
});
|
|
4402
4580
|
import { execSync as execSync5 } from "child_process";
|
|
4403
|
-
import { existsSync as
|
|
4581
|
+
import { existsSync as existsSync14 } from "fs";
|
|
4404
4582
|
function checkCommitsExist(taskCreatedAt) {
|
|
4405
4583
|
try {
|
|
4406
4584
|
const since = new Date(taskCreatedAt).toISOString();
|
|
@@ -4463,7 +4641,7 @@ function checkTestCoverage(taskCreatedAt) {
|
|
|
4463
4641
|
const testPath = file.replace(/^src\//, "tests/").replace(/\.ts$/, ".test.ts");
|
|
4464
4642
|
const baseName = file.split("/").pop()?.replace(/\.ts$/, "") ?? "";
|
|
4465
4643
|
const testDir = testPath.substring(0, testPath.lastIndexOf("/"));
|
|
4466
|
-
const hasDirectTest =
|
|
4644
|
+
const hasDirectTest = existsSync14(testPath);
|
|
4467
4645
|
let hasRelatedTest = false;
|
|
4468
4646
|
try {
|
|
4469
4647
|
const related = execSync5(
|
|
@@ -4517,9 +4695,9 @@ var init_review_gate = __esm({
|
|
|
4517
4695
|
});
|
|
4518
4696
|
|
|
4519
4697
|
// src/adapters/claude/hooks/pre-tool-use.ts
|
|
4520
|
-
import { existsSync as
|
|
4698
|
+
import { existsSync as existsSync15, writeFileSync as writeFileSync8, mkdirSync as mkdirSync7 } from "fs";
|
|
4521
4699
|
import { execSync as execSync6 } from "child_process";
|
|
4522
|
-
import
|
|
4700
|
+
import path16 from "path";
|
|
4523
4701
|
|
|
4524
4702
|
// src/lib/active-agent.ts
|
|
4525
4703
|
init_config();
|
|
@@ -4633,17 +4811,17 @@ if (!process.env.AGENT_ID) {
|
|
|
4633
4811
|
}
|
|
4634
4812
|
var DELEGATION_TASK_THRESHOLD = 3;
|
|
4635
4813
|
var CTO_ROLES = ["CTO", "executive"];
|
|
4636
|
-
var CACHE_DIR2 =
|
|
4814
|
+
var CACHE_DIR2 = path16.join(EXE_AI_DIR, "session-cache");
|
|
4637
4815
|
var timeout = setTimeout(() => {
|
|
4638
4816
|
process.exit(0);
|
|
4639
4817
|
}, 5e3);
|
|
4640
4818
|
timeout.unref();
|
|
4641
4819
|
function getDelegationFlagPath() {
|
|
4642
|
-
return
|
|
4820
|
+
return path16.join(CACHE_DIR2, `delegation-checkpoint-${getSessionKey()}.json`);
|
|
4643
4821
|
}
|
|
4644
4822
|
function hasDelegationFired() {
|
|
4645
4823
|
try {
|
|
4646
|
-
return
|
|
4824
|
+
return existsSync15(getDelegationFlagPath());
|
|
4647
4825
|
} catch {
|
|
4648
4826
|
return false;
|
|
4649
4827
|
}
|
|
@@ -4651,7 +4829,7 @@ function hasDelegationFired() {
|
|
|
4651
4829
|
function markDelegationFired() {
|
|
4652
4830
|
try {
|
|
4653
4831
|
mkdirSync7(CACHE_DIR2, { recursive: true });
|
|
4654
|
-
|
|
4832
|
+
writeFileSync8(getDelegationFlagPath(), JSON.stringify({ fired: true }));
|
|
4655
4833
|
} catch {
|
|
4656
4834
|
}
|
|
4657
4835
|
}
|