@satelliteoflove/godot-mcp 3.12.0 → 3.13.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.
Files changed (33) hide show
  1. package/addon/commands/game_time_commands.gd +14 -6
  2. package/addon/commands/input_commands.gd +38 -21
  3. package/addon/game_bridge/mcp_game_bridge.gd +22 -12
  4. package/addon/plugin.cfg +1 -1
  5. package/dist/__tests__/connection/timeouts.test.d.ts +2 -0
  6. package/dist/__tests__/connection/timeouts.test.d.ts.map +1 -0
  7. package/dist/__tests__/connection/timeouts.test.js +58 -0
  8. package/dist/__tests__/connection/timeouts.test.js.map +1 -0
  9. package/dist/__tests__/connection/websocket.test.js +58 -0
  10. package/dist/__tests__/connection/websocket.test.js.map +1 -1
  11. package/dist/__tests__/helpers/mock-godot.d.ts +3 -0
  12. package/dist/__tests__/helpers/mock-godot.d.ts.map +1 -1
  13. package/dist/__tests__/helpers/mock-godot.js +2 -2
  14. package/dist/__tests__/helpers/mock-godot.js.map +1 -1
  15. package/dist/__tests__/tools/game-time.test.js +45 -5
  16. package/dist/__tests__/tools/game-time.test.js.map +1 -1
  17. package/dist/__tests__/tools/input.test.js +42 -0
  18. package/dist/__tests__/tools/input.test.js.map +1 -1
  19. package/dist/connection/timeouts.d.ts +47 -0
  20. package/dist/connection/timeouts.d.ts.map +1 -0
  21. package/dist/connection/timeouts.js +72 -0
  22. package/dist/connection/timeouts.js.map +1 -0
  23. package/dist/connection/websocket.d.ts +3 -1
  24. package/dist/connection/websocket.d.ts.map +1 -1
  25. package/dist/connection/websocket.js +8 -4
  26. package/dist/connection/websocket.js.map +1 -1
  27. package/dist/tools/game-time.d.ts.map +1 -1
  28. package/dist/tools/game-time.js +33 -8
  29. package/dist/tools/game-time.js.map +1 -1
  30. package/dist/tools/input.d.ts.map +1 -1
  31. package/dist/tools/input.js +31 -3
  32. package/dist/tools/input.js.map +1 -1
  33. package/package.json +1 -1
@@ -4,10 +4,11 @@ class_name MCPGameTimeCommands
4
4
 
5
5
  # Game-time control relay: freeze / step / step_until / thaw / status execute in
6
6
  # the game bridge (see mcp_game_bridge.gd); this side only forwards over the
7
- # debugger channel and waits. Timeout cascade: a step/step_until request is
8
- # capped at 20s of game time and the bridge's wall budget returns by 25s, so the
9
- # 28s relay timeout below fires only if the bridge is gone and stays under the
10
- # server's 30s command timeout so errors surface typed instead of generic.
7
+ # debugger channel and waits. Timeout cascade (#276): the server derives the
8
+ # whole stagger from the call's in-game budget and pushes relay_timeout_ms down
9
+ # in params; we wait exactly that long, so the bridge (which returns by its
10
+ # pushed wall budget) answers first and errors surface typed. BASE_TIMEOUT and
11
+ # STEP_TIMEOUT are fallbacks only — for an older server that pushes no budget.
11
12
  const BASE_TIMEOUT := 10.0
12
13
  const STEP_TIMEOUT := 28.0
13
14
 
@@ -29,11 +30,11 @@ func game_time_freeze(params: Dictionary) -> Dictionary:
29
30
 
30
31
 
31
32
  func game_time_step(params: Dictionary) -> Dictionary:
32
- return await _relay("game_time_step", [params], STEP_TIMEOUT)
33
+ return await _relay("game_time_step", [params], _relay_timeout(params, STEP_TIMEOUT))
33
34
 
34
35
 
35
36
  func game_time_step_until(params: Dictionary) -> Dictionary:
36
- return await _relay("game_time_step_until", [params], STEP_TIMEOUT)
37
+ return await _relay("game_time_step_until", [params], _relay_timeout(params, STEP_TIMEOUT))
37
38
 
38
39
 
39
40
  func game_time_thaw(params: Dictionary) -> Dictionary:
@@ -44,6 +45,13 @@ func game_time_status(params: Dictionary) -> Dictionary:
44
45
  return await _relay("game_time_status", [params], BASE_TIMEOUT)
45
46
 
46
47
 
48
+ func _relay_timeout(params: Dictionary, fallback: float) -> float:
49
+ # Use the server-pushed relay budget when present (#276); the local constant
50
+ # is only a fallback for an older server that does not derive the cascade.
51
+ var ms: float = float(params.get("relay_timeout_ms", fallback * 1000.0))
52
+ return ms / 1000.0
53
+
54
+
47
55
  func _relay(msg_type: String, args: Array, timeout: float) -> Dictionary:
48
56
  var response = await _send_and_wait(msg_type, args, timeout)
49
57
  if response == null:
@@ -34,19 +34,30 @@ func get_commands() -> Dictionary:
34
34
  }
35
35
 
36
36
 
37
+ # Total wall budget for a long-running input command. The server derives the
38
+ # whole cascade and pushes relay_timeout_ms down in params (#276); the local
39
+ # fallback is used only for an older server that pushes no budget.
40
+ func _pushed_budget(params: Dictionary, fallback: float) -> float:
41
+ if params.has("relay_timeout_ms"):
42
+ return float(params["relay_timeout_ms"]) / 1000.0
43
+ return fallback
44
+
45
+
37
46
  # Block until the running game's bridge reports it can consume input, bounded by
