Commit Graph

4563 Commits

Author SHA1 Message Date
Disaster-Terminator 4e3684eb2a fix(tmux): gate isolated pane activation on visible client focus 2026-05-16 00:05:02 +09:00
Disaster-Terminator c63108d55b fix(tmux): track placeholder panes before attach readiness 2026-05-16 00:02:02 +09:00
Disaster-Terminator 688bb551b2 fix(tmux): defer subagent attach until pane focus 2026-05-15 23:57:07 +09:00
Enoch d11613999a fix tool execute after hook boundary 2026-05-15 23:37:45 +09:00
YeonGyu-Kim ad10450b5c Merge pull request #3841 from Momentum96/fix/background-manager-tmux-ordering 2026-05-15 23:35:29 +09:00
YeonGyu-Kim be25109f6d fix(continuation): skip internal user turns 2026-05-15 23:16:23 +09:00
YeonGyu-Kim c580b8f2ce fix(session): ignore internal synthetic turns 2026-05-15 23:16:05 +09:00
YeonGyu-Kim e8de8b79a8 fix(team-mode): skip pending mailbox reinjection 2026-05-15 23:15:46 +09:00
Momentum96 e90ff8058e fix(tmux): treat busy sessions as attachable 2026-05-15 23:12:56 +09:00
Momentum96 efb862ce9f fix(tmux): prefer real tmux when session env exists 2026-05-15 23:12:56 +09:00
Momentum96 5238dd484e fix(background-agent): start promptAsync before blocking tmux callback
- Fixes BackgroundManager to launch promptAsync before invoking the blocking tmux callback.
- Adds regression test to ensure promptAsync is called before tmux callback.
2026-05-15 23:11:07 +09:00
YeonGyu-Kim a9a003250c Merge pull request #3497 from Disaster-Terminator/fix/reminder-hooks-preserve-state-across-compaction 2026-05-15 23:08:48 +09:00
YeonGyu-Kim 291b1f7b3c test(reminder-hooks): clean up compaction regressions 2026-05-15 22:59:58 +09:00
YeonGyu-Kim 672f5d6e9b fix(keyword-detector): skip synthetic turns 2026-05-15 22:49:17 +09:00
YeonGyu-Kim 196f6512ae fix(team-mode): defer live mailbox acks 2026-05-15 22:49:10 +09:00
Disaster-Terminator 392c20e53a test(reminder-hooks): make delete reset regression diagnostic 2026-05-15 22:43:32 +09:00
Disaster-Terminator 29e7e97d8f test(reminder-hooks): cover delegated sessions across compaction 2026-05-15 22:42:49 +09:00
Disaster-Terminator 3db1da1e5b fix(reminder-hooks): preserve suppression state across compaction 2026-05-15 22:42:49 +09:00
YeonGyu-Kim 3e9b125fd5 test(runtime-fallback): cover localized provider errors 2026-05-15 22:25:20 +09:00
wjiuxing c206b16865 feat: add Chinese error patterns to model-error-classifier 2026-05-15 22:23:06 +09:00
wjiuxing 149a83d703 feat: add Chinese quota patterns to classifyErrorType 2026-05-15 22:22:21 +09:00
wjiuxing adfa8befbb feat: add Chinese error patterns to RETRYABLE_ERROR_PATTERNS 2026-05-15 22:21:06 +09:00
Ravi Tharuma d9033d73ae fix(runtime-fallback): keep variant in equivalence
Treat parsed variant as part of runtime-fallback model equivalence so variant-only fallback hops remain distinct while preserving the existing Claude-family alias handling.

Constraint: Oracle verification flagged unresolved PR #3322 review concerns about variant equivalence and remote state
Rejected: Preserve provider identity in equivalence | contradicted the original live-loop fix for equivalent Claude aliases
Confidence: medium
Scope-risk: narrow
Directive: Any future equivalence broadening must prove both live retry-loop behavior and variant/provider semantics with targeted tests before merging
Tested: bun run typecheck
Tested: bun test src/hooks/runtime-fallback/index.test.ts src/hooks/runtime-fallback/error-classifier.test.ts src/plugin/event.model-fallback.test.ts
Not-tested: Full live end-to-end repro across all provider redundancy policies
2026-05-15 22:05:27 +09:00
Ravi Tharuma f501c47c49 fix(runtime-fallback): skip equivalent claude aliases
Prevent runtime fallback from cycling through provider aliases that resolve to the same underlying Claude family model. This keeps retry handling moving toward a genuinely distinct fallback model instead of appearing to fallback while staying on the same effective model.

