mirror of
https://github.com/ThearchyHelios/AgentLab.git
synced 2026-11-15 07:02:00 +00:00
03c18c4d78
一、文案(前端约 1600 处,后端传到界面的约 880 处) - 术语统一:工作流层面用「运行」(继续运行、重新运行、试运行),节点和工具层面用「执行」,不再用「跑」; 总时长 / 执行时长 / 等待审批;服务端;助手;Agent;token;工作流;固定版本;模型接入;系统提示;批准 / 驳回;受管级别 - 口语改书面:取不到、没取回来、读不懂、连不上、多半、照样、兜底、揉成这类说法改成「无法 / 未能 / 失败 / 请」;去掉拟人写法 - 不再露出实现细节:界面上不写 checkpoint、同一拍、哈希(凭证处除外),不写改版历史(「以前…」「老数据」); 报错、校验、门禁、自动修复里裸写的配置键名和枚举值换成界面上的中文标签,由新的 backend/app/engine/labels.py 统一提供; 发布弹窗里结论句的选项不再是 off / require_citation - 同一件事只留一种说法:生成阶段文案、出具档位说明、画布锁定提示各合成一份 - 去掉界面上的工业场景示例(MES、ERP、「张工」「王工」)和真实产品名,换成通用示例 二、说错的提示(都有测试证明) - 数据库测连接失败时的专用提示以前从不出现(按报错文字全等比较,永远比不上):改为按错误类型判断,不再拼出重复的前缀 - 「设置 → 供应商」改指「设置 → 模型接入」;「在设置里建数据源」改指「数据」页 - 缺少 API Key、模型接入已停用的报错不再夹英文,写明去哪里填 - 两处原因说错(「这种引用在后续版本支持」「这一版还不支持」)改成真实原因 - 节点说明里不准确的说法改正:代码节点在 microVM 或系统沙箱中执行;报告撰写、口径卡的说明不再说过头 - 导出的证据 CSV 里两列同名,第三列改为「片段编号」 三、前后端对齐 - 前端按后端原文识别日志、报错的地方,新旧两种写法都认得(历史运行里存的是旧文字),逐条补了新旧原文的核对 - 后端交回模型的原指令放进单独的 for_model 字段,前端在解析响应时去掉,不会显示到界面上 四、检查 - 检查脚本里按原文匹配的断言改成新文案;改完会变成永远成立的反向断言逐条修正,并做了变异验证 - 新增 check-copy(静态扫描前端界面字符串和后端上界面的文案):再出现「跑」「后端」「多半」「令牌」、 界面上的 Copilot、裸写的配置键名、半角标点等就报错;确需保留的写进 scripts/copy-allow.json 并注明理由
70 lines
2.6 KiB
Python
70 lines
2.6 KiB
Python
"""最近一次测连接的结果:数据源、模型接入、MCP 服务共用的一套记法。
|
|
|
|
以前这份结果只在浏览器的 localStorage 里,换台电脑就全回到「未测试」。现在记在
|
|
对象上(数据源、MCP 是 last_check 列,模型接入是 extra.last_check),列表接口
|
|
平铺成 last_checked_at / last_check_ok / last_latency_ms / last_error 四个字段。
|
|
|
|
表单里「先测再保存」的那一次也要算数:测的是草稿,保存时后端按连接配置的指纹
|
|
认出「刚测过的就是这一份」,把结果带到新对象上。指纹只在进程里记一小会儿,
|
|
用的是哈希,不留明文密码。
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import hashlib
|
|
import json
|
|
import time
|
|
from typing import Any
|
|
|
|
from app.db.base import utcnow
|
|
|
|
#: 草稿测完多久之内保存还算数。测完去倒杯水回来再点保存,也该认得出来
|
|
_DRAFT_TTL = 15 * 60
|
|
_DRAFT_MAX = 64
|
|
_drafts: dict[str, tuple[float, dict[str, Any]]] = {}
|
|
|
|
|
|
def record(ok: bool, latency_ms: int | None, error: str | None = None) -> dict[str, Any]:
|
|
return {
|
|
"at": utcnow().isoformat(),
|
|
"ok": bool(ok),
|
|
"latency_ms": None if latency_ms is None else int(latency_ms),
|
|
"error": None if ok else (error or "无法连接"),
|
|
}
|
|
|
|
|
|
def fields(last: dict[str, Any] | None) -> dict[str, Any]:
|
|
"""对象上记的那份 → 列表接口的四个字段。没测过全是 None。"""
|
|
last = last if isinstance(last, dict) else {}
|
|
ok = last.get("ok")
|
|
return {
|
|
"last_checked_at": last.get("at"),
|
|
"last_check_ok": ok if isinstance(ok, bool) else None,
|
|
"last_latency_ms": last.get("latency_ms"),
|
|
"last_error": last.get("error"),
|
|
}
|
|
|
|
|
|
def fingerprint(*parts: Any) -> str:
|
|
"""连接配置的指纹。同一份配置得出同一个值;只拿来比对,不可逆。"""
|
|
blob = json.dumps(parts, sort_keys=True, ensure_ascii=False, default=str)
|
|
return hashlib.sha256(blob.encode()).hexdigest()
|
|
|
|
|
|
def remember_draft(key: str | None, last: dict[str, Any]) -> None:
|
|
if not key:
|
|
return
|
|
now = time.monotonic()
|
|
for stale in [k for k, (at, _) in _drafts.items() if now - at > _DRAFT_TTL]:
|
|
_drafts.pop(stale, None)
|
|
if len(_drafts) >= _DRAFT_MAX:
|
|
_drafts.pop(min(_drafts, key=lambda k: _drafts[k][0]), None)
|
|
_drafts[key] = (now, last)
|
|
|
|
|
|
def draft_result(key: str | None) -> dict[str, Any] | None:
|
|
"""这份配置最近在表单里测过的结果,没有或太久了返回 None。"""
|
|
hit = _drafts.get(key or "")
|
|
if not hit or time.monotonic() - hit[0] > _DRAFT_TTL:
|
|
return None
|
|
return dict(hit[1])
|