claude-flow-novice 1.6.3 → 1.6.5

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 (290) hide show
  1. package/.claude/commands/parse-epic.js +180 -0
  2. package/.claude/settings.json +12 -2
  3. package/.claude/settings.local.json +4 -2
  4. package/.claude-flow-novice/dist/mcp/mcp-server-novice.js +37 -2
  5. package/.claude-flow-novice/dist/mcp/transports/base.js +5 -0
  6. package/.claude-flow-novice/dist/mcp/transports/base.js.map +1 -0
  7. package/.claude-flow-novice/dist/mcp/transports/http.js +414 -0
  8. package/.claude-flow-novice/dist/mcp/transports/http.js.map +1 -0
  9. package/.claude-flow-novice/dist/mcp/transports/stdio.js +217 -0
  10. package/.claude-flow-novice/dist/mcp/transports/stdio.js.map +1 -0
  11. package/.claude-flow-novice/dist/src/cli/commands/parse-epic.js +129 -0
  12. package/.claude-flow-novice/dist/src/cli/commands/parse-epic.js.map +1 -0
  13. package/.claude-flow-novice/dist/src/cli/index.js +3 -0
  14. package/.claude-flow-novice/dist/src/cli/index.js.map +1 -1
  15. package/.claude-flow-novice/dist/src/cli/utils/epic-parser.js +266 -0
  16. package/.claude-flow-novice/dist/src/cli/utils/epic-parser.js.map +1 -0
  17. package/.claude-flow-novice/dist/src/communication/message-bus.js +105 -2
  18. package/.claude-flow-novice/dist/src/communication/message-bus.js.map +1 -1
  19. package/.claude-flow-novice/dist/src/coordination/adapters/v1-coordinator-adapter.js +1 -1
  20. package/.claude-flow-novice/dist/src/coordination/adapters/v1-coordinator-adapter.js.map +1 -1
  21. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/cache/artifact-cache-optimizer.js +632 -0
  22. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/cache/artifact-cache-optimizer.js.map +1 -0
  23. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/cache/index.js +11 -0
  24. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/cache/index.js.map +1 -0
  25. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/checkpoints/checkpoint-compressor.js +318 -0
  26. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/checkpoints/checkpoint-compressor.js.map +1 -0
  27. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/completion/completion-detector.js +234 -0
  28. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/completion/completion-detector.js.map +1 -0
  29. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/completion/hierarchical-detector.js +347 -0
  30. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/completion/hierarchical-detector.js.map +1 -0
  31. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/completion/index.js +13 -0
  32. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/completion/index.js.map +1 -0
  33. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/completion/lamport-clock.js +173 -0
  34. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/completion/lamport-clock.js.map +1 -0
  35. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/completion/mesh-detector.js +526 -0
  36. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/completion/mesh-detector.js.map +1 -0
  37. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/completion/sdk-completion-detector.js +443 -0
  38. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/completion/sdk-completion-detector.js.map +1 -0
  39. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/completion/swarm-shutdown.js +366 -0
  40. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/completion/swarm-shutdown.js.map +1 -0
  41. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/coordinator-factory.js +287 -0
  42. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/coordinator-factory.js.map +1 -0
  43. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/coordinators/cascading-shutdown.example.js +364 -0
  44. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/coordinators/cascading-shutdown.example.js.map +1 -0
  45. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/coordinators/cascading-shutdown.js +492 -0
  46. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/coordinators/cascading-shutdown.js.map +1 -0
  47. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/coordinators/hierarchical-coordinator.js +786 -0
  48. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/coordinators/hierarchical-coordinator.js.map +1 -0
  49. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/coordinators/index.js +16 -0
  50. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/coordinators/index.js.map +1 -0
  51. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/coordinators/parent-child-manager.js +342 -0
  52. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/coordinators/parent-child-manager.js.map +1 -0
  53. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/coordinators/swarm-coordinator-v2.js +601 -0
  54. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/coordinators/swarm-coordinator-v2.js.map +1 -0
  55. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/agent-state.js +9 -0
  56. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/agent-state.js.map +1 -0
  57. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/dead-letter-queue.js +413 -0
  58. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/dead-letter-queue.js.map +1 -0
  59. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/dependency-graph.js +471 -0
  60. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/dependency-graph.js.map +1 -0
  61. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/dependency-node.js +379 -0
  62. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/dependency-node.js.map +1 -0
  63. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/dependency-resolver.js +335 -0
  64. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/dependency-resolver.js.map +1 -0
  65. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/help-request-metrics.js +211 -0
  66. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/help-request-metrics.js.map +1 -0
  67. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/index.js +33 -0
  68. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/index.js.map +1 -0
  69. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/message-broker.js +920 -0
  70. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/message-broker.js.map +1 -0
  71. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/message-router.js +385 -0
  72. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/message-router.js.map +1 -0
  73. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/message.js +138 -0
  74. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/message.js.map +1 -0
  75. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/resource-manager-safe.js +478 -0
  76. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/resource-manager-safe.js.map +1 -0
  77. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/state-machine-config.js +358 -0
  78. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/state-machine-config.js.map +1 -0
  79. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/state-machine.js +588 -0
  80. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/state-machine.js.map +1 -0
  81. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/state-transition.js +153 -0
  82. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/state-transition.js.map +1 -0
  83. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/task-scheduler.js +360 -0
  84. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/task-scheduler.js.map +1 -0
  85. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/topic-manager.js +337 -0
  86. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/core/topic-manager.js.map +1 -0
  87. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/deadlock/deadlock-detector.js +424 -0
  88. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/deadlock/deadlock-detector.js.map +1 -0
  89. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/deadlock/index.js +9 -0
  90. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/deadlock/index.js.map +1 -0
  91. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/deadlock/resource-manager.js +669 -0
  92. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/deadlock/resource-manager.js.map +1 -0
  93. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/dependency/artifact-storage.js +451 -0
  94. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/dependency/artifact-storage.js.map +1 -0
  95. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/dependency/cycle-detector.js +271 -0
  96. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/dependency/cycle-detector.js.map +1 -0
  97. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/dependency/dependency-graph.js +335 -0
  98. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/dependency/dependency-graph.js.map +1 -0
  99. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/dependency/dependency-manager.js +439 -0
  100. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/dependency/dependency-manager.js.map +1 -0
  101. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/dependency/dependency-request.js +92 -0
  102. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/dependency/dependency-request.js.map +1 -0
  103. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/dependency/index.js +21 -0
  104. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/dependency/index.js.map +1 -0
  105. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/dependency/topological-sort.js +223 -0
  106. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/dependency/topological-sort.js.map +1 -0
  107. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/help-system/help-coordinator.js +436 -0
  108. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/help-system/help-coordinator.js.map +1 -0
  109. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/help-system/help-matcher.js +278 -0
  110. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/help-system/help-matcher.js.map +1 -0
  111. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/help-system/help-request-handler.js +317 -0
  112. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/help-system/help-request-handler.js.map +1 -0
  113. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/help-system/help-request.js +273 -0
  114. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/help-system/help-request.js.map +1 -0
  115. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/help-system/index.js +15 -0
  116. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/help-system/index.js.map +1 -0
  117. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/help-system/waiting-agent-pool.js +512 -0
  118. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/help-system/waiting-agent-pool.js.map +1 -0
  119. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/index.js +67 -0
  120. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/index.js.map +1 -0
  121. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/integration/help-deadlock-integration.js +557 -0
  122. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/integration/help-deadlock-integration.js.map +1 -0
  123. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/integration/index.js +14 -0
  124. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/integration/index.js.map +1 -0
  125. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/integration/message-bus-completion-integration.example.js +212 -0
  126. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/integration/message-bus-completion-integration.example.js.map +1 -0
  127. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/integration/message-bus-completion-integration.js +552 -0
  128. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/integration/message-bus-completion-integration.js.map +1 -0
  129. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/integration/state-machine-integration.js +635 -0
  130. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/integration/state-machine-integration.js.map +1 -0
  131. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/interfaces/IArtifactStorage.js +28 -0
  132. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/interfaces/IArtifactStorage.js.map +1 -0
  133. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/interfaces/ICoordinator.js +9 -0
  134. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/interfaces/ICoordinator.js.map +1 -0
  135. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/interfaces/ISessionStore.js +25 -0
  136. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/interfaces/ISessionStore.js.map +1 -0
  137. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/interfaces/index.js +14 -0
  138. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/interfaces/index.js.map +1 -0
  139. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/memory/artifact-adapter.js +308 -0
  140. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/memory/artifact-adapter.js.map +1 -0
  141. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/memory/completion-storage.js +439 -0
  142. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/memory/completion-storage.js.map +1 -0
  143. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/memory/dependency-graph-storage.js +540 -0
  144. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/memory/dependency-graph-storage.js.map +1 -0
  145. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/memory/dependency-storage.js +367 -0
  146. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/memory/dependency-storage.js.map +1 -0
  147. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/memory/index.js +14 -0
  148. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/memory/index.js.map +1 -0
  149. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/memory/message-storage.js +518 -0
  150. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/memory/message-storage.js.map +1 -0
  151. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/memory/state-storage.js +377 -0
  152. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/memory/state-storage.js.map +1 -0
  153. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/messaging/channel.js +371 -0
  154. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/messaging/channel.js.map +1 -0
  155. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/messaging/channels/dependency-channel.js +355 -0
  156. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/messaging/channels/dependency-channel.js.map +1 -0
  157. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/messaging/channels/help-channel.js +424 -0
  158. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/messaging/channels/help-channel.js.map +1 -0
  159. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/messaging/channels/index.js +16 -0
  160. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/messaging/channels/index.js.map +1 -0
  161. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/messaging/channels/state-channel.js +295 -0
  162. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/messaging/channels/state-channel.js.map +1 -0
  163. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/messaging/channels/task-channel.js +411 -0
  164. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/messaging/channels/task-channel.js.map +1 -0
  165. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/messaging/index.js +14 -0
  166. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/messaging/index.js.map +1 -0
  167. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/messaging/message-bus.js +387 -0
  168. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/messaging/message-bus.js.map +1 -0
  169. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/messaging/message-persistence.js +589 -0
  170. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/messaging/message-persistence.js.map +1 -0
  171. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/messaging/message-router.js +444 -0
  172. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/messaging/message-router.js.map +1 -0
  173. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/artifact-storage.js +560 -0
  174. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/artifact-storage.js.map +1 -0
  175. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/background-orchestrator.js +335 -0
  176. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/background-orchestrator.js.map +1 -0
  177. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/bash-output-monitor.js +104 -0
  178. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/bash-output-monitor.js.map +1 -0
  179. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/checkpoint-manager.js +847 -0
  180. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/checkpoint-manager.js.map +1 -0
  181. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/help-coordinator.js +470 -0
  182. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/help-coordinator.js.map +1 -0
  183. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/hierarchical-background-integration.js +450 -0
  184. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/hierarchical-background-integration.js.map +1 -0
  185. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/index.js +13 -0
  186. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/index.js.map +1 -0
  187. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/message-bus-integration.js +625 -0
  188. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/message-bus-integration.js.map +1 -0
  189. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/multi-level-control.js +545 -0
  190. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/multi-level-control.js.map +1 -0
  191. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/query-controller.js +740 -0
  192. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/query-controller.js.map +1 -0
  193. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/query-message-integration.js +415 -0
  194. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/query-message-integration.js.map +1 -0
  195. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/session-pool-optimizer.js +615 -0
  196. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/session-pool-optimizer.js.map +1 -0
  197. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/state-machine-integration.js +547 -0
  198. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/state-machine-integration.js.map +1 -0
  199. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/state-sdk-integration.js +342 -0
  200. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/sdk/state-sdk-integration.js.map +1 -0
  201. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/security/payload-validator.js +259 -0
  202. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/security/payload-validator.js.map +1 -0
  203. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/truth/framework-registry.js +273 -0
  204. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/truth/framework-registry.js.map +1 -0
  205. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/truth/index.js +8 -0
  206. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/truth/index.js.map +1 -0
  207. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/truth/truth-config-manager.js +310 -0
  208. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/truth/truth-config-manager.js.map +1 -0
  209. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/truth/truth-validator.js +218 -0
  210. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/truth/truth-validator.js.map +1 -0
  211. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/types/sdk.js +9 -0
  212. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/types/sdk.js.map +1 -0
  213. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/utils/index.js +6 -0
  214. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/utils/index.js.map +1 -0
  215. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/utils/priority-queue.js +145 -0
  216. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/utils/priority-queue.js.map +1 -0
  217. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/utils/sdk-helpers.js +122 -0
  218. package/.claude-flow-novice/dist/src/coordination/archives/v2-sdk-typescript/v2/utils/sdk-helpers.js.map +1 -0
  219. package/.claude-flow-novice/dist/src/coordination/config-translator.js +17 -43
  220. package/.claude-flow-novice/dist/src/coordination/config-translator.js.map +1 -1
  221. package/.claude-flow-novice/dist/src/coordination/coordination-toggle.js +34 -76
  222. package/.claude-flow-novice/dist/src/coordination/coordination-toggle.js.map +1 -1
  223. package/.claude-flow-novice/dist/src/coordination/index.js +3 -0
  224. package/.claude-flow-novice/dist/src/coordination/index.js.map +1 -1
  225. package/.claude-flow-novice/dist/src/coordination/shared/core/agent-state.js +172 -0
  226. package/.claude-flow-novice/dist/src/coordination/shared/core/agent-state.js.map +1 -0
  227. package/.claude-flow-novice/dist/src/coordination/shared/core/index.js +7 -0
  228. package/.claude-flow-novice/dist/src/coordination/shared/core/index.js.map +1 -0
  229. package/.claude-flow-novice/dist/src/coordination/shared/index.js +19 -0
  230. package/.claude-flow-novice/dist/src/coordination/shared/index.js.map +1 -0
  231. package/.claude-flow-novice/dist/src/coordination/shared/interfaces/ICoordinator.js +24 -0
  232. package/.claude-flow-novice/dist/src/coordination/shared/interfaces/ICoordinator.js.map +1 -0
  233. package/.claude-flow-novice/dist/src/coordination/shared/interfaces/index.js +7 -0
  234. package/.claude-flow-novice/dist/src/coordination/shared/interfaces/index.js.map +1 -0
  235. package/.claude-flow-novice/dist/src/coordination/shared/message-broker.js +920 -0
  236. package/.claude-flow-novice/dist/src/coordination/shared/message-broker.js.map +1 -0
  237. package/.claude-flow-novice/dist/src/coordination/shared/message.js +138 -0
  238. package/.claude-flow-novice/dist/src/coordination/shared/message.js.map +1 -0
  239. package/.claude-flow-novice/dist/src/coordination/shared/security/payload-validator.js +259 -0
  240. package/.claude-flow-novice/dist/src/coordination/shared/security/payload-validator.js.map +1 -0
  241. package/.claude-flow-novice/dist/src/coordination/shared/transparency/index.js +17 -0
  242. package/.claude-flow-novice/dist/src/coordination/shared/transparency/index.js.map +1 -0
  243. package/.claude-flow-novice/dist/src/coordination/shared/transparency/interfaces/transparency-system.js +19 -0
  244. package/.claude-flow-novice/dist/src/coordination/shared/transparency/interfaces/transparency-system.js.map +1 -0
  245. package/.claude-flow-novice/dist/src/coordination/shared/transparency/transparency-integration.js +357 -0
  246. package/.claude-flow-novice/dist/src/coordination/shared/transparency/transparency-integration.js.map +1 -0
  247. package/.claude-flow-novice/dist/src/coordination/shared/transparency/transparency-system.js +679 -0
  248. package/.claude-flow-novice/dist/src/coordination/shared/transparency/transparency-system.js.map +1 -0
  249. package/.claude-flow-novice/dist/src/coordination/shared/types/index.js +7 -0
  250. package/.claude-flow-novice/dist/src/coordination/shared/types/index.js.map +1 -0
  251. package/.claude-flow-novice/dist/src/coordination/shared/types/sdk.js +10 -0
  252. package/.claude-flow-novice/dist/src/coordination/shared/types/sdk.js.map +1 -0
  253. package/.claude-flow-novice/dist/src/coordination/v1-transparency/interfaces/v1-transparency-system.js +12 -0
  254. package/.claude-flow-novice/dist/src/coordination/v1-transparency/interfaces/v1-transparency-system.js.map +1 -0
  255. package/.claude-flow-novice/dist/src/coordination/v1-transparency/v1-to-v2-bridge.js +433 -0
  256. package/.claude-flow-novice/dist/src/coordination/v1-transparency/v1-to-v2-bridge.js.map +1 -0
  257. package/.claude-flow-novice/dist/src/coordination/v1-transparency/v1-transparency-adapter.js +1468 -0
  258. package/.claude-flow-novice/dist/src/coordination/v1-transparency/v1-transparency-adapter.js.map +1 -0
  259. package/.claude-flow-novice/dist/src/feature-flags/core/FeatureFlagManager.js +52 -2
  260. package/.claude-flow-novice/dist/src/feature-flags/core/FeatureFlagManager.js.map +1 -1
  261. package/.claude-flow-novice/dist/src/mcp/mcp-server-novice.js +37 -2
  262. package/.claude-flow-novice/dist/src/mcp/session-manager.js +3 -1
  263. package/.claude-flow-novice/dist/src/mcp/session-manager.js.map +1 -1
  264. package/.claude-flow-novice/dist/src/monitoring/apm/apm-integration.js +5 -0
  265. package/.claude-flow-novice/dist/src/monitoring/apm/apm-integration.js.map +1 -1
  266. package/.claude-flow-novice/dist/src/providers/provider-manager.js +41 -6
  267. package/.claude-flow-novice/dist/src/providers/provider-manager.js.map +1 -1
  268. package/.claude-flow-novice/dist/src/providers/tiered-router.js +9 -17
  269. package/.claude-flow-novice/dist/src/providers/tiered-router.js.map +1 -1
  270. package/.claude-flow-novice/dist/src/utils/markdown-sanitizer.js +65 -41
  271. package/.claude-flow-novice/dist/src/utils/markdown-sanitizer.js.map +1 -1
  272. package/.claude-flow-novice/dist/src/web/api/server.js +1 -1
  273. package/.claude-flow-novice/dist/src/web/api/server.js.map +1 -1
  274. package/.claude-flow-novice/dist/src/workflows/progressive-rollout-manager.js +30 -0
  275. package/.claude-flow-novice/dist/src/workflows/progressive-rollout-manager.js.map +1 -1
  276. package/.claude-flow-novice/metrics.db +0 -0
  277. package/.claude-flow-novice/metrics.db-shm +0 -0
  278. package/.claude-flow-novice/metrics.db-wal +0 -0
  279. package/CLAUDE.md +72 -0
  280. package/config/hooks/post-edit-pipeline.js +68 -118
  281. package/config/hooks/pre-tool-memory-safety.js +209 -0
  282. package/package.json +7 -4
  283. package/scripts/cleanup-idle-sessions.sh +59 -0
  284. package/scripts/monitoring/alert-monitor.sh +220 -0
  285. package/scripts/monitoring/view-alerts.sh +307 -0
  286. package/scripts/test-provider-routing.cjs +7 -9
  287. package/scripts/test-zai-api.cjs +2 -2
  288. package/src/slash-commands/parse-epic.js +1 -1
  289. package/wiki/Provider-Routing.md +57 -69
  290. package/MEMORY_LEAK_ROOT_CAUSE.md +0 -149