Constraint: Live retry/fallback bug is in /Users/ravi/Code/personal/oh-my-opencode, while oh-my-openagent contribution work remains isolated to /Users/ravi/Code/forks/oh-my-openagent
Rejected: Change fallback chain precedence (category vs agent) first | lower-confidence root cause than equivalent-model retry
Confidence: high
Scope-risk: narrow
Directive: Keep alias-equivalence logic limited to model families that are intentionally interchangeable for runtime failover, and expand with targeted tests before broadening provider-family collapsing
Tested: bun run typecheck
Tested: bun test src/hooks/runtime-fallback/index.test.ts src/hooks/runtime-fallback/error-classifier.test.ts src/plugin/event.model-fallback.test.ts
Not-tested: Full live end-to-end session repro against external provider outages
2026-05-15 22:05:00 +09:00
YeonGyu-Kim f54888b2fe Merge pull request #3576 from Disaster-Terminator/fix/background-busy-stall-detection 2026-05-15 21:56:31 +09:00
YeonGyu-Kim 27788b4ab0 fix(session-recovery): audit raw prompt aliases 2026-05-15 21:53:05 +09:00
YeonGyu-Kim 4a1c260d8b test(todo-continuation): cover peer-message reservation holds 2026-05-15 21:52:53 +09:00
YeonGyu-Kim 39fef2042b fix(background-agent): resolve parent wake agent aliases 2026-05-15 21:52:40 +09:00
YeonGyu-Kim 2bd4944bad fix(prompt-gate): scope reservation releases 2026-05-15 21:52:29 +09:00
Disaster-Terminator b6caa5d3e0 fix(background-agent): correct stall timeout guidance 2026-05-15 21:44:29 +09:00
Disaster-Terminator 189af23e96 fix(background-agent): detect stalled active sessions 2026-05-15 21:44:29 +09:00
YeonGyu-Kim 65c1283338 fix(todo-continuation): clean up idle event diagnostics 2026-05-15 21:29:21 +09:00
Evgeny Zotov 047ca069a2 test: rename test to reflect todo-only stagnation check
Address review feedback: test name no longer references 'tool activity'
since activity tracking was removed.
2026-05-15 21:11:08 +09:00
Evgeny Zotov 68e9d54fa5 fix(todo-continuation): remove activity-based stagnation bypass
Activity signals (tool calls like compress, grep, bash) were treated as
'progress' by the stagnation detector, resetting the stagnation counter
every cycle. This prevented MAX_STAGNATION_COUNT from being reached,
causing infinite continuation loops when models degrade to minimal
responses in long sessions (e.g. GLM-5.1 at ~100K tokens).

Stagnation now only tracks actual todo state changes: incomplete count
decrease, completed count increase, or todo snapshot change. Tool-level
activity no longer resets the stagnation counter.
2026-05-15 21:11:08 +09:00
rshks b504fb1deb fix(tool-pair-validator): emit schema-compatible synthetic tool results 2026-05-15 21:04:03 +09:00
Ivan Smetanin 3199bd3d90 fix(runtime-fallback): broaden watchdog progress detection + harden test timing
Addresses two issues identified by cubic on PR #3952.

1. Watchdog cancellation was too narrow — only `text`/`reasoning` parts
   counted as progress, so a subagent that immediately ran tools
   (Read/Bash/Edit) emitted `tool`/`tool_use`/`tool_result`/`tool-call`/
   `step-start` parts that the watchdog ignored, risking a false fire
   on actively-working subagents. Broaden to: any assistant part of any
   known type counts as progress (the model has started responding,
   whether or not visible text has arrived yet). `info.error` and
   `info.finish` continue to cancel.

