openclaw-agent-dashboard 1.0.34 → 1.0.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dashboard/api/timeline.py +18 -1
- package/dashboard/data/config_reader.py +4 -1
- package/dashboard/data/timeline_reader.py +633 -333
- package/frontend-dist/assets/{index-zZLJo64M.css → index-DoK53sgy.css} +1 -1
- package/frontend-dist/assets/index-Drb7GQ4m.js +24 -0
- package/frontend-dist/index.html +2 -2
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/frontend-dist/assets/index-xwKb2VFi.js +0 -24
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Timeline API 路由 - 实时执行时序图
|
|
3
3
|
"""
|
|
4
|
+
import logging
|
|
5
|
+
import time
|
|
4
6
|
from fastapi import APIRouter, Query, HTTPException
|
|
5
7
|
from pydantic import BaseModel
|
|
6
8
|
from typing import Optional, List, Dict, Any
|
|
7
9
|
import sys
|
|
8
10
|
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
LOG = logging.getLogger(__name__)
|
|
9
13
|
sys.path.append(str(Path(__file__).parent.parent))
|
|
10
14
|
|
|
11
15
|
from data.timeline_reader import get_timeline_steps, StepType, StepStatus
|
|
@@ -38,13 +42,17 @@ class TimelineResponse(BaseModel):
|
|
|
38
42
|
agentName: Optional[str] = None
|
|
39
43
|
model: Optional[str] = None
|
|
40
44
|
startedAt: Optional[int] = None
|
|
45
|
+
runStartedAt: Optional[int] = None
|
|
41
46
|
status: str
|
|
42
47
|
steps: List[Dict[str, Any]]
|
|
43
48
|
stats: TimelineStats
|
|
44
49
|
message: Optional[str] = None
|
|
50
|
+
# 主 Agent 无会话文件时由后端置 True,避免前端误用「子代理」空态文案
|
|
51
|
+
isMainAgent: Optional[bool] = None
|
|
45
52
|
# LLM 轮次分组
|
|
46
53
|
rounds: Optional[List[LLMRound]] = None
|
|
47
54
|
roundMode: Optional[bool] = None
|
|
55
|
+
dataSource: Optional[str] = None
|
|
48
56
|
|
|
49
57
|
|
|
50
58
|
@router.get("/timeline/{agent_id}", response_model=TimelineResponse)
|
|
@@ -73,8 +81,17 @@ async def get_timeline(
|
|
|
73
81
|
if not agent_info:
|
|
74
82
|
raise HTTPException(status_code=404, detail=f"Agent {agent_id} not found")
|
|
75
83
|
|
|
76
|
-
|
|
84
|
+
t0 = time.perf_counter()
|
|
77
85
|
result = get_timeline_steps(agent_id, session_key, limit)
|
|
86
|
+
elapsed_ms = (time.perf_counter() - t0) * 1000
|
|
87
|
+
if elapsed_ms >= 200.0:
|
|
88
|
+
LOG.info(
|
|
89
|
+
"timeline agent=%s limit=%d steps=%d ms=%.1f",
|
|
90
|
+
agent_id,
|
|
91
|
+
limit,
|
|
92
|
+
len(result.get("steps", [])),
|
|
93
|
+
elapsed_ms,
|
|
94
|
+
)
|
|
78
95
|
|
|
79
96
|
# 补充 Agent 信息
|
|
80
97
|
result['agentName'] = agent_info.get('name', agent_id)
|
|
@@ -52,8 +52,11 @@ def get_agents_list() -> List[Dict[str, Any]]:
|
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
def get_main_agent_id() -> str:
|
|
55
|
-
"""获取主 Agent ID
|
|
55
|
+
"""获取主 Agent ID:优先 default:true,其次 id 为 main,否则列表第一项。"""
|
|
56
56
|
agents = get_agents_list()
|
|
57
|
+
for a in agents:
|
|
58
|
+
if a.get('default') is True:
|
|
59
|
+
return a.get('id', 'main')
|
|
57
60
|
for a in agents:
|
|
58
61
|
if a.get('id') == 'main':
|
|
59
62
|
return 'main'
|