claude-mpm 4.21.0__py3-none-any.whl → 5.0.2__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 (497) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_PM.md +12 -0
  3. claude_mpm/agents/OUTPUT_STYLE.md +3 -48
  4. claude_mpm/agents/PM_INSTRUCTIONS.md +632 -334
  5. claude_mpm/agents/WORKFLOW.md +75 -2
  6. claude_mpm/agents/__init__.py +6 -0
  7. claude_mpm/agents/agent_loader.py +1 -4
  8. claude_mpm/agents/base_agent.json +6 -3
  9. claude_mpm/agents/frontmatter_validator.py +1 -1
  10. claude_mpm/agents/templates/{circuit_breakers.md → circuit-breakers.md} +370 -3
  11. claude_mpm/agents/templates/context-management-examples.md +544 -0
  12. claude_mpm/agents/templates/{pm_red_flags.md → pm-red-flags.md} +89 -19
  13. claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
  14. claude_mpm/agents/templates/research-gate-examples.md +669 -0
  15. claude_mpm/agents/templates/structured-questions-examples.md +615 -0
  16. claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
  17. claude_mpm/agents/templates/ticketing-examples.md +277 -0
  18. claude_mpm/cli/__init__.py +38 -2
  19. claude_mpm/cli/commands/agent_source.py +774 -0
  20. claude_mpm/cli/commands/agent_state_manager.py +125 -20
  21. claude_mpm/cli/commands/agents.py +684 -13
  22. claude_mpm/cli/commands/agents_cleanup.py +210 -0
  23. claude_mpm/cli/commands/agents_discover.py +338 -0
  24. claude_mpm/cli/commands/aggregate.py +1 -1
  25. claude_mpm/cli/commands/analyze.py +3 -3
  26. claude_mpm/cli/commands/auto_configure.py +2 -6
  27. claude_mpm/cli/commands/cleanup.py +1 -1
  28. claude_mpm/cli/commands/config.py +7 -4
  29. claude_mpm/cli/commands/configure.py +478 -44
  30. claude_mpm/cli/commands/configure_agent_display.py +4 -4
  31. claude_mpm/cli/commands/configure_navigation.py +63 -46
  32. claude_mpm/cli/commands/debug.py +12 -12
  33. claude_mpm/cli/commands/doctor.py +10 -2
  34. claude_mpm/cli/commands/hook_errors.py +277 -0
  35. claude_mpm/cli/commands/local_deploy.py +1 -4
  36. claude_mpm/cli/commands/mcp_install_commands.py +1 -1
  37. claude_mpm/cli/commands/mpm_init/core.py +50 -2
  38. claude_mpm/cli/commands/mpm_init/git_activity.py +10 -10
  39. claude_mpm/cli/commands/mpm_init/prompts.py +6 -6
  40. claude_mpm/cli/commands/run.py +124 -128
  41. claude_mpm/cli/commands/skill_source.py +694 -0
  42. claude_mpm/cli/commands/skills.py +435 -1
  43. claude_mpm/cli/executor.py +78 -3
  44. claude_mpm/cli/interactive/agent_wizard.py +919 -41
  45. claude_mpm/cli/parsers/agent_source_parser.py +171 -0
  46. claude_mpm/cli/parsers/agents_parser.py +173 -4
  47. claude_mpm/cli/parsers/base_parser.py +49 -0
  48. claude_mpm/cli/parsers/config_parser.py +96 -43
  49. claude_mpm/cli/parsers/skill_source_parser.py +169 -0
  50. claude_mpm/cli/parsers/skills_parser.py +138 -0
  51. claude_mpm/cli/parsers/source_parser.py +138 -0
  52. claude_mpm/cli/startup.py +499 -84
  53. claude_mpm/cli/startup_display.py +480 -0
  54. claude_mpm/cli/utils.py +1 -1
  55. claude_mpm/cli_module/commands.py +1 -1
  56. claude_mpm/commands/{mpm-auto-configure.md → mpm-agents-auto-configure.md} +9 -0
  57. claude_mpm/commands/mpm-agents-detect.md +9 -0
  58. claude_mpm/commands/{mpm-agents.md → mpm-agents-list.md} +9 -0
  59. claude_mpm/commands/mpm-agents-recommend.md +9 -0
  60. claude_mpm/commands/{mpm-config.md → mpm-config-view.md} +9 -0
  61. claude_mpm/commands/mpm-doctor.md +9 -0
  62. claude_mpm/commands/mpm-help.md +14 -2
  63. claude_mpm/commands/mpm-init.md +27 -2
  64. claude_mpm/commands/mpm-monitor.md +9 -0
  65. claude_mpm/commands/mpm-session-resume.md +381 -0
  66. claude_mpm/commands/mpm-status.md +9 -0
  67. claude_mpm/commands/{mpm-organize.md → mpm-ticket-organize.md} +9 -0
  68. claude_mpm/commands/mpm-ticket-view.md +552 -0
  69. claude_mpm/commands/mpm-version.md +9 -0
  70. claude_mpm/commands/mpm.md +11 -0
  71. claude_mpm/config/agent_presets.py +258 -0
  72. claude_mpm/config/agent_sources.py +325 -0
  73. claude_mpm/config/skill_sources.py +590 -0
  74. claude_mpm/constants.py +12 -0
  75. claude_mpm/core/api_validator.py +1 -1
  76. claude_mpm/core/claude_runner.py +17 -10
  77. claude_mpm/core/config.py +24 -0
  78. claude_mpm/core/constants.py +1 -1
  79. claude_mpm/core/framework/__init__.py +3 -16
  80. claude_mpm/core/framework/loaders/instruction_loader.py +25 -5
  81. claude_mpm/core/framework/processors/metadata_processor.py +1 -1
  82. claude_mpm/core/hook_error_memory.py +381 -0
  83. claude_mpm/core/hook_manager.py +41 -2
  84. claude_mpm/core/interactive_session.py +112 -5
  85. claude_mpm/core/logger.py +3 -1
  86. claude_mpm/core/oneshot_session.py +94 -4
  87. claude_mpm/dashboard/static/css/activity.css +69 -69
  88. claude_mpm/dashboard/static/css/connection-status.css +10 -10
  89. claude_mpm/dashboard/static/css/dashboard.css +15 -15
  90. claude_mpm/dashboard/static/js/components/activity-tree.js +178 -178
  91. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +101 -101
  92. claude_mpm/dashboard/static/js/components/agent-inference.js +31 -31
  93. claude_mpm/dashboard/static/js/components/build-tracker.js +59 -59
  94. claude_mpm/dashboard/static/js/components/code-simple.js +107 -107
  95. claude_mpm/dashboard/static/js/components/connection-debug.js +101 -101
  96. claude_mpm/dashboard/static/js/components/diff-viewer.js +113 -113
  97. claude_mpm/dashboard/static/js/components/event-viewer.js +12 -12
  98. claude_mpm/dashboard/static/js/components/file-change-tracker.js +57 -57
  99. claude_mpm/dashboard/static/js/components/file-change-viewer.js +74 -74
  100. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +6 -6
  101. claude_mpm/dashboard/static/js/components/file-viewer.js +42 -42
  102. claude_mpm/dashboard/static/js/components/module-viewer.js +27 -27
  103. claude_mpm/dashboard/static/js/components/session-manager.js +14 -14
  104. claude_mpm/dashboard/static/js/components/socket-manager.js +1 -1
  105. claude_mpm/dashboard/static/js/components/ui-state-manager.js +14 -14
  106. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +110 -110
  107. claude_mpm/dashboard/static/js/components/working-directory.js +8 -8
  108. claude_mpm/dashboard/static/js/connection-manager.js +76 -76
  109. claude_mpm/dashboard/static/js/dashboard.js +76 -58
  110. claude_mpm/dashboard/static/js/extension-error-handler.js +22 -22
  111. claude_mpm/dashboard/static/js/socket-client.js +138 -121
  112. claude_mpm/dashboard/templates/code_simple.html +23 -23
  113. claude_mpm/dashboard/templates/index.html +18 -18
  114. claude_mpm/experimental/cli_enhancements.py +1 -5
  115. claude_mpm/hooks/claude_hooks/event_handlers.py +3 -1
  116. claude_mpm/hooks/claude_hooks/hook_handler.py +24 -7
  117. claude_mpm/hooks/claude_hooks/installer.py +45 -0
  118. claude_mpm/hooks/failure_learning/__init__.py +2 -8
  119. claude_mpm/hooks/failure_learning/failure_detection_hook.py +1 -6
  120. claude_mpm/hooks/failure_learning/fix_detection_hook.py +1 -6
  121. claude_mpm/hooks/failure_learning/learning_extraction_hook.py +1 -6
  122. claude_mpm/hooks/kuzu_response_hook.py +1 -5
  123. claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
  124. claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
  125. claude_mpm/models/git_repository.py +198 -0
  126. claude_mpm/scripts/claude-hook-handler.sh +3 -3
  127. claude_mpm/scripts/start_activity_logging.py +3 -1
  128. claude_mpm/services/agents/agent_builder.py +45 -9
  129. claude_mpm/services/agents/agent_preset_service.py +238 -0
  130. claude_mpm/services/agents/agent_selection_service.py +484 -0
  131. claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
  132. claude_mpm/services/agents/deployment/agent_deployment.py +126 -2
  133. claude_mpm/services/agents/deployment/agent_discovery_service.py +105 -73
  134. claude_mpm/services/agents/deployment/agent_format_converter.py +1 -1
  135. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +1 -5
  136. claude_mpm/services/agents/deployment/agent_metrics_collector.py +3 -3
  137. claude_mpm/services/agents/deployment/agent_restore_handler.py +1 -4
  138. claude_mpm/services/agents/deployment/agent_template_builder.py +236 -15
  139. claude_mpm/services/agents/deployment/agents_directory_resolver.py +101 -15
  140. claude_mpm/services/agents/deployment/async_agent_deployment.py +2 -1
  141. claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -3
  142. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +115 -15
  143. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +2 -2
  144. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +1 -4
  145. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +363 -0
  146. claude_mpm/services/agents/deployment/single_agent_deployer.py +2 -2
  147. claude_mpm/services/agents/deployment/system_instructions_deployer.py +168 -46
  148. claude_mpm/services/agents/deployment/validation/deployment_validator.py +2 -2
  149. claude_mpm/services/agents/git_source_manager.py +629 -0
  150. claude_mpm/services/agents/loading/framework_agent_loader.py +9 -12
  151. claude_mpm/services/agents/local_template_manager.py +50 -10
  152. claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
  153. claude_mpm/services/agents/sources/__init__.py +13 -0
  154. claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
  155. claude_mpm/services/agents/sources/git_source_sync_service.py +1055 -0
  156. claude_mpm/services/agents/startup_sync.py +239 -0
  157. claude_mpm/services/agents/toolchain_detector.py +474 -0
  158. claude_mpm/services/cli/session_pause_manager.py +1 -1
  159. claude_mpm/services/cli/unified_dashboard_manager.py +1 -1
  160. claude_mpm/services/command_deployment_service.py +92 -1
  161. claude_mpm/services/core/base.py +26 -11
  162. claude_mpm/services/core/interfaces/__init__.py +1 -3
  163. claude_mpm/services/core/interfaces/health.py +1 -4
  164. claude_mpm/services/core/models/__init__.py +2 -11
  165. claude_mpm/services/diagnostics/checks/__init__.py +4 -0
  166. claude_mpm/services/diagnostics/checks/agent_check.py +0 -2
  167. claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
  168. claude_mpm/services/diagnostics/checks/instructions_check.py +1 -2
  169. claude_mpm/services/diagnostics/checks/mcp_check.py +0 -1
  170. claude_mpm/services/diagnostics/checks/monitor_check.py +0 -1
  171. claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
  172. claude_mpm/services/diagnostics/diagnostic_runner.py +9 -0
  173. claude_mpm/services/diagnostics/doctor_reporter.py +40 -10
  174. claude_mpm/services/event_bus/direct_relay.py +3 -3
  175. claude_mpm/services/event_bus/event_bus.py +36 -3
  176. claude_mpm/services/event_bus/relay.py +23 -7
  177. claude_mpm/services/events/consumers/logging.py +1 -2
  178. claude_mpm/services/git/__init__.py +21 -0
  179. claude_mpm/services/git/git_operations_service.py +494 -0
  180. claude_mpm/services/github/__init__.py +21 -0
  181. claude_mpm/services/github/github_cli_service.py +397 -0
  182. claude_mpm/services/infrastructure/monitoring/__init__.py +1 -5
  183. claude_mpm/services/infrastructure/monitoring/aggregator.py +1 -6
  184. claude_mpm/services/infrastructure/monitoring/resources.py +1 -1
  185. claude_mpm/services/instructions/__init__.py +9 -0
  186. claude_mpm/services/instructions/instruction_cache_service.py +374 -0
  187. claude_mpm/services/local_ops/__init__.py +3 -13
  188. claude_mpm/services/local_ops/health_checks/__init__.py +1 -3
  189. claude_mpm/services/local_ops/health_manager.py +1 -4
  190. claude_mpm/services/local_ops/process_manager.py +1 -1
  191. claude_mpm/services/local_ops/resource_monitor.py +2 -2
  192. claude_mpm/services/mcp_gateway/config/configuration.py +1 -1
  193. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +1 -6
  194. claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -2
  195. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +1 -1
  196. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +6 -2
  197. claude_mpm/services/memory/failure_tracker.py +19 -4
  198. claude_mpm/services/memory/optimizer.py +1 -1
  199. claude_mpm/services/model/model_router.py +8 -9
  200. claude_mpm/services/monitor/daemon.py +1 -1
  201. claude_mpm/services/monitor/server.py +2 -2
  202. claude_mpm/services/native_agent_converter.py +356 -0
  203. claude_mpm/services/port_manager.py +1 -1
  204. claude_mpm/services/pr/__init__.py +14 -0
  205. claude_mpm/services/pr/pr_template_service.py +329 -0
  206. claude_mpm/services/project/documentation_manager.py +2 -1
  207. claude_mpm/services/project/toolchain_analyzer.py +3 -1
  208. claude_mpm/services/runner_configuration_service.py +1 -0
  209. claude_mpm/services/self_upgrade_service.py +165 -7
  210. claude_mpm/services/skills/__init__.py +18 -0
  211. claude_mpm/services/skills/git_skill_source_manager.py +1169 -0
  212. claude_mpm/services/skills/skill_discovery_service.py +568 -0
  213. claude_mpm/services/skills_config.py +547 -0
  214. claude_mpm/services/skills_deployer.py +955 -0
  215. claude_mpm/services/socketio/handlers/connection.py +1 -1
  216. claude_mpm/services/socketio/handlers/git.py +2 -2
  217. claude_mpm/services/socketio/server/core.py +1 -4
  218. claude_mpm/services/socketio/server/main.py +1 -3
  219. claude_mpm/services/system_instructions_service.py +1 -3
  220. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +0 -3
  221. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +0 -1
  222. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +1 -1
  223. claude_mpm/services/unified/deployment_strategies/vercel.py +1 -5
  224. claude_mpm/services/unified/unified_deployment.py +1 -5
  225. claude_mpm/services/version_control/conflict_resolution.py +6 -4
  226. claude_mpm/services/visualization/__init__.py +1 -5
  227. claude_mpm/services/visualization/mermaid_generator.py +2 -3
  228. claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
  229. claude_mpm/skills/bundled/performance-profiling.md +6 -0
  230. claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +2 -2
  231. claude_mpm/skills/skills_registry.py +0 -1
  232. claude_mpm/templates/questions/__init__.py +38 -0
  233. claude_mpm/templates/questions/base.py +193 -0
  234. claude_mpm/templates/questions/pr_strategy.py +311 -0
  235. claude_mpm/templates/questions/project_init.py +385 -0
  236. claude_mpm/templates/questions/ticket_mgmt.py +394 -0
  237. claude_mpm/tools/__main__.py +8 -8
  238. claude_mpm/tools/code_tree_analyzer/__init__.py +45 -0
  239. claude_mpm/tools/code_tree_analyzer/analysis.py +299 -0
  240. claude_mpm/tools/code_tree_analyzer/cache.py +131 -0
  241. claude_mpm/tools/code_tree_analyzer/core.py +380 -0
  242. claude_mpm/tools/code_tree_analyzer/discovery.py +403 -0
  243. claude_mpm/tools/code_tree_analyzer/events.py +168 -0
  244. claude_mpm/tools/code_tree_analyzer/gitignore.py +308 -0
  245. claude_mpm/tools/code_tree_analyzer/models.py +39 -0
  246. claude_mpm/tools/code_tree_analyzer/multilang_analyzer.py +224 -0
  247. claude_mpm/tools/code_tree_analyzer/python_analyzer.py +284 -0
  248. claude_mpm/utils/agent_dependency_loader.py +80 -13
  249. claude_mpm/utils/dependency_cache.py +3 -1
  250. claude_mpm/utils/gitignore.py +241 -0
  251. claude_mpm/utils/log_cleanup.py +3 -3
  252. claude_mpm/utils/progress.py +383 -0
  253. claude_mpm/utils/robust_installer.py +3 -5
  254. claude_mpm/utils/structured_questions.py +619 -0
  255. {claude_mpm-4.21.0.dist-info → claude_mpm-5.0.2.dist-info}/METADATA +429 -59
  256. {claude_mpm-4.21.0.dist-info → claude_mpm-5.0.2.dist-info}/RECORD +264 -427
  257. claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -17
  258. claude_mpm/agents/templates/.claude-mpm/memories/engineer_memories.md +0 -3
  259. claude_mpm/agents/templates/agent-manager.json +0 -273
  260. claude_mpm/agents/templates/agentic-coder-optimizer.json +0 -248
  261. claude_mpm/agents/templates/api_qa.json +0 -180
  262. claude_mpm/agents/templates/clerk-ops.json +0 -235
  263. claude_mpm/agents/templates/code_analyzer.json +0 -101
  264. claude_mpm/agents/templates/content-agent.json +0 -358
  265. claude_mpm/agents/templates/dart_engineer.json +0 -307
  266. claude_mpm/agents/templates/data_engineer.json +0 -225
  267. claude_mpm/agents/templates/documentation.json +0 -211
  268. claude_mpm/agents/templates/engineer.json +0 -210
  269. claude_mpm/agents/templates/gcp_ops_agent.json +0 -253
  270. claude_mpm/agents/templates/golang_engineer.json +0 -270
  271. claude_mpm/agents/templates/imagemagick.json +0 -264
  272. claude_mpm/agents/templates/java_engineer.json +0 -346
  273. claude_mpm/agents/templates/local_ops_agent.json +0 -1840
  274. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250826_014258_728.md +0 -39
  275. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250901_010124_142.md +0 -400
  276. claude_mpm/agents/templates/memory_manager.json +0 -158
  277. claude_mpm/agents/templates/nextjs_engineer.json +0 -285
  278. claude_mpm/agents/templates/ops.json +0 -185
  279. claude_mpm/agents/templates/php-engineer.json +0 -287
  280. claude_mpm/agents/templates/product_owner.json +0 -338
  281. claude_mpm/agents/templates/project_organizer.json +0 -140
  282. claude_mpm/agents/templates/prompt-engineer.json +0 -737
  283. claude_mpm/agents/templates/python_engineer.json +0 -387
  284. claude_mpm/agents/templates/qa.json +0 -242
  285. claude_mpm/agents/templates/react_engineer.json +0 -238
  286. claude_mpm/agents/templates/refactoring_engineer.json +0 -276
  287. claude_mpm/agents/templates/research.json +0 -188
  288. claude_mpm/agents/templates/ruby-engineer.json +0 -280
  289. claude_mpm/agents/templates/rust_engineer.json +0 -275
  290. claude_mpm/agents/templates/security.json +0 -202
  291. claude_mpm/agents/templates/svelte-engineer.json +0 -225
  292. claude_mpm/agents/templates/ticketing.json +0 -177
  293. claude_mpm/agents/templates/typescript_engineer.json +0 -285
  294. claude_mpm/agents/templates/vercel_ops_agent.json +0 -412
  295. claude_mpm/agents/templates/version_control.json +0 -157
  296. claude_mpm/agents/templates/web_qa.json +0 -399
  297. claude_mpm/agents/templates/web_ui.json +0 -189
  298. claude_mpm/commands/mpm-tickets.md +0 -102
  299. claude_mpm/dashboard/.claude-mpm/socketio-instances.json +0 -1
  300. claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +0 -188
  301. claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +0 -156
  302. claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +0 -38
  303. claude_mpm/dashboard/react/components/shared/FilterBar.module.css +0 -92
  304. claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +0 -248
  305. claude_mpm/dashboard/static/archive/activity_dashboard_test.html +0 -61
  306. claude_mpm/dashboard/static/archive/test_activity_connection.html +0 -179
  307. claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +0 -68
  308. claude_mpm/dashboard/static/archive/test_dashboard.html +0 -409
  309. claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +0 -519
  310. claude_mpm/dashboard/static/archive/test_dashboard_verification.html +0 -181
  311. claude_mpm/dashboard/static/archive/test_file_data.html +0 -315
  312. claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +0 -243
  313. claude_mpm/dashboard/static/archive/test_file_tree_fix.html +0 -234
  314. claude_mpm/dashboard/static/archive/test_file_tree_rename.html +0 -117
  315. claude_mpm/dashboard/static/archive/test_file_tree_tab.html +0 -115
  316. claude_mpm/dashboard/static/archive/test_file_viewer.html +0 -224
  317. claude_mpm/dashboard/static/archive/test_final_activity.html +0 -220
  318. claude_mpm/dashboard/static/archive/test_tab_fix.html +0 -139
  319. claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +0 -1
  320. claude_mpm/dashboard/static/built/components/activity-tree.js +0 -2
  321. claude_mpm/dashboard/static/built/components/agent-hierarchy.js +0 -777
  322. claude_mpm/dashboard/static/built/components/agent-inference.js +0 -2
  323. claude_mpm/dashboard/static/built/components/build-tracker.js +0 -333
  324. claude_mpm/dashboard/static/built/components/code-simple.js +0 -857
  325. claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +0 -353
  326. claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +0 -235
  327. claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +0 -409
  328. claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +0 -435
  329. claude_mpm/dashboard/static/built/components/code-tree.js +0 -2
  330. claude_mpm/dashboard/static/built/components/code-viewer.js +0 -2
  331. claude_mpm/dashboard/static/built/components/connection-debug.js +0 -654
  332. claude_mpm/dashboard/static/built/components/diff-viewer.js +0 -891
  333. claude_mpm/dashboard/static/built/components/event-processor.js +0 -2
  334. claude_mpm/dashboard/static/built/components/event-viewer.js +0 -2
  335. claude_mpm/dashboard/static/built/components/export-manager.js +0 -2
  336. claude_mpm/dashboard/static/built/components/file-change-tracker.js +0 -443
  337. claude_mpm/dashboard/static/built/components/file-change-viewer.js +0 -690
  338. claude_mpm/dashboard/static/built/components/file-tool-tracker.js +0 -2
  339. claude_mpm/dashboard/static/built/components/file-viewer.js +0 -2
  340. claude_mpm/dashboard/static/built/components/hud-library-loader.js +0 -2
  341. claude_mpm/dashboard/static/built/components/hud-manager.js +0 -2
  342. claude_mpm/dashboard/static/built/components/hud-visualizer.js +0 -2
  343. claude_mpm/dashboard/static/built/components/module-viewer.js +0 -2
  344. claude_mpm/dashboard/static/built/components/nav-bar.js +0 -145
  345. claude_mpm/dashboard/static/built/components/page-structure.js +0 -429
  346. claude_mpm/dashboard/static/built/components/session-manager.js +0 -2
  347. claude_mpm/dashboard/static/built/components/socket-manager.js +0 -2
  348. claude_mpm/dashboard/static/built/components/ui-state-manager.js +0 -2
  349. claude_mpm/dashboard/static/built/components/unified-data-viewer.js +0 -2
  350. claude_mpm/dashboard/static/built/components/working-directory.js +0 -2
  351. claude_mpm/dashboard/static/built/connection-manager.js +0 -536
  352. claude_mpm/dashboard/static/built/dashboard.js +0 -2
  353. claude_mpm/dashboard/static/built/extension-error-handler.js +0 -164
  354. claude_mpm/dashboard/static/built/react/events.js +0 -30
  355. claude_mpm/dashboard/static/built/shared/dom-helpers.js +0 -396
  356. claude_mpm/dashboard/static/built/shared/event-bus.js +0 -330
  357. claude_mpm/dashboard/static/built/shared/event-filter-service.js +0 -540
  358. claude_mpm/dashboard/static/built/shared/logger.js +0 -385
  359. claude_mpm/dashboard/static/built/shared/page-structure.js +0 -249
  360. claude_mpm/dashboard/static/built/shared/tooltip-service.js +0 -253
  361. claude_mpm/dashboard/static/built/socket-client.js +0 -2
  362. claude_mpm/dashboard/static/built/tab-isolation-fix.js +0 -185
  363. claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +0 -1
  364. claude_mpm/dashboard/static/dist/components/activity-tree.js +0 -2
  365. claude_mpm/dashboard/static/dist/components/agent-inference.js +0 -2
  366. claude_mpm/dashboard/static/dist/components/code-tree.js +0 -2
  367. claude_mpm/dashboard/static/dist/components/code-viewer.js +0 -2
  368. claude_mpm/dashboard/static/dist/components/event-processor.js +0 -2
  369. claude_mpm/dashboard/static/dist/components/event-viewer.js +0 -2
  370. claude_mpm/dashboard/static/dist/components/export-manager.js +0 -2
  371. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +0 -2
  372. claude_mpm/dashboard/static/dist/components/file-viewer.js +0 -2
  373. claude_mpm/dashboard/static/dist/components/hud-library-loader.js +0 -2
  374. claude_mpm/dashboard/static/dist/components/hud-manager.js +0 -2
  375. claude_mpm/dashboard/static/dist/components/hud-visualizer.js +0 -2
  376. claude_mpm/dashboard/static/dist/components/module-viewer.js +0 -2
  377. claude_mpm/dashboard/static/dist/components/session-manager.js +0 -2
  378. claude_mpm/dashboard/static/dist/components/socket-manager.js +0 -2
  379. claude_mpm/dashboard/static/dist/components/ui-state-manager.js +0 -2
  380. claude_mpm/dashboard/static/dist/components/unified-data-viewer.js +0 -2
  381. claude_mpm/dashboard/static/dist/components/working-directory.js +0 -2
  382. claude_mpm/dashboard/static/dist/dashboard.js +0 -2
  383. claude_mpm/dashboard/static/dist/react/events.js +0 -30
  384. claude_mpm/dashboard/static/dist/socket-client.js +0 -2
  385. claude_mpm/dashboard/static/events.html +0 -607
  386. claude_mpm/dashboard/static/index.html +0 -635
  387. claude_mpm/dashboard/static/js/shared/dom-helpers.js +0 -396
  388. claude_mpm/dashboard/static/js/shared/event-bus.js +0 -330
  389. claude_mpm/dashboard/static/js/shared/logger.js +0 -385
  390. claude_mpm/dashboard/static/js/shared/tooltip-service.js +0 -253
  391. claude_mpm/dashboard/static/js/stores/dashboard-store.js +0 -562
  392. claude_mpm/dashboard/static/legacy/activity.html +0 -736
  393. claude_mpm/dashboard/static/legacy/agents.html +0 -786
  394. claude_mpm/dashboard/static/legacy/files.html +0 -747
  395. claude_mpm/dashboard/static/legacy/tools.html +0 -831
  396. claude_mpm/dashboard/static/monitors.html +0 -431
  397. claude_mpm/dashboard/static/production/events.html +0 -659
  398. claude_mpm/dashboard/static/production/main.html +0 -698
  399. claude_mpm/dashboard/static/production/monitors.html +0 -483
  400. claude_mpm/dashboard/static/test-archive/dashboard.html +0 -635
  401. claude_mpm/dashboard/static/test-archive/debug-events.html +0 -147
  402. claude_mpm/dashboard/static/test-archive/test-navigation.html +0 -256
  403. claude_mpm/dashboard/static/test-archive/test-react-exports.html +0 -180
  404. claude_mpm/dashboard/static/test-archive/test_debug.html +0 -25
  405. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +0 -79
  406. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +0 -178
  407. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +0 -577
  408. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +0 -467
  409. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +0 -537
  410. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +0 -730
  411. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +0 -112
  412. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +0 -146
  413. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +0 -412
  414. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +0 -81
  415. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +0 -362
  416. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +0 -312
  417. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +0 -152
  418. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +0 -668
  419. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +0 -587
  420. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +0 -438
  421. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +0 -391
  422. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +0 -119
  423. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +0 -148
  424. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +0 -483
  425. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +0 -452
  426. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +0 -449
  427. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +0 -411
  428. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +0 -14
  429. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +0 -58
  430. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +0 -68
  431. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +0 -69
  432. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +0 -131
  433. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +0 -325
  434. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +0 -490
  435. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +0 -425
  436. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +0 -499
  437. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +0 -86
  438. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +0 -43
  439. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +0 -47
  440. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +0 -65
  441. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +0 -30
  442. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +0 -16
  443. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +0 -160
  444. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +0 -412
  445. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +0 -602
  446. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +0 -915
  447. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +0 -916
  448. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +0 -752
  449. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +0 -1237
  450. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +0 -189
  451. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +0 -500
  452. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +0 -464
  453. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +0 -619
  454. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +0 -437
  455. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +0 -231
  456. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +0 -170
  457. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +0 -602
  458. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +0 -821
  459. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +0 -742
  460. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +0 -726
  461. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +0 -764
  462. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +0 -831
  463. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +0 -226
  464. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +0 -901
  465. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +0 -901
  466. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +0 -775
  467. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +0 -937
  468. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +0 -770
  469. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +0 -961
  470. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +0 -119
  471. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +0 -253
  472. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +0 -145
  473. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +0 -543
  474. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +0 -741
  475. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +0 -470
  476. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +0 -458
  477. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +0 -639
  478. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +0 -140
  479. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +0 -572
  480. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +0 -411
  481. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +0 -569
  482. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +0 -695
  483. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +0 -184
  484. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +0 -459
  485. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +0 -479
  486. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +0 -687
  487. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +0 -758
  488. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +0 -868
  489. claude_mpm/tools/code_tree_analyzer.py +0 -1825
  490. /claude_mpm/agents/templates/{git_file_tracking.md → git-file-tracking.md} +0 -0
  491. /claude_mpm/agents/templates/{pm_examples.md → pm-examples.md} +0 -0
  492. /claude_mpm/agents/templates/{response_format.md → response-format.md} +0 -0
  493. /claude_mpm/agents/templates/{validation_templates.md → validation-templates.md} +0 -0
  494. {claude_mpm-4.21.0.dist-info → claude_mpm-5.0.2.dist-info}/WHEEL +0 -0
  495. {claude_mpm-4.21.0.dist-info → claude_mpm-5.0.2.dist-info}/entry_points.txt +0 -0
  496. {claude_mpm-4.21.0.dist-info → claude_mpm-5.0.2.dist-info}/licenses/LICENSE +0 -0
  497. {claude_mpm-4.21.0.dist-info → claude_mpm-5.0.2.dist-info}/top_level.txt +0 -0
