362 lines
23 KiB
Markdown
362 lines
23 KiB
Markdown
# TJWater 供水 Agent
|
||
|
||
这个服务把供水 WebGIS 中的对话、数据查询、地图操作和工况任务接到 OpenCode 2。浏览器负责展示和交互,Agent 编排工具,TJWater Server 校验身份、项目权限并保存业务状态。
|
||
|
||
本仓库仍是实验服务,与历史 `TJWaterAgent` 仓库独立。排水业务由排水 Agent 仓库维护。
|
||
|
||
## 配置文件在哪里
|
||
|
||
| 要修改什么 | 文件或位置 | 说明 |
|
||
| --- | --- | --- |
|
||
| 模型、provider、API 地址、默认模型 | [agent-models.json](agent-models.json) | 模型配置的唯一入口 |
|
||
| API key、服务地址、端口等环境变量 | 仓库根目录 `.local.env` | 本地私有文件,已被 Git 忽略;字段参考 [.env.example](.env.example) |
|
||
| 工具权限、外部 MCP 连接 | [opencode.json](opencode.json) | 不再单独配置模型和 provider |
|
||
| Agent 的业务指令 | [.opencode/agents/instruction.md](.opencode/agents/instruction.md) | 指令文件不指定模型 |
|
||
| Agent、插件、Skill 和 MCP 的管理索引 | [.opencode/agent-plugin.json](.opencode/agent-plugin.json) | 描述用途和实际配置入口;管理方法见 [.opencode/README.md](.opencode/README.md) |
|
||
| 代码修改规则 | [AGENTS.md](AGENTS.md) | 面向维护代码的 Agent |
|
||
|
||
服务自动读取根目录的 `.local.env`,已有系统环境变量优先。普通启动不会自动读取 `.env`;部署时应由容器或进程管理器注入环境变量。
|
||
|
||
如果不想修改仓库自带的模型配置,可以复制为 `agent-models.local.json`,再在 `.local.env` 中设置:
|
||
|
||
```dotenv
|
||
AGENT_MODEL_CONFIG_PATH=./agent-models.local.json
|
||
```
|
||
|
||
该文件已被 Git 和镜像构建忽略。它会替换整份模型配置,不与 `agent-models.json` 合并;相对路径按启动目录解析。
|
||
|
||
## 本地启动
|
||
|
||
在本仓库目录执行命令。运行环境需要 Bun、OpenCode 2、Python 3 和 `libseccomp2`,Linux 内核需支持 Landlock ABI 4 或更高版本。服务启动时会实际探测沙箱,失败会停止启动。
|
||
|
||
仓库使用 OpenCode `2.0.24`,安装并检查 CLI:
|
||
|
||
```bash
|
||
bun add --global --trust --exact @opencode/cli@2.0.24
|
||
opencode2 --version
|
||
bun install
|
||
```
|
||
|
||
首次配置时创建本地环境文件,已有文件则直接编辑:
|
||
|
||
```bash
|
||
test -e .local.env || cp .env.example .local.env
|
||
chmod 600 .local.env
|
||
```
|
||
|
||
在 `.local.env` 中填写启用的 provider 所需密钥,以及 TJWater Server 的实际地址。下面只列字段,密钥占位值需要替换:
|
||
|
||
```dotenv
|
||
HOST=127.0.0.1
|
||
PORT=8787
|
||
OPENCODE_MODE=embedded
|
||
TJWATER_SERVER_BASE_URL=http://127.0.0.1:8000
|
||
WATERNETWORK_API_KEY=replace-with-your-key
|
||
```
|
||
|
||
默认仅启用 WaterNetwork,填写 `WATERNETWORK_API_KEY` 即可。增加其他 provider 时,还需提供对应凭据,并将默认模型引用指向有效的已配置模型。
|
||
|
||
配置完成后检查模型,再启动服务:
|
||
|
||
```bash
|
||
bun run check:models
|
||
bun run dev
|
||
```
|
||
|
||
另开一个终端查看启动结果,地址和端口按实际配置替换:
|
||
|
||
```bash
|
||
curl --fail http://127.0.0.1:8787/health
|
||
```
|
||
|
||
正常响应中 `ok`、`ready`、`warmed_up` 均为 `true`,并包含 OpenCode 版本和沙箱探测结果。`bun run dev` 使用 watch 模式;无 watch 的启动命令是 `bun run start`。修改模型配置或密钥后需重启服务,不依赖 watch 自动加载配置文件。
|
||
|
||
开发环境允许无凭据的本地对话,但访问 Server 业务数据仍需产品凭据。生产环境中的聊天接口要求 `Authorization: Bearer ...` 和 `X-Project-Id`,用户身份和项目权限由 Server 验证。项目 ID 应使用 Server 返回的项目 UUID;本地上下文头不能替代产品鉴权。
|
||
|
||
## 配置模型和自定义 provider
|
||
|
||
[agent-models.json](agent-models.json) 同时控制聊天菜单和 OpenCode 的模型定义。当前仅包含地址为 `https://llm.waternetwork.cn/v1` 的 `waternetwork` provider,保留两个模型:`gpt-6-luna` 显示为“快速”,使用闪电图标;`gpt-6.1-sol` 显示为“专家”,使用星光图标。两者的上下文窗口均配置为 272,000 tokens。
|
||
|
||
三个默认模型分别用于:
|
||
|
||
| 字段 | 用途 | 当前配置 |
|
||
| --- | --- | --- |
|
||
| `default_model` | 普通聊天默认值 | `waternetwork/gpt-6-luna` |
|
||
| `task_model` | 后台工况任务首选模型 | `waternetwork/gpt-6-luna` |
|
||
| `learning_gate_model` | 判断是否需要学习复盘 | `waternetwork/gpt-6-luna` |
|
||
|
||
后两项省略时沿用 `default_model`。三个引用都必须指向已定义、启用且声明支持文本输出和工具调用的模型;聊天默认模型还必须在菜单中可选。
|
||
|
||
### 使用 WaterNetwork 的最小配置
|
||
|
||
下面是一份完整示例,三个用途都使用 `gpt-6.1-sol`。可以将它保存到自己的模型配置文件中:
|
||
|
||
```json
|
||
{
|
||
"default_model": "waternetwork/gpt-6.1-sol",
|
||
"task_model": "waternetwork/gpt-6.1-sol",
|
||
"learning_gate_model": "waternetwork/gpt-6.1-sol",
|
||
"providers": {
|
||
"waternetwork": {
|
||
"name": "WaterNetwork",
|
||
"api_url": "https://llm.waternetwork.cn/v1",
|
||
"api_key": "{env:WATERNETWORK_API_KEY}",
|
||
"models": {
|
||
"gpt-6.1-sol": {
|
||
"name": "通用助手",
|
||
"description": "对话与任务处理",
|
||
"icon": "sparkle",
|
||
"limit": { "context": 272000 }
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
新增其他 provider 时,在 `providers` 下增加同样结构的一项,并换成自己的地址、密钥变量名和模型名。provider 名只允许字母、数字、下划线和连字符。
|
||
|
||
`api_url` 填 API 基础地址,例如以 `/v1` 结尾的地址,不填 `/chat/completions`;不允许在地址中嵌入账号、密码、查询参数或片段。默认使用 OpenAI compatible 运行包,真实密钥始终放在环境变量中。
|
||
|
||
| 模型字段 | 怎么填写 |
|
||
| --- | --- |
|
||
| `models` 的键 | Agent 使用的模型名;完整引用为 `provider/模型名` |
|
||
| `model_id` | 上游实际接收的名称,省略时与键名相同;支持 `org/model` 这样的名称 |
|
||
| `name`、`description`、`icon` | 聊天菜单的名称、说明和图标;图标可用 `bolt` 或 `sparkle` |
|
||
| `disabled: true` | 禁用模型,不进入聊天菜单,也不参与运行时校验 |
|
||
| `selectable: false` | 从聊天菜单隐藏,仍可供后台或学习使用,仍需通过校验 |
|
||
| `capabilities` | 工具调用和输入、输出类型;默认声明支持工具调用和文本输入、输出 |
|
||
| `limit`、`compatibility` | provider 所需的上下文限制和兼容设置,按实际服务能力填写 |
|
||
|
||
DeepSeek provider 已停用,默认角色不再引用它。重新启用 Flash 时,模型名使用 `deepseek-flash`;其他自定义别名可通过 `model_id` 映射到上游名称。配置文件使用标准 JSON,移除停用条目或给模型设置 `disabled: true`,不使用注释禁用配置。
|
||
|
||
旧的 `OPENCODE_MODEL`、`OPERATIONAL_TASK_MODEL`、`OPENCODE_MODEL_OPTIONS` 环境变量已不控制模型选择。在 `opencode.json` 或指令文件中另写模型定义也不会覆盖统一配置。
|
||
|
||
### 保存后检查模型
|
||
|
||
```bash
|
||
bun run check:models
|
||
```
|
||
|
||
该命令启动独立的 OpenCode 2,核对所有未禁用模型的注册结果、启用状态、工具能力声明和实际请求名称,再由插件使用 OpenCode 生效的 provider 配置读取上游 `/models` 目录。手工注册了一个名字,也必须在上游目录中找到对应名称才能通过。
|
||
|
||
命令不发送模型推理请求,结束后清理自己启动的进程和临时目录。检查通过表示模型名称和运行时配置一致;模型的推理效果、额度和实际工具调用表现需在使用时验证。
|
||
|
||
使用 Ctrl+C 或发送 SIGTERM 取消检查时,命令会等待自己的 OpenCode 子进程退出,再清理临时目录。
|
||
|
||
Agent 启动时也执行同一检查,失败则不监听 HTTP。常见结果如下:
|
||
|
||
| 检查结果 | 排查方向 |
|
||
| --- | --- |
|
||
| `not_advertised` | 上游没有该名称,检查 `model_id` 和 provider 的模型目录 |
|
||
| `not_registered`、`not_enabled` | OpenCode 未加载或未启用该定义;client 模式需同步配置 |
|
||
| `wire_id_mismatch`、`no_tools` | 运行时的名称映射或工具能力声明与配置不一致 |
|
||
| `credentials_unavailable` | OpenCode 没有取得该 provider 的凭据 |
|
||
| `catalog_unavailable` | 检查网络、API 基础地址或鉴权;HTTP 401/403 应排查凭据和权限 |
|
||
| `catalog_invalid` | `/models` 返回的数据结构不符合预期 |
|
||
| `unsupported_catalog` | 当前检查器不支持该运行包的目录接口 |
|
||
|
||
检查器支持 OpenAI compatible、OpenAI、OpenRouter 和 xAI 运行包的 `/models` 目录,其他运行包会拒绝启动。报告不输出密钥、连接地址或上游原始错误内容。
|
||
|
||
## Agent 与 OpenCode 的运行方式
|
||
|
||
默认 `OPENCODE_MODE=embedded`,Agent 启动和关闭自己的 OpenCode 子进程,并自动管理连接密码和内部工具桥密钥。`OPENCODE_COMMAND` 可指定 CLI 的绝对路径,`OPENCODE_PORT=0` 让系统分配空闲端口。
|
||
|
||
`OPENCODE_MODE=client` 用于连接单独管理的 OpenCode 服务,需要配置 `OPENCODE_CLIENT_BASE_URL`、`OPENCODE_CLIENT_PASSWORD`,并在两个进程中设置相同的稳定 `AGENT_INTERNAL_TOKEN`。
|
||
|
||
外部 OpenCode 还需通过 `serviceOpencodeConfig` 加载同一份模型配置、可信插件包 `.opencode/tjwater-plugin/` 和业务指令。其 `TJWATER_AGENT_WORKSPACE_ROOT` 必须与 Agent 的 `CONVERSATION_WORKSPACE_ROOT` 指向同一个绝对目录,同时设置 `TJWATER_AGENT_INTERNAL_BASE_URL` 指向 Agent 内部工具桥。只启动一个普通 OpenCode 服务不足以完成接入;缺少业务工具、模型检查 RPC 或目录绑定会导致预热失败。
|
||
|
||
要保留已有服务进行隔离联调,可以使用仓库启动器:
|
||
|
||
```bash
|
||
bun run start:integration:isolated
|
||
```
|
||
|
||
默认端口为 Agent `18787`、OpenCode `14096`,数据保存在 `data/integration-18787/`,不复用默认会话数据。可通过 `INTEGRATION_AGENT_PORT`、`INTEGRATION_OPENCODE_PORT` 和 `INTEGRATION_DATA_DIR` 修改。启动器负责配对配置和停止自己创建的两个进程。
|
||
|
||
## `.agent-workspaces` 是什么
|
||
|
||
这是会话的文件工作区,默认位置由 `CONVERSATION_WORKSPACE_ROOT=./.agent-workspaces` 决定。每创建一个会话,就创建一个独立目录,即使该会话尚未调用 Shell,也可能已有空工作区:
|
||
|
||
```text
|
||
.agent-workspaces/
|
||
└── conversation-<uuid>/
|
||
├── files/ 生成文件、计算脚本、结果和较长的 Shell 输出
|
||
├── tmp/ 临时文件
|
||
└── .cache/ 运行缓存
|
||
```
|
||
|
||
OpenCode 会话保存与该目录的绑定,恢复时继续使用原目录。会话分支使用独立的空工作区;历史上绑定到仓库根目录的旧会话会在继续执行前迁入新工作区,不复制源码、凭据或其他会话文件。
|
||
|
||
Shell 默认在 `files/` 中运行,只能写入上述三个子目录,工作区根目录只读。目录隔离配合 Landlock 和 seccomp 限制文件访问、网络与进程行为;目录本身不等于 OS 沙箱。限制覆盖 Shell 及其子进程,OpenCode 服务和类型化业务工具仍由可信宿主进程运行。本地 stdio MCP 也不在这个沙箱中。
|
||
|
||
Shell 和文件修改需要用户审批,即使聊天设置了 `approval_mode=always` 也会请求确认。Shell 不能联网或访问源码、密钥、其他会话;业务查询、网页搜索和地址解析使用类型化工具。超时单位为秒,默认 120 秒、最大 1800 秒;stdout 默认限制 1 MiB、stderr 最多 256 KiB、单文件最多 128 MiB。较长输出以文件保存在 `files/`,工具返回预览和路径;取消、超时、超限和命令结束均清理该进程组,不保留后台进程。
|
||
|
||
工作区已被 Git 和镜像构建忽略,但其中的文件需要随会话保留。目前没有自动过期清理,删除聊天记录也不会同步删除工作区。启动探测、预热和创建失败产生的临时工作区会清理。
|
||
|
||
删除仍被会话引用的目录会丢失生成文件,并可能使会话后续文件操作失败。需要改变根目录时,应同步保留会话数据库及目录绑定,不能只改环境变量后丢弃原目录。服务目前没有工作区附件下载接口。
|
||
|
||
持久化部署需要分别保存:
|
||
|
||
| 数据 | 默认位置 | 用途 |
|
||
| --- | --- | --- |
|
||
| 会话文件 | `.agent-workspaces/` | 文件计算和生成结果 |
|
||
| Agent 数据 | `data/` | 会话元数据、对话记录、记忆、学习状态和结果引用 |
|
||
| Skill 文件 | `.opencode/skills/` | 工具可读取的 Skill,目录可由 `OPENCODE_SKILLS_ROOT_DIR` 指定 |
|
||
| OpenCode 数据 | OpenCode 的 XDG 数据目录 | 原生会话数据库;部署时保留对应数据卷 |
|
||
| 日志 | `logs/` | 运行审计和学习日志 |
|
||
|
||
仅持久化 `data/` 无法保留会话生成的文件。`result_ref` 有独立的过期清理,不代表工作区也会自动清理。
|
||
|
||
## 当前能做什么
|
||
|
||
| 场景 | 工具或协议 | 说明 |
|
||
| --- | --- | --- |
|
||
| 查询供水数据 | `query_project_data` | 有限数据源:元素属性、SCADA 设备与历史、元素历史、分析运行和分页结果 |
|
||
| 地图与图表交互 | `locate_features`、`zoom_to_map`、`show_chart`、`view_history` | 通过 `frontend-action@1` 等待浏览器实际回执 |
|
||
| SCADA 地图分析 | `render_scada_analysis`、`clear_scada_analysis` | 展示和清除受控叠加层 |
|
||
| 网页搜索与地址解析 | `web_search`、`geocode` | 调用 Server 的 Bocha、天地图接口,模型不能指定任意 URL 或鉴权头 |
|
||
| 工况任务 | 查询、计划、报告、行动建议和人工证据工具 | 通过 Server 的任务与运行身份访问业务 |
|
||
| 会话与学习 | `session_search`、`memory_manager`、`skill_manager` | 按会话、用户和项目范围管理记录、记忆和 Skill |
|
||
| 本地计算 | `shell` | 在会话 OS 沙箱中运行经过审批的命令 |
|
||
| 外部资料和工具 | MCP 客户端 | 由管理员配置,并按会话权限调用 |
|
||
|
||
历史查询的时间窗口最长 24 小时,SCADA 字段限 `monitored_value` 和 `cleaned_value`;物理指标和单位以设备元数据为准。历史查询由 Server 校验只读权限,清洗操作仍需清洗权限。`view_history` 当前最多展示 100 个非空样本,不代表完整高频历史;缺失资产和历史缺数会返回实际状态。
|
||
|
||
`web_search` 支持 freshness、summary、1 至 50 条结果以及域名筛选;`geocode` 返回 `center=[lon,lat]`、`source_crs=EPSG:4326`,可用于地图定位。服务密钥配置在 Server 的 `BOCHA_API_KEY` 和 `TIANDITU_GEOCODER_TOKEN` 中。
|
||
|
||
后台执行由 worker 提交 Server 已保存的 `task_id`、`run_id`、`execution_request_id`。Agent claim 成功后每 20 秒发送心跳,运行正常结束显式调用 `complete`,失败或中止调用 `fail`。Server 决定活动运行和租约状态;计划、报告或 `final_answer` 的发布不代表业务任务完成。执行计划规则见 [工况执行计划](docs/execution-plan.md)。
|
||
|
||
交互会话遇到 `credential_refresh_required` 后,前端更新凭据;令牌只通过鉴权头传递,工具请求最多重试一次,403 不触发续期。后台 worker 使用已有 OAuth provider 更新凭据,不等待浏览器;无法写回失败时仍由 Server 的租约恢复处理。
|
||
|
||
服务保留 `agent-ui@1` UIEnvelope 兼容接口,目前该注册表为空。当前 6 个浏览器动作使用独立的 `frontend-action@1` 注册表;前端需声明能力并回传动作结果。待办使用 `todoread`、`todowrite`,通过 `todo_update` 更新前端。协议见 [Agent UI 协议](docs/agent-ui-protocol.md)。
|
||
|
||
大结果文件中转、供水瓶颈和服务区算法仍未从旧仓库迁入。
|
||
|
||
## 配置外部 MCP
|
||
|
||
在 `opencode.json` 的 `mcp.servers` 中添加服务,或由部署环境提供 `OPENCODE_CONFIG_CONTENT`。默认未连接任何外部 MCP。连接地址、命令和凭据由管理员配置,不接受浏览器或模型临时提交。
|
||
|
||
下面给出远程 HTTP 和本地 stdio 两种配置片段,示例均禁用,填写真实连接信息后再启用:
|
||
|
||
```json
|
||
{
|
||
"mcp": {
|
||
"timeout": { "startup": 10000, "catalog": 10000, "execution": 60000 },
|
||
"servers": {
|
||
"mcp_docs": {
|
||
"type": "remote",
|
||
"url": "https://mcp.example.com/mcp",
|
||
"protocol": "auto",
|
||
"oauth": false,
|
||
"headers": { "Authorization": "Bearer {env:MCP_DOCS_TOKEN}" },
|
||
"disabled": true
|
||
},
|
||
"mcp_company": {
|
||
"type": "local",
|
||
"command": ["node", "/opt/company-mcp/server.js"],
|
||
"cwd": "/opt/company-mcp",
|
||
"environment": { "MCP_API_KEY": "{env:COMPANY_MCP_API_KEY}" },
|
||
"protocol": "legacy",
|
||
"disabled": true
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
服务名必须以 `mcp_` 开头。远程默认使用 `auto`,本地默认使用 `legacy`;代码还支持显式协议值 `2026-07-28`。超时单位为毫秒,默认启动和目录查询各 10 秒、执行 60 秒,可按服务覆盖。`codemode` 默认开启,改为 `false` 时直接暴露工具,两种方式使用同一权限策略。
|
||
|
||
管理员核实为只读的工具,可以在 `permissions` 中添加精确的自动放行规则;名称以会话 MCP 状态接口返回的工具 ID 为准,后续匹配的拒绝规则仍生效:
|
||
|
||
```json
|
||
{ "action": "mcp_docs_search", "resource": "*", "effect": "allow" }
|
||
```
|
||
|
||
宽泛的 `mcp_* allow`、服务自报的 `readOnlyHint` 和历史审批不构成只读白名单。普通聊天和任务协作中,白名单外调用需用户审批;后台任务只能调用白名单工具,学习复盘禁用 MCP。通用 MCP 资源读取也受会话策略约束,外部结果不能直接替代 Server 保存的业务证据。
|
||
|
||
需要 OAuth 的服务应省略 `oauth: false`,由管理员以同一服务账号和 XDG 数据目录执行 `opencode2 mcp auth mcp_docs`。TJWater 的 Bearer 和项目头不会自动转交外部 MCP。
|
||
|
||
本地 stdio MCP 是管理员信任的宿主进程,不受会话 Shell 沙箱约束。插件收敛继承环境,只传入基础运行变量及明确配置的 MCP 环境;该进程仍有服务账号的宿主文件和网络权限。
|
||
|
||
会话 MCP 状态接口返回服务名、类型、状态、配置协议和工具 ID,不返回连接地址、命令或凭据。状态可能为 `connected`、`pending`、`disabled`、`failed`、`needs_auth`;配置协议不代表实际协商版本,连接成功也不代表工具目录已加载。结构错误会阻止启动,可选服务连接失败或等待 OAuth 不影响核心服务就绪。
|
||
|
||
## 前端与任务接入
|
||
|
||
聊天 API 的前缀是 `/api/v1/agent/chat`。生产请求需携带产品 Bearer 和项目头;涉及会话的操作还校验会话归属。
|
||
|
||
| 方法 | 路径 | 用途 |
|
||
| --- | --- | --- |
|
||
| GET | `/health` | OpenCode 和沙箱就绪状态,无聊天前缀 |
|
||
| GET | `/models` | 聊天模型菜单与默认值,不含 provider 凭据 |
|
||
| POST | `/session` | 创建会话 |
|
||
| GET | `/sessions`、`/session/:session_id` | 列表和会话内容 |
|
||
| DELETE | `/session/:session_id` | 删除聊天记录,不同步清理工作区 |
|
||
| POST | `/stream` | 发起对话并接收 SSE |
|
||
| GET | `/session/:session_id/stream` | 订阅会话流 |
|
||
| POST | `/abort` | 中止运行 |
|
||
| POST | `/permission/:request_id/reply` | 回复工具审批 |
|
||
| POST | `/question/:request_id/reply`、`/question/:request_id/reject` | 回复或拒绝澄清问题 |
|
||
| POST | `/session/:session_id/credentials` | 刷新运行凭据 |
|
||
| GET | `/ui-registry`、`/frontend-action-registry` | 查询界面与浏览器动作协议 |
|
||
| POST | `/frontend-actions/:action_id/result` | 浏览器回传动作结果 |
|
||
| GET | `/session/:session_id/mcp` | 查询本会话 MCP 状态和实际工具 ID |
|
||
| POST | `/task-executions` | 提交后台任务执行 |
|
||
| POST | `/task/:task_id/collaboration/session` | 创建任务协作会话 |
|
||
|
||
SSE 包含 `token`、`progress`、`ui_envelope`、`frontend_action`、`permission_request`、`question_request`、`todo_update`、`credential_refresh_required`、`session_title`、`done` 和 `error`,并保留兼容用途的 `tool_call` 事件。聊天 token 流与 Server 的 `/api/v1/workbench/events` 业务事件流相互独立。
|
||
|
||
开发环境的本地上下文可通过 `AGENT_LOCAL_USER_ID`、`AGENT_LOCAL_PROJECT_ID`、`AGENT_LOCAL_NETWORK` 设置,对应请求头为 `X-Agent-Local-User`、`X-Agent-Local-Project`、`X-Agent-Local-Network`。`X-Trace-Id` 用于请求追踪。
|
||
|
||
## 部署与维护
|
||
|
||
[Dockerfile](Dockerfile) 安装匹配的 OpenCode 2 和沙箱依赖,并把统一模型配置复制到镜像。环境文件、运行数据和日志不进入镜像。容器仍依赖宿主内核支持 Landlock。
|
||
|
||
部署时通过环境文件或密钥管理器注入凭据,并将模型文件及运行数据按需要挂载。比如 Compose 服务可包含以下片段,需合并到自己的完整部署配置中:
|
||
|
||
```yaml
|
||
env_file:
|
||
- .local.env
|
||
volumes:
|
||
- ./agent-models.json:/app/agent-models.json:ro
|
||
- ./agent-workspaces:/app/.agent-workspaces
|
||
- ./data:/app/data
|
||
- ./logs:/app/logs
|
||
- ./skills:/app/.opencode/skills
|
||
- ./opencode-data:/root/.local/share/opencode
|
||
```
|
||
|
||
配置 `AGENT_MODEL_CONFIG_PATH` 时需把相应文件挂载到容器可读路径。`docker-compose.yml` 是被 Git 忽略的本地配置,使用前需核对当前模型入口、环境变量和数据卷;不要沿用旧模型环境变量。
|
||
|
||
常用维护命令:
|
||
|
||
| 命令 | 用途 |
|
||
| --- | --- |
|
||
| `bun run check` | 检查服务和 OpenCode 插件的 TypeScript 类型 |
|
||
| `bun run check:models` | 通过实际 OpenCode 和上游目录检查模型,不请求推理 |
|
||
| `bun run start:prod` | 类型检查通过后启动服务 |
|
||
| `bun test tests/**/*.test.ts` | 全部单元测试,日常修改优先运行相关测试 |
|
||
| `bun run tests/integration/mcp-smoke.ts` | 可选的本地 MCP 联调,使用自己的样例服务和临时数据,不请求推理 |
|
||
|
||
[CI 工作流](.gitea/workflows/package.yml) 在推送 `v*` 标签或手动触发时调用共享容器流水线。当前镜像名为 `gitea.waternetwork.cn/orgtjwater/next-tjwater-agent`,部署服务名为 `next-agent`;仓库需设置 `REGISTRY_USERNAME`、`REGISTRY_PASSWORD`、`DEV_DEPLOY_SSH_KEY`。具体候选验证和发布步骤由共享模板定义。
|
||
|
||
代码修改约束见 [AGENTS.md](AGENTS.md),前端协议见 [Agent UI 协议](docs/agent-ui-protocol.md),任务计划规则见 [工况执行计划](docs/execution-plan.md)。
|
||
|
||
### 本地交互式聊天回答
|
||
|
||
原生插件通过 `present_answer` 发布 `answer-ui@1` 内容块,现有聊天消息流输出
|
||
`data-answer_ui`,允许文字与本地指标、表格、图表、证据、地图定位和补充资料表单交替出现。
|
||
相同 block_id 更新本轮内容;消息持久化与历史恢复保留结构化部分。最终答复包含
|
||
完整报告文字及 ui_block_ids 引用的已发布组件,其余过程默认折叠。已发布界面的
|
||
聊天在最终答复完成且无待完成工具时收尾,不代替后台任务的完成接口。后台调查执行
|
||
不发布聊天界面块,继续使用原任务报告和展示通道。
|
||
|
||
组件参数契约由供水前端 catalog 导出到 `src/chat/answer-ui-catalog.json`,
|
||
本服务按该契约校验组件参数及树结构。前端与 Agent 需同步更新,插件变化需要重启
|
||
Agent,客户端模式也需更新外部 OpenCode 的可信资产。无需新增 domain key、
|
||
UI 托管服务配置或数据库迁移。详见
|
||
[前端接入与扩展说明](../next-tjwater-frontend/docs/agent-answer-ui.md)。
|
||
|
||
原生工具发现验证:`bun run tests/integration/answer-ui-smoke.ts`,使用独立临时数据库,
|
||
不调用模型推理,不接管既有服务。
|