Agent keys are remapped to display names, so preserving `default_agent`
values could still select a missing key at runtime.
This regression surfaced after d94a739203 remapped `config.agent` keys
to display names without canonicalizing configured defaults.
Normalize configured `default_agent` through display-name mapping before
fallback logic and extend tests to cover canonical and display-name
inputs.
oh-my-opencode overwrote OpenCode's default_agent with sisyphus whenever
Sisyphus orchestration was enabled. This made explicit defaults like
Hephaestus ineffective and forced manual agent switching in new sessions.
Only assign sisyphus as default when default_agent is missing or blank,
and preserve existing configured values. Add tests for both preservation
and fallback behavior to prevent regressions.
When experimental.task_system is enabled, add todowrite: deny and
todoread: deny to per-agent permissions for all primary agents
(sisyphus, hephaestus, atlas, prometheus, sisyphus-junior).
This ensures the model never sees these tools in its tool list,
complementing the existing global tools config and runtime hook.
Previously, demoted plan agent only received { mode: 'subagent' } with no
model settings, causing fallback to step-3.5-flash. Now inherits all
model-related settings (model, variant, temperature, top_p, maxTokens,
thinking, reasoningEffort, textVerbosity, providerOptions) from the
resolved prometheus config. User overrides via agents.plan.* take priority.
Prompt, permission, description, and color are intentionally NOT inherited.
Plan agent demote now only sets mode to 'subagent' without spreading
prometheus config. This ensures plan agent uses OpenCode's default
prompt instead of inheriting prometheus prompt.
* refactor(keyword-detector): split constants into domain-specific modules
* feat(shared): add requiresAnyModel and isAnyFallbackModelAvailable
* feat(config): add hephaestus to agent schemas
* feat(agents): add Hephaestus autonomous deep worker
* feat(cli): update model-fallback for hephaestus support
* feat(plugin): add hephaestus to config handler with ordering
* test(delegate-task): update tests for hephaestus agent
* docs: update AGENTS.md files for hephaestus
* docs: add hephaestus to READMEs
* chore: regenerate config schema
* fix(delegate-task): bypass requiresModel check when user provides explicit config
* docs(hephaestus): add 4-part context structure for explore/librarian prompts
* docs: fix review comments from cubic (non-breaking changes)
- Move Hephaestus from Primary Agents to Subagents (uses own fallback chain)
- Fix Hephaestus fallback chain documentation (claude-opus-4-5 → gemini-3-pro)
- Add settings.local.json to claude-code-hooks config sources
- Fix delegate_task parameters in ultrawork prompt (agent→subagent_type, background→run_in_background, add load_skills)
- Update line counts in AGENTS.md (index.ts: 788, manager.ts: 1440)
* docs: fix additional documentation inconsistencies from oracle review
- Fix delegate_task parameters in Background Agents example (docs/features.md)
- Fix Hephaestus fallback chain in root AGENTS.md to match model-requirements.ts
* docs: clarify Hephaestus has no fallback (requires gpt-5.2-codex only)
Hephaestus uses requiresModel constraint - it only activates when gpt-5.2-codex
is available. The fallback chain in code is unreachable, so documentation
should not mention fallbacks.
* fix(hephaestus): remove unreachable fallback chain entries
Hephaestus has requiresModel: gpt-5.2-codex which means the agent only
activates when that specific model is available. The fallback entries
(claude-opus-4-5, gemini-3-pro) were unreachable and misleading.
---------
Co-authored-by: justsisyphus <justsisyphus@users.noreply.github.com>
- Extract prompt_append from override and append to prompt instead of shallow spread
- Add test verifying prompt_append is appended, not overwriting base prompt
- Fixes#723
Co-authored-by: Gabriel Ečegi <gabriel-ecegi@users.noreply.github.com>
* fix: resolve deadlock in config handler during plugin initialization
The config handler and createBuiltinAgents were calling fetchAvailableModels
with client, which triggers client.provider.list() API call to OpenCode server.
This caused a deadlock because:
- Plugin initialization waits for server response
- Server waits for plugin init to complete before handling requests
Now using cache-only mode by passing undefined instead of client.
If cache is unavailable, the fallback chain will use the first model.
Fixes#1301
* test: add regression tests for deadlock prevention in fetchAvailableModels
Add tests to ensure fetchAvailableModels is called with undefined client
during plugin initialization. This prevents regression on issue #1301.
- config-handler.test.ts: verify config handler does not pass client
- utils.test.ts: verify createBuiltinAgents does not pass client
* test: restore spies in utils.test.ts to prevent test pollution
Add mockRestore() calls for all spies created in test cases to ensure proper cleanup between tests and prevent state leakage.
* test: restore fetchAvailableModels spy
---------
Co-authored-by: robin <robin@watcha.com>
Co-authored-by: justsisyphus <justsisyphus@users.noreply.github.com>
* fix: expand override.category and explicit reasoningEffort priority (#1219)
Two bugs fixed:
1. createBuiltinAgents(): override.category was never expanded into concrete
config properties (model, variant, reasoningEffort, etc.). Added
applyCategoryOverride() helper and applied it in the standard agent loop,
Sisyphus path, and Atlas path.
2. Prometheus config-handler: reasoningEffort/textVerbosity/thinking from
direct override now use explicit priority chains (direct > category)
matching the existing variant pattern, instead of relying on spread
ordering.
Priority order (highest to lowest):
1. Direct override properties
2. Override category properties
3. Resolved variant from model fallback chain
4. Factory base defaults
Closes#1219
* fix: use undefined check for thinking to allow explicit false
Previously, when using categories like 'quick', the parent session's model
(e.g., Opus 4.5) would override the category's built-in model (e.g., Haiku).
Fixed priority: userConfig.model → category built-in → systemDefault
The inherited model from parent session no longer affects category-based
delegation - categories have their own explicit models.
BREAKING CHANGE: Model resolution overhauled
- Created centralized model-resolver.ts with priority chain:
userModel → inheritedModel → systemDefaultModel
- Removed model field from all 7 DEFAULT_CATEGORIES entries
- Removed DEFAULT_MODEL constants from 10 agents
- Removed singleton agent exports (use factories instead)
- Made CategoryConfigSchema.model optional
- CLI no longer generates model overrides
- Empty strings treated as unset (uses fallback)
Users must now:
1. Use factory functions (createOracleAgent, etc.) instead of singletons
2. Provide model explicitly or use systemDefaultModel
3. Configure category models explicitly if needed
Fixes model fallback bug where hardcoded defaults overrode
user's OpenCode configured model.
* fix(config): resolve category to model for Prometheus (Planner) agent
When Prometheus (Planner) was configured with only a category (e.g.,
"ultrabrain") and no explicit model, the category was ignored and the
agent fell back to the hardcoded default "anthropic/claude-opus-4-5".
Add resolveModelFromCategoryWithUserOverride() helper that checks user
categories first, then DEFAULT_CATEGORIES, to resolve category names
to their corresponding models. Apply this resolution when building
the Prometheus agent configuration.
Co-Authored-By: Sisyphus <sisyphus@mengmota.com>
* fix(test): use actual implementation instead of local duplicate
Co-Authored-By: Sisyphus <sisyphus@mengmota.com>
* fix(config): apply all category properties, not just model for Prometheus (Planner)
The resolveModelFromCategoryWithUserOverride() helper only extracted
the model field from CategoryConfig, ignoring critical properties like
temperature, top_p, tools, maxTokens, thinking, reasoningEffort, and
textVerbosity. This caused categories like "ultrabrain" (temperature:
0.1) to run with incorrect default temperatures.
Refactor resolveModelFromCategoryWithUserOverride() to
resolveCategoryConfig() that returns the full CategoryConfig. Update
Prometheus (Planner) configuration to apply all category properties
(temperature, top_p, tools, etc.) when a category is specified, matching
the pattern established in Sisyphus-Junior. Explicit overrides still
take precedence during merge.
Co-Authored-By: Sisyphus <sisyphus@mengmota.com>
---------
Co-authored-by: Sisyphus <sisyphus@mengmota.com>