# AGENTS.md — 项目智能体说明书 > 本文件是给所有 AI 编程助手(CodeBuddy / WorkBuddy / Claude Code / Codex / Cursor 等)看的项目级上下文。 > 任何账号 clone 本仓库后,助手都应先读本文件与 `docs/change-log/` 下最近的记录,即可无缝衔接。 > 请保持本文件**长期稳定**:只写「架构、规范、约定」,不要写一次性事项。 ## 项目简介 `service.xpcool.com`:个人多客户端(mini / h5 / app)后端服务,GoFrame v2 单体应用。 核心业务:用户认证(JWT)、内容、收藏、站内消息;后台管理(RBAC + 操作审计)。 ## 技术栈 | 项 | 值 | |---|---| | 语言 | Go 1.23.0 | | 框架 | github.com/gogf/gf/v2 v2.10.2 | | 数据库 | MySQL(ORM 由 gf 生成 dao/do/entity) | | 认证 | JWT(`internal/library/jwt`),admin 另有 `X-Permission` 校验 | ## 目录结构 ``` service.xpcool.com/ ├── api/ # HTTP 契约与 Swagger 元数据 │ ├── user/v1/ # /api/v1 用户端 API(登录公开,其余走 UserAuth) │ ├── admin/v1/ # /admin/v1 管理端 API(AdminAuth + X-Permission) │ └── open/v1/ # /api/open/v1 开放接口(给前端调用,公开无鉴权) │ └── tools/ # 工具子功能契约,每子功能一目录:tools//index.go ├── common/ # 公共可复用模块(不依赖 internal,可独立抽取成库) │ └── tools/ # 工具模块,按子功能分包(见下文) ├── internal/ │ ├── cmd/ # 启动引导(路由分组注册在此) │ ├── consts/ # 错误码与常量 │ ├── controller/ # API→service 适配层(不写业务;含 open/ 开放接口实现) │ ├── service/ # 领域用例(业务逻辑直接写这里,不用 logic/) │ ├── dao/ # gf gen dao 生成,禁止手改 │ ├── model/ # entity/ do/ dto/ vo/(entity、do 生成,禁止手改) │ ├── middleware/ # 路由中间件 │ ├── library/ # jwt / page / response 等内部基础件 │ └── table/ # 表列名常量 ├── manifest/ # config.dev/test/prod.yaml、sql 迁移 ├── docs/change-log/ # 每次请求与变更的记录(重要!见「上下文记忆」) └── utility/ # (预留)跨切面辅助 ``` ## 开放接口(api/open/v1,前端调用)与命名规则 - **命名决策**:公共接口前缀用 **open**(不用 common)。理由:`common` 语义偏"内部公共代码",`open` 是开放接口业界惯例(支付宝 /open/api 等),更能表达"对外暴露、无鉴权"。同属"公开"语义的备选还有 `public`。 - 路由前缀 `/api/open/v1`,**公开、无鉴权**,实现于 `internal/controller/open`。 - **tools 子功能目录规则**:`api/open/v1/tools/<子功能名>/index.go` 定义该子功能的 Req/Res 契约(index.go 内 `package <子功能名>`);控制器 `internal/controller/open/<子功能名>.go` 放对应方法(controller 统一 `package open`)。 - 当前端点:`GET/POST /tools/*`(uuid、md5、random、time、ip),底层复用 `common/tools` Go 包。 - **新增子功能三步**:① `api/open/v1/tools//index.go` 写 Req/Res(g.Meta 带 path/method);② `internal/controller/open/.go` 加方法;③ 路由自动绑定,无需改 cmd.go。 ## 公共工具模块 common/tools - 规则:**不依赖 internal/**,只薄封装 GoFrame 内置组件;新工具优先复用内置(gmd5/gaes/gdes/guid/grand/gtime/gconv/gstr/gfile...),避免重复造轮子。 - 子功能:`md5`、`cryptox`(AES/DES)、`uuid`、`random`、`timex`、`convertx`、`strx`、`slicex`、`ip`、`filex`。 - 新增子功能:在 `common/tools/` 下建子包,更新 `common/tools/doc.go` 的布局清单。 ## 分层与调用规范(必须遵守) 1. 调用链:`controller → service → dao → model(do)`;controller 不碰 dao。 2. DTO/VO 边界:跨层出入参走 `internal/model/dto` 与 `internal/model/vo`,API 类型与 entity 不得越界。 3. **数据库操作必须用 DO 对象**(`internal/model/do`),禁止 `g.Map`;未赋值字段保持 nil 自动忽略: ```go dao.Users.Ctx(ctx).Where(cols.Id, id).Data(do.User{Uid: uid}).Update() ``` 4. **时间字段自动维护**:`created_at/updated_at/deleted_at` 由 ORM 自动处理,禁止手动赋值;软删除用 `Delete()`,禁止手写 `WhereNull(cols.DeletedAt)`。 5. **错误处理一律用 gerror**(保留堆栈);响应统一走 `internal/library/response`。 6. 生成代码(dao/do/entity)**禁止手改**,改表后跑 `gf gen dao` 重新生成。 7. 声明 ≥3 个相关变量时,用 `var (...)` 块对齐。 ## 常用命令 ```bash # 运行(dev) GF_GCFG_FILE=config.dev.yaml DB_DSN="user:pass@tcp(127.0.0.1:3306)/db?loc=Local" JWT_SECRET=xxx go run main.go # 数据库模型生成(唯一来源) gf gen dao -p internal -g default -gt -c # 构建 / 测试 go build ./... go test ./... ``` ## 上下文记忆(重要) 三层配合,保证「换个账号/换台机器也能无缝衔接」: 1. **本文件(AGENTS.md)**:长期稳定的架构与规范。 2. **`docs/change-log/YYYY-MM-DD.md`**:每次对话的「请求 + 变更 + 决策」记录,随 git 提交。 - 每次完成任务后,若 `docs/change-log/` 已有当日文件则**追加**,否则新建; - 格式固定:`## 请求` / `## 变更`(含文件清单)/ `## 决策与理由` / `## 待办与风险`; - 助手开工前先读最近 1-2 篇,快速恢复上下文。 3. **`.workbuddy/memory/`**:WorkBuddy 桌面端本机记忆(每日日志 + MEMORY.md),**已加入 .gitignore,不入库**,仅本机增强。 ## 注意事项 - ⚠️ **gtime v2.10.2 格式化**:`Time.Format("Y-m-d H:i:s")` 是 PHP 风格;传 Go layout(`2006-01-02`)要用 `Time.Layout(...)`。工具包 `common/tools/timex` 已统一封装。 - ⚠️ **gf v2.10.2 包名与旧版不同**:AES/DES 在 `crypto/gaes`、`crypto/gdes`(无 gcrypto);UUID 在 `util/guid`(无 guuid);无 gslicer(用标准库 slices)。 - 配置文件按 `GF_GCFG_FILE` 切换;`manifest/config/config.yaml` 不入库。 - 生产环境强密码:`JWT_SECRET`、数据库口令。 - 变更涉及 API 时同步更新 `api/` 下的 Swagger 元数据注释。