openclaw-agent-dashboard 1.0.35 → 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.
@@ -1,7 +1,7 @@
1
1
  """
2
2
  Agent API 路由
3
3
  """
4
- from fastapi import APIRouter, HTTPException
4
+ from fastapi import APIRouter
5
5
  from pydantic import BaseModel
6
6
  from typing import List, Optional
7
7
  import sys
@@ -51,37 +51,10 @@ async def get_agent(agent_id: str):
51
51
  agent['lastActiveFormatted'] = format_last_active(agent['lastActiveAt'])
52
52
  return agent
53
53
 
54
+ from fastapi import HTTPException
54
55
  raise HTTPException(status_code=404, detail=f"Agent {agent_id} not found")
55
56
 
56
57
 
57
- class TimelineContextResponse(BaseModel):
58
- """供「实时执行时序」与 runs.json 对齐:使用最新 run 的 childSessionKey 解析独立会话。"""
59
- childSessionKey: Optional[str] = None
60
-
61
-
62
- @router.get("/agents/{agent_id}/timeline-context", response_model=TimelineContextResponse)
63
- async def get_agent_timeline_context(agent_id: str):
64
- """
65
- 返回该 Agent 在 runs.json 中最近一条 run 的 childSessionKey(若有)。
66
- 前端传给 GET /api/timeline/{agent_id}?session_key= 以命中 sessions.json 指定 jsonl,
67
- 避免仅靠 mtime 选文件或误扫主会话合并路径。
68
- """
69
- from data.config_reader import get_agents_list
70
- from data.subagent_reader import get_agent_runs
71
-
72
- agents = get_agents_list()
73
- if not any(a.get("id") == agent_id for a in agents):
74
- raise HTTPException(status_code=404, detail=f"Agent {agent_id} not found")
75
-
76
- runs = get_agent_runs(agent_id, limit=1)
77
- key = None
78
- if runs:
79
- key = runs[0].get("childSessionKey") or None
80
- if isinstance(key, str) and not key.strip():
81
- key = None
82
- return TimelineContextResponse(childSessionKey=key)
83
-
84
-
85
58
  @router.get("/agents/{agent_id}/output")
86
59
  async def get_agent_output(agent_id: str, limit: int = 50):
87
60
  """
@@ -93,6 +66,7 @@ async def get_agent_output(agent_id: str, limit: int = 50):
93
66
 
94
67
  agents = get_agents_list()
95
68
  if not any(a.get('id') == agent_id for a in agents):
69
+ from fastapi import HTTPException
96
70
  raise HTTPException(status_code=404, detail=f"Agent {agent_id} not found")
97
71
 
98
72
  turns = get_session_turns(agent_id, limit=limit)
@@ -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(配置中 id 为 main 的,或列表第一个)"""
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'