
DeepChat Agent 浏览器原生画中画迁移指南基于 NativeKit 0.6.3 的主进程浮层面板架构【免费下载链接】deepchatDeepChat - A smart assistant that connects powerful AI to your personal world项目地址: https://gitcode.com/GitHub_Trending/dee/deepchatDeepChat 在 Agent 操控后台浏览器时需要为用户提供一个可拖动、只读、不抢占聊天渲染的实时预览。本文将完整讲解 DeepChat 将这一画中画PiP能力从渲染进程 Canvas 实现迁移到 Electron 主进程 zerob13/nativekit 原生浮层的完整架构设计从依赖演进史、NativeKit 0.6.3 的 API 契约与运行时能力矩阵到表面选择Surface Selection、帧投递、生命周期矩阵、性能验收口径、打包校验与失败语义。读完本文你将掌握如何在一个 Electron 应用中安全地接入进程级原生叠加层理解原生拖动 有界快照流这一诚实的能力边界并能直接对照 DeepChat 仓库中的实现与测试进行验证。本文对应的架构规格位于 docs/architecture/nativekit-agent-browser-pip/spec.md其用户侧契约与面板移交语义见 docs/features/agent-browser-pip/spec.md与 Computer Use 快照 PiP 的共享协调见 docs/features/computer-use-snapshot-pip/spec.md。1. 迁移背景与状态1.1 为什么需要迁移在旧实现中Agent 浏览器预览是一张渲染进聊天界面的 Vue 卡片由AgentBrowserPiP.vue挂载在ChatTabView.vue中。每帧画面都要经历页面捕获 → 缩放 → 编码 → 跨进程投递 → 结构化克隆 →createImageBitmap→ Canvas 绘制 → Vue DOM 布局的完整链路。问题不在于后台页面或capturePage()本身而在于链路的后半段每一帧都要跨入聊天 renderer与对话渲染、滚动竞争资源renderer 每帧都要分配并解码一个新的图像对象Canvas 替换参与了聊天 renderer 的 paint/compositing 工作指针拖动通过 Vue 状态与布局完成产生大量布局抖动PiP 随应用内容区域消失且无法使用原生工作区work area边界钳制。正确的归属层是Electron 主进程 NativeKit由操作系统原生栈AppKit / Win32 / XCB直接拥有窗口移动、工作区钳制、z-order 与面板控件renderer 只负责资格协调与原生能力不可用时的Browser 侧面板移交。1.2 依赖演进与版本锁定迁移的最终落点是把 zerob13/nativekit 精确锁定在0.6.3。从 0.5.1 到 0.6.3 的演进史本身就是一个典型的原生模块跨平台发布案例版本变更要点0.5.1发布的 macOS arm64/x64 二进制声明的最低部署目标为 macOS 15.00.5.2修正两个 macOS 预编译产物为 macOS 12.0与 DeepChat / Electron 40 的 Monterey 下限一致API 与架构矩阵不变0.5.3修复 macOS 手动放置在 AppKit 异步原生拖动开始后记录NSWindowDidMove图片刷新不再恢复锚点0.5.4增加xwayland-satellite下的宿主内嵌拖动仍是五个预编译产物、macOS 12.0 下限0.5.5纯打包发布把所有 N-API 二进制从nativekit.napi.node改名为node.napi.node修复了 x64 查找但electron/rebuild把 arm64 映射到armv8预编译标签macOS/Linux arm64 仍回退到源码编译0.5.6修正 arm64 包名为node.napi.armv8.nodex64 保留node.napi.node并用仅预编译的node-gyp-build解析验证每个 CI 产物0.6.0用最多两个调用方配置控件取代固定的隐藏/重定位控件根级面板改为按显示器工作区而非宿主边界定位0.6.1增加固定样式自定义工具栏DeepChat 提供透明 PNG 模板图open-panel 与 close 按钮几何、明暗、hover、按压反馈、缩放与对比度由 NativeKit 平台原生负责0.6.2修复 AppKit 忽略NSButton.bezelColor导致的 macOS 工具栏背景问题改为绘制样式感知的图层背景与边框0.6.3Windows x64 预编译产物静态链接 MSVC 运行时加载不再依赖单独安装的动态运行库仓库中 package.json 的dependencies明确写着zerob13/nativekit: 0.6.3无^或~与规格中精确版本的要求一致。npm registry 对 0.6.3 声明了 Electron28.0.0与 Node18的兼容范围DeepChat 当前所用的 Electron 41见 package.jsondevDependencies位于其声明范围内。1.3 与 Computer Use 快照 PiP 的关系2026-07-28 起Computer Use 最新快照 PiP 落地AgentPreviewCoordinator现在持有进程级的 NativeKit 生命周期仲裁 Browser 与 Computer Use 的同一时刻仅一个展示。Browser 保留页面、捕获、面板移交与Open in panel/Close行为Computer Use 只贡献有界的最近快照与Close。2. 反方观点Counterpoint诚实的能力边界规格文档专门用一节澄清 NativeKit 迁移到底保证了什么、没有保证什么已确认面板拖动是原生的、流畅的面板可以完全脱离 DeepChat 窗口。被评审的实现直接把原生窗口放进 AppKit / Win32 / XCB拖动采样不经过 renderer 状态或 IPC。未承诺远程页面的内容刷新率并不因此变成视频级。NativeKit 0.6.3 仍然通过同步的overlay.pushImage()接收完整 PNG/JPEG data URL原生解码每张图不提供共享纹理、原始缓冲流、局部更新或动画 API。因此这次迁移的对外表述是原生移动 有界快照流native movement with a bounded snapshot stream而不是60 FPS 浏览器视频。这一边界贯穿后续的性能验收口径。3. 现状工程简报与热路径3.1 目标与当前归属项现状用户可见行为不强制打开 Browser 面板即展示只读 Agent 浏览器预览用户可移动或关闭它而不打断 Agent当前 renderer 归属AgentBrowserPiP.vue由ChatTabView.vue挂载当前主进程归属YoBrowserPresenter触发路径renderer 会话、侧面板与窗口状态推导出capturing | rendering | stopped再调用browser.setPreviewMode既有原生页面一个WebContentsView面板关闭时被重新挂到 1280 x 800 的透明离屏BaseWindow中3.2 迁移前的热路径Agent WebContentsView at 1280 x 800 - webContents.capturePage() - NativeImage.resize(400 x 250) - JPEG quality 72 Buffer - typed main-to-renderer event - structured clone / Uint8Array - Blob - createImageBitmap() - Canvas resize drawImage() - Vue DOM card, toolbar, halo, and pointer dragBrowser 预览的调度策略是活跃捕获完成后 500 ms 排下一次捕获空闲捕获完成后 2000 ms 排下一次即捕获成本之前的上限约 2 FPS 与 0.5 FPS同一时刻只有一次捕获在途帧不会排队。规格明确提醒这些运行时调度设置并不代表下方首帧、帧龄、高刷新率验收预算已经达标——它们是现状而非证据。3.3 诊断结论开销与脆弱性不在于后台页面或capturePage()而在于链路后半段renderer 解码、Canvas 参与合成、Vue 拖动布局、随应用内容区域消失、无法原生钳制。正确的浮面归属层是主进程 NativeKitrenderer 只保留资格协调与原生不可用时的侧面板移交两项职责。4. 用户需求与目标 / 非目标用户需要一个满足以下条件的预览直接原生输入移动而非 renderer 指针事件不与聊天渲染和滚动竞争保持同一个活跃 Agent 页面与 CDP 目标只读、不向远程页面转发输入在用户主动激活时打开既有 Browser 面板只关闭当前 run 的预览在 NativeKit 0.6.3 无法提供浮层的平台上安全降级。4.1 核心目标精确使用zerob13/nativekit0.6.3在其支持的运行时矩阵上NativeKit 成为首选 PiP 表面PiP 可拖到当前显示器工作区内的任意位置包括完全离开 DeepChat 窗口保留既有 1280 x 800 无焦点渲染宿主与同一个页面WebContentsView已完成的 JPEG 帧由YoBrowserPresenter直接送 NativeKit原生路径不做 renderer 帧投递拖动、工作区钳制、z-order、原生面板控件全部交给 AppKit / Win32 / XCB保持单捕获在途、epoch/run 校验、末帧有效保留、图像尺寸有界NativeKit 不进应用启动路径只在出现具体 PiP 请求时加载NativeKit 不可用时打开既有侧面板 Browser抑制 Computer Use PiP两个 Agent 工具都不受影响会话过期、面板可见性、宿主 blur/hide/minimize、run 终结、页面销毁、应用退出时同步隐藏原生面板增加打包校验确保受支持的目标构建不会静默遗漏.node预编译产物迁移完成前必须实测拖动行为、首帧延迟、帧新鲜度与同步原生解码成本。4.2 非目标明确不做全帧率视频、共享纹理、WebRTC 或 GPU 表面共享PiP 内远程页面交互把活体WebContentsView放进原生浮层维护下游 NativeKit fork 或安装期二进制改名在原生面板上方再造第二个透明 Vue 工具栏窗口强制所有 Linux 用户以--ozone-platformx11启动多个同时可见的 PiP 面板跨应用重启持久化面板位置原 SDD 中推迟的多标签 / Fit-desktop 工作围绕单一 NativeKit 消费方搭建通用原生能力框架。5. NativeKit 0.6.3 契约5.1 有效 API 与 DeepChat 用途APIDeepChat 用途overlay.start({ toolbar })配置高对比深色工具栏Open in panel在前Close在后overlay.attachHost()按 content bounds 与原生句柄绑定一个聊天BrowserWindowoverlay.setMaxSize(360)把 400 x 250 的源画面渲染为 360 x 225 DIP 面板overlay.pushImage()创建或替换当前 Agent 浏览器 JPEGoverlay.setActiveSession()显示前先把当前逻辑 Agent 会话置为第一overlay.setVisible()临时不合规时隐藏而不删除当前展示overlay.removeImage()清除终结的、销毁的或被替换的展示overlay.detachHost()释放已关闭的聊天窗口overlay.stop()presenter 关闭时释放全部原生资源activate双击意图聚焦 DeepChat 并打开既有 Browser 面板control配置的控件 ID映射到 open-panel 或当前 run 的关闭suppressSessions、completeSession、应用图标查找与系统窗口查询在此迁移中不需要——同一时刻一个 PiP、一个当前目标使其成为冗余。5.2 运行时特征仅主进程使用绝不能被 renderer 或 preload 导入Node-API v8 预编译DeepChat 所用 Electron 版本在声明的 peer 范围内pushImage()接受PNG/JPEG base64 data URL而非BufferJavaScript 边界上的调用全部是同步的macOS 在主线程解码并更新NSPanelWindows 将更新同步编组到其 STA 浮层线程经 WIC 解码后用UpdateLayeredWindow呈现Linux 同步更新其专用 XCB 浮层线程经 GdkPixbuf 解码拖动完全留在平台实现内部不产生任何 renderermousemoveIPC移动与过渡即时生效0.6.3 无动画 API原生control事件携带调用方定义的 ID但不携带展示 ID——只有当 DeepChat 强制单可见 PiP不变式时才安全。5.3 已发布的运行时能力矩阵运行时首选表面原因macOS arm64/x64原生浮层已发布预编译非激活NSPanelWindows x64原生浮层已发布预编译自有的 layered topmostHWNDWindows arm64Browser 侧面板无 Computer Use PiPNativeKit 0.6.3 未发布 win32-arm64 预编译Linux x64/arm64X11 / 集成 XWayland原生浮层已发布预编译与全局 XCB 窗口模型Linux x64/arm64xwayland-satellite原生浮层0.5.4 起 XCB 面板内嵌于 Electron 宿主拖动被钳制在宿主边界内Linux 原生 WaylandBrowser 侧面板无 Computer Use PiP无全局定位、无兼容的 X11 窗口句柄缺失/损坏 addon 或原生启动失败Browser 侧面板无 Computer Use PiP应用启动与 Agent 工具保持可用DeepChat不会为了启用 PiP 而改变用户的 Linux 显示后端。这一点与 AgentPreviewCoordinator.ts 中isPublishedTarget()的实现完全一致它只对darwin:arm64、darwin:x64、win32:x64、linux:arm64、linux:x64五个组合放行。6. 目标架构与归属one live page / one CDP target | v focusless render-host BaseWindow - Agent WebContentsView at 1280 x 800 | v capturePage (one in flight) | v resize 400 x 250 / JPEG 72 | -------------------------------------- | | native capability native unavailable | | v ---------------- JPEG Buffer - base64 data URL | | | v v v Browser activate event Computer Use zerob13/nativekit overlay - existing side panel no PiP | AppKit / Win32 / XCB panel6.1 三方归属划分YoBrowserPresenter见 src/main/desktop/browser/YoBrowserPresenter.ts仍是页面、run、渲染宿主、捕获 epoch 与预览模式的权威校验发送方的BrowserWindow与当前 Agent run按原生能力选择native-overlay或none原生能力不可用时请求既有 Browser 侧面板把完成帧分叉到恰好一个表面在每个既有生命周期边界上停止捕获并清理表面。AgentPreviewCoordinator进程级、聚焦的协调器见 src/main/desktop/preview/AgentPreviewCoordinator.ts只负责动态包加载与一次性能力探测overlay.start()/stop()生命周期一个活跃宿主与一个活跃展示Browser 与 Computer Use 工具栏配置切换源码中toolbarOptions(source)按source browser决定按钮组Browser 为 open-panel closeComputer Use 仅 close见OPEN_PANEL_CONTROL_ID/CLOSE_CONTROL_ID常量最新显式源声明claim与共享的 run 级关闭宿主 move/resize/close 同步JPEGBuffer→ data URL 转换present()内data:image/jpeg;base64,${jpeg.toString(base64)}显示前预绘帧prepaint-before-show排序把 NativeKit 的 activate 与配置控件映射到当前源特定的处理器同步原生调用周围的计时计数器recordPushDuration25 ms 慢推送告警阈值、60 s 限频。RendererAgentBrowserPiP.vue保留当前会话 / 面板 / run / 窗口资格推导既有setPreviewMode请求合并处理 open-panel 与 run 关闭的类型化原生动作。在native-overlay下它不渲染任何 PiD DOM、不接收任何帧字节原生能力失败时同一类型化激活路径打开 Browser 侧面板。6.2 协调器源码要点从 AgentPreviewCoordinator.ts 的实现可以看到几个关键常量与设计PREVIEW_MAX_EDGE 360原生面板最大边长HOST_ANCHOR_OFFSET 16、HOST_SYNC_DELAY_MS 50宿主锚点偏移与去抖后的宿主同步延迟SLOW_PUSH_WARNING_MS 25/SLOW_PUSH_WARNING_INTERVAL_MS 60_000同步pushImage()耗时告警阈值与限频attachHost()使用真实BrowserWindow.getNativeWindowHandle()与getContentBounds()锚定edge: trailingstart()中动态import(zerob13/nativekit)依次调用overlay.start(toolbarOptions(browser))、overlay.setMaxSize(360)、overlay.setVisible(false)保持全局隐藏并监听activate/control事件展示身份函数hostId chat-window:windowIdpresentationId agent-preview:source:windowId:sessionIdnativeSessionId agent-preview:source:sessionId宿主事件绑定覆盖 focus / blur / show / hide / minimize / restore / move / resize / closed配合screen的 display-added / removed / metrics-changed 监听shutdown()幂等清理清空 claims / dismissedRuns / handlers置unavailable true并stopNative()。7. 表面选择契约Surface Selectionbrowser.setPreviewMode的返回值类型YoBrowserPresenter.setPreviewMode在 src/main/desktop/browser/YoBrowserPresenter.ts 中实现并返回该结构type BrowserPreviewSurface native-overlay | renderer-canvas | none type BrowserPreviewModeResult { updated: boolean surface: BrowserPreviewSurface }选择过程在按需 NativeKit 初始化后进程级稳定不从应用启动、Browser 后台渲染或 Computer Use 资格判断中导入 NativeKit在第一次具体 Browser 捕获或 Computer Use 目标出现时动态导入zerob13/nativekit启动浮层并保持全局隐藏在第一个合格宿主上用真实BrowserWindow.getNativeWindowHandle()验证attachHost()两步都成功则使用native-overlay否则记录一次脱敏能力告警本进程内保持能力禁用打开既有侧面板 Browser且不暴露 Computer Use PiP。瞬时坏帧不切换表面NativeKit 保留上一个有效展示下一次有界捕获重试。另外renderer-canvas表面值及其组件对既有调用方仍然可用但原生能力失败不再自动选择它作为产品回退——唯一的产品回退是既有 Browser 侧面板。8. 原生展示身份与帧投递8.1 单展示身份模型hostId chat-window:windowId presentationId agent-browser:windowId:sessionId native session agent-browser:sessionId logical target { windowId, sessionId, runId, captureEpoch }逻辑目标而非 NativeKit 无作用域的回调才用于识别 activate 与 dismiss 动作。窗口或会话改变时先移除上一个展示再挂接下一个宿主。展示在 Browser 面板暂时可见或宿主短暂失去资格时保持分配但隐藏从而保留 NativeKit 的手动拖动位置run 终结、会话/页面销毁、宿主关闭与关机时移除它。8.2 帧投递规则既有捕获安全规则全部保留1280 x 800 源视口400 x 250 输出最大原生面板 360 x 225对 400 x 250 帧降采样JPEG quality 72512 KiB 的 DeepChat 帧上限远低于 NativeKit 的 32 MiB 输入上限单捕获在途捕获、缩放、编码、呈现全部结束后才排下一次呈现前即时校验模式、run ID、目标窗口与 epoch陈旧结果直接丢弃捕获或解码失败时保留最后一张有效原生图像。原生分支的帧路径只有一步JPEG Buffer - data:image/jpeg;base64,Buffer.toString(base64) - overlay.pushImage()该分支不向 renderer 发送任何帧。浮层初始隐藏首次显示或恢复时DeepChat 在隐藏状态下推入当前帧且只有pushImage()成功后才会调用setVisible(true)避免闪烁出陈旧或空面板。首帧语义第一张成功帧还会调用一次setActiveSession()选定 NativeKit 会话后续图像刷新只调用pushImage()同一 host / presentation / session ID不重复attachHost()、setActiveSession()、setVisible(true)或任何移除操作。NativeKit 按稳定的presentationId拥有手动帧因此图像替换只改变像素与尺寸不会重置用户拖动的原点宿主 move/resize 同步是独立的、去抖的路径。9. 交互契约与 UI 布局9.1 原生交互面NativeKit 0.6.3 定义工具栏按钮之外的任意图像区域可拖动双击图像激活点击Open in panel关闭 PiP 并激活既有 Browser 面板点击Close关闭当前 Agent run 的预览面板永不成为 key/main window永不向远程页面转发输入。activate 映射① 显示并聚焦属主聊天窗口 → ② 为精确的 window/session/run 发布类型化browser.preview.action事件 → ③ 由当前 renderer 打开既有 Browser 面板 → ④ 停止原生捕获并把同一页面 View 重挂到稳定面板边界。Close 映射① 标记逻辑 run 已关闭 → ② 停止捕获但让页面继续在隐藏渲染宿主中渲染 → ③ 发布同一类型化动作事件使 renderer 资格一致 → ④ 允许后续 run 再次显示 PiP。原生路径只配置 NativeKit 的两个内置图标类型并在 DeepChat 内映射其 ID不保留 Canvas 时代的标题工具栏、居中拖动提示或活动光晕——用另一个浮层重建它们会重新引入本次迁移要消除的焦点、z-order 与跨窗口协调问题。两种表面都保持只读绝不把点击转发进远程页面。9.2 UI 布局前后对比迁移前对话内 renderer 卡片---------------------------------------------------------------- | DeepChat | | | | Conversation ---------------------- | | | Vue toolbar | | | | Canvas page mirror | | | | drag / open / close | | | ---------------------- | ----------------------------------------------------------------迁移后桌面工作区中的原生面板------------------------------------------ ---------------------- | DeepChat | | Native PiP | | | | | | Conversation | | Agent page snapshot | | Browser panel remains closed | | [▯][×]| | | | drag; double-click | ------------------------------------------ ---------------------- AppKit/Win32/XCB控件从左到右配置为Open in panel再Close实际 NativeKit 符号为平台原生上图只表达结构而非确切图标。原生能力不可用Windows arm64 / native Wayland / unavailable addon - Browser: open the existing side-panel browser - Computer Use: continue without PiP10. 生命周期矩阵事件原生动作页面动作合格捕获开始Attach/update hostpush current frameshow保持在 1280 x 800 渲染宿主新帧只替换同一展示保留手动原点不重挂Browser 面板打开隐藏展示停止捕获同一 View 重挂进面板合格 run 中面板关闭Show 前 push 当前帧重挂进渲染宿主原生Close控件隐藏记录 run 关闭保留渲染宿主停止捕获原生Open in panel控件聚焦宿主请求 Browser 面板稳定边界后重挂原生双击聚焦宿主请求 Browser 面板稳定边界后重挂宿主 move/resize/显示变化去抖attachHost()刷新页面不变宿主 blur/hide/minimize同步隐藏仅当 Agent 仍需要时继续渲染宿主重新聚焦重评估push-before-show不重载run 终结移除展示停止捕获释放渲染宿主会话/页面销毁移除展示销毁既有页面资源宿主关闭移除展示detach host清理目标应用退出overlay.stop()一次既有 presenter 关闭流程一个值得注意的产品策略尽管 macOS 的 NativeKit 面板可以加入所有 SpacesDeepChat 仍保留现行产品策略——Agent 页面预览在其属主聊天窗口不在前台时隐藏让它持续悬浮在无关应用之上是独立的产品决策不在本次迁移范围。11. 性能契约两个可测量的承诺原生手感被拆成两个可测量承诺避免把感觉流畅变成不可验证的营销话术。11.1 原生移动原生路径无 renderer 指针移动处理器、无拖动位置 IPC拖动、钳制、z-order 全部在 NativeKit 内完成面板可越过 DeepChat 的每一条窗口边缘仅受显示器工作区约束捕获工作不得在 60 Hz / 120 Hz 参考显示器上产生可见拖动卡顿。11.2 页面新鲜度验收目标活跃 Agent 活动目标至多 8 FPS上一完整周期结束后 125 ms 调度空闲页面目标1 FPS捕获绝不排队或重叠暖启动合格 → 首可见帧p95 ≤ 300 ms活跃端到端帧龄 p95 ≤ 250 msoverlay.pushImage()p95 ≤ 8 ms、p99 ≤ 25 ms受支持参考平台归因于 PiP 帧呈现的主进程任务不得有单次超过 50 ms。规格反复强调当前 Browser 调度仍是每完整周期后 500 ms 活跃 / 2000 ms 空闲提升节奏必须以同步 NativeKit 解码/呈现与实体显示器验收为前提当前调度不是新鲜度目标已通过的证据。在 NativeKit 0.6.3 下目标上限不得超过 8 FPS。这些是发布门槛release gates而非任意硬件的运行时承诺——对外可见的说法只能是原生移动 新鲜只读预览而非原生速率浏览器视频。12. 安全与隐私NativeKit 只在 Electron 主进程导入任何 NativeKit 对象、原生句柄、原始 IPC 通道或通用能力都不经 preload 暴露远程页面执行继续留在既有 YoBrowser 会话的沙箱中原生面板只接收降采样后的 JPEG data URL帧只存在于内存绝不记日志、缓存、持久化或写盘日志只包含平台、表面、时长、尺寸与脱敏生命周期原因不含图像字节、URL、标题、DOM 或会话内容主进程在每次显示前校验目标BrowserWindow、会话、run ID、模式与 epoch陈旧捕获不能替换当前会话的面板宿主 blur/hide/minimize 与会话失活由主进程直接隐藏原生面板不等 renderer 清理。13. 打包与兼容性13.1 五项打包约束精确依赖zerob13/nativekit: 0.6.3在 pnpm-workspace.yaml 中把zerob13/nativekit标记为禁止安装期构建allowBuilds: zerob13/nativekit: false——已发布预编译在运行时解析不支持的目标必须禁用原生 PiP 而不是现场编译本地 addon保持它位于 Electron 主 bundle 之外让node-gyp-build能解析打包后的原生 addon从 ASAR 解包node_modules/zerob13/nativekit/prebuilds/**/*——对应 electron-builder.yml 的asarUnpack规则**/node_modules/zerob13/nativekit/prebuilds/**/*打包后校验darwin-arm64 与 linux-arm64 验证node.napi.armv8.nodedarwin-x64、win32-x64、linux-x64 验证node.napi.node。13.2 打包期校验的实现scripts/afterPack.js 中的validateNativeKitPrebuilds()正是这条规则的落地它按目标平台/架构映射预编译目录darwin-universal 同时覆盖 x64 与 arm64并在app.asar.unpacked/node_modules/zerob13/nativekit/prebuilds/platform-arch/下检查对应文件名缺失即抛错Missing NativeKit prebuild。配套的打包配置测试见 test/main/build/electronBuilderConfig.test.ts 与 test/main/scripts/afterPack.test.ts。关键区分win32-arm64 打包不得失败——该目标在 0.6.3 下有意使用按源禁用行为缺失受支持预编译是打包失败不支持的运行时只是禁用原生 PiP不阻塞应用启动与 Agent 工具。同时禁止在正常 DeepChat 发布流程中源码编译该 addon。本次迁移不需要任何持久化数据或设置 schema 变更。14. 回滚、失败语义与验收标准14.1 回滚回滚是纯代码层面的三步① 无条件选择renderer-canvas② 停止加载 NativeKit③ 确认无其他消费方后移除精确依赖与 ASAR 规则。由于浏览器页面、路由、渲染宿主、捕获格式与 Canvas 实现保持兼容回滚不涉及页面导航、用户数据迁移或已存设置变更。14.2 失败语义速查失败点行为动态导入或overlay.start()失败记一次日志并为本进程禁用原生 PiP首个真实宿主attachHost()失败本进程内标记原生能力不可用Browser 原生能力失败发布既有 activate 动作并打开侧面板Computer Use 原生能力失败不暴露预览表面工具执行不变帧捕获/缩放/编码失败保留上一帧下个有界 tick 重试pushImage()失败NativeKit 事务性保留上一展示限频告警后重试模式/run/窗口变更后的陈旧帧在pushImage()前丢弃无当前逻辑目标的原生动作忽略面板激活超时保留或恢复原生 PiP绝不丢失活体页面宿主关闭或 addon 关闭清理幂等14.3 验收标准要点受支持平台恰好加载 NativeKit 0.6.3 并使用其原生浮层Windows arm64、原生 Wayland、addon 不可用三类情况打开既有侧面板 Browser 且不显示 Computer Use PiP首选路径不向 renderer 发送browser.preview.frame负载远程页面在原生 PiP 与 Browser 面板移交间保持同一WebContents/WebContentsView/ 会话 / URL / DOM / 滚动状态 / cookies / CDP 目标面板只读、可拖、工作区钳制、非激活可拖到完全离开 DeepChat 窗口而不弹回同展示下替换图像不 reattach / reactivate / re-show / remove / 重置手动位置双击与Open in panel打开既有面板、Close只关闭当前 run进程内恰好一个原生 PiP 可见首显与恢复先 push 当前帧再可见宿主 blur/hide/minimize、面板打开、run 终结、页面销毁、关机确定性隐藏/移除拖动零 renderermousemoveIPC 并通过原生移动 QA 门槛帧延迟与同步调用预算达标前不提升捕获节奏打包应用在受支持目标上含正确预编译renderer/preload 安全边界不变测试覆盖按需加载、进程级禁用、Browser 侧面板移交、Computer Use 无表面、原生适配器选择、动作映射与打包pnpm run format、pnpm run i18n、pnpm run lint、typecheck、聚焦测试、构建与打包平台检查全部通过。15. 实现证据与测试落点规格文档记录的实现证据截至 2026-07-29包括zerob13/nativekit锁定 0.6.3 且保持主 bundle 外部与 ASAR 解包0.5.5 tarball 五平台全部使用node.napi.node导致 Linux arm64 回退源码编译失败、0.5.6 修正为架构特定文件名macOS arm64 安装electron-builder install-app-deps配合PREBUILDS_ONLY1可解析 arm64 预编译且不产生build/Release回退二进制0.6.3 静态链接 Windows MSVC 运行时0.5.4 的 macOS 二进制报minos 12.0真实 Electron smoke test 完成start - attachHost - pushImage - removeImage - detachHost - stop250 ms 替换同展示时面板 3 秒后仍停在(180, 420)证明图片刷新不再恢复右上锚点macOS arm64 目录包内app.asar.unpacked/node_modules/zerob13/nativekit/prebuilds/darwin-arm64/nativekit.napi.node与已装预编译逐字节一致。测试与代码落点可在仓库中直接验证协调器核心实现src/main/desktop/preview/AgentPreviewCoordinator.ts协调器单元测试test/main/desktop/preview/AgentPreviewCoordinator.test.tsBrowser presenter 集成src/main/desktop/browser/YoBrowserPresenter.tssetPreviewMode在 L351 附近Computer Use presentersrc/main/desktop/computerUse/ComputerUsePreviewPresenter.ts 及其测试 test/main/desktop/computerUse/ComputerUsePreviewPresenter.test.ts组合与装配src/main/app/composition.ts依赖锁定package.json、pnpm-workspace.yaml、pnpm-lock.yaml打包解包与校验electron-builder.yml、scripts/afterPack.js规格同时如实记录尚未关闭的验证项Windows / Linux / macOS x64 实体机交互、原生 Wayland 不可用行为、窗口外视觉交互以及 60/120 Hz 性能测量仍需在真实目标环境上完成renderer 套件的App.startup.test.ts基线 mock 问题initAppStores()返回undefined而生产链路.then()与本迁移无关。16. 已解决决策汇总NativeKit 版本精确为 0.6.3原生移动是主要流畅性收益页面仍是有界快照流NativeKit 绝不因应用启动或仅资格判断而加载原生能力失败 → 打开既有侧面板 Browser 并禁用 Computer Use PiP不强制 Linux 显示后端使用 NativeKit 调用方配置工具栏不新增配套 Vue/原生工具栏窗口单可见 PiP使得 NativeKit 无作用域动作回调安全保留既有前台窗口可见性策略无阻塞实现的遗留澄清标记。这份规格与实现的完整配合为任何需要在 Electron 主进程中接入原生叠加层的项目提供了一个可复用的参考样本把流畅拆成原生移动与快照新鲜度两个可测量承诺用能力矩阵 生命周期矩阵 失败语义表把边界钉死再用打包期预编译校验守住分发底线。【免费下载链接】deepchatDeepChat - A smart assistant that connects powerful AI to your personal world项目地址: https://gitcode.com/GitHub_Trending/dee/deepchat创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考