38
- # READY_TIMEOUT. Returns true once ready, false if the game stops or never comes
39
- # up in time. In the common case (game already running) this returns immediately
40
- # without waiting a frame. Gating input on this is the fix for #241: the debug
41
- # session connects before the main scene loads, so input dispatched on
42
- # has_active_session() alone lands in a game with nothing to receive it.
43
- func _await_bridge_ready(debugger_plugin) -> bool:
44
- var start_time := Time.get_ticks_msec()
47
+ # READY_TIMEOUT and the shared call deadline (op_start + total_budget) so the
48
+ # ready-wait can never eat the budget the command itself needs (#276). Returns
49
+ # true once ready, false if the game stops or never comes up in time. In the
50
+ # common case (game already running) this returns immediately without waiting a
51
+ # frame. Gating input on this is the fix for #241: the debug session connects
52
+ # before the main scene loads, so input dispatched on has_active_session() alone
53
+ # lands in a game with nothing to receive it.
54
+ func _await_bridge_ready(debugger_plugin, op_start: int, total_budget: float) -> bool:
45
55
  while not debugger_plugin.is_bridge_ready():
46
56
  if not EditorInterface.is_playing_scene():
47
57
  return false # game stopped or crashed while we waited
48
58
  await Engine.get_main_loop().process_frame
49
- if (Time.get_ticks_msec() - start_time) / 1000.0 > READY_TIMEOUT:
59
+ var elapsed := (Time.get_ticks_msec() - op_start) / 1000.0
60
+ if elapsed > READY_TIMEOUT or elapsed > total_budget:
50
61
  return false
51
62
  return true
52
63
 
@@ -146,11 +157,12 @@ func execute_input_sequence(params: Dictionary) -> Dictionary:
146
157
  var debugger_plugin = _plugin.get_debugger_plugin() if _plugin else null
147
158
  if debugger_plugin == null:
148
159
  return _error("NO_SESSION", "No active debug session")
149
- if not await _await_bridge_ready(debugger_plugin):
150
- return _error("BRIDGE_NOT_READY", _BRIDGE_NOT_READY_MSG)
151
-
152
- # The window can extend past the last input if a frame capture is requested
153
- # at a later offset, so factor capture offsets into the timeout too.
160
+ # One deadline for the whole call, stamped BEFORE the ready-wait so the
161
+ # bridge-ready gap is folded into the budget instead of stacking on top of
162
+ # it (#276). Prefer the server-pushed budget; the fallback (older server) is
163
+ # the longest input/capture offset plus headroom, floored at INPUT_TIMEOUT,
164
+ # plus the ready-wait that now counts against the same deadline.
165
+ var op_start := Time.get_ticks_msec()
154
166
  var max_end_time: float = 0.0
155
167
  for input in inputs:
156
168
  var start_ms: float = input.get("start_ms", 0.0)
@@ -158,8 +170,11 @@ func execute_input_sequence(params: Dictionary) -> Dictionary:
158
170
  max_end_time = max(max_end_time, start_ms + duration_ms)
159
171
  for shot_ms in screenshots:
160
172
  max_end_time = max(max_end_time, float(shot_ms))
173
+ var fallback: float = max(INPUT_TIMEOUT, (max_end_time / 1000.0) + 5.0) + READY_TIMEOUT
174
+ var timeout := _pushed_budget(params, fallback)
161
175
 
162
- var timeout := max(INPUT_TIMEOUT, (max_end_time / 1000.0) + 5.0)
176
+ if not await _await_bridge_ready(debugger_plugin, op_start, timeout):
177
+ return _error("BRIDGE_NOT_READY", _BRIDGE_NOT_READY_MSG)
163
178
 
164
179
  _sequence_pending = true
165
180
  _sequence_result = {}
@@ -171,10 +186,9 @@ func execute_input_sequence(params: Dictionary) -> Dictionary:
171
186
  debugger_plugin.input_sequence_completed.connect(_on_sequence_completed, CONNECT_ONE_SHOT)
172
187
  debugger_plugin.request_input_sequence(inputs, report, screenshots, screenshot_max_width)
173
188
 
174
- var start_time := Time.get_ticks_msec()
175
189
  while _sequence_pending:
176
190
  await Engine.get_main_loop().process_frame
177
- if (Time.get_ticks_msec() - start_time) / 1000.0 > timeout:
191
+ if (Time.get_ticks_msec() - op_start) / 1000.0 > timeout:
178
192
  _sequence_pending = false
179
193
  if debugger_plugin.input_sequence_completed.is_connected(_on_sequence_completed):
180
194
  debugger_plugin.input_sequence_completed.disconnect(_on_sequence_completed)
@@ -225,10 +239,14 @@ func type_text(params: Dictionary) -> Dictionary:
225
239
  var debugger_plugin = _plugin.get_debugger_plugin() if _plugin else null
226
240
  if debugger_plugin == null:
227
241
  return _error("NO_SESSION", "No active debug session")
228
- if not await _await_bridge_ready(debugger_plugin):
229
- return _error("BRIDGE_NOT_READY", _BRIDGE_NOT_READY_MSG)
242
+ # Shared deadline (ready-wait + typing), stamped before the ready-wait so the
243
+ # gap is folded into the budget (#276); server-pushed budget or local fallback.
244
+ var op_start := Time.get_ticks_msec()
245
+ var fallback: float = max(INPUT_TIMEOUT, (text.length() * delay_ms / 1000.0) + 5.0) + READY_TIMEOUT
246
+ var timeout := _pushed_budget(params, fallback)
230
247
 
