first commit

This commit is contained in:
2026-08-14 23:41:57 +08:00
commit 086803a8dd
471 changed files with 91938 additions and 0 deletions
+377
View File
@@ -0,0 +1,377 @@
// This file defines the central provider registry (US-001): a single source of
// truth for every built-in provider's metadata — its name, the environment
// variables that carry its API key (in precedence order), its default base URL,
// wire protocol, auth scheme, any extra headers, and provider-specific base-URL
// override env vars.
//
// The registry is deliberately additive and self-contained: later nodes wire
// auth resolution (auth.go), the --provider flag (main.go), base_url overrides,
// and per-provider construction (providers.go) to READ from it. This node only
// introduces the data + a lookup, so it does not change existing behavior.
//
// Data source: the PRD "Technical Considerations" table
// (tasks/prd-provider-env-parity.md), derived from pi's env-api-keys.ts and the
// per-provider *.models.ts files.
//
// Security: the registry holds only env var NAMES, never secret values. Keys are
// resolved from the environment at request time (see auth.go) and never logged.
package provider
// ProviderSpec is the metadata describing one built-in provider. It is the
// single source of truth consumed by auth resolution, the --provider flag,
// base_url override handling, and per-provider wiring.
type ProviderSpec struct {
// Name is the canonical provider name (e.g. "deepseek", "zai-coding-cn").
Name string
// EnvVars lists the environment variables checked (in precedence order) for
// this provider's API key. The first non-empty value wins.
EnvVars []string
// DefaultBaseURL is the provider's default API endpoint. It may be a template
// (containing placeholders like {region}) for providers whose endpoint is
// composed from additional parameters (Bedrock, Vertex, Cloudflare, Azure).
DefaultBaseURL string
// Protocol is the wire protocol the provider speaks: "openai" (OpenAI Chat
// Completions) or "anthropic" (Anthropic Messages).
Protocol string
// AuthScheme names how credentials are attached: "bearer", "x-api-key",
// "aws", "azure", or "special".
AuthScheme string
// ExtraHeaders are provider-specific headers attached to every request (may
// be nil).
ExtraHeaders map[string]string
// BaseURLEnvVars lists provider-specific base-URL override environment
// variables (e.g. AZURE_OPENAI_BASE_URL), in precedence order. May be empty;
// the generic <PROVIDER>_BASE_URL convention is handled by callers.
BaseURLEnvVars []string
}
// Protocol values.
const (
ProtocolOpenAI = "openai"
ProtocolAnthropic = "anthropic"
)
// AuthScheme values.
const (
AuthBearer = "bearer"
AuthXAPIKey = "x-api-key"
AuthAWS = "aws"
AuthAzure = "azure"
AuthSpecial = "special"
)
// providerRegistry is the ordered list of all built-in provider specs. Order is
// stable so callers that enumerate providers (e.g. --help) get a deterministic
// list. LookupProviderSpec indexes it by name.
var providerRegistry = []ProviderSpec{
{
Name: "anthropic",
EnvVars: []string{"ANTHROPIC_OAUTH_TOKEN", "ANTHROPIC_API_KEY", "CLAUDE_API_KEY"},
DefaultBaseURL: anthropicBaseURL, // https://api.anthropic.com/v1
Protocol: ProtocolAnthropic,
AuthScheme: AuthXAPIKey,
},
{
Name: "openai",
EnvVars: []string{"OPENAI_API_KEY"},
DefaultBaseURL: "https://api.openai.com/v1",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
Name: "ant-ling",
EnvVars: []string{"ANT_LING_API_KEY"},
DefaultBaseURL: "https://api.ant-ling.com/v1",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
Name: "deepseek",
EnvVars: []string{"DEEPSEEK_API_KEY"},
DefaultBaseURL: "https://api.deepseek.com",
Protocol: ProtocolOpenAIResponses,
AuthScheme: AuthBearer,
},
{
Name: "nvidia",
EnvVars: []string{"NVIDIA_API_KEY", "NVIDIA_NIM_API_KEY"},
DefaultBaseURL: nvidiaBaseURL, // https://integrate.api.nvidia.com/v1
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
Name: "google",
EnvVars: []string{"GEMINI_API_KEY", "GOOGLE_API_KEY"},
DefaultBaseURL: "https://generativelanguage.googleapis.com/v1beta",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
Name: "groq",
EnvVars: []string{"GROQ_API_KEY"},
DefaultBaseURL: "https://api.groq.com/openai/v1",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
Name: "cerebras",
EnvVars: []string{"CEREBRAS_API_KEY"},
DefaultBaseURL: "https://api.cerebras.ai/v1",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
Name: "xai",
EnvVars: []string{"XAI_API_KEY"},
DefaultBaseURL: "https://api.x.ai/v1",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
Name: "openrouter",
EnvVars: []string{"OPENROUTER_API_KEY"},
DefaultBaseURL: openRouterBaseURL, // https://openrouter.ai/api/v1
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
Name: "vercel-ai-gateway",
EnvVars: []string{"AI_GATEWAY_API_KEY"},
DefaultBaseURL: "https://ai-gateway.vercel.sh",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
Name: "zai",
EnvVars: []string{"ZAI_API_KEY"},
DefaultBaseURL: "https://api.z.ai/api/coding/paas/v4",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
Name: "zai-coding-cn",
EnvVars: []string{"ZAI_CODING_CN_API_KEY"},
DefaultBaseURL: "https://open.bigmodel.cn/api/coding/paas/v4",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
Name: "mistral",
EnvVars: []string{"MISTRAL_API_KEY"},
DefaultBaseURL: "https://api.mistral.ai",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
Name: "minimax",
EnvVars: []string{"MINIMAX_API_KEY"},
DefaultBaseURL: "https://api.minimax.io/anthropic",
Protocol: ProtocolAnthropic,
AuthScheme: AuthXAPIKey,
},
{
Name: "minimax-cn",
EnvVars: []string{"MINIMAX_CN_API_KEY"},
DefaultBaseURL: "https://api.minimaxi.com/anthropic",
Protocol: ProtocolAnthropic,
AuthScheme: AuthXAPIKey,
},
{
Name: "moonshotai",
EnvVars: []string{"MOONSHOT_API_KEY"},
DefaultBaseURL: "https://api.moonshot.ai/v1",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
Name: "moonshotai-cn",
EnvVars: []string{"MOONSHOT_API_KEY"},
DefaultBaseURL: "https://api.moonshot.cn/v1",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
Name: "huggingface",
EnvVars: []string{"HF_TOKEN"},
DefaultBaseURL: "https://router.huggingface.co/v1",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
Name: "fireworks",
EnvVars: []string{"FIREWORKS_API_KEY"},
DefaultBaseURL: "https://api.fireworks.ai/inference",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
Name: "together",
EnvVars: []string{"TOGETHER_API_KEY"},
DefaultBaseURL: "https://api.together.ai/v1",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
Name: "opencode",
EnvVars: []string{"OPENCODE_API_KEY"},
DefaultBaseURL: "https://opencode.ai/zen",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
Name: "opencode-go",
EnvVars: []string{"OPENCODE_API_KEY"},
DefaultBaseURL: "https://opencode.ai/zen/go",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
Name: "kimi-coding",
EnvVars: []string{"KIMI_API_KEY"},
DefaultBaseURL: "https://api.kimi.com/coding",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
Name: "xiaomi",
EnvVars: []string{"XIAOMI_API_KEY"},
DefaultBaseURL: "https://api.xiaomimimo.com/v1",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
Name: "xiaomi-token-plan-cn",
EnvVars: []string{"XIAOMI_TOKEN_PLAN_CN_API_KEY"},
DefaultBaseURL: "https://token-plan-cn.xiaomimimo.com/v1",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
Name: "xiaomi-token-plan-ams",
EnvVars: []string{"XIAOMI_TOKEN_PLAN_AMS_API_KEY"},
DefaultBaseURL: "https://token-plan-ams.xiaomimimo.com/v1",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
Name: "xiaomi-token-plan-sgp",
EnvVars: []string{"XIAOMI_TOKEN_PLAN_SGP_API_KEY"},
DefaultBaseURL: "https://token-plan-sgp.xiaomimimo.com/v1",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
// Chinese cloud LLM platforms. All four expose OpenAI-compatible endpoints
// authenticated with a plain Bearer API key, so they reuse the standard
// OpenAI-compatible driver with no bespoke auth. Base URLs are the platforms'
// OpenAI-compatible endpoints as documented at implementation time.
{
// Baidu AI Cloud Qianfan (Baidu Qianfan).
Name: "qianfan",
EnvVars: []string{"QIANFAN_API_KEY"},
DefaultBaseURL: "https://qianfan.baidubce.com/v2",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
// ByteDance Volcengine Ark (Volcengine Ark). ARK_API_KEY is the platform's
// conventional variable; VOLCENGINE_API_KEY is accepted as a fallback.
Name: "volcengine",
EnvVars: []string{"ARK_API_KEY", "VOLCENGINE_API_KEY"},
DefaultBaseURL: "https://ark.cn-beijing.volces.com/api/v3",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
// Alibaba Cloud DashScope (DashScope), OpenAI-compatible mode.
Name: "dashscope",
EnvVars: []string{"DASHSCOPE_API_KEY"},
DefaultBaseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
// Tencent Hunyuan (Hunyuan), OpenAI-compatible endpoint.
Name: "hunyuan",
EnvVars: []string{"HUNYUAN_API_KEY"},
DefaultBaseURL: "https://api.hunyuan.cloud.tencent.com/v1",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
Name: "azure-openai-responses",
EnvVars: []string{"AZURE_OPENAI_API_KEY"},
// Endpoint is composed from AZURE_OPENAI_BASE_URL / AZURE_OPENAI_RESOURCE_NAME
// per the Azure OpenAI convention; there is no fixed public default.
DefaultBaseURL: "",
Protocol: ProtocolOpenAI,
AuthScheme: AuthAzure,
BaseURLEnvVars: []string{"AZURE_OPENAI_BASE_URL"},
},
{
Name: "amazon-bedrock",
EnvVars: []string{"AWS_BEARER_TOKEN_BEDROCK"},
// Region-specific runtime endpoint; {AWS_REGION} defaults to us-east-1.
DefaultBaseURL: "https://bedrock-runtime.{AWS_REGION}.amazonaws.com",
Protocol: ProtocolAnthropic,
AuthScheme: AuthAWS,
},
{
Name: "google-vertex",
EnvVars: []string{"GOOGLE_CLOUD_API_KEY"},
// Location-specific endpoint; protocol varies by model (Gemini vs Claude).
DefaultBaseURL: "https://{location}-aiplatform.googleapis.com",
Protocol: ProtocolOpenAI,
AuthScheme: AuthSpecial,
},
{
Name: "cloudflare-workers-ai",
EnvVars: []string{"CLOUDFLARE_API_KEY"},
// {id} is CLOUDFLARE_ACCOUNT_ID.
DefaultBaseURL: "https://api.cloudflare.com/client/v4/accounts/{account_id}/ai/v1",
Protocol: ProtocolOpenAI,
AuthScheme: AuthBearer,
},
{
Name: "cloudflare-ai-gateway",
EnvVars: []string{"CLOUDFLARE_API_KEY"},
// {acct}/{gw} are CLOUDFLARE_ACCOUNT_ID / CLOUDFLARE_GATEWAY_ID.
DefaultBaseURL: "https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}/anthropic",
Protocol: ProtocolAnthropic,
AuthScheme: AuthXAPIKey,
},
}
// providerRegistryByName indexes providerRegistry by provider name for O(1)
// lookup. Built once at package init.
var providerRegistryByName = func() map[string]ProviderSpec {
m := make(map[string]ProviderSpec, len(providerRegistry))
for _, spec := range providerRegistry {
m[spec.Name] = spec
}
return m
}()
// LookupProviderSpec returns the ProviderSpec for a provider name and whether it
// is a known built-in provider. The returned spec is a copy; mutating its slice
// or map fields is discouraged as they are shared with the registry.
func LookupProviderSpec(name string) (ProviderSpec, bool) {
spec, ok := providerRegistryByName[name]
return spec, ok
}
// ProviderSpecs returns all built-in provider specs in registry (display) order.
// Callers must not mutate the returned specs' slice/map fields.
func ProviderSpecs() []ProviderSpec {
out := make([]ProviderSpec, len(providerRegistry))
copy(out, providerRegistry)
return out
}
// ProviderNames returns all built-in provider names in registry order.
func ProviderNames() []string {
out := make([]string, len(providerRegistry))
for i, spec := range providerRegistry {
out[i] = spec.Name
}
return out
}