Skip to content

feat(ai): add Opper as an AI provider - #1265

Open
Felixkw12 wants to merge 6 commits into
TabularisDB:mainfrom
Felixkw12:add-opper-provider
Open

Felixkw12 wants to merge 6 commits into
TabularisDB:mainfrom
Felixkw12:add-opper-provider

Conversation

@Felixkw12

Copy link
Copy Markdown

Summary

Adds Opper, an EU-hosted, OpenAI-compatible AI gateway (700+ models from 50+ providers behind one API key), as an AI provider. It follows the Requesty integration step by step, so it shows up in Settings > AI next to Requesty and works for SQL generation, query explanation, explain plan analysis, cell and tab naming and table name suggestions.

Changes

  • src-tauri/src/ai.rs: generate_opper (POST https://api.opper.ai/v3/compat/chat/completions, same body as Requesty, with an X-Opper-Name: tabularis header so calls are labelled in Opper's traces), dispatch arm, and fetch_opper_models, which reads Opper's public catalog (GET https://api.opper.ai/v3/models, no key needed) and keeps pooled chat models without duplicates. Merged into the static list like OpenRouter and Requesty.
  • src-tauri/src/ai_models.yaml: opper entry with claude-sonnet-4-6 first as the default, plus a few more pool names. All ids checked against the live catalog.
  • src-tauri/src/application/ai.rs, src-tauri/src/transport/desktop/config.rs: OPPER_API_KEY env var for key lookup and key status.
  • packages/web-ui: provider type, label, settings entry, key status check and an Opper icon (single colour, currentColor).
  • Opper is left out of the automatic provider detection, so it is only used when picked explicitly. A test covers that, next to the Requesty one, plus a label test and the default models assertion in Rust.
  • READMEs (all languages), .gitster/gitster.md and snap/snapcraft.yaml: Opper added to the provider lists.

Pool names such as claude-sonnet-4-6 let Opper pick the provider per request; a provider/model id such as anthropic/claude-sonnet-4-6 pins one route.

How to test

  1. Get a key at https://platform.opper.ai and either save it in Settings > AI > Opper or export OPPER_API_KEY.
  2. Pick Opper and the model claude-sonnet-4-6 (or refresh the model list to see all pooled models).
  3. Generate a query from natural language or explain a query.

Checks

I did not run the toolchains locally (no pnpm, cargo or vitest run); CI will be the first run. The new Rust code is written to rustfmt defaults and the TypeScript to the repo's Prettier config by hand. Model ids were checked against Opper's public catalog.

Disclosure: Opper is my startup. Happy to adjust anything to match project conventions.

Adds Opper as a built-in AI provider, in the same places as Requesty:
API key lookup (keychain, then OPPER_API_KEY), a curated model list in
ai_models.yaml, dynamic model discovery from Opper's public catalog,
and generation through https://api.opper.ai/v3/compat/chat/completions
with an X-Opper-Name: tabularis header. It is not part of the automatic
provider detection.

Opper is an EU-hosted, OpenAI-compatible AI gateway: 700+ models from
50+ providers behind one API key. Discovery keeps pooled chat models
(bare names such as claude-sonnet-4-6, where Opper picks the route).

Also lists Opper among the AI providers in the READMEs, the snap
description and the gitster summary, and adds tests next to the
Requesty ones (default models, provider label, no auto-select).

Disclosure: Opper is my startup.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Felix Wunderlich <felix@opper.ai>
@kilo-code-bot

kilo-code-bot Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

The PR mirrors every Requesty touchpoint for Opper: Rust dispatch, key lookup in both env-var paths, model discovery, YAML defaults, web-ui type/label/settings entry/key-status check, tests, and docs. Opper is correctly excluded from automatic provider detection.

The incremental change since the last review (fix(ai): handle the client result in fetch_opper_models) adapts fetch_opper_models to ai_client_for now returning Result<Client, String>. It uses the same let Ok(client) = ... else { return Vec::new(); } pattern as the other model fetchers, and dispatch_provider already propagates the Result with ?. No bugs, security problems, or missing integration points were found in the changed lines.

Assumptions and gaps: the Opper API behaviour (/v3/models schema, /v3/compat/chat/completions response shape) and the model ids in ai_models.yaml were not verified against the live service, and no tests were executed (read-only review). The PR author disclosed that Opper is their own startup.

Files Reviewed (23 files)
  • .gitster/gitster.md
  • README.md
  • docs/translations/README.{de,es,fr,it,ja,ko,pt-BR,ru,tl,zh-CN}.md
  • packages/web-ui/src/components/icons/ClientIcons.tsx
  • packages/web-ui/src/components/settings/AiTab.tsx
  • packages/web-ui/src/contexts/SettingsContext.ts
  • packages/web-ui/src/utils/settingsUI.ts
  • packages/web-ui/tests/utils/settings.test.ts
  • packages/web-ui/tests/utils/settingsUI.test.ts
  • snap/snapcraft.yaml
  • src-tauri/src/ai.rs
  • src-tauri/src/ai_models.yaml
  • src-tauri/src/application/ai.rs
  • src-tauri/src/transport/desktop/config.rs
Previous Review Summary (commit 28b0573)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 28b0573)

