- 补齐 tool_call 和 edge 验证链路的 duration_ms 计算与返回 - 任务详情和任务报告新增 result_summary_detail 结构化摘要 - 摘要中补充最终状态、失败原因、software-a 摘要、审批摘要、验证摘要 - 软件A层术语统一为“最小能力实现” - 同步更新 README、当前进度总结和相关设计文档 - 补充并通过对应自动化测试
43 lines
1.2 KiB
Python
43 lines
1.2 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import UTC, datetime, timedelta, timezone
|
|
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
|
|
|
|
|
|
TIME_FORMAT = "%Y-%m-%d %H:%M:%S.%f"
|
|
|
|
|
|
def resolve_timezone(timezone_name: str):
|
|
try:
|
|
return ZoneInfo(timezone_name)
|
|
except ZoneInfoNotFoundError:
|
|
fallback_mapping = {
|
|
"Asia/Shanghai": timezone(timedelta(hours=8)),
|
|
"Asia/Hong_Kong": timezone(timedelta(hours=8)),
|
|
"UTC": UTC,
|
|
}
|
|
return fallback_mapping.get(timezone_name, UTC)
|
|
|
|
|
|
def format_now(timezone_name: str) -> str:
|
|
current = datetime.now(resolve_timezone(timezone_name))
|
|
return current.strftime(TIME_FORMAT)[:-3]
|
|
|
|
|
|
def parse_timestamp(value: str | None) -> datetime | None:
|
|
if not value:
|
|
return None
|
|
try:
|
|
return datetime.strptime(value, TIME_FORMAT)
|
|
except ValueError:
|
|
return None
|
|
|
|
|
|
def compute_duration_ms(started_at: str | None, finished_at: str | None) -> int | None:
|
|
started = parse_timestamp(started_at)
|
|
finished = parse_timestamp(finished_at)
|
|
if not started or not finished:
|
|
return None
|
|
duration_ms = int((finished - started).total_seconds() * 1000)
|
|
return max(duration_ms, 0)
|