Hotdry.
systems

一人加一智能体从零构建浏览器:72 小时 20K LOC 的工程实践

剖析在零第三方依赖约束下,如何用 Rust 从零实现一个支持多平台的浏览器内核,涵盖布局引擎架构、平台抽象层设计与人机协作工作流。

当一位工程师决定用 72 小时构建一个完整浏览器,并且全程只有一个智能体辅助时会发生什么?答案是一个约 20K 行代码的项目,它能够渲染 HTML 和 CSS,支持三大桌面平台,甚至能处理滚动、后退等交互。这个名为 one-agent-one-browser 的实验,不仅证明了人机协作在复杂系统工程中的可行性,更揭示了浏览器内核各个模块的工程化参数与实现权衡。

项目约束与设计边界

项目在启动之初就设定了几条硬性约束,这些约束直接塑造了最终的代码形态。首先是零第三方依赖原则 —— 这意味着不能使用诸如 html5ever、cssparser、curl-sys 等现成库,所有网络请求、HTML 解析、CSS 处理都必须从零实现。这一决策的背后逻辑是避免智能体在依赖版本兼容性问题中消耗时间,同时让生成的代码能够直接使用操作系统原生提供的功能。Rust 的标准库在网络、文件 I/O、字符串处理方面的能力被充分挖掘,而操作系统层面的图形绘制则通过平台原生 API 实现:Linux 上使用 X11 + Xft 字体渲染,macOS 上使用 Core Graphics 与 AppKit,Windows 上则调用 GDI/DirectWrite/Direct2D/D3D。

第二个关键约束是跨平台兼容性。项目要求同一个代码库能够编译运行于 Windows、macOS 和常见 Linux 发行版。这意味着必须在代码结构中精心设计平台抽象层,将平台相关的绘制、窗口管理、字体渲染、网络请求等逻辑隔离到独立模块。从代码统计可以看到,平台相关代码占据了相当比例:src/platform/x11/ 目录下有 xlib.rs、xft.rs、cairo.rs 等文件,src/platform/windows/ 下有 d2d.rs、dwrite.rs、gdi.rs、wic.rs 等,而 src/platform/macos/ 下则有 painter.rs、windowed.rs、svg.rs 等。每个平台模块都实现了统一的 Trait 接口,由上层布局与渲染逻辑调用。

布局引擎:浏览器最复杂的子系统

从代码行数来看,布局模块是整个项目中规模最大的部分。src/layout/flex.rs 有 994 行,src/layout/inline.rs 有 933 行,src/layout/mod.rs 有 910 行,这三个文件合计近 3000 行代码,占整个项目代码量的约 15%。布局引擎之所以复杂,是因为它需要将 HTML 的树状结构转换为二维平面上的矩形框布局,这涉及样式计算、盒模型构建、文本排版、浮动元素处理、表格布局等多层逻辑。

Flex 布局是现代浏览器最重要的布局方式之一,代码中实现了完整的 flex 容器与 flex 项处理逻辑。flex.rs 文件需要处理 flex-direction、flex-wrap、justify-content、align-items、align-content 等属性,计算 flex 项的主轴尺寸与交叉轴尺寸,处理 flex-grow、flex-shrink、flex-basis 等弹性缩放逻辑。当容器空间不足时,需要根据各项目的 shrink 因子计算收缩比例;当容器空间有余时,需要根据 grow 因子分配剩余空间。这些计算涉及多次遍历与浮点运算,任何一处精度问题都可能导致布局错乱。

Inline 布局处理行内文本与行内元素的排版,是实现段落、标题、行内样式的核心模块。inline.rs 需要处理文本的换行逻辑,包括基于字符的换行、基于单词边界的换行、基于断行机会点的换行。行高的计算涉及行内框的高度叠加、基线对齐、行距调整。inline 布局还必须处理行内块元素(inline-block)的宽度高度计算,以及行内元素的垂直对齐方式。

除了 flex 与 inline,项目还实现了 floats.rs(浮动布局)、table.rs(表格布局)、replaced.rs(可替换元素如图片的布局)。表格布局需要处理列宽计算、单元格合并、行列交叉等复杂逻辑;浮动布局需要处理浮动元素的脱离文档流以及后续元素围绕浮动元素的环绕;可替换元素则需要根据元素的固有尺寸与 CSS 宽高属性计算最终的盒子尺寸。

样式系统:从 CSS 文本到计算值

CSS 处理是另一个关键子系统。src/css.rs 有 423 行代码用于 CSS 解析,再加上 src/style/parse.rs、src/style/computer.rs、src/style/builder.rs、src/style/declarations.rs、src/style/mod.rs 等文件,整个样式系统的代码量相当可观。CSS 解析器需要将 CSS 文本转换为抽象语法树(AST),处理选择器、属性名、属性值、优先级等语法元素。src/style/selectors.rs 有 123 行用于选择器匹配,需要实现类选择器、ID 选择器、标签选择器、属性选择器、伪类选择器等功能。

