-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Playground Studio
Feature: Playground Studio — unified AI testing workspace for
/dashboard/playground. Plans:17-playground-studio-redesign.plan.md+_orchestration/master-plan-group-C.mdStatus: Released in v3.8.6
Playground Studio transforms /dashboard/playground from a simple Monaco-based editor into
a full-featured testing workspace. It replaces the legacy page.tsx with a PlaygroundStudio
shell that renders four tabs and a shared config pane.
┌ Playground ──────────────────────────────────────────────────────────┐
│ [💬 Chat] [⚖ Compare] [{} API] [🔧 Build] 142↑ 38↓ · $0.002 </>│
├──────────────────────────────────────────┬───────────────────────────┤
│ {active tab content} │ ─ Config │
│ │ Endpoint [chat ∨] │
│ │ Model [gpt-5.4 ∨] │
│ │ System [textarea] │
│ │ Temp ▕▕▔▔ 0.7 │
│ │ Presets [▾ load][save] │
│ │ [✨ Improve prompt] │
└──────────────────────────────────────────┴───────────────────────────┘
Evolves ChatPlayground.tsx into a multi-turn streaming workbench:
- Full markdown rendering via
MarkdownMessage.tsx(code blocks, tables, lists, links). - System prompt sourced from the shared Config pane.
- Token/cost per message (prompt + completion tokens).
- Regenerate last response.
- Sends to
POST /v1/chat/completionswith SSE streaming.
The key differentiator for a proxy: run 1 prompt across up to 4 models in parallel.
- Up to 4 columns, each independently streaming from
/v1/chat/completions. -
+ Add modelbutton (Cmd+K shortcut) to add columns. -
Run all ▶triggers all streams simultaneously viaPromise.all+ per-columnAbortController. - Global Cancel all aborts every in-flight stream.
- Per-column
ProviderMetricsshows TTFT, TPS, tokens, and estimated cost in real time. - Metrics labelled "client-side estimate" (D12) — measured from first SSE chunk.
Preserves 100% of the original Monaco editor for power users (D14):
- 10 endpoints: chat completions, completions, embeddings, images, audio, speech, transcriptions, moderations, rerank, search.
- Multimodal file upload.
- SSE streaming with real-time output.
- Wrapped as
ApiTab.tsx(lazy-loaded,ssr: false).
Tools/function calling and structured output UI:
-
ToolsBuilder.tsx— add/edit/removetools[]with JSON schema editor per tool. Validates parameters viaToolDefinitionSchema(Zod). -
StructuredOutputEditor.tsx— toggle JSON mode + JSON schema editor. Validates response against schema viaStructuredOutputSchema(Zod). - Sends request to
/v1/chat/completionswithtools[]and/orresponse_format.
StudioConfigPane.tsx — always visible, collapsible.
| Field | Component | Notes |
|---|---|---|
| Endpoint | <select> |
10 options matching PlaygroundEndpoint
|
| Model | <input> |
free text, e.g. openai/gpt-4o
|
| System prompt | <textarea> |
fed into all tabs |
| Parameters | ParamSliders |
temperature, max_tokens, top_p, presence/frequency penalty, seed, stop |
| Presets | PresetPicker |
load/save named config snapshots (persisted in DB) |
| Improve prompt | ImprovePromptButton |
opens quota-warning modal, calls /api/playground/improve-prompt
|
State is lifted to PlaygroundStudio.tsx and passed down to all tabs. Switching tabs
preserves config state.
StudioTopBar.tsx:
- Tab switcher (role="tablist").
-
TokenCostCounter— live token (↑/↓) and estimated cost display. - Export code button (
</>) — opensExportCodeModal.
ExportCodeModal.tsx uses codeExport.ts to generate curl / Python / TypeScript snippets
from the current PlaygroundState. API key placeholder is always $OMNIROUTE_API_KEY (D11).
ImprovePromptButton.tsx → useImprovePrompt.ts → POST /api/playground/improve-prompt:
- Modal warns "will consume quota".
- On confirm, sends
{ system, prompt, model, tone }to the route. - Route calls
/v1/chat/completionsinternally withpromptImprover.META_SYSTEM_PROMPT. - Returns
{ improvedSystem?, improvedPrompt?, tokensIn, tokensOut }. - UI patches the Config pane system prompt and the Chat tab user prompt.
PresetPicker.tsx → usePresets.ts → /api/playground/presets/*:
- Stored in
playground_presetsSQLite table (migration076_playground_presets.sql). - Each preset stores:
name,endpoint,model,system,params_json,created_at. - CRUD:
GETlist,POSTcreate,GET /:id,PUT /:id,DELETE /:id.
useStreamMetrics.ts + streamMetrics.ts (pure function):
-
start()— records request start time. -
onFirstChunk()— records TTFT. -
onChunk(n)— accumulates completion token count. -
finish(usage?)— computes final metrics:ttftMs,totalMs,tps,tokensIn,tokensOut,costUsd. - Pricing from static table in
src/lib/playground/types.ts(labelled "estimated" — D13).
| Method | Path | Handler |
|---|---|---|
POST |
/api/playground/improve-prompt |
Zod-validates ImprovePromptRequestSchema; calls /v1/chat/completions with meta-prompt |
GET |
/api/playground/presets |
Returns { presets: PlaygroundPresetListItem[] }
|
POST |
/api/playground/presets |
Creates preset; validates PlaygroundPresetCreateSchema
|
GET |
/api/playground/presets/:id |
Returns one preset or 404 |
PUT |
/api/playground/presets/:id |
Partial update |
DELETE |
/api/playground/presets/:id |
204 |
Auth: optional (REQUIRE_API_KEY). Errors via buildErrorBody() (Hard Rule #12).
| Path | Purpose |
|---|---|
src/app/(dashboard)/dashboard/playground/PlaygroundStudio.tsx |
Shell component, tab orchestrator |
src/app/(dashboard)/dashboard/playground/components/StudioTopBar.tsx |
Tabs + counter + export button |
src/app/(dashboard)/dashboard/playground/components/StudioConfigPane.tsx |
Shared config panel |
src/app/(dashboard)/dashboard/playground/components/tabs/ChatTab.tsx |
Chat workbench |
src/app/(dashboard)/dashboard/playground/components/tabs/CompareTab.tsx |
Multi-model compare |
src/app/(dashboard)/dashboard/playground/components/tabs/ApiTab.tsx |
Monaco editor (preserved) |
src/app/(dashboard)/dashboard/playground/components/tabs/BuildTab.tsx |
Tools + structured output |
src/app/(dashboard)/dashboard/playground/components/ExportCodeModal.tsx |
Code export modal |
src/app/(dashboard)/dashboard/playground/components/CompareColumn.tsx |
Single compare column |
src/app/(dashboard)/dashboard/playground/components/ProviderMetrics.tsx |
TTFT/TPS display |
src/app/(dashboard)/dashboard/playground/hooks/useStreamMetrics.ts |
Client-side metric hook |
src/app/(dashboard)/dashboard/playground/hooks/usePresets.ts |
Presets CRUD hook |
src/app/(dashboard)/dashboard/playground/hooks/useImprovePrompt.ts |
Improve-prompt hook |
src/lib/playground/codeExport.ts |
curl/Python/TS generator (shared with Search Tools) |
src/lib/playground/promptImprover.ts |
Meta-prompt builder |
src/lib/playground/streamMetrics.ts |
Pure metrics computation |
src/lib/db/playgroundPresets.ts |
DB module (CRUD) |
src/app/api/playground/improve-prompt/route.ts |
Improve-prompt REST route |
src/app/api/playground/presets/route.ts |
Presets list + create |
src/app/api/playground/presets/[id]/route.ts |
Presets get/update/delete |
src/lib/db/migrations/076_playground_presets.sql |
DB migration |
| Symptom | Cause | Fix |
|---|---|---|
| Monaco editor not rendering in API tab | SSR loaded Monaco | Verify ApiTab uses dynamic(..., { ssr: false })
|
| Compare streams fire sequentially | Wrong Promise.all usage |
All stream starts must be dispatched in one Promise.all call |
Metrics show null TTFT |
First chunk handler not wired | Check useStreamMetrics.onFirstChunk() is called in the SSE reader loop |
| Preset not persisting | DB migration not run | Run npm run db:migrate or restart the server (migration auto-runs on startup) |
| Improve prompt returns 502 | Model not set in Config | User must enter a model name in the Config pane before improving |
Export code shows MISSING_API_KEY
|
Placeholder not inserted |
codeExport.ts always uses API_KEY_PLACEHOLDER = "$OMNIROUTE_API_KEY"
|
- Master plan:
_tasks/features-v3.8.6/refactorpages/_orchestration/master-plan-group-C.md - Feature plan:
_tasks/features-v3.8.6/refactorpages/17-playground-studio-redesign.plan.md - Code export:
src/lib/playground/codeExport.ts - Prompt improver:
src/lib/playground/promptImprover.ts - Search Tools Studio:
docs/frameworks/SEARCH_TOOLS_STUDIO.md
OmniRoute · Website · npm · Docker Hub
- Setup Guide
- User Guide
- Features
- Quick Start (Docker)
- Electron Desktop App
- Termux (Android)
- PWA Guide
- MCP Server
- A2A Server
- Agent Protocols
- OpenCode Plugin
- Webhooks
- Cloud Agents
- Skills
- Memory
- Evals
- Gamification
- Guardrails
- Compliance
- Error Sanitization
- Public Credentials
- Route Guard Tiers
- Stealth Guide
- CLI Token Auth