@askexenow/exe-os 0.9.21 → 0.9.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/backfill-conversations.js +17 -4
- package/dist/bin/backfill-responses.js +17 -4
- package/dist/bin/backfill-vectors.js +2 -2
- package/dist/bin/cleanup-stale-review-tasks.js +17 -4
- package/dist/bin/cli.js +378 -171
- package/dist/bin/exe-assign.js +17 -4
- package/dist/bin/exe-boot.js +2 -2
- package/dist/bin/exe-dispatch.js +17 -4
- package/dist/bin/exe-doctor.js +2 -2
- package/dist/bin/exe-export-behaviors.js +17 -4
- package/dist/bin/exe-forget.js +17 -4
- package/dist/bin/exe-gateway.js +17 -4
- package/dist/bin/exe-heartbeat.js +17 -4
- package/dist/bin/exe-kill.js +17 -4
- package/dist/bin/exe-launch-agent.js +17 -4
- package/dist/bin/exe-pending-messages.js +17 -4
- package/dist/bin/exe-pending-notifications.js +17 -4
- package/dist/bin/exe-pending-reviews.js +17 -4
- package/dist/bin/exe-review.js +17 -4
- package/dist/bin/exe-search.js +23 -8
- package/dist/bin/exe-session-cleanup.js +17 -4
- package/dist/bin/exe-start-codex.js +209 -32
- package/dist/bin/exe-start-opencode.js +17 -4
- package/dist/bin/exe-status.js +17 -4
- package/dist/bin/exe-team.js +17 -4
- package/dist/bin/git-sweep.js +17 -4
- package/dist/bin/graph-backfill.js +17 -4
- package/dist/bin/graph-export.js +17 -4
- package/dist/bin/install.js +42 -0
- package/dist/bin/intercom-check.js +17 -4
- package/dist/bin/scan-tasks.js +17 -4
- package/dist/bin/shard-migrate.js +17 -4
- package/dist/bin/update.js +187 -42
- package/dist/gateway/index.js +17 -4
- package/dist/hooks/bug-report-worker.js +793 -150
- package/dist/hooks/codex-stop-task-finalizer.js +3020 -2375
- package/dist/hooks/commit-complete.js +156 -6
- package/dist/hooks/error-recall.js +23 -8
- package/dist/hooks/ingest.js +17 -4
- package/dist/hooks/instructions-loaded.js +17 -4
- package/dist/hooks/notification.js +17 -4
- package/dist/hooks/post-compact.js +17 -4
- package/dist/hooks/post-tool-combined.js +23 -8
- package/dist/hooks/pre-compact.js +156 -8
- package/dist/hooks/pre-tool-use.js +21 -12
- package/dist/hooks/prompt-submit.js +23 -8
- package/dist/hooks/session-end.js +156 -8
- package/dist/hooks/session-start.js +23 -8
- package/dist/hooks/stop.js +306 -9
- package/dist/hooks/subagent-stop.js +306 -9
- package/dist/hooks/summary-worker.js +2 -2
- package/dist/index.js +17 -4
- package/dist/lib/exe-daemon.js +17 -4
- package/dist/lib/hybrid-search.js +23 -8
- package/dist/lib/schedules.js +2 -2
- package/dist/lib/store.js +17 -4
- package/dist/mcp/server.js +36 -10
- package/dist/runtime/index.js +17 -4
- package/dist/tui/App.js +17 -4
- package/package.json +1 -1
package/dist/bin/cli.js
CHANGED
|
@@ -5985,9 +5985,9 @@ async function cloudPullGraphRAG(config) {
|
|
|
5985
5985
|
pulled += stmts.length;
|
|
5986
5986
|
}
|
|
5987
5987
|
if (blob.relationship_memories.length > 0) {
|
|
5988
|
-
const stmts = blob.relationship_memories.map((
|
|
5988
|
+
const stmts = blob.relationship_memories.map((rm2) => ({
|
|
5989
5989
|
sql: `INSERT OR IGNORE INTO relationship_memories (relationship_id, memory_id) VALUES (?, ?)`,
|
|
5990
|
-
args: [sqlSafe(
|
|
5990
|
+
args: [sqlSafe(rm2.relationship_id), sqlSafe(rm2.memory_id)]
|
|
5991
5991
|
}));
|
|
5992
5992
|
await client.batch(stmts, "write");
|
|
5993
5993
|
pulled += stmts.length;
|
|
@@ -6504,8 +6504,8 @@ function getShardClient(projectName) {
|
|
|
6504
6504
|
throw new Error("Shard manager not initialized. Call initShardManager() first.");
|
|
6505
6505
|
}
|
|
6506
6506
|
const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
6507
|
-
if (!safeName) {
|
|
6508
|
-
throw new Error(`Invalid project name for shard: "${projectName}"`);
|
|
6507
|
+
if (!safeName || safeName === "unknown") {
|
|
6508
|
+
throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
|
|
6509
6509
|
}
|
|
6510
6510
|
const cached = _shards.get(safeName);
|
|
6511
6511
|
if (cached) {
|
|
@@ -7374,19 +7374,32 @@ async function flushBatch() {
|
|
|
7374
7374
|
const { isShardingEnabled: isShardingEnabled2, getReadyShardClient: getReadyShardClient2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
7375
7375
|
if (isShardingEnabled2()) {
|
|
7376
7376
|
const byProject = /* @__PURE__ */ new Map();
|
|
7377
|
+
let skippedUnknown = 0;
|
|
7377
7378
|
for (const row of batch) {
|
|
7378
|
-
const proj = row.project_name
|
|
7379
|
+
const proj = row.project_name?.trim();
|
|
7380
|
+
if (!proj) {
|
|
7381
|
+
skippedUnknown++;
|
|
7382
|
+
continue;
|
|
7383
|
+
}
|
|
7379
7384
|
if (!byProject.has(proj)) byProject.set(proj, []);
|
|
7380
7385
|
byProject.get(proj).push(row);
|
|
7381
7386
|
}
|
|
7387
|
+
if (skippedUnknown > 0) {
|
|
7388
|
+
process.stderr.write(
|
|
7389
|
+
`[store] Shard skip: ${skippedUnknown} record(s) with empty project_name (kept in main DB only)
|
|
7390
|
+
`
|
|
7391
|
+
);
|
|
7392
|
+
}
|
|
7382
7393
|
for (const [project, rows] of byProject) {
|
|
7383
7394
|
try {
|
|
7384
7395
|
const shardClient = await getReadyShardClient2(project);
|
|
7385
7396
|
const shardStmts = rows.map(buildStmt);
|
|
7386
7397
|
await shardClient.batch(shardStmts, "write");
|
|
7387
7398
|
} catch (err) {
|
|
7399
|
+
const fullError = err instanceof Error ? `${err.name}: ${err.message}${err.stack ? `
|
|
7400
|
+
${err.stack.split("\n").slice(1, 3).join("\n")}` : ""}` : String(err);
|
|
7388
7401
|
process.stderr.write(
|
|
7389
|
-
`[store] Shard write failed for ${project}
|
|
7402
|
+
`[store] Shard write failed for ${project} (${rows.length} records): ${fullError}
|
|
7390
7403
|
`
|
|
7391
7404
|
);
|
|
7392
7405
|
}
|
|
@@ -8414,9 +8427,9 @@ Unclassified: ${unclassified}
|
|
|
8414
8427
|
}
|
|
8415
8428
|
async function exportBatches(options) {
|
|
8416
8429
|
const fs8 = await import("fs");
|
|
8417
|
-
const
|
|
8430
|
+
const path47 = await import("path");
|
|
8418
8431
|
const client = getClient();
|
|
8419
|
-
const outDir =
|
|
8432
|
+
const outDir = path47.join(process.cwd(), "exe/output/classifications/input");
|
|
8420
8433
|
fs8.mkdirSync(outDir, { recursive: true });
|
|
8421
8434
|
const countResult = await client.execute({
|
|
8422
8435
|
sql: "SELECT COUNT(*) as cnt FROM memories WHERE intent IS NULL AND outcome IS NULL AND domain IS NULL",
|
|
@@ -8440,7 +8453,7 @@ async function exportBatches(options) {
|
|
|
8440
8453
|
const text = String(row.text || "").replace(/\n/g, " ");
|
|
8441
8454
|
return JSON.stringify({ id: row.id, text });
|
|
8442
8455
|
});
|
|
8443
|
-
const batchFile =
|
|
8456
|
+
const batchFile = path47.join(outDir, `batch-${String(batchNum).padStart(4, "0")}.jsonl`);
|
|
8444
8457
|
fs8.writeFileSync(batchFile, lines.join("\n") + "\n");
|
|
8445
8458
|
exported += batch.rows.length;
|
|
8446
8459
|
offset += options.batchSize;
|
|
@@ -8456,7 +8469,7 @@ async function exportBatches(options) {
|
|
|
8456
8469
|
}
|
|
8457
8470
|
async function importClassifications(importDir) {
|
|
8458
8471
|
const fs8 = await import("fs");
|
|
8459
|
-
const
|
|
8472
|
+
const path47 = await import("path");
|
|
8460
8473
|
const client = getClient();
|
|
8461
8474
|
const files = fs8.readdirSync(importDir).filter((f) => f.endsWith(".jsonl")).sort();
|
|
8462
8475
|
process.stderr.write(`[backfill-metadata] Found ${files.length} JSONL files to import from ${importDir}
|
|
@@ -8464,7 +8477,7 @@ async function importClassifications(importDir) {
|
|
|
8464
8477
|
let imported = 0;
|
|
8465
8478
|
let invalid = 0;
|
|
8466
8479
|
for (const file of files) {
|
|
8467
|
-
const lines = fs8.readFileSync(
|
|
8480
|
+
const lines = fs8.readFileSync(path47.join(importDir, file), "utf-8").split("\n").filter(Boolean);
|
|
8468
8481
|
for (const line of lines) {
|
|
8469
8482
|
try {
|
|
8470
8483
|
const rec = JSON.parse(line);
|
|
@@ -11097,10 +11110,10 @@ async function disposeEmbedder() {
|
|
|
11097
11110
|
async function embedDirect(text) {
|
|
11098
11111
|
const llamaCpp = await import("node-llama-cpp");
|
|
11099
11112
|
const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
11100
|
-
const { existsSync:
|
|
11101
|
-
const
|
|
11102
|
-
const modelPath =
|
|
11103
|
-
if (!
|
|
11113
|
+
const { existsSync: existsSync33 } = await import("fs");
|
|
11114
|
+
const path47 = await import("path");
|
|
11115
|
+
const modelPath = path47.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
|
|
11116
|
+
if (!existsSync33(modelPath)) {
|
|
11104
11117
|
throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
|
|
11105
11118
|
}
|
|
11106
11119
|
const llama = await llamaCpp.getLlama();
|
|
@@ -15515,12 +15528,108 @@ var init_setup_wizard = __esm({
|
|
|
15515
15528
|
}
|
|
15516
15529
|
});
|
|
15517
15530
|
|
|
15531
|
+
// src/lib/update-backup.ts
|
|
15532
|
+
import { copyFile, readFile as readFile6, readdir as readdir3, writeFile as writeFile7, rm, mkdir as mkdir7, cp } from "fs/promises";
|
|
15533
|
+
import { existsSync as existsSync28 } from "fs";
|
|
15534
|
+
import path34 from "path";
|
|
15535
|
+
import os17 from "os";
|
|
15536
|
+
function resolveDataDir2() {
|
|
15537
|
+
if (process.env.EXE_OS_DIR) return process.env.EXE_OS_DIR;
|
|
15538
|
+
if (process.env.EXE_MEM_DIR) return process.env.EXE_MEM_DIR;
|
|
15539
|
+
return path34.join(os17.homedir(), ".exe-os");
|
|
15540
|
+
}
|
|
15541
|
+
async function createUpdateBackup(currentVersion, dataDir) {
|
|
15542
|
+
const dir = dataDir ?? resolveDataDir2();
|
|
15543
|
+
const backupDir = path34.join(dir, BACKUP_DIR_NAME);
|
|
15544
|
+
if (existsSync28(backupDir)) {
|
|
15545
|
+
await rm(backupDir, { recursive: true, force: true });
|
|
15546
|
+
}
|
|
15547
|
+
await mkdir7(backupDir, { recursive: true });
|
|
15548
|
+
const backedUpFiles = [];
|
|
15549
|
+
for (const target of BACKUP_TARGETS) {
|
|
15550
|
+
const src = path34.join(dir, target.name);
|
|
15551
|
+
if (!existsSync28(src)) continue;
|
|
15552
|
+
const dest = path34.join(backupDir, target.name);
|
|
15553
|
+
if (target.type === "file") {
|
|
15554
|
+
await copyFile(src, dest);
|
|
15555
|
+
} else {
|
|
15556
|
+
await cp(src, dest, { recursive: true });
|
|
15557
|
+
}
|
|
15558
|
+
backedUpFiles.push(target.name);
|
|
15559
|
+
}
|
|
15560
|
+
const entries = await readdir3(dir, { withFileTypes: true });
|
|
15561
|
+
for (const entry of entries) {
|
|
15562
|
+
if (entry.isFile() && entry.name.endsWith(".db") && entry.name !== BACKUP_DIR_NAME) {
|
|
15563
|
+
const src = path34.join(dir, entry.name);
|
|
15564
|
+
const dest = path34.join(backupDir, entry.name);
|
|
15565
|
+
await copyFile(src, dest);
|
|
15566
|
+
backedUpFiles.push(entry.name);
|
|
15567
|
+
}
|
|
15568
|
+
}
|
|
15569
|
+
const manifest = {
|
|
15570
|
+
version: currentVersion,
|
|
15571
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
15572
|
+
files: backedUpFiles
|
|
15573
|
+
};
|
|
15574
|
+
await writeFile7(
|
|
15575
|
+
path34.join(backupDir, "manifest.json"),
|
|
15576
|
+
JSON.stringify(manifest, null, 2) + "\n"
|
|
15577
|
+
);
|
|
15578
|
+
return manifest;
|
|
15579
|
+
}
|
|
15580
|
+
async function restoreFromBackup(dataDir) {
|
|
15581
|
+
const dir = dataDir ?? resolveDataDir2();
|
|
15582
|
+
const backupDir = path34.join(dir, BACKUP_DIR_NAME);
|
|
15583
|
+
const manifestPath = path34.join(backupDir, "manifest.json");
|
|
15584
|
+
if (!existsSync28(manifestPath)) {
|
|
15585
|
+
throw new Error(
|
|
15586
|
+
`No backup found at ${backupDir}. Nothing to restore.`
|
|
15587
|
+
);
|
|
15588
|
+
}
|
|
15589
|
+
const manifest = JSON.parse(
|
|
15590
|
+
await readFile6(manifestPath, "utf-8")
|
|
15591
|
+
);
|
|
15592
|
+
for (const fileName of manifest.files) {
|
|
15593
|
+
const src = path34.join(backupDir, fileName);
|
|
15594
|
+
const dest = path34.join(dir, fileName);
|
|
15595
|
+
if (!existsSync28(src)) continue;
|
|
15596
|
+
const stat2 = await import("fs/promises").then((m) => m.stat(src));
|
|
15597
|
+
if (stat2.isDirectory()) {
|
|
15598
|
+
await cp(src, dest, { recursive: true, force: true });
|
|
15599
|
+
} else {
|
|
15600
|
+
await copyFile(src, dest);
|
|
15601
|
+
}
|
|
15602
|
+
}
|
|
15603
|
+
return manifest;
|
|
15604
|
+
}
|
|
15605
|
+
async function deleteBackup(dataDir) {
|
|
15606
|
+
const dir = dataDir ?? resolveDataDir2();
|
|
15607
|
+
const backupDir = path34.join(dir, BACKUP_DIR_NAME);
|
|
15608
|
+
if (existsSync28(backupDir)) {
|
|
15609
|
+
await rm(backupDir, { recursive: true, force: true });
|
|
15610
|
+
}
|
|
15611
|
+
}
|
|
15612
|
+
var BACKUP_DIR_NAME, BACKUP_TARGETS;
|
|
15613
|
+
var init_update_backup = __esm({
|
|
15614
|
+
"src/lib/update-backup.ts"() {
|
|
15615
|
+
"use strict";
|
|
15616
|
+
BACKUP_DIR_NAME = ".update-backup";
|
|
15617
|
+
BACKUP_TARGETS = [
|
|
15618
|
+
{ name: "config.json", type: "file" },
|
|
15619
|
+
{ name: "exe-employees.json", type: "file" },
|
|
15620
|
+
{ name: "master.key", type: "file" },
|
|
15621
|
+
{ name: "identity", type: "dir" }
|
|
15622
|
+
// All .db files (SQLCipher databases) — matched dynamically
|
|
15623
|
+
];
|
|
15624
|
+
}
|
|
15625
|
+
});
|
|
15626
|
+
|
|
15518
15627
|
// src/lib/update-check.ts
|
|
15519
15628
|
import { execSync as execSync11 } from "child_process";
|
|
15520
15629
|
import { readFileSync as readFileSync24 } from "fs";
|
|
15521
|
-
import
|
|
15630
|
+
import path35 from "path";
|
|
15522
15631
|
function getLocalVersion(packageRoot) {
|
|
15523
|
-
const pkgPath =
|
|
15632
|
+
const pkgPath = path35.join(packageRoot, "package.json");
|
|
15524
15633
|
const pkg = JSON.parse(readFileSync24(pkgPath, "utf-8"));
|
|
15525
15634
|
return pkg.version;
|
|
15526
15635
|
}
|
|
@@ -15567,10 +15676,47 @@ __export(update_exports, {
|
|
|
15567
15676
|
});
|
|
15568
15677
|
import { execSync as execSync12 } from "child_process";
|
|
15569
15678
|
import { createInterface as createInterface4 } from "readline";
|
|
15679
|
+
async function runRestore() {
|
|
15680
|
+
console.log("\n\u{1F504} Restoring from update backup...");
|
|
15681
|
+
try {
|
|
15682
|
+
const manifest = await restoreFromBackup();
|
|
15683
|
+
console.log(` Restored ${manifest.files.length} file(s) from v${manifest.version} backup.`);
|
|
15684
|
+
console.log(` Backup was created at ${manifest.timestamp}`);
|
|
15685
|
+
console.log(`
|
|
15686
|
+
\u{1F4E5} Reinstalling @askexenow/exe-os@${manifest.version}...`);
|
|
15687
|
+
try {
|
|
15688
|
+
execSync12(`npm install -g @askexenow/exe-os@${manifest.version}`, {
|
|
15689
|
+
stdio: ["pipe", "pipe", "inherit"],
|
|
15690
|
+
timeout: 3e5
|
|
15691
|
+
});
|
|
15692
|
+
console.log(`
|
|
15693
|
+
\u2705 Restored to v${manifest.version}`);
|
|
15694
|
+
} catch {
|
|
15695
|
+
console.error(`
|
|
15696
|
+
\u26A0\uFE0F Could not reinstall v${manifest.version} via npm.`);
|
|
15697
|
+
console.error(` Your data files have been restored. Try manually:`);
|
|
15698
|
+
console.error(` npm install -g @askexenow/exe-os@${manifest.version}`);
|
|
15699
|
+
}
|
|
15700
|
+
try {
|
|
15701
|
+
await deleteBackup();
|
|
15702
|
+
} catch {
|
|
15703
|
+
}
|
|
15704
|
+
console.log("\n\u{1F680} Restore complete. Restart your sessions.\n");
|
|
15705
|
+
} catch (err) {
|
|
15706
|
+
console.error("\u274C Restore failed.");
|
|
15707
|
+
if (err instanceof Error) console.error(` ${err.message}`);
|
|
15708
|
+
process.exit(1);
|
|
15709
|
+
}
|
|
15710
|
+
}
|
|
15570
15711
|
async function runUpdate(cliArgs) {
|
|
15571
15712
|
const args2 = cliArgs ?? process.argv.slice(2);
|
|
15572
15713
|
const autoMode = args2.includes("--auto") || args2.includes("-y");
|
|
15573
15714
|
const checkOnly = args2.includes("--check");
|
|
15715
|
+
const restoreMode = args2.includes("--restore");
|
|
15716
|
+
if (restoreMode) {
|
|
15717
|
+
await runRestore();
|
|
15718
|
+
return;
|
|
15719
|
+
}
|
|
15574
15720
|
const packageRoot = new URL("../..", import.meta.url).pathname;
|
|
15575
15721
|
const result = checkForUpdate(packageRoot);
|
|
15576
15722
|
if (result.error) {
|
|
@@ -15605,7 +15751,16 @@ async function runUpdate(cliArgs) {
|
|
|
15605
15751
|
console.log("Update skipped.");
|
|
15606
15752
|
process.exit(0);
|
|
15607
15753
|
}
|
|
15608
|
-
console.log("\n\u{
|
|
15754
|
+
console.log("\n\u{1F4BE} Backing up customer data...");
|
|
15755
|
+
try {
|
|
15756
|
+
const backupResult = await createUpdateBackup(result.localVersion);
|
|
15757
|
+
console.log(` Backed up ${backupResult.files.length} file(s) to ${BACKUP_DIR_NAME}/`);
|
|
15758
|
+
} catch (err) {
|
|
15759
|
+
console.error("\u274C Backup failed \u2014 aborting update to protect your data.");
|
|
15760
|
+
if (err instanceof Error) console.error(` ${err.message}`);
|
|
15761
|
+
process.exit(1);
|
|
15762
|
+
}
|
|
15763
|
+
console.log("\u{1F9F9} Clearing npm cache...");
|
|
15609
15764
|
try {
|
|
15610
15765
|
execSync12("npm cache clean --force", { stdio: "pipe" });
|
|
15611
15766
|
console.log(" Done");
|
|
@@ -15620,8 +15775,9 @@ async function runUpdate(cliArgs) {
|
|
|
15620
15775
|
timeout: 3e5
|
|
15621
15776
|
});
|
|
15622
15777
|
} catch (err) {
|
|
15623
|
-
console.error("\n\u274C Update failed.");
|
|
15624
|
-
console.error(
|
|
15778
|
+
console.error("\n\u274C Update failed. Your backup is preserved.");
|
|
15779
|
+
console.error(` Restore with: exe-os update --restore`);
|
|
15780
|
+
console.error(" Or try manually: npm install -g @askexenow/exe-os@latest");
|
|
15625
15781
|
if (err instanceof Error && err.message) {
|
|
15626
15782
|
console.error(` Error: ${err.message.split("\n")[0]}`);
|
|
15627
15783
|
}
|
|
@@ -15640,30 +15796,38 @@ async function runUpdate(cliArgs) {
|
|
|
15640
15796
|
}
|
|
15641
15797
|
}
|
|
15642
15798
|
const remoteVersion = result.remoteVersion;
|
|
15799
|
+
const updateSucceeded = newVersion !== result.localVersion;
|
|
15643
15800
|
if (newVersion === remoteVersion) {
|
|
15644
15801
|
console.log(`
|
|
15645
15802
|
\u2705 Updated to v${newVersion}`);
|
|
15646
|
-
} else if (
|
|
15803
|
+
} else if (updateSucceeded) {
|
|
15647
15804
|
console.log(`
|
|
15648
15805
|
\u2705 Updated to v${newVersion} (latest: v${remoteVersion})`);
|
|
15649
15806
|
} else {
|
|
15650
15807
|
console.log(`
|
|
15651
15808
|
\u26A0\uFE0F Version unchanged (v${newVersion}). npm cache may be stale.`);
|
|
15809
|
+
console.log(" Backup preserved. Restore with: exe-os update --restore");
|
|
15652
15810
|
console.log(" Try: npm cache clean --force && npm install -g @askexenow/exe-os@latest");
|
|
15653
15811
|
}
|
|
15812
|
+
if (updateSucceeded) {
|
|
15813
|
+
try {
|
|
15814
|
+
await deleteBackup();
|
|
15815
|
+
} catch {
|
|
15816
|
+
}
|
|
15817
|
+
}
|
|
15654
15818
|
console.log(" Hooks re-wired, daemon restarted automatically.");
|
|
15655
15819
|
console.log("");
|
|
15656
15820
|
console.log(" \x1B[33m\u26A1 Run /mcp in each active Claude Code session to pick up new tools.\x1B[0m");
|
|
15657
15821
|
console.log(" \x1B[2m(MCP servers can't hot-reload \u2014 Claude Code needs to reconnect them.)\x1B[0m");
|
|
15658
15822
|
try {
|
|
15659
|
-
const { existsSync: exists, readFileSync:
|
|
15823
|
+
const { existsSync: exists, readFileSync: readFile9 } = await import("fs");
|
|
15660
15824
|
const p = await import("path");
|
|
15661
15825
|
const { homedir: home } = await import("os");
|
|
15662
15826
|
const exeDir = p.default.join(home(), ".exe-os");
|
|
15663
15827
|
const licKeyPath = p.default.join(exeDir, "license.key");
|
|
15664
15828
|
const configPath = p.default.join(exeDir, "config.json");
|
|
15665
15829
|
if (!exists(licKeyPath) && exists(configPath)) {
|
|
15666
|
-
const cfg = JSON.parse(
|
|
15830
|
+
const cfg = JSON.parse(readFile9(configPath, "utf8"));
|
|
15667
15831
|
const cloud = cfg.cloud;
|
|
15668
15832
|
if (cloud?.apiKey) {
|
|
15669
15833
|
const { mirrorLicenseKey: mirrorLicenseKey2 } = await Promise.resolve().then(() => (init_license(), license_exports));
|
|
@@ -15679,6 +15843,7 @@ var init_update = __esm({
|
|
|
15679
15843
|
"src/bin/update.ts"() {
|
|
15680
15844
|
"use strict";
|
|
15681
15845
|
init_is_main();
|
|
15846
|
+
init_update_backup();
|
|
15682
15847
|
init_update_check();
|
|
15683
15848
|
init_update_check();
|
|
15684
15849
|
if (isMainModule(import.meta.url) && process.argv[1]?.includes("update")) {
|
|
@@ -20048,8 +20213,8 @@ var init_ErrorOverview = __esm({
|
|
|
20048
20213
|
"use strict";
|
|
20049
20214
|
init_Box();
|
|
20050
20215
|
init_Text();
|
|
20051
|
-
cleanupPath = (
|
|
20052
|
-
return
|
|
20216
|
+
cleanupPath = (path47) => {
|
|
20217
|
+
return path47?.replace(`file://${cwd()}/`, "");
|
|
20053
20218
|
};
|
|
20054
20219
|
stackUtils = new StackUtils({
|
|
20055
20220
|
cwd: cwd(),
|
|
@@ -21467,8 +21632,8 @@ var init_parse_keypress = __esm({
|
|
|
21467
21632
|
57453: "isoLevel3Shift",
|
|
21468
21633
|
57454: "isoLevel5Shift"
|
|
21469
21634
|
};
|
|
21470
|
-
isValidCodepoint = (
|
|
21471
|
-
safeFromCodePoint = (
|
|
21635
|
+
isValidCodepoint = (cp2) => cp2 >= 0 && cp2 <= 1114111 && !(cp2 >= 55296 && cp2 <= 57343);
|
|
21636
|
+
safeFromCodePoint = (cp2) => isValidCodepoint(cp2) ? String.fromCodePoint(cp2) : "?";
|
|
21472
21637
|
parseKittyKeypress = (s) => {
|
|
21473
21638
|
const match = kittyKeyRe.exec(s);
|
|
21474
21639
|
if (!match)
|
|
@@ -21482,7 +21647,7 @@ var init_parse_keypress = __esm({
|
|
|
21482
21647
|
}
|
|
21483
21648
|
let text;
|
|
21484
21649
|
if (textField) {
|
|
21485
|
-
text = textField.split(":").map((
|
|
21650
|
+
text = textField.split(":").map((cp2) => safeFromCodePoint(parseInt(cp2, 10))).join("");
|
|
21486
21651
|
}
|
|
21487
21652
|
let name;
|
|
21488
21653
|
let isPrintable;
|
|
@@ -22457,11 +22622,11 @@ function Footer() {
|
|
|
22457
22622
|
} catch {
|
|
22458
22623
|
}
|
|
22459
22624
|
try {
|
|
22460
|
-
const { existsSync:
|
|
22625
|
+
const { existsSync: existsSync33 } = await import("fs");
|
|
22461
22626
|
const { join } = await import("path");
|
|
22462
22627
|
const home = process.env.HOME ?? "";
|
|
22463
22628
|
const pidPath = join(home, ".exe-os", "exed.pid");
|
|
22464
|
-
setDaemon(
|
|
22629
|
+
setDaemon(existsSync33(pidPath) ? "running" : "stopped");
|
|
22465
22630
|
} catch {
|
|
22466
22631
|
setDaemon("unknown");
|
|
22467
22632
|
}
|
|
@@ -24512,10 +24677,10 @@ var init_hooks = __esm({
|
|
|
24512
24677
|
});
|
|
24513
24678
|
|
|
24514
24679
|
// src/runtime/safety-checks.ts
|
|
24515
|
-
import
|
|
24516
|
-
import
|
|
24680
|
+
import path36 from "path";
|
|
24681
|
+
import os18 from "os";
|
|
24517
24682
|
function checkPathSafety(filePath) {
|
|
24518
|
-
const resolved =
|
|
24683
|
+
const resolved = path36.resolve(filePath);
|
|
24519
24684
|
for (const { pattern, reason } of BYPASS_IMMUNE_PATTERNS) {
|
|
24520
24685
|
const matches = typeof pattern === "function" ? pattern(resolved) : pattern.test(resolved);
|
|
24521
24686
|
if (matches) {
|
|
@@ -24525,7 +24690,7 @@ function checkPathSafety(filePath) {
|
|
|
24525
24690
|
return { safe: true, bypassImmune: true };
|
|
24526
24691
|
}
|
|
24527
24692
|
function checkReadPathSafety(filePath) {
|
|
24528
|
-
const resolved =
|
|
24693
|
+
const resolved = path36.resolve(filePath);
|
|
24529
24694
|
const credPatterns = BYPASS_IMMUNE_PATTERNS.filter(
|
|
24530
24695
|
(p) => typeof p.pattern !== "function" && (p.reason.includes("secrets") || p.reason.includes("Private key") || p.reason.includes("Credential"))
|
|
24531
24696
|
);
|
|
@@ -24540,7 +24705,7 @@ var HOME, BYPASS_IMMUNE_PATTERNS;
|
|
|
24540
24705
|
var init_safety_checks = __esm({
|
|
24541
24706
|
"src/runtime/safety-checks.ts"() {
|
|
24542
24707
|
"use strict";
|
|
24543
|
-
HOME =
|
|
24708
|
+
HOME = os18.homedir();
|
|
24544
24709
|
BYPASS_IMMUNE_PATTERNS = [
|
|
24545
24710
|
{
|
|
24546
24711
|
pattern: /\/\.git\/hooks\//,
|
|
@@ -24551,11 +24716,11 @@ var init_safety_checks = __esm({
|
|
|
24551
24716
|
reason: "Git config can set hooks and command execution"
|
|
24552
24717
|
},
|
|
24553
24718
|
{
|
|
24554
|
-
pattern: (p) => p.startsWith(
|
|
24719
|
+
pattern: (p) => p.startsWith(path36.join(HOME, ".claude")),
|
|
24555
24720
|
reason: "Claude configuration files are protected"
|
|
24556
24721
|
},
|
|
24557
24722
|
{
|
|
24558
|
-
pattern: (p) => p.startsWith(
|
|
24723
|
+
pattern: (p) => p.startsWith(path36.join(HOME, ".exe-os")),
|
|
24559
24724
|
reason: "exe-os configuration files are protected"
|
|
24560
24725
|
},
|
|
24561
24726
|
{
|
|
@@ -24572,7 +24737,7 @@ var init_safety_checks = __esm({
|
|
|
24572
24737
|
},
|
|
24573
24738
|
{
|
|
24574
24739
|
pattern: (p) => {
|
|
24575
|
-
const name =
|
|
24740
|
+
const name = path36.basename(p);
|
|
24576
24741
|
return [".bashrc", ".zshrc", ".profile", ".bash_profile", ".zprofile", ".zshenv"].includes(name);
|
|
24577
24742
|
},
|
|
24578
24743
|
reason: "Shell configuration files can execute arbitrary code on login"
|
|
@@ -24599,7 +24764,7 @@ __export(file_read_exports, {
|
|
|
24599
24764
|
FileReadTool: () => FileReadTool
|
|
24600
24765
|
});
|
|
24601
24766
|
import fs3 from "fs/promises";
|
|
24602
|
-
import
|
|
24767
|
+
import path37 from "path";
|
|
24603
24768
|
import { z } from "zod";
|
|
24604
24769
|
function isBinary(buf) {
|
|
24605
24770
|
for (let i = 0; i < buf.length; i++) {
|
|
@@ -24635,7 +24800,7 @@ var init_file_read = __esm({
|
|
|
24635
24800
|
return { behavior: "allow" };
|
|
24636
24801
|
},
|
|
24637
24802
|
async call(input, context) {
|
|
24638
|
-
const filePath =
|
|
24803
|
+
const filePath = path37.isAbsolute(input.file_path) ? input.file_path : path37.resolve(context.cwd, input.file_path);
|
|
24639
24804
|
let stat2;
|
|
24640
24805
|
try {
|
|
24641
24806
|
stat2 = await fs3.stat(filePath);
|
|
@@ -24675,7 +24840,7 @@ __export(glob_exports, {
|
|
|
24675
24840
|
GlobTool: () => GlobTool
|
|
24676
24841
|
});
|
|
24677
24842
|
import fs4 from "fs/promises";
|
|
24678
|
-
import
|
|
24843
|
+
import path38 from "path";
|
|
24679
24844
|
import { z as z2 } from "zod";
|
|
24680
24845
|
async function walkDir(dir, maxDepth = 10) {
|
|
24681
24846
|
const results = [];
|
|
@@ -24691,7 +24856,7 @@ async function walkDir(dir, maxDepth = 10) {
|
|
|
24691
24856
|
if (entry.isDirectory() && (entry.name === "node_modules" || entry.name === ".git")) {
|
|
24692
24857
|
continue;
|
|
24693
24858
|
}
|
|
24694
|
-
const fullPath =
|
|
24859
|
+
const fullPath = path38.join(current, entry.name);
|
|
24695
24860
|
if (entry.isDirectory()) {
|
|
24696
24861
|
await walk(fullPath, depth + 1);
|
|
24697
24862
|
} else {
|
|
@@ -24725,11 +24890,11 @@ var init_glob = __esm({
|
|
|
24725
24890
|
inputSchema: inputSchema2,
|
|
24726
24891
|
isReadOnly: true,
|
|
24727
24892
|
async call(input, context) {
|
|
24728
|
-
const baseDir = input.path ?
|
|
24893
|
+
const baseDir = input.path ? path38.isAbsolute(input.path) ? input.path : path38.resolve(context.cwd, input.path) : context.cwd;
|
|
24729
24894
|
try {
|
|
24730
24895
|
const entries = await walkDir(baseDir);
|
|
24731
24896
|
const matched = entries.filter(
|
|
24732
|
-
(e) => simpleGlobMatch(
|
|
24897
|
+
(e) => simpleGlobMatch(path38.relative(baseDir, e.path), input.pattern)
|
|
24733
24898
|
);
|
|
24734
24899
|
matched.sort((a, b) => b.mtime - a.mtime);
|
|
24735
24900
|
if (matched.length === 0) {
|
|
@@ -24755,7 +24920,7 @@ __export(grep_exports, {
|
|
|
24755
24920
|
});
|
|
24756
24921
|
import { spawn as spawn2 } from "child_process";
|
|
24757
24922
|
import fs5 from "fs/promises";
|
|
24758
|
-
import
|
|
24923
|
+
import path39 from "path";
|
|
24759
24924
|
import { z as z3 } from "zod";
|
|
24760
24925
|
function runRipgrep(input, searchPath, context) {
|
|
24761
24926
|
return new Promise((resolve, reject) => {
|
|
@@ -24809,7 +24974,7 @@ async function nodeGrep(input, searchPath) {
|
|
|
24809
24974
|
}
|
|
24810
24975
|
for (const entry of entries) {
|
|
24811
24976
|
if (entry.name === "node_modules" || entry.name === ".git") continue;
|
|
24812
|
-
const fullPath =
|
|
24977
|
+
const fullPath = path39.join(dir, entry.name);
|
|
24813
24978
|
if (entry.isDirectory()) {
|
|
24814
24979
|
await walk(fullPath);
|
|
24815
24980
|
} else {
|
|
@@ -24855,7 +25020,7 @@ var init_grep = __esm({
|
|
|
24855
25020
|
inputSchema: inputSchema3,
|
|
24856
25021
|
isReadOnly: true,
|
|
24857
25022
|
async call(input, context) {
|
|
24858
|
-
const searchPath = input.path ?
|
|
25023
|
+
const searchPath = input.path ? path39.isAbsolute(input.path) ? input.path : path39.resolve(context.cwd, input.path) : context.cwd;
|
|
24859
25024
|
try {
|
|
24860
25025
|
const result = await runRipgrep(input, searchPath, context);
|
|
24861
25026
|
return result;
|
|
@@ -24880,7 +25045,7 @@ __export(file_write_exports, {
|
|
|
24880
25045
|
FileWriteTool: () => FileWriteTool
|
|
24881
25046
|
});
|
|
24882
25047
|
import fs6 from "fs/promises";
|
|
24883
|
-
import
|
|
25048
|
+
import path40 from "path";
|
|
24884
25049
|
import { z as z4 } from "zod";
|
|
24885
25050
|
var inputSchema4, FileWriteTool;
|
|
24886
25051
|
var init_file_write = __esm({
|
|
@@ -24908,8 +25073,8 @@ var init_file_write = __esm({
|
|
|
24908
25073
|
return { behavior: "allow" };
|
|
24909
25074
|
},
|
|
24910
25075
|
async call(input, context) {
|
|
24911
|
-
const filePath =
|
|
24912
|
-
const dir =
|
|
25076
|
+
const filePath = path40.isAbsolute(input.file_path) ? input.file_path : path40.resolve(context.cwd, input.file_path);
|
|
25077
|
+
const dir = path40.dirname(filePath);
|
|
24913
25078
|
await fs6.mkdir(dir, { recursive: true });
|
|
24914
25079
|
await fs6.writeFile(filePath, input.content, "utf-8");
|
|
24915
25080
|
return {
|
|
@@ -24927,7 +25092,7 @@ __export(file_edit_exports, {
|
|
|
24927
25092
|
FileEditTool: () => FileEditTool
|
|
24928
25093
|
});
|
|
24929
25094
|
import fs7 from "fs/promises";
|
|
24930
|
-
import
|
|
25095
|
+
import path41 from "path";
|
|
24931
25096
|
import { z as z5 } from "zod";
|
|
24932
25097
|
function countOccurrences(haystack, needle) {
|
|
24933
25098
|
let count = 0;
|
|
@@ -24968,7 +25133,7 @@ var init_file_edit = __esm({
|
|
|
24968
25133
|
return { behavior: "allow" };
|
|
24969
25134
|
},
|
|
24970
25135
|
async call(input, context) {
|
|
24971
|
-
const filePath =
|
|
25136
|
+
const filePath = path41.isAbsolute(input.file_path) ? input.file_path : path41.resolve(context.cwd, input.file_path);
|
|
24972
25137
|
let content;
|
|
24973
25138
|
try {
|
|
24974
25139
|
content = await fs7.readFile(filePath, "utf-8");
|
|
@@ -25210,7 +25375,7 @@ var init_bash = __esm({
|
|
|
25210
25375
|
// src/tui/views/CommandCenter.tsx
|
|
25211
25376
|
import { useState as useState6, useEffect as useEffect8, useMemo as useMemo4, useCallback as useCallback4, useRef as useRef4 } from "react";
|
|
25212
25377
|
import TextInput from "ink-text-input";
|
|
25213
|
-
import
|
|
25378
|
+
import path42 from "path";
|
|
25214
25379
|
import { homedir as homedir6 } from "os";
|
|
25215
25380
|
import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
25216
25381
|
function CommandCenterView({
|
|
@@ -25245,13 +25410,13 @@ function CommandCenterView({
|
|
|
25245
25410
|
const { createPermissionsFromPreset: createPermissionsFromPreset2, EMPLOYEE_PERMISSIONS: EMPLOYEE_PERMISSIONS2 } = await Promise.resolve().then(() => (init_permissions(), permissions_exports));
|
|
25246
25411
|
const { getPresetByRole: getPresetByRole2 } = await Promise.resolve().then(() => (init_permission_presets(), permission_presets_exports));
|
|
25247
25412
|
const { createDefaultHooks: createDefaultHooks2 } = await Promise.resolve().then(() => (init_hooks(), hooks_exports));
|
|
25248
|
-
const { readFileSync: readFileSync28, existsSync:
|
|
25413
|
+
const { readFileSync: readFileSync28, existsSync: existsSync33 } = await import("fs");
|
|
25249
25414
|
const { join } = await import("path");
|
|
25250
25415
|
const { homedir: homedir8 } = await import("os");
|
|
25251
25416
|
const configPath = join(homedir8(), ".exe-os", "config.json");
|
|
25252
25417
|
let failoverChain = ["anthropic", "opencode", "gemini", "openai"];
|
|
25253
25418
|
let providerConfigs = {};
|
|
25254
|
-
if (
|
|
25419
|
+
if (existsSync33(configPath)) {
|
|
25255
25420
|
try {
|
|
25256
25421
|
const raw = JSON.parse(readFileSync28(configPath, "utf8"));
|
|
25257
25422
|
if (Array.isArray(raw.failoverChain)) failoverChain = raw.failoverChain;
|
|
@@ -25459,7 +25624,7 @@ function CommandCenterView({
|
|
|
25459
25624
|
const demoEntries = DEMO_PROJECTS.map((p) => ({
|
|
25460
25625
|
projectName: p.projectName,
|
|
25461
25626
|
exeSession: p.exeSession,
|
|
25462
|
-
projectDir:
|
|
25627
|
+
projectDir: path42.join(homedir6(), p.projectName),
|
|
25463
25628
|
employeeCount: p.employees.length,
|
|
25464
25629
|
activeCount: p.employees.filter((e) => e.status === "active").length,
|
|
25465
25630
|
memoryCount: p.employees.length * 4e3,
|
|
@@ -25497,7 +25662,7 @@ function CommandCenterView({
|
|
|
25497
25662
|
const { listSessions: listSessions2 } = await Promise.resolve().then(() => (init_session_registry(), session_registry_exports));
|
|
25498
25663
|
const { listTmuxSessions: listTmuxSessions2, inTmux: inTmux2 } = await Promise.resolve().then(() => (init_tmux_status(), tmux_status_exports));
|
|
25499
25664
|
const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
25500
|
-
const { existsSync:
|
|
25665
|
+
const { existsSync: existsSync33 } = await import("fs");
|
|
25501
25666
|
const { join } = await import("path");
|
|
25502
25667
|
const client = getClient2();
|
|
25503
25668
|
if (!client) {
|
|
@@ -25568,7 +25733,7 @@ function CommandCenterView({
|
|
|
25568
25733
|
}
|
|
25569
25734
|
const memoryCount = memoryCounts.get(name) ?? 0;
|
|
25570
25735
|
const openTaskCount = openTaskCounts.get(name) ?? 0;
|
|
25571
|
-
const hasGit = projectDir ?
|
|
25736
|
+
const hasGit = projectDir ? existsSync33(join(projectDir, ".git")) : false;
|
|
25572
25737
|
const type = hasGit ? "code" : memoryCount > 0 ? "code" : "automation";
|
|
25573
25738
|
projectList.push({
|
|
25574
25739
|
projectName: name,
|
|
@@ -25593,7 +25758,7 @@ function CommandCenterView({
|
|
|
25593
25758
|
setHealth((h) => ({ ...h, memories: Number(totalResult.rows[0]?.cnt ?? 0) }));
|
|
25594
25759
|
try {
|
|
25595
25760
|
const pidPath = join(process.env.HOME ?? "", ".exe-os", "exed.pid");
|
|
25596
|
-
setHealth((h) => ({ ...h, daemon:
|
|
25761
|
+
setHealth((h) => ({ ...h, daemon: existsSync33(pidPath) ? "running" : "stopped" }));
|
|
25597
25762
|
} catch {
|
|
25598
25763
|
}
|
|
25599
25764
|
const activityResult = await client.execute(
|
|
@@ -26463,7 +26628,7 @@ var init_useOrchestrator = __esm({
|
|
|
26463
26628
|
|
|
26464
26629
|
// src/tui/views/Sessions.tsx
|
|
26465
26630
|
import React19, { useState as useState9, useEffect as useEffect11, useCallback as useCallback6 } from "react";
|
|
26466
|
-
import
|
|
26631
|
+
import path43 from "path";
|
|
26467
26632
|
import { homedir as homedir7 } from "os";
|
|
26468
26633
|
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
26469
26634
|
function isCoordinatorEntry(entry) {
|
|
@@ -26501,7 +26666,7 @@ function SessionsView({
|
|
|
26501
26666
|
if (demo) {
|
|
26502
26667
|
setProjects(DEMO_PROJECTS.map((p) => ({
|
|
26503
26668
|
...p,
|
|
26504
|
-
projectDir:
|
|
26669
|
+
projectDir: path43.join(homedir7(), p.projectName),
|
|
26505
26670
|
employees: p.employees.map((e) => ({ ...e, attached: e.status === "active" }))
|
|
26506
26671
|
})));
|
|
26507
26672
|
return;
|
|
@@ -27716,11 +27881,11 @@ async function loadGatewayConfig() {
|
|
|
27716
27881
|
state.running = false;
|
|
27717
27882
|
}
|
|
27718
27883
|
try {
|
|
27719
|
-
const { existsSync:
|
|
27884
|
+
const { existsSync: existsSync33, readFileSync: readFileSync28 } = await import("fs");
|
|
27720
27885
|
const { join } = await import("path");
|
|
27721
27886
|
const home = process.env.HOME ?? "";
|
|
27722
27887
|
const configPath = join(home, ".exe-os", "gateway.json");
|
|
27723
|
-
if (
|
|
27888
|
+
if (existsSync33(configPath)) {
|
|
27724
27889
|
const raw = JSON.parse(readFileSync28(configPath, "utf8"));
|
|
27725
27890
|
state.port = raw.port ?? 3100;
|
|
27726
27891
|
state.gatewayUrl = raw.gatewayUrl ?? "";
|
|
@@ -28319,11 +28484,11 @@ function TeamView({ onBack, onViewSessions }) {
|
|
|
28319
28484
|
setMembers(teamData);
|
|
28320
28485
|
setDbError(null);
|
|
28321
28486
|
try {
|
|
28322
|
-
const { existsSync:
|
|
28487
|
+
const { existsSync: existsSync33, readFileSync: readFileSync28 } = await import("fs");
|
|
28323
28488
|
const { join } = await import("path");
|
|
28324
28489
|
const home = process.env.HOME ?? "";
|
|
28325
28490
|
const gatewayConfig = join(home, ".exe-os", "gateway.json");
|
|
28326
|
-
if (
|
|
28491
|
+
if (existsSync33(gatewayConfig)) {
|
|
28327
28492
|
const raw = JSON.parse(readFileSync28(gatewayConfig, "utf8"));
|
|
28328
28493
|
if (raw.agents && raw.agents.length > 0) {
|
|
28329
28494
|
setExternals(raw.agents.map((a) => ({
|
|
@@ -28504,8 +28669,8 @@ __export(wiki_client_exports, {
|
|
|
28504
28669
|
listDocuments: () => listDocuments,
|
|
28505
28670
|
listWorkspaces: () => listWorkspaces
|
|
28506
28671
|
});
|
|
28507
|
-
async function wikiFetch(config,
|
|
28508
|
-
const url = `${config.baseUrl}/api/v1${
|
|
28672
|
+
async function wikiFetch(config, path47, method = "GET", body) {
|
|
28673
|
+
const url = `${config.baseUrl}/api/v1${path47}`;
|
|
28509
28674
|
const headers = {
|
|
28510
28675
|
Authorization: `Bearer ${config.apiKey}`,
|
|
28511
28676
|
"Content-Type": "application/json"
|
|
@@ -28538,7 +28703,7 @@ async function wikiFetch(config, path46, method = "GET", body) {
|
|
|
28538
28703
|
}
|
|
28539
28704
|
}
|
|
28540
28705
|
if (!response.ok) {
|
|
28541
|
-
throw new Error(`Wiki API ${method} ${
|
|
28706
|
+
throw new Error(`Wiki API ${method} ${path47}: ${response.status} ${response.statusText}`);
|
|
28542
28707
|
}
|
|
28543
28708
|
return response.json();
|
|
28544
28709
|
} finally {
|
|
@@ -29132,12 +29297,12 @@ function SettingsView({ onBack }) {
|
|
|
29132
29297
|
}
|
|
29133
29298
|
setProviders(providerList);
|
|
29134
29299
|
try {
|
|
29135
|
-
const { existsSync:
|
|
29300
|
+
const { existsSync: existsSync33 } = await import("fs");
|
|
29136
29301
|
const { join } = await import("path");
|
|
29137
29302
|
const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
29138
29303
|
const cfg = await loadConfig2();
|
|
29139
29304
|
const home = process.env.HOME ?? "";
|
|
29140
|
-
const hasKey =
|
|
29305
|
+
const hasKey = existsSync33(join(home, ".exe-os", "master.key"));
|
|
29141
29306
|
if (cfg.cloud) {
|
|
29142
29307
|
setCloud({
|
|
29143
29308
|
configured: true,
|
|
@@ -29150,7 +29315,7 @@ function SettingsView({ onBack }) {
|
|
|
29150
29315
|
const pidPath = join(home, ".exe-os", "exed.pid");
|
|
29151
29316
|
let daemon = "unknown";
|
|
29152
29317
|
try {
|
|
29153
|
-
daemon =
|
|
29318
|
+
daemon = existsSync33(pidPath) ? "running" : "stopped";
|
|
29154
29319
|
} catch {
|
|
29155
29320
|
}
|
|
29156
29321
|
let version = "unknown";
|
|
@@ -29965,18 +30130,18 @@ __export(installer_exports2, {
|
|
|
29965
30130
|
runOpenCodeInstaller: () => runOpenCodeInstaller,
|
|
29966
30131
|
verifyOpenCodeHooks: () => verifyOpenCodeHooks
|
|
29967
30132
|
});
|
|
29968
|
-
import { readFile as
|
|
29969
|
-
import { existsSync as
|
|
29970
|
-
import
|
|
29971
|
-
import
|
|
29972
|
-
async function registerOpenCodeMcp(packageRoot, homeDir =
|
|
29973
|
-
const configDir =
|
|
29974
|
-
const configPath =
|
|
29975
|
-
await
|
|
30133
|
+
import { readFile as readFile7, writeFile as writeFile8, mkdir as mkdir8 } from "fs/promises";
|
|
30134
|
+
import { existsSync as existsSync30, readFileSync as readFileSync26 } from "fs";
|
|
30135
|
+
import path44 from "path";
|
|
30136
|
+
import os19 from "os";
|
|
30137
|
+
async function registerOpenCodeMcp(packageRoot, homeDir = os19.homedir()) {
|
|
30138
|
+
const configDir = path44.join(homeDir, ".config", "opencode");
|
|
30139
|
+
const configPath = path44.join(configDir, "opencode.json");
|
|
30140
|
+
await mkdir8(configDir, { recursive: true });
|
|
29976
30141
|
let config = {};
|
|
29977
|
-
if (
|
|
30142
|
+
if (existsSync30(configPath)) {
|
|
29978
30143
|
try {
|
|
29979
|
-
config = JSON.parse(await
|
|
30144
|
+
config = JSON.parse(await readFile7(configPath, "utf-8"));
|
|
29980
30145
|
} catch {
|
|
29981
30146
|
config = {};
|
|
29982
30147
|
}
|
|
@@ -29986,7 +30151,7 @@ async function registerOpenCodeMcp(packageRoot, homeDir = os18.homedir()) {
|
|
|
29986
30151
|
}
|
|
29987
30152
|
const newEntry = {
|
|
29988
30153
|
type: "local",
|
|
29989
|
-
command: ["node",
|
|
30154
|
+
command: ["node", path44.join(packageRoot, "dist", "mcp", "server.js")],
|
|
29990
30155
|
enabled: true
|
|
29991
30156
|
};
|
|
29992
30157
|
const current = config.mcp["exe-os"];
|
|
@@ -29997,37 +30162,37 @@ async function registerOpenCodeMcp(packageRoot, homeDir = os18.homedir()) {
|
|
|
29997
30162
|
if (!config.$schema) {
|
|
29998
30163
|
config.$schema = "https://opencode.ai/config.json";
|
|
29999
30164
|
}
|
|
30000
|
-
await
|
|
30165
|
+
await writeFile8(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
30001
30166
|
return true;
|
|
30002
30167
|
}
|
|
30003
|
-
async function installOpenCodePlugin(packageRoot, homeDir =
|
|
30004
|
-
const pluginDir =
|
|
30005
|
-
const pluginPath =
|
|
30006
|
-
await
|
|
30168
|
+
async function installOpenCodePlugin(packageRoot, homeDir = os19.homedir()) {
|
|
30169
|
+
const pluginDir = path44.join(homeDir, ".config", "opencode", "plugins");
|
|
30170
|
+
const pluginPath = path44.join(pluginDir, "exe-os.mjs");
|
|
30171
|
+
await mkdir8(pluginDir, { recursive: true });
|
|
30007
30172
|
const pluginContent = PLUGIN_TEMPLATE.replace(
|
|
30008
30173
|
/__PACKAGE_ROOT__/g,
|
|
30009
30174
|
packageRoot.replace(/\\/g, "\\\\")
|
|
30010
30175
|
);
|
|
30011
|
-
if (
|
|
30012
|
-
const existing = await
|
|
30176
|
+
if (existsSync30(pluginPath)) {
|
|
30177
|
+
const existing = await readFile7(pluginPath, "utf-8");
|
|
30013
30178
|
if (existing === pluginContent) {
|
|
30014
30179
|
return false;
|
|
30015
30180
|
}
|
|
30016
30181
|
}
|
|
30017
|
-
await
|
|
30182
|
+
await writeFile8(pluginPath, pluginContent);
|
|
30018
30183
|
return true;
|
|
30019
30184
|
}
|
|
30020
|
-
function verifyOpenCodeHooks(homeDir =
|
|
30021
|
-
const configPath =
|
|
30022
|
-
const pluginPath =
|
|
30023
|
-
if (!
|
|
30185
|
+
function verifyOpenCodeHooks(homeDir = os19.homedir()) {
|
|
30186
|
+
const configPath = path44.join(homeDir, ".config", "opencode", "opencode.json");
|
|
30187
|
+
const pluginPath = path44.join(homeDir, ".config", "opencode", "plugins", "exe-os.mjs");
|
|
30188
|
+
if (!existsSync30(configPath)) return false;
|
|
30024
30189
|
try {
|
|
30025
30190
|
const config = JSON.parse(readFileSync26(configPath, "utf-8"));
|
|
30026
30191
|
if (!config.mcp?.["exe-os"]?.enabled) return false;
|
|
30027
30192
|
} catch {
|
|
30028
30193
|
return false;
|
|
30029
30194
|
}
|
|
30030
|
-
if (!
|
|
30195
|
+
if (!existsSync30(pluginPath)) return false;
|
|
30031
30196
|
return true;
|
|
30032
30197
|
}
|
|
30033
30198
|
async function runOpenCodeInstaller(homeDir) {
|
|
@@ -30056,25 +30221,26 @@ var installer_exports3 = {};
|
|
|
30056
30221
|
__export(installer_exports3, {
|
|
30057
30222
|
installCodexStatusLine: () => installCodexStatusLine,
|
|
30058
30223
|
mergeCodexHooks: () => mergeCodexHooks,
|
|
30224
|
+
registerCodexMcpServer: () => registerCodexMcpServer,
|
|
30059
30225
|
runCodexInstaller: () => runCodexInstaller,
|
|
30060
30226
|
verifyCodexHooks: () => verifyCodexHooks
|
|
30061
30227
|
});
|
|
30062
|
-
import { readFile as
|
|
30063
|
-
import { existsSync as
|
|
30064
|
-
import
|
|
30065
|
-
import
|
|
30066
|
-
async function mergeCodexHooks(packageRoot, homeDir =
|
|
30067
|
-
const codexDir =
|
|
30068
|
-
const hooksPath =
|
|
30069
|
-
const logsDir =
|
|
30070
|
-
const hookLogPath =
|
|
30228
|
+
import { readFile as readFile8, writeFile as writeFile9, mkdir as mkdir9 } from "fs/promises";
|
|
30229
|
+
import { existsSync as existsSync31 } from "fs";
|
|
30230
|
+
import path45 from "path";
|
|
30231
|
+
import os20 from "os";
|
|
30232
|
+
async function mergeCodexHooks(packageRoot, homeDir = os20.homedir()) {
|
|
30233
|
+
const codexDir = path45.join(homeDir, ".codex");
|
|
30234
|
+
const hooksPath = path45.join(codexDir, "hooks.json");
|
|
30235
|
+
const logsDir = path45.join(homeDir, ".exe-os", "logs");
|
|
30236
|
+
const hookLogPath = path45.join(logsDir, "hooks.log");
|
|
30071
30237
|
const logSuffix = ` 2>> "${hookLogPath}"`;
|
|
30072
|
-
await
|
|
30073
|
-
await
|
|
30238
|
+
await mkdir9(codexDir, { recursive: true });
|
|
30239
|
+
await mkdir9(logsDir, { recursive: true });
|
|
30074
30240
|
let hooksJson = {};
|
|
30075
|
-
if (
|
|
30241
|
+
if (existsSync31(hooksPath)) {
|
|
30076
30242
|
try {
|
|
30077
|
-
hooksJson = JSON.parse(await
|
|
30243
|
+
hooksJson = JSON.parse(await readFile8(hooksPath, "utf-8"));
|
|
30078
30244
|
} catch {
|
|
30079
30245
|
hooksJson = {};
|
|
30080
30246
|
}
|
|
@@ -30089,7 +30255,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os19.homedir()) {
|
|
|
30089
30255
|
hooks: [
|
|
30090
30256
|
{
|
|
30091
30257
|
type: "command",
|
|
30092
|
-
command: `node "${
|
|
30258
|
+
command: `node "${path45.join(packageRoot, "dist", "hooks", "session-start.js")}"${logSuffix}`,
|
|
30093
30259
|
timeout: 30,
|
|
30094
30260
|
statusMessage: "exe-os: loading memory brief"
|
|
30095
30261
|
}
|
|
@@ -30104,11 +30270,11 @@ async function mergeCodexHooks(packageRoot, homeDir = os19.homedir()) {
|
|
|
30104
30270
|
hooks: [
|
|
30105
30271
|
{
|
|
30106
30272
|
type: "command",
|
|
30107
|
-
command: `node "${
|
|
30273
|
+
command: `node "${path45.join(packageRoot, "dist", "hooks", "ingest.js")}"${logSuffix}`
|
|
30108
30274
|
},
|
|
30109
30275
|
{
|
|
30110
30276
|
type: "command",
|
|
30111
|
-
command: `node "${
|
|
30277
|
+
command: `node "${path45.join(packageRoot, "dist", "hooks", "error-recall.js")}"${logSuffix}`
|
|
30112
30278
|
}
|
|
30113
30279
|
]
|
|
30114
30280
|
},
|
|
@@ -30120,11 +30286,11 @@ async function mergeCodexHooks(packageRoot, homeDir = os19.homedir()) {
|
|
|
30120
30286
|
hooks: [
|
|
30121
30287
|
{
|
|
30122
30288
|
type: "command",
|
|
30123
|
-
command: `node "${
|
|
30289
|
+
command: `node "${path45.join(packageRoot, "dist", "hooks", "prompt-submit.js")}"${logSuffix}`
|
|
30124
30290
|
},
|
|
30125
30291
|
{
|
|
30126
30292
|
type: "command",
|
|
30127
|
-
command: `node "${
|
|
30293
|
+
command: `node "${path45.join(packageRoot, "dist", "hooks", "exe-heartbeat-hook.js")}"${logSuffix}`,
|
|
30128
30294
|
timeout: 5
|
|
30129
30295
|
}
|
|
30130
30296
|
]
|
|
@@ -30137,7 +30303,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os19.homedir()) {
|
|
|
30137
30303
|
hooks: [
|
|
30138
30304
|
{
|
|
30139
30305
|
type: "command",
|
|
30140
|
-
command: `node "${
|
|
30306
|
+
command: `node "${path45.join(packageRoot, "dist", "hooks", "stop.js")}"${logSuffix}`
|
|
30141
30307
|
}
|
|
30142
30308
|
]
|
|
30143
30309
|
},
|
|
@@ -30150,7 +30316,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os19.homedir()) {
|
|
|
30150
30316
|
hooks: [
|
|
30151
30317
|
{
|
|
30152
30318
|
type: "command",
|
|
30153
|
-
command: `node "${
|
|
30319
|
+
command: `node "${path45.join(packageRoot, "dist", "hooks", "pre-tool-use.js")}"${logSuffix}`
|
|
30154
30320
|
}
|
|
30155
30321
|
]
|
|
30156
30322
|
},
|
|
@@ -30178,12 +30344,12 @@ async function mergeCodexHooks(packageRoot, homeDir = os19.homedir()) {
|
|
|
30178
30344
|
added++;
|
|
30179
30345
|
}
|
|
30180
30346
|
}
|
|
30181
|
-
await
|
|
30347
|
+
await writeFile9(hooksPath, JSON.stringify(hooksJson, null, 2) + "\n");
|
|
30182
30348
|
return { added, skipped };
|
|
30183
30349
|
}
|
|
30184
|
-
function verifyCodexHooks(homeDir =
|
|
30185
|
-
const hooksPath =
|
|
30186
|
-
if (!
|
|
30350
|
+
function verifyCodexHooks(homeDir = os20.homedir()) {
|
|
30351
|
+
const hooksPath = path45.join(homeDir, ".codex", "hooks.json");
|
|
30352
|
+
if (!existsSync31(hooksPath)) return false;
|
|
30187
30353
|
try {
|
|
30188
30354
|
const hooksJson = JSON.parse(
|
|
30189
30355
|
__require("fs").readFileSync(hooksPath, "utf-8")
|
|
@@ -30203,15 +30369,15 @@ function verifyCodexHooks(homeDir = os19.homedir()) {
|
|
|
30203
30369
|
return false;
|
|
30204
30370
|
}
|
|
30205
30371
|
}
|
|
30206
|
-
async function installCodexStatusLine(homeDir =
|
|
30372
|
+
async function installCodexStatusLine(homeDir = os20.homedir()) {
|
|
30207
30373
|
const prefs = loadPreferences(homeDir);
|
|
30208
30374
|
if (prefs.codexStatusLine === false) return "opted-out";
|
|
30209
|
-
const codexDir =
|
|
30210
|
-
const configPath =
|
|
30211
|
-
await
|
|
30375
|
+
const codexDir = path45.join(homeDir, ".codex");
|
|
30376
|
+
const configPath = path45.join(codexDir, "config.toml");
|
|
30377
|
+
await mkdir9(codexDir, { recursive: true });
|
|
30212
30378
|
let content = "";
|
|
30213
|
-
if (
|
|
30214
|
-
content = await
|
|
30379
|
+
if (existsSync31(configPath)) {
|
|
30380
|
+
content = await readFile8(configPath, "utf-8");
|
|
30215
30381
|
if (/\[tui\][\s\S]*?status_line\s*=/.test(content)) {
|
|
30216
30382
|
return "already-configured";
|
|
30217
30383
|
}
|
|
@@ -30224,14 +30390,55 @@ status_line = [${DEFAULT_CODEX_STATUS_LINE.map((s) => `"${s}"`).join(", ")}]`;
|
|
|
30224
30390
|
const separator = content.length > 0 && !content.endsWith("\n") ? "\n\n" : content.length > 0 ? "\n" : "";
|
|
30225
30391
|
content = content + separator + statusLineToml + "\n";
|
|
30226
30392
|
}
|
|
30227
|
-
await
|
|
30393
|
+
await writeFile9(configPath, content);
|
|
30228
30394
|
return "installed";
|
|
30229
30395
|
}
|
|
30396
|
+
async function registerCodexMcpServer(packageRoot, homeDir = os20.homedir()) {
|
|
30397
|
+
const codexDir = path45.join(homeDir, ".codex");
|
|
30398
|
+
const configPath = path45.join(codexDir, "config.toml");
|
|
30399
|
+
const serverJsPath = path45.join(packageRoot, "dist", "mcp", "server.js");
|
|
30400
|
+
await mkdir9(codexDir, { recursive: true });
|
|
30401
|
+
let content = "";
|
|
30402
|
+
if (existsSync31(configPath)) {
|
|
30403
|
+
content = await readFile8(configPath, "utf-8");
|
|
30404
|
+
}
|
|
30405
|
+
const sectionHeader = "[mcp_servers.exe-os]";
|
|
30406
|
+
const headerIndex = content.indexOf(sectionHeader);
|
|
30407
|
+
if (headerIndex !== -1) {
|
|
30408
|
+
const afterHeader = content.slice(headerIndex + sectionHeader.length);
|
|
30409
|
+
const nextSectionMatch = afterHeader.match(/\n\[(?!mcp_servers\.exe-os)/);
|
|
30410
|
+
const sectionEnd = nextSectionMatch ? headerIndex + sectionHeader.length + nextSectionMatch.index : content.length;
|
|
30411
|
+
const sectionContent = content.slice(headerIndex, sectionEnd);
|
|
30412
|
+
if (sectionContent.includes(serverJsPath)) {
|
|
30413
|
+
return "already-registered";
|
|
30414
|
+
}
|
|
30415
|
+
const newSection2 = `${sectionHeader}
|
|
30416
|
+
command = "node"
|
|
30417
|
+
args = ["${serverJsPath}"]
|
|
30418
|
+
`;
|
|
30419
|
+
content = content.slice(0, headerIndex) + newSection2 + content.slice(sectionEnd);
|
|
30420
|
+
await writeFile9(configPath, content);
|
|
30421
|
+
return "updated";
|
|
30422
|
+
}
|
|
30423
|
+
const newSection = `[mcp_servers.exe-os]
|
|
30424
|
+
command = "node"
|
|
30425
|
+
args = ["${serverJsPath}"]
|
|
30426
|
+
`;
|
|
30427
|
+
const separator = content.length > 0 && !content.endsWith("\n") ? "\n\n" : content.length > 0 ? "\n" : "";
|
|
30428
|
+
content = content + separator + newSection;
|
|
30429
|
+
await writeFile9(configPath, content);
|
|
30430
|
+
return "registered";
|
|
30431
|
+
}
|
|
30230
30432
|
async function runCodexInstaller(homeDir) {
|
|
30231
30433
|
const packageRoot = resolvePackageRoot();
|
|
30232
30434
|
const result = await mergeCodexHooks(packageRoot, homeDir);
|
|
30233
30435
|
process.stderr.write(
|
|
30234
30436
|
`[exe-os] Codex hooks: ${result.added} added, ${result.skipped} unchanged
|
|
30437
|
+
`
|
|
30438
|
+
);
|
|
30439
|
+
const mcpResult = await registerCodexMcpServer(packageRoot, homeDir);
|
|
30440
|
+
process.stderr.write(
|
|
30441
|
+
`[exe-os] Codex MCP server: ${mcpResult}
|
|
30235
30442
|
`
|
|
30236
30443
|
);
|
|
30237
30444
|
const statusResult = await installCodexStatusLine(homeDir);
|
|
@@ -30258,13 +30465,13 @@ var init_installer3 = __esm({
|
|
|
30258
30465
|
});
|
|
30259
30466
|
|
|
30260
30467
|
// src/bin/cli.ts
|
|
30261
|
-
import { existsSync as
|
|
30262
|
-
import
|
|
30263
|
-
import
|
|
30468
|
+
import { existsSync as existsSync32, readFileSync as readFileSync27, writeFileSync as writeFileSync20, readdirSync as readdirSync9, rmSync } from "fs";
|
|
30469
|
+
import path46 from "path";
|
|
30470
|
+
import os21 from "os";
|
|
30264
30471
|
var args = process.argv.slice(2);
|
|
30265
30472
|
if (args.includes("--version") || args.includes("-v")) {
|
|
30266
30473
|
try {
|
|
30267
|
-
const pkgPath =
|
|
30474
|
+
const pkgPath = path46.join(path46.dirname(new URL(import.meta.url).pathname), "..", "..", "package.json");
|
|
30268
30475
|
const pkg = JSON.parse(readFileSync27(pkgPath, "utf8"));
|
|
30269
30476
|
console.log(pkg.version);
|
|
30270
30477
|
} catch {
|
|
@@ -30429,9 +30636,9 @@ ID: ${result.id}`);
|
|
|
30429
30636
|
});
|
|
30430
30637
|
await init_App2().then(() => App_exports);
|
|
30431
30638
|
} else {
|
|
30432
|
-
const claudeDir =
|
|
30433
|
-
const settingsPath =
|
|
30434
|
-
const hasClaudeCode =
|
|
30639
|
+
const claudeDir = path46.join(os21.homedir(), ".claude");
|
|
30640
|
+
const settingsPath = path46.join(claudeDir, "settings.json");
|
|
30641
|
+
const hasClaudeCode = existsSync32(settingsPath) && (() => {
|
|
30435
30642
|
try {
|
|
30436
30643
|
const raw = readFileSync27(settingsPath, "utf8");
|
|
30437
30644
|
return raw.includes("exe-os") || raw.includes("exe-mem");
|
|
@@ -30443,8 +30650,8 @@ ID: ${result.id}`);
|
|
|
30443
30650
|
const { DEFAULT_COORDINATOR_TEMPLATE_NAME: DEFAULT_COORDINATOR_TEMPLATE_NAME2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
30444
30651
|
let cooName = DEFAULT_COORDINATOR_TEMPLATE_NAME2;
|
|
30445
30652
|
try {
|
|
30446
|
-
const rosterPath =
|
|
30447
|
-
if (
|
|
30653
|
+
const rosterPath = path46.join(os21.homedir(), ".exe-os", "exe-employees.json");
|
|
30654
|
+
if (existsSync32(rosterPath)) {
|
|
30448
30655
|
const roster = JSON.parse(readFileSync27(rosterPath, "utf8"));
|
|
30449
30656
|
const coo = roster.find((e) => e.role === "COO");
|
|
30450
30657
|
if (coo) cooName = coo.name;
|
|
@@ -30509,11 +30716,11 @@ async function runCodexInstall() {
|
|
|
30509
30716
|
}
|
|
30510
30717
|
}
|
|
30511
30718
|
async function runClaudeCheck() {
|
|
30512
|
-
const claudeDir =
|
|
30513
|
-
const settingsPath =
|
|
30514
|
-
const claudeJsonPath =
|
|
30719
|
+
const claudeDir = path46.join(os21.homedir(), ".claude");
|
|
30720
|
+
const settingsPath = path46.join(claudeDir, "settings.json");
|
|
30721
|
+
const claudeJsonPath = path46.join(os21.homedir(), ".claude.json");
|
|
30515
30722
|
let ok = true;
|
|
30516
|
-
if (
|
|
30723
|
+
if (existsSync32(settingsPath)) {
|
|
30517
30724
|
let settings;
|
|
30518
30725
|
try {
|
|
30519
30726
|
settings = JSON.parse(readFileSync27(settingsPath, "utf8"));
|
|
@@ -30542,7 +30749,7 @@ async function runClaudeCheck() {
|
|
|
30542
30749
|
console.log("\x1B[31m\u2717\x1B[0m settings.json not found");
|
|
30543
30750
|
ok = false;
|
|
30544
30751
|
}
|
|
30545
|
-
if (
|
|
30752
|
+
if (existsSync32(claudeJsonPath)) {
|
|
30546
30753
|
let claudeJson;
|
|
30547
30754
|
try {
|
|
30548
30755
|
claudeJson = JSON.parse(readFileSync27(claudeJsonPath, "utf8"));
|
|
@@ -30564,8 +30771,8 @@ async function runClaudeCheck() {
|
|
|
30564
30771
|
console.log("\x1B[31m\u2717\x1B[0m claude.json not found");
|
|
30565
30772
|
ok = false;
|
|
30566
30773
|
}
|
|
30567
|
-
const skillsDir =
|
|
30568
|
-
if (
|
|
30774
|
+
const skillsDir = path46.join(claudeDir, "skills");
|
|
30775
|
+
if (existsSync32(skillsDir)) {
|
|
30569
30776
|
console.log("\x1B[32m\u2713\x1B[0m Slash skills directory exists");
|
|
30570
30777
|
} else {
|
|
30571
30778
|
console.log("\x1B[31m\u2717\x1B[0m Slash skills directory missing");
|
|
@@ -30581,15 +30788,15 @@ async function runClaudeCheck() {
|
|
|
30581
30788
|
async function runClaudeUninstall(flags = []) {
|
|
30582
30789
|
const dryRun = flags.includes("--dry-run");
|
|
30583
30790
|
const purge = flags.includes("--purge");
|
|
30584
|
-
const homeDir =
|
|
30585
|
-
const claudeDir =
|
|
30586
|
-
const settingsPath =
|
|
30587
|
-
const claudeJsonPath =
|
|
30588
|
-
const exeOsDir =
|
|
30791
|
+
const homeDir = os21.homedir();
|
|
30792
|
+
const claudeDir = path46.join(homeDir, ".claude");
|
|
30793
|
+
const settingsPath = path46.join(claudeDir, "settings.json");
|
|
30794
|
+
const claudeJsonPath = path46.join(homeDir, ".claude.json");
|
|
30795
|
+
const exeOsDir = path46.join(homeDir, ".exe-os");
|
|
30589
30796
|
let removed = 0;
|
|
30590
30797
|
const log = (msg) => console.log(dryRun ? `[dry-run] ${msg}` : msg);
|
|
30591
30798
|
let settings = {};
|
|
30592
|
-
if (
|
|
30799
|
+
if (existsSync32(settingsPath)) {
|
|
30593
30800
|
try {
|
|
30594
30801
|
settings = JSON.parse(readFileSync27(settingsPath, "utf8"));
|
|
30595
30802
|
} catch {
|
|
@@ -30636,7 +30843,7 @@ async function runClaudeUninstall(flags = []) {
|
|
|
30636
30843
|
removed++;
|
|
30637
30844
|
}
|
|
30638
30845
|
}
|
|
30639
|
-
if (
|
|
30846
|
+
if (existsSync32(claudeJsonPath)) {
|
|
30640
30847
|
const raw = readFileSync27(claudeJsonPath, "utf8");
|
|
30641
30848
|
if (raw.length > 1e6) {
|
|
30642
30849
|
console.error("claude.json exceeds 1 MB \u2014 skipping parse.");
|
|
@@ -30666,14 +30873,14 @@ async function runClaudeUninstall(flags = []) {
|
|
|
30666
30873
|
}
|
|
30667
30874
|
}
|
|
30668
30875
|
}
|
|
30669
|
-
const skillsDir =
|
|
30670
|
-
if (
|
|
30876
|
+
const skillsDir = path46.join(claudeDir, "skills");
|
|
30877
|
+
if (existsSync32(skillsDir)) {
|
|
30671
30878
|
let skillCount = 0;
|
|
30672
30879
|
try {
|
|
30673
30880
|
const entries = readdirSync9(skillsDir);
|
|
30674
30881
|
for (const entry of entries) {
|
|
30675
30882
|
if (entry.startsWith("exe")) {
|
|
30676
|
-
const fullPath =
|
|
30883
|
+
const fullPath = path46.join(skillsDir, entry);
|
|
30677
30884
|
if (!dryRun) rmSync(fullPath, { recursive: true, force: true });
|
|
30678
30885
|
skillCount++;
|
|
30679
30886
|
}
|
|
@@ -30685,8 +30892,8 @@ async function runClaudeUninstall(flags = []) {
|
|
|
30685
30892
|
removed++;
|
|
30686
30893
|
}
|
|
30687
30894
|
}
|
|
30688
|
-
const claudeMdPath =
|
|
30689
|
-
if (
|
|
30895
|
+
const claudeMdPath = path46.join(claudeDir, "CLAUDE.md");
|
|
30896
|
+
if (existsSync32(claudeMdPath)) {
|
|
30690
30897
|
const content = readFileSync27(claudeMdPath, "utf8");
|
|
30691
30898
|
const startMarker = "<!-- exe-os:orchestration-start -->";
|
|
30692
30899
|
const endMarker = "<!-- exe-os:orchestration-end -->";
|
|
@@ -30699,14 +30906,14 @@ async function runClaudeUninstall(flags = []) {
|
|
|
30699
30906
|
removed++;
|
|
30700
30907
|
}
|
|
30701
30908
|
}
|
|
30702
|
-
const agentsDir =
|
|
30703
|
-
if (
|
|
30909
|
+
const agentsDir = path46.join(claudeDir, "agents");
|
|
30910
|
+
if (existsSync32(agentsDir)) {
|
|
30704
30911
|
let agentCount = 0;
|
|
30705
30912
|
try {
|
|
30706
30913
|
const entries = readdirSync9(agentsDir).filter((f) => f.endsWith(".md"));
|
|
30707
30914
|
let knownNames = /* @__PURE__ */ new Set();
|
|
30708
|
-
const rosterPath =
|
|
30709
|
-
if (
|
|
30915
|
+
const rosterPath = path46.join(exeOsDir, "exe-employees.json");
|
|
30916
|
+
if (existsSync32(rosterPath)) {
|
|
30710
30917
|
try {
|
|
30711
30918
|
const roster = JSON.parse(readFileSync27(rosterPath, "utf8"));
|
|
30712
30919
|
knownNames = new Set(roster.map((e) => e.name));
|
|
@@ -30716,7 +30923,7 @@ async function runClaudeUninstall(flags = []) {
|
|
|
30716
30923
|
for (const entry of entries) {
|
|
30717
30924
|
const name = entry.replace(/\.md$/, "");
|
|
30718
30925
|
if (knownNames.has(name)) {
|
|
30719
|
-
if (!dryRun) rmSync(
|
|
30926
|
+
if (!dryRun) rmSync(path46.join(agentsDir, entry), { force: true });
|
|
30720
30927
|
agentCount++;
|
|
30721
30928
|
}
|
|
30722
30929
|
}
|
|
@@ -30727,14 +30934,14 @@ async function runClaudeUninstall(flags = []) {
|
|
|
30727
30934
|
removed++;
|
|
30728
30935
|
}
|
|
30729
30936
|
}
|
|
30730
|
-
const projectsDir =
|
|
30731
|
-
if (
|
|
30937
|
+
const projectsDir = path46.join(claudeDir, "projects");
|
|
30938
|
+
if (existsSync32(projectsDir)) {
|
|
30732
30939
|
let projectCount = 0;
|
|
30733
30940
|
try {
|
|
30734
30941
|
const projects = readdirSync9(projectsDir);
|
|
30735
30942
|
for (const proj of projects) {
|
|
30736
|
-
const projSettings =
|
|
30737
|
-
if (!
|
|
30943
|
+
const projSettings = path46.join(projectsDir, proj, "settings.json");
|
|
30944
|
+
if (!existsSync32(projSettings)) continue;
|
|
30738
30945
|
try {
|
|
30739
30946
|
const pSettings = JSON.parse(readFileSync27(projSettings, "utf8"));
|
|
30740
30947
|
let changed = false;
|
|
@@ -30770,18 +30977,18 @@ async function runClaudeUninstall(flags = []) {
|
|
|
30770
30977
|
};
|
|
30771
30978
|
const exeBinPath = findExeBin3();
|
|
30772
30979
|
if (!exeBinPath) throw new Error("exe-os not found in PATH");
|
|
30773
|
-
const binDir =
|
|
30980
|
+
const binDir = path46.dirname(exeBinPath);
|
|
30774
30981
|
let symlinkCount = 0;
|
|
30775
|
-
const rosterPath =
|
|
30776
|
-
if (
|
|
30982
|
+
const rosterPath = path46.join(exeOsDir, "exe-employees.json");
|
|
30983
|
+
if (existsSync32(rosterPath)) {
|
|
30777
30984
|
const roster = JSON.parse(readFileSync27(rosterPath, "utf8"));
|
|
30778
30985
|
const { DEFAULT_COORDINATOR_TEMPLATE_NAME: DEFAULT_COORDINATOR_TEMPLATE_NAME2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
30779
30986
|
const coordinatorName = roster.find((e) => e.role?.toLowerCase() === "coo")?.name ?? DEFAULT_COORDINATOR_TEMPLATE_NAME2;
|
|
30780
30987
|
for (const emp of roster) {
|
|
30781
30988
|
if (emp.name === coordinatorName) continue;
|
|
30782
30989
|
for (const suffix of ["", "-opencode"]) {
|
|
30783
|
-
const linkPath =
|
|
30784
|
-
if (
|
|
30990
|
+
const linkPath = path46.join(binDir, `${emp.name}${suffix}`);
|
|
30991
|
+
if (existsSync32(linkPath)) {
|
|
30785
30992
|
if (!dryRun) rmSync(linkPath, { force: true });
|
|
30786
30993
|
symlinkCount++;
|
|
30787
30994
|
}
|
|
@@ -30794,7 +31001,7 @@ async function runClaudeUninstall(flags = []) {
|
|
|
30794
31001
|
}
|
|
30795
31002
|
} catch {
|
|
30796
31003
|
}
|
|
30797
|
-
if (purge &&
|
|
31004
|
+
if (purge && existsSync32(exeOsDir)) {
|
|
30798
31005
|
if (!dryRun) {
|
|
30799
31006
|
process.stdout.write("\x1B[33m\u26A0 This will delete all memories, identities, and agent data.\x1B[0m\n");
|
|
30800
31007
|
process.stdout.write(" Removing ~/.exe-os...\n");
|
|
@@ -30819,7 +31026,7 @@ async function checkForUpdateOnBoot() {
|
|
|
30819
31026
|
const config = await loadConfig2();
|
|
30820
31027
|
if (!config.autoUpdate.checkOnBoot) return;
|
|
30821
31028
|
const { checkForUpdate: checkForUpdate2 } = await Promise.resolve().then(() => (init_update(), update_exports));
|
|
30822
|
-
const packageRoot =
|
|
31029
|
+
const packageRoot = path46.resolve(
|
|
30823
31030
|
new URL("../..", import.meta.url).pathname
|
|
30824
31031
|
);
|
|
30825
31032
|
const result = checkForUpdate2(packageRoot);
|
|
@@ -30879,7 +31086,7 @@ async function runActivate(key) {
|
|
|
30879
31086
|
const idTemplate = getIdentityTemplate(identityKey);
|
|
30880
31087
|
if (idTemplate) {
|
|
30881
31088
|
const idPath = identityPath2(name);
|
|
30882
|
-
const dir =
|
|
31089
|
+
const dir = path46.dirname(idPath);
|
|
30883
31090
|
if (!fs8.existsSync(dir)) fs8.mkdirSync(dir, { recursive: true });
|
|
30884
31091
|
fs8.writeFileSync(idPath, idTemplate.replace(/^agent_id: \w+/m, `agent_id: ${name}`), "utf-8");
|
|
30885
31092
|
}
|