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.
Files changed (135) hide show
  1. package/README.md +55 -321
  2. package/frontend-dist/assets/index-B7XqKAxm.css +1 -0
  3. package/frontend-dist/assets/index-CxJaSYyo.js +24 -0
  4. package/{frontend → frontend-dist}/index.html +2 -1
  5. package/{plugin/openclaw.plugin.json → openclaw.plugin.json} +2 -2
  6. package/package.json +21 -13
  7. package/.github/workflows/release.yml +0 -56
  8. package/VERSION_DISPLAY_delivery.md +0 -242
  9. package/VERSION_DISPLAY_implementation_summary.md +0 -315
  10. package/design_manifest.md +0 -100
  11. package/docs/CHANGELOG_AGENT_MODIFICATIONS.md +0 -132
  12. package/docs/MAINTAINER_RELEASE_WORKFLOW.md +0 -211
  13. package/docs/Openclaw-Agent-Dashboard/345/217/221/345/270/203/344/270/216/346/233/264/346/226/260.md +0 -147
  14. package/docs/RELEASE-LATEST.md +0 -189
  15. package/docs/RELEASE-MODEL-CONFIG.md +0 -95
  16. package/docs/WINDOWS_INSTALL_TROUBLESHOOTING.md +0 -171
  17. package/docs/design/.gitkeep +0 -0
  18. package/docs/design/VERSION_DISPLAY_design.md +0 -1236
  19. package/docs/release-guide.md +0 -259
  20. package/docs/release-operations-manual.md +0 -167
  21. package/docs/reviews/.gitkeep +0 -0
  22. package/docs/reviews/approval_history.json +0 -14
  23. package/docs/reviews/cr_VERSION_DISPLAY.md +0 -397
  24. package/docs/reviews/traceability_manifest.json +0 -279
  25. package/docs/specs/VERSION_DISPLAY_spec.md +0 -371
  26. package/docs/specs/tr3-install-system.md +0 -580
  27. package/docs/windows-collaboration-model-paths-troubleshooting.md +0 -0
  28. package/frontend/package-lock.json +0 -1240
  29. package/frontend/package.json +0 -19
  30. package/frontend/src/App.vue +0 -355
  31. package/frontend/src/components/AgentCard.vue +0 -796
  32. package/frontend/src/components/AgentConfigPanel.vue +0 -539
  33. package/frontend/src/components/AgentDetailPanel.vue +0 -738
  34. package/frontend/src/components/ErrorAnalysisView.vue +0 -546
  35. package/frontend/src/components/ErrorCenterPanel.vue +0 -844
  36. package/frontend/src/components/PerformanceMonitor.vue +0 -515
  37. package/frontend/src/components/SettingsPanel.vue +0 -236
  38. package/frontend/src/components/TokenAnalysisPanel.vue +0 -683
  39. package/frontend/src/components/chain/ChainEdge.vue +0 -85
  40. package/frontend/src/components/chain/ChainNode.vue +0 -166
  41. package/frontend/src/components/chain/TaskChainView.vue +0 -425
  42. package/frontend/src/components/chain/index.ts +0 -3
  43. package/frontend/src/components/chain/types.ts +0 -70
  44. package/frontend/src/components/collaboration/CollaborationFlowSection.vue +0 -1032
  45. package/frontend/src/components/collaboration/CollaborationFlowWrapper.vue +0 -113
  46. package/frontend/src/components/common/VersionDisplay.vue +0 -187
  47. package/frontend/src/components/performance/PerformancePanel.vue +0 -119
  48. package/frontend/src/components/performance/PerformanceSection.vue +0 -1137
  49. package/frontend/src/components/tasks/TaskStatusSection.vue +0 -973
  50. package/frontend/src/components/timeline/TimelineConnector.vue +0 -31
  51. package/frontend/src/components/timeline/TimelineRound.vue +0 -135
  52. package/frontend/src/components/timeline/TimelineStep.vue +0 -691
  53. package/frontend/src/components/timeline/TimelineToolLink.vue +0 -109
  54. package/frontend/src/components/timeline/TimelineView.vue +0 -540
  55. package/frontend/src/components/timeline/index.ts +0 -5
  56. package/frontend/src/components/timeline/types.ts +0 -120
  57. package/frontend/src/composables/index.ts +0 -7
  58. package/frontend/src/composables/useDebounce.ts +0 -48
  59. package/frontend/src/composables/useRealtime.ts +0 -52
  60. package/frontend/src/composables/useState.ts +0 -52
  61. package/frontend/src/composables/useThrottle.ts +0 -46
  62. package/frontend/src/composables/useVirtualScroll.ts +0 -106
  63. package/frontend/src/main.ts +0 -4
  64. package/frontend/src/managers/EventDispatcher.ts +0 -127
  65. package/frontend/src/managers/RealtimeDataManager.ts +0 -302
  66. package/frontend/src/managers/StateManager.ts +0 -128
  67. package/frontend/src/managers/index.ts +0 -5
  68. package/frontend/src/types/collaboration.ts +0 -135
  69. package/frontend/src/types/index.ts +0 -20
  70. package/frontend/src/types/performance.ts +0 -105
  71. package/frontend/src/types/task.ts +0 -38
  72. package/frontend/vite.config.ts +0 -18
  73. package/legacy_code_anatomy.md +0 -518
  74. package/plugin/README.md +0 -99
  75. package/plugin/config.json.example +0 -1
  76. package/plugin/package.json +0 -26
  77. package/scripts/build-plugin.js +0 -81
  78. package/scripts/bundle.sh +0 -62
  79. package/scripts/install-plugin.sh +0 -162
  80. package/scripts/install-python-deps.sh +0 -226
  81. package/scripts/install.js +0 -684
  82. package/scripts/install.sh +0 -367
  83. package/scripts/lib/common.sh +0 -137
  84. package/scripts/release-pack.sh +0 -110
  85. package/scripts/start.js +0 -50
  86. package/scripts/test_available_models.py +0 -284
  87. package/scripts/test_version_display.sh +0 -128
  88. package/scripts/test_websocket_ping.py +0 -44
  89. package/session_registry.json +0 -58
  90. package/tests/.gitkeep +0 -0
  91. package/tests/qa_regression_report.md +0 -359
  92. package/tests/qa_version_display_report.md +0 -598
  93. /package/{src/backend → dashboard}/agents.py +0 -0
  94. /package/{src/backend → dashboard}/api/__init__.py +0 -0
  95. /package/{src/backend → dashboard}/api/agent_config_api.py +0 -0
  96. /package/{src/backend → dashboard}/api/agents.py +0 -0
  97. /package/{src/backend → dashboard}/api/agents_config.py +0 -0
  98. /package/{src/backend → dashboard}/api/chains.py +0 -0
  99. /package/{src/backend → dashboard}/api/collaboration.py +0 -0
  100. /package/{src/backend → dashboard}/api/debug_paths.py +0 -0
  101. /package/{src/backend → dashboard}/api/error_analysis.py +0 -0
  102. /package/{src/backend → dashboard}/api/errors.py +0 -0
  103. /package/{src/backend → dashboard}/api/performance.py +0 -0
  104. /package/{src/backend → dashboard}/api/subagents.py +0 -0
  105. /package/{src/backend → dashboard}/api/timeline.py +0 -0
  106. /package/{src/backend → dashboard}/api/version.py +0 -0
  107. /package/{src/backend → dashboard}/api/websocket.py +0 -0
  108. /package/{src/backend → dashboard}/collaboration.py +0 -0
  109. /package/{src/backend → dashboard}/data/__init__.py +0 -0
  110. /package/{src/backend → dashboard}/data/agent_config_manager.py +0 -0
  111. /package/{src/backend → dashboard}/data/chain_reader.py +0 -0
  112. /package/{src/backend → dashboard}/data/config_reader.py +0 -0
  113. /package/{src/backend → dashboard}/data/error_analyzer.py +0 -0
  114. /package/{src/backend → dashboard}/data/session_reader.py +0 -0
  115. /package/{src/backend → dashboard}/data/subagent_reader.py +0 -0
  116. /package/{src/backend → dashboard}/data/task_history.py +0 -0
  117. /package/{src/backend → dashboard}/data/timeline_reader.py +0 -0
  118. /package/{src/backend → dashboard}/data/version_info_reader.py +0 -0
  119. /package/{src/backend → dashboard}/errors.py +0 -0
  120. /package/{src/backend → dashboard}/main.py +0 -0
  121. /package/{src/backend → dashboard}/mechanism_reader.py +0 -0
  122. /package/{src/backend → dashboard}/mechanisms.py +0 -0
  123. /package/{src/backend → dashboard}/performance.py +0 -0
  124. /package/{src/backend → dashboard}/requirements.txt +0 -0
  125. /package/{src/backend → dashboard}/session_reader.py +0 -0
  126. /package/{src/backend → dashboard}/status/__init__.py +0 -0
  127. /package/{src/backend → dashboard}/status/change_tracker.py +0 -0
  128. /package/{src/backend → dashboard}/status/error_detector.py +0 -0
  129. /package/{src/backend → dashboard}/status/status_cache.py +0 -0
  130. /package/{src/backend → dashboard}/status/status_calculator.py +0 -0
  131. /package/{src/backend → dashboard}/status_calculator.py +0 -0
  132. /package/{src/backend → dashboard}/subagent_reader.py +0 -0
  133. /package/{src/backend → dashboard}/watchers/__init__.py +0 -0
  134. /package/{src/backend → dashboard}/watchers/file_watcher.py +0 -0
  135. /package/{plugin/index.js → index.js} +0 -0
