openclaw-agent-dashboard 1.0.4

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.
Files changed (111) hide show
  1. package/.github/workflows/release.yml +56 -0
  2. package/README.md +302 -0
  3. package/docs/CHANGELOG_AGENT_MODIFICATIONS.md +132 -0
  4. package/docs/RELEASE-LATEST.md +189 -0
  5. package/docs/RELEASE-MODEL-CONFIG.md +95 -0
  6. package/docs/release-guide.md +259 -0
  7. package/docs/release-operations-manual.md +167 -0
  8. package/docs/specs/tr3-install-system.md +580 -0
  9. package/docs/windows-collaboration-model-paths-troubleshooting.md +0 -0
  10. package/frontend/index.html +12 -0
  11. package/frontend/package-lock.json +1240 -0
  12. package/frontend/package.json +19 -0
  13. package/frontend/src/App.vue +331 -0
  14. package/frontend/src/components/AgentCard.vue +796 -0
  15. package/frontend/src/components/AgentConfigPanel.vue +539 -0
  16. package/frontend/src/components/AgentDetailPanel.vue +738 -0
  17. package/frontend/src/components/ErrorAnalysisView.vue +546 -0
  18. package/frontend/src/components/ErrorCenterPanel.vue +844 -0
  19. package/frontend/src/components/PerformanceMonitor.vue +515 -0
  20. package/frontend/src/components/SettingsPanel.vue +236 -0
  21. package/frontend/src/components/TokenAnalysisPanel.vue +683 -0
  22. package/frontend/src/components/chain/ChainEdge.vue +85 -0
  23. package/frontend/src/components/chain/ChainNode.vue +166 -0
  24. package/frontend/src/components/chain/TaskChainView.vue +425 -0
  25. package/frontend/src/components/chain/index.ts +3 -0
  26. package/frontend/src/components/chain/types.ts +70 -0
  27. package/frontend/src/components/collaboration/CollaborationFlowSection.vue +1032 -0
  28. package/frontend/src/components/collaboration/CollaborationFlowWrapper.vue +113 -0
  29. package/frontend/src/components/performance/PerformancePanel.vue +119 -0
  30. package/frontend/src/components/performance/PerformanceSection.vue +1137 -0
  31. package/frontend/src/components/tasks/TaskStatusSection.vue +973 -0
  32. package/frontend/src/components/timeline/TimelineConnector.vue +31 -0
  33. package/frontend/src/components/timeline/TimelineRound.vue +135 -0
  34. package/frontend/src/components/timeline/TimelineStep.vue +691 -0
  35. package/frontend/src/components/timeline/TimelineToolLink.vue +109 -0
  36. package/frontend/src/components/timeline/TimelineView.vue +540 -0
  37. package/frontend/src/components/timeline/index.ts +5 -0
  38. package/frontend/src/components/timeline/types.ts +120 -0
  39. package/frontend/src/composables/index.ts +7 -0
  40. package/frontend/src/composables/useDebounce.ts +48 -0
  41. package/frontend/src/composables/useRealtime.ts +52 -0
  42. package/frontend/src/composables/useState.ts +52 -0
  43. package/frontend/src/composables/useThrottle.ts +46 -0
  44. package/frontend/src/composables/useVirtualScroll.ts +106 -0
  45. package/frontend/src/main.ts +4 -0
  46. package/frontend/src/managers/EventDispatcher.ts +127 -0
  47. package/frontend/src/managers/RealtimeDataManager.ts +293 -0
  48. package/frontend/src/managers/StateManager.ts +128 -0
  49. package/frontend/src/managers/index.ts +5 -0
  50. package/frontend/src/types/collaboration.ts +135 -0
  51. package/frontend/src/types/index.ts +20 -0
  52. package/frontend/src/types/performance.ts +105 -0
  53. package/frontend/src/types/task.ts +38 -0
  54. package/frontend/vite.config.ts +18 -0
  55. package/package.json +22 -0
  56. package/plugin/README.md +99 -0
  57. package/plugin/config.json.example +1 -0
  58. package/plugin/index.js +250 -0
  59. package/plugin/openclaw.plugin.json +17 -0
  60. package/plugin/package.json +21 -0
  61. package/scripts/build-plugin.js +67 -0
  62. package/scripts/bundle.sh +62 -0
  63. package/scripts/install-plugin.sh +162 -0
  64. package/scripts/install-python-deps.js +346 -0
  65. package/scripts/install-python-deps.sh +226 -0
  66. package/scripts/install.js +512 -0
  67. package/scripts/install.sh +367 -0
  68. package/scripts/lib/common.js +490 -0
  69. package/scripts/lib/common.sh +137 -0
  70. package/scripts/release-pack.sh +110 -0
  71. package/scripts/start.js +50 -0
  72. package/scripts/test_available_models.py +284 -0
  73. package/scripts/test_websocket_ping.py +44 -0
  74. package/src/backend/agents.py +73 -0
  75. package/src/backend/api/__init__.py +1 -0
  76. package/src/backend/api/agent_config_api.py +90 -0
  77. package/src/backend/api/agents.py +73 -0
  78. package/src/backend/api/agents_config.py +75 -0
  79. package/src/backend/api/chains.py +126 -0
  80. package/src/backend/api/collaboration.py +902 -0
  81. package/src/backend/api/debug_paths.py +39 -0
  82. package/src/backend/api/error_analysis.py +146 -0
  83. package/src/backend/api/errors.py +281 -0
  84. package/src/backend/api/performance.py +784 -0
  85. package/src/backend/api/subagents.py +770 -0
  86. package/src/backend/api/timeline.py +144 -0
  87. package/src/backend/api/websocket.py +251 -0
  88. package/src/backend/collaboration.py +405 -0
  89. package/src/backend/data/__init__.py +1 -0
  90. package/src/backend/data/agent_config_manager.py +270 -0
  91. package/src/backend/data/chain_reader.py +299 -0
  92. package/src/backend/data/config_reader.py +153 -0
  93. package/src/backend/data/error_analyzer.py +430 -0
  94. package/src/backend/data/session_reader.py +445 -0
  95. package/src/backend/data/subagent_reader.py +244 -0
  96. package/src/backend/data/task_history.py +118 -0
  97. package/src/backend/data/timeline_reader.py +981 -0
  98. package/src/backend/errors.py +63 -0
  99. package/src/backend/main.py +89 -0
  100. package/src/backend/mechanism_reader.py +131 -0
  101. package/src/backend/mechanisms.py +32 -0
  102. package/src/backend/performance.py +474 -0
  103. package/src/backend/requirements.txt +5 -0
  104. package/src/backend/session_reader.py +238 -0
  105. package/src/backend/status/__init__.py +1 -0
  106. package/src/backend/status/error_detector.py +122 -0
  107. package/src/backend/status/status_calculator.py +301 -0
  108. package/src/backend/status_calculator.py +121 -0
  109. package/src/backend/subagent_reader.py +229 -0
  110. package/src/backend/watchers/__init__.py +4 -0
  111. package/src/backend/watchers/file_watcher.py +159 -0
