- 人工智能
- AI Agent
- AI 应用
- 前端
- 后端
- 即时通讯
- 交互助手
- 工具调用
【免费下载链接】holaOS
Open-source agentic workspace enterprises can make their own. Connect the systems you already run — 100+ integrations, MCP, chat tools, apps, browser, local files — with shared memory. Any agent (Claude Code, Codex), any model, or BYOK. Set up in clicks, not months. Local-first: your data never leaves your machines.
本文基于 holaOS 仓库中的规划文档 docs/plans/2026-05-24-chat-integration-ux-polish.md 展开。该文档描述了一次以用户每日高频接触面为目标的体验专项:投入约 4.5 周,打磨聊天面板(Surface A)与集成连接流程(Surface B),让 OAuth 等待不再“被遗弃”、工具失败在聊天中变成一键修复、Agent 输出具备“存在感”、集成列表不再闪烁或出现损坏 Logo。读完本文,你将掌握这套计划的完整工作分解(Phase 0 预备 + 4 个迭代周)、每一阶段的验收标准,以及它在当前仓库源码中的落点与底层依据。
背景:为什么放弃 MCP → 原生迁移,转而做 UX 打磨
计划的开端是一次架构决策的“刹车”。早期提案设想把 Composio 集成从 MCP 工具迁移为直接函数调用(direct function calls),但 PM 侧评审后得出四个结论:
- “连接了 toolkit 却无法立即使用”的痛点,已经被
composioMcpManager.restart()的管线修复,用户不再需要手动拉取; - 经由 Hono 的计费流程结构上正确,无需架构变更;
- MCP → 原生迁移中用户唯一能感知的价值,是Composio 结构化错误能传导到聊天 UI——这一小块被单独拆出来作为一次性预备任务(Phase 0);
- 其余工程收益(LOC 减少、token 节省、延迟降低)用户不可见,机会成本大于价值。
因此决策是:保留基于 MCP 的 Composio 管线,把 4.5 周投入到用户每天都在接触的两个面:聊天输出打磨(Surface A)与集成连接流程打磨(Surface B)。
目标(Goals)
- 连接流程不再让人感觉被遗弃——每个 OAuth 等待、错误与恢复路径都有清晰的视觉与操作提示;
- 工具失败在聊天中可执行——Composio 的结构化错误以可读文本 + 一键修复的形式到达用户;
- Agent 输出有“存在感”——草稿、工件(artifact)与工具完成态落地为用户想保留的东西,而不是日志条目;
- 集成列表看起来是“已加载”的——无闪烁、无损坏 Logo、无被遗弃的状态。
非目标(Non-goals)
- MCP → 原生 Composio 迁移(无限期推迟;仅当 token 成本成为 P0 时重新审视);
- 轮次内动态工具扩展(非用户诉求;工作区启动时的预注册继续工作);
- 新增 Composio toolkits / 集成(独立路线图);
- 超出错误传导预备之外的后端 / 运行时架构变更。
Phase 0 — 预备(½ 天,Week 2 之前落地)
Composio 错误传导(Week 2 的依赖)
涉及文件:
runtime/api-server/src/composio-mcp-host.ts—— 当ComposioService.executeTool返回{ ok: false, error }时,调整错误映射逻辑;runtime/api-server/src/composio-service.ts—— 确认已从 Hono 侧透出{ code, message, log_id, slug? }。
现状与变更:目前当ComposioService.executeToolreject 时,MCP host 会把错误包装成 MCP 响应上的通用internal_errorcode。变更为:
- 若 Composio 错误 code 属于
tool_failed、connection_expired、connection_not_authorized、rate_limited、not_configured、not_found之一,则作为 MCPisError: true的工具结果返回,并在 JSONcontent块中包含{ code, message, log_id, slug, retriable },使结构化错误能流入 pi 的tool_result,进而作为可读数据进入聊天的 TraceStepGroup; - 在
composio-mcp-host.test.ts中补充覆盖三个最高频 code(tool_failed、connection_expired、rate_limited)的单元测试。
验收标准:Composio 返回 401 时,聊天 UI 收到code: "connection_expired"并渲染正确的横幅;原始错误字符串保留在data.message中,供“显示技术细节”(Show technical details)折叠披露。
风险提示:下游消费者已经按模式匹配的错误语义(IntegrationErrorBanner 的正则)必须保持可用。变更前需对前 5 个高频模式的当前details字符串做快照验证。
源码佐证:错误结构已经在服务层成型
在 composio-service.ts 中可以看到ComposioExecuteError接口已经携带了code、message、slug、status、log_id、connected_account_id、user_action,并额外包含responseBody(上游返回非 JSON 错误时的截断响应体)、cfRay(Cloudflare Ray ID,用于与边缘日志关联)与originServer。ComposioToolExecutionError同时保留httpStatus与完整detail。这意味着计划中“把结构化错误透传到聊天”所需的字段在服务层早已就绪,Phase 0 的核心工作是让 MCP host 不再把它们压平为通用的internal_error。
Week 1 — 连接流程有“声音”(5 个工作日)
W1.1 — 统一取消(Cancel)操作(1 天)
涉及文件:
apps/desktop/src/components/panes/ChatPane/AssistantTurn/IntegrationProposalCard.tsxapps/desktop/src/lib/workspaceDesktop.tsx(connectIntegrationProvider轮询循环)
变更:
- 在轮询循环的返回值中加入
cancel():一个AbortController,其.abort()以code: "user_cancelled"拒绝轮询 promise; - 在 IntegrationProposalCard 的
connecting阶段暴露 Cancel 链接/按钮,视觉风格与 IntegrationConnectCard 的 Cancel 一致; - 取消时:清除
phase、隐藏 spinner、不显示错误(静默回到 idle,并重新显示淡化的 “Connect” CTA)。
验收标准:用户在 OAuth 等待期间可从 IntegrationProposalCard 按下 Cancel 并立即回到 idle;取消时不弹出 “Connection failed” toast。
源码佐证:当前的 IntegrationProposalCard.tsx 已经通过useAddApp()拿到{ add, status, cancel },且phase的推导是status.kind === "cancelled" ? "idle" : status.kind(第 69 行),说明“取消 → 静默回 idle”的语义已经存在,W1.1 的工作是把同一语义推广到轮询路径并补齐 UI。而 workspaceDesktop.tsx 中的connectIntegrationProvider已经接受signal?: AbortSignal,并通过throwIfAborted()在检测到signal.aborted时抛出IntegrationConnectCancelled——这正是计划中“以user_cancelled拒绝”的底层机制。此外,连接过程在inFlightConnectsRef中登记,聊天输入框会在点击 Connect 的瞬间禁用(第 712-721 行的注释解释了为什么必须在任何 await 之前注册,避免首个往返 ~300ms 的窗口期)。
W1.2 — OAuth 等待倒计时 + 辅助文案(1.5 天)
涉及文件:
apps/desktop/src/components/panes/ChatPane/AssistantTurn/IntegrationProposalCard.tsxapps/desktop/src/components/panes/ChatPane/AssistantTurn/IntegrationConnectCard.tsx- 新增共享子组件
OAuthWaitIndicator.tsx(置于AssistantTurn/或components/integration/)
变更:
- OAuthWaitIndicator 展示:spinner、“Waiting for {provider} authorization…”、由 elapsed/total 秒驱动的细进度条(5 分钟硬上限 = 300s)、以及弱化的倒计时(“4:32 left”);
- 经过 30 秒后,淡入辅助行:“If the window didn't open, try reopening it”,并附 “Reopen” CTA 重新唤起同一个 OAuth URL;
- 90 秒无进展后,调暗 spinner 并升级为更柔和的提示:“Still waiting — try Cancel and reconnect”。
验收标准:视觉上任何时刻都呈现“活着”的状态;用户永远不会感到被搁置。
W1.3 — 检测 OAuth 窗口被关闭(0.5 天)
涉及文件:
apps/desktop/src/lib/workspaceDesktop.tsx—— 在轮询循环中扩展window.addEventListener('focus', …)启发式:若焦点回到应用且 4 秒后仍未出现连接,则提示 “Did the authorization complete? If you closed the window without authorizing, click Reopen”。
验收标准:关闭 OAuth 窗口(未授权)时,约 5 秒内出现内联提示,而不是 5 分钟静默超时。
W1.4 — 友好的错误文案 + Retry(1 天)
涉及文件:
- 新增
apps/desktop/src/lib/integrationErrorMessages.ts—— 纯映射函数(code, slug?) => { headline, detail, action: "retry" | "reconnect" | "contact" }; IntegrationProposalCard.tsx+IntegrationConnectCard.tsx—— 消费该映射函数,渲染绑定到 action 枚举的 Retry/Reconnect 按钮。
初始覆盖的 code 集合:
| code | 文案 | action |
|---|---|---|
user_cancelled | 静默(无错误 UI) | — |
connection_expired | “Your {provider} session expired” | Reconnect |
connection_not_authorized | “{provider} hasn't been authorized yet” | Reconnect |
rate_limited | “{provider} is busy — try again in a minute” | Retry |
network_error | “Couldn't reach {provider}” | Retry |
popup_blocked | “Allow popups for the desktop app, then click Reopen” | Reopen |
unknown | “Something went wrong” | Retry + “Show details” 中披露原始data.message |
验收标准:用户永远不会看到原始异常字符串;所有路径都有 Retry/Reconnect/Reopen 动作。
W1.5 — 打磨 + QA(1 天)
- 三张卡片的深色 + 浅色模式一致性巡检;
- 减少动效(reduced-motion):倒计时仍工作,只是 spinner/进度条不做动画;
- 为新的映射函数补充快照测试(
integrationErrorMessages.test.ts)。
Week 1 发布目标:不放在 feature flag 后面——这些都是纯 UI 改进,随版本一起发布。
Week 2 — 错误变成一键修复(5 天)
依赖 Phase 0(Composio 错误传导)。
W2.1 — 扩展 IntegrationErrorBanner 的模式匹配(1.5 天)
涉及文件:
apps/desktop/src/components/panes/ChatPane/skeletons.tsx(IntegrationErrorBanner 函数);- 新增
apps/desktop/src/lib/integrationErrorBannerMap.ts—— 持有(code | slug | message-regex) → banner-config的映射。
变更:
- 把内联正则的模式匹配迁移到集中式映射;
- 覆盖集成商店目录(
integration-store-catalog.ts)中的每个 toolkit; - 每个条目包含:icon、headline、detail、action(
"reconnect" | "retry" | "open_settings")以及目标connection_id(用于内联重连)。
验收标准:目录内 100% 的 toolkit 失败命中带类型的 banner;只有真正未知的错误才落到 “Show technical details”。
源码佐证:当前 skeletons.tsx 中IntegrationErrorBanner已经优先使用带类型、可操作文案 + 内联重连的IntegrationErrorBannerBody,解析失败时回退到GenericToolFailureBanner。IntegrationErrorBannerBody(第 141 行起)通过resolveIntegrationError解析{ headline, detail, action },且copy.action === "silent"时直接返回 null(第 189 行)——这与 W1.4 中user_cancelled静默的语义一致。重连成功后还会调用rebindWorkspaceAppsForProvider把工作区中绑定到旧 connection 的应用重新绑定(第 160-175 行的注释解释了原因:OAuth 成功只修复 Agent 直连路径,工作区应用的HOLABOSS_APP_GRANT仍指向过期连接,必须显式 rebind)。
W2.2 — 内联重连迷你卡片(2 天)
涉及文件:
- 新增
apps/desktop/src/components/panes/ChatPane/AssistantTurn/InlineReconnectCard.tsx; - banner action 为
"reconnect"时,在失败的 TraceStepGroup 正下方渲染迷你卡片; - 复用 Week 1 的 OAuth 等待机制(倒计时、取消、错误映射),通过共享的 OAuthWaitIndicator。
验收标准:工具以connection_expired失败 → 出现 banner → 点击 “Reconnect” → OAuth 流程内联进行 → 成功后提示 “Retry the original tool call” → Agent 自动重试(带限流保护)。
W2.3 — 通用工具失败外壳(1 天)
涉及文件:
apps/desktop/src/components/panes/ChatPane/AssistantTurn/TraceStepGroup.tsx;- 新增
apps/desktop/src/components/panes/ChatPane/AssistantTurn/ToolFailureShell.tsx。
变更:
- 当
step.status === 'error'且没有 IntegrationErrorBanner 模式命中时,渲染 ToolFailureShell 而不是倾倒原始 JSON; - 外壳展示:一行摘要(“Tool {name} failed”)、错误消息(截断为一行,完整文本放在
<details>中)、以及 “Show technical details” 开关,展开后显示原始 JSON payload。
验收标准:折叠的步骤详情中不再出现原始 JSON 墙——即使是未知错误看起来也是有意的设计。
W2.4 — 打磨 + QA(0.5 天)
- E2E 走查:在 e2e 脚本中模拟 token 过期的工具失败,确认 banner → reconnect → retry 全路径可用。
Week 3 — 输出有“存在感”(5 天)
W3.1 — 工件类型分类体系 + 管线(1.5 天)
涉及文件:
runtime/state-store/src/store.ts—— 确认artifacts表已有type字段(若无则加迁移);runtime/api-server/src/runtime-agent-tools.ts—— Agent 产生工件时传递type(draft_post | draft_email | draft_image | dashboard | report | other);apps/desktop/src/types/electron.d.ts—— 在 artifact 事件中透出 type。
验收标准:Agent 创建的每个新工件都携带类型化枚举;遗留工件默认归为other。
W3.2 — 工件卡片重设计(2 天)
涉及文件:
apps/desktop/src/components/panes/ChatPane/AssistantTurn/Outputs.tsx;- 新增
apps/desktop/src/components/panes/ChatPane/AssistantTurn/ArtifactCard.tsx(每卡片一个,取代当前的<li>)。
变更:
- 按类型显示图标(Lucide:草稿用 FileText、邮件草稿用 Mail、图片草稿用 Image、仪表盘用 LayoutDashboard、报告用 FileBarChart);
- 默认标题规则:标题缺失时用
{type} #{n}—— “Twitter draft #2”、“Email draft #1”; - 1 行预览(正文前 60 字符,图片用 alt 文本);
- 悬停态:微弱的背景偏移 + 1px 边框高亮(按设计规范不抬升阴影);
- 点击 → 进入现有的 ArtifactBrowserModal。
源码佐证:当前 Outputs.tsx 已引入ChevronDown图标,并在第 100-189 行附近实现了多工件分享(一个 turn 产生 ≥2 个可分享工件时让用户选择、单一工件时走快速分享通道),且第 243 行注释说明纯构建型 turn 不显示输出区。这为 ArtifactCard 的接入提供了清晰的插入点。
W3.3 — “Show more” 操作提升(0.5 天)
涉及文件:
Outputs.tsx。
变更:
- 从 xs 弱化的 “Show 2 more” 改为全宽 “+2 more artifacts” 按钮,带图标(ChevronDown)与 Cmd+Shift+A 键盘提示;
- 阈值仍为 3(避免卡片墙)。
W3.4 — 工具完成微动画(0.5 天)
涉及文件:
apps/desktop/src/components/panes/ChatPane/AssistantTurn/TraceStepGroup.tsx;- 通过 Tailwind 工具类实现 CSS——在全局样式表中定义
@keyframes draw-check(若已安装 motion 库则使用之,否则懒加载)。
变更:
- 步骤从
running→success时,为对勾图标做动画:SVG path 的 stroke-dasharray 在 200ms 内绘制完成。尊重prefers-reduced-motion: reduce。
W3.5 — QA(0.5 天)
- 所有工件类型的浅色 + 深色模式;
- 压力测试:单 turn 10 个工件——折叠后的 “+7 more” 依然可读。
Week 3 设计师介入:计划确认设计师参与,具体触点:ArtifactCard 视觉处理(字体排版、间距、悬停)、”Show more” 操作的比例、Week 4 的 Provider Logo 处理。脚手架代码与桩视觉选择遵循现有设计系统(OKLch token、Inter/Newsreader 字体、0-3 级阴影),设计评审可在合并前精修。
Week 4 — 列表感觉“已加载”(4 天 + ½ 缓冲)
W4.1 — 骨架屏(1.5 天)
涉及文件:
- 新增
apps/desktop/src/components/panes/IntegrationsPane.skeleton.tsx; - 新增
apps/desktop/src/components/panes/AddIntegrationDialog.skeleton.tsx; MarketplacePane.tsx—— 为connect_integrations标签页做骨架。
变更:
- 与真实行高匹配的 pulse-bg 骨架行,渲染到
listIntegrationConnections与 toolkit 目录都解析完成。
W4.2 — 打包英雄 Logo(1.5 天)
涉及文件:
- 新目录
apps/desktop/src/assets/integration-logos/,为 Top 20 toolkits 提供 SVG(gmail、twitter、linkedin、reddit、github、slack、notion、hubspot、salesforce、gcal、gdrive、dropbox、figma、asana、jira、intercom、zendesk、stripe、airtable、calendly); - 新增
apps/desktop/src/lib/integrationLogo.ts——getIntegrationLogo(slug): { src: string; isLocal: boolean }。已知 slug 返回打包资源,否则回退到 Composio CDN URL; - 替换 IntegrationsPane、AddIntegrationDialog、IntegrationProposalCard、IntegrationConnectCard、MarketplacePane 中直接使用
<img src={composioLogoUrl}>的写法。
验收标准:Top 20 toolkit Logo 始终正确渲染(无白底白字 SVG、无破损宽高比);长尾 toolkit 仍从 CDN 加载。
W4.3 — 跨界面状态词汇审计(1 天)
涉及文件(审计 + 修复):
- IntegrationProposalCard、IntegrationConnectCard、IntegrationsPane 行、AddIntegrationDialog 条目、MarketplacePane provider 行。
变更:
- 在
apps/desktop/src/lib/integrationStateStyles.ts中定义规范的视觉词汇:idle:弱化的 secondary 色 + 插头图标;loading:骨架;connecting:spinner + 倒计时 + 取消;success:对勾图标 + green-50 背景(或 oklch 等价色)持续 2s,然后回 idle;error:AlertTriangle 图标 + red-50 背景 + Retry CTA;
- 在全部 5 个界面一致应用。
W4.4 — 缓冲 + QA + 演示(0.5 天)
- 端到端走查视频;
- 更新
backend/docs/work_log.md与docs/work-log.md(holaOS 本地)记录本周变更。
验收标准——何时算完成
- 用户可以从任意入口以一致的 UI 取消 OAuth;
- OAuth 等待超过 30s 时必有可见的安抚提示;
- 用户看不到任何原始错误消息;所有错误都有 Retry/Reconnect/Reopen 动作;
- token 过期的工具失败 → 用户可内联重连 → 原始工具自动重试;
- 目录内所有 toolkit 失败都通过 IntegrationErrorBanner 渲染(已知 toolkit 无原始 JSON 回退);
- 工件有类型图标与有信息量的默认标题;正常流程中不再出现 “Untitled artifact”;
- 工具完成有一个瞬间(200ms 动画)再过渡到摘要;
- 任何地方都没有无骨架的列表闪烁;
- Top 20 toolkit Logo 始终正确渲染;
- 所有变更在浅色/深色模式下一致;尊重 reduced-motion。
明确超出范围(Out of scope)
- 新手引导(onboarding)重设计(独立路线图);
- 工作区控制中心打磨;
- Module app UI lint 强制执行(已在 8453030d 提交中交付);
- 聊天输入区重设计;
- 记忆面板 / 工件浏览器模态框重设计。
未决问题 / 依赖
- Q1:设计师能否在 W3.2 实现前评审 ArtifactCard 原型?计划默认可以。
- Q2:进行中的
feat/integration-store-unified合并是否会改变 IntegrationProposalCard 的 props 结构?若是,本分支需在 W1 落地前 rebase。缓解措施:保持改动小而命名良好,使 rebase 机械化。 - Q3:Composio webhook 处理器(
composio.ts:1799)在connection_expired时已使 session 缓存失效。需确认该路径是否触发运行时的composioMcpManager.restart(或聊天只会在下一次工具调用时看到失败)。这影响 W2.2 是否需要订阅 webhook 事件以主动提示重连。(默认:不在本计划范围内;被动流程已足够。)
Rebase 策略
feat/integration-store-unified正在合并中。本分支从干净 HEAD 275e8d45 分出。合并完成并进入 main 后:
git fetch origin main;- 在本分支上
git rebase origin/main; - 冲突将集中在 IntegrationProposalCard 及相关 ChatPane 文件——解决时保留本计划的 UX 工作(取消按钮、倒计时、错误映射),保留合并工作(integration-store-unified 团队新增的内容);
- 推送前在工作树中重新运行 lint 与测试。
阅读建议:如何在仓库中继续深入
- 计划源头:docs/plans/2026-05-24-chat-integration-ux-polish.md;
- 聊天侧三张卡片的现状:IntegrationProposalCard.tsx、IntegrationConnectCard.tsx、skeletons.tsx;
- 连接轮询与取消机制的底层:workspaceDesktop.tsx;
- 错误结构化与服务层字段:composio-service.ts;
- 工件输出区现状:Outputs.tsx。
需要注意的是:计划中提到的个别文件路径(如runtime/api-server/src/composio-mcp-host.ts)在本文写作时的仓库快照中尚未出现或已更名,实施时应以实际分支状态为准;计划本身也明确标注了 “In progress” 状态与 rebase 依赖。本文所有源码引用均可在当前仓库对应路径中直接查阅。
- 人工智能
- AI Agent
- AI 应用
- 前端
- 后端
- 即时通讯
- 交互助手
- 工具调用
【免费下载链接】holaOS
Open-source agentic workspace enterprises can make their own. Connect the systems you already run — 100+ integrations, MCP, chat tools, apps, browser, local files — with shared memory. Any agent (Claude Code, Codex), any model, or BYOK. Set up in clicks, not months. Local-first: your data never leaves your machines.
相关推荐
improve 交接计划模板全解:为低成本执行模型编写可执行的代码库实施计划
improve 交接计划模板全解:为低成本执行模型编写可执行的代码库实施计划 导读 :本文深入拆解 Agent 技能 improve 的核心交付物——交接计划模
SuperClaude Framework 的 /sc:workflow 实现工作流生成器:从 PRD 到可执行实施计划的编排实践
SuperClaude Framework 的 /sc:workflow 实现工作流生成器:从 PRD 到可执行实施计划的编排实践 导读 /sc:workflo
开发工具CLIAI 技能/插件测试人工智能AI 评测CrewAI 任务如何启用 reasoning 让 Agent 执行前先生成并打磨计划
CrewAI 任务如何启用 reasoning 让 Agent 执行前先生成并打磨计划 在 CrewAI 中运行一个复杂 Task 时,Agent 有时会直接开
人工智能AI AgentAgent 框架多智能体工作流自动化后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考