9.2 KiB
9.2 KiB
AGENTS.md
本文件面向两类协作者:
- 手写代码的人类朋友
- 会在此仓库中协助开发的 AI Agents
这个项目以手写为主,欢迎协作,但请先理解这里的约束和结构,再开始改动。
项目定位
- 这是一个娱乐性质的、私域使用的 QQ Bot 项目。
- 虽然主要用于熟人环境,但依然要按“不信任输入”的标准写代码。
- 不要因为使用场景偏内部,就默认消息内容、安全边界、调用参数一定可靠。
基本原则
1. 默认不信任用户输入
所有来自聊天消息、命令参数、平台事件等的输入,都应视为不可信。
开发时至少注意以下几点:
- 不假设输入类型正确,先校验再使用。
- 不假设输入长度合理,注意超长文本、大量参数、异常嵌套结构。
- 不假设输入内容安全,避免直接拼接到文件路径、SQL、shell 参数、HTML 或模板中。
- 不假设用户一定按预期使用命令,错误输入要能优雅失败。
- 对任何外部请求、文件读写、渲染、执行型逻辑,都要先考虑滥用风险。
2. 优先保持现有风格
- 这是一个以人工维护为主的项目,改动应尽量贴近现有写法。
- 除非有明确收益,不要为了“看起来更现代”而大规模重构。
- 新增能力时,优先复用已有通用模块,而不是重复造轮子。
3. 小步修改,影响清晰
- 尽量做局部、明确、可解释的改动。
- 修改插件时,避免顺手改动无关插件。
- 如果要调整公共模块,先确认是否会影响大量插件行为。
仓库结构
konabot/
核心代码目录。
konabot/common/
通用模块目录。
- 放置可复用的基础能力、工具模块、公共逻辑。
- 如果某段逻辑可能被多个插件共享,应优先考虑放到这里。
- 修改这里的代码时,要额外关注兼容性,因为它可能被很多插件依赖。
konabot/docs/
Bot 内部文档系统使用的文档目录。
- 这是给用户看的文档来源。
- 文档会通过
man指令被触发和展示。 - 虽然文档文件通常使用
.txt后缀,但内容可以按 markdown 风格书写。 .md后缀文件会被忽略,因此.md更适合只留给仓库维护者阅读的附加说明。- 文档文件名就是用户查询时使用的指令名,应保持简洁、稳定、易理解。
补充说明:
konabot/docs/user/是直接面向用户检索的文档。konabot/docs/lib/更偏向维护者参考。konabot/docs/concepts/用于记录概念。konabot/docs/sys/用于特定范围可见的系统文档。
konabot/plugins/
插件目录。
- 插件数量很多,是本项目最主要的功能承载位置。
- 插件可以是单文件,也可以是文件夹形式。
- 新增插件或修改插件时,请先观察相邻插件的组织方式,再决定采用单文件还是目录结构。
- 如果逻辑已经明显超出单文件可维护范围,应拆成目录插件,不要把一个文件堆得过大。
根目录文档
docs/
仓库根目录下的 docs/ 主要用于记录一些可以通用的模块说明和开发文档。
- 这里的内容主要面向开发和维护。
- 适合放公共模块说明、集成说明、配置说明、开发笔记。
- 不要把面向
man指令直接展示给用户的文档放到这里;那类内容应放在konabot/docs/下。
对 AI Agents 的具体要求
如果你是 AI Agent,请遵守以下约定:
修改前
- 先阅读将要修改的文件以及相关上下文,不要只凭文件名猜用途。
- 先判断目标逻辑属于公共模块、用户文档,还是某个具体插件。
- 如果需求可以在局部完成,就不要扩大改动范围。
修改时
- 优先延续现有命名、目录结构和编码风格。
- 不要因为“顺手”而批量格式化整个项目。
- 不要擅自重命名大量文件、移动目录、替换现有架构。
- 涉及用户输入、路径、网络、数据库、渲染时,主动补上必要的校验与防御。
- 如果要新增
konabot/common/或其他会被多处依赖的模块,优先考虑 NoneBot2 框架下的依赖注入方式,而不是把全局状态或硬编码依赖散落到调用方。 - 写文档时,区分清楚是给
man系统看的,还是给仓库维护者看的。
修改后
- 检查改动是否误伤其他插件或公共模块。
- 如果新增了用户可见功能,考虑是否需要补充
konabot/docs/下对应文档。 - 如果新增或调整了通用能力,考虑是否需要补充根目录
docs/下的说明。
插件开发建议
- 单个插件内部优先保持自洽,不要把特定业务逻辑过早抽成公共模块。
- 当多个插件开始重复同类逻辑时,再考虑上移到
konabot/common/。 - 插件应尽量对异常输入有稳定反馈,而不是直接抛出难理解的错误。
- 如果插件会访问外部服务,要考虑超时、失败降级和返回内容校验。
最基本的用户交互书写建议
- 先用清晰、可收敛的规则匹配消息,再进入处理逻辑,不要一上来就在 handler 里兜底解析所有输入。
- 在 handler 里尽早提取纯文本、拆分命令和参数,并对缺失参数、非法参数、异常格式给出稳定反馈。
- 如果用户输入只允许有限枚举值,先定义允许集合,再进行归一化和校验。
- 输出优先保持简单直接;能一句话说明问题时,不要返回难懂的异常堆栈或过度技术化提示。
- 涉及渲染、网络请求、图片生成等较重操作时,先确认输入合理,再执行昂贵逻辑。
- 如果插件只是做单一交互,优先保持 handler 简短,把渲染、请求、转换等逻辑拆成独立函数。
- 倾向于使用
UniMessage/UniMsg这一套消息抽象来组织收发消息,而不是把平台细节和文本拼接散落在各处。 - 倾向于显式构造返回消息并发送,而不是大量依赖 NoneBot2 原生的
.finish()作为主要输出路径,除非该场景确实更简单清晰。
关于公共能力的依赖方式
- 新建通用能力时,优先设计成可注入、可替换、可测试的接口。
- 如果一个模块未来可能被多个插件依赖,优先考虑 NoneBot2 的依赖注入,而不是让调用方手动维护重复的初始化流程。
- 除非确有必要,不要让插件直接依赖隐藏的全局副作用。
- 如果使用单例、缓存或全局管理器,要明确其生命周期、并发行为以及关闭时机。
运行环境与部署限制
这个项目默认会跑在 Docker 环境里,修改功能时请先意识到运行环境不是一台“什么都有”的开发机。
容器环境
- 运行时基础镜像是
python:3.13-slim,不是完整桌面 Linux;很多系统库默认不存在。 - 项目运行依赖 Playwright Chromium、字体库、图形相关库,以及部分额外二进制工具。
- 构建阶段和运行阶段是分离的;不要假设在 builder 里装过的系统包,runtime 里也一定可用。
- 额外制品目前通过多阶段构建放进镜像,例如
typst。
Docker 相关要求
- 如果你新增的 Python 依赖背后还需要 Linux 动态库、字体、图形库、编译工具或其他系统包,必须同步检查并在
Dockerfile中补齐。 - 不要只让本地虚拟环境能跑;要默认以容器可运行作为完成标准之一。
- 如果新功能依赖系统命令、共享库、浏览器能力或字体,请在提交说明里明确写出原因。
.dockerignore当前会排除/.env、/.git、/data等内容;不要依赖这些文件被复制进镜像。- 关于额外制品的管理,优先先阅读根目录文档
docs/artifact.md;适合统一管理的二进制或外部资源,倾向于复用konabot/common/artifact.py,而不是在各插件里各自处理下载和校验。
本地运行
- 本地开发可参考
justfile,当前主要入口是just watch。 - 如果你的改动影响启动方式、依赖准备方式或运行命令,记得同步更新对应文档或脚本。
分支与协作流程
- 本项目托管在个人 Gitea 实例:
https://gitea.service.jazzwhom.top/mttu-developers/konabot。 - 如果需要创建 Pull Request,优先倾向使用
teaCLI:https://gitea.com/gitea/tea。 - Pull Request 创建后,当前主要会有自动机器人做初步评审,项目维护者会手动查看;不要催促立即合并,也不要默认会马上进主分支。
- 如果当前是在仓库本体上直接开发、而不是在 fork 上工作,尽量提醒用户不要直接在主分支持续改动,优先使用功能分支。
- 除非用户明确要求,否则不要擅自把改动直接合并到主分支。
文档编写建议
面向 man 的文档
- 放在
konabot/docs/对应子目录。 - 文件名直接对应用户查询名称。
- 建议内容简洁,优先说明“做什么、怎么用、示例、注意事项”。
- 使用
.txt后缀;内容可以写成接近 markdown 的可读格式。
面向开发者的文档
- 放在仓库根目录
docs/。 - 主要描述公共模块、配置方法、设计说明、维护经验。
- 可以使用
.md。