claude-mpm 4.2.44__py3-none-any.whl → 4.2.51__py3-none-any.whl

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 (148) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_PM.md +43 -1
  3. claude_mpm/agents/INSTRUCTIONS.md +75 -1
  4. claude_mpm/agents/WORKFLOW.md +46 -1
  5. claude_mpm/agents/frontmatter_validator.py +20 -12
  6. claude_mpm/agents/templates/nextjs_engineer.json +277 -0
  7. claude_mpm/agents/templates/python_engineer.json +289 -0
  8. claude_mpm/agents/templates/react_engineer.json +11 -3
  9. claude_mpm/agents/templates/security.json +50 -9
  10. claude_mpm/cli/commands/agents.py +2 -2
  11. claude_mpm/cli/commands/uninstall.py +1 -2
  12. claude_mpm/cli/interactive/agent_wizard.py +3 -3
  13. claude_mpm/cli/parsers/agent_manager_parser.py +3 -3
  14. claude_mpm/cli/parsers/agents_parser.py +1 -1
  15. claude_mpm/constants.py +1 -1
  16. claude_mpm/core/error_handler.py +2 -4
  17. claude_mpm/core/file_utils.py +4 -12
  18. claude_mpm/core/log_manager.py +8 -5
  19. claude_mpm/core/logger.py +1 -1
  20. claude_mpm/core/logging_utils.py +6 -6
  21. claude_mpm/core/unified_agent_registry.py +18 -4
  22. claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +188 -0
  23. claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +156 -0
  24. claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +38 -0
  25. claude_mpm/dashboard/react/components/shared/FilterBar.module.css +92 -0
  26. claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +248 -0
  27. claude_mpm/dashboard/static/archive/activity_dashboard_test.html +61 -0
  28. claude_mpm/dashboard/static/archive/test_activity_connection.html +179 -0
  29. claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +68 -0
  30. claude_mpm/dashboard/static/archive/test_dashboard.html +409 -0
  31. claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +519 -0
  32. claude_mpm/dashboard/static/archive/test_dashboard_verification.html +181 -0
  33. claude_mpm/dashboard/static/archive/test_file_data.html +315 -0
  34. claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +243 -0
  35. claude_mpm/dashboard/static/archive/test_file_tree_fix.html +234 -0
  36. claude_mpm/dashboard/static/archive/test_file_tree_rename.html +117 -0
  37. claude_mpm/dashboard/static/archive/test_file_tree_tab.html +115 -0
  38. claude_mpm/dashboard/static/archive/test_file_viewer.html +224 -0
  39. claude_mpm/dashboard/static/archive/test_final_activity.html +220 -0
  40. claude_mpm/dashboard/static/archive/test_tab_fix.html +139 -0
  41. claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +1 -0
  42. claude_mpm/dashboard/static/built/components/activity-tree.js +1 -1
  43. claude_mpm/dashboard/static/built/components/agent-hierarchy.js +777 -0
  44. claude_mpm/dashboard/static/built/components/agent-inference.js +1 -1
  45. claude_mpm/dashboard/static/built/components/build-tracker.js +333 -0
  46. claude_mpm/dashboard/static/built/components/code-simple.js +857 -0
  47. claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +353 -0
  48. claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +235 -0
  49. claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +409 -0
  50. claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +435 -0
  51. claude_mpm/dashboard/static/built/components/code-viewer.js +2 -1076
  52. claude_mpm/dashboard/static/built/components/connection-debug.js +654 -0
  53. claude_mpm/dashboard/static/built/components/diff-viewer.js +891 -0
  54. claude_mpm/dashboard/static/built/components/event-processor.js +1 -1
  55. claude_mpm/dashboard/static/built/components/event-viewer.js +1 -1
  56. claude_mpm/dashboard/static/built/components/export-manager.js +1 -1
  57. claude_mpm/dashboard/static/built/components/file-change-tracker.js +443 -0
  58. claude_mpm/dashboard/static/built/components/file-change-viewer.js +690 -0
  59. claude_mpm/dashboard/static/built/components/file-tool-tracker.js +1 -1
  60. claude_mpm/dashboard/static/built/components/module-viewer.js +1 -1
  61. claude_mpm/dashboard/static/built/components/nav-bar.js +145 -0
  62. claude_mpm/dashboard/static/built/components/page-structure.js +429 -0
  63. claude_mpm/dashboard/static/built/components/session-manager.js +1 -1
  64. claude_mpm/dashboard/static/built/components/ui-state-manager.js +2 -465
  65. claude_mpm/dashboard/static/built/components/working-directory.js +1 -1
  66. claude_mpm/dashboard/static/built/connection-manager.js +536 -0
  67. claude_mpm/dashboard/static/built/dashboard.js +1 -1
  68. claude_mpm/dashboard/static/built/extension-error-handler.js +164 -0
  69. claude_mpm/dashboard/static/built/react/events.js +30 -0
  70. claude_mpm/dashboard/static/built/shared/dom-helpers.js +396 -0
  71. claude_mpm/dashboard/static/built/shared/event-bus.js +330 -0
  72. claude_mpm/dashboard/static/built/shared/event-filter-service.js +540 -0
  73. claude_mpm/dashboard/static/built/shared/logger.js +385 -0
  74. claude_mpm/dashboard/static/built/shared/page-structure.js +251 -0
  75. claude_mpm/dashboard/static/built/shared/tooltip-service.js +253 -0
  76. claude_mpm/dashboard/static/built/socket-client.js +1 -1
  77. claude_mpm/dashboard/static/built/tab-isolation-fix.js +185 -0
  78. claude_mpm/dashboard/static/css/dashboard.css +28 -5
  79. claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +1 -0
  80. claude_mpm/dashboard/static/dist/components/activity-tree.js +1 -1
  81. claude_mpm/dashboard/static/dist/components/agent-inference.js +1 -1
  82. claude_mpm/dashboard/static/dist/components/code-viewer.js +2 -0
  83. claude_mpm/dashboard/static/dist/components/event-processor.js +1 -1
  84. claude_mpm/dashboard/static/dist/components/event-viewer.js +1 -1
  85. claude_mpm/dashboard/static/dist/components/export-manager.js +1 -1
  86. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +1 -1
  87. claude_mpm/dashboard/static/dist/components/module-viewer.js +1 -1
  88. claude_mpm/dashboard/static/dist/components/session-manager.js +1 -1
  89. claude_mpm/dashboard/static/dist/components/working-directory.js +1 -1
  90. claude_mpm/dashboard/static/dist/dashboard.js +1 -1
  91. claude_mpm/dashboard/static/dist/react/events.js +30 -0
  92. claude_mpm/dashboard/static/dist/socket-client.js +1 -1
  93. claude_mpm/dashboard/static/events.html +607 -0
  94. claude_mpm/dashboard/static/index.html +713 -0
  95. claude_mpm/dashboard/static/js/components/activity-tree.js +3 -17
  96. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +4 -1
  97. claude_mpm/dashboard/static/js/components/agent-inference.js +3 -0
  98. claude_mpm/dashboard/static/js/components/build-tracker.js +8 -0
  99. claude_mpm/dashboard/static/js/components/code-viewer.js +306 -66
  100. claude_mpm/dashboard/static/js/components/event-processor.js +3 -0
  101. claude_mpm/dashboard/static/js/components/event-viewer.js +39 -2
  102. claude_mpm/dashboard/static/js/components/export-manager.js +3 -0
  103. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +30 -10
  104. claude_mpm/dashboard/static/js/components/socket-manager.js +4 -0
  105. claude_mpm/dashboard/static/js/components/ui-state-manager.js +285 -85
  106. claude_mpm/dashboard/static/js/components/working-directory.js +3 -0
  107. claude_mpm/dashboard/static/js/dashboard.js +61 -33
  108. claude_mpm/dashboard/static/js/socket-client.js +12 -8
  109. claude_mpm/dashboard/static/js/stores/dashboard-store.js +562 -0
  110. claude_mpm/dashboard/static/js/tab-isolation-fix.js +185 -0
  111. claude_mpm/dashboard/static/legacy/activity.html +736 -0
  112. claude_mpm/dashboard/static/legacy/agents.html +786 -0
  113. claude_mpm/dashboard/static/legacy/files.html +747 -0
  114. claude_mpm/dashboard/static/legacy/tools.html +831 -0
  115. claude_mpm/dashboard/static/monitors-index.html +218 -0
  116. claude_mpm/dashboard/static/monitors.html +431 -0
  117. claude_mpm/dashboard/static/production/events.html +659 -0
  118. claude_mpm/dashboard/static/production/main.html +715 -0
  119. claude_mpm/dashboard/static/production/monitors.html +483 -0
  120. claude_mpm/dashboard/static/socket.io.min.js +7 -0
  121. claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +7 -0
  122. claude_mpm/dashboard/static/test-archive/dashboard.html +635 -0
  123. claude_mpm/dashboard/static/test-archive/debug-events.html +147 -0
  124. claude_mpm/dashboard/static/test-archive/test-navigation.html +256 -0
  125. claude_mpm/dashboard/static/test-archive/test-react-exports.html +180 -0
  126. claude_mpm/dashboard/templates/index.html +79 -9
  127. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +1 -1
  128. claude_mpm/services/agents/deployment/agent_discovery_service.py +3 -0
  129. claude_mpm/services/agents/deployment/agent_template_builder.py +25 -8
  130. claude_mpm/services/agents/deployment/agent_validator.py +3 -0
  131. claude_mpm/services/agents/deployment/validation/template_validator.py +13 -4
  132. claude_mpm/services/agents/local_template_manager.py +2 -6
  133. claude_mpm/services/monitor/daemon.py +1 -2
  134. claude_mpm/services/monitor/daemon_manager.py +2 -5
  135. claude_mpm/services/monitor/event_emitter.py +2 -2
  136. claude_mpm/services/monitor/handlers/code_analysis.py +4 -6
  137. claude_mpm/services/monitor/handlers/hooks.py +2 -4
  138. claude_mpm/services/monitor/server.py +27 -4
  139. claude_mpm/tools/code_tree_analyzer.py +2 -2
  140. {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/METADATA +1 -1
  141. {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/RECORD +146 -81
  142. claude_mpm/dashboard/static/test-browser-monitor.html +0 -470
  143. claude_mpm/dashboard/static/test-simple.html +0 -97
  144. /claude_mpm/dashboard/static/{test_debug.html → test-archive/test_debug.html} +0 -0
  145. {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/WHEEL +0 -0
  146. {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/entry_points.txt +0 -0
  147. {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/licenses/LICENSE +0 -0
  148. {claude_mpm-4.2.44.dist-info → claude_mpm-4.2.51.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,562 @@
1
+ /**
2
+ * Shared Zustand Store for Dashboard Components
3
+ * This store manages all dashboard state and socket events
4
+ */
5
+
6
+ (function(window) {
7
+ 'use strict';
8
+
9
+ // Store will be initialized when Zustand is loaded
10
+ let store = null;
11
+ let subscribe = null;
12
+ let getState = null;
13
+ let setState = null;
14
+
15
+ /**
16
+ * Initialize the dashboard store
17
+ * @param {Object} zustand - The Zustand vanilla module
18
+ */
19
+ function initializeStore(zustand) {
20
+ const storeApi = zustand.createStore((set, get) => ({
21
+ // Connection State
22
+ socket: null,
23
+ isConnected: false,
24
+ connectionError: null,
25
+ reconnectAttempts: 0,
26
+ lastHeartbeat: null,
27
+
28
+ // Session State
29
+ currentSession: null,
30
+ sessions: [],
31
+
32
+ // Events
33
+ events: [],
34
+ maxEvents: 1000,
35
+ eventFilters: {
36
+ type: null,
37
+ agent: null,
38
+ tool: null,
39
+ search: ''
40
+ },
41
+
42
+ // Agents
43
+ agents: new Map(),
44
+ agentHierarchy: [],
45
+ activeAgent: null,
46
+
47
+ // Tools
48
+ tools: new Map(),
49
+ toolOperations: [],
50
+ activeTools: new Set(),
51
+
52
+ // Files
53
+ files: new Map(),
54
+ fileOperations: [],
55
+ fileTree: {},
56
+ workingDirectory: null,
57
+
58
+ // Activity
59
+ activityTree: [],
60
+ activityNodes: new Map(),
61
+
62
+ // UI State
63
+ debugMode: false,
64
+ autoScroll: true,
65
+ theme: 'dark',
66
+
67
+ // Statistics
68
+ stats: {
69
+ totalEvents: 0,
70
+ eventsPerSecond: 0,
71
+ agentCount: 0,
72
+ toolCount: 0,
73
+ fileCount: 0,
74
+ sessionDuration: 0
75
+ },
76
+
77
+ // Actions
78
+ actions: {
79
+ // Connection Management
80
+ setSocket: (socket) => set({ socket }),
81
+
82
+ setConnected: (isConnected) => set({
83
+ isConnected,
84
+ connectionError: isConnected ? null : get().connectionError,
85
+ reconnectAttempts: isConnected ? 0 : get().reconnectAttempts
86
+ }),
87
+
88
+ setConnectionError: (error) => set({
89
+ connectionError: error,
90
+ isConnected: false
91
+ }),
92
+
93
+ incrementReconnectAttempts: () => set(state => ({
94
+ reconnectAttempts: state.reconnectAttempts + 1
95
+ })),
96
+
97
+ updateHeartbeat: () => set({ lastHeartbeat: Date.now() }),
98
+
99
+ // Session Management
100
+ setCurrentSession: (session) => set({ currentSession: session }),
101
+
102
+ addSession: (session) => set(state => ({
103
+ sessions: [...state.sessions, session].slice(-50) // Keep last 50 sessions
104
+ })),
105
+
106
+ // Event Processing
107
+ addEvent: (event) => set(state => {
108
+ const events = [...state.events, {
109
+ ...event,
110
+ timestamp: event.timestamp || Date.now(),
111
+ id: event.id || `${Date.now()}-${Math.random()}`
112
+ }];
113
+
114
+ // Keep only maxEvents
115
+ if (events.length > state.maxEvents) {
116
+ events.splice(0, events.length - state.maxEvents);
117
+ }
118
+
119
+ // Update statistics
120
+ const stats = { ...state.stats };
121
+ stats.totalEvents++;
122
+
123
+ return {
124
+ events,
125
+ stats
126
+ };
127
+ }),
128
+
129
+ clearEvents: () => set({
130
+ events: [],
131
+ stats: { ...get().stats, totalEvents: 0 }
132
+ }),
133
+
134
+ setEventFilter: (filterType, value) => set(state => ({
135
+ eventFilters: { ...state.eventFilters, [filterType]: value }
136
+ })),
137
+
138
+ // Agent Management
139
+ updateAgent: (agentId, data) => set(state => {
140
+ const agents = new Map(state.agents);
141
+ const existing = agents.get(agentId) || {};
142
+ agents.set(agentId, {
143
+ ...existing,
144
+ ...data,
145
+ id: agentId,
146
+ lastUpdate: Date.now()
147
+ });
148
+
149
+ return {
150
+ agents,
151
+ stats: { ...state.stats, agentCount: agents.size }
152
+ };
153
+ }),
154
+
155
+ removeAgent: (agentId) => set(state => {
156
+ const agents = new Map(state.agents);
157
+ agents.delete(agentId);
158
+ return {
159
+ agents,
160
+ stats: { ...state.stats, agentCount: agents.size }
161
+ };
162
+ }),
163
+
164
+ setActiveAgent: (agentId) => set({ activeAgent: agentId }),
165
+
166
+ updateAgentHierarchy: (hierarchy) => set({ agentHierarchy: hierarchy }),
167
+
168
+ // Tool Management
169
+ updateTool: (toolId, data) => set(state => {
170
+ const tools = new Map(state.tools);
171
+ const existing = tools.get(toolId) || {};
172
+ tools.set(toolId, {
173
+ ...existing,
174
+ ...data,
175
+ id: toolId,
176
+ lastUpdate: Date.now()
177
+ });
178
+
179
+ // Update active tools
180
+ const activeTools = new Set(state.activeTools);
181
+ if (data.status === 'active' || data.status === 'running') {
182
+ activeTools.add(toolId);
183
+ } else if (data.status === 'completed' || data.status === 'error') {
184
+ activeTools.delete(toolId);
185
+ }
186
+
187
+ return {
188
+ tools,
189
+ activeTools,
190
+ stats: { ...state.stats, toolCount: tools.size }
191
+ };
192
+ }),
193
+
194
+ addToolOperation: (operation) => set(state => ({
195
+ toolOperations: [...state.toolOperations, {
196
+ ...operation,
197
+ timestamp: Date.now(),
198
+ id: `${Date.now()}-${Math.random()}`
199
+ }].slice(-500) // Keep last 500 operations
200
+ })),
201
+
202
+ // File Management
203
+ updateFile: (filePath, data) => set(state => {
204
+ const files = new Map(state.files);
205
+ const existing = files.get(filePath) || {};
206
+ files.set(filePath, {
207
+ ...existing,
208
+ ...data,
209
+ path: filePath,
210
+ lastUpdate: Date.now()
211
+ });
212
+
213
+ return {
214
+ files,
215
+ stats: { ...state.stats, fileCount: files.size }
216
+ };
217
+ }),
218
+
219
+ addFileOperation: (operation) => set(state => ({
220
+ fileOperations: [...state.fileOperations, {
221
+ ...operation,
222
+ timestamp: Date.now(),
223
+ id: `${Date.now()}-${Math.random()}`
224
+ }].slice(-500) // Keep last 500 operations
225
+ })),
226
+
227
+ updateFileTree: (tree) => set({ fileTree: tree }),
228
+
229
+ setWorkingDirectory: (dir) => set({ workingDirectory: dir }),
230
+
231
+ // Activity Management
232
+ addActivityNode: (node) => set(state => {
233
+ const activityNodes = new Map(state.activityNodes);
234
+ activityNodes.set(node.id, {
235
+ ...node,
236
+ timestamp: Date.now()
237
+ });
238
+
239
+ // Build tree structure
240
+ const activityTree = buildActivityTree(activityNodes);
241
+
242
+ return { activityNodes, activityTree };
243
+ }),
244
+
245
+ clearActivity: () => set({
246
+ activityTree: [],
247
+ activityNodes: new Map()
248
+ }),
249
+
250
+ // UI State
251
+ toggleDebugMode: () => set(state => ({ debugMode: !state.debugMode })),
252
+
253
+ toggleAutoScroll: () => set(state => ({ autoScroll: !state.autoScroll })),
254
+
255
+ setTheme: (theme) => set({ theme }),
256
+
257
+ // Bulk Updates
258
+ processSocketEvent: (eventType, data) => {
259
+ const actions = get().actions;
260
+
261
+ // Add to events list
262
+ actions.addEvent({ type: eventType, data });
263
+
264
+ // Process based on event type
265
+ switch(eventType) {
266
+ case 'agent_start':
267
+ case 'agent_update':
268
+ case 'agent_complete':
269
+ if (data.agent_id) {
270
+ actions.updateAgent(data.agent_id, data);
271
+ }
272
+ break;
273
+
274
+ case 'tool_start':
275
+ case 'tool_update':
276
+ case 'tool_complete':
277
+ case 'tool_error':
278
+ if (data.tool_id || data.tool) {
279
+ const toolId = data.tool_id || data.tool;
280
+ actions.updateTool(toolId, data);
281
+ actions.addToolOperation({
282
+ type: eventType,
283
+ tool: toolId,
284
+ ...data
285
+ });
286
+ }
287
+ break;
288
+
289
+ case 'file_read':
290
+ case 'file_write':
291
+ case 'file_edit':
292
+ case 'file_delete':
293
+ if (data.file_path) {
294
+ actions.updateFile(data.file_path, {
295
+ operation: eventType.replace('file_', ''),
296
+ ...data
297
+ });
298
+ actions.addFileOperation({
299
+ type: eventType,
300
+ path: data.file_path,
301
+ ...data
302
+ });
303
+ }
304
+ break;
305
+
306
+ case 'session_start':
307
+ case 'session_update':
308
+ actions.setCurrentSession(data);
309
+ actions.addSession(data);
310
+ break;
311
+
312
+ case 'working_directory':
313
+ actions.setWorkingDirectory(data.path || data.directory);
314
+ break;
315
+
316
+ case 'activity_node':
317
+ actions.addActivityNode(data);
318
+ break;
319
+
320
+ case 'heartbeat':
321
+ actions.updateHeartbeat();
322
+ break;
323
+
324
+ case 'connected':
325
+ actions.setConnected(true);
326
+ break;
327
+
328
+ case 'disconnected':
329
+ actions.setConnected(false);
330
+ break;
331
+
332
+ case 'error':
333
+ actions.setConnectionError(data.message || data.error);
334
+ break;
335
+ }
336
+
337
+ // Log in debug mode
338
+ if (get().debugMode) {
339
+ console.log(`[DashboardStore] Event: ${eventType}`, data);
340
+ }
341
+ },
342
+
343
+ // Reset store
344
+ reset: () => set({
345
+ events: [],
346
+ agents: new Map(),
347
+ tools: new Map(),
348
+ files: new Map(),
349
+ toolOperations: [],
350
+ fileOperations: [],
351
+ activityTree: [],
352
+ activityNodes: new Map(),
353
+ stats: {
354
+ totalEvents: 0,
355
+ eventsPerSecond: 0,
356
+ agentCount: 0,
357
+ toolCount: 0,
358
+ fileCount: 0,
359
+ sessionDuration: 0
360
+ }
361
+ })
362
+ },
363
+
364
+ // Computed getters
365
+ getFilteredEvents: () => {
366
+ const state = get();
367
+ let filtered = state.events;
368
+
369
+ if (state.eventFilters.type) {
370
+ filtered = filtered.filter(e => e.type === state.eventFilters.type);
371
+ }
372
+ if (state.eventFilters.agent) {
373
+ filtered = filtered.filter(e => e.data?.agent_id === state.eventFilters.agent);
374
+ }
375
+ if (state.eventFilters.tool) {
376
+ filtered = filtered.filter(e => e.data?.tool === state.eventFilters.tool);
377
+ }
378
+ if (state.eventFilters.search) {
379
+ const search = state.eventFilters.search.toLowerCase();
380
+ filtered = filtered.filter(e =>
381
+ JSON.stringify(e).toLowerCase().includes(search)
382
+ );
383
+ }
384
+
385
+ return filtered;
386
+ },
387
+
388
+ getAgentsList: () => Array.from(get().agents.values()),
389
+
390
+ getToolsList: () => Array.from(get().tools.values()),
391
+
392
+ getFilesList: () => Array.from(get().files.values()),
393
+
394
+ getActiveToolsList: () => {
395
+ const state = get();
396
+ return Array.from(state.activeTools).map(id => state.tools.get(id)).filter(Boolean);
397
+ }
398
+ }));
399
+
400
+ // Extract store methods
401
+ store = storeApi;
402
+ subscribe = storeApi.subscribe;
403
+ getState = storeApi.getState;
404
+ setState = storeApi.setState;
405
+
406
+ return storeApi;
407
+ }
408
+
409
+ /**
410
+ * Build hierarchical activity tree from flat nodes
411
+ */
412
+ function buildActivityTree(nodes) {
413
+ const tree = [];
414
+ const nodeMap = new Map();
415
+
416
+ // First pass: create all nodes
417
+ nodes.forEach((node, id) => {
418
+ nodeMap.set(id, {
419
+ ...node,
420
+ children: []
421
+ });
422
+ });
423
+
424
+ // Second pass: build tree structure
425
+ nodeMap.forEach(node => {
426
+ if (node.parentId && nodeMap.has(node.parentId)) {
427
+ nodeMap.get(node.parentId).children.push(node);
428
+ } else {
429
+ tree.push(node);
430
+ }
431
+ });
432
+
433
+ return tree;
434
+ }
435
+
436
+ /**
437
+ * Format bytes to human readable
438
+ */
439
+ function formatBytes(bytes) {
440
+ if (bytes === 0) return '0 B';
441
+ const k = 1024;
442
+ const sizes = ['B', 'KB', 'MB', 'GB'];
443
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
444
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
445
+ }
446
+
447
+ /**
448
+ * Format duration to human readable
449
+ */
450
+ function formatDuration(ms) {
451
+ if (ms < 1000) return `${ms}ms`;
452
+ if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;
453
+ if (ms < 3600000) return `${Math.floor(ms / 60000)}m ${Math.floor((ms % 60000) / 1000)}s`;
454
+ return `${Math.floor(ms / 3600000)}h ${Math.floor((ms % 3600000) / 60000)}m`;
455
+ }
456
+
457
+ /**
458
+ * Connect to Socket.IO server
459
+ */
460
+ function connectSocket(io, url = 'http://localhost:8765') {
461
+ if (!store) {
462
+ console.error('[DashboardStore] Store not initialized');
463
+ return null;
464
+ }
465
+
466
+ // Enhanced connection options for better compatibility
467
+ const socket = io(url, {
468
+ transports: ['polling', 'websocket'], // Start with polling for better compatibility
469
+ reconnection: true,
470
+ reconnectionAttempts: Infinity,
471
+ reconnectionDelay: 1000,
472
+ reconnectionDelayMax: 5000,
473
+ timeout: 20000,
474
+ forceNew: true, // Force new connection
475
+ withCredentials: false, // Disable credentials for CORS
476
+ path: '/socket.io/' // Explicit Socket.IO path
477
+ });
478
+
479
+ const actions = getState().actions;
480
+ actions.setSocket(socket);
481
+
482
+ // Socket event handlers
483
+ socket.on('connect', () => {
484
+ console.log('[DashboardStore] Connected to server');
485
+ console.log('[DashboardStore] Socket ID:', socket.id);
486
+ actions.setConnected(true);
487
+ actions.processSocketEvent('connected', { timestamp: Date.now(), socketId: socket.id });
488
+ });
489
+
490
+ socket.on('disconnect', (reason) => {
491
+ console.log('[DashboardStore] Disconnected:', reason);
492
+ actions.setConnected(false);
493
+ actions.processSocketEvent('disconnected', { reason });
494
+ });
495
+
496
+ socket.on('connect_error', (error) => {
497
+ console.error('[DashboardStore] Connection error:', error.message);
498
+ console.error('[DashboardStore] Error type:', error.type);
499
+ actions.setConnectionError(error.message || 'Connection error');
500
+ });
501
+
502
+ socket.on('error', (error) => {
503
+ console.error('[DashboardStore] Socket error:', error);
504
+ actions.setConnectionError(error.message || 'Socket error');
505
+ });
506
+
507
+ socket.on('reconnect_attempt', (attemptNumber) => {
508
+ console.log('[DashboardStore] Reconnection attempt:', attemptNumber);
509
+ actions.incrementReconnectAttempts();
510
+ });
511
+
512
+ socket.on('reconnect', (attemptNumber) => {
513
+ console.log('[DashboardStore] Reconnected after', attemptNumber, 'attempts');
514
+ });
515
+
516
+ socket.on('heartbeat', (data) => {
517
+ actions.updateHeartbeat();
518
+ });
519
+
520
+ // Listen for all events and process them
521
+ const allEvents = [
522
+ 'agent_start', 'agent_update', 'agent_complete', 'agent_error',
523
+ 'tool_start', 'tool_update', 'tool_complete', 'tool_error',
524
+ 'file_read', 'file_write', 'file_edit', 'file_delete',
525
+ 'session_start', 'session_update', 'session_end',
526
+ 'working_directory', 'activity_node', 'code_analysis',
527
+ 'message', 'log', 'debug', 'info', 'warning', 'error'
528
+ ];
529
+
530
+ allEvents.forEach(eventType => {
531
+ socket.on(eventType, (data) => {
532
+ actions.processSocketEvent(eventType, data);
533
+ });
534
+ });
535
+
536
+ // Generic event handler for unknown events
537
+ socket.onAny((eventName, ...args) => {
538
+ if (!allEvents.includes(eventName) && eventName !== 'connect' && eventName !== 'disconnect') {
539
+ console.log('[DashboardStore] Unknown event:', eventName, args);
540
+ actions.processSocketEvent(eventName, args[0] || {});
541
+ }
542
+ });
543
+
544
+ return socket;
545
+ }
546
+
547
+ // Export public API
548
+ window.DashboardStore = {
549
+ initializeStore,
550
+ connectSocket,
551
+ getStore: () => store,
552
+ getState: () => getState ? getState() : null,
553
+ setState: (partial) => setState ? setState(partial) : null,
554
+ subscribe: (listener) => subscribe ? subscribe(listener) : null,
555
+ utils: {
556
+ formatBytes,
557
+ formatDuration,
558
+ buildActivityTree
559
+ }
560
+ };
561
+
562
+ })(window);