@dreamboard-games/cli 0.1.30-alpha.0 → 0.1.30-alpha.10

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 (156) hide show
  1. package/README.md +179 -22
  2. package/dist/agent-verifier/agent-workspace-verifier.mjs +31 -30
  3. package/dist/agent-verifier/agent-workspace-verifier.mjs.map +1 -0
  4. package/dist/agent-verifier/{chunk-2NZNKIND.mjs → chunk-3IJBOLGT.mjs} +4 -12
  5. package/dist/agent-verifier/chunk-3IJBOLGT.mjs.map +1 -0
  6. package/dist/agent-verifier/{chunk-6A5HRJMQ.mjs → chunk-4GU3PCHV.mjs} +62 -99
  7. package/dist/agent-verifier/chunk-4GU3PCHV.mjs.map +1 -0
  8. package/dist/agent-verifier/{chunk-SYPLYRGB.mjs → chunk-6XRC5PWB.mjs} +119 -310
  9. package/dist/agent-verifier/chunk-6XRC5PWB.mjs.map +1 -0
  10. package/dist/agent-verifier/{chunk-BVVNBJM4.mjs → chunk-COB56ESI.mjs} +2 -1
  11. package/dist/agent-verifier/chunk-COB56ESI.mjs.map +1 -0
  12. package/dist/agent-verifier/{chunk-2GBBP27W.mjs → chunk-F2DIOJJZ.mjs} +1 -0
  13. package/dist/agent-verifier/chunk-F2DIOJJZ.mjs.map +1 -0
  14. package/dist/agent-verifier/{chunk-CFU5EWIC.mjs → chunk-G42BGGG2.mjs} +7 -6
  15. package/dist/agent-verifier/chunk-G42BGGG2.mjs.map +1 -0
  16. package/dist/agent-verifier/{chunk-XYDL7GY6.mjs → chunk-H6XDQJ3N.mjs} +1 -0
  17. package/dist/agent-verifier/{chunk-LM3OZLZG.mjs → chunk-IAYRNVUC.mjs} +1 -0
  18. package/dist/agent-verifier/chunk-IAYRNVUC.mjs.map +1 -0
  19. package/dist/agent-verifier/{chunk-2QMNAVV4.mjs → chunk-JZTH3EMV.mjs} +2 -1
  20. package/dist/agent-verifier/chunk-JZTH3EMV.mjs.map +1 -0
  21. package/dist/agent-verifier/chunk-KK47X7RV.mjs +14 -0
  22. package/dist/agent-verifier/chunk-KK47X7RV.mjs.map +1 -0
  23. package/dist/agent-verifier/{chunk-SHUMAVAP.mjs → chunk-M7UVBANQ.mjs} +8 -9
  24. package/dist/agent-verifier/chunk-M7UVBANQ.mjs.map +1 -0
  25. package/dist/agent-verifier/{chunk-RJBLBYHX.mjs → chunk-MGXX4WFR.mjs} +87 -22
  26. package/dist/agent-verifier/chunk-MGXX4WFR.mjs.map +1 -0
  27. package/dist/agent-verifier/{chunk-2E5P5NWG.mjs → chunk-NAK77WXW.mjs} +58 -126
  28. package/dist/agent-verifier/chunk-NAK77WXW.mjs.map +1 -0
  29. package/dist/agent-verifier/{chunk-CEQ2VJWN.mjs → chunk-POBFNXD4.mjs} +2 -1
  30. package/dist/agent-verifier/chunk-POBFNXD4.mjs.map +1 -0
  31. package/dist/agent-verifier/{chunk-6UUJEYDV.mjs → chunk-QBAF7EYR.mjs} +1 -0
  32. package/dist/agent-verifier/chunk-QBAF7EYR.mjs.map +1 -0
  33. package/dist/agent-verifier/{chunk-7653FPGJ.mjs → chunk-RHI6S4SU.mjs} +3 -2
  34. package/dist/agent-verifier/chunk-RHI6S4SU.mjs.map +1 -0
  35. package/dist/agent-verifier/{chunk-MINCYHXN.mjs → chunk-TAEQKBJB.mjs} +1 -0
  36. package/dist/agent-verifier/chunk-TAEQKBJB.mjs.map +1 -0
  37. package/dist/agent-verifier/{chunk-PM3SVG6R.mjs → chunk-TLYGTHXU.mjs} +3 -2
  38. package/dist/agent-verifier/chunk-TLYGTHXU.mjs.map +1 -0
  39. package/dist/agent-verifier/{chunk-EIQWDQWJ.mjs → chunk-UWJIZML3.mjs} +13 -14
  40. package/dist/agent-verifier/chunk-UWJIZML3.mjs.map +1 -0
  41. package/dist/agent-verifier/{chunk-DTMJCPS4.mjs → chunk-VLOIZDR6.mjs} +15 -31
  42. package/dist/agent-verifier/chunk-VLOIZDR6.mjs.map +1 -0
  43. package/dist/agent-verifier/{chunk-HJFQDSTU.mjs → chunk-W2MDP5ZN.mjs} +6 -5
  44. package/dist/agent-verifier/chunk-W2MDP5ZN.mjs.map +1 -0
  45. package/dist/agent-verifier/{chunk-CEDUHGNH.mjs → chunk-XKCJBIRY.mjs} +2 -1
  46. package/dist/agent-verifier/chunk-XKCJBIRY.mjs.map +1 -0
  47. package/dist/agent-verifier/{chunk-VYJTHSYR.mjs → chunk-YDIOW2BO.mjs} +2 -1
  48. package/dist/agent-verifier/chunk-YDIOW2BO.mjs.map +1 -0
  49. package/dist/agent-verifier/{chunk-MRCUP5SW.mjs → chunk-YE7UAO3T.mjs} +1 -0
  50. package/dist/agent-verifier/chunk-YE7UAO3T.mjs.map +1 -0
  51. package/dist/agent-verifier/{chunk-EOQIV6PS.mjs → chunk-YR664DJX.mjs} +111 -116
  52. package/dist/agent-verifier/chunk-YR664DJX.mjs.map +1 -0
  53. package/dist/agent-verifier/{chunk-2SZHMP6F.mjs → chunk-Z6OZWUIZ.mjs} +6 -9
  54. package/dist/agent-verifier/chunk-Z6OZWUIZ.mjs.map +1 -0
  55. package/dist/agent-verifier/{chunk-RBDDIIPM.mjs → chunk-ZEELHSY3.mjs} +1 -0
  56. package/dist/agent-verifier/chunk-ZEELHSY3.mjs.map +1 -0
  57. package/dist/agent-verifier/{compile-WNCQQVOF.mjs → compile-C2VIP6VC.mjs} +27 -27
  58. package/dist/agent-verifier/compile-C2VIP6VC.mjs.map +1 -0
  59. package/dist/agent-verifier/{global-config-WX3ZZIVU.mjs → global-config-XHL7BCKN.mjs} +6 -5
  60. package/dist/agent-verifier/global-config-XHL7BCKN.mjs.map +1 -0
  61. package/dist/agent-verifier/{keychain-backend-TNOPQV3Z.mjs → keychain-backend-A3MRWLPF.mjs} +2 -1
  62. package/dist/agent-verifier/keychain-backend-A3MRWLPF.mjs.map +1 -0
  63. package/dist/agent-verifier/{local-files-MTPLP62S.mjs → local-files-ZW52HSVT.mjs} +10 -11
  64. package/dist/agent-verifier/local-files-ZW52HSVT.mjs.map +1 -0
  65. package/dist/agent-verifier/local-typecheck-3JXL2NMG.mjs +10 -0
  66. package/dist/agent-verifier/local-typecheck-3JXL2NMG.mjs.map +1 -0
  67. package/dist/agent-verifier/{materialize-workspace-EWGZIVOY.mjs → materialize-workspace-BKZLLFI4.mjs} +20 -20
  68. package/dist/agent-verifier/materialize-workspace-BKZLLFI4.mjs.map +1 -0
  69. package/dist/agent-verifier/{project-state-7GR6BQTQ.mjs → project-state-XKUSCFSV.mjs} +3 -2
  70. package/dist/agent-verifier/project-state-XKUSCFSV.mjs.map +1 -0
  71. package/dist/agent-verifier/{prompt-3BAINGAQ.mjs → prompt-VKHMCQT6.mjs} +2 -1
  72. package/dist/agent-verifier/prompt-VKHMCQT6.mjs.map +1 -0
  73. package/dist/agent-verifier/{reducer-bundle-preflight-C73LEXI2.mjs → reducer-bundle-preflight-7NYZF5ZT.mjs} +6 -9
  74. package/dist/agent-verifier/reducer-bundle-preflight-7NYZF5ZT.mjs.map +1 -0
  75. package/dist/agent-verifier/reducer-contract-preflight-COD2CO22.mjs +11 -0
  76. package/dist/agent-verifier/reducer-contract-preflight-COD2CO22.mjs.map +1 -0
  77. package/dist/agent-verifier/{reducer-native-test-harness-GMWBUISX.mjs → reducer-native-test-harness-D4VWPIAC.mjs} +14 -17
  78. package/dist/agent-verifier/reducer-native-test-harness-D4VWPIAC.mjs.map +1 -0
  79. package/dist/agent-verifier/static-scaffold-JCRBDKEH.mjs +26 -0
  80. package/dist/agent-verifier/static-scaffold-JCRBDKEH.mjs.map +1 -0
  81. package/dist/agent-verifier/{sync-LOQAH4RC.mjs → sync-UTL2IIZV.mjs} +35 -39
  82. package/dist/agent-verifier/sync-UTL2IIZV.mjs.map +1 -0
  83. package/dist/agent-verifier/{test-YOJERVHN.mjs → test-H26XCBFA.mjs} +29 -31
  84. package/dist/agent-verifier/test-H26XCBFA.mjs.map +1 -0
  85. package/dist/agent-verifier/workspace-codegen-WPZHMATU.mjs +10 -0
  86. package/dist/agent-verifier/workspace-codegen-WPZHMATU.mjs.map +1 -0
  87. package/dist/agent-verifier/{workspace-dependencies-HZ6VVS4G.mjs → workspace-dependencies-ULZZZPNX.mjs} +5 -4
  88. package/dist/agent-verifier/workspace-dependencies-ULZZZPNX.mjs.map +1 -0
  89. package/dist/{chunk-TSJVWTJO.js → chunk-GXM7RRZJ.js} +14 -11
  90. package/dist/chunk-GXM7RRZJ.js.map +1 -0
  91. package/dist/{chunk-3XNJT3RK.js → chunk-P5TITCD3.js} +808 -17878
  92. package/dist/chunk-P5TITCD3.js.map +1 -0
  93. package/dist/{global-config-UKSWNDTX.js → global-config-WPJRXVDO.js} +2 -2
  94. package/dist/global-config-WPJRXVDO.js.map +1 -0
  95. package/dist/index.js +987 -255
  96. package/dist/index.js.map +1 -1
  97. package/dist/internal.js +2 -3
  98. package/package.json +8 -7
  99. package/skills/dreamboard/references/building-your-first-game.md +510 -0
  100. package/skills/dreamboard/references/cli.md +104 -0
  101. package/skills/dreamboard/references/game-interface.md +548 -0
  102. package/skills/dreamboard/references/manifest-authoring.md +597 -0
  103. package/skills/dreamboard/references/quickstart.md +66 -0
  104. package/skills/dreamboard/references/reducer.md +864 -0
  105. package/skills/dreamboard/references/rule-authoring.md +147 -0
  106. package/skills/dreamboard/references/testing.md +249 -0
  107. package/skills/dreamboard/scripts/events-extract.mjs +218 -0
  108. package/dist/agent-verifier/chunk-54TAYXUD.mjs +0 -12
  109. package/dist/agent-verifier/chunk-HBNDKQT5.mjs +0 -8381
  110. package/dist/agent-verifier/chunk-LI3ZR3BI.mjs +0 -41
  111. package/dist/agent-verifier/chunk-U6OJN7XS.mjs +0 -8092
  112. package/dist/agent-verifier/local-typecheck-QFYYAZOK.mjs +0 -9
  113. package/dist/agent-verifier/reducer-contract-preflight-22X7DSZW.mjs +0 -10
  114. package/dist/agent-verifier/static-scaffold-4YEQME5N.mjs +0 -28
  115. package/dist/agent-verifier/testing-5K2BJYF2.mjs +0 -674
  116. package/dist/agent-verifier/workspace-codegen-JDZJRSDV.mjs +0 -11
  117. package/dist/chunk-3XNJT3RK.js.map +0 -1
  118. package/dist/chunk-7FOO4AJI.js +0 -50
  119. package/dist/chunk-7FOO4AJI.js.map +0 -1
  120. package/dist/chunk-TSJVWTJO.js.map +0 -1
  121. package/dist/internal.d.ts +0 -311
  122. package/dist/runtime-packages/ui-host-runtime/src/actor-principal.ts +0 -71
  123. package/dist/runtime-packages/ui-host-runtime/src/browser-interaction.ts +0 -139
  124. package/dist/runtime-packages/ui-host-runtime/src/components/host-controls.tsx +0 -374
  125. package/dist/runtime-packages/ui-host-runtime/src/components/host-feedback-toaster.tsx +0 -266
  126. package/dist/runtime-packages/ui-host-runtime/src/components/host-feedback.tsx +0 -212
  127. package/dist/runtime-packages/ui-host-runtime/src/components/host-primitives.tsx +0 -271
  128. package/dist/runtime-packages/ui-host-runtime/src/components/host-session-metadata.tsx +0 -135
  129. package/dist/runtime-packages/ui-host-runtime/src/components/index.ts +0 -5
  130. package/dist/runtime-packages/ui-host-runtime/src/components/perf-overlay.tsx +0 -194
  131. package/dist/runtime-packages/ui-host-runtime/src/gameplay-authority-transport.ts +0 -626
  132. package/dist/runtime-packages/ui-host-runtime/src/host-controls.tsx +0 -1
  133. package/dist/runtime-packages/ui-host-runtime/src/host-feedback.tsx +0 -1
  134. package/dist/runtime-packages/ui-host-runtime/src/host-session-transport.ts +0 -294
  135. package/dist/runtime-packages/ui-host-runtime/src/index.ts +0 -3
  136. package/dist/runtime-packages/ui-host-runtime/src/logger.ts +0 -11
  137. package/dist/runtime-packages/ui-host-runtime/src/perf.ts +0 -324
  138. package/dist/runtime-packages/ui-host-runtime/src/plugin-bridge.ts +0 -195
  139. package/dist/runtime-packages/ui-host-runtime/src/plugin-health-check.ts +0 -138
  140. package/dist/runtime-packages/ui-host-runtime/src/plugin-messages.ts +0 -159
  141. package/dist/runtime-packages/ui-host-runtime/src/plugin-session-gateway.ts +0 -551
  142. package/dist/runtime-packages/ui-host-runtime/src/runtime/index.ts +0 -13
  143. package/dist/runtime-packages/ui-host-runtime/src/screenshot/projection-to-snapshot.ts +0 -122
  144. package/dist/runtime-packages/ui-host-runtime/src/screenshot/static-store-api.ts +0 -26
  145. package/dist/runtime-packages/ui-host-runtime/src/session-ingress-controller.ts +0 -583
  146. package/dist/runtime-packages/ui-host-runtime/src/session-ingress.ts +0 -219
  147. package/dist/runtime-packages/ui-host-runtime/src/session-live-runtime.ts +0 -117
  148. package/dist/runtime-packages/ui-host-runtime/src/session-model.ts +0 -431
  149. package/dist/runtime-packages/ui-host-runtime/src/session-projection.ts +0 -211
  150. package/dist/runtime-packages/ui-host-runtime/src/session-recovery.ts +0 -80
  151. package/dist/runtime-packages/ui-host-runtime/src/session-state-reducer.ts +0 -1034
  152. package/dist/runtime-packages/ui-host-runtime/src/sse-manager.ts +0 -416
  153. package/dist/runtime-packages/ui-host-runtime/src/unified-session-store.ts +0 -184
  154. package/dist/testing-KLSV6CPJ.js +0 -674
  155. package/dist/testing-KLSV6CPJ.js.map +0 -1
  156. /package/dist/{global-config-UKSWNDTX.js.map → agent-verifier/chunk-H6XDQJ3N.mjs.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>;