Previously, migrateConfigFile() mutated rawConfig directly. If the file
write failed (e.g. read-only file, permissions), the in-memory config was
already changed to the migrated values, causing the plugin to use migrated
models even though the user's file was untouched. On the next run, the
migration would fire again since _migrations was never persisted.
Now all mutations happen on a structuredClone copy. The original rawConfig
is only updated after the file write succeeds. If the write fails,
rawConfig stays untouched and the function returns false.
- Use namespace import for connected-providers-cache for better clarity
- Add explicit type annotation for modelsByProvider to improve type safety
- Update tests to reflect refactored module organization
- Improve code organization while maintaining functionality
🤖 Generated with assistance of OhMyOpenCode
Migrate imports from monolithic `model-availability` to split modules
(`model-name-matcher`, `available-models-fetcher`, `model-cache-availability`).
Replace XDG_CACHE_HOME env var manipulation with `mock.module` for
`data-path`, ensuring test isolation without polluting process env.
🤖 Generated with assistance of [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
- Update main AGENTS.md with current file sizes
- Update complexity hotspot line counts
- Update agent count from 11 to 32 files
- Update CLI utility count to 70
- Update test file count from 100+ to 163
🤖 Generated with assistance of OhMyOpenCode
PR #1620 migrated all prompt calls from session.prompt (blocking) to
session.promptAsync (fire-and-forget HTTP 204). This broke look_at which
needs the multimodal-looker response to be available immediately after
the prompt call returns.
Fix: add promptSyncWithModelSuggestionRetry() that uses session.prompt
(blocking) with model suggestion retry support. look_at now uses this
sync variant while all other callers keep using promptAsync.
- Add promptSyncWithModelSuggestionRetry to model-suggestion-retry.ts
- Switch look_at from promptWithModelSuggestionRetry to sync variant
- Add comprehensive tests for the new sync function
- No changes to other callers (delegate-task, background-agent)
- Add _migrations field to OhMyOpenCodeConfigSchema to track applied migrations
- Update migrateModelVersions() to accept appliedMigrations Set and return newMigrations array
- Skip migrations that are already in _migrations (preserves user reverts)
- Update migrateConfigFile() to read/write _migrations field
- Add 8 new tests for migration history tracking
Fixes#1570
Some models (e.g. kimi-k2.5) return tool names with leading spaces
like ' delegate_task', causing tool matching to fail.
Add .trim() in transformToolName() and defensive trim in claude-code-hooks.
Fixes#1568
Fixes#1521. When hook matcher patterns contained regex special characters
like parentheses, the pattern-matcher would throw 'SyntaxError: Invalid
regular expression: unmatched parentheses' because these characters were
not escaped before constructing the RegExp.
The fix escapes all regex special characters (.+?^${}()|[\]\) EXCEPT
the asterisk (*) which is intentionally converted to .* for glob-style
matching.
Add comprehensive test suite for pattern-matcher covering:
- Exact matching (case-insensitive)
- Wildcard matching (glob-style *)
- Pipe-separated patterns
- All regex special characters (parentheses, brackets, etc.)
- Edge cases (empty matcher, complex patterns)
After model version update (opus-4-5 → opus-4-6), several agents had
identical duplicate fallback entries for the same model. The anthropic-only
entry was a superset covered by the broader providers entry, making it dead
code. Consolidate to single entry with all providers.
Hephaestus now appears when any of its providers (openai, github-copilot, opencode) is
connected, rather than requiring the exact gpt-5.2-codex model. This allows users with
newer codex models (e.g., gpt-5.3-codex) to use Hephaestus without manual config overrides.
- Add requiresProvider field to ModelRequirement type
- Add isAnyProviderConnected() helper in model-availability
- Update hephaestus config from requiresModel to requiresProvider
- Update cli model-fallback to handle requiresProvider checks
Add claude-opus-4-6 as the first anthropic provider entry before
claude-opus-4-5 across all agent and category fallback chains.
Also add high variant mapping for think-mode switcher.
Gemini 3 Pro only supports 'low' and 'high' thinking levels according to
Google's official API documentation. The 'max' variant is not supported
and would result in API errors.
Changed variant: 'max' -> 'high' for gemini-3-pro in:
- oracle agent
- metis agent
- momus agent
- ultrabrain category
- deep category
- artistry category
Ref: https://ai.google.dev/gemini-api/docs/thinking-modeCloses#1433
Category delegation fails when provider-models.json contains model objects
with metadata (id, provider, context, output) instead of plain strings.
Line 196 in model-availability.ts assumes string[] format, causing:
- Object concatenation: `${providerId}/${modelId}` becomes "ollama/[object Object]"
- Empty availableModels Set passed to resolveModelPipeline()
- Error: "Model not configured for category"
This is the root cause of issue #1508 where delegate_task(category='quick')
fails despite direct agent routing (delegate_task(subagent_type='explore'))
working correctly.
Changes:
- model-availability.ts: Add type check to handle both string and object formats
- connected-providers-cache.ts: Update ProviderModelsCache interface to accept both formats
- model-availability.test.ts: Add 4 test cases for object[] format handling
Direct agent routing bypasses fetchAvailableModels() entirely, explaining why
it works while category routing fails. This fix enables category delegation
to work with manually-populated Ollama model caches.
Fixes#1508