detached d761259

Add Gondola provider

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
commit
d761259be71933bff8508782b885c1727b53562a
author
Codonyat · · 2026-08-11 12:52 UTC
parent
9fa3d04
signature
unsigned
8 files · +39 -2
M docs/providers.md +1 -0
@@ -112,6 +112,7 @@ show instructions and should be configured with environment variables.
112112 | Together AI | `TOGETHER_API_KEY` | `together` |
113113 | Hugging Face | `HF_TOKEN` | `huggingface` |
114114 | OpenRouter | `OPENROUTER_API_KEY` | `openrouter` |
115+| Gondola | `GONDOLA_API_KEY` | `gondola` |
115116 | Mistral | `MISTRAL_API_KEY` | `mistral` |
116117 | ZAI | `ZAI_API_KEY` | `zai` |
117118 | Xiaomi MiMo | `XIAOMI_API_KEY` | `xiaomi` |
@@ -112,6 +112,7 @@ show instructions and should be configured with environment variables.
112 | Together AI | `TOGETHER_API_KEY` | `together` |112 | Together AI | `TOGETHER_API_KEY` | `together` |
113 | Hugging Face | `HF_TOKEN` | `huggingface` |113 | Hugging Face | `HF_TOKEN` | `huggingface` |
114 | OpenRouter | `OPENROUTER_API_KEY` | `openrouter` |114 | OpenRouter | `OPENROUTER_API_KEY` | `openrouter` |
115+| Gondola | `GONDOLA_API_KEY` | `gondola` |
115 | Mistral | `MISTRAL_API_KEY` | `mistral` |116 | Mistral | `MISTRAL_API_KEY` | `mistral` |
116 | ZAI | `ZAI_API_KEY` | `zai` |117 | ZAI | `ZAI_API_KEY` | `zai` |
117 | Xiaomi MiMo | `XIAOMI_API_KEY` | `xiaomi` |118 | Xiaomi MiMo | `XIAOMI_API_KEY` | `xiaomi` |
M packages/agent/build.go +7 -1
@@ -183,6 +183,8 @@ func defaultModelForProvider(prov string) string {
183183 return "moonshotai/Kimi-K2-Instruct"
184184 case "openrouter":
185185 return "anthropic/claude-sonnet-4.5"
186+ case "gondola":
187+ return "claude-opus-5"
186188 case "mistral":
187189 return "mistral-large-latest"
188190 case "zai":
@@ -224,7 +226,7 @@ func defaultModelForProvider(prov string) string {
224226 var knownProviders = []string{
225227 "anthropic", "openai", "openai-codex", "openai-responses", "kimi", "deepseek", "google", "ollama", provider.LlamaCPPProviderID,
226228 "moonshotai", "moonshotai-cn",
227- "cerebras", "groq", "xai", "together", "huggingface", "openrouter",
229+ "cerebras", "groq", "xai", "together", "huggingface", "openrouter", "gondola",
228230 "mistral", "zai",
229231 "xiaomi", "xiaomi-token-plan-ams", "xiaomi-token-plan-cn", "xiaomi-token-plan-sgp",
230232 "minimax", "minimax-cn",
@@ -831,6 +833,8 @@ func (r Resolved) NewClient() provider.Client {
831833 return wrap(provider.NewHuggingFace(r.Credential, r.BaseURL))
832834 case "openrouter":
833835 return wrap(provider.NewOpenRouter(r.Credential, r.BaseURL))
836+ case "gondola":
837+ return wrap(provider.NewGondola(r.Credential, r.BaseURL))
834838 case "zai":
835839 return wrap(provider.NewZAI(r.Credential, r.BaseURL))
836840 case "xiaomi":
@@ -1073,6 +1077,8 @@ func envVarName(provider string) string {
10731077 return "HF"
10741078 case "openrouter":
10751079 return "OPENROUTER"
1080+ case "gondola":
1081+ return "GONDOLA"
10761082 case "mistral":
10771083 return "MISTRAL"
10781084 case "zai":
@@ -183,6 +183,8 @@ func defaultModelForProvider(prov string) string {
183 return "moonshotai/Kimi-K2-Instruct"183 return "moonshotai/Kimi-K2-Instruct"
184 case "openrouter":184 case "openrouter":
185 return "anthropic/claude-sonnet-4.5"185 return "anthropic/claude-sonnet-4.5"
186+ case "gondola":
187+ return "claude-opus-5"
186 case "mistral":188 case "mistral":
187 return "mistral-large-latest"189 return "mistral-large-latest"
188 case "zai":190 case "zai":
@@ -224,7 +226,7 @@ func defaultModelForProvider(prov string) string {
224 var knownProviders = []string{226 var knownProviders = []string{
225 "anthropic", "openai", "openai-codex", "openai-responses", "kimi", "deepseek", "google", "ollama", provider.LlamaCPPProviderID,227 "anthropic", "openai", "openai-codex", "openai-responses", "kimi", "deepseek", "google", "ollama", provider.LlamaCPPProviderID,
226 "moonshotai", "moonshotai-cn",228 "moonshotai", "moonshotai-cn",
227- "cerebras", "groq", "xai", "together", "huggingface", "openrouter",229+ "cerebras", "groq", "xai", "together", "huggingface", "openrouter", "gondola",
228 "mistral", "zai",230 "mistral", "zai",
229 "xiaomi", "xiaomi-token-plan-ams", "xiaomi-token-plan-cn", "xiaomi-token-plan-sgp",231 "xiaomi", "xiaomi-token-plan-ams", "xiaomi-token-plan-cn", "xiaomi-token-plan-sgp",
230 "minimax", "minimax-cn",232 "minimax", "minimax-cn",
@@ -831,6 +833,8 @@ func (r Resolved) NewClient() provider.Client {
831 return wrap(provider.NewHuggingFace(r.Credential, r.BaseURL))833 return wrap(provider.NewHuggingFace(r.Credential, r.BaseURL))
832 case "openrouter":834 case "openrouter":
833 return wrap(provider.NewOpenRouter(r.Credential, r.BaseURL))835 return wrap(provider.NewOpenRouter(r.Credential, r.BaseURL))
836+ case "gondola":
837+ return wrap(provider.NewGondola(r.Credential, r.BaseURL))
834 case "zai":838 case "zai":
835 return wrap(provider.NewZAI(r.Credential, r.BaseURL))839 return wrap(provider.NewZAI(r.Credential, r.BaseURL))
836 case "xiaomi":840 case "xiaomi":
@@ -1073,6 +1077,8 @@ func envVarName(provider string) string {
1073 return "HF"1077 return "HF"
1074 case "openrouter":1078 case "openrouter":
1075 return "OPENROUTER"1079 return "OPENROUTER"
1080+ case "gondola":
1081+ return "GONDOLA"
1076 case "mistral":1082 case "mistral":
1077 return "MISTRAL"1083 return "MISTRAL"
1078 case "zai":1084 case "zai":
M packages/agent/config.go +4 -0
@@ -415,6 +415,10 @@ func resolveCredentialFull(ctx context.Context, provider, explicit string, comma
415415 if v := os.Getenv("OPENROUTER_API_KEY"); v != "" {
416416 return v, "apikey", "", nil
417417 }
418+ case "gondola":
419+ if v := os.Getenv("GONDOLA_API_KEY"); v != "" {
420+ return v, "apikey", "", nil
421+ }
418422 case "mistral":
419423 if v := os.Getenv("MISTRAL_API_KEY"); v != "" {
420424 return v, "apikey", "", nil
@@ -415,6 +415,10 @@ func resolveCredentialFull(ctx context.Context, provider, explicit string, comma
415 if v := os.Getenv("OPENROUTER_API_KEY"); v != "" {415 if v := os.Getenv("OPENROUTER_API_KEY"); v != "" {
416 return v, "apikey", "", nil416 return v, "apikey", "", nil
417 }417 }
418+ case "gondola":
419+ if v := os.Getenv("GONDOLA_API_KEY"); v != "" {
420+ return v, "apikey", "", nil
421+ }
418 case "mistral":422 case "mistral":
419 if v := os.Getenv("MISTRAL_API_KEY"); v != "" {423 if v := os.Getenv("MISTRAL_API_KEY"); v != "" {
420 return v, "apikey", "", nil424 return v, "apikey", "", nil
M packages/provider/auth/probe.go +6 -0
@@ -99,6 +99,12 @@ func ProbeAPIKey(ctx context.Context, provider, key string) error {
9999 return err
100100 }
101101 req.Header.Set("authorization", "Bearer "+key)
102+ case "gondola":
103+ req, err = http.NewRequestWithContext(ctx, "GET", "https://api.gondola-ai.com/v1/models", nil)
104+ if err != nil {
105+ return err
106+ }
107+ req.Header.Set("authorization", "Bearer "+key)
102108 case "huggingface":
103109 req, err = http.NewRequestWithContext(ctx, "GET", "https://router.huggingface.co/v1/models", nil)
104110 if err != nil {
@@ -99,6 +99,12 @@ func ProbeAPIKey(ctx context.Context, provider, key string) error {
99 return err99 return err
100 }100 }
101 req.Header.Set("authorization", "Bearer "+key)101 req.Header.Set("authorization", "Bearer "+key)
102+ case "gondola":
103+ req, err = http.NewRequestWithContext(ctx, "GET", "https://api.gondola-ai.com/v1/models", nil)
104+ if err != nil {
105+ return err
106+ }
107+ req.Header.Set("authorization", "Bearer "+key)
102 case "huggingface":108 case "huggingface":
103 req, err = http.NewRequestWithContext(ctx, "GET", "https://router.huggingface.co/v1/models", nil)109 req, err = http.NewRequestWithContext(ctx, "GET", "https://router.huggingface.co/v1/models", nil)
104 if err != nil {110 if err != nil {
M packages/provider/auth/server.go +1 -1
@@ -138,7 +138,7 @@ func APIKeyProviders() []string {
138138 return []string{
139139 "anthropic", "openai", "kimi", "deepseek", "google", "llama.cpp",
140140 "moonshotai", "moonshotai-cn", "groq", "cerebras", "xai", "together",
141- "huggingface", "openrouter", "mistral", "zai",
141+ "huggingface", "openrouter", "gondola", "mistral", "zai",
142142 "xiaomi", "xiaomi-token-plan-ams", "xiaomi-token-plan-cn", "xiaomi-token-plan-sgp",
143143 "minimax", "minimax-cn", "fireworks", "vercel-ai-gateway",
144144 "opencode", "opencode-go", "amazon-bedrock", "google-vertex", "azure-openai-responses",
@@ -138,7 +138,7 @@ func APIKeyProviders() []string {
138 return []string{138 return []string{
139 "anthropic", "openai", "kimi", "deepseek", "google", "llama.cpp",139 "anthropic", "openai", "kimi", "deepseek", "google", "llama.cpp",
140 "moonshotai", "moonshotai-cn", "groq", "cerebras", "xai", "together",140 "moonshotai", "moonshotai-cn", "groq", "cerebras", "xai", "together",
141- "huggingface", "openrouter", "mistral", "zai",141+ "huggingface", "openrouter", "gondola", "mistral", "zai",
142 "xiaomi", "xiaomi-token-plan-ams", "xiaomi-token-plan-cn", "xiaomi-token-plan-sgp",142 "xiaomi", "xiaomi-token-plan-ams", "xiaomi-token-plan-cn", "xiaomi-token-plan-sgp",
143 "minimax", "minimax-cn", "fireworks", "vercel-ai-gateway",143 "minimax", "minimax-cn", "fireworks", "vercel-ai-gateway",
144 "opencode", "opencode-go", "amazon-bedrock", "google-vertex", "azure-openai-responses",144 "opencode", "opencode-go", "amazon-bedrock", "google-vertex", "azure-openai-responses",
M packages/provider/extra_providers.go +6 -0
@@ -116,6 +116,12 @@ func NewOpenRouter(apiKey, baseURL string) Client {
116116 return NewOpenAICompat("openrouter", apiKey, baseURL, openrouterDefaultBaseURL)
117117 }
118118
119+// NewGondola: Gondola, a USDC-paid marketplace gateway for Venice AI
120+// inference. OpenAI Chat Completions-compatible.
121+func NewGondola(apiKey, baseURL string) Client {
122+ return NewOpenAICompat("gondola", apiKey, baseURL, "https://api.gondola-ai.com/v1")
123+}
124+
119125 // NewOpenCode is the opencode.ai Zen endpoint. Mixed APIs upstream; this
120126 // constructor wires the openai-completions flavor only. Models that need
121127 // the anthropic-messages flavor under the same provider should be built
@@ -116,6 +116,12 @@ func NewOpenRouter(apiKey, baseURL string) Client {
116 return NewOpenAICompat("openrouter", apiKey, baseURL, openrouterDefaultBaseURL)116 return NewOpenAICompat("openrouter", apiKey, baseURL, openrouterDefaultBaseURL)
117 }117 }
118 118
119+// NewGondola: Gondola, a USDC-paid marketplace gateway for Venice AI
120+// inference. OpenAI Chat Completions-compatible.
121+func NewGondola(apiKey, baseURL string) Client {
122+ return NewOpenAICompat("gondola", apiKey, baseURL, "https://api.gondola-ai.com/v1")
123+}
124+
119 // NewOpenCode is the opencode.ai Zen endpoint. Mixed APIs upstream; this125 // NewOpenCode is the opencode.ai Zen endpoint. Mixed APIs upstream; this
120 // constructor wires the openai-completions flavor only. Models that need126 // constructor wires the openai-completions flavor only. Models that need
121 // the anthropic-messages flavor under the same provider should be built127 // the anthropic-messages flavor under the same provider should be built
M packages/provider/labels.go +2 -0
@@ -37,6 +37,8 @@ func ProviderLabel(id string) string {
3737 return "Hugging Face"
3838 case "openrouter":
3939 return "OpenRouter"
40+ case "gondola":
41+ return "Gondola"
4042 case "mistral":
4143 return "Mistral"
4244 case "zai":
@@ -37,6 +37,8 @@ func ProviderLabel(id string) string {
37 return "Hugging Face"37 return "Hugging Face"
38 case "openrouter":38 case "openrouter":
39 return "OpenRouter"39 return "OpenRouter"
40+ case "gondola":
41+ return "Gondola"
40 case "mistral":42 case "mistral":
41 return "Mistral"43 return "Mistral"
42 case "zai":44 case "zai":
M packages/provider/models.go +12 -0
@@ -254,6 +254,18 @@ var Catalog = []Model{
254254 BaseURL: openrouterDefaultBaseURL,
255255 },
256256
257+ // ---- Gondola ----
258+ // Seed entry only: the default model returned by defaultModelForProvider
259+ // so it resolves offline. Gondola is a USDC-paid marketplace gateway for
260+ // Venice AI inference; prices/limits pulled live from
261+ // https://api.gondola-ai.com/v1/models (2026-08-11).
262+ {
263+ Provider: "gondola", ID: "claude-opus-5", DisplayName: "Claude Opus 5 (Gondola)",
264+ ContextWindow: 1000000, MaxOutput: 128000, Reasoning: true, AdaptiveThinking: true,
265+ PriceInput: 1.836, PriceOutput: 9.18,
266+ BaseURL: "https://api.gondola-ai.com/v1",
267+ },
268+
257269 // ---- Speculative: Anthropic ----
258270 {
259271 Provider: "anthropic", ID: "claude-opus-4-5", DisplayName: "Claude Opus 4.5 (latest)",
@@ -254,6 +254,18 @@ var Catalog = []Model{
254 BaseURL: openrouterDefaultBaseURL,254 BaseURL: openrouterDefaultBaseURL,
255 },255 },
256 256
257+ // ---- Gondola ----
258+ // Seed entry only: the default model returned by defaultModelForProvider
259+ // so it resolves offline. Gondola is a USDC-paid marketplace gateway for
260+ // Venice AI inference; prices/limits pulled live from
261+ // https://api.gondola-ai.com/v1/models (2026-08-11).
262+ {
263+ Provider: "gondola", ID: "claude-opus-5", DisplayName: "Claude Opus 5 (Gondola)",
264+ ContextWindow: 1000000, MaxOutput: 128000, Reasoning: true, AdaptiveThinking: true,
265+ PriceInput: 1.836, PriceOutput: 9.18,
266+ BaseURL: "https://api.gondola-ai.com/v1",
267+ },
268+
257 // ---- Speculative: Anthropic ----269 // ---- Speculative: Anthropic ----
258 {270 {
259 Provider: "anthropic", ID: "claude-opus-4-5", DisplayName: "Claude Opus 4.5 (latest)",271 Provider: "anthropic", ID: "claude-opus-4-5", DisplayName: "Claude Opus 4.5 (latest)",

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 476

↑↓ moveenter openesc close