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,不含完整数据:
{
"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 |
顶层结构
{
"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)是整体替换,不做深度合并:
# ❌ 危险:只发 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 字):填写本次更新的备注,会记录在历史版本里,方便日后回溯。
{ "status": { ... }, "_note": "修复登录 bug 后同步状态" }
definition
{
"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_linerstage枚举:development/production/maintenance/running/archivedtech_stack每项:tech(必填)、layer(必填)、version(选填)、framework(选填)、note(选填)、port(选填)layer常用值:frontend/backend/database/deployment/runtime/plugin/service/proxy/control_plane/vpn_clientconventions:key-value 对象,key 自定义,value 为字符串;整体是对象不是数组estimated_completion:选填,"YYYY-MM"或null
decisions
[
{
"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 行为:按
idupsert——发送的条目与现有数据按id合并,字段值为null时该字段被删除,不存在的id则新增
pitfalls
[
{
"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/identifiedseverity枚举:high/medium/lowcondition、consequence、solution是必填核心三件套mitigation、description:选填- PATCH 行为:按
idupsert——同 decisions,按id合并,null值删字段
status
{
"completed": ["已完成项"],
"in_progress": ["进行中"],
"pending": ["待办"],
"known_issues": ["已知轻量问题"]
}
所有字段都是字符串数组,空时写 [],不能写 null。
ops
⚠️ PATCH 时整体替换,修改前必须先 GET
?full=true拿完整 ops,合并后再发。
{
"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:<pw>@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)
{
"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。
[
{
"name": "User",
"table": "users",
"desc": "用户账号",
"key_fields": ["id", "email", "password"]
}
]
无数据库的项目留 []。POST 新建时不支持此字段。
历史版本
每次 PATCH 会自动保存当前状态为快照,每个项目最多保留 50 个版本,超出时自动删除最旧的。
# 列表(只含 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