@askexenow/exe-os 0.9.68 → 0.9.69
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/cc-doctor.js +293 -30
- package/dist/bin/exe-healthcheck.js +293 -30
- package/dist/lib/exe-daemon.js +1183 -860
- package/dist/mcp/server.js +728 -530
- package/package.json +1 -1
package/dist/mcp/server.js
CHANGED
|
@@ -873,10 +873,10 @@ async function disposeEmbedder() {
|
|
|
873
873
|
async function embedDirect(text3) {
|
|
874
874
|
const llamaCpp = await import("node-llama-cpp");
|
|
875
875
|
const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
876
|
-
const { existsSync:
|
|
877
|
-
const
|
|
878
|
-
const modelPath =
|
|
879
|
-
if (!
|
|
876
|
+
const { existsSync: existsSync41 } = await import("fs");
|
|
877
|
+
const path52 = await import("path");
|
|
878
|
+
const modelPath = path52.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
|
|
879
|
+
if (!existsSync41(modelPath)) {
|
|
880
880
|
throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
|
|
881
881
|
}
|
|
882
882
|
const llama = await llamaCpp.getLlama();
|
|
@@ -3691,8 +3691,8 @@ function deriveMachineKey() {
|
|
|
3691
3691
|
}
|
|
3692
3692
|
function readMachineId() {
|
|
3693
3693
|
try {
|
|
3694
|
-
const { readFileSync:
|
|
3695
|
-
return
|
|
3694
|
+
const { readFileSync: readFileSync34 } = __require("fs");
|
|
3695
|
+
return readFileSync34("/etc/machine-id", "utf-8").trim();
|
|
3696
3696
|
} catch {
|
|
3697
3697
|
return "";
|
|
3698
3698
|
}
|
|
@@ -7267,10 +7267,10 @@ async function hybridSearch(queryText, agentId, options) {
|
|
|
7267
7267
|
};
|
|
7268
7268
|
try {
|
|
7269
7269
|
const fs = await import("fs");
|
|
7270
|
-
const
|
|
7270
|
+
const path52 = await import("path");
|
|
7271
7271
|
const os21 = await import("os");
|
|
7272
|
-
const logPath =
|
|
7273
|
-
fs.mkdirSync(
|
|
7272
|
+
const logPath = path52.join(os21.homedir(), ".exe-os", "search-quality.jsonl");
|
|
7273
|
+
fs.mkdirSync(path52.dirname(logPath), { recursive: true });
|
|
7274
7274
|
fs.appendFileSync(logPath, JSON.stringify(logEntry) + "\n");
|
|
7275
7275
|
} catch {
|
|
7276
7276
|
}
|
|
@@ -8223,8 +8223,8 @@ async function validateLicense(apiKey, deviceId) {
|
|
|
8223
8223
|
}
|
|
8224
8224
|
function getCacheAgeMs() {
|
|
8225
8225
|
try {
|
|
8226
|
-
const { statSync:
|
|
8227
|
-
const s =
|
|
8226
|
+
const { statSync: statSync10 } = __require("fs");
|
|
8227
|
+
const s = statSync10(CACHE_PATH);
|
|
8228
8228
|
return Date.now() - s.mtimeMs;
|
|
8229
8229
|
} catch {
|
|
8230
8230
|
return Infinity;
|
|
@@ -8562,8 +8562,8 @@ __export(wiki_client_exports, {
|
|
|
8562
8562
|
listDocuments: () => listDocuments,
|
|
8563
8563
|
listWorkspaces: () => listWorkspaces
|
|
8564
8564
|
});
|
|
8565
|
-
async function wikiFetch(config2,
|
|
8566
|
-
const url = `${config2.baseUrl}/api/v1${
|
|
8565
|
+
async function wikiFetch(config2, path52, method = "GET", body) {
|
|
8566
|
+
const url = `${config2.baseUrl}/api/v1${path52}`;
|
|
8567
8567
|
const headers = {
|
|
8568
8568
|
Authorization: `Bearer ${config2.apiKey}`,
|
|
8569
8569
|
"Content-Type": "application/json"
|
|
@@ -8596,7 +8596,7 @@ async function wikiFetch(config2, path50, method = "GET", body) {
|
|
|
8596
8596
|
}
|
|
8597
8597
|
}
|
|
8598
8598
|
if (!response.ok) {
|
|
8599
|
-
throw new Error(`Wiki API ${method} ${
|
|
8599
|
+
throw new Error(`Wiki API ${method} ${path52}: ${response.status} ${response.statusText}`);
|
|
8600
8600
|
}
|
|
8601
8601
|
return response.json();
|
|
8602
8602
|
} finally {
|
|
@@ -9436,8 +9436,8 @@ function logQueue(msg) {
|
|
|
9436
9436
|
process.stderr.write(`[intercom-queue] ${msg}
|
|
9437
9437
|
`);
|
|
9438
9438
|
try {
|
|
9439
|
-
const { appendFileSync:
|
|
9440
|
-
|
|
9439
|
+
const { appendFileSync: appendFileSync4 } = __require("fs");
|
|
9440
|
+
appendFileSync4(INTERCOM_LOG, line);
|
|
9441
9441
|
} catch {
|
|
9442
9442
|
}
|
|
9443
9443
|
}
|
|
@@ -13377,14 +13377,14 @@ __export(worker_gate_exports, {
|
|
|
13377
13377
|
tryAcquireBackfillLock: () => tryAcquireBackfillLock,
|
|
13378
13378
|
tryAcquireWorkerSlot: () => tryAcquireWorkerSlot
|
|
13379
13379
|
});
|
|
13380
|
-
import { readdirSync as readdirSync8, writeFileSync as
|
|
13381
|
-
import
|
|
13380
|
+
import { readdirSync as readdirSync8, writeFileSync as writeFileSync15, unlinkSync as unlinkSync8, mkdirSync as mkdirSync12, existsSync as existsSync26 } from "fs";
|
|
13381
|
+
import path31 from "path";
|
|
13382
13382
|
function tryAcquireWorkerSlot() {
|
|
13383
13383
|
try {
|
|
13384
|
-
|
|
13384
|
+
mkdirSync12(WORKER_PID_DIR, { recursive: true });
|
|
13385
13385
|
const reservationId = `res-${process.pid}-${Date.now()}`;
|
|
13386
|
-
const reservationPath =
|
|
13387
|
-
|
|
13386
|
+
const reservationPath = path31.join(WORKER_PID_DIR, `${reservationId}.pid`);
|
|
13387
|
+
writeFileSync15(reservationPath, String(process.pid));
|
|
13388
13388
|
const files = readdirSync8(WORKER_PID_DIR);
|
|
13389
13389
|
let alive = 0;
|
|
13390
13390
|
for (const f of files) {
|
|
@@ -13401,7 +13401,7 @@ function tryAcquireWorkerSlot() {
|
|
|
13401
13401
|
alive++;
|
|
13402
13402
|
} catch {
|
|
13403
13403
|
try {
|
|
13404
|
-
unlinkSync8(
|
|
13404
|
+
unlinkSync8(path31.join(WORKER_PID_DIR, f));
|
|
13405
13405
|
} catch {
|
|
13406
13406
|
}
|
|
13407
13407
|
}
|
|
@@ -13424,21 +13424,21 @@ function tryAcquireWorkerSlot() {
|
|
|
13424
13424
|
}
|
|
13425
13425
|
function registerWorkerPid(pid) {
|
|
13426
13426
|
try {
|
|
13427
|
-
|
|
13428
|
-
|
|
13427
|
+
mkdirSync12(WORKER_PID_DIR, { recursive: true });
|
|
13428
|
+
writeFileSync15(path31.join(WORKER_PID_DIR, `worker-${pid}.pid`), String(pid));
|
|
13429
13429
|
} catch {
|
|
13430
13430
|
}
|
|
13431
13431
|
}
|
|
13432
13432
|
function cleanupWorkerPid() {
|
|
13433
13433
|
try {
|
|
13434
|
-
unlinkSync8(
|
|
13434
|
+
unlinkSync8(path31.join(WORKER_PID_DIR, `worker-${process.pid}.pid`));
|
|
13435
13435
|
} catch {
|
|
13436
13436
|
}
|
|
13437
13437
|
}
|
|
13438
13438
|
function tryAcquireBackfillLock() {
|
|
13439
13439
|
try {
|
|
13440
|
-
|
|
13441
|
-
if (
|
|
13440
|
+
mkdirSync12(WORKER_PID_DIR, { recursive: true });
|
|
13441
|
+
if (existsSync26(BACKFILL_LOCK)) {
|
|
13442
13442
|
try {
|
|
13443
13443
|
const pid = parseInt(
|
|
13444
13444
|
__require("fs").readFileSync(BACKFILL_LOCK, "utf8").trim(),
|
|
@@ -13454,7 +13454,7 @@ function tryAcquireBackfillLock() {
|
|
|
13454
13454
|
} catch {
|
|
13455
13455
|
}
|
|
13456
13456
|
}
|
|
13457
|
-
|
|
13457
|
+
writeFileSync15(BACKFILL_LOCK, String(process.pid));
|
|
13458
13458
|
return true;
|
|
13459
13459
|
} catch {
|
|
13460
13460
|
return true;
|
|
@@ -13471,9 +13471,9 @@ var init_worker_gate = __esm({
|
|
|
13471
13471
|
"src/lib/worker-gate.ts"() {
|
|
13472
13472
|
"use strict";
|
|
13473
13473
|
init_config();
|
|
13474
|
-
WORKER_PID_DIR =
|
|
13474
|
+
WORKER_PID_DIR = path31.join(EXE_AI_DIR, "worker-pids");
|
|
13475
13475
|
MAX_CONCURRENT_WORKERS = 3;
|
|
13476
|
-
BACKFILL_LOCK =
|
|
13476
|
+
BACKFILL_LOCK = path31.join(WORKER_PID_DIR, "backfill.lock");
|
|
13477
13477
|
}
|
|
13478
13478
|
});
|
|
13479
13479
|
|
|
@@ -13484,16 +13484,16 @@ __export(key_backup_status_exports, {
|
|
|
13484
13484
|
keyBackupMarkerPath: () => keyBackupMarkerPath,
|
|
13485
13485
|
markKeyBackupConfirmed: () => markKeyBackupConfirmed
|
|
13486
13486
|
});
|
|
13487
|
-
import { existsSync as
|
|
13488
|
-
import
|
|
13487
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync13, readFileSync as readFileSync22, writeFileSync as writeFileSync16 } from "fs";
|
|
13488
|
+
import path33 from "path";
|
|
13489
13489
|
function keyBackupMarkerPath() {
|
|
13490
|
-
return
|
|
13490
|
+
return path33.join(EXE_AI_DIR, "key-backup-confirmed.json");
|
|
13491
13491
|
}
|
|
13492
13492
|
function getKeyBackupStatus() {
|
|
13493
13493
|
const marker = keyBackupMarkerPath();
|
|
13494
|
-
if (!
|
|
13494
|
+
if (!existsSync28(marker)) return { exists: false };
|
|
13495
13495
|
try {
|
|
13496
|
-
const parsed = JSON.parse(
|
|
13496
|
+
const parsed = JSON.parse(readFileSync22(marker, "utf8"));
|
|
13497
13497
|
return {
|
|
13498
13498
|
exists: true,
|
|
13499
13499
|
confirmedAt: parsed.confirmedAt,
|
|
@@ -13504,8 +13504,8 @@ function getKeyBackupStatus() {
|
|
|
13504
13504
|
}
|
|
13505
13505
|
}
|
|
13506
13506
|
function markKeyBackupConfirmed(source) {
|
|
13507
|
-
|
|
13508
|
-
|
|
13507
|
+
mkdirSync13(EXE_AI_DIR, { recursive: true, mode: 448 });
|
|
13508
|
+
writeFileSync16(
|
|
13509
13509
|
keyBackupMarkerPath(),
|
|
13510
13510
|
JSON.stringify({ confirmedAt: (/* @__PURE__ */ new Date()).toISOString(), source }, null, 2) + "\n",
|
|
13511
13511
|
{ mode: 384 }
|
|
@@ -13601,33 +13601,33 @@ __export(db_backup_exports, {
|
|
|
13601
13601
|
listBackups: () => listBackups,
|
|
13602
13602
|
rotateBackups: () => rotateBackups
|
|
13603
13603
|
});
|
|
13604
|
-
import { copyFileSync, existsSync as
|
|
13605
|
-
import
|
|
13604
|
+
import { copyFileSync, existsSync as existsSync29, mkdirSync as mkdirSync14, readdirSync as readdirSync10, unlinkSync as unlinkSync9, statSync as statSync6 } from "fs";
|
|
13605
|
+
import path34 from "path";
|
|
13606
13606
|
function findActiveDb() {
|
|
13607
13607
|
for (const name of DB_NAMES) {
|
|
13608
|
-
const p =
|
|
13609
|
-
if (
|
|
13608
|
+
const p = path34.join(EXE_AI_DIR, name);
|
|
13609
|
+
if (existsSync29(p)) return p;
|
|
13610
13610
|
}
|
|
13611
13611
|
return null;
|
|
13612
13612
|
}
|
|
13613
13613
|
function createBackup(reason = "manual") {
|
|
13614
13614
|
const dbPath = findActiveDb();
|
|
13615
13615
|
if (!dbPath) return null;
|
|
13616
|
-
|
|
13617
|
-
const dbName =
|
|
13616
|
+
mkdirSync14(BACKUP_DIR, { recursive: true });
|
|
13617
|
+
const dbName = path34.basename(dbPath, ".db");
|
|
13618
13618
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
13619
13619
|
const backupName = `${dbName}-${reason}-${timestamp}.db`;
|
|
13620
|
-
const backupPath =
|
|
13620
|
+
const backupPath = path34.join(BACKUP_DIR, backupName);
|
|
13621
13621
|
copyFileSync(dbPath, backupPath);
|
|
13622
13622
|
const walPath = dbPath + "-wal";
|
|
13623
|
-
if (
|
|
13623
|
+
if (existsSync29(walPath)) {
|
|
13624
13624
|
try {
|
|
13625
13625
|
copyFileSync(walPath, backupPath + "-wal");
|
|
13626
13626
|
} catch {
|
|
13627
13627
|
}
|
|
13628
13628
|
}
|
|
13629
13629
|
const shmPath = dbPath + "-shm";
|
|
13630
|
-
if (
|
|
13630
|
+
if (existsSync29(shmPath)) {
|
|
13631
13631
|
try {
|
|
13632
13632
|
copyFileSync(shmPath, backupPath + "-shm");
|
|
13633
13633
|
} catch {
|
|
@@ -13636,16 +13636,16 @@ function createBackup(reason = "manual") {
|
|
|
13636
13636
|
return backupPath;
|
|
13637
13637
|
}
|
|
13638
13638
|
function rotateBackups(keepDays = DEFAULT_KEEP_DAYS) {
|
|
13639
|
-
if (!
|
|
13639
|
+
if (!existsSync29(BACKUP_DIR)) return 0;
|
|
13640
13640
|
const cutoff = Date.now() - keepDays * 24 * 60 * 60 * 1e3;
|
|
13641
13641
|
let deleted = 0;
|
|
13642
13642
|
try {
|
|
13643
13643
|
const files = readdirSync10(BACKUP_DIR);
|
|
13644
13644
|
for (const file of files) {
|
|
13645
13645
|
if (!file.endsWith(".db") && !file.endsWith(".db-wal") && !file.endsWith(".db-shm")) continue;
|
|
13646
|
-
const filePath =
|
|
13646
|
+
const filePath = path34.join(BACKUP_DIR, file);
|
|
13647
13647
|
try {
|
|
13648
|
-
const stat =
|
|
13648
|
+
const stat = statSync6(filePath);
|
|
13649
13649
|
if (stat.mtimeMs < cutoff) {
|
|
13650
13650
|
unlinkSync9(filePath);
|
|
13651
13651
|
deleted++;
|
|
@@ -13658,12 +13658,12 @@ function rotateBackups(keepDays = DEFAULT_KEEP_DAYS) {
|
|
|
13658
13658
|
return deleted;
|
|
13659
13659
|
}
|
|
13660
13660
|
function listBackups() {
|
|
13661
|
-
if (!
|
|
13661
|
+
if (!existsSync29(BACKUP_DIR)) return [];
|
|
13662
13662
|
try {
|
|
13663
13663
|
const files = readdirSync10(BACKUP_DIR).filter((f) => f.endsWith(".db") && !f.endsWith("-wal") && !f.endsWith("-shm"));
|
|
13664
13664
|
return files.map((name) => {
|
|
13665
|
-
const p =
|
|
13666
|
-
const stat =
|
|
13665
|
+
const p = path34.join(BACKUP_DIR, name);
|
|
13666
|
+
const stat = statSync6(p);
|
|
13667
13667
|
return { path: p, name, size: stat.size, date: stat.mtime };
|
|
13668
13668
|
}).sort((a, b) => b.date.getTime() - a.date.getTime());
|
|
13669
13669
|
} catch {
|
|
@@ -13687,7 +13687,7 @@ var init_db_backup = __esm({
|
|
|
13687
13687
|
"src/lib/db-backup.ts"() {
|
|
13688
13688
|
"use strict";
|
|
13689
13689
|
init_config();
|
|
13690
|
-
BACKUP_DIR =
|
|
13690
|
+
BACKUP_DIR = path34.join(EXE_AI_DIR, "backups");
|
|
13691
13691
|
DEFAULT_KEEP_DAYS = 3;
|
|
13692
13692
|
DB_NAMES = ["memories.db", "exe-mem.db", "exe-os.db", "exe.db"];
|
|
13693
13693
|
}
|
|
@@ -13712,9 +13712,9 @@ __export(crdt_sync_exports, {
|
|
|
13712
13712
|
rebuildFromDb: () => rebuildFromDb
|
|
13713
13713
|
});
|
|
13714
13714
|
import * as Y from "yjs";
|
|
13715
|
-
import { readFileSync as
|
|
13716
|
-
import
|
|
13717
|
-
import { homedir as
|
|
13715
|
+
import { readFileSync as readFileSync24, writeFileSync as writeFileSync17, existsSync as existsSync31, mkdirSync as mkdirSync15, unlinkSync as unlinkSync10 } from "fs";
|
|
13716
|
+
import path36 from "path";
|
|
13717
|
+
import { homedir as homedir6 } from "os";
|
|
13718
13718
|
function getStatePath() {
|
|
13719
13719
|
return _statePathOverride ?? DEFAULT_STATE_PATH;
|
|
13720
13720
|
}
|
|
@@ -13725,9 +13725,9 @@ function initCrdtDoc() {
|
|
|
13725
13725
|
if (doc) return doc;
|
|
13726
13726
|
doc = new Y.Doc();
|
|
13727
13727
|
const sp = getStatePath();
|
|
13728
|
-
if (
|
|
13728
|
+
if (existsSync31(sp)) {
|
|
13729
13729
|
try {
|
|
13730
|
-
const state =
|
|
13730
|
+
const state = readFileSync24(sp);
|
|
13731
13731
|
Y.applyUpdate(doc, new Uint8Array(state));
|
|
13732
13732
|
} catch {
|
|
13733
13733
|
console.warn("[crdt-sync] WARN: corrupted state file, rebuilding from DB");
|
|
@@ -13869,10 +13869,10 @@ function persistState() {
|
|
|
13869
13869
|
if (!doc) return;
|
|
13870
13870
|
try {
|
|
13871
13871
|
const sp = getStatePath();
|
|
13872
|
-
const dir =
|
|
13873
|
-
if (!
|
|
13872
|
+
const dir = path36.dirname(sp);
|
|
13873
|
+
if (!existsSync31(dir)) mkdirSync15(dir, { recursive: true });
|
|
13874
13874
|
const state = Y.encodeStateAsUpdate(doc);
|
|
13875
|
-
|
|
13875
|
+
writeFileSync17(sp, Buffer.from(state));
|
|
13876
13876
|
} catch {
|
|
13877
13877
|
}
|
|
13878
13878
|
}
|
|
@@ -13913,7 +13913,7 @@ var DEFAULT_STATE_PATH, _statePathOverride, doc;
|
|
|
13913
13913
|
var init_crdt_sync = __esm({
|
|
13914
13914
|
"src/lib/crdt-sync.ts"() {
|
|
13915
13915
|
"use strict";
|
|
13916
|
-
DEFAULT_STATE_PATH =
|
|
13916
|
+
DEFAULT_STATE_PATH = path36.join(homedir6(), ".exe-os", "crdt-state.bin");
|
|
13917
13917
|
_statePathOverride = null;
|
|
13918
13918
|
doc = null;
|
|
13919
13919
|
}
|
|
@@ -13926,10 +13926,10 @@ init_database();
|
|
|
13926
13926
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
13927
13927
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
13928
13928
|
import { spawn as spawn4 } from "child_process";
|
|
13929
|
-
import { existsSync as
|
|
13930
|
-
import
|
|
13929
|
+
import { existsSync as existsSync40, openSync as openSync4, mkdirSync as mkdirSync22, closeSync as closeSync4, readFileSync as readFileSync33 } from "fs";
|
|
13930
|
+
import path51 from "path";
|
|
13931
13931
|
import os20 from "os";
|
|
13932
|
-
import { fileURLToPath as
|
|
13932
|
+
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
13933
13933
|
|
|
13934
13934
|
// src/mcp/tools/memory.ts
|
|
13935
13935
|
import { z as z10 } from "zod";
|
|
@@ -15313,10 +15313,10 @@ function registerCreateTask(server2) {
|
|
|
15313
15313
|
skipDispatch: true
|
|
15314
15314
|
});
|
|
15315
15315
|
try {
|
|
15316
|
-
const { existsSync:
|
|
15316
|
+
const { existsSync: existsSync41, mkdirSync: mkdirSync23, writeFileSync: writeFileSync24 } = await import("fs");
|
|
15317
15317
|
const { identityPath: identityPath2 } = await Promise.resolve().then(() => (init_identity(), identity_exports));
|
|
15318
15318
|
const idPath = identityPath2(assigned_to);
|
|
15319
|
-
if (!
|
|
15319
|
+
if (!existsSync41(idPath)) {
|
|
15320
15320
|
const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
15321
15321
|
const employees = await loadEmployees2();
|
|
15322
15322
|
const emp = employees.find((e) => e.name === assigned_to);
|
|
@@ -15325,8 +15325,8 @@ function registerCreateTask(server2) {
|
|
|
15325
15325
|
const template = getTemplateForTitle2(emp.role);
|
|
15326
15326
|
if (template) {
|
|
15327
15327
|
const dir = (await import("path")).dirname(idPath);
|
|
15328
|
-
if (!
|
|
15329
|
-
|
|
15328
|
+
if (!existsSync41(dir)) mkdirSync23(dir, { recursive: true });
|
|
15329
|
+
writeFileSync24(idPath, template.replace(/^agent_id: \w+/m, `agent_id: ${assigned_to}`), "utf-8");
|
|
15330
15330
|
}
|
|
15331
15331
|
}
|
|
15332
15332
|
}
|
|
@@ -18288,12 +18288,12 @@ function registerExportGraph(server2) {
|
|
|
18288
18288
|
}
|
|
18289
18289
|
const html = await exportGraphHTML(client);
|
|
18290
18290
|
const fs = await import("fs");
|
|
18291
|
-
const
|
|
18291
|
+
const path52 = await import("path");
|
|
18292
18292
|
const os21 = await import("os");
|
|
18293
|
-
const outDir =
|
|
18293
|
+
const outDir = path52.join(os21.homedir(), ".exe-os", "exports");
|
|
18294
18294
|
fs.mkdirSync(outDir, { recursive: true });
|
|
18295
18295
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
18296
|
-
const filePath =
|
|
18296
|
+
const filePath = path52.join(outDir, `graph-${timestamp}.html`);
|
|
18297
18297
|
fs.writeFileSync(filePath, html, "utf-8");
|
|
18298
18298
|
return {
|
|
18299
18299
|
content: [
|
|
@@ -18808,7 +18808,7 @@ function registerGraph(server2) {
|
|
|
18808
18808
|
}
|
|
18809
18809
|
|
|
18810
18810
|
// src/mcp/tools/config.ts
|
|
18811
|
-
import { z as
|
|
18811
|
+
import { z as z74 } from "zod";
|
|
18812
18812
|
|
|
18813
18813
|
// src/mcp/tools/set-agent-config.ts
|
|
18814
18814
|
init_active_agent();
|
|
@@ -19346,10 +19346,133 @@ function registerGetSessionKills(server2) {
|
|
|
19346
19346
|
|
|
19347
19347
|
// src/mcp/tools/get-daemon-health.ts
|
|
19348
19348
|
import { z as z53 } from "zod";
|
|
19349
|
-
import { existsSync as
|
|
19350
|
-
import
|
|
19349
|
+
import { existsSync as existsSync23, readFileSync as readFileSync19 } from "fs";
|
|
19350
|
+
import path29 from "path";
|
|
19351
19351
|
import { homedir as homedir3 } from "os";
|
|
19352
|
-
|
|
19352
|
+
|
|
19353
|
+
// src/lib/mcp-transport-health.ts
|
|
19354
|
+
init_config();
|
|
19355
|
+
import { appendFileSync as appendFileSync2, closeSync as closeSync2, existsSync as existsSync22, mkdirSync as mkdirSync11, openSync as openSync2, readFileSync as readFileSync18, readSync, statSync as statSync5, writeFileSync as writeFileSync13 } from "fs";
|
|
19356
|
+
import path28 from "path";
|
|
19357
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
19358
|
+
var MCP_HTTP_EVENTS_PATH = path28.join(EXE_AI_DIR, "mcp-http-events.jsonl");
|
|
19359
|
+
var MCP_MONITOR_DIR = path28.join(EXE_AI_DIR, "monitor");
|
|
19360
|
+
var MCP_TRANSPORT_SUMMARY_PATH = path28.join(MCP_MONITOR_DIR, "mcp-transport-summary.json");
|
|
19361
|
+
var DEFAULT_EVENT_READ_BYTES = 256 * 1024;
|
|
19362
|
+
var DEFAULT_EVENT_MAX_BYTES = 1024 * 1024;
|
|
19363
|
+
var EVENT_READ_BYTES = parsePositiveInt(process.env.EXE_MCP_HTTP_EVENT_READ_BYTES, DEFAULT_EVENT_READ_BYTES);
|
|
19364
|
+
var EVENT_MAX_BYTES = parsePositiveInt(process.env.EXE_MCP_HTTP_EVENT_MAX_BYTES, DEFAULT_EVENT_MAX_BYTES);
|
|
19365
|
+
function parsePositiveInt(value, fallback) {
|
|
19366
|
+
if (!value) return fallback;
|
|
19367
|
+
const parsed = Number.parseInt(value, 10);
|
|
19368
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
19369
|
+
}
|
|
19370
|
+
function readTailText(filePath, maxBytes) {
|
|
19371
|
+
const stats = statSync5(filePath);
|
|
19372
|
+
if (stats.size <= maxBytes) return readFileSync18(filePath, "utf8");
|
|
19373
|
+
const fd = openSync2(filePath, "r");
|
|
19374
|
+
try {
|
|
19375
|
+
const buffer = Buffer.allocUnsafe(maxBytes);
|
|
19376
|
+
readSync(fd, buffer, 0, maxBytes, stats.size - maxBytes);
|
|
19377
|
+
const text3 = buffer.toString("utf8");
|
|
19378
|
+
const firstNewline = text3.indexOf("\n");
|
|
19379
|
+
return firstNewline >= 0 ? text3.slice(firstNewline + 1) : text3;
|
|
19380
|
+
} finally {
|
|
19381
|
+
closeSync2(fd);
|
|
19382
|
+
}
|
|
19383
|
+
}
|
|
19384
|
+
function readPackageVersion() {
|
|
19385
|
+
let dir = path28.dirname(fileURLToPath3(import.meta.url));
|
|
19386
|
+
const { root } = path28.parse(dir);
|
|
19387
|
+
while (dir !== root) {
|
|
19388
|
+
const pkgPath = path28.join(dir, "package.json");
|
|
19389
|
+
if (existsSync22(pkgPath)) {
|
|
19390
|
+
try {
|
|
19391
|
+
const parsed = JSON.parse(readFileSync18(pkgPath, "utf8"));
|
|
19392
|
+
return parsed.version ?? "unknown";
|
|
19393
|
+
} catch {
|
|
19394
|
+
return "unknown";
|
|
19395
|
+
}
|
|
19396
|
+
}
|
|
19397
|
+
dir = path28.dirname(dir);
|
|
19398
|
+
}
|
|
19399
|
+
return "unknown";
|
|
19400
|
+
}
|
|
19401
|
+
function parseMcpHttpEventLines(raw, limit = 200) {
|
|
19402
|
+
const lines = raw.trim().split("\n").filter(Boolean).slice(-limit);
|
|
19403
|
+
const events = [];
|
|
19404
|
+
for (const line of lines) {
|
|
19405
|
+
try {
|
|
19406
|
+
events.push(JSON.parse(line));
|
|
19407
|
+
} catch {
|
|
19408
|
+
}
|
|
19409
|
+
}
|
|
19410
|
+
return events;
|
|
19411
|
+
}
|
|
19412
|
+
function readMcpHttpEvents(limit = 200) {
|
|
19413
|
+
if (!existsSync22(MCP_HTTP_EVENTS_PATH)) return [];
|
|
19414
|
+
const raw = readTailText(MCP_HTTP_EVENTS_PATH, EVENT_READ_BYTES);
|
|
19415
|
+
return parseMcpHttpEventLines(raw, limit);
|
|
19416
|
+
}
|
|
19417
|
+
function summarizeMcpTransport(events = readMcpHttpEvents()) {
|
|
19418
|
+
const lastServerStartIndex = events.map((event) => event.message).lastIndexOf("server_started");
|
|
19419
|
+
const scopedEvents = lastServerStartIndex >= 0 ? events.slice(lastServerStartIndex) : events;
|
|
19420
|
+
const activeSessionEvent = [...scopedEvents].reverse().find((event) => typeof event.activeSessions === "number");
|
|
19421
|
+
const successfulToolCalls = scopedEvents.filter((event) => event.message === "tool_call_ok");
|
|
19422
|
+
const lastSuccessfulToolCall = successfulToolCalls.at(-1) ?? null;
|
|
19423
|
+
const summary = {
|
|
19424
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19425
|
+
version: readPackageVersion(),
|
|
19426
|
+
scope: "local",
|
|
19427
|
+
privacy: "metadata_only",
|
|
19428
|
+
eventLogPath: MCP_HTTP_EVENTS_PATH,
|
|
19429
|
+
activeSessions: activeSessionEvent?.activeSessions ?? null,
|
|
19430
|
+
sessionsCreated: scopedEvents.filter((event) => event.message === "session_initialized").length,
|
|
19431
|
+
sessionsClosed: scopedEvents.filter((event) => event.message === "session_closed").length,
|
|
19432
|
+
missingSessionErrors: scopedEvents.filter((event) => event.message?.includes("missing MCP session")).length,
|
|
19433
|
+
staleSessionErrors: scopedEvents.filter((event) => event.message?.includes("stale or unknown")).length,
|
|
19434
|
+
transportErrors: scopedEvents.filter((event) => event.level === "warn" || event.level === "error").length,
|
|
19435
|
+
lastSuccessfulHandshake: scopedEvents.filter((event) => event.message === "session_initialized").at(-1)?.timestamp ?? null,
|
|
19436
|
+
lastSuccessfulToolCall: lastSuccessfulToolCall?.timestamp ?? null,
|
|
19437
|
+
lastSuccessfulToolCallByRuntime: {},
|
|
19438
|
+
lastSuccessfulToolCallByAgent: {},
|
|
19439
|
+
lastSuccessfulToolCallByFamily: {},
|
|
19440
|
+
activeSessionsByRuntime: {},
|
|
19441
|
+
recentWarnings: scopedEvents.filter((event) => event.level === "warn" || event.level === "error").slice(-10),
|
|
19442
|
+
remediation: [
|
|
19443
|
+
"If MCP tools fail with missing/stale session, reconnect the MCP client (/mcp or restart the runtime).",
|
|
19444
|
+
"Do not access the database directly; MCP is the only data interface.",
|
|
19445
|
+
"Check get_daemon_health or exe-healthcheck for daemon/MCP endpoint status before retrying work."
|
|
19446
|
+
]
|
|
19447
|
+
};
|
|
19448
|
+
const createdBySession = /* @__PURE__ */ new Map();
|
|
19449
|
+
for (const event of scopedEvents) {
|
|
19450
|
+
if (event.message === "session_initialized" && event.sessionId) createdBySession.set(event.sessionId, event);
|
|
19451
|
+
if ((event.message === "session_closed" || event.message === "session_expired") && event.sessionId) {
|
|
19452
|
+
createdBySession.delete(event.sessionId);
|
|
19453
|
+
}
|
|
19454
|
+
}
|
|
19455
|
+
for (const event of createdBySession.values()) {
|
|
19456
|
+
const runtime = event.runtime ?? "Unknown";
|
|
19457
|
+
summary.activeSessionsByRuntime[runtime] = (summary.activeSessionsByRuntime[runtime] ?? 0) + 1;
|
|
19458
|
+
}
|
|
19459
|
+
for (const event of successfulToolCalls) {
|
|
19460
|
+
if (event.runtime) summary.lastSuccessfulToolCallByRuntime[event.runtime] = event.timestamp ?? "";
|
|
19461
|
+
if (event.agentId) summary.lastSuccessfulToolCallByAgent[event.agentId] = event.timestamp ?? "";
|
|
19462
|
+
if (event.toolFamily) summary.lastSuccessfulToolCallByFamily[event.toolFamily] = event.timestamp ?? "";
|
|
19463
|
+
}
|
|
19464
|
+
return summary;
|
|
19465
|
+
}
|
|
19466
|
+
function writeMcpTransportSummary(events) {
|
|
19467
|
+
try {
|
|
19468
|
+
mkdirSync11(MCP_MONITOR_DIR, { recursive: true });
|
|
19469
|
+
writeFileSync13(MCP_TRANSPORT_SUMMARY_PATH, JSON.stringify(summarizeMcpTransport(events), null, 2) + "\n");
|
|
19470
|
+
} catch {
|
|
19471
|
+
}
|
|
19472
|
+
}
|
|
19473
|
+
|
|
19474
|
+
// src/mcp/tools/get-daemon-health.ts
|
|
19475
|
+
var PID_PATH2 = path29.join(homedir3(), ".exe-os", "exed.pid");
|
|
19353
19476
|
function formatUptime(seconds) {
|
|
19354
19477
|
const h = Math.floor(seconds / 3600);
|
|
19355
19478
|
const m = Math.floor(seconds % 3600 / 60);
|
|
@@ -19360,8 +19483,8 @@ function formatUptime(seconds) {
|
|
|
19360
19483
|
}
|
|
19361
19484
|
function isDaemonAlive() {
|
|
19362
19485
|
try {
|
|
19363
|
-
if (!
|
|
19364
|
-
const pid = parseInt(
|
|
19486
|
+
if (!existsSync23(PID_PATH2)) return { alive: false, pid: null };
|
|
19487
|
+
const pid = parseInt(readFileSync19(PID_PATH2, "utf8").trim(), 10);
|
|
19365
19488
|
if (isNaN(pid) || pid <= 0) return { alive: false, pid: null };
|
|
19366
19489
|
process.kill(pid, 0);
|
|
19367
19490
|
return { alive: true, pid };
|
|
@@ -19408,6 +19531,27 @@ function registerGetDaemonHealth(server2) {
|
|
|
19408
19531
|
lines.push(`| Uptime | ${formatUptime(health.uptime)} |`);
|
|
19409
19532
|
lines.push(`| Requests served | ${health.requests_served.toLocaleString()} |`);
|
|
19410
19533
|
}
|
|
19534
|
+
const events = readMcpHttpEvents(50);
|
|
19535
|
+
const summary = summarizeMcpTransport(events);
|
|
19536
|
+
const lastEvent = events.at(-1);
|
|
19537
|
+
lines.push(`| MCP HTTP events | ${events.length > 0 ? `${events.length} recent` : "none recorded"} |`);
|
|
19538
|
+
lines.push(`| MCP HTTP active sessions | ${summary.activeSessions ?? "unknown"} |`);
|
|
19539
|
+
lines.push(`| Last MCP handshake | ${summary.lastSuccessfulHandshake ?? "none"} |`);
|
|
19540
|
+
lines.push(`| Last MCP tool call | ${summary.lastSuccessfulToolCall ?? "none"} |`);
|
|
19541
|
+
lines.push(`| MCP monitor summary | ${summary.eventLogPath.replace("mcp-http-events.jsonl", "monitor/mcp-transport-summary.json")} |`);
|
|
19542
|
+
if (lastEvent) {
|
|
19543
|
+
lines.push(`| Last MCP HTTP event | ${lastEvent.timestamp ?? "unknown"} ${lastEvent.message ?? "unknown"} |`);
|
|
19544
|
+
}
|
|
19545
|
+
if (summary.recentWarnings.length > 0) {
|
|
19546
|
+
lines.push("\n### Recent MCP HTTP warnings");
|
|
19547
|
+
for (const event of summary.recentWarnings.slice(-5)) {
|
|
19548
|
+
lines.push(
|
|
19549
|
+
`- ${event.timestamp ?? "unknown"} \u2014 ${event.message ?? "unknown"} (agent=${event.agentId ?? "unknown"}, session=${event.sessionId ?? "none"})`
|
|
19550
|
+
);
|
|
19551
|
+
}
|
|
19552
|
+
}
|
|
19553
|
+
lines.push("\n### Agent remediation");
|
|
19554
|
+
for (const item of summary.remediation) lines.push(`- ${item}`);
|
|
19411
19555
|
return {
|
|
19412
19556
|
content: [{ type: "text", text: lines.join("\n") }]
|
|
19413
19557
|
};
|
|
@@ -19425,24 +19569,73 @@ function registerGetDaemonHealth(server2) {
|
|
|
19425
19569
|
);
|
|
19426
19570
|
}
|
|
19427
19571
|
|
|
19572
|
+
// src/mcp/tools/mcp-ping.ts
|
|
19573
|
+
import { existsSync as existsSync24, readFileSync as readFileSync20 } from "fs";
|
|
19574
|
+
import path30 from "path";
|
|
19575
|
+
import { homedir as homedir4 } from "os";
|
|
19576
|
+
import { z as z54 } from "zod";
|
|
19577
|
+
var PID_PATH3 = path30.join(homedir4(), ".exe-os", "exed.pid");
|
|
19578
|
+
function isDaemonAlive2() {
|
|
19579
|
+
try {
|
|
19580
|
+
if (!existsSync24(PID_PATH3)) return { alive: false, pid: null };
|
|
19581
|
+
const pid = parseInt(readFileSync20(PID_PATH3, "utf8").trim(), 10);
|
|
19582
|
+
if (!Number.isFinite(pid) || pid <= 0) return { alive: false, pid: null };
|
|
19583
|
+
process.kill(pid, 0);
|
|
19584
|
+
return { alive: true, pid };
|
|
19585
|
+
} catch {
|
|
19586
|
+
return { alive: false, pid: null };
|
|
19587
|
+
}
|
|
19588
|
+
}
|
|
19589
|
+
function registerMcpPing(server2) {
|
|
19590
|
+
server2.registerTool(
|
|
19591
|
+
"mcp_ping",
|
|
19592
|
+
{
|
|
19593
|
+
title: "MCP Ping",
|
|
19594
|
+
description: "Safe local MCP synthetic probe: daemon liveness plus privacy-safe transport/session summary.",
|
|
19595
|
+
inputSchema: {
|
|
19596
|
+
_placeholder: z54.string().optional().describe("No input required")
|
|
19597
|
+
}
|
|
19598
|
+
},
|
|
19599
|
+
async () => {
|
|
19600
|
+
const daemon = isDaemonAlive2();
|
|
19601
|
+
const summary = summarizeMcpTransport();
|
|
19602
|
+
writeMcpTransportSummary();
|
|
19603
|
+
const status = daemon.alive ? "ok" : "degraded";
|
|
19604
|
+
return {
|
|
19605
|
+
content: [
|
|
19606
|
+
{
|
|
19607
|
+
type: "text",
|
|
19608
|
+
text: JSON.stringify({
|
|
19609
|
+
status,
|
|
19610
|
+
daemon,
|
|
19611
|
+
mcpTransport: summary,
|
|
19612
|
+
remediation: daemon.alive ? "MCP transport probe reached the server. If tools still fail, reconnect the MCP client." : "Daemon is offline. Restart exe-os/exed; do not bypass MCP or access the DB directly."
|
|
19613
|
+
}, null, 2)
|
|
19614
|
+
}
|
|
19615
|
+
]
|
|
19616
|
+
};
|
|
19617
|
+
}
|
|
19618
|
+
);
|
|
19619
|
+
}
|
|
19620
|
+
|
|
19428
19621
|
// src/mcp/tools/get-auto-wake-status.ts
|
|
19429
19622
|
init_database();
|
|
19430
19623
|
init_session_registry();
|
|
19431
|
-
import { z as
|
|
19624
|
+
import { z as z55 } from "zod";
|
|
19432
19625
|
|
|
19433
19626
|
// src/lib/daemon-orchestration.ts
|
|
19434
19627
|
init_tmux_routing();
|
|
19435
19628
|
init_task_scope();
|
|
19436
19629
|
init_employees();
|
|
19437
19630
|
import { execSync as execSync10 } from "child_process";
|
|
19438
|
-
import { existsSync as
|
|
19439
|
-
import { homedir as
|
|
19631
|
+
import { existsSync as existsSync25, readFileSync as readFileSync21, writeFileSync as writeFileSync14 } from "fs";
|
|
19632
|
+
import { homedir as homedir5 } from "os";
|
|
19440
19633
|
import { join as join3 } from "path";
|
|
19441
19634
|
var IDLE_NUDGE_DEDUP_MS = Number(process.env.EXE_NUDGE_INTERVAL_MS) || 6e4;
|
|
19442
19635
|
var SESSION_TTL_HOURS = Number(process.env.EXE_SESSION_TTL_HOURS) || 4;
|
|
19443
19636
|
var SESSION_CONTEXT_THRESHOLD_PCT = Number(process.env.EXE_CONTEXT_KILL_PCT) || 50;
|
|
19444
19637
|
var IDLE_KILL_INTERCOM_ACK_WINDOW_MS = Number(process.env.EXE_INTERCOM_ACK_WINDOW_MS) || 1e4;
|
|
19445
|
-
var NUDGE_STATE_PATH = join3(
|
|
19638
|
+
var NUDGE_STATE_PATH = join3(homedir5(), ".exe-os", "review-nudge-state.json");
|
|
19446
19639
|
var AUTO_WAKE_COOLDOWN_MS = 5 * 60 * 1e3;
|
|
19447
19640
|
var AUTO_WAKE_MAX_RETRIES = 3;
|
|
19448
19641
|
|
|
@@ -19456,7 +19649,7 @@ function registerGetAutoWakeStatus(server2) {
|
|
|
19456
19649
|
title: "Get Auto-Wake Status",
|
|
19457
19650
|
description: "Check auto-wake status: orphaned tasks (assigned agent has no running session), tasks blocked by auto-wake retry limit, and session activity.",
|
|
19458
19651
|
inputSchema: {
|
|
19459
|
-
_placeholder:
|
|
19652
|
+
_placeholder: z55.string().optional().describe("No input required")
|
|
19460
19653
|
}
|
|
19461
19654
|
},
|
|
19462
19655
|
async () => {
|
|
@@ -19537,16 +19730,16 @@ function registerGetAutoWakeStatus(server2) {
|
|
|
19537
19730
|
// src/mcp/tools/get-worker-gate.ts
|
|
19538
19731
|
init_worker_gate();
|
|
19539
19732
|
init_config();
|
|
19540
|
-
import { z as
|
|
19541
|
-
import { readdirSync as readdirSync9, existsSync as
|
|
19542
|
-
import
|
|
19543
|
-
var WORKER_PID_DIR2 =
|
|
19733
|
+
import { z as z56 } from "zod";
|
|
19734
|
+
import { readdirSync as readdirSync9, existsSync as existsSync27 } from "fs";
|
|
19735
|
+
import path32 from "path";
|
|
19736
|
+
var WORKER_PID_DIR2 = path32.join(EXE_AI_DIR, "worker-pids");
|
|
19544
19737
|
function countAliveWorkers() {
|
|
19545
19738
|
let alive = 0;
|
|
19546
19739
|
let stale = 0;
|
|
19547
19740
|
let reservations = 0;
|
|
19548
19741
|
try {
|
|
19549
|
-
if (!
|
|
19742
|
+
if (!existsSync27(WORKER_PID_DIR2)) return { alive: 0, stale: 0, reservations: 0 };
|
|
19550
19743
|
const files = readdirSync9(WORKER_PID_DIR2);
|
|
19551
19744
|
for (const f of files) {
|
|
19552
19745
|
if (!f.endsWith(".pid")) continue;
|
|
@@ -19575,7 +19768,7 @@ function registerGetWorkerGate(server2) {
|
|
|
19575
19768
|
title: "Get Worker Gate",
|
|
19576
19769
|
description: "Check worker concurrency gate status: how many worker slots are in use, the maximum allowed, and whether new workers can spawn.",
|
|
19577
19770
|
inputSchema: {
|
|
19578
|
-
_placeholder:
|
|
19771
|
+
_placeholder: z56.string().optional().describe("No input required")
|
|
19579
19772
|
}
|
|
19580
19773
|
},
|
|
19581
19774
|
async () => {
|
|
@@ -19611,20 +19804,20 @@ function registerGetWorkerGate(server2) {
|
|
|
19611
19804
|
|
|
19612
19805
|
// src/mcp/tools/run-memory-audit.ts
|
|
19613
19806
|
init_database();
|
|
19614
|
-
import { z as
|
|
19807
|
+
import { z as z57 } from "zod";
|
|
19615
19808
|
|
|
19616
19809
|
// src/bin/exe-doctor.ts
|
|
19617
19810
|
import os14 from "os";
|
|
19618
19811
|
|
|
19619
19812
|
// src/lib/is-main.ts
|
|
19620
19813
|
import { realpathSync } from "fs";
|
|
19621
|
-
import { fileURLToPath as
|
|
19814
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
19622
19815
|
function isMainModule(importMetaUrl) {
|
|
19623
19816
|
if (process.argv[1] == null) return false;
|
|
19624
19817
|
if (process.argv[1].includes("mcp/server")) return false;
|
|
19625
19818
|
try {
|
|
19626
19819
|
const scriptPath = realpathSync(process.argv[1]);
|
|
19627
|
-
const modulePath = realpathSync(
|
|
19820
|
+
const modulePath = realpathSync(fileURLToPath4(importMetaUrl));
|
|
19628
19821
|
return scriptPath === modulePath;
|
|
19629
19822
|
} catch {
|
|
19630
19823
|
return importMetaUrl === `file://${process.argv[1]}` || importMetaUrl === new URL(process.argv[1], "file://").href;
|
|
@@ -19632,9 +19825,9 @@ function isMainModule(importMetaUrl) {
|
|
|
19632
19825
|
}
|
|
19633
19826
|
|
|
19634
19827
|
// src/bin/exe-doctor.ts
|
|
19635
|
-
import { existsSync as
|
|
19828
|
+
import { existsSync as existsSync30, readFileSync as readFileSync23 } from "fs";
|
|
19636
19829
|
import { spawn as spawn2 } from "child_process";
|
|
19637
|
-
import
|
|
19830
|
+
import path35 from "path";
|
|
19638
19831
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
19639
19832
|
|
|
19640
19833
|
// src/lib/conflict-detector.ts
|
|
@@ -20182,7 +20375,7 @@ async function auditOrphanedProjects(client) {
|
|
|
20182
20375
|
for (const row of result2.rows) {
|
|
20183
20376
|
const name = row.project_name;
|
|
20184
20377
|
const count = Number(row.cnt);
|
|
20185
|
-
const exists =
|
|
20378
|
+
const exists = existsSync30(path35.join(home, name)) || existsSync30(path35.join(home, "..", name)) || existsSync30(path35.join(process.cwd(), "..", name));
|
|
20186
20379
|
if (!exists) {
|
|
20187
20380
|
orphans.push({ project_name: name, count });
|
|
20188
20381
|
}
|
|
@@ -20190,18 +20383,18 @@ async function auditOrphanedProjects(client) {
|
|
|
20190
20383
|
return orphans;
|
|
20191
20384
|
}
|
|
20192
20385
|
function auditHookHealth() {
|
|
20193
|
-
const logPath =
|
|
20386
|
+
const logPath = path35.join(
|
|
20194
20387
|
process.env.HOME ?? process.env.USERPROFILE ?? "",
|
|
20195
20388
|
".exe-os",
|
|
20196
20389
|
"logs",
|
|
20197
20390
|
"hooks.log"
|
|
20198
20391
|
);
|
|
20199
|
-
if (!
|
|
20392
|
+
if (!existsSync30(logPath)) {
|
|
20200
20393
|
return { logExists: false, totalLines: 0, errorsLastHour: 0, topPatterns: [] };
|
|
20201
20394
|
}
|
|
20202
20395
|
let content;
|
|
20203
20396
|
try {
|
|
20204
|
-
content =
|
|
20397
|
+
content = readFileSync23(logPath, "utf-8");
|
|
20205
20398
|
} catch {
|
|
20206
20399
|
return { logExists: false, totalLines: 0, errorsLastHour: 0, topPatterns: [] };
|
|
20207
20400
|
}
|
|
@@ -20230,9 +20423,9 @@ function auditHookHealth() {
|
|
|
20230
20423
|
return { logExists: true, totalLines, errorsLastHour, topPatterns };
|
|
20231
20424
|
}
|
|
20232
20425
|
function safeReadJson(filePath) {
|
|
20233
|
-
if (!
|
|
20426
|
+
if (!existsSync30(filePath)) return null;
|
|
20234
20427
|
try {
|
|
20235
|
-
return JSON.parse(
|
|
20428
|
+
return JSON.parse(readFileSync23(filePath, "utf-8"));
|
|
20236
20429
|
} catch {
|
|
20237
20430
|
return null;
|
|
20238
20431
|
}
|
|
@@ -20326,13 +20519,13 @@ function auditHookOwnership() {
|
|
|
20326
20519
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
20327
20520
|
const checkedFiles = [];
|
|
20328
20521
|
const issues = [];
|
|
20329
|
-
const claudeSettingsPath =
|
|
20522
|
+
const claudeSettingsPath = path35.join(home, ".claude", "settings.json");
|
|
20330
20523
|
const claudeSettings = safeReadJson(claudeSettingsPath);
|
|
20331
20524
|
if (claudeSettings) {
|
|
20332
20525
|
checkedFiles.push(claudeSettingsPath);
|
|
20333
20526
|
issues.push(...buildHookOwnershipIssues("claude", collectHookCommandsFromClaudeSettings(claudeSettings)));
|
|
20334
20527
|
}
|
|
20335
|
-
const codexHooksPath =
|
|
20528
|
+
const codexHooksPath = path35.join(home, ".codex", "hooks.json");
|
|
20336
20529
|
const codexHooks = safeReadJson(codexHooksPath);
|
|
20337
20530
|
if (codexHooks) {
|
|
20338
20531
|
checkedFiles.push(codexHooksPath);
|
|
@@ -20596,7 +20789,7 @@ async function fixNullVectors() {
|
|
|
20596
20789
|
}
|
|
20597
20790
|
}
|
|
20598
20791
|
const npmRoot = (await import("child_process")).execSync("npm root -g", { encoding: "utf8" }).trim();
|
|
20599
|
-
const backfillPath =
|
|
20792
|
+
const backfillPath = path35.join(npmRoot, "exe-os", "dist", "bin", "backfill-vectors.js");
|
|
20600
20793
|
return new Promise((resolve, reject) => {
|
|
20601
20794
|
const child = spawn2("node", [backfillPath], { stdio: "inherit" });
|
|
20602
20795
|
if (child.pid) registerWorkerPid2(child.pid);
|
|
@@ -20781,8 +20974,8 @@ function registerRunMemoryAudit(server2) {
|
|
|
20781
20974
|
title: "Run Memory Audit",
|
|
20782
20975
|
description: "Run a memory health audit: total counts, per-agent breakdown, null vectors, duplicates, FTS sync status, bloated records, and conflict detection (contradictory/superseded memories).",
|
|
20783
20976
|
inputSchema: {
|
|
20784
|
-
agent_id:
|
|
20785
|
-
project_name:
|
|
20977
|
+
agent_id: z57.string().optional().describe("Filter audit to a specific agent"),
|
|
20978
|
+
project_name: z57.string().optional().describe("Filter audit to a specific project")
|
|
20786
20979
|
}
|
|
20787
20980
|
},
|
|
20788
20981
|
async ({ agent_id, project_name }) => {
|
|
@@ -20820,7 +21013,7 @@ function registerRunMemoryAudit(server2) {
|
|
|
20820
21013
|
init_database();
|
|
20821
21014
|
init_consolidation();
|
|
20822
21015
|
init_config();
|
|
20823
|
-
import { z as
|
|
21016
|
+
import { z as z58 } from "zod";
|
|
20824
21017
|
function registerRunConsolidation(server2) {
|
|
20825
21018
|
server2.registerTool(
|
|
20826
21019
|
"run_consolidation",
|
|
@@ -20828,7 +21021,7 @@ function registerRunConsolidation(server2) {
|
|
|
20828
21021
|
title: "Run Consolidation",
|
|
20829
21022
|
description: "Run memory consolidation \u2014 synthesizes unconsolidated memories into meta-insights. Use dry_run=true (default) to preview without executing.",
|
|
20830
21023
|
inputSchema: {
|
|
20831
|
-
dry_run:
|
|
21024
|
+
dry_run: z58.boolean().default(true).describe("Preview mode \u2014 show what would be consolidated without doing it")
|
|
20832
21025
|
}
|
|
20833
21026
|
},
|
|
20834
21027
|
async ({ dry_run }) => {
|
|
@@ -20896,14 +21089,14 @@ function registerRunConsolidation(server2) {
|
|
|
20896
21089
|
}
|
|
20897
21090
|
|
|
20898
21091
|
// src/mcp/tools/cloud-sync.ts
|
|
20899
|
-
import { z as
|
|
21092
|
+
import { z as z59 } from "zod";
|
|
20900
21093
|
|
|
20901
21094
|
// src/lib/cloud-sync.ts
|
|
20902
21095
|
init_database();
|
|
20903
|
-
import { readFileSync as
|
|
21096
|
+
import { readFileSync as readFileSync25, writeFileSync as writeFileSync18, existsSync as existsSync32, readdirSync as readdirSync11, mkdirSync as mkdirSync16, appendFileSync as appendFileSync3, unlinkSync as unlinkSync11, openSync as openSync3, closeSync as closeSync3, statSync as statSync7 } from "fs";
|
|
20904
21097
|
import crypto15 from "crypto";
|
|
20905
|
-
import
|
|
20906
|
-
import { homedir as
|
|
21098
|
+
import path37 from "path";
|
|
21099
|
+
import { homedir as homedir7 } from "os";
|
|
20907
21100
|
|
|
20908
21101
|
// src/lib/crypto.ts
|
|
20909
21102
|
import crypto14 from "crypto";
|
|
@@ -20977,8 +21170,8 @@ function sqlSafe(v) {
|
|
|
20977
21170
|
}
|
|
20978
21171
|
function logError(msg) {
|
|
20979
21172
|
try {
|
|
20980
|
-
const logPath =
|
|
20981
|
-
|
|
21173
|
+
const logPath = path37.join(homedir7(), ".exe-os", "workers.log");
|
|
21174
|
+
appendFileSync3(logPath, `${(/* @__PURE__ */ new Date()).toISOString()} ${msg}
|
|
20982
21175
|
`);
|
|
20983
21176
|
} catch {
|
|
20984
21177
|
}
|
|
@@ -20986,7 +21179,7 @@ function logError(msg) {
|
|
|
20986
21179
|
var LOCALHOST_PATTERNS = /^(localhost|127\.0\.0\.1|\[::1\])$/i;
|
|
20987
21180
|
var FETCH_TIMEOUT_MS2 = 3e4;
|
|
20988
21181
|
var PUSH_BATCH_SIZE = 5e3;
|
|
20989
|
-
var ROSTER_LOCK_PATH =
|
|
21182
|
+
var ROSTER_LOCK_PATH = path37.join(EXE_AI_DIR, "roster-merge.lock");
|
|
20990
21183
|
var LOCK_STALE_MS = 3e4;
|
|
20991
21184
|
var _pgPromise = null;
|
|
20992
21185
|
var _pgFailed = false;
|
|
@@ -20995,12 +21188,12 @@ function isTruthyEnv(value) {
|
|
|
20995
21188
|
}
|
|
20996
21189
|
function loadPgClient() {
|
|
20997
21190
|
if (_pgFailed) return null;
|
|
20998
|
-
const configPath =
|
|
21191
|
+
const configPath = path37.join(EXE_AI_DIR, "config.json");
|
|
20999
21192
|
let cloudPostgresUrl;
|
|
21000
21193
|
let configEnabled = false;
|
|
21001
21194
|
try {
|
|
21002
|
-
if (
|
|
21003
|
-
const cfg = JSON.parse(
|
|
21195
|
+
if (existsSync32(configPath)) {
|
|
21196
|
+
const cfg = JSON.parse(readFileSync25(configPath, "utf8"));
|
|
21004
21197
|
cloudPostgresUrl = cfg.cloud?.postgresUrl;
|
|
21005
21198
|
configEnabled = cfg.cloud?.syncToPostgres === true;
|
|
21006
21199
|
}
|
|
@@ -21027,9 +21220,9 @@ function loadPgClient() {
|
|
|
21027
21220
|
if (!Ctor) throw new Error(`No PrismaClient at ${explicitPath}`);
|
|
21028
21221
|
return new Ctor();
|
|
21029
21222
|
}
|
|
21030
|
-
const exeDbRoot = process.env.EXE_DB_ROOT ??
|
|
21031
|
-
const packagePath =
|
|
21032
|
-
if (
|
|
21223
|
+
const exeDbRoot = process.env.EXE_DB_ROOT ?? path37.join(homedir7(), "exe-db");
|
|
21224
|
+
const packagePath = path37.join(exeDbRoot, "package.json");
|
|
21225
|
+
if (existsSync32(packagePath)) {
|
|
21033
21226
|
const req = createRequire6(packagePath);
|
|
21034
21227
|
const entry = req.resolve("@prisma/client");
|
|
21035
21228
|
const mod = await import(pathToFileURL6(entry).href);
|
|
@@ -21089,20 +21282,20 @@ async function pushToPostgres(records) {
|
|
|
21089
21282
|
}
|
|
21090
21283
|
async function withRosterLock(fn) {
|
|
21091
21284
|
try {
|
|
21092
|
-
const fd =
|
|
21093
|
-
|
|
21094
|
-
|
|
21285
|
+
const fd = openSync3(ROSTER_LOCK_PATH, "wx");
|
|
21286
|
+
closeSync3(fd);
|
|
21287
|
+
writeFileSync18(ROSTER_LOCK_PATH, String(Date.now()));
|
|
21095
21288
|
} catch (err) {
|
|
21096
21289
|
if (err.code === "EEXIST") {
|
|
21097
21290
|
try {
|
|
21098
|
-
const ts2 = parseInt(
|
|
21291
|
+
const ts2 = parseInt(readFileSync25(ROSTER_LOCK_PATH, "utf-8"), 10);
|
|
21099
21292
|
if (Date.now() - ts2 < LOCK_STALE_MS) {
|
|
21100
21293
|
throw new Error("Roster merge already in progress \u2014 another sync is running");
|
|
21101
21294
|
}
|
|
21102
21295
|
unlinkSync11(ROSTER_LOCK_PATH);
|
|
21103
|
-
const fd =
|
|
21104
|
-
|
|
21105
|
-
|
|
21296
|
+
const fd = openSync3(ROSTER_LOCK_PATH, "wx");
|
|
21297
|
+
closeSync3(fd);
|
|
21298
|
+
writeFileSync18(ROSTER_LOCK_PATH, String(Date.now()));
|
|
21106
21299
|
} catch (retryErr) {
|
|
21107
21300
|
if (retryErr instanceof Error && retryErr.message.includes("already in progress")) throw retryErr;
|
|
21108
21301
|
throw new Error("Roster merge already in progress \u2014 another sync is running");
|
|
@@ -21532,8 +21725,8 @@ async function cloudSync(config2) {
|
|
|
21532
21725
|
try {
|
|
21533
21726
|
const employees = await loadEmployees();
|
|
21534
21727
|
rosterResult.employees = employees.length;
|
|
21535
|
-
const idDir =
|
|
21536
|
-
if (
|
|
21728
|
+
const idDir = path37.join(EXE_AI_DIR, "identity");
|
|
21729
|
+
if (existsSync32(idDir)) {
|
|
21537
21730
|
rosterResult.identities = readdirSync11(idDir).filter((f) => f.endsWith(".md")).length;
|
|
21538
21731
|
}
|
|
21539
21732
|
} catch {
|
|
@@ -21543,10 +21736,10 @@ async function cloudSync(config2) {
|
|
|
21543
21736
|
const { getLatestBackup: getLatestBackup2 } = await Promise.resolve().then(() => (init_db_backup(), db_backup_exports));
|
|
21544
21737
|
const latestBackup = getLatestBackup2();
|
|
21545
21738
|
if (latestBackup) {
|
|
21546
|
-
const backupSize =
|
|
21739
|
+
const backupSize = statSync7(latestBackup).size;
|
|
21547
21740
|
const MAX_CLOUD_BACKUP_BYTES = 50 * 1024 * 1024;
|
|
21548
21741
|
if (backupSize <= MAX_CLOUD_BACKUP_BYTES) {
|
|
21549
|
-
const backupData =
|
|
21742
|
+
const backupData = readFileSync25(latestBackup);
|
|
21550
21743
|
const deviceId = loadDeviceId() ?? "unknown";
|
|
21551
21744
|
const encrypted = encryptSyncBlob(backupData);
|
|
21552
21745
|
const backupRes = await fetchWithRetry(`${config2.endpoint}/sync/push-db-backup`, {
|
|
@@ -21554,7 +21747,7 @@ async function cloudSync(config2) {
|
|
|
21554
21747
|
headers: { "Content-Type": "application/json", Authorization: `Bearer ${config2.apiKey}` },
|
|
21555
21748
|
body: JSON.stringify({
|
|
21556
21749
|
device_id: deviceId,
|
|
21557
|
-
filename:
|
|
21750
|
+
filename: path37.basename(latestBackup),
|
|
21558
21751
|
blob: encrypted,
|
|
21559
21752
|
size: backupData.length
|
|
21560
21753
|
})
|
|
@@ -21579,49 +21772,49 @@ async function cloudSync(config2) {
|
|
|
21579
21772
|
roster: rosterResult
|
|
21580
21773
|
};
|
|
21581
21774
|
}
|
|
21582
|
-
var ROSTER_DELETIONS_PATH =
|
|
21775
|
+
var ROSTER_DELETIONS_PATH = path37.join(EXE_AI_DIR, "roster-deletions.json");
|
|
21583
21776
|
function consumeRosterDeletions() {
|
|
21584
21777
|
try {
|
|
21585
|
-
if (!
|
|
21586
|
-
const deletions = JSON.parse(
|
|
21587
|
-
|
|
21778
|
+
if (!existsSync32(ROSTER_DELETIONS_PATH)) return [];
|
|
21779
|
+
const deletions = JSON.parse(readFileSync25(ROSTER_DELETIONS_PATH, "utf-8"));
|
|
21780
|
+
writeFileSync18(ROSTER_DELETIONS_PATH, "[]");
|
|
21588
21781
|
return deletions;
|
|
21589
21782
|
} catch {
|
|
21590
21783
|
return [];
|
|
21591
21784
|
}
|
|
21592
21785
|
}
|
|
21593
21786
|
function buildRosterBlob(paths) {
|
|
21594
|
-
const rosterPath = paths?.rosterPath ??
|
|
21595
|
-
const identityDir = paths?.identityDir ??
|
|
21596
|
-
const configPath = paths?.configPath ??
|
|
21787
|
+
const rosterPath = paths?.rosterPath ?? path37.join(EXE_AI_DIR, "exe-employees.json");
|
|
21788
|
+
const identityDir = paths?.identityDir ?? path37.join(EXE_AI_DIR, "identity");
|
|
21789
|
+
const configPath = paths?.configPath ?? path37.join(EXE_AI_DIR, "config.json");
|
|
21597
21790
|
let roster = [];
|
|
21598
|
-
if (
|
|
21791
|
+
if (existsSync32(rosterPath)) {
|
|
21599
21792
|
try {
|
|
21600
|
-
roster = JSON.parse(
|
|
21793
|
+
roster = JSON.parse(readFileSync25(rosterPath, "utf-8"));
|
|
21601
21794
|
} catch {
|
|
21602
21795
|
}
|
|
21603
21796
|
}
|
|
21604
21797
|
const identities = {};
|
|
21605
|
-
if (
|
|
21798
|
+
if (existsSync32(identityDir)) {
|
|
21606
21799
|
for (const file of readdirSync11(identityDir).filter((f) => f.endsWith(".md"))) {
|
|
21607
21800
|
try {
|
|
21608
|
-
identities[file] =
|
|
21801
|
+
identities[file] = readFileSync25(path37.join(identityDir, file), "utf-8");
|
|
21609
21802
|
} catch {
|
|
21610
21803
|
}
|
|
21611
21804
|
}
|
|
21612
21805
|
}
|
|
21613
21806
|
let config2;
|
|
21614
|
-
if (
|
|
21807
|
+
if (existsSync32(configPath)) {
|
|
21615
21808
|
try {
|
|
21616
|
-
config2 = JSON.parse(
|
|
21809
|
+
config2 = JSON.parse(readFileSync25(configPath, "utf-8"));
|
|
21617
21810
|
} catch {
|
|
21618
21811
|
}
|
|
21619
21812
|
}
|
|
21620
21813
|
let agentConfig;
|
|
21621
|
-
const agentConfigPath =
|
|
21622
|
-
if (
|
|
21814
|
+
const agentConfigPath = path37.join(EXE_AI_DIR, "agent-config.json");
|
|
21815
|
+
if (existsSync32(agentConfigPath)) {
|
|
21623
21816
|
try {
|
|
21624
|
-
agentConfig = JSON.parse(
|
|
21817
|
+
agentConfig = JSON.parse(readFileSync25(agentConfigPath, "utf-8"));
|
|
21625
21818
|
} catch {
|
|
21626
21819
|
}
|
|
21627
21820
|
}
|
|
@@ -21697,24 +21890,24 @@ async function cloudPullRoster(config2) {
|
|
|
21697
21890
|
}
|
|
21698
21891
|
}
|
|
21699
21892
|
function mergeConfig(remoteConfig, configPath) {
|
|
21700
|
-
const cfgPath = configPath ??
|
|
21893
|
+
const cfgPath = configPath ?? path37.join(EXE_AI_DIR, "config.json");
|
|
21701
21894
|
let local = {};
|
|
21702
|
-
if (
|
|
21895
|
+
if (existsSync32(cfgPath)) {
|
|
21703
21896
|
try {
|
|
21704
|
-
local = JSON.parse(
|
|
21897
|
+
local = JSON.parse(readFileSync25(cfgPath, "utf-8"));
|
|
21705
21898
|
} catch {
|
|
21706
21899
|
}
|
|
21707
21900
|
}
|
|
21708
21901
|
const merged = { ...remoteConfig, ...local };
|
|
21709
|
-
const dir =
|
|
21902
|
+
const dir = path37.dirname(cfgPath);
|
|
21710
21903
|
ensurePrivateDirSync(dir);
|
|
21711
|
-
|
|
21904
|
+
writeFileSync18(cfgPath, JSON.stringify(merged, null, 2), "utf-8");
|
|
21712
21905
|
enforcePrivateFileSync(cfgPath);
|
|
21713
21906
|
}
|
|
21714
21907
|
async function mergeRosterFromRemote(remote, paths) {
|
|
21715
21908
|
return withRosterLock(async () => {
|
|
21716
21909
|
const rosterPath = paths?.rosterPath ?? void 0;
|
|
21717
|
-
const identityDir = paths?.identityDir ??
|
|
21910
|
+
const identityDir = paths?.identityDir ?? path37.join(EXE_AI_DIR, "identity");
|
|
21718
21911
|
const localEmployees = await loadEmployees(rosterPath);
|
|
21719
21912
|
const localNames = new Set(localEmployees.map((e) => e.name));
|
|
21720
21913
|
let added = 0;
|
|
@@ -21735,15 +21928,15 @@ async function mergeRosterFromRemote(remote, paths) {
|
|
|
21735
21928
|
) ?? lookupKey;
|
|
21736
21929
|
const remoteIdentity = remote.identities[matchedKey];
|
|
21737
21930
|
if (remoteIdentity) {
|
|
21738
|
-
if (!
|
|
21739
|
-
const idPath =
|
|
21931
|
+
if (!existsSync32(identityDir)) mkdirSync16(identityDir, { recursive: true });
|
|
21932
|
+
const idPath = path37.join(identityDir, `${remoteEmp.name}.md`);
|
|
21740
21933
|
let localIdentity = null;
|
|
21741
21934
|
try {
|
|
21742
|
-
localIdentity =
|
|
21935
|
+
localIdentity = existsSync32(idPath) ? readFileSync25(idPath, "utf-8") : null;
|
|
21743
21936
|
} catch {
|
|
21744
21937
|
}
|
|
21745
21938
|
if (localIdentity !== remoteIdentity) {
|
|
21746
|
-
|
|
21939
|
+
writeFileSync18(idPath, remoteIdentity, "utf-8");
|
|
21747
21940
|
identitiesUpdated++;
|
|
21748
21941
|
}
|
|
21749
21942
|
}
|
|
@@ -21769,17 +21962,17 @@ async function mergeRosterFromRemote(remote, paths) {
|
|
|
21769
21962
|
}
|
|
21770
21963
|
if (remote.agentConfig && Object.keys(remote.agentConfig).length > 0) {
|
|
21771
21964
|
try {
|
|
21772
|
-
const agentConfigPath =
|
|
21965
|
+
const agentConfigPath = path37.join(EXE_AI_DIR, "agent-config.json");
|
|
21773
21966
|
let local = {};
|
|
21774
|
-
if (
|
|
21967
|
+
if (existsSync32(agentConfigPath)) {
|
|
21775
21968
|
try {
|
|
21776
|
-
local = JSON.parse(
|
|
21969
|
+
local = JSON.parse(readFileSync25(agentConfigPath, "utf-8"));
|
|
21777
21970
|
} catch {
|
|
21778
21971
|
}
|
|
21779
21972
|
}
|
|
21780
21973
|
const merged = { ...remote.agentConfig, ...local };
|
|
21781
|
-
ensurePrivateDirSync(
|
|
21782
|
-
|
|
21974
|
+
ensurePrivateDirSync(path37.dirname(agentConfigPath));
|
|
21975
|
+
writeFileSync18(agentConfigPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
|
|
21783
21976
|
enforcePrivateFileSync(agentConfigPath);
|
|
21784
21977
|
} catch {
|
|
21785
21978
|
}
|
|
@@ -22290,9 +22483,9 @@ function registerCloudSync(server2) {
|
|
|
22290
22483
|
title: "Cloud Sync",
|
|
22291
22484
|
description: "Consolidated Exe Cloud tool. Supports read-only status, normal sync-now, and explicitly confirmed post-key-rotation re-upload. Does not reveal recovery phrases and does not rotate keys.",
|
|
22292
22485
|
inputSchema: {
|
|
22293
|
-
action:
|
|
22294
|
-
force:
|
|
22295
|
-
confirm_local_db_source_of_truth:
|
|
22486
|
+
action: z59.enum(["status", "sync", "reupload"]).default("sync").describe("Cloud operation. status is read-only; sync is normal sync-now; reupload repairs cloud after key rotation."),
|
|
22487
|
+
force: z59.boolean().default(false).describe("Reserved for sync compatibility; normal cloud sync already runs when requested."),
|
|
22488
|
+
confirm_local_db_source_of_truth: z59.string().optional().describe('Required for action=reupload. Must exactly equal "LOCAL DB IS SOURCE OF TRUTH".')
|
|
22296
22489
|
}
|
|
22297
22490
|
},
|
|
22298
22491
|
async ({ action = "sync", confirm_local_db_source_of_truth }) => {
|
|
@@ -22364,7 +22557,7 @@ function registerCloudSync(server2) {
|
|
|
22364
22557
|
}
|
|
22365
22558
|
|
|
22366
22559
|
// src/mcp/tools/orchestration-phase.ts
|
|
22367
|
-
import { z as
|
|
22560
|
+
import { z as z60 } from "zod";
|
|
22368
22561
|
|
|
22369
22562
|
// src/lib/orchestration-phase.ts
|
|
22370
22563
|
init_config();
|
|
@@ -22450,8 +22643,8 @@ function registerOrchestrationPhase(server2) {
|
|
|
22450
22643
|
title: "Orchestration Phase",
|
|
22451
22644
|
description: "View or change the customer-owned orchestration maturity phase. MCP parity for `exe-os org phase`, `exe-os org unlock executives`, and `exe-os org unlock parallel`. This is a recommendation layer, not a blocker; it never exposes recovery phrases or secrets.",
|
|
22452
22645
|
inputSchema: {
|
|
22453
|
-
action:
|
|
22454
|
-
phase:
|
|
22646
|
+
action: z60.enum(["status", "set", "unlock_executives", "unlock_parallel"]).default("status"),
|
|
22647
|
+
phase: z60.enum(["phase_1_coo", "phase_2_executives", "phase_3_parallel_org", "1", "2", "3"]).optional().describe("Phase to set when action='set'.")
|
|
22455
22648
|
}
|
|
22456
22649
|
},
|
|
22457
22650
|
async ({ action = "status", phase }) => {
|
|
@@ -22492,7 +22685,7 @@ function registerOrchestrationPhase(server2) {
|
|
|
22492
22685
|
|
|
22493
22686
|
// src/mcp/tools/backup-vps.ts
|
|
22494
22687
|
init_keychain();
|
|
22495
|
-
import { z as
|
|
22688
|
+
import { z as z61 } from "zod";
|
|
22496
22689
|
|
|
22497
22690
|
// src/lib/vps-backup.ts
|
|
22498
22691
|
import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
|
|
@@ -22817,43 +23010,43 @@ function registerBackupVps(server2) {
|
|
|
22817
23010
|
{
|
|
22818
23011
|
title: "VPS Backup",
|
|
22819
23012
|
description: "Run VPS Postgres backup/restore workflows and check status.",
|
|
22820
|
-
inputSchema:
|
|
22821
|
-
|
|
22822
|
-
action:
|
|
22823
|
-
databaseUrl:
|
|
22824
|
-
encryptionKeyB64:
|
|
23013
|
+
inputSchema: z61.discriminatedUnion("action", [
|
|
23014
|
+
z61.object({
|
|
23015
|
+
action: z61.literal("backup"),
|
|
23016
|
+
databaseUrl: z61.string().min(1).describe("Postgres DATABASE_URL to dump from"),
|
|
23017
|
+
encryptionKeyB64: z61.string().min(1).max(4096).optional().describe(
|
|
22825
23018
|
"Base64 AES-256 key (defaults to local master key if omitted)"
|
|
22826
23019
|
),
|
|
22827
|
-
r2Bucket:
|
|
22828
|
-
r2Endpoint:
|
|
22829
|
-
r2AccessKeyId:
|
|
22830
|
-
r2SecretAccessKey:
|
|
23020
|
+
r2Bucket: z61.string().min(1).describe("R2 bucket name"),
|
|
23021
|
+
r2Endpoint: z61.string().min(1).describe("R2 endpoint URL"),
|
|
23022
|
+
r2AccessKeyId: z61.string().min(1).describe("R2 access key ID"),
|
|
23023
|
+
r2SecretAccessKey: z61.string().min(1).describe("R2 secret access key")
|
|
22831
23024
|
}),
|
|
22832
|
-
|
|
22833
|
-
action:
|
|
22834
|
-
databaseUrl:
|
|
22835
|
-
backupKey:
|
|
22836
|
-
encryptionKeyB64:
|
|
23025
|
+
z61.object({
|
|
23026
|
+
action: z61.literal("restore"),
|
|
23027
|
+
databaseUrl: z61.string().min(1).describe("Target Postgres DATABASE_URL for restore"),
|
|
23028
|
+
backupKey: z61.string().min(1).describe("R2 object key to restore from"),
|
|
23029
|
+
encryptionKeyB64: z61.string().min(1).max(4096).optional().describe(
|
|
22837
23030
|
"Base64 AES-256 key (defaults to local master key if omitted)"
|
|
22838
23031
|
),
|
|
22839
|
-
r2Bucket:
|
|
22840
|
-
r2Endpoint:
|
|
22841
|
-
r2AccessKeyId:
|
|
22842
|
-
r2SecretAccessKey:
|
|
23032
|
+
r2Bucket: z61.string().min(1).describe("R2 bucket name"),
|
|
23033
|
+
r2Endpoint: z61.string().min(1).describe("R2 endpoint URL"),
|
|
23034
|
+
r2AccessKeyId: z61.string().min(1).describe("R2 access key ID"),
|
|
23035
|
+
r2SecretAccessKey: z61.string().min(1).describe("R2 secret access key")
|
|
22843
23036
|
}),
|
|
22844
|
-
|
|
22845
|
-
action:
|
|
22846
|
-
r2Bucket:
|
|
22847
|
-
r2Endpoint:
|
|
22848
|
-
r2AccessKeyId:
|
|
22849
|
-
r2SecretAccessKey:
|
|
23037
|
+
z61.object({
|
|
23038
|
+
action: z61.literal("list"),
|
|
23039
|
+
r2Bucket: z61.string().min(1).describe("R2 bucket name"),
|
|
23040
|
+
r2Endpoint: z61.string().min(1).describe("R2 endpoint URL"),
|
|
23041
|
+
r2AccessKeyId: z61.string().min(1).describe("R2 access key ID"),
|
|
23042
|
+
r2SecretAccessKey: z61.string().min(1).describe("R2 secret access key")
|
|
22850
23043
|
}),
|
|
22851
|
-
|
|
22852
|
-
action:
|
|
22853
|
-
r2Bucket:
|
|
22854
|
-
r2Endpoint:
|
|
22855
|
-
r2AccessKeyId:
|
|
22856
|
-
r2SecretAccessKey:
|
|
23044
|
+
z61.object({
|
|
23045
|
+
action: z61.literal("health"),
|
|
23046
|
+
r2Bucket: z61.string().min(1).describe("R2 bucket name"),
|
|
23047
|
+
r2Endpoint: z61.string().min(1).describe("R2 endpoint URL"),
|
|
23048
|
+
r2AccessKeyId: z61.string().min(1).describe("R2 access key ID"),
|
|
23049
|
+
r2SecretAccessKey: z61.string().min(1).describe("R2 secret access key")
|
|
22857
23050
|
})
|
|
22858
23051
|
])
|
|
22859
23052
|
},
|
|
@@ -22991,11 +23184,11 @@ async function resolveEncryptionKey(providedB64) {
|
|
|
22991
23184
|
}
|
|
22992
23185
|
|
|
22993
23186
|
// src/mcp/tools/deploy-client.ts
|
|
22994
|
-
import { z as
|
|
23187
|
+
import { z as z62 } from "zod";
|
|
22995
23188
|
import { execFile } from "child_process";
|
|
22996
23189
|
import { promisify } from "util";
|
|
22997
|
-
import
|
|
22998
|
-
import { existsSync as
|
|
23190
|
+
import path38 from "path";
|
|
23191
|
+
import { existsSync as existsSync33 } from "fs";
|
|
22999
23192
|
|
|
23000
23193
|
// src/lib/hostinger-api.ts
|
|
23001
23194
|
var DEFAULT_BASE_URL = "https://developers.hostinger.com/api/vps/v1";
|
|
@@ -23043,9 +23236,9 @@ var HostingerApiClient = class {
|
|
|
23043
23236
|
}
|
|
23044
23237
|
this.lastRequestTime = Date.now();
|
|
23045
23238
|
}
|
|
23046
|
-
async request(method,
|
|
23239
|
+
async request(method, path52, body) {
|
|
23047
23240
|
await this.rateLimit();
|
|
23048
|
-
const url = `${this.baseUrl}${
|
|
23241
|
+
const url = `${this.baseUrl}${path52}`;
|
|
23049
23242
|
const headers = {
|
|
23050
23243
|
Authorization: `Bearer ${this.apiKey}`,
|
|
23051
23244
|
"Content-Type": "application/json",
|
|
@@ -23118,8 +23311,8 @@ async function requestCloudflare(cfApiToken, zoneId, options) {
|
|
|
23118
23311
|
}
|
|
23119
23312
|
return envelope.result;
|
|
23120
23313
|
}
|
|
23121
|
-
function buildUrl(zoneId,
|
|
23122
|
-
const normalizedPath =
|
|
23314
|
+
function buildUrl(zoneId, path52 = "/dns_records", query) {
|
|
23315
|
+
const normalizedPath = path52.startsWith("/") ? path52 : `/${path52}`;
|
|
23123
23316
|
const url = new URL(
|
|
23124
23317
|
`${CLOUDFLARE_API_BASE_URL}/zones/${zoneId}${normalizedPath}`
|
|
23125
23318
|
);
|
|
@@ -23259,12 +23452,12 @@ function registerDeployClient(server2) {
|
|
|
23259
23452
|
title: "Deploy Client",
|
|
23260
23453
|
description: "Provision a Hostinger VPS and deploy exe-os for a client. Creates VPS, waits for ready state, runs Ansible playbook, verifies health.",
|
|
23261
23454
|
inputSchema: {
|
|
23262
|
-
client_name:
|
|
23263
|
-
domain:
|
|
23264
|
-
region:
|
|
23265
|
-
plan:
|
|
23266
|
-
ssl_email:
|
|
23267
|
-
user_id:
|
|
23455
|
+
client_name: z62.string().min(1).describe("Client name (used for hostname and identification)"),
|
|
23456
|
+
domain: z62.string().min(1).describe("Domain name for the deployment (e.g., client.exe.ai)"),
|
|
23457
|
+
region: z62.string().default("jakarta").describe("VPS region (default: jakarta)"),
|
|
23458
|
+
plan: z62.string().default("kvm-2").describe("Hostinger VPS plan (default: kvm-2)"),
|
|
23459
|
+
ssl_email: z62.string().email().describe("Email for Let's Encrypt SSL certificate"),
|
|
23460
|
+
user_id: z62.string().min(1).describe("User/customer ID for inventory tracking")
|
|
23268
23461
|
}
|
|
23269
23462
|
},
|
|
23270
23463
|
async ({ client_name, domain, region, plan, ssl_email, user_id }) => {
|
|
@@ -23332,12 +23525,12 @@ async function waitForReady(client, vpsId) {
|
|
|
23332
23525
|
}
|
|
23333
23526
|
async function runAnsiblePlaybook(vpsIp, domain, sslEmail, clientName) {
|
|
23334
23527
|
const safeClientName = clientName.replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
23335
|
-
const playbookDir =
|
|
23336
|
-
const playbookPath =
|
|
23337
|
-
const inventoryPath =
|
|
23338
|
-
const clientVarsPath =
|
|
23339
|
-
const varsDir =
|
|
23340
|
-
if (!
|
|
23528
|
+
const playbookDir = path38.resolve(process.cwd(), "infrastructure", "ansible");
|
|
23529
|
+
const playbookPath = path38.join(playbookDir, "deploy.yml");
|
|
23530
|
+
const inventoryPath = path38.join(playbookDir, "inventory", "hosts.yml");
|
|
23531
|
+
const clientVarsPath = path38.join(playbookDir, "vars", `${safeClientName}.yml`);
|
|
23532
|
+
const varsDir = path38.join(playbookDir, "vars");
|
|
23533
|
+
if (!path38.resolve(clientVarsPath).startsWith(path38.resolve(varsDir))) {
|
|
23341
23534
|
throw new Error(`Invalid client name for vars path: ${clientName}`);
|
|
23342
23535
|
}
|
|
23343
23536
|
const args = [
|
|
@@ -23353,7 +23546,7 @@ async function runAnsiblePlaybook(vpsIp, domain, sslEmail, clientName) {
|
|
|
23353
23546
|
"-e",
|
|
23354
23547
|
`client_name=${safeClientName}`
|
|
23355
23548
|
];
|
|
23356
|
-
if (
|
|
23549
|
+
if (existsSync33(clientVarsPath)) {
|
|
23357
23550
|
args.push("-e", `@${clientVarsPath}`);
|
|
23358
23551
|
}
|
|
23359
23552
|
try {
|
|
@@ -23426,7 +23619,7 @@ function buildInventoryRecord(params) {
|
|
|
23426
23619
|
|
|
23427
23620
|
// src/mcp/tools/get-license-status.ts
|
|
23428
23621
|
init_license();
|
|
23429
|
-
import { z as
|
|
23622
|
+
import { z as z63 } from "zod";
|
|
23430
23623
|
var FEATURES = [
|
|
23431
23624
|
"cloud_sync",
|
|
23432
23625
|
"external_agents",
|
|
@@ -23440,7 +23633,7 @@ function registerGetLicenseStatus(server2) {
|
|
|
23440
23633
|
title: "Get License Status",
|
|
23441
23634
|
description: "Get current license status: plan, validity, feature gates, limits, and expiry.",
|
|
23442
23635
|
inputSchema: {
|
|
23443
|
-
_dummy:
|
|
23636
|
+
_dummy: z63.string().optional().describe("Unused \u2014 no input required")
|
|
23444
23637
|
}
|
|
23445
23638
|
},
|
|
23446
23639
|
async () => {
|
|
@@ -23494,11 +23687,11 @@ function registerGetLicenseStatus(server2) {
|
|
|
23494
23687
|
// src/mcp/tools/create-license.ts
|
|
23495
23688
|
init_license();
|
|
23496
23689
|
import os15 from "os";
|
|
23497
|
-
import
|
|
23690
|
+
import path39 from "path";
|
|
23498
23691
|
import { randomBytes as randomBytes2, randomUUID as randomUUID6 } from "crypto";
|
|
23499
23692
|
import { createRequire as createRequire3 } from "module";
|
|
23500
23693
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
23501
|
-
import { z as
|
|
23694
|
+
import { z as z64 } from "zod";
|
|
23502
23695
|
var prismaPromise = null;
|
|
23503
23696
|
function loadPrisma() {
|
|
23504
23697
|
if (!prismaPromise) {
|
|
@@ -23510,8 +23703,8 @@ function loadPrisma() {
|
|
|
23510
23703
|
if (!Ctor2) throw new Error(`No PrismaClient at ${explicitPath}`);
|
|
23511
23704
|
return new Ctor2();
|
|
23512
23705
|
}
|
|
23513
|
-
const exeDbRoot = process.env.EXE_DB_ROOT ??
|
|
23514
|
-
const req = createRequire3(
|
|
23706
|
+
const exeDbRoot = process.env.EXE_DB_ROOT ?? path39.join(os15.homedir(), "exe-db");
|
|
23707
|
+
const req = createRequire3(path39.join(exeDbRoot, "package.json"));
|
|
23515
23708
|
const entry = req.resolve("@prisma/client");
|
|
23516
23709
|
const mod = await import(pathToFileURL3(entry).href);
|
|
23517
23710
|
const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
|
|
@@ -23531,10 +23724,10 @@ function registerCreateLicense(server2) {
|
|
|
23531
23724
|
title: "Create License",
|
|
23532
23725
|
description: "Generate an exe_sk_* license key for a user. Stores in billing.licenses. Returns the key to give to the customer.",
|
|
23533
23726
|
inputSchema: {
|
|
23534
|
-
email:
|
|
23535
|
-
name:
|
|
23536
|
-
plan:
|
|
23537
|
-
expires_in_days:
|
|
23727
|
+
email: z64.string().email().describe("Customer email address"),
|
|
23728
|
+
name: z64.string().optional().describe("Customer name"),
|
|
23729
|
+
plan: z64.enum(["free", "pro", "team", "agency", "enterprise"]).default("pro").describe("License plan tier"),
|
|
23730
|
+
expires_in_days: z64.number().int().positive().default(365).describe("Days until expiration (default 365)")
|
|
23538
23731
|
}
|
|
23539
23732
|
},
|
|
23540
23733
|
async ({ email, name, plan, expires_in_days }) => {
|
|
@@ -23586,10 +23779,10 @@ Give this key to the customer. They paste it during \`exe-os setup\`.`);
|
|
|
23586
23779
|
|
|
23587
23780
|
// src/mcp/tools/list-licenses.ts
|
|
23588
23781
|
import os16 from "os";
|
|
23589
|
-
import
|
|
23782
|
+
import path40 from "path";
|
|
23590
23783
|
import { createRequire as createRequire4 } from "module";
|
|
23591
23784
|
import { pathToFileURL as pathToFileURL4 } from "url";
|
|
23592
|
-
import { z as
|
|
23785
|
+
import { z as z65 } from "zod";
|
|
23593
23786
|
var prismaPromise2 = null;
|
|
23594
23787
|
function loadPrisma2() {
|
|
23595
23788
|
if (!prismaPromise2) {
|
|
@@ -23601,8 +23794,8 @@ function loadPrisma2() {
|
|
|
23601
23794
|
if (!Ctor2) throw new Error(`No PrismaClient at ${explicitPath}`);
|
|
23602
23795
|
return new Ctor2();
|
|
23603
23796
|
}
|
|
23604
|
-
const exeDbRoot = process.env.EXE_DB_ROOT ??
|
|
23605
|
-
const req = createRequire4(
|
|
23797
|
+
const exeDbRoot = process.env.EXE_DB_ROOT ?? path40.join(os16.homedir(), "exe-db");
|
|
23798
|
+
const req = createRequire4(path40.join(exeDbRoot, "package.json"));
|
|
23606
23799
|
const entry = req.resolve("@prisma/client");
|
|
23607
23800
|
const mod = await import(pathToFileURL4(entry).href);
|
|
23608
23801
|
const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
|
|
@@ -23619,7 +23812,7 @@ function registerListLicenses(server2) {
|
|
|
23619
23812
|
title: "List Licenses",
|
|
23620
23813
|
description: "List all issued licenses with status (active/expired/revoked). Optionally filter by plan.",
|
|
23621
23814
|
inputSchema: {
|
|
23622
|
-
plan:
|
|
23815
|
+
plan: z65.enum(["free", "pro", "team", "agency", "enterprise"]).optional().describe("Filter by plan tier (omit for all)")
|
|
23623
23816
|
}
|
|
23624
23817
|
},
|
|
23625
23818
|
async ({ plan }) => {
|
|
@@ -23670,7 +23863,7 @@ function registerListLicenses(server2) {
|
|
|
23670
23863
|
|
|
23671
23864
|
// src/mcp/tools/activate-license.ts
|
|
23672
23865
|
init_license();
|
|
23673
|
-
import { z as
|
|
23866
|
+
import { z as z66 } from "zod";
|
|
23674
23867
|
function registerActivateLicense(server2) {
|
|
23675
23868
|
server2.registerTool(
|
|
23676
23869
|
"activate_license",
|
|
@@ -23678,7 +23871,7 @@ function registerActivateLicense(server2) {
|
|
|
23678
23871
|
title: "Activate License",
|
|
23679
23872
|
description: "Activate an exe_sk_* license key on this device. Writes to ~/.exe-os/license.key, validates against Postgres, and caches the result.",
|
|
23680
23873
|
inputSchema: {
|
|
23681
|
-
key:
|
|
23874
|
+
key: z66.string().startsWith("exe_sk_").describe("License key (exe_sk_*)")
|
|
23682
23875
|
}
|
|
23683
23876
|
},
|
|
23684
23877
|
async ({ key }) => {
|
|
@@ -23724,18 +23917,18 @@ Key saved to ~/.exe-os/license.key. Device ID: ${deviceId}`);
|
|
|
23724
23917
|
}
|
|
23725
23918
|
|
|
23726
23919
|
// src/mcp/tools/create-trigger.ts
|
|
23727
|
-
import { z as
|
|
23920
|
+
import { z as z67 } from "zod";
|
|
23728
23921
|
|
|
23729
23922
|
// src/automation/trigger-engine.ts
|
|
23730
|
-
import { readFileSync as
|
|
23923
|
+
import { readFileSync as readFileSync26, writeFileSync as writeFileSync19, existsSync as existsSync34, mkdirSync as mkdirSync17 } from "fs";
|
|
23731
23924
|
import { randomUUID as randomUUID7 } from "crypto";
|
|
23732
|
-
import
|
|
23925
|
+
import path41 from "path";
|
|
23733
23926
|
import os17 from "os";
|
|
23734
|
-
var TRIGGERS_PATH =
|
|
23927
|
+
var TRIGGERS_PATH = path41.join(os17.homedir(), ".exe-os", "triggers.json");
|
|
23735
23928
|
function loadTriggers(project) {
|
|
23736
|
-
if (!
|
|
23929
|
+
if (!existsSync34(TRIGGERS_PATH)) return [];
|
|
23737
23930
|
try {
|
|
23738
|
-
const raw =
|
|
23931
|
+
const raw = readFileSync26(TRIGGERS_PATH, "utf-8");
|
|
23739
23932
|
const all = JSON.parse(raw);
|
|
23740
23933
|
if (!Array.isArray(all)) return [];
|
|
23741
23934
|
if (project) {
|
|
@@ -23747,9 +23940,9 @@ function loadTriggers(project) {
|
|
|
23747
23940
|
}
|
|
23748
23941
|
}
|
|
23749
23942
|
function saveTriggers(triggers) {
|
|
23750
|
-
const dir =
|
|
23751
|
-
if (!
|
|
23752
|
-
|
|
23943
|
+
const dir = path41.dirname(TRIGGERS_PATH);
|
|
23944
|
+
if (!existsSync34(dir)) mkdirSync17(dir, { recursive: true });
|
|
23945
|
+
writeFileSync19(TRIGGERS_PATH, JSON.stringify(triggers, null, 2), "utf-8");
|
|
23753
23946
|
}
|
|
23754
23947
|
function createNewTrigger(input) {
|
|
23755
23948
|
const triggers = loadTriggers();
|
|
@@ -23905,14 +24098,14 @@ function addToCrontab(id, cron, prompt, projectDir) {
|
|
|
23905
24098
|
}
|
|
23906
24099
|
|
|
23907
24100
|
// src/mcp/tools/create-trigger.ts
|
|
23908
|
-
var conditionSchema =
|
|
23909
|
-
field:
|
|
23910
|
-
op:
|
|
23911
|
-
value:
|
|
24101
|
+
var conditionSchema = z67.object({
|
|
24102
|
+
field: z67.string().describe("Dot-path field to evaluate, e.g., 'stage' or 'amount'"),
|
|
24103
|
+
op: z67.enum(["eq", "neq", "gt", "lt", "gte", "lte", "contains", "not_contains"]).describe("Comparison operator"),
|
|
24104
|
+
value: z67.string().or(z67.number()).or(z67.boolean()).describe("Value to compare against")
|
|
23912
24105
|
});
|
|
23913
|
-
var actionSchema =
|
|
23914
|
-
type:
|
|
23915
|
-
params:
|
|
24106
|
+
var actionSchema = z67.object({
|
|
24107
|
+
type: z67.enum(["send_whatsapp", "send_message", "create_task", "mcp_tool"]).describe("Action type to execute"),
|
|
24108
|
+
params: z67.record(z67.string(), z67.string()).describe(
|
|
23916
24109
|
"Action parameters. Supports {{record.field}} templates for dynamic values."
|
|
23917
24110
|
)
|
|
23918
24111
|
});
|
|
@@ -23923,18 +24116,18 @@ function registerCreateTrigger(server2) {
|
|
|
23923
24116
|
title: "Create Trigger",
|
|
23924
24117
|
description: "Create a CRM event trigger or scheduled automation. When matching events occur (e.g., Deal.updated with stage=won), configured actions fire automatically (send_whatsapp, create_task, etc.).",
|
|
23925
24118
|
inputSchema: {
|
|
23926
|
-
name:
|
|
23927
|
-
event:
|
|
24119
|
+
name: z67.string().describe("Human-readable trigger name"),
|
|
24120
|
+
event: z67.string().describe(
|
|
23928
24121
|
'CRM event to match, e.g., "Deal.updated", "Order.created", "*" for all'
|
|
23929
24122
|
),
|
|
23930
|
-
conditions:
|
|
23931
|
-
actions:
|
|
23932
|
-
project:
|
|
23933
|
-
enabled:
|
|
23934
|
-
schedule:
|
|
24123
|
+
conditions: z67.array(conditionSchema).default([]).describe("Conditions that must all match (AND logic)"),
|
|
24124
|
+
actions: z67.array(actionSchema).min(1).describe("Actions to execute when trigger fires"),
|
|
24125
|
+
project: z67.string().optional().describe("Scope trigger to a specific project"),
|
|
24126
|
+
enabled: z67.boolean().default(true).describe("Whether trigger is active"),
|
|
24127
|
+
schedule: z67.string().optional().describe(
|
|
23935
24128
|
'Cron schedule for time-based triggers, e.g., "0 9 * * *" or "Monday 9am"'
|
|
23936
24129
|
),
|
|
23937
|
-
query:
|
|
24130
|
+
query: z67.string().optional().describe(
|
|
23938
24131
|
"CRM GraphQL query to run on schedule (required if schedule is set)"
|
|
23939
24132
|
)
|
|
23940
24133
|
}
|
|
@@ -24007,7 +24200,7 @@ Enabled: ${trigger.enabled}` + scheduleInfo;
|
|
|
24007
24200
|
}
|
|
24008
24201
|
|
|
24009
24202
|
// src/mcp/tools/list-triggers.ts
|
|
24010
|
-
import { z as
|
|
24203
|
+
import { z as z68 } from "zod";
|
|
24011
24204
|
function registerListTriggers(server2) {
|
|
24012
24205
|
server2.registerTool(
|
|
24013
24206
|
"list_triggers",
|
|
@@ -24015,7 +24208,7 @@ function registerListTriggers(server2) {
|
|
|
24015
24208
|
title: "List Triggers",
|
|
24016
24209
|
description: "List configured CRM event triggers and scheduled automations.",
|
|
24017
24210
|
inputSchema: {
|
|
24018
|
-
project:
|
|
24211
|
+
project: z68.string().optional().describe("Filter triggers by project name")
|
|
24019
24212
|
}
|
|
24020
24213
|
},
|
|
24021
24214
|
async ({ project }) => {
|
|
@@ -24050,51 +24243,51 @@ function registerListTriggers(server2) {
|
|
|
24050
24243
|
}
|
|
24051
24244
|
|
|
24052
24245
|
// src/mcp/tools/apply-starter-pack.ts
|
|
24053
|
-
import { z as
|
|
24246
|
+
import { z as z69 } from "zod";
|
|
24054
24247
|
|
|
24055
24248
|
// src/automation/starter-packs/index.ts
|
|
24056
|
-
import { readFileSync as
|
|
24057
|
-
import
|
|
24058
|
-
import { fileURLToPath as
|
|
24059
|
-
var __dirname =
|
|
24249
|
+
import { readFileSync as readFileSync27, readdirSync as readdirSync12, existsSync as existsSync35 } from "fs";
|
|
24250
|
+
import path42 from "path";
|
|
24251
|
+
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
24252
|
+
var __dirname = path42.dirname(fileURLToPath5(import.meta.url));
|
|
24060
24253
|
function listPacks() {
|
|
24061
|
-
const packsDir =
|
|
24062
|
-
if (!
|
|
24254
|
+
const packsDir = path42.join(__dirname, ".");
|
|
24255
|
+
if (!existsSync35(packsDir)) return [];
|
|
24063
24256
|
return readdirSync12(packsDir, { withFileTypes: true }).filter(
|
|
24064
|
-
(d) => d.isDirectory() &&
|
|
24257
|
+
(d) => d.isDirectory() && existsSync35(path42.join(packsDir, d.name, "custom-objects.json"))
|
|
24065
24258
|
).map((d) => d.name);
|
|
24066
24259
|
}
|
|
24067
24260
|
function loadPack(industry) {
|
|
24068
|
-
const packDir =
|
|
24069
|
-
const objectsPath =
|
|
24070
|
-
const triggersPath =
|
|
24071
|
-
const wikiDir =
|
|
24072
|
-
const manifestPath =
|
|
24073
|
-
const identityContextPath =
|
|
24074
|
-
if (!
|
|
24261
|
+
const packDir = path42.join(__dirname, industry);
|
|
24262
|
+
const objectsPath = path42.join(packDir, "custom-objects.json");
|
|
24263
|
+
const triggersPath = path42.join(packDir, "triggers.json");
|
|
24264
|
+
const wikiDir = path42.join(packDir, "wiki-seeds");
|
|
24265
|
+
const manifestPath = path42.join(packDir, "pack.json");
|
|
24266
|
+
const identityContextPath = path42.join(packDir, "identity-context.md");
|
|
24267
|
+
if (!existsSync35(objectsPath)) return null;
|
|
24075
24268
|
let customObjects = [];
|
|
24076
24269
|
try {
|
|
24077
24270
|
customObjects = JSON.parse(
|
|
24078
|
-
|
|
24271
|
+
readFileSync27(objectsPath, "utf-8")
|
|
24079
24272
|
);
|
|
24080
24273
|
} catch {
|
|
24081
24274
|
customObjects = [];
|
|
24082
24275
|
}
|
|
24083
24276
|
let triggers = [];
|
|
24084
|
-
if (
|
|
24277
|
+
if (existsSync35(triggersPath)) {
|
|
24085
24278
|
try {
|
|
24086
24279
|
triggers = JSON.parse(
|
|
24087
|
-
|
|
24280
|
+
readFileSync27(triggersPath, "utf-8")
|
|
24088
24281
|
);
|
|
24089
24282
|
} catch {
|
|
24090
24283
|
triggers = [];
|
|
24091
24284
|
}
|
|
24092
24285
|
}
|
|
24093
24286
|
const wikiSeeds = [];
|
|
24094
|
-
if (
|
|
24287
|
+
if (existsSync35(wikiDir)) {
|
|
24095
24288
|
const files = readdirSync12(wikiDir).filter((f) => f.endsWith(".md"));
|
|
24096
24289
|
for (const file of files) {
|
|
24097
|
-
const content =
|
|
24290
|
+
const content = readFileSync27(path42.join(wikiDir, file), "utf-8");
|
|
24098
24291
|
const titleMatch = content.match(/^#\s+(.+)/m);
|
|
24099
24292
|
wikiSeeds.push({
|
|
24100
24293
|
filename: file,
|
|
@@ -24104,17 +24297,17 @@ function loadPack(industry) {
|
|
|
24104
24297
|
}
|
|
24105
24298
|
}
|
|
24106
24299
|
let manifest = {};
|
|
24107
|
-
if (
|
|
24300
|
+
if (existsSync35(manifestPath)) {
|
|
24108
24301
|
try {
|
|
24109
|
-
manifest = JSON.parse(
|
|
24302
|
+
manifest = JSON.parse(readFileSync27(manifestPath, "utf-8"));
|
|
24110
24303
|
} catch {
|
|
24111
24304
|
manifest = {};
|
|
24112
24305
|
}
|
|
24113
24306
|
}
|
|
24114
24307
|
let identityContext = null;
|
|
24115
|
-
if (
|
|
24308
|
+
if (existsSync35(identityContextPath)) {
|
|
24116
24309
|
try {
|
|
24117
|
-
identityContext =
|
|
24310
|
+
identityContext = readFileSync27(identityContextPath, "utf-8");
|
|
24118
24311
|
} catch {
|
|
24119
24312
|
identityContext = null;
|
|
24120
24313
|
}
|
|
@@ -24171,8 +24364,8 @@ function applyPack(industry, project) {
|
|
|
24171
24364
|
|
|
24172
24365
|
// src/lib/client-coo.ts
|
|
24173
24366
|
init_config();
|
|
24174
|
-
import { existsSync as
|
|
24175
|
-
import
|
|
24367
|
+
import { existsSync as existsSync36, mkdirSync as mkdirSync18, writeFileSync as writeFileSync20 } from "fs";
|
|
24368
|
+
import path43 from "path";
|
|
24176
24369
|
|
|
24177
24370
|
// src/lib/employee-templates.ts
|
|
24178
24371
|
init_global_procedures();
|
|
@@ -24312,18 +24505,18 @@ var ClientCOOClobberError = class extends Error {
|
|
|
24312
24505
|
var COO_ROLE = "Chief Operating Officer";
|
|
24313
24506
|
var FEEDBACK_BEHAVIOR_CONTENT = "Tag exe-os issues with needs_improvement \u2014 this is the feedback loop that surfaces bugs, gaps, and friction to the founder each Monday.";
|
|
24314
24507
|
async function provisionClientCOO(vars, opts = {}) {
|
|
24315
|
-
const identityDir = opts.identityDir ??
|
|
24508
|
+
const identityDir = opts.identityDir ?? path43.join(EXE_AI_DIR, "identity");
|
|
24316
24509
|
const rosterPath = opts.employeesPath ?? EMPLOYEES_PATH;
|
|
24317
24510
|
const storeFeedbackBehavior = opts.storeFeedbackBehavior ?? true;
|
|
24318
|
-
const identityPath2 =
|
|
24319
|
-
if (
|
|
24511
|
+
const identityPath2 = path43.join(identityDir, `${vars.agent_name}.md`);
|
|
24512
|
+
if (existsSync36(identityPath2)) {
|
|
24320
24513
|
throw new ClientCOOClobberError(vars.agent_name, identityPath2);
|
|
24321
24514
|
}
|
|
24322
24515
|
const body = renderClientCOOTemplate(vars);
|
|
24323
|
-
if (!
|
|
24324
|
-
|
|
24516
|
+
if (!existsSync36(identityDir)) {
|
|
24517
|
+
mkdirSync18(identityDir, { recursive: true });
|
|
24325
24518
|
}
|
|
24326
|
-
|
|
24519
|
+
writeFileSync20(identityPath2, body, "utf-8");
|
|
24327
24520
|
const employees = await loadEmployees(rosterPath);
|
|
24328
24521
|
const existing = employees.find((e) => e.name === vars.agent_name);
|
|
24329
24522
|
let addedToRoster = false;
|
|
@@ -24359,17 +24552,17 @@ function registerApplyStarterPack(server2) {
|
|
|
24359
24552
|
title: "Apply Starter Pack",
|
|
24360
24553
|
description: "Apply an industry starter pack to a project. Sets up CRM custom objects, pre-wired automation triggers, and wiki seed content. When the pack creates a Client COO (e.g. distribution) and agent_name, company_name, founder_name are all provided, also provisions the COO identity, roster entry, and feedback-loop behavior. Available packs: distribution. More coming.",
|
|
24361
24554
|
inputSchema: {
|
|
24362
|
-
industry:
|
|
24555
|
+
industry: z69.string().describe(
|
|
24363
24556
|
'Industry pack to apply (e.g., "distribution"). Use without args to list available packs.'
|
|
24364
24557
|
),
|
|
24365
|
-
project:
|
|
24366
|
-
agent_name:
|
|
24558
|
+
project: z69.string().describe("Project name to scope the triggers to"),
|
|
24559
|
+
agent_name: z69.string().optional().describe(
|
|
24367
24560
|
"Optional. Lowercase alphanumeric name for the Client COO agent. Required (alongside company_name and founder_name) to provision a COO."
|
|
24368
24561
|
),
|
|
24369
|
-
company_name:
|
|
24562
|
+
company_name: z69.string().optional().describe(
|
|
24370
24563
|
"Optional. The client company the COO serves. Required to provision a COO."
|
|
24371
24564
|
),
|
|
24372
|
-
founder_name:
|
|
24565
|
+
founder_name: z69.string().optional().describe(
|
|
24373
24566
|
"Optional. The founder the COO reports to. Required to provision a COO."
|
|
24374
24567
|
)
|
|
24375
24568
|
}
|
|
@@ -24514,20 +24707,20 @@ ${err.message}`
|
|
|
24514
24707
|
}
|
|
24515
24708
|
|
|
24516
24709
|
// src/mcp/tools/load-skill.ts
|
|
24517
|
-
import { z as
|
|
24518
|
-
import { readFileSync as
|
|
24519
|
-
import
|
|
24520
|
-
import { homedir as
|
|
24521
|
-
var SKILLS_DIR =
|
|
24710
|
+
import { z as z70 } from "zod";
|
|
24711
|
+
import { readFileSync as readFileSync28, readdirSync as readdirSync13, statSync as statSync8 } from "fs";
|
|
24712
|
+
import path44 from "path";
|
|
24713
|
+
import { homedir as homedir8 } from "os";
|
|
24714
|
+
var SKILLS_DIR = path44.join(homedir8(), ".claude", "skills");
|
|
24522
24715
|
function listAvailableSkills() {
|
|
24523
24716
|
try {
|
|
24524
24717
|
const entries = readdirSync13(SKILLS_DIR);
|
|
24525
24718
|
return entries.filter((entry) => {
|
|
24526
24719
|
try {
|
|
24527
|
-
const entryPath =
|
|
24528
|
-
if (!
|
|
24529
|
-
const skillFile =
|
|
24530
|
-
|
|
24720
|
+
const entryPath = path44.join(SKILLS_DIR, entry);
|
|
24721
|
+
if (!statSync8(entryPath).isDirectory()) return false;
|
|
24722
|
+
const skillFile = path44.join(entryPath, "SKILL.md");
|
|
24723
|
+
statSync8(skillFile);
|
|
24531
24724
|
return true;
|
|
24532
24725
|
} catch {
|
|
24533
24726
|
return false;
|
|
@@ -24544,7 +24737,7 @@ function registerLoadSkill(server2) {
|
|
|
24544
24737
|
title: "Load Skill",
|
|
24545
24738
|
description: "Load domain-specific guidance into your context. Use when you need specialized knowledge for a task (e.g., load_skill('seo') before doing SEO work, load_skill('code-reviewer') before reviewing code). Pass skill_name='list' to see all available skills.",
|
|
24546
24739
|
inputSchema: {
|
|
24547
|
-
skill_name:
|
|
24740
|
+
skill_name: z70.string().describe(
|
|
24548
24741
|
"Skill to load (e.g. 'seo', 'code-reviewer', 'frontend-design'). Pass 'list' to see all available skills."
|
|
24549
24742
|
)
|
|
24550
24743
|
}
|
|
@@ -24569,10 +24762,10 @@ ${skills.map((s) => `- ${s}`).join("\n")}`
|
|
|
24569
24762
|
}]
|
|
24570
24763
|
};
|
|
24571
24764
|
}
|
|
24572
|
-
const sanitized =
|
|
24573
|
-
const skillFile =
|
|
24765
|
+
const sanitized = path44.basename(skill_name);
|
|
24766
|
+
const skillFile = path44.join(SKILLS_DIR, sanitized, "SKILL.md");
|
|
24574
24767
|
try {
|
|
24575
|
-
const content =
|
|
24768
|
+
const content = readFileSync28(skillFile, "utf-8");
|
|
24576
24769
|
return {
|
|
24577
24770
|
content: [{
|
|
24578
24771
|
type: "text",
|
|
@@ -24600,18 +24793,18 @@ ${available.map((s) => `- ${s}`).join("\n")}` : "\n\nNo skills found in ~/.claud
|
|
|
24600
24793
|
|
|
24601
24794
|
// src/mcp/tools/export-orchestration.ts
|
|
24602
24795
|
init_active_agent();
|
|
24603
|
-
import { mkdirSync as
|
|
24604
|
-
import
|
|
24605
|
-
import { z as
|
|
24796
|
+
import { mkdirSync as mkdirSync20, writeFileSync as writeFileSync22 } from "fs";
|
|
24797
|
+
import path46 from "path";
|
|
24798
|
+
import { z as z71 } from "zod";
|
|
24606
24799
|
|
|
24607
24800
|
// src/lib/orchestration-package.ts
|
|
24608
24801
|
init_database();
|
|
24609
24802
|
init_identity();
|
|
24610
24803
|
init_platform_procedures();
|
|
24611
24804
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
24612
|
-
import { copyFileSync as copyFileSync2, existsSync as
|
|
24805
|
+
import { copyFileSync as copyFileSync2, existsSync as existsSync37, mkdirSync as mkdirSync19, readFileSync as readFileSync29, writeFileSync as writeFileSync21 } from "fs";
|
|
24613
24806
|
import os18 from "os";
|
|
24614
|
-
import
|
|
24807
|
+
import path45 from "path";
|
|
24615
24808
|
var PACKAGE_VERSION = "1.0";
|
|
24616
24809
|
var ROSTER_FILENAME = "exe-employees.json";
|
|
24617
24810
|
var ROSTER_BACKUP_FILENAME = "exe-employees.json.bak";
|
|
@@ -24677,15 +24870,15 @@ function validateProcedureEntry(value, index) {
|
|
|
24677
24870
|
};
|
|
24678
24871
|
}
|
|
24679
24872
|
function getRosterPath() {
|
|
24680
|
-
return
|
|
24873
|
+
return path45.join(os18.homedir(), EXE_OS_DIRNAME, ROSTER_FILENAME);
|
|
24681
24874
|
}
|
|
24682
24875
|
function getBackupPath() {
|
|
24683
|
-
return
|
|
24876
|
+
return path45.join(os18.homedir(), EXE_OS_DIRNAME, ROSTER_BACKUP_FILENAME);
|
|
24684
24877
|
}
|
|
24685
24878
|
function readRosterFile() {
|
|
24686
24879
|
const rosterPath = getRosterPath();
|
|
24687
|
-
if (!
|
|
24688
|
-
const raw =
|
|
24880
|
+
if (!existsSync37(rosterPath)) return [];
|
|
24881
|
+
const raw = readFileSync29(rosterPath, "utf-8");
|
|
24689
24882
|
const parsed = JSON.parse(raw);
|
|
24690
24883
|
if (!Array.isArray(parsed)) {
|
|
24691
24884
|
throw new Error("Roster file must contain a JSON array");
|
|
@@ -24697,8 +24890,8 @@ function writeRosterFile(roster) {
|
|
|
24697
24890
|
throw new Error("Refusing to write empty roster \u2014 this would delete all employees");
|
|
24698
24891
|
}
|
|
24699
24892
|
const rosterPath = getRosterPath();
|
|
24700
|
-
|
|
24701
|
-
if (
|
|
24893
|
+
mkdirSync19(path45.dirname(rosterPath), { recursive: true });
|
|
24894
|
+
if (existsSync37(rosterPath)) {
|
|
24702
24895
|
const currentRoster = readRosterFile();
|
|
24703
24896
|
if (roster.length < currentRoster.length) {
|
|
24704
24897
|
throw new Error(
|
|
@@ -24707,7 +24900,7 @@ function writeRosterFile(roster) {
|
|
|
24707
24900
|
}
|
|
24708
24901
|
copyFileSync2(rosterPath, getBackupPath());
|
|
24709
24902
|
}
|
|
24710
|
-
|
|
24903
|
+
writeFileSync21(rosterPath, `${JSON.stringify(roster, null, 2)}
|
|
24711
24904
|
`, "utf-8");
|
|
24712
24905
|
}
|
|
24713
24906
|
function buildImportedRosterEntries(roster, timestamp) {
|
|
@@ -24962,15 +25155,15 @@ function registerExportOrchestration(server2) {
|
|
|
24962
25155
|
title: "Export Orchestration",
|
|
24963
25156
|
description: "Export roster, identities, behaviors, and customer procedures to a JSON package.",
|
|
24964
25157
|
inputSchema: {
|
|
24965
|
-
output_path:
|
|
25158
|
+
output_path: z71.string().describe("File path to write the JSON package")
|
|
24966
25159
|
}
|
|
24967
25160
|
},
|
|
24968
25161
|
async ({ output_path }) => {
|
|
24969
25162
|
try {
|
|
24970
25163
|
await initStore();
|
|
24971
25164
|
const pkg = await exportOrchestration(getActiveAgent().agentId);
|
|
24972
|
-
|
|
24973
|
-
|
|
25165
|
+
mkdirSync20(path46.dirname(output_path), { recursive: true });
|
|
25166
|
+
writeFileSync22(output_path, `${JSON.stringify(pkg, null, 2)}
|
|
24974
25167
|
`, "utf-8");
|
|
24975
25168
|
return {
|
|
24976
25169
|
content: [{
|
|
@@ -24992,8 +25185,8 @@ function registerExportOrchestration(server2) {
|
|
|
24992
25185
|
}
|
|
24993
25186
|
|
|
24994
25187
|
// src/mcp/tools/import-orchestration.ts
|
|
24995
|
-
import { readFileSync as
|
|
24996
|
-
import { z as
|
|
25188
|
+
import { readFileSync as readFileSync30 } from "fs";
|
|
25189
|
+
import { z as z72 } from "zod";
|
|
24997
25190
|
init_store();
|
|
24998
25191
|
init_active_agent();
|
|
24999
25192
|
init_employees();
|
|
@@ -25004,8 +25197,8 @@ function registerImportOrchestration(server2) {
|
|
|
25004
25197
|
title: "Import Orchestration",
|
|
25005
25198
|
description: "Import roster, identities, behaviors, and procedures from an orchestration package. Restricted to coordinator/founder.",
|
|
25006
25199
|
inputSchema: {
|
|
25007
|
-
package_path:
|
|
25008
|
-
merge_strategy:
|
|
25200
|
+
package_path: z72.string().describe("Path to the orchestration package JSON file"),
|
|
25201
|
+
merge_strategy: z72.enum(["replace", "merge"]).default("merge").describe("How to apply the package: both strategies are additive-only \u2014 existing data is never deleted or overwritten")
|
|
25009
25202
|
}
|
|
25010
25203
|
},
|
|
25011
25204
|
async ({ package_path, merge_strategy }) => {
|
|
@@ -25022,7 +25215,7 @@ function registerImportOrchestration(server2) {
|
|
|
25022
25215
|
};
|
|
25023
25216
|
}
|
|
25024
25217
|
await initStore();
|
|
25025
|
-
const raw =
|
|
25218
|
+
const raw = readFileSync30(package_path, "utf-8");
|
|
25026
25219
|
const pkg = validatePackage(JSON.parse(raw));
|
|
25027
25220
|
const result2 = await importOrchestration(pkg, merge_strategy);
|
|
25028
25221
|
return {
|
|
@@ -25050,7 +25243,7 @@ init_platform_procedures();
|
|
|
25050
25243
|
init_active_agent();
|
|
25051
25244
|
init_database();
|
|
25052
25245
|
init_employees();
|
|
25053
|
-
import { z as
|
|
25246
|
+
import { z as z73 } from "zod";
|
|
25054
25247
|
function registerCompanyProcedureTool(server2, toolName) {
|
|
25055
25248
|
server2.registerTool(
|
|
25056
25249
|
toolName,
|
|
@@ -25058,12 +25251,12 @@ function registerCompanyProcedureTool(server2, toolName) {
|
|
|
25058
25251
|
title: "Company Procedure",
|
|
25059
25252
|
description: "Manage company procedures (customer-owned Layer 0 rules) that supersede identity, expertise, and experience. Actions: store (create new, restricted), list (view all, open), deactivate (soft-delete, restricted).",
|
|
25060
25253
|
inputSchema: {
|
|
25061
|
-
action:
|
|
25062
|
-
title:
|
|
25063
|
-
content:
|
|
25064
|
-
priority:
|
|
25065
|
-
domain:
|
|
25066
|
-
procedure_id:
|
|
25254
|
+
action: z73.enum(["store", "list", "deactivate"]).describe("Action to perform"),
|
|
25255
|
+
title: z73.string().optional().describe("Short title for the procedure (store)"),
|
|
25256
|
+
content: z73.string().max(500).optional().describe("The procedure content \u2014 clear, actionable instruction (store)"),
|
|
25257
|
+
priority: z73.enum(["p0", "p1", "p2"]).optional().describe("Priority tier. p0 = always (default). p1 = standard. p2 = nice-to-have."),
|
|
25258
|
+
domain: z73.string().optional().describe("Category: workflow, code-style, communication, architecture, testing, security"),
|
|
25259
|
+
procedure_id: z73.string().optional().describe("UUID of the company procedure (deactivate)")
|
|
25067
25260
|
}
|
|
25068
25261
|
},
|
|
25069
25262
|
async ({ action, title, content, priority, domain, procedure_id }) => {
|
|
@@ -25191,6 +25384,7 @@ var ACTION_TO_TOOL2 = {
|
|
|
25191
25384
|
list_agent_sessions: "list_agent_sessions",
|
|
25192
25385
|
session_kills: "get_session_kills",
|
|
25193
25386
|
daemon_health: "get_daemon_health",
|
|
25387
|
+
mcp_ping: "mcp_ping",
|
|
25194
25388
|
auto_wake_status: "get_auto_wake_status",
|
|
25195
25389
|
worker_gate: "get_worker_gate",
|
|
25196
25390
|
memory_audit: "run_memory_audit",
|
|
@@ -25228,6 +25422,7 @@ function buildHandlers5() {
|
|
|
25228
25422
|
registerListAgentSessions(localServer);
|
|
25229
25423
|
registerGetSessionKills(localServer);
|
|
25230
25424
|
registerGetDaemonHealth(localServer);
|
|
25425
|
+
registerMcpPing(localServer);
|
|
25231
25426
|
registerGetAutoWakeStatus(localServer);
|
|
25232
25427
|
registerGetWorkerGate(localServer);
|
|
25233
25428
|
registerRunMemoryAudit(localServer);
|
|
@@ -25256,44 +25451,44 @@ function registerConfig(server2) {
|
|
|
25256
25451
|
title: "Config",
|
|
25257
25452
|
description: "Consolidated COO/admin tool for runtime config, system health, licensing, triggers, orchestration import/export, and company procedures.",
|
|
25258
25453
|
inputSchema: {
|
|
25259
|
-
action:
|
|
25260
|
-
agent_id:
|
|
25261
|
-
runtime:
|
|
25262
|
-
model:
|
|
25263
|
-
reasoning_effort:
|
|
25264
|
-
dry_run:
|
|
25265
|
-
fix:
|
|
25266
|
-
verbose:
|
|
25267
|
-
project_name:
|
|
25268
|
-
since:
|
|
25269
|
-
limit:
|
|
25270
|
-
output_path:
|
|
25271
|
-
input_path:
|
|
25272
|
-
strategy:
|
|
25273
|
-
license_key:
|
|
25274
|
-
email:
|
|
25275
|
-
plan:
|
|
25276
|
-
name:
|
|
25277
|
-
event:
|
|
25278
|
-
conditions:
|
|
25279
|
-
actions:
|
|
25280
|
-
enabled:
|
|
25281
|
-
schedule:
|
|
25282
|
-
query:
|
|
25283
|
-
skill_name:
|
|
25284
|
-
pack_name:
|
|
25285
|
-
title:
|
|
25286
|
-
content:
|
|
25287
|
-
priority:
|
|
25288
|
-
domain:
|
|
25289
|
-
procedure_id:
|
|
25290
|
-
subaction:
|
|
25291
|
-
max_clusters:
|
|
25292
|
-
force:
|
|
25293
|
-
cloud_action:
|
|
25294
|
-
confirm_local_db_source_of_truth:
|
|
25295
|
-
domain_name:
|
|
25296
|
-
phase:
|
|
25454
|
+
action: z74.enum(Object.keys(ACTION_TO_TOOL2)).describe("Admin/config operation"),
|
|
25455
|
+
agent_id: z74.string().optional().describe("Agent id for set_agent_config/agent_spend/session queries"),
|
|
25456
|
+
runtime: z74.string().optional().describe("Runtime for set_agent_config"),
|
|
25457
|
+
model: z74.string().optional().describe("Model for set_agent_config"),
|
|
25458
|
+
reasoning_effort: z74.string().optional().describe("Reasoning effort for Codex agents"),
|
|
25459
|
+
dry_run: z74.boolean().optional().describe("Preview without applying where supported"),
|
|
25460
|
+
fix: z74.boolean().optional().describe("Apply fixes for memory_audit where supported"),
|
|
25461
|
+
verbose: z74.boolean().optional().describe("Verbose output where supported"),
|
|
25462
|
+
project_name: z74.string().optional().describe("Project filter/name"),
|
|
25463
|
+
since: z74.string().optional().describe("ISO lower-bound timestamp"),
|
|
25464
|
+
limit: z74.coerce.number().optional().describe("Result limit"),
|
|
25465
|
+
output_path: z74.string().optional().describe("Output path for export/backup"),
|
|
25466
|
+
input_path: z74.string().optional().describe("Input path for import_orchestration"),
|
|
25467
|
+
strategy: z74.enum(["merge", "replace"]).optional().describe("Import strategy; replace must still be additive-only per platform rules"),
|
|
25468
|
+
license_key: z74.string().optional().describe("License key for activation/status"),
|
|
25469
|
+
email: z74.string().optional().describe("Customer email for license creation"),
|
|
25470
|
+
plan: z74.string().optional().describe("License plan"),
|
|
25471
|
+
name: z74.string().optional().describe("Trigger/starter pack/procedure/client name"),
|
|
25472
|
+
event: z74.string().optional().describe("Trigger event"),
|
|
25473
|
+
conditions: z74.array(z74.record(z74.string(), z74.unknown())).optional().describe("Trigger conditions"),
|
|
25474
|
+
actions: z74.array(z74.record(z74.string(), z74.unknown())).optional().describe("Trigger actions"),
|
|
25475
|
+
enabled: z74.boolean().optional().describe("Trigger enabled flag"),
|
|
25476
|
+
schedule: z74.string().optional().describe("Trigger schedule"),
|
|
25477
|
+
query: z74.string().optional().describe("Trigger query or filter"),
|
|
25478
|
+
skill_name: z74.string().optional().describe("Skill name for load_skill"),
|
|
25479
|
+
pack_name: z74.string().optional().describe("Starter pack name"),
|
|
25480
|
+
title: z74.string().optional().describe("Procedure title"),
|
|
25481
|
+
content: z74.string().optional().describe("Procedure content"),
|
|
25482
|
+
priority: z74.enum(["p0", "p1", "p2"]).optional().describe("Procedure priority"),
|
|
25483
|
+
domain: z74.string().optional().describe("Procedure domain"),
|
|
25484
|
+
procedure_id: z74.string().optional().describe("Procedure id for deactivate"),
|
|
25485
|
+
subaction: z74.enum(["store", "list", "deactivate"]).optional().describe("Nested action for company_procedure/global_procedure"),
|
|
25486
|
+
max_clusters: z74.coerce.number().optional().describe("Consolidation max clusters"),
|
|
25487
|
+
force: z74.boolean().optional().describe("Force operation where supported"),
|
|
25488
|
+
cloud_action: z74.enum(["status", "sync", "reupload"]).optional().describe("Nested operation for action=cloud_sync"),
|
|
25489
|
+
confirm_local_db_source_of_truth: z74.string().optional().describe("Required for cloud_action=reupload; must exactly equal LOCAL DB IS SOURCE OF TRUTH"),
|
|
25490
|
+
domain_name: z74.string().optional().describe("Client deployment domain"),
|
|
25491
|
+
phase: z74.enum(["phase_1_coo", "phase_2_executives", "phase_3_parallel_org", "1", "2", "3"]).optional().describe("Orchestration phase for orchestration_phase action")
|
|
25297
25492
|
}
|
|
25298
25493
|
}, async (input, extra) => {
|
|
25299
25494
|
const action = input.action;
|
|
@@ -25317,10 +25512,10 @@ function registerConfig(server2) {
|
|
|
25317
25512
|
}
|
|
25318
25513
|
|
|
25319
25514
|
// src/mcp/tools/wiki.ts
|
|
25320
|
-
import { z as
|
|
25515
|
+
import { z as z77 } from "zod";
|
|
25321
25516
|
|
|
25322
25517
|
// src/mcp/tools/list-wiki-pages.ts
|
|
25323
|
-
import { z as
|
|
25518
|
+
import { z as z75 } from "zod";
|
|
25324
25519
|
var FETCH_TIMEOUT_MS3 = 1e4;
|
|
25325
25520
|
function registerListWikiPages(server2) {
|
|
25326
25521
|
server2.registerTool(
|
|
@@ -25329,8 +25524,8 @@ function registerListWikiPages(server2) {
|
|
|
25329
25524
|
title: "List Wiki Pages",
|
|
25330
25525
|
description: "List documents in an exe-wiki workspace. Optionally filter by folder.",
|
|
25331
25526
|
inputSchema: {
|
|
25332
|
-
workspace:
|
|
25333
|
-
folder:
|
|
25527
|
+
workspace: z75.string().describe('Wiki workspace slug (e.g., "hygo")'),
|
|
25528
|
+
folder: z75.string().optional().describe("Filter by folder path")
|
|
25334
25529
|
}
|
|
25335
25530
|
},
|
|
25336
25531
|
async ({ workspace, folder }) => {
|
|
@@ -25419,7 +25614,7 @@ function registerListWikiPages(server2) {
|
|
|
25419
25614
|
}
|
|
25420
25615
|
|
|
25421
25616
|
// src/mcp/tools/get-wiki-page.ts
|
|
25422
|
-
import { z as
|
|
25617
|
+
import { z as z76 } from "zod";
|
|
25423
25618
|
var FETCH_TIMEOUT_MS4 = 1e4;
|
|
25424
25619
|
function registerGetWikiPage(server2) {
|
|
25425
25620
|
server2.registerTool(
|
|
@@ -25428,9 +25623,9 @@ function registerGetWikiPage(server2) {
|
|
|
25428
25623
|
title: "Get Wiki Page",
|
|
25429
25624
|
description: "Read a wiki page by document ID or title. Returns content, metadata, and folder path. Use title search when you know the page name but not the ID.",
|
|
25430
25625
|
inputSchema: {
|
|
25431
|
-
workspace:
|
|
25432
|
-
document_id:
|
|
25433
|
-
title:
|
|
25626
|
+
workspace: z76.string().describe('Wiki workspace slug (e.g., "hygo")'),
|
|
25627
|
+
document_id: z76.string().optional().describe("Specific document ID (exact lookup)"),
|
|
25628
|
+
title: z76.string().optional().describe("Search by title (fuzzy match)")
|
|
25434
25629
|
}
|
|
25435
25630
|
},
|
|
25436
25631
|
async ({ workspace, document_id, title }) => {
|
|
@@ -25612,14 +25807,14 @@ function registerWiki(server2) {
|
|
|
25612
25807
|
title: "Wiki",
|
|
25613
25808
|
description: "Consolidated wiki domain tool. Actions: list, get. Wiki writes flow through raw data ingestion/projection into the curated wiki store; direct create/update MCP tools have been removed.",
|
|
25614
25809
|
inputSchema: {
|
|
25615
|
-
action:
|
|
25616
|
-
workspace:
|
|
25617
|
-
title:
|
|
25618
|
-
content:
|
|
25619
|
-
folder:
|
|
25620
|
-
document_id:
|
|
25621
|
-
mode:
|
|
25622
|
-
section:
|
|
25810
|
+
action: z77.enum(["list", "get"]).describe("Wiki read operation. Writes use raw-data ingestion/projection, not direct MCP writes."),
|
|
25811
|
+
workspace: z77.string().optional().describe("Wiki workspace slug"),
|
|
25812
|
+
title: z77.string().optional().describe("Fuzzy page title lookup for get"),
|
|
25813
|
+
content: z77.string().optional().describe("Reserved; wiki writes use raw-data ingestion/projection"),
|
|
25814
|
+
folder: z77.string().optional().describe("Optional folder path for list"),
|
|
25815
|
+
document_id: z77.string().optional().describe("Document ID for get"),
|
|
25816
|
+
mode: z77.enum(["replace", "append"]).optional().describe("Reserved; direct wiki updates are removed"),
|
|
25817
|
+
section: z77.string().optional().describe("Reserved; direct wiki updates are removed")
|
|
25623
25818
|
}
|
|
25624
25819
|
},
|
|
25625
25820
|
async (input, extra) => {
|
|
@@ -25647,7 +25842,7 @@ init_active_agent();
|
|
|
25647
25842
|
init_project_name();
|
|
25648
25843
|
init_database();
|
|
25649
25844
|
init_employees();
|
|
25650
|
-
import { z as
|
|
25845
|
+
import { z as z78 } from "zod";
|
|
25651
25846
|
function rowToBehavior2(r) {
|
|
25652
25847
|
return {
|
|
25653
25848
|
id: String(r.id),
|
|
@@ -25669,13 +25864,13 @@ function registerBehavior(server2) {
|
|
|
25669
25864
|
title: "Behavior",
|
|
25670
25865
|
description: "Manage behavioral patterns, corrections, and reusable procedures for employees. Actions: store (create new), list (query existing), deactivate (soft-delete, restricted).",
|
|
25671
25866
|
inputSchema: {
|
|
25672
|
-
action:
|
|
25673
|
-
content:
|
|
25674
|
-
domain:
|
|
25675
|
-
priority:
|
|
25676
|
-
agent_id:
|
|
25677
|
-
project_name:
|
|
25678
|
-
behavior_id:
|
|
25867
|
+
action: z78.enum(["store", "list", "deactivate"]).describe("Action to perform"),
|
|
25868
|
+
content: z78.string().max(500).optional().describe("The behavioral instruction \u2014 one clear sentence (store)"),
|
|
25869
|
+
domain: z78.string().optional().describe("Category: workflow, code-style, tool-use, communication, architecture, testing"),
|
|
25870
|
+
priority: z78.enum(["p0", "p1", "p2"]).optional().describe("Priority tier. p0 = always included. p1 = standard (default). p2 = nice-to-have."),
|
|
25871
|
+
agent_id: z78.string().optional().describe("Employee name. Defaults to current agent. Pass 'all' to list everyone's (list only)."),
|
|
25872
|
+
project_name: z78.string().optional().describe("Defaults to current project. Pass 'global' for a behavior that applies everywhere (store)."),
|
|
25873
|
+
behavior_id: z78.string().optional().describe("UUID of the behavior (deactivate)")
|
|
25679
25874
|
}
|
|
25680
25875
|
},
|
|
25681
25876
|
async ({ action, content, domain, priority, agent_id, project_name, behavior_id }) => {
|
|
@@ -25846,7 +26041,7 @@ Content: ${row.content}`
|
|
|
25846
26041
|
}
|
|
25847
26042
|
|
|
25848
26043
|
// src/mcp/tools/reminder.ts
|
|
25849
|
-
import { z as
|
|
26044
|
+
import { z as z79 } from "zod";
|
|
25850
26045
|
function registerReminder(server2) {
|
|
25851
26046
|
server2.registerTool(
|
|
25852
26047
|
"reminder",
|
|
@@ -25854,11 +26049,11 @@ function registerReminder(server2) {
|
|
|
25854
26049
|
title: "Reminder",
|
|
25855
26050
|
description: "Manage reminders for the founder. Shown in the boot brief every session. Actions: create (set new), list (view active), complete (mark done).",
|
|
25856
26051
|
inputSchema: {
|
|
25857
|
-
action:
|
|
25858
|
-
text:
|
|
25859
|
-
due_date:
|
|
25860
|
-
reminder_id:
|
|
25861
|
-
include_completed:
|
|
26052
|
+
action: z79.enum(["create", "list", "complete"]).describe("Action to perform"),
|
|
26053
|
+
text: z79.string().optional().describe("What to remind about (create)"),
|
|
26054
|
+
due_date: z79.string().optional().describe("Optional due date \u2014 ISO date (2026-04-01) or null for persistent (create)"),
|
|
26055
|
+
reminder_id: z79.string().optional().describe("Reminder UUID or text substring to match (complete)"),
|
|
26056
|
+
include_completed: z79.boolean().optional().default(false).describe("Include completed reminders (list)")
|
|
25862
26057
|
}
|
|
25863
26058
|
},
|
|
25864
26059
|
async ({ action, text: text3, due_date, reminder_id, include_completed }) => {
|
|
@@ -25914,7 +26109,7 @@ function registerReminder(server2) {
|
|
|
25914
26109
|
init_global_procedures();
|
|
25915
26110
|
init_active_agent();
|
|
25916
26111
|
init_employees();
|
|
25917
|
-
import { z as
|
|
26112
|
+
import { z as z80 } from "zod";
|
|
25918
26113
|
function registerStoreGlobalProcedure(server2) {
|
|
25919
26114
|
server2.registerTool(
|
|
25920
26115
|
"store_global_procedure",
|
|
@@ -25922,10 +26117,10 @@ function registerStoreGlobalProcedure(server2) {
|
|
|
25922
26117
|
title: "Store Company Procedure (use global_procedure instead)",
|
|
25923
26118
|
description: "DEPRECATED \u2014 use global_procedure with action='store'. Create a company procedure (customer-owned Layer 0 rule). RESTRICTED: only coordinator or founder sessions.",
|
|
25924
26119
|
inputSchema: {
|
|
25925
|
-
title:
|
|
25926
|
-
content:
|
|
25927
|
-
priority:
|
|
25928
|
-
domain:
|
|
26120
|
+
title: z80.string().describe("Short title for the procedure"),
|
|
26121
|
+
content: z80.string().max(500).describe("The procedure content \u2014 clear, actionable instruction"),
|
|
26122
|
+
priority: z80.enum(["p0", "p1", "p2"]).optional().describe("Priority tier. p0 = always (default)."),
|
|
26123
|
+
domain: z80.string().optional().describe("Category: workflow, code-style, communication, architecture, testing, security")
|
|
25929
26124
|
}
|
|
25930
26125
|
},
|
|
25931
26126
|
async ({ title, content, priority, domain }) => {
|
|
@@ -26003,7 +26198,7 @@ init_global_procedures();
|
|
|
26003
26198
|
init_active_agent();
|
|
26004
26199
|
init_database();
|
|
26005
26200
|
init_employees();
|
|
26006
|
-
import { z as
|
|
26201
|
+
import { z as z81 } from "zod";
|
|
26007
26202
|
function registerDeactivateGlobalProcedure(server2) {
|
|
26008
26203
|
server2.registerTool(
|
|
26009
26204
|
"deactivate_global_procedure",
|
|
@@ -26011,7 +26206,7 @@ function registerDeactivateGlobalProcedure(server2) {
|
|
|
26011
26206
|
title: "Deactivate Company Procedure (use global_procedure instead)",
|
|
26012
26207
|
description: "DEPRECATED \u2014 use global_procedure with action='deactivate'. Soft-delete a company procedure. RESTRICTED: only coordinator or founder sessions.",
|
|
26013
26208
|
inputSchema: {
|
|
26014
|
-
procedure_id:
|
|
26209
|
+
procedure_id: z81.string().describe("UUID of the company procedure to deactivate")
|
|
26015
26210
|
}
|
|
26016
26211
|
},
|
|
26017
26212
|
async ({ procedure_id }) => {
|
|
@@ -26071,7 +26266,7 @@ init_store();
|
|
|
26071
26266
|
init_active_agent();
|
|
26072
26267
|
init_database();
|
|
26073
26268
|
init_plan_limits();
|
|
26074
|
-
import { z as
|
|
26269
|
+
import { z as z82 } from "zod";
|
|
26075
26270
|
import crypto17 from "crypto";
|
|
26076
26271
|
function registerStoreDecision(server2) {
|
|
26077
26272
|
server2.registerTool(
|
|
@@ -26080,13 +26275,13 @@ function registerStoreDecision(server2) {
|
|
|
26080
26275
|
title: "Store Decision",
|
|
26081
26276
|
description: "Store an authoritative decision keyed by domain. Use this when a decision is made that should be canonical \u2014 future lookups via get_decision return the latest decision for that domain. Supports supersession chains.",
|
|
26082
26277
|
inputSchema: {
|
|
26083
|
-
domain:
|
|
26278
|
+
domain: z82.string().describe(
|
|
26084
26279
|
"Domain key, e.g. 'auth-strategy', 'db-migration-approach', 'api-versioning'"
|
|
26085
26280
|
),
|
|
26086
|
-
decision:
|
|
26087
|
-
rationale:
|
|
26088
|
-
supersedes:
|
|
26089
|
-
project_name:
|
|
26281
|
+
decision: z82.string().describe("The decision text \u2014 what was decided"),
|
|
26282
|
+
rationale: z82.string().optional().describe("Why this decision was made \u2014 constraints, trade-offs, context"),
|
|
26283
|
+
supersedes: z82.string().optional().describe("UUID of the decision this supersedes (previous decision for this domain)"),
|
|
26284
|
+
project_name: z82.string().optional().describe("Project name")
|
|
26090
26285
|
}
|
|
26091
26286
|
},
|
|
26092
26287
|
async ({ domain, decision, rationale, supersedes, project_name }) => {
|
|
@@ -26154,7 +26349,7 @@ Supersedes: ${supersedes}` : ""}`
|
|
|
26154
26349
|
|
|
26155
26350
|
// src/mcp/tools/get-decision.ts
|
|
26156
26351
|
init_database();
|
|
26157
|
-
import { z as
|
|
26352
|
+
import { z as z83 } from "zod";
|
|
26158
26353
|
function registerGetDecision(server2) {
|
|
26159
26354
|
server2.registerTool(
|
|
26160
26355
|
"get_decision",
|
|
@@ -26162,7 +26357,7 @@ function registerGetDecision(server2) {
|
|
|
26162
26357
|
title: "Get Decision",
|
|
26163
26358
|
description: "Retrieve the latest authoritative decision for a domain. Returns the current active decision and the supersession history.",
|
|
26164
26359
|
inputSchema: {
|
|
26165
|
-
domain:
|
|
26360
|
+
domain: z83.string().describe(
|
|
26166
26361
|
"Domain key to look up, e.g. 'auth-strategy', 'db-migration-approach'"
|
|
26167
26362
|
)
|
|
26168
26363
|
}
|
|
@@ -26225,16 +26420,16 @@ function registerGetDecision(server2) {
|
|
|
26225
26420
|
}
|
|
26226
26421
|
|
|
26227
26422
|
// src/mcp/tools/people-roster.ts
|
|
26228
|
-
import { z as
|
|
26423
|
+
import { z as z84 } from "zod";
|
|
26229
26424
|
|
|
26230
26425
|
// src/lib/people.ts
|
|
26231
26426
|
init_config();
|
|
26232
26427
|
import { readFile as readFile5, writeFile as writeFile6, mkdir as mkdir5 } from "fs/promises";
|
|
26233
|
-
import { existsSync as
|
|
26234
|
-
import
|
|
26235
|
-
var PEOPLE_PATH =
|
|
26428
|
+
import { existsSync as existsSync38, readFileSync as readFileSync31 } from "fs";
|
|
26429
|
+
import path47 from "path";
|
|
26430
|
+
var PEOPLE_PATH = path47.join(EXE_AI_DIR, "people.json");
|
|
26236
26431
|
async function loadPeople() {
|
|
26237
|
-
if (!
|
|
26432
|
+
if (!existsSync38(PEOPLE_PATH)) return [];
|
|
26238
26433
|
try {
|
|
26239
26434
|
const raw = await readFile5(PEOPLE_PATH, "utf-8");
|
|
26240
26435
|
return JSON.parse(raw);
|
|
@@ -26243,7 +26438,7 @@ async function loadPeople() {
|
|
|
26243
26438
|
}
|
|
26244
26439
|
}
|
|
26245
26440
|
async function savePeople(people) {
|
|
26246
|
-
await mkdir5(
|
|
26441
|
+
await mkdir5(path47.dirname(PEOPLE_PATH), { recursive: true });
|
|
26247
26442
|
await writeFile6(PEOPLE_PATH, JSON.stringify(people, null, 2) + "\n", "utf-8");
|
|
26248
26443
|
}
|
|
26249
26444
|
async function addPerson(person) {
|
|
@@ -26273,10 +26468,10 @@ function registerAddPerson(server2) {
|
|
|
26273
26468
|
title: "Add Person",
|
|
26274
26469
|
description: "Add or update a key human in the people roster. Used for co-founders, partners, customers \u2014 anyone agents need to know about.",
|
|
26275
26470
|
inputSchema: {
|
|
26276
|
-
name:
|
|
26277
|
-
role:
|
|
26278
|
-
relationship:
|
|
26279
|
-
notes:
|
|
26471
|
+
name: z84.string().describe("Person's name"),
|
|
26472
|
+
role: z84.string().describe("Their role (e.g. co-founder, customer, partner)"),
|
|
26473
|
+
relationship: z84.string().describe("Relationship to the organization (e.g. co-founder, early adopter, investor)"),
|
|
26474
|
+
notes: z84.string().optional().describe("Additional context about this person")
|
|
26280
26475
|
}
|
|
26281
26476
|
},
|
|
26282
26477
|
async ({ name, role, relationship, notes }) => {
|
|
@@ -26322,7 +26517,7 @@ function registerGetPerson(server2) {
|
|
|
26322
26517
|
title: "Get Person",
|
|
26323
26518
|
description: "Look up a specific person by name from the people roster.",
|
|
26324
26519
|
inputSchema: {
|
|
26325
|
-
name:
|
|
26520
|
+
name: z84.string().describe("Person's name to look up")
|
|
26326
26521
|
}
|
|
26327
26522
|
},
|
|
26328
26523
|
async ({ name }) => {
|
|
@@ -26346,10 +26541,10 @@ Notes: ${person.notes}` : ""}`
|
|
|
26346
26541
|
}
|
|
26347
26542
|
|
|
26348
26543
|
// src/mcp/tools/crm.ts
|
|
26349
|
-
import { z as
|
|
26544
|
+
import { z as z85 } from "zod";
|
|
26350
26545
|
|
|
26351
26546
|
// src/lib/exe-db-read.ts
|
|
26352
|
-
import
|
|
26547
|
+
import path48 from "path";
|
|
26353
26548
|
import os19 from "os";
|
|
26354
26549
|
import { createRequire as createRequire5 } from "module";
|
|
26355
26550
|
import { pathToFileURL as pathToFileURL5 } from "url";
|
|
@@ -26367,8 +26562,8 @@ async function getExeDbReadClient() {
|
|
|
26367
26562
|
if (!Ctor2) throw new Error(`No PrismaClient export found at ${explicitPath}`);
|
|
26368
26563
|
return new Ctor2();
|
|
26369
26564
|
}
|
|
26370
|
-
const exeDbRoot = process.env.EXE_DB_ROOT ??
|
|
26371
|
-
const req = createRequire5(
|
|
26565
|
+
const exeDbRoot = process.env.EXE_DB_ROOT ?? path48.join(os19.homedir(), "exe-db");
|
|
26566
|
+
const req = createRequire5(path48.join(exeDbRoot, "package.json"));
|
|
26372
26567
|
const entry = req.resolve("@prisma/client");
|
|
26373
26568
|
const mod = await import(pathToFileURL5(entry).href);
|
|
26374
26569
|
const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
|
|
@@ -26401,12 +26596,12 @@ function registerCrm(server2) {
|
|
|
26401
26596
|
title: "CRM",
|
|
26402
26597
|
description: "Read-only CRM access from exe-db crm schema. Actions: list_people, get_person, list_tables, describe_table.",
|
|
26403
26598
|
inputSchema: {
|
|
26404
|
-
action:
|
|
26405
|
-
id:
|
|
26406
|
-
query:
|
|
26407
|
-
table:
|
|
26408
|
-
limit:
|
|
26409
|
-
offset:
|
|
26599
|
+
action: z85.enum(["list_people", "get_person", "list_tables", "describe_table"]).describe("CRM read operation"),
|
|
26600
|
+
id: z85.string().optional().describe("CRM row/person id for get_person"),
|
|
26601
|
+
query: z85.string().optional().describe("Text search for list_people/get_person"),
|
|
26602
|
+
table: z85.string().optional().describe("crm schema table name for describe_table"),
|
|
26603
|
+
limit: z85.coerce.number().int().min(1).max(50).optional().describe("Max rows, capped at 50"),
|
|
26604
|
+
offset: z85.coerce.number().int().min(0).optional().describe("Rows to skip")
|
|
26410
26605
|
}
|
|
26411
26606
|
}, async ({ action, id, query, table, limit, offset }) => {
|
|
26412
26607
|
try {
|
|
@@ -26465,7 +26660,7 @@ function registerCrm(server2) {
|
|
|
26465
26660
|
}
|
|
26466
26661
|
|
|
26467
26662
|
// src/mcp/tools/raw-data.ts
|
|
26468
|
-
import { z as
|
|
26663
|
+
import { z as z86 } from "zod";
|
|
26469
26664
|
function text2(content, isError = false) {
|
|
26470
26665
|
return { content: [{ type: "text", text: content }], ...isError ? { isError: true } : {} };
|
|
26471
26666
|
}
|
|
@@ -26474,15 +26669,15 @@ function registerRawData(server2) {
|
|
|
26474
26669
|
title: "Raw Data",
|
|
26475
26670
|
description: "Read-only access to exe-db raw.raw_events landing pad. Actions: list_sources, query, get. Results are capped because raw payloads can consume many tokens.",
|
|
26476
26671
|
inputSchema: {
|
|
26477
|
-
action:
|
|
26478
|
-
id:
|
|
26479
|
-
source:
|
|
26480
|
-
event_type:
|
|
26481
|
-
query:
|
|
26482
|
-
processed:
|
|
26483
|
-
limit:
|
|
26484
|
-
offset:
|
|
26485
|
-
include_payload:
|
|
26672
|
+
action: z86.enum(["list_sources", "query", "get"]).describe("Raw data read operation"),
|
|
26673
|
+
id: z86.string().optional().describe("raw.raw_events id for action=get"),
|
|
26674
|
+
source: z86.string().optional().describe("Filter by raw source"),
|
|
26675
|
+
event_type: z86.string().optional().describe("Filter by event_type"),
|
|
26676
|
+
query: z86.string().optional().describe("Search payload/metadata text"),
|
|
26677
|
+
processed: z86.boolean().optional().describe("Filter processed_at IS NULL/NOT NULL"),
|
|
26678
|
+
limit: z86.coerce.number().int().min(1).max(50).optional().describe("Max rows, capped at 50"),
|
|
26679
|
+
offset: z86.coerce.number().int().min(0).optional().describe("Rows to skip"),
|
|
26680
|
+
include_payload: z86.boolean().optional().describe("Include full payload JSON. Default false to save tokens.")
|
|
26486
26681
|
}
|
|
26487
26682
|
}, async ({ action, id, source, event_type, query, processed, limit, offset, include_payload }) => {
|
|
26488
26683
|
try {
|
|
@@ -26549,17 +26744,17 @@ init_active_agent();
|
|
|
26549
26744
|
init_config();
|
|
26550
26745
|
init_license();
|
|
26551
26746
|
init_store();
|
|
26552
|
-
import { z as
|
|
26747
|
+
import { z as z87 } from "zod";
|
|
26553
26748
|
import crypto18 from "crypto";
|
|
26554
26749
|
import { mkdir as mkdir6, writeFile as writeFile7 } from "fs/promises";
|
|
26555
|
-
import
|
|
26556
|
-
var CLASSIFICATION =
|
|
26750
|
+
import path49 from "path";
|
|
26751
|
+
var CLASSIFICATION = z87.enum([
|
|
26557
26752
|
"upstream_bug",
|
|
26558
26753
|
"customer_customization",
|
|
26559
26754
|
"emergency_hotfix",
|
|
26560
26755
|
"unclear"
|
|
26561
26756
|
]);
|
|
26562
|
-
var SEVERITY =
|
|
26757
|
+
var SEVERITY = z87.enum(["p0", "p1", "p2", "p3"]);
|
|
26563
26758
|
function slugify2(input) {
|
|
26564
26759
|
return input.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80) || "bug-report";
|
|
26565
26760
|
}
|
|
@@ -26637,22 +26832,22 @@ function registerCreateBugReport(server2) {
|
|
|
26637
26832
|
title: "Create Bug Report",
|
|
26638
26833
|
description: "Classify and file an exe-os issue as upstream_bug, customer_customization, emergency_hotfix, or unclear. Writes a local report, stores memory, and optionally sends to AskExe support when a support endpoint is configured.",
|
|
26639
26834
|
inputSchema: {
|
|
26640
|
-
title:
|
|
26835
|
+
title: z87.string().min(3).describe("Short descriptive title"),
|
|
26641
26836
|
classification: CLASSIFICATION.describe(
|
|
26642
26837
|
"upstream_bug = platform defect; customer_customization = local preference; emergency_hotfix = temporary local patch; unclear = needs maintainer triage"
|
|
26643
26838
|
),
|
|
26644
26839
|
severity: SEVERITY.default("p2").describe("p0 critical \u2192 p3 low"),
|
|
26645
|
-
summary:
|
|
26646
|
-
customer_impact:
|
|
26647
|
-
reproduction_steps:
|
|
26648
|
-
expected:
|
|
26649
|
-
actual:
|
|
26650
|
-
files_changed:
|
|
26651
|
-
workaround:
|
|
26652
|
-
local_patch_diff:
|
|
26653
|
-
package_version:
|
|
26654
|
-
project_name:
|
|
26655
|
-
send_upstream:
|
|
26840
|
+
summary: z87.string().min(10).describe("What happened and why it matters"),
|
|
26841
|
+
customer_impact: z87.string().optional().describe("How this affects the customer/founder"),
|
|
26842
|
+
reproduction_steps: z87.array(z87.string()).optional().describe("Steps to reproduce"),
|
|
26843
|
+
expected: z87.string().optional().describe("Expected behavior"),
|
|
26844
|
+
actual: z87.string().optional().describe("Actual behavior"),
|
|
26845
|
+
files_changed: z87.array(z87.string()).optional().describe("Files changed or suspected"),
|
|
26846
|
+
workaround: z87.string().optional().describe("Temporary local workaround/hotfix, if any"),
|
|
26847
|
+
local_patch_diff: z87.string().optional().describe("Small local diff or patch summary"),
|
|
26848
|
+
package_version: z87.string().optional().describe("Installed @askexenow/exe-os version"),
|
|
26849
|
+
project_name: z87.string().optional().describe("Project/customer context"),
|
|
26850
|
+
send_upstream: z87.boolean().default(true).describe("Attempt to POST to configured AskExe support endpoint")
|
|
26656
26851
|
}
|
|
26657
26852
|
},
|
|
26658
26853
|
async ({
|
|
@@ -26692,9 +26887,9 @@ function registerCreateBugReport(server2) {
|
|
|
26692
26887
|
filesChanged: files_changed,
|
|
26693
26888
|
projectName: project_name
|
|
26694
26889
|
});
|
|
26695
|
-
const outDir =
|
|
26890
|
+
const outDir = path49.join(EXE_AI_DIR, "bug-reports");
|
|
26696
26891
|
await mkdir6(outDir, { recursive: true });
|
|
26697
|
-
const reportPath =
|
|
26892
|
+
const reportPath = path49.join(outDir, `${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}-${slugify2(title)}-${id.slice(0, 8)}.md`);
|
|
26698
26893
|
await writeFile7(reportPath, markdown, "utf-8");
|
|
26699
26894
|
let vector = null;
|
|
26700
26895
|
try {
|
|
@@ -26761,33 +26956,33 @@ Upstream status: ${upstreamStatus}`
|
|
|
26761
26956
|
}
|
|
26762
26957
|
|
|
26763
26958
|
// src/mcp/tools/code-context.ts
|
|
26764
|
-
import { z as
|
|
26959
|
+
import { z as z88 } from "zod";
|
|
26765
26960
|
|
|
26766
26961
|
// src/lib/code-context-index.ts
|
|
26767
26962
|
init_config();
|
|
26768
26963
|
import crypto19 from "crypto";
|
|
26769
|
-
import
|
|
26770
|
-
import { existsSync as
|
|
26964
|
+
import path50 from "path";
|
|
26965
|
+
import { existsSync as existsSync39, mkdirSync as mkdirSync21, readFileSync as readFileSync32, statSync as statSync9, writeFileSync as writeFileSync23 } from "fs";
|
|
26771
26966
|
import { spawnSync } from "child_process";
|
|
26772
26967
|
var INDEX_VERSION = 1;
|
|
26773
26968
|
var DEFAULT_MAX_FILES = 2e3;
|
|
26774
26969
|
var CODE_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx"]);
|
|
26775
26970
|
var IGNORE_SEGMENTS = /* @__PURE__ */ new Set(["node_modules", "dist", ".git", "coverage", ".worktrees", ".next", "build"]);
|
|
26776
26971
|
function normalizeProjectRoot(projectRoot) {
|
|
26777
|
-
return
|
|
26972
|
+
return path50.resolve(projectRoot || process.cwd());
|
|
26778
26973
|
}
|
|
26779
26974
|
function hashText(text3) {
|
|
26780
26975
|
return crypto19.createHash("sha256").update(text3).digest("hex");
|
|
26781
26976
|
}
|
|
26782
26977
|
function indexDir() {
|
|
26783
|
-
const dir =
|
|
26784
|
-
|
|
26978
|
+
const dir = path50.join(EXE_AI_DIR, "code-context");
|
|
26979
|
+
mkdirSync21(dir, { recursive: true });
|
|
26785
26980
|
return dir;
|
|
26786
26981
|
}
|
|
26787
26982
|
function getCodeContextIndexPath(projectRoot) {
|
|
26788
26983
|
const root = normalizeProjectRoot(projectRoot);
|
|
26789
26984
|
const rootHash = hashText(root).slice(0, 16);
|
|
26790
|
-
return
|
|
26985
|
+
return path50.join(indexDir(), `${rootHash}.json`);
|
|
26791
26986
|
}
|
|
26792
26987
|
function currentBranch(projectRoot) {
|
|
26793
26988
|
const result2 = spawnSync("git", ["branch", "--show-current"], {
|
|
@@ -26799,11 +26994,11 @@ function currentBranch(projectRoot) {
|
|
|
26799
26994
|
return branch || "detached-or-unknown";
|
|
26800
26995
|
}
|
|
26801
26996
|
function shouldIgnore(relPath) {
|
|
26802
|
-
const parts = relPath.split(
|
|
26997
|
+
const parts = relPath.split(path50.sep);
|
|
26803
26998
|
return parts.some((part) => IGNORE_SEGMENTS.has(part));
|
|
26804
26999
|
}
|
|
26805
27000
|
function isCodeFile(relPath) {
|
|
26806
|
-
return CODE_EXTENSIONS.has(
|
|
27001
|
+
return CODE_EXTENSIONS.has(path50.extname(relPath).toLowerCase());
|
|
26807
27002
|
}
|
|
26808
27003
|
function listCodeFiles(projectRoot, maxFiles) {
|
|
26809
27004
|
const git = spawnSync("git", ["ls-files", "*.ts", "*.tsx", "*.js", "*.jsx"], {
|
|
@@ -26845,7 +27040,7 @@ function parseImportPaths(importText) {
|
|
|
26845
27040
|
}
|
|
26846
27041
|
function resolveImport(fromFile, importPath, allFiles) {
|
|
26847
27042
|
if (!importPath.startsWith(".")) return null;
|
|
26848
|
-
const base =
|
|
27043
|
+
const base = path50.posix.normalize(path50.posix.join(path50.posix.dirname(fromFile.replaceAll(path50.sep, "/")), importPath));
|
|
26849
27044
|
const withoutKnownExt = base.replace(/\.(?:js|jsx|ts|tsx)$/, "");
|
|
26850
27045
|
const candidates = [
|
|
26851
27046
|
base,
|
|
@@ -26857,10 +27052,10 @@ function resolveImport(fromFile, importPath, allFiles) {
|
|
|
26857
27052
|
`${base}.tsx`,
|
|
26858
27053
|
`${base}.js`,
|
|
26859
27054
|
`${base}.jsx`,
|
|
26860
|
-
|
|
26861
|
-
|
|
26862
|
-
|
|
26863
|
-
|
|
27055
|
+
path50.posix.join(base, "index.ts"),
|
|
27056
|
+
path50.posix.join(base, "index.tsx"),
|
|
27057
|
+
path50.posix.join(base, "index.js"),
|
|
27058
|
+
path50.posix.join(base, "index.jsx")
|
|
26864
27059
|
];
|
|
26865
27060
|
return candidates.find((candidate) => allFiles.has(candidate)) ?? null;
|
|
26866
27061
|
}
|
|
@@ -26869,9 +27064,9 @@ function symbolId(filePath, chunk) {
|
|
|
26869
27064
|
}
|
|
26870
27065
|
function loadIndex(projectRoot) {
|
|
26871
27066
|
const file = getCodeContextIndexPath(projectRoot);
|
|
26872
|
-
if (!
|
|
27067
|
+
if (!existsSync39(file)) return null;
|
|
26873
27068
|
try {
|
|
26874
|
-
const parsed = JSON.parse(
|
|
27069
|
+
const parsed = JSON.parse(readFileSync32(file, "utf8"));
|
|
26875
27070
|
if (parsed.version !== INDEX_VERSION || parsed.projectRoot !== projectRoot) return null;
|
|
26876
27071
|
return parsed;
|
|
26877
27072
|
} catch {
|
|
@@ -26879,18 +27074,18 @@ function loadIndex(projectRoot) {
|
|
|
26879
27074
|
}
|
|
26880
27075
|
}
|
|
26881
27076
|
function saveIndex(index) {
|
|
26882
|
-
|
|
27077
|
+
writeFileSync23(getCodeContextIndexPath(index.projectRoot), JSON.stringify(index, null, 2));
|
|
26883
27078
|
}
|
|
26884
27079
|
function buildFileRecord(projectRoot, relPath, allFiles, previous) {
|
|
26885
|
-
const absPath =
|
|
27080
|
+
const absPath = path50.join(projectRoot, relPath);
|
|
26886
27081
|
let stat;
|
|
26887
27082
|
try {
|
|
26888
|
-
stat =
|
|
27083
|
+
stat = statSync9(absPath);
|
|
26889
27084
|
} catch {
|
|
26890
27085
|
return null;
|
|
26891
27086
|
}
|
|
26892
27087
|
if (!stat.isFile()) return null;
|
|
26893
|
-
const source =
|
|
27088
|
+
const source = readFileSync32(absPath, "utf8");
|
|
26894
27089
|
const hash = hashText(source);
|
|
26895
27090
|
if (previous && previous.hash === hash && previous.mtimeMs === stat.mtimeMs && previous.size === stat.size) {
|
|
26896
27091
|
return previous;
|
|
@@ -26927,10 +27122,10 @@ function buildCodeContextIndex(options = {}) {
|
|
|
26927
27122
|
const branch = currentBranch(projectRoot);
|
|
26928
27123
|
const previous = options.force ? null : loadIndex(projectRoot);
|
|
26929
27124
|
const files = listCodeFiles(projectRoot, maxFiles);
|
|
26930
|
-
const allFiles = new Set(files.map((file) => file.replaceAll(
|
|
27125
|
+
const allFiles = new Set(files.map((file) => file.replaceAll(path50.sep, "/")));
|
|
26931
27126
|
const fileRecords = {};
|
|
26932
27127
|
for (const rel of files) {
|
|
26933
|
-
const normalized = rel.replaceAll(
|
|
27128
|
+
const normalized = rel.replaceAll(path50.sep, "/");
|
|
26934
27129
|
const record = buildFileRecord(projectRoot, normalized, allFiles, previous?.files[normalized]);
|
|
26935
27130
|
if (record) fileRecords[normalized] = record;
|
|
26936
27131
|
}
|
|
@@ -26952,11 +27147,11 @@ function loadOrBuildCodeContextIndex(options = {}) {
|
|
|
26952
27147
|
if (loaded) {
|
|
26953
27148
|
const currentFiles = listCodeFiles(projectRoot, options.maxFiles ?? DEFAULT_MAX_FILES);
|
|
26954
27149
|
const unchanged = currentFiles.every((rel) => {
|
|
26955
|
-
const normalized = rel.replaceAll(
|
|
27150
|
+
const normalized = rel.replaceAll(path50.sep, "/");
|
|
26956
27151
|
const existing = loaded.files[normalized];
|
|
26957
27152
|
if (!existing) return false;
|
|
26958
27153
|
try {
|
|
26959
|
-
const stat =
|
|
27154
|
+
const stat = statSync9(path50.join(projectRoot, normalized));
|
|
26960
27155
|
return stat.mtimeMs === existing.mtimeMs && stat.size === existing.size;
|
|
26961
27156
|
} catch {
|
|
26962
27157
|
return false;
|
|
@@ -27059,7 +27254,7 @@ function traceCodeSymbol(symbolName, options = {}) {
|
|
|
27059
27254
|
}
|
|
27060
27255
|
function resolveTargetFile(index, input) {
|
|
27061
27256
|
if (input.filePath) {
|
|
27062
|
-
const normalized = input.filePath.replaceAll(
|
|
27257
|
+
const normalized = input.filePath.replaceAll(path50.sep, "/").replace(/^\.\//, "");
|
|
27063
27258
|
if (index.files[normalized]) return { filePath: normalized, target: normalized };
|
|
27064
27259
|
const suffix = Object.keys(index.files).find((file) => file.endsWith(normalized));
|
|
27065
27260
|
if (suffix) return { filePath: suffix, target: input.filePath };
|
|
@@ -27089,7 +27284,7 @@ function analyzeBlastRadius(input) {
|
|
|
27089
27284
|
}
|
|
27090
27285
|
}
|
|
27091
27286
|
}
|
|
27092
|
-
const targetBase =
|
|
27287
|
+
const targetBase = path50.basename(target.filePath).replace(/\.[^.]+$/, "").toLowerCase();
|
|
27093
27288
|
const symbolLower = input.symbol?.toLowerCase();
|
|
27094
27289
|
const tests = Object.keys(index.files).filter((file) => {
|
|
27095
27290
|
const lower = file.toLowerCase();
|
|
@@ -27135,15 +27330,15 @@ function registerCodeContext(server2) {
|
|
|
27135
27330
|
title: "Code Context",
|
|
27136
27331
|
description: "Persistent codebase context engine. One consolidated tool to avoid MCP bloat. Actions: index, search, trace, blast_radius, stats.",
|
|
27137
27332
|
inputSchema: {
|
|
27138
|
-
action:
|
|
27139
|
-
project_root:
|
|
27140
|
-
query:
|
|
27141
|
-
symbol:
|
|
27142
|
-
file_path:
|
|
27143
|
-
force:
|
|
27144
|
-
limit:
|
|
27145
|
-
depth:
|
|
27146
|
-
max_files:
|
|
27333
|
+
action: z88.enum(["index", "search", "trace", "blast_radius", "stats"]).describe("Code context operation"),
|
|
27334
|
+
project_root: z88.string().optional().describe("Repository root. Defaults to current working directory."),
|
|
27335
|
+
query: z88.string().optional().describe("Search query for action=search"),
|
|
27336
|
+
symbol: z88.string().optional().describe("Symbol/function/class/type name for trace or blast_radius"),
|
|
27337
|
+
file_path: z88.string().optional().describe("File path for blast_radius"),
|
|
27338
|
+
force: z88.boolean().optional().describe("Force rebuild before answering"),
|
|
27339
|
+
limit: z88.coerce.number().int().min(1).max(100).optional().describe("Max results"),
|
|
27340
|
+
depth: z88.coerce.number().int().min(1).max(5).optional().describe("Dependent traversal depth for blast_radius"),
|
|
27341
|
+
max_files: z88.coerce.number().int().min(1).max(1e4).optional().describe("Max code files to index")
|
|
27147
27342
|
}
|
|
27148
27343
|
}, async ({ action, project_root, query, symbol, file_path, force, limit, depth, max_files }) => {
|
|
27149
27344
|
const opts = { projectRoot: project_root, force, maxFiles: max_files };
|
|
@@ -27180,9 +27375,9 @@ function registerCodeContext(server2) {
|
|
|
27180
27375
|
}
|
|
27181
27376
|
|
|
27182
27377
|
// src/mcp/tools/support-inbox.ts
|
|
27183
|
-
import { z as
|
|
27378
|
+
import { z as z89 } from "zod";
|
|
27184
27379
|
var DEFAULT_ENDPOINT = "https://askexe.com/admin/support/bug-reports";
|
|
27185
|
-
var STATUS =
|
|
27380
|
+
var STATUS = z89.enum(["open", "triaged", "fixed", "closed", "wontfix"]);
|
|
27186
27381
|
function adminToken() {
|
|
27187
27382
|
return process.env.ASKEXE_SUPPORT_ADMIN_TOKEN || process.env.EXE_SUPPORT_ADMIN_TOKEN;
|
|
27188
27383
|
}
|
|
@@ -27221,9 +27416,9 @@ function registerListBugReports(server2) {
|
|
|
27221
27416
|
title: "List Bug Reports",
|
|
27222
27417
|
description: "AskExe-internal only: list incoming customer bug reports from the support inbox.",
|
|
27223
27418
|
inputSchema: {
|
|
27224
|
-
status:
|
|
27225
|
-
severity:
|
|
27226
|
-
limit:
|
|
27419
|
+
status: z89.enum(["all", "open", "triaged", "fixed", "closed", "wontfix"]).default("open"),
|
|
27420
|
+
severity: z89.enum(["p0", "p1", "p2", "p3"]).optional(),
|
|
27421
|
+
limit: z89.number().int().min(1).max(100).default(25)
|
|
27227
27422
|
}
|
|
27228
27423
|
},
|
|
27229
27424
|
async ({ status, severity, limit }) => {
|
|
@@ -27242,7 +27437,7 @@ function registerGetBugReport(server2) {
|
|
|
27242
27437
|
{
|
|
27243
27438
|
title: "Get Bug Report",
|
|
27244
27439
|
description: "AskExe-internal only: fetch one customer bug report with full markdown payload.",
|
|
27245
|
-
inputSchema: { id:
|
|
27440
|
+
inputSchema: { id: z89.string().min(8) }
|
|
27246
27441
|
},
|
|
27247
27442
|
async ({ id }) => {
|
|
27248
27443
|
const data = await requestJson(`${endpoint()}/${encodeURIComponent(id)}`);
|
|
@@ -27257,12 +27452,12 @@ function registerTriageBugReport(server2) {
|
|
|
27257
27452
|
title: "Triage Bug Report",
|
|
27258
27453
|
description: "AskExe-internal only: update bug report status and link task/commit/release metadata.",
|
|
27259
27454
|
inputSchema: {
|
|
27260
|
-
id:
|
|
27455
|
+
id: z89.string().min(8),
|
|
27261
27456
|
status: STATUS.optional(),
|
|
27262
|
-
triage_notes:
|
|
27263
|
-
linked_task_id:
|
|
27264
|
-
linked_commit:
|
|
27265
|
-
fixed_version:
|
|
27457
|
+
triage_notes: z89.string().optional(),
|
|
27458
|
+
linked_task_id: z89.string().optional(),
|
|
27459
|
+
linked_commit: z89.string().optional(),
|
|
27460
|
+
fixed_version: z89.string().optional()
|
|
27266
27461
|
}
|
|
27267
27462
|
},
|
|
27268
27463
|
async ({ id, status, triage_notes, linked_task_id, linked_commit, fixed_version }) => {
|
|
@@ -27388,6 +27583,7 @@ var TOOL_CATEGORIES = {
|
|
|
27388
27583
|
registerDeployClient: "admin",
|
|
27389
27584
|
registerBackupVps: "admin",
|
|
27390
27585
|
registerGetDaemonHealth: "admin",
|
|
27586
|
+
registerMcpPing: "core",
|
|
27391
27587
|
registerGetAutoWakeStatus: "admin",
|
|
27392
27588
|
registerGetWorkerGate: "admin",
|
|
27393
27589
|
registerRunMemoryAudit: "admin",
|
|
@@ -27425,6 +27621,7 @@ var CHIEF_OF_STAFF_READ_TOOLS = /* @__PURE__ */ new Set([
|
|
|
27425
27621
|
"registerSearchEverything",
|
|
27426
27622
|
"registerGetDecision",
|
|
27427
27623
|
"registerGetIdentity",
|
|
27624
|
+
"registerMcpPing",
|
|
27428
27625
|
"registerListTasks",
|
|
27429
27626
|
"registerGetTask",
|
|
27430
27627
|
"registerListReminders",
|
|
@@ -27597,6 +27794,7 @@ function registerAllTools(server2) {
|
|
|
27597
27794
|
if (exposeLegacyConfig) {
|
|
27598
27795
|
gate("registerGetAgentSpend", registerGetAgentSpend);
|
|
27599
27796
|
}
|
|
27797
|
+
gate("registerMcpPing", registerMcpPing);
|
|
27600
27798
|
if (exposeLegacyGraph) {
|
|
27601
27799
|
gate("registerGetGraphStats", registerGetGraphStats);
|
|
27602
27800
|
gate("registerGetEntityNeighbors", registerGetEntityNeighbors);
|
|
@@ -27758,16 +27956,16 @@ try {
|
|
|
27758
27956
|
}
|
|
27759
27957
|
}, 3e4);
|
|
27760
27958
|
_ppidWatchdog.unref();
|
|
27761
|
-
const MCP_VERSION_PATH =
|
|
27959
|
+
const MCP_VERSION_PATH = path51.join(os20.homedir(), ".exe-os", "mcp-version");
|
|
27762
27960
|
let _currentMcpVersion = null;
|
|
27763
27961
|
try {
|
|
27764
|
-
_currentMcpVersion =
|
|
27962
|
+
_currentMcpVersion = existsSync40(MCP_VERSION_PATH) ? readFileSync33(MCP_VERSION_PATH, "utf8").trim() : null;
|
|
27765
27963
|
} catch {
|
|
27766
27964
|
}
|
|
27767
27965
|
const _versionWatchdog = setInterval(() => {
|
|
27768
27966
|
try {
|
|
27769
|
-
if (!
|
|
27770
|
-
const diskVersion =
|
|
27967
|
+
if (!existsSync40(MCP_VERSION_PATH)) return;
|
|
27968
|
+
const diskVersion = readFileSync33(MCP_VERSION_PATH, "utf8").trim();
|
|
27771
27969
|
if (_currentMcpVersion && diskVersion !== _currentMcpVersion) {
|
|
27772
27970
|
process.stderr.write(
|
|
27773
27971
|
`[exe-os] MCP version changed (${_currentMcpVersion} \u2192 ${diskVersion}). Hot-reloading...
|
|
@@ -27799,18 +27997,18 @@ try {
|
|
|
27799
27997
|
`[exe-os] Periodic backfill: ${nullCount} NULL vectors \u2014 spawning job
|
|
27800
27998
|
`
|
|
27801
27999
|
);
|
|
27802
|
-
const thisFile =
|
|
27803
|
-
const backfillPath =
|
|
27804
|
-
|
|
28000
|
+
const thisFile = fileURLToPath6(import.meta.url);
|
|
28001
|
+
const backfillPath = path51.resolve(
|
|
28002
|
+
path51.dirname(thisFile),
|
|
27805
28003
|
"../bin/backfill-vectors.js"
|
|
27806
28004
|
);
|
|
27807
|
-
if (
|
|
28005
|
+
if (existsSync40(backfillPath)) {
|
|
27808
28006
|
const { EXE_AI_DIR: exeDir } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
27809
|
-
const logPath =
|
|
27810
|
-
|
|
28007
|
+
const logPath = path51.join(exeDir, "workers.log");
|
|
28008
|
+
mkdirSync22(path51.dirname(logPath), { recursive: true });
|
|
27811
28009
|
let logFd = "ignore";
|
|
27812
28010
|
try {
|
|
27813
|
-
logFd =
|
|
28011
|
+
logFd = openSync4(logPath, "a");
|
|
27814
28012
|
} catch {
|
|
27815
28013
|
}
|
|
27816
28014
|
const child = spawn4(process.execPath, [backfillPath], {
|
|
@@ -27820,7 +28018,7 @@ try {
|
|
|
27820
28018
|
child.unref();
|
|
27821
28019
|
if (child.pid) registerWorkerPid2(child.pid);
|
|
27822
28020
|
if (typeof logFd === "number") try {
|
|
27823
|
-
|
|
28021
|
+
closeSync4(logFd);
|
|
27824
28022
|
} catch {
|
|
27825
28023
|
}
|
|
27826
28024
|
} else {
|