dev-browser 仓库开发指南:Rust CLI 与 Node.js Daemon 的构建、验证与 Bundle 嵌入机制
【免费下载链接】dev-browserA Claude Skill to give your agent the ability to use a web browser项目地址https://gitcode.com/gh_mirrors/dev/dev-browser点击查看免费下载本文是一份面向开发者的仓库协作指南基于 AGENTS.md仓库根目录下的 CLAUDE.md 同级文件整理。它说明了 dev-browser 项目的整体架构——一个由 Rust CLI、Node.js daemon 与 QuickJS 沙箱组成的浏览器自动化工具以及修改运行时代码时必须遵守的工具链约束、验证命令和 Bundle 重新打包流程。读完本文你将掌握daemon/与cli/两个子项目的职责边界、如何正确触发 TypeScript 与 Rust 的构建验证以及 daemon 代码被include_str!嵌入 Rust 二进制后重新生效的完整原理。仓库结构一份工程文件两个运行时AGENTS.md开篇即点明了本仓库的技术骨架This repository shipsdev-browser: a Rust CLI plus a Node.js daemon for browser automation with a QuickJS sandbox.dev-browser 对外表现为一条 CLI 命令内部则由两套运行时协作完成浏览器自动化Rust CLIcli/负责命令行参数解析、脚本读取、daemon 生命周期管理启动、探测、停止以及与 daemon 的进程间通信。Cargo.toml 中声明了clap参数解析、serde_json通信协议、dirs定位~/.dev-browser、interprocessWindows 命名管道等依赖见 cli/Cargo.toml。Node.js daemondaemon/后台进程真正管理浏览器实例、命名页面、CDP 连接并在 QuickJS WASM 沙箱中执行用户的 JavaScript 脚本。入口为 daemon/src/daemon.ts。而仓库根目录package.json、scripts/、bin 目录只承担打包胶水的角色npm 包发布、postinstall下载原生二进制见 scripts/postinstall.js、版本同步scripts/sync-version.js等。也就是说绝大多数运行时行为都集中在cli/与daemon/两个目录这是开发者在改动代码前必须建立的第一认知。工具链约定Node 管 daemon、Cargo 管 CLI禁止 BunAGENTS.md对工具链做了硬性规定违反它会破坏后续构建流程daemon/使用Node.js 生态工具链TypeScript、tsx、esbuild、vitest包管理使用pnpm见 daemon/package.json 中的packageManager: pnpm10.30.1与 pnpm-lock.yamlcli/使用CargoRust 标准工具链不要使用 Bun替代 Node.js。从 daemon/tsconfig.json 可以看到daemon 采用严格的 TypeScript 配置strict: true、noUncheckedIndexedAccess: true、NodeNext模块解析配合 daemon/vitest.config.ts 定义的src/**/*.test.ts测试发现规则整个 daemon 侧拥有一套完整可验证的单元测试体系测试用例分布在 daemon/src 各处例如idle-browser-reaper.test.ts、execute-request.test.ts、protocol.test.ts以及sandbox/__tests__/下的沙箱测试集。修改运行时代码前必须通过的验证AGENTS.md给出了三条必须在提交前执行的命令它们共同覆盖了 TypeScript 类型检查、JS 单元测试和 Rust 构建三条防线cd daemon npx tsc --noEmit cd daemon pnpm vitest run cd cli cargo buildnpx tsc --noEmit对 daemon 全量代码做类型检查使用 daemon/tsconfig.json 的严格配置不改写文件、只报错适合 CI 和提交前快检pnpm vitest run执行 daemon 侧全部单元测试。从源码看这些测试覆盖了浏览器管理器browser-manager-pages.test.ts、browser-manager-title-timeout.test.ts、空闲回收器idle-browser-reaper.test.ts、请求执行execute-request.test.ts、错误格式化format-error.test.ts、本地端点local-endpoint.test.ts、锁lock.test.ts、协议编解码protocol.test.ts以及沙箱侧的安全、文件 I/O、QuickJS host、Playwright API 桥接等主题cargo build编译 Rust CLI。仓库的 cli/rustfmt.toml 规定max_width 100、newline_style Unix提交 Rust 代码前同样建议遵循该格式。需要强调的是cd cli cargo build编译的并不是最新源码而是上一次打包的产物。这引出了本文最核心的机制——Bundle 嵌入。关键机制include_str!将 daemon Bundle 嵌入 Rust 二进制AGENTS.md明确警告了一个容易踩坑的事实cli/src/daemon.rsembedsdaemon/dist/daemon.bundle.mjsanddaemon/dist/sandbox-client.jsviainclude_str!, socargo buildonly sees the latest daemon changes after those bundles are regenerated.在 cli/src/daemon.rs 的顶部可以看到两行编译期嵌入const EMBEDDED_DAEMON: str include_str!(../../daemon/dist/daemon.bundle.mjs); const EMBEDDED_SANDBOX_CLIENT: str include_str!(../../daemon/dist/sandbox-client.js);include_str!是 Rust 的编译期宏它在编译时将指定文件的字符串内容直接写入二进制。这意味着你修改了daemon/src/下的 TypeScript 源码但没有重新打包daemon/dist/中的产物仍然是旧的此时执行cargo buildRust 编译器读到的还是旧字符串——新的 daemon 改动不会生效必须按AGENTS.md的指示先重新生成两个 Bundle再编译 Rust。这两个嵌入字符串的实际用途可以在 daemon.rs 的ensure_daemon_extracted与install_daemon_runtime中看到CLI 首次启动时会把它们写出到用户目录~/.dev-browser/下daemon.mjs、sandbox-client.js、内嵌的package.json再调用npm install与playwright install chromium安装运行依赖随后用node启动 daemon并通过 Unix socketLinux/macOS或命名管道Windows与它通信参见 cli/src/connection.rs。两个 Bundle 各自的生成命令当改动涉及 daemon 运行时代码时需要依次执行cd daemon pnpm bundle cd daemon pnpm bundle:sandbox-clientpnpm bundle打包 daemon 主程序该命令在 daemon/package.json 中定义使用 esbuild 将src/daemon.ts打成 ESM 单文件dist/daemon.bundle.mjsesbuild src/daemon.ts --bundle --platformnode --formatesm \ --outfiledist/daemon.bundle.mjs \ --external:playwright --external:quickjs-emscripten --external:jitl/*关键点在于--externalplaywright、quickjs-emscripten等重型依赖不被打进 Bundle而是保留为运行时import由前面写入~/.dev-browser/的package.json在npm install时安装。这与 daemon.rs 中内嵌的dev-browser-runtimepackage.json 声明的依赖版本playwright 1.58.2、quickjs-emscripten ^0.32.0严格对应也保证了嵌入代码与依赖版本的锁定关系。pnpm bundle:sandbox-client打包沙箱内运行的 Playwright 客户端该命令由 daemon/scripts/bundle-sandbox-client.ts 实现以src/sandbox/forked-client/bundle-entry.ts为入口打包为 IIFE 格式、全局名为__PlaywrightClient的dist/sandbox-client.jsplatform: neutral、target: es2022。这段脚本的注释揭示了一个非常容易踩雷的细节src/sandbox/forked-client/src/client/domCuaInjected.tsexports functions that are serialized withString(fn)and re-evaluated inside the page. Do not add flags that rewrite function bodies (minify, keepNames) — they would corrupt the serialized source.即domCuaInjected.ts中的部分函数会被String(fn)序列化后再注入页面执行如果打包时开启minify或keepNames等会改写函数体的选项就会破坏序列化后的源码导致 DOM 级 computer-use 工具失效。这是对 daemon/src/sandbox/forked-client 目录的维护者必须记住的硬约束。打包产物随后被 daemon/src/sandbox/quickjs-sandbox.ts 在运行时定位读取注入 QuickJS WASM 沙箱为沙箱内的脚本提供完整的 Playwright 客户端能力forked-client 源码位于 daemon/src/sandbox/forked-client/src/client。端到端流程一次 daemon 代码改动的完整生命周期结合AGENTS.md与源码一次涉及 daemon 运行时的改动应按以下顺序完成验证修改 daemon/src/ 下的 TypeScript 源码执行类型检查与单测cd daemon npx tsc --noEmit pnpm vitest run重新生成两个 Bundlecd daemon pnpm bundle pnpm bundle:sandbox-client编译 Rust CLIcd cli cargo build此时include_str!才读入最新产物若改动只涉及 CLI 侧cli/src/ 下的 Rust 代码则无需执行第 3 步直接cargo build即可。这套流程背后的设计意图是清晰的daemon 的 TypeScript 源码在生产环境并不直接运行而是先被 esbuild 压缩进dist/Bundle再由 Rust 编译期嵌入最终由 CLI 在用户机器上以node方式落地执行。理解这一源码 → Bundle →include_str!→ 二进制的链路是避免明明改了代码却不生效类问题的关键也是 AGENTS.md 作为仓库协作契约想传达的核心信息。赞分享【免费下载链接】dev-browserA Claude Skill to give your agent the ability to use a web browser项目地址https://gitcode.com/gh_mirrors/dev/dev-browser点击查看免费下载相关推荐rustc-dev-guide 开发指南构建、维护与同步 Rust 编译器文档仓库rustc dev guide 开发指南构建、维护与同步 Rust 编译器文档仓库 导读 rustc dev guide 是 rust lang 官方为 Ru编程语言编译器语言运行时标准库零构建嵌入 OpenUIopenuidev/browser-bundle 浏览器 IIFE 包完全指南零构建嵌入 OpenUIopenuidev/browser bundle 浏览器 IIFE 包完全指南 openuidev/browser bundle人工智能AI 应用前端UI组件GitHub CLI 发布流程深度解析cli/cli 的跨平台构建、签名、公证与包仓库发布机制GitHub CLI 发布流程深度解析cli/cli 的跨平台构建、签名、公证与包仓库发布机制 本文基于 cli/cli 仓库中的 docs/releaseCLI开发工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考