@askexenow/exe-os 0.9.0 → 0.9.2
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 +127 -34
- package/dist/bin/exe-agent-config.js +1 -1
- package/dist/bin/exe-boot.js +89 -5
- package/dist/bin/exe-call.js +1 -1
- 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-settings.js +1 -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/bin/update.js +3 -2
- 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 +18 -1
- package/dist/hooks/session-end.js +96 -6
- package/dist/hooks/stop.js +18 -0
- package/dist/index.js +94 -10
- package/dist/lib/agent-config.js +1 -1
- package/dist/lib/exe-daemon.js +18 -1
- package/dist/lib/tasks.js +91 -1
- package/dist/lib/tmux-routing.js +91 -1
- package/dist/mcp/server.js +955 -224
- 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/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,
|
package/dist/bin/exe-doctor.js
CHANGED
|
@@ -2025,7 +2025,7 @@ function isMainModule(importMetaUrl) {
|
|
|
2025
2025
|
}
|
|
2026
2026
|
|
|
2027
2027
|
// src/bin/exe-doctor.ts
|
|
2028
|
-
import { existsSync as existsSync6 } from "fs";
|
|
2028
|
+
import { existsSync as existsSync6, readFileSync as readFileSync3 } from "fs";
|
|
2029
2029
|
import { spawn } from "child_process";
|
|
2030
2030
|
import path6 from "path";
|
|
2031
2031
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
@@ -2437,6 +2437,46 @@ async function auditOrphanedProjects(client) {
|
|
|
2437
2437
|
}
|
|
2438
2438
|
return orphans;
|
|
2439
2439
|
}
|
|
2440
|
+
function auditHookHealth() {
|
|
2441
|
+
const logPath = path6.join(
|
|
2442
|
+
process.env.HOME ?? process.env.USERPROFILE ?? "",
|
|
2443
|
+
".exe-os",
|
|
2444
|
+
"logs",
|
|
2445
|
+
"hooks.log"
|
|
2446
|
+
);
|
|
2447
|
+
if (!existsSync6(logPath)) {
|
|
2448
|
+
return { logExists: false, totalLines: 0, errorsLastHour: 0, topPatterns: [] };
|
|
2449
|
+
}
|
|
2450
|
+
let content;
|
|
2451
|
+
try {
|
|
2452
|
+
content = readFileSync3(logPath, "utf-8");
|
|
2453
|
+
} catch {
|
|
2454
|
+
return { logExists: false, totalLines: 0, errorsLastHour: 0, topPatterns: [] };
|
|
2455
|
+
}
|
|
2456
|
+
const lines = content.split("\n").filter(Boolean);
|
|
2457
|
+
const totalLines = lines.length;
|
|
2458
|
+
const recent = lines.slice(-200);
|
|
2459
|
+
const oneHourAgo = new Date(Date.now() - 36e5).toISOString();
|
|
2460
|
+
let errorsLastHour = 0;
|
|
2461
|
+
const patternCounts = /* @__PURE__ */ new Map();
|
|
2462
|
+
for (const line of recent) {
|
|
2463
|
+
const isError = /error|Error|ERR|FAIL|throw|exception|TypeError|ReferenceError|SyntaxError/i.test(line);
|
|
2464
|
+
if (!isError) continue;
|
|
2465
|
+
const tsMatch = line.match(/(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})/);
|
|
2466
|
+
if (tsMatch && tsMatch[1] >= oneHourAgo) {
|
|
2467
|
+
errorsLastHour++;
|
|
2468
|
+
} else if (!tsMatch) {
|
|
2469
|
+
errorsLastHour++;
|
|
2470
|
+
}
|
|
2471
|
+
const patternMatch = line.match(/((?:TypeError|ReferenceError|SyntaxError|Error):[^\n]{0,80})/);
|
|
2472
|
+
if (patternMatch) {
|
|
2473
|
+
const p = patternMatch[1];
|
|
2474
|
+
patternCounts.set(p, (patternCounts.get(p) ?? 0) + 1);
|
|
2475
|
+
}
|
|
2476
|
+
}
|
|
2477
|
+
const topPatterns = [...patternCounts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5).map(([pattern, count]) => ({ pattern, count }));
|
|
2478
|
+
return { logExists: true, totalLines, errorsLastHour, topPatterns };
|
|
2479
|
+
}
|
|
2440
2480
|
async function runAudit(client, flags) {
|
|
2441
2481
|
const [stats, nullVectors, duplicates, bloated, fts, orphanedProjects, conflicts] = await Promise.all([
|
|
2442
2482
|
auditStats(client, flags),
|
|
@@ -2448,7 +2488,8 @@ async function runAudit(client, flags) {
|
|
|
2448
2488
|
detectConflicts(client, flags.project, flags.agent)
|
|
2449
2489
|
]);
|
|
2450
2490
|
const duplicateCount = duplicates.reduce((sum, d) => sum + d.delete_ids.length, 0);
|
|
2451
|
-
|
|
2491
|
+
const hookHealth = auditHookHealth();
|
|
2492
|
+
return { stats, nullVectors, duplicates, duplicateCount, bloated, fts, orphanedProjects, conflicts, hookHealth };
|
|
2452
2493
|
}
|
|
2453
2494
|
function indicator(value, warn) {
|
|
2454
2495
|
if (value === 0) return "\u{1F7E2}";
|
|
@@ -2516,6 +2557,17 @@ function formatReport(report, flags) {
|
|
|
2516
2557
|
} else {
|
|
2517
2558
|
lines.push("\u{1F7E2} Conflicts: none detected");
|
|
2518
2559
|
}
|
|
2560
|
+
const hh = report.hookHealth;
|
|
2561
|
+
if (!hh.logExists) {
|
|
2562
|
+
lines.push("\u{1F7E0} Hook logs: no log file (run installer to enable stderr capture)");
|
|
2563
|
+
} else if (hh.errorsLastHour === 0) {
|
|
2564
|
+
lines.push(`\u{1F7E2} Hook logs: ${fmtNum(hh.totalLines)} lines, 0 errors in last hour`);
|
|
2565
|
+
} else {
|
|
2566
|
+
lines.push(`\u{1F534} Hook logs: ${fmtNum(hh.errorsLastHour)} errors in last hour (${fmtNum(hh.totalLines)} total lines)`);
|
|
2567
|
+
for (const p of hh.topPatterns) {
|
|
2568
|
+
lines.push(` ${p.count}x: ${p.pattern}`);
|
|
2569
|
+
}
|
|
2570
|
+
}
|
|
2519
2571
|
lines.push("");
|
|
2520
2572
|
if (flags.verbose) {
|
|
2521
2573
|
if (report.duplicates.length > 0) {
|
|
@@ -2749,6 +2801,7 @@ export {
|
|
|
2749
2801
|
auditBloated,
|
|
2750
2802
|
auditDuplicates,
|
|
2751
2803
|
auditFts,
|
|
2804
|
+
auditHookHealth,
|
|
2752
2805
|
auditNullVectors,
|
|
2753
2806
|
auditOrphanedProjects,
|
|
2754
2807
|
auditStats,
|
package/dist/bin/exe-gateway.js
CHANGED
|
@@ -6448,6 +6448,14 @@ var init_agent_config = __esm({
|
|
|
6448
6448
|
});
|
|
6449
6449
|
|
|
6450
6450
|
// src/lib/intercom-queue.ts
|
|
6451
|
+
var intercom_queue_exports = {};
|
|
6452
|
+
__export(intercom_queue_exports, {
|
|
6453
|
+
clearQueueForAgent: () => clearQueueForAgent,
|
|
6454
|
+
drainForSession: () => drainForSession,
|
|
6455
|
+
drainQueue: () => drainQueue,
|
|
6456
|
+
queueIntercom: () => queueIntercom,
|
|
6457
|
+
readQueue: () => readQueue
|
|
6458
|
+
});
|
|
6451
6459
|
import { readFileSync as readFileSync8, writeFileSync as writeFileSync5, renameSync as renameSync3, existsSync as existsSync9, mkdirSync as mkdirSync6 } from "fs";
|
|
6452
6460
|
import path10 from "path";
|
|
6453
6461
|
import os7 from "os";
|
|
@@ -6486,11 +6494,80 @@ function queueIntercom(targetSession, reason) {
|
|
|
6486
6494
|
}
|
|
6487
6495
|
writeQueue(queue);
|
|
6488
6496
|
}
|
|
6489
|
-
|
|
6497
|
+
function drainQueue(isSessionBusy2, sendKeys) {
|
|
6498
|
+
const queue = readQueue();
|
|
6499
|
+
if (queue.length === 0) return { drained: 0, failed: 0 };
|
|
6500
|
+
const remaining = [];
|
|
6501
|
+
let drained = 0;
|
|
6502
|
+
let failed = 0;
|
|
6503
|
+
for (const item of queue) {
|
|
6504
|
+
const age = Date.now() - new Date(item.queuedAt).getTime();
|
|
6505
|
+
if (age > TTL_MS) {
|
|
6506
|
+
logQueue(`EXPIRED \u2192 ${item.targetSession} (${Math.round(age / 6e4)}min old, reason: ${item.reason})`);
|
|
6507
|
+
failed++;
|
|
6508
|
+
continue;
|
|
6509
|
+
}
|
|
6510
|
+
try {
|
|
6511
|
+
if (!isSessionBusy2(item.targetSession)) {
|
|
6512
|
+
const success = sendKeys(item.targetSession);
|
|
6513
|
+
if (success) {
|
|
6514
|
+
logQueue(`DRAINED \u2192 ${item.targetSession} (after ${item.attempts} retries)`);
|
|
6515
|
+
drained++;
|
|
6516
|
+
continue;
|
|
6517
|
+
}
|
|
6518
|
+
}
|
|
6519
|
+
} catch {
|
|
6520
|
+
}
|
|
6521
|
+
item.attempts++;
|
|
6522
|
+
if (item.attempts >= MAX_RETRIES2) {
|
|
6523
|
+
logQueue(`FAILED \u2192 ${item.targetSession} (${MAX_RETRIES2} retries exhausted, reason: ${item.reason})`);
|
|
6524
|
+
failed++;
|
|
6525
|
+
continue;
|
|
6526
|
+
}
|
|
6527
|
+
remaining.push(item);
|
|
6528
|
+
}
|
|
6529
|
+
writeQueue(remaining);
|
|
6530
|
+
return { drained, failed };
|
|
6531
|
+
}
|
|
6532
|
+
function drainForSession(targetSession, sendKeys) {
|
|
6533
|
+
const queue = readQueue();
|
|
6534
|
+
const match = queue.findIndex((q) => q.targetSession === targetSession);
|
|
6535
|
+
if (match < 0) return false;
|
|
6536
|
+
const success = sendKeys(targetSession);
|
|
6537
|
+
if (success) {
|
|
6538
|
+
queue.splice(match, 1);
|
|
6539
|
+
writeQueue(queue);
|
|
6540
|
+
logQueue(`DRAINED \u2192 ${targetSession} (prompt-submit trigger)`);
|
|
6541
|
+
return true;
|
|
6542
|
+
}
|
|
6543
|
+
return false;
|
|
6544
|
+
}
|
|
6545
|
+
function clearQueueForAgent(agentName) {
|
|
6546
|
+
const queue = readQueue();
|
|
6547
|
+
const before = queue.length;
|
|
6548
|
+
const filtered = queue.filter((q) => !q.targetSession.startsWith(`${agentName}-`));
|
|
6549
|
+
if (filtered.length < before) {
|
|
6550
|
+
writeQueue(filtered);
|
|
6551
|
+
logQueue(`CLEARED ${before - filtered.length} stale item(s) for ${agentName}`);
|
|
6552
|
+
}
|
|
6553
|
+
}
|
|
6554
|
+
function logQueue(msg) {
|
|
6555
|
+
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] [queue] ${msg}
|
|
6556
|
+
`;
|
|
6557
|
+
process.stderr.write(`[intercom-queue] ${msg}
|
|
6558
|
+
`);
|
|
6559
|
+
try {
|
|
6560
|
+
const { appendFileSync: appendFileSync2 } = __require("fs");
|
|
6561
|
+
appendFileSync2(INTERCOM_LOG, line);
|
|
6562
|
+
} catch {
|
|
6563
|
+
}
|
|
6564
|
+
}
|
|
6565
|
+
var QUEUE_PATH, MAX_RETRIES2, TTL_MS, INTERCOM_LOG;
|
|
6490
6566
|
var init_intercom_queue = __esm({
|
|
6491
6567
|
"src/lib/intercom-queue.ts"() {
|
|
6492
6568
|
"use strict";
|
|
6493
6569
|
QUEUE_PATH = path10.join(os7.homedir(), ".exe-os", "intercom-queue.json");
|
|
6570
|
+
MAX_RETRIES2 = 5;
|
|
6494
6571
|
TTL_MS = 60 * 60 * 1e3;
|
|
6495
6572
|
INTERCOM_LOG = path10.join(os7.homedir(), ".exe-os", "intercom.log");
|
|
6496
6573
|
}
|
|
@@ -7176,6 +7253,13 @@ ${input.result}` : `\u26A0\uFE0F ${warning}`;
|
|
|
7176
7253
|
await client.execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
7177
7254
|
} catch {
|
|
7178
7255
|
}
|
|
7256
|
+
if (input.status === "done" || input.status === "cancelled") {
|
|
7257
|
+
try {
|
|
7258
|
+
const { clearQueueForAgent: clearQueueForAgent2 } = await Promise.resolve().then(() => (init_intercom_queue(), intercom_queue_exports));
|
|
7259
|
+
clearQueueForAgent2(String(row.assigned_to));
|
|
7260
|
+
} catch {
|
|
7261
|
+
}
|
|
7262
|
+
}
|
|
7179
7263
|
try {
|
|
7180
7264
|
await writeCheckpoint({
|
|
7181
7265
|
taskId,
|
|
@@ -9415,7 +9499,7 @@ async function deliverLocalMessage(messageId) {
|
|
|
9415
9499
|
return true;
|
|
9416
9500
|
} catch {
|
|
9417
9501
|
const newRetryCount = msg.retryCount + 1;
|
|
9418
|
-
if (newRetryCount >=
|
|
9502
|
+
if (newRetryCount >= MAX_RETRIES3) {
|
|
9419
9503
|
await markFailed(messageId, "session unavailable after 10 retries");
|
|
9420
9504
|
} else {
|
|
9421
9505
|
await client.execute({
|
|
@@ -9504,7 +9588,7 @@ async function retryPendingMessages() {
|
|
|
9504
9588
|
sql: `SELECT * FROM messages
|
|
9505
9589
|
WHERE status = 'pending' AND retry_count < ?
|
|
9506
9590
|
ORDER BY id`,
|
|
9507
|
-
args: [
|
|
9591
|
+
args: [MAX_RETRIES3]
|
|
9508
9592
|
});
|
|
9509
9593
|
let delivered = 0;
|
|
9510
9594
|
for (const row of result.rows) {
|
|
@@ -9517,13 +9601,13 @@ async function retryPendingMessages() {
|
|
|
9517
9601
|
}
|
|
9518
9602
|
return delivered;
|
|
9519
9603
|
}
|
|
9520
|
-
var
|
|
9604
|
+
var MAX_RETRIES3, _wsClientSend;
|
|
9521
9605
|
var init_messaging = __esm({
|
|
9522
9606
|
"src/lib/messaging.ts"() {
|
|
9523
9607
|
"use strict";
|
|
9524
9608
|
init_database();
|
|
9525
9609
|
init_tmux_routing();
|
|
9526
|
-
|
|
9610
|
+
MAX_RETRIES3 = 10;
|
|
9527
9611
|
_wsClientSend = null;
|
|
9528
9612
|
}
|
|
9529
9613
|
});
|
|
@@ -1162,6 +1162,10 @@ async function cleanSettingsJsonMcp(settingsPath) {
|
|
|
1162
1162
|
}
|
|
1163
1163
|
async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
1164
1164
|
const settingsPath = path9.join(homeDir, ".claude", "settings.json");
|
|
1165
|
+
const logsDir = path9.join(homeDir, ".exe-os", "logs");
|
|
1166
|
+
const hookLogPath = path9.join(logsDir, "hooks.log");
|
|
1167
|
+
const logSuffix = ` 2>> "${hookLogPath}"`;
|
|
1168
|
+
await mkdir3(logsDir, { recursive: true });
|
|
1165
1169
|
let settings = {};
|
|
1166
1170
|
if (existsSync9(settingsPath)) {
|
|
1167
1171
|
try {
|
|
@@ -1185,11 +1189,11 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
1185
1189
|
hooks: [
|
|
1186
1190
|
{
|
|
1187
1191
|
type: "command",
|
|
1188
|
-
command: `node "${path9.join(packageRoot, "dist", "hooks", "ingest.js")}"`
|
|
1192
|
+
command: `node "${path9.join(packageRoot, "dist", "hooks", "ingest.js")}"${logSuffix}`
|
|
1189
1193
|
},
|
|
1190
1194
|
{
|
|
1191
1195
|
type: "command",
|
|
1192
|
-
command: `node "${path9.join(packageRoot, "dist", "hooks", "error-recall.js")}"`
|
|
1196
|
+
command: `node "${path9.join(packageRoot, "dist", "hooks", "error-recall.js")}"${logSuffix}`
|
|
1193
1197
|
}
|
|
1194
1198
|
]
|
|
1195
1199
|
},
|
|
@@ -1201,7 +1205,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
1201
1205
|
hooks: [
|
|
1202
1206
|
{
|
|
1203
1207
|
type: "command",
|
|
1204
|
-
command: `node "${path9.join(packageRoot, "dist", "hooks", "session-start.js")}"`,
|
|
1208
|
+
command: `node "${path9.join(packageRoot, "dist", "hooks", "session-start.js")}"${logSuffix}`,
|
|
1205
1209
|
timeout: 1e4
|
|
1206
1210
|
}
|
|
1207
1211
|
]
|
|
@@ -1214,7 +1218,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
1214
1218
|
hooks: [
|
|
1215
1219
|
{
|
|
1216
1220
|
type: "command",
|
|
1217
|
-
command: `node "${path9.join(packageRoot, "dist", "hooks", "prompt-submit.js")}"`
|
|
1221
|
+
command: `node "${path9.join(packageRoot, "dist", "hooks", "prompt-submit.js")}"${logSuffix}`
|
|
1218
1222
|
}
|
|
1219
1223
|
]
|
|
1220
1224
|
},
|
|
@@ -1226,7 +1230,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
1226
1230
|
hooks: [
|
|
1227
1231
|
{
|
|
1228
1232
|
type: "command",
|
|
1229
|
-
command: `node "${path9.join(packageRoot, "dist", "hooks", "exe-heartbeat-hook.js")}"`,
|
|
1233
|
+
command: `node "${path9.join(packageRoot, "dist", "hooks", "exe-heartbeat-hook.js")}"${logSuffix}`,
|
|
1230
1234
|
timeout: 5e3
|
|
1231
1235
|
}
|
|
1232
1236
|
]
|
|
@@ -1239,7 +1243,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
1239
1243
|
hooks: [
|
|
1240
1244
|
{
|
|
1241
1245
|
type: "command",
|
|
1242
|
-
command: `node "${path9.join(packageRoot, "dist", "hooks", "stop.js")}"`
|
|
1246
|
+
command: `node "${path9.join(packageRoot, "dist", "hooks", "stop.js")}"${logSuffix}`
|
|
1243
1247
|
}
|
|
1244
1248
|
]
|
|
1245
1249
|
},
|
|
@@ -1252,7 +1256,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
1252
1256
|
hooks: [
|
|
1253
1257
|
{
|
|
1254
1258
|
type: "command",
|
|
1255
|
-
command: `node "${path9.join(packageRoot, "dist", "hooks", "pre-tool-use.js")}"`
|
|
1259
|
+
command: `node "${path9.join(packageRoot, "dist", "hooks", "pre-tool-use.js")}"${logSuffix}`
|
|
1256
1260
|
}
|
|
1257
1261
|
]
|
|
1258
1262
|
},
|
|
@@ -1264,7 +1268,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
1264
1268
|
hooks: [
|
|
1265
1269
|
{
|
|
1266
1270
|
type: "command",
|
|
1267
|
-
command: `node "${path9.join(packageRoot, "dist", "hooks", "subagent-stop.js")}"`
|
|
1271
|
+
command: `node "${path9.join(packageRoot, "dist", "hooks", "subagent-stop.js")}"${logSuffix}`
|
|
1268
1272
|
}
|
|
1269
1273
|
]
|
|
1270
1274
|
},
|
|
@@ -1276,7 +1280,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
1276
1280
|
hooks: [
|
|
1277
1281
|
{
|
|
1278
1282
|
type: "command",
|
|
1279
|
-
command: `node "${path9.join(packageRoot, "dist", "hooks", "pre-compact.js")}"`,
|
|
1283
|
+
command: `node "${path9.join(packageRoot, "dist", "hooks", "pre-compact.js")}"${logSuffix}`,
|
|
1280
1284
|
timeout: 1e4
|
|
1281
1285
|
}
|
|
1282
1286
|
]
|
|
@@ -1289,7 +1293,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
1289
1293
|
hooks: [
|
|
1290
1294
|
{
|
|
1291
1295
|
type: "command",
|
|
1292
|
-
command: `node "${path9.join(packageRoot, "dist", "hooks", "session-end.js")}"`
|
|
1296
|
+
command: `node "${path9.join(packageRoot, "dist", "hooks", "session-end.js")}"${logSuffix}`
|
|
1293
1297
|
}
|
|
1294
1298
|
]
|
|
1295
1299
|
},
|
|
@@ -1301,7 +1305,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
1301
1305
|
hooks: [
|
|
1302
1306
|
{
|
|
1303
1307
|
type: "command",
|
|
1304
|
-
command: `node "${path9.join(packageRoot, "dist", "hooks", "notification.js")}"`
|
|
1308
|
+
command: `node "${path9.join(packageRoot, "dist", "hooks", "notification.js")}"${logSuffix}`
|
|
1305
1309
|
}
|
|
1306
1310
|
]
|
|
1307
1311
|
},
|
|
@@ -1313,7 +1317,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
1313
1317
|
hooks: [
|
|
1314
1318
|
{
|
|
1315
1319
|
type: "command",
|
|
1316
|
-
command: `node "${path9.join(packageRoot, "dist", "hooks", "post-compact.js")}"`,
|
|
1320
|
+
command: `node "${path9.join(packageRoot, "dist", "hooks", "post-compact.js")}"${logSuffix}`,
|
|
1317
1321
|
timeout: 1e4
|
|
1318
1322
|
}
|
|
1319
1323
|
]
|
|
@@ -1326,7 +1330,7 @@ async function mergeHooks(packageRoot, homeDir = os5.homedir()) {
|
|
|
1326
1330
|
hooks: [
|
|
1327
1331
|
{
|
|
1328
1332
|
type: "command",
|
|
1329
|
-
command: `node "${path9.join(packageRoot, "dist", "hooks", "instructions-loaded.js")}"`
|
|
1333
|
+
command: `node "${path9.join(packageRoot, "dist", "hooks", "instructions-loaded.js")}"${logSuffix}`
|
|
1330
1334
|
}
|
|
1331
1335
|
]
|
|
1332
1336
|
},
|
|
@@ -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
|
};
|
|
@@ -3428,6 +3434,14 @@ var init_agent_config = __esm({
|
|
|
3428
3434
|
});
|
|
3429
3435
|
|
|
3430
3436
|
// src/lib/intercom-queue.ts
|
|
3437
|
+
var intercom_queue_exports = {};
|
|
3438
|
+
__export(intercom_queue_exports, {
|
|
3439
|
+
clearQueueForAgent: () => clearQueueForAgent,
|
|
3440
|
+
drainForSession: () => drainForSession,
|
|
3441
|
+
drainQueue: () => drainQueue,
|
|
3442
|
+
queueIntercom: () => queueIntercom,
|
|
3443
|
+
readQueue: () => readQueue
|
|
3444
|
+
});
|
|
3431
3445
|
import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, renameSync as renameSync3, existsSync as existsSync8, mkdirSync as mkdirSync4 } from "fs";
|
|
3432
3446
|
import path8 from "path";
|
|
3433
3447
|
import os6 from "os";
|
|
@@ -3466,11 +3480,80 @@ function queueIntercom(targetSession, reason) {
|
|
|
3466
3480
|
}
|
|
3467
3481
|
writeQueue(queue);
|
|
3468
3482
|
}
|
|
3469
|
-
|
|
3483
|
+
function drainQueue(isSessionBusy2, sendKeys) {
|
|
3484
|
+
const queue = readQueue();
|
|
3485
|
+
if (queue.length === 0) return { drained: 0, failed: 0 };
|
|
3486
|
+
const remaining = [];
|
|
3487
|
+
let drained = 0;
|
|
3488
|
+
let failed = 0;
|
|
3489
|
+
for (const item of queue) {
|
|
3490
|
+
const age = Date.now() - new Date(item.queuedAt).getTime();
|
|
3491
|
+
if (age > TTL_MS) {
|
|
3492
|
+
logQueue(`EXPIRED \u2192 ${item.targetSession} (${Math.round(age / 6e4)}min old, reason: ${item.reason})`);
|
|
3493
|
+
failed++;
|
|
3494
|
+
continue;
|
|
3495
|
+
}
|
|
3496
|
+
try {
|
|
3497
|
+
if (!isSessionBusy2(item.targetSession)) {
|
|
3498
|
+
const success = sendKeys(item.targetSession);
|
|
3499
|
+
if (success) {
|
|
3500
|
+
logQueue(`DRAINED \u2192 ${item.targetSession} (after ${item.attempts} retries)`);
|
|
3501
|
+
drained++;
|
|
3502
|
+
continue;
|
|
3503
|
+
}
|
|
3504
|
+
}
|
|
3505
|
+
} catch {
|
|
3506
|
+
}
|
|
3507
|
+
item.attempts++;
|
|
3508
|
+
if (item.attempts >= MAX_RETRIES2) {
|
|
3509
|
+
logQueue(`FAILED \u2192 ${item.targetSession} (${MAX_RETRIES2} retries exhausted, reason: ${item.reason})`);
|
|
3510
|
+
failed++;
|
|
3511
|
+
continue;
|
|
3512
|
+
}
|
|
3513
|
+
remaining.push(item);
|
|
3514
|
+
}
|
|
3515
|
+
writeQueue(remaining);
|
|
3516
|
+
return { drained, failed };
|
|
3517
|
+
}
|
|
3518
|
+
function drainForSession(targetSession, sendKeys) {
|
|
3519
|
+
const queue = readQueue();
|
|
3520
|
+
const match = queue.findIndex((q) => q.targetSession === targetSession);
|
|
3521
|
+
if (match < 0) return false;
|
|
3522
|
+
const success = sendKeys(targetSession);
|
|
3523
|
+
if (success) {
|
|
3524
|
+
queue.splice(match, 1);
|
|
3525
|
+
writeQueue(queue);
|
|
3526
|
+
logQueue(`DRAINED \u2192 ${targetSession} (prompt-submit trigger)`);
|
|
3527
|
+
return true;
|
|
3528
|
+
}
|
|
3529
|
+
return false;
|
|
3530
|
+
}
|
|
3531
|
+
function clearQueueForAgent(agentName2) {
|
|
3532
|
+
const queue = readQueue();
|
|
3533
|
+
const before = queue.length;
|
|
3534
|
+
const filtered = queue.filter((q) => !q.targetSession.startsWith(`${agentName2}-`));
|
|
3535
|
+
if (filtered.length < before) {
|
|
3536
|
+
writeQueue(filtered);
|
|
3537
|
+
logQueue(`CLEARED ${before - filtered.length} stale item(s) for ${agentName2}`);
|
|
3538
|
+
}
|
|
3539
|
+
}
|
|
3540
|
+
function logQueue(msg) {
|
|
3541
|
+
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] [queue] ${msg}
|
|
3542
|
+
`;
|
|
3543
|
+
process.stderr.write(`[intercom-queue] ${msg}
|
|
3544
|
+
`);
|
|
3545
|
+
try {
|
|
3546
|
+
const { appendFileSync: appendFileSync3 } = __require("fs");
|
|
3547
|
+
appendFileSync3(INTERCOM_LOG, line);
|
|
3548
|
+
} catch {
|
|
3549
|
+
}
|
|
3550
|
+
}
|
|
3551
|
+
var QUEUE_PATH, MAX_RETRIES2, TTL_MS, INTERCOM_LOG;
|
|
3470
3552
|
var init_intercom_queue = __esm({
|
|
3471
3553
|
"src/lib/intercom-queue.ts"() {
|
|
3472
3554
|
"use strict";
|
|
3473
3555
|
QUEUE_PATH = path8.join(os6.homedir(), ".exe-os", "intercom-queue.json");
|
|
3556
|
+
MAX_RETRIES2 = 5;
|
|
3474
3557
|
TTL_MS = 60 * 60 * 1e3;
|
|
3475
3558
|
INTERCOM_LOG = path8.join(os6.homedir(), ".exe-os", "intercom.log");
|
|
3476
3559
|
}
|
|
@@ -4171,6 +4254,13 @@ ${input.result}` : `\u26A0\uFE0F ${warning}`;
|
|
|
4171
4254
|
await client.execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
4172
4255
|
} catch {
|
|
4173
4256
|
}
|
|
4257
|
+
if (input.status === "done" || input.status === "cancelled") {
|
|
4258
|
+
try {
|
|
4259
|
+
const { clearQueueForAgent: clearQueueForAgent2 } = await Promise.resolve().then(() => (init_intercom_queue(), intercom_queue_exports));
|
|
4260
|
+
clearQueueForAgent2(String(row.assigned_to));
|
|
4261
|
+
} catch {
|
|
4262
|
+
}
|
|
4263
|
+
}
|
|
4174
4264
|
try {
|
|
4175
4265
|
await writeCheckpoint({
|
|
4176
4266
|
taskId,
|
package/dist/bin/exe-settings.js
CHANGED
|
@@ -342,7 +342,7 @@ var DEFAULT_RUNTIME = "claude";
|
|
|
342
342
|
var AGENT_CONFIG_PATH = path6.join(EXE_AI_DIR, "agent-config.json");
|
|
343
343
|
var KNOWN_RUNTIMES = {
|
|
344
344
|
claude: ["claude-opus-4", "claude-sonnet-4", "claude-haiku-4.5"],
|
|
345
|
-
codex: ["gpt-5.4", "gpt-5.5", "o3", "o4-mini"],
|
|
345
|
+
codex: ["gpt-5.4", "gpt-5.5", "gpt-5.3-codex-spark", "o3", "o4-mini"],
|
|
346
346
|
opencode: ["anthropic/claude-sonnet-4-6", "openai/gpt-5.4", "google/gemini-2.5-pro", "deepseek/deepseek-r3", "minimax/minimax-m2.5"]
|
|
347
347
|
};
|
|
348
348
|
var RUNTIME_LABELS = {
|