@askexenow/exe-os 0.9.211 → 0.9.214
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/exe-forget.js +1 -1
- package/dist/bin/exe-search.js +1 -1
- package/dist/{catchup-brief-FIVK6YIX.js → catchup-brief-6AD7QQZB.js} +1 -1
- package/dist/{chunk-4TQ3GE3G.js → chunk-LSARQLX3.js} +2 -2
- package/dist/{chunk-PTO7FEZG.js → chunk-NVZODD7S.js} +3 -3
- package/dist/hooks/error-recall.js +1 -1
- package/dist/hooks/manifest.json +4 -4
- package/dist/hooks/prompt-submit.js +1 -1
- package/dist/hooks/session-start.js +1 -1
- package/dist/lib/exe-daemon.js +213 -108
- package/dist/lib/hybrid-search.js +1 -1
- package/dist/mcp/register-tools.js +3 -3
- package/dist/mcp/server.js +3 -3
- package/dist/{reranker-2D2XI6KV.js → reranker-AZN6MN2N.js} +1 -1
- package/package.json +1 -1
- package/release-notes.json +54 -54
- /package/dist/{chunk-G3JAB3O5.js → chunk-UFOERR37.js} +0 -0
package/dist/bin/exe-forget.js
CHANGED
package/dist/bin/exe-search.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
import {
|
|
8
8
|
isRerankerAvailable,
|
|
9
9
|
rerankWithScores
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-UFOERR37.js";
|
|
11
11
|
import {
|
|
12
12
|
getEntityByName,
|
|
13
13
|
getEntityNeighbors,
|
|
@@ -187,7 +187,7 @@ import {
|
|
|
187
187
|
import {
|
|
188
188
|
hybridSearch,
|
|
189
189
|
recentRecords
|
|
190
|
-
} from "./chunk-
|
|
190
|
+
} from "./chunk-NVZODD7S.js";
|
|
191
191
|
import {
|
|
192
192
|
attachDocumentMetadata,
|
|
193
193
|
flushBatch,
|
|
@@ -233,7 +233,7 @@ async function hybridSearch(queryText, agentId, options) {
|
|
|
233
233
|
let rerankerAvailable = false;
|
|
234
234
|
if (process.env.EXE_IS_DAEMON === "1") {
|
|
235
235
|
try {
|
|
236
|
-
const { isRerankerAvailable } = await import("./reranker-
|
|
236
|
+
const { isRerankerAvailable } = await import("./reranker-AZN6MN2N.js");
|
|
237
237
|
rerankerAvailable = isRerankerAvailable();
|
|
238
238
|
} catch {
|
|
239
239
|
}
|
|
@@ -397,7 +397,7 @@ async function hybridSearch(queryText, agentId, options) {
|
|
|
397
397
|
try {
|
|
398
398
|
let rerankedRecords;
|
|
399
399
|
if (graphContextMap.size > 0) {
|
|
400
|
-
const { rerankWithContext } = await import("./reranker-
|
|
400
|
+
const { rerankWithContext } = await import("./reranker-AZN6MN2N.js");
|
|
401
401
|
const candidates = merged.map((m) => ({
|
|
402
402
|
text: m.raw_text,
|
|
403
403
|
context: graphContextMap.get(m.id)
|
|
@@ -405,7 +405,7 @@ async function hybridSearch(queryText, agentId, options) {
|
|
|
405
405
|
const scored = await rerankWithContext(effectiveQuery, candidates, rerankReturnLimit);
|
|
406
406
|
rerankedRecords = scored.map((s) => merged[s.index]);
|
|
407
407
|
} else {
|
|
408
|
-
const { rerank } = await import("./reranker-
|
|
408
|
+
const { rerank } = await import("./reranker-AZN6MN2N.js");
|
|
409
409
|
rerankedRecords = await rerank(effectiveQuery, merged, rerankReturnLimit);
|
|
410
410
|
}
|
|
411
411
|
if (rerankedRecords.length > 0) {
|
package/dist/hooks/manifest.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 1,
|
|
3
|
-
"generatedAt": "2026-06-
|
|
3
|
+
"generatedAt": "2026-06-04T08:59:34.433Z",
|
|
4
4
|
"hashes": {
|
|
5
5
|
"bug-report-worker.js": "0026604aac324e295b46bde719681de6800b2df144012cc2c2b349dcdbb082be",
|
|
6
6
|
"codex-stop-task-finalizer.js": "f6188b6e85f247546996d138de58cd658e40c8175511e22b1b201a1379502632",
|
|
7
7
|
"commit-complete.js": "1bc2e33e1d00daebc727c5c3e73ec8d5025ad08544e4cde2848d035ee5e21352",
|
|
8
|
-
"error-recall.js": "
|
|
8
|
+
"error-recall.js": "b21822616521e68d752ac273a70c9e505fb3636379c31e66ab8609a95a87b02d",
|
|
9
9
|
"exe-heartbeat-hook.js": "10688da0e9c9972fff33c3bb33923df4e743df9d48e744b96d227836c6270c4c",
|
|
10
10
|
"ingest-worker.js": "df9693b3a590f313868019ab91dd2f7298750492f792c2b8055c4ad68a1c9d67",
|
|
11
11
|
"ingest.js": "5af6b8a3a4e30c282d27a17a82d55337b7102d84e796198c6390315a39755404",
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
"post-tool-combined.js": "19469891de74713eab9d5d9273c130d5fe5ad95a2b99618ac4bb9d60120b5c71",
|
|
16
16
|
"pre-compact.js": "01761e0a404d9cc5fa2ef1788829bd62bbd426395703491906f4b255f32976f4",
|
|
17
17
|
"pre-tool-use.js": "c2e10257f91ba7a759aa41db28e374b20780d7376eb17d3d167c3e7cbf0a226d",
|
|
18
|
-
"prompt-submit.js": "
|
|
18
|
+
"prompt-submit.js": "5722df8ad7789f51bd37dbbd152209e2330952680c686460d393875c5b549072",
|
|
19
19
|
"session-end.js": "2cfe3cbc196cb11bbe68ae23d128eacc99d1dbbbdd7b3698189922bf5645a71a",
|
|
20
|
-
"session-start.js": "
|
|
20
|
+
"session-start.js": "0416fc6b642529eb0125b02b892cb0014010294baaf5e864819a4fa745fddfa8",
|
|
21
21
|
"stop.js": "9c784c10f1a8eddfec9f5dc66463d67a5b09eb21f340e0d92157e9e7befb367b",
|
|
22
22
|
"subagent-stop.js": "a3d3a01d99dcdcebd5763e5974ce912d69c5f07ba254eb01c2f8c587903ec88c",
|
|
23
23
|
"summary-worker.js": "f29f29e148ea34b38eab656131b2045e0e4020b526ab8bada9c693eb19dc690e"
|
|
@@ -158,7 +158,7 @@ You are **${ag.agentId}** (${ag.agentRole}). Daemon is degraded \u2014 memory un
|
|
|
158
158
|
query = `last actions on ${projectName}`;
|
|
159
159
|
header = "## Resuming Session\nHere's where you left off:";
|
|
160
160
|
try {
|
|
161
|
-
const { buildCatchupBrief } = await import("../catchup-brief-
|
|
161
|
+
const { buildCatchupBrief } = await import("../catchup-brief-6AD7QQZB.js");
|
|
162
162
|
const brief = await buildCatchupBrief(
|
|
163
163
|
agentId,
|
|
164
164
|
projectName,
|
package/dist/lib/exe-daemon.js
CHANGED
|
@@ -407,12 +407,15 @@ var MAX_QUEUE_SIZE = 5e3;
|
|
|
407
407
|
var _tmuxSessionCache = [];
|
|
408
408
|
var _tmuxCacheTimestamp = 0;
|
|
409
409
|
var TMUX_CACHE_TTL_MS = 5e3;
|
|
410
|
-
function
|
|
410
|
+
async function getTmuxSessionsAsync() {
|
|
411
411
|
const now = Date.now();
|
|
412
412
|
if (now - _tmuxCacheTimestamp < TMUX_CACHE_TTL_MS) return _tmuxSessionCache;
|
|
413
413
|
try {
|
|
414
|
-
const
|
|
415
|
-
|
|
414
|
+
const { stdout } = await execFileAsync("tmux", ["list-sessions", "-F", "#{session_name}"], {
|
|
415
|
+
encoding: "utf8",
|
|
416
|
+
timeout: 3e3
|
|
417
|
+
});
|
|
418
|
+
_tmuxSessionCache = String(stdout ?? "").trim().split("\n").filter(Boolean);
|
|
416
419
|
_tmuxCacheTimestamp = now;
|
|
417
420
|
} catch {
|
|
418
421
|
_tmuxSessionCache = [];
|
|
@@ -451,6 +454,48 @@ async function batchCapturePanes(sessions, lines = 20) {
|
|
|
451
454
|
}
|
|
452
455
|
return results;
|
|
453
456
|
}
|
|
457
|
+
async function tmuxPaneAliveAsync(session) {
|
|
458
|
+
try {
|
|
459
|
+
const { stdout } = await execFileAsync(
|
|
460
|
+
"tmux",
|
|
461
|
+
["list-panes", "-t", session, "-F", "#{pane_dead}"],
|
|
462
|
+
{ encoding: "utf8", timeout: 3e3 }
|
|
463
|
+
);
|
|
464
|
+
return String(stdout ?? "").trim() !== "1";
|
|
465
|
+
} catch {
|
|
466
|
+
return false;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
async function batchPaneAlive(sessions) {
|
|
470
|
+
const alive = /* @__PURE__ */ new Set();
|
|
471
|
+
const CONCURRENCY = 4;
|
|
472
|
+
for (let i = 0; i < sessions.length; i += CONCURRENCY) {
|
|
473
|
+
const batch = sessions.slice(i, i + CONCURRENCY);
|
|
474
|
+
const settled = await Promise.allSettled(
|
|
475
|
+
batch.map(async (session) => ({ session, alive: await tmuxPaneAliveAsync(session) }))
|
|
476
|
+
);
|
|
477
|
+
for (const result of settled) {
|
|
478
|
+
if (result.status === "fulfilled" && result.value.alive) {
|
|
479
|
+
alive.add(result.value.session);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
return alive;
|
|
484
|
+
}
|
|
485
|
+
var CACHED_SESSION_BUSY_PATTERN = /[✻✽✶✳·].*…|Running…|• Working|• Ran |• Explored|• Called|esc to interrupt/;
|
|
486
|
+
function getCachedSessionState(sessionName, paneCache, aliveSessions) {
|
|
487
|
+
if (!aliveSessions.has(sessionName)) return "offline";
|
|
488
|
+
const pane = paneCache.get(sessionName);
|
|
489
|
+
if (!pane) return "offline";
|
|
490
|
+
if (!pane.includes("\u276F") && !pane.includes("Claude Code") && !CACHED_SESSION_BUSY_PATTERN.test(pane) && !/Running…/.test(pane)) {
|
|
491
|
+
if (/\$\s*$/.test(pane) || /% $/.test(pane.trimEnd())) {
|
|
492
|
+
return "no_claude";
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
if (/Running…/.test(pane)) return "tool";
|
|
496
|
+
if (CACHED_SESSION_BUSY_PATTERN.test(pane)) return "thinking";
|
|
497
|
+
return "idle";
|
|
498
|
+
}
|
|
454
499
|
setInterval(() => {
|
|
455
500
|
const now = Date.now();
|
|
456
501
|
for (const [key, entry] of _paneCacheMap) {
|
|
@@ -480,6 +525,35 @@ var _idleTimer = null;
|
|
|
480
525
|
var _requestsServed = 0;
|
|
481
526
|
var _droppedRequests = 0;
|
|
482
527
|
var _startedAt2 = Date.now();
|
|
528
|
+
var TIMER_TRACE_BOOT_WINDOW_MS = Number(process.env.EXE_TIMER_TRACE_BOOT_WINDOW_MS) || 10 * 60 * 1e3;
|
|
529
|
+
var TIMER_TRACE_SLOW_MS = Number(process.env.EXE_TIMER_TRACE_SLOW_MS) || 500;
|
|
530
|
+
function shouldTraceDaemonTimer(durationMs = 0) {
|
|
531
|
+
return Date.now() - _startedAt2 < TIMER_TRACE_BOOT_WINDOW_MS || durationMs >= TIMER_TRACE_SLOW_MS;
|
|
532
|
+
}
|
|
533
|
+
async function traceDaemonTimer(name, fn) {
|
|
534
|
+
const startedAt = Date.now();
|
|
535
|
+
const traceStart = shouldTraceDaemonTimer();
|
|
536
|
+
if (traceStart) {
|
|
537
|
+
process.stderr.write(`[exed] Timer start: ${name}
|
|
538
|
+
`);
|
|
539
|
+
}
|
|
540
|
+
try {
|
|
541
|
+
return await fn();
|
|
542
|
+
} finally {
|
|
543
|
+
const durationMs = Date.now() - startedAt;
|
|
544
|
+
if (shouldTraceDaemonTimer(durationMs)) {
|
|
545
|
+
const msg = `[exed] Timer duration: ${name} ${durationMs}ms`;
|
|
546
|
+
process.stderr.write(`${msg}
|
|
547
|
+
`);
|
|
548
|
+
logDaemonHealth({
|
|
549
|
+
event: "process_stats",
|
|
550
|
+
pid: process.pid,
|
|
551
|
+
message: msg,
|
|
552
|
+
data: { type: "timer_duration", timer: name, durationMs, uptimeMs: Date.now() - _startedAt2 }
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
483
557
|
function enqueue(queue, entry) {
|
|
484
558
|
if (queue.length >= MAX_QUEUE_SIZE) {
|
|
485
559
|
queue.shift();
|
|
@@ -1200,7 +1274,7 @@ async function _writeMemoryRecordInner(entry) {
|
|
|
1200
1274
|
}
|
|
1201
1275
|
var MEMORY_DRAIN_INTERVAL_MS = 30 * 1e3;
|
|
1202
1276
|
function startMemoryQueueDrain() {
|
|
1203
|
-
const drain = async () => {
|
|
1277
|
+
const drain = async () => traceDaemonTimer("memory_queue_drain", async () => {
|
|
1204
1278
|
fired("memory_queue_drain");
|
|
1205
1279
|
if (!await ensureStoreForPolling()) return;
|
|
1206
1280
|
try {
|
|
@@ -1237,7 +1311,7 @@ function startMemoryQueueDrain() {
|
|
|
1237
1311
|
`
|
|
1238
1312
|
);
|
|
1239
1313
|
}
|
|
1240
|
-
};
|
|
1314
|
+
});
|
|
1241
1315
|
void drain();
|
|
1242
1316
|
const timer = setInterval(() => void drain(), MEMORY_DRAIN_INTERVAL_MS);
|
|
1243
1317
|
timer.unref();
|
|
@@ -1246,7 +1320,7 @@ function startMemoryQueueDrain() {
|
|
|
1246
1320
|
}
|
|
1247
1321
|
var MESSAGE_DRAIN_INTERVAL_MS = 3e4;
|
|
1248
1322
|
function startMessageQueueDrain() {
|
|
1249
|
-
const drain = async () => {
|
|
1323
|
+
const drain = async () => traceDaemonTimer("message_queue_drain", async () => {
|
|
1250
1324
|
fired("message_queue_drain");
|
|
1251
1325
|
if (!await ensureStoreForPolling()) return;
|
|
1252
1326
|
try {
|
|
@@ -1290,7 +1364,7 @@ function startMessageQueueDrain() {
|
|
|
1290
1364
|
`
|
|
1291
1365
|
);
|
|
1292
1366
|
}
|
|
1293
|
-
};
|
|
1367
|
+
});
|
|
1294
1368
|
void drain();
|
|
1295
1369
|
const timer = setInterval(() => void drain(), MESSAGE_DRAIN_INTERVAL_MS);
|
|
1296
1370
|
timer.unref();
|
|
@@ -2252,7 +2326,7 @@ async function startReviewPolling() {
|
|
|
2252
2326
|
};
|
|
2253
2327
|
const { pollReviewNudge, createReviewNudgeRealDeps, loadNudgeState } = await import("../daemon-orchestration-QVJ26DDN.js");
|
|
2254
2328
|
const nudgeState = loadNudgeState();
|
|
2255
|
-
const tick = async () => {
|
|
2329
|
+
const tick = async () => traceDaemonTimer("review_polling", async () => {
|
|
2256
2330
|
fired("review_polling");
|
|
2257
2331
|
if (!await ensureStoreForPolling()) return;
|
|
2258
2332
|
try {
|
|
@@ -2279,7 +2353,7 @@ async function startReviewPolling() {
|
|
|
2279
2353
|
process.stderr.write(`[exed] Review poll error: ${err instanceof Error ? err.message : String(err)}
|
|
2280
2354
|
`);
|
|
2281
2355
|
}
|
|
2282
|
-
};
|
|
2356
|
+
});
|
|
2283
2357
|
const timer = setInterval(() => void tick(), REVIEW_POLL_INTERVAL_MS);
|
|
2284
2358
|
timer.unref();
|
|
2285
2359
|
process.stderr.write(`[exed] Review polling started (every ${REVIEW_POLL_INTERVAL_MS / 6e4}m)
|
|
@@ -2287,7 +2361,7 @@ async function startReviewPolling() {
|
|
|
2287
2361
|
}
|
|
2288
2362
|
var SESSION_TTL_INTERVAL_MS = 5 * 60 * 1e3;
|
|
2289
2363
|
function startSessionTTL() {
|
|
2290
|
-
const tick = async () => {
|
|
2364
|
+
const tick = async () => traceDaemonTimer("session_ttl", async () => {
|
|
2291
2365
|
fired("session_ttl");
|
|
2292
2366
|
if (!await ensureStoreForPolling()) return;
|
|
2293
2367
|
try {
|
|
@@ -2300,7 +2374,7 @@ function startSessionTTL() {
|
|
|
2300
2374
|
process.stderr.write(`[exed] Session TTL error: ${err instanceof Error ? err.message : String(err)}
|
|
2301
2375
|
`);
|
|
2302
2376
|
}
|
|
2303
|
-
};
|
|
2377
|
+
});
|
|
2304
2378
|
const timer = setInterval(() => void tick(), SESSION_TTL_INTERVAL_MS);
|
|
2305
2379
|
timer.unref();
|
|
2306
2380
|
process.stderr.write(`[exed] Session TTL started (every ${SESSION_TTL_INTERVAL_MS / 6e4}m)
|
|
@@ -2310,7 +2384,7 @@ var COO_RESTART_COOLDOWN_MS = 5 * 6e4;
|
|
|
2310
2384
|
var IDLE_KILL_INTERVAL_MS = 30 * 1e3;
|
|
2311
2385
|
var _idleTickCounts = /* @__PURE__ */ new Map();
|
|
2312
2386
|
function startIdleKill() {
|
|
2313
|
-
const tick = async () => {
|
|
2387
|
+
const tick = async () => traceDaemonTimer("idle_kill", async () => {
|
|
2314
2388
|
fired("idle_kill");
|
|
2315
2389
|
if (!await ensureStoreForPolling()) return;
|
|
2316
2390
|
try {
|
|
@@ -2321,7 +2395,7 @@ function startIdleKill() {
|
|
|
2321
2395
|
const agentId = file.replace(".terminate", "");
|
|
2322
2396
|
const signalPath = path3.join(signalDir, file);
|
|
2323
2397
|
try {
|
|
2324
|
-
const sessions =
|
|
2398
|
+
const sessions = await getTmuxSessionsAsync();
|
|
2325
2399
|
const match = sessions.find((s) => s.startsWith(`${agentId}-`) || s.startsWith(`${agentId}2-`) || s.startsWith(`${agentId}3-`));
|
|
2326
2400
|
if (match) {
|
|
2327
2401
|
execSyncNode(`tmux kill-session -t ${match} 2>/dev/null`, { timeout: 2e3 });
|
|
@@ -2342,10 +2416,20 @@ function startIdleKill() {
|
|
|
2342
2416
|
if (!cfg) return;
|
|
2343
2417
|
const { getClient } = await import("./database.js");
|
|
2344
2418
|
const { pollIdleKill, createIdleKillRealDeps } = await import("../daemon-orchestration-QVJ26DDN.js");
|
|
2345
|
-
const
|
|
2419
|
+
const liveSessions = (await getTmuxSessionsAsync()).filter((s) => s.includes("-"));
|
|
2420
|
+
const [paneCache, aliveSessions] = await Promise.all([
|
|
2421
|
+
batchCapturePanes(liveSessions, 5),
|
|
2422
|
+
batchPaneAlive(liveSessions)
|
|
2423
|
+
]);
|
|
2424
|
+
const realDeps = createIdleKillRealDeps(
|
|
2346
2425
|
getClient,
|
|
2347
2426
|
cfg.sessionLifecycle.idleKillIntercomAckWindowMs
|
|
2348
2427
|
);
|
|
2428
|
+
const deps = {
|
|
2429
|
+
...realDeps,
|
|
2430
|
+
listTmuxSessions: () => liveSessions,
|
|
2431
|
+
getSessionState: (sessionName) => getCachedSessionState(sessionName, paneCache, aliveSessions)
|
|
2432
|
+
};
|
|
2349
2433
|
const killed = await pollIdleKill(deps, _idleTickCounts, {
|
|
2350
2434
|
ticksRequired: cfg.sessionLifecycle.idleKillTicksRequired,
|
|
2351
2435
|
enabled: cfg.sessionLifecycle.idleKillEnabled
|
|
@@ -2359,7 +2443,7 @@ function startIdleKill() {
|
|
|
2359
2443
|
process.stderr.write(`[exed] Idle kill error: ${err instanceof Error ? err.message : String(err)}
|
|
2360
2444
|
`);
|
|
2361
2445
|
}
|
|
2362
|
-
};
|
|
2446
|
+
});
|
|
2363
2447
|
const timer = setInterval(() => void tick(), IDLE_KILL_INTERVAL_MS);
|
|
2364
2448
|
timer.unref();
|
|
2365
2449
|
process.stderr.write(`[exed] Idle kill started (every ${IDLE_KILL_INTERVAL_MS / 1e3}s)
|
|
@@ -2370,7 +2454,7 @@ function startConsolidation() {
|
|
|
2370
2454
|
const { loadConfig: lc } = await import("./config.js");
|
|
2371
2455
|
return lc();
|
|
2372
2456
|
};
|
|
2373
|
-
const tick = async () => {
|
|
2457
|
+
const tick = async () => traceDaemonTimer("consolidation_tick", async () => {
|
|
2374
2458
|
fired("consolidation");
|
|
2375
2459
|
try {
|
|
2376
2460
|
const config = await loadConfig();
|
|
@@ -2421,8 +2505,9 @@ function startConsolidation() {
|
|
|
2421
2505
|
process.stderr.write(`[exed] Consolidation error: ${err instanceof Error ? err.message : String(err)}
|
|
2422
2506
|
`);
|
|
2423
2507
|
}
|
|
2424
|
-
};
|
|
2425
|
-
|
|
2508
|
+
});
|
|
2509
|
+
void traceDaemonTimer("consolidation_init", async () => {
|
|
2510
|
+
const config = await loadConfig();
|
|
2426
2511
|
const intervalMs = config.consolidationIntervalMs;
|
|
2427
2512
|
const timer = setInterval(() => void tick(), intervalMs);
|
|
2428
2513
|
timer.unref();
|
|
@@ -2607,54 +2692,37 @@ function startGraphExtraction() {
|
|
|
2607
2692
|
`);
|
|
2608
2693
|
}
|
|
2609
2694
|
var AGENT_STATS_INTERVAL_MS = 60 * 1e3;
|
|
2610
|
-
var AGENT_STATS_SPEND_INTERVAL_MS = 10 * 60 * 1e3;
|
|
2611
2695
|
var AGENT_STATS_PATH = path3.join(EXE_AI_DIR, "agent-stats.json");
|
|
2612
2696
|
var _agentStatsInFlight = false;
|
|
2613
|
-
var
|
|
2614
|
-
var _cachedSpend = null;
|
|
2697
|
+
var _cachedAgentData = null;
|
|
2615
2698
|
async function writeAgentStats() {
|
|
2616
2699
|
fired("agent_stats");
|
|
2617
2700
|
if (_agentStatsInFlight) return;
|
|
2701
|
+
if (!_cachedAgentData) return;
|
|
2618
2702
|
_agentStatsInFlight = true;
|
|
2619
|
-
const started = Date.now();
|
|
2620
2703
|
try {
|
|
2621
|
-
if (!await ensureStoreForPolling()) return;
|
|
2622
2704
|
acted("agent_stats");
|
|
2623
|
-
const
|
|
2624
|
-
const
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
SUM(CASE WHEN timestamp > datetime('now', '-1 day') THEN 1 ELSE 0 END) as growth_24h,
|
|
2629
|
-
SUM(CASE WHEN timestamp > datetime('now', '-7 days') THEN 1 ELSE 0 END) as growth_7d,
|
|
2630
|
-
SUM(CASE WHEN timestamp > datetime('now', '-30 days') THEN 1 ELSE 0 END) as growth_30d
|
|
2631
|
-
FROM memories
|
|
2632
|
-
WHERE agent_id != 'default'
|
|
2633
|
-
GROUP BY agent_id
|
|
2634
|
-
ORDER BY total DESC`,
|
|
2635
|
-
args: []
|
|
2636
|
-
});
|
|
2637
|
-
const agentsBase = result.rows.map((row) => {
|
|
2638
|
-
const id = String(row.agent_id);
|
|
2639
|
-
const s24 = _cachedSpend?.spend24h.get(id);
|
|
2640
|
-
const s7 = _cachedSpend?.spend7d.get(id);
|
|
2641
|
-
const s30 = _cachedSpend?.spend30d.get(id);
|
|
2705
|
+
const cache = _cachedAgentData;
|
|
2706
|
+
const agents = [...cache.counts.entries()].map(([id, c]) => {
|
|
2707
|
+
const s24 = cache.spend24h.get(id);
|
|
2708
|
+
const s7 = cache.spend7d.get(id);
|
|
2709
|
+
const s30 = cache.spend30d.get(id);
|
|
2642
2710
|
return {
|
|
2643
2711
|
id,
|
|
2644
|
-
total:
|
|
2645
|
-
growth24h:
|
|
2646
|
-
growth7d:
|
|
2647
|
-
growth30d:
|
|
2712
|
+
total: c.total,
|
|
2713
|
+
growth24h: c.growth24h,
|
|
2714
|
+
growth7d: c.growth7d,
|
|
2715
|
+
growth30d: c.growth30d,
|
|
2648
2716
|
spend24h: s24 ?? { inputTokens: 0, outputTokens: 0, costUSD: 0, sessions: 0 },
|
|
2649
2717
|
spend7d: s7 ?? { inputTokens: 0, outputTokens: 0, costUSD: 0, sessions: 0 },
|
|
2650
2718
|
spend30d: s30 ?? { inputTokens: 0, outputTokens: 0, costUSD: 0, sessions: 0 }
|
|
2651
2719
|
};
|
|
2652
2720
|
});
|
|
2653
|
-
const
|
|
2721
|
+
const cacheAge = Math.round((Date.now() - cache.refreshedAt) / 1e3);
|
|
2654
2722
|
const stats = {
|
|
2655
2723
|
generated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2656
|
-
|
|
2657
|
-
agents
|
|
2724
|
+
dataStatus: cacheAge < AGENT_STATS_REFRESH_INTERVAL_MS / 1e3 ? "fresh" : "stale",
|
|
2725
|
+
agents,
|
|
2658
2726
|
daemon: {
|
|
2659
2727
|
uptime: Math.floor((Date.now() - _startedAt2) / 1e3),
|
|
2660
2728
|
pid: process.pid
|
|
@@ -2666,55 +2734,82 @@ async function writeAgentStats() {
|
|
|
2666
2734
|
`);
|
|
2667
2735
|
} finally {
|
|
2668
2736
|
_agentStatsInFlight = false;
|
|
2669
|
-
const durationMs = Date.now() - started;
|
|
2670
|
-
if (durationMs > 3e3) {
|
|
2671
|
-
process.stderr.write(`[exed] Agent stats slow path: ${durationMs}ms
|
|
2672
|
-
`);
|
|
2673
|
-
logDaemonHealth({
|
|
2674
|
-
event: "process_stats",
|
|
2675
|
-
pid: process.pid,
|
|
2676
|
-
message: `agent_stats took ${durationMs}ms`,
|
|
2677
|
-
data: { type: "timer_slow", timer: "agent_stats", durationMs }
|
|
2678
|
-
});
|
|
2679
|
-
}
|
|
2680
2737
|
}
|
|
2681
2738
|
}
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2739
|
+
var AGENT_STATS_REFRESH_INTERVAL_MS = 10 * 60 * 1e3;
|
|
2740
|
+
var _agentRefreshInFlight = false;
|
|
2741
|
+
async function refreshAgentData() {
|
|
2742
|
+
if (_agentRefreshInFlight) return;
|
|
2743
|
+
_agentRefreshInFlight = true;
|
|
2685
2744
|
const started = Date.now();
|
|
2686
2745
|
try {
|
|
2687
|
-
|
|
2688
|
-
const
|
|
2689
|
-
const
|
|
2690
|
-
const
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2746
|
+
if (!await ensureStoreForPolling()) return;
|
|
2747
|
+
const { getClient } = await import("./database.js");
|
|
2748
|
+
const client = getClient();
|
|
2749
|
+
const result = await client.execute({
|
|
2750
|
+
sql: `SELECT agent_id,
|
|
2751
|
+
COUNT(*) as total,
|
|
2752
|
+
SUM(CASE WHEN timestamp > datetime('now', '-1 day') THEN 1 ELSE 0 END) as growth_24h,
|
|
2753
|
+
SUM(CASE WHEN timestamp > datetime('now', '-7 days') THEN 1 ELSE 0 END) as growth_7d,
|
|
2754
|
+
SUM(CASE WHEN timestamp > datetime('now', '-30 days') THEN 1 ELSE 0 END) as growth_30d
|
|
2755
|
+
FROM memories
|
|
2756
|
+
WHERE agent_id != 'default'
|
|
2757
|
+
GROUP BY agent_id
|
|
2758
|
+
ORDER BY total DESC`,
|
|
2759
|
+
args: []
|
|
2760
|
+
});
|
|
2761
|
+
const counts = /* @__PURE__ */ new Map();
|
|
2762
|
+
for (const row of result.rows) {
|
|
2763
|
+
counts.set(String(row.agent_id), {
|
|
2764
|
+
total: Number(row.total),
|
|
2765
|
+
growth24h: Number(row.growth_24h),
|
|
2766
|
+
growth7d: Number(row.growth_7d),
|
|
2767
|
+
growth30d: Number(row.growth_30d)
|
|
2768
|
+
});
|
|
2769
|
+
}
|
|
2770
|
+
let spend24h = /* @__PURE__ */ new Map();
|
|
2771
|
+
let spend7d = /* @__PURE__ */ new Map();
|
|
2772
|
+
let spend30d = /* @__PURE__ */ new Map();
|
|
2773
|
+
try {
|
|
2774
|
+
const { getAgentSpend } = await import("./token-spend.js");
|
|
2775
|
+
const r24 = await getAgentSpend("24h");
|
|
2776
|
+
spend24h = new Map(r24.map((s) => [s.agentId, { inputTokens: s.inputTokens, outputTokens: s.outputTokens, costUSD: s.costUSD, sessions: s.sessions }]));
|
|
2777
|
+
const r7 = await getAgentSpend("7d");
|
|
2778
|
+
spend7d = new Map(r7.map((s) => [s.agentId, { inputTokens: s.inputTokens, outputTokens: s.outputTokens, costUSD: s.costUSD, sessions: s.sessions }]));
|
|
2779
|
+
const r30 = await getAgentSpend("30d");
|
|
2780
|
+
spend30d = new Map(r30.map((s) => [s.agentId, { inputTokens: s.inputTokens, outputTokens: s.outputTokens, costUSD: s.costUSD, sessions: s.sessions }]));
|
|
2781
|
+
} catch (err) {
|
|
2782
|
+
process.stderr.write(`[exed] Agent spend refresh error: ${err instanceof Error ? err.message : String(err)}
|
|
2783
|
+
`);
|
|
2784
|
+
}
|
|
2785
|
+
_cachedAgentData = { counts, spend24h, spend7d, spend30d, refreshedAt: Date.now() };
|
|
2697
2786
|
const durationMs = Date.now() - started;
|
|
2698
2787
|
if (durationMs > 5e3) {
|
|
2699
|
-
process.stderr.write(`[exed] Agent
|
|
2788
|
+
process.stderr.write(`[exed] Agent data refresh: ${durationMs}ms (${counts.size} agents)
|
|
2700
2789
|
`);
|
|
2790
|
+
logDaemonHealth({
|
|
2791
|
+
event: "process_stats",
|
|
2792
|
+
pid: process.pid,
|
|
2793
|
+
message: `agent_data_refresh took ${durationMs}ms`,
|
|
2794
|
+
data: { type: "timer_slow", timer: "agent_data_refresh", durationMs }
|
|
2795
|
+
});
|
|
2701
2796
|
}
|
|
2702
2797
|
} catch (err) {
|
|
2703
|
-
process.stderr.write(`[exed] Agent
|
|
2798
|
+
process.stderr.write(`[exed] Agent data refresh error: ${err instanceof Error ? err.message : String(err)}
|
|
2704
2799
|
`);
|
|
2705
2800
|
} finally {
|
|
2706
|
-
|
|
2801
|
+
_agentRefreshInFlight = false;
|
|
2707
2802
|
}
|
|
2708
2803
|
}
|
|
2709
2804
|
function startAgentStats() {
|
|
2710
|
-
const statsTimer = setInterval(() => void writeAgentStats(), AGENT_STATS_INTERVAL_MS);
|
|
2805
|
+
const statsTimer = setInterval(() => void traceDaemonTimer("agent_stats_write", () => writeAgentStats()), AGENT_STATS_INTERVAL_MS);
|
|
2711
2806
|
statsTimer.unref();
|
|
2712
2807
|
setTimeout(() => {
|
|
2713
|
-
void
|
|
2714
|
-
const
|
|
2715
|
-
|
|
2808
|
+
void traceDaemonTimer("agent_data_refresh", () => refreshAgentData());
|
|
2809
|
+
const refreshTimer = setInterval(() => void traceDaemonTimer("agent_data_refresh", () => refreshAgentData()), AGENT_STATS_REFRESH_INTERVAL_MS);
|
|
2810
|
+
refreshTimer.unref();
|
|
2716
2811
|
}, 3 * 60 * 1e3);
|
|
2717
|
-
process.stderr.write(`[exed] Agent stats started (
|
|
2812
|
+
process.stderr.write(`[exed] Agent stats started (file every ${AGENT_STATS_INTERVAL_MS / 1e3}s, data refresh every ${AGENT_STATS_REFRESH_INTERVAL_MS / 6e4}m, first refresh at +3m)
|
|
2718
2813
|
`);
|
|
2719
2814
|
}
|
|
2720
2815
|
var CONFIDENCE_DECAY_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -2781,7 +2876,7 @@ function startReflectionSweep() {
|
|
|
2781
2876
|
`);
|
|
2782
2877
|
}
|
|
2783
2878
|
};
|
|
2784
|
-
setTimeout(async () => {
|
|
2879
|
+
setTimeout(() => void traceDaemonTimer("memory_card_backfill", async () => {
|
|
2785
2880
|
try {
|
|
2786
2881
|
if (!await ensureStoreForPolling()) return;
|
|
2787
2882
|
const { getClient: gc } = await import("./database.js");
|
|
@@ -2826,7 +2921,7 @@ function startReflectionSweep() {
|
|
|
2826
2921
|
process.stderr.write("[exe-daemon] card backfill: " + (e instanceof Error ? e.message : String(e)) + "\n");
|
|
2827
2922
|
}
|
|
2828
2923
|
void tick();
|
|
2829
|
-
}, 5 * 60 * 1e3);
|
|
2924
|
+
}), 5 * 60 * 1e3);
|
|
2830
2925
|
const timer = setInterval(() => void tick(), REFLECTION_SWEEP_INTERVAL_MS);
|
|
2831
2926
|
timer.unref();
|
|
2832
2927
|
process.stderr.write(`[exed] Reflection sweep started (every 6h)
|
|
@@ -2896,7 +2991,7 @@ function startSoftDeletePurge() {
|
|
|
2896
2991
|
}
|
|
2897
2992
|
var QUEUE_DRAIN_INTERVAL_MS = 6e4;
|
|
2898
2993
|
function startIntercomQueueDrain() {
|
|
2899
|
-
const tick = async () => {
|
|
2994
|
+
const tick = async () => traceDaemonTimer("intercom_queue_drain", async () => {
|
|
2900
2995
|
fired("intercom_queue_drain");
|
|
2901
2996
|
try {
|
|
2902
2997
|
const { drainQueue } = await import("../intercom-queue-RNM6EPGA.js");
|
|
@@ -2924,7 +3019,7 @@ function startIntercomQueueDrain() {
|
|
|
2924
3019
|
} catch (e) {
|
|
2925
3020
|
process.stderr.write("[exe-daemon] intercom queue drain: " + (e instanceof Error ? e.message : String(e)) + "\n");
|
|
2926
3021
|
}
|
|
2927
|
-
};
|
|
3022
|
+
});
|
|
2928
3023
|
const timer = setInterval(tick, QUEUE_DRAIN_INTERVAL_MS);
|
|
2929
3024
|
timer.unref();
|
|
2930
3025
|
process.stderr.write(`[exed] Intercom queue drain started (every ${QUEUE_DRAIN_INTERVAL_MS / 1e3}s)
|
|
@@ -3075,7 +3170,7 @@ function getV8HeapLimitBytes() {
|
|
|
3075
3170
|
}
|
|
3076
3171
|
var TASK_ENFORCEMENT_INTERVAL_MS = 6e4;
|
|
3077
3172
|
function startTaskEnforcementScanner() {
|
|
3078
|
-
const tick = async () => {
|
|
3173
|
+
const tick = async () => traceDaemonTimer("task_enforcement", async () => {
|
|
3079
3174
|
fired("task_enforcement");
|
|
3080
3175
|
try {
|
|
3081
3176
|
const { runTaskEnforcementTick } = await import("../task-enforcement-OSPCFH5T.js");
|
|
@@ -3085,10 +3180,20 @@ function startTaskEnforcementScanner() {
|
|
|
3085
3180
|
const { loadEmployeesSync } = await import("./employees.js");
|
|
3086
3181
|
const { sessionScopeFilter } = await import("../task-scope-4CBJ3QI2.js");
|
|
3087
3182
|
const transport = getTransport();
|
|
3088
|
-
const allSessions =
|
|
3089
|
-
const paneCache = await
|
|
3183
|
+
const allSessions = (await getTmuxSessionsAsync()).filter((s) => s.includes("-"));
|
|
3184
|
+
const [paneCache, aliveSessions] = await Promise.all([
|
|
3185
|
+
batchCapturePanes(allSessions, 20),
|
|
3186
|
+
batchPaneAlive(allSessions)
|
|
3187
|
+
]);
|
|
3188
|
+
const enforcementTransport = {
|
|
3189
|
+
listSessions: () => allSessions,
|
|
3190
|
+
capturePane: transport.capturePane.bind(transport),
|
|
3191
|
+
sendKeys: transport.sendKeys.bind(transport),
|
|
3192
|
+
sendKeysLiteral: transport.sendKeysLiteral?.bind(transport),
|
|
3193
|
+
isAlive: (session) => aliveSessions.has(session)
|
|
3194
|
+
};
|
|
3090
3195
|
await runTaskEnforcementTick({
|
|
3091
|
-
transport,
|
|
3196
|
+
transport: enforcementTransport,
|
|
3092
3197
|
agentConfig: loadAgentConfig(),
|
|
3093
3198
|
employees: loadEmployeesSync(),
|
|
3094
3199
|
client: await getClient(),
|
|
@@ -3103,7 +3208,7 @@ function startTaskEnforcementScanner() {
|
|
|
3103
3208
|
`
|
|
3104
3209
|
);
|
|
3105
3210
|
}
|
|
3106
|
-
};
|
|
3211
|
+
});
|
|
3107
3212
|
const timer = setInterval(tick, TASK_ENFORCEMENT_INTERVAL_MS);
|
|
3108
3213
|
timer.unref();
|
|
3109
3214
|
process.stderr.write(`[exed] Task enforcement scanner started (${TASK_ENFORCEMENT_INTERVAL_MS / 1e3}s interval)
|
|
@@ -3189,13 +3294,13 @@ var _apiWatchdogLastNudge = /* @__PURE__ */ new Map();
|
|
|
3189
3294
|
var _apiWatchdogLastError = /* @__PURE__ */ new Map();
|
|
3190
3295
|
var _apiWatchdogNudgeCounts = /* @__PURE__ */ new Map();
|
|
3191
3296
|
function startApiWatchdog() {
|
|
3192
|
-
const tick = async () => {
|
|
3297
|
+
const tick = async () => traceDaemonTimer("api_watchdog", async () => {
|
|
3193
3298
|
fired("api_watchdog");
|
|
3194
3299
|
try {
|
|
3195
3300
|
const cfg = await getCachedConfig();
|
|
3196
3301
|
if (!cfg?.apiWatchdog?.enabled) return;
|
|
3197
3302
|
const cooldownMs = (cfg.apiWatchdog.cooldownMinutes ?? 10) * 6e4;
|
|
3198
|
-
const sessions =
|
|
3303
|
+
const sessions = await getTmuxSessionsAsync();
|
|
3199
3304
|
if (sessions.length === 0) return;
|
|
3200
3305
|
for (const session of sessions) {
|
|
3201
3306
|
if (!session.includes("-")) continue;
|
|
@@ -3260,13 +3365,13 @@ function startApiWatchdog() {
|
|
|
3260
3365
|
process.stderr.write(`[exed] API watchdog error: ${err instanceof Error ? err.message : String(err)}
|
|
3261
3366
|
`);
|
|
3262
3367
|
}
|
|
3263
|
-
};
|
|
3368
|
+
});
|
|
3264
3369
|
const timer = setInterval(() => void tick(), API_WATCHDOG_INTERVAL_MS);
|
|
3265
3370
|
timer.unref();
|
|
3266
3371
|
process.stderr.write("[exed] API watchdog started (30s scan, 10m cooldown per session)\n");
|
|
3267
3372
|
}
|
|
3268
3373
|
function startBackgroundJobGuardrails() {
|
|
3269
|
-
const tick = async () => {
|
|
3374
|
+
const tick = async () => traceDaemonTimer("background_job_guardrails", async () => {
|
|
3270
3375
|
fired("background_job_guardrails");
|
|
3271
3376
|
try {
|
|
3272
3377
|
const { enforceBackgroundJobGuardrails } = await import("../background-jobs-Q4S27FCN.js");
|
|
@@ -3285,7 +3390,7 @@ function startBackgroundJobGuardrails() {
|
|
|
3285
3390
|
process.stderr.write(`[exed] Background job guardrail error: ${err instanceof Error ? err.message : String(err)}
|
|
3286
3391
|
`);
|
|
3287
3392
|
}
|
|
3288
|
-
};
|
|
3393
|
+
});
|
|
3289
3394
|
const timer = setInterval(() => void tick(), 6e4);
|
|
3290
3395
|
timer.unref();
|
|
3291
3396
|
process.stderr.write("[exed] Background job guardrails started (every 60s)\n");
|
|
@@ -3672,7 +3777,7 @@ try {
|
|
|
3672
3777
|
startApiWatchdog();
|
|
3673
3778
|
startRssWatchdog();
|
|
3674
3779
|
setTimeout(startWalCheckpoint, 5e3);
|
|
3675
|
-
setTimeout(async () => {
|
|
3780
|
+
setTimeout(() => void traceDaemonTimer("task_file_resync", async () => {
|
|
3676
3781
|
try {
|
|
3677
3782
|
if (!await ensureStoreForPolling()) return;
|
|
3678
3783
|
const { readdir, readFile } = await import("fs/promises");
|
|
@@ -3740,17 +3845,17 @@ try {
|
|
|
3740
3845
|
process.stderr.write(`[exed] Task re-sync error: ${e.message}
|
|
3741
3846
|
`);
|
|
3742
3847
|
}
|
|
3743
|
-
}, 8e3);
|
|
3848
|
+
}), 8e3);
|
|
3744
3849
|
setTimeout(startIdleKill, 1e4);
|
|
3745
3850
|
setTimeout(startStuckTaskRelease, 15e3);
|
|
3746
3851
|
setTimeout(startOrphanReaper, 2e4);
|
|
3747
3852
|
setTimeout(startCloudSyncTimer, 25e3);
|
|
3748
3853
|
setTimeout(startAgentStats, 3e4);
|
|
3749
|
-
setTimeout(async () => {
|
|
3854
|
+
setTimeout(() => void traceDaemonTimer("session_registry_consistency", async () => {
|
|
3750
3855
|
fired("session_registry_consistency");
|
|
3751
3856
|
try {
|
|
3752
3857
|
const { checkSessionRegistryConsistency } = await import("./session-registry.js");
|
|
3753
|
-
const result = checkSessionRegistryConsistency();
|
|
3858
|
+
const result = checkSessionRegistryConsistency(await getTmuxSessionsAsync());
|
|
3754
3859
|
if (result.missingTmux > 0 || result.missingRegistry > 0) {
|
|
3755
3860
|
acted("session_registry_consistency");
|
|
3756
3861
|
process.stderr.write(
|
|
@@ -3762,8 +3867,8 @@ try {
|
|
|
3762
3867
|
process.stderr.write(`[exed] Session registry consistency error: ${err instanceof Error ? err.message : String(err)}
|
|
3763
3868
|
`);
|
|
3764
3869
|
}
|
|
3765
|
-
}, 35e3);
|
|
3766
|
-
setTimeout(startConsolidation, 6e4);
|
|
3870
|
+
}), 35e3);
|
|
3871
|
+
setTimeout(() => void traceDaemonTimer("consolidation_start", () => startConsolidation()), 6e4);
|
|
3767
3872
|
setTimeout(startSkillSweep, 9e4);
|
|
3768
3873
|
setTimeout(startSkillRefinement, 18e4);
|
|
3769
3874
|
setTimeout(startGraphExtraction, 27e4);
|
|
@@ -3773,10 +3878,10 @@ try {
|
|
|
3773
3878
|
setTimeout(startBugAutoFix, 24e4);
|
|
3774
3879
|
setTimeout(startDatabaseBackup, 27e4);
|
|
3775
3880
|
setTimeout(startAutoUpdateCheck, 3e5);
|
|
3776
|
-
setTimeout(startBackgroundJobGuardrails, 6e4);
|
|
3881
|
+
setTimeout(() => void traceDaemonTimer("background_job_guardrails_start", () => startBackgroundJobGuardrails()), 6e4);
|
|
3777
3882
|
setTimeout(startWorktreeReaper, 12e4);
|
|
3778
3883
|
setTimeout(startZombieAgentReaper, 25e3);
|
|
3779
|
-
setTimeout(async () => {
|
|
3884
|
+
setTimeout(() => void traceDaemonTimer("intercom_dedup_cleanup", async () => {
|
|
3780
3885
|
fired("intercom_dedup_cleanup");
|
|
3781
3886
|
try {
|
|
3782
3887
|
if (!await ensureStoreForPolling()) return;
|
|
@@ -3792,8 +3897,8 @@ try {
|
|
|
3792
3897
|
process.stderr.write(`[exed] Intercom dedup error: ${err instanceof Error ? err.message : String(err)}
|
|
3793
3898
|
`);
|
|
3794
3899
|
}
|
|
3795
|
-
}, 3e4);
|
|
3796
|
-
setTimeout(async () => {
|
|
3900
|
+
}), 3e4);
|
|
3901
|
+
setTimeout(() => void traceDaemonTimer("trace_ttl_sweep", async () => {
|
|
3797
3902
|
fired("trace_ttl_sweep");
|
|
3798
3903
|
try {
|
|
3799
3904
|
if (!await ensureStoreForPolling()) return;
|
|
@@ -3809,8 +3914,8 @@ try {
|
|
|
3809
3914
|
process.stderr.write(`[exed] Trace TTL error: ${err instanceof Error ? err.message : String(err)}
|
|
3810
3915
|
`);
|
|
3811
3916
|
}
|
|
3812
|
-
}, 45e3);
|
|
3813
|
-
setTimeout(async () => {
|
|
3917
|
+
}), 45e3);
|
|
3918
|
+
setTimeout(() => void traceDaemonTimer("orphan_task_cleanup", async () => {
|
|
3814
3919
|
fired("orphan_task_cleanup");
|
|
3815
3920
|
try {
|
|
3816
3921
|
if (!await ensureStoreForPolling()) return;
|
|
@@ -3830,7 +3935,7 @@ try {
|
|
|
3830
3935
|
process.stderr.write(`[exed] Orphan cleanup error: ${err instanceof Error ? err.message : String(err)}
|
|
3831
3936
|
`);
|
|
3832
3937
|
}
|
|
3833
|
-
}, 45e3);
|
|
3938
|
+
}), 45e3);
|
|
3834
3939
|
const HEALTH_HEARTBEAT_MS = 5 * 60 * 1e3;
|
|
3835
3940
|
setInterval(() => {
|
|
3836
3941
|
logHeartbeat();
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
registerAllTools
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-LSARQLX3.js";
|
|
4
4
|
import "../chunk-557C2IGL.js";
|
|
5
5
|
import "../chunk-3GFXV46R.js";
|
|
6
6
|
import "../chunk-BO6HP63V.js";
|
|
7
|
-
import "../chunk-
|
|
7
|
+
import "../chunk-UFOERR37.js";
|
|
8
8
|
import "../chunk-KH5Y6RR4.js";
|
|
9
9
|
import "../chunk-GCMXBQ7Y.js";
|
|
10
10
|
import "../chunk-IENYOYZ6.js";
|
|
@@ -56,7 +56,7 @@ import "../chunk-GMQKS5JD.js";
|
|
|
56
56
|
import "../chunk-K5EXLDQD.js";
|
|
57
57
|
import "../chunk-EF4PA3TY.js";
|
|
58
58
|
import "../chunk-LMSRF47U.js";
|
|
59
|
-
import "../chunk-
|
|
59
|
+
import "../chunk-NVZODD7S.js";
|
|
60
60
|
import "../chunk-E3Q4R3K6.js";
|
|
61
61
|
import "../chunk-CHCA3ZM2.js";
|
|
62
62
|
import "../chunk-XJQASQPO.js";
|
package/dist/mcp/server.js
CHANGED
|
@@ -3,11 +3,11 @@ import {
|
|
|
3
3
|
} from "../chunk-V4TZI6EO.js";
|
|
4
4
|
import {
|
|
5
5
|
registerAllTools
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-LSARQLX3.js";
|
|
7
7
|
import "../chunk-557C2IGL.js";
|
|
8
8
|
import "../chunk-3GFXV46R.js";
|
|
9
9
|
import "../chunk-BO6HP63V.js";
|
|
10
|
-
import "../chunk-
|
|
10
|
+
import "../chunk-UFOERR37.js";
|
|
11
11
|
import "../chunk-KH5Y6RR4.js";
|
|
12
12
|
import {
|
|
13
13
|
initLicenseGate
|
|
@@ -66,7 +66,7 @@ import "../chunk-GMQKS5JD.js";
|
|
|
66
66
|
import "../chunk-K5EXLDQD.js";
|
|
67
67
|
import "../chunk-EF4PA3TY.js";
|
|
68
68
|
import "../chunk-LMSRF47U.js";
|
|
69
|
-
import "../chunk-
|
|
69
|
+
import "../chunk-NVZODD7S.js";
|
|
70
70
|
import {
|
|
71
71
|
disposeStore,
|
|
72
72
|
initStore
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askexenow/exe-os",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.214",
|
|
4
4
|
"description": "AI employee operating system — persistent memory, task management, and multi-agent coordination for Claude Code.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"type": "module",
|
package/release-notes.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"current": "0.9.
|
|
2
|
+
"current": "0.9.214",
|
|
3
3
|
"notes": {
|
|
4
|
-
"0.9.
|
|
5
|
-
"version": "0.9.
|
|
6
|
-
"date": "2026-06-
|
|
4
|
+
"0.9.214": {
|
|
5
|
+
"version": "0.9.214",
|
|
6
|
+
"date": "2026-06-04",
|
|
7
7
|
"features": [
|
|
8
8
|
"free license telemetry is mandatory, paid can opt out",
|
|
9
9
|
"add mcp-sessions CLI — rich status table for running sessions",
|
|
@@ -32,6 +32,11 @@
|
|
|
32
32
|
"wire update.askexe.com — billing schema + non-fatal image credentials"
|
|
33
33
|
],
|
|
34
34
|
"fixes": [
|
|
35
|
+
"remove failed DB warmup workaround",
|
|
36
|
+
"trace daemon timers and async tmux session checks",
|
|
37
|
+
"add scope comment to DB warmup task query (readiness gate)",
|
|
38
|
+
"add DB warmup at boot+5s to prevent 15s block on first query",
|
|
39
|
+
"move DB memory count query to slow path — fast path is cache-only",
|
|
35
40
|
"split agent stats into fast path (60s) + slow path (10m)",
|
|
36
41
|
"defer agent stats first tick + async file write",
|
|
37
42
|
"Fix daemon agent stats event-loop stalls",
|
|
@@ -51,12 +56,7 @@
|
|
|
51
56
|
"shard circuit breaker, event loop self-healing, heap cap, intercom reason",
|
|
52
57
|
"add generate-hook-manifest to tsup entries — unblocks publish gate",
|
|
53
58
|
"remove unused cleanupExpiredJars import — fixes TS6133 blocking publish",
|
|
54
|
-
"remove dead actualRuntime variable — fixes TS6133 blocking publish"
|
|
55
|
-
"isolate Metal/GPU ops in worker process — reranker dispose crash was killing daemon",
|
|
56
|
-
"remove remaining /exe-intercom invocations + update tests",
|
|
57
|
-
"replace /exe-intercom skill invocation with plain text prompt",
|
|
58
|
-
"remove ALL --strict-mcp-config usage — was blocking /exe-intercom in session MCP config too",
|
|
59
|
-
"tsup outputs to dist directly — kill dist-next migration shim"
|
|
59
|
+
"remove dead actualRuntime variable — fixes TS6133 blocking publish"
|
|
60
60
|
],
|
|
61
61
|
"security": [
|
|
62
62
|
"fix shell injection, SSRF, socket leaks, backup validation",
|
|
@@ -73,6 +73,9 @@
|
|
|
73
73
|
"fix 4 pricing tier bypass vulnerabilities (audit F1-F4)"
|
|
74
74
|
],
|
|
75
75
|
"other": [
|
|
76
|
+
"bump to v0.9.214",
|
|
77
|
+
"bump to v0.9.213",
|
|
78
|
+
"bump to v0.9.212",
|
|
76
79
|
"bump to v0.9.211",
|
|
77
80
|
"bump to v0.9.210",
|
|
78
81
|
"bump to v0.9.209",
|
|
@@ -94,15 +97,12 @@
|
|
|
94
97
|
"bump to v0.9.201",
|
|
95
98
|
"bump to v0.9.200",
|
|
96
99
|
"design orchestration measurement baseline",
|
|
97
|
-
"capture tmux hardening path"
|
|
98
|
-
"add orchestration counterargument",
|
|
99
|
-
"audit tmux orchestration architecture",
|
|
100
|
-
"bump to v0.9.199"
|
|
100
|
+
"capture tmux hardening path"
|
|
101
101
|
],
|
|
102
102
|
"migration_notes": []
|
|
103
103
|
},
|
|
104
|
-
"0.9.
|
|
105
|
-
"version": "0.9.
|
|
104
|
+
"0.9.212": {
|
|
105
|
+
"version": "0.9.212",
|
|
106
106
|
"date": "2026-06-03",
|
|
107
107
|
"features": [
|
|
108
108
|
"free license telemetry is mandatory, paid can opt out",
|
|
@@ -132,6 +132,8 @@
|
|
|
132
132
|
"wire update.askexe.com — billing schema + non-fatal image credentials"
|
|
133
133
|
],
|
|
134
134
|
"fixes": [
|
|
135
|
+
"move DB memory count query to slow path — fast path is cache-only",
|
|
136
|
+
"split agent stats into fast path (60s) + slow path (10m)",
|
|
135
137
|
"defer agent stats first tick + async file write",
|
|
136
138
|
"Fix daemon agent stats event-loop stalls",
|
|
137
139
|
"async-ify task re-sync walk + git worktree list in daemon",
|
|
@@ -154,9 +156,7 @@
|
|
|
154
156
|
"isolate Metal/GPU ops in worker process — reranker dispose crash was killing daemon",
|
|
155
157
|
"remove remaining /exe-intercom invocations + update tests",
|
|
156
158
|
"replace /exe-intercom skill invocation with plain text prompt",
|
|
157
|
-
"remove ALL --strict-mcp-config usage — was blocking /exe-intercom in session MCP config too"
|
|
158
|
-
"tsup outputs to dist directly — kill dist-next migration shim",
|
|
159
|
-
"drop --strict-mcp-config from lean MCP — was blocking skill loading (/exe-intercom)"
|
|
159
|
+
"remove ALL --strict-mcp-config usage — was blocking /exe-intercom in session MCP config too"
|
|
160
160
|
],
|
|
161
161
|
"security": [
|
|
162
162
|
"fix shell injection, SSRF, socket leaks, backup validation",
|
|
@@ -173,6 +173,8 @@
|
|
|
173
173
|
"fix 4 pricing tier bypass vulnerabilities (audit F1-F4)"
|
|
174
174
|
],
|
|
175
175
|
"other": [
|
|
176
|
+
"bump to v0.9.212",
|
|
177
|
+
"bump to v0.9.211",
|
|
176
178
|
"bump to v0.9.210",
|
|
177
179
|
"bump to v0.9.209",
|
|
178
180
|
"update release-notes.json",
|
|
@@ -195,14 +197,12 @@
|
|
|
195
197
|
"design orchestration measurement baseline",
|
|
196
198
|
"capture tmux hardening path",
|
|
197
199
|
"add orchestration counterargument",
|
|
198
|
-
"audit tmux orchestration architecture"
|
|
199
|
-
"bump to v0.9.199",
|
|
200
|
-
"remove registry.askexe.com references — fully consolidated to update.askexe.com"
|
|
200
|
+
"audit tmux orchestration architecture"
|
|
201
201
|
],
|
|
202
202
|
"migration_notes": []
|
|
203
203
|
},
|
|
204
|
-
"0.9.
|
|
205
|
-
"version": "0.9.
|
|
204
|
+
"0.9.211": {
|
|
205
|
+
"version": "0.9.211",
|
|
206
206
|
"date": "2026-06-03",
|
|
207
207
|
"features": [
|
|
208
208
|
"free license telemetry is mandatory, paid can opt out",
|
|
@@ -232,6 +232,8 @@
|
|
|
232
232
|
"wire update.askexe.com — billing schema + non-fatal image credentials"
|
|
233
233
|
],
|
|
234
234
|
"fixes": [
|
|
235
|
+
"split agent stats into fast path (60s) + slow path (10m)",
|
|
236
|
+
"defer agent stats first tick + async file write",
|
|
235
237
|
"Fix daemon agent stats event-loop stalls",
|
|
236
238
|
"async-ify task re-sync walk + git worktree list in daemon",
|
|
237
239
|
"async worktree reaper — eliminates 30-min event loop blocks",
|
|
@@ -254,9 +256,7 @@
|
|
|
254
256
|
"remove remaining /exe-intercom invocations + update tests",
|
|
255
257
|
"replace /exe-intercom skill invocation with plain text prompt",
|
|
256
258
|
"remove ALL --strict-mcp-config usage — was blocking /exe-intercom in session MCP config too",
|
|
257
|
-
"tsup outputs to dist directly — kill dist-next migration shim"
|
|
258
|
-
"drop --strict-mcp-config from lean MCP — was blocking skill loading (/exe-intercom)",
|
|
259
|
-
"zombie agent reaper never kills coordinator/exe session processes"
|
|
259
|
+
"tsup outputs to dist directly — kill dist-next migration shim"
|
|
260
260
|
],
|
|
261
261
|
"security": [
|
|
262
262
|
"fix shell injection, SSRF, socket leaks, backup validation",
|
|
@@ -273,6 +273,8 @@
|
|
|
273
273
|
"fix 4 pricing tier bypass vulnerabilities (audit F1-F4)"
|
|
274
274
|
],
|
|
275
275
|
"other": [
|
|
276
|
+
"bump to v0.9.211",
|
|
277
|
+
"bump to v0.9.210",
|
|
276
278
|
"bump to v0.9.209",
|
|
277
279
|
"update release-notes.json",
|
|
278
280
|
"Standardize task completion reports",
|
|
@@ -295,16 +297,16 @@
|
|
|
295
297
|
"capture tmux hardening path",
|
|
296
298
|
"add orchestration counterargument",
|
|
297
299
|
"audit tmux orchestration architecture",
|
|
298
|
-
"bump to v0.9.199"
|
|
299
|
-
"remove registry.askexe.com references — fully consolidated to update.askexe.com",
|
|
300
|
-
"bump to 0.9.198 — coordinator reaper guard"
|
|
300
|
+
"bump to v0.9.199"
|
|
301
301
|
],
|
|
302
302
|
"migration_notes": []
|
|
303
303
|
},
|
|
304
|
-
"0.9.
|
|
305
|
-
"version": "0.9.
|
|
304
|
+
"0.9.210": {
|
|
305
|
+
"version": "0.9.210",
|
|
306
306
|
"date": "2026-06-03",
|
|
307
307
|
"features": [
|
|
308
|
+
"free license telemetry is mandatory, paid can opt out",
|
|
309
|
+
"add mcp-sessions CLI — rich status table for running sessions",
|
|
308
310
|
"5-minute telemetry batching + per-tool-call usage in payload",
|
|
309
311
|
"disk outbox for failed telemetry + remote killswitch",
|
|
310
312
|
"auto-attach orchestration metrics to every bug report",
|
|
@@ -327,11 +329,10 @@
|
|
|
327
329
|
"scale daemon heap to 25% of system RAM, support 10+ coordinators",
|
|
328
330
|
"add query expansion + benchmark results to retrieval platform procedure",
|
|
329
331
|
"3-mode BEAM benchmark — FTS vs FTS+Graph vs Hybrid",
|
|
330
|
-
"wire update.askexe.com — billing schema + non-fatal image credentials"
|
|
331
|
-
"add 'never defer' platform procedure — fix it now or assign it now",
|
|
332
|
-
"BEAM multi-tier support — 100K, 1M, 10M token scales"
|
|
332
|
+
"wire update.askexe.com — billing schema + non-fatal image credentials"
|
|
333
333
|
],
|
|
334
334
|
"fixes": [
|
|
335
|
+
"defer agent stats first tick + async file write",
|
|
335
336
|
"Fix daemon agent stats event-loop stalls",
|
|
336
337
|
"async-ify task re-sync walk + git worktree list in daemon",
|
|
337
338
|
"async worktree reaper — eliminates 30-min event loop blocks",
|
|
@@ -355,8 +356,7 @@
|
|
|
355
356
|
"replace /exe-intercom skill invocation with plain text prompt",
|
|
356
357
|
"remove ALL --strict-mcp-config usage — was blocking /exe-intercom in session MCP config too",
|
|
357
358
|
"tsup outputs to dist directly — kill dist-next migration shim",
|
|
358
|
-
"drop --strict-mcp-config from lean MCP — was blocking skill loading (/exe-intercom)"
|
|
359
|
-
"zombie agent reaper never kills coordinator/exe session processes"
|
|
359
|
+
"drop --strict-mcp-config from lean MCP — was blocking skill loading (/exe-intercom)"
|
|
360
360
|
],
|
|
361
361
|
"security": [
|
|
362
362
|
"fix shell injection, SSRF, socket leaks, backup validation",
|
|
@@ -373,12 +373,15 @@
|
|
|
373
373
|
"fix 4 pricing tier bypass vulnerabilities (audit F1-F4)"
|
|
374
374
|
],
|
|
375
375
|
"other": [
|
|
376
|
+
"bump to v0.9.210",
|
|
377
|
+
"bump to v0.9.209",
|
|
378
|
+
"update release-notes.json",
|
|
379
|
+
"Standardize task completion reports",
|
|
376
380
|
"bump to v0.9.208",
|
|
377
381
|
"bump to v0.9.207",
|
|
378
382
|
"bump to v0.9.206",
|
|
379
383
|
"bump to v0.9.205",
|
|
380
384
|
"bump to v0.9.204",
|
|
381
|
-
"update release-notes.json",
|
|
382
385
|
"bump stack manifest to v0.9.12 — CRM v0.9.44, exe-os v0.9.199",
|
|
383
386
|
"review full orchestration measurement coverage",
|
|
384
387
|
"bump to v0.9.203",
|
|
@@ -394,17 +397,16 @@
|
|
|
394
397
|
"add orchestration counterargument",
|
|
395
398
|
"audit tmux orchestration architecture",
|
|
396
399
|
"bump to v0.9.199",
|
|
397
|
-
"remove registry.askexe.com references — fully consolidated to update.askexe.com"
|
|
398
|
-
"bump to 0.9.198 — coordinator reaper guard",
|
|
399
|
-
"bump to 0.9.197 — TTL fix + registry consolidation + TS fixes",
|
|
400
|
-
"update all manifest images to update.askexe.com + compose + beam tuning"
|
|
400
|
+
"remove registry.askexe.com references — fully consolidated to update.askexe.com"
|
|
401
401
|
],
|
|
402
402
|
"migration_notes": []
|
|
403
403
|
},
|
|
404
|
-
"0.9.
|
|
405
|
-
"version": "0.9.
|
|
404
|
+
"0.9.209": {
|
|
405
|
+
"version": "0.9.209",
|
|
406
406
|
"date": "2026-06-03",
|
|
407
407
|
"features": [
|
|
408
|
+
"free license telemetry is mandatory, paid can opt out",
|
|
409
|
+
"add mcp-sessions CLI — rich status table for running sessions",
|
|
408
410
|
"5-minute telemetry batching + per-tool-call usage in payload",
|
|
409
411
|
"disk outbox for failed telemetry + remote killswitch",
|
|
410
412
|
"auto-attach orchestration metrics to every bug report",
|
|
@@ -427,11 +429,10 @@
|
|
|
427
429
|
"scale daemon heap to 25% of system RAM, support 10+ coordinators",
|
|
428
430
|
"add query expansion + benchmark results to retrieval platform procedure",
|
|
429
431
|
"3-mode BEAM benchmark — FTS vs FTS+Graph vs Hybrid",
|
|
430
|
-
"wire update.askexe.com — billing schema + non-fatal image credentials"
|
|
431
|
-
"add 'never defer' platform procedure — fix it now or assign it now",
|
|
432
|
-
"BEAM multi-tier support — 100K, 1M, 10M token scales"
|
|
432
|
+
"wire update.askexe.com — billing schema + non-fatal image credentials"
|
|
433
433
|
],
|
|
434
434
|
"fixes": [
|
|
435
|
+
"Fix daemon agent stats event-loop stalls",
|
|
435
436
|
"async-ify task re-sync walk + git worktree list in daemon",
|
|
436
437
|
"async worktree reaper — eliminates 30-min event loop blocks",
|
|
437
438
|
"simplify telemetry to once-per-day only",
|
|
@@ -455,8 +456,7 @@
|
|
|
455
456
|
"remove ALL --strict-mcp-config usage — was blocking /exe-intercom in session MCP config too",
|
|
456
457
|
"tsup outputs to dist directly — kill dist-next migration shim",
|
|
457
458
|
"drop --strict-mcp-config from lean MCP — was blocking skill loading (/exe-intercom)",
|
|
458
|
-
"zombie agent reaper never kills coordinator/exe session processes"
|
|
459
|
-
"typecheck errors blocking publish — async embed alert + dead code cleanup"
|
|
459
|
+
"zombie agent reaper never kills coordinator/exe session processes"
|
|
460
460
|
],
|
|
461
461
|
"security": [
|
|
462
462
|
"fix shell injection, SSRF, socket leaks, backup validation",
|
|
@@ -473,11 +473,14 @@
|
|
|
473
473
|
"fix 4 pricing tier bypass vulnerabilities (audit F1-F4)"
|
|
474
474
|
],
|
|
475
475
|
"other": [
|
|
476
|
+
"bump to v0.9.209",
|
|
477
|
+
"update release-notes.json",
|
|
478
|
+
"Standardize task completion reports",
|
|
479
|
+
"bump to v0.9.208",
|
|
476
480
|
"bump to v0.9.207",
|
|
477
481
|
"bump to v0.9.206",
|
|
478
482
|
"bump to v0.9.205",
|
|
479
483
|
"bump to v0.9.204",
|
|
480
|
-
"update release-notes.json",
|
|
481
484
|
"bump stack manifest to v0.9.12 — CRM v0.9.44, exe-os v0.9.199",
|
|
482
485
|
"review full orchestration measurement coverage",
|
|
483
486
|
"bump to v0.9.203",
|
|
@@ -494,10 +497,7 @@
|
|
|
494
497
|
"audit tmux orchestration architecture",
|
|
495
498
|
"bump to v0.9.199",
|
|
496
499
|
"remove registry.askexe.com references — fully consolidated to update.askexe.com",
|
|
497
|
-
"bump to 0.9.198 — coordinator reaper guard"
|
|
498
|
-
"bump to 0.9.197 — TTL fix + registry consolidation + TS fixes",
|
|
499
|
-
"update all manifest images to update.askexe.com + compose + beam tuning",
|
|
500
|
-
"bump to 0.9.196"
|
|
500
|
+
"bump to 0.9.198 — coordinator reaper guard"
|
|
501
501
|
],
|
|
502
502
|
"migration_notes": []
|
|
503
503
|
}
|
|
File without changes
|