diff --git a/README.md b/README.md index 884c004..aaeb5b5 100644 --- a/README.md +++ b/README.md @@ -1,345 +1,92 @@ -# TJWaterAgent 目录结构说明 +# TJWaterAgent 内部智能体服务 -`TJWaterAgent/` 是新的 opencode Agent 服务工程目录,负责对外提供 TJWater 智能助手接口,并通过 opencode SDK 启动或连接 opencode 运行时。 +`TJWaterAgent` 是 TJWater 内部版智能体服务,负责连接前端聊天界面、OpenCode 运行时、MCP 工具和 TJWater 后端 API。它面向内部研发与部署,保留完整的 Agent 编排、会话上下文、工具调用和运行时调试能力。 -## 总体边界 +## 主要能力 + +- 提供 `POST /api/v1/agent/chat/stream` SSE 聊天接口。 +- 支持 embedded OpenCode 运行时,也可连接外部 OpenCode server。 +- 管理前端 `session_id` 与 OpenCode session 的映射。 +- 在服务端保存当前会话的用户 token、项目、network 和 trace 上下文。 +- 通过 `.opencode/tools` 和 MCP 工具驱动地图定位、图表、SCADA、历史数据和业务 API 调用。 +- 通过 `data/` 保存运行时会话元数据、结果引用和本地状态。 + +## 目录结构 ```text -TJWaterAgent/ - package.json - tsconfig.json - src/ - opencode.json - .opencode/ - agents/ - tools/ - skills/ - package.json - tsconfig.json +src/ 服务端 TypeScript 源码 +src/routes/ HTTP 路由 +src/chat/ 聊天流和 SSE 事件适配 +src/runtime/ OpenCode 运行时管理 +src/session/ 会话映射和运行上下文 +src/mcp/ MCP 服务与工具桥接 +.opencode/agents/ Agent prompt 和模型行为配置 +.opencode/tools/ OpenCode 自定义工具 +.opencode/skills/ 可复用分析工作流 +node-tests/ Node CLI 测试 +data/ 本地运行时数据,禁止提交 +logs/ 本地日志,禁止提交 ``` -| 位置 | 主要作用 | 典型内容 | -| --- | --- | --- | -| `TJWaterAgent/` | 服务宿主、API 层和编排层 | Express 服务、SSE 接口、会话管理、鉴权上下文、后端 API 代理、opencode SDK 启动逻辑 | -| `TJWaterAgent/.opencode/` | opencode 项目资产目录 | agent prompt、自定义 tools、skills 树、plugins 相关依赖 | +## 本地开发 -## `TJWaterAgent/` 根目录的职责 - -根目录是 Node/TypeScript 服务本体,主要负责: - -1. 启动 HTTP 服务。 -2. 通过 `@opencode-ai/sdk` 启动内嵌 opencode server,或连接外部 opencode server。 -3. 管理前端 `session_id -> opencode sessionId` 的映射。 -4. 保存并传递后端认证后的用户 token、metadata 用户 ID、项目 ID 和 trace。 -5. 把 opencode 输出适配成前端需要的 SSE 事件。 -6. 为 `.opencode/tools/tjwater_cli.ts` 提供内部回调接口。 -7. 代理调用真实 TJWater 后端 API。 - -当前 Agent API 的主入口: - -```text -POST /api/v1/agent/chat/stream -``` - -该接口返回 SSE,事件包括: - -| event | 用途 | -| --- | --- | -| `progress` | 前端过程可视化,展示规划、工具调用和完成状态 | -| `token` | 最终回答文本流 | -| `tool_call` | 前端地图/面板/图表动作 | -| `done` | 当前轮完成 | -| `error` | 当前轮失败 | -| `auth_required` | 运行中 access token 过期或被后端拒绝,需要前端刷新登录态后重试 | - -主要目录和文件: - -```text -src/ - server.ts - config.ts - runtime/ - session/ - chat/ - routes/ - tools/ -``` - -其中 `src/` 是业务服务层,不直接放 opencode skill 或 agent prompt。 - -## `.opencode/` 的职责 - -`.opencode/` 是给 opencode 运行时读取的项目资产目录,不是对外 HTTP 服务的主代码目录。 - -### agents - -```text -.opencode/agents/agent.md -``` - -这里定义默认 agent 的角色、行为规则、模型配置和工具使用策略。 - -当前项目已将 always-loaded instructions 收敛到 `agent.md`,`opencode.json` 不再额外配置 `instructions` 数组。 - -### tools - -```text -.opencode/tools/ - tjwater_cli.ts - store_render_ref.ts - locate_features.ts - view_history.ts - view_scada.ts - show_chart.ts - render_junctions.ts - apply_layer_style.ts - memory_manager.ts - session_search.ts - skill_manager.ts -``` - -这些是 opencode 可以调用的自定义工具。 - -`tjwater_cli.ts` 不直接保存用户 token。它会回调 `TJWaterAgent` 的内部接口,由上级服务层根据当前 session 补上用户 token、项目 ID 和 trace ID,再调用 `tjwater-cli` 二进制执行后端命令。 - -`store_render_ref.ts` 用于把大型 junction 渲染 payload 存成 `render_ref`,再由 `render_junctions.ts` 交给前端回读并渲染。 - -前端类工具如 `locate_features`、`view_history`、`view_scada`、`show_chart`、`render_junctions`、`apply_layer_style` 主要用于触发 UI 动作或可视化,不应被当作数据查询工具。 - -### skills - -```text -.opencode/skills/ - SKILL.md - examples.md - runbook.md - tjwater-cli/ ← tjwater-cli 可执行文件 - workflow/ ← 可复用分析工作流 - SKILL.md - simulation-diagnosis/ - bottleneck-analysis/ - source-service-area-analysis/ -``` - -Skills 仅保留可复用的多步工作流。Agent 通过 `tjwater-cli help` 自行发现原子命令,无需逐接口技能树。 - -agent 加载技能树时按需取用对应 workflow skill。 - -## 依赖边界 - -根目录和 `.opencode/` 使用两组 npm 依赖,职责不同。 - -### 根目录依赖 - -```text -TJWaterAgent/package.json -``` - -用于服务本体,例如: - -```text -@opencode-ai/sdk -express -zod -pino -``` - -### `.opencode` 依赖 - -```text -TJWaterAgent/.opencode/package.json -``` - -用于 opencode 自定义 tools/plugins,例如: - -```text -@opencode-ai/plugin -typescript -@types/node -``` - -这两组依赖不要混在一起:根目录负责服务运行,`.opencode` 负责 opencode 扩展资产的类型检查和运行依赖。 - -## 启动与部署 - -支持两种 opencode 接入方式: - -1. Embedded 模式:服务通过 `@opencode-ai/sdk` 调用 `createOpencode`,启动本地 `opencode` CLI 子进程并自动创建 client。 -2. Client 模式:服务通过 `createOpencodeClient` 直接连接一个已经存在的 opencode server。 - -因此,只有 Embedded 模式要求运行环境已安装 `opencode` CLI;Client 模式不依赖本地 CLI。 - -根目录的 Bun scripts 已经封装 `.opencode` 依赖安装和类型检查,日常只需要在 `TJWaterAgent/` 根目录操作。 - -### 本地开发 +项目使用 Bun: ```bash -cd TJWaterAgent bun install bun run dev ``` -`bun install` 会通过 `postinstall` 自动执行 `.opencode` 依赖安装;`bun run dev` 启动前会检查 `.opencode/tools` 的类型。 +`bun install` 会通过 `postinstall` 安装 `.opencode` 子目录依赖。`bun run dev` 以 watch 模式启动 `src/server.ts`,修改 `src/**`、`.opencode/**`、`opencode.json` 或 `.local.env` 后会自动重启。 -开发模式支持热重载,以下文件变化会触发服务重启并重新拉起 embedded opencode: +## 常用命令 -```text -src/** -.opencode/** -opencode.json -.local.env +```bash +bun run check +bun run test:cli +bun run start +bun run start:prod +docker build -t tjwater-agent:local . ``` -因此修改 agent prompt、tools、skills、模型配置或本地环境变量后,不需要手动重启 `bun run dev`。 +- `bun run check`:检查主项目和 `.opencode` 的 TypeScript 类型。 +- `bun run test:cli`:运行 `node-tests/cli/*.node.mjs`。 +- `bun run start`:直接启动服务。 +- `bun run start:prod`:先类型检查,再启动服务。 -本地开发可以在项目根目录的 `.local.env` 中配置环境变量。 +## 运行模式 -Embedded 模式示例: +Embedded 模式由服务进程拉起本机 OpenCode: ```bash OPENCODE_MODE=embedded -DEEPSEEK_API_KEY=sk-xxx TJWATER_API_BASE_URL=http://127.0.0.1:8000 ``` -Client 模式示例: +Client 模式连接外部 OpenCode server: ```bash OPENCODE_MODE=client OPENCODE_CLIENT_BASE_URL=http://127.0.0.1:4096 -DEEPSEEK_API_KEY=sk-xxx TJWATER_API_BASE_URL=http://127.0.0.1:8000 ``` -服务启动时会自动读取 `.local.env`,但系统环境变量优先级更高,适合在本机保存开发用 key。 +本地可使用 `.local.env` 保存开发配置;系统环境变量优先级更高。 -### 生产启动 +## 配置与安全 + +不要提交 `.env`、`.local.env`、`data/`、`logs/`、会话记录、模型输出、访问令牌或 `node_modules/`。部署凭据、镜像仓库账号和 webhook 地址应放在 Gitea secrets 或部署环境变量中。 + +## 发布 + +Gitea 包工作流位于 `.gitea/workflows/package.yml`。发布前至少运行: ```bash -cd TJWaterAgent -bun install bun run check -bun run start ``` -也可以使用一条命令完成构建并启动: +如修改 CLI 或工具调用逻辑,同时运行: ```bash -cd TJWaterAgent -bun install -bun run start:prod +bun run test:cli ``` - -### Docker Compose 启动 - -项目根目录已提供 `Dockerfile` 和 `docker-compose.yml`,可直接使用: - -```bash -cd TJWaterAgent -docker compose up -d --build -``` - -查看日志: - -```bash -docker compose logs -f tjwater-agent -``` - -停止并清理容器: - -```bash -docker compose down -``` - -### 常用脚本 - -| 命令 | 作用 | -| --- | --- | -| `bun run dev` | 类型检查 `.opencode` tools 后,以 watch 模式直接运行 `src/server.ts` | -| `bun run check` | 执行完整类型检查(服务与 `.opencode` tools) | -| `bun run start` | 直接运行 `src/server.ts` | -| `bun run start:prod` | 先类型检查再启动 | -| `bun run install:opencode` | 手动安装 `.opencode` 依赖 | -| `bun run pipeline:trigger` | 通过重建并强推 annotated `latest` tag 触发 Gitea CI/CD,只发布/覆盖 `latest` 镜像 | - -### 模型与 API 配置 - -默认 Agent 模型为: - -```text -deepseek/deepseek-v4-flash -``` - -默认聊天模型配置组为: - -```json -[ - { - "id": "deepseek/deepseek-v4-flash", - "label": "快速", - "description": "快速回答和任务执行", - "icon": "bolt" - }, - { - "id": "deepseek/deepseek-v4-pro", - "label": "专家", - "description": "探索、解决复杂任务", - "icon": "sparkle" - } -] -``` - -涉及位置: - -```text -src/chat/modelConfig.ts 的默认模型配置组 -src/config.ts 的 OPENCODE_MODEL 与 OPENCODE_MODEL_OPTIONS 默认值 -opencode.json 的 opencode 运行时默认模型 -``` - -如果需要临时覆盖默认模型和模型配置组,可以在启动时设置: - -```bash -OPENCODE_MODEL=deepseek/deepseek-v4-pro \ -OPENCODE_MODEL_OPTIONS='[{"id":"deepseek/deepseek-v4-flash","label":"快速","description":"快速回答和任务执行","icon":"bolt"},{"id":"deepseek/deepseek-v4-pro","label":"专家","description":"探索、解决复杂任务","icon":"sparkle"}]' \ -bun run start -``` - -DeepSeek API key 不写入代码,部署时通过环境变量设置: - -```bash -DEEPSEEK_API_KEY=sk-xxx bun run start -``` - -`opencode.json` 已配置从环境变量读取: - -```json -{ - "provider": { - "deepseek": { - "options": { - "apiKey": "{env:DEEPSEEK_API_KEY}" - } - } - } -} -``` - -如果需要自定义 DeepSeek 兼容 API 地址,可以通过 opencode 的 provider 配置增加 `baseURL`,例如在部署环境使用 `OPENCODE_CONFIG_CONTENT` 覆盖: - -```bash -OPENCODE_CONFIG_CONTENT='{"provider":{"deepseek":{"options":{"baseURL":"https://your-api.example.com/v1"}}}}' \ -DEEPSEEK_API_KEY=sk-xxx \ -bun run start -``` - -也可以使用 opencode 的 `/connect` 命令写入用户级凭据,但服务部署更推荐使用环境变量。 - -如果需要连接外部独立运行的 opencode server,可以配置: - -```bash -OPENCODE_MODE=client -OPENCODE_CLIENT_BASE_URL=http://127.0.0.1:4096 -``` - -配置后,`TJWaterAgent` 会连接该外部 opencode server,而不是自行启动 embedded opencode server。