hoi4-agent-tools 0.0.0-bootstrap.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (416) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/LICENSE +201 -0
  3. package/README.md +140 -2
  4. package/SECURITY.md +17 -0
  5. package/dist/bin/http.d.ts +3 -0
  6. package/dist/bin/http.d.ts.map +1 -0
  7. package/dist/bin/http.js +27 -0
  8. package/dist/bin/http.js.map +1 -0
  9. package/dist/bin/setup.d.ts +3 -0
  10. package/dist/bin/setup.d.ts.map +1 -0
  11. package/dist/bin/setup.js +188 -0
  12. package/dist/bin/setup.js.map +1 -0
  13. package/dist/bin/stdio.d.ts +3 -0
  14. package/dist/bin/stdio.d.ts.map +1 -0
  15. package/dist/bin/stdio.js +36 -0
  16. package/dist/bin/stdio.js.map +1 -0
  17. package/dist/hoi4_agent_tools/core/artifacts.d.ts +117 -0
  18. package/dist/hoi4_agent_tools/core/artifacts.d.ts.map +1 -0
  19. package/dist/hoi4_agent_tools/core/artifacts.js +1047 -0
  20. package/dist/hoi4_agent_tools/core/artifacts.js.map +1 -0
  21. package/dist/hoi4_agent_tools/core/canonical.d.ts +13 -0
  22. package/dist/hoi4_agent_tools/core/canonical.d.ts.map +1 -0
  23. package/dist/hoi4_agent_tools/core/canonical.js +41 -0
  24. package/dist/hoi4_agent_tools/core/canonical.js.map +1 -0
  25. package/dist/hoi4_agent_tools/core/configuration.d.ts +137 -0
  26. package/dist/hoi4_agent_tools/core/configuration.d.ts.map +1 -0
  27. package/dist/hoi4_agent_tools/core/configuration.js +383 -0
  28. package/dist/hoi4_agent_tools/core/configuration.js.map +1 -0
  29. package/dist/hoi4_agent_tools/core/diagnostic-collector.d.ts +18 -0
  30. package/dist/hoi4_agent_tools/core/diagnostic-collector.d.ts.map +1 -0
  31. package/dist/hoi4_agent_tools/core/diagnostic-collector.js +45 -0
  32. package/dist/hoi4_agent_tools/core/diagnostic-collector.js.map +1 -0
  33. package/dist/hoi4_agent_tools/core/diagnostics.d.ts +26 -0
  34. package/dist/hoi4_agent_tools/core/diagnostics.d.ts.map +1 -0
  35. package/dist/hoi4_agent_tools/core/diagnostics.js +25 -0
  36. package/dist/hoi4_agent_tools/core/diagnostics.js.map +1 -0
  37. package/dist/hoi4_agent_tools/core/diff.d.ts +22 -0
  38. package/dist/hoi4_agent_tools/core/diff.d.ts.map +1 -0
  39. package/dist/hoi4_agent_tools/core/diff.js +93 -0
  40. package/dist/hoi4_agent_tools/core/diff.js.map +1 -0
  41. package/dist/hoi4_agent_tools/core/engine.d.ts +56 -0
  42. package/dist/hoi4_agent_tools/core/engine.d.ts.map +1 -0
  43. package/dist/hoi4_agent_tools/core/engine.js +319 -0
  44. package/dist/hoi4_agent_tools/core/engine.js.map +1 -0
  45. package/dist/hoi4_agent_tools/core/image-diff.d.ts +14 -0
  46. package/dist/hoi4_agent_tools/core/image-diff.d.ts.map +1 -0
  47. package/dist/hoi4_agent_tools/core/image-diff.js +121 -0
  48. package/dist/hoi4_agent_tools/core/image-diff.js.map +1 -0
  49. package/dist/hoi4_agent_tools/core/index.d.ts +64 -0
  50. package/dist/hoi4_agent_tools/core/index.d.ts.map +1 -0
  51. package/dist/hoi4_agent_tools/core/index.js +963 -0
  52. package/dist/hoi4_agent_tools/core/index.js.map +1 -0
  53. package/dist/hoi4_agent_tools/core/index.public.d.ts +16 -0
  54. package/dist/hoi4_agent_tools/core/index.public.d.ts.map +1 -0
  55. package/dist/hoi4_agent_tools/core/index.public.js +16 -0
  56. package/dist/hoi4_agent_tools/core/index.public.js.map +1 -0
  57. package/dist/hoi4_agent_tools/core/render-budget.d.ts +51 -0
  58. package/dist/hoi4_agent_tools/core/render-budget.d.ts.map +1 -0
  59. package/dist/hoi4_agent_tools/core/render-budget.js +109 -0
  60. package/dist/hoi4_agent_tools/core/render-budget.js.map +1 -0
  61. package/dist/hoi4_agent_tools/core/result.d.ts +45 -0
  62. package/dist/hoi4_agent_tools/core/result.d.ts.map +1 -0
  63. package/dist/hoi4_agent_tools/core/result.js +26 -0
  64. package/dist/hoi4_agent_tools/core/result.js.map +1 -0
  65. package/dist/hoi4_agent_tools/core/scanner.d.ts +28 -0
  66. package/dist/hoi4_agent_tools/core/scanner.d.ts.map +1 -0
  67. package/dist/hoi4_agent_tools/core/scanner.js +136 -0
  68. package/dist/hoi4_agent_tools/core/scanner.js.map +1 -0
  69. package/dist/hoi4_agent_tools/core/server-state.d.ts +31 -0
  70. package/dist/hoi4_agent_tools/core/server-state.d.ts.map +1 -0
  71. package/dist/hoi4_agent_tools/core/server-state.js +413 -0
  72. package/dist/hoi4_agent_tools/core/server-state.js.map +1 -0
  73. package/dist/hoi4_agent_tools/core/source/encoding.d.ts +10 -0
  74. package/dist/hoi4_agent_tools/core/source/encoding.d.ts.map +1 -0
  75. package/dist/hoi4_agent_tools/core/source/encoding.js +54 -0
  76. package/dist/hoi4_agent_tools/core/source/encoding.js.map +1 -0
  77. package/dist/hoi4_agent_tools/core/source/index.d.ts +7 -0
  78. package/dist/hoi4_agent_tools/core/source/index.d.ts.map +1 -0
  79. package/dist/hoi4_agent_tools/core/source/index.js +7 -0
  80. package/dist/hoi4_agent_tools/core/source/index.js.map +1 -0
  81. package/dist/hoi4_agent_tools/core/source/lexer.d.ts +30 -0
  82. package/dist/hoi4_agent_tools/core/source/lexer.d.ts.map +1 -0
  83. package/dist/hoi4_agent_tools/core/source/lexer.js +266 -0
  84. package/dist/hoi4_agent_tools/core/source/lexer.js.map +1 -0
  85. package/dist/hoi4_agent_tools/core/source/limits.d.ts +21 -0
  86. package/dist/hoi4_agent_tools/core/source/limits.d.ts.map +1 -0
  87. package/dist/hoi4_agent_tools/core/source/limits.js +49 -0
  88. package/dist/hoi4_agent_tools/core/source/limits.js.map +1 -0
  89. package/dist/hoi4_agent_tools/core/source/localisation.d.ts +20 -0
  90. package/dist/hoi4_agent_tools/core/source/localisation.d.ts.map +1 -0
  91. package/dist/hoi4_agent_tools/core/source/localisation.js +163 -0
  92. package/dist/hoi4_agent_tools/core/source/localisation.js.map +1 -0
  93. package/dist/hoi4_agent_tools/core/source/parser.d.ts +44 -0
  94. package/dist/hoi4_agent_tools/core/source/parser.d.ts.map +1 -0
  95. package/dist/hoi4_agent_tools/core/source/parser.js +334 -0
  96. package/dist/hoi4_agent_tools/core/source/parser.js.map +1 -0
  97. package/dist/hoi4_agent_tools/core/source/rewrite.d.ts +10 -0
  98. package/dist/hoi4_agent_tools/core/source/rewrite.d.ts.map +1 -0
  99. package/dist/hoi4_agent_tools/core/source/rewrite.js +28 -0
  100. package/dist/hoi4_agent_tools/core/source/rewrite.js.map +1 -0
  101. package/dist/hoi4_agent_tools/core/svg-text.d.ts +34 -0
  102. package/dist/hoi4_agent_tools/core/svg-text.d.ts.map +1 -0
  103. package/dist/hoi4_agent_tools/core/svg-text.js +127 -0
  104. package/dist/hoi4_agent_tools/core/svg-text.js.map +1 -0
  105. package/dist/hoi4_agent_tools/core/transaction-limits.d.ts +9 -0
  106. package/dist/hoi4_agent_tools/core/transaction-limits.d.ts.map +1 -0
  107. package/dist/hoi4_agent_tools/core/transaction-limits.js +9 -0
  108. package/dist/hoi4_agent_tools/core/transaction-limits.js.map +1 -0
  109. package/dist/hoi4_agent_tools/core/transactions.d.ts +162 -0
  110. package/dist/hoi4_agent_tools/core/transactions.d.ts.map +1 -0
  111. package/dist/hoi4_agent_tools/core/transactions.js +1181 -0
  112. package/dist/hoi4_agent_tools/core/transactions.js.map +1 -0
  113. package/dist/hoi4_agent_tools/core/workspace.d.ts +68 -0
  114. package/dist/hoi4_agent_tools/core/workspace.d.ts.map +1 -0
  115. package/dist/hoi4_agent_tools/core/workspace.js +794 -0
  116. package/dist/hoi4_agent_tools/core/workspace.js.map +1 -0
  117. package/dist/hoi4_agent_tools/focus/compiler.d.ts +9 -0
  118. package/dist/hoi4_agent_tools/focus/compiler.d.ts.map +1 -0
  119. package/dist/hoi4_agent_tools/focus/compiler.js +273 -0
  120. package/dist/hoi4_agent_tools/focus/compiler.js.map +1 -0
  121. package/dist/hoi4_agent_tools/focus/continuous-render.d.ts +32 -0
  122. package/dist/hoi4_agent_tools/focus/continuous-render.d.ts.map +1 -0
  123. package/dist/hoi4_agent_tools/focus/continuous-render.js +179 -0
  124. package/dist/hoi4_agent_tools/focus/continuous-render.js.map +1 -0
  125. package/dist/hoi4_agent_tools/focus/drift.d.ts +22 -0
  126. package/dist/hoi4_agent_tools/focus/drift.d.ts.map +1 -0
  127. package/dist/hoi4_agent_tools/focus/drift.js +124 -0
  128. package/dist/hoi4_agent_tools/focus/drift.js.map +1 -0
  129. package/dist/hoi4_agent_tools/focus/geometry.d.ts +17 -0
  130. package/dist/hoi4_agent_tools/focus/geometry.d.ts.map +1 -0
  131. package/dist/hoi4_agent_tools/focus/geometry.js +35 -0
  132. package/dist/hoi4_agent_tools/focus/geometry.js.map +1 -0
  133. package/dist/hoi4_agent_tools/focus/importer.d.ts +9 -0
  134. package/dist/hoi4_agent_tools/focus/importer.d.ts.map +1 -0
  135. package/dist/hoi4_agent_tools/focus/importer.js +732 -0
  136. package/dist/hoi4_agent_tools/focus/importer.js.map +1 -0
  137. package/dist/hoi4_agent_tools/focus/index.d.ts +14 -0
  138. package/dist/hoi4_agent_tools/focus/index.d.ts.map +1 -0
  139. package/dist/hoi4_agent_tools/focus/index.js +14 -0
  140. package/dist/hoi4_agent_tools/focus/index.js.map +1 -0
  141. package/dist/hoi4_agent_tools/focus/layout.d.ts +5 -0
  142. package/dist/hoi4_agent_tools/focus/layout.d.ts.map +1 -0
  143. package/dist/hoi4_agent_tools/focus/layout.js +653 -0
  144. package/dist/hoi4_agent_tools/focus/layout.js.map +1 -0
  145. package/dist/hoi4_agent_tools/focus/limits.d.ts +9 -0
  146. package/dist/hoi4_agent_tools/focus/limits.d.ts.map +1 -0
  147. package/dist/hoi4_agent_tools/focus/limits.js +9 -0
  148. package/dist/hoi4_agent_tools/focus/limits.js.map +1 -0
  149. package/dist/hoi4_agent_tools/focus/lint.d.ts +14 -0
  150. package/dist/hoi4_agent_tools/focus/lint.d.ts.map +1 -0
  151. package/dist/hoi4_agent_tools/focus/lint.js +839 -0
  152. package/dist/hoi4_agent_tools/focus/lint.js.map +1 -0
  153. package/dist/hoi4_agent_tools/focus/model.d.ts +303 -0
  154. package/dist/hoi4_agent_tools/focus/model.d.ts.map +1 -0
  155. package/dist/hoi4_agent_tools/focus/model.js +20 -0
  156. package/dist/hoi4_agent_tools/focus/model.js.map +1 -0
  157. package/dist/hoi4_agent_tools/focus/native-effects.d.ts +9 -0
  158. package/dist/hoi4_agent_tools/focus/native-effects.d.ts.map +1 -0
  159. package/dist/hoi4_agent_tools/focus/native-effects.js +563 -0
  160. package/dist/hoi4_agent_tools/focus/native-effects.js.map +1 -0
  161. package/dist/hoi4_agent_tools/focus/planning.d.ts +15 -0
  162. package/dist/hoi4_agent_tools/focus/planning.d.ts.map +1 -0
  163. package/dist/hoi4_agent_tools/focus/planning.js +241 -0
  164. package/dist/hoi4_agent_tools/focus/planning.js.map +1 -0
  165. package/dist/hoi4_agent_tools/focus/presentation.d.ts +24 -0
  166. package/dist/hoi4_agent_tools/focus/presentation.d.ts.map +1 -0
  167. package/dist/hoi4_agent_tools/focus/presentation.js +204 -0
  168. package/dist/hoi4_agent_tools/focus/presentation.js.map +1 -0
  169. package/dist/hoi4_agent_tools/focus/render.d.ts +35 -0
  170. package/dist/hoi4_agent_tools/focus/render.d.ts.map +1 -0
  171. package/dist/hoi4_agent_tools/focus/render.js +491 -0
  172. package/dist/hoi4_agent_tools/focus/render.js.map +1 -0
  173. package/dist/hoi4_agent_tools/focus/service.d.ts +82 -0
  174. package/dist/hoi4_agent_tools/focus/service.d.ts.map +1 -0
  175. package/dist/hoi4_agent_tools/focus/service.js +492 -0
  176. package/dist/hoi4_agent_tools/focus/service.js.map +1 -0
  177. package/dist/hoi4_agent_tools/focus/source-update.d.ts +6 -0
  178. package/dist/hoi4_agent_tools/focus/source-update.d.ts.map +1 -0
  179. package/dist/hoi4_agent_tools/focus/source-update.js +328 -0
  180. package/dist/hoi4_agent_tools/focus/source-update.js.map +1 -0
  181. package/dist/hoi4_agent_tools/gui/animation-manifest.d.ts +37 -0
  182. package/dist/hoi4_agent_tools/gui/animation-manifest.d.ts.map +1 -0
  183. package/dist/hoi4_agent_tools/gui/animation-manifest.js +66 -0
  184. package/dist/hoi4_agent_tools/gui/animation-manifest.js.map +1 -0
  185. package/dist/hoi4_agent_tools/gui/assets.d.ts +71 -0
  186. package/dist/hoi4_agent_tools/gui/assets.d.ts.map +1 -0
  187. package/dist/hoi4_agent_tools/gui/assets.js +629 -0
  188. package/dist/hoi4_agent_tools/gui/assets.js.map +1 -0
  189. package/dist/hoi4_agent_tools/gui/dds.d.ts +17 -0
  190. package/dist/hoi4_agent_tools/gui/dds.d.ts.map +1 -0
  191. package/dist/hoi4_agent_tools/gui/dds.js +245 -0
  192. package/dist/hoi4_agent_tools/gui/dds.js.map +1 -0
  193. package/dist/hoi4_agent_tools/gui/helpers.d.ts +101 -0
  194. package/dist/hoi4_agent_tools/gui/helpers.d.ts.map +1 -0
  195. package/dist/hoi4_agent_tools/gui/helpers.js +1072 -0
  196. package/dist/hoi4_agent_tools/gui/helpers.js.map +1 -0
  197. package/dist/hoi4_agent_tools/gui/index.d.ts +15 -0
  198. package/dist/hoi4_agent_tools/gui/index.d.ts.map +1 -0
  199. package/dist/hoi4_agent_tools/gui/index.js +15 -0
  200. package/dist/hoi4_agent_tools/gui/index.js.map +1 -0
  201. package/dist/hoi4_agent_tools/gui/layout.d.ts +6 -0
  202. package/dist/hoi4_agent_tools/gui/layout.d.ts.map +1 -0
  203. package/dist/hoi4_agent_tools/gui/layout.js +753 -0
  204. package/dist/hoi4_agent_tools/gui/layout.js.map +1 -0
  205. package/dist/hoi4_agent_tools/gui/limits.d.ts +25 -0
  206. package/dist/hoi4_agent_tools/gui/limits.d.ts.map +1 -0
  207. package/dist/hoi4_agent_tools/gui/limits.js +27 -0
  208. package/dist/hoi4_agent_tools/gui/limits.js.map +1 -0
  209. package/dist/hoi4_agent_tools/gui/renderer.d.ts +18 -0
  210. package/dist/hoi4_agent_tools/gui/renderer.d.ts.map +1 -0
  211. package/dist/hoi4_agent_tools/gui/renderer.js +388 -0
  212. package/dist/hoi4_agent_tools/gui/renderer.js.map +1 -0
  213. package/dist/hoi4_agent_tools/gui/scenario.d.ts +66 -0
  214. package/dist/hoi4_agent_tools/gui/scenario.d.ts.map +1 -0
  215. package/dist/hoi4_agent_tools/gui/scenario.js +191 -0
  216. package/dist/hoi4_agent_tools/gui/scenario.js.map +1 -0
  217. package/dist/hoi4_agent_tools/gui/source-graph.d.ts +7 -0
  218. package/dist/hoi4_agent_tools/gui/source-graph.d.ts.map +1 -0
  219. package/dist/hoi4_agent_tools/gui/source-graph.js +1074 -0
  220. package/dist/hoi4_agent_tools/gui/source-graph.js.map +1 -0
  221. package/dist/hoi4_agent_tools/gui/source-patch.d.ts +13 -0
  222. package/dist/hoi4_agent_tools/gui/source-patch.d.ts.map +1 -0
  223. package/dist/hoi4_agent_tools/gui/source-patch.js +90 -0
  224. package/dist/hoi4_agent_tools/gui/source-patch.js.map +1 -0
  225. package/dist/hoi4_agent_tools/gui/studio.d.ts +86 -0
  226. package/dist/hoi4_agent_tools/gui/studio.d.ts.map +1 -0
  227. package/dist/hoi4_agent_tools/gui/studio.js +830 -0
  228. package/dist/hoi4_agent_tools/gui/studio.js.map +1 -0
  229. package/dist/hoi4_agent_tools/gui/tga.d.ts +16 -0
  230. package/dist/hoi4_agent_tools/gui/tga.d.ts.map +1 -0
  231. package/dist/hoi4_agent_tools/gui/tga.js +157 -0
  232. package/dist/hoi4_agent_tools/gui/tga.js.map +1 -0
  233. package/dist/hoi4_agent_tools/gui/types.d.ts +322 -0
  234. package/dist/hoi4_agent_tools/gui/types.d.ts.map +1 -0
  235. package/dist/hoi4_agent_tools/gui/types.js +19 -0
  236. package/dist/hoi4_agent_tools/gui/types.js.map +1 -0
  237. package/dist/hoi4_agent_tools/gui/validators.d.ts +8 -0
  238. package/dist/hoi4_agent_tools/gui/validators.d.ts.map +1 -0
  239. package/dist/hoi4_agent_tools/gui/validators.js +951 -0
  240. package/dist/hoi4_agent_tools/gui/validators.js.map +1 -0
  241. package/dist/hoi4_agent_tools/map/bmp.d.ts +62 -0
  242. package/dist/hoi4_agent_tools/map/bmp.d.ts.map +1 -0
  243. package/dist/hoi4_agent_tools/map/bmp.js +363 -0
  244. package/dist/hoi4_agent_tools/map/bmp.js.map +1 -0
  245. package/dist/hoi4_agent_tools/map/diagnostic-limit.d.ts +5 -0
  246. package/dist/hoi4_agent_tools/map/diagnostic-limit.d.ts.map +1 -0
  247. package/dist/hoi4_agent_tools/map/diagnostic-limit.js +21 -0
  248. package/dist/hoi4_agent_tools/map/diagnostic-limit.js.map +1 -0
  249. package/dist/hoi4_agent_tools/map/index.d.ts +8 -0
  250. package/dist/hoi4_agent_tools/map/index.d.ts.map +1 -0
  251. package/dist/hoi4_agent_tools/map/index.js +8 -0
  252. package/dist/hoi4_agent_tools/map/index.js.map +1 -0
  253. package/dist/hoi4_agent_tools/map/limits.d.ts +13 -0
  254. package/dist/hoi4_agent_tools/map/limits.d.ts.map +1 -0
  255. package/dist/hoi4_agent_tools/map/limits.js +13 -0
  256. package/dist/hoi4_agent_tools/map/limits.js.map +1 -0
  257. package/dist/hoi4_agent_tools/map/model.d.ts +269 -0
  258. package/dist/hoi4_agent_tools/map/model.d.ts.map +1 -0
  259. package/dist/hoi4_agent_tools/map/model.js +1114 -0
  260. package/dist/hoi4_agent_tools/map/model.js.map +1 -0
  261. package/dist/hoi4_agent_tools/map/operations.d.ts +401 -0
  262. package/dist/hoi4_agent_tools/map/operations.d.ts.map +1 -0
  263. package/dist/hoi4_agent_tools/map/operations.js +2717 -0
  264. package/dist/hoi4_agent_tools/map/operations.js.map +1 -0
  265. package/dist/hoi4_agent_tools/map/render.d.ts +90 -0
  266. package/dist/hoi4_agent_tools/map/render.d.ts.map +1 -0
  267. package/dist/hoi4_agent_tools/map/render.js +759 -0
  268. package/dist/hoi4_agent_tools/map/render.js.map +1 -0
  269. package/dist/hoi4_agent_tools/map/service.d.ts +81 -0
  270. package/dist/hoi4_agent_tools/map/service.d.ts.map +1 -0
  271. package/dist/hoi4_agent_tools/map/service.js +695 -0
  272. package/dist/hoi4_agent_tools/map/service.js.map +1 -0
  273. package/dist/hoi4_agent_tools/map/validation.d.ts +23 -0
  274. package/dist/hoi4_agent_tools/map/validation.d.ts.map +1 -0
  275. package/dist/hoi4_agent_tools/map/validation.js +1177 -0
  276. package/dist/hoi4_agent_tools/map/validation.js.map +1 -0
  277. package/dist/hoi4_agent_tools/mcp/prompts/register.d.ts +3 -0
  278. package/dist/hoi4_agent_tools/mcp/prompts/register.d.ts.map +1 -0
  279. package/dist/hoi4_agent_tools/mcp/prompts/register.js +50 -0
  280. package/dist/hoi4_agent_tools/mcp/prompts/register.js.map +1 -0
  281. package/dist/hoi4_agent_tools/mcp/registry/metadata.d.ts +9 -0
  282. package/dist/hoi4_agent_tools/mcp/registry/metadata.d.ts.map +1 -0
  283. package/dist/hoi4_agent_tools/mcp/registry/metadata.js +10 -0
  284. package/dist/hoi4_agent_tools/mcp/registry/metadata.js.map +1 -0
  285. package/dist/hoi4_agent_tools/mcp/resources/register.d.ts +5 -0
  286. package/dist/hoi4_agent_tools/mcp/resources/register.d.ts.map +1 -0
  287. package/dist/hoi4_agent_tools/mcp/resources/register.js +278 -0
  288. package/dist/hoi4_agent_tools/mcp/resources/register.js.map +1 -0
  289. package/dist/hoi4_agent_tools/mcp/security/auth.d.ts +24 -0
  290. package/dist/hoi4_agent_tools/mcp/security/auth.d.ts.map +1 -0
  291. package/dist/hoi4_agent_tools/mcp/security/auth.js +234 -0
  292. package/dist/hoi4_agent_tools/mcp/security/auth.js.map +1 -0
  293. package/dist/hoi4_agent_tools/mcp/server/base-tools.d.ts +35 -0
  294. package/dist/hoi4_agent_tools/mcp/server/base-tools.d.ts.map +1 -0
  295. package/dist/hoi4_agent_tools/mcp/server/base-tools.js +835 -0
  296. package/dist/hoi4_agent_tools/mcp/server/base-tools.js.map +1 -0
  297. package/dist/hoi4_agent_tools/mcp/server/create.d.ts +5 -0
  298. package/dist/hoi4_agent_tools/mcp/server/create.d.ts.map +1 -0
  299. package/dist/hoi4_agent_tools/mcp/server/create.js +26 -0
  300. package/dist/hoi4_agent_tools/mcp/server/create.js.map +1 -0
  301. package/dist/hoi4_agent_tools/mcp/server/output-schemas.d.ts +133 -0
  302. package/dist/hoi4_agent_tools/mcp/server/output-schemas.d.ts.map +1 -0
  303. package/dist/hoi4_agent_tools/mcp/server/output-schemas.js +127 -0
  304. package/dist/hoi4_agent_tools/mcp/server/output-schemas.js.map +1 -0
  305. package/dist/hoi4_agent_tools/mcp/server/progress.d.ts +8 -0
  306. package/dist/hoi4_agent_tools/mcp/server/progress.d.ts.map +1 -0
  307. package/dist/hoi4_agent_tools/mcp/server/progress.js +21 -0
  308. package/dist/hoi4_agent_tools/mcp/server/progress.js.map +1 -0
  309. package/dist/hoi4_agent_tools/mcp/server/result.d.ts +232 -0
  310. package/dist/hoi4_agent_tools/mcp/server/result.d.ts.map +1 -0
  311. package/dist/hoi4_agent_tools/mcp/server/result.js +353 -0
  312. package/dist/hoi4_agent_tools/mcp/server/result.js.map +1 -0
  313. package/dist/hoi4_agent_tools/mcp/tools/focus.d.ts +5 -0
  314. package/dist/hoi4_agent_tools/mcp/tools/focus.d.ts.map +1 -0
  315. package/dist/hoi4_agent_tools/mcp/tools/focus.js +1059 -0
  316. package/dist/hoi4_agent_tools/mcp/tools/focus.js.map +1 -0
  317. package/dist/hoi4_agent_tools/mcp/tools/gui.d.ts +111 -0
  318. package/dist/hoi4_agent_tools/mcp/tools/gui.d.ts.map +1 -0
  319. package/dist/hoi4_agent_tools/mcp/tools/gui.js +598 -0
  320. package/dist/hoi4_agent_tools/mcp/tools/gui.js.map +1 -0
  321. package/dist/hoi4_agent_tools/mcp/tools/map.d.ts +5 -0
  322. package/dist/hoi4_agent_tools/mcp/tools/map.d.ts.map +1 -0
  323. package/dist/hoi4_agent_tools/mcp/tools/map.js +685 -0
  324. package/dist/hoi4_agent_tools/mcp/tools/map.js.map +1 -0
  325. package/dist/hoi4_agent_tools/mcp/transports/bounded-stdio.d.ts +58 -0
  326. package/dist/hoi4_agent_tools/mcp/transports/bounded-stdio.d.ts.map +1 -0
  327. package/dist/hoi4_agent_tools/mcp/transports/bounded-stdio.js +181 -0
  328. package/dist/hoi4_agent_tools/mcp/transports/bounded-stdio.js.map +1 -0
  329. package/dist/hoi4_agent_tools/mcp/transports/event-store.d.ts +26 -0
  330. package/dist/hoi4_agent_tools/mcp/transports/event-store.d.ts.map +1 -0
  331. package/dist/hoi4_agent_tools/mcp/transports/event-store.js +86 -0
  332. package/dist/hoi4_agent_tools/mcp/transports/event-store.js.map +1 -0
  333. package/dist/hoi4_agent_tools/mcp/transports/http.d.ts +28 -0
  334. package/dist/hoi4_agent_tools/mcp/transports/http.d.ts.map +1 -0
  335. package/dist/hoi4_agent_tools/mcp/transports/http.js +744 -0
  336. package/dist/hoi4_agent_tools/mcp/transports/http.js.map +1 -0
  337. package/dist/hoi4_agent_tools/mcp/transports/protocol-gate.d.ts +15 -0
  338. package/dist/hoi4_agent_tools/mcp/transports/protocol-gate.d.ts.map +1 -0
  339. package/dist/hoi4_agent_tools/mcp/transports/protocol-gate.js +51 -0
  340. package/dist/hoi4_agent_tools/mcp/transports/protocol-gate.js.map +1 -0
  341. package/dist/hoi4_agent_tools/runtime.d.ts +4 -0
  342. package/dist/hoi4_agent_tools/runtime.d.ts.map +1 -0
  343. package/dist/hoi4_agent_tools/runtime.js +27 -0
  344. package/dist/hoi4_agent_tools/runtime.js.map +1 -0
  345. package/dist/hoi4_agent_tools/schemas/common.d.ts +74 -0
  346. package/dist/hoi4_agent_tools/schemas/common.d.ts.map +1 -0
  347. package/dist/hoi4_agent_tools/schemas/common.js +51 -0
  348. package/dist/hoi4_agent_tools/schemas/common.js.map +1 -0
  349. package/dist/hoi4_agent_tools/schemas/focus.d.ts +784 -0
  350. package/dist/hoi4_agent_tools/schemas/focus.d.ts.map +1 -0
  351. package/dist/hoi4_agent_tools/schemas/focus.js +330 -0
  352. package/dist/hoi4_agent_tools/schemas/focus.js.map +1 -0
  353. package/dist/hoi4_agent_tools/schemas/index.d.ts +5 -0
  354. package/dist/hoi4_agent_tools/schemas/index.d.ts.map +1 -0
  355. package/dist/hoi4_agent_tools/schemas/index.js +5 -0
  356. package/dist/hoi4_agent_tools/schemas/index.js.map +1 -0
  357. package/dist/hoi4_agent_tools/schemas/map.d.ts +654 -0
  358. package/dist/hoi4_agent_tools/schemas/map.d.ts.map +1 -0
  359. package/dist/hoi4_agent_tools/schemas/map.js +570 -0
  360. package/dist/hoi4_agent_tools/schemas/map.js.map +1 -0
  361. package/dist/hoi4_agent_tools/schemas/transaction.d.ts +259 -0
  362. package/dist/hoi4_agent_tools/schemas/transaction.d.ts.map +1 -0
  363. package/dist/hoi4_agent_tools/schemas/transaction.js +104 -0
  364. package/dist/hoi4_agent_tools/schemas/transaction.js.map +1 -0
  365. package/dist/hoi4_agent_tools/version.d.ts +6 -0
  366. package/dist/hoi4_agent_tools/version.d.ts.map +1 -0
  367. package/dist/hoi4_agent_tools/version.js +7 -0
  368. package/dist/hoi4_agent_tools/version.js.map +1 -0
  369. package/dist/index.d.ts +3 -0
  370. package/dist/index.d.ts.map +1 -0
  371. package/dist/index.js +3 -0
  372. package/dist/index.js.map +1 -0
  373. package/docs/README.md +22 -0
  374. package/docs/adr/0001-runtime-and-language.md +16 -0
  375. package/docs/adr/0002-lossless-source-model.md +18 -0
  376. package/docs/adr/0003-image-and-font-codecs.md +18 -0
  377. package/docs/adr/0004-focus-layout.md +16 -0
  378. package/docs/adr/0005-offline-rendering.md +18 -0
  379. package/docs/adr/0006-mcp-sdk-and-protocol.md +16 -0
  380. package/docs/adr/0007-storage-and-transactions.md +24 -0
  381. package/docs/adr/0008-test-strategy.md +18 -0
  382. package/docs/adr/0009-packaging-and-registry.md +16 -0
  383. package/docs/adr/0010-unsupported-and-refusal-policy.md +18 -0
  384. package/docs/adr/0011-http-security.md +16 -0
  385. package/docs/adr/README.md +13 -0
  386. package/docs/architecture.md +60 -0
  387. package/docs/artifacts.md +133 -0
  388. package/docs/compatibility.md +33 -0
  389. package/docs/completion-report.md +69 -0
  390. package/docs/configuration.md +285 -0
  391. package/docs/focus-workflow.md +68 -0
  392. package/docs/gui-workflow.md +121 -0
  393. package/docs/limitations.md +30 -0
  394. package/docs/map-workflow.md +89 -0
  395. package/docs/performance.md +117 -0
  396. package/docs/release.md +200 -0
  397. package/docs/research/mcp-2026-07-10.md +46 -0
  398. package/docs/research/source-ledger.md +68 -0
  399. package/docs/security.md +139 -0
  400. package/docs/self-hosting.md +168 -0
  401. package/docs/testing.md +43 -0
  402. package/docs/third-party-notices.md +11 -0
  403. package/docs/transactions.md +162 -0
  404. package/docs/troubleshooting.md +46 -0
  405. package/package.json +98 -5
  406. package/schemas/configuration.schema.json +794 -0
  407. package/schemas/continuous-focus-palette.schema.json +325 -0
  408. package/schemas/focus-plan.schema.json +902 -0
  409. package/schemas/focus-planning-sidecar.schema.json +364 -0
  410. package/schemas/gui-animation-source.schema.json +176 -0
  411. package/schemas/gui-helper.schema.json +301 -0
  412. package/schemas/gui-scenario.schema.json +298 -0
  413. package/schemas/map-operation.schema.json +2284 -0
  414. package/schemas/operation-result.schema.json +344 -0
  415. package/schemas/transaction-manifest.schema.json +685 -0
  416. package/server.json +32 -0
