106 lines
4.7 KiB
Markdown
106 lines
4.7 KiB
Markdown
# TJWaterAgent 内部智能体服务
|
||
|
||
`TJWaterAgent` 是 TJWater 内部版智能体服务,负责连接前端聊天界面、OpenCode 运行时、MCP 工具和 TJWater 后端 API。它面向内部研发与部署,保留完整的 Agent 编排、会话上下文、工具调用和运行时调试能力。
|
||
|
||
## 主要能力
|
||
|
||
- 提供 `POST /api/v1/agent/sessions/{session_id}/runs` SSE 聊天接口。
|
||
- 以内嵌模式启动并预热 OpenCode 运行时。
|
||
- 管理前端 `session_id` 与 OpenCode session 的映射。
|
||
- 在服务端保存当前会话的用户 token、项目、network 和 trace 上下文。
|
||
- 通过 `.opencode/tools` 和 MCP 工具驱动地图定位、图表、SCADA、历史数据和业务 API 调用。
|
||
- 通过 `data/` 保存运行时会话元数据、结果引用和本地状态。
|
||
|
||
## 目录结构
|
||
|
||
```text
|
||
src/ 服务端 TypeScript 源码
|
||
src/routes/ HTTP 路由
|
||
src/chat/ 聊天流和 SSE 事件适配
|
||
src/runtime/ OpenCode 运行时管理
|
||
src/session/ 会话映射和运行上下文
|
||
src/mcp/ MCP 服务与工具桥接
|
||
cli/ Agent 使用的 TypeScript 后端 API CLI
|
||
.opencode/agents/ Agent prompt 和模型行为配置
|
||
.opencode/tools/ OpenCode 自定义工具
|
||
.opencode/skills/ 可复用分析工作流
|
||
node-tests/ Node CLI 测试
|
||
data/ 本地运行时数据,禁止提交
|
||
logs/ 本地日志,禁止提交
|
||
```
|
||
|
||
## 本地开发
|
||
|
||
项目使用 Bun:
|
||
|
||
```bash
|
||
bun install
|
||
bun run dev
|
||
```
|
||
|
||
`bun install` 会通过 `postinstall` 安装 `.opencode` 子目录依赖。`bun run dev` 以 watch 模式启动 `src/server.ts`,修改 `src/**`、`.opencode/**`、`opencode.json` 或 `.local.env` 后会自动重启。
|
||
|
||
`cli/tjwater-cli` 是当前唯一的 TJWater 业务 CLI 入口,由 Bun 直接执行
|
||
`cli/tjwater-cli.ts` 及 `cli/src/` 源码,并随 Agent 镜像一起交付,不需要
|
||
Python 或 PyInstaller 构建步骤。
|
||
|
||
## 常用命令
|
||
|
||
```bash
|
||
bun run check
|
||
bun run contract:generate
|
||
bun run test:api
|
||
bun run test:cli
|
||
bun run start
|
||
bun run start:prod
|
||
docker build -t tjwater-agent:local .
|
||
```
|
||
|
||
- `bun run check`:检查主项目和 `.opencode` 的 TypeScript 类型。
|
||
- `bun run contract:generate`:生成 `contracts/agent-v1.openapi.json`。
|
||
- `bun run test:api`:验证公开 REST 契约和聊天路由。
|
||
- `bun run test:cli`:运行 `node-tests/cli/*.node.mjs`。
|
||
- `bun run start`:直接启动服务。
|
||
- `bun run start:prod`:先类型检查,再启动服务。
|
||
|
||
## 运行模式
|
||
|
||
当前运行时使用 OpenCode 稳定版 1.x CLI,并通过稳定版 SDK 的 `@opencode-ai/sdk/v2` HTTP 客户端访问运行时;这与 `opencode2` 及 `@opencode-ai/client` 的 2.0 beta 运行时不同。Embedded 模式由服务进程拉起本机 OpenCode:
|
||
|
||
```bash
|
||
OPENCODE_MODE=embedded
|
||
TJWATER_API_BASE_URL=http://127.0.0.1:8000
|
||
```
|
||
|
||
当前仅支持 Embedded 模式,不支持连接外部 OpenCode server。
|
||
|
||
## 认证续期与学习工具
|
||
|
||
后端工具调用遇到即将过期的 access token 或首次 `401` 时,Agent 会通过当前 SSE 流发送 `credential_refresh_required`。前端使用服务端保存的 Keycloak refresh token 强制换取新 access token,再调用 `POST /api/v1/agent/sessions/{session_id}/credential-refreshes` 唤醒原工具调用。等待上限为 30 秒,同一会话的并发请求合并为一次续期,原调用最多重试一次;`403` 不触发续期。
|
||
|
||
`memory_manager` 和 `skill_manager` 在 OpenCode 侧只保留内部 HTTP 桥,读取会话上下文和持久化数据的逻辑统一在 Agent 主进程中执行。长期记忆、自动学习和显式工具写入因此共享同一组 `MemoryStore`、`SkillStore` 和运行时会话上下文。
|
||
|
||
本地可使用 `.local.env` 保存开发配置;系统环境变量优先级更高。
|
||
|
||
服务会在 HTTP 端口开始监听前完成 OpenCode 健康检查、临时会话创建和工具目录加载。`GET /health` 返回 `ready: true` 与 `warmed_up: true` 时,表示冷启动预热已经完成。开发环境会输出各预热阶段的耗时。
|
||
|
||
`opencode.json` 已启用 `experimental.continue_loop_on_deny`。用户拒绝权限请求后,OpenCode V1 会把拒绝结果交还给 Agent,让其尝试无需该权限的替代方案,而不是直接结束本轮执行。
|
||
|
||
## 配置与安全
|
||
|
||
不要提交 `.env`、`.local.env`、`data/`、`logs/`、会话记录、模型输出、访问令牌或 `node_modules/`。部署凭据、镜像仓库账号和 webhook 地址应放在 Gitea secrets 或部署环境变量中。
|
||
|
||
## 发布
|
||
|
||
Gitea 包工作流位于 `.gitea/workflows/package.yml`。发布前至少运行:
|
||
|
||
```bash
|
||
bun run check
|
||
```
|
||
|
||
如修改 CLI 或工具调用逻辑,同时运行:
|
||
|
||
```bash
|
||
bun run test:cli
|
||
```
|