重构会话管理,简化上下文存储逻辑

This commit is contained in:
2026-06-03 17:14:55 +08:00
parent 76d4b510f4
commit 04ded0ceb0
19 changed files with 420 additions and 235 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ mode: primary
model: deepseek/deepseek-v4-pro
temperature: 0.2
---
是 TJWater 供水管网分析 Agent,运用水力专业知识,使用简体中文,回复简洁准确。
是 TJWater 供水管网分析 Agent,运用水力专业知识,回复用户时使用简体中文,内容要求简洁准确。
## 工作流生命周期
+2 -2
View File
@@ -34,12 +34,12 @@ SSE 事件:
{
"reason": "查询当前项目数据库健康状态",
"command": "project db-health",
"timeout": 60
"timeout": 120
}
```
- `command`tjwater-cli 子命令(不含二进制路径和 `--auth-context`
- `timeout`:可选超时秒数,默认 60,大结果集建议 300+
- `timeout`:可选超时秒数,默认 120,大结果集建议 300+
- 认证上下文(token、server、project)由内部桥接自动注入
## 4) 工具参数约定(前端工具)
+15 -7
View File
@@ -17,7 +17,7 @@ description: tjwater-cli 命令行工具使用说明,涵盖命令发现、输
{
"reason": "说明调用原因",
"command": "project list",
"timeout": 60
"timeout": 120
}
```
@@ -25,7 +25,7 @@ description: tjwater-cli 命令行工具使用说明,涵盖命令发现、输
|------|------|------|------|
| `reason` | string | 是 | 调用原因 |
| `command` | string | 是 | CLI 子命令(不含二进制路径和 `--auth-context` |
| `timeout` | number | 否 | 超时秒数,默认 60,大结果集建议 300+ |
| `timeout` | number | 否 | 超时秒数,默认 120,大结果集建议 300+ |
认证上下文(token、server、project、network)由内部桥接自动注入,无需手动传参。
@@ -117,6 +117,7 @@ tjwater-cli help COMMAND → 子命令与参数详情
4. **管道串联** — workflow 脚本中用 shell pipe 串联多个 CLI 命令,减少 `subprocess.run` 次数
5. **结果验证** — 始终检查 `ok` 字段,失败时先处理错误码再重试
6. **大结果集** — 优先过滤/采样,不要一次性拉取全部数据
7. **模拟时长控制** — 模拟(`simulation`)或方案模拟的 `--duration` 不宜过长,建议每次仿真时间跨度控制在一小时以内,避免计算耗时过长或结果数据量过大
## 示例
@@ -147,18 +148,25 @@ tjwater-cli help COMMAND → 子命令与参数详情
### 触发仿真并获取结果
`simulation run` 仅接受 `--start-time`RFC3339,必填)和 `--duration`(整数分钟,必填)。结果需从 `data timeseries` 获取
通常系统会自动跑仿真,建议**先尝试获取结果**,若无数据再触发仿真
```json
// step 1: 触发仿真 (duration 为分钟数)
// step 1: 先尝试获取仿真结果
{
"reason": "触发24小时水力仿真",
"command": "simulation run --start-time 2026-06-03T08:00:00+08:00 --duration 1440"
"reason": "尝试获取节点 J-001 09:00 时刻的仿真压力",
"command": "data timeseries realtime simulation-by-id-time --id J-001 --type junction --time 2026-06-03T09:00:00+08:00"
}
// step 2: 按节点和时间获取仿真结果
// step 2: 若 step 1 无数据(ok: false 或 data 为空),触发仿真
{
"reason": "无已有仿真结果,触发1小时水力仿真",
"command": "simulation run --start-time 2026-06-03T08:00:00+08:00 --duration 60"
}
// step 3: 仿真完成后,再次获取结果(同 step 1)
{
"reason": "获取仿真结果中节点 J-001 09:00 时刻的压力",
"command": "data timeseries realtime simulation-by-id-time --id J-001 --type junction --time 2026-06-03T09:00:00+08:00"
}
```
`simulation run` 仅接受 `--start-time`RFC3339,必填)和 `--duration`(整数分钟,必填)。
+29
View File
@@ -0,0 +1,29 @@
---
name: workflow
description: 供水管网分析工作流目录,描述可复用的分析流程与操作序列。
---
# workflow 工作流
## 简介
本 skill 为工作流目录入口,汇总可复用的多步骤分析流程。每个工作流对应一个子目录,内含该流程的完整操作步骤、所需数据来源与判定策略。
## 可用工作流
| 工作流 | 子目录 | 用途 |
|--------|--------|------|
| 水力瓶颈分析 | `hydraulic-bottleneck-analysis` | 复合评分法识别管网水力瓶颈,区分管径不足与阀门节流问题 |
## 使用方式
1. 根据分析需求匹配对应工作流
2. 按子目录 `SKILL.md` 中的步骤依次执行
3. 严格遵循判定策略与阈值,避免凭经验跳过步骤
## 工作流规范
- 每个工作流子目录包含独立的 `SKILL.md`,描述目的、步骤、参数与判定阈值
- 所有数据获取均通过 `tjwater-cli` 命令族(见 `tjwater-cli` skill
- 流程中若涉及仿真,遵循"先查结果后触发"原则
- 新工作流由 `skill_manager` 在线追加,若子目录不存在则无对应工作流
@@ -0,0 +1,14 @@
---
name: hydraulic-bottleneck-analysis
description: 由 skill_manager 在线追加的高置信度可复用 workflow。
version: 1.0.0
---
# learned skill
## 简介
记录由 `skill_manager` 在线追加的高置信度 workflow 模式。
## Learned Patterns
- [350873f4366ebc50601f694a] 水力瓶颈复合评分法:流速分级(>3.0m/s=极危, >2.0m/s=严重, >1.5m/s=偏高) × 水头损失绝对值(>P90=严重, >P80=中度),双侧超标为复合瓶颈;辅以节点压力(<20m低压, 20-25m偏低)验证。管道setting字段<100=阀门节流(优先调整阀门), >100=疑似水泵增压
+1 -9
View File
@@ -1,11 +1,8 @@
import { tool } from "@opencode-ai/plugin";
import { ToolSessionContextStore } from "../../src/session/toolContextStore.js";
const internalBaseUrl =
process.env.TJWATER_AGENT_INTERNAL_BASE_URL ?? "http://127.0.0.1:8787";
const internalToken = process.env.TJWATER_AGENT_INTERNAL_TOKEN ?? "";
const toolContextStore = new ToolSessionContextStore();
const initializePromise = toolContextStore.initialize();
export default tool({
description:
@@ -25,11 +22,6 @@ export default tool({
.describe("Optional maximum number of hits to return."),
},
async execute(args, context) {
await initializePromise;
const sessionContext = await toolContextStore.read(context.sessionID);
if (!sessionContext) {
throw new Error(`session context not found for ${context.sessionID}`);
}
const response = await fetch(`${internalBaseUrl}/internal/tools/session-search`, {
method: "POST",
headers: {
@@ -39,7 +31,7 @@ export default tool({
body: JSON.stringify({
max_results: args.max_results,
query: args.query,
sessionScopeKey: sessionContext.sessionScopeKey,
session_id: context.sessionID,
}),
});
const text = await response.text();
+1 -9
View File
@@ -1,10 +1,7 @@
import { tool } from "@opencode-ai/plugin";
import { ToolSessionContextStore } from "../../src/session/toolContextStore.js";
const internalBaseUrl = process.env.TJWATER_AGENT_INTERNAL_BASE_URL ?? "http://127.0.0.1:8787";
const internalToken = process.env.TJWATER_AGENT_INTERNAL_TOKEN ?? "";
const toolContextStore = new ToolSessionContextStore();
const initializePromise = toolContextStore.initialize();
export default tool({
description:
@@ -20,11 +17,6 @@ export default tool({
),
},
async execute(args, context) {
await initializePromise;
const sessionContext = await toolContextStore.read(context.sessionID);
if (!sessionContext) {
throw new Error(`session context not found for ${context.sessionID}`);
}
const response = await fetch(`${internalBaseUrl}/internal/tools/store-render-ref`, {
method: "POST",
headers: {
@@ -32,7 +24,7 @@ export default tool({
"x-agent-internal-token": internalToken,
},
body: JSON.stringify({
sessionScopeKey: sessionContext.sessionScopeKey,
session_id: context.sessionID,
file_path: args.file_path,
}),
});
+2 -10
View File
@@ -1,10 +1,7 @@
import { tool } from "@opencode-ai/plugin";
import { ToolSessionContextStore } from "../../src/session/toolContextStore.js";
const internalBaseUrl = process.env.TJWATER_AGENT_INTERNAL_BASE_URL ?? "http://127.0.0.1:8787";
const internalToken = process.env.TJWATER_AGENT_INTERNAL_TOKEN ?? "";
const toolContextStore = new ToolSessionContextStore();
const initializePromise = toolContextStore.initialize();
export default tool({
description:
@@ -21,14 +18,9 @@ export default tool({
timeout: tool.schema
.number()
.optional()
.describe("超时秒数,默认 60。大结果集建议设 120。"),
.describe("超时秒数,默认 120。大结果集建议设 300+。"),
},
async execute(args, context) {
await initializePromise;
const sessionContext = await toolContextStore.read(context.sessionID);
if (!sessionContext) {
throw new Error(`session context not found for ${context.sessionID}`);
}
const response = await fetch(`${internalBaseUrl}/internal/tools/tjwater-cli-call`, {
method: "POST",
headers: {
@@ -36,7 +28,7 @@ export default tool({
"x-agent-internal-token": internalToken,
},
body: JSON.stringify({
sessionScopeKey: sessionContext.sessionScopeKey,
session_id: context.sessionID,
reason: args.reason,
command: args.command,
timeout: args.timeout,