@holoscript/core 6.0.4 → 7.0.0

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 (236) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1 -1
  3. package/dist/compiler/index.d.ts +82 -0
  4. package/dist/constants.d.ts +3 -2
  5. package/dist/coordinators/index.d.ts +189 -0
  6. package/dist/index.d.ts +501 -19
  7. package/dist/paper-0c-spike/index.d.ts +29 -0
  8. package/dist/reconstruction/index.d.ts +78 -0
  9. package/dist/tools/index.d.ts +22 -1
  10. package/dist/traitDocs/traitDocs.d.ts +69 -0
  11. package/dist/traits/index.d.ts +61 -0
  12. package/package.json +105 -57
  13. package/dist/GLTFPipeline-DEN36VNK.js +0 -12
  14. package/dist/GLTFPipeline-YPCAK236.cjs +0 -33
  15. package/dist/HoloScriptPlusParser-BN6KVRCM.js +0 -692
  16. package/dist/HoloScriptPlusParser-NC5FE6AL.cjs +0 -697
  17. package/dist/USDZExporter-NTMBNTDB.js +0 -707
  18. package/dist/USDZExporter-UWGWNMMD.cjs +0 -709
  19. package/dist/chunk-27LWW5FU.cjs +0 -410
  20. package/dist/chunk-2CWOLHTE.js +0 -69
  21. package/dist/chunk-33LSUQDD.cjs +0 -835
  22. package/dist/chunk-3FJCK5XA.js +0 -2232
  23. package/dist/chunk-3FXV5S25.cjs +0 -633
  24. package/dist/chunk-3FYZOR7S.cjs +0 -69
  25. package/dist/chunk-3SAK5KFL.cjs +0 -83
  26. package/dist/chunk-4XSNJCLC.cjs +0 -1859
  27. package/dist/chunk-54FHG2MX.js +0 -655
  28. package/dist/chunk-56IF4NTA.js +0 -56
  29. package/dist/chunk-5BGSECRJ.cjs +0 -2237
  30. package/dist/chunk-5GLCTO44.js +0 -161
  31. package/dist/chunk-5O6TQC6M.cjs +0 -1871
  32. package/dist/chunk-5OEOHAAW.cjs +0 -682
  33. package/dist/chunk-5TOFIR6L.js +0 -407
  34. package/dist/chunk-5WUNN6ZN.cjs +0 -428
  35. package/dist/chunk-6TZPZCOJ.cjs +0 -1404
  36. package/dist/chunk-6UEHYZ7V.cjs +0 -773
  37. package/dist/chunk-6XSERL6L.js +0 -5678
  38. package/dist/chunk-72EQECGT.cjs +0 -908
  39. package/dist/chunk-7AGYRWKW.cjs +0 -507
  40. package/dist/chunk-7LCYLPW2.cjs +0 -663
  41. package/dist/chunk-A7PIMZGU.js +0 -263
  42. package/dist/chunk-ATSKSYVE.cjs +0 -51683
  43. package/dist/chunk-B5TCIAPQ.cjs +0 -117
  44. package/dist/chunk-BF2235SI.cjs +0 -5714
  45. package/dist/chunk-BKIGPPVM.js +0 -629
  46. package/dist/chunk-BND3ST2K.cjs +0 -662
  47. package/dist/chunk-BU7VWW2K.js +0 -2522
  48. package/dist/chunk-BWFJEM5A.js +0 -5419
  49. package/dist/chunk-CAUCGUEA.cjs +0 -130
  50. package/dist/chunk-CBJSLA2E.cjs +0 -5423
  51. package/dist/chunk-CDPGV4DN.js +0 -114
  52. package/dist/chunk-CLYEIWA5.cjs +0 -408
  53. package/dist/chunk-CS2EMTGF.js +0 -1966
  54. package/dist/chunk-DMG7C4H2.js +0 -975
  55. package/dist/chunk-DXJQDCFL.js +0 -468
  56. package/dist/chunk-E3FWRT3Z.js +0 -608
  57. package/dist/chunk-E3UALNFA.js +0 -421
  58. package/dist/chunk-EONILVMF.js +0 -762
  59. package/dist/chunk-EQV4R3EV.cjs +0 -769
  60. package/dist/chunk-F3HH56EB.cjs +0 -5538
  61. package/dist/chunk-F4IULT7N.js +0 -1488
  62. package/dist/chunk-FF3Q7ADR.js +0 -380
  63. package/dist/chunk-FFKU7BTK.cjs +0 -1046
  64. package/dist/chunk-FHQVYCH2.js +0 -70
  65. package/dist/chunk-FSF7EQVA.cjs +0 -1974
  66. package/dist/chunk-G4VZTCIB.js +0 -659
  67. package/dist/chunk-G7CT3EMP.cjs +0 -1002
  68. package/dist/chunk-GGHSW2NN.js +0 -51334
  69. package/dist/chunk-GVUR45UF.cjs +0 -777
  70. package/dist/chunk-H5Z7NASB.js +0 -9662
  71. package/dist/chunk-HE7ULERA.cjs +0 -697
  72. package/dist/chunk-HJJLD366.js +0 -1169
  73. package/dist/chunk-HPS76H7Q.js +0 -309
  74. package/dist/chunk-HQUEA5R6.cjs +0 -424
  75. package/dist/chunk-HYNTS5CP.js +0 -422
  76. package/dist/chunk-I6XZ5DZF.cjs +0 -488
  77. package/dist/chunk-IBDG74G2.cjs +0 -1219
  78. package/dist/chunk-IFNQFCTM.js +0 -3098
  79. package/dist/chunk-IHOUYQIA.js +0 -406
  80. package/dist/chunk-ILRBGFVD.cjs +0 -72
  81. package/dist/chunk-IWI6J7FX.js +0 -421
  82. package/dist/chunk-K3JDKWGI.cjs +0 -270
  83. package/dist/chunk-K6EKD26I.js +0 -630
  84. package/dist/chunk-KCQ5NDYC.cjs +0 -3172
  85. package/dist/chunk-KED34ILP.js +0 -832
  86. package/dist/chunk-KSGXLT74.cjs +0 -457
  87. package/dist/chunk-L4G4RLXX.js +0 -767
  88. package/dist/chunk-LDP5OK6G.js +0 -1216
  89. package/dist/chunk-LGGRPKTV.cjs +0 -735
  90. package/dist/chunk-LK5IAVH6.cjs +0 -1173
  91. package/dist/chunk-LSW7P7ML.js +0 -3675
  92. package/dist/chunk-LXJ4667L.cjs +0 -3874
  93. package/dist/chunk-LZ266PCM.cjs +0 -4499
  94. package/dist/chunk-MD6KDHVE.cjs +0 -237
  95. package/dist/chunk-MEASWI2Y.js +0 -126
  96. package/dist/chunk-MPXBVFHQ.js +0 -768
  97. package/dist/chunk-N5FTS757.cjs +0 -415
  98. package/dist/chunk-NCUKG4SK.cjs +0 -3075
  99. package/dist/chunk-NDQNIJEH.js +0 -1715
  100. package/dist/chunk-NOZZ46QU.js +0 -168
  101. package/dist/chunk-OFKWH2IP.js +0 -449
  102. package/dist/chunk-PHENW4MQ.js +0 -65
  103. package/dist/chunk-PMGODDJA.cjs +0 -319
  104. package/dist/chunk-Q4QX3AET.cjs +0 -1505
  105. package/dist/chunk-Q56TT7IL.js +0 -483
  106. package/dist/chunk-Q5JT3YML.cjs +0 -129
  107. package/dist/chunk-Q5SJOGHQ.cjs +0 -4256
  108. package/dist/chunk-QGKNANZ3.js +0 -3071
  109. package/dist/chunk-QLEAOI3Q.cjs +0 -424
  110. package/dist/chunk-R7MA7QWV.js +0 -732
  111. package/dist/chunk-RVYPEYPX.js +0 -678
  112. package/dist/chunk-S2N5TNMA.js +0 -1855
  113. package/dist/chunk-S565K7NK.js +0 -752
  114. package/dist/chunk-SDAMZIRE.js +0 -765
  115. package/dist/chunk-T36DDXSF.js +0 -4250
  116. package/dist/chunk-T4NKMBDL.js +0 -5474
  117. package/dist/chunk-T7LEXZUZ.cjs +0 -2526
  118. package/dist/chunk-TEWCN33Y.js +0 -694
  119. package/dist/chunk-TQSZUOW5.cjs +0 -793
  120. package/dist/chunk-TSH3MSQU.cjs +0 -129
  121. package/dist/chunk-UERJ3YJV.js +0 -504
  122. package/dist/chunk-UPJBDCVF.js +0 -1395
  123. package/dist/chunk-V3NN3HPP.js +0 -4462
  124. package/dist/chunk-VJ3L7CHT.cjs +0 -169
  125. package/dist/chunk-WB4Z63GG.js +0 -229
  126. package/dist/chunk-WDW67DZB.cjs +0 -9728
  127. package/dist/chunk-WGMEAYBG.js +0 -126
  128. package/dist/chunk-X4ZF6CNE.cjs +0 -473
  129. package/dist/chunk-X6SEAXAX.cjs +0 -3681
  130. package/dist/chunk-XCWFGZAA.js +0 -1043
  131. package/dist/chunk-XD6IYDUX.js +0 -903
  132. package/dist/chunk-XG23EUQX.cjs +0 -1717
  133. package/dist/chunk-XRKWN5PL.cjs +0 -173
  134. package/dist/chunk-XUILI4KB.cjs +0 -430
  135. package/dist/chunk-XUTX5CBW.js +0 -126
  136. package/dist/chunk-XWPNTWDN.cjs +0 -755
  137. package/dist/chunk-XXINBTZK.cjs +0 -633
  138. package/dist/chunk-YCXFCXDS.js +0 -1868
  139. package/dist/chunk-YQK5JNFK.js +0 -3725
  140. package/dist/chunk-YYXH45E2.js +0 -426
  141. package/dist/chunk-Z34RLXRA.cjs +0 -612
  142. package/dist/chunk-ZP4D3CSX.cjs +0 -72
  143. package/dist/cli/holoscript-runner.cjs +0 -2259
  144. package/dist/cli/holoscript-runner.js +0 -2234
  145. package/dist/codebase/index.cjs +0 -336
  146. package/dist/codebase/index.js +0 -331
  147. package/dist/compiler/agent-inference.cjs +0 -28
  148. package/dist/compiler/agent-inference.js +0 -5
  149. package/dist/compiler/android-xr.cjs +0 -19
  150. package/dist/compiler/android-xr.js +0 -9
  151. package/dist/compiler/android.cjs +0 -20
  152. package/dist/compiler/android.js +0 -10
  153. package/dist/compiler/ar.cjs +0 -20
  154. package/dist/compiler/ar.js +0 -8
  155. package/dist/compiler/babylon.cjs +0 -17
  156. package/dist/compiler/babylon.js +0 -11
  157. package/dist/compiler/coco.cjs +0 -27
  158. package/dist/compiler/coco.js +0 -4
  159. package/dist/compiler/domain-block-utils.cjs +0 -602
  160. package/dist/compiler/domain-block-utils.js +0 -8
  161. package/dist/compiler/dtdl.cjs +0 -24
  162. package/dist/compiler/dtdl.js +0 -8
  163. package/dist/compiler/gltf-pipeline.cjs +0 -39
  164. package/dist/compiler/gltf-pipeline.js +0 -4
  165. package/dist/compiler/godot.cjs +0 -15
  166. package/dist/compiler/godot.js +0 -9
  167. package/dist/compiler/incremental.cjs +0 -29
  168. package/dist/compiler/incremental.js +0 -4
  169. package/dist/compiler/index.cjs +0 -2578
  170. package/dist/compiler/index.js +0 -2383
  171. package/dist/compiler/ios.cjs +0 -20
  172. package/dist/compiler/ios.js +0 -10
  173. package/dist/compiler/multi-layer.cjs +0 -20
  174. package/dist/compiler/multi-layer.js +0 -11
  175. package/dist/compiler/nodetoy.cjs +0 -23
  176. package/dist/compiler/nodetoy.js +0 -4
  177. package/dist/compiler/openxr.cjs +0 -15
  178. package/dist/compiler/openxr.js +0 -9
  179. package/dist/compiler/playcanvas.cjs +0 -16
  180. package/dist/compiler/playcanvas.js +0 -10
  181. package/dist/compiler/r3f.cjs +0 -34
  182. package/dist/compiler/r3f.js +0 -12
  183. package/dist/compiler/remotion.cjs +0 -23
  184. package/dist/compiler/remotion.js +0 -4
  185. package/dist/compiler/reproducibility.cjs +0 -39
  186. package/dist/compiler/reproducibility.js +0 -4
  187. package/dist/compiler/sdf.cjs +0 -21
  188. package/dist/compiler/sdf.js +0 -9
  189. package/dist/compiler/semantic-scene.cjs +0 -31
  190. package/dist/compiler/semantic-scene.js +0 -4
  191. package/dist/compiler/state.cjs +0 -17
  192. package/dist/compiler/state.js +0 -7
  193. package/dist/compiler/trait-composition.cjs +0 -26
  194. package/dist/compiler/trait-composition.js +0 -5
  195. package/dist/compiler/unity.cjs +0 -15
  196. package/dist/compiler/unity.js +0 -9
  197. package/dist/compiler/unreal.cjs +0 -19
  198. package/dist/compiler/unreal.js +0 -9
  199. package/dist/compiler/urdf.cjs +0 -45
  200. package/dist/compiler/urdf.js +0 -9
  201. package/dist/compiler/usd-physics.cjs +0 -23
  202. package/dist/compiler/usd-physics.js +0 -6
  203. package/dist/compiler/visionos.cjs +0 -15
  204. package/dist/compiler/visionos.js +0 -9
  205. package/dist/compiler/vrchat.cjs +0 -19
  206. package/dist/compiler/vrchat.js +0 -9
  207. package/dist/compiler/vrr.cjs +0 -21
  208. package/dist/compiler/vrr.js +0 -9
  209. package/dist/compiler/wasm.cjs +0 -33
  210. package/dist/compiler/wasm.js +0 -9
  211. package/dist/compiler/webgpu.cjs +0 -15
  212. package/dist/compiler/webgpu.js +0 -9
  213. package/dist/debugger.cjs +0 -21
  214. package/dist/debugger.js +0 -8
  215. package/dist/entries/interop.cjs +0 -62
  216. package/dist/entries/interop.js +0 -5
  217. package/dist/entries/scripting.cjs +0 -68
  218. package/dist/entries/scripting.js +0 -11
  219. package/dist/index.cjs +0 -40921
  220. package/dist/index.js +0 -37763
  221. package/dist/math/vec3.cjs +0 -57
  222. package/dist/math/vec3.js +0 -4
  223. package/dist/ml-dsa-PHCWUBPX.cjs +0 -1178
  224. package/dist/ml-dsa-WYLJHJO6.js +0 -1178
  225. package/dist/parser.cjs +0 -27
  226. package/dist/parser.js +0 -10
  227. package/dist/playwright-5OSAPTNH.js +0 -98660
  228. package/dist/playwright-RL6GY4F7.cjs +0 -98673
  229. package/dist/runtime.cjs +0 -16
  230. package/dist/runtime.js +0 -7
  231. package/dist/storage/index.cjs +0 -37
  232. package/dist/storage/index.js +0 -4
  233. package/dist/traits/index.cjs +0 -14649
  234. package/dist/traits/index.js +0 -12243
  235. package/dist/type-checker.cjs +0 -18
  236. package/dist/type-checker.js +0 -5
