@seriousgaming/sdk-tools 0.0.0-stage → 1.0.0-alpha.1

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 (391) hide show
  1. package/LICENSE +93 -0
  2. package/README.md +36 -2
  3. package/dist/bundling/logic-exports.d.ts +34 -0
  4. package/dist/bundling/node-builtins.d.ts +21 -0
  5. package/dist/bundling/transpiler.d.ts +7 -0
  6. package/dist/cli.js +27368 -0
  7. package/dist/client/dev-server.d.ts +59 -0
  8. package/dist/client/index.d.ts +28 -0
  9. package/dist/client/stub-services.d.ts +32 -0
  10. package/dist/client/test-session.d.ts +195 -0
  11. package/dist/client.js +16884 -0
  12. package/dist/core/asset-reference-translator.d.ts +46 -0
  13. package/dist/core/clock.d.ts +57 -0
  14. package/dist/core/faults.d.ts +65 -0
  15. package/dist/core/game-settings.d.ts +65 -0
  16. package/dist/core/history.d.ts +89 -0
  17. package/dist/core/listen-with-fallback.d.ts +30 -0
  18. package/dist/core/mutation-queue.d.ts +61 -0
  19. package/dist/core/package-scenario.d.ts +89 -0
  20. package/dist/core/participant-registry.d.ts +109 -0
  21. package/dist/core/pending-changes.d.ts +14 -0
  22. package/dist/core/protocol.d.ts +83 -0
  23. package/dist/core/scenario-drafts.d.ts +32 -0
  24. package/dist/core/session-endpoints.d.ts +108 -0
  25. package/dist/core/session-gates.d.ts +75 -0
  26. package/dist/core/session-host.d.ts +94 -0
  27. package/dist/core/session-refusals.d.ts +56 -0
  28. package/dist/core/session-rewind.d.ts +32 -0
  29. package/dist/core/session-roster.d.ts +128 -0
  30. package/dist/core/session-surfaces.d.ts +32 -0
  31. package/dist/core/session-ticks.d.ts +18 -0
  32. package/dist/core/session-timers.d.ts +84 -0
  33. package/dist/core/session-writes.d.ts +40 -0
  34. package/dist/core/session.d.ts +385 -0
  35. package/dist/core/settings-locks.d.ts +22 -0
  36. package/dist/core/team-names.d.ts +52 -0
  37. package/dist/core/team-state-store.d.ts +209 -0
  38. package/dist/core/tick-timer.d.ts +75 -0
  39. package/dist/dev/blob-links.d.ts +10 -0
  40. package/dist/dev/console/assets/index-DgFglsnA.js +204 -0
  41. package/dist/dev/console/index.html +12 -0
  42. package/dist/dev/console-path.d.ts +19 -0
  43. package/dist/dev/lockfile.d.ts +124 -0
  44. package/dist/dev/package-watcher.d.ts +21 -0
  45. package/dist/dev/routes.d.ts +67 -0
  46. package/dist/dev/shell.d.ts +260 -0
  47. package/dist/dev/surfaces.d.ts +41 -0
  48. package/dist/dev/tools-identity.d.ts +23 -0
  49. package/dist/dev/view/batch.d.ts +172 -0
  50. package/dist/dev/view/commands.d.ts +75 -0
  51. package/dist/dev/view/route.d.ts +58 -0
  52. package/dist/dev/view/view.d.ts +78 -0
  53. package/dist/dev/view/viewer.d.ts +32 -0
  54. package/dist/discovery/config.d.ts +9 -0
  55. package/dist/discovery/manifest-paths.d.ts +21 -0
  56. package/dist/discovery/removed-fields.d.ts +90 -0
  57. package/dist/docs/api/deck.md +386 -0
  58. package/dist/docs/api/index.md +67 -0
  59. package/dist/docs/api/sdk-commands.md +286 -0
  60. package/dist/docs/api/sdk-e2e.md +433 -0
  61. package/dist/docs/api/sdk-projection.md +207 -0
  62. package/dist/docs/api/sdk-testing.md +214 -0
  63. package/dist/docs/api/sdk-tools-client.md +560 -0
  64. package/dist/docs/api/sdk-ui-testing.md +231 -0
  65. package/dist/docs/api/sdk-ui.md +1269 -0
  66. package/dist/docs/api/sdk.md +2140 -0
  67. package/dist/docs/changelog-0.x.md +1156 -0
  68. package/dist/docs/changelog.md +236 -0
  69. package/dist/docs/cli-and-dev-server.md +217 -0
  70. package/dist/docs/cli-error-codes.md +154 -0
  71. package/dist/docs/cli-reference.md +2488 -0
  72. package/dist/docs/cli-simulation-testing.md +222 -0
  73. package/dist/docs/concepts/index.md +46 -0
  74. package/dist/docs/concepts/terminology.md +322 -0
  75. package/dist/docs/environment-variables.md +102 -0
  76. package/dist/docs/getting-started.md +145 -0
  77. package/dist/docs/guides/ai-facilitation.md +220 -0
  78. package/dist/docs/guides/capabilities.md +460 -0
  79. package/dist/docs/guides/endpoints.md +335 -0
  80. package/dist/docs/guides/engine-testing.md +477 -0
  81. package/dist/docs/guides/engine.md +527 -0
  82. package/dist/docs/guides/file-handling.md +405 -0
  83. package/dist/docs/guides/games.md +176 -0
  84. package/dist/docs/guides/global-settings.md +94 -0
  85. package/dist/docs/guides/guide.md +123 -0
  86. package/dist/docs/guides/hooks.md +183 -0
  87. package/dist/docs/guides/index.md +51 -0
  88. package/dist/docs/guides/internationalization.md +288 -0
  89. package/dist/docs/guides/llm-integration.md +635 -0
  90. package/dist/docs/guides/multi-team-games.md +586 -0
  91. package/dist/docs/guides/patterns.md +391 -0
  92. package/dist/docs/guides/presentation.md +196 -0
  93. package/dist/docs/guides/production-constraints.md +130 -0
  94. package/dist/docs/guides/scenario-editor.md +143 -0
  95. package/dist/docs/guides/scenarios.md +515 -0
  96. package/dist/docs/guides/session.md +972 -0
  97. package/dist/docs/guides/settings.md +458 -0
  98. package/dist/docs/guides/setup.md +193 -0
  99. package/dist/docs/guides/speech-generation.md +233 -0
  100. package/dist/docs/guides/starter-game.md +164 -0
  101. package/dist/docs/guides/testing.md +575 -0
  102. package/dist/docs/guides/tick-controller.md +569 -0
  103. package/dist/docs/guides/type-safety.md +516 -0
  104. package/dist/docs/guides/ui.md +1389 -0
  105. package/dist/docs/guides/upgrading.md +636 -0
  106. package/dist/docs/guides/validators.md +217 -0
  107. package/dist/docs/guides/waiting-room.md +244 -0
  108. package/dist/docs/index.md +41 -0
  109. package/dist/docs/recipes/act-on-the-session-from-an-endpoint.md +95 -0
  110. package/dist/docs/recipes/adapt-a-game-for-walkthroughs.md +133 -0
  111. package/dist/docs/recipes/adapt-ui-for-observers.md +74 -0
  112. package/dist/docs/recipes/call-endpoint-from-ui.md +109 -0
  113. package/dist/docs/recipes/check-a-package-from-a-script.md +117 -0
  114. package/dist/docs/recipes/create-capability.md +66 -0
  115. package/dist/docs/recipes/create-endpoint.md +127 -0
  116. package/dist/docs/recipes/create-engine.md +111 -0
  117. package/dist/docs/recipes/create-game.md +70 -0
  118. package/dist/docs/recipes/create-guide.md +75 -0
  119. package/dist/docs/recipes/create-hook.md +80 -0
  120. package/dist/docs/recipes/create-presentation.md +142 -0
  121. package/dist/docs/recipes/create-scenario-editor.md +102 -0
  122. package/dist/docs/recipes/create-scenario.md +98 -0
  123. package/dist/docs/recipes/create-session-ui.md +116 -0
  124. package/dist/docs/recipes/create-settings.md +88 -0
  125. package/dist/docs/recipes/create-setup.md +115 -0
  126. package/dist/docs/recipes/create-tick-controller.md +65 -0
  127. package/dist/docs/recipes/create-user-interface.md +96 -0
  128. package/dist/docs/recipes/create-validator.md +67 -0
  129. package/dist/docs/recipes/create-waiting-room-ui.md +109 -0
  130. package/dist/docs/recipes/declare-api-uses.md +67 -0
  131. package/dist/docs/recipes/design-state-for-concurrent-writes.md +96 -0
  132. package/dist/docs/recipes/distribute-package.md +80 -0
  133. package/dist/docs/recipes/e2e-testing.md +116 -0
  134. package/dist/docs/recipes/end-game-on-condition.md +154 -0
  135. package/dist/docs/recipes/fix-duplicate-packages.md +101 -0
  136. package/dist/docs/recipes/index.md +86 -0
  137. package/dist/docs/recipes/make-an-endpoint-external.md +101 -0
  138. package/dist/docs/recipes/negotiate-across-teams.md +164 -0
  139. package/dist/docs/recipes/observe-other-teams-state.md +119 -0
  140. package/dist/docs/recipes/publish-a-package.md +139 -0
  141. package/dist/docs/recipes/remember-a-viewers-choice.md +55 -0
  142. package/dist/docs/recipes/review-a-past-day.md +73 -0
  143. package/dist/docs/recipes/share-assets-across-scenarios.md +120 -0
  144. package/dist/docs/recipes/share-logic-between-engine-and-ui.md +130 -0
  145. package/dist/docs/recipes/show-all-teams-participants.md +109 -0
  146. package/dist/docs/recipes/start-from-an-empty-package.md +169 -0
  147. package/dist/docs/recipes/take-a-file-in-an-endpoint.md +82 -0
  148. package/dist/docs/recipes/test-a-multi-role-game.md +51 -0
  149. package/dist/docs/recipes/test-user-interface.md +95 -0
  150. package/dist/docs/recipes/test-with-engine.md +115 -0
  151. package/dist/docs/recipes/upload-and-display-files.md +148 -0
  152. package/dist/docs/recipes/use-request-play.md +65 -0
  153. package/dist/docs/recipes/use-request-tick.md +75 -0
  154. package/dist/docs/troubleshooting.md +816 -0
  155. package/dist/execution/blob-inputs.d.ts +57 -0
  156. package/dist/execution/bundle-reload.d.ts +42 -0
  157. package/dist/execution/config-resolver.d.ts +127 -0
  158. package/dist/execution/configuration-builder.d.ts +66 -0
  159. package/dist/execution/context-composition.d.ts +161 -0
  160. package/dist/execution/endpoint-actions.d.ts +9 -0
  161. package/dist/execution/endpoint-payloads.d.ts +32 -0
  162. package/dist/execution/endpoint-runner.d.ts +129 -0
  163. package/dist/execution/engine-state.d.ts +40 -0
  164. package/dist/execution/executor-callbacks.d.ts +56 -0
  165. package/dist/execution/executor.d.ts +436 -0
  166. package/dist/execution/gates.d.ts +45 -0
  167. package/dist/execution/hook-chain.d.ts +25 -0
  168. package/dist/execution/logic-calls.d.ts +190 -0
  169. package/dist/execution/logic-failure.d.ts +84 -0
  170. package/dist/execution/logic-loader.d.ts +54 -0
  171. package/dist/execution/logic-result.d.ts +76 -0
  172. package/dist/execution/tick-controller-call.d.ts +32 -0
  173. package/dist/execution/types.d.ts +48 -0
  174. package/dist/generation/ts-type.d.ts +39 -0
  175. package/dist/guide/locale.d.ts +12 -0
  176. package/dist/guide/video-registry.d.ts +42 -0
  177. package/dist/help-examples.d.ts +125 -0
  178. package/dist/host/adapter.d.ts +67 -0
  179. package/dist/host/host-channel.d.ts +222 -0
  180. package/dist/host/index.d.ts +20 -0
  181. package/dist/host/protocol.d.ts +783 -0
  182. package/dist/host/surfaces.d.ts +42 -0
  183. package/dist/host/theme.d.ts +55 -0
  184. package/dist/host.js +583 -0
  185. package/dist/prompts/index.d.ts +7 -0
  186. package/dist/prompts/schema-builder.d.ts +29 -0
  187. package/dist/prompts/types.d.ts +108 -0
  188. package/dist/prompts/validators.d.ts +32 -0
  189. package/dist/runtime/capability-scope.d.ts +6 -0
  190. package/dist/runtime/context-merge.d.ts +29 -0
  191. package/dist/runtime/context-projection.d.ts +41 -0
  192. package/dist/runtime/guarded-callbacks.d.ts +15 -0
  193. package/dist/runtime/index.d.ts +27 -0
  194. package/dist/runtime/manifest-version.d.ts +55 -0
  195. package/dist/runtime/tick-validation.d.ts +25 -0
  196. package/dist/runtime.js +346 -0
  197. package/dist/schema.json +1546 -0
  198. package/dist/server/vite-plugin.d.ts +46 -0
  199. package/dist/services/tts/client.d.ts +51 -0
  200. package/dist/services/tts/elevenlabs.d.ts +24 -0
  201. package/dist/services/tts/types.d.ts +44 -0
  202. package/dist/storage/asset-resolver.d.ts +49 -0
  203. package/dist/storage/blob-store.d.ts +41 -0
  204. package/dist/templates/endpoint/logic.test.ts.liquid +61 -0
  205. package/dist/templates/endpoint/logic.ts.liquid +25 -0
  206. package/dist/templates/engine/init.json.liquid +7 -0
  207. package/dist/templates/engine/logic-aggregate.test.ts.liquid +90 -0
  208. package/dist/templates/engine/logic-aggregate.ts.liquid +46 -0
  209. package/dist/templates/engine/logic.test.ts.liquid +61 -0
  210. package/dist/templates/engine/logic.ts.liquid +32 -0
  211. package/dist/templates/engine/run.json.liquid +7 -0
  212. package/dist/templates/guide/01-at-a-glance.md.liquid +19 -0
  213. package/dist/templates/guide/02-preparation.md.liquid +18 -0
  214. package/dist/templates/guide/03-running-the-session.md.liquid +37 -0
  215. package/dist/templates/hook/logic.test.ts.liquid +46 -0
  216. package/dist/templates/hook/logic.ts.liquid +12 -0
  217. package/dist/templates/package/CLAUDE.md.template +338 -0
  218. package/dist/templates/package/DESIGN.md.liquid +144 -0
  219. package/dist/templates/package/README.md.liquid +143 -0
  220. package/dist/templates/package/claude/rules/workflow-create-capability.md +26 -0
  221. package/dist/templates/package/claude/rules/workflow-create-endpoint.md +35 -0
  222. package/dist/templates/package/claude/rules/workflow-create-engine.md +35 -0
  223. package/dist/templates/package/claude/rules/workflow-create-guide.md +40 -0
  224. package/dist/templates/package/claude/rules/workflow-create-presentation.md +37 -0
  225. package/dist/templates/package/claude/rules/workflow-create-user-interface.md +31 -0
  226. package/dist/templates/package/claude/rules/workflow-publish-package.md +54 -0
  227. package/dist/templates/package/claude/rules/workflow-test-engine-or-ui.md +30 -0
  228. package/dist/templates/package/claude/rules/workflow-update-sdk-version.md +43 -0
  229. package/dist/templates/package/claude/settings.json.template +16 -0
  230. package/dist/templates/package/gitignore.template +15 -0
  231. package/dist/templates/package/global-setup.ts.template +21 -0
  232. package/dist/templates/package/globals.d.ts.template +2 -0
  233. package/dist/templates/package/oxfmtrc.json.template +14 -0
  234. package/dist/templates/package/oxlintrc.json.template +238 -0
  235. package/dist/templates/package/package.json.liquid +65 -0
  236. package/dist/templates/package/playwright.config.ts.liquid +19 -0
  237. package/dist/templates/package/pnpm-workspace.yaml.template +27 -0
  238. package/dist/templates/package/test-setup.ts.liquid +7 -0
  239. package/dist/templates/package/tsconfig.json.liquid +15 -0
  240. package/dist/templates/package/vite.config.ts.liquid +19 -0
  241. package/dist/templates/package/vitest.config.ts.liquid +25 -0
  242. package/dist/templates/package/vitest.engine.config.ts.liquid +12 -0
  243. package/dist/templates/presentation/index.html.liquid +20 -0
  244. package/dist/templates/presentation/src/App.tsx.liquid +49 -0
  245. package/dist/templates/presentation/src/Slides.tsx.liquid +81 -0
  246. package/dist/templates/presentation/src/i18n.ts.liquid +54 -0
  247. package/dist/templates/presentation/src/main.tsx.liquid +14 -0
  248. package/dist/templates/scenario_editor/src/App.test.tsx.liquid +30 -0
  249. package/dist/templates/scenario_editor/src/App.tsx.liquid +95 -0
  250. package/dist/templates/scenario_editor/src/i18n.ts.liquid +44 -0
  251. package/dist/templates/session/src/App.test.tsx.liquid +60 -0
  252. package/dist/templates/session/src/App.tsx.liquid +128 -0
  253. package/dist/templates/session/src/i18n.ts.liquid +53 -0
  254. package/dist/templates/session/src/main.tsx.liquid +48 -0
  255. package/dist/templates/session/src/theme.ts.liquid +46 -0
  256. package/dist/templates/settings-editor/index.html.liquid +12 -0
  257. package/dist/templates/settings-editor/src/main.tsx.liquid +48 -0
  258. package/dist/templates/settings-editor/src/theme.ts.liquid +24 -0
  259. package/dist/templates/setup/src/App.test.tsx.liquid +39 -0
  260. package/dist/templates/setup/src/App.tsx.liquid +102 -0
  261. package/dist/templates/setup/src/i18n.ts.liquid +47 -0
  262. package/dist/templates/starter-game/capabilities/briefing/capability.sdk.json +18 -0
  263. package/dist/templates/starter-game/capabilities/plan/capability.sdk.json +17 -0
  264. package/dist/templates/starter-game/capabilities/results/capability.sdk.json +61 -0
  265. package/dist/templates/starter-game/capabilities/roles/capability.sdk.json +17 -0
  266. package/dist/templates/starter-game/capabilities/weather/capability.sdk.json +23 -0
  267. package/dist/templates/starter-game/engine/defaults.ts +81 -0
  268. package/dist/templates/starter-game/engine/engine.sdk.json +12 -0
  269. package/dist/templates/starter-game/engine/logic.test.ts +221 -0
  270. package/dist/templates/starter-game/engine/logic.ts +149 -0
  271. package/dist/templates/starter-game/engine/test-helpers.ts +74 -0
  272. package/dist/templates/starter-game/engine/types.ts +139 -0
  273. package/dist/templates/starter-game/guide/content/en/01-at-a-glance.md +51 -0
  274. package/dist/templates/starter-game/guide/content/en/02-preparation.md +35 -0
  275. package/dist/templates/starter-game/guide/content/en/03-running-the-day.md +58 -0
  276. package/dist/templates/starter-game/guide/guide.sdk.json +10 -0
  277. package/dist/templates/starter-game/guide/guide.test.ts +108 -0
  278. package/dist/templates/starter-game/hooks/assignproducts/defaults.ts +37 -0
  279. package/dist/templates/starter-game/hooks/assignproducts/hook.sdk.json +13 -0
  280. package/dist/templates/starter-game/hooks/assignproducts/logic/logic.test.ts +77 -0
  281. package/dist/templates/starter-game/hooks/assignproducts/logic/logic.ts +47 -0
  282. package/dist/templates/starter-game/hooks/assignproducts/types.ts +55 -0
  283. package/dist/templates/starter-game/package.json +68 -0
  284. package/dist/templates/starter-game/playwright.config.ts +19 -0
  285. package/dist/templates/starter-game/scenarios/heatwave/scenario.sdk.json +20 -0
  286. package/dist/templates/starter-game/scenarios/ordinary_week/scenario.sdk.json +12 -0
  287. package/dist/templates/starter-game/seriousgaming.sdk.json +23 -0
  288. package/dist/templates/starter-game/session/defaults.ts +80 -0
  289. package/dist/templates/starter-game/session/index.html +12 -0
  290. package/dist/templates/starter-game/session/session.sdk.json +11 -0
  291. package/dist/templates/starter-game/session/src/App.test.tsx +307 -0
  292. package/dist/templates/starter-game/session/src/App.tsx +309 -0
  293. package/dist/templates/starter-game/session/src/Section.tsx +37 -0
  294. package/dist/templates/starter-game/session/src/TeamDoor.tsx +96 -0
  295. package/dist/templates/starter-game/session/src/format.ts +8 -0
  296. package/dist/templates/starter-game/session/src/i18n.ts +51 -0
  297. package/dist/templates/starter-game/session/src/main.tsx +48 -0
  298. package/dist/templates/starter-game/session/src/theme.ts +45 -0
  299. package/dist/templates/starter-game/session/types.ts +135 -0
  300. package/dist/templates/starter-game/settings/engine/settings.sdk.json +50 -0
  301. package/dist/templates/starter-game/settings/menu/settings.sdk.json +78 -0
  302. package/dist/templates/starter-game/settings/session/settings.sdk.json +23 -0
  303. package/dist/templates/starter-game/settings/ui/settings.sdk.json +25 -0
  304. package/dist/templates/starter-game/test-setup.ts +7 -0
  305. package/dist/templates/starter-game/testing/e2e/game.spec.ts +139 -0
  306. package/dist/templates/starter-game/testing/e2e/global-setup.ts +21 -0
  307. package/dist/templates/starter-game/testing/engine/game.engine.test.ts +171 -0
  308. package/dist/templates/starter-game/tsconfig.json +19 -0
  309. package/dist/templates/starter-game/ui/defaults.ts +60 -0
  310. package/dist/templates/starter-game/ui/index.html +12 -0
  311. package/dist/templates/starter-game/ui/src/App.test.tsx +138 -0
  312. package/dist/templates/starter-game/ui/src/App.tsx +175 -0
  313. package/dist/templates/starter-game/ui/src/DayBar.test.tsx +78 -0
  314. package/dist/templates/starter-game/ui/src/DayBar.tsx +72 -0
  315. package/dist/templates/starter-game/ui/src/HistoryPanel.test.tsx +74 -0
  316. package/dist/templates/starter-game/ui/src/HistoryPanel.tsx +120 -0
  317. package/dist/templates/starter-game/ui/src/MakeRow.tsx +129 -0
  318. package/dist/templates/starter-game/ui/src/Section.tsx +37 -0
  319. package/dist/templates/starter-game/ui/src/ThemeToggle.tsx +49 -0
  320. package/dist/templates/starter-game/ui/src/TodayPanel.test.tsx +179 -0
  321. package/dist/templates/starter-game/ui/src/TodayPanel.tsx +92 -0
  322. package/dist/templates/starter-game/ui/src/YesterdayPanel.tsx +142 -0
  323. package/dist/templates/starter-game/ui/src/format.ts +12 -0
  324. package/dist/templates/starter-game/ui/src/i18n.ts +95 -0
  325. package/dist/templates/starter-game/ui/src/main.tsx +48 -0
  326. package/dist/templates/starter-game/ui/src/menu.ts +18 -0
  327. package/dist/templates/starter-game/ui/src/test-helpers.ts +58 -0
  328. package/dist/templates/starter-game/ui/src/theme.ts +45 -0
  329. package/dist/templates/starter-game/ui/src/writes.ts +43 -0
  330. package/dist/templates/starter-game/ui/types.ts +137 -0
  331. package/dist/templates/starter-game/ui/ui.sdk.json +11 -0
  332. package/dist/templates/starter-game/validators/capacity/defaults.ts +37 -0
  333. package/dist/templates/starter-game/validators/capacity/logic/logic.test.ts +96 -0
  334. package/dist/templates/starter-game/validators/capacity/logic/logic.ts +45 -0
  335. package/dist/templates/starter-game/validators/capacity/types.ts +55 -0
  336. package/dist/templates/starter-game/validators/capacity/validator.sdk.json +11 -0
  337. package/dist/templates/starter-game/vite.config.ts +19 -0
  338. package/dist/templates/starter-game/vitest.config.ts +15 -0
  339. package/dist/templates/starter-game/vitest.engine.config.ts +19 -0
  340. package/dist/templates/starter-game/waiting_room/defaults.ts +40 -0
  341. package/dist/templates/starter-game/waiting_room/index.html +12 -0
  342. package/dist/templates/starter-game/waiting_room/src/App.test.tsx +102 -0
  343. package/dist/templates/starter-game/waiting_room/src/App.tsx +194 -0
  344. package/dist/templates/starter-game/waiting_room/src/i18n.ts +33 -0
  345. package/dist/templates/starter-game/waiting_room/src/main.tsx +48 -0
  346. package/dist/templates/starter-game/waiting_room/src/theme.ts +45 -0
  347. package/dist/templates/starter-game/waiting_room/types.ts +59 -0
  348. package/dist/templates/starter-game/waiting_room/waiting_room.sdk.json +10 -0
  349. package/dist/templates/tick-controller/logic.ts.liquid +8 -0
  350. package/dist/templates/ui/index.html.liquid +12 -0
  351. package/dist/templates/ui/src/App.test.tsx.liquid +41 -0
  352. package/dist/templates/ui/src/App.tsx.liquid +103 -0
  353. package/dist/templates/ui/src/i18n.ts.liquid +47 -0
  354. package/dist/templates/ui/src/main.tsx.liquid +48 -0
  355. package/dist/templates/ui/src/theme.ts.liquid +46 -0
  356. package/dist/templates/validator/logic.test.ts.liquid +42 -0
  357. package/dist/templates/validator/logic.ts.liquid +21 -0
  358. package/dist/templates/waiting-room/index.html.liquid +12 -0
  359. package/dist/templates/waiting-room/src/App.test.tsx.liquid +57 -0
  360. package/dist/templates/waiting-room/src/App.tsx.liquid +118 -0
  361. package/dist/templates/waiting-room/src/i18n.ts.liquid +44 -0
  362. package/dist/templates/waiting-room/src/main.tsx.liquid +48 -0
  363. package/dist/templates/waiting-room/src/theme.ts.liquid +46 -0
  364. package/dist/templating/resource-metadata.d.ts +131 -0
  365. package/dist/types.d.ts +14 -0
  366. package/dist/utils/atomic-write.d.ts +40 -0
  367. package/dist/utils/cli-error.d.ts +64 -0
  368. package/dist/utils/document-parser-client.d.ts +20 -0
  369. package/dist/utils/env-loader.d.ts +40 -0
  370. package/dist/utils/error-codes.d.ts +335 -0
  371. package/dist/utils/errors.d.ts +19 -0
  372. package/dist/utils/global-settings.d.ts +65 -0
  373. package/dist/utils/llm-client.d.ts +34 -0
  374. package/dist/utils/logger.d.ts +36 -0
  375. package/dist/utils/output.d.ts +109 -0
  376. package/dist/utils/platform.d.ts +14 -0
  377. package/dist/utils/prompt.d.ts +36 -0
  378. package/dist/utils/real-path.d.ts +6 -0
  379. package/dist/utils/schema-properties.d.ts +35 -0
  380. package/dist/validation/ajv.d.ts +17 -0
  381. package/dist/validation/facilitator-guide-validator.d.ts +27 -0
  382. package/dist/validation/findings.d.ts +40 -0
  383. package/dist/validation/game-constraints.d.ts +10 -0
  384. package/dist/validation/game-validator.d.ts +34 -0
  385. package/dist/validation/package-validation.d.ts +41 -0
  386. package/dist/validation/package-validator.d.ts +19 -0
  387. package/dist/validation/resource-validator.d.ts +79 -0
  388. package/dist/validation/schema-defaults-validator.d.ts +29 -0
  389. package/dist/validation/schema-validation.d.ts +115 -0
  390. package/dist/validation/semver.d.ts +9 -0
  391. package/package.json +122 -3
