@gamedevagents/sdk-web 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +79 -0
- package/dist/index.d.ts +67 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +254 -0
- package/dist/index.js.map +1 -0
- package/package.json +41 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 GameDevAgents
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# @gamedevagents/sdk-web
|
|
2
|
+
|
|
3
|
+
Part of **[GameDevAgents](https://gamedevagents.com)**, AI-agent + human-curated game QA.
|
|
4
|
+
· [Platform](https://gamedevagents.com) · [Docs](https://gamedevagents.com/docs) · [Other engines](https://gitlab.com/gamedevagents) (Godot, Unity, Unreal)
|
|
5
|
+
|
|
6
|
+
The browser/web integration for [GameDevAgents](https://gamedevagents.com) automated + human-assisted
|
|
7
|
+
game QA. It's a small, dependency-free bridge you drop into your web game so the QA platform can both
|
|
8
|
+
**observe** it (version, errors, crashes, custom events) and **drive** it (synthetic keyboard / mouse /
|
|
9
|
+
gamepad / touch input). QA-relevant signals you route through the SDK are judged from your game's own
|
|
10
|
+
truth instead of inferred from the outside.
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install @gamedevagents/sdk-web
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Use
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
import { GDA } from '@gamedevagents/sdk-web'
|
|
22
|
+
|
|
23
|
+
// Once, at boot. Registers global error/crash hooks and connects the input bridge.
|
|
24
|
+
await GDA.init({
|
|
25
|
+
version: '1.4.2', // the exact build under test (regression tracking keys on this)
|
|
26
|
+
titleId: 'my-game',
|
|
27
|
+
// workerEndpoint?: 'http://localhost:8787' // defaults to the local worker bridge
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
// Emit notable game state as it happens, so QA judges from your truth:
|
|
31
|
+
await GDA.emit('spin', { bet: 5, result: 'win', payout: 20 })
|
|
32
|
+
await GDA.emit('scene_change', { to: 'shop' })
|
|
33
|
+
|
|
34
|
+
// Errors/unhandled rejections are captured automatically once init() runs.
|
|
35
|
+
// For SDK validation you can force a crash event:
|
|
36
|
+
await GDA.triggerTestCrash()
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The semantic decision loop is the recommended integration (reliable, no vision guessing):
|
|
40
|
+
|
|
41
|
+
```js
|
|
42
|
+
// At every point a player would act:
|
|
43
|
+
const choice = await GDA.turn('main menu', [
|
|
44
|
+
'PLAY',
|
|
45
|
+
{ name: 'OPTIONS', label: 'Options', tags: ['passive'] },
|
|
46
|
+
])
|
|
47
|
+
executeAction(choice.name, choice.data)
|
|
48
|
+
|
|
49
|
+
// At every terminal state (round/level/game over, win or loss):
|
|
50
|
+
await GDA.over('win', { score: 9000 })
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`turn(state, actions)` advertises the game's REAL choices and resolves with the platform's pick
|
|
54
|
+
(the promise never resolves without a worker attached, gate on your QA-mode flag). `actions`
|
|
55
|
+
entries are strings or `{ name, label?, group?, data?, tags? }`; `tags` use the personality
|
|
56
|
+
vocabulary (`reckless | aggressive | tactical | passive | exploitative`) so player personalities
|
|
57
|
+
bias selection without the platform interpreting game meaning. `over(outcome)` is the
|
|
58
|
+
SDK-authoritative end-of-run signal; always pair the last `turn` with an `over`.
|
|
59
|
+
|
|
60
|
+
Full runtime surface: `init`, `turn`, `over`, `emit` (custom events), `sendEvent` (low-level), and
|
|
61
|
+
`triggerTestCrash`. Global `error`/`unhandledrejection` and a `session_start` announcement are wired by
|
|
62
|
+
`init`. The platform can also drive raw input (commands become real DOM/gamepad events) and request
|
|
63
|
+
viewport screenshots (`<canvas>` to PNG); your game needs no input-side code for either.
|
|
64
|
+
|
|
65
|
+
## Strip from shipping builds
|
|
66
|
+
|
|
67
|
+
All SDK calls should be excluded from production/release bundles (dead-code-eliminated behind a flag).
|
|
68
|
+
See [`SPEC.md`](SPEC.md) → Build config.
|
|
69
|
+
|
|
70
|
+
## Docs
|
|
71
|
+
|
|
72
|
+
- [`SPEC.md`](SPEC.md), the full SDK contract (all engines, the target API).
|
|
73
|
+
- [`ONBOARDING-KIT.md`](ONBOARDING-KIT.md), the one-shot prompt to wire the SDK + emit your
|
|
74
|
+
game profile, run from inside your game's repo.
|
|
75
|
+
- Platform docs & dashboard: **[gamedevagents.com](https://gamedevagents.com)**.
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
MIT, see [LICENSE](LICENSE).
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @gda/sdk-web, GameDevAgents web SDK.
|
|
3
|
+
*
|
|
4
|
+
* Implements the full SDK contract from sdk/SPEC.md:
|
|
5
|
+
* - Outbound: session_start, error, crash, scene_change, custom, session_end
|
|
6
|
+
* - Semantic loop: turn(state, actions) → platform choice; over(outcome) terminal
|
|
7
|
+
* - Inbound: keyboard, mouse, gamepad, touch injection; game (semantic) actions;
|
|
8
|
+
* capture (viewport PNG → /frame)
|
|
9
|
+
*/
|
|
10
|
+
export interface GDAConfig {
|
|
11
|
+
version: string;
|
|
12
|
+
titleId: string;
|
|
13
|
+
workerEndpoint?: string;
|
|
14
|
+
}
|
|
15
|
+
/** An action the game advertises at a decision point (see `turn`). A bare string is
|
|
16
|
+
* shorthand for `{ name }`. `tags` carry the personality vocabulary (reckless | aggressive |
|
|
17
|
+
* tactical | passive | exploitative), GDA matches them to the active player personality;
|
|
18
|
+
* it never interprets game meaning. */
|
|
19
|
+
export interface GDAAction {
|
|
20
|
+
name: string;
|
|
21
|
+
label?: string;
|
|
22
|
+
group?: string;
|
|
23
|
+
data?: Record<string, unknown>;
|
|
24
|
+
tags?: string[];
|
|
25
|
+
}
|
|
26
|
+
/** The platform's pick for a `turn()`, the advertised action name, plus any args. */
|
|
27
|
+
export interface GDAChoice {
|
|
28
|
+
name: string;
|
|
29
|
+
data?: Record<string, unknown>;
|
|
30
|
+
}
|
|
31
|
+
declare class GDAClient {
|
|
32
|
+
private endpoint;
|
|
33
|
+
private version;
|
|
34
|
+
private titleId;
|
|
35
|
+
private gamepadState;
|
|
36
|
+
private pendingTurn;
|
|
37
|
+
init(config: GDAConfig): Promise<void>;
|
|
38
|
+
sendEvent(type: string, data?: Record<string, unknown>): Promise<void>;
|
|
39
|
+
/** Emit a custom game event (spin, result, scene_change, etc.) */
|
|
40
|
+
emit(name: string, data?: Record<string, unknown>): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Advertise a decision point and wait for the platform's choice.
|
|
43
|
+
*
|
|
44
|
+
* Call at EVERY point a player would act, menu, level select, in-game turn. `state` is a
|
|
45
|
+
* short natural-language summary (or a structured object) of what the player sees; `actions`
|
|
46
|
+
* are the choices the game will accept right now. Resolves with the platform's pick; the game
|
|
47
|
+
* then executes it exactly as if the player chose it.
|
|
48
|
+
*
|
|
49
|
+
* Without a worker attached (normal dev), the returned promise simply never resolves, * gate the call on your own "QA mode" flag, or race it against real player input.
|
|
50
|
+
*/
|
|
51
|
+
turn(state: string | Record<string, unknown>, actions: Array<string | GDAAction>): Promise<GDAChoice>;
|
|
52
|
+
/**
|
|
53
|
+
* Declare a terminal state, round/level/game over, win or loss. This is the
|
|
54
|
+
* SDK-authoritative end-of-run signal: the platform closes the session on it instead of
|
|
55
|
+
* guessing from silence. Always pair the last `turn()` with an `over()`.
|
|
56
|
+
*/
|
|
57
|
+
over(outcome: string, data?: Record<string, unknown>): Promise<void>;
|
|
58
|
+
/** Trigger a test crash (for SDK validation). */
|
|
59
|
+
triggerTestCrash(): Promise<void>;
|
|
60
|
+
private startInputListener;
|
|
61
|
+
private executeInput;
|
|
62
|
+
/** Grab the game canvas as a PNG and post it to the worker's /frame endpoint. */
|
|
63
|
+
private postFrame;
|
|
64
|
+
}
|
|
65
|
+
export declare const GDA: GDAClient;
|
|
66
|
+
export {};
|
|
67
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;wCAGwC;AACxC,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,qFAAqF;AACrF,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAqBD,cAAM,SAAS;IACb,OAAO,CAAC,QAAQ,CAAoB;IACpC,OAAO,CAAC,OAAO,CAAM;IACrB,OAAO,CAAC,OAAO,CAAM;IACrB,OAAO,CAAC,YAAY,CAAoC;IACxD,OAAO,CAAC,WAAW,CAAgF;IAE7F,IAAI,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BtC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYhF,kEAAkE;IAC5D,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3E;;;;;;;;;OASG;IACG,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC;IAiB3G;;;;OAIG;IACG,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ9E,iDAAiD;IAC3C,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAQvC,OAAO,CAAC,kBAAkB;YAmBZ,YAAY;IAkC1B,iFAAiF;YACnE,SAAS;CAiBxB;AA2FD,eAAO,MAAM,GAAG,WAAkB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @gda/sdk-web, GameDevAgents web SDK.
|
|
3
|
+
*
|
|
4
|
+
* Implements the full SDK contract from sdk/SPEC.md:
|
|
5
|
+
* - Outbound: session_start, error, crash, scene_change, custom, session_end
|
|
6
|
+
* - Semantic loop: turn(state, actions) → platform choice; over(outcome) terminal
|
|
7
|
+
* - Inbound: keyboard, mouse, gamepad, touch injection; game (semantic) actions;
|
|
8
|
+
* capture (viewport PNG → /frame)
|
|
9
|
+
*/
|
|
10
|
+
const DEFAULT_ENDPOINT = 'http://127.0.0.1:7373';
|
|
11
|
+
class GDAClient {
|
|
12
|
+
endpoint = DEFAULT_ENDPOINT;
|
|
13
|
+
version = '';
|
|
14
|
+
titleId = '';
|
|
15
|
+
gamepadState = makeGamepadState();
|
|
16
|
+
pendingTurn = null;
|
|
17
|
+
async init(config) {
|
|
18
|
+
this.endpoint = config.workerEndpoint ?? DEFAULT_ENDPOINT;
|
|
19
|
+
this.version = config.version;
|
|
20
|
+
this.titleId = config.titleId;
|
|
21
|
+
// Hook global error handlers
|
|
22
|
+
window.onerror = (message, _source, _line, _col, error) => {
|
|
23
|
+
this.sendEvent('error', { message: String(message), stack: error?.stack });
|
|
24
|
+
};
|
|
25
|
+
window.onunhandledrejection = (event) => {
|
|
26
|
+
this.sendEvent('error', { message: String(event.reason), stack: event.reason?.stack });
|
|
27
|
+
};
|
|
28
|
+
// Install gamepad shim
|
|
29
|
+
installGamepadShim(this.gamepadState);
|
|
30
|
+
// Start input command listener
|
|
31
|
+
this.startInputListener();
|
|
32
|
+
// Announce session
|
|
33
|
+
await this.sendEvent('session_start', {
|
|
34
|
+
version: this.version,
|
|
35
|
+
titleId: this.titleId,
|
|
36
|
+
platform: 'web',
|
|
37
|
+
engine: 'browser',
|
|
38
|
+
});
|
|
39
|
+
console.log(`[GDA] Initialised, v${this.version} title:${this.titleId}`);
|
|
40
|
+
}
|
|
41
|
+
async sendEvent(type, data = {}) {
|
|
42
|
+
try {
|
|
43
|
+
await fetch(`${this.endpoint}/event`, {
|
|
44
|
+
method: 'POST',
|
|
45
|
+
headers: { 'Content-Type': 'application/json' },
|
|
46
|
+
body: JSON.stringify({ type, ...data, ts: Date.now() }),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// Worker not connected, silently suppress (normal during dev without worker)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/** Emit a custom game event (spin, result, scene_change, etc.) */
|
|
54
|
+
async emit(name, data = {}) {
|
|
55
|
+
await this.sendEvent('custom', { name, data });
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Advertise a decision point and wait for the platform's choice.
|
|
59
|
+
*
|
|
60
|
+
* Call at EVERY point a player would act, menu, level select, in-game turn. `state` is a
|
|
61
|
+
* short natural-language summary (or a structured object) of what the player sees; `actions`
|
|
62
|
+
* are the choices the game will accept right now. Resolves with the platform's pick; the game
|
|
63
|
+
* then executes it exactly as if the player chose it.
|
|
64
|
+
*
|
|
65
|
+
* Without a worker attached (normal dev), the returned promise simply never resolves, * gate the call on your own "QA mode" flag, or race it against real player input.
|
|
66
|
+
*/
|
|
67
|
+
async turn(state, actions) {
|
|
68
|
+
if (this.pendingTurn) {
|
|
69
|
+
// A new decision point supersedes the previous one (e.g. the scene changed under it).
|
|
70
|
+
this.pendingTurn.reject(new Error('superseded by a newer turn()'));
|
|
71
|
+
this.pendingTurn = null;
|
|
72
|
+
}
|
|
73
|
+
const allowed = actions.map((a) => (typeof a === 'string' ? { name: a } : a));
|
|
74
|
+
const promise = new Promise((resolve, reject) => {
|
|
75
|
+
this.pendingTurn = { resolve, reject };
|
|
76
|
+
});
|
|
77
|
+
await this.emit('user_action_required', {
|
|
78
|
+
state: typeof state === 'string' ? { summary: state } : state,
|
|
79
|
+
allowed_actions: allowed,
|
|
80
|
+
});
|
|
81
|
+
return promise;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Declare a terminal state, round/level/game over, win or loss. This is the
|
|
85
|
+
* SDK-authoritative end-of-run signal: the platform closes the session on it instead of
|
|
86
|
+
* guessing from silence. Always pair the last `turn()` with an `over()`.
|
|
87
|
+
*/
|
|
88
|
+
async over(outcome, data = {}) {
|
|
89
|
+
if (this.pendingTurn) {
|
|
90
|
+
this.pendingTurn.reject(new Error(`run ended (${outcome}) with a turn still pending`));
|
|
91
|
+
this.pendingTurn = null;
|
|
92
|
+
}
|
|
93
|
+
await this.emit('game_terminal', { outcome, ...data });
|
|
94
|
+
}
|
|
95
|
+
/** Trigger a test crash (for SDK validation). */
|
|
96
|
+
async triggerTestCrash() {
|
|
97
|
+
await this.sendEvent('crash', {
|
|
98
|
+
message: 'Test crash triggered via GDA.triggerTestCrash()',
|
|
99
|
+
stack: new Error().stack,
|
|
100
|
+
context: 'test',
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
startInputListener() {
|
|
104
|
+
// Poll for input commands from the worker.
|
|
105
|
+
// In v2 this becomes a WebSocket. For now we poll /input/next.
|
|
106
|
+
const poll = async () => {
|
|
107
|
+
try {
|
|
108
|
+
const resp = await fetch(`${this.endpoint}/input/next`, { method: 'GET' });
|
|
109
|
+
if (resp.ok) {
|
|
110
|
+
const cmd = await resp.json();
|
|
111
|
+
await this.executeInput(cmd);
|
|
112
|
+
await fetch(`${this.endpoint}/input/ack`, { method: 'POST' });
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
// Worker not connected
|
|
117
|
+
}
|
|
118
|
+
setTimeout(poll, 16); // ~60fps polling
|
|
119
|
+
};
|
|
120
|
+
poll();
|
|
121
|
+
}
|
|
122
|
+
async executeInput(cmd) {
|
|
123
|
+
switch (cmd.device) {
|
|
124
|
+
case 'keyboard':
|
|
125
|
+
dispatchKeyboardEvent(cmd);
|
|
126
|
+
break;
|
|
127
|
+
case 'mouse':
|
|
128
|
+
dispatchMouseEvent(cmd);
|
|
129
|
+
break;
|
|
130
|
+
case 'gamepad':
|
|
131
|
+
updateGamepad(this.gamepadState, cmd);
|
|
132
|
+
break;
|
|
133
|
+
case 'touch':
|
|
134
|
+
dispatchTouchEvent(cmd);
|
|
135
|
+
break;
|
|
136
|
+
case 'game': {
|
|
137
|
+
// Semantic action, resolves the pending turn(). A choice with no turn waiting is
|
|
138
|
+
// dropped loudly rather than buffered: replaying a stale choice into a NEW decision
|
|
139
|
+
// point would be worse than missing one.
|
|
140
|
+
const choice = { name: cmd.name ?? '', ...(cmd.data ? { data: cmd.data } : {}) };
|
|
141
|
+
if (this.pendingTurn) {
|
|
142
|
+
const t = this.pendingTurn;
|
|
143
|
+
this.pendingTurn = null;
|
|
144
|
+
t.resolve(choice);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
console.warn(`[GDA] game action "${choice.name}" arrived with no turn() pending, dropped`);
|
|
148
|
+
}
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
case 'capture':
|
|
152
|
+
await this.postFrame(cmd.requestId ?? '');
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/** Grab the game canvas as a PNG and post it to the worker's /frame endpoint. */
|
|
157
|
+
async postFrame(requestId) {
|
|
158
|
+
try {
|
|
159
|
+
const canvas = document.querySelector('canvas');
|
|
160
|
+
if (!canvas)
|
|
161
|
+
throw new Error('no <canvas> found');
|
|
162
|
+
const dataUrl = canvas.toDataURL('image/png');
|
|
163
|
+
const png_base64 = dataUrl.slice(dataUrl.indexOf(',') + 1);
|
|
164
|
+
await fetch(`${this.endpoint}/frame`, {
|
|
165
|
+
method: 'POST',
|
|
166
|
+
headers: { 'Content-Type': 'application/json' },
|
|
167
|
+
body: JSON.stringify({ requestId, png_base64 }),
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
catch (err) {
|
|
171
|
+
// Best-effort: an uncapturable frame must not break the game loop; the worker's
|
|
172
|
+
// captureFrame() times out and the integration test marks the check warn.
|
|
173
|
+
console.warn(`[GDA] frame capture failed: ${err.message}`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// ── Input injection ────────────────────────────────────────────────────────
|
|
178
|
+
function dispatchKeyboardEvent(cmd) {
|
|
179
|
+
const type = cmd.action === 'press' ? 'keydown' : 'keyup';
|
|
180
|
+
document.dispatchEvent(new KeyboardEvent(type, {
|
|
181
|
+
code: cmd.key ?? '',
|
|
182
|
+
key: cmd.key ?? '',
|
|
183
|
+
bubbles: true,
|
|
184
|
+
cancelable: true,
|
|
185
|
+
}));
|
|
186
|
+
}
|
|
187
|
+
function dispatchMouseEvent(cmd) {
|
|
188
|
+
const canvas = document.querySelector('canvas');
|
|
189
|
+
const rect = canvas?.getBoundingClientRect();
|
|
190
|
+
const clientX = rect ? rect.left + (cmd.x ?? 0) * rect.width : (cmd.x ?? 0) * window.innerWidth;
|
|
191
|
+
const clientY = rect ? rect.top + (cmd.y ?? 0) * rect.height : (cmd.y ?? 0) * window.innerHeight;
|
|
192
|
+
const typeMap = {
|
|
193
|
+
press: 'mousedown',
|
|
194
|
+
release: 'mouseup',
|
|
195
|
+
move: 'mousemove',
|
|
196
|
+
tap: 'click',
|
|
197
|
+
};
|
|
198
|
+
const type = typeMap[cmd.action ?? ''] ?? 'mousemove';
|
|
199
|
+
document.dispatchEvent(new MouseEvent(type, { clientX, clientY, bubbles: true, cancelable: true }));
|
|
200
|
+
}
|
|
201
|
+
function dispatchTouchEvent(cmd) {
|
|
202
|
+
const canvas = document.querySelector('canvas');
|
|
203
|
+
const rect = canvas?.getBoundingClientRect();
|
|
204
|
+
const clientX = rect ? rect.left + (cmd.x ?? 0) * rect.width : (cmd.x ?? 0) * window.innerWidth;
|
|
205
|
+
const clientY = rect ? rect.top + (cmd.y ?? 0) * rect.height : (cmd.y ?? 0) * window.innerHeight;
|
|
206
|
+
const typeMap = {
|
|
207
|
+
press: 'touchstart', tap: 'touchstart', release: 'touchend', move: 'touchmove',
|
|
208
|
+
};
|
|
209
|
+
const touch = new Touch({ identifier: 0, target: document.body, clientX, clientY });
|
|
210
|
+
document.dispatchEvent(new TouchEvent(typeMap[cmd.action ?? ''] ?? 'touchstart', {
|
|
211
|
+
touches: [touch], changedTouches: [touch], bubbles: true,
|
|
212
|
+
}));
|
|
213
|
+
}
|
|
214
|
+
function makeGamepadState() {
|
|
215
|
+
return { connected: false, buttons: new Array(17).fill(0), axes: new Array(4).fill(0) };
|
|
216
|
+
}
|
|
217
|
+
function installGamepadShim(state) {
|
|
218
|
+
const original = typeof navigator.getGamepads === 'function'
|
|
219
|
+
? navigator.getGamepads.bind(navigator)
|
|
220
|
+
: () => [null, null, null, null];
|
|
221
|
+
Object.defineProperty(navigator, 'getGamepads', {
|
|
222
|
+
value: () => {
|
|
223
|
+
if (!state.connected)
|
|
224
|
+
return original();
|
|
225
|
+
// Cast needed: lib.dom's Gamepad requires a non-null vibrationActuator,
|
|
226
|
+
// but real browsers return null when the pad has no rumble support.
|
|
227
|
+
const gp = {
|
|
228
|
+
id: 'GDA Virtual Gamepad', index: 0, connected: true,
|
|
229
|
+
timestamp: performance.now(), mapping: 'standard',
|
|
230
|
+
axes: [...state.axes],
|
|
231
|
+
buttons: state.buttons.map(v => ({ pressed: v > 0.5, touched: v > 0, value: v })),
|
|
232
|
+
hapticActuators: [], vibrationActuator: null,
|
|
233
|
+
};
|
|
234
|
+
return [gp, null, null, null];
|
|
235
|
+
},
|
|
236
|
+
configurable: true,
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
function updateGamepad(state, cmd) {
|
|
240
|
+
if (!state.connected) {
|
|
241
|
+
state.connected = true;
|
|
242
|
+
window.dispatchEvent(new GamepadEvent('gamepadconnected', {
|
|
243
|
+
gamepad: navigator.getGamepads()[0],
|
|
244
|
+
}));
|
|
245
|
+
}
|
|
246
|
+
if (cmd.action === 'press' && cmd.button !== undefined)
|
|
247
|
+
state.buttons[cmd.button] = 1;
|
|
248
|
+
if (cmd.action === 'release' && cmd.button !== undefined)
|
|
249
|
+
state.buttons[cmd.button] = 0;
|
|
250
|
+
if (cmd.action === 'axis' && cmd.axis !== undefined)
|
|
251
|
+
state.axes[cmd.axis] = cmd.value ?? 0;
|
|
252
|
+
}
|
|
253
|
+
export const GDA = new GDAClient();
|
|
254
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@gamedevagents/sdk-web",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "GameDevAgents web SDK, event reporting + input injection bridge for browser games",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"homepage": "https://gamedevagents.com",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "https://gitlab.com/gamedevagents/sdk-web.git"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"gamedevagents",
|
|
19
|
+
"game-qa",
|
|
20
|
+
"qa",
|
|
21
|
+
"testing",
|
|
22
|
+
"automation",
|
|
23
|
+
"sdk",
|
|
24
|
+
"game"
|
|
25
|
+
],
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsc",
|
|
31
|
+
"test": "vitest run",
|
|
32
|
+
"test:watch": "vitest",
|
|
33
|
+
"prepare": "npm run build",
|
|
34
|
+
"prepublishOnly": "npm run build"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"happy-dom": "^14.0.0",
|
|
38
|
+
"typescript": "^5.3.0",
|
|
39
|
+
"vitest": "^1.6.0"
|
|
40
|
+
}
|
|
41
|
+
}
|