From 4624e34c067121130d9fd6f87edca20ef0beda56 Mon Sep 17 00:00:00 2001 From: "Will (via Claude Code)" Date: Wed, 20 May 2026 17:49:45 -0700 Subject: [PATCH] fix(auth): extend legacy OAuth sidecar resolution to all secrets entry points MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit L4 patched only `loadAuthProfileStoreForSecretsRuntime`, but `ensureAuthProfileStoreWithoutExternalProfiles` (used by the embedded runner via `pi-embedded-runner/run.ts:59` and by `model-provider-auth.ts`) and `loadAuthProfileStoreWithoutExternalProfiles` (used by `model-auth-label`, `pi-auth-discovery`, the models list command, the OAuth manager) are parallel entry points that ALSO needed the same flag flip. Without this follow-up, cron-isolated lanes (`lane=cron-nested`, `lane=session:agent:main:cron:...:run:...`) keep hitting the legacy "No API key found for provider \"openai-codex\"" error path even though direct user-Telegram lanes resolve fine. Observed live 2026-05-20 17:45 PDT on the L4-patched v2026.5.19 build: direct Telegram replies worked, but the 15-minute AgentOS task-board sweep cron (`9584014c`) fired at 17:45:24 and surfaced the same `FailoverError: No API key found for provider "openai-codex"` to the delivery channel. Fix: 1. `loadAuthProfileStoreWithoutExternalProfiles`: default `resolveLegacyOAuthSidecars` from `false` to `true` — matches L4's reasoning for the secrets-runtime helper. 2. `ensureAuthProfileStoreWithoutExternalProfiles`: accept the `resolveLegacyOAuthSidecars` option (was unsupported, hardcoded `false` downstream), default to `true`, and forward it through `resolveRuntimeAuthProfileStore` and both `loadAuthProfileStoreForAgent` call sites (requested agentDir + main fallback merge). These functions are read-only and do not mutate persisted state, so flipping the default is safe — they just include the credential material that's been on disk all along. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/agents/auth-profiles/store.ts | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/agents/auth-profiles/store.ts b/src/agents/auth-profiles/store.ts index 6edc7684d92..fb5619808bd 100644 --- a/src/agents/auth-profiles/store.ts +++ b/src/agents/auth-profiles/store.ts @@ -614,7 +614,13 @@ export function loadAuthProfileStoreWithoutExternalProfiles( const options: LoadAuthProfileStoreOptions = { readOnly: true, allowKeychainPrompt: loadOptions?.allowKeychainPrompt ?? false, - resolveLegacyOAuthSidecars: loadOptions?.resolveLegacyOAuthSidecars ?? false, + // L4.1 PATCH: default sidecar resolution to true so that any caller + // not explicitly overriding (model-auth-label, model-provider-auth, + // pi-auth-discovery, list.list-command, etc.) still picks up legacy + // OAuth credential material. Was inadvertently left at `false` in the + // upstream #82777/#83312 refactor and breaks isolated/sub-agent auth + // resolution paths (e.g., cron-nested lanes). + resolveLegacyOAuthSidecars: loadOptions?.resolveLegacyOAuthSidecars ?? true, }; const store = loadAuthProfileStoreForAgent(agentDir, options); const authPath = resolveAuthStorePath(agentDir); @@ -649,20 +655,32 @@ export function ensureAuthProfileStore( export function ensureAuthProfileStoreWithoutExternalProfiles( agentDir?: string, - options?: { allowKeychainPrompt?: boolean }, + options?: { allowKeychainPrompt?: boolean; resolveLegacyOAuthSidecars?: boolean }, ): AuthProfileStore { - const runtimeStore = resolveRuntimeAuthProfileStore(agentDir, options); + // L4.1 PATCH: forward `resolveLegacyOAuthSidecars` through this entry + // point so embedded-runner sub-agents (cron-nested, isolated session + // lanes for AgentOS sweeps) can read the legacy sidecar credential + // material. Default true to match `loadAuthProfileStoreWithoutExternalProfiles`. + const resolveLegacyOAuthSidecars = options?.resolveLegacyOAuthSidecars ?? true; + const effectiveOptions: LoadAuthProfileStoreOptions = { + ...(options ?? {}), + resolveLegacyOAuthSidecars, + }; + const runtimeStore = resolveRuntimeAuthProfileStore(agentDir, effectiveOptions); if (runtimeStore) { return runtimeStore; } - const store = loadAuthProfileStoreForAgent(agentDir, options); + const store = loadAuthProfileStoreForAgent(agentDir, effectiveOptions); const authPath = resolveAuthStorePath(agentDir); const mainAuthPath = resolveAuthStorePath(); if (!agentDir || authPath === mainAuthPath) { return store; } - const mainStore = loadAuthProfileStoreForAgent(undefined, options); + // L4.1 PATCH: use effectiveOptions (with sidecar resolution) for the main + // fallback load too, otherwise sub-agents that need to merge in the main + // store would still miss the legacy credential material. + const mainStore = loadAuthProfileStoreForAgent(undefined, effectiveOptions); return mergeAuthProfileStores(mainStore, store); }