@@ -0,0 +1,920 @@
1
+ /**
2
+ * Agent Coordination V2 - Message Broker Implementation
3
+ *
4
+ * EventEmitter-based message broker supporting:
5
+ * - Pub/sub pattern with topic-based routing
6
+ * - Request/reply pattern with timeout handling
7
+ * - Broadcast pattern to all subscribers
8
+ * - Priority queue ordering
9
+ * - At-least-once delivery semantics
10
+ *
11
+ * @module coordination/v2/core/message-broker
12
+ */ import { EventEmitter } from 'events';
13
+ import { RateLimiter } from 'limiter';
14
+ import { MessagePriority, MessageUtils, DeliverySemantics } from './message.js';
15
+ import { PayloadValidator } from '../security/payload-validator.js';
16
+ /**
17
+ * Message broker error.
18
+ */ export class MessageBrokerError extends Error {
19
+ constructor(message){
20
+ super(message);
21
+ this.name = 'MessageBrokerError';
22
+ }
23
+ }
24
+ /**
25
+ * Priority queue for message ordering.
26
+ */ let PriorityQueue = class PriorityQueue {
27
+ items = [];
28
+ enqueue(item) {
29
+ this.items.push(item);
30
+ this.items.sort((a, b)=>b.priority - a.priority); // Higher priority first
31
+ }
32
+ dequeue() {
33
+ return this.items.shift();
34
+ }
35
+ peek() {
36
+ return this.items[0];
37
+ }
38
+ get length() {
39
+ return this.items.length;
40
+ }
41
+ size() {
42
+ return this.items.length;
43
+ }
44
+ clear() {
45
+ this.items = [];
46
+ }
47
+ };
48
+ /**
49
+ * Message Broker Implementation.
50
+ *
51
+ * Core message bus for inter-agent communication with support for:
52
+ * - Topic-based pub/sub pattern
53
+ * - Request/reply pattern with correlation
54
+ * - Broadcast to all subscribers
55
+ * - Priority-based message ordering
56
+ * - At-least-once delivery semantics
57
+ * - Subscription management
58
+ * - Message statistics and monitoring
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * const broker = new MessageBroker();
63
+ *
64
+ * // Subscribe to topic
65
+ * const sub = await broker.subscribe({
66
+ * topic: 'task.completed',
67
+ * handler: async (msg) => {
68
+ * console.log('Task completed:', msg.payload);
69
+ * }
70
+ * });
71
+ *
72
+ * // Publish message
73
+ * await broker.publish({
74
+ * topic: 'task.completed',
75
+ * payload: { taskId: 'task-1', result: 'success' },
76
+ * priority: MessagePriority.HIGH
77
+ * });
78
+ *
79
+ * // Request/reply pattern
80
+ * const reply = await broker.request('task.execute', { taskId: 'task-2' });
81
+ * console.log('Reply:', reply.payload);
82
+ *
83
+ * // Unsubscribe
84
+ * sub.unsubscribe();
85
+ * ```
86
+ */ export class MessageBroker {
87
+ emitter;
88
+ subscriptions;
89
+ pendingRequests;
90
+ messageQueue;
91
+ config;
92
+ stats;
93
+ processing;
94
+ subscriptionCounter;
95
+ // SEC-DOS-001: Per-sender queue tracking and dead letter queue
96
+ senderQueueSizes;
97
+ deadLetterQueue;
98
+ // SEC-DOS-002: Rate limiting
99
+ rateLimiters;
100
+ rateLimiterCleanupInterval;
101
+ // SEC-INJ-001: Payload validation
102
+ payloadValidator;
103
+ // SEC-MEM-001: Subscription tracking and limits
104
+ agentSubscriptions;
105
+ subscriptionCleanupInterval;
106
+ /**
107
+ * Creates a new message broker instance.
108
+ *
109
+ * @param config - Broker configuration options
110
+ */ constructor(config){
111
+ this.emitter = new EventEmitter();
112
+ this.emitter.setMaxListeners(0); // Unlimited listeners
113
+ this.subscriptions = new Map();
114
+ this.pendingRequests = new Map();
115
+ this.messageQueue = new PriorityQueue();
116
+ this.subscriptionCounter = 0;
117
+ this.processing = false;
118
+ // SEC-DOS-001: Initialize per-sender queue tracking
119
+ this.senderQueueSizes = new Map();
120
+ this.deadLetterQueue = new PriorityQueue();
121
+ // SEC-DOS-002: Initialize rate limiters
122
+ this.rateLimiters = new Map();
123
+ // SEC-MEM-001: Initialize subscription tracking
124
+ this.agentSubscriptions = new Map();
125
+ this.config = {
126
+ maxQueueSize: config?.maxQueueSize ?? 10000,
127
+ maxQueueSizePerSender: config?.maxQueueSizePerSender ?? 100,
128
+ enableDeadLetterQueue: config?.enableDeadLetterQueue ?? true,
129
+ priorityEvictionThreshold: config?.priorityEvictionThreshold ?? 0.9,
130
+ defaultRequestTimeout: config?.defaultRequestTimeout ?? 30000,
131
+ enableStats: config?.enableStats ?? true,
132
+ maxConcurrency: config?.maxConcurrency ?? 100,
133
+ maxSubscriptions: config?.maxSubscriptions ?? 10000,
134
+ maxSubscriptionsPerAgent: config?.maxSubscriptionsPerAgent ?? 100,
135
+ subscriptionTTL: config?.subscriptionTTL ?? 3600000,
136
+ cleanupIntervalMs: config?.cleanupIntervalMs ?? 60000,
137
+ authorizationProvider: config?.authorizationProvider,
138
+ rateLimit: config?.rateLimit ? {
139
+ maxMessagesPerSecond: config.rateLimit.maxMessagesPerSecond ?? 100,
140
+ maxBurstSize: config.rateLimit.maxBurstSize ?? 10,
141
+ strategy: config.rateLimit.strategy ?? 'token-bucket'
142
+ } : undefined,
143
+ payloadValidation: config?.payloadValidation
144
+ };
145
+ // SEC-INJ-001: Initialize payload validator
146
+ this.payloadValidator = new PayloadValidator(this.config.payloadValidation);
147
+ this.stats = {
148
+ totalPublished: 0,
149
+ totalDelivered: 0,
150
+ totalFailed: 0,
151
+ totalSubscriptions: 0,
152
+ messagesByTopic: {},
153
+ messagesByPriority: {},
154
+ avgDeliveryTime: 0
155
+ };
156
+ // SEC-DOS-002: Start rate limiter cleanup if rate limiting is enabled
157
+ if (this.config.rateLimit) {
158
+ this.startRateLimiterCleanup();
159
+ }
160
+ // SEC-MEM-001: Start subscription cleanup for TTL expiration
161
+ this.startSubscriptionCleanup();
162
+ }
163
+ // ============================================
164
+ // Pub/Sub Pattern
165
+ // ============================================
166
+ /**
167
+ * Subscribes to a topic with a message handler.
168
+ *
169
+ * @param config - Subscription configuration
170
+ * @returns Subscription handle for management
171
+ * @throws {MessageBrokerError} If configuration is invalid
172
+ *
173
+ * @example
174
+ * ```typescript
175
+ * const sub = await broker.subscribe({
176
+ * topic: 'task.*',
177
+ * handler: async (msg) => {
178
+ * console.log('Received:', msg.payload);
179
+ * },
180
+ * priority: 10
181
+ * });
182
+ * ```
183
+ */ async subscribe(config) {
184
+ if (!config.topic || typeof config.topic !== 'string') {
185
+ throw new MessageBrokerError('Subscription topic must be a non-empty string');
186
+ }
187
+ // SEC-007: Validate topic name to prevent injection
188
+ this.validateTopicName(config.topic);
189
+ if (typeof config.handler !== 'function') {
190
+ throw new MessageBrokerError('Subscription handler must be a function');
191
+ }
192
+ // SEC-MEM-001: Check global subscription limit
193
+ if (this.stats.totalSubscriptions >= this.config.maxSubscriptions) {
194
+ throw new MessageBrokerError(`Maximum subscriptions reached (max: ${this.config.maxSubscriptions})`);
195
+ }
196
+ // SEC-MEM-001: Check per-agent subscription limit
197
+ const subscriberId = config.subscriberId || 'anonymous';
198
+ const agentSubs = this.agentSubscriptions.get(subscriberId) || new Set();
199
+ if (agentSubs.size >= this.config.maxSubscriptionsPerAgent) {
200
+ throw new MessageBrokerError(`Subscriber ${subscriberId} exceeded subscription limit (max: ${this.config.maxSubscriptionsPerAgent})`);
201
+ }
202
+ // SEC-012: Check subscription authorization
203
+ if (this.config.authorizationProvider && config.subscriberId) {
204
+ const authorized = await this.config.authorizationProvider.canSubscribe(config.subscriberId, config.topic);
205
+ if (!authorized) {
206
+ throw new MessageBrokerError(`Subscriber ${config.subscriberId} not authorized to subscribe to topic ${config.topic}`);
207
+ }
208
+ }
209
+ const subscriptionId = `sub-${++this.subscriptionCounter}-${Date.now()}`;
210
+ // SEC-MEM-001: Create subscription with TTL expiration
211
+ const internalSub = {
212
+ id: subscriptionId,
213
+ topic: config.topic,
214
+ handler: config.handler,
215
+ priority: config.priority ?? 0,
216
+ createdAt: Date.now(),
217
+ filter: config.filter,
218
+ expiresAt: Date.now() + this.config.subscriptionTTL,
219
+ subscriberId
220
+ };
221
+ // Add to subscriptions map
222
+ if (!this.subscriptions.has(config.topic)) {
223
+ this.subscriptions.set(config.topic, []);
224
+ }
225
+ const topicSubs = this.subscriptions.get(config.topic);
226
+ topicSubs.push(internalSub);
227
+ // Sort by priority (higher priority first)
228
+ topicSubs.sort((a, b)=>b.priority - a.priority);
229
+ // SEC-MEM-001: Track subscription by agent
230
+ agentSubs.add(subscriptionId);
231
+ this.agentSubscriptions.set(subscriberId, agentSubs);
232
+ this.stats.totalSubscriptions++;
233
+ return {
234
+ id: subscriptionId,
235
+ topic: config.topic,
236
+ createdAt: internalSub.createdAt,
237
+ unsubscribe: ()=>this.unsubscribe(subscriptionId)
238
+ };
239
+ }
240
+ /**
241
+ * Unsubscribes a subscription by ID.
242
+ *
243
+ * @param subscriptionId - Subscription ID to remove
244
+ * @returns True if subscription was removed, false if not found
245
+ */ unsubscribe(subscriptionId) {
246
+ for (const topic of Array.from(this.subscriptions.keys())){
247
+ const subs = this.subscriptions.get(topic);
248
+ const index = subs.findIndex((sub)=>sub.id === subscriptionId);
249
+ if (index !== -1) {
250
+ const sub = subs[index];
251
+ subs.splice(index, 1);
252
+ this.stats.totalSubscriptions--;
253
+ // SEC-MEM-001: Clean up agent subscription tracking
254
+ if (sub.subscriberId) {
255
+ const agentSubs = this.agentSubscriptions.get(sub.subscriberId);
256
+ if (agentSubs) {
257
+ agentSubs.delete(subscriptionId);
258
+ if (agentSubs.size === 0) {
259
+ this.agentSubscriptions.delete(sub.subscriberId);
260
+ }
261
+ }
262
+ }
263
+ // Clean up empty topic entries
264
+ if (subs.length === 0) {
265
+ this.subscriptions.delete(topic);
266
+ }
267
+ return true;
268
+ }
269
+ }
270
+ return false;
271
+ }
272
+ /**
273
+ * Publishes a message to a topic.
274
+ *
275
+ * @param config - Message configuration
276
+ * @returns Promise resolving to the published message
277
+ * @throws {MessageBrokerError} If message validation fails or queue is full
278
+ *
279
+ * @example
280
+ * ```typescript
281
+ * await broker.publish({
282
+ * topic: 'task.completed',
283
+ * payload: { taskId: 'task-1' },
284
+ * priority: MessagePriority.HIGH
285
+ * });
286
+ * ```
287
+ */ async publish(config) {
288
+ MessageUtils.validateConfig(config);
289
+ // SEC-007: Validate topic name to prevent injection
290
+ this.validateTopicName(config.topic);
291
+ // SEC-INJ-001: Validate and sanitize payload BEFORE processing
292
+ const validationResult = this.payloadValidator.validate(config.payload);
293
+ if (!validationResult.valid) {
294
+ this.emitter.emit('validation:failed', {
295
+ errors: validationResult.errors,
296
+ senderId: config.senderId,
297
+ topic: config.topic
298
+ });
299
+ throw new MessageBrokerError(`Payload validation failed: ${validationResult.errors.join(', ')}`);
300
+ }
301
+ // SEC-INJ-001: Sanitize payload to prevent injection attacks
302
+ const sanitizedPayload = this.payloadValidator.sanitize(config.payload);
303
+ const senderId = config.senderId || 'anonymous';
304
+ // SEC-DOS-002: Rate limiting - Check FIRST before any processing
305
+ if (this.config.rateLimit) {
306
+ const allowed = await this.checkRateLimit(senderId);
307
+ if (!allowed) {
308
+ this.emitter.emit('rate-limit:exceeded', {
309
+ senderId,
310
+ topic: config.topic
311
+ });
312
+ throw new MessageBrokerError(`Rate limit exceeded for sender ${senderId}`);
313
+ }
314
+ }
315
+ // SEC-DOS-001: Per-sender queue limit - Check BEFORE global limit
316
+ // CRITICAL: Read and increment atomically to prevent race condition
317
+ const currentSenderSize = this.senderQueueSizes.get(senderId) || 0;
318
+ // Debug logging for per-sender queue tracking
319
+ if (process.env.DEBUG_MESSAGE_BROKER) {
320
+ console.log(`[MessageBroker PUBLISH] Sender ${senderId}: ${currentSenderSize} messages (limit: ${this.config.maxQueueSizePerSender}), queue processing: ${this.processing}`);
321
+ }
322
+ if (currentSenderSize >= this.config.maxQueueSizePerSender) {
323
+ throw new MessageBrokerError(`Sender ${senderId} exceeded queue limit (${currentSenderSize}/${this.config.maxQueueSizePerSender})`);
324
+ }
325
+ // SEC-DOS-001: Increment IMMEDIATELY after check to reserve slot (before async processing)
326
+ this.senderQueueSizes.set(senderId, currentSenderSize + 1);
327
+ if (process.env.DEBUG_MESSAGE_BROKER) {
328
+ console.log(`[MessageBroker PUBLISH] After increment: ${this.senderQueueSizes.get(senderId)}`);
329
+ }
330
+ // SEC-DOS-001: Global queue limit with priority eviction
331
+ if (this.messageQueue.length >= this.config.maxQueueSize) {
332
+ // If queue is at priority eviction threshold, evict low-priority messages
333
+ const evictionThreshold = Math.floor(this.config.maxQueueSize * this.config.priorityEvictionThreshold);
334
+ if (this.messageQueue.length >= evictionThreshold) {
335
+ const messagePriority = MessageUtils.normalizePriority(config.priority);
336
+ const evicted = this.evictLowPriorityMessages(messagePriority);
337
+ if (evicted.length === 0) {
338
+ throw new MessageBrokerError(`Message queue full (max: ${this.config.maxQueueSize}, no evictable messages)`);
339
+ }
340
+ this.emitter.emit('queue:high-pressure', {
341
+ queueSize: this.messageQueue.length,
342
+ evicted: evicted.length,
343
+ evictedMessages: evicted,
344
+ threshold: evictionThreshold
345
+ });
346
+ } else {
347
+ throw new MessageBrokerError(`Message queue full (max: ${this.config.maxQueueSize})`);
348
+ }
349
+ }
350
+ // SEC-INJ-001: Use sanitized payload in message
351
+ const message = {
352
+ id: MessageUtils.generateMessageId(),
353
+ topic: config.topic,
354
+ payload: sanitizedPayload,
355
+ priority: MessageUtils.normalizePriority(config.priority),
356
+ timestamp: Date.now(),
357
+ replyTo: config.replyTo,
358
+ correlationId: config.correlationId,
359
+ senderId: config.senderId,
360
+ recipientId: config.recipientId,
361
+ deliverySemantics: config.deliverySemantics ?? DeliverySemantics.AT_LEAST_ONCE,
362
+ metadata: config.metadata
363
+ };
364
+ this.messageQueue.enqueue(message);
365
+ // SEC-DOS-001: Sender queue size already incremented at line 517 (atomic check-and-increment)
366
+ if (this.config.enableStats) {
367
+ this.stats.totalPublished++;
368
+ this.stats.messagesByTopic[message.topic] = (this.stats.messagesByTopic[message.topic] || 0) + 1;
369
+ this.stats.messagesByPriority[message.priority] = (this.stats.messagesByPriority[message.priority] || 0) + 1;
370
+ }
371
+ // Start processing if not already processing
372
+ this.processQueue().catch((error)=>{
373
+ console.error('Message queue processing error:', error);
374
+ });
375
+ return message;
376
+ }
377
+ /**
378
+ * Broadcasts a message to all subscribers matching the topic pattern.
379
+ *
380
+ * @param config - Message configuration
381
+ * @returns Promise resolving to array of delivery results
382
+ */ async broadcast(config) {
383
+ await this.publish({
384
+ ...config,
385
+ metadata: {
386
+ ...config.metadata,
387
+ broadcast: true
388
+ }
389
+ });
390
+ }
391
+ // ============================================
392
+ // Request/Reply Pattern
393
+ // ============================================
394
+ /**
395
+ * Sends a request message and waits for a reply.
396
+ *
397
+ * @param topic - Request topic
398
+ * @param payload - Request payload
399
+ * @param options - Request options (timeout, correlation ID)
400
+ * @returns Promise resolving to reply message
401
+ * @throws {MessageBrokerError} If request times out or fails
402
+ *
403
+ * @example
404
+ * ```typescript
405
+ * const reply = await broker.request('task.execute', { taskId: 'task-1' }, {
406
+ * timeout: 5000
407
+ * });
408
+ * console.log('Reply:', reply.payload);
409
+ * ```
410
+ */ async request(topic, payload, options) {
411
+ const correlationId = options?.correlationId ?? MessageUtils.generateCorrelationId();
412
+ const timeout = options?.timeout ?? this.config.defaultRequestTimeout;
413
+ const priority = options?.priority ?? MessagePriority.NORMAL;
414
+ const replyTopic = `${topic}.reply.${correlationId}`;
415
+ return new Promise((resolve, reject)=>{
416
+ // Set timeout
417
+ const timeoutId = setTimeout(()=>{
418
+ this.pendingRequests.delete(correlationId);
419
+ reject(new MessageBrokerError(`Request timeout after ${timeout}ms (correlationId: ${correlationId})`));
420
+ }, timeout);
421
+ // Store pending request
422
+ this.pendingRequests.set(correlationId, {
423
+ correlationId,
424
+ resolve: resolve,
425
+ reject,
426
+ timeoutId,
427
+ createdAt: Date.now(),
428
+ expectedSender: options?.senderId,
429
+ resolved: false
430
+ });
431
+ // Publish request message
432
+ this.publish({
433
+ topic,
434
+ payload,
435
+ priority,
436
+ replyTo: replyTopic,
437
+ correlationId
438
+ }).catch((error)=>{
439
+ clearTimeout(timeoutId);
440
+ this.pendingRequests.delete(correlationId);
441
+ reject(error);
442
+ });
443
+ });
444
+ }
445
+ /**
446
+ * Sends a reply to a request message.
447
+ *
448
+ * @param request - Original request message
449
+ * @param payload - Reply payload
450
+ * @param success - Success status (default: true)
451
+ * @param error - Error message if failed
452
+ * @returns Promise resolving when reply is sent
453
+ *
454
+ * @example
455
+ * ```typescript
456
+ * await broker.subscribe({
457
+ * topic: 'task.execute',
458
+ * handler: async (msg) => {
459
+ * const result = await executeTask(msg.payload);
460
+ * await broker.reply(msg, result);
461
+ * }
462
+ * });
463
+ * ```
464
+ */ async reply(request, payload, success = true, error) {
465
+ if (!request.replyTo) {
466
+ throw new MessageBrokerError('Cannot reply: request has no replyTo topic');
467
+ }
468
+ if (!request.correlationId) {
469
+ throw new MessageBrokerError('Cannot reply: request has no correlationId');
470
+ }
471
+ const reply = MessageUtils.createReply(request, payload, success, error);
472
+ await this.publish({
473
+ topic: request.replyTo,
474
+ payload: reply,
475
+ priority: request.priority,
476
+ correlationId: request.correlationId,
477
+ senderId: request.recipientId // SEC-006: Propagate responder ID for validation
478
+ });
479
+ }
480
+ // ============================================
481
+ // Message Processing
482
+ // ============================================
483
+ /**
484
+ * Processes the message queue (internal).
485
+ * Handles priority ordering and at-least-once delivery.
486
+ */ async processQueue() {
487
+ if (this.processing) {
488
+ return; // Already processing
489
+ }
490
+ this.processing = true;
491
+ try {
492
+ while(this.messageQueue.length > 0){
493
+ // SEC-DOS-001-RACE: Peek at message first to check for matching handlers
494
+ const message = this.messageQueue.peek();
495
+ if (!message) break;
496
+ // Check if there are any matching handlers BEFORE dequeuing
497
+ const hasHandlers = this.hasMatchingHandlers(message);
498
+ // SEC-DOS-001-RACE: Only dequeue if handlers exist to prevent race condition
499
+ if (!hasHandlers) {
500
+ break;
501
+ }
502
+ // Now dequeue the message
503
+ this.messageQueue.dequeue();
504
+ // SEC-DOS-001: Deliver first, then decrement (counter represents "in-flight" messages)
505
+ await this.deliverMessage(message);
506
+ // SEC-DOS-001: Decrement AFTER successful delivery (message no longer in-flight)
507
+ const senderId = message.senderId || 'anonymous';
508
+ const senderSize = this.senderQueueSizes.get(senderId) || 0;
509
+ if (senderSize > 0) {
510
+ this.senderQueueSizes.set(senderId, senderSize - 1);
511
+ if (process.env.DEBUG_MESSAGE_BROKER) {
512
+ console.log(`[MessageBroker DELIVER] Decremented ${senderId}: ${senderSize} -> ${this.senderQueueSizes.get(senderId)}`);
513
+ }
514
+ }
515
+ }
516
+ } finally{
517
+ this.processing = false;
518
+ }
519
+ }
520
+ /**
521
+ * Checks if there are any matching handlers for a message (without delivering).
522
+ * Used to prevent dequeuing messages when no subscribers exist.
523
+ */ hasMatchingHandlers(message) {
524
+ // Check for pending request/reply handlers
525
+ if (message.correlationId && this.pendingRequests.has(message.correlationId)) {
526
+ return true;
527
+ }
528
+ // Check for topic subscribers
529
+ for (const topicPattern of Array.from(this.subscriptions.keys())){
530
+ if (MessageUtils.matchesTopic(message.topic, topicPattern)) {
531
+ const subs = this.subscriptions.get(topicPattern);
532
+ if (subs.length > 0) {
533
+ return true;
534
+ }
535
+ }
536
+ }
537
+ return false;
538
+ }
539
+ /**
540
+ * Delivers a message to all matching subscribers.
541
+ * Returns true if message was delivered to any handler, false otherwise.
542
+ */ async deliverMessage(message) {
543
+ const startTime = Date.now();
544
+ const matchingHandlers = [];
545
+ // SEC-MEM-001: Clean up expired subscriptions before delivery
546
+ this.cleanupExpiredSubscriptions();
547
+ // Find matching subscriptions
548
+ for (const topicPattern of Array.from(this.subscriptions.keys())){
549
+ const subs = this.subscriptions.get(topicPattern);
550
+ if (MessageUtils.matchesTopic(message.topic, topicPattern)) {
551
+ matchingHandlers.push(...subs);
552
+ }
553
+ }
554
+ // Handle reply messages (special case)
555
+ if (message.correlationId && this.pendingRequests.has(message.correlationId)) {
556
+ const pendingRequest = this.pendingRequests.get(message.correlationId);
557
+ // SEC-006: Validate sender authorization for reply
558
+ if (pendingRequest.expectedSender && message.senderId !== pendingRequest.expectedSender) {
559
+ console.warn(`[MessageBroker] Unauthorized reply sender: expected ${pendingRequest.expectedSender}, got ${message.senderId}`);
560
+ return; // Drop unauthorized reply
561
+ }
562
+ // SEC-006: Check duplicate reply detection
563
+ if (pendingRequest.resolved) {
564
+ console.warn(`[MessageBroker] Duplicate reply detected for correlationId ${message.correlationId}`);
565
+ return; // Drop duplicate reply
566
+ }
567
+ // Mark resolved and cleanup
568
+ pendingRequest.resolved = true;
569
+ clearTimeout(pendingRequest.timeoutId);
570
+ this.pendingRequests.delete(message.correlationId);
571
+ pendingRequest.resolve(message.payload);
572
+ }
573
+ // Sort handlers by priority
574
+ matchingHandlers.sort((a, b)=>b.priority - a.priority);
575
+ // Deliver to handlers
576
+ for (const sub of matchingHandlers){
577
+ try {
578
+ // Apply filter if present
579
+ if (sub.filter && !sub.filter(message)) {
580
+ continue;
581
+ }
582
+ await sub.handler(message);
583
+ if (this.config.enableStats) {
584
+ this.stats.totalDelivered++;
585
+ }
586
+ } catch (error) {
587
+ if (this.config.enableStats) {
588
+ this.stats.totalFailed++;
589
+ }
590
+ // Emit error event but don't throw (at-least-once delivery)
591
+ this.emitter.emit('error', {
592
+ error,
593
+ message,
594
+ subscription: sub
595
+ });
596
+ }
597
+ }
598
+ // SEC-DOS-001: Sender queue size already decremented in processQueue() after dequeue (line 729-734)
599
+ // Update delivery time statistics
600
+ if (this.config.enableStats && matchingHandlers.length > 0) {
601
+ const deliveryTime = Date.now() - startTime;
602
+ this.stats.avgDeliveryTime = (this.stats.avgDeliveryTime * (this.stats.totalDelivered - 1) + deliveryTime) / this.stats.totalDelivered;
603
+ }
604
+ // Return true if message was delivered to any handler
605
+ return matchingHandlers.length > 0;
606
+ }
607
+ // ============================================
608
+ // Statistics and Monitoring
609
+ // ============================================
610
+ /**
611
+ * Gets current message broker statistics.
612
+ *
613
+ * @returns Statistics object
614
+ */ getStats() {
615
+ return {
616
+ ...this.stats,
617
+ messagesByTopic: {
618
+ ...this.stats.messagesByTopic
619
+ },
620
+ messagesByPriority: {
621
+ ...this.stats.messagesByPriority
622
+ }
623
+ };
624
+ }
625
+ /**
626
+ * Resets all statistics counters.
627
+ */ resetStats() {
628
+ this.stats = {
629
+ totalPublished: 0,
630
+ totalDelivered: 0,
631
+ totalFailed: 0,
632
+ totalSubscriptions: this.stats.totalSubscriptions,
633
+ messagesByTopic: {},
634
+ messagesByPriority: {},
635
+ avgDeliveryTime: 0
636
+ };
637
+ }
638
+ /**
639
+ * Gets all active subscriptions.
640
+ *
641
+ * @returns Array of subscription information
642
+ */ getSubscriptions() {
643
+ const result = [];
644
+ for (const subs of Array.from(this.subscriptions.values())){
645
+ for (const sub of subs){
646
+ result.push({
647
+ id: sub.id,
648
+ topic: sub.topic,
649
+ priority: sub.priority,
650
+ createdAt: sub.createdAt
651
+ });
652
+ }
653
+ }
654
+ return result;
655
+ }
656
+ /**
657
+ * Gets the current queue size.
658
+ *
659
+ * @returns Number of messages in queue
660
+ */ getQueueSize() {
661
+ return this.messageQueue.length;
662
+ }
663
+ /**
664
+ * Gets the number of pending requests.
665
+ *
666
+ * @returns Number of pending request/reply operations
667
+ */ getPendingRequestCount() {
668
+ return this.pendingRequests.size;
669
+ }
670
+ // ============================================
671
+ // Security Validation
672
+ // ============================================
673
+ /**
674
+ * Validates topic name to prevent injection attacks (SEC-007).
675
+ *
676
+ * @param topic - Topic name to validate
677
+ * @throws {MessageBrokerError} If topic name is invalid
678
+ */ validateTopicName(topic) {
679
+ // SEC-007: Prevent path traversal FIRST (before pattern check)
680
+ if (topic.includes('..') || topic.includes('//')) {
681
+ throw new MessageBrokerError('Path traversal detected in topic name');
682
+ }
683
+ // SEC-007: Prevent excessively long topics
684
+ if (topic.length > 256) {
685
+ throw new MessageBrokerError('Topic name exceeds 256 characters');
686
+ }
687
+ // SEC-007: Validate topic pattern (alphanumeric, dots, dashes, underscores, wildcards)
688
+ const validTopicPattern = /^[a-zA-Z0-9._-]+(\.[a-zA-Z0-9._*-]+)*$/;
689
+ if (!validTopicPattern.test(topic)) {
690
+ throw new MessageBrokerError(`Invalid topic name: ${topic}`);
691
+ }
692
+ }
693
+ // ============================================
694
+ // SEC-DOS-001 & SEC-DOS-002: DoS Protection Methods
695
+ // ============================================
696
+ /**
697
+ * SEC-DOS-002: Checks rate limit for a sender using token bucket algorithm.
698
+ *
699
+ * @param senderId - Sender identifier
700
+ * @returns True if request is allowed, false if rate limit exceeded
701
+ */ async checkRateLimit(senderId) {
702
+ if (!this.config.rateLimit) {
703
+ return true; // Rate limiting disabled
704
+ }
705
+ let limiter = this.rateLimiters.get(senderId);
706
+ if (!limiter) {
707
+ // Create new rate limiter for this sender
708
+ limiter = new RateLimiter({
709
+ tokensPerInterval: this.config.rateLimit.maxMessagesPerSecond,
710
+ interval: 'second',
711
+ fireImmediately: true
712
+ });
713
+ this.rateLimiters.set(senderId, limiter);
714
+ }
715
+ try {
716
+ const remainingTokens = await limiter.removeTokens(1);
717
+ return remainingTokens >= 0;
718
+ } catch (error) {
719
+ // Rate limit exceeded
720
+ return false;
721
+ }
722
+ }
723
+ /**
724
+ * SEC-DOS-002: Periodically cleanup idle rate limiters to prevent memory leaks.
725
+ */ startRateLimiterCleanup() {
726
+ this.rateLimiterCleanupInterval = setInterval(()=>{
727
+ // Remove rate limiters that haven't been used recently
728
+ // In production, you would track last access time
729
+ // For now, we clear limiters periodically to prevent unbounded growth
730
+ if (this.rateLimiters.size > 1000) {
731
+ // Keep only the most recent 500 limiters (simple cleanup strategy)
732
+ const entries = Array.from(this.rateLimiters.entries());
733
+ const toKeep = entries.slice(-500);
734
+ this.rateLimiters.clear();
735
+ toKeep.forEach(([key, value])=>this.rateLimiters.set(key, value));
736
+ }
737
+ }, 60000); // Cleanup every 60 seconds
738
+ }
739
+ /**
740
+ * SEC-DOS-001: Evicts low-priority messages when queue is full.
741
+ * Only evicts enough messages to make room for 1 new message.
742
+ *
743
+ * @param incomingPriority - Priority of the incoming message
744
+ * @returns Array of evicted messages
745
+ */ evictLowPriorityMessages(incomingPriority) {
746
+ const evicted = [];
747
+ // SEC-DOS-001-RACE: Only evict 1 message to make room for the incoming message
748
+ // Don't evict ALL lower-priority messages
749
+ const items = this.messageQueue.items;
750
+ if (!items || items.length === 0) {
751
+ return evicted;
752
+ }
753
+ // Find lowest priority message
754
+ let lowestIndex = 0;
755
+ let lowestPriority = items[0].priority;
756
+ for(let i = 1; i < items.length; i++){
757
+ if (items[i].priority < lowestPriority) {
758
+ lowestPriority = items[i].priority;
759
+ lowestIndex = i;
760
+ }
761
+ }
762
+ // Only evict if priority is lower than incoming
763
+ if (lowestPriority < incomingPriority) {
764
+ const candidate = items[lowestIndex];
765
+ items.splice(lowestIndex, 1);
766
+ // Move to dead letter queue if enabled
767
+ if (this.config.enableDeadLetterQueue) {
768
+ this.deadLetterQueue.enqueue(candidate);
769
+ }
770
+ // Decrement sender queue size
771
+ const senderId = candidate.senderId || 'anonymous';
772
+ const senderSize = this.senderQueueSizes.get(senderId) || 0;
773
+ if (senderSize > 0) {
774
+ this.senderQueueSizes.set(senderId, senderSize - 1);
775
+ }
776
+ evicted.push(candidate);
777
+ }
778
+ return evicted;
779
+ }
780
+ /**
781
+ * Gets the current size of the dead letter queue.
782
+ *
783
+ * @returns Number of messages in dead letter queue
784
+ */ getDeadLetterQueueSize() {
785
+ return this.deadLetterQueue.length;
786
+ }
787
+ /**
788
+ * SEC-DOS-002: Returns the number of active rate limiters.
789
+ */ getRateLimiterCount() {
790
+ return this.rateLimiters.size;
791
+ }
792
+ /**
793
+ * Retrieves messages from the dead letter queue.
794
+ *
795
+ * @param count - Number of messages to retrieve (default: all)
796
+ * @returns Array of dead letter messages
797
+ */ getDeadLetterMessages(count) {
798
+ const items = this.deadLetterQueue.items;
799
+ if (!items) return [];
800
+ if (count === undefined) {
801
+ return [
802
+ ...items
803
+ ];
804
+ }
805
+ return items.slice(0, count);
806
+ }
807
+ /**
808
+ * Clears the dead letter queue.
809
+ */ clearDeadLetterQueue() {
810
+ this.deadLetterQueue.clear();
811
+ }
812
+ // ============================================
813
+ // SEC-MEM-001: Subscription Cleanup
814
+ // ============================================
815
+ /**
816
+ * Starts periodic subscription cleanup to expire old subscriptions (SEC-MEM-001).
817
+ * Runs periodically to remove expired subscriptions based on TTL.
818
+ */ startSubscriptionCleanup() {
819
+ const cleanupInterval = this.config.cleanupIntervalMs ?? 60000;
820
+ this.subscriptionCleanupInterval = setInterval(()=>{
821
+ this.cleanupExpiredSubscriptions();
822
+ }, cleanupInterval);
823
+ }
824
+ /**
825
+ * Synchronously removes expired subscriptions (SEC-MEM-001).
826
+ * Called by background timer and immediately before publishing.
827
+ *
828
+ * @returns Number of subscriptions removed
829
+ */ cleanupExpiredSubscriptions() {
830
+ const now = Date.now();
831
+ let expiredCount = 0;
832
+ for (const topic of Array.from(this.subscriptions.keys())){
833
+ const subs = this.subscriptions.get(topic);
834
+ const validSubs = subs.filter((sub)=>{
835
+ if (sub.expiresAt && now >= sub.expiresAt) {
836
+ // Expired subscription
837
+ expiredCount++;
838
+ // Clean up agent tracking
839
+ if (sub.subscriberId) {
840
+ const agentSubs = this.agentSubscriptions.get(sub.subscriberId);
841
+ if (agentSubs) {
842
+ agentSubs.delete(sub.id);
843
+ if (agentSubs.size === 0) {
844
+ this.agentSubscriptions.delete(sub.subscriberId);
845
+ }
846
+ }
847
+ }
848
+ this.stats.totalSubscriptions--;
849
+ return false; // Remove expired subscription
850
+ }
851
+ return true; // Keep valid subscription
852
+ });
853
+ if (validSubs.length === 0) {
854
+ this.subscriptions.delete(topic);
855
+ } else if (validSubs.length !== subs.length) {
856
+ this.subscriptions.set(topic, validSubs);
857
+ }
858
+ }
859
+ if (expiredCount > 0) {
860
+ this.emitter.emit('subscriptions:expired', {
861
+ count: expiredCount
862
+ });
863
+ }
864
+ return expiredCount;
865
+ }
866
+ // ============================================
867
+ // Lifecycle Management
868
+ // ============================================
869
+ /**
870
+ * Clears all subscriptions and pending messages.
871
+ */ clear() {
872
+ this.subscriptions.clear();
873
+ this.messageQueue.clear();
874
+ // Cancel all pending requests
875
+ for (const correlationId of Array.from(this.pendingRequests.keys())){
876
+ const pending = this.pendingRequests.get(correlationId);
877
+ clearTimeout(pending.timeoutId);
878
+ pending.reject(new MessageBrokerError('Broker cleared'));
879
+ }
880
+ this.pendingRequests.clear();
881
+ // SEC-MEM-001: Clear subscription tracking
882
+ this.agentSubscriptions.clear();
883
+ // SEC-DOS-002: Clear rate limiters
884
+ this.rateLimiters.clear();
885
+ if (this.rateLimiterCleanupInterval) {
886
+ clearInterval(this.rateLimiterCleanupInterval);
887
+ this.rateLimiterCleanupInterval = undefined;
888
+ }
889
+ // SEC-MEM-001: Clear subscription cleanup interval
890
+ if (this.subscriptionCleanupInterval) {
891
+ clearInterval(this.subscriptionCleanupInterval);
892
+ this.subscriptionCleanupInterval = undefined;
893
+ }
894
+ this.stats.totalSubscriptions = 0;
895
+ this.emitter.removeAllListeners();
896
+ }
897
+ /**
898
+ * Shuts down the message broker gracefully.
899
+ * Waits for pending messages to be processed.
900
+ *
901
+ * @param timeout - Maximum wait time in milliseconds (default: 5000)
902
+ * @returns Promise resolving when shutdown complete
903
+ */ async shutdown(timeout = 5000) {
904
+ const startTime = Date.now();
905
+ // Wait for queue to drain
906
+ while(this.messageQueue.length > 0 && Date.now() - startTime < timeout){
907
+ await new Promise((resolve)=>setTimeout(resolve, 100));
908
+ }
909
+ this.clear();
910
+ }
911
+ /**
912
+ * Registers an error handler for message processing errors.
913
+ *
914
+ * @param handler - Error handler function
915
+ */ onError(handler) {
916
+ this.emitter.on('error', handler);
917
+ }
918
+ }
919
+
920
+ //# sourceMappingURL=message-broker.js.map