When users configure agents.sisyphus-junior.model, category sessions
should use that model without falling back to hardcoded
AGENT_MODEL_REQUIREMENTS. Two leaks existed:
1. Launch-time: category-resolver.ts did not check overrideModel when
deciding whether to use the hardcoded fallbackChain. Fixed by adding
overrideModel to the suppression condition.
2. Runtime retry: model-fallback hook.ts treated undefined fallbackChain
(from setSessionFallbackChain(id, undefined)) as 'no override' and
fell through to AGENT_MODEL_REQUIREMENTS on session.error/status
retry. Fixed by storing explicit empty array and checking .has()
instead of truthiness.
Tests added:
- hook.test.ts: explicit empty session fallback suppresses agent chain
- event.model-fallback-2941.test.ts: session.error does not arm retry
- category-resolver.test.ts: overrideModel suppresses fallbackChain
- tools.test.ts: sisyphusJuniorModel override assertion
Display names with parentheses like 'Atlas (Plan Executor)' cause HTTP
header validation errors in x-opencode-agent-name. This was blocking
Atlas/Prometheus from working via /start-work and auto-retry.
Changes:
- Display names: parens -> dashes ('Atlas - Plan Executor')
- Hooks (start-work, no-hephaestus-non-gpt, no-sisyphus-gpt): use
config keys ('atlas', 'sisyphus', 'hephaestus') for agent API fields
- auto-retry: use config key instead of display name for promptAsync
- agent-override-protection: handle dash-suffix normalization
- Updated all test expectations to match new format
Closes#3138
When weaker models (GLM-5, MiniMax) omit the description parameter on
delegate_task, the tool now auto-generates it from the first 4 words of
the prompt instead of throwing an error.
Changes:
- Schema: description is now optional (tool.schema.string().optional())
- Runtime: auto-generates from prompt when missing/empty/whitespace
- DelegateTaskArgs.description type stays as string (guaranteed by auto-gen)
- Tests: 3 new cases - missing/empty/explicit description handling
- Metadata title set after description resolution (correct ordering)
Tool return values contained CTAs ("Use background_output to check") that
caused models to immediately poll instead of waiting for <system-reminder>
notifications. Unified all 5 tool return messages with explicit "Do NOT call
background_output now" guard, added pre-notification warning to BackgroundOutput
tool description, and strengthened Background Result Collection sections across
all 3 Sisyphus prompt variants (default, gpt-5-4, main) with BLOCKING
anti-pattern enforcement.
🤖 Generated with assistance of [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
OpenCode's fromPlugin wrapper skips Zod validation for plugin tools, so
LLMs can omit required args like description without getting an error.
When Atlas orchestrates and the model omits description, it flows through
as undefined to manager.launch() and background task notifications show
'undefined' for all completed tasks.
Two fixes:
- Add runtime validation for description in delegate-task tool (matches
existing run_in_background and load_skills validation pattern)
- Defensive fallback in notification template: use task ID when
description is missing instead of rendering 'undefined'
- Remove kimi from auto-detected unstable agents in category-resolver (only gemini/minimax remain)
- Add resolveCallID() to safely resolve callID/callId/call_id variants from tool context
- Use resolveCallID across all 5 delegate task execution paths (sync, background, unstable, continuations)
- Update writing category test to verify kimi runs sync when kimi provider is available
- Add atlas metadata preservation tests confirming tool-execute-after does not clobber metadata
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
When a user configures a custom model for a category (e.g. quick.model),
the hardcoded CATEGORY_MODEL_REQUIREMENTS fallbackChain was overriding it.
This caused the user's model to be ignored and replaced with the default
(e.g. openai/gpt-5.4-mini).
Fix:
- Use userModelOverride directly instead of potentially stale actualModel
- Suppress hardcoded fallbackChain when explicitCategoryModel is provided
- Add regression test verifying user category model takes precedence
Closes#3040
LLMs sometimes wrap agent names in backslashes, quotes, or slashes
(e.g. \hephaestus\ instead of hephaestus). The trim() call only
removed whitespace, causing "Agent not found" errors during delegation.
Now strips leading/trailing backslashes, quotes, and slashes before
the case-insensitive agent lookup.
Adds regression tests for backslash-wrapped, double-quoted, and
single-quoted agent names.
Fixes: release blocker — delegate_task to hephaestus failing in
pre-publish review sessions.
Deep category now uses gpt-5.4 as its default model across all providers
(openai, github-copilot, venice, opencode), matching Hephaestus's GPT 5.4
upgrade. The requiresModel constraint is removed since gpt-5.4 is widely
available. Adds openai/gpt-5.3-codex -> openai/gpt-5.4 config migration
for existing user configs. Deep category prompt optimized for GPT 5.4's
stronger native capabilities (leaner, less verbose).
subagent-resolver: when falling back to matchedAgent.model for custom
subagents, verify the model is actually available via fuzzyMatchModel
before setting it as categoryModel. Prevents delegate_task from using
an unavailable model when the user's custom agent config references
a model they don't have access to.
Test updated to include the target model in available models mock.
Background subagents (explore/librarian) failed with auth errors because
resolveModelForDelegateTask() always picked the first fallback entry when
availableModels was empty — often an unauthenticated provider like xai
or opencode-go.
Fix: when connectedProvidersCache is populated, iterate fallback chain
and pick the first entry whose provider is in the connected set.
Legacy behavior preserved when cache is null (not yet populated).
- model-selection.ts: use readConnectedProvidersCache to filter fallback chain
- test: 4 new tests for connected-provider-aware resolution
- fix(switcher): use lastIndexOf for multi-slash model IDs (e.g. aws/anthropic/claude-sonnet-4)
- fix(model-resolution): same lastIndexOf fix in doctor parseProviderModel
- fix(call-omo-agent): resolve model from agent config and forward to both
background and sync executors via DelegatedModelConfig
- fix(subagent-resolver): inherit category model/variant when agent uses
category reference without explicit model override
- test: add model override forwarding tests for call-omo-agent
- test: add multi-slash model ID test for switcher
When provider-models cache is cold (first run / cache miss),
resolveModelForDelegateTask returns {skipped: true}. Previously this
caused the subagent resolver to:
1. Ignore the user's explicit model override (e.g. explore.model)
2. Fall through to the hardcoded fallback chain which may contain
model IDs that don't exist in the provider catalog
Now:
- subagent-resolver: if resolution is skipped but user explicitly
configured a model, use it directly
- subagent-resolver: don't assign hardcoded fallback chain on skip
- category-resolver: same — don't leak hardcoded chain on skip
- general-agents: if user model fails resolution, use it as-is
instead of falling back to hardcoded chain first entry
Closes#2820
Add support for object-style entries in fallback_models arrays, enabling
per-model configuration of variant, reasoningEffort, temperature, top_p,
maxTokens, and thinking settings.
- Zod schema for FallbackModelObject with full validation
- normalizeFallbackModels() and flattenToFallbackModelStrings() utilities
- Provider-agnostic model resolution pipeline with fallback chain
- Session prompt params state management
- Fallback chain construction with prefix-match lookup
- Integration across delegate-task, background-agent, and plugin layers
Previously, when an explicit model was configured, the agent name was
omitted to prevent opencode's built-in agent fallback chain from
overriding the user-specified model. This removes that conditional logic
and always passes the agent name alongside the model. Tests are updated
to reflect this behavior change.
🤖 GENERATED WITH ASSISTANCE OF [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>