Follow-up slice of #455. Slice 1 (#464) refreshes the gateway token at client-build time (applyGatewaySettings calls EnsureGatewayToken at the start of forge run / try / serve). A token that expires mid-session — e.g. during a long-running forge serve daemon or a very long agent loop — is not refreshed per LLM call, so it can go stale within the process.
Scope
- Add a dynamic credential source on the provider clients (an
APIKeyProvider func() (string, error) on llm.ClientConfig, or a per-call hook) so the token is resolved/refreshed per request rather than baked in at construction.
- Wire the gateway path (
EnsureGatewayToken) as that provider when a gateway api_key_helper (or, after slice 2, an OIDC provider) is configured, so an expiring token is transparently re-acquired between calls.
- Keep the refresh-buffer semantics (re-acquire within 5 min of
exp); no stale-token 401 mid-run.
Acceptance
Touch points
forge-core/llm/client.go (ClientConfig), forge-core/llm/providers/* (setHeaders), forge-cli/runtime/gateway_credential.go.
Depends on #455 slice 1 (#464); complements slice 2 (#490).
Follow-up slice of #455. Slice 1 (#464) refreshes the gateway token at client-build time (
applyGatewaySettingscallsEnsureGatewayTokenat the start offorge run/try/serve). A token that expires mid-session — e.g. during a long-runningforge servedaemon or a very long agent loop — is not refreshed per LLM call, so it can go stale within the process.Scope
APIKeyProvider func() (string, error)onllm.ClientConfig, or a per-call hook) so the token is resolved/refreshed per request rather than baked in at construction.EnsureGatewayToken) as that provider when a gatewayapi_key_helper(or, after slice 2, an OIDC provider) is configured, so an expiring token is transparently re-acquired between calls.exp); no stale-token 401 mid-run.Acceptance
forge serveprocess whose gateway token expires during its lifetime refreshes transparently on the next LLM call (no restart, no 401).Touch points
forge-core/llm/client.go(ClientConfig),forge-core/llm/providers/*(setHeaders),forge-cli/runtime/gateway_credential.go.Depends on #455 slice 1 (#464); complements slice 2 (#490).