本地调试与启动
在开发机上把数据服务、节点控制服务、Tunnel Runtime 和 Web 前端逐个拉起来,并用日志与接口探针定位问题。生产部署走 Docker Compose,见 部署文档。
0. 四个进程与端口
本地调试是手工拉起多个进程,不是一个命令。先记住谁监听哪个端口、谁是可选的:
| 进程 | 启动命令 | 默认端口 | 必需性 |
|---|---|---|---|
| 数据服务 | python main.py | 8001 | 必需。API、管理端、用户门户、Agent 运行时、MCP 都在这里。 |
| 节点控制服务 | python -m node_server | 8003 | 用节点/编辑器/任务/终端时必需。不是网页,只接节点连接和数据服务的内部调用。 |
| Tunnel Runtime | python -m tunnel_server | 8004 | 用内网穿透(frp / cloudflared / nps)时必需。 |
| Web 前端 Vite | pnpm dev:offline | 11180 | 调前端页面时用;只调 API 可以不启,直接打 8001。 |
.env 和同一个 PostgreSQL/Redis。它们各自独立解析配置(数据服务读 server/bootstrap_config.py,控制服务读 node_server/config.py),字段含义见 环境变量清单。Compose 里这三个进程是三个容器跑同一个镜像、换 command。1. 环境准备
- Python 3.11(推荐 venv)+
requirements.txt依赖。这一份依赖同时覆盖三个 Python 进程,不需要分别装。 - PostgreSQL 与 Redis(本机、Docker 或远程均可)。Redis 必须 ≥ 6.0:客户端强制
HELLO 3握手,早期版本没有这个命令。 - 前端:Node.js 18+ 与 pnpm(仓库锁文件是
pnpm-lock.yaml)。 - (可选)Go 工具链用于重新构建节点二进制;调试后端通常不需要。
python -m venv .venv
# Linux/macOS
source .venv/bin/activate
# Windows Git Bash
# source .venv/Scripts/activate
pip install -r requirements.txt
cp .env.example .env
2. 启动 PostgreSQL 与 Redis
最简单的方式是只启动 Compose 中的依赖,不启动应用:
docker compose up -d postgres redis
docker compose ps
这会把 PostgreSQL 映射到宿主 127.0.0.1:15432、Redis 映射到 127.0.0.1:6479(不是容器内的 5432/6379)。此时把 .env 指到这两个宿主端口:
POSTGRES_HOST=127.0.0.1
POSTGRES_PORT=15432
POSTGRES_USER=ai_lubricant
POSTGRES_PASSWORD=ai_lubricant
POSTGRES_DATABASE=ai-lubricant
REDIS_HOST=127.0.0.1
REDIS_PORT=6479
REDIS_DB=0
REDIS_PREFIX_KEY=marsview
.env 是扁平的 KEY=VALUE,没有 [section] 节头。.env.example 里的 # [postgres] 只是分组注释。当前代码不解析任何 INI/JSON 配置文件——启动配置只有「环境变量 → .env → 内置默认值」三层,写成 host = 127.0.0.1 这种 INI 风格不会生效。.env 的 host/port 指过去(通常是默认的 5432/6379)。Docker Compose 只负责依赖,不负责前端和节点控制服务。3. 初始化数据库
python server/init_db.py
脚本连接到默认 postgres 库,若不存在则创建 ai-lubricant 数据库,然后执行 sql/init.sql 建表。重复运行是安全的(存在则跳过)。注意路径带 server/,脚本不在仓库根。
app_config['main'] 主配置,需要从既有环境导入配置,或在管理端完成初始化引导(取决于部署流程)。不要用“反复重启”解决配置缺失。4. 启动数据服务
# 常规
python main.py
# 调试开发模式:自动重载
uvicorn main:app --host 0.0.0.0 --port 8001 --reload
# 只监听本机
uvicorn main:app --host 127.0.0.1 --port 8001
python main.py 固定监听 8001(端口写在 main.py 末尾,.env 里的 SERVER_HOST/SERVER_PORT 不生效)。要换地址或端口就用 uvicorn main:app --host ... --port ...。python main.py 没有热重载;日常改代码调试用 uvicorn ... --reload。
main.py 会建双栈监听Windows 上 localhost 先解析 ::1,只绑 0.0.0.0 会让客户端先等一次 IPv6 连接失败(本机约 2 秒)。main.py 显式创建 IPv4/IPv6 双栈 socket 规避;用 uvicorn --host 时没有这层处理,排障统一用 127.0.0.1 而不是 localhost。DEBUG 视为 true(server/config.py),所以本地直跑默认就是调试行为。Compose 的数据服务显式设了 DEBUG=false,生产部署保持这样。5. 启动节点控制服务
python -m node_server
默认监听 0.0.0.0:8003(NODE_CONTROL_HOST / NODE_CONTROL_PORT 可调)。它用 Hypercorn 而非 uvicorn,因为节点的 NodeConnect 走 h2c(明文 HTTP/2),uvicorn 不支持。
仅调试模型网关 API、前端页面或 MCP 时可以先不启动它;数据服务要用到编辑器、任务、终端、文件、节点出口时才会去调 AGENT_COMPOSE_BASE_URL(本地填 http://127.0.0.1:8003)。
.env控制服务启动时若发现没有 NODE_CONTROL_TOKEN 或 NODE_CREDENTIAL_ENCRYPTION_KEY,会生成并写回 .env,因此 .env 必须是可写文件。NODE_CONTROL_TOKEN 是数据服务→控制服务的内部 Bearer,两个进程必须读到同一个值;生成后重启数据服务让它读到新值。6. 启动 Tunnel Runtime(可选)
python -m tunnel_server
默认监听 0.0.0.0:8004(TUNNEL_RUNTIME_HOST / TUNNEL_RUNTIME_PORT 可调)。它负责管理 frpc / cloudflared / npc 客户端子进程——隧道方案管理页和任务预览端口对外暴露都依赖它。不用内网穿透时可以完全不启动,其余功能不受影响。
它自己不直连节点:启停命令都经 AGENT_COMPOSE_BASE_URL 转给节点控制服务,所以要先有 8003 在跑。穿透客户端二进制不随代码分发,首次使用时联网下载并缓存到 MC_TUNNEL_BIN_DIR。
main.py → node_server → tunnel_server 的顺序起,Compose 里靠 depends_on + 健康检查达到同样效果。多实例还有单写者租约(TUNNEL_RUNTIME_LEASE_TTL_SECONDS),同一库不要同时跑两个。7. 启动 Web 前端
cd user-frontend
pnpm install
# 离线/私有化版(默认首页跳到登录),开发端口 11180
pnpm dev:offline
# 在线版
# pnpm dev:online
Vite 默认监听 0.0.0.0:11180。开发服务器把 /api、/admin、/v1、/agent、/mcp 转发到 TARGET(.env.offline 指向 http://localhost:8001;.env.online 使用 VITE_APP_EDITION=online 并默认不设 TARGET)。如果数据服务不在本机 8001,用环境变量或对应 env 文件覆盖 TARGET。
/admin 做了按 Accept 头分流:浏览器 HTML 导航回到 SPA 的 index.html,XHR/fetch 才转发后端。调试管理页面登录时若只见 HTML 不见接口响应,先确认数据服务是否在 TARGET 上运行。管理端在 http://localhost:11180/manager,用户门户在 http://localhost:11180/console。
8. 移动端本地调试
移动端位于 mobile/(独立仓库,以 git submodule 挂在主仓该路径;首次需 git submodule update --init mobile),使用 Expo Router + React Native。它通过 Cookie 会话或 Basic Auth 访问同一套数据服务接口;本地调试时通常先按上文启动数据服务(8001),再让 App 指向该后端。
cd mobile
npm install
# 启动 Metro / Expo 开发服务
npm start
# 真机或模拟器调试
npm run android
npm run ios
启动后在登录页填写后端地址(例如 http://127.0.0.1:8001 或局域网 IP)。Android 模拟器访问宿主机后端时,部分环境需要用 http://10.0.2.2:8001 代替 127.0.0.1。
本地校验
cd mobile
# TypeScript 类型检查(当前仓库必须通过)
npx tsc --noEmit
# ESLint(expo 配置)
npx eslint . --no-cache
# Jest(当前 mobile/ 下暂无 *.test.ts(x) 用例,命令可用但通常没有测试可跑)
npm test -- --runInBand --silent
npx tsc --noEmit。仓库目前未在 mobile/ 内置 Jest 用例,因此“测试通过”主要依赖类型检查、ESLint 和真机/模拟器手测。9. 接口探针
数据服务(8001)
# 存活
curl -s http://127.0.0.1:8001/ | head -20
# MCP 运行时健康
curl -s http://127.0.0.1:8001/mcp/health
# 模型列表(无需鉴权)
curl -s http://127.0.0.1:8001/v1/models | head -c 400; echo
节点控制服务(8003)
# 健康:包含已连接节点数
curl -s http://127.0.0.1:8003/health
Tunnel Runtime(8004)
# 就绪:包含 running / notifier 状态
curl -s http://127.0.0.1:8004/ready
前端开发代理(11180)
# 经 Vite 代理访问后端,验证 /api 与 /admin 转发
curl -s http://127.0.0.1:11180/v1/models | head -c 200; echo
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:11180/manager
GET / 返回 HTML 首页;GET /v1/models 返回包含 data 的 JSON;/mcp/health 返回 {"ok": true, ...};/manager 返回 200(SPA 页面)。10. 日志
- 数据服务文件日志:项目根
logs/ai-lubricant-YYYY-MM-DD.log,按天轮转、保留 30 天并压缩。首次启动时自动创建。 - 标准输出:启动时 loguru 也会输出到控制台。
- 日志级别:文件 sink 固定 DEBUG;
system.debug与logging.level影响业务日志细节。可在管理端主配置页面调整。 - 敏感字段:文件 sink 使用
diagnose=False,异常堆栈不打印变量值,避免把请求密钥写进日志。
# 跟随日志
tail -f logs/ai-lubricant-$(date +%F).log
# 只看最近错误
grep -iE 'error|traceback|exception' logs/ai-lubricant-$(date +%F).log | tail -30
11. 常见故障排查
| 现象 | 原因 | 排查/解决 |
|---|---|---|
| 启动即失败,提示连接 PostgreSQL 失败 | host/port/凭据错误或服务未启动 | 核对 .env 或环境变量;确认 Compose 依赖已 up;从应用容器或宿主机测试端口连通。 |
| 启动失败,提示 Redis ping 失败 | Redis 未启动/地址错误/前缀错误 | redis-cli ping 验证;检查 prefix_key、db 和 max_connections。 |
| “缺少必填主配置 app_config['main']” | 空库只有表结构,没有业务主配置 | 补齐/导入主配置,或完成初始化引导;不要反复重启。 |
| 前端页面能打开,但 API 请求 404/502 | Vite TARGET 指向不对或后端没起 | 确认 curl http://127.0.0.1:8001/v1/models;检查 .env 的 TARGET;看 Vite 控制台代理日志。 |
| /manager 打开空白或一直加载 | 管理会话过期或后端 /admin 不可达 | 先访问 /manager/login 应急登录;确认后端 curl http://127.0.0.1:8001/admin/...。 |
| 节点控制服务拒绝启动,提示无法回写 .env | .env 只读或目录不可写 | 授予进程写权限;检查属主;容器场景确保卷可写。 |
| Tunnel Runtime 起不来 / 一直 not ready | 8003 没起,或 8004 被占,或穿透客户端二进制下载失败 | 先确认 curl http://127.0.0.1:8003/health 通;看 MC_TUNNEL_BIN_DIR 是否可写、是否联网下载了 frpc/cloudflared/npc。 |
| 节点连不上 / 校验失败 | public_url、token 或主密钥不一致,TOTP 时钟偏差 | 核对节点拨号 URL 与 AGENT_COMPOSE_NODE_SERVER_PUBLIC_URL;确认节点时间与服务器时间偏差在 TOTP 窗口内;核对共享 token 和 NODE_CONTROL_TOKEN / NODE_CREDENTIAL_ENCRYPTION_KEY。 |
| ClickHouse 相关对话/统计不可用 | 未启用 ClickHouse 或地址错误 | 主模型代理链路仍可用;确认是否真的需要该特性,再按部署文档启用。 |
| 请求日志出现但响应体为空 | payload 双写未启用或保留策略 | 若需要 payload,开启 ClickHouse capture 并完成隐私/保留评估;普通日志与主链路不依赖它。 |