diff --git a/src/main/adapters/opencode-adapter.ts b/src/main/adapters/opencode-adapter.ts index c6cdfe3..57763a1 100644 --- a/src/main/adapters/opencode-adapter.ts +++ b/src/main/adapters/opencode-adapter.ts @@ -444,6 +444,18 @@ export class OpencodeAdapter implements CodingAgentAdapter { await this.ensureServerRunning(config.serverUrl || DEFAULT_SERVER_URL) + // Always push the latest merged config (incl. refreshed AI gateway key) + // to the running server. ensureServerRunning skips the config push when + // the server is already running at the same URL, but provider credentials + // may have been rotated since the server was started. + if (this.sharedClient) { + try { + await this.pushMergedConfigToClient(this.sharedClient) + } catch { + // pushMergedConfigToClient already logs details; proceed with cached config + } + } + const baseUrl = this.serverUrl || config.serverUrl || DEFAULT_SERVER_URL const ocClient = OpenCodeSDK!.createOpencodeClient({ baseUrl, fetch: noTimeoutFetch as unknown as (request: Request) => ReturnType }) diff --git a/src/main/agent-manager.ts b/src/main/agent-manager.ts index 462cbac..d93f3e5 100644 --- a/src/main/agent-manager.ts +++ b/src/main/agent-manager.ts @@ -1073,6 +1073,17 @@ export class AgentManager extends EventEmitter { } await yieldEL() + // Refresh the AI gateway virtual key before building the provider config + // so the adapter gets the latest key from the backend (handles key rotation, + // admin plan changes, etc.). Best-effort — fall back to the cached key. + if (this.enterpriseAuth) { + try { + await this.enterpriseAuth.refreshAiGatewayVirtualKey() + } catch (err) { + console.warn('[AgentManager] AI gateway key refresh failed (will use cached key):', err) + } + } + // Initialize adapter console.log(`[AgentManager] startAdapterSession: agent=${agent.name}, coding_agent=${agent.config?.coding_agent || 'opencode'}, model=${agent.config?.model}, adapter=${adapter.constructor.name}`) await adapter.initialize() diff --git a/src/main/enterprise-auth.ts b/src/main/enterprise-auth.ts index da33085..4de93c4 100644 --- a/src/main/enterprise-auth.ts +++ b/src/main/enterprise-auth.ts @@ -654,6 +654,15 @@ export class EnterpriseAuth { return jwt } + /** + * Re-fetch and store the AI gateway virtual key from the backend. + * Exposed publicly so callers (e.g. IPC handlers, adapter error recovery) + * can trigger a key refresh when LiteLLM returns "Invalid proxy server token". + */ + async refreshAiGatewayVirtualKey(): Promise { + return this.fetchAndStoreAiGatewayVirtualKey() + } + private async fetchAndStoreAiGatewayVirtualKey(): Promise { const result = await this.apiRequest('GET', '/api/20x/ai-gateway/virtual-key') as EnterpriseAiGatewayVirtualKeyResponse