openclaw-agent-dashboard 1.0.21 → 1.0.23
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/README.md +55 -321
- package/frontend-dist/assets/index-B7XqKAxm.css +1 -0
- package/frontend-dist/assets/index-CxJaSYyo.js +24 -0
- package/{frontend → frontend-dist}/index.html +2 -1
- package/{plugin/openclaw.plugin.json → openclaw.plugin.json} +2 -2
- package/package.json +21 -13
- package/.github/workflows/release.yml +0 -56
- package/VERSION_DISPLAY_delivery.md +0 -242
- package/VERSION_DISPLAY_implementation_summary.md +0 -315
- package/design_manifest.md +0 -100
- package/docs/CHANGELOG_AGENT_MODIFICATIONS.md +0 -132
- package/docs/MAINTAINER_RELEASE_WORKFLOW.md +0 -211
- package/docs/Openclaw-Agent-Dashboard/345/217/221/345/270/203/344/270/216/346/233/264/346/226/260.md +0 -147
- package/docs/RELEASE-LATEST.md +0 -189
- package/docs/RELEASE-MODEL-CONFIG.md +0 -95
- package/docs/WINDOWS_INSTALL_TROUBLESHOOTING.md +0 -171
- package/docs/design/.gitkeep +0 -0
- package/docs/design/VERSION_DISPLAY_design.md +0 -1236
- package/docs/release-guide.md +0 -259
- package/docs/release-operations-manual.md +0 -167
- package/docs/reviews/.gitkeep +0 -0
- package/docs/reviews/approval_history.json +0 -14
- package/docs/reviews/cr_VERSION_DISPLAY.md +0 -397
- package/docs/reviews/traceability_manifest.json +0 -279
- package/docs/specs/VERSION_DISPLAY_spec.md +0 -371
- package/docs/specs/tr3-install-system.md +0 -580
- package/docs/windows-collaboration-model-paths-troubleshooting.md +0 -0
- package/frontend/package-lock.json +0 -1240
- package/frontend/package.json +0 -19
- package/frontend/src/App.vue +0 -355
- package/frontend/src/components/AgentCard.vue +0 -796
- package/frontend/src/components/AgentConfigPanel.vue +0 -539
- package/frontend/src/components/AgentDetailPanel.vue +0 -738
- package/frontend/src/components/ErrorAnalysisView.vue +0 -546
- package/frontend/src/components/ErrorCenterPanel.vue +0 -844
- package/frontend/src/components/PerformanceMonitor.vue +0 -515
- package/frontend/src/components/SettingsPanel.vue +0 -236
- package/frontend/src/components/TokenAnalysisPanel.vue +0 -683
- package/frontend/src/components/chain/ChainEdge.vue +0 -85
- package/frontend/src/components/chain/ChainNode.vue +0 -166
- package/frontend/src/components/chain/TaskChainView.vue +0 -425
- package/frontend/src/components/chain/index.ts +0 -3
- package/frontend/src/components/chain/types.ts +0 -70
- package/frontend/src/components/collaboration/CollaborationFlowSection.vue +0 -1032
- package/frontend/src/components/collaboration/CollaborationFlowWrapper.vue +0 -113
- package/frontend/src/components/common/VersionDisplay.vue +0 -187
- package/frontend/src/components/performance/PerformancePanel.vue +0 -119
- package/frontend/src/components/performance/PerformanceSection.vue +0 -1137
- package/frontend/src/components/tasks/TaskStatusSection.vue +0 -973
- package/frontend/src/components/timeline/TimelineConnector.vue +0 -31
- package/frontend/src/components/timeline/TimelineRound.vue +0 -135
- package/frontend/src/components/timeline/TimelineStep.vue +0 -691
- package/frontend/src/components/timeline/TimelineToolLink.vue +0 -109
- package/frontend/src/components/timeline/TimelineView.vue +0 -540
- package/frontend/src/components/timeline/index.ts +0 -5
- package/frontend/src/components/timeline/types.ts +0 -120
- package/frontend/src/composables/index.ts +0 -7
- package/frontend/src/composables/useDebounce.ts +0 -48
- package/frontend/src/composables/useRealtime.ts +0 -52
- package/frontend/src/composables/useState.ts +0 -52
- package/frontend/src/composables/useThrottle.ts +0 -46
- package/frontend/src/composables/useVirtualScroll.ts +0 -106
- package/frontend/src/main.ts +0 -4
- package/frontend/src/managers/EventDispatcher.ts +0 -127
- package/frontend/src/managers/RealtimeDataManager.ts +0 -302
- package/frontend/src/managers/StateManager.ts +0 -128
- package/frontend/src/managers/index.ts +0 -5
- package/frontend/src/types/collaboration.ts +0 -135
- package/frontend/src/types/index.ts +0 -20
- package/frontend/src/types/performance.ts +0 -105
- package/frontend/src/types/task.ts +0 -38
- package/frontend/vite.config.ts +0 -18
- package/legacy_code_anatomy.md +0 -518
- package/plugin/README.md +0 -99
- package/plugin/config.json.example +0 -1
- package/plugin/package.json +0 -26
- package/scripts/build-plugin.js +0 -81
- package/scripts/bundle.sh +0 -62
- package/scripts/install-plugin.sh +0 -162
- package/scripts/install-python-deps.sh +0 -226
- package/scripts/install.js +0 -684
- package/scripts/install.sh +0 -367
- package/scripts/lib/common.sh +0 -137
- package/scripts/release-pack.sh +0 -110
- package/scripts/start.js +0 -50
- package/scripts/test_available_models.py +0 -284
- package/scripts/test_version_display.sh +0 -128
- package/scripts/test_websocket_ping.py +0 -44
- package/session_registry.json +0 -58
- package/tests/.gitkeep +0 -0
- package/tests/qa_regression_report.md +0 -359
- package/tests/qa_version_display_report.md +0 -598
- /package/{src/backend → dashboard}/agents.py +0 -0
- /package/{src/backend → dashboard}/api/__init__.py +0 -0
- /package/{src/backend → dashboard}/api/agent_config_api.py +0 -0
- /package/{src/backend → dashboard}/api/agents.py +0 -0
- /package/{src/backend → dashboard}/api/agents_config.py +0 -0
- /package/{src/backend → dashboard}/api/chains.py +0 -0
- /package/{src/backend → dashboard}/api/collaboration.py +0 -0
- /package/{src/backend → dashboard}/api/debug_paths.py +0 -0
- /package/{src/backend → dashboard}/api/error_analysis.py +0 -0
- /package/{src/backend → dashboard}/api/errors.py +0 -0
- /package/{src/backend → dashboard}/api/performance.py +0 -0
- /package/{src/backend → dashboard}/api/subagents.py +0 -0
- /package/{src/backend → dashboard}/api/timeline.py +0 -0
- /package/{src/backend → dashboard}/api/version.py +0 -0
- /package/{src/backend → dashboard}/api/websocket.py +0 -0
- /package/{src/backend → dashboard}/collaboration.py +0 -0
- /package/{src/backend → dashboard}/data/__init__.py +0 -0
- /package/{src/backend → dashboard}/data/agent_config_manager.py +0 -0
- /package/{src/backend → dashboard}/data/chain_reader.py +0 -0
- /package/{src/backend → dashboard}/data/config_reader.py +0 -0
- /package/{src/backend → dashboard}/data/error_analyzer.py +0 -0
- /package/{src/backend → dashboard}/data/session_reader.py +0 -0
- /package/{src/backend → dashboard}/data/subagent_reader.py +0 -0
- /package/{src/backend → dashboard}/data/task_history.py +0 -0
- /package/{src/backend → dashboard}/data/timeline_reader.py +0 -0
- /package/{src/backend → dashboard}/data/version_info_reader.py +0 -0
- /package/{src/backend → dashboard}/errors.py +0 -0
- /package/{src/backend → dashboard}/main.py +0 -0
- /package/{src/backend → dashboard}/mechanism_reader.py +0 -0
- /package/{src/backend → dashboard}/mechanisms.py +0 -0
- /package/{src/backend → dashboard}/performance.py +0 -0
- /package/{src/backend → dashboard}/requirements.txt +0 -0
- /package/{src/backend → dashboard}/session_reader.py +0 -0
- /package/{src/backend → dashboard}/status/__init__.py +0 -0
- /package/{src/backend → dashboard}/status/change_tracker.py +0 -0
- /package/{src/backend → dashboard}/status/error_detector.py +0 -0
- /package/{src/backend → dashboard}/status/status_cache.py +0 -0
- /package/{src/backend → dashboard}/status/status_calculator.py +0 -0
- /package/{src/backend → dashboard}/status_calculator.py +0 -0
- /package/{src/backend → dashboard}/subagent_reader.py +0 -0
- /package/{src/backend → dashboard}/watchers/__init__.py +0 -0
- /package/{src/backend → dashboard}/watchers/file_watcher.py +0 -0
- /package/{plugin/index.js → index.js} +0 -0
|
@@ -1,1236 +0,0 @@
|
|
|
1
|
-
# OpenClaw Agent Dashboard 版本号显示 架构设计
|
|
2
|
-
|
|
3
|
-
> **项目名称**: OpenClaw Agent Dashboard
|
|
4
|
-
> **特性标识**: VERSION_DISPLAY
|
|
5
|
-
> **版本**: 1.0.0
|
|
6
|
-
> **编写日期**: 2026-03-19
|
|
7
|
-
> **编写人员**: 架构师 (SA)
|
|
8
|
-
> **项目模式**: 增量开发(Incremental Mode)
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
## 1. 设计概述
|
|
13
|
-
|
|
14
|
-
### 1.1 设计目标
|
|
15
|
-
|
|
16
|
-
在 OpenClaw Agent Dashboard 中新增版本号显示功能,使用户能够在界面上直观地查看当前插件的版本信息。具体目标包括:
|
|
17
|
-
|
|
18
|
-
1. **提供版本信息 API**:新增 `GET /api/version` 端点,返回插件版本号、名称、描述等元数据
|
|
19
|
-
2. **实现前端显示组件**:创建 Vue 3 组件,在 Dashboard 主界面显示版本号
|
|
20
|
-
3. **集成实时数据管理**:将版本信息纳入现有的实时数据管理机制
|
|
21
|
-
4. **确保版本一致性**:保证前端显示、API 返回、实际安装版本三者完全一致
|
|
22
|
-
|
|
23
|
-
### 1.2 设计原则
|
|
24
|
-
|
|
25
|
-
1. **最小侵入原则**:对现有代码的修改范围最小化,优先通过新增模块实现功能
|
|
26
|
-
2. **降级优先原则**:版本信息获取失败时必须有合理的降级方案,不影响系统核心功能
|
|
27
|
-
3. **单一数据源原则**:版本号仅从 `package.json` 读取,避免多源数据导致的不一致
|
|
28
|
-
4. **性能优先原则**:使用缓存机制,避免频繁读取文件,确保响应时间 < 50ms
|
|
29
|
-
|
|
30
|
-
### 1.3 架构分层
|
|
31
|
-
|
|
32
|
-
```
|
|
33
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
34
|
-
│ 表现层 (Presentation Layer) │
|
|
35
|
-
│ └── VersionDisplay.vue (版本显示组件) │
|
|
36
|
-
├─────────────────────────────────────────────────────────────┤
|
|
37
|
-
│ 数据管理层 (Data Management Layer) │
|
|
38
|
-
│ ├── StateManager.ts (状态缓存) │
|
|
39
|
-
│ └── RealtimeDataManager.ts (实时数据管理) │
|
|
40
|
-
├─────────────────────────────────────────────────────────────┤
|
|
41
|
-
│ 通信层 (Communication Layer) │
|
|
42
|
-
│ └── HTTP Client (调用 GET /api/version) │
|
|
43
|
-
├─────────────────────────────────────────────────────────────┤
|
|
44
|
-
│ API 层 (API Layer) │
|
|
45
|
-
│ └── /api/version (版本信息端点) │
|
|
46
|
-
├─────────────────────────────────────────────────────────────┤
|
|
47
|
-
│ 数据访问层 (Data Access Layer) │
|
|
48
|
-
│ └── version_info_reader.py (版本信息读取) │
|
|
49
|
-
├─────────────────────────────────────────────────────────────┤
|
|
50
|
-
│ 数据源层 (Data Source Layer) │
|
|
51
|
-
│ └── package.json (版本号单一数据源) │
|
|
52
|
-
└─────────────────────────────────────────────────────────────┘
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
---
|
|
56
|
-
|
|
57
|
-
## 2. 模块设计
|
|
58
|
-
|
|
59
|
-
### 2.1 新增模块
|
|
60
|
-
|
|
61
|
-
#### 2.1.1 version.py `[src/backend/api/version.py]`
|
|
62
|
-
|
|
63
|
-
**职责**: 提供 `GET /api/version` 端点,返回插件版本信息。从 `package.json` 读取版本号,支持应用启动时缓存。
|
|
64
|
-
|
|
65
|
-
**导出接口**:
|
|
66
|
-
```python
|
|
67
|
-
from fastapi import APIRouter
|
|
68
|
-
from pydantic import BaseModel
|
|
69
|
-
from typing import Optional
|
|
70
|
-
|
|
71
|
-
router = APIRouter(prefix="/api", tags=["version"])
|
|
72
|
-
|
|
73
|
-
class VersionInfo(BaseModel):
|
|
74
|
-
version: str # 版本号,如 "1.0.10"
|
|
75
|
-
name: str # 插件名称
|
|
76
|
-
description: str # 插件描述
|
|
77
|
-
build_date: Optional[str] = None # 构建时间(可选)
|
|
78
|
-
git_commit: Optional[str] = None # Git 提交哈希(可选)
|
|
79
|
-
|
|
80
|
-
@router.get("/version", response_model=VersionInfo)
|
|
81
|
-
async def get_version_info() -> VersionInfo:
|
|
82
|
-
"""获取插件版本信息"""
|
|
83
|
-
...
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
**降级策略**:
|
|
87
|
-
- 如果 `package.json` 读取失败,返回 `version="unknown"`,其他字段填充默认值
|
|
88
|
-
- 记录错误日志,但不抛出异常,确保 API 始终返回 200 状态码
|
|
89
|
-
|
|
90
|
-
**需求追溯**:
|
|
91
|
-
- [REQ_VERSION_DISPLAY_001]
|
|
92
|
-
|
|
93
|
-
---
|
|
94
|
-
|
|
95
|
-
#### 2.1.2 VersionInfoReader `[src/backend/data/version_info_reader.py]`
|
|
96
|
-
|
|
97
|
-
**职责**: 负责从文件系统读取版本信息,支持缓存机制。在应用启动时读取并缓存,后续请求直接返回缓存数据。
|
|
98
|
-
|
|
99
|
-
**类设计**:
|
|
100
|
-
|
|
101
|
-
```python
|
|
102
|
-
from pathlib import Path
|
|
103
|
-
from typing import Optional
|
|
104
|
-
import json
|
|
105
|
-
from datetime import datetime
|
|
106
|
-
|
|
107
|
-
class VersionInfoReader:
|
|
108
|
-
"""版本信息读取器,支持缓存"""
|
|
109
|
-
|
|
110
|
-
def __init__(self, package_json_path: Optional[Path] = None):
|
|
111
|
-
self.package_json_path = package_json_path or Path(__file__).parent.parent.parent / "package.json"
|
|
112
|
-
self._cached_info: Optional[dict] = None
|
|
113
|
-
|
|
114
|
-
def read_version_info(self) -> dict:
|
|
115
|
-
"""
|
|
116
|
-
读取版本信息(带缓存)
|
|
117
|
-
|
|
118
|
-
Returns:
|
|
119
|
-
dict: 包含 version, name, description 等字段的字典
|
|
120
|
-
"""
|
|
121
|
-
if self._cached_info is not None:
|
|
122
|
-
return self._cached_info
|
|
123
|
-
|
|
124
|
-
try:
|
|
125
|
-
with open(self.package_json_path, 'r', encoding='utf-8') as f:
|
|
126
|
-
package_data = json.load(f)
|
|
127
|
-
|
|
128
|
-
self._cached_info = {
|
|
129
|
-
"version": package_data.get("version", "unknown"),
|
|
130
|
-
"name": package_data.get("name", "openclaw-agent-dashboard"),
|
|
131
|
-
"description": package_data.get("description", ""),
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
# 可选:读取构建时间(从环境变量或文件)
|
|
135
|
-
build_date = self._read_build_date()
|
|
136
|
-
if build_date:
|
|
137
|
-
self._cached_info["build_date"] = build_date
|
|
138
|
-
|
|
139
|
-
# 可选:读取 Git 提交哈希
|
|
140
|
-
git_commit = self._read_git_commit()
|
|
141
|
-
if git_commit:
|
|
142
|
-
self._cached_info["git_commit"] = git_commit
|
|
143
|
-
|
|
144
|
-
return self._cached_info
|
|
145
|
-
|
|
146
|
-
except Exception as e:
|
|
147
|
-
# 降级:返回默认值
|
|
148
|
-
self._cached_info = {
|
|
149
|
-
"version": "unknown",
|
|
150
|
-
"name": "openclaw-agent-dashboard",
|
|
151
|
-
"description": "",
|
|
152
|
-
}
|
|
153
|
-
# 记录错误日志
|
|
154
|
-
import logging
|
|
155
|
-
logger = logging.getLogger(__name__)
|
|
156
|
-
logger.error(f"Failed to read version info: {e}", exc_info=True)
|
|
157
|
-
return self._cached_info
|
|
158
|
-
|
|
159
|
-
def _read_build_date(self) -> Optional[str]:
|
|
160
|
-
"""读取构建时间(可选)"""
|
|
161
|
-
import os
|
|
162
|
-
return os.getenv("DASHBOARD_BUILD_DATE")
|
|
163
|
-
|
|
164
|
-
def _read_git_commit(self) -> Optional[str]:
|
|
165
|
-
"""读取 Git 提交哈希(可选)"""
|
|
166
|
-
import os
|
|
167
|
-
return os.getenv("DASHBOARD_GIT_COMMIT")
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
**降级策略**:
|
|
171
|
-
- 文件读取失败时返回默认值,不抛出异常
|
|
172
|
-
- 错误日志记录,便于排查问题
|
|
173
|
-
|
|
174
|
-
**需求追溯**:
|
|
175
|
-
- [REQ_VERSION_DISPLAY_001]
|
|
176
|
-
- [REQ_VERSION_DISPLAY_004]
|
|
177
|
-
|
|
178
|
-
---
|
|
179
|
-
|
|
180
|
-
#### 2.1.3 VersionDisplay.vue `[frontend/src/components/common/VersionDisplay.vue]`
|
|
181
|
-
|
|
182
|
-
**职责**: Vue 3 组件,在界面上显示版本号。使用 Composition API,在组件挂载时调用 API 获取版本信息,支持加载中、错误等状态。
|
|
183
|
-
|
|
184
|
-
**代码设计**:
|
|
185
|
-
|
|
186
|
-
```vue
|
|
187
|
-
<template>
|
|
188
|
-
<div class="version-display">
|
|
189
|
-
<template v-if="loading">
|
|
190
|
-
<span class="loading-text">加载中...</span>
|
|
191
|
-
</template>
|
|
192
|
-
<template v-else-if="error">
|
|
193
|
-
<span class="error-text">版本信息获取失败</span>
|
|
194
|
-
</template>
|
|
195
|
-
<template v-else>
|
|
196
|
-
<span class="version-text" @mouseenter="showTooltip = true" @mouseleave="showTooltip = false">
|
|
197
|
-
{{ displayText }}
|
|
198
|
-
</span>
|
|
199
|
-
<div v-if="showTooltip" class="tooltip">
|
|
200
|
-
<div class="tooltip-item"><strong>名称:</strong> {{ versionInfo.name }}</div>
|
|
201
|
-
<div class="tooltip-item"><strong>版本:</strong> {{ versionInfo.version }}</div>
|
|
202
|
-
<div class="tooltip-item"><strong>描述:</strong> {{ versionInfo.description }}</div>
|
|
203
|
-
<div v-if="versionInfo.build_date" class="tooltip-item">
|
|
204
|
-
<strong>构建时间:</strong> {{ formatBuildDate(versionInfo.build_date) }}
|
|
205
|
-
</div>
|
|
206
|
-
<div v-if="versionInfo.git_commit" class="tooltip-item">
|
|
207
|
-
<strong>Git 提交:</strong> {{ versionInfo.git_commit }}
|
|
208
|
-
</div>
|
|
209
|
-
</div>
|
|
210
|
-
</template>
|
|
211
|
-
</div>
|
|
212
|
-
</template>
|
|
213
|
-
|
|
214
|
-
<script setup lang="ts">
|
|
215
|
-
import { ref, onMounted, computed } from 'vue';
|
|
216
|
-
|
|
217
|
-
interface VersionInfo {
|
|
218
|
-
version: string;
|
|
219
|
-
name: string;
|
|
220
|
-
description: string;
|
|
221
|
-
build_date?: string;
|
|
222
|
-
git_commit?: string;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
const loading = ref(true);
|
|
226
|
-
const error = ref(false);
|
|
227
|
-
const versionInfo = ref<VersionInfo>({
|
|
228
|
-
version: '',
|
|
229
|
-
name: '',
|
|
230
|
-
description: '',
|
|
231
|
-
});
|
|
232
|
-
const showTooltip = ref(false);
|
|
233
|
-
|
|
234
|
-
const displayText = computed(() => {
|
|
235
|
-
if (versionInfo.value.name && versionInfo.value.version) {
|
|
236
|
-
return `${versionInfo.value.name} v${versionInfo.value.version}`;
|
|
237
|
-
}
|
|
238
|
-
return versionInfo.value.version || 'v?';
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
const formatBuildDate = (dateStr: string) => {
|
|
242
|
-
try {
|
|
243
|
-
return new Date(dateStr).toLocaleString('zh-CN');
|
|
244
|
-
} catch {
|
|
245
|
-
return dateStr;
|
|
246
|
-
}
|
|
247
|
-
};
|
|
248
|
-
|
|
249
|
-
const fetchVersionInfo = async () => {
|
|
250
|
-
try {
|
|
251
|
-
const response = await fetch('/api/version');
|
|
252
|
-
if (!response.ok) {
|
|
253
|
-
throw new Error(`HTTP ${response.status}`);
|
|
254
|
-
}
|
|
255
|
-
versionInfo.value = await response.json();
|
|
256
|
-
} catch (err) {
|
|
257
|
-
console.error('Failed to fetch version info:', err);
|
|
258
|
-
error.value = true;
|
|
259
|
-
} finally {
|
|
260
|
-
loading.value = false;
|
|
261
|
-
}
|
|
262
|
-
};
|
|
263
|
-
|
|
264
|
-
onMounted(() => {
|
|
265
|
-
fetchVersionInfo();
|
|
266
|
-
});
|
|
267
|
-
</script>
|
|
268
|
-
|
|
269
|
-
<style scoped>
|
|
270
|
-
.version-display {
|
|
271
|
-
font-size: 12px;
|
|
272
|
-
color: var(--text-color-secondary, #666);
|
|
273
|
-
display: inline-block;
|
|
274
|
-
position: relative;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
.loading-text,
|
|
278
|
-
.error-text {
|
|
279
|
-
color: var(--text-color-muted, #999);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
.version-text {
|
|
283
|
-
cursor: pointer;
|
|
284
|
-
transition: color 0.2s;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
.version-text:hover {
|
|
288
|
-
color: var(--text-color-primary, #333);
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
.tooltip {
|
|
292
|
-
position: absolute;
|
|
293
|
-
bottom: 100%;
|
|
294
|
-
left: 50%;
|
|
295
|
-
transform: translateX(-50%);
|
|
296
|
-
background: var(--tooltip-bg, #fff);
|
|
297
|
-
border: 1px solid var(--border-color, #ddd);
|
|
298
|
-
border-radius: 4px;
|
|
299
|
-
padding: 8px;
|
|
300
|
-
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
301
|
-
white-space: nowrap;
|
|
302
|
-
z-index: 1000;
|
|
303
|
-
margin-bottom: 4px;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
.tooltip-item {
|
|
307
|
-
margin: 4px 0;
|
|
308
|
-
}
|
|
309
|
-
</style>
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
**需求追溯**:
|
|
313
|
-
- [REQ_VERSION_DISPLAY_002]
|
|
314
|
-
|
|
315
|
-
---
|
|
316
|
-
|
|
317
|
-
#### 2.1.4 useVersionInfo.ts `[frontend/src/composables/useVersionInfo.ts]`(可选)
|
|
318
|
-
|
|
319
|
-
**职责**: 组合式函数,提供版本信息获取和状态管理的复用逻辑。
|
|
320
|
-
|
|
321
|
-
**代码设计**:
|
|
322
|
-
|
|
323
|
-
```typescript
|
|
324
|
-
import { ref, Ref } from 'vue';
|
|
325
|
-
|
|
326
|
-
export interface VersionInfo {
|
|
327
|
-
version: string;
|
|
328
|
-
name: string;
|
|
329
|
-
description: string;
|
|
330
|
-
build_date?: string;
|
|
331
|
-
git_commit?: string;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
export function useVersionInfo() {
|
|
335
|
-
const loading = ref(true);
|
|
336
|
-
const error = ref(false);
|
|
337
|
-
const versionInfo = ref<VersionInfo>({
|
|
338
|
-
version: '',
|
|
339
|
-
name: '',
|
|
340
|
-
description: '',
|
|
341
|
-
});
|
|
342
|
-
|
|
343
|
-
const fetchVersionInfo = async () => {
|
|
344
|
-
try {
|
|
345
|
-
const response = await fetch('/api/version');
|
|
346
|
-
if (!response.ok) {
|
|
347
|
-
throw new Error(`HTTP ${response.status}`);
|
|
348
|
-
}
|
|
349
|
-
versionInfo.value = await response.json();
|
|
350
|
-
} catch (err) {
|
|
351
|
-
console.error('Failed to fetch version info:', err);
|
|
352
|
-
error.value = true;
|
|
353
|
-
} finally {
|
|
354
|
-
loading.value = false;
|
|
355
|
-
}
|
|
356
|
-
};
|
|
357
|
-
|
|
358
|
-
return {
|
|
359
|
-
loading,
|
|
360
|
-
error,
|
|
361
|
-
versionInfo,
|
|
362
|
-
fetchVersionInfo,
|
|
363
|
-
};
|
|
364
|
-
}
|
|
365
|
-
```
|
|
366
|
-
|
|
367
|
-
**需求追溯**:
|
|
368
|
-
- [REQ_VERSION_DISPLAY_002]
|
|
369
|
-
|
|
370
|
-
---
|
|
371
|
-
|
|
372
|
-
### 2.2 修改模块
|
|
373
|
-
|
|
374
|
-
#### 2.2.1 main.py `[src/backend/main.py]`
|
|
375
|
-
|
|
376
|
-
**修改内容**: 在 FastAPI 应用中注册版本信息 API 路由。
|
|
377
|
-
|
|
378
|
-
**修改前**:
|
|
379
|
-
```python
|
|
380
|
-
from fastapi import FastAPI
|
|
381
|
-
from src.backend.api.agents import router as agents_router
|
|
382
|
-
from src.backend.api.websocket import router as websocket_router
|
|
383
|
-
# ... 其他路由
|
|
384
|
-
|
|
385
|
-
app = FastAPI(title="OpenClaw Agent Dashboard API")
|
|
386
|
-
|
|
387
|
-
app.include_router(agents_router)
|
|
388
|
-
app.include_router(websocket_router)
|
|
389
|
-
# ... 其他路由
|
|
390
|
-
```
|
|
391
|
-
|
|
392
|
-
**修改后**:
|
|
393
|
-
```python
|
|
394
|
-
from fastapi import FastAPI
|
|
395
|
-
from src.backend.api.agents import router as agents_router
|
|
396
|
-
from src.backend.api.websocket import router as websocket_router
|
|
397
|
-
from src.backend.api.version import router as version_router # 新增
|
|
398
|
-
# ... 其他路由
|
|
399
|
-
|
|
400
|
-
app = FastAPI(title="OpenClaw Agent Dashboard API")
|
|
401
|
-
|
|
402
|
-
app.include_router(agents_router)
|
|
403
|
-
app.include_router(websocket_router)
|
|
404
|
-
app.include_router(version_router) # 新增:注册版本信息路由
|
|
405
|
-
# ... 其他路由
|
|
406
|
-
```
|
|
407
|
-
|
|
408
|
-
**数据流变化**:
|
|
409
|
-
|
|
410
|
-
```
|
|
411
|
-
修改前:
|
|
412
|
-
前端 → 其他 API 路由
|
|
413
|
-
|
|
414
|
-
修改后:
|
|
415
|
-
前端 → GET /api/version → version.py → version_info_reader.py → package.json
|
|
416
|
-
前端 → 其他 API 路由
|
|
417
|
-
```
|
|
418
|
-
|
|
419
|
-
**需求追溯**: [REQ_VERSION_DISPLAY_001]
|
|
420
|
-
|
|
421
|
-
---
|
|
422
|
-
|
|
423
|
-
#### 2.2.2 App.vue `[frontend/src/App.vue]`
|
|
424
|
-
|
|
425
|
-
**修改内容**: 在主应用中引入并使用 `VersionDisplay` 组件。
|
|
426
|
-
|
|
427
|
-
**修改前**:
|
|
428
|
-
```vue
|
|
429
|
-
<template>
|
|
430
|
-
<div id="app">
|
|
431
|
-
<Header />
|
|
432
|
-
<MainContent />
|
|
433
|
-
<Footer />
|
|
434
|
-
</div>
|
|
435
|
-
</template>
|
|
436
|
-
|
|
437
|
-
<script setup lang="ts">
|
|
438
|
-
import Header from './components/Header.vue';
|
|
439
|
-
import MainContent from './components/MainContent.vue';
|
|
440
|
-
import Footer from './components/Footer.vue';
|
|
441
|
-
</script>
|
|
442
|
-
```
|
|
443
|
-
|
|
444
|
-
**修改后**:
|
|
445
|
-
```vue
|
|
446
|
-
<template>
|
|
447
|
-
<div id="app">
|
|
448
|
-
<Header />
|
|
449
|
-
<MainContent />
|
|
450
|
-
<Footer />
|
|
451
|
-
<VersionDisplay /> <!-- 新增:版本显示组件 -->
|
|
452
|
-
</div>
|
|
453
|
-
</template>
|
|
454
|
-
|
|
455
|
-
<script setup lang="ts">
|
|
456
|
-
import Header from './components/Header.vue';
|
|
457
|
-
import MainContent from './components/MainContent.vue';
|
|
458
|
-
import Footer from './components/Footer.vue';
|
|
459
|
-
import VersionDisplay from './components/common/VersionDisplay.vue'; // 新增
|
|
460
|
-
</script>
|
|
461
|
-
```
|
|
462
|
-
|
|
463
|
-
**数据流变化**: 无数据流变化,仅新增 UI 组件渲染
|
|
464
|
-
|
|
465
|
-
**需求追溯**: [REQ_VERSION_DISPLAY_002]
|
|
466
|
-
|
|
467
|
-
---
|
|
468
|
-
|
|
469
|
-
#### 2.2.3 RealtimeDataManager.ts `[frontend/src/managers/RealtimeDataManager.ts]`
|
|
470
|
-
|
|
471
|
-
**修改内容**: 新增版本信息管理逻辑,在应用启动时调用一次 `/api/version`。
|
|
472
|
-
|
|
473
|
-
**修改前**:
|
|
474
|
-
```typescript
|
|
475
|
-
export class RealtimeDataManager {
|
|
476
|
-
private stateManager: StateManager;
|
|
477
|
-
|
|
478
|
-
constructor(stateManager: StateManager) {
|
|
479
|
-
this.stateManager = stateManager;
|
|
480
|
-
this.initialize();
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
private async initialize() {
|
|
484
|
-
// 现有的初始化逻辑
|
|
485
|
-
await this.connectWebSocket();
|
|
486
|
-
// ...
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
```
|
|
490
|
-
|
|
491
|
-
**修改后**:
|
|
492
|
-
```typescript
|
|
493
|
-
export interface VersionInfo {
|
|
494
|
-
version: string;
|
|
495
|
-
name: string;
|
|
496
|
-
description: string;
|
|
497
|
-
build_date?: string;
|
|
498
|
-
git_commit?: string;
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
export class RealtimeDataManager {
|
|
502
|
-
private stateManager: StateManager;
|
|
503
|
-
|
|
504
|
-
constructor(stateManager: StateManager) {
|
|
505
|
-
this.stateManager = stateManager;
|
|
506
|
-
this.initialize();
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
private async initialize() {
|
|
510
|
-
// 现有的初始化逻辑
|
|
511
|
-
await this.connectWebSocket();
|
|
512
|
-
// 新增:加载版本信息
|
|
513
|
-
await this.loadVersionInfo();
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
/**
|
|
517
|
-
* 加载版本信息
|
|
518
|
-
* @private
|
|
519
|
-
*/
|
|
520
|
-
private async loadVersionInfo(retryCount = 0, maxRetries = 3): Promise<void> {
|
|
521
|
-
try {
|
|
522
|
-
const response = await fetch('/api/version');
|
|
523
|
-
if (!response.ok) {
|
|
524
|
-
throw new Error(`HTTP ${response.status}`);
|
|
525
|
-
}
|
|
526
|
-
const versionInfo: VersionInfo = await response.json();
|
|
527
|
-
|
|
528
|
-
// 缓存到 StateManager
|
|
529
|
-
this.stateManager.setVersionInfo(versionInfo);
|
|
530
|
-
|
|
531
|
-
} catch (err) {
|
|
532
|
-
console.error('Failed to load version info:', err);
|
|
533
|
-
|
|
534
|
-
// 重试机制(指数退避)
|
|
535
|
-
if (retryCount < maxRetries) {
|
|
536
|
-
const delay = Math.pow(2, retryCount) * 1000; // 1s, 2s, 4s
|
|
537
|
-
await new Promise(resolve => setTimeout(resolve, delay));
|
|
538
|
-
await this.loadVersionInfo(retryCount + 1, maxRetries);
|
|
539
|
-
} else {
|
|
540
|
-
// 最终失败,设置默认版本信息
|
|
541
|
-
this.stateManager.setVersionInfo({
|
|
542
|
-
version: 'unknown',
|
|
543
|
-
name: 'openclaw-agent-dashboard',
|
|
544
|
-
description: '',
|
|
545
|
-
});
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
/**
|
|
551
|
-
* 获取缓存的版本信息
|
|
552
|
-
*/
|
|
553
|
-
public getVersionInfo(): VersionInfo | null {
|
|
554
|
-
return this.stateManager.getVersionInfo();
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
```
|
|
558
|
-
|
|
559
|
-
**数据流变化**:
|
|
560
|
-
|
|
561
|
-
```
|
|
562
|
-
修改前:
|
|
563
|
-
应用启动 → RealtimeDataManager.initialize() → WebSocket 连接
|
|
564
|
-
|
|
565
|
-
修改后:
|
|
566
|
-
应用启动 → RealtimeDataManager.initialize() → WebSocket 连接
|
|
567
|
-
→ loadVersionInfo() → GET /api/version → StateManager.setVersionInfo()
|
|
568
|
-
```
|
|
569
|
-
|
|
570
|
-
**需求追溯**: [REQ_VERSION_DISPLAY_003]
|
|
571
|
-
|
|
572
|
-
---
|
|
573
|
-
|
|
574
|
-
#### 2.2.4 StateManager.ts `[frontend/src/managers/StateManager.ts]`
|
|
575
|
-
|
|
576
|
-
**修改内容**: 新增版本信息的缓存字段和访问方法。
|
|
577
|
-
|
|
578
|
-
**修改前**:
|
|
579
|
-
```typescript
|
|
580
|
-
export class StateManager {
|
|
581
|
-
private agentStates: Map<string, AgentState> = new Map();
|
|
582
|
-
private taskHistory: TaskHistory[] = [];
|
|
583
|
-
|
|
584
|
-
constructor() {
|
|
585
|
-
// ...
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
// ... 现有方法
|
|
589
|
-
}
|
|
590
|
-
```
|
|
591
|
-
|
|
592
|
-
**修改后**:
|
|
593
|
-
```typescript
|
|
594
|
-
export interface VersionInfo {
|
|
595
|
-
version: string;
|
|
596
|
-
name: string;
|
|
597
|
-
description: string;
|
|
598
|
-
build_date?: string;
|
|
599
|
-
git_commit?: string;
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
export class StateManager {
|
|
603
|
-
private agentStates: Map<string, AgentState> = new Map();
|
|
604
|
-
private taskHistory: TaskHistory[] = [];
|
|
605
|
-
private versionInfo: VersionInfo | null = null; // 新增:版本信息缓存
|
|
606
|
-
|
|
607
|
-
constructor() {
|
|
608
|
-
// ...
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
/**
|
|
612
|
-
* 设置版本信息
|
|
613
|
-
*/
|
|
614
|
-
public setVersionInfo(versionInfo: VersionInfo): void {
|
|
615
|
-
this.versionInfo = versionInfo;
|
|
616
|
-
// 可选:触发版本信息更新事件
|
|
617
|
-
this.eventDispatcher.dispatch('version-info-updated', versionInfo);
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
/**
|
|
621
|
-
* 获取版本信息
|
|
622
|
-
*/
|
|
623
|
-
public getVersionInfo(): VersionInfo | null {
|
|
624
|
-
return this.versionInfo;
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
// ... 现有方法
|
|
628
|
-
}
|
|
629
|
-
```
|
|
630
|
-
|
|
631
|
-
**数据流变化**: 无数据流变化,仅新增状态字段和访问方法
|
|
632
|
-
|
|
633
|
-
**需求追溯**: [REQ_VERSION_DISPLAY_003]
|
|
634
|
-
|
|
635
|
-
---
|
|
636
|
-
|
|
637
|
-
#### 2.2.5 build-plugin.js `[scripts/build-plugin.js]`
|
|
638
|
-
|
|
639
|
-
**修改内容**: 确保构建脚本在构建时正确处理版本信息。
|
|
640
|
-
|
|
641
|
-
**修改前**:
|
|
642
|
-
```javascript
|
|
643
|
-
// 现有构建逻辑
|
|
644
|
-
async function build() {
|
|
645
|
-
// 构建前端
|
|
646
|
-
await exec('npm run build');
|
|
647
|
-
|
|
648
|
-
// 复制后端文件
|
|
649
|
-
await copyFiles('src/backend/', 'plugin/dashboard/');
|
|
650
|
-
|
|
651
|
-
// 复制前端构建产物
|
|
652
|
-
await copyFiles('frontend/dist/', 'plugin/frontend-dist/');
|
|
653
|
-
}
|
|
654
|
-
```
|
|
655
|
-
|
|
656
|
-
**修改后**:
|
|
657
|
-
```javascript
|
|
658
|
-
// 可选:在构建时注入构建时间
|
|
659
|
-
async function build() {
|
|
660
|
-
// 设置构建时间环境变量(可选)
|
|
661
|
-
const buildDate = new Date().toISOString();
|
|
662
|
-
process.env.DASHBOARD_BUILD_DATE = buildDate;
|
|
663
|
-
|
|
664
|
-
// 构建前端
|
|
665
|
-
await exec('npm run build');
|
|
666
|
-
|
|
667
|
-
// 复制后端文件
|
|
668
|
-
await copyFiles('src/backend/', 'plugin/dashboard/');
|
|
669
|
-
|
|
670
|
-
// 复制前端构建产物
|
|
671
|
-
await copyFiles('frontend/dist/', 'plugin/frontend-dist/');
|
|
672
|
-
|
|
673
|
-
// 验证版本信息是否正确(可选)
|
|
674
|
-
const packageJson = JSON.parse(await fs.readFile('package.json', 'utf-8'));
|
|
675
|
-
console.log(`Building version: ${packageJson.version}`);
|
|
676
|
-
}
|
|
677
|
-
```
|
|
678
|
-
|
|
679
|
-
**需求追溯**: [REQ_VERSION_DISPLAY_004]
|
|
680
|
-
|
|
681
|
-
---
|
|
682
|
-
|
|
683
|
-
## 3. 类设计
|
|
684
|
-
|
|
685
|
-
### 3.1 新增类清单
|
|
686
|
-
|
|
687
|
-
| 类名 | 所在模块 | 职责 | 依赖 |
|
|
688
|
-
|-----|---------|------|------|
|
|
689
|
-
| VersionInfoReader | src/backend/data/version_info_reader.py | 从 package.json 读取版本信息,支持缓存 | pathlib, json, logging |
|
|
690
|
-
| VersionInfo | src/backend/api/version.py (Pydantic Model) | 版本信息数据模型 | pydantic |
|
|
691
|
-
| VersionDisplay.vue | frontend/src/components/common/VersionDisplay.vue | 前端版本显示组件 | Vue 3 Composition API |
|
|
692
|
-
| useVersionInfo | frontend/src/composables/useVersionInfo.ts (可选) | 版本信息组合式函数 | Vue 3, TypeScript |
|
|
693
|
-
|
|
694
|
-
### 3.2 修改类清单
|
|
695
|
-
|
|
696
|
-
| 类名 | 所在模块 | 修改内容 | 影响程度 |
|
|
697
|
-
|-----|---------|---------|---------|
|
|
698
|
-
| FastAPI App | src/backend/main.py | 新增 version_router 注册 | 低(仅新增一行) |
|
|
699
|
-
| App.vue | frontend/src/App.vue | 新增 VersionDisplay 组件引入和使用 | 低(仅新增导入和标签) |
|
|
700
|
-
| RealtimeDataManager | frontend/src/managers/RealtimeDataManager.ts | 新增 loadVersionInfo() 方法和 getVersionInfo() 方法 | 中(新增方法) |
|
|
701
|
-
| StateManager | frontend/src/managers/StateManager.ts | 新增 versionInfo 字段和 setVersionInfo()/getVersionInfo() 方法 | 低(新增字段和方法) |
|
|
702
|
-
|
|
703
|
-
### 3.3 类关系图
|
|
704
|
-
|
|
705
|
-
```
|
|
706
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
707
|
-
│ 前端层 │
|
|
708
|
-
├─────────────────────────────────────────────────────────────┤
|
|
709
|
-
│ │
|
|
710
|
-
│ ┌─────────────────┐ 使用 ┌──────────────────────┐ │
|
|
711
|
-
│ │ VersionDisplay │─────────────▶│ useVersionInfo │ │
|
|
712
|
-
│ │ .vue │ │ (可选) │ │
|
|
713
|
-
│ └─────────────────┘ └──────────────────────┘ │
|
|
714
|
-
│ │ │
|
|
715
|
-
│ │ 调用 │
|
|
716
|
-
│ ▼ │
|
|
717
|
-
│ ┌─────────────────────────────────────────────────────┐ │
|
|
718
|
-
│ │ RealtimeDataManager │ │
|
|
719
|
-
│ │ + loadVersionInfo() │ │
|
|
720
|
-
│ │ + getVersionInfo() │ │
|
|
721
|
-
│ └───────────────┬─────────────────────────────────────┘ │
|
|
722
|
-
│ │ 管理 │
|
|
723
|
-
│ ▼ │
|
|
724
|
-
│ ┌─────────────────────────────────────────────────────┐ │
|
|
725
|
-
│ │ StateManager │ │
|
|
726
|
-
│ │ - versionInfo: VersionInfo | null │ │
|
|
727
|
-
│ │ + setVersionInfo(versionInfo) │ │
|
|
728
|
-
│ │ + getVersionInfo(): VersionInfo | null │ │
|
|
729
|
-
│ └─────────────────────────────────────────────────────┘ │
|
|
730
|
-
│ │
|
|
731
|
-
└─────────────────────────────────────────────────────────────┘
|
|
732
|
-
│
|
|
733
|
-
│ HTTP GET
|
|
734
|
-
▼
|
|
735
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
736
|
-
│ 后端层 │
|
|
737
|
-
├─────────────────────────────────────────────────────────────┤
|
|
738
|
-
│ │
|
|
739
|
-
│ ┌─────────────────┐ 调用 ┌──────────────────────┐ │
|
|
740
|
-
│ │ FastAPI App │─────────────▶│ version.py (router) │ │
|
|
741
|
-
│ │ (main.py) │ └──────────┬───────────┘ │
|
|
742
|
-
│ └─────────────────┘ │ │
|
|
743
|
-
│ │ 使用 │
|
|
744
|
-
│ ▼ │
|
|
745
|
-
│ ┌─────────────────────────────────────────────────────┐ │
|
|
746
|
-
│ │ VersionInfoReader │ │
|
|
747
|
-
│ │ - _cached_info: dict | null │ │
|
|
748
|
-
│ │ + readVersionInfo(): dict │ │
|
|
749
|
-
│ │ + _readBuildDate(): str | null │ │
|
|
750
|
-
│ │ + _readGitCommit(): str | null │ │
|
|
751
|
-
│ └───────────────────┬─────────────────────────────────┘ │
|
|
752
|
-
│ │ 读取 │
|
|
753
|
-
│ ▼ │
|
|
754
|
-
│ ┌─────────────────────────────────────────────────────┐ │
|
|
755
|
-
│ │ package.json │ │
|
|
756
|
-
│ │ - version: "1.0.10" │ │
|
|
757
|
-
│ │ - name: "openclaw-agent-dashboard" │ │
|
|
758
|
-
│ │ - description: "..." │ │
|
|
759
|
-
│ └─────────────────────────────────────────────────────┘ │
|
|
760
|
-
│ │
|
|
761
|
-
└─────────────────────────────────────────────────────────────┘
|
|
762
|
-
```
|
|
763
|
-
|
|
764
|
-
---
|
|
765
|
-
|
|
766
|
-
## 4. 数据流设计
|
|
767
|
-
|
|
768
|
-
### 4.1 版本信息加载流程
|
|
769
|
-
|
|
770
|
-
```
|
|
771
|
-
应用启动
|
|
772
|
-
│
|
|
773
|
-
├─▶ RealtimeDataManager.initialize()
|
|
774
|
-
│ │
|
|
775
|
-
│ ├─▶ connectWebSocket() (现有逻辑)
|
|
776
|
-
│ │
|
|
777
|
-
│ └─▶ loadVersionInfo()
|
|
778
|
-
│ │
|
|
779
|
-
│ ├─▶ fetch('/api/version')
|
|
780
|
-
│ │ │
|
|
781
|
-
│ │ ▼
|
|
782
|
-
│ │ FastAPI: GET /api/version
|
|
783
|
-
│ │ │
|
|
784
|
-
│ │ ├─▶ version_info_reader.readVersionInfo()
|
|
785
|
-
│ │ │ │
|
|
786
|
-
│ │ │ ├─▶ [首次] 读取 package.json
|
|
787
|
-
│ │ │ │ │
|
|
788
|
-
│ │ │ │ ├─▶ 解析 JSON
|
|
789
|
-
│ │ │ │ │
|
|
790
|
-
│ │ │ │ ├─▶ 读取环境变量(可选)
|
|
791
|
-
│ │ │ │ │
|
|
792
|
-
│ │ │ │ └─▶ 缓存到 _cached_info
|
|
793
|
-
│ │ │ │
|
|
794
|
-
│ │ │ └─▶ [后续] 返回缓存
|
|
795
|
-
│ │ │
|
|
796
|
-
│ │ └─▶ 返回 VersionInfo JSON
|
|
797
|
-
│ │
|
|
798
|
-
│ └─▶ StateManager.setVersionInfo(versionInfo)
|
|
799
|
-
│ │
|
|
800
|
-
│ └─▶ 触发 'version-info-updated' 事件
|
|
801
|
-
│
|
|
802
|
-
└─▶ App.vue 渲染
|
|
803
|
-
│
|
|
804
|
-
└─▶ VersionDisplay 组件挂载
|
|
805
|
-
│
|
|
806
|
-
└─▶ onMounted() → fetchVersionInfo()
|
|
807
|
-
│
|
|
808
|
-
└─▶ 从 StateManager 获取版本信息
|
|
809
|
-
│
|
|
810
|
-
└─▶ 显示版本号
|
|
811
|
-
```
|
|
812
|
-
|
|
813
|
-
### 4.2 降级流程(API 失败)
|
|
814
|
-
|
|
815
|
-
```
|
|
816
|
-
loadVersionInfo()
|
|
817
|
-
│
|
|
818
|
-
├─▶ fetch('/api/version') 失败
|
|
819
|
-
│ │
|
|
820
|
-
│ ├─▶ 捕获异常
|
|
821
|
-
│ │
|
|
822
|
-
│ ├─▶ 检查重试次数 < maxRetries (3次)
|
|
823
|
-
│ │ │
|
|
824
|
-
│ │ ├─▶ 是:延迟后重试(指数退避:1s, 2s, 4s)
|
|
825
|
-
│ │ │
|
|
826
|
-
│ │ └─▶ 否:设置默认版本信息
|
|
827
|
-
│ │ │
|
|
828
|
-
│ │ └─▶ StateManager.setVersionInfo({
|
|
829
|
-
│ │ version: "unknown",
|
|
830
|
-
│ │ name: "openclaw-agent-dashboard",
|
|
831
|
-
│ │ description: ""
|
|
832
|
-
│ │ })
|
|
833
|
-
│ │
|
|
834
|
-
│ └─▶ 记录错误日志
|
|
835
|
-
│
|
|
836
|
-
└─▶ VersionDisplay 组件显示
|
|
837
|
-
│
|
|
838
|
-
└─▶ 显示 "v?" 或 "openclaw-agent-dashboard vunknown"
|
|
839
|
-
```
|
|
840
|
-
|
|
841
|
-
### 4.3 降级流程(文件读取失败)
|
|
842
|
-
|
|
843
|
-
```
|
|
844
|
-
version_info_reader.readVersionInfo()
|
|
845
|
-
│
|
|
846
|
-
├─▶ 尝试读取 package.json
|
|
847
|
-
│ │
|
|
848
|
-
│ ├─▶ 失败(文件不存在、权限错误等)
|
|
849
|
-
│ │ │
|
|
850
|
-
│ │ ├─▶ 捕获异常
|
|
851
|
-
│ │ │
|
|
852
|
-
│ │ ├─▶ 返回默认值
|
|
853
|
-
│ │ │ │
|
|
854
|
-
│ │ │ └─▶ {
|
|
855
|
-
│ │ │ version: "unknown",
|
|
856
|
-
│ │ │ name: "openclaw-agent-dashboard",
|
|
857
|
-
│ │ │ description: ""
|
|
858
|
-
│ │ │ }
|
|
859
|
-
│ │ │
|
|
860
|
-
│ │ └─▶ 记录错误日志
|
|
861
|
-
│ │
|
|
862
|
-
│ └─▶ API 返回 200 OK(降级响应)
|
|
863
|
-
│
|
|
864
|
-
└─▶ 前端正常显示 "unknown" 版本号
|
|
865
|
-
```
|
|
866
|
-
|
|
867
|
-
---
|
|
868
|
-
|
|
869
|
-
## 5. 配置设计
|
|
870
|
-
|
|
871
|
-
### 5.1 环境变量配置
|
|
872
|
-
|
|
873
|
-
| 环境变量 | 类型 | 默认值 | 说明 | 对应需求 |
|
|
874
|
-
|---------|------|--------|------|---------|
|
|
875
|
-
| `DASHBOARD_VERSION` | String | 从 package.json 读取 | 覆盖版本号(用于开发环境) | [REQ_VERSION_DISPLAY_004] |
|
|
876
|
-
| `DASHBOARD_BUILD_DATE` | String | 构建时自动生成 | 构建时间戳(ISO 8601 格式) | [REQ_VERSION_DISPLAY_004] |
|
|
877
|
-
| `DASHBOARD_GIT_COMMIT` | String | 从 git 读取 | Git 提交哈希(短格式,如 abc123d) | [REQ_VERSION_DISPLAY_004] |
|
|
878
|
-
|
|
879
|
-
### 5.2 配置文件示例
|
|
880
|
-
|
|
881
|
-
**package.json**(现有文件,无需修改):
|
|
882
|
-
```json
|
|
883
|
-
{
|
|
884
|
-
"name": "openclaw-agent-dashboard",
|
|
885
|
-
"version": "1.0.10",
|
|
886
|
-
"description": "多 Agent 可视化看板 - 状态、任务、API、工作流、协作流程",
|
|
887
|
-
...
|
|
888
|
-
}
|
|
889
|
-
```
|
|
890
|
-
|
|
891
|
-
---
|
|
892
|
-
|
|
893
|
-
## 6. 降级策略
|
|
894
|
-
|
|
895
|
-
### 6.1 降级场景
|
|
896
|
-
|
|
897
|
-
| 场景 | 触发条件 | 降级行为 | 影响范围 |
|
|
898
|
-
|-----|---------|---------|---------|
|
|
899
|
-
| 文件读取失败 | package.json 文件不存在、权限不足、格式错误 | 返回 `version="unknown"`,记录错误日志 | 仅影响版本信息显示 |
|
|
900
|
-
| API 调用失败 | 网络错误、后端服务不可用 | 前端重试 3 次后显示 "版本信息获取失败" | 仅影响版本信息显示 |
|
|
901
|
-
| JSON 解析失败 | package.json 格式错误 | 返回 `version="unknown"`,记录错误日志 | 仅影响版本信息显示 |
|
|
902
|
-
| 超时 | 文件读取或 API 响应时间超过阈值 | 返回缓存数据(如果有)或默认值 | 仅影响版本信息显示 |
|
|
903
|
-
|
|
904
|
-
### 6.2 降级实现
|
|
905
|
-
|
|
906
|
-
**后端降级** (src/backend/data/version_info_reader.py):
|
|
907
|
-
```python
|
|
908
|
-
try:
|
|
909
|
-
with open(self.package_json_path, 'r', encoding='utf-8') as f:
|
|
910
|
-
package_data = json.load(f)
|
|
911
|
-
# 正常处理
|
|
912
|
-
except Exception as e:
|
|
913
|
-
# 降级:返回默认值
|
|
914
|
-
logger.error(f"Failed to read version info: {e}", exc_info=True)
|
|
915
|
-
return {
|
|
916
|
-
"version": "unknown",
|
|
917
|
-
"name": "openclaw-agent-dashboard",
|
|
918
|
-
"description": "",
|
|
919
|
-
}
|
|
920
|
-
```
|
|
921
|
-
|
|
922
|
-
**前端降级** (frontend/src/managers/RealtimeDataManager.ts):
|
|
923
|
-
```typescript
|
|
924
|
-
private async loadVersionInfo(retryCount = 0, maxRetries = 3): Promise<void> {
|
|
925
|
-
try {
|
|
926
|
-
const response = await fetch('/api/version');
|
|
927
|
-
if (!response.ok) {
|
|
928
|
-
throw new Error(`HTTP ${response.status}`);
|
|
929
|
-
}
|
|
930
|
-
const versionInfo: VersionInfo = await response.json();
|
|
931
|
-
this.stateManager.setVersionInfo(versionInfo);
|
|
932
|
-
} catch (err) {
|
|
933
|
-
console.error('Failed to load version info:', err);
|
|
934
|
-
|
|
935
|
-
if (retryCount < maxRetries) {
|
|
936
|
-
// 指数退避重试
|
|
937
|
-
const delay = Math.pow(2, retryCount) * 1000;
|
|
938
|
-
await new Promise(resolve => setTimeout(resolve, delay));
|
|
939
|
-
await this.loadVersionInfo(retryCount + 1, maxRetries);
|
|
940
|
-
} else {
|
|
941
|
-
// 最终降级:设置默认值
|
|
942
|
-
this.stateManager.setVersionInfo({
|
|
943
|
-
version: 'unknown',
|
|
944
|
-
name: 'openclaw-agent-dashboard',
|
|
945
|
-
description: '',
|
|
946
|
-
});
|
|
947
|
-
}
|
|
948
|
-
}
|
|
949
|
-
}
|
|
950
|
-
```
|
|
951
|
-
|
|
952
|
-
### 6.3 降级告警
|
|
953
|
-
|
|
954
|
-
- **日志级别**: ERROR(当降级发生时记录错误日志)
|
|
955
|
-
- **告警内容**: 包含降级原因(文件路径、错误信息)、时间戳
|
|
956
|
-
- **告警渠道**: 后端日志(可接入日志聚合平台如 ELK)
|
|
957
|
-
- **告警频率**: 避免重复告警,可使用去重机制
|
|
958
|
-
|
|
959
|
-
---
|
|
960
|
-
|
|
961
|
-
## 7. API 设计
|
|
962
|
-
|
|
963
|
-
### 7.1 新增 API 清单
|
|
964
|
-
|
|
965
|
-
| 方法 | 路径 | 描述 | 请求体 | 响应体 | 需求追溯 |
|
|
966
|
-
|-----|------|------|--------|--------|---------|
|
|
967
|
-
| GET | /api/version | 获取插件版本信息 | 无 | VersionInfo JSON | [REQ_VERSION_DISPLAY_001] |
|
|
968
|
-
|
|
969
|
-
### 7.2 API 详细设计
|
|
970
|
-
|
|
971
|
-
#### 7.2.1 GET /api/version
|
|
972
|
-
|
|
973
|
-
**接口描述**: 获取 OpenClaw Agent Dashboard 插件的版本信息,包括版本号、名称、描述等元数据。
|
|
974
|
-
|
|
975
|
-
**请求参数**: 无
|
|
976
|
-
|
|
977
|
-
**请求示例**:
|
|
978
|
-
```http
|
|
979
|
-
GET /api/version HTTP/1.1
|
|
980
|
-
Host: localhost:8000
|
|
981
|
-
Accept: application/json
|
|
982
|
-
```
|
|
983
|
-
|
|
984
|
-
**响应示例**(成功):
|
|
985
|
-
```http
|
|
986
|
-
HTTP/1.1 200 OK
|
|
987
|
-
Content-Type: application/json
|
|
988
|
-
|
|
989
|
-
{
|
|
990
|
-
"version": "1.0.10",
|
|
991
|
-
"name": "openclaw-agent-dashboard",
|
|
992
|
-
"description": "多 Agent 可视化看板 - 状态、任务、API、工作流、协作流程",
|
|
993
|
-
"build_date": "2026-03-19T12:34:56Z",
|
|
994
|
-
"git_commit": "abc123def456"
|
|
995
|
-
}
|
|
996
|
-
```
|
|
997
|
-
|
|
998
|
-
**响应示例**(降级):
|
|
999
|
-
```http
|
|
1000
|
-
HTTP/1.1 200 OK
|
|
1001
|
-
Content-Type: application/json
|
|
1002
|
-
|
|
1003
|
-
{
|
|
1004
|
-
"version": "unknown",
|
|
1005
|
-
"name": "openclaw-agent-dashboard",
|
|
1006
|
-
"description": ""
|
|
1007
|
-
}
|
|
1008
|
-
```
|
|
1009
|
-
|
|
1010
|
-
**响应字段说明**:
|
|
1011
|
-
|
|
1012
|
-
| 字段 | 类型 | 必填 | 说明 |
|
|
1013
|
-
|-----|------|------|------|
|
|
1014
|
-
| version | string | 是 | 版本号,如 "1.0.10" |
|
|
1015
|
-
| name | string | 是 | 插件名称 |
|
|
1016
|
-
| description | string | 是 | 插件描述 |
|
|
1017
|
-
| build_date | string | 否 | 构建时间(ISO 8601 格式) |
|
|
1018
|
-
| git_commit | string | 否 | Git 提交哈希(短格式) |
|
|
1019
|
-
|
|
1020
|
-
**错误处理**: 本接口始终返回 200 状态码,文件读取失败时返回降级数据(`version="unknown"`),错误信息通过后端日志记录。
|
|
1021
|
-
|
|
1022
|
-
**性能指标**:
|
|
1023
|
-
- 首次请求(无缓存): < 100ms(文件读取 + JSON 解析)
|
|
1024
|
-
- 后续请求(有缓存): < 50ms(内存读取)
|
|
1025
|
-
|
|
1026
|
-
**需求追溯**: [REQ_VERSION_DISPLAY_001]
|
|
1027
|
-
|
|
1028
|
-
---
|
|
1029
|
-
|
|
1030
|
-
## 8. 需求追溯表
|
|
1031
|
-
|
|
1032
|
-
### 8.1 需求 → 设计映射
|
|
1033
|
-
|
|
1034
|
-
| 需求 ID | 需求描述 | 设计章节 | 实现模块 |
|
|
1035
|
-
|---------|---------|---------|---------|
|
|
1036
|
-
| [REQ_VERSION_DISPLAY_001] | 后端版本信息 API | 2.1.1, 2.1.2, 2.2.1, 7.2.1 | src/backend/api/version.py, src/backend/data/version_info_reader.py |
|
|
1037
|
-
| [REQ_VERSION_DISPLAY_002] | 前端版本信息组件 | 2.1.3, 2.1.4, 2.2.2 | frontend/src/components/common/VersionDisplay.vue, frontend/src/composables/useVersionInfo.ts |
|
|
1038
|
-
| [REQ_VERSION_DISPLAY_003] | 实时数据管理器集成 | 2.2.3, 2.2.4 | frontend/src/managers/RealtimeDataManager.ts, frontend/src/managers/StateManager.ts |
|
|
1039
|
-
| [REQ_VERSION_DISPLAY_004] | 版本信息配置 | 2.1.2, 2.2.5, 5.1 | src/backend/data/version_info_reader.py, scripts/build-plugin.js, 环境变量 |
|
|
1040
|
-
|
|
1041
|
-
### 8.2 验收条件追溯
|
|
1042
|
-
|
|
1043
|
-
| 验收条件 | 对应设计 | 验证方法 |
|
|
1044
|
-
|---------|---------|---------|
|
|
1045
|
-
| AC-001-1: GET /api/version 返回 200 | 7.2.1 | 使用 curl 访问 API,检查状态码 |
|
|
1046
|
-
| AC-001-2: version 字段与 package.json 一致 | 2.1.2, 7.2.1 | 对比 API 返回值与 package.json |
|
|
1047
|
-
| AC-001-3: name 字段值为 "openclaw-agent-dashboard" | 7.2.1 | 检查 API 响应的 name 字段 |
|
|
1048
|
-
| AC-001-4: 文件读取失败时返回 "unknown" | 6.2 | 删除 package.json,检查 API 响应 |
|
|
1049
|
-
| AC-002-1: 组件成功渲染并显示版本号 | 2.1.3 | 在浏览器中打开 Dashboard,检查 UI |
|
|
1050
|
-
| AC-002-2: 版本号与 package.json 一致 | 2.1.3 | 对比前端显示与 package.json |
|
|
1051
|
-
| AC-002-3: 加载中状态显示 "加载中..." | 2.1.3 | 清除缓存,刷新页面,检查 UI |
|
|
1052
|
-
| AC-002-4: API 失败时显示友好提示 | 2.1.3, 6.2 | 模拟 API 失败,检查错误提示 |
|
|
1053
|
-
| AC-002-5: hover 显示完整信息 | 2.1.3 | 鼠标悬停版本号,检查 Tooltip |
|
|
1054
|
-
| AC-003-1: 版本信息在应用启动时自动加载 | 2.2.3, 4.1 | 检查应用启动日志,确认调用时机 |
|
|
1055
|
-
| AC-003-2: 状态管理器提供全局访问接口 | 2.2.4 | 测试 StateManager.getVersionInfo() |
|
|
1056
|
-
| AC-003-3: 加载失败时支持重试机制 | 2.2.3, 6.2 | 模拟 API 失败,检查重试逻辑 |
|
|
1057
|
-
| AC-004-1: 构建后插件包包含正确版本信息 | 2.2.5 | 构建插件,检查打包文件 |
|
|
1058
|
-
| AC-004-2: 后端 API 能正确读取版本信息 | 2.1.2 | 运行后端服务,访问 API |
|
|
1059
|
-
| AC-004-3: 环境变量覆盖功能正常 | 2.1.2, 5.1 | 设置环境变量,验证覆盖效果 |
|
|
1060
|
-
|
|
1061
|
-
---
|
|
1062
|
-
|
|
1063
|
-
## 9. 设计评审点
|
|
1064
|
-
|
|
1065
|
-
### 9.1 关键技术决策
|
|
1066
|
-
|
|
1067
|
-
| 决策点 | 选择 | 理由 | 风险 |
|
|
1068
|
-
|-------|------|------|------|
|
|
1069
|
-
| 版本号数据源 | 仅从 package.json 读取 | 单一数据源避免不一致,符合 npm 生态规范 | 需确保 package.json 版本号同步更新 |
|
|
1070
|
-
| 缓存策略 | 应用启动时读取并缓存 | 减少文件 I/O,提升响应性能(< 50ms) | 升级后需重启应用才能看到新版本号(可接受) |
|
|
1071
|
-
| API 设计 | GET /api/version,始终返回 200 | 简化前端错误处理,降级策略在后端实现 | 需通过日志记录降级事件 |
|
|
1072
|
-
| 前端组件位置 | 放在 App.vue 全局显示 | 一次性集成,所有页面都能看到版本号 | 可能占用屏幕空间(可通过样式调整) |
|
|
1073
|
-
| 重试机制 | 指数退避,最多 3 次 | 平衡可靠性和用户体验,避免无限重试 | 网络不稳定时可能导致较长的加载时间 |
|
|
1074
|
-
| 降级显示 | 显示 "unknown" 或 "v?" | 避免空白显示,给用户明确反馈 | 可能掩盖真实问题(需配合日志) |
|
|
1075
|
-
|
|
1076
|
-
### 9.2 风险点
|
|
1077
|
-
|
|
1078
|
-
| 风险 | 影响 | 缓解措施 | 优先级 |
|
|
1079
|
-
|-----|------|---------|--------|
|
|
1080
|
-
| package.json 版本号未同步更新 | 前端显示的版本号与实际安装版本不一致 | 在发布流程中增加版本号检查步骤 | 高 |
|
|
1081
|
-
| 版本文件读取失败率高 | 频繁触发降级,影响用户体验 | 在 CI/CD 中验证文件完整性,添加健康检查 | 中 |
|
|
1082
|
-
| 缓存导致升级后版本号不更新 | 用户升级后仍显示旧版本号 | 在文档中说明需重启应用,或提供刷新按钮 | 低 |
|
|
1083
|
-
| 前端组件渲染错误 | 导致整个 Dashboard 页面崩溃 | 使用 Vue 错误边界捕获异常,隔离组件错误 | 中 |
|
|
1084
|
-
| 环境变量被滥用 | 开发环境覆盖版本号后误发布到生产环境 | 在构建脚本中检查环境,生产环境禁止覆盖 | 中 |
|
|
1085
|
-
|
|
1086
|
-
### 9.3 待确认事项
|
|
1087
|
-
|
|
1088
|
-
| 事项 | 选项 | 建议 | 状态 |
|
|
1089
|
-
|-----|------|------|------|
|
|
1090
|
-
| 版本信息显示位置 | Footer / 右上角工具栏 / 其他 | 建议 Footer,不占用主要操作区域 | 待确认 |
|
|
1091
|
-
| 是否支持手动刷新版本号 | 是 / 否 | 建议不实现(需重启应用即可) | 待确认 |
|
|
1092
|
-
| 是否显示 Git 提交哈希 | 是 / 否 | 建议显示,方便问题排查 | 待确认 |
|
|
1093
|
-
| 降级时是否显示详细错误信息 | 是 / 否 | 建议否,仅显示 "unknown",错误信息在日志中 | 待确认 |
|
|
1094
|
-
|
|
1095
|
-
---
|
|
1096
|
-
|
|
1097
|
-
## 10. 依赖变更
|
|
1098
|
-
|
|
1099
|
-
### 10.1 新增依赖
|
|
1100
|
-
|
|
1101
|
-
**后端依赖**: 无新增依赖。仅使用 Python 标准库(`pathlib`、`json`、`logging`、`os`)和现有依赖(`fastapi`、`pydantic`)。
|
|
1102
|
-
|
|
1103
|
-
**前端依赖**: 无新增 npm 包。仅使用 Vue 3 和 TypeScript 标准特性。
|
|
1104
|
-
|
|
1105
|
-
### 10.2 版本兼容性
|
|
1106
|
-
|
|
1107
|
-
| 依赖 | 版本要求 | 兼容性说明 |
|
|
1108
|
-
|-----|---------|-----------|
|
|
1109
|
-
| Python | ≥ 3.8 | 使用标准库特性,兼容性良好 |
|
|
1110
|
-
| FastAPI | ≥ 0.109.0 | 使用现有版本,无变更 |
|
|
1111
|
-
| Pydantic | ≥ 2.5.0 | 使用现有版本,无变更 |
|
|
1112
|
-
| Vue | 3.4.0+ | 使用现有版本,无变更 |
|
|
1113
|
-
| TypeScript | 5.3+ | 使用现有版本,无变更 |
|
|
1114
|
-
|
|
1115
|
-
---
|
|
1116
|
-
|
|
1117
|
-
## 11. 实施建议
|
|
1118
|
-
|
|
1119
|
-
### 11.1 实施顺序
|
|
1120
|
-
|
|
1121
|
-
**阶段 1: 后端 API 实现(P0)**
|
|
1122
|
-
1. 创建 `src/backend/data/version_info_reader.py`,实现版本信息读取和缓存
|
|
1123
|
-
2. 创建 `src/backend/api/version.py`,实现 GET /api/version 端点
|
|
1124
|
-
3. 修改 `src/backend/main.py`,注册 version_router
|
|
1125
|
-
4. 单元测试:验证 API 返回正确的版本信息
|
|
1126
|
-
|
|
1127
|
-
**阶段 2: 前端组件实现(P0)**
|
|
1128
|
-
1. 创建 `frontend/src/components/common/VersionDisplay.vue`
|
|
1129
|
-
2. 修改 `frontend/src/App.vue`,集成版本显示组件
|
|
1130
|
-
3. 本地测试:验证组件渲染和版本号显示
|
|
1131
|
-
|
|
1132
|
-
**阶段 3: 实时数据管理集成(P1)**
|
|
1133
|
-
1. 修改 `frontend/src/managers/StateManager.ts`,新增版本信息缓存
|
|
1134
|
-
2. 修改 `frontend/src/managers/RealtimeDataManager.ts`,实现自动加载和重试机制
|
|
1135
|
-
3. 集成测试:验证应用启动时自动加载版本信息
|
|
1136
|
-
|
|
1137
|
-
**阶段 4: 配置和构建优化(P2)**
|
|
1138
|
-
1. 修改 `scripts/build-plugin.js`,确保版本信息正确注入(可选)
|
|
1139
|
-
2. 测试环境变量覆盖功能(可选)
|
|
1140
|
-
3. 端到端测试:验证从构建到部署的完整流程
|
|
1141
|
-
|
|
1142
|
-
### 11.2 测试策略
|
|
1143
|
-
|
|
1144
|
-
| 测试类型 | 测试内容 | 工具 |
|
|
1145
|
-
|---------|---------|------|
|
|
1146
|
-
| 单元测试 | VersionInfoReader 读取逻辑、缓存机制、降级策略 | pytest |
|
|
1147
|
-
| 单元测试 | VersionDisplay 组件渲染、状态切换、交互逻辑 | Vue Test Utils |
|
|
1148
|
-
| 集成测试 | API 端点响应、数据流完整链路 | pytest + httpx |
|
|
1149
|
-
| 手动测试 | 浏览器中验证 UI 显示、hover 效果 | Chrome DevTools |
|
|
1150
|
-
| 性能测试 | API 响应时间(首次/缓存)、内存占用 | locust / Apache Bench |
|
|
1151
|
-
| 兼容性测试 | Chrome、Firefox、Safari 下的组件渲染 | BrowserStack(可选) |
|
|
1152
|
-
|
|
1153
|
-
---
|
|
1154
|
-
|
|
1155
|
-
## 12. 附录
|
|
1156
|
-
|
|
1157
|
-
### 12.1 文件变更清单
|
|
1158
|
-
|
|
1159
|
-
| 变更类型 | 文件路径 | 说明 |
|
|
1160
|
-
|---------|---------|------|
|
|
1161
|
-
| **新增** | src/backend/data/version_info_reader.py | 版本信息读取器(支持缓存) |
|
|
1162
|
-
| **新增** | src/backend/api/version.py | 版本信息 API 路由 |
|
|
1163
|
-
| **新增** | frontend/src/components/common/VersionDisplay.vue | 版本显示 Vue 组件 |
|
|
1164
|
-
| **新增** | frontend/src/composables/useVersionInfo.ts | 版本信息组合式函数(可选) |
|
|
1165
|
-
| **修改** | src/backend/main.py | 注册 version_router(新增一行) |
|
|
1166
|
-
| **修改** | frontend/src/App.vue | 集成 VersionDisplay 组件(新增导入和标签) |
|
|
1167
|
-
| **修改** | frontend/src/managers/RealtimeDataManager.ts | 新增 loadVersionInfo() 方法 |
|
|
1168
|
-
| **修改** | frontend/src/managers/StateManager.ts | 新增版本信息缓存字段和方法 |
|
|
1169
|
-
| **修改** | scripts/build-plugin.js | 确保版本信息正确注入(可选) |
|
|
1170
|
-
|
|
1171
|
-
### 12.2 架构图
|
|
1172
|
-
|
|
1173
|
-
**系统整体架构**(包含版本显示功能):
|
|
1174
|
-
|
|
1175
|
-
```
|
|
1176
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
1177
|
-
│ 用户浏览器 │
|
|
1178
|
-
│ ┌─────────────────────────────────────────────────────────┐ │
|
|
1179
|
-
│ │ App.vue │ │
|
|
1180
|
-
│ │ ┌──────────────┐ ┌──────────────┐ ┌─────────────┐ │ │
|
|
1181
|
-
│ │ │ Header │ │ MainContent │ │ Footer │ │ │
|
|
1182
|
-
│ │ └──────────────┘ └──────────────┘ └─────────────┘ │ │
|
|
1183
|
-
│ │ ┌─────────────────────────────────────────────────────┐│ │
|
|
1184
|
-
│ │ │ VersionDisplay: "openclaw-agent-dashboard v1.0.10" ││ │
|
|
1185
|
-
│ │ └─────────────────────────────────────────────────────┘│ │
|
|
1186
|
-
│ └─────────────────────────────────────────────────────────┘ │
|
|
1187
|
-
│ ┌─────────────────────────────────────────────────────────┐ │
|
|
1188
|
-
│ │ StateManager (状态缓存) │ │
|
|
1189
|
-
│ │ - versionInfo: { version, name, description, ... } │ │
|
|
1190
|
-
│ └─────────────────────────────────────────────────────────┘ │
|
|
1191
|
-
│ ┌─────────────────────────────────────────────────────────┐ │
|
|
1192
|
-
│ │ RealtimeDataManager (实时数据管理) │ │
|
|
1193
|
-
│ │ - loadVersionInfo(): 调用 /api/version │ │
|
|
1194
|
-
│ └─────────────────────────────────────────────────────────┘ │
|
|
1195
|
-
└─────────────────────────────────────────────────────────────┘
|
|
1196
|
-
│
|
|
1197
|
-
│ HTTP GET /api/version
|
|
1198
|
-
▼
|
|
1199
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
1200
|
-
│ FastAPI 后端服务 │
|
|
1201
|
-
│ ┌─────────────────────────────────────────────────────────┐ │
|
|
1202
|
-
│ │ main.py (应用入口) │ │
|
|
1203
|
-
│ │ - app.include_router(version_router) │ │
|
|
1204
|
-
│ └─────────────────────────────────────────────────────────┘ │
|
|
1205
|
-
│ ┌─────────────────────────────────────────────────────────┐ │
|
|
1206
|
-
│ │ version.py (API 路由) │ │
|
|
1207
|
-
│ │ - @router.get("/version") │ │
|
|
1208
|
-
│ │ - 返回 VersionInfo 响应模型 │ │
|
|
1209
|
-
│ └─────────────────────────────────────────────────────────┘ │
|
|
1210
|
-
│ ┌─────────────────────────────────────────────────────────┐ │
|
|
1211
|
-
│ │ version_info_reader.py (数据读取) │ │
|
|
1212
|
-
│ │ - _cached_info: 缓存的版本信息 │ │
|
|
1213
|
-
│ │ - readVersionInfo(): 读取 package.json │ │
|
|
1214
|
-
│ └─────────────────────────────────────────────────────────┘ │
|
|
1215
|
-
└─────────────────────────────────────────────────────────────┘
|
|
1216
|
-
│
|
|
1217
|
-
│ 读取文件
|
|
1218
|
-
▼
|
|
1219
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
1220
|
-
│ 文件系统 │
|
|
1221
|
-
│ ┌─────────────────────────────────────────────────────────┐ │
|
|
1222
|
-
│ │ package.json │ │
|
|
1223
|
-
│ │ { │ │
|
|
1224
|
-
│ │ "name": "openclaw-agent-dashboard", │ │
|
|
1225
|
-
│ │ "version": "1.0.10", │ │
|
|
1226
|
-
│ │ "description": "..." │ │
|
|
1227
|
-
│ │ } │ │
|
|
1228
|
-
│ └─────────────────────────────────────────────────────────┘ │
|
|
1229
|
-
└─────────────────────────────────────────────────────────────┘
|
|
1230
|
-
```
|
|
1231
|
-
|
|
1232
|
-
---
|
|
1233
|
-
|
|
1234
|
-
**文档版本**: 1.0.0
|
|
1235
|
-
**最后更新**: 2026-03-19
|
|
1236
|
-
**审核状态**: 待审核
|