@holoscript/framework 6.0.3

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 (329) hide show
  1. package/ALL-test-results.json +1 -0
  2. package/CHANGELOG.md +8 -0
  3. package/LICENSE +21 -0
  4. package/ROADMAP.md +175 -0
  5. package/dist/AgentManifest-CB4xM-Ma.d.cts +704 -0
  6. package/dist/AgentManifest-CB4xM-Ma.d.ts +704 -0
  7. package/dist/BehaviorTree-BrBFECv5.d.cts +103 -0
  8. package/dist/BehaviorTree-BrBFECv5.d.ts +103 -0
  9. package/dist/InvisibleWallet-BB6tFvRA.d.cts +1732 -0
  10. package/dist/InvisibleWallet-rtRrBOA8.d.ts +1732 -0
  11. package/dist/OrchestratorAgent-BvWgf9uw.d.cts +798 -0
  12. package/dist/OrchestratorAgent-Q_CbVTmO.d.ts +798 -0
  13. package/dist/agents/index.cjs +4790 -0
  14. package/dist/agents/index.d.cts +1788 -0
  15. package/dist/agents/index.d.ts +1788 -0
  16. package/dist/agents/index.js +4695 -0
  17. package/dist/ai/index.cjs +5347 -0
  18. package/dist/ai/index.d.cts +1753 -0
  19. package/dist/ai/index.d.ts +1753 -0
  20. package/dist/ai/index.js +5244 -0
  21. package/dist/behavior.cjs +449 -0
  22. package/dist/behavior.d.cts +130 -0
  23. package/dist/behavior.d.ts +130 -0
  24. package/dist/behavior.js +407 -0
  25. package/dist/economy/index.cjs +3659 -0
  26. package/dist/economy/index.d.cts +747 -0
  27. package/dist/economy/index.d.ts +747 -0
  28. package/dist/economy/index.js +3617 -0
  29. package/dist/implementations-D9T3un9D.d.cts +236 -0
  30. package/dist/implementations-D9T3un9D.d.ts +236 -0
  31. package/dist/index.cjs +24550 -0
  32. package/dist/index.d.cts +1729 -0
  33. package/dist/index.d.ts +1729 -0
  34. package/dist/index.js +24277 -0
  35. package/dist/learning/index.cjs +219 -0
  36. package/dist/learning/index.d.cts +104 -0
  37. package/dist/learning/index.d.ts +104 -0
  38. package/dist/learning/index.js +189 -0
  39. package/dist/negotiation/index.cjs +970 -0
  40. package/dist/negotiation/index.d.cts +610 -0
  41. package/dist/negotiation/index.d.ts +610 -0
  42. package/dist/negotiation/index.js +931 -0
  43. package/dist/skills/index.cjs +1118 -0
  44. package/dist/skills/index.d.cts +289 -0
  45. package/dist/skills/index.d.ts +289 -0
  46. package/dist/skills/index.js +1079 -0
  47. package/dist/swarm/index.cjs +5268 -0
  48. package/dist/swarm/index.d.cts +2433 -0
  49. package/dist/swarm/index.d.ts +2433 -0
  50. package/dist/swarm/index.js +5221 -0
  51. package/dist/training/index.cjs +2745 -0
  52. package/dist/training/index.d.cts +1734 -0
  53. package/dist/training/index.d.ts +1734 -0
  54. package/dist/training/index.js +2687 -0
  55. package/extract-failures.js +10 -0
  56. package/package.json +82 -0
  57. package/src/__tests__/bounty-marketplace.test.ts +374 -0
  58. package/src/__tests__/delegation.test.ts +144 -0
  59. package/src/__tests__/distributed-claimer.test.ts +147 -0
  60. package/src/__tests__/done-log-audit.test.ts +342 -0
  61. package/src/__tests__/framework.test.ts +865 -0
  62. package/src/__tests__/goal-synthesizer.test.ts +236 -0
  63. package/src/__tests__/presence.test.ts +223 -0
  64. package/src/__tests__/protocol-agent.test.ts +254 -0
  65. package/src/__tests__/revenue-splitter.test.ts +114 -0
  66. package/src/__tests__/scenario-driven-todo.test.ts +197 -0
  67. package/src/__tests__/self-improve.test.ts +349 -0
  68. package/src/__tests__/service-lifecycle.test.ts +237 -0
  69. package/src/__tests__/skill-router.test.ts +121 -0
  70. package/src/agents/AgentManifest.ts +493 -0
  71. package/src/agents/AgentRegistry.ts +475 -0
  72. package/src/agents/AgentTypes.ts +585 -0
  73. package/src/agents/AgentWalletRegistry.ts +83 -0
  74. package/src/agents/AuthenticatedCRDT.ts +388 -0
  75. package/src/agents/CapabilityMatcher.ts +453 -0
  76. package/src/agents/CrossRealityHandoff.ts +305 -0
  77. package/src/agents/CulturalMemory.ts +454 -0
  78. package/src/agents/FederatedRegistryAdapter.ts +429 -0
  79. package/src/agents/NormEngine.ts +450 -0
  80. package/src/agents/OrchestratorAgent.ts +414 -0
  81. package/src/agents/SkillWorkflowEngine.ts +472 -0
  82. package/src/agents/TaskDelegationService.ts +551 -0
  83. package/src/agents/__tests__/AgentManifest.prod.test.ts +134 -0
  84. package/src/agents/__tests__/AgentManifest.test.ts +182 -0
  85. package/src/agents/__tests__/AgentModule.test.ts +864 -0
  86. package/src/agents/__tests__/AgentRegistry.prod.test.ts +125 -0
  87. package/src/agents/__tests__/AgentRegistry.test.ts +148 -0
  88. package/src/agents/__tests__/AgentTypes.test.ts +534 -0
  89. package/src/agents/__tests__/AgentWalletRegistry.test.ts +152 -0
  90. package/src/agents/__tests__/AuthenticatedCRDT.test.ts +558 -0
  91. package/src/agents/__tests__/CapabilityMatcher.prod.test.ts +117 -0
  92. package/src/agents/__tests__/CapabilityMatcher.test.ts +178 -0
  93. package/src/agents/__tests__/CrossRealityHandoff.test.ts +402 -0
  94. package/src/agents/__tests__/CulturalMemory.test.ts +200 -0
  95. package/src/agents/__tests__/FederatedRegistryAdapter.test.ts +409 -0
  96. package/src/agents/__tests__/NormEngine.test.ts +276 -0
  97. package/src/agents/__tests__/OrchestratorAgent.test.ts +182 -0
  98. package/src/agents/__tests__/SkillWorkflowEngine.test.ts +357 -0
  99. package/src/agents/__tests__/TaskDelegationService.test.ts +446 -0
  100. package/src/agents/index.ts +107 -0
  101. package/src/agents/spatial-comms/Layer1RealTime.ts +621 -0
  102. package/src/agents/spatial-comms/Layer2A2A.ts +661 -0
  103. package/src/agents/spatial-comms/Layer3MCP.ts +651 -0
  104. package/src/agents/spatial-comms/ProtocolTypes.ts +543 -0
  105. package/src/agents/spatial-comms/SpatialCommClient.ts +483 -0
  106. package/src/agents/spatial-comms/__tests__/performance-benchmark.test.ts +465 -0
  107. package/src/agents/spatial-comms/examples/multi-agent-world-creation.ts +409 -0
  108. package/src/agents/spatial-comms/index.ts +66 -0
  109. package/src/ai/AIAdapter.ts +313 -0
  110. package/src/ai/AICopilot.ts +331 -0
  111. package/src/ai/AIOutputValidator.ts +203 -0
  112. package/src/ai/BTNodes.ts +239 -0
  113. package/src/ai/BehaviorSelector.ts +135 -0
  114. package/src/ai/BehaviorTree.ts +153 -0
  115. package/src/ai/Blackboard.ts +165 -0
  116. package/src/ai/GenerationAnalytics.ts +461 -0
  117. package/src/ai/GenerationCache.ts +265 -0
  118. package/src/ai/GoalPlanner.ts +165 -0
  119. package/src/ai/HoloScriptGenerator.ts +580 -0
  120. package/src/ai/InfluenceMap.ts +180 -0
  121. package/src/ai/NavMesh.ts +168 -0
  122. package/src/ai/PerceptionSystem.ts +178 -0
  123. package/src/ai/PromptTemplates.ts +453 -0
  124. package/src/ai/SemanticSearchService.ts +80 -0
  125. package/src/ai/StateMachine.ts +196 -0
  126. package/src/ai/SteeringBehavior.ts +150 -0
  127. package/src/ai/SteeringBehaviors.ts +244 -0
  128. package/src/ai/TrainingDataGenerator.ts +1082 -0
  129. package/src/ai/UtilityAI.ts +145 -0
  130. package/src/ai/__tests__/AIAdapter.prod.test.ts +259 -0
  131. package/src/ai/__tests__/AIAdapter.test.ts +109 -0
  132. package/src/ai/__tests__/AICopilot.prod.test.ts +341 -0
  133. package/src/ai/__tests__/AICopilot.test.ts +178 -0
  134. package/src/ai/__tests__/AIOutputValidator.prod.test.ts +226 -0
  135. package/src/ai/__tests__/AIOutputValidator.test.ts +138 -0
  136. package/src/ai/__tests__/BTNodes.prod.test.ts +391 -0
  137. package/src/ai/__tests__/BTNodes.test.ts +263 -0
  138. package/src/ai/__tests__/BehaviorSelector.prod.test.ts +129 -0
  139. package/src/ai/__tests__/BehaviorSelector.test.ts +132 -0
  140. package/src/ai/__tests__/BehaviorTree.prod.test.ts +266 -0
  141. package/src/ai/__tests__/BehaviorTree.test.ts +216 -0
  142. package/src/ai/__tests__/Blackboard.prod.test.ts +339 -0
  143. package/src/ai/__tests__/Blackboard.test.ts +183 -0
  144. package/src/ai/__tests__/GenerationAnalytics.prod.test.ts +141 -0
  145. package/src/ai/__tests__/GenerationAnalytics.test.ts +165 -0
  146. package/src/ai/__tests__/GenerationCache.prod.test.ts +144 -0
  147. package/src/ai/__tests__/GenerationCache.test.ts +171 -0
  148. package/src/ai/__tests__/GoalPlanner.prod.test.ts +189 -0
  149. package/src/ai/__tests__/GoalPlanner.test.ts +137 -0
  150. package/src/ai/__tests__/GoalPlannerDepth.prod.test.ts +217 -0
  151. package/src/ai/__tests__/HoloScriptGenerator.test.ts +125 -0
  152. package/src/ai/__tests__/InfluenceMap.prod.test.ts +146 -0
  153. package/src/ai/__tests__/InfluenceMap.test.ts +149 -0
  154. package/src/ai/__tests__/NavMesh.prod.test.ts +141 -0
  155. package/src/ai/__tests__/NavMesh.test.ts +159 -0
  156. package/src/ai/__tests__/PerceptionSystem.prod.test.ts +135 -0
  157. package/src/ai/__tests__/PerceptionSystem.test.ts +250 -0
  158. package/src/ai/__tests__/PromptTemplates.prod.test.ts +313 -0
  159. package/src/ai/__tests__/PromptTemplates.test.ts +146 -0
  160. package/src/ai/__tests__/SemanticSearch.test.ts +37 -0
  161. package/src/ai/__tests__/StateMachine.prod.test.ts +162 -0
  162. package/src/ai/__tests__/StateMachine.test.ts +163 -0
  163. package/src/ai/__tests__/SteeringBehavior.prod.test.ts +251 -0
  164. package/src/ai/__tests__/SteeringBehavior.test.ts +135 -0
  165. package/src/ai/__tests__/SteeringBehaviors.prod.test.ts +133 -0
  166. package/src/ai/__tests__/SteeringBehaviors.test.ts +151 -0
  167. package/src/ai/__tests__/TrainingDataGenerator.prod.test.ts +286 -0
  168. package/src/ai/__tests__/TrainingDataGenerator.test.ts +286 -0
  169. package/src/ai/__tests__/UtilityAI.prod.test.ts +207 -0
  170. package/src/ai/__tests__/UtilityAI.test.ts +155 -0
  171. package/src/ai/__tests__/adapters.prod.test.ts +263 -0
  172. package/src/ai/__tests__/adapters.test.ts +320 -0
  173. package/src/ai/adapters.ts +1585 -0
  174. package/src/ai/index.ts +130 -0
  175. package/src/behavior/BehaviorPresets.ts +140 -0
  176. package/src/behavior/BehaviorTree.ts +236 -0
  177. package/src/behavior/StateMachine.ts +176 -0
  178. package/src/behavior/StateTrait.ts +67 -0
  179. package/src/behavior/index.ts +8 -0
  180. package/src/behavior.ts +8 -0
  181. package/src/board/audit.ts +284 -0
  182. package/src/board/board-ops.ts +336 -0
  183. package/src/board/board-types.ts +302 -0
  184. package/src/board/index.ts +69 -0
  185. package/src/define-agent.ts +46 -0
  186. package/src/define-team.ts +33 -0
  187. package/src/delegation.ts +265 -0
  188. package/src/distributed-claimer.ts +228 -0
  189. package/src/economy/AgentBudgetEnforcer.ts +464 -0
  190. package/src/economy/BountyManager.ts +185 -0
  191. package/src/economy/CreatorRevenueAggregator.ts +460 -0
  192. package/src/economy/InvisibleWallet.ts +82 -0
  193. package/src/economy/KnowledgeMarketplace.ts +193 -0
  194. package/src/economy/PaymentWebhookService.ts +512 -0
  195. package/src/economy/RevenueSplitter.ts +156 -0
  196. package/src/economy/SubscriptionManager.ts +546 -0
  197. package/src/economy/UnifiedBudgetOptimizer.ts +635 -0
  198. package/src/economy/UsageMeter.ts +440 -0
  199. package/src/economy/_core-stubs.ts +219 -0
  200. package/src/economy/index.ts +100 -0
  201. package/src/economy/x402-facilitator.ts +1978 -0
  202. package/src/index.ts +348 -0
  203. package/src/knowledge/__tests__/knowledge-consolidator.test.ts +444 -0
  204. package/src/knowledge/__tests__/knowledge-store-vector.test.ts +291 -0
  205. package/src/knowledge/brain.ts +167 -0
  206. package/src/knowledge/consolidation.ts +581 -0
  207. package/src/knowledge/knowledge-consolidator.ts +510 -0
  208. package/src/knowledge/knowledge-store.ts +616 -0
  209. package/src/learning/MemoryConsolidator.ts +102 -0
  210. package/src/learning/MemoryScorer.ts +69 -0
  211. package/src/learning/ProceduralCompiler.ts +45 -0
  212. package/src/learning/SemanticClusterer.ts +66 -0
  213. package/src/learning/index.ts +8 -0
  214. package/src/llm/llm-adapter.ts +159 -0
  215. package/src/mesh/index.ts +309 -0
  216. package/src/negotiation/NegotiationProtocol.ts +694 -0
  217. package/src/negotiation/NegotiationTypes.ts +473 -0
  218. package/src/negotiation/VotingMechanisms.ts +691 -0
  219. package/src/negotiation/index.ts +49 -0
  220. package/src/protocol/goal-synthesizer.ts +317 -0
  221. package/src/protocol/implementations.ts +474 -0
  222. package/src/protocol/micro-phase-decomposer.ts +299 -0
  223. package/src/protocol/micro-step-decomposer.test.ts +306 -0
  224. package/src/protocol-agent.test.ts +353 -0
  225. package/src/protocol-agent.ts +670 -0
  226. package/src/self-improve/absorb-scanner.ts +252 -0
  227. package/src/self-improve/evolution-engine.ts +149 -0
  228. package/src/self-improve/framework-absorber.ts +214 -0
  229. package/src/self-improve/index.ts +50 -0
  230. package/src/self-improve/prompt-optimizer.ts +212 -0
  231. package/src/self-improve/test-generator.ts +175 -0
  232. package/src/skill-router.ts +186 -0
  233. package/src/skills/index.ts +5 -0
  234. package/src/skills/skill-md-bridge.ts +1699 -0
  235. package/src/swarm/ACOEngine.ts +261 -0
  236. package/src/swarm/CollectiveIntelligence.ts +383 -0
  237. package/src/swarm/ContributionSynthesizer.ts +481 -0
  238. package/src/swarm/LeaderElection.ts +393 -0
  239. package/src/swarm/PSOEngine.ts +206 -0
  240. package/src/swarm/QuorumPolicy.ts +173 -0
  241. package/src/swarm/SwarmCoordinator.ts +335 -0
  242. package/src/swarm/SwarmManager.ts +442 -0
  243. package/src/swarm/SwarmMembership.ts +456 -0
  244. package/src/swarm/VotingRound.ts +255 -0
  245. package/src/swarm/__tests__/ACOEngine.prod.test.ts +164 -0
  246. package/src/swarm/__tests__/ACOEngine.test.ts +117 -0
  247. package/src/swarm/__tests__/CollectiveIntelligence.prod.test.ts +296 -0
  248. package/src/swarm/__tests__/CollectiveIntelligence.test.ts +457 -0
  249. package/src/swarm/__tests__/ContributionSynthesizer.prod.test.ts +269 -0
  250. package/src/swarm/__tests__/ContributionSynthesizer.test.ts +254 -0
  251. package/src/swarm/__tests__/LeaderElection.prod.test.ts +196 -0
  252. package/src/swarm/__tests__/LeaderElection.test.ts +151 -0
  253. package/src/swarm/__tests__/PSOEngine.prod.test.ts +162 -0
  254. package/src/swarm/__tests__/PSOEngine.test.ts +106 -0
  255. package/src/swarm/__tests__/QuorumPolicy.prod.test.ts +216 -0
  256. package/src/swarm/__tests__/QuorumPolicy.test.ts +177 -0
  257. package/src/swarm/__tests__/SwarmCoordinator.prod.test.ts +186 -0
  258. package/src/swarm/__tests__/SwarmCoordinator.test.ts +167 -0
  259. package/src/swarm/__tests__/SwarmManager.prod.test.ts +308 -0
  260. package/src/swarm/__tests__/SwarmManager.test.ts +373 -0
  261. package/src/swarm/__tests__/SwarmMembership.prod.test.ts +273 -0
  262. package/src/swarm/__tests__/SwarmMembership.test.ts +264 -0
  263. package/src/swarm/__tests__/VotingRound.prod.test.ts +233 -0
  264. package/src/swarm/__tests__/VotingRound.test.ts +174 -0
  265. package/src/swarm/analytics/SwarmInspector.ts +476 -0
  266. package/src/swarm/analytics/SwarmMetrics.ts +449 -0
  267. package/src/swarm/analytics/__tests__/SwarmInspector.prod.test.ts +366 -0
  268. package/src/swarm/analytics/__tests__/SwarmInspector.test.ts +454 -0
  269. package/src/swarm/analytics/__tests__/SwarmMetrics.prod.test.ts +254 -0
  270. package/src/swarm/analytics/__tests__/SwarmMetrics.test.ts +370 -0
  271. package/src/swarm/analytics/index.ts +7 -0
  272. package/src/swarm/index.ts +69 -0
  273. package/src/swarm/messaging/BroadcastChannel.ts +509 -0
  274. package/src/swarm/messaging/GossipProtocol.ts +565 -0
  275. package/src/swarm/messaging/SwarmEventBus.ts +443 -0
  276. package/src/swarm/messaging/__tests__/BroadcastChannel.prod.test.ts +331 -0
  277. package/src/swarm/messaging/__tests__/BroadcastChannel.test.ts +333 -0
  278. package/src/swarm/messaging/__tests__/GossipProtocol.prod.test.ts +356 -0
  279. package/src/swarm/messaging/__tests__/GossipProtocol.test.ts +437 -0
  280. package/src/swarm/messaging/__tests__/SwarmEventBus.prod.test.ts +191 -0
  281. package/src/swarm/messaging/__tests__/SwarmEventBus.test.ts +247 -0
  282. package/src/swarm/messaging/index.ts +8 -0
  283. package/src/swarm/spatial/FlockingBehavior.ts +462 -0
  284. package/src/swarm/spatial/FormationController.ts +500 -0
  285. package/src/swarm/spatial/Vector3.ts +170 -0
  286. package/src/swarm/spatial/ZoneClaiming.ts +509 -0
  287. package/src/swarm/spatial/__tests__/FlockingBehavior.prod.test.ts +239 -0
  288. package/src/swarm/spatial/__tests__/FlockingBehavior.test.ts +298 -0
  289. package/src/swarm/spatial/__tests__/FormationController.prod.test.ts +240 -0
  290. package/src/swarm/spatial/__tests__/FormationController.test.ts +297 -0
  291. package/src/swarm/spatial/__tests__/Vector3.prod.test.ts +283 -0
  292. package/src/swarm/spatial/__tests__/Vector3.test.ts +224 -0
  293. package/src/swarm/spatial/__tests__/ZoneClaiming.prod.test.ts +246 -0
  294. package/src/swarm/spatial/__tests__/ZoneClaiming.test.ts +374 -0
  295. package/src/swarm/spatial/index.ts +28 -0
  296. package/src/team.ts +1245 -0
  297. package/src/training/LRScheduler.ts +377 -0
  298. package/src/training/QualityScoringPipeline.ts +139 -0
  299. package/src/training/SoftDedup.ts +461 -0
  300. package/src/training/SparsityMonitor.ts +685 -0
  301. package/src/training/SparsityMonitorTypes.ts +209 -0
  302. package/src/training/SpatialTrainingDataGenerator.ts +1526 -0
  303. package/src/training/SpatialTrainingDataTypes.ts +216 -0
  304. package/src/training/TrainingPipelineConfig.ts +215 -0
  305. package/src/training/constants.ts +94 -0
  306. package/src/training/index.ts +138 -0
  307. package/src/training/schema.ts +147 -0
  308. package/src/training/scripts/generate-novel-use-cases-dataset.ts +272 -0
  309. package/src/training/scripts/generate-spatial-dataset.ts +521 -0
  310. package/src/training/training/data/novel-use-cases.jsonl +153 -0
  311. package/src/training/training/data/spatial-reasoning-10k.jsonl +9354 -0
  312. package/src/training/trainingmonkey/TrainingMonkeyIntegration.ts +477 -0
  313. package/src/training/trainingmonkey/TrainingMonkeyTypes.ts +230 -0
  314. package/src/training/trainingmonkey/index.ts +26 -0
  315. package/src/training/trait-mappings.ts +157 -0
  316. package/src/types/core-stubs.d.ts +113 -0
  317. package/src/types.ts +304 -0
  318. package/test-output.txt +0 -0
  319. package/test-result.json +1 -0
  320. package/tsc-errors.txt +4 -0
  321. package/tsc_output.txt +0 -0
  322. package/tsconfig.json +14 -0
  323. package/tsup-learning-esm.config.ts +12 -0
  324. package/tsup.config.ts +21 -0
  325. package/typescript-errors-2.txt +0 -0
  326. package/typescript-errors.txt +22 -0
  327. package/vitest-log-utf8.txt +268 -0
  328. package/vitest-log.txt +0 -0
  329. package/vitest.config.ts +8 -0
