@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,1585 @@
1
+ /**
2
+ * @holoscript/core - Built-in AI Adapters
3
+ *
4
+ * Ready-to-use adapters for popular AI providers.
5
+ * Users just need to provide their API key.
6
+ */
7
+
8
+ import type {
9
+ AIAdapter,
10
+ GenerateResult,
11
+ ExplainResult,
12
+ OptimizeResult,
13
+ FixResult,
14
+ GenerateOptions,
15
+ } from './AIAdapter';
16
+ /** Shape of API error responses from AI providers. */
17
+ interface APIErrorResponse {
18
+ error?: { message?: string };
19
+ }
20
+
21
+ export type {
22
+ AIAdapter,
23
+ GenerateResult,
24
+ ExplainResult,
25
+ OptimizeResult,
26
+ FixResult,
27
+ GenerateOptions,
28
+ };
29
+
30
+ // ============================================================================
31
+ // System Prompt for HoloScript Generation
32
+ // ============================================================================
33
+
34
+ const HOLOSCRIPT_SYSTEM_PROMPT = `You are a HoloScript expert. HoloScript is a visual flow language for VR/AR world creation.
35
+
36
+ Generate valid HoloScript code following this syntax:
37
+
38
+ COMPOSITIONS:
39
+ composition "Scene Name" {
40
+ environment { skybox: "sky_day", ambient: 0.5 }
41
+
42
+ template "ObjectType" {
43
+ state { property: value }
44
+ action doSomething() { }
45
+ }
46
+
47
+ spatial_group "GroupName" {
48
+ object "Object1" { position: [x, y, z] }
49
+ object "Object2" using "ObjectType" { position: [x, y, z] }
50
+ }
51
+
52
+ logic {
53
+ on_event { action() }
54
+ every(1000) { periodic_action() }
55
+ }
56
+ }
57
+
58
+ SHAPES: cube, sphere, cylinder, cone, plane, torus, capsule, pyramid, prism, hexagon, octahedron, icosahedron, ring, tube, spiral, stairs, arch, dome, wedge, ramp
59
+
60
+ TRAITS: @grabbable, @throwable, @hoverable, @interactive, @collidable, @animatable, @networked
61
+
62
+ RULES:
63
+ 1. Use descriptive object names
64
+ 2. Position objects logically in 3D space (y is up)
65
+ 3. Include templates for reusable objects
66
+ 4. Add logic for interactivity
67
+ 5. Output ONLY valid HoloScript code, no explanations unless asked`;
68
+
69
+ // ============================================================================
70
+ // OpenAI Adapter
71
+ // ============================================================================
72
+
73
+ export interface OpenAIAdapterConfig {
74
+ apiKey: string;
75
+ model?: string;
76
+ baseUrl?: string;
77
+ organization?: string;
78
+ }
79
+
80
+ export class OpenAIAdapter implements AIAdapter {
81
+ readonly id = 'openai';
82
+ readonly name = 'OpenAI';
83
+
84
+ private config: OpenAIAdapterConfig;
85
+ private model: string;
86
+
87
+ constructor(config: OpenAIAdapterConfig) {
88
+ this.config = config;
89
+ this.model = config.model || 'gpt-4o-mini';
90
+ }
91
+
92
+ isReady(): boolean {
93
+ return !!this.config.apiKey;
94
+ }
95
+
96
+ async generateHoloScript(prompt: string, options?: GenerateOptions): Promise<GenerateResult> {
97
+ const systemPrompt = this.buildSystemPrompt(options);
98
+ const response = await this.chat('Create a HoloScript scene: ' + prompt, undefined, [
99
+ { role: 'assistant', content: systemPrompt },
100
+ ]);
101
+
102
+ return {
103
+ holoScript: this.extractCode(response),
104
+ confidence: 0.85,
105
+ };
106
+ }
107
+
108
+ async explainHoloScript(holoScript: string): Promise<ExplainResult> {
109
+ const response = await this.callAPI([
110
+ {
111
+ role: 'system',
112
+ content: 'You are a HoloScript expert. Explain the following code clearly.',
113
+ },
114
+ { role: 'user', content: 'Explain this HoloScript:\n\n' + holoScript },
115
+ ]);
116
+
117
+ return { explanation: response };
118
+ }
119
+
120
+ async optimizeHoloScript(
121
+ holoScript: string,
122
+ target: 'mobile' | 'desktop' | 'vr' | 'ar'
123
+ ): Promise<OptimizeResult> {
124
+ const response = await this.callAPI([
125
+ {
126
+ role: 'system',
127
+ content:
128
+ 'You are a HoloScript optimizer. Optimize for ' +
129
+ target +
130
+ ' platform. Return only the optimized code.',
131
+ },
132
+ { role: 'user', content: holoScript },
133
+ ]);
134
+
135
+ return {
136
+ holoScript: this.extractCode(response),
137
+ improvements: ['Optimized for ' + target],
138
+ };
139
+ }
140
+
141
+ async fixHoloScript(holoScript: string, errors: string[]): Promise<FixResult> {
142
+ const response = await this.callAPI([
143
+ {
144
+ role: 'system',
145
+ content: 'You are a HoloScript debugger. Fix the errors and return corrected code.',
146
+ },
147
+ {
148
+ role: 'user',
149
+ content: 'Fix these errors:\n' + errors.join('\n') + '\n\nCode:\n' + holoScript,
150
+ },
151
+ ]);
152
+
153
+ return {
154
+ holoScript: this.extractCode(response),
155
+ fixes: errors.map((e) => ({ line: 0, issue: e, fix: 'auto-fixed' })),
156
+ };
157
+ }
158
+
159
+ async chat(
160
+ message: string,
161
+ holoScript?: string,
162
+ history?: Array<{ role: 'user' | 'assistant'; content: string }>
163
+ ): Promise<string> {
164
+ const messages: Array<{ role: string; content: string }> = [
165
+ { role: 'system', content: HOLOSCRIPT_SYSTEM_PROMPT },
166
+ ];
167
+
168
+ if (history) {
169
+ messages.push(...history);
170
+ }
171
+
172
+ if (holoScript) {
173
+ messages.push({
174
+ role: 'user',
175
+ content: 'Context (current code):\n' + holoScript + '\n\nQuestion: ' + message,
176
+ });
177
+ } else {
178
+ messages.push({ role: 'user', content: message });
179
+ }
180
+
181
+ return this.callAPI(messages, history);
182
+ }
183
+
184
+ private buildSystemPrompt(options?: GenerateOptions): string {
185
+ let prompt = HOLOSCRIPT_SYSTEM_PROMPT;
186
+ if (options?.style) prompt += '\nStyle: ' + options.style;
187
+ if (options?.complexity) prompt += '\nComplexity: ' + options.complexity;
188
+ if (options?.targetPlatform) prompt += '\nOptimize for: ' + options.targetPlatform;
189
+ return prompt;
190
+ }
191
+
192
+ private extractCode(response: string): string {
193
+ // Extract code from markdown code blocks
194
+ const match = response.match(/```(?:holoscript|holo)?\n([\s\S]*?)```/);
195
+ return match ? match[1].trim() : response.trim();
196
+ }
197
+
198
+ private async callAPI(
199
+ messages: Array<{ role: string; content: string }>,
200
+ _history?: Array<{ role: 'user' | 'assistant'; content: string }>
201
+ ): Promise<string> {
202
+ const baseUrl = this.config.baseUrl || 'https://api.openai.com/v1';
203
+
204
+ const headers: Record<string, string> = {
205
+ 'Content-Type': 'application/json',
206
+ Authorization: 'Bearer ' + this.config.apiKey,
207
+ };
208
+
209
+ if (this.config.organization) {
210
+ headers['OpenAI-Organization'] = this.config.organization;
211
+ }
212
+
213
+ const response = await fetch(baseUrl + '/chat/completions', {
214
+ method: 'POST',
215
+ headers,
216
+ body: JSON.stringify({
217
+ model: this.model,
218
+ messages,
219
+ temperature: 0.7,
220
+ }),
221
+ });
222
+
223
+ if (response.status === 429) {
224
+ throw new Error('OpenAI rate limited (429) - please retry after backoff');
225
+ }
226
+ if (response.status === 401 || response.status === 403) {
227
+ throw new Error('OpenAI auth failed - check API key and permissions');
228
+ }
229
+ if (!response.ok) {
230
+ throw new Error('OpenAI API error: ' + response.statusText);
231
+ }
232
+
233
+ const data = await response.json();
234
+ return data.choices[0].message.content;
235
+ }
236
+
237
+ async getEmbeddings(text: string | string[]): Promise<number[][]> {
238
+ const baseUrl = this.config.baseUrl || 'https://api.openai.com/v1';
239
+ const inputs = Array.isArray(text) ? text : [text];
240
+
241
+ const response = await fetch(baseUrl + '/embeddings', {
242
+ method: 'POST',
243
+ headers: {
244
+ 'Content-Type': 'application/json',
245
+ Authorization: 'Bearer ' + this.config.apiKey,
246
+ },
247
+ body: JSON.stringify({
248
+ model: 'text-embedding-3-small',
249
+ input: inputs,
250
+ }),
251
+ });
252
+
253
+ if (!response.ok) {
254
+ throw new Error('OpenAI Embeddings API error: ' + response.statusText);
255
+ }
256
+
257
+ const data = await response.json();
258
+ return data.data.map((item: { embedding: number[] }) => item.embedding);
259
+ }
260
+ }
261
+
262
+ // ============================================================================
263
+ // Anthropic (Claude) Adapter
264
+ // ============================================================================
265
+
266
+ export interface AnthropicAdapterConfig {
267
+ apiKey: string;
268
+ model?: string;
269
+ }
270
+
271
+ export class AnthropicAdapter implements AIAdapter {
272
+ readonly id = 'anthropic';
273
+ readonly name = 'Anthropic Claude';
274
+
275
+ private config: AnthropicAdapterConfig;
276
+ private model: string;
277
+
278
+ constructor(config: AnthropicAdapterConfig) {
279
+ this.config = config;
280
+ this.model = config.model || 'claude-3-5-sonnet-20241022';
281
+ }
282
+
283
+ isReady(): boolean {
284
+ return !!this.config.apiKey;
285
+ }
286
+
287
+ async generateHoloScript(prompt: string, options?: GenerateOptions): Promise<GenerateResult> {
288
+ const messages: Array<{ role: 'user' | 'assistant'; content: string }> = [
289
+ { role: 'user', content: 'Create a HoloScript scene: ' + prompt },
290
+ ];
291
+ const response = await this.callAPI(messages, options);
292
+
293
+ return {
294
+ holoScript: this.extractCode(response),
295
+ confidence: 0.85,
296
+ };
297
+ }
298
+
299
+ async explainHoloScript(holoScript: string): Promise<ExplainResult> {
300
+ const messages: Array<{ role: 'user' | 'assistant'; content: string }> = [
301
+ { role: 'user', content: 'Explain this HoloScript code clearly:\n\n' + holoScript },
302
+ ];
303
+ const response = await this.callAPI(messages);
304
+ return { explanation: response };
305
+ }
306
+
307
+ async optimizeHoloScript(
308
+ holoScript: string,
309
+ target: 'mobile' | 'desktop' | 'vr' | 'ar'
310
+ ): Promise<OptimizeResult> {
311
+ const messages: Array<{ role: 'user' | 'assistant'; content: string }> = [
312
+ {
313
+ role: 'user',
314
+ content:
315
+ 'Optimize this HoloScript for ' +
316
+ target +
317
+ '. Return only the optimized code:\n\n' +
318
+ holoScript,
319
+ },
320
+ ];
321
+ const response = await this.callAPI(messages);
322
+ return {
323
+ holoScript: this.extractCode(response),
324
+ improvements: ['Optimized for ' + target],
325
+ };
326
+ }
327
+
328
+ async fixHoloScript(holoScript: string, errors: string[]): Promise<FixResult> {
329
+ const messages: Array<{ role: 'user' | 'assistant'; content: string }> = [
330
+ {
331
+ role: 'user',
332
+ content:
333
+ 'Fix these errors in the HoloScript:\nErrors: ' +
334
+ errors.join(', ') +
335
+ '\n\nCode:\n' +
336
+ holoScript,
337
+ },
338
+ ];
339
+ const response = await this.callAPI(messages);
340
+ return {
341
+ holoScript: this.extractCode(response),
342
+ fixes: errors.map((e) => ({ line: 0, issue: e, fix: 'auto-fixed' })),
343
+ };
344
+ }
345
+
346
+ async chat(
347
+ message: string,
348
+ holoScript?: string,
349
+ history?: Array<{ role: 'user' | 'assistant'; content: string }>
350
+ ): Promise<string> {
351
+ const messages: Array<{ role: 'user' | 'assistant'; content: string }> = history
352
+ ? [...history]
353
+ : [];
354
+
355
+ if (holoScript) {
356
+ messages.push({
357
+ role: 'user',
358
+ content: 'Context:\n' + holoScript + '\n\nQuestion: ' + message,
359
+ });
360
+ } else {
361
+ messages.push({ role: 'user', content: message });
362
+ }
363
+
364
+ return this.callAPI(messages);
365
+ }
366
+
367
+ private extractCode(response: string): string {
368
+ const match = response.match(/```(?:holoscript|holo)?\n([\s\S]*?)```/);
369
+ return match ? match[1].trim() : response.trim();
370
+ }
371
+
372
+ private async callAPI(
373
+ messages: Array<{ role: 'user' | 'assistant'; content: string }>,
374
+ _options?: GenerateOptions
375
+ ): Promise<string> {
376
+ const response = await fetch('https://api.anthropic.com/v1/messages', {
377
+ method: 'POST',
378
+ headers: {
379
+ 'Content-Type': 'application/json',
380
+ 'x-api-key': this.config.apiKey,
381
+ 'anthropic-version': '2023-06-01',
382
+ },
383
+ body: JSON.stringify({
384
+ model: this.model,
385
+ max_tokens: 4096,
386
+ system: HOLOSCRIPT_SYSTEM_PROMPT,
387
+ messages,
388
+ }),
389
+ });
390
+
391
+ if (response.status === 429) {
392
+ throw new Error('Anthropic rate limited (429) - please retry after backoff');
393
+ }
394
+ if (response.status === 401 || response.status === 403) {
395
+ throw new Error('Anthropic auth failed - check API key');
396
+ }
397
+ if (!response.ok) {
398
+ throw new Error('Anthropic API error: ' + response.statusText);
399
+ }
400
+
401
+ const data = await response.json();
402
+ return data.content[0].text;
403
+ }
404
+
405
+ async getEmbeddings(text: string | string[]): Promise<number[][]> {
406
+ // Anthropic doesn't have native embeddings API yet, return mock for compatibility
407
+ const inputs = Array.isArray(text) ? text : [text];
408
+ return inputs.map((_) =>
409
+ Array(1024)
410
+ .fill(0.5)
411
+ .map(() => Math.random())
412
+ );
413
+ }
414
+ }
415
+
416
+ // ============================================================================
417
+ // Ollama (Local) Adapter
418
+ // ============================================================================
419
+
420
+ export interface OllamaAdapterConfig {
421
+ baseUrl?: string;
422
+ model?: string;
423
+ }
424
+
425
+ export class OllamaAdapter implements AIAdapter {
426
+ readonly id = 'ollama';
427
+ readonly name = 'Ollama (Local)';
428
+
429
+ private baseUrl: string;
430
+ private model: string;
431
+
432
+ constructor(config: OllamaAdapterConfig = {}) {
433
+ this.baseUrl = config.baseUrl || 'http://localhost:11434';
434
+ this.model = config.model || 'brittney-qwen-v23:latest';
435
+ }
436
+
437
+ async isReady(): Promise<boolean> {
438
+ try {
439
+ const response = await fetch(this.baseUrl + '/api/tags');
440
+ return response.ok;
441
+ } catch {
442
+ return false;
443
+ }
444
+ }
445
+
446
+ async generateHoloScript(prompt: string, _options?: GenerateOptions): Promise<GenerateResult> {
447
+ const response = await this.callAPI(
448
+ HOLOSCRIPT_SYSTEM_PROMPT,
449
+ 'Create a HoloScript scene: ' + prompt
450
+ );
451
+
452
+ return {
453
+ holoScript: this.extractCode(response),
454
+ confidence: 0.75,
455
+ };
456
+ }
457
+
458
+ async explainHoloScript(holoScript: string): Promise<ExplainResult> {
459
+ const response = await this.callAPI(
460
+ 'You are a HoloScript expert. Explain code clearly.',
461
+ 'Explain this HoloScript:\n\n' + holoScript
462
+ );
463
+ return { explanation: response };
464
+ }
465
+
466
+ async optimizeHoloScript(
467
+ holoScript: string,
468
+ target: 'mobile' | 'desktop' | 'vr' | 'ar'
469
+ ): Promise<OptimizeResult> {
470
+ const response = await this.callAPI(
471
+ 'You are a HoloScript optimizer. Optimize for ' + target + '.',
472
+ holoScript
473
+ );
474
+ return {
475
+ holoScript: this.extractCode(response),
476
+ improvements: ['Optimized for ' + target],
477
+ };
478
+ }
479
+
480
+ async fixHoloScript(holoScript: string, errors: string[]): Promise<FixResult> {
481
+ const response = await this.callAPI(
482
+ 'You are a HoloScript debugger. Fix errors and return corrected code.',
483
+ 'Errors: ' + errors.join(', ') + '\n\nCode:\n' + holoScript
484
+ );
485
+ return {
486
+ holoScript: this.extractCode(response),
487
+ fixes: errors.map((e) => ({ line: 0, issue: e, fix: 'auto-fixed' })),
488
+ };
489
+ }
490
+
491
+ async chat(
492
+ message: string,
493
+ holoScript?: string,
494
+ history?: Array<{ role: 'user' | 'assistant'; content: string }>
495
+ ): Promise<string> {
496
+ // Ollama doesn't support multi-turn natively, but log history for context
497
+ if (history && history.length > 0) {
498
+ const contextMsg = history.map((h) => h.role + ': ' + h.content.slice(0, 100)).join('\n');
499
+ const fullMessage = holoScript
500
+ ? 'History:\n' + contextMsg + '\n\nContext:\n' + holoScript + '\n\nQuestion: ' + message
501
+ : 'History:\n' + contextMsg + '\n\nQuestion: ' + message;
502
+ return this.callAPI(HOLOSCRIPT_SYSTEM_PROMPT, fullMessage);
503
+ }
504
+ const fullMessage = holoScript
505
+ ? 'Context:\n' + holoScript + '\n\nQuestion: ' + message
506
+ : message;
507
+ return this.callAPI(HOLOSCRIPT_SYSTEM_PROMPT, fullMessage);
508
+ }
509
+
510
+ private async callAPIWithErrorHandling(apiPath: string, body: RequestInit): Promise<Response> {
511
+ const response = await fetch(this.baseUrl + apiPath, body);
512
+
513
+ if (response.status === 429) {
514
+ throw new Error('Ollama rate limited (429) - model may be busy');
515
+ }
516
+ if (response.status === 503) {
517
+ throw new Error('Ollama service unavailable - ensure service is running');
518
+ }
519
+ if (!response.ok) {
520
+ throw new Error('Ollama API error: ' + response.statusText);
521
+ }
522
+
523
+ return response;
524
+ }
525
+
526
+ private extractCode(response: string): string {
527
+ const match = response.match(/```(?:holoscript|holo)?\n([\s\S]*?)```/);
528
+ return match ? match[1].trim() : response.trim();
529
+ }
530
+
531
+ private async callAPI(system: string, prompt: string): Promise<string> {
532
+ const response = await this.callAPIWithErrorHandling('/api/generate', {
533
+ method: 'POST',
534
+ headers: { 'Content-Type': 'application/json' },
535
+ body: JSON.stringify({
536
+ model: this.model,
537
+ system,
538
+ prompt,
539
+ stream: false,
540
+ }),
541
+ });
542
+
543
+ const data = await response.json();
544
+ return data.response;
545
+ }
546
+
547
+ async getEmbeddings(text: string | string[]): Promise<number[][]> {
548
+ const inputs = Array.isArray(text) ? text : [text];
549
+ const results: number[][] = [];
550
+
551
+ for (const input of inputs) {
552
+ const response = await fetch(this.baseUrl + '/api/embeddings', {
553
+ method: 'POST',
554
+ headers: { 'Content-Type': 'application/json' },
555
+ body: JSON.stringify({
556
+ model: this.model,
557
+ prompt: input,
558
+ }),
559
+ });
560
+
561
+ if (!response.ok) {
562
+ throw new Error('Ollama Embeddings API error: ' + response.statusText);
563
+ }
564
+
565
+ const data = await response.json();
566
+ results.push(data.embedding);
567
+ }
568
+
569
+ return results;
570
+ }
571
+ }
572
+
573
+ // ============================================================================
574
+ // LM Studio Adapter (OpenAI-compatible local)
575
+ // ============================================================================
576
+
577
+ export interface LMStudioAdapterConfig {
578
+ baseUrl?: string;
579
+ model?: string;
580
+ }
581
+
582
+ /**
583
+ * LM Studio adapter - uses OpenAI-compatible API running locally
584
+ */
585
+ export class LMStudioAdapter implements AIAdapter {
586
+ readonly id = 'lmstudio';
587
+ readonly name = 'LM Studio (Local)';
588
+
589
+ private openaiAdapter: OpenAIAdapter;
590
+
591
+ constructor(config: LMStudioAdapterConfig = {}) {
592
+ this.openaiAdapter = new OpenAIAdapter({
593
+ apiKey: 'lm-studio', // LM Studio doesn't require an API key
594
+ baseUrl: config.baseUrl || 'http://localhost:1234/v1',
595
+ model: config.model || 'local-model',
596
+ });
597
+ }
598
+
599
+ isReady(): boolean {
600
+ return true; // Assume ready, will fail gracefully if not running
601
+ }
602
+
603
+ generateHoloScript(prompt: string, options?: GenerateOptions): Promise<GenerateResult> {
604
+ return this.openaiAdapter.generateHoloScript(prompt, options);
605
+ }
606
+
607
+ explainHoloScript(holoScript: string): Promise<ExplainResult> {
608
+ return this.openaiAdapter.explainHoloScript(holoScript);
609
+ }
610
+
611
+ optimizeHoloScript(
612
+ holoScript: string,
613
+ target: 'mobile' | 'desktop' | 'vr' | 'ar'
614
+ ): Promise<OptimizeResult> {
615
+ return this.openaiAdapter.optimizeHoloScript(holoScript, target);
616
+ }
617
+
618
+ fixHoloScript(holoScript: string, errors: string[]): Promise<FixResult> {
619
+ return this.openaiAdapter.fixHoloScript(holoScript, errors);
620
+ }
621
+
622
+ chat(
623
+ message: string,
624
+ holoScript?: string,
625
+ history?: Array<{ role: 'user' | 'assistant'; content: string }>
626
+ ): Promise<string> {
627
+ return this.openaiAdapter.chat(message, holoScript, history);
628
+ }
629
+ }
630
+
631
+ // ============================================================================
632
+ // Factory Functions
633
+ // ============================================================================
634
+
635
+ import { registerAIAdapter } from './AIAdapter';
636
+
637
+ /**
638
+ * Create and register an OpenAI adapter
639
+ */
640
+ export function useOpenAI(config: OpenAIAdapterConfig): OpenAIAdapter {
641
+ const adapter = new OpenAIAdapter(config);
642
+ registerAIAdapter(adapter, true);
643
+ return adapter;
644
+ }
645
+
646
+ /**
647
+ * Create and register an Anthropic adapter
648
+ */
649
+ export function useAnthropic(config: AnthropicAdapterConfig): AnthropicAdapter {
650
+ const adapter = new AnthropicAdapter(config);
651
+ registerAIAdapter(adapter, true);
652
+ return adapter;
653
+ }
654
+
655
+ /**
656
+ * Create and register an Ollama adapter (local)
657
+ */
658
+ export function useOllama(config: OllamaAdapterConfig = {}): OllamaAdapter {
659
+ const adapter = new OllamaAdapter(config);
660
+ registerAIAdapter(adapter, true);
661
+ return adapter;
662
+ }
663
+
664
+ /**
665
+ * Create and register an LM Studio adapter (local)
666
+ */
667
+ export function useLMStudio(config: LMStudioAdapterConfig = {}): LMStudioAdapter {
668
+ const adapter = new LMStudioAdapter(config);
669
+ registerAIAdapter(adapter, true);
670
+ return adapter;
671
+ }
672
+
673
+ // ============================================================================
674
+ // Google Gemini Adapter
675
+ // ============================================================================
676
+
677
+ export interface GeminiAdapterConfig {
678
+ apiKey: string;
679
+ model?: string;
680
+ /** Embedding model (default: text-embedding-004) */
681
+ embeddingModel?: string;
682
+ }
683
+
684
+ export class GeminiAdapter implements AIAdapter {
685
+ readonly id = 'gemini';
686
+ readonly name = 'Google Gemini';
687
+
688
+ private config: GeminiAdapterConfig;
689
+ private model: string;
690
+ private embeddingModel: string;
691
+
692
+ constructor(config: GeminiAdapterConfig) {
693
+ this.config = config;
694
+ this.model = config.model || 'gemini-2.0-flash';
695
+ this.embeddingModel = config.embeddingModel || 'text-embedding-004';
696
+ }
697
+
698
+ isReady(): boolean {
699
+ return !!this.config.apiKey;
700
+ }
701
+
702
+ async generateHoloScript(prompt: string, options?: GenerateOptions): Promise<GenerateResult> {
703
+ const response = await this.callAPI('Create a HoloScript scene: ' + prompt, options);
704
+
705
+ return {
706
+ holoScript: this.extractCode(response),
707
+ confidence: 0.85,
708
+ };
709
+ }
710
+
711
+ async explainHoloScript(holoScript: string): Promise<ExplainResult> {
712
+ const response = await this.callAPI('Explain this HoloScript code clearly:\n\n' + holoScript);
713
+ return { explanation: response };
714
+ }
715
+
716
+ async optimizeHoloScript(
717
+ holoScript: string,
718
+ target: 'mobile' | 'desktop' | 'vr' | 'ar'
719
+ ): Promise<OptimizeResult> {
720
+ const response = await this.callAPI(
721
+ 'Optimize this HoloScript for ' +
722
+ target +
723
+ '. Return only the optimized code:\n\n' +
724
+ holoScript
725
+ );
726
+ return {
727
+ holoScript: this.extractCode(response),
728
+ improvements: ['Optimized for ' + target],
729
+ };
730
+ }
731
+
732
+ async fixHoloScript(holoScript: string, errors: string[]): Promise<FixResult> {
733
+ const response = await this.callAPI(
734
+ 'Fix these errors in the HoloScript:\nErrors: ' +
735
+ errors.join(', ') +
736
+ '\n\nCode:\n' +
737
+ holoScript
738
+ );
739
+ return {
740
+ holoScript: this.extractCode(response),
741
+ fixes: errors.map((e) => ({ line: 0, issue: e, fix: 'auto-fixed' })),
742
+ };
743
+ }
744
+
745
+ async chat(
746
+ message: string,
747
+ holoScript?: string,
748
+ history?: Array<{ role: 'user' | 'assistant'; content: string }>
749
+ ): Promise<string> {
750
+ const fullMessage = holoScript
751
+ ? 'Context:\n' + holoScript + '\n\nQuestion: ' + message
752
+ : message;
753
+ return this.callAPI(fullMessage, undefined, history);
754
+ }
755
+
756
+ async getEmbeddings(text: string | string[]): Promise<number[][]> {
757
+ const inputs = Array.isArray(text) ? text : [text];
758
+ const results: number[][] = [];
759
+
760
+ for (const input of inputs) {
761
+ const response = await fetch(
762
+ `https://generativelanguage.googleapis.com/v1beta/models/${this.embeddingModel}:embedContent?key=${this.config.apiKey}`,
763
+ {
764
+ method: 'POST',
765
+ headers: { 'Content-Type': 'application/json' },
766
+ body: JSON.stringify({
767
+ model: `models/${this.embeddingModel}`,
768
+ content: { parts: [{ text: input }] },
769
+ }),
770
+ }
771
+ );
772
+
773
+ if (!response.ok) {
774
+ const errorData = await response.json().catch(() => ({}));
775
+ const errorMsg = (errorData as APIErrorResponse)?.error?.message || response.statusText;
776
+ throw new Error('Gemini Embeddings API error: ' + errorMsg);
777
+ }
778
+
779
+ const data = await response.json();
780
+ results.push(data.embedding.values);
781
+ }
782
+
783
+ return results;
784
+ }
785
+
786
+ private extractCode(response: string): string {
787
+ const match = response.match(/```(?:holoscript|holo)?\n([\s\S]*?)```/);
788
+ return match ? match[1].trim() : response.trim();
789
+ }
790
+
791
+ private async callAPI(
792
+ message: string,
793
+ _options?: GenerateOptions,
794
+ history?: Array<{ role: 'user' | 'assistant'; content: string }>
795
+ ): Promise<string> {
796
+ // Build contents array with optional history
797
+ const contents: Array<{ role: string; parts: Array<{ text: string }> }> = [];
798
+
799
+ if (history && history.length > 0) {
800
+ for (const msg of history) {
801
+ contents.push({
802
+ role: msg.role === 'assistant' ? 'model' : 'user',
803
+ parts: [{ text: msg.content }],
804
+ });
805
+ }
806
+ }
807
+
808
+ // Add system prompt + current message
809
+ contents.push({
810
+ role: 'user',
811
+ parts: [{ text: HOLOSCRIPT_SYSTEM_PROMPT }, { text: message }],
812
+ });
813
+
814
+ const response = await fetch(
815
+ `https://generativelanguage.googleapis.com/v1beta/models/${this.model}:generateContent?key=${this.config.apiKey}`,
816
+ {
817
+ method: 'POST',
818
+ headers: { 'Content-Type': 'application/json' },
819
+ body: JSON.stringify({
820
+ contents,
821
+ generationConfig: {
822
+ temperature: 0.7,
823
+ maxOutputTokens: 4096,
824
+ },
825
+ }),
826
+ }
827
+ );
828
+
829
+ if (!response.ok) {
830
+ const errorData = await response.json().catch(() => ({}));
831
+ const errorMsg = (errorData as APIErrorResponse)?.error?.message || response.statusText;
832
+ const status = response.status;
833
+
834
+ if (status === 429) {
835
+ throw new Error('Gemini API rate limited. Please retry after a short delay.');
836
+ }
837
+ if (status === 403) {
838
+ throw new Error('Gemini API key invalid or quota exceeded: ' + errorMsg);
839
+ }
840
+ throw new Error('Gemini API error (' + status + '): ' + errorMsg);
841
+ }
842
+
843
+ const data = await response.json();
844
+
845
+ if (!data.candidates || data.candidates.length === 0) {
846
+ const blockReason = data.promptFeedback?.blockReason;
847
+ if (blockReason) {
848
+ throw new Error('Gemini request blocked: ' + blockReason);
849
+ }
850
+ throw new Error('Gemini returned no candidates');
851
+ }
852
+
853
+ return data.candidates[0].content.parts[0].text;
854
+ }
855
+ }
856
+
857
+ // ============================================================================
858
+ // XAI (Grok) Adapter
859
+ // ============================================================================
860
+
861
+ export interface XAIAdapterConfig {
862
+ apiKey: string;
863
+ model?: string;
864
+ }
865
+
866
+ export class XAIAdapter implements AIAdapter {
867
+ readonly id = 'xai';
868
+ readonly name = 'xAI Grok';
869
+
870
+ private config: XAIAdapterConfig;
871
+ private model: string;
872
+
873
+ constructor(config: XAIAdapterConfig) {
874
+ this.config = config;
875
+ this.model = config.model || 'grok-3';
876
+ }
877
+
878
+ isReady(): boolean {
879
+ return !!this.config.apiKey;
880
+ }
881
+
882
+ async generateHoloScript(prompt: string, _options?: GenerateOptions): Promise<GenerateResult> {
883
+ const messages: Array<{ role: string; content: string }> = [
884
+ { role: 'system', content: HOLOSCRIPT_SYSTEM_PROMPT },
885
+ { role: 'user', content: 'Create a HoloScript scene: ' + prompt },
886
+ ];
887
+ const response = await this.callAPI(messages);
888
+
889
+ return {
890
+ holoScript: this.extractCode(response),
891
+ confidence: 0.85,
892
+ };
893
+ }
894
+
895
+ async explainHoloScript(holoScript: string): Promise<ExplainResult> {
896
+ const messages: Array<{ role: string; content: string }> = [
897
+ { role: 'system', content: HOLOSCRIPT_SYSTEM_PROMPT },
898
+ { role: 'user', content: 'Explain this HoloScript code clearly:\n\n' + holoScript },
899
+ ];
900
+ const response = await this.callAPI(messages);
901
+ return { explanation: response };
902
+ }
903
+
904
+ async optimizeHoloScript(
905
+ holoScript: string,
906
+ target: 'mobile' | 'desktop' | 'vr' | 'ar'
907
+ ): Promise<OptimizeResult> {
908
+ const messages: Array<{ role: string; content: string }> = [
909
+ { role: 'system', content: HOLOSCRIPT_SYSTEM_PROMPT },
910
+ {
911
+ role: 'user',
912
+ content:
913
+ 'Optimize this HoloScript for ' +
914
+ target +
915
+ '. Return only the optimized code:\n\n' +
916
+ holoScript,
917
+ },
918
+ ];
919
+ const response = await this.callAPI(messages);
920
+ return {
921
+ holoScript: this.extractCode(response),
922
+ improvements: ['Optimized for ' + target],
923
+ };
924
+ }
925
+
926
+ async fixHoloScript(holoScript: string, errors: string[]): Promise<FixResult> {
927
+ const messages: Array<{ role: string; content: string }> = [
928
+ { role: 'system', content: HOLOSCRIPT_SYSTEM_PROMPT },
929
+ {
930
+ role: 'user',
931
+ content:
932
+ 'Fix these errors in the HoloScript:\nErrors: ' +
933
+ errors.join(', ') +
934
+ '\n\nCode:\n' +
935
+ holoScript,
936
+ },
937
+ ];
938
+ const response = await this.callAPI(messages);
939
+ return {
940
+ holoScript: this.extractCode(response),
941
+ fixes: errors.map((e) => ({ line: 0, issue: e, fix: 'auto-fixed' })),
942
+ };
943
+ }
944
+
945
+ async chat(
946
+ message: string,
947
+ holoScript?: string,
948
+ history?: Array<{ role: 'user' | 'assistant'; content: string }>
949
+ ): Promise<string> {
950
+ const messages: Array<{ role: string; content: string }> = [
951
+ { role: 'system', content: HOLOSCRIPT_SYSTEM_PROMPT },
952
+ ];
953
+
954
+ if (history) {
955
+ messages.push(...history);
956
+ }
957
+
958
+ if (holoScript) {
959
+ messages.push({
960
+ role: 'user',
961
+ content: 'Context:\n' + holoScript + '\n\nQuestion: ' + message,
962
+ });
963
+ } else {
964
+ messages.push({ role: 'user', content: message });
965
+ }
966
+
967
+ return this.callAPI(messages);
968
+ }
969
+
970
+ private extractCode(response: string): string {
971
+ const match = response.match(/```(?:holoscript|holo)?\n([\s\S]*?)```/);
972
+ return match ? match[1].trim() : response.trim();
973
+ }
974
+
975
+ private async callAPI(messages: Array<{ role: string; content: string }>): Promise<string> {
976
+ const response = await fetch('https://api.x.ai/v1/chat/completions', {
977
+ method: 'POST',
978
+ headers: {
979
+ 'Content-Type': 'application/json',
980
+ Authorization: 'Bearer ' + this.config.apiKey,
981
+ },
982
+ body: JSON.stringify({
983
+ model: this.model,
984
+ messages,
985
+ temperature: 0.7,
986
+ }),
987
+ });
988
+
989
+ if (response.status === 429) {
990
+ throw new Error('xAI rate limited (429) - please retry after backoff');
991
+ }
992
+ if (response.status === 401 || response.status === 403) {
993
+ throw new Error('xAI auth failed - check API key');
994
+ }
995
+ if (!response.ok) {
996
+ throw new Error('xAI API error: ' + response.statusText);
997
+ }
998
+
999
+ const data = await response.json();
1000
+ return data.choices[0].message.content;
1001
+ }
1002
+ }
1003
+
1004
+ // ============================================================================
1005
+ // Together AI Adapter
1006
+ // ============================================================================
1007
+
1008
+ export interface TogetherAdapterConfig {
1009
+ apiKey: string;
1010
+ model?: string;
1011
+ }
1012
+
1013
+ export class TogetherAdapter implements AIAdapter {
1014
+ readonly id = 'together';
1015
+ readonly name = 'Together AI';
1016
+
1017
+ private config: TogetherAdapterConfig;
1018
+ private model: string;
1019
+
1020
+ constructor(config: TogetherAdapterConfig) {
1021
+ this.config = config;
1022
+ this.model = config.model || 'meta-llama/Llama-3.3-70B-Instruct-Turbo';
1023
+ }
1024
+
1025
+ async getEmbeddings(text: string | string[]): Promise<number[][]> {
1026
+ const inputs = Array.isArray(text) ? text : [text];
1027
+ const results: number[][] = [];
1028
+
1029
+ for (const input of inputs) {
1030
+ const response = await fetch('https://api.together.xyz/v1/embeddings', {
1031
+ method: 'POST',
1032
+ headers: {
1033
+ 'Content-Type': 'application/json',
1034
+ Authorization: 'Bearer ' + this.config.apiKey,
1035
+ },
1036
+ body: JSON.stringify({
1037
+ model: 'togethercomputer/m2-bert-80M-32k-retrieval',
1038
+ input,
1039
+ }),
1040
+ });
1041
+
1042
+ if (!response.ok) {
1043
+ throw new Error('Together Embeddings API error: ' + response.statusText);
1044
+ }
1045
+
1046
+ const data = await response.json();
1047
+ results.push(data.data[0].embedding);
1048
+ }
1049
+
1050
+ return results;
1051
+ }
1052
+
1053
+ isReady(): boolean {
1054
+ return !!this.config.apiKey;
1055
+ }
1056
+
1057
+ async generateHoloScript(prompt: string, _options?: GenerateOptions): Promise<GenerateResult> {
1058
+ const messages: Array<{ role: string; content: string }> = [
1059
+ { role: 'system', content: HOLOSCRIPT_SYSTEM_PROMPT },
1060
+ { role: 'user', content: 'Create a HoloScript scene: ' + prompt },
1061
+ ];
1062
+ const response = await this.callAPI(messages);
1063
+
1064
+ return {
1065
+ holoScript: this.extractCode(response),
1066
+ confidence: 0.8,
1067
+ };
1068
+ }
1069
+
1070
+ async explainHoloScript(holoScript: string): Promise<ExplainResult> {
1071
+ const messages: Array<{ role: string; content: string }> = [
1072
+ { role: 'system', content: HOLOSCRIPT_SYSTEM_PROMPT },
1073
+ { role: 'user', content: 'Explain this HoloScript code clearly:\n\n' + holoScript },
1074
+ ];
1075
+ const response = await this.callAPI(messages);
1076
+ return { explanation: response };
1077
+ }
1078
+
1079
+ async optimizeHoloScript(
1080
+ holoScript: string,
1081
+ target: 'mobile' | 'desktop' | 'vr' | 'ar'
1082
+ ): Promise<OptimizeResult> {
1083
+ const messages: Array<{ role: string; content: string }> = [
1084
+ { role: 'system', content: HOLOSCRIPT_SYSTEM_PROMPT },
1085
+ {
1086
+ role: 'user',
1087
+ content:
1088
+ 'Optimize this HoloScript for ' +
1089
+ target +
1090
+ '. Return only the optimized code:\n\n' +
1091
+ holoScript,
1092
+ },
1093
+ ];
1094
+ const response = await this.callAPI(messages);
1095
+ return {
1096
+ holoScript: this.extractCode(response),
1097
+ improvements: ['Optimized for ' + target],
1098
+ };
1099
+ }
1100
+
1101
+ async fixHoloScript(holoScript: string, errors: string[]): Promise<FixResult> {
1102
+ const messages: Array<{ role: string; content: string }> = [
1103
+ { role: 'system', content: HOLOSCRIPT_SYSTEM_PROMPT },
1104
+ {
1105
+ role: 'user',
1106
+ content:
1107
+ 'Fix these errors in the HoloScript:\nErrors: ' +
1108
+ errors.join(', ') +
1109
+ '\n\nCode:\n' +
1110
+ holoScript,
1111
+ },
1112
+ ];
1113
+ const response = await this.callAPI(messages);
1114
+ return {
1115
+ holoScript: this.extractCode(response),
1116
+ fixes: errors.map((e) => ({ line: 0, issue: e, fix: 'auto-fixed' })),
1117
+ };
1118
+ }
1119
+
1120
+ async chat(
1121
+ message: string,
1122
+ holoScript?: string,
1123
+ history?: Array<{ role: 'user' | 'assistant'; content: string }>
1124
+ ): Promise<string> {
1125
+ const messages: Array<{ role: string; content: string }> = [
1126
+ { role: 'system', content: HOLOSCRIPT_SYSTEM_PROMPT },
1127
+ ];
1128
+
1129
+ if (history) {
1130
+ messages.push(...history);
1131
+ }
1132
+
1133
+ if (holoScript) {
1134
+ messages.push({
1135
+ role: 'user',
1136
+ content: 'Context:\n' + holoScript + '\n\nQuestion: ' + message,
1137
+ });
1138
+ } else {
1139
+ messages.push({ role: 'user', content: message });
1140
+ }
1141
+
1142
+ return this.callAPI(messages);
1143
+ }
1144
+
1145
+ private extractCode(response: string): string {
1146
+ const match = response.match(/```(?:holoscript|holo)?\n([\s\S]*?)```/);
1147
+ return match ? match[1].trim() : response.trim();
1148
+ }
1149
+
1150
+ private async callAPI(messages: Array<{ role: string; content: string }>): Promise<string> {
1151
+ const response = await fetch('https://api.together.xyz/v1/chat/completions', {
1152
+ method: 'POST',
1153
+ headers: {
1154
+ 'Content-Type': 'application/json',
1155
+ Authorization: 'Bearer ' + this.config.apiKey,
1156
+ },
1157
+ body: JSON.stringify({
1158
+ model: this.model,
1159
+ messages,
1160
+ temperature: 0.7,
1161
+ max_tokens: 4096,
1162
+ }),
1163
+ });
1164
+
1165
+ if (response.status === 429) {
1166
+ throw new Error('Together AI rate limited (429) - please retry');
1167
+ }
1168
+ if (response.status === 401 || response.status === 403) {
1169
+ throw new Error('Together AI auth failed - check API key');
1170
+ }
1171
+ if (!response.ok) {
1172
+ throw new Error('Together AI API error: ' + response.statusText);
1173
+ }
1174
+
1175
+ const data = await response.json();
1176
+ return data.choices[0].message.content;
1177
+ }
1178
+ }
1179
+
1180
+ // ============================================================================
1181
+ // Fireworks AI Adapter
1182
+ // ============================================================================
1183
+
1184
+ export interface FireworksAdapterConfig {
1185
+ apiKey: string;
1186
+ model?: string;
1187
+ }
1188
+
1189
+ export class FireworksAdapter implements AIAdapter {
1190
+ readonly id = 'fireworks';
1191
+ readonly name = 'Fireworks AI';
1192
+
1193
+ private config: FireworksAdapterConfig;
1194
+ private model: string;
1195
+
1196
+ constructor(config: FireworksAdapterConfig) {
1197
+ this.config = config;
1198
+ this.model = config.model || 'accounts/fireworks/models/llama-v3p1-70b-instruct';
1199
+ }
1200
+
1201
+ isReady(): boolean {
1202
+ return !!this.config.apiKey;
1203
+ }
1204
+
1205
+ async generateHoloScript(prompt: string, _options?: GenerateOptions): Promise<GenerateResult> {
1206
+ const messages: Array<{ role: string; content: string }> = [
1207
+ { role: 'system', content: HOLOSCRIPT_SYSTEM_PROMPT },
1208
+ { role: 'user', content: 'Create a HoloScript scene: ' + prompt },
1209
+ ];
1210
+ const response = await this.callAPI(messages);
1211
+
1212
+ return {
1213
+ holoScript: this.extractCode(response),
1214
+ confidence: 0.8,
1215
+ };
1216
+ }
1217
+
1218
+ async explainHoloScript(holoScript: string): Promise<ExplainResult> {
1219
+ const messages: Array<{ role: string; content: string }> = [
1220
+ { role: 'system', content: HOLOSCRIPT_SYSTEM_PROMPT },
1221
+ { role: 'user', content: 'Explain this HoloScript code clearly:\n\n' + holoScript },
1222
+ ];
1223
+ const response = await this.callAPI(messages);
1224
+ return { explanation: response };
1225
+ }
1226
+
1227
+ async optimizeHoloScript(
1228
+ holoScript: string,
1229
+ target: 'mobile' | 'desktop' | 'vr' | 'ar'
1230
+ ): Promise<OptimizeResult> {
1231
+ const messages: Array<{ role: string; content: string }> = [
1232
+ { role: 'system', content: HOLOSCRIPT_SYSTEM_PROMPT },
1233
+ {
1234
+ role: 'user',
1235
+ content:
1236
+ 'Optimize this HoloScript for ' +
1237
+ target +
1238
+ '. Return only the optimized code:\n\n' +
1239
+ holoScript,
1240
+ },
1241
+ ];
1242
+ const response = await this.callAPI(messages);
1243
+ return {
1244
+ holoScript: this.extractCode(response),
1245
+ improvements: ['Optimized for ' + target],
1246
+ };
1247
+ }
1248
+
1249
+ async fixHoloScript(holoScript: string, errors: string[]): Promise<FixResult> {
1250
+ const messages: Array<{ role: string; content: string }> = [
1251
+ { role: 'system', content: HOLOSCRIPT_SYSTEM_PROMPT },
1252
+ {
1253
+ role: 'user',
1254
+ content:
1255
+ 'Fix these errors in the HoloScript:\nErrors: ' +
1256
+ errors.join(', ') +
1257
+ '\n\nCode:\n' +
1258
+ holoScript,
1259
+ },
1260
+ ];
1261
+ const response = await this.callAPI(messages);
1262
+ return {
1263
+ holoScript: this.extractCode(response),
1264
+ fixes: errors.map((e) => ({ line: 0, issue: e, fix: 'auto-fixed' })),
1265
+ };
1266
+ }
1267
+
1268
+ async chat(
1269
+ message: string,
1270
+ holoScript?: string,
1271
+ history?: Array<{ role: 'user' | 'assistant'; content: string }>
1272
+ ): Promise<string> {
1273
+ const messages: Array<{ role: string; content: string }> = [
1274
+ { role: 'system', content: HOLOSCRIPT_SYSTEM_PROMPT },
1275
+ ];
1276
+
1277
+ if (history) {
1278
+ messages.push(...history);
1279
+ }
1280
+
1281
+ if (holoScript) {
1282
+ messages.push({
1283
+ role: 'user',
1284
+ content: 'Context:\n' + holoScript + '\n\nQuestion: ' + message,
1285
+ });
1286
+ } else {
1287
+ messages.push({ role: 'user', content: message });
1288
+ }
1289
+
1290
+ return this.callAPI(messages);
1291
+ }
1292
+
1293
+ private extractCode(response: string): string {
1294
+ const match = response.match(/```(?:holoscript|holo)?\n([\s\S]*?)```/);
1295
+ return match ? match[1].trim() : response.trim();
1296
+ }
1297
+
1298
+ private async callAPI(messages: Array<{ role: string; content: string }>): Promise<string> {
1299
+ const response = await fetch('https://api.fireworks.ai/inference/v1/chat/completions', {
1300
+ method: 'POST',
1301
+ headers: {
1302
+ 'Content-Type': 'application/json',
1303
+ Authorization: 'Bearer ' + this.config.apiKey,
1304
+ },
1305
+ body: JSON.stringify({
1306
+ model: this.model,
1307
+ messages,
1308
+ temperature: 0.7,
1309
+ max_tokens: 4096,
1310
+ }),
1311
+ });
1312
+
1313
+ if (response.status === 429) {
1314
+ throw new Error('Fireworks AI rate limited (429) - please retry');
1315
+ }
1316
+ if (response.status === 401 || response.status === 403) {
1317
+ throw new Error('Fireworks AI auth failed - check API key');
1318
+ }
1319
+ if (!response.ok) {
1320
+ throw new Error('Fireworks AI API error: ' + response.statusText);
1321
+ }
1322
+
1323
+ const data = await response.json();
1324
+ return data.choices[0].message.content;
1325
+ }
1326
+
1327
+ async getEmbeddings(text: string | string[]): Promise<number[][]> {
1328
+ const inputs = Array.isArray(text) ? text : [text];
1329
+ const results: number[][] = [];
1330
+
1331
+ for (const input of inputs) {
1332
+ const response = await fetch('https://api.fireworks.ai/inference/v1/embeddings', {
1333
+ method: 'POST',
1334
+ headers: {
1335
+ 'Content-Type': 'application/json',
1336
+ Authorization: 'Bearer ' + this.config.apiKey,
1337
+ },
1338
+ body: JSON.stringify({
1339
+ model: 'nomic-ai/nomic-embed-text-v1',
1340
+ input,
1341
+ }),
1342
+ });
1343
+
1344
+ if (!response.ok) {
1345
+ throw new Error('Fireworks Embeddings API error: ' + response.statusText);
1346
+ }
1347
+
1348
+ const data = await response.json();
1349
+ results.push(data.data[0].embedding);
1350
+ }
1351
+
1352
+ return results;
1353
+ }
1354
+ }
1355
+
1356
+ // ============================================================================
1357
+ // NVIDIA NIM Adapter
1358
+ // ============================================================================
1359
+
1360
+ export interface NVIDIAAdapterConfig {
1361
+ apiKey: string;
1362
+ model?: string;
1363
+ baseUrl?: string;
1364
+ }
1365
+
1366
+ export class NVIDIAAdapter implements AIAdapter {
1367
+ readonly id = 'nvidia';
1368
+ readonly name = 'NVIDIA NIM';
1369
+
1370
+ private config: NVIDIAAdapterConfig;
1371
+ private model: string;
1372
+ private baseUrl: string;
1373
+
1374
+ constructor(config: NVIDIAAdapterConfig) {
1375
+ this.config = config;
1376
+ this.model = config.model || 'meta/llama-3.1-70b-instruct';
1377
+ this.baseUrl = config.baseUrl || 'https://integrate.api.nvidia.com/v1';
1378
+ }
1379
+
1380
+ isReady(): boolean {
1381
+ return !!this.config.apiKey;
1382
+ }
1383
+
1384
+ async generateHoloScript(prompt: string, _options?: GenerateOptions): Promise<GenerateResult> {
1385
+ const messages: Array<{ role: string; content: string }> = [
1386
+ { role: 'system', content: HOLOSCRIPT_SYSTEM_PROMPT },
1387
+ { role: 'user', content: 'Create a HoloScript scene: ' + prompt },
1388
+ ];
1389
+ const response = await this.callAPI(messages);
1390
+
1391
+ return {
1392
+ holoScript: this.extractCode(response),
1393
+ confidence: 0.85,
1394
+ };
1395
+ }
1396
+
1397
+ async explainHoloScript(holoScript: string): Promise<ExplainResult> {
1398
+ const messages: Array<{ role: string; content: string }> = [
1399
+ { role: 'system', content: HOLOSCRIPT_SYSTEM_PROMPT },
1400
+ { role: 'user', content: 'Explain this HoloScript code clearly:\n\n' + holoScript },
1401
+ ];
1402
+ const response = await this.callAPI(messages);
1403
+ return { explanation: response };
1404
+ }
1405
+
1406
+ async optimizeHoloScript(
1407
+ holoScript: string,
1408
+ target: 'mobile' | 'desktop' | 'vr' | 'ar'
1409
+ ): Promise<OptimizeResult> {
1410
+ const messages: Array<{ role: string; content: string }> = [
1411
+ { role: 'system', content: HOLOSCRIPT_SYSTEM_PROMPT },
1412
+ {
1413
+ role: 'user',
1414
+ content:
1415
+ 'Optimize this HoloScript for ' +
1416
+ target +
1417
+ '. Return only the optimized code:\n\n' +
1418
+ holoScript,
1419
+ },
1420
+ ];
1421
+ const response = await this.callAPI(messages);
1422
+ return {
1423
+ holoScript: this.extractCode(response),
1424
+ improvements: ['Optimized for ' + target],
1425
+ };
1426
+ }
1427
+
1428
+ async fixHoloScript(holoScript: string, errors: string[]): Promise<FixResult> {
1429
+ const messages: Array<{ role: string; content: string }> = [
1430
+ { role: 'system', content: HOLOSCRIPT_SYSTEM_PROMPT },
1431
+ {
1432
+ role: 'user',
1433
+ content:
1434
+ 'Fix these errors in the HoloScript:\nErrors: ' +
1435
+ errors.join(', ') +
1436
+ '\n\nCode:\n' +
1437
+ holoScript,
1438
+ },
1439
+ ];
1440
+ const response = await this.callAPI(messages);
1441
+ return {
1442
+ holoScript: this.extractCode(response),
1443
+ fixes: errors.map((e) => ({ line: 0, issue: e, fix: 'auto-fixed' })),
1444
+ };
1445
+ }
1446
+
1447
+ async chat(
1448
+ message: string,
1449
+ holoScript?: string,
1450
+ history?: Array<{ role: 'user' | 'assistant'; content: string }>
1451
+ ): Promise<string> {
1452
+ const messages: Array<{ role: string; content: string }> = [
1453
+ { role: 'system', content: HOLOSCRIPT_SYSTEM_PROMPT },
1454
+ ];
1455
+
1456
+ if (history) {
1457
+ messages.push(...history);
1458
+ }
1459
+
1460
+ if (holoScript) {
1461
+ messages.push({
1462
+ role: 'user',
1463
+ content: 'Context:\n' + holoScript + '\n\nQuestion: ' + message,
1464
+ });
1465
+ } else {
1466
+ messages.push({ role: 'user', content: message });
1467
+ }
1468
+
1469
+ return this.callAPI(messages);
1470
+ }
1471
+
1472
+ private extractCode(response: string): string {
1473
+ const match = response.match(/```(?:holoscript|holo)?\n([\s\S]*?)```/);
1474
+ return match ? match[1].trim() : response.trim();
1475
+ }
1476
+
1477
+ private async callAPI(messages: Array<{ role: string; content: string }>): Promise<string> {
1478
+ const response = await fetch(this.baseUrl + '/chat/completions', {
1479
+ method: 'POST',
1480
+ headers: {
1481
+ 'Content-Type': 'application/json',
1482
+ Authorization: 'Bearer ' + this.config.apiKey,
1483
+ },
1484
+ body: JSON.stringify({
1485
+ model: this.model,
1486
+ messages,
1487
+ temperature: 0.7,
1488
+ max_tokens: 4096,
1489
+ }),
1490
+ });
1491
+
1492
+ if (response.status === 429) {
1493
+ throw new Error('NVIDIA NIM rate limited (429) - please retry');
1494
+ }
1495
+ if (response.status === 401 || response.status === 403) {
1496
+ throw new Error('NVIDIA NIM auth failed - check API key');
1497
+ }
1498
+ if (!response.ok) {
1499
+ throw new Error('NVIDIA NIM API error: ' + response.statusText);
1500
+ }
1501
+
1502
+ const data = await response.json();
1503
+ return data.choices[0].message.content;
1504
+ }
1505
+
1506
+ async getEmbeddings(text: string | string[]): Promise<number[][]> {
1507
+ const inputs = Array.isArray(text) ? text : [text];
1508
+ const results: number[][] = [];
1509
+
1510
+ for (const input of inputs) {
1511
+ const response = await fetch(this.baseUrl + '/embeddings', {
1512
+ method: 'POST',
1513
+ headers: {
1514
+ 'Content-Type': 'application/json',
1515
+ Authorization: 'Bearer ' + this.config.apiKey,
1516
+ },
1517
+ body: JSON.stringify({
1518
+ model: 'nvidia/nvembed-v1',
1519
+ input,
1520
+ }),
1521
+ });
1522
+
1523
+ if (!response.ok) {
1524
+ throw new Error('NVIDIA Embeddings API error: ' + response.statusText);
1525
+ }
1526
+
1527
+ const data = await response.json();
1528
+ results.push(data.data[0].embedding);
1529
+ }
1530
+
1531
+ return results;
1532
+ }
1533
+ }
1534
+
1535
+ // ============================================================================
1536
+ // Additional Factory Functions
1537
+ // ============================================================================
1538
+
1539
+ /**
1540
+ * Create and register a Gemini adapter
1541
+ */
1542
+ export function useGemini(config: GeminiAdapterConfig): GeminiAdapter {
1543
+ const adapter = new GeminiAdapter(config);
1544
+ registerAIAdapter(adapter, true);
1545
+ return adapter;
1546
+ }
1547
+
1548
+ /**
1549
+ * Create and register an xAI (Grok) adapter
1550
+ */
1551
+ export function useXAI(config: XAIAdapterConfig): XAIAdapter {
1552
+ const adapter = new XAIAdapter(config);
1553
+ registerAIAdapter(adapter, true);
1554
+ return adapter;
1555
+ }
1556
+
1557
+ /** Alias for useXAI */
1558
+ export const useGrok = useXAI;
1559
+
1560
+ /**
1561
+ * Create and register a Together AI adapter
1562
+ */
1563
+ export function useTogether(config: TogetherAdapterConfig): TogetherAdapter {
1564
+ const adapter = new TogetherAdapter(config);
1565
+ registerAIAdapter(adapter, true);
1566
+ return adapter;
1567
+ }
1568
+
1569
+ /**
1570
+ * Create and register a Fireworks AI adapter
1571
+ */
1572
+ export function useFireworks(config: FireworksAdapterConfig): FireworksAdapter {
1573
+ const adapter = new FireworksAdapter(config);
1574
+ registerAIAdapter(adapter, true);
1575
+ return adapter;
1576
+ }
1577
+
1578
+ /**
1579
+ * Create and register an NVIDIA NIM adapter
1580
+ */
1581
+ export function useNVIDIA(config: NVIDIAAdapterConfig): NVIDIAAdapter {
1582
+ const adapter = new NVIDIAAdapter(config);
1583
+ registerAIAdapter(adapter, true);
1584
+ return adapter;
1585
+ }