@askexenow/exe-os 0.9.0 → 0.9.1
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/cli.js +124 -32
- package/dist/bin/exe-boot.js +89 -5
- package/dist/bin/exe-dispatch.js +96 -6
- package/dist/bin/exe-doctor.js +55 -2
- package/dist/bin/exe-gateway.js +89 -5
- package/dist/bin/exe-new-employee.js +17 -13
- package/dist/bin/exe-session-cleanup.js +91 -1
- package/dist/bin/exe-start-codex.js +12 -8
- package/dist/bin/git-sweep.js +96 -6
- package/dist/bin/install.js +17 -13
- package/dist/bin/scan-tasks.js +96 -6
- package/dist/gateway/index.js +95 -5
- package/dist/hooks/bug-report-worker.js +91 -1
- package/dist/hooks/commit-complete.js +96 -6
- package/dist/hooks/error-recall.js +14 -0
- package/dist/hooks/ingest-worker.js +85 -1
- package/dist/hooks/ingest.js +11 -0
- package/dist/hooks/pre-compact.js +96 -6
- package/dist/hooks/prompt-submit.js +17 -0
- package/dist/hooks/session-end.js +96 -6
- package/dist/hooks/stop.js +18 -0
- package/dist/index.js +94 -10
- package/dist/lib/exe-daemon.js +17 -0
- package/dist/lib/tasks.js +91 -1
- package/dist/lib/tmux-routing.js +91 -1
- package/dist/mcp/server.js +339 -34
- package/dist/mcp/tools/create-task.js +91 -1
- package/dist/mcp/tools/update-task.js +91 -1
- package/dist/runtime/index.js +90 -6
- package/dist/tui/App.js +90 -6
- package/package.json +1 -1
package/dist/bin/cli.js
CHANGED
|
@@ -749,6 +749,10 @@ async function cleanSettingsJsonMcp(settingsPath) {
|
|
|
749
749
|
}
|
|
750
750
|
async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
751
751
|
const settingsPath = path5.join(homeDir, ".claude", "settings.json");
|
|
752
|
+
const logsDir = path5.join(homeDir, ".exe-os", "logs");
|
|
753
|
+
const hookLogPath = path5.join(logsDir, "hooks.log");
|
|
754
|
+
const logSuffix = ` 2>> "${hookLogPath}"`;
|
|
755
|
+
await mkdir3(logsDir, { recursive: true });
|
|
752
756
|
let settings = {};
|
|
753
757
|
if (existsSync5(settingsPath)) {
|
|
754
758
|
try {
|
|
@@ -772,11 +776,11 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
772
776
|
hooks: [
|
|
773
777
|
{
|
|
774
778
|
type: "command",
|
|
775
|
-
command: `node "${path5.join(packageRoot, "dist", "hooks", "ingest.js")}"`
|
|
779
|
+
command: `node "${path5.join(packageRoot, "dist", "hooks", "ingest.js")}"${logSuffix}`
|
|
776
780
|
},
|
|
777
781
|
{
|
|
778
782
|
type: "command",
|
|
779
|
-
command: `node "${path5.join(packageRoot, "dist", "hooks", "error-recall.js")}"`
|
|
783
|
+
command: `node "${path5.join(packageRoot, "dist", "hooks", "error-recall.js")}"${logSuffix}`
|
|
780
784
|
}
|
|
781
785
|
]
|
|
782
786
|
},
|
|
@@ -788,7 +792,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
788
792
|
hooks: [
|
|
789
793
|
{
|
|
790
794
|
type: "command",
|
|
791
|
-
command: `node "${path5.join(packageRoot, "dist", "hooks", "session-start.js")}"`,
|
|
795
|
+
command: `node "${path5.join(packageRoot, "dist", "hooks", "session-start.js")}"${logSuffix}`,
|
|
792
796
|
timeout: 1e4
|
|
793
797
|
}
|
|
794
798
|
]
|
|
@@ -801,7 +805,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
801
805
|
hooks: [
|
|
802
806
|
{
|
|
803
807
|
type: "command",
|
|
804
|
-
command: `node "${path5.join(packageRoot, "dist", "hooks", "prompt-submit.js")}"`
|
|
808
|
+
command: `node "${path5.join(packageRoot, "dist", "hooks", "prompt-submit.js")}"${logSuffix}`
|
|
805
809
|
}
|
|
806
810
|
]
|
|
807
811
|
},
|
|
@@ -813,7 +817,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
813
817
|
hooks: [
|
|
814
818
|
{
|
|
815
819
|
type: "command",
|
|
816
|
-
command: `node "${path5.join(packageRoot, "dist", "hooks", "exe-heartbeat-hook.js")}"`,
|
|
820
|
+
command: `node "${path5.join(packageRoot, "dist", "hooks", "exe-heartbeat-hook.js")}"${logSuffix}`,
|
|
817
821
|
timeout: 5e3
|
|
818
822
|
}
|
|
819
823
|
]
|
|
@@ -826,7 +830,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
826
830
|
hooks: [
|
|
827
831
|
{
|
|
828
832
|
type: "command",
|
|
829
|
-
command: `node "${path5.join(packageRoot, "dist", "hooks", "stop.js")}"`
|
|
833
|
+
command: `node "${path5.join(packageRoot, "dist", "hooks", "stop.js")}"${logSuffix}`
|
|
830
834
|
}
|
|
831
835
|
]
|
|
832
836
|
},
|
|
@@ -839,7 +843,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
839
843
|
hooks: [
|
|
840
844
|
{
|
|
841
845
|
type: "command",
|
|
842
|
-
command: `node "${path5.join(packageRoot, "dist", "hooks", "pre-tool-use.js")}"`
|
|
846
|
+
command: `node "${path5.join(packageRoot, "dist", "hooks", "pre-tool-use.js")}"${logSuffix}`
|
|
843
847
|
}
|
|
844
848
|
]
|
|
845
849
|
},
|
|
@@ -851,7 +855,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
851
855
|
hooks: [
|
|
852
856
|
{
|
|
853
857
|
type: "command",
|
|
854
|
-
command: `node "${path5.join(packageRoot, "dist", "hooks", "subagent-stop.js")}"`
|
|
858
|
+
command: `node "${path5.join(packageRoot, "dist", "hooks", "subagent-stop.js")}"${logSuffix}`
|
|
855
859
|
}
|
|
856
860
|
]
|
|
857
861
|
},
|
|
@@ -863,7 +867,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
863
867
|
hooks: [
|
|
864
868
|
{
|
|
865
869
|
type: "command",
|
|
866
|
-
command: `node "${path5.join(packageRoot, "dist", "hooks", "pre-compact.js")}"`,
|
|
870
|
+
command: `node "${path5.join(packageRoot, "dist", "hooks", "pre-compact.js")}"${logSuffix}`,
|
|
867
871
|
timeout: 1e4
|
|
868
872
|
}
|
|
869
873
|
]
|
|
@@ -876,7 +880,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
876
880
|
hooks: [
|
|
877
881
|
{
|
|
878
882
|
type: "command",
|
|
879
|
-
command: `node "${path5.join(packageRoot, "dist", "hooks", "session-end.js")}"`
|
|
883
|
+
command: `node "${path5.join(packageRoot, "dist", "hooks", "session-end.js")}"${logSuffix}`
|
|
880
884
|
}
|
|
881
885
|
]
|
|
882
886
|
},
|
|
@@ -888,7 +892,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
888
892
|
hooks: [
|
|
889
893
|
{
|
|
890
894
|
type: "command",
|
|
891
|
-
command: `node "${path5.join(packageRoot, "dist", "hooks", "notification.js")}"`
|
|
895
|
+
command: `node "${path5.join(packageRoot, "dist", "hooks", "notification.js")}"${logSuffix}`
|
|
892
896
|
}
|
|
893
897
|
]
|
|
894
898
|
},
|
|
@@ -900,7 +904,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
900
904
|
hooks: [
|
|
901
905
|
{
|
|
902
906
|
type: "command",
|
|
903
|
-
command: `node "${path5.join(packageRoot, "dist", "hooks", "post-compact.js")}"`,
|
|
907
|
+
command: `node "${path5.join(packageRoot, "dist", "hooks", "post-compact.js")}"${logSuffix}`,
|
|
904
908
|
timeout: 1e4
|
|
905
909
|
}
|
|
906
910
|
]
|
|
@@ -913,7 +917,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
913
917
|
hooks: [
|
|
914
918
|
{
|
|
915
919
|
type: "command",
|
|
916
|
-
command: `node "${path5.join(packageRoot, "dist", "hooks", "instructions-loaded.js")}"`
|
|
920
|
+
command: `node "${path5.join(packageRoot, "dist", "hooks", "instructions-loaded.js")}"${logSuffix}`
|
|
917
921
|
}
|
|
918
922
|
]
|
|
919
923
|
},
|
|
@@ -3940,21 +3944,21 @@ async function withRosterLock(fn) {
|
|
|
3940
3944
|
}
|
|
3941
3945
|
}
|
|
3942
3946
|
async function fetchWithRetry(url, init) {
|
|
3943
|
-
const
|
|
3947
|
+
const MAX_RETRIES4 = 3;
|
|
3944
3948
|
const BASE_DELAY_MS2 = 200;
|
|
3945
3949
|
let lastError;
|
|
3946
|
-
for (let attempt = 0; attempt <=
|
|
3950
|
+
for (let attempt = 0; attempt <= MAX_RETRIES4; attempt++) {
|
|
3947
3951
|
try {
|
|
3948
3952
|
const signal = AbortSignal.timeout(FETCH_TIMEOUT_MS);
|
|
3949
3953
|
const resp = await fetch(url, { ...init, signal });
|
|
3950
|
-
if (resp && resp.status >= 500 && attempt <
|
|
3954
|
+
if (resp && resp.status >= 500 && attempt < MAX_RETRIES4) {
|
|
3951
3955
|
await new Promise((r) => setTimeout(r, BASE_DELAY_MS2 * Math.pow(2, attempt)));
|
|
3952
3956
|
continue;
|
|
3953
3957
|
}
|
|
3954
3958
|
return resp;
|
|
3955
3959
|
} catch (err) {
|
|
3956
3960
|
lastError = err;
|
|
3957
|
-
if (attempt ===
|
|
3961
|
+
if (attempt === MAX_RETRIES4) throw err;
|
|
3958
3962
|
await new Promise((r) => setTimeout(r, BASE_DELAY_MS2 * Math.pow(2, attempt)));
|
|
3959
3963
|
}
|
|
3960
3964
|
}
|
|
@@ -7583,6 +7587,14 @@ var init_agent_config = __esm({
|
|
|
7583
7587
|
});
|
|
7584
7588
|
|
|
7585
7589
|
// src/lib/intercom-queue.ts
|
|
7590
|
+
var intercom_queue_exports = {};
|
|
7591
|
+
__export(intercom_queue_exports, {
|
|
7592
|
+
clearQueueForAgent: () => clearQueueForAgent,
|
|
7593
|
+
drainForSession: () => drainForSession,
|
|
7594
|
+
drainQueue: () => drainQueue,
|
|
7595
|
+
queueIntercom: () => queueIntercom,
|
|
7596
|
+
readQueue: () => readQueue
|
|
7597
|
+
});
|
|
7586
7598
|
import { readFileSync as readFileSync11, writeFileSync as writeFileSync9, renameSync as renameSync3, existsSync as existsSync14, mkdirSync as mkdirSync10 } from "fs";
|
|
7587
7599
|
import path15 from "path";
|
|
7588
7600
|
import os9 from "os";
|
|
@@ -7621,11 +7633,80 @@ function queueIntercom(targetSession, reason) {
|
|
|
7621
7633
|
}
|
|
7622
7634
|
writeQueue(queue);
|
|
7623
7635
|
}
|
|
7624
|
-
|
|
7636
|
+
function drainQueue(isSessionBusy2, sendKeys) {
|
|
7637
|
+
const queue = readQueue();
|
|
7638
|
+
if (queue.length === 0) return { drained: 0, failed: 0 };
|
|
7639
|
+
const remaining = [];
|
|
7640
|
+
let drained = 0;
|
|
7641
|
+
let failed = 0;
|
|
7642
|
+
for (const item of queue) {
|
|
7643
|
+
const age = Date.now() - new Date(item.queuedAt).getTime();
|
|
7644
|
+
if (age > TTL_MS) {
|
|
7645
|
+
logQueue(`EXPIRED \u2192 ${item.targetSession} (${Math.round(age / 6e4)}min old, reason: ${item.reason})`);
|
|
7646
|
+
failed++;
|
|
7647
|
+
continue;
|
|
7648
|
+
}
|
|
7649
|
+
try {
|
|
7650
|
+
if (!isSessionBusy2(item.targetSession)) {
|
|
7651
|
+
const success = sendKeys(item.targetSession);
|
|
7652
|
+
if (success) {
|
|
7653
|
+
logQueue(`DRAINED \u2192 ${item.targetSession} (after ${item.attempts} retries)`);
|
|
7654
|
+
drained++;
|
|
7655
|
+
continue;
|
|
7656
|
+
}
|
|
7657
|
+
}
|
|
7658
|
+
} catch {
|
|
7659
|
+
}
|
|
7660
|
+
item.attempts++;
|
|
7661
|
+
if (item.attempts >= MAX_RETRIES2) {
|
|
7662
|
+
logQueue(`FAILED \u2192 ${item.targetSession} (${MAX_RETRIES2} retries exhausted, reason: ${item.reason})`);
|
|
7663
|
+
failed++;
|
|
7664
|
+
continue;
|
|
7665
|
+
}
|
|
7666
|
+
remaining.push(item);
|
|
7667
|
+
}
|
|
7668
|
+
writeQueue(remaining);
|
|
7669
|
+
return { drained, failed };
|
|
7670
|
+
}
|
|
7671
|
+
function drainForSession(targetSession, sendKeys) {
|
|
7672
|
+
const queue = readQueue();
|
|
7673
|
+
const match = queue.findIndex((q) => q.targetSession === targetSession);
|
|
7674
|
+
if (match < 0) return false;
|
|
7675
|
+
const success = sendKeys(targetSession);
|
|
7676
|
+
if (success) {
|
|
7677
|
+
queue.splice(match, 1);
|
|
7678
|
+
writeQueue(queue);
|
|
7679
|
+
logQueue(`DRAINED \u2192 ${targetSession} (prompt-submit trigger)`);
|
|
7680
|
+
return true;
|
|
7681
|
+
}
|
|
7682
|
+
return false;
|
|
7683
|
+
}
|
|
7684
|
+
function clearQueueForAgent(agentName) {
|
|
7685
|
+
const queue = readQueue();
|
|
7686
|
+
const before = queue.length;
|
|
7687
|
+
const filtered = queue.filter((q) => !q.targetSession.startsWith(`${agentName}-`));
|
|
7688
|
+
if (filtered.length < before) {
|
|
7689
|
+
writeQueue(filtered);
|
|
7690
|
+
logQueue(`CLEARED ${before - filtered.length} stale item(s) for ${agentName}`);
|
|
7691
|
+
}
|
|
7692
|
+
}
|
|
7693
|
+
function logQueue(msg) {
|
|
7694
|
+
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] [queue] ${msg}
|
|
7695
|
+
`;
|
|
7696
|
+
process.stderr.write(`[intercom-queue] ${msg}
|
|
7697
|
+
`);
|
|
7698
|
+
try {
|
|
7699
|
+
const { appendFileSync: appendFileSync3 } = __require("fs");
|
|
7700
|
+
appendFileSync3(INTERCOM_LOG, line);
|
|
7701
|
+
} catch {
|
|
7702
|
+
}
|
|
7703
|
+
}
|
|
7704
|
+
var QUEUE_PATH, MAX_RETRIES2, TTL_MS, INTERCOM_LOG;
|
|
7625
7705
|
var init_intercom_queue = __esm({
|
|
7626
7706
|
"src/lib/intercom-queue.ts"() {
|
|
7627
7707
|
"use strict";
|
|
7628
7708
|
QUEUE_PATH = path15.join(os9.homedir(), ".exe-os", "intercom-queue.json");
|
|
7709
|
+
MAX_RETRIES2 = 5;
|
|
7629
7710
|
TTL_MS = 60 * 60 * 1e3;
|
|
7630
7711
|
INTERCOM_LOG = path15.join(os9.homedir(), ".exe-os", "intercom.log");
|
|
7631
7712
|
}
|
|
@@ -8332,6 +8413,13 @@ ${input.result}` : `\u26A0\uFE0F ${warning}`;
|
|
|
8332
8413
|
await client.execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
8333
8414
|
} catch {
|
|
8334
8415
|
}
|
|
8416
|
+
if (input.status === "done" || input.status === "cancelled") {
|
|
8417
|
+
try {
|
|
8418
|
+
const { clearQueueForAgent: clearQueueForAgent2 } = await Promise.resolve().then(() => (init_intercom_queue(), intercom_queue_exports));
|
|
8419
|
+
clearQueueForAgent2(String(row.assigned_to));
|
|
8420
|
+
} catch {
|
|
8421
|
+
}
|
|
8422
|
+
}
|
|
8335
8423
|
try {
|
|
8336
8424
|
await writeCheckpoint({
|
|
8337
8425
|
taskId,
|
|
@@ -10571,7 +10659,7 @@ async function deliverLocalMessage(messageId) {
|
|
|
10571
10659
|
return true;
|
|
10572
10660
|
} catch {
|
|
10573
10661
|
const newRetryCount = msg.retryCount + 1;
|
|
10574
|
-
if (newRetryCount >=
|
|
10662
|
+
if (newRetryCount >= MAX_RETRIES3) {
|
|
10575
10663
|
await markFailed(messageId, "session unavailable after 10 retries");
|
|
10576
10664
|
} else {
|
|
10577
10665
|
await client.execute({
|
|
@@ -10660,7 +10748,7 @@ async function retryPendingMessages() {
|
|
|
10660
10748
|
sql: `SELECT * FROM messages
|
|
10661
10749
|
WHERE status = 'pending' AND retry_count < ?
|
|
10662
10750
|
ORDER BY id`,
|
|
10663
|
-
args: [
|
|
10751
|
+
args: [MAX_RETRIES3]
|
|
10664
10752
|
});
|
|
10665
10753
|
let delivered = 0;
|
|
10666
10754
|
for (const row of result.rows) {
|
|
@@ -10673,13 +10761,13 @@ async function retryPendingMessages() {
|
|
|
10673
10761
|
}
|
|
10674
10762
|
return delivered;
|
|
10675
10763
|
}
|
|
10676
|
-
var
|
|
10764
|
+
var MAX_RETRIES3, _wsClientSend;
|
|
10677
10765
|
var init_messaging = __esm({
|
|
10678
10766
|
"src/lib/messaging.ts"() {
|
|
10679
10767
|
"use strict";
|
|
10680
10768
|
init_database();
|
|
10681
10769
|
init_tmux_routing();
|
|
10682
|
-
|
|
10770
|
+
MAX_RETRIES3 = 10;
|
|
10683
10771
|
_wsClientSend = null;
|
|
10684
10772
|
}
|
|
10685
10773
|
});
|
|
@@ -11692,11 +11780,11 @@ async function downloadModel(opts) {
|
|
|
11692
11780
|
return destPath;
|
|
11693
11781
|
}
|
|
11694
11782
|
}
|
|
11695
|
-
const
|
|
11783
|
+
const MAX_RETRIES4 = 3;
|
|
11696
11784
|
const DOWNLOAD_TIMEOUT_MS = 3e5;
|
|
11697
11785
|
let lastErr;
|
|
11698
11786
|
let downloaded = 0;
|
|
11699
|
-
for (let attempt = 1; attempt <=
|
|
11787
|
+
for (let attempt = 1; attempt <= MAX_RETRIES4; attempt++) {
|
|
11700
11788
|
try {
|
|
11701
11789
|
if (existsSync21(tmpPath)) unlinkSync11(tmpPath);
|
|
11702
11790
|
const response = await fetchFn(GGUF_URL, {
|
|
@@ -11739,7 +11827,7 @@ async function downloadModel(opts) {
|
|
|
11739
11827
|
return destPath;
|
|
11740
11828
|
} catch (err) {
|
|
11741
11829
|
lastErr = err instanceof Error ? err : new Error(String(err));
|
|
11742
|
-
if (attempt <
|
|
11830
|
+
if (attempt < MAX_RETRIES4) {
|
|
11743
11831
|
process.stderr.write(`
|
|
11744
11832
|
Download attempt ${attempt} failed, retrying...
|
|
11745
11833
|
`);
|
|
@@ -27838,7 +27926,11 @@ import os16 from "os";
|
|
|
27838
27926
|
async function mergeCodexHooks(packageRoot, homeDir = os16.homedir()) {
|
|
27839
27927
|
const codexDir = path40.join(homeDir, ".codex");
|
|
27840
27928
|
const hooksPath = path40.join(codexDir, "hooks.json");
|
|
27929
|
+
const logsDir = path40.join(homeDir, ".exe-os", "logs");
|
|
27930
|
+
const hookLogPath = path40.join(logsDir, "hooks.log");
|
|
27931
|
+
const logSuffix = ` 2>> "${hookLogPath}"`;
|
|
27841
27932
|
await mkdir8(codexDir, { recursive: true });
|
|
27933
|
+
await mkdir8(logsDir, { recursive: true });
|
|
27842
27934
|
let hooksJson = {};
|
|
27843
27935
|
if (existsSync27(hooksPath)) {
|
|
27844
27936
|
try {
|
|
@@ -27857,7 +27949,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os16.homedir()) {
|
|
|
27857
27949
|
hooks: [
|
|
27858
27950
|
{
|
|
27859
27951
|
type: "command",
|
|
27860
|
-
command: `node "${path40.join(packageRoot, "dist", "hooks", "session-start.js")}"`,
|
|
27952
|
+
command: `node "${path40.join(packageRoot, "dist", "hooks", "session-start.js")}"${logSuffix}`,
|
|
27861
27953
|
timeout: 30,
|
|
27862
27954
|
statusMessage: "exe-os: loading memory brief"
|
|
27863
27955
|
}
|
|
@@ -27872,11 +27964,11 @@ async function mergeCodexHooks(packageRoot, homeDir = os16.homedir()) {
|
|
|
27872
27964
|
hooks: [
|
|
27873
27965
|
{
|
|
27874
27966
|
type: "command",
|
|
27875
|
-
command: `node "${path40.join(packageRoot, "dist", "hooks", "ingest.js")}"`
|
|
27967
|
+
command: `node "${path40.join(packageRoot, "dist", "hooks", "ingest.js")}"${logSuffix}`
|
|
27876
27968
|
},
|
|
27877
27969
|
{
|
|
27878
27970
|
type: "command",
|
|
27879
|
-
command: `node "${path40.join(packageRoot, "dist", "hooks", "error-recall.js")}"`
|
|
27971
|
+
command: `node "${path40.join(packageRoot, "dist", "hooks", "error-recall.js")}"${logSuffix}`
|
|
27880
27972
|
}
|
|
27881
27973
|
]
|
|
27882
27974
|
},
|
|
@@ -27888,11 +27980,11 @@ async function mergeCodexHooks(packageRoot, homeDir = os16.homedir()) {
|
|
|
27888
27980
|
hooks: [
|
|
27889
27981
|
{
|
|
27890
27982
|
type: "command",
|
|
27891
|
-
command: `node "${path40.join(packageRoot, "dist", "hooks", "prompt-submit.js")}"`
|
|
27983
|
+
command: `node "${path40.join(packageRoot, "dist", "hooks", "prompt-submit.js")}"${logSuffix}`
|
|
27892
27984
|
},
|
|
27893
27985
|
{
|
|
27894
27986
|
type: "command",
|
|
27895
|
-
command: `node "${path40.join(packageRoot, "dist", "hooks", "exe-heartbeat-hook.js")}"`,
|
|
27987
|
+
command: `node "${path40.join(packageRoot, "dist", "hooks", "exe-heartbeat-hook.js")}"${logSuffix}`,
|
|
27896
27988
|
timeout: 5
|
|
27897
27989
|
}
|
|
27898
27990
|
]
|
|
@@ -27905,7 +27997,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os16.homedir()) {
|
|
|
27905
27997
|
hooks: [
|
|
27906
27998
|
{
|
|
27907
27999
|
type: "command",
|
|
27908
|
-
command: `node "${path40.join(packageRoot, "dist", "hooks", "stop.js")}"`
|
|
28000
|
+
command: `node "${path40.join(packageRoot, "dist", "hooks", "stop.js")}"${logSuffix}`
|
|
27909
28001
|
}
|
|
27910
28002
|
]
|
|
27911
28003
|
},
|
|
@@ -27918,7 +28010,7 @@ async function mergeCodexHooks(packageRoot, homeDir = os16.homedir()) {
|
|
|
27918
28010
|
hooks: [
|
|
27919
28011
|
{
|
|
27920
28012
|
type: "command",
|
|
27921
|
-
command: `node "${path40.join(packageRoot, "dist", "hooks", "pre-tool-use.js")}"`
|
|
28013
|
+
command: `node "${path40.join(packageRoot, "dist", "hooks", "pre-tool-use.js")}"${logSuffix}`
|
|
27922
28014
|
}
|
|
27923
28015
|
]
|
|
27924
28016
|
},
|
package/dist/bin/exe-boot.js
CHANGED
|
@@ -2994,6 +2994,14 @@ var init_agent_config = __esm({
|
|
|
2994
2994
|
});
|
|
2995
2995
|
|
|
2996
2996
|
// src/lib/intercom-queue.ts
|
|
2997
|
+
var intercom_queue_exports = {};
|
|
2998
|
+
__export(intercom_queue_exports, {
|
|
2999
|
+
clearQueueForAgent: () => clearQueueForAgent,
|
|
3000
|
+
drainForSession: () => drainForSession,
|
|
3001
|
+
drainQueue: () => drainQueue,
|
|
3002
|
+
queueIntercom: () => queueIntercom,
|
|
3003
|
+
readQueue: () => readQueue
|
|
3004
|
+
});
|
|
2997
3005
|
import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, renameSync as renameSync3, existsSync as existsSync8, mkdirSync as mkdirSync4 } from "fs";
|
|
2998
3006
|
import path8 from "path";
|
|
2999
3007
|
import os6 from "os";
|
|
@@ -3032,11 +3040,80 @@ function queueIntercom(targetSession, reason) {
|
|
|
3032
3040
|
}
|
|
3033
3041
|
writeQueue(queue);
|
|
3034
3042
|
}
|
|
3035
|
-
|
|
3043
|
+
function drainQueue(isSessionBusy2, sendKeys) {
|
|
3044
|
+
const queue = readQueue();
|
|
3045
|
+
if (queue.length === 0) return { drained: 0, failed: 0 };
|
|
3046
|
+
const remaining = [];
|
|
3047
|
+
let drained = 0;
|
|
3048
|
+
let failed = 0;
|
|
3049
|
+
for (const item of queue) {
|
|
3050
|
+
const age = Date.now() - new Date(item.queuedAt).getTime();
|
|
3051
|
+
if (age > TTL_MS) {
|
|
3052
|
+
logQueue(`EXPIRED \u2192 ${item.targetSession} (${Math.round(age / 6e4)}min old, reason: ${item.reason})`);
|
|
3053
|
+
failed++;
|
|
3054
|
+
continue;
|
|
3055
|
+
}
|
|
3056
|
+
try {
|
|
3057
|
+
if (!isSessionBusy2(item.targetSession)) {
|
|
3058
|
+
const success = sendKeys(item.targetSession);
|
|
3059
|
+
if (success) {
|
|
3060
|
+
logQueue(`DRAINED \u2192 ${item.targetSession} (after ${item.attempts} retries)`);
|
|
3061
|
+
drained++;
|
|
3062
|
+
continue;
|
|
3063
|
+
}
|
|
3064
|
+
}
|
|
3065
|
+
} catch {
|
|
3066
|
+
}
|
|
3067
|
+
item.attempts++;
|
|
3068
|
+
if (item.attempts >= MAX_RETRIES2) {
|
|
3069
|
+
logQueue(`FAILED \u2192 ${item.targetSession} (${MAX_RETRIES2} retries exhausted, reason: ${item.reason})`);
|
|
3070
|
+
failed++;
|
|
3071
|
+
continue;
|
|
3072
|
+
}
|
|
3073
|
+
remaining.push(item);
|
|
3074
|
+
}
|
|
3075
|
+
writeQueue(remaining);
|
|
3076
|
+
return { drained, failed };
|
|
3077
|
+
}
|
|
3078
|
+
function drainForSession(targetSession, sendKeys) {
|
|
3079
|
+
const queue = readQueue();
|
|
3080
|
+
const match = queue.findIndex((q) => q.targetSession === targetSession);
|
|
3081
|
+
if (match < 0) return false;
|
|
3082
|
+
const success = sendKeys(targetSession);
|
|
3083
|
+
if (success) {
|
|
3084
|
+
queue.splice(match, 1);
|
|
3085
|
+
writeQueue(queue);
|
|
3086
|
+
logQueue(`DRAINED \u2192 ${targetSession} (prompt-submit trigger)`);
|
|
3087
|
+
return true;
|
|
3088
|
+
}
|
|
3089
|
+
return false;
|
|
3090
|
+
}
|
|
3091
|
+
function clearQueueForAgent(agentName) {
|
|
3092
|
+
const queue = readQueue();
|
|
3093
|
+
const before = queue.length;
|
|
3094
|
+
const filtered = queue.filter((q) => !q.targetSession.startsWith(`${agentName}-`));
|
|
3095
|
+
if (filtered.length < before) {
|
|
3096
|
+
writeQueue(filtered);
|
|
3097
|
+
logQueue(`CLEARED ${before - filtered.length} stale item(s) for ${agentName}`);
|
|
3098
|
+
}
|
|
3099
|
+
}
|
|
3100
|
+
function logQueue(msg) {
|
|
3101
|
+
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] [queue] ${msg}
|
|
3102
|
+
`;
|
|
3103
|
+
process.stderr.write(`[intercom-queue] ${msg}
|
|
3104
|
+
`);
|
|
3105
|
+
try {
|
|
3106
|
+
const { appendFileSync: appendFileSync3 } = __require("fs");
|
|
3107
|
+
appendFileSync3(INTERCOM_LOG, line);
|
|
3108
|
+
} catch {
|
|
3109
|
+
}
|
|
3110
|
+
}
|
|
3111
|
+
var QUEUE_PATH, MAX_RETRIES2, TTL_MS, INTERCOM_LOG;
|
|
3036
3112
|
var init_intercom_queue = __esm({
|
|
3037
3113
|
"src/lib/intercom-queue.ts"() {
|
|
3038
3114
|
"use strict";
|
|
3039
3115
|
QUEUE_PATH = path8.join(os6.homedir(), ".exe-os", "intercom-queue.json");
|
|
3116
|
+
MAX_RETRIES2 = 5;
|
|
3040
3117
|
TTL_MS = 60 * 60 * 1e3;
|
|
3041
3118
|
INTERCOM_LOG = path8.join(os6.homedir(), ".exe-os", "intercom.log");
|
|
3042
3119
|
}
|
|
@@ -4276,6 +4353,13 @@ ${input.result}` : `\u26A0\uFE0F ${warning}`;
|
|
|
4276
4353
|
await client.execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
4277
4354
|
} catch {
|
|
4278
4355
|
}
|
|
4356
|
+
if (input.status === "done" || input.status === "cancelled") {
|
|
4357
|
+
try {
|
|
4358
|
+
const { clearQueueForAgent: clearQueueForAgent2 } = await Promise.resolve().then(() => (init_intercom_queue(), intercom_queue_exports));
|
|
4359
|
+
clearQueueForAgent2(String(row.assigned_to));
|
|
4360
|
+
} catch {
|
|
4361
|
+
}
|
|
4362
|
+
}
|
|
4279
4363
|
try {
|
|
4280
4364
|
await writeCheckpoint({
|
|
4281
4365
|
taskId,
|
|
@@ -6919,21 +7003,21 @@ async function withRosterLock(fn) {
|
|
|
6919
7003
|
}
|
|
6920
7004
|
}
|
|
6921
7005
|
async function fetchWithRetry(url, init) {
|
|
6922
|
-
const
|
|
7006
|
+
const MAX_RETRIES3 = 3;
|
|
6923
7007
|
const BASE_DELAY_MS2 = 200;
|
|
6924
7008
|
let lastError;
|
|
6925
|
-
for (let attempt = 0; attempt <=
|
|
7009
|
+
for (let attempt = 0; attempt <= MAX_RETRIES3; attempt++) {
|
|
6926
7010
|
try {
|
|
6927
7011
|
const signal = AbortSignal.timeout(FETCH_TIMEOUT_MS);
|
|
6928
7012
|
const resp = await fetch(url, { ...init, signal });
|
|
6929
|
-
if (resp && resp.status >= 500 && attempt <
|
|
7013
|
+
if (resp && resp.status >= 500 && attempt < MAX_RETRIES3) {
|
|
6930
7014
|
await new Promise((r) => setTimeout(r, BASE_DELAY_MS2 * Math.pow(2, attempt)));
|
|
6931
7015
|
continue;
|
|
6932
7016
|
}
|
|
6933
7017
|
return resp;
|
|
6934
7018
|
} catch (err) {
|
|
6935
7019
|
lastError = err;
|
|
6936
|
-
if (attempt ===
|
|
7020
|
+
if (attempt === MAX_RETRIES3) throw err;
|
|
6937
7021
|
await new Promise((r) => setTimeout(r, BASE_DELAY_MS2 * Math.pow(2, attempt)));
|
|
6938
7022
|
}
|
|
6939
7023
|
}
|
package/dist/bin/exe-dispatch.js
CHANGED
|
@@ -3,6 +3,12 @@ var __defProp = Object.defineProperty;
|
|
|
3
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
7
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
8
|
+
}) : x)(function(x) {
|
|
9
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
10
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
11
|
+
});
|
|
6
12
|
var __esm = (fn, res) => function __init() {
|
|
7
13
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
8
14
|
};
|
|
@@ -547,6 +553,14 @@ var init_agent_config = __esm({
|
|
|
547
553
|
});
|
|
548
554
|
|
|
549
555
|
// src/lib/intercom-queue.ts
|
|
556
|
+
var intercom_queue_exports = {};
|
|
557
|
+
__export(intercom_queue_exports, {
|
|
558
|
+
clearQueueForAgent: () => clearQueueForAgent,
|
|
559
|
+
drainForSession: () => drainForSession,
|
|
560
|
+
drainQueue: () => drainQueue,
|
|
561
|
+
queueIntercom: () => queueIntercom,
|
|
562
|
+
readQueue: () => readQueue
|
|
563
|
+
});
|
|
550
564
|
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, renameSync as renameSync2, existsSync as existsSync4, mkdirSync as mkdirSync3 } from "fs";
|
|
551
565
|
import path4 from "path";
|
|
552
566
|
import os3 from "os";
|
|
@@ -585,11 +599,80 @@ function queueIntercom(targetSession, reason) {
|
|
|
585
599
|
}
|
|
586
600
|
writeQueue(queue);
|
|
587
601
|
}
|
|
588
|
-
|
|
602
|
+
function drainQueue(isSessionBusy2, sendKeys) {
|
|
603
|
+
const queue = readQueue();
|
|
604
|
+
if (queue.length === 0) return { drained: 0, failed: 0 };
|
|
605
|
+
const remaining = [];
|
|
606
|
+
let drained = 0;
|
|
607
|
+
let failed = 0;
|
|
608
|
+
for (const item of queue) {
|
|
609
|
+
const age = Date.now() - new Date(item.queuedAt).getTime();
|
|
610
|
+
if (age > TTL_MS) {
|
|
611
|
+
logQueue(`EXPIRED \u2192 ${item.targetSession} (${Math.round(age / 6e4)}min old, reason: ${item.reason})`);
|
|
612
|
+
failed++;
|
|
613
|
+
continue;
|
|
614
|
+
}
|
|
615
|
+
try {
|
|
616
|
+
if (!isSessionBusy2(item.targetSession)) {
|
|
617
|
+
const success = sendKeys(item.targetSession);
|
|
618
|
+
if (success) {
|
|
619
|
+
logQueue(`DRAINED \u2192 ${item.targetSession} (after ${item.attempts} retries)`);
|
|
620
|
+
drained++;
|
|
621
|
+
continue;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
} catch {
|
|
625
|
+
}
|
|
626
|
+
item.attempts++;
|
|
627
|
+
if (item.attempts >= MAX_RETRIES) {
|
|
628
|
+
logQueue(`FAILED \u2192 ${item.targetSession} (${MAX_RETRIES} retries exhausted, reason: ${item.reason})`);
|
|
629
|
+
failed++;
|
|
630
|
+
continue;
|
|
631
|
+
}
|
|
632
|
+
remaining.push(item);
|
|
633
|
+
}
|
|
634
|
+
writeQueue(remaining);
|
|
635
|
+
return { drained, failed };
|
|
636
|
+
}
|
|
637
|
+
function drainForSession(targetSession, sendKeys) {
|
|
638
|
+
const queue = readQueue();
|
|
639
|
+
const match = queue.findIndex((q) => q.targetSession === targetSession);
|
|
640
|
+
if (match < 0) return false;
|
|
641
|
+
const success = sendKeys(targetSession);
|
|
642
|
+
if (success) {
|
|
643
|
+
queue.splice(match, 1);
|
|
644
|
+
writeQueue(queue);
|
|
645
|
+
logQueue(`DRAINED \u2192 ${targetSession} (prompt-submit trigger)`);
|
|
646
|
+
return true;
|
|
647
|
+
}
|
|
648
|
+
return false;
|
|
649
|
+
}
|
|
650
|
+
function clearQueueForAgent(agentName) {
|
|
651
|
+
const queue = readQueue();
|
|
652
|
+
const before = queue.length;
|
|
653
|
+
const filtered = queue.filter((q) => !q.targetSession.startsWith(`${agentName}-`));
|
|
654
|
+
if (filtered.length < before) {
|
|
655
|
+
writeQueue(filtered);
|
|
656
|
+
logQueue(`CLEARED ${before - filtered.length} stale item(s) for ${agentName}`);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
function logQueue(msg) {
|
|
660
|
+
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] [queue] ${msg}
|
|
661
|
+
`;
|
|
662
|
+
process.stderr.write(`[intercom-queue] ${msg}
|
|
663
|
+
`);
|
|
664
|
+
try {
|
|
665
|
+
const { appendFileSync: appendFileSync2 } = __require("fs");
|
|
666
|
+
appendFileSync2(INTERCOM_LOG, line);
|
|
667
|
+
} catch {
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
var QUEUE_PATH, MAX_RETRIES, TTL_MS, INTERCOM_LOG;
|
|
589
671
|
var init_intercom_queue = __esm({
|
|
590
672
|
"src/lib/intercom-queue.ts"() {
|
|
591
673
|
"use strict";
|
|
592
674
|
QUEUE_PATH = path4.join(os3.homedir(), ".exe-os", "intercom-queue.json");
|
|
675
|
+
MAX_RETRIES = 5;
|
|
593
676
|
TTL_MS = 60 * 60 * 1e3;
|
|
594
677
|
INTERCOM_LOG = path4.join(os3.homedir(), ".exe-os", "intercom.log");
|
|
595
678
|
}
|
|
@@ -608,18 +691,18 @@ function delay(ms) {
|
|
|
608
691
|
}
|
|
609
692
|
async function retryOnBusy(fn, label) {
|
|
610
693
|
let lastError;
|
|
611
|
-
for (let attempt = 0; attempt <=
|
|
694
|
+
for (let attempt = 0; attempt <= MAX_RETRIES2; attempt++) {
|
|
612
695
|
try {
|
|
613
696
|
return await fn();
|
|
614
697
|
} catch (err) {
|
|
615
698
|
lastError = err;
|
|
616
|
-
if (!isBusyError(err) || attempt ===
|
|
699
|
+
if (!isBusyError(err) || attempt === MAX_RETRIES2) {
|
|
617
700
|
throw err;
|
|
618
701
|
}
|
|
619
702
|
const backoff = BASE_DELAY_MS * Math.pow(2, attempt);
|
|
620
703
|
const jitter = Math.floor(Math.random() * MAX_JITTER_MS);
|
|
621
704
|
process.stderr.write(
|
|
622
|
-
`[exe-os] SQLITE_BUSY ${label} retry ${attempt + 1}/${
|
|
705
|
+
`[exe-os] SQLITE_BUSY ${label} retry ${attempt + 1}/${MAX_RETRIES2} \u2014 waiting ${backoff + jitter}ms
|
|
623
706
|
`
|
|
624
707
|
);
|
|
625
708
|
await delay(backoff + jitter);
|
|
@@ -640,11 +723,11 @@ function wrapWithRetry(client) {
|
|
|
640
723
|
}
|
|
641
724
|
});
|
|
642
725
|
}
|
|
643
|
-
var
|
|
726
|
+
var MAX_RETRIES2, BASE_DELAY_MS, MAX_JITTER_MS;
|
|
644
727
|
var init_db_retry = __esm({
|
|
645
728
|
"src/lib/db-retry.ts"() {
|
|
646
729
|
"use strict";
|
|
647
|
-
|
|
730
|
+
MAX_RETRIES2 = 3;
|
|
648
731
|
BASE_DELAY_MS = 200;
|
|
649
732
|
MAX_JITTER_MS = 300;
|
|
650
733
|
}
|
|
@@ -2451,6 +2534,13 @@ ${input.result}` : `\u26A0\uFE0F ${warning}`;
|
|
|
2451
2534
|
await client.execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
2452
2535
|
} catch {
|
|
2453
2536
|
}
|
|
2537
|
+
if (input.status === "done" || input.status === "cancelled") {
|
|
2538
|
+
try {
|
|
2539
|
+
const { clearQueueForAgent: clearQueueForAgent2 } = await Promise.resolve().then(() => (init_intercom_queue(), intercom_queue_exports));
|
|
2540
|
+
clearQueueForAgent2(String(row.assigned_to));
|
|
2541
|
+
} catch {
|
|
2542
|
+
}
|
|
2543
|
+
}
|
|
2454
2544
|
try {
|
|
2455
2545
|
await writeCheckpoint({
|
|
2456
2546
|
taskId,
|