feat: refresh model and voice test catalog with favicon

This commit is contained in:
AdamWen95
2026-10-20 11:06:52 +08:00
parent ae7c5bc967
commit 36c228544e
23 changed files with 1026 additions and 42 deletions
+29 -8
View File
@@ -88,11 +88,11 @@ def public_execution(settings, script):
profile = profile_for(settings, script)
if profile is None:
return {"mode": "container", "interactive": False, "max_timeout_seconds": 7200}
return {"mode": "native", "profile_id": profile["id"], "interpreter": profile["interpreter"],
"user": profile["user"], "cwd": profile["cwd"], "description": "使用服务器原有环境和原始入口,不迁移依赖或修改源文件。",
return {"mode": "native", "runtime": "docker" if profile.get("docker") else "host", "profile_id": profile["id"], "interpreter": profile["interpreter"],
"user": profile["user"], "cwd": profile["cwd"], "description": "复用原依赖镜像和原始入口,只读挂载源文件,结果写入本次独立目录。" if profile.get("docker") else "使用服务器原有环境和原始入口,不迁移依赖或修改源文件。",
"impact": profile["impact"], "parameters": profile.get("parameters", []),
"interactive": profile.get("interactive", False), "max_timeout_seconds": MAX_TIMEOUT,
"notes": profile.get("notes", []), "verification": "启动方案已接入,未完成本轮 GPU/长稳业务验收"}
"notes": profile.get("notes", []), "verification": "启动方案已接入,未完成本轮业务测试验收" if profile.get("available", True) else "原环境方案待配置:" + profile.get("unavailable_reason", "请核对依赖与运行条件")}
def validate_config(settings, script, values):
@@ -138,10 +138,14 @@ def build_plan(settings, script, run_id=None, check_host=True):
return str(variables[match[1]])
return PLACEHOLDER.sub(replace, str(value))
argv = [profile["interpreter"], str(source), *[render(a) for a in profile.get("arguments", [])]]
if profile.get("docker"):
from .native_container import command
argv = command(profile, source, argv[2:], directory, identity)
environment = {**target.get("environment", {}), **{k: render(v) for k, v in profile.get("environment", {}).items()}}
credential_files = list(dict.fromkeys(profile.get("credential_files", []) + target.get("credential_files", [])))
setup_files = [render(p) for p in profile.get("env_setup_files", [])]
required_files = [render(p) for p in profile.get("required_files", [])]
required_files.extend(table["path"] for table in profile.get("secret_tables", []))
if target.get("config_file"):
required_files.append(target["config_file"])
timeout = script["config"].get("timeout_seconds", profile.get("timeout_seconds", 3600))
@@ -153,11 +157,21 @@ def build_plan(settings, script, run_id=None, check_host=True):
check("启动方案", profile.get("available", True), profile.get("unavailable_reason", "已登记原环境入口"))
if check_host:
check("原工作目录", Path(profile["cwd"]).is_dir(), profile["cwd"])
tools = list(dict.fromkeys([profile["interpreter"], "/usr/bin/systemd-run", *profile.get("required_tools", [])]))
tools = list(dict.fromkeys(["/usr/bin/docker" if profile.get("docker") else profile["interpreter"], "/usr/bin/systemd-run", *profile.get("required_tools", [])]))
for tool in tools:
check("工具", Path(tool).is_file() and os.access(tool, os.X_OK), tool)
for path in required_files + credential_files + setup_files:
check("原配置或素材", Path(path).is_file(), path)
if profile.get("docker"):
from .native_container import checks as container_checks
checks.extend(container_checks(profile))
if profile.get("secret_tables"):
from .native_io import read_secret_tables
try:
read_secret_tables(profile["secret_tables"])
check("测试身份引用", True, "已找到原测试身份,凭据仅在内存中读取")
except (OSError, ValueError):
check("测试身份引用", False, "原凭据表缺失、格式不支持或没有登记的测试身份")
for value in profile.get("check_ports", []):
port = int(render(value))
if not 1 <= port <= 65535:
@@ -167,20 +181,27 @@ def build_plan(settings, script, run_id=None, check_host=True):
available = True
except OSError:available = False
check("目标服务端口", available, f"127.0.0.1:{port}" + (" 可连接" if available else " 未监听,请先准备原服务"))
if target.get("verify_model"):
if all(c["ok"] for c in checks):
from .model_preflight import check_model
checks.append(check_model(target, credential_files))
else:
check("模型身份", False, "先满足上方原环境条件,再核对服务提供的模型")
# Binds acknowledgment to saved configuration, source and recipe, not to a mutable browser flag.
dependency_hashes = {}
for name in required_files + setup_files:
path = Path(name)
if name not in credential_files and path.is_file() and path.stat().st_size <= 16 * 1024**2:
secret_paths = [table["path"] for table in profile.get("secret_tables", [])]
if name not in credential_files + secret_paths + profile.get("mutable_files", []) and path.is_file() and path.stat().st_size <= 16 * 1024**2:
dependency_hashes[name] = hashlib.sha256(path.read_bytes()).hexdigest()
fingerprint = {"profile": profile, "target": target, "options": options, "source": source_hash,
"dependencies": dependency_hashes,
"script_id": script["id"], "timeout_seconds": timeout}
token = hashlib.sha256(json.dumps(fingerprint, sort_keys=True, ensure_ascii=False).encode()).hexdigest()
return {"mode": "native", "profile_id": profile["id"], "plan_token": token,
return {"mode": "native", "runtime": "docker" if profile.get("docker") else "host", "profile_id": profile["id"], "plan_token": token,
"ready": all(c["ok"] for c in checks), "checks": checks, "argv": argv, "command_preview": shlex.join(argv),
"cwd": profile["cwd"], "user": profile["user"], "environment": environment,
"credential_files": credential_files, "env_setup_files": setup_files,
"credential_files": credential_files, "env_setup_files": setup_files, "secret_tables": profile.get("secret_tables", []),
"impact": profile["impact"], "interactive": profile.get("interactive", False),
"timeout_seconds": timeout, "source_sha256": source_hash, "dependency_hashes": dependency_hashes,
"output_paths": [render(p) for p in profile.get("output_paths", [])],
@@ -190,4 +211,4 @@ def build_plan(settings, script, run_id=None, check_host=True):
def public_plan(plan):
keys = ("mode", "profile_id", "plan_token", "ready", "checks", "command_preview", "cwd", "user",
"impact", "interactive", "output_paths", "notes", "timeout_seconds", "source_sha256")
return {key: plan[key] for key in keys}
return {**{key: plan[key] for key in keys}, "runtime": plan.get("runtime", "host")}