@askexenow/exe-os 0.8.85 → 0.8.86
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 +57 -19
- package/dist/bin/cli.js +507 -337
- package/dist/bin/exe-agent-config.js +242 -0
- package/dist/bin/exe-agent.js +3 -3
- package/dist/bin/exe-boot.js +344 -346
- package/dist/bin/exe-dispatch.js +375 -250
- package/dist/bin/exe-forget.js +5 -1
- package/dist/bin/exe-gateway.js +260 -135
- package/dist/bin/exe-healthcheck.js +133 -1
- package/dist/bin/exe-heartbeat.js +72 -31
- package/dist/bin/exe-link.js +25 -2
- package/dist/bin/exe-new-employee.js +22 -0
- package/dist/bin/exe-pending-messages.js +55 -17
- package/dist/bin/exe-pending-reviews.js +57 -19
- package/dist/bin/exe-search.js +6 -2
- package/dist/bin/exe-session-cleanup.js +260 -135
- package/dist/bin/exe-start-codex.js +2598 -0
- package/dist/bin/exe-start.sh +15 -3
- package/dist/bin/exe-status.js +57 -19
- package/dist/bin/git-sweep.js +391 -266
- package/dist/bin/install.js +22 -0
- package/dist/bin/scan-tasks.js +394 -269
- package/dist/bin/setup.js +47 -2
- package/dist/gateway/index.js +257 -132
- package/dist/hooks/bug-report-worker.js +242 -117
- package/dist/hooks/commit-complete.js +389 -264
- package/dist/hooks/error-recall.js +6 -2
- package/dist/hooks/ingest-worker.js +314 -193
- package/dist/hooks/post-compact.js +84 -46
- package/dist/hooks/pre-compact.js +272 -147
- package/dist/hooks/pre-tool-use.js +104 -66
- package/dist/hooks/prompt-submit.js +126 -66
- package/dist/hooks/session-end.js +277 -152
- package/dist/hooks/session-start.js +70 -28
- package/dist/hooks/stop.js +90 -52
- package/dist/hooks/subagent-stop.js +84 -46
- package/dist/hooks/summary-worker.js +175 -114
- package/dist/index.js +296 -171
- package/dist/lib/agent-config.js +167 -0
- package/dist/lib/cloud-sync.js +25 -2
- package/dist/lib/exe-daemon.js +338 -213
- package/dist/lib/hybrid-search.js +7 -2
- package/dist/lib/messaging.js +95 -39
- package/dist/lib/runtime-table.js +16 -0
- package/dist/lib/session-wrappers.js +22 -0
- package/dist/lib/tasks.js +242 -117
- package/dist/lib/tmux-routing.js +314 -189
- package/dist/mcp/server.js +573 -274
- package/dist/mcp/tools/create-task.js +260 -135
- package/dist/mcp/tools/list-tasks.js +68 -30
- package/dist/mcp/tools/send-message.js +100 -44
- package/dist/mcp/tools/update-task.js +123 -67
- package/dist/runtime/index.js +276 -151
- package/dist/tui/App.js +479 -354
- package/package.json +1 -1
- package/src/commands/exe/agent-config.md +27 -0
- package/src/commands/exe/cc-doctor.md +10 -0
package/dist/bin/cli.js
CHANGED
|
@@ -4081,10 +4081,18 @@ function buildRosterBlob(paths) {
|
|
|
4081
4081
|
} catch {
|
|
4082
4082
|
}
|
|
4083
4083
|
}
|
|
4084
|
+
let agentConfig;
|
|
4085
|
+
const agentConfigPath = path9.join(EXE_AI_DIR, "agent-config.json");
|
|
4086
|
+
if (existsSync9(agentConfigPath)) {
|
|
4087
|
+
try {
|
|
4088
|
+
agentConfig = JSON.parse(readFileSync7(agentConfigPath, "utf-8"));
|
|
4089
|
+
} catch {
|
|
4090
|
+
}
|
|
4091
|
+
}
|
|
4084
4092
|
const deletedNames = consumeRosterDeletions();
|
|
4085
|
-
const content = JSON.stringify({ roster, identities, config, deletedNames });
|
|
4093
|
+
const content = JSON.stringify({ roster, identities, config, agentConfig, deletedNames });
|
|
4086
4094
|
const hash = crypto3.createHash("sha256").update(content).digest("hex").slice(0, 16);
|
|
4087
|
-
return { roster, identities, config, deletedNames, version: hash };
|
|
4095
|
+
return { roster, identities, config, agentConfig, deletedNames, version: hash };
|
|
4088
4096
|
}
|
|
4089
4097
|
async function cloudPushRoster(config) {
|
|
4090
4098
|
assertSecureEndpoint(config.endpoint);
|
|
@@ -4222,6 +4230,21 @@ async function mergeRosterFromRemote(remote, paths) {
|
|
|
4222
4230
|
} catch {
|
|
4223
4231
|
}
|
|
4224
4232
|
}
|
|
4233
|
+
if (remote.agentConfig && Object.keys(remote.agentConfig).length > 0) {
|
|
4234
|
+
try {
|
|
4235
|
+
const agentConfigPath = path9.join(EXE_AI_DIR, "agent-config.json");
|
|
4236
|
+
let local = {};
|
|
4237
|
+
if (existsSync9(agentConfigPath)) {
|
|
4238
|
+
try {
|
|
4239
|
+
local = JSON.parse(readFileSync7(agentConfigPath, "utf-8"));
|
|
4240
|
+
} catch {
|
|
4241
|
+
}
|
|
4242
|
+
}
|
|
4243
|
+
const merged = { ...remote.agentConfig, ...local };
|
|
4244
|
+
writeFileSync5(agentConfigPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
|
|
4245
|
+
} catch {
|
|
4246
|
+
}
|
|
4247
|
+
}
|
|
4225
4248
|
return { added, identitiesUpdated };
|
|
4226
4249
|
});
|
|
4227
4250
|
}
|
|
@@ -6717,9 +6740,9 @@ Unclassified: ${unclassified}
|
|
|
6717
6740
|
}
|
|
6718
6741
|
async function exportBatches(options) {
|
|
6719
6742
|
const fs8 = await import("fs");
|
|
6720
|
-
const
|
|
6743
|
+
const path39 = await import("path");
|
|
6721
6744
|
const client = getClient();
|
|
6722
|
-
const outDir =
|
|
6745
|
+
const outDir = path39.join(process.cwd(), "exe/output/classifications/input");
|
|
6723
6746
|
fs8.mkdirSync(outDir, { recursive: true });
|
|
6724
6747
|
const countResult = await client.execute({
|
|
6725
6748
|
sql: "SELECT COUNT(*) as cnt FROM memories WHERE intent IS NULL AND outcome IS NULL AND domain IS NULL",
|
|
@@ -6743,7 +6766,7 @@ async function exportBatches(options) {
|
|
|
6743
6766
|
const text = String(row.text || "").replace(/\n/g, " ");
|
|
6744
6767
|
return JSON.stringify({ id: row.id, text });
|
|
6745
6768
|
});
|
|
6746
|
-
const batchFile =
|
|
6769
|
+
const batchFile = path39.join(outDir, `batch-${String(batchNum).padStart(4, "0")}.jsonl`);
|
|
6747
6770
|
fs8.writeFileSync(batchFile, lines.join("\n") + "\n");
|
|
6748
6771
|
exported += batch.rows.length;
|
|
6749
6772
|
offset += options.batchSize;
|
|
@@ -6759,7 +6782,7 @@ async function exportBatches(options) {
|
|
|
6759
6782
|
}
|
|
6760
6783
|
async function importClassifications(importDir) {
|
|
6761
6784
|
const fs8 = await import("fs");
|
|
6762
|
-
const
|
|
6785
|
+
const path39 = await import("path");
|
|
6763
6786
|
const client = getClient();
|
|
6764
6787
|
const files = fs8.readdirSync(importDir).filter((f) => f.endsWith(".jsonl")).sort();
|
|
6765
6788
|
process.stderr.write(`[backfill-metadata] Found ${files.length} JSONL files to import from ${importDir}
|
|
@@ -6767,7 +6790,7 @@ async function importClassifications(importDir) {
|
|
|
6767
6790
|
let imported = 0;
|
|
6768
6791
|
let invalid = 0;
|
|
6769
6792
|
for (const file of files) {
|
|
6770
|
-
const lines = fs8.readFileSync(
|
|
6793
|
+
const lines = fs8.readFileSync(path39.join(importDir, file), "utf-8").split("\n").filter(Boolean);
|
|
6771
6794
|
for (const line of lines) {
|
|
6772
6795
|
try {
|
|
6773
6796
|
const rec = JSON.parse(line);
|
|
@@ -7156,18 +7179,69 @@ var init_provider_table = __esm({
|
|
|
7156
7179
|
}
|
|
7157
7180
|
});
|
|
7158
7181
|
|
|
7159
|
-
// src/lib/
|
|
7160
|
-
|
|
7182
|
+
// src/lib/runtime-table.ts
|
|
7183
|
+
var RUNTIME_TABLE, DEFAULT_RUNTIME;
|
|
7184
|
+
var init_runtime_table = __esm({
|
|
7185
|
+
"src/lib/runtime-table.ts"() {
|
|
7186
|
+
"use strict";
|
|
7187
|
+
RUNTIME_TABLE = {
|
|
7188
|
+
codex: {
|
|
7189
|
+
binary: "codex",
|
|
7190
|
+
launchMode: "exec",
|
|
7191
|
+
autoApproveFlag: "--full-auto",
|
|
7192
|
+
inlineFlag: "--no-alt-screen",
|
|
7193
|
+
apiKeyEnv: "OPENAI_API_KEY",
|
|
7194
|
+
defaultModel: "gpt-5.4"
|
|
7195
|
+
}
|
|
7196
|
+
};
|
|
7197
|
+
DEFAULT_RUNTIME = "claude";
|
|
7198
|
+
}
|
|
7199
|
+
});
|
|
7200
|
+
|
|
7201
|
+
// src/lib/agent-config.ts
|
|
7202
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync7, existsSync as existsSync12, mkdirSync as mkdirSync8 } from "fs";
|
|
7161
7203
|
import path13 from "path";
|
|
7204
|
+
function loadAgentConfig() {
|
|
7205
|
+
if (!existsSync12(AGENT_CONFIG_PATH)) return {};
|
|
7206
|
+
try {
|
|
7207
|
+
return JSON.parse(readFileSync9(AGENT_CONFIG_PATH, "utf-8"));
|
|
7208
|
+
} catch {
|
|
7209
|
+
return {};
|
|
7210
|
+
}
|
|
7211
|
+
}
|
|
7212
|
+
function getAgentRuntime(agentId) {
|
|
7213
|
+
const config = loadAgentConfig();
|
|
7214
|
+
const entry = config[agentId];
|
|
7215
|
+
if (entry) return entry;
|
|
7216
|
+
return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
|
|
7217
|
+
}
|
|
7218
|
+
var AGENT_CONFIG_PATH, DEFAULT_MODELS;
|
|
7219
|
+
var init_agent_config = __esm({
|
|
7220
|
+
"src/lib/agent-config.ts"() {
|
|
7221
|
+
"use strict";
|
|
7222
|
+
init_config();
|
|
7223
|
+
init_runtime_table();
|
|
7224
|
+
AGENT_CONFIG_PATH = path13.join(EXE_AI_DIR, "agent-config.json");
|
|
7225
|
+
DEFAULT_MODELS = {
|
|
7226
|
+
claude: "claude-opus-4",
|
|
7227
|
+
codex: RUNTIME_TABLE.codex?.defaultModel ?? "gpt-5.4",
|
|
7228
|
+
opencode: "minimax-m2.7"
|
|
7229
|
+
};
|
|
7230
|
+
}
|
|
7231
|
+
});
|
|
7232
|
+
|
|
7233
|
+
// src/lib/intercom-queue.ts
|
|
7234
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync8, renameSync as renameSync3, existsSync as existsSync13, mkdirSync as mkdirSync9 } from "fs";
|
|
7235
|
+
import path14 from "path";
|
|
7162
7236
|
import os7 from "os";
|
|
7163
7237
|
function ensureDir() {
|
|
7164
|
-
const dir =
|
|
7165
|
-
if (!
|
|
7238
|
+
const dir = path14.dirname(QUEUE_PATH);
|
|
7239
|
+
if (!existsSync13(dir)) mkdirSync9(dir, { recursive: true });
|
|
7166
7240
|
}
|
|
7167
7241
|
function readQueue() {
|
|
7168
7242
|
try {
|
|
7169
|
-
if (!
|
|
7170
|
-
return JSON.parse(
|
|
7243
|
+
if (!existsSync13(QUEUE_PATH)) return [];
|
|
7244
|
+
return JSON.parse(readFileSync10(QUEUE_PATH, "utf8"));
|
|
7171
7245
|
} catch {
|
|
7172
7246
|
return [];
|
|
7173
7247
|
}
|
|
@@ -7175,7 +7249,7 @@ function readQueue() {
|
|
|
7175
7249
|
function writeQueue(queue) {
|
|
7176
7250
|
ensureDir();
|
|
7177
7251
|
const tmp = `${QUEUE_PATH}.tmp`;
|
|
7178
|
-
|
|
7252
|
+
writeFileSync8(tmp, JSON.stringify(queue, null, 2));
|
|
7179
7253
|
renameSync3(tmp, QUEUE_PATH);
|
|
7180
7254
|
}
|
|
7181
7255
|
function queueIntercom(targetSession, reason) {
|
|
@@ -7199,19 +7273,19 @@ var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
|
|
|
7199
7273
|
var init_intercom_queue = __esm({
|
|
7200
7274
|
"src/lib/intercom-queue.ts"() {
|
|
7201
7275
|
"use strict";
|
|
7202
|
-
QUEUE_PATH =
|
|
7276
|
+
QUEUE_PATH = path14.join(os7.homedir(), ".exe-os", "intercom-queue.json");
|
|
7203
7277
|
TTL_MS = 60 * 60 * 1e3;
|
|
7204
|
-
INTERCOM_LOG =
|
|
7278
|
+
INTERCOM_LOG = path14.join(os7.homedir(), ".exe-os", "intercom.log");
|
|
7205
7279
|
}
|
|
7206
7280
|
});
|
|
7207
7281
|
|
|
7208
7282
|
// src/lib/plan-limits.ts
|
|
7209
|
-
import { readFileSync as
|
|
7210
|
-
import
|
|
7283
|
+
import { readFileSync as readFileSync11, existsSync as existsSync14 } from "fs";
|
|
7284
|
+
import path15 from "path";
|
|
7211
7285
|
function getLicenseSync() {
|
|
7212
7286
|
try {
|
|
7213
|
-
if (!
|
|
7214
|
-
const raw = JSON.parse(
|
|
7287
|
+
if (!existsSync14(CACHE_PATH2)) return freeLicense();
|
|
7288
|
+
const raw = JSON.parse(readFileSync11(CACHE_PATH2, "utf8"));
|
|
7215
7289
|
if (!raw.token || typeof raw.token !== "string") return freeLicense();
|
|
7216
7290
|
const parts = raw.token.split(".");
|
|
7217
7291
|
if (parts.length !== 3) return freeLicense();
|
|
@@ -7249,8 +7323,8 @@ function assertEmployeeLimitSync(rosterPath) {
|
|
|
7249
7323
|
const filePath = rosterPath ?? EMPLOYEES_PATH;
|
|
7250
7324
|
let count = 0;
|
|
7251
7325
|
try {
|
|
7252
|
-
if (
|
|
7253
|
-
const raw =
|
|
7326
|
+
if (existsSync14(filePath)) {
|
|
7327
|
+
const raw = readFileSync11(filePath, "utf8");
|
|
7254
7328
|
const employees = JSON.parse(raw);
|
|
7255
7329
|
count = Array.isArray(employees) ? employees.length : 0;
|
|
7256
7330
|
}
|
|
@@ -7279,19 +7353,19 @@ var init_plan_limits = __esm({
|
|
|
7279
7353
|
this.name = "PlanLimitError";
|
|
7280
7354
|
}
|
|
7281
7355
|
};
|
|
7282
|
-
CACHE_PATH2 =
|
|
7356
|
+
CACHE_PATH2 = path15.join(EXE_AI_DIR, "license-cache.json");
|
|
7283
7357
|
}
|
|
7284
7358
|
});
|
|
7285
7359
|
|
|
7286
7360
|
// src/lib/notifications.ts
|
|
7287
7361
|
import crypto5 from "crypto";
|
|
7288
|
-
import
|
|
7362
|
+
import path16 from "path";
|
|
7289
7363
|
import os8 from "os";
|
|
7290
7364
|
import {
|
|
7291
|
-
readFileSync as
|
|
7365
|
+
readFileSync as readFileSync12,
|
|
7292
7366
|
readdirSync as readdirSync3,
|
|
7293
7367
|
unlinkSync as unlinkSync5,
|
|
7294
|
-
existsSync as
|
|
7368
|
+
existsSync as existsSync15,
|
|
7295
7369
|
rmdirSync
|
|
7296
7370
|
} from "fs";
|
|
7297
7371
|
async function writeNotification(notification) {
|
|
@@ -7416,11 +7490,11 @@ __export(tasks_crud_exports, {
|
|
|
7416
7490
|
writeCheckpoint: () => writeCheckpoint
|
|
7417
7491
|
});
|
|
7418
7492
|
import crypto7 from "crypto";
|
|
7419
|
-
import
|
|
7493
|
+
import path17 from "path";
|
|
7420
7494
|
import os9 from "os";
|
|
7421
7495
|
import { execSync as execSync6 } from "child_process";
|
|
7422
7496
|
import { mkdir as mkdir5, writeFile as writeFile5, appendFile } from "fs/promises";
|
|
7423
|
-
import { existsSync as
|
|
7497
|
+
import { existsSync as existsSync16, readFileSync as readFileSync13 } from "fs";
|
|
7424
7498
|
async function writeCheckpoint(input) {
|
|
7425
7499
|
const client = getClient();
|
|
7426
7500
|
const row = await resolveTask(client, input.taskId);
|
|
@@ -7595,8 +7669,8 @@ ${laneWarning}` : laneWarning;
|
|
|
7595
7669
|
}
|
|
7596
7670
|
if (input.baseDir) {
|
|
7597
7671
|
try {
|
|
7598
|
-
await mkdir5(
|
|
7599
|
-
await mkdir5(
|
|
7672
|
+
await mkdir5(path17.join(input.baseDir, "exe", "output"), { recursive: true });
|
|
7673
|
+
await mkdir5(path17.join(input.baseDir, "exe", "research"), { recursive: true });
|
|
7600
7674
|
await ensureArchitectureDoc(input.baseDir, input.projectName);
|
|
7601
7675
|
await ensureGitignoreExe(input.baseDir);
|
|
7602
7676
|
} catch {
|
|
@@ -7632,10 +7706,10 @@ ${laneWarning}` : laneWarning;
|
|
|
7632
7706
|
});
|
|
7633
7707
|
if (input.baseDir) {
|
|
7634
7708
|
try {
|
|
7635
|
-
const EXE_OS_DIR =
|
|
7636
|
-
const mdPath =
|
|
7637
|
-
const mdDir =
|
|
7638
|
-
if (!
|
|
7709
|
+
const EXE_OS_DIR = path17.join(os9.homedir(), ".exe-os");
|
|
7710
|
+
const mdPath = path17.join(EXE_OS_DIR, taskFile);
|
|
7711
|
+
const mdDir = path17.dirname(mdPath);
|
|
7712
|
+
if (!existsSync16(mdDir)) await mkdir5(mdDir, { recursive: true });
|
|
7639
7713
|
const reviewer = input.reviewer ?? input.assignedBy;
|
|
7640
7714
|
const mdContent = `# ${input.title}
|
|
7641
7715
|
|
|
@@ -7660,7 +7734,11 @@ If you skip this, your reviewer will not know you're done and your work won't be
|
|
|
7660
7734
|
Do NOT let a failed commit or any error prevent you from calling update_task(done).
|
|
7661
7735
|
`;
|
|
7662
7736
|
await writeFile5(mdPath, mdContent, "utf-8");
|
|
7663
|
-
} catch {
|
|
7737
|
+
} catch (err) {
|
|
7738
|
+
process.stderr.write(
|
|
7739
|
+
`[create-task] WARNING: .md file write failed for ${taskFile}: ${err instanceof Error ? err.message : String(err)}
|
|
7740
|
+
`
|
|
7741
|
+
);
|
|
7664
7742
|
}
|
|
7665
7743
|
}
|
|
7666
7744
|
return {
|
|
@@ -7920,9 +7998,9 @@ async function deleteTaskCore(taskId, _baseDir) {
|
|
|
7920
7998
|
return { taskFile, assignedTo, assignedBy, taskSlug };
|
|
7921
7999
|
}
|
|
7922
8000
|
async function ensureArchitectureDoc(baseDir, projectName) {
|
|
7923
|
-
const archPath =
|
|
8001
|
+
const archPath = path17.join(baseDir, "exe", "ARCHITECTURE.md");
|
|
7924
8002
|
try {
|
|
7925
|
-
if (
|
|
8003
|
+
if (existsSync16(archPath)) return;
|
|
7926
8004
|
const template = [
|
|
7927
8005
|
`# ${projectName} \u2014 System Architecture`,
|
|
7928
8006
|
"",
|
|
@@ -7955,10 +8033,10 @@ async function ensureArchitectureDoc(baseDir, projectName) {
|
|
|
7955
8033
|
}
|
|
7956
8034
|
}
|
|
7957
8035
|
async function ensureGitignoreExe(baseDir) {
|
|
7958
|
-
const gitignorePath =
|
|
8036
|
+
const gitignorePath = path17.join(baseDir, ".gitignore");
|
|
7959
8037
|
try {
|
|
7960
|
-
if (
|
|
7961
|
-
const content =
|
|
8038
|
+
if (existsSync16(gitignorePath)) {
|
|
8039
|
+
const content = readFileSync13(gitignorePath, "utf-8");
|
|
7962
8040
|
if (/^\/?exe\/?$/m.test(content)) return;
|
|
7963
8041
|
await appendFile(gitignorePath, "\n# Employee task assignments (private)\n/exe/\n");
|
|
7964
8042
|
} else {
|
|
@@ -7989,8 +8067,8 @@ var init_tasks_crud = __esm({
|
|
|
7989
8067
|
});
|
|
7990
8068
|
|
|
7991
8069
|
// src/lib/tasks-review.ts
|
|
7992
|
-
import
|
|
7993
|
-
import { existsSync as
|
|
8070
|
+
import path18 from "path";
|
|
8071
|
+
import { existsSync as existsSync17, readdirSync as readdirSync4, unlinkSync as unlinkSync6 } from "fs";
|
|
7994
8072
|
async function countPendingReviews(sessionScope) {
|
|
7995
8073
|
const client = getClient();
|
|
7996
8074
|
if (sessionScope) {
|
|
@@ -8171,11 +8249,11 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
|
|
|
8171
8249
|
);
|
|
8172
8250
|
}
|
|
8173
8251
|
try {
|
|
8174
|
-
const cacheDir =
|
|
8175
|
-
if (
|
|
8252
|
+
const cacheDir = path18.join(EXE_AI_DIR, "session-cache");
|
|
8253
|
+
if (existsSync17(cacheDir)) {
|
|
8176
8254
|
for (const f of readdirSync4(cacheDir)) {
|
|
8177
8255
|
if (f.startsWith("review-notified-")) {
|
|
8178
|
-
unlinkSync6(
|
|
8256
|
+
unlinkSync6(path18.join(cacheDir, f));
|
|
8179
8257
|
}
|
|
8180
8258
|
}
|
|
8181
8259
|
}
|
|
@@ -8196,7 +8274,7 @@ var init_tasks_review = __esm({
|
|
|
8196
8274
|
});
|
|
8197
8275
|
|
|
8198
8276
|
// src/lib/tasks-chain.ts
|
|
8199
|
-
import
|
|
8277
|
+
import path19 from "path";
|
|
8200
8278
|
import { readFile as readFile5, writeFile as writeFile6 } from "fs/promises";
|
|
8201
8279
|
async function cascadeUnblock(taskId, baseDir, now) {
|
|
8202
8280
|
const client = getClient();
|
|
@@ -8213,7 +8291,7 @@ async function cascadeUnblock(taskId, baseDir, now) {
|
|
|
8213
8291
|
});
|
|
8214
8292
|
for (const ur of unblockedRows.rows) {
|
|
8215
8293
|
try {
|
|
8216
|
-
const ubFile =
|
|
8294
|
+
const ubFile = path19.join(baseDir, String(ur.task_file));
|
|
8217
8295
|
let ubContent = await readFile5(ubFile, "utf-8");
|
|
8218
8296
|
ubContent = ubContent.replace(/\*\*Status:\*\* blocked/, "**Status:** open");
|
|
8219
8297
|
ubContent = ubContent.replace(/\n\*\*Blocked by:\*\*.*\n/, "\n");
|
|
@@ -8282,7 +8360,7 @@ var init_tasks_chain = __esm({
|
|
|
8282
8360
|
|
|
8283
8361
|
// src/lib/project-name.ts
|
|
8284
8362
|
import { execSync as execSync7 } from "child_process";
|
|
8285
|
-
import
|
|
8363
|
+
import path20 from "path";
|
|
8286
8364
|
function getProjectName(cwd2) {
|
|
8287
8365
|
const dir = cwd2 ?? process.cwd();
|
|
8288
8366
|
if (_cached2 && _cachedCwd === dir) return _cached2;
|
|
@@ -8295,7 +8373,7 @@ function getProjectName(cwd2) {
|
|
|
8295
8373
|
timeout: 2e3,
|
|
8296
8374
|
stdio: ["pipe", "pipe", "pipe"]
|
|
8297
8375
|
}).trim();
|
|
8298
|
-
repoRoot =
|
|
8376
|
+
repoRoot = path20.dirname(gitCommonDir);
|
|
8299
8377
|
} catch {
|
|
8300
8378
|
repoRoot = execSync7("git rev-parse --show-toplevel", {
|
|
8301
8379
|
cwd: dir,
|
|
@@ -8304,11 +8382,11 @@ function getProjectName(cwd2) {
|
|
|
8304
8382
|
stdio: ["pipe", "pipe", "pipe"]
|
|
8305
8383
|
}).trim();
|
|
8306
8384
|
}
|
|
8307
|
-
_cached2 =
|
|
8385
|
+
_cached2 = path20.basename(repoRoot);
|
|
8308
8386
|
_cachedCwd = dir;
|
|
8309
8387
|
return _cached2;
|
|
8310
8388
|
} catch {
|
|
8311
|
-
_cached2 =
|
|
8389
|
+
_cached2 = path20.basename(dir);
|
|
8312
8390
|
_cachedCwd = dir;
|
|
8313
8391
|
return _cached2;
|
|
8314
8392
|
}
|
|
@@ -8781,8 +8859,8 @@ __export(tasks_exports, {
|
|
|
8781
8859
|
updateTaskStatus: () => updateTaskStatus,
|
|
8782
8860
|
writeCheckpoint: () => writeCheckpoint
|
|
8783
8861
|
});
|
|
8784
|
-
import
|
|
8785
|
-
import { writeFileSync as
|
|
8862
|
+
import path21 from "path";
|
|
8863
|
+
import { writeFileSync as writeFileSync9, mkdirSync as mkdirSync10, unlinkSync as unlinkSync7 } from "fs";
|
|
8786
8864
|
async function createTask(input) {
|
|
8787
8865
|
const result = await createTaskCore(input);
|
|
8788
8866
|
if (!input.skipDispatch && result.status !== "blocked" && !process.env.VITEST) {
|
|
@@ -8801,11 +8879,11 @@ async function updateTask(input) {
|
|
|
8801
8879
|
const { row, taskFile, now, taskId } = await updateTaskStatus(input);
|
|
8802
8880
|
try {
|
|
8803
8881
|
const agent = String(row.assigned_to);
|
|
8804
|
-
const cacheDir =
|
|
8805
|
-
const cachePath =
|
|
8882
|
+
const cacheDir = path21.join(EXE_AI_DIR, "session-cache");
|
|
8883
|
+
const cachePath = path21.join(cacheDir, `current-task-${agent}.json`);
|
|
8806
8884
|
if (input.status === "in_progress") {
|
|
8807
|
-
|
|
8808
|
-
|
|
8885
|
+
mkdirSync10(cacheDir, { recursive: true });
|
|
8886
|
+
writeFileSync9(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
|
|
8809
8887
|
} else if (input.status === "done" || input.status === "blocked" || input.status === "cancelled") {
|
|
8810
8888
|
try {
|
|
8811
8889
|
unlinkSync7(cachePath);
|
|
@@ -9272,13 +9350,13 @@ __export(tmux_routing_exports, {
|
|
|
9272
9350
|
verifyPaneAtCapacity: () => verifyPaneAtCapacity
|
|
9273
9351
|
});
|
|
9274
9352
|
import { execFileSync as execFileSync2, execSync as execSync8 } from "child_process";
|
|
9275
|
-
import { readFileSync as
|
|
9276
|
-
import
|
|
9353
|
+
import { readFileSync as readFileSync14, writeFileSync as writeFileSync10, mkdirSync as mkdirSync11, existsSync as existsSync18, appendFileSync as appendFileSync2 } from "fs";
|
|
9354
|
+
import path22 from "path";
|
|
9277
9355
|
import os10 from "os";
|
|
9278
9356
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
9279
9357
|
import { unlinkSync as unlinkSync8 } from "fs";
|
|
9280
9358
|
function spawnLockPath(sessionName) {
|
|
9281
|
-
return
|
|
9359
|
+
return path22.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
|
|
9282
9360
|
}
|
|
9283
9361
|
function isProcessAlive(pid) {
|
|
9284
9362
|
try {
|
|
@@ -9289,13 +9367,13 @@ function isProcessAlive(pid) {
|
|
|
9289
9367
|
}
|
|
9290
9368
|
}
|
|
9291
9369
|
function acquireSpawnLock2(sessionName) {
|
|
9292
|
-
if (!
|
|
9293
|
-
|
|
9370
|
+
if (!existsSync18(SPAWN_LOCK_DIR)) {
|
|
9371
|
+
mkdirSync11(SPAWN_LOCK_DIR, { recursive: true });
|
|
9294
9372
|
}
|
|
9295
9373
|
const lockFile = spawnLockPath(sessionName);
|
|
9296
|
-
if (
|
|
9374
|
+
if (existsSync18(lockFile)) {
|
|
9297
9375
|
try {
|
|
9298
|
-
const lock = JSON.parse(
|
|
9376
|
+
const lock = JSON.parse(readFileSync14(lockFile, "utf8"));
|
|
9299
9377
|
const age = Date.now() - lock.timestamp;
|
|
9300
9378
|
if (isProcessAlive(lock.pid) && age < 6e4) {
|
|
9301
9379
|
return false;
|
|
@@ -9303,7 +9381,7 @@ function acquireSpawnLock2(sessionName) {
|
|
|
9303
9381
|
} catch {
|
|
9304
9382
|
}
|
|
9305
9383
|
}
|
|
9306
|
-
|
|
9384
|
+
writeFileSync10(lockFile, JSON.stringify({ pid: process.pid, timestamp: Date.now() }));
|
|
9307
9385
|
return true;
|
|
9308
9386
|
}
|
|
9309
9387
|
function releaseSpawnLock2(sessionName) {
|
|
@@ -9315,13 +9393,13 @@ function releaseSpawnLock2(sessionName) {
|
|
|
9315
9393
|
function resolveBehaviorsExporterScript() {
|
|
9316
9394
|
try {
|
|
9317
9395
|
const thisFile = fileURLToPath4(import.meta.url);
|
|
9318
|
-
const scriptPath =
|
|
9319
|
-
|
|
9396
|
+
const scriptPath = path22.join(
|
|
9397
|
+
path22.dirname(thisFile),
|
|
9320
9398
|
"..",
|
|
9321
9399
|
"bin",
|
|
9322
9400
|
"exe-export-behaviors.js"
|
|
9323
9401
|
);
|
|
9324
|
-
return
|
|
9402
|
+
return existsSync18(scriptPath) ? scriptPath : null;
|
|
9325
9403
|
} catch {
|
|
9326
9404
|
return null;
|
|
9327
9405
|
}
|
|
@@ -9387,12 +9465,12 @@ function extractRootExe(name) {
|
|
|
9387
9465
|
return parts.length > 0 ? parts[parts.length - 1] : null;
|
|
9388
9466
|
}
|
|
9389
9467
|
function registerParentExe(sessionKey, parentExe, dispatchedBy) {
|
|
9390
|
-
if (!
|
|
9391
|
-
|
|
9468
|
+
if (!existsSync18(SESSION_CACHE)) {
|
|
9469
|
+
mkdirSync11(SESSION_CACHE, { recursive: true });
|
|
9392
9470
|
}
|
|
9393
9471
|
const rootExe = extractRootExe(parentExe) ?? parentExe;
|
|
9394
|
-
const filePath =
|
|
9395
|
-
|
|
9472
|
+
const filePath = path22.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
|
|
9473
|
+
writeFileSync10(filePath, JSON.stringify({
|
|
9396
9474
|
parentExe: rootExe,
|
|
9397
9475
|
dispatchedBy: dispatchedBy || rootExe,
|
|
9398
9476
|
registeredAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -9400,7 +9478,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
|
|
|
9400
9478
|
}
|
|
9401
9479
|
function getParentExe(sessionKey) {
|
|
9402
9480
|
try {
|
|
9403
|
-
const data = JSON.parse(
|
|
9481
|
+
const data = JSON.parse(readFileSync14(path22.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
|
|
9404
9482
|
return data.parentExe || null;
|
|
9405
9483
|
} catch {
|
|
9406
9484
|
return null;
|
|
@@ -9408,8 +9486,8 @@ function getParentExe(sessionKey) {
|
|
|
9408
9486
|
}
|
|
9409
9487
|
function getDispatchedBy(sessionKey) {
|
|
9410
9488
|
try {
|
|
9411
|
-
const data = JSON.parse(
|
|
9412
|
-
|
|
9489
|
+
const data = JSON.parse(readFileSync14(
|
|
9490
|
+
path22.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
|
|
9413
9491
|
"utf8"
|
|
9414
9492
|
));
|
|
9415
9493
|
return data.dispatchedBy ?? data.parentExe ?? null;
|
|
@@ -9470,32 +9548,50 @@ async function verifyPaneAtCapacity(sessionName) {
|
|
|
9470
9548
|
}
|
|
9471
9549
|
function readDebounceState() {
|
|
9472
9550
|
try {
|
|
9473
|
-
if (!
|
|
9474
|
-
|
|
9551
|
+
if (!existsSync18(DEBOUNCE_FILE)) return {};
|
|
9552
|
+
const raw = JSON.parse(readFileSync14(DEBOUNCE_FILE, "utf8"));
|
|
9553
|
+
const state = {};
|
|
9554
|
+
for (const [key, val] of Object.entries(raw)) {
|
|
9555
|
+
if (typeof val === "number") {
|
|
9556
|
+
state[key] = { lastSent: val, pending: 0 };
|
|
9557
|
+
} else if (val && typeof val === "object" && "lastSent" in val) {
|
|
9558
|
+
state[key] = val;
|
|
9559
|
+
}
|
|
9560
|
+
}
|
|
9561
|
+
return state;
|
|
9475
9562
|
} catch {
|
|
9476
9563
|
return {};
|
|
9477
9564
|
}
|
|
9478
9565
|
}
|
|
9479
9566
|
function writeDebounceState(state) {
|
|
9480
9567
|
try {
|
|
9481
|
-
if (!
|
|
9482
|
-
|
|
9568
|
+
if (!existsSync18(SESSION_CACHE)) mkdirSync11(SESSION_CACHE, { recursive: true });
|
|
9569
|
+
writeFileSync10(DEBOUNCE_FILE, JSON.stringify(state));
|
|
9483
9570
|
} catch {
|
|
9484
9571
|
}
|
|
9485
9572
|
}
|
|
9486
9573
|
function isDebounced(targetSession) {
|
|
9487
9574
|
const state = readDebounceState();
|
|
9488
|
-
const
|
|
9489
|
-
|
|
9575
|
+
const entry = state[targetSession];
|
|
9576
|
+
const lastSent = entry?.lastSent ?? 0;
|
|
9577
|
+
if (Date.now() - lastSent < INTERCOM_DEBOUNCE_MS) {
|
|
9578
|
+
if (!state[targetSession]) state[targetSession] = { lastSent, pending: 0 };
|
|
9579
|
+
state[targetSession].pending++;
|
|
9580
|
+
writeDebounceState(state);
|
|
9581
|
+
return true;
|
|
9582
|
+
}
|
|
9583
|
+
return false;
|
|
9490
9584
|
}
|
|
9491
9585
|
function recordDebounce(targetSession) {
|
|
9492
9586
|
const state = readDebounceState();
|
|
9493
|
-
state[targetSession]
|
|
9587
|
+
const batched = state[targetSession]?.pending ?? 0;
|
|
9588
|
+
state[targetSession] = { lastSent: Date.now(), pending: 0 };
|
|
9494
9589
|
const cutoff = Date.now() - DEBOUNCE_CLEANUP_AGE_MS;
|
|
9495
9590
|
for (const key of Object.keys(state)) {
|
|
9496
|
-
if ((state[key] ?? 0) < cutoff) delete state[key];
|
|
9591
|
+
if ((state[key]?.lastSent ?? 0) < cutoff) delete state[key];
|
|
9497
9592
|
}
|
|
9498
9593
|
writeDebounceState(state);
|
|
9594
|
+
return batched;
|
|
9499
9595
|
}
|
|
9500
9596
|
function logIntercom(msg) {
|
|
9501
9597
|
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${msg}
|
|
@@ -9540,7 +9636,7 @@ function sendIntercom(targetSession) {
|
|
|
9540
9636
|
return "skipped_exe";
|
|
9541
9637
|
}
|
|
9542
9638
|
if (isDebounced(targetSession)) {
|
|
9543
|
-
logIntercom(`DEBOUNCE \u2192 ${targetSession} (
|
|
9639
|
+
logIntercom(`DEBOUNCE \u2192 ${targetSession} (nudge batched, task safe in DB)`);
|
|
9544
9640
|
return "debounced";
|
|
9545
9641
|
}
|
|
9546
9642
|
try {
|
|
@@ -9552,14 +9648,14 @@ function sendIntercom(targetSession) {
|
|
|
9552
9648
|
const sessionState = getSessionState(targetSession);
|
|
9553
9649
|
if (sessionState === "no_claude") {
|
|
9554
9650
|
queueIntercom(targetSession, "claude not running in session");
|
|
9555
|
-
recordDebounce(targetSession);
|
|
9556
|
-
logIntercom(`QUEUED \u2192 ${targetSession} (no claude process
|
|
9651
|
+
const batched2 = recordDebounce(targetSession);
|
|
9652
|
+
logIntercom(`QUEUED \u2192 ${targetSession} (no claude process)${batched2 > 0 ? ` [${batched2} batched]` : ""}`);
|
|
9557
9653
|
return "queued";
|
|
9558
9654
|
}
|
|
9559
9655
|
if (sessionState === "thinking" || sessionState === "tool") {
|
|
9560
9656
|
queueIntercom(targetSession, "session busy at send time");
|
|
9561
|
-
recordDebounce(targetSession);
|
|
9562
|
-
logIntercom(`QUEUED \u2192 ${targetSession} (session busy
|
|
9657
|
+
const batched2 = recordDebounce(targetSession);
|
|
9658
|
+
logIntercom(`QUEUED \u2192 ${targetSession} (session busy)${batched2 > 0 ? ` [${batched2} batched]` : ""}`);
|
|
9563
9659
|
return "queued";
|
|
9564
9660
|
}
|
|
9565
9661
|
if (transport.isPaneInCopyMode(targetSession)) {
|
|
@@ -9567,8 +9663,8 @@ function sendIntercom(targetSession) {
|
|
|
9567
9663
|
transport.sendKeys(targetSession, "q");
|
|
9568
9664
|
}
|
|
9569
9665
|
transport.sendKeys(targetSession, "/exe-intercom");
|
|
9570
|
-
recordDebounce(targetSession);
|
|
9571
|
-
logIntercom(`DELIVERED \u2192 ${targetSession} (fire-and-forget)`);
|
|
9666
|
+
const batched = recordDebounce(targetSession);
|
|
9667
|
+
logIntercom(`DELIVERED \u2192 ${targetSession}${batched > 0 ? ` [${batched} nudges batched during debounce]` : ""} (fire-and-forget)`);
|
|
9572
9668
|
return "delivered";
|
|
9573
9669
|
} catch {
|
|
9574
9670
|
logIntercom(`FAIL \u2192 ${targetSession}`);
|
|
@@ -9670,26 +9766,26 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
9670
9766
|
const transport = getTransport();
|
|
9671
9767
|
const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
|
|
9672
9768
|
const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
|
|
9673
|
-
const logDir =
|
|
9674
|
-
const logFile =
|
|
9675
|
-
if (!
|
|
9676
|
-
|
|
9769
|
+
const logDir = path22.join(os10.homedir(), ".exe-os", "session-logs");
|
|
9770
|
+
const logFile = path22.join(logDir, `${instanceLabel}-${Date.now()}.log`);
|
|
9771
|
+
if (!existsSync18(logDir)) {
|
|
9772
|
+
mkdirSync11(logDir, { recursive: true });
|
|
9677
9773
|
}
|
|
9678
9774
|
transport.kill(sessionName);
|
|
9679
9775
|
let cleanupSuffix = "";
|
|
9680
9776
|
try {
|
|
9681
9777
|
const thisFile = fileURLToPath4(import.meta.url);
|
|
9682
|
-
const cleanupScript =
|
|
9683
|
-
if (
|
|
9778
|
+
const cleanupScript = path22.join(path22.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
|
|
9779
|
+
if (existsSync18(cleanupScript)) {
|
|
9684
9780
|
cleanupSuffix = `; ${process.execPath} "${cleanupScript}" "${employeeName}" "${exeSession}"`;
|
|
9685
9781
|
}
|
|
9686
9782
|
} catch {
|
|
9687
9783
|
}
|
|
9688
9784
|
try {
|
|
9689
|
-
const claudeJsonPath =
|
|
9785
|
+
const claudeJsonPath = path22.join(os10.homedir(), ".claude.json");
|
|
9690
9786
|
let claudeJson = {};
|
|
9691
9787
|
try {
|
|
9692
|
-
claudeJson = JSON.parse(
|
|
9788
|
+
claudeJson = JSON.parse(readFileSync14(claudeJsonPath, "utf8"));
|
|
9693
9789
|
} catch {
|
|
9694
9790
|
}
|
|
9695
9791
|
if (!claudeJson.projects) claudeJson.projects = {};
|
|
@@ -9697,17 +9793,17 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
9697
9793
|
const trustDir = opts?.cwd ?? projectDir;
|
|
9698
9794
|
if (!projects[trustDir]) projects[trustDir] = {};
|
|
9699
9795
|
projects[trustDir].hasTrustDialogAccepted = true;
|
|
9700
|
-
|
|
9796
|
+
writeFileSync10(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
|
|
9701
9797
|
} catch {
|
|
9702
9798
|
}
|
|
9703
9799
|
try {
|
|
9704
|
-
const settingsDir =
|
|
9800
|
+
const settingsDir = path22.join(os10.homedir(), ".claude", "projects");
|
|
9705
9801
|
const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
|
|
9706
|
-
const projSettingsDir =
|
|
9707
|
-
const settingsPath =
|
|
9802
|
+
const projSettingsDir = path22.join(settingsDir, normalizedKey);
|
|
9803
|
+
const settingsPath = path22.join(projSettingsDir, "settings.json");
|
|
9708
9804
|
let settings = {};
|
|
9709
9805
|
try {
|
|
9710
|
-
settings = JSON.parse(
|
|
9806
|
+
settings = JSON.parse(readFileSync14(settingsPath, "utf8"));
|
|
9711
9807
|
} catch {
|
|
9712
9808
|
}
|
|
9713
9809
|
const perms = settings.permissions ?? {};
|
|
@@ -9735,20 +9831,23 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
9735
9831
|
if (changed) {
|
|
9736
9832
|
perms.allow = allow;
|
|
9737
9833
|
settings.permissions = perms;
|
|
9738
|
-
|
|
9739
|
-
|
|
9834
|
+
mkdirSync11(projSettingsDir, { recursive: true });
|
|
9835
|
+
writeFileSync10(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
9740
9836
|
}
|
|
9741
9837
|
} catch {
|
|
9742
9838
|
}
|
|
9743
9839
|
const spawnCwd = opts?.cwd ?? projectDir;
|
|
9744
9840
|
const useExeAgent = !!(opts?.model && opts?.provider);
|
|
9745
|
-
const
|
|
9841
|
+
const agentRtConfig = getAgentRuntime(employeeName);
|
|
9842
|
+
const useCodex = !useExeAgent && agentRtConfig.runtime === "codex";
|
|
9843
|
+
const useOpencode = !useExeAgent && !useCodex && agentRtConfig.runtime === "opencode";
|
|
9844
|
+
const ccProvider = useExeAgent || useCodex || useOpencode ? DEFAULT_PROVIDER : detectActiveProvider();
|
|
9746
9845
|
const useBinSymlink = ccProvider !== DEFAULT_PROVIDER;
|
|
9747
9846
|
let identityFlag = "";
|
|
9748
9847
|
let behaviorsFlag = "";
|
|
9749
9848
|
let legacyFallbackWarned = false;
|
|
9750
9849
|
if (!useExeAgent && !useBinSymlink) {
|
|
9751
|
-
const identityPath2 =
|
|
9850
|
+
const identityPath2 = path22.join(
|
|
9752
9851
|
os10.homedir(),
|
|
9753
9852
|
".exe-os",
|
|
9754
9853
|
"identity",
|
|
@@ -9758,13 +9857,13 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
9758
9857
|
const hasAgentFlag = claudeSupportsAgentFlag();
|
|
9759
9858
|
if (hasAgentFlag) {
|
|
9760
9859
|
identityFlag = ` --agent ${employeeName}`;
|
|
9761
|
-
} else if (
|
|
9860
|
+
} else if (existsSync18(identityPath2)) {
|
|
9762
9861
|
identityFlag = ` --append-system-prompt-file ${identityPath2}`;
|
|
9763
9862
|
legacyFallbackWarned = true;
|
|
9764
9863
|
}
|
|
9765
9864
|
const behaviorsFile = exportBehaviorsSync(
|
|
9766
9865
|
employeeName,
|
|
9767
|
-
|
|
9866
|
+
path22.basename(spawnCwd),
|
|
9768
9867
|
sessionName
|
|
9769
9868
|
);
|
|
9770
9869
|
if (behaviorsFile) {
|
|
@@ -9779,16 +9878,16 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
9779
9878
|
}
|
|
9780
9879
|
let sessionContextFlag = "";
|
|
9781
9880
|
try {
|
|
9782
|
-
const ctxDir =
|
|
9783
|
-
|
|
9784
|
-
const ctxFile =
|
|
9881
|
+
const ctxDir = path22.join(os10.homedir(), ".exe-os", "session-cache");
|
|
9882
|
+
mkdirSync11(ctxDir, { recursive: true });
|
|
9883
|
+
const ctxFile = path22.join(ctxDir, `session-context-${sessionName}.md`);
|
|
9785
9884
|
const ctxContent = [
|
|
9786
9885
|
`## Session Context`,
|
|
9787
9886
|
`You are running in tmux session: ${sessionName}.`,
|
|
9788
9887
|
`Your parent coordinator session is ${exeSession}.`,
|
|
9789
9888
|
`Your employees (if any) use the -${exeSession} suffix.`
|
|
9790
9889
|
].join("\n");
|
|
9791
|
-
|
|
9890
|
+
writeFileSync10(ctxFile, ctxContent);
|
|
9792
9891
|
sessionContextFlag = ` --append-system-prompt-file ${ctxFile}`;
|
|
9793
9892
|
} catch {
|
|
9794
9893
|
}
|
|
@@ -9802,9 +9901,48 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
9802
9901
|
}
|
|
9803
9902
|
}
|
|
9804
9903
|
}
|
|
9904
|
+
if (useCodex) {
|
|
9905
|
+
const codexCfg = RUNTIME_TABLE.codex;
|
|
9906
|
+
if (codexCfg?.apiKeyEnv) {
|
|
9907
|
+
const keyVal = process.env[codexCfg.apiKeyEnv];
|
|
9908
|
+
if (keyVal) {
|
|
9909
|
+
envPrefix = `${envPrefix} ${codexCfg.apiKeyEnv}=${keyVal}`;
|
|
9910
|
+
}
|
|
9911
|
+
}
|
|
9912
|
+
envPrefix = `${envPrefix} EXE_AGENT_MODEL=${agentRtConfig.model}`;
|
|
9913
|
+
}
|
|
9914
|
+
if (useOpencode) {
|
|
9915
|
+
const ocCfg = PROVIDER_TABLE.opencode;
|
|
9916
|
+
if (ocCfg?.apiKeyEnv) {
|
|
9917
|
+
const keyVal = process.env[ocCfg.apiKeyEnv];
|
|
9918
|
+
if (keyVal) {
|
|
9919
|
+
envPrefix = `${envPrefix} ${ocCfg.apiKeyEnv}=${keyVal}`;
|
|
9920
|
+
}
|
|
9921
|
+
}
|
|
9922
|
+
envPrefix = `${envPrefix} ANTHROPIC_MODEL=${agentRtConfig.model}`;
|
|
9923
|
+
}
|
|
9924
|
+
if (!useExeAgent && !useCodex && !useOpencode && !useBinSymlink) {
|
|
9925
|
+
const defaultClaudeModel = DEFAULT_MODELS.claude;
|
|
9926
|
+
if (agentRtConfig.runtime === "claude" && agentRtConfig.model !== defaultClaudeModel) {
|
|
9927
|
+
envPrefix = `${envPrefix} ANTHROPIC_MODEL=${agentRtConfig.model}`;
|
|
9928
|
+
}
|
|
9929
|
+
}
|
|
9805
9930
|
let spawnCommand;
|
|
9806
9931
|
if (useExeAgent) {
|
|
9807
9932
|
spawnCommand = `${envPrefix} exe-agent --employee ${employeeName} --model ${opts.model} --provider ${opts.provider}${cleanupSuffix}`;
|
|
9933
|
+
} else if (useCodex) {
|
|
9934
|
+
process.stderr.write(
|
|
9935
|
+
`[tmux-routing] agent-config: ${employeeName} \u2192 codex (${agentRtConfig.model})
|
|
9936
|
+
`
|
|
9937
|
+
);
|
|
9938
|
+
spawnCommand = `${envPrefix} exe-start-codex --agent ${employeeName}${cleanupSuffix}`;
|
|
9939
|
+
} else if (useOpencode) {
|
|
9940
|
+
const binName = `${employeeName}-opencode`;
|
|
9941
|
+
process.stderr.write(
|
|
9942
|
+
`[tmux-routing] agent-config: ${employeeName} \u2192 opencode (${agentRtConfig.model})
|
|
9943
|
+
`
|
|
9944
|
+
);
|
|
9945
|
+
spawnCommand = `${envPrefix} ${binName}${cleanupSuffix}`;
|
|
9808
9946
|
} else if (useBinSymlink) {
|
|
9809
9947
|
const binName = `${employeeName}-${ccProvider}`;
|
|
9810
9948
|
process.stderr.write(
|
|
@@ -9826,11 +9964,13 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
9826
9964
|
transport.pipeLog(sessionName, logFile);
|
|
9827
9965
|
try {
|
|
9828
9966
|
const mySession = getMySession();
|
|
9829
|
-
const dispatchInfo =
|
|
9830
|
-
|
|
9967
|
+
const dispatchInfo = path22.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
|
|
9968
|
+
writeFileSync10(dispatchInfo, JSON.stringify({
|
|
9831
9969
|
dispatchedBy: mySession,
|
|
9832
9970
|
rootExe: exeSession,
|
|
9833
|
-
provider: useBinSymlink ? ccProvider : useExeAgent ? opts.provider : "anthropic",
|
|
9971
|
+
provider: useBinSymlink ? ccProvider : useExeAgent ? opts.provider : useCodex ? "openai" : useOpencode ? "opencode" : "anthropic",
|
|
9972
|
+
runtime: useCodex ? "codex" : useOpencode ? "opencode" : useExeAgent ? "exe-agent" : "claude",
|
|
9973
|
+
model: useCodex ? agentRtConfig.model : useOpencode ? agentRtConfig.model : void 0,
|
|
9834
9974
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
9835
9975
|
}));
|
|
9836
9976
|
} catch {
|
|
@@ -9848,6 +9988,11 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
9848
9988
|
booted = true;
|
|
9849
9989
|
break;
|
|
9850
9990
|
}
|
|
9991
|
+
} else if (useCodex) {
|
|
9992
|
+
if (pane.includes("codex") || pane.includes("Codex") || pane.includes("exe-start-codex")) {
|
|
9993
|
+
booted = true;
|
|
9994
|
+
break;
|
|
9995
|
+
}
|
|
9851
9996
|
} else {
|
|
9852
9997
|
if (pane.includes("Claude Code") || pane.includes("\u276F")) {
|
|
9853
9998
|
booted = true;
|
|
@@ -9859,9 +10004,10 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
9859
10004
|
}
|
|
9860
10005
|
if (!booted) {
|
|
9861
10006
|
releaseSpawnLock2(sessionName);
|
|
9862
|
-
|
|
10007
|
+
const runtimeLabel = useExeAgent ? "exe-agent" : useCodex ? "codex" : "claude";
|
|
10008
|
+
return { sessionName, error: `${runtimeLabel} did not boot within 15s` };
|
|
9863
10009
|
}
|
|
9864
|
-
if (!useExeAgent) {
|
|
10010
|
+
if (!useExeAgent && !useCodex) {
|
|
9865
10011
|
try {
|
|
9866
10012
|
transport.sendKeys(sessionName, `/exe-call ${employeeName}`);
|
|
9867
10013
|
} catch {
|
|
@@ -9888,17 +10034,19 @@ var init_tmux_routing = __esm({
|
|
|
9888
10034
|
init_cc_agent_support();
|
|
9889
10035
|
init_mcp_prefix();
|
|
9890
10036
|
init_provider_table();
|
|
10037
|
+
init_agent_config();
|
|
10038
|
+
init_runtime_table();
|
|
9891
10039
|
init_intercom_queue();
|
|
9892
10040
|
init_plan_limits();
|
|
9893
10041
|
init_employees();
|
|
9894
|
-
SPAWN_LOCK_DIR =
|
|
9895
|
-
SESSION_CACHE =
|
|
10042
|
+
SPAWN_LOCK_DIR = path22.join(os10.homedir(), ".exe-os", "spawn-locks");
|
|
10043
|
+
SESSION_CACHE = path22.join(os10.homedir(), ".exe-os", "session-cache");
|
|
9896
10044
|
BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
|
|
9897
10045
|
VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
|
|
9898
10046
|
VERIFY_PANE_LINES = 200;
|
|
9899
10047
|
INTERCOM_DEBOUNCE_MS = 3e4;
|
|
9900
|
-
INTERCOM_LOG2 =
|
|
9901
|
-
DEBOUNCE_FILE =
|
|
10048
|
+
INTERCOM_LOG2 = path22.join(os10.homedir(), ".exe-os", "intercom.log");
|
|
10049
|
+
DEBOUNCE_FILE = path22.join(SESSION_CACHE, "intercom-debounce.json");
|
|
9902
10050
|
DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
|
|
9903
10051
|
BUSY_PATTERN = /[✻✽✶✳·].*…|Running…/;
|
|
9904
10052
|
}
|
|
@@ -10173,9 +10321,9 @@ __export(active_agent_exports, {
|
|
|
10173
10321
|
resolveActiveAgentFromTmuxSession: () => resolveActiveAgentFromTmuxSession,
|
|
10174
10322
|
writeActiveAgent: () => writeActiveAgent
|
|
10175
10323
|
});
|
|
10176
|
-
import { readFileSync as
|
|
10324
|
+
import { readFileSync as readFileSync15, writeFileSync as writeFileSync11, mkdirSync as mkdirSync12, unlinkSync as unlinkSync9, readdirSync as readdirSync5 } from "fs";
|
|
10177
10325
|
import { execSync as execSync9 } from "child_process";
|
|
10178
|
-
import
|
|
10326
|
+
import path23 from "path";
|
|
10179
10327
|
function isNameWithOptionalInstance(candidate, baseName) {
|
|
10180
10328
|
if (candidate === baseName) return true;
|
|
10181
10329
|
if (!candidate.startsWith(baseName)) return false;
|
|
@@ -10219,12 +10367,12 @@ function resolveActiveAgentFromTmuxSession(sessionName) {
|
|
|
10219
10367
|
return null;
|
|
10220
10368
|
}
|
|
10221
10369
|
function getMarkerPath() {
|
|
10222
|
-
return
|
|
10370
|
+
return path23.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
|
|
10223
10371
|
}
|
|
10224
10372
|
function writeActiveAgent(agentId, agentRole) {
|
|
10225
10373
|
try {
|
|
10226
|
-
|
|
10227
|
-
|
|
10374
|
+
mkdirSync12(CACHE_DIR, { recursive: true });
|
|
10375
|
+
writeFileSync11(
|
|
10228
10376
|
getMarkerPath(),
|
|
10229
10377
|
JSON.stringify({ agentId, agentRole, startedAt: (/* @__PURE__ */ new Date()).toISOString() })
|
|
10230
10378
|
);
|
|
@@ -10240,7 +10388,7 @@ function clearActiveAgent() {
|
|
|
10240
10388
|
function getActiveAgent() {
|
|
10241
10389
|
try {
|
|
10242
10390
|
const markerPath = getMarkerPath();
|
|
10243
|
-
const raw =
|
|
10391
|
+
const raw = readFileSync15(markerPath, "utf8");
|
|
10244
10392
|
const data = JSON.parse(raw);
|
|
10245
10393
|
if (data.agentId) {
|
|
10246
10394
|
if (data.startedAt) {
|
|
@@ -10288,14 +10436,14 @@ function getAllActiveAgents() {
|
|
|
10288
10436
|
const key = file.slice("active-agent-".length, -".json".length);
|
|
10289
10437
|
if (key === "undefined") continue;
|
|
10290
10438
|
try {
|
|
10291
|
-
const raw =
|
|
10439
|
+
const raw = readFileSync15(path23.join(CACHE_DIR, file), "utf8");
|
|
10292
10440
|
const data = JSON.parse(raw);
|
|
10293
10441
|
if (!data.agentId) continue;
|
|
10294
10442
|
if (data.startedAt) {
|
|
10295
10443
|
const age = Date.now() - new Date(data.startedAt).getTime();
|
|
10296
10444
|
if (age > STALE_MS) {
|
|
10297
10445
|
try {
|
|
10298
|
-
unlinkSync9(
|
|
10446
|
+
unlinkSync9(path23.join(CACHE_DIR, file));
|
|
10299
10447
|
} catch {
|
|
10300
10448
|
}
|
|
10301
10449
|
continue;
|
|
@@ -10318,11 +10466,11 @@ function getAllActiveAgents() {
|
|
|
10318
10466
|
function cleanupSessionMarkers() {
|
|
10319
10467
|
const key = getSessionKey();
|
|
10320
10468
|
try {
|
|
10321
|
-
unlinkSync9(
|
|
10469
|
+
unlinkSync9(path23.join(CACHE_DIR, `active-agent-${key}.json`));
|
|
10322
10470
|
} catch {
|
|
10323
10471
|
}
|
|
10324
10472
|
try {
|
|
10325
|
-
unlinkSync9(
|
|
10473
|
+
unlinkSync9(path23.join(CACHE_DIR, "active-agent-undefined.json"));
|
|
10326
10474
|
} catch {
|
|
10327
10475
|
}
|
|
10328
10476
|
}
|
|
@@ -10333,7 +10481,7 @@ var init_active_agent = __esm({
|
|
|
10333
10481
|
init_config();
|
|
10334
10482
|
init_session_key2();
|
|
10335
10483
|
init_employees();
|
|
10336
|
-
CACHE_DIR =
|
|
10484
|
+
CACHE_DIR = path23.join(EXE_AI_DIR, "session-cache");
|
|
10337
10485
|
STALE_MS = 24 * 60 * 60 * 1e3;
|
|
10338
10486
|
}
|
|
10339
10487
|
});
|
|
@@ -10961,14 +11109,14 @@ __export(exe_rename_exports, {
|
|
|
10961
11109
|
main: () => main2,
|
|
10962
11110
|
renameEmployee: () => renameEmployee
|
|
10963
11111
|
});
|
|
10964
|
-
import { readFileSync as
|
|
11112
|
+
import { readFileSync as readFileSync16, writeFileSync as writeFileSync12, renameSync as renameSync4, unlinkSync as unlinkSync10, existsSync as existsSync19 } from "fs";
|
|
10965
11113
|
import { execSync as execSync10 } from "child_process";
|
|
10966
|
-
import
|
|
11114
|
+
import path24 from "path";
|
|
10967
11115
|
import { homedir as homedir4 } from "os";
|
|
10968
11116
|
async function renameEmployee(oldName, newName, opts = {}) {
|
|
10969
|
-
const rosterPath = opts.rosterPath ??
|
|
10970
|
-
const identityDir = opts.identityDir ??
|
|
10971
|
-
const agentsDir = opts.agentsDir ??
|
|
11117
|
+
const rosterPath = opts.rosterPath ?? path24.join(homedir4(), ".exe-os", "exe-employees.json");
|
|
11118
|
+
const identityDir = opts.identityDir ?? path24.join(homedir4(), ".exe-os", "identity");
|
|
11119
|
+
const agentsDir = opts.agentsDir ?? path24.join(homedir4(), ".claude", "agents");
|
|
10972
11120
|
const validation = validateEmployeeName(newName);
|
|
10973
11121
|
if (!validation.valid) {
|
|
10974
11122
|
return { success: false, error: validation.error };
|
|
@@ -10997,40 +11145,40 @@ async function renameEmployee(oldName, newName, opts = {}) {
|
|
|
10997
11145
|
undo: () => {
|
|
10998
11146
|
employee.name = originalName;
|
|
10999
11147
|
employee.systemPrompt = originalPrompt;
|
|
11000
|
-
|
|
11148
|
+
writeFileSync12(rosterPath, JSON.stringify(employees, null, 2) + "\n", "utf-8");
|
|
11001
11149
|
}
|
|
11002
11150
|
});
|
|
11003
|
-
const oldIdentityPath =
|
|
11004
|
-
const newIdentityPath =
|
|
11005
|
-
if (
|
|
11006
|
-
const content =
|
|
11151
|
+
const oldIdentityPath = path24.join(identityDir, `${rosterOldName}.md`);
|
|
11152
|
+
const newIdentityPath = path24.join(identityDir, `${newName}.md`);
|
|
11153
|
+
if (existsSync19(oldIdentityPath)) {
|
|
11154
|
+
const content = readFileSync16(oldIdentityPath, "utf-8");
|
|
11007
11155
|
const updatedContent = content.replace(
|
|
11008
11156
|
/^(agent_id:\s*)\S+/m,
|
|
11009
11157
|
`$1${newName}`
|
|
11010
11158
|
);
|
|
11011
11159
|
renameSync4(oldIdentityPath, newIdentityPath);
|
|
11012
|
-
|
|
11160
|
+
writeFileSync12(newIdentityPath, updatedContent, "utf-8");
|
|
11013
11161
|
rollbackStack.push({
|
|
11014
11162
|
description: "restore identity file",
|
|
11015
11163
|
undo: () => {
|
|
11016
|
-
if (
|
|
11017
|
-
|
|
11164
|
+
if (existsSync19(newIdentityPath)) {
|
|
11165
|
+
writeFileSync12(newIdentityPath, content, "utf-8");
|
|
11018
11166
|
renameSync4(newIdentityPath, oldIdentityPath);
|
|
11019
11167
|
}
|
|
11020
11168
|
}
|
|
11021
11169
|
});
|
|
11022
11170
|
}
|
|
11023
|
-
const oldAgentPath =
|
|
11024
|
-
const newAgentPath =
|
|
11025
|
-
if (
|
|
11026
|
-
const agentContent =
|
|
11171
|
+
const oldAgentPath = path24.join(agentsDir, `${rosterOldName}.md`);
|
|
11172
|
+
const newAgentPath = path24.join(agentsDir, `${newName}.md`);
|
|
11173
|
+
if (existsSync19(oldAgentPath)) {
|
|
11174
|
+
const agentContent = readFileSync16(oldAgentPath, "utf-8");
|
|
11027
11175
|
renameSync4(oldAgentPath, newAgentPath);
|
|
11028
11176
|
rollbackStack.push({
|
|
11029
11177
|
description: "restore agent file",
|
|
11030
11178
|
undo: () => {
|
|
11031
|
-
if (
|
|
11179
|
+
if (existsSync19(newAgentPath)) {
|
|
11032
11180
|
renameSync4(newAgentPath, oldAgentPath);
|
|
11033
|
-
|
|
11181
|
+
writeFileSync12(oldAgentPath, agentContent, "utf-8");
|
|
11034
11182
|
}
|
|
11035
11183
|
}
|
|
11036
11184
|
});
|
|
@@ -11108,10 +11256,10 @@ function removeOldSymlinks(name) {
|
|
|
11108
11256
|
try {
|
|
11109
11257
|
const exeBinPath = findExeBin2();
|
|
11110
11258
|
if (!exeBinPath) return;
|
|
11111
|
-
const binDir =
|
|
11259
|
+
const binDir = path24.dirname(exeBinPath);
|
|
11112
11260
|
for (const suffix of ["", "-opencode"]) {
|
|
11113
|
-
const linkPath =
|
|
11114
|
-
if (
|
|
11261
|
+
const linkPath = path24.join(binDir, `${name}${suffix}`);
|
|
11262
|
+
if (existsSync19(linkPath)) {
|
|
11115
11263
|
try {
|
|
11116
11264
|
unlinkSync10(linkPath);
|
|
11117
11265
|
} catch {
|
|
@@ -11156,16 +11304,16 @@ var init_exe_rename = __esm({
|
|
|
11156
11304
|
});
|
|
11157
11305
|
|
|
11158
11306
|
// src/lib/model-downloader.ts
|
|
11159
|
-
import { createWriteStream, createReadStream as createReadStream2, existsSync as
|
|
11307
|
+
import { createWriteStream, createReadStream as createReadStream2, existsSync as existsSync20, unlinkSync as unlinkSync11, renameSync as renameSync5 } from "fs";
|
|
11160
11308
|
import { mkdir as mkdir6 } from "fs/promises";
|
|
11161
11309
|
import { createHash as createHash2 } from "crypto";
|
|
11162
|
-
import
|
|
11310
|
+
import path25 from "path";
|
|
11163
11311
|
async function downloadModel(opts) {
|
|
11164
11312
|
const { destDir, onProgress, fetchFn = globalThis.fetch } = opts;
|
|
11165
|
-
const destPath =
|
|
11313
|
+
const destPath = path25.join(destDir, LOCAL_FILENAME);
|
|
11166
11314
|
const tmpPath = destPath + ".tmp";
|
|
11167
11315
|
await mkdir6(destDir, { recursive: true });
|
|
11168
|
-
if (
|
|
11316
|
+
if (existsSync20(destPath)) {
|
|
11169
11317
|
const hash = await fileHash(destPath);
|
|
11170
11318
|
if (hash === EXPECTED_SHA256) {
|
|
11171
11319
|
return destPath;
|
|
@@ -11177,7 +11325,7 @@ async function downloadModel(opts) {
|
|
|
11177
11325
|
let downloaded = 0;
|
|
11178
11326
|
for (let attempt = 1; attempt <= MAX_RETRIES3; attempt++) {
|
|
11179
11327
|
try {
|
|
11180
|
-
if (
|
|
11328
|
+
if (existsSync20(tmpPath)) unlinkSync11(tmpPath);
|
|
11181
11329
|
const response = await fetchFn(GGUF_URL, {
|
|
11182
11330
|
redirect: "follow",
|
|
11183
11331
|
signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS)
|
|
@@ -11222,7 +11370,7 @@ async function downloadModel(opts) {
|
|
|
11222
11370
|
process.stderr.write(`
|
|
11223
11371
|
Download attempt ${attempt} failed, retrying...
|
|
11224
11372
|
`);
|
|
11225
|
-
if (
|
|
11373
|
+
if (existsSync20(tmpPath)) unlinkSync11(tmpPath);
|
|
11226
11374
|
}
|
|
11227
11375
|
}
|
|
11228
11376
|
}
|
|
@@ -11285,10 +11433,10 @@ async function disposeEmbedder() {
|
|
|
11285
11433
|
async function embedDirect(text) {
|
|
11286
11434
|
const llamaCpp = await import("node-llama-cpp");
|
|
11287
11435
|
const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
11288
|
-
const { existsSync:
|
|
11289
|
-
const
|
|
11290
|
-
const modelPath =
|
|
11291
|
-
if (!
|
|
11436
|
+
const { existsSync: existsSync26 } = await import("fs");
|
|
11437
|
+
const path39 = await import("path");
|
|
11438
|
+
const modelPath = path39.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
|
|
11439
|
+
if (!existsSync26(modelPath)) {
|
|
11292
11440
|
throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
|
|
11293
11441
|
}
|
|
11294
11442
|
const llama = await llamaCpp.getLlama();
|
|
@@ -11325,17 +11473,17 @@ __export(identity_exports, {
|
|
|
11325
11473
|
listIdentities: () => listIdentities,
|
|
11326
11474
|
updateIdentity: () => updateIdentity
|
|
11327
11475
|
});
|
|
11328
|
-
import { existsSync as
|
|
11476
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync13, readFileSync as readFileSync17, writeFileSync as writeFileSync13 } from "fs";
|
|
11329
11477
|
import { readdirSync as readdirSync6 } from "fs";
|
|
11330
|
-
import
|
|
11478
|
+
import path26 from "path";
|
|
11331
11479
|
import { createHash as createHash3 } from "crypto";
|
|
11332
11480
|
function ensureDir2() {
|
|
11333
|
-
if (!
|
|
11334
|
-
|
|
11481
|
+
if (!existsSync21(IDENTITY_DIR)) {
|
|
11482
|
+
mkdirSync13(IDENTITY_DIR, { recursive: true });
|
|
11335
11483
|
}
|
|
11336
11484
|
}
|
|
11337
11485
|
function identityPath(agentId) {
|
|
11338
|
-
return
|
|
11486
|
+
return path26.join(IDENTITY_DIR, `${agentId}.md`);
|
|
11339
11487
|
}
|
|
11340
11488
|
function parseFrontmatter(raw) {
|
|
11341
11489
|
const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
@@ -11376,8 +11524,8 @@ function contentHash(content) {
|
|
|
11376
11524
|
}
|
|
11377
11525
|
function getIdentity(agentId) {
|
|
11378
11526
|
const filePath = identityPath(agentId);
|
|
11379
|
-
if (!
|
|
11380
|
-
const raw =
|
|
11527
|
+
if (!existsSync21(filePath)) return null;
|
|
11528
|
+
const raw = readFileSync17(filePath, "utf-8");
|
|
11381
11529
|
const { frontmatter, body } = parseFrontmatter(raw);
|
|
11382
11530
|
return {
|
|
11383
11531
|
agentId,
|
|
@@ -11391,7 +11539,7 @@ async function updateIdentity(agentId, content, updatedBy) {
|
|
|
11391
11539
|
ensureDir2();
|
|
11392
11540
|
const filePath = identityPath(agentId);
|
|
11393
11541
|
const hash = contentHash(content);
|
|
11394
|
-
|
|
11542
|
+
writeFileSync13(filePath, content, "utf-8");
|
|
11395
11543
|
try {
|
|
11396
11544
|
const client = getClient();
|
|
11397
11545
|
await client.execute({
|
|
@@ -11447,7 +11595,7 @@ var init_identity = __esm({
|
|
|
11447
11595
|
"use strict";
|
|
11448
11596
|
init_config();
|
|
11449
11597
|
init_database();
|
|
11450
|
-
IDENTITY_DIR =
|
|
11598
|
+
IDENTITY_DIR = path26.join(EXE_AI_DIR, "identity");
|
|
11451
11599
|
}
|
|
11452
11600
|
});
|
|
11453
11601
|
|
|
@@ -11987,36 +12135,36 @@ __export(session_wrappers_exports, {
|
|
|
11987
12135
|
generateSessionWrappers: () => generateSessionWrappers
|
|
11988
12136
|
});
|
|
11989
12137
|
import {
|
|
11990
|
-
existsSync as
|
|
11991
|
-
readFileSync as
|
|
11992
|
-
writeFileSync as
|
|
11993
|
-
mkdirSync as
|
|
12138
|
+
existsSync as existsSync22,
|
|
12139
|
+
readFileSync as readFileSync18,
|
|
12140
|
+
writeFileSync as writeFileSync14,
|
|
12141
|
+
mkdirSync as mkdirSync14,
|
|
11994
12142
|
chmodSync,
|
|
11995
12143
|
readdirSync as readdirSync7,
|
|
11996
12144
|
unlinkSync as unlinkSync12
|
|
11997
12145
|
} from "fs";
|
|
11998
|
-
import
|
|
12146
|
+
import path27 from "path";
|
|
11999
12147
|
import { homedir as homedir5 } from "os";
|
|
12000
12148
|
function generateSessionWrappers(packageRoot, homeDir) {
|
|
12001
12149
|
const home = homeDir ?? homedir5();
|
|
12002
|
-
const binDir =
|
|
12003
|
-
const rosterPath =
|
|
12004
|
-
|
|
12005
|
-
const exeStartDst =
|
|
12150
|
+
const binDir = path27.join(home, ".exe-os", "bin");
|
|
12151
|
+
const rosterPath = path27.join(home, ".exe-os", "exe-employees.json");
|
|
12152
|
+
mkdirSync14(binDir, { recursive: true });
|
|
12153
|
+
const exeStartDst = path27.join(binDir, "exe-start");
|
|
12006
12154
|
const candidates = [
|
|
12007
|
-
|
|
12008
|
-
|
|
12155
|
+
path27.join(packageRoot, "dist", "bin", "exe-start.sh"),
|
|
12156
|
+
path27.join(packageRoot, "src", "bin", "exe-start.sh")
|
|
12009
12157
|
];
|
|
12010
12158
|
for (const src of candidates) {
|
|
12011
|
-
if (
|
|
12012
|
-
|
|
12159
|
+
if (existsSync22(src)) {
|
|
12160
|
+
writeFileSync14(exeStartDst, readFileSync18(src));
|
|
12013
12161
|
chmodSync(exeStartDst, 493);
|
|
12014
12162
|
break;
|
|
12015
12163
|
}
|
|
12016
12164
|
}
|
|
12017
12165
|
let employees = [];
|
|
12018
12166
|
try {
|
|
12019
|
-
employees = JSON.parse(
|
|
12167
|
+
employees = JSON.parse(readFileSync18(rosterPath, "utf8"));
|
|
12020
12168
|
} catch {
|
|
12021
12169
|
return { created: 0, pathConfigured: false };
|
|
12022
12170
|
}
|
|
@@ -12026,9 +12174,9 @@ function generateSessionWrappers(packageRoot, homeDir) {
|
|
|
12026
12174
|
try {
|
|
12027
12175
|
for (const f of readdirSync7(binDir)) {
|
|
12028
12176
|
if (f === "exe-start") continue;
|
|
12029
|
-
const fPath =
|
|
12177
|
+
const fPath = path27.join(binDir, f);
|
|
12030
12178
|
try {
|
|
12031
|
-
const content =
|
|
12179
|
+
const content = readFileSync18(fPath, "utf8");
|
|
12032
12180
|
if (content.includes("exe-start")) {
|
|
12033
12181
|
unlinkSync12(fPath);
|
|
12034
12182
|
}
|
|
@@ -12043,8 +12191,30 @@ exec "${exeStartDst}" "$0" "$@"
|
|
|
12043
12191
|
`;
|
|
12044
12192
|
for (const emp of employees) {
|
|
12045
12193
|
for (let n = 1; n <= MAX_N; n++) {
|
|
12046
|
-
const wrapperPath =
|
|
12047
|
-
|
|
12194
|
+
const wrapperPath = path27.join(binDir, `${emp.name}${n}`);
|
|
12195
|
+
writeFileSync14(wrapperPath, wrapperContent);
|
|
12196
|
+
chmodSync(wrapperPath, 493);
|
|
12197
|
+
created++;
|
|
12198
|
+
}
|
|
12199
|
+
}
|
|
12200
|
+
const codexLauncherCandidates = [
|
|
12201
|
+
path27.join(packageRoot, "dist", "bin", "exe-start-codex.js"),
|
|
12202
|
+
path27.join(packageRoot, "src", "bin", "exe-start-codex.ts")
|
|
12203
|
+
];
|
|
12204
|
+
let codexLauncher = null;
|
|
12205
|
+
for (const c of codexLauncherCandidates) {
|
|
12206
|
+
if (existsSync22(c)) {
|
|
12207
|
+
codexLauncher = c;
|
|
12208
|
+
break;
|
|
12209
|
+
}
|
|
12210
|
+
}
|
|
12211
|
+
if (codexLauncher) {
|
|
12212
|
+
for (const emp of employees) {
|
|
12213
|
+
const wrapperPath = path27.join(binDir, `${emp.name}-codex`);
|
|
12214
|
+
const content = `#!/bin/bash
|
|
12215
|
+
exec node "${codexLauncher}" --agent ${emp.name} "$@"
|
|
12216
|
+
`;
|
|
12217
|
+
writeFileSync14(wrapperPath, content);
|
|
12048
12218
|
chmodSync(wrapperPath, 493);
|
|
12049
12219
|
created++;
|
|
12050
12220
|
}
|
|
@@ -12063,24 +12233,24 @@ export PATH="${binDir}:$PATH"
|
|
|
12063
12233
|
const shell = process.env.SHELL ?? "/bin/bash";
|
|
12064
12234
|
const profilePaths = [];
|
|
12065
12235
|
if (shell.includes("zsh")) {
|
|
12066
|
-
profilePaths.push(
|
|
12236
|
+
profilePaths.push(path27.join(home, ".zshrc"));
|
|
12067
12237
|
} else if (shell.includes("bash")) {
|
|
12068
|
-
profilePaths.push(
|
|
12069
|
-
profilePaths.push(
|
|
12238
|
+
profilePaths.push(path27.join(home, ".bashrc"));
|
|
12239
|
+
profilePaths.push(path27.join(home, ".bash_profile"));
|
|
12070
12240
|
} else {
|
|
12071
|
-
profilePaths.push(
|
|
12241
|
+
profilePaths.push(path27.join(home, ".profile"));
|
|
12072
12242
|
}
|
|
12073
12243
|
for (const profilePath of profilePaths) {
|
|
12074
12244
|
try {
|
|
12075
12245
|
let content = "";
|
|
12076
12246
|
try {
|
|
12077
|
-
content =
|
|
12247
|
+
content = readFileSync18(profilePath, "utf8");
|
|
12078
12248
|
} catch {
|
|
12079
12249
|
}
|
|
12080
12250
|
if (content.includes(".exe-os/bin")) {
|
|
12081
12251
|
return false;
|
|
12082
12252
|
}
|
|
12083
|
-
|
|
12253
|
+
writeFileSync14(profilePath, content + exportLine);
|
|
12084
12254
|
return true;
|
|
12085
12255
|
} catch {
|
|
12086
12256
|
continue;
|
|
@@ -12103,36 +12273,36 @@ __export(setup_wizard_exports, {
|
|
|
12103
12273
|
validateModel: () => validateModel
|
|
12104
12274
|
});
|
|
12105
12275
|
import crypto11 from "crypto";
|
|
12106
|
-
import { existsSync as
|
|
12276
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync15, readFileSync as readFileSync19, writeFileSync as writeFileSync15, unlinkSync as unlinkSync13 } from "fs";
|
|
12107
12277
|
import os11 from "os";
|
|
12108
|
-
import
|
|
12278
|
+
import path28 from "path";
|
|
12109
12279
|
import { createInterface as createInterface3 } from "readline";
|
|
12110
12280
|
function findPackageRoot2() {
|
|
12111
|
-
let dir =
|
|
12112
|
-
const root =
|
|
12281
|
+
let dir = path28.dirname(new URL(import.meta.url).pathname);
|
|
12282
|
+
const root = path28.parse(dir).root;
|
|
12113
12283
|
while (dir !== root) {
|
|
12114
|
-
const pkgPath =
|
|
12115
|
-
if (
|
|
12284
|
+
const pkgPath = path28.join(dir, "package.json");
|
|
12285
|
+
if (existsSync23(pkgPath)) {
|
|
12116
12286
|
try {
|
|
12117
|
-
const pkg = JSON.parse(
|
|
12287
|
+
const pkg = JSON.parse(readFileSync19(pkgPath, "utf-8"));
|
|
12118
12288
|
if (pkg.name === "@askexenow/exe-os" || pkg.name === "exe-os") return dir;
|
|
12119
12289
|
} catch {
|
|
12120
12290
|
}
|
|
12121
12291
|
}
|
|
12122
|
-
dir =
|
|
12292
|
+
dir = path28.dirname(dir);
|
|
12123
12293
|
}
|
|
12124
12294
|
return null;
|
|
12125
12295
|
}
|
|
12126
12296
|
function loadSetupState() {
|
|
12127
12297
|
try {
|
|
12128
|
-
return JSON.parse(
|
|
12298
|
+
return JSON.parse(readFileSync19(SETUP_STATE_PATH, "utf8"));
|
|
12129
12299
|
} catch {
|
|
12130
12300
|
return { completedSteps: [], startedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
12131
12301
|
}
|
|
12132
12302
|
}
|
|
12133
12303
|
function saveSetupState(state) {
|
|
12134
|
-
|
|
12135
|
-
|
|
12304
|
+
mkdirSync15(path28.dirname(SETUP_STATE_PATH), { recursive: true });
|
|
12305
|
+
writeFileSync15(SETUP_STATE_PATH, JSON.stringify(state, null, 2));
|
|
12136
12306
|
}
|
|
12137
12307
|
function clearSetupState() {
|
|
12138
12308
|
try {
|
|
@@ -12230,7 +12400,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
12230
12400
|
if (state.completedSteps.length > 0) {
|
|
12231
12401
|
log(`Resuming setup from step ${Math.max(...state.completedSteps) + 1}...`);
|
|
12232
12402
|
}
|
|
12233
|
-
if (
|
|
12403
|
+
if (existsSync23(LEGACY_LANCE_PATH)) {
|
|
12234
12404
|
log("\u26A0 Found v1.0 LanceDB at ~/.exe-os/local.lance");
|
|
12235
12405
|
log(" v1.1 uses libSQL (SQLite). Your existing memories are not automatically migrated.");
|
|
12236
12406
|
log(" The old directory will not be modified or deleted.");
|
|
@@ -12378,10 +12548,10 @@ async function runSetupWizard(opts = {}) {
|
|
|
12378
12548
|
await saveConfig(config);
|
|
12379
12549
|
log("");
|
|
12380
12550
|
try {
|
|
12381
|
-
const claudeJsonPath =
|
|
12551
|
+
const claudeJsonPath = path28.join(os11.homedir(), ".claude.json");
|
|
12382
12552
|
let claudeJson = {};
|
|
12383
12553
|
try {
|
|
12384
|
-
claudeJson = JSON.parse(
|
|
12554
|
+
claudeJson = JSON.parse(readFileSync19(claudeJsonPath, "utf8"));
|
|
12385
12555
|
} catch {
|
|
12386
12556
|
}
|
|
12387
12557
|
if (!claudeJson.projects) claudeJson.projects = {};
|
|
@@ -12390,7 +12560,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
12390
12560
|
if (!projects[dir]) projects[dir] = {};
|
|
12391
12561
|
projects[dir].hasTrustDialogAccepted = true;
|
|
12392
12562
|
}
|
|
12393
|
-
|
|
12563
|
+
writeFileSync15(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
|
|
12394
12564
|
} catch {
|
|
12395
12565
|
}
|
|
12396
12566
|
state.completedSteps.push(5);
|
|
@@ -12429,7 +12599,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
12429
12599
|
let missingIdentities = [];
|
|
12430
12600
|
for (const emp of roster) {
|
|
12431
12601
|
const idPath = identityPath2(emp.name);
|
|
12432
|
-
if (!
|
|
12602
|
+
if (!existsSync23(idPath)) {
|
|
12433
12603
|
missingIdentities.push(emp.name);
|
|
12434
12604
|
}
|
|
12435
12605
|
}
|
|
@@ -12461,7 +12631,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
12461
12631
|
}
|
|
12462
12632
|
missingIdentities = [];
|
|
12463
12633
|
for (const emp of roster) {
|
|
12464
|
-
if (!
|
|
12634
|
+
if (!existsSync23(identityPath2(emp.name))) {
|
|
12465
12635
|
missingIdentities.push(emp.name);
|
|
12466
12636
|
}
|
|
12467
12637
|
}
|
|
@@ -12518,9 +12688,9 @@ async function runSetupWizard(opts = {}) {
|
|
|
12518
12688
|
const cooIdentityContent = getIdentityTemplate("coo");
|
|
12519
12689
|
if (cooIdentityContent) {
|
|
12520
12690
|
const cooIdPath = identityPath2(cooName);
|
|
12521
|
-
|
|
12691
|
+
mkdirSync15(path28.dirname(cooIdPath), { recursive: true });
|
|
12522
12692
|
const replaced = cooIdentityContent.replace(/agent_id:\s*exe/g, `agent_id: ${cooName}`).replace(/\$\{agent_id\}/g, cooName);
|
|
12523
|
-
|
|
12693
|
+
writeFileSync15(cooIdPath, replaced, "utf-8");
|
|
12524
12694
|
}
|
|
12525
12695
|
registerBinSymlinks2(cooName);
|
|
12526
12696
|
createdEmployees.push({ name: cooName, role: "COO" });
|
|
@@ -12614,9 +12784,9 @@ async function runSetupWizard(opts = {}) {
|
|
|
12614
12784
|
const ctoIdentityContent = getIdentityTemplate("cto");
|
|
12615
12785
|
if (ctoIdentityContent) {
|
|
12616
12786
|
const ctoIdPath = identityPath2(ctoName);
|
|
12617
|
-
|
|
12787
|
+
mkdirSync15(path28.dirname(ctoIdPath), { recursive: true });
|
|
12618
12788
|
const replaced = ctoIdentityContent.replace(/agent_id:\s*\w+/g, `agent_id: ${ctoName}`).replace(/\$\{agent_id\}/g, ctoName);
|
|
12619
|
-
|
|
12789
|
+
writeFileSync15(ctoIdPath, replaced, "utf-8");
|
|
12620
12790
|
}
|
|
12621
12791
|
registerBinSymlinks2(ctoName);
|
|
12622
12792
|
createdEmployees.push({ name: ctoName, role: "CTO" });
|
|
@@ -12637,9 +12807,9 @@ async function runSetupWizard(opts = {}) {
|
|
|
12637
12807
|
const cmoIdentityContent = getIdentityTemplate("cmo");
|
|
12638
12808
|
if (cmoIdentityContent) {
|
|
12639
12809
|
const cmoIdPath = identityPath2(cmoName);
|
|
12640
|
-
|
|
12810
|
+
mkdirSync15(path28.dirname(cmoIdPath), { recursive: true });
|
|
12641
12811
|
const replaced = cmoIdentityContent.replace(/agent_id:\s*\w+/g, `agent_id: ${cmoName}`).replace(/\$\{agent_id\}/g, cmoName);
|
|
12642
|
-
|
|
12812
|
+
writeFileSync15(cmoIdPath, replaced, "utf-8");
|
|
12643
12813
|
}
|
|
12644
12814
|
registerBinSymlinks2(cmoName);
|
|
12645
12815
|
createdEmployees.push({ name: cmoName, role: "CMO" });
|
|
@@ -12661,7 +12831,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
12661
12831
|
log(`Session shortcuts generated (${cooName}1, ${cooName}2, ...)`);
|
|
12662
12832
|
}
|
|
12663
12833
|
if (wrapResult.pathConfigured) {
|
|
12664
|
-
const binDir =
|
|
12834
|
+
const binDir = path28.join(os11.homedir(), ".exe-os", "bin");
|
|
12665
12835
|
process.env.PATH = `${binDir}:${process.env.PATH ?? ""}`;
|
|
12666
12836
|
pathJustConfigured = true;
|
|
12667
12837
|
}
|
|
@@ -12701,7 +12871,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
12701
12871
|
const pkgRoot2 = findPackageRoot2();
|
|
12702
12872
|
if (pkgRoot2) {
|
|
12703
12873
|
try {
|
|
12704
|
-
version = JSON.parse(
|
|
12874
|
+
version = JSON.parse(readFileSync19(path28.join(pkgRoot2, "package.json"), "utf-8")).version;
|
|
12705
12875
|
} catch {
|
|
12706
12876
|
}
|
|
12707
12877
|
}
|
|
@@ -12738,17 +12908,17 @@ var init_setup_wizard = __esm({
|
|
|
12738
12908
|
init_config();
|
|
12739
12909
|
init_keychain();
|
|
12740
12910
|
init_model_downloader();
|
|
12741
|
-
SETUP_STATE_PATH =
|
|
12911
|
+
SETUP_STATE_PATH = path28.join(os11.homedir(), ".exe-os", "setup-state.json");
|
|
12742
12912
|
}
|
|
12743
12913
|
});
|
|
12744
12914
|
|
|
12745
12915
|
// src/lib/update-check.ts
|
|
12746
12916
|
import { execSync as execSync11 } from "child_process";
|
|
12747
|
-
import { readFileSync as
|
|
12748
|
-
import
|
|
12917
|
+
import { readFileSync as readFileSync20 } from "fs";
|
|
12918
|
+
import path29 from "path";
|
|
12749
12919
|
function getLocalVersion(packageRoot) {
|
|
12750
|
-
const pkgPath =
|
|
12751
|
-
const pkg = JSON.parse(
|
|
12920
|
+
const pkgPath = path29.join(packageRoot, "package.json");
|
|
12921
|
+
const pkg = JSON.parse(readFileSync20(pkgPath, "utf-8"));
|
|
12752
12922
|
return pkg.version;
|
|
12753
12923
|
}
|
|
12754
12924
|
function getRemoteVersion() {
|
|
@@ -17271,8 +17441,8 @@ var init_ErrorOverview = __esm({
|
|
|
17271
17441
|
"use strict";
|
|
17272
17442
|
init_Box();
|
|
17273
17443
|
init_Text();
|
|
17274
|
-
cleanupPath = (
|
|
17275
|
-
return
|
|
17444
|
+
cleanupPath = (path39) => {
|
|
17445
|
+
return path39?.replace(`file://${cwd()}/`, "");
|
|
17276
17446
|
};
|
|
17277
17447
|
stackUtils = new StackUtils({
|
|
17278
17448
|
cwd: cwd(),
|
|
@@ -19680,11 +19850,11 @@ function Footer() {
|
|
|
19680
19850
|
} catch {
|
|
19681
19851
|
}
|
|
19682
19852
|
try {
|
|
19683
|
-
const { existsSync:
|
|
19853
|
+
const { existsSync: existsSync26 } = await import("fs");
|
|
19684
19854
|
const { join } = await import("path");
|
|
19685
19855
|
const home = process.env.HOME ?? "";
|
|
19686
19856
|
const pidPath = join(home, ".exe-os", "exed.pid");
|
|
19687
|
-
setDaemon(
|
|
19857
|
+
setDaemon(existsSync26(pidPath) ? "running" : "stopped");
|
|
19688
19858
|
} catch {
|
|
19689
19859
|
setDaemon("unknown");
|
|
19690
19860
|
}
|
|
@@ -21715,10 +21885,10 @@ var init_hooks = __esm({
|
|
|
21715
21885
|
});
|
|
21716
21886
|
|
|
21717
21887
|
// src/runtime/safety-checks.ts
|
|
21718
|
-
import
|
|
21888
|
+
import path30 from "path";
|
|
21719
21889
|
import os12 from "os";
|
|
21720
21890
|
function checkPathSafety(filePath) {
|
|
21721
|
-
const resolved =
|
|
21891
|
+
const resolved = path30.resolve(filePath);
|
|
21722
21892
|
for (const { pattern, reason } of BYPASS_IMMUNE_PATTERNS) {
|
|
21723
21893
|
const matches = typeof pattern === "function" ? pattern(resolved) : pattern.test(resolved);
|
|
21724
21894
|
if (matches) {
|
|
@@ -21728,7 +21898,7 @@ function checkPathSafety(filePath) {
|
|
|
21728
21898
|
return { safe: true, bypassImmune: true };
|
|
21729
21899
|
}
|
|
21730
21900
|
function checkReadPathSafety(filePath) {
|
|
21731
|
-
const resolved =
|
|
21901
|
+
const resolved = path30.resolve(filePath);
|
|
21732
21902
|
const credPatterns = BYPASS_IMMUNE_PATTERNS.filter(
|
|
21733
21903
|
(p) => typeof p.pattern !== "function" && (p.reason.includes("secrets") || p.reason.includes("Private key") || p.reason.includes("Credential"))
|
|
21734
21904
|
);
|
|
@@ -21754,11 +21924,11 @@ var init_safety_checks = __esm({
|
|
|
21754
21924
|
reason: "Git config can set hooks and command execution"
|
|
21755
21925
|
},
|
|
21756
21926
|
{
|
|
21757
|
-
pattern: (p) => p.startsWith(
|
|
21927
|
+
pattern: (p) => p.startsWith(path30.join(HOME, ".claude")),
|
|
21758
21928
|
reason: "Claude configuration files are protected"
|
|
21759
21929
|
},
|
|
21760
21930
|
{
|
|
21761
|
-
pattern: (p) => p.startsWith(
|
|
21931
|
+
pattern: (p) => p.startsWith(path30.join(HOME, ".exe-os")),
|
|
21762
21932
|
reason: "exe-os configuration files are protected"
|
|
21763
21933
|
},
|
|
21764
21934
|
{
|
|
@@ -21775,7 +21945,7 @@ var init_safety_checks = __esm({
|
|
|
21775
21945
|
},
|
|
21776
21946
|
{
|
|
21777
21947
|
pattern: (p) => {
|
|
21778
|
-
const name =
|
|
21948
|
+
const name = path30.basename(p);
|
|
21779
21949
|
return [".bashrc", ".zshrc", ".profile", ".bash_profile", ".zprofile", ".zshenv"].includes(name);
|
|
21780
21950
|
},
|
|
21781
21951
|
reason: "Shell configuration files can execute arbitrary code on login"
|
|
@@ -21802,7 +21972,7 @@ __export(file_read_exports, {
|
|
|
21802
21972
|
FileReadTool: () => FileReadTool
|
|
21803
21973
|
});
|
|
21804
21974
|
import fs3 from "fs/promises";
|
|
21805
|
-
import
|
|
21975
|
+
import path31 from "path";
|
|
21806
21976
|
import { z } from "zod";
|
|
21807
21977
|
function isBinary(buf) {
|
|
21808
21978
|
for (let i = 0; i < buf.length; i++) {
|
|
@@ -21838,7 +22008,7 @@ var init_file_read = __esm({
|
|
|
21838
22008
|
return { behavior: "allow" };
|
|
21839
22009
|
},
|
|
21840
22010
|
async call(input, context) {
|
|
21841
|
-
const filePath =
|
|
22011
|
+
const filePath = path31.isAbsolute(input.file_path) ? input.file_path : path31.resolve(context.cwd, input.file_path);
|
|
21842
22012
|
let stat2;
|
|
21843
22013
|
try {
|
|
21844
22014
|
stat2 = await fs3.stat(filePath);
|
|
@@ -21878,7 +22048,7 @@ __export(glob_exports, {
|
|
|
21878
22048
|
GlobTool: () => GlobTool
|
|
21879
22049
|
});
|
|
21880
22050
|
import fs4 from "fs/promises";
|
|
21881
|
-
import
|
|
22051
|
+
import path32 from "path";
|
|
21882
22052
|
import { z as z2 } from "zod";
|
|
21883
22053
|
async function walkDir(dir, maxDepth = 10) {
|
|
21884
22054
|
const results = [];
|
|
@@ -21894,7 +22064,7 @@ async function walkDir(dir, maxDepth = 10) {
|
|
|
21894
22064
|
if (entry.isDirectory() && (entry.name === "node_modules" || entry.name === ".git")) {
|
|
21895
22065
|
continue;
|
|
21896
22066
|
}
|
|
21897
|
-
const fullPath =
|
|
22067
|
+
const fullPath = path32.join(current, entry.name);
|
|
21898
22068
|
if (entry.isDirectory()) {
|
|
21899
22069
|
await walk(fullPath, depth + 1);
|
|
21900
22070
|
} else {
|
|
@@ -21928,11 +22098,11 @@ var init_glob = __esm({
|
|
|
21928
22098
|
inputSchema: inputSchema2,
|
|
21929
22099
|
isReadOnly: true,
|
|
21930
22100
|
async call(input, context) {
|
|
21931
|
-
const baseDir = input.path ?
|
|
22101
|
+
const baseDir = input.path ? path32.isAbsolute(input.path) ? input.path : path32.resolve(context.cwd, input.path) : context.cwd;
|
|
21932
22102
|
try {
|
|
21933
22103
|
const entries = await walkDir(baseDir);
|
|
21934
22104
|
const matched = entries.filter(
|
|
21935
|
-
(e) => simpleGlobMatch(
|
|
22105
|
+
(e) => simpleGlobMatch(path32.relative(baseDir, e.path), input.pattern)
|
|
21936
22106
|
);
|
|
21937
22107
|
matched.sort((a, b) => b.mtime - a.mtime);
|
|
21938
22108
|
if (matched.length === 0) {
|
|
@@ -21958,7 +22128,7 @@ __export(grep_exports, {
|
|
|
21958
22128
|
});
|
|
21959
22129
|
import { spawn as spawn2 } from "child_process";
|
|
21960
22130
|
import fs5 from "fs/promises";
|
|
21961
|
-
import
|
|
22131
|
+
import path33 from "path";
|
|
21962
22132
|
import { z as z3 } from "zod";
|
|
21963
22133
|
function runRipgrep(input, searchPath, context) {
|
|
21964
22134
|
return new Promise((resolve, reject) => {
|
|
@@ -22012,7 +22182,7 @@ async function nodeGrep(input, searchPath) {
|
|
|
22012
22182
|
}
|
|
22013
22183
|
for (const entry of entries) {
|
|
22014
22184
|
if (entry.name === "node_modules" || entry.name === ".git") continue;
|
|
22015
|
-
const fullPath =
|
|
22185
|
+
const fullPath = path33.join(dir, entry.name);
|
|
22016
22186
|
if (entry.isDirectory()) {
|
|
22017
22187
|
await walk(fullPath);
|
|
22018
22188
|
} else {
|
|
@@ -22058,7 +22228,7 @@ var init_grep = __esm({
|
|
|
22058
22228
|
inputSchema: inputSchema3,
|
|
22059
22229
|
isReadOnly: true,
|
|
22060
22230
|
async call(input, context) {
|
|
22061
|
-
const searchPath = input.path ?
|
|
22231
|
+
const searchPath = input.path ? path33.isAbsolute(input.path) ? input.path : path33.resolve(context.cwd, input.path) : context.cwd;
|
|
22062
22232
|
try {
|
|
22063
22233
|
const result = await runRipgrep(input, searchPath, context);
|
|
22064
22234
|
return result;
|
|
@@ -22083,7 +22253,7 @@ __export(file_write_exports, {
|
|
|
22083
22253
|
FileWriteTool: () => FileWriteTool
|
|
22084
22254
|
});
|
|
22085
22255
|
import fs6 from "fs/promises";
|
|
22086
|
-
import
|
|
22256
|
+
import path34 from "path";
|
|
22087
22257
|
import { z as z4 } from "zod";
|
|
22088
22258
|
var inputSchema4, FileWriteTool;
|
|
22089
22259
|
var init_file_write = __esm({
|
|
@@ -22111,8 +22281,8 @@ var init_file_write = __esm({
|
|
|
22111
22281
|
return { behavior: "allow" };
|
|
22112
22282
|
},
|
|
22113
22283
|
async call(input, context) {
|
|
22114
|
-
const filePath =
|
|
22115
|
-
const dir =
|
|
22284
|
+
const filePath = path34.isAbsolute(input.file_path) ? input.file_path : path34.resolve(context.cwd, input.file_path);
|
|
22285
|
+
const dir = path34.dirname(filePath);
|
|
22116
22286
|
await fs6.mkdir(dir, { recursive: true });
|
|
22117
22287
|
await fs6.writeFile(filePath, input.content, "utf-8");
|
|
22118
22288
|
return {
|
|
@@ -22130,7 +22300,7 @@ __export(file_edit_exports, {
|
|
|
22130
22300
|
FileEditTool: () => FileEditTool
|
|
22131
22301
|
});
|
|
22132
22302
|
import fs7 from "fs/promises";
|
|
22133
|
-
import
|
|
22303
|
+
import path35 from "path";
|
|
22134
22304
|
import { z as z5 } from "zod";
|
|
22135
22305
|
function countOccurrences(haystack, needle) {
|
|
22136
22306
|
let count = 0;
|
|
@@ -22171,7 +22341,7 @@ var init_file_edit = __esm({
|
|
|
22171
22341
|
return { behavior: "allow" };
|
|
22172
22342
|
},
|
|
22173
22343
|
async call(input, context) {
|
|
22174
|
-
const filePath =
|
|
22344
|
+
const filePath = path35.isAbsolute(input.file_path) ? input.file_path : path35.resolve(context.cwd, input.file_path);
|
|
22175
22345
|
let content;
|
|
22176
22346
|
try {
|
|
22177
22347
|
content = await fs7.readFile(filePath, "utf-8");
|
|
@@ -22413,7 +22583,7 @@ var init_bash = __esm({
|
|
|
22413
22583
|
// src/tui/views/CommandCenter.tsx
|
|
22414
22584
|
import { useState as useState6, useEffect as useEffect8, useMemo as useMemo4, useCallback as useCallback4, useRef as useRef4 } from "react";
|
|
22415
22585
|
import TextInput from "ink-text-input";
|
|
22416
|
-
import
|
|
22586
|
+
import path36 from "path";
|
|
22417
22587
|
import { homedir as homedir6 } from "os";
|
|
22418
22588
|
import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
22419
22589
|
function CommandCenterView({
|
|
@@ -22448,15 +22618,15 @@ function CommandCenterView({
|
|
|
22448
22618
|
const { createPermissionsFromPreset: createPermissionsFromPreset2, EMPLOYEE_PERMISSIONS: EMPLOYEE_PERMISSIONS2 } = await Promise.resolve().then(() => (init_permissions(), permissions_exports));
|
|
22449
22619
|
const { getPresetByRole: getPresetByRole2 } = await Promise.resolve().then(() => (init_permission_presets(), permission_presets_exports));
|
|
22450
22620
|
const { createDefaultHooks: createDefaultHooks2 } = await Promise.resolve().then(() => (init_hooks(), hooks_exports));
|
|
22451
|
-
const { readFileSync:
|
|
22621
|
+
const { readFileSync: readFileSync23, existsSync: existsSync26 } = await import("fs");
|
|
22452
22622
|
const { join } = await import("path");
|
|
22453
22623
|
const { homedir: homedir8 } = await import("os");
|
|
22454
22624
|
const configPath = join(homedir8(), ".exe-os", "config.json");
|
|
22455
22625
|
let failoverChain = ["anthropic", "opencode", "gemini", "openai"];
|
|
22456
22626
|
let providerConfigs = {};
|
|
22457
|
-
if (
|
|
22627
|
+
if (existsSync26(configPath)) {
|
|
22458
22628
|
try {
|
|
22459
|
-
const raw = JSON.parse(
|
|
22629
|
+
const raw = JSON.parse(readFileSync23(configPath, "utf8"));
|
|
22460
22630
|
if (Array.isArray(raw.failoverChain)) failoverChain = raw.failoverChain;
|
|
22461
22631
|
if (raw.providers && typeof raw.providers === "object") {
|
|
22462
22632
|
providerConfigs = raw.providers;
|
|
@@ -22517,7 +22687,7 @@ function CommandCenterView({
|
|
|
22517
22687
|
const markerDir = join(homedir8(), ".exe-os", "session-cache");
|
|
22518
22688
|
const agentFiles = (await import("fs")).readdirSync(markerDir).filter((f) => f.startsWith("active-agent-"));
|
|
22519
22689
|
for (const f of agentFiles) {
|
|
22520
|
-
const data = JSON.parse(
|
|
22690
|
+
const data = JSON.parse(readFileSync23(join(markerDir, f), "utf8"));
|
|
22521
22691
|
if (data.agentRole) {
|
|
22522
22692
|
agentRole = data.agentRole;
|
|
22523
22693
|
break;
|
|
@@ -22662,7 +22832,7 @@ function CommandCenterView({
|
|
|
22662
22832
|
const demoEntries = DEMO_PROJECTS.map((p) => ({
|
|
22663
22833
|
projectName: p.projectName,
|
|
22664
22834
|
exeSession: p.exeSession,
|
|
22665
|
-
projectDir:
|
|
22835
|
+
projectDir: path36.join(homedir6(), p.projectName),
|
|
22666
22836
|
employeeCount: p.employees.length,
|
|
22667
22837
|
activeCount: p.employees.filter((e) => e.status === "active").length,
|
|
22668
22838
|
memoryCount: p.employees.length * 4e3,
|
|
@@ -22700,7 +22870,7 @@ function CommandCenterView({
|
|
|
22700
22870
|
const { listSessions: listSessions2 } = await Promise.resolve().then(() => (init_session_registry(), session_registry_exports));
|
|
22701
22871
|
const { listTmuxSessions: listTmuxSessions2, inTmux: inTmux2 } = await Promise.resolve().then(() => (init_tmux_status(), tmux_status_exports));
|
|
22702
22872
|
const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
22703
|
-
const { existsSync:
|
|
22873
|
+
const { existsSync: existsSync26 } = await import("fs");
|
|
22704
22874
|
const { join } = await import("path");
|
|
22705
22875
|
const client = getClient2();
|
|
22706
22876
|
if (!client) {
|
|
@@ -22771,7 +22941,7 @@ function CommandCenterView({
|
|
|
22771
22941
|
}
|
|
22772
22942
|
const memoryCount = memoryCounts.get(name) ?? 0;
|
|
22773
22943
|
const openTaskCount = openTaskCounts.get(name) ?? 0;
|
|
22774
|
-
const hasGit = projectDir ?
|
|
22944
|
+
const hasGit = projectDir ? existsSync26(join(projectDir, ".git")) : false;
|
|
22775
22945
|
const type = hasGit ? "code" : memoryCount > 0 ? "code" : "automation";
|
|
22776
22946
|
projectList.push({
|
|
22777
22947
|
projectName: name,
|
|
@@ -22796,7 +22966,7 @@ function CommandCenterView({
|
|
|
22796
22966
|
setHealth((h) => ({ ...h, memories: Number(totalResult.rows[0]?.cnt ?? 0) }));
|
|
22797
22967
|
try {
|
|
22798
22968
|
const pidPath = join(process.env.HOME ?? "", ".exe-os", "exed.pid");
|
|
22799
|
-
setHealth((h) => ({ ...h, daemon:
|
|
22969
|
+
setHealth((h) => ({ ...h, daemon: existsSync26(pidPath) ? "running" : "stopped" }));
|
|
22800
22970
|
} catch {
|
|
22801
22971
|
}
|
|
22802
22972
|
const activityResult = await client.execute(
|
|
@@ -23665,7 +23835,7 @@ var init_useOrchestrator = __esm({
|
|
|
23665
23835
|
|
|
23666
23836
|
// src/tui/views/Sessions.tsx
|
|
23667
23837
|
import React19, { useState as useState9, useEffect as useEffect11, useCallback as useCallback6 } from "react";
|
|
23668
|
-
import
|
|
23838
|
+
import path37 from "path";
|
|
23669
23839
|
import { homedir as homedir7 } from "os";
|
|
23670
23840
|
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
23671
23841
|
function isCoordinatorEntry(entry) {
|
|
@@ -23703,7 +23873,7 @@ function SessionsView({
|
|
|
23703
23873
|
if (demo) {
|
|
23704
23874
|
setProjects(DEMO_PROJECTS.map((p) => ({
|
|
23705
23875
|
...p,
|
|
23706
|
-
projectDir:
|
|
23876
|
+
projectDir: path37.join(homedir7(), p.projectName),
|
|
23707
23877
|
employees: p.employees.map((e) => ({ ...e, attached: e.status === "active" }))
|
|
23708
23878
|
})));
|
|
23709
23879
|
return;
|
|
@@ -24807,12 +24977,12 @@ async function loadGatewayConfig() {
|
|
|
24807
24977
|
state.running = false;
|
|
24808
24978
|
}
|
|
24809
24979
|
try {
|
|
24810
|
-
const { existsSync:
|
|
24980
|
+
const { existsSync: existsSync26, readFileSync: readFileSync23 } = await import("fs");
|
|
24811
24981
|
const { join } = await import("path");
|
|
24812
24982
|
const home = process.env.HOME ?? "";
|
|
24813
24983
|
const configPath = join(home, ".exe-os", "gateway.json");
|
|
24814
|
-
if (
|
|
24815
|
-
const raw = JSON.parse(
|
|
24984
|
+
if (existsSync26(configPath)) {
|
|
24985
|
+
const raw = JSON.parse(readFileSync23(configPath, "utf8"));
|
|
24816
24986
|
state.port = raw.port ?? 3100;
|
|
24817
24987
|
state.gatewayUrl = raw.gatewayUrl ?? "";
|
|
24818
24988
|
if (raw.adapters) {
|
|
@@ -25435,12 +25605,12 @@ function TeamView({ onBack, onViewSessions }) {
|
|
|
25435
25605
|
setMembers(teamData);
|
|
25436
25606
|
setDbError(null);
|
|
25437
25607
|
try {
|
|
25438
|
-
const { existsSync:
|
|
25608
|
+
const { existsSync: existsSync26, readFileSync: readFileSync23 } = await import("fs");
|
|
25439
25609
|
const { join } = await import("path");
|
|
25440
25610
|
const home = process.env.HOME ?? "";
|
|
25441
25611
|
const gatewayConfig = join(home, ".exe-os", "gateway.json");
|
|
25442
|
-
if (
|
|
25443
|
-
const raw = JSON.parse(
|
|
25612
|
+
if (existsSync26(gatewayConfig)) {
|
|
25613
|
+
const raw = JSON.parse(readFileSync23(gatewayConfig, "utf8"));
|
|
25444
25614
|
if (raw.agents && raw.agents.length > 0) {
|
|
25445
25615
|
setExternals(raw.agents.map((a) => ({
|
|
25446
25616
|
name: a.name,
|
|
@@ -25621,8 +25791,8 @@ __export(wiki_client_exports, {
|
|
|
25621
25791
|
listDocuments: () => listDocuments,
|
|
25622
25792
|
listWorkspaces: () => listWorkspaces
|
|
25623
25793
|
});
|
|
25624
|
-
async function wikiFetch(config,
|
|
25625
|
-
const url = `${config.baseUrl}/api/v1${
|
|
25794
|
+
async function wikiFetch(config, path39, method = "GET", body) {
|
|
25795
|
+
const url = `${config.baseUrl}/api/v1${path39}`;
|
|
25626
25796
|
const headers = {
|
|
25627
25797
|
Authorization: `Bearer ${config.apiKey}`,
|
|
25628
25798
|
"Content-Type": "application/json"
|
|
@@ -25655,7 +25825,7 @@ async function wikiFetch(config, path38, method = "GET", body) {
|
|
|
25655
25825
|
}
|
|
25656
25826
|
}
|
|
25657
25827
|
if (!response.ok) {
|
|
25658
|
-
throw new Error(`Wiki API ${method} ${
|
|
25828
|
+
throw new Error(`Wiki API ${method} ${path39}: ${response.status} ${response.statusText}`);
|
|
25659
25829
|
}
|
|
25660
25830
|
return response.json();
|
|
25661
25831
|
} finally {
|
|
@@ -26265,12 +26435,12 @@ function SettingsView({ onBack }) {
|
|
|
26265
26435
|
}
|
|
26266
26436
|
setProviders(providerList);
|
|
26267
26437
|
try {
|
|
26268
|
-
const { existsSync:
|
|
26438
|
+
const { existsSync: existsSync26 } = await import("fs");
|
|
26269
26439
|
const { join } = await import("path");
|
|
26270
26440
|
const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
26271
26441
|
const cfg = await loadConfig2();
|
|
26272
26442
|
const home = process.env.HOME ?? "";
|
|
26273
|
-
const hasKey =
|
|
26443
|
+
const hasKey = existsSync26(join(home, ".exe-os", "master.key"));
|
|
26274
26444
|
if (cfg.cloud) {
|
|
26275
26445
|
setCloud({
|
|
26276
26446
|
configured: true,
|
|
@@ -26283,22 +26453,22 @@ function SettingsView({ onBack }) {
|
|
|
26283
26453
|
const pidPath = join(home, ".exe-os", "exed.pid");
|
|
26284
26454
|
let daemon = "unknown";
|
|
26285
26455
|
try {
|
|
26286
|
-
daemon =
|
|
26456
|
+
daemon = existsSync26(pidPath) ? "running" : "stopped";
|
|
26287
26457
|
} catch {
|
|
26288
26458
|
}
|
|
26289
26459
|
let version = "unknown";
|
|
26290
26460
|
try {
|
|
26291
|
-
const { readFileSync:
|
|
26461
|
+
const { readFileSync: readFileSync23 } = await import("fs");
|
|
26292
26462
|
const { createRequire } = await import("module");
|
|
26293
26463
|
const require2 = createRequire(import.meta.url);
|
|
26294
26464
|
const pkgPath = require2.resolve("@askexenow/exe-os/package.json");
|
|
26295
|
-
const pkg = JSON.parse(
|
|
26465
|
+
const pkg = JSON.parse(readFileSync23(pkgPath, "utf8"));
|
|
26296
26466
|
version = pkg.version;
|
|
26297
26467
|
} catch {
|
|
26298
26468
|
try {
|
|
26299
|
-
const { readFileSync:
|
|
26469
|
+
const { readFileSync: readFileSync23 } = await import("fs");
|
|
26300
26470
|
const { join: joinPath } = await import("path");
|
|
26301
|
-
const pkg = JSON.parse(
|
|
26471
|
+
const pkg = JSON.parse(readFileSync23(joinPath(process.cwd(), "package.json"), "utf8"));
|
|
26302
26472
|
version = pkg.version;
|
|
26303
26473
|
} catch {
|
|
26304
26474
|
}
|
|
@@ -26907,14 +27077,14 @@ Unhandled rejection: ${reason}
|
|
|
26907
27077
|
});
|
|
26908
27078
|
|
|
26909
27079
|
// src/bin/cli.ts
|
|
26910
|
-
import { existsSync as
|
|
26911
|
-
import
|
|
27080
|
+
import { existsSync as existsSync25, readFileSync as readFileSync22, writeFileSync as writeFileSync16, readdirSync as readdirSync8, rmSync } from "fs";
|
|
27081
|
+
import path38 from "path";
|
|
26912
27082
|
import os13 from "os";
|
|
26913
27083
|
var args = process.argv.slice(2);
|
|
26914
27084
|
if (args.includes("--version") || args.includes("-v")) {
|
|
26915
27085
|
try {
|
|
26916
|
-
const pkgPath =
|
|
26917
|
-
const pkg = JSON.parse(
|
|
27086
|
+
const pkgPath = path38.join(path38.dirname(new URL(import.meta.url).pathname), "..", "..", "package.json");
|
|
27087
|
+
const pkg = JSON.parse(readFileSync22(pkgPath, "utf8"));
|
|
26918
27088
|
console.log(pkg.version);
|
|
26919
27089
|
} catch {
|
|
26920
27090
|
console.log("unknown");
|
|
@@ -27052,11 +27222,11 @@ ID: ${result.id}`);
|
|
|
27052
27222
|
});
|
|
27053
27223
|
await init_App2().then(() => App_exports);
|
|
27054
27224
|
} else {
|
|
27055
|
-
const claudeDir =
|
|
27056
|
-
const settingsPath =
|
|
27057
|
-
const hasClaudeCode =
|
|
27225
|
+
const claudeDir = path38.join(os13.homedir(), ".claude");
|
|
27226
|
+
const settingsPath = path38.join(claudeDir, "settings.json");
|
|
27227
|
+
const hasClaudeCode = existsSync25(settingsPath) && (() => {
|
|
27058
27228
|
try {
|
|
27059
|
-
const raw =
|
|
27229
|
+
const raw = readFileSync22(settingsPath, "utf8");
|
|
27060
27230
|
return raw.includes("exe-os") || raw.includes("exe-mem");
|
|
27061
27231
|
} catch {
|
|
27062
27232
|
return false;
|
|
@@ -27065,9 +27235,9 @@ ID: ${result.id}`);
|
|
|
27065
27235
|
if (hasClaudeCode) {
|
|
27066
27236
|
let cooName = "exe";
|
|
27067
27237
|
try {
|
|
27068
|
-
const rosterPath =
|
|
27069
|
-
if (
|
|
27070
|
-
const roster = JSON.parse(
|
|
27238
|
+
const rosterPath = path38.join(os13.homedir(), ".exe-os", "exe-employees.json");
|
|
27239
|
+
if (existsSync25(rosterPath)) {
|
|
27240
|
+
const roster = JSON.parse(readFileSync22(rosterPath, "utf8"));
|
|
27071
27241
|
const coo = roster.find((e) => e.role === "COO");
|
|
27072
27242
|
if (coo) cooName = coo.name;
|
|
27073
27243
|
}
|
|
@@ -27107,14 +27277,14 @@ async function runClaudeInstall() {
|
|
|
27107
27277
|
}
|
|
27108
27278
|
}
|
|
27109
27279
|
async function runClaudeCheck() {
|
|
27110
|
-
const claudeDir =
|
|
27111
|
-
const settingsPath =
|
|
27112
|
-
const claudeJsonPath =
|
|
27280
|
+
const claudeDir = path38.join(os13.homedir(), ".claude");
|
|
27281
|
+
const settingsPath = path38.join(claudeDir, "settings.json");
|
|
27282
|
+
const claudeJsonPath = path38.join(os13.homedir(), ".claude.json");
|
|
27113
27283
|
let ok = true;
|
|
27114
|
-
if (
|
|
27284
|
+
if (existsSync25(settingsPath)) {
|
|
27115
27285
|
let settings;
|
|
27116
27286
|
try {
|
|
27117
|
-
settings = JSON.parse(
|
|
27287
|
+
settings = JSON.parse(readFileSync22(settingsPath, "utf8"));
|
|
27118
27288
|
} catch {
|
|
27119
27289
|
console.log("\x1B[31m\u2717\x1B[0m settings.json is malformed (invalid JSON)");
|
|
27120
27290
|
ok = false;
|
|
@@ -27140,10 +27310,10 @@ async function runClaudeCheck() {
|
|
|
27140
27310
|
console.log("\x1B[31m\u2717\x1B[0m settings.json not found");
|
|
27141
27311
|
ok = false;
|
|
27142
27312
|
}
|
|
27143
|
-
if (
|
|
27313
|
+
if (existsSync25(claudeJsonPath)) {
|
|
27144
27314
|
let claudeJson;
|
|
27145
27315
|
try {
|
|
27146
|
-
claudeJson = JSON.parse(
|
|
27316
|
+
claudeJson = JSON.parse(readFileSync22(claudeJsonPath, "utf8"));
|
|
27147
27317
|
} catch {
|
|
27148
27318
|
console.log("\x1B[31m\u2717\x1B[0m claude.json is malformed (invalid JSON)");
|
|
27149
27319
|
ok = false;
|
|
@@ -27162,8 +27332,8 @@ async function runClaudeCheck() {
|
|
|
27162
27332
|
console.log("\x1B[31m\u2717\x1B[0m claude.json not found");
|
|
27163
27333
|
ok = false;
|
|
27164
27334
|
}
|
|
27165
|
-
const skillsDir =
|
|
27166
|
-
if (
|
|
27335
|
+
const skillsDir = path38.join(claudeDir, "skills");
|
|
27336
|
+
if (existsSync25(skillsDir)) {
|
|
27167
27337
|
console.log("\x1B[32m\u2713\x1B[0m Slash skills directory exists");
|
|
27168
27338
|
} else {
|
|
27169
27339
|
console.log("\x1B[31m\u2717\x1B[0m Slash skills directory missing");
|
|
@@ -27180,16 +27350,16 @@ async function runClaudeUninstall(flags = []) {
|
|
|
27180
27350
|
const dryRun = flags.includes("--dry-run");
|
|
27181
27351
|
const purge = flags.includes("--purge");
|
|
27182
27352
|
const homeDir = os13.homedir();
|
|
27183
|
-
const claudeDir =
|
|
27184
|
-
const settingsPath =
|
|
27185
|
-
const claudeJsonPath =
|
|
27186
|
-
const exeOsDir =
|
|
27353
|
+
const claudeDir = path38.join(homeDir, ".claude");
|
|
27354
|
+
const settingsPath = path38.join(claudeDir, "settings.json");
|
|
27355
|
+
const claudeJsonPath = path38.join(homeDir, ".claude.json");
|
|
27356
|
+
const exeOsDir = path38.join(homeDir, ".exe-os");
|
|
27187
27357
|
let removed = 0;
|
|
27188
27358
|
const log = (msg) => console.log(dryRun ? `[dry-run] ${msg}` : msg);
|
|
27189
27359
|
let settings = {};
|
|
27190
|
-
if (
|
|
27360
|
+
if (existsSync25(settingsPath)) {
|
|
27191
27361
|
try {
|
|
27192
|
-
settings = JSON.parse(
|
|
27362
|
+
settings = JSON.parse(readFileSync22(settingsPath, "utf8"));
|
|
27193
27363
|
} catch {
|
|
27194
27364
|
console.error("Your ~/.claude/settings.json appears malformed.");
|
|
27195
27365
|
if (purge) {
|
|
@@ -27227,15 +27397,15 @@ async function runClaudeUninstall(flags = []) {
|
|
|
27227
27397
|
permCount = before - settings.permissions.allow.length;
|
|
27228
27398
|
}
|
|
27229
27399
|
if (!dryRun) {
|
|
27230
|
-
|
|
27400
|
+
writeFileSync16(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
27231
27401
|
}
|
|
27232
27402
|
log("\u2713 Removed exe-os hooks from settings.json");
|
|
27233
27403
|
if (permCount > 0) log(`\u2713 Removed ${permCount} MCP permission entries`);
|
|
27234
27404
|
removed++;
|
|
27235
27405
|
}
|
|
27236
27406
|
}
|
|
27237
|
-
if (
|
|
27238
|
-
const raw =
|
|
27407
|
+
if (existsSync25(claudeJsonPath)) {
|
|
27408
|
+
const raw = readFileSync22(claudeJsonPath, "utf8");
|
|
27239
27409
|
if (raw.length > 1e6) {
|
|
27240
27410
|
console.error("claude.json exceeds 1 MB \u2014 skipping parse.");
|
|
27241
27411
|
} else {
|
|
@@ -27256,7 +27426,7 @@ async function runClaudeUninstall(flags = []) {
|
|
|
27256
27426
|
}
|
|
27257
27427
|
if (removedMcp) {
|
|
27258
27428
|
if (!dryRun) {
|
|
27259
|
-
|
|
27429
|
+
writeFileSync16(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
|
|
27260
27430
|
}
|
|
27261
27431
|
log("\u2713 Removed exe-os MCP server from claude.json");
|
|
27262
27432
|
removed++;
|
|
@@ -27264,14 +27434,14 @@ async function runClaudeUninstall(flags = []) {
|
|
|
27264
27434
|
}
|
|
27265
27435
|
}
|
|
27266
27436
|
}
|
|
27267
|
-
const skillsDir =
|
|
27268
|
-
if (
|
|
27437
|
+
const skillsDir = path38.join(claudeDir, "skills");
|
|
27438
|
+
if (existsSync25(skillsDir)) {
|
|
27269
27439
|
let skillCount = 0;
|
|
27270
27440
|
try {
|
|
27271
27441
|
const entries = readdirSync8(skillsDir);
|
|
27272
27442
|
for (const entry of entries) {
|
|
27273
27443
|
if (entry.startsWith("exe")) {
|
|
27274
|
-
const fullPath =
|
|
27444
|
+
const fullPath = path38.join(skillsDir, entry);
|
|
27275
27445
|
if (!dryRun) rmSync(fullPath, { recursive: true, force: true });
|
|
27276
27446
|
skillCount++;
|
|
27277
27447
|
}
|
|
@@ -27283,30 +27453,30 @@ async function runClaudeUninstall(flags = []) {
|
|
|
27283
27453
|
removed++;
|
|
27284
27454
|
}
|
|
27285
27455
|
}
|
|
27286
|
-
const claudeMdPath =
|
|
27287
|
-
if (
|
|
27288
|
-
const content =
|
|
27456
|
+
const claudeMdPath = path38.join(claudeDir, "CLAUDE.md");
|
|
27457
|
+
if (existsSync25(claudeMdPath)) {
|
|
27458
|
+
const content = readFileSync22(claudeMdPath, "utf8");
|
|
27289
27459
|
const startMarker = "<!-- exe-os:orchestration-start -->";
|
|
27290
27460
|
const endMarker = "<!-- exe-os:orchestration-end -->";
|
|
27291
27461
|
const startIdx = content.indexOf(startMarker);
|
|
27292
27462
|
const endIdx = content.indexOf(endMarker);
|
|
27293
27463
|
if (startIdx !== -1 && endIdx !== -1) {
|
|
27294
27464
|
const cleaned = (content.slice(0, startIdx) + content.slice(endIdx + endMarker.length)).replace(/\n{3,}/g, "\n\n").trim() + "\n";
|
|
27295
|
-
if (!dryRun)
|
|
27465
|
+
if (!dryRun) writeFileSync16(claudeMdPath, cleaned);
|
|
27296
27466
|
log("\u2713 Removed orchestration block from CLAUDE.md");
|
|
27297
27467
|
removed++;
|
|
27298
27468
|
}
|
|
27299
27469
|
}
|
|
27300
|
-
const agentsDir =
|
|
27301
|
-
if (
|
|
27470
|
+
const agentsDir = path38.join(claudeDir, "agents");
|
|
27471
|
+
if (existsSync25(agentsDir)) {
|
|
27302
27472
|
let agentCount = 0;
|
|
27303
27473
|
try {
|
|
27304
27474
|
const entries = readdirSync8(agentsDir).filter((f) => f.endsWith(".md"));
|
|
27305
27475
|
let knownNames = /* @__PURE__ */ new Set();
|
|
27306
|
-
const rosterPath =
|
|
27307
|
-
if (
|
|
27476
|
+
const rosterPath = path38.join(exeOsDir, "exe-employees.json");
|
|
27477
|
+
if (existsSync25(rosterPath)) {
|
|
27308
27478
|
try {
|
|
27309
|
-
const roster = JSON.parse(
|
|
27479
|
+
const roster = JSON.parse(readFileSync22(rosterPath, "utf8"));
|
|
27310
27480
|
knownNames = new Set(roster.map((e) => e.name));
|
|
27311
27481
|
} catch {
|
|
27312
27482
|
}
|
|
@@ -27314,7 +27484,7 @@ async function runClaudeUninstall(flags = []) {
|
|
|
27314
27484
|
for (const entry of entries) {
|
|
27315
27485
|
const name = entry.replace(/\.md$/, "");
|
|
27316
27486
|
if (knownNames.has(name)) {
|
|
27317
|
-
if (!dryRun) rmSync(
|
|
27487
|
+
if (!dryRun) rmSync(path38.join(agentsDir, entry), { force: true });
|
|
27318
27488
|
agentCount++;
|
|
27319
27489
|
}
|
|
27320
27490
|
}
|
|
@@ -27325,16 +27495,16 @@ async function runClaudeUninstall(flags = []) {
|
|
|
27325
27495
|
removed++;
|
|
27326
27496
|
}
|
|
27327
27497
|
}
|
|
27328
|
-
const projectsDir =
|
|
27329
|
-
if (
|
|
27498
|
+
const projectsDir = path38.join(claudeDir, "projects");
|
|
27499
|
+
if (existsSync25(projectsDir)) {
|
|
27330
27500
|
let projectCount = 0;
|
|
27331
27501
|
try {
|
|
27332
27502
|
const projects = readdirSync8(projectsDir);
|
|
27333
27503
|
for (const proj of projects) {
|
|
27334
|
-
const projSettings =
|
|
27335
|
-
if (!
|
|
27504
|
+
const projSettings = path38.join(projectsDir, proj, "settings.json");
|
|
27505
|
+
if (!existsSync25(projSettings)) continue;
|
|
27336
27506
|
try {
|
|
27337
|
-
const pSettings = JSON.parse(
|
|
27507
|
+
const pSettings = JSON.parse(readFileSync22(projSettings, "utf8"));
|
|
27338
27508
|
let changed = false;
|
|
27339
27509
|
if (Array.isArray(pSettings.permissions?.allow)) {
|
|
27340
27510
|
const before = pSettings.permissions.allow.length;
|
|
@@ -27344,7 +27514,7 @@ async function runClaudeUninstall(flags = []) {
|
|
|
27344
27514
|
if (pSettings.permissions.allow.length < before) changed = true;
|
|
27345
27515
|
}
|
|
27346
27516
|
if (changed && !dryRun) {
|
|
27347
|
-
|
|
27517
|
+
writeFileSync16(projSettings, JSON.stringify(pSettings, null, 2) + "\n");
|
|
27348
27518
|
}
|
|
27349
27519
|
if (changed) projectCount++;
|
|
27350
27520
|
} catch {
|
|
@@ -27368,17 +27538,17 @@ async function runClaudeUninstall(flags = []) {
|
|
|
27368
27538
|
};
|
|
27369
27539
|
const exeBinPath = findExeBin3();
|
|
27370
27540
|
if (!exeBinPath) throw new Error("exe-os not found in PATH");
|
|
27371
|
-
const binDir =
|
|
27541
|
+
const binDir = path38.dirname(exeBinPath);
|
|
27372
27542
|
let symlinkCount = 0;
|
|
27373
|
-
const rosterPath =
|
|
27374
|
-
if (
|
|
27375
|
-
const roster = JSON.parse(
|
|
27543
|
+
const rosterPath = path38.join(exeOsDir, "exe-employees.json");
|
|
27544
|
+
if (existsSync25(rosterPath)) {
|
|
27545
|
+
const roster = JSON.parse(readFileSync22(rosterPath, "utf8"));
|
|
27376
27546
|
const coordinatorName = roster.find((e) => e.role?.toLowerCase() === "coo")?.name ?? "exe";
|
|
27377
27547
|
for (const emp of roster) {
|
|
27378
27548
|
if (emp.name === coordinatorName) continue;
|
|
27379
27549
|
for (const suffix of ["", "-opencode"]) {
|
|
27380
|
-
const linkPath =
|
|
27381
|
-
if (
|
|
27550
|
+
const linkPath = path38.join(binDir, `${emp.name}${suffix}`);
|
|
27551
|
+
if (existsSync25(linkPath)) {
|
|
27382
27552
|
if (!dryRun) rmSync(linkPath, { force: true });
|
|
27383
27553
|
symlinkCount++;
|
|
27384
27554
|
}
|
|
@@ -27391,7 +27561,7 @@ async function runClaudeUninstall(flags = []) {
|
|
|
27391
27561
|
}
|
|
27392
27562
|
} catch {
|
|
27393
27563
|
}
|
|
27394
|
-
if (purge &&
|
|
27564
|
+
if (purge && existsSync25(exeOsDir)) {
|
|
27395
27565
|
if (!dryRun) {
|
|
27396
27566
|
process.stdout.write("\x1B[33m\u26A0 This will delete all memories, identities, and agent data.\x1B[0m\n");
|
|
27397
27567
|
process.stdout.write(" Removing ~/.exe-os...\n");
|
|
@@ -27416,7 +27586,7 @@ async function checkForUpdateOnBoot() {
|
|
|
27416
27586
|
const config = await loadConfig2();
|
|
27417
27587
|
if (!config.autoUpdate.checkOnBoot) return;
|
|
27418
27588
|
const { checkForUpdate: checkForUpdate2 } = await Promise.resolve().then(() => (init_update(), update_exports));
|
|
27419
|
-
const packageRoot =
|
|
27589
|
+
const packageRoot = path38.resolve(
|
|
27420
27590
|
new URL("../..", import.meta.url).pathname
|
|
27421
27591
|
);
|
|
27422
27592
|
const result = checkForUpdate2(packageRoot);
|
|
@@ -27475,7 +27645,7 @@ async function runActivate(key) {
|
|
|
27475
27645
|
const idTemplate = getIdentityTemplate(identityKey);
|
|
27476
27646
|
if (idTemplate) {
|
|
27477
27647
|
const idPath = identityPath2(name);
|
|
27478
|
-
const dir =
|
|
27648
|
+
const dir = path38.dirname(idPath);
|
|
27479
27649
|
if (!fs8.existsSync(dir)) fs8.mkdirSync(dir, { recursive: true });
|
|
27480
27650
|
fs8.writeFileSync(idPath, idTemplate.replace(/^agent_id: \w+/m, `agent_id: ${name}`), "utf-8");
|
|
27481
27651
|
}
|