# OctoHz 我的项目 API ## 接口一览 | Method | Route | 说明 | |--------|-------|------| | GET | `/api/my/projects` | 列表(摘要) | | POST | `/api/my/projects` | 新建 | | GET | `/api/my/projects/:id` | 获取索引(轻量);`?full=true` 获取完整数据 | | PATCH | `/api/my/projects/:id` | 部分更新 | | DELETE | `/api/my/projects/:id` | 删除 | | GET | `/api/my/projects/:id/definition` | 获取 definition 分段 | | GET | `/api/my/projects/:id/status` | 获取 status 分段 | | GET | `/api/my/projects/:id/ops` | 获取 ops 分段 | | GET | `/api/my/projects/:id/decisions` | 获取 decisions 分段 | | GET | `/api/my/projects/:id/pitfalls` | 获取 pitfalls 分段 | | GET | `/api/my/projects/:id/design` | 获取 design 分段 | | GET | `/api/my/projects/:id/data-models` | 获取 data_models 分段 | | GET | `/api/my/projects/:id/snapshots` | 历史版本列表 | | GET | `/api/my/projects/:id/snapshots/:sid` | 某个历史版本完整内容 | | POST | `/api/my/projects/:id/snapshots/:sid` | 恢复至该版本(恢复前自动备份当前) | **重要:** project ID 只能放 URL,不能放 body。 --- ## 索引结构 `GET /api/my/projects/:id` 默认返回轻量索引,每个分段只给摘要和 URL,**不含完整数据**: ```json { "id": 1, "name": "项目名", "stage": "production", "oneliner": "...", "updatedAt": "...", "sections": { "definition": { "summary": "tech_stack 摘要 | conventions 列表", "url": "/api/my/projects/1/definition" }, "status": { "summary": "completed: N · in_progress: N · pending: N", "url": "/api/my/projects/1/status" }, "ops": { "summary": "repo · servers(N) · databases(N) · ...", "url": "/api/my/projects/1/ops" }, "decisions": { "summary": "N条 — D001 标题 · D002 标题", "url": "/api/my/projects/1/decisions" }, "pitfalls": { "summary": "N条 — P001[高] 标题 · ...", "url": "/api/my/projects/1/pitfalls" }, "design": { "summary": "colors · buttons(N) · card", "url": "/api/my/projects/1/design" }, "data_models": { "summary": "N个 — Model1 · Model2", "url": "/api/my/projects/1/data-models" } } } ``` **推荐工作流:先读索引 → 根据任务判断需要哪几节 → 只请求那几个 URL** | 任务类型 | 建议拉取 | |----------|---------| | 修 bug / 接手 | `pitfalls` + `ops` | | 新功能开发 | `definition` + `data_models` + `ops` | | 了解当前进度 | `status` | | UI 相关 | `design` + `definition` | | 全量获取 | `?full=true` | --- ## 顶层结构 ```json { "id": 1, "name": "项目名称", "definition": {}, "decisions": [], "pitfalls": [], "status": {}, "ops": {}, "design": {}, "dataModels": [] } ``` **POST 支持字段:** `name`、`definition`、`decisions`、`pitfalls`、`status`、`ops` **PATCH 额外支持:** `design`、`data_models`(POST 不接受这两个字段) --- ## ⚠️ PATCH 行为说明 **顶层字段**是局部更新——只发哪个字段就更新哪个字段,其余不变。 **但嵌套对象(`ops`、`definition`、`status`)是整体替换**,不做深度合并: ```bash # ❌ 危险:只发 ops.nodes,ops 的其余字段(servers、deploy_flow 等)会丢失 curl -s -X PATCH https://octohz.com/api/my/projects/1 \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"ops": {"nodes": [...]}}' # ✅ 正确:先 GET 完整数据,本地合并后整体发 curl -s "https://octohz.com/api/my/projects/1?full=true" \ -H "Authorization: Bearer $TOKEN" > /tmp/proj.json # 在 /tmp/proj.json 中修改 ops.nodes,然后整体发回 curl -s -X PATCH https://octohz.com/api/my/projects/1 \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d "{\"ops\": $(jq '.ops' /tmp/proj.json)}" ``` **例外**:`decisions` 和 `pitfalls` 是数组,按 `id` upsert,不受此影响——直接发新条目即可,不会覆盖历史。 **可选字段 `_note`**(最多 200 字):填写本次更新的备注,会记录在历史版本里,方便日后回溯。 ```json { "status": { ... }, "_note": "修复登录 bug 后同步状态" } ``` --- ## definition ```json { "oneliner": "一句话描述", "stage": "production", "tech_stack": [ { "tech": "Next.js", "layer": "frontend", "version": "16.2.1", "framework": "App Router" } ], "conventions": { "styling": "Tailwind v4 utility classes", "deploy": "改完后端先 git push,再 SSH 执行部署脚本" }, "estimated_completion": "2026-06" } ``` - `oneliner`:注意**不是** `one_liner` - `stage` 枚举:`development` / `production` / `maintenance` / `running` / `archived` - `tech_stack` 每项:`tech`(必填)、`layer`(必填)、`version`(选填)、`framework`(选填)、`note`(选填)、`port`(选填) - `layer` 常用值:`frontend` / `backend` / `database` / `deployment` / `runtime` / `plugin` / `service` / `proxy` / `control_plane` / `vpn_client` - `conventions`:key-value 对象,key 自定义,value 为字符串;**整体是对象不是数组** - `estimated_completion`:选填,`"YYYY-MM"` 或 `null` --- ## decisions ```json [ { "id": "D001", "date": "2026-04", "title": "决策标题", "impact": "影响的文件或模块", "status": "active", "context": "做这个决策的背景", "decision": "具体做了什么决定", "rationale": "(选填)更详细的理由" } ] ``` - `id` 格式:`D001`、`D002` 递增 - `date`:选填,`"YYYY-MM"` 或 `"YYYY-MM-DD"` - `status` 常用值:`active` / `deprecated` / `superseded`(服务端不校验枚举,写语义清晰的字符串即可) - `context` 和 `decision` 分开写,不要合并 - **PATCH 行为:按 `id` upsert**——发送的条目与现有数据按 `id` 合并,字段值为 `null` 时该字段被删除,不存在的 `id` 则新增 --- ## pitfalls ```json [ { "id": "P001", "date": "2026-04-24", "title": "坑的标题", "status": "mitigated", "severity": "high", "condition": "在什么情况下触发", "consequence": "触发后会发生什么", "solution": "怎么解决或规避", "mitigation": "(选填)已采取的缓解措施", "description": "(选填)更详细说明" } ] ``` - `id` 格式:`P001`、`P002` 递增 - `date`:选填,`"YYYY-MM-DD"` - `status` 枚举:`resolved` / `mitigated` / `active` / `identified` - `severity` 枚举:`high` / `medium` / `low` - `condition`、`consequence`、`solution` 是必填核心三件套 - `mitigation`、`description`:选填 - **PATCH 行为:按 `id` upsert**——同 decisions,按 `id` 合并,`null` 值删字段 --- ## status ```json { "completed": ["已完成项"], "in_progress": ["进行中"], "pending": ["待办"], "known_issues": ["已知轻量问题"] } ``` 所有字段都是字符串数组,空时写 `[]`,**不能写 `null`**。 --- ## ops > **⚠️ PATCH 时整体替换,修改前必须先 GET `?full=true` 拿完整 ops,合并后再发。** ```json { "repo": "https://github.com/xxx/yyy", "servers": [ { "address": "67.230.160.74 / octohz.com", "purpose": "生产环境", "services": ["Next.js 16", "PostgreSQL"] } ], "env_vars": [ { "key": "DATABASE_URL", "hint": "postgresql://user:@host:5432/db,密码见服务器 .env" } ], "cron_jobs": [], "databases": [ { "name": "mydb", "type": "PostgreSQL", "address": "172.18.0.3:5432", "notes": "容器间通信用内网地址" } ], "local_dev": ["Node.js 20+", "npm install", "npm run dev"], "onboarding": { "summary": "项目一句话介绍", "key_files": ["path/to/file — 说明"], "first_steps": ["1. 第一步", "2. 第二步"], "forbidden_zones": ["禁止做的事"] }, "deploy_flow": ["Step 1: ...", "Step 2: ..."], "third_party": [ {"name": "Resend", "status": "normal", "purpose": "邮件发送"} ], "dir_structure": { "root": "/opt/project", "notes": "补充说明", "key_paths": [ {"path": "src/app", "desc": "Next.js 路由"} ] } } ``` - `env_vars` 每项用 `hint` 字段(**不是** `note` / `value` / `scope`),不写明文密码 - `databases` 本地文件型存储(JSON / safetensors / SQLite 等)也用同一 schema:`address` 填文件路径(如 `~/.omlx/stats.json`),`type` 填 `JSON file` / `safetensors` 等,`notes` 补充说明;**不要自创 `path` 或 `note` 字段** - `onboarding` 是**对象**,不是字符串 - `servers[].address` 多个地址用 ` / ` 分隔 - 不涉及的字段(`cron_jobs`、`databases` 等)填 `[]`,不要省略 --- ## design(选填,仅 PATCH) ```json { "notes": "整体风格说明", "colors": { "primary": "#e64831", "bg": {"page": "#f4f4f4", "card": "#ffffff"} }, "buttons": [ {"name": "主操作按钮", "style": "CSS 字符串", "usage": "使用场景"} ], "card": "卡片的 Tailwind class 字符串" } ``` 无 UI 的项目留 `{}`。POST 新建时不支持此字段,需建好后再 PATCH。 --- ## dataModels(选填,仅 PATCH) PATCH body 中字段名为 **`data_models`**(snake_case),服务端存储为 `dataModels`。 ```json [ { "name": "User", "table": "users", "desc": "用户账号", "key_fields": ["id", "email", "password"] } ] ``` 无数据库的项目留 `[]`。POST 新建时不支持此字段。 --- ## 历史版本 每次 PATCH 会**自动保存当前状态为快照**,每个项目最多保留 50 个版本,超出时自动删除最旧的。 ```bash # 列表(只含 id、savedAt、note,不含完整数据) curl -s https://octohz.com/api/my/projects/1/snapshots \ -H "Authorization: Bearer $TOKEN" # → [{ "id": 12, "savedAt": "2026-04-27T10:00:00Z", "note": "修复登录 bug" }, ...] # 查看某个版本完整内容 curl -s https://octohz.com/api/my/projects/1/snapshots/12 \ -H "Authorization: Bearer $TOKEN" # 恢复至该版本(无需 body;恢复前自动备份当前状态) curl -s -X POST https://octohz.com/api/my/projects/1/snapshots/12 \ -H "Authorization: Bearer $TOKEN" ``` --- ## 常见错误速查 | 错误写法 | 正确写法 | |---------|----------| | `one_liner` | `oneliner` | | `conventions: ["字符串"]` | `conventions: {"key": "value"}` | | `env_vars[].note` | `env_vars[].hint` | | `databases[].path` | `databases[].address`(本地文件路径也填这里) | | `databases[].note` | `databases[].notes`(注意末尾有 s) | | `onboarding: "字符串"` | `onboarding: {summary, key_files, ...}` | | `tech_stack: ["Next.js"]` | `tech_stack: [{tech, layer}]` | | 空字段写 `null` | 空字段写 `[]` 或 `{}` | | body 里传 `id` | ID 只放 URL | | PATCH body 用 `dataModels` | PATCH body 用 `data_models` | | decisions/pitfalls 全量覆盖 | 按 `id` upsert,`null` 值删字段 | | PATCH ops 只发部分字段 | 先 GET `?full=true`,合并后整体发 | | curl 示例漏写 Authorization 头 | 所有请求加 `-H "Authorization: Bearer $TOKEN"` | | GET 时写 `curl -s GET url` | `curl -s url`(GET 会被当成第二个 URL)| | `pitfalls[].severity` 用中文("高"/"中"/"低") | 必须用英文枚举:`"high"` / `"medium"` / `"low"` | --- **分类**:Agent 使用教程 **链接**:https://octohz.com/docs?doc=68 --- **分类**:Octohz 我的功能 **链接**:https://octohz.com/docs?doc=68