Files
plane-gptproto-integration/CLAUDE.md
T
carlandCursor 0136c15274 Initial commit: Plane 自部署与 gptproto AI 集成
包含本地/远程部署脚本、AI Agent 服务、Dashboard 与 QA 验证。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-21 11:37:41 +08:00

8.2 KiB
Raw Blame History

plane-gptproto-integration

Plane v1.3.0(AGPL-3.0 开源项目管理)自部署 + gptproto.com(OpenAI 兼容聚合 API)AI Agent 集成。本地 mac docker 验证后再上 YOUR_SERVER_IP 生产。

双环境部署架构

环境 Web 入口 AI 端点 compose 路径 端口绑定
本地 mac http://localhost:8090 http://localhost:8100 deploy/local/ + src/ git clone 0.0.0.0:8090/8100
生产 YOUR_SERVER_IP https://YOUR_SERVER_IP:8445 https://YOUR_SERVER_IP:8446 /opt/plane/ (1Panel + OpenResty) 127.0.0.1:8092/8101

生产走 1Panel + OpenResty 反代 + ufw + 自签 SSL(/opt/1panel/www/ssl/luma/luma.{crt,key},已存在)。容器只绑 127.0.0.1,公网入口由 OpenResty /opt/1panel/www/conf.d/plane.conf 反代。生产端口规划遵循 ~/dev/PRODUCTION_DEPLOY_TEMPLATE.md:公网用 8445/8446/8447 段,内部用 8090+。8090 已被 1Panel openresty 占用,本地 mac 用 8090 OK,生产改 8092。

常用命令

# 本地启停
cd deploy/local
docker compose -f src/deployments/cli/community/docker-compose.yml -f docker-compose.override.yml --env-file .env up -d --pull never
bash ../../qa/verify-local.sh   # 6 项健康检查,exit=0 全过

# 生产 (ssh + docker compose)
ssh root@YOUR_SERVER_IP 'cd /opt/plane && docker compose -f src/deployments/cli/community/docker-compose.yml -f docker-compose.override.yml --env-file .env restart'

# AI Agent 改 main.py 后同步生产 + rebuild
rsync -az --exclude=.venv --exclude=__pycache__ ai-agent/ root@YOUR_SERVER_IP:/opt/plane/ai-agent/
ssh root@YOUR_SERVER_IP 'cd /opt/plane && docker compose -f src/deployments/cli/community/docker-compose.yml -f docker-compose.override.yml --env-file .env up -d --build --force-recreate plane-ai'

# pytest 本地 TDD
cd ai-agent && source .venv/bin/activate && pytest -v

非显然坑点(必读,本次会话血泪验证)

1. Plane v1.3.0 compose 路径变了

官方 selfhost 入口从旧版 src/deploy/selfhost/docker-compose.yml 搬到 src/deployments/cli/community/docker-compose.yml。Worker 用旧路径会 no such file or directory。

2. Docker Desktop 自动捕获 macOS 系统代理 → TLS bug

mac 上 docker pull 报 tls: bad record MAC / version 300 vs 303 几乎一定是你 Clash/V2Ray 占着 127.0.0.1:1082,Docker Desktop 自动用了它,本地代理拆 TLS 失败。修法:Docker Desktop → Settings → Resources → Proxies → 打开 Manual 但三栏全留空 → Quit Docker Desktop(完整退出,Restart 不够,要 Quit)→ 重开。http.docker.internal:3128 在 docker info 里永远显示,是 Docker 内置 forwarder,跟你的代理设置无关。

3. OpenResty 反代 FastAPI uvicorn 必须显式 HTTP/1.1

proxy_pass http://127.0.0.1:8101;
proxy_http_version 1.1;
proxy_set_header Connection "";

缺这两行 → uvicorn 等 keepalive 不释放 → 30s 必 ReadTimeout。已修进 deploy/remote/plane.conf 8446 server block。

4. gptproto 部分 model 当前不可用

claude-sonnet-4-6 60s timeout(gptproto 端挂),改用 claude-sonnet-4-5-20250929 或 claude-haiku-4-5-20251001。chatgpt-4o-latest 可能 503 overloaded。.env 里 GPTPROTO_MODEL 决定。

5. Anthropic 不支持 OpenAI 的 response_format: json_object

gptproto 转发给 Anthropic 时该参数被忽略,模型可能返回 ```json ... ``` 围栏或纯文本。ai_agent/main.py::_extract_json 已用 regex 兜底(先抓围栏再抓 {...})。

6. plane-ai 进程残留死连接

切 model 或修 .env 后 ReadTimeout 不消失,必须 docker compose up -d --force-recreate plane-ai。普通 restart 或 up -d 不彻底。

7. rsync --delete 会清生产 src/

本地 staging 目录没 src/ 时,rsync -az --delete /tmp/staging/ /opt/plane/ 会删服务器 git clone 的 src/。绝不在生产路径用 --delete,或显式 --exclude=src/。