@@ -0,0 +1,1072 @@
1
+ import { compareCodeUnits, deterministicId } from '../core/canonical.js';
2
+ import { ServiceError } from '../core/result.js';
3
+ import { assignments, parseClausewitz, SOURCE_MAX_BYTES, } from '../core/source/index.js';
4
+ import { z } from 'zod';
5
+ const scalarSchema = z.union([z.string(), z.number(), z.boolean()]);
6
+ const guiAttributeKeySchema = z
7
+ .string()
8
+ .regex(/^[A-Za-z_][A-Za-z0-9_]*$/u, 'GUI helper attribute keys must be safe identifiers');
9
+ const attributesSchema = z.record(guiAttributeKeySchema, scalarSchema).default({});
10
+ const insetSchema = z.union([
11
+ z.number(),
12
+ z
13
+ .object({
14
+ top: z.number().default(0),
15
+ right: z.number().default(0),
16
+ bottom: z.number().default(0),
17
+ left: z.number().default(0),
18
+ })
19
+ .strict(),
20
+ ]);
21
+ export const guiAnchorPoints = [
22
+ 'center',
23
+ 'center_up',
24
+ 'center_upper',
25
+ 'center_down',
26
+ 'center_lower',
27
+ 'center_left',
28
+ 'center_right',
29
+ 'upper_left',
30
+ 'lower_left',
31
+ 'upper_right',
32
+ 'lower_right',
33
+ ];
34
+ const anchorPointSet = new Set(guiAnchorPoints);
35
+ export const guiHelperKinds = [
36
+ 'raw',
37
+ 'template',
38
+ 'anchor',
39
+ 'row',
40
+ 'column',
41
+ 'stack',
42
+ 'grid',
43
+ 'card',
44
+ 'tabs',
45
+ 'scroll-list',
46
+ 'target-row',
47
+ 'meter',
48
+ 'status-panel',
49
+ 'modal',
50
+ 'overlay',
51
+ 'element',
52
+ ];
53
+ export const GUI_HELPER_MAX_DEPTH = 128;
54
+ export const GUI_HELPER_MAX_NODES = 10_000;
55
+ export const GUI_HELPER_MAX_TEMPLATES = 1_024;
56
+ export const GUI_HELPER_MAX_STATE_VARIANTS = 64;
57
+ export const GUI_HELPER_MAX_EXPANDED_IDENTIFIER_BYTES = 1_024;
58
+ export const GUI_HELPER_MAX_GENERATED_SOURCE_WORK = SOURCE_MAX_BYTES * 2;
59
+ export const GUI_HELPER_MAX_GENERATED_SOURCE_BYTES = SOURCE_MAX_BYTES;
60
+ function helperInputRoots(input) {
61
+ if (input === null || typeof input !== 'object')
62
+ return [];
63
+ const document = input;
64
+ const roots = document.root === undefined ? [] : [document.root];
65
+ if (!Array.isArray(document.templates))
66
+ return roots;
67
+ for (const template of document.templates) {
68
+ if (template !== null && typeof template === 'object' && 'root' in template)
69
+ roots.push(template.root);
70
+ }
71
+ return roots;
72
+ }
73
+ function assertGuiHelperInputBudget(input) {
74
+ if (input !== null && typeof input === 'object') {
75
+ const templates = input.templates;
76
+ if (Array.isArray(templates) && templates.length > GUI_HELPER_MAX_TEMPLATES) {
77
+ throw new ServiceError('GUI_HELPER_TEMPLATE_BUDGET_BLOCKED', 'GUI helper input exceeds the fixed template ceiling', { templates: templates.length, maximumTemplates: GUI_HELPER_MAX_TEMPLATES });
78
+ }
79
+ }
80
+ const pending = helperInputRoots(input).map((value) => ({ value, depth: 1 }));
81
+ const seen = new WeakSet();
82
+ let nodes = 0;
83
+ while (pending.length > 0) {
84
+ const current = pending.pop();
85
+ if (current.value === null || typeof current.value !== 'object')
86
+ continue;
87
+ if (seen.has(current.value)) {
88
+ throw new ServiceError('GUI_HELPER_GRAPH_BLOCKED', 'GUI helper input must contain independent acyclic trees');
89
+ }
90
+ seen.add(current.value);
91
+ nodes += 1;
92
+ if (nodes > GUI_HELPER_MAX_NODES) {
93
+ throw new ServiceError('GUI_HELPER_NODE_BUDGET_BLOCKED', 'GUI helper input exceeds the fixed source-node ceiling', { nodes, maximumNodes: GUI_HELPER_MAX_NODES, stage: 'source' });
94
+ }
95
+ if (current.depth > GUI_HELPER_MAX_DEPTH) {
96
+ throw new ServiceError('GUI_HELPER_DEPTH_BUDGET_BLOCKED', 'GUI helper input exceeds the fixed source nesting ceiling', { depth: current.depth, maximumDepth: GUI_HELPER_MAX_DEPTH, stage: 'source' });
97
+ }
98
+ const children = current.value.children;
99
+ if (!Array.isArray(children))
100
+ continue;
101
+ for (let index = children.length - 1; index >= 0; index -= 1)
102
+ pending.push({ value: children[index], depth: current.depth + 1 });
103
+ }
104
+ }
105
+ const GuiHelperStateVariantSchema = z
106
+ .object({
107
+ state: z.string().min(1).max(128),
108
+ frame: z.number().int().min(0).optional(),
109
+ sprite: z.string().min(1).optional(),
110
+ text: z.string().optional(),
111
+ font: z.string().min(1).optional(),
112
+ attributes: attributesSchema,
113
+ })
114
+ .strict()
115
+ .superRefine((variant, context) => {
116
+ if (variant.frame === undefined &&
117
+ variant.sprite === undefined &&
118
+ variant.text === undefined &&
119
+ variant.font === undefined &&
120
+ Object.keys(variant.attributes).length === 0)
121
+ context.addIssue({
122
+ code: 'custom',
123
+ message: 'A GUI helper state variant must change a frame, sprite, text, font, or attribute',
124
+ });
125
+ });
126
+ const GuiHelperNodeSchema = z.lazy(() => z
127
+ .object({
128
+ id: z.string().min(1).max(256),
129
+ kind: z.enum(guiHelperKinds),
130
+ templateId: z.string().min(1).max(256).optional(),
131
+ name: z.string().min(1).max(256).optional(),
132
+ elementType: z.string().min(1).max(256).optional(),
133
+ x: z.number().optional(),
134
+ y: z.number().optional(),
135
+ width: z.number().nonnegative().optional(),
136
+ height: z.number().nonnegative().optional(),
137
+ gap: z.number().nonnegative().optional(),
138
+ columns: z.number().int().positive().max(GUI_HELPER_MAX_NODES).optional(),
139
+ padding: insetSchema.optional(),
140
+ margin: insetSchema.optional(),
141
+ orientation: z.string().min(1).max(64).optional(),
142
+ origo: z.string().min(1).max(64).optional(),
143
+ flow: z.enum(['horizontal', 'vertical']).optional(),
144
+ sprite: z.string().min(1).optional(),
145
+ backgroundSprite: z.string().min(1).optional(),
146
+ scrollbar: z.string().min(1).optional(),
147
+ text: z.string().optional(),
148
+ font: z.string().min(1).optional(),
149
+ state: z.string().min(1).max(128).optional(),
150
+ stateVariants: z
151
+ .array(GuiHelperStateVariantSchema)
152
+ .max(GUI_HELPER_MAX_STATE_VARIANTS)
153
+ .default([]),
154
+ minValue: z.number().optional(),
155
+ maxValue: z.number().optional(),
156
+ value: z.number().optional(),
157
+ frames: z.number().int().min(2).max(10_000).optional(),
158
+ attributes: attributesSchema,
159
+ raw: z.string().optional(),
160
+ children: z.array(GuiHelperNodeSchema).default([]),
161
+ })
162
+ .strict());
163
+ const GuiHelperTemplateSchema = z
164
+ .object({
165
+ id: z.string().min(1).max(256),
166
+ root: GuiHelperNodeSchema,
167
+ })
168
+ .strict();
169
+ export const GuiHelperDocumentSchema = z.preprocess((input) => {
170
+ assertGuiHelperInputBudget(input);
171
+ return input;
172
+ }, z
173
+ .object({
174
+ version: z.literal(1).default(1),
175
+ templates: z.array(GuiHelperTemplateSchema).max(GUI_HELPER_MAX_TEMPLATES).default([]),
176
+ root: GuiHelperNodeSchema,
177
+ })
178
+ .strict());
179
+ function normalizedAnchorPoint(value) {
180
+ return value.toLowerCase();
181
+ }
182
+ function isAnchorPoint(value) {
183
+ return anchorPointSet.has(normalizedAnchorPoint(value));
184
+ }
185
+ function insets(value) {
186
+ return typeof value === 'number'
187
+ ? { top: value, right: value, bottom: value, left: value }
188
+ : (value ?? { top: 0, right: 0, bottom: 0, left: 0 });
189
+ }
190
+ function walkNodes(root) {
191
+ const output = [];
192
+ const pending = [root];
193
+ while (pending.length > 0) {
194
+ const node = pending.pop();
195
+ output.push(node);
196
+ for (let index = node.children.length - 1; index >= 0; index -= 1)
197
+ pending.push(node.children[index]);
198
+ }
199
+ return output;
200
+ }
201
+ function assertUniqueNodeIds(root, scope) {
202
+ const seen = new Set();
203
+ for (const node of walkNodes(root)) {
204
+ if (seen.has(node.id))
205
+ throw new ServiceError('GUI_HELPER_DUPLICATE_ID', `GUI helper ${scope} contains duplicate node id ${node.id}`, { id: node.id, scope });
206
+ seen.add(node.id);
207
+ }
208
+ }
209
+ function templateReferences(root) {
210
+ return walkNodes(root).flatMap((node) => node.kind === 'template' && node.templateId !== undefined ? [node.templateId] : []);
211
+ }
212
+ function assertTemplateGraph(document) {
213
+ const templates = new Map();
214
+ for (const template of document.templates) {
215
+ if (templates.has(template.id))
216
+ throw new ServiceError('GUI_HELPER_TEMPLATE_DUPLICATE', `GUI helper template ${template.id} is declared more than once`, { templateId: template.id });
217
+ templates.set(template.id, template);
218
+ }
219
+ const assertReferencesExist = (root, scope) => {
220
+ for (const reference of templateReferences(root))
221
+ if (!templates.has(reference))
222
+ throw new ServiceError('GUI_HELPER_TEMPLATE_MISSING', `GUI helper ${scope} references missing template ${reference}`, { templateId: reference, scope });
223
+ };
224
+ assertReferencesExist(document.root, 'root');
225
+ for (const template of document.templates)
226
+ assertReferencesExist(template.root, template.id);
227
+ const visiting = new Set();
228
+ const longestPaths = new Map();
229
+ const visit = (templateId, stack) => {
230
+ if (visiting.has(templateId)) {
231
+ const start = stack.indexOf(templateId);
232
+ const cycle = [...stack.slice(Math.max(0, start)), templateId];
233
+ throw new ServiceError('GUI_HELPER_TEMPLATE_CYCLE', `GUI helper template cycle: ${cycle.join(' -> ')}`, { cycle });
234
+ }
235
+ const cached = longestPaths.get(templateId);
236
+ if (cached !== undefined) {
237
+ if (stack.length + cached > GUI_HELPER_MAX_DEPTH)
238
+ throw new ServiceError('GUI_HELPER_DEPTH_BUDGET_BLOCKED', 'GUI helper template reference depth exceeds the fixed nesting ceiling', {
239
+ depth: stack.length + cached,
240
+ maximumDepth: GUI_HELPER_MAX_DEPTH,
241
+ stage: 'template-graph',
242
+ });
243
+ return cached;
244
+ }
245
+ if (stack.length >= GUI_HELPER_MAX_DEPTH)
246
+ throw new ServiceError('GUI_HELPER_DEPTH_BUDGET_BLOCKED', 'GUI helper template reference depth exceeds the fixed nesting ceiling', { depth: stack.length + 1, maximumDepth: GUI_HELPER_MAX_DEPTH, stage: 'template-graph' });
247
+ visiting.add(templateId);
248
+ const template = templates.get(templateId);
249
+ let longestPath = 1;
250
+ for (const dependency of new Set(templateReferences(template.root)))
251
+ longestPath = Math.max(longestPath, 1 + visit(dependency, [...stack, templateId]));
252
+ visiting.delete(templateId);
253
+ if (longestPath > GUI_HELPER_MAX_DEPTH)
254
+ throw new ServiceError('GUI_HELPER_DEPTH_BUDGET_BLOCKED', 'GUI helper template reference depth exceeds the fixed nesting ceiling', {
255
+ depth: longestPath,
256
+ maximumDepth: GUI_HELPER_MAX_DEPTH,
257
+ stage: 'template-graph',
258
+ });
259
+ longestPaths.set(templateId, longestPath);
260
+ return longestPath;
261
+ };
262
+ for (const templateId of templates.keys())
263
+ visit(templateId, []);
264
+ return templates;
265
+ }
266
+ const buttonElementTypes = new Set(['buttonType']);
267
+ const iconElementTypes = new Set(['iconType']);
268
+ const textElementTypes = new Set(['instantTextBoxType']);
269
+ const containerElementTypes = new Set(['containerWindowType', 'windowType']);
270
+ const leafElementTypes = new Set([...buttonElementTypes, ...iconElementTypes, ...textElementTypes]);
271
+ const supportedElementTypes = new Set([...leafElementTypes, ...containerElementTypes]);
272
+ const runtimeButtonStates = new Set(['normal', 'hover', 'pressed', 'disabled']);
273
+ const controlledAttributeKeys = new Set([
274
+ 'name',
275
+ 'position',
276
+ 'size',
277
+ 'orientation',
278
+ 'origo',
279
+ 'spriteType',
280
+ 'quadTextureSprite',
281
+ 'text',
282
+ 'font',
283
+ 'buttonText',
284
+ 'buttonFont',
285
+ 'frame',
286
+ 'background',
287
+ 'minValue',
288
+ 'maxValue',
289
+ 'startValue',
290
+ 'maxWidth',
291
+ 'maxHeight',
292
+ ].map((key) => key.toLowerCase()));
293
+ const scrollListControlledAttributeKeys = new Set([
294
+ 'clipping',
295
+ 'horizontalScrollbar',
296
+ 'verticalScrollbar',
297
+ 'scroll_wheel_factor',
298
+ 'smooth_scrolling',
299
+ 'gridBoxType',
300
+ ].map((key) => key.toLowerCase()));
301
+ const containerAttributeKeys = new Set(['clipping', 'moveable', 'fullScreen'].map((key) => key.toLowerCase()));
302
+ const iconAttributeKeys = new Set(['alwaystransparent', 'hint_tag', 'pdx_tooltip', 'pdx_tooltip_delayed', 'centerposition'].map((key) => key.toLowerCase()));
303
+ const textAttributeKeys = new Set([
304
+ 'format',
305
+ 'fixedsize',
306
+ 'alwaystransparent',
307
+ 'scrollbarType',
308
+ 'pdx_tooltip',
309
+ 'pdx_tooltip_delayed',
310
+ ].map((key) => key.toLowerCase()));
311
+ const buttonAttributeKeys = new Set([
312
+ 'alwaystransparent',
313
+ 'shortcut',
314
+ 'clicksound',
315
+ 'oversound',
316
+ 'hint_tag',
317
+ 'pdx_tooltip',
318
+ 'pdx_tooltip_delayed',
319
+ 'scale',
320
+ 'web_link',
321
+ ].map((key) => key.toLowerCase()));
322
+ function allowedAttributeKeys(node) {
323
+ if (node.kind === 'template')
324
+ return undefined;
325
+ if (node.kind === 'raw')
326
+ return new Set();
327
+ const elementType = typeFor(node);
328
+ if (containerElementTypes.has(elementType))
329
+ return containerAttributeKeys;
330
+ if (iconElementTypes.has(elementType))
331
+ return iconAttributeKeys;
332
+ if (textElementTypes.has(elementType))
333
+ return textAttributeKeys;
334
+ if (buttonElementTypes.has(elementType))
335
+ return buttonAttributeKeys;
336
+ return new Set();
337
+ }
338
+ function assertStructuredElementFields(node, elementType, variant, scope) {
339
+ const sprite = variant?.sprite ?? node.sprite;
340
+ const text = variant?.text ?? node.text;
341
+ const font = variant?.font ?? node.font;
342
+ const frame = variant?.frame;
343
+ if (iconElementTypes.has(elementType) && (text !== undefined || font !== undefined))
344
+ throw new ServiceError('GUI_HELPER_ICON_TEXT_UNSUPPORTED', `GUI helper icon ${node.id} cannot emit text or font fields`, { id: node.id, elementType, state: variant?.state, scope });
345
+ if (textElementTypes.has(elementType) && (sprite !== undefined || frame !== undefined))
346
+ throw new ServiceError('GUI_HELPER_TEXT_SPRITE_UNSUPPORTED', `GUI helper text box ${node.id} cannot emit sprite or frame fields`, { id: node.id, elementType, state: variant?.state, scope });
347
+ if (containerElementTypes.has(elementType) &&
348
+ node.kind !== 'card' &&
349
+ node.kind !== 'modal' &&
350
+ node.kind !== 'meter' &&
351
+ (sprite !== undefined || text !== undefined || font !== undefined || frame !== undefined))
352
+ throw new ServiceError('GUI_HELPER_CONTAINER_FIELDS_UNSUPPORTED', `GUI helper container ${node.id} cannot emit sprite, text, font, or frame fields directly`, { id: node.id, elementType, state: variant?.state, scope });
353
+ if ((node.kind === 'card' || node.kind === 'modal') &&
354
+ (text !== undefined || font !== undefined || frame !== undefined))
355
+ throw new ServiceError('GUI_HELPER_BACKGROUND_STATE_UNSUPPORTED', `GUI helper ${node.kind} ${node.id} supports sprite-only background state variants`, { id: node.id, state: variant?.state, scope });
356
+ if (node.kind === 'meter' && (text !== undefined || font !== undefined))
357
+ throw new ServiceError('GUI_HELPER_METER_FIELDS_UNSUPPORTED', `GUI helper meter ${node.id} supports sprite, frame, and scalar-attribute state changes, but not text or font fields`, { id: node.id, state: variant?.state, scope });
358
+ }
359
+ const kindSpecificFields = [
360
+ ['columns', ['grid']],
361
+ ['flow', ['scroll-list']],
362
+ ['backgroundSprite', ['card', 'scroll-list', 'meter', 'modal']],
363
+ ['scrollbar', ['scroll-list']],
364
+ ['minValue', ['meter']],
365
+ ['maxValue', ['meter']],
366
+ ['value', ['meter']],
367
+ ['frames', ['meter']],
368
+ ];
369
+ function assertNodeSemantics(root, scope) {
370
+ for (const node of walkNodes(root)) {
371
+ const variants = new Set();
372
+ for (const variant of node.stateVariants ?? []) {
373
+ if (variants.has(variant.state))
374
+ throw new ServiceError('GUI_HELPER_STATE_VARIANT_DUPLICATE', `GUI helper node ${node.id} declares state ${variant.state} more than once`, { id: node.id, state: variant.state, scope });
375
+ variants.add(variant.state);
376
+ }
377
+ if (node.kind === 'template') {
378
+ if (node.templateId === undefined)
379
+ throw new ServiceError('GUI_HELPER_TEMPLATE_ID_MISSING', `GUI helper template instance ${node.id} must name templateId`, { id: node.id, scope });
380
+ if (node.children.length > 0)
381
+ throw new ServiceError('GUI_HELPER_TEMPLATE_CHILDREN_UNSUPPORTED', `GUI helper template instance ${node.id} cannot append children`, { id: node.id, scope });
382
+ }
383
+ else if (node.templateId !== undefined) {
384
+ throw new ServiceError('GUI_HELPER_TEMPLATE_ID_UNEXPECTED', `GUI helper node ${node.id} is not a template instance but declares templateId`, { id: node.id, scope });
385
+ }
386
+ if (node.kind !== 'template')
387
+ for (const [field, allowedKinds] of kindSpecificFields)
388
+ if (node[field] !== undefined &&
389
+ !allowedKinds.includes(node.kind))
390
+ throw new ServiceError('GUI_HELPER_FIELD_UNSUPPORTED', `GUI helper ${node.kind} node ${node.id} cannot use ${field}`, { id: node.id, kind: node.kind, field, allowedKinds, scope });
391
+ if (node.kind === 'raw' && node.raw === undefined)
392
+ throw new ServiceError('GUI_HELPER_RAW_MISSING', `GUI helper raw node ${node.id} must provide raw source`, { id: node.id, scope });
393
+ if ((node.kind === 'raw' || node.kind === 'meter') && node.children.length > 0)
394
+ throw new ServiceError('GUI_HELPER_CHILDREN_UNSUPPORTED', `GUI helper ${node.kind} node ${node.id} cannot contain children`, { id: node.id, kind: node.kind, scope });
395
+ if (node.kind === 'anchor') {
396
+ for (const [field, value] of [
397
+ ['orientation', node.orientation ?? 'upper_left'],
398
+ ['origo', node.origo ?? 'upper_left'],
399
+ ])
400
+ if (!isAnchorPoint(value))
401
+ throw new ServiceError('GUI_HELPER_ANCHOR_POINT_INVALID', `GUI helper anchor ${node.id} has invalid ${field} ${value}`, { id: node.id, field, value, scope });
402
+ }
403
+ else if (node.orientation !== undefined && !isAnchorPoint(node.orientation)) {
404
+ throw new ServiceError('GUI_HELPER_ORIENTATION_INVALID', `GUI helper node ${node.id} has invalid orientation ${node.orientation}`, { id: node.id, value: node.orientation, scope });
405
+ }
406
+ if (node.kind !== 'anchor' && node.origo !== undefined && !isAnchorPoint(node.origo)) {
407
+ throw new ServiceError('GUI_HELPER_ORIGO_INVALID', `GUI helper node ${node.id} has invalid origo ${node.origo}`, { id: node.id, value: node.origo, scope });
408
+ }
409
+ if (node.kind === 'meter') {
410
+ const minimum = node.minValue ?? 0;
411
+ const maximum = node.maxValue ?? 100;
412
+ const value = node.value ?? minimum;
413
+ if (maximum <= minimum ||
414
+ value < minimum ||
415
+ value > maximum ||
416
+ node.sprite === undefined ||
417
+ node.frames === undefined ||
418
+ node.width === undefined ||
419
+ node.width <= 0 ||
420
+ node.height === undefined ||
421
+ node.height <= 0 ||
422
+ (node.stateVariants ?? []).some(({ frame }) => frame !== undefined && frame > node.frames))
423
+ throw new ServiceError('GUI_HELPER_METER_RANGE_INVALID', `GUI helper meter ${node.id} requires positive layout dimensions, a sprite with at least two frames, minValue < maxValue, and minValue <= value <= maxValue`, {
424
+ id: node.id,
425
+ minValue: minimum,
426
+ maxValue: maximum,
427
+ value,
428
+ sprite: node.sprite,
429
+ frames: node.frames,
430
+ scope,
431
+ });
432
+ }
433
+ if (node.kind === 'scroll-list') {
434
+ if (node.children.length !== 1 ||
435
+ node.backgroundSprite === undefined ||
436
+ node.scrollbar === undefined ||
437
+ node.width === undefined ||
438
+ node.width <= 0 ||
439
+ node.height === undefined ||
440
+ node.height <= 0)
441
+ throw new ServiceError('GUI_HELPER_SCROLL_LIST_BINDING_INCOMPLETE', `GUI helper scroll-list ${node.id} requires width, height, backgroundSprite, scrollbar, and exactly one entry-container child`, { id: node.id, children: node.children.length, scope });
442
+ const entryNode = node.children[0];
443
+ const entryType = typeFor(entryNode);
444
+ if (entryNode.kind !== 'template' &&
445
+ (entryNode.kind === 'raw' || !containerElementTypes.has(entryType)))
446
+ throw new ServiceError('GUI_HELPER_SCROLL_ENTRY_INVALID', `GUI helper scroll-list ${node.id} entry must compile to a container`, { id: node.id, entryKind: entryNode.kind, entryType, scope });
447
+ }
448
+ if (node.kind !== 'template' && node.elementType !== undefined && node.kind !== 'element')
449
+ throw new ServiceError('GUI_HELPER_ELEMENT_TYPE_UNEXPECTED', `GUI helper ${node.kind} node ${node.id} cannot override elementType`, { id: node.id, kind: node.kind, scope });
450
+ if (node.kind !== 'template' && node.kind !== 'raw') {
451
+ if (node.kind === 'element' &&
452
+ node.elementType === undefined &&
453
+ node.sprite !== undefined &&
454
+ (node.text !== undefined || node.font !== undefined))
455
+ throw new ServiceError('GUI_HELPER_ELEMENT_FIELDS_AMBIGUOUS', `GUI helper element ${node.id} combines icon and text fields without an explicit buttonType`, { id: node.id, scope });
456
+ const elementType = typeFor(node);
457
+ if (!supportedElementTypes.has(elementType))
458
+ throw new ServiceError('GUI_HELPER_ELEMENT_TYPE_UNSUPPORTED', `GUI helper node ${node.id} uses unsupported structured element type ${elementType}; use a raw node for advanced types`, { id: node.id, elementType, scope });
459
+ if (leafElementTypes.has(elementType) && node.children.length > 0)
460
+ throw new ServiceError('GUI_HELPER_LEAF_CHILDREN_UNSUPPORTED', `GUI helper leaf element ${node.id} cannot contain child GUI elements`, { id: node.id, elementType, children: node.children.length, scope });
461
+ if (leafElementTypes.has(elementType) && node.origo !== undefined)
462
+ throw new ServiceError('GUI_HELPER_LEAF_ORIGO_UNSUPPORTED', `GUI helper leaf element ${node.id} cannot use container-only origo`, { id: node.id, elementType, origo: node.origo, scope });
463
+ const selected = node.stateVariants?.find(({ state }) => state === node.state);
464
+ if (node.state !== undefined &&
465
+ selected === undefined &&
466
+ !(buttonElementTypes.has(elementType) && runtimeButtonStates.has(node.state)))
467
+ throw new ServiceError('GUI_HELPER_STATE_VARIANT_MISSING', `GUI helper node ${node.id} selects state ${node.state} without an explicit variant`, { id: node.id, state: node.state, elementType, scope });
468
+ assertStructuredElementFields(node, elementType, undefined, scope);
469
+ for (const variant of node.stateVariants ?? [])
470
+ assertStructuredElementFields(node, elementType, variant, scope);
471
+ }
472
+ const attributeCasing = new Map();
473
+ const allowedAttributes = allowedAttributeKeys(node);
474
+ for (const [owner, attributes] of [
475
+ ['node', node.attributes ?? {}],
476
+ ...(node.stateVariants ?? []).map((variant) => [`state ${variant.state}`, variant.attributes ?? {}]),
477
+ ])
478
+ for (const key of Object.keys(attributes)) {
479
+ const normalizedKey = key.toLowerCase();
480
+ const previousCasing = attributeCasing.get(normalizedKey);
481
+ if (previousCasing !== undefined && previousCasing !== key)
482
+ throw new ServiceError('GUI_HELPER_ATTRIBUTE_CASE_CONFLICT', `GUI helper node ${node.id} uses conflicting casing for attribute ${key}`, { id: node.id, key, previousCasing, owner, scope });
483
+ attributeCasing.set(normalizedKey, key);
484
+ if (controlledAttributeKeys.has(normalizedKey) ||
485
+ (node.kind === 'scroll-list' && scrollListControlledAttributeKeys.has(normalizedKey)))
486
+ throw new ServiceError('GUI_HELPER_CONTROLLED_ATTRIBUTE', `GUI helper node ${node.id} must express ${key} through its structured fields or raw escape hatch`, { id: node.id, key, owner, scope });
487
+ if (allowedAttributes !== undefined && !allowedAttributes.has(normalizedKey))
488
+ throw new ServiceError('GUI_HELPER_ATTRIBUTE_UNSUPPORTED', `GUI helper node ${node.id} cannot emit unsupported scalar attribute ${key}`, { id: node.id, key, owner, elementType: typeFor(node), scope });
489
+ }
490
+ }
491
+ }
492
+ function mergeStateVariants(base, overrides) {
493
+ const variants = new Map(base.map((variant) => [variant.state, variant]));
494
+ for (const variant of overrides)
495
+ variants.set(variant.state, variant);
496
+ return [...variants.values()].sort((left, right) => compareCodeUnits(left.state, right.state));
497
+ }
498
+ const templateOverrideKeys = [
499
+ 'elementType',
500
+ 'x',
501
+ 'y',
502
+ 'width',
503
+ 'height',
504
+ 'gap',
505
+ 'columns',
506
+ 'padding',
507
+ 'margin',
508
+ 'orientation',
509
+ 'origo',
510
+ 'flow',
511
+ 'sprite',
512
+ 'backgroundSprite',
513
+ 'scrollbar',
514
+ 'text',
515
+ 'font',
516
+ 'state',
517
+ 'minValue',
518
+ 'maxValue',
519
+ 'value',
520
+ 'frames',
521
+ 'raw',
522
+ ];
523
+ function boundedExpandedIdentifier(prefix, value, owner) {
524
+ const expanded = prefix === undefined ? value : `${prefix}__${value}`;
525
+ const bytes = Buffer.byteLength(expanded, 'utf8');
526
+ if (bytes > GUI_HELPER_MAX_EXPANDED_IDENTIFIER_BYTES)
527
+ throw new ServiceError('GUI_HELPER_IDENTIFIER_BUDGET_BLOCKED', `Expanded GUI helper identifier for ${owner} exceeds the fixed byte ceiling`, {
528
+ owner,
529
+ bytes,
530
+ maximumBytes: GUI_HELPER_MAX_EXPANDED_IDENTIFIER_BYTES,
531
+ });
532
+ return expanded;
533
+ }
534
+ function applyTemplateOverrides(expanded, instance, prefix) {
535
+ const stateVariants = mergeStateVariants(expanded.stateVariants ?? [], instance.stateVariants ?? []);
536
+ if (stateVariants.length > GUI_HELPER_MAX_STATE_VARIANTS)
537
+ throw new ServiceError('GUI_HELPER_STATE_VARIANT_BUDGET_BLOCKED', `GUI helper template instance ${instance.id} exceeds the expanded state-variant ceiling`, {
538
+ id: instance.id,
539
+ stateVariants: stateVariants.length,
540
+ maximumStateVariants: GUI_HELPER_MAX_STATE_VARIANTS,
541
+ });
542
+ const result = {
543
+ ...expanded,
544
+ ...(instance.name === undefined
545
+ ? {}
546
+ : { name: boundedExpandedIdentifier(prefix, instance.name, `template ${instance.id} name`) }),
547
+ attributes: { ...(expanded.attributes ?? {}), ...(instance.attributes ?? {}) },
548
+ stateVariants,
549
+ };
550
+ for (const key of templateOverrideKeys) {
551
+ const value = instance[key];
552
+ if (value !== undefined)
553
+ result[key] = value;
554
+ }
555
+ return result;
556
+ }
557
+ function expandNode(node, context, prefix, templateStack, depth) {
558
+ if (node.kind === 'template') {
559
+ const templateId = node.templateId;
560
+ const template = context.templates.get(templateId);
561
+ if (templateStack.includes(templateId)) {
562
+ const cycle = [...templateStack, templateId];
563
+ throw new ServiceError('GUI_HELPER_TEMPLATE_CYCLE', `GUI helper template cycle: ${cycle.join(' -> ')}`, { cycle });
564
+ }
565
+ context.templateInstances += 1;
566
+ const instancePrefix = boundedExpandedIdentifier(prefix, node.id, `template ${node.id}`);
567
+ const expanded = expandNode(template.root, context, instancePrefix, [...templateStack, templateId], depth);
568
+ return applyTemplateOverrides(expanded, node, instancePrefix);
569
+ }
570
+ if (depth > GUI_HELPER_MAX_DEPTH)
571
+ throw new ServiceError('GUI_HELPER_DEPTH_BUDGET_BLOCKED', 'Expanded GUI helper tree exceeds the fixed nesting ceiling', { depth, maximumDepth: GUI_HELPER_MAX_DEPTH, stage: 'expanded' });
572
+ context.expandedNodes += 1;
573
+ if (context.expandedNodes > GUI_HELPER_MAX_NODES)
574
+ throw new ServiceError('GUI_HELPER_NODE_BUDGET_BLOCKED', 'Expanded GUI helper tree exceeds the fixed node ceiling', {
575
+ nodes: context.expandedNodes,
576
+ maximumNodes: GUI_HELPER_MAX_NODES,
577
+ stage: 'expanded',
578
+ });
579
+ const expandedId = boundedExpandedIdentifier(prefix, node.id, `node ${node.id}`);
580
+ const expandedName = node.name === undefined
581
+ ? undefined
582
+ : boundedExpandedIdentifier(prefix, node.name, `node ${node.id} name`);
583
+ return {
584
+ ...node,
585
+ id: expandedId,
586
+ ...(expandedName === undefined ? {} : { name: expandedName }),
587
+ children: node.children.map((child) => expandNode(child, context, prefix, templateStack, depth + 1)),
588
+ };
589
+ }
590
+ function expandDocument(document) {
591
+ assertUniqueNodeIds(document.root, 'root');
592
+ for (const template of document.templates) {
593
+ assertUniqueNodeIds(template.root, `template ${template.id}`);
594
+ assertNodeSemantics(template.root, `template ${template.id}`);
595
+ }
596
+ assertNodeSemantics(document.root, 'root');
597
+ const templates = assertTemplateGraph(document);
598
+ const context = { templates, expandedNodes: 0, templateInstances: 0 };
599
+ const root = expandNode(document.root, context, undefined, [], 1);
600
+ assertUniqueNodeIds(root, 'expanded tree');
601
+ assertNodeSemantics(root, 'expanded tree');
602
+ if (root.kind !== 'raw' && !containerElementTypes.has(typeFor(root)))
603
+ throw new ServiceError('GUI_HELPER_ROOT_INVALID', 'A structured GUI helper root must compile to a container; use a container helper or an explicit raw root', { id: root.id, kind: root.kind, elementType: typeFor(root) });
604
+ return {
605
+ root,
606
+ nodeCount: context.expandedNodes,
607
+ templateInstanceCount: context.templateInstances,
608
+ };
609
+ }
610
+ function typeFor(node) {
611
+ if (node.elementType !== undefined)
612
+ return node.elementType;
613
+ if (node.kind === 'modal')
614
+ return 'windowType';
615
+ if (node.kind === 'element' &&
616
+ node.sprite !== undefined &&
617
+ node.text === undefined &&
618
+ node.font === undefined)
619
+ return 'iconType';
620
+ if (node.kind === 'element' &&
621
+ node.sprite === undefined &&
622
+ (node.text !== undefined || node.font !== undefined))
623
+ return 'instantTextBoxType';
624
+ return 'containerWindowType';
625
+ }
626
+ function positioned(compiled, x, y) {
627
+ return { ...compiled, x, y };
628
+ }
629
+ function layoutHelper(node, forcedWidth) {
630
+ const padding = insets(node.padding);
631
+ const ownX = node.x ?? 0;
632
+ const ownY = node.y ?? 0;
633
+ const requestedWidth = node.width ?? forcedWidth;
634
+ const gap = node.gap ?? 0;
635
+ const children = [];
636
+ const flow = node.kind === 'row' || node.kind === 'target-row' || node.kind === 'tabs'
637
+ ? 'horizontal'
638
+ : node.kind === 'column' || node.kind === 'status-panel'
639
+ ? 'vertical'
640
+ : node.kind === 'scroll-list'
641
+ ? (node.flow ?? 'vertical')
642
+ : 'stack';
643
+ if (node.kind === 'grid') {
644
+ const columns = Math.max(1, node.columns ?? 1);
645
+ const cellWidth = requestedWidth === undefined
646
+ ? undefined
647
+ : Math.max(0, (requestedWidth - padding.left - padding.right - gap * (columns - 1)) / columns);
648
+ const entries = node.children.map((child, index) => {
649
+ const margin = insets(child.margin);
650
+ const width = cellWidth === undefined || child.width !== undefined
651
+ ? undefined
652
+ : Math.max(0, cellWidth - margin.left - margin.right);
653
+ return {
654
+ child,
655
+ index,
656
+ margin,
657
+ compiled: layoutHelper(child, width),
658
+ column: index % columns,
659
+ row: Math.floor(index / columns),
660
+ };
661
+ });
662
+ const rowCount = entries.reduce((maximum, entry) => Math.max(maximum, entry.row + 1), 0);
663
+ const usedColumns = Math.min(columns, entries.length);
664
+ const columnWidths = Array.from({ length: usedColumns }, () => cellWidth ?? 0);
665
+ const rowHeights = Array.from({ length: rowCount }, () => 0);
666
+ for (const entry of entries) {
667
+ if (cellWidth === undefined)
668
+ columnWidths[entry.column] = Math.max(columnWidths[entry.column], entry.margin.left + entry.compiled.x + entry.compiled.width + entry.margin.right);
669
+ rowHeights[entry.row] = Math.max(rowHeights[entry.row], entry.margin.top + entry.compiled.y + entry.compiled.height + entry.margin.bottom);
670
+ }
671
+ let columnOffset = 0;
672
+ const columnOffsets = columnWidths.map((width) => {
673
+ const offset = columnOffset;
674
+ columnOffset += width + gap;
675
+ return offset;
676
+ });
677
+ let rowOffset = 0;
678
+ const rowOffsets = rowHeights.map((height) => {
679
+ const offset = rowOffset;
680
+ rowOffset += height + gap;
681
+ return offset;
682
+ });
683
+ for (const entry of entries) {
684
+ children.push(positioned(entry.compiled, padding.left + columnOffsets[entry.column] + entry.margin.left + entry.compiled.x, padding.top + rowOffsets[entry.row] + entry.margin.top + entry.compiled.y));
685
+ }
686
+ }
687
+ else {
688
+ let cursorX = padding.left;
689
+ let cursorY = padding.top;
690
+ for (const child of node.children) {
691
+ const margin = insets(child.margin);
692
+ const compiled = layoutHelper(child);
693
+ const x = flow === 'horizontal'
694
+ ? cursorX + margin.left + compiled.x
695
+ : padding.left + margin.left + compiled.x;
696
+ const y = flow === 'vertical'
697
+ ? cursorY + margin.top + compiled.y
698
+ : padding.top + margin.top + compiled.y;
699
+ children.push(positioned(compiled, x, y));
700
+ if (flow === 'horizontal')
701
+ cursorX += margin.left + compiled.x + compiled.width + margin.right + gap;
702
+ if (flow === 'vertical')
703
+ cursorY += margin.top + compiled.y + compiled.height + margin.bottom + gap;
704
+ }
705
+ }
706
+ const inferredWidth = children.length === 0
707
+ ? 0
708
+ : Math.max(...children.map((child, index) => child.x + child.width + insets(node.children[index]?.margin).right)) + padding.right;
709
+ const inferredHeight = children.length === 0
710
+ ? 0
711
+ : Math.max(...children.map((child, index) => child.y + child.height + insets(node.children[index]?.margin).bottom)) + padding.bottom;
712
+ return {
713
+ node,
714
+ x: ownX,
715
+ y: ownY,
716
+ width: requestedWidth ?? inferredWidth,
717
+ height: node.height ?? inferredHeight,
718
+ children,
719
+ };
720
+ }
721
+ function quote(value) {
722
+ return `"${value.replaceAll('\\', '\\\\').replaceAll('"', '\\"')}"`;
723
+ }
724
+ function scalar(value) {
725
+ if (typeof value === 'boolean')
726
+ return value ? 'yes' : 'no';
727
+ if (typeof value === 'number')
728
+ return Number.isInteger(value) ? String(value) : String(Math.round(value * 1000) / 1000);
729
+ return /^[A-Za-z0-9_@.:-]+$/u.test(value) ? value : quote(value);
730
+ }
731
+ function indentRaw(raw, depth) {
732
+ const indentation = '\t'.repeat(depth);
733
+ return raw
734
+ .replaceAll('\r\n', '\n')
735
+ .split('\n')
736
+ .map((line) => `${indentation}${line}`)
737
+ .join('\n');
738
+ }
739
+ function selectedStateVariant(node) {
740
+ if (node.state === undefined)
741
+ return undefined;
742
+ return node.stateVariants?.find(({ state }) => state === node.state);
743
+ }
744
+ function backgroundLines(name, sprite, childIndentation) {
745
+ const backgroundName = boundedExpandedIdentifier(undefined, `${name}__background`, `${name} background`);
746
+ return [
747
+ `${childIndentation}background = {`,
748
+ `${childIndentation}\tname = ${quote(backgroundName)}`,
749
+ `${childIndentation}\tspriteType = ${scalar(sprite)}`,
750
+ `${childIndentation}}`,
751
+ ];
752
+ }
753
+ function compileNode(compiled, depth) {
754
+ const { node } = compiled;
755
+ if (node.kind === 'raw')
756
+ return { inline: indentRaw(node.raw, depth), hoisted: [] };
757
+ if (node.kind === 'template')
758
+ throw new ServiceError('GUI_HELPER_TEMPLATE_UNEXPANDED', `GUI helper template instance ${node.id} reached source compilation`);
759
+ const indentation = '\t'.repeat(depth);
760
+ const childIndentation = '\t'.repeat(depth + 1);
761
+ const name = node.name ?? node.id;
762
+ const state = selectedStateVariant(node);
763
+ const attributes = {
764
+ ...(node.attributes ?? {}),
765
+ ...(state?.attributes ?? {}),
766
+ };
767
+ const requestedOrientation = node.kind === 'anchor'
768
+ ? (node.orientation ?? 'upper_left')
769
+ : node.kind === 'modal'
770
+ ? (node.orientation ?? 'center')
771
+ : (node.orientation ?? 'upper_left');
772
+ const requestedOrigo = node.kind === 'anchor'
773
+ ? (node.origo ?? 'upper_left')
774
+ : node.kind === 'modal'
775
+ ? (node.origo ?? 'center')
776
+ : node.origo;
777
+ const orientation = normalizedAnchorPoint(requestedOrientation);
778
+ const origo = requestedOrigo === undefined ? undefined : normalizedAnchorPoint(requestedOrigo);
779
+ const sprite = state?.sprite ?? node.sprite;
780
+ const text = state?.text ?? node.text;
781
+ const font = state?.font ?? node.font;
782
+ const frame = state?.frame;
783
+ const elementType = typeFor(node);
784
+ const lines = [
785
+ `${indentation}${elementType} = {`,
786
+ `${childIndentation}name = ${quote(name)}`,
787
+ `${childIndentation}position = { x = ${scalar(compiled.x)} y = ${scalar(compiled.y)} }`,
788
+ ];
789
+ if (containerElementTypes.has(elementType))
790
+ lines.push(`${childIndentation}size = { width = ${scalar(compiled.width)} height = ${scalar(compiled.height)} }`);
791
+ if (textElementTypes.has(elementType)) {
792
+ if (compiled.width > 0)
793
+ lines.push(`${childIndentation}maxWidth = ${scalar(compiled.width)}`);
794
+ if (compiled.height > 0)
795
+ lines.push(`${childIndentation}maxHeight = ${scalar(compiled.height)}`);
796
+ }
797
+ lines.push(`${childIndentation}orientation = ${scalar(orientation)}`);
798
+ if (origo !== undefined)
799
+ lines.push(`${childIndentation}origo = ${scalar(origo)}`);
800
+ if (node.kind === 'card' || node.kind === 'modal') {
801
+ const background = state?.sprite ?? node.backgroundSprite ?? node.sprite;
802
+ if (background !== undefined)
803
+ lines.push(...backgroundLines(name, background, childIndentation));
804
+ }
805
+ else if (iconElementTypes.has(elementType) && sprite !== undefined) {
806
+ lines.push(`${childIndentation}spriteType = ${scalar(sprite)}`);
807
+ }
808
+ else if (buttonElementTypes.has(elementType) && sprite !== undefined) {
809
+ lines.push(`${childIndentation}spriteType = ${scalar(sprite)}`);
810
+ }
811
+ if (textElementTypes.has(elementType)) {
812
+ if (text !== undefined)
813
+ lines.push(`${childIndentation}text = ${scalar(text)}`);
814
+ if (font !== undefined)
815
+ lines.push(`${childIndentation}font = ${scalar(font)}`);
816
+ }
817
+ if (buttonElementTypes.has(elementType)) {
818
+ if (text !== undefined)
819
+ lines.push(`${childIndentation}buttonText = ${scalar(text)}`);
820
+ if (font !== undefined)
821
+ lines.push(`${childIndentation}buttonFont = ${scalar(font)}`);
822
+ }
823
+ if ((iconElementTypes.has(elementType) || buttonElementTypes.has(elementType)) &&
824
+ frame !== undefined)
825
+ lines.push(`${childIndentation}frame = ${scalar(frame)}`);
826
+ if (node.kind === 'scroll-list') {
827
+ const horizontal = node.flow === 'horizontal';
828
+ const scrollbarKey = horizontal ? 'horizontalScrollbar' : 'verticalScrollbar';
829
+ const entry = compiled.children[0];
830
+ const gridName = boundedExpandedIdentifier(undefined, `${name}__grid`, `${name} grid`);
831
+ if (entry.width <= 0 || entry.height <= 0)
832
+ throw new ServiceError('GUI_HELPER_SCROLL_ENTRY_INVALID', `GUI helper scroll-list ${node.id} entry must have positive inferred or explicit dimensions`, { id: node.id, entryWidth: entry.width, entryHeight: entry.height });
833
+ const slotWidth = entry.width + (horizontal ? (node.gap ?? 0) : 0);
834
+ const slotHeight = entry.height + (horizontal ? 0 : (node.gap ?? 0));
835
+ lines.push(...backgroundLines(name, node.backgroundSprite, childIndentation), `${childIndentation}clipping = yes`, `${childIndentation}${scrollbarKey} = ${scalar(node.scrollbar)}`, `${childIndentation}scroll_wheel_factor = 40`, `${childIndentation}smooth_scrolling = yes`, `${childIndentation}gridBoxType = {`, `${childIndentation}\tname = ${quote(gridName)}`, `${childIndentation}\tposition = { x = 0 y = 0 }`, `${childIndentation}\torientation = upper_left`, `${childIndentation}\tsize = { width = ${scalar(compiled.width)} height = ${scalar(compiled.height)} }`, `${childIndentation}\tslotsize = { width = ${scalar(slotWidth)} height = ${scalar(slotHeight)} }`, `${childIndentation}\tformat = upper_left`, horizontal
836
+ ? `${childIndentation}\tmax_slots_vertical = 1`
837
+ : `${childIndentation}\tmax_slots_horizontal = 1`, `${childIndentation}}`);
838
+ }
839
+ if (node.kind === 'meter') {
840
+ const minimum = node.minValue ?? 0;
841
+ const maximum = node.maxValue ?? 100;
842
+ const value = node.value ?? minimum;
843
+ const ratio = (value - minimum) / (maximum - minimum);
844
+ const meterFrame = state?.frame ?? 1 + Math.round(ratio * (node.frames - 1));
845
+ const fillSprite = state?.sprite ?? node.sprite;
846
+ const fillName = boundedExpandedIdentifier(undefined, `${name}__fill`, `${name} meter fill`);
847
+ if (node.backgroundSprite !== undefined)
848
+ lines.push(...backgroundLines(name, node.backgroundSprite, childIndentation));
849
+ lines.push(`${childIndentation}iconType = {`, `${childIndentation}\tname = ${quote(fillName)}`, `${childIndentation}\tposition = { x = 0 y = 0 }`, `${childIndentation}\torientation = upper_left`, `${childIndentation}\tspriteType = ${scalar(fillSprite)}`, `${childIndentation}\tframe = ${scalar(meterFrame)}`, `${childIndentation}}`);
850
+ }
851
+ if (node.kind === 'overlay' &&
852
+ !Object.keys(attributes).some((key) => key.toLowerCase() === 'clipping'))
853
+ lines.push(`${childIndentation}clipping = no`);
854
+ for (const [key, value] of Object.entries(attributes).sort(([left], [right]) => compareCodeUnits(left, right)))
855
+ lines.push(`${childIndentation}${key} = ${scalar(value)}`);
856
+ if (node.raw !== undefined)
857
+ lines.push(indentRaw(node.raw, depth + 1));
858
+ const hoisted = [];
859
+ if (node.kind === 'scroll-list') {
860
+ const entry = compiled.children[0];
861
+ const entryName = boundedExpandedIdentifier(undefined, `${name}__entry`, `${name} entry`);
862
+ const entrySource = compileNode({
863
+ ...entry,
864
+ x: 0,
865
+ y: 0,
866
+ node: { ...entry.node, name: entryName },
867
+ }, 1);
868
+ hoisted.push(entrySource.inline, ...entrySource.hoisted);
869
+ }
870
+ else {
871
+ for (const child of compiled.children) {
872
+ const source = compileNode(child, depth + 1);
873
+ if (source.inline.length > 0)
874
+ lines.push(source.inline);
875
+ hoisted.push(...source.hoisted);
876
+ }
877
+ }
878
+ lines.push(`${indentation}}`);
879
+ return { inline: lines.join('\n'), hoisted };
880
+ }
881
+ function countRaw(root) {
882
+ return walkNodes(root).filter(({ raw }) => raw !== undefined).length;
883
+ }
884
+ function assertGeneratedSourceWork(root) {
885
+ const pending = [{ node: root, depth: 1 }];
886
+ let work = 256;
887
+ const spend = (amount) => {
888
+ work += amount;
889
+ if (work > GUI_HELPER_MAX_GENERATED_SOURCE_WORK)
890
+ throw new ServiceError('GUI_HELPER_SOURCE_WORK_BUDGET_BLOCKED', 'Expanded GUI helper source exceeds the fixed pre-compilation work ceiling', { work, maximumWork: GUI_HELPER_MAX_GENERATED_SOURCE_WORK });
891
+ };
892
+ const spendString = (value) => {
893
+ if (value !== undefined)
894
+ spend(Buffer.byteLength(value, 'utf8') * 8 + 64);
895
+ };
896
+ const spendAttributes = (attributes) => {
897
+ for (const [key, value] of Object.entries(attributes ?? {})) {
898
+ spendString(key);
899
+ if (typeof value === 'string')
900
+ spendString(value);
901
+ else
902
+ spend(64);
903
+ }
904
+ };
905
+ while (pending.length > 0) {
906
+ const { node, depth } = pending.pop();
907
+ spend(384 + depth * 32);
908
+ for (const value of [
909
+ node.id,
910
+ node.name,
911
+ node.elementType,
912
+ node.orientation,
913
+ node.origo,
914
+ node.sprite,
915
+ node.backgroundSprite,
916
+ node.scrollbar,
917
+ node.text,
918
+ node.font,
919
+ node.state,
920
+ ])
921
+ spendString(value);
922
+ spendAttributes(node.attributes);
923
+ for (const variant of node.stateVariants ?? []) {
924
+ spendString(variant.state);
925
+ spendString(variant.sprite);
926
+ spendString(variant.text);
927
+ spendString(variant.font);
928
+ spendAttributes(variant.attributes);
929
+ spend(64);
930
+ }
931
+ if (node.raw !== undefined) {
932
+ spend(Buffer.byteLength(node.raw, 'utf8'));
933
+ let lineCount = 1;
934
+ for (let index = 0; index < node.raw.length; index += 1)
935
+ if (node.raw.charCodeAt(index) === 10)
936
+ lineCount += 1;
937
+ spend((depth + 1) * lineCount);
938
+ }
939
+ if (node.kind === 'scroll-list' || node.kind === 'meter')
940
+ spend(1_024);
941
+ for (let index = node.children.length - 1; index >= 0; index -= 1)
942
+ pending.push({ node: node.children[index], depth: depth + 1 });
943
+ }
944
+ }
945
+ function assertUniqueCompiledNames(source) {
946
+ const document = parseClausewitz(Buffer.from(source), 'generated:gui-helper.gui');
947
+ const blocking = document.diagnostics.filter(({ severity }) => severity === 'error' || severity === 'blocker');
948
+ if (blocking.length > 0)
949
+ throw new ServiceError('GUI_HELPER_GENERATED_SOURCE_INVALID', 'GUI helper compilation produced malformed explicit GUI source', { diagnosticCodes: blocking.map(({ code }) => code) });
950
+ const pending = [document.root];
951
+ const names = new Set();
952
+ while (pending.length > 0) {
953
+ const block = pending.pop();
954
+ for (const assignment of assignments(block)) {
955
+ if (assignment.value.type !== 'block')
956
+ continue;
957
+ pending.push(assignment.value);
958
+ const name = assignments(assignment.value).find((child) => child.key.value.toLowerCase() === 'name' && child.value.type === 'scalar')?.value;
959
+ if (name === undefined)
960
+ continue;
961
+ const nameValue = name.type === 'scalar' ? name.value : undefined;
962
+ if (nameValue === undefined)
963
+ continue;
964
+ if (names.has(nameValue))
965
+ throw new ServiceError('GUI_HELPER_DUPLICATE_NAME', `GUI helper compilation produced duplicate GUI name ${nameValue}`, { name: nameValue });
966
+ names.add(nameValue);
967
+ }
968
+ }
969
+ }
970
+ export function assertGuiHelperGeneratedSourceBytes(source, maximumBytes = GUI_HELPER_MAX_GENERATED_SOURCE_BYTES) {
971
+ if (!Number.isSafeInteger(maximumBytes) || maximumBytes < 0)
972
+ throw new Error('GUI helper generated-source byte limit must be a non-negative safe integer');
973
+ const sourceBytes = Buffer.byteLength(source, 'utf8');
974
+ if (sourceBytes > maximumBytes)
975
+ throw new ServiceError('GUI_HELPER_SOURCE_BYTE_BUDGET_BLOCKED', 'Compiled GUI helper source exceeds the Clausewitz parser byte ceiling', { sourceBytes, maximumBytes });
976
+ }
977
+ export function compileGuiHelpers(input) {
978
+ const document = GuiHelperDocumentSchema.parse(input);
979
+ const expanded = expandDocument(document);
980
+ assertGeneratedSourceWork(expanded.root);
981
+ const compiled = layoutHelper(expanded.root);
982
+ const compiledSource = compileNode(compiled, 1);
983
+ const source = `# Generated as explicit HOI4 GUI source; the game has no dependency on hoi4-agent-tools.\nguiTypes = {\n${[compiledSource.inline, ...compiledSource.hoisted].join('\n')}\n}\n`;
984
+ assertGuiHelperGeneratedSourceBytes(source);
985
+ assertUniqueCompiledNames(source);
986
+ return {
987
+ document,
988
+ source,
989
+ nodeCount: expanded.nodeCount,
990
+ templateInstanceCount: expanded.templateInstanceCount,
991
+ rawEscapeCount: countRaw(expanded.root),
992
+ };
993
+ }
994
+ export async function planGuiHelperCompilation(transactions, input) {
995
+ input.signal?.throwIfAborted();
996
+ if (!input.relativePath.replaceAll('\\', '/').toLowerCase().endsWith('.gui'))
997
+ throw new Error('GUI helper output must target a .gui file.');
998
+ const compilation = compileGuiHelpers(input.helper);
999
+ const operationId = deterministicId('gui_helper_compile', {
1000
+ relativePath: input.relativePath,
1001
+ source: compilation.source,
1002
+ });
1003
+ const transaction = await transactions.plan({
1004
+ workspaceId: input.workspaceId,
1005
+ ...(input.principal === undefined ? {} : { principal: input.principal }),
1006
+ operationKind: 'gui-helper-compilation',
1007
+ operations: [
1008
+ {
1009
+ id: operationId,
1010
+ kind: 'compile-gui-helper',
1011
+ summary: `Compile declarative GUI helper to ${input.relativePath}`,
1012
+ data: {
1013
+ relativePath: input.relativePath,
1014
+ nodeCount: compilation.nodeCount,
1015
+ templateInstanceCount: compilation.templateInstanceCount,
1016
+ rawEscapeCount: compilation.rawEscapeCount,
1017
+ },
1018
+ },
1019
+ ],
1020
+ changes: [
1021
+ {
1022
+ relativePath: input.relativePath,
1023
+ content: Buffer.from(compilation.source, 'utf8'),
1024
+ operationIds: [operationId],
1025
+ mediaType: 'text/plain',
1026
+ },
1027
+ ],
1028
+ validate: (proposed) => {
1029
+ input.signal?.throwIfAborted();
1030
+ const bytes = proposed.get(input.relativePath);
1031
+ if (bytes === undefined || bytes === null)
1032
+ return Promise.resolve({
1033
+ diagnostics: [
1034
+ {
1035
+ code: 'GUI_HELPER_OUTPUT_MISSING',
1036
+ severity: 'blocker',
1037
+ category: 'transaction',
1038
+ message: `Proposed source is missing ${input.relativePath}`,
1039
+ operationId,
1040
+ },
1041
+ ],
1042
+ checks: [
1043
+ {
1044
+ id: 'gui-helper-output-present',
1045
+ passed: false,
1046
+ message: 'Compiled GUI source is present.',
1047
+ },
1048
+ ],
1049
+ });
1050
+ const document = parseClausewitz(bytes, `mod:${input.relativePath}`);
1051
+ const blocking = document.diagnostics.some(({ severity }) => severity === 'error' || severity === 'blocker');
1052
+ return Promise.resolve({
1053
+ diagnostics: document.diagnostics.map((diagnostic) => ({ ...diagnostic, operationId })),
1054
+ checks: [
1055
+ {
1056
+ id: 'gui-helper-output-present',
1057
+ passed: true,
1058
+ message: 'Compiled GUI source is present.',
1059
+ },
1060
+ {
1061
+ id: 'gui-helper-source-syntax',
1062
+ passed: !blocking,
1063
+ message: 'Compiled explicit GUI source parses safely.',
1064
+ },
1065
+ ],
1066
+ });
1067
+ },
1068
+ ...(input.signal === undefined ? {} : { signal: input.signal }),
1069
+ });
1070
+ return { transaction, compilation };
1071
+ }
1072
+ //# sourceMappingURL=helpers.js.map