@@ -1,821 +0,0 @@
1
- # Common Tasks Reference
2
-
3
- ## Scheduled Jobs
4
-
5
- Scheduled jobs run automatically at specified intervals via cron.
6
-
7
- ### Creating a Scheduled Job
8
-
9
- #### Step 1: Define Job in Metadata
10
-
11
- Create `src/files/custom/Espo/Modules/MyModule/Resources/metadata/app/scheduledJobs.json`:
12
-
13
- ```json
14
- {
15
- "MyCustomJob": {
16
- "name": "My Custom Job",
17
- "scheduling": "*/30 * * * *"
18
- },
19
- "DataSyncJob": {
20
- "name": "Sync External Data",
21
- "scheduling": "0 2 * * *"
22
- }
23
- }
24
- ```
25
-
26
- Scheduling format (cron syntax):
27
- ```
28
- * * * * *
29
- │ │ │ │ │
30
- │ │ │ │ └─── Day of week (0-6, Sunday = 0)
31
- │ │ │ └───── Month (1-12)
32
- │ │ └─────── Day of month (1-31)
33
- │ └───────── Hour (0-23)
34
- └─────────── Minute (0-59)
35
- ```
36
-
37
- Common schedules:
38
- - `*/5 * * * *` - Every 5 minutes
39
- - `0 * * * *` - Every hour
40
- - `0 2 * * *` - Daily at 2 AM
41
- - `0 0 * * 0` - Weekly on Sunday at midnight
42
-
43
- #### Step 2: Implement Job Class
44
-
45
- Create `src/files/custom/Espo/Modules/MyModule/Jobs/MyCustomJob.php`:
46
-
47
- ```php
48
- <?php
49
- namespace Espo\Modules\MyModule\Jobs;
50
-
51
- use Espo\Core\Job\JobDataLess;
52
- use Espo\ORM\EntityManager;
53
- use Espo\Core\Utils\Log;
54
-
55
- class MyCustomJob implements JobDataLess
56
- {
57
- public function __construct(
58
- private EntityManager $entityManager,
59
- private Log $log
60
- ) {}
61
-
62
- public function run(): void
63
- {
64
- $this->log->info('MyCustomJob started');
65
-
66
- try {
67
- // Job logic
68
- $this->processRecords();
69
-
70
- $this->log->info('MyCustomJob completed successfully');
71
- } catch (\Throwable $e) {
72
- $this->log->error('MyCustomJob failed: ' . $e->getMessage());
73
- throw $e;
74
- }
75
- }
76
-
77
- private function processRecords(): void
78
- {
79
- $accounts = $this->entityManager
80
- ->getRDBRepository('Account')
81
- ->where([
82
- 'status' => 'Active',
83
- 'lastContactedAt<' => date('Y-m-d', strtotime('-30 days'))
84
- ])
85
- ->find();
86
-
87
- foreach ($accounts as $account) {
88
- $account->set('needsFollowUp', true);
89
- $this->entityManager->saveEntity($account);
90
- }
91
-
92
- $this->log->info('Processed ' . count($accounts) . ' accounts');
93
- }
94
- }
95
- ```
96
-
97
- #### Advanced: Job with Data
98
-
99
- For jobs that need parameters:
100
-
101
- ```php
102
- <?php
103
- namespace Espo\Modules\MyModule\Jobs;
104
-
105
- use Espo\Core\Job\Job;
106
- use Espo\Core\Job\Job\Data;
107
-
108
- class DataSyncJob implements Job
109
- {
110
- public function __construct(
111
- private EntityManager $entityManager,
112
- private Log $log
113
- ) {}
114
-
115
- public function run(Data $data): void
116
- {
117
- $entityType = $data->get('entityType');
118
- $limit = $data->get('limit') ?? 100;
119
-
120
- $this->syncData($entityType, $limit);
121
- }
122
-
123
- private function syncData(string $entityType, int $limit): void
124
- {
125
- // Implementation
126
- }
127
- }
128
- ```
129
-
130
- ### Running Jobs Manually
131
-
132
- ```php
133
- // Via service
134
- use Espo\Core\Job\JobSchedulerFactory;
135
-
136
- class MyService {
137
- public function __construct(
138
- private JobSchedulerFactory $jobSchedulerFactory
139
- ) {}
140
-
141
- public function triggerJob(): void
142
- {
143
- $jobScheduler = $this->jobSchedulerFactory->create();
144
-
145
- $jobScheduler->scheduleJob('MyCustomJob', [
146
- 'entityType' => 'Account',
147
- 'limit' => 50
148
- ]);
149
- }
150
- }
151
- ```
152
-
153
- ## Email Management
154
-
155
- ### Sending Emails
156
-
157
- ```php
158
- <?php
159
- namespace Espo\Modules\MyModule\Services;
160
-
161
- use Espo\Core\Mail\EmailSender;
162
- use Espo\Entities\Email;
163
- use Espo\ORM\EntityManager;
164
-
165
- class NotificationService
166
- {
167
- public function __construct(
168
- private EmailSender $emailSender,
169
- private EntityManager $entityManager
170
- ) {}
171
-
172
- public function sendWelcomeEmail(string $contactId): void
173
- {
174
- $contact = $this->entityManager->getEntityById('Contact', $contactId);
175
-
176
- if (!$contact) {
177
- return;
178
- }
179
-
180
- $emailAddress = $contact->get('emailAddress');
181
-
182
- if (!$emailAddress) {
183
- return;
184
- }
185
-
186
- $sender = $this->emailSender->create();
187
-
188
- $sender
189
- ->withSubject('Welcome to Our Platform')
190
- ->withBody('Dear ' . $contact->get('name') . ',\n\nWelcome!')
191
- ->withTo($emailAddress)
192
- ->send();
193
- }
194
-
195
- public function sendEmailWithTemplate(string $contactId): void
196
- {
197
- $contact = $this->entityManager->getEntityById('Contact', $contactId);
198
-
199
- if (!$contact) {
200
- return;
201
- }
202
-
203
- // Create email entity
204
- $email = $this->entityManager->getNewEntity('Email');
205
-
206
- $email->set([
207
- 'to' => $contact->get('emailAddress'),
208
- 'subject' => 'Welcome',
209
- 'body' => $this->renderTemplate($contact),
210
- 'isHtml' => true,
211
- 'parentType' => 'Contact',
212
- 'parentId' => $contactId
213
- ]);
214
-
215
- $this->entityManager->saveEntity($email);
216
-
217
- // Send
218
- $sender = $this->emailSender->create();
219
- $sender
220
- ->withEnvelopeOptions([
221
- 'from' => 'noreply@example.com'
222
- ])
223
- ->send($email);
224
- }
225
-
226
- private function renderTemplate($contact): string
227
- {
228
- return '<h1>Welcome ' . htmlspecialchars($contact->get('name')) . '</h1>';
229
- }
230
- }
231
- ```
232
-
233
- ### Email Templates
234
-
235
- Create `src/files/custom/Espo/Modules/MyModule/Resources/metadata/app/emailTemplates.json`:
236
-
237
- ```json
238
- {
239
- "welcomeEmail": {
240
- "subject": "Welcome {Contact.name}",
241
- "body": "<p>Dear {Contact.name},</p><p>Welcome to our platform!</p>"
242
- }
243
- }
244
- ```
245
-
246
- Using email templates:
247
-
248
- ```php
249
- use Espo\Tools\EmailTemplate\Processor;
250
-
251
- class EmailService {
252
- public function __construct(
253
- private Processor $emailTemplateProcessor,
254
- private EmailSender $emailSender,
255
- private EntityManager $entityManager
256
- ) {}
257
-
258
- public function sendFromTemplate(string $templateId, string $entityId): void
259
- {
260
- $template = $this->entityManager->getEntityById('EmailTemplate', $templateId);
261
- $entity = $this->entityManager->getEntityById('Contact', $entityId);
262
-
263
- // Process template (replace placeholders)
264
- $data = $this->emailTemplateProcessor->process($template, [
265
- 'entityType' => 'Contact',
266
- 'entity' => $entity
267
- ]);
268
-
269
- // Send
270
- $sender = $this->emailSender->create();
271
- $sender
272
- ->withSubject($data->getSubject())
273
- ->withBody($data->getBody())
274
- ->withTo($entity->get('emailAddress'))
275
- ->withIsHtml($data->isHtml())
276
- ->send();
277
- }
278
- }
279
- ```
280
-
281
- ## PDF Generation
282
-
283
- ### Creating PDF Templates
284
-
285
- PDF templates use HTML with placeholders.
286
-
287
- Create `custom/Espo/Custom/Resources/templates/Invoice.html`:
288
-
289
- ```html
290
- <!DOCTYPE html>
291
- <html>
292
- <head>
293
- <style>
294
- body { font-family: Arial, sans-serif; }
295
- .header { text-align: center; margin-bottom: 30px; }
296
- .invoice-details { margin-bottom: 20px; }
297
- table { width: 100%; border-collapse: collapse; }
298
- th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
299
- th { background-color: #f2f2f2; }
300
- .total { text-align: right; font-weight: bold; }
301
- </style>
302
- </head>
303
- <body>
304
- <div class="header">
305
- <h1>INVOICE</h1>
306
- <p>Invoice #{{number}}</p>
307
- </div>
308
-
309
- <div class="invoice-details">
310
- <p><strong>Date:</strong> {{dateInvoiced}}</p>
311
- <p><strong>Customer:</strong> {{account.name}}</p>
312
- <p><strong>Amount:</strong> {{amount}}</p>
313
- </div>
314
-
315
- <table>
316
- <thead>
317
- <tr>
318
- <th>Item</th>
319
- <th>Quantity</th>
320
- <th>Price</th>
321
- <th>Total</th>
322
- </tr>
323
- </thead>
324
- <tbody>
325
- {{#each items}}
326
- <tr>
327
- <td>{{name}}</td>
328
- <td>{{quantity}}</td>
329
- <td>{{price}}</td>
330
- <td>{{total}}</td>
331
- </tr>
332
- {{/each}}
333
- </tbody>
334
- </table>
335
-
336
- <div class="total">
337
- <p>Total: {{amount}}</p>
338
- </div>
339
- </body>
340
- </html>
341
- ```
342
-
343
- ### Generating PDFs Programmatically
344
-
345
- ```php
346
- <?php
347
- namespace Espo\Modules\MyModule\Services;
348
-
349
- use Espo\Tools\Pdf\Service as PdfService;
350
- use Espo\ORM\EntityManager;
351
-
352
- class InvoiceService
353
- {
354
- public function __construct(
355
- private PdfService $pdfService,
356
- private EntityManager $entityManager
357
- ) {}
358
-
359
- public function generateInvoicePdf(string $invoiceId): string
360
- {
361
- $invoice = $this->entityManager->getEntityById('Invoice', $invoiceId);
362
-
363
- if (!$invoice) {
364
- throw new \Espo\Core\Exceptions\NotFound();
365
- }
366
-
367
- // Generate PDF
368
- $contents = $this->pdfService->generate(
369
- 'Invoice', // Entity type
370
- $invoiceId, // Entity ID
371
- 'Invoice' // Template name
372
- );
373
-
374
- // Save to file
375
- $fileName = 'invoice_' . $invoice->get('number') . '.pdf';
376
- $filePath = 'data/upload/' . $fileName;
377
-
378
- file_put_contents($filePath, $contents);
379
-
380
- return $filePath;
381
- }
382
- }
383
- ```
384
-
385
- ## Access Control (ACL)
386
-
387
- ### Implementing Custom ACL
388
-
389
- Create `src/files/custom/Espo/Modules/MyModule/Acl/MyEntity.php`:
390
-
391
- ```php
392
- <?php
393
- namespace Espo\Modules\MyModule\Acl;
394
-
395
- use Espo\ORM\Entity;
396
- use Espo\Core\Acl\Table;
397
- use Espo\Entities\User;
398
- use Espo\Core\Acl\AccessEntityCREDChecker;
399
- use Espo\Core\Acl\DefaultAccessChecker;
400
- use Espo\Core\Acl\ScopeData;
401
- use Espo\Core\Acl\Traits\DefaultAccessCheckerDependency;
402
-
403
- class MyEntity implements AccessEntityCREDChecker
404
- {
405
- use DefaultAccessCheckerDependency;
406
-
407
- public function __construct(
408
- private DefaultAccessChecker $defaultAccessChecker
409
- ) {}
410
-
411
- public function checkEntityRead(User $user, Entity $entity, ScopeData $data): bool
412
- {
413
- // Custom read permission logic
414
-
415
- // Check if user is assigned
416
- if ($entity->get('assignedUserId') === $user->getId()) {
417
- return true;
418
- }
419
-
420
- // Check if user is in account team
421
- if ($entity->get('accountId')) {
422
- $account = $entity->get('account');
423
- if ($this->isUserInAccountTeams($user, $account)) {
424
- return true;
425
- }
426
- }
427
-
428
- // Fall back to default ACL check
429
- return $this->defaultAccessChecker->checkEntityRead($user, $entity, $data);
430
- }
431
-
432
- public function checkEntityCreate(User $user, Entity $entity, ScopeData $data): bool
433
- {
434
- // Custom create permission logic
435
- if ($user->get('type') === 'portal') {
436
- // Portal users can only create if they have an account
437
- return $entity->get('accountId') !== null;
438
- }
439
-
440
- return $this->defaultAccessChecker->checkEntityCreate($user, $entity, $data);
441
- }
442
-
443
- public function checkEntityEdit(User $user, Entity $entity, ScopeData $data): bool
444
- {
445
- // Custom edit permission logic
446
-
447
- // Only owner can edit after 7 days
448
- $createdAt = $entity->get('createdAt');
449
- if ($createdAt) {
450
- $daysSinceCreation = (time() - strtotime($createdAt)) / 86400;
451
-
452
- if ($daysSinceCreation > 7) {
453
- if ($entity->get('createdById') !== $user->getId()) {
454
- return false;
455
- }
456
- }
457
- }
458
-
459
- return $this->defaultAccessChecker->checkEntityEdit($user, $entity, $data);
460
- }
461
-
462
- public function checkEntityDelete(User $user, Entity $entity, ScopeData $data): bool
463
- {
464
- // Custom delete permission logic
465
-
466
- // Prevent deletion of completed items
467
- if ($entity->get('status') === 'Complete') {
468
- return false;
469
- }
470
-
471
- return $this->defaultAccessChecker->checkEntityDelete($user, $entity, $data);
472
- }
473
-
474
- private function isUserInAccountTeams(User $user, ?Entity $account): bool
475
- {
476
- if (!$account) {
477
- return false;
478
- }
479
-
480
- $userTeamIds = array_column($user->get('teams')->toArray(), 'id');
481
- $accountTeamIds = array_column($account->get('teams')->toArray(), 'id');
482
-
483
- return !empty(array_intersect($userTeamIds, $accountTeamIds));
484
- }
485
- }
486
- ```
487
-
488
- ### Checking ACL in Code
489
-
490
- ```php
491
- // Check entity-level permission
492
- if (!$this->acl->check($entity, 'read')) {
493
- throw new Forbidden();
494
- }
495
-
496
- // Check scope-level permission
497
- if (!$this->acl->check('Account', 'create')) {
498
- throw new Forbidden();
499
- }
500
-
501
- // Check field-level permission
502
- if (!$this->acl->checkField('Account', 'billingAddress', 'edit')) {
503
- throw new Forbidden('Cannot edit billing address');
504
- }
505
-
506
- // Check ownership level
507
- $level = $this->acl->getLevel('Account', 'read');
508
- // Levels: all, team, own, no
509
-
510
- // Filter query by ACL
511
- $query = $this->entityManager
512
- ->getQueryBuilder()
513
- ->select()
514
- ->from('Account')
515
- ->build();
516
-
517
- $this->acl->applyFilter($query, 'Account', 'read');
518
- ```
519
-
520
- ## Workflow Customization
521
-
522
- ### Custom Workflow Action
523
-
524
- Create `src/files/custom/Espo/Modules/MyModule/Classes/Workflow/Actions/SendSlackNotification.php`:
525
-
526
- ```php
527
- <?php
528
- namespace Espo\Modules\MyModule\Classes\Workflow\Actions;
529
-
530
- use Espo\Core\Workflow\Action;
531
- use Espo\Core\Workflow\Action\Params;
532
- use Espo\ORM\Entity;
533
-
534
- class SendSlackNotification implements Action
535
- {
536
- public function __construct(
537
- private SlackClient $slackClient
538
- ) {}
539
-
540
- public function run(Entity $entity, Params $params): bool
541
- {
542
- $channel = $params->get('channel') ?? '#general';
543
- $message = $params->get('message') ?? 'Entity updated';
544
-
545
- // Replace placeholders
546
- $message = str_replace('{name}', $entity->get('name'), $message);
547
-
548
- $this->slackClient->sendMessage($channel, $message);
549
-
550
- return true;
551
- }
552
- }
553
- ```
554
-
555
- ### Custom Workflow Condition
556
-
557
- Create `src/files/custom/Espo/Modules/MyModule/Classes/Workflow/Conditions/IsHighValue.php`:
558
-
559
- ```php
560
- <?php
561
- namespace Espo\Modules\MyModule\Classes\Workflow\Conditions;
562
-
563
- use Espo\Core\Workflow\Condition;
564
- use Espo\Core\Workflow\Condition\Params;
565
- use Espo\ORM\Entity;
566
-
567
- class IsHighValue implements Condition
568
- {
569
- public function check(Entity $entity, Params $params): bool
570
- {
571
- $threshold = $params->get('threshold') ?? 10000;
572
- $amount = $entity->get('amount') ?? 0;
573
-
574
- return $amount >= $threshold;
575
- }
576
- }
577
- ```
578
-
579
- ## Integration Patterns
580
-
581
- ### REST API Integration
582
-
583
- ```php
584
- <?php
585
- namespace Espo\Modules\MyModule\Services;
586
-
587
- use Espo\Core\Utils\Config;
588
- use Espo\Core\Utils\Log;
589
-
590
- class ExternalApiService
591
- {
592
- private string $apiUrl;
593
- private string $apiKey;
594
-
595
- public function __construct(
596
- private Config $config,
597
- private Log $log
598
- ) {
599
- $this->apiUrl = $this->config->get('externalApiUrl');
600
- $this->apiKey = $this->config->get('externalApiKey');
601
- }
602
-
603
- public function fetchCustomerData(string $customerId): ?array
604
- {
605
- $url = $this->apiUrl . '/customers/' . $customerId;
606
-
607
- $ch = curl_init();
608
-
609
- curl_setopt_array($ch, [
610
- CURLOPT_URL => $url,
611
- CURLOPT_RETURNTRANSFER => true,
612
- CURLOPT_HTTPHEADER => [
613
- 'Authorization: Bearer ' . $this->apiKey,
614
- 'Content-Type: application/json'
615
- ]
616
- ]);
617
-
618
- $response = curl_exec($ch);
619
- $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
620
-
621
- curl_close($ch);
622
-
623
- if ($httpCode !== 200) {
624
- $this->log->error('External API request failed: ' . $httpCode);
625
- return null;
626
- }
627
-
628
- return json_decode($response, true);
629
- }
630
-
631
- public function syncCustomer(Entity $account): bool
632
- {
633
- $data = [
634
- 'name' => $account->get('name'),
635
- 'email' => $account->get('emailAddress'),
636
- 'phone' => $account->get('phoneNumber')
637
- ];
638
-
639
- $url = $this->apiUrl . '/customers';
640
-
641
- $ch = curl_init();
642
-
643
- curl_setopt_array($ch, [
644
- CURLOPT_URL => $url,
645
- CURLOPT_RETURNTRANSFER => true,
646
- CURLOPT_POST => true,
647
- CURLOPT_POSTFIELDS => json_encode($data),
648
- CURLOPT_HTTPHEADER => [
649
- 'Authorization: Bearer ' . $this->apiKey,
650
- 'Content-Type: application/json'
651
- ]
652
- ]);
653
-
654
- $response = curl_exec($ch);
655
- $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
656
-
657
- curl_close($ch);
658
-
659
- if ($httpCode === 201) {
660
- $responseData = json_decode($response, true);
661
- $account->set('externalId', $responseData['id']);
662
- return true;
663
- }
664
-
665
- $this->log->error('Failed to sync customer: ' . $httpCode);
666
- return false;
667
- }
668
- }
669
- ```
670
-
671
- ### Webhook Handler
672
-
673
- ```php
674
- <?php
675
- namespace Espo\Modules\MyModule\Controllers;
676
-
677
- use Espo\Core\Api\Request;
678
- use Espo\Core\Api\Response;
679
- use Espo\Core\Controllers\Base;
680
- use Espo\Core\Exceptions\BadRequest;
681
-
682
- class Webhook extends Base
683
- {
684
- public function postActionReceive(Request $request, Response $response): bool
685
- {
686
- $data = $request->getParsedBody();
687
-
688
- if (!$data->event) {
689
- throw new BadRequest('Missing event type');
690
- }
691
-
692
- // Verify webhook signature
693
- $signature = $request->getHeader('X-Webhook-Signature');
694
- if (!$this->verifySignature($signature, $request->getBodyContents())) {
695
- throw new Forbidden('Invalid signature');
696
- }
697
-
698
- // Process webhook
699
- $service = $this->getRecordService('WebhookEvent');
700
- $service->processWebhook($data->event, $data);
701
-
702
- $response->setStatus(200);
703
- return true;
704
- }
705
-
706
- private function verifySignature(?string $signature, string $payload): bool
707
- {
708
- if (!$signature) {
709
- return false;
710
- }
711
-
712
- $secret = $this->config->get('webhookSecret');
713
- $expectedSignature = hash_hmac('sha256', $payload, $secret);
714
-
715
- return hash_equals($expectedSignature, $signature);
716
- }
717
- }
718
- ```
719
-
720
- ## File Handling
721
-
722
- ### File Upload and Storage
723
-
724
- ```php
725
- <?php
726
- namespace Espo\Modules\MyModule\Services;
727
-
728
- use Espo\Core\FileStorage\Manager as FileStorageManager;
729
- use Espo\Entities\Attachment;
730
-
731
- class DocumentService
732
- {
733
- public function __construct(
734
- private FileStorageManager $fileStorageManager,
735
- private EntityManager $entityManager
736
- ) {}
737
-
738
- public function uploadFile(string $filePath, string $name, string $type): Attachment
739
- {
740
- $contents = file_get_contents($filePath);
741
-
742
- $attachment = $this->entityManager->getNewEntity('Attachment');
743
- $attachment->set([
744
- 'name' => $name,
745
- 'type' => $type,
746
- 'size' => strlen($contents),
747
- 'role' => 'Attachment'
748
- ]);
749
-
750
- $this->entityManager->saveEntity($attachment);
751
-
752
- // Store file
753
- $this->fileStorageManager->putContents($attachment, $contents);
754
-
755
- return $attachment;
756
- }
757
-
758
- public function getFileContents(string $attachmentId): ?string
759
- {
760
- $attachment = $this->entityManager->getEntityById('Attachment', $attachmentId);
761
-
762
- if (!$attachment) {
763
- return null;
764
- }
765
-
766
- return $this->fileStorageManager->getContents($attachment);
767
- }
768
- }
769
- ```
770
-
771
- ## Custom Entry Points
772
-
773
- Entry points are public endpoints (no authentication required).
774
-
775
- ```php
776
- <?php
777
- namespace Espo\Modules\MyModule\EntryPoints;
778
-
779
- use Espo\Core\EntryPoint\EntryPoint;
780
- use Espo\Core\Api\Request;
781
- use Espo\Core\Api\Response;
782
-
783
- class PublicDownload implements EntryPoint
784
- {
785
- public function run(Request $request, Response $response): void
786
- {
787
- $id = $request->getQueryParam('id');
788
-
789
- if (!$id) {
790
- $response->setStatus(400);
791
- return;
792
- }
793
-
794
- // Fetch file
795
- $attachment = $this->entityManager->getEntityById('Attachment', $id);
796
-
797
- if (!$attachment || !$attachment->get('isPublic')) {
798
- $response->setStatus(404);
799
- return;
800
- }
801
-
802
- // Serve file
803
- $contents = $this->fileStorageManager->getContents($attachment);
804
-
805
- $response->setHeader('Content-Type', $attachment->get('type'));
806
- $response->setHeader('Content-Disposition', 'attachment; filename="' . $attachment->get('name') . '"');
807
- $response->writeBody($contents);
808
- }
809
- }
810
- ```
811
-
812
- Register in metadata (`app/entryPoints.json`):
813
- ```json
814
- {
815
- "publicDownload": {
816
- "className": "Espo\\Modules\\MyModule\\EntryPoints\\PublicDownload"
817
- }
818
- }
819
- ```
820
-
821
- Access via: `?entryPoint=publicDownload&id=ATTACHMENT_ID`