@@ -0,0 +1,118 @@
1
+ """
2
+ 任务历史持久化 - 保存已完成任务,避免 runs.json 清空后数据丢失
3
+ 数据存放在 Dashboard 自有目录,不修改 OpenClaw 的 ~/.openclaw 目录结构。
4
+ """
5
+ import json
6
+ import os
7
+ from pathlib import Path
8
+ from typing import List, Dict, Any
9
+
10
+ # 旧路径(兼容迁移):~/.openclaw/dashboard/ → ~/.openclaw-dashboard/ → ~/.openclaw-agent-dashboard/
11
+ _LEGACY_DASHBOARD_DIR = Path.home() / ".openclaw" / "dashboard"
12
+ _LEGACY_TASK_HISTORY_PATH = _LEGACY_DASHBOARD_DIR / "task_history.json"
13
+ _PREV_DASHBOARD_DIR = Path.home() / ".openclaw-dashboard"
14
+ _PREV_TASK_HISTORY_PATH = _PREV_DASHBOARD_DIR / "task_history.json"
15
+
16
+
17
+ def get_dashboard_data_dir() -> Path:
18
+ """Dashboard 数据目录:优先 OPENCLAW_AGENT_DASHBOARD_DATA,否则 ~/.openclaw-agent-dashboard"""
19
+ env = os.environ.get("OPENCLAW_AGENT_DASHBOARD_DATA")
20
+ if env:
21
+ return Path(env).expanduser()
22
+ return Path.home() / ".openclaw-agent-dashboard"
23
+
24
+
25
+ DASHBOARD_DATA_DIR = get_dashboard_data_dir()
26
+ TASK_HISTORY_PATH = DASHBOARD_DATA_DIR / "task_history.json"
27
+ MAX_HISTORY_ITEMS = 200
28
+
29
+
30
+ def _ensure_dir():
31
+ DASHBOARD_DATA_DIR.mkdir(parents=True, exist_ok=True)
32
+
33
+
34
+ def _migrate_from_legacy_if_needed() -> None:
35
+ """若新路径下无文件,则从旧路径迁移一次(顺序:~/.openclaw/dashboard → ~/.openclaw-dashboard)"""
36
+ if TASK_HISTORY_PATH.exists():
37
+ return
38
+ for src in (_LEGACY_TASK_HISTORY_PATH, _PREV_TASK_HISTORY_PATH):
39
+ if not src.exists():
40
+ continue
41
+ try:
42
+ _ensure_dir()
43
+ with open(src, 'r', encoding='utf-8') as f:
44
+ data = json.load(f)
45
+ with open(TASK_HISTORY_PATH, 'w', encoding='utf-8') as f:
46
+ json.dump(data, f, ensure_ascii=False, indent=2)
47
+ print(f"[TaskHistory] 已从 {src} 迁移到 {TASK_HISTORY_PATH}")
48
+ except Exception as e:
49
+ print(f"[TaskHistory] 迁移旧数据失败: {e}")
50
+ return
51
+
52
+
53
+ def load_task_history() -> List[Dict[str, Any]]:
54
+ """加载任务历史"""
55
+ _migrate_from_legacy_if_needed()
56
+ if not TASK_HISTORY_PATH.exists():
57
+ return []
58
+ try:
59
+ with open(TASK_HISTORY_PATH, 'r', encoding='utf-8') as f:
60
+ data = json.load(f)
61
+ tasks = data.get('tasks', [])
62
+ return tasks if isinstance(tasks, list) else []
63
+ except Exception as e:
64
+ print(f"加载任务历史失败: {e}")
65
+ return []
66
+
67
+
68
+ def save_task_history(tasks: List[Dict[str, Any]]) -> None:
69
+ """保存任务历史,保留最近 N 条"""
70
+ _ensure_dir()
71
+ trimmed = tasks[:MAX_HISTORY_ITEMS]
72
+ try:
73
+ with open(TASK_HISTORY_PATH, 'w', encoding='utf-8') as f:
74
+ json.dump({'tasks': trimmed, 'version': 1}, f, ensure_ascii=False, indent=2)
75
+ except Exception as e:
76
+ print(f"保存任务历史失败: {e}")
77
+
78
+
79
+ def merge_with_history(
80
+ current_runs: List[Dict[str, Any]],
81
+ run_to_task_fn,
82
+ ) -> List[Dict[str, Any]]:
83
+ """
84
+ 合并当前 runs 与历史,并持久化新完成的任务
85
+
86
+ Args:
87
+ current_runs: 从 runs.json 读取的当前运行记录
88
+ run_to_task_fn: 将 run 转为 task 格式的函数 (run) -> dict
89
+ """
90
+ history = load_task_history()
91
+ history_ids = {t.get('id') for t in history if t.get('id')}
92
+
93
+ # 当前 runs 转为 tasks
94
+ current_tasks = []
95
+ new_completed = []
96
+ for run in current_runs:
97
+ task = run_to_task_fn(run)
98
+ current_tasks.append(task)
99
+ run_id = run.get('runId', '')
100
+ if run.get('endedAt') and run_id and run_id not in history_ids:
101
+ new_completed.append(task)
102
+ history_ids.add(run_id)
103
+
104
+ # 新完成的任务加入历史
105
+ if new_completed:
106
+ for t in reversed(new_completed):
107
+ history.insert(0, t)
108
+ save_task_history(history)
109
+
110
+ # 合并:当前 runs 中的任务 + 历史中已不在 runs 里的
111
+ current_ids = {r.get('runId') for r in current_runs}
112
+ for h in history:
113
+ if h.get('id') not in current_ids:
114
+ current_tasks.append(h)
115
+
116
+ # 按开始时间倒序
117
+ current_tasks.sort(key=lambda x: x.get('startTime') or 0, reverse=True)
118
+ return current_tasks[:100] # 最多返回 100 条