evil-omo 3.12.2 → 3.12.4
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/cli/index.js +12 -12
- package/dist/features/background-agent/constants.d.ts +2 -2
- package/dist/index.js +23 -39
- package/package.json +12 -12
package/dist/cli/index.js
CHANGED
|
@@ -8967,7 +8967,7 @@ var {
|
|
|
8967
8967
|
// package.json
|
|
8968
8968
|
var package_default = {
|
|
8969
8969
|
name: "evil-omo",
|
|
8970
|
-
version: "3.12.
|
|
8970
|
+
version: "3.12.4",
|
|
8971
8971
|
description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
|
|
8972
8972
|
main: "dist/index.js",
|
|
8973
8973
|
types: "dist/index.d.ts",
|
|
@@ -9043,17 +9043,17 @@ var package_default = {
|
|
|
9043
9043
|
typescript: "^5.7.3"
|
|
9044
9044
|
},
|
|
9045
9045
|
optionalDependencies: {
|
|
9046
|
-
"evil-omo-darwin-arm64": "3.12.
|
|
9047
|
-
"evil-omo-darwin-x64": "3.12.
|
|
9048
|
-
"evil-omo-darwin-x64-baseline": "3.12.
|
|
9049
|
-
"evil-omo-linux-x64": "3.12.
|
|
9050
|
-
"evil-omo-linux-x64-baseline": "3.12.
|
|
9051
|
-
"evil-omo-linux-arm64": "3.12.
|
|
9052
|
-
"evil-omo-linux-x64-musl": "3.12.
|
|
9053
|
-
"evil-omo-linux-x64-musl-baseline": "3.12.
|
|
9054
|
-
"evil-omo-linux-arm64-musl": "3.12.
|
|
9055
|
-
"evil-omo-windows-x64": "3.12.
|
|
9056
|
-
"evil-omo-windows-x64-baseline": "3.12.
|
|
9046
|
+
"evil-omo-darwin-arm64": "3.12.4",
|
|
9047
|
+
"evil-omo-darwin-x64": "3.12.4",
|
|
9048
|
+
"evil-omo-darwin-x64-baseline": "3.12.4",
|
|
9049
|
+
"evil-omo-linux-x64": "3.12.4",
|
|
9050
|
+
"evil-omo-linux-x64-baseline": "3.12.4",
|
|
9051
|
+
"evil-omo-linux-arm64": "3.12.4",
|
|
9052
|
+
"evil-omo-linux-x64-musl": "3.12.4",
|
|
9053
|
+
"evil-omo-linux-x64-musl-baseline": "3.12.4",
|
|
9054
|
+
"evil-omo-linux-arm64-musl": "3.12.4",
|
|
9055
|
+
"evil-omo-windows-x64": "3.12.4",
|
|
9056
|
+
"evil-omo-windows-x64-baseline": "3.12.4"
|
|
9057
9057
|
},
|
|
9058
9058
|
overrides: {
|
|
9059
9059
|
"@opencode-ai/sdk": "^1.2.24"
|
|
@@ -5,9 +5,9 @@ export declare const TERMINAL_TASK_TTL_MS: number;
|
|
|
5
5
|
export declare const MIN_STABILITY_TIME_MS: number;
|
|
6
6
|
export declare const DEFAULT_STALE_TIMEOUT_MS = 1200000;
|
|
7
7
|
export declare const DEFAULT_MESSAGE_STALENESS_TIMEOUT_MS = 1800000;
|
|
8
|
-
export declare const DEFAULT_MAX_TOOL_CALLS =
|
|
8
|
+
export declare const DEFAULT_MAX_TOOL_CALLS = 4000;
|
|
9
9
|
export declare const DEFAULT_CIRCUIT_BREAKER_CONSECUTIVE_THRESHOLD = 20;
|
|
10
|
-
export declare const DEFAULT_CIRCUIT_BREAKER_ENABLED =
|
|
10
|
+
export declare const DEFAULT_CIRCUIT_BREAKER_ENABLED = false;
|
|
11
11
|
export declare const MIN_RUNTIME_BEFORE_STALE_MS = 30000;
|
|
12
12
|
export declare const MIN_IDLE_TIME_MS = 5000;
|
|
13
13
|
export declare const POLLING_INTERVAL_MS = 3000;
|
package/dist/index.js
CHANGED
|
@@ -20487,18 +20487,15 @@ async function handleSessionIdle(args) {
|
|
|
20487
20487
|
shouldSkipContinuation
|
|
20488
20488
|
} = args;
|
|
20489
20489
|
log(`[${HOOK_NAME}] session.idle`, { sessionID });
|
|
20490
|
-
console.error(`[TODO-DIAG] session.idle fired for ${sessionID}`);
|
|
20491
20490
|
const state2 = sessionStateStore.getState(sessionID);
|
|
20492
20491
|
if (state2.isRecovering) {
|
|
20493
20492
|
log(`[${HOOK_NAME}] Skipped: in recovery`, { sessionID });
|
|
20494
|
-
console.error(`[TODO-DIAG] BLOCKED: isRecovering=true`);
|
|
20495
20493
|
return;
|
|
20496
20494
|
}
|
|
20497
20495
|
if (state2.abortDetectedAt) {
|
|
20498
20496
|
const timeSinceAbort = Date.now() - state2.abortDetectedAt;
|
|
20499
20497
|
if (timeSinceAbort < ABORT_WINDOW_MS) {
|
|
20500
20498
|
log(`[${HOOK_NAME}] Skipped: abort detected via event ${timeSinceAbort}ms ago`, { sessionID });
|
|
20501
|
-
console.error(`[TODO-DIAG] BLOCKED: abort detected ${timeSinceAbort}ms ago`);
|
|
20502
20499
|
state2.abortDetectedAt = undefined;
|
|
20503
20500
|
return;
|
|
20504
20501
|
}
|
|
@@ -20507,7 +20504,6 @@ async function handleSessionIdle(args) {
|
|
|
20507
20504
|
const hasRunningBgTasks = backgroundManager ? backgroundManager.getTasksByParentSession(sessionID).some((task) => task.status === "running") : false;
|
|
20508
20505
|
if (hasRunningBgTasks) {
|
|
20509
20506
|
log(`[${HOOK_NAME}] Skipped: background tasks running`, { sessionID });
|
|
20510
|
-
console.error(`[TODO-DIAG] BLOCKED: background tasks running`, backgroundManager?.getTasksByParentSession(sessionID).filter((t) => t.status === "running").map((t) => t.id));
|
|
20511
20507
|
return;
|
|
20512
20508
|
}
|
|
20513
20509
|
try {
|
|
@@ -20518,12 +20514,10 @@ async function handleSessionIdle(args) {
|
|
|
20518
20514
|
const messages = normalizeSDKResponse(messagesResp, []);
|
|
20519
20515
|
if (isLastAssistantMessageAborted(messages)) {
|
|
20520
20516
|
log(`[${HOOK_NAME}] Skipped: last assistant message was aborted (API fallback)`, { sessionID });
|
|
20521
|
-
console.error(`[TODO-DIAG] BLOCKED: last assistant message aborted`);
|
|
20522
20517
|
return;
|
|
20523
20518
|
}
|
|
20524
20519
|
if (hasUnansweredQuestion(messages)) {
|
|
20525
20520
|
log(`[${HOOK_NAME}] Skipped: pending question awaiting user response`, { sessionID });
|
|
20526
|
-
console.error(`[TODO-DIAG] BLOCKED: hasUnansweredQuestion=true`);
|
|
20527
20521
|
return;
|
|
20528
20522
|
}
|
|
20529
20523
|
} catch (error) {
|
|
@@ -20535,14 +20529,12 @@ async function handleSessionIdle(args) {
|
|
|
20535
20529
|
todos = normalizeSDKResponse(response, [], { preferResponseOnMissingData: true });
|
|
20536
20530
|
} catch (error) {
|
|
20537
20531
|
log(`[${HOOK_NAME}] Todo fetch failed`, { sessionID, error: String(error) });
|
|
20538
|
-
console.error(`[TODO-DIAG] BLOCKED: todo fetch failed`, String(error));
|
|
20539
20532
|
return;
|
|
20540
20533
|
}
|
|
20541
20534
|
if (!todos || todos.length === 0) {
|
|
20542
20535
|
sessionStateStore.resetContinuationProgress(sessionID);
|
|
20543
20536
|
sessionStateStore.resetContinuationProgress(sessionID);
|
|
20544
20537
|
log(`[${HOOK_NAME}] No todos`, { sessionID });
|
|
20545
|
-
console.error(`[TODO-DIAG] BLOCKED: no todos`);
|
|
20546
20538
|
return;
|
|
20547
20539
|
}
|
|
20548
20540
|
const incompleteCount = getIncompleteCount(todos);
|
|
@@ -20550,12 +20542,10 @@ async function handleSessionIdle(args) {
|
|
|
20550
20542
|
sessionStateStore.resetContinuationProgress(sessionID);
|
|
20551
20543
|
sessionStateStore.resetContinuationProgress(sessionID);
|
|
20552
20544
|
log(`[${HOOK_NAME}] All todos complete`, { sessionID, total: todos.length });
|
|
20553
|
-
console.error(`[TODO-DIAG] BLOCKED: all todos complete (${todos.length})`);
|
|
20554
20545
|
return;
|
|
20555
20546
|
}
|
|
20556
20547
|
if (state2.inFlight) {
|
|
20557
20548
|
log(`[${HOOK_NAME}] Skipped: injection in flight`, { sessionID });
|
|
20558
|
-
console.error(`[TODO-DIAG] BLOCKED: inFlight=true`);
|
|
20559
20549
|
return;
|
|
20560
20550
|
}
|
|
20561
20551
|
if (state2.consecutiveFailures >= MAX_CONSECUTIVE_FAILURES && state2.lastInjectedAt && Date.now() - state2.lastInjectedAt >= FAILURE_RESET_WINDOW_MS) {
|
|
@@ -20564,13 +20554,11 @@ async function handleSessionIdle(args) {
|
|
|
20564
20554
|
}
|
|
20565
20555
|
if (state2.consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
|
|
20566
20556
|
log(`[${HOOK_NAME}] Skipped: max consecutive failures reached`, { sessionID, consecutiveFailures: state2.consecutiveFailures });
|
|
20567
|
-
console.error(`[TODO-DIAG] BLOCKED: consecutiveFailures=${state2.consecutiveFailures} >= ${MAX_CONSECUTIVE_FAILURES}`);
|
|
20568
20557
|
return;
|
|
20569
20558
|
}
|
|
20570
20559
|
const effectiveCooldown = CONTINUATION_COOLDOWN_MS * Math.pow(2, Math.min(state2.consecutiveFailures, 5));
|
|
20571
20560
|
if (state2.lastInjectedAt && Date.now() - state2.lastInjectedAt < effectiveCooldown) {
|
|
20572
20561
|
log(`[${HOOK_NAME}] Skipped: cooldown active`, { sessionID, effectiveCooldown, consecutiveFailures: state2.consecutiveFailures });
|
|
20573
|
-
console.error(`[TODO-DIAG] BLOCKED: cooldown active (${effectiveCooldown}ms, failures=${state2.consecutiveFailures})`);
|
|
20574
20562
|
return;
|
|
20575
20563
|
}
|
|
20576
20564
|
let resolvedInfo;
|
|
@@ -20591,12 +20579,10 @@ async function handleSessionIdle(args) {
|
|
|
20591
20579
|
const resolvedAgentName = resolvedInfo?.agent;
|
|
20592
20580
|
if (resolvedAgentName && skipAgents.some((s) => getAgentConfigKey(s) === getAgentConfigKey(resolvedAgentName))) {
|
|
20593
20581
|
log(`[${HOOK_NAME}] Skipped: agent in skipAgents list`, { sessionID, agent: resolvedAgentName });
|
|
20594
|
-
console.error(`[TODO-DIAG] BLOCKED: agent '${resolvedAgentName}' in skipAgents`);
|
|
20595
20582
|
return;
|
|
20596
20583
|
}
|
|
20597
20584
|
if ((compactionGuardActive || encounteredCompaction) && !resolvedInfo?.agent) {
|
|
20598
20585
|
log(`[${HOOK_NAME}] Skipped: compaction occurred but no agent info resolved`, { sessionID });
|
|
20599
|
-
console.error(`[TODO-DIAG] BLOCKED: compaction guard + no agent`);
|
|
20600
20586
|
return;
|
|
20601
20587
|
}
|
|
20602
20588
|
if (state2.recentCompactionAt && resolvedInfo?.agent) {
|
|
@@ -20604,20 +20590,16 @@ async function handleSessionIdle(args) {
|
|
|
20604
20590
|
}
|
|
20605
20591
|
if (isContinuationStopped?.(sessionID)) {
|
|
20606
20592
|
log(`[${HOOK_NAME}] Skipped: continuation stopped for session`, { sessionID });
|
|
20607
|
-
console.error(`[TODO-DIAG] BLOCKED: isContinuationStopped=true`);
|
|
20608
20593
|
return;
|
|
20609
20594
|
}
|
|
20610
20595
|
if (shouldSkipContinuation?.(sessionID)) {
|
|
20611
20596
|
log(`[${HOOK_NAME}] Skipped: another continuation hook already injected`, { sessionID });
|
|
20612
|
-
console.error(`[TODO-DIAG] BLOCKED: shouldSkipContinuation=true (gptPermissionContinuation recently injected)`);
|
|
20613
20597
|
return;
|
|
20614
20598
|
}
|
|
20615
20599
|
const progressUpdate = sessionStateStore.trackContinuationProgress(sessionID, incompleteCount, todos);
|
|
20616
20600
|
if (shouldStopForStagnation({ sessionID, incompleteCount, progressUpdate })) {
|
|
20617
|
-
console.error(`[TODO-DIAG] BLOCKED: stagnation detected (count=${progressUpdate.stagnationCount})`);
|
|
20618
20601
|
return;
|
|
20619
20602
|
}
|
|
20620
|
-
console.error(`[TODO-DIAG] PASSED all gates! Starting countdown (${incompleteCount}/${todos.length} incomplete)`);
|
|
20621
20603
|
startCountdown({
|
|
20622
20604
|
ctx,
|
|
20623
20605
|
sessionID,
|
|
@@ -20708,9 +20690,6 @@ function createTodoContinuationHandler(args) {
|
|
|
20708
20690
|
} = args;
|
|
20709
20691
|
return async ({ event }) => {
|
|
20710
20692
|
const props = event.properties;
|
|
20711
|
-
if (event.type === "session.idle") {
|
|
20712
|
-
console.error(`[TODO-DIAG] handler received session.idle event`, { sessionID: props?.sessionID });
|
|
20713
|
-
}
|
|
20714
20693
|
if (event.type === "session.error") {
|
|
20715
20694
|
const sessionID = props?.sessionID;
|
|
20716
20695
|
if (!sessionID)
|
|
@@ -78169,9 +78148,9 @@ var TERMINAL_TASK_TTL_MS = 30 * 60 * 1000;
|
|
|
78169
78148
|
var MIN_STABILITY_TIME_MS2 = 10 * 1000;
|
|
78170
78149
|
var DEFAULT_STALE_TIMEOUT_MS = 1200000;
|
|
78171
78150
|
var DEFAULT_MESSAGE_STALENESS_TIMEOUT_MS = 1800000;
|
|
78172
|
-
var DEFAULT_MAX_TOOL_CALLS =
|
|
78151
|
+
var DEFAULT_MAX_TOOL_CALLS = 4000;
|
|
78173
78152
|
var DEFAULT_CIRCUIT_BREAKER_CONSECUTIVE_THRESHOLD = 20;
|
|
78174
|
-
var DEFAULT_CIRCUIT_BREAKER_ENABLED =
|
|
78153
|
+
var DEFAULT_CIRCUIT_BREAKER_ENABLED = false;
|
|
78175
78154
|
var MIN_RUNTIME_BEFORE_STALE_MS = 30000;
|
|
78176
78155
|
var MIN_IDLE_TIME_MS = 5000;
|
|
78177
78156
|
var POLLING_INTERVAL_MS = 3000;
|
|
@@ -78638,13 +78617,15 @@ function pruneStaleTasksAndNotifications(args) {
|
|
|
78638
78617
|
tasks.delete(taskId);
|
|
78639
78618
|
continue;
|
|
78640
78619
|
}
|
|
78620
|
+
if (task.status === "running")
|
|
78621
|
+
continue;
|
|
78641
78622
|
const timestamp2 = task.status === "pending" ? task.queuedAt?.getTime() : task.startedAt?.getTime();
|
|
78642
78623
|
if (!timestamp2)
|
|
78643
78624
|
continue;
|
|
78644
78625
|
const age = now - timestamp2;
|
|
78645
78626
|
if (age <= TASK_TTL_MS)
|
|
78646
78627
|
continue;
|
|
78647
|
-
const errorMessage =
|
|
78628
|
+
const errorMessage = "Task timed out while queued (30 minutes)";
|
|
78648
78629
|
onTaskPruned(taskId, task, errorMessage);
|
|
78649
78630
|
}
|
|
78650
78631
|
for (const [sessionID, queued] of notifications.entries()) {
|
|
@@ -79514,22 +79495,22 @@ class BackgroundManager {
|
|
|
79514
79495
|
});
|
|
79515
79496
|
return;
|
|
79516
79497
|
}
|
|
79498
|
+
const maxToolCalls = circuitBreaker.maxToolCalls;
|
|
79499
|
+
if (task.progress.toolCalls >= maxToolCalls) {
|
|
79500
|
+
log("[background-agent] Circuit breaker: tool call limit reached", {
|
|
79501
|
+
taskId: task.id,
|
|
79502
|
+
toolCalls: task.progress.toolCalls,
|
|
79503
|
+
maxToolCalls,
|
|
79504
|
+
agent: task.agent,
|
|
79505
|
+
sessionID
|
|
79506
|
+
});
|
|
79507
|
+
this.cancelTask(task.id, {
|
|
79508
|
+
source: "circuit-breaker",
|
|
79509
|
+
reason: `Subagent exceeded maximum tool call limit (${maxToolCalls}). This usually indicates an infinite loop. The task was automatically cancelled to prevent excessive token usage.`
|
|
79510
|
+
});
|
|
79511
|
+
}
|
|
79517
79512
|
}
|
|
79518
79513
|
}
|
|
79519
|
-
const maxToolCalls = circuitBreaker.maxToolCalls;
|
|
79520
|
-
if (task.progress.toolCalls >= maxToolCalls) {
|
|
79521
|
-
log("[background-agent] Circuit breaker: tool call limit reached", {
|
|
79522
|
-
taskId: task.id,
|
|
79523
|
-
toolCalls: task.progress.toolCalls,
|
|
79524
|
-
maxToolCalls,
|
|
79525
|
-
agent: task.agent,
|
|
79526
|
-
sessionID
|
|
79527
|
-
});
|
|
79528
|
-
this.cancelTask(task.id, {
|
|
79529
|
-
source: "circuit-breaker",
|
|
79530
|
-
reason: `Subagent exceeded maximum tool call limit (${maxToolCalls}). This usually indicates an infinite loop. The task was automatically cancelled to prevent excessive token usage.`
|
|
79531
|
-
});
|
|
79532
|
-
}
|
|
79533
79514
|
}
|
|
79534
79515
|
}
|
|
79535
79516
|
if (event.type === "session.idle") {
|
|
@@ -80144,7 +80125,10 @@ Use \`background_output(task_id="${task.id}")\` to retrieve this result when rea
|
|
|
80144
80125
|
this.pruneStaleTasksAndNotifications();
|
|
80145
80126
|
const statusResult = await this.client.session.status();
|
|
80146
80127
|
const allStatuses = normalizeSDKResponse(statusResult, {});
|
|
80147
|
-
|
|
80128
|
+
const circuitBreakerForPolling = this.cachedCircuitBreakerSettings ?? resolveCircuitBreakerSettings(this.config);
|
|
80129
|
+
if (circuitBreakerForPolling.enabled) {
|
|
80130
|
+
await this.checkAndInterruptStaleTasks(allStatuses);
|
|
80131
|
+
}
|
|
80148
80132
|
for (const task of this.tasks.values()) {
|
|
80149
80133
|
if (task.status !== "running")
|
|
80150
80134
|
continue;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "evil-omo",
|
|
3
|
-
"version": "3.12.
|
|
3
|
+
"version": "3.12.4",
|
|
4
4
|
"description": "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -76,17 +76,17 @@
|
|
|
76
76
|
"typescript": "^5.7.3"
|
|
77
77
|
},
|
|
78
78
|
"optionalDependencies": {
|
|
79
|
-
"evil-omo-darwin-arm64": "3.12.
|
|
80
|
-
"evil-omo-darwin-x64": "3.12.
|
|
81
|
-
"evil-omo-darwin-x64-baseline": "3.12.
|
|
82
|
-
"evil-omo-linux-x64": "3.12.
|
|
83
|
-
"evil-omo-linux-x64-baseline": "3.12.
|
|
84
|
-
"evil-omo-linux-arm64": "3.12.
|
|
85
|
-
"evil-omo-linux-x64-musl": "3.12.
|
|
86
|
-
"evil-omo-linux-x64-musl-baseline": "3.12.
|
|
87
|
-
"evil-omo-linux-arm64-musl": "3.12.
|
|
88
|
-
"evil-omo-windows-x64": "3.12.
|
|
89
|
-
"evil-omo-windows-x64-baseline": "3.12.
|
|
79
|
+
"evil-omo-darwin-arm64": "3.12.4",
|
|
80
|
+
"evil-omo-darwin-x64": "3.12.4",
|
|
81
|
+
"evil-omo-darwin-x64-baseline": "3.12.4",
|
|
82
|
+
"evil-omo-linux-x64": "3.12.4",
|
|
83
|
+
"evil-omo-linux-x64-baseline": "3.12.4",
|
|
84
|
+
"evil-omo-linux-arm64": "3.12.4",
|
|
85
|
+
"evil-omo-linux-x64-musl": "3.12.4",
|
|
86
|
+
"evil-omo-linux-x64-musl-baseline": "3.12.4",
|
|
87
|
+
"evil-omo-linux-arm64-musl": "3.12.4",
|
|
88
|
+
"evil-omo-windows-x64": "3.12.4",
|
|
89
|
+
"evil-omo-windows-x64-baseline": "3.12.4"
|
|
90
90
|
},
|
|
91
91
|
"overrides": {
|
|
92
92
|
"@opencode-ai/sdk": "^1.2.24"
|