2. Test timing margins were tight (15ms pre-cancel against a 40ms
   timer), risking CI flakiness on loaded runners. Bumped to a 100ms
   threshold with a 40ms pre-cancel window and a 250ms post-fire wait,
   giving a 60ms margin before the timer fires and ~2.5x the threshold
   after — robust against scheduler delay.

Refactor for testability: extracted the OpenCode-event→watchdog-signal
translation out of `hook.ts` into an exported `observeEventForWatchdog`
helper on the watchdog module. This let me add direct unit tests for
every part-type case (text, reasoning, tool, tool_use, tool_result,
tool-call, step-start, file) plus the error/finish/empty-parts branches
without spinning up the full hook. Net diff: hook.ts shrinks, watchdog
module gains a small pure function with parametrised coverage.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 20:47:03 +09:00
Ivan Smetanin a130fa70d1 fix(runtime-fallback): add first-prompt watchdog for stuck subagents
When a subagent is dispatched to a provider and the underlying SDK
enters a silent internal retry loop on a 429/quota error, no error
event is ever emitted back to OpenCode. The runtime-fallback hook —
which is fully reactive (listens to message.updated/session.error/
session.status) — has nothing to react to and never dispatches the
configured fallback. The subagent sits in `retry` status until the
parent's 30-minute poll timeout (DEFAULT_POLL_TIMEOUT_MS) gives up,
during which the parent's pending task tool call shows "waiting for
subagent" with no indication of failure.

This change adds a first-prompt watchdog that synthesises the missing
error-event trigger:

  - Armed when a user message lands in a subagent session
    (membership check via `subagentSessions`).
  - Cancelled on the first sign of progress: any assistant message
    with text/reasoning content, finish field, or an error field (any
    of which is something the existing handlers will deal with).
  - Cancelled on session terminal events (idle/stop/deleted/error).
  - On fire (90s default): aborts the in-flight request and routes
    into the existing dispatchFallbackRetry path — the same code that
    runs when a session.error arrives. No new fallback mechanism.

Design choices:

  - Dispatch fallback, do not abort the subagent outright. Network
    loss looks identical to a stuck retry from the hook's vantage
    point; with fallback-dispatch behaviour, network loss degrades
    to today's baseline (both attempts fail, 30-min outer timeout
    still ends things) rather than destructively aborting work.
  - Scope strictly to subagents. Parent/user sessions can legitimately
    take 90s+ to produce the first token; subagent dispatches in
    practice produce first content much faster, so a 90s ceiling is
    safe.
  - Threshold is tunable via the third arg to createFirstPromptWatchdog;
    DEFAULT_FIRST_PROMPT_WATCHDOG_MS = 90_000 in constants.ts.

Also adds a diagnostic log in session-status-handler when a
`session.status: retry` event arrives whose message does not match
RETRYABLE_ERROR_PATTERNS. This is the hook's other silent-return
spot for retry events; logging the raw retry message will let us
extend the patterns next time we hit a provider whose phrasing
we don't yet match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 20:45:46 +09:00
YeonGyu-Kim bda0452b2a Merge pull request #4029 from sandikodev/fix/json-error-recovery-exclude-todowrite
fix(json-error-recovery): add todowrite and todoread to exclude list
2026-05-15 20:27:42 +09:00
YeonGyu-Kim f835244d42 Merge pull request #4047 from PeterPonyu/fix/3894-skip-tmux-layout-when-server-unreachable
fix(team-mode): skip tmux layout when opencode server unreachable
2026-05-15 20:25:22 +09:00
YeonGyu-Kim e66d60f4c5 Merge pull request #3773 from cailgarrisk-collab/fix/glm-rate-limit-fallback-statuscode
fix(model-fallback): add HTTP statusCode check for GLM rate limit fallback
2026-05-15 20:04:22 +09:00
YeonGyu-Kim 5cda8b8fe8 Merge pull request #3330 from codeg-dev/fix/isplan-display-name-getAgentConfigKey
fix(delegate-task): apply getAgentConfigKey normalization to isPlanAgent
2026-05-15 19:57:41 +09:00
YeonGyu-Kim a328343622 Merge pull request #3299 from kilhyeonjun/fix/claude-code-settings-hooks-not-executed
fix: don't early-return on 'allow' in executePreToolUseHooks, accumulate hook outputs
2026-05-15 19:57:37 +09:00
YeonGyu-Kim 0036c203a2 Merge pull request #3934 from Qihao0v0/fix/unifyllm-quota-classifier
fix(runtime-fallback): classify localized balance failures as quota exhaustion
2026-05-15 19:57:34 +09:00
YeonGyu-Kim c6054af9fa Merge pull request #3872 from x-x-gpu/dev
fix: pass resolved model to session.create so sub-agent sessions use the correct model
2026-05-15 19:56:09 +09:00
brooksbUWO 9f6b68118e fix(hooks): do not clear sessionFirstMessageProcessed on session.idle
SessionStart hooks fire on every user prompt instead of only at session
start. The root cause is clearSessionHookState(), called on every
session.idle event, which clears sessionFirstMessageProcessed. This
resets the isFirstMessage guard, making it always return true, so
SessionStart hooks execute on every prompt.

