diff --git a/src/components/chat/permission-actions.tsx b/src/components/chat/permission-actions.tsx new file mode 100644 index 00000000..bfbd84f7 --- /dev/null +++ b/src/components/chat/permission-actions.tsx @@ -0,0 +1,84 @@ +"use client" + +import { useTranslations } from "next-intl" +import { Button } from "@/components/ui/button" +import type { PermissionOptionInfo } from "@/lib/types" + +type PermissionActionVariant = "default" | "outline" +type ActionLabelKey = (typeof KIND_LABEL_KEYS)[keyof typeof KIND_LABEL_KEYS] + +interface PermissionActionsProps { + options: PermissionOptionInfo[] + onRespond: (optionId: string) => void +} + +const KIND_LABEL_KEYS = { + allow_once: "allowOnce", + allow_always: "allowAlways", + reject_once: "rejectOnce", + reject_always: "rejectAlways", +} as const + +const KIND_VARIANTS: Record = { + allow_once: "default", + allow_always: "default", + reject_once: "outline", + reject_always: "outline", +} + +function extractDetail(name: string): string | undefined { + const match = name.match(/`([^`]+)`/) + return match?.[1] +} + +export function PermissionActions({ + options, + onRespond, +}: PermissionActionsProps) { + const t = useTranslations("Folder.chat.permissionDialog.actions") + + return ( +
+ {options.map((opt) => { + const variant: PermissionActionVariant = + KIND_VARIANTS[opt.kind] ?? + (opt.kind.startsWith("reject") ? "outline" : "default") + const labelKey = + KIND_LABEL_KEYS[opt.kind as keyof typeof KIND_LABEL_KEYS] + const label = labelKey ? t(labelKey as ActionLabelKey) : opt.name + // Only split label/detail for known kinds; unrecognized kinds + // render opt.name as-is since we have no translation key for them. + const detail = labelKey ? extractDetail(opt.name) : undefined + + if (detail) { + return ( + + ) + } + + return ( + + ) + })} +
+ ) +} diff --git a/src/components/chat/permission-dialog.tsx b/src/components/chat/permission-dialog.tsx index f2047804..b2bce8ba 100644 --- a/src/components/chat/permission-dialog.tsx +++ b/src/components/chat/permission-dialog.tsx @@ -11,11 +11,11 @@ import { Globe, Search, } from "lucide-react" -import { Button } from "@/components/ui/button" import { Badge } from "@/components/ui/badge" import { CodeBlock } from "@/components/ai-elements/code-block" import { UnifiedDiffPreview } from "@/components/diff/unified-diff-preview" import { MessageResponse } from "@/components/ai-elements/message" +import { PermissionActions } from "@/components/chat/permission-actions" import type { PendingPermission } from "@/contexts/acp-connections-context" import { parsePermissionToolCall } from "@/lib/permission-request" @@ -34,6 +34,7 @@ export function PermissionDialog({ onRespond, }: PermissionDialogProps) { const t = useTranslations("Folder.chat.permissionDialog") + const parsed = useMemo( () => parsePermissionToolCall(permission?.tool_call), [permission?.tool_call] @@ -56,7 +57,7 @@ export function PermissionDialog({ hasWeb return ( -
+
@@ -196,21 +197,10 @@ export function PermissionDialog({ )}
-
- {permission.options.map((opt) => { - const isReject = opt.kind.startsWith("reject") - return ( - - ) - })} -
+ onRespond(permission.request_id, optionId)} + />
) } diff --git a/src/i18n/messages/ar.json b/src/i18n/messages/ar.json index 41ddcd82..6efab57a 100644 --- a/src/i18n/messages/ar.json +++ b/src/i18n/messages/ar.json @@ -1439,7 +1439,13 @@ "moreFiles": "+{count} ملف إضافي", "plan": "الخطة", "allowedActions": "الإجراءات المسموح بها", - "targetMode": "وضع الهدف: {mode}" + "targetMode": "وضع الهدف: {mode}", + "actions": { + "allowOnce": "السماح", + "allowAlways": "السماح دائمًا", + "rejectOnce": "رفض", + "rejectAlways": "رفض دائمًا" + } }, "questionDialog": { "title": "الوكيل يطرح سؤالاً", diff --git a/src/i18n/messages/de.json b/src/i18n/messages/de.json index 573e24b6..9ce4a918 100644 --- a/src/i18n/messages/de.json +++ b/src/i18n/messages/de.json @@ -1439,7 +1439,13 @@ "moreFiles": "+{count} weitere Dateien", "plan": "Arbeitsplan", "allowedActions": "Erlaubte Aktionen", - "targetMode": "Zielmodus: {mode}" + "targetMode": "Zielmodus: {mode}", + "actions": { + "allowOnce": "Erlauben", + "allowAlways": "Immer erlauben", + "rejectOnce": "Ablehnen", + "rejectAlways": "Immer ablehnen" + } }, "questionDialog": { "title": "Agent stellt eine Frage", diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json index 846d68a1..52d31a4b 100644 --- a/src/i18n/messages/en.json +++ b/src/i18n/messages/en.json @@ -1439,7 +1439,13 @@ "moreFiles": "+{count} more files", "plan": "Plan", "allowedActions": "Allowed actions", - "targetMode": "Target mode: {mode}" + "targetMode": "Target mode: {mode}", + "actions": { + "allowOnce": "Allow", + "allowAlways": "Always allow", + "rejectOnce": "Reject", + "rejectAlways": "Always reject" + } }, "questionDialog": { "title": "Agent is asking a question", diff --git a/src/i18n/messages/es.json b/src/i18n/messages/es.json index 83e58175..aeb3642c 100644 --- a/src/i18n/messages/es.json +++ b/src/i18n/messages/es.json @@ -1439,7 +1439,13 @@ "moreFiles": "+{count} archivos más", "plan": "Plan de trabajo", "allowedActions": "Acciones permitidas", - "targetMode": "Modo objetivo: {mode}" + "targetMode": "Modo objetivo: {mode}", + "actions": { + "allowOnce": "Permitir", + "allowAlways": "Permitir siempre", + "rejectOnce": "Rechazar", + "rejectAlways": "Rechazar siempre" + } }, "questionDialog": { "title": "El agente está haciendo una pregunta", diff --git a/src/i18n/messages/fr.json b/src/i18n/messages/fr.json index aba2feaf..f2dafbc0 100644 --- a/src/i18n/messages/fr.json +++ b/src/i18n/messages/fr.json @@ -1439,7 +1439,13 @@ "moreFiles": "+{count} fichiers supplémentaires", "plan": "Plan de travail", "allowedActions": "Actions autorisées", - "targetMode": "Mode cible : {mode}" + "targetMode": "Mode cible : {mode}", + "actions": { + "allowOnce": "Autoriser", + "allowAlways": "Toujours autoriser", + "rejectOnce": "Refuser", + "rejectAlways": "Toujours refuser" + } }, "questionDialog": { "title": "L'agent pose une question", diff --git a/src/i18n/messages/ja.json b/src/i18n/messages/ja.json index 10ac49c5..05d5321b 100644 --- a/src/i18n/messages/ja.json +++ b/src/i18n/messages/ja.json @@ -1439,7 +1439,13 @@ "moreFiles": "+{count} 件の追加ファイル", "plan": "計画", "allowedActions": "許可されたアクション", - "targetMode": "対象モード: {mode}" + "targetMode": "対象モード: {mode}", + "actions": { + "allowOnce": "許可", + "allowAlways": "常に許可", + "rejectOnce": "拒否", + "rejectAlways": "常に拒否" + } }, "questionDialog": { "title": "エージェントが質問しています", diff --git a/src/i18n/messages/ko.json b/src/i18n/messages/ko.json index 3df750b8..5c3c670e 100644 --- a/src/i18n/messages/ko.json +++ b/src/i18n/messages/ko.json @@ -1439,7 +1439,13 @@ "moreFiles": "+{count}개 파일 더", "plan": "계획", "allowedActions": "허용된 작업", - "targetMode": "대상 모드: {mode}" + "targetMode": "대상 모드: {mode}", + "actions": { + "allowOnce": "허용", + "allowAlways": "항상 허용", + "rejectOnce": "거부", + "rejectAlways": "항상 거부" + } }, "questionDialog": { "title": "에이전트가 질문하고 있습니다", diff --git a/src/i18n/messages/pt.json b/src/i18n/messages/pt.json index 923655df..8fafad69 100644 --- a/src/i18n/messages/pt.json +++ b/src/i18n/messages/pt.json @@ -1439,7 +1439,13 @@ "moreFiles": "+{count} arquivos a mais", "plan": "Plano", "allowedActions": "Ações permitidas", - "targetMode": "Modo de destino: {mode}" + "targetMode": "Modo de destino: {mode}", + "actions": { + "allowOnce": "Permitir", + "allowAlways": "Permitir sempre", + "rejectOnce": "Rejeitar", + "rejectAlways": "Rejeitar sempre" + } }, "questionDialog": { "title": "O agente está fazendo uma pergunta", diff --git a/src/i18n/messages/zh-CN.json b/src/i18n/messages/zh-CN.json index 40b0d4c1..ab6816cc 100644 --- a/src/i18n/messages/zh-CN.json +++ b/src/i18n/messages/zh-CN.json @@ -1439,7 +1439,13 @@ "moreFiles": "+{count} 个更多文件", "plan": "计划", "allowedActions": "允许的操作", - "targetMode": "目标模式:{mode}" + "targetMode": "目标模式:{mode}", + "actions": { + "allowOnce": "允许", + "allowAlways": "始终允许", + "rejectOnce": "拒绝", + "rejectAlways": "始终拒绝" + } }, "questionDialog": { "title": "代理正在提问", diff --git a/src/i18n/messages/zh-TW.json b/src/i18n/messages/zh-TW.json index 52cbf7b3..212fc00b 100644 --- a/src/i18n/messages/zh-TW.json +++ b/src/i18n/messages/zh-TW.json @@ -1439,7 +1439,13 @@ "moreFiles": "+{count} 個更多檔案", "plan": "計畫", "allowedActions": "允許的操作", - "targetMode": "目標模式:{mode}" + "targetMode": "目標模式:{mode}", + "actions": { + "allowOnce": "允許", + "allowAlways": "始終允許", + "rejectOnce": "拒絕", + "rejectAlways": "始終拒絕" + } }, "questionDialog": { "title": "代理正在提問",