@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.
- package/README.md +179 -22
- package/dist/agent-verifier/agent-workspace-verifier.mjs +30 -30
- package/dist/agent-verifier/agent-workspace-verifier.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-JH22JNYD.mjs → chunk-3UKQVWLV.mjs} +82 -19
- package/dist/agent-verifier/chunk-3UKQVWLV.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-4WD3YU2E.mjs → chunk-776W3UGV.mjs} +4 -3
- package/dist/agent-verifier/chunk-776W3UGV.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-CJEEA6NJ.mjs → chunk-7WWGFAAU.mjs} +9 -10
- package/dist/agent-verifier/chunk-7WWGFAAU.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-2SZHMP6F.mjs → chunk-A64ZZUZV.mjs} +6 -9
- package/dist/agent-verifier/chunk-A64ZZUZV.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-6A5HRJMQ.mjs → chunk-E7SSWJXJ.mjs} +62 -99
- package/dist/agent-verifier/chunk-E7SSWJXJ.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-2GBBP27W.mjs → chunk-F2DIOJJZ.mjs} +1 -0
- package/dist/agent-verifier/chunk-F2DIOJJZ.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-CFU5EWIC.mjs → chunk-G42BGGG2.mjs} +7 -6
- package/dist/agent-verifier/chunk-G42BGGG2.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-SHUMAVAP.mjs → chunk-H76MT5UR.mjs} +7 -9
- package/dist/agent-verifier/chunk-H76MT5UR.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-7E65UQLY.mjs → chunk-HGMUAL33.mjs} +3 -2
- package/dist/agent-verifier/chunk-HGMUAL33.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-LM3OZLZG.mjs → chunk-IAYRNVUC.mjs} +1 -0
- package/dist/agent-verifier/chunk-IAYRNVUC.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-VYJTHSYR.mjs → chunk-JGT4P4UD.mjs} +2 -1
- package/dist/agent-verifier/chunk-JGT4P4UD.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-CEDUHGNH.mjs → chunk-LUZ7KE6H.mjs} +8 -3
- package/dist/agent-verifier/chunk-LUZ7KE6H.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-2E5P5NWG.mjs → chunk-NAK77WXW.mjs} +58 -126
- package/dist/agent-verifier/chunk-NAK77WXW.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-SYPLYRGB.mjs → chunk-O4YCPU7C.mjs} +116 -15
- package/dist/agent-verifier/chunk-O4YCPU7C.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-BVVNBJM4.mjs → chunk-S34FRJHS.mjs} +2 -1
- package/dist/agent-verifier/chunk-S34FRJHS.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-HJFQDSTU.mjs → chunk-SH5JKYOB.mjs} +6 -5
- package/dist/agent-verifier/chunk-SH5JKYOB.mjs.map +1 -0
- package/dist/agent-verifier/chunk-SKI2ESE5.mjs +44 -0
- package/dist/agent-verifier/{chunk-MINCYHXN.mjs → chunk-TAEQKBJB.mjs} +1 -0
- package/dist/agent-verifier/chunk-TAEQKBJB.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-CEQ2VJWN.mjs → chunk-UIOLGH4A.mjs} +2 -1
- package/dist/agent-verifier/chunk-UIOLGH4A.mjs.map +1 -0
- package/dist/agent-verifier/chunk-UIZNWRM6.mjs +2432 -0
- package/dist/agent-verifier/chunk-UIZNWRM6.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-2QMNAVV4.mjs → chunk-VS573ERH.mjs} +2 -1
- package/dist/agent-verifier/chunk-VS573ERH.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-EOQIV6PS.mjs → chunk-W3N3QJ4V.mjs} +75 -100
- package/dist/agent-verifier/chunk-W3N3QJ4V.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-EIQWDQWJ.mjs → chunk-XGWCY624.mjs} +11 -12
- package/dist/agent-verifier/chunk-XGWCY624.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-7653FPGJ.mjs → chunk-XQXDOBYB.mjs} +3 -2
- package/dist/agent-verifier/chunk-XQXDOBYB.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-MRCUP5SW.mjs → chunk-YE7UAO3T.mjs} +1 -0
- package/dist/agent-verifier/chunk-YE7UAO3T.mjs.map +1 -0
- package/dist/agent-verifier/{chunk-RBDDIIPM.mjs → chunk-ZEELHSY3.mjs} +1 -0
- package/dist/agent-verifier/chunk-ZEELHSY3.mjs.map +1 -0
- package/dist/agent-verifier/{compile-5QSPIOUT.mjs → compile-TEQVA46V.mjs} +24 -25
- package/dist/agent-verifier/compile-TEQVA46V.mjs.map +1 -0
- package/dist/agent-verifier/{global-config-WX3ZZIVU.mjs → global-config-Y2NTSK4R.mjs} +6 -5
- package/dist/{keychain-backend-JHTXAKWC.js → agent-verifier/keychain-backend-SPQWGKZN.mjs} +2 -2
- package/dist/agent-verifier/keychain-backend-SPQWGKZN.mjs.map +1 -0
- package/dist/agent-verifier/{local-files-MTPLP62S.mjs → local-files-JFOQQZDL.mjs} +10 -11
- package/dist/agent-verifier/local-files-JFOQQZDL.mjs.map +1 -0
- package/dist/agent-verifier/local-typecheck-XVGWI75X.mjs +10 -0
- package/dist/agent-verifier/local-typecheck-XVGWI75X.mjs.map +1 -0
- package/dist/agent-verifier/{materialize-workspace-FKALAE2T.mjs → materialize-workspace-ZAVGQQSF.mjs} +17 -18
- package/dist/agent-verifier/materialize-workspace-ZAVGQQSF.mjs.map +1 -0
- package/dist/agent-verifier/{project-state-7GR6BQTQ.mjs → project-state-K576C2TE.mjs} +3 -2
- package/dist/agent-verifier/project-state-K576C2TE.mjs.map +1 -0
- package/dist/{prompt-GMZABCJC.js → agent-verifier/prompt-MJRJMOGQ.mjs} +2 -2
- package/dist/agent-verifier/prompt-MJRJMOGQ.mjs.map +1 -0
- package/dist/agent-verifier/{reducer-bundle-preflight-C73LEXI2.mjs → reducer-bundle-preflight-LXNJUBKL.mjs} +6 -9
- package/dist/agent-verifier/reducer-bundle-preflight-LXNJUBKL.mjs.map +1 -0
- package/dist/agent-verifier/reducer-contract-preflight-TUMQ43JV.mjs +11 -0
- package/dist/agent-verifier/reducer-contract-preflight-TUMQ43JV.mjs.map +1 -0
- package/dist/agent-verifier/{reducer-native-test-harness-GMWBUISX.mjs → reducer-native-test-harness-CHX5MBL5.mjs} +14 -17
- package/dist/agent-verifier/reducer-native-test-harness-CHX5MBL5.mjs.map +1 -0
- package/dist/agent-verifier/static-scaffold-R7SVDRQI.mjs +27 -0
- package/dist/agent-verifier/static-scaffold-R7SVDRQI.mjs.map +1 -0
- package/dist/agent-verifier/{sync-3DUQH32H.mjs → sync-THAI546U.mjs} +31 -37
- package/dist/agent-verifier/sync-THAI546U.mjs.map +1 -0
- package/dist/agent-verifier/{test-P4U5INTD.mjs → test-AFAQFKOB.mjs} +28 -31
- package/dist/agent-verifier/test-AFAQFKOB.mjs.map +1 -0
- package/dist/agent-verifier/workspace-codegen-2ZMQRIKJ.mjs +10 -0
- package/dist/agent-verifier/workspace-codegen-2ZMQRIKJ.mjs.map +1 -0
- package/dist/agent-verifier/{workspace-dependencies-HZ6VVS4G.mjs → workspace-dependencies-NOOQBK6I.mjs} +5 -4
- package/dist/agent-verifier/workspace-dependencies-NOOQBK6I.mjs.map +1 -0
- package/dist/{chunk-C6UAT6EH.js → chunk-N7XPNNUI.js} +9 -12
- package/dist/chunk-N7XPNNUI.js.map +1 -0
- package/dist/chunk-SEGVTWSK.js +44 -0
- package/dist/chunk-SEGVTWSK.js.map +1 -0
- package/dist/{chunk-RS7UXJZV.js → chunk-TAQKH67O.js} +21300 -35881
- package/dist/chunk-TAQKH67O.js.map +1 -0
- package/dist/{global-config-AGFBDFYD.js → global-config-S4ZIPECE.js} +3 -3
- package/dist/global-config-S4ZIPECE.js.map +1 -0
- package/dist/index.js +415 -37
- package/dist/index.js.map +1 -1
- package/dist/internal.js +3 -4
- package/dist/{agent-verifier/keychain-backend-TNOPQV3Z.mjs → keychain-backend-HDF4TZDL.js} +2 -1
- package/dist/{agent-verifier/prompt-3BAINGAQ.mjs → prompt-NDV3AE5L.js} +2 -1
- package/package.json +8 -7
- package/skills/dreamboard/references/building-your-first-game.md +510 -0
- package/skills/dreamboard/references/cli.md +104 -0
- package/skills/dreamboard/references/game-interface.md +548 -0
- package/skills/dreamboard/references/manifest-authoring.md +597 -0
- package/skills/dreamboard/references/quickstart.md +66 -0
- package/skills/dreamboard/references/reducer.md +864 -0
- package/skills/dreamboard/references/rule-authoring.md +147 -0
- package/skills/dreamboard/references/testing.md +249 -0
- package/skills/dreamboard/scripts/events-extract.mjs +218 -0
- package/dist/agent-verifier/chunk-54TAYXUD.mjs +0 -12
- package/dist/agent-verifier/chunk-6UUJEYDV.mjs +0 -213
- package/dist/agent-verifier/chunk-HBNDKQT5.mjs +0 -8381
- package/dist/agent-verifier/chunk-LI3ZR3BI.mjs +0 -41
- package/dist/agent-verifier/chunk-U6OJN7XS.mjs +0 -8092
- package/dist/agent-verifier/chunk-XYDL7GY6.mjs +0 -10
- package/dist/agent-verifier/local-typecheck-QFYYAZOK.mjs +0 -9
- package/dist/agent-verifier/reducer-contract-preflight-22X7DSZW.mjs +0 -10
- package/dist/agent-verifier/static-scaffold-AJMZZQWS.mjs +0 -28
- package/dist/agent-verifier/testing-5K2BJYF2.mjs +0 -674
- package/dist/agent-verifier/workspace-codegen-JDZJRSDV.mjs +0 -11
- package/dist/chunk-2H7UOFLK.js +0 -11
- package/dist/chunk-7FOO4AJI.js +0 -50
- package/dist/chunk-7FOO4AJI.js.map +0 -1
- package/dist/chunk-C6UAT6EH.js.map +0 -1
- package/dist/chunk-RS7UXJZV.js.map +0 -1
- package/dist/internal.d.ts +0 -311
- package/dist/runtime-packages/ui-host-runtime/src/actor-principal.ts +0 -71
- package/dist/runtime-packages/ui-host-runtime/src/browser-interaction.ts +0 -139
- package/dist/runtime-packages/ui-host-runtime/src/components/host-controls.tsx +0 -374
- package/dist/runtime-packages/ui-host-runtime/src/components/host-feedback-toaster.tsx +0 -266
- package/dist/runtime-packages/ui-host-runtime/src/components/host-feedback.tsx +0 -212
- package/dist/runtime-packages/ui-host-runtime/src/components/host-primitives.tsx +0 -271
- package/dist/runtime-packages/ui-host-runtime/src/components/host-session-metadata.tsx +0 -135
- package/dist/runtime-packages/ui-host-runtime/src/components/index.ts +0 -5
- package/dist/runtime-packages/ui-host-runtime/src/components/perf-overlay.tsx +0 -194
- package/dist/runtime-packages/ui-host-runtime/src/gameplay-authority-transport.ts +0 -626
- package/dist/runtime-packages/ui-host-runtime/src/host-controls.tsx +0 -1
- package/dist/runtime-packages/ui-host-runtime/src/host-feedback.tsx +0 -1
- package/dist/runtime-packages/ui-host-runtime/src/host-session-transport.ts +0 -294
- package/dist/runtime-packages/ui-host-runtime/src/index.ts +0 -3
- package/dist/runtime-packages/ui-host-runtime/src/logger.ts +0 -11
- package/dist/runtime-packages/ui-host-runtime/src/perf.ts +0 -324
- package/dist/runtime-packages/ui-host-runtime/src/plugin-bridge.ts +0 -195
- package/dist/runtime-packages/ui-host-runtime/src/plugin-health-check.ts +0 -138
- package/dist/runtime-packages/ui-host-runtime/src/plugin-messages.ts +0 -159
- package/dist/runtime-packages/ui-host-runtime/src/plugin-session-gateway.ts +0 -551
- package/dist/runtime-packages/ui-host-runtime/src/runtime/index.ts +0 -13
- package/dist/runtime-packages/ui-host-runtime/src/screenshot/projection-to-snapshot.ts +0 -122
- package/dist/runtime-packages/ui-host-runtime/src/screenshot/static-store-api.ts +0 -26
- package/dist/runtime-packages/ui-host-runtime/src/session-ingress-controller.ts +0 -583
- package/dist/runtime-packages/ui-host-runtime/src/session-ingress.ts +0 -219
- package/dist/runtime-packages/ui-host-runtime/src/session-live-runtime.ts +0 -117
- package/dist/runtime-packages/ui-host-runtime/src/session-model.ts +0 -431
- package/dist/runtime-packages/ui-host-runtime/src/session-projection.ts +0 -211
- package/dist/runtime-packages/ui-host-runtime/src/session-recovery.ts +0 -80
- package/dist/runtime-packages/ui-host-runtime/src/session-state-reducer.ts +0 -1034
- package/dist/runtime-packages/ui-host-runtime/src/sse-manager.ts +0 -416
- package/dist/runtime-packages/ui-host-runtime/src/unified-session-store.ts +0 -184
- package/dist/testing-KLSV6CPJ.js +0 -674
- package/dist/testing-KLSV6CPJ.js.map +0 -1
- /package/dist/{chunk-2H7UOFLK.js.map → agent-verifier/chunk-SKI2ESE5.mjs.map} +0 -0
- /package/dist/{global-config-AGFBDFYD.js.map → agent-verifier/global-config-Y2NTSK4R.mjs.map} +0 -0
- /package/dist/{keychain-backend-JHTXAKWC.js.map → keychain-backend-HDF4TZDL.js.map} +0 -0
- /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>;
|