news 2026/9/19 19:09:49

background-agents贡献者指南:Monorepo测试策略、lint复杂度约束与代码规范

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
background-agents贡献者指南:Monorepo测试策略、lint复杂度约束与代码规范

background-agents贡献者指南:Monorepo测试策略、lint复杂度约束与代码规范

【免费下载链接】background-agentsAn open-source background agents coding system项目地址: https://gitcode.com/GitHub_Trending/ba/background-agents

background-agents 是一个开源的后台智能体(background agents)编码系统:你发出提示词后,AI 会话在云端沙箱中独立运行,你可以合上电脑,稍后回来审查 PR。本文带你完整走一遍这个 Monorepo 的贡献者指南——从环境搭建、三层测试策略,到两个自研 lint 检查脚本和代码规范,帮你快速提交第一个合格的 PR。

🧩 项目一览:Monorepo 结构速览

上图是 background-agents 的 Web 控制台:左侧是会话与自动化列表,右侧是向后台智能体下达任务的入口。

整个仓库采用 npm workspaces Monorepo 组织,核心包如下:

语言/框架职责
packages/control-planeTypeScript / Cloudflare Workers + Durable Objects会话生命周期、WebSocket 流、GitHub 集成
packages/webTypeScript / Next.js + React用户界面、OAuth、实时会话面板
packages/sandbox-runtimePython + JS沙箱内智能体运行时
packages/modal-infraPython 3.12 / Modal沙箱生命周期、快照、镜像构建
packages/sharedTypeScript共享类型、鉴权工具、模型定义
packages/slack-botTypeScript / Workers + HonoSlack、GitHub、Linear 三方触发器

架构上分为三层,通过 WebSocket 串联:Web 客户端 → Control Plane(会话中枢)→ Data Plane(Modal 沙箱)。改动前建议先通读 AGENTS.md 和 docs/HOW_IT_WORKS.md,两者包含完整的架构说明与依赖图。

🚀 环境搭建:一键安装与构建顺序

克隆仓库后,最快的上手路径:

git clone https://gitcode.com/GitHub_Trending/ba/background-agents cd background-agents bash .openinspect/setup.sh # 安装依赖、构建 shared 包、配置 husky 钩子

也可以手动执行分步操作(见 CONTRIBUTING.md):

npm install npm run build -w @open-inspect/shared # ⚠️ shared 必须最先构建 npm run typecheck npm run lint npm test

关键坑位@open-inspect/shared是其他所有包的依赖,改了共享类型后必须先构建它(根目录npm run typechecknpm run build已自动帮你处理了这个顺序,见 package.json)。环境要求 Node ≥ 22.13.0。

🧪 Monorepo 测试策略:三层布局

所有 TypeScript 包使用Vitest,Python 包使用pytest,测试文件位置各有约定:

单元测试:与源码同目录

  • control-plane 单测src/**/*.test.ts,运行在 Node 环境,配置见 packages/control-plane/vitest.config.ts
  • web / slack-bot / linear-bot:同样同目录src/**/*.test.ts
  • github-bot例外:单独放在test/*.test.ts
  • modal-infratests/test_*.py,配合 pytest-asyncio

按包运行测试非常直观:

npm test -w @open-inspect/control-plane # 单测 npm test -w @open-inspect/slack-bot cd packages/modal-infra && pytest tests/ -v # Python 侧

根目录 vitest.workspace.ts 把所有包的vitest.config.ts汇聚成一个工作区,一条npm test全仓库跑完。

集成测试:在真实 workerd 运行时里跑

control-plane 是本项目最重的部分,它另有一层集成测试:

npm run test:integration -w @open-inspect/control-plane

配置在 packages/control-plane/vitest.integration.config.ts,要点:

  • 通过@cloudflare/vitest-pool-workerscloudflareTest()插件,在真实 workerd 运行时中执行,并绑定真实 D1
  • terraform/d1/migrations/下的全部 SQL 迁移会自动应用,无需手工建表
  • pool-workers 按测试文件隔离 D1 存储;同一文件内的用例共享一个 D1 实例,因此务必在beforeEach/afterEach中调用cleanD1Tables()防止数据串染
  • 常用辅助函数在test/integration/helpers.tsinitSession()queryDO()seedEvents()

给新手的核心建议:涉及会话、调度、WebSocket 的改动,光写单测不够,补一个集成用例才能覆盖 Durable Object + D1 的真实行为。

Python 侧:pytest + ruff 双保险

cd packages/modal-infra && ruff check --fix && ruff format

Ruff 规则集中在 ruff.toml:目标 Python 3.12、行宽 100,启用了 bugbear、pyupgrade、type-checking 等规则组,测试文件额外豁免了部分规则。

🔍 Lint 复杂度约束:两个容易忽略的自研检查

除了标准的eslint .prettier,这个仓库还有两个自研 lint 脚本,CI 中都会执行:

lint:complexity —— 圈复杂度热区报告

npm run lint:complexity # 文本报告 npm run lint:complexity -- --json # 结构化报告

脚本 scripts/lint-complexity.mjs 用 ESLint 的complexity规则扫描全部packages/**/*.{ts,tsx},输出按复杂度排序的生产代码热区表。值得了解的三个设计决策:

  • 热区阈值 20:圈复杂度超过 20 的函数会被列入报告(见 scripts/lint-complexity.mjs)
  • 测试文件单独统计:测试代码不计入生产热区表,避免"为了凑覆盖率写出的大函数"污染报告
  • 仅报告、不阻断:复杂度发现不影响退出码——它是一份持续观察的技术债仪表盘,而不是硬门槛。提交大型重构前跑一次,可以看看自己碰的模块是否已是热区

