@askexenow/exe-os 0.9.55 → 0.9.56
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/cleanup-stale-review-tasks.js +26 -8
- package/dist/bin/cli.js +14 -1
- package/dist/bin/exe-boot.js +267 -190
- package/dist/bin/exe-dispatch.js +182 -105
- package/dist/bin/exe-export-behaviors.js +7 -0
- package/dist/bin/exe-gateway.js +177 -100
- package/dist/bin/exe-heartbeat.js +38 -20
- package/dist/bin/exe-launch-agent.js +7 -0
- package/dist/bin/exe-pending-messages.js +50 -32
- package/dist/bin/exe-pending-notifications.js +53 -35
- package/dist/bin/exe-pending-reviews.js +55 -37
- package/dist/bin/exe-session-cleanup.js +168 -91
- package/dist/bin/exe-start-codex.js +7 -0
- package/dist/bin/exe-start-opencode.js +7 -0
- package/dist/bin/exe-status.js +26 -8
- package/dist/bin/git-sweep.js +184 -107
- package/dist/bin/intercom-check.js +170 -93
- package/dist/bin/scan-tasks.js +190 -113
- package/dist/gateway/index.js +166 -89
- package/dist/hooks/bug-report-worker.js +158 -81
- package/dist/hooks/codex-stop-task-finalizer.js +57 -39
- package/dist/hooks/commit-complete.js +182 -105
- package/dist/hooks/post-compact.js +50 -32
- package/dist/hooks/pre-compact.js +185 -108
- package/dist/hooks/pre-tool-use.js +71 -53
- package/dist/hooks/prompt-submit.js +176 -92
- package/dist/hooks/session-end.js +193 -116
- package/dist/hooks/session-start.js +53 -35
- package/dist/hooks/stop.js +62 -44
- package/dist/hooks/subagent-stop.js +50 -32
- package/dist/hooks/summary-worker.js +109 -91
- package/dist/index.js +205 -121
- package/dist/lib/exe-daemon.js +381 -304
- package/dist/lib/messaging.js +32 -14
- package/dist/lib/tasks.js +180 -103
- package/dist/lib/tmux-routing.js +180 -103
- package/dist/mcp/server.js +356 -279
- package/dist/mcp/tools/create-task.js +194 -117
- package/dist/mcp/tools/list-tasks.js +45 -27
- package/dist/mcp/tools/send-message.js +36 -18
- package/dist/mcp/tools/update-task.js +189 -112
- package/dist/runtime/index.js +191 -107
- package/dist/tui/App.js +228 -151
- package/package.json +1 -1
package/dist/bin/exe-boot.js
CHANGED
|
@@ -5090,15 +5090,79 @@ var init_plan_limits = __esm({
|
|
|
5090
5090
|
}
|
|
5091
5091
|
});
|
|
5092
5092
|
|
|
5093
|
+
// src/lib/agent-symlinks.ts
|
|
5094
|
+
import os9 from "os";
|
|
5095
|
+
import path13 from "path";
|
|
5096
|
+
import {
|
|
5097
|
+
existsSync as existsSync13,
|
|
5098
|
+
lstatSync,
|
|
5099
|
+
mkdirSync as mkdirSync6,
|
|
5100
|
+
readlinkSync as readlinkSync2,
|
|
5101
|
+
symlinkSync as symlinkSync2
|
|
5102
|
+
} from "fs";
|
|
5103
|
+
function claudeAgentsDir(homeDir) {
|
|
5104
|
+
return path13.join(homeDir, ".claude", "agents");
|
|
5105
|
+
}
|
|
5106
|
+
function identitySourcePath(homeDir, agentId) {
|
|
5107
|
+
return path13.join(homeDir, ".exe-os", "identity", `${agentId}.md`);
|
|
5108
|
+
}
|
|
5109
|
+
function claudeAgentLinkPath(homeDir, agentId) {
|
|
5110
|
+
return path13.join(claudeAgentsDir(homeDir), `${agentId}.md`);
|
|
5111
|
+
}
|
|
5112
|
+
function ensureAgentSymlink(agentId, homeDir = os9.homedir()) {
|
|
5113
|
+
const target = identitySourcePath(homeDir, agentId);
|
|
5114
|
+
const link = claudeAgentLinkPath(homeDir, agentId);
|
|
5115
|
+
mkdirSync6(claudeAgentsDir(homeDir), { recursive: true });
|
|
5116
|
+
if (existsSync13(link)) {
|
|
5117
|
+
let stat;
|
|
5118
|
+
try {
|
|
5119
|
+
stat = lstatSync(link);
|
|
5120
|
+
} catch {
|
|
5121
|
+
return { agentId, action: "conflict", target, link, conflict: "stat_failed" };
|
|
5122
|
+
}
|
|
5123
|
+
if (!stat.isSymbolicLink()) {
|
|
5124
|
+
return { agentId, action: "conflict", target, link, conflict: "regular_file" };
|
|
5125
|
+
}
|
|
5126
|
+
let currentTarget;
|
|
5127
|
+
try {
|
|
5128
|
+
currentTarget = readlinkSync2(link);
|
|
5129
|
+
} catch {
|
|
5130
|
+
return { agentId, action: "conflict", target, link, conflict: "readlink_failed" };
|
|
5131
|
+
}
|
|
5132
|
+
if (currentTarget === target) {
|
|
5133
|
+
return { agentId, action: "already_correct", target, link };
|
|
5134
|
+
}
|
|
5135
|
+
return { agentId, action: "conflict", target, link, conflict: `points_to:${currentTarget}` };
|
|
5136
|
+
}
|
|
5137
|
+
try {
|
|
5138
|
+
symlinkSync2(target, link);
|
|
5139
|
+
} catch (err) {
|
|
5140
|
+
return {
|
|
5141
|
+
agentId,
|
|
5142
|
+
action: "conflict",
|
|
5143
|
+
target,
|
|
5144
|
+
link,
|
|
5145
|
+
conflict: err instanceof Error ? err.message : String(err)
|
|
5146
|
+
};
|
|
5147
|
+
}
|
|
5148
|
+
return { agentId, action: "created", target, link };
|
|
5149
|
+
}
|
|
5150
|
+
var init_agent_symlinks = __esm({
|
|
5151
|
+
"src/lib/agent-symlinks.ts"() {
|
|
5152
|
+
"use strict";
|
|
5153
|
+
init_employees();
|
|
5154
|
+
}
|
|
5155
|
+
});
|
|
5156
|
+
|
|
5093
5157
|
// src/lib/notifications.ts
|
|
5094
5158
|
import crypto2 from "crypto";
|
|
5095
|
-
import
|
|
5096
|
-
import
|
|
5159
|
+
import path14 from "path";
|
|
5160
|
+
import os10 from "os";
|
|
5097
5161
|
import {
|
|
5098
5162
|
readFileSync as readFileSync10,
|
|
5099
5163
|
readdirSync as readdirSync2,
|
|
5100
5164
|
unlinkSync as unlinkSync3,
|
|
5101
|
-
existsSync as
|
|
5165
|
+
existsSync as existsSync14,
|
|
5102
5166
|
rmdirSync
|
|
5103
5167
|
} from "fs";
|
|
5104
5168
|
async function writeNotification(notification) {
|
|
@@ -5221,9 +5285,9 @@ async function markDoneTaskNotificationsAsRead(sessionScope) {
|
|
|
5221
5285
|
}
|
|
5222
5286
|
}
|
|
5223
5287
|
async function migrateJsonNotifications() {
|
|
5224
|
-
const base = process.env.EXE_OS_DIR || process.env.EXE_MEM_DIR ||
|
|
5225
|
-
const notifDir =
|
|
5226
|
-
if (!
|
|
5288
|
+
const base = process.env.EXE_OS_DIR || process.env.EXE_MEM_DIR || path14.join(os10.homedir(), ".exe-os");
|
|
5289
|
+
const notifDir = path14.join(base, "notifications");
|
|
5290
|
+
if (!existsSync14(notifDir)) return 0;
|
|
5227
5291
|
let migrated = 0;
|
|
5228
5292
|
try {
|
|
5229
5293
|
const files = readdirSync2(notifDir).filter((f) => f.endsWith(".json"));
|
|
@@ -5231,7 +5295,7 @@ async function migrateJsonNotifications() {
|
|
|
5231
5295
|
const client = getClient();
|
|
5232
5296
|
for (const file of files) {
|
|
5233
5297
|
try {
|
|
5234
|
-
const filePath =
|
|
5298
|
+
const filePath = path14.join(notifDir, file);
|
|
5235
5299
|
const data = JSON.parse(readFileSync10(filePath, "utf8"));
|
|
5236
5300
|
await client.execute({
|
|
5237
5301
|
sql: `INSERT OR IGNORE INTO notifications (id, agent_id, agent_role, event, project, summary, task_file, session_scope, read, created_at)
|
|
@@ -5386,7 +5450,7 @@ __export(project_name_exports, {
|
|
|
5386
5450
|
getProjectName: () => getProjectName
|
|
5387
5451
|
});
|
|
5388
5452
|
import { execSync as execSync6 } from "child_process";
|
|
5389
|
-
import
|
|
5453
|
+
import path15 from "path";
|
|
5390
5454
|
function getProjectName(cwd) {
|
|
5391
5455
|
const dir = cwd ?? process.cwd();
|
|
5392
5456
|
if (_cached2 && _cachedCwd === dir) return _cached2;
|
|
@@ -5399,7 +5463,7 @@ function getProjectName(cwd) {
|
|
|
5399
5463
|
timeout: 2e3,
|
|
5400
5464
|
stdio: ["pipe", "pipe", "pipe"]
|
|
5401
5465
|
}).trim();
|
|
5402
|
-
repoRoot =
|
|
5466
|
+
repoRoot = path15.dirname(gitCommonDir);
|
|
5403
5467
|
} catch {
|
|
5404
5468
|
repoRoot = execSync6("git rev-parse --show-toplevel", {
|
|
5405
5469
|
cwd: dir,
|
|
@@ -5408,11 +5472,11 @@ function getProjectName(cwd) {
|
|
|
5408
5472
|
stdio: ["pipe", "pipe", "pipe"]
|
|
5409
5473
|
}).trim();
|
|
5410
5474
|
}
|
|
5411
|
-
_cached2 =
|
|
5475
|
+
_cached2 = path15.basename(repoRoot);
|
|
5412
5476
|
_cachedCwd = dir;
|
|
5413
5477
|
return _cached2;
|
|
5414
5478
|
} catch {
|
|
5415
|
-
_cached2 =
|
|
5479
|
+
_cached2 = path15.basename(dir);
|
|
5416
5480
|
_cachedCwd = dir;
|
|
5417
5481
|
return _cached2;
|
|
5418
5482
|
}
|
|
@@ -5494,11 +5558,11 @@ var init_session_scope = __esm({
|
|
|
5494
5558
|
|
|
5495
5559
|
// src/lib/tasks-crud.ts
|
|
5496
5560
|
import crypto4 from "crypto";
|
|
5497
|
-
import
|
|
5498
|
-
import
|
|
5561
|
+
import path16 from "path";
|
|
5562
|
+
import os11 from "os";
|
|
5499
5563
|
import { execSync as execSync7 } from "child_process";
|
|
5500
5564
|
import { mkdir as mkdir4, writeFile as writeFile4, appendFile } from "fs/promises";
|
|
5501
|
-
import { existsSync as
|
|
5565
|
+
import { existsSync as existsSync15, readFileSync as readFileSync11 } from "fs";
|
|
5502
5566
|
async function writeCheckpoint(input) {
|
|
5503
5567
|
const client = getClient();
|
|
5504
5568
|
const row = await resolveTask(client, input.taskId);
|
|
@@ -5697,8 +5761,8 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
|
|
|
5697
5761
|
}
|
|
5698
5762
|
if (input.baseDir) {
|
|
5699
5763
|
try {
|
|
5700
|
-
await mkdir4(
|
|
5701
|
-
await mkdir4(
|
|
5764
|
+
await mkdir4(path16.join(input.baseDir, "exe", "output"), { recursive: true });
|
|
5765
|
+
await mkdir4(path16.join(input.baseDir, "exe", "research"), { recursive: true });
|
|
5702
5766
|
await ensureArchitectureDoc(input.baseDir, input.projectName);
|
|
5703
5767
|
await ensureGitignoreExe(input.baseDir);
|
|
5704
5768
|
} catch {
|
|
@@ -5734,10 +5798,10 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
|
|
|
5734
5798
|
});
|
|
5735
5799
|
if (input.baseDir) {
|
|
5736
5800
|
try {
|
|
5737
|
-
const EXE_OS_DIR =
|
|
5738
|
-
const mdPath =
|
|
5739
|
-
const mdDir =
|
|
5740
|
-
if (!
|
|
5801
|
+
const EXE_OS_DIR = path16.join(os11.homedir(), ".exe-os");
|
|
5802
|
+
const mdPath = path16.join(EXE_OS_DIR, taskFile);
|
|
5803
|
+
const mdDir = path16.dirname(mdPath);
|
|
5804
|
+
if (!existsSync15(mdDir)) await mkdir4(mdDir, { recursive: true });
|
|
5741
5805
|
const reviewer = input.reviewer ?? input.assignedBy;
|
|
5742
5806
|
const mdContent = `# ${input.title}
|
|
5743
5807
|
|
|
@@ -6037,9 +6101,9 @@ async function deleteTaskCore(taskId, _baseDir) {
|
|
|
6037
6101
|
return { taskFile, assignedTo, assignedBy, taskSlug };
|
|
6038
6102
|
}
|
|
6039
6103
|
async function ensureArchitectureDoc(baseDir, projectName) {
|
|
6040
|
-
const archPath =
|
|
6104
|
+
const archPath = path16.join(baseDir, "exe", "ARCHITECTURE.md");
|
|
6041
6105
|
try {
|
|
6042
|
-
if (
|
|
6106
|
+
if (existsSync15(archPath)) return;
|
|
6043
6107
|
const template = [
|
|
6044
6108
|
`# ${projectName} \u2014 System Architecture`,
|
|
6045
6109
|
"",
|
|
@@ -6072,9 +6136,9 @@ async function ensureArchitectureDoc(baseDir, projectName) {
|
|
|
6072
6136
|
}
|
|
6073
6137
|
}
|
|
6074
6138
|
async function ensureGitignoreExe(baseDir) {
|
|
6075
|
-
const gitignorePath =
|
|
6139
|
+
const gitignorePath = path16.join(baseDir, ".gitignore");
|
|
6076
6140
|
try {
|
|
6077
|
-
if (
|
|
6141
|
+
if (existsSync15(gitignorePath)) {
|
|
6078
6142
|
const content = readFileSync11(gitignorePath, "utf-8");
|
|
6079
6143
|
if (/^\/?exe\/?$/m.test(content)) return;
|
|
6080
6144
|
await appendFile(gitignorePath, "\n# Employee task assignments (private)\n/exe/\n");
|
|
@@ -6118,8 +6182,8 @@ __export(tasks_review_exports, {
|
|
|
6118
6182
|
isStale: () => isStale,
|
|
6119
6183
|
listPendingReviews: () => listPendingReviews
|
|
6120
6184
|
});
|
|
6121
|
-
import
|
|
6122
|
-
import { existsSync as
|
|
6185
|
+
import path17 from "path";
|
|
6186
|
+
import { existsSync as existsSync16, readdirSync as readdirSync3, unlinkSync as unlinkSync4 } from "fs";
|
|
6123
6187
|
function formatAge(isoTimestamp) {
|
|
6124
6188
|
if (!isoTimestamp) return "";
|
|
6125
6189
|
const ms = Date.now() - new Date(isoTimestamp).getTime();
|
|
@@ -6388,11 +6452,11 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
|
|
|
6388
6452
|
);
|
|
6389
6453
|
}
|
|
6390
6454
|
try {
|
|
6391
|
-
const cacheDir =
|
|
6392
|
-
if (
|
|
6455
|
+
const cacheDir = path17.join(EXE_AI_DIR, "session-cache");
|
|
6456
|
+
if (existsSync16(cacheDir)) {
|
|
6393
6457
|
for (const f of readdirSync3(cacheDir)) {
|
|
6394
6458
|
if (f.startsWith("review-notified-")) {
|
|
6395
|
-
unlinkSync4(
|
|
6459
|
+
unlinkSync4(path17.join(cacheDir, f));
|
|
6396
6460
|
}
|
|
6397
6461
|
}
|
|
6398
6462
|
}
|
|
@@ -6414,7 +6478,7 @@ var init_tasks_review = __esm({
|
|
|
6414
6478
|
});
|
|
6415
6479
|
|
|
6416
6480
|
// src/lib/tasks-chain.ts
|
|
6417
|
-
import
|
|
6481
|
+
import path18 from "path";
|
|
6418
6482
|
import { readFile as readFile4, writeFile as writeFile5 } from "fs/promises";
|
|
6419
6483
|
async function cascadeUnblock(taskId, baseDir, now) {
|
|
6420
6484
|
const client = getClient();
|
|
@@ -6431,7 +6495,7 @@ async function cascadeUnblock(taskId, baseDir, now) {
|
|
|
6431
6495
|
});
|
|
6432
6496
|
for (const ur of unblockedRows.rows) {
|
|
6433
6497
|
try {
|
|
6434
|
-
const ubFile =
|
|
6498
|
+
const ubFile = path18.join(baseDir, String(ur.task_file));
|
|
6435
6499
|
let ubContent = await readFile4(ubFile, "utf-8");
|
|
6436
6500
|
ubContent = ubContent.replace(/\*\*Status:\*\* blocked/, "**Status:** open");
|
|
6437
6501
|
ubContent = ubContent.replace(/\n\*\*Blocked by:\*\*.*\n/, "\n");
|
|
@@ -6615,10 +6679,10 @@ async function disposeEmbedder() {
|
|
|
6615
6679
|
async function embedDirect(text) {
|
|
6616
6680
|
const llamaCpp = await import("node-llama-cpp");
|
|
6617
6681
|
const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
6618
|
-
const { existsSync:
|
|
6619
|
-
const
|
|
6620
|
-
const modelPath =
|
|
6621
|
-
if (!
|
|
6682
|
+
const { existsSync: existsSync23 } = await import("fs");
|
|
6683
|
+
const path27 = await import("path");
|
|
6684
|
+
const modelPath = path27.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
|
|
6685
|
+
if (!existsSync23(modelPath)) {
|
|
6622
6686
|
throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
|
|
6623
6687
|
}
|
|
6624
6688
|
const llama = await llamaCpp.getLlama();
|
|
@@ -6984,8 +7048,8 @@ __export(tasks_exports, {
|
|
|
6984
7048
|
updateTaskStatus: () => updateTaskStatus,
|
|
6985
7049
|
writeCheckpoint: () => writeCheckpoint
|
|
6986
7050
|
});
|
|
6987
|
-
import
|
|
6988
|
-
import { writeFileSync as writeFileSync7, mkdirSync as
|
|
7051
|
+
import path19 from "path";
|
|
7052
|
+
import { writeFileSync as writeFileSync7, mkdirSync as mkdirSync7, unlinkSync as unlinkSync5 } from "fs";
|
|
6989
7053
|
async function createTask(input) {
|
|
6990
7054
|
const result = await createTaskCore(input);
|
|
6991
7055
|
if (!input.skipDispatch && result.status !== "blocked" && !process.env.VITEST) {
|
|
@@ -7004,10 +7068,10 @@ async function updateTask(input) {
|
|
|
7004
7068
|
const { row, taskFile, now, taskId } = await updateTaskStatus(input);
|
|
7005
7069
|
try {
|
|
7006
7070
|
const agent = String(row.assigned_to);
|
|
7007
|
-
const cacheDir =
|
|
7008
|
-
const cachePath =
|
|
7071
|
+
const cacheDir = path19.join(EXE_AI_DIR, "session-cache");
|
|
7072
|
+
const cachePath = path19.join(cacheDir, `current-task-${agent}.json`);
|
|
7009
7073
|
if (input.status === "in_progress") {
|
|
7010
|
-
|
|
7074
|
+
mkdirSync7(cacheDir, { recursive: true });
|
|
7011
7075
|
writeFileSync7(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
|
|
7012
7076
|
} else if (input.status === "done" || input.status === "blocked" || input.status === "cancelled" || input.status === "closed") {
|
|
7013
7077
|
try {
|
|
@@ -7477,13 +7541,13 @@ __export(tmux_routing_exports, {
|
|
|
7477
7541
|
verifyPaneAtCapacity: () => verifyPaneAtCapacity
|
|
7478
7542
|
});
|
|
7479
7543
|
import { execFileSync as execFileSync2, execSync as execSync8 } from "child_process";
|
|
7480
|
-
import { readFileSync as readFileSync12, writeFileSync as writeFileSync8, mkdirSync as
|
|
7481
|
-
import
|
|
7482
|
-
import
|
|
7544
|
+
import { readFileSync as readFileSync12, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8, existsSync as existsSync17, appendFileSync, readdirSync as readdirSync4 } from "fs";
|
|
7545
|
+
import path20 from "path";
|
|
7546
|
+
import os12 from "os";
|
|
7483
7547
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
7484
7548
|
import { unlinkSync as unlinkSync6 } from "fs";
|
|
7485
7549
|
function spawnLockPath(sessionName) {
|
|
7486
|
-
return
|
|
7550
|
+
return path20.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
|
|
7487
7551
|
}
|
|
7488
7552
|
function isProcessAlive(pid) {
|
|
7489
7553
|
try {
|
|
@@ -7494,11 +7558,11 @@ function isProcessAlive(pid) {
|
|
|
7494
7558
|
}
|
|
7495
7559
|
}
|
|
7496
7560
|
function acquireSpawnLock2(sessionName) {
|
|
7497
|
-
if (!
|
|
7498
|
-
|
|
7561
|
+
if (!existsSync17(SPAWN_LOCK_DIR)) {
|
|
7562
|
+
mkdirSync8(SPAWN_LOCK_DIR, { recursive: true });
|
|
7499
7563
|
}
|
|
7500
7564
|
const lockFile = spawnLockPath(sessionName);
|
|
7501
|
-
if (
|
|
7565
|
+
if (existsSync17(lockFile)) {
|
|
7502
7566
|
try {
|
|
7503
7567
|
const lock = JSON.parse(readFileSync12(lockFile, "utf8"));
|
|
7504
7568
|
const age = Date.now() - lock.timestamp;
|
|
@@ -7520,13 +7584,13 @@ function releaseSpawnLock2(sessionName) {
|
|
|
7520
7584
|
function resolveBehaviorsExporterScript() {
|
|
7521
7585
|
try {
|
|
7522
7586
|
const thisFile = fileURLToPath2(import.meta.url);
|
|
7523
|
-
const scriptPath =
|
|
7524
|
-
|
|
7587
|
+
const scriptPath = path20.join(
|
|
7588
|
+
path20.dirname(thisFile),
|
|
7525
7589
|
"..",
|
|
7526
7590
|
"bin",
|
|
7527
7591
|
"exe-export-behaviors.js"
|
|
7528
7592
|
);
|
|
7529
|
-
return
|
|
7593
|
+
return existsSync17(scriptPath) ? scriptPath : null;
|
|
7530
7594
|
} catch {
|
|
7531
7595
|
return null;
|
|
7532
7596
|
}
|
|
@@ -7592,11 +7656,11 @@ function extractRootExe(name) {
|
|
|
7592
7656
|
return parts.length > 0 ? parts[parts.length - 1] : null;
|
|
7593
7657
|
}
|
|
7594
7658
|
function registerParentExe(sessionKey, parentExe, dispatchedBy) {
|
|
7595
|
-
if (!
|
|
7596
|
-
|
|
7659
|
+
if (!existsSync17(SESSION_CACHE)) {
|
|
7660
|
+
mkdirSync8(SESSION_CACHE, { recursive: true });
|
|
7597
7661
|
}
|
|
7598
7662
|
const rootExe = extractRootExe(parentExe) ?? parentExe;
|
|
7599
|
-
const filePath =
|
|
7663
|
+
const filePath = path20.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
|
|
7600
7664
|
writeFileSync8(filePath, JSON.stringify({
|
|
7601
7665
|
parentExe: rootExe,
|
|
7602
7666
|
dispatchedBy: dispatchedBy || rootExe,
|
|
@@ -7605,7 +7669,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
|
|
|
7605
7669
|
}
|
|
7606
7670
|
function getParentExe(sessionKey) {
|
|
7607
7671
|
try {
|
|
7608
|
-
const data = JSON.parse(readFileSync12(
|
|
7672
|
+
const data = JSON.parse(readFileSync12(path20.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
|
|
7609
7673
|
return data.parentExe || null;
|
|
7610
7674
|
} catch {
|
|
7611
7675
|
return null;
|
|
@@ -7614,7 +7678,7 @@ function getParentExe(sessionKey) {
|
|
|
7614
7678
|
function getDispatchedBy(sessionKey) {
|
|
7615
7679
|
try {
|
|
7616
7680
|
const data = JSON.parse(readFileSync12(
|
|
7617
|
-
|
|
7681
|
+
path20.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
|
|
7618
7682
|
"utf8"
|
|
7619
7683
|
));
|
|
7620
7684
|
return data.dispatchedBy ?? data.parentExe ?? null;
|
|
@@ -7684,7 +7748,7 @@ async function verifyPaneAtCapacity(sessionName) {
|
|
|
7684
7748
|
}
|
|
7685
7749
|
function readDebounceState() {
|
|
7686
7750
|
try {
|
|
7687
|
-
if (!
|
|
7751
|
+
if (!existsSync17(DEBOUNCE_FILE)) return {};
|
|
7688
7752
|
const raw = JSON.parse(readFileSync12(DEBOUNCE_FILE, "utf8"));
|
|
7689
7753
|
const state = {};
|
|
7690
7754
|
for (const [key, val] of Object.entries(raw)) {
|
|
@@ -7701,7 +7765,7 @@ function readDebounceState() {
|
|
|
7701
7765
|
}
|
|
7702
7766
|
function writeDebounceState(state) {
|
|
7703
7767
|
try {
|
|
7704
|
-
if (!
|
|
7768
|
+
if (!existsSync17(SESSION_CACHE)) mkdirSync8(SESSION_CACHE, { recursive: true });
|
|
7705
7769
|
writeFileSync8(DEBOUNCE_FILE, JSON.stringify(state));
|
|
7706
7770
|
} catch {
|
|
7707
7771
|
}
|
|
@@ -7801,8 +7865,8 @@ function sendIntercom(targetSession) {
|
|
|
7801
7865
|
try {
|
|
7802
7866
|
const rawAgent = targetSession.split("-")[0] ?? targetSession;
|
|
7803
7867
|
const agent = baseAgentName(rawAgent);
|
|
7804
|
-
const markerPath =
|
|
7805
|
-
if (
|
|
7868
|
+
const markerPath = path20.join(SESSION_CACHE, `current-task-${agent}.json`);
|
|
7869
|
+
if (existsSync17(markerPath)) {
|
|
7806
7870
|
logIntercom(`SKIP \u2192 ${targetSession} (has in_progress task marker + not idle \u2014 will auto-chain)`);
|
|
7807
7871
|
return "debounced";
|
|
7808
7872
|
}
|
|
@@ -7812,8 +7876,8 @@ function sendIntercom(targetSession) {
|
|
|
7812
7876
|
try {
|
|
7813
7877
|
const rawAgent = targetSession.split("-")[0] ?? targetSession;
|
|
7814
7878
|
const agent = baseAgentName(rawAgent);
|
|
7815
|
-
const taskDir =
|
|
7816
|
-
if (
|
|
7879
|
+
const taskDir = path20.join(process.cwd(), "exe", agent);
|
|
7880
|
+
if (existsSync17(taskDir)) {
|
|
7817
7881
|
const files = readdirSync4(taskDir).filter(
|
|
7818
7882
|
(f) => f.endsWith(".md") && f !== "DONE.txt"
|
|
7819
7883
|
);
|
|
@@ -7972,23 +8036,23 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
7972
8036
|
const transport = getTransport();
|
|
7973
8037
|
const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
|
|
7974
8038
|
const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
|
|
7975
|
-
const logDir =
|
|
7976
|
-
const logFile =
|
|
7977
|
-
if (!
|
|
7978
|
-
|
|
8039
|
+
const logDir = path20.join(os12.homedir(), ".exe-os", "session-logs");
|
|
8040
|
+
const logFile = path20.join(logDir, `${instanceLabel}-${Date.now()}.log`);
|
|
8041
|
+
if (!existsSync17(logDir)) {
|
|
8042
|
+
mkdirSync8(logDir, { recursive: true });
|
|
7979
8043
|
}
|
|
7980
8044
|
transport.kill(sessionName);
|
|
7981
8045
|
let cleanupSuffix = "";
|
|
7982
8046
|
try {
|
|
7983
8047
|
const thisFile = fileURLToPath2(import.meta.url);
|
|
7984
|
-
const cleanupScript =
|
|
7985
|
-
if (
|
|
8048
|
+
const cleanupScript = path20.join(path20.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
|
|
8049
|
+
if (existsSync17(cleanupScript)) {
|
|
7986
8050
|
cleanupSuffix = `; ${process.execPath} "${cleanupScript}" "${employeeName}" "${exeSession}"`;
|
|
7987
8051
|
}
|
|
7988
8052
|
} catch {
|
|
7989
8053
|
}
|
|
7990
8054
|
try {
|
|
7991
|
-
const claudeJsonPath =
|
|
8055
|
+
const claudeJsonPath = path20.join(os12.homedir(), ".claude.json");
|
|
7992
8056
|
let claudeJson = {};
|
|
7993
8057
|
try {
|
|
7994
8058
|
claudeJson = JSON.parse(readFileSync12(claudeJsonPath, "utf8"));
|
|
@@ -8003,10 +8067,10 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
8003
8067
|
} catch {
|
|
8004
8068
|
}
|
|
8005
8069
|
try {
|
|
8006
|
-
const settingsDir =
|
|
8070
|
+
const settingsDir = path20.join(os12.homedir(), ".claude", "projects");
|
|
8007
8071
|
const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
|
|
8008
|
-
const projSettingsDir =
|
|
8009
|
-
const settingsPath =
|
|
8072
|
+
const projSettingsDir = path20.join(settingsDir, normalizedKey);
|
|
8073
|
+
const settingsPath = path20.join(projSettingsDir, "settings.json");
|
|
8010
8074
|
let settings = {};
|
|
8011
8075
|
try {
|
|
8012
8076
|
settings = JSON.parse(readFileSync12(settingsPath, "utf8"));
|
|
@@ -8037,7 +8101,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
8037
8101
|
if (changed) {
|
|
8038
8102
|
perms.allow = allow;
|
|
8039
8103
|
settings.permissions = perms;
|
|
8040
|
-
|
|
8104
|
+
mkdirSync8(projSettingsDir, { recursive: true });
|
|
8041
8105
|
writeFileSync8(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
8042
8106
|
}
|
|
8043
8107
|
} catch {
|
|
@@ -8053,8 +8117,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
8053
8117
|
let behaviorsFlag = "";
|
|
8054
8118
|
let legacyFallbackWarned = false;
|
|
8055
8119
|
if (!useExeAgent && !useBinSymlink) {
|
|
8056
|
-
const identityPath =
|
|
8057
|
-
|
|
8120
|
+
const identityPath = path20.join(
|
|
8121
|
+
os12.homedir(),
|
|
8058
8122
|
".exe-os",
|
|
8059
8123
|
"identity",
|
|
8060
8124
|
`${employeeName}.md`
|
|
@@ -8062,14 +8126,26 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
8062
8126
|
_resetCcAgentSupportCache();
|
|
8063
8127
|
const hasAgentFlag = claudeSupportsAgentFlag();
|
|
8064
8128
|
if (hasAgentFlag) {
|
|
8065
|
-
|
|
8066
|
-
|
|
8129
|
+
const symlink = ensureAgentSymlink(employeeName);
|
|
8130
|
+
if (symlink.action === "created" || symlink.action === "already_correct") {
|
|
8131
|
+
identityFlag = ` --agent ${employeeName}`;
|
|
8132
|
+
} else if (existsSync17(identityPath)) {
|
|
8133
|
+
identityFlag = ` --append-system-prompt-file ${identityPath}`;
|
|
8134
|
+
legacyFallbackWarned = true;
|
|
8135
|
+
process.stderr.write(
|
|
8136
|
+
`[tmux-routing] WARN: ~/.claude/agents/${employeeName}.md is not the exe-os identity symlink (${symlink.conflict}). Using authoritative ${identityPath} via --append-system-prompt-file.
|
|
8137
|
+
`
|
|
8138
|
+
);
|
|
8139
|
+
} else {
|
|
8140
|
+
identityFlag = ` --agent ${employeeName}`;
|
|
8141
|
+
}
|
|
8142
|
+
} else if (existsSync17(identityPath)) {
|
|
8067
8143
|
identityFlag = ` --append-system-prompt-file ${identityPath}`;
|
|
8068
8144
|
legacyFallbackWarned = true;
|
|
8069
8145
|
}
|
|
8070
8146
|
const behaviorsFile = exportBehaviorsSync(
|
|
8071
8147
|
employeeName,
|
|
8072
|
-
|
|
8148
|
+
path20.basename(spawnCwd),
|
|
8073
8149
|
sessionName
|
|
8074
8150
|
);
|
|
8075
8151
|
if (behaviorsFile) {
|
|
@@ -8084,9 +8160,9 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
8084
8160
|
}
|
|
8085
8161
|
let sessionContextFlag = "";
|
|
8086
8162
|
try {
|
|
8087
|
-
const ctxDir =
|
|
8088
|
-
|
|
8089
|
-
const ctxFile =
|
|
8163
|
+
const ctxDir = path20.join(os12.homedir(), ".exe-os", "session-cache");
|
|
8164
|
+
mkdirSync8(ctxDir, { recursive: true });
|
|
8165
|
+
const ctxFile = path20.join(ctxDir, `session-context-${sessionName}.md`);
|
|
8090
8166
|
const ctxContent = [
|
|
8091
8167
|
`## Session Context`,
|
|
8092
8168
|
`You are running in tmux session: ${sessionName}.`,
|
|
@@ -8176,7 +8252,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
8176
8252
|
transport.pipeLog(sessionName, logFile);
|
|
8177
8253
|
try {
|
|
8178
8254
|
const mySession = getMySession();
|
|
8179
|
-
const dispatchInfo =
|
|
8255
|
+
const dispatchInfo = path20.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
|
|
8180
8256
|
writeFileSync8(dispatchInfo, JSON.stringify({
|
|
8181
8257
|
dispatchedBy: mySession,
|
|
8182
8258
|
rootExe: exeSession,
|
|
@@ -8251,15 +8327,16 @@ var init_tmux_routing = __esm({
|
|
|
8251
8327
|
init_intercom_queue();
|
|
8252
8328
|
init_plan_limits();
|
|
8253
8329
|
init_employees();
|
|
8254
|
-
|
|
8255
|
-
|
|
8330
|
+
init_agent_symlinks();
|
|
8331
|
+
SPAWN_LOCK_DIR = path20.join(os12.homedir(), ".exe-os", "spawn-locks");
|
|
8332
|
+
SESSION_CACHE = path20.join(os12.homedir(), ".exe-os", "session-cache");
|
|
8256
8333
|
BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
|
|
8257
8334
|
VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
|
|
8258
8335
|
VERIFY_PANE_LINES = 200;
|
|
8259
8336
|
INTERCOM_DEBOUNCE_MS = 3e4;
|
|
8260
8337
|
CODEX_DEBOUNCE_MS = 12e4;
|
|
8261
|
-
INTERCOM_LOG2 =
|
|
8262
|
-
DEBOUNCE_FILE =
|
|
8338
|
+
INTERCOM_LOG2 = path20.join(os12.homedir(), ".exe-os", "intercom.log");
|
|
8339
|
+
DEBOUNCE_FILE = path20.join(SESSION_CACHE, "intercom-debounce.json");
|
|
8263
8340
|
DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
|
|
8264
8341
|
BUSY_PATTERN = /[✻✽✶✳·].*…|Running…|• Working|• Ran |• Explored|• Called|esc to interrupt/;
|
|
8265
8342
|
}
|
|
@@ -8325,13 +8402,13 @@ __export(worker_gate_exports, {
|
|
|
8325
8402
|
tryAcquireBackfillLock: () => tryAcquireBackfillLock,
|
|
8326
8403
|
tryAcquireWorkerSlot: () => tryAcquireWorkerSlot
|
|
8327
8404
|
});
|
|
8328
|
-
import { readdirSync as readdirSync6, writeFileSync as writeFileSync10, unlinkSync as unlinkSync8, mkdirSync as
|
|
8329
|
-
import
|
|
8405
|
+
import { readdirSync as readdirSync6, writeFileSync as writeFileSync10, unlinkSync as unlinkSync8, mkdirSync as mkdirSync10, existsSync as existsSync18 } from "fs";
|
|
8406
|
+
import path22 from "path";
|
|
8330
8407
|
function tryAcquireWorkerSlot() {
|
|
8331
8408
|
try {
|
|
8332
|
-
|
|
8409
|
+
mkdirSync10(WORKER_PID_DIR, { recursive: true });
|
|
8333
8410
|
const reservationId = `res-${process.pid}-${Date.now()}`;
|
|
8334
|
-
const reservationPath =
|
|
8411
|
+
const reservationPath = path22.join(WORKER_PID_DIR, `${reservationId}.pid`);
|
|
8335
8412
|
writeFileSync10(reservationPath, String(process.pid));
|
|
8336
8413
|
const files = readdirSync6(WORKER_PID_DIR);
|
|
8337
8414
|
let alive = 0;
|
|
@@ -8349,7 +8426,7 @@ function tryAcquireWorkerSlot() {
|
|
|
8349
8426
|
alive++;
|
|
8350
8427
|
} catch {
|
|
8351
8428
|
try {
|
|
8352
|
-
unlinkSync8(
|
|
8429
|
+
unlinkSync8(path22.join(WORKER_PID_DIR, f));
|
|
8353
8430
|
} catch {
|
|
8354
8431
|
}
|
|
8355
8432
|
}
|
|
@@ -8372,21 +8449,21 @@ function tryAcquireWorkerSlot() {
|
|
|
8372
8449
|
}
|
|
8373
8450
|
function registerWorkerPid(pid) {
|
|
8374
8451
|
try {
|
|
8375
|
-
|
|
8376
|
-
writeFileSync10(
|
|
8452
|
+
mkdirSync10(WORKER_PID_DIR, { recursive: true });
|
|
8453
|
+
writeFileSync10(path22.join(WORKER_PID_DIR, `worker-${pid}.pid`), String(pid));
|
|
8377
8454
|
} catch {
|
|
8378
8455
|
}
|
|
8379
8456
|
}
|
|
8380
8457
|
function cleanupWorkerPid() {
|
|
8381
8458
|
try {
|
|
8382
|
-
unlinkSync8(
|
|
8459
|
+
unlinkSync8(path22.join(WORKER_PID_DIR, `worker-${process.pid}.pid`));
|
|
8383
8460
|
} catch {
|
|
8384
8461
|
}
|
|
8385
8462
|
}
|
|
8386
8463
|
function tryAcquireBackfillLock() {
|
|
8387
8464
|
try {
|
|
8388
|
-
|
|
8389
|
-
if (
|
|
8465
|
+
mkdirSync10(WORKER_PID_DIR, { recursive: true });
|
|
8466
|
+
if (existsSync18(BACKFILL_LOCK)) {
|
|
8390
8467
|
try {
|
|
8391
8468
|
const pid = parseInt(
|
|
8392
8469
|
__require("fs").readFileSync(BACKFILL_LOCK, "utf8").trim(),
|
|
@@ -8419,9 +8496,9 @@ var init_worker_gate = __esm({
|
|
|
8419
8496
|
"src/lib/worker-gate.ts"() {
|
|
8420
8497
|
"use strict";
|
|
8421
8498
|
init_config();
|
|
8422
|
-
WORKER_PID_DIR =
|
|
8499
|
+
WORKER_PID_DIR = path22.join(EXE_AI_DIR, "worker-pids");
|
|
8423
8500
|
MAX_CONCURRENT_WORKERS = 3;
|
|
8424
|
-
BACKFILL_LOCK =
|
|
8501
|
+
BACKFILL_LOCK = path22.join(WORKER_PID_DIR, "backfill.lock");
|
|
8425
8502
|
}
|
|
8426
8503
|
});
|
|
8427
8504
|
|
|
@@ -8523,8 +8600,8 @@ __export(crdt_sync_exports, {
|
|
|
8523
8600
|
rebuildFromDb: () => rebuildFromDb
|
|
8524
8601
|
});
|
|
8525
8602
|
import * as Y from "yjs";
|
|
8526
|
-
import { readFileSync as readFileSync14, writeFileSync as writeFileSync11, existsSync as
|
|
8527
|
-
import
|
|
8603
|
+
import { readFileSync as readFileSync14, writeFileSync as writeFileSync11, existsSync as existsSync19, mkdirSync as mkdirSync11, unlinkSync as unlinkSync9 } from "fs";
|
|
8604
|
+
import path23 from "path";
|
|
8528
8605
|
import { homedir } from "os";
|
|
8529
8606
|
function getStatePath() {
|
|
8530
8607
|
return _statePathOverride ?? DEFAULT_STATE_PATH;
|
|
@@ -8536,7 +8613,7 @@ function initCrdtDoc() {
|
|
|
8536
8613
|
if (doc) return doc;
|
|
8537
8614
|
doc = new Y.Doc();
|
|
8538
8615
|
const sp = getStatePath();
|
|
8539
|
-
if (
|
|
8616
|
+
if (existsSync19(sp)) {
|
|
8540
8617
|
try {
|
|
8541
8618
|
const state = readFileSync14(sp);
|
|
8542
8619
|
Y.applyUpdate(doc, new Uint8Array(state));
|
|
@@ -8680,8 +8757,8 @@ function persistState() {
|
|
|
8680
8757
|
if (!doc) return;
|
|
8681
8758
|
try {
|
|
8682
8759
|
const sp = getStatePath();
|
|
8683
|
-
const dir =
|
|
8684
|
-
if (!
|
|
8760
|
+
const dir = path23.dirname(sp);
|
|
8761
|
+
if (!existsSync19(dir)) mkdirSync11(dir, { recursive: true });
|
|
8685
8762
|
const state = Y.encodeStateAsUpdate(doc);
|
|
8686
8763
|
writeFileSync11(sp, Buffer.from(state));
|
|
8687
8764
|
} catch {
|
|
@@ -8724,7 +8801,7 @@ var DEFAULT_STATE_PATH, _statePathOverride, doc;
|
|
|
8724
8801
|
var init_crdt_sync = __esm({
|
|
8725
8802
|
"src/lib/crdt-sync.ts"() {
|
|
8726
8803
|
"use strict";
|
|
8727
|
-
DEFAULT_STATE_PATH =
|
|
8804
|
+
DEFAULT_STATE_PATH = path23.join(homedir(), ".exe-os", "crdt-state.bin");
|
|
8728
8805
|
_statePathOverride = null;
|
|
8729
8806
|
doc = null;
|
|
8730
8807
|
}
|
|
@@ -8741,33 +8818,33 @@ __export(db_backup_exports, {
|
|
|
8741
8818
|
listBackups: () => listBackups,
|
|
8742
8819
|
rotateBackups: () => rotateBackups
|
|
8743
8820
|
});
|
|
8744
|
-
import { copyFileSync, existsSync as
|
|
8745
|
-
import
|
|
8821
|
+
import { copyFileSync, existsSync as existsSync20, mkdirSync as mkdirSync12, readdirSync as readdirSync7, unlinkSync as unlinkSync10, statSync as statSync3 } from "fs";
|
|
8822
|
+
import path24 from "path";
|
|
8746
8823
|
function findActiveDb() {
|
|
8747
8824
|
for (const name of DB_NAMES) {
|
|
8748
|
-
const p =
|
|
8749
|
-
if (
|
|
8825
|
+
const p = path24.join(EXE_AI_DIR, name);
|
|
8826
|
+
if (existsSync20(p)) return p;
|
|
8750
8827
|
}
|
|
8751
8828
|
return null;
|
|
8752
8829
|
}
|
|
8753
8830
|
function createBackup(reason = "manual") {
|
|
8754
8831
|
const dbPath = findActiveDb();
|
|
8755
8832
|
if (!dbPath) return null;
|
|
8756
|
-
|
|
8757
|
-
const dbName =
|
|
8833
|
+
mkdirSync12(BACKUP_DIR, { recursive: true });
|
|
8834
|
+
const dbName = path24.basename(dbPath, ".db");
|
|
8758
8835
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
8759
8836
|
const backupName = `${dbName}-${reason}-${timestamp}.db`;
|
|
8760
|
-
const backupPath =
|
|
8837
|
+
const backupPath = path24.join(BACKUP_DIR, backupName);
|
|
8761
8838
|
copyFileSync(dbPath, backupPath);
|
|
8762
8839
|
const walPath = dbPath + "-wal";
|
|
8763
|
-
if (
|
|
8840
|
+
if (existsSync20(walPath)) {
|
|
8764
8841
|
try {
|
|
8765
8842
|
copyFileSync(walPath, backupPath + "-wal");
|
|
8766
8843
|
} catch {
|
|
8767
8844
|
}
|
|
8768
8845
|
}
|
|
8769
8846
|
const shmPath = dbPath + "-shm";
|
|
8770
|
-
if (
|
|
8847
|
+
if (existsSync20(shmPath)) {
|
|
8771
8848
|
try {
|
|
8772
8849
|
copyFileSync(shmPath, backupPath + "-shm");
|
|
8773
8850
|
} catch {
|
|
@@ -8776,14 +8853,14 @@ function createBackup(reason = "manual") {
|
|
|
8776
8853
|
return backupPath;
|
|
8777
8854
|
}
|
|
8778
8855
|
function rotateBackups(keepDays = DEFAULT_KEEP_DAYS) {
|
|
8779
|
-
if (!
|
|
8856
|
+
if (!existsSync20(BACKUP_DIR)) return 0;
|
|
8780
8857
|
const cutoff = Date.now() - keepDays * 24 * 60 * 60 * 1e3;
|
|
8781
8858
|
let deleted = 0;
|
|
8782
8859
|
try {
|
|
8783
8860
|
const files = readdirSync7(BACKUP_DIR);
|
|
8784
8861
|
for (const file of files) {
|
|
8785
8862
|
if (!file.endsWith(".db") && !file.endsWith(".db-wal") && !file.endsWith(".db-shm")) continue;
|
|
8786
|
-
const filePath =
|
|
8863
|
+
const filePath = path24.join(BACKUP_DIR, file);
|
|
8787
8864
|
try {
|
|
8788
8865
|
const stat = statSync3(filePath);
|
|
8789
8866
|
if (stat.mtimeMs < cutoff) {
|
|
@@ -8798,11 +8875,11 @@ function rotateBackups(keepDays = DEFAULT_KEEP_DAYS) {
|
|
|
8798
8875
|
return deleted;
|
|
8799
8876
|
}
|
|
8800
8877
|
function listBackups() {
|
|
8801
|
-
if (!
|
|
8878
|
+
if (!existsSync20(BACKUP_DIR)) return [];
|
|
8802
8879
|
try {
|
|
8803
8880
|
const files = readdirSync7(BACKUP_DIR).filter((f) => f.endsWith(".db") && !f.endsWith("-wal") && !f.endsWith("-shm"));
|
|
8804
8881
|
return files.map((name) => {
|
|
8805
|
-
const p =
|
|
8882
|
+
const p = path24.join(BACKUP_DIR, name);
|
|
8806
8883
|
const stat = statSync3(p);
|
|
8807
8884
|
return { path: p, name, size: stat.size, date: stat.mtime };
|
|
8808
8885
|
}).sort((a, b) => b.date.getTime() - a.date.getTime());
|
|
@@ -8827,7 +8904,7 @@ var init_db_backup = __esm({
|
|
|
8827
8904
|
"src/lib/db-backup.ts"() {
|
|
8828
8905
|
"use strict";
|
|
8829
8906
|
init_config();
|
|
8830
|
-
BACKUP_DIR =
|
|
8907
|
+
BACKUP_DIR = path24.join(EXE_AI_DIR, "backups");
|
|
8831
8908
|
DEFAULT_KEEP_DAYS = 3;
|
|
8832
8909
|
DB_NAMES = ["memories.db", "exe-mem.db", "exe-os.db", "exe.db"];
|
|
8833
8910
|
}
|
|
@@ -8862,16 +8939,16 @@ __export(cloud_sync_exports, {
|
|
|
8862
8939
|
pushToPostgres: () => pushToPostgres,
|
|
8863
8940
|
recordRosterDeletion: () => recordRosterDeletion
|
|
8864
8941
|
});
|
|
8865
|
-
import { readFileSync as readFileSync15, writeFileSync as writeFileSync12, existsSync as
|
|
8942
|
+
import { readFileSync as readFileSync15, writeFileSync as writeFileSync12, existsSync as existsSync21, readdirSync as readdirSync8, mkdirSync as mkdirSync13, appendFileSync as appendFileSync2, unlinkSync as unlinkSync11, openSync as openSync2, closeSync as closeSync2, statSync as statSync4 } from "fs";
|
|
8866
8943
|
import crypto8 from "crypto";
|
|
8867
|
-
import
|
|
8944
|
+
import path25 from "path";
|
|
8868
8945
|
import { homedir as homedir2 } from "os";
|
|
8869
8946
|
function sqlSafe(v) {
|
|
8870
8947
|
return v === void 0 ? null : v;
|
|
8871
8948
|
}
|
|
8872
8949
|
function logError(msg) {
|
|
8873
8950
|
try {
|
|
8874
|
-
const logPath =
|
|
8951
|
+
const logPath = path25.join(homedir2(), ".exe-os", "workers.log");
|
|
8875
8952
|
appendFileSync2(logPath, `${(/* @__PURE__ */ new Date()).toISOString()} ${msg}
|
|
8876
8953
|
`);
|
|
8877
8954
|
} catch {
|
|
@@ -8880,10 +8957,10 @@ function logError(msg) {
|
|
|
8880
8957
|
function loadPgClient() {
|
|
8881
8958
|
if (_pgFailed) return null;
|
|
8882
8959
|
const postgresUrl = process.env.DATABASE_URL;
|
|
8883
|
-
const configPath =
|
|
8960
|
+
const configPath = path25.join(EXE_AI_DIR, "config.json");
|
|
8884
8961
|
let cloudPostgresUrl;
|
|
8885
8962
|
try {
|
|
8886
|
-
if (
|
|
8963
|
+
if (existsSync21(configPath)) {
|
|
8887
8964
|
const cfg = JSON.parse(readFileSync15(configPath, "utf8"));
|
|
8888
8965
|
cloudPostgresUrl = cfg.cloud?.postgresUrl;
|
|
8889
8966
|
if (cfg.cloud?.syncToPostgres === false) {
|
|
@@ -8902,8 +8979,8 @@ function loadPgClient() {
|
|
|
8902
8979
|
_pgPromise = (async () => {
|
|
8903
8980
|
const { createRequire: createRequire3 } = await import("module");
|
|
8904
8981
|
const { pathToFileURL: pathToFileURL3 } = await import("url");
|
|
8905
|
-
const exeDbRoot = process.env.EXE_DB_ROOT ??
|
|
8906
|
-
const req = createRequire3(
|
|
8982
|
+
const exeDbRoot = process.env.EXE_DB_ROOT ?? path25.join(homedir2(), "exe-db");
|
|
8983
|
+
const req = createRequire3(path25.join(exeDbRoot, "package.json"));
|
|
8907
8984
|
const entry = req.resolve("@prisma/client");
|
|
8908
8985
|
const mod = await import(pathToFileURL3(entry).href);
|
|
8909
8986
|
const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
|
|
@@ -9343,8 +9420,8 @@ async function cloudSync(config) {
|
|
|
9343
9420
|
try {
|
|
9344
9421
|
const employees = await loadEmployees();
|
|
9345
9422
|
rosterResult.employees = employees.length;
|
|
9346
|
-
const idDir =
|
|
9347
|
-
if (
|
|
9423
|
+
const idDir = path25.join(EXE_AI_DIR, "identity");
|
|
9424
|
+
if (existsSync21(idDir)) {
|
|
9348
9425
|
rosterResult.identities = readdirSync8(idDir).filter((f) => f.endsWith(".md")).length;
|
|
9349
9426
|
}
|
|
9350
9427
|
} catch {
|
|
@@ -9365,7 +9442,7 @@ async function cloudSync(config) {
|
|
|
9365
9442
|
headers: { "Content-Type": "application/json", Authorization: `Bearer ${config.apiKey}` },
|
|
9366
9443
|
body: JSON.stringify({
|
|
9367
9444
|
device_id: deviceId,
|
|
9368
|
-
filename:
|
|
9445
|
+
filename: path25.basename(latestBackup),
|
|
9369
9446
|
blob: encrypted,
|
|
9370
9447
|
size: backupData.length
|
|
9371
9448
|
})
|
|
@@ -9393,7 +9470,7 @@ async function cloudSync(config) {
|
|
|
9393
9470
|
function recordRosterDeletion(name) {
|
|
9394
9471
|
let deletions = [];
|
|
9395
9472
|
try {
|
|
9396
|
-
if (
|
|
9473
|
+
if (existsSync21(ROSTER_DELETIONS_PATH)) {
|
|
9397
9474
|
deletions = JSON.parse(readFileSync15(ROSTER_DELETIONS_PATH, "utf-8"));
|
|
9398
9475
|
}
|
|
9399
9476
|
} catch {
|
|
@@ -9403,7 +9480,7 @@ function recordRosterDeletion(name) {
|
|
|
9403
9480
|
}
|
|
9404
9481
|
function consumeRosterDeletions() {
|
|
9405
9482
|
try {
|
|
9406
|
-
if (!
|
|
9483
|
+
if (!existsSync21(ROSTER_DELETIONS_PATH)) return [];
|
|
9407
9484
|
const deletions = JSON.parse(readFileSync15(ROSTER_DELETIONS_PATH, "utf-8"));
|
|
9408
9485
|
writeFileSync12(ROSTER_DELETIONS_PATH, "[]");
|
|
9409
9486
|
return deletions;
|
|
@@ -9412,35 +9489,35 @@ function consumeRosterDeletions() {
|
|
|
9412
9489
|
}
|
|
9413
9490
|
}
|
|
9414
9491
|
function buildRosterBlob(paths) {
|
|
9415
|
-
const rosterPath = paths?.rosterPath ??
|
|
9416
|
-
const identityDir = paths?.identityDir ??
|
|
9417
|
-
const configPath = paths?.configPath ??
|
|
9492
|
+
const rosterPath = paths?.rosterPath ?? path25.join(EXE_AI_DIR, "exe-employees.json");
|
|
9493
|
+
const identityDir = paths?.identityDir ?? path25.join(EXE_AI_DIR, "identity");
|
|
9494
|
+
const configPath = paths?.configPath ?? path25.join(EXE_AI_DIR, "config.json");
|
|
9418
9495
|
let roster = [];
|
|
9419
|
-
if (
|
|
9496
|
+
if (existsSync21(rosterPath)) {
|
|
9420
9497
|
try {
|
|
9421
9498
|
roster = JSON.parse(readFileSync15(rosterPath, "utf-8"));
|
|
9422
9499
|
} catch {
|
|
9423
9500
|
}
|
|
9424
9501
|
}
|
|
9425
9502
|
const identities = {};
|
|
9426
|
-
if (
|
|
9503
|
+
if (existsSync21(identityDir)) {
|
|
9427
9504
|
for (const file of readdirSync8(identityDir).filter((f) => f.endsWith(".md"))) {
|
|
9428
9505
|
try {
|
|
9429
|
-
identities[file] = readFileSync15(
|
|
9506
|
+
identities[file] = readFileSync15(path25.join(identityDir, file), "utf-8");
|
|
9430
9507
|
} catch {
|
|
9431
9508
|
}
|
|
9432
9509
|
}
|
|
9433
9510
|
}
|
|
9434
9511
|
let config;
|
|
9435
|
-
if (
|
|
9512
|
+
if (existsSync21(configPath)) {
|
|
9436
9513
|
try {
|
|
9437
9514
|
config = JSON.parse(readFileSync15(configPath, "utf-8"));
|
|
9438
9515
|
} catch {
|
|
9439
9516
|
}
|
|
9440
9517
|
}
|
|
9441
9518
|
let agentConfig;
|
|
9442
|
-
const agentConfigPath =
|
|
9443
|
-
if (
|
|
9519
|
+
const agentConfigPath = path25.join(EXE_AI_DIR, "agent-config.json");
|
|
9520
|
+
if (existsSync21(agentConfigPath)) {
|
|
9444
9521
|
try {
|
|
9445
9522
|
agentConfig = JSON.parse(readFileSync15(agentConfigPath, "utf-8"));
|
|
9446
9523
|
} catch {
|
|
@@ -9518,16 +9595,16 @@ async function cloudPullRoster(config) {
|
|
|
9518
9595
|
}
|
|
9519
9596
|
}
|
|
9520
9597
|
function mergeConfig(remoteConfig, configPath) {
|
|
9521
|
-
const cfgPath = configPath ??
|
|
9598
|
+
const cfgPath = configPath ?? path25.join(EXE_AI_DIR, "config.json");
|
|
9522
9599
|
let local = {};
|
|
9523
|
-
if (
|
|
9600
|
+
if (existsSync21(cfgPath)) {
|
|
9524
9601
|
try {
|
|
9525
9602
|
local = JSON.parse(readFileSync15(cfgPath, "utf-8"));
|
|
9526
9603
|
} catch {
|
|
9527
9604
|
}
|
|
9528
9605
|
}
|
|
9529
9606
|
const merged = { ...remoteConfig, ...local };
|
|
9530
|
-
const dir =
|
|
9607
|
+
const dir = path25.dirname(cfgPath);
|
|
9531
9608
|
ensurePrivateDirSync(dir);
|
|
9532
9609
|
writeFileSync12(cfgPath, JSON.stringify(merged, null, 2), "utf-8");
|
|
9533
9610
|
enforcePrivateFileSync(cfgPath);
|
|
@@ -9535,7 +9612,7 @@ function mergeConfig(remoteConfig, configPath) {
|
|
|
9535
9612
|
async function mergeRosterFromRemote(remote, paths) {
|
|
9536
9613
|
return withRosterLock(async () => {
|
|
9537
9614
|
const rosterPath = paths?.rosterPath ?? void 0;
|
|
9538
|
-
const identityDir = paths?.identityDir ??
|
|
9615
|
+
const identityDir = paths?.identityDir ?? path25.join(EXE_AI_DIR, "identity");
|
|
9539
9616
|
const localEmployees = await loadEmployees(rosterPath);
|
|
9540
9617
|
const localNames = new Set(localEmployees.map((e) => e.name));
|
|
9541
9618
|
let added = 0;
|
|
@@ -9556,11 +9633,11 @@ async function mergeRosterFromRemote(remote, paths) {
|
|
|
9556
9633
|
) ?? lookupKey;
|
|
9557
9634
|
const remoteIdentity = remote.identities[matchedKey];
|
|
9558
9635
|
if (remoteIdentity) {
|
|
9559
|
-
if (!
|
|
9560
|
-
const idPath =
|
|
9636
|
+
if (!existsSync21(identityDir)) mkdirSync13(identityDir, { recursive: true });
|
|
9637
|
+
const idPath = path25.join(identityDir, `${remoteEmp.name}.md`);
|
|
9561
9638
|
let localIdentity = null;
|
|
9562
9639
|
try {
|
|
9563
|
-
localIdentity =
|
|
9640
|
+
localIdentity = existsSync21(idPath) ? readFileSync15(idPath, "utf-8") : null;
|
|
9564
9641
|
} catch {
|
|
9565
9642
|
}
|
|
9566
9643
|
if (localIdentity !== remoteIdentity) {
|
|
@@ -9590,16 +9667,16 @@ async function mergeRosterFromRemote(remote, paths) {
|
|
|
9590
9667
|
}
|
|
9591
9668
|
if (remote.agentConfig && Object.keys(remote.agentConfig).length > 0) {
|
|
9592
9669
|
try {
|
|
9593
|
-
const agentConfigPath =
|
|
9670
|
+
const agentConfigPath = path25.join(EXE_AI_DIR, "agent-config.json");
|
|
9594
9671
|
let local = {};
|
|
9595
|
-
if (
|
|
9672
|
+
if (existsSync21(agentConfigPath)) {
|
|
9596
9673
|
try {
|
|
9597
9674
|
local = JSON.parse(readFileSync15(agentConfigPath, "utf-8"));
|
|
9598
9675
|
} catch {
|
|
9599
9676
|
}
|
|
9600
9677
|
}
|
|
9601
9678
|
const merged = { ...remote.agentConfig, ...local };
|
|
9602
|
-
ensurePrivateDirSync(
|
|
9679
|
+
ensurePrivateDirSync(path25.dirname(agentConfigPath));
|
|
9603
9680
|
writeFileSync12(agentConfigPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
|
|
9604
9681
|
enforcePrivateFileSync(agentConfigPath);
|
|
9605
9682
|
} catch {
|
|
@@ -10040,11 +10117,11 @@ var init_cloud_sync = __esm({
|
|
|
10040
10117
|
LOCALHOST_PATTERNS = /^(localhost|127\.0\.0\.1|\[::1\])$/i;
|
|
10041
10118
|
FETCH_TIMEOUT_MS = 3e4;
|
|
10042
10119
|
PUSH_BATCH_SIZE = 5e3;
|
|
10043
|
-
ROSTER_LOCK_PATH =
|
|
10120
|
+
ROSTER_LOCK_PATH = path25.join(EXE_AI_DIR, "roster-merge.lock");
|
|
10044
10121
|
LOCK_STALE_MS = 3e4;
|
|
10045
10122
|
_pgPromise = null;
|
|
10046
10123
|
_pgFailed = false;
|
|
10047
|
-
ROSTER_DELETIONS_PATH =
|
|
10124
|
+
ROSTER_DELETIONS_PATH = path25.join(EXE_AI_DIR, "roster-deletions.json");
|
|
10048
10125
|
}
|
|
10049
10126
|
});
|
|
10050
10127
|
|
|
@@ -10248,10 +10325,10 @@ var init_schedules = __esm({
|
|
|
10248
10325
|
|
|
10249
10326
|
// src/bin/exe-boot.ts
|
|
10250
10327
|
init_employees();
|
|
10251
|
-
import
|
|
10328
|
+
import path26 from "path";
|
|
10252
10329
|
import { mkdir as mkdir5, writeFile as writeFile6 } from "fs/promises";
|
|
10253
|
-
import { existsSync as
|
|
10254
|
-
import
|
|
10330
|
+
import { existsSync as existsSync22, readFileSync as readFileSync16, readdirSync as readdirSync9, unlinkSync as unlinkSync12 } from "fs";
|
|
10331
|
+
import os13 from "os";
|
|
10255
10332
|
|
|
10256
10333
|
// src/lib/employee-templates.ts
|
|
10257
10334
|
init_global_procedures();
|
|
@@ -10753,9 +10830,9 @@ init_notifications();
|
|
|
10753
10830
|
// src/lib/active-agent.ts
|
|
10754
10831
|
init_config();
|
|
10755
10832
|
init_session_key();
|
|
10756
|
-
import { readFileSync as readFileSync13, writeFileSync as writeFileSync9, mkdirSync as
|
|
10833
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync9, mkdirSync as mkdirSync9, unlinkSync as unlinkSync7, readdirSync as readdirSync5 } from "fs";
|
|
10757
10834
|
import { execSync as execSync9 } from "child_process";
|
|
10758
|
-
import
|
|
10835
|
+
import path21 from "path";
|
|
10759
10836
|
|
|
10760
10837
|
// src/mcp/agent-context.ts
|
|
10761
10838
|
import { AsyncLocalStorage } from "async_hooks";
|
|
@@ -10763,14 +10840,14 @@ var agentStore = new AsyncLocalStorage();
|
|
|
10763
10840
|
|
|
10764
10841
|
// src/lib/active-agent.ts
|
|
10765
10842
|
init_employees();
|
|
10766
|
-
var CACHE_DIR =
|
|
10843
|
+
var CACHE_DIR = path21.join(EXE_AI_DIR, "session-cache");
|
|
10767
10844
|
var STALE_MS = 24 * 60 * 60 * 1e3;
|
|
10768
10845
|
function getMarkerPath() {
|
|
10769
|
-
return
|
|
10846
|
+
return path21.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
|
|
10770
10847
|
}
|
|
10771
10848
|
function writeActiveAgent(agentId, agentRole) {
|
|
10772
10849
|
try {
|
|
10773
|
-
|
|
10850
|
+
mkdirSync9(CACHE_DIR, { recursive: true });
|
|
10774
10851
|
writeFileSync9(
|
|
10775
10852
|
getMarkerPath(),
|
|
10776
10853
|
JSON.stringify({ agentId, agentRole, startedAt: (/* @__PURE__ */ new Date()).toISOString() })
|
|
@@ -10781,11 +10858,11 @@ function writeActiveAgent(agentId, agentRole) {
|
|
|
10781
10858
|
function cleanupSessionMarkers() {
|
|
10782
10859
|
const key = getSessionKey();
|
|
10783
10860
|
try {
|
|
10784
|
-
unlinkSync7(
|
|
10861
|
+
unlinkSync7(path21.join(CACHE_DIR, `active-agent-${key}.json`));
|
|
10785
10862
|
} catch {
|
|
10786
10863
|
}
|
|
10787
10864
|
try {
|
|
10788
|
-
unlinkSync7(
|
|
10865
|
+
unlinkSync7(path21.join(CACHE_DIR, "active-agent-undefined.json"));
|
|
10789
10866
|
} catch {
|
|
10790
10867
|
}
|
|
10791
10868
|
}
|
|
@@ -10875,7 +10952,7 @@ async function boot(options) {
|
|
|
10875
10952
|
const employeeDirs = entries.filter((e) => e.isDirectory() && !["output", "research"].includes(e.name));
|
|
10876
10953
|
for (const dir of employeeDirs) {
|
|
10877
10954
|
const employee = dir.name;
|
|
10878
|
-
const taskDir =
|
|
10955
|
+
const taskDir = path26.join(exeDir, employee);
|
|
10879
10956
|
let files;
|
|
10880
10957
|
try {
|
|
10881
10958
|
files = readdirSync10(taskDir).filter((f) => f.endsWith(".md"));
|
|
@@ -10886,7 +10963,7 @@ async function boot(options) {
|
|
|
10886
10963
|
const taskFilePath = `exe/${employee}/${file}`;
|
|
10887
10964
|
let content;
|
|
10888
10965
|
try {
|
|
10889
|
-
content = readFs(
|
|
10966
|
+
content = readFs(path26.join(taskDir, file), "utf8");
|
|
10890
10967
|
} catch {
|
|
10891
10968
|
continue;
|
|
10892
10969
|
}
|
|
@@ -10972,12 +11049,12 @@ async function boot(options) {
|
|
|
10972
11049
|
}
|
|
10973
11050
|
try {
|
|
10974
11051
|
for (const reviewDirName of /* @__PURE__ */ new Set(["exe", coordinatorName])) {
|
|
10975
|
-
const reviewDir =
|
|
10976
|
-
if (
|
|
11052
|
+
const reviewDir = path26.join(process.cwd(), "exe", reviewDirName);
|
|
11053
|
+
if (existsSync22(reviewDir)) {
|
|
10977
11054
|
for (const f of readdirSync9(reviewDir)) {
|
|
10978
11055
|
if (f.startsWith("review-") && f.endsWith(".md")) {
|
|
10979
11056
|
try {
|
|
10980
|
-
unlinkSync12(
|
|
11057
|
+
unlinkSync12(path26.join(reviewDir, f));
|
|
10981
11058
|
} catch {
|
|
10982
11059
|
}
|
|
10983
11060
|
}
|
|
@@ -11023,8 +11100,8 @@ async function boot(options) {
|
|
|
11023
11100
|
});
|
|
11024
11101
|
const taskFile = String(r.task_file);
|
|
11025
11102
|
try {
|
|
11026
|
-
const filePath =
|
|
11027
|
-
if (
|
|
11103
|
+
const filePath = path26.join(process.cwd(), taskFile);
|
|
11104
|
+
if (existsSync22(filePath)) {
|
|
11028
11105
|
let content = readFileSync16(filePath, "utf8");
|
|
11029
11106
|
content = content.replace(/\*\*Status:\*\* needs_review/, "**Status:** done");
|
|
11030
11107
|
const { writeFileSync: writeFileSync13 } = await import("fs");
|
|
@@ -11522,19 +11599,19 @@ async function boot(options) {
|
|
|
11522
11599
|
})()
|
|
11523
11600
|
]);
|
|
11524
11601
|
try {
|
|
11525
|
-
const configPath =
|
|
11526
|
-
process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ??
|
|
11602
|
+
const configPath = path26.join(
|
|
11603
|
+
process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path26.join(os13.homedir(), ".exe-os"),
|
|
11527
11604
|
"config.json"
|
|
11528
11605
|
);
|
|
11529
|
-
if (
|
|
11606
|
+
if (existsSync22(configPath)) {
|
|
11530
11607
|
const raw = JSON.parse(readFileSync16(configPath, "utf8"));
|
|
11531
11608
|
briefData.cloudConnected = !!(raw.cloud || raw.turso);
|
|
11532
11609
|
}
|
|
11533
11610
|
} catch {
|
|
11534
11611
|
}
|
|
11535
11612
|
try {
|
|
11536
|
-
const backfillFlagPath =
|
|
11537
|
-
const isBackfillNeeded = () =>
|
|
11613
|
+
const backfillFlagPath = path26.join(EXE_AI_DIR, "session-cache", "needs-backfill");
|
|
11614
|
+
const isBackfillNeeded = () => existsSync22(backfillFlagPath);
|
|
11538
11615
|
const coverageResult = await client.execute({
|
|
11539
11616
|
sql: `SELECT COUNT(*) as total,
|
|
11540
11617
|
SUM(CASE WHEN vector IS NOT NULL THEN 1 ELSE 0 END) as with_vectors
|
|
@@ -11556,8 +11633,8 @@ async function boot(options) {
|
|
|
11556
11633
|
let daemonRunning = false;
|
|
11557
11634
|
let daemonUptime;
|
|
11558
11635
|
let daemonRequestsServed;
|
|
11559
|
-
const socketPath =
|
|
11560
|
-
if (
|
|
11636
|
+
const socketPath = path26.join(EXE_AI_DIR, "exed.sock");
|
|
11637
|
+
if (existsSync22(socketPath)) {
|
|
11561
11638
|
try {
|
|
11562
11639
|
const net2 = await import("net");
|
|
11563
11640
|
const health = await new Promise((resolve) => {
|
|
@@ -11599,8 +11676,8 @@ async function boot(options) {
|
|
|
11599
11676
|
}
|
|
11600
11677
|
}
|
|
11601
11678
|
if (!daemonRunning) {
|
|
11602
|
-
const pidPath =
|
|
11603
|
-
if (
|
|
11679
|
+
const pidPath = path26.join(EXE_AI_DIR, "exed.pid");
|
|
11680
|
+
if (existsSync22(pidPath)) {
|
|
11604
11681
|
try {
|
|
11605
11682
|
const pid = parseInt(readFileSync16(pidPath, "utf8").trim(), 10);
|
|
11606
11683
|
if (pid > 0) {
|
|
@@ -11613,8 +11690,8 @@ async function boot(options) {
|
|
|
11613
11690
|
}
|
|
11614
11691
|
if (nullCount === 0) {
|
|
11615
11692
|
try {
|
|
11616
|
-
const flagPath =
|
|
11617
|
-
if (
|
|
11693
|
+
const flagPath = path26.join(EXE_AI_DIR, "session-cache", "needs-backfill");
|
|
11694
|
+
if (existsSync22(flagPath)) {
|
|
11618
11695
|
const { unlinkSync: unlinkSync13 } = await import("fs");
|
|
11619
11696
|
unlinkSync13(flagPath);
|
|
11620
11697
|
}
|
|
@@ -11640,10 +11717,10 @@ async function boot(options) {
|
|
|
11640
11717
|
const { spawn: spawn2 } = await import("child_process");
|
|
11641
11718
|
const { fileURLToPath: fileURLToPath4 } = await import("url");
|
|
11642
11719
|
const thisFile = fileURLToPath4(import.meta.url);
|
|
11643
|
-
const backfillPath =
|
|
11644
|
-
if (
|
|
11720
|
+
const backfillPath = path26.resolve(path26.dirname(thisFile), "backfill-vectors.js");
|
|
11721
|
+
if (existsSync22(backfillPath)) {
|
|
11645
11722
|
const { openSync: openSync3, closeSync: closeSync3 } = await import("fs");
|
|
11646
|
-
const workerLogPath =
|
|
11723
|
+
const workerLogPath = path26.join(EXE_AI_DIR, "workers.log");
|
|
11647
11724
|
let stderrFd = "ignore";
|
|
11648
11725
|
try {
|
|
11649
11726
|
stderrFd = openSync3(workerLogPath, "a");
|
|
@@ -11673,8 +11750,8 @@ async function boot(options) {
|
|
|
11673
11750
|
const criticalBinaries = ["backfill-vectors.js", "scan-tasks.js"];
|
|
11674
11751
|
const missing = [];
|
|
11675
11752
|
for (const bin of criticalBinaries) {
|
|
11676
|
-
const binPath =
|
|
11677
|
-
if (!
|
|
11753
|
+
const binPath = path26.resolve(path26.dirname(thisFile), bin);
|
|
11754
|
+
if (!existsSync22(binPath)) {
|
|
11678
11755
|
missing.push(`dist/bin/${bin}`);
|
|
11679
11756
|
}
|
|
11680
11757
|
}
|
|
@@ -11703,10 +11780,10 @@ async function boot(options) {
|
|
|
11703
11780
|
console.log(brief);
|
|
11704
11781
|
return;
|
|
11705
11782
|
}
|
|
11706
|
-
const sessionDir =
|
|
11783
|
+
const sessionDir = path26.join(EXE_AI_DIR, "sessions", coordinatorName);
|
|
11707
11784
|
await mkdir5(sessionDir, { recursive: true });
|
|
11708
|
-
const coordinatorIdentityPath =
|
|
11709
|
-
const coordinatorPrompt =
|
|
11785
|
+
const coordinatorIdentityPath = path26.join(EXE_AI_DIR, "identity", `${coordinatorName}.md`);
|
|
11786
|
+
const coordinatorPrompt = existsSync22(coordinatorIdentityPath) ? readFileSync16(coordinatorIdentityPath, "utf-8") : coordinatorEmployee.systemPrompt ?? "";
|
|
11710
11787
|
const claudeMdContent = `${getSessionPrompt(coordinatorPrompt)}
|
|
11711
11788
|
|
|
11712
11789
|
---
|
|
@@ -11714,7 +11791,7 @@ async function boot(options) {
|
|
|
11714
11791
|
# Status Brief
|
|
11715
11792
|
|
|
11716
11793
|
${brief}`;
|
|
11717
|
-
await writeFile6(
|
|
11794
|
+
await writeFile6(path26.join(sessionDir, "CLAUDE.md"), claudeMdContent, "utf-8");
|
|
11718
11795
|
const unread = await readUnreadNotifications();
|
|
11719
11796
|
if (unread.length > 0) {
|
|
11720
11797
|
console.log(`\u{1F4EC} ${unread.length} unread notification${unread.length === 1 ? "" : "s"}`);
|
|
@@ -11723,11 +11800,11 @@ ${brief}`;
|
|
|
11723
11800
|
await cleanupOldNotifications();
|
|
11724
11801
|
console.log(brief);
|
|
11725
11802
|
try {
|
|
11726
|
-
const configPath2 =
|
|
11727
|
-
process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ??
|
|
11803
|
+
const configPath2 = path26.join(
|
|
11804
|
+
process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path26.join(os13.homedir(), ".exe-os"),
|
|
11728
11805
|
"config.json"
|
|
11729
11806
|
);
|
|
11730
|
-
if (
|
|
11807
|
+
if (existsSync22(configPath2)) {
|
|
11731
11808
|
const rawCfg = JSON.parse(readFileSync16(configPath2, "utf8"));
|
|
11732
11809
|
const cloudCfg = rawCfg.cloud;
|
|
11733
11810
|
if (cloudCfg?.apiKey) {
|