@@ -0,0 +1,57 @@
1
+ /**
2
+ * File-valued request fields (§6.12, 'File inputs').
3
+ *
4
+ * A request schema marks a string property as a file with the `blob` keyword:
5
+ *
6
+ * "photo": { "type": "string", "blob": { "accept": ["image/*"], "maxBytes": 2097152 } }
7
+ *
8
+ * On the wire the field is a URI string, which is what lets one declaration
9
+ * serve every caller: a surface that has already uploaded sends the `blob:`
10
+ * reference `uploadBlob` gave it, and a caller with no upload of its own (a
11
+ * script, or an agent whose host cannot upload out of band) sends the bytes
12
+ * inline as an RFC 2397 `data:` URI. The handler only ever receives `blob:`,
13
+ * checked against the declaration, so it never parses base64 or wonders
14
+ * whether the caller told the truth about the type.
15
+ *
16
+ * The shape is the one MCP's file-upload proposals settle on (`x-mcp-file`
17
+ * over URI strings), so a platform exposing an endpoint as an MCP tool can
18
+ * translate the keyword rather than invent a second model.
19
+ */
20
+ import type { JSONSchema7 } from 'json-schema';
21
+ export interface BlobFieldSpec {
22
+ /** Media types, `type/*` wildcards allowed. Absent means any. */
23
+ accept?: string[];
24
+ maxBytes?: number;
25
+ }
26
+ /** What the resolver needs from a blob store. */
27
+ export interface BlobInputStore {
28
+ /** The stored blob's type and size, or undefined when there is none. */
29
+ describe(id: string): Promise<{
30
+ mimeType: string;
31
+ size: number;
32
+ } | undefined>;
33
+ store(data: Uint8Array, name: string, mimeType: string): Promise<string>;
34
+ }
35
+ /**
36
+ * Bytes a `data:` URI may carry inline, whatever a field allows. Inline bytes
37
+ * cross the request as base64, and a model writing them spends its context
38
+ * doing it: past this, a caller uploads first and sends the reference.
39
+ */
40
+ export declare const MAX_INLINE_BYTES: number;
41
+ /**
42
+ * The type the bytes say they are, for the handful of formats a game commonly
43
+ * takes, or undefined for anything else. A caller's claimed type is checked
44
+ * against this rather than trusted: an endpoint told it has a PNG will hand it
45
+ * to a surface as one.
46
+ */
47
+ export declare function sniffMimeType(data: Uint8Array): string | undefined;
48
+ /**
49
+ * The request with every file field resolved to a checked `blob:` reference.
50
+ * Throws, naming the field, when a value is neither kind of URI, names a blob
51
+ * the store does not hold, or breaks the declaration's type or size.
52
+ *
53
+ * A `data:` URI is stored before the handler runs, so a call refused later,
54
+ * by the schema or by the handler, leaves its upload behind. That is the same
55
+ * as a surface that uploads and then never submits, and retention clears both.
56
+ */
57
+ export declare function resolveBlobInputs(identifier: string, schema: JSONSchema7 | undefined, request: unknown, store: BlobInputStore): Promise<unknown>;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * What a package edited while its session runs may change live, and what has
3
+ * to wait for the session to initialise again (#640).
4
+ *
5
+ * A running session reloads the package's bundles and adopts what it can: new
6
+ * logic, surfaces, endpoints and the game's locale names. What it
7
+ * cannot adopt is anything `Init` or session creation already acted on, since
8
+ * applying that mid-session produces a state no real session can reach: a
9
+ * setting `Init` read keeps its old effect while the next tick reads the new
10
+ * value. Those parts are kept as the session started with them and reported,
11
+ * so the session runs on one consistent package and says that the one on disk
12
+ * differs.
13
+ */
14
+ import type { ResolvedPackageManifest } from '@seriousgaming/sdk';
15
+ import type { PendingChanges } from '@seriousgaming/sdk/projection';
16
+ /** What one reload of the bundles did. */
17
+ export interface BundleReload {
18
+ /** Changes on disk the session applies only when it next initialises. */
19
+ pending: PendingChanges;
20
+ /** Capabilities adopted live and seeded with their schema defaults. */
21
+ added: string[];
22
+ }
23
+ /** A reloaded package with its init-only parts held as they were. */
24
+ export interface PinnedReload {
25
+ config: ResolvedPackageManifest;
26
+ /** Manifest fields that differ on disk and apply at the next init. */
27
+ manifest: string[];
28
+ /** Capabilities removed on disk, or whose scope changed. */
29
+ capabilities: string[];
30
+ }
31
+ /**
32
+ * `reloaded`, with everything a session cannot change mid-flight taken from
33
+ * `previous`, and a note of each part that differs.
34
+ */
35
+ export declare function pinInitOnly(previous: ResolvedPackageManifest, reloaded: ResolvedPackageManifest): PinnedReload;
36
+ /**
37
+ * The settings resources whose resolved values differ between two
38
+ * resolutions, including one present in only one of them.
39
+ */
40
+ export declare function changedSettings(before: Record<string, unknown>, after: Record<string, unknown>): string[];
41
+ /** `config`, with the settings resources and scenarios of `from`. */
42
+ export declare function withSettingsOf(config: ResolvedPackageManifest, from: ResolvedPackageManifest): ResolvedPackageManifest;
@@ -0,0 +1,127 @@
1
+ /**
2
+ * ConfigResolver - owns the runtime's settings layering and persistence.
3
+ *
4
+ * Every settings resource is resolved the same way, through the §8.2 layers in
5
+ * order: its schema defaults, the active scenario's overrides, then the session
6
+ * overrides. Every layer contributes and none replaces. This class owns the
7
+ * session-override layer, that layering, its disk persistence, scenario
8
+ * resolution, and the pre-flight validation of the partial-override sources.
9
+ *
10
+ * It reads the executor's live `game` / `config` / `activeScenario` through
11
+ * injected accessors, so it always sees current state without owning it.
12
+ */
13
+ import type { ResolvedPackageManifest, SDKGame, SDKScenario } from '@seriousgaming/sdk';
14
+ import type { ResolvedSettings } from './configuration-builder';
15
+ import type { SessionSettingsOverrides, ExecutorDependencies } from './types';
16
+ /** The layered-config state the resolver needs from the executor. */
17
+ export interface ConfigResolverContext {
18
+ packagePath: string;
19
+ inMemory: boolean;
20
+ deps: Pick<ExecutorDependencies, 'loadConfig' | 'fs' | 'configStore'>;
21
+ getGame: () => SDKGame | null;
22
+ getConfig: () => ResolvedPackageManifest | null;
23
+ getActiveScenario: () => SDKScenario | null;
24
+ }
25
+ export declare class ConfigResolver {
26
+ private readonly ctx;
27
+ private sessionOverrides;
28
+ constructor(ctx: ConfigResolverContext);
29
+ hasSessionOverrides(): boolean;
30
+ /**
31
+ * Directly set the session-override layer in memory. Used by the dev
32
+ * server in in-memory mode so config UI changes are captured without
33
+ * writing to disk.
34
+ */
35
+ setConfiguration(config: SessionSettingsOverrides): void;
36
+ /** Return the current in-memory session-override layer, if any. */
37
+ getSessionOverrides(): SessionSettingsOverrides | null;
38
+ /** Drop the cached session-override layer so the next load rebuilds it. */
39
+ clearSessionOverrides(): void;
40
+ /**
41
+ * Start the session-override layer for an in-memory session.
42
+ *
43
+ * Empty, because nobody has overridden anything yet (§8.2). The resolved
44
+ * values a surface needs come from {@link resolveConfiguration}, which
45
+ * re-layers on demand; storing them here instead would freeze the layers
46
+ * beneath and make the active scenario unchangeable.
47
+ */
48
+ regenerateInMemoryConfiguration(): void;
49
+ /**
50
+ * Resolve the active scenario from a provided ID or the game's default.
51
+ * Returns null if the game declares no scenarios, or when null is passed
52
+ * to explicitly opt out of the default scenario (the settings defaults).
53
+ */
54
+ resolveScenario(scenarioId?: string | null): SDKScenario | null;
55
+ /**
56
+ * Reject undeclared keys in the given scenario's overrides, validating them
57
+ * against each settings resource's `settingsSchema` exactly as
58
+ * `configuration.json` is validated on load.
59
+ *
60
+ * Mutates nothing and reads no disk, so dev-server boundaries (file-watch
61
+ * reload, scenario switch) can call it before committing and keep the
62
+ * last-good session running when it throws. Throws with the offending keys
63
+ * named and remediation guidance when invalid.
64
+ */
65
+ assertLayeredSettingsValid(scenario: SDKScenario | null): void;
66
+ /**
67
+ * Resolve every settings resource through the §8.2 layers, in order: its
68
+ * schema defaults, then the active scenario's overrides, then the session
69
+ * overrides.
70
+ *
71
+ * Every layer contributes and none replaces. The session layer used to
72
+ * short-circuit the others, which worked only because it was a generated
73
+ * snapshot containing them all; the moment it held what a facilitator
74
+ * actually changed, everything they had not touched went missing (§8.2).
75
+ *
76
+ * Without the session layer, it is what a surface shown outside the
77
+ * session reads, such as a presentation with no session (§6.15.1).
78
+ */
79
+ resolveSettings({ sessionLayer }?: {
80
+ sessionLayer?: boolean;
81
+ }): Record<string, Record<string, unknown>>;
82
+ /**
83
+ * The same layering over any scenario and any top layer, touching neither
84
+ * the active scenario nor the session's own layer. What the scenario
85
+ * editor's draft resolves through (§6.5): the scenario being edited, then
86
+ * the editor's unsaved edits.
87
+ */
88
+ resolveLayers(scenario: SDKScenario | null, overrides: SessionSettingsOverrides | null): Record<string, Record<string, unknown>>;
89
+ /**
90
+ * The settings a resource receives: exactly the ones it lists in
91
+ * `settings`, keyed by identifier (§8). A resource that lists none
92
+ * receives none, on the same terms as an undeclared capability (§7.4).
93
+ */
94
+ settingsFor(declaration: {
95
+ settings?: string[];
96
+ }): Record<string, Record<string, unknown>>;
97
+ /**
98
+ * Load session-override layer from disk.
99
+ * @param reconfigure - If true, regenerate an invalid configuration rather
100
+ * than throwing. Reserved for a caller that knows the file is disposable.
101
+ */
102
+ loadSessionSettingsOverrides(reconfigure?: boolean): Promise<void>;
103
+ /**
104
+ * The settings with the session-override layer ignored: defaults and the
105
+ * active scenario alone. Used by the dev server's 'Reset configuration'
106
+ * action so the operator can return to a clean slate without restarting.
107
+ */
108
+ buildResetConfiguration(): ResolvedSettings;
109
+ /**
110
+ * Every settings resource's resolved values, right now: what a settings
111
+ * editor is seeded with (§8.3), what a save-as-scenario flow
112
+ * bakes in, and what an operator surface displays. Recomputed on demand
113
+ * precisely so a scenario change is reflected in it.
114
+ */
115
+ resolveConfiguration(): ResolvedSettings;
116
+ /**
117
+ * Establish the session-override layer for a fresh session (§8.2).
118
+ *
119
+ * It starts empty and stays empty until something session-scoped writes to
120
+ * it, which for a game with no `setup` slot is never (§8.3). This
121
+ * used to persist a resolved snapshot instead, and because the session layer
122
+ * outranks the scenario, every value the snapshot carried down from one
123
+ * scenario then suppressed the next: selecting a different scenario changed
124
+ * the label and nothing else.
125
+ */
126
+ saveGameConfiguration(): Promise<void>;
127
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Configuration builder - generates and saves session-override layer
3
+ */
4
+ /**
5
+ * Settings values keyed by settings identifier (#597): `{ pricing: {...} }`.
6
+ *
7
+ * The two aliases below share this shape and mean different things. Keeping
8
+ * one name for both is how §12.3 came to type a settings editor's seed as the
9
+ * override layer while §8.3 said it carries the resolved values — which, read
10
+ * literally, seeds a fresh session's form with `{}`.
11
+ */
12
+ type SettingsKeyedValues = Record<string, Record<string, unknown>>;
13
+ /**
14
+ * The session-override layer (§8.2 layer 3): what a facilitator changed for
15
+ * this session, and nothing else.
16
+ *
17
+ * **Sparse by contract.** It holds only the keys something session-scoped
18
+ * actually supplied, never a resolved snapshot of the layers beneath it. A
19
+ * value copied down from a scenario would be indistinguishable from one a
20
+ * facilitator typed, and because this layer outranks the scenario, the
21
+ * scenario could then never be changed (#439).
22
+ */
23
+ export type SessionSettingsOverrides = SettingsKeyedValues;
24
+ /**
25
+ * Settings after §8.2 layering: schema defaults → scenario overrides →
26
+ * session overrides.
27
+ *
28
+ * Complete rather than sparse, because every `settingsSchema` property
29
+ * declares a default (§8.2). This is what logic and surfaces actually receive,
30
+ * what seeds a settings editor (§8.3), and what the state projection reports
31
+ * (§20.1) — deliberately not the override layer, which for a session nobody
32
+ * has configured is empty.
33
+ */
34
+ export type ResolvedSettings = SettingsKeyedValues;
35
+ /**
36
+ * Get the path to the session-override layer file
37
+ */
38
+ export declare function getConfigurationFilePath(packagePath: string): string;
39
+ /**
40
+ * Path to the record of which scenario the saved configuration was built for.
41
+ *
42
+ * `configuration.json` is the sparse session-override layer (§8.2), so it no
43
+ * longer carries values down from the scenario it was built under. The record
44
+ * survives from when it did: a snapshot built under one scenario could not be
45
+ * reused under another, and this let a load tell "for the scenario about to
46
+ * run" from "stale" rather than regenerating and discarding whatever
47
+ * `sdk configure` had just written (#439).
48
+ */
49
+ export declare function getConfigurationScenarioPath(packagePath: string): string;
50
+ /** Record the scenario a saved configuration was built for. `null` means none. */
51
+ export declare function saveConfigurationScenario(packagePath: string, scenarioId: string | null): Promise<void>;
52
+ /**
53
+ * The scenario the saved configuration was built for: an identifier, `null` for
54
+ * none, or `undefined` when nothing was recorded (no configuration has been
55
+ * saved, or it predates this record).
56
+ */
57
+ export declare function readConfigurationScenario(packagePath: string): string | null | undefined;
58
+ /**
59
+ * Save session-override layer to disk
60
+ */
61
+ export declare function saveSessionSettingsOverrides(packagePath: string, configuration: SessionSettingsOverrides): Promise<void>;
62
+ /**
63
+ * Load session-override layer from disk
64
+ */
65
+ export declare function loadSessionSettingsOverrides(packagePath: string): Promise<SessionSettingsOverrides | null>;
66
+ export {};
@@ -0,0 +1,161 @@
1
+ /**
2
+ * How a context is cut down for logic and how what logic returns is folded
3
+ * back into it (§7.4, §7.5, §10.5).
4
+ *
5
+ * Logic receives only the capabilities it declared, and returns a patch rather
6
+ * than a replacement, so the input projection and the result fold are two
7
+ * halves of one contract: projecting is safe only because folding carries
8
+ * through what a resource never saw. The shared store is the other half of the
9
+ * composition: one value per shared capability, written by an aggregate's
10
+ * `shared` slice alone and mirrored into every team's view. These are pure
11
+ * functions over the boards and the store they are handed, so the executor
12
+ * owns the state and this module owns the rules, and each can be read without
13
+ * the other's bookkeeping in the way.
14
+ */
15
+ import type { ResolvedPackageManifest, ContextDeletePath, Participant } from '@seriousgaming/sdk';
16
+ import { type EngineResultRead } from './logic-result';
17
+ import type { GameContext } from './types';
18
+ /** A resource's capability declaration, which projection and write checks read. */
19
+ export interface Declaration {
20
+ reads?: string[];
21
+ writes?: string[];
22
+ }
23
+ /** What folding a result needs to know about the game it lands in. */
24
+ export interface CompositionScope {
25
+ /** Each capability's schema defaults, the base a returned capability merges over. */
26
+ defaults: ReadonlyMap<string, Record<string, unknown>>;
27
+ /** The shared-scope capabilities, which a team's board cannot write (§10.5). */
28
+ sharedIds: ReadonlySet<string>;
29
+ /** The engine's declaration, which an engine result's `deletes` are held to. */
30
+ engine: Declaration;
31
+ }
32
+ /**
33
+ * Whether a proposed mutation changes the value of any capability in
34
+ * `reads`.
35
+ *
36
+ * An empty or absent declaration answers `true`: with nothing declared the
37
+ * runtime cannot tell which writes matter, and a resource whose answer
38
+ * comes from somewhere other than context is exactly the one that must run
39
+ * on every write. That is the honest default rather than an oversight, and
40
+ * it is the same default §11.1a gives the tick controller.
41
+ */
42
+ export declare function mutationAffects(reads: string[] | undefined, previous: GameContext, next: GameContext): boolean;
43
+ /**
44
+ * Refuse a change to any capability the resource does not declare in
45
+ * `writes` (§10.5), whether it reads it or never declared it at all.
46
+ *
47
+ * `writes` is the authorisation for a logic result. The comparison is by
48
+ * value, not by key. Author logic returns its whole projected context by
49
+ * spreading, so every declared capability comes back on every call whether
50
+ * or not it was touched; rejecting on presence would reject the ordinary
51
+ * idiom. A capability that comes back unchanged is the spread doing its job,
52
+ * and only a changed one is a write.
53
+ */
54
+ export declare function enforceDeclaredWrites(identifier: string, declaration: Declaration, contextBefore: GameContext, contextAfter: GameContext, phase: string): void;
55
+ /**
56
+ * Refuse a shared-capability write from a per-team `Init` or `Run` (§10.5).
57
+ *
58
+ * A per-team call runs against one team's board, so a shared value it
59
+ * changed would be a team-addressed write to a value every team reads
60
+ * (§7.5). Only the matching aggregate function writes the store. Compared by
61
+ * value, as {@link enforceDeclaredWrites} compares, so a shared capability
62
+ * returned unchanged by a spread is not a write.
63
+ */
64
+ export declare function enforceSharedWrites(engineIdentifier: string, sharedCapabilityIds: readonly string[], contextBefore: GameContext, contextAfter: GameContext, phase: 'Init' | 'Run'): void;
65
+ /**
66
+ * The capabilities a logic-bearing resource receives (§7.4): its `reads`
67
+ * and its `writes`, and nothing else.
68
+ *
69
+ * No scope filter is applied. `private` reaches logic on the same terms as
70
+ * `team` (§6.1) — only a UI surface withholds it — so this is the union of
71
+ * the two declarations and nothing more. A resource that declares nothing
72
+ * receives nothing, which is what a declaration saying it needs nothing
73
+ * means.
74
+ *
75
+ * Projecting the input is only safe because the result is folded back as a
76
+ * patch ({@link mergeCapabilityFields}): the capabilities a resource never
77
+ * saw are carried through from the context it was called with, not dropped
78
+ * because its return value did not mention them.
79
+ */
80
+ export declare function projectForLogic(context: GameContext, declaration: Declaration): GameContext;
81
+ /**
82
+ * Fold a logic result back into the whole context.
83
+ *
84
+ * Logic receives only the capabilities it declared (§7.4), so what it
85
+ * returns is a **patch** over the rest of the context rather than a
86
+ * replacement for it: the base is `contextBefore`, and only the
87
+ * capabilities the result actually carries are overwritten. An undeclared
88
+ * capability the resource never saw survives untouched, which is what
89
+ * makes projecting the input safe.
90
+ *
91
+ * Within each returned capability the merge order is (last wins): schema
92
+ * defaults → previous values → returned values, so a result that replaces
93
+ * a capability with a subset of its fields does not drop the rest.
94
+ */
95
+ export declare function mergeCapabilityFields(context: GameContext, contextBefore: GameContext, defaults: ReadonlyMap<string, Record<string, unknown>>): GameContext;
96
+ /**
97
+ * Fold a logic result's `capabilities`, then remove each path in its
98
+ * `deletes` (§7.4). The order is §9.5's, and the removal is the very one a
99
+ * UI's `deletes` gets, so a result can replace an entry of a keyed map by
100
+ * writing the new key and dropping the old one in either order.
101
+ */
102
+ export declare function foldLogicResult(capabilities: GameContext, deletes: readonly ContextDeletePath[], contextBefore: GameContext, defaults: ReadonlyMap<string, Record<string, unknown>>): GameContext;
103
+ /**
104
+ * The arguments an aggregate function receives besides config, meta and
105
+ * callbacks: the shared store once, and each team's own capabilities.
106
+ *
107
+ * Both halves are projected onto what the engine declared (§7.4). The
108
+ * store is not repeated inside each team: a game that read it from
109
+ * `teams[0]` had nothing to read in a session with no teams, and at a
110
+ * hundred teams was handed a hundred copies of one value.
111
+ */
112
+ export declare function aggregateArgs(contexts: GameContext[], identities: {
113
+ teamId: string;
114
+ index: number;
115
+ }[], declaration: Declaration, store: GameContext, sharedIds: ReadonlySet<string>, participants: Participant[]): {
116
+ shared: {
117
+ context: GameContext;
118
+ state: unknown;
119
+ };
120
+ teams: {
121
+ teamId: string;
122
+ index: number;
123
+ context: GameContext;
124
+ state: unknown;
125
+ }[];
126
+ participants: Participant[];
127
+ };
128
+ /**
129
+ * Fold an engine result into the context it was called with: its
130
+ * capabilities as a patch, and its `state`, when it returned one, as the
131
+ * team's new engine state whole.
132
+ */
133
+ export declare function applyEngineResult(label: string, result: EngineResultRead, contextBefore: GameContext, scope: CompositionScope): GameContext;
134
+ /**
135
+ * Fold an aggregate result into the team contexts it was called with, write
136
+ * its shared slice to the canonical store, and mirror the store into every
137
+ * team's view.
138
+ *
139
+ * A shared capability is written through `shared` alone. One in a `teams`
140
+ * entry fails the operation: the entry is a per-team patch, and a per-team
141
+ * value for a capability with one value per session cannot be represented.
142
+ * Earlier revisions adopted it when every team agreed, which is how games
143
+ * came to write shared state by returning a copy per team.
144
+ *
145
+ * Every team entry and the shared slice are held to the engine's `writes`
146
+ * before anything lands (§10.5), so a refused result leaves the store as it
147
+ * was. `store` is then written in place, as the canonical store is; the store
148
+ * to keep is returned beside the contexts, because a `deletes` replaces it.
149
+ */
150
+ export declare function applyAggregateResult(read: {
151
+ shared: EngineResultRead;
152
+ teams: EngineResultRead[];
153
+ }, contextsBefore: GameContext[], engineIdentifier: string, phase: 'InitAggregate' | 'RunAggregate', scope: CompositionScope, store: GameContext): {
154
+ contexts: GameContext[];
155
+ store: GameContext;
156
+ };
157
+ /**
158
+ * The schema defaults of every capability a resource of the package reads
159
+ * or writes, keyed by capability.
160
+ */
161
+ export declare function computeCapabilityDefaults(config: ResolvedPackageManifest | null): Map<string, Record<string, unknown>>;
@@ -0,0 +1,9 @@
1
+ import type { EndpointAction, EndpointActionType } from '@seriousgaming/sdk';
2
+ /**
3
+ * The actions an endpoint returned, checked against what it declared (§6.12).
4
+ *
5
+ * All or nothing, like a patch naming an undeclared capability: one bad action
6
+ * fails the call before anything is applied, because carrying out the good
7
+ * ones would leave the response describing a session the caller never gets.
8
+ */
9
+ export declare function readEndpointActions(identifier: string, declared: readonly EndpointActionType[], returned: unknown): EndpointAction[];
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Request and response validation for endpoint calls (§6.12, rules 1 and 5).
3
+ *
4
+ * The schemas an endpoint declares were only ever compiled into types, which
5
+ * binds the surface an author writes against and binds nothing at run time. A
6
+ * caller sending a value the schema forbids reached the handler, and the
7
+ * handler's return reached the caller unchecked.
8
+ *
9
+ * That was survivable while every caller was a screen built from those same
10
+ * generated types. An external endpoint's requests come from outside the game,
11
+ * often from a model, so the schema is the boundary rather than a description
12
+ * of one.
13
+ */
14
+ import type { JSONSchema7 } from 'json-schema';
15
+ /**
16
+ * A failure only an endpoint call can have (§6.12), carrying the
17
+ * `EndpointFailure` kind the caller is told: the request was refused before the
18
+ * handler ran, the handler threw, or what it returned broke its declaration.
19
+ */
20
+ export declare class EndpointFault extends Error {
21
+ readonly kind: 'invalid-request' | 'handler-error' | 'invalid-response';
22
+ constructor(kind: 'invalid-request' | 'handler-error' | 'invalid-response', message: string);
23
+ }
24
+ /**
25
+ * Run `work`, reporting anything it throws as `kind`. A fault already
26
+ * classified keeps its own kind.
27
+ */
28
+ export declare function faultAs<T>(kind: EndpointFault['kind'], work: () => T | Promise<T>): Promise<T>;
29
+ /** Throws when `request` does not satisfy the endpoint's `requestSchema`. */
30
+ export declare function assertValidEndpointRequest(identifier: string, schema: JSONSchema7 | undefined, request: unknown): void;
31
+ /** Throws when `response` does not satisfy the endpoint's `responseSchema`. */
32
+ export declare function assertValidEndpointResponse(identifier: string, schema: JSONSchema7 | undefined, response: unknown): void;
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Running an endpoint's logic (§6.12): building its arguments, calling
3
+ * `Handle`, or `Plan` and later `Respond`, and holding what it returns to its
4
+ * declaration.
5
+ *
6
+ * Everything here is about the call itself and none of it about the session:
7
+ * what the endpoint is handed is cut down to its `reads` and `writes`, file
8
+ * fields in the request become stored `blob:` references, and a returned patch,
9
+ * per-team patch or action list is checked against what the bundle declares
10
+ * before anything is allowed to act on it. Applying those effects is the
11
+ * session's, on its mutation queue with every other write (§9.7), so a run
12
+ * ends in an {@link EndpointRun} describing them rather than in any change.
13
+ */
14
+ import type { ContextDeletePath, EndpointAction, EndpointCaller, EndpointOutcome, EndpointSession, Participant, SDKEndpoint, TeamInfo } from '@seriousgaming/sdk';
15
+ import type { LogicHost } from './logic-calls';
16
+ import type { GameContext } from './types';
17
+ /**
18
+ * The call-shaped half of `runEndpoint`'s arguments: everything a handler's
19
+ * arguments are built from. `respondEndpoint` takes the same, read afresh.
20
+ */
21
+ export interface EndpointCallArgs {
22
+ identifier: string;
23
+ request: unknown;
24
+ caller: EndpointCaller;
25
+ context?: GameContext;
26
+ teams?: readonly {
27
+ teamId: string;
28
+ index: number;
29
+ name: string;
30
+ context: GameContext;
31
+ }[];
32
+ team?: TeamInfo;
33
+ scopedTeamIndex?: number;
34
+ session: EndpointSession;
35
+ /**
36
+ * When the call started (`meta.now`, §10.2). The host takes it once, so
37
+ * `Plan` and `Respond` read the same instant. Read from the executor's
38
+ * clock when absent.
39
+ */
40
+ now?: number;
41
+ /**
42
+ * The participants the call covers (§6.12): the team's, or every one for a
43
+ * session-scoped endpoint. Taken from the roster source when absent.
44
+ */
45
+ participants?: Participant[];
46
+ /**
47
+ * Every settings resource's resolved values, where the call resolves them
48
+ * other than the session does: a call from the scenario editor, which
49
+ * reads the draft it is editing (§6.12). The endpoint is handed its
50
+ * declared ones. The session's when absent.
51
+ */
52
+ settings?: Record<string, Record<string, unknown>>;
53
+ }
54
+ /**
55
+ * One endpoint call's outcome: the response its caller receives, and, for an
56
+ * endpoint that declares `writes`, the board change it asks for. The patch is
57
+ * applied by the session rather than here, so it lands on the mutation queue
58
+ * with every other write (§9.7).
59
+ */
60
+ export interface EndpointRun {
61
+ response: unknown;
62
+ patch?: GameContext;
63
+ /**
64
+ * Paths the endpoint removes after `patch` lands, from the same board:
65
+ * the team's for a team-scoped endpoint, the shared store for a
66
+ * session-scoped one. Already held to its `writes`.
67
+ */
68
+ deletes?: ContextDeletePath[];
69
+ /**
70
+ * A session-scoped endpoint's changes to individual teams' boards, keyed
71
+ * by team id, each already held to its non-shared `writes`.
72
+ */
73
+ teamPatches?: Record<string, GameContext>;
74
+ /** Session actions to carry out after the writes, already checked. */
75
+ actions?: EndpointAction[];
76
+ /**
77
+ * The request as the handler received it, file fields resolved to `blob:`
78
+ * references. `Respond` is given this one, so an inline upload is stored
79
+ * once rather than again for the second phase.
80
+ */
81
+ request?: unknown;
82
+ /**
83
+ * True when the endpoint exports `Plan` and `Respond`: `response` is then
84
+ * absent, and the session calls `respondEndpoint` once the effects land.
85
+ */
86
+ responds?: boolean;
87
+ }
88
+ export interface EndpointRunnerHost extends LogicHost {
89
+ packagePath: string;
90
+ /** The executor's own board, for a team-scoped call that names none. */
91
+ board(): GameContext;
92
+ /** The canonical shared store, as a copy. */
93
+ sharedContext(): GameContext;
94
+ }
95
+ export declare class EndpointRunner {
96
+ private readonly host;
97
+ constructor(host: EndpointRunnerHost);
98
+ /** Look up an endpoint by identifier in the loaded configuration. */
99
+ find(identifier: string): SDKEndpoint | undefined;
100
+ /**
101
+ * Invoke an endpoint's `Handle` function. The caller identity is sourced
102
+ * from host bookkeeping — iframe-supplied fields are never trusted. The
103
+ * returned value is validated against the endpoint's `responseSchema` by
104
+ * the dispatcher before being returned to the caller.
105
+ *
106
+ * Throws if the endpoint is unknown or its bundle does not export a
107
+ * `Handle` function.
108
+ */
109
+ run(args: EndpointCallArgs): Promise<EndpointRun>;
110
+ /**
111
+ * Call `Respond` once an endpoint's effects have landed (§6.12). The
112
+ * arguments are built exactly as `Handle`'s were, from state the session
113
+ * has read afresh, with the plan `Handle` returned and what each of its
114
+ * actions came to. Its return is the response, held to `responseSchema`.
115
+ */
116
+ respond(args: EndpointCallArgs & {
117
+ plan: EndpointRun;
118
+ outcomes: EndpointOutcome[];
119
+ }): Promise<unknown>;
120
+ /** Load endpoint logic (with caching). */
121
+ private load;
122
+ /** Hold what `Handle` or `Plan` returned to the endpoint's declaration (§6.12). */
123
+ private readRun;
124
+ /**
125
+ * Build an endpoint function's arguments and call it, bounded (§6.12).
126
+ * Shared by `Handle`, `Plan` and `Respond`, which see the same shape.
127
+ */
128
+ private invoke;
129
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * The engine's private memory (§10.2): what `Init` and `Run` return under
3
+ * `state`, handed back to the engine alone on its next call.
4
+ *
5
+ * It is held inside the stored context, under a key no capability identifier
6
+ * can take, rather than beside it. Everything that already carries a team's
7
+ * context therefore carries its state for free — tick snapshots, undo, a
8
+ * per-team reset to the initial board, a team added mid-session — and
9
+ * everything that already projects a context onto declared capabilities, which
10
+ * is every path to a surface, a hook, a validator or an endpoint, drops it for
11
+ * free. The two places that hand context out whole, the state projection and
12
+ * past-state rows, strip it explicitly.
13
+ *
14
+ * The session-wide half, `shared.state`, lives in the shared store under a key
15
+ * of its own and is mirrored into every team's view like a shared capability,
16
+ * so a shared-state undo rewinds it with the store.
17
+ */
18
+ import type { GameContext } from './types';
19
+ /** A team's engine state, inside that team's stored context. */
20
+ export declare const ENGINE_STATE_KEY = "$engineState";
21
+ /** The session-wide engine state, inside the shared store and every view. */
22
+ export declare const SHARED_ENGINE_STATE_KEY = "$sharedEngineState";
23
+ /** Whether a context key is engine state rather than a capability. */
24
+ export declare function isReservedKey(key: string): boolean;
25
+ /** A context with the engine's state removed, for anything that is not the engine. */
26
+ export declare function withoutEngineState(context: GameContext): GameContext;
27
+ /**
28
+ * Fail unless `value` survives a JSON round trip unchanged: plain objects,
29
+ * arrays, strings, finite numbers, booleans and `null`.
30
+ *
31
+ * The runtime asks nothing else of engine state, and a hosted runtime persists
32
+ * it as JSON, so a `Date`, a `Map` or a `NaN` that the dev server would happily
33
+ * hold in memory would come back different after a restart. Checked here so it
34
+ * fails on the first tick rather than on the day.
35
+ *
36
+ * Realm-safe: logic runs in its own V8 context, so a plain object it built has
37
+ * that realm's `Object.prototype`, and an `instanceof` or prototype identity
38
+ * check would call it a class instance (#394).
39
+ */
40
+ export declare function assertJsonSerialisable(label: string, value: unknown): void;