mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-20 08:04:44 +00:00
133 lines
4.2 KiB
TypeScript
133 lines
4.2 KiB
TypeScript
/**
|
|
* OAuth credential management for AI providers.
|
|
*
|
|
* This module handles login, token refresh, and credential storage
|
|
* for OAuth-based providers:
|
|
* - Anthropic (Claude Pro/Max)
|
|
* - GitHub Copilot
|
|
* - Google Cloud Code Assist (Gemini CLI)
|
|
* - Antigravity (Gemini 3, Claude, GPT-OSS via Google Cloud)
|
|
*/
|
|
|
|
// Anthropic
|
|
export { anthropicOAuthProvider, loginAnthropic, refreshAnthropicToken } from "./anthropic.js";
|
|
// GitHub Copilot
|
|
export {
|
|
getGitHubCopilotBaseUrl,
|
|
githubCopilotOAuthProvider,
|
|
loginGitHubCopilot,
|
|
normalizeDomain,
|
|
refreshGitHubCopilotToken,
|
|
} from "./github-copilot.js";
|
|
// Google Antigravity
|
|
export { antigravityOAuthProvider, loginAntigravity, refreshAntigravityToken } from "./google-antigravity.js";
|
|
// Google Gemini CLI
|
|
export { geminiCliOAuthProvider, loginGeminiCli, refreshGoogleCloudToken } from "./google-gemini-cli.js";
|
|
// OpenAI Codex (ChatGPT OAuth)
|
|
export { loginOpenAICodex, openaiCodexOAuthProvider, refreshOpenAICodexToken } from "./openai-codex.js";
|
|
|
|
export * from "./types.js";
|
|
|
|
// ============================================================================
|
|
// Provider Registry
|
|
// ============================================================================
|
|
|
|
import { anthropicOAuthProvider } from "./anthropic.js";
|
|
import { githubCopilotOAuthProvider } from "./github-copilot.js";
|
|
import { antigravityOAuthProvider } from "./google-antigravity.js";
|
|
import { geminiCliOAuthProvider } from "./google-gemini-cli.js";
|
|
import { openaiCodexOAuthProvider } from "./openai-codex.js";
|
|
import type { OAuthCredentials, OAuthProviderId, OAuthProviderInfo, OAuthProviderInterface } from "./types.js";
|
|
|
|
const oauthProviderRegistry = new Map<string, OAuthProviderInterface>([
|
|
[anthropicOAuthProvider.id, anthropicOAuthProvider],
|
|
[githubCopilotOAuthProvider.id, githubCopilotOAuthProvider],
|
|
[geminiCliOAuthProvider.id, geminiCliOAuthProvider],
|
|
[antigravityOAuthProvider.id, antigravityOAuthProvider],
|
|
[openaiCodexOAuthProvider.id, openaiCodexOAuthProvider],
|
|
]);
|
|
|
|
/**
|
|
* Get an OAuth provider by ID
|
|
*/
|
|
export function getOAuthProvider(id: OAuthProviderId): OAuthProviderInterface | undefined {
|
|
return oauthProviderRegistry.get(id);
|
|
}
|
|
|
|
/**
|
|
* Register a custom OAuth provider
|
|
*/
|
|
export function registerOAuthProvider(provider: OAuthProviderInterface): void {
|
|
oauthProviderRegistry.set(provider.id, provider);
|
|
}
|
|
|
|
/**
|
|
* Get all registered OAuth providers
|
|
*/
|
|
export function getOAuthProviders(): OAuthProviderInterface[] {
|
|
return Array.from(oauthProviderRegistry.values());
|
|
}
|
|
|
|
/**
|
|
* @deprecated Use getOAuthProviders() which returns OAuthProviderInterface[]
|
|
*/
|
|
export function getOAuthProviderInfoList(): OAuthProviderInfo[] {
|
|
return getOAuthProviders().map((p) => ({
|
|
id: p.id,
|
|
name: p.name,
|
|
available: true,
|
|
}));
|
|
}
|
|
|
|
// ============================================================================
|
|
// High-level API (uses provider registry)
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Refresh token for any OAuth provider.
|
|
* @deprecated Use getOAuthProvider(id).refreshToken() instead
|
|
*/
|
|
export async function refreshOAuthToken(
|
|
providerId: OAuthProviderId,
|
|
credentials: OAuthCredentials,
|
|
): Promise<OAuthCredentials> {
|
|
const provider = getOAuthProvider(providerId);
|
|
if (!provider) {
|
|
throw new Error(`Unknown OAuth provider: ${providerId}`);
|
|
}
|
|
return provider.refreshToken(credentials);
|
|
}
|
|
|
|
/**
|
|
* Get API key for a provider from OAuth credentials.
|
|
* Automatically refreshes expired tokens.
|
|
*
|
|
* @returns API key string and updated credentials, or null if no credentials
|
|
* @throws Error if refresh fails
|
|
*/
|
|
export async function getOAuthApiKey(
|
|
providerId: OAuthProviderId,
|
|
credentials: Record<string, OAuthCredentials>,
|
|
): Promise<{ newCredentials: OAuthCredentials; apiKey: string } | null> {
|
|
const provider = getOAuthProvider(providerId);
|
|
if (!provider) {
|
|
throw new Error(`Unknown OAuth provider: ${providerId}`);
|
|
}
|
|
|
|
let creds = credentials[providerId];
|
|
if (!creds) {
|
|
return null;
|
|
}
|
|
|
|
// Refresh if expired
|
|
if (Date.now() >= creds.expires) {
|
|
try {
|
|
creds = await provider.refreshToken(creds);
|
|
} catch (_error) {
|
|
throw new Error(`Failed to refresh OAuth token for ${providerId}`);
|
|
}
|
|
}
|
|
|
|
const apiKey = provider.getApiKey(creds);
|
|
return { newCredentials: creds, apiKey };
|
|
}
|