@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
package/src/ai/index.ts
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @holoscript/framework AI Module
|
|
3
|
+
*
|
|
4
|
+
* Provider-agnostic AI integration, game AI systems (behavior trees, state machines,
|
|
5
|
+
* steering, perception, utility AI), and generation pipeline.
|
|
6
|
+
*
|
|
7
|
+
* Canonical home for all AI subsystems (moved from @holoscript/core in A.011.02c).
|
|
8
|
+
*
|
|
9
|
+
* @packageDocumentation
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
// Core adapter interface and registry
|
|
13
|
+
export {
|
|
14
|
+
// Types
|
|
15
|
+
type AIAdapter,
|
|
16
|
+
type GenerateResult,
|
|
17
|
+
type ExplainResult,
|
|
18
|
+
type OptimizeResult,
|
|
19
|
+
type FixResult,
|
|
20
|
+
type GenerateOptions,
|
|
21
|
+
|
|
22
|
+
// Registry functions
|
|
23
|
+
registerAIAdapter,
|
|
24
|
+
getAIAdapter,
|
|
25
|
+
getDefaultAIAdapter,
|
|
26
|
+
setDefaultAIAdapter,
|
|
27
|
+
listAIAdapters,
|
|
28
|
+
unregisterAIAdapter,
|
|
29
|
+
|
|
30
|
+
// Convenience functions (use default adapter)
|
|
31
|
+
generateHoloScript,
|
|
32
|
+
explainHoloScript,
|
|
33
|
+
optimizeHoloScript,
|
|
34
|
+
fixHoloScript,
|
|
35
|
+
} from './AIAdapter';
|
|
36
|
+
|
|
37
|
+
// Built-in adapters
|
|
38
|
+
export {
|
|
39
|
+
// Adapter classes
|
|
40
|
+
OpenAIAdapter,
|
|
41
|
+
AnthropicAdapter,
|
|
42
|
+
OllamaAdapter,
|
|
43
|
+
LMStudioAdapter,
|
|
44
|
+
GeminiAdapter,
|
|
45
|
+
XAIAdapter,
|
|
46
|
+
TogetherAdapter,
|
|
47
|
+
FireworksAdapter,
|
|
48
|
+
NVIDIAAdapter,
|
|
49
|
+
|
|
50
|
+
// Config types
|
|
51
|
+
type OpenAIAdapterConfig,
|
|
52
|
+
type AnthropicAdapterConfig,
|
|
53
|
+
type OllamaAdapterConfig,
|
|
54
|
+
type LMStudioAdapterConfig,
|
|
55
|
+
type GeminiAdapterConfig,
|
|
56
|
+
type XAIAdapterConfig,
|
|
57
|
+
type TogetherAdapterConfig,
|
|
58
|
+
type FireworksAdapterConfig,
|
|
59
|
+
type NVIDIAAdapterConfig,
|
|
60
|
+
|
|
61
|
+
// Factory functions (create + register in one call)
|
|
62
|
+
useOpenAI,
|
|
63
|
+
useAnthropic,
|
|
64
|
+
useOllama,
|
|
65
|
+
useLMStudio,
|
|
66
|
+
useGemini,
|
|
67
|
+
useXAI,
|
|
68
|
+
useGrok,
|
|
69
|
+
useTogether,
|
|
70
|
+
useFireworks,
|
|
71
|
+
useNVIDIA,
|
|
72
|
+
} from './adapters';
|
|
73
|
+
|
|
74
|
+
export { SemanticSearchService, type SearchResult } from './SemanticSearchService';
|
|
75
|
+
|
|
76
|
+
// AI game systems (behavior trees, state machines, blackboards, steering, etc.)
|
|
77
|
+
export { BehaviorTree } from './BehaviorTree';
|
|
78
|
+
export type { BTContext as BTTreeContext, BTTreeDef } from './BehaviorTree';
|
|
79
|
+
|
|
80
|
+
export {
|
|
81
|
+
BTNode,
|
|
82
|
+
SequenceNode,
|
|
83
|
+
SelectorNode,
|
|
84
|
+
ParallelNode,
|
|
85
|
+
InverterNode,
|
|
86
|
+
RepeaterNode,
|
|
87
|
+
GuardNode,
|
|
88
|
+
ActionNode,
|
|
89
|
+
ConditionNode,
|
|
90
|
+
WaitNode,
|
|
91
|
+
} from './BTNodes';
|
|
92
|
+
export type { BTStatus } from './BTNodes';
|
|
93
|
+
|
|
94
|
+
export { Blackboard } from './Blackboard';
|
|
95
|
+
|
|
96
|
+
export { StateMachine } from './StateMachine';
|
|
97
|
+
export type { StateConfig, TransitionConfig, StateAction, GuardFn } from './StateMachine';
|
|
98
|
+
|
|
99
|
+
// Steering & navigation
|
|
100
|
+
export { SteeringBehavior } from './SteeringBehavior';
|
|
101
|
+
export { SteeringBehaviors } from './SteeringBehaviors';
|
|
102
|
+
export { NavMesh } from './NavMesh';
|
|
103
|
+
|
|
104
|
+
// Perception & influence
|
|
105
|
+
export { PerceptionSystem } from './PerceptionSystem';
|
|
106
|
+
export { InfluenceMap } from './InfluenceMap';
|
|
107
|
+
|
|
108
|
+
// Utility AI & behavior selection
|
|
109
|
+
export { UtilityAI } from './UtilityAI';
|
|
110
|
+
export { BehaviorSelector } from './BehaviorSelector';
|
|
111
|
+
|
|
112
|
+
// Goal planning
|
|
113
|
+
export { GoalPlanner } from './GoalPlanner';
|
|
114
|
+
|
|
115
|
+
// Generation pipeline
|
|
116
|
+
export {
|
|
117
|
+
HoloScriptGenerator,
|
|
118
|
+
generateHoloScript as generateHoloScriptWithAdapter,
|
|
119
|
+
generateBatch,
|
|
120
|
+
validateBatch,
|
|
121
|
+
} from './HoloScriptGenerator';
|
|
122
|
+
export { GenerationCache, cachedGenerate } from './GenerationCache';
|
|
123
|
+
export { GenerationAnalytics, createAnalytics } from './GenerationAnalytics';
|
|
124
|
+
export { TrainingDataGenerator, createTrainingDataGenerator, ALL_CATEGORIES } from './TrainingDataGenerator';
|
|
125
|
+
export { PromptTemplateSystem, QuickPrompts } from './PromptTemplates';
|
|
126
|
+
export type { PromptTemplate, TemplateContext } from './PromptTemplates';
|
|
127
|
+
|
|
128
|
+
// AI copilot & validation
|
|
129
|
+
export { AICopilot } from './AICopilot';
|
|
130
|
+
export { validateAIOutput, isAISafe } from './AIOutputValidator';
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BehaviorPresets.ts
|
|
3
|
+
*
|
|
4
|
+
* Pre-built behavior tree patterns for common NPC and object behaviors.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
BTNode,
|
|
9
|
+
ActionNode,
|
|
10
|
+
ConditionNode,
|
|
11
|
+
WaitNode,
|
|
12
|
+
SequenceNode,
|
|
13
|
+
SelectorNode,
|
|
14
|
+
RepeaterNode,
|
|
15
|
+
InverterNode,
|
|
16
|
+
} from './BehaviorTree';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Patrol: Move between waypoints with pauses.
|
|
20
|
+
*/
|
|
21
|
+
export function createPatrolBehavior(
|
|
22
|
+
waypointCount: number = 3,
|
|
23
|
+
pauseDuration: number = 2.0
|
|
24
|
+
): BTNode {
|
|
25
|
+
return new RepeaterNode(
|
|
26
|
+
new SequenceNode([
|
|
27
|
+
new ActionNode('selectNextWaypoint', (ctx) => {
|
|
28
|
+
ctx.waypointIndex = ((ctx.waypointIndex || 0) + 1) % waypointCount;
|
|
29
|
+
ctx.targetReached = false;
|
|
30
|
+
return 'success';
|
|
31
|
+
}),
|
|
32
|
+
new ActionNode('moveToWaypoint', (ctx, delta) => {
|
|
33
|
+
ctx.moveProgress = (ctx.moveProgress || 0) + delta * 0.5;
|
|
34
|
+
if (ctx.moveProgress >= 1) {
|
|
35
|
+
ctx.moveProgress = 0;
|
|
36
|
+
ctx.targetReached = true;
|
|
37
|
+
return 'success';
|
|
38
|
+
}
|
|
39
|
+
return 'running';
|
|
40
|
+
}),
|
|
41
|
+
new WaitNode(pauseDuration),
|
|
42
|
+
]),
|
|
43
|
+
-1 // Infinite loop
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Idle: Wait, look around, repeat.
|
|
49
|
+
*/
|
|
50
|
+
export function createIdleBehavior(idleDuration: number = 3.0): BTNode {
|
|
51
|
+
return new RepeaterNode(
|
|
52
|
+
new SequenceNode([
|
|
53
|
+
new WaitNode(idleDuration),
|
|
54
|
+
new ActionNode('lookAround', (ctx) => {
|
|
55
|
+
ctx.lookAngle = Math.random() * Math.PI * 2;
|
|
56
|
+
return 'success';
|
|
57
|
+
}),
|
|
58
|
+
]),
|
|
59
|
+
-1
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Interact: Approach target, interact, return to origin.
|
|
65
|
+
*/
|
|
66
|
+
export function createInteractBehavior(): BTNode {
|
|
67
|
+
return new SequenceNode([
|
|
68
|
+
new ConditionNode('hasTarget', (ctx) => !!ctx.interactTarget),
|
|
69
|
+
new ActionNode('approach', (ctx, delta) => {
|
|
70
|
+
ctx.approachProgress = (ctx.approachProgress || 0) + delta;
|
|
71
|
+
if (ctx.approachProgress >= 1.5) {
|
|
72
|
+
ctx.approachProgress = 0;
|
|
73
|
+
return 'success';
|
|
74
|
+
}
|
|
75
|
+
return 'running';
|
|
76
|
+
}),
|
|
77
|
+
new ActionNode('interact', (ctx) => {
|
|
78
|
+
ctx.interactionCount = (ctx.interactionCount || 0) + 1;
|
|
79
|
+
ctx.interactTarget = null;
|
|
80
|
+
return 'success';
|
|
81
|
+
}),
|
|
82
|
+
]);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Follow: Follow a target entity, maintaining distance.
|
|
87
|
+
*/
|
|
88
|
+
export function createFollowBehavior(minDist: number = 1.5): BTNode {
|
|
89
|
+
return new RepeaterNode(
|
|
90
|
+
new SelectorNode([
|
|
91
|
+
// If close enough, idle
|
|
92
|
+
new SequenceNode([
|
|
93
|
+
new ConditionNode('closeEnough', (ctx) => {
|
|
94
|
+
const dist = ctx.distanceToTarget || 0;
|
|
95
|
+
return dist <= minDist;
|
|
96
|
+
}),
|
|
97
|
+
new WaitNode(0.5),
|
|
98
|
+
]),
|
|
99
|
+
// Otherwise, move toward target
|
|
100
|
+
new ActionNode('moveToTarget', (ctx, delta) => {
|
|
101
|
+
ctx.distanceToTarget = Math.max(0, (ctx.distanceToTarget || 5) - delta * 2);
|
|
102
|
+
return ctx.distanceToTarget <= minDist ? 'success' : 'running';
|
|
103
|
+
}),
|
|
104
|
+
]),
|
|
105
|
+
-1
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Alert: Check for threats, flee or fight.
|
|
111
|
+
*/
|
|
112
|
+
export function createAlertBehavior(): BTNode {
|
|
113
|
+
return new SelectorNode([
|
|
114
|
+
// Fight if brave
|
|
115
|
+
new SequenceNode([
|
|
116
|
+
new ConditionNode('isBrave', (ctx) => ctx.courage > 0.5),
|
|
117
|
+
new ConditionNode('hasThreat', (ctx) => !!ctx.threat),
|
|
118
|
+
new ActionNode('fight', (ctx) => {
|
|
119
|
+
ctx.fightCount = (ctx.fightCount || 0) + 1;
|
|
120
|
+
ctx.threat = null;
|
|
121
|
+
return 'success';
|
|
122
|
+
}),
|
|
123
|
+
]),
|
|
124
|
+
// Flee if threatened
|
|
125
|
+
new SequenceNode([
|
|
126
|
+
new ConditionNode('hasThreat', (ctx) => !!ctx.threat),
|
|
127
|
+
new ActionNode('flee', (ctx, delta) => {
|
|
128
|
+
ctx.fleeProgress = (ctx.fleeProgress || 0) + delta;
|
|
129
|
+
if (ctx.fleeProgress >= 2.0) {
|
|
130
|
+
ctx.fleeProgress = 0;
|
|
131
|
+
ctx.threat = null;
|
|
132
|
+
return 'success';
|
|
133
|
+
}
|
|
134
|
+
return 'running';
|
|
135
|
+
}),
|
|
136
|
+
]),
|
|
137
|
+
// Default: idle
|
|
138
|
+
new WaitNode(1.0),
|
|
139
|
+
]);
|
|
140
|
+
}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BehaviorTree.ts
|
|
3
|
+
*
|
|
4
|
+
* Lightweight behavior tree for NPC AI and complex decision-making.
|
|
5
|
+
* Supports: Sequence, Selector, Inverter, Repeater, Action, Condition nodes.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// =============================================================================
|
|
9
|
+
// TYPES
|
|
10
|
+
// =============================================================================
|
|
11
|
+
|
|
12
|
+
export type NodeStatus = 'success' | 'failure' | 'running';
|
|
13
|
+
|
|
14
|
+
export interface BTContext {
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- dynamic context bag for behavior tree state
|
|
16
|
+
[key: string]: any;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface BTNode {
|
|
20
|
+
type: string;
|
|
21
|
+
tick(context: BTContext, delta: number): NodeStatus;
|
|
22
|
+
reset?(): void;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// =============================================================================
|
|
26
|
+
// LEAF NODES
|
|
27
|
+
// =============================================================================
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Action: Executes a function. Returns success/failure/running.
|
|
31
|
+
*/
|
|
32
|
+
export class ActionNode implements BTNode {
|
|
33
|
+
type = 'action';
|
|
34
|
+
constructor(
|
|
35
|
+
public name: string,
|
|
36
|
+
private fn: (ctx: BTContext, delta: number) => NodeStatus
|
|
37
|
+
) {}
|
|
38
|
+
|
|
39
|
+
tick(context: BTContext, delta: number): NodeStatus {
|
|
40
|
+
return this.fn(context, delta);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Condition: Checks a predicate. Returns success/failure.
|
|
46
|
+
*/
|
|
47
|
+
export class ConditionNode implements BTNode {
|
|
48
|
+
type = 'condition';
|
|
49
|
+
constructor(
|
|
50
|
+
public name: string,
|
|
51
|
+
private predicate: (ctx: BTContext) => boolean
|
|
52
|
+
) {}
|
|
53
|
+
|
|
54
|
+
tick(context: BTContext): NodeStatus {
|
|
55
|
+
return this.predicate(context) ? 'success' : 'failure';
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Wait: Returns 'running' for a specified duration, then 'success'.
|
|
61
|
+
*/
|
|
62
|
+
export class WaitNode implements BTNode {
|
|
63
|
+
type = 'wait';
|
|
64
|
+
private elapsed: number = 0;
|
|
65
|
+
constructor(public duration: number) {}
|
|
66
|
+
|
|
67
|
+
tick(_context: BTContext, delta: number): NodeStatus {
|
|
68
|
+
this.elapsed += delta;
|
|
69
|
+
if (this.elapsed >= this.duration) {
|
|
70
|
+
return 'success';
|
|
71
|
+
}
|
|
72
|
+
return 'running';
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
reset(): void {
|
|
76
|
+
this.elapsed = 0;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// =============================================================================
|
|
81
|
+
// COMPOSITE NODES
|
|
82
|
+
// =============================================================================
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Sequence: Runs children in order. Fails on first failure.
|
|
86
|
+
* Returns 'running' if a child is running.
|
|
87
|
+
*/
|
|
88
|
+
export class SequenceNode implements BTNode {
|
|
89
|
+
type = 'sequence';
|
|
90
|
+
private currentIndex: number = 0;
|
|
91
|
+
|
|
92
|
+
constructor(public children: BTNode[]) {}
|
|
93
|
+
|
|
94
|
+
tick(context: BTContext, delta: number): NodeStatus {
|
|
95
|
+
while (this.currentIndex < this.children.length) {
|
|
96
|
+
const status = this.children[this.currentIndex].tick(context, delta);
|
|
97
|
+
|
|
98
|
+
if (status === 'failure') {
|
|
99
|
+
this.currentIndex = 0;
|
|
100
|
+
return 'failure';
|
|
101
|
+
}
|
|
102
|
+
if (status === 'running') {
|
|
103
|
+
return 'running';
|
|
104
|
+
}
|
|
105
|
+
// success -> next child
|
|
106
|
+
this.currentIndex++;
|
|
107
|
+
}
|
|
108
|
+
this.currentIndex = 0;
|
|
109
|
+
return 'success';
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
reset(): void {
|
|
113
|
+
this.currentIndex = 0;
|
|
114
|
+
for (const child of this.children) child.reset?.();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Selector: Tries children in order. Succeeds on first success.
|
|
120
|
+
* Falls through to next child on failure.
|
|
121
|
+
*/
|
|
122
|
+
export class SelectorNode implements BTNode {
|
|
123
|
+
type = 'selector';
|
|
124
|
+
private currentIndex: number = 0;
|
|
125
|
+
|
|
126
|
+
constructor(public children: BTNode[]) {}
|
|
127
|
+
|
|
128
|
+
tick(context: BTContext, delta: number): NodeStatus {
|
|
129
|
+
while (this.currentIndex < this.children.length) {
|
|
130
|
+
const status = this.children[this.currentIndex].tick(context, delta);
|
|
131
|
+
|
|
132
|
+
if (status === 'success') {
|
|
133
|
+
this.currentIndex = 0;
|
|
134
|
+
return 'success';
|
|
135
|
+
}
|
|
136
|
+
if (status === 'running') {
|
|
137
|
+
return 'running';
|
|
138
|
+
}
|
|
139
|
+
// failure -> try next child
|
|
140
|
+
this.currentIndex++;
|
|
141
|
+
}
|
|
142
|
+
this.currentIndex = 0;
|
|
143
|
+
return 'failure';
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
reset(): void {
|
|
147
|
+
this.currentIndex = 0;
|
|
148
|
+
for (const child of this.children) child.reset?.();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// =============================================================================
|
|
153
|
+
// DECORATOR NODES
|
|
154
|
+
// =============================================================================
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Inverter: Flips success/failure.
|
|
158
|
+
*/
|
|
159
|
+
export class InverterNode implements BTNode {
|
|
160
|
+
type = 'inverter';
|
|
161
|
+
constructor(public child: BTNode) {}
|
|
162
|
+
|
|
163
|
+
tick(context: BTContext, delta: number): NodeStatus {
|
|
164
|
+
const status = this.child.tick(context, delta);
|
|
165
|
+
if (status === 'success') return 'failure';
|
|
166
|
+
if (status === 'failure') return 'success';
|
|
167
|
+
return 'running';
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
reset(): void {
|
|
171
|
+
this.child.reset?.();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Repeater: Repeats a child N times (or infinitely if count = -1).
|
|
177
|
+
*/
|
|
178
|
+
export class RepeaterNode implements BTNode {
|
|
179
|
+
type = 'repeater';
|
|
180
|
+
private count: number = 0;
|
|
181
|
+
constructor(
|
|
182
|
+
public child: BTNode,
|
|
183
|
+
public maxCount: number = -1
|
|
184
|
+
) {}
|
|
185
|
+
|
|
186
|
+
tick(context: BTContext, delta: number): NodeStatus {
|
|
187
|
+
const status = this.child.tick(context, delta);
|
|
188
|
+
|
|
189
|
+
if (status === 'running') return 'running';
|
|
190
|
+
|
|
191
|
+
this.count++;
|
|
192
|
+
this.child.reset?.();
|
|
193
|
+
|
|
194
|
+
if (this.maxCount !== -1 && this.count >= this.maxCount) {
|
|
195
|
+
this.count = 0;
|
|
196
|
+
return 'success';
|
|
197
|
+
}
|
|
198
|
+
return 'running';
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
reset(): void {
|
|
202
|
+
this.count = 0;
|
|
203
|
+
this.child.reset?.();
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// =============================================================================
|
|
208
|
+
// BEHAVIOR TREE
|
|
209
|
+
// =============================================================================
|
|
210
|
+
|
|
211
|
+
export class BehaviorTree {
|
|
212
|
+
private root: BTNode;
|
|
213
|
+
private context: BTContext;
|
|
214
|
+
|
|
215
|
+
constructor(root: BTNode, context: BTContext = {}) {
|
|
216
|
+
this.root = root;
|
|
217
|
+
this.context = context;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
tick(delta: number): NodeStatus {
|
|
221
|
+
return this.root.tick(this.context, delta);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
getContext(): BTContext {
|
|
225
|
+
return this.context;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- matches BTContext index signature
|
|
229
|
+
setContext(key: string, value: any): void {
|
|
230
|
+
this.context[key] = value;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
reset(): void {
|
|
234
|
+
this.root.reset?.();
|
|
235
|
+
}
|
|
236
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StateMachine.ts
|
|
3
|
+
*
|
|
4
|
+
* Finite State Machine (FSM) for game logic, NPC AI, and UI state management.
|
|
5
|
+
* Supports:
|
|
6
|
+
* - Named states with enter/update/exit callbacks
|
|
7
|
+
* - Guarded transitions (conditions that must be true to transition)
|
|
8
|
+
* - Transition actions (side effects on transition)
|
|
9
|
+
* - Event-driven and tick-driven transitions
|
|
10
|
+
* - State history tracking
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// =============================================================================
|
|
14
|
+
// TYPES
|
|
15
|
+
// =============================================================================
|
|
16
|
+
|
|
17
|
+
export interface StateConfig {
|
|
18
|
+
name: string;
|
|
19
|
+
onEnter?: (context: Record<string, unknown>) => void;
|
|
20
|
+
onUpdate?: (context: Record<string, unknown>, delta: number) => void;
|
|
21
|
+
onExit?: (context: Record<string, unknown>) => void;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface TransitionConfig {
|
|
25
|
+
from: string;
|
|
26
|
+
to: string;
|
|
27
|
+
event?: string; // Trigger on event
|
|
28
|
+
guard?: (context: Record<string, unknown>) => boolean; // Must return true to allow
|
|
29
|
+
action?: (context: Record<string, unknown>) => void; // Side effect on transition
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface StateMachineConfig {
|
|
33
|
+
initialState: string;
|
|
34
|
+
states: StateConfig[];
|
|
35
|
+
transitions: TransitionConfig[];
|
|
36
|
+
context?: Record<string, unknown>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// =============================================================================
|
|
40
|
+
// STATE MACHINE
|
|
41
|
+
// =============================================================================
|
|
42
|
+
|
|
43
|
+
export class StateMachine {
|
|
44
|
+
private states: Map<string, StateConfig> = new Map();
|
|
45
|
+
private transitions: TransitionConfig[] = [];
|
|
46
|
+
private currentStateName: string = '';
|
|
47
|
+
private previousStateName: string = '';
|
|
48
|
+
private context: Record<string, unknown>;
|
|
49
|
+
private history: string[] = [];
|
|
50
|
+
private maxHistory: number = 50;
|
|
51
|
+
|
|
52
|
+
constructor(config: StateMachineConfig) {
|
|
53
|
+
this.context = config.context || {};
|
|
54
|
+
|
|
55
|
+
for (const state of config.states) {
|
|
56
|
+
this.states.set(state.name, state);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
this.transitions = config.transitions;
|
|
60
|
+
|
|
61
|
+
// Enter initial state
|
|
62
|
+
this.enterState(config.initialState);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Get the current state name.
|
|
67
|
+
*/
|
|
68
|
+
getCurrentState(): string {
|
|
69
|
+
return this.currentStateName;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Get the previous state name.
|
|
74
|
+
*/
|
|
75
|
+
getPreviousState(): string {
|
|
76
|
+
return this.previousStateName;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Get the shared context.
|
|
81
|
+
*/
|
|
82
|
+
getContext(): Record<string, unknown> {
|
|
83
|
+
return this.context;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Get state transition history.
|
|
88
|
+
*/
|
|
89
|
+
getHistory(): string[] {
|
|
90
|
+
return [...this.history];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Send an event to the state machine. May trigger a transition.
|
|
95
|
+
*/
|
|
96
|
+
send(event: string): boolean {
|
|
97
|
+
const transition = this.transitions.find(
|
|
98
|
+
(t) =>
|
|
99
|
+
t.from === this.currentStateName && t.event === event && (!t.guard || t.guard(this.context))
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
if (!transition) return false;
|
|
103
|
+
|
|
104
|
+
this.executeTransition(transition);
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Try to transition based on guards (no event, just check conditions).
|
|
110
|
+
* Called automatically during update, or manually.
|
|
111
|
+
*/
|
|
112
|
+
evaluate(): boolean {
|
|
113
|
+
const transition = this.transitions.find(
|
|
114
|
+
(t) => t.from === this.currentStateName && !t.event && t.guard && t.guard(this.context)
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
if (!transition) return false;
|
|
118
|
+
|
|
119
|
+
this.executeTransition(transition);
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Force a transition to a specific state (bypasses guards).
|
|
125
|
+
*/
|
|
126
|
+
forceTransition(stateName: string): void {
|
|
127
|
+
if (!this.states.has(stateName)) return;
|
|
128
|
+
|
|
129
|
+
const currentState = this.states.get(this.currentStateName);
|
|
130
|
+
if (currentState?.onExit) currentState.onExit(this.context);
|
|
131
|
+
|
|
132
|
+
this.enterState(stateName);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Update the state machine. Call every frame.
|
|
137
|
+
*/
|
|
138
|
+
update(delta: number): void {
|
|
139
|
+
const state = this.states.get(this.currentStateName);
|
|
140
|
+
if (state?.onUpdate) {
|
|
141
|
+
state.onUpdate(this.context, delta);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Auto-evaluate guard-based transitions
|
|
145
|
+
this.evaluate();
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Check if we're in a specific state.
|
|
150
|
+
*/
|
|
151
|
+
isInState(stateName: string): boolean {
|
|
152
|
+
return this.currentStateName === stateName;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
private executeTransition(transition: TransitionConfig): void {
|
|
156
|
+
const fromState = this.states.get(this.currentStateName);
|
|
157
|
+
if (fromState?.onExit) fromState.onExit(this.context);
|
|
158
|
+
|
|
159
|
+
if (transition.action) transition.action(this.context);
|
|
160
|
+
|
|
161
|
+
this.enterState(transition.to);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
private enterState(stateName: string): void {
|
|
165
|
+
this.previousStateName = this.currentStateName;
|
|
166
|
+
this.currentStateName = stateName;
|
|
167
|
+
|
|
168
|
+
this.history.push(stateName);
|
|
169
|
+
if (this.history.length > this.maxHistory) {
|
|
170
|
+
this.history.shift();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const state = this.states.get(stateName);
|
|
174
|
+
if (state?.onEnter) state.onEnter(this.context);
|
|
175
|
+
}
|
|
176
|
+
}
|