231
- var timeout := max(INPUT_TIMEOUT, (text.length() * delay_ms / 1000.0) + 5.0)
248
+ if not await _await_bridge_ready(debugger_plugin, op_start, timeout):
249
+ return _error("BRIDGE_NOT_READY", _BRIDGE_NOT_READY_MSG)
232
250
 
233
251
  _type_text_pending = true
234
252
  _type_text_result = {}
@@ -236,10 +254,9 @@ func type_text(params: Dictionary) -> Dictionary:
236
254
  debugger_plugin.type_text_completed.connect(_on_type_text_completed, CONNECT_ONE_SHOT)
237
255
  debugger_plugin.request_type_text(text, delay_ms, submit)
238
256
 
239
- var start_time := Time.get_ticks_msec()
240
257
  while _type_text_pending:
241
258
  await Engine.get_main_loop().process_frame
242
- if (Time.get_ticks_msec() - start_time) / 1000.0 > timeout:
259
+ if (Time.get_ticks_msec() - op_start) / 1000.0 > timeout:
243
260
  _type_text_pending = false
244
261
  if debugger_plugin.type_text_completed.is_connected(_on_type_text_completed):
245
262
  debugger_plugin.type_text_completed.disconnect(_on_type_text_completed)
@@ -283,11 +283,13 @@ var _sequence_capture_offsets: Array = []
283
283
  var _sequence_captures_pending: int = 0
284
284
  var _sequence_capture_max_width: int = 640
285
285
  const SEQUENCE_MAX_CAPTURES := 8
286
- # Capped well under the 30s server command timeout: the sequence runs until its
287
- # last capture offset, so a larger value would let the whole call time out
288
- # server-side. 20s is already far longer than any transient-visual capture needs.
289
- # This bound is a placeholder for the global-timeout fix tracked in godot-mcp#276.
290
- const SEQUENCE_MAX_CAPTURE_OFFSET_MS := 20000
286
+ # Non-binding sanity backstop only (#276). The server derives the per-call
287
+ # timeout from the sequence span and rejects offsets beyond what the ceiling
288
+ # permits before they ever reach here, so this just guards a malformed direct
289
+ # message. Kept far above any server-permitted budget so it never silently
290
+ # clamps a legitimate offset (which would reintroduce the cross-layer drift
291
+ # that #276 removed).
292
+ const SEQUENCE_MAX_CAPTURE_OFFSET_MS := 300000
291
293
  # Actions whose press has been injected but whose paired release has not yet
292
294
  # fired. Used to guarantee a release even if the queue is cleared mid-flight
293
295
  # (new sequence) or the node leaves the tree — otherwise the dropped release
@@ -1332,10 +1334,15 @@ func _type_text_async(text: String, delay_ms: int, submit: bool) -> void:
1332
1334
  # ---------------------------------------------------------------------------
1333
1335
 
1334
1336
  const LAUNCH_FROZEN_ENV := "GODOT_MCP_LAUNCH_FROZEN"
1335
- # Timeout cascade: step request <= 20s game time, wall budget 25s, editor
1336
- # relay 28s, server command timeout 30s. Each layer answers before the one
1337
- # above it gives up.
1338
- const STEP_MAX_MS := 20000
1337
+ # Timeout cascade (#276): the server derives the whole stagger from the call's
1338
+ # in-game budget and pushes wall_budget_ms down here. The bridge returns by that
1339
+ # wall budget, the editor relay waits a margin longer, the server socket a
1340
+ # margin longer still — each answers before the one above gives up.
1341
+ # STEP_MAX_MS non-binding sanity backstop (the server already clamps the request)
1342
+ # STEP_DEFAULT_MS budget used when a call omits max_ms (older server that sends no default)
1343
+ # STEP_WALL_BUDGET_MS wall-budget fallback when the server pushes no wall_budget_ms
1344
+ const STEP_MAX_MS := 300000
1345
+ const STEP_DEFAULT_MS := 20000
1339
1346
  const STEP_MAX_FRAMES := 1200
1340
1347
  const STEP_WALL_BUDGET_MS := 25000
1341
1348
  const STEP_MAX_TRANSITIONS := 50
@@ -1358,6 +1365,7 @@ var _step_gameplay_ms := 0.0 # the unpaused portion: what gameplay actually exp
1358
1365
  var _step_frames := 0
1359
1366
  var _step_physics_ticks := 0
1360
1367
  var _step_wall_start := 0
1368
+ var _step_wall_budget_ms := STEP_WALL_BUDGET_MS # set per-call from the server-pushed wall_budget_ms (#276)
1361
1369
  var _step_events: Array = [] # in-step input timeline, scheduled on the game-time clock
1362
1370
  var _step_events_fired := 0
1363
1371
  var _step_transitions: Array = []
@@ -1515,6 +1523,7 @@ func _handle_game_time_step(data: Array) -> void:
1515
1523
  _step_finish_pending = false
1516
1524
  _step_wall_exceeded = false
1517
1525
  _step_wall_start = Time.get_ticks_msec()
1526
+ _step_wall_budget_ms = int(params.get("wall_budget_ms", STEP_WALL_BUDGET_MS))
1518
1527
  _step_predicate = null
1519
1528
  _step_response_type = "game_time_step"
1520
1529
  _step_active = true
@@ -1631,9 +1640,9 @@ func _handle_game_time_step_until(data: Array) -> void:
1631
1640
  _send_game_time_response("game_time_step_until", {"error": "step_until requires a non-empty `until` expression"})
1632
1641
  return
1633
1642
 
1634
- var max_ms: int = int(params.get("max_ms", STEP_MAX_MS))
1643
+ var max_ms: int = int(params.get("max_ms", STEP_DEFAULT_MS))
1635
1644
  if max_ms <= 0:
