@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
package/dist/bin/exe-status.js
CHANGED
|
@@ -1014,7 +1014,7 @@ __export(exe_daemon_client_exports, {
|
|
|
1014
1014
|
});
|
|
1015
1015
|
import net from "net";
|
|
1016
1016
|
import os4 from "os";
|
|
1017
|
-
import { spawn } from "child_process";
|
|
1017
|
+
import { spawn, execSync as execSync2 } from "child_process";
|
|
1018
1018
|
import { randomUUID } from "crypto";
|
|
1019
1019
|
import { existsSync as existsSync5, unlinkSync as unlinkSync2, readFileSync as readFileSync4, openSync, closeSync, statSync } from "fs";
|
|
1020
1020
|
import path5 from "path";
|
|
@@ -1044,6 +1044,14 @@ function handleData(chunk) {
|
|
|
1044
1044
|
}
|
|
1045
1045
|
}
|
|
1046
1046
|
}
|
|
1047
|
+
function isZombie(pid) {
|
|
1048
|
+
try {
|
|
1049
|
+
const state = execSync2(`ps -p ${pid} -o state=`, { encoding: "utf8", timeout: 2e3 }).trim();
|
|
1050
|
+
return state.startsWith("Z");
|
|
1051
|
+
} catch {
|
|
1052
|
+
return false;
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1047
1055
|
function cleanupStaleFiles() {
|
|
1048
1056
|
if (existsSync5(PID_PATH)) {
|
|
1049
1057
|
try {
|
|
@@ -1051,7 +1059,11 @@ function cleanupStaleFiles() {
|
|
|
1051
1059
|
if (pid > 0) {
|
|
1052
1060
|
try {
|
|
1053
1061
|
process.kill(pid, 0);
|
|
1054
|
-
|
|
1062
|
+
if (!isZombie(pid)) {
|
|
1063
|
+
return;
|
|
1064
|
+
}
|
|
1065
|
+
process.stderr.write(`[exed-client] PID ${pid} is a zombie \u2014 cleaning up stale files
|
|
1066
|
+
`);
|
|
1055
1067
|
} catch {
|
|
1056
1068
|
}
|
|
1057
1069
|
}
|
|
@@ -1079,8 +1091,8 @@ function findPackageRoot() {
|
|
|
1079
1091
|
function getAvailableMemoryGB() {
|
|
1080
1092
|
if (process.platform === "darwin") {
|
|
1081
1093
|
try {
|
|
1082
|
-
const { execSync:
|
|
1083
|
-
const vmstat =
|
|
1094
|
+
const { execSync: execSync7 } = __require("child_process");
|
|
1095
|
+
const vmstat = execSync7("vm_stat", { encoding: "utf8" });
|
|
1084
1096
|
const pageSize = 16384;
|
|
1085
1097
|
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
1086
1098
|
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
@@ -3070,6 +3082,12 @@ async function disposeDatabase() {
|
|
|
3070
3082
|
clearInterval(_walCheckpointTimer);
|
|
3071
3083
|
_walCheckpointTimer = null;
|
|
3072
3084
|
}
|
|
3085
|
+
if (_client) {
|
|
3086
|
+
try {
|
|
3087
|
+
await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
3088
|
+
} catch {
|
|
3089
|
+
}
|
|
3090
|
+
}
|
|
3073
3091
|
if (_daemonClient) {
|
|
3074
3092
|
_daemonClient.close();
|
|
3075
3093
|
_daemonClient = null;
|
|
@@ -3106,7 +3124,7 @@ var init_database = __esm({
|
|
|
3106
3124
|
// src/lib/keychain.ts
|
|
3107
3125
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
3108
3126
|
import { existsSync as existsSync6, statSync as statSync2 } from "fs";
|
|
3109
|
-
import { execSync as
|
|
3127
|
+
import { execSync as execSync3 } from "child_process";
|
|
3110
3128
|
import path6 from "path";
|
|
3111
3129
|
import os5 from "os";
|
|
3112
3130
|
function getKeyDir() {
|
|
@@ -3123,13 +3141,13 @@ function linuxSecretAvailable() {
|
|
|
3123
3141
|
if (process.platform !== "linux") return false;
|
|
3124
3142
|
if (linuxSecretAvailability !== null) return linuxSecretAvailability;
|
|
3125
3143
|
try {
|
|
3126
|
-
|
|
3144
|
+
execSync3("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
|
|
3127
3145
|
} catch {
|
|
3128
3146
|
linuxSecretAvailability = false;
|
|
3129
3147
|
return false;
|
|
3130
3148
|
}
|
|
3131
3149
|
try {
|
|
3132
|
-
|
|
3150
|
+
execSync3("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
|
|
3133
3151
|
linuxSecretAvailability = true;
|
|
3134
3152
|
} catch {
|
|
3135
3153
|
linuxSecretAvailability = false;
|
|
@@ -3153,7 +3171,7 @@ function macKeychainGet(service = SERVICE) {
|
|
|
3153
3171
|
if (!nativeKeychainAllowed()) return null;
|
|
3154
3172
|
if (process.platform !== "darwin") return null;
|
|
3155
3173
|
try {
|
|
3156
|
-
return
|
|
3174
|
+
return execSync3(
|
|
3157
3175
|
`security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
3158
3176
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
3159
3177
|
).trim();
|
|
@@ -3166,13 +3184,13 @@ function macKeychainSet(value, service = SERVICE) {
|
|
|
3166
3184
|
if (process.platform !== "darwin") return false;
|
|
3167
3185
|
try {
|
|
3168
3186
|
try {
|
|
3169
|
-
|
|
3187
|
+
execSync3(
|
|
3170
3188
|
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
3171
3189
|
{ timeout: 5e3 }
|
|
3172
3190
|
);
|
|
3173
3191
|
} catch {
|
|
3174
3192
|
}
|
|
3175
|
-
|
|
3193
|
+
execSync3(
|
|
3176
3194
|
`security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
|
|
3177
3195
|
{ timeout: 5e3 }
|
|
3178
3196
|
);
|
|
@@ -3185,7 +3203,7 @@ function macKeychainDelete(service = SERVICE) {
|
|
|
3185
3203
|
if (!nativeKeychainAllowed()) return false;
|
|
3186
3204
|
if (process.platform !== "darwin") return false;
|
|
3187
3205
|
try {
|
|
3188
|
-
|
|
3206
|
+
execSync3(
|
|
3189
3207
|
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
3190
3208
|
{ timeout: 5e3 }
|
|
3191
3209
|
);
|
|
@@ -3197,7 +3215,7 @@ function macKeychainDelete(service = SERVICE) {
|
|
|
3197
3215
|
function linuxSecretGet(service = SERVICE) {
|
|
3198
3216
|
if (!linuxSecretAvailable()) return null;
|
|
3199
3217
|
try {
|
|
3200
|
-
return
|
|
3218
|
+
return execSync3(
|
|
3201
3219
|
`secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3202
3220
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
3203
3221
|
).trim();
|
|
@@ -3208,7 +3226,7 @@ function linuxSecretGet(service = SERVICE) {
|
|
|
3208
3226
|
function linuxSecretSet(value, service = SERVICE) {
|
|
3209
3227
|
if (!linuxSecretAvailable()) return false;
|
|
3210
3228
|
try {
|
|
3211
|
-
|
|
3229
|
+
execSync3(
|
|
3212
3230
|
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3213
3231
|
{ timeout: 5e3 }
|
|
3214
3232
|
);
|
|
@@ -3221,7 +3239,7 @@ function linuxSecretDelete(service = SERVICE) {
|
|
|
3221
3239
|
if (!nativeKeychainAllowed()) return false;
|
|
3222
3240
|
if (process.platform !== "linux") return false;
|
|
3223
3241
|
try {
|
|
3224
|
-
|
|
3242
|
+
execSync3(
|
|
3225
3243
|
`secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3226
3244
|
{ timeout: 5e3 }
|
|
3227
3245
|
);
|
|
@@ -4158,6 +4176,24 @@ var init_platform_procedures = __esm({
|
|
|
4158
4176
|
priority: "p0",
|
|
4159
4177
|
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."
|
|
4160
4178
|
},
|
|
4179
|
+
{
|
|
4180
|
+
title: "Bug report status check \u2014 surface available fixes on boot",
|
|
4181
|
+
domain: "support",
|
|
4182
|
+
priority: "p1",
|
|
4183
|
+
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."
|
|
4184
|
+
},
|
|
4185
|
+
{
|
|
4186
|
+
title: "Feature request triage \u2014 upstream feature vs local customization",
|
|
4187
|
+
domain: "support",
|
|
4188
|
+
priority: "p0",
|
|
4189
|
+
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."
|
|
4190
|
+
},
|
|
4191
|
+
{
|
|
4192
|
+
title: "Feature request status check \u2014 surface shipped features on boot",
|
|
4193
|
+
domain: "support",
|
|
4194
|
+
priority: "p1",
|
|
4195
|
+
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."
|
|
4196
|
+
},
|
|
4161
4197
|
// --- Operations ---
|
|
4162
4198
|
{
|
|
4163
4199
|
title: "Managers must supervise deployed workers",
|
|
@@ -5409,7 +5445,7 @@ var init_session_registry = __esm({
|
|
|
5409
5445
|
});
|
|
5410
5446
|
|
|
5411
5447
|
// src/lib/session-key.ts
|
|
5412
|
-
import { execSync as
|
|
5448
|
+
import { execSync as execSync5 } from "child_process";
|
|
5413
5449
|
function normalizeCommand(command) {
|
|
5414
5450
|
const trimmed = command.trim().toLowerCase();
|
|
5415
5451
|
const parts = trimmed.split(/[\\/]/);
|
|
@@ -5428,7 +5464,7 @@ function resolveRuntimeProcess() {
|
|
|
5428
5464
|
let pid = process.ppid;
|
|
5429
5465
|
for (let i = 0; i < 10; i++) {
|
|
5430
5466
|
try {
|
|
5431
|
-
const info =
|
|
5467
|
+
const info = execSync5(`ps -p ${pid} -o ppid=,comm=`, {
|
|
5432
5468
|
encoding: "utf8",
|
|
5433
5469
|
timeout: 2e3
|
|
5434
5470
|
}).trim();
|
|
@@ -5594,7 +5630,7 @@ var init_transport = __esm({
|
|
|
5594
5630
|
});
|
|
5595
5631
|
|
|
5596
5632
|
// src/lib/cc-agent-support.ts
|
|
5597
|
-
import { execSync as
|
|
5633
|
+
import { execSync as execSync6 } from "child_process";
|
|
5598
5634
|
var init_cc_agent_support = __esm({
|
|
5599
5635
|
"src/lib/cc-agent-support.ts"() {
|
|
5600
5636
|
"use strict";
|
|
@@ -5894,13 +5930,13 @@ async function fastDbInit() {
|
|
|
5894
5930
|
init_database();
|
|
5895
5931
|
|
|
5896
5932
|
// src/lib/tmux-status.ts
|
|
5897
|
-
import { execSync as
|
|
5933
|
+
import { execSync as execSync4 } from "child_process";
|
|
5898
5934
|
function inTmux() {
|
|
5899
5935
|
if (process.env.TMUX || process.env.TMUX_PANE) return true;
|
|
5900
5936
|
const term = process.env.TERM ?? "";
|
|
5901
5937
|
if (term.startsWith("tmux") || term.startsWith("screen")) return true;
|
|
5902
5938
|
try {
|
|
5903
|
-
|
|
5939
|
+
execSync4("tmux display-message -p '#{session_name}' 2>/dev/null", {
|
|
5904
5940
|
encoding: "utf8",
|
|
5905
5941
|
timeout: 2e3
|
|
5906
5942
|
});
|
|
@@ -5910,12 +5946,12 @@ function inTmux() {
|
|
|
5910
5946
|
try {
|
|
5911
5947
|
let pid = process.ppid;
|
|
5912
5948
|
for (let depth = 0; depth < 8 && pid > 1; depth++) {
|
|
5913
|
-
const comm =
|
|
5949
|
+
const comm = execSync4(`ps -p ${pid} -o comm= 2>/dev/null`, {
|
|
5914
5950
|
encoding: "utf8",
|
|
5915
5951
|
timeout: 1e3
|
|
5916
5952
|
}).trim();
|
|
5917
5953
|
if (/tmux/.test(comm)) return true;
|
|
5918
|
-
const ppid =
|
|
5954
|
+
const ppid = execSync4(`ps -p ${pid} -o ppid= 2>/dev/null`, {
|
|
5919
5955
|
encoding: "utf8",
|
|
5920
5956
|
timeout: 1e3
|
|
5921
5957
|
}).trim();
|
|
@@ -5928,7 +5964,7 @@ function inTmux() {
|
|
|
5928
5964
|
}
|
|
5929
5965
|
function listTmuxSessions() {
|
|
5930
5966
|
try {
|
|
5931
|
-
const out =
|
|
5967
|
+
const out = execSync4("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
|
|
5932
5968
|
encoding: "utf8",
|
|
5933
5969
|
timeout: 3e3
|
|
5934
5970
|
});
|
|
@@ -5939,7 +5975,7 @@ function listTmuxSessions() {
|
|
|
5939
5975
|
}
|
|
5940
5976
|
function capturePaneLines(windowName, lines = 10) {
|
|
5941
5977
|
try {
|
|
5942
|
-
const out =
|
|
5978
|
+
const out = execSync4(
|
|
5943
5979
|
`tmux capture-pane -t ${JSON.stringify(windowName)} -p 2>/dev/null | tail -${lines}`,
|
|
5944
5980
|
{ encoding: "utf8", timeout: 3e3 }
|
|
5945
5981
|
);
|
|
@@ -5950,7 +5986,7 @@ function capturePaneLines(windowName, lines = 10) {
|
|
|
5950
5986
|
}
|
|
5951
5987
|
function getPaneCwd(windowName) {
|
|
5952
5988
|
try {
|
|
5953
|
-
const out =
|
|
5989
|
+
const out = execSync4(
|
|
5954
5990
|
`tmux display-message -t ${JSON.stringify(windowName)} -p '#{pane_current_path}' 2>/dev/null`,
|
|
5955
5991
|
{ encoding: "utf8", timeout: 3e3 }
|
|
5956
5992
|
);
|
|
@@ -5961,7 +5997,7 @@ function getPaneCwd(windowName) {
|
|
|
5961
5997
|
}
|
|
5962
5998
|
function projectFromPath(dir) {
|
|
5963
5999
|
try {
|
|
5964
|
-
const root =
|
|
6000
|
+
const root = execSync4("git -C " + JSON.stringify(dir) + " rev-parse --show-toplevel 2>/dev/null", {
|
|
5965
6001
|
encoding: "utf8",
|
|
5966
6002
|
timeout: 3e3
|
|
5967
6003
|
}).trim();
|
|
@@ -6020,7 +6056,7 @@ function getEmployeeStatuses(employeeNames) {
|
|
|
6020
6056
|
}
|
|
6021
6057
|
let paneAlive = true;
|
|
6022
6058
|
try {
|
|
6023
|
-
const paneStatus =
|
|
6059
|
+
const paneStatus = execSync4(
|
|
6024
6060
|
`tmux list-panes -t ${JSON.stringify(sessionName)} -F '#{pane_dead}' 2>/dev/null`,
|
|
6025
6061
|
{ encoding: "utf8", timeout: 3e3 }
|
|
6026
6062
|
).trim();
|
package/dist/bin/exe-team.js
CHANGED
|
@@ -1003,7 +1003,7 @@ __export(exe_daemon_client_exports, {
|
|
|
1003
1003
|
});
|
|
1004
1004
|
import net from "net";
|
|
1005
1005
|
import os4 from "os";
|
|
1006
|
-
import { spawn } from "child_process";
|
|
1006
|
+
import { spawn, execSync as execSync2 } from "child_process";
|
|
1007
1007
|
import { randomUUID } from "crypto";
|
|
1008
1008
|
import { existsSync as existsSync5, unlinkSync as unlinkSync2, readFileSync as readFileSync4, openSync, closeSync, statSync } from "fs";
|
|
1009
1009
|
import path5 from "path";
|
|
@@ -1033,6 +1033,14 @@ function handleData(chunk) {
|
|
|
1033
1033
|
}
|
|
1034
1034
|
}
|
|
1035
1035
|
}
|
|
1036
|
+
function isZombie(pid) {
|
|
1037
|
+
try {
|
|
1038
|
+
const state = execSync2(`ps -p ${pid} -o state=`, { encoding: "utf8", timeout: 2e3 }).trim();
|
|
1039
|
+
return state.startsWith("Z");
|
|
1040
|
+
} catch {
|
|
1041
|
+
return false;
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1036
1044
|
function cleanupStaleFiles() {
|
|
1037
1045
|
if (existsSync5(PID_PATH)) {
|
|
1038
1046
|
try {
|
|
@@ -1040,7 +1048,11 @@ function cleanupStaleFiles() {
|
|
|
1040
1048
|
if (pid > 0) {
|
|
1041
1049
|
try {
|
|
1042
1050
|
process.kill(pid, 0);
|
|
1043
|
-
|
|
1051
|
+
if (!isZombie(pid)) {
|
|
1052
|
+
return;
|
|
1053
|
+
}
|
|
1054
|
+
process.stderr.write(`[exed-client] PID ${pid} is a zombie \u2014 cleaning up stale files
|
|
1055
|
+
`);
|
|
1044
1056
|
} catch {
|
|
1045
1057
|
}
|
|
1046
1058
|
}
|
|
@@ -1068,8 +1080,8 @@ function findPackageRoot() {
|
|
|
1068
1080
|
function getAvailableMemoryGB() {
|
|
1069
1081
|
if (process.platform === "darwin") {
|
|
1070
1082
|
try {
|
|
1071
|
-
const { execSync:
|
|
1072
|
-
const vmstat =
|
|
1083
|
+
const { execSync: execSync4 } = __require("child_process");
|
|
1084
|
+
const vmstat = execSync4("vm_stat", { encoding: "utf8" });
|
|
1073
1085
|
const pageSize = 16384;
|
|
1074
1086
|
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
1075
1087
|
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
@@ -3059,6 +3071,12 @@ async function disposeDatabase() {
|
|
|
3059
3071
|
clearInterval(_walCheckpointTimer);
|
|
3060
3072
|
_walCheckpointTimer = null;
|
|
3061
3073
|
}
|
|
3074
|
+
if (_client) {
|
|
3075
|
+
try {
|
|
3076
|
+
await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
3077
|
+
} catch {
|
|
3078
|
+
}
|
|
3079
|
+
}
|
|
3062
3080
|
if (_daemonClient) {
|
|
3063
3081
|
_daemonClient.close();
|
|
3064
3082
|
_daemonClient = null;
|
|
@@ -3095,7 +3113,7 @@ var init_database = __esm({
|
|
|
3095
3113
|
// src/lib/keychain.ts
|
|
3096
3114
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
3097
3115
|
import { existsSync as existsSync6, statSync as statSync2 } from "fs";
|
|
3098
|
-
import { execSync as
|
|
3116
|
+
import { execSync as execSync3 } from "child_process";
|
|
3099
3117
|
import path6 from "path";
|
|
3100
3118
|
import os5 from "os";
|
|
3101
3119
|
function getKeyDir() {
|
|
@@ -3112,13 +3130,13 @@ function linuxSecretAvailable() {
|
|
|
3112
3130
|
if (process.platform !== "linux") return false;
|
|
3113
3131
|
if (linuxSecretAvailability !== null) return linuxSecretAvailability;
|
|
3114
3132
|
try {
|
|
3115
|
-
|
|
3133
|
+
execSync3("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
|
|
3116
3134
|
} catch {
|
|
3117
3135
|
linuxSecretAvailability = false;
|
|
3118
3136
|
return false;
|
|
3119
3137
|
}
|
|
3120
3138
|
try {
|
|
3121
|
-
|
|
3139
|
+
execSync3("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
|
|
3122
3140
|
linuxSecretAvailability = true;
|
|
3123
3141
|
} catch {
|
|
3124
3142
|
linuxSecretAvailability = false;
|
|
@@ -3142,7 +3160,7 @@ function macKeychainGet(service = SERVICE) {
|
|
|
3142
3160
|
if (!nativeKeychainAllowed()) return null;
|
|
3143
3161
|
if (process.platform !== "darwin") return null;
|
|
3144
3162
|
try {
|
|
3145
|
-
return
|
|
3163
|
+
return execSync3(
|
|
3146
3164
|
`security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
3147
3165
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
3148
3166
|
).trim();
|
|
@@ -3155,13 +3173,13 @@ function macKeychainSet(value, service = SERVICE) {
|
|
|
3155
3173
|
if (process.platform !== "darwin") return false;
|
|
3156
3174
|
try {
|
|
3157
3175
|
try {
|
|
3158
|
-
|
|
3176
|
+
execSync3(
|
|
3159
3177
|
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
3160
3178
|
{ timeout: 5e3 }
|
|
3161
3179
|
);
|
|
3162
3180
|
} catch {
|
|
3163
3181
|
}
|
|
3164
|
-
|
|
3182
|
+
execSync3(
|
|
3165
3183
|
`security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
|
|
3166
3184
|
{ timeout: 5e3 }
|
|
3167
3185
|
);
|
|
@@ -3174,7 +3192,7 @@ function macKeychainDelete(service = SERVICE) {
|
|
|
3174
3192
|
if (!nativeKeychainAllowed()) return false;
|
|
3175
3193
|
if (process.platform !== "darwin") return false;
|
|
3176
3194
|
try {
|
|
3177
|
-
|
|
3195
|
+
execSync3(
|
|
3178
3196
|
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
3179
3197
|
{ timeout: 5e3 }
|
|
3180
3198
|
);
|
|
@@ -3186,7 +3204,7 @@ function macKeychainDelete(service = SERVICE) {
|
|
|
3186
3204
|
function linuxSecretGet(service = SERVICE) {
|
|
3187
3205
|
if (!linuxSecretAvailable()) return null;
|
|
3188
3206
|
try {
|
|
3189
|
-
return
|
|
3207
|
+
return execSync3(
|
|
3190
3208
|
`secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3191
3209
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
3192
3210
|
).trim();
|
|
@@ -3197,7 +3215,7 @@ function linuxSecretGet(service = SERVICE) {
|
|
|
3197
3215
|
function linuxSecretSet(value, service = SERVICE) {
|
|
3198
3216
|
if (!linuxSecretAvailable()) return false;
|
|
3199
3217
|
try {
|
|
3200
|
-
|
|
3218
|
+
execSync3(
|
|
3201
3219
|
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3202
3220
|
{ timeout: 5e3 }
|
|
3203
3221
|
);
|
|
@@ -3210,7 +3228,7 @@ function linuxSecretDelete(service = SERVICE) {
|
|
|
3210
3228
|
if (!nativeKeychainAllowed()) return false;
|
|
3211
3229
|
if (process.platform !== "linux") return false;
|
|
3212
3230
|
try {
|
|
3213
|
-
|
|
3231
|
+
execSync3(
|
|
3214
3232
|
`secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3215
3233
|
{ timeout: 5e3 }
|
|
3216
3234
|
);
|
|
@@ -4147,6 +4165,24 @@ var init_platform_procedures = __esm({
|
|
|
4147
4165
|
priority: "p0",
|
|
4148
4166
|
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."
|
|
4149
4167
|
},
|
|
4168
|
+
{
|
|
4169
|
+
title: "Bug report status check \u2014 surface available fixes on boot",
|
|
4170
|
+
domain: "support",
|
|
4171
|
+
priority: "p1",
|
|
4172
|
+
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."
|
|
4173
|
+
},
|
|
4174
|
+
{
|
|
4175
|
+
title: "Feature request triage \u2014 upstream feature vs local customization",
|
|
4176
|
+
domain: "support",
|
|
4177
|
+
priority: "p0",
|
|
4178
|
+
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."
|
|
4179
|
+
},
|
|
4180
|
+
{
|
|
4181
|
+
title: "Feature request status check \u2014 surface shipped features on boot",
|
|
4182
|
+
domain: "support",
|
|
4183
|
+
priority: "p1",
|
|
4184
|
+
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."
|
|
4185
|
+
},
|
|
4150
4186
|
// --- Operations ---
|
|
4151
4187
|
{
|
|
4152
4188
|
title: "Managers must supervise deployed workers",
|