mirror of
https://github.com/basketikun/infinite-canvas.git
synced 2026-07-24 15:24:06 +08:00
refactor: remove agent mode switch and streamline local agent usage in the canvas assistant panel
This commit is contained in:
@@ -10,6 +10,7 @@ description: 当前版本已实现但仍需人工验证的变更项
|
||||
- Codex App 插件文档:新增插件安装教程,区分 AI 自动安装、手动安装和本仓库开发调试安装;同步优化插件 README 与技能说明。
|
||||
- 顶部导航:缩小桌面顶部导航栏高度,导航项下划线和内容垂直对齐需确认。
|
||||
- 配置与用户偏好:新增独立顶部导航页面,并在页面和弹窗中复用同一套配置面板;新增 Codex Tab,展示插件安装和本地 Agent 启动步骤,可配置本地 Agent 地址、Connect token 和工具执行确认开关。
|
||||
- 画布 Agent:右侧 Agent 面板移除网站 / 本机模式切换,固定使用本机 Agent。
|
||||
- 配置与用户偏好:每个模型渠道新增 OpenAI / Gemini 调用格式选择,默认 OpenAI,切换默认格式时同步更新默认 Base URL;渠道 Tab 增加紧凑醒目的提醒,说明模型是否可选需要到“模型”Tab 选择。
|
||||
- Gemini 调用格式:支持拉取 Gemini 模型列表,并用于文本问答、在线 Agent 工具调用、基础生图和图生图请求。
|
||||
- 音频和视频生成:选择 Gemini 调用格式时先给出不支持提示,仍需使用 OpenAI 兼容渠道。
|
||||
|
||||
@@ -6,7 +6,6 @@ import { canvasThemes } from "@/lib/canvas-theme";
|
||||
import type { LocalUser } from "@/stores/use-user-store";
|
||||
|
||||
export type CanvasAgentChatAttachment = { id: string; name: string; url: string };
|
||||
export type CanvasAgentMode = "online" | "local";
|
||||
export type CanvasAgentChatMessage = {
|
||||
id: string;
|
||||
role: "user" | "assistant" | "system" | "tool" | "error";
|
||||
@@ -228,18 +227,6 @@ export function AgentChatComposer({
|
||||
);
|
||||
}
|
||||
|
||||
export function AgentModeSwitch({ value, theme, onChange }: { value: CanvasAgentMode; theme: (typeof canvasThemes)[keyof typeof canvasThemes]; onChange: (value: CanvasAgentMode) => void }) {
|
||||
return (
|
||||
<div className="inline-flex shrink-0 rounded-lg border p-0.5 text-xs" style={{ borderColor: theme.node.stroke }}>
|
||||
{(["online", "local"] as const).map((item) => (
|
||||
<button key={item} type="button" className="rounded-md px-2 py-1 transition" style={{ background: value === item ? theme.node.fill : "transparent", color: value === item ? theme.node.text : theme.node.muted }} onClick={() => onChange(item)}>
|
||||
{item === "online" ? "网站" : "本机"}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function AgentPanelTabs<T extends string>({ 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 (
|
||||
<div className="border-b px-3" style={{ borderColor: theme.node.stroke }}>
|
||||
|
||||
@@ -16,7 +16,7 @@ import { imageReferenceLabel } from "@/lib/image-reference-prompt";
|
||||
import { DiaTextReveal } from "@/components/ui/dia-text-reveal";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger } from "@/components/ui/select";
|
||||
import { CanvasPromptLibrary } from "./canvas-prompt-library";
|
||||
import { AgentChatComposer, AgentChatMessage, AgentModeSwitch, AgentPanelTabs, AgentWorkingMessage, type CanvasAgentChatMessage, type CanvasAgentMode } from "./canvas-agent-chat-ui";
|
||||
import { AgentChatComposer, AgentChatMessage, AgentPanelTabs, AgentWorkingMessage, type CanvasAgentChatMessage } from "./canvas-agent-chat-ui";
|
||||
import { CanvasLocalAgentPanel } from "./canvas-local-agent-panel";
|
||||
import { NODE_DEFAULT_SIZE } from "@/constant/canvas";
|
||||
import { CanvasNodeType, type CanvasAssistantMessage, type CanvasAssistantReference, type CanvasAssistantSession, type CanvasNodeData } from "@/types/canvas";
|
||||
@@ -133,14 +133,12 @@ type CanvasAssistantPanelProps = {
|
||||
canUndoOps: boolean;
|
||||
onUndoOps: () => CanvasAgentSnapshot | null;
|
||||
onPasteImage: (file: File) => void;
|
||||
agentMode: CanvasAgentMode;
|
||||
onAgentModeChange: (mode: CanvasAgentMode) => void;
|
||||
autoConnectLocal?: boolean;
|
||||
closing: boolean;
|
||||
onCollapse: () => void;
|
||||
};
|
||||
|
||||
export function CanvasAssistantPanel({ nodes, selectedNodeIds, snapshot, sessions, activeSessionId, onSelectNodeIds, onSessionsChange, onApplyOps, canUndoOps, onUndoOps, onPasteImage, agentMode, onAgentModeChange, autoConnectLocal, closing, onCollapse }: CanvasAssistantPanelProps) {
|
||||
export function CanvasAssistantPanel({ nodes, selectedNodeIds, snapshot, sessions, activeSessionId, onSelectNodeIds, onSessionsChange, onApplyOps, canUndoOps, onUndoOps, onPasteImage, autoConnectLocal, closing, onCollapse }: CanvasAssistantPanelProps) {
|
||||
const theme = canvasThemes[useThemeStore((state) => state.theme)];
|
||||
const user = useUserStore((state) => state.user);
|
||||
const effectiveConfig = useEffectiveConfig();
|
||||
@@ -642,7 +640,6 @@ export function CanvasAssistantPanel({ nodes, selectedNodeIds, snapshot, session
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex shrink-0 items-center gap-2">
|
||||
<AgentModeSwitch value={agentMode} theme={theme} onChange={onAgentModeChange} />
|
||||
<label className="flex items-center gap-1.5 text-xs" style={{ color: theme.node.muted }}>
|
||||
<Switch size="small" checked={confirmTools} onChange={(confirmTools) => setAgentState({ confirmTools })} />
|
||||
工具确认
|
||||
@@ -652,18 +649,14 @@ export function CanvasAssistantPanel({ nodes, selectedNodeIds, snapshot, session
|
||||
</Tooltip>
|
||||
</div>
|
||||
</header>
|
||||
{agentMode === "local" ? (
|
||||
<CanvasLocalAgentPanel
|
||||
embedded
|
||||
snapshot={snapshot}
|
||||
canUndoOps={canUndoOps}
|
||||
onApplyOps={onApplyOps}
|
||||
onUndoOps={onUndoOps}
|
||||
autoConnect={autoConnectLocal}
|
||||
/>
|
||||
) : (
|
||||
onlineContent
|
||||
)}
|
||||
<CanvasLocalAgentPanel
|
||||
embedded
|
||||
snapshot={snapshot}
|
||||
canUndoOps={canUndoOps}
|
||||
onApplyOps={onApplyOps}
|
||||
onUndoOps={onUndoOps}
|
||||
autoConnect={autoConnectLocal}
|
||||
/>
|
||||
</motion.aside>
|
||||
</motion.div>
|
||||
);
|
||||
|
||||
@@ -47,7 +47,7 @@ const webdavDomainLabels: Record<AppSyncDomainKey, string> = {
|
||||
};
|
||||
const codexSetupSteps = [
|
||||
{ title: "安装 Codex 插件", text: "先在 Codex App 安装 Infinite Canvas 插件,插件会注册 MCP 并尝试启动本地 Canvas Agent。" },
|
||||
{ title: "打开画布 Agent", text: "回到画布右侧 Agent 面板选择本地模式,网页会自动读取 Local URL 和 Connect token。" },
|
||||
{ title: "打开画布 Agent", text: "回到画布右侧 Agent 面板,网页会自动读取 Local URL 和 Connect token。" },
|
||||
{ title: "手动启动备用", text: "如果插件没有自动启动本地服务,在终端运行下面命令。", command: "npx -y @basketikun/canvas-agent" },
|
||||
];
|
||||
|
||||
|
||||
@@ -45,7 +45,6 @@ import { useCanvasAgentStore } from "@/stores/canvas/use-canvas-agent-store";
|
||||
import { useCanvasStore } from "@/stores/canvas/use-canvas-store";
|
||||
import { applyCanvasAgentOps, type CanvasAgentOp, type CanvasAgentSnapshot } from "@/lib/canvas/canvas-agent-ops";
|
||||
import { buildCanvasResourceReferences, buildNodeMentionReferences } from "@/lib/canvas/canvas-resource-references";
|
||||
import type { CanvasAgentMode } from "@/components/canvas/canvas-agent-chat-ui";
|
||||
import {
|
||||
CanvasNodeType,
|
||||
type CanvasAssistantImage,
|
||||
@@ -304,7 +303,6 @@ function InfiniteCanvasPage() {
|
||||
const [assistantCollapsed, setAssistantCollapsed] = useState(true);
|
||||
const [assistantMounted, setAssistantMounted] = useState(false);
|
||||
const [assistantClosing, setAssistantClosing] = useState(false);
|
||||
const [agentMode, setAgentMode] = useState<CanvasAgentMode>("online");
|
||||
const [agentUndoSnapshot, setAgentUndoSnapshot] = useState<CanvasAgentSnapshot | null>(null);
|
||||
const codexAutoConnect = ["new", "recent", "choose"].includes(searchParams.get("mode") || "");
|
||||
const codexCompactAgent = codexAutoConnect && searchParams.has("agentUrl");
|
||||
@@ -432,11 +430,7 @@ function InfiniteCanvasPage() {
|
||||
|
||||
useEffect(() => {
|
||||
if (!projectLoaded || !["new", "recent", "choose"].includes(searchParams.get("mode") || "")) return;
|
||||
if (searchParams.has("agentUrl")) {
|
||||
setAgentMode("local");
|
||||
return;
|
||||
}
|
||||
openAgent("local");
|
||||
if (!searchParams.has("agentUrl")) openAgent();
|
||||
}, [projectLoaded, searchParams]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -2465,12 +2459,11 @@ function InfiniteCanvasPage() {
|
||||
);
|
||||
|
||||
const assistantOpen = assistantMounted && !assistantCollapsed;
|
||||
const openAgent = (mode: CanvasAgentMode = agentMode) => {
|
||||
const openAgent = () => {
|
||||
if (agentCloseTimerRef.current) {
|
||||
clearTimeout(agentCloseTimerRef.current);
|
||||
agentCloseTimerRef.current = null;
|
||||
}
|
||||
setAgentMode(mode);
|
||||
setAssistantMounted(true);
|
||||
setAssistantClosing(false);
|
||||
setAssistantCollapsed(false);
|
||||
@@ -2806,8 +2799,6 @@ function InfiniteCanvasPage() {
|
||||
canUndoOps={Boolean(agentUndoSnapshot)}
|
||||
onUndoOps={undoAgentOps}
|
||||
onPasteImage={pasteAssistantImage}
|
||||
agentMode={agentMode}
|
||||
onAgentModeChange={setAgentMode}
|
||||
autoConnectLocal={codexAutoConnect}
|
||||
closing={assistantClosing}
|
||||
onCollapse={closeAgent}
|
||||
|
||||
Reference in New Issue
Block a user