1636
- max_ms = STEP_MAX_MS
1645
+ max_ms = STEP_DEFAULT_MS
1637
1646
  max_ms = mini(max_ms, STEP_MAX_MS)
1638
1647
 
1639
1648
  # Compile and validate the predicate against the live tree before committing
@@ -1696,6 +1705,7 @@ func _handle_game_time_step_until(data: Array) -> void:
1696
1705
  _step_finish_pending = false
1697
1706
  _step_wall_exceeded = false
1698
1707
  _step_wall_start = Time.get_ticks_msec()
1708
+ _step_wall_budget_ms = int(params.get("wall_budget_ms", STEP_WALL_BUDGET_MS))
1699
1709
  _step_predicate = expr
1700
1710
  _step_predicate_inputs = ctx_inputs
1701
1711
  _step_predicate_met = false
@@ -1767,7 +1777,7 @@ func _step_process(delta: float) -> void:
1767
1777
  _step_predicate_met = true
1768
1778
  done = true
1769
1779
 
1770
- if Time.get_ticks_msec() - _step_wall_start > STEP_WALL_BUDGET_MS:
1780
+ if Time.get_ticks_msec() - _step_wall_start > _step_wall_budget_ms:
1771
1781
  # Slow-mo, Engine.time_scale = 0, or a pause-held window can starve
1772
1782
  # the game-time clock; the wall budget guarantees the call returns
1773
1783
  # (partial, honestly reported) before the editor relay gives up.
package/addon/plugin.cfg CHANGED
@@ -3,6 +3,6 @@
3
3
  name="Godot MCP"
4
4
  description="Model Context Protocol server for AI assistant integration"
5
5
  author="godot-mcp"
6
- version="3.12.0"
6
+ version="3.13.0"
7
7
  script="plugin.gd"
8
8
  godot_version_min="4.5"
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=timeouts.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeouts.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/connection/timeouts.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,58 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { deriveTimeouts, maxInGameBudgetMs, QUICK_TIMEOUT_MS, ABSOLUTE_CEILING_MS, READY_WAIT_MS, BRIDGE_WALL_SLOP_MS, STEP_BUDGET_CAP_MS, INPUT_BUDGET_CAP_MS, } from '../../connection/timeouts.js';
3
+ describe('timeout cascade (#276)', () => {
4
+ describe('deriveTimeouts stagger invariant', () => {
5
+ // The whole point: bridge answers before relay answers before the server
6
+ // gives up, and the server never exceeds the absolute ceiling — for ANY
7
+ // budget, clamped or not, with or without the ready-wait.
8
+ const cases = [
9
+ { label: 'zero budget, no ready', budget: 0, readyWait: false },
10
+ { label: 'mid budget, no ready', budget: 5_000, readyWait: false },
11
+ { label: 'at step cap', budget: STEP_BUDGET_CAP_MS, readyWait: false },
12
+ { label: 'over cap, no ready', budget: 10_000_000, readyWait: false },
13
+ { label: 'zero budget, ready', budget: 0, readyWait: true },
14
+ { label: 'at input cap', budget: INPUT_BUDGET_CAP_MS, readyWait: true },
15
+ { label: 'over cap, ready', budget: 999_999, readyWait: true },
16
+ ];
17
+ for (const c of cases) {
18
+ it(`${c.label}: bridgeWall < relay < server <= ceiling`, () => {
19
+ const t = deriveTimeouts(c.budget, { readyWait: c.readyWait });
20
+ expect(t.bridgeWallMs).toBeLessThan(t.relayMs);
21
+ expect(t.relayMs).toBeLessThan(t.serverMs);
22
+ expect(t.serverMs).toBeLessThanOrEqual(ABSOLUTE_CEILING_MS);
23
+ expect(t.clampedBudgetMs).toBeGreaterThanOrEqual(0);
24
+ expect(t.clampedBudgetMs).toBeLessThanOrEqual(maxInGameBudgetMs({ readyWait: c.readyWait }));
25
+ });
26
+ }
27
+ });
28
+ it('produces a proportionally small (sub-ceiling) timeout for a small budget', () => {
29
+ const t = deriveTimeouts(3_000, { readyWait: false });
30
+ // bridgeWall = 3000 + slop; relay = +2000; server = +2000.
31
+ expect(t.bridgeWallMs).toBe(3_000 + BRIDGE_WALL_SLOP_MS);
32
+ expect(t.serverMs).toBeLessThan(ABSOLUTE_CEILING_MS);
33
+ });
34
+ it('reserves an extra READY_WAIT_MS of headroom when the ready-wait applies', () => {
35
+ expect(maxInGameBudgetMs({ readyWait: false }) - maxInGameBudgetMs({ readyWait: true })).toBe(READY_WAIT_MS);
36
+ });
37
+ it('clamps an over-budget request to the ceiling, never beyond', () => {
38
+ expect(deriveTimeouts(Number.MAX_SAFE_INTEGER, { readyWait: true }).serverMs).toBe(ABSOLUTE_CEILING_MS);
39
+ expect(deriveTimeouts(Number.MAX_SAFE_INTEGER, { readyWait: false }).serverMs).toBe(ABSOLUTE_CEILING_MS);
40
+ });
41
+ it('handles a non-finite budget defensively (treats it as zero)', () => {
42
+ const t = deriveTimeouts(NaN, { readyWait: false });
43
+ expect(t.clampedBudgetMs).toBe(0);
44
+ expect(t.serverMs).toBeGreaterThan(0);
45
+ });
46
+ describe('published caps stay under the ceiling so they can never time out server-side', () => {
47
+ it('step cap <= max in-game budget (no ready-wait)', () => {
48
+ expect(STEP_BUDGET_CAP_MS).toBeLessThanOrEqual(maxInGameBudgetMs({ readyWait: false }));
49
+ });
50
+ it('input cap <= max in-game budget (with ready-wait)', () => {
51
+ expect(INPUT_BUDGET_CAP_MS).toBeLessThanOrEqual(maxInGameBudgetMs({ readyWait: true }));
52
+ });
53
+ });
54
+ it('keeps the quick default unchanged at 30s', () => {
55
+ expect(QUICK_TIMEOUT_MS).toBe(30_000);
56
+ });
57
+ });
58
+ //# sourceMappingURL=timeouts.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeouts.test.js","sourceRoot":"","sources":["../../../src/__tests__/connection/timeouts.test.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
2
  import { once } from 'node:events';
