@holoscript/framework 6.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (329) hide show
  1. package/ALL-test-results.json +1 -0
  2. package/CHANGELOG.md +8 -0
  3. package/LICENSE +21 -0
  4. package/ROADMAP.md +175 -0
  5. package/dist/AgentManifest-CB4xM-Ma.d.cts +704 -0
  6. package/dist/AgentManifest-CB4xM-Ma.d.ts +704 -0
  7. package/dist/BehaviorTree-BrBFECv5.d.cts +103 -0
  8. package/dist/BehaviorTree-BrBFECv5.d.ts +103 -0
  9. package/dist/InvisibleWallet-BB6tFvRA.d.cts +1732 -0
  10. package/dist/InvisibleWallet-rtRrBOA8.d.ts +1732 -0
  11. package/dist/OrchestratorAgent-BvWgf9uw.d.cts +798 -0
  12. package/dist/OrchestratorAgent-Q_CbVTmO.d.ts +798 -0
  13. package/dist/agents/index.cjs +4790 -0
  14. package/dist/agents/index.d.cts +1788 -0
  15. package/dist/agents/index.d.ts +1788 -0
  16. package/dist/agents/index.js +4695 -0
  17. package/dist/ai/index.cjs +5347 -0
  18. package/dist/ai/index.d.cts +1753 -0
  19. package/dist/ai/index.d.ts +1753 -0
  20. package/dist/ai/index.js +5244 -0
  21. package/dist/behavior.cjs +449 -0
  22. package/dist/behavior.d.cts +130 -0
  23. package/dist/behavior.d.ts +130 -0
  24. package/dist/behavior.js +407 -0
  25. package/dist/economy/index.cjs +3659 -0
  26. package/dist/economy/index.d.cts +747 -0
  27. package/dist/economy/index.d.ts +747 -0
  28. package/dist/economy/index.js +3617 -0
  29. package/dist/implementations-D9T3un9D.d.cts +236 -0
  30. package/dist/implementations-D9T3un9D.d.ts +236 -0
  31. package/dist/index.cjs +24550 -0
  32. package/dist/index.d.cts +1729 -0
  33. package/dist/index.d.ts +1729 -0
  34. package/dist/index.js +24277 -0
  35. package/dist/learning/index.cjs +219 -0
  36. package/dist/learning/index.d.cts +104 -0
  37. package/dist/learning/index.d.ts +104 -0
  38. package/dist/learning/index.js +189 -0
  39. package/dist/negotiation/index.cjs +970 -0
  40. package/dist/negotiation/index.d.cts +610 -0
  41. package/dist/negotiation/index.d.ts +610 -0
  42. package/dist/negotiation/index.js +931 -0
  43. package/dist/skills/index.cjs +1118 -0
  44. package/dist/skills/index.d.cts +289 -0
  45. package/dist/skills/index.d.ts +289 -0
  46. package/dist/skills/index.js +1079 -0
  47. package/dist/swarm/index.cjs +5268 -0
  48. package/dist/swarm/index.d.cts +2433 -0
  49. package/dist/swarm/index.d.ts +2433 -0
  50. package/dist/swarm/index.js +5221 -0
  51. package/dist/training/index.cjs +2745 -0
  52. package/dist/training/index.d.cts +1734 -0
  53. package/dist/training/index.d.ts +1734 -0
  54. package/dist/training/index.js +2687 -0
  55. package/extract-failures.js +10 -0
  56. package/package.json +82 -0
  57. package/src/__tests__/bounty-marketplace.test.ts +374 -0
  58. package/src/__tests__/delegation.test.ts +144 -0
  59. package/src/__tests__/distributed-claimer.test.ts +147 -0
  60. package/src/__tests__/done-log-audit.test.ts +342 -0
  61. package/src/__tests__/framework.test.ts +865 -0
  62. package/src/__tests__/goal-synthesizer.test.ts +236 -0
  63. package/src/__tests__/presence.test.ts +223 -0
  64. package/src/__tests__/protocol-agent.test.ts +254 -0
  65. package/src/__tests__/revenue-splitter.test.ts +114 -0
  66. package/src/__tests__/scenario-driven-todo.test.ts +197 -0
  67. package/src/__tests__/self-improve.test.ts +349 -0
  68. package/src/__tests__/service-lifecycle.test.ts +237 -0
  69. package/src/__tests__/skill-router.test.ts +121 -0
  70. package/src/agents/AgentManifest.ts +493 -0
  71. package/src/agents/AgentRegistry.ts +475 -0
  72. package/src/agents/AgentTypes.ts +585 -0
  73. package/src/agents/AgentWalletRegistry.ts +83 -0
  74. package/src/agents/AuthenticatedCRDT.ts +388 -0
  75. package/src/agents/CapabilityMatcher.ts +453 -0
  76. package/src/agents/CrossRealityHandoff.ts +305 -0
  77. package/src/agents/CulturalMemory.ts +454 -0
  78. package/src/agents/FederatedRegistryAdapter.ts +429 -0
  79. package/src/agents/NormEngine.ts +450 -0
  80. package/src/agents/OrchestratorAgent.ts +414 -0
  81. package/src/agents/SkillWorkflowEngine.ts +472 -0
  82. package/src/agents/TaskDelegationService.ts +551 -0
  83. package/src/agents/__tests__/AgentManifest.prod.test.ts +134 -0
  84. package/src/agents/__tests__/AgentManifest.test.ts +182 -0
  85. package/src/agents/__tests__/AgentModule.test.ts +864 -0
  86. package/src/agents/__tests__/AgentRegistry.prod.test.ts +125 -0
  87. package/src/agents/__tests__/AgentRegistry.test.ts +148 -0
  88. package/src/agents/__tests__/AgentTypes.test.ts +534 -0
  89. package/src/agents/__tests__/AgentWalletRegistry.test.ts +152 -0
  90. package/src/agents/__tests__/AuthenticatedCRDT.test.ts +558 -0
  91. package/src/agents/__tests__/CapabilityMatcher.prod.test.ts +117 -0
  92. package/src/agents/__tests__/CapabilityMatcher.test.ts +178 -0
  93. package/src/agents/__tests__/CrossRealityHandoff.test.ts +402 -0
  94. package/src/agents/__tests__/CulturalMemory.test.ts +200 -0
  95. package/src/agents/__tests__/FederatedRegistryAdapter.test.ts +409 -0
  96. package/src/agents/__tests__/NormEngine.test.ts +276 -0
  97. package/src/agents/__tests__/OrchestratorAgent.test.ts +182 -0
  98. package/src/agents/__tests__/SkillWorkflowEngine.test.ts +357 -0
  99. package/src/agents/__tests__/TaskDelegationService.test.ts +446 -0
  100. package/src/agents/index.ts +107 -0
  101. package/src/agents/spatial-comms/Layer1RealTime.ts +621 -0
  102. package/src/agents/spatial-comms/Layer2A2A.ts +661 -0
  103. package/src/agents/spatial-comms/Layer3MCP.ts +651 -0
  104. package/src/agents/spatial-comms/ProtocolTypes.ts +543 -0
  105. package/src/agents/spatial-comms/SpatialCommClient.ts +483 -0
  106. package/src/agents/spatial-comms/__tests__/performance-benchmark.test.ts +465 -0
  107. package/src/agents/spatial-comms/examples/multi-agent-world-creation.ts +409 -0
  108. package/src/agents/spatial-comms/index.ts +66 -0
  109. package/src/ai/AIAdapter.ts +313 -0
  110. package/src/ai/AICopilot.ts +331 -0
  111. package/src/ai/AIOutputValidator.ts +203 -0
  112. package/src/ai/BTNodes.ts +239 -0
  113. package/src/ai/BehaviorSelector.ts +135 -0
  114. package/src/ai/BehaviorTree.ts +153 -0
  115. package/src/ai/Blackboard.ts +165 -0
  116. package/src/ai/GenerationAnalytics.ts +461 -0
  117. package/src/ai/GenerationCache.ts +265 -0
  118. package/src/ai/GoalPlanner.ts +165 -0
  119. package/src/ai/HoloScriptGenerator.ts +580 -0
  120. package/src/ai/InfluenceMap.ts +180 -0
  121. package/src/ai/NavMesh.ts +168 -0
  122. package/src/ai/PerceptionSystem.ts +178 -0
  123. package/src/ai/PromptTemplates.ts +453 -0
  124. package/src/ai/SemanticSearchService.ts +80 -0
  125. package/src/ai/StateMachine.ts +196 -0
  126. package/src/ai/SteeringBehavior.ts +150 -0
  127. package/src/ai/SteeringBehaviors.ts +244 -0
  128. package/src/ai/TrainingDataGenerator.ts +1082 -0
  129. package/src/ai/UtilityAI.ts +145 -0
  130. package/src/ai/__tests__/AIAdapter.prod.test.ts +259 -0
  131. package/src/ai/__tests__/AIAdapter.test.ts +109 -0
  132. package/src/ai/__tests__/AICopilot.prod.test.ts +341 -0
  133. package/src/ai/__tests__/AICopilot.test.ts +178 -0
  134. package/src/ai/__tests__/AIOutputValidator.prod.test.ts +226 -0
  135. package/src/ai/__tests__/AIOutputValidator.test.ts +138 -0
  136. package/src/ai/__tests__/BTNodes.prod.test.ts +391 -0
  137. package/src/ai/__tests__/BTNodes.test.ts +263 -0
  138. package/src/ai/__tests__/BehaviorSelector.prod.test.ts +129 -0
  139. package/src/ai/__tests__/BehaviorSelector.test.ts +132 -0
  140. package/src/ai/__tests__/BehaviorTree.prod.test.ts +266 -0
  141. package/src/ai/__tests__/BehaviorTree.test.ts +216 -0
  142. package/src/ai/__tests__/Blackboard.prod.test.ts +339 -0
  143. package/src/ai/__tests__/Blackboard.test.ts +183 -0
  144. package/src/ai/__tests__/GenerationAnalytics.prod.test.ts +141 -0
  145. package/src/ai/__tests__/GenerationAnalytics.test.ts +165 -0
  146. package/src/ai/__tests__/GenerationCache.prod.test.ts +144 -0
  147. package/src/ai/__tests__/GenerationCache.test.ts +171 -0
  148. package/src/ai/__tests__/GoalPlanner.prod.test.ts +189 -0
  149. package/src/ai/__tests__/GoalPlanner.test.ts +137 -0
  150. package/src/ai/__tests__/GoalPlannerDepth.prod.test.ts +217 -0
  151. package/src/ai/__tests__/HoloScriptGenerator.test.ts +125 -0
  152. package/src/ai/__tests__/InfluenceMap.prod.test.ts +146 -0
  153. package/src/ai/__tests__/InfluenceMap.test.ts +149 -0
  154. package/src/ai/__tests__/NavMesh.prod.test.ts +141 -0
  155. package/src/ai/__tests__/NavMesh.test.ts +159 -0
  156. package/src/ai/__tests__/PerceptionSystem.prod.test.ts +135 -0
  157. package/src/ai/__tests__/PerceptionSystem.test.ts +250 -0
  158. package/src/ai/__tests__/PromptTemplates.prod.test.ts +313 -0
  159. package/src/ai/__tests__/PromptTemplates.test.ts +146 -0
  160. package/src/ai/__tests__/SemanticSearch.test.ts +37 -0
  161. package/src/ai/__tests__/StateMachine.prod.test.ts +162 -0
  162. package/src/ai/__tests__/StateMachine.test.ts +163 -0
  163. package/src/ai/__tests__/SteeringBehavior.prod.test.ts +251 -0
  164. package/src/ai/__tests__/SteeringBehavior.test.ts +135 -0
  165. package/src/ai/__tests__/SteeringBehaviors.prod.test.ts +133 -0
  166. package/src/ai/__tests__/SteeringBehaviors.test.ts +151 -0
  167. package/src/ai/__tests__/TrainingDataGenerator.prod.test.ts +286 -0
  168. package/src/ai/__tests__/TrainingDataGenerator.test.ts +286 -0
  169. package/src/ai/__tests__/UtilityAI.prod.test.ts +207 -0
  170. package/src/ai/__tests__/UtilityAI.test.ts +155 -0
  171. package/src/ai/__tests__/adapters.prod.test.ts +263 -0
  172. package/src/ai/__tests__/adapters.test.ts +320 -0
  173. package/src/ai/adapters.ts +1585 -0
  174. package/src/ai/index.ts +130 -0
  175. package/src/behavior/BehaviorPresets.ts +140 -0
  176. package/src/behavior/BehaviorTree.ts +236 -0
  177. package/src/behavior/StateMachine.ts +176 -0
  178. package/src/behavior/StateTrait.ts +67 -0
  179. package/src/behavior/index.ts +8 -0
  180. package/src/behavior.ts +8 -0
  181. package/src/board/audit.ts +284 -0
  182. package/src/board/board-ops.ts +336 -0
  183. package/src/board/board-types.ts +302 -0
  184. package/src/board/index.ts +69 -0
  185. package/src/define-agent.ts +46 -0
  186. package/src/define-team.ts +33 -0
  187. package/src/delegation.ts +265 -0
  188. package/src/distributed-claimer.ts +228 -0
  189. package/src/economy/AgentBudgetEnforcer.ts +464 -0
  190. package/src/economy/BountyManager.ts +185 -0
  191. package/src/economy/CreatorRevenueAggregator.ts +460 -0
  192. package/src/economy/InvisibleWallet.ts +82 -0
  193. package/src/economy/KnowledgeMarketplace.ts +193 -0
  194. package/src/economy/PaymentWebhookService.ts +512 -0
  195. package/src/economy/RevenueSplitter.ts +156 -0
  196. package/src/economy/SubscriptionManager.ts +546 -0
  197. package/src/economy/UnifiedBudgetOptimizer.ts +635 -0
  198. package/src/economy/UsageMeter.ts +440 -0
  199. package/src/economy/_core-stubs.ts +219 -0
  200. package/src/economy/index.ts +100 -0
  201. package/src/economy/x402-facilitator.ts +1978 -0
  202. package/src/index.ts +348 -0
  203. package/src/knowledge/__tests__/knowledge-consolidator.test.ts +444 -0
  204. package/src/knowledge/__tests__/knowledge-store-vector.test.ts +291 -0
  205. package/src/knowledge/brain.ts +167 -0
  206. package/src/knowledge/consolidation.ts +581 -0
  207. package/src/knowledge/knowledge-consolidator.ts +510 -0
  208. package/src/knowledge/knowledge-store.ts +616 -0
  209. package/src/learning/MemoryConsolidator.ts +102 -0
  210. package/src/learning/MemoryScorer.ts +69 -0
  211. package/src/learning/ProceduralCompiler.ts +45 -0
  212. package/src/learning/SemanticClusterer.ts +66 -0
  213. package/src/learning/index.ts +8 -0
  214. package/src/llm/llm-adapter.ts +159 -0
  215. package/src/mesh/index.ts +309 -0
  216. package/src/negotiation/NegotiationProtocol.ts +694 -0
  217. package/src/negotiation/NegotiationTypes.ts +473 -0
  218. package/src/negotiation/VotingMechanisms.ts +691 -0
  219. package/src/negotiation/index.ts +49 -0
  220. package/src/protocol/goal-synthesizer.ts +317 -0
  221. package/src/protocol/implementations.ts +474 -0
  222. package/src/protocol/micro-phase-decomposer.ts +299 -0
  223. package/src/protocol/micro-step-decomposer.test.ts +306 -0
  224. package/src/protocol-agent.test.ts +353 -0
  225. package/src/protocol-agent.ts +670 -0
  226. package/src/self-improve/absorb-scanner.ts +252 -0
  227. package/src/self-improve/evolution-engine.ts +149 -0
  228. package/src/self-improve/framework-absorber.ts +214 -0
  229. package/src/self-improve/index.ts +50 -0
  230. package/src/self-improve/prompt-optimizer.ts +212 -0
  231. package/src/self-improve/test-generator.ts +175 -0
  232. package/src/skill-router.ts +186 -0
  233. package/src/skills/index.ts +5 -0
  234. package/src/skills/skill-md-bridge.ts +1699 -0
  235. package/src/swarm/ACOEngine.ts +261 -0
  236. package/src/swarm/CollectiveIntelligence.ts +383 -0
  237. package/src/swarm/ContributionSynthesizer.ts +481 -0
  238. package/src/swarm/LeaderElection.ts +393 -0
  239. package/src/swarm/PSOEngine.ts +206 -0
  240. package/src/swarm/QuorumPolicy.ts +173 -0
  241. package/src/swarm/SwarmCoordinator.ts +335 -0
  242. package/src/swarm/SwarmManager.ts +442 -0
  243. package/src/swarm/SwarmMembership.ts +456 -0
  244. package/src/swarm/VotingRound.ts +255 -0
  245. package/src/swarm/__tests__/ACOEngine.prod.test.ts +164 -0
  246. package/src/swarm/__tests__/ACOEngine.test.ts +117 -0
  247. package/src/swarm/__tests__/CollectiveIntelligence.prod.test.ts +296 -0
  248. package/src/swarm/__tests__/CollectiveIntelligence.test.ts +457 -0
  249. package/src/swarm/__tests__/ContributionSynthesizer.prod.test.ts +269 -0
  250. package/src/swarm/__tests__/ContributionSynthesizer.test.ts +254 -0
  251. package/src/swarm/__tests__/LeaderElection.prod.test.ts +196 -0
  252. package/src/swarm/__tests__/LeaderElection.test.ts +151 -0
  253. package/src/swarm/__tests__/PSOEngine.prod.test.ts +162 -0
  254. package/src/swarm/__tests__/PSOEngine.test.ts +106 -0
  255. package/src/swarm/__tests__/QuorumPolicy.prod.test.ts +216 -0
  256. package/src/swarm/__tests__/QuorumPolicy.test.ts +177 -0
  257. package/src/swarm/__tests__/SwarmCoordinator.prod.test.ts +186 -0
  258. package/src/swarm/__tests__/SwarmCoordinator.test.ts +167 -0
  259. package/src/swarm/__tests__/SwarmManager.prod.test.ts +308 -0
  260. package/src/swarm/__tests__/SwarmManager.test.ts +373 -0
  261. package/src/swarm/__tests__/SwarmMembership.prod.test.ts +273 -0
  262. package/src/swarm/__tests__/SwarmMembership.test.ts +264 -0
  263. package/src/swarm/__tests__/VotingRound.prod.test.ts +233 -0
  264. package/src/swarm/__tests__/VotingRound.test.ts +174 -0
  265. package/src/swarm/analytics/SwarmInspector.ts +476 -0
  266. package/src/swarm/analytics/SwarmMetrics.ts +449 -0
  267. package/src/swarm/analytics/__tests__/SwarmInspector.prod.test.ts +366 -0
  268. package/src/swarm/analytics/__tests__/SwarmInspector.test.ts +454 -0
  269. package/src/swarm/analytics/__tests__/SwarmMetrics.prod.test.ts +254 -0
  270. package/src/swarm/analytics/__tests__/SwarmMetrics.test.ts +370 -0
  271. package/src/swarm/analytics/index.ts +7 -0
  272. package/src/swarm/index.ts +69 -0
  273. package/src/swarm/messaging/BroadcastChannel.ts +509 -0
  274. package/src/swarm/messaging/GossipProtocol.ts +565 -0
  275. package/src/swarm/messaging/SwarmEventBus.ts +443 -0
  276. package/src/swarm/messaging/__tests__/BroadcastChannel.prod.test.ts +331 -0
  277. package/src/swarm/messaging/__tests__/BroadcastChannel.test.ts +333 -0
  278. package/src/swarm/messaging/__tests__/GossipProtocol.prod.test.ts +356 -0
  279. package/src/swarm/messaging/__tests__/GossipProtocol.test.ts +437 -0
  280. package/src/swarm/messaging/__tests__/SwarmEventBus.prod.test.ts +191 -0
  281. package/src/swarm/messaging/__tests__/SwarmEventBus.test.ts +247 -0
  282. package/src/swarm/messaging/index.ts +8 -0
  283. package/src/swarm/spatial/FlockingBehavior.ts +462 -0
  284. package/src/swarm/spatial/FormationController.ts +500 -0
  285. package/src/swarm/spatial/Vector3.ts +170 -0
  286. package/src/swarm/spatial/ZoneClaiming.ts +509 -0
  287. package/src/swarm/spatial/__tests__/FlockingBehavior.prod.test.ts +239 -0
  288. package/src/swarm/spatial/__tests__/FlockingBehavior.test.ts +298 -0
  289. package/src/swarm/spatial/__tests__/FormationController.prod.test.ts +240 -0
  290. package/src/swarm/spatial/__tests__/FormationController.test.ts +297 -0
  291. package/src/swarm/spatial/__tests__/Vector3.prod.test.ts +283 -0
  292. package/src/swarm/spatial/__tests__/Vector3.test.ts +224 -0
  293. package/src/swarm/spatial/__tests__/ZoneClaiming.prod.test.ts +246 -0
  294. package/src/swarm/spatial/__tests__/ZoneClaiming.test.ts +374 -0
  295. package/src/swarm/spatial/index.ts +28 -0
  296. package/src/team.ts +1245 -0
  297. package/src/training/LRScheduler.ts +377 -0
  298. package/src/training/QualityScoringPipeline.ts +139 -0
  299. package/src/training/SoftDedup.ts +461 -0
  300. package/src/training/SparsityMonitor.ts +685 -0
  301. package/src/training/SparsityMonitorTypes.ts +209 -0
  302. package/src/training/SpatialTrainingDataGenerator.ts +1526 -0
  303. package/src/training/SpatialTrainingDataTypes.ts +216 -0
  304. package/src/training/TrainingPipelineConfig.ts +215 -0
  305. package/src/training/constants.ts +94 -0
  306. package/src/training/index.ts +138 -0
  307. package/src/training/schema.ts +147 -0
  308. package/src/training/scripts/generate-novel-use-cases-dataset.ts +272 -0
  309. package/src/training/scripts/generate-spatial-dataset.ts +521 -0
  310. package/src/training/training/data/novel-use-cases.jsonl +153 -0
  311. package/src/training/training/data/spatial-reasoning-10k.jsonl +9354 -0
  312. package/src/training/trainingmonkey/TrainingMonkeyIntegration.ts +477 -0
  313. package/src/training/trainingmonkey/TrainingMonkeyTypes.ts +230 -0
  314. package/src/training/trainingmonkey/index.ts +26 -0
  315. package/src/training/trait-mappings.ts +157 -0
  316. package/src/types/core-stubs.d.ts +113 -0
  317. package/src/types.ts +304 -0
  318. package/test-output.txt +0 -0
  319. package/test-result.json +1 -0
  320. package/tsc-errors.txt +4 -0
  321. package/tsc_output.txt +0 -0
  322. package/tsconfig.json +14 -0
  323. package/tsup-learning-esm.config.ts +12 -0
  324. package/tsup.config.ts +21 -0
  325. package/typescript-errors-2.txt +0 -0
  326. package/typescript-errors.txt +22 -0
  327. package/vitest-log-utf8.txt +268 -0
  328. package/vitest-log.txt +0 -0
  329. package/vitest.config.ts +8 -0
@@ -0,0 +1,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
+ }