Skip to content

feat(webui): Wave 4B — vision, compare, and omnifail provider tiers - #16

Merged
bodencrouch merged 8 commits into
mainfrom
feat/chat-ui-wave4b
Jul 25, 2026
Merged

feat(webui): Wave 4B — vision, compare, and omnifail provider tiers#16
bodencrouch merged 8 commits into
mainfrom
feat/chat-ui-wave4b

Conversation

@bodencrouch

Copy link
Copy Markdown
Contributor

Summary

  • Ship Wave 4B differentiation: image attachments with vision guard, two-column compare mode, and a user-ordered omnifail tier stack (quality_api → optional web runner → SearXNG discovery → proxy_failover) with disjoint route ownership so zero-config proxy chat stays unchanged.
  • Add an opt-in local companion in runner/ (OpenAI-shaped SSE; stub + BYO-selector adapters) and a dismissible SearXNG pick list that never automates third-party chats.
  • Cover vision, compare, and tier settings with Playwright specs registered in the Pages workflow; document caveats, plugins, CONCEPTS Wave 4B terms, and strategy/learnings alignment.

Test plan

  • cd webui && npm test && npm run build (68+ vitest green)
  • cd runner && npm test (health + SSE + 501 + CORS)
  • Playwright: npx playwright test tests/e2e/vision-attach.spec.ts tests/e2e/compare-mode.spec.ts tests/e2e/tier-settings.spec.ts
  • Manual: attach PNG on a vision-badged model → reply streams; non-vision model → clear block
  • Manual: enable Compare → two columns, banner when both metered; exit keeps history
  • Manual: Tiers panel reorder + save → reload preserves order; zero-config text chat still works with web/SearXNG off
  • Confirm Pages CI runs the three new Wave 4B specs after merge

Copilot added 8 commits July 25, 2026 04:20
…g (U1)

Establish the provider-tier orchestrator foundation for Wave 4B:

- Split quality_api (direct/BYOK routes only) from proxy_failover (cloud
  proxy chain) so a single request is never attempted twice against the
  same endpoint. quality_api skips without a usable key, letting the
  orchestrator advance to the proxy tier — keyless zero-config visitors
  are still served by the proxy, matching pre-4B behavior.
- Enable quality_api + proxy_failover by default for zero-config routing.
- Preserve the user's saved tier order in normalizeTierSettings (R36),
  deduping and dropping unknown ids, appending omitted tiers at their
  default-enabled state instead of rebuilding from a fixed order.
- Surface which tiers were tried and their last error on failure while
  preserving the ChatRouteError taxonomy (R40).
- Add an in-memory localStorage/window test seam (vitest.setup.ts) so
  tier tests run under the node environment without full jsdom.
- Add orchestrator ordering tests, normalize/default unit tests, and a
  FailoverProvider integration test for zero-config proxy routing and
  failure diagnostics.

npm test: 41 passing (7 new).
- Register murm-ui AttachmentPlugin (image/* only, 4MB client cap) with
  clear oversize/unsupported errors that leave the session intact (R28, R31).
- Add message-openai mapper: text-only turns stay strings; image file blocks
  become OpenAI image_url content parts so attachments are never dropped.
- Vision guard (R29): block send with a clear, explorer-pointing message when
  an image is attached but the selected model is not vision-capable.
- quality_api (direct/BYOK) skips image turns so multimodal requests route to
  the proxy tier instead of silently dropping the image; proxy body carries
  the multimodal content parts.
- Expose modelSupportsVision / getVisionCatalogModels helpers (R30) and tighten
  the attachment tray thumbnails for the dark shell.

npm test: 50 passing (9 new).
Ship the Tiers shell panel so users can reorder and enable omnifail routes
(R36), with opt-in web-runner and SearXNG URL fields (R41) and clear ToS /
best-effort copy (R42). Persist order through normalizeTierSettings so the
orchestrator attempt sequence matches what the panel saved.

Document the distinction between the omnifail route stack and cloud free-tier
limits, bootstrap merge stale-localStorage behavior, and text-only vision
export in CAVEATS; register the plugin in chat-ui-plugins.md.

npm test: 54 passing (4 new).
Ship compare mode as a murm-ui plugin with dual FailoverProvider delegates
(KTD4): same prompt streams to two independently chosen models in a
split-pane grid. Sequential onEvent delivery creates two labeled assistant
messages in one generation; exit keeps session history (R32–R35).

Show a pre-send banner when both columns hit the metered public proxy (R34).
Cover metered helpers in vitest and add a Playwright happy-path spec.

npm test: 59 passing. Playwright compare-mode.spec.ts green.
Query a user-configured SearXNG instance for candidate free web chat URLs
when the tier is enabled (R39). Heuristic filter keeps https chat-looking
results, one per host; matches render as a dismissible pick list of manual
links between history and composer — nothing is automated on the user's
behalf.

Discovery records a descriptive attempt and the chain continues to the next
tier, so zero-config proxy chat is unchanged (R43). Empty results, HTTP
errors, and CORS/network failures surface as typed diagnostics (R40).

npm test: 65 passing. npm run build green.
Ship the web_ui tier (R38) as a user-run companion in runner/: a
zero-dependency Node service exposing OpenAI-shaped SSE at
/v1/chat/completions with a stub adapter for smoke testing and a generic
selector-driven Playwright adapter (BYO selectors — no site automation is
shipped). Chat returns 501 with setup guidance until an adapter is
configured; CORS allows localhost and *.github.io.

Browser side, streamFromWebRunner bridges the runner into FailoverProvider
with typed not-configured/unreachable diagnostics (R40) and an image skip so
attachments stay on the proxy tier. Routing metadata records web_ui only
once the runner actually streams.

Runner runs TypeScript natively (Node >= 23.6 type stripping) — no build
step, no tsx/esbuild postinstall.

webui npm test: 68 passing; runner npm test: 4 passing; build green.
Add vision-attach.spec.ts (PNG + vision model streams via proxy with an
image_url part; non-vision model blocks clearly, AE1/R29) and
tier-settings.spec.ts (reorder persists through localStorage and reload,
R36; zero-config chat unchanged, AE3). Register the three Wave 4B specs —
including compare-mode from U3 — in the Pages workflow.

installLocalIndexHtml serves the locally built docs/index.html when a spec
needs static markup (Tiers button) that has not deployed yet. Trim CONCEPTS
to Wave 4B glossary terms only — Wave 5/6 rows land with their waves.
…tatus

Mark the Wave 4B differentiation plan completed with landed-unit delta and
commit trail; queue Wave 5 behind it and close out Wave 3. Refresh STRATEGY
tracks (demo stays display/routing-first; user-run companions are opt-in
extensions), record the murm-ui streaming plaintext-tail patch as a
tooling-decision learning, and add the matching AGENTS pitfall.
@bodencrouch
bodencrouch merged commit f3c8dcb into main Jul 25, 2026
3 checks passed
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