@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.
- package/ALL-test-results.json +1 -0
- package/CHANGELOG.md +8 -0
- package/LICENSE +21 -0
- package/ROADMAP.md +175 -0
- package/dist/AgentManifest-CB4xM-Ma.d.cts +704 -0
- package/dist/AgentManifest-CB4xM-Ma.d.ts +704 -0
- package/dist/BehaviorTree-BrBFECv5.d.cts +103 -0
- package/dist/BehaviorTree-BrBFECv5.d.ts +103 -0
- package/dist/InvisibleWallet-BB6tFvRA.d.cts +1732 -0
- package/dist/InvisibleWallet-rtRrBOA8.d.ts +1732 -0
- package/dist/OrchestratorAgent-BvWgf9uw.d.cts +798 -0
- package/dist/OrchestratorAgent-Q_CbVTmO.d.ts +798 -0
- package/dist/agents/index.cjs +4790 -0
- package/dist/agents/index.d.cts +1788 -0
- package/dist/agents/index.d.ts +1788 -0
- package/dist/agents/index.js +4695 -0
- package/dist/ai/index.cjs +5347 -0
- package/dist/ai/index.d.cts +1753 -0
- package/dist/ai/index.d.ts +1753 -0
- package/dist/ai/index.js +5244 -0
- package/dist/behavior.cjs +449 -0
- package/dist/behavior.d.cts +130 -0
- package/dist/behavior.d.ts +130 -0
- package/dist/behavior.js +407 -0
- package/dist/economy/index.cjs +3659 -0
- package/dist/economy/index.d.cts +747 -0
- package/dist/economy/index.d.ts +747 -0
- package/dist/economy/index.js +3617 -0
- package/dist/implementations-D9T3un9D.d.cts +236 -0
- package/dist/implementations-D9T3un9D.d.ts +236 -0
- package/dist/index.cjs +24550 -0
- package/dist/index.d.cts +1729 -0
- package/dist/index.d.ts +1729 -0
- package/dist/index.js +24277 -0
- package/dist/learning/index.cjs +219 -0
- package/dist/learning/index.d.cts +104 -0
- package/dist/learning/index.d.ts +104 -0
- package/dist/learning/index.js +189 -0
- package/dist/negotiation/index.cjs +970 -0
- package/dist/negotiation/index.d.cts +610 -0
- package/dist/negotiation/index.d.ts +610 -0
- package/dist/negotiation/index.js +931 -0
- package/dist/skills/index.cjs +1118 -0
- package/dist/skills/index.d.cts +289 -0
- package/dist/skills/index.d.ts +289 -0
- package/dist/skills/index.js +1079 -0
- package/dist/swarm/index.cjs +5268 -0
- package/dist/swarm/index.d.cts +2433 -0
- package/dist/swarm/index.d.ts +2433 -0
- package/dist/swarm/index.js +5221 -0
- package/dist/training/index.cjs +2745 -0
- package/dist/training/index.d.cts +1734 -0
- package/dist/training/index.d.ts +1734 -0
- package/dist/training/index.js +2687 -0
- package/extract-failures.js +10 -0
- package/package.json +82 -0
- package/src/__tests__/bounty-marketplace.test.ts +374 -0
- package/src/__tests__/delegation.test.ts +144 -0
- package/src/__tests__/distributed-claimer.test.ts +147 -0
- package/src/__tests__/done-log-audit.test.ts +342 -0
- package/src/__tests__/framework.test.ts +865 -0
- package/src/__tests__/goal-synthesizer.test.ts +236 -0
- package/src/__tests__/presence.test.ts +223 -0
- package/src/__tests__/protocol-agent.test.ts +254 -0
- package/src/__tests__/revenue-splitter.test.ts +114 -0
- package/src/__tests__/scenario-driven-todo.test.ts +197 -0
- package/src/__tests__/self-improve.test.ts +349 -0
- package/src/__tests__/service-lifecycle.test.ts +237 -0
- package/src/__tests__/skill-router.test.ts +121 -0
- package/src/agents/AgentManifest.ts +493 -0
- package/src/agents/AgentRegistry.ts +475 -0
- package/src/agents/AgentTypes.ts +585 -0
- package/src/agents/AgentWalletRegistry.ts +83 -0
- package/src/agents/AuthenticatedCRDT.ts +388 -0
- package/src/agents/CapabilityMatcher.ts +453 -0
- package/src/agents/CrossRealityHandoff.ts +305 -0
- package/src/agents/CulturalMemory.ts +454 -0
- package/src/agents/FederatedRegistryAdapter.ts +429 -0
- package/src/agents/NormEngine.ts +450 -0
- package/src/agents/OrchestratorAgent.ts +414 -0
- package/src/agents/SkillWorkflowEngine.ts +472 -0
- package/src/agents/TaskDelegationService.ts +551 -0
- package/src/agents/__tests__/AgentManifest.prod.test.ts +134 -0
- package/src/agents/__tests__/AgentManifest.test.ts +182 -0
- package/src/agents/__tests__/AgentModule.test.ts +864 -0
- package/src/agents/__tests__/AgentRegistry.prod.test.ts +125 -0
- package/src/agents/__tests__/AgentRegistry.test.ts +148 -0
- package/src/agents/__tests__/AgentTypes.test.ts +534 -0
- package/src/agents/__tests__/AgentWalletRegistry.test.ts +152 -0
- package/src/agents/__tests__/AuthenticatedCRDT.test.ts +558 -0
- package/src/agents/__tests__/CapabilityMatcher.prod.test.ts +117 -0
- package/src/agents/__tests__/CapabilityMatcher.test.ts +178 -0
- package/src/agents/__tests__/CrossRealityHandoff.test.ts +402 -0
- package/src/agents/__tests__/CulturalMemory.test.ts +200 -0
- package/src/agents/__tests__/FederatedRegistryAdapter.test.ts +409 -0
- package/src/agents/__tests__/NormEngine.test.ts +276 -0
- package/src/agents/__tests__/OrchestratorAgent.test.ts +182 -0
- package/src/agents/__tests__/SkillWorkflowEngine.test.ts +357 -0
- package/src/agents/__tests__/TaskDelegationService.test.ts +446 -0
- package/src/agents/index.ts +107 -0
- package/src/agents/spatial-comms/Layer1RealTime.ts +621 -0
- package/src/agents/spatial-comms/Layer2A2A.ts +661 -0
- package/src/agents/spatial-comms/Layer3MCP.ts +651 -0
- package/src/agents/spatial-comms/ProtocolTypes.ts +543 -0
- package/src/agents/spatial-comms/SpatialCommClient.ts +483 -0
- package/src/agents/spatial-comms/__tests__/performance-benchmark.test.ts +465 -0
- package/src/agents/spatial-comms/examples/multi-agent-world-creation.ts +409 -0
- package/src/agents/spatial-comms/index.ts +66 -0
- package/src/ai/AIAdapter.ts +313 -0
- package/src/ai/AICopilot.ts +331 -0
- package/src/ai/AIOutputValidator.ts +203 -0
- package/src/ai/BTNodes.ts +239 -0
- package/src/ai/BehaviorSelector.ts +135 -0
- package/src/ai/BehaviorTree.ts +153 -0
- package/src/ai/Blackboard.ts +165 -0
- package/src/ai/GenerationAnalytics.ts +461 -0
- package/src/ai/GenerationCache.ts +265 -0
- package/src/ai/GoalPlanner.ts +165 -0
- package/src/ai/HoloScriptGenerator.ts +580 -0
- package/src/ai/InfluenceMap.ts +180 -0
- package/src/ai/NavMesh.ts +168 -0
- package/src/ai/PerceptionSystem.ts +178 -0
- package/src/ai/PromptTemplates.ts +453 -0
- package/src/ai/SemanticSearchService.ts +80 -0
- package/src/ai/StateMachine.ts +196 -0
- package/src/ai/SteeringBehavior.ts +150 -0
- package/src/ai/SteeringBehaviors.ts +244 -0
- package/src/ai/TrainingDataGenerator.ts +1082 -0
- package/src/ai/UtilityAI.ts +145 -0
- package/src/ai/__tests__/AIAdapter.prod.test.ts +259 -0
- package/src/ai/__tests__/AIAdapter.test.ts +109 -0
- package/src/ai/__tests__/AICopilot.prod.test.ts +341 -0
- package/src/ai/__tests__/AICopilot.test.ts +178 -0
- package/src/ai/__tests__/AIOutputValidator.prod.test.ts +226 -0
- package/src/ai/__tests__/AIOutputValidator.test.ts +138 -0
- package/src/ai/__tests__/BTNodes.prod.test.ts +391 -0
- package/src/ai/__tests__/BTNodes.test.ts +263 -0
- package/src/ai/__tests__/BehaviorSelector.prod.test.ts +129 -0
- package/src/ai/__tests__/BehaviorSelector.test.ts +132 -0
- package/src/ai/__tests__/BehaviorTree.prod.test.ts +266 -0
- package/src/ai/__tests__/BehaviorTree.test.ts +216 -0
- package/src/ai/__tests__/Blackboard.prod.test.ts +339 -0
- package/src/ai/__tests__/Blackboard.test.ts +183 -0
- package/src/ai/__tests__/GenerationAnalytics.prod.test.ts +141 -0
- package/src/ai/__tests__/GenerationAnalytics.test.ts +165 -0
- package/src/ai/__tests__/GenerationCache.prod.test.ts +144 -0
- package/src/ai/__tests__/GenerationCache.test.ts +171 -0
- package/src/ai/__tests__/GoalPlanner.prod.test.ts +189 -0
- package/src/ai/__tests__/GoalPlanner.test.ts +137 -0
- package/src/ai/__tests__/GoalPlannerDepth.prod.test.ts +217 -0
- package/src/ai/__tests__/HoloScriptGenerator.test.ts +125 -0
- package/src/ai/__tests__/InfluenceMap.prod.test.ts +146 -0
- package/src/ai/__tests__/InfluenceMap.test.ts +149 -0
- package/src/ai/__tests__/NavMesh.prod.test.ts +141 -0
- package/src/ai/__tests__/NavMesh.test.ts +159 -0
- package/src/ai/__tests__/PerceptionSystem.prod.test.ts +135 -0
- package/src/ai/__tests__/PerceptionSystem.test.ts +250 -0
- package/src/ai/__tests__/PromptTemplates.prod.test.ts +313 -0
- package/src/ai/__tests__/PromptTemplates.test.ts +146 -0
- package/src/ai/__tests__/SemanticSearch.test.ts +37 -0
- package/src/ai/__tests__/StateMachine.prod.test.ts +162 -0
- package/src/ai/__tests__/StateMachine.test.ts +163 -0
- package/src/ai/__tests__/SteeringBehavior.prod.test.ts +251 -0
- package/src/ai/__tests__/SteeringBehavior.test.ts +135 -0
- package/src/ai/__tests__/SteeringBehaviors.prod.test.ts +133 -0
- package/src/ai/__tests__/SteeringBehaviors.test.ts +151 -0
- package/src/ai/__tests__/TrainingDataGenerator.prod.test.ts +286 -0
- package/src/ai/__tests__/TrainingDataGenerator.test.ts +286 -0
- package/src/ai/__tests__/UtilityAI.prod.test.ts +207 -0
- package/src/ai/__tests__/UtilityAI.test.ts +155 -0
- package/src/ai/__tests__/adapters.prod.test.ts +263 -0
- package/src/ai/__tests__/adapters.test.ts +320 -0
- package/src/ai/adapters.ts +1585 -0
- package/src/ai/index.ts +130 -0
- package/src/behavior/BehaviorPresets.ts +140 -0
- package/src/behavior/BehaviorTree.ts +236 -0
- package/src/behavior/StateMachine.ts +176 -0
- package/src/behavior/StateTrait.ts +67 -0
- package/src/behavior/index.ts +8 -0
- package/src/behavior.ts +8 -0
- package/src/board/audit.ts +284 -0
- package/src/board/board-ops.ts +336 -0
- package/src/board/board-types.ts +302 -0
- package/src/board/index.ts +69 -0
- package/src/define-agent.ts +46 -0
- package/src/define-team.ts +33 -0
- package/src/delegation.ts +265 -0
- package/src/distributed-claimer.ts +228 -0
- package/src/economy/AgentBudgetEnforcer.ts +464 -0
- package/src/economy/BountyManager.ts +185 -0
- package/src/economy/CreatorRevenueAggregator.ts +460 -0
- package/src/economy/InvisibleWallet.ts +82 -0
- package/src/economy/KnowledgeMarketplace.ts +193 -0
- package/src/economy/PaymentWebhookService.ts +512 -0
- package/src/economy/RevenueSplitter.ts +156 -0
- package/src/economy/SubscriptionManager.ts +546 -0
- package/src/economy/UnifiedBudgetOptimizer.ts +635 -0
- package/src/economy/UsageMeter.ts +440 -0
- package/src/economy/_core-stubs.ts +219 -0
- package/src/economy/index.ts +100 -0
- package/src/economy/x402-facilitator.ts +1978 -0
- package/src/index.ts +348 -0
- package/src/knowledge/__tests__/knowledge-consolidator.test.ts +444 -0
- package/src/knowledge/__tests__/knowledge-store-vector.test.ts +291 -0
- package/src/knowledge/brain.ts +167 -0
- package/src/knowledge/consolidation.ts +581 -0
- package/src/knowledge/knowledge-consolidator.ts +510 -0
- package/src/knowledge/knowledge-store.ts +616 -0
- package/src/learning/MemoryConsolidator.ts +102 -0
- package/src/learning/MemoryScorer.ts +69 -0
- package/src/learning/ProceduralCompiler.ts +45 -0
- package/src/learning/SemanticClusterer.ts +66 -0
- package/src/learning/index.ts +8 -0
- package/src/llm/llm-adapter.ts +159 -0
- package/src/mesh/index.ts +309 -0
- package/src/negotiation/NegotiationProtocol.ts +694 -0
- package/src/negotiation/NegotiationTypes.ts +473 -0
- package/src/negotiation/VotingMechanisms.ts +691 -0
- package/src/negotiation/index.ts +49 -0
- package/src/protocol/goal-synthesizer.ts +317 -0
- package/src/protocol/implementations.ts +474 -0
- package/src/protocol/micro-phase-decomposer.ts +299 -0
- package/src/protocol/micro-step-decomposer.test.ts +306 -0
- package/src/protocol-agent.test.ts +353 -0
- package/src/protocol-agent.ts +670 -0
- package/src/self-improve/absorb-scanner.ts +252 -0
- package/src/self-improve/evolution-engine.ts +149 -0
- package/src/self-improve/framework-absorber.ts +214 -0
- package/src/self-improve/index.ts +50 -0
- package/src/self-improve/prompt-optimizer.ts +212 -0
- package/src/self-improve/test-generator.ts +175 -0
- package/src/skill-router.ts +186 -0
- package/src/skills/index.ts +5 -0
- package/src/skills/skill-md-bridge.ts +1699 -0
- package/src/swarm/ACOEngine.ts +261 -0
- package/src/swarm/CollectiveIntelligence.ts +383 -0
- package/src/swarm/ContributionSynthesizer.ts +481 -0
- package/src/swarm/LeaderElection.ts +393 -0
- package/src/swarm/PSOEngine.ts +206 -0
- package/src/swarm/QuorumPolicy.ts +173 -0
- package/src/swarm/SwarmCoordinator.ts +335 -0
- package/src/swarm/SwarmManager.ts +442 -0
- package/src/swarm/SwarmMembership.ts +456 -0
- package/src/swarm/VotingRound.ts +255 -0
- package/src/swarm/__tests__/ACOEngine.prod.test.ts +164 -0
- package/src/swarm/__tests__/ACOEngine.test.ts +117 -0
- package/src/swarm/__tests__/CollectiveIntelligence.prod.test.ts +296 -0
- package/src/swarm/__tests__/CollectiveIntelligence.test.ts +457 -0
- package/src/swarm/__tests__/ContributionSynthesizer.prod.test.ts +269 -0
- package/src/swarm/__tests__/ContributionSynthesizer.test.ts +254 -0
- package/src/swarm/__tests__/LeaderElection.prod.test.ts +196 -0
- package/src/swarm/__tests__/LeaderElection.test.ts +151 -0
- package/src/swarm/__tests__/PSOEngine.prod.test.ts +162 -0
- package/src/swarm/__tests__/PSOEngine.test.ts +106 -0
- package/src/swarm/__tests__/QuorumPolicy.prod.test.ts +216 -0
- package/src/swarm/__tests__/QuorumPolicy.test.ts +177 -0
- package/src/swarm/__tests__/SwarmCoordinator.prod.test.ts +186 -0
- package/src/swarm/__tests__/SwarmCoordinator.test.ts +167 -0
- package/src/swarm/__tests__/SwarmManager.prod.test.ts +308 -0
- package/src/swarm/__tests__/SwarmManager.test.ts +373 -0
- package/src/swarm/__tests__/SwarmMembership.prod.test.ts +273 -0
- package/src/swarm/__tests__/SwarmMembership.test.ts +264 -0
- package/src/swarm/__tests__/VotingRound.prod.test.ts +233 -0
- package/src/swarm/__tests__/VotingRound.test.ts +174 -0
- package/src/swarm/analytics/SwarmInspector.ts +476 -0
- package/src/swarm/analytics/SwarmMetrics.ts +449 -0
- package/src/swarm/analytics/__tests__/SwarmInspector.prod.test.ts +366 -0
- package/src/swarm/analytics/__tests__/SwarmInspector.test.ts +454 -0
- package/src/swarm/analytics/__tests__/SwarmMetrics.prod.test.ts +254 -0
- package/src/swarm/analytics/__tests__/SwarmMetrics.test.ts +370 -0
- package/src/swarm/analytics/index.ts +7 -0
- package/src/swarm/index.ts +69 -0
- package/src/swarm/messaging/BroadcastChannel.ts +509 -0
- package/src/swarm/messaging/GossipProtocol.ts +565 -0
- package/src/swarm/messaging/SwarmEventBus.ts +443 -0
- package/src/swarm/messaging/__tests__/BroadcastChannel.prod.test.ts +331 -0
- package/src/swarm/messaging/__tests__/BroadcastChannel.test.ts +333 -0
- package/src/swarm/messaging/__tests__/GossipProtocol.prod.test.ts +356 -0
- package/src/swarm/messaging/__tests__/GossipProtocol.test.ts +437 -0
- package/src/swarm/messaging/__tests__/SwarmEventBus.prod.test.ts +191 -0
- package/src/swarm/messaging/__tests__/SwarmEventBus.test.ts +247 -0
- package/src/swarm/messaging/index.ts +8 -0
- package/src/swarm/spatial/FlockingBehavior.ts +462 -0
- package/src/swarm/spatial/FormationController.ts +500 -0
- package/src/swarm/spatial/Vector3.ts +170 -0
- package/src/swarm/spatial/ZoneClaiming.ts +509 -0
- package/src/swarm/spatial/__tests__/FlockingBehavior.prod.test.ts +239 -0
- package/src/swarm/spatial/__tests__/FlockingBehavior.test.ts +298 -0
- package/src/swarm/spatial/__tests__/FormationController.prod.test.ts +240 -0
- package/src/swarm/spatial/__tests__/FormationController.test.ts +297 -0
- package/src/swarm/spatial/__tests__/Vector3.prod.test.ts +283 -0
- package/src/swarm/spatial/__tests__/Vector3.test.ts +224 -0
- package/src/swarm/spatial/__tests__/ZoneClaiming.prod.test.ts +246 -0
- package/src/swarm/spatial/__tests__/ZoneClaiming.test.ts +374 -0
- package/src/swarm/spatial/index.ts +28 -0
- package/src/team.ts +1245 -0
- package/src/training/LRScheduler.ts +377 -0
- package/src/training/QualityScoringPipeline.ts +139 -0
- package/src/training/SoftDedup.ts +461 -0
- package/src/training/SparsityMonitor.ts +685 -0
- package/src/training/SparsityMonitorTypes.ts +209 -0
- package/src/training/SpatialTrainingDataGenerator.ts +1526 -0
- package/src/training/SpatialTrainingDataTypes.ts +216 -0
- package/src/training/TrainingPipelineConfig.ts +215 -0
- package/src/training/constants.ts +94 -0
- package/src/training/index.ts +138 -0
- package/src/training/schema.ts +147 -0
- package/src/training/scripts/generate-novel-use-cases-dataset.ts +272 -0
- package/src/training/scripts/generate-spatial-dataset.ts +521 -0
- package/src/training/training/data/novel-use-cases.jsonl +153 -0
- package/src/training/training/data/spatial-reasoning-10k.jsonl +9354 -0
- package/src/training/trainingmonkey/TrainingMonkeyIntegration.ts +477 -0
- package/src/training/trainingmonkey/TrainingMonkeyTypes.ts +230 -0
- package/src/training/trainingmonkey/index.ts +26 -0
- package/src/training/trait-mappings.ts +157 -0
- package/src/types/core-stubs.d.ts +113 -0
- package/src/types.ts +304 -0
- package/test-output.txt +0 -0
- package/test-result.json +1 -0
- package/tsc-errors.txt +4 -0
- package/tsc_output.txt +0 -0
- package/tsconfig.json +14 -0
- package/tsup-learning-esm.config.ts +12 -0
- package/tsup.config.ts +21 -0
- package/typescript-errors-2.txt +0 -0
- package/typescript-errors.txt +22 -0
- package/vitest-log-utf8.txt +268 -0
- package/vitest-log.txt +0 -0
- package/vitest.config.ts +8 -0
|
@@ -0,0 +1,661 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @holoscript/core - Layer 2: A2A Coordination Layer
|
|
3
|
+
*
|
|
4
|
+
* JSON-RPC over HTTP/2 for agent-to-agent collaboration.
|
|
5
|
+
* Features:
|
|
6
|
+
* - Task assignment and completion tracking
|
|
7
|
+
* - Spatial region claims and conflict resolution
|
|
8
|
+
* - Resource request/release management
|
|
9
|
+
* - Request/response with acknowledgments
|
|
10
|
+
* - Retry with exponential backoff
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { EventEmitter } from 'events';
|
|
14
|
+
import { DEFAULT_A2A_CONFIG } from './ProtocolTypes';
|
|
15
|
+
import type {
|
|
16
|
+
A2AMessage,
|
|
17
|
+
A2AMessageBody,
|
|
18
|
+
A2AResponse,
|
|
19
|
+
A2AProtocolConfig,
|
|
20
|
+
TaskSpec,
|
|
21
|
+
ConflictResolutionStrategy,
|
|
22
|
+
} from './ProtocolTypes';
|
|
23
|
+
|
|
24
|
+
// ============================================================================
|
|
25
|
+
// A2A MESSAGE QUEUE
|
|
26
|
+
// ============================================================================
|
|
27
|
+
|
|
28
|
+
interface QueuedMessage {
|
|
29
|
+
message: A2AMessage;
|
|
30
|
+
attempt: number;
|
|
31
|
+
maxRetries: number;
|
|
32
|
+
backoffBase: number;
|
|
33
|
+
resolve: (response: A2AResponse) => void;
|
|
34
|
+
reject: (error: Error) => void;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Message queue for retry management
|
|
39
|
+
*/
|
|
40
|
+
class MessageQueue {
|
|
41
|
+
private queue: Map<string, QueuedMessage> = new Map();
|
|
42
|
+
private retryTimers: Map<string, ReturnType<typeof setTimeout>> = new Map();
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Add message to queue
|
|
46
|
+
*/
|
|
47
|
+
add(message: A2AMessage, maxRetries: number, backoffBase: number): Promise<A2AResponse> {
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
this.queue.set(message.message_id, {
|
|
50
|
+
message,
|
|
51
|
+
attempt: 0,
|
|
52
|
+
maxRetries,
|
|
53
|
+
backoffBase,
|
|
54
|
+
resolve,
|
|
55
|
+
reject,
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Get message from queue
|
|
62
|
+
*/
|
|
63
|
+
get(messageId: string): QueuedMessage | undefined {
|
|
64
|
+
return this.queue.get(messageId);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Remove message from queue
|
|
69
|
+
*/
|
|
70
|
+
remove(messageId: string): void {
|
|
71
|
+
const timer = this.retryTimers.get(messageId);
|
|
72
|
+
if (timer) {
|
|
73
|
+
clearTimeout(timer);
|
|
74
|
+
this.retryTimers.delete(messageId);
|
|
75
|
+
}
|
|
76
|
+
this.queue.delete(messageId);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Schedule retry for message
|
|
81
|
+
*/
|
|
82
|
+
scheduleRetry(messageId: string, callback: () => void): void {
|
|
83
|
+
const queued = this.queue.get(messageId);
|
|
84
|
+
if (!queued) return;
|
|
85
|
+
|
|
86
|
+
queued.attempt++;
|
|
87
|
+
|
|
88
|
+
// Exponential backoff: base * 2^attempt
|
|
89
|
+
const delay = queued.backoffBase * Math.pow(2, queued.attempt - 1);
|
|
90
|
+
|
|
91
|
+
const timer = setTimeout(() => {
|
|
92
|
+
this.retryTimers.delete(messageId);
|
|
93
|
+
callback();
|
|
94
|
+
}, delay);
|
|
95
|
+
|
|
96
|
+
this.retryTimers.set(messageId, timer);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Check if message should retry
|
|
101
|
+
*/
|
|
102
|
+
shouldRetry(messageId: string): boolean {
|
|
103
|
+
const queued = this.queue.get(messageId);
|
|
104
|
+
if (!queued) return false;
|
|
105
|
+
return queued.attempt < queued.maxRetries;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Get queue size
|
|
110
|
+
*/
|
|
111
|
+
get size(): number {
|
|
112
|
+
return this.queue.size;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Clear all queued messages
|
|
117
|
+
*/
|
|
118
|
+
clear(): void {
|
|
119
|
+
for (const timer of this.retryTimers.values()) {
|
|
120
|
+
clearTimeout(timer);
|
|
121
|
+
}
|
|
122
|
+
this.retryTimers.clear();
|
|
123
|
+
this.queue.clear();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ============================================================================
|
|
128
|
+
// SPATIAL CLAIM MANAGER
|
|
129
|
+
// ============================================================================
|
|
130
|
+
|
|
131
|
+
export interface SpatialClaim {
|
|
132
|
+
claim_id: string;
|
|
133
|
+
agent_id: string;
|
|
134
|
+
bounding_box: {
|
|
135
|
+
min: [number, number, number];
|
|
136
|
+
max: [number, number, number];
|
|
137
|
+
};
|
|
138
|
+
priority: 'low' | 'medium' | 'high' | 'critical';
|
|
139
|
+
exclusive: boolean;
|
|
140
|
+
expires_at?: number;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Spatial claim manager for conflict detection
|
|
145
|
+
*/
|
|
146
|
+
class SpatialClaimManager {
|
|
147
|
+
private claims: Map<string, SpatialClaim> = new Map();
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Add spatial claim
|
|
151
|
+
*/
|
|
152
|
+
addClaim(claim: SpatialClaim): void {
|
|
153
|
+
this.claims.set(claim.claim_id, claim);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Remove spatial claim
|
|
158
|
+
*/
|
|
159
|
+
removeClaim(claimId: string): void {
|
|
160
|
+
this.claims.delete(claimId);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Get claims by agent
|
|
165
|
+
*/
|
|
166
|
+
getClaimsByAgent(agentId: string): SpatialClaim[] {
|
|
167
|
+
return Array.from(this.claims.values()).filter((c) => c.agent_id === agentId);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Check for conflicts with new claim
|
|
172
|
+
*/
|
|
173
|
+
checkConflicts(newClaim: SpatialClaim): SpatialClaim[] {
|
|
174
|
+
const conflicts: SpatialClaim[] = [];
|
|
175
|
+
|
|
176
|
+
for (const existingClaim of this.claims.values()) {
|
|
177
|
+
// Skip if same agent
|
|
178
|
+
if (existingClaim.agent_id === newClaim.agent_id) continue;
|
|
179
|
+
|
|
180
|
+
// Check if bounding boxes overlap
|
|
181
|
+
if (this.boundingBoxesOverlap(newClaim.bounding_box, existingClaim.bounding_box)) {
|
|
182
|
+
// Check if either claim is exclusive
|
|
183
|
+
if (newClaim.exclusive || existingClaim.exclusive) {
|
|
184
|
+
conflicts.push(existingClaim);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return conflicts;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Check if two bounding boxes overlap
|
|
194
|
+
*/
|
|
195
|
+
private boundingBoxesOverlap(
|
|
196
|
+
box1: { min: [number, number, number]; max: [number, number, number] },
|
|
197
|
+
box2: { min: [number, number, number]; max: [number, number, number] }
|
|
198
|
+
): boolean {
|
|
199
|
+
return (
|
|
200
|
+
box1.min[0] <= box2.max[0] &&
|
|
201
|
+
box1.max[0] >= box2.min[0] &&
|
|
202
|
+
box1.min[1] <= box2.max[1] &&
|
|
203
|
+
box1.max[1] >= box2.min[1] &&
|
|
204
|
+
box1.min[2] <= box2.max[2] &&
|
|
205
|
+
box1.max[2] >= box2.min[2]
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Cleanup expired claims
|
|
211
|
+
*/
|
|
212
|
+
cleanup(): void {
|
|
213
|
+
const now = Date.now();
|
|
214
|
+
for (const [claimId, claim] of this.claims) {
|
|
215
|
+
if (claim.expires_at && claim.expires_at < now) {
|
|
216
|
+
this.claims.delete(claimId);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Get all claims
|
|
223
|
+
*/
|
|
224
|
+
getAllClaims(): SpatialClaim[] {
|
|
225
|
+
return Array.from(this.claims.values());
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Clear all claims
|
|
230
|
+
*/
|
|
231
|
+
clear(): void {
|
|
232
|
+
this.claims.clear();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// ============================================================================
|
|
237
|
+
// LAYER 2 CLIENT
|
|
238
|
+
// ============================================================================
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Layer 2 A2A Coordination Client
|
|
242
|
+
*/
|
|
243
|
+
export class Layer2A2AClient extends EventEmitter {
|
|
244
|
+
private config: A2AProtocolConfig;
|
|
245
|
+
private agentId: string;
|
|
246
|
+
private messageQueue: MessageQueue = new MessageQueue();
|
|
247
|
+
private claimManager: SpatialClaimManager = new SpatialClaimManager();
|
|
248
|
+
private messageHandlers: Map<string, (message: A2AMessage) => Promise<A2AResponse>> = new Map();
|
|
249
|
+
private batchBuffer: A2AMessage[] = [];
|
|
250
|
+
private batchTimer?: ReturnType<typeof setTimeout>;
|
|
251
|
+
|
|
252
|
+
constructor(agentId: string, config?: Partial<A2AProtocolConfig>) {
|
|
253
|
+
super();
|
|
254
|
+
this.agentId = agentId;
|
|
255
|
+
this.config = { ...DEFAULT_A2A_CONFIG, ...config } as A2AProtocolConfig;
|
|
256
|
+
|
|
257
|
+
// Start periodic cleanup
|
|
258
|
+
setInterval(() => {
|
|
259
|
+
this.claimManager.cleanup();
|
|
260
|
+
}, 60000); // Every minute
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Send A2A message with retry
|
|
265
|
+
*/
|
|
266
|
+
async send(
|
|
267
|
+
message: A2AMessageBody
|
|
268
|
+
): Promise<A2AResponse> {
|
|
269
|
+
// Generate message ID and add metadata
|
|
270
|
+
const fullMessage: A2AMessage = {
|
|
271
|
+
...message,
|
|
272
|
+
message_id: this.generateMessageId(),
|
|
273
|
+
from_agent: this.agentId,
|
|
274
|
+
timestamp: Date.now(),
|
|
275
|
+
} as A2AMessage;
|
|
276
|
+
|
|
277
|
+
// Add to batch if batching enabled
|
|
278
|
+
if (this.config.enableBatching) {
|
|
279
|
+
return this.addToBatch(fullMessage);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Send immediately
|
|
283
|
+
return this.sendMessage(fullMessage);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Send task assignment
|
|
288
|
+
*/
|
|
289
|
+
async assignTask(toAgent: string, task: TaskSpec): Promise<A2AResponse> {
|
|
290
|
+
return this.send({
|
|
291
|
+
type: 'task_assignment',
|
|
292
|
+
to_agent: toAgent,
|
|
293
|
+
task,
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Send task completion
|
|
299
|
+
*/
|
|
300
|
+
async completeTask(
|
|
301
|
+
taskId: string,
|
|
302
|
+
success: boolean,
|
|
303
|
+
result?: unknown,
|
|
304
|
+
error?: string,
|
|
305
|
+
performanceMetrics?: {
|
|
306
|
+
duration_ms: number;
|
|
307
|
+
frame_time_avg_ms: number;
|
|
308
|
+
frame_time_max_ms: number;
|
|
309
|
+
quality_level: 'high' | 'medium' | 'low' | 'minimal';
|
|
310
|
+
}
|
|
311
|
+
): Promise<A2AResponse> {
|
|
312
|
+
return this.send({
|
|
313
|
+
type: 'task_complete',
|
|
314
|
+
task_id: taskId,
|
|
315
|
+
success,
|
|
316
|
+
result,
|
|
317
|
+
error,
|
|
318
|
+
performance_metrics: performanceMetrics,
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Claim spatial region
|
|
324
|
+
*/
|
|
325
|
+
async claimSpatialRegion(
|
|
326
|
+
claimId: string,
|
|
327
|
+
boundingBox: {
|
|
328
|
+
min: [number, number, number];
|
|
329
|
+
max: [number, number, number];
|
|
330
|
+
},
|
|
331
|
+
priority: 'low' | 'medium' | 'high' | 'critical',
|
|
332
|
+
durationMs?: number,
|
|
333
|
+
exclusive = true
|
|
334
|
+
): Promise<A2AResponse> {
|
|
335
|
+
// Create claim
|
|
336
|
+
const claim: SpatialClaim = {
|
|
337
|
+
claim_id: claimId,
|
|
338
|
+
agent_id: this.agentId,
|
|
339
|
+
bounding_box: boundingBox,
|
|
340
|
+
priority,
|
|
341
|
+
exclusive,
|
|
342
|
+
expires_at: durationMs ? Date.now() + durationMs : undefined,
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
// Check for conflicts
|
|
346
|
+
const conflicts = this.claimManager.checkConflicts(claim);
|
|
347
|
+
|
|
348
|
+
if (conflicts.length > 0) {
|
|
349
|
+
// Emit conflict event
|
|
350
|
+
this.emit('spatial_conflict', {
|
|
351
|
+
claim,
|
|
352
|
+
conflicts,
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
// If any conflict has higher or equal priority, fail
|
|
356
|
+
const hasHigherPriority = conflicts.some((c) => {
|
|
357
|
+
const priorities = ['low', 'medium', 'high', 'critical'];
|
|
358
|
+
return priorities.indexOf(c.priority) >= priorities.indexOf(priority);
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
if (hasHigherPriority) {
|
|
362
|
+
return {
|
|
363
|
+
message_id: this.generateMessageId(),
|
|
364
|
+
success: false,
|
|
365
|
+
error: 'Spatial conflict with higher priority claim',
|
|
366
|
+
data: { conflicts },
|
|
367
|
+
timestamp: Date.now(),
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Add claim
|
|
373
|
+
this.claimManager.addClaim(claim);
|
|
374
|
+
|
|
375
|
+
// Send claim message
|
|
376
|
+
return this.send({
|
|
377
|
+
type: 'spatial_claim',
|
|
378
|
+
claim_id: claimId,
|
|
379
|
+
bounding_box: boundingBox,
|
|
380
|
+
priority,
|
|
381
|
+
duration_ms: durationMs,
|
|
382
|
+
exclusive,
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Resolve spatial conflict
|
|
388
|
+
*/
|
|
389
|
+
async resolveConflict(
|
|
390
|
+
conflictId: string,
|
|
391
|
+
involvedAgents: string[],
|
|
392
|
+
strategy: ConflictResolutionStrategy,
|
|
393
|
+
resolutionParams?: Record<string, unknown>
|
|
394
|
+
): Promise<A2AResponse> {
|
|
395
|
+
return this.send({
|
|
396
|
+
type: 'conflict_resolution',
|
|
397
|
+
conflict_id: conflictId,
|
|
398
|
+
strategy,
|
|
399
|
+
involved_agents: involvedAgents,
|
|
400
|
+
resolution_params: resolutionParams,
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Request resource
|
|
406
|
+
*/
|
|
407
|
+
async requestResource(
|
|
408
|
+
resourceId: string,
|
|
409
|
+
resourceType: 'mesh' | 'texture' | 'material' | 'audio' | 'compute' | 'memory',
|
|
410
|
+
amount?: number,
|
|
411
|
+
priority: 'low' | 'medium' | 'high' | 'critical' = 'medium'
|
|
412
|
+
): Promise<A2AResponse> {
|
|
413
|
+
return this.send({
|
|
414
|
+
type: 'resource_request',
|
|
415
|
+
resource_id: resourceId,
|
|
416
|
+
resource_type: resourceType,
|
|
417
|
+
amount,
|
|
418
|
+
priority,
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Release resource
|
|
424
|
+
*/
|
|
425
|
+
async releaseResource(resourceId: string): Promise<A2AResponse> {
|
|
426
|
+
return this.send({
|
|
427
|
+
type: 'resource_release',
|
|
428
|
+
resource_id: resourceId,
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Perform agent handshake
|
|
434
|
+
*/
|
|
435
|
+
async handshake(
|
|
436
|
+
toAgent: string,
|
|
437
|
+
capabilities: string[],
|
|
438
|
+
protocolVersion: string
|
|
439
|
+
): Promise<A2AResponse> {
|
|
440
|
+
return this.send({
|
|
441
|
+
type: 'agent_handshake',
|
|
442
|
+
to_agent: toAgent,
|
|
443
|
+
capabilities,
|
|
444
|
+
protocol_version: protocolVersion,
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Register message handler
|
|
450
|
+
*/
|
|
451
|
+
onMessage(messageType: string, handler: (message: A2AMessage) => Promise<A2AResponse>): void {
|
|
452
|
+
this.messageHandlers.set(messageType, handler);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Handle incoming message
|
|
457
|
+
*/
|
|
458
|
+
async handleIncoming(message: A2AMessage): Promise<A2AResponse> {
|
|
459
|
+
// Emit event
|
|
460
|
+
this.emit('message', message);
|
|
461
|
+
this.emit(message.type, message);
|
|
462
|
+
|
|
463
|
+
// Check if handler registered
|
|
464
|
+
const handler = this.messageHandlers.get(message.type);
|
|
465
|
+
if (handler) {
|
|
466
|
+
return handler(message);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// Default response
|
|
470
|
+
return {
|
|
471
|
+
message_id: message.message_id,
|
|
472
|
+
success: true,
|
|
473
|
+
timestamp: Date.now(),
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* Get spatial claims for this agent
|
|
479
|
+
*/
|
|
480
|
+
getMyClaims(): SpatialClaim[] {
|
|
481
|
+
return this.claimManager.getClaimsByAgent(this.agentId);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* Get all spatial claims
|
|
486
|
+
*/
|
|
487
|
+
getAllClaims(): SpatialClaim[] {
|
|
488
|
+
return this.claimManager.getAllClaims();
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Send message with retry logic
|
|
493
|
+
*/
|
|
494
|
+
private async sendMessage(message: A2AMessage): Promise<A2AResponse> {
|
|
495
|
+
// Add to queue
|
|
496
|
+
const responsePromise = this.messageQueue.add(
|
|
497
|
+
message,
|
|
498
|
+
this.config.maxRetries,
|
|
499
|
+
this.config.retryBackoffBase
|
|
500
|
+
);
|
|
501
|
+
|
|
502
|
+
// Attempt to send
|
|
503
|
+
this.attemptSend(message);
|
|
504
|
+
|
|
505
|
+
return responsePromise;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* Attempt to send message
|
|
510
|
+
*/
|
|
511
|
+
private async attemptSend(message: A2AMessage): Promise<void> {
|
|
512
|
+
try {
|
|
513
|
+
// Send HTTP/2 request
|
|
514
|
+
const response = await this.httpRequest(message);
|
|
515
|
+
|
|
516
|
+
// Get queued message
|
|
517
|
+
const queued = this.messageQueue.get(message.message_id);
|
|
518
|
+
if (!queued) return;
|
|
519
|
+
|
|
520
|
+
// Resolve promise
|
|
521
|
+
queued.resolve(response);
|
|
522
|
+
this.messageQueue.remove(message.message_id);
|
|
523
|
+
|
|
524
|
+
// Emit success
|
|
525
|
+
this.emit('message_sent', { message, response });
|
|
526
|
+
} catch (error) {
|
|
527
|
+
// Get queued message
|
|
528
|
+
const queued = this.messageQueue.get(message.message_id);
|
|
529
|
+
if (!queued) return;
|
|
530
|
+
|
|
531
|
+
// Check if should retry
|
|
532
|
+
if (this.messageQueue.shouldRetry(message.message_id)) {
|
|
533
|
+
this.emit('retry', { message, attempt: queued.attempt });
|
|
534
|
+
this.messageQueue.scheduleRetry(message.message_id, () => {
|
|
535
|
+
this.attemptSend(message);
|
|
536
|
+
});
|
|
537
|
+
} else {
|
|
538
|
+
// Max retries exceeded
|
|
539
|
+
queued.reject(error as Error);
|
|
540
|
+
this.messageQueue.remove(message.message_id);
|
|
541
|
+
this.emit('message_failed', { message, error });
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* HTTP/2 request
|
|
548
|
+
*/
|
|
549
|
+
private async httpRequest(message: A2AMessage): Promise<A2AResponse> {
|
|
550
|
+
// In a real implementation, this would use HTTP/2
|
|
551
|
+
// For now, using fetch with timeout
|
|
552
|
+
|
|
553
|
+
const controller = new AbortController();
|
|
554
|
+
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
555
|
+
|
|
556
|
+
try {
|
|
557
|
+
const response = await fetch(this.config.endpoint, {
|
|
558
|
+
method: 'POST',
|
|
559
|
+
headers: {
|
|
560
|
+
'Content-Type': 'application/json',
|
|
561
|
+
},
|
|
562
|
+
body: JSON.stringify(message),
|
|
563
|
+
signal: controller.signal,
|
|
564
|
+
});
|
|
565
|
+
|
|
566
|
+
if (!response.ok) {
|
|
567
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
const data = await response.json();
|
|
571
|
+
return data as A2AResponse;
|
|
572
|
+
} finally {
|
|
573
|
+
clearTimeout(timeoutId);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* Add message to batch
|
|
579
|
+
*/
|
|
580
|
+
private addToBatch(message: A2AMessage): Promise<A2AResponse> {
|
|
581
|
+
this.batchBuffer.push(message);
|
|
582
|
+
|
|
583
|
+
// Create promise for response
|
|
584
|
+
const responsePromise = new Promise<A2AResponse>((resolve, reject) => {
|
|
585
|
+
// Store resolve/reject in message queue
|
|
586
|
+
this.messageQueue
|
|
587
|
+
.add(message, this.config.maxRetries, this.config.retryBackoffBase)
|
|
588
|
+
.then(resolve)
|
|
589
|
+
.catch(reject);
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
// Schedule batch send if not already scheduled
|
|
593
|
+
if (!this.batchTimer) {
|
|
594
|
+
this.batchTimer = setTimeout(() => {
|
|
595
|
+
this.flushBatch();
|
|
596
|
+
}, 10); // 10ms batch window
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
// Check if batch is full
|
|
600
|
+
if (this.batchBuffer.length >= this.config.batchSize) {
|
|
601
|
+
this.flushBatch();
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
return responsePromise;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* Flush batch of messages
|
|
609
|
+
*/
|
|
610
|
+
private flushBatch(): void {
|
|
611
|
+
if (this.batchTimer) {
|
|
612
|
+
clearTimeout(this.batchTimer);
|
|
613
|
+
this.batchTimer = undefined;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
if (this.batchBuffer.length === 0) return;
|
|
617
|
+
|
|
618
|
+
const batch = this.batchBuffer.splice(0);
|
|
619
|
+
|
|
620
|
+
// Send batch
|
|
621
|
+
for (const message of batch) {
|
|
622
|
+
this.attemptSend(message);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* Generate unique message ID
|
|
628
|
+
*/
|
|
629
|
+
private generateMessageId(): string {
|
|
630
|
+
return `${this.agentId}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* Get queue statistics
|
|
635
|
+
*/
|
|
636
|
+
getQueueStats(): {
|
|
637
|
+
queueSize: number;
|
|
638
|
+
claimCount: number;
|
|
639
|
+
} {
|
|
640
|
+
return {
|
|
641
|
+
queueSize: this.messageQueue.size,
|
|
642
|
+
claimCount: this.getAllClaims().length,
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
/**
|
|
647
|
+
* Shutdown client
|
|
648
|
+
*/
|
|
649
|
+
async shutdown(): Promise<void> {
|
|
650
|
+
// Flush any pending batches
|
|
651
|
+
this.flushBatch();
|
|
652
|
+
|
|
653
|
+
// Clear claims
|
|
654
|
+
this.claimManager.clear();
|
|
655
|
+
|
|
656
|
+
// Clear queue
|
|
657
|
+
this.messageQueue.clear();
|
|
658
|
+
|
|
659
|
+
this.emit('shutdown');
|
|
660
|
+
}
|
|
661
|
+
}
|