From 85f36e8d2b4e3ed48c2e0f1c1eabab56a5e16cbd Mon Sep 17 00:00:00 2001 From: "Will (via Claude Code)" Date: Wed, 20 May 2026 15:29:23 -0700 Subject: [PATCH] fix(auth): include legacy OAuth sidecars in secrets-runtime store load MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The embedded agent runner — Telegram replies, cron invocations, any sub-agent dispatch — calls into the secrets runtime to resolve provider auth. That path goes through `loadAuthProfileStoreForSecretsRuntime`, which hardcoded `resolveLegacyOAuthSidecars: false`. As a result, OAuth profiles whose credential material lives in the legacy sidecar layout (`oauthRef.source: "openclaw-credentials"`, hash-named files under `/credentials/auth-profiles/.json`) were loaded without their access/refresh tokens, and `resolveApiKeyForProfile()` fell through to the "No API key found for provider" error. The OAuth-manager-internal helper added in #83312 already sets this to `true`, but the secrets-runtime path is a parallel entry point: when the embedded agent resolves provider auth for a model turn, it loads the store through this helper, *before* the OAuth manager's own reload would have a chance to compensate. Direct CLI inference is unaffected because it routes through a different store-load path that still sees the material. Repro (against v2026.5.19 stock): 1. Have an `openai-codex:default` profile with type=oauth and `oauthRef.source = "openclaw-credentials"` (typical for users who onboarded before the sidecar runtime was removed in #82777). 2. Send a Telegram message to the bot, or wait for any cron with an embedded payload to fire. 3. Gateway logs: [diagnostic] lane task error: ... error="Error: No API key found for provider \"openai-codex\". Auth store: .../auth-profiles.json ... Configure auth for this agent (openclaw agents add ) or copy only portable static auth profiles from the main agentDir." 4. Meanwhile, `openclaw infer model run --model openai/gpt-5.5 --prompt "say OK"` returns a normal completion using the same OAuth profile. Fix: flip the hardcoded default in `loadAuthProfileStoreForSecretsRuntime` from `false` to `true`, matching the OAuth-manager helper's choice. Sidecar resolution is read-only and already gated by per-process feature gates downstream, so this is safe to enable unconditionally for the secrets-runtime load. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/agents/auth-profiles/store.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/agents/auth-profiles/store.ts b/src/agents/auth-profiles/store.ts index 7f74bb3ed0d..6edc7684d92 100644 --- a/src/agents/auth-profiles/store.ts +++ b/src/agents/auth-profiles/store.ts @@ -590,7 +590,17 @@ export function loadAuthProfileStoreForSecretsRuntime(agentDir?: string): AuthPr return loadAuthProfileStoreForRuntime(agentDir, { readOnly: true, allowKeychainPrompt: false, - resolveLegacyOAuthSidecars: false, + // L4 PATCH (lane-pump branch): include legacy OAuth sidecar material when + // the runtime is resolving secrets for an agent turn. Without this, embedded + // agent runs (Telegram replies, cron invocations) cannot reach the access + // token for openai-codex profiles whose `oauthRef.source` is + // "openclaw-credentials", and resolveApiKeyForProfile() falls through to + // "No API key found". The OAuth-manager-internal refresh helper added in + // upstream #83312 already sets this to true; this default was inadvertently + // left at `false` after the sidecar runtime removal in #82777, breaking + // the embedded-agent OAuth resolution path while leaving the direct CLI + // inference path unaffected. See UPSTREAM_ISSUE_DRAFT.md in local-patches. + resolveLegacyOAuthSidecars: true, }); }