Status: No Issues Found | Recommendation: Merge

The PR mirrors every Requesty touchpoint for Opper (Rust dispatch, key lookup in both env-var paths, model discovery, YAML defaults, web-ui type/label/settings entry/key-status check, tests, docs). Opper is correctly excluded from automatic provider detection. No bugs, security problems, or missing integration points were found in the changed lines.

Assumptions and gaps: the Opper API behaviour (/v3/models schema, /v3/compat/chat/completions response shape) and the model ids in ai_models.yaml were not verified against the live service, and no tests were executed (read-only review). The PR author disclosed that Opper is their own startup.

Files Reviewed (23 files)
  • .gitster/gitster.md
  • README.md
  • docs/translations/README.{de,es,fr,it,ja,ko,pt-BR,ru,tl,zh-CN}.md
  • packages/web-ui/src/components/icons/ClientIcons.tsx
  • packages/web-ui/src/components/settings/AiTab.tsx
  • packages/web-ui/src/contexts/SettingsContext.ts
  • packages/web-ui/src/utils/settingsUI.ts
  • packages/web-ui/tests/utils/settings.test.ts
  • packages/web-ui/tests/utils/settingsUI.test.ts
  • snap/snapcraft.yaml
  • src-tauri/src/ai.rs
  • src-tauri/src/ai_models.yaml
  • src-tauri/src/application/ai.rs
  • src-tauri/src/transport/desktop/config.rs

Reviewed by claude-sonnet-5.5 · Input: 248 · Output: 1.9K · Cached: 292K

Review guidance: REVIEW.md from base branch main

@debba debba left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for adding Opper across the provider settings, key lookup and model catalogue, and for being upfront about your connection to the service. Keeping it out of automatic provider selection is a thoughtful default. The settings and provider-label suites passed, with 97 tests in total.

Welcome with your first PR here! We'd be happy to have you join us on Discord if you'd like: https://discord.com/invite/K2hmhfHRSt

I haven't found a blocking issue in the diff. I'll run the desktop end-to-end checks and the remaining validation before merging. I'll report any part that I can't verify against the live service.

@debba debba left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks again for the integration. I hit a build blocker when checking it against the updated main.

To reproduce:

  1. Check out this PR and merge the current main locally.
  2. Run pnpm tauri build --debug --no-bundle -- --features e2e-testing.

The app should build so the Opper settings and requests can be tested. Instead, Rust stops in src-tauri/src/ai.rs, in fetch_opper_models, with E0599: no method named get found for enum Result<reqwest::Client, String>.

Since #1283, ai_client_for returns Result<Client, String>. The new fetcher still assigns that result directly to client and calls .get() on it. Please rebase and handle the result here, as the other model fetchers now do, while preserving the custom-proxy failure behavior.

Lint and typecheck passed. I couldn't reach the desktop or live-provider tests because the build fails, so I'm holding the merge until this is fixed.

Felixkw12 and others added 2 commits October 26, 2026 16:03
Signed-off-by: Felix Wunderlich <felix@opper.ai>
Since TabularisDB#1283 ai_client_for returns Result<Client, String>. Match the other model fetchers and return no dynamic models when the client cannot be built, which keeps the custom proxy failure behavior.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Felix Wunderlich <felix@opper.ai>
@Felixkw12

Copy link
Copy Markdown
Author

Thanks for checking it against main. I merged the current main into the branch and fixed fetch_opper_models to handle the Result from ai_client_for, the same way the other fetchers do since #1283. If the client cannot be built it returns no dynamic models, so the custom proxy failure behavior stays the same. I merged instead of rebasing to avoid a force push. Happy to squash if you prefer. I have not run the Tauri build myself, so your e2e run will be the first full build of this change.

debba
debba previously approved these changes Oct 29, 2026

@debba debba left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the quick turnaround on the ai_client_for change. The let Ok(client) = ai_client_for("opper") else { return Vec::new(); } guard is how the other fetchers handle it now, so a broken proxy config just leaves Opper with its static model list, which is what I was after. Merging main instead of force pushing is fine, we squash on merge anyway.

I rebuilt it on my side: cargo check passes with the desktop features and with --no-default-features, the ai tests pass (including the new opper assertion in the default models test), and the settings and label suites are green with 97 tests. The web UI build passes too. I also hit the public /v3/models endpoint without a key to check the response shape against the parser: the model, pooled and type fields line up, and all the ids in ai_models.yaml show up among the pooled chat models.