sessionFirstMessageProcessed is session-level state (tracks whether the
first message has been processed) and should only be cleared in
clearAllSessionHookState() on session deletion/disposal, not on idle.

sessionErrorState and sessionInterruptState remain cleared on idle since
they are per-response transient state.
2026-05-15 19:50:14 +09:00
PeterPonyu bd3928e158 fix(team-mode): skip tmux layout when opencode server unreachable
`createManagers` unconditionally called `markServerRunningInProcess()`
whenever `tmuxConfig.enabled` was true, which made `isServerRunning()`
short-circuit to `true` for *any* serverUrl — bypassing the guard in
`createTeamLayout` that is supposed to skip pane creation when the
opencode server is not running.

When a user launches vanilla `opencode` (no `opencode serve` /
`opencode web`), `ctx.serverUrl` is undefined and the TmuxSessionManager
falls back to `http://localhost:4096`. With the in-process flag set, the
team layout proceeded to spawn tmux panes whose `opencode attach`
commands then failed with "Unable to connect" — exactly the symptom in
the bug report.

Only mark the server as in-process running when the SDK actually
provides `ctx.serverUrl`. When it does not, `isServerRunning()` falls
back to a real HTTP probe, the existing guard in `createTeamLayout`
returns null, and no panes are created.

Closes #3894
2026-05-15 06:46:07 -04:00
YeonGyu-Kim 7caf74a9b9 fix(atlas,todo-continuation): strip ZWSP sort prefix before promptAsync agent
Both injectors call resolveRegisteredAgentName, which returns the
registered alias verbatim. OpenCode TUI registers agent names with
leading zero-width characters (U+200B) for sort ordering, so that
alias can be e.g. "\u200B\u200BAtlas - Plan Executor". Passing it
directly to promptAsync produces "Agent not found" because the
OpenCode SDK does an exact match against its canonical display
name registry.

Strip the ZWSP sort prefix on the resolved name before sending it
to promptAsync in:
- src/hooks/atlas/boulder-continuation-injector.ts
- src/hooks/todo-continuation-enforcer/continuation-injection.ts

Add regression tests asserting promptAsync receives the canonical
display name (no \u200B) even when the registered alias carries
a ZWSP sort prefix. Same root cause class as #3494 / #3547. Tests
were RED on dev before the fix and GREEN after.
2026-05-15 19:44:44 +09:00
Sami Jawhar 10f721de1f fix(call-omo-agent): translate config-key subagent_type to display name before SDK dispatch 2026-05-15 19:32:34 +09:00
YeonGyu-Kim 437a8edba6 Merge pull request #4007 from PeterPonyu/feat/runtime-fallback-internal-abort
fix(runtime-fallback): preserve attemptCount when our own abort is the cause
2026-05-15 19:26:53 +09:00
YeonGyu-Kim 5e7ee9418a Merge pull request #3982 from jas32096/fix/category-fallback-ignored-when-primary-set
fix(delegate-task): honor user fallback_models when category primary is unreachable
2026-05-15 19:26:37 +09:00