AI 應用元件

工具權限確認卡

代理請求執行工具時的權限確認卡:顯示工具名與參數摘要,允許、拒絕或永遠允許,決定後收合成一行紀錄。

放在對話訊息流裡、代理要執行有副作用的工具之前出現的授權卡。卡片列出工具名、風險等級、一句話說明與參數摘要,底部提供「拒絕」「永遠允許此工具」「允許」三個選擇;做出決定後,參數區與按鈕列淡出收起,整張卡以 layout 動畫收合成一行紀錄(「已允許:寫入檔案 · src/notes/今日.md」),點一下可重新展開檢視參數。高風險工具會加上紅色色帶、隱藏「永遠允許」並把預設焦點放在「拒絕」;也可以設定倒數秒數,逾時自動視為拒絕。和顯示「執行狀態」的工具呼叫卡互補,這張卡負責「執行前的授權」。

把這個效果裝進你的專案

在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。

npx webberui@latest add tool-permission-card

還沒有專案,或安裝遇到問題?看快速開始 →

Playground

即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。

220
0
編輯中的呼叫預設屬性
<ToolPermissionCard/>

完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。

安裝

npx webberui@latest add https://webberui.com/r/tool-permission-card.json

或在 components.json 設定 registries 後,改用 @webberui/tool-permission-card 安裝。

使用

import { ToolPermissionCard } from "@/components/ui/tool-permission-card";

<ToolPermissionCard
  toolName="寫入檔案"
  description="代理想在專案中建立一個新檔案"
  risk="low"
  params={[
    { label: "路徑", value: "src/notes/今日.md", mono: true },
    { label: "大小", value: "1.2 KB" },
  ]}
  onDecision={async (decision) => {
    // 把授權結果送回你的代理執行環境;reject 會讓卡片維持待決定
    await sendToAgent({ tool: "write_file", decision });
  }}
/>

Props

Prop型別預設值說明
toolNamestring—工具名稱(例「寫入檔案」)
toolIconReactNode扳手圖示工具圖示
descriptionstring—一句話說明代理想做什麼
paramsToolPermissionParam[][]參數摘要;超過 4 列時預設摺疊
risk"low" | "medium" | "high""medium"風險等級;high 時顯示紅色色帶並隱藏「永遠允許」
statusToolPermissionStatus—受控狀態;未提供時由元件內部管理(非受控)
defaultStatusToolPermissionStatus"pending"非受控模式的初始狀態
onStatusChange(status: ToolPermissionStatus) => void—狀態變動時回呼
onDecision(decision: "allow" | "deny" | "always") => void | Promise<void>—做出決定時回呼;回傳 Promise 時按鈕顯示載入中,resolve 後才收合,reject 則維持待決定
allowLabelstring"允許"允許按鈕文字
denyLabelstring"拒絕"拒絕按鈕文字
alwaysLabelstring"永遠允許此工具"永遠允許按鈕文字
hideAlwaysbooleanfalse隱藏「永遠允許」按鈕
expiresInnumber0倒數秒數;歸零時自動視為拒絕,0 表示不倒數
collapseDurationnumber220收合動畫時長(毫秒),同時寫入 --wb-tool-permission-card-duration
autoFocusbooleantrue出現時自動聚焦「允許」(high 風險時聚焦「拒絕」)
classNamestring—透傳到最外層容器

ToolPermissionStatus 為 "pending" \| "allowed" \| "denied" \| "always"。

ToolPermissionParam

欄位型別預設值說明
labelstring—參數名稱(例「路徑」)
valuestring—參數值;過長時截斷,hover 顯示完整內容
monobooleanfalse以等寬字體顯示(路徑、指令等)

細節

  • 收合動畫:決定瞬間參數區與按鈕列以 AnimatePresence 退場(透明度與高度歸零),外層 motion.div 帶 layout,在 collapseDuration 內以 easeInOut 收成一行;結果圖示(✓/✕/∞)以 spring 從 0.6 倍彈到原尺寸,顏色依結果為 emerald/red/sky。
  • 收合後的紀錄列是一顆按鈕,點擊可展開檢視說明與參數;展開內容唯讀,決定不可更改。
  • onDecision 回傳 Promise 時,被按下的按鈕顯示 spinner 並設定 aria-busy,其他按鈕暫停使用;Promise reject 時卡片維持待決定,可再按一次。
  • expiresIn 倒數以卡片底部的細進度條呈現,最後四分之一轉紅;歸零時呼叫 onDecision("deny") 並收合為「已拒絕」。
  • 按鈕 hover 過渡與展開箭頭的旋轉都使用 --wb-tool-permission-card-duration,可在全域覆寫。

可及性

  • 卡片為 role="group",以 aria-labelledby 指向工具名
  • 待決定時,焦點在卡片內按 Escape 拒絕;焦點不在按鈕上時按 Enter 允許(焦點在按鈕上時 Enter 交給該按鈕),並含 IME 組字保護
  • 預設聚焦「允許」,高風險時改為聚焦「拒絕」,降低誤按的代價;聚焦時不捲動頁面,訊息流裡有多張卡時可用 autoFocus={false} 關閉
  • 決定後焦點移到收合後的紀錄列(若決定時焦點在卡片內),紀錄列以 aria-expanded 標示展開狀態,並以 aria-live="polite" 宣告「已允許寫入檔案」等結果
  • 倒數進度條對輔助科技隱藏,剩餘秒數以 sr-only 文字提供
  • 使用者系統開啟「減少動態效果」時,收合不做高度與 layout 動畫、紀錄列以 120ms 淡入直接切換,結果圖示不彈跳,倒數進度條改為數字顯示