支持显示权限请求里面的plan markdown
This commit is contained in:
@@ -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({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{hasPlanMarkdown && (
|
||||
<div className="space-y-1.5 rounded-md border border-border/60 bg-muted/20 p-2">
|
||||
<div className="flex items-center gap-1 text-xs text-muted-foreground">
|
||||
<FileText className="h-3.5 w-3.5" />
|
||||
<span>{t("plan")}</span>
|
||||
</div>
|
||||
<div className="text-sm prose prose-sm dark:prose-invert max-w-none [&_ul]:list-inside [&_ol]:list-inside">
|
||||
<MessageResponse>{parsed.planMarkdown!}</MessageResponse>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{hasAllowedPrompts && (
|
||||
<div className="space-y-1.5 rounded-md border border-border/60 bg-muted/20 p-2">
|
||||
<div className="flex items-center gap-1 text-xs text-muted-foreground">
|
||||
<Terminal className="h-3.5 w-3.5" />
|
||||
<span>{t("allowedActions")}</span>
|
||||
</div>
|
||||
<div className="space-y-1 rounded-md bg-muted/40 p-2">
|
||||
{parsed.allowedPrompts.map((item, index) => (
|
||||
<div
|
||||
key={`${item.prompt}-${index}`}
|
||||
className="flex items-center gap-2 text-xs"
|
||||
>
|
||||
{item.tool && (
|
||||
<Badge variant="outline" className="shrink-0 text-[10px]">
|
||||
{item.tool}
|
||||
</Badge>
|
||||
)}
|
||||
<span className="text-foreground/90">{item.prompt}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{parsed.modeTarget && (
|
||||
<div className="rounded-md border border-border/60 bg-muted/20 p-2 text-xs">
|
||||
<div className="flex items-center gap-1 text-muted-foreground">
|
||||
|
||||
@@ -1173,6 +1173,7 @@
|
||||
"filesSummary": "الملفات: {count}",
|
||||
"moreFiles": "+{count} ملف إضافي",
|
||||
"plan": "الخطة",
|
||||
"allowedActions": "الإجراءات المسموح بها",
|
||||
"targetMode": "وضع الهدف: {mode}"
|
||||
},
|
||||
"questionDialog": {
|
||||
|
||||
@@ -1173,6 +1173,7 @@
|
||||
"filesSummary": "Dateien: {count}",
|
||||
"moreFiles": "+{count} weitere Dateien",
|
||||
"plan": "Arbeitsplan",
|
||||
"allowedActions": "Erlaubte Aktionen",
|
||||
"targetMode": "Zielmodus: {mode}"
|
||||
},
|
||||
"questionDialog": {
|
||||
|
||||
@@ -1173,6 +1173,7 @@
|
||||
"filesSummary": "Files: {count}",
|
||||
"moreFiles": "+{count} more files",
|
||||
"plan": "Plan",
|
||||
"allowedActions": "Allowed actions",
|
||||
"targetMode": "Target mode: {mode}"
|
||||
},
|
||||
"questionDialog": {
|
||||
|
||||
@@ -1173,6 +1173,7 @@
|
||||
"filesSummary": "Archivos: {count}",
|
||||
"moreFiles": "+{count} archivos más",
|
||||
"plan": "Plan de trabajo",
|
||||
"allowedActions": "Acciones permitidas",
|
||||
"targetMode": "Modo objetivo: {mode}"
|
||||
},
|
||||
"questionDialog": {
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -1173,6 +1173,7 @@
|
||||
"filesSummary": "ファイル: {count}",
|
||||
"moreFiles": "+{count} 件の追加ファイル",
|
||||
"plan": "計画",
|
||||
"allowedActions": "許可されたアクション",
|
||||
"targetMode": "対象モード: {mode}"
|
||||
},
|
||||
"questionDialog": {
|
||||
|
||||
@@ -1173,6 +1173,7 @@
|
||||
"filesSummary": "파일: {count}",
|
||||
"moreFiles": "+{count}개 파일 더",
|
||||
"plan": "계획",
|
||||
"allowedActions": "허용된 작업",
|
||||
"targetMode": "대상 모드: {mode}"
|
||||
},
|
||||
"questionDialog": {
|
||||
|
||||
@@ -1173,6 +1173,7 @@
|
||||
"filesSummary": "Arquivos: {count}",
|
||||
"moreFiles": "+{count} arquivos a mais",
|
||||
"plan": "Plano",
|
||||
"allowedActions": "Ações permitidas",
|
||||
"targetMode": "Modo de destino: {mode}"
|
||||
},
|
||||
"questionDialog": {
|
||||
|
||||
@@ -1173,6 +1173,7 @@
|
||||
"filesSummary": "文件:{count}",
|
||||
"moreFiles": "+{count} 个更多文件",
|
||||
"plan": "计划",
|
||||
"allowedActions": "允许的操作",
|
||||
"targetMode": "目标模式:{mode}"
|
||||
},
|
||||
"questionDialog": {
|
||||
|
||||
@@ -1173,6 +1173,7 @@
|
||||
"filesSummary": "檔案:{count}",
|
||||
"moreFiles": "+{count} 個更多檔案",
|
||||
"plan": "計畫",
|
||||
"allowedActions": "允許的操作",
|
||||
"targetMode": "目標模式:{mode}"
|
||||
},
|
||||
"questionDialog": {
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user