Docs/TypeScript/OAuth Providers
AIai/oauth

OAuth Providers

OAuth helpers live in src/facade/ml/kit/auth/* and are re-exported from indusagi/ai. They provide login, refresh, and API-key extraction for providers that authenticate over OAuth.

The OAuth registry currently ships in API-KEY-ONLY MODE. The provider objects exist and are exported, but none are registered, so getOAuthProviders() returns [] and both the CLI and the interactive TUI fall through to the API-key path. Register a provider explicitly with registerOAuthProvider(...) to enable its OAuth flow.

Registry API

From src/facade/ml/kit/auth/index.ts:

  • getOAuthProvider(id) returns the registered provider or undefined.
  • registerOAuthProvider(provider) adds (or replaces) a provider in the registry.
  • getOAuthProviders() lists registered providers.
  • getOAuthProviderInfoList() returns slim { id, name, available } summaries (deprecated).
  • getOAuthApiKey(providerId, credentialsMap) resolves an API key from a stored credential, refreshing it first if it has expired. Returns { newCredentials, apiKey } or null when no credential exists.
  • refreshOAuthToken(providerId, credentials) (deprecated) renews a credential.
  • ensureFreshOAuthCredentials(providerId, credentials) returns { credentials, refreshed }, refreshing only when expired.

Credential Types

From src/facade/ml/kit/auth/types.ts:

  • OAuthCredentials ({ access, refresh, expires, issuedAt?, provider? }).
  • AuthProviderContract (alias OAuthProviderInterface) — id, name, login, refreshToken, getApiKey, optional usesCallbackServer and modifyModels.
  • OAuthLoginCallbacks (onAuth, onPrompt, optional onManualCodeInput, onProgress, signal).
  • makeOAuthCredentials(access, refresh, expiresMs, extra?) and getTokenStatus(creds) (returns "valid" | "expired" | "missing").

PKCE

src/facade/ml/kit/auth/pkce.ts exports generatePKCE(), which returns a { verifier, challenge } pair (RFC 7636, S256) built on the Web Crypto API so it runs under Node.js 20+ and in browsers.

Provider Summary

Anthropic (Claude Pro/Max)

File: kit/auth/anthropic.ts. Provider id anthropic, name "Anthropic (Claude Pro/Max)".

  • loginAnthropic(onAuthUrl, onPromptCode) runs a PKCE flow with a manual authorization-code paste.
  • refreshAnthropicToken(refreshToken) renews the credential.
  • getApiKey returns the access token.
  • Also exports anthropicOAuthProvider and isAnthropicOAuthCredentialsValid.

GitHub Copilot

File: kit/auth/github-copilot.ts. Provider id github-copilot, name "GitHub Copilot".

  • loginGitHubCopilot (via copilotAuthFlow) uses the GitHub device-authorization grant.
  • refreshGitHubCopilotToken(refreshToken, enterpriseDomain?) renews the token.
  • getGitHubCopilotBaseUrl(token?, enterpriseDomain?) resolves the Copilot base URL.
  • normalizeDomain(raw) normalizes an enterprise domain.
  • Also exports githubCopilotOAuthProvider and isGitHubCopilotOAuthCredentialsValid.

ChatGPT Codex (OpenAI)

File: kit/auth/openai-codex.ts. Provider id openai-codex, name "ChatGPT Plus or Pro — Codex plan", usesCallbackServer: true.

  • loginOpenAICodex({ onAuth, onPrompt, onProgress?, onManualCodeInput? }) runs a PKCE flow with a local callback server bound to 127.0.0.1:1455 (redirect URI http://localhost:1455/auth/callback). If the port cannot be bound, it falls back to manual code entry.
  • refreshOpenAICodexToken(refreshToken) renews the credential.
  • Also exports openaiCodexOAuthProvider.

Kimi (Moonshot AI)

File: kit/auth/kimi.ts. Kimi is API-key only — there is no OAuth flow.

  • loginKimi() and refreshKimiToken() always throw; use getEnvApiKey("kimi") (MOONSHOT_API_KEY) instead.
  • isKimiApiKeyStyleCredential(credentials) reports whether a credential is the key-style shape.

Login CLI

src/facade/ml/cli.ts is a standalone helper (shebang #!/usr/bin/env node, usage banner indusvx-ml <command> [provider]) that stores OAuth credentials in a local auth.json. It supports list, login [provider], refresh <provider>, and help. Because the registry ships empty, it lists no providers until one is registered. This module is not re-exported from indusagi/ai.