@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.
- package/LICENSE +93 -0
- package/README.md +36 -2
- package/dist/bundling/logic-exports.d.ts +34 -0
- package/dist/bundling/node-builtins.d.ts +21 -0
- package/dist/bundling/transpiler.d.ts +7 -0
- package/dist/cli.js +27368 -0
- package/dist/client/dev-server.d.ts +59 -0
- package/dist/client/index.d.ts +28 -0
- package/dist/client/stub-services.d.ts +32 -0
- package/dist/client/test-session.d.ts +195 -0
- package/dist/client.js +16884 -0
- package/dist/core/asset-reference-translator.d.ts +46 -0
- package/dist/core/clock.d.ts +57 -0
- package/dist/core/faults.d.ts +65 -0
- package/dist/core/game-settings.d.ts +65 -0
- package/dist/core/history.d.ts +89 -0
- package/dist/core/listen-with-fallback.d.ts +30 -0
- package/dist/core/mutation-queue.d.ts +61 -0
- package/dist/core/package-scenario.d.ts +89 -0
- package/dist/core/participant-registry.d.ts +109 -0
- package/dist/core/pending-changes.d.ts +14 -0
- package/dist/core/protocol.d.ts +83 -0
- package/dist/core/scenario-drafts.d.ts +32 -0
- package/dist/core/session-endpoints.d.ts +108 -0
- package/dist/core/session-gates.d.ts +75 -0
- package/dist/core/session-host.d.ts +94 -0
- package/dist/core/session-refusals.d.ts +56 -0
- package/dist/core/session-rewind.d.ts +32 -0
- package/dist/core/session-roster.d.ts +128 -0
- package/dist/core/session-surfaces.d.ts +32 -0
- package/dist/core/session-ticks.d.ts +18 -0
- package/dist/core/session-timers.d.ts +84 -0
- package/dist/core/session-writes.d.ts +40 -0
- package/dist/core/session.d.ts +385 -0
- package/dist/core/settings-locks.d.ts +22 -0
- package/dist/core/team-names.d.ts +52 -0
- package/dist/core/team-state-store.d.ts +209 -0
- package/dist/core/tick-timer.d.ts +75 -0
- package/dist/dev/blob-links.d.ts +10 -0
- package/dist/dev/console/assets/index-DgFglsnA.js +204 -0
- package/dist/dev/console/index.html +12 -0
- package/dist/dev/console-path.d.ts +19 -0
- package/dist/dev/lockfile.d.ts +124 -0
- package/dist/dev/package-watcher.d.ts +21 -0
- package/dist/dev/routes.d.ts +67 -0
- package/dist/dev/shell.d.ts +260 -0
- package/dist/dev/surfaces.d.ts +41 -0
- package/dist/dev/tools-identity.d.ts +23 -0
- package/dist/dev/view/batch.d.ts +172 -0
- package/dist/dev/view/commands.d.ts +75 -0
- package/dist/dev/view/route.d.ts +58 -0
- package/dist/dev/view/view.d.ts +78 -0
- package/dist/dev/view/viewer.d.ts +32 -0
- package/dist/discovery/config.d.ts +9 -0
- package/dist/discovery/manifest-paths.d.ts +21 -0
- package/dist/discovery/removed-fields.d.ts +90 -0
- package/dist/docs/api/deck.md +386 -0
- package/dist/docs/api/index.md +67 -0
- package/dist/docs/api/sdk-commands.md +286 -0
- package/dist/docs/api/sdk-e2e.md +433 -0
- package/dist/docs/api/sdk-projection.md +207 -0
- package/dist/docs/api/sdk-testing.md +214 -0
- package/dist/docs/api/sdk-tools-client.md +560 -0
- package/dist/docs/api/sdk-ui-testing.md +231 -0
- package/dist/docs/api/sdk-ui.md +1269 -0
- package/dist/docs/api/sdk.md +2140 -0
- package/dist/docs/changelog-0.x.md +1156 -0
- package/dist/docs/changelog.md +236 -0
- package/dist/docs/cli-and-dev-server.md +217 -0
- package/dist/docs/cli-error-codes.md +154 -0
- package/dist/docs/cli-reference.md +2488 -0
- package/dist/docs/cli-simulation-testing.md +222 -0
- package/dist/docs/concepts/index.md +46 -0
- package/dist/docs/concepts/terminology.md +322 -0
- package/dist/docs/environment-variables.md +102 -0
- package/dist/docs/getting-started.md +145 -0
- package/dist/docs/guides/ai-facilitation.md +220 -0
- package/dist/docs/guides/capabilities.md +460 -0
- package/dist/docs/guides/endpoints.md +335 -0
- package/dist/docs/guides/engine-testing.md +477 -0
- package/dist/docs/guides/engine.md +527 -0
- package/dist/docs/guides/file-handling.md +405 -0
- package/dist/docs/guides/games.md +176 -0
- package/dist/docs/guides/global-settings.md +94 -0
- package/dist/docs/guides/guide.md +123 -0
- package/dist/docs/guides/hooks.md +183 -0
- package/dist/docs/guides/index.md +51 -0
- package/dist/docs/guides/internationalization.md +288 -0
- package/dist/docs/guides/llm-integration.md +635 -0
- package/dist/docs/guides/multi-team-games.md +586 -0
- package/dist/docs/guides/patterns.md +391 -0
- package/dist/docs/guides/presentation.md +196 -0
- package/dist/docs/guides/production-constraints.md +130 -0
- package/dist/docs/guides/scenario-editor.md +143 -0
- package/dist/docs/guides/scenarios.md +515 -0
- package/dist/docs/guides/session.md +972 -0
- package/dist/docs/guides/settings.md +458 -0
- package/dist/docs/guides/setup.md +193 -0
- package/dist/docs/guides/speech-generation.md +233 -0
- package/dist/docs/guides/starter-game.md +164 -0
- package/dist/docs/guides/testing.md +575 -0
- package/dist/docs/guides/tick-controller.md +569 -0
- package/dist/docs/guides/type-safety.md +516 -0
- package/dist/docs/guides/ui.md +1389 -0
- package/dist/docs/guides/upgrading.md +636 -0
- package/dist/docs/guides/validators.md +217 -0
- package/dist/docs/guides/waiting-room.md +244 -0
- package/dist/docs/index.md +41 -0
- package/dist/docs/recipes/act-on-the-session-from-an-endpoint.md +95 -0
- package/dist/docs/recipes/adapt-a-game-for-walkthroughs.md +133 -0
- package/dist/docs/recipes/adapt-ui-for-observers.md +74 -0
- package/dist/docs/recipes/call-endpoint-from-ui.md +109 -0
- package/dist/docs/recipes/check-a-package-from-a-script.md +117 -0
- package/dist/docs/recipes/create-capability.md +66 -0
- package/dist/docs/recipes/create-endpoint.md +127 -0
- package/dist/docs/recipes/create-engine.md +111 -0
- package/dist/docs/recipes/create-game.md +70 -0
- package/dist/docs/recipes/create-guide.md +75 -0
- package/dist/docs/recipes/create-hook.md +80 -0
- package/dist/docs/recipes/create-presentation.md +142 -0
- package/dist/docs/recipes/create-scenario-editor.md +102 -0
- package/dist/docs/recipes/create-scenario.md +98 -0
- package/dist/docs/recipes/create-session-ui.md +116 -0
- package/dist/docs/recipes/create-settings.md +88 -0
- package/dist/docs/recipes/create-setup.md +115 -0
- package/dist/docs/recipes/create-tick-controller.md +65 -0
- package/dist/docs/recipes/create-user-interface.md +96 -0
- package/dist/docs/recipes/create-validator.md +67 -0
- package/dist/docs/recipes/create-waiting-room-ui.md +109 -0
- package/dist/docs/recipes/declare-api-uses.md +67 -0
- package/dist/docs/recipes/design-state-for-concurrent-writes.md +96 -0
- package/dist/docs/recipes/distribute-package.md +80 -0
- package/dist/docs/recipes/e2e-testing.md +116 -0
- package/dist/docs/recipes/end-game-on-condition.md +154 -0
- package/dist/docs/recipes/fix-duplicate-packages.md +101 -0
- package/dist/docs/recipes/index.md +86 -0
- package/dist/docs/recipes/make-an-endpoint-external.md +101 -0
- package/dist/docs/recipes/negotiate-across-teams.md +164 -0
- package/dist/docs/recipes/observe-other-teams-state.md +119 -0
- package/dist/docs/recipes/publish-a-package.md +139 -0
- package/dist/docs/recipes/remember-a-viewers-choice.md +55 -0
- package/dist/docs/recipes/review-a-past-day.md +73 -0
- package/dist/docs/recipes/share-assets-across-scenarios.md +120 -0
- package/dist/docs/recipes/share-logic-between-engine-and-ui.md +130 -0
- package/dist/docs/recipes/show-all-teams-participants.md +109 -0
- package/dist/docs/recipes/start-from-an-empty-package.md +169 -0
- package/dist/docs/recipes/take-a-file-in-an-endpoint.md +82 -0
- package/dist/docs/recipes/test-a-multi-role-game.md +51 -0
- package/dist/docs/recipes/test-user-interface.md +95 -0
- package/dist/docs/recipes/test-with-engine.md +115 -0
- package/dist/docs/recipes/upload-and-display-files.md +148 -0
- package/dist/docs/recipes/use-request-play.md +65 -0
- package/dist/docs/recipes/use-request-tick.md +75 -0
- package/dist/docs/troubleshooting.md +816 -0
- package/dist/execution/blob-inputs.d.ts +57 -0
- package/dist/execution/bundle-reload.d.ts +42 -0
- package/dist/execution/config-resolver.d.ts +127 -0
- package/dist/execution/configuration-builder.d.ts +66 -0
- package/dist/execution/context-composition.d.ts +161 -0
- package/dist/execution/endpoint-actions.d.ts +9 -0
- package/dist/execution/endpoint-payloads.d.ts +32 -0
- package/dist/execution/endpoint-runner.d.ts +129 -0
- package/dist/execution/engine-state.d.ts +40 -0
- package/dist/execution/executor-callbacks.d.ts +56 -0
- package/dist/execution/executor.d.ts +436 -0
- package/dist/execution/gates.d.ts +45 -0
- package/dist/execution/hook-chain.d.ts +25 -0
- package/dist/execution/logic-calls.d.ts +190 -0
- package/dist/execution/logic-failure.d.ts +84 -0
- package/dist/execution/logic-loader.d.ts +54 -0
- package/dist/execution/logic-result.d.ts +76 -0
- package/dist/execution/tick-controller-call.d.ts +32 -0
- package/dist/execution/types.d.ts +48 -0
- package/dist/generation/ts-type.d.ts +39 -0
- package/dist/guide/locale.d.ts +12 -0
- package/dist/guide/video-registry.d.ts +42 -0
- package/dist/help-examples.d.ts +125 -0
- package/dist/host/adapter.d.ts +67 -0
- package/dist/host/host-channel.d.ts +222 -0
- package/dist/host/index.d.ts +20 -0
- package/dist/host/protocol.d.ts +783 -0
- package/dist/host/surfaces.d.ts +42 -0
- package/dist/host/theme.d.ts +55 -0
- package/dist/host.js +583 -0
- package/dist/prompts/index.d.ts +7 -0
- package/dist/prompts/schema-builder.d.ts +29 -0
- package/dist/prompts/types.d.ts +108 -0
- package/dist/prompts/validators.d.ts +32 -0
- package/dist/runtime/capability-scope.d.ts +6 -0
- package/dist/runtime/context-merge.d.ts +29 -0
- package/dist/runtime/context-projection.d.ts +41 -0
- package/dist/runtime/guarded-callbacks.d.ts +15 -0
- package/dist/runtime/index.d.ts +27 -0
- package/dist/runtime/manifest-version.d.ts +55 -0
- package/dist/runtime/tick-validation.d.ts +25 -0
- package/dist/runtime.js +346 -0
- package/dist/schema.json +1546 -0
- package/dist/server/vite-plugin.d.ts +46 -0
- package/dist/services/tts/client.d.ts +51 -0
- package/dist/services/tts/elevenlabs.d.ts +24 -0
- package/dist/services/tts/types.d.ts +44 -0
- package/dist/storage/asset-resolver.d.ts +49 -0
- package/dist/storage/blob-store.d.ts +41 -0
- package/dist/templates/endpoint/logic.test.ts.liquid +61 -0
- package/dist/templates/endpoint/logic.ts.liquid +25 -0
- package/dist/templates/engine/init.json.liquid +7 -0
- package/dist/templates/engine/logic-aggregate.test.ts.liquid +90 -0
- package/dist/templates/engine/logic-aggregate.ts.liquid +46 -0
- package/dist/templates/engine/logic.test.ts.liquid +61 -0
- package/dist/templates/engine/logic.ts.liquid +32 -0
- package/dist/templates/engine/run.json.liquid +7 -0
- package/dist/templates/guide/01-at-a-glance.md.liquid +19 -0
- package/dist/templates/guide/02-preparation.md.liquid +18 -0
- package/dist/templates/guide/03-running-the-session.md.liquid +37 -0
- package/dist/templates/hook/logic.test.ts.liquid +46 -0
- package/dist/templates/hook/logic.ts.liquid +12 -0
- package/dist/templates/package/CLAUDE.md.template +338 -0
- package/dist/templates/package/DESIGN.md.liquid +144 -0
- package/dist/templates/package/README.md.liquid +143 -0
- package/dist/templates/package/claude/rules/workflow-create-capability.md +26 -0
- package/dist/templates/package/claude/rules/workflow-create-endpoint.md +35 -0
- package/dist/templates/package/claude/rules/workflow-create-engine.md +35 -0
- package/dist/templates/package/claude/rules/workflow-create-guide.md +40 -0
- package/dist/templates/package/claude/rules/workflow-create-presentation.md +37 -0
- package/dist/templates/package/claude/rules/workflow-create-user-interface.md +31 -0
- package/dist/templates/package/claude/rules/workflow-publish-package.md +54 -0
- package/dist/templates/package/claude/rules/workflow-test-engine-or-ui.md +30 -0
- package/dist/templates/package/claude/rules/workflow-update-sdk-version.md +43 -0
- package/dist/templates/package/claude/settings.json.template +16 -0
- package/dist/templates/package/gitignore.template +15 -0
- package/dist/templates/package/global-setup.ts.template +21 -0
- package/dist/templates/package/globals.d.ts.template +2 -0
- package/dist/templates/package/oxfmtrc.json.template +14 -0
- package/dist/templates/package/oxlintrc.json.template +238 -0
- package/dist/templates/package/package.json.liquid +65 -0
- package/dist/templates/package/playwright.config.ts.liquid +19 -0
- package/dist/templates/package/pnpm-workspace.yaml.template +27 -0
- package/dist/templates/package/test-setup.ts.liquid +7 -0
- package/dist/templates/package/tsconfig.json.liquid +15 -0
- package/dist/templates/package/vite.config.ts.liquid +19 -0
- package/dist/templates/package/vitest.config.ts.liquid +25 -0
- package/dist/templates/package/vitest.engine.config.ts.liquid +12 -0
- package/dist/templates/presentation/index.html.liquid +20 -0
- package/dist/templates/presentation/src/App.tsx.liquid +49 -0
- package/dist/templates/presentation/src/Slides.tsx.liquid +81 -0
- package/dist/templates/presentation/src/i18n.ts.liquid +54 -0
- package/dist/templates/presentation/src/main.tsx.liquid +14 -0
- package/dist/templates/scenario_editor/src/App.test.tsx.liquid +30 -0
- package/dist/templates/scenario_editor/src/App.tsx.liquid +95 -0
- package/dist/templates/scenario_editor/src/i18n.ts.liquid +44 -0
- package/dist/templates/session/src/App.test.tsx.liquid +60 -0
- package/dist/templates/session/src/App.tsx.liquid +128 -0
- package/dist/templates/session/src/i18n.ts.liquid +53 -0
- package/dist/templates/session/src/main.tsx.liquid +48 -0
- package/dist/templates/session/src/theme.ts.liquid +46 -0
- package/dist/templates/settings-editor/index.html.liquid +12 -0
- package/dist/templates/settings-editor/src/main.tsx.liquid +48 -0
- package/dist/templates/settings-editor/src/theme.ts.liquid +24 -0
- package/dist/templates/setup/src/App.test.tsx.liquid +39 -0
- package/dist/templates/setup/src/App.tsx.liquid +102 -0
- package/dist/templates/setup/src/i18n.ts.liquid +47 -0
- package/dist/templates/starter-game/capabilities/briefing/capability.sdk.json +18 -0
- package/dist/templates/starter-game/capabilities/plan/capability.sdk.json +17 -0
- package/dist/templates/starter-game/capabilities/results/capability.sdk.json +61 -0
- package/dist/templates/starter-game/capabilities/roles/capability.sdk.json +17 -0
- package/dist/templates/starter-game/capabilities/weather/capability.sdk.json +23 -0
- package/dist/templates/starter-game/engine/defaults.ts +81 -0
- package/dist/templates/starter-game/engine/engine.sdk.json +12 -0
- package/dist/templates/starter-game/engine/logic.test.ts +221 -0
- package/dist/templates/starter-game/engine/logic.ts +149 -0
- package/dist/templates/starter-game/engine/test-helpers.ts +74 -0
- package/dist/templates/starter-game/engine/types.ts +139 -0
- package/dist/templates/starter-game/guide/content/en/01-at-a-glance.md +51 -0
- package/dist/templates/starter-game/guide/content/en/02-preparation.md +35 -0
- package/dist/templates/starter-game/guide/content/en/03-running-the-day.md +58 -0
- package/dist/templates/starter-game/guide/guide.sdk.json +10 -0
- package/dist/templates/starter-game/guide/guide.test.ts +108 -0
- package/dist/templates/starter-game/hooks/assignproducts/defaults.ts +37 -0
- package/dist/templates/starter-game/hooks/assignproducts/hook.sdk.json +13 -0
- package/dist/templates/starter-game/hooks/assignproducts/logic/logic.test.ts +77 -0
- package/dist/templates/starter-game/hooks/assignproducts/logic/logic.ts +47 -0
- package/dist/templates/starter-game/hooks/assignproducts/types.ts +55 -0
- package/dist/templates/starter-game/package.json +68 -0
- package/dist/templates/starter-game/playwright.config.ts +19 -0
- package/dist/templates/starter-game/scenarios/heatwave/scenario.sdk.json +20 -0
- package/dist/templates/starter-game/scenarios/ordinary_week/scenario.sdk.json +12 -0
- package/dist/templates/starter-game/seriousgaming.sdk.json +23 -0
- package/dist/templates/starter-game/session/defaults.ts +80 -0
- package/dist/templates/starter-game/session/index.html +12 -0
- package/dist/templates/starter-game/session/session.sdk.json +11 -0
- package/dist/templates/starter-game/session/src/App.test.tsx +307 -0
- package/dist/templates/starter-game/session/src/App.tsx +309 -0
- package/dist/templates/starter-game/session/src/Section.tsx +37 -0
- package/dist/templates/starter-game/session/src/TeamDoor.tsx +96 -0
- package/dist/templates/starter-game/session/src/format.ts +8 -0
- package/dist/templates/starter-game/session/src/i18n.ts +51 -0
- package/dist/templates/starter-game/session/src/main.tsx +48 -0
- package/dist/templates/starter-game/session/src/theme.ts +45 -0
- package/dist/templates/starter-game/session/types.ts +135 -0
- package/dist/templates/starter-game/settings/engine/settings.sdk.json +50 -0
- package/dist/templates/starter-game/settings/menu/settings.sdk.json +78 -0
- package/dist/templates/starter-game/settings/session/settings.sdk.json +23 -0
- package/dist/templates/starter-game/settings/ui/settings.sdk.json +25 -0
- package/dist/templates/starter-game/test-setup.ts +7 -0
- package/dist/templates/starter-game/testing/e2e/game.spec.ts +139 -0
- package/dist/templates/starter-game/testing/e2e/global-setup.ts +21 -0
- package/dist/templates/starter-game/testing/engine/game.engine.test.ts +171 -0
- package/dist/templates/starter-game/tsconfig.json +19 -0
- package/dist/templates/starter-game/ui/defaults.ts +60 -0
- package/dist/templates/starter-game/ui/index.html +12 -0
- package/dist/templates/starter-game/ui/src/App.test.tsx +138 -0
- package/dist/templates/starter-game/ui/src/App.tsx +175 -0
- package/dist/templates/starter-game/ui/src/DayBar.test.tsx +78 -0
- package/dist/templates/starter-game/ui/src/DayBar.tsx +72 -0
- package/dist/templates/starter-game/ui/src/HistoryPanel.test.tsx +74 -0
- package/dist/templates/starter-game/ui/src/HistoryPanel.tsx +120 -0
- package/dist/templates/starter-game/ui/src/MakeRow.tsx +129 -0
- package/dist/templates/starter-game/ui/src/Section.tsx +37 -0
- package/dist/templates/starter-game/ui/src/ThemeToggle.tsx +49 -0
- package/dist/templates/starter-game/ui/src/TodayPanel.test.tsx +179 -0
- package/dist/templates/starter-game/ui/src/TodayPanel.tsx +92 -0
- package/dist/templates/starter-game/ui/src/YesterdayPanel.tsx +142 -0
- package/dist/templates/starter-game/ui/src/format.ts +12 -0
- package/dist/templates/starter-game/ui/src/i18n.ts +95 -0
- package/dist/templates/starter-game/ui/src/main.tsx +48 -0
- package/dist/templates/starter-game/ui/src/menu.ts +18 -0
- package/dist/templates/starter-game/ui/src/test-helpers.ts +58 -0
- package/dist/templates/starter-game/ui/src/theme.ts +45 -0
- package/dist/templates/starter-game/ui/src/writes.ts +43 -0
- package/dist/templates/starter-game/ui/types.ts +137 -0
- package/dist/templates/starter-game/ui/ui.sdk.json +11 -0
- package/dist/templates/starter-game/validators/capacity/defaults.ts +37 -0
- package/dist/templates/starter-game/validators/capacity/logic/logic.test.ts +96 -0
- package/dist/templates/starter-game/validators/capacity/logic/logic.ts +45 -0
- package/dist/templates/starter-game/validators/capacity/types.ts +55 -0
- package/dist/templates/starter-game/validators/capacity/validator.sdk.json +11 -0
- package/dist/templates/starter-game/vite.config.ts +19 -0
- package/dist/templates/starter-game/vitest.config.ts +15 -0
- package/dist/templates/starter-game/vitest.engine.config.ts +19 -0
- package/dist/templates/starter-game/waiting_room/defaults.ts +40 -0
- package/dist/templates/starter-game/waiting_room/index.html +12 -0
- package/dist/templates/starter-game/waiting_room/src/App.test.tsx +102 -0
- package/dist/templates/starter-game/waiting_room/src/App.tsx +194 -0
- package/dist/templates/starter-game/waiting_room/src/i18n.ts +33 -0
- package/dist/templates/starter-game/waiting_room/src/main.tsx +48 -0
- package/dist/templates/starter-game/waiting_room/src/theme.ts +45 -0
- package/dist/templates/starter-game/waiting_room/types.ts +59 -0
- package/dist/templates/starter-game/waiting_room/waiting_room.sdk.json +10 -0
- package/dist/templates/tick-controller/logic.ts.liquid +8 -0
- package/dist/templates/ui/index.html.liquid +12 -0
- package/dist/templates/ui/src/App.test.tsx.liquid +41 -0
- package/dist/templates/ui/src/App.tsx.liquid +103 -0
- package/dist/templates/ui/src/i18n.ts.liquid +47 -0
- package/dist/templates/ui/src/main.tsx.liquid +48 -0
- package/dist/templates/ui/src/theme.ts.liquid +46 -0
- package/dist/templates/validator/logic.test.ts.liquid +42 -0
- package/dist/templates/validator/logic.ts.liquid +21 -0
- package/dist/templates/waiting-room/index.html.liquid +12 -0
- package/dist/templates/waiting-room/src/App.test.tsx.liquid +57 -0
- package/dist/templates/waiting-room/src/App.tsx.liquid +118 -0
- package/dist/templates/waiting-room/src/i18n.ts.liquid +44 -0
- package/dist/templates/waiting-room/src/main.tsx.liquid +48 -0
- package/dist/templates/waiting-room/src/theme.ts.liquid +46 -0
- package/dist/templating/resource-metadata.d.ts +131 -0
- package/dist/types.d.ts +14 -0
- package/dist/utils/atomic-write.d.ts +40 -0
- package/dist/utils/cli-error.d.ts +64 -0
- package/dist/utils/document-parser-client.d.ts +20 -0
- package/dist/utils/env-loader.d.ts +40 -0
- package/dist/utils/error-codes.d.ts +335 -0
- package/dist/utils/errors.d.ts +19 -0
- package/dist/utils/global-settings.d.ts +65 -0
- package/dist/utils/llm-client.d.ts +34 -0
- package/dist/utils/logger.d.ts +36 -0
- package/dist/utils/output.d.ts +109 -0
- package/dist/utils/platform.d.ts +14 -0
- package/dist/utils/prompt.d.ts +36 -0
- package/dist/utils/real-path.d.ts +6 -0
- package/dist/utils/schema-properties.d.ts +35 -0
- package/dist/validation/ajv.d.ts +17 -0
- package/dist/validation/facilitator-guide-validator.d.ts +27 -0
- package/dist/validation/findings.d.ts +40 -0
- package/dist/validation/game-constraints.d.ts +10 -0
- package/dist/validation/game-validator.d.ts +34 -0
- package/dist/validation/package-validation.d.ts +41 -0
- package/dist/validation/package-validator.d.ts +19 -0
- package/dist/validation/resource-validator.d.ts +79 -0
- package/dist/validation/schema-defaults-validator.d.ts +29 -0
- package/dist/validation/schema-validation.d.ts +115 -0
- package/dist/validation/semver.d.ts +9 -0
- 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;
|