@askexenow/exe-os 0.9.102 → 0.9.104
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/agentic-ontology-backfill.js +334 -100
- package/dist/bin/agentic-reflection-backfill.js +328 -97
- package/dist/bin/agentic-semantic-label.js +328 -97
- package/dist/bin/backfill-conversations.js +332 -97
- package/dist/bin/backfill-responses.js +332 -97
- package/dist/bin/backfill-vectors.js +337 -106
- package/dist/bin/bulk-sync-postgres.js +335 -101
- package/dist/bin/cleanup-stale-review-tasks.js +356 -108
- package/dist/bin/cli.js +653 -405
- package/dist/bin/exe-agent.js +21 -3
- package/dist/bin/exe-assign.js +338 -94
- package/dist/bin/exe-boot.js +472 -239
- package/dist/bin/exe-call.js +22 -5
- package/dist/bin/exe-cloud.js +404 -158
- package/dist/bin/exe-dispatch.js +390 -142
- package/dist/bin/exe-doctor.js +349 -103
- package/dist/bin/exe-export-behaviors.js +351 -105
- package/dist/bin/exe-forget.js +352 -103
- package/dist/bin/exe-gateway.js +420 -172
- package/dist/bin/exe-heartbeat.js +361 -113
- package/dist/bin/exe-kill.js +344 -98
- package/dist/bin/exe-launch-agent.js +375 -129
- package/dist/bin/exe-new-employee.js +83 -67
- package/dist/bin/exe-pending-messages.js +356 -108
- package/dist/bin/exe-pending-notifications.js +358 -110
- package/dist/bin/exe-pending-reviews.js +359 -111
- package/dist/bin/exe-rename.js +354 -108
- package/dist/bin/exe-review.js +343 -97
- package/dist/bin/exe-search.js +363 -113
- package/dist/bin/exe-session-cleanup.js +403 -155
- package/dist/bin/exe-settings.js +14 -9
- package/dist/bin/exe-start-codex.js +365 -131
- package/dist/bin/exe-start-opencode.js +359 -125
- package/dist/bin/exe-status.js +356 -108
- package/dist/bin/exe-team.js +343 -97
- package/dist/bin/git-sweep.js +390 -142
- package/dist/bin/graph-backfill.js +334 -100
- package/dist/bin/graph-export.js +346 -100
- package/dist/bin/install.js +1 -0
- package/dist/bin/intercom-check.js +403 -155
- package/dist/bin/pre-publish.js +12 -0
- package/dist/bin/scan-tasks.js +393 -145
- package/dist/bin/setup.js +331 -159
- package/dist/bin/shard-migrate.js +328 -94
- package/dist/gateway/index.js +406 -158
- package/dist/hooks/bug-report-worker.js +396 -148
- package/dist/hooks/codex-stop-task-finalizer.js +374 -126
- package/dist/hooks/commit-complete.js +390 -142
- package/dist/hooks/error-recall.js +365 -115
- package/dist/hooks/ingest.js +357 -111
- package/dist/hooks/instructions-loaded.js +351 -105
- package/dist/hooks/notification.js +343 -97
- package/dist/hooks/post-compact.js +358 -110
- package/dist/hooks/post-tool-combined.js +384 -132
- package/dist/hooks/pre-compact.js +391 -143
- package/dist/hooks/pre-tool-use.js +362 -114
- package/dist/hooks/prompt-submit.js +422 -170
- package/dist/hooks/session-end.js +393 -145
- package/dist/hooks/session-start.js +390 -138
- package/dist/hooks/stop.js +361 -113
- package/dist/hooks/subagent-stop.js +354 -106
- package/dist/hooks/summary-worker.js +418 -185
- package/dist/index.js +400 -152
- package/dist/lib/cloud-sync.js +291 -131
- package/dist/lib/consolidation.js +8 -2
- package/dist/lib/database.js +233 -73
- package/dist/lib/db.js +233 -73
- package/dist/lib/device-registry.js +237 -77
- package/dist/lib/employee-templates.js +19 -1
- package/dist/lib/exe-daemon.js +705 -409
- package/dist/lib/hybrid-search.js +363 -113
- package/dist/lib/identity.js +9 -5
- package/dist/lib/messaging.js +26 -20
- package/dist/lib/reminders.js +5 -1
- package/dist/lib/schedules.js +320 -89
- package/dist/lib/skill-learning.js +28 -24
- package/dist/lib/store.js +342 -96
- package/dist/lib/tasks.js +82 -76
- package/dist/lib/tmux-routing.js +74 -68
- package/dist/lib/token-spend.js +5 -1
- package/dist/mcp/server.js +628 -355
- package/dist/mcp/tools/complete-reminder.js +5 -1
- package/dist/mcp/tools/create-reminder.js +5 -1
- package/dist/mcp/tools/create-task.js +89 -83
- package/dist/mcp/tools/deactivate-behavior.js +7 -3
- package/dist/mcp/tools/list-reminders.js +5 -1
- package/dist/mcp/tools/list-tasks.js +28 -21
- package/dist/mcp/tools/send-message.js +28 -22
- package/dist/mcp/tools/update-task.js +89 -83
- package/dist/runtime/index.js +390 -142
- package/dist/tui/App.js +437 -189
- package/package.json +1 -1
package/dist/lib/tasks.js
CHANGED
|
@@ -439,8 +439,10 @@ var init_memory = __esm({
|
|
|
439
439
|
});
|
|
440
440
|
|
|
441
441
|
// src/lib/database.ts
|
|
442
|
-
import { chmodSync as chmodSync2 } from "fs";
|
|
442
|
+
import { chmodSync as chmodSync2, existsSync as existsSync4, statSync, copyFileSync, unlinkSync as unlinkSync2, openSync, closeSync, mkdirSync as mkdirSync2 } from "fs";
|
|
443
443
|
import { createClient } from "@libsql/client";
|
|
444
|
+
import { homedir } from "os";
|
|
445
|
+
import { join } from "path";
|
|
444
446
|
function getClient() {
|
|
445
447
|
if (!_adapterClient) {
|
|
446
448
|
throw new Error("Database client not initialized. Call initDatabase() first.");
|
|
@@ -459,7 +461,7 @@ function getClient() {
|
|
|
459
461
|
}
|
|
460
462
|
return _resilientClient;
|
|
461
463
|
}
|
|
462
|
-
var _resilientClient, _daemonClient, _adapterClient;
|
|
464
|
+
var _debugDb, _resilientClient, _daemonClient, _adapterClient, DB_LOCK_PATH;
|
|
463
465
|
var init_database = __esm({
|
|
464
466
|
"src/lib/database.ts"() {
|
|
465
467
|
"use strict";
|
|
@@ -467,20 +469,22 @@ var init_database = __esm({
|
|
|
467
469
|
init_employees();
|
|
468
470
|
init_database_adapter();
|
|
469
471
|
init_memory();
|
|
472
|
+
_debugDb = process.env.EXE_DEBUG === "1";
|
|
470
473
|
_resilientClient = null;
|
|
471
474
|
_daemonClient = null;
|
|
472
475
|
_adapterClient = null;
|
|
476
|
+
DB_LOCK_PATH = join(homedir(), ".exe-os", "db.lock");
|
|
473
477
|
}
|
|
474
478
|
});
|
|
475
479
|
|
|
476
480
|
// src/lib/session-registry.ts
|
|
477
|
-
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as
|
|
481
|
+
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3, existsSync as existsSync5 } from "fs";
|
|
478
482
|
import path4 from "path";
|
|
479
483
|
import os4 from "os";
|
|
480
484
|
function registerSession(entry) {
|
|
481
485
|
const dir = path4.dirname(REGISTRY_PATH);
|
|
482
|
-
if (!
|
|
483
|
-
|
|
486
|
+
if (!existsSync5(dir)) {
|
|
487
|
+
mkdirSync3(dir, { recursive: true });
|
|
484
488
|
}
|
|
485
489
|
const sessions = listSessions();
|
|
486
490
|
const idx = sessions.findIndex((s) => s.windowName === entry.windowName);
|
|
@@ -793,10 +797,10 @@ var init_runtime_table = __esm({
|
|
|
793
797
|
});
|
|
794
798
|
|
|
795
799
|
// src/lib/agent-config.ts
|
|
796
|
-
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as
|
|
800
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync6 } from "fs";
|
|
797
801
|
import path5 from "path";
|
|
798
802
|
function loadAgentConfig() {
|
|
799
|
-
if (!
|
|
803
|
+
if (!existsSync6(AGENT_CONFIG_PATH)) return {};
|
|
800
804
|
try {
|
|
801
805
|
return JSON.parse(readFileSync4(AGENT_CONFIG_PATH, "utf-8"));
|
|
802
806
|
} catch {
|
|
@@ -836,16 +840,16 @@ __export(intercom_queue_exports, {
|
|
|
836
840
|
queueIntercom: () => queueIntercom,
|
|
837
841
|
readQueue: () => readQueue
|
|
838
842
|
});
|
|
839
|
-
import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, renameSync as renameSync3, existsSync as
|
|
843
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, renameSync as renameSync3, existsSync as existsSync7, mkdirSync as mkdirSync4 } from "fs";
|
|
840
844
|
import path6 from "path";
|
|
841
845
|
import os5 from "os";
|
|
842
846
|
function ensureDir() {
|
|
843
847
|
const dir = path6.dirname(QUEUE_PATH);
|
|
844
|
-
if (!
|
|
848
|
+
if (!existsSync7(dir)) mkdirSync4(dir, { recursive: true });
|
|
845
849
|
}
|
|
846
850
|
function readQueue() {
|
|
847
851
|
try {
|
|
848
|
-
if (!
|
|
852
|
+
if (!existsSync7(QUEUE_PATH)) return [];
|
|
849
853
|
return JSON.parse(readFileSync5(QUEUE_PATH, "utf8"));
|
|
850
854
|
} catch {
|
|
851
855
|
return [];
|
|
@@ -954,7 +958,7 @@ var init_intercom_queue = __esm({
|
|
|
954
958
|
});
|
|
955
959
|
|
|
956
960
|
// src/lib/license.ts
|
|
957
|
-
import { readFileSync as readFileSync6, writeFileSync as writeFileSync5, existsSync as
|
|
961
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync5, existsSync as existsSync8, mkdirSync as mkdirSync5 } from "fs";
|
|
958
962
|
import { randomUUID } from "crypto";
|
|
959
963
|
import { createRequire as createRequire2 } from "module";
|
|
960
964
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
@@ -981,11 +985,11 @@ var init_license = __esm({
|
|
|
981
985
|
});
|
|
982
986
|
|
|
983
987
|
// src/lib/plan-limits.ts
|
|
984
|
-
import { readFileSync as readFileSync7, existsSync as
|
|
988
|
+
import { readFileSync as readFileSync7, existsSync as existsSync9 } from "fs";
|
|
985
989
|
import path8 from "path";
|
|
986
990
|
function getLicenseSync() {
|
|
987
991
|
try {
|
|
988
|
-
if (!
|
|
992
|
+
if (!existsSync9(CACHE_PATH2)) return freeLicense();
|
|
989
993
|
const raw = JSON.parse(readFileSync7(CACHE_PATH2, "utf8"));
|
|
990
994
|
if (!raw.token || typeof raw.token !== "string") return freeLicense();
|
|
991
995
|
const parts = raw.token.split(".");
|
|
@@ -1024,7 +1028,7 @@ function assertEmployeeLimitSync(rosterPath) {
|
|
|
1024
1028
|
const filePath = rosterPath ?? EMPLOYEES_PATH;
|
|
1025
1029
|
let count = 0;
|
|
1026
1030
|
try {
|
|
1027
|
-
if (
|
|
1031
|
+
if (existsSync9(filePath)) {
|
|
1028
1032
|
const raw = readFileSync7(filePath, "utf8");
|
|
1029
1033
|
const employees = JSON.parse(raw);
|
|
1030
1034
|
count = Array.isArray(employees) ? employees.length : 0;
|
|
@@ -1062,9 +1066,9 @@ var init_plan_limits = __esm({
|
|
|
1062
1066
|
import os7 from "os";
|
|
1063
1067
|
import path9 from "path";
|
|
1064
1068
|
import {
|
|
1065
|
-
existsSync as
|
|
1069
|
+
existsSync as existsSync10,
|
|
1066
1070
|
lstatSync,
|
|
1067
|
-
mkdirSync as
|
|
1071
|
+
mkdirSync as mkdirSync6,
|
|
1068
1072
|
readlinkSync as readlinkSync2,
|
|
1069
1073
|
symlinkSync as symlinkSync2
|
|
1070
1074
|
} from "fs";
|
|
@@ -1080,8 +1084,8 @@ function claudeAgentLinkPath(homeDir, agentId) {
|
|
|
1080
1084
|
function ensureAgentSymlink(agentId, homeDir = os7.homedir()) {
|
|
1081
1085
|
const target = identitySourcePath(homeDir, agentId);
|
|
1082
1086
|
const link = claudeAgentLinkPath(homeDir, agentId);
|
|
1083
|
-
|
|
1084
|
-
if (
|
|
1087
|
+
mkdirSync6(claudeAgentsDir(homeDir), { recursive: true });
|
|
1088
|
+
if (existsSync10(link)) {
|
|
1085
1089
|
let stat;
|
|
1086
1090
|
try {
|
|
1087
1091
|
stat = lstatSync(link);
|
|
@@ -1510,7 +1514,7 @@ __export(tasks_review_exports, {
|
|
|
1510
1514
|
listPendingReviews: () => listPendingReviews
|
|
1511
1515
|
});
|
|
1512
1516
|
import path10 from "path";
|
|
1513
|
-
import { existsSync as
|
|
1517
|
+
import { existsSync as existsSync11, readdirSync, unlinkSync as unlinkSync3 } from "fs";
|
|
1514
1518
|
function formatAge(isoTimestamp) {
|
|
1515
1519
|
if (!isoTimestamp) return "";
|
|
1516
1520
|
const ms = Date.now() - new Date(isoTimestamp).getTime();
|
|
@@ -1780,10 +1784,10 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
|
|
|
1780
1784
|
}
|
|
1781
1785
|
try {
|
|
1782
1786
|
const cacheDir = path10.join(EXE_AI_DIR, "session-cache");
|
|
1783
|
-
if (
|
|
1787
|
+
if (existsSync11(cacheDir)) {
|
|
1784
1788
|
for (const f of readdirSync(cacheDir)) {
|
|
1785
1789
|
if (f.startsWith("review-notified-")) {
|
|
1786
|
-
|
|
1790
|
+
unlinkSync3(path10.join(cacheDir, f));
|
|
1787
1791
|
}
|
|
1788
1792
|
}
|
|
1789
1793
|
}
|
|
@@ -1830,11 +1834,11 @@ __export(tmux_routing_exports, {
|
|
|
1830
1834
|
verifyPaneAtCapacity: () => verifyPaneAtCapacity
|
|
1831
1835
|
});
|
|
1832
1836
|
import { execFileSync as execFileSync2, execSync as execSync4 } from "child_process";
|
|
1833
|
-
import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, mkdirSync as
|
|
1837
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, mkdirSync as mkdirSync7, existsSync as existsSync12, appendFileSync, readdirSync as readdirSync2 } from "fs";
|
|
1834
1838
|
import path11 from "path";
|
|
1835
1839
|
import os8 from "os";
|
|
1836
1840
|
import { fileURLToPath } from "url";
|
|
1837
|
-
import { unlinkSync as
|
|
1841
|
+
import { unlinkSync as unlinkSync4 } from "fs";
|
|
1838
1842
|
function spawnLockPath(sessionName) {
|
|
1839
1843
|
return path11.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
|
|
1840
1844
|
}
|
|
@@ -1847,11 +1851,11 @@ function isProcessAlive(pid) {
|
|
|
1847
1851
|
}
|
|
1848
1852
|
}
|
|
1849
1853
|
function acquireSpawnLock(sessionName) {
|
|
1850
|
-
if (!
|
|
1851
|
-
|
|
1854
|
+
if (!existsSync12(SPAWN_LOCK_DIR)) {
|
|
1855
|
+
mkdirSync7(SPAWN_LOCK_DIR, { recursive: true });
|
|
1852
1856
|
}
|
|
1853
1857
|
const lockFile = spawnLockPath(sessionName);
|
|
1854
|
-
if (
|
|
1858
|
+
if (existsSync12(lockFile)) {
|
|
1855
1859
|
try {
|
|
1856
1860
|
const lock = JSON.parse(readFileSync8(lockFile, "utf8"));
|
|
1857
1861
|
const age = Date.now() - lock.timestamp;
|
|
@@ -1866,7 +1870,7 @@ function acquireSpawnLock(sessionName) {
|
|
|
1866
1870
|
}
|
|
1867
1871
|
function releaseSpawnLock(sessionName) {
|
|
1868
1872
|
try {
|
|
1869
|
-
|
|
1873
|
+
unlinkSync4(spawnLockPath(sessionName));
|
|
1870
1874
|
} catch {
|
|
1871
1875
|
}
|
|
1872
1876
|
}
|
|
@@ -1879,7 +1883,7 @@ function resolveBehaviorsExporterScript() {
|
|
|
1879
1883
|
"bin",
|
|
1880
1884
|
"exe-export-behaviors.js"
|
|
1881
1885
|
);
|
|
1882
|
-
return
|
|
1886
|
+
return existsSync12(scriptPath) ? scriptPath : null;
|
|
1883
1887
|
} catch {
|
|
1884
1888
|
return null;
|
|
1885
1889
|
}
|
|
@@ -1945,8 +1949,8 @@ function extractRootExe(name) {
|
|
|
1945
1949
|
return parts.length > 0 ? parts[parts.length - 1] : null;
|
|
1946
1950
|
}
|
|
1947
1951
|
function registerParentExe(sessionKey, parentExe, dispatchedBy) {
|
|
1948
|
-
if (!
|
|
1949
|
-
|
|
1952
|
+
if (!existsSync12(SESSION_CACHE)) {
|
|
1953
|
+
mkdirSync7(SESSION_CACHE, { recursive: true });
|
|
1950
1954
|
}
|
|
1951
1955
|
const rootExe = extractRootExe(parentExe) ?? parentExe;
|
|
1952
1956
|
const filePath = path11.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
|
|
@@ -1976,11 +1980,13 @@ function getDispatchedBy(sessionKey) {
|
|
|
1976
1980
|
}
|
|
1977
1981
|
}
|
|
1978
1982
|
function resolveExeSession() {
|
|
1979
|
-
if (process.env.EXE_SESSION_NAME) {
|
|
1980
|
-
return extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
|
|
1981
|
-
}
|
|
1982
1983
|
const mySession = getMySession();
|
|
1983
|
-
if (!mySession)
|
|
1984
|
+
if (!mySession) {
|
|
1985
|
+
if (process.env.EXE_SESSION_NAME) {
|
|
1986
|
+
return extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
|
|
1987
|
+
}
|
|
1988
|
+
return null;
|
|
1989
|
+
}
|
|
1984
1990
|
const fromSessionName = extractRootExe(mySession);
|
|
1985
1991
|
let candidate = null;
|
|
1986
1992
|
try {
|
|
@@ -2075,7 +2081,7 @@ async function verifyPaneAtCapacity(sessionName) {
|
|
|
2075
2081
|
}
|
|
2076
2082
|
function readDebounceState() {
|
|
2077
2083
|
try {
|
|
2078
|
-
if (!
|
|
2084
|
+
if (!existsSync12(DEBOUNCE_FILE)) return {};
|
|
2079
2085
|
const raw = JSON.parse(readFileSync8(DEBOUNCE_FILE, "utf8"));
|
|
2080
2086
|
const state = {};
|
|
2081
2087
|
for (const [key, val] of Object.entries(raw)) {
|
|
@@ -2092,7 +2098,7 @@ function readDebounceState() {
|
|
|
2092
2098
|
}
|
|
2093
2099
|
function writeDebounceState(state) {
|
|
2094
2100
|
try {
|
|
2095
|
-
if (!
|
|
2101
|
+
if (!existsSync12(SESSION_CACHE)) mkdirSync7(SESSION_CACHE, { recursive: true });
|
|
2096
2102
|
writeFileSync6(DEBOUNCE_FILE, JSON.stringify(state));
|
|
2097
2103
|
} catch {
|
|
2098
2104
|
}
|
|
@@ -2193,7 +2199,7 @@ function sendIntercom(targetSession) {
|
|
|
2193
2199
|
const rawAgent = targetSession.split("-")[0] ?? targetSession;
|
|
2194
2200
|
const agent = baseAgentName(rawAgent);
|
|
2195
2201
|
const markerPath = path11.join(SESSION_CACHE, `current-task-${agent}.json`);
|
|
2196
|
-
if (
|
|
2202
|
+
if (existsSync12(markerPath)) {
|
|
2197
2203
|
logIntercom(`SKIP \u2192 ${targetSession} (has in_progress task marker + not idle \u2014 will auto-chain)`);
|
|
2198
2204
|
return "debounced";
|
|
2199
2205
|
}
|
|
@@ -2204,7 +2210,7 @@ function sendIntercom(targetSession) {
|
|
|
2204
2210
|
const rawAgent = targetSession.split("-")[0] ?? targetSession;
|
|
2205
2211
|
const agent = baseAgentName(rawAgent);
|
|
2206
2212
|
const taskDir = path11.join(process.cwd(), "exe", agent);
|
|
2207
|
-
if (
|
|
2213
|
+
if (existsSync12(taskDir)) {
|
|
2208
2214
|
const files = readdirSync2(taskDir).filter(
|
|
2209
2215
|
(f) => f.endsWith(".md") && f !== "DONE.txt"
|
|
2210
2216
|
);
|
|
@@ -2365,15 +2371,15 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
2365
2371
|
const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
|
|
2366
2372
|
const logDir = path11.join(os8.homedir(), ".exe-os", "session-logs");
|
|
2367
2373
|
const logFile = path11.join(logDir, `${instanceLabel}-${Date.now()}.log`);
|
|
2368
|
-
if (!
|
|
2369
|
-
|
|
2374
|
+
if (!existsSync12(logDir)) {
|
|
2375
|
+
mkdirSync7(logDir, { recursive: true });
|
|
2370
2376
|
}
|
|
2371
2377
|
transport.kill(sessionName);
|
|
2372
2378
|
let cleanupSuffix = "";
|
|
2373
2379
|
try {
|
|
2374
2380
|
const thisFile = fileURLToPath(import.meta.url);
|
|
2375
2381
|
const cleanupScript = path11.join(path11.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
|
|
2376
|
-
if (
|
|
2382
|
+
if (existsSync12(cleanupScript)) {
|
|
2377
2383
|
cleanupSuffix = `; ${process.execPath} "${cleanupScript}" "${employeeName}" "${exeSession}"`;
|
|
2378
2384
|
}
|
|
2379
2385
|
} catch {
|
|
@@ -2428,7 +2434,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
2428
2434
|
if (changed) {
|
|
2429
2435
|
perms.allow = allow;
|
|
2430
2436
|
settings.permissions = perms;
|
|
2431
|
-
|
|
2437
|
+
mkdirSync7(projSettingsDir, { recursive: true });
|
|
2432
2438
|
writeFileSync6(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
2433
2439
|
}
|
|
2434
2440
|
} catch {
|
|
@@ -2466,7 +2472,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
2466
2472
|
`
|
|
2467
2473
|
);
|
|
2468
2474
|
}
|
|
2469
|
-
} else if (
|
|
2475
|
+
} else if (existsSync12(identityPath)) {
|
|
2470
2476
|
identityFlag = ` --append-system-prompt-file ${identityPath}`;
|
|
2471
2477
|
legacyFallbackWarned = true;
|
|
2472
2478
|
}
|
|
@@ -2488,7 +2494,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
2488
2494
|
let sessionContextFlag = "";
|
|
2489
2495
|
try {
|
|
2490
2496
|
const ctxDir = path11.join(os8.homedir(), ".exe-os", "session-cache");
|
|
2491
|
-
|
|
2497
|
+
mkdirSync7(ctxDir, { recursive: true });
|
|
2492
2498
|
const ctxFile = path11.join(ctxDir, `session-context-${sessionName}.md`);
|
|
2493
2499
|
const ctxContent = [
|
|
2494
2500
|
`## Session Context`,
|
|
@@ -2709,8 +2715,8 @@ import os9 from "os";
|
|
|
2709
2715
|
import {
|
|
2710
2716
|
readFileSync as readFileSync9,
|
|
2711
2717
|
readdirSync as readdirSync3,
|
|
2712
|
-
unlinkSync as
|
|
2713
|
-
existsSync as
|
|
2718
|
+
unlinkSync as unlinkSync5,
|
|
2719
|
+
existsSync as existsSync13,
|
|
2714
2720
|
rmdirSync
|
|
2715
2721
|
} from "fs";
|
|
2716
2722
|
async function writeNotification(notification) {
|
|
@@ -2869,7 +2875,7 @@ import path14 from "path";
|
|
|
2869
2875
|
import os10 from "os";
|
|
2870
2876
|
import { execSync as execSync6 } from "child_process";
|
|
2871
2877
|
import { mkdir as mkdir3, writeFile as writeFile3, appendFile } from "fs/promises";
|
|
2872
|
-
import { existsSync as
|
|
2878
|
+
import { existsSync as existsSync14, readFileSync as readFileSync10 } from "fs";
|
|
2873
2879
|
async function writeCheckpoint(input) {
|
|
2874
2880
|
const client = getClient();
|
|
2875
2881
|
const row = await resolveTask(client, input.taskId);
|
|
@@ -3110,7 +3116,7 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
|
|
|
3110
3116
|
const EXE_OS_DIR = path14.join(os10.homedir(), ".exe-os");
|
|
3111
3117
|
const mdPath = path14.join(EXE_OS_DIR, taskFile);
|
|
3112
3118
|
const mdDir = path14.dirname(mdPath);
|
|
3113
|
-
if (!
|
|
3119
|
+
if (!existsSync14(mdDir)) await mkdir3(mdDir, { recursive: true });
|
|
3114
3120
|
const reviewer = input.reviewer ?? input.assignedBy;
|
|
3115
3121
|
const mdContent = `# ${input.title}
|
|
3116
3122
|
|
|
@@ -3416,7 +3422,7 @@ async function deleteTaskCore(taskId, _baseDir) {
|
|
|
3416
3422
|
async function ensureArchitectureDoc(baseDir, projectName) {
|
|
3417
3423
|
const archPath = path14.join(baseDir, "exe", "ARCHITECTURE.md");
|
|
3418
3424
|
try {
|
|
3419
|
-
if (
|
|
3425
|
+
if (existsSync14(archPath)) return;
|
|
3420
3426
|
const template = [
|
|
3421
3427
|
`# ${projectName} \u2014 System Architecture`,
|
|
3422
3428
|
"",
|
|
@@ -3451,7 +3457,7 @@ async function ensureArchitectureDoc(baseDir, projectName) {
|
|
|
3451
3457
|
async function ensureGitignoreExe(baseDir) {
|
|
3452
3458
|
const gitignorePath = path14.join(baseDir, ".gitignore");
|
|
3453
3459
|
try {
|
|
3454
|
-
if (
|
|
3460
|
+
if (existsSync14(gitignorePath)) {
|
|
3455
3461
|
const content = readFileSync10(gitignorePath, "utf-8");
|
|
3456
3462
|
if (/^\/?exe\/?$/m.test(content)) return;
|
|
3457
3463
|
await appendFile(gitignorePath, "\n# Employee task assignments (private)\n/exe/\n");
|
|
@@ -3650,7 +3656,7 @@ var init_tasks_notify = __esm({
|
|
|
3650
3656
|
// src/lib/daemon-auth.ts
|
|
3651
3657
|
import crypto4 from "crypto";
|
|
3652
3658
|
import path16 from "path";
|
|
3653
|
-
import { existsSync as
|
|
3659
|
+
import { existsSync as existsSync15, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "fs";
|
|
3654
3660
|
function normalizeToken(token) {
|
|
3655
3661
|
if (!token) return null;
|
|
3656
3662
|
const trimmed = token.trim();
|
|
@@ -3658,7 +3664,7 @@ function normalizeToken(token) {
|
|
|
3658
3664
|
}
|
|
3659
3665
|
function readDaemonToken() {
|
|
3660
3666
|
try {
|
|
3661
|
-
if (!
|
|
3667
|
+
if (!existsSync15(DAEMON_TOKEN_PATH)) return null;
|
|
3662
3668
|
return normalizeToken(readFileSync11(DAEMON_TOKEN_PATH, "utf8"));
|
|
3663
3669
|
} catch {
|
|
3664
3670
|
return null;
|
|
@@ -3689,7 +3695,7 @@ import net from "net";
|
|
|
3689
3695
|
import os11 from "os";
|
|
3690
3696
|
import { spawn, execSync as execSync7 } from "child_process";
|
|
3691
3697
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
3692
|
-
import { existsSync as
|
|
3698
|
+
import { existsSync as existsSync16, unlinkSync as unlinkSync6, readFileSync as readFileSync12, openSync as openSync2, closeSync as closeSync2, statSync as statSync2 } from "fs";
|
|
3693
3699
|
import path17 from "path";
|
|
3694
3700
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3695
3701
|
function handleData(chunk) {
|
|
@@ -3726,7 +3732,7 @@ function isZombie(pid) {
|
|
|
3726
3732
|
}
|
|
3727
3733
|
}
|
|
3728
3734
|
function cleanupStaleFiles() {
|
|
3729
|
-
if (
|
|
3735
|
+
if (existsSync16(PID_PATH)) {
|
|
3730
3736
|
try {
|
|
3731
3737
|
const pid = parseInt(readFileSync12(PID_PATH, "utf8").trim(), 10);
|
|
3732
3738
|
if (pid > 0) {
|
|
@@ -3743,11 +3749,11 @@ function cleanupStaleFiles() {
|
|
|
3743
3749
|
} catch {
|
|
3744
3750
|
}
|
|
3745
3751
|
try {
|
|
3746
|
-
|
|
3752
|
+
unlinkSync6(PID_PATH);
|
|
3747
3753
|
} catch {
|
|
3748
3754
|
}
|
|
3749
3755
|
try {
|
|
3750
|
-
|
|
3756
|
+
unlinkSync6(SOCKET_PATH);
|
|
3751
3757
|
} catch {
|
|
3752
3758
|
}
|
|
3753
3759
|
}
|
|
@@ -3756,7 +3762,7 @@ function findPackageRoot() {
|
|
|
3756
3762
|
let dir = path17.dirname(fileURLToPath2(import.meta.url));
|
|
3757
3763
|
const { root } = path17.parse(dir);
|
|
3758
3764
|
while (dir !== root) {
|
|
3759
|
-
if (
|
|
3765
|
+
if (existsSync16(path17.join(dir, "package.json"))) return dir;
|
|
3760
3766
|
dir = path17.dirname(dir);
|
|
3761
3767
|
}
|
|
3762
3768
|
return null;
|
|
@@ -3776,7 +3782,7 @@ function spawnDaemon() {
|
|
|
3776
3782
|
return;
|
|
3777
3783
|
}
|
|
3778
3784
|
const daemonPath = path17.join(pkgRoot, "dist", "lib", "exe-daemon.js");
|
|
3779
|
-
if (!
|
|
3785
|
+
if (!existsSync16(daemonPath)) {
|
|
3780
3786
|
process.stderr.write(`[exed-client] WARN: daemon script not found at ${daemonPath}
|
|
3781
3787
|
`);
|
|
3782
3788
|
return;
|
|
@@ -3788,7 +3794,7 @@ function spawnDaemon() {
|
|
|
3788
3794
|
const logPath = path17.join(path17.dirname(SOCKET_PATH), "exed.log");
|
|
3789
3795
|
let stderrFd = "ignore";
|
|
3790
3796
|
try {
|
|
3791
|
-
stderrFd =
|
|
3797
|
+
stderrFd = openSync2(logPath, "a");
|
|
3792
3798
|
} catch {
|
|
3793
3799
|
}
|
|
3794
3800
|
const heapCapMB = totalGB <= 8 ? 256 : 512;
|
|
@@ -3810,27 +3816,27 @@ function spawnDaemon() {
|
|
|
3810
3816
|
child.unref();
|
|
3811
3817
|
if (typeof stderrFd === "number") {
|
|
3812
3818
|
try {
|
|
3813
|
-
|
|
3819
|
+
closeSync2(stderrFd);
|
|
3814
3820
|
} catch {
|
|
3815
3821
|
}
|
|
3816
3822
|
}
|
|
3817
3823
|
}
|
|
3818
3824
|
function acquireSpawnLock2() {
|
|
3819
3825
|
try {
|
|
3820
|
-
const fd =
|
|
3821
|
-
|
|
3826
|
+
const fd = openSync2(SPAWN_LOCK_PATH, "wx");
|
|
3827
|
+
closeSync2(fd);
|
|
3822
3828
|
return true;
|
|
3823
3829
|
} catch {
|
|
3824
3830
|
try {
|
|
3825
|
-
const stat =
|
|
3831
|
+
const stat = statSync2(SPAWN_LOCK_PATH);
|
|
3826
3832
|
if (Date.now() - stat.mtimeMs > SPAWN_LOCK_STALE_MS) {
|
|
3827
3833
|
try {
|
|
3828
|
-
|
|
3834
|
+
unlinkSync6(SPAWN_LOCK_PATH);
|
|
3829
3835
|
} catch {
|
|
3830
3836
|
}
|
|
3831
3837
|
try {
|
|
3832
|
-
const fd =
|
|
3833
|
-
|
|
3838
|
+
const fd = openSync2(SPAWN_LOCK_PATH, "wx");
|
|
3839
|
+
closeSync2(fd);
|
|
3834
3840
|
return true;
|
|
3835
3841
|
} catch {
|
|
3836
3842
|
}
|
|
@@ -3842,7 +3848,7 @@ function acquireSpawnLock2() {
|
|
|
3842
3848
|
}
|
|
3843
3849
|
function releaseSpawnLock2() {
|
|
3844
3850
|
try {
|
|
3845
|
-
|
|
3851
|
+
unlinkSync6(SPAWN_LOCK_PATH);
|
|
3846
3852
|
} catch {
|
|
3847
3853
|
}
|
|
3848
3854
|
}
|
|
@@ -3950,7 +3956,7 @@ function killAndRespawnDaemon() {
|
|
|
3950
3956
|
}
|
|
3951
3957
|
try {
|
|
3952
3958
|
process.stderr.write("[exed-client] Killing daemon for restart...\n");
|
|
3953
|
-
if (
|
|
3959
|
+
if (existsSync16(PID_PATH)) {
|
|
3954
3960
|
try {
|
|
3955
3961
|
const pid = parseInt(readFileSync12(PID_PATH, "utf8").trim(), 10);
|
|
3956
3962
|
if (pid > 0) {
|
|
@@ -3969,11 +3975,11 @@ function killAndRespawnDaemon() {
|
|
|
3969
3975
|
_connected = false;
|
|
3970
3976
|
_buffer = "";
|
|
3971
3977
|
try {
|
|
3972
|
-
|
|
3978
|
+
unlinkSync6(PID_PATH);
|
|
3973
3979
|
} catch {
|
|
3974
3980
|
}
|
|
3975
3981
|
try {
|
|
3976
|
-
|
|
3982
|
+
unlinkSync6(SOCKET_PATH);
|
|
3977
3983
|
} catch {
|
|
3978
3984
|
}
|
|
3979
3985
|
spawnDaemon();
|
|
@@ -3983,7 +3989,7 @@ function killAndRespawnDaemon() {
|
|
|
3983
3989
|
}
|
|
3984
3990
|
function isDaemonTooYoung() {
|
|
3985
3991
|
try {
|
|
3986
|
-
const stat =
|
|
3992
|
+
const stat = statSync2(PID_PATH);
|
|
3987
3993
|
return Date.now() - stat.mtimeMs < MIN_DAEMON_AGE_MS;
|
|
3988
3994
|
} catch {
|
|
3989
3995
|
return false;
|
|
@@ -4133,10 +4139,10 @@ async function disposeEmbedder() {
|
|
|
4133
4139
|
async function embedDirect(text) {
|
|
4134
4140
|
const llamaCpp = await import("node-llama-cpp");
|
|
4135
4141
|
const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
4136
|
-
const { existsSync:
|
|
4142
|
+
const { existsSync: existsSync17 } = await import("fs");
|
|
4137
4143
|
const path19 = await import("path");
|
|
4138
4144
|
const modelPath = path19.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
|
|
4139
|
-
if (!
|
|
4145
|
+
if (!existsSync17(modelPath)) {
|
|
4140
4146
|
throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
|
|
4141
4147
|
}
|
|
4142
4148
|
const llama = await llamaCpp.getLlama();
|
|
@@ -4503,7 +4509,7 @@ __export(tasks_exports, {
|
|
|
4503
4509
|
writeCheckpoint: () => writeCheckpoint
|
|
4504
4510
|
});
|
|
4505
4511
|
import path18 from "path";
|
|
4506
|
-
import { writeFileSync as writeFileSync8, mkdirSync as
|
|
4512
|
+
import { writeFileSync as writeFileSync8, mkdirSync as mkdirSync8, unlinkSync as unlinkSync7 } from "fs";
|
|
4507
4513
|
async function createTask(input) {
|
|
4508
4514
|
const result = await createTaskCore(input);
|
|
4509
4515
|
if (!input.skipDispatch && result.status !== "blocked" && !process.env.VITEST) {
|
|
@@ -4525,11 +4531,11 @@ async function updateTask(input) {
|
|
|
4525
4531
|
const cacheDir = path18.join(EXE_AI_DIR, "session-cache");
|
|
4526
4532
|
const cachePath = path18.join(cacheDir, `current-task-${agent}.json`);
|
|
4527
4533
|
if (input.status === "in_progress") {
|
|
4528
|
-
|
|
4534
|
+
mkdirSync8(cacheDir, { recursive: true });
|
|
4529
4535
|
writeFileSync8(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
|
|
4530
4536
|
} else if (input.status === "done" || input.status === "blocked" || input.status === "cancelled" || input.status === "closed") {
|
|
4531
4537
|
try {
|
|
4532
|
-
|
|
4538
|
+
unlinkSync7(cachePath);
|
|
4533
4539
|
} catch {
|
|
4534
4540
|
}
|
|
4535
4541
|
}
|