diff --git a/web/src/components/canvas/canvas-agent-chat-ui.tsx b/web/src/components/canvas/canvas-agent-chat-ui.tsx index dbf0559a4..68dc8471c 100644 --- a/web/src/components/canvas/canvas-agent-chat-ui.tsx +++ b/web/src/components/canvas/canvas-agent-chat-ui.tsx @@ -37,16 +37,16 @@ export function AgentChatMessage({ item, theme, user, onRejectTool, onApproveToo if (item.role === "tool") { if (objectField(item.detail, "status") === "pending") return onRejectTool?.(item.id)} onApprove={() => onApproveTool?.(item.id)} />; return ( -
+
); } return ( -
+
{!isUser ? : null} -
+
{item.text}
{item.attachments?.length ? : null} {item.meta ?
{item.meta}
: null} @@ -59,23 +59,23 @@ export function AgentChatMessage({ item, theme, user, onRejectTool, onApproveToo export function AgentPendingToolCard({ summary, detail, theme, onReject, onApprove }: { summary: string; detail?: unknown; theme: (typeof canvasThemes)[keyof typeof canvasThemes]; onReject?: () => void; onApprove?: () => void }) { const impact = agentImpactFromDetail(detail); return ( -
+
-
+
- +
确认工具调用 - 等待确认 + 等待确认
{summary}
{impact?.operationCount ? ( -
+
@@ -83,10 +83,10 @@ export function AgentPendingToolCard({ summary, detail, theme, onReject, onAppro 0} theme={theme} />
{impact.items.length ?
{impact.items.map((item, index) =>
{item}
)}
: null} - {impact.warning ?
{impact.warning}
: null} + {impact.warning ?
{impact.warning}
: null}
) : null} - {detail ?
技术详情
: null} + {detail ?
技术详情
: null} {onReject || onApprove ? (
-
); } -export function AgentModeSwitch({ value, theme, onChange }: { value: CanvasAgentMode; theme: (typeof canvasThemes)[keyof typeof canvasThemes]; onChange: (value: CanvasAgentMode) => void }) { - return ( -
- {(["online", "local"] as const).map((item) => ( - - ))} -
- ); -} - export function AgentPanelTabs({ value, items, theme, right, onChange }: { value: T; items: { value: T; label: string; icon?: ReactNode; count?: number }[]; theme: (typeof canvasThemes)[keyof typeof canvasThemes]; right?: ReactNode; onChange: (value: T) => void }) { return ( -
-
-
-
+ )}
)} @@ -804,7 +794,7 @@ export function CanvasAssistantPanel({ nodes, selectedNodeIds, snapshot, project left={ <> updateConfig("textModel", model)} /> - {cinematicEntryActive ? 影视项目 : null} + {cinematicEntryActive ? 影视项目 : null} } /> @@ -846,45 +836,26 @@ export function CanvasAssistantPanel({ nodes, selectedNodeIds, snapshot, project style={{ overflow: "clip", pointerEvents: closing ? "none" : undefined }} >
- -
- 将读取 - 当前画布 {contextSummary.nodeCount} 个节点 - {contextSummary.selectedCount ? 选区 {contextSummary.selectedCount} 个 : null} - {contextSummary.chapterLabel ? {contextSummary.chapterLabel}{contextSummary.shotLabel ? ` · ${contextSummary.shotLabel}` : ""} : null} - {selectedReferences.length ? {selectedReferences.length} 个参考节点 : null} - {undoOpsCount ? 可撤销 {undoOpsCount} 批 : null} -
+ setAgentState({ confirmTools })} + onUndo={undoLastOnlineBatch} + onCollapse={collapse} + /> {agentMode === "local" ? ( {sessions.map((session) => ( -
+
@@ -1016,7 +987,7 @@ function OnlineAgentSetupView({ theme, activeModel, onOpenConfig }: { theme: (ty 网站 Agent 直接使用当前网页配置的文本模型和 API。
-
+
文本模型
@@ -1059,8 +1030,8 @@ function OnlineAgentLogView({ logs, theme, context, onClear }: { logs: OnlineAge ref={textareaRef} readOnly value={content} - className="thin-scrollbar min-h-[360px] flex-1 resize-none rounded-lg border bg-transparent p-3 font-mono text-xs leading-5 outline-none" - style={{ borderColor: theme.node.stroke, color: theme.node.text }} + className="thin-scrollbar min-h-[360px] flex-1 resize-none rounded-md border-0 p-3 font-mono text-xs leading-5 outline-none" + style={{ background: theme.spatial.surface, color: theme.node.text }} onFocus={(event) => event.currentTarget.select()} />
@@ -1088,7 +1059,7 @@ function AssistantReferenceChip({ item, label, onRemove }: { item: CanvasAssista {label ? {label} : null} ) : ( - + {text} )} diff --git a/web/src/components/canvas/canvas-local-agent-panel.tsx b/web/src/components/canvas/canvas-local-agent-panel.tsx index bed6534a8..fa1b931c4 100644 --- a/web/src/components/canvas/canvas-local-agent-panel.tsx +++ b/web/src/components/canvas/canvas-local-agent-panel.tsx @@ -2,7 +2,7 @@ import { memo, useCallback, useEffect, useMemo, useRef, useState, type PointerEv import { useSearchParams } from "react-router"; import { App, Button, Input, Segmented, Tooltip } from "antd"; import copyToClipboard from "copy-to-clipboard"; -import { Copy, FolderOpen, History, KeyRound, Link2, LoaderCircle, PlugZap, Plus, RefreshCw, RotateCcw, Terminal, Trash2 } from "lucide-react"; +import { Copy, FolderOpen, History, KeyRound, Link2, LoaderCircle, MessageSquareText, PlugZap, Plus, RefreshCw, RotateCcw, Terminal, Trash2 } from "lucide-react"; import { motion } from "motion/react"; import { canvasThemes } from "@/lib/canvas-theme"; @@ -12,6 +12,7 @@ import { useCanvasAgentStore, type AgentAttachment, type AgentChatItem, type Age import { previewCanvasAgentOps, summarizeCanvasAgentOps, type CanvasAgentOp, type CanvasAgentSnapshot } from "@/lib/canvas/canvas-agent-ops"; import { isProjectAgentReadTool, isProjectAgentToolName, runProjectAgentTool } from "@/services/api/project-agent-tools"; import { AgentChatComposer, AgentChatMessage, AgentPanelTabs, AgentPendingToolCard, AgentWorkingMessage, type CanvasAgentChatAttachment } from "./canvas-agent-chat-ui"; +import { AgentChatEmptyState } from "./canvas-agent-panel-chrome"; const PANEL_MOTION_SECONDS = 0.5; const MAX_ATTACHMENTS = 6; @@ -487,7 +488,7 @@ export const CanvasLocalAgentPanel = memo(function CanvasLocalAgentPanel({ snaps theme={theme} items={[ { value: "setup", label: "连接", icon: }, - { value: "chat", label: "对话" }, + { value: "chat", label: "对话", icon: }, { value: "history", label: "历史", icon: , count: threads.length }, { value: "log", label: "日志", icon: , count: eventLogs.length }, ]} @@ -497,9 +498,9 @@ export const CanvasLocalAgentPanel = memo(function CanvasLocalAgentPanel({ snaps }} right={ <> - + +
))}
-
+
网页连接 - + {statusText} @@ -690,7 +692,7 @@ function AgentConnectView({ theme, url, token, enabled, connected, activity, con } value={token} onChange={(event) => onTokenChange(event.target.value)} placeholder="自动发现,或手动填入 Connect token" /> {connectError ? ( -
+
{connectError}
) : null} @@ -727,7 +729,7 @@ function AgentHistoryView({ theme, threads, activeThreadId, workspacePath, loadi {threads.map((thread) => { const active = thread.id === activeThreadId; return ( -
+