diff --git a/CHANGELOG.md b/CHANGELOG.md index 99504d2..cd6e179 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased ++ [优化] Agent 首次发送消息时立即清空输入框并展示用户消息,避免等待线程创建期间出现输入内容滞留和后续草稿被清空。 + [优化] Agent 动态工具卡片显示具体工具名称、准确执行状态和失败原因,避免统一显示为含糊的「工具操作」。 + [修复] 画布 Agent 默认通过画布节点生成内容,仅在用户明确指定时使用 Codex 内置生图并将结果展示到对话和当前画布。 + [优化] Agent 面板标题、功能标签与新对话操作合并为单行顶部栏,减少面板空间占用。 diff --git a/docs/content/docs/progress/pending-test.mdx b/docs/content/docs/progress/pending-test.mdx index 145376a..7304540 100644 --- a/docs/content/docs/progress/pending-test.mdx +++ b/docs/content/docs/progress/pending-test.mdx @@ -5,6 +5,7 @@ description: 当前版本已实现但仍需人工验证的变更项 # 待测试 +- Agent 首次发送响应:在空白新对话中输入内容并按回车后,输入框应立即清空、用户消息应立即出现在对话中,再显示「正在思考」;线程创建或发送失败时,原输入和附件应恢复;任务运行期间输入的新草稿不应在请求成功后被清空。 - Agent 动态工具信息:执行内置生图、查看图片、命令、文件修改或其他动态工具时,卡片标题应显示具体工具名称;执行失败时正文应显示真实错误原因,刷新并恢复历史对话后仍应保持一致,不再统一显示「工具操作已完成」。 - Agent 画布生图:重启 Canvas Agent 后,其自动生成的工作区 `AGENTS.md` 应同步为最新版指令(用户自行编写的其他 `AGENTS.md` 不应被覆盖);输入“生成一张图片”时应调用 `canvas_generate_image`,通过当前画布节点创建并运行生成流程;只有明确输入“使用 Codex 内置生图/ImageGen 技能生成”时才允许调用内置能力,Codex App Server 返回的 `imageGeneration` 结果应显示在对话中并作为保持原比例的图片节点添加到当前画布;Agent 不应在没有生成结果时提前声称“已生成”。 - Agent 顶部栏:标题只显示垂直居中的「Agent」,连接、对话、历史、日志、新对话和收起操作应位于同一行;面板较窄时标签仍可横向滚动且操作不应错位。 diff --git a/web/src/components/agent/local-agent-panel.tsx b/web/src/components/agent/local-agent-panel.tsx index 3747e69..fe46d51 100644 --- a/web/src/components/agent/local-agent-panel.tsx +++ b/web/src/components/agent/local-agent-panel.tsx @@ -298,18 +298,18 @@ export function LocalAgentPanel({ embedded, headless, autoConnect }: { embedded? addMessage({ role: "error", title: "图片过大", text: "图片附件超过 30MB,请删减后再发送。" }); return; } - setAgentState({ activity: "发送中", sending: true }); const messageId = createId(); const userText = text || `发送了 ${files.length} 张图片`; + setAgentState({ prompt: "", attachments: [], activity: "发送中", sending: true }); + addMessage({ id: messageId, role: "user", text: userText, historyText: requestPrompt, attachments: files }); let threadId = useAgentStore.getState().activeThreadId; try { if (!threadId) { const created = await fetchAgentJson(endpoint, token, "/agent/codex/threads/new", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ permissionMode }) }); threadId = created.thread?.id || created.workspace?.activeThreadId || ""; if (!threadId) throw new Error("新建对话失败"); - setAgentState({ activeThreadId: threadId, messages: [], tokenUsage: null }); + setAgentState({ activeThreadId: threadId, tokenUsage: null }); } - addMessage({ id: messageId, role: "user", text: userText, historyText: requestPrompt, attachments: files }); if (files.length) void saveAgentUserMessage(threadId, { id: messageId, role: "user", text: userText, historyText: requestPrompt, attachments: files }).catch(() => undefined); addEventLog("发送任务", `${compactText(text) || "仅附件"}${files.length ? ` · 附件 ${files.length}` : ""}`); const data = await fetchAgentJson<{ threadId?: string }>(endpoint, token, "/agent/codex/turn", { @@ -330,11 +330,15 @@ export function LocalAgentPanel({ embedded, headless, autoConnect }: { embedded? URL.revokeObjectURL(item.url); attachmentUrlsRef.current.delete(item.url); }); - setAgentState({ prompt: "", attachments: [], sending: false, waiting: true, activity: "Codex 正在运行" }); + setAgentState({ sending: false, waiting: true, activity: "Codex 正在运行" }); } catch (error) { const text = error instanceof Error ? error.message : "发送失败"; const busy = text.includes("Codex 正在运行"); - setAgentState({ activity: busy ? "Codex 正在运行" : "发送失败" }); + const state = useAgentStore.getState(); + setAgentState({ + activity: busy ? "Codex 正在运行" : "发送失败", + ...(state.prompt || state.attachments.length ? {} : { prompt, attachments: files }), + }); addMessage({ role: "error", title: busy ? "任务仍在运行" : "发送失败", text }); addEventLog("发送失败", error); } finally {