feat: add OpenAI Codex OAuth login and Z.AI Coding Plan quick-setup#537
feat: add OpenAI Codex OAuth login and Z.AI Coding Plan quick-setup#537alchemistklk merged 4 commits intomainfrom
Conversation
Add alternative authentication methods on the provider settings page: **OpenAI Codex OAuth:** - "Login with ChatGPT" button on the OpenAI provider panel - PKCE OAuth flow via auth.openai.com (fixed port 1455) - Writes OAuth tokens to OpenClaw's auth-profiles.json - OpenClaw auto-refreshes tokens — no Nexu refresh timer needed - Config compiler maps openai/* → openai-codex/* for OAuth users - Runtime model resolver trusts openai-codex/ refs from auth-profiles **Z.AI Coding Plan:** - Quick-setup section on GLM provider panel with region toggle (Global/CN) - Global: api.z.ai/api/coding/paas/v4 - CN: open.bigmodel.cn/api/coding/paas/v4 - Pre-fills base URL and known free models (glm-5, glm-4.7, etc.) **Auth profiles writer fix:** - Read-merge-write instead of overwrite to preserve OAuth profiles - Prevents sync loop from destroying OpenClaw-managed tokens Includes unit tests, Playwright E2E specs, and test plan document.
📝 WalkthroughWalkthroughAdds OpenAI Codex OAuth: new controller routes, an OpenClawAuthService implementing PKCE + local callback, persistence/merge of OAuth profiles into per-agent auth stores, OAuth-aware model resolution and sync, frontend SDK/types/UI updates, tests, and schema/validation tweaks (nullable provider apiKey, stricter SkillHub slug pattern). Changes
Sequence Diagram(s)sequenceDiagram
participant WebUI
participant Controller
participant OpenClawAuthService as AuthSvc
participant OpenAI
participant FS as "Agent FS"
participant ModelSvc
participant SyncSvc
WebUI->>Controller: POST /api/v1/providers/{id}/oauth/start
Controller->>AuthSvc: startOAuthFlow(providerId)
AuthSvc-->>Controller: { browserUrl }
Controller-->>WebUI: { browserUrl }
note over WebUI,OpenAI: User authenticates in browser
OpenAI->>AuthSvc: GET /auth/callback?code=...&state=...
AuthSvc->>AuthSvc: validate state, exchange code (token endpoint)
AuthSvc->>FS: merge/write OAuth profile into agent auth-profiles.json
AuthSvc-->>Controller: mark flow completed
loop polling
WebUI->>Controller: GET /api/v1/providers/{id}/oauth/status
Controller->>AuthSvc: getFlowStatus()
AuthSvc-->>Controller: { status:"completed", models:[...] }
Controller->>ModelSvc: upsertProvider(... apiKey: null, modelsJson ...)
Controller->>SyncSvc: syncAll()
Controller-->>WebUI: { status:"completed", models:[...] }
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 722c46a4ff
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
Actionable comments posted: 10
🧹 Nitpick comments (2)
apps/controller/src/services/openclaw-sync-service.ts (1)
59-61: Keep the OAuth provider mapping in one source of truth.
OAUTH_PROVIDER_PREFIXEShere now has to stay aligned withOAUTH_PROVIDER_MAPinapps/controller/src/lib/openclaw-config-compiler.ts:265-267. If one side changes without the other, compile-time and runtime model resolution will drift silently. Please extract the mapping into a shared helper/constant.Also applies to: 71-75
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/controller/src/services/openclaw-sync-service.ts` around lines 59 - 61, OAUTH_PROVIDER_PREFIXES is duplicated and must be the single source of truth; extract the mapping into a shared constant (e.g., export const OAUTH_PROVIDER_PREFIXES or OAUTH_PROVIDER_MAP in a new shared module like openclaw-oauth-constants) and replace the local definitions in both openclaw-sync-service.ts (const OAUTH_PROVIDER_PREFIXES) and openclaw-config-compiler.ts (OAUTH_PROVIDER_MAP) to import and use that shared export so runtime and compile-time model resolution stay in sync; ensure the exported name is descriptive and update all references in both files to use the imported symbol.docs/plans/2026-03-24-oauth-model-persistence.md (1)
11-11: Prefer a repo-relative worktree reference instead of an absolute local path.Line 11 hardcodes a machine-specific path, which is not reusable by other contributors.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/plans/2026-03-24-oauth-model-persistence.md` at line 11, Replace the machine-specific absolute worktree path on line 11 with a repo-relative reference; change the hardcoded "/Users/alche/Documents/digit-sutando/nexu/.worktrees/openai-oauth" to a relative path such as ".worktrees/openai-oauth" or "./.worktrees/openai-oauth" and keep the branch name `feat/openai-codex-oauth` intact so contributors can use the same worktree reference across machines.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/controller/src/lib/openclaw-config-compiler.ts`:
- Around line 263-275: The code currently treats provider.apiKey === null as
“OAuth connected” and rewrites openai → openai-codex; change this to check a
persisted OAuth connection flag instead. In the block that uses
OAUTH_PROVIDER_MAP, oauthTarget and provider (from config.providers.find by
providerId), replace the apiKey === null gate with a check for a persisted
connection indicator on the provider (for example provider.oauthConnected ===
true or provider.connection?.profileId != null or provider.profile?.id != null
depending on your model for persisted OAuth state). Ensure you only return
`${oauthTarget}/${modelSuffix}` when provider.enabled is true AND the provider
has that persisted OAuth connection flag set (not merely apiKey === null).
In `@apps/controller/src/routes/provider-oauth-routes.ts`:
- Around line 67-81: Don't call container.openclawAuthService.consumeCompleted()
before persisting the provider and syncing; consumeCompleted() clears the
in-memory completion state too early. Change the flow in the completed branch so
you first compute models (using completed.models or OPENAI_CODEX_KNOWN_MODELS),
then call container.modelProviderService.upsertProvider(providerId, ...) and
await container.openclawSyncService.syncAll(), and only after both succeed call
container.openclawAuthService.consumeCompleted() and return c.json({
...flowStatus, models }, 200); alternatively implement a transactional
consumeCompleted() variant that only clears state after upsertProvider and
syncAll complete successfully.
In `@apps/controller/src/runtime/openclaw-auth-profiles-writer.ts`:
- Around line 19-45: readExistingProfiles currently swallows all read/parse
errors which can turn transient partial reads into full clobbers; change
readExistingProfiles to only return null for ENOENT and to rethrow other errors
(including JSON.parse failures) so callers can decide how to proceed. Add a
shared per-file lock/single-writer helper (e.g., withFileLock or a Mutex keyed
by "auth-profiles.json") and use it from both writeForAgents and
OpenClawAuthService.mergeOAuthProfile so the read-modify-write cycle for
auth-profiles.json is serialized; move the read->modify->write logic inside the
locked callback and ensure mergeOAuthProfile and writeForAgents call that
helper.
In `@apps/controller/src/services/openclaw-auth-service.ts`:
- Around line 473-526: findAgentAuthProfilesPath currently returns the
auth-profiles.json for the "first directory wins" agent which makes
readAuthProfiles and writeAuthProfiles nondeterministic in multi-agent setups;
change the logic so the target agent is resolved explicitly (preferred) or
updates are fanned out to every agent directory: update
findAgentAuthProfilesPath to accept an agent identifier (or provide a new
findAllAgentAuthProfilesPaths helper) and have readAuthProfiles/readAuthProfiles
use that explicit path(s); alternatively implement a loop in writeAuthProfiles
that writes the same JSON to every path returned by a new
findAllAgentAuthProfilesPaths, and make readAuthProfiles deterministic by
reading a specified agent path or merging/validating all agent files
consistently.
- Around line 528-543: mergeOAuthProfile is doing an unlocked read-modify-write
(readAuthProfiles -> writeAuthProfiles) which races with the new sync writer;
serialize updates by acquiring the same global/shared writer lock or delegating
all mutations to the single-writer helper in openclaw-auth-profiles-writer
(instead of calling writeAuthProfiles directly). Wrap the entire
read/merge/write sequence in the shared lock API provided by
apps/controller/src/runtime/openclaw-auth-profiles-writer.ts (or call its single
writer method) so mergeOAuthProfile (function name) uses that lock/entrypoint
and prevents concurrent clobbering of auth-profiles.json.
- Around line 95-101: Validate the incoming state before processing the error
branch in the OAuth callback: in the callback handler, check that the request's
state matches the stored/expected state and reject or ignore the request (return
400) if it does not, before reading error_description; additionally,
sanitize/escape any user-provided text passed into errorHtml by HTML-escaping
characters (use a small utility that replaces &, <, >, ", ' with entities) and
pass the escaped string into errorHtml instead of raw error_description; apply
the same state-first validation and escaping to the other error-handling branch
in this file as well.
- Around line 242-251: When removing the profileKey ("openai-codex:default")
from existing.profiles in disconnect logic, also clear any stale lastGood
pointer that references that profile: check existing.lastGood and if it equals
profileKey (or if lastGood points to a profile key that no longer exists in
remainingProfiles) remove or set updated.lastGood to undefined/null so
AuthProfilesData stays consistent; update the same updated object created after
computing remainingProfiles (references: profileKey, existing,
remainingProfiles, updated, lastGood).
In `@apps/web/src/pages/models.tsx`:
- Around line 1285-1356: The queries and mutations currently coerce missing
backend responses into harmless defaults, which hides failures and can leave
oauthPending spinning; update the oauthProviderStatus and oauthFlowStatus
queryFn functions to treat missing or error responses as failures by throwing an
error when res.data is undefined or indicates an error (instead of returning
{connected:false} or {status:"idle"}), and update startOAuthMutation.mutationFn
and disconnectOAuthMutation.mutationFn to validate res.data and throw when the
response is missing or contains an error so React Query routes to onError rather
than onSuccess; keep the existing enabled/refetchInterval logic and ensure the
useEffect still reads oauthFlowStatus.data after failures are surfaced via
react-query errors.
In `@docs/plans/2026-03-24-oauth-model-persistence.md`:
- Line 15: Several task headings (for example "Task 1: Add `models` field to
OAuth status response schema" and the other task headings noted in the review)
are using level-3 headings (###) directly under the document's top-level #
header, causing a heading-level jump; change those task headings from ### to
level-2 (##) so the structure is # then ## for tasks, and scan the file for the
other task headings mentioned (the ones at the other commented locations) and
update them similarly to maintain consistent hierarchical markdown structure.
In `@docs/plans/2026-03-24-openai-oauth-test-plan.md`:
- Around line 35-36: Update the test plan so callback behavior no longer assumes
model-fetch during the OAuth callback: change table rows for cases 11 and 12 to
remove "Mock `fetch` for token + models endpoints" and instead assert that on a
valid callback the status becomes "completed" and the user's profile is
populated while models are NOT populated at callback (models are populated later
via the known-model persistence flow), and for the state-mismatch case assert
status "failed" with a CSRF error and no model-fetch attempt; apply the same
adjustments to the corresponding section covering lines 59-67 so all
expectations reflect the no-fetch callback flow.
---
Nitpick comments:
In `@apps/controller/src/services/openclaw-sync-service.ts`:
- Around line 59-61: OAUTH_PROVIDER_PREFIXES is duplicated and must be the
single source of truth; extract the mapping into a shared constant (e.g., export
const OAUTH_PROVIDER_PREFIXES or OAUTH_PROVIDER_MAP in a new shared module like
openclaw-oauth-constants) and replace the local definitions in both
openclaw-sync-service.ts (const OAUTH_PROVIDER_PREFIXES) and
openclaw-config-compiler.ts (OAUTH_PROVIDER_MAP) to import and use that shared
export so runtime and compile-time model resolution stay in sync; ensure the
exported name is descriptive and update all references in both files to use the
imported symbol.
In `@docs/plans/2026-03-24-oauth-model-persistence.md`:
- Line 11: Replace the machine-specific absolute worktree path on line 11 with a
repo-relative reference; change the hardcoded
"/Users/alche/Documents/digit-sutando/nexu/.worktrees/openai-oauth" to a
relative path such as ".worktrees/openai-oauth" or "./.worktrees/openai-oauth"
and keep the branch name `feat/openai-codex-oauth` intact so contributors can
use the same worktree reference across machines.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 9a8cb3f9-1a3c-4160-8f3f-297e5dff4c56
📒 Files selected for processing (18)
apps/controller/openapi.jsonapps/controller/src/app/container.tsapps/controller/src/app/create-app.tsapps/controller/src/lib/openclaw-config-compiler.tsapps/controller/src/routes/provider-oauth-routes.tsapps/controller/src/runtime/openclaw-auth-profiles-writer.tsapps/controller/src/services/openclaw-auth-service.tsapps/controller/src/services/openclaw-sync-service.tsapps/web/e2e/openai-oauth.spec.tsapps/web/lib/api/sdk.gen.tsapps/web/lib/api/types.gen.tsapps/web/src/i18n/locales/en.tsapps/web/src/i18n/locales/zh-CN.tsapps/web/src/pages/models.tsxdocs/plans/2026-03-24-oauth-model-persistence.mddocs/plans/2026-03-24-openai-oauth-test-plan.mdpackages/shared/src/schemas/provider.tstests/controller/openclaw-auth-service.test.ts
Address Codex review findings: - Explicitly pass apiKey: null when OAuth completes so any previously saved API key is cleared. Updated config store merge to treat null as an explicit clear instead of "keep existing". - Auth service now reads/writes/disconnects OAuth profiles across all agent workspace directories, not just the first one found. Prevents bot-specific auth failures in multi-bot setups. - Added regression tests for both fixes.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
apps/controller/tests/provider-oauth-routes.test.ts (1)
8-55: Consider extracting shared test utilities.The
createEnvhelper is duplicated between this file andopenclaw-auth-service.test.ts. Consider extracting it to a shared test fixture file (e.g.,apps/controller/tests/fixtures/test-env.ts) to reduce maintenance burden and ensure consistency.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/controller/tests/provider-oauth-routes.test.ts` around lines 8 - 55, The createEnv helper is duplicated across tests; extract it into a single shared test fixture (e.g., export function createEnv(rootDir: string): ControllerEnv from a new tests/fixtures/test-env module), export the ControllerEnv type if needed, and replace the duplicate implementations in provider-oauth-routes.test and openclaw-auth-service.test with an import of the shared createEnv function; ensure both tests update their imports to reference the new fixture and that the function signature and returned keys remain unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/controller/openapi.json`:
- Around line 4848-4850: The OpenAPI 3.1 schema for the apiKey property still
uses the removed "nullable": true; update the apiKey schema (the "apiKey"
property in the OpenAPI document) to express nullability using a union type by
replacing "type": "string" and "nullable": true with a JSON Schema
3.1-compatible null union such as "type": ["string","null"] so SDKs will honor
sending null to clear the saved key.
---
Nitpick comments:
In `@apps/controller/tests/provider-oauth-routes.test.ts`:
- Around line 8-55: The createEnv helper is duplicated across tests; extract it
into a single shared test fixture (e.g., export function createEnv(rootDir:
string): ControllerEnv from a new tests/fixtures/test-env module), export the
ControllerEnv type if needed, and replace the duplicate implementations in
provider-oauth-routes.test and openclaw-auth-service.test with an import of the
shared createEnv function; ensure both tests update their imports to reference
the new fixture and that the function signature and returned keys remain
unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 4eec8ea3-18af-4919-9516-4eee20a00407
📒 Files selected for processing (8)
apps/controller/openapi.jsonapps/controller/src/routes/provider-oauth-routes.tsapps/controller/src/services/openclaw-auth-service.tsapps/controller/src/store/nexu-config-store.tsapps/controller/tests/nexu-config-store.test.tsapps/controller/tests/openclaw-auth-service.test.tsapps/controller/tests/provider-oauth-routes.test.tspackages/shared/src/schemas/provider.ts
✅ Files skipped from review due to trivial changes (1)
- apps/controller/tests/nexu-config-store.test.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- apps/controller/src/routes/provider-oauth-routes.ts
- packages/shared/src/schemas/provider.ts
- apps/controller/src/services/openclaw-auth-service.ts
Deploying nexu-docs with
|
| Latest commit: |
c482fef
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://4079c61a.nexu-docs.pages.dev |
| Branch Preview URL: | https://feat-openai-codex-oauth.nexu-docs.pages.dev |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
apps/web/src/pages/models.tsx (1)
1328-1337: Consider addingproviderIdto the effect's dependency array.The effect relies on
meta.defaultProxyUrlchanging to trigger reset when the provider changes. While this works because each provider has a uniquedefaultProxyUrl, explicitly includingproviderIdwould make the intent clearer and avoid potential issues if two providers ever share the same URL.Suggested fix
useEffect(() => { setApiKey(""); setBaseUrl(dbProvider?.baseUrl ?? meta.defaultProxyUrl ?? ""); setIsEditingApiKey(!dbProvider?.hasApiKey); setVerifiedModels(null); setOauthPending(false); setCodingPlanKey(""); setCodingPlanRegion("global"); - }, [dbProvider, meta.defaultProxyUrl]); + }, [providerId, dbProvider, meta.defaultProxyUrl]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/web/src/pages/models.tsx` around lines 1328 - 1337, The reset useEffect that calls setApiKey, setBaseUrl, setIsEditingApiKey, setVerifiedModels, setOauthPending, setCodingPlanKey, and setCodingPlanRegion currently depends on [dbProvider, meta.defaultProxyUrl]; update the dependency array to also include providerId so the effect explicitly re-runs when the selected provider changes (keeps the same reset logic in the useEffect tied to dbProvider, meta.defaultProxyUrl, and providerId).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/web/src/pages/models.tsx`:
- Around line 1273-1279: The onSuccess callback currently calls
window.open(data.browserUrl, "_blank") in the OAuth flow; update that call to
pass the third feature string "noopener,noreferrer" (i.e.,
window.open(data.browserUrl, "_blank", "noopener,noreferrer")) to prevent the
opened page from accessing window.opener, leaving the rest of the logic
(setOauthPending(true) and toast.error(data.error)) unchanged; locate this
change in the onSuccess handler where window.open, setOauthPending, and
toast.error are referenced.
- Around line 1307-1326: The saveCodingPlanMutation currently has no error
handler so failures from saveProvider leave the UI silent; add an onError
handler on saveCodingPlanMutation that captures the error from saveProvider and
surfaces user feedback (e.g., set an error state or call a toast/notification)
and ensures UI state cleanup (e.g., do not clear codingPlanKey or call
markSetupComplete/onAutoSelectModel on failure). Locate saveCodingPlanMutation
and implement onError to accept the error, log/report it, update any local error
state or show a notification, and avoid running the success-side effects
(setCodingPlanKey, markSetupComplete, onAutoSelectModel) when an error occurs.
---
Nitpick comments:
In `@apps/web/src/pages/models.tsx`:
- Around line 1328-1337: The reset useEffect that calls setApiKey, setBaseUrl,
setIsEditingApiKey, setVerifiedModels, setOauthPending, setCodingPlanKey, and
setCodingPlanRegion currently depends on [dbProvider, meta.defaultProxyUrl];
update the dependency array to also include providerId so the effect explicitly
re-runs when the selected provider changes (keeps the same reset logic in the
useEffect tied to dbProvider, meta.defaultProxyUrl, and providerId).
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 3cd105d2-f79d-4a92-9d6f-db0bad236bc5
📒 Files selected for processing (6)
apps/controller/src/app/create-app.tsapps/controller/src/lib/openclaw-config-compiler.tsapps/controller/src/store/nexu-config-store.tsapps/web/src/i18n/locales/en.tsapps/web/src/i18n/locales/zh-CN.tsapps/web/src/pages/models.tsx
✅ Files skipped from review due to trivial changes (2)
- apps/web/src/i18n/locales/en.ts
- apps/web/src/i18n/locales/zh-CN.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- apps/controller/src/app/create-app.ts
- apps/controller/src/store/nexu-config-store.ts
- apps/controller/src/lib/openclaw-config-compiler.ts
Replace implicit apiKey === null detection with explicit OAuthConnectionState derived from auth-profiles.json files. - New OpenClawAuthProfilesStore: shared serialized store for reading/writing auth profiles across all agent workspaces - OAuthConnectionState passed into config compiler and sync service - Model ID remap (openai → openai-codex) now gated by actual connected OAuth profiles, not inferred from missing API key - Per-file serial queue prevents race conditions on concurrent writes - Malformed auth-profiles.json treated as hard errors instead of silently rebuilding from empty - Regression tests for store, compiler, and route behavior
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
apps/controller/tests/openclaw-config-compiler.test.ts (1)
223-248: Consider extracting a shared OpenAI config fixture.Both tests construct nearly identical config payloads. A small helper would reduce duplication and future drift.
Also applies to: 265-288
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/controller/tests/openclaw-config-compiler.test.ts` around lines 223 - 248, Tests around compileOpenClawConfig and createConfig duplicate nearly identical OpenAI config payloads (bots, runtime.defaultModelId, providers.models, etc.); extract a shared fixture/helper (e.g., createOpenAIConfigFixture or openaiConfigPayload) that builds the common config and accept small overrides for bot/model/provider differences, then replace the duplicated inline objects in the tests with calls to that helper to reduce duplication and future drift.apps/controller/src/services/openclaw-sync-service.ts (1)
62-78: Consider extracting OAUTH_PROVIDER_PREFIXES from the canonical OAUTH_PROVIDER_MAP.The
OAUTH_PROVIDER_PREFIXESarray duplicates knowledge of OAuth provider output prefixes that's already defined inOAUTH_PROVIDER_MAPwithinopenclaw-config-compiler.ts. If additional OAuth providers are added to the map (e.g.,google: "google-oauth"), this array must be updated manually.♻️ Proposed approach
Export the map values from the compiler and derive prefixes:
// In openclaw-config-compiler.ts, export: export const OAUTH_PROVIDER_MAP: Record<string, string> = { openai: "openai-codex", }; // In openclaw-sync-service.ts: import { OAUTH_PROVIDER_MAP } from "../lib/openclaw-config-compiler.js"; const OAUTH_PROVIDER_PREFIXES = Object.values(OAUTH_PROVIDER_MAP).map( (p) => `${p}/`, );🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/controller/src/services/openclaw-sync-service.ts` around lines 62 - 78, Replace the hard-coded OAUTH_PROVIDER_PREFIXES in openclaw-sync-service.ts with a derived list from the canonical OAUTH_PROVIDER_MAP exported from openclaw-config-compiler.ts: export OAUTH_PROVIDER_MAP (if not already exported) from openclaw-config-compiler.ts, import it into openclaw-sync-service.ts, and compute OAUTH_PROVIDER_PREFIXES as Object.values(OAUTH_PROVIDER_MAP).map(p => `${p}/`) so resolveAvailableRuntimeModel uses the authoritative prefixes instead of a duplicated array.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/controller/src/runtime/openclaw-auth-profiles-store.ts`:
- Around line 99-112: readAuthProfiles currently only swallows missing-file
errors but lets parse errors from parseAuthProfilesData propagate; update
readAuthProfiles to catch JSON/parse errors and, when options?.missingOk is
true, return null instead of rethrowing. Specifically, wrap the readFile +
parseAuthProfilesData call in a try/catch, keep the existing isMissingFileError
check, and add a check for parse failures (e.g., any non-missing error from
parseAuthProfilesData) to return null when options?.missingOk is true; otherwise
rethrow. This targets the readAuthProfiles function and prevents uncaught parse
errors for callers (e.g., openclaw-auth-service.ts) that rely on missingOk.
---
Nitpick comments:
In `@apps/controller/src/services/openclaw-sync-service.ts`:
- Around line 62-78: Replace the hard-coded OAUTH_PROVIDER_PREFIXES in
openclaw-sync-service.ts with a derived list from the canonical
OAUTH_PROVIDER_MAP exported from openclaw-config-compiler.ts: export
OAUTH_PROVIDER_MAP (if not already exported) from openclaw-config-compiler.ts,
import it into openclaw-sync-service.ts, and compute OAUTH_PROVIDER_PREFIXES as
Object.values(OAUTH_PROVIDER_MAP).map(p => `${p}/`) so
resolveAvailableRuntimeModel uses the authoritative prefixes instead of a
duplicated array.
In `@apps/controller/tests/openclaw-config-compiler.test.ts`:
- Around line 223-248: Tests around compileOpenClawConfig and createConfig
duplicate nearly identical OpenAI config payloads (bots, runtime.defaultModelId,
providers.models, etc.); extract a shared fixture/helper (e.g.,
createOpenAIConfigFixture or openaiConfigPayload) that builds the common config
and accept small overrides for bot/model/provider differences, then replace the
duplicated inline objects in the tests with calls to that helper to reduce
duplication and future drift.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 6393f065-13aa-46cc-aed1-d35926fe8232
📒 Files selected for processing (10)
apps/controller/src/app/container.tsapps/controller/src/lib/openclaw-config-compiler.tsapps/controller/src/runtime/openclaw-auth-profiles-store.tsapps/controller/src/runtime/openclaw-auth-profiles-writer.tsapps/controller/src/services/openclaw-auth-service.tsapps/controller/src/services/openclaw-sync-service.tsapps/controller/tests/openclaw-auth-profiles-store.test.tsapps/controller/tests/openclaw-config-compiler.test.tsapps/controller/tests/openclaw-sync.test.tsapps/controller/tests/route-compat.test.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- apps/controller/src/app/container.ts
- apps/controller/src/lib/openclaw-config-compiler.ts
- apps/controller/src/services/openclaw-auth-service.ts
|
/cr |
|
✅ CR topic created in Feishu topic group Refly CR. |
Closes #412, closes #438
Summary
What changed
OpenAI Codex OAuth
OpenClawAuthService— handles PKCE OAuth flow withauth.openai.comauth-profiles.jsonfor auto token refreshopenai/*→openai-codex/*when provider is OAuth-connectedopenai-codex/model refs from auth-profiles/oauth/start,/oauth/status,/oauth/provider-status,/oauth/disconnectZ.AI Coding Plan
api.z.ai/api/coding/paas/v4/ CN:open.bigmodel.cn/api/coding/paas/v4Auth profiles writer
Test plan
pnpm typecheck— all 4 projects passpnpm lint— no errors in changed filespnpm test— 135/135 tests pass (15 new)apps/web/e2e/openai-oauth.spec.ts(mocked)🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
UX
Validation
Tests
Documentation