Skip to content

feat(app): consolidate web UI fixes, session toolbar, and OmniRoute provider - #53772

Open
afonsoft wants to merge 2 commits into
anomalyco:devfrom
afonsoft:web-ui-fixes
Open

afonsoft wants to merge 2 commits into
anomalyco:devfrom
afonsoft:web-ui-fixes

Conversation

@afonsoft

@afonsoft afonsoft commented Oct 7, 2026 •

Copy link
Copy Markdown

Issue for this PR

This PR consolidates a set of web UI fixes for packages/app/packages/session-ui/packages/ui/packages/web and adds two related features: a Devin-style action toolbar on the session header and an OmniRoute/9router provider entry with automatic model discovery for config-defined OpenAI-compatible providers.

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

This PR does three things on the web app (packages/app, packages/session-ui, packages/ui, packages/web):

  1. Consolidates a batch of small, targeted web UI fixes (session header, home sessions view, timeline rendering, composer, terminal, draft store, markdown sharing, layout) into one branch.
  2. Adds a Devin-style action toolbar to the session header (Files, Tasks, Progress, Terminal, Review buttons) with per-tool enable/disable switches under Settings -> General -> Advanced.
  3. Adds "OmniRoute / 9router" to Popular Providers: the connect dialog asks only for Base URL + API key, and the backend auto-discovers models from {baseURL}/models for config-defined OpenAI-compatible providers.

It also fixes a scalability bug found while E2E-testing that feature: the model pickers rendered every model unvirtualized, which froze the tab with a ~8k-model gateway; rendering is now capped at 200 items with a "keep typing to filter" hint.

1. Consolidated web UI fixes

Small, targeted fixes across the web app surface:

  • packages/app/src/components/dialog-connect-provider.tsx — improved provider connect dialog behavior.
  • packages/app/src/components/session/session-header.tsx — right-side header actions refactored into a generic tool list (see below); also switches path copy to the shared copyText helper.
  • packages/app/src/components/session/open-in-app.tsx, terminal.tsx, pages/home.tsx, pages/home/home-sessions*.tsx, pages/layout(-new).tsx, pages/session/composer/session-permission-dock.tsx, pages/session/timeline/message-timeline.tsx, utils/draft-store.ts — assorted UI correctness fixes.
  • packages/session-ui — markdown.tsx, message-part.tsx, tool-error-card.tsx, v2 prompt-input/attachments.ts rendering fixes.
  • packages/ui — text-field.tsx fix; new shared clipboard.tsx (copyText) and digest.tsx components.
  • packages/web/src/components/share/content-markdown.tsx — share-page markdown fix.
  • packages/opencode/src/server/shared/ui.ts, src/tool/code-mode.ts — minor supporting fixes.
  • Extracted theme/language command registration into packages/app/src/pages/layout/theme-language-commands.ts with unit tests.

2. Session header action toolbar

The session header previously exposed a single review toggle (#opencode-v2-icon-sidebar-right, tooltip-v2-trigger). It now renders a tool list — Files, Tasks, Progress (context), Terminal, Review — modeled on Devin-style workbench actions:

  • Each button invokes the existing real action: tabs().open(SESSION_OPEN_FILE_TAB) / "context" for Files/Progress, terminal toggle, reviewPanel.toggle(), todoCollapsed for Tasks (disabled when the session has no todos).
  • Buttons show pressed state while their panel is open.
  • New per-tool toggles under Settings → General → Advanced (showSessionReview, showSessionFiles, showSessionTerminal, showSessionTasks, showSessionProgress; all default on) let users hide tools they don't use. Desktop-only, preserving previous visibility behavior.
  • All new copy goes through i18n keys added for every locale.

3. OmniRoute / 9router provider + auto model discovery

  • "OmniRoute / 9router" added to Popular Providers (settings-v2/providers.tsx) with a dedicated connect dialog (dialog-omniroute-provider.tsx) that takes only a Base URL and API key, then writes provider.omniroute (npm: "@ai-sdk/openai-compatible") to config and stores the key in the auth store.
  • packages/opencode/src/provider/provider.ts: config-defined OpenAI-compatible providers with no declared models are now auto-populated by fetching {baseURL}/models once at provider-list build time. Guarded so it only applies to source: "config" providers with npm unset-or-@ai-sdk/openai-compatible and a baseURL; failures return empty and the provider is dropped as before. Timeout is 30s — real gateways (e.g. OmniRoute serving ~8k models) answer in ~9s, so a tighter bound produced silent empty results.
  • Verified end-to-end against a live OmniRoute gateway: connect → 7,990 models discovered and individually toggleable in Settings → Models.

4. Model picker scalability fix (found during E2E)

  • Connecting a large gateway (~8k models) exposed that both model pickers rendered every model as full components, freezing the tab. Both are now capped at 200 rendered items with a "keep typing to filter" footer hint; search still covers the full set.
  • packages/ui: new List limit prop backed by exported limitGroups (list-limit.ts) with unit tests; List renders a list-more row when truncated.
  • packages/app/src/components/dialog-select-model.tsx: ModelList passes limit; the v2 popover controller slices results and exposes hidden for the hint row.
  • New i18n keys dialog.model.more / ui.list.more in all locales.

How did you verify your code works?

  • bun run test:unit in packages/app — 728 tests pass, including new theme-language-commands.test.ts.
  • bun test test/provider/ test/tool/ in packages/opencode — 1086 tests pass, including a new openai-compatible-discovery.test.ts (discovers models, keeps declared models, skips non-openai-compatible npm, drops unreachable endpoints).
  • bun turbo typecheck — all 30 packages pass.
  • Live E2E: connected an OmniRoute gateway through the new dialog; backend discovered 7,990 models; OmniRoute group renders under Settings → Models.

Screenshots / recordings

OmniRoute connect dialog

OmniRoute models discovered in Settings → Models

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

…ute provider

- web interface fixes across session, home, timeline, composer, and shared ui
- session header toolbar (files, tasks, progress, terminal, review) like Devin web
- Settings > General > Advanced toggles for each new session tool
- OmniRoute (9router) in Popular Providers: endpoint + api key connect,
  auto-discovers models from OpenAI-compatible /models endpoint (30s timeout)
- theme/language command palette unit tests
- i18n keys for new copy across all locales

Co-Authored-By: Afonso Dutra Nogueira Filho <afonsoft@gmail.com>
@github-actions github-actions Bot added the needs:compliance This means the issue will auto-close after 2 hours. label Oct 7, 2026
@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

The model selector rendered every model unvirtualized; providers like
OmniRoute expose ~8k models which froze the tab on open. Cap rendered
items at 200 in both the v1 model list (List limit prop) and the v2
popover, with a 'keep typing to filter' hint for the remainder.

Adds List.limit to @opencode-ai/ui plus limitGroups unit tests, and
dialog.model.more / ui.list.more i18n keys across all locales.

Co-Authored-By: Afonso Dutra Nogueira Filho <afonsoft@gmail.com>
@github-actions github-actions Bot removed the needs:compliance This means the issue will auto-close after 2 hours. label Oct 7, 2026
@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

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.

1 participant