news 2026/10/2 1:55:18

holaOS Chat 与集成 UX 打磨:从 OAuth 连接到错误可执行的 4.5 周实施计划

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
holaOS Chat 与集成 UX 打磨:从 OAuth 连接到错误可执行的 4.5 周实施计划
  • 人工智能
  • 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.

项目地址:https://gitcode.com/GitHub_Trending/ho/holaOS
点击查看免费下载

本文基于 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)

  1. 连接流程不再让人感觉被遗弃——每个 OAuth 等待、错误与恢复路径都有清晰的视觉与操作提示;
  2. 工具失败在聊天中可执行——Composio 的结构化错误以可读文本 + 一键修复的形式到达用户;
  3. Agent 输出有“存在感”——草稿、工件(artifact)与工具完成态落地为用户想保留的东西,而不是日志条目;
  4. 集成列表看起来是“已加载”的——无闪烁、无损坏 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.tsx
  • apps/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.tsx
  • apps/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 后:

  1. git fetch origin main;
  2. 在本分支上git rebase origin/main;
  3. 冲突将集中在 IntegrationProposalCard 及相关 ChatPane 文件——解决时保留本计划的 UX 工作(取消按钮、倒计时、错误映射),保留合并工作(integration-store-unified 团队新增的内容);
  4. 推送前在工作树中重新运行 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.

项目地址:https://gitcode.com/GitHub_Trending/ho/holaOS
点击查看免费下载

相关推荐

上一篇:electerm 扩展功能完整指南:从启动 Widget 到远程监控,一文走通全流程
下一篇:JavaScript状态机终极指南:Node.js后端开发的完整实践方案

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 1:55:10

Win10产品密钥查找原理与安全提取实战指南

1. 项目概述&#xff1a;为什么Win10产品密钥查找这件事&#xff0c;比你想象中更值得深挖Win10怎么查找产品密钥&#xff1f;这个问题看似简单&#xff0c;但背后藏着Windows激活机制、系统安全边界、硬件绑定逻辑和用户数据主权的多重博弈。我做系统部署和企业IT支持十多年&a…

作者头像 李华
网站建设 2026/10/2 1:54:56

基于C#与MySQL的仓库管理系统实战:从建库到入库单落地的完整路径

简介&#xff1a;这份资源是一套基于C#与MySQL数据库开发的仓库管理系统完整项目包&#xff0c;面向学习C#面向对象编程、数据库设计及企业级应用开发的学生与开发者&#xff0c;可用于课程设计、毕业设计或自学实践。压缩包共163个文件&#xff0c;约1.22MB&#xff0c;以49个…

作者头像 李华
网站建设 2026/10/2 1:54:16

AppsFlyer S2S事件上报实战:参数获取、避坑指南与Firebase选型对比

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华