lint:sql-portability —— 可移植 SQL 子集检查

npm run lint:sql-portability

scripts/lint-sql-portability.mjs 检查 control-plane 存储层的 SQL 是否踩了SQLite 专属语法(因为 Postgres 是计划中的新引擎,现在写一条 SQLite-only 语句,将来就要付出"迁移双胞胎"的代价)。被拦截的典型写法与可移植替代:

❌ 不要写✅ 请写成
INSERT OR IGNORE / REPLACEON CONFLICT DO NOTHING / DO UPDATE SET
?1?2编号占位符顺序?,按出现顺序绑定
unixepoch()strftime(...)在 TypeScript 里传Date.now()并格式化
json_object(...)等 JSON 函数在 TS 中构造 JSON 再作为参数绑定
AUTOINCREMENTCREATE TRIGGERPRAGMA应用层生成 ID / 在 store 里约束 / 留在引擎适配器中

完整子集与易错点说明见 docs/PORTABLE_SQL.md。

一个精巧的设计:历史遗留的例外被逐条登记在 scripts/sql-portability-baseline.json 中,写明具体文本与保留理由,数量采用棘轮机制——新增一处会失败,擅自删减一处也会失败,确保技术债清单始终诚实。

📏 代码规范与提交约定

命名规范:把单位写进名字里

AGENTS.md 中最重要的几条约定:

  • Python 用秒,TypeScript 用毫秒,与各自生态一致(Modal 的timeout=收秒,control-plane 全程_MS后缀)
  • 禁止裸用timeout:Python 写timeout_seconds,TypeScript 写timeoutMs/INACTIVITY_TIMEOUT_MS
  • 默认值只定义一次:抽成命名常量到处 import,注释里写Defaults to DEFAULT_SANDBOX_TIMEOUT_SECONDS而不是重复字面量Default: 7200
  • 顺手修坏味道:把一个既有字段穿进新代码路径时,若发现命名/单位本身有问题,就在同一次改动中修掉,而不是把问题扩散开

ESLint 关键规则

eslint.config.js 基于 typescript-eslint + React Hooks,几条会直接影响你代码的规则:

  • consistent-type-imports强制类型导入import type),npm run lint:fix可自动修复
  • no-unused-vars:下划线前缀的变量/参数被豁免
  • no-explicit-any:警告级,尽量避免any
  • no-restricted-imports鉴权相关符号必须从子路径导入,例如@open-inspect/shared/auth而非包根——这是有意维护的模块边界,报错信息会直接告诉你正确的导入路径

提交前记得用npm run lint:fix+npm run format,或者交给 husky:lint-staged 会在 pre-commit 阶段对暂存的 TS/TSX 自动执行eslint --fix+prettier --write,对 Python 文件执行ruff check --fix+ruff format(配置见 package.json)。

提交信息:Conventional Commits

使用规范化提交,主题行控制在72 字符以内,细节放 PR 描述而非 commit message:

feat: add new feature fix: resolve issue with X docs: update documentation refactor: restructure module chore: / test: ...

✅ 常见踩坑清单(提交 PR 前自查)

  1. 构建顺序:改了@open-inspect/shared却没先构建它,下游包的类型检查会满屏报错
  2. GitHub App 私钥格式:Cloudflare Workers 要求 PKCS#8,用openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt转换
  3. Durable Object 新绑定:需要两阶段 Terraform 部署(先enable_durable_object_bindings = false再置true
  4. 没有 wrangler.toml:control-plane 的配置由 Terraform 生成,仓库里查不到是正常的
  5. Modal 部署:在packages/modal-infra下先跑uv run python deploy.py --build-sandbox-image,再uv run modal deploy deploy.py,直接部署src/app.py不会导入任何函数模块

标准 PR 检查单npm test全绿 →npm run lint通过 →npm run typecheck通过 → 两个自研 lint 脚本通过 → 文档同步更新。CI 在每次推送与 PR 上都会执行 lint、typecheck 与全量测试,推送main还会按变更范围自动部署对应服务。

延伸阅读

  • 贡献流程与 PR 规范:CONTRIBUTING.md
  • 架构与会话生命周期:docs/HOW_IT_WORKS.md
  • 可移植 SQL 子集详解:docs/PORTABLE_SQL.md
  • Control Plane 测试与集成说明:packages/control-plane/README.md

准备好后,从docs:fix:类型的小 PR 开始,就是融入 background-agents 社区的最佳方式。

【免费下载链接】background-agentsAn open-source background agents coding system项目地址: https://gitcode.com/GitHub_Trending/ba/background-agents

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/19 18:31:55

Redis Linux部署与远程连接排查实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/19 19:08:30

Codex CLI下载与本地部署:接入Ollama本地大模型实战

本地跑AI编程助手这件事,我从去年就开始折腾,前后在Windows、macOS和一台Ubuntu服务器上都部署过一遍。标题里说的"Codex下载与本地部署",核心其实就是把Codex这个命令行编程代理装到自己的机器上,再决定是接云端模型还…

作者头像 李华
网站建设 2026/9/19 19:06:40

Vue3全局方法挂载方案对比与实践指南

1. 理解全局方法挂载的核心诉求在Vue3项目开发中,我们经常遇到需要全局访问某些方法或属性的场景。比如在非组件模块中调用路由跳转、在工具函数里触发全局提示、或者在跨组件逻辑中共享状态。传统的Vue2方案是通过Vue.prototype挂载,但在Composition AP…

作者头像 李华
网站建设 2026/9/19 19:09:38

WiFi CSI动作识别数据集全解析:从数据采集到深度学习应用

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/18 16:42:06

从矩阵分析到STM32:卡尔曼滤波工程落地指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华