@@ -1,539 +0,0 @@
1
- <template>
2
- <div class="agent-config-panel">
3
- <div class="header">
4
- <h3>⚙️ Agent 配置</h3>
5
- <button class="refresh-btn" @click="loadConfig" :disabled="loading">
6
- {{ loading ? '加载中...' : '刷新' }}
7
- </button>
8
- </div>
9
-
10
- <div v-if="loading && !config" class="loading-state">
11
- 加载配置...
12
- </div>
13
-
14
- <div v-else-if="error" class="error-state">
15
- {{ error }}
16
- </div>
17
-
18
- <div v-else-if="config" class="config-content">
19
- <!-- 基本信息 -->
20
- <div class="config-section">
21
- <h4>基本信息</h4>
22
- <div class="info-grid">
23
- <div class="info-item">
24
- <span class="label">ID</span>
25
- <span class="value monospace">{{ config.id }}</span>
26
- </div>
27
- <div class="info-item">
28
- <span class="label">名称</span>
29
- <span class="value">{{ config.name }}</span>
30
- </div>
31
- <div class="info-item full-width">
32
- <span class="label">工作区</span>
33
- <span class="value monospace">{{ config.workspace || '未设置' }}</span>
34
- </div>
35
- <div class="info-item">
36
- <span class="label">状态</span>
37
- <span class="value" :class="`status-${config.status}`">
38
- {{ statusLabel(config.status) }}
39
- </span>
40
- </div>
41
- </div>
42
- </div>
43
-
44
- <!-- 模型配置 -->
45
- <div class="config-section">
46
- <h4>模型配置</h4>
47
-
48
- <div class="model-config">
49
- <div class="model-field">
50
- <label>主模型 (Primary)</label>
51
- <div class="model-select-wrapper">
52
- <select v-model="selectedPrimary" :disabled="saving" class="model-select">
53
- <option value="">-- 选择模型 --</option>
54
- <optgroup v-for="group in modelGroups" :key="group.provider" :label="group.provider">
55
- <option v-for="model in group.models" :key="model.id" :value="model.id">
56
- {{ model.name }}
57
- </option>
58
- </optgroup>
59
- </select>
60
- <span v-if="config.model?.primary" class="current-model">
61
- 当前: {{ formatModelId(config.model.primary) }}
62
- </span>
63
- </div>
64
- </div>
65
-
66
- <div class="model-field">
67
- <label>备选模型 (Fallbacks)</label>
68
- <div class="fallbacks-list">
69
- <div v-for="(fb, idx) in selectedFallbacks" :key="idx" class="fallback-item">
70
- <select v-model="selectedFallbacks[idx]" :disabled="saving" class="model-select small">
71
- <option value="">-- 选择 --</option>
72
- <optgroup v-for="group in modelGroups" :key="group.provider" :label="group.provider">
73
- <option v-for="model in group.models" :key="model.id" :value="model.id">
74
- {{ model.name }}
75
- </option>
76
- </optgroup>
77
- </select>
78
- <button class="remove-btn" @click="removeFallback(idx)" :disabled="saving">×</button>
79
- </div>
80
- <button class="add-fallback-btn" @click="addFallback" :disabled="saving || selectedFallbacks.length >= 3">
81
- + 添加备选模型
82
- </button>
83
- </div>
84
- </div>
85
-
86
- <div class="model-actions">
87
- <button
88
- class="save-btn"
89
- @click="saveModelConfig"
90
- :disabled="saving || !hasModelChanges"
91
- >
92
- {{ saving ? '保存中...' : '保存修改' }}
93
- </button>
94
- <button class="reset-btn" @click="resetModelSelection" :disabled="saving">
95
- 重置
96
- </button>
97
- </div>
98
- </div>
99
- </div>
100
-
101
- <!-- 描述 -->
102
- <div v-if="config.description" class="config-section">
103
- <h4>描述</h4>
104
- <p class="description-text">{{ config.description }}</p>
105
- </div>
106
- </div>
107
- </div>
108
- </template>
109
-
110
- <script setup lang="ts">
111
- import { ref, computed, onMounted, watch } from 'vue'
112
-
113
- interface Model {
114
- id: string
115
- name: string
116
- provider: string
117
- contextWindow?: number
118
- maxTokens?: number
119
- reasoning?: boolean
120
- }
121
-
122
- interface ModelGroup {
123
- provider: string
124
- models: Model[]
125
- }
126
-
127
- interface AgentConfig {
128
- id: string
129
- name: string
130
- workspace?: string
131
- status: string
132
- model?: {
133
- primary: string
134
- fallbacks: string[]
135
- }
136
- description?: string
137
- systemPrompt?: string
138
- lastActiveAt?: number
139
- }
140
-
141
- const props = defineProps<{
142
- agentId: string
143
- }>()
144
-
145
- const config = ref<AgentConfig | null>(null)
146
- const availableModels = ref<Model[]>([])
147
- const loading = ref(false)
148
- const saving = ref(false)
149
- const error = ref('')
150
-
151
- const selectedPrimary = ref('')
152
- const selectedFallbacks = ref<string[]>([])
153
-
154
- const modelGroups = computed<ModelGroup[]>(() => {
155
- const groups: Record<string, Model[]> = {}
156
- for (const model of availableModels.value) {
157
- if (!groups[model.provider]) {
158
- groups[model.provider] = []
159
- }
160
- groups[model.provider].push(model)
161
- }
162
- return Object.entries(groups).map(([provider, models]) => ({ provider, models }))
163
- })
164
-
165
- const hasModelChanges = computed(() => {
166
- if (!config.value?.model) return false
167
- const original = config.value.model
168
- return selectedPrimary.value !== original.primary ||
169
- JSON.stringify(selectedFallbacks.value.filter(f => f)) !== JSON.stringify(original.fallbacks || [])
170
- })
171
-
172
- function statusLabel(status: string): string {
173
- const map: Record<string, string> = {
174
- idle: '空闲',
175
- working: '工作中',
176
- down: '异常',
177
- }
178
- return map[status] || status
179
- }
180
-
181
- function formatModelId(modelId: string): string {
182
- if (!modelId) return ''
183
- const parts = modelId.split('/')
184
- return parts.length > 1 ? parts[parts.length - 1] : modelId
185
- }
186
-
187
- async function loadConfig() {
188
- loading.value = true
189
- error.value = ''
190
- try {
191
- const [configRes, modelsRes] = await Promise.all([
192
- fetch(`/api/agent-config/${props.agentId}`),
193
- fetch('/api/available-models'),
194
- ])
195
-
196
- if (configRes.ok) {
197
- config.value = await configRes.json()
198
- // 初始化选择
199
- if (config.value?.model) {
200
- selectedPrimary.value = config.value.model.primary || ''
201
- selectedFallbacks.value = [...(config.value.model.fallbacks || [])]
202
- }
203
- } else {
204
- error.value = '加载配置失败'
205
- }
206
-
207
- if (modelsRes.ok) {
208
- const data = await modelsRes.json()
209
- availableModels.value = data.models || []
210
- }
211
- } catch (e) {
212
- error.value = '加载失败: ' + (e as Error).message
213
- } finally {
214
- loading.value = false
215
- }
216
- }
217
-
218
- function addFallback() {
219
- if (selectedFallbacks.value.length < 3) {
220
- selectedFallbacks.value.push('')
221
- }
222
- }
223
-
224
- function removeFallback(idx: number) {
225
- selectedFallbacks.value.splice(idx, 1)
226
- }
227
-
228
- function resetModelSelection() {
229
- if (config.value?.model) {
230
- selectedPrimary.value = config.value.model.primary || ''
231
- selectedFallbacks.value = [...(config.value.model.fallbacks || [])]
232
- }
233
- }
234
-
235
- async function saveModelConfig() {
236
- if (!hasModelChanges.value) return
237
-
238
- saving.value = true
239
- try {
240
- const res = await fetch(`/api/agent-config/${props.agentId}/model`, {
241
- method: 'PUT',
242
- headers: { 'Content-Type': 'application/json' },
243
- body: JSON.stringify({
244
- primary: selectedPrimary.value || null,
245
- fallbacks: selectedFallbacks.value.filter(f => f) || null,
246
- }),
247
- })
248
-
249
- if (res.ok) {
250
- const data = await res.json()
251
- if (config.value && data.model) {
252
- config.value.model = data.model
253
- }
254
- alert('模型配置已保存!重启 Agent 后生效。')
255
- } else {
256
- const errData = await res.json()
257
- alert('保存失败: ' + (errData.detail || '未知错误'))
258
- }
259
- } catch (e) {
260
- alert('保存失败: ' + (e as Error).message)
261
- } finally {
262
- saving.value = false
263
- }
264
- }
265
-
266
- watch(() => props.agentId, () => {
267
- loadConfig()
268
- }, { immediate: true })
269
-
270
- onMounted(() => {
271
- loadConfig()
272
- })
273
- </script>
274
-
275
- <style scoped>
276
- .agent-config-panel {
277
- padding: 12px;
278
- max-height: 500px;
279
- overflow-y: auto;
280
- }
281
-
282
- .header {
283
- display: flex;
284
- justify-content: space-between;
285
- align-items: center;
286
- margin-bottom: 16px;
287
- }
288
-
289
- .header h3 {
290
- margin: 0;
291
- font-size: 14px;
292
- color: #374151;
293
- }
294
-
295
- .refresh-btn {
296
- padding: 4px 12px;
297
- font-size: 12px;
298
- border: 1px solid #d1d5db;
299
- border-radius: 4px;
300
- background: #fff;
301
- cursor: pointer;
302
- }
303
-
304
- .refresh-btn:hover:not(:disabled) {
305
- background: #f3f4f6;
306
- }
307
-
308
- .refresh-btn:disabled {
309
- opacity: 0.5;
310
- cursor: not-allowed;
311
- }
312
-
313
- .loading-state,
314
- .error-state {
315
- text-align: center;
316
- padding: 40px 20px;
317
- color: #6b7280;
318
- }
319
-
320
- .error-state {
321
- color: #dc2626;
322
- }
323
-
324
- .config-section {
325
- margin-bottom: 16px;
326
- padding-bottom: 16px;
327
- border-bottom: 1px solid #e5e7eb;
328
- }
329
-
330
- .config-section:last-child {
331
- border-bottom: none;
332
- margin-bottom: 0;
333
- }
334
-
335
- .config-section h4 {
336
- margin: 0 0 12px 0;
337
- font-size: 13px;
338
- color: #374151;
339
- font-weight: 600;
340
- }
341
-
342
- .info-grid {
343
- display: grid;
344
- grid-template-columns: 1fr 1fr;
345
- gap: 8px;
346
- }
347
-
348
- .info-item {
349
- display: flex;
350
- flex-direction: column;
351
- gap: 2px;
352
- }
353
-
354
- .info-item.full-width {
355
- grid-column: 1 / -1;
356
- }
357
-
358
- .info-item .label {
359
- font-size: 11px;
360
- color: #6b7280;
361
- }
362
-
363
- .info-item .value {
364
- font-size: 13px;
365
- color: #1f2937;
366
- }
367
-
368
- .info-item .value.monospace {
369
- font-family: monospace;
370
- font-size: 12px;
371
- word-break: break-all;
372
- }
373
-
374
- .info-item .value.status-idle {
375
- color: #22c55e;
376
- }
377
-
378
- .info-item .value.status-working {
379
- color: #f59e0b;
380
- }
381
-
382
- .info-item .value.status-down {
383
- color: #ef4444;
384
- }
385
-
386
- .model-config {
387
- display: flex;
388
- flex-direction: column;
389
- gap: 16px;
390
- }
391
-
392
- .model-field label {
393
- display: block;
394
- font-size: 12px;
395
- color: #374151;
396
- margin-bottom: 6px;
397
- font-weight: 500;
398
- }
399
-
400
- .model-select-wrapper {
401
- display: flex;
402
- flex-direction: column;
403
- gap: 4px;
404
- }
405
-
406
- .model-select {
407
- width: 100%;
408
- padding: 8px 10px;
409
- font-size: 13px;
410
- border: 1px solid #d1d5db;
411
- border-radius: 6px;
412
- background: #fff;
413
- cursor: pointer;
414
- }
415
-
416
- .model-select:focus {
417
- outline: none;
418
- border-color: #3b82f6;
419
- }
420
-
421
- .model-select:disabled {
422
- background: #f3f4f6;
423
- cursor: not-allowed;
424
- }
425
-
426
- .model-select.small {
427
- padding: 6px 8px;
428
- font-size: 12px;
429
- }
430
-
431
- .current-model {
432
- font-size: 11px;
433
- color: #6b7280;
434
- }
435
-
436
- .fallbacks-list {
437
- display: flex;
438
- flex-direction: column;
439
- gap: 8px;
440
- }
441
-
442
- .fallback-item {
443
- display: flex;
444
- gap: 8px;
445
- align-items: center;
446
- }
447
-
448
- .fallback-item .model-select {
449
- flex: 1;
450
- }
451
-
452
- .remove-btn {
453
- width: 28px;
454
- height: 28px;
455
- border: 1px solid #d1d5db;
456
- border-radius: 4px;
457
- background: #fff;
458
- cursor: pointer;
459
- font-size: 16px;
460
- color: #6b7280;
461
- display: flex;
462
- align-items: center;
463
- justify-content: center;
464
- }
465
-
466
- .remove-btn:hover:not(:disabled) {
467
- background: #fee2e2;
468
- border-color: #fca5a5;
469
- color: #dc2626;
470
- }
471
-
472
- .add-fallback-btn {
473
- padding: 6px 12px;
474
- font-size: 12px;
475
- border: 1px dashed #d1d5db;
476
- border-radius: 4px;
477
- background: #f9fafb;
478
- cursor: pointer;
479
- color: #6b7280;
480
- }
481
-
482
- .add-fallback-btn:hover:not(:disabled) {
483
- border-color: #3b82f6;
484
- color: #3b82f6;
485
- }
486
-
487
- .add-fallback-btn:disabled {
488
- opacity: 0.5;
489
- cursor: not-allowed;
490
- }
491
-
492
- .model-actions {
493
- display: flex;
494
- gap: 8px;
495
- margin-top: 8px;
496
- }
497
-
498
- .save-btn {
499
- padding: 8px 16px;
500
- font-size: 13px;
501
- border: none;
502
- border-radius: 6px;
503
- background: #3b82f6;
504
- color: #fff;
505
- cursor: pointer;
506
- font-weight: 500;
507
- }
508
-
509
- .save-btn:hover:not(:disabled) {
510
- background: #2563eb;
511
- }
512
-
513
- .save-btn:disabled {
514
- opacity: 0.5;
515
- cursor: not-allowed;
516
- }
517
-
518
- .reset-btn {
519
- padding: 8px 16px;
520
- font-size: 13px;
521
- border: 1px solid #d1d5db;
522
- border-radius: 6px;
523
- background: #fff;
524
- cursor: pointer;
525
- color: #6b7280;
526
- }
527
-
528
- .reset-btn:hover:not(:disabled) {
529
- background: #f3f4f6;
530
- }
531
-
532
- .description-text {
533
- margin: 0;
534
- font-size: 13px;
535
- color: #4b5563;
536
- line-height: 1.5;
537
- white-space: pre-wrap;
538
- }
539
- </style>