@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/lib/exe-daemon.js
CHANGED
|
@@ -3655,6 +3655,170 @@ var init_memory_write_governor = __esm({
|
|
|
3655
3655
|
}
|
|
3656
3656
|
});
|
|
3657
3657
|
|
|
3658
|
+
// src/lib/mcp-transport-health.ts
|
|
3659
|
+
import { appendFileSync, closeSync as closeSync2, existsSync as existsSync8, mkdirSync as mkdirSync2, openSync as openSync2, readFileSync as readFileSync7, readSync, statSync as statSync2, writeFileSync as writeFileSync5 } from "fs";
|
|
3660
|
+
import path8 from "path";
|
|
3661
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3662
|
+
function parsePositiveInt(value, fallback) {
|
|
3663
|
+
if (!value) return fallback;
|
|
3664
|
+
const parsed = Number.parseInt(value, 10);
|
|
3665
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
3666
|
+
}
|
|
3667
|
+
function readTailText(filePath, maxBytes) {
|
|
3668
|
+
const stats = statSync2(filePath);
|
|
3669
|
+
if (stats.size <= maxBytes) return readFileSync7(filePath, "utf8");
|
|
3670
|
+
const fd = openSync2(filePath, "r");
|
|
3671
|
+
try {
|
|
3672
|
+
const buffer = Buffer.allocUnsafe(maxBytes);
|
|
3673
|
+
readSync(fd, buffer, 0, maxBytes, stats.size - maxBytes);
|
|
3674
|
+
const text3 = buffer.toString("utf8");
|
|
3675
|
+
const firstNewline = text3.indexOf("\n");
|
|
3676
|
+
return firstNewline >= 0 ? text3.slice(firstNewline + 1) : text3;
|
|
3677
|
+
} finally {
|
|
3678
|
+
closeSync2(fd);
|
|
3679
|
+
}
|
|
3680
|
+
}
|
|
3681
|
+
function rotateMcpHttpEventLogIfNeeded() {
|
|
3682
|
+
if (!existsSync8(MCP_HTTP_EVENTS_PATH)) return;
|
|
3683
|
+
const stats = statSync2(MCP_HTTP_EVENTS_PATH);
|
|
3684
|
+
if (stats.size <= EVENT_MAX_BYTES) return;
|
|
3685
|
+
const keepBytes = Math.min(EVENT_READ_BYTES, EVENT_MAX_BYTES);
|
|
3686
|
+
const tail = readTailText(MCP_HTTP_EVENTS_PATH, keepBytes);
|
|
3687
|
+
writeFileSync5(MCP_HTTP_EVENTS_PATH, tail, "utf8");
|
|
3688
|
+
}
|
|
3689
|
+
function readPackageVersion() {
|
|
3690
|
+
let dir = path8.dirname(fileURLToPath2(import.meta.url));
|
|
3691
|
+
const { root } = path8.parse(dir);
|
|
3692
|
+
while (dir !== root) {
|
|
3693
|
+
const pkgPath = path8.join(dir, "package.json");
|
|
3694
|
+
if (existsSync8(pkgPath)) {
|
|
3695
|
+
try {
|
|
3696
|
+
const parsed = JSON.parse(readFileSync7(pkgPath, "utf8"));
|
|
3697
|
+
return parsed.version ?? "unknown";
|
|
3698
|
+
} catch {
|
|
3699
|
+
return "unknown";
|
|
3700
|
+
}
|
|
3701
|
+
}
|
|
3702
|
+
dir = path8.dirname(dir);
|
|
3703
|
+
}
|
|
3704
|
+
return "unknown";
|
|
3705
|
+
}
|
|
3706
|
+
function inferMcpRuntime(input) {
|
|
3707
|
+
const text3 = [input.runtimeHeader, input.userAgent, input.agentId, input.clientName].filter(Boolean).join(" ").toLowerCase();
|
|
3708
|
+
if (text3.includes("codex")) return "Codex";
|
|
3709
|
+
if (text3.includes("claude")) return "Claude";
|
|
3710
|
+
if (text3.includes("opencode") || text3.includes("open-code")) return "OpenCode";
|
|
3711
|
+
return "Unknown";
|
|
3712
|
+
}
|
|
3713
|
+
function getMcpToolFamily(toolName) {
|
|
3714
|
+
if (!toolName) return "unknown";
|
|
3715
|
+
if (/task|employee|review|checkpoint|resume/i.test(toolName)) return "task";
|
|
3716
|
+
if (/memory|consolidat|document|search_everything|get_session_context/i.test(toolName)) return "memory";
|
|
3717
|
+
if (/config|daemon|worker|auto_wake|license|trigger|starter|orchestration|cloud_sync|backup/i.test(toolName)) return "config";
|
|
3718
|
+
if (/message|whatsapp|conversation|gateway/i.test(toolName)) return "gateway";
|
|
3719
|
+
if (/wiki|crm|raw_data|person|people/i.test(toolName)) return "company-data";
|
|
3720
|
+
if (/graph|entity|relationship|trajectory/i.test(toolName)) return "graph";
|
|
3721
|
+
if (/identity|behavior|decision|procedure/i.test(toolName)) return "cognition";
|
|
3722
|
+
if (/ping|health/i.test(toolName)) return "health";
|
|
3723
|
+
return "other";
|
|
3724
|
+
}
|
|
3725
|
+
function parseMcpHttpEventLines(raw, limit = 200) {
|
|
3726
|
+
const lines = raw.trim().split("\n").filter(Boolean).slice(-limit);
|
|
3727
|
+
const events = [];
|
|
3728
|
+
for (const line of lines) {
|
|
3729
|
+
try {
|
|
3730
|
+
events.push(JSON.parse(line));
|
|
3731
|
+
} catch {
|
|
3732
|
+
}
|
|
3733
|
+
}
|
|
3734
|
+
return events;
|
|
3735
|
+
}
|
|
3736
|
+
function readMcpHttpEvents(limit = 200) {
|
|
3737
|
+
if (!existsSync8(MCP_HTTP_EVENTS_PATH)) return [];
|
|
3738
|
+
const raw = readTailText(MCP_HTTP_EVENTS_PATH, EVENT_READ_BYTES);
|
|
3739
|
+
return parseMcpHttpEventLines(raw, limit);
|
|
3740
|
+
}
|
|
3741
|
+
function summarizeMcpTransport(events = readMcpHttpEvents()) {
|
|
3742
|
+
const lastServerStartIndex = events.map((event) => event.message).lastIndexOf("server_started");
|
|
3743
|
+
const scopedEvents = lastServerStartIndex >= 0 ? events.slice(lastServerStartIndex) : events;
|
|
3744
|
+
const activeSessionEvent = [...scopedEvents].reverse().find((event) => typeof event.activeSessions === "number");
|
|
3745
|
+
const successfulToolCalls = scopedEvents.filter((event) => event.message === "tool_call_ok");
|
|
3746
|
+
const lastSuccessfulToolCall = successfulToolCalls.at(-1) ?? null;
|
|
3747
|
+
const summary = {
|
|
3748
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3749
|
+
version: readPackageVersion(),
|
|
3750
|
+
scope: "local",
|
|
3751
|
+
privacy: "metadata_only",
|
|
3752
|
+
eventLogPath: MCP_HTTP_EVENTS_PATH,
|
|
3753
|
+
activeSessions: activeSessionEvent?.activeSessions ?? null,
|
|
3754
|
+
sessionsCreated: scopedEvents.filter((event) => event.message === "session_initialized").length,
|
|
3755
|
+
sessionsClosed: scopedEvents.filter((event) => event.message === "session_closed").length,
|
|
3756
|
+
missingSessionErrors: scopedEvents.filter((event) => event.message?.includes("missing MCP session")).length,
|
|
3757
|
+
staleSessionErrors: scopedEvents.filter((event) => event.message?.includes("stale or unknown")).length,
|
|
3758
|
+
transportErrors: scopedEvents.filter((event) => event.level === "warn" || event.level === "error").length,
|
|
3759
|
+
lastSuccessfulHandshake: scopedEvents.filter((event) => event.message === "session_initialized").at(-1)?.timestamp ?? null,
|
|
3760
|
+
lastSuccessfulToolCall: lastSuccessfulToolCall?.timestamp ?? null,
|
|
3761
|
+
lastSuccessfulToolCallByRuntime: {},
|
|
3762
|
+
lastSuccessfulToolCallByAgent: {},
|
|
3763
|
+
lastSuccessfulToolCallByFamily: {},
|
|
3764
|
+
activeSessionsByRuntime: {},
|
|
3765
|
+
recentWarnings: scopedEvents.filter((event) => event.level === "warn" || event.level === "error").slice(-10),
|
|
3766
|
+
remediation: [
|
|
3767
|
+
"If MCP tools fail with missing/stale session, reconnect the MCP client (/mcp or restart the runtime).",
|
|
3768
|
+
"Do not access the database directly; MCP is the only data interface.",
|
|
3769
|
+
"Check get_daemon_health or exe-healthcheck for daemon/MCP endpoint status before retrying work."
|
|
3770
|
+
]
|
|
3771
|
+
};
|
|
3772
|
+
const createdBySession = /* @__PURE__ */ new Map();
|
|
3773
|
+
for (const event of scopedEvents) {
|
|
3774
|
+
if (event.message === "session_initialized" && event.sessionId) createdBySession.set(event.sessionId, event);
|
|
3775
|
+
if ((event.message === "session_closed" || event.message === "session_expired") && event.sessionId) {
|
|
3776
|
+
createdBySession.delete(event.sessionId);
|
|
3777
|
+
}
|
|
3778
|
+
}
|
|
3779
|
+
for (const event of createdBySession.values()) {
|
|
3780
|
+
const runtime = event.runtime ?? "Unknown";
|
|
3781
|
+
summary.activeSessionsByRuntime[runtime] = (summary.activeSessionsByRuntime[runtime] ?? 0) + 1;
|
|
3782
|
+
}
|
|
3783
|
+
for (const event of successfulToolCalls) {
|
|
3784
|
+
if (event.runtime) summary.lastSuccessfulToolCallByRuntime[event.runtime] = event.timestamp ?? "";
|
|
3785
|
+
if (event.agentId) summary.lastSuccessfulToolCallByAgent[event.agentId] = event.timestamp ?? "";
|
|
3786
|
+
if (event.toolFamily) summary.lastSuccessfulToolCallByFamily[event.toolFamily] = event.timestamp ?? "";
|
|
3787
|
+
}
|
|
3788
|
+
return summary;
|
|
3789
|
+
}
|
|
3790
|
+
function writeMcpTransportSummary(events) {
|
|
3791
|
+
try {
|
|
3792
|
+
mkdirSync2(MCP_MONITOR_DIR, { recursive: true });
|
|
3793
|
+
writeFileSync5(MCP_TRANSPORT_SUMMARY_PATH, JSON.stringify(summarizeMcpTransport(events), null, 2) + "\n");
|
|
3794
|
+
} catch {
|
|
3795
|
+
}
|
|
3796
|
+
}
|
|
3797
|
+
function recordMcpHttpEvent(event) {
|
|
3798
|
+
try {
|
|
3799
|
+
mkdirSync2(EXE_AI_DIR, { recursive: true });
|
|
3800
|
+
const enriched = { timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...event };
|
|
3801
|
+
appendFileSync(MCP_HTTP_EVENTS_PATH, JSON.stringify(enriched) + "\n");
|
|
3802
|
+
rotateMcpHttpEventLogIfNeeded();
|
|
3803
|
+
writeMcpTransportSummary(readMcpHttpEvents());
|
|
3804
|
+
} catch {
|
|
3805
|
+
}
|
|
3806
|
+
}
|
|
3807
|
+
var MCP_HTTP_EVENTS_PATH, MCP_MONITOR_DIR, MCP_TRANSPORT_SUMMARY_PATH, DEFAULT_EVENT_READ_BYTES, DEFAULT_EVENT_MAX_BYTES, EVENT_READ_BYTES, EVENT_MAX_BYTES;
|
|
3808
|
+
var init_mcp_transport_health = __esm({
|
|
3809
|
+
"src/lib/mcp-transport-health.ts"() {
|
|
3810
|
+
"use strict";
|
|
3811
|
+
init_config();
|
|
3812
|
+
MCP_HTTP_EVENTS_PATH = path8.join(EXE_AI_DIR, "mcp-http-events.jsonl");
|
|
3813
|
+
MCP_MONITOR_DIR = path8.join(EXE_AI_DIR, "monitor");
|
|
3814
|
+
MCP_TRANSPORT_SUMMARY_PATH = path8.join(MCP_MONITOR_DIR, "mcp-transport-summary.json");
|
|
3815
|
+
DEFAULT_EVENT_READ_BYTES = 256 * 1024;
|
|
3816
|
+
DEFAULT_EVENT_MAX_BYTES = 1024 * 1024;
|
|
3817
|
+
EVENT_READ_BYTES = parsePositiveInt(process.env.EXE_MCP_HTTP_EVENT_READ_BYTES, DEFAULT_EVENT_READ_BYTES);
|
|
3818
|
+
EVENT_MAX_BYTES = parsePositiveInt(process.env.EXE_MCP_HTTP_EVENT_MAX_BYTES, DEFAULT_EVENT_MAX_BYTES);
|
|
3819
|
+
}
|
|
3820
|
+
});
|
|
3821
|
+
|
|
3658
3822
|
// src/lib/agentic-ontology.ts
|
|
3659
3823
|
var agentic_ontology_exports = {};
|
|
3660
3824
|
__export(agentic_ontology_exports, {
|
|
@@ -3936,8 +4100,8 @@ __export(projection_worker_exports, {
|
|
|
3936
4100
|
stopProjectionWorker: () => stopProjectionWorker
|
|
3937
4101
|
});
|
|
3938
4102
|
import os5 from "os";
|
|
3939
|
-
import
|
|
3940
|
-
import { existsSync as
|
|
4103
|
+
import path9 from "path";
|
|
4104
|
+
import { existsSync as existsSync9 } from "fs";
|
|
3941
4105
|
import { createRequire as createRequire2 } from "module";
|
|
3942
4106
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
3943
4107
|
function loadPrisma() {
|
|
@@ -3950,9 +4114,9 @@ function loadPrisma() {
|
|
|
3950
4114
|
if (!Ctor) throw new Error(`No PrismaClient at ${explicitPath}`);
|
|
3951
4115
|
return new Ctor();
|
|
3952
4116
|
}
|
|
3953
|
-
const exeDbRoot = process.env.EXE_DB_ROOT ??
|
|
3954
|
-
const packagePath =
|
|
3955
|
-
if (
|
|
4117
|
+
const exeDbRoot = process.env.EXE_DB_ROOT ?? path9.join(os5.homedir(), "exe-db");
|
|
4118
|
+
const packagePath = path9.join(exeDbRoot, "package.json");
|
|
4119
|
+
if (existsSync9(packagePath)) {
|
|
3956
4120
|
const req = createRequire2(packagePath);
|
|
3957
4121
|
const entry = req.resolve("@prisma/client");
|
|
3958
4122
|
const mod = await import(pathToFileURL2(entry).href);
|
|
@@ -4386,8 +4550,8 @@ async function shouldStartProjectionWorker() {
|
|
|
4386
4550
|
if (!process.env.DATABASE_URL) {
|
|
4387
4551
|
return { start: false, reason: "DATABASE_URL is not set" };
|
|
4388
4552
|
}
|
|
4389
|
-
const exeDbRoot = process.env.EXE_DB_ROOT ??
|
|
4390
|
-
if (!
|
|
4553
|
+
const exeDbRoot = process.env.EXE_DB_ROOT ?? path9.join(os5.homedir(), "exe-db");
|
|
4554
|
+
if (!existsSync9(path9.join(exeDbRoot, "package.json")) && !process.env.EXE_OS_PRISMA_CLIENT_PATH) {
|
|
4391
4555
|
try {
|
|
4392
4556
|
await import("pg");
|
|
4393
4557
|
} catch {
|
|
@@ -4592,13 +4756,13 @@ __export(shard_manager_exports, {
|
|
|
4592
4756
|
listShards: () => listShards,
|
|
4593
4757
|
shardExists: () => shardExists
|
|
4594
4758
|
});
|
|
4595
|
-
import
|
|
4596
|
-
import { existsSync as
|
|
4759
|
+
import path10 from "path";
|
|
4760
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync3, readdirSync, renameSync as renameSync3, statSync as statSync3 } from "fs";
|
|
4597
4761
|
import { createClient as createClient2 } from "@libsql/client";
|
|
4598
4762
|
function initShardManager(encryptionKey) {
|
|
4599
4763
|
_encryptionKey = encryptionKey;
|
|
4600
|
-
if (!
|
|
4601
|
-
|
|
4764
|
+
if (!existsSync10(SHARDS_DIR)) {
|
|
4765
|
+
mkdirSync3(SHARDS_DIR, { recursive: true });
|
|
4602
4766
|
}
|
|
4603
4767
|
_shardingEnabled = true;
|
|
4604
4768
|
if (_evictionTimer) clearInterval(_evictionTimer);
|
|
@@ -4627,7 +4791,7 @@ function getShardClient(projectName) {
|
|
|
4627
4791
|
while (_shards.size >= MAX_OPEN_SHARDS) {
|
|
4628
4792
|
evictLRU();
|
|
4629
4793
|
}
|
|
4630
|
-
const dbPath =
|
|
4794
|
+
const dbPath = path10.join(SHARDS_DIR, `${safeName}.db`);
|
|
4631
4795
|
const client = createClient2({
|
|
4632
4796
|
url: `file:${dbPath}`,
|
|
4633
4797
|
encryptionKey: _encryptionKey
|
|
@@ -4638,13 +4802,13 @@ function getShardClient(projectName) {
|
|
|
4638
4802
|
}
|
|
4639
4803
|
function shardExists(projectName) {
|
|
4640
4804
|
const safeName = safeShardName(projectName);
|
|
4641
|
-
return
|
|
4805
|
+
return existsSync10(path10.join(SHARDS_DIR, `${safeName}.db`));
|
|
4642
4806
|
}
|
|
4643
4807
|
function safeShardName(projectName) {
|
|
4644
4808
|
return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
4645
4809
|
}
|
|
4646
4810
|
function listShards() {
|
|
4647
|
-
if (!
|
|
4811
|
+
if (!existsSync10(SHARDS_DIR)) return [];
|
|
4648
4812
|
return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
4649
4813
|
}
|
|
4650
4814
|
async function auditShardHealth(options = {}) {
|
|
@@ -4656,8 +4820,8 @@ async function auditShardHealth(options = {}) {
|
|
|
4656
4820
|
const names = listShards();
|
|
4657
4821
|
const shards = [];
|
|
4658
4822
|
for (const name of names) {
|
|
4659
|
-
const dbPath =
|
|
4660
|
-
const stat =
|
|
4823
|
+
const dbPath = path10.join(SHARDS_DIR, `${name}.db`);
|
|
4824
|
+
const stat = statSync3(dbPath);
|
|
4661
4825
|
const item = {
|
|
4662
4826
|
name,
|
|
4663
4827
|
path: dbPath,
|
|
@@ -4691,7 +4855,7 @@ async function auditShardHealth(options = {}) {
|
|
|
4691
4855
|
_shards.delete(name);
|
|
4692
4856
|
_shardLastAccess.delete(name);
|
|
4693
4857
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
4694
|
-
const archivedPath =
|
|
4858
|
+
const archivedPath = path10.join(SHARDS_DIR, `${name}.db.broken-${stamp}`);
|
|
4695
4859
|
renameSync3(dbPath, archivedPath);
|
|
4696
4860
|
item.archivedPath = archivedPath;
|
|
4697
4861
|
}
|
|
@@ -4908,11 +5072,11 @@ async function getReadyShardClient(projectName) {
|
|
|
4908
5072
|
client.close();
|
|
4909
5073
|
_shards.delete(safeName);
|
|
4910
5074
|
_shardLastAccess.delete(safeName);
|
|
4911
|
-
const dbPath =
|
|
4912
|
-
if (
|
|
4913
|
-
const stat =
|
|
5075
|
+
const dbPath = path10.join(SHARDS_DIR, `${safeName}.db`);
|
|
5076
|
+
if (existsSync10(dbPath)) {
|
|
5077
|
+
const stat = statSync3(dbPath);
|
|
4914
5078
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
4915
|
-
const archivedPath =
|
|
5079
|
+
const archivedPath = path10.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
4916
5080
|
renameSync3(dbPath, archivedPath);
|
|
4917
5081
|
process.stderr.write(
|
|
4918
5082
|
`[shard-manager] Archived unreadable shard ${safeName}: ${archivedPath} (${stat.size} bytes, mtime ${stat.mtime.toISOString()})
|
|
@@ -4980,7 +5144,7 @@ var init_shard_manager = __esm({
|
|
|
4980
5144
|
"src/lib/shard-manager.ts"() {
|
|
4981
5145
|
"use strict";
|
|
4982
5146
|
init_config();
|
|
4983
|
-
SHARDS_DIR =
|
|
5147
|
+
SHARDS_DIR = path10.join(EXE_AI_DIR, "shards");
|
|
4984
5148
|
SHARD_IDLE_MS = 5 * 60 * 1e3;
|
|
4985
5149
|
MAX_OPEN_SHARDS = 10;
|
|
4986
5150
|
EVICTION_INTERVAL_MS = 60 * 1e3;
|
|
@@ -5003,15 +5167,15 @@ __export(keychain_exports, {
|
|
|
5003
5167
|
setMasterKey: () => setMasterKey
|
|
5004
5168
|
});
|
|
5005
5169
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
5006
|
-
import { existsSync as
|
|
5170
|
+
import { existsSync as existsSync11, statSync as statSync4 } from "fs";
|
|
5007
5171
|
import { execSync as execSync2 } from "child_process";
|
|
5008
|
-
import
|
|
5172
|
+
import path11 from "path";
|
|
5009
5173
|
import os6 from "os";
|
|
5010
5174
|
function getKeyDir() {
|
|
5011
|
-
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ??
|
|
5175
|
+
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path11.join(os6.homedir(), ".exe-os");
|
|
5012
5176
|
}
|
|
5013
5177
|
function getKeyPath() {
|
|
5014
|
-
return
|
|
5178
|
+
return path11.join(getKeyDir(), "master.key");
|
|
5015
5179
|
}
|
|
5016
5180
|
function nativeKeychainAllowed() {
|
|
5017
5181
|
return process.env.EXE_OS_DISABLE_NATIVE_KEYCHAIN !== "1";
|
|
@@ -5038,11 +5202,11 @@ function isRootOnlyTrustedServerKeyFile(keyPath) {
|
|
|
5038
5202
|
if (process.platform !== "linux") return false;
|
|
5039
5203
|
try {
|
|
5040
5204
|
const uid = typeof os6.userInfo().uid === "number" ? os6.userInfo().uid : -1;
|
|
5041
|
-
const st =
|
|
5205
|
+
const st = statSync4(keyPath);
|
|
5042
5206
|
if (!st.isFile() || (st.mode & 63) !== 0) return false;
|
|
5043
5207
|
if (uid === 0) return true;
|
|
5044
5208
|
const exeOsDir = process.env.EXE_OS_DIR;
|
|
5045
|
-
return Boolean(exeOsDir &&
|
|
5209
|
+
return Boolean(exeOsDir && path11.resolve(keyPath).startsWith(path11.resolve(exeOsDir) + path11.sep));
|
|
5046
5210
|
} catch {
|
|
5047
5211
|
return false;
|
|
5048
5212
|
}
|
|
@@ -5154,8 +5318,8 @@ function deriveMachineKey() {
|
|
|
5154
5318
|
}
|
|
5155
5319
|
function readMachineId() {
|
|
5156
5320
|
try {
|
|
5157
|
-
const { readFileSync:
|
|
5158
|
-
return
|
|
5321
|
+
const { readFileSync: readFileSync40 } = __require("fs");
|
|
5322
|
+
return readFileSync40("/etc/machine-id", "utf-8").trim();
|
|
5159
5323
|
} catch {
|
|
5160
5324
|
return "";
|
|
5161
5325
|
}
|
|
@@ -5239,7 +5403,7 @@ async function getMasterKey() {
|
|
|
5239
5403
|
}
|
|
5240
5404
|
}
|
|
5241
5405
|
const keyPath = getKeyPath();
|
|
5242
|
-
if (!
|
|
5406
|
+
if (!existsSync11(keyPath)) {
|
|
5243
5407
|
process.stderr.write(
|
|
5244
5408
|
`[keychain] Key not found at ${keyPath} (HOME=${os6.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
|
|
5245
5409
|
`
|
|
@@ -5347,7 +5511,7 @@ async function getKeyStorageInfo() {
|
|
|
5347
5511
|
}
|
|
5348
5512
|
}
|
|
5349
5513
|
const keyPath = getKeyPath();
|
|
5350
|
-
if (!
|
|
5514
|
+
if (!existsSync11(keyPath)) {
|
|
5351
5515
|
return {
|
|
5352
5516
|
kind: "missing",
|
|
5353
5517
|
secure: false,
|
|
@@ -5424,7 +5588,7 @@ async function deleteMasterKey() {
|
|
|
5424
5588
|
}
|
|
5425
5589
|
}
|
|
5426
5590
|
const keyPath = getKeyPath();
|
|
5427
|
-
if (
|
|
5591
|
+
if (existsSync11(keyPath)) {
|
|
5428
5592
|
await unlink(keyPath);
|
|
5429
5593
|
}
|
|
5430
5594
|
}
|
|
@@ -6579,23 +6743,23 @@ __export(memory_queue_exports, {
|
|
|
6579
6743
|
enqueueMemory: () => enqueueMemory,
|
|
6580
6744
|
queueDepth: () => queueDepth
|
|
6581
6745
|
});
|
|
6582
|
-
import { appendFileSync, readFileSync as
|
|
6583
|
-
import
|
|
6746
|
+
import { appendFileSync as appendFileSync2, readFileSync as readFileSync8, renameSync as renameSync4, unlinkSync as unlinkSync3, existsSync as existsSync12, statSync as statSync5 } from "fs";
|
|
6747
|
+
import path12 from "path";
|
|
6584
6748
|
function enqueueMemory(entry) {
|
|
6585
|
-
|
|
6749
|
+
appendFileSync2(QUEUE_PATH, JSON.stringify(entry) + "\n");
|
|
6586
6750
|
}
|
|
6587
6751
|
function drainQueue() {
|
|
6588
6752
|
const entries = [];
|
|
6589
|
-
if (
|
|
6753
|
+
if (existsSync12(PROCESSING_PATH)) {
|
|
6590
6754
|
entries.push(...parseQueueFile(PROCESSING_PATH));
|
|
6591
6755
|
try {
|
|
6592
6756
|
unlinkSync3(PROCESSING_PATH);
|
|
6593
6757
|
} catch {
|
|
6594
6758
|
}
|
|
6595
6759
|
}
|
|
6596
|
-
if (!
|
|
6760
|
+
if (!existsSync12(QUEUE_PATH)) return entries;
|
|
6597
6761
|
try {
|
|
6598
|
-
const stat =
|
|
6762
|
+
const stat = statSync5(QUEUE_PATH);
|
|
6599
6763
|
if (stat.size === 0) return entries;
|
|
6600
6764
|
} catch {
|
|
6601
6765
|
return entries;
|
|
@@ -6613,9 +6777,9 @@ function drainQueue() {
|
|
|
6613
6777
|
return entries;
|
|
6614
6778
|
}
|
|
6615
6779
|
function queueDepth() {
|
|
6616
|
-
if (!
|
|
6780
|
+
if (!existsSync12(QUEUE_PATH)) return 0;
|
|
6617
6781
|
try {
|
|
6618
|
-
const content =
|
|
6782
|
+
const content = readFileSync8(QUEUE_PATH, "utf8");
|
|
6619
6783
|
return content.split("\n").filter((line) => line.trim().length > 0).length;
|
|
6620
6784
|
} catch {
|
|
6621
6785
|
return 0;
|
|
@@ -6626,7 +6790,7 @@ function parseQueueFile(filePath) {
|
|
|
6626
6790
|
const entries = [];
|
|
6627
6791
|
let content;
|
|
6628
6792
|
try {
|
|
6629
|
-
content =
|
|
6793
|
+
content = readFileSync8(filePath, "utf8");
|
|
6630
6794
|
} catch {
|
|
6631
6795
|
return entries;
|
|
6632
6796
|
}
|
|
@@ -6652,7 +6816,7 @@ var init_memory_queue = __esm({
|
|
|
6652
6816
|
"src/lib/memory-queue.ts"() {
|
|
6653
6817
|
"use strict";
|
|
6654
6818
|
init_config();
|
|
6655
|
-
QUEUE_PATH =
|
|
6819
|
+
QUEUE_PATH = path12.join(EXE_AI_DIR, "memory-queue.jsonl");
|
|
6656
6820
|
PROCESSING_PATH = QUEUE_PATH + ".processing";
|
|
6657
6821
|
TTL_MS = 24 * 60 * 60 * 1e3;
|
|
6658
6822
|
}
|
|
@@ -6818,8 +6982,8 @@ __export(reranker_exports, {
|
|
|
6818
6982
|
rerankWithContext: () => rerankWithContext,
|
|
6819
6983
|
rerankWithScores: () => rerankWithScores
|
|
6820
6984
|
});
|
|
6821
|
-
import
|
|
6822
|
-
import { existsSync as
|
|
6985
|
+
import path13 from "path";
|
|
6986
|
+
import { existsSync as existsSync13 } from "fs";
|
|
6823
6987
|
function resetIdleTimer() {
|
|
6824
6988
|
if (_idleTimer) clearTimeout(_idleTimer);
|
|
6825
6989
|
_idleTimer = setTimeout(() => {
|
|
@@ -6830,18 +6994,18 @@ function resetIdleTimer() {
|
|
|
6830
6994
|
}
|
|
6831
6995
|
}
|
|
6832
6996
|
function isRerankerAvailable() {
|
|
6833
|
-
return
|
|
6997
|
+
return existsSync13(path13.join(MODELS_DIR, RERANKER_MODEL_FILE));
|
|
6834
6998
|
}
|
|
6835
6999
|
function getRerankerModelPath() {
|
|
6836
|
-
return
|
|
7000
|
+
return path13.join(MODELS_DIR, RERANKER_MODEL_FILE);
|
|
6837
7001
|
}
|
|
6838
7002
|
async function ensureLoaded() {
|
|
6839
7003
|
if (_rerankerContext) {
|
|
6840
7004
|
resetIdleTimer();
|
|
6841
7005
|
return;
|
|
6842
7006
|
}
|
|
6843
|
-
const modelPath =
|
|
6844
|
-
if (!
|
|
7007
|
+
const modelPath = path13.join(MODELS_DIR, RERANKER_MODEL_FILE);
|
|
7008
|
+
if (!existsSync13(modelPath)) {
|
|
6845
7009
|
throw new Error(
|
|
6846
7010
|
`Reranker model not found at ${modelPath}. Run /exe-setup to download it.`
|
|
6847
7011
|
);
|
|
@@ -6974,10 +7138,10 @@ async function disposeEmbedder() {
|
|
|
6974
7138
|
async function embedDirect(text3) {
|
|
6975
7139
|
const llamaCpp = await import("node-llama-cpp");
|
|
6976
7140
|
const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
6977
|
-
const { existsSync:
|
|
6978
|
-
const
|
|
6979
|
-
const modelPath =
|
|
6980
|
-
if (!
|
|
7141
|
+
const { existsSync: existsSync47 } = await import("fs");
|
|
7142
|
+
const path60 = await import("path");
|
|
7143
|
+
const modelPath = path60.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
|
|
7144
|
+
if (!existsSync47(modelPath)) {
|
|
6981
7145
|
throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
|
|
6982
7146
|
}
|
|
6983
7147
|
const llama = await llamaCpp.getLlama();
|
|
@@ -7012,7 +7176,7 @@ __export(project_name_exports, {
|
|
|
7012
7176
|
getProjectName: () => getProjectName
|
|
7013
7177
|
});
|
|
7014
7178
|
import { execSync as execSync3 } from "child_process";
|
|
7015
|
-
import
|
|
7179
|
+
import path14 from "path";
|
|
7016
7180
|
function getProjectName(cwd) {
|
|
7017
7181
|
const dir = cwd ?? process.cwd();
|
|
7018
7182
|
if (_cached && _cachedCwd === dir) return _cached;
|
|
@@ -7025,7 +7189,7 @@ function getProjectName(cwd) {
|
|
|
7025
7189
|
timeout: 2e3,
|
|
7026
7190
|
stdio: ["pipe", "pipe", "pipe"]
|
|
7027
7191
|
}).trim();
|
|
7028
|
-
repoRoot =
|
|
7192
|
+
repoRoot = path14.dirname(gitCommonDir);
|
|
7029
7193
|
} catch {
|
|
7030
7194
|
repoRoot = execSync3("git rev-parse --show-toplevel", {
|
|
7031
7195
|
cwd: dir,
|
|
@@ -7034,11 +7198,11 @@ function getProjectName(cwd) {
|
|
|
7034
7198
|
stdio: ["pipe", "pipe", "pipe"]
|
|
7035
7199
|
}).trim();
|
|
7036
7200
|
}
|
|
7037
|
-
_cached =
|
|
7201
|
+
_cached = path14.basename(repoRoot);
|
|
7038
7202
|
_cachedCwd = dir;
|
|
7039
7203
|
return _cached;
|
|
7040
7204
|
} catch {
|
|
7041
|
-
_cached =
|
|
7205
|
+
_cached = path14.basename(dir);
|
|
7042
7206
|
_cachedCwd = dir;
|
|
7043
7207
|
return _cached;
|
|
7044
7208
|
}
|
|
@@ -7062,8 +7226,8 @@ __export(file_grep_exports, {
|
|
|
7062
7226
|
grepProjectFiles: () => grepProjectFiles
|
|
7063
7227
|
});
|
|
7064
7228
|
import { execSync as execSync4 } from "child_process";
|
|
7065
|
-
import { readFileSync as
|
|
7066
|
-
import
|
|
7229
|
+
import { readFileSync as readFileSync9, readdirSync as readdirSync2, statSync as statSync6, existsSync as existsSync14 } from "fs";
|
|
7230
|
+
import path15 from "path";
|
|
7067
7231
|
import crypto3 from "crypto";
|
|
7068
7232
|
function hasRipgrep() {
|
|
7069
7233
|
if (_hasRg === null) {
|
|
@@ -7103,7 +7267,7 @@ async function grepProjectFiles(query, projectRoot, options) {
|
|
|
7103
7267
|
session_id: "file-grep",
|
|
7104
7268
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7105
7269
|
tool_name: "file_grep",
|
|
7106
|
-
project_name:
|
|
7270
|
+
project_name: path15.basename(projectRoot),
|
|
7107
7271
|
has_error: false,
|
|
7108
7272
|
raw_text: `${prefix} ${buildSnippet(hit, projectRoot)}`,
|
|
7109
7273
|
vector: null,
|
|
@@ -7115,7 +7279,7 @@ function getChunkContext(filePath, lineNumber) {
|
|
|
7115
7279
|
try {
|
|
7116
7280
|
const ext = filePath.split(".").pop()?.toLowerCase();
|
|
7117
7281
|
if (ext !== "ts" && ext !== "tsx" && ext !== "js" && ext !== "jsx") return "";
|
|
7118
|
-
const source =
|
|
7282
|
+
const source = readFileSync9(filePath, "utf8");
|
|
7119
7283
|
const lines = source.split("\n");
|
|
7120
7284
|
for (let i = Math.min(lineNumber - 1, lines.length - 1); i >= 0; i--) {
|
|
7121
7285
|
const line = lines[i];
|
|
@@ -7177,11 +7341,11 @@ function grepWithNodeFs(pattern, projectRoot, patterns) {
|
|
|
7177
7341
|
const files = collectFiles(projectRoot, patterns ?? DEFAULT_PATTERNS);
|
|
7178
7342
|
const hits = [];
|
|
7179
7343
|
for (const filePath of files.slice(0, MAX_FILES)) {
|
|
7180
|
-
const absPath =
|
|
7344
|
+
const absPath = path15.join(projectRoot, filePath);
|
|
7181
7345
|
try {
|
|
7182
|
-
const stat =
|
|
7346
|
+
const stat = statSync6(absPath);
|
|
7183
7347
|
if (stat.size > MAX_FILE_SIZE) continue;
|
|
7184
|
-
const content =
|
|
7348
|
+
const content = readFileSync9(absPath, "utf8");
|
|
7185
7349
|
const lines = content.split("\n");
|
|
7186
7350
|
const matches = content.match(regex);
|
|
7187
7351
|
if (!matches || matches.length === 0) continue;
|
|
@@ -7204,15 +7368,15 @@ function collectFiles(root, patterns) {
|
|
|
7204
7368
|
const files = [];
|
|
7205
7369
|
function walk(dir, relative) {
|
|
7206
7370
|
if (files.length >= MAX_FILES) return;
|
|
7207
|
-
const basename =
|
|
7371
|
+
const basename = path15.basename(dir);
|
|
7208
7372
|
if (EXCLUDE_DIRS.includes(basename)) return;
|
|
7209
7373
|
try {
|
|
7210
7374
|
const entries = readdirSync2(dir, { withFileTypes: true });
|
|
7211
7375
|
for (const entry of entries) {
|
|
7212
7376
|
if (files.length >= MAX_FILES) return;
|
|
7213
|
-
const rel =
|
|
7377
|
+
const rel = path15.join(relative, entry.name);
|
|
7214
7378
|
if (entry.isDirectory()) {
|
|
7215
|
-
walk(
|
|
7379
|
+
walk(path15.join(dir, entry.name), rel);
|
|
7216
7380
|
} else if (entry.isFile()) {
|
|
7217
7381
|
for (const pat of patterns) {
|
|
7218
7382
|
if (matchGlob(rel, pat)) {
|
|
@@ -7244,7 +7408,7 @@ function matchGlob(filePath, pattern) {
|
|
|
7244
7408
|
if (slashIdx !== -1) {
|
|
7245
7409
|
const dir = pattern.slice(0, slashIdx);
|
|
7246
7410
|
const ext2 = pattern.slice(slashIdx + 1).replace("*", "");
|
|
7247
|
-
const fileDir =
|
|
7411
|
+
const fileDir = path15.dirname(filePath);
|
|
7248
7412
|
return fileDir === dir && filePath.endsWith(ext2);
|
|
7249
7413
|
}
|
|
7250
7414
|
const ext = pattern.replace("*", "");
|
|
@@ -7252,9 +7416,9 @@ function matchGlob(filePath, pattern) {
|
|
|
7252
7416
|
}
|
|
7253
7417
|
function buildSnippet(hit, projectRoot) {
|
|
7254
7418
|
try {
|
|
7255
|
-
const absPath =
|
|
7256
|
-
if (!
|
|
7257
|
-
const lines =
|
|
7419
|
+
const absPath = path15.join(projectRoot, hit.filePath);
|
|
7420
|
+
if (!existsSync14(absPath)) return hit.matchLine;
|
|
7421
|
+
const lines = readFileSync9(absPath, "utf8").split("\n");
|
|
7258
7422
|
const start = Math.max(0, hit.lineNumber - 3);
|
|
7259
7423
|
const end = Math.min(lines.length, hit.lineNumber + 2);
|
|
7260
7424
|
return lines.slice(start, end).join("\n").slice(0, 500);
|
|
@@ -8068,10 +8232,10 @@ async function hybridSearch(queryText, agentId, options) {
|
|
|
8068
8232
|
};
|
|
8069
8233
|
try {
|
|
8070
8234
|
const fs = await import("fs");
|
|
8071
|
-
const
|
|
8235
|
+
const path60 = await import("path");
|
|
8072
8236
|
const os25 = await import("os");
|
|
8073
|
-
const logPath =
|
|
8074
|
-
fs.mkdirSync(
|
|
8237
|
+
const logPath = path60.join(os25.homedir(), ".exe-os", "search-quality.jsonl");
|
|
8238
|
+
fs.mkdirSync(path60.dirname(logPath), { recursive: true });
|
|
8075
8239
|
fs.appendFileSync(logPath, JSON.stringify(logEntry) + "\n");
|
|
8076
8240
|
} catch {
|
|
8077
8241
|
}
|
|
@@ -8603,9 +8767,9 @@ __export(active_agent_exports, {
|
|
|
8603
8767
|
resolveActiveAgentFromTmuxSession: () => resolveActiveAgentFromTmuxSession,
|
|
8604
8768
|
writeActiveAgent: () => writeActiveAgent
|
|
8605
8769
|
});
|
|
8606
|
-
import { readFileSync as
|
|
8770
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync6, mkdirSync as mkdirSync4, unlinkSync as unlinkSync4, readdirSync as readdirSync3 } from "fs";
|
|
8607
8771
|
import { execSync as execSync6 } from "child_process";
|
|
8608
|
-
import
|
|
8772
|
+
import path16 from "path";
|
|
8609
8773
|
function isNameWithOptionalInstance(candidate, baseName) {
|
|
8610
8774
|
if (candidate === baseName) return true;
|
|
8611
8775
|
if (!candidate.startsWith(baseName)) return false;
|
|
@@ -8649,12 +8813,12 @@ function resolveActiveAgentFromTmuxSession(sessionName) {
|
|
|
8649
8813
|
return null;
|
|
8650
8814
|
}
|
|
8651
8815
|
function getMarkerPath() {
|
|
8652
|
-
return
|
|
8816
|
+
return path16.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
|
|
8653
8817
|
}
|
|
8654
8818
|
function writeActiveAgent(agentId, agentRole) {
|
|
8655
8819
|
try {
|
|
8656
|
-
|
|
8657
|
-
|
|
8820
|
+
mkdirSync4(CACHE_DIR, { recursive: true });
|
|
8821
|
+
writeFileSync6(
|
|
8658
8822
|
getMarkerPath(),
|
|
8659
8823
|
JSON.stringify({ agentId, agentRole, startedAt: (/* @__PURE__ */ new Date()).toISOString() })
|
|
8660
8824
|
);
|
|
@@ -8672,7 +8836,7 @@ function getActiveAgent() {
|
|
|
8672
8836
|
if (httpCtx) return httpCtx;
|
|
8673
8837
|
try {
|
|
8674
8838
|
const markerPath = getMarkerPath();
|
|
8675
|
-
const raw =
|
|
8839
|
+
const raw = readFileSync10(markerPath, "utf8");
|
|
8676
8840
|
const data = JSON.parse(raw);
|
|
8677
8841
|
if (data.agentId) {
|
|
8678
8842
|
if (data.startedAt) {
|
|
@@ -8720,14 +8884,14 @@ function getAllActiveAgents() {
|
|
|
8720
8884
|
const key = file.slice("active-agent-".length, -".json".length);
|
|
8721
8885
|
if (key === "undefined") continue;
|
|
8722
8886
|
try {
|
|
8723
|
-
const raw =
|
|
8887
|
+
const raw = readFileSync10(path16.join(CACHE_DIR, file), "utf8");
|
|
8724
8888
|
const data = JSON.parse(raw);
|
|
8725
8889
|
if (!data.agentId) continue;
|
|
8726
8890
|
if (data.startedAt) {
|
|
8727
8891
|
const age = Date.now() - new Date(data.startedAt).getTime();
|
|
8728
8892
|
if (age > STALE_MS) {
|
|
8729
8893
|
try {
|
|
8730
|
-
unlinkSync4(
|
|
8894
|
+
unlinkSync4(path16.join(CACHE_DIR, file));
|
|
8731
8895
|
} catch {
|
|
8732
8896
|
}
|
|
8733
8897
|
continue;
|
|
@@ -8750,11 +8914,11 @@ function getAllActiveAgents() {
|
|
|
8750
8914
|
function cleanupSessionMarkers() {
|
|
8751
8915
|
const key = getSessionKey();
|
|
8752
8916
|
try {
|
|
8753
|
-
unlinkSync4(
|
|
8917
|
+
unlinkSync4(path16.join(CACHE_DIR, `active-agent-${key}.json`));
|
|
8754
8918
|
} catch {
|
|
8755
8919
|
}
|
|
8756
8920
|
try {
|
|
8757
|
-
unlinkSync4(
|
|
8921
|
+
unlinkSync4(path16.join(CACHE_DIR, "active-agent-undefined.json"));
|
|
8758
8922
|
} catch {
|
|
8759
8923
|
}
|
|
8760
8924
|
}
|
|
@@ -8766,7 +8930,7 @@ var init_active_agent = __esm({
|
|
|
8766
8930
|
init_session_key();
|
|
8767
8931
|
init_agent_context();
|
|
8768
8932
|
init_employees();
|
|
8769
|
-
CACHE_DIR =
|
|
8933
|
+
CACHE_DIR = path16.join(EXE_AI_DIR, "session-cache");
|
|
8770
8934
|
STALE_MS = 24 * 60 * 60 * 1e3;
|
|
8771
8935
|
}
|
|
8772
8936
|
});
|
|
@@ -9031,12 +9195,12 @@ var init_ask_team_memory = __esm({
|
|
|
9031
9195
|
});
|
|
9032
9196
|
|
|
9033
9197
|
// src/lib/license.ts
|
|
9034
|
-
import { readFileSync as
|
|
9198
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync7, existsSync as existsSync15, mkdirSync as mkdirSync5 } from "fs";
|
|
9035
9199
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
9036
9200
|
import { createRequire as createRequire3 } from "module";
|
|
9037
9201
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
9038
9202
|
import os7 from "os";
|
|
9039
|
-
import
|
|
9203
|
+
import path17 from "path";
|
|
9040
9204
|
import { jwtVerify, importSPKI } from "jose";
|
|
9041
9205
|
async function fetchRetry(url, init) {
|
|
9042
9206
|
try {
|
|
@@ -9047,37 +9211,37 @@ async function fetchRetry(url, init) {
|
|
|
9047
9211
|
}
|
|
9048
9212
|
}
|
|
9049
9213
|
function loadDeviceId() {
|
|
9050
|
-
const deviceJsonPath =
|
|
9214
|
+
const deviceJsonPath = path17.join(EXE_AI_DIR, "device.json");
|
|
9051
9215
|
try {
|
|
9052
|
-
if (
|
|
9053
|
-
const data = JSON.parse(
|
|
9216
|
+
if (existsSync15(deviceJsonPath)) {
|
|
9217
|
+
const data = JSON.parse(readFileSync11(deviceJsonPath, "utf8"));
|
|
9054
9218
|
if (data.deviceId) return data.deviceId;
|
|
9055
9219
|
}
|
|
9056
9220
|
} catch {
|
|
9057
9221
|
}
|
|
9058
9222
|
try {
|
|
9059
|
-
if (
|
|
9060
|
-
const id2 =
|
|
9223
|
+
if (existsSync15(DEVICE_ID_PATH)) {
|
|
9224
|
+
const id2 = readFileSync11(DEVICE_ID_PATH, "utf8").trim();
|
|
9061
9225
|
if (id2) return id2;
|
|
9062
9226
|
}
|
|
9063
9227
|
} catch {
|
|
9064
9228
|
}
|
|
9065
9229
|
const id = randomUUID3();
|
|
9066
|
-
|
|
9067
|
-
|
|
9230
|
+
mkdirSync5(EXE_AI_DIR, { recursive: true });
|
|
9231
|
+
writeFileSync7(DEVICE_ID_PATH, id, "utf8");
|
|
9068
9232
|
return id;
|
|
9069
9233
|
}
|
|
9070
9234
|
function loadLicense() {
|
|
9071
9235
|
try {
|
|
9072
|
-
if (!
|
|
9073
|
-
return
|
|
9236
|
+
if (!existsSync15(LICENSE_PATH)) return null;
|
|
9237
|
+
return readFileSync11(LICENSE_PATH, "utf8").trim();
|
|
9074
9238
|
} catch {
|
|
9075
9239
|
return null;
|
|
9076
9240
|
}
|
|
9077
9241
|
}
|
|
9078
9242
|
function saveLicense(apiKey) {
|
|
9079
|
-
|
|
9080
|
-
|
|
9243
|
+
mkdirSync5(EXE_AI_DIR, { recursive: true });
|
|
9244
|
+
writeFileSync7(LICENSE_PATH, apiKey.trim(), { encoding: "utf8", mode: 384 });
|
|
9081
9245
|
}
|
|
9082
9246
|
async function verifyLicenseJwt(token) {
|
|
9083
9247
|
try {
|
|
@@ -9103,8 +9267,8 @@ async function verifyLicenseJwt(token) {
|
|
|
9103
9267
|
}
|
|
9104
9268
|
async function getCachedLicense() {
|
|
9105
9269
|
try {
|
|
9106
|
-
if (!
|
|
9107
|
-
const raw = JSON.parse(
|
|
9270
|
+
if (!existsSync15(CACHE_PATH)) return null;
|
|
9271
|
+
const raw = JSON.parse(readFileSync11(CACHE_PATH, "utf8"));
|
|
9108
9272
|
if (!raw.token || typeof raw.token !== "string") return null;
|
|
9109
9273
|
return await verifyLicenseJwt(raw.token);
|
|
9110
9274
|
} catch {
|
|
@@ -9113,8 +9277,8 @@ async function getCachedLicense() {
|
|
|
9113
9277
|
}
|
|
9114
9278
|
function readCachedToken() {
|
|
9115
9279
|
try {
|
|
9116
|
-
if (!
|
|
9117
|
-
const raw = JSON.parse(
|
|
9280
|
+
if (!existsSync15(CACHE_PATH)) return null;
|
|
9281
|
+
const raw = JSON.parse(readFileSync11(CACHE_PATH, "utf8"));
|
|
9118
9282
|
return typeof raw.token === "string" ? raw.token : null;
|
|
9119
9283
|
} catch {
|
|
9120
9284
|
return null;
|
|
@@ -9148,7 +9312,7 @@ function getRawCachedPlan() {
|
|
|
9148
9312
|
}
|
|
9149
9313
|
function cacheResponse(token) {
|
|
9150
9314
|
try {
|
|
9151
|
-
|
|
9315
|
+
writeFileSync7(CACHE_PATH, JSON.stringify({ token }), "utf8");
|
|
9152
9316
|
} catch {
|
|
9153
9317
|
}
|
|
9154
9318
|
}
|
|
@@ -9156,8 +9320,8 @@ function loadPrismaForLicense() {
|
|
|
9156
9320
|
if (_prismaFailed) return null;
|
|
9157
9321
|
const dbUrl = process.env.DATABASE_URL;
|
|
9158
9322
|
if (!dbUrl) {
|
|
9159
|
-
const exeDbRoot = process.env.EXE_DB_ROOT ??
|
|
9160
|
-
if (!
|
|
9323
|
+
const exeDbRoot = process.env.EXE_DB_ROOT ?? path17.join(os7.homedir(), "exe-db");
|
|
9324
|
+
if (!existsSync15(path17.join(exeDbRoot, "package.json"))) {
|
|
9161
9325
|
_prismaFailed = true;
|
|
9162
9326
|
return null;
|
|
9163
9327
|
}
|
|
@@ -9171,8 +9335,8 @@ function loadPrismaForLicense() {
|
|
|
9171
9335
|
if (!Ctor2) throw new Error(`No PrismaClient at ${explicitPath}`);
|
|
9172
9336
|
return new Ctor2();
|
|
9173
9337
|
}
|
|
9174
|
-
const exeDbRoot = process.env.EXE_DB_ROOT ??
|
|
9175
|
-
const req = createRequire3(
|
|
9338
|
+
const exeDbRoot = process.env.EXE_DB_ROOT ?? path17.join(os7.homedir(), "exe-db");
|
|
9339
|
+
const req = createRequire3(path17.join(exeDbRoot, "package.json"));
|
|
9176
9340
|
const entry = req.resolve("@prisma/client");
|
|
9177
9341
|
const mod = await import(pathToFileURL3(entry).href);
|
|
9178
9342
|
const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
|
|
@@ -9251,7 +9415,7 @@ async function validateLicense(apiKey, deviceId) {
|
|
|
9251
9415
|
const pgResult = await validateViaPostgres(apiKey);
|
|
9252
9416
|
if (pgResult) {
|
|
9253
9417
|
try {
|
|
9254
|
-
|
|
9418
|
+
writeFileSync7(CACHE_PATH, JSON.stringify({ pgLicense: pgResult, ts: Date.now() }), "utf8");
|
|
9255
9419
|
} catch {
|
|
9256
9420
|
}
|
|
9257
9421
|
return pgResult;
|
|
@@ -9261,8 +9425,8 @@ async function validateLicense(apiKey, deviceId) {
|
|
|
9261
9425
|
const cached = await getCachedLicense();
|
|
9262
9426
|
if (cached) return cached;
|
|
9263
9427
|
try {
|
|
9264
|
-
if (
|
|
9265
|
-
const raw = JSON.parse(
|
|
9428
|
+
if (existsSync15(CACHE_PATH)) {
|
|
9429
|
+
const raw = JSON.parse(readFileSync11(CACHE_PATH, "utf8"));
|
|
9266
9430
|
if (raw.pgLicense && raw.ts && Date.now() - raw.ts < 7 * 24 * 60 * 60 * 1e3) {
|
|
9267
9431
|
return raw.pgLicense;
|
|
9268
9432
|
}
|
|
@@ -9275,8 +9439,8 @@ async function validateLicense(apiKey, deviceId) {
|
|
|
9275
9439
|
}
|
|
9276
9440
|
function getCacheAgeMs() {
|
|
9277
9441
|
try {
|
|
9278
|
-
const { statSync:
|
|
9279
|
-
const s =
|
|
9442
|
+
const { statSync: statSync11 } = __require("fs");
|
|
9443
|
+
const s = statSync11(CACHE_PATH);
|
|
9280
9444
|
return Date.now() - s.mtimeMs;
|
|
9281
9445
|
} catch {
|
|
9282
9446
|
return Infinity;
|
|
@@ -9286,9 +9450,9 @@ async function checkLicense() {
|
|
|
9286
9450
|
let key = loadLicense();
|
|
9287
9451
|
if (!key) {
|
|
9288
9452
|
try {
|
|
9289
|
-
const configPath =
|
|
9290
|
-
if (
|
|
9291
|
-
const raw = JSON.parse(
|
|
9453
|
+
const configPath = path17.join(EXE_AI_DIR, "config.json");
|
|
9454
|
+
if (existsSync15(configPath)) {
|
|
9455
|
+
const raw = JSON.parse(readFileSync11(configPath, "utf8"));
|
|
9292
9456
|
const cloud = raw.cloud;
|
|
9293
9457
|
if (cloud?.apiKey) {
|
|
9294
9458
|
key = cloud.apiKey;
|
|
@@ -9319,9 +9483,9 @@ var init_license = __esm({
|
|
|
9319
9483
|
"src/lib/license.ts"() {
|
|
9320
9484
|
"use strict";
|
|
9321
9485
|
init_config();
|
|
9322
|
-
LICENSE_PATH =
|
|
9323
|
-
CACHE_PATH =
|
|
9324
|
-
DEVICE_ID_PATH =
|
|
9486
|
+
LICENSE_PATH = path17.join(EXE_AI_DIR, "license.key");
|
|
9487
|
+
CACHE_PATH = path17.join(EXE_AI_DIR, "license-cache.json");
|
|
9488
|
+
DEVICE_ID_PATH = path17.join(EXE_AI_DIR, "device-id");
|
|
9325
9489
|
API_BASE = "https://askexe.com/cloud";
|
|
9326
9490
|
RETRY_DELAY_MS = 500;
|
|
9327
9491
|
LICENSE_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----
|
|
@@ -9362,12 +9526,12 @@ __export(plan_limits_exports, {
|
|
|
9362
9526
|
countActiveMemories: () => countActiveMemories,
|
|
9363
9527
|
getLicenseSync: () => getLicenseSync
|
|
9364
9528
|
});
|
|
9365
|
-
import { readFileSync as
|
|
9366
|
-
import
|
|
9529
|
+
import { readFileSync as readFileSync12, existsSync as existsSync16 } from "fs";
|
|
9530
|
+
import path18 from "path";
|
|
9367
9531
|
function getLicenseSync() {
|
|
9368
9532
|
try {
|
|
9369
|
-
if (!
|
|
9370
|
-
const raw = JSON.parse(
|
|
9533
|
+
if (!existsSync16(CACHE_PATH2)) return freeLicense();
|
|
9534
|
+
const raw = JSON.parse(readFileSync12(CACHE_PATH2, "utf8"));
|
|
9371
9535
|
if (!raw.token || typeof raw.token !== "string") return freeLicense();
|
|
9372
9536
|
const parts = raw.token.split(".");
|
|
9373
9537
|
if (parts.length !== 3) return freeLicense();
|
|
@@ -9434,8 +9598,8 @@ function assertEmployeeLimitSync(rosterPath) {
|
|
|
9434
9598
|
const filePath = rosterPath ?? EMPLOYEES_PATH;
|
|
9435
9599
|
let count = 0;
|
|
9436
9600
|
try {
|
|
9437
|
-
if (
|
|
9438
|
-
const raw =
|
|
9601
|
+
if (existsSync16(filePath)) {
|
|
9602
|
+
const raw = readFileSync12(filePath, "utf8");
|
|
9439
9603
|
const employees = JSON.parse(raw);
|
|
9440
9604
|
count = Array.isArray(employees) ? employees.length : 0;
|
|
9441
9605
|
}
|
|
@@ -9472,15 +9636,15 @@ var init_plan_limits = __esm({
|
|
|
9472
9636
|
this.name = "PlanLimitError";
|
|
9473
9637
|
}
|
|
9474
9638
|
};
|
|
9475
|
-
CACHE_PATH2 =
|
|
9639
|
+
CACHE_PATH2 = path18.join(EXE_AI_DIR, "license-cache.json");
|
|
9476
9640
|
}
|
|
9477
9641
|
});
|
|
9478
9642
|
|
|
9479
9643
|
// src/mcp/tools/store-memory.ts
|
|
9480
9644
|
import { z as z3 } from "zod";
|
|
9481
9645
|
import crypto4 from "crypto";
|
|
9482
|
-
import { writeFileSync as
|
|
9483
|
-
import
|
|
9646
|
+
import { writeFileSync as writeFileSync8 } from "fs";
|
|
9647
|
+
import path19 from "path";
|
|
9484
9648
|
function registerStoreMemory(server) {
|
|
9485
9649
|
server.registerTool(
|
|
9486
9650
|
"store_memory",
|
|
@@ -9548,8 +9712,8 @@ function registerStoreMemory(server) {
|
|
|
9548
9712
|
if (needsBackfill) {
|
|
9549
9713
|
try {
|
|
9550
9714
|
const { EXE_AI_DIR: exeDir } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
9551
|
-
const flagPath =
|
|
9552
|
-
|
|
9715
|
+
const flagPath = path19.join(exeDir, "session-cache", "needs-backfill");
|
|
9716
|
+
writeFileSync8(flagPath, "1");
|
|
9553
9717
|
} catch {
|
|
9554
9718
|
}
|
|
9555
9719
|
}
|
|
@@ -9577,8 +9741,8 @@ var init_store_memory = __esm({
|
|
|
9577
9741
|
// src/mcp/tools/commit-memory.ts
|
|
9578
9742
|
import { z as z4 } from "zod";
|
|
9579
9743
|
import crypto5 from "crypto";
|
|
9580
|
-
import { writeFileSync as
|
|
9581
|
-
import
|
|
9744
|
+
import { writeFileSync as writeFileSync9 } from "fs";
|
|
9745
|
+
import path20 from "path";
|
|
9582
9746
|
function registerCommitMemory(server) {
|
|
9583
9747
|
server.registerTool(
|
|
9584
9748
|
"commit_to_long_term_memory",
|
|
@@ -9668,8 +9832,8 @@ function registerCommitMemory(server) {
|
|
|
9668
9832
|
if (needsBackfill) {
|
|
9669
9833
|
try {
|
|
9670
9834
|
const { EXE_AI_DIR: exeDir } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
9671
|
-
const flagPath =
|
|
9672
|
-
|
|
9835
|
+
const flagPath = path20.join(exeDir, "session-cache", "needs-backfill");
|
|
9836
|
+
writeFileSync9(flagPath, "1");
|
|
9673
9837
|
} catch {
|
|
9674
9838
|
}
|
|
9675
9839
|
}
|
|
@@ -9704,8 +9868,8 @@ __export(wiki_client_exports, {
|
|
|
9704
9868
|
listDocuments: () => listDocuments,
|
|
9705
9869
|
listWorkspaces: () => listWorkspaces
|
|
9706
9870
|
});
|
|
9707
|
-
async function wikiFetch(config2,
|
|
9708
|
-
const url = `${config2.baseUrl}/api/v1${
|
|
9871
|
+
async function wikiFetch(config2, path60, method = "GET", body) {
|
|
9872
|
+
const url = `${config2.baseUrl}/api/v1${path60}`;
|
|
9709
9873
|
const headers = {
|
|
9710
9874
|
Authorization: `Bearer ${config2.apiKey}`,
|
|
9711
9875
|
"Content-Type": "application/json"
|
|
@@ -9738,7 +9902,7 @@ async function wikiFetch(config2, path58, method = "GET", body) {
|
|
|
9738
9902
|
}
|
|
9739
9903
|
}
|
|
9740
9904
|
if (!response.ok) {
|
|
9741
|
-
throw new Error(`Wiki API ${method} ${
|
|
9905
|
+
throw new Error(`Wiki API ${method} ${path60}: ${response.status} ${response.statusText}`);
|
|
9742
9906
|
}
|
|
9743
9907
|
return response.json();
|
|
9744
9908
|
} finally {
|
|
@@ -11107,14 +11271,14 @@ __export(session_registry_exports, {
|
|
|
11107
11271
|
refreshSessionProject: () => refreshSessionProject,
|
|
11108
11272
|
registerSession: () => registerSession
|
|
11109
11273
|
});
|
|
11110
|
-
import { readFileSync as
|
|
11274
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync10, mkdirSync as mkdirSync6, existsSync as existsSync17 } from "fs";
|
|
11111
11275
|
import { execSync as execSync7 } from "child_process";
|
|
11112
|
-
import
|
|
11276
|
+
import path21 from "path";
|
|
11113
11277
|
import os8 from "os";
|
|
11114
11278
|
function registerSession(entry) {
|
|
11115
|
-
const dir =
|
|
11116
|
-
if (!
|
|
11117
|
-
|
|
11279
|
+
const dir = path21.dirname(REGISTRY_PATH);
|
|
11280
|
+
if (!existsSync17(dir)) {
|
|
11281
|
+
mkdirSync6(dir, { recursive: true });
|
|
11118
11282
|
}
|
|
11119
11283
|
const sessions = listSessions();
|
|
11120
11284
|
const idx = sessions.findIndex((s) => s.windowName === entry.windowName);
|
|
@@ -11123,7 +11287,7 @@ function registerSession(entry) {
|
|
|
11123
11287
|
} else {
|
|
11124
11288
|
sessions.push(entry);
|
|
11125
11289
|
}
|
|
11126
|
-
|
|
11290
|
+
writeFileSync10(REGISTRY_PATH, JSON.stringify(sessions, null, 2));
|
|
11127
11291
|
}
|
|
11128
11292
|
function refreshSessionProject(windowName, projectDir) {
|
|
11129
11293
|
const sessions = listSessions();
|
|
@@ -11131,13 +11295,13 @@ function refreshSessionProject(windowName, projectDir) {
|
|
|
11131
11295
|
if (!entry || entry.projectDir === projectDir) return;
|
|
11132
11296
|
entry.projectDir = projectDir;
|
|
11133
11297
|
try {
|
|
11134
|
-
|
|
11298
|
+
writeFileSync10(REGISTRY_PATH, JSON.stringify(sessions, null, 2));
|
|
11135
11299
|
} catch {
|
|
11136
11300
|
}
|
|
11137
11301
|
}
|
|
11138
11302
|
function listSessions() {
|
|
11139
11303
|
try {
|
|
11140
|
-
const raw =
|
|
11304
|
+
const raw = readFileSync13(REGISTRY_PATH, "utf8");
|
|
11141
11305
|
return JSON.parse(raw);
|
|
11142
11306
|
} catch {
|
|
11143
11307
|
return [];
|
|
@@ -11158,7 +11322,7 @@ function pruneStaleSessions() {
|
|
|
11158
11322
|
const alive = sessions.filter((s) => liveSet.has(s.windowName));
|
|
11159
11323
|
const pruned = sessions.length - alive.length;
|
|
11160
11324
|
if (pruned > 0) {
|
|
11161
|
-
|
|
11325
|
+
writeFileSync10(REGISTRY_PATH, JSON.stringify(alive, null, 2));
|
|
11162
11326
|
}
|
|
11163
11327
|
return pruned;
|
|
11164
11328
|
}
|
|
@@ -11166,7 +11330,7 @@ var REGISTRY_PATH;
|
|
|
11166
11330
|
var init_session_registry = __esm({
|
|
11167
11331
|
"src/lib/session-registry.ts"() {
|
|
11168
11332
|
"use strict";
|
|
11169
|
-
REGISTRY_PATH =
|
|
11333
|
+
REGISTRY_PATH = path21.join(os8.homedir(), ".exe-os", "session-registry.json");
|
|
11170
11334
|
}
|
|
11171
11335
|
});
|
|
11172
11336
|
|
|
@@ -11377,17 +11541,17 @@ __export(intercom_queue_exports, {
|
|
|
11377
11541
|
queueIntercom: () => queueIntercom,
|
|
11378
11542
|
readQueue: () => readQueue
|
|
11379
11543
|
});
|
|
11380
|
-
import { readFileSync as
|
|
11381
|
-
import
|
|
11544
|
+
import { readFileSync as readFileSync14, writeFileSync as writeFileSync11, renameSync as renameSync5, existsSync as existsSync18, mkdirSync as mkdirSync7 } from "fs";
|
|
11545
|
+
import path22 from "path";
|
|
11382
11546
|
import os9 from "os";
|
|
11383
11547
|
function ensureDir() {
|
|
11384
|
-
const dir =
|
|
11385
|
-
if (!
|
|
11548
|
+
const dir = path22.dirname(QUEUE_PATH2);
|
|
11549
|
+
if (!existsSync18(dir)) mkdirSync7(dir, { recursive: true });
|
|
11386
11550
|
}
|
|
11387
11551
|
function readQueue() {
|
|
11388
11552
|
try {
|
|
11389
|
-
if (!
|
|
11390
|
-
return JSON.parse(
|
|
11553
|
+
if (!existsSync18(QUEUE_PATH2)) return [];
|
|
11554
|
+
return JSON.parse(readFileSync14(QUEUE_PATH2, "utf8"));
|
|
11391
11555
|
} catch {
|
|
11392
11556
|
return [];
|
|
11393
11557
|
}
|
|
@@ -11395,7 +11559,7 @@ function readQueue() {
|
|
|
11395
11559
|
function writeQueue(queue) {
|
|
11396
11560
|
ensureDir();
|
|
11397
11561
|
const tmp = `${QUEUE_PATH2}.tmp`;
|
|
11398
|
-
|
|
11562
|
+
writeFileSync11(tmp, JSON.stringify(queue, null, 2));
|
|
11399
11563
|
renameSync5(tmp, QUEUE_PATH2);
|
|
11400
11564
|
}
|
|
11401
11565
|
function queueIntercom(targetSession, reason) {
|
|
@@ -11487,37 +11651,37 @@ var QUEUE_PATH2, MAX_RETRIES2, TTL_MS2, INTERCOM_LOG;
|
|
|
11487
11651
|
var init_intercom_queue = __esm({
|
|
11488
11652
|
"src/lib/intercom-queue.ts"() {
|
|
11489
11653
|
"use strict";
|
|
11490
|
-
QUEUE_PATH2 =
|
|
11654
|
+
QUEUE_PATH2 = path22.join(os9.homedir(), ".exe-os", "intercom-queue.json");
|
|
11491
11655
|
MAX_RETRIES2 = 5;
|
|
11492
11656
|
TTL_MS2 = 60 * 60 * 1e3;
|
|
11493
|
-
INTERCOM_LOG =
|
|
11657
|
+
INTERCOM_LOG = path22.join(os9.homedir(), ".exe-os", "intercom.log");
|
|
11494
11658
|
}
|
|
11495
11659
|
});
|
|
11496
11660
|
|
|
11497
11661
|
// src/lib/agent-symlinks.ts
|
|
11498
11662
|
import os10 from "os";
|
|
11499
|
-
import
|
|
11663
|
+
import path23 from "path";
|
|
11500
11664
|
import {
|
|
11501
|
-
existsSync as
|
|
11665
|
+
existsSync as existsSync19,
|
|
11502
11666
|
lstatSync,
|
|
11503
|
-
mkdirSync as
|
|
11667
|
+
mkdirSync as mkdirSync8,
|
|
11504
11668
|
readlinkSync as readlinkSync2,
|
|
11505
11669
|
symlinkSync as symlinkSync2
|
|
11506
11670
|
} from "fs";
|
|
11507
11671
|
function claudeAgentsDir(homeDir) {
|
|
11508
|
-
return
|
|
11672
|
+
return path23.join(homeDir, ".claude", "agents");
|
|
11509
11673
|
}
|
|
11510
11674
|
function identitySourcePath(homeDir, agentId) {
|
|
11511
|
-
return
|
|
11675
|
+
return path23.join(homeDir, ".exe-os", "identity", `${agentId}.md`);
|
|
11512
11676
|
}
|
|
11513
11677
|
function claudeAgentLinkPath(homeDir, agentId) {
|
|
11514
|
-
return
|
|
11678
|
+
return path23.join(claudeAgentsDir(homeDir), `${agentId}.md`);
|
|
11515
11679
|
}
|
|
11516
11680
|
function ensureAgentSymlink(agentId, homeDir = os10.homedir()) {
|
|
11517
11681
|
const target = identitySourcePath(homeDir, agentId);
|
|
11518
11682
|
const link = claudeAgentLinkPath(homeDir, agentId);
|
|
11519
|
-
|
|
11520
|
-
if (
|
|
11683
|
+
mkdirSync8(claudeAgentsDir(homeDir), { recursive: true });
|
|
11684
|
+
if (existsSync19(link)) {
|
|
11521
11685
|
let stat;
|
|
11522
11686
|
try {
|
|
11523
11687
|
stat = lstatSync(link);
|
|
@@ -11960,8 +12124,8 @@ __export(tasks_review_exports, {
|
|
|
11960
12124
|
isStale: () => isStale,
|
|
11961
12125
|
listPendingReviews: () => listPendingReviews
|
|
11962
12126
|
});
|
|
11963
|
-
import
|
|
11964
|
-
import { existsSync as
|
|
12127
|
+
import path24 from "path";
|
|
12128
|
+
import { existsSync as existsSync20, readdirSync as readdirSync4, unlinkSync as unlinkSync5 } from "fs";
|
|
11965
12129
|
function formatAge(isoTimestamp) {
|
|
11966
12130
|
if (!isoTimestamp) return "";
|
|
11967
12131
|
const ms = Date.now() - new Date(isoTimestamp).getTime();
|
|
@@ -12230,11 +12394,11 @@ async function cleanupReviewFile(row, taskFile, _baseDir) {
|
|
|
12230
12394
|
);
|
|
12231
12395
|
}
|
|
12232
12396
|
try {
|
|
12233
|
-
const cacheDir =
|
|
12234
|
-
if (
|
|
12397
|
+
const cacheDir = path24.join(EXE_AI_DIR, "session-cache");
|
|
12398
|
+
if (existsSync20(cacheDir)) {
|
|
12235
12399
|
for (const f of readdirSync4(cacheDir)) {
|
|
12236
12400
|
if (f.startsWith("review-notified-")) {
|
|
12237
|
-
unlinkSync5(
|
|
12401
|
+
unlinkSync5(path24.join(cacheDir, f));
|
|
12238
12402
|
}
|
|
12239
12403
|
}
|
|
12240
12404
|
}
|
|
@@ -12281,13 +12445,13 @@ __export(tmux_routing_exports, {
|
|
|
12281
12445
|
verifyPaneAtCapacity: () => verifyPaneAtCapacity
|
|
12282
12446
|
});
|
|
12283
12447
|
import { execFileSync as execFileSync2, execSync as execSync9 } from "child_process";
|
|
12284
|
-
import { readFileSync as
|
|
12285
|
-
import
|
|
12448
|
+
import { readFileSync as readFileSync15, writeFileSync as writeFileSync12, mkdirSync as mkdirSync9, existsSync as existsSync21, appendFileSync as appendFileSync3, readdirSync as readdirSync5 } from "fs";
|
|
12449
|
+
import path25 from "path";
|
|
12286
12450
|
import os11 from "os";
|
|
12287
|
-
import { fileURLToPath as
|
|
12451
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
12288
12452
|
import { unlinkSync as unlinkSync6 } from "fs";
|
|
12289
12453
|
function spawnLockPath(sessionName) {
|
|
12290
|
-
return
|
|
12454
|
+
return path25.join(SPAWN_LOCK_DIR, `${sessionName}.lock`);
|
|
12291
12455
|
}
|
|
12292
12456
|
function isProcessAlive(pid) {
|
|
12293
12457
|
try {
|
|
@@ -12298,13 +12462,13 @@ function isProcessAlive(pid) {
|
|
|
12298
12462
|
}
|
|
12299
12463
|
}
|
|
12300
12464
|
function acquireSpawnLock2(sessionName) {
|
|
12301
|
-
if (!
|
|
12302
|
-
|
|
12465
|
+
if (!existsSync21(SPAWN_LOCK_DIR)) {
|
|
12466
|
+
mkdirSync9(SPAWN_LOCK_DIR, { recursive: true });
|
|
12303
12467
|
}
|
|
12304
12468
|
const lockFile = spawnLockPath(sessionName);
|
|
12305
|
-
if (
|
|
12469
|
+
if (existsSync21(lockFile)) {
|
|
12306
12470
|
try {
|
|
12307
|
-
const lock = JSON.parse(
|
|
12471
|
+
const lock = JSON.parse(readFileSync15(lockFile, "utf8"));
|
|
12308
12472
|
const age = Date.now() - lock.timestamp;
|
|
12309
12473
|
if (isProcessAlive(lock.pid) && age < 6e4) {
|
|
12310
12474
|
return false;
|
|
@@ -12312,7 +12476,7 @@ function acquireSpawnLock2(sessionName) {
|
|
|
12312
12476
|
} catch {
|
|
12313
12477
|
}
|
|
12314
12478
|
}
|
|
12315
|
-
|
|
12479
|
+
writeFileSync12(lockFile, JSON.stringify({ pid: process.pid, timestamp: Date.now() }));
|
|
12316
12480
|
return true;
|
|
12317
12481
|
}
|
|
12318
12482
|
function releaseSpawnLock2(sessionName) {
|
|
@@ -12323,14 +12487,14 @@ function releaseSpawnLock2(sessionName) {
|
|
|
12323
12487
|
}
|
|
12324
12488
|
function resolveBehaviorsExporterScript() {
|
|
12325
12489
|
try {
|
|
12326
|
-
const thisFile =
|
|
12327
|
-
const scriptPath =
|
|
12328
|
-
|
|
12490
|
+
const thisFile = fileURLToPath3(import.meta.url);
|
|
12491
|
+
const scriptPath = path25.join(
|
|
12492
|
+
path25.dirname(thisFile),
|
|
12329
12493
|
"..",
|
|
12330
12494
|
"bin",
|
|
12331
12495
|
"exe-export-behaviors.js"
|
|
12332
12496
|
);
|
|
12333
|
-
return
|
|
12497
|
+
return existsSync21(scriptPath) ? scriptPath : null;
|
|
12334
12498
|
} catch {
|
|
12335
12499
|
return null;
|
|
12336
12500
|
}
|
|
@@ -12396,12 +12560,12 @@ function extractRootExe(name) {
|
|
|
12396
12560
|
return parts.length > 0 ? parts[parts.length - 1] : null;
|
|
12397
12561
|
}
|
|
12398
12562
|
function registerParentExe(sessionKey, parentExe, dispatchedBy) {
|
|
12399
|
-
if (!
|
|
12400
|
-
|
|
12563
|
+
if (!existsSync21(SESSION_CACHE)) {
|
|
12564
|
+
mkdirSync9(SESSION_CACHE, { recursive: true });
|
|
12401
12565
|
}
|
|
12402
12566
|
const rootExe = extractRootExe(parentExe) ?? parentExe;
|
|
12403
|
-
const filePath =
|
|
12404
|
-
|
|
12567
|
+
const filePath = path25.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
|
|
12568
|
+
writeFileSync12(filePath, JSON.stringify({
|
|
12405
12569
|
parentExe: rootExe,
|
|
12406
12570
|
dispatchedBy: dispatchedBy || rootExe,
|
|
12407
12571
|
registeredAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -12409,7 +12573,7 @@ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
|
|
|
12409
12573
|
}
|
|
12410
12574
|
function getParentExe(sessionKey) {
|
|
12411
12575
|
try {
|
|
12412
|
-
const data = JSON.parse(
|
|
12576
|
+
const data = JSON.parse(readFileSync15(path25.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
|
|
12413
12577
|
return data.parentExe || null;
|
|
12414
12578
|
} catch {
|
|
12415
12579
|
return null;
|
|
@@ -12417,8 +12581,8 @@ function getParentExe(sessionKey) {
|
|
|
12417
12581
|
}
|
|
12418
12582
|
function getDispatchedBy(sessionKey) {
|
|
12419
12583
|
try {
|
|
12420
|
-
const data = JSON.parse(
|
|
12421
|
-
|
|
12584
|
+
const data = JSON.parse(readFileSync15(
|
|
12585
|
+
path25.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`),
|
|
12422
12586
|
"utf8"
|
|
12423
12587
|
));
|
|
12424
12588
|
return data.dispatchedBy ?? data.parentExe ?? null;
|
|
@@ -12488,8 +12652,8 @@ async function verifyPaneAtCapacity(sessionName) {
|
|
|
12488
12652
|
}
|
|
12489
12653
|
function readDebounceState() {
|
|
12490
12654
|
try {
|
|
12491
|
-
if (!
|
|
12492
|
-
const raw = JSON.parse(
|
|
12655
|
+
if (!existsSync21(DEBOUNCE_FILE)) return {};
|
|
12656
|
+
const raw = JSON.parse(readFileSync15(DEBOUNCE_FILE, "utf8"));
|
|
12493
12657
|
const state = {};
|
|
12494
12658
|
for (const [key, val] of Object.entries(raw)) {
|
|
12495
12659
|
if (typeof val === "number") {
|
|
@@ -12505,8 +12669,8 @@ function readDebounceState() {
|
|
|
12505
12669
|
}
|
|
12506
12670
|
function writeDebounceState(state) {
|
|
12507
12671
|
try {
|
|
12508
|
-
if (!
|
|
12509
|
-
|
|
12672
|
+
if (!existsSync21(SESSION_CACHE)) mkdirSync9(SESSION_CACHE, { recursive: true });
|
|
12673
|
+
writeFileSync12(DEBOUNCE_FILE, JSON.stringify(state));
|
|
12510
12674
|
} catch {
|
|
12511
12675
|
}
|
|
12512
12676
|
}
|
|
@@ -12542,7 +12706,7 @@ function logIntercom(msg) {
|
|
|
12542
12706
|
process.stderr.write(`[intercom] ${msg}
|
|
12543
12707
|
`);
|
|
12544
12708
|
try {
|
|
12545
|
-
|
|
12709
|
+
appendFileSync3(INTERCOM_LOG2, line);
|
|
12546
12710
|
} catch {
|
|
12547
12711
|
}
|
|
12548
12712
|
}
|
|
@@ -12605,8 +12769,8 @@ function sendIntercom(targetSession) {
|
|
|
12605
12769
|
try {
|
|
12606
12770
|
const rawAgent = targetSession.split("-")[0] ?? targetSession;
|
|
12607
12771
|
const agent = baseAgentName(rawAgent);
|
|
12608
|
-
const markerPath =
|
|
12609
|
-
if (
|
|
12772
|
+
const markerPath = path25.join(SESSION_CACHE, `current-task-${agent}.json`);
|
|
12773
|
+
if (existsSync21(markerPath)) {
|
|
12610
12774
|
logIntercom(`SKIP \u2192 ${targetSession} (has in_progress task marker + not idle \u2014 will auto-chain)`);
|
|
12611
12775
|
return "debounced";
|
|
12612
12776
|
}
|
|
@@ -12616,8 +12780,8 @@ function sendIntercom(targetSession) {
|
|
|
12616
12780
|
try {
|
|
12617
12781
|
const rawAgent = targetSession.split("-")[0] ?? targetSession;
|
|
12618
12782
|
const agent = baseAgentName(rawAgent);
|
|
12619
|
-
const taskDir =
|
|
12620
|
-
if (
|
|
12783
|
+
const taskDir = path25.join(process.cwd(), "exe", agent);
|
|
12784
|
+
if (existsSync21(taskDir)) {
|
|
12621
12785
|
const files = readdirSync5(taskDir).filter(
|
|
12622
12786
|
(f) => f.endsWith(".md") && f !== "DONE.txt"
|
|
12623
12787
|
);
|
|
@@ -12776,26 +12940,26 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
12776
12940
|
const transport = getTransport();
|
|
12777
12941
|
const sessionName = employeeSessionName(employeeName, exeSession, opts?.instance);
|
|
12778
12942
|
const instanceLabel = opts?.instance != null && opts.instance > 0 ? `${employeeName}${opts.instance}` : employeeName;
|
|
12779
|
-
const logDir =
|
|
12780
|
-
const logFile =
|
|
12781
|
-
if (!
|
|
12782
|
-
|
|
12943
|
+
const logDir = path25.join(os11.homedir(), ".exe-os", "session-logs");
|
|
12944
|
+
const logFile = path25.join(logDir, `${instanceLabel}-${Date.now()}.log`);
|
|
12945
|
+
if (!existsSync21(logDir)) {
|
|
12946
|
+
mkdirSync9(logDir, { recursive: true });
|
|
12783
12947
|
}
|
|
12784
12948
|
transport.kill(sessionName);
|
|
12785
12949
|
let cleanupSuffix = "";
|
|
12786
12950
|
try {
|
|
12787
|
-
const thisFile =
|
|
12788
|
-
const cleanupScript =
|
|
12789
|
-
if (
|
|
12951
|
+
const thisFile = fileURLToPath3(import.meta.url);
|
|
12952
|
+
const cleanupScript = path25.join(path25.dirname(thisFile), "..", "bin", "exe-session-cleanup.js");
|
|
12953
|
+
if (existsSync21(cleanupScript)) {
|
|
12790
12954
|
cleanupSuffix = `; ${process.execPath} "${cleanupScript}" "${employeeName}" "${exeSession}"`;
|
|
12791
12955
|
}
|
|
12792
12956
|
} catch {
|
|
12793
12957
|
}
|
|
12794
12958
|
try {
|
|
12795
|
-
const claudeJsonPath =
|
|
12959
|
+
const claudeJsonPath = path25.join(os11.homedir(), ".claude.json");
|
|
12796
12960
|
let claudeJson = {};
|
|
12797
12961
|
try {
|
|
12798
|
-
claudeJson = JSON.parse(
|
|
12962
|
+
claudeJson = JSON.parse(readFileSync15(claudeJsonPath, "utf8"));
|
|
12799
12963
|
} catch {
|
|
12800
12964
|
}
|
|
12801
12965
|
if (!claudeJson.projects) claudeJson.projects = {};
|
|
@@ -12803,17 +12967,17 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
12803
12967
|
const trustDir = opts?.cwd ?? projectDir;
|
|
12804
12968
|
if (!projects[trustDir]) projects[trustDir] = {};
|
|
12805
12969
|
projects[trustDir].hasTrustDialogAccepted = true;
|
|
12806
|
-
|
|
12970
|
+
writeFileSync12(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
|
|
12807
12971
|
} catch {
|
|
12808
12972
|
}
|
|
12809
12973
|
try {
|
|
12810
|
-
const settingsDir =
|
|
12974
|
+
const settingsDir = path25.join(os11.homedir(), ".claude", "projects");
|
|
12811
12975
|
const normalizedKey = (opts?.cwd ?? projectDir).replace(/\//g, "-").replace(/^-/, "");
|
|
12812
|
-
const projSettingsDir =
|
|
12813
|
-
const settingsPath =
|
|
12976
|
+
const projSettingsDir = path25.join(settingsDir, normalizedKey);
|
|
12977
|
+
const settingsPath = path25.join(projSettingsDir, "settings.json");
|
|
12814
12978
|
let settings = {};
|
|
12815
12979
|
try {
|
|
12816
|
-
settings = JSON.parse(
|
|
12980
|
+
settings = JSON.parse(readFileSync15(settingsPath, "utf8"));
|
|
12817
12981
|
} catch {
|
|
12818
12982
|
}
|
|
12819
12983
|
const perms = settings.permissions ?? {};
|
|
@@ -12841,8 +13005,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
12841
13005
|
if (changed) {
|
|
12842
13006
|
perms.allow = allow;
|
|
12843
13007
|
settings.permissions = perms;
|
|
12844
|
-
|
|
12845
|
-
|
|
13008
|
+
mkdirSync9(projSettingsDir, { recursive: true });
|
|
13009
|
+
writeFileSync12(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
12846
13010
|
}
|
|
12847
13011
|
} catch {
|
|
12848
13012
|
}
|
|
@@ -12857,7 +13021,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
12857
13021
|
let behaviorsFlag = "";
|
|
12858
13022
|
let legacyFallbackWarned = false;
|
|
12859
13023
|
if (!useExeAgent && !useBinSymlink) {
|
|
12860
|
-
const identityPath2 =
|
|
13024
|
+
const identityPath2 = path25.join(
|
|
12861
13025
|
os11.homedir(),
|
|
12862
13026
|
".exe-os",
|
|
12863
13027
|
"identity",
|
|
@@ -12874,13 +13038,13 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
12874
13038
|
`
|
|
12875
13039
|
);
|
|
12876
13040
|
}
|
|
12877
|
-
} else if (
|
|
13041
|
+
} else if (existsSync21(identityPath2)) {
|
|
12878
13042
|
identityFlag = ` --append-system-prompt-file ${identityPath2}`;
|
|
12879
13043
|
legacyFallbackWarned = true;
|
|
12880
13044
|
}
|
|
12881
13045
|
const behaviorsFile = exportBehaviorsSync(
|
|
12882
13046
|
employeeName,
|
|
12883
|
-
|
|
13047
|
+
path25.basename(spawnCwd),
|
|
12884
13048
|
sessionName
|
|
12885
13049
|
);
|
|
12886
13050
|
if (behaviorsFile) {
|
|
@@ -12895,16 +13059,16 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
12895
13059
|
}
|
|
12896
13060
|
let sessionContextFlag = "";
|
|
12897
13061
|
try {
|
|
12898
|
-
const ctxDir =
|
|
12899
|
-
|
|
12900
|
-
const ctxFile =
|
|
13062
|
+
const ctxDir = path25.join(os11.homedir(), ".exe-os", "session-cache");
|
|
13063
|
+
mkdirSync9(ctxDir, { recursive: true });
|
|
13064
|
+
const ctxFile = path25.join(ctxDir, `session-context-${sessionName}.md`);
|
|
12901
13065
|
const ctxContent = [
|
|
12902
13066
|
`## Session Context`,
|
|
12903
13067
|
`You are running in tmux session: ${sessionName}.`,
|
|
12904
13068
|
`Your parent coordinator session is ${exeSession}.`,
|
|
12905
13069
|
`Your employees (if any) use the -${exeSession} suffix.`
|
|
12906
13070
|
].join("\n");
|
|
12907
|
-
|
|
13071
|
+
writeFileSync12(ctxFile, ctxContent);
|
|
12908
13072
|
sessionContextFlag = ` --append-system-prompt-file ${ctxFile}`;
|
|
12909
13073
|
} catch {
|
|
12910
13074
|
}
|
|
@@ -12987,8 +13151,8 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
12987
13151
|
transport.pipeLog(sessionName, logFile);
|
|
12988
13152
|
try {
|
|
12989
13153
|
const mySession = getMySession();
|
|
12990
|
-
const dispatchInfo =
|
|
12991
|
-
|
|
13154
|
+
const dispatchInfo = path25.join(SESSION_CACHE, `dispatch-info-${sessionName}.json`);
|
|
13155
|
+
writeFileSync12(dispatchInfo, JSON.stringify({
|
|
12992
13156
|
dispatchedBy: mySession,
|
|
12993
13157
|
rootExe: exeSession,
|
|
12994
13158
|
provider: useBinSymlink ? ccProvider : useExeAgent ? opts.provider : useCodex ? "openai" : useOpencode ? "opencode" : "anthropic",
|
|
@@ -13063,15 +13227,15 @@ var init_tmux_routing = __esm({
|
|
|
13063
13227
|
init_plan_limits();
|
|
13064
13228
|
init_employees();
|
|
13065
13229
|
init_agent_symlinks();
|
|
13066
|
-
SPAWN_LOCK_DIR =
|
|
13067
|
-
SESSION_CACHE =
|
|
13230
|
+
SPAWN_LOCK_DIR = path25.join(os11.homedir(), ".exe-os", "spawn-locks");
|
|
13231
|
+
SESSION_CACHE = path25.join(os11.homedir(), ".exe-os", "session-cache");
|
|
13068
13232
|
BEHAVIORS_EXPORT_TIMEOUT_MS = 1e4;
|
|
13069
13233
|
VALID_SESSION_NAME = /^[a-z]+\d*-[a-zA-Z0-9_]+$/;
|
|
13070
13234
|
VERIFY_PANE_LINES = 200;
|
|
13071
13235
|
INTERCOM_DEBOUNCE_MS = 3e4;
|
|
13072
13236
|
CODEX_DEBOUNCE_MS = 12e4;
|
|
13073
|
-
INTERCOM_LOG2 =
|
|
13074
|
-
DEBOUNCE_FILE =
|
|
13237
|
+
INTERCOM_LOG2 = path25.join(os11.homedir(), ".exe-os", "intercom.log");
|
|
13238
|
+
DEBOUNCE_FILE = path25.join(SESSION_CACHE, "intercom-debounce.json");
|
|
13075
13239
|
DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
|
|
13076
13240
|
BUSY_PATTERN = /[✻✽✶✳·].*…|Running…|• Working|• Ran |• Explored|• Called|esc to interrupt/;
|
|
13077
13241
|
}
|
|
@@ -13118,13 +13282,13 @@ var init_task_scope = __esm({
|
|
|
13118
13282
|
|
|
13119
13283
|
// src/lib/notifications.ts
|
|
13120
13284
|
import crypto7 from "crypto";
|
|
13121
|
-
import
|
|
13285
|
+
import path26 from "path";
|
|
13122
13286
|
import os12 from "os";
|
|
13123
13287
|
import {
|
|
13124
|
-
readFileSync as
|
|
13288
|
+
readFileSync as readFileSync16,
|
|
13125
13289
|
readdirSync as readdirSync6,
|
|
13126
13290
|
unlinkSync as unlinkSync7,
|
|
13127
|
-
existsSync as
|
|
13291
|
+
existsSync as existsSync22,
|
|
13128
13292
|
rmdirSync
|
|
13129
13293
|
} from "fs";
|
|
13130
13294
|
async function writeNotification(notification) {
|
|
@@ -13253,11 +13417,11 @@ __export(tasks_crud_exports, {
|
|
|
13253
13417
|
writeCheckpoint: () => writeCheckpoint
|
|
13254
13418
|
});
|
|
13255
13419
|
import crypto8 from "crypto";
|
|
13256
|
-
import
|
|
13420
|
+
import path27 from "path";
|
|
13257
13421
|
import os13 from "os";
|
|
13258
13422
|
import { execSync as execSync10 } from "child_process";
|
|
13259
13423
|
import { mkdir as mkdir4, writeFile as writeFile4, appendFile } from "fs/promises";
|
|
13260
|
-
import { existsSync as
|
|
13424
|
+
import { existsSync as existsSync23, readFileSync as readFileSync17 } from "fs";
|
|
13261
13425
|
async function writeCheckpoint(input) {
|
|
13262
13426
|
const client = getClient();
|
|
13263
13427
|
const row = await resolveTask(client, input.taskId);
|
|
@@ -13456,8 +13620,8 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
|
|
|
13456
13620
|
}
|
|
13457
13621
|
if (input.baseDir) {
|
|
13458
13622
|
try {
|
|
13459
|
-
await mkdir4(
|
|
13460
|
-
await mkdir4(
|
|
13623
|
+
await mkdir4(path27.join(input.baseDir, "exe", "output"), { recursive: true });
|
|
13624
|
+
await mkdir4(path27.join(input.baseDir, "exe", "research"), { recursive: true });
|
|
13461
13625
|
await ensureArchitectureDoc(input.baseDir, input.projectName);
|
|
13462
13626
|
await ensureGitignoreExe(input.baseDir);
|
|
13463
13627
|
} catch {
|
|
@@ -13493,10 +13657,10 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
|
|
|
13493
13657
|
});
|
|
13494
13658
|
if (input.baseDir) {
|
|
13495
13659
|
try {
|
|
13496
|
-
const EXE_OS_DIR =
|
|
13497
|
-
const mdPath =
|
|
13498
|
-
const mdDir =
|
|
13499
|
-
if (!
|
|
13660
|
+
const EXE_OS_DIR = path27.join(os13.homedir(), ".exe-os");
|
|
13661
|
+
const mdPath = path27.join(EXE_OS_DIR, taskFile);
|
|
13662
|
+
const mdDir = path27.dirname(mdPath);
|
|
13663
|
+
if (!existsSync23(mdDir)) await mkdir4(mdDir, { recursive: true });
|
|
13500
13664
|
const reviewer = input.reviewer ?? input.assignedBy;
|
|
13501
13665
|
const mdContent = `# ${input.title}
|
|
13502
13666
|
|
|
@@ -13796,9 +13960,9 @@ async function deleteTaskCore(taskId, _baseDir) {
|
|
|
13796
13960
|
return { taskFile, assignedTo, assignedBy, taskSlug };
|
|
13797
13961
|
}
|
|
13798
13962
|
async function ensureArchitectureDoc(baseDir, projectName) {
|
|
13799
|
-
const archPath =
|
|
13963
|
+
const archPath = path27.join(baseDir, "exe", "ARCHITECTURE.md");
|
|
13800
13964
|
try {
|
|
13801
|
-
if (
|
|
13965
|
+
if (existsSync23(archPath)) return;
|
|
13802
13966
|
const template = [
|
|
13803
13967
|
`# ${projectName} \u2014 System Architecture`,
|
|
13804
13968
|
"",
|
|
@@ -13831,10 +13995,10 @@ async function ensureArchitectureDoc(baseDir, projectName) {
|
|
|
13831
13995
|
}
|
|
13832
13996
|
}
|
|
13833
13997
|
async function ensureGitignoreExe(baseDir) {
|
|
13834
|
-
const gitignorePath =
|
|
13998
|
+
const gitignorePath = path27.join(baseDir, ".gitignore");
|
|
13835
13999
|
try {
|
|
13836
|
-
if (
|
|
13837
|
-
const content =
|
|
14000
|
+
if (existsSync23(gitignorePath)) {
|
|
14001
|
+
const content = readFileSync17(gitignorePath, "utf-8");
|
|
13838
14002
|
if (/^\/?exe\/?$/m.test(content)) return;
|
|
13839
14003
|
await appendFile(gitignorePath, "\n# Employee task assignments (private)\n/exe/\n");
|
|
13840
14004
|
} else {
|
|
@@ -13865,7 +14029,7 @@ var init_tasks_crud = __esm({
|
|
|
13865
14029
|
});
|
|
13866
14030
|
|
|
13867
14031
|
// src/lib/tasks-chain.ts
|
|
13868
|
-
import
|
|
14032
|
+
import path28 from "path";
|
|
13869
14033
|
import { readFile as readFile4, writeFile as writeFile5 } from "fs/promises";
|
|
13870
14034
|
async function cascadeUnblock(taskId, baseDir, now2) {
|
|
13871
14035
|
const client = getClient();
|
|
@@ -13882,7 +14046,7 @@ async function cascadeUnblock(taskId, baseDir, now2) {
|
|
|
13882
14046
|
});
|
|
13883
14047
|
for (const ur of unblockedRows.rows) {
|
|
13884
14048
|
try {
|
|
13885
|
-
const ubFile =
|
|
14049
|
+
const ubFile = path28.join(baseDir, String(ur.task_file));
|
|
13886
14050
|
let ubContent = await readFile4(ubFile, "utf-8");
|
|
13887
14051
|
ubContent = ubContent.replace(/\*\*Status:\*\* blocked/, "**Status:** open");
|
|
13888
14052
|
ubContent = ubContent.replace(/\n\*\*Blocked by:\*\*.*\n/, "\n");
|
|
@@ -14396,8 +14560,8 @@ __export(tasks_exports, {
|
|
|
14396
14560
|
updateTaskStatus: () => updateTaskStatus,
|
|
14397
14561
|
writeCheckpoint: () => writeCheckpoint
|
|
14398
14562
|
});
|
|
14399
|
-
import
|
|
14400
|
-
import { writeFileSync as
|
|
14563
|
+
import path29 from "path";
|
|
14564
|
+
import { writeFileSync as writeFileSync13, mkdirSync as mkdirSync10, unlinkSync as unlinkSync8 } from "fs";
|
|
14401
14565
|
async function createTask(input) {
|
|
14402
14566
|
const result2 = await createTaskCore(input);
|
|
14403
14567
|
if (!input.skipDispatch && result2.status !== "blocked" && !process.env.VITEST) {
|
|
@@ -14416,11 +14580,11 @@ async function updateTask(input) {
|
|
|
14416
14580
|
const { row, taskFile, now: now2, taskId } = await updateTaskStatus(input);
|
|
14417
14581
|
try {
|
|
14418
14582
|
const agent = String(row.assigned_to);
|
|
14419
|
-
const cacheDir =
|
|
14420
|
-
const cachePath =
|
|
14583
|
+
const cacheDir = path29.join(EXE_AI_DIR, "session-cache");
|
|
14584
|
+
const cachePath = path29.join(cacheDir, `current-task-${agent}.json`);
|
|
14421
14585
|
if (input.status === "in_progress") {
|
|
14422
|
-
|
|
14423
|
-
|
|
14586
|
+
mkdirSync10(cacheDir, { recursive: true });
|
|
14587
|
+
writeFileSync13(cachePath, JSON.stringify({ taskId, title: String(row.title) }));
|
|
14424
14588
|
} else if (input.status === "done" || input.status === "blocked" || input.status === "cancelled" || input.status === "closed") {
|
|
14425
14589
|
try {
|
|
14426
14590
|
unlinkSync8(cachePath);
|
|
@@ -14587,17 +14751,17 @@ __export(identity_exports, {
|
|
|
14587
14751
|
listIdentities: () => listIdentities,
|
|
14588
14752
|
updateIdentity: () => updateIdentity
|
|
14589
14753
|
});
|
|
14590
|
-
import { existsSync as
|
|
14754
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync11, readFileSync as readFileSync18, writeFileSync as writeFileSync14 } from "fs";
|
|
14591
14755
|
import { readdirSync as readdirSync7 } from "fs";
|
|
14592
|
-
import
|
|
14756
|
+
import path30 from "path";
|
|
14593
14757
|
import { createHash as createHash4 } from "crypto";
|
|
14594
14758
|
function ensureDir2() {
|
|
14595
|
-
if (!
|
|
14596
|
-
|
|
14759
|
+
if (!existsSync24(IDENTITY_DIR2)) {
|
|
14760
|
+
mkdirSync11(IDENTITY_DIR2, { recursive: true });
|
|
14597
14761
|
}
|
|
14598
14762
|
}
|
|
14599
14763
|
function identityPath(agentId) {
|
|
14600
|
-
return
|
|
14764
|
+
return path30.join(IDENTITY_DIR2, `${agentId}.md`);
|
|
14601
14765
|
}
|
|
14602
14766
|
function sanitizeIdentityBody(body) {
|
|
14603
14767
|
return body.replace(/<!--[\s\S]*?-->/g, "").trim();
|
|
@@ -14641,8 +14805,8 @@ function contentHash(content) {
|
|
|
14641
14805
|
}
|
|
14642
14806
|
function getIdentity(agentId) {
|
|
14643
14807
|
const filePath = identityPath(agentId);
|
|
14644
|
-
if (!
|
|
14645
|
-
const raw =
|
|
14808
|
+
if (!existsSync24(filePath)) return null;
|
|
14809
|
+
const raw = readFileSync18(filePath, "utf-8");
|
|
14646
14810
|
const { frontmatter, body } = parseFrontmatter(raw);
|
|
14647
14811
|
return {
|
|
14648
14812
|
agentId,
|
|
@@ -14656,7 +14820,7 @@ async function updateIdentity(agentId, content, updatedBy) {
|
|
|
14656
14820
|
ensureDir2();
|
|
14657
14821
|
const filePath = identityPath(agentId);
|
|
14658
14822
|
const hash = contentHash(content);
|
|
14659
|
-
|
|
14823
|
+
writeFileSync14(filePath, content, "utf-8");
|
|
14660
14824
|
try {
|
|
14661
14825
|
const client = getClient();
|
|
14662
14826
|
await client.execute({
|
|
@@ -14714,7 +14878,7 @@ var init_identity = __esm({
|
|
|
14714
14878
|
"use strict";
|
|
14715
14879
|
init_config();
|
|
14716
14880
|
init_database();
|
|
14717
|
-
IDENTITY_DIR2 =
|
|
14881
|
+
IDENTITY_DIR2 = path30.join(EXE_AI_DIR, "identity");
|
|
14718
14882
|
}
|
|
14719
14883
|
});
|
|
14720
14884
|
|
|
@@ -15316,10 +15480,10 @@ function registerCreateTask(server) {
|
|
|
15316
15480
|
skipDispatch: true
|
|
15317
15481
|
});
|
|
15318
15482
|
try {
|
|
15319
|
-
const { existsSync:
|
|
15483
|
+
const { existsSync: existsSync47, mkdirSync: mkdirSync25, writeFileSync: writeFileSync29 } = await import("fs");
|
|
15320
15484
|
const { identityPath: identityPath2 } = await Promise.resolve().then(() => (init_identity(), identity_exports));
|
|
15321
15485
|
const idPath = identityPath2(assigned_to);
|
|
15322
|
-
if (!
|
|
15486
|
+
if (!existsSync47(idPath)) {
|
|
15323
15487
|
const { loadEmployees: loadEmployees2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
|
|
15324
15488
|
const employees = await loadEmployees2();
|
|
15325
15489
|
const emp = employees.find((e) => e.name === assigned_to);
|
|
@@ -15328,8 +15492,8 @@ function registerCreateTask(server) {
|
|
|
15328
15492
|
const template = getTemplateForTitle2(emp.role);
|
|
15329
15493
|
if (template) {
|
|
15330
15494
|
const dir = (await import("path")).dirname(idPath);
|
|
15331
|
-
if (!
|
|
15332
|
-
|
|
15495
|
+
if (!existsSync47(dir)) mkdirSync25(dir, { recursive: true });
|
|
15496
|
+
writeFileSync29(idPath, template.replace(/^agent_id: \w+/m, `agent_id: ${assigned_to}`), "utf-8");
|
|
15333
15497
|
}
|
|
15334
15498
|
}
|
|
15335
15499
|
}
|
|
@@ -17632,13 +17796,13 @@ var init_document = __esm({
|
|
|
17632
17796
|
});
|
|
17633
17797
|
|
|
17634
17798
|
// src/gateway/whatsapp-accounts.ts
|
|
17635
|
-
import { readFileSync as
|
|
17799
|
+
import { readFileSync as readFileSync19 } from "fs";
|
|
17636
17800
|
import { join } from "path";
|
|
17637
17801
|
import { homedir } from "os";
|
|
17638
17802
|
function loadAccounts() {
|
|
17639
17803
|
if (cachedAccounts !== null) return cachedAccounts;
|
|
17640
17804
|
try {
|
|
17641
|
-
const raw =
|
|
17805
|
+
const raw = readFileSync19(CONFIG_PATH2, "utf8");
|
|
17642
17806
|
const parsed = JSON.parse(raw);
|
|
17643
17807
|
if (!Array.isArray(parsed)) {
|
|
17644
17808
|
console.warn("[whatsapp] Config is not an array, ignoring");
|
|
@@ -17816,7 +17980,7 @@ var init_crm_bridge = __esm({
|
|
|
17816
17980
|
|
|
17817
17981
|
// src/mcp/tools/send-whatsapp.ts
|
|
17818
17982
|
import { z as z37 } from "zod";
|
|
17819
|
-
import { existsSync as
|
|
17983
|
+
import { existsSync as existsSync25, readFileSync as readFileSync20 } from "fs";
|
|
17820
17984
|
import { homedir as homedir2 } from "os";
|
|
17821
17985
|
import { join as join2 } from "path";
|
|
17822
17986
|
async function lookupPhoneByName(name) {
|
|
@@ -17871,9 +18035,9 @@ function normalizeGatewaySendUrl(value) {
|
|
|
17871
18035
|
}
|
|
17872
18036
|
function loadGatewayJson() {
|
|
17873
18037
|
const configPath = process.env.EXE_GATEWAY_CONFIG?.trim() || process.env.EXE_GATEWAY_CONFIG_PATH?.trim() || join2(homedir2(), ".exe-os", "gateway.json");
|
|
17874
|
-
if (!
|
|
18038
|
+
if (!existsSync25(configPath)) return {};
|
|
17875
18039
|
try {
|
|
17876
|
-
return JSON.parse(
|
|
18040
|
+
return JSON.parse(readFileSync20(configPath, "utf8"));
|
|
17877
18041
|
} catch {
|
|
17878
18042
|
return {};
|
|
17879
18043
|
}
|
|
@@ -18813,12 +18977,12 @@ function registerExportGraph(server) {
|
|
|
18813
18977
|
}
|
|
18814
18978
|
const html = await exportGraphHTML(client);
|
|
18815
18979
|
const fs = await import("fs");
|
|
18816
|
-
const
|
|
18980
|
+
const path60 = await import("path");
|
|
18817
18981
|
const os25 = await import("os");
|
|
18818
|
-
const outDir =
|
|
18982
|
+
const outDir = path60.join(os25.homedir(), ".exe-os", "exports");
|
|
18819
18983
|
fs.mkdirSync(outDir, { recursive: true });
|
|
18820
18984
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
18821
|
-
const filePath =
|
|
18985
|
+
const filePath = path60.join(outDir, `graph-${timestamp}.html`);
|
|
18822
18986
|
fs.writeFileSync(filePath, html, "utf-8");
|
|
18823
18987
|
return {
|
|
18824
18988
|
content: [
|
|
@@ -20056,7 +20220,7 @@ __export(token_spend_exports, {
|
|
|
20056
20220
|
import { readdir } from "fs/promises";
|
|
20057
20221
|
import { createReadStream } from "fs";
|
|
20058
20222
|
import { createInterface } from "readline";
|
|
20059
|
-
import
|
|
20223
|
+
import path31 from "path";
|
|
20060
20224
|
import os14 from "os";
|
|
20061
20225
|
function getPricing(model) {
|
|
20062
20226
|
if (MODEL_PRICING[model]) return MODEL_PRICING[model];
|
|
@@ -20084,18 +20248,18 @@ async function getAgentSpend(period = "7d") {
|
|
|
20084
20248
|
for (const row of dbResult.rows) {
|
|
20085
20249
|
sessionAgent.set(row.session_uuid, row.agent_id);
|
|
20086
20250
|
}
|
|
20087
|
-
const claudeDir =
|
|
20251
|
+
const claudeDir = path31.join(os14.homedir(), ".claude", "projects");
|
|
20088
20252
|
let projectDirs = [];
|
|
20089
20253
|
try {
|
|
20090
20254
|
const entries = await readdir(claudeDir);
|
|
20091
|
-
projectDirs = entries.map((e) =>
|
|
20255
|
+
projectDirs = entries.map((e) => path31.join(claudeDir, e));
|
|
20092
20256
|
} catch {
|
|
20093
20257
|
return [];
|
|
20094
20258
|
}
|
|
20095
20259
|
const agentTotals = /* @__PURE__ */ new Map();
|
|
20096
20260
|
for (const [sessionUuid, agentId] of sessionAgent) {
|
|
20097
20261
|
for (const dir of projectDirs) {
|
|
20098
|
-
const jsonlPath =
|
|
20262
|
+
const jsonlPath = path31.join(dir, `${sessionUuid}.jsonl`);
|
|
20099
20263
|
try {
|
|
20100
20264
|
const usage = await extractSessionUsage(jsonlPath);
|
|
20101
20265
|
if (usage.input === 0 && usage.output === 0) continue;
|
|
@@ -20421,8 +20585,8 @@ var init_get_session_kills = __esm({
|
|
|
20421
20585
|
|
|
20422
20586
|
// src/mcp/tools/get-daemon-health.ts
|
|
20423
20587
|
import { z as z53 } from "zod";
|
|
20424
|
-
import { existsSync as
|
|
20425
|
-
import
|
|
20588
|
+
import { existsSync as existsSync26, readFileSync as readFileSync21 } from "fs";
|
|
20589
|
+
import path32 from "path";
|
|
20426
20590
|
import { homedir as homedir3 } from "os";
|
|
20427
20591
|
function formatUptime(seconds) {
|
|
20428
20592
|
const h = Math.floor(seconds / 3600);
|
|
@@ -20434,8 +20598,8 @@ function formatUptime(seconds) {
|
|
|
20434
20598
|
}
|
|
20435
20599
|
function isDaemonAlive() {
|
|
20436
20600
|
try {
|
|
20437
|
-
if (!
|
|
20438
|
-
const pid = parseInt(
|
|
20601
|
+
if (!existsSync26(PID_PATH2)) return { alive: false, pid: null };
|
|
20602
|
+
const pid = parseInt(readFileSync21(PID_PATH2, "utf8").trim(), 10);
|
|
20439
20603
|
if (isNaN(pid) || pid <= 0) return { alive: false, pid: null };
|
|
20440
20604
|
process.kill(pid, 0);
|
|
20441
20605
|
return { alive: true, pid };
|
|
@@ -20482,6 +20646,27 @@ function registerGetDaemonHealth(server) {
|
|
|
20482
20646
|
lines.push(`| Uptime | ${formatUptime(health.uptime)} |`);
|
|
20483
20647
|
lines.push(`| Requests served | ${health.requests_served.toLocaleString()} |`);
|
|
20484
20648
|
}
|
|
20649
|
+
const events = readMcpHttpEvents(50);
|
|
20650
|
+
const summary = summarizeMcpTransport(events);
|
|
20651
|
+
const lastEvent = events.at(-1);
|
|
20652
|
+
lines.push(`| MCP HTTP events | ${events.length > 0 ? `${events.length} recent` : "none recorded"} |`);
|
|
20653
|
+
lines.push(`| MCP HTTP active sessions | ${summary.activeSessions ?? "unknown"} |`);
|
|
20654
|
+
lines.push(`| Last MCP handshake | ${summary.lastSuccessfulHandshake ?? "none"} |`);
|
|
20655
|
+
lines.push(`| Last MCP tool call | ${summary.lastSuccessfulToolCall ?? "none"} |`);
|
|
20656
|
+
lines.push(`| MCP monitor summary | ${summary.eventLogPath.replace("mcp-http-events.jsonl", "monitor/mcp-transport-summary.json")} |`);
|
|
20657
|
+
if (lastEvent) {
|
|
20658
|
+
lines.push(`| Last MCP HTTP event | ${lastEvent.timestamp ?? "unknown"} ${lastEvent.message ?? "unknown"} |`);
|
|
20659
|
+
}
|
|
20660
|
+
if (summary.recentWarnings.length > 0) {
|
|
20661
|
+
lines.push("\n### Recent MCP HTTP warnings");
|
|
20662
|
+
for (const event of summary.recentWarnings.slice(-5)) {
|
|
20663
|
+
lines.push(
|
|
20664
|
+
`- ${event.timestamp ?? "unknown"} \u2014 ${event.message ?? "unknown"} (agent=${event.agentId ?? "unknown"}, session=${event.sessionId ?? "none"})`
|
|
20665
|
+
);
|
|
20666
|
+
}
|
|
20667
|
+
}
|
|
20668
|
+
lines.push("\n### Agent remediation");
|
|
20669
|
+
for (const item of summary.remediation) lines.push(`- ${item}`);
|
|
20485
20670
|
return {
|
|
20486
20671
|
content: [{ type: "text", text: lines.join("\n") }]
|
|
20487
20672
|
};
|
|
@@ -20502,7 +20687,64 @@ var PID_PATH2;
|
|
|
20502
20687
|
var init_get_daemon_health = __esm({
|
|
20503
20688
|
"src/mcp/tools/get-daemon-health.ts"() {
|
|
20504
20689
|
"use strict";
|
|
20505
|
-
|
|
20690
|
+
init_mcp_transport_health();
|
|
20691
|
+
PID_PATH2 = path32.join(homedir3(), ".exe-os", "exed.pid");
|
|
20692
|
+
}
|
|
20693
|
+
});
|
|
20694
|
+
|
|
20695
|
+
// src/mcp/tools/mcp-ping.ts
|
|
20696
|
+
import { existsSync as existsSync27, readFileSync as readFileSync22 } from "fs";
|
|
20697
|
+
import path33 from "path";
|
|
20698
|
+
import { homedir as homedir4 } from "os";
|
|
20699
|
+
import { z as z54 } from "zod";
|
|
20700
|
+
function isDaemonAlive2() {
|
|
20701
|
+
try {
|
|
20702
|
+
if (!existsSync27(PID_PATH3)) return { alive: false, pid: null };
|
|
20703
|
+
const pid = parseInt(readFileSync22(PID_PATH3, "utf8").trim(), 10);
|
|
20704
|
+
if (!Number.isFinite(pid) || pid <= 0) return { alive: false, pid: null };
|
|
20705
|
+
process.kill(pid, 0);
|
|
20706
|
+
return { alive: true, pid };
|
|
20707
|
+
} catch {
|
|
20708
|
+
return { alive: false, pid: null };
|
|
20709
|
+
}
|
|
20710
|
+
}
|
|
20711
|
+
function registerMcpPing(server) {
|
|
20712
|
+
server.registerTool(
|
|
20713
|
+
"mcp_ping",
|
|
20714
|
+
{
|
|
20715
|
+
title: "MCP Ping",
|
|
20716
|
+
description: "Safe local MCP synthetic probe: daemon liveness plus privacy-safe transport/session summary.",
|
|
20717
|
+
inputSchema: {
|
|
20718
|
+
_placeholder: z54.string().optional().describe("No input required")
|
|
20719
|
+
}
|
|
20720
|
+
},
|
|
20721
|
+
async () => {
|
|
20722
|
+
const daemon = isDaemonAlive2();
|
|
20723
|
+
const summary = summarizeMcpTransport();
|
|
20724
|
+
writeMcpTransportSummary();
|
|
20725
|
+
const status = daemon.alive ? "ok" : "degraded";
|
|
20726
|
+
return {
|
|
20727
|
+
content: [
|
|
20728
|
+
{
|
|
20729
|
+
type: "text",
|
|
20730
|
+
text: JSON.stringify({
|
|
20731
|
+
status,
|
|
20732
|
+
daemon,
|
|
20733
|
+
mcpTransport: summary,
|
|
20734
|
+
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."
|
|
20735
|
+
}, null, 2)
|
|
20736
|
+
}
|
|
20737
|
+
]
|
|
20738
|
+
};
|
|
20739
|
+
}
|
|
20740
|
+
);
|
|
20741
|
+
}
|
|
20742
|
+
var PID_PATH3;
|
|
20743
|
+
var init_mcp_ping = __esm({
|
|
20744
|
+
"src/mcp/tools/mcp-ping.ts"() {
|
|
20745
|
+
"use strict";
|
|
20746
|
+
init_mcp_transport_health();
|
|
20747
|
+
PID_PATH3 = path33.join(homedir4(), ".exe-os", "exed.pid");
|
|
20506
20748
|
}
|
|
20507
20749
|
});
|
|
20508
20750
|
|
|
@@ -20784,9 +21026,9 @@ __export(agent_signals_exports, {
|
|
|
20784
21026
|
hasOpenTasks: () => hasOpenTasks,
|
|
20785
21027
|
hasUnreadInbox: () => hasUnreadInbox
|
|
20786
21028
|
});
|
|
20787
|
-
import { readFileSync as
|
|
21029
|
+
import { readFileSync as readFileSync23, existsSync as existsSync28 } from "fs";
|
|
20788
21030
|
import os15 from "os";
|
|
20789
|
-
import
|
|
21031
|
+
import path34 from "path";
|
|
20790
21032
|
async function hasOpenTasks(client, agentId) {
|
|
20791
21033
|
try {
|
|
20792
21034
|
const scope = sessionScopeFilter(null);
|
|
@@ -20828,10 +21070,10 @@ async function hasUnreadInbox(client, agentId) {
|
|
|
20828
21070
|
return CONSERVATIVE_ON_ERROR;
|
|
20829
21071
|
}
|
|
20830
21072
|
}
|
|
20831
|
-
function hadRecentIntercomAck(sessionName, windowMs, nowMs = Date.now(), intercomLog =
|
|
20832
|
-
if (!
|
|
21073
|
+
function hadRecentIntercomAck(sessionName, windowMs, nowMs = Date.now(), intercomLog = path34.join(os15.homedir(), ".exe-os", "intercom.log")) {
|
|
21074
|
+
if (!existsSync28(intercomLog)) return false;
|
|
20833
21075
|
try {
|
|
20834
|
-
const raw =
|
|
21076
|
+
const raw = readFileSync23(intercomLog, "utf8");
|
|
20835
21077
|
const lines = raw.split("\n");
|
|
20836
21078
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
20837
21079
|
const line = lines[i];
|
|
@@ -20904,8 +21146,8 @@ __export(daemon_orchestration_exports, {
|
|
|
20904
21146
|
shouldNudgeEmployee: () => shouldNudgeEmployee
|
|
20905
21147
|
});
|
|
20906
21148
|
import { execSync as execSync12 } from "child_process";
|
|
20907
|
-
import { existsSync as
|
|
20908
|
-
import { homedir as
|
|
21149
|
+
import { existsSync as existsSync29, readFileSync as readFileSync24, writeFileSync as writeFileSync15 } from "fs";
|
|
21150
|
+
import { homedir as homedir5 } from "os";
|
|
20909
21151
|
import { join as join3 } from "path";
|
|
20910
21152
|
function shouldNudgeEmployee(sessionState, hasOpenTasks2, lastNudgeMs, nowMs, dedupMs) {
|
|
20911
21153
|
if (sessionState !== "idle") return false;
|
|
@@ -21131,8 +21373,8 @@ async function pollReviewNudge(deps, state) {
|
|
|
21131
21373
|
function loadNudgeState() {
|
|
21132
21374
|
const state = { lastNudge: /* @__PURE__ */ new Map() };
|
|
21133
21375
|
try {
|
|
21134
|
-
if (!
|
|
21135
|
-
const raw = JSON.parse(
|
|
21376
|
+
if (!existsSync29(NUDGE_STATE_PATH)) return state;
|
|
21377
|
+
const raw = JSON.parse(readFileSync24(NUDGE_STATE_PATH, "utf8"));
|
|
21136
21378
|
if (Array.isArray(raw)) {
|
|
21137
21379
|
for (const [key, val] of raw) {
|
|
21138
21380
|
if (key && typeof val?.at === "number" && typeof val?.count === "number") {
|
|
@@ -21146,7 +21388,7 @@ function loadNudgeState() {
|
|
|
21146
21388
|
}
|
|
21147
21389
|
function saveNudgeState(state) {
|
|
21148
21390
|
const entries = Array.from(state.lastNudge.entries());
|
|
21149
|
-
|
|
21391
|
+
writeFileSync15(NUDGE_STATE_PATH, JSON.stringify(entries), "utf8");
|
|
21150
21392
|
}
|
|
21151
21393
|
function createReviewNudgeRealDeps(getClient2) {
|
|
21152
21394
|
return {
|
|
@@ -21480,7 +21722,7 @@ var init_daemon_orchestration = __esm({
|
|
|
21480
21722
|
SESSION_CONTEXT_THRESHOLD_PCT = Number(process.env.EXE_CONTEXT_KILL_PCT) || 50;
|
|
21481
21723
|
IDLE_KILL_INTERCOM_ACK_WINDOW_MS = Number(process.env.EXE_INTERCOM_ACK_WINDOW_MS) || 1e4;
|
|
21482
21724
|
REVIEW_NUDGE_COOLDOWN_MS = 3e5;
|
|
21483
|
-
NUDGE_STATE_PATH = join3(
|
|
21725
|
+
NUDGE_STATE_PATH = join3(homedir5(), ".exe-os", "review-nudge-state.json");
|
|
21484
21726
|
AUTO_WAKE_COOLDOWN_MS = 5 * 60 * 1e3;
|
|
21485
21727
|
AUTO_WAKE_MAX_RETRIES = 3;
|
|
21486
21728
|
_autoWakeLastSpawn = /* @__PURE__ */ new Map();
|
|
@@ -21496,7 +21738,7 @@ var init_daemon_orchestration = __esm({
|
|
|
21496
21738
|
});
|
|
21497
21739
|
|
|
21498
21740
|
// src/mcp/tools/get-auto-wake-status.ts
|
|
21499
|
-
import { z as
|
|
21741
|
+
import { z as z55 } from "zod";
|
|
21500
21742
|
function registerGetAutoWakeStatus(server) {
|
|
21501
21743
|
server.registerTool(
|
|
21502
21744
|
"get_auto_wake_status",
|
|
@@ -21504,7 +21746,7 @@ function registerGetAutoWakeStatus(server) {
|
|
|
21504
21746
|
title: "Get Auto-Wake Status",
|
|
21505
21747
|
description: "Check auto-wake status: orphaned tasks (assigned agent has no running session), tasks blocked by auto-wake retry limit, and session activity.",
|
|
21506
21748
|
inputSchema: {
|
|
21507
|
-
_placeholder:
|
|
21749
|
+
_placeholder: z55.string().optional().describe("No input required")
|
|
21508
21750
|
}
|
|
21509
21751
|
},
|
|
21510
21752
|
async () => {
|
|
@@ -21602,14 +21844,14 @@ __export(worker_gate_exports, {
|
|
|
21602
21844
|
tryAcquireBackfillLock: () => tryAcquireBackfillLock,
|
|
21603
21845
|
tryAcquireWorkerSlot: () => tryAcquireWorkerSlot
|
|
21604
21846
|
});
|
|
21605
|
-
import { readdirSync as readdirSync8, writeFileSync as
|
|
21606
|
-
import
|
|
21847
|
+
import { readdirSync as readdirSync8, writeFileSync as writeFileSync16, unlinkSync as unlinkSync9, mkdirSync as mkdirSync12, existsSync as existsSync30 } from "fs";
|
|
21848
|
+
import path35 from "path";
|
|
21607
21849
|
function tryAcquireWorkerSlot() {
|
|
21608
21850
|
try {
|
|
21609
|
-
|
|
21851
|
+
mkdirSync12(WORKER_PID_DIR, { recursive: true });
|
|
21610
21852
|
const reservationId = `res-${process.pid}-${Date.now()}`;
|
|
21611
|
-
const reservationPath =
|
|
21612
|
-
|
|
21853
|
+
const reservationPath = path35.join(WORKER_PID_DIR, `${reservationId}.pid`);
|
|
21854
|
+
writeFileSync16(reservationPath, String(process.pid));
|
|
21613
21855
|
const files = readdirSync8(WORKER_PID_DIR);
|
|
21614
21856
|
let alive = 0;
|
|
21615
21857
|
for (const f of files) {
|
|
@@ -21626,7 +21868,7 @@ function tryAcquireWorkerSlot() {
|
|
|
21626
21868
|
alive++;
|
|
21627
21869
|
} catch {
|
|
21628
21870
|
try {
|
|
21629
|
-
unlinkSync9(
|
|
21871
|
+
unlinkSync9(path35.join(WORKER_PID_DIR, f));
|
|
21630
21872
|
} catch {
|
|
21631
21873
|
}
|
|
21632
21874
|
}
|
|
@@ -21649,21 +21891,21 @@ function tryAcquireWorkerSlot() {
|
|
|
21649
21891
|
}
|
|
21650
21892
|
function registerWorkerPid(pid) {
|
|
21651
21893
|
try {
|
|
21652
|
-
|
|
21653
|
-
|
|
21894
|
+
mkdirSync12(WORKER_PID_DIR, { recursive: true });
|
|
21895
|
+
writeFileSync16(path35.join(WORKER_PID_DIR, `worker-${pid}.pid`), String(pid));
|
|
21654
21896
|
} catch {
|
|
21655
21897
|
}
|
|
21656
21898
|
}
|
|
21657
21899
|
function cleanupWorkerPid() {
|
|
21658
21900
|
try {
|
|
21659
|
-
unlinkSync9(
|
|
21901
|
+
unlinkSync9(path35.join(WORKER_PID_DIR, `worker-${process.pid}.pid`));
|
|
21660
21902
|
} catch {
|
|
21661
21903
|
}
|
|
21662
21904
|
}
|
|
21663
21905
|
function tryAcquireBackfillLock() {
|
|
21664
21906
|
try {
|
|
21665
|
-
|
|
21666
|
-
if (
|
|
21907
|
+
mkdirSync12(WORKER_PID_DIR, { recursive: true });
|
|
21908
|
+
if (existsSync30(BACKFILL_LOCK)) {
|
|
21667
21909
|
try {
|
|
21668
21910
|
const pid = parseInt(
|
|
21669
21911
|
__require("fs").readFileSync(BACKFILL_LOCK, "utf8").trim(),
|
|
@@ -21679,7 +21921,7 @@ function tryAcquireBackfillLock() {
|
|
|
21679
21921
|
} catch {
|
|
21680
21922
|
}
|
|
21681
21923
|
}
|
|
21682
|
-
|
|
21924
|
+
writeFileSync16(BACKFILL_LOCK, String(process.pid));
|
|
21683
21925
|
return true;
|
|
21684
21926
|
} catch {
|
|
21685
21927
|
return true;
|
|
@@ -21696,22 +21938,22 @@ var init_worker_gate = __esm({
|
|
|
21696
21938
|
"src/lib/worker-gate.ts"() {
|
|
21697
21939
|
"use strict";
|
|
21698
21940
|
init_config();
|
|
21699
|
-
WORKER_PID_DIR =
|
|
21941
|
+
WORKER_PID_DIR = path35.join(EXE_AI_DIR, "worker-pids");
|
|
21700
21942
|
MAX_CONCURRENT_WORKERS = 3;
|
|
21701
|
-
BACKFILL_LOCK =
|
|
21943
|
+
BACKFILL_LOCK = path35.join(WORKER_PID_DIR, "backfill.lock");
|
|
21702
21944
|
}
|
|
21703
21945
|
});
|
|
21704
21946
|
|
|
21705
21947
|
// src/mcp/tools/get-worker-gate.ts
|
|
21706
|
-
import { z as
|
|
21707
|
-
import { readdirSync as readdirSync9, existsSync as
|
|
21708
|
-
import
|
|
21948
|
+
import { z as z56 } from "zod";
|
|
21949
|
+
import { readdirSync as readdirSync9, existsSync as existsSync31 } from "fs";
|
|
21950
|
+
import path36 from "path";
|
|
21709
21951
|
function countAliveWorkers() {
|
|
21710
21952
|
let alive = 0;
|
|
21711
21953
|
let stale = 0;
|
|
21712
21954
|
let reservations = 0;
|
|
21713
21955
|
try {
|
|
21714
|
-
if (!
|
|
21956
|
+
if (!existsSync31(WORKER_PID_DIR2)) return { alive: 0, stale: 0, reservations: 0 };
|
|
21715
21957
|
const files = readdirSync9(WORKER_PID_DIR2);
|
|
21716
21958
|
for (const f of files) {
|
|
21717
21959
|
if (!f.endsWith(".pid")) continue;
|
|
@@ -21740,7 +21982,7 @@ function registerGetWorkerGate(server) {
|
|
|
21740
21982
|
title: "Get Worker Gate",
|
|
21741
21983
|
description: "Check worker concurrency gate status: how many worker slots are in use, the maximum allowed, and whether new workers can spawn.",
|
|
21742
21984
|
inputSchema: {
|
|
21743
|
-
_placeholder:
|
|
21985
|
+
_placeholder: z56.string().optional().describe("No input required")
|
|
21744
21986
|
}
|
|
21745
21987
|
},
|
|
21746
21988
|
async () => {
|
|
@@ -21779,19 +22021,19 @@ var init_get_worker_gate = __esm({
|
|
|
21779
22021
|
"use strict";
|
|
21780
22022
|
init_worker_gate();
|
|
21781
22023
|
init_config();
|
|
21782
|
-
WORKER_PID_DIR2 =
|
|
22024
|
+
WORKER_PID_DIR2 = path36.join(EXE_AI_DIR, "worker-pids");
|
|
21783
22025
|
}
|
|
21784
22026
|
});
|
|
21785
22027
|
|
|
21786
22028
|
// src/lib/is-main.ts
|
|
21787
22029
|
import { realpathSync } from "fs";
|
|
21788
|
-
import { fileURLToPath as
|
|
22030
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
21789
22031
|
function isMainModule(importMetaUrl) {
|
|
21790
22032
|
if (process.argv[1] == null) return false;
|
|
21791
22033
|
if (process.argv[1].includes("mcp/server")) return false;
|
|
21792
22034
|
try {
|
|
21793
22035
|
const scriptPath = realpathSync(process.argv[1]);
|
|
21794
|
-
const modulePath = realpathSync(
|
|
22036
|
+
const modulePath = realpathSync(fileURLToPath4(importMetaUrl));
|
|
21795
22037
|
return scriptPath === modulePath;
|
|
21796
22038
|
} catch {
|
|
21797
22039
|
return importMetaUrl === `file://${process.argv[1]}` || importMetaUrl === new URL(process.argv[1], "file://").href;
|
|
@@ -22216,16 +22458,16 @@ __export(key_backup_status_exports, {
|
|
|
22216
22458
|
keyBackupMarkerPath: () => keyBackupMarkerPath,
|
|
22217
22459
|
markKeyBackupConfirmed: () => markKeyBackupConfirmed
|
|
22218
22460
|
});
|
|
22219
|
-
import { existsSync as
|
|
22220
|
-
import
|
|
22461
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync13, readFileSync as readFileSync25, writeFileSync as writeFileSync17 } from "fs";
|
|
22462
|
+
import path37 from "path";
|
|
22221
22463
|
function keyBackupMarkerPath() {
|
|
22222
|
-
return
|
|
22464
|
+
return path37.join(EXE_AI_DIR, "key-backup-confirmed.json");
|
|
22223
22465
|
}
|
|
22224
22466
|
function getKeyBackupStatus() {
|
|
22225
22467
|
const marker = keyBackupMarkerPath();
|
|
22226
|
-
if (!
|
|
22468
|
+
if (!existsSync32(marker)) return { exists: false };
|
|
22227
22469
|
try {
|
|
22228
|
-
const parsed = JSON.parse(
|
|
22470
|
+
const parsed = JSON.parse(readFileSync25(marker, "utf8"));
|
|
22229
22471
|
return {
|
|
22230
22472
|
exists: true,
|
|
22231
22473
|
confirmedAt: parsed.confirmedAt,
|
|
@@ -22236,8 +22478,8 @@ function getKeyBackupStatus() {
|
|
|
22236
22478
|
}
|
|
22237
22479
|
}
|
|
22238
22480
|
function markKeyBackupConfirmed(source) {
|
|
22239
|
-
|
|
22240
|
-
|
|
22481
|
+
mkdirSync13(EXE_AI_DIR, { recursive: true, mode: 448 });
|
|
22482
|
+
writeFileSync17(
|
|
22241
22483
|
keyBackupMarkerPath(),
|
|
22242
22484
|
JSON.stringify({ confirmedAt: (/* @__PURE__ */ new Date()).toISOString(), source }, null, 2) + "\n",
|
|
22243
22485
|
{ mode: 384 }
|
|
@@ -22333,33 +22575,33 @@ __export(db_backup_exports, {
|
|
|
22333
22575
|
listBackups: () => listBackups,
|
|
22334
22576
|
rotateBackups: () => rotateBackups
|
|
22335
22577
|
});
|
|
22336
|
-
import { copyFileSync, existsSync as
|
|
22337
|
-
import
|
|
22578
|
+
import { copyFileSync, existsSync as existsSync33, mkdirSync as mkdirSync14, readdirSync as readdirSync10, unlinkSync as unlinkSync10, statSync as statSync7 } from "fs";
|
|
22579
|
+
import path38 from "path";
|
|
22338
22580
|
function findActiveDb() {
|
|
22339
22581
|
for (const name of DB_NAMES) {
|
|
22340
|
-
const p =
|
|
22341
|
-
if (
|
|
22582
|
+
const p = path38.join(EXE_AI_DIR, name);
|
|
22583
|
+
if (existsSync33(p)) return p;
|
|
22342
22584
|
}
|
|
22343
22585
|
return null;
|
|
22344
22586
|
}
|
|
22345
22587
|
function createBackup(reason = "manual") {
|
|
22346
22588
|
const dbPath = findActiveDb();
|
|
22347
22589
|
if (!dbPath) return null;
|
|
22348
|
-
|
|
22349
|
-
const dbName =
|
|
22590
|
+
mkdirSync14(BACKUP_DIR, { recursive: true });
|
|
22591
|
+
const dbName = path38.basename(dbPath, ".db");
|
|
22350
22592
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
22351
22593
|
const backupName = `${dbName}-${reason}-${timestamp}.db`;
|
|
22352
|
-
const backupPath =
|
|
22594
|
+
const backupPath = path38.join(BACKUP_DIR, backupName);
|
|
22353
22595
|
copyFileSync(dbPath, backupPath);
|
|
22354
22596
|
const walPath = dbPath + "-wal";
|
|
22355
|
-
if (
|
|
22597
|
+
if (existsSync33(walPath)) {
|
|
22356
22598
|
try {
|
|
22357
22599
|
copyFileSync(walPath, backupPath + "-wal");
|
|
22358
22600
|
} catch {
|
|
22359
22601
|
}
|
|
22360
22602
|
}
|
|
22361
22603
|
const shmPath = dbPath + "-shm";
|
|
22362
|
-
if (
|
|
22604
|
+
if (existsSync33(shmPath)) {
|
|
22363
22605
|
try {
|
|
22364
22606
|
copyFileSync(shmPath, backupPath + "-shm");
|
|
22365
22607
|
} catch {
|
|
@@ -22368,16 +22610,16 @@ function createBackup(reason = "manual") {
|
|
|
22368
22610
|
return backupPath;
|
|
22369
22611
|
}
|
|
22370
22612
|
function rotateBackups(keepDays = DEFAULT_KEEP_DAYS) {
|
|
22371
|
-
if (!
|
|
22613
|
+
if (!existsSync33(BACKUP_DIR)) return 0;
|
|
22372
22614
|
const cutoff = Date.now() - keepDays * 24 * 60 * 60 * 1e3;
|
|
22373
22615
|
let deleted = 0;
|
|
22374
22616
|
try {
|
|
22375
22617
|
const files = readdirSync10(BACKUP_DIR);
|
|
22376
22618
|
for (const file of files) {
|
|
22377
22619
|
if (!file.endsWith(".db") && !file.endsWith(".db-wal") && !file.endsWith(".db-shm")) continue;
|
|
22378
|
-
const filePath =
|
|
22620
|
+
const filePath = path38.join(BACKUP_DIR, file);
|
|
22379
22621
|
try {
|
|
22380
|
-
const stat =
|
|
22622
|
+
const stat = statSync7(filePath);
|
|
22381
22623
|
if (stat.mtimeMs < cutoff) {
|
|
22382
22624
|
unlinkSync10(filePath);
|
|
22383
22625
|
deleted++;
|
|
@@ -22390,12 +22632,12 @@ function rotateBackups(keepDays = DEFAULT_KEEP_DAYS) {
|
|
|
22390
22632
|
return deleted;
|
|
22391
22633
|
}
|
|
22392
22634
|
function listBackups() {
|
|
22393
|
-
if (!
|
|
22635
|
+
if (!existsSync33(BACKUP_DIR)) return [];
|
|
22394
22636
|
try {
|
|
22395
22637
|
const files = readdirSync10(BACKUP_DIR).filter((f) => f.endsWith(".db") && !f.endsWith("-wal") && !f.endsWith("-shm"));
|
|
22396
22638
|
return files.map((name) => {
|
|
22397
|
-
const p =
|
|
22398
|
-
const stat =
|
|
22639
|
+
const p = path38.join(BACKUP_DIR, name);
|
|
22640
|
+
const stat = statSync7(p);
|
|
22399
22641
|
return { path: p, name, size: stat.size, date: stat.mtime };
|
|
22400
22642
|
}).sort((a, b) => b.date.getTime() - a.date.getTime());
|
|
22401
22643
|
} catch {
|
|
@@ -22419,7 +22661,7 @@ var init_db_backup = __esm({
|
|
|
22419
22661
|
"src/lib/db-backup.ts"() {
|
|
22420
22662
|
"use strict";
|
|
22421
22663
|
init_config();
|
|
22422
|
-
BACKUP_DIR =
|
|
22664
|
+
BACKUP_DIR = path38.join(EXE_AI_DIR, "backups");
|
|
22423
22665
|
DEFAULT_KEEP_DAYS = 3;
|
|
22424
22666
|
DB_NAMES = ["memories.db", "exe-mem.db", "exe-os.db", "exe.db"];
|
|
22425
22667
|
}
|
|
@@ -22427,9 +22669,9 @@ var init_db_backup = __esm({
|
|
|
22427
22669
|
|
|
22428
22670
|
// src/bin/exe-doctor.ts
|
|
22429
22671
|
import os16 from "os";
|
|
22430
|
-
import { existsSync as
|
|
22672
|
+
import { existsSync as existsSync34, readFileSync as readFileSync26 } from "fs";
|
|
22431
22673
|
import { spawn as spawn2 } from "child_process";
|
|
22432
|
-
import
|
|
22674
|
+
import path39 from "path";
|
|
22433
22675
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
22434
22676
|
function parseFlags(argv) {
|
|
22435
22677
|
const flags = { fix: false, dryRun: false, verbose: false, conflicts: false };
|
|
@@ -22581,7 +22823,7 @@ async function auditOrphanedProjects(client) {
|
|
|
22581
22823
|
for (const row of result2.rows) {
|
|
22582
22824
|
const name = row.project_name;
|
|
22583
22825
|
const count = Number(row.cnt);
|
|
22584
|
-
const exists =
|
|
22826
|
+
const exists = existsSync34(path39.join(home, name)) || existsSync34(path39.join(home, "..", name)) || existsSync34(path39.join(process.cwd(), "..", name));
|
|
22585
22827
|
if (!exists) {
|
|
22586
22828
|
orphans.push({ project_name: name, count });
|
|
22587
22829
|
}
|
|
@@ -22589,18 +22831,18 @@ async function auditOrphanedProjects(client) {
|
|
|
22589
22831
|
return orphans;
|
|
22590
22832
|
}
|
|
22591
22833
|
function auditHookHealth() {
|
|
22592
|
-
const logPath =
|
|
22834
|
+
const logPath = path39.join(
|
|
22593
22835
|
process.env.HOME ?? process.env.USERPROFILE ?? "",
|
|
22594
22836
|
".exe-os",
|
|
22595
22837
|
"logs",
|
|
22596
22838
|
"hooks.log"
|
|
22597
22839
|
);
|
|
22598
|
-
if (!
|
|
22840
|
+
if (!existsSync34(logPath)) {
|
|
22599
22841
|
return { logExists: false, totalLines: 0, errorsLastHour: 0, topPatterns: [] };
|
|
22600
22842
|
}
|
|
22601
22843
|
let content;
|
|
22602
22844
|
try {
|
|
22603
|
-
content =
|
|
22845
|
+
content = readFileSync26(logPath, "utf-8");
|
|
22604
22846
|
} catch {
|
|
22605
22847
|
return { logExists: false, totalLines: 0, errorsLastHour: 0, topPatterns: [] };
|
|
22606
22848
|
}
|
|
@@ -22629,9 +22871,9 @@ function auditHookHealth() {
|
|
|
22629
22871
|
return { logExists: true, totalLines, errorsLastHour, topPatterns };
|
|
22630
22872
|
}
|
|
22631
22873
|
function safeReadJson(filePath) {
|
|
22632
|
-
if (!
|
|
22874
|
+
if (!existsSync34(filePath)) return null;
|
|
22633
22875
|
try {
|
|
22634
|
-
return JSON.parse(
|
|
22876
|
+
return JSON.parse(readFileSync26(filePath, "utf-8"));
|
|
22635
22877
|
} catch {
|
|
22636
22878
|
return null;
|
|
22637
22879
|
}
|
|
@@ -22725,13 +22967,13 @@ function auditHookOwnership() {
|
|
|
22725
22967
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
22726
22968
|
const checkedFiles = [];
|
|
22727
22969
|
const issues = [];
|
|
22728
|
-
const claudeSettingsPath =
|
|
22970
|
+
const claudeSettingsPath = path39.join(home, ".claude", "settings.json");
|
|
22729
22971
|
const claudeSettings = safeReadJson(claudeSettingsPath);
|
|
22730
22972
|
if (claudeSettings) {
|
|
22731
22973
|
checkedFiles.push(claudeSettingsPath);
|
|
22732
22974
|
issues.push(...buildHookOwnershipIssues("claude", collectHookCommandsFromClaudeSettings(claudeSettings)));
|
|
22733
22975
|
}
|
|
22734
|
-
const codexHooksPath =
|
|
22976
|
+
const codexHooksPath = path39.join(home, ".codex", "hooks.json");
|
|
22735
22977
|
const codexHooks = safeReadJson(codexHooksPath);
|
|
22736
22978
|
if (codexHooks) {
|
|
22737
22979
|
checkedFiles.push(codexHooksPath);
|
|
@@ -22995,7 +23237,7 @@ async function fixNullVectors() {
|
|
|
22995
23237
|
}
|
|
22996
23238
|
}
|
|
22997
23239
|
const npmRoot = (await import("child_process")).execSync("npm root -g", { encoding: "utf8" }).trim();
|
|
22998
|
-
const backfillPath =
|
|
23240
|
+
const backfillPath = path39.join(npmRoot, "exe-os", "dist", "bin", "backfill-vectors.js");
|
|
22999
23241
|
return new Promise((resolve, reject) => {
|
|
23000
23242
|
const child = spawn2("node", [backfillPath], { stdio: "inherit" });
|
|
23001
23243
|
if (child.pid) registerWorkerPid2(child.pid);
|
|
@@ -23181,7 +23423,7 @@ var init_exe_doctor = __esm({
|
|
|
23181
23423
|
});
|
|
23182
23424
|
|
|
23183
23425
|
// src/mcp/tools/run-memory-audit.ts
|
|
23184
|
-
import { z as
|
|
23426
|
+
import { z as z57 } from "zod";
|
|
23185
23427
|
function registerRunMemoryAudit(server) {
|
|
23186
23428
|
server.registerTool(
|
|
23187
23429
|
"run_memory_audit",
|
|
@@ -23189,8 +23431,8 @@ function registerRunMemoryAudit(server) {
|
|
|
23189
23431
|
title: "Run Memory Audit",
|
|
23190
23432
|
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).",
|
|
23191
23433
|
inputSchema: {
|
|
23192
|
-
agent_id:
|
|
23193
|
-
project_name:
|
|
23434
|
+
agent_id: z57.string().optional().describe("Filter audit to a specific agent"),
|
|
23435
|
+
project_name: z57.string().optional().describe("Filter audit to a specific project")
|
|
23194
23436
|
}
|
|
23195
23437
|
},
|
|
23196
23438
|
async ({ agent_id, project_name }) => {
|
|
@@ -23232,7 +23474,7 @@ var init_run_memory_audit = __esm({
|
|
|
23232
23474
|
});
|
|
23233
23475
|
|
|
23234
23476
|
// src/mcp/tools/run-consolidation.ts
|
|
23235
|
-
import { z as
|
|
23477
|
+
import { z as z58 } from "zod";
|
|
23236
23478
|
function registerRunConsolidation(server) {
|
|
23237
23479
|
server.registerTool(
|
|
23238
23480
|
"run_consolidation",
|
|
@@ -23240,7 +23482,7 @@ function registerRunConsolidation(server) {
|
|
|
23240
23482
|
title: "Run Consolidation",
|
|
23241
23483
|
description: "Run memory consolidation \u2014 synthesizes unconsolidated memories into meta-insights. Use dry_run=true (default) to preview without executing.",
|
|
23242
23484
|
inputSchema: {
|
|
23243
|
-
dry_run:
|
|
23485
|
+
dry_run: z58.boolean().default(true).describe("Preview mode \u2014 show what would be consolidated without doing it")
|
|
23244
23486
|
}
|
|
23245
23487
|
},
|
|
23246
23488
|
async ({ dry_run }) => {
|
|
@@ -23406,9 +23648,9 @@ __export(crdt_sync_exports, {
|
|
|
23406
23648
|
rebuildFromDb: () => rebuildFromDb
|
|
23407
23649
|
});
|
|
23408
23650
|
import * as Y from "yjs";
|
|
23409
|
-
import { readFileSync as
|
|
23410
|
-
import
|
|
23411
|
-
import { homedir as
|
|
23651
|
+
import { readFileSync as readFileSync27, writeFileSync as writeFileSync18, existsSync as existsSync35, mkdirSync as mkdirSync15, unlinkSync as unlinkSync11 } from "fs";
|
|
23652
|
+
import path40 from "path";
|
|
23653
|
+
import { homedir as homedir6 } from "os";
|
|
23412
23654
|
function getStatePath() {
|
|
23413
23655
|
return _statePathOverride ?? DEFAULT_STATE_PATH;
|
|
23414
23656
|
}
|
|
@@ -23419,9 +23661,9 @@ function initCrdtDoc() {
|
|
|
23419
23661
|
if (doc) return doc;
|
|
23420
23662
|
doc = new Y.Doc();
|
|
23421
23663
|
const sp = getStatePath();
|
|
23422
|
-
if (
|
|
23664
|
+
if (existsSync35(sp)) {
|
|
23423
23665
|
try {
|
|
23424
|
-
const state =
|
|
23666
|
+
const state = readFileSync27(sp);
|
|
23425
23667
|
Y.applyUpdate(doc, new Uint8Array(state));
|
|
23426
23668
|
} catch {
|
|
23427
23669
|
console.warn("[crdt-sync] WARN: corrupted state file, rebuilding from DB");
|
|
@@ -23563,10 +23805,10 @@ function persistState() {
|
|
|
23563
23805
|
if (!doc) return;
|
|
23564
23806
|
try {
|
|
23565
23807
|
const sp = getStatePath();
|
|
23566
|
-
const dir =
|
|
23567
|
-
if (!
|
|
23808
|
+
const dir = path40.dirname(sp);
|
|
23809
|
+
if (!existsSync35(dir)) mkdirSync15(dir, { recursive: true });
|
|
23568
23810
|
const state = Y.encodeStateAsUpdate(doc);
|
|
23569
|
-
|
|
23811
|
+
writeFileSync18(sp, Buffer.from(state));
|
|
23570
23812
|
} catch {
|
|
23571
23813
|
}
|
|
23572
23814
|
}
|
|
@@ -23607,7 +23849,7 @@ var DEFAULT_STATE_PATH, _statePathOverride, doc;
|
|
|
23607
23849
|
var init_crdt_sync = __esm({
|
|
23608
23850
|
"src/lib/crdt-sync.ts"() {
|
|
23609
23851
|
"use strict";
|
|
23610
|
-
DEFAULT_STATE_PATH =
|
|
23852
|
+
DEFAULT_STATE_PATH = path40.join(homedir6(), ".exe-os", "crdt-state.bin");
|
|
23611
23853
|
_statePathOverride = null;
|
|
23612
23854
|
doc = null;
|
|
23613
23855
|
}
|
|
@@ -23647,17 +23889,17 @@ __export(cloud_sync_exports, {
|
|
|
23647
23889
|
pushToPostgres: () => pushToPostgres,
|
|
23648
23890
|
recordRosterDeletion: () => recordRosterDeletion
|
|
23649
23891
|
});
|
|
23650
|
-
import { readFileSync as
|
|
23892
|
+
import { readFileSync as readFileSync28, writeFileSync as writeFileSync19, existsSync as existsSync36, readdirSync as readdirSync11, mkdirSync as mkdirSync16, appendFileSync as appendFileSync4, unlinkSync as unlinkSync12, openSync as openSync3, closeSync as closeSync3, statSync as statSync8 } from "fs";
|
|
23651
23893
|
import crypto16 from "crypto";
|
|
23652
|
-
import
|
|
23653
|
-
import { homedir as
|
|
23894
|
+
import path41 from "path";
|
|
23895
|
+
import { homedir as homedir7 } from "os";
|
|
23654
23896
|
function sqlSafe(v) {
|
|
23655
23897
|
return v === void 0 ? null : v;
|
|
23656
23898
|
}
|
|
23657
23899
|
function logError(msg) {
|
|
23658
23900
|
try {
|
|
23659
|
-
const logPath =
|
|
23660
|
-
|
|
23901
|
+
const logPath = path41.join(homedir7(), ".exe-os", "workers.log");
|
|
23902
|
+
appendFileSync4(logPath, `${(/* @__PURE__ */ new Date()).toISOString()} ${msg}
|
|
23661
23903
|
`);
|
|
23662
23904
|
} catch {
|
|
23663
23905
|
}
|
|
@@ -23667,12 +23909,12 @@ function isTruthyEnv2(value) {
|
|
|
23667
23909
|
}
|
|
23668
23910
|
function loadPgClient() {
|
|
23669
23911
|
if (_pgFailed) return null;
|
|
23670
|
-
const configPath =
|
|
23912
|
+
const configPath = path41.join(EXE_AI_DIR, "config.json");
|
|
23671
23913
|
let cloudPostgresUrl;
|
|
23672
23914
|
let configEnabled = false;
|
|
23673
23915
|
try {
|
|
23674
|
-
if (
|
|
23675
|
-
const cfg = JSON.parse(
|
|
23916
|
+
if (existsSync36(configPath)) {
|
|
23917
|
+
const cfg = JSON.parse(readFileSync28(configPath, "utf8"));
|
|
23676
23918
|
cloudPostgresUrl = cfg.cloud?.postgresUrl;
|
|
23677
23919
|
configEnabled = cfg.cloud?.syncToPostgres === true;
|
|
23678
23920
|
}
|
|
@@ -23699,9 +23941,9 @@ function loadPgClient() {
|
|
|
23699
23941
|
if (!Ctor) throw new Error(`No PrismaClient at ${explicitPath}`);
|
|
23700
23942
|
return new Ctor();
|
|
23701
23943
|
}
|
|
23702
|
-
const exeDbRoot = process.env.EXE_DB_ROOT ??
|
|
23703
|
-
const packagePath =
|
|
23704
|
-
if (
|
|
23944
|
+
const exeDbRoot = process.env.EXE_DB_ROOT ?? path41.join(homedir7(), "exe-db");
|
|
23945
|
+
const packagePath = path41.join(exeDbRoot, "package.json");
|
|
23946
|
+
if (existsSync36(packagePath)) {
|
|
23705
23947
|
const req = createRequire7(packagePath);
|
|
23706
23948
|
const entry = req.resolve("@prisma/client");
|
|
23707
23949
|
const mod = await import(pathToFileURL7(entry).href);
|
|
@@ -23761,20 +24003,20 @@ async function pushToPostgres(records) {
|
|
|
23761
24003
|
}
|
|
23762
24004
|
async function withRosterLock(fn) {
|
|
23763
24005
|
try {
|
|
23764
|
-
const fd =
|
|
23765
|
-
|
|
23766
|
-
|
|
24006
|
+
const fd = openSync3(ROSTER_LOCK_PATH, "wx");
|
|
24007
|
+
closeSync3(fd);
|
|
24008
|
+
writeFileSync19(ROSTER_LOCK_PATH, String(Date.now()));
|
|
23767
24009
|
} catch (err) {
|
|
23768
24010
|
if (err.code === "EEXIST") {
|
|
23769
24011
|
try {
|
|
23770
|
-
const ts2 = parseInt(
|
|
24012
|
+
const ts2 = parseInt(readFileSync28(ROSTER_LOCK_PATH, "utf-8"), 10);
|
|
23771
24013
|
if (Date.now() - ts2 < LOCK_STALE_MS) {
|
|
23772
24014
|
throw new Error("Roster merge already in progress \u2014 another sync is running");
|
|
23773
24015
|
}
|
|
23774
24016
|
unlinkSync12(ROSTER_LOCK_PATH);
|
|
23775
|
-
const fd =
|
|
23776
|
-
|
|
23777
|
-
|
|
24017
|
+
const fd = openSync3(ROSTER_LOCK_PATH, "wx");
|
|
24018
|
+
closeSync3(fd);
|
|
24019
|
+
writeFileSync19(ROSTER_LOCK_PATH, String(Date.now()));
|
|
23778
24020
|
} catch (retryErr) {
|
|
23779
24021
|
if (retryErr instanceof Error && retryErr.message.includes("already in progress")) throw retryErr;
|
|
23780
24022
|
throw new Error("Roster merge already in progress \u2014 another sync is running");
|
|
@@ -24220,8 +24462,8 @@ async function cloudSync(config2) {
|
|
|
24220
24462
|
try {
|
|
24221
24463
|
const employees = await loadEmployees();
|
|
24222
24464
|
rosterResult.employees = employees.length;
|
|
24223
|
-
const idDir =
|
|
24224
|
-
if (
|
|
24465
|
+
const idDir = path41.join(EXE_AI_DIR, "identity");
|
|
24466
|
+
if (existsSync36(idDir)) {
|
|
24225
24467
|
rosterResult.identities = readdirSync11(idDir).filter((f) => f.endsWith(".md")).length;
|
|
24226
24468
|
}
|
|
24227
24469
|
} catch {
|
|
@@ -24231,10 +24473,10 @@ async function cloudSync(config2) {
|
|
|
24231
24473
|
const { getLatestBackup: getLatestBackup2 } = await Promise.resolve().then(() => (init_db_backup(), db_backup_exports));
|
|
24232
24474
|
const latestBackup = getLatestBackup2();
|
|
24233
24475
|
if (latestBackup) {
|
|
24234
|
-
const backupSize =
|
|
24476
|
+
const backupSize = statSync8(latestBackup).size;
|
|
24235
24477
|
const MAX_CLOUD_BACKUP_BYTES = 50 * 1024 * 1024;
|
|
24236
24478
|
if (backupSize <= MAX_CLOUD_BACKUP_BYTES) {
|
|
24237
|
-
const backupData =
|
|
24479
|
+
const backupData = readFileSync28(latestBackup);
|
|
24238
24480
|
const deviceId = loadDeviceId() ?? "unknown";
|
|
24239
24481
|
const encrypted = encryptSyncBlob(backupData);
|
|
24240
24482
|
const backupRes = await fetchWithRetry(`${config2.endpoint}/sync/push-db-backup`, {
|
|
@@ -24242,7 +24484,7 @@ async function cloudSync(config2) {
|
|
|
24242
24484
|
headers: { "Content-Type": "application/json", Authorization: `Bearer ${config2.apiKey}` },
|
|
24243
24485
|
body: JSON.stringify({
|
|
24244
24486
|
device_id: deviceId,
|
|
24245
|
-
filename:
|
|
24487
|
+
filename: path41.basename(latestBackup),
|
|
24246
24488
|
blob: encrypted,
|
|
24247
24489
|
size: backupData.length
|
|
24248
24490
|
})
|
|
@@ -24270,56 +24512,56 @@ async function cloudSync(config2) {
|
|
|
24270
24512
|
function recordRosterDeletion(name) {
|
|
24271
24513
|
let deletions = [];
|
|
24272
24514
|
try {
|
|
24273
|
-
if (
|
|
24274
|
-
deletions = JSON.parse(
|
|
24515
|
+
if (existsSync36(ROSTER_DELETIONS_PATH)) {
|
|
24516
|
+
deletions = JSON.parse(readFileSync28(ROSTER_DELETIONS_PATH, "utf-8"));
|
|
24275
24517
|
}
|
|
24276
24518
|
} catch {
|
|
24277
24519
|
}
|
|
24278
24520
|
if (!deletions.includes(name)) deletions.push(name);
|
|
24279
|
-
|
|
24521
|
+
writeFileSync19(ROSTER_DELETIONS_PATH, JSON.stringify(deletions));
|
|
24280
24522
|
}
|
|
24281
24523
|
function consumeRosterDeletions() {
|
|
24282
24524
|
try {
|
|
24283
|
-
if (!
|
|
24284
|
-
const deletions = JSON.parse(
|
|
24285
|
-
|
|
24525
|
+
if (!existsSync36(ROSTER_DELETIONS_PATH)) return [];
|
|
24526
|
+
const deletions = JSON.parse(readFileSync28(ROSTER_DELETIONS_PATH, "utf-8"));
|
|
24527
|
+
writeFileSync19(ROSTER_DELETIONS_PATH, "[]");
|
|
24286
24528
|
return deletions;
|
|
24287
24529
|
} catch {
|
|
24288
24530
|
return [];
|
|
24289
24531
|
}
|
|
24290
24532
|
}
|
|
24291
24533
|
function buildRosterBlob(paths) {
|
|
24292
|
-
const rosterPath = paths?.rosterPath ??
|
|
24293
|
-
const identityDir = paths?.identityDir ??
|
|
24294
|
-
const configPath = paths?.configPath ??
|
|
24534
|
+
const rosterPath = paths?.rosterPath ?? path41.join(EXE_AI_DIR, "exe-employees.json");
|
|
24535
|
+
const identityDir = paths?.identityDir ?? path41.join(EXE_AI_DIR, "identity");
|
|
24536
|
+
const configPath = paths?.configPath ?? path41.join(EXE_AI_DIR, "config.json");
|
|
24295
24537
|
let roster = [];
|
|
24296
|
-
if (
|
|
24538
|
+
if (existsSync36(rosterPath)) {
|
|
24297
24539
|
try {
|
|
24298
|
-
roster = JSON.parse(
|
|
24540
|
+
roster = JSON.parse(readFileSync28(rosterPath, "utf-8"));
|
|
24299
24541
|
} catch {
|
|
24300
24542
|
}
|
|
24301
24543
|
}
|
|
24302
24544
|
const identities = {};
|
|
24303
|
-
if (
|
|
24545
|
+
if (existsSync36(identityDir)) {
|
|
24304
24546
|
for (const file of readdirSync11(identityDir).filter((f) => f.endsWith(".md"))) {
|
|
24305
24547
|
try {
|
|
24306
|
-
identities[file] =
|
|
24548
|
+
identities[file] = readFileSync28(path41.join(identityDir, file), "utf-8");
|
|
24307
24549
|
} catch {
|
|
24308
24550
|
}
|
|
24309
24551
|
}
|
|
24310
24552
|
}
|
|
24311
24553
|
let config2;
|
|
24312
|
-
if (
|
|
24554
|
+
if (existsSync36(configPath)) {
|
|
24313
24555
|
try {
|
|
24314
|
-
config2 = JSON.parse(
|
|
24556
|
+
config2 = JSON.parse(readFileSync28(configPath, "utf-8"));
|
|
24315
24557
|
} catch {
|
|
24316
24558
|
}
|
|
24317
24559
|
}
|
|
24318
24560
|
let agentConfig;
|
|
24319
|
-
const agentConfigPath =
|
|
24320
|
-
if (
|
|
24561
|
+
const agentConfigPath = path41.join(EXE_AI_DIR, "agent-config.json");
|
|
24562
|
+
if (existsSync36(agentConfigPath)) {
|
|
24321
24563
|
try {
|
|
24322
|
-
agentConfig = JSON.parse(
|
|
24564
|
+
agentConfig = JSON.parse(readFileSync28(agentConfigPath, "utf-8"));
|
|
24323
24565
|
} catch {
|
|
24324
24566
|
}
|
|
24325
24567
|
}
|
|
@@ -24395,24 +24637,24 @@ async function cloudPullRoster(config2) {
|
|
|
24395
24637
|
}
|
|
24396
24638
|
}
|
|
24397
24639
|
function mergeConfig(remoteConfig, configPath) {
|
|
24398
|
-
const cfgPath = configPath ??
|
|
24640
|
+
const cfgPath = configPath ?? path41.join(EXE_AI_DIR, "config.json");
|
|
24399
24641
|
let local = {};
|
|
24400
|
-
if (
|
|
24642
|
+
if (existsSync36(cfgPath)) {
|
|
24401
24643
|
try {
|
|
24402
|
-
local = JSON.parse(
|
|
24644
|
+
local = JSON.parse(readFileSync28(cfgPath, "utf-8"));
|
|
24403
24645
|
} catch {
|
|
24404
24646
|
}
|
|
24405
24647
|
}
|
|
24406
24648
|
const merged = { ...remoteConfig, ...local };
|
|
24407
|
-
const dir =
|
|
24649
|
+
const dir = path41.dirname(cfgPath);
|
|
24408
24650
|
ensurePrivateDirSync(dir);
|
|
24409
|
-
|
|
24651
|
+
writeFileSync19(cfgPath, JSON.stringify(merged, null, 2), "utf-8");
|
|
24410
24652
|
enforcePrivateFileSync(cfgPath);
|
|
24411
24653
|
}
|
|
24412
24654
|
async function mergeRosterFromRemote(remote, paths) {
|
|
24413
24655
|
return withRosterLock(async () => {
|
|
24414
24656
|
const rosterPath = paths?.rosterPath ?? void 0;
|
|
24415
|
-
const identityDir = paths?.identityDir ??
|
|
24657
|
+
const identityDir = paths?.identityDir ?? path41.join(EXE_AI_DIR, "identity");
|
|
24416
24658
|
const localEmployees = await loadEmployees(rosterPath);
|
|
24417
24659
|
const localNames = new Set(localEmployees.map((e) => e.name));
|
|
24418
24660
|
let added = 0;
|
|
@@ -24433,15 +24675,15 @@ async function mergeRosterFromRemote(remote, paths) {
|
|
|
24433
24675
|
) ?? lookupKey;
|
|
24434
24676
|
const remoteIdentity = remote.identities[matchedKey];
|
|
24435
24677
|
if (remoteIdentity) {
|
|
24436
|
-
if (!
|
|
24437
|
-
const idPath =
|
|
24678
|
+
if (!existsSync36(identityDir)) mkdirSync16(identityDir, { recursive: true });
|
|
24679
|
+
const idPath = path41.join(identityDir, `${remoteEmp.name}.md`);
|
|
24438
24680
|
let localIdentity = null;
|
|
24439
24681
|
try {
|
|
24440
|
-
localIdentity =
|
|
24682
|
+
localIdentity = existsSync36(idPath) ? readFileSync28(idPath, "utf-8") : null;
|
|
24441
24683
|
} catch {
|
|
24442
24684
|
}
|
|
24443
24685
|
if (localIdentity !== remoteIdentity) {
|
|
24444
|
-
|
|
24686
|
+
writeFileSync19(idPath, remoteIdentity, "utf-8");
|
|
24445
24687
|
identitiesUpdated++;
|
|
24446
24688
|
}
|
|
24447
24689
|
}
|
|
@@ -24467,17 +24709,17 @@ async function mergeRosterFromRemote(remote, paths) {
|
|
|
24467
24709
|
}
|
|
24468
24710
|
if (remote.agentConfig && Object.keys(remote.agentConfig).length > 0) {
|
|
24469
24711
|
try {
|
|
24470
|
-
const agentConfigPath =
|
|
24712
|
+
const agentConfigPath = path41.join(EXE_AI_DIR, "agent-config.json");
|
|
24471
24713
|
let local = {};
|
|
24472
|
-
if (
|
|
24714
|
+
if (existsSync36(agentConfigPath)) {
|
|
24473
24715
|
try {
|
|
24474
|
-
local = JSON.parse(
|
|
24716
|
+
local = JSON.parse(readFileSync28(agentConfigPath, "utf-8"));
|
|
24475
24717
|
} catch {
|
|
24476
24718
|
}
|
|
24477
24719
|
}
|
|
24478
24720
|
const merged = { ...remote.agentConfig, ...local };
|
|
24479
|
-
ensurePrivateDirSync(
|
|
24480
|
-
|
|
24721
|
+
ensurePrivateDirSync(path41.dirname(agentConfigPath));
|
|
24722
|
+
writeFileSync19(agentConfigPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
|
|
24481
24723
|
enforcePrivateFileSync(agentConfigPath);
|
|
24482
24724
|
} catch {
|
|
24483
24725
|
}
|
|
@@ -24917,17 +25159,17 @@ var init_cloud_sync = __esm({
|
|
|
24917
25159
|
LOCALHOST_PATTERNS = /^(localhost|127\.0\.0\.1|\[::1\])$/i;
|
|
24918
25160
|
FETCH_TIMEOUT_MS2 = 3e4;
|
|
24919
25161
|
PUSH_BATCH_SIZE = 5e3;
|
|
24920
|
-
ROSTER_LOCK_PATH =
|
|
25162
|
+
ROSTER_LOCK_PATH = path41.join(EXE_AI_DIR, "roster-merge.lock");
|
|
24921
25163
|
LOCK_STALE_MS = 3e4;
|
|
24922
25164
|
_pgPromise = null;
|
|
24923
25165
|
_pgFailed = false;
|
|
24924
25166
|
CLOUD_REUPLOAD_REQUIRED_MESSAGE = "Cloud sync is blocked because this device rotated its memory encryption key. Run `exe-os cloud reupload` first to re-upload the cloud backup with the new key.";
|
|
24925
|
-
ROSTER_DELETIONS_PATH =
|
|
25167
|
+
ROSTER_DELETIONS_PATH = path41.join(EXE_AI_DIR, "roster-deletions.json");
|
|
24926
25168
|
}
|
|
24927
25169
|
});
|
|
24928
25170
|
|
|
24929
25171
|
// src/mcp/tools/cloud-sync.ts
|
|
24930
|
-
import { z as
|
|
25172
|
+
import { z as z59 } from "zod";
|
|
24931
25173
|
function result(text3, isError = false) {
|
|
24932
25174
|
return { content: [{ type: "text", text: text3 }], ...isError ? { isError: true } : {} };
|
|
24933
25175
|
}
|
|
@@ -25008,9 +25250,9 @@ function registerCloudSync(server) {
|
|
|
25008
25250
|
title: "Cloud Sync",
|
|
25009
25251
|
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.",
|
|
25010
25252
|
inputSchema: {
|
|
25011
|
-
action:
|
|
25012
|
-
force:
|
|
25013
|
-
confirm_local_db_source_of_truth:
|
|
25253
|
+
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."),
|
|
25254
|
+
force: z59.boolean().default(false).describe("Reserved for sync compatibility; normal cloud sync already runs when requested."),
|
|
25255
|
+
confirm_local_db_source_of_truth: z59.string().optional().describe('Required for action=reupload. Must exactly equal "LOCAL DB IS SOURCE OF TRUTH".')
|
|
25014
25256
|
}
|
|
25015
25257
|
},
|
|
25016
25258
|
async ({ action = "sync", confirm_local_db_source_of_truth }) => {
|
|
@@ -25163,7 +25405,7 @@ var init_orchestration_phase = __esm({
|
|
|
25163
25405
|
});
|
|
25164
25406
|
|
|
25165
25407
|
// src/mcp/tools/orchestration-phase.ts
|
|
25166
|
-
import { z as
|
|
25408
|
+
import { z as z60 } from "zod";
|
|
25167
25409
|
function render(info, prefix) {
|
|
25168
25410
|
return [
|
|
25169
25411
|
prefix,
|
|
@@ -25182,8 +25424,8 @@ function registerOrchestrationPhase(server) {
|
|
|
25182
25424
|
title: "Orchestration Phase",
|
|
25183
25425
|
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.",
|
|
25184
25426
|
inputSchema: {
|
|
25185
|
-
action:
|
|
25186
|
-
phase:
|
|
25427
|
+
action: z60.enum(["status", "set", "unlock_executives", "unlock_parallel"]).default("status"),
|
|
25428
|
+
phase: z60.enum(["phase_1_coo", "phase_2_executives", "phase_3_parallel_org", "1", "2", "3"]).optional().describe("Phase to set when action='set'.")
|
|
25187
25429
|
}
|
|
25188
25430
|
},
|
|
25189
25431
|
async ({ action = "status", phase }) => {
|
|
@@ -25551,50 +25793,50 @@ var init_vps_backup = __esm({
|
|
|
25551
25793
|
});
|
|
25552
25794
|
|
|
25553
25795
|
// src/mcp/tools/backup-vps.ts
|
|
25554
|
-
import { z as
|
|
25796
|
+
import { z as z61 } from "zod";
|
|
25555
25797
|
function registerBackupVps(server) {
|
|
25556
25798
|
server.registerTool(
|
|
25557
25799
|
"backup_vps",
|
|
25558
25800
|
{
|
|
25559
25801
|
title: "VPS Backup",
|
|
25560
25802
|
description: "Run VPS Postgres backup/restore workflows and check status.",
|
|
25561
|
-
inputSchema:
|
|
25562
|
-
|
|
25563
|
-
action:
|
|
25564
|
-
databaseUrl:
|
|
25565
|
-
encryptionKeyB64:
|
|
25803
|
+
inputSchema: z61.discriminatedUnion("action", [
|
|
25804
|
+
z61.object({
|
|
25805
|
+
action: z61.literal("backup"),
|
|
25806
|
+
databaseUrl: z61.string().min(1).describe("Postgres DATABASE_URL to dump from"),
|
|
25807
|
+
encryptionKeyB64: z61.string().min(1).max(4096).optional().describe(
|
|
25566
25808
|
"Base64 AES-256 key (defaults to local master key if omitted)"
|
|
25567
25809
|
),
|
|
25568
|
-
r2Bucket:
|
|
25569
|
-
r2Endpoint:
|
|
25570
|
-
r2AccessKeyId:
|
|
25571
|
-
r2SecretAccessKey:
|
|
25810
|
+
r2Bucket: z61.string().min(1).describe("R2 bucket name"),
|
|
25811
|
+
r2Endpoint: z61.string().min(1).describe("R2 endpoint URL"),
|
|
25812
|
+
r2AccessKeyId: z61.string().min(1).describe("R2 access key ID"),
|
|
25813
|
+
r2SecretAccessKey: z61.string().min(1).describe("R2 secret access key")
|
|
25572
25814
|
}),
|
|
25573
|
-
|
|
25574
|
-
action:
|
|
25575
|
-
databaseUrl:
|
|
25576
|
-
backupKey:
|
|
25577
|
-
encryptionKeyB64:
|
|
25815
|
+
z61.object({
|
|
25816
|
+
action: z61.literal("restore"),
|
|
25817
|
+
databaseUrl: z61.string().min(1).describe("Target Postgres DATABASE_URL for restore"),
|
|
25818
|
+
backupKey: z61.string().min(1).describe("R2 object key to restore from"),
|
|
25819
|
+
encryptionKeyB64: z61.string().min(1).max(4096).optional().describe(
|
|
25578
25820
|
"Base64 AES-256 key (defaults to local master key if omitted)"
|
|
25579
25821
|
),
|
|
25580
|
-
r2Bucket:
|
|
25581
|
-
r2Endpoint:
|
|
25582
|
-
r2AccessKeyId:
|
|
25583
|
-
r2SecretAccessKey:
|
|
25822
|
+
r2Bucket: z61.string().min(1).describe("R2 bucket name"),
|
|
25823
|
+
r2Endpoint: z61.string().min(1).describe("R2 endpoint URL"),
|
|
25824
|
+
r2AccessKeyId: z61.string().min(1).describe("R2 access key ID"),
|
|
25825
|
+
r2SecretAccessKey: z61.string().min(1).describe("R2 secret access key")
|
|
25584
25826
|
}),
|
|
25585
|
-
|
|
25586
|
-
action:
|
|
25587
|
-
r2Bucket:
|
|
25588
|
-
r2Endpoint:
|
|
25589
|
-
r2AccessKeyId:
|
|
25590
|
-
r2SecretAccessKey:
|
|
25827
|
+
z61.object({
|
|
25828
|
+
action: z61.literal("list"),
|
|
25829
|
+
r2Bucket: z61.string().min(1).describe("R2 bucket name"),
|
|
25830
|
+
r2Endpoint: z61.string().min(1).describe("R2 endpoint URL"),
|
|
25831
|
+
r2AccessKeyId: z61.string().min(1).describe("R2 access key ID"),
|
|
25832
|
+
r2SecretAccessKey: z61.string().min(1).describe("R2 secret access key")
|
|
25591
25833
|
}),
|
|
25592
|
-
|
|
25593
|
-
action:
|
|
25594
|
-
r2Bucket:
|
|
25595
|
-
r2Endpoint:
|
|
25596
|
-
r2AccessKeyId:
|
|
25597
|
-
r2SecretAccessKey:
|
|
25834
|
+
z61.object({
|
|
25835
|
+
action: z61.literal("health"),
|
|
25836
|
+
r2Bucket: z61.string().min(1).describe("R2 bucket name"),
|
|
25837
|
+
r2Endpoint: z61.string().min(1).describe("R2 endpoint URL"),
|
|
25838
|
+
r2AccessKeyId: z61.string().min(1).describe("R2 access key ID"),
|
|
25839
|
+
r2SecretAccessKey: z61.string().min(1).describe("R2 secret access key")
|
|
25598
25840
|
})
|
|
25599
25841
|
])
|
|
25600
25842
|
},
|
|
@@ -25788,9 +26030,9 @@ var init_hostinger_api = __esm({
|
|
|
25788
26030
|
}
|
|
25789
26031
|
this.lastRequestTime = Date.now();
|
|
25790
26032
|
}
|
|
25791
|
-
async request(method,
|
|
26033
|
+
async request(method, path60, body) {
|
|
25792
26034
|
await this.rateLimit();
|
|
25793
|
-
const url = `${this.baseUrl}${
|
|
26035
|
+
const url = `${this.baseUrl}${path60}`;
|
|
25794
26036
|
const headers = {
|
|
25795
26037
|
Authorization: `Bearer ${this.apiKey}`,
|
|
25796
26038
|
"Content-Type": "application/json",
|
|
@@ -25859,8 +26101,8 @@ async function requestCloudflare(cfApiToken, zoneId, options) {
|
|
|
25859
26101
|
}
|
|
25860
26102
|
return envelope.result;
|
|
25861
26103
|
}
|
|
25862
|
-
function buildUrl(zoneId,
|
|
25863
|
-
const normalizedPath =
|
|
26104
|
+
function buildUrl(zoneId, path60 = "/dns_records", query) {
|
|
26105
|
+
const normalizedPath = path60.startsWith("/") ? path60 : `/${path60}`;
|
|
25864
26106
|
const url = new URL(
|
|
25865
26107
|
`${CLOUDFLARE_API_BASE_URL}/zones/${zoneId}${normalizedPath}`
|
|
25866
26108
|
);
|
|
@@ -25931,11 +26173,11 @@ var init_cloudflare_dns = __esm({
|
|
|
25931
26173
|
});
|
|
25932
26174
|
|
|
25933
26175
|
// src/mcp/tools/deploy-client.ts
|
|
25934
|
-
import { z as
|
|
26176
|
+
import { z as z62 } from "zod";
|
|
25935
26177
|
import { execFile } from "child_process";
|
|
25936
26178
|
import { promisify } from "util";
|
|
25937
|
-
import
|
|
25938
|
-
import { existsSync as
|
|
26179
|
+
import path42 from "path";
|
|
26180
|
+
import { existsSync as existsSync37 } from "fs";
|
|
25939
26181
|
async function executeDeployment(params, client) {
|
|
25940
26182
|
const {
|
|
25941
26183
|
client_name,
|
|
@@ -26007,12 +26249,12 @@ function registerDeployClient(server) {
|
|
|
26007
26249
|
title: "Deploy Client",
|
|
26008
26250
|
description: "Provision a Hostinger VPS and deploy exe-os for a client. Creates VPS, waits for ready state, runs Ansible playbook, verifies health.",
|
|
26009
26251
|
inputSchema: {
|
|
26010
|
-
client_name:
|
|
26011
|
-
domain:
|
|
26012
|
-
region:
|
|
26013
|
-
plan:
|
|
26014
|
-
ssl_email:
|
|
26015
|
-
user_id:
|
|
26252
|
+
client_name: z62.string().min(1).describe("Client name (used for hostname and identification)"),
|
|
26253
|
+
domain: z62.string().min(1).describe("Domain name for the deployment (e.g., client.exe.ai)"),
|
|
26254
|
+
region: z62.string().default("jakarta").describe("VPS region (default: jakarta)"),
|
|
26255
|
+
plan: z62.string().default("kvm-2").describe("Hostinger VPS plan (default: kvm-2)"),
|
|
26256
|
+
ssl_email: z62.string().email().describe("Email for Let's Encrypt SSL certificate"),
|
|
26257
|
+
user_id: z62.string().min(1).describe("User/customer ID for inventory tracking")
|
|
26016
26258
|
}
|
|
26017
26259
|
},
|
|
26018
26260
|
async ({ client_name, domain, region, plan, ssl_email, user_id }) => {
|
|
@@ -26080,12 +26322,12 @@ async function waitForReady(client, vpsId) {
|
|
|
26080
26322
|
}
|
|
26081
26323
|
async function runAnsiblePlaybook(vpsIp, domain, sslEmail, clientName) {
|
|
26082
26324
|
const safeClientName = clientName.replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
26083
|
-
const playbookDir =
|
|
26084
|
-
const playbookPath =
|
|
26085
|
-
const inventoryPath =
|
|
26086
|
-
const clientVarsPath =
|
|
26087
|
-
const varsDir =
|
|
26088
|
-
if (!
|
|
26325
|
+
const playbookDir = path42.resolve(process.cwd(), "infrastructure", "ansible");
|
|
26326
|
+
const playbookPath = path42.join(playbookDir, "deploy.yml");
|
|
26327
|
+
const inventoryPath = path42.join(playbookDir, "inventory", "hosts.yml");
|
|
26328
|
+
const clientVarsPath = path42.join(playbookDir, "vars", `${safeClientName}.yml`);
|
|
26329
|
+
const varsDir = path42.join(playbookDir, "vars");
|
|
26330
|
+
if (!path42.resolve(clientVarsPath).startsWith(path42.resolve(varsDir))) {
|
|
26089
26331
|
throw new Error(`Invalid client name for vars path: ${clientName}`);
|
|
26090
26332
|
}
|
|
26091
26333
|
const args = [
|
|
@@ -26101,7 +26343,7 @@ async function runAnsiblePlaybook(vpsIp, domain, sslEmail, clientName) {
|
|
|
26101
26343
|
"-e",
|
|
26102
26344
|
`client_name=${safeClientName}`
|
|
26103
26345
|
];
|
|
26104
|
-
if (
|
|
26346
|
+
if (existsSync37(clientVarsPath)) {
|
|
26105
26347
|
args.push("-e", `@${clientVarsPath}`);
|
|
26106
26348
|
}
|
|
26107
26349
|
try {
|
|
@@ -26191,7 +26433,7 @@ var init_deploy_client = __esm({
|
|
|
26191
26433
|
});
|
|
26192
26434
|
|
|
26193
26435
|
// src/mcp/tools/get-license-status.ts
|
|
26194
|
-
import { z as
|
|
26436
|
+
import { z as z63 } from "zod";
|
|
26195
26437
|
function registerGetLicenseStatus(server) {
|
|
26196
26438
|
server.registerTool(
|
|
26197
26439
|
"get_license_status",
|
|
@@ -26199,7 +26441,7 @@ function registerGetLicenseStatus(server) {
|
|
|
26199
26441
|
title: "Get License Status",
|
|
26200
26442
|
description: "Get current license status: plan, validity, feature gates, limits, and expiry.",
|
|
26201
26443
|
inputSchema: {
|
|
26202
|
-
_dummy:
|
|
26444
|
+
_dummy: z63.string().optional().describe("Unused \u2014 no input required")
|
|
26203
26445
|
}
|
|
26204
26446
|
},
|
|
26205
26447
|
async () => {
|
|
@@ -26265,11 +26507,11 @@ var init_get_license_status = __esm({
|
|
|
26265
26507
|
|
|
26266
26508
|
// src/mcp/tools/create-license.ts
|
|
26267
26509
|
import os17 from "os";
|
|
26268
|
-
import
|
|
26510
|
+
import path43 from "path";
|
|
26269
26511
|
import { randomBytes as randomBytes2, randomUUID as randomUUID6 } from "crypto";
|
|
26270
26512
|
import { createRequire as createRequire4 } from "module";
|
|
26271
26513
|
import { pathToFileURL as pathToFileURL4 } from "url";
|
|
26272
|
-
import { z as
|
|
26514
|
+
import { z as z64 } from "zod";
|
|
26273
26515
|
function loadPrisma2() {
|
|
26274
26516
|
if (!prismaPromise2) {
|
|
26275
26517
|
prismaPromise2 = (async () => {
|
|
@@ -26280,8 +26522,8 @@ function loadPrisma2() {
|
|
|
26280
26522
|
if (!Ctor2) throw new Error(`No PrismaClient at ${explicitPath}`);
|
|
26281
26523
|
return new Ctor2();
|
|
26282
26524
|
}
|
|
26283
|
-
const exeDbRoot = process.env.EXE_DB_ROOT ??
|
|
26284
|
-
const req = createRequire4(
|
|
26525
|
+
const exeDbRoot = process.env.EXE_DB_ROOT ?? path43.join(os17.homedir(), "exe-db");
|
|
26526
|
+
const req = createRequire4(path43.join(exeDbRoot, "package.json"));
|
|
26285
26527
|
const entry = req.resolve("@prisma/client");
|
|
26286
26528
|
const mod = await import(pathToFileURL4(entry).href);
|
|
26287
26529
|
const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
|
|
@@ -26301,10 +26543,10 @@ function registerCreateLicense(server) {
|
|
|
26301
26543
|
title: "Create License",
|
|
26302
26544
|
description: "Generate an exe_sk_* license key for a user. Stores in billing.licenses. Returns the key to give to the customer.",
|
|
26303
26545
|
inputSchema: {
|
|
26304
|
-
email:
|
|
26305
|
-
name:
|
|
26306
|
-
plan:
|
|
26307
|
-
expires_in_days:
|
|
26546
|
+
email: z64.string().email().describe("Customer email address"),
|
|
26547
|
+
name: z64.string().optional().describe("Customer name"),
|
|
26548
|
+
plan: z64.enum(["free", "pro", "team", "agency", "enterprise"]).default("pro").describe("License plan tier"),
|
|
26549
|
+
expires_in_days: z64.number().int().positive().default(365).describe("Days until expiration (default 365)")
|
|
26308
26550
|
}
|
|
26309
26551
|
},
|
|
26310
26552
|
async ({ email, name, plan, expires_in_days }) => {
|
|
@@ -26364,10 +26606,10 @@ var init_create_license = __esm({
|
|
|
26364
26606
|
|
|
26365
26607
|
// src/mcp/tools/list-licenses.ts
|
|
26366
26608
|
import os18 from "os";
|
|
26367
|
-
import
|
|
26609
|
+
import path44 from "path";
|
|
26368
26610
|
import { createRequire as createRequire5 } from "module";
|
|
26369
26611
|
import { pathToFileURL as pathToFileURL5 } from "url";
|
|
26370
|
-
import { z as
|
|
26612
|
+
import { z as z65 } from "zod";
|
|
26371
26613
|
function loadPrisma3() {
|
|
26372
26614
|
if (!prismaPromise3) {
|
|
26373
26615
|
prismaPromise3 = (async () => {
|
|
@@ -26378,8 +26620,8 @@ function loadPrisma3() {
|
|
|
26378
26620
|
if (!Ctor2) throw new Error(`No PrismaClient at ${explicitPath}`);
|
|
26379
26621
|
return new Ctor2();
|
|
26380
26622
|
}
|
|
26381
|
-
const exeDbRoot = process.env.EXE_DB_ROOT ??
|
|
26382
|
-
const req = createRequire5(
|
|
26623
|
+
const exeDbRoot = process.env.EXE_DB_ROOT ?? path44.join(os18.homedir(), "exe-db");
|
|
26624
|
+
const req = createRequire5(path44.join(exeDbRoot, "package.json"));
|
|
26383
26625
|
const entry = req.resolve("@prisma/client");
|
|
26384
26626
|
const mod = await import(pathToFileURL5(entry).href);
|
|
26385
26627
|
const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
|
|
@@ -26396,7 +26638,7 @@ function registerListLicenses(server) {
|
|
|
26396
26638
|
title: "List Licenses",
|
|
26397
26639
|
description: "List all issued licenses with status (active/expired/revoked). Optionally filter by plan.",
|
|
26398
26640
|
inputSchema: {
|
|
26399
|
-
plan:
|
|
26641
|
+
plan: z65.enum(["free", "pro", "team", "agency", "enterprise"]).optional().describe("Filter by plan tier (omit for all)")
|
|
26400
26642
|
}
|
|
26401
26643
|
},
|
|
26402
26644
|
async ({ plan }) => {
|
|
@@ -26453,7 +26695,7 @@ var init_list_licenses = __esm({
|
|
|
26453
26695
|
});
|
|
26454
26696
|
|
|
26455
26697
|
// src/mcp/tools/activate-license.ts
|
|
26456
|
-
import { z as
|
|
26698
|
+
import { z as z66 } from "zod";
|
|
26457
26699
|
function registerActivateLicense(server) {
|
|
26458
26700
|
server.registerTool(
|
|
26459
26701
|
"activate_license",
|
|
@@ -26461,7 +26703,7 @@ function registerActivateLicense(server) {
|
|
|
26461
26703
|
title: "Activate License",
|
|
26462
26704
|
description: "Activate an exe_sk_* license key on this device. Writes to ~/.exe-os/license.key, validates against Postgres, and caches the result.",
|
|
26463
26705
|
inputSchema: {
|
|
26464
|
-
key:
|
|
26706
|
+
key: z66.string().startsWith("exe_sk_").describe("License key (exe_sk_*)")
|
|
26465
26707
|
}
|
|
26466
26708
|
},
|
|
26467
26709
|
async ({ key }) => {
|
|
@@ -26513,14 +26755,14 @@ var init_activate_license = __esm({
|
|
|
26513
26755
|
});
|
|
26514
26756
|
|
|
26515
26757
|
// src/automation/trigger-engine.ts
|
|
26516
|
-
import { readFileSync as
|
|
26758
|
+
import { readFileSync as readFileSync29, writeFileSync as writeFileSync20, existsSync as existsSync38, mkdirSync as mkdirSync17 } from "fs";
|
|
26517
26759
|
import { randomUUID as randomUUID7 } from "crypto";
|
|
26518
|
-
import
|
|
26760
|
+
import path45 from "path";
|
|
26519
26761
|
import os19 from "os";
|
|
26520
26762
|
function loadTriggers(project) {
|
|
26521
|
-
if (!
|
|
26763
|
+
if (!existsSync38(TRIGGERS_PATH)) return [];
|
|
26522
26764
|
try {
|
|
26523
|
-
const raw =
|
|
26765
|
+
const raw = readFileSync29(TRIGGERS_PATH, "utf-8");
|
|
26524
26766
|
const all = JSON.parse(raw);
|
|
26525
26767
|
if (!Array.isArray(all)) return [];
|
|
26526
26768
|
if (project) {
|
|
@@ -26532,9 +26774,9 @@ function loadTriggers(project) {
|
|
|
26532
26774
|
}
|
|
26533
26775
|
}
|
|
26534
26776
|
function saveTriggers(triggers) {
|
|
26535
|
-
const dir =
|
|
26536
|
-
if (!
|
|
26537
|
-
|
|
26777
|
+
const dir = path45.dirname(TRIGGERS_PATH);
|
|
26778
|
+
if (!existsSync38(dir)) mkdirSync17(dir, { recursive: true });
|
|
26779
|
+
writeFileSync20(TRIGGERS_PATH, JSON.stringify(triggers, null, 2), "utf-8");
|
|
26538
26780
|
}
|
|
26539
26781
|
function createNewTrigger(input) {
|
|
26540
26782
|
const triggers = loadTriggers();
|
|
@@ -26553,7 +26795,7 @@ var TRIGGERS_PATH;
|
|
|
26553
26795
|
var init_trigger_engine = __esm({
|
|
26554
26796
|
"src/automation/trigger-engine.ts"() {
|
|
26555
26797
|
"use strict";
|
|
26556
|
-
TRIGGERS_PATH =
|
|
26798
|
+
TRIGGERS_PATH = path45.join(os19.homedir(), ".exe-os", "triggers.json");
|
|
26557
26799
|
}
|
|
26558
26800
|
});
|
|
26559
26801
|
|
|
@@ -26703,7 +26945,7 @@ var init_schedules = __esm({
|
|
|
26703
26945
|
});
|
|
26704
26946
|
|
|
26705
26947
|
// src/mcp/tools/create-trigger.ts
|
|
26706
|
-
import { z as
|
|
26948
|
+
import { z as z67 } from "zod";
|
|
26707
26949
|
function registerCreateTrigger(server) {
|
|
26708
26950
|
server.registerTool(
|
|
26709
26951
|
"create_trigger",
|
|
@@ -26711,18 +26953,18 @@ function registerCreateTrigger(server) {
|
|
|
26711
26953
|
title: "Create Trigger",
|
|
26712
26954
|
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.).",
|
|
26713
26955
|
inputSchema: {
|
|
26714
|
-
name:
|
|
26715
|
-
event:
|
|
26956
|
+
name: z67.string().describe("Human-readable trigger name"),
|
|
26957
|
+
event: z67.string().describe(
|
|
26716
26958
|
'CRM event to match, e.g., "Deal.updated", "Order.created", "*" for all'
|
|
26717
26959
|
),
|
|
26718
|
-
conditions:
|
|
26719
|
-
actions:
|
|
26720
|
-
project:
|
|
26721
|
-
enabled:
|
|
26722
|
-
schedule:
|
|
26960
|
+
conditions: z67.array(conditionSchema).default([]).describe("Conditions that must all match (AND logic)"),
|
|
26961
|
+
actions: z67.array(actionSchema).min(1).describe("Actions to execute when trigger fires"),
|
|
26962
|
+
project: z67.string().optional().describe("Scope trigger to a specific project"),
|
|
26963
|
+
enabled: z67.boolean().default(true).describe("Whether trigger is active"),
|
|
26964
|
+
schedule: z67.string().optional().describe(
|
|
26723
26965
|
'Cron schedule for time-based triggers, e.g., "0 9 * * *" or "Monday 9am"'
|
|
26724
26966
|
),
|
|
26725
|
-
query:
|
|
26967
|
+
query: z67.string().optional().describe(
|
|
26726
26968
|
"CRM GraphQL query to run on schedule (required if schedule is set)"
|
|
26727
26969
|
)
|
|
26728
26970
|
}
|
|
@@ -26799,14 +27041,14 @@ var init_create_trigger = __esm({
|
|
|
26799
27041
|
"use strict";
|
|
26800
27042
|
init_trigger_engine();
|
|
26801
27043
|
init_schedules();
|
|
26802
|
-
conditionSchema =
|
|
26803
|
-
field:
|
|
26804
|
-
op:
|
|
26805
|
-
value:
|
|
27044
|
+
conditionSchema = z67.object({
|
|
27045
|
+
field: z67.string().describe("Dot-path field to evaluate, e.g., 'stage' or 'amount'"),
|
|
27046
|
+
op: z67.enum(["eq", "neq", "gt", "lt", "gte", "lte", "contains", "not_contains"]).describe("Comparison operator"),
|
|
27047
|
+
value: z67.string().or(z67.number()).or(z67.boolean()).describe("Value to compare against")
|
|
26806
27048
|
});
|
|
26807
|
-
actionSchema =
|
|
26808
|
-
type:
|
|
26809
|
-
params:
|
|
27049
|
+
actionSchema = z67.object({
|
|
27050
|
+
type: z67.enum(["send_whatsapp", "send_message", "create_task", "mcp_tool"]).describe("Action type to execute"),
|
|
27051
|
+
params: z67.record(z67.string(), z67.string()).describe(
|
|
26810
27052
|
"Action parameters. Supports {{record.field}} templates for dynamic values."
|
|
26811
27053
|
)
|
|
26812
27054
|
});
|
|
@@ -26814,7 +27056,7 @@ var init_create_trigger = __esm({
|
|
|
26814
27056
|
});
|
|
26815
27057
|
|
|
26816
27058
|
// src/mcp/tools/list-triggers.ts
|
|
26817
|
-
import { z as
|
|
27059
|
+
import { z as z68 } from "zod";
|
|
26818
27060
|
function registerListTriggers(server) {
|
|
26819
27061
|
server.registerTool(
|
|
26820
27062
|
"list_triggers",
|
|
@@ -26822,7 +27064,7 @@ function registerListTriggers(server) {
|
|
|
26822
27064
|
title: "List Triggers",
|
|
26823
27065
|
description: "List configured CRM event triggers and scheduled automations.",
|
|
26824
27066
|
inputSchema: {
|
|
26825
|
-
project:
|
|
27067
|
+
project: z68.string().optional().describe("Filter triggers by project name")
|
|
26826
27068
|
}
|
|
26827
27069
|
},
|
|
26828
27070
|
async ({ project }) => {
|
|
@@ -26863,47 +27105,47 @@ var init_list_triggers = __esm({
|
|
|
26863
27105
|
});
|
|
26864
27106
|
|
|
26865
27107
|
// src/automation/starter-packs/index.ts
|
|
26866
|
-
import { readFileSync as
|
|
26867
|
-
import
|
|
26868
|
-
import { fileURLToPath as
|
|
27108
|
+
import { readFileSync as readFileSync30, readdirSync as readdirSync12, existsSync as existsSync39 } from "fs";
|
|
27109
|
+
import path46 from "path";
|
|
27110
|
+
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
26869
27111
|
function listPacks() {
|
|
26870
|
-
const packsDir =
|
|
26871
|
-
if (!
|
|
27112
|
+
const packsDir = path46.join(__dirname, ".");
|
|
27113
|
+
if (!existsSync39(packsDir)) return [];
|
|
26872
27114
|
return readdirSync12(packsDir, { withFileTypes: true }).filter(
|
|
26873
|
-
(d) => d.isDirectory() &&
|
|
27115
|
+
(d) => d.isDirectory() && existsSync39(path46.join(packsDir, d.name, "custom-objects.json"))
|
|
26874
27116
|
).map((d) => d.name);
|
|
26875
27117
|
}
|
|
26876
27118
|
function loadPack(industry) {
|
|
26877
|
-
const packDir =
|
|
26878
|
-
const objectsPath =
|
|
26879
|
-
const triggersPath =
|
|
26880
|
-
const wikiDir =
|
|
26881
|
-
const manifestPath =
|
|
26882
|
-
const identityContextPath =
|
|
26883
|
-
if (!
|
|
27119
|
+
const packDir = path46.join(__dirname, industry);
|
|
27120
|
+
const objectsPath = path46.join(packDir, "custom-objects.json");
|
|
27121
|
+
const triggersPath = path46.join(packDir, "triggers.json");
|
|
27122
|
+
const wikiDir = path46.join(packDir, "wiki-seeds");
|
|
27123
|
+
const manifestPath = path46.join(packDir, "pack.json");
|
|
27124
|
+
const identityContextPath = path46.join(packDir, "identity-context.md");
|
|
27125
|
+
if (!existsSync39(objectsPath)) return null;
|
|
26884
27126
|
let customObjects = [];
|
|
26885
27127
|
try {
|
|
26886
27128
|
customObjects = JSON.parse(
|
|
26887
|
-
|
|
27129
|
+
readFileSync30(objectsPath, "utf-8")
|
|
26888
27130
|
);
|
|
26889
27131
|
} catch {
|
|
26890
27132
|
customObjects = [];
|
|
26891
27133
|
}
|
|
26892
27134
|
let triggers = [];
|
|
26893
|
-
if (
|
|
27135
|
+
if (existsSync39(triggersPath)) {
|
|
26894
27136
|
try {
|
|
26895
27137
|
triggers = JSON.parse(
|
|
26896
|
-
|
|
27138
|
+
readFileSync30(triggersPath, "utf-8")
|
|
26897
27139
|
);
|
|
26898
27140
|
} catch {
|
|
26899
27141
|
triggers = [];
|
|
26900
27142
|
}
|
|
26901
27143
|
}
|
|
26902
27144
|
const wikiSeeds = [];
|
|
26903
|
-
if (
|
|
27145
|
+
if (existsSync39(wikiDir)) {
|
|
26904
27146
|
const files = readdirSync12(wikiDir).filter((f) => f.endsWith(".md"));
|
|
26905
27147
|
for (const file of files) {
|
|
26906
|
-
const content =
|
|
27148
|
+
const content = readFileSync30(path46.join(wikiDir, file), "utf-8");
|
|
26907
27149
|
const titleMatch = content.match(/^#\s+(.+)/m);
|
|
26908
27150
|
wikiSeeds.push({
|
|
26909
27151
|
filename: file,
|
|
@@ -26913,17 +27155,17 @@ function loadPack(industry) {
|
|
|
26913
27155
|
}
|
|
26914
27156
|
}
|
|
26915
27157
|
let manifest = {};
|
|
26916
|
-
if (
|
|
27158
|
+
if (existsSync39(manifestPath)) {
|
|
26917
27159
|
try {
|
|
26918
|
-
manifest = JSON.parse(
|
|
27160
|
+
manifest = JSON.parse(readFileSync30(manifestPath, "utf-8"));
|
|
26919
27161
|
} catch {
|
|
26920
27162
|
manifest = {};
|
|
26921
27163
|
}
|
|
26922
27164
|
}
|
|
26923
27165
|
let identityContext = null;
|
|
26924
|
-
if (
|
|
27166
|
+
if (existsSync39(identityContextPath)) {
|
|
26925
27167
|
try {
|
|
26926
|
-
identityContext =
|
|
27168
|
+
identityContext = readFileSync30(identityContextPath, "utf-8");
|
|
26927
27169
|
} catch {
|
|
26928
27170
|
identityContext = null;
|
|
26929
27171
|
}
|
|
@@ -26982,7 +27224,7 @@ var init_starter_packs = __esm({
|
|
|
26982
27224
|
"src/automation/starter-packs/index.ts"() {
|
|
26983
27225
|
"use strict";
|
|
26984
27226
|
init_trigger_engine();
|
|
26985
|
-
__dirname =
|
|
27227
|
+
__dirname = path46.dirname(fileURLToPath5(import.meta.url));
|
|
26986
27228
|
}
|
|
26987
27229
|
});
|
|
26988
27230
|
|
|
@@ -27114,21 +27356,21 @@ All memory, tasks, behaviors, documents, and wiki content belonging to {{company
|
|
|
27114
27356
|
});
|
|
27115
27357
|
|
|
27116
27358
|
// src/lib/client-coo.ts
|
|
27117
|
-
import { existsSync as
|
|
27118
|
-
import
|
|
27359
|
+
import { existsSync as existsSync40, mkdirSync as mkdirSync18, writeFileSync as writeFileSync21 } from "fs";
|
|
27360
|
+
import path47 from "path";
|
|
27119
27361
|
async function provisionClientCOO(vars, opts = {}) {
|
|
27120
|
-
const identityDir = opts.identityDir ??
|
|
27362
|
+
const identityDir = opts.identityDir ?? path47.join(EXE_AI_DIR, "identity");
|
|
27121
27363
|
const rosterPath = opts.employeesPath ?? EMPLOYEES_PATH;
|
|
27122
27364
|
const storeFeedbackBehavior = opts.storeFeedbackBehavior ?? true;
|
|
27123
|
-
const identityPath2 =
|
|
27124
|
-
if (
|
|
27365
|
+
const identityPath2 = path47.join(identityDir, `${vars.agent_name}.md`);
|
|
27366
|
+
if (existsSync40(identityPath2)) {
|
|
27125
27367
|
throw new ClientCOOClobberError(vars.agent_name, identityPath2);
|
|
27126
27368
|
}
|
|
27127
27369
|
const body = renderClientCOOTemplate(vars);
|
|
27128
|
-
if (!
|
|
27129
|
-
|
|
27370
|
+
if (!existsSync40(identityDir)) {
|
|
27371
|
+
mkdirSync18(identityDir, { recursive: true });
|
|
27130
27372
|
}
|
|
27131
|
-
|
|
27373
|
+
writeFileSync21(identityPath2, body, "utf-8");
|
|
27132
27374
|
const employees = await loadEmployees(rosterPath);
|
|
27133
27375
|
const existing = employees.find((e) => e.name === vars.agent_name);
|
|
27134
27376
|
let addedToRoster = false;
|
|
@@ -27180,7 +27422,7 @@ var init_client_coo = __esm({
|
|
|
27180
27422
|
});
|
|
27181
27423
|
|
|
27182
27424
|
// src/mcp/tools/apply-starter-pack.ts
|
|
27183
|
-
import { z as
|
|
27425
|
+
import { z as z69 } from "zod";
|
|
27184
27426
|
function registerApplyStarterPack(server) {
|
|
27185
27427
|
server.registerTool(
|
|
27186
27428
|
"apply_starter_pack",
|
|
@@ -27188,17 +27430,17 @@ function registerApplyStarterPack(server) {
|
|
|
27188
27430
|
title: "Apply Starter Pack",
|
|
27189
27431
|
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.",
|
|
27190
27432
|
inputSchema: {
|
|
27191
|
-
industry:
|
|
27433
|
+
industry: z69.string().describe(
|
|
27192
27434
|
'Industry pack to apply (e.g., "distribution"). Use without args to list available packs.'
|
|
27193
27435
|
),
|
|
27194
|
-
project:
|
|
27195
|
-
agent_name:
|
|
27436
|
+
project: z69.string().describe("Project name to scope the triggers to"),
|
|
27437
|
+
agent_name: z69.string().optional().describe(
|
|
27196
27438
|
"Optional. Lowercase alphanumeric name for the Client COO agent. Required (alongside company_name and founder_name) to provision a COO."
|
|
27197
27439
|
),
|
|
27198
|
-
company_name:
|
|
27440
|
+
company_name: z69.string().optional().describe(
|
|
27199
27441
|
"Optional. The client company the COO serves. Required to provision a COO."
|
|
27200
27442
|
),
|
|
27201
|
-
founder_name:
|
|
27443
|
+
founder_name: z69.string().optional().describe(
|
|
27202
27444
|
"Optional. The founder the COO reports to. Required to provision a COO."
|
|
27203
27445
|
)
|
|
27204
27446
|
}
|
|
@@ -27350,19 +27592,19 @@ var init_apply_starter_pack = __esm({
|
|
|
27350
27592
|
});
|
|
27351
27593
|
|
|
27352
27594
|
// src/mcp/tools/load-skill.ts
|
|
27353
|
-
import { z as
|
|
27354
|
-
import { readFileSync as
|
|
27355
|
-
import
|
|
27356
|
-
import { homedir as
|
|
27595
|
+
import { z as z70 } from "zod";
|
|
27596
|
+
import { readFileSync as readFileSync31, readdirSync as readdirSync13, statSync as statSync9 } from "fs";
|
|
27597
|
+
import path48 from "path";
|
|
27598
|
+
import { homedir as homedir8 } from "os";
|
|
27357
27599
|
function listAvailableSkills() {
|
|
27358
27600
|
try {
|
|
27359
27601
|
const entries = readdirSync13(SKILLS_DIR);
|
|
27360
27602
|
return entries.filter((entry) => {
|
|
27361
27603
|
try {
|
|
27362
|
-
const entryPath =
|
|
27363
|
-
if (!
|
|
27364
|
-
const skillFile =
|
|
27365
|
-
|
|
27604
|
+
const entryPath = path48.join(SKILLS_DIR, entry);
|
|
27605
|
+
if (!statSync9(entryPath).isDirectory()) return false;
|
|
27606
|
+
const skillFile = path48.join(entryPath, "SKILL.md");
|
|
27607
|
+
statSync9(skillFile);
|
|
27366
27608
|
return true;
|
|
27367
27609
|
} catch {
|
|
27368
27610
|
return false;
|
|
@@ -27379,7 +27621,7 @@ function registerLoadSkill(server) {
|
|
|
27379
27621
|
title: "Load Skill",
|
|
27380
27622
|
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.",
|
|
27381
27623
|
inputSchema: {
|
|
27382
|
-
skill_name:
|
|
27624
|
+
skill_name: z70.string().describe(
|
|
27383
27625
|
"Skill to load (e.g. 'seo', 'code-reviewer', 'frontend-design'). Pass 'list' to see all available skills."
|
|
27384
27626
|
)
|
|
27385
27627
|
}
|
|
@@ -27404,10 +27646,10 @@ ${skills.map((s) => `- ${s}`).join("\n")}`
|
|
|
27404
27646
|
}]
|
|
27405
27647
|
};
|
|
27406
27648
|
}
|
|
27407
|
-
const sanitized =
|
|
27408
|
-
const skillFile =
|
|
27649
|
+
const sanitized = path48.basename(skill_name);
|
|
27650
|
+
const skillFile = path48.join(SKILLS_DIR, sanitized, "SKILL.md");
|
|
27409
27651
|
try {
|
|
27410
|
-
const content =
|
|
27652
|
+
const content = readFileSync31(skillFile, "utf-8");
|
|
27411
27653
|
return {
|
|
27412
27654
|
content: [{
|
|
27413
27655
|
type: "text",
|
|
@@ -27436,15 +27678,15 @@ var SKILLS_DIR;
|
|
|
27436
27678
|
var init_load_skill = __esm({
|
|
27437
27679
|
"src/mcp/tools/load-skill.ts"() {
|
|
27438
27680
|
"use strict";
|
|
27439
|
-
SKILLS_DIR =
|
|
27681
|
+
SKILLS_DIR = path48.join(homedir8(), ".claude", "skills");
|
|
27440
27682
|
}
|
|
27441
27683
|
});
|
|
27442
27684
|
|
|
27443
27685
|
// src/lib/orchestration-package.ts
|
|
27444
27686
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
27445
|
-
import { copyFileSync as copyFileSync2, existsSync as
|
|
27687
|
+
import { copyFileSync as copyFileSync2, existsSync as existsSync41, mkdirSync as mkdirSync19, readFileSync as readFileSync32, writeFileSync as writeFileSync22 } from "fs";
|
|
27446
27688
|
import os20 from "os";
|
|
27447
|
-
import
|
|
27689
|
+
import path49 from "path";
|
|
27448
27690
|
function ensureObject(value, label) {
|
|
27449
27691
|
if (value == null || Array.isArray(value) || typeof value !== "object") {
|
|
27450
27692
|
throw new Error(`${label} must be an object`);
|
|
@@ -27503,15 +27745,15 @@ function validateProcedureEntry(value, index) {
|
|
|
27503
27745
|
};
|
|
27504
27746
|
}
|
|
27505
27747
|
function getRosterPath() {
|
|
27506
|
-
return
|
|
27748
|
+
return path49.join(os20.homedir(), EXE_OS_DIRNAME, ROSTER_FILENAME);
|
|
27507
27749
|
}
|
|
27508
27750
|
function getBackupPath() {
|
|
27509
|
-
return
|
|
27751
|
+
return path49.join(os20.homedir(), EXE_OS_DIRNAME, ROSTER_BACKUP_FILENAME);
|
|
27510
27752
|
}
|
|
27511
27753
|
function readRosterFile() {
|
|
27512
27754
|
const rosterPath = getRosterPath();
|
|
27513
|
-
if (!
|
|
27514
|
-
const raw =
|
|
27755
|
+
if (!existsSync41(rosterPath)) return [];
|
|
27756
|
+
const raw = readFileSync32(rosterPath, "utf-8");
|
|
27515
27757
|
const parsed = JSON.parse(raw);
|
|
27516
27758
|
if (!Array.isArray(parsed)) {
|
|
27517
27759
|
throw new Error("Roster file must contain a JSON array");
|
|
@@ -27523,8 +27765,8 @@ function writeRosterFile(roster) {
|
|
|
27523
27765
|
throw new Error("Refusing to write empty roster \u2014 this would delete all employees");
|
|
27524
27766
|
}
|
|
27525
27767
|
const rosterPath = getRosterPath();
|
|
27526
|
-
|
|
27527
|
-
if (
|
|
27768
|
+
mkdirSync19(path49.dirname(rosterPath), { recursive: true });
|
|
27769
|
+
if (existsSync41(rosterPath)) {
|
|
27528
27770
|
const currentRoster = readRosterFile();
|
|
27529
27771
|
if (roster.length < currentRoster.length) {
|
|
27530
27772
|
throw new Error(
|
|
@@ -27533,7 +27775,7 @@ function writeRosterFile(roster) {
|
|
|
27533
27775
|
}
|
|
27534
27776
|
copyFileSync2(rosterPath, getBackupPath());
|
|
27535
27777
|
}
|
|
27536
|
-
|
|
27778
|
+
writeFileSync22(rosterPath, `${JSON.stringify(roster, null, 2)}
|
|
27537
27779
|
`, "utf-8");
|
|
27538
27780
|
}
|
|
27539
27781
|
function buildImportedRosterEntries(roster, timestamp) {
|
|
@@ -27796,9 +28038,9 @@ var init_orchestration_package = __esm({
|
|
|
27796
28038
|
});
|
|
27797
28039
|
|
|
27798
28040
|
// src/mcp/tools/export-orchestration.ts
|
|
27799
|
-
import { mkdirSync as
|
|
27800
|
-
import
|
|
27801
|
-
import { z as
|
|
28041
|
+
import { mkdirSync as mkdirSync20, writeFileSync as writeFileSync23 } from "fs";
|
|
28042
|
+
import path50 from "path";
|
|
28043
|
+
import { z as z71 } from "zod";
|
|
27802
28044
|
function registerExportOrchestration(server) {
|
|
27803
28045
|
server.registerTool(
|
|
27804
28046
|
"export_orchestration",
|
|
@@ -27806,15 +28048,15 @@ function registerExportOrchestration(server) {
|
|
|
27806
28048
|
title: "Export Orchestration",
|
|
27807
28049
|
description: "Export roster, identities, behaviors, and customer procedures to a JSON package.",
|
|
27808
28050
|
inputSchema: {
|
|
27809
|
-
output_path:
|
|
28051
|
+
output_path: z71.string().describe("File path to write the JSON package")
|
|
27810
28052
|
}
|
|
27811
28053
|
},
|
|
27812
28054
|
async ({ output_path }) => {
|
|
27813
28055
|
try {
|
|
27814
28056
|
await initStore();
|
|
27815
28057
|
const pkg = await exportOrchestration(getActiveAgent().agentId);
|
|
27816
|
-
|
|
27817
|
-
|
|
28058
|
+
mkdirSync20(path50.dirname(output_path), { recursive: true });
|
|
28059
|
+
writeFileSync23(output_path, `${JSON.stringify(pkg, null, 2)}
|
|
27818
28060
|
`, "utf-8");
|
|
27819
28061
|
return {
|
|
27820
28062
|
content: [{
|
|
@@ -27844,8 +28086,8 @@ var init_export_orchestration = __esm({
|
|
|
27844
28086
|
});
|
|
27845
28087
|
|
|
27846
28088
|
// src/mcp/tools/import-orchestration.ts
|
|
27847
|
-
import { readFileSync as
|
|
27848
|
-
import { z as
|
|
28089
|
+
import { readFileSync as readFileSync33 } from "fs";
|
|
28090
|
+
import { z as z72 } from "zod";
|
|
27849
28091
|
function registerImportOrchestration(server) {
|
|
27850
28092
|
server.registerTool(
|
|
27851
28093
|
"import_orchestration",
|
|
@@ -27853,8 +28095,8 @@ function registerImportOrchestration(server) {
|
|
|
27853
28095
|
title: "Import Orchestration",
|
|
27854
28096
|
description: "Import roster, identities, behaviors, and procedures from an orchestration package. Restricted to coordinator/founder.",
|
|
27855
28097
|
inputSchema: {
|
|
27856
|
-
package_path:
|
|
27857
|
-
merge_strategy:
|
|
28098
|
+
package_path: z72.string().describe("Path to the orchestration package JSON file"),
|
|
28099
|
+
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")
|
|
27858
28100
|
}
|
|
27859
28101
|
},
|
|
27860
28102
|
async ({ package_path, merge_strategy }) => {
|
|
@@ -27871,7 +28113,7 @@ function registerImportOrchestration(server) {
|
|
|
27871
28113
|
};
|
|
27872
28114
|
}
|
|
27873
28115
|
await initStore();
|
|
27874
|
-
const raw =
|
|
28116
|
+
const raw = readFileSync33(package_path, "utf-8");
|
|
27875
28117
|
const pkg = validatePackage(JSON.parse(raw));
|
|
27876
28118
|
const result2 = await importOrchestration(pkg, merge_strategy);
|
|
27877
28119
|
return {
|
|
@@ -27903,7 +28145,7 @@ var init_import_orchestration = __esm({
|
|
|
27903
28145
|
});
|
|
27904
28146
|
|
|
27905
28147
|
// src/mcp/tools/global-procedure.ts
|
|
27906
|
-
import { z as
|
|
28148
|
+
import { z as z73 } from "zod";
|
|
27907
28149
|
function registerCompanyProcedureTool(server, toolName) {
|
|
27908
28150
|
server.registerTool(
|
|
27909
28151
|
toolName,
|
|
@@ -27911,12 +28153,12 @@ function registerCompanyProcedureTool(server, toolName) {
|
|
|
27911
28153
|
title: "Company Procedure",
|
|
27912
28154
|
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).",
|
|
27913
28155
|
inputSchema: {
|
|
27914
|
-
action:
|
|
27915
|
-
title:
|
|
27916
|
-
content:
|
|
27917
|
-
priority:
|
|
27918
|
-
domain:
|
|
27919
|
-
procedure_id:
|
|
28156
|
+
action: z73.enum(["store", "list", "deactivate"]).describe("Action to perform"),
|
|
28157
|
+
title: z73.string().optional().describe("Short title for the procedure (store)"),
|
|
28158
|
+
content: z73.string().max(500).optional().describe("The procedure content \u2014 clear, actionable instruction (store)"),
|
|
28159
|
+
priority: z73.enum(["p0", "p1", "p2"]).optional().describe("Priority tier. p0 = always (default). p1 = standard. p2 = nice-to-have."),
|
|
28160
|
+
domain: z73.string().optional().describe("Category: workflow, code-style, communication, architecture, testing, security"),
|
|
28161
|
+
procedure_id: z73.string().optional().describe("UUID of the company procedure (deactivate)")
|
|
27920
28162
|
}
|
|
27921
28163
|
},
|
|
27922
28164
|
async ({ action, title, content, priority, domain, procedure_id }) => {
|
|
@@ -28047,7 +28289,7 @@ var init_global_procedure = __esm({
|
|
|
28047
28289
|
});
|
|
28048
28290
|
|
|
28049
28291
|
// src/mcp/tools/config.ts
|
|
28050
|
-
import { z as
|
|
28292
|
+
import { z as z74 } from "zod";
|
|
28051
28293
|
function errorResult8(text3) {
|
|
28052
28294
|
return { content: [{ type: "text", text: text3 }], isError: true };
|
|
28053
28295
|
}
|
|
@@ -28064,6 +28306,7 @@ function buildHandlers5() {
|
|
|
28064
28306
|
registerListAgentSessions(localServer);
|
|
28065
28307
|
registerGetSessionKills(localServer);
|
|
28066
28308
|
registerGetDaemonHealth(localServer);
|
|
28309
|
+
registerMcpPing(localServer);
|
|
28067
28310
|
registerGetAutoWakeStatus(localServer);
|
|
28068
28311
|
registerGetWorkerGate(localServer);
|
|
28069
28312
|
registerRunMemoryAudit(localServer);
|
|
@@ -28092,44 +28335,44 @@ function registerConfig(server) {
|
|
|
28092
28335
|
title: "Config",
|
|
28093
28336
|
description: "Consolidated COO/admin tool for runtime config, system health, licensing, triggers, orchestration import/export, and company procedures.",
|
|
28094
28337
|
inputSchema: {
|
|
28095
|
-
action:
|
|
28096
|
-
agent_id:
|
|
28097
|
-
runtime:
|
|
28098
|
-
model:
|
|
28099
|
-
reasoning_effort:
|
|
28100
|
-
dry_run:
|
|
28101
|
-
fix:
|
|
28102
|
-
verbose:
|
|
28103
|
-
project_name:
|
|
28104
|
-
since:
|
|
28105
|
-
limit:
|
|
28106
|
-
output_path:
|
|
28107
|
-
input_path:
|
|
28108
|
-
strategy:
|
|
28109
|
-
license_key:
|
|
28110
|
-
email:
|
|
28111
|
-
plan:
|
|
28112
|
-
name:
|
|
28113
|
-
event:
|
|
28114
|
-
conditions:
|
|
28115
|
-
actions:
|
|
28116
|
-
enabled:
|
|
28117
|
-
schedule:
|
|
28118
|
-
query:
|
|
28119
|
-
skill_name:
|
|
28120
|
-
pack_name:
|
|
28121
|
-
title:
|
|
28122
|
-
content:
|
|
28123
|
-
priority:
|
|
28124
|
-
domain:
|
|
28125
|
-
procedure_id:
|
|
28126
|
-
subaction:
|
|
28127
|
-
max_clusters:
|
|
28128
|
-
force:
|
|
28129
|
-
cloud_action:
|
|
28130
|
-
confirm_local_db_source_of_truth:
|
|
28131
|
-
domain_name:
|
|
28132
|
-
phase:
|
|
28338
|
+
action: z74.enum(Object.keys(ACTION_TO_TOOL2)).describe("Admin/config operation"),
|
|
28339
|
+
agent_id: z74.string().optional().describe("Agent id for set_agent_config/agent_spend/session queries"),
|
|
28340
|
+
runtime: z74.string().optional().describe("Runtime for set_agent_config"),
|
|
28341
|
+
model: z74.string().optional().describe("Model for set_agent_config"),
|
|
28342
|
+
reasoning_effort: z74.string().optional().describe("Reasoning effort for Codex agents"),
|
|
28343
|
+
dry_run: z74.boolean().optional().describe("Preview without applying where supported"),
|
|
28344
|
+
fix: z74.boolean().optional().describe("Apply fixes for memory_audit where supported"),
|
|
28345
|
+
verbose: z74.boolean().optional().describe("Verbose output where supported"),
|
|
28346
|
+
project_name: z74.string().optional().describe("Project filter/name"),
|
|
28347
|
+
since: z74.string().optional().describe("ISO lower-bound timestamp"),
|
|
28348
|
+
limit: z74.coerce.number().optional().describe("Result limit"),
|
|
28349
|
+
output_path: z74.string().optional().describe("Output path for export/backup"),
|
|
28350
|
+
input_path: z74.string().optional().describe("Input path for import_orchestration"),
|
|
28351
|
+
strategy: z74.enum(["merge", "replace"]).optional().describe("Import strategy; replace must still be additive-only per platform rules"),
|
|
28352
|
+
license_key: z74.string().optional().describe("License key for activation/status"),
|
|
28353
|
+
email: z74.string().optional().describe("Customer email for license creation"),
|
|
28354
|
+
plan: z74.string().optional().describe("License plan"),
|
|
28355
|
+
name: z74.string().optional().describe("Trigger/starter pack/procedure/client name"),
|
|
28356
|
+
event: z74.string().optional().describe("Trigger event"),
|
|
28357
|
+
conditions: z74.array(z74.record(z74.string(), z74.unknown())).optional().describe("Trigger conditions"),
|
|
28358
|
+
actions: z74.array(z74.record(z74.string(), z74.unknown())).optional().describe("Trigger actions"),
|
|
28359
|
+
enabled: z74.boolean().optional().describe("Trigger enabled flag"),
|
|
28360
|
+
schedule: z74.string().optional().describe("Trigger schedule"),
|
|
28361
|
+
query: z74.string().optional().describe("Trigger query or filter"),
|
|
28362
|
+
skill_name: z74.string().optional().describe("Skill name for load_skill"),
|
|
28363
|
+
pack_name: z74.string().optional().describe("Starter pack name"),
|
|
28364
|
+
title: z74.string().optional().describe("Procedure title"),
|
|
28365
|
+
content: z74.string().optional().describe("Procedure content"),
|
|
28366
|
+
priority: z74.enum(["p0", "p1", "p2"]).optional().describe("Procedure priority"),
|
|
28367
|
+
domain: z74.string().optional().describe("Procedure domain"),
|
|
28368
|
+
procedure_id: z74.string().optional().describe("Procedure id for deactivate"),
|
|
28369
|
+
subaction: z74.enum(["store", "list", "deactivate"]).optional().describe("Nested action for company_procedure/global_procedure"),
|
|
28370
|
+
max_clusters: z74.coerce.number().optional().describe("Consolidation max clusters"),
|
|
28371
|
+
force: z74.boolean().optional().describe("Force operation where supported"),
|
|
28372
|
+
cloud_action: z74.enum(["status", "sync", "reupload"]).optional().describe("Nested operation for action=cloud_sync"),
|
|
28373
|
+
confirm_local_db_source_of_truth: z74.string().optional().describe("Required for cloud_action=reupload; must exactly equal LOCAL DB IS SOURCE OF TRUTH"),
|
|
28374
|
+
domain_name: z74.string().optional().describe("Client deployment domain"),
|
|
28375
|
+
phase: z74.enum(["phase_1_coo", "phase_2_executives", "phase_3_parallel_org", "1", "2", "3"]).optional().describe("Orchestration phase for orchestration_phase action")
|
|
28133
28376
|
}
|
|
28134
28377
|
}, async (input, extra) => {
|
|
28135
28378
|
const action = input.action;
|
|
@@ -28161,6 +28404,7 @@ var init_config2 = __esm({
|
|
|
28161
28404
|
init_list_agent_sessions();
|
|
28162
28405
|
init_get_session_kills();
|
|
28163
28406
|
init_get_daemon_health();
|
|
28407
|
+
init_mcp_ping();
|
|
28164
28408
|
init_get_auto_wake_status();
|
|
28165
28409
|
init_get_worker_gate();
|
|
28166
28410
|
init_run_memory_audit();
|
|
@@ -28187,6 +28431,7 @@ var init_config2 = __esm({
|
|
|
28187
28431
|
list_agent_sessions: "list_agent_sessions",
|
|
28188
28432
|
session_kills: "get_session_kills",
|
|
28189
28433
|
daemon_health: "get_daemon_health",
|
|
28434
|
+
mcp_ping: "mcp_ping",
|
|
28190
28435
|
auto_wake_status: "get_auto_wake_status",
|
|
28191
28436
|
worker_gate: "get_worker_gate",
|
|
28192
28437
|
memory_audit: "run_memory_audit",
|
|
@@ -28212,7 +28457,7 @@ var init_config2 = __esm({
|
|
|
28212
28457
|
});
|
|
28213
28458
|
|
|
28214
28459
|
// src/mcp/tools/list-wiki-pages.ts
|
|
28215
|
-
import { z as
|
|
28460
|
+
import { z as z75 } from "zod";
|
|
28216
28461
|
function registerListWikiPages(server) {
|
|
28217
28462
|
server.registerTool(
|
|
28218
28463
|
"list_wiki_pages",
|
|
@@ -28220,8 +28465,8 @@ function registerListWikiPages(server) {
|
|
|
28220
28465
|
title: "List Wiki Pages",
|
|
28221
28466
|
description: "List documents in an exe-wiki workspace. Optionally filter by folder.",
|
|
28222
28467
|
inputSchema: {
|
|
28223
|
-
workspace:
|
|
28224
|
-
folder:
|
|
28468
|
+
workspace: z75.string().describe('Wiki workspace slug (e.g., "hygo")'),
|
|
28469
|
+
folder: z75.string().optional().describe("Filter by folder path")
|
|
28225
28470
|
}
|
|
28226
28471
|
},
|
|
28227
28472
|
async ({ workspace, folder }) => {
|
|
@@ -28317,7 +28562,7 @@ var init_list_wiki_pages = __esm({
|
|
|
28317
28562
|
});
|
|
28318
28563
|
|
|
28319
28564
|
// src/mcp/tools/get-wiki-page.ts
|
|
28320
|
-
import { z as
|
|
28565
|
+
import { z as z76 } from "zod";
|
|
28321
28566
|
function registerGetWikiPage(server) {
|
|
28322
28567
|
server.registerTool(
|
|
28323
28568
|
"get_wiki_page",
|
|
@@ -28325,9 +28570,9 @@ function registerGetWikiPage(server) {
|
|
|
28325
28570
|
title: "Get Wiki Page",
|
|
28326
28571
|
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.",
|
|
28327
28572
|
inputSchema: {
|
|
28328
|
-
workspace:
|
|
28329
|
-
document_id:
|
|
28330
|
-
title:
|
|
28573
|
+
workspace: z76.string().describe('Wiki workspace slug (e.g., "hygo")'),
|
|
28574
|
+
document_id: z76.string().optional().describe("Specific document ID (exact lookup)"),
|
|
28575
|
+
title: z76.string().optional().describe("Search by title (fuzzy match)")
|
|
28331
28576
|
}
|
|
28332
28577
|
},
|
|
28333
28578
|
async ({ workspace, document_id, title }) => {
|
|
@@ -28483,7 +28728,7 @@ var init_get_wiki_page = __esm({
|
|
|
28483
28728
|
});
|
|
28484
28729
|
|
|
28485
28730
|
// src/mcp/tools/wiki.ts
|
|
28486
|
-
import { z as
|
|
28731
|
+
import { z as z77 } from "zod";
|
|
28487
28732
|
function errorResult9(text3) {
|
|
28488
28733
|
return { content: [{ type: "text", text: text3 }], isError: true };
|
|
28489
28734
|
}
|
|
@@ -28509,14 +28754,14 @@ function registerWiki(server) {
|
|
|
28509
28754
|
title: "Wiki",
|
|
28510
28755
|
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.",
|
|
28511
28756
|
inputSchema: {
|
|
28512
|
-
action:
|
|
28513
|
-
workspace:
|
|
28514
|
-
title:
|
|
28515
|
-
content:
|
|
28516
|
-
folder:
|
|
28517
|
-
document_id:
|
|
28518
|
-
mode:
|
|
28519
|
-
section:
|
|
28757
|
+
action: z77.enum(["list", "get"]).describe("Wiki read operation. Writes use raw-data ingestion/projection, not direct MCP writes."),
|
|
28758
|
+
workspace: z77.string().optional().describe("Wiki workspace slug"),
|
|
28759
|
+
title: z77.string().optional().describe("Fuzzy page title lookup for get"),
|
|
28760
|
+
content: z77.string().optional().describe("Reserved; wiki writes use raw-data ingestion/projection"),
|
|
28761
|
+
folder: z77.string().optional().describe("Optional folder path for list"),
|
|
28762
|
+
document_id: z77.string().optional().describe("Document ID for get"),
|
|
28763
|
+
mode: z77.enum(["replace", "append"]).optional().describe("Reserved; direct wiki updates are removed"),
|
|
28764
|
+
section: z77.string().optional().describe("Reserved; direct wiki updates are removed")
|
|
28520
28765
|
}
|
|
28521
28766
|
},
|
|
28522
28767
|
async (input, extra) => {
|
|
@@ -28555,7 +28800,7 @@ var init_wiki = __esm({
|
|
|
28555
28800
|
});
|
|
28556
28801
|
|
|
28557
28802
|
// src/mcp/tools/behavior.ts
|
|
28558
|
-
import { z as
|
|
28803
|
+
import { z as z78 } from "zod";
|
|
28559
28804
|
function rowToBehavior2(r) {
|
|
28560
28805
|
return {
|
|
28561
28806
|
id: String(r.id),
|
|
@@ -28577,13 +28822,13 @@ function registerBehavior(server) {
|
|
|
28577
28822
|
title: "Behavior",
|
|
28578
28823
|
description: "Manage behavioral patterns, corrections, and reusable procedures for employees. Actions: store (create new), list (query existing), deactivate (soft-delete, restricted).",
|
|
28579
28824
|
inputSchema: {
|
|
28580
|
-
action:
|
|
28581
|
-
content:
|
|
28582
|
-
domain:
|
|
28583
|
-
priority:
|
|
28584
|
-
agent_id:
|
|
28585
|
-
project_name:
|
|
28586
|
-
behavior_id:
|
|
28825
|
+
action: z78.enum(["store", "list", "deactivate"]).describe("Action to perform"),
|
|
28826
|
+
content: z78.string().max(500).optional().describe("The behavioral instruction \u2014 one clear sentence (store)"),
|
|
28827
|
+
domain: z78.string().optional().describe("Category: workflow, code-style, tool-use, communication, architecture, testing"),
|
|
28828
|
+
priority: z78.enum(["p0", "p1", "p2"]).optional().describe("Priority tier. p0 = always included. p1 = standard (default). p2 = nice-to-have."),
|
|
28829
|
+
agent_id: z78.string().optional().describe("Employee name. Defaults to current agent. Pass 'all' to list everyone's (list only)."),
|
|
28830
|
+
project_name: z78.string().optional().describe("Defaults to current project. Pass 'global' for a behavior that applies everywhere (store)."),
|
|
28831
|
+
behavior_id: z78.string().optional().describe("UUID of the behavior (deactivate)")
|
|
28587
28832
|
}
|
|
28588
28833
|
},
|
|
28589
28834
|
async ({ action, content, domain, priority, agent_id, project_name, behavior_id }) => {
|
|
@@ -28764,7 +29009,7 @@ var init_behavior = __esm({
|
|
|
28764
29009
|
});
|
|
28765
29010
|
|
|
28766
29011
|
// src/mcp/tools/reminder.ts
|
|
28767
|
-
import { z as
|
|
29012
|
+
import { z as z79 } from "zod";
|
|
28768
29013
|
function registerReminder(server) {
|
|
28769
29014
|
server.registerTool(
|
|
28770
29015
|
"reminder",
|
|
@@ -28772,11 +29017,11 @@ function registerReminder(server) {
|
|
|
28772
29017
|
title: "Reminder",
|
|
28773
29018
|
description: "Manage reminders for the founder. Shown in the boot brief every session. Actions: create (set new), list (view active), complete (mark done).",
|
|
28774
29019
|
inputSchema: {
|
|
28775
|
-
action:
|
|
28776
|
-
text:
|
|
28777
|
-
due_date:
|
|
28778
|
-
reminder_id:
|
|
28779
|
-
include_completed:
|
|
29020
|
+
action: z79.enum(["create", "list", "complete"]).describe("Action to perform"),
|
|
29021
|
+
text: z79.string().optional().describe("What to remind about (create)"),
|
|
29022
|
+
due_date: z79.string().optional().describe("Optional due date \u2014 ISO date (2026-04-01) or null for persistent (create)"),
|
|
29023
|
+
reminder_id: z79.string().optional().describe("Reminder UUID or text substring to match (complete)"),
|
|
29024
|
+
include_completed: z79.boolean().optional().default(false).describe("Include completed reminders (list)")
|
|
28780
29025
|
}
|
|
28781
29026
|
},
|
|
28782
29027
|
async ({ action, text: text3, due_date, reminder_id, include_completed }) => {
|
|
@@ -28835,7 +29080,7 @@ var init_reminder = __esm({
|
|
|
28835
29080
|
});
|
|
28836
29081
|
|
|
28837
29082
|
// src/mcp/tools/store-global-procedure.ts
|
|
28838
|
-
import { z as
|
|
29083
|
+
import { z as z80 } from "zod";
|
|
28839
29084
|
function registerStoreGlobalProcedure(server) {
|
|
28840
29085
|
server.registerTool(
|
|
28841
29086
|
"store_global_procedure",
|
|
@@ -28843,10 +29088,10 @@ function registerStoreGlobalProcedure(server) {
|
|
|
28843
29088
|
title: "Store Company Procedure (use global_procedure instead)",
|
|
28844
29089
|
description: "DEPRECATED \u2014 use global_procedure with action='store'. Create a company procedure (customer-owned Layer 0 rule). RESTRICTED: only coordinator or founder sessions.",
|
|
28845
29090
|
inputSchema: {
|
|
28846
|
-
title:
|
|
28847
|
-
content:
|
|
28848
|
-
priority:
|
|
28849
|
-
domain:
|
|
29091
|
+
title: z80.string().describe("Short title for the procedure"),
|
|
29092
|
+
content: z80.string().max(500).describe("The procedure content \u2014 clear, actionable instruction"),
|
|
29093
|
+
priority: z80.enum(["p0", "p1", "p2"]).optional().describe("Priority tier. p0 = always (default)."),
|
|
29094
|
+
domain: z80.string().optional().describe("Category: workflow, code-style, communication, architecture, testing, security")
|
|
28850
29095
|
}
|
|
28851
29096
|
},
|
|
28852
29097
|
async ({ title, content, priority, domain }) => {
|
|
@@ -28933,7 +29178,7 @@ var init_list_global_procedures = __esm({
|
|
|
28933
29178
|
});
|
|
28934
29179
|
|
|
28935
29180
|
// src/mcp/tools/deactivate-global-procedure.ts
|
|
28936
|
-
import { z as
|
|
29181
|
+
import { z as z81 } from "zod";
|
|
28937
29182
|
function registerDeactivateGlobalProcedure(server) {
|
|
28938
29183
|
server.registerTool(
|
|
28939
29184
|
"deactivate_global_procedure",
|
|
@@ -28941,7 +29186,7 @@ function registerDeactivateGlobalProcedure(server) {
|
|
|
28941
29186
|
title: "Deactivate Company Procedure (use global_procedure instead)",
|
|
28942
29187
|
description: "DEPRECATED \u2014 use global_procedure with action='deactivate'. Soft-delete a company procedure. RESTRICTED: only coordinator or founder sessions.",
|
|
28943
29188
|
inputSchema: {
|
|
28944
|
-
procedure_id:
|
|
29189
|
+
procedure_id: z81.string().describe("UUID of the company procedure to deactivate")
|
|
28945
29190
|
}
|
|
28946
29191
|
},
|
|
28947
29192
|
async ({ procedure_id }) => {
|
|
@@ -29005,7 +29250,7 @@ var init_deactivate_global_procedure = __esm({
|
|
|
29005
29250
|
});
|
|
29006
29251
|
|
|
29007
29252
|
// src/mcp/tools/store-decision.ts
|
|
29008
|
-
import { z as
|
|
29253
|
+
import { z as z82 } from "zod";
|
|
29009
29254
|
import crypto18 from "crypto";
|
|
29010
29255
|
function registerStoreDecision(server) {
|
|
29011
29256
|
server.registerTool(
|
|
@@ -29014,13 +29259,13 @@ function registerStoreDecision(server) {
|
|
|
29014
29259
|
title: "Store Decision",
|
|
29015
29260
|
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.",
|
|
29016
29261
|
inputSchema: {
|
|
29017
|
-
domain:
|
|
29262
|
+
domain: z82.string().describe(
|
|
29018
29263
|
"Domain key, e.g. 'auth-strategy', 'db-migration-approach', 'api-versioning'"
|
|
29019
29264
|
),
|
|
29020
|
-
decision:
|
|
29021
|
-
rationale:
|
|
29022
|
-
supersedes:
|
|
29023
|
-
project_name:
|
|
29265
|
+
decision: z82.string().describe("The decision text \u2014 what was decided"),
|
|
29266
|
+
rationale: z82.string().optional().describe("Why this decision was made \u2014 constraints, trade-offs, context"),
|
|
29267
|
+
supersedes: z82.string().optional().describe("UUID of the decision this supersedes (previous decision for this domain)"),
|
|
29268
|
+
project_name: z82.string().optional().describe("Project name")
|
|
29024
29269
|
}
|
|
29025
29270
|
},
|
|
29026
29271
|
async ({ domain, decision, rationale, supersedes, project_name }) => {
|
|
@@ -29097,7 +29342,7 @@ var init_store_decision = __esm({
|
|
|
29097
29342
|
});
|
|
29098
29343
|
|
|
29099
29344
|
// src/mcp/tools/get-decision.ts
|
|
29100
|
-
import { z as
|
|
29345
|
+
import { z as z83 } from "zod";
|
|
29101
29346
|
function registerGetDecision(server) {
|
|
29102
29347
|
server.registerTool(
|
|
29103
29348
|
"get_decision",
|
|
@@ -29105,7 +29350,7 @@ function registerGetDecision(server) {
|
|
|
29105
29350
|
title: "Get Decision",
|
|
29106
29351
|
description: "Retrieve the latest authoritative decision for a domain. Returns the current active decision and the supersession history.",
|
|
29107
29352
|
inputSchema: {
|
|
29108
|
-
domain:
|
|
29353
|
+
domain: z83.string().describe(
|
|
29109
29354
|
"Domain key to look up, e.g. 'auth-strategy', 'db-migration-approach'"
|
|
29110
29355
|
)
|
|
29111
29356
|
}
|
|
@@ -29175,10 +29420,10 @@ var init_get_decision = __esm({
|
|
|
29175
29420
|
|
|
29176
29421
|
// src/lib/people.ts
|
|
29177
29422
|
import { readFile as readFile5, writeFile as writeFile6, mkdir as mkdir5 } from "fs/promises";
|
|
29178
|
-
import { existsSync as
|
|
29179
|
-
import
|
|
29423
|
+
import { existsSync as existsSync42, readFileSync as readFileSync34 } from "fs";
|
|
29424
|
+
import path51 from "path";
|
|
29180
29425
|
async function loadPeople() {
|
|
29181
|
-
if (!
|
|
29426
|
+
if (!existsSync42(PEOPLE_PATH)) return [];
|
|
29182
29427
|
try {
|
|
29183
29428
|
const raw = await readFile5(PEOPLE_PATH, "utf-8");
|
|
29184
29429
|
return JSON.parse(raw);
|
|
@@ -29187,7 +29432,7 @@ async function loadPeople() {
|
|
|
29187
29432
|
}
|
|
29188
29433
|
}
|
|
29189
29434
|
async function savePeople(people) {
|
|
29190
|
-
await mkdir5(
|
|
29435
|
+
await mkdir5(path51.dirname(PEOPLE_PATH), { recursive: true });
|
|
29191
29436
|
await writeFile6(PEOPLE_PATH, JSON.stringify(people, null, 2) + "\n", "utf-8");
|
|
29192
29437
|
}
|
|
29193
29438
|
async function addPerson(person) {
|
|
@@ -29213,12 +29458,12 @@ var init_people = __esm({
|
|
|
29213
29458
|
"src/lib/people.ts"() {
|
|
29214
29459
|
"use strict";
|
|
29215
29460
|
init_config();
|
|
29216
|
-
PEOPLE_PATH =
|
|
29461
|
+
PEOPLE_PATH = path51.join(EXE_AI_DIR, "people.json");
|
|
29217
29462
|
}
|
|
29218
29463
|
});
|
|
29219
29464
|
|
|
29220
29465
|
// src/mcp/tools/people-roster.ts
|
|
29221
|
-
import { z as
|
|
29466
|
+
import { z as z84 } from "zod";
|
|
29222
29467
|
function registerAddPerson(server) {
|
|
29223
29468
|
server.registerTool(
|
|
29224
29469
|
"add_person",
|
|
@@ -29226,10 +29471,10 @@ function registerAddPerson(server) {
|
|
|
29226
29471
|
title: "Add Person",
|
|
29227
29472
|
description: "Add or update a key human in the people roster. Used for co-founders, partners, customers \u2014 anyone agents need to know about.",
|
|
29228
29473
|
inputSchema: {
|
|
29229
|
-
name:
|
|
29230
|
-
role:
|
|
29231
|
-
relationship:
|
|
29232
|
-
notes:
|
|
29474
|
+
name: z84.string().describe("Person's name"),
|
|
29475
|
+
role: z84.string().describe("Their role (e.g. co-founder, customer, partner)"),
|
|
29476
|
+
relationship: z84.string().describe("Relationship to the organization (e.g. co-founder, early adopter, investor)"),
|
|
29477
|
+
notes: z84.string().optional().describe("Additional context about this person")
|
|
29233
29478
|
}
|
|
29234
29479
|
},
|
|
29235
29480
|
async ({ name, role, relationship, notes }) => {
|
|
@@ -29275,7 +29520,7 @@ function registerGetPerson(server) {
|
|
|
29275
29520
|
title: "Get Person",
|
|
29276
29521
|
description: "Look up a specific person by name from the people roster.",
|
|
29277
29522
|
inputSchema: {
|
|
29278
|
-
name:
|
|
29523
|
+
name: z84.string().describe("Person's name to look up")
|
|
29279
29524
|
}
|
|
29280
29525
|
},
|
|
29281
29526
|
async ({ name }) => {
|
|
@@ -29305,7 +29550,7 @@ var init_people_roster = __esm({
|
|
|
29305
29550
|
});
|
|
29306
29551
|
|
|
29307
29552
|
// src/lib/exe-db-read.ts
|
|
29308
|
-
import
|
|
29553
|
+
import path52 from "path";
|
|
29309
29554
|
import os21 from "os";
|
|
29310
29555
|
import { createRequire as createRequire6 } from "module";
|
|
29311
29556
|
import { pathToFileURL as pathToFileURL6 } from "url";
|
|
@@ -29322,8 +29567,8 @@ async function getExeDbReadClient() {
|
|
|
29322
29567
|
if (!Ctor2) throw new Error(`No PrismaClient export found at ${explicitPath}`);
|
|
29323
29568
|
return new Ctor2();
|
|
29324
29569
|
}
|
|
29325
|
-
const exeDbRoot = process.env.EXE_DB_ROOT ??
|
|
29326
|
-
const req = createRequire6(
|
|
29570
|
+
const exeDbRoot = process.env.EXE_DB_ROOT ?? path52.join(os21.homedir(), "exe-db");
|
|
29571
|
+
const req = createRequire6(path52.join(exeDbRoot, "package.json"));
|
|
29327
29572
|
const entry = req.resolve("@prisma/client");
|
|
29328
29573
|
const mod = await import(pathToFileURL6(entry).href);
|
|
29329
29574
|
const Ctor = mod.PrismaClient ?? mod.default?.PrismaClient;
|
|
@@ -29350,7 +29595,7 @@ var init_exe_db_read = __esm({
|
|
|
29350
29595
|
});
|
|
29351
29596
|
|
|
29352
29597
|
// src/mcp/tools/crm.ts
|
|
29353
|
-
import { z as
|
|
29598
|
+
import { z as z85 } from "zod";
|
|
29354
29599
|
function text(content, isError = false) {
|
|
29355
29600
|
return { content: [{ type: "text", text: content }], ...isError ? { isError: true } : {} };
|
|
29356
29601
|
}
|
|
@@ -29364,12 +29609,12 @@ function registerCrm(server) {
|
|
|
29364
29609
|
title: "CRM",
|
|
29365
29610
|
description: "Read-only CRM access from exe-db crm schema. Actions: list_people, get_person, list_tables, describe_table.",
|
|
29366
29611
|
inputSchema: {
|
|
29367
|
-
action:
|
|
29368
|
-
id:
|
|
29369
|
-
query:
|
|
29370
|
-
table:
|
|
29371
|
-
limit:
|
|
29372
|
-
offset:
|
|
29612
|
+
action: z85.enum(["list_people", "get_person", "list_tables", "describe_table"]).describe("CRM read operation"),
|
|
29613
|
+
id: z85.string().optional().describe("CRM row/person id for get_person"),
|
|
29614
|
+
query: z85.string().optional().describe("Text search for list_people/get_person"),
|
|
29615
|
+
table: z85.string().optional().describe("crm schema table name for describe_table"),
|
|
29616
|
+
limit: z85.coerce.number().int().min(1).max(50).optional().describe("Max rows, capped at 50"),
|
|
29617
|
+
offset: z85.coerce.number().int().min(0).optional().describe("Rows to skip")
|
|
29373
29618
|
}
|
|
29374
29619
|
}, async ({ action, id, query, table, limit, offset }) => {
|
|
29375
29620
|
try {
|
|
@@ -29434,7 +29679,7 @@ var init_crm = __esm({
|
|
|
29434
29679
|
});
|
|
29435
29680
|
|
|
29436
29681
|
// src/mcp/tools/raw-data.ts
|
|
29437
|
-
import { z as
|
|
29682
|
+
import { z as z86 } from "zod";
|
|
29438
29683
|
function text2(content, isError = false) {
|
|
29439
29684
|
return { content: [{ type: "text", text: content }], ...isError ? { isError: true } : {} };
|
|
29440
29685
|
}
|
|
@@ -29443,15 +29688,15 @@ function registerRawData(server) {
|
|
|
29443
29688
|
title: "Raw Data",
|
|
29444
29689
|
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.",
|
|
29445
29690
|
inputSchema: {
|
|
29446
|
-
action:
|
|
29447
|
-
id:
|
|
29448
|
-
source:
|
|
29449
|
-
event_type:
|
|
29450
|
-
query:
|
|
29451
|
-
processed:
|
|
29452
|
-
limit:
|
|
29453
|
-
offset:
|
|
29454
|
-
include_payload:
|
|
29691
|
+
action: z86.enum(["list_sources", "query", "get"]).describe("Raw data read operation"),
|
|
29692
|
+
id: z86.string().optional().describe("raw.raw_events id for action=get"),
|
|
29693
|
+
source: z86.string().optional().describe("Filter by raw source"),
|
|
29694
|
+
event_type: z86.string().optional().describe("Filter by event_type"),
|
|
29695
|
+
query: z86.string().optional().describe("Search payload/metadata text"),
|
|
29696
|
+
processed: z86.boolean().optional().describe("Filter processed_at IS NULL/NOT NULL"),
|
|
29697
|
+
limit: z86.coerce.number().int().min(1).max(50).optional().describe("Max rows, capped at 50"),
|
|
29698
|
+
offset: z86.coerce.number().int().min(0).optional().describe("Rows to skip"),
|
|
29699
|
+
include_payload: z86.boolean().optional().describe("Include full payload JSON. Default false to save tokens.")
|
|
29455
29700
|
}
|
|
29456
29701
|
}, async ({ action, id, source, event_type, query, processed, limit, offset, include_payload }) => {
|
|
29457
29702
|
try {
|
|
@@ -29519,10 +29764,10 @@ var init_raw_data = __esm({
|
|
|
29519
29764
|
});
|
|
29520
29765
|
|
|
29521
29766
|
// src/mcp/tools/create-bug-report.ts
|
|
29522
|
-
import { z as
|
|
29767
|
+
import { z as z87 } from "zod";
|
|
29523
29768
|
import crypto19 from "crypto";
|
|
29524
29769
|
import { mkdir as mkdir6, writeFile as writeFile7 } from "fs/promises";
|
|
29525
|
-
import
|
|
29770
|
+
import path53 from "path";
|
|
29526
29771
|
function slugify2(input) {
|
|
29527
29772
|
return input.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80) || "bug-report";
|
|
29528
29773
|
}
|
|
@@ -29600,22 +29845,22 @@ function registerCreateBugReport(server) {
|
|
|
29600
29845
|
title: "Create Bug Report",
|
|
29601
29846
|
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.",
|
|
29602
29847
|
inputSchema: {
|
|
29603
|
-
title:
|
|
29848
|
+
title: z87.string().min(3).describe("Short descriptive title"),
|
|
29604
29849
|
classification: CLASSIFICATION.describe(
|
|
29605
29850
|
"upstream_bug = platform defect; customer_customization = local preference; emergency_hotfix = temporary local patch; unclear = needs maintainer triage"
|
|
29606
29851
|
),
|
|
29607
29852
|
severity: SEVERITY.default("p2").describe("p0 critical \u2192 p3 low"),
|
|
29608
|
-
summary:
|
|
29609
|
-
customer_impact:
|
|
29610
|
-
reproduction_steps:
|
|
29611
|
-
expected:
|
|
29612
|
-
actual:
|
|
29613
|
-
files_changed:
|
|
29614
|
-
workaround:
|
|
29615
|
-
local_patch_diff:
|
|
29616
|
-
package_version:
|
|
29617
|
-
project_name:
|
|
29618
|
-
send_upstream:
|
|
29853
|
+
summary: z87.string().min(10).describe("What happened and why it matters"),
|
|
29854
|
+
customer_impact: z87.string().optional().describe("How this affects the customer/founder"),
|
|
29855
|
+
reproduction_steps: z87.array(z87.string()).optional().describe("Steps to reproduce"),
|
|
29856
|
+
expected: z87.string().optional().describe("Expected behavior"),
|
|
29857
|
+
actual: z87.string().optional().describe("Actual behavior"),
|
|
29858
|
+
files_changed: z87.array(z87.string()).optional().describe("Files changed or suspected"),
|
|
29859
|
+
workaround: z87.string().optional().describe("Temporary local workaround/hotfix, if any"),
|
|
29860
|
+
local_patch_diff: z87.string().optional().describe("Small local diff or patch summary"),
|
|
29861
|
+
package_version: z87.string().optional().describe("Installed @askexenow/exe-os version"),
|
|
29862
|
+
project_name: z87.string().optional().describe("Project/customer context"),
|
|
29863
|
+
send_upstream: z87.boolean().default(true).describe("Attempt to POST to configured AskExe support endpoint")
|
|
29619
29864
|
}
|
|
29620
29865
|
},
|
|
29621
29866
|
async ({
|
|
@@ -29655,9 +29900,9 @@ function registerCreateBugReport(server) {
|
|
|
29655
29900
|
filesChanged: files_changed,
|
|
29656
29901
|
projectName: project_name
|
|
29657
29902
|
});
|
|
29658
|
-
const outDir =
|
|
29903
|
+
const outDir = path53.join(EXE_AI_DIR, "bug-reports");
|
|
29659
29904
|
await mkdir6(outDir, { recursive: true });
|
|
29660
|
-
const reportPath =
|
|
29905
|
+
const reportPath = path53.join(outDir, `${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}-${slugify2(title)}-${id.slice(0, 8)}.md`);
|
|
29661
29906
|
await writeFile7(reportPath, markdown, "utf-8");
|
|
29662
29907
|
let vector = null;
|
|
29663
29908
|
try {
|
|
@@ -29731,36 +29976,36 @@ var init_create_bug_report = __esm({
|
|
|
29731
29976
|
init_config();
|
|
29732
29977
|
init_license();
|
|
29733
29978
|
init_store();
|
|
29734
|
-
CLASSIFICATION =
|
|
29979
|
+
CLASSIFICATION = z87.enum([
|
|
29735
29980
|
"upstream_bug",
|
|
29736
29981
|
"customer_customization",
|
|
29737
29982
|
"emergency_hotfix",
|
|
29738
29983
|
"unclear"
|
|
29739
29984
|
]);
|
|
29740
|
-
SEVERITY =
|
|
29985
|
+
SEVERITY = z87.enum(["p0", "p1", "p2", "p3"]);
|
|
29741
29986
|
}
|
|
29742
29987
|
});
|
|
29743
29988
|
|
|
29744
29989
|
// src/lib/code-context-index.ts
|
|
29745
29990
|
import crypto20 from "crypto";
|
|
29746
|
-
import
|
|
29747
|
-
import { existsSync as
|
|
29991
|
+
import path54 from "path";
|
|
29992
|
+
import { existsSync as existsSync43, mkdirSync as mkdirSync21, readFileSync as readFileSync35, statSync as statSync10, writeFileSync as writeFileSync24 } from "fs";
|
|
29748
29993
|
import { spawnSync } from "child_process";
|
|
29749
29994
|
function normalizeProjectRoot(projectRoot) {
|
|
29750
|
-
return
|
|
29995
|
+
return path54.resolve(projectRoot || process.cwd());
|
|
29751
29996
|
}
|
|
29752
29997
|
function hashText(text3) {
|
|
29753
29998
|
return crypto20.createHash("sha256").update(text3).digest("hex");
|
|
29754
29999
|
}
|
|
29755
30000
|
function indexDir() {
|
|
29756
|
-
const dir =
|
|
29757
|
-
|
|
30001
|
+
const dir = path54.join(EXE_AI_DIR, "code-context");
|
|
30002
|
+
mkdirSync21(dir, { recursive: true });
|
|
29758
30003
|
return dir;
|
|
29759
30004
|
}
|
|
29760
30005
|
function getCodeContextIndexPath(projectRoot) {
|
|
29761
30006
|
const root = normalizeProjectRoot(projectRoot);
|
|
29762
30007
|
const rootHash = hashText(root).slice(0, 16);
|
|
29763
|
-
return
|
|
30008
|
+
return path54.join(indexDir(), `${rootHash}.json`);
|
|
29764
30009
|
}
|
|
29765
30010
|
function currentBranch(projectRoot) {
|
|
29766
30011
|
const result2 = spawnSync("git", ["branch", "--show-current"], {
|
|
@@ -29772,11 +30017,11 @@ function currentBranch(projectRoot) {
|
|
|
29772
30017
|
return branch || "detached-or-unknown";
|
|
29773
30018
|
}
|
|
29774
30019
|
function shouldIgnore(relPath) {
|
|
29775
|
-
const parts = relPath.split(
|
|
30020
|
+
const parts = relPath.split(path54.sep);
|
|
29776
30021
|
return parts.some((part) => IGNORE_SEGMENTS.has(part));
|
|
29777
30022
|
}
|
|
29778
30023
|
function isCodeFile(relPath) {
|
|
29779
|
-
return CODE_EXTENSIONS.has(
|
|
30024
|
+
return CODE_EXTENSIONS.has(path54.extname(relPath).toLowerCase());
|
|
29780
30025
|
}
|
|
29781
30026
|
function listCodeFiles(projectRoot, maxFiles) {
|
|
29782
30027
|
const git = spawnSync("git", ["ls-files", "*.ts", "*.tsx", "*.js", "*.jsx"], {
|
|
@@ -29818,7 +30063,7 @@ function parseImportPaths2(importText) {
|
|
|
29818
30063
|
}
|
|
29819
30064
|
function resolveImport(fromFile, importPath, allFiles) {
|
|
29820
30065
|
if (!importPath.startsWith(".")) return null;
|
|
29821
|
-
const base =
|
|
30066
|
+
const base = path54.posix.normalize(path54.posix.join(path54.posix.dirname(fromFile.replaceAll(path54.sep, "/")), importPath));
|
|
29822
30067
|
const withoutKnownExt = base.replace(/\.(?:js|jsx|ts|tsx)$/, "");
|
|
29823
30068
|
const candidates = [
|
|
29824
30069
|
base,
|
|
@@ -29830,10 +30075,10 @@ function resolveImport(fromFile, importPath, allFiles) {
|
|
|
29830
30075
|
`${base}.tsx`,
|
|
29831
30076
|
`${base}.js`,
|
|
29832
30077
|
`${base}.jsx`,
|
|
29833
|
-
|
|
29834
|
-
|
|
29835
|
-
|
|
29836
|
-
|
|
30078
|
+
path54.posix.join(base, "index.ts"),
|
|
30079
|
+
path54.posix.join(base, "index.tsx"),
|
|
30080
|
+
path54.posix.join(base, "index.js"),
|
|
30081
|
+
path54.posix.join(base, "index.jsx")
|
|
29837
30082
|
];
|
|
29838
30083
|
return candidates.find((candidate) => allFiles.has(candidate)) ?? null;
|
|
29839
30084
|
}
|
|
@@ -29842,9 +30087,9 @@ function symbolId(filePath, chunk) {
|
|
|
29842
30087
|
}
|
|
29843
30088
|
function loadIndex(projectRoot) {
|
|
29844
30089
|
const file = getCodeContextIndexPath(projectRoot);
|
|
29845
|
-
if (!
|
|
30090
|
+
if (!existsSync43(file)) return null;
|
|
29846
30091
|
try {
|
|
29847
|
-
const parsed = JSON.parse(
|
|
30092
|
+
const parsed = JSON.parse(readFileSync35(file, "utf8"));
|
|
29848
30093
|
if (parsed.version !== INDEX_VERSION || parsed.projectRoot !== projectRoot) return null;
|
|
29849
30094
|
return parsed;
|
|
29850
30095
|
} catch {
|
|
@@ -29852,18 +30097,18 @@ function loadIndex(projectRoot) {
|
|
|
29852
30097
|
}
|
|
29853
30098
|
}
|
|
29854
30099
|
function saveIndex(index) {
|
|
29855
|
-
|
|
30100
|
+
writeFileSync24(getCodeContextIndexPath(index.projectRoot), JSON.stringify(index, null, 2));
|
|
29856
30101
|
}
|
|
29857
30102
|
function buildFileRecord(projectRoot, relPath, allFiles, previous) {
|
|
29858
|
-
const absPath =
|
|
30103
|
+
const absPath = path54.join(projectRoot, relPath);
|
|
29859
30104
|
let stat;
|
|
29860
30105
|
try {
|
|
29861
|
-
stat =
|
|
30106
|
+
stat = statSync10(absPath);
|
|
29862
30107
|
} catch {
|
|
29863
30108
|
return null;
|
|
29864
30109
|
}
|
|
29865
30110
|
if (!stat.isFile()) return null;
|
|
29866
|
-
const source =
|
|
30111
|
+
const source = readFileSync35(absPath, "utf8");
|
|
29867
30112
|
const hash = hashText(source);
|
|
29868
30113
|
if (previous && previous.hash === hash && previous.mtimeMs === stat.mtimeMs && previous.size === stat.size) {
|
|
29869
30114
|
return previous;
|
|
@@ -29900,10 +30145,10 @@ function buildCodeContextIndex(options = {}) {
|
|
|
29900
30145
|
const branch = currentBranch(projectRoot);
|
|
29901
30146
|
const previous = options.force ? null : loadIndex(projectRoot);
|
|
29902
30147
|
const files = listCodeFiles(projectRoot, maxFiles);
|
|
29903
|
-
const allFiles = new Set(files.map((file) => file.replaceAll(
|
|
30148
|
+
const allFiles = new Set(files.map((file) => file.replaceAll(path54.sep, "/")));
|
|
29904
30149
|
const fileRecords = {};
|
|
29905
30150
|
for (const rel of files) {
|
|
29906
|
-
const normalized = rel.replaceAll(
|
|
30151
|
+
const normalized = rel.replaceAll(path54.sep, "/");
|
|
29907
30152
|
const record = buildFileRecord(projectRoot, normalized, allFiles, previous?.files[normalized]);
|
|
29908
30153
|
if (record) fileRecords[normalized] = record;
|
|
29909
30154
|
}
|
|
@@ -29925,11 +30170,11 @@ function loadOrBuildCodeContextIndex(options = {}) {
|
|
|
29925
30170
|
if (loaded) {
|
|
29926
30171
|
const currentFiles = listCodeFiles(projectRoot, options.maxFiles ?? DEFAULT_MAX_FILES);
|
|
29927
30172
|
const unchanged = currentFiles.every((rel) => {
|
|
29928
|
-
const normalized = rel.replaceAll(
|
|
30173
|
+
const normalized = rel.replaceAll(path54.sep, "/");
|
|
29929
30174
|
const existing = loaded.files[normalized];
|
|
29930
30175
|
if (!existing) return false;
|
|
29931
30176
|
try {
|
|
29932
|
-
const stat =
|
|
30177
|
+
const stat = statSync10(path54.join(projectRoot, normalized));
|
|
29933
30178
|
return stat.mtimeMs === existing.mtimeMs && stat.size === existing.size;
|
|
29934
30179
|
} catch {
|
|
29935
30180
|
return false;
|
|
@@ -30032,7 +30277,7 @@ function traceCodeSymbol(symbolName, options = {}) {
|
|
|
30032
30277
|
}
|
|
30033
30278
|
function resolveTargetFile(index, input) {
|
|
30034
30279
|
if (input.filePath) {
|
|
30035
|
-
const normalized = input.filePath.replaceAll(
|
|
30280
|
+
const normalized = input.filePath.replaceAll(path54.sep, "/").replace(/^\.\//, "");
|
|
30036
30281
|
if (index.files[normalized]) return { filePath: normalized, target: normalized };
|
|
30037
30282
|
const suffix = Object.keys(index.files).find((file) => file.endsWith(normalized));
|
|
30038
30283
|
if (suffix) return { filePath: suffix, target: input.filePath };
|
|
@@ -30062,7 +30307,7 @@ function analyzeBlastRadius(input) {
|
|
|
30062
30307
|
}
|
|
30063
30308
|
}
|
|
30064
30309
|
}
|
|
30065
|
-
const targetBase =
|
|
30310
|
+
const targetBase = path54.basename(target.filePath).replace(/\.[^.]+$/, "").toLowerCase();
|
|
30066
30311
|
const symbolLower = input.symbol?.toLowerCase();
|
|
30067
30312
|
const tests = Object.keys(index.files).filter((file) => {
|
|
30068
30313
|
const lower = file.toLowerCase();
|
|
@@ -30109,7 +30354,7 @@ var init_code_context_index = __esm({
|
|
|
30109
30354
|
});
|
|
30110
30355
|
|
|
30111
30356
|
// src/mcp/tools/code-context.ts
|
|
30112
|
-
import { z as
|
|
30357
|
+
import { z as z88 } from "zod";
|
|
30113
30358
|
function errorResult10(text3) {
|
|
30114
30359
|
return { content: [{ type: "text", text: text3 }], isError: true };
|
|
30115
30360
|
}
|
|
@@ -30121,15 +30366,15 @@ function registerCodeContext(server) {
|
|
|
30121
30366
|
title: "Code Context",
|
|
30122
30367
|
description: "Persistent codebase context engine. One consolidated tool to avoid MCP bloat. Actions: index, search, trace, blast_radius, stats.",
|
|
30123
30368
|
inputSchema: {
|
|
30124
|
-
action:
|
|
30125
|
-
project_root:
|
|
30126
|
-
query:
|
|
30127
|
-
symbol:
|
|
30128
|
-
file_path:
|
|
30129
|
-
force:
|
|
30130
|
-
limit:
|
|
30131
|
-
depth:
|
|
30132
|
-
max_files:
|
|
30369
|
+
action: z88.enum(["index", "search", "trace", "blast_radius", "stats"]).describe("Code context operation"),
|
|
30370
|
+
project_root: z88.string().optional().describe("Repository root. Defaults to current working directory."),
|
|
30371
|
+
query: z88.string().optional().describe("Search query for action=search"),
|
|
30372
|
+
symbol: z88.string().optional().describe("Symbol/function/class/type name for trace or blast_radius"),
|
|
30373
|
+
file_path: z88.string().optional().describe("File path for blast_radius"),
|
|
30374
|
+
force: z88.boolean().optional().describe("Force rebuild before answering"),
|
|
30375
|
+
limit: z88.coerce.number().int().min(1).max(100).optional().describe("Max results"),
|
|
30376
|
+
depth: z88.coerce.number().int().min(1).max(5).optional().describe("Dependent traversal depth for blast_radius"),
|
|
30377
|
+
max_files: z88.coerce.number().int().min(1).max(1e4).optional().describe("Max code files to index")
|
|
30133
30378
|
}
|
|
30134
30379
|
}, async ({ action, project_root, query, symbol, file_path, force, limit, depth, max_files }) => {
|
|
30135
30380
|
const opts = { projectRoot: project_root, force, maxFiles: max_files };
|
|
@@ -30172,7 +30417,7 @@ var init_code_context = __esm({
|
|
|
30172
30417
|
});
|
|
30173
30418
|
|
|
30174
30419
|
// src/mcp/tools/support-inbox.ts
|
|
30175
|
-
import { z as
|
|
30420
|
+
import { z as z89 } from "zod";
|
|
30176
30421
|
function adminToken() {
|
|
30177
30422
|
return process.env.ASKEXE_SUPPORT_ADMIN_TOKEN || process.env.EXE_SUPPORT_ADMIN_TOKEN;
|
|
30178
30423
|
}
|
|
@@ -30211,9 +30456,9 @@ function registerListBugReports(server) {
|
|
|
30211
30456
|
title: "List Bug Reports",
|
|
30212
30457
|
description: "AskExe-internal only: list incoming customer bug reports from the support inbox.",
|
|
30213
30458
|
inputSchema: {
|
|
30214
|
-
status:
|
|
30215
|
-
severity:
|
|
30216
|
-
limit:
|
|
30459
|
+
status: z89.enum(["all", "open", "triaged", "fixed", "closed", "wontfix"]).default("open"),
|
|
30460
|
+
severity: z89.enum(["p0", "p1", "p2", "p3"]).optional(),
|
|
30461
|
+
limit: z89.number().int().min(1).max(100).default(25)
|
|
30217
30462
|
}
|
|
30218
30463
|
},
|
|
30219
30464
|
async ({ status, severity, limit }) => {
|
|
@@ -30232,7 +30477,7 @@ function registerGetBugReport(server) {
|
|
|
30232
30477
|
{
|
|
30233
30478
|
title: "Get Bug Report",
|
|
30234
30479
|
description: "AskExe-internal only: fetch one customer bug report with full markdown payload.",
|
|
30235
|
-
inputSchema: { id:
|
|
30480
|
+
inputSchema: { id: z89.string().min(8) }
|
|
30236
30481
|
},
|
|
30237
30482
|
async ({ id }) => {
|
|
30238
30483
|
const data = await requestJson(`${endpoint()}/${encodeURIComponent(id)}`);
|
|
@@ -30247,12 +30492,12 @@ function registerTriageBugReport(server) {
|
|
|
30247
30492
|
title: "Triage Bug Report",
|
|
30248
30493
|
description: "AskExe-internal only: update bug report status and link task/commit/release metadata.",
|
|
30249
30494
|
inputSchema: {
|
|
30250
|
-
id:
|
|
30495
|
+
id: z89.string().min(8),
|
|
30251
30496
|
status: STATUS.optional(),
|
|
30252
|
-
triage_notes:
|
|
30253
|
-
linked_task_id:
|
|
30254
|
-
linked_commit:
|
|
30255
|
-
fixed_version:
|
|
30497
|
+
triage_notes: z89.string().optional(),
|
|
30498
|
+
linked_task_id: z89.string().optional(),
|
|
30499
|
+
linked_commit: z89.string().optional(),
|
|
30500
|
+
fixed_version: z89.string().optional()
|
|
30256
30501
|
}
|
|
30257
30502
|
},
|
|
30258
30503
|
async ({ id, status, triage_notes, linked_task_id, linked_commit, fixed_version }) => {
|
|
@@ -30269,7 +30514,7 @@ var init_support_inbox = __esm({
|
|
|
30269
30514
|
"src/mcp/tools/support-inbox.ts"() {
|
|
30270
30515
|
"use strict";
|
|
30271
30516
|
DEFAULT_ENDPOINT = "https://askexe.com/admin/support/bug-reports";
|
|
30272
|
-
STATUS =
|
|
30517
|
+
STATUS = z89.enum(["open", "triaged", "fixed", "closed", "wontfix"]);
|
|
30273
30518
|
}
|
|
30274
30519
|
});
|
|
30275
30520
|
|
|
@@ -30406,6 +30651,7 @@ var init_tool_gates = __esm({
|
|
|
30406
30651
|
registerDeployClient: "admin",
|
|
30407
30652
|
registerBackupVps: "admin",
|
|
30408
30653
|
registerGetDaemonHealth: "admin",
|
|
30654
|
+
registerMcpPing: "core",
|
|
30409
30655
|
registerGetAutoWakeStatus: "admin",
|
|
30410
30656
|
registerGetWorkerGate: "admin",
|
|
30411
30657
|
registerRunMemoryAudit: "admin",
|
|
@@ -30443,6 +30689,7 @@ var init_tool_gates = __esm({
|
|
|
30443
30689
|
"registerSearchEverything",
|
|
30444
30690
|
"registerGetDecision",
|
|
30445
30691
|
"registerGetIdentity",
|
|
30692
|
+
"registerMcpPing",
|
|
30446
30693
|
"registerListTasks",
|
|
30447
30694
|
"registerGetTask",
|
|
30448
30695
|
"registerListReminders",
|
|
@@ -30605,6 +30852,7 @@ function registerAllTools(server) {
|
|
|
30605
30852
|
if (exposeLegacyConfig) {
|
|
30606
30853
|
gate("registerGetAgentSpend", registerGetAgentSpend);
|
|
30607
30854
|
}
|
|
30855
|
+
gate("registerMcpPing", registerMcpPing);
|
|
30608
30856
|
if (exposeLegacyGraph) {
|
|
30609
30857
|
gate("registerGetGraphStats", registerGetGraphStats);
|
|
30610
30858
|
gate("registerGetEntityNeighbors", registerGetEntityNeighbors);
|
|
@@ -30720,6 +30968,7 @@ var init_register_tools = __esm({
|
|
|
30720
30968
|
init_get_session_kills();
|
|
30721
30969
|
init_list_agent_sessions();
|
|
30722
30970
|
init_get_daemon_health();
|
|
30971
|
+
init_mcp_ping();
|
|
30723
30972
|
init_get_auto_wake_status();
|
|
30724
30973
|
init_get_worker_gate();
|
|
30725
30974
|
init_run_memory_audit();
|
|
@@ -30965,12 +31214,12 @@ __export(task_enforcement_exports, {
|
|
|
30965
31214
|
runTaskEnforcementTick: () => runTaskEnforcementTick,
|
|
30966
31215
|
sendNudge: () => sendNudge
|
|
30967
31216
|
});
|
|
30968
|
-
import { writeFileSync as
|
|
30969
|
-
import
|
|
31217
|
+
import { writeFileSync as writeFileSync25 } from "fs";
|
|
31218
|
+
import path55 from "path";
|
|
30970
31219
|
function writeAuditEntry(entry) {
|
|
30971
31220
|
try {
|
|
30972
31221
|
const line = JSON.stringify(entry) + "\n";
|
|
30973
|
-
|
|
31222
|
+
writeFileSync25(AUDIT_LOG_PATH, line, { flag: "a" });
|
|
30974
31223
|
} catch {
|
|
30975
31224
|
}
|
|
30976
31225
|
}
|
|
@@ -31141,7 +31390,7 @@ var init_task_enforcement = __esm({
|
|
|
31141
31390
|
"What do you need?"
|
|
31142
31391
|
];
|
|
31143
31392
|
MANAGER_ROLES = ["COO", "CTO"];
|
|
31144
|
-
AUDIT_LOG_PATH =
|
|
31393
|
+
AUDIT_LOG_PATH = path55.join(
|
|
31145
31394
|
process.env.HOME ?? process.env.USERPROFILE ?? "/tmp",
|
|
31146
31395
|
".exe-os",
|
|
31147
31396
|
"enforcement-audit.jsonl"
|
|
@@ -31163,12 +31412,12 @@ __export(background_jobs_exports, {
|
|
|
31163
31412
|
reniceCurrentProcess: () => reniceCurrentProcess,
|
|
31164
31413
|
startManagedJob: () => startManagedJob
|
|
31165
31414
|
});
|
|
31166
|
-
import { existsSync as
|
|
31415
|
+
import { existsSync as existsSync44, mkdirSync as mkdirSync22, readFileSync as readFileSync36, writeFileSync as writeFileSync26, unlinkSync as unlinkSync13 } from "fs";
|
|
31167
31416
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
31168
31417
|
import os22 from "os";
|
|
31169
|
-
import
|
|
31418
|
+
import path56 from "path";
|
|
31170
31419
|
function ensureDirs() {
|
|
31171
|
-
|
|
31420
|
+
mkdirSync22(LOCK_DIR, { recursive: true });
|
|
31172
31421
|
}
|
|
31173
31422
|
function now() {
|
|
31174
31423
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -31184,9 +31433,9 @@ function isAlive(pid) {
|
|
|
31184
31433
|
}
|
|
31185
31434
|
function readJobsRaw() {
|
|
31186
31435
|
ensureDirs();
|
|
31187
|
-
if (!
|
|
31436
|
+
if (!existsSync44(JOBS_FILE)) return [];
|
|
31188
31437
|
try {
|
|
31189
|
-
const parsed = JSON.parse(
|
|
31438
|
+
const parsed = JSON.parse(readFileSync36(JOBS_FILE, "utf8"));
|
|
31190
31439
|
return Array.isArray(parsed) ? parsed : [];
|
|
31191
31440
|
} catch {
|
|
31192
31441
|
return [];
|
|
@@ -31196,7 +31445,7 @@ function writeJobsRaw(jobs) {
|
|
|
31196
31445
|
ensureDirs();
|
|
31197
31446
|
const running2 = jobs.filter((j) => j.status === "running");
|
|
31198
31447
|
const rest = jobs.filter((j) => j.status !== "running").slice(-MAX_HISTORY);
|
|
31199
|
-
|
|
31448
|
+
writeFileSync26(JOBS_FILE, JSON.stringify([...rest, ...running2], null, 2) + "\n");
|
|
31200
31449
|
}
|
|
31201
31450
|
function listBackgroundJobs() {
|
|
31202
31451
|
const jobs = readJobsRaw();
|
|
@@ -31212,14 +31461,14 @@ function listBackgroundJobs() {
|
|
|
31212
31461
|
return jobs;
|
|
31213
31462
|
}
|
|
31214
31463
|
function lockPath(type) {
|
|
31215
|
-
return
|
|
31464
|
+
return path56.join(LOCK_DIR, `${type.replace(/[^a-zA-Z0-9_.-]/g, "_")}.lock`);
|
|
31216
31465
|
}
|
|
31217
31466
|
function acquireJobLock(type, ttlMs = DEFAULT_LOCK_TTL_MS) {
|
|
31218
31467
|
ensureDirs();
|
|
31219
31468
|
const file = lockPath(type);
|
|
31220
|
-
if (
|
|
31469
|
+
if (existsSync44(file)) {
|
|
31221
31470
|
try {
|
|
31222
|
-
const lock = JSON.parse(
|
|
31471
|
+
const lock = JSON.parse(readFileSync36(file, "utf8"));
|
|
31223
31472
|
const age = Date.now() - Date.parse(lock.updatedAt ?? "");
|
|
31224
31473
|
if (lock.pid && isAlive(lock.pid) && Number.isFinite(age) && age < ttlMs) return false;
|
|
31225
31474
|
} catch {
|
|
@@ -31230,7 +31479,7 @@ function acquireJobLock(type, ttlMs = DEFAULT_LOCK_TTL_MS) {
|
|
|
31230
31479
|
}
|
|
31231
31480
|
}
|
|
31232
31481
|
try {
|
|
31233
|
-
|
|
31482
|
+
writeFileSync26(file, JSON.stringify({ pid: process.pid, updatedAt: now() }, null, 2) + "\n", { flag: "wx" });
|
|
31234
31483
|
return true;
|
|
31235
31484
|
} catch {
|
|
31236
31485
|
return false;
|
|
@@ -31239,8 +31488,8 @@ function acquireJobLock(type, ttlMs = DEFAULT_LOCK_TTL_MS) {
|
|
|
31239
31488
|
function releaseJobLock(type) {
|
|
31240
31489
|
const file = lockPath(type);
|
|
31241
31490
|
try {
|
|
31242
|
-
if (!
|
|
31243
|
-
const lock = JSON.parse(
|
|
31491
|
+
if (!existsSync44(file)) return;
|
|
31492
|
+
const lock = JSON.parse(readFileSync36(file, "utf8"));
|
|
31244
31493
|
if (lock.pid === process.pid || !lock.pid || !isAlive(lock.pid)) unlinkSync13(file);
|
|
31245
31494
|
} catch {
|
|
31246
31495
|
try {
|
|
@@ -31279,7 +31528,7 @@ function startManagedJob(options) {
|
|
|
31279
31528
|
writeJobsRaw([...jobs, record]);
|
|
31280
31529
|
const file = lockPath(options.type);
|
|
31281
31530
|
try {
|
|
31282
|
-
|
|
31531
|
+
writeFileSync26(file, JSON.stringify({ pid: process.pid, jobId: id, updatedAt: record.updatedAt }, null, 2) + "\n");
|
|
31283
31532
|
} catch {
|
|
31284
31533
|
}
|
|
31285
31534
|
};
|
|
@@ -31439,9 +31688,9 @@ var init_background_jobs = __esm({
|
|
|
31439
31688
|
"src/lib/background-jobs.ts"() {
|
|
31440
31689
|
"use strict";
|
|
31441
31690
|
init_config();
|
|
31442
|
-
JOB_DIR =
|
|
31443
|
-
JOBS_FILE =
|
|
31444
|
-
LOCK_DIR =
|
|
31691
|
+
JOB_DIR = path56.join(EXE_AI_DIR, "jobs");
|
|
31692
|
+
JOBS_FILE = path56.join(JOB_DIR, "jobs.json");
|
|
31693
|
+
LOCK_DIR = path56.join(JOB_DIR, "locks");
|
|
31445
31694
|
DEFAULT_LOCK_TTL_MS = 6 * 60 * 60 * 1e3;
|
|
31446
31695
|
MAX_HISTORY = 200;
|
|
31447
31696
|
}
|
|
@@ -31455,11 +31704,11 @@ __export(update_check_exports, {
|
|
|
31455
31704
|
getRemoteVersion: () => getRemoteVersion
|
|
31456
31705
|
});
|
|
31457
31706
|
import { execSync as execSync15 } from "child_process";
|
|
31458
|
-
import { readFileSync as
|
|
31459
|
-
import
|
|
31707
|
+
import { readFileSync as readFileSync37 } from "fs";
|
|
31708
|
+
import path57 from "path";
|
|
31460
31709
|
function getLocalVersion(packageRoot) {
|
|
31461
|
-
const pkgPath =
|
|
31462
|
-
const pkg = JSON.parse(
|
|
31710
|
+
const pkgPath = path57.join(packageRoot, "package.json");
|
|
31711
|
+
const pkg = JSON.parse(readFileSync37(pkgPath, "utf-8"));
|
|
31463
31712
|
return pkg.version;
|
|
31464
31713
|
}
|
|
31465
31714
|
function getRemoteVersion() {
|
|
@@ -31531,12 +31780,12 @@ __export(device_registry_exports, {
|
|
|
31531
31780
|
});
|
|
31532
31781
|
import crypto22 from "crypto";
|
|
31533
31782
|
import os23 from "os";
|
|
31534
|
-
import { readFileSync as
|
|
31535
|
-
import
|
|
31783
|
+
import { readFileSync as readFileSync38, writeFileSync as writeFileSync27, mkdirSync as mkdirSync23, existsSync as existsSync45 } from "fs";
|
|
31784
|
+
import path58 from "path";
|
|
31536
31785
|
function getDeviceInfo() {
|
|
31537
|
-
if (
|
|
31786
|
+
if (existsSync45(DEVICE_JSON_PATH)) {
|
|
31538
31787
|
try {
|
|
31539
|
-
const raw =
|
|
31788
|
+
const raw = readFileSync38(DEVICE_JSON_PATH, "utf8");
|
|
31540
31789
|
const data = JSON.parse(raw);
|
|
31541
31790
|
if (data.deviceId && data.friendlyName && data.hostname) {
|
|
31542
31791
|
return data;
|
|
@@ -31550,14 +31799,14 @@ function getDeviceInfo() {
|
|
|
31550
31799
|
friendlyName: hostname.replace(/\./g, "-").toLowerCase(),
|
|
31551
31800
|
hostname
|
|
31552
31801
|
};
|
|
31553
|
-
|
|
31554
|
-
|
|
31802
|
+
mkdirSync23(path58.dirname(DEVICE_JSON_PATH), { recursive: true });
|
|
31803
|
+
writeFileSync27(DEVICE_JSON_PATH, JSON.stringify(info, null, 2));
|
|
31555
31804
|
return info;
|
|
31556
31805
|
}
|
|
31557
31806
|
function setFriendlyName(name) {
|
|
31558
31807
|
const info = getDeviceInfo();
|
|
31559
31808
|
info.friendlyName = name;
|
|
31560
|
-
|
|
31809
|
+
writeFileSync27(DEVICE_JSON_PATH, JSON.stringify(info, null, 2));
|
|
31561
31810
|
}
|
|
31562
31811
|
async function resolveTargetDevice(targetAgent, targetProject) {
|
|
31563
31812
|
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
@@ -31591,7 +31840,7 @@ var init_device_registry = __esm({
|
|
|
31591
31840
|
"src/lib/device-registry.ts"() {
|
|
31592
31841
|
"use strict";
|
|
31593
31842
|
init_config();
|
|
31594
|
-
DEVICE_JSON_PATH =
|
|
31843
|
+
DEVICE_JSON_PATH = path58.join(EXE_AI_DIR, "device.json");
|
|
31595
31844
|
}
|
|
31596
31845
|
});
|
|
31597
31846
|
|
|
@@ -31807,8 +32056,8 @@ import os24 from "os";
|
|
|
31807
32056
|
import net2 from "net";
|
|
31808
32057
|
import { createServer as createHttpServer } from "http";
|
|
31809
32058
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
31810
|
-
import {
|
|
31811
|
-
import
|
|
32059
|
+
import { writeFileSync as writeFileSync28, unlinkSync as unlinkSync14, mkdirSync as mkdirSync24, existsSync as existsSync46, readFileSync as readFileSync39, chmodSync as chmodSync2 } from "fs";
|
|
32060
|
+
import path59 from "path";
|
|
31812
32061
|
|
|
31813
32062
|
// src/lib/orchestration-metrics.ts
|
|
31814
32063
|
init_config();
|
|
@@ -31880,8 +32129,9 @@ function initMetrics() {
|
|
|
31880
32129
|
|
|
31881
32130
|
// src/lib/exe-daemon.ts
|
|
31882
32131
|
init_memory_write_governor();
|
|
31883
|
-
|
|
31884
|
-
var
|
|
32132
|
+
init_mcp_transport_health();
|
|
32133
|
+
var SOCKET_PATH2 = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ?? path59.join(EXE_AI_DIR, "exed.sock");
|
|
32134
|
+
var PID_PATH4 = process.env.EXE_DAEMON_PID ?? process.env.EXE_EMBED_PID ?? path59.join(EXE_AI_DIR, "exed.pid");
|
|
31885
32135
|
var MODEL_FILE = "jina-embeddings-v5-small-q4_k_m.gguf";
|
|
31886
32136
|
var IDLE_TIMEOUT_MS2 = parseInt(process.env.EXE_DAEMON_IDLE_TIMEOUT_MS || "0", 10);
|
|
31887
32137
|
var REVIEW_POLL_INTERVAL_MS = 60 * 1e3;
|
|
@@ -31909,8 +32159,8 @@ function enqueue(queue, entry) {
|
|
|
31909
32159
|
queue.push(entry);
|
|
31910
32160
|
}
|
|
31911
32161
|
async function loadModel() {
|
|
31912
|
-
const modelPath =
|
|
31913
|
-
if (!
|
|
32162
|
+
const modelPath = path59.join(MODELS_DIR, MODEL_FILE);
|
|
32163
|
+
if (!existsSync46(modelPath)) {
|
|
31914
32164
|
process.stderr.write(`[exed] No model at ${modelPath} \u2014 running without embeddings (VPS mode).
|
|
31915
32165
|
`);
|
|
31916
32166
|
return;
|
|
@@ -32022,7 +32272,7 @@ async function shutdown() {
|
|
|
32022
32272
|
} catch {
|
|
32023
32273
|
}
|
|
32024
32274
|
try {
|
|
32025
|
-
unlinkSync14(
|
|
32275
|
+
unlinkSync14(PID_PATH4);
|
|
32026
32276
|
} catch {
|
|
32027
32277
|
}
|
|
32028
32278
|
process.stderr.write("[exed] Shutdown complete.\n");
|
|
@@ -32330,17 +32580,17 @@ function startMemoryQueueDrain() {
|
|
|
32330
32580
|
`);
|
|
32331
32581
|
}
|
|
32332
32582
|
function startServer() {
|
|
32333
|
-
|
|
32583
|
+
mkdirSync24(path59.dirname(SOCKET_PATH2), { recursive: true });
|
|
32334
32584
|
try {
|
|
32335
|
-
chmodSync2(
|
|
32585
|
+
chmodSync2(path59.dirname(SOCKET_PATH2), 448);
|
|
32336
32586
|
} catch {
|
|
32337
32587
|
}
|
|
32338
32588
|
_daemonToken = ensureDaemonToken(process.env[DAEMON_TOKEN_ENV2] ?? null);
|
|
32339
32589
|
for (const oldFile of ["embed.sock", "embed.pid"]) {
|
|
32340
|
-
const oldPath =
|
|
32590
|
+
const oldPath = path59.join(path59.dirname(SOCKET_PATH2), oldFile);
|
|
32341
32591
|
try {
|
|
32342
32592
|
if (oldFile.endsWith(".pid")) {
|
|
32343
|
-
const pid = parseInt(
|
|
32593
|
+
const pid = parseInt(readFileSync39(oldPath, "utf8").trim(), 10);
|
|
32344
32594
|
if (pid > 0) try {
|
|
32345
32595
|
process.kill(pid, "SIGKILL");
|
|
32346
32596
|
} catch {
|
|
@@ -32463,11 +32713,38 @@ function startServer() {
|
|
|
32463
32713
|
}
|
|
32464
32714
|
async function startMcpHttpServer() {
|
|
32465
32715
|
try {
|
|
32466
|
-
let
|
|
32716
|
+
let parseDurationMs2 = function(value, fallback, options = {}) {
|
|
32717
|
+
if (!value) return fallback;
|
|
32718
|
+
const parsed = Number.parseInt(value, 10);
|
|
32719
|
+
if (!Number.isFinite(parsed)) return fallback;
|
|
32720
|
+
if (parsed === 0 && options.allowZero) return 0;
|
|
32721
|
+
return parsed > 0 ? parsed : fallback;
|
|
32722
|
+
}, closeMcpSession2 = function(sid, reason) {
|
|
32723
|
+
const transport = transports.get(sid);
|
|
32724
|
+
if (!transport) return;
|
|
32725
|
+
transports.delete(sid);
|
|
32726
|
+
sessionLastSeen.delete(sid);
|
|
32727
|
+
const details = sessionDetails.get(sid);
|
|
32728
|
+
sessionDetails.delete(sid);
|
|
32467
32729
|
try {
|
|
32468
|
-
|
|
32730
|
+
void transport.close();
|
|
32469
32731
|
} catch {
|
|
32470
32732
|
}
|
|
32733
|
+
recordMcpHttpEvent({
|
|
32734
|
+
level: reason === "session_expired" ? "warn" : "info",
|
|
32735
|
+
message: reason,
|
|
32736
|
+
sessionId: sid,
|
|
32737
|
+
agentId: details?.agentId,
|
|
32738
|
+
agentRole: details?.agentRole,
|
|
32739
|
+
runtime: details?.runtime,
|
|
32740
|
+
activeSessions: transports.size
|
|
32741
|
+
});
|
|
32742
|
+
}, sweepStaleMcpSessions2 = function() {
|
|
32743
|
+
if (MCP_SESSION_TTL_MS <= 0) return;
|
|
32744
|
+
const now2 = Date.now();
|
|
32745
|
+
for (const [sid, lastSeen] of sessionLastSeen.entries()) {
|
|
32746
|
+
if (now2 - lastSeen > MCP_SESSION_TTL_MS) closeMcpSession2(sid, "session_expired");
|
|
32747
|
+
}
|
|
32471
32748
|
}, sendJsonRpcError2 = function(res, status, message, extra) {
|
|
32472
32749
|
res.writeHead(status, { "Content-Type": "application/json" });
|
|
32473
32750
|
res.end(JSON.stringify({
|
|
@@ -32475,9 +32752,9 @@ async function startMcpHttpServer() {
|
|
|
32475
32752
|
error: { code: -32e3, message },
|
|
32476
32753
|
id: null
|
|
32477
32754
|
}));
|
|
32478
|
-
|
|
32755
|
+
recordMcpHttpEvent({ level: "warn", message, status, ...extra });
|
|
32479
32756
|
};
|
|
32480
|
-
var
|
|
32757
|
+
var parseDurationMs = parseDurationMs2, closeMcpSession = closeMcpSession2, sweepStaleMcpSessions = sweepStaleMcpSessions2, sendJsonRpcError = sendJsonRpcError2;
|
|
32481
32758
|
const { McpServer } = await import("@modelcontextprotocol/sdk/server/mcp.js");
|
|
32482
32759
|
const { StreamableHTTPServerTransport } = await import("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
32483
32760
|
const { isInitializeRequest } = await import("@modelcontextprotocol/sdk/types.js");
|
|
@@ -32487,7 +32764,12 @@ async function startMcpHttpServer() {
|
|
|
32487
32764
|
await initStore2();
|
|
32488
32765
|
const transports = /* @__PURE__ */ new Map();
|
|
32489
32766
|
const MCP_HTTP_PORT = parseInt(process.env.EXE_MCP_PORT || "48739", 10);
|
|
32490
|
-
const
|
|
32767
|
+
const MCP_SESSION_TTL_MS = parseDurationMs2(process.env.EXE_MCP_SESSION_TTL_MS, 4 * 60 * 60 * 1e3, { allowZero: true });
|
|
32768
|
+
const MCP_SESSION_SWEEP_MS = parseDurationMs2(process.env.EXE_MCP_SESSION_SWEEP_MS, 60 * 1e3);
|
|
32769
|
+
const sessionLastSeen = /* @__PURE__ */ new Map();
|
|
32770
|
+
const sessionDetails = /* @__PURE__ */ new Map();
|
|
32771
|
+
const sessionSweepTimer = setInterval(sweepStaleMcpSessions2, MCP_SESSION_SWEEP_MS);
|
|
32772
|
+
sessionSweepTimer.unref();
|
|
32491
32773
|
const httpServer = createHttpServer(async (req, res) => {
|
|
32492
32774
|
res.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1");
|
|
32493
32775
|
res.setHeader("Access-Control-Allow-Methods", "POST, GET, DELETE, OPTIONS");
|
|
@@ -32498,20 +32780,29 @@ async function startMcpHttpServer() {
|
|
|
32498
32780
|
res.end();
|
|
32499
32781
|
return;
|
|
32500
32782
|
}
|
|
32783
|
+
const url = new URL(req.url || "/", `http://127.0.0.1:${MCP_HTTP_PORT}`);
|
|
32501
32784
|
const authHeader = req.headers.authorization;
|
|
32502
32785
|
if (!authHeader || authHeader !== `Bearer ${_daemonToken}`) {
|
|
32503
|
-
res
|
|
32504
|
-
|
|
32786
|
+
sendJsonRpcError2(res, 401, "Unauthorized: invalid or missing daemon token", {
|
|
32787
|
+
method: req.method,
|
|
32788
|
+
path: url.pathname
|
|
32789
|
+
});
|
|
32505
32790
|
return;
|
|
32506
32791
|
}
|
|
32507
|
-
const url = new URL(req.url || "/", `http://127.0.0.1:${MCP_HTTP_PORT}`);
|
|
32508
32792
|
if (url.pathname !== "/mcp") {
|
|
32509
|
-
res
|
|
32510
|
-
|
|
32793
|
+
sendJsonRpcError2(res, 404, "Not Found: MCP endpoint is /mcp", {
|
|
32794
|
+
method: req.method,
|
|
32795
|
+
path: url.pathname
|
|
32796
|
+
});
|
|
32511
32797
|
return;
|
|
32512
32798
|
}
|
|
32513
32799
|
const agentId = req.headers["x-agent-id"] || "default";
|
|
32514
32800
|
const agentRole = req.headers["x-agent-role"] || "employee";
|
|
32801
|
+
const runtime = inferMcpRuntime({
|
|
32802
|
+
runtimeHeader: req.headers["x-agent-runtime"] || req.headers["x-runtime"],
|
|
32803
|
+
userAgent: req.headers["user-agent"],
|
|
32804
|
+
agentId
|
|
32805
|
+
});
|
|
32515
32806
|
let parsedBody;
|
|
32516
32807
|
try {
|
|
32517
32808
|
const body = await new Promise((resolve) => {
|
|
@@ -32525,6 +32816,9 @@ async function startMcpHttpServer() {
|
|
|
32525
32816
|
} catch (err) {
|
|
32526
32817
|
sendJsonRpcError2(res, 400, "Bad Request: invalid JSON body", {
|
|
32527
32818
|
method: req.method,
|
|
32819
|
+
agentId,
|
|
32820
|
+
agentRole,
|
|
32821
|
+
runtime,
|
|
32528
32822
|
error: err instanceof Error ? err.message : String(err)
|
|
32529
32823
|
});
|
|
32530
32824
|
return;
|
|
@@ -32533,34 +32827,28 @@ async function startMcpHttpServer() {
|
|
|
32533
32827
|
let transport;
|
|
32534
32828
|
if (sessionId && transports.has(sessionId)) {
|
|
32535
32829
|
transport = transports.get(sessionId);
|
|
32830
|
+
sessionLastSeen.set(sessionId, Date.now());
|
|
32536
32831
|
} else if (!sessionId && req.method === "POST" && isInitializeRequest(parsedBody)) {
|
|
32537
32832
|
transport = new StreamableHTTPServerTransport({
|
|
32538
32833
|
sessionIdGenerator: () => randomUUID9(),
|
|
32539
32834
|
onsessioninitialized: (sid) => {
|
|
32540
32835
|
transports.set(sid, transport);
|
|
32541
|
-
|
|
32836
|
+
sessionLastSeen.set(sid, Date.now());
|
|
32837
|
+
sessionDetails.set(sid, { agentId, agentRole, runtime });
|
|
32838
|
+
recordMcpHttpEvent({
|
|
32542
32839
|
level: "info",
|
|
32543
32840
|
message: "session_initialized",
|
|
32544
32841
|
sessionId: sid,
|
|
32545
32842
|
agentId,
|
|
32546
32843
|
agentRole,
|
|
32844
|
+
runtime,
|
|
32547
32845
|
activeSessions: transports.size
|
|
32548
32846
|
});
|
|
32549
32847
|
}
|
|
32550
32848
|
});
|
|
32551
32849
|
transport.onclose = () => {
|
|
32552
32850
|
const sid = Array.from(transports.entries()).find(([, t]) => t === transport)?.[0];
|
|
32553
|
-
if (sid)
|
|
32554
|
-
transports.delete(sid);
|
|
32555
|
-
recordMcpHttpEvent2({
|
|
32556
|
-
level: "info",
|
|
32557
|
-
message: "session_closed",
|
|
32558
|
-
sessionId: sid,
|
|
32559
|
-
agentId,
|
|
32560
|
-
agentRole,
|
|
32561
|
-
activeSessions: transports.size
|
|
32562
|
-
});
|
|
32563
|
-
}
|
|
32851
|
+
if (sid) closeMcpSession2(sid, "session_closed");
|
|
32564
32852
|
};
|
|
32565
32853
|
const sessionMcp = new McpServer({ name: "exe-os", version: "1.3.0" });
|
|
32566
32854
|
registerAllTools2(sessionMcp);
|
|
@@ -32573,30 +32861,56 @@ async function startMcpHttpServer() {
|
|
|
32573
32861
|
sessionId,
|
|
32574
32862
|
agentId,
|
|
32575
32863
|
agentRole,
|
|
32864
|
+
runtime,
|
|
32576
32865
|
activeSessions: transports.size
|
|
32577
32866
|
});
|
|
32578
32867
|
return;
|
|
32579
32868
|
}
|
|
32869
|
+
const startedAt = Date.now();
|
|
32870
|
+
const parsedRequest = parsedBody;
|
|
32871
|
+
const toolName = parsedRequest?.method === "tools/call" ? parsedRequest.params?.name : void 0;
|
|
32580
32872
|
try {
|
|
32581
32873
|
await runWithAgent2({ agentId, agentRole }, async () => {
|
|
32582
32874
|
await transport.handleRequest(req, res, parsedBody);
|
|
32583
32875
|
});
|
|
32584
|
-
|
|
32876
|
+
const latencyMs = Date.now() - startedAt;
|
|
32877
|
+
if (sessionId) sessionLastSeen.set(sessionId, Date.now());
|
|
32878
|
+
recordMcpHttpEvent({
|
|
32585
32879
|
level: "info",
|
|
32586
32880
|
message: "request_ok",
|
|
32587
32881
|
method: req.method,
|
|
32588
32882
|
sessionId: sessionId ?? "new",
|
|
32589
32883
|
agentId,
|
|
32590
|
-
agentRole
|
|
32884
|
+
agentRole,
|
|
32885
|
+
runtime,
|
|
32886
|
+
latencyMs
|
|
32591
32887
|
});
|
|
32888
|
+
if (toolName) {
|
|
32889
|
+
recordMcpHttpEvent({
|
|
32890
|
+
level: "info",
|
|
32891
|
+
message: "tool_call_ok",
|
|
32892
|
+
method: req.method,
|
|
32893
|
+
sessionId,
|
|
32894
|
+
agentId,
|
|
32895
|
+
agentRole,
|
|
32896
|
+
runtime,
|
|
32897
|
+
toolName,
|
|
32898
|
+
toolFamily: getMcpToolFamily(toolName),
|
|
32899
|
+
latencyMs
|
|
32900
|
+
});
|
|
32901
|
+
}
|
|
32592
32902
|
} catch (err) {
|
|
32593
|
-
|
|
32903
|
+
recordMcpHttpEvent({
|
|
32594
32904
|
level: "error",
|
|
32595
32905
|
message: "request_failed",
|
|
32596
32906
|
method: req.method,
|
|
32597
32907
|
sessionId,
|
|
32598
32908
|
agentId,
|
|
32599
32909
|
agentRole,
|
|
32910
|
+
runtime,
|
|
32911
|
+
toolName,
|
|
32912
|
+
toolFamily: getMcpToolFamily(toolName),
|
|
32913
|
+
latencyMs: Date.now() - startedAt,
|
|
32600
32914
|
error: err instanceof Error ? err.message : String(err)
|
|
32601
32915
|
});
|
|
32602
32916
|
if (!res.headersSent) {
|
|
@@ -32604,7 +32918,8 @@ async function startMcpHttpServer() {
|
|
|
32604
32918
|
method: req.method,
|
|
32605
32919
|
sessionId,
|
|
32606
32920
|
agentId,
|
|
32607
|
-
agentRole
|
|
32921
|
+
agentRole,
|
|
32922
|
+
runtime
|
|
32608
32923
|
});
|
|
32609
32924
|
}
|
|
32610
32925
|
}
|
|
@@ -32612,6 +32927,14 @@ async function startMcpHttpServer() {
|
|
|
32612
32927
|
httpServer.listen(MCP_HTTP_PORT, "127.0.0.1", () => {
|
|
32613
32928
|
process.stderr.write(`[exed] MCP HTTP listening on 127.0.0.1:${MCP_HTTP_PORT}
|
|
32614
32929
|
`);
|
|
32930
|
+
recordMcpHttpEvent({
|
|
32931
|
+
level: "info",
|
|
32932
|
+
message: "server_started",
|
|
32933
|
+
activeSessions: transports.size
|
|
32934
|
+
});
|
|
32935
|
+
});
|
|
32936
|
+
httpServer.on("close", () => {
|
|
32937
|
+
clearInterval(sessionSweepTimer);
|
|
32615
32938
|
});
|
|
32616
32939
|
httpServer.on("error", (err) => {
|
|
32617
32940
|
if (err.code === "EADDRINUSE") {
|
|
@@ -32892,7 +33215,7 @@ function startGraphExtraction() {
|
|
|
32892
33215
|
`);
|
|
32893
33216
|
}
|
|
32894
33217
|
var AGENT_STATS_INTERVAL_MS = 60 * 1e3;
|
|
32895
|
-
var AGENT_STATS_PATH =
|
|
33218
|
+
var AGENT_STATS_PATH = path59.join(EXE_AI_DIR, "agent-stats.json");
|
|
32896
33219
|
async function writeAgentStats() {
|
|
32897
33220
|
fired("agent_stats");
|
|
32898
33221
|
if (!await ensureStoreForPolling()) return;
|
|
@@ -32952,7 +33275,7 @@ async function writeAgentStats() {
|
|
|
32952
33275
|
pid: process.pid
|
|
32953
33276
|
}
|
|
32954
33277
|
};
|
|
32955
|
-
|
|
33278
|
+
writeFileSync28(AGENT_STATS_PATH, JSON.stringify(stats, null, 2), "utf8");
|
|
32956
33279
|
} catch (err) {
|
|
32957
33280
|
process.stderr.write(`[exed] Agent stats error: ${err instanceof Error ? err.message : String(err)}
|
|
32958
33281
|
`);
|
|
@@ -33069,12 +33392,12 @@ function startIntercomQueueDrain() {
|
|
|
33069
33392
|
const hasInProgressTask = (session) => {
|
|
33070
33393
|
try {
|
|
33071
33394
|
const { baseAgentName: ban } = (init_employees(), __toCommonJS(employees_exports));
|
|
33072
|
-
const
|
|
33073
|
-
const { existsSync:
|
|
33395
|
+
const path60 = __require("path");
|
|
33396
|
+
const { existsSync: existsSync47 } = __require("fs");
|
|
33074
33397
|
const os25 = __require("os");
|
|
33075
33398
|
const agent = ban(session.split("-")[0] ?? session);
|
|
33076
|
-
const markerPath =
|
|
33077
|
-
return
|
|
33399
|
+
const markerPath = path60.join(os25.homedir(), ".exe-os", "session-cache", `current-task-${agent}.json`);
|
|
33400
|
+
return existsSync47(markerPath);
|
|
33078
33401
|
} catch {
|
|
33079
33402
|
return false;
|
|
33080
33403
|
}
|
|
@@ -33263,12 +33586,12 @@ process.on("SIGINT", () => void shutdown());
|
|
|
33263
33586
|
process.on("SIGTERM", () => void shutdown());
|
|
33264
33587
|
function checkExistingDaemon() {
|
|
33265
33588
|
try {
|
|
33266
|
-
if (!
|
|
33267
|
-
const pid = parseInt(
|
|
33589
|
+
if (!existsSync46(PID_PATH4)) return false;
|
|
33590
|
+
const pid = parseInt(readFileSync39(PID_PATH4, "utf8").trim(), 10);
|
|
33268
33591
|
if (!pid || isNaN(pid)) return false;
|
|
33269
33592
|
if (pid === process.pid) {
|
|
33270
33593
|
try {
|
|
33271
|
-
unlinkSync14(
|
|
33594
|
+
unlinkSync14(PID_PATH4);
|
|
33272
33595
|
} catch {
|
|
33273
33596
|
}
|
|
33274
33597
|
return false;
|
|
@@ -33284,7 +33607,7 @@ function checkExistingDaemon() {
|
|
|
33284
33607
|
return true;
|
|
33285
33608
|
}
|
|
33286
33609
|
try {
|
|
33287
|
-
unlinkSync14(
|
|
33610
|
+
unlinkSync14(PID_PATH4);
|
|
33288
33611
|
} catch {
|
|
33289
33612
|
}
|
|
33290
33613
|
return false;
|
|
@@ -33341,9 +33664,9 @@ function startAutoUpdateCheck() {
|
|
|
33341
33664
|
if (checkExistingDaemon()) {
|
|
33342
33665
|
process.exit(0);
|
|
33343
33666
|
}
|
|
33344
|
-
|
|
33667
|
+
writeFileSync28(PID_PATH4, String(process.pid));
|
|
33345
33668
|
try {
|
|
33346
|
-
chmodSync2(
|
|
33669
|
+
chmodSync2(PID_PATH4, 384);
|
|
33347
33670
|
} catch {
|
|
33348
33671
|
}
|
|
33349
33672
|
process.env.EXE_IS_DAEMON = "1";
|
|
@@ -33469,7 +33792,7 @@ try {
|
|
|
33469
33792
|
} catch {
|
|
33470
33793
|
}
|
|
33471
33794
|
try {
|
|
33472
|
-
unlinkSync14(
|
|
33795
|
+
unlinkSync14(PID_PATH4);
|
|
33473
33796
|
} catch {
|
|
33474
33797
|
}
|
|
33475
33798
|
process.exit(1);
|