@askexenow/exe-os 0.9.85 → 0.9.87
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 +50 -14
- package/dist/bin/agentic-reflection-backfill.js +50 -14
- package/dist/bin/agentic-semantic-label.js +50 -14
- package/dist/bin/backfill-conversations.js +50 -14
- package/dist/bin/backfill-responses.js +50 -14
- package/dist/bin/backfill-vectors.js +50 -14
- package/dist/bin/bulk-sync-postgres.js +50 -14
- package/dist/bin/cleanup-stale-review-tasks.js +53 -17
- package/dist/bin/cli.js +339 -81
- package/dist/bin/exe-agent.js +18 -0
- package/dist/bin/exe-assign.js +50 -14
- package/dist/bin/exe-boot.js +75 -39
- package/dist/bin/exe-call.js +18 -0
- package/dist/bin/exe-cloud.js +40 -4
- package/dist/bin/exe-dispatch.js +61 -25
- package/dist/bin/exe-doctor.js +40 -4
- package/dist/bin/exe-export-behaviors.js +50 -14
- package/dist/bin/exe-forget.js +50 -14
- package/dist/bin/exe-gateway.js +65 -29
- package/dist/bin/exe-heartbeat.js +55 -19
- package/dist/bin/exe-kill.js +54 -18
- package/dist/bin/exe-launch-agent.js +58 -22
- package/dist/bin/exe-new-employee.js +33 -2
- package/dist/bin/exe-pending-messages.js +53 -17
- package/dist/bin/exe-pending-notifications.js +53 -17
- package/dist/bin/exe-pending-reviews.js +55 -19
- package/dist/bin/exe-rename.js +52 -16
- package/dist/bin/exe-review.js +50 -14
- package/dist/bin/exe-search.js +58 -22
- package/dist/bin/exe-session-cleanup.js +85 -44
- package/dist/bin/exe-start-codex.js +57 -21
- package/dist/bin/exe-start-opencode.js +55 -19
- package/dist/bin/exe-status.js +62 -26
- package/dist/bin/exe-team.js +50 -14
- package/dist/bin/git-sweep.js +63 -27
- package/dist/bin/graph-backfill.js +50 -14
- package/dist/bin/graph-export.js +50 -14
- package/dist/bin/install.js +9 -0
- package/dist/bin/intercom-check.js +67 -31
- package/dist/bin/scan-tasks.js +63 -27
- package/dist/bin/setup.js +53 -13
- package/dist/bin/shard-migrate.js +50 -14
- package/dist/bin/stack-update.js +59 -2
- package/dist/bin/update.js +1 -1
- package/dist/gateway/index.js +65 -29
- package/dist/hooks/bug-report-worker.js +65 -29
- package/dist/hooks/codex-stop-task-finalizer.js +59 -23
- package/dist/hooks/commit-complete.js +64 -28
- package/dist/hooks/error-recall.js +62 -26
- package/dist/hooks/ingest-worker.js +4 -4
- package/dist/hooks/ingest.js +56 -20
- package/dist/hooks/instructions-loaded.js +50 -14
- package/dist/hooks/notification.js +50 -14
- package/dist/hooks/post-compact.js +50 -14
- package/dist/hooks/post-tool-combined.js +63 -27
- package/dist/hooks/pre-compact.js +61 -25
- package/dist/hooks/pre-tool-use.js +58 -22
- package/dist/hooks/prompt-submit.js +78 -42
- package/dist/hooks/session-end.js +66 -30
- package/dist/hooks/session-start.js +68 -32
- package/dist/hooks/stop.js +53 -17
- package/dist/hooks/subagent-stop.js +50 -14
- package/dist/hooks/summary-worker.js +55 -19
- package/dist/index.js +61 -25
- package/dist/lib/cloud-sync.js +32 -14
- package/dist/lib/database.js +22 -4
- package/dist/lib/db-daemon-client.js +16 -4
- package/dist/lib/db.js +22 -4
- package/dist/lib/device-registry.js +22 -4
- package/dist/lib/embedder.js +16 -4
- package/dist/lib/employee-templates.js +18 -0
- package/dist/lib/exe-daemon-client.js +16 -4
- package/dist/lib/exe-daemon.js +874 -232
- package/dist/lib/hybrid-search.js +58 -22
- package/dist/lib/identity-templates.js +6 -2
- package/dist/lib/schedules.js +53 -17
- package/dist/lib/skill-learning.js +16 -4
- package/dist/lib/store.js +50 -14
- package/dist/lib/tasks.js +16 -4
- package/dist/lib/tmux-routing.js +18 -6
- package/dist/mcp/server.js +809 -200
- package/dist/mcp/tools/create-task.js +24 -8
- package/dist/mcp/tools/update-task.js +18 -6
- package/dist/runtime/index.js +61 -25
- package/dist/tui/App.js +91 -55
- package/package.json +1 -1
|
@@ -981,7 +981,7 @@ var init_daemon_auth = __esm({
|
|
|
981
981
|
// src/lib/exe-daemon-client.ts
|
|
982
982
|
import net from "net";
|
|
983
983
|
import os4 from "os";
|
|
984
|
-
import { spawn } from "child_process";
|
|
984
|
+
import { spawn, execSync as execSync2 } from "child_process";
|
|
985
985
|
import { randomUUID } from "crypto";
|
|
986
986
|
import { existsSync as existsSync5, unlinkSync as unlinkSync2, readFileSync as readFileSync4, openSync, closeSync, statSync } from "fs";
|
|
987
987
|
import path5 from "path";
|
|
@@ -1011,6 +1011,14 @@ function handleData(chunk) {
|
|
|
1011
1011
|
}
|
|
1012
1012
|
}
|
|
1013
1013
|
}
|
|
1014
|
+
function isZombie(pid) {
|
|
1015
|
+
try {
|
|
1016
|
+
const state = execSync2(`ps -p ${pid} -o state=`, { encoding: "utf8", timeout: 2e3 }).trim();
|
|
1017
|
+
return state.startsWith("Z");
|
|
1018
|
+
} catch {
|
|
1019
|
+
return false;
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1014
1022
|
function cleanupStaleFiles() {
|
|
1015
1023
|
if (existsSync5(PID_PATH)) {
|
|
1016
1024
|
try {
|
|
@@ -1018,7 +1026,11 @@ function cleanupStaleFiles() {
|
|
|
1018
1026
|
if (pid > 0) {
|
|
1019
1027
|
try {
|
|
1020
1028
|
process.kill(pid, 0);
|
|
1021
|
-
|
|
1029
|
+
if (!isZombie(pid)) {
|
|
1030
|
+
return;
|
|
1031
|
+
}
|
|
1032
|
+
process.stderr.write(`[exed-client] PID ${pid} is a zombie \u2014 cleaning up stale files
|
|
1033
|
+
`);
|
|
1022
1034
|
} catch {
|
|
1023
1035
|
}
|
|
1024
1036
|
}
|
|
@@ -1046,8 +1058,8 @@ function findPackageRoot() {
|
|
|
1046
1058
|
function getAvailableMemoryGB() {
|
|
1047
1059
|
if (process.platform === "darwin") {
|
|
1048
1060
|
try {
|
|
1049
|
-
const { execSync:
|
|
1050
|
-
const vmstat =
|
|
1061
|
+
const { execSync: execSync4 } = __require("child_process");
|
|
1062
|
+
const vmstat = execSync4("vm_stat", { encoding: "utf8" });
|
|
1051
1063
|
const pageSize = 16384;
|
|
1052
1064
|
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
1053
1065
|
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
@@ -2833,6 +2845,12 @@ async function disposeDatabase() {
|
|
|
2833
2845
|
clearInterval(_walCheckpointTimer);
|
|
2834
2846
|
_walCheckpointTimer = null;
|
|
2835
2847
|
}
|
|
2848
|
+
if (_client) {
|
|
2849
|
+
try {
|
|
2850
|
+
await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
2851
|
+
} catch {
|
|
2852
|
+
}
|
|
2853
|
+
}
|
|
2836
2854
|
if (_daemonClient) {
|
|
2837
2855
|
_daemonClient.close();
|
|
2838
2856
|
_daemonClient = null;
|
|
@@ -3364,6 +3382,24 @@ var init_platform_procedures = __esm({
|
|
|
3364
3382
|
priority: "p0",
|
|
3365
3383
|
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."
|
|
3366
3384
|
},
|
|
3385
|
+
{
|
|
3386
|
+
title: "Bug report status check \u2014 surface available fixes on boot",
|
|
3387
|
+
domain: "support",
|
|
3388
|
+
priority: "p1",
|
|
3389
|
+
content: "Once per session (COO boot only, never repeat), call list_my_bug_reports to check if any previously filed bug reports have been fixed by AskExe. If any report has status 'fixed' with a fixed_version, surface it to the founder immediately: '\u{1F527} N bug fix(es) available \u2014 run exe-os update to get version X.Y.Z'. This is a one-time check at boot, not a recurring poll. If no reports exist or none are fixed, skip silently. If the MCP tool is unavailable or the network call fails, skip silently \u2014 this is informational, not blocking."
|
|
3390
|
+
},
|
|
3391
|
+
{
|
|
3392
|
+
title: "Feature request triage \u2014 upstream feature vs local customization",
|
|
3393
|
+
domain: "support",
|
|
3394
|
+
priority: "p0",
|
|
3395
|
+
content: "When an agent or founder identifies a desired capability that exe-os does not yet provide, the COO (or equivalent coordinator) must decide: is this a local customization (identity, behavior, procedure, config, branding, workflow preference that can be configured in customer-owned layers) or an upstream feature request (a platform capability that requires changes to exe-os code, shipped via npm update)? Local customizations: implement immediately using store_behavior, update_identity, company_procedure, or config changes. Upstream features: use create_feature_request to submit to AskExe. Include use case, business impact, and current workaround. Do NOT ask the founder for permission to file a feature request \u2014 file it proactively when the need is clear."
|
|
3396
|
+
},
|
|
3397
|
+
{
|
|
3398
|
+
title: "Feature request status check \u2014 surface shipped features on boot",
|
|
3399
|
+
domain: "support",
|
|
3400
|
+
priority: "p1",
|
|
3401
|
+
content: "Once per session (COO boot only, never repeat), call list_my_feature_requests to check if any previously filed feature requests have been shipped by AskExe. If any request has status 'shipped' with a shipped_version, surface it to the founder immediately: '\u{1F680} N feature(s) shipped \u2014 run exe-os update to get version X.Y.Z'. This is a one-time check at boot, not a recurring poll. If no requests exist or none are shipped, skip silently. If the MCP tool is unavailable or the network call fails, skip silently \u2014 this is informational, not blocking."
|
|
3402
|
+
},
|
|
3367
3403
|
// --- Operations ---
|
|
3368
3404
|
{
|
|
3369
3405
|
title: "Managers must supervise deployed workers",
|
|
@@ -3987,7 +4023,7 @@ init_database();
|
|
|
3987
4023
|
// src/lib/keychain.ts
|
|
3988
4024
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
3989
4025
|
import { existsSync as existsSync6, statSync as statSync2 } from "fs";
|
|
3990
|
-
import { execSync as
|
|
4026
|
+
import { execSync as execSync3 } from "child_process";
|
|
3991
4027
|
import path6 from "path";
|
|
3992
4028
|
import os5 from "os";
|
|
3993
4029
|
var SERVICE = "exe-os";
|
|
@@ -4008,13 +4044,13 @@ function linuxSecretAvailable() {
|
|
|
4008
4044
|
if (process.platform !== "linux") return false;
|
|
4009
4045
|
if (linuxSecretAvailability !== null) return linuxSecretAvailability;
|
|
4010
4046
|
try {
|
|
4011
|
-
|
|
4047
|
+
execSync3("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
|
|
4012
4048
|
} catch {
|
|
4013
4049
|
linuxSecretAvailability = false;
|
|
4014
4050
|
return false;
|
|
4015
4051
|
}
|
|
4016
4052
|
try {
|
|
4017
|
-
|
|
4053
|
+
execSync3("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
|
|
4018
4054
|
linuxSecretAvailability = true;
|
|
4019
4055
|
} catch {
|
|
4020
4056
|
linuxSecretAvailability = false;
|
|
@@ -4038,7 +4074,7 @@ function macKeychainGet(service = SERVICE) {
|
|
|
4038
4074
|
if (!nativeKeychainAllowed()) return null;
|
|
4039
4075
|
if (process.platform !== "darwin") return null;
|
|
4040
4076
|
try {
|
|
4041
|
-
return
|
|
4077
|
+
return execSync3(
|
|
4042
4078
|
`security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
4043
4079
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
4044
4080
|
).trim();
|
|
@@ -4051,13 +4087,13 @@ function macKeychainSet(value, service = SERVICE) {
|
|
|
4051
4087
|
if (process.platform !== "darwin") return false;
|
|
4052
4088
|
try {
|
|
4053
4089
|
try {
|
|
4054
|
-
|
|
4090
|
+
execSync3(
|
|
4055
4091
|
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
4056
4092
|
{ timeout: 5e3 }
|
|
4057
4093
|
);
|
|
4058
4094
|
} catch {
|
|
4059
4095
|
}
|
|
4060
|
-
|
|
4096
|
+
execSync3(
|
|
4061
4097
|
`security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
|
|
4062
4098
|
{ timeout: 5e3 }
|
|
4063
4099
|
);
|
|
@@ -4070,7 +4106,7 @@ function macKeychainDelete(service = SERVICE) {
|
|
|
4070
4106
|
if (!nativeKeychainAllowed()) return false;
|
|
4071
4107
|
if (process.platform !== "darwin") return false;
|
|
4072
4108
|
try {
|
|
4073
|
-
|
|
4109
|
+
execSync3(
|
|
4074
4110
|
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
4075
4111
|
{ timeout: 5e3 }
|
|
4076
4112
|
);
|
|
@@ -4082,7 +4118,7 @@ function macKeychainDelete(service = SERVICE) {
|
|
|
4082
4118
|
function linuxSecretGet(service = SERVICE) {
|
|
4083
4119
|
if (!linuxSecretAvailable()) return null;
|
|
4084
4120
|
try {
|
|
4085
|
-
return
|
|
4121
|
+
return execSync3(
|
|
4086
4122
|
`secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
4087
4123
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
4088
4124
|
).trim();
|
|
@@ -4093,7 +4129,7 @@ function linuxSecretGet(service = SERVICE) {
|
|
|
4093
4129
|
function linuxSecretSet(value, service = SERVICE) {
|
|
4094
4130
|
if (!linuxSecretAvailable()) return false;
|
|
4095
4131
|
try {
|
|
4096
|
-
|
|
4132
|
+
execSync3(
|
|
4097
4133
|
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
4098
4134
|
{ timeout: 5e3 }
|
|
4099
4135
|
);
|
|
@@ -4106,7 +4142,7 @@ function linuxSecretDelete(service = SERVICE) {
|
|
|
4106
4142
|
if (!nativeKeychainAllowed()) return false;
|
|
4107
4143
|
if (process.platform !== "linux") return false;
|
|
4108
4144
|
try {
|
|
4109
|
-
|
|
4145
|
+
execSync3(
|
|
4110
4146
|
`secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
4111
4147
|
{ timeout: 5e3 }
|
|
4112
4148
|
);
|
|
@@ -981,7 +981,7 @@ var init_daemon_auth = __esm({
|
|
|
981
981
|
// src/lib/exe-daemon-client.ts
|
|
982
982
|
import net from "net";
|
|
983
983
|
import os4 from "os";
|
|
984
|
-
import { spawn } from "child_process";
|
|
984
|
+
import { spawn, execSync as execSync2 } from "child_process";
|
|
985
985
|
import { randomUUID } from "crypto";
|
|
986
986
|
import { existsSync as existsSync5, unlinkSync as unlinkSync2, readFileSync as readFileSync4, openSync, closeSync, statSync } from "fs";
|
|
987
987
|
import path5 from "path";
|
|
@@ -1011,6 +1011,14 @@ function handleData(chunk) {
|
|
|
1011
1011
|
}
|
|
1012
1012
|
}
|
|
1013
1013
|
}
|
|
1014
|
+
function isZombie(pid) {
|
|
1015
|
+
try {
|
|
1016
|
+
const state = execSync2(`ps -p ${pid} -o state=`, { encoding: "utf8", timeout: 2e3 }).trim();
|
|
1017
|
+
return state.startsWith("Z");
|
|
1018
|
+
} catch {
|
|
1019
|
+
return false;
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1014
1022
|
function cleanupStaleFiles() {
|
|
1015
1023
|
if (existsSync5(PID_PATH)) {
|
|
1016
1024
|
try {
|
|
@@ -1018,7 +1026,11 @@ function cleanupStaleFiles() {
|
|
|
1018
1026
|
if (pid > 0) {
|
|
1019
1027
|
try {
|
|
1020
1028
|
process.kill(pid, 0);
|
|
1021
|
-
|
|
1029
|
+
if (!isZombie(pid)) {
|
|
1030
|
+
return;
|
|
1031
|
+
}
|
|
1032
|
+
process.stderr.write(`[exed-client] PID ${pid} is a zombie \u2014 cleaning up stale files
|
|
1033
|
+
`);
|
|
1022
1034
|
} catch {
|
|
1023
1035
|
}
|
|
1024
1036
|
}
|
|
@@ -1046,8 +1058,8 @@ function findPackageRoot() {
|
|
|
1046
1058
|
function getAvailableMemoryGB() {
|
|
1047
1059
|
if (process.platform === "darwin") {
|
|
1048
1060
|
try {
|
|
1049
|
-
const { execSync:
|
|
1050
|
-
const vmstat =
|
|
1061
|
+
const { execSync: execSync4 } = __require("child_process");
|
|
1062
|
+
const vmstat = execSync4("vm_stat", { encoding: "utf8" });
|
|
1051
1063
|
const pageSize = 16384;
|
|
1052
1064
|
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
1053
1065
|
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
@@ -2833,6 +2845,12 @@ async function disposeDatabase() {
|
|
|
2833
2845
|
clearInterval(_walCheckpointTimer);
|
|
2834
2846
|
_walCheckpointTimer = null;
|
|
2835
2847
|
}
|
|
2848
|
+
if (_client) {
|
|
2849
|
+
try {
|
|
2850
|
+
await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
2851
|
+
} catch {
|
|
2852
|
+
}
|
|
2853
|
+
}
|
|
2836
2854
|
if (_daemonClient) {
|
|
2837
2855
|
_daemonClient.close();
|
|
2838
2856
|
_daemonClient = null;
|
|
@@ -3364,6 +3382,24 @@ var init_platform_procedures = __esm({
|
|
|
3364
3382
|
priority: "p0",
|
|
3365
3383
|
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."
|
|
3366
3384
|
},
|
|
3385
|
+
{
|
|
3386
|
+
title: "Bug report status check \u2014 surface available fixes on boot",
|
|
3387
|
+
domain: "support",
|
|
3388
|
+
priority: "p1",
|
|
3389
|
+
content: "Once per session (COO boot only, never repeat), call list_my_bug_reports to check if any previously filed bug reports have been fixed by AskExe. If any report has status 'fixed' with a fixed_version, surface it to the founder immediately: '\u{1F527} N bug fix(es) available \u2014 run exe-os update to get version X.Y.Z'. This is a one-time check at boot, not a recurring poll. If no reports exist or none are fixed, skip silently. If the MCP tool is unavailable or the network call fails, skip silently \u2014 this is informational, not blocking."
|
|
3390
|
+
},
|
|
3391
|
+
{
|
|
3392
|
+
title: "Feature request triage \u2014 upstream feature vs local customization",
|
|
3393
|
+
domain: "support",
|
|
3394
|
+
priority: "p0",
|
|
3395
|
+
content: "When an agent or founder identifies a desired capability that exe-os does not yet provide, the COO (or equivalent coordinator) must decide: is this a local customization (identity, behavior, procedure, config, branding, workflow preference that can be configured in customer-owned layers) or an upstream feature request (a platform capability that requires changes to exe-os code, shipped via npm update)? Local customizations: implement immediately using store_behavior, update_identity, company_procedure, or config changes. Upstream features: use create_feature_request to submit to AskExe. Include use case, business impact, and current workaround. Do NOT ask the founder for permission to file a feature request \u2014 file it proactively when the need is clear."
|
|
3396
|
+
},
|
|
3397
|
+
{
|
|
3398
|
+
title: "Feature request status check \u2014 surface shipped features on boot",
|
|
3399
|
+
domain: "support",
|
|
3400
|
+
priority: "p1",
|
|
3401
|
+
content: "Once per session (COO boot only, never repeat), call list_my_feature_requests to check if any previously filed feature requests have been shipped by AskExe. If any request has status 'shipped' with a shipped_version, surface it to the founder immediately: '\u{1F680} N feature(s) shipped \u2014 run exe-os update to get version X.Y.Z'. This is a one-time check at boot, not a recurring poll. If no requests exist or none are shipped, skip silently. If the MCP tool is unavailable or the network call fails, skip silently \u2014 this is informational, not blocking."
|
|
3402
|
+
},
|
|
3367
3403
|
// --- Operations ---
|
|
3368
3404
|
{
|
|
3369
3405
|
title: "Managers must supervise deployed workers",
|
|
@@ -3575,7 +3611,7 @@ init_database();
|
|
|
3575
3611
|
// src/lib/keychain.ts
|
|
3576
3612
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
3577
3613
|
import { existsSync as existsSync6, statSync as statSync2 } from "fs";
|
|
3578
|
-
import { execSync as
|
|
3614
|
+
import { execSync as execSync3 } from "child_process";
|
|
3579
3615
|
import path6 from "path";
|
|
3580
3616
|
import os5 from "os";
|
|
3581
3617
|
var SERVICE = "exe-os";
|
|
@@ -3596,13 +3632,13 @@ function linuxSecretAvailable() {
|
|
|
3596
3632
|
if (process.platform !== "linux") return false;
|
|
3597
3633
|
if (linuxSecretAvailability !== null) return linuxSecretAvailability;
|
|
3598
3634
|
try {
|
|
3599
|
-
|
|
3635
|
+
execSync3("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
|
|
3600
3636
|
} catch {
|
|
3601
3637
|
linuxSecretAvailability = false;
|
|
3602
3638
|
return false;
|
|
3603
3639
|
}
|
|
3604
3640
|
try {
|
|
3605
|
-
|
|
3641
|
+
execSync3("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
|
|
3606
3642
|
linuxSecretAvailability = true;
|
|
3607
3643
|
} catch {
|
|
3608
3644
|
linuxSecretAvailability = false;
|
|
@@ -3626,7 +3662,7 @@ function macKeychainGet(service = SERVICE) {
|
|
|
3626
3662
|
if (!nativeKeychainAllowed()) return null;
|
|
3627
3663
|
if (process.platform !== "darwin") return null;
|
|
3628
3664
|
try {
|
|
3629
|
-
return
|
|
3665
|
+
return execSync3(
|
|
3630
3666
|
`security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
3631
3667
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
3632
3668
|
).trim();
|
|
@@ -3639,13 +3675,13 @@ function macKeychainSet(value, service = SERVICE) {
|
|
|
3639
3675
|
if (process.platform !== "darwin") return false;
|
|
3640
3676
|
try {
|
|
3641
3677
|
try {
|
|
3642
|
-
|
|
3678
|
+
execSync3(
|
|
3643
3679
|
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
3644
3680
|
{ timeout: 5e3 }
|
|
3645
3681
|
);
|
|
3646
3682
|
} catch {
|
|
3647
3683
|
}
|
|
3648
|
-
|
|
3684
|
+
execSync3(
|
|
3649
3685
|
`security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
|
|
3650
3686
|
{ timeout: 5e3 }
|
|
3651
3687
|
);
|
|
@@ -3658,7 +3694,7 @@ function macKeychainDelete(service = SERVICE) {
|
|
|
3658
3694
|
if (!nativeKeychainAllowed()) return false;
|
|
3659
3695
|
if (process.platform !== "darwin") return false;
|
|
3660
3696
|
try {
|
|
3661
|
-
|
|
3697
|
+
execSync3(
|
|
3662
3698
|
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
3663
3699
|
{ timeout: 5e3 }
|
|
3664
3700
|
);
|
|
@@ -3670,7 +3706,7 @@ function macKeychainDelete(service = SERVICE) {
|
|
|
3670
3706
|
function linuxSecretGet(service = SERVICE) {
|
|
3671
3707
|
if (!linuxSecretAvailable()) return null;
|
|
3672
3708
|
try {
|
|
3673
|
-
return
|
|
3709
|
+
return execSync3(
|
|
3674
3710
|
`secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3675
3711
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
3676
3712
|
).trim();
|
|
@@ -3681,7 +3717,7 @@ function linuxSecretGet(service = SERVICE) {
|
|
|
3681
3717
|
function linuxSecretSet(value, service = SERVICE) {
|
|
3682
3718
|
if (!linuxSecretAvailable()) return false;
|
|
3683
3719
|
try {
|
|
3684
|
-
|
|
3720
|
+
execSync3(
|
|
3685
3721
|
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3686
3722
|
{ timeout: 5e3 }
|
|
3687
3723
|
);
|
|
@@ -3694,7 +3730,7 @@ function linuxSecretDelete(service = SERVICE) {
|
|
|
3694
3730
|
if (!nativeKeychainAllowed()) return false;
|
|
3695
3731
|
if (process.platform !== "linux") return false;
|
|
3696
3732
|
try {
|
|
3697
|
-
|
|
3733
|
+
execSync3(
|
|
3698
3734
|
`secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3699
3735
|
{ timeout: 5e3 }
|
|
3700
3736
|
);
|
|
@@ -981,7 +981,7 @@ var init_daemon_auth = __esm({
|
|
|
981
981
|
// src/lib/exe-daemon-client.ts
|
|
982
982
|
import net from "net";
|
|
983
983
|
import os4 from "os";
|
|
984
|
-
import { spawn } from "child_process";
|
|
984
|
+
import { spawn, execSync as execSync2 } from "child_process";
|
|
985
985
|
import { randomUUID } from "crypto";
|
|
986
986
|
import { existsSync as existsSync5, unlinkSync as unlinkSync2, readFileSync as readFileSync4, openSync, closeSync, statSync } from "fs";
|
|
987
987
|
import path5 from "path";
|
|
@@ -1011,6 +1011,14 @@ function handleData(chunk) {
|
|
|
1011
1011
|
}
|
|
1012
1012
|
}
|
|
1013
1013
|
}
|
|
1014
|
+
function isZombie(pid) {
|
|
1015
|
+
try {
|
|
1016
|
+
const state = execSync2(`ps -p ${pid} -o state=`, { encoding: "utf8", timeout: 2e3 }).trim();
|
|
1017
|
+
return state.startsWith("Z");
|
|
1018
|
+
} catch {
|
|
1019
|
+
return false;
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1014
1022
|
function cleanupStaleFiles() {
|
|
1015
1023
|
if (existsSync5(PID_PATH)) {
|
|
1016
1024
|
try {
|
|
@@ -1018,7 +1026,11 @@ function cleanupStaleFiles() {
|
|
|
1018
1026
|
if (pid > 0) {
|
|
1019
1027
|
try {
|
|
1020
1028
|
process.kill(pid, 0);
|
|
1021
|
-
|
|
1029
|
+
if (!isZombie(pid)) {
|
|
1030
|
+
return;
|
|
1031
|
+
}
|
|
1032
|
+
process.stderr.write(`[exed-client] PID ${pid} is a zombie \u2014 cleaning up stale files
|
|
1033
|
+
`);
|
|
1022
1034
|
} catch {
|
|
1023
1035
|
}
|
|
1024
1036
|
}
|
|
@@ -1046,8 +1058,8 @@ function findPackageRoot() {
|
|
|
1046
1058
|
function getAvailableMemoryGB() {
|
|
1047
1059
|
if (process.platform === "darwin") {
|
|
1048
1060
|
try {
|
|
1049
|
-
const { execSync:
|
|
1050
|
-
const vmstat =
|
|
1061
|
+
const { execSync: execSync4 } = __require("child_process");
|
|
1062
|
+
const vmstat = execSync4("vm_stat", { encoding: "utf8" });
|
|
1051
1063
|
const pageSize = 16384;
|
|
1052
1064
|
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
1053
1065
|
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
@@ -2833,6 +2845,12 @@ async function disposeDatabase() {
|
|
|
2833
2845
|
clearInterval(_walCheckpointTimer);
|
|
2834
2846
|
_walCheckpointTimer = null;
|
|
2835
2847
|
}
|
|
2848
|
+
if (_client) {
|
|
2849
|
+
try {
|
|
2850
|
+
await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
2851
|
+
} catch {
|
|
2852
|
+
}
|
|
2853
|
+
}
|
|
2836
2854
|
if (_daemonClient) {
|
|
2837
2855
|
_daemonClient.close();
|
|
2838
2856
|
_daemonClient = null;
|
|
@@ -3364,6 +3382,24 @@ var init_platform_procedures = __esm({
|
|
|
3364
3382
|
priority: "p0",
|
|
3365
3383
|
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."
|
|
3366
3384
|
},
|
|
3385
|
+
{
|
|
3386
|
+
title: "Bug report status check \u2014 surface available fixes on boot",
|
|
3387
|
+
domain: "support",
|
|
3388
|
+
priority: "p1",
|
|
3389
|
+
content: "Once per session (COO boot only, never repeat), call list_my_bug_reports to check if any previously filed bug reports have been fixed by AskExe. If any report has status 'fixed' with a fixed_version, surface it to the founder immediately: '\u{1F527} N bug fix(es) available \u2014 run exe-os update to get version X.Y.Z'. This is a one-time check at boot, not a recurring poll. If no reports exist or none are fixed, skip silently. If the MCP tool is unavailable or the network call fails, skip silently \u2014 this is informational, not blocking."
|
|
3390
|
+
},
|
|
3391
|
+
{
|
|
3392
|
+
title: "Feature request triage \u2014 upstream feature vs local customization",
|
|
3393
|
+
domain: "support",
|
|
3394
|
+
priority: "p0",
|
|
3395
|
+
content: "When an agent or founder identifies a desired capability that exe-os does not yet provide, the COO (or equivalent coordinator) must decide: is this a local customization (identity, behavior, procedure, config, branding, workflow preference that can be configured in customer-owned layers) or an upstream feature request (a platform capability that requires changes to exe-os code, shipped via npm update)? Local customizations: implement immediately using store_behavior, update_identity, company_procedure, or config changes. Upstream features: use create_feature_request to submit to AskExe. Include use case, business impact, and current workaround. Do NOT ask the founder for permission to file a feature request \u2014 file it proactively when the need is clear."
|
|
3396
|
+
},
|
|
3397
|
+
{
|
|
3398
|
+
title: "Feature request status check \u2014 surface shipped features on boot",
|
|
3399
|
+
domain: "support",
|
|
3400
|
+
priority: "p1",
|
|
3401
|
+
content: "Once per session (COO boot only, never repeat), call list_my_feature_requests to check if any previously filed feature requests have been shipped by AskExe. If any request has status 'shipped' with a shipped_version, surface it to the founder immediately: '\u{1F680} N feature(s) shipped \u2014 run exe-os update to get version X.Y.Z'. This is a one-time check at boot, not a recurring poll. If no requests exist or none are shipped, skip silently. If the MCP tool is unavailable or the network call fails, skip silently \u2014 this is informational, not blocking."
|
|
3402
|
+
},
|
|
3367
3403
|
// --- Operations ---
|
|
3368
3404
|
{
|
|
3369
3405
|
title: "Managers must supervise deployed workers",
|
|
@@ -3699,7 +3735,7 @@ init_database();
|
|
|
3699
3735
|
// src/lib/keychain.ts
|
|
3700
3736
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
3701
3737
|
import { existsSync as existsSync6, statSync as statSync2 } from "fs";
|
|
3702
|
-
import { execSync as
|
|
3738
|
+
import { execSync as execSync3 } from "child_process";
|
|
3703
3739
|
import path6 from "path";
|
|
3704
3740
|
import os5 from "os";
|
|
3705
3741
|
var SERVICE = "exe-os";
|
|
@@ -3720,13 +3756,13 @@ function linuxSecretAvailable() {
|
|
|
3720
3756
|
if (process.platform !== "linux") return false;
|
|
3721
3757
|
if (linuxSecretAvailability !== null) return linuxSecretAvailability;
|
|
3722
3758
|
try {
|
|
3723
|
-
|
|
3759
|
+
execSync3("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
|
|
3724
3760
|
} catch {
|
|
3725
3761
|
linuxSecretAvailability = false;
|
|
3726
3762
|
return false;
|
|
3727
3763
|
}
|
|
3728
3764
|
try {
|
|
3729
|
-
|
|
3765
|
+
execSync3("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
|
|
3730
3766
|
linuxSecretAvailability = true;
|
|
3731
3767
|
} catch {
|
|
3732
3768
|
linuxSecretAvailability = false;
|
|
@@ -3750,7 +3786,7 @@ function macKeychainGet(service = SERVICE) {
|
|
|
3750
3786
|
if (!nativeKeychainAllowed()) return null;
|
|
3751
3787
|
if (process.platform !== "darwin") return null;
|
|
3752
3788
|
try {
|
|
3753
|
-
return
|
|
3789
|
+
return execSync3(
|
|
3754
3790
|
`security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
3755
3791
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
3756
3792
|
).trim();
|
|
@@ -3763,13 +3799,13 @@ function macKeychainSet(value, service = SERVICE) {
|
|
|
3763
3799
|
if (process.platform !== "darwin") return false;
|
|
3764
3800
|
try {
|
|
3765
3801
|
try {
|
|
3766
|
-
|
|
3802
|
+
execSync3(
|
|
3767
3803
|
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
3768
3804
|
{ timeout: 5e3 }
|
|
3769
3805
|
);
|
|
3770
3806
|
} catch {
|
|
3771
3807
|
}
|
|
3772
|
-
|
|
3808
|
+
execSync3(
|
|
3773
3809
|
`security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
|
|
3774
3810
|
{ timeout: 5e3 }
|
|
3775
3811
|
);
|
|
@@ -3782,7 +3818,7 @@ function macKeychainDelete(service = SERVICE) {
|
|
|
3782
3818
|
if (!nativeKeychainAllowed()) return false;
|
|
3783
3819
|
if (process.platform !== "darwin") return false;
|
|
3784
3820
|
try {
|
|
3785
|
-
|
|
3821
|
+
execSync3(
|
|
3786
3822
|
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
3787
3823
|
{ timeout: 5e3 }
|
|
3788
3824
|
);
|
|
@@ -3794,7 +3830,7 @@ function macKeychainDelete(service = SERVICE) {
|
|
|
3794
3830
|
function linuxSecretGet(service = SERVICE) {
|
|
3795
3831
|
if (!linuxSecretAvailable()) return null;
|
|
3796
3832
|
try {
|
|
3797
|
-
return
|
|
3833
|
+
return execSync3(
|
|
3798
3834
|
`secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3799
3835
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
3800
3836
|
).trim();
|
|
@@ -3805,7 +3841,7 @@ function linuxSecretGet(service = SERVICE) {
|
|
|
3805
3841
|
function linuxSecretSet(value, service = SERVICE) {
|
|
3806
3842
|
if (!linuxSecretAvailable()) return false;
|
|
3807
3843
|
try {
|
|
3808
|
-
|
|
3844
|
+
execSync3(
|
|
3809
3845
|
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3810
3846
|
{ timeout: 5e3 }
|
|
3811
3847
|
);
|
|
@@ -3818,7 +3854,7 @@ function linuxSecretDelete(service = SERVICE) {
|
|
|
3818
3854
|
if (!nativeKeychainAllowed()) return false;
|
|
3819
3855
|
if (process.platform !== "linux") return false;
|
|
3820
3856
|
try {
|
|
3821
|
-
|
|
3857
|
+
execSync3(
|
|
3822
3858
|
`secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3823
3859
|
{ timeout: 5e3 }
|
|
3824
3860
|
);
|