Skip to content

feat: add Gondola channel - #6672

Closed
Codonyat wants to merge 2 commits into
QuantumNous:mainfrom
Codonyat:feat/gondola-channel
Closed

feat: add Gondola channel#6672
Codonyat wants to merge 2 commits into
QuantumNous:mainfrom
Codonyat:feat/gondola-channel

Conversation

@Codonyat

@Codonyat Codonyat commented Aug 5, 2026

Copy link
Copy Markdown

Adds Gondola (https://gondola-ai.com) as a first-class channel type (61).

Gondola is an OpenAI-compatible marketplace for Venice AI inference: it routes each request to the cheapest available supplier and exposes one gateway at https://api.gondola-ai.com. 260+ models (text, image, video), including an uncensored line. Keys look like gnd_....

Why a dedicated channel type

Operators can already point a Custom channel at Gondola, so this is partly convenience (pre-filled base URL, icon, seed model list). But two of the registrations are functional, not cosmetic:

  • streamSupportedChannels — Gondola supports stream_options: {"include_usage": true} and returns a final usage-only chunk. Without the entry, compatible_handler.go strips the option and streamed requests fall back to estimated token counts instead of upstream-reported usage. Verified against the live API.
  • EndpointTypeAnthropic — Gondola serves a native Anthropic Messages endpoint at /v1/messages (streaming and non-streaming, with usage). The adaptor passes Claude-format requests straight through rather than converting them down to /v1/chat/completions the way a generic OpenAI channel does. Verified against the live API.

GET /v1/models is public and needs no auth, so the default fetch path already works and the channel is added to MODEL_FETCHABLE_TYPES.

Changes

Backend, following the moonshot / New API (#60) precedent:

  • constant/channel.goChannelTypeGondola = 61, base URL, display name.
  • constant/api_type.goAPITypeGondola, inserted before APITypeDummy.
  • common/api_type.goChannelType2APIType mapping.
  • common/endpoint_type.go — OpenAI + Anthropic endpoints.
  • relay/common/relay_info.gostreamSupportedChannels entry.
  • relay/channel/gondola/{adaptor.go,constants.go} — new adaptor. Chat/image delegate to openai.Adaptor, Claude format to claude.Adaptor; rerank/embedding/audio/gemini/responses report unsupported (Gondola serves none of them: /v1/completions and /v1/rerank 404, /v1/embeddings 501).
  • relay/relay_adaptor.go — switch branch.

Frontend:

  • constants.ts — type label, display order, MODEL_FETCHABLE_TYPES, key-format hint.
  • channel-type-config.ts / channel-utils.ts — config entry + icon mapping.
  • assets/custom/icon-gondola.tsx + lib/lobe-icon.tsx — custom icon (@lobehub/icons has no Gondola glyph), following the Sub2API pattern.

ModelList is a small seed set; the catalog is a live marketplace, so operators are expected to use "Fetch Models". No model_ratio.go defaults, since marketplace prices are dynamic and static entries would be misleading.

Verification

Ran the CI gate set locally (GOWORK=off, with the web/dist placeholder):

  • go vet ./... and go build ./... pass for both the root module and relaykit.
  • make test passes except for two failures in ./service/ (TestObserveChannelAffinityUsageCacheByRelayFormat_MixedMode and ..._UnsupportedModeKeepsEmpty) that reproduce identically on an unmodified main, so they are unrelated to this change.
  • bun run typecheck passes. bun test shows the same 12 failures on this branch as on unmodified main (they are describe()-inside-test() cases that Bun does not implement on my platform); the 4 channel test files pass, including the 2 new Gondola cases.

Placement of 61 in CHANNEL_TYPE_DISPLAY_ORDER is next to OpenRouter (same product category); happy to move it if you would rather it sit elsewhere.

Summary by CodeRabbit

  • New Features
    • Added Gondola as a supported channel, including its default base URL, API key guidance, and model discovery.
    • Enabled Gondola for streaming-capable options.
    • Added Gondola request routing for both OpenAI-compatible and Claude Messages styles, plus updated endpoint prioritization.
    • Included Gondola branding via a new UI icon across the interface.
  • Tests
    • Added Gondola channel tests covering configuration, ordering, icon rendering, base URL validation, and model availability.

Gondola (https://gondola-ai.com) is an OpenAI-compatible marketplace for
Venice AI inference. Registers it as channel type 61 following the
moonshot / New API precedent.

Beyond the usual registration, two entries are functional rather than
cosmetic: Gondola honors stream_options include_usage, so the
streamSupportedChannels entry keeps streamed requests billing on
upstream-reported usage instead of estimates; and Gondola serves a native
Anthropic Messages endpoint at /v1/messages, so the adaptor passes
Claude-format requests through rather than converting them down to
/v1/chat/completions.

Rerank, embeddings, audio, Gemini and Responses report unsupported,
matching what the upstream actually serves.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e02eca98-6c29-4063-a489-0556e875bb69

📥 Commits

Reviewing files that changed from the base of the PR and between c940412 and 3186976.

📒 Files selected for processing (2)
  • web/src/assets/custom/icon-gondola.tsx
  • web/src/features/channels/lib/__tests__/gondola-channel.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • web/src/features/channels/lib/tests/gondola-channel.test.ts

Walkthrough

Gondola is added as a backend and frontend channel. The change defines channel and API constants, registers relay routing, supports OpenAI and Claude Messages requests, enables streaming, and adds frontend metadata, validation, and icons.

Changes

Gondola channel integration

Layer / File(s) Summary
Backend channel contracts
common/api_type.go, common/endpoint_type.go, constant/api_type.go, constant/channel.go, relay/common/relay_info.go
Adds Gondola constants, API and endpoint mappings, display metadata, and streaming support.
Relay adaptor and dispatch
relay/channel/gondola/*, relay/relay_adaptor.go
Adds authenticated OpenAI and Claude Messages routing, request conversions, response handling, model metadata, and adaptor dispatch.
Frontend channel registration
web/src/features/channels/*, web/src/assets/custom/icon-gondola.tsx, web/src/lib/lobe-icon.tsx, web/src/features/channels/lib/__tests__/gondola-channel.test.ts
Adds Gondola configuration, model-fetch support, API-key prompts, icon registration, and channel form tests.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant GetAdaptor
  participant GondolaAdaptor
  participant GondolaAPI
  Client->>GetAdaptor: request with APITypeGondola
  GetAdaptor->>GondolaAdaptor: create adaptor
  GondolaAdaptor->>GondolaAdaptor: select OpenAI or Claude route
  GondolaAdaptor->>GondolaAPI: send authenticated request
  GondolaAPI-->>GondolaAdaptor: response
  GondolaAdaptor-->>Client: converted response
Loading

Possibly related PRs

Poem

A rabbit rows through code so bright,
Gondola joins the API flight.
OpenAI and Claude paths align,
With icons and forms in a tidy line.
Tests watch the channel shine.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the primary change: adding Gondola as a channel.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
web/src/features/channels/lib/__tests__/gondola-channel.test.ts (2)

43-69: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Split this test into focused behaviors.

This test combines option registration, ordering, model fetching, icon selection, key prompt, and channel configuration. Use one test for each behavior so a failure identifies the broken contract.

As per coding guidelines, “每个用例只保护一个可描述行为”.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/src/features/channels/lib/__tests__/gondola-channel.test.ts` around lines
43 - 69, Split the combined test around CHANNEL_TYPE_GONDOLA into focused tests,
with separate cases for option registration, ordering, model fetchability, icon
selection, key prompt text, and channel configuration/defaultBaseUrl. Keep each
assertion group limited to one describable behavior so failures identify the
specific broken contract.

Source: Coding guidelines


31-40: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add an explicit return type to gondolaForm.

Declare the returned form-value type. This keeps the fixture contract explicit when CHANNEL_FORM_DEFAULT_VALUES changes.

As per coding guidelines, “参数和返回值应显式标注类型”.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/src/features/channels/lib/__tests__/gondola-channel.test.ts` around lines
31 - 40, Update the gondolaForm function to explicitly declare its return type
using the existing channel form-value type, while preserving the current fixture
fields and values.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@web/src/assets/custom/icon-gondola.tsx`:
- Around line 27-35: Update IconGondola’s SVG in the custom icon component to be
accessible and theme-aware: add an explicit aria-hidden="true" for decorative
usage, or provide an accessible name on the IconGondola wrapper/path when it
serves as the only identifier. Replace the hard-coded stroke color in the svg
element with currentColor or a theme CSS variable so styling follows the active
theme, and keep the change localized to the IconGondola component and its svg
props.

In `@web/src/features/channels/constants.ts`:
- Line 86: Replace the Gondola display literal in
web/src/features/channels/constants.ts:86 with a semantic translation key and
resolve it with t() at the UI display boundary; apply the same pattern to the
API-key prompt at web/src/features/channels/constants.ts:409. In
web/src/features/channels/lib/channel-type-config.ts:173-174, store translation
keys for the key and model-hint labels and translate them where rendered. Update
web/src/features/channels/lib/__tests__/gondola-channel.test.ts:48-68 to assert
the translation-key semantics or rendered output under a fixed locale.

---

Nitpick comments:
In `@web/src/features/channels/lib/__tests__/gondola-channel.test.ts`:
- Around line 43-69: Split the combined test around CHANNEL_TYPE_GONDOLA into
focused tests, with separate cases for option registration, ordering, model
fetchability, icon selection, key prompt text, and channel
configuration/defaultBaseUrl. Keep each assertion group limited to one
describable behavior so failures identify the specific broken contract.
- Around line 31-40: Update the gondolaForm function to explicitly declare its
return type using the existing channel form-value type, while preserving the
current fixture fields and values.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: fe80c684-696a-4943-b6f0-e49b805ba9dd

📥 Commits

Reviewing files that changed from the base of the PR and between 0ab0202 and c940412.

📒 Files selected for processing (14)
  • common/api_type.go
  • common/endpoint_type.go
  • constant/api_type.go
  • constant/channel.go
  • relay/channel/gondola/adaptor.go
  • relay/channel/gondola/constants.go
  • relay/common/relay_info.go
  • relay/relay_adaptor.go
  • web/src/assets/custom/icon-gondola.tsx
  • web/src/features/channels/constants.ts
  • web/src/features/channels/lib/__tests__/gondola-channel.test.ts
  • web/src/features/channels/lib/channel-type-config.ts
  • web/src/features/channels/lib/channel-utils.ts
  • web/src/lib/lobe-icon.tsx

Comment on lines +27 to +35
<svg
xmlns='http://www.w3.org/2000/svg'
viewBox='0 0 32 32'
width={size}
height={size}
fill='none'
stroke='#c9a96a'
strokeLinecap='round'
{...props}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Make the custom SVG accessible and theme-aware.

IconGondola has no accessible name and no aria-hidden attribute. Mark it aria-hidden='true' when it is decorative. If it can be the only channel identifier, provide an accessible name.

stroke='#c9a96a' bypasses the theme system. Use a theme CSS variable or currentColor with theme-controlled styling.

As per coding guidelines, “装饰性图标使用 aria-hidden="true"” and “主题使用 CSS 变量与 dark:”.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/src/assets/custom/icon-gondola.tsx` around lines 27 - 35, Update
IconGondola’s SVG in the custom icon component to be accessible and theme-aware:
add an explicit aria-hidden="true" for decorative usage, or provide an
accessible name on the IconGondola wrapper/path when it serves as the only
identifier. Replace the hard-coded stroke color in the svg element with
currentColor or a theme CSS variable so styling follows the active theme, and
keep the change localized to the IconGondola component and its svg props.

Source: Coding guidelines

58: 'Advanced Custom',
59: 'Sub2API',
60: 'New API',
61: 'Gondola',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Move Gondola display strings to i18n resources.

The new frontend literals bypass i18next. Store semantic translation keys and resolve them with t() where the UI displays them.

  • web/src/features/channels/constants.ts#L86-L86: replace the Gondola display literal with an i18n-backed label.
  • web/src/features/channels/constants.ts#L409-L409: store a semantic API-key prompt key and translate it at the display boundary.
  • web/src/features/channels/lib/channel-type-config.ts#L173-L174: replace the key and model hint literals with translation keys.
  • web/src/features/channels/lib/__tests__/gondola-channel.test.ts#L48-L68: assert translation-key semantics or output under a fixed test locale.

As per coding guidelines, “面向用户的文案必须使用 i18n” and “常量中的消息和状态 label 应保存翻译键,并在展示时通过 t() 翻译”.

📍 Affects 3 files
  • web/src/features/channels/constants.ts#L86-L86 (this comment)
  • web/src/features/channels/constants.ts#L409-L409
  • web/src/features/channels/lib/channel-type-config.ts#L173-L174
  • web/src/features/channels/lib/__tests__/gondola-channel.test.ts#L48-L68
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/src/features/channels/constants.ts` at line 86, Replace the Gondola
display literal in web/src/features/channels/constants.ts:86 with a semantic
translation key and resolve it with t() at the UI display boundary; apply the
same pattern to the API-key prompt at
web/src/features/channels/constants.ts:409. In
web/src/features/channels/lib/channel-type-config.ts:173-174, store translation
keys for the key and model-hint labels and translate them where rendered. Update
web/src/features/channels/lib/__tests__/gondola-channel.test.ts:48-68 to assert
the translation-key semantics or rendered output under a fixed locale.

Source: Coding guidelines

…om a11y tree

Addresses CodeRabbit review on QuantumNous#6672: one describable behavior per test case,
explicit ChannelFormValues return type on the form fixture, and aria-hidden on
the decorative channel icon.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Codonyat

Codonyat commented Aug 5, 2026

Copy link
Copy Markdown
Author

Thanks for the review. Pushed 3186976 for three of the four:

  • Split the channel test into one describable behavior per case.
  • Explicit ChannelFormValues return type on the form fixture.
  • aria-hidden='true' (plus focusable='false') on the icon, which is decorative next to the channel name.

Leaving two as-is, and happy to change either if you disagree:

i18n keys for the display strings. The header of constants.ts states that all label/name values are the i18n keys and are resolved with t(value) at display time, and every sibling follows that: CHANNEL_TYPES uses brand literals ('Sub2API', 'New API', 'OpenAI'), TYPE_TO_KEY_PROMPT uses English sentences directly ('Format: APIKey|SecretKey'), and channel-type-config.ts hints do the same ('DeepSeek API Key'). Sub2API has no locale entry in any file and renders fine via react-i18next key fallback. Introducing separate semantic keys just for Gondola would make it the only channel on a different scheme.

currentColor for the icon stroke. This is a brand mark, so it keeps its brand color the same way icon-sub2api.tsx hardcodes its brand gradient and the @lobehub/icons provider glyphs keep theirs. #c9a96a is a muted gold that reads on both light and dark backgrounds. Switching to currentColor would make Gondola the only monochrome provider icon in the picker.

@seefs001 seefs001 closed this Aug 11, 2026
@coderabbitai coderabbitai Bot mentioned this pull request Aug 15, 2026
11 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants