claude-mpm 4.1.11__py3-none-any.whl → 4.1.12__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 +1 -1
- claude_mpm/agents/INSTRUCTIONS.md +8 -0
- claude_mpm/cli/__init__.py +1 -1
- claude_mpm/cli/commands/mpm_init.py +125 -110
- claude_mpm/cli/commands/mpm_init_handler.py +24 -23
- claude_mpm/cli/parsers/mpm_init_parser.py +34 -28
- claude_mpm/core/config.py +18 -0
- claude_mpm/core/instruction_reinforcement_hook.py +266 -0
- claude_mpm/core/pm_hook_interceptor.py +105 -8
- claude_mpm/dashboard/static/dist/components/code-tree.js +2593 -2
- claude_mpm/dashboard/static/js/components/build-tracker.js +15 -13
- claude_mpm/dashboard/static/js/components/code-tree.js +551 -143
- claude_mpm/dashboard/static/js/dashboard.js +31 -41
- claude_mpm/dashboard/templates/index.html +19 -12
- claude_mpm/services/agents/deployment/agent_template_builder.py +11 -7
- claude_mpm/services/cli/socketio_manager.py +39 -8
- claude_mpm/services/infrastructure/monitoring.py +1 -1
- claude_mpm/services/socketio/handlers/code_analysis.py +83 -136
- claude_mpm/tools/code_tree_analyzer.py +290 -202
- {claude_mpm-4.1.11.dist-info → claude_mpm-4.1.12.dist-info}/METADATA +1 -1
- {claude_mpm-4.1.11.dist-info → claude_mpm-4.1.12.dist-info}/RECORD +25 -24
- {claude_mpm-4.1.11.dist-info → claude_mpm-4.1.12.dist-info}/WHEEL +0 -0
- {claude_mpm-4.1.11.dist-info → claude_mpm-4.1.12.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.1.11.dist-info → claude_mpm-4.1.12.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.1.11.dist-info → claude_mpm-4.1.12.dist-info}/top_level.txt +0 -0
|
@@ -163,14 +163,22 @@ class Dashboard {
|
|
|
163
163
|
// Set the socket client for receiving updates
|
|
164
164
|
this.buildTracker.setSocketClient(this.socketClient);
|
|
165
165
|
|
|
166
|
-
// Mount to header
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
166
|
+
// Mount to header with retry logic for DOM readiness
|
|
167
|
+
const mountBuildTracker = () => {
|
|
168
|
+
const headerTitle = document.querySelector('.header-title');
|
|
169
|
+
if (headerTitle) {
|
|
170
|
+
// Insert after the title and status badge
|
|
171
|
+
this.buildTracker.mount(headerTitle);
|
|
172
|
+
console.log('BuildTracker mounted successfully');
|
|
173
|
+
} else {
|
|
174
|
+
console.warn('Header-title element not found for build tracker, will retry');
|
|
175
|
+
// Retry after a short delay if DOM is still being constructed
|
|
176
|
+
setTimeout(mountBuildTracker, 100);
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
// Try to mount immediately, with retry logic if needed
|
|
181
|
+
mountBuildTracker();
|
|
174
182
|
|
|
175
183
|
// Make available globally for debugging
|
|
176
184
|
window.buildTracker = this.buildTracker;
|
|
@@ -1080,14 +1088,11 @@ async function updateFileViewerModal(modal, filePath, workingDir) {
|
|
|
1080
1088
|
working_dir: workingDir
|
|
1081
1089
|
});
|
|
1082
1090
|
|
|
1083
|
-
|
|
1084
|
-
filePath,
|
|
1085
|
-
workingDir
|
|
1086
|
-
});
|
|
1091
|
+
// File viewer request sent
|
|
1087
1092
|
|
|
1088
1093
|
// Wait for response
|
|
1089
1094
|
const result = await responsePromise;
|
|
1090
|
-
|
|
1095
|
+
// File content received successfully
|
|
1091
1096
|
|
|
1092
1097
|
// Hide loading
|
|
1093
1098
|
modal.querySelector('.file-viewer-loading').style.display = 'none';
|
|
@@ -1143,7 +1148,7 @@ async function updateFileViewerModal(modal, filePath, workingDir) {
|
|
|
1143
1148
|
}
|
|
1144
1149
|
|
|
1145
1150
|
function displayFileContent(modal, result) {
|
|
1146
|
-
|
|
1151
|
+
// Display file content in modal
|
|
1147
1152
|
const contentArea = modal.querySelector('.file-viewer-content-area');
|
|
1148
1153
|
const extensionElement = modal.querySelector('.file-extension');
|
|
1149
1154
|
const encodingElement = modal.querySelector('.file-encoding');
|
|
@@ -1157,7 +1162,7 @@ function displayFileContent(modal, result) {
|
|
|
1157
1162
|
|
|
1158
1163
|
// Update content with basic syntax highlighting
|
|
1159
1164
|
if (codeElement && result.content) {
|
|
1160
|
-
|
|
1165
|
+
// Setting file content
|
|
1161
1166
|
codeElement.innerHTML = highlightCode(result.content, result.extension);
|
|
1162
1167
|
|
|
1163
1168
|
// Force scrolling to work by setting explicit heights
|
|
@@ -1175,12 +1180,7 @@ function displayFileContent(modal, result) {
|
|
|
1175
1180
|
|
|
1176
1181
|
const availableHeight = modalHeight - headerHeight - toolbarHeight - 40; // 40px for padding
|
|
1177
1182
|
|
|
1178
|
-
|
|
1179
|
-
modalHeight,
|
|
1180
|
-
headerHeight,
|
|
1181
|
-
toolbarHeight,
|
|
1182
|
-
availableHeight
|
|
1183
|
-
});
|
|
1183
|
+
// Setting file viewer scroll height
|
|
1184
1184
|
|
|
1185
1185
|
wrapper.style.maxHeight = `${availableHeight}px`;
|
|
1186
1186
|
wrapper.style.overflowY = 'auto';
|
|
@@ -1193,7 +1193,7 @@ function displayFileContent(modal, result) {
|
|
|
1193
1193
|
// Show content area
|
|
1194
1194
|
if (contentArea) {
|
|
1195
1195
|
contentArea.style.display = 'block';
|
|
1196
|
-
|
|
1196
|
+
// File content area displayed
|
|
1197
1197
|
}
|
|
1198
1198
|
}
|
|
1199
1199
|
|
|
@@ -1533,7 +1533,7 @@ async function updateGitDiffModal(modal, filePath, timestamp, workingDir) {
|
|
|
1533
1533
|
throw new Error(`Server health check failed: ${healthResponse.status} ${healthResponse.statusText}`);
|
|
1534
1534
|
}
|
|
1535
1535
|
|
|
1536
|
-
|
|
1536
|
+
// Server health check passed
|
|
1537
1537
|
} catch (healthError) {
|
|
1538
1538
|
throw new Error(`Cannot reach server at localhost:${port}. Health check failed: ${healthError.message}`);
|
|
1539
1539
|
}
|
|
@@ -1553,17 +1553,17 @@ async function updateGitDiffModal(modal, filePath, timestamp, workingDir) {
|
|
|
1553
1553
|
}
|
|
1554
1554
|
|
|
1555
1555
|
const result = await response.json();
|
|
1556
|
-
|
|
1556
|
+
// Git diff response received
|
|
1557
1557
|
|
|
1558
1558
|
// Hide loading
|
|
1559
1559
|
modal.querySelector('.git-diff-loading').style.display = 'none';
|
|
1560
1560
|
|
|
1561
1561
|
if (result.success) {
|
|
1562
|
-
|
|
1562
|
+
// Displaying successful git diff
|
|
1563
1563
|
// Show successful diff
|
|
1564
1564
|
displayGitDiff(modal, result);
|
|
1565
1565
|
} else {
|
|
1566
|
-
|
|
1566
|
+
// Displaying git diff error
|
|
1567
1567
|
// Show error
|
|
1568
1568
|
displayGitDiffError(modal, result);
|
|
1569
1569
|
}
|
|
@@ -1661,18 +1661,13 @@ function highlightGitDiff(diffText) {
|
|
|
1661
1661
|
}
|
|
1662
1662
|
|
|
1663
1663
|
function displayGitDiff(modal, result) {
|
|
1664
|
-
|
|
1664
|
+
// Display git diff content
|
|
1665
1665
|
const contentArea = modal.querySelector('.git-diff-content-area');
|
|
1666
1666
|
const commitHashElement = modal.querySelector('.commit-hash');
|
|
1667
1667
|
const methodElement = modal.querySelector('.diff-method');
|
|
1668
1668
|
const codeElement = modal.querySelector('.git-diff-code');
|
|
1669
1669
|
|
|
1670
|
-
|
|
1671
|
-
contentArea: !!contentArea,
|
|
1672
|
-
commitHashElement: !!commitHashElement,
|
|
1673
|
-
methodElement: !!methodElement,
|
|
1674
|
-
codeElement: !!codeElement
|
|
1675
|
-
});
|
|
1670
|
+
// Elements found for diff display
|
|
1676
1671
|
|
|
1677
1672
|
// Update metadata
|
|
1678
1673
|
if (commitHashElement) commitHashElement.textContent = `Commit: ${result.commit_hash}`;
|
|
@@ -1680,7 +1675,7 @@ function displayGitDiff(modal, result) {
|
|
|
1680
1675
|
|
|
1681
1676
|
// Update diff content with basic syntax highlighting
|
|
1682
1677
|
if (codeElement && result.diff) {
|
|
1683
|
-
|
|
1678
|
+
// Setting diff content
|
|
1684
1679
|
codeElement.innerHTML = highlightGitDiff(result.diff);
|
|
1685
1680
|
|
|
1686
1681
|
// Force scrolling to work by setting explicit heights
|
|
@@ -1698,12 +1693,7 @@ function displayGitDiff(modal, result) {
|
|
|
1698
1693
|
|
|
1699
1694
|
const availableHeight = modalHeight - headerHeight - toolbarHeight - 40; // 40px for padding
|
|
1700
1695
|
|
|
1701
|
-
|
|
1702
|
-
modalHeight,
|
|
1703
|
-
headerHeight,
|
|
1704
|
-
toolbarHeight,
|
|
1705
|
-
availableHeight
|
|
1706
|
-
});
|
|
1696
|
+
// Setting explicit scroll height
|
|
1707
1697
|
|
|
1708
1698
|
wrapper.style.maxHeight = `${availableHeight}px`;
|
|
1709
1699
|
wrapper.style.overflowY = 'auto';
|
|
@@ -1716,7 +1706,7 @@ function displayGitDiff(modal, result) {
|
|
|
1716
1706
|
// Show content area
|
|
1717
1707
|
if (contentArea) {
|
|
1718
1708
|
contentArea.style.display = 'block';
|
|
1719
|
-
|
|
1709
|
+
// Content area displayed
|
|
1720
1710
|
}
|
|
1721
1711
|
}
|
|
1722
1712
|
|
|
@@ -425,9 +425,6 @@
|
|
|
425
425
|
<div class="option-group">
|
|
426
426
|
<label>Ignore: <input type="text" id="ignore-patterns" placeholder="test*, *.spec.js, node_modules" class="input-compact" style="width: 200px;"></label>
|
|
427
427
|
</div>
|
|
428
|
-
<div class="option-group">
|
|
429
|
-
<label><input type="checkbox" id="show-hidden-files"> Show hidden files (dotfiles)</label>
|
|
430
|
-
</div>
|
|
431
428
|
</div>
|
|
432
429
|
</div>
|
|
433
430
|
<div id="code-tree-container" class="code-tree-container">
|
|
@@ -513,14 +510,24 @@
|
|
|
513
510
|
</div>
|
|
514
511
|
|
|
515
512
|
<!-- JavaScript Modules -->
|
|
516
|
-
<!-- Load bundled dashboard assets (built with Vite) -->
|
|
517
|
-
<script type="module"
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
513
|
+
<!-- Load bundled dashboard assets (built with Vite) - with timestamp cache busting -->
|
|
514
|
+
<script type="module">
|
|
515
|
+
// Add timestamp-based cache busting to all module imports
|
|
516
|
+
const timestamp = Date.now();
|
|
517
|
+
const modules = [
|
|
518
|
+
'/static/dist/dashboard.js',
|
|
519
|
+
'/static/dist/components/activity-tree.js',
|
|
520
|
+
'/static/dist/components/code-tree.js',
|
|
521
|
+
'/static/dist/components/code-viewer.js'
|
|
522
|
+
];
|
|
523
|
+
|
|
524
|
+
// Dynamically import each module with cache busting
|
|
525
|
+
modules.forEach(modulePath => {
|
|
526
|
+
const script = document.createElement('script');
|
|
527
|
+
script.type = 'module';
|
|
528
|
+
script.src = `${modulePath}?t=${timestamp}`;
|
|
529
|
+
document.body.appendChild(script);
|
|
530
|
+
});
|
|
531
|
+
</script>
|
|
525
532
|
</body>
|
|
526
533
|
</html>
|
|
@@ -190,7 +190,17 @@ class AgentTemplateBuilder:
|
|
|
190
190
|
# Include tools field only if agent is clearly restricted (missing core tools or very few tools)
|
|
191
191
|
include_tools_field = not has_core_tools or len(agent_tools) < 6
|
|
192
192
|
|
|
193
|
-
# Build YAML frontmatter using Claude Code's
|
|
193
|
+
# Build YAML frontmatter using Claude Code's minimal format
|
|
194
|
+
# ONLY include fields that Claude Code recognizes
|
|
195
|
+
#
|
|
196
|
+
# REMOVED FIELDS for Claude Code compatibility:
|
|
197
|
+
# - model, color, version, type, source, author
|
|
198
|
+
# These fields caused Claude Code to silently fail agent discovery
|
|
199
|
+
#
|
|
200
|
+
# CLAUDE CODE COMPATIBLE FORMAT:
|
|
201
|
+
# - name: kebab-case agent name (required)
|
|
202
|
+
# - description: when/why to use this agent (required)
|
|
203
|
+
# - tools: comma-separated tool list (optional, only if restricting)
|
|
194
204
|
frontmatter_lines = [
|
|
195
205
|
"---",
|
|
196
206
|
f"name: {claude_code_name}",
|
|
@@ -203,12 +213,6 @@ class AgentTemplateBuilder:
|
|
|
203
213
|
|
|
204
214
|
frontmatter_lines.extend(
|
|
205
215
|
[
|
|
206
|
-
f"model: {model_type}", # Use explicit model type instead of inherit
|
|
207
|
-
f"color: {color}",
|
|
208
|
-
f"version: {agent_version}",
|
|
209
|
-
f"type: {agent_type}",
|
|
210
|
-
f"source: {source_info}", # Track which source provided this agent
|
|
211
|
-
"author: claude-mpm", # Mark as system-managed agent
|
|
212
216
|
"---",
|
|
213
217
|
"",
|
|
214
218
|
]
|
|
@@ -172,10 +172,18 @@ class SocketIOManager(ISocketIOManager):
|
|
|
172
172
|
|
|
173
173
|
# Check if server already running on this port
|
|
174
174
|
if self.is_server_running(target_port):
|
|
175
|
-
|
|
176
|
-
|
|
175
|
+
# Verify the server is healthy and responding
|
|
176
|
+
if self.wait_for_server(target_port, timeout=2):
|
|
177
|
+
self.logger.info(
|
|
178
|
+
f"Healthy Socket.IO server already running on port {target_port}"
|
|
179
|
+
)
|
|
180
|
+
return True, self.get_server_info(target_port)
|
|
181
|
+
# Server exists but not responding, try to clean it up
|
|
182
|
+
self.logger.warning(
|
|
183
|
+
f"Socket.IO server on port {target_port} not responding, attempting cleanup"
|
|
177
184
|
)
|
|
178
|
-
|
|
185
|
+
self.stop_server(port=target_port, timeout=5)
|
|
186
|
+
# Continue with starting a new server
|
|
179
187
|
|
|
180
188
|
# Ensure dependencies are available
|
|
181
189
|
deps_ok, error_msg = self.ensure_dependencies()
|
|
@@ -459,14 +467,37 @@ class SocketIOManager(ISocketIOManager):
|
|
|
459
467
|
Returns:
|
|
460
468
|
Available port number
|
|
461
469
|
"""
|
|
462
|
-
#
|
|
470
|
+
# First check if our Socket.IO server is already running on the preferred port
|
|
471
|
+
if self.is_server_running(preferred_port):
|
|
472
|
+
# Check if it's healthy
|
|
473
|
+
if self.wait_for_server(preferred_port, timeout=2):
|
|
474
|
+
self.logger.info(
|
|
475
|
+
f"Healthy Socket.IO server already running on port {preferred_port}"
|
|
476
|
+
)
|
|
477
|
+
return preferred_port
|
|
478
|
+
self.logger.warning(
|
|
479
|
+
f"Socket.IO server on port {preferred_port} not responding, will try to restart"
|
|
480
|
+
)
|
|
481
|
+
|
|
482
|
+
# Try preferred port first if available
|
|
463
483
|
if self.port_manager.is_port_available(preferred_port):
|
|
464
484
|
return preferred_port
|
|
465
485
|
|
|
466
|
-
# Find alternative port
|
|
467
|
-
available_port = self.port_manager.
|
|
468
|
-
|
|
469
|
-
|
|
486
|
+
# Find alternative port using the correct method name
|
|
487
|
+
available_port = self.port_manager.find_available_port(
|
|
488
|
+
preferred_port=preferred_port, reclaim=True
|
|
489
|
+
)
|
|
490
|
+
|
|
491
|
+
if available_port:
|
|
492
|
+
self.logger.info(
|
|
493
|
+
f"Port {preferred_port} unavailable, using {available_port}"
|
|
494
|
+
)
|
|
495
|
+
return available_port
|
|
496
|
+
# If no port found, raise an error
|
|
497
|
+
raise RuntimeError(
|
|
498
|
+
f"No available ports in range {self.port_manager.PORT_RANGE.start}-"
|
|
499
|
+
f"{self.port_manager.PORT_RANGE.stop-1}"
|
|
500
|
+
)
|
|
470
501
|
|
|
471
502
|
def ensure_dependencies(self) -> Tuple[bool, Optional[str]]:
|
|
472
503
|
"""
|
|
@@ -30,7 +30,7 @@ For backward compatibility, legacy classes are still available:
|
|
|
30
30
|
"""
|
|
31
31
|
|
|
32
32
|
# Re-export all components from the modular implementation
|
|
33
|
-
from .monitoring import ( # noqa: F401
|
|
33
|
+
from .monitoring import ( # noqa: F401
|
|
34
34
|
AdvancedHealthMonitor,
|
|
35
35
|
HealthChecker,
|
|
36
36
|
HealthCheckResult,
|