feat(agent): integrate auth profile rotation into runner and resolver

Extend credentials.ts with llm.order and listProfileIdsForProvider.
Add resolveApiKeyForProfile and resolveApiKeyForProvider to resolver.
Modify runner to support dynamic API key swapping and automatic
rotation on auth/rate_limit/billing errors with retry.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
yushen 2026-02-03 16:56:04 +08:00
parent d89b409add
commit dcc336f2d0
5 changed files with 273 additions and 12 deletions

View file

@ -21,6 +21,8 @@ export type CredentialsConfig = {
llm?: {
provider?: string | undefined;
providers?: Record<string, ProviderConfig> | undefined;
/** Explicit profile ordering per provider (e.g. { anthropic: ["anthropic", "anthropic:backup"] }) */
order?: Record<string, string[]> | undefined;
} | undefined;
tools?: Record<string, ToolConfig> | undefined;
};
@ -185,6 +187,30 @@ export class CredentialManager {
return name in process.env;
}
/**
* Get explicit profile order for a provider from credentials.json5 `llm.order`.
* Returns undefined if no explicit order is configured.
*/
getLlmOrder(provider: string): string[] | undefined {
this.loadCore();
return this.coreConfig?.llm?.order?.[provider];
}
/**
* List all profile IDs from `llm.providers` that belong to a given provider.
* A profile matches if its key equals the provider exactly or starts with "provider:".
*/
listProfileIdsForProvider(provider: string): string[] {
this.loadCore();
const providers = this.coreConfig?.llm?.providers;
if (!providers) return [];
const prefix = `${provider}:`;
return Object.keys(providers).filter(
(key) => key === provider || key.startsWith(prefix),
);
}
getResolvedEnvSnapshot(): Record<string, string> {
return { ...this.getResolvedSkillsEnv() };
}