Skip to content

feat(media): add OrcaRouter image provider - #6723

Open
Marc-oss-hub wants to merge 1 commit into
nexu-io:mainfrom
Marc-oss-hub:feat/orcarouter-media-provider
Open

feat(media): add OrcaRouter image provider#6723
Marc-oss-hub wants to merge 1 commit into
nexu-io:mainfrom
Marc-oss-hub:feat/orcarouter-media-provider

Conversation

@Marc-oss-hub

Copy link
Copy Markdown

Why

I use Open Design for quick image generation loops and recently wanted to route image generation through OrcaRouter, an OpenAI-compatible gateway that exposes 160+ models (OpenAI, Gemini, xAI, and more) behind a single key. Open Design already shipped a named openrouter provider, so an orcarouter provider is a natural addition — the same class of "one API key, many image models" gateway, wired through the same OpenAI-standard /v1/images/generations contract the daemon already speaks for OpenAI and ImageRouter.

The pain being addressed: users who hold an OrcaRouter key currently have no first-class surface in Settings or the model picker. They could work around it by hand-writing a custom OpenAI-compatible endpoint, but that loses the named provider UX (label, docs link, key hint, catalog models) every other integrated gateway gets.

I'm an engineer on the OrcaRouter team. OrcaRouter is a drop-in OpenAI-compatible API gateway — https://api.orcarouter.ai/v1 with an sk-orca- key — that exposes 160+ models through one endpoint. It also runs gateway-level, zero-trust security for AI agents on the same endpoint — screening every prompt/response and governing every tool call on a default-deny basis, with no application code changes.