8. 非标端口部署:OpenResty 必须用 $http_host 不是 $host

Plane backend storage.py 用 request.get_host() 构造 MinIO presigned upload URL。两层反代(OpenResty → Caddy → Django)必须把带端口的 Host 头透传到底:

  • nginx $host 不带端口(YOUR_SERVER_IP)
  • nginx $http_host 带端口(YOUR_SERVER_IP:8445)

错误用 $host → Django 得到 host 没端口 → presigned URL https://YOUR_SERVER_IP/uploads(走 443 撞别的服务) → CORS blocked。

正确:

location / {
  proxy_pass http://127.0.0.1:8092;
  proxy_set_header Host $http_host;   # ← 必须 $http_host 不是 $host
  ...
}

APP_DOMAIN=YOUR_SERVER_IP:8445 也要(影响 Plane CORS allow-origin 等),但单独改它不够,必须配合 OpenResty 修。

Plane v1.3.0 数据库/安全实测

  • users.password PBKDF2 哈希 ✅ 标准
  • api_tokens.token 明文存储 ⚠️ 任何 PG 读权限可枚举所有 token
  • instance_configurations 加密字段(如 LLM_API_KEY)通过 GET /api/instances/configurations/ 时被 InstanceConfigurationSerializer.to_representation decrypt 后明文回吐给前端 → F12 Network 可见
  • 真 GPTPROTO_API_KEY 仅放 .env(chmod 600)+ 容器 env,不入 Plane DB
  • god-mode AI Settings 永远留空(我们走独立 plane-ai 服务,Plane backend 用不到这个 key)

API 端点 (FastAPI plane-ai)

端点 输入 行为
GET /healthz — {"status":"ok"},Dockerfile healthcheck 用
POST /ai/create-issue {prompt, project_id, workspace_slug} gptproto 解析 → POST Plane /api/v1/.../issues/
POST /ai/summarize {issues:[...]} gptproto 中文摘要
POST /ai/search {query, workspace_slug} Plane /issues/search/?search= + gptproto 排序

注意 search 用 /issues/search/(v1 public 端点)不是 /search/(internal app 端点要 session auth)。

文件清单

CLAUDE.md                                  本文件
AGENTS.md                                  worker 共享上下文(开发期产物)
README.md                                  对外简介
docs/PLAN.md                               完整设计 + 后门/隐私评估
docs/USER_GUIDE.md                         给领导/团队的使用说明
deploy/local/.env                          本地密钥(600, .gitignore)
deploy/local/docker-compose.override.yml   本地端口 0.0.0.0:8090/8100
deploy/local/pull-plane.sh                 git clone v1.3.0(idempotent)
deploy/local/src/                          Plane 源码(git, .gitignore)
deploy/remote/docker-compose.override.yml  生产端口 127.0.0.1:8092/8101
deploy/remote/plane.conf                   OpenResty 反代(8445/8446 → 8092/8101,含 HTTP/1.1 修复)
ai-agent/ai_agent/main.py                  4 端点 + _extract_json + httpx async
ai-agent/tests/                            pytest TDD,respx mock 不真联网
qa/verify-local.sh                         6 项健康检查
qa/checklist.md                            worker 签名 + 人工验收项

红线

  • 不在 god-mode → AI Settings 填真 GPTPROTO_API_KEY(Plane backend 用不到 + 解密回显有 leak 风险)
  • 不直接绑容器到 0.0.0.0:80(违反 ~/dev/PRODUCTION_DEPLOY_TEMPLATE.md)
  • 不 ssh 手动改生产 .env 不同步本地(本地 deploy/remote/ 是 source of truth)
  • 不拉 Plane master/latest,锁 v1.3.0 + GitHub Release tag
  • 不在生产路径用 rsync --delete

升级流程(Plane 出新版后)

ssh root@YOUR_SERVER_IP
cd /opt/plane/src
git fetch --depth 1 origin refs/tags/vX.Y.Z:refs/tags/vX.Y.Z
git checkout vX.Y.Z
cd ..
sed -i 's/^APP_RELEASE=.*/APP_RELEASE=vX.Y.Z/' .env
docker compose -f src/deployments/cli/community/docker-compose.yml -f docker-compose.override.yml --env-file .env pull
docker compose -f src/deployments/cli/community/docker-compose.yml -f docker-compose.override.yml --env-file .env up -d
# 本地同步: 改 deploy/remote/.env.template 的 APP_RELEASE
# 验证: 镜像无 :latest, ufw 无变, openresty conf 无需改

服务器现状 (YOUR_SERVER_IP, 1Panel v2.1.10)

8 核 / 31GB / 387GB(余 360GB+),Hostinger VPS。已部署兄弟项目:Luma 主站(443/8088)、harvester(8443/8089)、领航 BI(8444)、VideoFlow(9080-9443)。新增 Plane 占 8445(web)/8446(ai),内部 8092/8101。