- Replaced single-provider preferences with ordered priority lists for web search and image generation.
- Added a `MultiSelectSubmenu` component supporting toggle and reordering interactions in settings.
- Implemented migration logic to convert legacy single-provider preferences into ordered priority lists.
- Updated setup wizard scenes, image generation fallback logic, and search provider chains to use priority lists.
Threw ProviderHttpError from generateOpenAIHostedImage so a failing active OpenAI/Codex image call records the failure and continues the provider fallback chain instead of aborting the tool call.
Fixes#5218
Preferred the active session provider after any explicit image preference and retained the configured auto order for remaining candidates.
Continued to the next credentialed image provider after HTTP failures.
Fixes#5218
- Made GenerateImage omit chatgpt-account-id when Codex bearer tokens do not expose an account id.
- Added Codex hosted image coverage for opaque proxy keys and JWT-derived account headers.
Fixes#5174
The generate_image tool gains an optional 'provider' param
(auto|openai|openai-codex|antigravity|xai|gemini|openrouter): say the
provider in chat and the tool uses it for that call; absent, it falls back
to the providers.image setting, then auto-detect. openai-codex now works
INDEPENDENT of the active chat model: a connected Codex (ChatGPT OAuth)
subscription drives OpenAI's hosted image_generation tool (model priority
gpt-5.5 -> gpt-5.4 -> gpt-5.1 -> gpt-5 -> gpt-5-codex), so images ride the
subscription instead of the metered API key. providers.image accepts
openai-codex. (Recovered from parked lane dbf87cd04; oauth.html rebrand
left parked.)
Migrate 203 test files (356 call sites) from fs.rm/fs.rmSync to
removeWithRetries/removeSyncWithRetries to reduce EBUSY test failures
on Windows. removeWithRetries is now exported from @oh-my-pi/pi-utils.
The migration uses a regex-based approach that:
- Replaces fs.rm(path, { recursive, force }) → removeWithRetries(path)
- Replaces fs.rmSync(path, { recursive, force }) → removeSyncWithRetries(path)
- Replaces fs.rm(path) → removeWithRetries(path) (no options)
- Skips fs.rm/fs.rmSync inside template literals (bun --eval scripts)
- Adds imports to existing @oh-my-pi/pi-utils import or creates new one
- Removes unused fs imports where fs.rm was the only fs usage (4 files)
Stopped image tool registration from resolving provider credentials during session startup. Added coverage that registration stays lazy while execution still resolves credentials.
Fixes#3036
- Added optional FetchImpl fields to compaction, proxy, AI, coding-agent, and mnemopi options.
- Threaded injected fetch implementations through OAuth, discovery, and search/LLM request flows.
- Removed exported hookFetch utility and its package entrypoint from utils.
- Replaced global-fetch test monkeypatching with per-test FetchImpl mocks across test suites.
- Routed image-gen, inspect-image, and web search providers through `withAuth`.
- Used `reuseInitialApiKey`/`createAuthStorageResolver` for force-refresh and rotate retries.
- Attached HTTP status to thrown errors so the retry classifier detects retryable failures.
The Surface 1 commit added authStorage.hasNonEnvCredential as a credential
gate inside resolveXAIHttpCredentials, and the Surface 3 commit added
resolveXAIBaseURL which consults getProviderBaseUrl and getAll. The
existing image-gen xAI test mocked only getApiKeyForProvider on
modelRegistry, so the new code paths threw "undefined is not an object"
at runtime.
Add the missing mock surface:
- authStorage.hasNonEnvCredential returns true for "xai-oauth" so the
dedicated-credential gate routes through the xai-oauth branch (which
the test's getApiKeyForProvider mock services).
- getProviderBaseUrl returns undefined so resolveXAIBaseURL falls
through to the XAI_BASE_URL / DEFAULT_BASE_URL leg, preserving the
test's existing expectation that the request hits
https://api.x.ai/v1/images/generations.
- getAll returns [] so the per-model override check in
resolveXAIBaseURL no-ops cleanly.
Op: correct
Restores: ref:feat/xai-grok-oauth@015437534 ref:feat/xai-grok-oauth@2c1abd7fa
- Added `extraBody` merging into OpenAI Responses request params.
- Fixed xAI OAuth redirect URI to fail fast on port conflicts.
- Exposed `antigravity` and `xai` as explicit `providers.image` options.
- Added `isImageProviderPreference` guard, replacing inline string checks.
- Fixed TTS tool to resolve output path relative to cwd and require write approval.
- Removed export leakage by demoting many helper and const symbols to module-local scope.
- Renamed underscore-prefixed internals and cache fields, then updated related references and `satisfies never` checks.
- Deleted obsolete logic branches and helpers, including harmony-stream interruption flow and unused benchmark runtime helpers.
- Updated Biome config and manifests by broadening lint coverage and removing an unused `@napi-rs/cli` dev dependency.
- Adjusted tests and utilities to use renamed test helpers and remove redundant private test-only helpers/locals.
- Updated OpenAI completion request construction to include OpenRouter attribution headers and always-on cache directives (1h TTL).
- Updated image-generation requests to replace legacy X-Title with OpenRouter-specific HTTP-Referer, title, and category headers.
- Removed old OpenRouter X-Title defaults from provider options and removed the matching image-gen header assertion test.
- Added `openai` and `openai-codex` as image providers and let `providers.image=auto` prefer GPT images.
- Updated settings, selector, and SDK wiring so OpenAI image providers pass through `setPreferredImageProvider`.
- Replaced Gemini-only image tooling with `image-gen` and added OpenAI/Codex hosted-image execution with SSE parsing.
- Added image-gen and handoff tests, including final-yield no-compaction regression and OpenAI payload/header assertions.