@askexenow/exe-os 0.9.7 → 0.9.8
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 +754 -79
- package/dist/bin/backfill-responses.js +752 -77
- package/dist/bin/backfill-vectors.js +752 -77
- package/dist/bin/cleanup-stale-review-tasks.js +657 -35
- package/dist/bin/cli.js +1388 -605
- package/dist/bin/exe-agent-config.js +123 -95
- package/dist/bin/exe-agent.js +41 -25
- package/dist/bin/exe-assign.js +732 -57
- package/dist/bin/exe-boot.js +784 -153
- package/dist/bin/exe-call.js +209 -138
- package/dist/bin/exe-cloud.js +35 -12
- package/dist/bin/exe-dispatch.js +692 -70
- package/dist/bin/exe-doctor.js +648 -26
- package/dist/bin/exe-export-behaviors.js +650 -20
- package/dist/bin/exe-forget.js +635 -13
- package/dist/bin/exe-gateway.js +1053 -271
- package/dist/bin/exe-heartbeat.js +665 -43
- package/dist/bin/exe-kill.js +646 -16
- package/dist/bin/exe-launch-agent.js +887 -97
- package/dist/bin/exe-link.js +658 -43
- package/dist/bin/exe-new-employee.js +378 -177
- package/dist/bin/exe-pending-messages.js +656 -34
- package/dist/bin/exe-pending-notifications.js +635 -13
- package/dist/bin/exe-pending-reviews.js +659 -37
- package/dist/bin/exe-rename.js +645 -30
- package/dist/bin/exe-review.js +635 -13
- package/dist/bin/exe-search.js +771 -88
- package/dist/bin/exe-session-cleanup.js +834 -150
- package/dist/bin/exe-settings.js +127 -91
- package/dist/bin/exe-start-codex.js +729 -94
- package/dist/bin/exe-start-opencode.js +717 -82
- package/dist/bin/exe-status.js +657 -35
- package/dist/bin/exe-team.js +635 -13
- package/dist/bin/git-sweep.js +720 -89
- package/dist/bin/graph-backfill.js +643 -13
- package/dist/bin/graph-export.js +646 -16
- package/dist/bin/install.js +596 -193
- package/dist/bin/scan-tasks.js +724 -93
- package/dist/bin/setup.js +1038 -210
- package/dist/bin/shard-migrate.js +645 -15
- package/dist/bin/wiki-sync.js +646 -16
- package/dist/gateway/index.js +1027 -245
- package/dist/hooks/bug-report-worker.js +891 -170
- package/dist/hooks/commit-complete.js +718 -87
- package/dist/hooks/error-recall.js +776 -93
- package/dist/hooks/exe-heartbeat-hook.js +85 -71
- package/dist/hooks/ingest-worker.js +840 -156
- package/dist/hooks/ingest.js +90 -73
- package/dist/hooks/instructions-loaded.js +669 -38
- package/dist/hooks/notification.js +661 -30
- package/dist/hooks/post-compact.js +674 -43
- package/dist/hooks/pre-compact.js +718 -87
- package/dist/hooks/pre-tool-use.js +872 -125
- package/dist/hooks/prompt-ingest-worker.js +758 -83
- package/dist/hooks/prompt-submit.js +1060 -319
- package/dist/hooks/response-ingest-worker.js +758 -83
- package/dist/hooks/session-end.js +721 -90
- package/dist/hooks/session-start.js +1031 -207
- package/dist/hooks/stop.js +680 -49
- package/dist/hooks/subagent-stop.js +674 -43
- package/dist/hooks/summary-worker.js +816 -132
- package/dist/index.js +1015 -232
- package/dist/lib/cloud-sync.js +663 -48
- package/dist/lib/consolidation.js +26 -3
- package/dist/lib/database.js +626 -18
- package/dist/lib/db.js +2261 -0
- package/dist/lib/device-registry.js +640 -25
- package/dist/lib/embedder.js +96 -43
- package/dist/lib/employee-templates.js +16 -0
- package/dist/lib/employees.js +259 -83
- package/dist/lib/exe-daemon-client.js +101 -63
- package/dist/lib/exe-daemon.js +894 -162
- package/dist/lib/hybrid-search.js +771 -88
- package/dist/lib/identity.js +27 -7
- package/dist/lib/messaging.js +55 -28
- package/dist/lib/reminders.js +21 -1
- package/dist/lib/schedules.js +636 -14
- package/dist/lib/skill-learning.js +21 -1
- package/dist/lib/store.js +643 -13
- package/dist/lib/task-router.js +82 -71
- package/dist/lib/tasks.js +98 -71
- package/dist/lib/tmux-routing.js +87 -60
- package/dist/lib/token-spend.js +26 -6
- package/dist/mcp/server.js +1784 -458
- package/dist/mcp/tools/complete-reminder.js +21 -1
- package/dist/mcp/tools/create-reminder.js +21 -1
- package/dist/mcp/tools/create-task.js +290 -164
- package/dist/mcp/tools/deactivate-behavior.js +24 -4
- package/dist/mcp/tools/list-reminders.js +21 -1
- package/dist/mcp/tools/list-tasks.js +195 -38
- package/dist/mcp/tools/send-message.js +58 -31
- package/dist/mcp/tools/update-task.js +75 -48
- package/dist/runtime/index.js +720 -89
- package/dist/tui/App.js +853 -123
- package/package.json +3 -2
package/dist/lib/tasks.js
CHANGED
|
@@ -262,7 +262,7 @@ function isMultiInstance(agentName, employees) {
|
|
|
262
262
|
if (!emp) return false;
|
|
263
263
|
return MULTI_INSTANCE_ROLES.has(emp.role.toLowerCase());
|
|
264
264
|
}
|
|
265
|
-
var EMPLOYEES_PATH, DEFAULT_COORDINATOR_TEMPLATE_NAME, COORDINATOR_ROLE, MULTI_INSTANCE_ROLES;
|
|
265
|
+
var EMPLOYEES_PATH, DEFAULT_COORDINATOR_TEMPLATE_NAME, COORDINATOR_ROLE, MULTI_INSTANCE_ROLES, IDENTITY_DIR;
|
|
266
266
|
var init_employees = __esm({
|
|
267
267
|
"src/lib/employees.ts"() {
|
|
268
268
|
"use strict";
|
|
@@ -271,15 +271,40 @@ var init_employees = __esm({
|
|
|
271
271
|
DEFAULT_COORDINATOR_TEMPLATE_NAME = "exe";
|
|
272
272
|
COORDINATOR_ROLE = "COO";
|
|
273
273
|
MULTI_INSTANCE_ROLES = /* @__PURE__ */ new Set(["principal engineer", "content production specialist", "staff code reviewer"]);
|
|
274
|
+
IDENTITY_DIR = path2.join(EXE_AI_DIR, "identity");
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
// src/lib/database-adapter.ts
|
|
279
|
+
import os3 from "os";
|
|
280
|
+
import path3 from "path";
|
|
281
|
+
import { createRequire } from "module";
|
|
282
|
+
import { pathToFileURL } from "url";
|
|
283
|
+
var BOOLEAN_COLUMNS_BY_TABLE, BOOLEAN_COLUMN_NAMES;
|
|
284
|
+
var init_database_adapter = __esm({
|
|
285
|
+
"src/lib/database-adapter.ts"() {
|
|
286
|
+
"use strict";
|
|
287
|
+
BOOLEAN_COLUMNS_BY_TABLE = {
|
|
288
|
+
memories: /* @__PURE__ */ new Set(["has_error", "draft"]),
|
|
289
|
+
behaviors: /* @__PURE__ */ new Set(["active"]),
|
|
290
|
+
notifications: /* @__PURE__ */ new Set(["read"]),
|
|
291
|
+
users: /* @__PURE__ */ new Set(["has_personal_memory"])
|
|
292
|
+
};
|
|
293
|
+
BOOLEAN_COLUMN_NAMES = new Set(
|
|
294
|
+
Object.values(BOOLEAN_COLUMNS_BY_TABLE).flatMap((cols) => [...cols])
|
|
295
|
+
);
|
|
274
296
|
}
|
|
275
297
|
});
|
|
276
298
|
|
|
277
299
|
// src/lib/database.ts
|
|
278
300
|
import { createClient } from "@libsql/client";
|
|
279
301
|
function getClient() {
|
|
280
|
-
if (!
|
|
302
|
+
if (!_adapterClient) {
|
|
281
303
|
throw new Error("Database client not initialized. Call initDatabase() first.");
|
|
282
304
|
}
|
|
305
|
+
if (process.env.DATABASE_URL) {
|
|
306
|
+
return _adapterClient;
|
|
307
|
+
}
|
|
283
308
|
if (process.env.EXE_IS_DAEMON === "1") {
|
|
284
309
|
return _resilientClient;
|
|
285
310
|
}
|
|
@@ -288,21 +313,23 @@ function getClient() {
|
|
|
288
313
|
}
|
|
289
314
|
return _resilientClient;
|
|
290
315
|
}
|
|
291
|
-
var _resilientClient, _daemonClient;
|
|
316
|
+
var _resilientClient, _daemonClient, _adapterClient;
|
|
292
317
|
var init_database = __esm({
|
|
293
318
|
"src/lib/database.ts"() {
|
|
294
319
|
"use strict";
|
|
295
320
|
init_db_retry();
|
|
296
321
|
init_employees();
|
|
322
|
+
init_database_adapter();
|
|
297
323
|
_resilientClient = null;
|
|
298
324
|
_daemonClient = null;
|
|
325
|
+
_adapterClient = null;
|
|
299
326
|
}
|
|
300
327
|
});
|
|
301
328
|
|
|
302
329
|
// src/lib/notifications.ts
|
|
303
330
|
import crypto from "crypto";
|
|
304
|
-
import
|
|
305
|
-
import
|
|
331
|
+
import path4 from "path";
|
|
332
|
+
import os4 from "os";
|
|
306
333
|
import {
|
|
307
334
|
readFileSync as readFileSync3,
|
|
308
335
|
readdirSync,
|
|
@@ -408,10 +435,10 @@ var init_state_bus = __esm({
|
|
|
408
435
|
|
|
409
436
|
// src/lib/session-registry.ts
|
|
410
437
|
import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, mkdirSync, existsSync as existsSync4 } from "fs";
|
|
411
|
-
import
|
|
412
|
-
import
|
|
438
|
+
import path5 from "path";
|
|
439
|
+
import os5 from "os";
|
|
413
440
|
function registerSession(entry) {
|
|
414
|
-
const dir =
|
|
441
|
+
const dir = path5.dirname(REGISTRY_PATH);
|
|
415
442
|
if (!existsSync4(dir)) {
|
|
416
443
|
mkdirSync(dir, { recursive: true });
|
|
417
444
|
}
|
|
@@ -436,7 +463,7 @@ var REGISTRY_PATH;
|
|
|
436
463
|
var init_session_registry = __esm({
|
|
437
464
|
"src/lib/session-registry.ts"() {
|
|
438
465
|
"use strict";
|
|
439
|
-
REGISTRY_PATH =
|
|
466
|
+
REGISTRY_PATH = path5.join(os5.homedir(), ".exe-os", "session-registry.json");
|
|
440
467
|
}
|
|
441
468
|
});
|
|
442
469
|
|
|
@@ -717,7 +744,7 @@ var init_runtime_table = __esm({
|
|
|
717
744
|
|
|
718
745
|
// src/lib/agent-config.ts
|
|
719
746
|
import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, existsSync as existsSync5, mkdirSync as mkdirSync2 } from "fs";
|
|
720
|
-
import
|
|
747
|
+
import path6 from "path";
|
|
721
748
|
function loadAgentConfig() {
|
|
722
749
|
if (!existsSync5(AGENT_CONFIG_PATH)) return {};
|
|
723
750
|
try {
|
|
@@ -740,7 +767,7 @@ var init_agent_config = __esm({
|
|
|
740
767
|
"use strict";
|
|
741
768
|
init_config();
|
|
742
769
|
init_runtime_table();
|
|
743
|
-
AGENT_CONFIG_PATH =
|
|
770
|
+
AGENT_CONFIG_PATH = path6.join(EXE_AI_DIR, "agent-config.json");
|
|
744
771
|
DEFAULT_MODELS = {
|
|
745
772
|
claude: "claude-opus-4",
|
|
746
773
|
codex: RUNTIME_TABLE.codex?.defaultModel ?? "gpt-5.4",
|
|
@@ -759,10 +786,10 @@ __export(intercom_queue_exports, {
|
|
|
759
786
|
readQueue: () => readQueue
|
|
760
787
|
});
|
|
761
788
|
import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, renameSync as renameSync3, existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
|
|
762
|
-
import
|
|
763
|
-
import
|
|
789
|
+
import path7 from "path";
|
|
790
|
+
import os6 from "os";
|
|
764
791
|
function ensureDir() {
|
|
765
|
-
const dir =
|
|
792
|
+
const dir = path7.dirname(QUEUE_PATH);
|
|
766
793
|
if (!existsSync6(dir)) mkdirSync3(dir, { recursive: true });
|
|
767
794
|
}
|
|
768
795
|
function readQueue() {
|
|
@@ -868,26 +895,26 @@ var QUEUE_PATH, MAX_RETRIES, TTL_MS, INTERCOM_LOG;
|
|
|
868
895
|
var init_intercom_queue = __esm({
|
|
869
896
|
"src/lib/intercom-queue.ts"() {
|
|
870
897
|
"use strict";
|
|
871
|
-
QUEUE_PATH =
|
|
898
|
+
QUEUE_PATH = path7.join(os6.homedir(), ".exe-os", "intercom-queue.json");
|
|
872
899
|
MAX_RETRIES = 5;
|
|
873
900
|
TTL_MS = 60 * 60 * 1e3;
|
|
874
|
-
INTERCOM_LOG =
|
|
901
|
+
INTERCOM_LOG = path7.join(os6.homedir(), ".exe-os", "intercom.log");
|
|
875
902
|
}
|
|
876
903
|
});
|
|
877
904
|
|
|
878
905
|
// src/lib/license.ts
|
|
879
906
|
import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsSync as existsSync7, mkdirSync as mkdirSync4 } from "fs";
|
|
880
907
|
import { randomUUID } from "crypto";
|
|
881
|
-
import
|
|
908
|
+
import path8 from "path";
|
|
882
909
|
import { jwtVerify, importSPKI } from "jose";
|
|
883
910
|
var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH, PLAN_LIMITS;
|
|
884
911
|
var init_license = __esm({
|
|
885
912
|
"src/lib/license.ts"() {
|
|
886
913
|
"use strict";
|
|
887
914
|
init_config();
|
|
888
|
-
LICENSE_PATH =
|
|
889
|
-
CACHE_PATH =
|
|
890
|
-
DEVICE_ID_PATH =
|
|
915
|
+
LICENSE_PATH = path8.join(EXE_AI_DIR, "license.key");
|
|
916
|
+
CACHE_PATH = path8.join(EXE_AI_DIR, "license-cache.json");
|
|
917
|
+
DEVICE_ID_PATH = path8.join(EXE_AI_DIR, "device-id");
|
|
891
918
|
PLAN_LIMITS = {
|
|
892
919
|
free: { devices: 1, employees: 1, memories: 5e3 },
|
|
893
920
|
pro: { devices: 3, employees: 5, memories: 1e5 },
|
|
@@ -900,7 +927,7 @@ var init_license = __esm({
|
|
|
900
927
|
|
|
901
928
|
// src/lib/plan-limits.ts
|
|
902
929
|
import { readFileSync as readFileSync8, existsSync as existsSync8 } from "fs";
|
|
903
|
-
import
|
|
930
|
+
import path9 from "path";
|
|
904
931
|
function getLicenseSync() {
|
|
905
932
|
try {
|
|
906
933
|
if (!existsSync8(CACHE_PATH2)) return freeLicense();
|
|
@@ -972,7 +999,7 @@ var init_plan_limits = __esm({
|
|
|
972
999
|
this.name = "PlanLimitError";
|
|
973
1000
|
}
|
|
974
1001
|
};
|
|
975
|
-
CACHE_PATH2 =
|
|
1002
|
+
CACHE_PATH2 = path9.join(EXE_AI_DIR, "license-cache.json");
|
|
976
1003
|
}
|
|
977
1004
|
});
|
|
978
1005
|
|
|
@@ -1321,12 +1348,12 @@ __export(tmux_routing_exports, {
|
|
|
1321
1348
|
});
|
|
1322
1349
|
import { execFileSync as execFileSync2, execSync as execSync4 } from "child_process";
|
|
1323
1350
|
import { readFileSync as readFileSync9, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, existsSync as existsSync9, appendFileSync, readdirSync as readdirSync2 } from "fs";
|
|
1324
|
-
import
|
|
1325
|
-
import
|
|
1351
|
+
import path10 from "path";
|
|
1352
|
+
import os7 from "os";
|
|
1326
1353
|
import { fileURLToPath } from "url";
|
|
1327
1354
|
import { unlinkSync as unlinkSync3 } from "fs";
|
|
1328
1355
|
function spawnLockPath(sessionName) {
|
|
1329
|
-
return
|
|
1356
|
+
return path10.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
|
|
1330
1357
|
}
|
|
1331
1358
|
function isProcessAlive(pid) {
|
|
1332
1359
|
try {
|
|
@@ -1363,8 +1390,8 @@ function releaseSpawnLock(sessionName) {
|
|
|
1363
1390
|
function resolveBehaviorsExporterScript() {
|
|
1364
1391
|
try {
|
|
1365
1392
|
const thisFile = fileURLToPath(import.meta.url);
|
|
1366
|
-
const scriptPath =
|
|
1367
|
-
|
|
1393
|
+
const scriptPath = path10.join(
|
|
1394
|
+
path10.dirname(thisFile),
|
|
1368
1395
|
"..",
|
|
1369
1396
|
"bin",
|
|
1370
1397
|
"exe-export-behaviors.js"
|
|
@@ -1439,7 +1466,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
|
|
|
1439
1466
|
mkdirSync5(SESSION_CACHE, { recursive: true });
|
|
1440
1467
|
}
|
|
1441
1468
|
const rootExe = extractRootExe(parentExe) ?? parentExe;
|
|
1442
|
-
const filePath =
|
|
1469
|
+
const filePath = path10.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
|
|
1443
1470
|
writeFileSync6(filePath, JSON.stringify({
|
|
1444
1471
|
parentExe: rootExe,
|
|
1445
1472
|
dispatchedBy: dispatchedBy || rootExe,
|
|
@@ -1448,7 +1475,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
|
|
|
1448
1475
|
}
|
|
1449
1476
|
function getParentExe(sessionKey) {
|
|
1450
1477
|
try {
|
|
1451
|
-
const data = JSON.parse(readFileSync9(
|
|
1478
|
+
const data = JSON.parse(readFileSync9(path10.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
|
|
1452
1479
|
return data.parentExe || null;
|
|
1453
1480
|
} catch {
|
|
1454
1481
|
return null;
|
|
@@ -1457,7 +1484,7 @@ function getParentExe(sessionKey) {
|
|
|
1457
1484
|
function getDispatchedBy(sessionKey) {
|
|
1458
1485
|
try {
|
|
1459
1486
|
const data = JSON.parse(readFileSync9(
|
|
1460
|
-
|
|
1487
|
+
path10.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
|
|
1461
1488
|
"utf8"
|
|
1462
1489
|
));
|
|
1463
1490
|
return data.dispatchedBy ?? data.parentExe ?? null;
|
|
@@ -1643,7 +1670,7 @@ function sendIntercom(targetSession) {
|
|
|
1643
1670
|
try {
|
|
1644
1671
|
const rawAgent = targetSession.split("-")[0] ?? targetSession;
|
|
1645
1672
|
const agent = baseAgentName(rawAgent);
|
|
1646
|
-
const markerPath =
|
|
1673
|
+
const markerPath = path10.join(SESSION_CACHE, `current-task-${agent}.json`);
|
|
1647
1674
|
if (existsSync9(markerPath)) {
|
|
1648
1675
|
logIntercom(`SKIP \u2192 ${targetSession} (has in_progress task marker \u2014 will auto-chain)`);
|
|
1649
1676
|
return "debounced";
|
|
@@ -1653,7 +1680,7 @@ function sendIntercom(targetSession) {
|
|
|
1653
1680
|
try {
|
|
1654
1681
|
const rawAgent = targetSession.split("-")[0] ?? targetSession;
|
|
1655
1682
|
const agent = baseAgentName(rawAgent);
|
|
1656
|
-
const taskDir =
|
|
1683
|
+
const taskDir = path10.join(process.cwd(), "exe", agent);
|
|
1657
1684
|
if (existsSync9(taskDir)) {
|
|
1658
1685
|
const files = readdirSync2(taskDir).filter(
|
|
1659
1686
|
(f) => f.endsWith(".md") && f !== "DONE.txt"
|
|
@@ -1787,8 +1814,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
1787
1814
|
const transport = getTransport();
|
|
1788
1815
|
const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
|
|
1789
1816
|
const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
|
|
1790
|
-
const logDir =
|
|
1791
|
-
const logFile =
|
|
1817
|
+
const logDir = path10.join(os7.homedir(), ".exe-os", "session-logs");
|
|
1818
|
+
const logFile = path10.join(logDir, `${instanceLabel}-${Date.now()}.log`);
|
|
1792
1819
|
if (!existsSync9(logDir)) {
|
|
1793
1820
|
mkdirSync5(logDir, { recursive: true });
|
|
1794
1821
|
}
|
|
@@ -1796,14 +1823,14 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
1796
1823
|
let cleanupSuffix = "";
|
|
1797
1824
|
try {
|
|
1798
1825
|
const thisFile = fileURLToPath(import.meta.url);
|
|
1799
|
-
const cleanupScript =
|
|
1826
|
+
const cleanupScript = path10.join(path10.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
|
|
1800
1827
|
if (existsSync9(cleanupScript)) {
|
|
1801
1828
|
cleanupSuffix = `; ${process.execPath} "${cleanupScript}" "${employeeName}" "${exeSession}"`;
|
|
1802
1829
|
}
|
|
1803
1830
|
} catch {
|
|
1804
1831
|
}
|
|
1805
1832
|
try {
|
|
1806
|
-
const claudeJsonPath =
|
|
1833
|
+
const claudeJsonPath = path10.join(os7.homedir(), ".claude.json");
|
|
1807
1834
|
let claudeJson = {};
|
|
1808
1835
|
try {
|
|
1809
1836
|
claudeJson = JSON.parse(readFileSync9(claudeJsonPath, "utf8"));
|
|
@@ -1818,10 +1845,10 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
1818
1845
|
} catch {
|
|
1819
1846
|
}
|
|
1820
1847
|
try {
|
|
1821
|
-
const settingsDir =
|
|
1848
|
+
const settingsDir = path10.join(os7.homedir(), ".claude", "projects");
|
|
1822
1849
|
const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
|
|
1823
|
-
const projSettingsDir =
|
|
1824
|
-
const settingsPath =
|
|
1850
|
+
const projSettingsDir = path10.join(settingsDir, normalizedKey);
|
|
1851
|
+
const settingsPath = path10.join(projSettingsDir, "settings.json");
|
|
1825
1852
|
let settings = {};
|
|
1826
1853
|
try {
|
|
1827
1854
|
settings = JSON.parse(readFileSync9(settingsPath, "utf8"));
|
|
@@ -1868,8 +1895,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
1868
1895
|
let behaviorsFlag = "";
|
|
1869
1896
|
let legacyFallbackWarned = false;
|
|
1870
1897
|
if (!useExeAgent && !useBinSymlink) {
|
|
1871
|
-
const identityPath =
|
|
1872
|
-
|
|
1898
|
+
const identityPath = path10.join(
|
|
1899
|
+
os7.homedir(),
|
|
1873
1900
|
".exe-os",
|
|
1874
1901
|
"identity",
|
|
1875
1902
|
`${employeeName}.md`
|
|
@@ -1884,7 +1911,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
1884
1911
|
}
|
|
1885
1912
|
const behaviorsFile = exportBehaviorsSync(
|
|
1886
1913
|
employeeName,
|
|
1887
|
-
|
|
1914
|
+
path10.basename(spawnCwd),
|
|
1888
1915
|
sessionName
|
|
1889
1916
|
);
|
|
1890
1917
|
if (behaviorsFile) {
|
|
@@ -1899,9 +1926,9 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
1899
1926
|
}
|
|
1900
1927
|
let sessionContextFlag = "";
|
|
1901
1928
|
try {
|
|
1902
|
-
const ctxDir =
|
|
1929
|
+
const ctxDir = path10.join(os7.homedir(), ".exe-os", "session-cache");
|
|
1903
1930
|
mkdirSync5(ctxDir, { recursive: true });
|
|
1904
|
-
const ctxFile =
|
|
1931
|
+
const ctxFile = path10.join(ctxDir, `session-context-${sessionName}.md`);
|
|
1905
1932
|
const ctxContent = [
|
|
1906
1933
|
`## Session Context`,
|
|
1907
1934
|
`You are running in tmux session: ${sessionName}.`,
|
|
@@ -1985,7 +2012,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
1985
2012
|
transport.pipeLog(sessionName, logFile);
|
|
1986
2013
|
try {
|
|
1987
2014
|
const mySession = getMySession();
|
|
1988
|
-
const dispatchInfo =
|
|
2015
|
+
const dispatchInfo = path10.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
|
|
1989
2016
|
writeFileSync6(dispatchInfo, JSON.stringify({
|
|
1990
2017
|
dispatchedBy: mySession,
|
|
1991
2018
|
rootExe: exeSession,
|
|
@@ -2060,15 +2087,15 @@ var init_tmux_routing = __esm({
|
|
|
2060
2087
|
init_intercom_queue();
|
|
2061
2088
|
init_plan_limits();
|
|
2062
2089
|
init_employees();
|
|
2063
|
-
SPAWN_LOCK_DIR =
|
|
2064
|
-
SESSION_CACHE =
|
|
2090
|
+
SPAWN_LOCK_DIR = path10.join(os7.homedir(), ".exe-os", "spawn-locks");
|
|
2091
|
+
SESSION_CACHE = path10.join(os7.homedir(), ".exe-os", "session-cache");
|
|
2065
2092
|
BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
|
|
2066
2093
|
VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
|
|
2067
2094
|
VERIFY_PANE_LINES = 200;
|
|
2068
2095
|
INTERCOM_DEBOUNCE_MS = 3e4;
|
|
2069
2096
|
CODEX_DEBOUNCE_MS = 12e4;
|
|
2070
|
-
INTERCOM_LOG2 =
|
|
2071
|
-
DEBOUNCE_FILE =
|
|
2097
|
+
INTERCOM_LOG2 = path10.join(os7.homedir(), ".exe-os", "intercom.log");
|
|
2098
|
+
DEBOUNCE_FILE = path10.join(SESSION_CACHE, "intercom-debounce.json");
|
|
2072
2099
|
DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
|
|
2073
2100
|
BUSY_PATTERN = /[✻✽✶✳·].*…|Running…|• Working|• Ran |• Explored|• Called|esc to interrupt/;
|
|
2074
2101
|
}
|
|
@@ -2100,8 +2127,8 @@ var init_task_scope = __esm({
|
|
|
2100
2127
|
|
|
2101
2128
|
// src/lib/tasks-crud.ts
|
|
2102
2129
|
import crypto3 from "crypto";
|
|
2103
|
-
import
|
|
2104
|
-
import
|
|
2130
|
+
import path11 from "path";
|
|
2131
|
+
import os8 from "os";
|
|
2105
2132
|
import { execSync as execSync5 } from "child_process";
|
|
2106
2133
|
import { mkdir as mkdir3, writeFile as writeFile3, appendFile } from "fs/promises";
|
|
2107
2134
|
import { existsSync as existsSync10, readFileSync as readFileSync10 } from "fs";
|
|
@@ -2279,8 +2306,8 @@ ${laneWarning}` : laneWarning;
|
|
|
2279
2306
|
}
|
|
2280
2307
|
if (input.baseDir) {
|
|
2281
2308
|
try {
|
|
2282
|
-
await mkdir3(
|
|
2283
|
-
await mkdir3(
|
|
2309
|
+
await mkdir3(path11.join(input.baseDir, "exe", "output"), { recursive: true });
|
|
2310
|
+
await mkdir3(path11.join(input.baseDir, "exe", "research"), { recursive: true });
|
|
2284
2311
|
await ensureArchitectureDoc(input.baseDir, input.projectName);
|
|
2285
2312
|
await ensureGitignoreExe(input.baseDir);
|
|
2286
2313
|
} catch {
|
|
@@ -2316,9 +2343,9 @@ ${laneWarning}` : laneWarning;
|
|
|
2316
2343
|
});
|
|
2317
2344
|
if (input.baseDir) {
|
|
2318
2345
|
try {
|
|
2319
|
-
const EXE_OS_DIR =
|
|
2320
|
-
const mdPath =
|
|
2321
|
-
const mdDir =
|
|
2346
|
+
const EXE_OS_DIR = path11.join(os8.homedir(), ".exe-os");
|
|
2347
|
+
const mdPath = path11.join(EXE_OS_DIR, taskFile);
|
|
2348
|
+
const mdDir = path11.dirname(mdPath);
|
|
2322
2349
|
if (!existsSync10(mdDir)) await mkdir3(mdDir, { recursive: true });
|
|
2323
2350
|
const reviewer = input.reviewer ?? input.assignedBy;
|
|
2324
2351
|
const mdContent = `# ${input.title}
|
|
@@ -2619,7 +2646,7 @@ async function deleteTaskCore(taskId, _baseDir) {
|
|
|
2619
2646
|
return { taskFile, assignedTo, assignedBy, taskSlug };
|
|
2620
2647
|
}
|
|
2621
2648
|
async function ensureArchitectureDoc(baseDir, projectName) {
|
|
2622
|
-
const archPath =
|
|
2649
|
+
const archPath = path11.join(baseDir, "exe", "ARCHITECTURE.md");
|
|
2623
2650
|
try {
|
|
2624
2651
|
if (existsSync10(archPath)) return;
|
|
2625
2652
|
const template = [
|
|
@@ -2654,7 +2681,7 @@ async function ensureArchitectureDoc(baseDir, projectName) {
|
|
|
2654
2681
|
}
|
|
2655
2682
|
}
|
|
2656
2683
|
async function ensureGitignoreExe(baseDir) {
|
|
2657
|
-
const gitignorePath =
|
|
2684
|
+
const gitignorePath = path11.join(baseDir, ".gitignore");
|
|
2658
2685
|
try {
|
|
2659
2686
|
if (existsSync10(gitignorePath)) {
|
|
2660
2687
|
const content = readFileSync10(gitignorePath, "utf-8");
|
|
@@ -2688,13 +2715,13 @@ var init_tasks_crud = __esm({
|
|
|
2688
2715
|
});
|
|
2689
2716
|
|
|
2690
2717
|
// src/lib/tasks-review.ts
|
|
2691
|
-
import
|
|
2718
|
+
import path12 from "path";
|
|
2692
2719
|
import { existsSync as existsSync11, readdirSync as readdirSync3, unlinkSync as unlinkSync4 } from "fs";
|
|
2693
2720
|
async function countPendingReviews(sessionScope) {
|
|
2694
2721
|
const client = getClient();
|
|
2695
2722
|
if (sessionScope) {
|
|
2696
2723
|
const result2 = await client.execute({
|
|
2697
|
-
sql: "SELECT COUNT(*) as cnt FROM tasks WHERE status = 'needs_review' AND
|
|
2724
|
+
sql: "SELECT COUNT(*) as cnt FROM tasks WHERE status = 'needs_review' AND session_scope = ?",
|
|
2698
2725
|
args: [sessionScope]
|
|
2699
2726
|
});
|
|
2700
2727
|
return Number(result2.rows[0]?.cnt) || 0;
|
|
@@ -2870,11 +2897,11 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
|
|
|
2870
2897
|
);
|
|
2871
2898
|
}
|
|
2872
2899
|
try {
|
|
2873
|
-
const cacheDir =
|
|
2900
|
+
const cacheDir = path12.join(EXE_AI_DIR, "session-cache");
|
|
2874
2901
|
if (existsSync11(cacheDir)) {
|
|
2875
2902
|
for (const f of readdirSync3(cacheDir)) {
|
|
2876
2903
|
if (f.startsWith("review-notified-")) {
|
|
2877
|
-
unlinkSync4(
|
|
2904
|
+
unlinkSync4(path12.join(cacheDir, f));
|
|
2878
2905
|
}
|
|
2879
2906
|
}
|
|
2880
2907
|
}
|
|
@@ -2895,7 +2922,7 @@ var init_tasks_review = __esm({
|
|
|
2895
2922
|
});
|
|
2896
2923
|
|
|
2897
2924
|
// src/lib/tasks-chain.ts
|
|
2898
|
-
import
|
|
2925
|
+
import path13 from "path";
|
|
2899
2926
|
import { readFile as readFile3, writeFile as writeFile4 } from "fs/promises";
|
|
2900
2927
|
async function cascadeUnblock(taskId, baseDir, now) {
|
|
2901
2928
|
const client = getClient();
|
|
@@ -2912,7 +2939,7 @@ async function cascadeUnblock(taskId, baseDir, now) {
|
|
|
2912
2939
|
});
|
|
2913
2940
|
for (const ur of unblockedRows.rows) {
|
|
2914
2941
|
try {
|
|
2915
|
-
const ubFile =
|
|
2942
|
+
const ubFile = path13.join(baseDir, String(ur.task_file));
|
|
2916
2943
|
let ubContent = await readFile3(ubFile, "utf-8");
|
|
2917
2944
|
ubContent = ubContent.replace(/\*\*Status:\*\* blocked/, "**Status:** open");
|
|
2918
2945
|
ubContent = ubContent.replace(/\n\*\*Blocked by:\*\*.*\n/, "\n");
|
|
@@ -2981,7 +3008,7 @@ var init_tasks_chain = __esm({
|
|
|
2981
3008
|
|
|
2982
3009
|
// src/lib/project-name.ts
|
|
2983
3010
|
import { execSync as execSync6 } from "child_process";
|
|
2984
|
-
import
|
|
3011
|
+
import path14 from "path";
|
|
2985
3012
|
function getProjectName(cwd) {
|
|
2986
3013
|
const dir = cwd ?? process.cwd();
|
|
2987
3014
|
if (_cached2 && _cachedCwd === dir) return _cached2;
|
|
@@ -2994,7 +3021,7 @@ function getProjectName(cwd) {
|
|
|
2994
3021
|
timeout: 2e3,
|
|
2995
3022
|
stdio: ["pipe", "pipe", "pipe"]
|
|
2996
3023
|
}).trim();
|
|
2997
|
-
repoRoot =
|
|
3024
|
+
repoRoot = path14.dirname(gitCommonDir);
|
|
2998
3025
|
} catch {
|
|
2999
3026
|
repoRoot = execSync6("git rev-parse --show-toplevel", {
|
|
3000
3027
|
cwd: dir,
|
|
@@ -3003,11 +3030,11 @@ function getProjectName(cwd) {
|
|
|
3003
3030
|
stdio: ["pipe", "pipe", "pipe"]
|
|
3004
3031
|
}).trim();
|
|
3005
3032
|
}
|
|
3006
|
-
_cached2 =
|
|
3033
|
+
_cached2 = path14.basename(repoRoot);
|
|
3007
3034
|
_cachedCwd = dir;
|
|
3008
3035
|
return _cached2;
|
|
3009
3036
|
} catch {
|
|
3010
|
-
_cached2 =
|
|
3037
|
+
_cached2 = path14.basename(dir);
|
|
3011
3038
|
_cachedCwd = dir;
|
|
3012
3039
|
return _cached2;
|
|
3013
3040
|
}
|
|
@@ -3480,7 +3507,7 @@ __export(tasks_exports, {
|
|
|
3480
3507
|
updateTaskStatus: () => updateTaskStatus,
|
|
3481
3508
|
writeCheckpoint: () => writeCheckpoint
|
|
3482
3509
|
});
|
|
3483
|
-
import
|
|
3510
|
+
import path15 from "path";
|
|
3484
3511
|
import { writeFileSync as writeFileSync7, mkdirSync as mkdirSync6, unlinkSync as unlinkSync5 } from "fs";
|
|
3485
3512
|
async function createTask(input) {
|
|
3486
3513
|
const result = await createTaskCore(input);
|
|
@@ -3500,8 +3527,8 @@ async function updateTask(input) {
|
|
|
3500
3527
|
const { row, taskFile, now, taskId } = await updateTaskStatus(input);
|
|
3501
3528
|
try {
|
|
3502
3529
|
const agent = String(row.assigned_to);
|
|
3503
|
-
const cacheDir =
|
|
3504
|
-
const cachePath =
|
|
3530
|
+
const cacheDir = path15.join(EXE_AI_DIR, "session-cache");
|
|
3531
|
+
const cachePath = path15.join(cacheDir, `current-task-${agent}.json`);
|
|
3505
3532
|
if (input.status === "in_progress") {
|
|
3506
3533
|
mkdirSync6(cacheDir, { recursive: true });
|
|
3507
3534
|
writeFileSync7(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
|