diff --git a/src/components/chat/permission-dialog.tsx b/src/components/chat/permission-dialog.tsx index 7edf7eb..a3934ba 100644 --- a/src/components/chat/permission-dialog.tsx +++ b/src/components/chat/permission-dialog.tsx @@ -8,10 +8,12 @@ import { FilePenLine, ListTodo, Compass, + FileText, } from "lucide-react" import { Button } from "@/components/ui/button" import { Badge } from "@/components/ui/badge" import { CodeBlock } from "@/components/ai-elements/code-block" +import { MessageResponse } from "@/components/ai-elements/message" import type { PendingPermission } from "@/contexts/acp-connections-context" import { parsePermissionToolCall } from "@/lib/permission-request" @@ -39,10 +41,14 @@ export function PermissionDialog({ const hasFileChanges = parsed.fileChanges.length > 0 const hasPlan = parsed.planEntries.length > 0 || Boolean(parsed.planExplanation) + const hasPlanMarkdown = Boolean(parsed.planMarkdown) + const hasAllowedPrompts = parsed.allowedPrompts.length > 0 const hasStructured = Boolean(parsed.command) || hasFileChanges || hasPlan || + hasPlanMarkdown || + hasAllowedPrompts || Boolean(parsed.modeTarget) return ( @@ -138,6 +144,42 @@ export function PermissionDialog({ )} + {hasPlanMarkdown && ( +
+
+ + {t("plan")} +
+
+ {parsed.planMarkdown!} +
+
+ )} + + {hasAllowedPrompts && ( +
+
+ + {t("allowedActions")} +
+
+ {parsed.allowedPrompts.map((item, index) => ( +
+ {item.tool && ( + + {item.tool} + + )} + {item.prompt} +
+ ))} +
+
+ )} + {parsed.modeTarget && (
diff --git a/src/i18n/messages/ar.json b/src/i18n/messages/ar.json index cacd3df..0874db8 100644 --- a/src/i18n/messages/ar.json +++ b/src/i18n/messages/ar.json @@ -1173,6 +1173,7 @@ "filesSummary": "الملفات: {count}", "moreFiles": "+{count} ملف إضافي", "plan": "الخطة", + "allowedActions": "الإجراءات المسموح بها", "targetMode": "وضع الهدف: {mode}" }, "questionDialog": { diff --git a/src/i18n/messages/de.json b/src/i18n/messages/de.json index b132d56..6f17238 100644 --- a/src/i18n/messages/de.json +++ b/src/i18n/messages/de.json @@ -1173,6 +1173,7 @@ "filesSummary": "Dateien: {count}", "moreFiles": "+{count} weitere Dateien", "plan": "Arbeitsplan", + "allowedActions": "Erlaubte Aktionen", "targetMode": "Zielmodus: {mode}" }, "questionDialog": { diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json index 556a45d..85a08a2 100644 --- a/src/i18n/messages/en.json +++ b/src/i18n/messages/en.json @@ -1173,6 +1173,7 @@ "filesSummary": "Files: {count}", "moreFiles": "+{count} more files", "plan": "Plan", + "allowedActions": "Allowed actions", "targetMode": "Target mode: {mode}" }, "questionDialog": { diff --git a/src/i18n/messages/es.json b/src/i18n/messages/es.json index a06a9e6..3430e4d 100644 --- a/src/i18n/messages/es.json +++ b/src/i18n/messages/es.json @@ -1173,6 +1173,7 @@ "filesSummary": "Archivos: {count}", "moreFiles": "+{count} archivos más", "plan": "Plan de trabajo", + "allowedActions": "Acciones permitidas", "targetMode": "Modo objetivo: {mode}" }, "questionDialog": { diff --git a/src/i18n/messages/fr.json b/src/i18n/messages/fr.json index c2fc8cf..552a452 100644 --- a/src/i18n/messages/fr.json +++ b/src/i18n/messages/fr.json @@ -1173,6 +1173,7 @@ "filesSummary": "Fichiers : {count}", "moreFiles": "+{count} fichiers supplémentaires", "plan": "Plan de travail", + "allowedActions": "Actions autorisées", "targetMode": "Mode cible : {mode}" }, "questionDialog": { diff --git a/src/i18n/messages/ja.json b/src/i18n/messages/ja.json index 748ea06..1feac08 100644 --- a/src/i18n/messages/ja.json +++ b/src/i18n/messages/ja.json @@ -1173,6 +1173,7 @@ "filesSummary": "ファイル: {count}", "moreFiles": "+{count} 件の追加ファイル", "plan": "計画", + "allowedActions": "許可されたアクション", "targetMode": "対象モード: {mode}" }, "questionDialog": { diff --git a/src/i18n/messages/ko.json b/src/i18n/messages/ko.json index ae10334..c57c83f 100644 --- a/src/i18n/messages/ko.json +++ b/src/i18n/messages/ko.json @@ -1173,6 +1173,7 @@ "filesSummary": "파일: {count}", "moreFiles": "+{count}개 파일 더", "plan": "계획", + "allowedActions": "허용된 작업", "targetMode": "대상 모드: {mode}" }, "questionDialog": { diff --git a/src/i18n/messages/pt.json b/src/i18n/messages/pt.json index 7e38f1c..0c3d2bb 100644 --- a/src/i18n/messages/pt.json +++ b/src/i18n/messages/pt.json @@ -1173,6 +1173,7 @@ "filesSummary": "Arquivos: {count}", "moreFiles": "+{count} arquivos a mais", "plan": "Plano", + "allowedActions": "Ações permitidas", "targetMode": "Modo de destino: {mode}" }, "questionDialog": { diff --git a/src/i18n/messages/zh-CN.json b/src/i18n/messages/zh-CN.json index cfb3bc4..f55f6ef 100644 --- a/src/i18n/messages/zh-CN.json +++ b/src/i18n/messages/zh-CN.json @@ -1173,6 +1173,7 @@ "filesSummary": "文件:{count}", "moreFiles": "+{count} 个更多文件", "plan": "计划", + "allowedActions": "允许的操作", "targetMode": "目标模式:{mode}" }, "questionDialog": { diff --git a/src/i18n/messages/zh-TW.json b/src/i18n/messages/zh-TW.json index 7716659..959ec53 100644 --- a/src/i18n/messages/zh-TW.json +++ b/src/i18n/messages/zh-TW.json @@ -1173,6 +1173,7 @@ "filesSummary": "檔案:{count}", "moreFiles": "+{count} 個更多檔案", "plan": "計畫", + "allowedActions": "允許的操作", "targetMode": "目標模式:{mode}" }, "questionDialog": { diff --git a/src/lib/permission-request.ts b/src/lib/permission-request.ts index 5f89d10..57403b9 100644 --- a/src/lib/permission-request.ts +++ b/src/lib/permission-request.ts @@ -19,6 +19,11 @@ export interface PermissionPlanEntry { status: string | null } +export interface PermissionAllowedPrompt { + prompt: string + tool: string +} + export interface ParsedPermissionToolCall { title: string normalizedKind: string @@ -30,6 +35,8 @@ export interface ParsedPermissionToolCall { diffPreview: string | null planEntries: PermissionPlanEntry[] planExplanation: string | null + planMarkdown: string | null + allowedPrompts: PermissionAllowedPrompt[] modeTarget: string | null jsonPreview: string } @@ -529,6 +536,28 @@ function parsePlanEntries( return [] } +function parseAllowedPrompts( + rawInputObj: ObjectLike | null +): PermissionAllowedPrompt[] { + if (!rawInputObj) return [] + const list = asArray( + pickValue(rawInputObj, ["allowedPrompts", "allowed_prompts"]) + ) + if (!list || list.length === 0) return [] + + const prompts: PermissionAllowedPrompt[] = [] + for (const item of list) { + const record = asObject(item) + if (!record) continue + const prompt = pickString(record, ["prompt", "description", "text"]) + const tool = pickString(record, ["tool", "toolName", "tool_name"]) + if (prompt) { + prompts.push({ prompt, tool: tool ?? "" }) + } + } + return prompts +} + function formatFallbackTitle(kind: string): string { const normalized = kind.replace(/_/g, " ").trim() if (!normalized) return "Permission Request" @@ -631,6 +660,13 @@ export function parsePermissionToolCall( const planEntries = parsePlanEntries(rawInputObj) const planExplanation = pickString(rawInputObj, ["explanation"]) + + const rawPlan = rawInputObj ? pickValue(rawInputObj, ["plan"]) : null + const planMarkdown = + typeof rawPlan === "string" && rawPlan.trim().length > 0 ? rawPlan : null + + const allowedPrompts = parseAllowedPrompts(rawInputObj) + const modeTarget = pickString(rawInputObj, [ "mode_id", @@ -654,6 +690,8 @@ export function parsePermissionToolCall( diffPreview, planEntries, planExplanation, + planMarkdown, + allowedPrompts, modeTarget, jsonPreview: stringifyJson(toolCallObj ?? toolCall), }