☰
holaOS Artifacts / Output 模块改造实战指南:从待办计划到源码落地
2026/10/2 8:15:45 网站建设 项目流程
  • 人工智能
  • 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
点击查看免费下载

本文以 docs/artifacts-output-fix-plan.md 这份内部"待办与修改方法"计划文档为骨架,逐一展开其列出的 Bug、功能改进、决策待拍板与暂缓项,并结合 holaOS 桌面端与 runtime 的真实源码(apps/desktop/electron/、apps/desktop/src/、runtime/)给出实现细节、路径依据与可验证证据。读完你将掌握:Agent 产出文件的 workspace 路径约束机制、浏览器 overflow 弹窗的原生菜单改造思路、HTML 产出的预览与归类优化方向,以及从零到落地完整的 Artifact 模板(存储 / IPC / 创建流程复用)实现方案。

一、计划文档背景与状态图例

这份文档是一份面向 holaOSArtifacts / Output 模块的治理清单,覆盖"产物产出、展示、预览、模板复用"这条核心链路。文档使用四类状态图例标记每一项的推进状态:

  • 🐛 Bug —— 已确认的缺陷,需修复;
  • ✨ 功能 / 改进 —— 已确认方向的功能或体验优化;
  • 🤔 决策待拍板 —— 方向已讨论、需要 PM 确认范围后实施;
  • ⏸️ 暂缓 —— 有意推迟,后续再做。

文档还单列了"已剔除"清单,记录讨论后确认不属于本任务范围的事项,避免后续重复评估。本文按这四类分组逐项讲解,并在每项中给出当前仓库源码中可验证的落点。

二、核心链路 Bug:Agent 产出文件必须落在 workspace 内

