claude-mpm 4.2.3__py3-none-any.whl → 4.2.5__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.
claude_mpm/VERSION CHANGED
@@ -1 +1 @@
1
- 4.2.3
1
+ 4.2.5
@@ -32,7 +32,7 @@ class CodeTree {
32
32
  lines: 0
33
33
  };
34
34
  // Radial layout settings
35
- this.isRadialLayout = true; // Toggle for radial vs linear layout
35
+ this.isRadialLayout = false; // Toggle for radial vs linear layout - defaulting to linear for better readability
36
36
  this.margin = {top: 20, right: 20, bottom: 20, left: 20};
37
37
  this.width = 960 - this.margin.left - this.margin.right;
38
38
  this.height = 600 - this.margin.top - this.margin.bottom;
@@ -4684,15 +4684,26 @@ class CodeTree {
4684
4684
  */
4685
4685
  async readSourceFile(filePath) {
4686
4686
  try {
4687
- // For now, we'll use a placeholder since we don't have direct file access
4688
- // In a real implementation, this would make an API call to read the file
4689
- console.log('📖 [SOURCE READER] Would read file:', filePath);
4690
-
4691
- // Return placeholder content for demonstration
4692
- return this.generatePlaceholderSource(filePath);
4687
+ console.log('📖 [SOURCE READER] Reading file:', filePath);
4688
+
4689
+ // Make API call to read the actual file content
4690
+ const response = await fetch(`/api/file/read?path=${encodeURIComponent(filePath)}`);
4691
+
4692
+ if (!response.ok) {
4693
+ const error = await response.json();
4694
+ console.error('Failed to read file:', error);
4695
+ // Fall back to placeholder for errors
4696
+ return this.generatePlaceholderSource(filePath);
4697
+ }
4698
+
4699
+ const data = await response.json();
4700
+ console.log('📖 [SOURCE READER] Read', data.lines, 'lines from', data.name);
4701
+ return data.content;
4702
+
4693
4703
  } catch (error) {
4694
4704
  console.error('Failed to read source file:', error);
4695
- return null;
4705
+ // Fall back to placeholder on error
4706
+ return this.generatePlaceholderSource(filePath);
4696
4707
  }
4697
4708
  }
4698
4709
 
@@ -248,7 +248,7 @@ class SocketClient {
248
248
  * @private
249
249
  * @const
250
250
  */
251
- this.pingTimeout = 90000; // 90 seconds for health check (more lenient than Socket.IO timeout)
251
+ this.pingTimeout = 120000; // 120 seconds for health check (more lenient for stability)
252
252
 
253
253
  /**
254
254
  * Health check interval timer.
@@ -346,13 +346,13 @@ class SocketClient {
346
346
  autoConnect: true,
347
347
  reconnection: true,
348
348
  reconnectionDelay: 1000,
349
- reconnectionDelayMax: 5000,
350
- reconnectionAttempts: 5, // Try 5 times then stop (was Infinity which can cause issues)
351
- timeout: 20000, // Connection timeout
349
+ reconnectionDelayMax: 10000, // Increased max delay for stability
350
+ reconnectionAttempts: 10, // Increased attempts for better resilience
351
+ timeout: 30000, // Increased connection timeout to 30 seconds
352
352
  forceNew: true,
353
353
  transports: ['websocket', 'polling'],
354
- pingInterval: 25000, // CRITICAL: Must match server's 25 seconds
355
- pingTimeout: 20000 // CRITICAL: Must match server's 20 seconds
354
+ pingInterval: 30000, // Increased ping interval for stability
355
+ pingTimeout: 60000 // Much longer timeout for better stability
356
356
  });
357
357
 
358
358
  this.setupSocketHandlers();
@@ -186,9 +186,14 @@ class StableDashboardServer:
186
186
 
187
187
  print(f"📁 Using dashboard files from: {self.dashboard_path}")
188
188
 
189
- # Create SocketIO server
189
+ # Create SocketIO server with improved timeout settings
190
190
  self.sio = socketio.AsyncServer(
191
- cors_allowed_origins="*", logger=True, engineio_logger=True
191
+ cors_allowed_origins="*",
192
+ logger=True,
193
+ engineio_logger=True,
194
+ ping_interval=30, # Match client's 30 second ping interval
195
+ ping_timeout=60, # Match client's 60 second timeout
196
+ max_http_buffer_size=1e8, # Allow larger messages
192
197
  )
193
198
  self.app = web.Application()
194
199
  self.sio.attach(self.app)
@@ -207,6 +212,7 @@ class StableDashboardServer:
207
212
  self.app.router.add_get("/", self._serve_dashboard)
208
213
  self.app.router.add_get("/static/{path:.*}", self._serve_static)
209
214
  self.app.router.add_get("/api/directory/list", self._list_directory)
215
+ self.app.router.add_get("/api/file/read", self._read_file)
210
216
  self.app.router.add_get("/version.json", self._serve_version)
211
217
 
212
218
  def _setup_socketio_events(self):
@@ -336,6 +342,62 @@ class StableDashboardServer:
336
342
 
337
343
  return web.json_response(result)
338
344
 
345
+ async def _read_file(self, request):
346
+ """Read file content for source viewer."""
347
+ file_path = request.query.get("path", "")
348
+
349
+ if not file_path:
350
+ return web.json_response({"error": "No path provided"}, status=400)
351
+
352
+ abs_path = os.path.abspath(os.path.expanduser(file_path))
353
+
354
+ # Security check - ensure file is within the project
355
+ try:
356
+ # Get the project root (current working directory)
357
+ project_root = os.getcwd()
358
+ # Ensure the path is within the project
359
+ if not abs_path.startswith(project_root):
360
+ return web.json_response({"error": "Access denied"}, status=403)
361
+ except Exception:
362
+ pass # Allow read if we can't determine project root
363
+
364
+ if not os.path.exists(abs_path):
365
+ return web.json_response({"error": "File not found"}, status=404)
366
+
367
+ if not os.path.isfile(abs_path):
368
+ return web.json_response({"error": "Not a file"}, status=400)
369
+
370
+ try:
371
+ # Read file with appropriate encoding
372
+ encodings = ["utf-8", "latin-1", "cp1252"]
373
+ content = None
374
+
375
+ for encoding in encodings:
376
+ try:
377
+ with open(abs_path, encoding=encoding) as f:
378
+ content = f.read()
379
+ break
380
+ except UnicodeDecodeError:
381
+ continue
382
+
383
+ if content is None:
384
+ return web.json_response({"error": "Could not decode file"}, status=400)
385
+
386
+ return web.json_response(
387
+ {
388
+ "path": abs_path,
389
+ "name": os.path.basename(abs_path),
390
+ "content": content,
391
+ "lines": len(content.splitlines()),
392
+ "size": os.path.getsize(abs_path),
393
+ }
394
+ )
395
+
396
+ except PermissionError:
397
+ return web.json_response({"error": "Permission denied"}, status=403)
398
+ except Exception as e:
399
+ return web.json_response({"error": str(e)}, status=500)
400
+
339
401
  async def _serve_version(self, request):
340
402
  """Serve version information."""
341
403
  version_info = {
@@ -347,7 +409,7 @@ class StableDashboardServer:
347
409
  return web.json_response(version_info)
348
410
 
349
411
  def run(self):
350
- """Run the server."""
412
+ """Run the server with automatic port conflict resolution."""
351
413
  print("🔧 Setting up server...")
352
414
  if not self.setup():
353
415
  print("❌ Server setup failed")
@@ -364,17 +426,48 @@ class StableDashboardServer:
364
426
  print(" - GET /api/directory/list (directory API)")
365
427
  print(f"🔗 Open in browser: http://{self.host}:{self.port}")
366
428
 
367
- try:
368
- web.run_app(self.app, host=self.host, port=self.port, access_log=None)
369
- except KeyboardInterrupt:
370
- print("\n🛑 Server stopped by user")
371
- except Exception as e:
372
- print(f"❌ Server error: {e}")
373
- if self.debug:
374
- import traceback
429
+ # Try to start server with port conflict handling
430
+ max_port_attempts = 10
431
+ original_port = self.port
375
432
 
376
- traceback.print_exc()
377
- return False
433
+ for attempt in range(max_port_attempts):
434
+ try:
435
+ web.run_app(self.app, host=self.host, port=self.port, access_log=None)
436
+ break # Server started successfully
437
+ except KeyboardInterrupt:
438
+ print("\n🛑 Server stopped by user")
439
+ break
440
+ except OSError as e:
441
+ if "[Errno 48]" in str(e) or "Address already in use" in str(e):
442
+ # Port is already in use, try next port
443
+ if attempt < max_port_attempts - 1:
444
+ self.port += 1
445
+ print(
446
+ f"⚠️ Port {self.port - 1} in use, trying port {self.port}..."
447
+ )
448
+ # Recreate the app with new port
449
+ self.setup()
450
+ else:
451
+ print(
452
+ f"❌ Could not find available port after {max_port_attempts} attempts"
453
+ )
454
+ print(f" Ports {original_port} to {self.port} are all in use")
455
+ return False
456
+ else:
457
+ # Other OS error
458
+ print(f"❌ Server error: {e}")
459
+ if self.debug:
460
+ import traceback
461
+
462
+ traceback.print_exc()
463
+ return False
464
+ except Exception as e:
465
+ print(f"❌ Server error: {e}")
466
+ if self.debug:
467
+ import traceback
468
+
469
+ traceback.print_exc()
470
+ return False
378
471
 
379
472
  return True
380
473
 
@@ -108,15 +108,46 @@ class SocketIOClientProxy:
108
108
  async def disconnect():
109
109
  self.logger.info("SocketIOClientProxy: Disconnected from server")
110
110
 
111
- # Connect to the server
112
- await self._sio_client.connect(f"http://127.0.0.1:{self.port}")
111
+ # Try connecting with different hostname formats
112
+ # Some systems resolve localhost differently than 127.0.0.1
113
+ connection_urls = [
114
+ f"http://{self.host}:{self.port}", # Use the provided host (usually "localhost")
115
+ f"http://127.0.0.1:{self.port}", # Try IP address
116
+ f"http://localhost:{self.port}", # Try localhost explicitly
117
+ ]
118
+
119
+ connected = False
120
+ last_error = None
121
+
122
+ for url in connection_urls:
123
+ try:
124
+ self.logger.debug(f"SocketIOClientProxy: Attempting connection to {url}")
125
+ await self._sio_client.connect(url)
126
+ connected = True
127
+ self.logger.info(f"SocketIOClientProxy: Successfully connected to {url}")
128
+ break
129
+ except Exception as e:
130
+ last_error = e
131
+ # Only log as debug to avoid confusion when fallback succeeds
132
+ self.logger.debug(f"SocketIOClientProxy: Failed to connect to {url}: {e}")
133
+ # Disconnect any partial connection before trying next URL
134
+ try:
135
+ await self._sio_client.disconnect()
136
+ except:
137
+ pass
138
+
139
+ if not connected:
140
+ # Only show error if all attempts failed
141
+ self.logger.error(f"SocketIOClientProxy: Connection error after trying all addresses: {last_error}")
142
+ self._sio_client = None
143
+ return
113
144
 
114
145
  # Keep the connection alive until stopped
115
146
  while self.running:
116
147
  await asyncio.sleep(1)
117
148
 
118
149
  except Exception as e:
119
- self.logger.error(f"SocketIOClientProxy: Connection error: {e}")
150
+ self.logger.error(f"SocketIOClientProxy: Unexpected error: {e}")
120
151
  self._sio_client = None
121
152
 
122
153
  def broadcast_event(self, event_type: str, data: Dict[str, Any]):
@@ -393,6 +393,68 @@ class SocketIOServerCore:
393
393
  self.app.router.add_post("/api/events", api_events_handler)
394
394
  self.logger.info("✅ HTTP API endpoint registered at /api/events")
395
395
 
396
+ # Add file reading endpoint for source viewer
397
+ async def file_read_handler(request):
398
+ """Handle GET /api/file/read for reading source files."""
399
+ import os
400
+
401
+ file_path = request.query.get("path", "")
402
+
403
+ if not file_path:
404
+ return web.json_response({"error": "No path provided"}, status=400)
405
+
406
+ abs_path = os.path.abspath(os.path.expanduser(file_path))
407
+
408
+ # Security check - ensure file is within the project
409
+ try:
410
+ project_root = os.getcwd()
411
+ if not abs_path.startswith(project_root):
412
+ return web.json_response({"error": "Access denied"}, status=403)
413
+ except Exception:
414
+ pass
415
+
416
+ if not os.path.exists(abs_path):
417
+ return web.json_response({"error": "File not found"}, status=404)
418
+
419
+ if not os.path.isfile(abs_path):
420
+ return web.json_response({"error": "Not a file"}, status=400)
421
+
422
+ try:
423
+ # Read file with appropriate encoding
424
+ encodings = ["utf-8", "latin-1", "cp1252"]
425
+ content = None
426
+
427
+ for encoding in encodings:
428
+ try:
429
+ with open(abs_path, encoding=encoding) as f:
430
+ content = f.read()
431
+ break
432
+ except UnicodeDecodeError:
433
+ continue
434
+
435
+ if content is None:
436
+ return web.json_response(
437
+ {"error": "Could not decode file"}, status=400
438
+ )
439
+
440
+ return web.json_response(
441
+ {
442
+ "path": abs_path,
443
+ "name": os.path.basename(abs_path),
444
+ "content": content,
445
+ "lines": len(content.splitlines()),
446
+ "size": os.path.getsize(abs_path),
447
+ }
448
+ )
449
+
450
+ except PermissionError:
451
+ return web.json_response({"error": "Permission denied"}, status=403)
452
+ except Exception as e:
453
+ return web.json_response({"error": str(e)}, status=500)
454
+
455
+ self.app.router.add_get("/api/file/read", file_read_handler)
456
+ self.logger.info("✅ File reading API registered at /api/file/read")
457
+
396
458
  def _setup_directory_api(self):
397
459
  """Setup simple directory listing API.
398
460
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-mpm
3
- Version: 4.2.3
3
+ Version: 4.2.5
4
4
  Summary: Claude Multi-Agent Project Manager - Orchestrate Claude with agent delegation and ticket tracking
5
5
  Author-email: Bob Matsuoka <bob@matsuoka.com>
6
6
  Maintainer: Claude MPM Team
@@ -1,5 +1,5 @@
1
1
  claude_mpm/BUILD_NUMBER,sha256=toytnNjkIKPgQaGwDqQdC1rpNTAdSEc6Vja50d7Ovug,4
2
- claude_mpm/VERSION,sha256=6x1PdPSbJsOWJHfe1gogK4OJOi8DiRJdBnDg6tfpcDI,6
2
+ claude_mpm/VERSION,sha256=rwXIWtsOJVrhT-T2eEOfESQ3sLYYzm_WGcjbp4g3dRE,6
3
3
  claude_mpm/__init__.py,sha256=lyTZAYGH4DTaFGLRNWJKk5Q5oTjzN5I6AXmfVX-Jff0,1512
4
4
  claude_mpm/__main__.py,sha256=Ro5UBWBoQaSAIoSqWAr7zkbLyvi4sSy28WShqAhKJG0,723
5
5
  claude_mpm/constants.py,sha256=I946iCQzIIPRZVVJ8aO7lA4euiyDnNw2IX7EelAOkIE,5915
@@ -227,13 +227,13 @@ claude_mpm/dashboard/static/dist/components/working-directory.js,sha256=xE1ydpKD
227
227
  claude_mpm/dashboard/static/js/connection-manager.js,sha256=nn7x1jmwEnBClcChbFk1uMhRPu5U1xmXz3sjuo0LNm4,17981
228
228
  claude_mpm/dashboard/static/js/dashboard.js,sha256=RYzzhNr1pPAHZ12pgWjTpe15Nzaqrm-S9vzTRfqob5A,64712
229
229
  claude_mpm/dashboard/static/js/extension-error-handler.js,sha256=DZHrJ3gbfv4nsjmZpNMj-Sc3GKjVJ5ds8lgoaLRnq5I,6274
230
- claude_mpm/dashboard/static/js/socket-client.js,sha256=iggcE6tJPjG1hChXNG_fTS05p0tU15rgh5P3hb67UPI,56202
230
+ claude_mpm/dashboard/static/js/socket-client.js,sha256=E6CmETHYwS4kPnk9gTnfoWO4FObWYvz0muosFS-zffs,56239
231
231
  claude_mpm/dashboard/static/js/components/activity-tree.js,sha256=1j46X0qjYReP6gwv0WGRpJSJNuBwuj6bKmumWrCZKUo,72740
232
232
  claude_mpm/dashboard/static/js/components/agent-hierarchy.js,sha256=Xihxog_vJrk8VBEkDogV_wbye2GIFWmH71VQ1lETOHk,28243
233
233
  claude_mpm/dashboard/static/js/components/agent-inference.js,sha256=RUVZ_fLOyDkHYjrROen_Pzzay79Bh29eXp_GRIPbIRg,37493
234
234
  claude_mpm/dashboard/static/js/components/build-tracker.js,sha256=iouv35tNhnyx9UKtD7X1eakJkpCnvZVCrAJ_VdzsKUY,11251
235
235
  claude_mpm/dashboard/static/js/components/code-simple.js,sha256=3A3VIvHMpYRjuDKGMaQYoVjf-zuUa4Q6pdBHWDJ0ygM,32050
236
- claude_mpm/dashboard/static/js/components/code-tree.js,sha256=5jCfXeNnnf7QaVqgEyMdijXn7R457MGhSYYS-wDtmAw,195638
236
+ claude_mpm/dashboard/static/js/components/code-tree.js,sha256=cnnnH_IdRy6Q-DaRPtPZfe5f5XMgyv2hVzLrMp3nwII,196135
237
237
  claude_mpm/dashboard/static/js/components/code-viewer.js,sha256=vhesEPYOM6MggweaYvYsv7ufVbuVpIcyJPXpJXyJwpM,14453
238
238
  claude_mpm/dashboard/static/js/components/connection-debug.js,sha256=Qxr_ofDNkxDlZAwbLnhZkXVMyuO9jOe-NMWC9VHxNnA,22196
239
239
  claude_mpm/dashboard/static/js/components/event-processor.js,sha256=pP15JIf2yEh7gqEdam42m_B1B4hDlfKbkDcGmQhyjM8,20567
@@ -433,7 +433,7 @@ claude_mpm/services/core/interfaces/agent.py,sha256=EaPYn6k9HjB2DRTiZIMJwEIBABZF
433
433
  claude_mpm/services/core/interfaces/communication.py,sha256=evwtLbYCFa3Zb8kEfL10LOBVdwP4-n3a3wa7NqIHmKQ,8887
434
434
  claude_mpm/services/core/interfaces/infrastructure.py,sha256=eLtr_dFhA3Ux3mPOV_4DbWhGjHpfpGnj6xOhfQcgZGk,10037
435
435
  claude_mpm/services/core/interfaces/service.py,sha256=hNfHXe45LcPCp_dToOmZCfnUZBF5axMf_TdxqCSm2-I,11536
436
- claude_mpm/services/dashboard/stable_server.py,sha256=Sy-MPE3qSRFpR--Vyf0c2t4n5lo7jpmJr7TAJaEma5k,13920
436
+ claude_mpm/services/dashboard/stable_server.py,sha256=vUiWXutYX5kMkSB3_FBuCp9qnlSAT0bnXjNlI9ybe3Q,17752
437
437
  claude_mpm/services/diagnostics/__init__.py,sha256=WTRucANR9EwNi53rotjkeE4k75s18RjHJ8s1BfBj7ic,614
438
438
  claude_mpm/services/diagnostics/diagnostic_runner.py,sha256=cpCZ7JBvRIpGEchiwYsojmiGaI99Wf-hGxk8eem7xXQ,9164
439
439
  claude_mpm/services/diagnostics/doctor_reporter.py,sha256=Z8hYLqUbGC02gL7nX9kZKbLWRzOmTORRINfCr7EHbBI,10537
@@ -550,7 +550,7 @@ claude_mpm/services/shared/lifecycle_service_base.py,sha256=WiAUJ5_k-2dYkDRMbJl7
550
550
  claude_mpm/services/shared/manager_base.py,sha256=kmjhpVqgfYC1N4YQnPAilCfdrSpAh9Qz7wcQ602L4x4,9296
551
551
  claude_mpm/services/shared/service_factory.py,sha256=blNkIowhIxykrn-a1qsD8Rtkjlky615nAT2nc8m18QI,9718
552
552
  claude_mpm/services/socketio/__init__.py,sha256=PS-2twllga-2mhSfKdu4MgpikfKp_730gMLAqU_9YX4,556
553
- claude_mpm/services/socketio/client_proxy.py,sha256=7e2oiRCBYhSyq3_iA7R48CbzHQS_dXC9eYHnYAN-r_Q,7182
553
+ claude_mpm/services/socketio/client_proxy.py,sha256=UEhLKZIgwgE4pxWDuMlj4QnAZMxoJQ5wchHls4VgC68,8704
554
554
  claude_mpm/services/socketio/dashboard_server.py,sha256=QMQyRvKxfy692A1oStxmY05BeUpVzQZzKHiplw9YgrU,13655
555
555
  claude_mpm/services/socketio/event_normalizer.py,sha256=TlhZbLgb6fSFNXNAZEEbGxHOqgTIB2S9WtEGJEV7Olw,28402
556
556
  claude_mpm/services/socketio/migration_utils.py,sha256=1pK_zGZ8Pd57pCg1O-3gKT8i7_fjEKZ377hxOMGUPQQ,11963
@@ -570,7 +570,7 @@ claude_mpm/services/socketio/handlers/registry.py,sha256=0f-8zBz-iXCbdPPG8iaMpam
570
570
  claude_mpm/services/socketio/server/__init__.py,sha256=S486w-i-hBo3rNW_AtzxbasEgP32By-uI9zz7hzKz-o,640
571
571
  claude_mpm/services/socketio/server/broadcaster.py,sha256=y_D-fDhSD2NZI0cP9wuoB2nlI7VkKjzW_EjVmP-xd5Y,21375
572
572
  claude_mpm/services/socketio/server/connection_manager.py,sha256=lf1rurOvUej0FWLWXn2u1q0xz2rlzSWKb818Le-LkFM,21234
573
- claude_mpm/services/socketio/server/core.py,sha256=-e9mftha7ptOwlau55vOLf_UO_Mhdy2E_s7VmUWzrAc,28970
573
+ claude_mpm/services/socketio/server/core.py,sha256=eBM_CkXDqwwIZ8UjsMiWN2qrnIQYb4S1aGOjOSwqCIM,31356
574
574
  claude_mpm/services/socketio/server/eventbus_integration.py,sha256=6LkK8W9wTiNd8d9KoAH2IY1b4osyGGgGaJ0DmwIwnVM,7790
575
575
  claude_mpm/services/socketio/server/main.py,sha256=JvaH4vHz1AgdBsyB7qSG-BZmak9E2FA02Ij2jYKMvqs,19535
576
576
  claude_mpm/services/ticket_services/__init__.py,sha256=I01W25n-tBWwZ0TD-dPA63nqzCU2KnpOvbqeysmaa2E,798
@@ -615,9 +615,9 @@ claude_mpm/utils/subprocess_utils.py,sha256=zgiwLqh_17WxHpySvUPH65pb4bzIeUGOAYUJ
615
615
  claude_mpm/validation/__init__.py,sha256=YZhwE3mhit-lslvRLuwfX82xJ_k4haZeKmh4IWaVwtk,156
616
616
  claude_mpm/validation/agent_validator.py,sha256=3Lo6LK-Mw9IdnL_bd3zl_R6FkgSVDYKUUM7EeVVD3jc,20865
617
617
  claude_mpm/validation/frontmatter_validator.py,sha256=u8g4Eyd_9O6ugj7Un47oSGh3kqv4wMkuks2i_CtWRvM,7028
618
- claude_mpm-4.2.3.dist-info/licenses/LICENSE,sha256=lpaivOlPuBZW1ds05uQLJJswy8Rp_HMNieJEbFlqvLk,1072
619
- claude_mpm-4.2.3.dist-info/METADATA,sha256=FS32yLLQTCdCSmQo6QblFKCk4HipuzVk3nUKq5L5KMc,13776
620
- claude_mpm-4.2.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
621
- claude_mpm-4.2.3.dist-info/entry_points.txt,sha256=FDPZgz8JOvD-6iuXY2l9Zbo9zYVRuE4uz4Qr0vLeGOk,471
622
- claude_mpm-4.2.3.dist-info/top_level.txt,sha256=1nUg3FEaBySgm8t-s54jK5zoPnu3_eY6EP6IOlekyHA,11
623
- claude_mpm-4.2.3.dist-info/RECORD,,
618
+ claude_mpm-4.2.5.dist-info/licenses/LICENSE,sha256=lpaivOlPuBZW1ds05uQLJJswy8Rp_HMNieJEbFlqvLk,1072
619
+ claude_mpm-4.2.5.dist-info/METADATA,sha256=y8K0gWlLWR4tW2V8YD-qp3Q8m9MbjNxVYodwr1oLKQs,13776
620
+ claude_mpm-4.2.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
621
+ claude_mpm-4.2.5.dist-info/entry_points.txt,sha256=FDPZgz8JOvD-6iuXY2l9Zbo9zYVRuE4uz4Qr0vLeGOk,471
622
+ claude_mpm-4.2.5.dist-info/top_level.txt,sha256=1nUg3FEaBySgm8t-s54jK5zoPnu3_eY6EP6IOlekyHA,11
623
+ claude_mpm-4.2.5.dist-info/RECORD,,