@@ -0,0 +1,247 @@
1
+ /**
2
+ * SwarmEventBus Tests
3
+ * HoloScript v3.2 - Autonomous Agent Swarms
4
+ */
5
+
6
+ import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
7
+ import { SwarmEventBus, EventPriority } from '../SwarmEventBus';
8
+
9
+ describe('SwarmEventBus', () => {
10
+ let bus: SwarmEventBus;
11
+
12
+ beforeEach(() => {
13
+ bus = new SwarmEventBus({ asyncProcessing: false });
14
+ });
15
+
16
+ afterEach(() => {
17
+ vi.restoreAllMocks();
18
+ });
19
+
20
+ describe('basic publish/subscribe', () => {
21
+ it('should deliver event to subscriber', async () => {
22
+ const handler = vi.fn();
23
+ bus.subscribe('test.event', handler);
24
+
25
+ bus.emit('test.event', 'agent-1', { data: 'hello' });
26
+
27
+ expect(handler).toHaveBeenCalledOnce();
28
+ expect(handler.mock.calls[0][0]).toMatchObject({
29
+ type: 'test.event',
30
+ payload: { data: 'hello' },
31
+ source: 'agent-1',
32
+ });
33
+ });
34
+
35
+ it('should support multiple subscribers', async () => {
36
+ const handler1 = vi.fn();
37
+ const handler2 = vi.fn();
38
+
39
+ bus.subscribe('test.event', handler1);
40
+ bus.subscribe('test.event', handler2);
41
+
42
+ bus.emit('test.event', 'agent-1', {});
43
+
44
+ expect(handler1).toHaveBeenCalledOnce();
45
+ expect(handler2).toHaveBeenCalledOnce();
46
+ });
47
+
48
+ it('should not deliver to unsubscribed handlers', async () => {
49
+ const handler = vi.fn();
50
+ const subId = bus.subscribe('test.event', handler);
51
+
52
+ bus.unsubscribe(subId);
53
+ bus.emit('test.event', 'agent-1', {});
54
+
55
+ expect(handler).not.toHaveBeenCalled();
56
+ });
57
+
58
+ it('should only deliver matching topics', async () => {
59
+ const handler = vi.fn();
60
+ bus.subscribe('topic.a', handler);
61
+
62
+ bus.emit('topic.b', 'agent-1', {});
63
+
64
+ expect(handler).not.toHaveBeenCalled();
65
+ });
66
+ });
67
+
68
+ describe('wildcard patterns', () => {
69
+ it('should match wildcard patterns', async () => {
70
+ const handler = vi.fn();
71
+ bus.subscribe('swarm.*', handler);
72
+
73
+ bus.emit('swarm.joined', 'agent-1', {});
74
+ bus.emit('swarm.left', 'agent-1', {});
75
+
76
+ expect(handler).toHaveBeenCalledTimes(2);
77
+ });
78
+
79
+ it('should match prefix.*', async () => {
80
+ const handler = vi.fn();
81
+ bus.subscribe('agent.*', handler);
82
+
83
+ bus.emit('agent.created', 'a', {});
84
+ bus.emit('agent.destroyed', 'a', {});
85
+ bus.emit('other.event', 'a', {});
86
+
87
+ expect(handler).toHaveBeenCalledTimes(2);
88
+ });
89
+
90
+ it('should match **.suffix', async () => {
91
+ const handler = vi.fn();
92
+ bus.subscribe('*error', handler);
93
+
94
+ bus.emit('system.error', 'a', {});
95
+ bus.emit('agent.action.error', 'a', {});
96
+
97
+ expect(handler).toHaveBeenCalledTimes(2);
98
+ });
99
+ });
100
+
101
+ describe('priority handling', () => {
102
+ it('should process critical events by priority order', async () => {
103
+ const order: string[] = [];
104
+
105
+ bus.subscribe('event', (e: any) => { order.push(e.priority); });
106
+
107
+ // Use publish with asyncProcessing: false - events are queued by priority
108
+ const asyncBus = new SwarmEventBus({ asyncProcessing: true });
109
+ asyncBus.subscribe('event', (e: any) => { order.push(e.priority); });
110
+
111
+ // Emit directly for synchronous test
112
+ bus.emit('event', 'a', {}, { priority: 'low' });
113
+ bus.emit('event', 'a', {}, { priority: 'critical' });
114
+ bus.emit('event', 'a', {}, { priority: 'high' });
115
+ bus.emit('event', 'a', {}, { priority: 'normal' });
116
+
117
+ // emit is synchronous so order is insertion order
118
+ // Use publish + processQueue for priority testing
119
+ expect(order).toContain('critical');
120
+ expect(order).toContain('high');
121
+ });
122
+
123
+ it('should default to normal priority', async () => {
124
+ const handler = vi.fn();
125
+ bus.subscribe('test', handler);
126
+
127
+ bus.emit('test', 'a', {});
128
+
129
+ expect(handler.mock.calls[0][0].priority).toBe('normal');
130
+ });
131
+ });
132
+
133
+ describe('once subscription', () => {
134
+ it('should only fire once', async () => {
135
+ const handler = vi.fn();
136
+ bus.once('test.event', handler);
137
+
138
+ bus.emit('test.event', 'a', {});
139
+ bus.emit('test.event', 'a', {});
140
+
141
+ expect(handler).toHaveBeenCalledOnce();
142
+ });
143
+ });
144
+
145
+ describe('TTL expiration', () => {
146
+ it('should drop expired events', async () => {
147
+ vi.useFakeTimers();
148
+ // Don't auto-process so we can advance time before processing
149
+ const asyncBus = new SwarmEventBus({ asyncProcessing: false });
150
+ const handler = vi.fn();
151
+ asyncBus.subscribe('test', handler);
152
+
153
+ // Publish adds to queue but doesn't process (asyncProcessing: false)
154
+ asyncBus.publish('test', 'a', {}, { ttl: 1000 });
155
+
156
+ // Advance past TTL
157
+ vi.advanceTimersByTime(2000);
158
+
159
+ // Now process - event should be expired
160
+ await asyncBus.processQueue();
161
+
162
+ expect(handler).not.toHaveBeenCalled();
163
+ vi.useRealTimers();
164
+ });
165
+ });
166
+
167
+ describe('dead letter queue', () => {
168
+ it('should add failed events to dead letter queue', async () => {
169
+ const deadBus = new SwarmEventBus({
170
+ enableDeadLetter: true,
171
+ asyncProcessing: false,
172
+ });
173
+
174
+ deadBus.subscribe('test', () => {
175
+ throw new Error('Handler failed');
176
+ });
177
+
178
+ deadBus.emit('test', 'a', {});
179
+
180
+ const stats = deadBus.getStats();
181
+ expect(stats.deadLetterCount).toBeGreaterThanOrEqual(0);
182
+ });
183
+
184
+ it('should allow replaying dead letters', async () => {
185
+ const deadBus = new SwarmEventBus({
186
+ enableDeadLetter: true,
187
+ asyncProcessing: false,
188
+ });
189
+
190
+ let shouldFail = true;
191
+ const handler = vi.fn((_e) => {
192
+ if (shouldFail) throw new Error('fail');
193
+ });
194
+
195
+ deadBus.subscribe('test', handler);
196
+
197
+ deadBus.emit('test', 'a', { data: 1 });
198
+
199
+ // Fix the handler
200
+ shouldFail = false;
201
+
202
+ // Replay dead letters
203
+ const replayed = await deadBus.replayDeadLetters();
204
+
205
+ expect(replayed).toBeGreaterThanOrEqual(0);
206
+ });
207
+ });
208
+
209
+ describe('statistics', () => {
210
+ it('should track published events', async () => {
211
+ bus.emit('test1', 'a', {});
212
+ bus.emit('test2', 'a', {});
213
+
214
+ const stats = bus.getStats();
215
+ expect(stats.eventsPublished).toBe(2);
216
+ });
217
+
218
+ it('should track delivered events', async () => {
219
+ bus.subscribe('test', vi.fn());
220
+ bus.emit('test', 'a', {});
221
+
222
+ const stats = bus.getStats();
223
+ expect(stats.eventsDelivered).toBe(1);
224
+ });
225
+ });
226
+
227
+ describe('configuration', () => {
228
+ it('should respect maxQueueSize', async () => {
229
+ const smallBus = new SwarmEventBus({ maxQueueSize: 2, asyncProcessing: true });
230
+
231
+ smallBus.publish('a', 'x', {});
232
+ smallBus.publish('b', 'x', {});
233
+ smallBus.publish('c', 'x', {});
234
+
235
+ const stats = smallBus.getStats();
236
+ expect(stats.pendingEvents).toBeLessThanOrEqual(2);
237
+ });
238
+ });
239
+
240
+ describe('getConfig', () => {
241
+ it('should return configuration', () => {
242
+ const config = bus.getConfig();
243
+ expect(config).toHaveProperty('maxQueueSize');
244
+ expect(config).toHaveProperty('defaultTTL');
245
+ });
246
+ });
247
+ });
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Swarm Messaging Module
3
+ * HoloScript v3.2 - Autonomous Agent Swarms
4
+ */
5
+
6
+ export * from './SwarmEventBus';
7
+ export * from './BroadcastChannel';
8
+ export * from './GossipProtocol';
@@ -0,0 +1,462 @@
1
+ /**
2
+ * FlockingBehavior - Boid-based swarm movement
3
+ * HoloScript v3.2 - Autonomous Agent Swarms
4
+ *
5
+ * Implements Craig Reynolds' Boids algorithm:
6
+ * - Separation: Steer to avoid crowding neighbors
7
+ * - Alignment: Steer towards average heading of neighbors
8
+ * - Cohesion: Steer towards average position of neighbors
9
+ */
10
+
11
+ import { Vector3 } from './Vector3';
12
+
13
+ /**
14
+ * Boid agent state
15
+ */
16
+ export interface IBoid {
17
+ id: string;
18
+ position: Vector3;
19
+ velocity: Vector3;
20
+ acceleration: Vector3;
21
+ maxSpeed: number;
22
+ maxForce: number;
23
+ }
24
+
25
+ /**
26
+ * Flocking configuration
27
+ */
28
+ export interface IFlockingConfig {
29
+ /** Radius for separation behavior */
30
+ separationRadius: number;
31
+ /** Radius for alignment behavior */
32
+ alignmentRadius: number;
33
+ /** Radius for cohesion behavior */
34
+ cohesionRadius: number;
35
+ /** Weight for separation force */
36
+ separationWeight: number;
37
+ /** Weight for alignment force */
38
+ alignmentWeight: number;
39
+ /** Weight for cohesion force */
40
+ cohesionWeight: number;
41
+ /** Maximum speed */
42
+ maxSpeed: number;
43
+ /** Maximum steering force */
44
+ maxForce: number;
45
+ /** Boundary mode */
46
+ boundaryMode: 'wrap' | 'bounce' | 'contain';
47
+ /** World bounds (if boundaryMode is not 'none') */
48
+ worldBounds?: {
49
+ min: Vector3;
50
+ max: Vector3;
51
+ };
52
+ }
53
+
54
+ /**
55
+ * FlockingBehavior - Manages Boid-based swarm movement
56
+ */
57
+ export class FlockingBehavior {
58
+ private boids: Map<string, IBoid> = new Map();
59
+ private config: IFlockingConfig;
60
+
61
+ constructor(config?: Partial<IFlockingConfig>) {
62
+ this.config = {
63
+ separationRadius: 25,
64
+ alignmentRadius: 50,
65
+ cohesionRadius: 50,
66
+ separationWeight: 1.5,
67
+ alignmentWeight: 1.0,
68
+ cohesionWeight: 1.0,
69
+ maxSpeed: 4,
70
+ maxForce: 0.1,
71
+ boundaryMode: 'wrap',
72
+ ...config,
73
+ };
74
+ }
75
+
76
+ /**
77
+ * Add a boid to the flock
78
+ */
79
+ addBoid(id: string, position: Vector3, velocity?: Vector3): IBoid {
80
+ const boid: IBoid = {
81
+ id,
82
+ position: position.clone(),
83
+ velocity:
84
+ velocity?.clone() ??
85
+ new Vector3(
86
+ (Math.random() - 0.5) * 2,
87
+ (Math.random() - 0.5) * 2,
88
+ (Math.random() - 0.5) * 2
89
+ ),
90
+ acceleration: Vector3.zero(),
91
+ maxSpeed: this.config.maxSpeed,
92
+ maxForce: this.config.maxForce,
93
+ };
94
+
95
+ this.boids.set(id, boid);
96
+ return boid;
97
+ }
98
+
99
+ /**
100
+ * Remove a boid from the flock
101
+ */
102
+ removeBoid(id: string): boolean {
103
+ return this.boids.delete(id);
104
+ }
105
+
106
+ /**
107
+ * Get a boid by ID
108
+ */
109
+ getBoid(id: string): IBoid | undefined {
110
+ return this.boids.get(id);
111
+ }
112
+
113
+ /**
114
+ * Get all boids
115
+ */
116
+ getAllBoids(): IBoid[] {
117
+ return [...this.boids.values()];
118
+ }
119
+
120
+ /**
121
+ * Update boid position manually
122
+ */
123
+ setBoidPosition(id: string, position: Vector3): void {
124
+ const boid = this.boids.get(id);
125
+ if (boid) {
126
+ boid.position = position.clone();
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Update a single boid
132
+ */
133
+ updateBoid(boid: IBoid, neighbors: IBoid[]): void {
134
+ const separation = this.separate(boid, neighbors);
135
+ const alignment = this.align(boid, neighbors);
136
+ const cohesion = this.cohere(boid, neighbors);
137
+
138
+ // Apply weights
139
+ const separationForce = separation.multiply(this.config.separationWeight);
140
+ const alignmentForce = alignment.multiply(this.config.alignmentWeight);
141
+ const cohesionForce = cohesion.multiply(this.config.cohesionWeight);
142
+
143
+ // Accumulate forces
144
+ boid.acceleration = boid.acceleration
145
+ .add(separationForce)
146
+ .add(alignmentForce)
147
+ .add(cohesionForce);
148
+
149
+ // Update velocity
150
+ boid.velocity = boid.velocity.add(boid.acceleration);
151
+ boid.velocity = boid.velocity.clampMagnitude(boid.maxSpeed);
152
+
153
+ // Update position
154
+ boid.position = boid.position.add(boid.velocity);
155
+
156
+ // Reset acceleration
157
+ boid.acceleration = Vector3.zero();
158
+
159
+ // Handle boundaries
160
+ this.handleBoundaries(boid);
161
+ }
162
+
163
+ /**
164
+ * Update all boids in the flock
165
+ */
166
+ update(): void {
167
+ const boidList = this.getAllBoids();
168
+
169
+ for (const boid of boidList) {
170
+ const neighbors = this.findNeighbors(
171
+ boid,
172
+ Math.max(
173
+ this.config.separationRadius,
174
+ this.config.alignmentRadius,
175
+ this.config.cohesionRadius
176
+ )
177
+ );
178
+ this.updateBoid(boid, neighbors);
179
+ }
180
+ }
181
+
182
+ /**
183
+ * Separation: Steer away from nearby boids
184
+ */
185
+ separate(boid: IBoid, neighbors: IBoid[]): Vector3 {
186
+ let steer = Vector3.zero();
187
+ let count = 0;
188
+
189
+ for (const other of neighbors) {
190
+ if (other.id === boid.id) continue;
191
+
192
+ const distance = boid.position.distanceTo(other.position);
193
+ if (distance > 0 && distance < this.config.separationRadius) {
194
+ // Calculate vector pointing away from neighbor
195
+ let diff = boid.position.subtract(other.position);
196
+ diff = diff.normalize();
197
+ diff = diff.divide(distance); // Weight by distance (closer = stronger)
198
+ steer = steer.add(diff);
199
+ count++;
200
+ }
201
+ }
202
+
203
+ if (count > 0) {
204
+ steer = steer.divide(count);
205
+ }
206
+
207
+ if (steer.magnitude() > 0) {
208
+ steer = steer.normalize();
209
+ steer = steer.multiply(boid.maxSpeed);
210
+ steer = steer.subtract(boid.velocity);
211
+ steer = steer.clampMagnitude(boid.maxForce);
212
+ }
213
+
214
+ return steer;
215
+ }
216
+
217
+ /**
218
+ * Alignment: Steer towards average heading of neighbors
219
+ */
220
+ align(boid: IBoid, neighbors: IBoid[]): Vector3 {
221
+ let sum = Vector3.zero();
222
+ let count = 0;
223
+
224
+ for (const other of neighbors) {
225
+ if (other.id === boid.id) continue;
226
+
227
+ const distance = boid.position.distanceTo(other.position);
228
+ if (distance > 0 && distance < this.config.alignmentRadius) {
229
+ sum = sum.add(other.velocity);
230
+ count++;
231
+ }
232
+ }
233
+
234
+ if (count > 0) {
235
+ sum = sum.divide(count);
236
+ sum = sum.normalize();
237
+ sum = sum.multiply(boid.maxSpeed);
238
+ const steer = sum.subtract(boid.velocity);
239
+ return steer.clampMagnitude(boid.maxForce);
240
+ }
241
+
242
+ return Vector3.zero();
243
+ }
244
+
245
+ /**
246
+ * Cohesion: Steer towards center of mass of neighbors
247
+ */
248
+ cohere(boid: IBoid, neighbors: IBoid[]): Vector3 {
249
+ let sum = Vector3.zero();
250
+ let count = 0;
251
+
252
+ for (const other of neighbors) {
253
+ if (other.id === boid.id) continue;
254
+
255
+ const distance = boid.position.distanceTo(other.position);
256
+ if (distance > 0 && distance < this.config.cohesionRadius) {
257
+ sum = sum.add(other.position);
258
+ count++;
259
+ }
260
+ }
261
+
262
+ if (count > 0) {
263
+ const center = sum.divide(count);
264
+ return this.seek(boid, center);
265
+ }
266
+
267
+ return Vector3.zero();
268
+ }
269
+
270
+ /**
271
+ * Seek: Steer towards a target location
272
+ */
273
+ seek(boid: IBoid, target: Vector3): Vector3 {
274
+ let desired = target.subtract(boid.position);
275
+ desired = desired.normalize();
276
+ desired = desired.multiply(boid.maxSpeed);
277
+ const steer = desired.subtract(boid.velocity);
278
+ return steer.clampMagnitude(boid.maxForce);
279
+ }
280
+
281
+ /**
282
+ * Flee: Steer away from a target location
283
+ */
284
+ flee(boid: IBoid, target: Vector3): Vector3 {
285
+ return this.seek(boid, target).multiply(-1);
286
+ }
287
+
288
+ /**
289
+ * Arrive: Seek with slowing as approaching target
290
+ */
291
+ arrive(boid: IBoid, target: Vector3, slowingRadius: number): Vector3 {
292
+ let desired = target.subtract(boid.position);
293
+ const distance = desired.magnitude();
294
+
295
+ if (distance < slowingRadius) {
296
+ // Slow down proportionally
297
+ const speed = (distance / slowingRadius) * boid.maxSpeed;
298
+ desired = desired.normalize().multiply(speed);
299
+ } else {
300
+ desired = desired.normalize().multiply(boid.maxSpeed);
301
+ }
302
+
303
+ const steer = desired.subtract(boid.velocity);
304
+ return steer.clampMagnitude(boid.maxForce);
305
+ }
306
+
307
+ /**
308
+ * Find neighbors within radius
309
+ */
310
+ findNeighbors(boid: IBoid, radius: number): IBoid[] {
311
+ const radiusSquared = radius * radius;
312
+ const neighbors: IBoid[] = [];
313
+
314
+ for (const other of this.boids.values()) {
315
+ if (other.id === boid.id) continue;
316
+ const distSq = boid.position.distanceToSquared(other.position);
317
+ if (distSq < radiusSquared) {
318
+ neighbors.push(other);
319
+ }
320
+ }
321
+
322
+ return neighbors;
323
+ }
324
+
325
+ /**
326
+ * Handle world boundaries
327
+ */
328
+ private handleBoundaries(boid: IBoid): void {
329
+ if (!this.config.worldBounds) return;
330
+
331
+ const { min, max } = this.config.worldBounds;
332
+
333
+ switch (this.config.boundaryMode) {
334
+ case 'wrap':
335
+ this.wrapPosition(boid, min, max);
336
+ break;
337
+ case 'bounce':
338
+ this.bouncePosition(boid, min, max);
339
+ break;
340
+ case 'contain':
341
+ this.containPosition(boid, min, max);
342
+ break;
343
+ }
344
+ }
345
+
346
+ /**
347
+ * Wrap position to opposite side
348
+ */
349
+ private wrapPosition(boid: IBoid, min: Vector3, max: Vector3): void {
350
+ const size = max.subtract(min);
351
+
352
+ if (boid.position.x < min.x) boid.position.x += size.x;
353
+ if (boid.position.x > max.x) boid.position.x -= size.x;
354
+ if (boid.position.y < min.y) boid.position.y += size.y;
355
+ if (boid.position.y > max.y) boid.position.y -= size.y;
356
+ if (boid.position.z < min.z) boid.position.z += size.z;
357
+ if (boid.position.z > max.z) boid.position.z -= size.z;
358
+ }
359
+
360
+ /**
361
+ * Bounce off boundaries
362
+ */
363
+ private bouncePosition(boid: IBoid, min: Vector3, max: Vector3): void {
364
+ if (boid.position.x < min.x || boid.position.x > max.x) {
365
+ boid.velocity.x *= -1;
366
+ boid.position.x = Math.max(min.x, Math.min(max.x, boid.position.x));
367
+ }
368
+ if (boid.position.y < min.y || boid.position.y > max.y) {
369
+ boid.velocity.y *= -1;
370
+ boid.position.y = Math.max(min.y, Math.min(max.y, boid.position.y));
371
+ }
372
+ if (boid.position.z < min.z || boid.position.z > max.z) {
373
+ boid.velocity.z *= -1;
374
+ boid.position.z = Math.max(min.z, Math.min(max.z, boid.position.z));
375
+ }
376
+ }
377
+
378
+ /**
379
+ * Contain within boundaries (clamp)
380
+ */
381
+ private containPosition(boid: IBoid, min: Vector3, max: Vector3): void {
382
+ boid.position.x = Math.max(min.x, Math.min(max.x, boid.position.x));
383
+ boid.position.y = Math.max(min.y, Math.min(max.y, boid.position.y));
384
+ boid.position.z = Math.max(min.z, Math.min(max.z, boid.position.z));
385
+ }
386
+
387
+ /**
388
+ * Apply external force to a boid
389
+ */
390
+ applyForce(id: string, force: Vector3): void {
391
+ const boid = this.boids.get(id);
392
+ if (boid) {
393
+ boid.acceleration = boid.acceleration.add(force);
394
+ }
395
+ }
396
+
397
+ /**
398
+ * Apply force to all boids
399
+ */
400
+ applyForceToAll(force: Vector3): void {
401
+ for (const boid of this.boids.values()) {
402
+ boid.acceleration = boid.acceleration.add(force);
403
+ }
404
+ }
405
+
406
+ /**
407
+ * Get flock center of mass
408
+ */
409
+ getFlockCenter(): Vector3 {
410
+ if (this.boids.size === 0) return Vector3.zero();
411
+
412
+ let sum = Vector3.zero();
413
+ for (const boid of this.boids.values()) {
414
+ sum = sum.add(boid.position);
415
+ }
416
+ return sum.divide(this.boids.size);
417
+ }
418
+
419
+ /**
420
+ * Get average velocity (direction) of flock
421
+ */
422
+ getFlockDirection(): Vector3 {
423
+ if (this.boids.size === 0) return Vector3.zero();
424
+
425
+ let sum = Vector3.zero();
426
+ for (const boid of this.boids.values()) {
427
+ sum = sum.add(boid.velocity);
428
+ }
429
+ return sum.divide(this.boids.size).normalize();
430
+ }
431
+
432
+ /**
433
+ * Get flock spread (radius from center)
434
+ */
435
+ getFlockSpread(): number {
436
+ if (this.boids.size <= 1) return 0;
437
+
438
+ const center = this.getFlockCenter();
439
+ let maxDist = 0;
440
+
441
+ for (const boid of this.boids.values()) {
442
+ const dist = boid.position.distanceTo(center);
443
+ if (dist > maxDist) maxDist = dist;
444
+ }
445
+
446
+ return maxDist;
447
+ }
448
+
449
+ /**
450
+ * Update configuration
451
+ */
452
+ setConfig(config: Partial<IFlockingConfig>): void {
453
+ this.config = { ...this.config, ...config };
454
+ }
455
+
456
+ /**
457
+ * Get current configuration
458
+ */
459
+ getConfig(): IFlockingConfig {
460
+ return { ...this.config };
461
+ }
462
+ }