TJWater 供水 Agent 实验服务

基于 OpenCode 的实验性供水 Agent 服务,用于编排 TJWater 供水管网前端交互。排水数据、排水分析流程和排水前端交互不在本仓库范围内。

本仓库与生产环境中的 TJWaterAgent 历史代码相互独立,不包含用户认证,也不包含旧版 tjwater-cli 桥接层。运行时请求默认使用本地上下文,后续可通过 src/context/ 接入实际的认证提供方。

当前边界

  • 不包含 Keycloak 或元数据认证上下文。
  • 不强制要求 Authorization 或 X-Project-Id 请求头。
  • 不包含 cli/、tjwater_cli OpenCode 工具或自由形式的 CLI 命令桥接。
  • Agent 的结构化界面输出使用 agent-ui@1 UIEnvelope 事件;受控浏览器操作使用 frontend-action@1 前端动作。
  • 依赖 TJWater Server 的工具处于禁用状态,Agent 不能访问任意 URL、SQL、Shell 命令或文件系统路径。

主要 API

GET    /health
GET    /api/v1/agent/chat/models
GET    /api/v1/agent/chat/ui-registry
GET    /api/v1/agent/chat/frontend-action-registry
POST   /api/v1/agent/chat/frontend-actions/:action_id/result
POST   /api/v1/agent/chat/session
POST   /api/v1/agent/chat/task-executions
GET    /api/v1/agent/chat/sessions
GET    /api/v1/agent/chat/session/:session_id
GET    /api/v1/agent/chat/session/:session_id/stream
POST   /api/v1/agent/chat/stream
POST   /api/v1/agent/chat/abort

工况 worker 通过 POST /api/v1/agent/chat/task-executions 提交 Server 已持久化的 task_id、run_id 和 execution_request_id。三者缺一即拒绝;Agent 不从进程内 Map 推断当前执行代次。Agent claim 成功后每 20 秒对该 run 心跳,正常流结束显式调用 complete,失败或中止显式调用 fail。计划、报告和完成命令均携带同一 run 身份,Server 是活动 run 与租约状态的唯一权威。

聊天 UIMessage 流与工作台业务事件流相互独立;业务状态由 Server 的 /api/v1/workbench/events 推送,不能混入 token SSE。

POST /api/v1/agent/chat/stream 通过 SSE 返回事件流。主要事件如下:

事件 用途
progress Agent 规划和工具执行进度
token 助手回复的增量文本
ui_envelope 供可信前端渲染的结构化界面描述
frontend_action 请求可信前端执行受控动作
tool_call 用于兼容和调试的旧版工具调用事件
permission_request 运行时权限请求
question_request 运行时向用户发起的澄清请求
todo_update Agent 待办事项更新
session_title 会话标题更新
done 本次运行完成
error 本次运行失败或被中止

本地上下文

服务通过 src/context/localContext.ts 提供本地上下文,默认值如下:

AGENT_LOCAL_USER_ID=local-user
AGENT_LOCAL_PROJECT_ID=local-project
AGENT_LOCAL_NETWORK=local-network

供水业务数据只来自用户输入、经过校验的事件上下文或已启用的受控工具。get_project_context、list_scada_assets、query_scada_readings、web_search 和 geocode 依赖 TJWater Server,因此当前不对外开放。

实验期间可以通过以下请求头覆盖本地上下文:

X-Agent-Local-User
X-Agent-Local-Project
X-Agent-Local-Network
X-Trace-Id

UIEnvelope 与前端动作

UIEnvelope 注册表通过以下接口提供:

GET /api/v1/agent/chat/ui-registry

该接口用于兼容 agent-ui@1 协议。目前没有注册图表语法、界面组件或 UIEnvelope 动作。

前端动作使用独立的注册表:

GET /api/v1/agent/chat/frontend-action-registry

当前提供 render_scada_analysis 和 clear_scada_analysis 两个地图叠加层动作。浏览器需要在流式请求中声明 frontend-action@1 能力,执行动作后再通过以下接口回传结果:

POST /api/v1/agent/chat/frontend-actions/:action_id/result

协议详情参见 Agent UI 协议。

本地开发

bun install
bun run dev
bun run check
bun test tests/**/*.test.ts

bun run check 会检查服务代码和 .opencode 工具的类型。

工况任务工具通过本机内部桥访问 Agent,再由 Agent 使用当前请求的短期产品凭据调用 TJWater Server。embedded 模式会把启动时生成的内部密钥传给子进程;client 模式必须在 Agent 与外部 OpenCode 服务中配置相同的 AGENT_INTERNAL_TOKEN 后分别重启。缺少共享密钥时 Agent 会拒绝启动,工具桥也不会退化为仅凭 session ID 访问。

独立管理 Agent 与 OpenCode 时必须显式配置稳定的 AGENT_INTERNAL_TOKEN;如果 bun --watch 使用自动生成的密钥重启 Agent,仍在运行的 OpenCode 子进程会保留旧密钥,内部工具桥将拒绝请求。需要保留现有开发服务做隔离联调时,可运行 bun run start:integration:isolated。它默认使用 Agent 18787、OpenCode 14096,从当前仓库目录加载 opencode.json、.opencode/ 与现有 provider 环境,并把 Agent Session、memory、result ref、Skill 及 OpenCode XDG 运行数据写入 data/integration-18787/,不会复用默认运行实例的数据目录。可用 INTEGRATION_AGENT_PORT、INTEGRATION_OPENCODE_PORT、INTEGRATION_DATA_DIR 覆盖这些隔离值;启动器不会输出内部密钥。

CI/CD

Gitea Actions 通过 .gitea/workflows/package.yml 复用 OrgTJWater/ci-templates 的容器发布流程。手动触发只构建镜像并在 Dev 服务器运行候选验证;从 main 创建并推送 v* tag 后,候选验证通过才会 提升为正式 agent 服务。

仓库需要配置 REGISTRY_USERNAME、REGISTRY_PASSWORD 和 DEV_DEPLOY_SSH_KEY 三个 Gitea Secrets。.env、持久化数据和日志不会写入镜像;它们由 Dev 服务器通过环境文件和卷挂载。

S
Description
No description provided
Readme
1.2 MiB
Languages
TypeScript 98.8%
Python 0.9%
Dockerfile 0.3%