Nothing blocking anymore, so I'm approving. Two things I'd keep as follow-ups, not for this PR:

  1. generate_opper could get a case in ai_provider_tests.rs so the X-Opper-Name header and the endpoint path are covered by the fixture tests.
  2. The model fetch pulls the whole catalog with a fixed limit=2000. That's fine today, but the list would be cut off silently if the catalog ever grows past it.

The CI workflows still need a maintainer approval to run since this is your first PR here. I'll get those going and do the manual desktop checks against the live service before merging.

debba and others added 2 commits October 29, 2026 09:15
Resolves the ai_models.yaml conflict: main's new MiniMax entries stay in
the Requesty list, and the Opper list follows it unchanged.

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

Copy link
Copy Markdown
Author

Merged the current main to resolve the conflict in ai_models.yaml (main's new MiniMax entries kept in the Requesty list, Opper list unchanged). No other changes.

@NewtTheWolf NewtTheWolf left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the ai_client_for error handling update. On 6e70468, the 97 affected frontend tests, typecheck and all 2,279 Rust library tests pass locally.

The branch currently conflicts with main in src-tauri/src/ai.rs, which has gained further provider and inline-completion changes. Please rebase and preserve those paths. I do not have a live Opper account for the promised account/catalog and generation checks, so those remain unverified. I am leaving this open for the integration update and service verification.

Resolves the conflicts with API Route (TabularisDB#1459) and the inline completion
and optional-key changes (TabularisDB#1455, TabularisDB#1457). Both providers are kept in every
list, with Opper after Requesty and API Route after Opper. In ai.rs the
Opper model fetch stays as step 7, followed by main's new custom-openai
discovery and the API Route catalog. Inline completion goes through
dispatch_provider, so it reaches Opper without further changes.

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

Copy link
Copy Markdown
Author

Thanks @NewtTheWolf. I merged the current main into the branch in a6f136c, the same way as before since you squash on merge. The conflicts were with API Route (#1459) and the inline completion and optional key changes (#1455, #1457). Both providers are now kept in every list. In ai.rs the Opper model fetch stays as step 7, followed by main's new custom-openai discovery and the API Route catalog. Inline completion goes through dispatch_provider, so it reaches Opper without further changes. Against main the diff is still Opper only, the same 23 files.

For the account, catalog and generation checks: if you sign up at https://platform.opper.ai and send the account email to hello@opper.ai, we will put $10 of credits on it for testing. The catalog check needs no key, since GET https://api.opper.ai/v3/models is public.

@debba

debba commented Nov 12, 2026

Copy link
Copy Markdown
Collaborator

The external AI assistant runtime from #1337 is now on main, and the production Tabularium registry now accepts ai-assistant packages. The runtime version to declare for the next nightly, expected on November 13, 2026, is:

"min_runtime_version": "0.32.1-4"

The current nightly is 0.32.1-3; 0.32.1-4 has not shipped yet. A package can be published now with this floor and used once that nightly (or a newer compatible runtime) is installed.

For a complete published example, see Google Gemini on Tabularium, the Gemini plugin repository, and release 1.0.2. The release includes the standalone .tabularium manifest and a universal ZIP; both declare the same plugin version and runtime floor. Gemini is approved and indexed with hashes and signed integrity metadata, and its repository webhook is active.

The authoring guide describes the declarative HTTP contract. New providers should use an external ai-assistant package, with credentials, requests and model discovery managed by the host.

Please port the Opper integration in this PR to that package format; Gemini demonstrates the repository and release structure to follow.

@NewtTheWolf NewtTheWolf left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for fixing the earlier ai_client_for integration and updating the branch. The target architecture has now changed: #1337 is merged, and external providers are declarative ai-assistant packages instead of additional Rust dispatch arms and hardcoded settings controls.

Please port Opper onto current main using plugins/ai-assistants/packages/opper/.tabularium and plugins/ai-assistants/README.md as the starting point. That existing example already expresses /v3/compat/chat/completions, X-Opper-Name: tabularis, the unauthenticated model source and its llm/pooled filters. Preserve the public catalog behavior and add fixture coverage for the generation path when validating the package. The Opper package will need an independent release and the real first supporting runtime version before production listing; the eight bundled providers do not need replacement releases.

On the current a6f136cb head, the focused frontend suites, typecheck and production build pass. pnpm lint fails Prettier on packages/web-ui/src/components/settings/AiTab.tsx, and GitHub reports conflicts with main. I also fetched the public models endpoint successfully: its response still has the fields the parser expects. I have not run a paid generation request or backend tests on this current head.

Requesting changes for the port and integration. This supersedes the old hardcoded-provider merge path; it does not require adding provider-specific Rust code to the new generic host.

This branch has not been deployed

No deployments
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.

3 participants