Playground Studio (中文 (繁體))
Playground Studio 將 /dashboard/playground 從簡易的 Monaco 編輯器轉變為
功能完整的測試工作區。它以 PlaygroundStudio 外殼取代舊版 page.tsx,
呈現四個分頁與共用設定窗格。
┌ Playground ──────────────────────────────────────────────────────────┐│ [💬 聊天] [⚖ 比較] [{} API] [🔧 建置] 142↑ 38↓ · $0.002 </>│├──────────────────────────────────────────┬───────────────────────────┤│ {使用中分頁內容} │ ─ 設定 ││ │ 端點 [chat ∨] ││ │ 模型 [gpt-5.4 ∨] ││ │ 系統 [文字區域] ││ │ 溫度 ▕▕▔▔ 0.7 ││ │ 預設集 [▾ 載入][儲存] ││ │ [✨ 改善提示詞] │└──────────────────────────────────────────┴───────────────────────────┘將 ChatPlayground.tsx 發展為支援多輪串流的工作台:
- 透過
MarkdownMessage.tsx完整呈現 Markdown(程式碼區塊、表格、清單、連結)。 - 系統提示詞取自共用的設定窗格。
- 顯示每則訊息的 Token/成本(提示詞 + 完成 Token)。
- 重新產生上一個回應。
- 傳送至
POST /v1/chat/completions,並使用 SSE 串流。
代理服務的關鍵差異化功能:針對最多 4 個模型並行執行 1 個提示詞。
- 最多 4 欄,每欄皆獨立從
/v1/chat/completions接收串流。 - 使用
+ 新增模型按鈕(Cmd+K 快捷鍵)新增欄位。 全部執行 ▶透過Promise.all與各欄專屬的AbortController同時觸發所有串流。- 全域的全部取消會中止每個進行中的串流。
- 各欄的
ProviderMetrics會即時顯示 TTFT、TPS、Token 數量與預估成本。 - 指標會標示為**「用戶端估算」**(D12)— 從第一個 SSE 區塊開始測量。
API 分頁
Section titled “API 分頁”為進階使用者完整保留原始 Monaco 編輯器的所有功能(D14):
- 10 個端點:聊天完成、文字完成、嵌入、影像、音訊、語音、轉錄、內容審核、重新排序、搜尋。
- 多模態檔案上傳。
- SSE 串流與即時輸出。
- 封裝為
ApiTab.tsx(延遲載入,ssr: false)。
工具/函式呼叫與結構化輸出的使用者介面:
ToolsBuilder.tsx— 新增/編輯/移除tools[],且每個工具皆有 JSON Schema 編輯器。 透過ToolDefinitionSchema(Zod)驗證參數。StructuredOutputEditor.tsx— 切換 JSON 模式 + JSON Schema 編輯器。 透過StructuredOutputSchema(Zod)依據結構描述驗證回應。- 將包含
tools[]和/或response_format的請求傳送至/v1/chat/completions。
設定窗格(共用)
Section titled “設定窗格(共用)”StudioConfigPane.tsx — 永遠可見,可收合。
| 欄位 | 元件 | 備註 |
|---|---|---|
| 端點 | <select> |
與 PlaygroundEndpoint 相符的 10 個選項 |
| 模型 | <input> |
自由文字,例如 openai/gpt-4o |
| 系統提示 | <textarea> |
提供給所有分頁使用 |
| 參數 | ParamSliders |
temperature、max_tokens、top_p、presence/frequency penalty、seed、stop |
| 預設集 | PresetPicker |
載入/儲存具名設定快照(持久化於 DB) |
| 改善提示 | ImprovePromptButton |
開啟配額警告對話框,呼叫 /api/playground/improve-prompt |
狀態會提升至 PlaygroundStudio.tsx,並向下傳遞至所有分頁。切換分頁時會
保留設定狀態。
StudioTopBar.tsx:
- 分頁切換器(role=“tablist”)。
TokenCostCounter— 即時權杖(↑/↓)與預估成本顯示。- 匯出程式碼按鈕(
</>)— 開啟ExportCodeModal。
匯出程式碼對話框
Section titled “匯出程式碼對話框”ExportCodeModal.tsx 使用 codeExport.ts,根據目前的 PlaygroundState 產生 curl / Python / TypeScript 程式碼片段。
API 金鑰預留位置一律為 $OMNIROUTE_API_KEY(D11)。
提示改善工具
Section titled “提示改善工具”ImprovePromptButton.tsx → useImprovePrompt.ts → POST /api/playground/improve-prompt:
- 對話框警告「將會消耗配額」。
- 確認後,將
{ system, prompt, model, tone }傳送至該路由。 - 路由在內部使用
promptImprover.META_SYSTEM_PROMPT呼叫/v1/chat/completions。 - 傳回
{ improvedSystem?, improvedPrompt?, tokensIn, tokensOut }。 - UI 會更新設定窗格的系統提示,以及聊天分頁的使用者提示。
PresetPicker.tsx → usePresets.ts → /api/playground/presets/*:
- 儲存於
playground_presetsSQLite 資料表(遷移檔案084_playground_presets.sql)。 - 每個預設集儲存:
name、endpoint、model、system、params_json、created_at。 - CRUD:
GET列出、POST建立、GET /:id、PUT /:id、DELETE /:id。
useStreamMetrics.ts + streamMetrics.ts(純函式):
start()— 記錄請求開始時間。onFirstChunk()— 記錄 TTFT。onChunk(n)— 累計完成權杖數。finish(usage?)— 計算最終指標:ttftMs、totalMs、tps、tokensIn、tokensOut、costUsd。- 定價來自
src/lib/playground/types.ts中的靜態表格(標示為「預估」— D13)。
| 方法 | 路徑 | 處理程序 |
|---|---|---|
POST |
/api/playground/improve-prompt |
使用 Zod 驗證 ImprovePromptRequestSchema;使用中繼提示呼叫 /v1/chat/completions |
GET |
/api/playground/presets |
傳回 { presets: PlaygroundPresetListItem[] } |
POST |
/api/playground/presets |
建立預設集;驗證 PlaygroundPresetCreateSchema |
GET |
/api/playground/presets/:id |
傳回單一預設集,若不存在則傳回 404 |
PUT |
/api/playground/presets/:id |
部分更新 |
DELETE |
/api/playground/presets/:id |
204 |
驗證:選用(REQUIRE_API_KEY)。錯誤透過 buildErrorBody() 處理(強制規則 #12)。
| 路徑 | 用途 |
|---|---|
src/app/(dashboard)/dashboard/playground/PlaygroundStudio.tsx |
外殼元件、分頁協調器 |
src/app/(dashboard)/dashboard/playground/components/StudioTopBar.tsx |
分頁 + 計數器 + 匯出按鈕 |
src/app/(dashboard)/dashboard/playground/components/StudioConfigPane.tsx |
共用設定面板 |
src/app/(dashboard)/dashboard/playground/components/tabs/ChatTab.tsx |
聊天工作台 |
src/app/(dashboard)/dashboard/playground/components/tabs/CompareTab.tsx |
多模型比較 |
src/app/(dashboard)/dashboard/playground/components/tabs/ApiTab.tsx |
Monaco 編輯器(保留) |
src/app/(dashboard)/dashboard/playground/components/tabs/BuildTab.tsx |
工具 + 結構化輸出 |
src/app/(dashboard)/dashboard/playground/components/ExportCodeModal.tsx |
程式碼匯出對話框 |
src/app/(dashboard)/dashboard/playground/components/CompareColumn.tsx |
單一比較欄 |
src/app/(dashboard)/dashboard/playground/components/ProviderMetrics.tsx |
TTFT/TPS 顯示 |
src/app/(dashboard)/dashboard/playground/hooks/useStreamMetrics.ts |
用戶端指標 Hook |
src/app/(dashboard)/dashboard/playground/hooks/usePresets.ts |
預設集 CRUD Hook |
src/app/(dashboard)/dashboard/playground/hooks/useImprovePrompt.ts |
改善提示詞 Hook |
src/lib/playground/codeExport.ts |
curl/Python/TS 產生器(與搜尋工具共用) |
src/lib/playground/promptImprover.ts |
元提示詞建構器 |
src/lib/playground/streamMetrics.ts |
純指標運算 |
src/lib/db/playgroundPresets.ts |
資料庫模組(CRUD) |
src/app/api/playground/improve-prompt/route.ts |
改善提示詞 REST 路由 |
src/app/api/playground/presets/route.ts |
預設集清單 + 建立 |
src/app/api/playground/presets/[id]/route.ts |
取得/更新/刪除預設集 |
src/lib/db/migrations/084_playground_presets.sql |
資料庫遷移 |
| 症狀 | 原因 | 修正方式 |
|---|---|---|
| Monaco 編輯器未顯示於 API 分頁中 | SSR 載入了 Monaco | 確認 ApiTab 使用 dynamic(..., { ssr: false }) |
| 比較串流依序啟動 | Promise.all 使用方式錯誤 |
所有串流啟動作業都必須在單一 Promise.all 呼叫中分派 |
指標顯示 null TTFT |
未連接第一個區塊處理常式 | 檢查 SSE 讀取器迴圈中是否呼叫了 useStreamMetrics.onFirstChunk() |
| 預設集未持續保存 | 未執行資料庫遷移 | 執行 npm run db:migrate 或重新啟動伺服器(遷移會在啟動時自動執行) |
| 改善提示詞時傳回 502 | Config 中未設定模型 | 使用者必須先在 Config 窗格中輸入模型名稱,才能進行改善 |
匯出的程式碼顯示 MISSING_API_KEY |
未插入預留位置 | codeExport.ts 一律使用 API_KEY_PLACEHOLDER = "$OMNIROUTE_API_KEY" |
- 總體計畫:
_tasks/features-v3.8.6/refactorpages/_orchestration/master-plan-group-C.md - 功能計畫:
_tasks/features-v3.8.6/refactorpages/17-playground-studio-redesign.plan.md - 程式碼匯出:
src/lib/playground/codeExport.ts - 提示詞改善器:
src/lib/playground/promptImprover.ts - Search Tools Studio:
docs/frameworks/SEARCH_TOOLS_STUDIO.md
HagiCode
HagiCode 是智慧代理程式開發工作台,結合結構化工作流程、多代理程式執行與 Hero Dungeon 介面,將想法化為交付成果。
以更聰明、更快速且更有趣的智慧代理程式工作流程,打造實用的軟體。

- Smart結構化流程將意圖轉化為從構想到交付的可執行步驟。
- Efficient多代理程式工作流程讓研究、實作與審查並行進行。
- FunHero Dungeon 讓長時間的程式協作更直覺、更有參與感。