Bilibili Evolved 仓库开发指南:面向编码 Agent 的 AGENTS.md 深度解读与实践
【免费下载链接】Bilibili-Evolved强大的哔哩哔哩增强脚本项目地址: https://gitcode.com/gh_mirrors/bi/Bilibili-Evolved
Bilibili Evolved 是一个基于 Web 前端技术构建的哔哩哔哩增强油猴脚本(userscript)。本文以仓库根目录的 AGENTS.md 为核心骨架,结合 CONTRIBUTING.md、开发服务源码与真实组件实现,系统讲解该仓库的项目结构、开发环境搭建、dev-server 调试协议、组件与插件编写规范、代码风格、验证流程以及分支与提交约定。阅读本文后,你将能够独立地在本地完成该仓库的开发环境配置,正确区分"组件"与"插件"的定位,使用命令行与 WebSocket 驱动 dev-server 完成功能编译、监听、调试与脚手架创建,并通过pnpm run type、pnpm run lint-check等命令通过代码检查,最终以preview-features/preview-fixes为基准确发起 Pull Request。
AGENTS.md 在仓库中的定位
AGENTS.md 是给编码 Agent 的仓库级专项指导文件。它在文档体系中处于"第二步"的位置:先阅读 CONTRIBUTING.md 了解贡献全流程,再把 AGENTS.md 作为实现与验证阶段的实操清单。
两者的分工可以概括为:
- CONTRIBUTING.md:面向人类的完整贡献指南,覆盖环境搭建、Tampermonkey 本地调试脚本配置、本体/组件/插件的开发与新增流程、可用 API 资源、代码检查与 PR 提交。
- AGENTS.md:面向 AI 编码 Agent 的精简检查单,用更结构化的条目把项目结构、命令、规范、验证标准浓缩成可执行的约束。
因此,任何在本仓库执行修改任务的 Agent,都应先通过 CONTRIBUTING.md 建立全局认知,再逐条对照 AGENTS.md 的清单落地实现。
项目结构:理解三个代码区的职责边界
AGENTS.md 首先明确了仓库的顶层布局,核心是理解"本体"与"功能"分离的架构:
src/:油猴脚本本体(userscript core),包含内置组件、共享运行时 API、设置 UI,以及随主脚本一起发布的代码。开发时会在dist/下生成开发版脚本bilibili-evolved.dev.user.js。registry/lib/components/:可安装组件(installable components)源码。新组件应放入对应的类别目录(如feeds/、live/、style/、touch/、utils/、video/),并以index.ts作为 webpack 编译入口——webpack 配置会搜索所有index.ts作为组件入口,该文件名不可更改。registry/lib/plugins/:插件源码。当某个功能只有作为另一个组件的扩展才有意义时,应实现为插件而非组件。registry/lib/docs/third-party.ts:第三方组件登记入口。希望保持独立于主仓库的组件,通过向该文件中的数组追加信息来注册,而不是把外部组件注册逻辑混入仓库内源码修改。dist/与registry/dist/:构建产物。开发分支不应保留生成的 dist 文件;preview、master、master-cdn等发布输出分支的产物由 CI 构建产生。doc/features/:由元数据生成的功能文档输出。仅在任务明确涉及生成文档或发布准备时才更新,普通功能或修复 PR 中不要手动修改。
从实现看,src/components/下也有一部分组件(如define.ts、types.ts),这些是内置组件,无法独立安装/卸载;真正可独立安装卸载的组件都在registry/lib/components/下。这一区分是理解"本体 vs 功能"的关键。
开发环境搭建与常用命令
环境前提与依赖安装
根据 CONTRIBUTING.md,环境需要 Node.js(>= 14.0)、Visual Studio Code 与 pnpm(>= 8.9.0)。AGENTS.md 强调包管理器是pnpm(根目录 package.json 中packageManager锁定为pnpm@10.3.0),并给出两条安装命令:
# 安装根目录依赖(本体) pnpm install # 构建 registry 功能时需要安装 registry 依赖 cd registry && pnpm install当对任务命令存疑时,以.vscode/tasks.json中定义的 VS Code Tasks 为本地任务命令的事实来源(npm scripts 仅用于 CI)。
常用命令速查
AGENTS.md 列出的常用命令如下,它们在根目录 package.json 的scripts中均有对应实现:
# TypeScript 类型检查(对应 scripts.type: tsc -p tsconfig.type-check.json --noEmit) pnpm run type # ESLint 风格检查(对应 scripts.lint-check: eslint . --ext .ts,.vue) pnpm run lint-check # 启动开发服务(核心 watcher + WebSocket + HTTP) pnpm tsx dev-tools/dev-server/index.ts # 查询当前被监听的功能会话 pnpm tsx dev-tools/dev-server/command.ts sessions # 优雅关闭开发服务 pnpm tsx dev-tools/dev-server/command.ts shutdown其中pnpm tsx dev-tools/dev-server/index.ts的启动逻辑见 dev-tools/dev-server/index.ts:依次启动 HTTP 服务器、核心 watcher(自动编译开发版本体)与 WebSocket 服务器。启动成功后终端会输出类似:
DevServer 已启动, 端口: 23333 本体编译中... (...可能有一长串输出) 本体已编译: (一段 hash)Dev Server 深入:HTTP、WebSocket 与 CLI 三条通道
开发服务是本地调试的核心设施,dev-tools/dev-server/README.md 给出了完整协议说明。它通过三条通道协同工作:
HTTP:静态资源与虚拟编译 URL
HTTP 服务器只为本体产物服务根目录静态文件:dist/*映射到核心 userscript 输出。
registry/dist/components/<id>.js与registry/dist/plugins/<id>.js是虚拟输出 URL:当内存中缺少对应产物时触发按需编译(build-on-request),随后从内存返回编译结果;其他/registry/*路径不从磁盘提供。HTTP 不暴露控制 API,所有控制能力都走 WebSocket。
WebSocket:命令与事件控制面
默认地址为ws://localhost:23333(端口见 dev-tools/dev-server/config.ts 中的默认值23333)。客户端可发送以下命令载荷(完整类型定义见 dev-tools/dev-server/payload.ts):
{ "type": "queryFeatureSessions" }{ "type": "shutdownServer", "requestId": "..." }{ "type": "buildFeature", "kind": "component", "id": "style/hide/banner", "requestId": "..." }{ "type": "startFeatureSession", "kind": "plugin", "id": "video/player/speed", "requestId": "..." }{ "type": "stopFeatureSession", "kind": "component", "id": "style/hide/banner", "requestId": "..." }{ "type": "startDebugFeature", "kind": "component", "id": "style/hide/banner", "targetClientId": "dev-client-1", "requestId": "..." }{ "type": "createFeature", "kind": "component", "id": "style/my-feature", "name": "myFeature", "displayName": "My Feature", "authorName": "Author Name", "authorLink": "https://example.com", "description": "Feature description.", "requestId": "..." }服务器侧会推送以下事件:
serverReady:连接建立时的初始事件,携带clientId与当前激活的featureSessions。featureSessionsChanged:被监听的功能路径发生变化。itemUpdate:被监听功能编译完成,DevClient 应进行更新。featureBuilt:显式构建或监听构建完成。featureBuildFailed:显式构建失败。serverStop:服务器正在关闭,DevClient 应恢复 dev URL 并关闭 socket。commandResult:针对带requestId命令的响应。
CLI:command.ts 命令行客户端
不需要手写 WebSocket 客户端时,直接使用命令客户端(开发服务运行期间):
pnpm tsx dev-tools/dev-server/command.ts sessions pnpm tsx dev-tools/dev-server/command.ts build component style/hide/banner pnpm tsx dev-tools/dev-server/command.ts watch plugin video/player/speed pnpm tsx dev-tools/dev-server/command.ts stop component style/hide/banner pnpm tsx dev-tools/dev-server/command.ts start-debug component style/hide/banner dev-client-1 pnpm tsx dev-tools/dev-server/command.ts stop-debug component style/hide/banner pnpm tsx dev-tools/dev-server/command.ts shutdown各命令的参数细节在 dev-tools/dev-server/command.ts 中有完整实现与用法输出:
build <component|plugin> <id> [development|production]:单功能编译,第二个可选参数决定 development 还是 production 模式,其余值一律视为 development。watch <component|plugin> <id>:启动监听会话,代码改动后自动重编译。stop <component|plugin> <id>:停止监听会话。start-debug <component|plugin> <id> [targetClientId]:将编译产物定向推送给指定clientId的 DevClient 进行页面调试。stop-debug <component|plugin> <id>:结束调试会话。sessions:列出当前所有被监听的功能会话。shutdown:优雅关闭整个开发服务。create <component|plugin> <id> <name> <displayName> <authorName> [authorLink] [description]:创建功能脚手架(见下文)。
shutdown命令会先响应命令客户端,广播serverStop,再依次关闭核心 watcher、功能 watcher、WebSocket 连接与 HTTP 服务器,因此完成开发后应使用它退出,而不是手动结束 Node.js 子进程。
配置项:dev/dev-server.json
dev-tools/dev-server/config.ts 展示了配置合并逻辑:默认值{ port: 23333, maxWatchers: 16 }与可选文件dev/dev-server.json中的配置做浅合并,后者可覆盖前者。也就是说,可以通过在仓库根目录创建dev/dev-server.json自定义端口与最大 watcher 数,例如:
{ "port": 23333, "maxWatchers": 16 }组件与插件编写规范
AGENTS.md 对组件与插件的编写给出了明确约束,下面逐条结合源码展开。
用 defineComponentMetadata 定义组件
组件必须通过defineComponentMetadata定义并导出component对象。src/components/define.ts 中该函数只是一个泛型恒等函数,作用是让 TypeScript 根据ComponentMetadata类型对元数据做静态校验。一个真实的组件示例是 registry/lib/components/feeds/filter/index.ts 中的feedsFilter(动态过滤器):
export const component = defineComponentMetadata({ name: 'feedsFilter', displayName: '动态过滤器', entry, tags: [componentsTags.feeds], options, reload: () => document.body.classList.remove('disable-feeds-filter'), unload: () => document.body.classList.add('disable-feeds-filter'), urlInclude: [/^https:\/\/t\.bilibili\.com\/$/], plugin: feedsFilterPlugin, })插件则遵循PluginMetadata接口,导出plugin对象(src/plugins/plugin.ts),例如setup函数作为插件初始化入口。AGENTS.md 要求:registry/lib/plugins/下的代码遵循既有插件定义模式。
关键元数据与生命周期约定
author必填:新组件必须包含author元数据,通常是 GitHub 用户名与主页地址;如需注明 AI 辅助开发,author可以是数组,追加 AI 名称与官网。- 命名规范:
name应具体且使用 camelCase;displayName与选项名应清晰描述功能,避免通用标签。 index.md即描述:若组件带index.md,编译时其内容会自动注入description,除非该组件的既有模式要求,否则不要在元数据中重复编写相同描述。- 页面匹配用
urlInclude/urlExclude:不要在手写entry中重复进行页面判断。上述动态过滤器就用urlInclude: [/^https:\/\/t\.bilibili\.com\/$/]限定仅作用于动态首页。 entry只做启动必要工作:保持entry专注于组件启动时必须完成的事。- 清理逻辑放
unload:不要依赖entry的返回值做清理。需要支持"关闭/重新开启"实时生效的组件,必须让reload与unload成对出现。 - 选项定义:遵循既有
defineOptionsMetadata与options模式(见 src/components/types.ts 中OptionsMetadata类型),让默认值、标签与校验器与元数据保持一处定义;互斥的多选布尔项应建模为单一选项(enum 或下拉)。
样式规范
- 固定的组件样式放入 SCSS 文件,不要在业务逻辑中拼接样式字符串。
- 使用
instantStyles、styledComponentEntry或toggleStyle,保证样式只在预期时机生效。 - 编写 SCSS 前先查找共享 Sass 文件:
ui/_common.scss可通过@import "common"引入,提供全屏、居中之类的通用 mixin。 - 当设置需要控制 CSS 时,优先在
html或body上切换 class,再针对该 class 编写 SCSS。
创建新功能的脚手架
create命令会调用 dev-tools/dev-server/scaffold.ts 中的createFeature:校验 ID 合法性(拒绝空值、以/开头、包含..或绝对路径),在registry/lib/components/<id>(或registry/lib/plugins/<id>)下创建目录,并生成index.ts与index.md。生成的组件模板自带defineComponentMetadata骨架、tags(自动取 ID 首段映射为分类标签)、author字段;插件模板则导出带setup的PluginMetadata。因此,新增功能的正确姿势是:先create生成骨架,再填充业务逻辑与选项。
代码风格约定
AGENTS.md 的 Code Style 章节对代码风格提出具体要求,均与仓库的 ESLint(airbnb-base 扩展)与 Prettier 配置对应:
- 遵循仓库的 ESLint 与 Prettier 配置。
- 除既有 ESLint overrides 覆盖的文件(如 Vue 单文件组件与构建相关文件)外,使用具名导出。
- 控制流语句体保持花括号包裹。
- 保留所修改代码周边的既有 TypeScript、Vue 2 与 SCSS 约定(项目当前基于 Vue 2.7,见 package.json 依赖)。
- 避免不必要的防御性分支、空错误处理、重复状态与一次性抽象。
- 优先复用既有的 Bilibili API 封装、请求辅助、设置辅助、observer 工具、样式工具与 UI 组件,而不是重新实现等价行为。
- 能通过稳定 Bilibili API 与既有封装获得数据时,不要读取页面内部全局变量或框架内部实现。
- DOM 选择器作用域应限定在最近的稳定父类或页面区域,避免命中无关 B 站 UI 的宽泛选择器。
- 名称与类型必须与行为一致:若函数开始返回更宽泛的形状,应更新类型与名称,而不是重载一个误导性契约。
- 谨慎对待数据单位与 API 失败态:不要把失败请求当作成功值缓存;字节、比特、数量、ID 与 URL 的语义要保持明确。
验证流程:本地检查与 CI 生产构建的分工
AGENTS.md 要求按变更的风险与范围选择验证方式:
- 类型检查:
pnpm run type。 - 风格检查:
pnpm run lint-check(可自动修复的问题也可运行pnpm run lint)。 - 本体核心修改:使用 dev-server 的核心 watcher,它会自动编译开发版本体。
- registry 功能修改:dev-server 运行期间执行
pnpm tsx dev-tools/dev-server/command.ts build <component|plugin> <id>。 - dev-server 自身 TypeScript 修改:
pnpm exec tsc -p dev-tools/dev-server/tsconfig.json。 - 浏览器行为验证:用本地 userscript 在真实浏览器中验证改动后的功能。
- 依赖 API 形状或 B 站灰度变化:记录实际自测的页面与账号状态。
此外,CONTRIBUTING.md 补充了 PR 文件检查命令pnpm run check-pr-files(对应 dev-tools/pr-check/ 实现),用于发现提交构建产物、手动编辑生成的功能文档、组件/插件描述文件缺失、reload/unload未成对等常见 PR 结构问题。
CI 生产构建不要作为常规本地验证重复执行。PR 的 CI 工作流会依次运行:pnpm run type→pnpm run lint-check→pnpm run build-core→ 在registry/安装依赖 →pnpm run build-features。仅在显式要求复现 CI 失败、改动共享构建基础设施或准备发布时,才在本地执行这些生产构建。
当改动影响页面行为时,还需打开浏览器控制台检查新增运行时错误,并在受影响的页面类型(视频、番剧、直播、动态、空间、设置面板等)上实测。
分支与提交约定
AGENTS.md 的 Branches And Commits 章节是提交前必须遵守的约定:
- 新功能以
preview-features为基线分支。 - Bug 修复以
preview-fixes为基线分支。 - commit message只需清晰描述改动;仓库不强求严格的 conventional commit 格式(CONTRIBUTING.md 也明确中英文随意、不做 commitlint 强校验)。
- 不要创建 release tag、推送发布分支或执行发布步骤,除非任务明确与发布相关。
- 提交仅含源代码修改,不要把
dist/或registry/dist/产物、无关缓存、profile、本地调试或包管理器输出文件提交上去。
面向 Agent 的实操自检清单
综合 AGENTS.md 全部章节,一个编码 Agent 在本仓库完成任务时应按如下顺序自检:
- 已通读 CONTRIBUTING.md,并按需阅读 dev-tools/dev-server/README.md 理解协议细节。
- 正确判断改动落点:本体在
src/,可安装组件在registry/lib/components/,扩展性插件在registry/lib/plugins/,第三方独立组件走 registry/lib/docs/third-party.ts。 - 组件/插件均以
index.ts为 webpack 入口,用defineComponentMetadata/PluginMetadata定义,author齐全,命名具体清晰,index.md描述不重复。 - 生命周期正确:
entry只做启动工作,页面匹配交给urlInclude/urlExclude,清理放unload,需要热开关时reload/unload成对。 - 样式进入 SCSS 并复用共享 mixin,设置控制 CSS 时用 html/body 上的 class 开关。
- 代码风格与类型契约符合仓库约定,不引入宽泛选择器与误导性命名。
- 验证按风险分级执行:
pnpm run type、pnpm run lint-check,必要时通过 dev-server 的build/watch/start-debug驱动功能编译,并在真实浏览器与对应页面类型中实测。 - 不手动改生成文件、不提交构建产物,分支基于
preview-features或preview-fixes,commit message 清晰描述改动。
【免费下载链接】Bilibili-Evolved强大的哔哩哔哩增强脚本项目地址: https://gitcode.com/gh_mirrors/bi/Bilibili-Evolved
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考