Craft Agents OSS v0.4.6 技术解析:HTML/PDF 内联预览、统一事件适配器与多后端模型发现

Craft Agents OSS v0.4.6 技术解析:HTML/PDF 内联预览、统一事件适配器与多后端模型发现 Craft Agents OSS v0.4.6 技术解析HTML/PDF 内联预览、统一事件适配器与多后端模型发现【免费下载链接】craft-agents-oss项目地址: https://gitcode.com/GitHub_Trending/cr/craft-agents-ossv0.4.6 是 Craft Agents OSS本仓库一次兼具新功能与架构重构的里程碑版本它为聊天界面引入了html-preview/pdf-preview内联渲染能力落地了 Source Templates 与 Mustache 模板引擎构建了面向 Claude / Codex / Copilot 的统一事件适配器架构并修复了多项社区反馈问题。阅读本文你将掌握这些能力的调用方式代码块 JSON 规格、render_template工具用法、SKILL.md frontmatter 写法以及其背后的源码实现原理可直接在真实会话中复现与使用。本文基于 apps/electron/resources/release-notes/0.4.6.md 展开并辅以仓库源码佐证。一、版本概览v0.4.6 的定位v0.4.6 是 Craft Agents OSS 的功能型大版本核心变化可以归纳为四条主线富内容内联预览新增html-preview与pdf-preview两种 Markdown 代码块可在聊天流中直接渲染 HTML 文档与 PDF 文件支持多项目 Tab 切换与全屏查看Source Templates 体系来源Source可以自带 Mustache 语法的 HTML 模板通过新的render_template工具实现品牌化、一致的渲染输出统一事件适配器架构将流式事件处理逻辑抽取为BaseEventAdapter基类按后端Claude、Codex、Copilot 等拆分适配器并新增EventQueue保证事件有序投递动态 Codex 模型发现从 Codex app-server 动态拉取可用模型周期性刷新并支持失败回退。此外还包含批量会话操作、Fast mode 特性开关迁移到共享包以及一批社区问题修复对应 issue #249、#254、#255。二、内联 HTML / PDF 预览让富内容所见即所得2.1html-preview代码块JSON 规格与渲染流程在 v0.4.6 中Agent 输出形如下面的代码块即可触发内联 HTML 预览html-preview { src: /absolute/path/to/file.html, title: Optional display title } src字段指向磁盘上的 HTML 文件绝对路径通常来自Write工具或transform_data的返回值文件在渲染时实时读取title字段预览面板头部显示的标题可选。底层实现位于 packages/ui/src/components/markdown/MarkdownHtmlBlock.tsx。组件先对代码块内容做JSON.parse支持两种规格单个src或items数组多项目 Tab。加载到的 HTML 会被缓存进contentCache并经过injectBaseTarget()预处理——在head中注入base target_top使 iframe 内链接点击能够上抛到顶层由 Electron 的will-navigate拦截后交给系统浏览器打开。安全机制是该组件设计的重点iframe 使用sandboxallow-same-origin allow-top-navigation-by-user-activation刻意不含allow-scripts即所有 JavaScript 执行被彻底阻断allow-same-origin则保证 CSS 与图片等资源可以正常解析。因此从源码注释看无需额外的内容消毒No sanitization needed。多项目切换采用了防闪烁设计所有已缓存的项被同时渲染为隐藏 iframedisplay:none切换 Tab 只是切换 CSS 显隐不做重新解析因此不会出现白屏闪烁。全屏查看通过HTMLPreviewOverlay组件实现并复用同一套items导航。2.2pdf-preview代码块基于 react-pdf 的内联 PDFpdf-preview { src: /absolute/path/to/file.pdf, title: Optional display title } 实现见 packages/ui/src/components/markdown/MarkdownPdfBlock.tsx使用react-pdfpdf.js 封装渲染 PDF 首页内联区域固定 400px 高度避免切换项目时布局跳动右下角提供展开按钮全屏模式进入PDFPreviewOverlay支持逐页导航。pdf.js worker 通过 Vite 的?url导入兼顾开发与生产环境的跨平台兼容。需要注意的一个实现细节组件通过onReadFileBinary读取二进制并在缓存时复制为new Uint8Array(data)——因为 react-pdf 会把 ArrayBuffer 转移给 workerdetach 原对象必须保留母本副本供后续全屏预览再次使用。2.3 与 html-preview 的关键区别在 packages/shared/src/prompts/system.ts 的模型提示词中对两者的定位做了明确区分HTML 内容邮件 HTML 正文、API 返回的富文本报告、复杂 CSS/表格/图片需要先用Write或transform_data落盘再通过src引用PDF 文件本身就在磁盘上Read 工具读取结果、下载的 PDF、脚本生成的报告直接引用文件路径即可无需额外提取。两者都支持多项目 Tab 写法items数组每个项目带label该提示词中还给出了邮件线程与季度报告的实际示例。2.4 模型侧使用工作流提示词 packages/shared/src/prompts/system.ts 为 Agent 定义了标准流程获取 HTML 内容如解码 base64 邮件正文、拉取 API 响应用Write工具写入会话数据目录或transform_data将 HTML 写为文件输出html-preview代码块src指向该文件。适用场景包括Gmail/Outlook 邮件 HTML 正文、API 返回的 HTML 报告、任何 Markdown 转换会丢失布局的富内容。三、Source Templates 与 Mustache 模板引擎3.1render_template工具从数据到品牌化 HTMLv0.4.6 引入了一个新的会话工具render_template注册于 packages/session-tools-core/src/tool-defs.ts实现于 packages/session-tools-core/src/handlers/render-template.ts调用参数为{ source: string; // 来源 slug如 linear template: string; // 模板 ID如 issue-detail data: Recordstring, unknown; // 渲染数据 }其内部流程见源码注释共 5 步校验来源存在workspacePath/sources/source加载模板source/templates/template.html依据模板声明的required字段对数据做软校验用 Mustache 渲染将结果 HTML 写入会话数据目录文件名形如source-template-timestamp.html返回绝对路径提示将该路径作为 html-preview 代码块的src值。软校验不会阻断渲染缺少必填字段时模板照常渲染但响应中会附带 Warnings 列表提示可能出现空白区块、建议补齐后重新渲染。3.2 模板目录结构与自描述元数据头模板存放在来源目录下的templates/子目录中每个模板是带元数据头注释的 HTML 文件。元数据格式定义于 packages/session-tools-core/src/templates/loader.ts!-- template issue-detail name Issue Detail description Renders a single Linear issue required identifier, title, status optional priority, assignee, team --template模板 ID必填缺失则该文件不视为模板name可读名称缺省回退为 IDdescription用途说明required/optional逗号分隔的数据字段清单用于软校验。loadTemplate()支持精确文件名匹配{templateId}.htmllistTemplates()则会扫描templates/目录下所有.html文件并解析元数据。没有元数据头的文件也能加载只是元数据退化为空值。3.3 零依赖 Mustache 实现语法子集与安全设计模板渲染引擎是 packages/session-tools-core/src/templates/mustache.ts一个零依赖、逻辑无关logic-less的 Mustache 实现覆盖核心规范语法含义{{var}}变量插值HTML 转义{{{var}}}非转义变量插值{{#section}}...{{/section}}区块条件 循环数组迭代、真值渲染一次{{^section}}...{{/section}}反向区块假值/空数组时渲染{{! comment }}注释跳过{{a.b.c}}点号路径嵌套解析沿上下文栈自顶向下查找{{.}}当前上下文实现要点HTML 转义默认插值对 做实体转义从根源上降低 XSS 风险渲染输出面向 iframe 沙箱形成双重防线真值语义空数组视为假值不渲染区块与 Mustache 规范一致上下文栈区块会向栈中压入新上下文数组项或真值对象支持嵌套作用域与同名变量遮蔽容错未闭合标签按字面文本处理findMatchingEnd()支持同名区块的嵌套深度计数。3.4 推荐工作流提示词 packages/shared/src/prompts/system.ts 建议当来源提供了 HTML 模板时优先使用render_template而非手写transform_data脚本标准流程为通过 MCP 工具或 API 调用获取来源数据调用render_template传入 source slug、模板 ID 与整理好的数据将返回的路径填入html-preview代码块的src。模板清单可通过来源的guide.md中 Templates 一节查看。四、统一事件适配器架构多后端流式事件处理的收敛4.1 背景与动机v0.4.6 之前不同模型后端Claude、Codex、Copilot、Pi 等各自处理流式事件存在大量重复逻辑。本次重构把公共逻辑抽入基类BaseEventAdapter各后端实现自己的适配器Claude / Codex / Copilot并新增EventQueue保证事件按序投递。4.2BaseEventAdapter继承共享、子类实现分发抽象基类定义于 packages/shared/src/agent/backend/base-event-adapter.ts子类如ClaudeEventAdapter、PiEventAdapter见 packages/shared/src/agent/backend/index.ts只需实现adapt*()系列方法即可免费获得回合生命周期Turn LifecyclestartTurn()递增回合索引、清空共享状态并回调onTurnStart()钩子Block reason 追踪setBlockReason()/consumeBlockReason()用于权限拒绝类工具结果的事件还原Read 命令分类classifyReadCommand()借助parseReadCommand()将 bash 读取命令如cat、head归类为 Read 工具展示createReadToolStart()可生成带file_path/offset/limit的 Read 事件命令输出累积accumulateOutput()把流式输出增量拼接到最终工具结果事件构造助手createToolStart()/createToolResult()统一产出AgentEvent并携带turnId、parentToolUseId便于追踪MCP 工具名规范化buildMcpToolName()处理 pool serversources前缀剥离后的工具名还原避免mcp__sources__craft__search_spaces这类破坏来源查找的名称。4.3EventQueue面向异步子进程流的有序事件队列packages/shared/src/agent/backend/event-queue.ts 中的EventQueue是为 PiAgent 这类事件从子进程 JSONL 流异步到达的场景设计的区别于 ClaudeAgent 同步for-await循环。其协作模式为handler 调用 enqueue(event) → 推入队列并唤醒等待者 chat() 循环调用 drain() → 产出队列事件队列为空时挂起等待 handler 调用 complete() → 通知不再有新事件drain()返回(done: boolean)元组complete()置位done标记从而让消费循环明确区分暂时无事件与流已结束。配套测试见 packages/shared/src/agent/tests/base-event-adapter.test.ts 与 packages/shared/src/agent/tests/event-queue.test.ts。五、动态 Codex 模型发现从 app-server 到硬编码回退v0.4.6 为 Codex 后端引入了动态模型发现动态拉取从 Codex app-server 获取可用模型列表周期刷新按 30 分钟间隔定时刷新release notes 标注 commit 1bcb1083失败回退拉取失败时回退到硬编码模型注册表保证可用性多连接支持同一 provider 类型允许配置多个连接并通过唯一 slug 生成机制区分release notes 同时提及借此修复了并发会话下的环境变量竞争问题。从当前仓库的 packages/server-core/src/model-fetchers 目录结构anthropic.ts、bedrock-vertex.ts、registry.ts、runtime.ts看模型刷新机制已演化为更通用的ModelFetcher架构每个 fetcher 声明refreshIntervalMs例如 Anthropic 为 60 分钟Copilot 连接因受 GitHub 模型策略管控被服务端强制每 10 分钟刷新见 packages/server-core/src/model-fetchers/index.ts 中COPILOT_REFRESH_INTERVAL_MS与相关注释bedrock-vertex则refreshIntervalMs 0表示无周期刷新。刷新定时器按连接 slug 管理删除连接时通过getModelRefreshService().stopConnection(slug)停止见 packages/server-core/src/handlers/rpc/llm-connections.ts。连接认证类型方面packages/core/src/types/workspace.ts 定义了codex_oauthChatGPT Plus OAuth 经 Codex app-server与codex_api_key兼容 OpenRouter、Vercel AI Gateway两种 Codex 相关认证方式与 v0.4.6 的 Codex 支持一脉相承。六、批量会话操作上下文菜单v0.4.6 改进了多选交互在会话列表中按住多选multi-select后右键菜单会从单会话操作切换为批量操作集合包括状态Status批量设置会话状态标签Labels批量添加/移除标签标记Flag批量置顶/标记归档Archive批量归档删除Delete批量删除。这样避免了误将批量操作作用于单个会话显著提升大批量会话治理效率release notes 标注 commit 61759915。七、Bug 修复深度解读7.1 macOS 登录启动时会话历史为空#254问题根因是启动竞态SessionManager初始化尚未完成时GET_SESSIONS处理器返回了空结果。修复方案是引入基于 Promise 的初始化门闩initialization gate——GET_SESSIONS处理前先await初始化完成杜绝空列表。对应实现在 packages/server-core/src/sessions/SessionManager.ts 及 packages/server-core/src/domain/init-gate.ts。7.2 窗口无法从所有面板头部拖动#255应用菜单、会话列表面板、各面板头部此前拖拽区域drag region不一致。修复后这些头部区域具备统一的拖拽区窗口可从任意头部区域移动。7.3 Skills 自动激活依赖来源#249SKILL.md frontmatter 新增requiredSources字段技能可声明其依赖的来源 slug在 Agent 首轮对话前这些来源会被自动启用。字段类型定义于 packages/shared/src/skills/types.ts/** Optional source slugs to auto-enable when this skill is invoked */ requiredSources?: string[];相关校验逻辑见 packages/session-tools-core/src/validation.ts存储侧支持见 packages/shared/src/skills/storage.ts。7.4 聊天中文件链接不可点击csv、pdf、png 等文件类型此前未被链接点击处理器匹配。修复后扩展名列表改为派生自file-classification.tspackages/ui/src/lib/file-classification.ts使可点击类型与文件分类逻辑自动保持同步避免再次遗漏新类型。7.5source_test对有效 OAuth 令牌误报过期此前source_test直接依据令牌过期时间判断导致有效令牌被误报。修复后先尝试令牌刷新刷新失败才报告过期与实际连接管线的行为保持一致。7.6 中断响应导致 LLM 误解上下文被停止/重定向的部分响应内容现在会被注入一条上下文注记context note使模型不会把中断后的后续消息误读为对未完成内容的继续。7.7 每会话环境变量覆盖消除并发竞争此前使用全局可变的optionsEnv在并发会话中会导致ANTHROPIC_BASE_URL互相覆盖。修复以每会话envOverrides取代全局optionsEnv每个会话拥有独立的环境变量覆盖从根源消除竞争条件。7.8 其余修复工作流选择器与下拉框图标尺寸超限修复StyledDropdown与 workflow selector 组件的图标尺寸Windows Git Bash 路径不持久化检测到的CLAUDE_CODE_GIT_BASH_PATH现在会写入配置并在启动时恢复。八、改进与内部重构8.1TodoState→SessionStatus重命名跨 54 个文件统一了状态命名同时保留对既有 hook 配置的向后兼容并支持会话文件的迁移。8.2 统一事件适配器详见第四章除基类与队列外还包含后端专属适配器Claude、Codex、Copilot对应测试覆盖于 packages/shared/src/agent/tests。8.3 其他改进内容块间距优化聊天内容块之间视觉间距更合理commit a0402076transform 工具超时健壮性数据处理脚本的超时处理更稳健commit c03011b6Fast mode 特性开关迁移移入共享包跨包core / server / electron 等统一可用对应实现见 packages/shared/src/feature-flags.ts。九、升级与使用建议若要体验内联预览能力确认渲染端版本包含 MarkdownHtmlBlock.tsx / MarkdownPdfBlock.tsx 组件Agent 侧提示词已随 system.ts 同步更新使用 Source Templates 时模板文件务必放入sources/slug/templates/目录并写好元数据头render_template返回路径后配合html-preview使用涉及 Skills 依赖来源的在 SKILL.md frontmatter 中声明requiredSources即可免去手动启用升级后如遇并发会话环境变量异常请确认已使用新版每会话envOverrides机制修复 commit 1bcb1083。v0.4.6 的完整变更清单与对应 commit 摘要可查阅 apps/electron/resources/release-notes/0.4.6.md相邻版本的演进可参考 0.5.0.md 与 0.5.1.md。总体而言这一版本标志着 Craft Agents OSS 在富内容呈现与多后端事件处理架构两个方向上的关键转折为其后更复杂的渲染与多模型能力打下了基础。【免费下载链接】craft-agents-oss项目地址: https://gitcode.com/GitHub_Trending/cr/craft-agents-oss创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考