@dreamboard-games/cli 0.1.30-alpha.1 → 0.1.30-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/README.md +179 -22
  2. package/dist/agent-verifier/agent-workspace-verifier.mjs +30 -30
  3. package/dist/agent-verifier/agent-workspace-verifier.mjs.map +1 -0
  4. package/dist/agent-verifier/{chunk-JH22JNYD.mjs → chunk-3UKQVWLV.mjs} +82 -19
  5. package/dist/agent-verifier/chunk-3UKQVWLV.mjs.map +1 -0
  6. package/dist/agent-verifier/{chunk-4WD3YU2E.mjs → chunk-776W3UGV.mjs} +4 -3
  7. package/dist/agent-verifier/chunk-776W3UGV.mjs.map +1 -0
  8. package/dist/agent-verifier/{chunk-CJEEA6NJ.mjs → chunk-7WWGFAAU.mjs} +9 -10
  9. package/dist/agent-verifier/chunk-7WWGFAAU.mjs.map +1 -0
  10. package/dist/agent-verifier/{chunk-2SZHMP6F.mjs → chunk-A64ZZUZV.mjs} +6 -9
  11. package/dist/agent-verifier/chunk-A64ZZUZV.mjs.map +1 -0
  12. package/dist/agent-verifier/{chunk-6A5HRJMQ.mjs → chunk-E7SSWJXJ.mjs} +62 -99
  13. package/dist/agent-verifier/chunk-E7SSWJXJ.mjs.map +1 -0
  14. package/dist/agent-verifier/{chunk-2GBBP27W.mjs → chunk-F2DIOJJZ.mjs} +1 -0
  15. package/dist/agent-verifier/chunk-F2DIOJJZ.mjs.map +1 -0
  16. package/dist/agent-verifier/{chunk-CFU5EWIC.mjs → chunk-G42BGGG2.mjs} +7 -6
  17. package/dist/agent-verifier/chunk-G42BGGG2.mjs.map +1 -0
  18. package/dist/agent-verifier/{chunk-SHUMAVAP.mjs → chunk-H76MT5UR.mjs} +7 -9
  19. package/dist/agent-verifier/chunk-H76MT5UR.mjs.map +1 -0
  20. package/dist/agent-verifier/{chunk-7E65UQLY.mjs → chunk-HGMUAL33.mjs} +3 -2
  21. package/dist/agent-verifier/chunk-HGMUAL33.mjs.map +1 -0
  22. package/dist/agent-verifier/{chunk-LM3OZLZG.mjs → chunk-IAYRNVUC.mjs} +1 -0
  23. package/dist/agent-verifier/chunk-IAYRNVUC.mjs.map +1 -0
  24. package/dist/agent-verifier/{chunk-VYJTHSYR.mjs → chunk-JGT4P4UD.mjs} +2 -1
  25. package/dist/agent-verifier/chunk-JGT4P4UD.mjs.map +1 -0
  26. package/dist/agent-verifier/{chunk-CEDUHGNH.mjs → chunk-LUZ7KE6H.mjs} +8 -3
  27. package/dist/agent-verifier/chunk-LUZ7KE6H.mjs.map +1 -0
  28. package/dist/agent-verifier/{chunk-2E5P5NWG.mjs → chunk-NAK77WXW.mjs} +58 -126
  29. package/dist/agent-verifier/chunk-NAK77WXW.mjs.map +1 -0
  30. package/dist/agent-verifier/{chunk-SYPLYRGB.mjs → chunk-O4YCPU7C.mjs} +116 -15
  31. package/dist/agent-verifier/chunk-O4YCPU7C.mjs.map +1 -0
  32. package/dist/agent-verifier/{chunk-BVVNBJM4.mjs → chunk-S34FRJHS.mjs} +2 -1
  33. package/dist/agent-verifier/chunk-S34FRJHS.mjs.map +1 -0
  34. package/dist/agent-verifier/{chunk-HJFQDSTU.mjs → chunk-SH5JKYOB.mjs} +6 -5
  35. package/dist/agent-verifier/chunk-SH5JKYOB.mjs.map +1 -0
  36. package/dist/agent-verifier/chunk-SKI2ESE5.mjs +44 -0
  37. package/dist/agent-verifier/{chunk-MINCYHXN.mjs → chunk-TAEQKBJB.mjs} +1 -0
  38. package/dist/agent-verifier/chunk-TAEQKBJB.mjs.map +1 -0
  39. package/dist/agent-verifier/{chunk-CEQ2VJWN.mjs → chunk-UIOLGH4A.mjs} +2 -1
  40. package/dist/agent-verifier/chunk-UIOLGH4A.mjs.map +1 -0
  41. package/dist/agent-verifier/chunk-UIZNWRM6.mjs +2432 -0
  42. package/dist/agent-verifier/chunk-UIZNWRM6.mjs.map +1 -0
  43. package/dist/agent-verifier/{chunk-2QMNAVV4.mjs → chunk-VS573ERH.mjs} +2 -1
  44. package/dist/agent-verifier/chunk-VS573ERH.mjs.map +1 -0
  45. package/dist/agent-verifier/{chunk-EOQIV6PS.mjs → chunk-W3N3QJ4V.mjs} +75 -100
  46. package/dist/agent-verifier/chunk-W3N3QJ4V.mjs.map +1 -0
  47. package/dist/agent-verifier/{chunk-EIQWDQWJ.mjs → chunk-XGWCY624.mjs} +11 -12
  48. package/dist/agent-verifier/chunk-XGWCY624.mjs.map +1 -0
  49. package/dist/agent-verifier/{chunk-7653FPGJ.mjs → chunk-XQXDOBYB.mjs} +3 -2
  50. package/dist/agent-verifier/chunk-XQXDOBYB.mjs.map +1 -0
  51. package/dist/agent-verifier/{chunk-MRCUP5SW.mjs → chunk-YE7UAO3T.mjs} +1 -0
  52. package/dist/agent-verifier/chunk-YE7UAO3T.mjs.map +1 -0
  53. package/dist/agent-verifier/{chunk-RBDDIIPM.mjs → chunk-ZEELHSY3.mjs} +1 -0
  54. package/dist/agent-verifier/chunk-ZEELHSY3.mjs.map +1 -0
  55. package/dist/agent-verifier/{compile-5QSPIOUT.mjs → compile-TEQVA46V.mjs} +24 -25
  56. package/dist/agent-verifier/compile-TEQVA46V.mjs.map +1 -0
  57. package/dist/agent-verifier/{global-config-WX3ZZIVU.mjs → global-config-Y2NTSK4R.mjs} +6 -5
  58. package/dist/{keychain-backend-JHTXAKWC.js → agent-verifier/keychain-backend-SPQWGKZN.mjs} +2 -2
  59. package/dist/agent-verifier/keychain-backend-SPQWGKZN.mjs.map +1 -0
  60. package/dist/agent-verifier/{local-files-MTPLP62S.mjs → local-files-JFOQQZDL.mjs} +10 -11
  61. package/dist/agent-verifier/local-files-JFOQQZDL.mjs.map +1 -0
  62. package/dist/agent-verifier/local-typecheck-XVGWI75X.mjs +10 -0
  63. package/dist/agent-verifier/local-typecheck-XVGWI75X.mjs.map +1 -0
  64. package/dist/agent-verifier/{materialize-workspace-FKALAE2T.mjs → materialize-workspace-ZAVGQQSF.mjs} +17 -18
  65. package/dist/agent-verifier/materialize-workspace-ZAVGQQSF.mjs.map +1 -0
  66. package/dist/agent-verifier/{project-state-7GR6BQTQ.mjs → project-state-K576C2TE.mjs} +3 -2
  67. package/dist/agent-verifier/project-state-K576C2TE.mjs.map +1 -0
  68. package/dist/{prompt-GMZABCJC.js → agent-verifier/prompt-MJRJMOGQ.mjs} +2 -2
  69. package/dist/agent-verifier/prompt-MJRJMOGQ.mjs.map +1 -0
  70. package/dist/agent-verifier/{reducer-bundle-preflight-C73LEXI2.mjs → reducer-bundle-preflight-LXNJUBKL.mjs} +6 -9
  71. package/dist/agent-verifier/reducer-bundle-preflight-LXNJUBKL.mjs.map +1 -0
  72. package/dist/agent-verifier/reducer-contract-preflight-TUMQ43JV.mjs +11 -0
  73. package/dist/agent-verifier/reducer-contract-preflight-TUMQ43JV.mjs.map +1 -0
  74. package/dist/agent-verifier/{reducer-native-test-harness-GMWBUISX.mjs → reducer-native-test-harness-CHX5MBL5.mjs} +14 -17
  75. package/dist/agent-verifier/reducer-native-test-harness-CHX5MBL5.mjs.map +1 -0
  76. package/dist/agent-verifier/static-scaffold-R7SVDRQI.mjs +27 -0
  77. package/dist/agent-verifier/static-scaffold-R7SVDRQI.mjs.map +1 -0
  78. package/dist/agent-verifier/{sync-3DUQH32H.mjs → sync-THAI546U.mjs} +31 -37
  79. package/dist/agent-verifier/sync-THAI546U.mjs.map +1 -0
  80. package/dist/agent-verifier/{test-P4U5INTD.mjs → test-AFAQFKOB.mjs} +28 -31
  81. package/dist/agent-verifier/test-AFAQFKOB.mjs.map +1 -0
  82. package/dist/agent-verifier/workspace-codegen-2ZMQRIKJ.mjs +10 -0
  83. package/dist/agent-verifier/workspace-codegen-2ZMQRIKJ.mjs.map +1 -0
  84. package/dist/agent-verifier/{workspace-dependencies-HZ6VVS4G.mjs → workspace-dependencies-NOOQBK6I.mjs} +5 -4
  85. package/dist/agent-verifier/workspace-dependencies-NOOQBK6I.mjs.map +1 -0
  86. package/dist/{chunk-C6UAT6EH.js → chunk-N7XPNNUI.js} +9 -12
  87. package/dist/chunk-N7XPNNUI.js.map +1 -0
  88. package/dist/chunk-SEGVTWSK.js +44 -0
  89. package/dist/chunk-SEGVTWSK.js.map +1 -0
  90. package/dist/{chunk-RS7UXJZV.js → chunk-TAQKH67O.js} +21300 -35881
  91. package/dist/chunk-TAQKH67O.js.map +1 -0
  92. package/dist/{global-config-AGFBDFYD.js → global-config-S4ZIPECE.js} +3 -3
  93. package/dist/global-config-S4ZIPECE.js.map +1 -0
  94. package/dist/index.js +415 -37
  95. package/dist/index.js.map +1 -1
  96. package/dist/internal.js +3 -4
  97. package/dist/{agent-verifier/keychain-backend-TNOPQV3Z.mjs → keychain-backend-HDF4TZDL.js} +2 -1
  98. package/dist/{agent-verifier/prompt-3BAINGAQ.mjs → prompt-NDV3AE5L.js} +2 -1
  99. package/package.json +8 -7
  100. package/skills/dreamboard/references/building-your-first-game.md +510 -0
  101. package/skills/dreamboard/references/cli.md +104 -0
  102. package/skills/dreamboard/references/game-interface.md +548 -0
  103. package/skills/dreamboard/references/manifest-authoring.md +597 -0
  104. package/skills/dreamboard/references/quickstart.md +66 -0
  105. package/skills/dreamboard/references/reducer.md +864 -0
  106. package/skills/dreamboard/references/rule-authoring.md +147 -0
  107. package/skills/dreamboard/references/testing.md +249 -0
  108. package/skills/dreamboard/scripts/events-extract.mjs +218 -0
  109. package/dist/agent-verifier/chunk-54TAYXUD.mjs +0 -12
  110. package/dist/agent-verifier/chunk-6UUJEYDV.mjs +0 -213
  111. package/dist/agent-verifier/chunk-HBNDKQT5.mjs +0 -8381
  112. package/dist/agent-verifier/chunk-LI3ZR3BI.mjs +0 -41
  113. package/dist/agent-verifier/chunk-U6OJN7XS.mjs +0 -8092
  114. package/dist/agent-verifier/chunk-XYDL7GY6.mjs +0 -10
  115. package/dist/agent-verifier/local-typecheck-QFYYAZOK.mjs +0 -9
  116. package/dist/agent-verifier/reducer-contract-preflight-22X7DSZW.mjs +0 -10
  117. package/dist/agent-verifier/static-scaffold-AJMZZQWS.mjs +0 -28
  118. package/dist/agent-verifier/testing-5K2BJYF2.mjs +0 -674
  119. package/dist/agent-verifier/workspace-codegen-JDZJRSDV.mjs +0 -11
  120. package/dist/chunk-2H7UOFLK.js +0 -11
  121. package/dist/chunk-7FOO4AJI.js +0 -50
  122. package/dist/chunk-7FOO4AJI.js.map +0 -1
  123. package/dist/chunk-C6UAT6EH.js.map +0 -1
  124. package/dist/chunk-RS7UXJZV.js.map +0 -1
  125. package/dist/internal.d.ts +0 -311
  126. package/dist/runtime-packages/ui-host-runtime/src/actor-principal.ts +0 -71
  127. package/dist/runtime-packages/ui-host-runtime/src/browser-interaction.ts +0 -139
  128. package/dist/runtime-packages/ui-host-runtime/src/components/host-controls.tsx +0 -374
  129. package/dist/runtime-packages/ui-host-runtime/src/components/host-feedback-toaster.tsx +0 -266
  130. package/dist/runtime-packages/ui-host-runtime/src/components/host-feedback.tsx +0 -212
  131. package/dist/runtime-packages/ui-host-runtime/src/components/host-primitives.tsx +0 -271
  132. package/dist/runtime-packages/ui-host-runtime/src/components/host-session-metadata.tsx +0 -135
  133. package/dist/runtime-packages/ui-host-runtime/src/components/index.ts +0 -5
  134. package/dist/runtime-packages/ui-host-runtime/src/components/perf-overlay.tsx +0 -194
  135. package/dist/runtime-packages/ui-host-runtime/src/gameplay-authority-transport.ts +0 -626
  136. package/dist/runtime-packages/ui-host-runtime/src/host-controls.tsx +0 -1
  137. package/dist/runtime-packages/ui-host-runtime/src/host-feedback.tsx +0 -1
  138. package/dist/runtime-packages/ui-host-runtime/src/host-session-transport.ts +0 -294
  139. package/dist/runtime-packages/ui-host-runtime/src/index.ts +0 -3
  140. package/dist/runtime-packages/ui-host-runtime/src/logger.ts +0 -11
  141. package/dist/runtime-packages/ui-host-runtime/src/perf.ts +0 -324
  142. package/dist/runtime-packages/ui-host-runtime/src/plugin-bridge.ts +0 -195
  143. package/dist/runtime-packages/ui-host-runtime/src/plugin-health-check.ts +0 -138
  144. package/dist/runtime-packages/ui-host-runtime/src/plugin-messages.ts +0 -159
  145. package/dist/runtime-packages/ui-host-runtime/src/plugin-session-gateway.ts +0 -551
  146. package/dist/runtime-packages/ui-host-runtime/src/runtime/index.ts +0 -13
  147. package/dist/runtime-packages/ui-host-runtime/src/screenshot/projection-to-snapshot.ts +0 -122
  148. package/dist/runtime-packages/ui-host-runtime/src/screenshot/static-store-api.ts +0 -26
  149. package/dist/runtime-packages/ui-host-runtime/src/session-ingress-controller.ts +0 -583
  150. package/dist/runtime-packages/ui-host-runtime/src/session-ingress.ts +0 -219
  151. package/dist/runtime-packages/ui-host-runtime/src/session-live-runtime.ts +0 -117
  152. package/dist/runtime-packages/ui-host-runtime/src/session-model.ts +0 -431
  153. package/dist/runtime-packages/ui-host-runtime/src/session-projection.ts +0 -211
  154. package/dist/runtime-packages/ui-host-runtime/src/session-recovery.ts +0 -80
  155. package/dist/runtime-packages/ui-host-runtime/src/session-state-reducer.ts +0 -1034
  156. package/dist/runtime-packages/ui-host-runtime/src/sse-manager.ts +0 -416
  157. package/dist/runtime-packages/ui-host-runtime/src/unified-session-store.ts +0 -184
  158. package/dist/testing-KLSV6CPJ.js +0 -674
  159. package/dist/testing-KLSV6CPJ.js.map +0 -1
  160. /package/dist/{chunk-2H7UOFLK.js.map → agent-verifier/chunk-SKI2ESE5.mjs.map} +0 -0
  161. /package/dist/{global-config-AGFBDFYD.js.map → agent-verifier/global-config-Y2NTSK4R.mjs.map} +0 -0
  162. /package/dist/{keychain-backend-JHTXAKWC.js.map → keychain-backend-HDF4TZDL.js.map} +0 -0
  163. /package/dist/{prompt-GMZABCJC.js.map → prompt-NDV3AE5L.js.map} +0 -0
