@seriousgaming/sdk 0.0.0-stage → 1.0.0-alpha.2

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 (170) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +1 -0
  3. package/README.md +33 -2
  4. package/lib/build/callbacks.d.ts +998 -0
  5. package/lib/build/callbacks.js +32 -0
  6. package/lib/build/context-merge.d.ts +59 -0
  7. package/lib/build/context-merge.js +118 -0
  8. package/lib/build/document.d.ts +36 -0
  9. package/lib/build/document.js +8 -0
  10. package/lib/build/encoding.d.ts +26 -0
  11. package/lib/build/encoding.js +78 -0
  12. package/lib/build/endpoints.d.ts +421 -0
  13. package/lib/build/endpoints.js +46 -0
  14. package/lib/build/hooks.d.ts +74 -0
  15. package/lib/build/hooks.js +1 -0
  16. package/lib/build/index.d.ts +18 -0
  17. package/lib/build/index.js +16 -0
  18. package/lib/build/llm.d.ts +166 -0
  19. package/lib/build/llm.js +17 -0
  20. package/lib/build/resource-schema.d.ts +1048 -0
  21. package/lib/build/resource-schema.js +7 -0
  22. package/lib/build/scheduling.d.ts +112 -0
  23. package/lib/build/scheduling.js +217 -0
  24. package/lib/build/seed.d.ts +51 -0
  25. package/lib/build/seed.js +89 -0
  26. package/lib/build/signatures.d.ts +372 -0
  27. package/lib/build/signatures.js +1 -0
  28. package/lib/build/speech.d.ts +102 -0
  29. package/lib/build/speech.js +11 -0
  30. package/lib/build/tick-validation.d.ts +23 -0
  31. package/lib/build/tick-validation.js +96 -0
  32. package/lib/build/timer.d.ts +74 -0
  33. package/lib/build/timer.js +1 -0
  34. package/lib/build/validators.d.ts +116 -0
  35. package/lib/build/validators.js +1 -0
  36. package/lib/commands.d.ts +357 -0
  37. package/lib/commands.js +14 -0
  38. package/lib/e2e.d.ts +238 -0
  39. package/lib/e2e.js +248 -0
  40. package/lib/projection.d.ts +266 -0
  41. package/lib/projection.js +23 -0
  42. package/lib/testing/index.d.ts +13 -0
  43. package/lib/testing/index.js +13 -0
  44. package/lib/testing/logic-args.d.ts +177 -0
  45. package/lib/testing/logic-args.js +229 -0
  46. package/lib/testing/stub-services.d.ts +41 -0
  47. package/lib/testing/stub-services.js +176 -0
  48. package/lib/ui/CrossTeamDataContext.d.ts +36 -0
  49. package/lib/ui/CrossTeamDataContext.js +32 -0
  50. package/lib/ui/PresentationContext.d.ts +72 -0
  51. package/lib/ui/PresentationContext.js +13 -0
  52. package/lib/ui/PresentationWrapper.d.ts +12 -0
  53. package/lib/ui/PresentationWrapper.js +78 -0
  54. package/lib/ui/SessionUserInterfaceCallbacksContext.d.ts +3 -0
  55. package/lib/ui/SessionUserInterfaceCallbacksContext.js +7 -0
  56. package/lib/ui/SessionUserInterfaceDataContext.d.ts +103 -0
  57. package/lib/ui/SessionUserInterfaceDataContext.js +17 -0
  58. package/lib/ui/SessionUserInterfaceHookFailuresContext.d.ts +44 -0
  59. package/lib/ui/SessionUserInterfaceHookFailuresContext.js +15 -0
  60. package/lib/ui/SessionUserInterfaceHostOverlaysContext.d.ts +23 -0
  61. package/lib/ui/SessionUserInterfaceHostOverlaysContext.js +23 -0
  62. package/lib/ui/SessionUserInterfaceLocaleContext.d.ts +11 -0
  63. package/lib/ui/SessionUserInterfaceLocaleContext.js +13 -0
  64. package/lib/ui/SessionUserInterfaceMetaContext.d.ts +39 -0
  65. package/lib/ui/SessionUserInterfaceMetaContext.js +13 -0
  66. package/lib/ui/SessionUserInterfaceParticipantsContext.d.ts +12 -0
  67. package/lib/ui/SessionUserInterfaceParticipantsContext.js +16 -0
  68. package/lib/ui/SessionUserInterfaceTeamConfigurationContext.d.ts +53 -0
  69. package/lib/ui/SessionUserInterfaceTeamConfigurationContext.js +23 -0
  70. package/lib/ui/SessionUserInterfaceTeamLinksContext.d.ts +56 -0
  71. package/lib/ui/SessionUserInterfaceTeamLinksContext.js +12 -0
  72. package/lib/ui/SessionUserInterfaceTeamsContext.d.ts +13 -0
  73. package/lib/ui/SessionUserInterfaceTeamsContext.js +13 -0
  74. package/lib/ui/SessionUserInterfaceThemeContext.d.ts +9 -0
  75. package/lib/ui/SessionUserInterfaceThemeContext.js +7 -0
  76. package/lib/ui/SessionUserInterfaceThemePreferenceContext.d.ts +3 -0
  77. package/lib/ui/SessionUserInterfaceThemePreferenceContext.js +7 -0
  78. package/lib/ui/SessionUserInterfaceWalkthroughLinkContext.d.ts +42 -0
  79. package/lib/ui/SessionUserInterfaceWalkthroughLinkContext.js +26 -0
  80. package/lib/ui/SessionUserInterfaceWrapper.d.ts +8 -0
  81. package/lib/ui/SessionUserInterfaceWrapper.js +321 -0
  82. package/lib/ui/SettingsEditorCallbacksContext.d.ts +3 -0
  83. package/lib/ui/SettingsEditorCallbacksContext.js +7 -0
  84. package/lib/ui/SettingsEditorContext.d.ts +33 -0
  85. package/lib/ui/SettingsEditorContext.js +16 -0
  86. package/lib/ui/SettingsEditorLocaleContext.d.ts +13 -0
  87. package/lib/ui/SettingsEditorLocaleContext.js +15 -0
  88. package/lib/ui/SettingsEditorThemeContext.d.ts +9 -0
  89. package/lib/ui/SettingsEditorThemeContext.js +7 -0
  90. package/lib/ui/SettingsEditorThemePreferenceContext.d.ts +3 -0
  91. package/lib/ui/SettingsEditorThemePreferenceContext.js +7 -0
  92. package/lib/ui/SettingsEditorWrapper.d.ts +13 -0
  93. package/lib/ui/SettingsEditorWrapper.js +74 -0
  94. package/lib/ui/UserInterfaceCallbacksContext.d.ts +3 -0
  95. package/lib/ui/UserInterfaceCallbacksContext.js +7 -0
  96. package/lib/ui/UserInterfaceDataContext.d.ts +78 -0
  97. package/lib/ui/UserInterfaceDataContext.js +11 -0
  98. package/lib/ui/UserInterfaceLocaleContext.d.ts +13 -0
  99. package/lib/ui/UserInterfaceLocaleContext.js +15 -0
  100. package/lib/ui/UserInterfaceOwnTeamContext.d.ts +25 -0
  101. package/lib/ui/UserInterfaceOwnTeamContext.js +26 -0
  102. package/lib/ui/UserInterfaceOwnTeamJoinLinkContext.d.ts +52 -0
  103. package/lib/ui/UserInterfaceOwnTeamJoinLinkContext.js +13 -0
  104. package/lib/ui/UserInterfaceParticipantContext.d.ts +16 -0
  105. package/lib/ui/UserInterfaceParticipantContext.js +24 -0
  106. package/lib/ui/UserInterfaceParticipantsContext.d.ts +12 -0
  107. package/lib/ui/UserInterfaceParticipantsContext.js +13 -0
  108. package/lib/ui/UserInterfaceRunKindContext.d.ts +31 -0
  109. package/lib/ui/UserInterfaceRunKindContext.js +31 -0
  110. package/lib/ui/UserInterfaceTeamsContext.d.ts +12 -0
  111. package/lib/ui/UserInterfaceTeamsContext.js +13 -0
  112. package/lib/ui/UserInterfaceThemeContext.d.ts +9 -0
  113. package/lib/ui/UserInterfaceThemeContext.js +7 -0
  114. package/lib/ui/UserInterfaceThemePreferenceContext.d.ts +3 -0
  115. package/lib/ui/UserInterfaceThemePreferenceContext.js +7 -0
  116. package/lib/ui/UserInterfaceTimerContext.d.ts +10 -0
  117. package/lib/ui/UserInterfaceTimerContext.js +12 -0
  118. package/lib/ui/UserInterfaceValidationContext.d.ts +25 -0
  119. package/lib/ui/UserInterfaceValidationContext.js +14 -0
  120. package/lib/ui/UserInterfaceViewerRoleContext.d.ts +14 -0
  121. package/lib/ui/UserInterfaceViewerRoleContext.js +17 -0
  122. package/lib/ui/UserInterfaceWrapper.d.ts +8 -0
  123. package/lib/ui/UserInterfaceWrapper.js +219 -0
  124. package/lib/ui/expectedParentOrigin.d.ts +10 -0
  125. package/lib/ui/expectedParentOrigin.js +32 -0
  126. package/lib/ui/index.d.ts +50 -0
  127. package/lib/ui/index.js +52 -0
  128. package/lib/ui/internal/SurfaceGate.d.ts +19 -0
  129. package/lib/ui/internal/SurfaceGate.js +17 -0
  130. package/lib/ui/internal/SurfaceScope.d.ts +17 -0
  131. package/lib/ui/internal/SurfaceScope.js +16 -0
  132. package/lib/ui/internal/createContexts.d.ts +50 -0
  133. package/lib/ui/internal/createContexts.js +32 -0
  134. package/lib/ui/internal/document-attributes.d.ts +9 -0
  135. package/lib/ui/internal/document-attributes.js +87 -0
  136. package/lib/ui/internal/surface-timer.d.ts +3 -0
  137. package/lib/ui/internal/surface-timer.js +11 -0
  138. package/lib/ui/internal/useLatestRef.d.ts +7 -0
  139. package/lib/ui/internal/useLatestRef.js +11 -0
  140. package/lib/ui/internal/useOptimisticMerge.d.ts +19 -0
  141. package/lib/ui/internal/useOptimisticMerge.js +28 -0
  142. package/lib/ui/internal/useSurfaceControls.d.ts +52 -0
  143. package/lib/ui/internal/useSurfaceControls.js +19 -0
  144. package/lib/ui/internal/useTypedPastState.d.ts +17 -0
  145. package/lib/ui/internal/useTypedPastState.js +17 -0
  146. package/lib/ui/mutation-commit.d.ts +32 -0
  147. package/lib/ui/mutation-commit.js +1 -0
  148. package/lib/ui/mutation-outcome.d.ts +66 -0
  149. package/lib/ui/mutation-outcome.js +49 -0
  150. package/lib/ui/request-id.d.ts +18 -0
  151. package/lib/ui/request-id.js +44 -0
  152. package/lib/ui/testing.d.ts +365 -0
  153. package/lib/ui/testing.js +572 -0
  154. package/lib/ui/tick-snapshot.d.ts +28 -0
  155. package/lib/ui/tick-snapshot.js +34 -0
  156. package/lib/ui/ui-protocol.d.ts +799 -0
  157. package/lib/ui/ui-protocol.js +50 -0
  158. package/lib/ui/useAsset.d.ts +80 -0
  159. package/lib/ui/useAsset.js +139 -0
  160. package/lib/ui/useEndpointCallbacks.d.ts +31 -0
  161. package/lib/ui/useEndpointCallbacks.js +68 -0
  162. package/lib/ui/useHostChannel.d.ts +90 -0
  163. package/lib/ui/useHostChannel.js +338 -0
  164. package/lib/ui/useMutationReporter.d.ts +100 -0
  165. package/lib/ui/useMutationReporter.js +97 -0
  166. package/lib/ui/usePastState.d.ts +39 -0
  167. package/lib/ui/usePastState.js +63 -0
  168. package/lib/ui/useViewerStorage.d.ts +54 -0
  169. package/lib/ui/useViewerStorage.js +141 -0
  170. package/package.json +89 -3
