GenUI — 生成式 UI 輸出規範
語言: 配合使用者的請求語言(否則使用其訊息語言),包括前後文與所有使用者可見的 UI 文字:標題、標籤、內容、選項與說明。以下中文範例僅說明結構;載入此技能後,請勿將對話切換為中文。JSON 鍵、元件類型、ID 與動作保持不變。英文請求產生英文文句與 UI 文字;中文請求產生中文文句與 UI 文字。<user-language ...> 標記僅為元佔位符。請將每個標記替換為對話語言的實際內容;切勿直接輸出這些佔位符。
你可以在回答正文中間輸出可互動 UI 元件:撰寫一個 dsh-ui 圍欄(語言標記為 dsh-ui 的 fenced block),內含 JSON 規格,渲染器會將整個區塊繪製成真實元件,文字則如常穿插在前後。元件是回答的一部分,不是工具呼叫。
{"title":"<user-language text>","gap":14,"items":[...]}
圍欄書寫鐵律(請先閱讀此節)
圍欄開頭那一行的語言標記統一寫為 dsh-ui,不要加入標點、引號或註解。渲染器會容錯大小寫、前後空格與部分結尾標點;其他語言標記不會被視為 GenUI 接管,使用者會看到一般程式碼區塊。
| 寫法 | 結果 |
|---|---|
```dsh-ui | ✅ 渲染 |
```dsh-ui> | ✅ 容錯渲染;生成時仍應去掉 > |
```dsh-ui 帶行尾空格 | ✅ 渲染(自動 trim) |
``` DSH-UI | ✅ 渲染(忽略大小寫) |
```dshui / ```ds-ui | ❌ 不是合法標記 |
此前同一模型曾在同一對話中寫出 182 個 ```dsh-ui> 圍欄並導致靜默失效;現在已對這類結尾標點統一容錯。撰寫圍欄時只寫 dsh-ui 這六個字元,不要加入任何標點、引號、註解;收尾必須是單獨一行的 ```。
圍欄位置:只寫在回答正文裡。寫進 reasoning / 思考塊不會渲染,使用者看不到。
公式:$...$ / \(...\) 為行內公式,$$...$$ / \[...\] 為獨立公式;支援矩陣、分段函數、多行對齊推導,以及粗體/高亮內部的公式。正文、列表、鍵值、表頭/儲存格、卡片/步驟/時間線/標籤頁標題、題目與說明、按鈕與表單標籤、指標、媒體說明與圖表外層標題皆可共用此能力。JSON 字串中的反斜線必須雙寫,例如 "content": "\\(\\frac{a}{b}\\)"。程式碼原始碼、輸入值/佔位符、原生下拉選項與圖表引擎內部繪圖文字仍遵循各自的原生格式,不解析富文字。數學語法以 KaTeX 為準,不執行 HTML、外部資源或腳本;不支援 LaTeX 文件編譯、載入任意宏包。
元件詞彙(僅允許這些 type)
佈局:text row col grid card carousel divider spacer arrow hero
展示:stat badge progress list table keyvalue avatar image image-group audio video timeline file-tree breadcrumb diff json code callout steps icon blocks
圖表:chart(bars/line/donut,可多序列)plot(數學函數圖)echart(ECharts 全功能圖表)
互動:button input select checkbox radio switch slider textarea tabs accordion copy link submit
進階:svg mermaid diagram scene3d quiz
佈局
- text:
{"type":"text","size":"display|h1|h2|h3|body|muted|caption","content":"...","align":"left|center|right"?}(tone:"danger|success|warning|info|muted"為整行文字上語義色,不須套用 badge;mono:true使用等寬字體,用於十六進位/二進位/識別碼,不帶行內程式碼底色)(size:"display"比標題大一檔,用作引言/開篇點題句,一條回答 ≤1;center:true是舊寫法,等價於align:"center",新寫一律使用align) - row / col:
{"type":"row"|"col","items":[...],"wrap":true?,"spacer":true?,"gap":n?};row.justify:"center"主軸居中(圖示+標題那種圖頭);col.width:n(1-100)設定此列佔行寬的百分比,不寫則按內容寬度 - grid:
{"type":"grid","cols":n,"items":[...]} - carousel:
{"type":"carousel","title":"<user-language title>","items":[{"type":"card","title":"...","items":[...]}],"itemWidth":240?,"gap":3?}— 原生節點橫向捲動;最多 24 項,寬度 80–640px 且不超過軌道寬度的 85%;預設寬度 240px。gap數值乘以 4px,省略時為 12px,負數視為 0。導航按鈕每次捲動軌道寬度的 85%,僅在內容溢出時顯示,觸控裝置可直接滑動軌道。不自動播放。軌道聚焦時支援左右鍵 / Home / End,卡片內表單按原有提交規則運作。瀏覽與滑動不發 action;子元件自身宣告的 action 按既有互動規則觸發。串流輸出只在尾部追加卡片以保留已有輸入路徑。 - hero:
{"type":"hero","title":"<user-language title>","subtitle":"<user-language text>","value":"99.96%","label":"<user-language metric>","delta":"+0.02%","spark":[...],"tone":"accent|success|warning|danger"}— 封面塊:eyebrow + 超大數字(52px,附入場計數)+ 標題 + 副標題 + tone 漸變底色。一條回答最多用一個,放在最前面作為視覺錨點 - span: 任意節點都可加入
"span":2(grid 子節點佔幾列)— Bento 排版唯一的原語:一張span:2寬卡配一張窄卡,比一列方塊堆疊下去好看得多 - card:
{"type":"card","title":"...","items":[...]};"tone":"info|success|warning|danger"為卡片加上語義底色(用於結論卡/風險卡);"accent":"#f59e0b"指定強調色(邊框 + 標題 + 極淡底色);"flat":true移除陰影,改為極淡中性底—圖中的面板必須使用 flat,否則每層都像浮起的卡片,疊兩層就變得雜亂;"eyebrow":"<user-language 小引題>"在標題上方加一行 meta 小字(將多張卡分章時使用—連續同章的卡片不要每張都加,一段回答 ≤3 個) - palette:
chart/echart皆支援"palette":["#ff8800","#3ecf8e"]覆蓋分類色板(預設跟隨宿主主題)。只有在語義上需要指定顏色時才寫(成本=紅、收益=綠),否則跟隨主題更穩定 - divider:
{"type":"divider"};附章節名稱{"type":"divider","label":"<user-language 章節名>"}(線 + 小標籤居中,作為章節切換:報告從摘要切入數據、圖表冊開新章時使用一段;卡片/列表內部、連續同主題內容之間不要使用,一條回答 ≤3 個); spacer:{"type":"spacer"}
展示
- stat:
{"type":"stat","label":"...","value":"...","delta":"+12.4%|-3%"}(-開頭自動紅、+綠);可選"spark":[3,5,4,8,6]繪製一條微趨勢線(2–60 個有限數值);"size":"hero"渲染超大數字(一條回答最多用一次,作為視覺錨點) - badge:
{"type":"badge","label":"...","tone":"success|warn|danger|accent","icon":"emoji?"} - progress:
{"type":"progress","label":"...","value":0-100,"valueLabel":"70%"};"variant":"ring"繪製環形進度,"target":70在軌道上標出目標刻度 - avatar:
{"type":"avatar","name":"...","color":"#hex?"} - image:
{"type":"image","src":"/mmx-files/result.png","alt":"<user-language description>"}— 展示瀏覽器可存取的 http(s) 或同源相對圖片位址;延遲載入;不支援file:/data:等本地或主動協議;"caption":"<user-language 圖註>"在圖下方加說明行(來源/解讀/署名;alt是圖上方的標籤行,兩者分工不同) - image-group:
{"type":"image-group","title":"<user-language title>","items":[{"src":"/mmx-files/a.png","alt":"<description>","caption":"<caption>"},{"src":"/mmx-files/b.png","alt":"<description>"}]}— 最多 24 張圖片按長寬比自適應換行;點擊使用原生 lightbox 放大,左右鍵 / Home / End 切圖,Esc / 關閉按鈕返回並恢復焦點。沿用 image 的 http(s) / 相對位址限制;不接受 file/data/javascript。僅作本地瀏覽,不發 action;需要模型動作請在旁邊放置獨立 button。追加 / 重排保留當前 src;當前圖片移除後關閉檢視器;相同 src 按出現次序區分。空列表與圖片載入失敗皆有明確狀態。匯出 HTML 不內嵌圖片位元組,圖片仍依賴原始位址。完整用法與驗收。 - audio:
{"type":"audio","src":"/mmx-files/result.mp3","alt":"<user-language description>","loop":true?}— 原生控制條;使用者主動播放,不自動播放;僅 http(s) 或同源相對位址 - video:
{"type":"video","src":"/mmx-files/result.mp4","alt":"<user-language description>","poster":"/mmx-files/poster.jpg"?,"loop":true?,"muted":true?,"aspectRatio":"16:9|4:3|1:1|9:16"?}— 原生播放/音量/全螢幕控制;不自動播放 - list:
{"type":"list","items":["..."] 或 [{"title":"...","desc":"..."}] 或巢狀節點(如 {"type":"badge","label":"TS"})}— 行內可嵌入節點(計入節點預算);記錄中的label/name標準化為title,description/content/text/body/detail標準化為desc;只有正文時將正文用作標題,未知欄位會收到警告 - table:
{"type":"table","columns":["..."],"rows":[["...","..."]],"types":["text|num|delta|bar|badge"]?,"details":[[...]]?,"total":true?}— 表頭點擊本地排序(升/降/還原,零往返);數值感知:千分位(1,234)、k/m/b、萬/億、%、貨幣符號皆可按真實數值比較,純數值列自動靠右對齊;帶符號儲存格自動著色(+12.4%綠、-3紅,無需額外欄位);types可按列指定bar(0-100 內聯進度條)、ring(0-100 小環)、spark(儲存格寫"3,5,4,8"繪製微趨勢線)、badge(膠囊標籤)、delta(強制漲跌色)、num(強制靠右對齊)、index(行號)、group(首列當分組標題:該行只有第一格有內容時渲染成跨列小標題);"total":true追加合計行(數值列自動求和);"export":true:表格上方出現「複製 Markdown / 複製 CSV」兩個小按鈕(純本地剪貼板,不發請求);"filter":"輸入框id":將表格與某個 input/select 綁定,讀者輸入即時過濾(filterColumn可限定列)—資料多時預設就該配一個;"sortField":"下拉id"使用下拉的值(列名)排序;"details"與 rows 同順序,第 i 項是該行展開後的內容(可放置任意元件,null= 該行不可展開)—首列出現 chevron,點開在整行下方展開明細,適合「主表 + 明細」 - keyvalue:
{"type":"keyvalue","pairs":[{"key":"...","value":"..."}]} - timeline:
{"type":"timeline","items":[{"title":"...","desc":"...","time":"..."}]} - file-tree:
{"type":"file-tree","items":[{"name":"...","type":"file|dir","children":[...]?}]}— 目錄行可點擊折疊/展開(本地,零往返) - breadcrumb:
{"type":"breadcrumb","items":["<user-language text>","<user-language text>","<user-language text>"]} - diff:
{"type":"diff","diffs":[{"path":"...","oldText":"..."|null,"newText":"..."}]} - json:
{"type":"json","value":...}(JSON 樹檢視器) - code:
{"type":"code","lang":"ts","code":"..."} - callout:
{"type":"callout","tone":"info|success|warning|error","title":"...","content":"..."}— 用於單條強調、提醒或風險摘要;content是文字字串,可使用 JSON"\n"分行。多條獨立事項使用list的{title,desc}保留逐項層次 - steps:
{"type":"steps","current":n,"steps":[{"title":"...","desc":"..."}]} - arrow:
{"type":"arrow","dir":"down|right","length":16-96,"label":"..."}— 圖中兩個塊之間的細線連接件(1.4px 線寬 + V 形箭頭,固定長度)。上下流程圖一律使用它,不要使用文字「↓」:字元箭頭會跟隨文字基線,無法撐開間距 - icon:
{"type":"icon","name":"Nodes","tone":"info|success|warning|danger|muted|default","size":16|20|24|32,"tile":true,"label":"<user-language 無障礙名>"}— 內建圖示集(749 個可忠實渲染;64 個內聯秒開,其餘首次使用時載入,完整名單請見 ICON-NAMES.md)。tile:true繪製成淡色圓角方底,用於階段卡/語義標記;不帶tile是跟隨文字色的行內圖示。label可省略(純裝飾),成對出現時只給一個加上 label - blocks:
{"type":"blocks","title":"...","rows":[{"label":"初始","cells":["0","1","2"],"color":"#64748b"}],"columns":n?,"caption":"..."}— 色塊圖解:按行分組的格子。三種形態共用同一結構:① 階梯圖(每行格子數不同,各行自己等分寬度,如 8→4→2→1)② 等分塊(一行 4 塊)③ 泳道圖(columns固定列數,cells裡寫"—"或留空)。color省略時使用強調色淡底;文字顏色按亮度自動反轉(深底白字/淺底黑字)。有「分成幾份、逐輪推進、分組對照」的結構就使用它,不要手寫 svg 座標。caption必寫:一句話說明每格代表什麼- 行級
"variant":"outline":細邊框不填滿,用於矩陣(每格都是一個框);"variant":"plain":連框都不畫,用於位串(1 0 1 0 0 0 0 0讀起來是數字不是表格)—只有帶tone/color的格子會畫出底色 - 格子可以寫成物件:
{"text":"1","tone":"danger","sub":"SF"}——tone(accent/success/warning/danger/muted)為單個格子加上語義色,sub在格子下方掛一行小字(位名、序號、角色)。color可顯式指定十六進位,優先於 tone - 例:
{"columns":8,"rows":[{"variant":"outline","cells":[{"text":"1","tone":"danger","sub":"SF"},"0","1","1","0","0","1","0","0"]}],"caption":"最高位元為 1,所以 SF=1。"}
- 行級
內建圖示名:以下 64 個內聯在套件中、立即渲染,優先從這些裡面選:
Check CheckCircle Info InfoCircle Warning Error X Plus Minus Circle ArrowDown ArrowUp ArrowRight ArrowLeft ArrowCurvedRight Function Functions Operator Atom Nodes Connect Share Branch Grid GridAlt Stack Cube Storage Chart Trending Pulse Speed Timer Clock TableFilled Code SquareCode Terminal File FileCode Folder Link Paperclip Lightbulb Book BookOpen GraduationCap Flask Lab Brain Robot Sparkles ShieldCheck Lock Globe WebsiteNetwork Search MagnifyingGlassSearch PluginPuzzle Settings Bolt Compass
其餘 685 個依需載入(首次使用時拉取約 1 MB,此後本頁全部可用)。完整名單在本 SKILL 同目錄的 ICON-NAMES.md—需要猜名字時請讀取它或 grep 它,不要在對話中窮舉。
圖表
- chart:
{"type":"chart","kind":"bars|line|donut","data":[{"label":"...","value":n,"color":"#hex?"}],"series":[{"label":"...","data":[...]}]?,"horizontal":true?}— bars 預設;line 趨勢;donut 佔比;series:bars 是分組柱狀圖,line 是多序列折線圖;每個series[].data使用[{"label":"Q1","value":30},{"label":"Q2","value":45}]這樣的物件陣列,不是[30,45]這樣的純數字陣列;horizontal:true繪製橫向柱狀圖(排行/長標籤首選);stacked:true將 series 堆疊(構成/佔比隨時間);堆疊段夠高時數值直接印在段內,滑鼠懸停任意柱/段/點/扇區都會彈出即時 tooltip(堆疊顯示該段數值 + 合計)。v3 渲染:寬度自適應、Y 軸 1/2/5 刻度、單序列負值在零線以下真實繪製、line 附面積漸變與抽稀 X 標籤、donut 圖例顯示數值與百分比。≤8 個點的快速比較使用 chart;多序列、需要縮放/互動或資料量大時使用 echart - plot:
{"type":"plot","series":[{"expr":"a*sin(b*x)","label":"...","color":"#hex?","params":[{"name":"a","value":1,"min":0,"max":5,"animateTo":3,"durationMs":4000,"loop":true},{"name":"b","value":1,"min":0.5,"max":5}]}],"xMin":-6.28,"xMax":6.28,"title":"..."}— SVG 函數圖;series 可帶"kind":"line|area|scatter"(預設 line;area 填色到基線;scatter 散點);params 渲染成即時滑桿(拖動即時重繪,y 軸鎖定=只變曲線不變數軸);animateTo 參數會顯示播放按鈕(自動動畫演示);SVG 可拖曳平移、滾輪縮放;表達式支援 sin/cos/tan/asin/acos/atan/sqrt/cbrt/exp/log/ln/abs/floor/ceil/round/min/max/pow,常數 pi/e/tau,變數 x(其他字母=參數) - echart:
{"type":"echart","title":"...","height":300,"preset":"bar|line|area|pie|scatter","data":[{"label":"...","value":n}],"series":[...]?}— ECharts 全功能圖表,視覺效果遠超chart(漸變、tooltip、動畫、圖例互動);preset 模式:使用和chart一樣的data/series格式,自動建立主題化的 ECharts 配置(顏色跟隨宿主主題);preset 一覽(只寫 preset + data/series/links,主題自動跟隨):bar·line·area·pie·scatter·radar(每 series 一個多邊形,指標取自第一條 series 的 label)·gauge(每個 datum 一個儀表,適合單 KPI)·funnel(漏斗/轉換)·treemap(體積/層級佔比)·sankey(流向,使用links:[{from,to,value}])·graph(關係圖,links驅動,節點大小隨連接數)·heatmap(series當行、第一條 series 的 label 當列)·bigline(長序列 + 內建縮放)·wordCloud(詞雲,data:[{label,value}]的 value 表示權重;顏色跟隨palette或主題調色板) full option 模式:傳送"option":{...}直接寫 ECharts 原生配置(支援 ECharts 內建圖表及已註冊的wordCloud詞雲擴充;其他第三方擴充不保證可用),option 中的函數會被過濾(只接受資料)。選擇原則:chart 輕量(無額外下載)適合 ≤8 點的快速比較;echart 視覺更豐富(漸變、tooltip、圖例互動、dataZoom),但會依需下載約 1MB 引擎,多序列/大屏/互動場景優先
互動
本地優先(v2.6):UI 自己能做的狀態變化—評分、判題、重置、展開、選中—一律本地即時完成,零模型往返。action 只用於必須模型參與的事(生成新內容、執行工具、下一步建議)。互動元件必須帶 action:不帶 action 的按鈕渲染為禁用狀態,使用者無法點擊;帶 action 的按鈕點擊後有「已觸發」本地反饋。
- button:
{"type":"button","label":"...","tone":"primary|danger|success|ghost","full":true?,"small":true?,"icon":"emoji?","action":"refresh"?} - 秘密禁令:不得索取或生成密碼、API Key、存取權杖、復原碼等秘密輸入;遇到此類需求直接拒絕並解釋
- input:
{"type":"input","label":"...","placeholder":"...","inputType":"text|email|color|number","value":"...","action":"name"?,"id":"field-id"?}—color使用瀏覽器原生取色器,值使用#RRGGBB;number可作為 Computed 數值輸入;action 在失焦和 Enter 時觸發(Enter 會附帶submit:true);blur 僅在值有變化時才發送(聚焦又離開不產生空往返);payload 帶id幫助模型定位欄位;帶id的值在重新整理後保留、並被 submit 收集進fields - select:
{"type":"select","label":"...","options":["...","..."],"selected":下標?,"action":"pick"?,"id":"field-id"?}—selected預選某選項(預設顯示「請選擇…」佔位符,不靜默預選第一項);帶id的選擇在跨重新整理後保留並進入 submit 的fields - checkbox:
{"type":"checkbox","label":"<user-language option>","checked":true?,"action":"toggle"?,"group":"group-id"?}— 預設保持逐次action行為;加入group進入多選聚合模式:同 group 的 checkbox 可反覆勾選/取消,變化僅在本地記錄、不發逐次 action,兄弟submit一次性將該組已選 label 作為字串陣列放進answers(例如{"styles":["<user-language option>","<user-language option>"]}) - slider:
{"type":"slider","label":"...","min":0,"max":100,"step":1,"value":n?,"action":"name"?,"id":"field-id"?}— 數值表單滑桿:即時顯示數值;帶id在跨重新整理後保留並進入 submit 的fields(拖拽經防抖合併成一次 action) - radio:
{"type":"radio","label":"<user-language label>","options":["<user-language option>","<user-language option>"],"selected":n?,"action":"pick"?}— 單選;加入"group":"group-id"進入聚合模式:選擇僅在本地記錄、不發往返;可設定"answer":正確下標或標籤和"explanation":"<user-language explanation>",在純 radio 且沒有其他待發送表單狀態時進行本地評分 - link:
{"type":"link","label":"...","href":"https://..."?}— 僅 http(s)/mailto 協定會被接受;無href時渲染為純文字樣式(不會假裝可點擊) - submit:
{"type":"submit","label":"<user-language action>","action":"grade","groups":["q1","styles"],"resetAction":"redo"?}— 聚合按鈕:groups引用當前 block 中的 submission member key,來源為radio.group、checkbox.group、input.id、textarea.id、select.id、slider.id;radio 需已選擇,checkbox 組需至少選擇一項,普通 field 的值需在 trim 後非空。groups控制提交所需成員與完成進度;未設定時,至少有一個已完成成員即可提交。純 radio 範圍包含answer且本次沒有範圍外 payload 時可本地評分;其餘場景一次發送[genui-action],payload 繼續收集當前 block 中已填寫的表單狀態,欄位...