@askexenow/exe-os 0.9.48 → 0.9.51
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/cli.js +312 -96
- package/dist/bin/update.js +14 -1
- package/package.json +1 -1
package/dist/bin/cli.js
CHANGED
|
@@ -1886,8 +1886,8 @@ function deriveMachineKey() {
|
|
|
1886
1886
|
}
|
|
1887
1887
|
function readMachineId() {
|
|
1888
1888
|
try {
|
|
1889
|
-
const { readFileSync:
|
|
1890
|
-
return
|
|
1889
|
+
const { readFileSync: readFileSync31 } = __require("fs");
|
|
1890
|
+
return readFileSync31("/etc/machine-id", "utf-8").trim();
|
|
1891
1891
|
} catch {
|
|
1892
1892
|
return "";
|
|
1893
1893
|
}
|
|
@@ -9140,9 +9140,9 @@ Unclassified: ${unclassified}
|
|
|
9140
9140
|
}
|
|
9141
9141
|
async function exportBatches(options) {
|
|
9142
9142
|
const fs8 = await import("fs");
|
|
9143
|
-
const
|
|
9143
|
+
const path50 = await import("path");
|
|
9144
9144
|
const client = getClient();
|
|
9145
|
-
const outDir =
|
|
9145
|
+
const outDir = path50.join(process.cwd(), "exe/output/classifications/input");
|
|
9146
9146
|
fs8.mkdirSync(outDir, { recursive: true });
|
|
9147
9147
|
const countResult = await client.execute({
|
|
9148
9148
|
sql: "SELECT COUNT(*) as cnt FROM memories WHERE intent IS NULL AND outcome IS NULL AND domain IS NULL",
|
|
@@ -9166,7 +9166,7 @@ async function exportBatches(options) {
|
|
|
9166
9166
|
const text = String(row.text || "").replace(/\n/g, " ");
|
|
9167
9167
|
return JSON.stringify({ id: row.id, text });
|
|
9168
9168
|
});
|
|
9169
|
-
const batchFile =
|
|
9169
|
+
const batchFile = path50.join(outDir, `batch-${String(batchNum).padStart(4, "0")}.jsonl`);
|
|
9170
9170
|
fs8.writeFileSync(batchFile, lines.join("\n") + "\n");
|
|
9171
9171
|
exported += batch.rows.length;
|
|
9172
9172
|
offset += options.batchSize;
|
|
@@ -9182,7 +9182,7 @@ async function exportBatches(options) {
|
|
|
9182
9182
|
}
|
|
9183
9183
|
async function importClassifications(importDir) {
|
|
9184
9184
|
const fs8 = await import("fs");
|
|
9185
|
-
const
|
|
9185
|
+
const path50 = await import("path");
|
|
9186
9186
|
const client = getClient();
|
|
9187
9187
|
const files = fs8.readdirSync(importDir).filter((f) => f.endsWith(".jsonl")).sort();
|
|
9188
9188
|
process.stderr.write(`[backfill-metadata] Found ${files.length} JSONL files to import from ${importDir}
|
|
@@ -9190,7 +9190,7 @@ async function importClassifications(importDir) {
|
|
|
9190
9190
|
let imported = 0;
|
|
9191
9191
|
let invalid = 0;
|
|
9192
9192
|
for (const file of files) {
|
|
9193
|
-
const lines = fs8.readFileSync(
|
|
9193
|
+
const lines = fs8.readFileSync(path50.join(importDir, file), "utf-8").split("\n").filter(Boolean);
|
|
9194
9194
|
for (const line of lines) {
|
|
9195
9195
|
try {
|
|
9196
9196
|
const rec = JSON.parse(line);
|
|
@@ -11828,10 +11828,10 @@ async function disposeEmbedder() {
|
|
|
11828
11828
|
async function embedDirect(text) {
|
|
11829
11829
|
const llamaCpp = await import("node-llama-cpp");
|
|
11830
11830
|
const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
11831
|
-
const { existsSync:
|
|
11832
|
-
const
|
|
11833
|
-
const modelPath =
|
|
11834
|
-
if (!
|
|
11831
|
+
const { existsSync: existsSync36 } = await import("fs");
|
|
11832
|
+
const path50 = await import("path");
|
|
11833
|
+
const modelPath = path50.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
|
|
11834
|
+
if (!existsSync36(modelPath)) {
|
|
11835
11835
|
throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
|
|
11836
11836
|
}
|
|
11837
11837
|
const llama = await llamaCpp.getLlama();
|
|
@@ -16607,7 +16607,20 @@ async function runUpdate(cliArgs) {
|
|
|
16607
16607
|
} catch {
|
|
16608
16608
|
}
|
|
16609
16609
|
}
|
|
16610
|
-
console.log("
|
|
16610
|
+
console.log("\u{1F527} Re-registering MCP, hooks, wrappers, and daemon...");
|
|
16611
|
+
try {
|
|
16612
|
+
execSync13("exe-os-install --global", {
|
|
16613
|
+
stdio: ["pipe", "inherit", "inherit"],
|
|
16614
|
+
timeout: 3e5
|
|
16615
|
+
});
|
|
16616
|
+
} catch (err) {
|
|
16617
|
+
console.error("\n\u26A0\uFE0F Package updated, but post-update install failed.");
|
|
16618
|
+
console.error(" Run manually: exe-os-install --global");
|
|
16619
|
+
if (err instanceof Error && err.message) {
|
|
16620
|
+
console.error(` Error: ${err.message.split("\n")[0]}`);
|
|
16621
|
+
}
|
|
16622
|
+
}
|
|
16623
|
+
console.log(" MCP, hooks, and daemon refreshed.");
|
|
16611
16624
|
console.log("");
|
|
16612
16625
|
console.log(" \x1B[33m\u26A1 Run /mcp in each active Claude Code session to pick up new tools.\x1B[0m");
|
|
16613
16626
|
console.log(" \x1B[2m(MCP servers can't hot-reload \u2014 Claude Code needs to reconnect them.)\x1B[0m");
|
|
@@ -21308,8 +21321,8 @@ var init_ErrorOverview = __esm({
|
|
|
21308
21321
|
"use strict";
|
|
21309
21322
|
init_Box();
|
|
21310
21323
|
init_Text();
|
|
21311
|
-
cleanupPath = (
|
|
21312
|
-
return
|
|
21324
|
+
cleanupPath = (path50) => {
|
|
21325
|
+
return path50?.replace(`file://${cwd()}/`, "");
|
|
21313
21326
|
};
|
|
21314
21327
|
stackUtils = new StackUtils({
|
|
21315
21328
|
cwd: cwd(),
|
|
@@ -23717,11 +23730,11 @@ function Footer() {
|
|
|
23717
23730
|
} catch {
|
|
23718
23731
|
}
|
|
23719
23732
|
try {
|
|
23720
|
-
const { existsSync:
|
|
23733
|
+
const { existsSync: existsSync36 } = await import("fs");
|
|
23721
23734
|
const { join } = await import("path");
|
|
23722
23735
|
const home = process.env.HOME ?? "";
|
|
23723
23736
|
const pidPath = join(home, ".exe-os", "exed.pid");
|
|
23724
|
-
setDaemon(
|
|
23737
|
+
setDaemon(existsSync36(pidPath) ? "running" : "stopped");
|
|
23725
23738
|
} catch {
|
|
23726
23739
|
setDaemon("unknown");
|
|
23727
23740
|
}
|
|
@@ -26505,15 +26518,15 @@ function CommandCenterView({
|
|
|
26505
26518
|
const { createPermissionsFromPreset: createPermissionsFromPreset2, EMPLOYEE_PERMISSIONS: EMPLOYEE_PERMISSIONS2 } = await Promise.resolve().then(() => (init_permissions(), permissions_exports));
|
|
26506
26519
|
const { getPresetByRole: getPresetByRole2 } = await Promise.resolve().then(() => (init_permission_presets(), permission_presets_exports));
|
|
26507
26520
|
const { createDefaultHooks: createDefaultHooks2 } = await Promise.resolve().then(() => (init_hooks(), hooks_exports));
|
|
26508
|
-
const { readFileSync:
|
|
26521
|
+
const { readFileSync: readFileSync31, existsSync: existsSync36 } = await import("fs");
|
|
26509
26522
|
const { join } = await import("path");
|
|
26510
26523
|
const { homedir: homedir8 } = await import("os");
|
|
26511
26524
|
const configPath = join(homedir8(), ".exe-os", "config.json");
|
|
26512
26525
|
let failoverChain = ["anthropic", "opencode", "gemini", "openai"];
|
|
26513
26526
|
let providerConfigs = {};
|
|
26514
|
-
if (
|
|
26527
|
+
if (existsSync36(configPath)) {
|
|
26515
26528
|
try {
|
|
26516
|
-
const raw = JSON.parse(
|
|
26529
|
+
const raw = JSON.parse(readFileSync31(configPath, "utf8"));
|
|
26517
26530
|
if (Array.isArray(raw.failoverChain)) failoverChain = raw.failoverChain;
|
|
26518
26531
|
if (raw.providers && typeof raw.providers === "object") {
|
|
26519
26532
|
providerConfigs = raw.providers;
|
|
@@ -26574,7 +26587,7 @@ function CommandCenterView({
|
|
|
26574
26587
|
const markerDir = join(homedir8(), ".exe-os", "session-cache");
|
|
26575
26588
|
const agentFiles = (await import("fs")).readdirSync(markerDir).filter((f) => f.startsWith("active-agent-"));
|
|
26576
26589
|
for (const f of agentFiles) {
|
|
26577
|
-
const data = JSON.parse(
|
|
26590
|
+
const data = JSON.parse(readFileSync31(join(markerDir, f), "utf8"));
|
|
26578
26591
|
if (data.agentRole) {
|
|
26579
26592
|
agentRole = data.agentRole;
|
|
26580
26593
|
break;
|
|
@@ -26757,7 +26770,7 @@ function CommandCenterView({
|
|
|
26757
26770
|
const { listSessions: listSessions2 } = await Promise.resolve().then(() => (init_session_registry(), session_registry_exports));
|
|
26758
26771
|
const { listTmuxSessions: listTmuxSessions2, inTmux: inTmux2 } = await Promise.resolve().then(() => (init_tmux_status(), tmux_status_exports));
|
|
26759
26772
|
const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
26760
|
-
const { existsSync:
|
|
26773
|
+
const { existsSync: existsSync36 } = await import("fs");
|
|
26761
26774
|
const { join } = await import("path");
|
|
26762
26775
|
const client = getClient2();
|
|
26763
26776
|
if (!client) {
|
|
@@ -26828,7 +26841,7 @@ function CommandCenterView({
|
|
|
26828
26841
|
}
|
|
26829
26842
|
const memoryCount = memoryCounts.get(name) ?? 0;
|
|
26830
26843
|
const openTaskCount = openTaskCounts.get(name) ?? 0;
|
|
26831
|
-
const hasGit = projectDir ?
|
|
26844
|
+
const hasGit = projectDir ? existsSync36(join(projectDir, ".git")) : false;
|
|
26832
26845
|
const type = hasGit ? "code" : memoryCount > 0 ? "code" : "automation";
|
|
26833
26846
|
projectList.push({
|
|
26834
26847
|
projectName: name,
|
|
@@ -26853,7 +26866,7 @@ function CommandCenterView({
|
|
|
26853
26866
|
setHealth((h) => ({ ...h, memories: Number(totalResult.rows[0]?.cnt ?? 0) }));
|
|
26854
26867
|
try {
|
|
26855
26868
|
const pidPath = join(process.env.HOME ?? "", ".exe-os", "exed.pid");
|
|
26856
|
-
setHealth((h) => ({ ...h, daemon:
|
|
26869
|
+
setHealth((h) => ({ ...h, daemon: existsSync36(pidPath) ? "running" : "stopped" }));
|
|
26857
26870
|
} catch {
|
|
26858
26871
|
}
|
|
26859
26872
|
const activityResult = await client.execute(
|
|
@@ -28976,12 +28989,12 @@ async function loadGatewayConfig() {
|
|
|
28976
28989
|
state.running = false;
|
|
28977
28990
|
}
|
|
28978
28991
|
try {
|
|
28979
|
-
const { existsSync:
|
|
28992
|
+
const { existsSync: existsSync36, readFileSync: readFileSync31 } = await import("fs");
|
|
28980
28993
|
const { join } = await import("path");
|
|
28981
28994
|
const home = process.env.HOME ?? "";
|
|
28982
28995
|
const configPath = join(home, ".exe-os", "gateway.json");
|
|
28983
|
-
if (
|
|
28984
|
-
const raw = JSON.parse(
|
|
28996
|
+
if (existsSync36(configPath)) {
|
|
28997
|
+
const raw = JSON.parse(readFileSync31(configPath, "utf8"));
|
|
28985
28998
|
state.port = raw.port ?? 3100;
|
|
28986
28999
|
state.gatewayUrl = raw.gatewayUrl ?? "";
|
|
28987
29000
|
if (raw.adapters) {
|
|
@@ -29579,12 +29592,12 @@ function TeamView({ onBack, onViewSessions }) {
|
|
|
29579
29592
|
setMembers(teamData);
|
|
29580
29593
|
setDbError(null);
|
|
29581
29594
|
try {
|
|
29582
|
-
const { existsSync:
|
|
29595
|
+
const { existsSync: existsSync36, readFileSync: readFileSync31 } = await import("fs");
|
|
29583
29596
|
const { join } = await import("path");
|
|
29584
29597
|
const home = process.env.HOME ?? "";
|
|
29585
29598
|
const gatewayConfig = join(home, ".exe-os", "gateway.json");
|
|
29586
|
-
if (
|
|
29587
|
-
const raw = JSON.parse(
|
|
29599
|
+
if (existsSync36(gatewayConfig)) {
|
|
29600
|
+
const raw = JSON.parse(readFileSync31(gatewayConfig, "utf8"));
|
|
29588
29601
|
if (raw.agents && raw.agents.length > 0) {
|
|
29589
29602
|
setExternals(raw.agents.map((a) => ({
|
|
29590
29603
|
name: a.name,
|
|
@@ -29764,8 +29777,8 @@ __export(wiki_client_exports, {
|
|
|
29764
29777
|
listDocuments: () => listDocuments,
|
|
29765
29778
|
listWorkspaces: () => listWorkspaces
|
|
29766
29779
|
});
|
|
29767
|
-
async function wikiFetch(config,
|
|
29768
|
-
const url = `${config.baseUrl}/api/v1${
|
|
29780
|
+
async function wikiFetch(config, path50, method = "GET", body) {
|
|
29781
|
+
const url = `${config.baseUrl}/api/v1${path50}`;
|
|
29769
29782
|
const headers = {
|
|
29770
29783
|
Authorization: `Bearer ${config.apiKey}`,
|
|
29771
29784
|
"Content-Type": "application/json"
|
|
@@ -29798,7 +29811,7 @@ async function wikiFetch(config, path49, method = "GET", body) {
|
|
|
29798
29811
|
}
|
|
29799
29812
|
}
|
|
29800
29813
|
if (!response.ok) {
|
|
29801
|
-
throw new Error(`Wiki API ${method} ${
|
|
29814
|
+
throw new Error(`Wiki API ${method} ${path50}: ${response.status} ${response.statusText}`);
|
|
29802
29815
|
}
|
|
29803
29816
|
return response.json();
|
|
29804
29817
|
} finally {
|
|
@@ -30392,12 +30405,12 @@ function SettingsView({ onBack }) {
|
|
|
30392
30405
|
}
|
|
30393
30406
|
setProviders(providerList);
|
|
30394
30407
|
try {
|
|
30395
|
-
const { existsSync:
|
|
30408
|
+
const { existsSync: existsSync36 } = await import("fs");
|
|
30396
30409
|
const { join } = await import("path");
|
|
30397
30410
|
const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
30398
30411
|
const cfg = await loadConfig2();
|
|
30399
30412
|
const home = process.env.HOME ?? "";
|
|
30400
|
-
const hasKey =
|
|
30413
|
+
const hasKey = existsSync36(join(home, ".exe-os", "master.key"));
|
|
30401
30414
|
if (cfg.cloud) {
|
|
30402
30415
|
setCloud({
|
|
30403
30416
|
configured: true,
|
|
@@ -30410,22 +30423,22 @@ function SettingsView({ onBack }) {
|
|
|
30410
30423
|
const pidPath = join(home, ".exe-os", "exed.pid");
|
|
30411
30424
|
let daemon = "unknown";
|
|
30412
30425
|
try {
|
|
30413
|
-
daemon =
|
|
30426
|
+
daemon = existsSync36(pidPath) ? "running" : "stopped";
|
|
30414
30427
|
} catch {
|
|
30415
30428
|
}
|
|
30416
30429
|
let version = "unknown";
|
|
30417
30430
|
try {
|
|
30418
|
-
const { readFileSync:
|
|
30431
|
+
const { readFileSync: readFileSync31 } = await import("fs");
|
|
30419
30432
|
const { createRequire: createRequire3 } = await import("module");
|
|
30420
30433
|
const require2 = createRequire3(import.meta.url);
|
|
30421
30434
|
const pkgPath = require2.resolve("@askexenow/exe-os/package.json");
|
|
30422
|
-
const pkg = JSON.parse(
|
|
30435
|
+
const pkg = JSON.parse(readFileSync31(pkgPath, "utf8"));
|
|
30423
30436
|
version = pkg.version;
|
|
30424
30437
|
} catch {
|
|
30425
30438
|
try {
|
|
30426
|
-
const { readFileSync:
|
|
30439
|
+
const { readFileSync: readFileSync31 } = await import("fs");
|
|
30427
30440
|
const { join: joinPath } = await import("path");
|
|
30428
|
-
const pkg = JSON.parse(
|
|
30441
|
+
const pkg = JSON.parse(readFileSync31(joinPath(process.cwd(), "package.json"), "utf8"));
|
|
30429
30442
|
version = pkg.version;
|
|
30430
30443
|
} catch {
|
|
30431
30444
|
}
|
|
@@ -31624,15 +31637,199 @@ var init_installer3 = __esm({
|
|
|
31624
31637
|
}
|
|
31625
31638
|
});
|
|
31626
31639
|
|
|
31627
|
-
// src/
|
|
31628
|
-
|
|
31640
|
+
// src/adapters/claude/mcp-diagnostics.ts
|
|
31641
|
+
var mcp_diagnostics_exports = {};
|
|
31642
|
+
__export(mcp_diagnostics_exports, {
|
|
31643
|
+
diagnoseClaudeMcpConfig: () => diagnoseClaudeMcpConfig,
|
|
31644
|
+
formatMcpDiagnosticReport: () => formatMcpDiagnosticReport
|
|
31645
|
+
});
|
|
31646
|
+
import { existsSync as existsSync34, readFileSync as readFileSync29 } from "fs";
|
|
31629
31647
|
import path48 from "path";
|
|
31630
31648
|
import os21 from "os";
|
|
31649
|
+
function readJson(filePath) {
|
|
31650
|
+
if (!existsSync34(filePath)) return null;
|
|
31651
|
+
try {
|
|
31652
|
+
return JSON.parse(readFileSync29(filePath, "utf8"));
|
|
31653
|
+
} catch {
|
|
31654
|
+
return null;
|
|
31655
|
+
}
|
|
31656
|
+
}
|
|
31657
|
+
function pathApplies2(projectPath, cwd2) {
|
|
31658
|
+
const project = path48.resolve(projectPath);
|
|
31659
|
+
const current = path48.resolve(cwd2);
|
|
31660
|
+
return current === project || current.startsWith(project + path48.sep);
|
|
31661
|
+
}
|
|
31662
|
+
function findAncestorMcpJsons2(cwd2, homeDir) {
|
|
31663
|
+
const files = [];
|
|
31664
|
+
let dir = path48.resolve(cwd2);
|
|
31665
|
+
const root = path48.parse(dir).root;
|
|
31666
|
+
const stop = path48.resolve(homeDir);
|
|
31667
|
+
while (dir !== root) {
|
|
31668
|
+
const candidate = path48.join(dir, ".mcp.json");
|
|
31669
|
+
if (existsSync34(candidate)) files.push(candidate);
|
|
31670
|
+
if (dir === stop) break;
|
|
31671
|
+
dir = path48.dirname(dir);
|
|
31672
|
+
}
|
|
31673
|
+
return files;
|
|
31674
|
+
}
|
|
31675
|
+
function extractPermissionPrefixes(settings) {
|
|
31676
|
+
const allow = settings?.permissions?.allow ?? [];
|
|
31677
|
+
const prefixes = /* @__PURE__ */ new Set();
|
|
31678
|
+
for (const entry of allow) {
|
|
31679
|
+
const match = entry.match(/^mcp__(.+?)__/);
|
|
31680
|
+
if (match?.[1]) prefixes.add(match[1]);
|
|
31681
|
+
}
|
|
31682
|
+
return [...prefixes].sort();
|
|
31683
|
+
}
|
|
31684
|
+
function serverAllowedByPermissions(serverName, prefixes) {
|
|
31685
|
+
return prefixes.has(serverName) || prefixes.has(serverName.replace(/-/g, "_"));
|
|
31686
|
+
}
|
|
31687
|
+
function diagnoseClaudeMcpConfig(homeDir = os21.homedir(), cwd2 = process.cwd(), env = process.env) {
|
|
31688
|
+
const claudeJsonPath = path48.join(homeDir, ".claude.json");
|
|
31689
|
+
const settingsPath = path48.join(homeDir, ".claude", "settings.json");
|
|
31690
|
+
const claudeJson = readJson(claudeJsonPath);
|
|
31691
|
+
const settings = readJson(settingsPath);
|
|
31692
|
+
const issues = [];
|
|
31693
|
+
if (!claudeJson) {
|
|
31694
|
+
issues.push({
|
|
31695
|
+
severity: "error",
|
|
31696
|
+
code: "claude-json-missing-or-invalid",
|
|
31697
|
+
message: "~/.claude.json is missing or invalid, so Claude MCP server config cannot be audited.",
|
|
31698
|
+
fix: "Run exe-os claude install, then re-open Claude Code."
|
|
31699
|
+
});
|
|
31700
|
+
}
|
|
31701
|
+
if (!settings) {
|
|
31702
|
+
issues.push({
|
|
31703
|
+
severity: "warn",
|
|
31704
|
+
code: "settings-json-missing-or-invalid",
|
|
31705
|
+
message: "~/.claude/settings.json is missing or invalid; MCP permissions cannot be audited.",
|
|
31706
|
+
fix: "Run exe-os claude install, then re-open Claude Code."
|
|
31707
|
+
});
|
|
31708
|
+
}
|
|
31709
|
+
const globalServers = Object.keys(claudeJson?.mcpServers ?? {}).sort();
|
|
31710
|
+
const projectServers = [];
|
|
31711
|
+
const applicableProjects = [];
|
|
31712
|
+
for (const [projectPath, projectConfig] of Object.entries(claudeJson?.projects ?? {})) {
|
|
31713
|
+
if (!pathApplies2(projectPath, cwd2)) continue;
|
|
31714
|
+
applicableProjects.push([projectPath, projectConfig]);
|
|
31715
|
+
for (const name of Object.keys(projectConfig.mcpServers ?? {})) {
|
|
31716
|
+
projectServers.push({ name, source: "project", path: projectPath });
|
|
31717
|
+
}
|
|
31718
|
+
if (Array.isArray(projectConfig.enabledMcpServers)) {
|
|
31719
|
+
issues.push({
|
|
31720
|
+
severity: projectConfig.enabledMcpServers.length === 0 ? "warn" : "info",
|
|
31721
|
+
code: "enabled-mcp-servers-present",
|
|
31722
|
+
message: `Project ${projectPath} contains enabledMcpServers=${JSON.stringify(projectConfig.enabledMcpServers)}. This key is not the same as enabledMcpjsonServers and has caused confusing /mcp debugging reports.`,
|
|
31723
|
+
fix: "If MCP tools are hidden, back up ~/.claude.json, remove only this key, restart Claude Code, and compare /mcp + ToolSearch."
|
|
31724
|
+
});
|
|
31725
|
+
}
|
|
31726
|
+
}
|
|
31727
|
+
const mcpJsonServers = [];
|
|
31728
|
+
for (const mcpJsonPath of findAncestorMcpJsons2(cwd2, homeDir)) {
|
|
31729
|
+
const mcpJson = readJson(mcpJsonPath);
|
|
31730
|
+
for (const name of Object.keys(mcpJson?.mcpServers ?? {})) {
|
|
31731
|
+
mcpJsonServers.push({ name, source: "mcp.json", path: mcpJsonPath });
|
|
31732
|
+
}
|
|
31733
|
+
}
|
|
31734
|
+
const permissionPrefixes = extractPermissionPrefixes(settings);
|
|
31735
|
+
const permissionPrefixSet = new Set(permissionPrefixes);
|
|
31736
|
+
const allConfiguredServerNames = [...globalServers, ...projectServers.map((s) => s.name), ...mcpJsonServers.map((s) => s.name)];
|
|
31737
|
+
const configuredServers = [...new Set(allConfiguredServerNames)].sort();
|
|
31738
|
+
const nonExeServers = configuredServers.filter((s) => s !== "exe-os" && s !== "exe-mem");
|
|
31739
|
+
const nonExeWithoutPermissions = nonExeServers.filter((s) => !serverAllowedByPermissions(s, permissionPrefixSet));
|
|
31740
|
+
if (nonExeWithoutPermissions.length > 0 && permissionPrefixes.some((p) => p === "exe-os" || p === "exe-mem")) {
|
|
31741
|
+
issues.push({
|
|
31742
|
+
severity: "warn",
|
|
31743
|
+
code: "non-exe-mcp-not-permission-allowlisted",
|
|
31744
|
+
message: `Interactive Claude Code may only surface/auto-run permission-allowed MCP tools. exe-os is allowlisted, but these configured servers are not: ${nonExeWithoutPermissions.join(", ")}.`,
|
|
31745
|
+
fix: "In Claude Code, run /permissions and allow the needed MCP server tools (for example mcp__figma__*), then restart. As a diagnostic only, test ENABLE_TOOL_SEARCH=false claude to compare tool injection."
|
|
31746
|
+
});
|
|
31747
|
+
}
|
|
31748
|
+
const duplicateNames = allConfiguredServerNames.filter((name, index, arr) => arr.indexOf(name) !== index);
|
|
31749
|
+
if (duplicateNames.length > 0) {
|
|
31750
|
+
issues.push({
|
|
31751
|
+
severity: "warn",
|
|
31752
|
+
code: "duplicate-mcp-server-names",
|
|
31753
|
+
message: `Duplicate MCP server names exist across global/project/.mcp.json scopes: ${[...new Set(duplicateNames)].join(", ")}. Claude Code can show Connected while dropping tools when scopes collide.`,
|
|
31754
|
+
fix: "Use one source of truth per MCP server name; remove or rename duplicates."
|
|
31755
|
+
});
|
|
31756
|
+
}
|
|
31757
|
+
for (const server of mcpJsonServers) {
|
|
31758
|
+
for (const [projectPath, projectConfig] of applicableProjects) {
|
|
31759
|
+
if (!projectConfig.mcpServers?.[server.name]) continue;
|
|
31760
|
+
const enabled = new Set(projectConfig.enabledMcpjsonServers ?? []);
|
|
31761
|
+
if (!enabled.has(server.name)) {
|
|
31762
|
+
issues.push({
|
|
31763
|
+
severity: "error",
|
|
31764
|
+
code: "disabled-mcp-json-shadows-project-server",
|
|
31765
|
+
message: `${server.name} appears in ${server.path} and project ${projectPath}, but is not enabled in enabledMcpjsonServers. This can shadow the project server and yield Connected/0 tools.`,
|
|
31766
|
+
fix: "Remove/rename the duplicate .mcp.json entry or enable that .mcp.json server explicitly."
|
|
31767
|
+
});
|
|
31768
|
+
}
|
|
31769
|
+
}
|
|
31770
|
+
}
|
|
31771
|
+
if (env.ENABLE_TOOL_SEARCH && env.ENABLE_TOOL_SEARCH !== "auto") {
|
|
31772
|
+
issues.push({
|
|
31773
|
+
severity: "info",
|
|
31774
|
+
code: "enable-tool-search-env-set",
|
|
31775
|
+
message: `ENABLE_TOOL_SEARCH is set to ${env.ENABLE_TOOL_SEARCH}. This changes Claude Code's deferred tool injection path.`,
|
|
31776
|
+
fix: "For debugging, compare interactive launches with ENABLE_TOOL_SEARCH=false, ENABLE_TOOL_SEARCH=auto, and unset."
|
|
31777
|
+
});
|
|
31778
|
+
}
|
|
31779
|
+
if (configuredServers.length > 8) {
|
|
31780
|
+
issues.push({
|
|
31781
|
+
severity: "info",
|
|
31782
|
+
code: "large-mcp-surface",
|
|
31783
|
+
message: `${configuredServers.length} MCP servers are configured for this project. If pipe mode sees tools but interactive mode does not, reduce scope temporarily or enable only needed servers while debugging Claude Code tool injection.`,
|
|
31784
|
+
fix: "Keep exe-os global, move project/design tools into the active project only, and use /permissions for the servers needed in that session."
|
|
31785
|
+
});
|
|
31786
|
+
}
|
|
31787
|
+
return {
|
|
31788
|
+
cwd: path48.resolve(cwd2),
|
|
31789
|
+
globalServers,
|
|
31790
|
+
projectServers: projectServers.sort((a, b) => a.name.localeCompare(b.name)),
|
|
31791
|
+
mcpJsonServers: mcpJsonServers.sort((a, b) => a.name.localeCompare(b.name)),
|
|
31792
|
+
permissionPrefixes,
|
|
31793
|
+
issues
|
|
31794
|
+
};
|
|
31795
|
+
}
|
|
31796
|
+
function formatMcpDiagnosticReport(report) {
|
|
31797
|
+
const lines = [];
|
|
31798
|
+
lines.push("Claude MCP Diagnostic");
|
|
31799
|
+
lines.push(`cwd: ${report.cwd}`);
|
|
31800
|
+
lines.push("");
|
|
31801
|
+
lines.push(`global servers: ${report.globalServers.length ? report.globalServers.join(", ") : "none"}`);
|
|
31802
|
+
lines.push(`project servers: ${report.projectServers.length ? report.projectServers.map((s) => `${s.name} (${s.path})`).join(", ") : "none"}`);
|
|
31803
|
+
lines.push(`.mcp.json servers: ${report.mcpJsonServers.length ? report.mcpJsonServers.map((s) => `${s.name} (${s.path})`).join(", ") : "none"}`);
|
|
31804
|
+
lines.push(`permission MCP prefixes: ${report.permissionPrefixes.length ? report.permissionPrefixes.join(", ") : "none"}`);
|
|
31805
|
+
lines.push("");
|
|
31806
|
+
if (report.issues.length === 0) {
|
|
31807
|
+
lines.push("\u2713 No obvious MCP config hazards detected.");
|
|
31808
|
+
return lines.join("\n");
|
|
31809
|
+
}
|
|
31810
|
+
lines.push("Issues / clues:");
|
|
31811
|
+
for (const issue of report.issues) {
|
|
31812
|
+
const icon = issue.severity === "error" ? "\u2717" : issue.severity === "warn" ? "!" : "i";
|
|
31813
|
+
lines.push(`${icon} [${issue.code}] ${issue.message}`);
|
|
31814
|
+
if (issue.fix) lines.push(` Fix/test: ${issue.fix}`);
|
|
31815
|
+
}
|
|
31816
|
+
return lines.join("\n");
|
|
31817
|
+
}
|
|
31818
|
+
var init_mcp_diagnostics = __esm({
|
|
31819
|
+
"src/adapters/claude/mcp-diagnostics.ts"() {
|
|
31820
|
+
"use strict";
|
|
31821
|
+
}
|
|
31822
|
+
});
|
|
31823
|
+
|
|
31824
|
+
// src/bin/cli.ts
|
|
31825
|
+
import { existsSync as existsSync35, readFileSync as readFileSync30, writeFileSync as writeFileSync21, readdirSync as readdirSync10, rmSync } from "fs";
|
|
31826
|
+
import path49 from "path";
|
|
31827
|
+
import os22 from "os";
|
|
31631
31828
|
var args = process.argv.slice(2);
|
|
31632
31829
|
if (args.includes("--version") || args.includes("-v")) {
|
|
31633
31830
|
try {
|
|
31634
|
-
const pkgPath =
|
|
31635
|
-
const pkg = JSON.parse(
|
|
31831
|
+
const pkgPath = path49.join(path49.dirname(new URL(import.meta.url).pathname), "..", "..", "package.json");
|
|
31832
|
+
const pkg = JSON.parse(readFileSync30(pkgPath, "utf8"));
|
|
31636
31833
|
console.log(pkg.version);
|
|
31637
31834
|
} catch {
|
|
31638
31835
|
console.log("unknown");
|
|
@@ -31666,6 +31863,17 @@ if (args.includes("--global")) {
|
|
|
31666
31863
|
case "check":
|
|
31667
31864
|
await runClaudeCheck();
|
|
31668
31865
|
break;
|
|
31866
|
+
case "mcp-doctor":
|
|
31867
|
+
await runClaudeMcpDoctor();
|
|
31868
|
+
break;
|
|
31869
|
+
case "mcp":
|
|
31870
|
+
if (args[2] === "doctor") {
|
|
31871
|
+
await runClaudeMcpDoctor();
|
|
31872
|
+
} else {
|
|
31873
|
+
console.error("Usage: exe-os claude mcp-doctor");
|
|
31874
|
+
process.exit(1);
|
|
31875
|
+
}
|
|
31876
|
+
break;
|
|
31669
31877
|
case "uninstall":
|
|
31670
31878
|
await runClaudeUninstall(args.slice(2));
|
|
31671
31879
|
break;
|
|
@@ -31799,11 +32007,11 @@ ID: ${result.id}`);
|
|
|
31799
32007
|
});
|
|
31800
32008
|
await init_App2().then(() => App_exports);
|
|
31801
32009
|
} else {
|
|
31802
|
-
const claudeDir =
|
|
31803
|
-
const settingsPath =
|
|
31804
|
-
const hasClaudeCode =
|
|
32010
|
+
const claudeDir = path49.join(os22.homedir(), ".claude");
|
|
32011
|
+
const settingsPath = path49.join(claudeDir, "settings.json");
|
|
32012
|
+
const hasClaudeCode = existsSync35(settingsPath) && (() => {
|
|
31805
32013
|
try {
|
|
31806
|
-
const raw =
|
|
32014
|
+
const raw = readFileSync30(settingsPath, "utf8");
|
|
31807
32015
|
return raw.includes("exe-os") || raw.includes("exe-mem");
|
|
31808
32016
|
} catch {
|
|
31809
32017
|
return false;
|
|
@@ -31813,9 +32021,9 @@ ID: ${result.id}`);
|
|
|
31813
32021
|
const { DEFAULT_COORDINATOR_TEMPLATE_NAME: DEFAULT_COORDINATOR_TEMPLATE_NAME2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
31814
32022
|
let cooName = DEFAULT_COORDINATOR_TEMPLATE_NAME2;
|
|
31815
32023
|
try {
|
|
31816
|
-
const rosterPath =
|
|
31817
|
-
if (
|
|
31818
|
-
const roster = JSON.parse(
|
|
32024
|
+
const rosterPath = path49.join(os22.homedir(), ".exe-os", "exe-employees.json");
|
|
32025
|
+
if (existsSync35(rosterPath)) {
|
|
32026
|
+
const roster = JSON.parse(readFileSync30(rosterPath, "utf8"));
|
|
31819
32027
|
const coo = roster.find((e) => e.role === "COO");
|
|
31820
32028
|
if (coo) cooName = coo.name;
|
|
31821
32029
|
}
|
|
@@ -31833,6 +32041,7 @@ cd into a project folder and run \x1B[1m${cooName}1\x1B[0m to boot your COO.
|
|
|
31833
32041
|
exe-os setup Re-run setup wizard
|
|
31834
32042
|
exe-os cloud sync Sync all data with Exe Cloud
|
|
31835
32043
|
exe-os claude check Verify Claude Code integration
|
|
32044
|
+
exe-os claude mcp-doctor Diagnose Claude MCP tool visibility
|
|
31836
32045
|
exe-os tui Launch TUI dashboard (Mode 2)
|
|
31837
32046
|
exe-os --help Show all commands
|
|
31838
32047
|
`);
|
|
@@ -31880,14 +32089,14 @@ async function runCodexInstall() {
|
|
|
31880
32089
|
}
|
|
31881
32090
|
async function runClaudeCheck() {
|
|
31882
32091
|
const { detectMcpNameCollisions: detectMcpNameCollisions2 } = await Promise.resolve().then(() => (init_installer(), installer_exports));
|
|
31883
|
-
const claudeDir =
|
|
31884
|
-
const settingsPath =
|
|
31885
|
-
const claudeJsonPath =
|
|
32092
|
+
const claudeDir = path49.join(os22.homedir(), ".claude");
|
|
32093
|
+
const settingsPath = path49.join(claudeDir, "settings.json");
|
|
32094
|
+
const claudeJsonPath = path49.join(os22.homedir(), ".claude.json");
|
|
31886
32095
|
let ok = true;
|
|
31887
|
-
if (
|
|
32096
|
+
if (existsSync35(settingsPath)) {
|
|
31888
32097
|
let settings;
|
|
31889
32098
|
try {
|
|
31890
|
-
settings = JSON.parse(
|
|
32099
|
+
settings = JSON.parse(readFileSync30(settingsPath, "utf8"));
|
|
31891
32100
|
} catch {
|
|
31892
32101
|
console.log("\x1B[31m\u2717\x1B[0m settings.json is malformed (invalid JSON)");
|
|
31893
32102
|
ok = false;
|
|
@@ -31913,10 +32122,10 @@ async function runClaudeCheck() {
|
|
|
31913
32122
|
console.log("\x1B[31m\u2717\x1B[0m settings.json not found");
|
|
31914
32123
|
ok = false;
|
|
31915
32124
|
}
|
|
31916
|
-
if (
|
|
32125
|
+
if (existsSync35(claudeJsonPath)) {
|
|
31917
32126
|
let claudeJson;
|
|
31918
32127
|
try {
|
|
31919
|
-
claudeJson = JSON.parse(
|
|
32128
|
+
claudeJson = JSON.parse(readFileSync30(claudeJsonPath, "utf8"));
|
|
31920
32129
|
} catch {
|
|
31921
32130
|
console.log("\x1B[31m\u2717\x1B[0m claude.json is malformed (invalid JSON)");
|
|
31922
32131
|
ok = false;
|
|
@@ -31935,7 +32144,7 @@ async function runClaudeCheck() {
|
|
|
31935
32144
|
console.log("\x1B[31m\u2717\x1B[0m claude.json not found");
|
|
31936
32145
|
ok = false;
|
|
31937
32146
|
}
|
|
31938
|
-
const collisions = detectMcpNameCollisions2(
|
|
32147
|
+
const collisions = detectMcpNameCollisions2(os22.homedir(), process.cwd());
|
|
31939
32148
|
const disabledCollisions = collisions.filter((c) => c.disabledInMcpJson);
|
|
31940
32149
|
if (disabledCollisions.length > 0) {
|
|
31941
32150
|
console.log("\x1B[31m\u2717\x1B[0m MCP name collision: disabled .mcp.json entries shadow project MCP servers");
|
|
@@ -31949,8 +32158,8 @@ async function runClaudeCheck() {
|
|
|
31949
32158
|
} else {
|
|
31950
32159
|
console.log("\x1B[32m\u2713\x1B[0m No .mcp.json/project MCP name collisions detected");
|
|
31951
32160
|
}
|
|
31952
|
-
const skillsDir =
|
|
31953
|
-
if (
|
|
32161
|
+
const skillsDir = path49.join(claudeDir, "skills");
|
|
32162
|
+
if (existsSync35(skillsDir)) {
|
|
31954
32163
|
console.log("\x1B[32m\u2713\x1B[0m Slash skills directory exists");
|
|
31955
32164
|
} else {
|
|
31956
32165
|
console.log("\x1B[31m\u2717\x1B[0m Slash skills directory missing");
|
|
@@ -31963,20 +32172,27 @@ async function runClaudeCheck() {
|
|
|
31963
32172
|
console.log("\nAll checks passed.");
|
|
31964
32173
|
}
|
|
31965
32174
|
}
|
|
32175
|
+
async function runClaudeMcpDoctor() {
|
|
32176
|
+
const { diagnoseClaudeMcpConfig: diagnoseClaudeMcpConfig2, formatMcpDiagnosticReport: formatMcpDiagnosticReport2 } = await Promise.resolve().then(() => (init_mcp_diagnostics(), mcp_diagnostics_exports));
|
|
32177
|
+
const report = diagnoseClaudeMcpConfig2(os22.homedir(), process.cwd(), process.env);
|
|
32178
|
+
console.log(formatMcpDiagnosticReport2(report));
|
|
32179
|
+
const hasError = report.issues.some((issue) => issue.severity === "error");
|
|
32180
|
+
process.exit(hasError ? 1 : 0);
|
|
32181
|
+
}
|
|
31966
32182
|
async function runClaudeUninstall(flags = []) {
|
|
31967
32183
|
const dryRun = flags.includes("--dry-run");
|
|
31968
32184
|
const purge = flags.includes("--purge");
|
|
31969
|
-
const homeDir =
|
|
31970
|
-
const claudeDir =
|
|
31971
|
-
const settingsPath =
|
|
31972
|
-
const claudeJsonPath =
|
|
31973
|
-
const exeOsDir =
|
|
32185
|
+
const homeDir = os22.homedir();
|
|
32186
|
+
const claudeDir = path49.join(homeDir, ".claude");
|
|
32187
|
+
const settingsPath = path49.join(claudeDir, "settings.json");
|
|
32188
|
+
const claudeJsonPath = path49.join(homeDir, ".claude.json");
|
|
32189
|
+
const exeOsDir = path49.join(homeDir, ".exe-os");
|
|
31974
32190
|
let removed = 0;
|
|
31975
32191
|
const log = (msg) => console.log(dryRun ? `[dry-run] ${msg}` : msg);
|
|
31976
32192
|
let settings = {};
|
|
31977
|
-
if (
|
|
32193
|
+
if (existsSync35(settingsPath)) {
|
|
31978
32194
|
try {
|
|
31979
|
-
settings = JSON.parse(
|
|
32195
|
+
settings = JSON.parse(readFileSync30(settingsPath, "utf8"));
|
|
31980
32196
|
} catch {
|
|
31981
32197
|
console.error("Your ~/.claude/settings.json appears malformed.");
|
|
31982
32198
|
if (purge) {
|
|
@@ -32021,8 +32237,8 @@ async function runClaudeUninstall(flags = []) {
|
|
|
32021
32237
|
removed++;
|
|
32022
32238
|
}
|
|
32023
32239
|
}
|
|
32024
|
-
if (
|
|
32025
|
-
const raw =
|
|
32240
|
+
if (existsSync35(claudeJsonPath)) {
|
|
32241
|
+
const raw = readFileSync30(claudeJsonPath, "utf8");
|
|
32026
32242
|
if (raw.length > 1e6) {
|
|
32027
32243
|
console.error("claude.json exceeds 1 MB \u2014 skipping parse.");
|
|
32028
32244
|
} else {
|
|
@@ -32051,14 +32267,14 @@ async function runClaudeUninstall(flags = []) {
|
|
|
32051
32267
|
}
|
|
32052
32268
|
}
|
|
32053
32269
|
}
|
|
32054
|
-
const skillsDir =
|
|
32055
|
-
if (
|
|
32270
|
+
const skillsDir = path49.join(claudeDir, "skills");
|
|
32271
|
+
if (existsSync35(skillsDir)) {
|
|
32056
32272
|
let skillCount = 0;
|
|
32057
32273
|
try {
|
|
32058
32274
|
const entries = readdirSync10(skillsDir);
|
|
32059
32275
|
for (const entry of entries) {
|
|
32060
32276
|
if (entry.startsWith("exe")) {
|
|
32061
|
-
const fullPath =
|
|
32277
|
+
const fullPath = path49.join(skillsDir, entry);
|
|
32062
32278
|
if (!dryRun) rmSync(fullPath, { recursive: true, force: true });
|
|
32063
32279
|
skillCount++;
|
|
32064
32280
|
}
|
|
@@ -32070,9 +32286,9 @@ async function runClaudeUninstall(flags = []) {
|
|
|
32070
32286
|
removed++;
|
|
32071
32287
|
}
|
|
32072
32288
|
}
|
|
32073
|
-
const claudeMdPath =
|
|
32074
|
-
if (
|
|
32075
|
-
const content =
|
|
32289
|
+
const claudeMdPath = path49.join(claudeDir, "CLAUDE.md");
|
|
32290
|
+
if (existsSync35(claudeMdPath)) {
|
|
32291
|
+
const content = readFileSync30(claudeMdPath, "utf8");
|
|
32076
32292
|
const startMarker = "<!-- exe-os:orchestration-start -->";
|
|
32077
32293
|
const endMarker = "<!-- exe-os:orchestration-end -->";
|
|
32078
32294
|
const startIdx = content.indexOf(startMarker);
|
|
@@ -32084,16 +32300,16 @@ async function runClaudeUninstall(flags = []) {
|
|
|
32084
32300
|
removed++;
|
|
32085
32301
|
}
|
|
32086
32302
|
}
|
|
32087
|
-
const agentsDir =
|
|
32088
|
-
if (
|
|
32303
|
+
const agentsDir = path49.join(claudeDir, "agents");
|
|
32304
|
+
if (existsSync35(agentsDir)) {
|
|
32089
32305
|
let agentCount = 0;
|
|
32090
32306
|
try {
|
|
32091
32307
|
const entries = readdirSync10(agentsDir).filter((f) => f.endsWith(".md"));
|
|
32092
32308
|
let knownNames = /* @__PURE__ */ new Set();
|
|
32093
|
-
const rosterPath =
|
|
32094
|
-
if (
|
|
32309
|
+
const rosterPath = path49.join(exeOsDir, "exe-employees.json");
|
|
32310
|
+
if (existsSync35(rosterPath)) {
|
|
32095
32311
|
try {
|
|
32096
|
-
const roster = JSON.parse(
|
|
32312
|
+
const roster = JSON.parse(readFileSync30(rosterPath, "utf8"));
|
|
32097
32313
|
knownNames = new Set(roster.map((e) => e.name));
|
|
32098
32314
|
} catch {
|
|
32099
32315
|
}
|
|
@@ -32101,7 +32317,7 @@ async function runClaudeUninstall(flags = []) {
|
|
|
32101
32317
|
for (const entry of entries) {
|
|
32102
32318
|
const name = entry.replace(/\.md$/, "");
|
|
32103
32319
|
if (knownNames.has(name)) {
|
|
32104
|
-
if (!dryRun) rmSync(
|
|
32320
|
+
if (!dryRun) rmSync(path49.join(agentsDir, entry), { force: true });
|
|
32105
32321
|
agentCount++;
|
|
32106
32322
|
}
|
|
32107
32323
|
}
|
|
@@ -32112,16 +32328,16 @@ async function runClaudeUninstall(flags = []) {
|
|
|
32112
32328
|
removed++;
|
|
32113
32329
|
}
|
|
32114
32330
|
}
|
|
32115
|
-
const projectsDir =
|
|
32116
|
-
if (
|
|
32331
|
+
const projectsDir = path49.join(claudeDir, "projects");
|
|
32332
|
+
if (existsSync35(projectsDir)) {
|
|
32117
32333
|
let projectCount = 0;
|
|
32118
32334
|
try {
|
|
32119
32335
|
const projects = readdirSync10(projectsDir);
|
|
32120
32336
|
for (const proj of projects) {
|
|
32121
|
-
const projSettings =
|
|
32122
|
-
if (!
|
|
32337
|
+
const projSettings = path49.join(projectsDir, proj, "settings.json");
|
|
32338
|
+
if (!existsSync35(projSettings)) continue;
|
|
32123
32339
|
try {
|
|
32124
|
-
const pSettings = JSON.parse(
|
|
32340
|
+
const pSettings = JSON.parse(readFileSync30(projSettings, "utf8"));
|
|
32125
32341
|
let changed = false;
|
|
32126
32342
|
if (Array.isArray(pSettings.permissions?.allow)) {
|
|
32127
32343
|
const before = pSettings.permissions.allow.length;
|
|
@@ -32155,18 +32371,18 @@ async function runClaudeUninstall(flags = []) {
|
|
|
32155
32371
|
};
|
|
32156
32372
|
const exeBinPath = findExeBin3();
|
|
32157
32373
|
if (!exeBinPath) throw new Error("exe-os not found in PATH");
|
|
32158
|
-
const binDir =
|
|
32374
|
+
const binDir = path49.dirname(exeBinPath);
|
|
32159
32375
|
let symlinkCount = 0;
|
|
32160
|
-
const rosterPath =
|
|
32161
|
-
if (
|
|
32162
|
-
const roster = JSON.parse(
|
|
32376
|
+
const rosterPath = path49.join(exeOsDir, "exe-employees.json");
|
|
32377
|
+
if (existsSync35(rosterPath)) {
|
|
32378
|
+
const roster = JSON.parse(readFileSync30(rosterPath, "utf8"));
|
|
32163
32379
|
const { DEFAULT_COORDINATOR_TEMPLATE_NAME: DEFAULT_COORDINATOR_TEMPLATE_NAME2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
32164
32380
|
const coordinatorName = roster.find((e) => e.role?.toLowerCase() === "coo")?.name ?? DEFAULT_COORDINATOR_TEMPLATE_NAME2;
|
|
32165
32381
|
for (const emp of roster) {
|
|
32166
32382
|
if (emp.name === coordinatorName) continue;
|
|
32167
32383
|
for (const suffix of ["", "-opencode"]) {
|
|
32168
|
-
const linkPath =
|
|
32169
|
-
if (
|
|
32384
|
+
const linkPath = path49.join(binDir, `${emp.name}${suffix}`);
|
|
32385
|
+
if (existsSync35(linkPath)) {
|
|
32170
32386
|
if (!dryRun) rmSync(linkPath, { force: true });
|
|
32171
32387
|
symlinkCount++;
|
|
32172
32388
|
}
|
|
@@ -32179,7 +32395,7 @@ async function runClaudeUninstall(flags = []) {
|
|
|
32179
32395
|
}
|
|
32180
32396
|
} catch {
|
|
32181
32397
|
}
|
|
32182
|
-
if (purge &&
|
|
32398
|
+
if (purge && existsSync35(exeOsDir)) {
|
|
32183
32399
|
if (!dryRun) {
|
|
32184
32400
|
process.stdout.write("\x1B[33m\u26A0 This will delete all memories, identities, and agent data.\x1B[0m\n");
|
|
32185
32401
|
process.stdout.write(" Removing ~/.exe-os...\n");
|
|
@@ -32204,13 +32420,13 @@ async function checkForUpdateOnBoot() {
|
|
|
32204
32420
|
const config = await loadConfig2();
|
|
32205
32421
|
if (!config.autoUpdate.checkOnBoot) return;
|
|
32206
32422
|
const { checkForUpdate: checkForUpdate2 } = await Promise.resolve().then(() => (init_update(), update_exports));
|
|
32207
|
-
const packageRoot =
|
|
32423
|
+
const packageRoot = path49.resolve(
|
|
32208
32424
|
new URL("../..", import.meta.url).pathname
|
|
32209
32425
|
);
|
|
32210
32426
|
const result = checkForUpdate2(packageRoot);
|
|
32211
32427
|
if (result.updateAvailable) {
|
|
32212
32428
|
process.stderr.write(
|
|
32213
|
-
`\x1B[33m[update]\x1B[0m exe-os v${result.remoteVersion} available (current: v${result.localVersion}). Run \x1B[
|
|
32429
|
+
`\x1B[33m[update]\x1B[0m exe-os v${result.remoteVersion} available (current: v${result.localVersion}). Run \x1B[36mexe-os update\x1B[0m to upgrade.
|
|
32214
32430
|
`
|
|
32215
32431
|
);
|
|
32216
32432
|
}
|
|
@@ -32265,7 +32481,7 @@ async function runActivate(key) {
|
|
|
32265
32481
|
const idTemplate = getIdentityTemplate(identityKey);
|
|
32266
32482
|
if (idTemplate) {
|
|
32267
32483
|
const idPath = identityPath2(name);
|
|
32268
|
-
const dir =
|
|
32484
|
+
const dir = path49.dirname(idPath);
|
|
32269
32485
|
if (!fs8.existsSync(dir)) fs8.mkdirSync(dir, { recursive: true });
|
|
32270
32486
|
fs8.writeFileSync(idPath, idTemplate.replace(/^agent_id: \w+/m, `agent_id: ${name}`), "utf-8");
|
|
32271
32487
|
}
|
package/dist/bin/update.js
CHANGED
|
@@ -901,7 +901,20 @@ async function runUpdate(cliArgs) {
|
|
|
901
901
|
} catch {
|
|
902
902
|
}
|
|
903
903
|
}
|
|
904
|
-
console.log("
|
|
904
|
+
console.log("\u{1F527} Re-registering MCP, hooks, wrappers, and daemon...");
|
|
905
|
+
try {
|
|
906
|
+
execSync2("exe-os-install --global", {
|
|
907
|
+
stdio: ["pipe", "inherit", "inherit"],
|
|
908
|
+
timeout: 3e5
|
|
909
|
+
});
|
|
910
|
+
} catch (err) {
|
|
911
|
+
console.error("\n\u26A0\uFE0F Package updated, but post-update install failed.");
|
|
912
|
+
console.error(" Run manually: exe-os-install --global");
|
|
913
|
+
if (err instanceof Error && err.message) {
|
|
914
|
+
console.error(` Error: ${err.message.split("\n")[0]}`);
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
console.log(" MCP, hooks, and daemon refreshed.");
|
|
905
918
|
console.log("");
|
|
906
919
|
console.log(" \x1B[33m\u26A1 Run /mcp in each active Claude Code session to pick up new tools.\x1B[0m");
|
|
907
920
|
console.log(" \x1B[2m(MCP servers can't hot-reload \u2014 Claude Code needs to reconnect them.)\x1B[0m");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askexenow/exe-os",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.51",
|
|
4
4
|
"description": "AI employee operating system — persistent memory, task management, and multi-agent coordination for Claude Code.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"type": "module",
|