Skip to content
153 linesCodeBlameRaw
1/**
2 * The AI providers a workspace can keep credentials for, as people are
3 * shown them: grouped, with a line each, a mark, and where to get a key.
4 */
5import type { Provider } from "@g1t/contracts";
6
7export type AiProviderGroup = "labs" | "platforms" | "any";
8
9export type AiProviderEntry = {
10 group: AiProviderGroup;
11 blurb: string;
12 /** The provider's colour, for its mark. */
13 color: string;
14 /** What the mark shows: an initial or two. Empty for an icon. */
15 mark: string;
16 /** Where to get a key. */
17 keyUrl?: string;
18 keyPlaceholder?: string;
19 /** A model to suggest. */
20 model?: string;
21};
22
23/** Every AI provider, in the order people are shown them. */
24export const AI_PROVIDERS: Partial<Record<Provider, AiProviderEntry>> = {
25 anthropic: {
26 group: "labs",
27 blurb: "Claude, on your own Anthropic key.",
28 color: "#d97757",
29 mark: "A",
30 keyUrl: "https://console.anthropic.com/settings/keys",
31 keyPlaceholder: "sk-ant-…",
32 },
33 openai: {
34 group: "labs",
35 blurb: "GPT and the o-series, on your own OpenAI key.",
36 color: "#10a37f",
37 mark: "O",
38 keyUrl: "https://platform.openai.com/api-keys",
39 keyPlaceholder: "sk-…",
40 model: "gpt-5",
41 },
42 gemini: {
43 group: "labs",
44 blurb: "Gemini, on your own Google AI Studio key.",
45 color: "#4285f4",
46 mark: "G",
47 keyUrl: "https://aistudio.google.com/apikey",
48 model: "gemini-2.5-pro",
49 },
50 xai: {
51 group: "labs",
52 blurb: "Grok, on your own xAI key.",
53 color: "#e5e5e5",
54 mark: "x",
55 keyUrl: "https://console.x.ai",
56 keyPlaceholder: "xai-…",
57 model: "grok-4",
58 },
59 mistral: {
60 group: "labs",
61 blurb: "Mistral and Codestral, on your own key.",
62 color: "#fa520f",
63 mark: "M",
64 keyUrl: "https://console.mistral.ai/api-keys",
65 model: "mistral-large-latest",
66 },
67 deepseek: {
68 group: "labs",
69 blurb: "DeepSeek's chat and reasoning models.",
70 color: "#4d6bfe",
71 mark: "D",
72 keyUrl: "https://platform.deepseek.com/api_keys",
73 keyPlaceholder: "sk-…",
74 model: "deepseek-chat",
75 },
76 azure_openai: {
77 group: "platforms",
78 blurb: "OpenAI's models on your own Azure resource and contract.",
79 color: "#0078d4",
80 mark: "Az",
81 },
82 openrouter: {
83 group: "platforms",
84 blurb: "Hundreds of models from every lab, on one key.",
85 color: "#7c7ff5",
86 mark: "OR",
87 keyUrl: "https://openrouter.ai/keys",
88 keyPlaceholder: "sk-or-…",
89 model: "anthropic/claude-sonnet-4.5",
90 },
91 groq: {
92 group: "platforms",
93 blurb: "Open models at very high speed.",
94 color: "#f55036",
95 mark: "Gq",
96 keyUrl: "https://console.groq.com/keys",
97 keyPlaceholder: "gsk_…",
98 model: "moonshotai/kimi-k2-instruct",
99 },
100 together: {
101 group: "platforms",
102 blurb: "Open models: Llama, Qwen, DeepSeek, Kimi.",
103 color: "#0f6fff",
104 mark: "T",
105 keyUrl: "https://api.together.ai/settings/api-keys",
106 model: "Qwen/Qwen3-Coder-480B-A35B-Instruct-FP8",
107 },
108 fireworks: {
109 group: "platforms",
110 blurb: "Fast open models, and your own fine-tunes.",
111 color: "#7c3aed",
112 mark: "F",
113 keyUrl: "https://fireworks.ai/account/api-keys",
114 model: "accounts/fireworks/models/kimi-k2-instruct",
115 },
116 cerebras: {
117 group: "platforms",
118 blurb: "Open models on wafer-scale chips.",
119 color: "#f05a28",
120 mark: "C",
121 keyUrl: "https://cloud.cerebras.ai",
122 keyPlaceholder: "csk-…",
123 model: "qwen-3-coder-480b",
124 },
125 anthropic_endpoint: {
126 group: "any",
127 blurb: "Anything that speaks Anthropic's API: your own gateway, LiteLLM, Bedrock or Vertex behind a proxy.",
128 color: "#a1a1aa",
129 mark: "",
130 },
131 openai_endpoint: {
132 group: "any",
133 blurb: "Anything that speaks OpenAI's API: vLLM, Ollama behind a tunnel, LiteLLM, a gateway.",
134 color: "#a1a1aa",
135 mark: "",
136 },
137};
138
139export const AI_PROVIDER_GROUPS: { group: AiProviderGroup; title: string }[] = [
140 { group: "labs", title: "Labs" },
141 { group: "platforms", title: "Platforms" },
142 { group: "any", title: "Any endpoint" },
143];
144
145/** The AI providers in one group, in catalogue order. */
146export function aiProvidersIn(group: AiProviderGroup): Provider[] {
147 return (Object.keys(AI_PROVIDERS) as Provider[]).filter((provider) => AI_PROVIDERS[provider]!.group === group);
148}
149
150/** Whether a provider is one whose own endpoint the connection gives. */
151export function isEndpoint(provider: Provider): boolean {
152 return provider === "anthropic_endpoint" || provider === "openai_endpoint";
153}