基于真实踩坑记录整理。按此步骤操作,新机器上 15 分钟内跑起来。
| 软件 | 版本要求 | 验证命令 | 踩坑记录 |
|---|---|---|---|
| Python | >= 3.13, < 3.15 |
python3 --version |
3.14 不行(pyproject.toml 限制);3.12 也不行 |
| Node.js | >= 20 |
node --version |
推荐 v24 LTS;v18 会导致 Next.js 16 报错 |
| pnpm | 11.6.0 |
pnpm --version |
必须用 pnpm,npm/yarn 都不行;版本偏差可能破坏 next 的 symlink |
| uv | 最新 | uv --version |
Python 包管理器,替代 pip;自动管理 .venv |
| Docker Desktop | 最新 | docker compose version |
需要 PostgreSQL (pg17 + pgvector) 和 MinIO |
| Git | 任意 | git --version |
— |
# Python 3.13(如果系统版本不够)
brew install python@3.13
# Node.js 24 LTS
brew install node@24
# pnpm 11.6.0
corepack enable && corepack prepare pnpm@11.6.0 --activate
# uv
curl -LsSf https://astral.sh/uv/install.sh | sh
# Docker Desktop
brew install --cask dockergit clone https://github.com/lora-sys/trustops.git
cd trustopsdocker compose up -d等待两个容器都 healthy:
docker compose ps
# 两个 service 的 State 都应该是 "healthy"坑 1:pg_isready 检查可能需要 10-20 秒。如果
docker compose ps显示starting,等几秒再查。坑 2:MinIO 的 healthcheck 用
curl,Docker Desktop 的 curl 可能不在 PATH 里。如果一直 unhealthy,手动检查:curl -f http://localhost:9000/minio/health/live
停止基础设施(开发结束时):
docker compose down
# 保留数据卷(下次启动不用重新建库):
docker compose down -v # 加这个会删数据,谨慎cp .env.example .env.env 已加入 .gitignore,不会泄露。需要填写的字段:
| 字段 | 默认值 | 是否需要改 | 说明 |
|---|---|---|---|
MODEL_API_KEY |
空 | 需要填 | StepFun API Key,LIVE AI 必需 |
MODEL_NAME |
空 | 可选 | 不填则用默认模型 |
| 其余字段 | 已预填 | 一般不需要 | 端口、数据库连接等已适配本地 |
坑 3:
DATABASE_URL中的密码是trustops,和compose.yaml里的POSTGRES_PASSWORD必须一致。
cd apps/api
# 安装依赖(uv 自动创建 .venv)
uv sync
# 运行数据库迁移
uv run alembic upgrade head
# 导入演示数据(NovaCloud 问卷 + 证据 + 控制快照)
uv run python scripts/seed_database.py
# 启动 API 服务
uv run uvicorn trustops.api:app --host 0.0.0.0 --port 8000 --reload验证后端是否就绪:
curl http://localhost:8000/health/ready
# 应返回 JSON,包含 agentteams_ready、database_ready 等字段坑 4:
uv sync会在apps/api/.venv创建虚拟环境。如果之前用pip或python -m venv创建过.venv,先删掉:rm -rf apps/api/.venv坑 5:
seed_database.py是幂等的(用ON CONFLICT DO NOTHING),重复运行不会报错。坑 6:
OBJECT_STORAGE_PATH默认./data/object-storage(相对路径)。从apps/api/目录启动时,会自动创建该目录。从其他目录启动时需要绝对路径。
坑 7(最大坑):官方镜像
higress-registry.us-west-1.cr.aliyuncs.com/higress/agentteams/agentteams-embedded:v1.2.0在国内无法拉取。如果遇到镜像拉取失败,有两条路:
路线 A:使用官方 AgentTeams Manager(推荐,如果网络允许)
# 从阿里云容器镜像服务手动拉取(可能需要代理)
docker pull higress-registry.us-west-1.cr.aliyuncs.com/higress/agentteams/agentteams-embedded:v1.2.0
# 或用 agentteams-install.sh(但该脚本也可能被墙)
./agentteams-install.sh路线 B:使用本地直接运行模式(当前项目使用的 fallback)
项目已内置 direct_runtime.py,不依赖外部镜像,直接用 LLM API 驱动 Agent。启动 API 后自动尝试连接。
验证 AgentTeams 状态:
curl http://localhost:8000/health/ready | python3 -m json.tool
# agentteams_ready=true 表示连接成功
# agentteams_ready=false 表示未连接(fallback 模式,后端仍可工作)cd apps/web
pnpm install
pnpm dev前端会在 http://localhost:3000 启动。
坑 8(已知问题):在某些环境下,
pnpm install后apps/web/node_modules/next会变成损坏的 symlink,导致next dev报ERR_INCOMPLETE_CHUNKED_ENCODING或500。如果遇到此问题,使用临时代理:
cd apps/web
# 手动编译代理脚本(需要 pnpm 已经安装过依赖)
node -e "
const fs = require('fs');
const code = fs.readFileSync('.trustops-frontend-proxy.mjs', 'utf8');
// 如果文件不存在,说明代理脚本还未生成,需要从 git 恢复或手动创建
"
# 更简单的方式:用下面的 single-file proxy
node -e "
const http = require('http');
const fs = require('fs');
const path = require('path');
const { fileURLToPath } = require('url');
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const PORT = 3000;
const API_BASE = 'http://127.0.0.1:8000';
const ROOT = path.join(__dirname, '..');
const pagePaths = new Set(['/','/reviews/','/reviews/review_finbank_2026/']);
function readAsset(...segments) { return fs.readFileSync(path.join(ROOT, ...segments), 'utf8'); }
const server = http.createServer(async (req, res) => {
const url = new URL(req.url, 'http://localhost');
if (url.pathname.startsWith('/api/')) {
const apiRes = await fetch(API_BASE + url.pathname + url.search, { headers: { accept: 'application/json' } });
res.writeHead(apiRes.status, { 'content-type': apiRes.headers.get('content-type') || 'application/json' });
await apiRes.body.pipeTo(new WritableStream({ write(c) { res.write(c); }, close() { res.end(); } }));
return;
}
if (url.pathname.endsWith('.css')) {
res.writeHead(200, { 'content-type': 'text/css' });
res.end(readAsset('app', 'styles.css'));
return;
}
res.writeHead(404); res.end('Not found');
});
server.listen(PORT, '127.0.0.1', () => console.log('Proxy on http://127.0.0.1:' + PORT));
"方案 B 是临时 workaround,只提供基础页面和 API 代理,不支持 HMR 和路由。
curl http://localhost:8000/health/ready
# 期望:status=ready, database_ready=true, pgvector_ready=true打开浏览器访问 http://localhost:3000,应看到中文 TrustOps 首页。
http://localhost:3000/reviews/review_finbank_2026/
子页面:
/mission— 任务面板/evaluations— 评估中心/approvals— 审批入口/exports— 导出门控/questions/question_005— Q-005 详情
cd apps/api
uv run pytest --tb=short
# 期望:39 passedcd apps/web
pnpm test
# 期望:approval-action 组件测试通过| 端口 | 服务 | 用途 |
|---|---|---|
5432 |
PostgreSQL (Docker) | 数据库 |
9000 |
MinIO API (Docker) | 对象存储 |
9001 |
MinIO Console (Docker) | 存储管理面板 |
8000 |
FastAPI (uvicorn) | 后端 API |
3000 |
Next.js / Proxy | 前端 UI |
如果端口被占用:
# macOS 查看占用
lsof -i :PORT
# 杀掉占用进程
kill -9 PIDA:删除 node_modules 重装,或使用方案 B 代理:
cd apps/web
rm -rf node_modules
pnpm install
# 如果还不行 → 使用方案 B 代理A:确认 Docker 容器在运行且 healthy:
docker compose ps
# 两个都必须是 healthy 状态A:先跑 migration:
cd apps/api
uv run alembic upgrade headA:确认后端 API 在 localhost:8000 运行,且 .env 中的 NEXT_PUBLIC_API_URL 指向正确地址。
A:这是已知问题。后端会 fallback 到 direct_runtime 模式,仍可正常工作(但不走官方 AgentTeams 多 Agent 架构)。如需完整 AgentTeams,需要解决镜像拉取问题。
A:使用了 psycopg[binary],不需要编译。如果仍有问题,确保 Xcode Command Line Tools 已安装:
xcode-select --installA:uv 的安装脚本可能没有把二进制文件加到 PATH。重启终端,或手动添加:
export PATH="$HOME/.cargo/bin:$PATH"# ── 基础设施 ──────────────────────────────────
docker compose up -d # 启动 PostgreSQL + MinIO
docker compose ps # 检查容器状态
docker compose logs -f postgres # 查看 PostgreSQL 日志
docker compose logs -f minio # 查看 MinIO 日志
docker compose down # 停止(保留数据卷)
# ── 后端 ──────────────────────────────────────
cd apps/api
uv sync # 安装/更新 Python 依赖
uv run alembic upgrade head # 执行迁移
uv run python scripts/seed_database.py # 导入演示数据
uv run uvicorn trustops.api:app --host 0.0.0.0 --port 8000 --reload # 启动
uv run pytest # 跑测试
uv run pytest tests/test_evaluations.py -k "test_control_accuracy" # 跑单个测试
# ── 前端 ──────────────────────────────────────
cd apps/web
pnpm install # 安装依赖
pnpm dev # 启动 dev server
pnpm build # 生产构建
pnpm test # 跑 vitest
pnpm lint # ESLint
pnpm typecheck # TypeScript 检查
# ── 验证 ──────────────────────────────────────
curl http://localhost:8000/health/ready
curl http://localhost:3000trustops/
├── apps/
│ ├── api/ # FastAPI 后端
│ │ ├── src/trustops/
│ │ │ ├── api.py # FastAPI app 入口
│ │ │ ├── config.py # 配置(Pydantic Settings)
│ │ │ ├── database.py # SQLAlchemy + async 引擎
│ │ │ ├── agentteams.py # AgentTeams 客户端
│ │ │ ├── model_gateway.py # LLM 模型网关
│ │ │ ├── direct_runtime.py # 本地直接运行模式(fallback)
│ │ │ ├── evaluation.py # 评估引擎
│ │ │ ├── worker.py # Background worker
│ │ │ ├── domain/ # 领域模型(Entity, Value Object)
│ │ │ ├── routes/ # API 路由
│ │ │ ├── ingestion/ # Excel 解析
│ │ │ └── skills/ # Control Skills
│ │ ├── migrations/ # Alembic 迁移(3 个)
│ │ ├── tests/ # 13 个测试文件
│ │ ├── scripts/
│ │ │ ├── seed_database.py # 导入演示数据(幂等)
│ │ │ ├── seed_demo.py # 生成演示证据文件
│ │ │ └── run_direct_q005.py # Q-005 直接运行脚本
│ │ └── pyproject.toml # 依赖 + 工具配置
│ │
│ └── web/ # Next.js 16 前端
│ ├── app/
│ │ ├── layout.tsx # 根布局
│ │ ├── page.tsx # 首页(中文 UI)
│ │ ├── styles.css # 全局样式
│ │ ├── reviews/[reviewId]/ # 动态审查页
│ │ └── api/ # BFF 路由
│ ├── components/
│ │ ├── workspace-frame.tsx # 主布局框架
│ │ ├── approval-action.tsx # 审批操作
│ │ ├── export-action.tsx # 导出操作
│ │ └── ...
│ └── lib/
│ ├── trustops.ts # 类型定义 + API client
│ └── api.ts # fetch 封装
│
├── data/
│ ├── demo/ # 演示数据
│ │ ├── NovaCloud_Security_Questionnaire.xlsx
│ │ └── evidence/ # 10 个证据目录
│ └── object-storage/ # MinIO 本地替代(.gitkeep 占位)
│ └── .gitkeep
│
├── compose.yaml # Docker 基础设施
├── .env.example # 环境变量模板
├── .gitignore # 忽略制品 / 日志 / 密钥
└── GETTING_STARTED.md # 本文档
┌──────────────┐ Excel ┌──────────────┐
│ seed_demo.py │ ─────────────> │ data/demo/ │
└──────────────┘ └──────┬───────┘
│ 导入时解析
┌──────────────┐ REST API ┌──────▼───────┐
│ Frontend │ ◄────────────── │ FastAPI │
│ (Next.js) │ │ Backend │
└──────────────┘ └──────┬───────┘
│
┌─────────────┼─────────────┐
│ │ │
┌──────▼──────┐ ┌───▼────┐ ┌─────▼─────┐
│ PostgreSQL │ │ MinIO │ │ AgentTeams│
│ + pgvector│ │ 对象存储│ │ LLM 运行时│
└────────────┘ └────────┘ └───────────┘
| Decision | 结论 | 影响 |
|---|---|---|
| D-001: Python 版本锁定 | >=3.13, <3.15 |
新机器必须装 Python 3.13 |
| D-003: 前端 Next.js dev server 损坏 | 使用 Node.js 代理作为 fallback | 换电脑时可能遇到相同问题 |
| D-007: AgentTeams 官方镜像不可用 | 使用 direct_runtime.py fallback |
LIVE AI 走本地 LLM 直连,不走多 Agent |
| D-010: 对象存储本地文件系统实现 | LocalObjectStorage 包装 data/object-storage/ |
不需要运行 MinIO 也能跑(但推荐跑) |
| D-012: 演示数据幂等导入 | ON CONFLICT DO NOTHING |
seed_database.py 可重复执行 |
新电脑上克隆完仓库后,逐条打勾:
[ ] git clone 成功
[ ] docker compose up -d 后两个容器 healthy
[ ] cp .env.example .env 且 MODEL_API_KEY 已填写
[ ] cd apps/api && uv sync 成功
[ ] uv run alembic upgrade head 成功
[ ] uv run python scripts/seed_database.py 成功
[ ] uvicorn 启动后 /health/ready 返回 200
[ ] 前端访问 http://localhost:3000 能看到中文首页
[ ] /reviews/review_finbank_2026/ 能看到审查面板
[ ] uv run pytest 显示 39 passed
全部打勾 = 环境就绪,可以开始开发。
- 仓库:https://github.com/lora-sys/trustops
- 内部文档:
docs/EXECUTION_STATE.md(最新执行状态) - 交接记录:
docs/HANDOFF.md - 实现审计:
docs/IMPLEMENTATION_AUDIT.md