-
-
Notifications
You must be signed in to change notification settings - Fork 192
Fix Docker provider fallback and auth error handling #168
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
friuns2
wants to merge
16
commits into
main
Choose a base branch
from
codex/runtime-zen-no-persist
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 13 commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
9a4fece
Avoid persisting unauthenticated Zen fallback
friuns 91f8562
Rename custom provider state file
friuns 545c0de
Handle pending first-turn live state
friuns 2eaf4bd
Load provider models before Codex model list
friuns 6405a6e
Document Zen Docker auth model fixes
friuns abbc073
Show failed auth turn errors in chat
friuns 7771c39
Add feedback action to auth errors
friuns 9f32963
Hide duplicate persisted auth error overlay
friuns dbb820f
Document Docker provider auth regression workflow
friuns aa10f66
Add provider auth test checklist
friuns 8d63a4d
Fix live error overlay de-duplication
friuns 7ee94f8
Promote copied auth to Codex provider
friuns 4d62f2c
Update wiki for copied auth provider promotion
friuns dfc0bd0
Fix Docker provider fallback runtime tests
friuns d939a17
Address provider review findings
friuns b51f44e
Fix turn error id collisions
friuns File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| # Copied Auth Provider Promotion Fix | ||
|
|
||
| Date: 2026-05-13 | ||
|
|
||
| ## Problem | ||
|
|
||
| In Docker no-auth mode, Codex Web Local starts with an OpenCode Zen runtime fallback. If the user switched the provider to OpenRouter while unauthenticated and then copied a valid `auth.json` into the mounted `CODEX_HOME`, the UI detected Codex auth but kept stale community-provider state. | ||
|
|
||
| Observed issues: | ||
| - Provider stayed on OpenRouter after valid Codex auth appeared. | ||
| - The Accounts badge stayed at `0` until a manual account refresh. | ||
| - The new-thread composer could show a generic `Model` label after provider promotion. | ||
| - The Settings feedback row could show stale `Send feedback / Issue detected` after recovery even when there was no visible current error. | ||
| - Sending on Codex worked after manually switching provider, proving the copied auth file was valid. | ||
|
|
||
| ## Root Cause | ||
|
|
||
| The server read `webui-custom-providers.json` as authoritative whenever it existed. That file can contain community fallback provider state created during the unauthenticated phase. After `auth.json` appeared, the fallback provider state still supplied app-server provider flags and `/codex-api/free-mode/status` data. | ||
|
|
||
| The frontend also relied on the accounts snapshot for the Accounts count. A copied `auth.json` did not automatically import the active auth file into the accounts store. | ||
|
|
||
| Finally, provider-scoped new-thread model persistence applied to non-Codex providers but not to Codex. After provider promotion, the home composer could temporarily fall back to the generic `Model` placeholder instead of a concrete Codex model. | ||
|
|
||
| ## Fix | ||
|
|
||
| Commit: | ||
| - `7ee94f83 Promote copied auth to Codex provider` | ||
|
|
||
| Implementation details: | ||
| - Added `shouldSuppressCommunityFreeModeForCodexAuth()` in `src/server/freeMode.ts`. | ||
| - `ensureDefaultFreeModeStateForMissingAuthSync()` now returns `null` when usable Codex auth exists and the existing provider state is only community fallback (`openrouter` or `opencode-zen` without a custom key). | ||
| - User-configured providers are preserved: | ||
| - OpenRouter with `customKey: true` | ||
| - OpenCode Zen with an explicit API key | ||
| - Custom endpoint provider | ||
| - `/codex-api/free-mode/status` now reports `hasCodexAuth`. | ||
| - `App.vue` uses `hasCodexAuth` to import a copied active `auth.json` into Accounts via `refreshAccountsFromAuth()` once. | ||
| - New-thread model persistence now uses provider-scoped slots for Codex as well as non-Codex providers. | ||
| - The Settings feedback row is shown only when a current visible error exists, not merely because historical diagnostics exist. | ||
|
|
||
| ## Docker Validation | ||
|
|
||
| Fresh packaged image: | ||
|
|
||
| ```text | ||
| codexui-local:e5e9-auth-promote-final2 | ||
| ``` | ||
|
|
||
| Flow: | ||
| 1. Start a fresh container with empty mounted `CODEX_HOME`. | ||
| 2. Confirm initial provider is `opencode-zen`. | ||
| 3. Switch provider to `openrouter`. | ||
| 4. Copy `/Users/igor/.codex/auth.json` into the mounted `CODEX_HOME`. | ||
| 5. Reload the UI. | ||
| 6. Confirm provider changes to `codex`. | ||
| 7. Confirm Accounts count becomes `1`. | ||
| 8. Confirm the composer shows a concrete Codex model, not generic `Model`. | ||
| 9. Confirm no stale `Send feedback / Issue detected` row appears. | ||
| 10. Send `hi`; wait for a Codex reply. | ||
|
|
||
| Final validation result: | ||
|
|
||
| ```json | ||
| { | ||
| "initialProvider": "opencode-zen", | ||
| "afterSwitchProvider": "openrouter", | ||
| "afterCopyProvider": "codex", | ||
| "afterCopyAccounts": 1, | ||
| "afterCopyHasIssue": false, | ||
| "finalProvider": "codex", | ||
| "finalHasIssue": false, | ||
| "stillBusy": false | ||
| } | ||
| ``` | ||
|
|
||
| Screenshot artifacts: | ||
| - `output/playwright/auth-promote-final2-01-noauth.png` | ||
| - `output/playwright/auth-promote-final2-02-openrouter.png` | ||
| - `output/playwright/auth-promote-final2-03-after-copy.png` | ||
| - `output/playwright/auth-promote-final2-04-reply.png` | ||
|
|
||
| ## Verification Commands | ||
|
|
||
| ```bash | ||
| pnpm test:unit src/server/freeMode.test.ts src/server/codexAppServerBridge.archive.test.ts src/composables/useDesktopState.test.ts src/api/codexGateway.test.ts | ||
| pnpm run build | ||
| pnpm pack --pack-destination /tmp | ||
| ``` |
78 changes: 78 additions & 0 deletions
78
llm-wiki/raw/fixes/opencode-zen-docker-auth-provider-models.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| # OpenCode Zen Docker Auth and Provider Models Fix | ||
|
|
||
| Date: 2026-05-13 | ||
|
|
||
| ## Problem | ||
|
|
||
| Codex Web Local had two Docker startup edge cases around OpenCode Zen fallback and Codex auth: | ||
|
|
||
| 1. In an authenticated Docker container, immediately polling `/codex-api/thread-live-state` after `turn/start` could return: | ||
|
|
||
| ```text | ||
| thread <id> is not materialized yet; includeTurns is unavailable before first user message | ||
| ``` | ||
|
|
||
| The turn completed normally, but the bridge exposed this transient Codex state as `liveStateError.kind = "readFailed"`, making the chat look broken during first-turn startup. | ||
|
|
||
| 2. In an unauthenticated Docker container, the model selector could appear empty or stale because frontend model loading called Codex `model/list` before `/codex-api/provider-models`. In OpenCode Zen fallback mode, provider models are authoritative; `model/list` can be slow, return Codex models, or fail independently. | ||
|
|
||
| ## Root Cause | ||
|
|
||
| The live-state endpoint treated every `thread/read includeTurns=true` failure as a real read failure. Codex can briefly create a thread before the first user message is materialized, so that exact error is a pending state, not a terminal failure. | ||
|
|
||
| The model-loading helper fetched `model/list` first and only then attempted provider model discovery. This made no-auth Zen startup depend on a Codex model-list call that is not the source of truth for Zen models. | ||
|
|
||
| ## Fix | ||
|
|
||
| Commits: | ||
| - `545c0dec Handle pending first-turn live state` | ||
| - `2eaf4bd3 Load provider models before Codex model list` | ||
|
|
||
| Implementation details: | ||
| - Added `isThreadMaterializationPendingError()` in `src/server/codexAppServerBridge.ts`. | ||
| - `/codex-api/thread-live-state` now maps that specific pending-materialization error to: | ||
| - `conversationState: { turns: [] }` | ||
| - `liveStateError: null` | ||
| - `isInProgress: true` | ||
| - Real `thread/read` failures still surface through `liveStateError`. | ||
| - `getAvailableModelIds()` now fetches `/codex-api/provider-models` first when provider models are included. | ||
| - If provider models are `exclusive` or `requireProviderModels` is true, it returns provider models without waiting on Codex `model/list`. | ||
| - Optional provider-model loading still falls back to `model/list` if provider models are unavailable. | ||
|
|
||
| ## Docker Validation | ||
|
|
||
| Fresh image: | ||
|
|
||
| ```text | ||
| codexui-local:e5e9-current | ||
| ``` | ||
|
|
||
| No-auth container: | ||
| - URL: `http://127.0.0.1:4191/#/` | ||
| - `config/read`: `model = "big-pickle"`, `model_provider = "opencode-zen"` | ||
| - App-server command includes Zen proxy flags. | ||
| - Sending `hi` returns an assistant reply. | ||
| - Model selector includes `big-pickle`, `deepseek-v4-flash-free`, and other Zen provider models. | ||
|
|
||
| Auth-mounted container: | ||
| - URL: `http://127.0.0.1:4192/#/` | ||
| - Mounted `/Users/igor/.codex/auth.json` to `/codex-home/auth.json`. | ||
| - `config/read`: `model = null`, `model_provider = null` | ||
| - App-server command has no Zen proxy flags. | ||
| - Sending `hi` returns an assistant reply. | ||
| - First-turn live-state polling does not expose the transient materialization error as `liveStateError`. | ||
|
|
||
| ## Operational Notes | ||
|
|
||
| - For Docker validation, install the packed `codexapp` artifact during image build instead of using `pnpm dlx` at container runtime. Runtime `pnpm dlx` can re-download and extract dependencies on every start and can be killed under memory pressure. | ||
| - When validating no-auth Zen mode, trust `/codex-api/provider-models` and `/codex-api/free-mode/status` for provider models; `model/list` may still return Codex catalog rows from the Codex CLI. | ||
| - Browser verification should include a screenshot of the opened model selector after loading `http://127.0.0.1:4191/#/`. | ||
|
|
||
| ## Verification Commands | ||
|
|
||
| ```bash | ||
| pnpm test:unit src/server/codexAppServerBridge.archive.test.ts | ||
| pnpm test:unit src/api/codexGateway.test.ts src/composables/useDesktopState.test.ts | ||
| pnpm run build | ||
| ``` | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1. Wiki log entry not appended
📘 Rule violation◔ ObservabilityAgent Prompt
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools