fix(agent): stabilize sandboxed streaming workflows

This commit is contained in:
2026-08-26 12:26:29 +08:00
parent 80cfc1f2ab
commit 4ec010455b
12 changed files with 916 additions and 34 deletions
@@ -148,3 +148,6 @@ if length < 0.01 and headloss > 0.5 → "短管高水损,检查是否存在模
- 水头损失百分位阈值(P80/P90)基于**全管网**统计,如果管网上游存在极端水损(如 400m+),会拉高整体 P 值,导致部分中高水损管段被漏判。极端场景下可考虑对水损做分位数裁剪(如排除 >P99.9 的离群值)后再计算 P80/P90。
- **setting 字段不可用**`data timeseries realtime links` 返回的 `setting` 值为无效数据,本工作流已移除所有基于 setting 的阀门节流 / 水泵出口判定。若需要此类判定,应通过 `network get-link-properties` 逐条获取属性中的 setting 作为替代。
- 脚本读取全量 JSON 入内存,峰值内存约 200-300MB,需确保执行环境有足够内存。
## Learned Patterns
- [5ba58cd24c9cea84b6ab5861] **数据 schema 实测适配(2026-04 验证)**`data timeseries realtime links` 返回记录的管道主键为 `link_id`(不是 `id`),`data timeseries realtime nodes` 返回记录的节点主键为 `node_id`(不是 `id`),且 `time` 字段为 UTC 格式(如 `2026-04-01T00:00:00+00:00`)。运行 `bottleneck_analysis.py` 前需:① 脚本内将 `r['id']` 改为 `r['link_id']``n['id']` 改为 `n['node_id']`;② `--target-tim...
@@ -144,3 +144,6 @@ show_chart(title="各水源分区节点数/压力对比", chart_type="bar", ...)
- **水库顺序敏感**:多源 BFS 中先遍历到的水库优先分配,不同水库启动顺序可能影响边界区域分配结果
- **单时刻快照**:分区仅反映目标时刻的水力工况,不同时段的泵站启停、阀门切换可能导致分区边界变化
- **零流量阈值**`1e-6` 阈值过滤极低流量管段,若管网有长期小流量管段可能漏判方向
## Learned Patterns
- [6614a914a8f7dcc2fc34c1ba] 实时数据时间匹配必须用 norm_time 归一化为 UTC 再比较(数据 time 为 UTC 格式如 2026-06-03T00:00:00+00:00target-time 传 +08:00 会因字符串不等而筛出 0 条);links/nodes 记录主键字段为 link_id/node_id(不是 id)。执行分区前先确认目标时刻存在实时数据,可用 `data timeseries realtime simulation-by-id-time` 探测;数据可能只覆盖某几天(本模型覆盖 2026-06-03 附近,2026-04 与 2026-08 均无数据)。
@@ -29,6 +29,13 @@ COLORS = [
"rgba(204,153,204,0.7)", "rgba(153,153,153,0.7)"
]
def norm_time(t):
"""把 ISO8601 字符串归一化为 UTC 的 ISO 字符串,用于跨时区比较"""
from datetime import datetime
return datetime.fromisoformat(t.replace("Z", "+00:00")).astimezone(
__import__("datetime").timezone.utc).isoformat()
def load_json(path, label):
print(f"Loading {label}...", file=sys.stderr)
with open(path) as f:
@@ -63,11 +70,12 @@ def main():
# --- Step 3: Load link flow at target time ---
ldata = load_json(args.links, "link flows")["data"]
target_links = [l for l in ldata if l["time"] == args.target_time]
target_ts = norm_time(args.target_time)
target_links = [l for l in ldata if norm_time(l["time"]) == target_ts]
flow_direction = {}
pipe_flow = {}
for l in target_links:
lid = l["id"]
lid = l.get("link_id") or l.get("id")
flow_val = l["flow"]
pipe_flow[lid] = abs(flow_val)
if lid in pipe_topology:
@@ -81,11 +89,11 @@ def main():
# --- Step 4: Load node data at target time ---
ndata = load_json(args.nodes, "node data")["data"]
target_nodes = [n for n in ndata if n["time"] == args.target_time]
target_nodes = [n for n in ndata if norm_time(n["time"]) == target_ts]
node_pressure = {}
node_demand = {}
for n in target_nodes:
nid = n["id"]
nid = n.get("node_id") or n.get("id")
node_pressure[nid] = n.get("pressure", 0)
node_demand[nid] = n.get("actual_demand", 0)
print(f" {len(target_nodes)} nodes", file=sys.stderr)