feat: 更新后端平台模块、Compute引擎、前端组件及构建产物

- 更新 backend 平台 API、platform_store、compute_gateway sync
- 更新 compute agent/engine/adapter 及 API
- 更新 Docker 部署配置(app/compute)
- 新增 frontend/src/utils/ 工具模块
- 新增 scripts/ops_diagnostics.py 运维诊断脚本
- 新增 docs/2026-07-23-development-summary.md 开发总结
- 重构 frontend/dist 构建产物(新 hash)
- 更新前端多个视图组件及 API 模块

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
wuyongtao
2026-07-23 19:32:42 +08:00
parent f04dc479bb
commit b28cfbc6fa
193 changed files with 2647 additions and 424 deletions

View File

@@ -3,6 +3,7 @@ from __future__ import annotations
import os
import json
import contextlib
import hashlib
import signal
import subprocess
import time
@@ -127,6 +128,7 @@ class ProcessManager:
def serialize(self, job: ManagedProcess) -> dict[str, Any]:
code = job.process.poll() if job.process is not None else None
checkpoints = self._collect_checkpoints(job.output_dir)
if job.status not in TERMINAL_STATUSES:
if job.process is None and job.pid is not None and not self._pid_alive(job.pid):
job.status = "failed"
@@ -157,6 +159,7 @@ class ProcessManager:
"output_dir": job.output_dir,
"log_file": str(job.log_path),
"artifacts": job.artifacts,
"checkpoints": checkpoints,
"return_code": code,
}
@@ -175,15 +178,47 @@ class ProcessManager:
artifacts: list[dict[str, Any]] = []
for path in root.rglob("*"):
if path.is_file():
digest = hashlib.sha256()
with path.open("rb") as handle:
for chunk in iter(lambda: handle.read(1024 * 1024), b""):
digest.update(chunk)
size = path.stat().st_size
artifacts.append(
{
"path": str(path),
"name": path.name,
"size": path.stat().st_size,
"size": size,
"size_bytes": size,
"checksum_sha256": digest.hexdigest(),
}
)
return artifacts[:200]
def _collect_checkpoints(self, output_dir: str) -> list[dict[str, Any]]:
root = Path(output_dir)
if not root.exists():
return []
checkpoints: list[dict[str, Any]] = []
for path in root.glob("checkpoint-*"):
if not path.is_dir():
continue
step = 0
try:
step = int(path.name.rsplit("-", 1)[-1])
except ValueError:
step = 0
size_bytes = sum(item.stat().st_size for item in path.rglob("*") if item.is_file())
checkpoints.append(
{
"step": step,
"name": path.name,
"path": str(path),
"size_bytes": size_bytes,
"create_time": path.stat().st_mtime,
}
)
return sorted(checkpoints, key=lambda item: (int(item.get("step") or 0), str(item.get("name") or "")))
def _save_registry(self) -> None:
items = []
for job in self.jobs.values():