@@ -0,0 +1,266 @@
1
+ /**
2
+ * The one documented shape of a session's observable state.
3
+ *
4
+ * Served three ways and declared once: `sdk view --json`, `GET /api/state`, and
5
+ * the payload the console renders. It is a projection, not any runtime's
6
+ * internal state, so internals can change without breaking an agent that
7
+ * learned to read it, and it is versioned so one that has learned can tell when
8
+ * they have not.
9
+ *
10
+ * Everything a runtime exposes about a session belongs here, because a check
11
+ * made from outside a runtime can only read what the runtime exposes.
12
+ *
13
+ * Published from the SDK rather than declared inside a runtime, because a
14
+ * second runtime implementing it needs the shape, and a type it has to copy is
15
+ * a type the two halves are free to drift apart on.
16
+ */
17
+ import type { Participant, TeamInfo } from './build/callbacks.js';
18
+ import type { EndpointCallerRole } from './build/endpoints.js';
19
+ import type { RunKind, SessionMode } from './build/signatures.js';
20
+ import type { TimerState } from './build/timer.js';
21
+ import type { MutationOutcome } from './ui/mutation-outcome.js';
22
+ export type { Participant, TeamInfo, TimerState };
23
+ /**
24
+ * Bumped when a field changes meaning or leaves.
25
+ *
26
+ * Adding a field is not a bump: a reader that ignores what it does not know
27
+ * keeps working. Renaming or removing one is.
28
+ */
29
+ export declare const PROJECTION_VERSION = 4;
30
+ /**
31
+ * A failure a runtime can produce that another otherwise cannot (§9.7, §12.5.1).
32
+ *
33
+ * Armed by name rather than provoked, so an author can verify a game's error
34
+ * handling without manufacturing the race that would otherwise be the only way
35
+ * to reach the state.
36
+ *
37
+ * @internal The SDK dev server's fault injection. Another runtime need not
38
+ * offer it, and the set may change without a major release.
39
+ */
40
+ export type FaultKind =
41
+ /** The next UI mutation settles `{ kind: 'conflict' }` (§12.5.1). */
42
+ 'conflict'
43
+ /** The next UI mutation settles `{ kind: 'denied' }` (§12.5.1). */
44
+ | 'denied'
45
+ /** The next platform service call (`generateText`, `extractText`, `generateSpeech`) rejects (§17). */
46
+ | 'llm-failure'
47
+ /** The next hook chain throws (§14.5). */
48
+ | 'hook-throw'
49
+ /** The next `callEndpoint` exceeds its bound (§6.12). */
50
+ | 'endpoint-timeout'
51
+ /** The next tick fails, atomically (§9.7). */
52
+ | 'tick-failure';
53
+ /**
54
+ * One armed fault, as the state projection reports it.
55
+ *
56
+ * @internal See {@link FaultKind}.
57
+ */
58
+ export interface ArmedFault {
59
+ kind: FaultKind;
60
+ /** How many more times it will fire. */
61
+ remaining: number;
62
+ /** Operator-supplied note, echoed back so a log says why. */
63
+ reason?: string;
64
+ }
65
+ /** Resolved settings, keyed by settings identifier (§8). */
66
+ export type ResolvedSettings = Record<string, Record<string, unknown>>;
67
+ /** The scenario editor's draft of one scenario (§6.5), resolved. */
68
+ export interface ScenarioDraft {
69
+ /** The scenario being edited, or null for one started from the package's own settings. */
70
+ scenarioId: string | null;
71
+ /** The defaults, then that scenario's `settings`, then the unsaved edits. */
72
+ settings: ResolvedSettings;
73
+ }
74
+ export type { SessionMode };
75
+ /** One team's observable state. */
76
+ export interface ProjectedTeam extends TeamInfo {
77
+ /** Ticks this team has completed. Equal to the session's outside independent mode. */
78
+ completedTicks: number;
79
+ complete: boolean;
80
+ canUndo: boolean;
81
+ /** The composed view: the team's own context plus the shared store (§7.5). */
82
+ context: Record<string, Record<string, unknown>>;
83
+ /** §13.2: absence is reported (`connected: false`), never erased. */
84
+ participants: Participant[];
85
+ /**
86
+ * The timer this team's surfaces are sent (§12.3, `TimerState`). In
87
+ * independent mode each team has its own; otherwise every team carries the
88
+ * cohort's. Absent from a runtime that reports none.
89
+ */
90
+ timer?: TimerState;
91
+ /**
92
+ * The engine's private memory for this team (§10.2), absent until the
93
+ * engine first returns one. No surface is ever sent it; it is here for the
94
+ * operator's tools and for tests.
95
+ */
96
+ state?: unknown;
97
+ }
98
+ /**
99
+ * What changed on disk that a running session applies only when it next
100
+ * initialises. Each list is empty when nothing of its kind is waiting.
101
+ */
102
+ export interface PendingChanges {
103
+ /** Settings resources whose resolved values differ from the session's. */
104
+ settings: string[];
105
+ /**
106
+ * Manifest fields read only at initialisation: `identifier`, `teams.mode`,
107
+ * and `setup` for the configuration step. The game's tick limit, team
108
+ * bounds and `openOnStart` are the `game` settings, listed in `settings`.
109
+ */
110
+ manifest: string[];
111
+ /** Capabilities removed from the package, or whose scope changed. */
112
+ capabilities: string[];
113
+ }
114
+ export interface StateProjection {
115
+ projectionVersion: number;
116
+ game: {
117
+ identifier: string;
118
+ /** The game's name in the session locale, which surfaces render. */
119
+ name: string;
120
+ /** The active scenario, or null when the game declares none. */
121
+ scenarioId: string | null;
122
+ };
123
+ session: {
124
+ /** Ticks the session has completed: the shared clock, or the furthest team's. */
125
+ completedTicks: number;
126
+ mode: SessionMode;
127
+ waitingRoomOpen: boolean;
128
+ /** True only once every team is complete (§12.4). */
129
+ complete: boolean;
130
+ /** Stable for the session, unchanged by a re-run of one tick (§10). */
131
+ seed: string;
132
+ /**
133
+ * What every surface of this run is sent on `init` to namespace its
134
+ * own storage by (§12.2): opaque, unique to the run, and not the
135
+ * session's address. Beyond §20.1's shape, as §20.1 permits: the
136
+ * console needs it to hand the frames it mounts.
137
+ */
138
+ sessionKey: string;
139
+ locale: string;
140
+ /**
141
+ * Whether this is the game being played or a walkthrough beside it
142
+ * (§5.7). The same value logic reads as `meta.runKind`.
143
+ */
144
+ runKind: RunKind;
145
+ /**
146
+ * The tick limit: the resolved `game` settings' `maxTicks`, or null when
147
+ * completion is the engine's or the tick controller's to decide.
148
+ */
149
+ maxTicks: number | null;
150
+ /**
151
+ * The team bounds a surface gates its controls on (§5.4).
152
+ *
153
+ * `max` is the **effective** maximum, already resolved as the lower of
154
+ * the game's declared maximum and this host's own ceiling. A surface
155
+ * that read the manifest value instead would disable its add-team
156
+ * control at the wrong point.
157
+ */
158
+ teamBounds: {
159
+ min?: number;
160
+ max: number;
161
+ };
162
+ /**
163
+ * True while the session is in its setup state (§8.3, §9.0): the game has a
164
+ * `setup` slot and nobody has started play yet.
165
+ *
166
+ * On the projection rather than only on a separate route because it
167
+ * decides what a client may render: a console that read it from a
168
+ * second request showed the setup UI for a frame after somebody
169
+ * pressed Play, and the player surfaces for a frame after somebody
170
+ * sent the session back to its setup state.
171
+ */
172
+ inSetup: boolean;
173
+ /**
174
+ * Edits on disk this session has not applied, because they take
175
+ * effect only when a session initialises. Absent when there are none.
176
+ *
177
+ * A local authoring host's own field, beyond §20.1's shape as §20.1
178
+ * permits: a host that reloads a package while it runs must say when
179
+ * the session no longer matches what is on disk, rather than run on
180
+ * a mixture of the two.
181
+ */
182
+ pending?: PendingChanges;
183
+ };
184
+ teams: ProjectedTeam[];
185
+ /** The canonical shared store (§7.5), empty outside shared-state mode. */
186
+ shared: Record<string, Record<string, unknown>>;
187
+ /**
188
+ * The engine's session-wide private memory (§10.2), absent until an
189
+ * aggregate function first returns one under `shared.state`.
190
+ */
191
+ sharedState?: unknown;
192
+ /**
193
+ * The cohort's automatic tick timer (§11.4), the same `TimerState` a
194
+ * surface is sent. Null in independent mode, where each team has its own
195
+ * on its entry.
196
+ */
197
+ timer: TimerState | null;
198
+ /**
199
+ * Every settings resource's resolved values (§8): defaults, the active
200
+ * scenario, then the session's overrides. Keyed by settings identifier.
201
+ */
202
+ settings: ResolvedSettings;
203
+ /**
204
+ * The same, without the session layer: defaults then the active scenario.
205
+ * What a surface shown outside the session reads, such as a presentation
206
+ * previewed with no session (§6.15.1).
207
+ */
208
+ settingsWithoutSession: ResolvedSettings;
209
+ /**
210
+ * Each scenario a scenario editor is open on, with its draft resolved:
211
+ * the defaults, that scenario, then the editor's unsaved edits (§6.5).
212
+ * What the editor is sent as `setSettings`. Absent while none is open.
213
+ */
214
+ scenarioDrafts?: ScenarioDraft[];
215
+ /**
216
+ * Faults armed for this session. Empty in a session nobody has armed one in.
217
+ *
218
+ * @internal See {@link FaultKind}.
219
+ */
220
+ faults: ArmedFault[];
221
+ }
222
+ /**
223
+ * One endpoint call that changed something (§6.12): who made it, and what it
224
+ * changed. Names only, never values, so the log does not become a second copy
225
+ * of the boards.
226
+ */
227
+ export interface EndpointAuditEntry {
228
+ /** Epoch milliseconds, on the session's clock. */
229
+ at: number;
230
+ endpoint: string;
231
+ /** The caller's role, as the endpoint was told it. */
232
+ role: EndpointCallerRole;
233
+ /** Who was behind an external call, where the host said. */
234
+ principal?: {
235
+ kind: string;
236
+ id: string;
237
+ name?: string;
238
+ };
239
+ /** The team a team-scoped call ran for. */
240
+ teamId?: string;
241
+ /** Capabilities its own patch wrote. */
242
+ wrote: string[];
243
+ /** A session-scoped call's per-team writes: team id to capabilities. */
244
+ teams?: Record<string, string[]>;
245
+ /** The session actions it returned, in order. */
246
+ actions: string[];
247
+ /**
248
+ * Where the call stopped, when a step failed after earlier ones had
249
+ * landed: those stay applied, and everything from here on did not.
250
+ */
251
+ stoppedAt?: string;
252
+ }
253
+ /**
254
+ * What a mutation settled as (§12.5.1).
255
+ *
256
+ * The failure half is the SDK's own {@link MutationOutcome}, not a restatement
257
+ * of it: a projection that re-declared the vocabulary it reports would be free
258
+ * to drift from it.
259
+ */
260
+ export type MutationResult = {
261
+ ok: true;
262
+ committedAtTick?: number;
263
+ } | {
264
+ ok: false;
265
+ outcome: MutationOutcome;
266
+ };
@@ -0,0 +1,23 @@
1
+ /**
2
+ * The one documented shape of a session's observable state.
3
+ *
4
+ * Served three ways and declared once: `sdk view --json`, `GET /api/state`, and
5
+ * the payload the console renders. It is a projection, not any runtime's
6
+ * internal state, so internals can change without breaking an agent that
7
+ * learned to read it, and it is versioned so one that has learned can tell when
8
+ * they have not.
9
+ *
10
+ * Everything a runtime exposes about a session belongs here, because a check
11
+ * made from outside a runtime can only read what the runtime exposes.
12
+ *
13
+ * Published from the SDK rather than declared inside a runtime, because a
14
+ * second runtime implementing it needs the shape, and a type it has to copy is
15
+ * a type the two halves are free to drift apart on.
16
+ */
17
+ /**
18
+ * Bumped when a field changes meaning or leaves.
19
+ *
20
+ * Adding a field is not a bump: a reader that ignores what it does not know
21
+ * keeps working. Renaming or removing one is.
22
+ */
23
+ export const PROJECTION_VERSION = 4;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Helpers for unit-testing a game's logic without a runtime.
3
+ *
4
+ * `logicArgs` builds the arguments object a logic function takes, filling
5
+ * everything the test does not name. `createStubCallbacks` is the offline,
6
+ * deterministic set of callbacks it uses, and the stubs behind it are the ones
7
+ * `createTestSession` answers service callbacks with.
8
+ *
9
+ * To test a game as a whole (hooks, validators, endpoints, undo, timers), use
10
+ * `createTestSession` from `@seriousgaming/sdk-tools/client`.
11
+ */
12
+ export { logicArgs, TEST_NOW, TEST_SEED, type AggregateArgsInput, type EndpointArgsInput, type EngineArgsInput, type HookArgsInput, type RequestTickArgsInput, type TickControllerArgsInput, type ValidatorArgsInput, } from './logic-args.js';
13
+ export { createStubCallbacks, STUB_SPEECH_DURATION_MS, stubExtractText, stubGenerateText, stubSpeechAudio, } from './stub-services.js';
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Helpers for unit-testing a game's logic without a runtime.
3
+ *
4
+ * `logicArgs` builds the arguments object a logic function takes, filling
5
+ * everything the test does not name. `createStubCallbacks` is the offline,
6
+ * deterministic set of callbacks it uses, and the stubs behind it are the ones
7
+ * `createTestSession` answers service callbacks with.
8
+ *
9
+ * To test a game as a whole (hooks, validators, endpoints, undo, timers), use
10
+ * `createTestSession` from `@seriousgaming/sdk-tools/client`.
11
+ */
12
+ export { logicArgs, TEST_NOW, TEST_SEED, } from './logic-args.js';
13
+ export { createStubCallbacks, STUB_SPEECH_DURATION_MS, stubExtractText, stubGenerateText, stubSpeechAudio, } from './stub-services.js';
@@ -0,0 +1,177 @@
1
+ /**
2
+ * Arguments for calling a logic function directly in a unit test.
3
+ *
4
+ * Every logic function takes one arguments object, and most of it is the
5
+ * runtime's to supply: `meta`, the roster, the callbacks, a session summary.
6
+ * A test cares about the context and perhaps one setting. Each builder here
7
+ * takes what the test cares about and fills the rest with fixed, deterministic
8
+ * values, typed so the result passes straight to the function with no cast.
9
+ *
10
+ * ```ts
11
+ * import { logicArgs } from '@seriousgaming/sdk/testing';
12
+ * import { defaultContext, defaultSettings } from './defaults';
13
+ * import { Run } from './logic';
14
+ *
15
+ * const result = await Run(
16
+ * logicArgs.run({ context: defaultContext, settings: defaultSettings, meta: { tick: 3 } })
17
+ * );
18
+ * ```
19
+ *
20
+ * Settings are not read from disk: there is no runtime here. Pass the
21
+ * resource's generated `defaultSettings`, spread with any value the test
22
+ * changes. A resource that declares no settings may leave `settings` out.
23
+ */
24
+ import type { AggregateFunctionShared, AggregateFunctionTeam, EndpointCaller, EndpointHandlerArgs, EndpointScope, EndpointSession, EndpointTeamEntry, EngineFunctionArgs, HookFunctionArgs, HookPayloadMap, LogicMeta, Participant, RequestTickFunctionArgs, RunAggregateFunctionArgs, RunMeta, SignatureCallbacks, TeamInfo, TeamRunMeta, TickControllerFunctionArgs, ValidatorActor, ValidatorFunctionArgs } from '../build/index.js';
25
+ import type { HookSignal } from '../build/resource-schema.js';
26
+ /** The `meta.seed` every builder uses unless told otherwise. */
27
+ export declare const TEST_SEED = "test-seed";
28
+ /** The `meta.now` every builder uses unless told otherwise: 2026-01-01T00:00:00Z. */
29
+ export declare const TEST_NOW: number;
30
+ /** A type with no members, which an empty object satisfies. */
31
+ type Empty = Record<never, never>;
32
+ /** The settings a resource that declares none receives. */
33
+ type NoSettings = Record<string, never>;
34
+ /** The callbacks of any logic-bearing resource: some subset of {@link SignatureCallbacks}. */
35
+ type AnyCallbacks = Partial<SignatureCallbacks>;
36
+ /**
37
+ * `settings`, optional only where the type has nothing a test could leave
38
+ * out: a resource that declares no settings resources. Anything else needs its
39
+ * values, since a builder cannot read the schema defaults from disk.
40
+ */
41
+ type SettingsInput<TSettings> = Empty extends TSettings ? {
42
+ settings?: TSettings;
43
+ } : {
44
+ settings: TSettings;
45
+ };
46
+ /** What every team-scoped builder takes beyond its own arguments. */
47
+ interface CommonInput<TCallbacks> {
48
+ /**
49
+ * The roster the call sees. Defaults to one connected participant on the
50
+ * call's team (two teams' worth for a builder with several teams).
51
+ */
52
+ participants?: readonly Readonly<Participant>[];
53
+ /**
54
+ * Callbacks to use instead of the stubs. Anything not named keeps its stub
55
+ * (see `createStubCallbacks`).
56
+ */
57
+ callbacks?: NoInfer<Partial<TCallbacks>>;
58
+ }
59
+ /** Input to {@link logicArgs.init} and {@link logicArgs.run}. */
60
+ export type EngineArgsInput<TContext, TSettings, TCallbacks, TState> = CommonInput<TCallbacks> & SettingsInput<TSettings> & {
61
+ context: TContext;
62
+ /** Any of `meta`; the rest is filled. `teamId` follows `index` when only `index` is given. */
63
+ meta?: Partial<TeamRunMeta>;
64
+ state?: TState;
65
+ };
66
+ /** Input to {@link logicArgs.aggregate}. */
67
+ export type AggregateArgsInput<TTeamContext, TSharedContext, TSettings, TCallbacks, TTeamState, TSharedState> = CommonInput<TCallbacks> & SettingsInput<TSettings> & (Empty extends TSharedContext ? {
68
+ shared?: AggregateFunctionShared<TSharedContext, TSharedState>;
69
+ } : {
70
+ shared: AggregateFunctionShared<TSharedContext, TSharedState>;
71
+ }) & {
72
+ /** Every team the call covers. A team's `teamId` follows its `index` when left out. */
73
+ teams: (Omit<AggregateFunctionTeam<TTeamContext, TTeamState>, 'teamId'> & {
74
+ teamId?: string;
75
+ })[];
76
+ meta?: Partial<RunMeta>;
77
+ };
78
+ /** Input to {@link logicArgs.hook}. */
79
+ export type HookArgsInput<S extends HookSignal, TContext, TSettings, TCallbacks> = CommonInput<TCallbacks> & SettingsInput<TSettings> & HookPayloadMap[S] & {
80
+ /**
81
+ * The signal the hook subscribes to, which decides the payload it
82
+ * needs. Defaults to `participantJoin`; name it for any other.
83
+ */
84
+ signal?: S;
85
+ context: TContext;
86
+ meta?: Partial<LogicMeta>;
87
+ };
88
+ /** Input to {@link logicArgs.endpoint}. */
89
+ export type EndpointArgsInput<TRequest, TContext, TCallbacks, TTeamContext, TSettings> = CommonInput<TCallbacks> & SettingsInput<TSettings> & {
90
+ request: TRequest;
91
+ context: TContext;
92
+ /**
93
+ * Who is calling. `role` defaults to `participant`; the rest follows the
94
+ * role: a participant is the first on the roster, through `ui`; a
95
+ * facilitator calls from `session`; an author calls from `scenario_editor`
96
+ * with no session; an external caller names no surface.
97
+ */
98
+ caller?: Partial<EndpointCaller>;
99
+ /** The team a team-scoped call acts on. Defaults to `team-1`, index 0. */
100
+ team?: Partial<TeamInfo>;
101
+ /** A session-scoped call's per-team values. */
102
+ teams?: EndpointTeamEntry<TTeamContext>[];
103
+ /** Where the session stands. Defaults to an independent session with no ticks completed. */
104
+ session?: Partial<EndpointSession>;
105
+ meta?: Partial<LogicMeta>;
106
+ };
107
+ /** Input to {@link logicArgs.tickController}. */
108
+ export type TickControllerArgsInput<TContext, TSettings, TCallbacks> = CommonInput<TCallbacks> & SettingsInput<TSettings> & {
109
+ context: TContext;
110
+ meta?: Partial<TeamRunMeta>;
111
+ /** Defaults to the one team `meta` names, with `context`. */
112
+ teams?: AggregateFunctionTeam<TContext>[];
113
+ waitingRoomOpen?: boolean;
114
+ };
115
+ /** Input to {@link logicArgs.validator}. */
116
+ export type ValidatorArgsInput<TContext, TSettings> = SettingsInput<TSettings> & {
117
+ previous: TContext;
118
+ next: TContext;
119
+ /** Defaults to the first participant on the roster. */
120
+ actor?: ValidatorActor;
121
+ meta?: Partial<LogicMeta>;
122
+ participants?: readonly Readonly<Participant>[];
123
+ };
124
+ /** Input to {@link logicArgs.requestTick}. */
125
+ export type RequestTickArgsInput<TContext, TSettings> = SettingsInput<TSettings> & {
126
+ context: TContext;
127
+ /** Defaults to 1, a team's first request. */
128
+ requestedTick?: number;
129
+ /** Defaults to the first participant on the roster. */
130
+ actor?: ValidatorActor;
131
+ meta?: Partial<LogicMeta>;
132
+ participants?: readonly Readonly<Participant>[];
133
+ };
134
+ declare function init<TContext, TSettings = NoSettings, TCallbacks extends AnyCallbacks = Required<SignatureCallbacks>, TState = never>(input: EngineArgsInput<TContext, TSettings, TCallbacks, TState>): EngineFunctionArgs<TContext, TSettings, TCallbacks, TState>;
135
+ declare function run<TContext, TSettings = NoSettings, TCallbacks extends AnyCallbacks = Required<SignatureCallbacks>, TState = never>(input: EngineArgsInput<TContext, TSettings, TCallbacks, TState>): EngineFunctionArgs<TContext, TSettings, TCallbacks, TState>;
136
+ declare function aggregate<TTeamContext, TSharedContext = NoSettings, TSettings = NoSettings, TCallbacks extends AnyCallbacks = Required<SignatureCallbacks>, TTeamState = never, TSharedState = never>(input: AggregateArgsInput<TTeamContext, TSharedContext, TSettings, TCallbacks, TTeamState, TSharedState>): RunAggregateFunctionArgs<TTeamContext, TSharedContext, TSettings, TCallbacks, TTeamState, TSharedState>;
137
+ declare function hook<S extends HookSignal = 'participantJoin', TContext = unknown, TSettings = NoSettings, TCallbacks extends AnyCallbacks = Required<SignatureCallbacks>>(input: HookArgsInput<S, TContext, TSettings, TCallbacks>): HookFunctionArgs<S, TContext, TSettings, TCallbacks>;
138
+ declare function endpoint<TRequest, TContext, TCallbacks extends AnyCallbacks = Required<SignatureCallbacks>, TTeamContext = never, TScope extends EndpointScope = 'team', TSettings = NoSettings>(input: EndpointArgsInput<TRequest, TContext, TCallbacks, TTeamContext, TSettings>): EndpointHandlerArgs<TRequest, TContext, TCallbacks, TTeamContext, TScope, TSettings>;
139
+ declare function tickController<TContext, TSettings = NoSettings, TCallbacks extends AnyCallbacks = Required<SignatureCallbacks>>(input: TickControllerArgsInput<TContext, TSettings, TCallbacks>): TickControllerFunctionArgs<TContext, TSettings, TCallbacks>;
140
+ declare function validator<TContext, TSettings = NoSettings>(input: ValidatorArgsInput<TContext, TSettings>): ValidatorFunctionArgs<TContext, TSettings>;
141
+ declare function requestTick<TContext, TSettings = NoSettings>(input: RequestTickArgsInput<TContext, TSettings>): RequestTickFunctionArgs<TContext, TSettings>;
142
+ /**
143
+ * Builders for each logic function's arguments. Each takes what the test
144
+ * names and fills the rest:
145
+ *
146
+ * - `meta`: `locale: 'en'`, `seed: 'test-seed'`, `runKind: 'session'`,
147
+ * `now` 2026-01-01T00:00:00Z, and where the function runs for a team,
148
+ * `index: 0` and `teamId: 'team-1'`. `tick` is 0 for `init` and 1 for the
149
+ * rest; `InitAggregate` passes `meta: { tick: 0 }`
150
+ * - `participants`: one connected participant on each team the call covers
151
+ * - `callbacks`: the offline stubs of `createStubCallbacks`, with any the
152
+ * test passes in their place
153
+ * - `settings`: required unless the resource declares none, since there is no
154
+ * runtime to resolve them. Pass the generated `defaultSettings`
155
+ *
156
+ * | Builder | For |
157
+ * | ---------------- | ----------------------------------------------- |
158
+ * | `init` | the engine's `Init` |
159
+ * | `run` | the engine's `Run`, and the steps it calls |
160
+ * | `aggregate` | `RunAggregate` and `InitAggregate` |
161
+ * | `hook` | a hook's `Run` |
162
+ * | `endpoint` | an endpoint's `Handle` or `Plan` |
163
+ * | `tickController` | `GetTickController` |
164
+ * | `validator` | a validator's `UpdateData` |
165
+ * | `requestTick` | a validator's `RequestTick` |
166
+ */
167
+ export declare const logicArgs: {
168
+ init: typeof init;
169
+ run: typeof run;
170
+ aggregate: typeof aggregate;
171
+ hook: typeof hook;
172
+ endpoint: typeof endpoint;
173
+ tickController: typeof tickController;
174
+ validator: typeof validator;
175
+ requestTick: typeof requestTick;
176
+ };
177
+ export {};