@@ -1,195 +0,0 @@
1
- import type { PluginStateSnapshot } from "@dreamboard-games/sdk/runtime/runtime-api";
2
- import {
3
- MainToPluginMessageSchema,
4
- PluginToMainMessageSchema,
5
- type MainToPluginMessage,
6
- type PluginToMainMessage,
7
- } from "./plugin-messages.js";
8
- import type { LoggerLike } from "./logger.js";
9
- import { consoleLogger } from "./logger.js";
10
-
11
- type MessageHandler<T> = (data: T) => void;
12
-
13
- export interface PluginBridgeOptions {
14
- logger?: LoggerLike;
15
- }
16
-
17
- export class PluginBridge {
18
- private iframe: HTMLIFrameElement;
19
- private targetOrigin: string;
20
- private allowedOrigins: Set<string>;
21
- private handlers: Map<
22
- PluginToMainMessage["type"],
23
- Set<MessageHandler<PluginToMainMessage>>
24
- > = new Map();
25
- private messageListener: ((event: MessageEvent) => void) | null = null;
26
- private logger: LoggerLike;
27
-
28
- constructor(
29
- iframe: HTMLIFrameElement,
30
- targetOrigin: string,
31
- options: PluginBridgeOptions = {},
32
- ) {
33
- if (!iframe.contentWindow) {
34
- throw new Error("iframe.contentWindow is not available");
35
- }
36
-
37
- this.iframe = iframe;
38
- this.targetOrigin = targetOrigin;
39
- this.allowedOrigins = resolveAllowedOrigins(iframe);
40
- this.logger = options.logger ?? consoleLogger;
41
- this.setupMessageListener();
42
- }
43
-
44
- private validateOrigin(origin: string): boolean {
45
- return this.allowedOrigins.has(origin);
46
- }
47
-
48
- private setupMessageListener(): void {
49
- this.messageListener = (event: MessageEvent) => {
50
- if (event.source !== this.iframe.contentWindow) {
51
- return;
52
- }
53
- if (!this.validateOrigin(event.origin)) {
54
- return;
55
- }
56
-
57
- const result = PluginToMainMessageSchema.safeParse(event.data);
58
- if (!result.success) {
59
- return;
60
- }
61
-
62
- this.emit(result.data.type, result.data);
63
- };
64
-
65
- window.addEventListener("message", this.messageListener);
66
- }
67
-
68
- sendInit(
69
- sessionId: string,
70
- controllablePlayerIds: string[],
71
- controllingPlayerId: string,
72
- userId: string | null,
73
- ): void {
74
- this.sendToPlugin({
75
- type: "init",
76
- sessionId,
77
- controllablePlayerIds,
78
- controllingPlayerId,
79
- userId,
80
- });
81
- }
82
-
83
- sendPing(): void {
84
- this.sendToPlugin({
85
- type: "ping",
86
- });
87
- }
88
-
89
- sendStateSync(syncId: number, state: PluginStateSnapshot): void {
90
- this.sendToPlugin({
91
- type: "state-sync",
92
- syncId,
93
- state,
94
- });
95
- }
96
-
97
- sendSubmitResult(result: {
98
- messageId: string;
99
- accepted: boolean;
100
- errorCode?: string;
101
- message?: string;
102
- }): void {
103
- this.sendToPlugin({
104
- type: "submit-result",
105
- ...result,
106
- });
107
- }
108
-
109
- send(message: Record<string, unknown>): void {
110
- if (!this.iframe.contentWindow) {
111
- this.logger.error(
112
- "[PluginBridge] iframe contentWindow not available for message:",
113
- message.type,
114
- );
115
- return;
116
- }
117
-
118
- this.iframe.contentWindow.postMessage(message, this.targetOrigin);
119
- }
120
-
121
- private sendToPlugin(message: MainToPluginMessage): void {
122
- if (!this.iframe.contentWindow) {
123
- this.logger.error(
124
- "[PluginBridge] iframe contentWindow not available for message:",
125
- message.type,
126
- );
127
- return;
128
- }
129
-
130
- const result = MainToPluginMessageSchema.safeParse(message);
131
- if (!result.success) {
132
- this.logger.error(
133
- "[PluginBridge] Failed to validate outgoing message:",
134
- message,
135
- );
136
- return;
137
- }
138
-
139
- this.iframe.contentWindow.postMessage(result.data, this.targetOrigin);
140
- }
141
-
142
- onPluginMessage<T extends PluginToMainMessage["type"]>(
143
- type: T,
144
- handler: MessageHandler<Extract<PluginToMainMessage, { type: T }>>,
145
- ): () => void {
146
- if (!this.handlers.has(type)) {
147
- this.handlers.set(type, new Set());
148
- }
149
-
150
- const handlers = this.handlers.get(type);
151
- if (!handlers) {
152
- throw new Error(`Handler for type ${type} not found`);
153
- }
154
-
155
- handlers.add(handler as MessageHandler<PluginToMainMessage>);
156
-
157
- return () => {
158
- handlers.delete(handler as MessageHandler<PluginToMainMessage>);
159
- };
160
- }
161
-
162
- private emit(
163
- type: PluginToMainMessage["type"],
164
- data: PluginToMainMessage,
165
- ): void {
166
- const handlers = this.handlers.get(type);
167
- if (handlers) {
168
- handlers.forEach((handler) => handler(data));
169
- }
170
- }
171
-
172
- disconnect(): void {
173
- if (this.messageListener) {
174
- window.removeEventListener("message", this.messageListener);
175
- this.messageListener = null;
176
- }
177
-
178
- this.handlers.clear();
179
- }
180
- }
181
-
182
- function resolveAllowedOrigins(iframe: HTMLIFrameElement): Set<string> {
183
- const allowedOrigins = new Set<string>(["null"]);
184
-
185
- try {
186
- const iframeUrl = new URL(iframe.src, window.location.href);
187
- if (iframeUrl.origin && iframeUrl.origin !== "null") {
188
- allowedOrigins.add(iframeUrl.origin);
189
- }
190
- } catch {
191
- // Ignore invalid or unset iframe URLs and keep the sandboxed null origin.
192
- }
193
-
194
- return allowedOrigins;
195
- }
@@ -1,138 +0,0 @@
1
- import { PluginBridge } from "./plugin-bridge.js";
2
- import type { LoggerLike } from "./logger.js";
3
- import { consoleLogger } from "./logger.js";
4
-
5
- export interface HealthCheckConfig {
6
- pingInterval: number;
7
- pongTimeout: number;
8
- maxMissedPongs: number;
9
- }
10
-
11
- const DEFAULT_CONFIG: HealthCheckConfig = {
12
- pingInterval: 5000,
13
- pongTimeout: 2000,
14
- maxMissedPongs: 3,
15
- };
16
-
17
- export class PluginHealthCheck {
18
- private bridge: PluginBridge;
19
- private config: HealthCheckConfig;
20
- private onUnhealthy: () => void;
21
- private logger: LoggerLike;
22
-
23
- private pingIntervalId: ReturnType<typeof setInterval> | null = null;
24
- private pongTimeoutId: ReturnType<typeof setTimeout> | null = null;
25
- private missedPongCount = 0;
26
- private isRunning = false;
27
- private pongUnsubscribe: (() => void) | null = null;
28
-
29
- constructor(
30
- bridge: PluginBridge,
31
- options: {
32
- config?: Partial<HealthCheckConfig>;
33
- onUnhealthy: () => void;
34
- logger?: LoggerLike;
35
- },
36
- ) {
37
- this.bridge = bridge;
38
- this.config = { ...DEFAULT_CONFIG, ...options.config };
39
- this.onUnhealthy = options.onUnhealthy;
40
- this.logger = options.logger ?? consoleLogger;
41
- }
42
-
43
- start(): void {
44
- if (this.isRunning) {
45
- this.logger.warn("[HealthCheck] Already running");
46
- return;
47
- }
48
-
49
- this.isRunning = true;
50
- this.missedPongCount = 0;
51
-
52
- this.pongUnsubscribe = this.bridge.onPluginMessage("pong", () => {
53
- this.handlePong();
54
- });
55
-
56
- this.pingIntervalId = setInterval(() => {
57
- this.sendPing();
58
- }, this.config.pingInterval);
59
-
60
- this.sendPing();
61
- }
62
-
63
- stop(): void {
64
- if (!this.isRunning) {
65
- return;
66
- }
67
-
68
- this.isRunning = false;
69
-
70
- if (this.pingIntervalId) {
71
- clearInterval(this.pingIntervalId);
72
- this.pingIntervalId = null;
73
- }
74
-
75
- if (this.pongTimeoutId) {
76
- clearTimeout(this.pongTimeoutId);
77
- this.pongTimeoutId = null;
78
- }
79
-
80
- if (this.pongUnsubscribe) {
81
- this.pongUnsubscribe();
82
- this.pongUnsubscribe = null;
83
- }
84
-
85
- this.missedPongCount = 0;
86
- this.logger.log("[HealthCheck] Stopped monitoring");
87
- }
88
-
89
- private sendPing(): void {
90
- if (!this.isRunning) {
91
- return;
92
- }
93
-
94
- if (this.pongTimeoutId) {
95
- clearTimeout(this.pongTimeoutId);
96
- }
97
-
98
- this.bridge.sendPing();
99
-
100
- this.pongTimeoutId = setTimeout(() => {
101
- this.handleMissedPong();
102
- }, this.config.pongTimeout);
103
- }
104
-
105
- private handlePong(): void {
106
- if (this.pongTimeoutId) {
107
- clearTimeout(this.pongTimeoutId);
108
- this.pongTimeoutId = null;
109
- }
110
-
111
- if (this.missedPongCount > 0) {
112
- this.logger.log("[HealthCheck] Plugin recovered");
113
- this.missedPongCount = 0;
114
- }
115
- }
116
-
117
- private handleMissedPong(): void {
118
- this.missedPongCount++;
119
-
120
- this.logger.warn(
121
- `[HealthCheck] Missed pong #${this.missedPongCount}/${this.config.maxMissedPongs}`,
122
- );
123
-
124
- if (this.missedPongCount >= this.config.maxMissedPongs) {
125
- this.logger.error("[HealthCheck] Plugin iframe is unresponsive!");
126
- this.stop();
127
- this.onUnhealthy();
128
- }
129
- }
130
-
131
- isHealthCheckRunning(): boolean {
132
- return this.isRunning;
133
- }
134
-
135
- getMissedPongCount(): number {
136
- return this.missedPongCount;
137
- }
138
- }
@@ -1,159 +0,0 @@
1
- import { z } from "zod";
2
- import type { PluginStateSnapshot } from "@dreamboard-games/sdk/runtime/runtime-api";
3
-
4
- export const InitMessageSchema = z.object({
5
- type: z.literal("init"),
6
- sessionId: z.string(),
7
- controllablePlayerIds: z.array(z.string()),
8
- controllingPlayerId: z.string(),
9
- userId: z.string().nullable(),
10
- });
11
-
12
- export const PingMessageSchema = z.object({
13
- type: z.literal("ping"),
14
- });
15
-
16
- export const StateSyncMessageSchema = z.object({
17
- type: z.literal("state-sync"),
18
- syncId: z.number(),
19
- state: z.custom<PluginStateSnapshot>((data) => {
20
- return (
21
- typeof data === "object" &&
22
- data !== null &&
23
- "session" in data &&
24
- "notifications" in data
25
- );
26
- }),
27
- });
28
-
29
- export const SubmitResultMessageSchema = z.object({
30
- type: z.literal("submit-result"),
31
- messageId: z.string(),
32
- accepted: z.boolean(),
33
- errorCode: z.string().optional(),
34
- message: z.string().optional(),
35
- });
36
-
37
- export const MainToPluginMessageSchema = z.discriminatedUnion("type", [
38
- InitMessageSchema,
39
- PingMessageSchema,
40
- StateSyncMessageSchema,
41
- SubmitResultMessageSchema,
42
- ]);
43
-
44
- export type MainToPluginMessage = z.infer<typeof MainToPluginMessageSchema>;
45
-
46
- export const ReadyMessageSchema = z.object({
47
- type: z.literal("ready"),
48
- });
49
-
50
- // `params` is intentionally `z.unknown()` rather than `z.record(...)`. The
51
- // unified interaction wire carries every player input — actions and prompt
52
- // responses alike — and the ingress layer's `runtimePayloadSchema` already
53
- // accepts scalars (`z.boolean() | z.number() | z.string() | z.null() |
54
- // Array<...> | Record<...>`). Constraining this bridge field to an object
55
- // would make the host stricter than the ingress it forwards into, which
56
- // would mask legitimate scalar payloads (e.g. if a future authoring API
57
- // exposes runtime-opened prompts with a scalar `responseSchema`). Safety
58
- // still lives downstream: the reducer re-validates prompt responses via
59
- // `validatePromptResponseInput` and actions via collector schemas, so this
60
- // widening doesn't weaken end-to-end validation.
61
- export const InteractionMessageSchema = z.object({
62
- type: z.literal("interaction"),
63
- messageId: z.string(),
64
- playerId: z.string(),
65
- interactionId: z.string(),
66
- params: z.unknown(),
67
- // Optional client-minted correlation id (UUID) that lets the whole
68
- // click-to-render path be stitched across plugin iframe, web host,
69
- // backend spans/logs and SSE. Added for Tier-0 input-latency
70
- // observability; the backend rides it through as an HTTP header
71
- // (`X-Dreamboard-Client-Action-Id`) but no wire contract changed.
72
- clientActionId: z.string().optional(),
73
- // Plugin-iframe `Date.now()` captured right before the postMessage
74
- // is sent, used as the `t0_click` timestamp on the host-side perf
75
- // buffer. Date.now() is intentional: the iframe and the host share
76
- // a wall-clock base, but not a `performance.now()` origin.
77
- clientSubmittedAtMs: z.number().optional(),
78
- });
79
-
80
- export const ValidateInteractionMessageSchema = z.object({
81
- type: z.literal("validate-interaction"),
82
- playerId: z.string(),
83
- interactionId: z.string(),
84
- params: z.unknown(),
85
- messageId: z.string(),
86
- });
87
-
88
- export const ValidateInteractionResultMessageSchema = z.object({
89
- type: z.literal("validate-interaction-result"),
90
- messageId: z.string(),
91
- result: z.object({
92
- valid: z.boolean(),
93
- errorCode: z.string().optional(),
94
- message: z.string().optional(),
95
- }),
96
- });
97
-
98
- export const PluginErrorMessageSchema = z.object({
99
- type: z.literal("error"),
100
- message: z.string(),
101
- code: z.string().optional(),
102
- });
103
-
104
- export const PongMessageSchema = z.object({
105
- type: z.literal("pong"),
106
- });
107
-
108
- export const SwitchPlayerMessageSchema = z.object({
109
- type: z.literal("switch-player"),
110
- playerId: z.string(),
111
- });
112
-
113
- export const StateAckMessageSchema = z.object({
114
- type: z.literal("state-ack"),
115
- syncId: z.number(),
116
- // Plugin-iframe `Date.now()` captured when the state-sync message
117
- // was received. Threaded so the host-side perf HUD can compute the
118
- // `t7_state_sync_received` mark without needing perf to be enabled
119
- // inside the plugin iframe itself.
120
- clientReceivedAtMs: z.number().optional(),
121
- });
122
-
123
- /**
124
- * Plugin -> host message sent from a `queueMicrotask` scheduled inside
125
- * the state-sync handler so the timestamp reflects roughly when React
126
- * would have committed the DOM update for the new state. Dev-only /
127
- * perf-only: host records it as `t8_render_commit` on the perf HUD.
128
- */
129
- export const StateRenderedMessageSchema = z.object({
130
- type: z.literal("state-rendered"),
131
- syncId: z.number(),
132
- clientReceivedAtMs: z.number(),
133
- clientRenderedAtMs: z.number(),
134
- });
135
-
136
- export const MarkNotificationReadMessageSchema = z.object({
137
- type: z.literal("mark-notification-read"),
138
- notificationId: z.string(),
139
- });
140
-
141
- export const RestoreHistoryMessageSchema = z.object({
142
- type: z.literal("restore-history"),
143
- entryId: z.string(),
144
- });
145
-
146
- export const PluginToMainMessageSchema = z.discriminatedUnion("type", [
147
- ReadyMessageSchema,
148
- InteractionMessageSchema,
149
- ValidateInteractionMessageSchema,
150
- PluginErrorMessageSchema,
151
- PongMessageSchema,
152
- SwitchPlayerMessageSchema,
153
- StateAckMessageSchema,
154
- StateRenderedMessageSchema,
155
- MarkNotificationReadMessageSchema,
156
- RestoreHistoryMessageSchema,
157
- ]);
158
-
159
- export type PluginToMainMessage = z.infer<typeof PluginToMainMessageSchema>;