2.1 现象与根因(#1)

文档记录了一个被定性为"核心链路问题"的 Bug:

  • 现象:让 Agent 写 doc,文件被写到了沙箱 / 工作目录之外,实际 workspace 文件夹是空的。
  • 根因方向:runtime/harness的 file-write 工具在拼接写入路径时,没有以 workspace 根目录为基准解析,而是沿用了进程 cwd。Agent 的所有产出文件都必须落在/holaboss/workspace/<workspace_id>/内。
  • 排查重点:harness 的工作目录设置 +write_file工具的路径拼接,涉及runtime/(harness-host / api-server 的文件写入),可能联动后端沙箱 cwd。
  • 备注:文档标注〔需 runtime 侧排查后再定确切改法〕,即定位精确根因后再确定修复写法。

2.2 与 #2 的关系

PM 确认#2 与 #1 是同一个问题,随 #1 一起排查修复即可,不单列。这提醒我们:待办清单中形似独立的两条,可能经核实后是同因同改,治理时先合并去重再排期。

2.3 源码侧的印证:路径解析始终以 workspace 根为基准

虽然本 Bug 指向 runtime 侧,但桌面端主进程(apps/desktop/electron/main.ts)的既有实现早已把"workspace 根目录解析"作为文件操作的硬约束,可作为修复参照:

  • resolveLocalWorkspaceRoot(workspaceId)负责解析某个 workspace 的根目录;
  • resolveWorkspaceScopedExplorerPath(sourceRelPath, workspaceId)将用户提交的相对路径强制限定在 workspace 根内再做解析,例如在saveOutputAsArtifactTemplate(main.ts)中,先调用它拿到absolutePath,再检查existsSync才继续拷贝;
  • resolveSessionDeliveryRoot(workspaceId, sessionId, workspaceRoot)(main.ts)进一步规定"会话产出物"落在哪里:项目绑定的会话写到项目自身目录(workspace 根之外),其他情况一律落到 workspace 根。这段注释明确写着"Mirrors the runtime's sessionOutputRoot so a file written here is found by resolveOutputAbsolutePath later",即与 runtime 的sessionOutputRoot保持一致,确保 Agent 写出的文件能被输出解析逻辑重新找到。

因此,修复 #1 的关键就是让 runtime/harness 的写入逻辑与这套约定对齐:写入目标一律以workspaceRoot为基准拼接,而不是进程 cwd。

三、浏览器 overflow 弹窗:弃用自定义 HTML,改用原生菜单(#3)

3.1 现状问题

浏览器 "..." 更多菜单当前是一个手写 HTML + CSS 的自定义 WebContents 弹窗,对应文档描述的browser-pane/popups.ts中createOverflowPopupHtml(themeCss)(约 455-527 行),通过browser:toggleOverflowPopup打开。自定义样式与系统观感不一致,导致视觉奇怪。

3.2 改造方案

弃用自定义 HTML 弹窗,改为Electron 原生菜单:

Menu.buildFromTemplate([ { label: "Downloads", click: openDownloads }, { label: "History", click: openHistory }, { label: "Import browser profile", click: openImportProfile }, ]).popup({ window, x, y });
  • 在锚点位置弹出系统原生下拉,不写任何 HTML/CSS;
  • 原有三个动作openDownloads / openHistory / openImportProfile直接挂到菜单项的click上;
  • 涉及文件(按文档指引):apps/desktop/electron/browser-pane/popups.ts(删除createOverflowPopupHtml路径,toggleOverflowPopup改为弹原生 Menu)、apps/desktop/electron/overflowPopupPreload.ts(可一并移除)。

3.3 当前仓库状态与取舍

从当前仓库源码结构看,apps/desktop/electron/browser-pane/目录(目录列表)已不存在popups.ts,仅保留 overflowPopupPreload.ts(其contextBridge.exposeInMainWorld("overflowPopup", ...)仍存在),说明该自定义弹窗实现很可能已被移除或重构——实施时以现有代码为准。文档还明确记录了取舍:原生 Menu 用主题色受限(跟随系统),但这正是"纯 native 不加样式"的收益。

四、产出预览能力盘点:pptx 只读预览与 HTML 输出的现状、优化空间

4.1 pptx 只做只读预览(#4,方向已定)

文档给出明确结论:pptx只做只读预览,不做 editor(editor 成本高),无需额外开发,保持现状。这是"范围收敛"的典型决策,避免在低 ROI 方向上投入编辑器级工作量。

4.2 HTML 输出:基础已支持,重点是找优化空间(#5)

文档先澄清了一个误解:PM 原以为"html 文件没支持",经核实html/htm 已包含在DOCUMENT_EXTENSIONS中,已被归类为 Document 且能用内置 tab 打开——基础能力已经支持,因此任务从"从零支持"转为"找优化空间"。

源码证据就在 ArtifactBrowserModal.tsx:

const DOCUMENT_EXTENSIONS = new Set([ "md", "mdx", "markdown", "txt", "doc", "docx", "rtf", "odt", "html", "htm", ]);

而 kind 归类逻辑中,扩展名落入DOCUMENT_EXTENSIONS时返回"document",与其它类型(spreadsheet / pdf / code)并列。可见浏览器 / Artifact 展示层对 HTML 的归类确实存在,但仍有以下优化空间:

  1. 真正的网页预览:打开 html 文件时渲染为网页(而非纯文本 / 编辑器),贴近"这是个网页"的直觉;
  2. 单列 "Web page" kind:把 HTML 从 Documents 中拆出独立类别,图标 / 标签更准确;
  3. 支持内容型 HTML 输出:渲染html_content字段(无对应文件的输出)而不是只认文件。

涉及文件(按文档指引):ArtifactBrowserModal.tsx(归类 / kind)、apps/desktop/src/components/layout/shell/useOpenWorkspaceOutput.ts(打开 / 预览)。文档将此项标记为低优先级(锦上添花,基础可用),可作为后续迭代的排期参考。

五、Artifacts 列表体验:Apps 空状态引导与 Pin 全覆盖

5.1 Apps 类型空状态加入口(#6)

现状:Apps filter 下没有内容时缺少引导。

修改方法:在 ArtifactsPane 的 Apps 过滤为空时,渲染一个引导入口(连接 / 安装 app 的 CTA)。

涉及文件:apps/desktop/src/components/panes/ArtifactsPane.tsx(文档备注:增强版在release/2026.612分支)。空状态 CTA 是列表型界面最常见的可用性缺口,这里的原则是"空列表也要给下一步动作"。

5.2 让"能 pin 的地方尽量都有 pin"(#7)

目标(PM 拍板):Pin(= 收藏)不必新建概念,只要凡是展示 artifact / 文件 / output 的表面,都提供 pin(star)入口,保持一致。

现状盘点:已知已有——artifact 行 star、文件树右键 "Pin to sidebar";需要排查补齐的候选——Recent 列表项、聊天内联 Outputs 行、文件预览(FilePreviewPane)、搜索结果等。

统一做法:复用toggleFavoriteAtom+isFavoriteAtom,在缺失处加一致的 star 按钮 / 菜单项。

源码印证:apps/desktop/src/components/layout/shell/state/favorites.ts定义了统一的收藏状态模型——第 108 行注释明确"Descriptor accepted by toggleFavoriteAtom——also the prop shape any…"(即该 atom 同时充当组件 props 形状),第 138 行为toggleFavoriteAtom定义。当前仓库中已有多个展示表面复用该模型:

  • apps/desktop/src/components/layout/shell/PinStarButton.tsx—— 通用 star 按钮组件;
  • apps/desktop/src/components/layout/shell/Sidebar.tsx—— 侧边栏(文件树右键 "Pin to sidebar" 即来自此);
  • apps/desktop/src/components/panes/ArtifactsPane.tsx—— artifact 行 star;
  • apps/desktop/src/components/panes/InstalledAppsList.tsx—— 已安装 Apps 列表。

可见 #7 的"统一复用 atom"思路已在多数表面落地,剩余工作是盘点并补齐(Recent / 内联 Outputs / FilePreviewPane / 搜索结果等)尚未覆盖的入口。

六、决策落地:只删除浏览器书签栏的 "Folders" 按钮(#8)

PM 决定:导入保留、书签保留(有意义)——书签栏继续显示散装书签,只删掉 "Folders" 那个弹层按钮。

修改方法(按文档指引):在BrowserPane.tsx移除bookmarkTree.folders.length > 0时渲染的那段 FoldersPopover(约 1059-1087 行)。书签栏(showBookmarkStrip)和散装书签(rootBookmarks)保持不动;bookmarkTree.folders数据可以保留不用,也可顺手不再渲染。

范围约束:不动BrowserProfileImportButton/ 导入流程 / 书签栏其余部分。

这是一个"最小化改动"的典型样例:功能上只需要删除一个入口,明确圈定不改的边界(导入、书签数据、书签栏渲染),避免改动蔓延。需要说明的是,按文档指引的BrowserPane.tsx在当前仓库apps/desktop/src/components/panes/下已无法直接检索到对应文件(书签相关实现可能已迁移或重构),实施时请以当前分支实际代码为准定位那一段 Popover 渲染。

七、Artifact 模板:从设计建议到完整源码实现(#9,已落地)

7.1 现状与目标

文档先厘清了现状(已查清):

  • 现有 "Save as template"(SaveTemplateDialog+ Sidebar 2743 行 + IPCworkspace:saveAsTemplate→saveWorkspaceAsTemplate)是workspace 级模板:把整个 workspace 目录拷到userData/local-templates/<id>/,供"新建 workspace"复用;
  • 没有artifact(单个产出物)级别的模板机制。

目标:让用户把某个 artifact(docx / pptx / xlsx / report 等)存成可复用模板,下次创建同类产出直接套用。

7.2 设计建议的五步方案

文档给出了 5 步实现方法,逐条如下:

  1. 存储:镜像现有 local-templates 模式,新增userData/local-artifact-templates/<templateId>/,内放 ① 该 artifact 的文件副本 ②template.jsonmanifest(output_type/title/extension/ 来源 metadata / emoji / 描述)。
  2. 入口(存):在 artifact 行的⋯菜单加 "Save as artifact template"(复用 ArtifactRow 行操作菜单),弹一个轻量 dialog 收名称 / 描述(复用SaveTemplateDialog模式)。
  3. IPC:新增workspace:saveArtifactAsTemplate(拷文件 + 写 manifest)、workspace:listArtifactTemplates、workspace:deleteArtifactTemplate,在main.ts仿saveWorkspaceAsTemplate实现。
  4. 入口(用):在 Output 创建选择器(Sidebar 约 3574-3624 行的 Folder / Markdown / Word / … picker)末尾追加 "From template…",列出已存的 artifact 模板;选中后把模板文件拷进当前 workspace 作为新文件(再交给 agent / editor)。
  5. (可选)agent 复用:把 artifact 模板登记进 workspace.yaml / skills,让 agent 创建同类产出时能引用模板结构。

7.3 当前仓库中的完整落地(源码证据)

关键发现:该功能在当前仓库中已经完整实现,落点在apps/desktop/electron/main.ts,与文档建议基本一一对应:

  • 存储根目录:artifactTemplatesRoot()(main.ts L15145)返回path.join(app.getPath("userData"), "artifact-templates")—— 与文档建议的local-artifact-templates同思路(实际目录名用了artifact-templates);
  • 列出模板:listArtifactTemplates()(main.ts L15157)遍历根目录下的每个子目录,读取template.json,校验id/name后按createdAt倒序返回;
  • 预览:readArtifactTemplatePreview()(main.ts L15225)—— 图片类扩展名(png/jpg/jpeg/gif/webp/svg/bmp/avif)返回 base64 dataURL(单文件 >2MB 返回 none),文本类扩展名(md/markdown/txt/html/htm/csv/tsv/json/xml/yaml/yml/css/ts/tsx/js/jsx/py)返回前 1200 字符的文本预览;对templateId做了..// 路径分隔符注入校验;
  • 保存模板:saveOutputAsArtifactTemplate()(main.ts L15273)—— 校验workspaceId/filePath/name必填,用resolveWorkspaceScopedExplorerPath解析源文件(保证在 workspace 根内),slugifyArtifactTemplate(name) + Date.now().toString(36)生成模板 ID,拷贝文件为content<ext>,并写出 manifest;
  • 从模板创建:createOutputFromArtifactTemplate()(main.ts L15362)—— 读取模板 manifest,解析目标 workspace 根与resolveSessionDeliveryRoot会话产出目录,把content<ext>拷入 workspace 作为新文件;
  • 删除模板:deleteArtifactTemplate()(main.ts L15418)。

**IPC 通道(main.ts L28670-L28703)**已注册五个:

IPC 通道功能
workspace:listArtifactTemplates列出全部模板
workspace:readArtifactTemplatePreview读取模板预览(图片 dataURL / 文本摘要)
workspace:saveOutputAsTemplate把某个 output 保存为模板
workspace:createOutputFromTemplate从模板创建新输出
workspace:deleteArtifactTemplate删除模板

渲染进程侧,apps/desktop/electron/preload.ts(第 2202 行起)通过contextBridge暴露listArtifactTemplates等对应方法,前端可直接调用。

manifest(template.json)字段(源码可见的ArtifactTemplateRecordPayload实际字段):id、name、description、category、ext、outputType(默认"document")、fileName(源文件 basename)、createdAt(ISO 字符串),以及内部追加的contentFileName与schemaVersion。文档建议的output_type / title / extension / emoji / 描述字段在实际实现中演化为上述字段集合。

7.4 待拍板事项

文档备注中请 PM 确认两点:先做 1-4 步(存 + 在创建流程里复用)即可,第 5 步 agent 复用作为后续;另外确认"artifact 模板"是 per-workspace 还是全局共享。从当前源码看,模板存储落在userData全局目录,即全局共享方案;第 5 步的 agent 复用(登记进 workspace.yaml / skills)在当前仓库中未见对应实现,仍属后续可选项。

八、暂缓项与已剔除清单

8.1 暂缓:docx editor 操作图标清晰化

docx 已支持 editor;操作图标可读性提升暂缓,后续再做。文档没有展开具体图标清单,仅记录"后续再做"的状态,避免在排期上遗留"未决但未记录"的悬空项。

8.2 已剔除(讨论后确认非任务)

文档明确排除以下条目,防止后续误纳入范围:

  • editor 崩溃—— 实际没有此问题;
  • "创建 → 弹对话框 → agent 跑"统一流程—— 暂时不用;
  • 可复用小组件—— 非确认任务;
  • 看图识别录入 Notion / 看图自动填输入框—— 没有此任务;
  • plugin onboarding 表单(@Sam)—— 不在本范围。

这类"已剔除"清单的价值在于:把讨论过的候选永久归档,标注否决理由,为后续评审省去重复论证。

九、相关源码索引

本文引用的核心证据文件(仓库根相对路径):

  • 计划文档本体:docs/artifacts-output-fix-plan.md
  • Agent 产出路径解析 / workspace 约束:apps/desktop/electron/main.ts(resolveLocalWorkspaceRoot、resolveWorkspaceScopedExplorerPath、resolveSessionDeliveryRoot,见 L15157-L15389 附近)
  • Artifact 模板完整实现:apps/desktop/electron/main.ts(存储 / 预览 / 保存 / 创建 / 删除)与 IPC 注册段、preload 桥接
  • 产出归类与扩展名清单:ArtifactBrowserModal.tsx 与 kind 判定
  • 收藏模型与 Pin 入口:favorites.ts、PinStarButton.tsx、Sidebar.tsx、ArtifactsPane.tsx
  • 产出打开 / 预览逻辑:useOpenWorkspaceOutput.ts
  • 浏览器 pane 目录(原生菜单改造落点):apps/desktop/electron/browser-pane/

小结

这份计划文档的价值不在于"列出了多少条待办",而在于每一条都给出了现象 → 根因 / 决策 → 修改方法 → 涉及文件的完整闭环,并明确标注了状态(Bug / 功能 / 待拍板 / 暂缓 / 已剔除)。对照当前仓库源码可以看到:核心的 Agent 产出路径约束已成为文件操作的统一前置校验(resolveWorkspaceScopedExplorerPath),HTML 产出的基础归类早已在DOCUMENT_EXTENSIONS中支持,Pin 入口已通过toggleFavoriteAtom在多个表面复用,而Artifact 模板(#9)已经从设计建议完整落地为main.ts中的五条 IPC + manifest 机制。对于尚未实施的项(原生菜单改造、Apps 空状态 CTA、Pin 补齐、Folders 按钮删除),本文给出的源码位置与边界说明可直接作为后续实施的起点。

  • 人工智能
  • 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
点击查看免费下载

相关推荐

上一篇:PPTTimer:Windows平台终极演讲计时器,让PPT演示时间掌控如呼吸般自然
下一篇:专业级OBS多平台直播插件:obs-multi-rtmp完全配置指南

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询