3
3
  import { WebSocketServer } from 'ws';
4
4
  import { GodotConnection } from '../../connection/websocket.js';
5
+ import { getServerVersion } from '../../version.js';
5
6
  // Keep diagnostics hermetic (no WSL detection / no child processes) and quiet.
6
7
  vi.mock('../../utils/connection-strategy.js', () => ({
7
8
  getTargetHost: () => '127.0.0.1',
@@ -105,4 +106,61 @@ describe('GodotConnection contention handling (#237)', () => {
105
106
  expect(message).toMatch(/reconnect/i);
106
107
  });
107
108
  });
109
+ describe('GodotConnection per-request timeout (#276)', () => {
110
+ let connection = null;
111
+ let wss = null;
112
+ afterEach(async () => {
113
+ connection?.disconnect();
114
+ connection = null;
115
+ if (wss) {
116
+ await new Promise((resolve) => wss.close(() => resolve()));
117
+ wss = null;
118
+ }
119
+ });
120
+ // Reply to the handshake (so connect() resolves immediately and without a
121
+ // version-mismatch), then let the supplied handler deal with real commands.
122
+ async function bridgeAfterHandshake(onCommand) {
123
+ return startFakeBridge((socket) => {
124
+ socket.on('message', (raw) => {
125
+ let msg;
126
+ try {
127
+ msg = JSON.parse(raw.toString());
128
+ }
129
+ catch {
130
+ return;
131
+ }
132
+ if (!msg)
133
+ return;
134
+ if (msg.command === 'mcp_handshake') {
135
+ socket.send(JSON.stringify({ id: msg.id, status: 'success', result: { addon_version: getServerVersion() } }));
136
+ return;
137
+ }
138
+ onCommand(socket, msg);
139
+ });
140
+ });
141
+ }
142
+ it('rejects after opts.timeoutMs when the bridge never answers the command', async () => {
143
+ // Drop every non-handshake command on the floor.
144
+ const bridge = await bridgeAfterHandshake(() => { });
145
+ wss = bridge.wss;
146
+ connection = new GodotConnection({ host: '127.0.0.1', port: bridge.port, autoReconnect: false });
147
+ await connection.connect();
148
+ const start = Date.now();
149
+ await expect(connection.sendCommand('get_runtime_state', {}, { timeoutMs: 150 })).rejects.toThrow();
150
+ const elapsed = Date.now() - start;
151
+ expect(elapsed).toBeGreaterThanOrEqual(120);
152
+ expect(elapsed).toBeLessThan(2000);
153
+ });
154
+ it('does not fire early when given a generous opts.timeoutMs', async () => {
155
+ // Answer the command after a short delay; a 1s budget must not trip on it.
156
+ const bridge = await bridgeAfterHandshake((socket, msg) => {
157
+ setTimeout(() => socket.send(JSON.stringify({ id: msg.id, status: 'success', result: { ok: true } })), 100);
158
+ });
159
+ wss = bridge.wss;
160
+ connection = new GodotConnection({ host: '127.0.0.1', port: bridge.port, autoReconnect: false });
161
+ await connection.connect();
162
+ const result = await connection.sendCommand('get_runtime_state', {}, { timeoutMs: 1000 });
163
+ expect(result.ok).toBe(true);
164
+ });
165
+ });
108
166
  //# sourceMappingURL=websocket.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"websocket.test.js","sourceRoot":"","sources":["../../../src/__tests__/connection/websocket.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"websocket.test.js","sourceRoot":"","sources":["../../../src/__tests__/connection/websocket.test.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,9 @@ import type { GodotConnection } from '../../connection/websocket.js';
3
3
  export interface CommandCall {
4
4
  command: string;
5
5
  params: Record<string, unknown>;
6
+ opts?: {
7
+ timeoutMs?: number;
8
+ };
6
9
  }
7
10
  export interface MockGodotConnection {
8
11
  sendCommand: ReturnType<typeof vi.fn>;
@@ -1 +1 @@
1
- {"version":3,"file":"mock-godot.d.ts","sourceRoot":"","sources":["../../../src/__tests__/helpers/mock-godot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC5B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAErE,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,UAAU,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;IACtC,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,YAAY,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1C,SAAS,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAClC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,wBAAgB,eAAe,IAAI,mBAAmB,CA4BrD;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,mBAAmB;WAOvC,eAAe;EAElC;AAKD,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,GAAG,CASjD"}
1
+ {"version":3,"file":"mock-godot.d.ts","sourceRoot":"","sources":["../../../src/__tests__/helpers/mock-godot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC5B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAErE,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/B;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,UAAU,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;IACtC,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,YAAY,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1C,SAAS,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAClC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,wBAAgB,eAAe,IAAI,mBAAmB,CA4BrD;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,mBAAmB;WAOvC,eAAe;EAElC;AAKD,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,GAAG,CASjD"}
@@ -3,8 +3,8 @@ export function createMockGodot() {
3
3
  const calls = [];
4
4
  let nextResponse = {};
5
5
  let nextError = null;
6
- const sendCommand = vi.fn(async (command, params = {}) => {
7
- calls.push({ command, params });
6
+ const sendCommand = vi.fn(async (command, params = {}, opts) => {
7
+ calls.push({ command, params, opts });
8
8
  if (nextError) {
9
9
  const err = nextError;
10
10
  nextError = null;
@@ -1 +1 @@
1
- {"version":3,"file":"mock-godot.js","sourceRoot":"","sources":["../../../src/__tests__/helpers/mock-godot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAgB5B,MAAM,UAAU,eAAe;IAC7B,MAAM,KAAK,GAAkB,EAAE,CAAC;IAChC,IAAI,YAAY,GAAY,EAAE,CAAC;IAC/B,IAAI,SAAS,GAAiB,IAAI,CAAC;IAEnC,MAAM,WAAW,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,OAAe,EAAE,SAAkC,EAAE,EAAE,EAAE;QACxF,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QAChC,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,GAAG,GAAG,SAAS,CAAC;YACtB,SAAS,GAAG,IAAI,CAAC;YACjB,MAAM,GAAG,CAAC;QACZ,CAAC;QACD,MAAM,QAAQ,GAAG,YAAY,CAAC;QAC9B,YAAY,GAAG,EAAE,CAAC;QAClB,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,WAAW;QACX,KAAK;QACL,YAAY,EAAE,CAAC,QAAiB,EAAE,EAAE;YAClC,YAAY,GAAG,QAAQ,CAAC;QAC1B,CAAC;QACD,SAAS,EAAE,CAAC,KAAY,EAAE,EAAE;YAC1B,SAAS,GAAG,KAAK,CAAC;QACpB,CAAC;QACD,YAAY,EAAE,IAAI;KACnB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAyB;IACzD,OAAO;QACL,KAAK,EAAE;YACL,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,IAAI,YAAY;gBACd,OAAO,IAAI,CAAC,YAAY,CAAC;YAC3B,CAAC;SAC4B;KAChC,CAAC;AACJ,CAAC;AAED,4EAA4E;AAC5E,uEAAuE;AACvE,uEAAuE;AACvE,MAAM,UAAU,YAAY,CAAC,MAAe;IAC1C,IACE,MAAM;QACN,OAAO,MAAM,KAAK,QAAQ;QAC1B,mBAAmB,IAAI,MAAM,EAC7B,CAAC;QACD,OAAQ,MAAyC,CAAC,iBAAiB,CAAC;IACtE,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,MAAgB,CAAC,CAAC;AACtC,CAAC"}
1
+ {"version":3,"file":"mock-godot.js","sourceRoot":"","sources":["../../../src/__tests__/helpers/mock-godot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAiB5B,MAAM,UAAU,eAAe;IAC7B,MAAM,KAAK,GAAkB,EAAE,CAAC;IAChC,IAAI,YAAY,GAAY,EAAE,CAAC;IAC/B,IAAI,SAAS,GAAiB,IAAI,CAAC;IAEnC,MAAM,WAAW,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,OAAe,EAAE,SAAkC,EAAE,EAAE,IAA6B,EAAE,EAAE;QACvH,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACtC,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,GAAG,GAAG,SAAS,CAAC;YACtB,SAAS,GAAG,IAAI,CAAC;YACjB,MAAM,GAAG,CAAC;QACZ,CAAC;QACD,MAAM,QAAQ,GAAG,YAAY,CAAC;QAC9B,YAAY,GAAG,EAAE,CAAC;QAClB,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,WAAW;QACX,KAAK;QACL,YAAY,EAAE,CAAC,QAAiB,EAAE,EAAE;YAClC,YAAY,GAAG,QAAQ,CAAC;QAC1B,CAAC;QACD,SAAS,EAAE,CAAC,KAAY,EAAE,EAAE;YAC1B,SAAS,GAAG,KAAK,CAAC;QACpB,CAAC;QACD,YAAY,EAAE,IAAI;KACnB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAyB;IACzD,OAAO;QACL,KAAK,EAAE;YACL,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,IAAI,YAAY;gBACd,OAAO,IAAI,CAAC,YAAY,CAAC;YAC3B,CAAC;SAC4B;KAChC,CAAC;AACJ,CAAC;AAED,4EAA4E;AAC5E,uEAAuE;AACvE,uEAAuE;AACvE,MAAM,UAAU,YAAY,CAAC,MAAe;IAC1C,IACE,MAAM;QACN,OAAO,MAAM,KAAK,QAAQ;QAC1B,mBAAmB,IAAI,MAAM,EAC7B,CAAC;QACD,OAAQ,MAAyC,CAAC,iBAAiB,CAAC;IACtE,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,MAAgB,CAAC,CAAC;AACtC,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import { describe, it, expect, beforeEach } from 'vitest';
2
2
  import { createMockGodot, createToolContext, structuredOf } from '../helpers/mock-godot.js';
3
3
  import { gameTime } from '../../tools/game-time.js';
4
+ import { deriveTimeouts } from '../../connection/timeouts.js';
4
5
  describe('game_time tool', () => {
5
6
  let mock;
6
7
  beforeEach(() => {
@@ -13,9 +14,9 @@ describe('game_time tool', () => {
13
14
  expect(gameTime.schema.safeParse({ action: 'step', duration_ms: 500 }).success).toBe(true);
14
15
  expect(gameTime.schema.safeParse({ action: 'step', frames: 1 }).success).toBe(true);
15
16
  });
16
- it('step enforces the bridge-side caps', () => {
17
- expect(gameTime.schema.safeParse({ action: 'step', duration_ms: 20000 }).success).toBe(true);
18
- expect(gameTime.schema.safeParse({ action: 'step', duration_ms: 20001 }).success).toBe(false);
17
+ it('step enforces the published caps', () => {
18
+ expect(gameTime.schema.safeParse({ action: 'step', duration_ms: 50000 }).success).toBe(true);
19
+ expect(gameTime.schema.safeParse({ action: 'step', duration_ms: 50001 }).success).toBe(false);
19
20
  expect(gameTime.schema.safeParse({ action: 'step', frames: 1200 }).success).toBe(true);
20
21
  expect(gameTime.schema.safeParse({ action: 'step', frames: 1201 }).success).toBe(false);
21
22
  expect(gameTime.schema.safeParse({ action: 'step', duration_ms: 0 }).success).toBe(false);
@@ -33,8 +34,8 @@ describe('game_time tool', () => {
33
34
  expect(gameTime.schema.safeParse({ action: 'step_until', until: 'G.wave > 1' }).success).toBe(true);
34
35
  });
35
36
  it('step_until caps max_ms and accepts report expressions and an input timeline', () => {
36
- expect(gameTime.schema.safeParse({ action: 'step_until', until: 'true', max_ms: 20000 }).success).toBe(true);
37
- expect(gameTime.schema.safeParse({ action: 'step_until', until: 'true', max_ms: 20001 }).success).toBe(false);
37
+ expect(gameTime.schema.safeParse({ action: 'step_until', until: 'true', max_ms: 50000 }).success).toBe(true);
38
+ expect(gameTime.schema.safeParse({ action: 'step_until', until: 'true', max_ms: 50001 }).success).toBe(false);
38
39
  expect(gameTime.schema.safeParse({ action: 'step_until', until: 'true', max_ms: 0 }).success).toBe(false);
39
40
  expect(gameTime.schema.safeParse({ action: 'step_until', until: 'true', report: ['G.wave', 'G.score'] }).success).toBe(true);
40
41
  expect(gameTime.schema.safeParse({ action: 'step_until', until: 'true', report: [''] }).success).toBe(false);
@@ -110,6 +111,19 @@ describe('game_time tool', () => {
110
111
  expect(data.game_paused).toBe(true);
111
112
  expect(data.gameplay_ms).toBe(120);
112
113
  });
114
+ it('derives the per-request timeout and pushes the relay/wall budgets to the bridge (#276)', async () => {
115
+ mock.mockResponse({
116
+ completed: true, frozen: true, elapsed_ms: 500, gameplay_ms: 500,
117
+ frames: 30, physics_ticks: 30, game_paused: false,
118
+ });
119
+ const ctx = createToolContext(mock);
120
+ await gameTime.execute({ action: 'step', duration_ms: 500 }, ctx);
121
+ const call = mock.calls[0];
122
+ const t = deriveTimeouts(500); // game_time has no ready-wait
123
+ expect(call.params.wall_budget_ms).toBe(t.bridgeWallMs);
124
+ expect(call.params.relay_timeout_ms).toBe(t.relayMs);
125
+ expect(call.opts?.timeoutMs).toBe(t.serverMs);
126
+ });
113
127
  });
114
128
  describe('step_until', () => {
115
129
  it('forwards the predicate and report, and surfaces a met result with its readings', async () => {
@@ -163,6 +177,32 @@ describe('game_time tool', () => {
163
177
  const ctx = createToolContext(mock);
164
178
  await expect(gameTime.execute({ action: 'step_until', until: 'Bogus.foo > 1' }, ctx)).rejects.toThrow('predicate failed to evaluate');
165
179
  });
180
+ it('sizes the timeout from max_ms and pushes the derived budgets (#276)', async () => {
181
+ mock.mockResponse({
182
+ completed: true, frozen: true, elapsed_ms: 0, gameplay_ms: 0,
183
+ frames: 0, physics_ticks: 0, game_paused: false, predicate_met: true,
184
+ });
185
+ const ctx = createToolContext(mock);
186
+ await gameTime.execute({ action: 'step_until', until: 'true', max_ms: 8000 }, ctx);
187
+ const call = mock.calls[0];
188
+ const t = deriveTimeouts(8000); // budget = explicit max_ms, no ready-wait
189
+ expect(call.params.max_ms).toBe(8000);
190
+ expect(call.params.wall_budget_ms).toBe(t.bridgeWallMs);
191
+ expect(call.params.relay_timeout_ms).toBe(t.relayMs);
192
+ expect(call.opts?.timeoutMs).toBe(t.serverMs);
193
+ });
194
+ it('defaults max_ms to a modest 20s, decoupled from the 50s cap, when omitted (#276)', async () => {
195
+ mock.mockResponse({
196
+ completed: true, frozen: true, elapsed_ms: 20000, gameplay_ms: 20000,
197
+ frames: 1200, physics_ticks: 1200, game_paused: false, predicate_met: false,
198
+ });
199
+ const ctx = createToolContext(mock);
200
+ await gameTime.execute({ action: 'step_until', until: 'false' }, ctx);
201
+ const call = mock.calls[0];
202
+ // Omitted max_ms must not inherit the 50s cap: a wrong predicate gives up in ~20s.
203
+ expect(call.params.max_ms).toBe(20000);
204
+ expect(call.opts?.timeoutMs).toBe(deriveTimeouts(20000).serverMs);
205
+ });
166
206
  });
167
207
  describe('thaw', () => {
168
208
  it('reports the frozen duration', async () => {
@@ -1 +1 @@
1
- {"version":3,"file":"game-time.test.js","sourceRoot":"","sources":["../../../src/__tests__/tools/game-time.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAuB,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACjH,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEpD,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,IAAI,IAAyB,CAAC;IAE9B,UAAU,CAAC,GAAG,EAAE;QACd,IAAI,GAAG,eAAe,EAAE,CAAC;IAC3B,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;YAC5D,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1E,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACxG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC3F,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtF,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;YAC5C,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC7F,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC9F,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACvF,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACxF,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5F,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC;gBAC/B,MAAM,EAAE,MAAM;gBACd,WAAW,EAAE,GAAG;gBAChB,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC;aACnE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;YAC1D,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAChF,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC3F,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtG,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6EAA6E,EAAE,GAAG,EAAE;YACrF,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC7G,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC9G,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1G,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC7H,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC7G,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC;gBAC/B,MAAM,EAAE,YAAY;gBACpB,KAAK,EAAE,MAAM;gBACb,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC;aACpE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;YAC1D,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC3E,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACzE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7E,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE;QACtB,EAAE,CAAC,wBAAwB,EAAE,KAAK,IAAI,EAAE;YACtC,IAAI,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;YAC3E,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAEpC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,GAAG,CAAC,CAAC;YACjE,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;YACnC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;YAC/C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;YACjE,IAAI,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;YACzE,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAEpC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,GAAG,CAAC,CAAC;YACjE,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;YAC3C,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE;QACpB,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;YAChF,IAAI,CAAC,YAAY,CAAC;gBAChB,SAAS,EAAE,IAAI;gBACf,MAAM,EAAE,IAAI;gBACZ,UAAU,EAAE,GAAG;gBACf,WAAW,EAAE,GAAG;gBAChB,MAAM,EAAE,EAAE;gBACV,aAAa,EAAE,EAAE;gBACjB,WAAW,EAAE,KAAK;gBAClB,YAAY,EAAE,CAAC;aAChB,CAAC,CAAC;YACH,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAEpC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC;gBACpC,MAAM,EAAE,MAAM;gBACd,WAAW,EAAE,GAAG;gBAChB,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC;aACjE,EAAE,GAAG,CAAC,CAAC;YAER,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACnD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YACpD,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;YAClC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAClC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;YAC9D,IAAI,CAAC,YAAY,CAAC;gBAChB,SAAS,EAAE,IAAI;gBACf,MAAM,EAAE,IAAI;gBACZ,UAAU,EAAE,GAAG;gBACf,WAAW,EAAE,GAAG;gBAChB,MAAM,EAAE,EAAE;gBACV,aAAa,EAAE,CAAC;gBAChB,WAAW,EAAE,IAAI;gBACjB,iBAAiB,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;aAClD,CAAC,CAAC;YACH,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAEpC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;YACjF,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;YAClC,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC/C,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;QAC1B,EAAE,CAAC,gFAAgF,EAAE,KAAK,IAAI,EAAE;YAC9F,IAAI,CAAC,YAAY,CAAC;gBAChB,SAAS,EAAE,IAAI;gBACf,MAAM,EAAE,IAAI;gBACZ,UAAU,EAAE,IAAI;gBAChB,WAAW,EAAE,IAAI;gBACjB,MAAM,EAAE,GAAG;gBACX,aAAa,EAAE,GAAG;gBAClB,WAAW,EAAE,KAAK;gBAClB,aAAa,EAAE,IAAI;gBACnB,MAAM,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE;aACxB,CAAC,CAAC;YACH,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAEpC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC;gBACpC,MAAM,EAAE,YAAY;gBACpB,KAAK,EAAE,gDAAgD;gBACvD,MAAM,EAAE,IAAI;gBACZ,MAAM,EAAE,CAAC,QAAQ,CAAC;aACnB,EAAE,GAAG,CAAC,CAAC;YAER,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;YAC3D,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;YAC1F,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;YACxD,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;YAClC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;YAC7C,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;YACrE,IAAI,CAAC,YAAY,CAAC;gBAChB,SAAS,EAAE,IAAI;gBACf,MAAM,EAAE,IAAI;gBACZ,UAAU,EAAE,IAAI;gBAChB,WAAW,EAAE,IAAI;gBACjB,MAAM,EAAE,GAAG;gBACX,aAAa,EAAE,GAAG;gBAClB,WAAW,EAAE,KAAK;gBAClB,aAAa,EAAE,KAAK;gBACpB,MAAM,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE;aACxB,CAAC,CAAC;YACH,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAEpC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAC5H,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;YAClC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACvC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;YAC5D,IAAI,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC,CAAC;YAC/E,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAEpC,MAAM,MAAM,CACV,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,EAAE,EAAE,GAAG,CAAC,CACxE,CAAC,OAAO,CAAC,OAAO,CAAC,8BAA8B,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE;QACpB,EAAE,CAAC,6BAA6B,EAAE,KAAK,IAAI,EAAE;YAC3C,IAAI,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC;YAClG,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAEpC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,CAAC;YAC/D,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;YACpC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;YAC7C,IAAI,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;YAC5E,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAEpC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,CAAC;YAC/D,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE;QACtB,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;YACnD,IAAI,CAAC,YAAY,CAAC;gBAChB,MAAM,EAAE,IAAI;gBACZ,WAAW,EAAE,KAAK;gBAClB,WAAW,EAAE,IAAI;gBACjB,iBAAiB,EAAE,GAAG;gBACtB,wBAAwB,EAAE,EAAE;gBAC5B,cAAc,EAAE,KAAK;gBACrB,kBAAkB,EAAE,CAAC;gBACrB,eAAe,EAAE,IAAI;aACtB,CAAC,CAAC;YACH,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAEpC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,GAAG,CAAC,CAAC;YACjE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;YACvD,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;YAClC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/B,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACxC,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"game-time.test.js","sourceRoot":"","sources":["../../../src/__tests__/tools/game-time.test.ts"],"names":[],"mappings":"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"}