@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,151 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { SteeringBehaviors, type SteeringAgent, type FlockConfig } from '../SteeringBehaviors';
|
|
3
|
+
|
|
4
|
+
type Vec3 = { x: number; y: number; z: number };
|
|
5
|
+
|
|
6
|
+
function agent(pos: Vec3, vel: Vec3 = { x: 0, y: 0, z: 0 }): SteeringAgent {
|
|
7
|
+
return { position: pos, velocity: vel, maxSpeed: 10, maxForce: 5, mass: 1 };
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function vecLen(v: Vec3): number {
|
|
11
|
+
return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
describe('SteeringBehaviors', () => {
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// Seek
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
|
|
19
|
+
it('seek produces force toward target', () => {
|
|
20
|
+
const a = agent({ x: 0, y: 0, z: 0 });
|
|
21
|
+
const force = SteeringBehaviors.seek(a, { x: 10, y: 0, z: 0 });
|
|
22
|
+
expect(force.x).toBeGreaterThan(0);
|
|
23
|
+
expect(Math.abs(force.y)).toBeLessThan(0.001);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('seek returns zero-ish force when at target', () => {
|
|
27
|
+
const a = agent({ x: 5, y: 5, z: 0 });
|
|
28
|
+
const force = SteeringBehaviors.seek(a, { x: 5, y: 5, z: 0 });
|
|
29
|
+
expect(vecLen(force)).toBeLessThan(0.01);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// Flee
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
|
|
36
|
+
it('flee produces force away from threat', () => {
|
|
37
|
+
const a = agent({ x: 0, y: 0, z: 0 });
|
|
38
|
+
const force = SteeringBehaviors.flee(a, { x: 10, y: 0, z: 0 });
|
|
39
|
+
expect(force.x).toBeLessThan(0);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
// Arrive
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
|
|
46
|
+
it('arrive slows down within slowRadius', () => {
|
|
47
|
+
const a = agent({ x: 0, y: 0, z: 0 });
|
|
48
|
+
const forceFar = SteeringBehaviors.arrive(a, { x: 100, y: 0, z: 0 }, 20);
|
|
49
|
+
const aClose = agent({ x: 95, y: 0, z: 0 });
|
|
50
|
+
const forceClose = SteeringBehaviors.arrive(aClose, { x: 100, y: 0, z: 0 }, 20);
|
|
51
|
+
expect(vecLen(forceClose)).toBeLessThanOrEqual(vecLen(forceFar) + 0.01);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('arrive returns zero when at target', () => {
|
|
55
|
+
const a = agent({ x: 5, y: 0, z: 0 });
|
|
56
|
+
const force = SteeringBehaviors.arrive(a, { x: 5, y: 0, z: 0 }, 10);
|
|
57
|
+
expect(vecLen(force)).toBeLessThan(0.01);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
// Wander
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
|
|
64
|
+
it('wander returns a force and new angle', () => {
|
|
65
|
+
const a = agent({ x: 0, y: 0, z: 0 }, { x: 1, y: 0, z: 0 });
|
|
66
|
+
const result = SteeringBehaviors.wander(a, 2, 1, 0.3, 0);
|
|
67
|
+
expect(result.force).toBeDefined();
|
|
68
|
+
expect(typeof result.newAngle).toBe('number');
|
|
69
|
+
expect(Number.isFinite(result.force.x)).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
// Flock
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
|
|
76
|
+
it('flock returns a combined steering force', () => {
|
|
77
|
+
const a = agent({ x: 0, y: 0, z: 0 });
|
|
78
|
+
const neighbors = [
|
|
79
|
+
agent({ x: 2, y: 0, z: 0 }, { x: 1, y: 0, z: 0 }),
|
|
80
|
+
agent({ x: -2, y: 0, z: 0 }, { x: 1, y: 0, z: 0 }),
|
|
81
|
+
];
|
|
82
|
+
const config: FlockConfig = {
|
|
83
|
+
separationWeight: 1,
|
|
84
|
+
alignmentWeight: 1,
|
|
85
|
+
cohesionWeight: 1,
|
|
86
|
+
neighborRadius: 10,
|
|
87
|
+
};
|
|
88
|
+
const force = SteeringBehaviors.flock(a, neighbors, config);
|
|
89
|
+
expect(Number.isFinite(force.x)).toBe(true);
|
|
90
|
+
expect(Number.isFinite(force.y)).toBe(true);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('flock returns zero with no neighbors in range', () => {
|
|
94
|
+
const a = agent({ x: 0, y: 0, z: 0 });
|
|
95
|
+
const neighbors = [agent({ x: 500, y: 500, z: 0 })]; // far away
|
|
96
|
+
const config: FlockConfig = {
|
|
97
|
+
separationWeight: 1,
|
|
98
|
+
alignmentWeight: 1,
|
|
99
|
+
cohesionWeight: 1,
|
|
100
|
+
neighborRadius: 5,
|
|
101
|
+
};
|
|
102
|
+
const force = SteeringBehaviors.flock(a, neighbors, config);
|
|
103
|
+
expect(force).toEqual({ x: 0, y: 0, z: 0 });
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
// Obstacle Avoidance
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
|
|
110
|
+
it('obstacleAvoidance returns force when obstacle ahead', () => {
|
|
111
|
+
const a = agent({ x: 0, y: 0, z: 0 }, { x: 1, y: 0, z: 0 });
|
|
112
|
+
const obstacles = [{ center: { x: 3, y: 0, z: 0 }, radius: 1 }];
|
|
113
|
+
const force = SteeringBehaviors.obstacleAvoidance(a, obstacles, 5);
|
|
114
|
+
expect(Number.isFinite(force.x)).toBe(true);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('obstacleAvoidance returns zero with no obstacles', () => {
|
|
118
|
+
const a = agent({ x: 0, y: 0, z: 0 }, { x: 1, y: 0, z: 0 });
|
|
119
|
+
const force = SteeringBehaviors.obstacleAvoidance(a, [], 5);
|
|
120
|
+
expect(force).toEqual({ x: 0, y: 0, z: 0 });
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
// Apply Force
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
|
|
127
|
+
it('applyForce updates agent position and velocity', () => {
|
|
128
|
+
const a = agent({ x: 0, y: 0, z: 0 }, { x: 0, y: 0, z: 0 });
|
|
129
|
+
SteeringBehaviors.applyForce(a, { x: 5, y: 0, z: 0 }, 1);
|
|
130
|
+
expect(a.velocity.x).toBeGreaterThan(0);
|
|
131
|
+
expect(a.position.x).toBeGreaterThan(0);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('applyForce clamps velocity to maxSpeed', () => {
|
|
135
|
+
const a = agent({ x: 0, y: 0, z: 0 }, { x: 0, y: 0, z: 0 });
|
|
136
|
+
a.maxSpeed = 5;
|
|
137
|
+
SteeringBehaviors.applyForce(a, { x: 100, y: 0, z: 0 }, 1);
|
|
138
|
+
const speed = vecLen(a.velocity);
|
|
139
|
+
expect(speed).toBeLessThanOrEqual(5.01);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('applyForce accounts for mass', () => {
|
|
143
|
+
const heavy = agent({ x: 0, y: 0, z: 0 }, { x: 0, y: 0, z: 0 });
|
|
144
|
+
heavy.mass = 10;
|
|
145
|
+
const light = agent({ x: 0, y: 0, z: 0 }, { x: 0, y: 0, z: 0 });
|
|
146
|
+
light.mass = 1;
|
|
147
|
+
SteeringBehaviors.applyForce(heavy, { x: 5, y: 0, z: 0 }, 1);
|
|
148
|
+
SteeringBehaviors.applyForce(light, { x: 5, y: 0, z: 0 }, 1);
|
|
149
|
+
expect(light.velocity.x).toBeGreaterThan(heavy.velocity.x);
|
|
150
|
+
});
|
|
151
|
+
});
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TrainingDataGenerator — Production Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests: constructor, generate (no opts, category, complexity, count, combined),
|
|
5
|
+
* generateAll, getByCategory, getByComplexity, getByTag, getStats,
|
|
6
|
+
* exportJSON, exportJSONL, createTrainingDataGenerator factory.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { describe, it, expect } from 'vitest';
|
|
10
|
+
import {
|
|
11
|
+
TrainingDataGenerator,
|
|
12
|
+
createTrainingDataGenerator,
|
|
13
|
+
ALL_CATEGORIES,
|
|
14
|
+
} from '../TrainingDataGenerator';
|
|
15
|
+
|
|
16
|
+
describe('TrainingDataGenerator — constructor / generateAll', () => {
|
|
17
|
+
it('has non-empty example pool after construction', () => {
|
|
18
|
+
const gen = new TrainingDataGenerator();
|
|
19
|
+
expect(gen.generateAll().length).toBeGreaterThan(0);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('all examples have required fields', () => {
|
|
23
|
+
const gen = new TrainingDataGenerator();
|
|
24
|
+
for (const ex of gen.generateAll()) {
|
|
25
|
+
expect(typeof ex.id).toBe('string');
|
|
26
|
+
expect(typeof ex.category).toBe('string');
|
|
27
|
+
expect(typeof ex.holoScript).toBe('string');
|
|
28
|
+
expect(['basic', 'intermediate', 'advanced']).toContain(ex.complexity);
|
|
29
|
+
expect(Array.isArray(ex.tags)).toBe(true);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('generateAll returns same count on each call', () => {
|
|
34
|
+
const gen = new TrainingDataGenerator();
|
|
35
|
+
expect(gen.generateAll().length).toBe(gen.generateAll().length);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('generateAll result is a copy (mutation does not affect internal state)', () => {
|
|
39
|
+
const gen = new TrainingDataGenerator();
|
|
40
|
+
const all1 = gen.generateAll();
|
|
41
|
+
all1.length = 0;
|
|
42
|
+
expect(gen.generateAll().length).toBeGreaterThan(0);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
describe('TrainingDataGenerator — generate() no filters', () => {
|
|
47
|
+
it('returns all examples when no options given', () => {
|
|
48
|
+
const gen = new TrainingDataGenerator();
|
|
49
|
+
expect(gen.generate().length).toBe(gen.generateAll().length);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
describe('TrainingDataGenerator — generate() category filter', () => {
|
|
54
|
+
it('filters by single category', () => {
|
|
55
|
+
const gen = new TrainingDataGenerator();
|
|
56
|
+
const results = gen.generate({ categories: ['geometry'] });
|
|
57
|
+
expect(results.length).toBeGreaterThan(0);
|
|
58
|
+
expect(results.every((e) => e.category === 'geometry')).toBe(true);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('filters by multiple categories', () => {
|
|
62
|
+
const gen = new TrainingDataGenerator();
|
|
63
|
+
const results = gen.generate({ categories: ['geometry', 'physics'] });
|
|
64
|
+
expect(results.every((e) => ['geometry', 'physics'].includes(e.category))).toBe(true);
|
|
65
|
+
expect(results.length).toBeGreaterThan(0);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('empty categories array returns all', () => {
|
|
69
|
+
const gen = new TrainingDataGenerator();
|
|
70
|
+
const results = gen.generate({ categories: [] });
|
|
71
|
+
expect(results.length).toBe(gen.generateAll().length);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
describe('TrainingDataGenerator — generate() complexity filter', () => {
|
|
76
|
+
it('filters basic only', () => {
|
|
77
|
+
const gen = new TrainingDataGenerator();
|
|
78
|
+
const results = gen.generate({ complexityFilter: ['basic'] });
|
|
79
|
+
expect(results.length).toBeGreaterThan(0);
|
|
80
|
+
expect(results.every((e) => e.complexity === 'basic')).toBe(true);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('filters advanced only', () => {
|
|
84
|
+
const gen = new TrainingDataGenerator();
|
|
85
|
+
const results = gen.generate({ complexityFilter: ['advanced'] });
|
|
86
|
+
expect(results.every((e) => e.complexity === 'advanced')).toBe(true);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('filters multiple complexities', () => {
|
|
90
|
+
const gen = new TrainingDataGenerator();
|
|
91
|
+
const results = gen.generate({ complexityFilter: ['basic', 'intermediate'] });
|
|
92
|
+
expect(results.every((e) => ['basic', 'intermediate'].includes(e.complexity))).toBe(true);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
describe('TrainingDataGenerator — generate() count limit', () => {
|
|
97
|
+
it('limits results to count', () => {
|
|
98
|
+
const gen = new TrainingDataGenerator();
|
|
99
|
+
const results = gen.generate({ count: 3 });
|
|
100
|
+
expect(results.length).toBe(3);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('count larger than pool returns all', () => {
|
|
104
|
+
const gen = new TrainingDataGenerator();
|
|
105
|
+
const total = gen.generateAll().length;
|
|
106
|
+
const results = gen.generate({ count: total + 999 });
|
|
107
|
+
expect(results.length).toBe(total);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('count=1 returns single example', () => {
|
|
111
|
+
const gen = new TrainingDataGenerator();
|
|
112
|
+
const results = gen.generate({ count: 1 });
|
|
113
|
+
expect(results.length).toBe(1);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
describe('TrainingDataGenerator — generate() combined filters', () => {
|
|
118
|
+
it('category + complexity combined', () => {
|
|
119
|
+
const gen = new TrainingDataGenerator();
|
|
120
|
+
const results = gen.generate({ categories: ['physics'], complexityFilter: ['basic'] });
|
|
121
|
+
expect(results.every((e) => e.category === 'physics' && e.complexity === 'basic')).toBe(true);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('count with category never exceeds category pool', () => {
|
|
125
|
+
const gen = new TrainingDataGenerator();
|
|
126
|
+
const geoAll = gen.generate({ categories: ['geometry'] });
|
|
127
|
+
const geoLimited = gen.generate({ categories: ['geometry'], count: 1 });
|
|
128
|
+
expect(geoLimited.length).toBe(Math.min(1, geoAll.length));
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
describe('TrainingDataGenerator — getByCategory', () => {
|
|
133
|
+
it('returns correct category', () => {
|
|
134
|
+
const gen = new TrainingDataGenerator();
|
|
135
|
+
const results = gen.getByCategory('audio');
|
|
136
|
+
expect(results.length).toBeGreaterThan(0);
|
|
137
|
+
expect(results.every((e) => e.category === 'audio')).toBe(true);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('returns empty for unknown category (cast)', () => {
|
|
141
|
+
const gen = new TrainingDataGenerator();
|
|
142
|
+
const results = gen.getByCategory('zzzz' as any);
|
|
143
|
+
expect(results).toHaveLength(0);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
describe('TrainingDataGenerator — getByComplexity', () => {
|
|
148
|
+
it('returns basic complexity examples', () => {
|
|
149
|
+
const gen = new TrainingDataGenerator();
|
|
150
|
+
const results = gen.getByComplexity('basic');
|
|
151
|
+
expect(results.every((e) => e.complexity === 'basic')).toBe(true);
|
|
152
|
+
expect(results.length).toBeGreaterThan(0);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('basic + intermediate + advanced covers all', () => {
|
|
156
|
+
const gen = new TrainingDataGenerator();
|
|
157
|
+
const total = gen.generateAll().length;
|
|
158
|
+
const b = gen.getByComplexity('basic').length;
|
|
159
|
+
const i = gen.getByComplexity('intermediate').length;
|
|
160
|
+
const a = gen.getByComplexity('advanced').length;
|
|
161
|
+
expect(b + i + a).toBe(total);
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
describe('TrainingDataGenerator — getByTag', () => {
|
|
166
|
+
it('returns examples that include the tag', () => {
|
|
167
|
+
const gen = new TrainingDataGenerator();
|
|
168
|
+
const results = gen.getByTag('physics');
|
|
169
|
+
expect(results.length).toBeGreaterThan(0);
|
|
170
|
+
expect(results.every((e) => e.tags.includes('physics'))).toBe(true);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('returns empty for unknown tag', () => {
|
|
174
|
+
const gen = new TrainingDataGenerator();
|
|
175
|
+
expect(gen.getByTag('zzz-unknown-xxx')).toHaveLength(0);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it('tag "basic" matches examples with that tag', () => {
|
|
179
|
+
const gen = new TrainingDataGenerator();
|
|
180
|
+
const results = gen.getByTag('basic');
|
|
181
|
+
expect(results.every((e) => e.tags.includes('basic'))).toBe(true);
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
describe('TrainingDataGenerator — getStats', () => {
|
|
186
|
+
it('returns an object with geometry key', () => {
|
|
187
|
+
const gen = new TrainingDataGenerator();
|
|
188
|
+
const stats = gen.getStats();
|
|
189
|
+
expect(typeof stats.geometry).toBe('number');
|
|
190
|
+
expect(stats.geometry).toBeGreaterThan(0);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('sum of all category counts equals total examples', () => {
|
|
194
|
+
const gen = new TrainingDataGenerator();
|
|
195
|
+
const stats = gen.getStats();
|
|
196
|
+
const sumStats = Object.values(stats).reduce((a, b) => a + b, 0);
|
|
197
|
+
expect(sumStats).toBe(gen.generateAll().length);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it('each category in stats appears in ALL_CATEGORIES', () => {
|
|
201
|
+
const gen = new TrainingDataGenerator();
|
|
202
|
+
const stats = gen.getStats();
|
|
203
|
+
for (const key of Object.keys(stats)) {
|
|
204
|
+
expect(ALL_CATEGORIES).toContain(key);
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
describe('TrainingDataGenerator — exportJSON / exportJSONL', () => {
|
|
210
|
+
it('exportJSON returns valid JSON string', () => {
|
|
211
|
+
const gen = new TrainingDataGenerator();
|
|
212
|
+
const json = gen.exportJSON();
|
|
213
|
+
expect(() => JSON.parse(json)).not.toThrow();
|
|
214
|
+
const parsed = JSON.parse(json);
|
|
215
|
+
expect(Array.isArray(parsed)).toBe(true);
|
|
216
|
+
expect(parsed.length).toBe(gen.generateAll().length);
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it('exportJSON is formatted with indentation', () => {
|
|
220
|
+
const gen = new TrainingDataGenerator();
|
|
221
|
+
const json = gen.exportJSON();
|
|
222
|
+
expect(json).toContain('\n');
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it('exportJSONL returns one object per line', () => {
|
|
226
|
+
const gen = new TrainingDataGenerator();
|
|
227
|
+
const lines = gen
|
|
228
|
+
.exportJSONL()
|
|
229
|
+
.split('\n')
|
|
230
|
+
.filter((l) => l.trim().length > 0);
|
|
231
|
+
expect(lines.length).toBe(gen.generateAll().length);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it('each JSONL line is valid JSON', () => {
|
|
235
|
+
const gen = new TrainingDataGenerator();
|
|
236
|
+
const lines = gen
|
|
237
|
+
.exportJSONL()
|
|
238
|
+
.split('\n')
|
|
239
|
+
.filter((l) => l.trim().length > 0);
|
|
240
|
+
for (const line of lines) {
|
|
241
|
+
expect(() => JSON.parse(line)).not.toThrow();
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it('JSONL lines do not contain newlines within them', () => {
|
|
246
|
+
const gen = new TrainingDataGenerator();
|
|
247
|
+
const lines = gen
|
|
248
|
+
.exportJSONL()
|
|
249
|
+
.split('\n')
|
|
250
|
+
.filter((l) => l.trim().length > 0);
|
|
251
|
+
for (const line of lines) {
|
|
252
|
+
// the holoScript field contains internal newlines but JSON.stringify escapes them
|
|
253
|
+
const obj = JSON.parse(line);
|
|
254
|
+
expect(typeof obj.id).toBe('string');
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
describe('createTrainingDataGenerator factory', () => {
|
|
260
|
+
it('returns a TrainingDataGenerator instance', () => {
|
|
261
|
+
const gen = createTrainingDataGenerator();
|
|
262
|
+
expect(gen).toBeInstanceOf(TrainingDataGenerator);
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it('factory produces same total as constructor', () => {
|
|
266
|
+
const gen1 = new TrainingDataGenerator();
|
|
267
|
+
const gen2 = createTrainingDataGenerator();
|
|
268
|
+
expect(gen2.generateAll().length).toBe(gen1.generateAll().length);
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
describe('ALL_CATEGORIES', () => {
|
|
273
|
+
it('is a non-empty array of strings', () => {
|
|
274
|
+
expect(Array.isArray(ALL_CATEGORIES)).toBe(true);
|
|
275
|
+
expect(ALL_CATEGORIES.length).toBeGreaterThan(0);
|
|
276
|
+
expect(ALL_CATEGORIES.every((c) => typeof c === 'string')).toBe(true);
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
it('includes expected categories', () => {
|
|
280
|
+
expect(ALL_CATEGORIES).toContain('geometry');
|
|
281
|
+
expect(ALL_CATEGORIES).toContain('physics');
|
|
282
|
+
expect(ALL_CATEGORIES).toContain('ui');
|
|
283
|
+
expect(ALL_CATEGORIES).toContain('animations');
|
|
284
|
+
expect(ALL_CATEGORIES).toContain('ar_vr');
|
|
285
|
+
});
|
|
286
|
+
});
|