@@ -1,2259 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
-
4
- var chunkG7CT3EMP_cjs = require('../chunk-G7CT3EMP.cjs');
5
- var chunkTQSZUOW5_cjs = require('../chunk-TQSZUOW5.cjs');
6
- var chunkCLYEIWA5_cjs = require('../chunk-CLYEIWA5.cjs');
7
- var chunkLZ266PCM_cjs = require('../chunk-LZ266PCM.cjs');
8
- require('../chunk-GVUR45UF.cjs');
9
- require('../chunk-XG23EUQX.cjs');
10
- require('../chunk-KCQ5NDYC.cjs');
11
- require('../chunk-PMGODDJA.cjs');
12
- require('../chunk-MD6KDHVE.cjs');
13
- require('../chunk-CAUCGUEA.cjs');
14
- require('../chunk-3SAK5KFL.cjs');
15
- require('dotenv/config');
16
- var fs = require('fs');
17
- var path = require('path');
18
- var readline = require('readline');
19
- var child_process = require('child_process');
20
- var crypto = require('crypto');
21
- var runtime = require('@holoscript/engine/runtime');
22
-
23
- function _interopNamespace(e) {
24
- if (e && e.__esModule) return e;
25
- var n = Object.create(null);
26
- if (e) {
27
- Object.keys(e).forEach(function (k) {
28
- if (k !== 'default') {
29
- var d = Object.getOwnPropertyDescriptor(e, k);
30
- Object.defineProperty(n, k, d.get ? d : {
31
- enumerable: true,
32
- get: function () { return e[k]; }
33
- });
34
- }
35
- });
36
- }
37
- n.default = e;
38
- return Object.freeze(n);
39
- }
40
-
41
- var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
42
- var path__namespace = /*#__PURE__*/_interopNamespace(path);
43
- var readline__namespace = /*#__PURE__*/_interopNamespace(readline);
44
-
45
- function defaultModelForProvider(provider) {
46
- switch (provider) {
47
- case "xai":
48
- return "grok-3";
49
- case "openai":
50
- return "gpt-4.1";
51
- case "ollama":
52
- return "brittney-qwen-v23:latest";
53
- case "anthropic":
54
- default:
55
- return "claude-sonnet-4-20250514";
56
- }
57
- }
58
- function defaultToolProfileForProvider(provider) {
59
- switch (provider) {
60
- case "xai":
61
- return "grok-hsplus";
62
- case "anthropic":
63
- return "claude-hsplus";
64
- case "openai":
65
- case "ollama":
66
- default:
67
- return "standard";
68
- }
69
- }
70
- function parseProvider(value) {
71
- const normalized = value?.toLowerCase();
72
- if (normalized === "anthropic" || normalized === "xai" || normalized === "openai" || normalized === "ollama") {
73
- return normalized;
74
- }
75
- return void 0;
76
- }
77
- function parseToolProfile(value) {
78
- const normalized = value?.toLowerCase();
79
- if (normalized === "claude-hsplus" || normalized === "grok-hsplus" || normalized === "standard") {
80
- return normalized;
81
- }
82
- return void 0;
83
- }
84
- function daemonEnvDefaults() {
85
- const provider = parseProvider(process.env.HOLODAEMON_PROVIDER) || "anthropic";
86
- const toolProfile = parseToolProfile(process.env.HOLODAEMON_TOOL_PROFILE) || defaultToolProfileForProvider(provider);
87
- const model = process.env.HOLODAEMON_MODEL || defaultModelForProvider(provider);
88
- return { provider, toolProfile, model };
89
- }
90
- function parseArgs(argv) {
91
- const args = argv.slice(2);
92
- const envDefaults = daemonEnvDefaults();
93
- const opts = {
94
- command: "help",
95
- json: false,
96
- target: "headless",
97
- profile: "headless",
98
- debug: false,
99
- watch: false,
100
- daemon: false,
101
- ticks: 100,
102
- cycles: 15,
103
- commit: false,
104
- enforceGotchas: false,
105
- providerRotation: false,
106
- alwaysOn: false,
107
- cycleIntervalSec: 30,
108
- allowShell: false,
109
- allowedShellCommands: [],
110
- allowedHosts: [],
111
- allowedPaths: [],
112
- provider: envDefaults.provider,
113
- toolProfile: envDefaults.toolProfile,
114
- model: envDefaults.model,
115
- timeout: 30,
116
- sessionId: crypto.randomUUID(),
117
- // Deploy defaults
118
- share: false,
119
- author: "",
120
- license: "free",
121
- serverUrl: "https://mcp.holoscript.net",
122
- // Protocol publish defaults
123
- publish: false,
124
- mintNft: false,
125
- price: "0",
126
- walletKey: ""
127
- };
128
- let modelExplicit = false;
129
- let toolProfileExplicit = false;
130
- if (args.length === 0) return opts;
131
- const cmd = args[0];
132
- if (cmd === "run" || cmd === "test" || cmd === "compile" || cmd === "deploy" || cmd === "absorb" || cmd === "daemon" || cmd === "holodaemon" || cmd === "moltbook-daemon" || cmd === "holomesh-daemon") {
133
- opts.command = cmd;
134
- }
135
- if (opts.command === "daemon" && args[1] === "status") {
136
- opts.command = "daemon-status";
137
- }
138
- if (args[1] && !args[1].startsWith("--") && opts.command !== "daemon-status") {
139
- opts.file = args[1];
140
- }
141
- for (let i = 0; i < args.length; i++) {
142
- if (args[i] === "--target" && args[i + 1]) opts.target = args[++i];
143
- if (args[i] === "--profile" && args[i + 1]) opts.profile = args[++i];
144
- if (args[i] === "--output" && args[i + 1]) opts.output = args[++i];
145
- if (args[i] === "--tier" && args[i + 1]) {
146
- const tier = args[++i].toLowerCase();
147
- if (["low", "med", "high", "ultra"].includes(tier)) {
148
- opts.qualityTier = tier;
149
- }
150
- }
151
- if (args[i] === "--debug" || args[i] === "--verbose") opts.debug = true;
152
- if (args[i] === "--watch" || args[i] === "-w") opts.watch = true;
153
- if (args[i] === "--daemon") opts.daemon = true;
154
- if (args[i] === "--ticks" && args[i + 1]) {
155
- const parsed = Number(args[++i]);
156
- if (Number.isFinite(parsed) && parsed >= 0) {
157
- opts.ticks = Math.floor(parsed);
158
- }
159
- }
160
- if (args[i] === "--cycles" && args[i + 1]) {
161
- const parsed = Number(args[++i]);
162
- if (Number.isFinite(parsed) && parsed > 0) {
163
- opts.cycles = Math.floor(parsed);
164
- }
165
- }
166
- if (args[i] === "--commit") opts.commit = true;
167
- if (args[i] === "--trial" && args[i + 1]) {
168
- opts.trial = Number(args[++i]);
169
- }
170
- if (args[i] === "--provider" && args[i + 1]) {
171
- const provider = parseProvider(args[++i]);
172
- if (provider) {
173
- opts.provider = provider;
174
- }
175
- }
176
- if (args[i] === "--tool-profile" && args[i + 1]) {
177
- const profile = parseToolProfile(args[++i]);
178
- if (profile) {
179
- opts.toolProfile = profile;
180
- toolProfileExplicit = true;
181
- }
182
- }
183
- if (args[i] === "--model" && args[i + 1]) {
184
- opts.model = args[++i];
185
- modelExplicit = true;
186
- }
187
- if (args[i] === "--timeout" && args[i + 1]) {
188
- const parsed = Number(args[++i]);
189
- if (Number.isFinite(parsed) && parsed > 0) {
190
- opts.timeout = Math.min(120, Math.max(1, Math.floor(parsed)));
191
- }
192
- }
193
- if (args[i] === "--focus" && args[i + 1]) {
194
- opts.focus = args[++i];
195
- }
196
- if (args[i] === "--enforce-gotchas") opts.enforceGotchas = true;
197
- if (args[i] === "--provider-rotation") opts.providerRotation = true;
198
- if (args[i] === "--always-on") opts.alwaysOn = true;
199
- if (args[i] === "--allow-shell") opts.allowShell = true;
200
- if (args[i] === "--skills-dir" && args[i + 1]) opts.skillsDir = args[++i];
201
- if (args[i] === "--cycle-interval-sec" && args[i + 1]) {
202
- const parsed = Number(args[++i]);
203
- if (Number.isFinite(parsed) && parsed >= 1) {
204
- opts.cycleIntervalSec = Math.floor(parsed);
205
- }
206
- }
207
- if (args[i] === "--allow-shell-command" && args[i + 1]) {
208
- opts.allowedShellCommands.push(args[++i]);
209
- }
210
- if (args[i] === "--allow-host" && args[i + 1]) {
211
- opts.allowedHosts.push(args[++i]);
212
- }
213
- if (args[i] === "--allow-path" && args[i + 1]) {
214
- opts.allowedPaths.push(args[++i]);
215
- }
216
- if (args[i] === "--json") opts.json = true;
217
- if (args[i] === "--share") opts.share = true;
218
- if (args[i] === "--author" && args[i + 1]) opts.author = args[++i];
219
- if (args[i] === "--license" && args[i + 1]) opts.license = args[++i];
220
- if (args[i] === "--server" && args[i + 1]) opts.serverUrl = args[++i];
221
- if (args[i] === "--publish") opts.publish = true;
222
- if (args[i] === "--mint-nft") opts.mintNft = true;
223
- if (args[i] === "--price" && args[i + 1]) opts.price = args[++i];
224
- if (args[i] === "--wallet-key" && args[i + 1]) opts.walletKey = args[++i];
225
- }
226
- if (!modelExplicit) {
227
- opts.model = defaultModelForProvider(opts.provider);
228
- }
229
- if (!toolProfileExplicit) {
230
- opts.toolProfile = defaultToolProfileForProvider(opts.provider);
231
- }
232
- return opts;
233
- }
234
- function extractChatText(data) {
235
- const d = data;
236
- return d?.content?.[0]?.text ?? d?.choices?.[0]?.message?.content ?? d?.message?.content ?? d?.response ?? "";
237
- }
238
- function extractTokenUsage(data) {
239
- const d = data;
240
- const inputTokens = d?.usage?.input_tokens ?? d?.usage?.prompt_tokens ?? d?.prompt_eval_count ?? 0;
241
- const outputTokens = d?.usage?.output_tokens ?? d?.usage?.completion_tokens ?? d?.eval_count ?? 0;
242
- return {
243
- inputTokens: Number.isFinite(inputTokens) ? Number(inputTokens) : 0,
244
- outputTokens: Number.isFinite(outputTokens) ? Number(outputTokens) : 0
245
- };
246
- }
247
- function createDaemonLLMProvider(opts) {
248
- if (opts.provider === "anthropic") {
249
- return {
250
- chat: async ({ system, prompt, maxTokens }) => {
251
- const apiKey = process.env.ANTHROPIC_API_KEY;
252
- if (!apiKey) throw new Error("ANTHROPIC_API_KEY not set");
253
- const response = await fetch("https://api.anthropic.com/v1/messages", {
254
- method: "POST",
255
- headers: {
256
- "x-api-key": apiKey,
257
- "anthropic-version": "2023-06-01",
258
- "content-type": "application/json"
259
- },
260
- body: JSON.stringify({
261
- model: opts.model,
262
- max_tokens: maxTokens || 4096,
263
- system,
264
- messages: [{ role: "user", content: prompt }]
265
- })
266
- });
267
- if (!response.ok) {
268
- const body = await response.text().catch(() => "");
269
- throw new Error(`Anthropic API ${response.status}: ${body.slice(0, 200)}`);
270
- }
271
- const data = await response.json();
272
- const usage = extractTokenUsage(data);
273
- return {
274
- text: extractChatText(data),
275
- inputTokens: usage.inputTokens,
276
- outputTokens: usage.outputTokens
277
- };
278
- }
279
- };
280
- }
281
- if (opts.provider === "xai") {
282
- return {
283
- chat: async ({ system, prompt, maxTokens }) => {
284
- const apiKey = process.env.XAI_API_KEY;
285
- if (!apiKey) throw new Error("XAI_API_KEY not set");
286
- const response = await fetch("https://api.x.ai/v1/chat/completions", {
287
- method: "POST",
288
- headers: {
289
- Authorization: `Bearer ${apiKey}`,
290
- "content-type": "application/json"
291
- },
292
- body: JSON.stringify({
293
- model: opts.model,
294
- max_tokens: maxTokens || 4096,
295
- temperature: 0.2,
296
- messages: [
297
- { role: "system", content: system },
298
- { role: "user", content: prompt }
299
- ]
300
- })
301
- });
302
- if (!response.ok) {
303
- const body = await response.text().catch(() => "");
304
- throw new Error(`xAI API ${response.status}: ${body.slice(0, 200)}`);
305
- }
306
- const data = await response.json();
307
- const usage = extractTokenUsage(data);
308
- return {
309
- text: extractChatText(data),
310
- inputTokens: usage.inputTokens,
311
- outputTokens: usage.outputTokens
312
- };
313
- }
314
- };
315
- }
316
- if (opts.provider === "openai") {
317
- return {
318
- chat: async ({ system, prompt, maxTokens }) => {
319
- const apiKey = process.env.OPENAI_API_KEY;
320
- if (!apiKey) throw new Error("OPENAI_API_KEY not set");
321
- const baseUrl = process.env.OPENAI_BASE_URL || "https://api.openai.com/v1";
322
- const response = await fetch(`${baseUrl}/chat/completions`, {
323
- method: "POST",
324
- headers: {
325
- Authorization: `Bearer ${apiKey}`,
326
- "content-type": "application/json"
327
- },
328
- body: JSON.stringify({
329
- model: opts.model,
330
- max_tokens: maxTokens || 4096,
331
- temperature: 0.2,
332
- messages: [
333
- { role: "system", content: system },
334
- { role: "user", content: prompt }
335
- ]
336
- })
337
- });
338
- if (!response.ok) {
339
- const body = await response.text().catch(() => "");
340
- throw new Error(`OpenAI API ${response.status}: ${body.slice(0, 200)}`);
341
- }
342
- const data = await response.json();
343
- const usage = extractTokenUsage(data);
344
- return {
345
- text: extractChatText(data),
346
- inputTokens: usage.inputTokens,
347
- outputTokens: usage.outputTokens
348
- };
349
- }
350
- };
351
- }
352
- return {
353
- chat: async ({ system, prompt }) => {
354
- const baseUrl = process.env.OLLAMA_BASE_URL || process.env.OLLAMA_URL;
355
- if (!baseUrl) throw new Error("Ollama selected but OLLAMA_BASE_URL/OLLAMA_URL not set. Use --provider anthropic|xai|openai or set OLLAMA_BASE_URL in .env");
356
- const response = await fetch(`${baseUrl}/api/generate`, {
357
- method: "POST",
358
- headers: { "content-type": "application/json" },
359
- body: JSON.stringify({
360
- model: opts.model,
361
- system,
362
- prompt,
363
- stream: false,
364
- options: {
365
- temperature: 0.2
366
- }
367
- })
368
- });
369
- if (!response.ok) {
370
- const body = await response.text().catch(() => "");
371
- throw new Error(`Ollama API ${response.status}: ${body.slice(0, 200)}`);
372
- }
373
- const data = await response.json();
374
- const usage = extractTokenUsage(data);
375
- return {
376
- text: extractChatText(data),
377
- inputTokens: usage.inputTokens,
378
- outputTokens: usage.outputTokens
379
- };
380
- }
381
- };
382
- }
383
- function createNodeHostCapabilities(cwd) {
384
- return {
385
- fileSystem: {
386
- readFile: (filePath) => fs__namespace.readFileSync(path__namespace.resolve(cwd, filePath), "utf-8"),
387
- writeFile: (filePath, content) => {
388
- fs__namespace.writeFileSync(path__namespace.resolve(cwd, filePath), content, "utf-8");
389
- },
390
- deleteFile: (filePath) => {
391
- fs__namespace.rmSync(path__namespace.resolve(cwd, filePath), { force: true });
392
- },
393
- exists: (filePath) => fs__namespace.existsSync(path__namespace.resolve(cwd, filePath))
394
- },
395
- process: {
396
- exec: (command, args = [], options) => new Promise((resolve2, reject) => {
397
- const child = child_process.spawn(command, args, {
398
- cwd: options?.cwd ?? cwd,
399
- env: { ...process.env, ...options?.env ?? {} },
400
- shell: true,
401
- stdio: ["ignore", "pipe", "pipe"]
402
- });
403
- let stdout = "";
404
- let stderr = "";
405
- let timeoutHandle = null;
406
- child.stdout?.on("data", (data) => {
407
- stdout += data.toString("utf-8");
408
- });
409
- child.stderr?.on("data", (data) => {
410
- stderr += data.toString("utf-8");
411
- });
412
- if (options?.timeoutMs && options.timeoutMs > 0) {
413
- timeoutHandle = setTimeout(() => {
414
- try {
415
- child.kill("SIGKILL");
416
- } catch {
417
- }
418
- }, options.timeoutMs);
419
- }
420
- child.on("close", (code, signal) => {
421
- if (timeoutHandle) clearTimeout(timeoutHandle);
422
- resolve2({ code, signal, stdout, stderr });
423
- });
424
- child.on("error", (error) => {
425
- if (timeoutHandle) clearTimeout(timeoutHandle);
426
- reject(error);
427
- });
428
- })
429
- },
430
- network: {
431
- fetch: async (url, options) => {
432
- if (typeof fetch === "undefined") {
433
- throw new Error("fetch is not available in this runtime");
434
- }
435
- const response = await fetch(url, {
436
- method: options?.method,
437
- headers: options?.headers,
438
- body: options?.body,
439
- credentials: options?.credentials
440
- });
441
- const headers = {};
442
- response.headers.forEach((value, key) => {
443
- headers[key.toLowerCase()] = value;
444
- });
445
- const contentType = headers["content-type"] ?? "";
446
- let body;
447
- let text;
448
- let json;
449
- if (contentType.includes("application/json")) {
450
- try {
451
- json = await response.json();
452
- body = json;
453
- } catch {
454
- text = await response.text();
455
- body = text;
456
- }
457
- } else {
458
- text = await response.text();
459
- body = text;
460
- }
461
- return {
462
- status: response.status,
463
- ok: response.ok,
464
- headers,
465
- body,
466
- text,
467
- json
468
- };
469
- }
470
- }
471
- };
472
- }
473
- function runTicks(runtime, count) {
474
- for (let i = 0; i < count; i++) {
475
- runtime.tick();
476
- }
477
- }
478
- async function runDaemon(runtime, opts) {
479
- const supportsEvents = typeof runtime.emit === "function";
480
- const supportsStats = typeof runtime.getStats === "function";
481
- const supportsActionRegistry = typeof runtime.registerAction === "function";
482
- const supportsSubscriptions = typeof runtime.on === "function";
483
- const pendingActionResolutions = /* @__PURE__ */ new Map();
484
- const registeredActions = /* @__PURE__ */ new Set();
485
- let nextActionId = 1;
486
- const send = (message) => {
487
- process.stdout.write(`${JSON.stringify(message)}
488
- `);
489
- };
490
- const unsubscribeActionResult = supportsSubscriptions ? runtime.on("action:result", (payload) => {
491
- send({
492
- type: "daemon:action_result",
493
- payload
494
- });
495
- }) : () => {
496
- };
497
- send({
498
- type: "daemon:ready",
499
- profile: opts.profile,
500
- supportsEvents,
501
- supportsStats,
502
- supportsActionRegistry
503
- });
504
- const rl = readline__namespace.createInterface({
505
- input: process.stdin,
506
- output: process.stdout,
507
- terminal: false
508
- });
509
- const close = () => {
510
- for (const [, pending] of pendingActionResolutions) {
511
- clearTimeout(pending.timer);
512
- pending.reject(new Error("Daemon shutting down"));
513
- }
514
- pendingActionResolutions.clear();
515
- try {
516
- unsubscribeActionResult();
517
- } catch {
518
- }
519
- try {
520
- runtime.stop();
521
- } catch {
522
- }
523
- rl.close();
524
- };
525
- process.once("SIGINT", () => {
526
- send({ type: "daemon:stopped", reason: "SIGINT" });
527
- close();
528
- });
529
- process.once("SIGTERM", () => {
530
- send({ type: "daemon:stopped", reason: "SIGTERM" });
531
- close();
532
- });
533
- rl.on("line", (line) => {
534
- const raw = line.trim();
535
- if (!raw) return;
536
- let command;
537
- try {
538
- command = JSON.parse(raw);
539
- } catch {
540
- send({ type: "daemon:error", error: "Invalid JSON command" });
541
- return;
542
- }
543
- const op = command?.op;
544
- switch (op) {
545
- case "tick": {
546
- const count = Number.isFinite(command?.count) ? Math.max(0, Math.floor(command.count)) : 1;
547
- runTicks(runtime, count);
548
- send({ type: "daemon:ok", op, ticked: count, stats: runtime.getStats?.() });
549
- break;
550
- }
551
- case "emit": {
552
- if (!supportsEvents) {
553
- send({ type: "daemon:error", op, error: "Runtime does not expose emit()" });
554
- break;
555
- }
556
- runtime.emit(command.event, command.payload);
557
- send({ type: "daemon:ok", op, event: command.event });
558
- break;
559
- }
560
- case "state:get": {
561
- const key = command?.key;
562
- const value = typeof key === "string" ? runtime.getState(key) : runtime.getAllState?.();
563
- send({ type: "daemon:ok", op, key, value });
564
- break;
565
- }
566
- case "state:set": {
567
- const key = command?.key;
568
- if (typeof key === "string") {
569
- runtime.setState(key, command.value);
570
- send({ type: "daemon:ok", op, key });
571
- } else {
572
- send({ type: "daemon:error", op, error: "state:set requires string key" });
573
- }
574
- break;
575
- }
576
- case "stats": {
577
- send({ type: "daemon:ok", op, stats: runtime.getStats?.() });
578
- break;
579
- }
580
- case "action:register": {
581
- if (!supportsActionRegistry) {
582
- send({ type: "daemon:error", op, error: "Runtime does not expose registerAction()" });
583
- break;
584
- }
585
- const actionName = command?.name;
586
- if (typeof actionName !== "string" || actionName.trim() === "") {
587
- send({ type: "daemon:error", op, error: "action:register requires non-empty name" });
588
- break;
589
- }
590
- runtime.registerAction(
591
- actionName,
592
- (params, blackboard) => {
593
- const actionRequestId = `daemon-action-${nextActionId++}`;
594
- const timeoutMs = Number.isFinite(command?.timeoutMs) ? Math.max(1, Math.floor(command.timeoutMs)) : 3e4;
595
- return new Promise((resolve2, reject) => {
596
- const timer = setTimeout(() => {
597
- pendingActionResolutions.delete(actionRequestId);
598
- resolve2(false);
599
- send({
600
- type: "daemon:action_timeout",
601
- action: actionName,
602
- actionRequestId,
603
- timeoutMs
604
- });
605
- }, timeoutMs);
606
- pendingActionResolutions.set(actionRequestId, {
607
- resolve: resolve2,
608
- reject,
609
- timer,
610
- runtimeRequestId: actionRequestId,
611
- actionName
612
- });
613
- send({
614
- type: "daemon:action_request",
615
- action: actionName,
616
- actionRequestId,
617
- params,
618
- blackboard
619
- });
620
- });
621
- }
622
- );
623
- registeredActions.add(actionName);
624
- send({ type: "daemon:ok", op, name: actionName });
625
- break;
626
- }
627
- case "action:list": {
628
- send({
629
- type: "daemon:ok",
630
- op,
631
- actions: [...registeredActions],
632
- pending: pendingActionResolutions.size
633
- });
634
- break;
635
- }
636
- case "action:reply": {
637
- const actionRequestId = command?.actionRequestId;
638
- if (typeof actionRequestId !== "string") {
639
- send({ type: "daemon:error", op, error: "action:reply requires actionRequestId" });
640
- break;
641
- }
642
- const pending = pendingActionResolutions.get(actionRequestId);
643
- if (!pending) {
644
- send({ type: "daemon:error", op, error: `Unknown actionRequestId: ${actionRequestId}` });
645
- break;
646
- }
647
- clearTimeout(pending.timer);
648
- pendingActionResolutions.delete(actionRequestId);
649
- const status = command?.status;
650
- const success = typeof command?.success === "boolean" ? command.success : status === "success" || status === "true";
651
- pending.resolve(Boolean(success));
652
- send({ type: "daemon:ok", op, actionRequestId, success: Boolean(success) });
653
- break;
654
- }
655
- case "action:unregister": {
656
- if (!supportsActionRegistry) {
657
- send({ type: "daemon:error", op, error: "Runtime does not expose registerAction()" });
658
- break;
659
- }
660
- const actionName = command?.name;
661
- if (typeof actionName !== "string" || actionName.trim() === "") {
662
- send({ type: "daemon:error", op, error: "action:unregister requires non-empty name" });
663
- break;
664
- }
665
- runtime.registerAction(actionName, () => false);
666
- registeredActions.delete(actionName);
667
- send({ type: "daemon:ok", op, name: actionName });
668
- break;
669
- }
670
- case "stop": {
671
- send({ type: "daemon:stopped", reason: "command" });
672
- close();
673
- break;
674
- }
675
- default:
676
- send({ type: "daemon:error", error: `Unknown op: ${String(op)}` });
677
- }
678
- });
679
- await new Promise((resolve2) => {
680
- rl.once("close", () => resolve2());
681
- });
682
- }
683
- async function runScript(opts) {
684
- if (!opts.file) {
685
- console.error("Error: No input file specified");
686
- process.exit(1);
687
- }
688
- const filePath = path__namespace.resolve(opts.file);
689
- if (!fs__namespace.existsSync(filePath)) {
690
- console.error(`Error: File not found: ${filePath}`);
691
- process.exit(1);
692
- }
693
- const source = fs__namespace.readFileSync(filePath, "utf-8");
694
- const ext = path__namespace.extname(filePath);
695
- console.log(`[holoscript] Running ${path__namespace.basename(filePath)} (target: ${opts.target})`);
696
- const parseResult = chunkLZ266PCM_cjs.parse(source);
697
- const ast = parseResult.ast;
698
- if (opts.debug) {
699
- console.log(`[holoscript] Parsed ${ast.body?.length || 0} top-level nodes`);
700
- console.log(`[holoscript] File type: ${ext}`);
701
- }
702
- const profile = opts.profile === "headless" ? runtime.HEADLESS_PROFILE : runtime.getProfile(opts.profile);
703
- const runtime$1 = runtime.createHeadlessRuntime(ast, {
704
- profile,
705
- tickRate: 10,
706
- debug: opts.debug,
707
- hostCapabilities: createNodeHostCapabilities(path__namespace.dirname(filePath))
708
- });
709
- chunkG7CT3EMP_cjs.registerStdlib(
710
- runtime$1,
711
- {
712
- policy: {
713
- rootDir: path__namespace.dirname(filePath),
714
- allowedPaths: opts.allowedPaths.length > 0 ? opts.allowedPaths : ["compositions", "data", "src", "packages"],
715
- maxFileBytes: 2 * 1024 * 1024,
716
- allowShell: opts.allowShell,
717
- allowedShellCommands: opts.allowedShellCommands,
718
- maxShellOutputBytes: 100 * 1024,
719
- shellTimeoutMs: 6e4,
720
- allowNetwork: opts.allowedHosts.length > 0,
721
- allowedHosts: opts.allowedHosts
722
- },
723
- hostCapabilities: createNodeHostCapabilities(path__namespace.dirname(filePath))
724
- }
725
- );
726
- new chunkCLYEIWA5_cjs.InteropContext(path__namespace.dirname(filePath));
727
- if (opts.debug) {
728
- console.log(`[holoscript] Profile: ${profile.name}`);
729
- console.log(`[holoscript] Interop context: ${path__namespace.dirname(filePath)}`);
730
- }
731
- runtime$1.start();
732
- if (opts.daemon) {
733
- if (opts.debug) {
734
- console.log("[holoscript] Entering daemon mode");
735
- }
736
- await runDaemon(runtime$1, opts);
737
- return;
738
- }
739
- runTicks(runtime$1, opts.ticks);
740
- runtime$1.stop();
741
- const stats = runtime$1.getStats();
742
- console.log(
743
- `[holoscript] Complete \u2014 ${stats.tickCount} ticks, ${stats.nodesProcessed} nodes processed`
744
- );
745
- if (opts.watch) {
746
- console.log(`[holoscript] Watching for changes... (Ctrl+C to stop)`);
747
- const watcher = new chunkTQSZUOW5_cjs.HotReloadWatcher({
748
- watchPaths: [path__namespace.dirname(filePath)],
749
- extensions: [".hs", ".hsplus", ".holo"],
750
- debounceMs: 300,
751
- mode: "soft"
752
- });
753
- watcher.on("reload", async (event) => {
754
- console.log(`
755
- [holoscript] File changed: ${path__namespace.basename(event.filePath)}`);
756
- console.log(`[holoscript] Re-running ${path__namespace.basename(filePath)}...`);
757
- try {
758
- const newSource = fs__namespace.readFileSync(filePath, "utf-8");
759
- const newParseResult = chunkLZ266PCM_cjs.parse(newSource);
760
- const newAst = newParseResult.ast;
761
- const newRuntime = runtime.createHeadlessRuntime(newAst, {
762
- profile: opts.profile === "headless" ? runtime.HEADLESS_PROFILE : runtime.getProfile(opts.profile),
763
- tickRate: 10,
764
- debug: opts.debug,
765
- hostCapabilities: createNodeHostCapabilities(path__namespace.dirname(filePath))
766
- });
767
- newRuntime.start();
768
- runTicks(newRuntime, opts.ticks);
769
- newRuntime.stop();
770
- const newStats = newRuntime.getStats();
771
- console.log(
772
- `[holoscript] Complete \u2014 ${newStats.tickCount} ticks, ${newStats.nodesProcessed} nodes`
773
- );
774
- } catch (err) {
775
- console.error(`[holoscript] Error:`, err.message);
776
- }
777
- });
778
- watcher.start();
779
- await new Promise(() => {
780
- });
781
- }
782
- }
783
- async function testScript(opts) {
784
- if (!opts.file) {
785
- console.error("Error: No test file specified");
786
- process.exit(1);
787
- }
788
- const filePath = path__namespace.resolve(opts.file);
789
- if (!fs__namespace.existsSync(filePath)) {
790
- console.error(`Error: File not found: ${filePath}`);
791
- process.exit(1);
792
- }
793
- const source = fs__namespace.readFileSync(filePath, "utf-8");
794
- console.log(`[holoscript test] Running tests in ${path__namespace.basename(filePath)}`);
795
- const parseResult = chunkLZ266PCM_cjs.parse(source);
796
- const ast = parseResult.ast;
797
- const profile = runtime.HEADLESS_PROFILE;
798
- const runtime$1 = runtime.createHeadlessRuntime(ast, { profile, tickRate: 10, debug: opts.debug });
799
- runtime$1.start();
800
- for (let i = 0; i < 50; i++) runtime$1.tick();
801
- const runner = new chunkTQSZUOW5_cjs.ScriptTestRunner({
802
- debug: opts.debug,
803
- runtimeState: runtime$1.getState()
804
- });
805
- const scriptResults = runner.runTestsFromSource(source, filePath);
806
- const runtimeState = runtime$1.getState();
807
- const compositionState = Object.keys(runtimeState).length > 0 ? runtimeState : chunkG7CT3EMP_cjs.CompositionTestRunner.extractStateFromSource(source);
808
- const computedDefs = chunkG7CT3EMP_cjs.CompositionTestRunner.extractComputedFromSource(source);
809
- const compositionRunner = new chunkG7CT3EMP_cjs.CompositionTestRunner(compositionState, computedDefs, {
810
- debug: opts.debug
811
- });
812
- const compositionResults = compositionRunner.runTestsFromSource(source);
813
- const results = [...scriptResults, ...compositionResults];
814
- const passed = results.filter((r) => r.status === "passed").length;
815
- const failed = results.filter((r) => r.status === "failed").length;
816
- const skipped = results.filter((r) => r.status === "skipped").length;
817
- console.log("");
818
- for (const result of results) {
819
- const icon = result.status === "passed" ? "\u2713" : result.status === "failed" ? "\u2717" : "\u25CB";
820
- const color = result.status === "passed" ? "\x1B[32m" : result.status === "failed" ? "\x1B[31m" : "\x1B[33m";
821
- console.log(` ${color}${icon}\x1B[0m ${result.name} (${result.durationMs}ms)`);
822
- if (result.error) {
823
- console.log(` \x1B[31m${result.error}\x1B[0m`);
824
- }
825
- }
826
- console.log("");
827
- console.log(
828
- `Tests: ${passed} passed, ${failed} failed, ${skipped} skipped (${results.length} total)`
829
- );
830
- if (failed > 0) process.exit(1);
831
- }
832
- function compileScript(opts) {
833
- if (!opts.file) {
834
- console.error("Error: No input file specified");
835
- process.exit(1);
836
- }
837
- const filePath = path__namespace.resolve(opts.file);
838
- if (!fs__namespace.existsSync(filePath)) {
839
- console.error(`Error: File not found: ${filePath}`);
840
- process.exit(1);
841
- }
842
- const source = fs__namespace.readFileSync(filePath, "utf-8");
843
- if (opts.enforceGotchas) {
844
- const gotchaRe = /@gotcha\s*\{([^}]+)\}/g;
845
- let gMatch;
846
- const criticals = [];
847
- while ((gMatch = gotchaRe.exec(source)) !== null) {
848
- const block = gMatch[1];
849
- const sevMatch = block.match(/severity:\s*"([^"]*)"/i);
850
- const severity = sevMatch?.[1] || "warning";
851
- if (severity === "critical") {
852
- const warnMatch = block.match(/warning:\s*"([^"]*)"/i);
853
- const mitMatch = block.match(/mitigation:\s*"([^"]*)"/i);
854
- criticals.push({
855
- warning: warnMatch?.[1] || "Unknown critical gotcha",
856
- mitigation: mitMatch?.[1] || "No mitigation specified"
857
- });
858
- }
859
- }
860
- if (criticals.length > 0) {
861
- console.error(
862
- `[holoscript compile] BLOCKED by ${criticals.length} critical @gotcha violation(s):`
863
- );
864
- for (const g of criticals) {
865
- console.error(` \u2717 ${g.warning}`);
866
- console.error(` mitigation: ${g.mitigation}`);
867
- }
868
- process.exit(1);
869
- }
870
- console.log(`[holoscript compile] @gotcha check passed (no critical violations)`);
871
- }
872
- const compileResult = chunkLZ266PCM_cjs.parse(source);
873
- if (!compileResult.success) {
874
- console.error(`[holoscript compile] Failed to parse: ${compileResult.errors?.[0]?.message}`);
875
- process.exit(1);
876
- }
877
- const ast = compileResult.ast;
878
- const outputPath = opts.output || filePath.replace(/\.(hs|hsplus|holo)$/, `.${opts.target === "python" ? "py" : "js"}`);
879
- console.log(
880
- `[holoscript compile] ${path__namespace.basename(filePath)} \u2192 ${opts.target} \u2192 ${path__namespace.basename(outputPath)}`
881
- );
882
- let output;
883
- switch (opts.target) {
884
- case "node":
885
- output = generateNodeTarget(ast);
886
- break;
887
- case "python":
888
- output = generatePythonTarget(ast);
889
- break;
890
- default:
891
- output = JSON.stringify(ast, null, 2);
892
- }
893
- fs__namespace.writeFileSync(outputPath, output, "utf-8");
894
- console.log(`[holoscript compile] Written to ${outputPath}`);
895
- }
896
- function generateNodeTarget(ast) {
897
- const lines = [
898
- "// Auto-generated by holoscript compile --target node",
899
- "// Source: HoloScript composition",
900
- `"use strict";`,
901
- ""
902
- ];
903
- if (ast.root && ast.root.children) {
904
- for (const node of ast.root.children) {
905
- if (node.type === "composition" || node.type === "ObjectDeclaration") {
906
- const name = node.name || "default";
907
- lines.push(`// ${node.type}: ${name}`);
908
- lines.push(`module.exports.${name} = ${JSON.stringify(node, null, 2)};`);
909
- lines.push("");
910
- }
911
- }
912
- }
913
- return lines.join("\n");
914
- }
915
- function generatePythonTarget(ast) {
916
- const lines = [
917
- "# Auto-generated by holoscript compile --target python",
918
- "# Source: HoloScript composition",
919
- "import json",
920
- ""
921
- ];
922
- if (ast.root && ast.root.children) {
923
- for (const node of ast.root.children) {
924
- if (node.type === "composition" || node.type === "ObjectDeclaration") {
925
- const name = node.name || "default_obj";
926
- lines.push(`# ${node.type}: ${name}`);
927
- lines.push(`${name} = json.loads('''${JSON.stringify(node)}''')`);
928
- lines.push("");
929
- }
930
- }
931
- }
932
- return lines.join("\n");
933
- }
934
- async function deployScript(opts) {
935
- if (!opts.file) {
936
- console.error("Error: No source file specified");
937
- console.error(
938
- "Usage: holoscript deploy <file> [--share] [--publish] [--price <eth>] [--mint-nft] [--author <name>] [--license <type>] [--server <url>]"
939
- );
940
- process.exit(1);
941
- }
942
- const filePath = path__namespace.resolve(opts.file);
943
- if (!fs__namespace.existsSync(filePath)) {
944
- console.error(`Error: File not found: ${filePath}`);
945
- process.exit(1);
946
- }
947
- const source = fs__namespace.readFileSync(filePath, "utf-8");
948
- const fileName = path__namespace.basename(filePath);
949
- const title = path__namespace.basename(filePath, path__namespace.extname(filePath));
950
- console.log(`Parsing ${fileName}...`);
951
- const ast = chunkLZ266PCM_cjs.parse(source);
952
- if (ast.errors && ast.errors.length > 0) {
953
- console.error("Parse errors:");
954
- for (const err of ast.errors) {
955
- console.error(` ${err.message || err}`);
956
- }
957
- process.exit(1);
958
- }
959
- const license = opts.license || "free";
960
- const provenance = chunkG7CT3EMP_cjs.generateProvenance(source, ast, {
961
- author: opts.author || "anonymous",
962
- license
963
- });
964
- console.log(
965
- `Provenance: ${provenance.publishMode} | hash: ${provenance.hash.slice(0, 12)}... | license: ${provenance.license}`
966
- );
967
- if (provenance.imports.length > 0) {
968
- const importedLicenses = provenance.imports.map((imp) => ({
969
- path: imp.path,
970
- license: "free"
971
- }));
972
- const licenseCheck = chunkG7CT3EMP_cjs.checkLicenseCompatibility(license, importedLicenses);
973
- if (licenseCheck.warnings.length > 0) {
974
- for (const w of licenseCheck.warnings) {
975
- console.log(` Warning: ${w}`);
976
- }
977
- }
978
- if (!licenseCheck.compatible) {
979
- console.error("License compatibility errors:");
980
- for (const e of licenseCheck.errors) {
981
- console.error(` ${e}`);
982
- }
983
- process.exit(1);
984
- }
985
- if (licenseCheck.forcedLicense) {
986
- console.log(` License forced to "${licenseCheck.forcedLicense}" by imports`);
987
- }
988
- }
989
- const serverUrl = opts.serverUrl.replace(/\/$/, "");
990
- if (opts.publish) {
991
- const priceWei = chunkG7CT3EMP_cjs.ethToWei(opts.price || "0");
992
- const importChain = provenance.imports.map((imp, i) => ({
993
- contentHash: imp.hash || `import-${i}`,
994
- author: imp.author || imp.path,
995
- depth: 1,
996
- children: []
997
- }));
998
- const revenuePreview = chunkG7CT3EMP_cjs.calculateRevenueDistribution(
999
- priceWei,
1000
- provenance.author || "anonymous",
1001
- importChain
1002
- );
1003
- console.log("\nRevenue distribution:");
1004
- for (const line of chunkG7CT3EMP_cjs.formatRevenueDistribution(revenuePreview)) {
1005
- console.log(` ${line}`);
1006
- }
1007
- console.log(`
1008
- Publishing to protocol at ${serverUrl}...`);
1009
- const metadataBody = JSON.stringify({
1010
- contentHash: provenance.hash,
1011
- provenance: {
1012
- hash: provenance.hash,
1013
- author: provenance.author,
1014
- license: provenance.license,
1015
- publishMode: provenance.publishMode,
1016
- imports: provenance.imports,
1017
- created: provenance.created
1018
- }
1019
- });
1020
- try {
1021
- const metaRes = await fetch(`${serverUrl}/api/protocol/metadata`, {
1022
- method: "POST",
1023
- headers: { "Content-Type": "application/json" },
1024
- body: metadataBody
1025
- });
1026
- if (!metaRes.ok) {
1027
- const text = await metaRes.text();
1028
- console.error(`Metadata storage failed (${metaRes.status}): ${text}`);
1029
- process.exit(1);
1030
- }
1031
- } catch (err) {
1032
- const msg = err instanceof Error ? err.message : String(err);
1033
- console.error(`Metadata storage failed: ${msg}`);
1034
- process.exit(1);
1035
- }
1036
- const protocolBody = JSON.stringify({
1037
- contentHash: provenance.hash,
1038
- author: provenance.author || "anonymous",
1039
- importHashes: provenance.imports.map((imp) => imp.hash).filter(Boolean),
1040
- license: provenance.license,
1041
- publishMode: provenance.publishMode,
1042
- price: opts.price || "0",
1043
- referralBps: chunkG7CT3EMP_cjs.PROTOCOL_CONSTANTS.DEFAULT_REFERRAL_BPS,
1044
- metadataURI: `${serverUrl}/metadata/${provenance.hash}`,
1045
- mintAsNFT: opts.mintNft,
1046
- // Include scene data for CDN deploy
1047
- code: source,
1048
- title,
1049
- description: `Published from CLI: ${fileName}`
1050
- });
1051
- try {
1052
- const pubRes = await fetch(`${serverUrl}/api/protocol`, {
1053
- method: "POST",
1054
- headers: { "Content-Type": "application/json" },
1055
- body: protocolBody
1056
- });
1057
- if (!pubRes.ok) {
1058
- const text = await pubRes.text();
1059
- console.error(`Protocol publish failed (${pubRes.status}): ${text}`);
1060
- process.exit(1);
1061
- }
1062
- const pubResult = await pubRes.json();
1063
- console.log("\nPublished to HoloScript Protocol!");
1064
- console.log(` Hash: ${pubResult.contentHash}`);
1065
- console.log(` ID: ${pubResult.protocolId}`);
1066
- console.log(` Collect: ${pubResult.collectUrl}`);
1067
- console.log(` Registry: ${pubResult.registryUrl}`);
1068
- if (pubResult.sceneUrl) {
1069
- console.log(` Scene: ${pubResult.sceneUrl}`);
1070
- }
1071
- if (pubResult.embedUrl) {
1072
- console.log(` Embed: ${pubResult.embedUrl}`);
1073
- }
1074
- if (priceWei > 0n) {
1075
- console.log(` Price: ${opts.price} ETH`);
1076
- } else {
1077
- console.log(" Price: Free collect");
1078
- }
1079
- if (opts.mintNft) {
1080
- console.log(" NFT: Zora mint requested");
1081
- }
1082
- } catch (err) {
1083
- const msg = err instanceof Error ? err.message : String(err);
1084
- console.error(`Protocol publish failed: ${msg}`);
1085
- console.error(
1086
- "Is the server running? Try: holoscript deploy <file> --publish --server http://localhost:3000"
1087
- );
1088
- process.exit(1);
1089
- }
1090
- return;
1091
- }
1092
- const endpoint = `${serverUrl}/api/deploy`;
1093
- console.log(`Deploying to ${serverUrl}...`);
1094
- const body = JSON.stringify({
1095
- code: source,
1096
- title,
1097
- description: `Deployed from CLI: ${fileName}`,
1098
- author: provenance.author,
1099
- license: provenance.license,
1100
- provenance: {
1101
- hash: provenance.hash,
1102
- publishMode: provenance.publishMode,
1103
- imports: provenance.imports
1104
- }
1105
- });
1106
- try {
1107
- const res = await fetch(endpoint, {
1108
- method: "POST",
1109
- headers: { "Content-Type": "application/json" },
1110
- body
1111
- });
1112
- if (!res.ok) {
1113
- const text = await res.text();
1114
- console.error(`Deploy failed (${res.status}): ${text}`);
1115
- process.exit(1);
1116
- }
1117
- const result = await res.json();
1118
- console.log("\nDeployed successfully!");
1119
- console.log(` ID: ${result.id}`);
1120
- console.log(` URL: ${result.url}`);
1121
- console.log(` Embed: ${result.embed}`);
1122
- console.log(` API: ${result.api}`);
1123
- if (result.provenance) {
1124
- console.log(` Mode: ${result.provenance.publishMode}`);
1125
- console.log(` Hash: ${result.provenance.hash}`);
1126
- }
1127
- if (opts.share) {
1128
- console.log(`
1129
- Share URL: ${result.url}`);
1130
- }
1131
- } catch (err) {
1132
- const msg = err instanceof Error ? err.message : String(err);
1133
- console.error(`Deploy failed: ${msg}`);
1134
- console.error(
1135
- "Is the server running? Try: holoscript deploy <file> --server http://localhost:3000"
1136
- );
1137
- process.exit(1);
1138
- }
1139
- }
1140
- function absorbScript(opts) {
1141
- if (!opts.file) {
1142
- console.error("Error: No source file specified");
1143
- process.exit(1);
1144
- }
1145
- const filePath = path__namespace.resolve(opts.file);
1146
- if (!fs__namespace.existsSync(filePath)) {
1147
- console.error(`Error: File not found: ${filePath}`);
1148
- process.exit(1);
1149
- }
1150
- const content = fs__namespace.readFileSync(filePath, "utf-8");
1151
- const ext = path__namespace.extname(filePath).toLowerCase();
1152
- const langMap = {
1153
- ".py": "python",
1154
- ".ts": "typescript",
1155
- ".tsx": "typescript",
1156
- ".js": "javascript",
1157
- ".jsx": "javascript",
1158
- ".mjs": "javascript"
1159
- };
1160
- const language = langMap[ext];
1161
- if (!language) {
1162
- console.error(
1163
- `Error: Unsupported file type '${ext}'. Supported: .py, .ts, .tsx, .js, .jsx, .mjs`
1164
- );
1165
- process.exit(1);
1166
- }
1167
- const outputPath = opts.output || filePath.replace(/\.\w+$/, ".hsplus");
1168
- console.log(
1169
- `[holoscript absorb] ${path__namespace.basename(filePath)} (${language}) \u2192 ${path__namespace.basename(outputPath)}`
1170
- );
1171
- const processor = new chunkTQSZUOW5_cjs.AbsorbProcessor();
1172
- const result = processor.absorb({ language, filePath, content });
1173
- fs__namespace.writeFileSync(outputPath, result.generatedHSPlus, "utf-8");
1174
- console.log(`[holoscript absorb] Extracted:`);
1175
- console.log(` ${result.functions.length} functions`);
1176
- console.log(` ${result.classes.length} classes`);
1177
- console.log(` ${result.imports.length} imports`);
1178
- console.log(` ${result.constants.length} constants`);
1179
- if (result.warnings.length > 0) {
1180
- console.log(`
1181
- Warnings:`);
1182
- for (const w of result.warnings) {
1183
- console.log(` \u26A0 ${w}`);
1184
- }
1185
- }
1186
- console.log(`[holoscript absorb] Written to ${outputPath}`);
1187
- }
1188
- function findGitRoot(startDir) {
1189
- let dir = startDir;
1190
- while (dir !== path__namespace.dirname(dir)) {
1191
- if (fs__namespace.existsSync(path__namespace.join(dir, ".git"))) return dir;
1192
- dir = path__namespace.dirname(dir);
1193
- }
1194
- return startDir;
1195
- }
1196
- function sleep(ms) {
1197
- return new Promise((resolve2) => setTimeout(resolve2, ms));
1198
- }
1199
- function extractEconomyConfig(ast) {
1200
- const result = {};
1201
- let found = false;
1202
- function walk(node) {
1203
- if (!node || typeof node !== "object") return;
1204
- const obj = node;
1205
- if (Array.isArray(obj.traits)) {
1206
- for (const trait of obj.traits) {
1207
- const t = trait;
1208
- if (t.name === "economy" && typeof t.config === "object" && t.config) {
1209
- const cfg = t.config;
1210
- if (typeof cfg.budget === "number") result.budget = cfg.budget;
1211
- if (typeof cfg.default_spend_limit === "number")
1212
- result.default_spend_limit = cfg.default_spend_limit;
1213
- if (typeof cfg.initial_balance === "number") result.initial_balance = cfg.initial_balance;
1214
- if (typeof cfg.task_completion_reward === "number")
1215
- result.task_completion_reward = cfg.task_completion_reward;
1216
- found = true;
1217
- }
1218
- }
1219
- }
1220
- if (Array.isArray(obj.directives)) {
1221
- for (const dir of obj.directives) {
1222
- const d = dir;
1223
- if ((d.type === "trait" || d.type === "ObjectTrait") && d.name === "economy" && typeof d.config === "object" && d.config) {
1224
- const cfg = d.config;
1225
- if (typeof cfg.budget === "number") result.budget = cfg.budget;
1226
- if (typeof cfg.default_spend_limit === "number")
1227
- result.default_spend_limit = cfg.default_spend_limit;
1228
- if (typeof cfg.initial_balance === "number") result.initial_balance = cfg.initial_balance;
1229
- if (typeof cfg.task_completion_reward === "number")
1230
- result.task_completion_reward = cfg.task_completion_reward;
1231
- found = true;
1232
- }
1233
- }
1234
- }
1235
- if (Array.isArray(obj.body)) obj.body.forEach(walk);
1236
- if (Array.isArray(obj.children)) obj.children.forEach(walk);
1237
- if (Array.isArray(obj.objects)) obj.objects.forEach(walk);
1238
- }
1239
- walk(ast);
1240
- return found ? result : void 0;
1241
- }
1242
- function loadRuntimeSkillActions(skillsDir, opts, host, repoRoot, debug = false) {
1243
- const actions = {};
1244
- if (!fs__namespace.existsSync(skillsDir)) return actions;
1245
- const files = fs__namespace.readdirSync(skillsDir).filter((name) => name.endsWith(".hsplus")).map((name) => path__namespace.join(skillsDir, name));
1246
- for (const file of files) {
1247
- const content = fs__namespace.readFileSync(file, "utf-8");
1248
- const actionRe = /action\s+"([^"]+)"\s*\{([\s\S]*?)\}/g;
1249
- let match;
1250
- while ((match = actionRe.exec(content)) !== null) {
1251
- const actionName = match[1].trim();
1252
- const block = match[2];
1253
- const commandMatch = block.match(/command\s*:\s*["']([^"']+)["']/);
1254
- if (!commandMatch) continue;
1255
- const command = commandMatch[1].trim();
1256
- const argMatch = block.match(/args\s*:\s*\[([^\]]*)\]/);
1257
- const bakedArgs = [];
1258
- if (argMatch) {
1259
- const argValueRe = /["']([^"']+)["']/g;
1260
- let argToken;
1261
- while ((argToken = argValueRe.exec(argMatch[1])) !== null) {
1262
- bakedArgs.push(argToken[1]);
1263
- }
1264
- }
1265
- actions[actionName] = async (params, bb, ctx) => {
1266
- if (!opts.allowShell) {
1267
- bb.skill_error = `Skill ${actionName} blocked: shell disabled`;
1268
- return false;
1269
- }
1270
- if (opts.allowedShellCommands.length > 0) {
1271
- const executable = command.split(/\s+/)[0].toLowerCase();
1272
- const allowed = opts.allowedShellCommands.some((c) => c.toLowerCase() === executable);
1273
- if (!allowed) {
1274
- bb.skill_error = `Skill ${actionName} blocked: command ${executable} not allowlisted`;
1275
- return false;
1276
- }
1277
- }
1278
- const runtimeArgs = Array.isArray(params.args) ? params.args.filter((v) => typeof v === "string") : [];
1279
- const timeoutMs = typeof params.timeoutMs === "number" && Number.isFinite(params.timeoutMs) ? Math.max(1e3, Math.min(3e5, Math.floor(params.timeoutMs))) : 6e4;
1280
- const result = await host.exec(command, [...bakedArgs, ...runtimeArgs], {
1281
- cwd: repoRoot,
1282
- timeoutMs
1283
- });
1284
- bb.skill_last_action = actionName;
1285
- bb.skill_last_code = result.code ?? -1;
1286
- bb.skill_last_stdout = result.stdout.slice(0, 5e4);
1287
- bb.skill_last_stderr = result.stderr.slice(0, 5e4);
1288
- ctx.emit("daemon:skill:executed", { actionName, code: result.code, file });
1289
- return result.code === 0;
1290
- };
1291
- }
1292
- }
1293
- if (debug) {
1294
- console.log(
1295
- `[daemon] Loaded ${Object.keys(actions).length} runtime skill action(s) from ${skillsDir}`
1296
- );
1297
- }
1298
- return actions;
1299
- }
1300
- async function daemonScript(opts) {
1301
- if (!opts.file) {
1302
- console.error("Error: No composition file specified");
1303
- process.exit(1);
1304
- }
1305
- const filePath = path__namespace.resolve(opts.file);
1306
- if (!fs__namespace.existsSync(filePath)) {
1307
- console.error(`Error: File not found: ${filePath}`);
1308
- process.exit(1);
1309
- }
1310
- const { createDaemonActions, getDaemonFileState } = await import('@holoscript/absorb-service/daemon');
1311
- const repoRoot = findGitRoot(path__namespace.dirname(filePath));
1312
- const source = fs__namespace.readFileSync(filePath, "utf-8");
1313
- const parseResult = chunkLZ266PCM_cjs.parse(source);
1314
- if (!parseResult.success || !parseResult.ast) {
1315
- const errors = parseResult.errors?.map((e) => e.message).join(", ") || "unknown";
1316
- console.error(`[daemon] Parse failed: ${errors}`);
1317
- process.exit(1);
1318
- }
1319
- const compositionAST = parseResult.ast;
1320
- console.log(`[daemon] Composition: ${path__namespace.basename(filePath)}`);
1321
- console.log(`[daemon] Repo root: ${repoRoot}`);
1322
- console.log(
1323
- `[daemon] Cycles: ${opts.cycles} | Commit: ${opts.commit} | Timeout: ${opts.timeout}min | Provider: ${opts.provider} | Model: ${opts.model} | Tool profile: ${opts.toolProfile} | Always-on: ${opts.alwaysOn} | Cycle interval: ${opts.cycleIntervalSec}s`
1324
- );
1325
- const stateDir = path__namespace.join(repoRoot, ".holoscript");
1326
- if (!fs__namespace.existsSync(stateDir)) fs__namespace.mkdirSync(stateDir, { recursive: true });
1327
- const lockFile = path__namespace.join(stateDir, "daemon.lock");
1328
- const lockData = { pid: process.pid, time: Date.now(), heartbeat: Date.now() };
1329
- if (fs__namespace.existsSync(lockFile)) {
1330
- try {
1331
- const existing = JSON.parse(fs__namespace.readFileSync(lockFile, "utf-8"));
1332
- const staleMs = 12e4;
1333
- if (Date.now() - existing.heartbeat < staleMs) {
1334
- console.error(
1335
- `[daemon] Another daemon is running (PID ${existing.pid}). Remove ${lockFile} to force.`
1336
- );
1337
- process.exit(1);
1338
- }
1339
- console.log(`[daemon] Reclaiming stale lock from PID ${existing.pid}`);
1340
- } catch {
1341
- }
1342
- }
1343
- fs__namespace.writeFileSync(lockFile, JSON.stringify(lockData), "utf-8");
1344
- const heartbeatTimer = setInterval(() => {
1345
- try {
1346
- fs__namespace.writeFileSync(lockFile, JSON.stringify({ ...lockData, heartbeat: Date.now() }), "utf-8");
1347
- } catch {
1348
- }
1349
- }, 3e4);
1350
- const fileWatchers = [];
1351
- const cleanup = () => {
1352
- clearInterval(heartbeatTimer);
1353
- for (const watcher of fileWatchers) {
1354
- try {
1355
- watcher.close();
1356
- } catch {
1357
- }
1358
- }
1359
- try {
1360
- fs__namespace.rmSync(lockFile, { force: true });
1361
- } catch {
1362
- }
1363
- };
1364
- process.once("SIGINT", cleanup);
1365
- process.once("SIGTERM", cleanup);
1366
- process.once("uncaughtException", (err) => {
1367
- cleanup();
1368
- console.error("[daemon] Uncaught:", err);
1369
- process.exit(1);
1370
- });
1371
- process.once("unhandledRejection", (err) => {
1372
- cleanup();
1373
- console.error("[daemon] Unhandled:", err);
1374
- process.exit(1);
1375
- });
1376
- const host = {
1377
- readFile: (p) => fs__namespace.readFileSync(path__namespace.resolve(repoRoot, p), "utf-8"),
1378
- writeFile: (p, c) => {
1379
- const resolved = path__namespace.resolve(repoRoot, p);
1380
- fs__namespace.mkdirSync(path__namespace.dirname(resolved), { recursive: true });
1381
- fs__namespace.writeFileSync(resolved, c, "utf-8");
1382
- },
1383
- exists: (p) => fs__namespace.existsSync(path__namespace.resolve(repoRoot, p)),
1384
- exec: (cmd, args = [], execOpts = {}) => new Promise((resolve2, reject) => {
1385
- const child = child_process.spawn(cmd, args, {
1386
- cwd: execOpts.cwd ?? repoRoot,
1387
- shell: true,
1388
- stdio: ["ignore", "pipe", "pipe"]
1389
- });
1390
- let stdout = "";
1391
- let stderr = "";
1392
- let timer = null;
1393
- child.stdout?.on("data", (d) => {
1394
- stdout += d.toString("utf-8");
1395
- });
1396
- child.stderr?.on("data", (d) => {
1397
- stderr += d.toString("utf-8");
1398
- });
1399
- if (execOpts.timeoutMs && execOpts.timeoutMs > 0) {
1400
- timer = setTimeout(() => {
1401
- try {
1402
- child.kill("SIGKILL");
1403
- } catch {
1404
- }
1405
- }, execOpts.timeoutMs);
1406
- }
1407
- child.on("close", (code) => {
1408
- if (timer) clearTimeout(timer);
1409
- resolve2({ code, stdout, stderr });
1410
- });
1411
- child.on("error", reject);
1412
- })
1413
- };
1414
- const skillsDirRel = opts.skillsDir || "compositions/skills";
1415
- const skillsDirAbs = path__namespace.resolve(repoRoot, skillsDirRel);
1416
- if (!fs__namespace.existsSync(skillsDirAbs)) {
1417
- fs__namespace.mkdirSync(skillsDirAbs, { recursive: true });
1418
- }
1419
- let runtimeSkillActions = loadRuntimeSkillActions(skillsDirAbs, opts, host, repoRoot, opts.debug);
1420
- let activeRuntime = null;
1421
- const reloadRuntimeSkills = () => {
1422
- runtimeSkillActions = loadRuntimeSkillActions(skillsDirAbs, opts, host, repoRoot, opts.debug);
1423
- if (activeRuntime) {
1424
- for (const [name, handler] of Object.entries(runtimeSkillActions)) {
1425
- activeRuntime.registerAction(name, handler);
1426
- }
1427
- }
1428
- };
1429
- try {
1430
- const watcher = fs__namespace.watch(skillsDirAbs, { persistent: false }, () => {
1431
- reloadRuntimeSkills();
1432
- });
1433
- fileWatchers.push(watcher);
1434
- } catch (error) {
1435
- if (opts.debug) {
1436
- console.warn(
1437
- `[daemon] Skill watcher unavailable for ${skillsDirAbs}: ${error.message}`
1438
- );
1439
- }
1440
- }
1441
- const llm = createDaemonLLMProvider(opts);
1442
- const defaultFocusRotation = [
1443
- "typefix",
1444
- "coverage",
1445
- "typefix",
1446
- "lint",
1447
- "target-sweep",
1448
- "trait-sampling",
1449
- "runtime-matrix",
1450
- "absorb-roundtrip",
1451
- "typefix",
1452
- "all"
1453
- ];
1454
- const focusRotation = getASTBlackboardValue(compositionAST, "focus_rotation") ?? defaultFocusRotation;
1455
- const providerRotationEnabled = getASTBlackboardValue(compositionAST, "provider_rotation_enabled") ?? opts.providerRotation;
1456
- const rotationProviders = getASTBlackboardValue(compositionAST, "provider_rotation") ?? ["anthropic", "xai"];
1457
- const quarantineThreshold = getASTBlackboardValue(compositionAST, "quarantine_threshold") ?? 3;
1458
- const economyConfig = extractEconomyConfig(compositionAST);
1459
- if (economyConfig && opts.debug) {
1460
- console.log(`[daemon] Economy config from composition:`, economyConfig);
1461
- }
1462
- const config = {
1463
- repoRoot,
1464
- commit: opts.commit,
1465
- model: opts.model,
1466
- provider: opts.provider,
1467
- toolProfile: opts.toolProfile,
1468
- verbose: opts.debug,
1469
- trial: opts.trial,
1470
- focusRotation,
1471
- stateDir,
1472
- quarantineThreshold,
1473
- skillsDir: opts.skillsDir,
1474
- toolPolicy: {
1475
- allowShell: opts.allowShell,
1476
- allowedShellCommands: opts.allowedShellCommands,
1477
- allowedHosts: opts.allowedHosts,
1478
- allowedPaths: opts.allowedPaths
1479
- },
1480
- economyConfig,
1481
- sessionId: opts.sessionId
1482
- };
1483
- const stateFile = path__namespace.join(stateDir, "daemon-state.json");
1484
- const telemetryFile = path__namespace.join(stateDir, "daemon-telemetry.jsonl");
1485
- const daemonStateDefaults = {
1486
- totalCycles: 0,
1487
- focusIndex: 0,
1488
- bestQuality: 0,
1489
- lastQuality: 0,
1490
- totalCostUSD: 0,
1491
- totalInputTokens: 0,
1492
- totalOutputTokens: 0,
1493
- typeErrorBaseline: 0,
1494
- lastFocus: "",
1495
- lastCycleTimeISO: ""
1496
- };
1497
- let daemonState = { ...daemonStateDefaults };
1498
- if (fs__namespace.existsSync(stateFile)) {
1499
- try {
1500
- daemonState = { ...daemonState, ...JSON.parse(fs__namespace.readFileSync(stateFile, "utf-8")) };
1501
- } catch {
1502
- }
1503
- }
1504
- const fileStateFile = path__namespace.join(stateDir, "daemon-file-state.json");
1505
- if (fs__namespace.existsSync(fileStateFile)) {
1506
- try {
1507
- const fileState = JSON.parse(fs__namespace.readFileSync(fileStateFile, "utf-8"));
1508
- config.committedFiles = fileState.committed || [];
1509
- config.failedFiles = fileState.failures || {};
1510
- } catch {
1511
- }
1512
- }
1513
- if (daemonState.typeErrorBaseline > 0) {
1514
- config.typeErrorBaseline = daemonState.typeErrorBaseline;
1515
- }
1516
- let daemonResult = createDaemonActions(host, llm, config);
1517
- let actions = daemonResult.actions;
1518
- try {
1519
- await llm.chat({ system: "reply ok", prompt: "ok", maxTokens: 1 });
1520
- console.log("[daemon] API key validated");
1521
- } catch (err) {
1522
- console.error(`[daemon] API key validation failed: ${err.message}`);
1523
- cleanup();
1524
- process.exit(1);
1525
- }
1526
- let convergenceStreak = 0;
1527
- const CONVERGENCE_THRESHOLD = 3;
1528
- let cycle = 0;
1529
- while (opts.alwaysOn || cycle < opts.cycles) {
1530
- let focusIdx = daemonState.focusIndex % focusRotation.length;
1531
- let focus = opts.focus || focusRotation[focusIdx];
1532
- if (!opts.focus) {
1533
- const wisdomFile = path__namespace.join(stateDir, "accumulated-wisdom.json");
1534
- let wisdomEntries = [];
1535
- try {
1536
- if (fs__namespace.existsSync(wisdomFile)) {
1537
- wisdomEntries = JSON.parse(fs__namespace.readFileSync(wisdomFile, "utf-8"));
1538
- }
1539
- } catch {
1540
- }
1541
- const STALE_THRESHOLD = 3;
1542
- let attempts = 0;
1543
- while (attempts < focusRotation.length) {
1544
- const focusHistory = wisdomEntries.filter((w) => w.focus === focus);
1545
- const lastN = focusHistory.slice(-STALE_THRESHOLD);
1546
- const isStale = lastN.length >= STALE_THRESHOLD && lastN.every((w) => (w.delta || 0) === 0);
1547
- if (!isStale) break;
1548
- console.log(
1549
- `[daemon] Skipping stale focus "${focus}" (${STALE_THRESHOLD} consecutive zero-delta cycles)`
1550
- );
1551
- focusIdx = (focusIdx + 1) % focusRotation.length;
1552
- focus = focusRotation[focusIdx];
1553
- attempts++;
1554
- }
1555
- }
1556
- config.cycleFocus = focus;
1557
- config.daemonFile = filePath;
1558
- config.qualityBefore = daemonState.lastQuality;
1559
- const cycleStart = Date.now();
1560
- if (providerRotationEnabled) {
1561
- const cycleProvider = rotationProviders[cycle % rotationProviders.length];
1562
- const cycleModel = defaultModelForProvider(cycleProvider);
1563
- const cycleToolProfile = defaultToolProfileForProvider(cycleProvider);
1564
- const cycleOpts = {
1565
- ...opts,
1566
- provider: cycleProvider,
1567
- model: cycleModel};
1568
- const cycleLlm = createDaemonLLMProvider(cycleOpts);
1569
- config.provider = cycleProvider;
1570
- config.model = cycleModel;
1571
- config.toolProfile = cycleToolProfile;
1572
- daemonResult = createDaemonActions(host, cycleLlm, config);
1573
- actions = daemonResult.actions;
1574
- console.log(
1575
- `
1576
- [daemon] === Cycle ${cycle + 1}${opts.alwaysOn ? "" : `/${opts.cycles}`} | Focus: ${focus} | Provider: ${cycleProvider} (${cycleModel}) ===`
1577
- );
1578
- } else {
1579
- console.log(
1580
- `
1581
- [daemon] === Cycle ${cycle + 1}${opts.alwaysOn ? "" : `/${opts.cycles}`} | Focus: ${focus} ===`
1582
- );
1583
- }
1584
- const cycleAST = JSON.parse(JSON.stringify(compositionAST));
1585
- materializeTraits(cycleAST);
1586
- const bbValues = {
1587
- focus,
1588
- cycleNumber: daemonState.totalCycles + cycle,
1589
- daemon_file: filePath,
1590
- quality_before: daemonState.lastQuality
1591
- };
1592
- setASTBlackboard(cycleAST, bbValues);
1593
- if (opts.debug) {
1594
- console.log(`[daemon] Blackboard injection: focus=${focus}, daemon_file=${filePath}`);
1595
- }
1596
- const runtime$1 = runtime.createHeadlessRuntime(cycleAST, {
1597
- profile: runtime.HEADLESS_PROFILE,
1598
- tickRate: 10,
1599
- debug: opts.debug,
1600
- hostCapabilities: createNodeHostCapabilities(repoRoot)
1601
- });
1602
- activeRuntime = runtime$1;
1603
- for (const [name, handler] of Object.entries(actions)) {
1604
- runtime$1.registerAction(name, handler);
1605
- }
1606
- for (const [name, handler] of Object.entries(runtimeSkillActions)) {
1607
- runtime$1.registerAction(name, handler);
1608
- }
1609
- daemonResult.wireTraitListeners(runtime$1);
1610
- const maxWaitMs = opts.timeout * 60 * 1e3;
1611
- const btResult = await new Promise(
1612
- (resolve2) => {
1613
- let resolved = false;
1614
- const timeout = setTimeout(() => {
1615
- if (!resolved) {
1616
- resolved = true;
1617
- resolve2({ status: "timeout", blackboard: {} });
1618
- }
1619
- }, maxWaitMs);
1620
- runtime$1.on("bt_complete", (payload) => {
1621
- if (!resolved) {
1622
- resolved = true;
1623
- clearTimeout(timeout);
1624
- const p = payload;
1625
- resolve2({
1626
- status: p?.status || "unknown",
1627
- blackboard: p?.blackboard || {}
1628
- });
1629
- }
1630
- });
1631
- runtime$1.start();
1632
- }
1633
- );
1634
- const btStatus = btResult.status;
1635
- const btBlackboard = btResult.blackboard;
1636
- const durationSec = ((Date.now() - cycleStart) / 1e3).toFixed(1);
1637
- const stats = runtime$1.getStats();
1638
- const inputTokens = btBlackboard.inputTokens || 0;
1639
- const outputTokens = btBlackboard.outputTokens || 0;
1640
- const qualityAfter = btBlackboard.quality_after || daemonState.lastQuality;
1641
- const costUSD = inputTokens * 3 / 1e6 + outputTokens * 15 / 1e6;
1642
- const committed = btBlackboard.committed_count || 0;
1643
- const qualityDelta = qualityAfter - (config.qualityBefore || 0);
1644
- runtime$1.emit("daemon:cycle_raw_telemetry", {
1645
- focus,
1646
- ticks: stats.updateCount,
1647
- inputTokens,
1648
- outputTokens,
1649
- qualityBefore: daemonState.lastQuality,
1650
- qualityAfter,
1651
- costUSD,
1652
- committed: committed > 0
1653
- });
1654
- runtime$1.emit("daemon:raw_quality", { value: qualityAfter, focus });
1655
- const totalTokens = inputTokens + outputTokens;
1656
- const costEfficiency = costUSD > 0 ? Math.min(1, qualityAfter * totalTokens / (costUSD * 5e5)) : qualityAfter;
1657
- runtime$1.emit("feedback:update_metric", { name: "cost_efficiency", value: costEfficiency });
1658
- const candidateCount = Array.isArray(btBlackboard.candidates) ? btBlackboard.candidates.length : 0;
1659
- const emergenceRatio = candidateCount > 0 ? Math.min(1, committed / candidateCount) : 0;
1660
- runtime$1.emit("feedback:update_metric", { name: "emergence_ratio", value: emergenceRatio });
1661
- const wisdomCount = btBlackboard.wisdomCount || 0;
1662
- const regenerativeHealth = Math.min(1, wisdomCount / 200);
1663
- runtime$1.emit("feedback:update_metric", {
1664
- name: "regenerative_health",
1665
- value: regenerativeHealth
1666
- });
1667
- runtime$1.stop();
1668
- activeRuntime = null;
1669
- const telemetryRecord = {
1670
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1671
- cycleNumber: daemonState.totalCycles + 1,
1672
- focus,
1673
- provider: config.provider,
1674
- model: config.model,
1675
- btStatus,
1676
- ticks: stats.updateCount,
1677
- inputTokens,
1678
- outputTokens,
1679
- totalTokens,
1680
- costUSD,
1681
- qualityBefore: config.qualityBefore || 0,
1682
- qualityAfter,
1683
- qualityDelta,
1684
- typeErrors: btBlackboard.quality_typeErrors ?? null,
1685
- testsPassed: btBlackboard.quality_testsPassed ?? null,
1686
- testsTotal: btBlackboard.quality_testsTotal ?? null,
1687
- committedCount: committed,
1688
- candidateCount,
1689
- wisdomCount,
1690
- durationSec: Number(durationSec)
1691
- };
1692
- fs__namespace.appendFileSync(telemetryFile, `${JSON.stringify(telemetryRecord)}
1693
- `, "utf-8");
1694
- console.log(
1695
- `[daemon] Cycle ${cycle + 1} done in ${durationSec}s | ${stats.updateCount} ticks | BT: ${btStatus} | quality: ${qualityAfter.toFixed(3)}`
1696
- );
1697
- daemonState.totalCycles++;
1698
- daemonState.focusIndex = (focusIdx + 1) % focusRotation.length;
1699
- daemonState.lastQuality = qualityAfter;
1700
- if (qualityAfter > daemonState.bestQuality) {
1701
- daemonState.bestQuality = qualityAfter;
1702
- }
1703
- daemonState.totalInputTokens += inputTokens;
1704
- daemonState.totalOutputTokens += outputTokens;
1705
- daemonState.totalCostUSD += costUSD;
1706
- daemonState.lastFocus = focus;
1707
- daemonState.lastCycleTimeISO = (/* @__PURE__ */ new Date()).toISOString();
1708
- const cycleTypeErrors = btBlackboard.typeErrorBaseline || btBlackboard.typeErrorCount || 0;
1709
- if (daemonState.typeErrorBaseline === 0 && cycleTypeErrors > 0) {
1710
- daemonState.typeErrorBaseline = cycleTypeErrors;
1711
- config.typeErrorBaseline = cycleTypeErrors;
1712
- console.log(`[daemon] Established type error baseline: ${cycleTypeErrors}`);
1713
- }
1714
- fs__namespace.writeFileSync(stateFile, JSON.stringify(daemonState, null, 2), "utf-8");
1715
- const fileState = getDaemonFileState(repoRoot);
1716
- fs__namespace.writeFileSync(fileStateFile, JSON.stringify(fileState, null, 2), "utf-8");
1717
- if (qualityDelta <= 0 && committed === 0) {
1718
- convergenceStreak++;
1719
- if (convergenceStreak >= CONVERGENCE_THRESHOLD) {
1720
- console.log(
1721
- `[daemon] Plateau detected \u2014 ${convergenceStreak} consecutive zero-delta cycles. Escalating strategy.`
1722
- );
1723
- convergenceStreak = 0;
1724
- const oldThreshold = config.quarantineThreshold || 3;
1725
- config.quarantineThreshold = oldThreshold + 2;
1726
- console.log(
1727
- `[daemon] Raised quarantine threshold: ${oldThreshold} \u2192 ${config.quarantineThreshold}`
1728
- );
1729
- if (!opts.focus) {
1730
- const typefixIdx = focusRotation.indexOf("typefix");
1731
- if (typefixIdx >= 0) {
1732
- daemonState.focusIndex = typefixIdx;
1733
- console.log(`[daemon] Forcing next cycle to 'typefix' focus`);
1734
- }
1735
- }
1736
- if (config.quarantineThreshold >= quarantineThreshold + 4) {
1737
- console.log(
1738
- `[daemon] Escalated twice with no progress. Stopping to avoid wasting tokens.`
1739
- );
1740
- break;
1741
- }
1742
- }
1743
- } else {
1744
- convergenceStreak = 0;
1745
- }
1746
- cycle++;
1747
- if (opts.alwaysOn && opts.cycleIntervalSec > 0) {
1748
- console.log(`[daemon] Sleeping ${opts.cycleIntervalSec}s before next cycle...`);
1749
- await sleep(opts.cycleIntervalSec * 1e3);
1750
- }
1751
- }
1752
- cleanup();
1753
- console.log(`
1754
- [daemon] Completed ${cycle} cycle(s).`);
1755
- console.log(
1756
- `[daemon] Best quality: ${daemonState.bestQuality.toFixed(3)} | Total cost: $${daemonState.totalCostUSD.toFixed(3)} | Total cycles: ${daemonState.totalCycles}`
1757
- );
1758
- }
1759
- function materializeTraits(ast) {
1760
- const walk = (node) => {
1761
- if (!node || typeof node !== "object") return;
1762
- const n = node;
1763
- const traits = /* @__PURE__ */ new Map();
1764
- if (Array.isArray(n.directives)) {
1765
- for (const directive of n.directives) {
1766
- const d = directive;
1767
- if (d.type === "trait" && typeof d.name === "string") {
1768
- traits.set(d.name, d.config ?? {});
1769
- }
1770
- }
1771
- }
1772
- if (traits.size > 0) {
1773
- n.traits = traits;
1774
- } else if (n.traits && !(n.traits instanceof Map)) {
1775
- delete n.traits;
1776
- }
1777
- for (const key of ["body", "children", "nodes", "members"]) {
1778
- if (Array.isArray(n[key])) {
1779
- n[key].forEach(walk);
1780
- }
1781
- }
1782
- if (n.root && typeof n.root === "object") {
1783
- walk(n.root);
1784
- }
1785
- };
1786
- walk(ast);
1787
- }
1788
- function setASTBlackboard(ast, values) {
1789
- const visited = /* @__PURE__ */ new WeakSet();
1790
- let found = false;
1791
- const walk = (node) => {
1792
- if (found || !node || typeof node !== "object") return;
1793
- const obj = node;
1794
- if (visited.has(obj)) return;
1795
- visited.add(obj);
1796
- if (obj.blackboard && typeof obj.blackboard === "object" && !Array.isArray(obj.blackboard)) {
1797
- Object.assign(obj.blackboard, values);
1798
- found = true;
1799
- return;
1800
- }
1801
- for (const key of Object.keys(obj)) {
1802
- const val = obj[key];
1803
- if (val && typeof val === "object") {
1804
- if (Array.isArray(val)) {
1805
- for (const item of val) walk(item);
1806
- } else if (val instanceof Map) {
1807
- for (const v of val.values()) walk(v);
1808
- } else {
1809
- walk(val);
1810
- }
1811
- }
1812
- if (found) return;
1813
- }
1814
- };
1815
- walk(ast);
1816
- }
1817
- function getASTBlackboardValue(ast, key) {
1818
- const visited = /* @__PURE__ */ new WeakSet();
1819
- let result = void 0;
1820
- const walk = (node) => {
1821
- if (result !== void 0 || !node || typeof node !== "object") return;
1822
- const obj = node;
1823
- if (visited.has(obj)) return;
1824
- visited.add(obj);
1825
- if (obj.blackboard && typeof obj.blackboard === "object" && !Array.isArray(obj.blackboard)) {
1826
- const bb = obj.blackboard;
1827
- if (key in bb) {
1828
- result = bb[key];
1829
- return;
1830
- }
1831
- }
1832
- for (const k of Object.keys(obj)) {
1833
- const val = obj[k];
1834
- if (val && typeof val === "object") {
1835
- if (Array.isArray(val)) {
1836
- for (const item of val) walk(item);
1837
- } else if (!(val instanceof Map)) {
1838
- walk(val);
1839
- }
1840
- }
1841
- if (result !== void 0) return;
1842
- }
1843
- };
1844
- walk(ast);
1845
- return result;
1846
- }
1847
- async function holoMeshDaemonScript(opts) {
1848
- if (!opts.file) {
1849
- console.error("Error: No composition file specified");
1850
- console.error("Usage: holoscript holomesh-daemon compositions/holomesh-agent.hsplus [options]");
1851
- process.exit(1);
1852
- }
1853
- const filePath = path__namespace.resolve(opts.file);
1854
- if (!fs__namespace.existsSync(filePath)) {
1855
- console.error(`Error: File not found: ${filePath}`);
1856
- process.exit(1);
1857
- }
1858
- if (!process.env.HOLOSCRIPT_API_KEY) {
1859
- console.error("[holomesh-daemon] HOLOSCRIPT_API_KEY environment variable is required");
1860
- process.exit(1);
1861
- }
1862
- const rawSource = fs__namespace.readFileSync(filePath, "utf-8");
1863
- const source = rawSource.replace(/^#(version|target|mode)\s+.*/gm, "");
1864
- const parseResult = chunkLZ266PCM_cjs.parse(source);
1865
- if (!parseResult.success || !parseResult.ast) {
1866
- const errors = parseResult.errors?.map((e) => e.message).join(", ") || "unknown";
1867
- console.error(`[holomesh-daemon] Parse failed: ${errors}`);
1868
- process.exit(1);
1869
- }
1870
- const compositionAST = parseResult.ast;
1871
- const stateDir = path__namespace.resolve(path__namespace.dirname(filePath), ".holoscript");
1872
- if (!fs__namespace.existsSync(stateDir)) fs__namespace.mkdirSync(stateDir, { recursive: true });
1873
- const stateFile = path__namespace.join(stateDir, "holomesh-state.json");
1874
- console.log(`[holomesh-daemon] Composition: ${path__namespace.basename(filePath)}`);
1875
- console.log(`[holomesh-daemon] Cycles: ${opts.cycles} | Always-on: ${opts.alwaysOn}`);
1876
- const lockFile = path__namespace.join(stateDir, "holomesh-daemon.lock");
1877
- const lockData = { pid: process.pid, time: Date.now(), heartbeat: Date.now() };
1878
- if (fs__namespace.existsSync(lockFile)) {
1879
- try {
1880
- const existing = JSON.parse(fs__namespace.readFileSync(lockFile, "utf-8"));
1881
- if (Date.now() - existing.heartbeat < 12e4) {
1882
- console.error(
1883
- `[holomesh-daemon] Another daemon is running (PID ${existing.pid}). Remove ${lockFile} to force.`
1884
- );
1885
- process.exit(1);
1886
- }
1887
- console.log(`[holomesh-daemon] Reclaiming stale lock from PID ${existing.pid}`);
1888
- } catch {
1889
- }
1890
- }
1891
- fs__namespace.writeFileSync(lockFile, JSON.stringify(lockData), "utf-8");
1892
- const heartbeatTimer = setInterval(() => {
1893
- try {
1894
- fs__namespace.writeFileSync(lockFile, JSON.stringify({ ...lockData, heartbeat: Date.now() }), "utf-8");
1895
- } catch {
1896
- }
1897
- }, 3e4);
1898
- const cleanup = () => {
1899
- clearInterval(heartbeatTimer);
1900
- try {
1901
- fs__namespace.rmSync(lockFile, { force: true });
1902
- } catch {
1903
- }
1904
- };
1905
- process.once("SIGINT", cleanup);
1906
- process.once("SIGTERM", cleanup);
1907
- let createHoloMeshDaemonActions;
1908
- let HoloMeshOrchestratorClient;
1909
- try {
1910
- let actionsModule;
1911
- let clientModule;
1912
- try {
1913
- actionsModule = await import('@holoscript/mcp-server/holomesh/agent/holomesh-daemon-actions');
1914
- clientModule = await import('@holoscript/mcp-server/holomesh/orchestrator-client');
1915
- } catch {
1916
- const actionsPath = "../../../mcp-server/src/holomesh/agent/holomesh-daemon-actions";
1917
- const clientPath = "../../../mcp-server/src/holomesh/orchestrator-client";
1918
- actionsModule = await import(actionsPath);
1919
- clientModule = await import(clientPath);
1920
- }
1921
- createHoloMeshDaemonActions = actionsModule.createHoloMeshDaemonActions;
1922
- HoloMeshOrchestratorClient = clientModule.HoloMeshOrchestratorClient;
1923
- } catch (err) {
1924
- console.error(`[holomesh-daemon] Failed to import holomesh modules: ${err.message}`);
1925
- console.error("[holomesh-daemon] Ensure @holoscript/mcp-server is installed");
1926
- cleanup();
1927
- process.exit(1);
1928
- }
1929
- const meshConfig = {
1930
- orchestratorUrl: process.env.MCP_ORCHESTRATOR_URL || "https://mcp-orchestrator-production-45f9.up.railway.app",
1931
- apiKey: process.env.HOLOSCRIPT_API_KEY,
1932
- workspace: process.env.HOLOMESH_WORKSPACE || "ai-ecosystem",
1933
- agentName: process.env.HOLOMESH_AGENT_NAME || "holomesh-agent",
1934
- discoveryIntervalMs: 5 * 60 * 1e3,
1935
- inboxIntervalMs: 60 * 1e3,
1936
- maxContributionsPerCycle: 5,
1937
- maxQueriesPerCycle: 3,
1938
- budgetCapUSD: parseFloat(process.env.HOLOMESH_BUDGET_CAP || "5")
1939
- };
1940
- const client = new HoloMeshOrchestratorClient(meshConfig);
1941
- const v2Enabled = process.env.HOLOMESH_V2_ENABLED === "true";
1942
- const localAgentDid = process.env.HOLOMESH_AGENT_DID || (v2Enabled ? `did:holo:${meshConfig.agentName}` : void 0);
1943
- const walletEnabled = process.env.HOLOMESH_WALLET_ENABLED === "true";
1944
- const walletTestnet = process.env.HOLOMESH_WALLET_TESTNET === "true";
1945
- const { actions, wireTraitListeners } = createHoloMeshDaemonActions(client, {
1946
- stateFile,
1947
- verbose: opts.debug,
1948
- v2Enabled,
1949
- localAgentDid,
1950
- localMcpUrl: process.env.HOLOMESH_LOCAL_MCP_URL || "https://mcp.holoscript.net",
1951
- crdtSnapshotPath: v2Enabled ? path__namespace.join(path__namespace.dirname(stateFile), "holomesh-crdt.bin") : void 0,
1952
- peerStorePath: v2Enabled ? path__namespace.join(path__namespace.dirname(stateFile), "holomesh-peers.json") : void 0,
1953
- walletEnabled,
1954
- walletTestnet
1955
- });
1956
- console.log(
1957
- `[holomesh-daemon] ${Object.keys(actions).length} action handlers registered${v2Enabled ? ` (V2 P2P enabled, DID: ${localAgentDid})` : ""}${walletEnabled ? " (V3 Wallet enabled)" : ""}`
1958
- );
1959
- let cycle = 0;
1960
- while (opts.alwaysOn || cycle < opts.cycles) {
1961
- console.log(
1962
- `
1963
- [holomesh-daemon] === Cycle ${cycle + 1}${opts.alwaysOn ? "" : `/${opts.cycles}`} ===`
1964
- );
1965
- const cycleAST = JSON.parse(JSON.stringify(compositionAST));
1966
- materializeTraits(cycleAST);
1967
- const runtime$1 = runtime.createHeadlessRuntime(cycleAST, {
1968
- profile: runtime.HEADLESS_PROFILE,
1969
- tickRate: 1,
1970
- debug: opts.debug,
1971
- hostCapabilities: createNodeHostCapabilities(path__namespace.dirname(filePath))
1972
- });
1973
- for (const [name, handler] of Object.entries(actions)) {
1974
- runtime$1.registerAction(name, handler);
1975
- }
1976
- wireTraitListeners(runtime$1);
1977
- const maxWaitMs = (opts.timeout ?? 5) * 60 * 1e3;
1978
- const btResult = await new Promise((resolve2) => {
1979
- let resolved = false;
1980
- const timeout = setTimeout(() => {
1981
- if (!resolved) {
1982
- resolved = true;
1983
- resolve2({ status: "timeout" });
1984
- }
1985
- }, maxWaitMs);
1986
- runtime$1.on("bt_complete", () => {
1987
- if (!resolved) {
1988
- resolved = true;
1989
- clearTimeout(timeout);
1990
- resolve2({ status: "complete" });
1991
- }
1992
- });
1993
- runtime$1.start();
1994
- });
1995
- runtime$1.stop();
1996
- console.log(`[holomesh-daemon] Cycle ${cycle + 1} ${btResult.status}`);
1997
- cycle++;
1998
- if (opts.alwaysOn || cycle < opts.cycles) {
1999
- const intervalSec = opts.cycleIntervalSec > 0 ? opts.cycleIntervalSec : 120;
2000
- const jitter = 1 + (Math.random() * 2 - 1) * 0.3;
2001
- const waitMs = Math.round(intervalSec * 1e3 * jitter);
2002
- console.log(`[holomesh-daemon] Waiting ${Math.round(waitMs / 1e3)}s before next cycle...`);
2003
- await new Promise((r) => setTimeout(r, waitMs));
2004
- }
2005
- }
2006
- cleanup();
2007
- console.log("[holomesh-daemon] Done");
2008
- }
2009
- async function daemonStatus(jsonOutput = false) {
2010
- const repoRoot = findGitRoot(process.cwd());
2011
- const stateDir = path__namespace.join(repoRoot, ".holoscript");
2012
- if (!fs__namespace.existsSync(stateDir)) {
2013
- if (jsonOutput) {
2014
- console.log(
2015
- JSON.stringify({
2016
- status: "missing_state_dir",
2017
- running: false,
2018
- stateDir
2019
- })
2020
- );
2021
- } else {
2022
- console.log("[daemon status] No state directory found. Run a daemon cycle first.");
2023
- }
2024
- return;
2025
- }
2026
- const lockFile = path__namespace.join(stateDir, "daemon.lock");
2027
- let isRunning = false;
2028
- let lockPid = 0;
2029
- let lastHeartbeat = 0;
2030
- if (fs__namespace.existsSync(lockFile)) {
2031
- try {
2032
- const lock = JSON.parse(fs__namespace.readFileSync(lockFile, "utf-8"));
2033
- lockPid = lock.pid;
2034
- lastHeartbeat = lock.heartbeat;
2035
- isRunning = Date.now() - lastHeartbeat < 12e4;
2036
- } catch {
2037
- }
2038
- }
2039
- const stateFile = path__namespace.join(stateDir, "daemon-state.json");
2040
- let ds = {};
2041
- if (fs__namespace.existsSync(stateFile)) {
2042
- try {
2043
- ds = JSON.parse(fs__namespace.readFileSync(stateFile, "utf-8"));
2044
- } catch {
2045
- }
2046
- }
2047
- const fileStateFile = path__namespace.join(stateDir, "daemon-file-state.json");
2048
- let fileState = {
2049
- committed: [],
2050
- failures: {}
2051
- };
2052
- if (fs__namespace.existsSync(fileStateFile)) {
2053
- try {
2054
- fileState = JSON.parse(fs__namespace.readFileSync(fileStateFile, "utf-8"));
2055
- } catch {
2056
- }
2057
- }
2058
- const wisdomFile = path__namespace.join(stateDir, "accumulated-wisdom.json");
2059
- let wisdomCount = 0;
2060
- if (fs__namespace.existsSync(wisdomFile)) {
2061
- try {
2062
- wisdomCount = JSON.parse(fs__namespace.readFileSync(wisdomFile, "utf-8")).length;
2063
- } catch {
2064
- }
2065
- }
2066
- const ledgerFile = path__namespace.join(stateDir, "fix-ledger.json");
2067
- let ledger = [];
2068
- if (fs__namespace.existsSync(ledgerFile)) {
2069
- try {
2070
- ledger = JSON.parse(fs__namespace.readFileSync(ledgerFile, "utf-8"));
2071
- } catch {
2072
- }
2073
- }
2074
- const telemetryFile = path__namespace.join(stateDir, "daemon-telemetry.jsonl");
2075
- let telemetryCount = 0;
2076
- let lastTelemetry;
2077
- if (fs__namespace.existsSync(telemetryFile)) {
2078
- try {
2079
- const lines = fs__namespace.readFileSync(telemetryFile, "utf-8").split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
2080
- telemetryCount = lines.length;
2081
- if (lines.length > 0) {
2082
- lastTelemetry = JSON.parse(lines[lines.length - 1]);
2083
- }
2084
- } catch {
2085
- }
2086
- }
2087
- const totalCycles = ds.totalCycles || 0;
2088
- const lastFocus = ds.lastFocus || "n/a";
2089
- const lastCycleTime = ds.lastCycleTimeISO ? new Date(ds.lastCycleTimeISO).toLocaleString() : "never";
2090
- const bestQ = Number(ds.bestQuality || 0).toFixed(3);
2091
- const lastQ = Number(ds.lastQuality || 0).toFixed(3);
2092
- const baseline = ds.typeErrorBaseline ? `${ds.typeErrorBaseline} type errors` : "not yet measured";
2093
- const totalCost = Number(ds.totalCostUSD || 0);
2094
- const tokIn = Number(ds.totalInputTokens || 0);
2095
- const tokOut = Number(ds.totalOutputTokens || 0);
2096
- const quarantined = Object.values(fileState.failures).filter((n) => n >= 3).length;
2097
- if (jsonOutput) {
2098
- console.log(
2099
- JSON.stringify({
2100
- status: "ok",
2101
- running: isRunning,
2102
- pid: lockPid || null,
2103
- heartbeatAgeSec: lastHeartbeat > 0 ? Math.round((Date.now() - lastHeartbeat) / 1e3) : null,
2104
- stateDir,
2105
- session: {
2106
- totalCycles,
2107
- lastFocus,
2108
- lastCycleTimeISO: ds.lastCycleTimeISO || null
2109
- },
2110
- quality: {
2111
- best: Number(bestQ),
2112
- last: Number(lastQ),
2113
- baselineTypeErrors: ds.typeErrorBaseline || 0
2114
- },
2115
- cost: {
2116
- totalUSD: totalCost,
2117
- tokensIn: tokIn,
2118
- tokensOut: tokOut
2119
- },
2120
- files: {
2121
- committed: fileState.committed.length,
2122
- quarantined
2123
- },
2124
- wisdomCount,
2125
- telemetry: {
2126
- file: telemetryFile,
2127
- count: telemetryCount,
2128
- last: lastTelemetry || null
2129
- },
2130
- recentLedger: ledger.slice(-5)
2131
- })
2132
- );
2133
- return;
2134
- }
2135
- const G = "\x1B[32m";
2136
- const Y = "\x1B[33m";
2137
- const R = "\x1B[0m";
2138
- const B = "\x1B[1m";
2139
- const runStatus = isRunning ? `${G}\u25CF RUNNING${R} (PID ${lockPid}, heartbeat ${Math.round((Date.now() - lastHeartbeat) / 1e3)}s ago)` : `${Y}\u25CB IDLE${R}`;
2140
- console.log(`
2141
- ${B}HoloDaemon Status${R} ${runStatus}`);
2142
- console.log(` State dir: ${stateDir}
2143
- `);
2144
- console.log(`${B}Session${R}`);
2145
- console.log(` Total cycles: ${totalCycles}`);
2146
- console.log(` Last focus: ${lastFocus}`);
2147
- console.log(` Last cycle: ${lastCycleTime}`);
2148
- console.log(`
2149
- ${B}Quality${R}`);
2150
- console.log(` Best: ${bestQ}`);
2151
- console.log(` Last: ${lastQ}`);
2152
- console.log(` Baseline: ${baseline}`);
2153
- const totalCostDisplay = totalCost.toFixed(4);
2154
- const tokInDisplay = tokIn.toLocaleString();
2155
- const tokOutDisplay = tokOut.toLocaleString();
2156
- console.log(`
2157
- ${B}Cost${R}`);
2158
- console.log(` Total: $${totalCostDisplay}`);
2159
- console.log(` Tokens in: ${tokInDisplay}`);
2160
- console.log(` Tokens out: ${tokOutDisplay}`);
2161
- console.log(`
2162
- ${B}Files${R}`);
2163
- console.log(` Committed: ${fileState.committed.length}`);
2164
- console.log(` Quarantined: ${quarantined}`);
2165
- console.log(` Wisdom: ${wisdomCount} entries`);
2166
- console.log(` Telemetry: ${telemetryCount} entries`);
2167
- const recent = ledger.slice(-5);
2168
- if (recent.length > 0) {
2169
- console.log(`
2170
- ${B}Recent Ledger Entries${R} (last ${recent.length})`);
2171
- for (const entry of recent) {
2172
- const ts = entry.timestamp ? new Date(entry.timestamp).toLocaleString() : "?";
2173
- const file = entry.candidate ? path__namespace.basename(entry.candidate) : "?";
2174
- const result = entry.result === "committed" ? `${G}committed${R}` : entry.result === "rolled_back" ? `${Y}rolled_back${R}` : entry.result || "?";
2175
- const sha = entry.commitSha ? ` (${entry.commitSha.slice(0, 7)})` : "";
2176
- console.log(` ${ts} ${file} ${result}${sha} focus:${entry.focus || "?"}`);
2177
- }
2178
- }
2179
- console.log("");
2180
- }
2181
- function showHelp() {
2182
- console.log(`
2183
- HoloScript CLI \u2014 Headless Runner v5.0
2184
-
2185
- Usage:
2186
- holoscript run <file> [--target node|python|ros2] [--profile headless|minimal|full] [--ticks <n>] [--daemon] [--debug]
2187
- holoscript test <file> [--debug]
2188
- holoscript compile <file> [--target node|python] [--output <path>] [--enforce-gotchas]
2189
- holoscript deploy <file> [--share] [--publish] [--price <eth>] [--mint-nft] [--wallet-key <key>] [--author <name>] [--license <type>] [--server <url>]
2190
- holoscript absorb <file> [--output <path>] [--debug]
2191
- holoscript daemon <file> [--provider anthropic|xai|openai|ollama] [--tool-profile claude-hsplus|grok-hsplus|standard] [--cycles <n>] [--commit] [--model <model>] [--trial <n>] [--provider-rotation] [--always-on] [--cycle-interval-sec <n>] [--skills-dir <path>] [--allow-shell] [--allow-shell-command <cmd>] [--allow-host <host>] [--allow-path <path>] [--debug]
2192
- holoscript daemon status [--json]
2193
-
2194
- Environment defaults (daemon):
2195
- HOLODAEMON_PROVIDER anthropic|xai|openai|ollama
2196
- HOLODAEMON_TOOL_PROFILE claude-hsplus|grok-hsplus|standard
2197
- HOLODAEMON_MODEL model identifier for selected provider
2198
-
2199
- Supported file types:
2200
- .hs Agent templates, behavior trees, event handlers
2201
- .hsplus Full language with modules, types, async/await
2202
- .holo Spatial compositions (optional render target)
2203
-
2204
- Examples:
2205
- holoscript run agent.hs --target node --debug
2206
- holoscript run agent.hs --daemon
2207
- holoscript test tests.hs
2208
- holoscript compile service.hsplus --target python --output service.py
2209
- holoscript compile world.holo --enforce-gotchas
2210
- holoscript absorb legacy.py --output agent.hsplus
2211
- holoscript daemon compositions/self-improve-daemon.hsplus --cycles 15 --commit
2212
- holoscript daemon compositions/self-improve-daemon.hsplus --provider xai --model grok-3
2213
- holoscript daemon compositions/self-improve-daemon.hsplus --provider anthropic --tool-profile claude-hsplus
2214
- holoscript daemon compositions/self-improve-daemon.hsplus --provider-rotation --cycles 10
2215
- holoscript daemon status
2216
- `);
2217
- }
2218
- async function main() {
2219
- const opts = parseArgs(process.argv);
2220
- switch (opts.command) {
2221
- case "run":
2222
- await runScript(opts);
2223
- break;
2224
- case "test":
2225
- await testScript(opts);
2226
- break;
2227
- case "compile":
2228
- compileScript(opts);
2229
- break;
2230
- case "deploy":
2231
- await deployScript(opts);
2232
- break;
2233
- case "absorb":
2234
- absorbScript(opts);
2235
- break;
2236
- case "daemon":
2237
- case "holodaemon":
2238
- await daemonScript(opts);
2239
- break;
2240
- case "holomesh-daemon":
2241
- await holoMeshDaemonScript(opts);
2242
- break;
2243
- case "daemon-status":
2244
- await daemonStatus(opts.json);
2245
- break;
2246
- case "help":
2247
- default:
2248
- showHelp();
2249
- }
2250
- }
2251
- main().catch((err) => {
2252
- console.error("[holoscript] Fatal error:", err.message);
2253
- process.exit(1);
2254
- });
2255
-
2256
- exports.daemonScript = daemonScript;
2257
- exports.holoMeshDaemonScript = holoMeshDaemonScript;
2258
- //# sourceMappingURL=holoscript-runner.cjs.map
2259
- //# sourceMappingURL=holoscript-runner.cjs.map