@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
|
@@ -1101,7 +1101,7 @@ __export(exe_daemon_client_exports, {
|
|
|
1101
1101
|
});
|
|
1102
1102
|
import net from "net";
|
|
1103
1103
|
import os4 from "os";
|
|
1104
|
-
import { spawn } from "child_process";
|
|
1104
|
+
import { spawn, execSync as execSync2 } from "child_process";
|
|
1105
1105
|
import { randomUUID } from "crypto";
|
|
1106
1106
|
import { existsSync as existsSync5, unlinkSync as unlinkSync2, readFileSync as readFileSync4, openSync, closeSync, statSync } from "fs";
|
|
1107
1107
|
import path5 from "path";
|
|
@@ -1131,6 +1131,14 @@ function handleData(chunk) {
|
|
|
1131
1131
|
}
|
|
1132
1132
|
}
|
|
1133
1133
|
}
|
|
1134
|
+
function isZombie(pid) {
|
|
1135
|
+
try {
|
|
1136
|
+
const state = execSync2(`ps -p ${pid} -o state=`, { encoding: "utf8", timeout: 2e3 }).trim();
|
|
1137
|
+
return state.startsWith("Z");
|
|
1138
|
+
} catch {
|
|
1139
|
+
return false;
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1134
1142
|
function cleanupStaleFiles() {
|
|
1135
1143
|
if (existsSync5(PID_PATH)) {
|
|
1136
1144
|
try {
|
|
@@ -1138,7 +1146,11 @@ function cleanupStaleFiles() {
|
|
|
1138
1146
|
if (pid > 0) {
|
|
1139
1147
|
try {
|
|
1140
1148
|
process.kill(pid, 0);
|
|
1141
|
-
|
|
1149
|
+
if (!isZombie(pid)) {
|
|
1150
|
+
return;
|
|
1151
|
+
}
|
|
1152
|
+
process.stderr.write(`[exed-client] PID ${pid} is a zombie \u2014 cleaning up stale files
|
|
1153
|
+
`);
|
|
1142
1154
|
} catch {
|
|
1143
1155
|
}
|
|
1144
1156
|
}
|
|
@@ -1166,8 +1178,8 @@ function findPackageRoot() {
|
|
|
1166
1178
|
function getAvailableMemoryGB() {
|
|
1167
1179
|
if (process.platform === "darwin") {
|
|
1168
1180
|
try {
|
|
1169
|
-
const { execSync:
|
|
1170
|
-
const vmstat =
|
|
1181
|
+
const { execSync: execSync9 } = __require("child_process");
|
|
1182
|
+
const vmstat = execSync9("vm_stat", { encoding: "utf8" });
|
|
1171
1183
|
const pageSize = 16384;
|
|
1172
1184
|
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
1173
1185
|
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
@@ -3157,6 +3169,12 @@ async function disposeDatabase() {
|
|
|
3157
3169
|
clearInterval(_walCheckpointTimer);
|
|
3158
3170
|
_walCheckpointTimer = null;
|
|
3159
3171
|
}
|
|
3172
|
+
if (_client) {
|
|
3173
|
+
try {
|
|
3174
|
+
await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
3175
|
+
} catch {
|
|
3176
|
+
}
|
|
3177
|
+
}
|
|
3160
3178
|
if (_daemonClient) {
|
|
3161
3179
|
_daemonClient.close();
|
|
3162
3180
|
_daemonClient = null;
|
|
@@ -3193,7 +3211,7 @@ var init_database = __esm({
|
|
|
3193
3211
|
// src/lib/keychain.ts
|
|
3194
3212
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
3195
3213
|
import { existsSync as existsSync6, statSync as statSync2 } from "fs";
|
|
3196
|
-
import { execSync as
|
|
3214
|
+
import { execSync as execSync3 } from "child_process";
|
|
3197
3215
|
import path6 from "path";
|
|
3198
3216
|
import os5 from "os";
|
|
3199
3217
|
function getKeyDir() {
|
|
@@ -3210,13 +3228,13 @@ function linuxSecretAvailable() {
|
|
|
3210
3228
|
if (process.platform !== "linux") return false;
|
|
3211
3229
|
if (linuxSecretAvailability !== null) return linuxSecretAvailability;
|
|
3212
3230
|
try {
|
|
3213
|
-
|
|
3231
|
+
execSync3("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
|
|
3214
3232
|
} catch {
|
|
3215
3233
|
linuxSecretAvailability = false;
|
|
3216
3234
|
return false;
|
|
3217
3235
|
}
|
|
3218
3236
|
try {
|
|
3219
|
-
|
|
3237
|
+
execSync3("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
|
|
3220
3238
|
linuxSecretAvailability = true;
|
|
3221
3239
|
} catch {
|
|
3222
3240
|
linuxSecretAvailability = false;
|
|
@@ -3240,7 +3258,7 @@ function macKeychainGet(service = SERVICE) {
|
|
|
3240
3258
|
if (!nativeKeychainAllowed()) return null;
|
|
3241
3259
|
if (process.platform !== "darwin") return null;
|
|
3242
3260
|
try {
|
|
3243
|
-
return
|
|
3261
|
+
return execSync3(
|
|
3244
3262
|
`security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
3245
3263
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
3246
3264
|
).trim();
|
|
@@ -3253,13 +3271,13 @@ function macKeychainSet(value, service = SERVICE) {
|
|
|
3253
3271
|
if (process.platform !== "darwin") return false;
|
|
3254
3272
|
try {
|
|
3255
3273
|
try {
|
|
3256
|
-
|
|
3274
|
+
execSync3(
|
|
3257
3275
|
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
3258
3276
|
{ timeout: 5e3 }
|
|
3259
3277
|
);
|
|
3260
3278
|
} catch {
|
|
3261
3279
|
}
|
|
3262
|
-
|
|
3280
|
+
execSync3(
|
|
3263
3281
|
`security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
|
|
3264
3282
|
{ timeout: 5e3 }
|
|
3265
3283
|
);
|
|
@@ -3272,7 +3290,7 @@ function macKeychainDelete(service = SERVICE) {
|
|
|
3272
3290
|
if (!nativeKeychainAllowed()) return false;
|
|
3273
3291
|
if (process.platform !== "darwin") return false;
|
|
3274
3292
|
try {
|
|
3275
|
-
|
|
3293
|
+
execSync3(
|
|
3276
3294
|
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
3277
3295
|
{ timeout: 5e3 }
|
|
3278
3296
|
);
|
|
@@ -3284,7 +3302,7 @@ function macKeychainDelete(service = SERVICE) {
|
|
|
3284
3302
|
function linuxSecretGet(service = SERVICE) {
|
|
3285
3303
|
if (!linuxSecretAvailable()) return null;
|
|
3286
3304
|
try {
|
|
3287
|
-
return
|
|
3305
|
+
return execSync3(
|
|
3288
3306
|
`secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3289
3307
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
3290
3308
|
).trim();
|
|
@@ -3295,7 +3313,7 @@ function linuxSecretGet(service = SERVICE) {
|
|
|
3295
3313
|
function linuxSecretSet(value, service = SERVICE) {
|
|
3296
3314
|
if (!linuxSecretAvailable()) return false;
|
|
3297
3315
|
try {
|
|
3298
|
-
|
|
3316
|
+
execSync3(
|
|
3299
3317
|
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3300
3318
|
{ timeout: 5e3 }
|
|
3301
3319
|
);
|
|
@@ -3308,7 +3326,7 @@ function linuxSecretDelete(service = SERVICE) {
|
|
|
3308
3326
|
if (!nativeKeychainAllowed()) return false;
|
|
3309
3327
|
if (process.platform !== "linux") return false;
|
|
3310
3328
|
try {
|
|
3311
|
-
|
|
3329
|
+
execSync3(
|
|
3312
3330
|
`secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
3313
3331
|
{ timeout: 5e3 }
|
|
3314
3332
|
);
|
|
@@ -4245,6 +4263,24 @@ var init_platform_procedures = __esm({
|
|
|
4245
4263
|
priority: "p0",
|
|
4246
4264
|
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."
|
|
4247
4265
|
},
|
|
4266
|
+
{
|
|
4267
|
+
title: "Bug report status check \u2014 surface available fixes on boot",
|
|
4268
|
+
domain: "support",
|
|
4269
|
+
priority: "p1",
|
|
4270
|
+
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."
|
|
4271
|
+
},
|
|
4272
|
+
{
|
|
4273
|
+
title: "Feature request triage \u2014 upstream feature vs local customization",
|
|
4274
|
+
domain: "support",
|
|
4275
|
+
priority: "p0",
|
|
4276
|
+
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."
|
|
4277
|
+
},
|
|
4278
|
+
{
|
|
4279
|
+
title: "Feature request status check \u2014 surface shipped features on boot",
|
|
4280
|
+
domain: "support",
|
|
4281
|
+
priority: "p1",
|
|
4282
|
+
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."
|
|
4283
|
+
},
|
|
4248
4284
|
// --- Operations ---
|
|
4249
4285
|
{
|
|
4250
4286
|
title: "Managers must supervise deployed workers",
|
|
@@ -5591,7 +5627,7 @@ var init_session_registry = __esm({
|
|
|
5591
5627
|
});
|
|
5592
5628
|
|
|
5593
5629
|
// src/lib/session-key.ts
|
|
5594
|
-
import { execSync as
|
|
5630
|
+
import { execSync as execSync4 } from "child_process";
|
|
5595
5631
|
function normalizeCommand(command) {
|
|
5596
5632
|
const trimmed = command.trim().toLowerCase();
|
|
5597
5633
|
const parts = trimmed.split(/[\\/]/);
|
|
@@ -5610,7 +5646,7 @@ function resolveRuntimeProcess() {
|
|
|
5610
5646
|
let pid = process.ppid;
|
|
5611
5647
|
for (let i = 0; i < 10; i++) {
|
|
5612
5648
|
try {
|
|
5613
|
-
const info =
|
|
5649
|
+
const info = execSync4(`ps -p ${pid} -o ppid=,comm=`, {
|
|
5614
5650
|
encoding: "utf8",
|
|
5615
5651
|
timeout: 2e3
|
|
5616
5652
|
}).trim();
|
|
@@ -5788,14 +5824,14 @@ var init_transport = __esm({
|
|
|
5788
5824
|
});
|
|
5789
5825
|
|
|
5790
5826
|
// src/lib/cc-agent-support.ts
|
|
5791
|
-
import { execSync as
|
|
5827
|
+
import { execSync as execSync5 } from "child_process";
|
|
5792
5828
|
function _resetCcAgentSupportCache() {
|
|
5793
5829
|
_cachedSupport = null;
|
|
5794
5830
|
}
|
|
5795
5831
|
function claudeSupportsAgentFlag() {
|
|
5796
5832
|
if (_cachedSupport !== null) return _cachedSupport;
|
|
5797
5833
|
try {
|
|
5798
|
-
const helpOutput =
|
|
5834
|
+
const helpOutput = execSync5("claude --help 2>&1", {
|
|
5799
5835
|
encoding: "utf-8",
|
|
5800
5836
|
timeout: 5e3
|
|
5801
5837
|
});
|
|
@@ -6256,7 +6292,7 @@ __export(project_name_exports, {
|
|
|
6256
6292
|
_resetCache: () => _resetCache,
|
|
6257
6293
|
getProjectName: () => getProjectName
|
|
6258
6294
|
});
|
|
6259
|
-
import { execSync as
|
|
6295
|
+
import { execSync as execSync6 } from "child_process";
|
|
6260
6296
|
import path14 from "path";
|
|
6261
6297
|
function getProjectName(cwd) {
|
|
6262
6298
|
const dir = cwd ?? process.cwd();
|
|
@@ -6264,7 +6300,7 @@ function getProjectName(cwd) {
|
|
|
6264
6300
|
try {
|
|
6265
6301
|
let repoRoot;
|
|
6266
6302
|
try {
|
|
6267
|
-
const gitCommonDir =
|
|
6303
|
+
const gitCommonDir = execSync6("git rev-parse --path-format=absolute --git-common-dir", {
|
|
6268
6304
|
cwd: dir,
|
|
6269
6305
|
encoding: "utf8",
|
|
6270
6306
|
timeout: 2e3,
|
|
@@ -6272,7 +6308,7 @@ function getProjectName(cwd) {
|
|
|
6272
6308
|
}).trim();
|
|
6273
6309
|
repoRoot = path14.dirname(gitCommonDir);
|
|
6274
6310
|
} catch {
|
|
6275
|
-
repoRoot =
|
|
6311
|
+
repoRoot = execSync6("git rev-parse --show-toplevel", {
|
|
6276
6312
|
cwd: dir,
|
|
6277
6313
|
encoding: "utf8",
|
|
6278
6314
|
timeout: 2e3,
|
|
@@ -6367,7 +6403,7 @@ var init_session_scope = __esm({
|
|
|
6367
6403
|
import crypto3 from "crypto";
|
|
6368
6404
|
import path15 from "path";
|
|
6369
6405
|
import os10 from "os";
|
|
6370
|
-
import { execSync as
|
|
6406
|
+
import { execSync as execSync7 } from "child_process";
|
|
6371
6407
|
import { mkdir as mkdir4, writeFile as writeFile4, appendFile } from "fs/promises";
|
|
6372
6408
|
import { existsSync as existsSync14, readFileSync as readFileSync10 } from "fs";
|
|
6373
6409
|
async function writeCheckpoint(input) {
|
|
@@ -6712,14 +6748,14 @@ function isTmuxSessionAlive(identifier) {
|
|
|
6712
6748
|
if (!identifier || identifier === "unknown") return true;
|
|
6713
6749
|
try {
|
|
6714
6750
|
if (identifier.startsWith("%")) {
|
|
6715
|
-
const output =
|
|
6751
|
+
const output = execSync7("tmux list-panes -a -F '#{pane_id}'", {
|
|
6716
6752
|
timeout: 2e3,
|
|
6717
6753
|
encoding: "utf8",
|
|
6718
6754
|
stdio: ["pipe", "pipe", "pipe"]
|
|
6719
6755
|
});
|
|
6720
6756
|
return output.split("\n").some((l) => l.trim() === identifier);
|
|
6721
6757
|
} else {
|
|
6722
|
-
|
|
6758
|
+
execSync7(`tmux has-session -t ${JSON.stringify(identifier)}`, {
|
|
6723
6759
|
timeout: 2e3,
|
|
6724
6760
|
stdio: ["pipe", "pipe", "pipe"]
|
|
6725
6761
|
});
|
|
@@ -6728,7 +6764,7 @@ function isTmuxSessionAlive(identifier) {
|
|
|
6728
6764
|
} catch {
|
|
6729
6765
|
if (identifier.startsWith("%")) return true;
|
|
6730
6766
|
try {
|
|
6731
|
-
|
|
6767
|
+
execSync7("tmux list-sessions", {
|
|
6732
6768
|
timeout: 2e3,
|
|
6733
6769
|
stdio: ["pipe", "pipe", "pipe"]
|
|
6734
6770
|
});
|
|
@@ -6743,12 +6779,12 @@ function checkStaleCompletion(taskContext, taskCreatedAt) {
|
|
|
6743
6779
|
if (!DELEGATION_KEYWORDS.test(taskContext)) return null;
|
|
6744
6780
|
try {
|
|
6745
6781
|
const since = new Date(taskCreatedAt).toISOString();
|
|
6746
|
-
const branch =
|
|
6782
|
+
const branch = execSync7(
|
|
6747
6783
|
"git rev-parse --abbrev-ref HEAD 2>/dev/null",
|
|
6748
6784
|
{ encoding: "utf8", timeout: 3e3 }
|
|
6749
6785
|
).trim();
|
|
6750
6786
|
const branchArg = branch && branch !== "HEAD" ? branch : "";
|
|
6751
|
-
const commitCount =
|
|
6787
|
+
const commitCount = execSync7(
|
|
6752
6788
|
`git log --oneline --since="${since}" ${branchArg} 2>/dev/null | wc -l`,
|
|
6753
6789
|
{ encoding: "utf8", timeout: 5e3 }
|
|
6754
6790
|
).trim();
|
|
@@ -8039,7 +8075,7 @@ __export(tmux_routing_exports, {
|
|
|
8039
8075
|
spawnEmployee: () => spawnEmployee,
|
|
8040
8076
|
verifyPaneAtCapacity: () => verifyPaneAtCapacity
|
|
8041
8077
|
});
|
|
8042
|
-
import { execFileSync as execFileSync2, execSync as
|
|
8078
|
+
import { execFileSync as execFileSync2, execSync as execSync8 } from "child_process";
|
|
8043
8079
|
import { readFileSync as readFileSync11, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8, existsSync as existsSync15, appendFileSync, readdirSync as readdirSync2 } from "fs";
|
|
8044
8080
|
import path18 from "path";
|
|
8045
8081
|
import os11 from "os";
|
|
@@ -8760,7 +8796,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
8760
8796
|
let booted = false;
|
|
8761
8797
|
for (let i = 0; i < 30; i++) {
|
|
8762
8798
|
try {
|
|
8763
|
-
|
|
8799
|
+
execSync8("sleep 0.5");
|
|
8764
8800
|
} catch {
|
|
8765
8801
|
}
|
|
8766
8802
|
try {
|
|
@@ -9633,8 +9669,8 @@ async function main() {
|
|
|
9633
9669
|
const agentId = folderArg.startsWith("exe/") ? folderArg.slice(4) : folderArg;
|
|
9634
9670
|
let tmuxSession;
|
|
9635
9671
|
try {
|
|
9636
|
-
const { execSync:
|
|
9637
|
-
const out =
|
|
9672
|
+
const { execSync: execSync9 } = await import("child_process");
|
|
9673
|
+
const out = execSync9("tmux display-message -p '#{session_name}' 2>/dev/null", {
|
|
9638
9674
|
encoding: "utf8",
|
|
9639
9675
|
timeout: 1e3
|
|
9640
9676
|
}).trim();
|
package/dist/bin/scan-tasks.js
CHANGED
|
@@ -1593,7 +1593,7 @@ __export(exe_daemon_client_exports, {
|
|
|
1593
1593
|
});
|
|
1594
1594
|
import net from "net";
|
|
1595
1595
|
import os6 from "os";
|
|
1596
|
-
import { spawn } from "child_process";
|
|
1596
|
+
import { spawn, execSync as execSync4 } from "child_process";
|
|
1597
1597
|
import { randomUUID } from "crypto";
|
|
1598
1598
|
import { existsSync as existsSync8, unlinkSync as unlinkSync2, readFileSync as readFileSync7, openSync, closeSync, statSync } from "fs";
|
|
1599
1599
|
import path8 from "path";
|
|
@@ -1623,6 +1623,14 @@ function handleData(chunk) {
|
|
|
1623
1623
|
}
|
|
1624
1624
|
}
|
|
1625
1625
|
}
|
|
1626
|
+
function isZombie(pid) {
|
|
1627
|
+
try {
|
|
1628
|
+
const state = execSync4(`ps -p ${pid} -o state=`, { encoding: "utf8", timeout: 2e3 }).trim();
|
|
1629
|
+
return state.startsWith("Z");
|
|
1630
|
+
} catch {
|
|
1631
|
+
return false;
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1626
1634
|
function cleanupStaleFiles() {
|
|
1627
1635
|
if (existsSync8(PID_PATH)) {
|
|
1628
1636
|
try {
|
|
@@ -1630,7 +1638,11 @@ function cleanupStaleFiles() {
|
|
|
1630
1638
|
if (pid > 0) {
|
|
1631
1639
|
try {
|
|
1632
1640
|
process.kill(pid, 0);
|
|
1633
|
-
|
|
1641
|
+
if (!isZombie(pid)) {
|
|
1642
|
+
return;
|
|
1643
|
+
}
|
|
1644
|
+
process.stderr.write(`[exed-client] PID ${pid} is a zombie \u2014 cleaning up stale files
|
|
1645
|
+
`);
|
|
1634
1646
|
} catch {
|
|
1635
1647
|
}
|
|
1636
1648
|
}
|
|
@@ -1658,8 +1670,8 @@ function findPackageRoot() {
|
|
|
1658
1670
|
function getAvailableMemoryGB() {
|
|
1659
1671
|
if (process.platform === "darwin") {
|
|
1660
1672
|
try {
|
|
1661
|
-
const { execSync:
|
|
1662
|
-
const vmstat =
|
|
1673
|
+
const { execSync: execSync9 } = __require("child_process");
|
|
1674
|
+
const vmstat = execSync9("vm_stat", { encoding: "utf8" });
|
|
1663
1675
|
const pageSize = 16384;
|
|
1664
1676
|
const pageSizeMatch = vmstat.match(/page size of (\d+) bytes/);
|
|
1665
1677
|
const actualPageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : pageSize;
|
|
@@ -3649,6 +3661,12 @@ async function disposeDatabase() {
|
|
|
3649
3661
|
clearInterval(_walCheckpointTimer);
|
|
3650
3662
|
_walCheckpointTimer = null;
|
|
3651
3663
|
}
|
|
3664
|
+
if (_client) {
|
|
3665
|
+
try {
|
|
3666
|
+
await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
3667
|
+
} catch {
|
|
3668
|
+
}
|
|
3669
|
+
}
|
|
3652
3670
|
if (_daemonClient) {
|
|
3653
3671
|
_daemonClient.close();
|
|
3654
3672
|
_daemonClient = null;
|
|
@@ -4002,7 +4020,7 @@ __export(project_name_exports, {
|
|
|
4002
4020
|
_resetCache: () => _resetCache,
|
|
4003
4021
|
getProjectName: () => getProjectName
|
|
4004
4022
|
});
|
|
4005
|
-
import { execSync as
|
|
4023
|
+
import { execSync as execSync5 } from "child_process";
|
|
4006
4024
|
import path13 from "path";
|
|
4007
4025
|
function getProjectName(cwd) {
|
|
4008
4026
|
const dir = cwd ?? process.cwd();
|
|
@@ -4010,7 +4028,7 @@ function getProjectName(cwd) {
|
|
|
4010
4028
|
try {
|
|
4011
4029
|
let repoRoot;
|
|
4012
4030
|
try {
|
|
4013
|
-
const gitCommonDir =
|
|
4031
|
+
const gitCommonDir = execSync5("git rev-parse --path-format=absolute --git-common-dir", {
|
|
4014
4032
|
cwd: dir,
|
|
4015
4033
|
encoding: "utf8",
|
|
4016
4034
|
timeout: 2e3,
|
|
@@ -4018,7 +4036,7 @@ function getProjectName(cwd) {
|
|
|
4018
4036
|
}).trim();
|
|
4019
4037
|
repoRoot = path13.dirname(gitCommonDir);
|
|
4020
4038
|
} catch {
|
|
4021
|
-
repoRoot =
|
|
4039
|
+
repoRoot = execSync5("git rev-parse --show-toplevel", {
|
|
4022
4040
|
cwd: dir,
|
|
4023
4041
|
encoding: "utf8",
|
|
4024
4042
|
timeout: 2e3,
|
|
@@ -4113,7 +4131,7 @@ var init_session_scope = __esm({
|
|
|
4113
4131
|
import crypto4 from "crypto";
|
|
4114
4132
|
import path14 from "path";
|
|
4115
4133
|
import os10 from "os";
|
|
4116
|
-
import { execSync as
|
|
4134
|
+
import { execSync as execSync6 } from "child_process";
|
|
4117
4135
|
import { mkdir as mkdir3, writeFile as writeFile3, appendFile } from "fs/promises";
|
|
4118
4136
|
import { existsSync as existsSync13, readFileSync as readFileSync11 } from "fs";
|
|
4119
4137
|
async function writeCheckpoint(input) {
|
|
@@ -4458,14 +4476,14 @@ function isTmuxSessionAlive(identifier) {
|
|
|
4458
4476
|
if (!identifier || identifier === "unknown") return true;
|
|
4459
4477
|
try {
|
|
4460
4478
|
if (identifier.startsWith("%")) {
|
|
4461
|
-
const output =
|
|
4479
|
+
const output = execSync6("tmux list-panes -a -F '#{pane_id}'", {
|
|
4462
4480
|
timeout: 2e3,
|
|
4463
4481
|
encoding: "utf8",
|
|
4464
4482
|
stdio: ["pipe", "pipe", "pipe"]
|
|
4465
4483
|
});
|
|
4466
4484
|
return output.split("\n").some((l) => l.trim() === identifier);
|
|
4467
4485
|
} else {
|
|
4468
|
-
|
|
4486
|
+
execSync6(`tmux has-session -t ${JSON.stringify(identifier)}`, {
|
|
4469
4487
|
timeout: 2e3,
|
|
4470
4488
|
stdio: ["pipe", "pipe", "pipe"]
|
|
4471
4489
|
});
|
|
@@ -4474,7 +4492,7 @@ function isTmuxSessionAlive(identifier) {
|
|
|
4474
4492
|
} catch {
|
|
4475
4493
|
if (identifier.startsWith("%")) return true;
|
|
4476
4494
|
try {
|
|
4477
|
-
|
|
4495
|
+
execSync6("tmux list-sessions", {
|
|
4478
4496
|
timeout: 2e3,
|
|
4479
4497
|
stdio: ["pipe", "pipe", "pipe"]
|
|
4480
4498
|
});
|
|
@@ -4489,12 +4507,12 @@ function checkStaleCompletion(taskContext, taskCreatedAt) {
|
|
|
4489
4507
|
if (!DELEGATION_KEYWORDS.test(taskContext)) return null;
|
|
4490
4508
|
try {
|
|
4491
4509
|
const since = new Date(taskCreatedAt).toISOString();
|
|
4492
|
-
const branch =
|
|
4510
|
+
const branch = execSync6(
|
|
4493
4511
|
"git rev-parse --abbrev-ref HEAD 2>/dev/null",
|
|
4494
4512
|
{ encoding: "utf8", timeout: 3e3 }
|
|
4495
4513
|
).trim();
|
|
4496
4514
|
const branchArg = branch && branch !== "HEAD" ? branch : "";
|
|
4497
|
-
const commitCount =
|
|
4515
|
+
const commitCount = execSync6(
|
|
4498
4516
|
`git log --oneline --since="${since}" ${branchArg} 2>/dev/null | wc -l`,
|
|
4499
4517
|
{ encoding: "utf8", timeout: 5e3 }
|
|
4500
4518
|
).trim();
|
|
@@ -6093,7 +6111,7 @@ __export(tmux_routing_exports, {
|
|
|
6093
6111
|
spawnEmployee: () => spawnEmployee,
|
|
6094
6112
|
verifyPaneAtCapacity: () => verifyPaneAtCapacity
|
|
6095
6113
|
});
|
|
6096
|
-
import { execFileSync as execFileSync2, execSync as
|
|
6114
|
+
import { execFileSync as execFileSync2, execSync as execSync7 } from "child_process";
|
|
6097
6115
|
import { readFileSync as readFileSync12, writeFileSync as writeFileSync8, mkdirSync as mkdirSync7, existsSync as existsSync15, appendFileSync, readdirSync as readdirSync3 } from "fs";
|
|
6098
6116
|
import path18 from "path";
|
|
6099
6117
|
import os11 from "os";
|
|
@@ -6814,7 +6832,7 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
6814
6832
|
let booted = false;
|
|
6815
6833
|
for (let i = 0; i < 30; i++) {
|
|
6816
6834
|
try {
|
|
6817
|
-
|
|
6835
|
+
execSync7("sleep 0.5");
|
|
6818
6836
|
} catch {
|
|
6819
6837
|
}
|
|
6820
6838
|
try {
|
|
@@ -6926,7 +6944,7 @@ var init_task_scope = __esm({
|
|
|
6926
6944
|
// src/lib/keychain.ts
|
|
6927
6945
|
import { readFile as readFile4, writeFile as writeFile5, unlink, mkdir as mkdir4, chmod as chmod2 } from "fs/promises";
|
|
6928
6946
|
import { existsSync as existsSync16, statSync as statSync2 } from "fs";
|
|
6929
|
-
import { execSync as
|
|
6947
|
+
import { execSync as execSync8 } from "child_process";
|
|
6930
6948
|
import path19 from "path";
|
|
6931
6949
|
import os12 from "os";
|
|
6932
6950
|
function getKeyDir() {
|
|
@@ -6943,13 +6961,13 @@ function linuxSecretAvailable() {
|
|
|
6943
6961
|
if (process.platform !== "linux") return false;
|
|
6944
6962
|
if (linuxSecretAvailability !== null) return linuxSecretAvailability;
|
|
6945
6963
|
try {
|
|
6946
|
-
|
|
6964
|
+
execSync8("command -v secret-tool >/dev/null 2>&1", { timeout: 1e3 });
|
|
6947
6965
|
} catch {
|
|
6948
6966
|
linuxSecretAvailability = false;
|
|
6949
6967
|
return false;
|
|
6950
6968
|
}
|
|
6951
6969
|
try {
|
|
6952
|
-
|
|
6970
|
+
execSync8("secret-tool search --all exe-os probe >/dev/null 2>&1", { timeout: 1e3 });
|
|
6953
6971
|
linuxSecretAvailability = true;
|
|
6954
6972
|
} catch {
|
|
6955
6973
|
linuxSecretAvailability = false;
|
|
@@ -6973,7 +6991,7 @@ function macKeychainGet(service = SERVICE) {
|
|
|
6973
6991
|
if (!nativeKeychainAllowed()) return null;
|
|
6974
6992
|
if (process.platform !== "darwin") return null;
|
|
6975
6993
|
try {
|
|
6976
|
-
return
|
|
6994
|
+
return execSync8(
|
|
6977
6995
|
`security find-generic-password -s "${service}" -a "${ACCOUNT}" -w 2>/dev/null`,
|
|
6978
6996
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
6979
6997
|
).trim();
|
|
@@ -6986,13 +7004,13 @@ function macKeychainSet(value, service = SERVICE) {
|
|
|
6986
7004
|
if (process.platform !== "darwin") return false;
|
|
6987
7005
|
try {
|
|
6988
7006
|
try {
|
|
6989
|
-
|
|
7007
|
+
execSync8(
|
|
6990
7008
|
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
6991
7009
|
{ timeout: 5e3 }
|
|
6992
7010
|
);
|
|
6993
7011
|
} catch {
|
|
6994
7012
|
}
|
|
6995
|
-
|
|
7013
|
+
execSync8(
|
|
6996
7014
|
`security add-generic-password -s "${service}" -a "${ACCOUNT}" -w "${value}"`,
|
|
6997
7015
|
{ timeout: 5e3 }
|
|
6998
7016
|
);
|
|
@@ -7005,7 +7023,7 @@ function macKeychainDelete(service = SERVICE) {
|
|
|
7005
7023
|
if (!nativeKeychainAllowed()) return false;
|
|
7006
7024
|
if (process.platform !== "darwin") return false;
|
|
7007
7025
|
try {
|
|
7008
|
-
|
|
7026
|
+
execSync8(
|
|
7009
7027
|
`security delete-generic-password -s "${service}" -a "${ACCOUNT}" 2>/dev/null`,
|
|
7010
7028
|
{ timeout: 5e3 }
|
|
7011
7029
|
);
|
|
@@ -7017,7 +7035,7 @@ function macKeychainDelete(service = SERVICE) {
|
|
|
7017
7035
|
function linuxSecretGet(service = SERVICE) {
|
|
7018
7036
|
if (!linuxSecretAvailable()) return null;
|
|
7019
7037
|
try {
|
|
7020
|
-
return
|
|
7038
|
+
return execSync8(
|
|
7021
7039
|
`secret-tool lookup service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
7022
7040
|
{ encoding: "utf-8", timeout: 5e3 }
|
|
7023
7041
|
).trim();
|
|
@@ -7028,7 +7046,7 @@ function linuxSecretGet(service = SERVICE) {
|
|
|
7028
7046
|
function linuxSecretSet(value, service = SERVICE) {
|
|
7029
7047
|
if (!linuxSecretAvailable()) return false;
|
|
7030
7048
|
try {
|
|
7031
|
-
|
|
7049
|
+
execSync8(
|
|
7032
7050
|
`echo -n "${value}" | secret-tool store --label="exe-os master key" service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
7033
7051
|
{ timeout: 5e3 }
|
|
7034
7052
|
);
|
|
@@ -7041,7 +7059,7 @@ function linuxSecretDelete(service = SERVICE) {
|
|
|
7041
7059
|
if (!nativeKeychainAllowed()) return false;
|
|
7042
7060
|
if (process.platform !== "linux") return false;
|
|
7043
7061
|
try {
|
|
7044
|
-
|
|
7062
|
+
execSync8(
|
|
7045
7063
|
`secret-tool clear service "${service}" account "${ACCOUNT}" 2>/dev/null`,
|
|
7046
7064
|
{ timeout: 5e3 }
|
|
7047
7065
|
);
|
|
@@ -7923,6 +7941,24 @@ var init_platform_procedures = __esm({
|
|
|
7923
7941
|
priority: "p0",
|
|
7924
7942
|
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."
|
|
7925
7943
|
},
|
|
7944
|
+
{
|
|
7945
|
+
title: "Bug report status check \u2014 surface available fixes on boot",
|
|
7946
|
+
domain: "support",
|
|
7947
|
+
priority: "p1",
|
|
7948
|
+
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."
|
|
7949
|
+
},
|
|
7950
|
+
{
|
|
7951
|
+
title: "Feature request triage \u2014 upstream feature vs local customization",
|
|
7952
|
+
domain: "support",
|
|
7953
|
+
priority: "p0",
|
|
7954
|
+
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."
|
|
7955
|
+
},
|
|
7956
|
+
{
|
|
7957
|
+
title: "Feature request status check \u2014 surface shipped features on boot",
|
|
7958
|
+
domain: "support",
|
|
7959
|
+
priority: "p1",
|
|
7960
|
+
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."
|
|
7961
|
+
},
|
|
7926
7962
|
// --- Operations ---
|
|
7927
7963
|
{
|
|
7928
7964
|
title: "Managers must supervise deployed workers",
|
|
@@ -9437,8 +9473,8 @@ async function main() {
|
|
|
9437
9473
|
const agentId = folderArg.startsWith("exe/") ? folderArg.slice(4) : folderArg;
|
|
9438
9474
|
let tmuxSession;
|
|
9439
9475
|
try {
|
|
9440
|
-
const { execSync:
|
|
9441
|
-
const out =
|
|
9476
|
+
const { execSync: execSync9 } = await import("child_process");
|
|
9477
|
+
const out = execSync9("tmux display-message -p '#{session_name}' 2>/dev/null", {
|
|
9442
9478
|
encoding: "utf8",
|
|
9443
9479
|
timeout: 1e3
|
|
9444
9480
|
}).trim();
|