What users will see

  • Settings → Media gains an OrcaRouter provider section (next to OpenRouter) with a base URL of https://api.orcarouter.ai/v1, a link to the key page, and a custom-model field.
  • The new-project model picker lists OrcaRouter image models — openai/gpt-image-2, google/gemini-2.5-flash-image, and grok/grok-imagine-image (labeled "(OrcaRouter)") — with the OrcaRouter brand mark.
  • Configuring a key via the new ORCAROUTER_API_KEY env var (or OD_ORCAROUTER_API_KEY, following the daemon's per-provider naming) lights up image generation through the gateway; the provider note on generated images reports orcarouter/<wire-model>.

The provider renders through the daemon's existing OpenAI-standard Images API path (POST /v1/images/generations), so it inherits the same size mapping, error surfacing, and output handling as the OpenAI/ImageRouter providers.

Surface area

  • UI — new provider section in Settings → Media and new catalog entries in the model picker (apps/web/src/media/models.ts, apps/web/public/model-icons/orcarouter.svg)
  • Keyboard shortcut — none
  • CLI / env var — new OD_ORCAROUTER_API_KEY / ORCAROUTER_API_KEY env vars (apps/daemon/src/media/config.ts)
  • API / contract — none
  • Extension point — none
  • i18n keys — none
  • New top-level dependency — none
  • Default behavior change — none (opt-in provider; existing defaults untouched)
  • None

Screenshots

No UI screenshot attached — the change adds a provider entry in the existing Settings → Media list and model-picker rows; both render through the existing provider/model list components with no new layout.

Bug fix verification

Not a bug fix — feature addition. The render path is anchored by the existing OpenAI-standard contract (verified live against the gateway: POST /v1/images/generations returns data[0].b64_json, and the dispatcher wrote a valid PNG through the repo's own generateMedia path).

Validation

  • node scripts/verify-media-models.mjs → OK (web/daemon registries in sync)
  • pnpm --filter @open-design/daemon typecheck → pass
  • pnpm --filter @open-design/web typecheck → pass
  • pnpm guard → pass
  • daemon: media-adapters (30), media-generate-multi-image, media-generate-prompt-file, memory-media-provider-fallback (7) → pass
  • web: modelProviderIcon (5), SettingsDialog.media, HomeView.media-options → pass
  • L3 live: generateMedia({ surface: 'image', model: 'orcarouter/openai/gpt-image-2' }) with a real key → 907 KB PNG written, providerNote: orcarouter/openai/gpt-image-2 · 1024x1024

@github-actions

Copy link
Copy Markdown
Contributor

Visual regression review

Head: 08cc33b · Base: bf71452

3 changed · 43 unchanged · 0 new without baseline · 0 failed

Changed cases

Case Main PR Diff
visual-home-plugin-use-staged
1,670 px (0.13%)
main pr diff
visual-home-staged-attachment
4,151 px (0.32%)
main pr diff
visual-topbar-execution-switcher
1,302 px (0.10%)
main pr diff
Unchanged cases
Case Main PR Diff
visual-avatar-local-agent-list
57 px (0.00%)
main pr diff
visual-avatar-local-agent-list-panel
0 px (0.00%)
main pr diff
visual-avatar-menu
0 px (0.00%)
main pr diff
visual-avatar-menu-panel
0 px (0.00%)
main pr diff
visual-avatar-open-design-model-picker
162 px (0.01%)
main pr diff
visual-critical-settings
0 px (0.00%)
main pr diff
visual-critical-workspace
254 px (0.02%)
main pr diff
visual-critical-workspace-preview
54 px (0.00%)
main pr diff
visual-design-system-detail
0 px (0.00%)
main pr diff
visual-design-systems
0 px (0.00%)
main pr diff
visual-home
69 px (0.01%)
main pr diff
visual-home-catalog
0 px (0.00%)
main pr diff
visual-home-context-picker
135 px (0.01%)
main pr diff
visual-home-context-picker-popover
0 px (0.00%)
main pr diff
visual-home-plugin-filter
0 px (0.00%)
main pr diff
visual-home-plugin-use-with-query
0 px (0.00%)
main pr diff
visual-integrations-use-everywhere
0 px (0.00%)
main pr diff
visual-new-project-modal
0 px (0.00%)
main pr diff
visual-plugin-details
0 px (0.00%)
main pr diff
visual-plugin-share-menu
0 px (0.00%)
main pr diff

Visual diff is advisory only and does not block merging.

@lefarcen lefarcen added size/S PR changes 20-100 lines risk/high High risk: apps/desktop, daemon, auth, migration, workflows, package deps type/feature New feature labels Aug 11, 2026
@lefarcen
lefarcen requested a review from mrcfps August 11, 2026 06:33
@lefarcen lefarcen added the needs-validation Runtime change detected; needs human or /explore agent validation. label Aug 11, 2026
@lefarcen

Copy link
Copy Markdown
Contributor

🧪 This PR has changes that need a manual QA pass before merge — please hold off self-merging for now; we'll loop QA in once it's merge-ready (and design/product have signed off, where applicable).

@lefarcen lefarcen added the needs-design-review Awaiting design review (external UI change); cleared by the Odcrew App applying design-approved label Aug 11, 2026

@mrcfps mrcfps 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.

Thanks @Marc-oss-hub — nice, tightly scoped OrcaRouter media provider addition. The daemon path (env keys, catalog entries, OpenAI-compatible /v1/images/generations renderer with prefix stripping) looks consistent with the existing ImageRouter/OpenAI patterns, and the Settings media section + icon wiring are in good shape.

I found one non-blocking gap that blocks the New Project model picker from actually listing these models, even though the catalog entries land correctly. Details in the inline comment.

🔁 Powered by Looper · runner=reviewer · agent=grok-build · An autonomous AI dev team for your GitHub repos.

Comment on lines +524 to +526
{ id: 'orcarouter/openai/gpt-image-2', label: 'openai/gpt-image-2 (OrcaRouter)', hint: 'OrcaRouter · routed GPT Image', provider: 'orcarouter', caps: ['t2i'] },
{ id: 'orcarouter/google/gemini-2.5-flash-image', label: 'gemini-2.5-flash-image (OrcaRouter)', hint: 'OrcaRouter · Gemini', provider: 'orcarouter', caps: ['t2i'] },
{ id: 'orcarouter/grok/grok-imagine-image', label: 'grok-imagine-image (OrcaRouter)', hint: 'OrcaRouter · xAI', provider: 'orcarouter', caps: ['t2i'] },

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.

Non-blocking: catalog is registered, but New Project picker will still hide these models

These three entries correctly add provider: 'orcarouter' to IMAGE_MODELS, and Settings will surface the provider because settingsVisible: true + integrated: true is enough for SettingsDialog.

However, the New Project image picker does not use the catalog alone. It goes through supportedModels() in apps/web/src/components/NewProjectPanel.tsx, which hard-filters providers:

image: new Set(['openai', 'codex', 'volcengine', 'grok', 'nanobanana', 'openrouter', 'imagerouter', 'leonardo', 'custom-image', 'aihubmix', 'minimax']),

orcarouter is absent, so supportedModels('image', IMAGE_MODELS) drops every OrcaRouter model. That contradicts the PR description (“the new-project model picker lists OrcaRouter image models…”) and is the same gate OpenRouter had to pass (see apps/web/tests/components/NewProjectPanel.test.ts for the existing openrouter regression coverage).

Why it matters: users who configure an OrcaRouter key in Settings still cannot pick the new models from New Project. Daemon/CLI generation may work if the id is known, but the primary UI discovery path claimed in this PR does not.

Suggested fix:

  1. Add 'orcarouter' to the image set in supportedModels().
  2. Extend apps/web/tests/components/NewProjectPanel.test.ts with a sibling assertion:
    expect(models.some((model) => model.provider === 'orcarouter')).toBe(true).

Optional related polish (not blocking): in HomeHero’s brand helper, slash-containing model ids currently fall through to the ImageRouter (IR) badge after the OpenRouter check. Adding an explicit orcarouter branch before the imagerouter || '/' fallback would keep the home badge consistent with the new icon.

🔁 Powered by Looper · runner=reviewer · agent=grok-build · An autonomous AI dev team for your GitHub repos.

@lefarcen lefarcen added the needs-product-review Feature PR awaiting product sign-off before merge (see roadmap) label Aug 11, 2026
@lefarcen

Copy link
Copy Markdown
Contributor

Thanks @Marc-oss-hub — this is a nice, focused provider addition.

We’ve already routed the product/design/QA follow-ups, and the current actionable code feedback is covered in @mrcfps’s comment above, so the next useful step is addressing that picker gap and pushing an update when ready.

💡 To drive this PR to merge hands-free, paste this to your AI coding agent (Claude Code / Codex / opencode / Cursor …):
Take over nexu-io/open-design#6723 until it merges — read https://raw.githubusercontent.com/nexu-io/looper/main/skills/pr-takeover/SKILL.md and follow it.

@xxiaoxiong xxiaoxiong 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.

LGTM. Adds OrcaRouter as a first-class OpenAI-compatible image provider — mirrors the existing imagerouter/openrouter pattern: ENV keys, default base URL,.MEDIA_PROVIDERS row, three routed models (openai/gpt-image-2, google/gemini-2.5-flash-image, grok/grok-imagine-image), an OrcaRouter SVG monogram, modelProviderIcon substring match, and a vitest covering the icon lookup. The render path strips the orcarouter/ catalogue prefix before the wire call and reuses openaiSizeFor / parseOpenAICompatibleJson / bytesFromOpenAICompatibleData — no new HTTP contract.

@xxiaoxiong xxiaoxiong 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.

LGTM — proper OpenAI-compatible image provider addition.

Verified the wiring: orcarouter listed in ENV_KEYS (with both OD_ORCAROUTER_API_KEY and ORCAROUTER_API_KEY fallback, matching the convention of other providers), default base URL https://api.orcarouter.ai/v1, MEDIA_PROVIDERS entry with credentialsRequired, settingsVisible, supportsCustomModel, and a useful customModelPlaceholder. Dispatch hook in generateMedia is placed next to imagerouter. renderOrcaRouterImage properly strips the orcarouter/ catalogue prefix so the wire model name matches OrcaRouter's canonical vendor slug, and openaiSizeFor is called with the bare model name for sizing. Fetch / parse / bytesFrom* helpers are all reused from existing code, no duplication.

@lefarcen

Copy link
Copy Markdown
Contributor

Thanks @Marc-oss-hub — design is waiting on the current-head visuals @xiaoche-hub requested above. Once you add those screenshots or recording for both surfaces (Settings → Media and the New Project model picker), that should unblock the design pass and keep the rest of the review moving.

@lefarcen

Copy link
Copy Markdown
Contributor

Thanks @Marc-oss-hub — one important update from design: please refresh this PR against current main, adapt the Settings → Media and New Project picker work to the current UI, and attach fresh current-head screenshots or a short recording showing both surfaces with an OrcaRouter model selected.

Once that updated UI + visuals are in place (alongside the earlier picker feedback from @mrcfps), @xiaoche-hub can take another pass.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-design-review Awaiting design review (external UI change); cleared by the Odcrew App applying design-approved needs-product-review Feature PR awaiting product sign-off before merge (see roadmap) needs-validation Runtime change detected; needs human or /explore agent validation. risk/high High risk: apps/desktop, daemon, auth, migration, workflows, package deps size/S PR changes 20-100 lines type/feature New feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants