@askexenow/exe-os 0.9.78 → 0.9.80
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/agentic-ontology-backfill.js +2 -2
- package/dist/bin/agentic-reflection-backfill.js +2 -2
- package/dist/bin/agentic-semantic-label.js +2 -2
- package/dist/bin/backfill-conversations.js +2 -2
- package/dist/bin/backfill-responses.js +2 -2
- package/dist/bin/backfill-vectors.js +2 -2
- package/dist/bin/bulk-sync-postgres.js +2 -2
- package/dist/bin/cleanup-stale-review-tasks.js +2 -2
- package/dist/bin/cli.js +116 -37
- package/dist/bin/customer-readiness.js +4 -0
- package/dist/bin/exe-agent.js +2 -2
- package/dist/bin/exe-assign.js +2 -2
- package/dist/bin/exe-boot.js +2 -2
- package/dist/bin/exe-call.js +2 -2
- package/dist/bin/exe-cloud.js +2 -2
- package/dist/bin/exe-dispatch.js +2 -2
- package/dist/bin/exe-doctor.js +2 -2
- package/dist/bin/exe-export-behaviors.js +2 -2
- package/dist/bin/exe-forget.js +2 -2
- package/dist/bin/exe-gateway.js +2 -2
- package/dist/bin/exe-heartbeat.js +2 -2
- package/dist/bin/exe-kill.js +2 -2
- package/dist/bin/exe-launch-agent.js +2 -2
- package/dist/bin/exe-new-employee.js +2 -2
- package/dist/bin/exe-pending-messages.js +2 -2
- package/dist/bin/exe-pending-notifications.js +2 -2
- package/dist/bin/exe-pending-reviews.js +2 -2
- package/dist/bin/exe-rename.js +2 -2
- package/dist/bin/exe-review.js +2 -2
- package/dist/bin/exe-search.js +2 -2
- package/dist/bin/exe-session-cleanup.js +2 -2
- package/dist/bin/exe-start-codex.js +2 -2
- package/dist/bin/exe-start-opencode.js +2 -2
- package/dist/bin/exe-status.js +2 -2
- package/dist/bin/exe-support.js +110 -31
- package/dist/bin/exe-team.js +2 -2
- package/dist/bin/git-sweep.js +2 -2
- package/dist/bin/graph-backfill.js +2 -2
- package/dist/bin/graph-export.js +2 -2
- package/dist/bin/intercom-check.js +2 -2
- package/dist/bin/scan-tasks.js +2 -2
- package/dist/bin/setup.js +2 -2
- package/dist/bin/shard-migrate.js +2 -2
- package/dist/gateway/index.js +2 -2
- package/dist/hooks/bug-report-worker.js +2 -2
- package/dist/hooks/codex-stop-task-finalizer.js +2 -2
- package/dist/hooks/commit-complete.js +2 -2
- package/dist/hooks/error-recall.js +2 -2
- package/dist/hooks/ingest.js +2 -2
- package/dist/hooks/instructions-loaded.js +2 -2
- package/dist/hooks/notification.js +2 -2
- package/dist/hooks/post-compact.js +2 -2
- package/dist/hooks/post-tool-combined.js +2 -2
- package/dist/hooks/pre-compact.js +2 -2
- package/dist/hooks/pre-tool-use.js +2 -2
- package/dist/hooks/prompt-submit.js +2 -2
- package/dist/hooks/session-end.js +2 -2
- package/dist/hooks/session-start.js +2 -2
- package/dist/hooks/stop.js +2 -2
- package/dist/hooks/subagent-stop.js +2 -2
- package/dist/hooks/summary-worker.js +2 -2
- package/dist/index.js +2 -2
- package/dist/lib/employee-templates.js +2 -2
- package/dist/lib/exe-daemon.js +431 -140
- package/dist/lib/hybrid-search.js +2 -2
- package/dist/lib/schedules.js +2 -2
- package/dist/lib/store.js +2 -2
- package/dist/mcp/server.js +368 -88
- package/dist/runtime/index.js +2 -2
- package/dist/tui/App.js +2 -2
- package/package.json +1 -1
package/dist/lib/exe-daemon.js
CHANGED
|
@@ -5348,8 +5348,8 @@ function deriveMachineKey() {
|
|
|
5348
5348
|
}
|
|
5349
5349
|
function readMachineId() {
|
|
5350
5350
|
try {
|
|
5351
|
-
const { readFileSync:
|
|
5352
|
-
return
|
|
5351
|
+
const { readFileSync: readFileSync41 } = __require("fs");
|
|
5352
|
+
return readFileSync41("/etc/machine-id", "utf-8").trim();
|
|
5353
5353
|
} catch {
|
|
5354
5354
|
return "";
|
|
5355
5355
|
}
|
|
@@ -5799,7 +5799,7 @@ var init_platform_procedures = __esm({
|
|
|
5799
5799
|
title: "Customer patch triage \u2014 upstream bug vs customization",
|
|
5800
5800
|
domain: "support",
|
|
5801
5801
|
priority: "p0",
|
|
5802
|
-
content: "When an agent encounters a suspected Exe OS bug, update breakage, MCP/tool failure, installer issue, memory/orchestration defect, or customer-local patch need, it MUST use create_bug_report. Do this before or alongside any local workaround so the report reaches AskExe support directly via the customer's license. Do NOT ask the founder for permission to file a required bug report. If create_bug_report is deferred/lazy-loaded, load it and call it. If it is unavailable in the live MCP surface, report 'create_bug_report unavailable in this session' and save a local report in exe/output \u2014 never claim the tool does not exist unless the live MCP surface was checked. If upstream delivery fails,
|
|
5802
|
+
content: "When an agent encounters a suspected Exe OS bug, update breakage, MCP/tool failure, installer issue, memory/orchestration defect, or customer-local patch need, it MUST use create_bug_report. Do this before or alongside any local workaround so the report reaches AskExe support directly via the customer's license. Do NOT ask the founder for permission to file a required bug report. If create_bug_report is deferred/lazy-loaded, load it and call it. If it is unavailable in the live MCP surface, report 'create_bug_report unavailable in this session' and save a local report in exe/output \u2014 never claim the tool does not exist unless the live MCP surface was checked. If upstream delivery fails, call support_test (MCP) and include its result in the local report so AskExe can distinguish customer setup, license provisioning, and server intake issues; only ask the founder to run `exe-os support test` if MCP is disconnected/unavailable. Classify first: upstream_bug = reproducible exe-os/platform defect; customer_customization = identity, behavior, procedure, config, branding, workflow preference that belongs in customer-owned layers; emergency_hotfix = temporary local patch. For upstream bugs/emergency hotfixes include version, repro steps, expected/actual, files changed, workaround, and local diff summary. Avoid permanent platform-code patches unless founder approves; if a hotfix is unavoidable, document it in the bug report and re-check after npm update."
|
|
5803
5803
|
},
|
|
5804
5804
|
// --- Operations ---
|
|
5805
5805
|
{
|
|
@@ -5881,7 +5881,7 @@ var init_platform_procedures = __esm({
|
|
|
5881
5881
|
title: "MCP tools \u2014 identity, behavior, and decisions",
|
|
5882
5882
|
domain: "tool-use",
|
|
5883
5883
|
priority: "p1",
|
|
5884
|
-
content: "get_identity: read an agent's exe.md (Layer 1 identity). update_identity: write an agent's exe.md. Identity > behavior \u2014 use for permanent rules. store_behavior: record a correction or pattern for an agent (Layer 2 expertise). list_behaviors: view an agent's active behaviors. deactivate_behavior: soft-delete a stale or conflicting behavior. store_decision: record an ADR (architectural decision record). get_decision: retrieve a past decision by query. create_bug_report: customer-facing bug/support intake; use whenever an Exe OS bug or emergency hotfix is encountered so the report reaches AskExe directly. Customers only get report access; internal list/get/triage support tools are AskExe-only. If a customer-side agent cannot send upstream,
|
|
5884
|
+
content: "get_identity: read an agent's exe.md (Layer 1 identity). update_identity: write an agent's exe.md. Identity > behavior \u2014 use for permanent rules. store_behavior: record a correction or pattern for an agent (Layer 2 expertise). list_behaviors: view an agent's active behaviors. deactivate_behavior: soft-delete a stale or conflicting behavior. store_decision: record an ADR (architectural decision record). get_decision: retrieve a past decision by query. create_bug_report: customer-facing bug/support intake; use whenever an Exe OS bug or emergency hotfix is encountered so the report reaches AskExe directly. support_health: check local support readiness and AskExe support server health without filing a report. support_test: file a safe end-to-end smoke report. Customers only get report/test access; internal list/get/triage support tools are AskExe-only. If a customer-side agent cannot send upstream, call support_test first; only fall back to the terminal command `exe-os support test` when MCP is disconnected."
|
|
5885
5885
|
},
|
|
5886
5886
|
{
|
|
5887
5887
|
title: "MCP tools \u2014 communication and messaging",
|
|
@@ -7175,8 +7175,8 @@ async function embedDirect(text3) {
|
|
|
7175
7175
|
const llamaCpp = await import("node-llama-cpp");
|
|
7176
7176
|
const { MODELS_DIR: MODELS_DIR2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
7177
7177
|
const { existsSync: existsSync47 } = await import("fs");
|
|
7178
|
-
const
|
|
7179
|
-
const modelPath =
|
|
7178
|
+
const path61 = await import("path");
|
|
7179
|
+
const modelPath = path61.join(MODELS_DIR2, "jina-embeddings-v5-small-q4_k_m.gguf");
|
|
7180
7180
|
if (!existsSync47(modelPath)) {
|
|
7181
7181
|
throw new Error(`Embedding model not found at ${modelPath}. Run '/exe-setup' to download it.`);
|
|
7182
7182
|
}
|
|
@@ -8268,10 +8268,10 @@ async function hybridSearch(queryText, agentId, options) {
|
|
|
8268
8268
|
};
|
|
8269
8269
|
try {
|
|
8270
8270
|
const fs = await import("fs");
|
|
8271
|
-
const
|
|
8271
|
+
const path61 = await import("path");
|
|
8272
8272
|
const os25 = await import("os");
|
|
8273
|
-
const logPath =
|
|
8274
|
-
fs.mkdirSync(
|
|
8273
|
+
const logPath = path61.join(os25.homedir(), ".exe-os", "search-quality.jsonl");
|
|
8274
|
+
fs.mkdirSync(path61.dirname(logPath), { recursive: true });
|
|
8275
8275
|
fs.appendFileSync(logPath, JSON.stringify(logEntry) + "\n");
|
|
8276
8276
|
} catch {
|
|
8277
8277
|
}
|
|
@@ -9904,8 +9904,8 @@ __export(wiki_client_exports, {
|
|
|
9904
9904
|
listDocuments: () => listDocuments,
|
|
9905
9905
|
listWorkspaces: () => listWorkspaces
|
|
9906
9906
|
});
|
|
9907
|
-
async function wikiFetch(config2,
|
|
9908
|
-
const url = `${config2.baseUrl}/api/v1${
|
|
9907
|
+
async function wikiFetch(config2, path61, method = "GET", body) {
|
|
9908
|
+
const url = `${config2.baseUrl}/api/v1${path61}`;
|
|
9909
9909
|
const headers = {
|
|
9910
9910
|
Authorization: `Bearer ${config2.apiKey}`,
|
|
9911
9911
|
"Content-Type": "application/json"
|
|
@@ -9938,7 +9938,7 @@ async function wikiFetch(config2, path60, method = "GET", body) {
|
|
|
9938
9938
|
}
|
|
9939
9939
|
}
|
|
9940
9940
|
if (!response.ok) {
|
|
9941
|
-
throw new Error(`Wiki API ${method} ${
|
|
9941
|
+
throw new Error(`Wiki API ${method} ${path61}: ${response.status} ${response.statusText}`);
|
|
9942
9942
|
}
|
|
9943
9943
|
return response.json();
|
|
9944
9944
|
} finally {
|
|
@@ -15516,7 +15516,7 @@ function registerCreateTask(server) {
|
|
|
15516
15516
|
skipDispatch: true
|
|
15517
15517
|
});
|
|
15518
15518
|
try {
|
|
15519
|
-
const { existsSync: existsSync47, mkdirSync:
|
|
15519
|
+
const { existsSync: existsSync47, mkdirSync: mkdirSync26, writeFileSync: writeFileSync30 } = await import("fs");
|
|
15520
15520
|
const { identityPath: identityPath2 } = await Promise.resolve().then(() => (init_identity(), identity_exports));
|
|
15521
15521
|
const idPath = identityPath2(assigned_to);
|
|
15522
15522
|
if (!existsSync47(idPath)) {
|
|
@@ -15528,8 +15528,8 @@ function registerCreateTask(server) {
|
|
|
15528
15528
|
const template = getTemplateForTitle2(emp.role);
|
|
15529
15529
|
if (template) {
|
|
15530
15530
|
const dir = (await import("path")).dirname(idPath);
|
|
15531
|
-
if (!existsSync47(dir))
|
|
15532
|
-
|
|
15531
|
+
if (!existsSync47(dir)) mkdirSync26(dir, { recursive: true });
|
|
15532
|
+
writeFileSync30(idPath, template.replace(/^agent_id: \w+/m, `agent_id: ${assigned_to}`), "utf-8");
|
|
15533
15533
|
}
|
|
15534
15534
|
}
|
|
15535
15535
|
}
|
|
@@ -19025,12 +19025,12 @@ function registerExportGraph(server) {
|
|
|
19025
19025
|
}
|
|
19026
19026
|
const html = await exportGraphHTML(client);
|
|
19027
19027
|
const fs = await import("fs");
|
|
19028
|
-
const
|
|
19028
|
+
const path61 = await import("path");
|
|
19029
19029
|
const os25 = await import("os");
|
|
19030
|
-
const outDir =
|
|
19030
|
+
const outDir = path61.join(os25.homedir(), ".exe-os", "exports");
|
|
19031
19031
|
fs.mkdirSync(outDir, { recursive: true });
|
|
19032
19032
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
19033
|
-
const filePath =
|
|
19033
|
+
const filePath = path61.join(outDir, `graph-${timestamp}.html`);
|
|
19034
19034
|
fs.writeFileSync(filePath, html, "utf-8");
|
|
19035
19035
|
return {
|
|
19036
19036
|
content: [
|
|
@@ -26115,9 +26115,9 @@ var init_hostinger_api = __esm({
|
|
|
26115
26115
|
}
|
|
26116
26116
|
this.lastRequestTime = Date.now();
|
|
26117
26117
|
}
|
|
26118
|
-
async request(method,
|
|
26118
|
+
async request(method, path61, body) {
|
|
26119
26119
|
await this.rateLimit();
|
|
26120
|
-
const url = `${this.baseUrl}${
|
|
26120
|
+
const url = `${this.baseUrl}${path61}`;
|
|
26121
26121
|
const headers = {
|
|
26122
26122
|
Authorization: `Bearer ${this.apiKey}`,
|
|
26123
26123
|
"Content-Type": "application/json",
|
|
@@ -26186,8 +26186,8 @@ async function requestCloudflare(cfApiToken, zoneId, options) {
|
|
|
26186
26186
|
}
|
|
26187
26187
|
return envelope.result;
|
|
26188
26188
|
}
|
|
26189
|
-
function buildUrl(zoneId,
|
|
26190
|
-
const normalizedPath =
|
|
26189
|
+
function buildUrl(zoneId, path61 = "/dns_records", query) {
|
|
26190
|
+
const normalizedPath = path61.startsWith("/") ? path61 : `/${path61}`;
|
|
26191
26191
|
const url = new URL(
|
|
26192
26192
|
`${CLOUDFLARE_API_BASE_URL}/zones/${zoneId}${normalizedPath}`
|
|
26193
26193
|
);
|
|
@@ -30073,8 +30073,296 @@ var init_create_bug_report = __esm({
|
|
|
30073
30073
|
}
|
|
30074
30074
|
});
|
|
30075
30075
|
|
|
30076
|
-
// src/
|
|
30076
|
+
// src/bin/exe-support.ts
|
|
30077
|
+
import { mkdirSync as mkdirSync21, readFileSync as readFileSync35, unlinkSync as unlinkSync13, writeFileSync as writeFileSync24 } from "fs";
|
|
30078
|
+
import path54 from "path";
|
|
30077
30079
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
30080
|
+
async function runHealth() {
|
|
30081
|
+
const checks = [];
|
|
30082
|
+
const endpoints = await resolveEndpoints();
|
|
30083
|
+
checks.push(checkLocalWrite());
|
|
30084
|
+
checks.push({
|
|
30085
|
+
check: "license_key_present",
|
|
30086
|
+
level: loadLicense() ? "pass" : "fail",
|
|
30087
|
+
detail: loadLicense() ? "license.key found" : "missing ~/.exe-os/license.key; run exe-os setup or exe-os cloud setup",
|
|
30088
|
+
next: loadLicense() ? void 0 : "Run `exe-os setup` or ask AskExe for the customer license key."
|
|
30089
|
+
});
|
|
30090
|
+
checks.push({
|
|
30091
|
+
check: "license_token_cached",
|
|
30092
|
+
level: readCachedLicenseToken() ? "pass" : "warn",
|
|
30093
|
+
detail: readCachedLicenseToken() ? "cached license token found" : "no cached token yet; support can still use license.key",
|
|
30094
|
+
next: readCachedLicenseToken() ? void 0 : "This is OK if license.key exists. It refreshes after cloud/license validation."
|
|
30095
|
+
});
|
|
30096
|
+
try {
|
|
30097
|
+
const res = await fetch(endpoints.healthEndpoint, { method: "GET", signal: AbortSignal.timeout(1e4) });
|
|
30098
|
+
const body = await safeJson2(res);
|
|
30099
|
+
checks.push({
|
|
30100
|
+
check: "support_health_endpoint",
|
|
30101
|
+
level: res.ok && body?.status !== "down" ? "pass" : "fail",
|
|
30102
|
+
detail: `${res.status} ${body?.status ?? res.statusText}`,
|
|
30103
|
+
next: res.ok ? void 0 : "Check internet access, DNS, or AskExe support status."
|
|
30104
|
+
});
|
|
30105
|
+
for (const remote of body?.checks ?? []) {
|
|
30106
|
+
const name = remote.name ?? "unknown";
|
|
30107
|
+
checks.push({
|
|
30108
|
+
check: `server_${name}`,
|
|
30109
|
+
level: remote.ok === true ? "pass" : name === "admin_inbox_configured" ? "warn" : "fail",
|
|
30110
|
+
detail: remote.detail ?? (remote.ok ? "ok" : "failed"),
|
|
30111
|
+
next: remote.ok ? void 0 : "AskExe must fix this server-side."
|
|
30112
|
+
});
|
|
30113
|
+
}
|
|
30114
|
+
} catch (err) {
|
|
30115
|
+
checks.push({
|
|
30116
|
+
check: "support_health_endpoint",
|
|
30117
|
+
level: "fail",
|
|
30118
|
+
detail: err instanceof Error ? err.message : String(err),
|
|
30119
|
+
next: "Check internet access, then run `exe-os support health` again."
|
|
30120
|
+
});
|
|
30121
|
+
}
|
|
30122
|
+
return checks;
|
|
30123
|
+
}
|
|
30124
|
+
async function runTest(project) {
|
|
30125
|
+
const checks = await runHealth();
|
|
30126
|
+
const endpoints = await resolveEndpoints();
|
|
30127
|
+
const licenseKey = loadLicense();
|
|
30128
|
+
const licenseToken = readCachedLicenseToken();
|
|
30129
|
+
const id = randomUUID9();
|
|
30130
|
+
const version = readPackageVersion2();
|
|
30131
|
+
const reportPath = writeLocalTestReport(id, project, version);
|
|
30132
|
+
checks.push({ check: "local_report_file", level: "pass", detail: reportPath });
|
|
30133
|
+
if (!licenseKey && !licenseToken) {
|
|
30134
|
+
checks.push({
|
|
30135
|
+
check: "upstream_post",
|
|
30136
|
+
level: "fail",
|
|
30137
|
+
detail: "not sent because this device has no license key/token",
|
|
30138
|
+
next: "Run `exe-os setup` or ask AskExe to provision this customer device."
|
|
30139
|
+
});
|
|
30140
|
+
return checks;
|
|
30141
|
+
}
|
|
30142
|
+
const payload = {
|
|
30143
|
+
id,
|
|
30144
|
+
title: `TEST \u2014 ${project} support intake (${version})`,
|
|
30145
|
+
classification: "unclear",
|
|
30146
|
+
severity: "p3",
|
|
30147
|
+
summary: "Synthetic exe-os support intake smoke test. Safe to close.",
|
|
30148
|
+
customer_impact: "No customer impact; diagnostic only.",
|
|
30149
|
+
reproduction_steps: ["Run exe-os support test"],
|
|
30150
|
+
expected: "The report reaches AskExe support intake and can be triaged.",
|
|
30151
|
+
actual: "Smoke test submitted by exe-os support test.",
|
|
30152
|
+
package_version: `@askexenow/exe-os@${version}`,
|
|
30153
|
+
project_name: project,
|
|
30154
|
+
agent_id: "support-test",
|
|
30155
|
+
agent_role: "diagnostic",
|
|
30156
|
+
report_path: reportPath,
|
|
30157
|
+
markdown: readFileSync35(reportPath, "utf8")
|
|
30158
|
+
};
|
|
30159
|
+
try {
|
|
30160
|
+
const headers = { "content-type": "application/json" };
|
|
30161
|
+
if (licenseKey) headers["x-exe-license-key"] = licenseKey;
|
|
30162
|
+
if (licenseToken) headers["x-exe-license-token"] = licenseToken;
|
|
30163
|
+
const res = await fetch(endpoints.bugEndpoint, {
|
|
30164
|
+
method: "POST",
|
|
30165
|
+
headers,
|
|
30166
|
+
body: JSON.stringify(payload),
|
|
30167
|
+
signal: AbortSignal.timeout(15e3)
|
|
30168
|
+
});
|
|
30169
|
+
const data = await safeJson2(res);
|
|
30170
|
+
checks.push({
|
|
30171
|
+
check: "upstream_post",
|
|
30172
|
+
level: res.ok ? "pass" : "fail",
|
|
30173
|
+
detail: res.ok ? `sent id=${String(data?.id ?? id)}` : summarizeHttpFailure(res.status, data),
|
|
30174
|
+
next: res.ok ? void 0 : nextForPostFailure(res.status)
|
|
30175
|
+
});
|
|
30176
|
+
if (res.ok) {
|
|
30177
|
+
checks.push(await maybeCloseAdmin(String(data?.id ?? id), endpoints.adminEndpoint, version));
|
|
30178
|
+
}
|
|
30179
|
+
} catch (err) {
|
|
30180
|
+
checks.push({
|
|
30181
|
+
check: "upstream_post",
|
|
30182
|
+
level: "fail",
|
|
30183
|
+
detail: err instanceof Error ? err.message : String(err),
|
|
30184
|
+
next: "Check internet access, then run `exe-os support test` again."
|
|
30185
|
+
});
|
|
30186
|
+
}
|
|
30187
|
+
return checks;
|
|
30188
|
+
}
|
|
30189
|
+
async function resolveEndpoints() {
|
|
30190
|
+
const config2 = await loadConfig();
|
|
30191
|
+
const bugEndpoint = process.env.EXE_SUPPORT_BUG_REPORT_ENDPOINT ?? config2.support?.bugReportEndpoint ?? DEFAULT_BUG_ENDPOINT;
|
|
30192
|
+
const healthEndpoint = process.env.EXE_SUPPORT_HEALTH_ENDPOINT ?? bugEndpoint.replace(/\/bug-reports\/?$/, "/health");
|
|
30193
|
+
const adminEndpoint = process.env.ASKEXE_SUPPORT_ADMIN_ENDPOINT ?? process.env.EXE_SUPPORT_ADMIN_ENDPOINT ?? DEFAULT_ADMIN_ENDPOINT;
|
|
30194
|
+
return { bugEndpoint, healthEndpoint, adminEndpoint };
|
|
30195
|
+
}
|
|
30196
|
+
function checkLocalWrite() {
|
|
30197
|
+
const dir = path54.join(EXE_AI_DIR, "bug-reports");
|
|
30198
|
+
const testPath = path54.join(dir, ".support-write-test");
|
|
30199
|
+
try {
|
|
30200
|
+
mkdirSync21(dir, { recursive: true, mode: 448 });
|
|
30201
|
+
writeFileSync24(testPath, "ok\n", { mode: 384 });
|
|
30202
|
+
unlinkSync13(testPath);
|
|
30203
|
+
return { check: "local_bug_report_dir_writable", level: "pass", detail: dir };
|
|
30204
|
+
} catch (err) {
|
|
30205
|
+
return {
|
|
30206
|
+
check: "local_bug_report_dir_writable",
|
|
30207
|
+
level: "fail",
|
|
30208
|
+
detail: err instanceof Error ? err.message : String(err),
|
|
30209
|
+
next: "Fix permissions on ~/.exe-os or rerun setup on a writable user account."
|
|
30210
|
+
};
|
|
30211
|
+
}
|
|
30212
|
+
}
|
|
30213
|
+
function writeLocalTestReport(id, project, version) {
|
|
30214
|
+
const dir = path54.join(EXE_AI_DIR, "bug-reports");
|
|
30215
|
+
mkdirSync21(dir, { recursive: true, mode: 448 });
|
|
30216
|
+
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
30217
|
+
const filePath = path54.join(dir, `${date}-support-intake-test-${id.slice(0, 8)}.md`);
|
|
30218
|
+
writeFileSync24(filePath, `# TEST \u2014 ${project} support intake
|
|
30219
|
+
|
|
30220
|
+
Report ID: ${id}
|
|
30221
|
+
Package: @askexenow/exe-os@${version}
|
|
30222
|
+
|
|
30223
|
+
Synthetic smoke test from \`exe-os support test\`. Safe to close.
|
|
30224
|
+
`, { mode: 384 });
|
|
30225
|
+
return filePath;
|
|
30226
|
+
}
|
|
30227
|
+
async function maybeCloseAdmin(id, adminEndpoint, version) {
|
|
30228
|
+
const token = process.env.ASKEXE_SUPPORT_ADMIN_TOKEN ?? process.env.EXE_SUPPORT_ADMIN_TOKEN;
|
|
30229
|
+
if (!token) {
|
|
30230
|
+
return { check: "askexe_admin_autoclose", level: "warn", detail: "skipped; admin token is AskExe-only" };
|
|
30231
|
+
}
|
|
30232
|
+
try {
|
|
30233
|
+
const res = await fetch(`${adminEndpoint}/${encodeURIComponent(id)}`, {
|
|
30234
|
+
method: "PATCH",
|
|
30235
|
+
headers: { authorization: `Bearer ${token}`, "content-type": "application/json" },
|
|
30236
|
+
body: JSON.stringify({
|
|
30237
|
+
status: "closed",
|
|
30238
|
+
triage_notes: "Auto-closed synthetic support smoke test.",
|
|
30239
|
+
fixed_version: version
|
|
30240
|
+
}),
|
|
30241
|
+
signal: AbortSignal.timeout(1e4)
|
|
30242
|
+
});
|
|
30243
|
+
return {
|
|
30244
|
+
check: "askexe_admin_autoclose",
|
|
30245
|
+
level: res.ok ? "pass" : "warn",
|
|
30246
|
+
detail: res.ok ? "closed" : `${res.status} ${await res.text()}`,
|
|
30247
|
+
next: res.ok ? void 0 : "Report was sent; AskExe can close the smoke report manually."
|
|
30248
|
+
};
|
|
30249
|
+
} catch (err) {
|
|
30250
|
+
return {
|
|
30251
|
+
check: "askexe_admin_autoclose",
|
|
30252
|
+
level: "warn",
|
|
30253
|
+
detail: err instanceof Error ? err.message : String(err),
|
|
30254
|
+
next: "Report was sent; AskExe can close the smoke report manually."
|
|
30255
|
+
};
|
|
30256
|
+
}
|
|
30257
|
+
}
|
|
30258
|
+
function readPackageVersion2() {
|
|
30259
|
+
let dir = path54.dirname(new URL(import.meta.url).pathname);
|
|
30260
|
+
for (let i = 0; i < 6; i++) {
|
|
30261
|
+
const pkg = path54.join(dir, "package.json");
|
|
30262
|
+
try {
|
|
30263
|
+
const parsed = JSON.parse(readFileSync35(pkg, "utf8"));
|
|
30264
|
+
if (parsed.version) return parsed.version;
|
|
30265
|
+
} catch {
|
|
30266
|
+
}
|
|
30267
|
+
dir = path54.dirname(dir);
|
|
30268
|
+
}
|
|
30269
|
+
return "unknown";
|
|
30270
|
+
}
|
|
30271
|
+
async function safeJson2(res) {
|
|
30272
|
+
try {
|
|
30273
|
+
return await res.json();
|
|
30274
|
+
} catch {
|
|
30275
|
+
return null;
|
|
30276
|
+
}
|
|
30277
|
+
}
|
|
30278
|
+
function hasFailures(rows) {
|
|
30279
|
+
return rows.some((row) => row.level === "fail");
|
|
30280
|
+
}
|
|
30281
|
+
function summarizeHttpFailure(status, data) {
|
|
30282
|
+
const error = data?.error;
|
|
30283
|
+
return `${status} ${error?.message ?? JSON.stringify(data)}`;
|
|
30284
|
+
}
|
|
30285
|
+
function nextForPostFailure(status) {
|
|
30286
|
+
if (status === 401) return "License credentials were not sent. Run `exe-os support health` and check license_key_present.";
|
|
30287
|
+
if (status === 403) return "License is valid locally but not accepted by support intake. AskExe must check server-side license provisioning.";
|
|
30288
|
+
if (status >= 500) return "AskExe support intake is unhealthy server-side. Try again shortly and report the local file path.";
|
|
30289
|
+
return "Run `exe-os support health`; if it passes, send this output to AskExe.";
|
|
30290
|
+
}
|
|
30291
|
+
var DEFAULT_BUG_ENDPOINT, DEFAULT_ADMIN_ENDPOINT;
|
|
30292
|
+
var init_exe_support = __esm({
|
|
30293
|
+
"src/bin/exe-support.ts"() {
|
|
30294
|
+
"use strict";
|
|
30295
|
+
init_config();
|
|
30296
|
+
init_license();
|
|
30297
|
+
DEFAULT_BUG_ENDPOINT = "https://askexe.com/v1/support/bug-reports";
|
|
30298
|
+
DEFAULT_ADMIN_ENDPOINT = "https://askexe.com/admin/support/bug-reports";
|
|
30299
|
+
}
|
|
30300
|
+
});
|
|
30301
|
+
|
|
30302
|
+
// src/mcp/tools/support.ts
|
|
30303
|
+
import { z as z88 } from "zod";
|
|
30304
|
+
function formatRows(rows, mode) {
|
|
30305
|
+
const lines = [`exe-os support ${mode}`, ""];
|
|
30306
|
+
for (const row of rows) {
|
|
30307
|
+
const icon = row.level === "pass" ? "\u2705" : row.level === "warn" ? "\u26A0\uFE0F" : "\u274C";
|
|
30308
|
+
lines.push(`${icon} ${row.check}: ${row.detail}`);
|
|
30309
|
+
if (row.next) lines.push(` \u2192 ${row.next}`);
|
|
30310
|
+
}
|
|
30311
|
+
lines.push("");
|
|
30312
|
+
if (hasFailures(rows)) {
|
|
30313
|
+
lines.push("Result: not ready. Fix the failed item(s), then rerun this tool.");
|
|
30314
|
+
} else if (rows.some((row) => row.level === "warn")) {
|
|
30315
|
+
lines.push("Result: ready with warnings. Bug reports can be sent; warnings are informational unless AskExe asked for stricter validation.");
|
|
30316
|
+
} else {
|
|
30317
|
+
lines.push(mode === "test" ? "Result: ready. AskExe received the test report." : "Result: ready. Use support_test for an end-to-end send test.");
|
|
30318
|
+
}
|
|
30319
|
+
return lines.join("\n");
|
|
30320
|
+
}
|
|
30321
|
+
function registerSupportTools(server) {
|
|
30322
|
+
server.registerTool(
|
|
30323
|
+
"support_health",
|
|
30324
|
+
{
|
|
30325
|
+
title: "Support Health",
|
|
30326
|
+
description: "Customer-safe support intake health check. Verifies local bug-report directory, license presence, and AskExe support server health without filing a report.",
|
|
30327
|
+
inputSchema: {}
|
|
30328
|
+
},
|
|
30329
|
+
async () => {
|
|
30330
|
+
const checks = await runHealth();
|
|
30331
|
+
return {
|
|
30332
|
+
content: [{ type: "text", text: formatRows(checks, "health") }],
|
|
30333
|
+
structuredContent: { ok: !hasFailures(checks), checks },
|
|
30334
|
+
isError: hasFailures(checks)
|
|
30335
|
+
};
|
|
30336
|
+
}
|
|
30337
|
+
);
|
|
30338
|
+
server.registerTool(
|
|
30339
|
+
"support_test",
|
|
30340
|
+
{
|
|
30341
|
+
title: "Support Test",
|
|
30342
|
+
description: "End-to-end support intake smoke test. Files a clearly marked test report upstream and auto-closes it on AskExe machines with admin credentials.",
|
|
30343
|
+
inputSchema: {
|
|
30344
|
+
project: z88.string().default("support-smoke").describe("Customer/project name, e.g. hygo")
|
|
30345
|
+
}
|
|
30346
|
+
},
|
|
30347
|
+
async ({ project }) => {
|
|
30348
|
+
const checks = await runTest(project);
|
|
30349
|
+
return {
|
|
30350
|
+
content: [{ type: "text", text: formatRows(checks, "test") }],
|
|
30351
|
+
structuredContent: { ok: !hasFailures(checks), checks },
|
|
30352
|
+
isError: hasFailures(checks)
|
|
30353
|
+
};
|
|
30354
|
+
}
|
|
30355
|
+
);
|
|
30356
|
+
}
|
|
30357
|
+
var init_support = __esm({
|
|
30358
|
+
"src/mcp/tools/support.ts"() {
|
|
30359
|
+
"use strict";
|
|
30360
|
+
init_exe_support();
|
|
30361
|
+
}
|
|
30362
|
+
});
|
|
30363
|
+
|
|
30364
|
+
// src/lib/session-events.ts
|
|
30365
|
+
import { randomUUID as randomUUID10 } from "crypto";
|
|
30078
30366
|
async function ensureSessionEventsTable(client) {
|
|
30079
30367
|
await client.execute(`
|
|
30080
30368
|
CREATE TABLE IF NOT EXISTS session_events (
|
|
@@ -30163,7 +30451,7 @@ var init_session_events = __esm({
|
|
|
30163
30451
|
});
|
|
30164
30452
|
|
|
30165
30453
|
// src/mcp/tools/get-session-events.ts
|
|
30166
|
-
import { z as
|
|
30454
|
+
import { z as z89 } from "zod";
|
|
30167
30455
|
function canReadAgent(activeRole, activeAgent, requestedAgent) {
|
|
30168
30456
|
return requestedAgent === activeAgent || activeRole === "COO" || activeRole === "CTO";
|
|
30169
30457
|
}
|
|
@@ -30187,11 +30475,11 @@ function registerGetSessionEvents(server) {
|
|
|
30187
30475
|
title: "Get Session Events",
|
|
30188
30476
|
description: "Return exact recent chronological user prompts, assistant responses, and tool calls from the append-only session journal. Use this when asked what happened last, not semantic memory search.",
|
|
30189
30477
|
inputSchema: {
|
|
30190
|
-
agent_id:
|
|
30191
|
-
session_id:
|
|
30478
|
+
agent_id: z89.string().optional().describe("Agent to inspect. Defaults to active agent. COO/CTO may inspect others."),
|
|
30479
|
+
session_id: z89.string().optional().describe("Optional exact runtime session id."),
|
|
30192
30480
|
event_type: EVENT_TYPE.optional().describe("Filter to one event type."),
|
|
30193
|
-
project_name:
|
|
30194
|
-
limit:
|
|
30481
|
+
project_name: z89.string().optional().describe("Optional project filter. Pass 'all' for all projects."),
|
|
30482
|
+
limit: z89.number().int().min(1).max(100).default(20).describe("Number of events to return.")
|
|
30195
30483
|
}
|
|
30196
30484
|
},
|
|
30197
30485
|
async ({ agent_id, session_id, event_type, project_name, limit }) => {
|
|
@@ -30227,8 +30515,8 @@ function registerGetLastAssistantResponse(server) {
|
|
|
30227
30515
|
title: "Get Last Assistant Response",
|
|
30228
30516
|
description: "Return the exact last assistant response for an agent from the session event journal. Use for 'what was the last thing you said?'",
|
|
30229
30517
|
inputSchema: {
|
|
30230
|
-
agent_id:
|
|
30231
|
-
project_name:
|
|
30518
|
+
agent_id: z89.string().optional().describe("Agent to inspect. Defaults to active agent. COO/CTO may inspect others."),
|
|
30519
|
+
project_name: z89.string().optional().describe("Optional project filter. Pass 'all' for all projects.")
|
|
30232
30520
|
}
|
|
30233
30521
|
},
|
|
30234
30522
|
async ({ agent_id, project_name }) => {
|
|
@@ -30263,7 +30551,7 @@ var init_get_session_events = __esm({
|
|
|
30263
30551
|
init_active_agent();
|
|
30264
30552
|
init_fast_db_init();
|
|
30265
30553
|
init_session_events();
|
|
30266
|
-
EVENT_TYPE =
|
|
30554
|
+
EVENT_TYPE = z89.enum([
|
|
30267
30555
|
"user_prompt",
|
|
30268
30556
|
"assistant_response",
|
|
30269
30557
|
"tool_call",
|
|
@@ -30275,24 +30563,24 @@ var init_get_session_events = __esm({
|
|
|
30275
30563
|
|
|
30276
30564
|
// src/lib/code-context-index.ts
|
|
30277
30565
|
import crypto20 from "crypto";
|
|
30278
|
-
import
|
|
30279
|
-
import { existsSync as existsSync43, mkdirSync as
|
|
30566
|
+
import path55 from "path";
|
|
30567
|
+
import { existsSync as existsSync43, mkdirSync as mkdirSync22, readFileSync as readFileSync36, readdirSync as readdirSync14, statSync as statSync10, writeFileSync as writeFileSync25 } from "fs";
|
|
30280
30568
|
import { spawnSync } from "child_process";
|
|
30281
30569
|
function normalizeProjectRoot(projectRoot) {
|
|
30282
|
-
return
|
|
30570
|
+
return path55.resolve(projectRoot || process.cwd());
|
|
30283
30571
|
}
|
|
30284
30572
|
function hashText(text3) {
|
|
30285
30573
|
return crypto20.createHash("sha256").update(text3).digest("hex");
|
|
30286
30574
|
}
|
|
30287
30575
|
function indexDir() {
|
|
30288
|
-
const dir =
|
|
30289
|
-
|
|
30576
|
+
const dir = path55.join(EXE_AI_DIR, "code-context");
|
|
30577
|
+
mkdirSync22(dir, { recursive: true });
|
|
30290
30578
|
return dir;
|
|
30291
30579
|
}
|
|
30292
30580
|
function getCodeContextIndexPath(projectRoot) {
|
|
30293
30581
|
const root = normalizeProjectRoot(projectRoot);
|
|
30294
30582
|
const rootHash = hashText(root).slice(0, 16);
|
|
30295
|
-
return
|
|
30583
|
+
return path55.join(indexDir(), `${rootHash}.json`);
|
|
30296
30584
|
}
|
|
30297
30585
|
function currentBranch(projectRoot) {
|
|
30298
30586
|
const result2 = spawnSync("git", ["branch", "--show-current"], { cwd: projectRoot, encoding: "utf8", timeout: 2e3 });
|
|
@@ -30305,8 +30593,8 @@ function shouldIgnore(relPath) {
|
|
|
30305
30593
|
}
|
|
30306
30594
|
function listRecursive(projectRoot, dir = projectRoot, out = []) {
|
|
30307
30595
|
for (const entry of readdirSync14(dir, { withFileTypes: true })) {
|
|
30308
|
-
const abs =
|
|
30309
|
-
const rel =
|
|
30596
|
+
const abs = path55.join(dir, entry.name);
|
|
30597
|
+
const rel = path55.relative(projectRoot, abs).replaceAll(path55.sep, "/");
|
|
30310
30598
|
if (shouldIgnore(rel)) continue;
|
|
30311
30599
|
if (entry.isDirectory()) listRecursive(projectRoot, abs, out);
|
|
30312
30600
|
else if (entry.isFile()) out.push(rel);
|
|
@@ -30322,7 +30610,7 @@ function listCodeFiles(projectRoot, maxFiles) {
|
|
|
30322
30610
|
const rg = spawnSync("rg", ["--files"], { cwd: projectRoot, encoding: "utf8", timeout: 5e3, maxBuffer: 1024 * 1024 * 16 });
|
|
30323
30611
|
files = rg.status === 0 && rg.stdout.trim() ? rg.stdout.split("\n").map((s) => s.trim()).filter(Boolean) : listRecursive(projectRoot);
|
|
30324
30612
|
}
|
|
30325
|
-
return files.map((file) => file.replaceAll(
|
|
30613
|
+
return files.map((file) => file.replaceAll(path55.sep, "/")).filter((file) => isChunkable(file) && !shouldIgnore(file)).slice(0, maxFiles).sort();
|
|
30326
30614
|
}
|
|
30327
30615
|
function parseImportPaths2(importText) {
|
|
30328
30616
|
const paths = [];
|
|
@@ -30335,13 +30623,13 @@ function parseImportPaths2(importText) {
|
|
|
30335
30623
|
}
|
|
30336
30624
|
function resolveImport(fromFile, importPath, allFiles) {
|
|
30337
30625
|
if (!importPath.startsWith(".")) return null;
|
|
30338
|
-
const base =
|
|
30626
|
+
const base = path55.posix.normalize(path55.posix.join(path55.posix.dirname(fromFile.replaceAll(path55.sep, "/")), importPath));
|
|
30339
30627
|
const withoutKnownExt = base.replace(/\.(?:[a-z0-9]+)$/i, "");
|
|
30340
30628
|
const candidates = [base];
|
|
30341
30629
|
for (const ext of ["ts", "tsx", "js", "jsx", "py", "rs", "go", "java", "cs", "cpp", "c", "rb", "php", "swift", "kt", "scala", "sql", "md", "json", "yaml", "yml"]) {
|
|
30342
30630
|
candidates.push(`${withoutKnownExt}.${ext}`, `${base}.${ext}`);
|
|
30343
30631
|
}
|
|
30344
|
-
for (const indexName of ["index.ts", "index.tsx", "index.js", "mod.rs", "__init__.py"]) candidates.push(
|
|
30632
|
+
for (const indexName of ["index.ts", "index.tsx", "index.js", "mod.rs", "__init__.py"]) candidates.push(path55.posix.join(base, indexName));
|
|
30345
30633
|
return candidates.find((candidate) => allFiles.has(candidate)) ?? null;
|
|
30346
30634
|
}
|
|
30347
30635
|
function symbolId(filePath, chunk) {
|
|
@@ -30351,7 +30639,7 @@ function loadIndex(projectRoot) {
|
|
|
30351
30639
|
const file = getCodeContextIndexPath(projectRoot);
|
|
30352
30640
|
if (!existsSync43(file)) return null;
|
|
30353
30641
|
try {
|
|
30354
|
-
const parsed = JSON.parse(
|
|
30642
|
+
const parsed = JSON.parse(readFileSync36(file, "utf8"));
|
|
30355
30643
|
if (parsed.version !== INDEX_VERSION || parsed.projectRoot !== projectRoot) return null;
|
|
30356
30644
|
return parsed;
|
|
30357
30645
|
} catch {
|
|
@@ -30359,10 +30647,10 @@ function loadIndex(projectRoot) {
|
|
|
30359
30647
|
}
|
|
30360
30648
|
}
|
|
30361
30649
|
function saveIndex(index) {
|
|
30362
|
-
|
|
30650
|
+
writeFileSync25(getCodeContextIndexPath(index.projectRoot), JSON.stringify(index, null, 2));
|
|
30363
30651
|
}
|
|
30364
30652
|
function buildFileRecord(projectRoot, relPath, allFiles, previous) {
|
|
30365
|
-
const absPath =
|
|
30653
|
+
const absPath = path55.join(projectRoot, relPath);
|
|
30366
30654
|
let stat;
|
|
30367
30655
|
try {
|
|
30368
30656
|
stat = statSync10(absPath);
|
|
@@ -30372,7 +30660,7 @@ function buildFileRecord(projectRoot, relPath, allFiles, previous) {
|
|
|
30372
30660
|
if (!stat.isFile()) return { record: null, reused: false };
|
|
30373
30661
|
const language = languageForFile(relPath);
|
|
30374
30662
|
if (!language || !isChunkable(relPath)) return { record: null, reused: false };
|
|
30375
|
-
const source =
|
|
30663
|
+
const source = readFileSync36(absPath, "utf8");
|
|
30376
30664
|
const hash = hashText(source);
|
|
30377
30665
|
if (previous && previous.hash === hash && previous.mtimeMs === stat.mtimeMs && previous.size === stat.size && previous.language === language) {
|
|
30378
30666
|
return { record: previous, reused: true };
|
|
@@ -30400,13 +30688,13 @@ function buildCodeContextIndex(options = {}) {
|
|
|
30400
30688
|
const branch = currentBranch(projectRoot);
|
|
30401
30689
|
const previous = options.force ? null : loadIndex(projectRoot);
|
|
30402
30690
|
const files = listCodeFiles(projectRoot, maxFiles);
|
|
30403
|
-
const allFiles = new Set(files.map((file) => file.replaceAll(
|
|
30691
|
+
const allFiles = new Set(files.map((file) => file.replaceAll(path55.sep, "/")));
|
|
30404
30692
|
const fileRecords = {};
|
|
30405
30693
|
let rebuiltFiles = 0;
|
|
30406
30694
|
let reusedFiles = 0;
|
|
30407
30695
|
let skippedFiles = 0;
|
|
30408
30696
|
for (const rel of files) {
|
|
30409
|
-
const normalized = rel.replaceAll(
|
|
30697
|
+
const normalized = rel.replaceAll(path55.sep, "/");
|
|
30410
30698
|
const { record, reused } = buildFileRecord(projectRoot, normalized, allFiles, previous?.files[normalized]);
|
|
30411
30699
|
if (record) {
|
|
30412
30700
|
fileRecords[normalized] = record;
|
|
@@ -30435,11 +30723,11 @@ function loadOrBuildCodeContextIndex(options = {}) {
|
|
|
30435
30723
|
if (loaded) {
|
|
30436
30724
|
const currentFiles = listCodeFiles(projectRoot, options.maxFiles ?? DEFAULT_MAX_FILES);
|
|
30437
30725
|
const unchanged = currentFiles.every((rel) => {
|
|
30438
|
-
const normalized = rel.replaceAll(
|
|
30726
|
+
const normalized = rel.replaceAll(path55.sep, "/");
|
|
30439
30727
|
const existing = loaded.files[normalized];
|
|
30440
30728
|
if (!existing) return false;
|
|
30441
30729
|
try {
|
|
30442
|
-
const stat = statSync10(
|
|
30730
|
+
const stat = statSync10(path55.join(projectRoot, normalized));
|
|
30443
30731
|
return stat.mtimeMs === existing.mtimeMs && stat.size === existing.size;
|
|
30444
30732
|
} catch {
|
|
30445
30733
|
return false;
|
|
@@ -30492,9 +30780,9 @@ function globToRegex(pattern) {
|
|
|
30492
30780
|
}
|
|
30493
30781
|
function matchesPath(filePath, patterns) {
|
|
30494
30782
|
if (!patterns || patterns.length === 0) return true;
|
|
30495
|
-
const normalized = filePath.replaceAll(
|
|
30783
|
+
const normalized = filePath.replaceAll(path55.sep, "/");
|
|
30496
30784
|
return patterns.some((pattern) => {
|
|
30497
|
-
const p = pattern.replaceAll(
|
|
30785
|
+
const p = pattern.replaceAll(path55.sep, "/").replace(/^\.\//, "");
|
|
30498
30786
|
return normalized === p || normalized.startsWith(`${p}/`) || normalized.endsWith(p) || globToRegex(p).test(normalized);
|
|
30499
30787
|
});
|
|
30500
30788
|
}
|
|
@@ -30612,7 +30900,7 @@ function traceCodeSymbol(symbolName, options = {}) {
|
|
|
30612
30900
|
}
|
|
30613
30901
|
function resolveTargetFile(index, input) {
|
|
30614
30902
|
if (input.filePath) {
|
|
30615
|
-
const normalized = input.filePath.replaceAll(
|
|
30903
|
+
const normalized = input.filePath.replaceAll(path55.sep, "/").replace(/^\.\//, "");
|
|
30616
30904
|
if (index.files[normalized]) return { filePath: normalized, target: normalized };
|
|
30617
30905
|
const suffix = Object.keys(index.files).find((file) => file.endsWith(normalized));
|
|
30618
30906
|
if (suffix) return { filePath: suffix, target: input.filePath };
|
|
@@ -30642,7 +30930,7 @@ function analyzeBlastRadius(input) {
|
|
|
30642
30930
|
}
|
|
30643
30931
|
}
|
|
30644
30932
|
}
|
|
30645
|
-
const targetBase =
|
|
30933
|
+
const targetBase = path55.basename(target.filePath).replace(/\.[^.]+$/, "").toLowerCase();
|
|
30646
30934
|
const symbolLower = input.symbol?.toLowerCase();
|
|
30647
30935
|
const tests = Object.keys(index.files).filter((file) => {
|
|
30648
30936
|
const lower = file.toLowerCase();
|
|
@@ -30683,7 +30971,7 @@ var init_code_context_index = __esm({
|
|
|
30683
30971
|
});
|
|
30684
30972
|
|
|
30685
30973
|
// src/mcp/tools/code-context.ts
|
|
30686
|
-
import { z as
|
|
30974
|
+
import { z as z90 } from "zod";
|
|
30687
30975
|
function errorResult10(text3) {
|
|
30688
30976
|
return { content: [{ type: "text", text: text3 }], isError: true };
|
|
30689
30977
|
}
|
|
@@ -30695,19 +30983,19 @@ function registerCodeContext(server) {
|
|
|
30695
30983
|
title: "Code Context",
|
|
30696
30984
|
description: "Persistent codebase context engine. One consolidated tool to avoid MCP bloat. Actions: index, search, trace, blast_radius, stats.",
|
|
30697
30985
|
inputSchema: {
|
|
30698
|
-
action:
|
|
30699
|
-
project_root:
|
|
30700
|
-
query:
|
|
30701
|
-
symbol:
|
|
30702
|
-
file_path:
|
|
30703
|
-
force:
|
|
30704
|
-
limit:
|
|
30705
|
-
offset:
|
|
30706
|
-
refresh_index:
|
|
30707
|
-
languages:
|
|
30708
|
-
paths:
|
|
30709
|
-
depth:
|
|
30710
|
-
max_files:
|
|
30986
|
+
action: z90.enum(["index", "search", "trace", "blast_radius", "stats"]).describe("Code context operation"),
|
|
30987
|
+
project_root: z90.string().optional().describe("Repository root. Defaults to current working directory."),
|
|
30988
|
+
query: z90.string().optional().describe("Search query for action=search"),
|
|
30989
|
+
symbol: z90.string().optional().describe("Symbol/function/class/type name for trace or blast_radius"),
|
|
30990
|
+
file_path: z90.string().optional().describe("File path for blast_radius"),
|
|
30991
|
+
force: z90.boolean().optional().describe("Force rebuild before answering"),
|
|
30992
|
+
limit: z90.coerce.number().int().min(1).max(100).optional().describe("Max results"),
|
|
30993
|
+
offset: z90.coerce.number().int().min(0).optional().describe("Search pagination offset"),
|
|
30994
|
+
refresh_index: z90.boolean().optional().describe("Refresh/rebuild index before searching"),
|
|
30995
|
+
languages: z90.array(z90.string()).optional().describe('Language filters, e.g. ["python", "typescript"]'),
|
|
30996
|
+
paths: z90.array(z90.string()).optional().describe("Path/glob filters"),
|
|
30997
|
+
depth: z90.coerce.number().int().min(1).max(5).optional().describe("Dependent traversal depth for blast_radius"),
|
|
30998
|
+
max_files: z90.coerce.number().int().min(1).max(1e4).optional().describe("Max code files to index")
|
|
30711
30999
|
}
|
|
30712
31000
|
}, async ({ action, project_root, query, symbol, file_path, force, limit, offset, refresh_index, languages, paths, depth, max_files }) => {
|
|
30713
31001
|
const opts = { projectRoot: project_root, force, maxFiles: max_files };
|
|
@@ -30758,7 +31046,7 @@ var init_code_context = __esm({
|
|
|
30758
31046
|
});
|
|
30759
31047
|
|
|
30760
31048
|
// src/mcp/tools/support-inbox.ts
|
|
30761
|
-
import { z as
|
|
31049
|
+
import { z as z91 } from "zod";
|
|
30762
31050
|
function adminToken() {
|
|
30763
31051
|
return process.env.ASKEXE_SUPPORT_ADMIN_TOKEN || process.env.EXE_SUPPORT_ADMIN_TOKEN;
|
|
30764
31052
|
}
|
|
@@ -30797,9 +31085,9 @@ function registerListBugReports(server) {
|
|
|
30797
31085
|
title: "List Bug Reports",
|
|
30798
31086
|
description: "AskExe-internal only: list incoming customer bug reports from the support inbox.",
|
|
30799
31087
|
inputSchema: {
|
|
30800
|
-
status:
|
|
30801
|
-
severity:
|
|
30802
|
-
limit:
|
|
31088
|
+
status: z91.enum(["all", "open", "triaged", "fixed", "closed", "wontfix"]).default("open"),
|
|
31089
|
+
severity: z91.enum(["p0", "p1", "p2", "p3"]).optional(),
|
|
31090
|
+
limit: z91.number().int().min(1).max(100).default(25)
|
|
30803
31091
|
}
|
|
30804
31092
|
},
|
|
30805
31093
|
async ({ status, severity, limit }) => {
|
|
@@ -30818,7 +31106,7 @@ function registerGetBugReport(server) {
|
|
|
30818
31106
|
{
|
|
30819
31107
|
title: "Get Bug Report",
|
|
30820
31108
|
description: "AskExe-internal only: fetch one customer bug report with full markdown payload.",
|
|
30821
|
-
inputSchema: { id:
|
|
31109
|
+
inputSchema: { id: z91.string().min(8) }
|
|
30822
31110
|
},
|
|
30823
31111
|
async ({ id }) => {
|
|
30824
31112
|
const data = await requestJson(`${endpoint()}/${encodeURIComponent(id)}`);
|
|
@@ -30833,12 +31121,12 @@ function registerTriageBugReport(server) {
|
|
|
30833
31121
|
title: "Triage Bug Report",
|
|
30834
31122
|
description: "AskExe-internal only: update bug report status and link task/commit/release metadata.",
|
|
30835
31123
|
inputSchema: {
|
|
30836
|
-
id:
|
|
31124
|
+
id: z91.string().min(8),
|
|
30837
31125
|
status: STATUS.optional(),
|
|
30838
|
-
triage_notes:
|
|
30839
|
-
linked_task_id:
|
|
30840
|
-
linked_commit:
|
|
30841
|
-
fixed_version:
|
|
31126
|
+
triage_notes: z91.string().optional(),
|
|
31127
|
+
linked_task_id: z91.string().optional(),
|
|
31128
|
+
linked_commit: z91.string().optional(),
|
|
31129
|
+
fixed_version: z91.string().optional()
|
|
30842
31130
|
}
|
|
30843
31131
|
},
|
|
30844
31132
|
async ({ id, status, triage_notes, linked_task_id, linked_commit, fixed_version }) => {
|
|
@@ -30855,7 +31143,7 @@ var init_support_inbox = __esm({
|
|
|
30855
31143
|
"src/mcp/tools/support-inbox.ts"() {
|
|
30856
31144
|
"use strict";
|
|
30857
31145
|
DEFAULT_ENDPOINT = "https://askexe.com/admin/support/bug-reports";
|
|
30858
|
-
STATUS =
|
|
31146
|
+
STATUS = z91.enum(["open", "triaged", "fixed", "closed", "wontfix"]);
|
|
30859
31147
|
}
|
|
30860
31148
|
});
|
|
30861
31149
|
|
|
@@ -30929,6 +31217,7 @@ var init_tool_gates = __esm({
|
|
|
30929
31217
|
registerStoreDecision: "core",
|
|
30930
31218
|
registerGetDecision: "core",
|
|
30931
31219
|
registerCreateBugReport: "core",
|
|
31220
|
+
registerSupportTools: "core",
|
|
30932
31221
|
registerGetSessionEvents: "core",
|
|
30933
31222
|
registerGetLastAssistantResponse: "core",
|
|
30934
31223
|
registerCodeContext: "graph-read",
|
|
@@ -31188,6 +31477,7 @@ function registerAllTools(server) {
|
|
|
31188
31477
|
gate("registerStoreDecision", registerStoreDecision);
|
|
31189
31478
|
gate("registerGetDecision", registerGetDecision);
|
|
31190
31479
|
gate("registerCreateBugReport", registerCreateBugReport);
|
|
31480
|
+
gate("registerSupportTools", registerSupportTools);
|
|
31191
31481
|
gate("registerGetSessionEvents", registerGetSessionEvents);
|
|
31192
31482
|
gate("registerGetLastAssistantResponse", registerGetLastAssistantResponse);
|
|
31193
31483
|
gate("registerCodeContext", registerCodeContext);
|
|
@@ -31335,6 +31625,7 @@ var init_register_tools = __esm({
|
|
|
31335
31625
|
init_activate_license();
|
|
31336
31626
|
init_query_company_brain();
|
|
31337
31627
|
init_create_bug_report();
|
|
31628
|
+
init_support();
|
|
31338
31629
|
init_get_session_events();
|
|
31339
31630
|
init_code_context();
|
|
31340
31631
|
init_support_inbox();
|
|
@@ -31562,12 +31853,12 @@ __export(task_enforcement_exports, {
|
|
|
31562
31853
|
runTaskEnforcementTick: () => runTaskEnforcementTick,
|
|
31563
31854
|
sendNudge: () => sendNudge
|
|
31564
31855
|
});
|
|
31565
|
-
import { writeFileSync as
|
|
31566
|
-
import
|
|
31856
|
+
import { writeFileSync as writeFileSync26 } from "fs";
|
|
31857
|
+
import path56 from "path";
|
|
31567
31858
|
function writeAuditEntry(entry) {
|
|
31568
31859
|
try {
|
|
31569
31860
|
const line = JSON.stringify(entry) + "\n";
|
|
31570
|
-
|
|
31861
|
+
writeFileSync26(AUDIT_LOG_PATH, line, { flag: "a" });
|
|
31571
31862
|
} catch {
|
|
31572
31863
|
}
|
|
31573
31864
|
}
|
|
@@ -31738,7 +32029,7 @@ var init_task_enforcement = __esm({
|
|
|
31738
32029
|
"What do you need?"
|
|
31739
32030
|
];
|
|
31740
32031
|
MANAGER_ROLES = ["COO", "CTO"];
|
|
31741
|
-
AUDIT_LOG_PATH =
|
|
32032
|
+
AUDIT_LOG_PATH = path56.join(
|
|
31742
32033
|
process.env.HOME ?? process.env.USERPROFILE ?? "/tmp",
|
|
31743
32034
|
".exe-os",
|
|
31744
32035
|
"enforcement-audit.jsonl"
|
|
@@ -31760,12 +32051,12 @@ __export(background_jobs_exports, {
|
|
|
31760
32051
|
reniceCurrentProcess: () => reniceCurrentProcess,
|
|
31761
32052
|
startManagedJob: () => startManagedJob
|
|
31762
32053
|
});
|
|
31763
|
-
import { existsSync as existsSync44, mkdirSync as
|
|
32054
|
+
import { existsSync as existsSync44, mkdirSync as mkdirSync23, readFileSync as readFileSync37, writeFileSync as writeFileSync27, unlinkSync as unlinkSync14 } from "fs";
|
|
31764
32055
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
31765
32056
|
import os22 from "os";
|
|
31766
|
-
import
|
|
32057
|
+
import path57 from "path";
|
|
31767
32058
|
function ensureDirs() {
|
|
31768
|
-
|
|
32059
|
+
mkdirSync23(LOCK_DIR, { recursive: true });
|
|
31769
32060
|
}
|
|
31770
32061
|
function now() {
|
|
31771
32062
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -31783,7 +32074,7 @@ function readJobsRaw() {
|
|
|
31783
32074
|
ensureDirs();
|
|
31784
32075
|
if (!existsSync44(JOBS_FILE)) return [];
|
|
31785
32076
|
try {
|
|
31786
|
-
const parsed = JSON.parse(
|
|
32077
|
+
const parsed = JSON.parse(readFileSync37(JOBS_FILE, "utf8"));
|
|
31787
32078
|
return Array.isArray(parsed) ? parsed : [];
|
|
31788
32079
|
} catch {
|
|
31789
32080
|
return [];
|
|
@@ -31793,7 +32084,7 @@ function writeJobsRaw(jobs) {
|
|
|
31793
32084
|
ensureDirs();
|
|
31794
32085
|
const running2 = jobs.filter((j) => j.status === "running");
|
|
31795
32086
|
const rest = jobs.filter((j) => j.status !== "running").slice(-MAX_HISTORY);
|
|
31796
|
-
|
|
32087
|
+
writeFileSync27(JOBS_FILE, JSON.stringify([...rest, ...running2], null, 2) + "\n");
|
|
31797
32088
|
}
|
|
31798
32089
|
function listBackgroundJobs() {
|
|
31799
32090
|
const jobs = readJobsRaw();
|
|
@@ -31809,25 +32100,25 @@ function listBackgroundJobs() {
|
|
|
31809
32100
|
return jobs;
|
|
31810
32101
|
}
|
|
31811
32102
|
function lockPath(type) {
|
|
31812
|
-
return
|
|
32103
|
+
return path57.join(LOCK_DIR, `${type.replace(/[^a-zA-Z0-9_.-]/g, "_")}.lock`);
|
|
31813
32104
|
}
|
|
31814
32105
|
function acquireJobLock(type, ttlMs = DEFAULT_LOCK_TTL_MS) {
|
|
31815
32106
|
ensureDirs();
|
|
31816
32107
|
const file = lockPath(type);
|
|
31817
32108
|
if (existsSync44(file)) {
|
|
31818
32109
|
try {
|
|
31819
|
-
const lock = JSON.parse(
|
|
32110
|
+
const lock = JSON.parse(readFileSync37(file, "utf8"));
|
|
31820
32111
|
const age = Date.now() - Date.parse(lock.updatedAt ?? "");
|
|
31821
32112
|
if (lock.pid && isAlive(lock.pid) && Number.isFinite(age) && age < ttlMs) return false;
|
|
31822
32113
|
} catch {
|
|
31823
32114
|
}
|
|
31824
32115
|
try {
|
|
31825
|
-
|
|
32116
|
+
unlinkSync14(file);
|
|
31826
32117
|
} catch {
|
|
31827
32118
|
}
|
|
31828
32119
|
}
|
|
31829
32120
|
try {
|
|
31830
|
-
|
|
32121
|
+
writeFileSync27(file, JSON.stringify({ pid: process.pid, updatedAt: now() }, null, 2) + "\n", { flag: "wx" });
|
|
31831
32122
|
return true;
|
|
31832
32123
|
} catch {
|
|
31833
32124
|
return false;
|
|
@@ -31837,11 +32128,11 @@ function releaseJobLock(type) {
|
|
|
31837
32128
|
const file = lockPath(type);
|
|
31838
32129
|
try {
|
|
31839
32130
|
if (!existsSync44(file)) return;
|
|
31840
|
-
const lock = JSON.parse(
|
|
31841
|
-
if (lock.pid === process.pid || !lock.pid || !isAlive(lock.pid))
|
|
32131
|
+
const lock = JSON.parse(readFileSync37(file, "utf8"));
|
|
32132
|
+
if (lock.pid === process.pid || !lock.pid || !isAlive(lock.pid)) unlinkSync14(file);
|
|
31842
32133
|
} catch {
|
|
31843
32134
|
try {
|
|
31844
|
-
|
|
32135
|
+
unlinkSync14(file);
|
|
31845
32136
|
} catch {
|
|
31846
32137
|
}
|
|
31847
32138
|
}
|
|
@@ -31876,7 +32167,7 @@ function startManagedJob(options) {
|
|
|
31876
32167
|
writeJobsRaw([...jobs, record]);
|
|
31877
32168
|
const file = lockPath(options.type);
|
|
31878
32169
|
try {
|
|
31879
|
-
|
|
32170
|
+
writeFileSync27(file, JSON.stringify({ pid: process.pid, jobId: id, updatedAt: record.updatedAt }, null, 2) + "\n");
|
|
31880
32171
|
} catch {
|
|
31881
32172
|
}
|
|
31882
32173
|
};
|
|
@@ -32036,9 +32327,9 @@ var init_background_jobs = __esm({
|
|
|
32036
32327
|
"src/lib/background-jobs.ts"() {
|
|
32037
32328
|
"use strict";
|
|
32038
32329
|
init_config();
|
|
32039
|
-
JOB_DIR =
|
|
32040
|
-
JOBS_FILE =
|
|
32041
|
-
LOCK_DIR =
|
|
32330
|
+
JOB_DIR = path57.join(EXE_AI_DIR, "jobs");
|
|
32331
|
+
JOBS_FILE = path57.join(JOB_DIR, "jobs.json");
|
|
32332
|
+
LOCK_DIR = path57.join(JOB_DIR, "locks");
|
|
32042
32333
|
DEFAULT_LOCK_TTL_MS = 6 * 60 * 60 * 1e3;
|
|
32043
32334
|
MAX_HISTORY = 200;
|
|
32044
32335
|
}
|
|
@@ -32052,11 +32343,11 @@ __export(update_check_exports, {
|
|
|
32052
32343
|
getRemoteVersion: () => getRemoteVersion
|
|
32053
32344
|
});
|
|
32054
32345
|
import { execSync as execSync15 } from "child_process";
|
|
32055
|
-
import { readFileSync as
|
|
32056
|
-
import
|
|
32346
|
+
import { readFileSync as readFileSync38 } from "fs";
|
|
32347
|
+
import path58 from "path";
|
|
32057
32348
|
function getLocalVersion(packageRoot) {
|
|
32058
|
-
const pkgPath =
|
|
32059
|
-
const pkg = JSON.parse(
|
|
32349
|
+
const pkgPath = path58.join(packageRoot, "package.json");
|
|
32350
|
+
const pkg = JSON.parse(readFileSync38(pkgPath, "utf-8"));
|
|
32060
32351
|
return pkg.version;
|
|
32061
32352
|
}
|
|
32062
32353
|
function getRemoteVersion() {
|
|
@@ -32128,12 +32419,12 @@ __export(device_registry_exports, {
|
|
|
32128
32419
|
});
|
|
32129
32420
|
import crypto22 from "crypto";
|
|
32130
32421
|
import os23 from "os";
|
|
32131
|
-
import { readFileSync as
|
|
32132
|
-
import
|
|
32422
|
+
import { readFileSync as readFileSync39, writeFileSync as writeFileSync28, mkdirSync as mkdirSync24, existsSync as existsSync45 } from "fs";
|
|
32423
|
+
import path59 from "path";
|
|
32133
32424
|
function getDeviceInfo() {
|
|
32134
32425
|
if (existsSync45(DEVICE_JSON_PATH)) {
|
|
32135
32426
|
try {
|
|
32136
|
-
const raw =
|
|
32427
|
+
const raw = readFileSync39(DEVICE_JSON_PATH, "utf8");
|
|
32137
32428
|
const data = JSON.parse(raw);
|
|
32138
32429
|
if (data.deviceId && data.friendlyName && data.hostname) {
|
|
32139
32430
|
return data;
|
|
@@ -32147,14 +32438,14 @@ function getDeviceInfo() {
|
|
|
32147
32438
|
friendlyName: hostname.replace(/\./g, "-").toLowerCase(),
|
|
32148
32439
|
hostname
|
|
32149
32440
|
};
|
|
32150
|
-
|
|
32151
|
-
|
|
32441
|
+
mkdirSync24(path59.dirname(DEVICE_JSON_PATH), { recursive: true });
|
|
32442
|
+
writeFileSync28(DEVICE_JSON_PATH, JSON.stringify(info, null, 2));
|
|
32152
32443
|
return info;
|
|
32153
32444
|
}
|
|
32154
32445
|
function setFriendlyName(name) {
|
|
32155
32446
|
const info = getDeviceInfo();
|
|
32156
32447
|
info.friendlyName = name;
|
|
32157
|
-
|
|
32448
|
+
writeFileSync28(DEVICE_JSON_PATH, JSON.stringify(info, null, 2));
|
|
32158
32449
|
}
|
|
32159
32450
|
async function resolveTargetDevice(targetAgent, targetProject) {
|
|
32160
32451
|
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
@@ -32188,7 +32479,7 @@ var init_device_registry = __esm({
|
|
|
32188
32479
|
"src/lib/device-registry.ts"() {
|
|
32189
32480
|
"use strict";
|
|
32190
32481
|
init_config();
|
|
32191
|
-
DEVICE_JSON_PATH =
|
|
32482
|
+
DEVICE_JSON_PATH = path59.join(EXE_AI_DIR, "device.json");
|
|
32192
32483
|
}
|
|
32193
32484
|
});
|
|
32194
32485
|
|
|
@@ -32403,9 +32694,9 @@ init_daemon_auth();
|
|
|
32403
32694
|
import os24 from "os";
|
|
32404
32695
|
import net2 from "net";
|
|
32405
32696
|
import { createServer as createHttpServer } from "http";
|
|
32406
|
-
import { randomUUID as
|
|
32407
|
-
import { writeFileSync as
|
|
32408
|
-
import
|
|
32697
|
+
import { randomUUID as randomUUID11 } from "crypto";
|
|
32698
|
+
import { writeFileSync as writeFileSync29, unlinkSync as unlinkSync15, mkdirSync as mkdirSync25, existsSync as existsSync46, readFileSync as readFileSync40, chmodSync as chmodSync2 } from "fs";
|
|
32699
|
+
import path60 from "path";
|
|
32409
32700
|
|
|
32410
32701
|
// src/lib/orchestration-metrics.ts
|
|
32411
32702
|
init_config();
|
|
@@ -32478,8 +32769,8 @@ function initMetrics() {
|
|
|
32478
32769
|
// src/lib/exe-daemon.ts
|
|
32479
32770
|
init_memory_write_governor();
|
|
32480
32771
|
init_mcp_transport_health();
|
|
32481
|
-
var SOCKET_PATH2 = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ??
|
|
32482
|
-
var PID_PATH4 = process.env.EXE_DAEMON_PID ?? process.env.EXE_EMBED_PID ??
|
|
32772
|
+
var SOCKET_PATH2 = process.env.EXE_DAEMON_SOCK ?? process.env.EXE_EMBED_SOCK ?? path60.join(EXE_AI_DIR, "exed.sock");
|
|
32773
|
+
var PID_PATH4 = process.env.EXE_DAEMON_PID ?? process.env.EXE_EMBED_PID ?? path60.join(EXE_AI_DIR, "exed.pid");
|
|
32483
32774
|
var MODEL_FILE = "jina-embeddings-v5-small-q4_k_m.gguf";
|
|
32484
32775
|
var IDLE_TIMEOUT_MS2 = parseInt(process.env.EXE_DAEMON_IDLE_TIMEOUT_MS || "0", 10);
|
|
32485
32776
|
var REVIEW_POLL_INTERVAL_MS = 60 * 1e3;
|
|
@@ -32508,7 +32799,7 @@ function enqueue(queue, entry) {
|
|
|
32508
32799
|
queue.push(entry);
|
|
32509
32800
|
}
|
|
32510
32801
|
async function loadModel() {
|
|
32511
|
-
const modelPath =
|
|
32802
|
+
const modelPath = path60.join(MODELS_DIR, MODEL_FILE);
|
|
32512
32803
|
if (!existsSync46(modelPath)) {
|
|
32513
32804
|
process.stderr.write(`[exed] No model at ${modelPath} \u2014 running without embeddings (VPS mode).
|
|
32514
32805
|
`);
|
|
@@ -32605,11 +32896,11 @@ async function shutdown() {
|
|
|
32605
32896
|
}
|
|
32606
32897
|
if (process.platform === "darwin" && _llama) {
|
|
32607
32898
|
try {
|
|
32608
|
-
|
|
32899
|
+
unlinkSync15(SOCKET_PATH2);
|
|
32609
32900
|
} catch {
|
|
32610
32901
|
}
|
|
32611
32902
|
try {
|
|
32612
|
-
|
|
32903
|
+
unlinkSync15(PID_PATH4);
|
|
32613
32904
|
} catch {
|
|
32614
32905
|
}
|
|
32615
32906
|
process.stderr.write("[exed] Shutdown complete (darwin fast native exit).\n");
|
|
@@ -32638,11 +32929,11 @@ async function shutdown() {
|
|
|
32638
32929
|
_llama = null;
|
|
32639
32930
|
}
|
|
32640
32931
|
try {
|
|
32641
|
-
|
|
32932
|
+
unlinkSync15(SOCKET_PATH2);
|
|
32642
32933
|
} catch {
|
|
32643
32934
|
}
|
|
32644
32935
|
try {
|
|
32645
|
-
|
|
32936
|
+
unlinkSync15(PID_PATH4);
|
|
32646
32937
|
} catch {
|
|
32647
32938
|
}
|
|
32648
32939
|
process.stderr.write("[exed] Shutdown complete.\n");
|
|
@@ -32793,7 +33084,7 @@ async function handleBatchWriteMemory(socket, requestId, entries) {
|
|
|
32793
33084
|
}
|
|
32794
33085
|
}
|
|
32795
33086
|
async function writeMemoryRecord(entry) {
|
|
32796
|
-
const id =
|
|
33087
|
+
const id = randomUUID11();
|
|
32797
33088
|
const now2 = entry.timestamp || (/* @__PURE__ */ new Date()).toISOString();
|
|
32798
33089
|
const governed = governMemoryRecord({
|
|
32799
33090
|
id,
|
|
@@ -32950,28 +33241,28 @@ function startMemoryQueueDrain() {
|
|
|
32950
33241
|
`);
|
|
32951
33242
|
}
|
|
32952
33243
|
function startServer() {
|
|
32953
|
-
|
|
33244
|
+
mkdirSync25(path60.dirname(SOCKET_PATH2), { recursive: true });
|
|
32954
33245
|
try {
|
|
32955
|
-
chmodSync2(
|
|
33246
|
+
chmodSync2(path60.dirname(SOCKET_PATH2), 448);
|
|
32956
33247
|
} catch {
|
|
32957
33248
|
}
|
|
32958
33249
|
_daemonToken = ensureDaemonToken(process.env[DAEMON_TOKEN_ENV2] ?? null);
|
|
32959
33250
|
for (const oldFile of ["embed.sock", "embed.pid"]) {
|
|
32960
|
-
const oldPath =
|
|
33251
|
+
const oldPath = path60.join(path60.dirname(SOCKET_PATH2), oldFile);
|
|
32961
33252
|
try {
|
|
32962
33253
|
if (oldFile.endsWith(".pid")) {
|
|
32963
|
-
const pid = parseInt(
|
|
33254
|
+
const pid = parseInt(readFileSync40(oldPath, "utf8").trim(), 10);
|
|
32964
33255
|
if (pid > 0) try {
|
|
32965
33256
|
process.kill(pid, "SIGKILL");
|
|
32966
33257
|
} catch {
|
|
32967
33258
|
}
|
|
32968
33259
|
}
|
|
32969
|
-
|
|
33260
|
+
unlinkSync15(oldPath);
|
|
32970
33261
|
} catch {
|
|
32971
33262
|
}
|
|
32972
33263
|
}
|
|
32973
33264
|
try {
|
|
32974
|
-
|
|
33265
|
+
unlinkSync15(SOCKET_PATH2);
|
|
32975
33266
|
} catch {
|
|
32976
33267
|
}
|
|
32977
33268
|
const server = net2.createServer((socket) => {
|
|
@@ -33206,7 +33497,7 @@ async function startMcpHttpServer() {
|
|
|
33206
33497
|
sessionLastSeen.set(sessionId, Date.now());
|
|
33207
33498
|
} else if (!sessionId && req.method === "POST" && isInitializeRequest(parsedBody)) {
|
|
33208
33499
|
transport = new StreamableHTTPServerTransport({
|
|
33209
|
-
sessionIdGenerator: () =>
|
|
33500
|
+
sessionIdGenerator: () => randomUUID11(),
|
|
33210
33501
|
onsessioninitialized: (sid) => {
|
|
33211
33502
|
transports.set(sid, transport);
|
|
33212
33503
|
sessionLastSeen.set(sid, Date.now());
|
|
@@ -33591,7 +33882,7 @@ function startGraphExtraction() {
|
|
|
33591
33882
|
`);
|
|
33592
33883
|
}
|
|
33593
33884
|
var AGENT_STATS_INTERVAL_MS = 60 * 1e3;
|
|
33594
|
-
var AGENT_STATS_PATH =
|
|
33885
|
+
var AGENT_STATS_PATH = path60.join(EXE_AI_DIR, "agent-stats.json");
|
|
33595
33886
|
async function writeAgentStats() {
|
|
33596
33887
|
fired("agent_stats");
|
|
33597
33888
|
if (!await ensureStoreForPolling()) return;
|
|
@@ -33651,7 +33942,7 @@ async function writeAgentStats() {
|
|
|
33651
33942
|
pid: process.pid
|
|
33652
33943
|
}
|
|
33653
33944
|
};
|
|
33654
|
-
|
|
33945
|
+
writeFileSync29(AGENT_STATS_PATH, JSON.stringify(stats, null, 2), "utf8");
|
|
33655
33946
|
} catch (err) {
|
|
33656
33947
|
process.stderr.write(`[exed] Agent stats error: ${err instanceof Error ? err.message : String(err)}
|
|
33657
33948
|
`);
|
|
@@ -33768,11 +34059,11 @@ function startIntercomQueueDrain() {
|
|
|
33768
34059
|
const hasInProgressTask = (session) => {
|
|
33769
34060
|
try {
|
|
33770
34061
|
const { baseAgentName: ban } = (init_employees(), __toCommonJS(employees_exports));
|
|
33771
|
-
const
|
|
34062
|
+
const path61 = __require("path");
|
|
33772
34063
|
const { existsSync: existsSync47 } = __require("fs");
|
|
33773
34064
|
const os25 = __require("os");
|
|
33774
34065
|
const agent = ban(session.split("-")[0] ?? session);
|
|
33775
|
-
const markerPath =
|
|
34066
|
+
const markerPath = path61.join(os25.homedir(), ".exe-os", "session-cache", `current-task-${agent}.json`);
|
|
33776
34067
|
return existsSync47(markerPath);
|
|
33777
34068
|
} catch {
|
|
33778
34069
|
return false;
|
|
@@ -33968,11 +34259,11 @@ function handleSignalShutdown() {
|
|
|
33968
34259
|
} catch {
|
|
33969
34260
|
}
|
|
33970
34261
|
try {
|
|
33971
|
-
|
|
34262
|
+
unlinkSync15(SOCKET_PATH2);
|
|
33972
34263
|
} catch {
|
|
33973
34264
|
}
|
|
33974
34265
|
try {
|
|
33975
|
-
|
|
34266
|
+
unlinkSync15(PID_PATH4);
|
|
33976
34267
|
} catch {
|
|
33977
34268
|
}
|
|
33978
34269
|
process.stderr.write("[exed] Shutdown complete (darwin signal fast native exit).\n");
|
|
@@ -33986,11 +34277,11 @@ process.on("SIGTERM", handleSignalShutdown);
|
|
|
33986
34277
|
function checkExistingDaemon() {
|
|
33987
34278
|
try {
|
|
33988
34279
|
if (!existsSync46(PID_PATH4)) return false;
|
|
33989
|
-
const pid = parseInt(
|
|
34280
|
+
const pid = parseInt(readFileSync40(PID_PATH4, "utf8").trim(), 10);
|
|
33990
34281
|
if (!pid || isNaN(pid)) return false;
|
|
33991
34282
|
if (pid === process.pid) {
|
|
33992
34283
|
try {
|
|
33993
|
-
|
|
34284
|
+
unlinkSync15(PID_PATH4);
|
|
33994
34285
|
} catch {
|
|
33995
34286
|
}
|
|
33996
34287
|
return false;
|
|
@@ -34006,7 +34297,7 @@ function checkExistingDaemon() {
|
|
|
34006
34297
|
return true;
|
|
34007
34298
|
}
|
|
34008
34299
|
try {
|
|
34009
|
-
|
|
34300
|
+
unlinkSync15(PID_PATH4);
|
|
34010
34301
|
} catch {
|
|
34011
34302
|
}
|
|
34012
34303
|
return false;
|
|
@@ -34063,7 +34354,7 @@ function startAutoUpdateCheck() {
|
|
|
34063
34354
|
if (checkExistingDaemon()) {
|
|
34064
34355
|
process.exit(0);
|
|
34065
34356
|
}
|
|
34066
|
-
|
|
34357
|
+
writeFileSync29(PID_PATH4, String(process.pid));
|
|
34067
34358
|
try {
|
|
34068
34359
|
chmodSync2(PID_PATH4, 384);
|
|
34069
34360
|
} catch {
|
|
@@ -34187,11 +34478,11 @@ try {
|
|
|
34187
34478
|
process.stderr.write(`[exed] FATAL: ${err instanceof Error ? err.message : String(err)}
|
|
34188
34479
|
`);
|
|
34189
34480
|
try {
|
|
34190
|
-
|
|
34481
|
+
unlinkSync15(SOCKET_PATH2);
|
|
34191
34482
|
} catch {
|
|
34192
34483
|
}
|
|
34193
34484
|
try {
|
|
34194
|
-
|
|
34485
|
+
unlinkSync15(PID_PATH4);
|
|
34195
34486
|
} catch {
|
|
34196
34487
|
}
|
|
34197
34488
|
process.exit(1);
|