@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,472 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @holoscript/core - Skill Workflow Engine
|
|
3
|
+
*
|
|
4
|
+
* DAG-based skill composition and chaining. Validates workflow definitions,
|
|
5
|
+
* resolves inter-step data dependencies, and executes steps in parallel groups.
|
|
6
|
+
* Uses topological sort pattern from MicroPhaseDecomposer.
|
|
7
|
+
*
|
|
8
|
+
* Part of HoloScript v5.5 "Agents as Universal Orchestrators".
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
// =============================================================================
|
|
12
|
+
// TYPES
|
|
13
|
+
// =============================================================================
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Input can be a literal value, a reference to another step's output, or context.
|
|
17
|
+
*/
|
|
18
|
+
export type WorkflowInput =
|
|
19
|
+
| { type: 'literal'; value: unknown }
|
|
20
|
+
| { type: 'ref'; stepId: string; outputKey: string }
|
|
21
|
+
| { type: 'context'; key: string };
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A single step in a workflow.
|
|
25
|
+
*/
|
|
26
|
+
export interface WorkflowStep {
|
|
27
|
+
/** Unique step identifier */
|
|
28
|
+
id: string;
|
|
29
|
+
/** Skill/tool to invoke */
|
|
30
|
+
skillId: string;
|
|
31
|
+
/** Input mapping: param name → source */
|
|
32
|
+
inputs: Record<string, WorkflowInput>;
|
|
33
|
+
/** Step IDs that must complete first */
|
|
34
|
+
dependsOn?: string[];
|
|
35
|
+
/** Per-step timeout in ms */
|
|
36
|
+
timeout?: number;
|
|
37
|
+
/** Error handling strategy */
|
|
38
|
+
onError?: 'fail' | 'skip' | 'fallback';
|
|
39
|
+
/** Fallback skill if primary fails and onError='fallback' */
|
|
40
|
+
fallbackSkillId?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Complete workflow definition.
|
|
45
|
+
*/
|
|
46
|
+
export interface WorkflowDefinition {
|
|
47
|
+
/** Workflow identifier */
|
|
48
|
+
id: string;
|
|
49
|
+
/** Human-readable name */
|
|
50
|
+
name: string;
|
|
51
|
+
/** Optional description */
|
|
52
|
+
description?: string;
|
|
53
|
+
/** Ordered steps (topologically sorted at validation) */
|
|
54
|
+
steps: WorkflowStep[];
|
|
55
|
+
/** Initial context data */
|
|
56
|
+
context?: Record<string, unknown>;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Validation result for a workflow definition.
|
|
61
|
+
*/
|
|
62
|
+
export interface WorkflowValidation {
|
|
63
|
+
/** Whether the workflow is valid */
|
|
64
|
+
valid: boolean;
|
|
65
|
+
/** Validation errors */
|
|
66
|
+
errors: string[];
|
|
67
|
+
/** Validation warnings */
|
|
68
|
+
warnings: string[];
|
|
69
|
+
/** Execution plan: groups of step IDs that can run in parallel */
|
|
70
|
+
executionPlan: { groups: string[][]; estimatedSteps: number };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Result of a single step execution.
|
|
75
|
+
*/
|
|
76
|
+
export interface WorkflowStepResult {
|
|
77
|
+
stepId: string;
|
|
78
|
+
status: 'completed' | 'failed' | 'skipped';
|
|
79
|
+
output: Record<string, unknown>;
|
|
80
|
+
durationMs: number;
|
|
81
|
+
error?: string;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Result of a full workflow execution.
|
|
86
|
+
*/
|
|
87
|
+
export interface WorkflowResult {
|
|
88
|
+
workflowId: string;
|
|
89
|
+
status: 'completed' | 'partial' | 'failed';
|
|
90
|
+
stepResults: WorkflowStepResult[];
|
|
91
|
+
totalDurationMs: number;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Executor function type: takes a skill ID and inputs, returns outputs.
|
|
96
|
+
*/
|
|
97
|
+
export type SkillExecutor = (
|
|
98
|
+
skillId: string,
|
|
99
|
+
inputs: Record<string, unknown>
|
|
100
|
+
) => Promise<Record<string, unknown>>;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Progress callback type.
|
|
104
|
+
*/
|
|
105
|
+
export type ProgressCallback = (stepId: string, status: string) => void;
|
|
106
|
+
|
|
107
|
+
// =============================================================================
|
|
108
|
+
// SKILL WORKFLOW ENGINE
|
|
109
|
+
// =============================================================================
|
|
110
|
+
|
|
111
|
+
export class SkillWorkflowEngine {
|
|
112
|
+
// ===========================================================================
|
|
113
|
+
// VALIDATION
|
|
114
|
+
// ===========================================================================
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Validate a workflow definition.
|
|
118
|
+
*/
|
|
119
|
+
validate(definition: WorkflowDefinition, availableSkills?: string[]): WorkflowValidation {
|
|
120
|
+
const errors: string[] = [];
|
|
121
|
+
const warnings: string[] = [];
|
|
122
|
+
const stepIds = new Set(definition.steps.map((s) => s.id));
|
|
123
|
+
|
|
124
|
+
if (definition.steps.length === 0) {
|
|
125
|
+
errors.push('Workflow must have at least one step');
|
|
126
|
+
return { valid: false, errors, warnings, executionPlan: { groups: [], estimatedSteps: 0 } };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Check for duplicate step IDs
|
|
130
|
+
if (stepIds.size !== definition.steps.length) {
|
|
131
|
+
errors.push('Duplicate step IDs detected');
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
for (const step of definition.steps) {
|
|
135
|
+
// Validate step ID
|
|
136
|
+
if (!step.id) {
|
|
137
|
+
errors.push('Step missing required "id" field');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Validate skill exists
|
|
141
|
+
if (!step.skillId) {
|
|
142
|
+
errors.push(`Step "${step.id}": missing required "skillId" field`);
|
|
143
|
+
} else if (availableSkills && !availableSkills.includes(step.skillId)) {
|
|
144
|
+
errors.push(`Step "${step.id}": skill "${step.skillId}" not found in available skills`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Validate dependencies exist
|
|
148
|
+
if (step.dependsOn) {
|
|
149
|
+
for (const depId of step.dependsOn) {
|
|
150
|
+
if (!stepIds.has(depId)) {
|
|
151
|
+
errors.push(`Step "${step.id}": dependency "${depId}" does not exist`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Validate ref inputs point to valid steps
|
|
157
|
+
for (const [paramName, input] of Object.entries(step.inputs || {})) {
|
|
158
|
+
if (input.type === 'ref') {
|
|
159
|
+
if (!stepIds.has(input.stepId)) {
|
|
160
|
+
errors.push(
|
|
161
|
+
`Step "${step.id}": input "${paramName}" references non-existent step "${input.stepId}"`
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
// Ensure the referenced step is in dependsOn (or warn)
|
|
165
|
+
if (!step.dependsOn || !step.dependsOn.includes(input.stepId)) {
|
|
166
|
+
warnings.push(
|
|
167
|
+
`Step "${step.id}": input "${paramName}" references step "${input.stepId}" which is not in dependsOn — adding implicit dependency`
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Validate fallback
|
|
174
|
+
if (step.onError === 'fallback' && !step.fallbackSkillId) {
|
|
175
|
+
warnings.push(`Step "${step.id}": onError='fallback' but no fallbackSkillId specified`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Check for cycles
|
|
180
|
+
const cycleCheck = this.detectCycles(definition.steps);
|
|
181
|
+
if (cycleCheck) {
|
|
182
|
+
errors.push(`Cycle detected: ${cycleCheck}`);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Build execution plan
|
|
186
|
+
const groups = errors.length === 0 ? this.buildExecutionGroups(definition.steps) : [];
|
|
187
|
+
|
|
188
|
+
return {
|
|
189
|
+
valid: errors.length === 0,
|
|
190
|
+
errors,
|
|
191
|
+
warnings,
|
|
192
|
+
executionPlan: {
|
|
193
|
+
groups,
|
|
194
|
+
estimatedSteps: definition.steps.length,
|
|
195
|
+
},
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// ===========================================================================
|
|
200
|
+
// EXECUTION
|
|
201
|
+
// ===========================================================================
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Execute a workflow using the provided executor function.
|
|
205
|
+
*/
|
|
206
|
+
async execute(
|
|
207
|
+
definition: WorkflowDefinition,
|
|
208
|
+
executor: SkillExecutor,
|
|
209
|
+
onProgress?: ProgressCallback
|
|
210
|
+
): Promise<WorkflowResult> {
|
|
211
|
+
const startTime = Date.now();
|
|
212
|
+
const stepResults: WorkflowStepResult[] = [];
|
|
213
|
+
const stepOutputs = new Map<string, Record<string, unknown>>();
|
|
214
|
+
const context = definition.context || {};
|
|
215
|
+
|
|
216
|
+
// Build execution groups (topological sort into parallel layers)
|
|
217
|
+
const groups = this.buildExecutionGroups(definition.steps);
|
|
218
|
+
const stepMap = new Map(definition.steps.map((s) => [s.id, s]));
|
|
219
|
+
|
|
220
|
+
let hasFailed = false;
|
|
221
|
+
|
|
222
|
+
for (const group of groups) {
|
|
223
|
+
// Execute all steps in this group in parallel
|
|
224
|
+
const groupResults = await Promise.all(
|
|
225
|
+
group.map(async (stepId) => {
|
|
226
|
+
const step = stepMap.get(stepId)!;
|
|
227
|
+
|
|
228
|
+
// Skip if a previous step failed and onError is not configured
|
|
229
|
+
if (hasFailed && step.onError !== 'skip') {
|
|
230
|
+
const result: WorkflowStepResult = {
|
|
231
|
+
stepId,
|
|
232
|
+
status: 'skipped',
|
|
233
|
+
output: {},
|
|
234
|
+
durationMs: 0,
|
|
235
|
+
error: 'Skipped due to previous failure',
|
|
236
|
+
};
|
|
237
|
+
return result;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
onProgress?.(stepId, 'starting');
|
|
241
|
+
|
|
242
|
+
// Resolve inputs
|
|
243
|
+
const resolvedInputs = this.resolveInputs(step, stepOutputs, context);
|
|
244
|
+
|
|
245
|
+
const stepStart = Date.now();
|
|
246
|
+
try {
|
|
247
|
+
const output = await this.executeStep(step, resolvedInputs, executor);
|
|
248
|
+
stepOutputs.set(stepId, output);
|
|
249
|
+
onProgress?.(stepId, 'completed');
|
|
250
|
+
return {
|
|
251
|
+
stepId,
|
|
252
|
+
status: 'completed' as const,
|
|
253
|
+
output,
|
|
254
|
+
durationMs: Date.now() - stepStart,
|
|
255
|
+
};
|
|
256
|
+
} catch (err) {
|
|
257
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
258
|
+
onProgress?.(stepId, 'failed');
|
|
259
|
+
|
|
260
|
+
if (step.onError === 'skip') {
|
|
261
|
+
stepOutputs.set(stepId, {});
|
|
262
|
+
return {
|
|
263
|
+
stepId,
|
|
264
|
+
status: 'skipped' as const,
|
|
265
|
+
output: {},
|
|
266
|
+
durationMs: Date.now() - stepStart,
|
|
267
|
+
error,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
hasFailed = true;
|
|
272
|
+
return {
|
|
273
|
+
stepId,
|
|
274
|
+
status: 'failed' as const,
|
|
275
|
+
output: {},
|
|
276
|
+
durationMs: Date.now() - stepStart,
|
|
277
|
+
error,
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
})
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
stepResults.push(...groupResults);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const completedCount = stepResults.filter((r) => r.status === 'completed').length;
|
|
287
|
+
let status: 'completed' | 'partial' | 'failed';
|
|
288
|
+
if (completedCount === definition.steps.length) {
|
|
289
|
+
status = 'completed';
|
|
290
|
+
} else if (completedCount > 0) {
|
|
291
|
+
status = 'partial';
|
|
292
|
+
} else {
|
|
293
|
+
status = 'failed';
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return {
|
|
297
|
+
workflowId: definition.id,
|
|
298
|
+
status,
|
|
299
|
+
stepResults,
|
|
300
|
+
totalDurationMs: Date.now() - startTime,
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// ===========================================================================
|
|
305
|
+
// PRIVATE HELPERS
|
|
306
|
+
// ===========================================================================
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Execute a single step with optional fallback.
|
|
310
|
+
*/
|
|
311
|
+
private async executeStep(
|
|
312
|
+
step: WorkflowStep,
|
|
313
|
+
resolvedInputs: Record<string, unknown>,
|
|
314
|
+
executor: SkillExecutor
|
|
315
|
+
): Promise<Record<string, unknown>> {
|
|
316
|
+
try {
|
|
317
|
+
if (step.timeout) {
|
|
318
|
+
return await Promise.race([
|
|
319
|
+
executor(step.skillId, resolvedInputs),
|
|
320
|
+
new Promise<never>((_, reject) =>
|
|
321
|
+
setTimeout(
|
|
322
|
+
() => reject(new Error(`Step "${step.id}" timed out after ${step.timeout}ms`)),
|
|
323
|
+
step.timeout
|
|
324
|
+
)
|
|
325
|
+
),
|
|
326
|
+
]);
|
|
327
|
+
}
|
|
328
|
+
return await executor(step.skillId, resolvedInputs);
|
|
329
|
+
} catch (err) {
|
|
330
|
+
// Try fallback if configured
|
|
331
|
+
if (step.onError === 'fallback' && step.fallbackSkillId) {
|
|
332
|
+
return executor(step.fallbackSkillId, resolvedInputs);
|
|
333
|
+
}
|
|
334
|
+
throw err;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Resolve step inputs from literal values, step outputs, or context.
|
|
340
|
+
*/
|
|
341
|
+
private resolveInputs(
|
|
342
|
+
step: WorkflowStep,
|
|
343
|
+
stepOutputs: Map<string, Record<string, unknown>>,
|
|
344
|
+
context: Record<string, unknown>
|
|
345
|
+
): Record<string, unknown> {
|
|
346
|
+
const resolved: Record<string, unknown> = {};
|
|
347
|
+
|
|
348
|
+
for (const [paramName, input] of Object.entries(step.inputs || {})) {
|
|
349
|
+
switch (input.type) {
|
|
350
|
+
case 'literal':
|
|
351
|
+
resolved[paramName] = input.value;
|
|
352
|
+
break;
|
|
353
|
+
case 'ref': {
|
|
354
|
+
const outputs = stepOutputs.get(input.stepId);
|
|
355
|
+
resolved[paramName] = outputs?.[input.outputKey];
|
|
356
|
+
break;
|
|
357
|
+
}
|
|
358
|
+
case 'context':
|
|
359
|
+
resolved[paramName] = context[input.key];
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
return resolved;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Detect cycles in the step dependency graph.
|
|
369
|
+
* Returns a cycle description string, or null if no cycles.
|
|
370
|
+
*/
|
|
371
|
+
private detectCycles(steps: WorkflowStep[]): string | null {
|
|
372
|
+
const visited = new Set<string>();
|
|
373
|
+
const inStack = new Set<string>();
|
|
374
|
+
const adjList = new Map<string, string[]>();
|
|
375
|
+
|
|
376
|
+
for (const step of steps) {
|
|
377
|
+
const deps = [...(step.dependsOn || [])];
|
|
378
|
+
// Also add implicit dependencies from ref inputs
|
|
379
|
+
for (const input of Object.values(step.inputs || {})) {
|
|
380
|
+
if (input.type === 'ref' && !deps.includes(input.stepId)) {
|
|
381
|
+
deps.push(input.stepId);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
adjList.set(step.id, deps);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
const dfs = (nodeId: string, path: string[]): string | null => {
|
|
388
|
+
if (inStack.has(nodeId)) {
|
|
389
|
+
return path.concat(nodeId).join(' → ');
|
|
390
|
+
}
|
|
391
|
+
if (visited.has(nodeId)) return null;
|
|
392
|
+
|
|
393
|
+
visited.add(nodeId);
|
|
394
|
+
inStack.add(nodeId);
|
|
395
|
+
|
|
396
|
+
for (const dep of adjList.get(nodeId) || []) {
|
|
397
|
+
const cycle = dfs(dep, [...path, nodeId]);
|
|
398
|
+
if (cycle) return cycle;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
inStack.delete(nodeId);
|
|
402
|
+
return null;
|
|
403
|
+
};
|
|
404
|
+
|
|
405
|
+
for (const step of steps) {
|
|
406
|
+
if (!visited.has(step.id)) {
|
|
407
|
+
const cycle = dfs(step.id, []);
|
|
408
|
+
if (cycle) return cycle;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
return null;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Build parallel execution groups via topological sort.
|
|
417
|
+
* Each group contains steps that can run concurrently.
|
|
418
|
+
*/
|
|
419
|
+
private buildExecutionGroups(steps: WorkflowStep[]): string[][] {
|
|
420
|
+
// Build adjacency and in-degree
|
|
421
|
+
const inDegree = new Map<string, number>();
|
|
422
|
+
const dependents = new Map<string, string[]>();
|
|
423
|
+
|
|
424
|
+
for (const step of steps) {
|
|
425
|
+
if (!inDegree.has(step.id)) inDegree.set(step.id, 0);
|
|
426
|
+
if (!dependents.has(step.id)) dependents.set(step.id, []);
|
|
427
|
+
|
|
428
|
+
const allDeps = this.getAllDependencies(step);
|
|
429
|
+
for (const dep of allDeps) {
|
|
430
|
+
inDegree.set(step.id, (inDegree.get(step.id) || 0) + 1);
|
|
431
|
+
if (!dependents.has(dep)) dependents.set(dep, []);
|
|
432
|
+
dependents.get(dep)!.push(step.id);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// BFS layer by layer
|
|
437
|
+
const groups: string[][] = [];
|
|
438
|
+
let ready = [...inDegree.entries()].filter(([, deg]) => deg === 0).map(([id]) => id);
|
|
439
|
+
|
|
440
|
+
while (ready.length > 0) {
|
|
441
|
+
groups.push([...ready]);
|
|
442
|
+
const nextReady: string[] = [];
|
|
443
|
+
|
|
444
|
+
for (const id of ready) {
|
|
445
|
+
for (const dependent of dependents.get(id) || []) {
|
|
446
|
+
const newDeg = (inDegree.get(dependent) || 1) - 1;
|
|
447
|
+
inDegree.set(dependent, newDeg);
|
|
448
|
+
if (newDeg === 0) {
|
|
449
|
+
nextReady.push(dependent);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
ready = nextReady;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
return groups;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Get all dependencies for a step (explicit + implicit from ref inputs).
|
|
462
|
+
*/
|
|
463
|
+
private getAllDependencies(step: WorkflowStep): string[] {
|
|
464
|
+
const deps = new Set(step.dependsOn || []);
|
|
465
|
+
for (const input of Object.values(step.inputs || {})) {
|
|
466
|
+
if (input.type === 'ref') {
|
|
467
|
+
deps.add(input.stepId);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
return Array.from(deps);
|
|
471
|
+
}
|
|
472
|
+
}
|