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,302 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 实时数据管理器
|
|
3
|
-
* 负责 WebSocket 连接管理和 HTTP 轮询回退
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { ConnectionState, WebSocketMessage } from '../types'
|
|
7
|
-
|
|
8
|
-
type EventCallback = (data: unknown) => void
|
|
9
|
-
|
|
10
|
-
export interface RealtimeDataManagerOptions {
|
|
11
|
-
wsUrl?: string
|
|
12
|
-
httpFallback?: boolean
|
|
13
|
-
reconnectMaxAttempts?: number
|
|
14
|
-
reconnectDelay?: number
|
|
15
|
-
pollingInterval?: number
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export class RealtimeDataManager {
|
|
19
|
-
private ws: WebSocket | null = null
|
|
20
|
-
private connectionState: ConnectionState = {
|
|
21
|
-
status: 'disconnected',
|
|
22
|
-
reconnectAttempts: 0
|
|
23
|
-
}
|
|
24
|
-
private subscribers: Map<string, Set<EventCallback>> = new Map()
|
|
25
|
-
private options: Required<RealtimeDataManagerOptions>
|
|
26
|
-
private reconnectTimer: ReturnType<typeof setTimeout> | null = null
|
|
27
|
-
private pollingTimer: ReturnType<typeof setInterval> | null = null
|
|
28
|
-
private heartbeatTimer: ReturnType<typeof setInterval> | null = null
|
|
29
|
-
private stateListeners: Set<(state: ConnectionState) => void> = new Set()
|
|
30
|
-
|
|
31
|
-
constructor(options: RealtimeDataManagerOptions = {}) {
|
|
32
|
-
this.options = {
|
|
33
|
-
wsUrl: options.wsUrl || `ws://${window.location.host}/ws`,
|
|
34
|
-
httpFallback: options.httpFallback ?? true,
|
|
35
|
-
reconnectMaxAttempts: options.reconnectMaxAttempts ?? 5,
|
|
36
|
-
reconnectDelay: options.reconnectDelay ?? 3000,
|
|
37
|
-
pollingInterval: options.pollingInterval ?? 10000
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* 建立 WebSocket 连接
|
|
43
|
-
*/
|
|
44
|
-
connect(): void {
|
|
45
|
-
if (this.ws?.readyState === WebSocket.OPEN) {
|
|
46
|
-
return
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
this.updateConnectionState({ status: 'connecting', reconnectAttempts: this.connectionState.reconnectAttempts })
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
this.ws = new WebSocket(this.options.wsUrl)
|
|
53
|
-
|
|
54
|
-
this.ws.onopen = () => {
|
|
55
|
-
this.updateConnectionState({
|
|
56
|
-
status: 'connected',
|
|
57
|
-
lastConnected: Date.now(),
|
|
58
|
-
reconnectAttempts: 0
|
|
59
|
-
})
|
|
60
|
-
this.startHeartbeat()
|
|
61
|
-
this.stopPolling()
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
this.ws.onclose = () => {
|
|
65
|
-
this.stopHeartbeat()
|
|
66
|
-
this.handleDisconnect()
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
this.ws.onerror = (error) => {
|
|
70
|
-
console.error('WebSocket error:', error)
|
|
71
|
-
this.updateConnectionState({
|
|
72
|
-
status: 'error',
|
|
73
|
-
errorMessage: 'WebSocket connection failed'
|
|
74
|
-
})
|
|
75
|
-
// 连接失败时触发重连或 HTTP 轮询回退
|
|
76
|
-
this.handleDisconnect()
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
this.ws.onmessage = (event) => {
|
|
80
|
-
try {
|
|
81
|
-
const message: WebSocketMessage = JSON.parse(event.data)
|
|
82
|
-
this.handleMessage(message)
|
|
83
|
-
} catch (e) {
|
|
84
|
-
console.error('Failed to parse WebSocket message:', e)
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
} catch (error) {
|
|
88
|
-
console.error('Failed to create WebSocket:', error)
|
|
89
|
-
this.handleDisconnect()
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* 断开连接
|
|
95
|
-
*/
|
|
96
|
-
disconnect(): void {
|
|
97
|
-
this.stopHeartbeat()
|
|
98
|
-
this.stopReconnect()
|
|
99
|
-
this.stopPolling()
|
|
100
|
-
|
|
101
|
-
if (this.ws) {
|
|
102
|
-
this.ws.close()
|
|
103
|
-
this.ws = null
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
this.updateConnectionState({ status: 'disconnected', reconnectAttempts: 0 })
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* 获取连接状态
|
|
111
|
-
*/
|
|
112
|
-
getConnectionState(): ConnectionState {
|
|
113
|
-
return { ...this.connectionState }
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* 订阅事件
|
|
118
|
-
*/
|
|
119
|
-
subscribe(event: string, callback: EventCallback): () => void {
|
|
120
|
-
if (!this.subscribers.has(event)) {
|
|
121
|
-
this.subscribers.set(event, new Set())
|
|
122
|
-
}
|
|
123
|
-
this.subscribers.get(event)!.add(callback)
|
|
124
|
-
|
|
125
|
-
// 返回取消订阅函数
|
|
126
|
-
return () => {
|
|
127
|
-
this.subscribers.get(event)?.delete(callback)
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* 监听连接状态变化
|
|
133
|
-
*/
|
|
134
|
-
onStateChange(callback: (state: ConnectionState) => void): () => void {
|
|
135
|
-
this.stateListeners.add(callback)
|
|
136
|
-
return () => {
|
|
137
|
-
this.stateListeners.delete(callback)
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* 是否已连接
|
|
143
|
-
*/
|
|
144
|
-
isConnected(): boolean {
|
|
145
|
-
return this.connectionState.status === 'connected'
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* 获取初始数据
|
|
150
|
-
*/
|
|
151
|
-
async fetchInitialData(): Promise<void> {
|
|
152
|
-
try {
|
|
153
|
-
const [collaboration, tasks, performance, agents] = await Promise.all([
|
|
154
|
-
fetch('/api/collaboration').then(r => r.json()).catch(() => null),
|
|
155
|
-
fetch('/api/tasks').then(r => r.json()).catch(() => null),
|
|
156
|
-
fetch('/api/performance?range=20m').then(r => r.json()).catch(() => null),
|
|
157
|
-
fetch('/api/agents').then(r => r.json()).catch(() => null)
|
|
158
|
-
])
|
|
159
|
-
|
|
160
|
-
if (collaboration) this.emit('collaboration', collaboration)
|
|
161
|
-
if (tasks) this.emit('tasks', tasks)
|
|
162
|
-
if (performance) this.emit('performance', performance)
|
|
163
|
-
if (agents) this.emit('agents', agents)
|
|
164
|
-
} catch (error) {
|
|
165
|
-
console.error('Failed to fetch initial data:', error)
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
private handleMessage(message: WebSocketMessage): void {
|
|
170
|
-
if (message.type === 'ping') {
|
|
171
|
-
this.send({ type: 'pong', timestamp: Date.now() })
|
|
172
|
-
return
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
if (message.type === 'full_state' && message.data) {
|
|
176
|
-
const data = message.data as Record<string, unknown>
|
|
177
|
-
if (data.agents) this.emit('agents', data.agents)
|
|
178
|
-
if (data.subagents) this.emit('subagents', data.subagents)
|
|
179
|
-
if (data.collaboration) this.emit('collaboration', data.collaboration)
|
|
180
|
-
// 统一为 { tasks: array },与 HTTP 轮询和组件 handleTasksUpdate 约定一致,避免形态不一致导致不更新或误覆盖
|
|
181
|
-
const tasksArray = Array.isArray(data.tasks) ? data.tasks : []
|
|
182
|
-
this.emit('tasks', { tasks: tasksArray })
|
|
183
|
-
if (data.performance) this.emit('performance', data.performance)
|
|
184
|
-
return
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// 新增:增量状态更新
|
|
188
|
-
if (message.type === 'state_update' && message.data) {
|
|
189
|
-
const data = message.data as Record<string, unknown>
|
|
190
|
-
if (data.agents) {
|
|
191
|
-
this.emit('agents_update', data.agents) // 新增事件
|
|
192
|
-
}
|
|
193
|
-
return
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
if (message.channel && message.data) {
|
|
197
|
-
this.emit(message.channel, message.data)
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
private emit(event: string, data: unknown): void {
|
|
202
|
-
const callbacks = this.subscribers.get(event)
|
|
203
|
-
if (callbacks) {
|
|
204
|
-
callbacks.forEach(cb => {
|
|
205
|
-
try {
|
|
206
|
-
cb(data)
|
|
207
|
-
} catch (e) {
|
|
208
|
-
console.error(`Error in subscriber callback for ${event}:`, e)
|
|
209
|
-
}
|
|
210
|
-
})
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
private send(message: unknown): void {
|
|
215
|
-
if (this.ws?.readyState === WebSocket.OPEN) {
|
|
216
|
-
this.ws.send(JSON.stringify(message))
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
private handleDisconnect(): void {
|
|
221
|
-
if (this.connectionState.reconnectAttempts < this.options.reconnectMaxAttempts) {
|
|
222
|
-
this.scheduleReconnect()
|
|
223
|
-
} else if (this.options.httpFallback) {
|
|
224
|
-
this.startPolling()
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
private scheduleReconnect(): void {
|
|
229
|
-
this.stopReconnect()
|
|
230
|
-
|
|
231
|
-
const delay = this.options.reconnectDelay * Math.pow(1.5, this.connectionState.reconnectAttempts)
|
|
232
|
-
|
|
233
|
-
this.reconnectTimer = setTimeout(() => {
|
|
234
|
-
this.updateConnectionState({
|
|
235
|
-
status: 'connecting',
|
|
236
|
-
reconnectAttempts: this.connectionState.reconnectAttempts + 1
|
|
237
|
-
})
|
|
238
|
-
this.connect()
|
|
239
|
-
}, delay)
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
private stopReconnect(): void {
|
|
243
|
-
if (this.reconnectTimer) {
|
|
244
|
-
clearTimeout(this.reconnectTimer)
|
|
245
|
-
this.reconnectTimer = null
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
private startHeartbeat(): void {
|
|
250
|
-
this.stopHeartbeat()
|
|
251
|
-
this.heartbeatTimer = setInterval(() => {
|
|
252
|
-
this.send({ type: 'ping', timestamp: Date.now() })
|
|
253
|
-
}, 30000)
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
private stopHeartbeat(): void {
|
|
257
|
-
if (this.heartbeatTimer) {
|
|
258
|
-
clearInterval(this.heartbeatTimer)
|
|
259
|
-
this.heartbeatTimer = null
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
private startPolling(): void {
|
|
264
|
-
this.stopPolling()
|
|
265
|
-
this.updateConnectionState({
|
|
266
|
-
status: 'connected',
|
|
267
|
-
errorMessage: 'Using HTTP polling fallback'
|
|
268
|
-
})
|
|
269
|
-
this.fetchInitialData()
|
|
270
|
-
this.pollingTimer = setInterval(() => {
|
|
271
|
-
this.fetchInitialData()
|
|
272
|
-
}, this.options.pollingInterval)
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
private stopPolling(): void {
|
|
276
|
-
if (this.pollingTimer) {
|
|
277
|
-
clearInterval(this.pollingTimer)
|
|
278
|
-
this.pollingTimer = null
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
private updateConnectionState(updates: Partial<ConnectionState>): void {
|
|
283
|
-
this.connectionState = { ...this.connectionState, ...updates }
|
|
284
|
-
this.stateListeners.forEach(listener => {
|
|
285
|
-
try {
|
|
286
|
-
listener(this.connectionState)
|
|
287
|
-
} catch (e) {
|
|
288
|
-
console.error('Error in state listener:', e)
|
|
289
|
-
}
|
|
290
|
-
})
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
// 单例实例
|
|
295
|
-
let instance: RealtimeDataManager | null = null
|
|
296
|
-
|
|
297
|
-
export function getRealtimeManager(options?: RealtimeDataManagerOptions): RealtimeDataManager {
|
|
298
|
-
if (!instance) {
|
|
299
|
-
instance = new RealtimeDataManager(options)
|
|
300
|
-
}
|
|
301
|
-
return instance
|
|
302
|
-
}
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 状态管理器
|
|
3
|
-
* 负责集中状态管理和数据缓存
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { ref, type Ref } from 'vue'
|
|
7
|
-
|
|
8
|
-
interface CacheEntry<T> {
|
|
9
|
-
value: T
|
|
10
|
-
expiresAt: number
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
type StateKey = string
|
|
14
|
-
|
|
15
|
-
export class StateManager {
|
|
16
|
-
private state: Map<StateKey, Ref<unknown>> = new Map()
|
|
17
|
-
private cache: Map<StateKey, CacheEntry<unknown>> = new Map()
|
|
18
|
-
private defaultTTL = 5000 // 默认缓存 5 秒
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* 获取状态值
|
|
22
|
-
*/
|
|
23
|
-
getState<T>(key: StateKey): T | undefined {
|
|
24
|
-
const stateRef = this.state.get(key)
|
|
25
|
-
return stateRef?.value as T | undefined
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* 设置状态值
|
|
30
|
-
*/
|
|
31
|
-
setState<T>(key: StateKey, value: T): void {
|
|
32
|
-
const existing = this.state.get(key)
|
|
33
|
-
if (existing) {
|
|
34
|
-
existing.value = value
|
|
35
|
-
} else {
|
|
36
|
-
this.state.set(key, ref(value))
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* 获取响应式状态引用
|
|
42
|
-
*/
|
|
43
|
-
useStore<T>(key: StateKey, defaultValue: T): Ref<T> {
|
|
44
|
-
const existing = this.state.get(key)
|
|
45
|
-
if (existing) {
|
|
46
|
-
return existing as Ref<T>
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const newRef = ref<T>(defaultValue) as Ref<T>
|
|
50
|
-
this.state.set(key, newRef)
|
|
51
|
-
return newRef
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* 获取缓存数据
|
|
56
|
-
*/
|
|
57
|
-
getCache<T>(key: StateKey): T | undefined {
|
|
58
|
-
const entry = this.cache.get(key)
|
|
59
|
-
if (!entry) return undefined
|
|
60
|
-
|
|
61
|
-
if (Date.now() > entry.expiresAt) {
|
|
62
|
-
this.cache.delete(key)
|
|
63
|
-
return undefined
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return entry.value as T
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* 设置缓存数据
|
|
71
|
-
*/
|
|
72
|
-
setCache<T>(key: StateKey, value: T, ttl?: number): void {
|
|
73
|
-
this.cache.set(key, {
|
|
74
|
-
value,
|
|
75
|
-
expiresAt: Date.now() + (ttl ?? this.defaultTTL)
|
|
76
|
-
})
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* 检查缓存是否有效
|
|
81
|
-
*/
|
|
82
|
-
hasValidCache(key: StateKey): boolean {
|
|
83
|
-
const entry = this.cache.get(key)
|
|
84
|
-
if (!entry) return false
|
|
85
|
-
return Date.now() <= entry.expiresAt
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* 使缓存失效
|
|
90
|
-
*/
|
|
91
|
-
invalidateCache(key: StateKey): void {
|
|
92
|
-
this.cache.delete(key)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* 批量更新状态
|
|
97
|
-
*/
|
|
98
|
-
batchUpdate(updates: Record<StateKey, unknown>): void {
|
|
99
|
-
Object.entries(updates).forEach(([key, value]) => {
|
|
100
|
-
this.setState(key, value)
|
|
101
|
-
})
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* 清除所有状态
|
|
106
|
-
*/
|
|
107
|
-
clearAll(): void {
|
|
108
|
-
this.state.clear()
|
|
109
|
-
this.cache.clear()
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* 清除所有缓存
|
|
114
|
-
*/
|
|
115
|
-
clearCache(): void {
|
|
116
|
-
this.cache.clear()
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// 单例实例
|
|
121
|
-
let instance: StateManager | null = null
|
|
122
|
-
|
|
123
|
-
export function getStateManager(): StateManager {
|
|
124
|
-
if (!instance) {
|
|
125
|
-
instance = new StateManager()
|
|
126
|
-
}
|
|
127
|
-
return instance
|
|
128
|
-
}
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
// 协作流程类型定义
|
|
2
|
-
|
|
3
|
-
export type NodeStatus = 'idle' | 'working' | 'active' | 'completed' | 'error'
|
|
4
|
-
export type NodeType = 'agent' | 'task' | 'tool' | 'model'
|
|
5
|
-
|
|
6
|
-
export interface AgentError {
|
|
7
|
-
hasError: boolean
|
|
8
|
-
type: string // rate-limit, token-limit, timeout, quota, unknown
|
|
9
|
-
message: string
|
|
10
|
-
timestamp: number
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface StuckWarning {
|
|
14
|
-
isStuck: boolean
|
|
15
|
-
idleSeconds: number
|
|
16
|
-
lastUpdate: number
|
|
17
|
-
// 卡顿原因分析
|
|
18
|
-
reason?: 'waiting_for_child' | 'self_busy' | 'unknown'
|
|
19
|
-
reasonDetail?: string
|
|
20
|
-
waitingFor?: {
|
|
21
|
-
agentId: string
|
|
22
|
-
task?: string
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export type SubStatus = 'thinking' | 'tool_executing' | 'waiting_llm' | 'waiting_child'
|
|
27
|
-
|
|
28
|
-
export interface CollaborationNode {
|
|
29
|
-
id: string
|
|
30
|
-
type: NodeType
|
|
31
|
-
name: string
|
|
32
|
-
status: NodeStatus
|
|
33
|
-
timestamp?: number
|
|
34
|
-
position?: { x: number; y: number }
|
|
35
|
-
metadata?: Record<string, unknown>
|
|
36
|
-
// 当前任务(有效描述)
|
|
37
|
-
currentTask?: string
|
|
38
|
-
// 错误信息
|
|
39
|
-
error?: AgentError
|
|
40
|
-
// 卡顿警告
|
|
41
|
-
stuckWarning?: StuckWarning
|
|
42
|
-
// 详细状态 (TR5)
|
|
43
|
-
subStatus?: SubStatus
|
|
44
|
-
currentAction?: string
|
|
45
|
-
toolName?: string
|
|
46
|
-
waitingFor?: string
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export type EdgeType = 'delegates' | 'calls' | 'returns' | 'error' | 'model'
|
|
50
|
-
|
|
51
|
-
export interface CollaborationEdge {
|
|
52
|
-
id: string
|
|
53
|
-
source: string
|
|
54
|
-
target: string
|
|
55
|
-
type: EdgeType
|
|
56
|
-
label?: string
|
|
57
|
-
animated?: boolean
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export interface ModelCall {
|
|
61
|
-
id: string
|
|
62
|
-
agentId: string
|
|
63
|
-
model: string
|
|
64
|
-
sessionId: string
|
|
65
|
-
trigger: string
|
|
66
|
-
tokens: number
|
|
67
|
-
timestamp: number
|
|
68
|
-
time: string
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export interface CollaborationFlow {
|
|
72
|
-
nodes: CollaborationNode[]
|
|
73
|
-
edges: CollaborationEdge[]
|
|
74
|
-
activePath: string[]
|
|
75
|
-
lastUpdate: number
|
|
76
|
-
mainAgentId?: string
|
|
77
|
-
agentModels?: Record<string, { primary?: string; fallbacks?: string[] }>
|
|
78
|
-
models?: string[]
|
|
79
|
-
recentCalls?: ModelCall[]
|
|
80
|
-
// 拓扑信息(用于嵌套组网布局)
|
|
81
|
-
hierarchy?: Record<string, string[]> // agentId -> [子 agent IDs]
|
|
82
|
-
depths?: Record<string, number> // agentId -> 层级深度
|
|
83
|
-
// 多任务并行数据(按 agent 分组)
|
|
84
|
-
agentActiveTasks?: Record<string, ActiveTask[]>
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export interface AgentDynamicStatus {
|
|
88
|
-
status: string // 'idle' | 'working'
|
|
89
|
-
subStatus?: SubStatus
|
|
90
|
-
currentAction?: string
|
|
91
|
-
toolName?: string
|
|
92
|
-
waitingFor?: string
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export interface AgentDisplayStatus {
|
|
96
|
-
/** 状态:idle 或 working */
|
|
97
|
-
status: 'idle' | 'working'
|
|
98
|
-
/** 显示文本,如 "等待响应"、"执行命令"、"处理中..." */
|
|
99
|
-
display: string
|
|
100
|
-
/** 持续时间(秒) */
|
|
101
|
-
duration: number
|
|
102
|
-
/** 是否需要警告(如等待时间过长) */
|
|
103
|
-
alert: boolean
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/** 单个活跃任务(用于多任务并行展示) */
|
|
107
|
-
export interface ActiveTask {
|
|
108
|
-
/** 任务ID */
|
|
109
|
-
id: string
|
|
110
|
-
/** 任务名称(清理后) */
|
|
111
|
-
name: string
|
|
112
|
-
/** 状态:working | retrying | failed */
|
|
113
|
-
status: 'working' | 'retrying' | 'failed'
|
|
114
|
-
/** 开始时间戳 */
|
|
115
|
-
timestamp?: number
|
|
116
|
-
/** 主 Agent 任务时,指向被派发的子 Agent */
|
|
117
|
-
childAgentId?: string
|
|
118
|
-
/** FEATURE_ID(如果有) */
|
|
119
|
-
featureId?: string
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export interface CollaborationDynamic {
|
|
123
|
-
activePath: string[]
|
|
124
|
-
recentCalls: ModelCall[]
|
|
125
|
-
agentStatuses: Record<string, string>
|
|
126
|
-
agentDynamicStatuses?: Record<string, AgentDynamicStatus>
|
|
127
|
-
/** 详细显示状态(TR9-1:基于时间阈值) */
|
|
128
|
-
agentDisplayStatuses?: Record<string, AgentDisplayStatus>
|
|
129
|
-
taskNodes: CollaborationNode[]
|
|
130
|
-
taskEdges: CollaborationEdge[]
|
|
131
|
-
mainAgentId: string
|
|
132
|
-
lastUpdate: number
|
|
133
|
-
/** 多任务并行数据(按 agent 分组) */
|
|
134
|
-
agentActiveTasks?: Record<string, ActiveTask[]>
|
|
135
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
// 类型定义入口文件
|
|
2
|
-
|
|
3
|
-
export * from './collaboration'
|
|
4
|
-
export * from './task'
|
|
5
|
-
export * from './performance'
|
|
6
|
-
|
|
7
|
-
// 通用类型
|
|
8
|
-
export interface ConnectionState {
|
|
9
|
-
status: 'disconnected' | 'connecting' | 'connected' | 'error'
|
|
10
|
-
lastConnected?: number
|
|
11
|
-
reconnectAttempts: number
|
|
12
|
-
errorMessage?: string
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface WebSocketMessage {
|
|
16
|
-
type: 'update' | 'ping' | 'pong' | 'error'
|
|
17
|
-
channel?: 'collaboration' | 'tasks' | 'performance'
|
|
18
|
-
data?: unknown
|
|
19
|
-
timestamp: number
|
|
20
|
-
}
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
// 性能数据类型定义
|
|
2
|
-
|
|
3
|
-
export interface PerformanceCurrent {
|
|
4
|
-
tpm: number
|
|
5
|
-
rpm: number
|
|
6
|
-
windowTotal: {
|
|
7
|
-
tokens: number
|
|
8
|
-
requests: number
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface PerformanceHistory {
|
|
13
|
-
tpm: number[]
|
|
14
|
-
rpm: number[]
|
|
15
|
-
timestamps: number[]
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface PerformanceStatistics {
|
|
19
|
-
avgTpm: number
|
|
20
|
-
peakTpm: number
|
|
21
|
-
peakTime: string
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface PerformanceData {
|
|
25
|
-
current: PerformanceCurrent
|
|
26
|
-
history: PerformanceHistory
|
|
27
|
-
statistics: PerformanceStatistics
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export type TimeRange = '20m' | '1h' | '24h'
|
|
31
|
-
|
|
32
|
-
export interface PerformanceAlert {
|
|
33
|
-
id: string
|
|
34
|
-
type: 'high_tpm'
|
|
35
|
-
message: string
|
|
36
|
-
value: number
|
|
37
|
-
threshold: number
|
|
38
|
-
timestamp: number
|
|
39
|
-
acknowledged: boolean
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// 调用详情类型
|
|
43
|
-
export interface CallDetail {
|
|
44
|
-
agentId: string
|
|
45
|
-
sessionId: string
|
|
46
|
-
model: string
|
|
47
|
-
tokens: number
|
|
48
|
-
trigger: string
|
|
49
|
-
inputTokens: number
|
|
50
|
-
outputTokens: number
|
|
51
|
-
time: string
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export interface CallDetailsResponse {
|
|
55
|
-
timeWindow: string
|
|
56
|
-
calls: CallDetail[]
|
|
57
|
-
totalCalls: number
|
|
58
|
-
totalTokens: number
|
|
59
|
-
summary: {
|
|
60
|
-
avgTokens: number
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Token 分析类型
|
|
65
|
-
export interface TokenSummary {
|
|
66
|
-
input: number
|
|
67
|
-
output: number
|
|
68
|
-
cacheRead: number
|
|
69
|
-
cacheWrite: number
|
|
70
|
-
total: number
|
|
71
|
-
cacheHitRate: number
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export interface TokenCost {
|
|
75
|
-
input: number
|
|
76
|
-
output: number
|
|
77
|
-
cacheRead: number
|
|
78
|
-
cacheWrite: number
|
|
79
|
-
total: number
|
|
80
|
-
saved: number
|
|
81
|
-
savedPercent: number
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export interface AgentTokenData {
|
|
85
|
-
agent: string
|
|
86
|
-
input: number
|
|
87
|
-
output: number
|
|
88
|
-
cacheRead: number
|
|
89
|
-
cacheWrite: number
|
|
90
|
-
total: number
|
|
91
|
-
percent: number
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export interface TokenTrend {
|
|
95
|
-
timestamps: number[]
|
|
96
|
-
input: number[]
|
|
97
|
-
output: number[]
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export interface TokenAnalysisData {
|
|
101
|
-
summary: TokenSummary
|
|
102
|
-
cost: TokenCost
|
|
103
|
-
byAgent: AgentTokenData[]
|
|
104
|
-
trend: TokenTrend | null
|
|
105
|
-
}
|