样式计算是样式系统的核心步骤。src/style/computer.rs 有 279 行代码,负责将声明性的 CSS 属性值转换为具体的布局数值。这包括将 em、rem、百分比、vw、vh 等相对单位转换为绝对像素值,处理 inherit、initial、unset 等继承关键字,应用层叠规则解决样式冲突。样式计算的结果被存储在 ComputedStyle 结构体中,供布局引擎使用。src/style/custom_properties.rs 有 186 行处理 CSS 自定义属性(CSS 变量)的解析与计算。

平台抽象:同一套代码,三套实现

浏览器内核的一个核心挑战是如何在不同操作系统上提供一致的图形输出。项目采用了典型的平台抽象模式:定义统一的 Trait 接口,在 platform/mod.rs 中声明,然后在各个平台子目录下提供具体实现。以 Painter Trait 为例,它声明了 draw_rect、draw_text、draw_image 等方法,X11 实现使用 Cairo 库(注意:这里使用的是系统级 Cairo,而非 Rust 依赖)、macOS 实现使用 Core Graphics,Windows 实现可以使用 GDI 或 Direct2D/Direct3D。

窗口管理同样如此。src/platform/x11/mod.rs、src/platform/windows/windowed.rs、src/platform/macos/windowed.rs 分别实现了各自系统上的窗口创建、事件循环、输入处理。src/platform/x11/xlib.rs 有 278 行,直接调用 Xlib C 接口获取键盘事件、鼠标事件、窗口大小变化事件。macOS 上使用了 AppKit 的 NSWindow 与 NSView,Windows 上则使用了 Win32 API 的 CreateWindowEx 与消息泵。

网络模块也遵循同样的模式。src/net/curl.rs 使用 curl 库处理 Linux 上的 HTTP 请求,src/net/winhttp.rs 使用 Windows HTTP API(WinHTTP)处理 Windows 上的网络请求,macOS 则可以使用系统自带的 CFNetwork 或 URLSession。网络请求的实现包括 DNS 解析、TLS 握手、HTTP 请求构建、响应解析、连接池管理等功能。src/net/pool.rs 有 129 行专门处理连接池,用于复用 TCP 连接以提升性能。

人机协作工作流:智能体的边界与人类的判断

这个项目的另一个值得关注之处是其人机协作模式。工程师在整个项目中扮演的是架构设计者、任务分配者、质量把关者的角色,而智能体(使用 OpenAI Codex)则负责具体的代码生成工作。工作流程大致如下:工程师首先确定功能需求与验收标准,然后让智能体根据需求生成代码,编译运行后通过截图比对的方式验证效果,如果发现问题则将错误信息或截图反馈给智能体进行修正。

智能体在生成代码时遵循几个关键指令:每个源文件不得超过 1000 行代码,以确保人类能够完整阅读理解;代码必须始终可编译可运行,不能出现长时间的红状态;使用操作系统原生提供的功能,不引入新的 Rust 依赖。这种约束有效避免了智能体生成难以维护的代码,也使得项目的代码结构保持清晰。

从结果来看,这种一人加一智能体的模式在 72 小时内生成了约 20K 行有效代码,覆盖了从 HTML 解析到图形渲染的完整链路。工程师在事后总结中提到,智能体能够在单一代码库上连续工作数小时,产出的代码质量虽然不算优秀,但完全可用。更重要的是,人类的判断在架构决策、接口设计、问题定位等环节发挥了不可替代的作用 —— 当智能体陷入局部最优时,人类能够提供全局视角的指导。

工程参数与可复现要素

从项目中可以提炼出几个可复用的工程参数。文件粒度控制在 1000 行以内,这一约束使得每个模块的复杂度保持在人类可处理的范围内。72 小时的总时间窗口、每日迭代的节奏、以及截图比对测试的引入,都为项目按时交付提供了保障。平台抽象层的接口设计遵循了 Rust 的 Trait 哲学,使得添加新平台支持变得相对简单。

如果你想复现这个实验,以下参数值得参考:每个功能模块的代码量目标设定在 500-1000 行;使用截图比对作为 E2E 测试的主要手段;设置 headless 模式以便于自动化测试;将网络请求、图形绘制、窗口管理作为平台抽象的第一批目标。从零构建浏览器是一个复杂度极高的系统工程,但这个项目证明了在正确的约束下,一人加一智能体能够在可接受的时间内完成有意义的实现。

资料来源:https://emsh.cat/one-human-one-agent-one-browser/、https://github.com/embedding-shapes/one-agent-one-browser

查看归档