Files
clawX/harness/specs/tasks/provider-switch-api-protocol-validation.md

4.2 KiB

id, title, scenario, taskType, intent, touchedAreas, expectedUserBehavior, requiredProfiles, requiredRules, requiredTests, acceptance, docs
id title scenario taskType intent touchedAreas expectedUserBehavior requiredProfiles requiredRules requiredTests acceptance docs
provider-switch-api-protocol-validation Reject invalid OpenClaw api protocol writes and self-heal stale entries gateway-backend-communication runtime-bridge Prevent ClawX from writing models.providers.*.api values outside the OpenClaw allowlist into openclaw.json, and opportunistically prune pre-existing invalid entries when the user switches default provider so a clean switch can rescue the Gateway from Invalid-config restart loops.
harness/specs/tasks/provider-switch-api-protocol-validation.md
electron/shared/providers/registry.ts
electron/shared/providers/types.ts
electron/utils/openclaw-auth.ts
electron/services/providers/provider-runtime-sync.ts
tests/unit/openclaw-auth.test.ts
Selecting OpenRouter (or any built-in provider) as default writes a Gateway-valid api protocol so Gateway reload stays healthy.
Attempting to save a provider whose api protocol is not in the OpenClaw allowlist surfaces an actionable error in the UI without polluting openclaw.json or triggering a Gateway restart.
Switching default to a healthy provider after a prior corrupt openclaw.json (legacy api=openrouter typo) self-heals the file before the next reload signal so the Gateway boots cleanly.
fast
comms
active-config-guards
backend-communication-boundary
renderer-main-boundary
api-client-transport-policy
tests/unit/openclaw-auth.test.ts
electron/shared/providers/types.ts exports OPENCLAW_API_PROTOCOLS as the single source of truth for openclaw.json api values, plus assertValidApiProtocol and InvalidApiProtocolError.
setOpenClawDefaultModel, setOpenClawDefaultModelWithOverride, syncProviderConfigToOpenClaw, and upsertOpenClawProviderEntry all invoke assertValidApiProtocol before any write to openclaw.json.
syncDefaultProviderToRuntime calls pruneInvalidApiProviderEntries before the OAuth and non-OAuth branches so a switch to any healthy provider drops legacy invalid models.providers entries.
Renderer does not add new direct ipcRenderer or Gateway HTTP calls.
Unit tests cover both the rejection path (no file write on invalid api) and the self-heal path (legacy entries pruned while valid ones remain).
required
false

Background

A historical bug in electron/shared/providers/registry.ts set the OpenRouter providerConfig.api to the literal string 'openrouter', which is not in OpenClaw's allowed api enum (openai-completions | openai-responses | openai-codex-responses | anthropic-messages | google-generative-ai | github-copilot | bedrock-converse-stream | ollama | azure-openai-responses).

When the user selected OpenRouter as their default provider, ClawX wrote that invalid value into ~/.openclaw/openclaw.json and then sent SIGUSR1 to the running Gateway. The Gateway's assertValidGatewayStartupConfigSnapshot rejected the config, tore down all channels (close code 1012), entered the startup_failed state, but kept the OS process alive. The Main process then spun for ~8 minutes inside waitForGatewayReady before doctor self-heal kicked in.

Switching to MiniMax during the broken window did not help, because the runtime-sync path only appended the MiniMax block and left the broken OpenRouter entry untouched.

Scope

  • Fix the registry typo so OpenRouter writes api: 'openai-completions', matching every other OpenAI-compatible built-in provider.
  • Add a single source of truth for the allowed api protocols and a runtime guard at every write site (setOpenClawDefaultModel, setOpenClawDefaultModelWithOverride, syncProviderConfigToOpenClaw, plus defense-in-depth inside upsertOpenClawProviderEntry).
  • Add a self-heal helper that prunes any models.providers.* entry whose api is outside the allowlist, and invoke it at the top of syncDefaultProviderToRuntime so a clean switch rescues legacy corrupted configs.

Out of scope

  • Gateway-side waitForGatewayReady short-circuit when the owned process is stuck in startup_failed.
  • Renderer pre-flight validation UI surface beyond the existing route-level error handling.
  • README updates (no user-visible UI change in this task).