@satelliteoflove/godot-mcp 2.11.0 → 2.12.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 (69) hide show
  1. package/README.md +75 -43
  2. package/addon/core/mcp_constants.gd +5 -0
  3. package/addon/core/mcp_enums.gd +10 -0
  4. package/addon/plugin.cfg +1 -1
  5. package/addon/plugin.gd +163 -5
  6. package/addon/ui/status_panel.gd +171 -9
  7. package/addon/ui/status_panel.tscn +80 -4
  8. package/addon/websocket_server.gd +22 -5
  9. package/dist/__tests__/utils/connection-strategy.test.d.ts +2 -0
  10. package/dist/__tests__/utils/connection-strategy.test.d.ts.map +1 -0
  11. package/dist/__tests__/utils/connection-strategy.test.js +106 -0
  12. package/dist/__tests__/utils/connection-strategy.test.js.map +1 -0
  13. package/dist/__tests__/utils/host-ip-resolver.test.d.ts +2 -0
  14. package/dist/__tests__/utils/host-ip-resolver.test.d.ts.map +1 -0
  15. package/dist/__tests__/utils/host-ip-resolver.test.js +116 -0
  16. package/dist/__tests__/utils/host-ip-resolver.test.js.map +1 -0
  17. package/dist/__tests__/utils/wsl-detection.test.d.ts +2 -0
  18. package/dist/__tests__/utils/wsl-detection.test.d.ts.map +1 -0
  19. package/dist/__tests__/utils/wsl-detection.test.js +116 -0
  20. package/dist/__tests__/utils/wsl-detection.test.js.map +1 -0
  21. package/dist/connection/websocket.d.ts +3 -1
  22. package/dist/connection/websocket.d.ts.map +1 -1
  23. package/dist/connection/websocket.js +21 -11
  24. package/dist/connection/websocket.js.map +1 -1
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +2 -1
  27. package/dist/index.js.map +1 -1
  28. package/dist/resources/script.d.ts.map +1 -1
  29. package/dist/resources/script.js +4 -5
  30. package/dist/resources/script.js.map +1 -1
  31. package/dist/tools/editor.js +2 -2
  32. package/dist/tools/editor.js.map +1 -1
  33. package/dist/utils/connection-strategy.d.ts +23 -0
  34. package/dist/utils/connection-strategy.d.ts.map +1 -0
  35. package/dist/utils/connection-strategy.js +44 -0
  36. package/dist/utils/connection-strategy.js.map +1 -0
  37. package/dist/utils/gateway-resolver.d.ts +18 -0
  38. package/dist/utils/gateway-resolver.d.ts.map +1 -0
  39. package/dist/utils/gateway-resolver.js +173 -0
  40. package/dist/utils/gateway-resolver.js.map +1 -0
  41. package/dist/utils/host-ip-resolver.d.ts +19 -0
  42. package/dist/utils/host-ip-resolver.d.ts.map +1 -0
  43. package/dist/utils/host-ip-resolver.js +60 -0
  44. package/dist/utils/host-ip-resolver.js.map +1 -0
  45. package/dist/utils/wsl-detection.d.ts +11 -0
  46. package/dist/utils/wsl-detection.d.ts.map +1 -0
  47. package/dist/utils/wsl-detection.js +43 -0
  48. package/dist/utils/wsl-detection.js.map +1 -0
  49. package/package.json +5 -2
  50. package/addon/command_router.gd.uid +0 -1
  51. package/addon/commands/animation_commands.gd.uid +0 -1
  52. package/addon/commands/debug_commands.gd.uid +0 -1
  53. package/addon/commands/node_commands.gd.uid +0 -1
  54. package/addon/commands/project_commands.gd.uid +0 -1
  55. package/addon/commands/resource_commands.gd.uid +0 -1
  56. package/addon/commands/scene3d_commands.gd.uid +0 -1
  57. package/addon/commands/scene_commands.gd.uid +0 -1
  58. package/addon/commands/screenshot_commands.gd.uid +0 -1
  59. package/addon/commands/script_commands.gd.uid +0 -1
  60. package/addon/commands/selection_commands.gd.uid +0 -1
  61. package/addon/commands/tilemap_commands.gd.uid +0 -1
  62. package/addon/core/base_command.gd.uid +0 -1
  63. package/addon/core/mcp_debugger_plugin.gd.uid +0 -1
  64. package/addon/core/mcp_logger.gd.uid +0 -1
  65. package/addon/core/mcp_utils.gd.uid +0 -1
  66. package/addon/game_bridge/mcp_game_bridge.gd.uid +0 -1
  67. package/addon/plugin.gd.uid +0 -1
  68. package/addon/ui/status_panel.gd.uid +0 -1
  69. package/addon/websocket_server.gd.uid +0 -1
@@ -22,20 +22,96 @@ theme_override_constants/margin_top = 4
22
22
  theme_override_constants/margin_right = 8
23
23
  theme_override_constants/margin_bottom = 4
24
24
 
25
- [node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer"]
25
+ [node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
26
26
  layout_mode = 2
27
27
  theme_override_constants/separation = 8
28
28
 
29
- [node name="Label" type="Label" parent="MarginContainer/HBoxContainer"]
29
+ [node name="StatusRow" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
30
+ layout_mode = 2
31
+ theme_override_constants/separation = 8
32
+
33
+ [node name="Label" type="Label" parent="MarginContainer/VBoxContainer/StatusRow"]
30
34
  layout_mode = 2
31
35
  text = "MCP Server:"
32
36
 
33
- [node name="StatusIcon" type="ColorRect" parent="MarginContainer/HBoxContainer"]
37
+ [node name="StatusIcon" type="ColorRect" parent="MarginContainer/VBoxContainer/StatusRow"]
34
38
  custom_minimum_size = Vector2(12, 12)
35
39
  layout_mode = 2
36
40
  size_flags_vertical = 4
37
41
  color = Color(0.5, 0.5, 0.5, 1)
38
42
 
39
- [node name="StatusLabel" type="Label" parent="MarginContainer/HBoxContainer"]
43
+ [node name="StatusLabel" type="Label" parent="MarginContainer/VBoxContainer/StatusRow"]
40
44
  layout_mode = 2
45
+ size_flags_horizontal = 3
41
46
  text = "Initializing..."
47
+
48
+ [node name="HSeparator" type="HSeparator" parent="MarginContainer/VBoxContainer"]
49
+ layout_mode = 2
50
+
51
+ [node name="SettingsGrid" type="GridContainer" parent="MarginContainer/VBoxContainer"]
52
+ layout_mode = 2
53
+ columns = 2
54
+ theme_override_constants/h_separation = 12
55
+ theme_override_constants/v_separation = 6
56
+
57
+ [node name="BindLabel" type="Label" parent="MarginContainer/VBoxContainer/SettingsGrid"]
58
+ layout_mode = 2
59
+ text = "Bind mode"
60
+
61
+ [node name="BindModeOption" type="OptionButton" parent="MarginContainer/VBoxContainer/SettingsGrid"]
62
+ layout_mode = 2
63
+ size_flags_horizontal = 3
64
+
65
+ [node name="CustomIpLabel" type="Label" parent="MarginContainer/VBoxContainer/SettingsGrid"]
66
+ layout_mode = 2
67
+ text = "Custom bind IP"
68
+
69
+ [node name="CustomIpControls" type="HBoxContainer" parent="MarginContainer/VBoxContainer/SettingsGrid"]
70
+ layout_mode = 2
71
+ theme_override_constants/separation = 6
72
+ size_flags_horizontal = 3
73
+
74
+ [node name="CustomIpEdit" type="LineEdit" parent="MarginContainer/VBoxContainer/SettingsGrid/CustomIpControls"]
75
+ custom_minimum_size = Vector2(220, 0)
76
+ layout_mode = 2
77
+ size_flags_horizontal = 3
78
+ placeholder_text = "e.g. 127.0.0.1"
79
+
80
+ [node name="PortOverrideLabel" type="Label" parent="MarginContainer/VBoxContainer/SettingsGrid"]
81
+ layout_mode = 2
82
+ text = "Port override"
83
+
84
+ [node name="PortOverrideControls" type="HBoxContainer" parent="MarginContainer/VBoxContainer/SettingsGrid"]
85
+ layout_mode = 2
86
+ theme_override_constants/separation = 8
87
+ size_flags_horizontal = 3
88
+
89
+ [node name="PortOverrideEnabled" type="CheckBox" parent="MarginContainer/VBoxContainer/SettingsGrid/PortOverrideControls"]
90
+ layout_mode = 2
91
+ text = "Enable"
92
+
93
+ [node name="PortOverrideSpin" type="SpinBox" parent="MarginContainer/VBoxContainer/SettingsGrid/PortOverrideControls"]
94
+ layout_mode = 2
95
+ min_value = 1.0
96
+ max_value = 65535.0
97
+ step = 1.0
98
+ value = 6550.0
99
+ allow_greater = false
100
+ allow_lesser = false
101
+ rounded = true
102
+
103
+ [node name="ApplySeparator" type="HSeparator" parent="MarginContainer/VBoxContainer"]
104
+ layout_mode = 2
105
+
106
+ [node name="ApplyRow" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
107
+ layout_mode = 2
108
+ theme_override_constants/separation = 8
109
+
110
+ [node name="Spacer" type="Control" parent="MarginContainer/VBoxContainer/ApplyRow"]
111
+ layout_mode = 2
112
+ size_flags_horizontal = 3
113
+
114
+ [node name="ApplyButton" type="Button" parent="MarginContainer/VBoxContainer/ApplyRow"]
115
+ layout_mode = 2
116
+ text = "Apply"
117
+
@@ -17,6 +17,8 @@ var _is_connected := false
17
17
  var _rejected_connections := 0
18
18
  var _pending_rejection: WebSocketPeer = null
19
19
  var _pending_rejection_peer: StreamPeerTCP = null
20
+ var _connected_host: String = ""
21
+ var _connected_port: int = 0
20
22
 
21
23
 
22
24
  func _process(_delta: float) -> void:
@@ -33,14 +35,13 @@ func _process(_delta: float) -> void:
33
35
  _process_pending_rejection()
34
36
 
35
37
 
36
- func start_server(port: int = DEFAULT_PORT) -> Error:
38
+ func start_server(port: int = DEFAULT_PORT, bind_address: String = "127.0.0.1") -> Error:
37
39
  _server = TCPServer.new()
38
- var err := _server.listen(port)
40
+ var err := _server.listen(port, bind_address)
39
41
  if err != OK:
40
- MCPLog.error("Failed to start server on port %d: %s" % [port, error_string(err)])
42
+ MCPLog.error("Failed to start server on %s:%d: %s" % [bind_address, port, error_string(err)])
41
43
  return err
42
44
 
43
- MCPLog.info("Server listening on port %d" % port)
44
45
  return OK
45
46
 
46
47
 
@@ -66,12 +67,24 @@ func stop_server() -> void:
66
67
 
67
68
  _is_connected = false
68
69
  _rejected_connections = 0
70
+ _connected_host = ""
71
+ _connected_port = 0
69
72
 
70
73
 
71
74
  func get_rejected_connection_count() -> int:
72
75
  return _rejected_connections
73
76
 
74
77
 
78
+ func get_connected_host() -> String:
79
+ """Returns the remote host IP address of the connected client."""
80
+ return _connected_host
81
+
82
+
83
+ func get_connected_port() -> int:
84
+ """Returns the remote port of the connected client."""
85
+ return _connected_port
86
+
87
+
75
88
  func send_response(response: Dictionary) -> void:
76
89
  if not _ws_peer or _ws_peer.get_ready_state() != WebSocketPeer.STATE_OPEN:
77
90
  MCPLog.warn("Cannot send response: not connected")
@@ -101,7 +114,11 @@ func _accept_connection() -> void:
101
114
  _peer = null
102
115
  return
103
116
 
104
- MCPLog.info("TCP connection received, awaiting WebSocket handshake...")
117
+ # Capture connection information
118
+ _connected_host = _peer.get_connected_host()
119
+ _connected_port = _peer.get_connected_port()
120
+
121
+ MCPLog.info("TCP connection received from %s:%d, awaiting WebSocket handshake..." % [_connected_host, _connected_port])
105
122
 
106
123
 
107
124
  func _reject_connection(incoming: StreamPeerTCP) -> void:
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=connection-strategy.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection-strategy.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/utils/connection-strategy.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,106 @@
1
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
+ import { getTargetHost, getConnectionStrategy } from '../../utils/connection-strategy.js';
3
+ import * as wslDetection from '../../utils/wsl-detection.js';
4
+ import * as hostIpResolver from '../../utils/host-ip-resolver.js';
5
+ vi.mock('../../utils/wsl-detection.js');
6
+ vi.mock('../../utils/host-ip-resolver.js');
7
+ vi.mock('../../utils/logger.js', () => ({
8
+ logger: {
9
+ debug: vi.fn(),
10
+ warning: vi.fn(),
11
+ info: vi.fn(),
12
+ },
13
+ }));
14
+ describe('connection-strategy', () => {
15
+ beforeEach(() => {
16
+ vi.clearAllMocks();
17
+ delete process.env.GODOT_HOST;
18
+ });
19
+ afterEach(() => {
20
+ vi.clearAllMocks();
21
+ });
22
+ describe('getTargetHost()', () => {
23
+ it('returns GODOT_HOST if set', () => {
24
+ process.env.GODOT_HOST = '192.168.1.100';
25
+ expect(getTargetHost()).toBe('192.168.1.100');
26
+ });
27
+ it('returns auto-detected IP when in WSL and available', () => {
28
+ vi.mocked(wslDetection.isWSL).mockReturnValue(true);
29
+ vi.mocked(hostIpResolver.getHostIpInWSL).mockReturnValue('192.168.1.1');
30
+ expect(getTargetHost()).toBe('192.168.1.1');
31
+ });
32
+ it('returns 127.0.0.1 as fallback when in WSL but no IP detected', () => {
33
+ vi.mocked(wslDetection.isWSL).mockReturnValue(true);
34
+ vi.mocked(hostIpResolver.getHostIpInWSL).mockReturnValue(null);
35
+ expect(getTargetHost()).toBe('127.0.0.1');
36
+ });
37
+ it('returns 127.0.0.1 when not in WSL', () => {
38
+ vi.mocked(wslDetection.isWSL).mockReturnValue(false);
39
+ expect(getTargetHost()).toBe('127.0.0.1');
40
+ });
41
+ it('prioritizes GODOT_HOST over auto-detection', () => {
42
+ process.env.GODOT_HOST = '10.0.0.1';
43
+ vi.mocked(wslDetection.isWSL).mockReturnValue(true);
44
+ vi.mocked(hostIpResolver.getHostIpInWSL).mockReturnValue('192.168.1.1');
45
+ expect(getTargetHost()).toBe('10.0.0.1');
46
+ });
47
+ it('prioritizes auto-detected IP over getHostIpInWSL calls', () => {
48
+ vi.mocked(wslDetection.isWSL).mockReturnValue(true);
49
+ vi.mocked(hostIpResolver.getHostIpInWSL).mockReturnValue('192.168.1.1');
50
+ expect(getTargetHost()).toBe('192.168.1.1');
51
+ expect(vi.mocked(hostIpResolver.getHostIpInWSL)).toHaveBeenCalled();
52
+ });
53
+ it('trims whitespace from GODOT_HOST', () => {
54
+ process.env.GODOT_HOST = ' 192.168.1.100 ';
55
+ expect(getTargetHost()).toBe('192.168.1.100');
56
+ });
57
+ it('accepts hostnames as well as IP addresses', () => {
58
+ process.env.GODOT_HOST = 'localhost';
59
+ expect(getTargetHost()).toBe('localhost');
60
+ process.env.GODOT_HOST = 'godot.local';
61
+ expect(getTargetHost()).toBe('godot.local');
62
+ });
63
+ });
64
+ describe('getConnectionStrategy()', () => {
65
+ it('returns WSL environment info when in WSL', () => {
66
+ vi.mocked(wslDetection.isWSL).mockReturnValue(true);
67
+ vi.mocked(hostIpResolver.getHostIpInWSL).mockReturnValue('192.168.1.1');
68
+ const strategy = getConnectionStrategy(6550);
69
+ expect(strategy.environment).toBe('wsl');
70
+ expect(strategy.targetHost).toBe('192.168.1.1');
71
+ expect(strategy.wsUrl).toBe('ws://192.168.1.1:6550');
72
+ });
73
+ it('returns native environment info when not in WSL', () => {
74
+ vi.mocked(wslDetection.isWSL).mockReturnValue(false);
75
+ const strategy = getConnectionStrategy(6550);
76
+ expect(strategy.environment).toBe('native');
77
+ expect(strategy.targetHost).toBe('127.0.0.1');
78
+ expect(strategy.wsUrl).toBe('ws://127.0.0.1:6550');
79
+ });
80
+ it('includes correct port in wsUrl', () => {
81
+ vi.mocked(wslDetection.isWSL).mockReturnValue(false);
82
+ const strategy = getConnectionStrategy(9999);
83
+ expect(strategy.wsUrl).toBe('ws://127.0.0.1:9999');
84
+ });
85
+ it('uses targetHost for wsUrl', () => {
86
+ process.env.GODOT_HOST = '10.0.0.1';
87
+ const strategy = getConnectionStrategy(6550);
88
+ expect(strategy.targetHost).toBe('10.0.0.1');
89
+ expect(strategy.wsUrl).toBe('ws://10.0.0.1:6550');
90
+ });
91
+ it('respects GODOT_HOST override', () => {
92
+ process.env.GODOT_HOST = '192.168.1.2';
93
+ vi.mocked(wslDetection.isWSL).mockReturnValue(true);
94
+ const strategy = getConnectionStrategy(6550);
95
+ expect(strategy.targetHost).toBe('192.168.1.2');
96
+ });
97
+ it('handles custom ports in URL', () => {
98
+ vi.mocked(wslDetection.isWSL).mockReturnValue(false);
99
+ for (const port of [80, 3000, 6550, 65535]) {
100
+ const strategy = getConnectionStrategy(port);
101
+ expect(strategy.wsUrl).toBe(`ws://127.0.0.1:${port}`);
102
+ }
103
+ });
104
+ });
105
+ });
106
+ //# sourceMappingURL=connection-strategy.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection-strategy.test.js","sourceRoot":"","sources":["../../../src/__tests__/utils/connection-strategy.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=host-ip-resolver.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-ip-resolver.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/utils/host-ip-resolver.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,116 @@
1
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
+ import { getHostIpInWSL, _clearHostIpCache } from '../../utils/host-ip-resolver.js';
3
+ import * as wslDetection from '../../utils/wsl-detection.js';
4
+ import * as gatewayResolver from '../../utils/gateway-resolver.js';
5
+ vi.mock('../../utils/wsl-detection.js');
6
+ vi.mock('../../utils/gateway-resolver.js');
7
+ vi.mock('../../utils/logger.js', () => ({
8
+ logger: {
9
+ debug: vi.fn(),
10
+ warning: vi.fn(),
11
+ info: vi.fn(),
12
+ },
13
+ }));
14
+ describe('host-ip-resolver', () => {
15
+ let originalGodotHost;
16
+ beforeEach(() => {
17
+ originalGodotHost = process.env.GODOT_HOST;
18
+ delete process.env.GODOT_HOST;
19
+ _clearHostIpCache();
20
+ vi.clearAllMocks();
21
+ });
22
+ afterEach(() => {
23
+ if (originalGodotHost !== undefined) {
24
+ process.env.GODOT_HOST = originalGodotHost;
25
+ }
26
+ else {
27
+ delete process.env.GODOT_HOST;
28
+ }
29
+ _clearHostIpCache();
30
+ vi.clearAllMocks();
31
+ });
32
+ describe('getHostIpInWSL()', () => {
33
+ it('returns GODOT_HOST env var if set', () => {
34
+ process.env.GODOT_HOST = '192.168.1.100';
35
+ expect(getHostIpInWSL()).toBe('192.168.1.100');
36
+ expect(vi.mocked(gatewayResolver.resolveGateway)).not.toHaveBeenCalled();
37
+ });
38
+ it('returns null when not in WSL and no override set', () => {
39
+ delete process.env.GODOT_HOST;
40
+ vi.mocked(wslDetection.isWSL).mockReturnValue(false);
41
+ expect(getHostIpInWSL()).toBeNull();
42
+ });
43
+ it('returns null on second call (uses cache)', () => {
44
+ delete process.env.GODOT_HOST;
45
+ vi.mocked(wslDetection.isWSL).mockReturnValue(false);
46
+ expect(getHostIpInWSL()).toBeNull();
47
+ expect(getHostIpInWSL()).toBeNull();
48
+ expect(vi.mocked(wslDetection.isWSL)).toHaveBeenCalledTimes(1);
49
+ });
50
+ it('returns cached host IP on second call', () => {
51
+ vi.mocked(wslDetection.isWSL).mockReturnValue(true);
52
+ vi.mocked(gatewayResolver.resolveGateway).mockReturnValue({
53
+ environment: 'wsl2',
54
+ gatewayIp: '192.168.1.1',
55
+ });
56
+ expect(getHostIpInWSL()).toBe('192.168.1.1');
57
+ expect(vi.mocked(gatewayResolver.resolveGateway)).toHaveBeenCalledTimes(1);
58
+ expect(getHostIpInWSL()).toBe('192.168.1.1');
59
+ expect(vi.mocked(gatewayResolver.resolveGateway)).toHaveBeenCalledTimes(1); // No additional call
60
+ });
61
+ it('returns null when gateway resolver returns null', () => {
62
+ delete process.env.GODOT_HOST;
63
+ vi.mocked(wslDetection.isWSL).mockReturnValue(true);
64
+ vi.mocked(gatewayResolver.resolveGateway).mockReturnValue({
65
+ environment: 'wsl2',
66
+ gatewayIp: null,
67
+ });
68
+ expect(getHostIpInWSL()).toBeNull();
69
+ });
70
+ it('returns gateway IP when available in WSL2', () => {
71
+ delete process.env.GODOT_HOST;
72
+ vi.mocked(wslDetection.isWSL).mockReturnValue(true);
73
+ vi.mocked(gatewayResolver.resolveGateway).mockReturnValue({
74
+ environment: 'wsl2',
75
+ gatewayIp: '192.168.1.1',
76
+ });
77
+ expect(getHostIpInWSL()).toBe('192.168.1.1');
78
+ });
79
+ it('returns null for WSL1 (no gateway IP)', () => {
80
+ delete process.env.GODOT_HOST;
81
+ vi.mocked(wslDetection.isWSL).mockReturnValue(true);
82
+ vi.mocked(gatewayResolver.resolveGateway).mockReturnValue({
83
+ environment: 'wsl1',
84
+ gatewayIp: null,
85
+ });
86
+ expect(getHostIpInWSL()).toBeNull();
87
+ });
88
+ it('handles gateway resolver errors gracefully', () => {
89
+ delete process.env.GODOT_HOST;
90
+ vi.mocked(wslDetection.isWSL).mockReturnValue(true);
91
+ vi.mocked(gatewayResolver.resolveGateway).mockImplementation(() => {
92
+ throw new Error('Resolution failed');
93
+ });
94
+ expect(getHostIpInWSL()).toBeNull();
95
+ });
96
+ it('supports various valid IPv4 addresses from gateway', () => {
97
+ const validIPs = [
98
+ '0.0.0.0',
99
+ '127.0.0.1',
100
+ '192.168.1.1',
101
+ '255.255.255.255',
102
+ '10.0.0.1',
103
+ ];
104
+ for (const ip of validIPs) {
105
+ _clearHostIpCache();
106
+ vi.mocked(wslDetection.isWSL).mockReturnValue(true);
107
+ vi.mocked(gatewayResolver.resolveGateway).mockReturnValue({
108
+ environment: 'wsl2',
109
+ gatewayIp: ip,
110
+ });
111
+ expect(getHostIpInWSL()).toBe(ip);
112
+ }
113
+ });
114
+ });
115
+ });
116
+ //# sourceMappingURL=host-ip-resolver.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-ip-resolver.test.js","sourceRoot":"","sources":["../../../src/__tests__/utils/host-ip-resolver.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=wsl-detection.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wsl-detection.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/utils/wsl-detection.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,116 @@
1
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
+ import { isWSL } from '../../utils/wsl-detection.js';
3
+ import fs from 'fs';
4
+ import os from 'os';
5
+ vi.mock('fs');
6
+ vi.mock('os');
7
+ describe('wsl-detection', () => {
8
+ beforeEach(() => {
9
+ vi.clearAllMocks();
10
+ // Reset environment
11
+ delete process.env.WSL_DISTRO_NAME;
12
+ delete process.env.WSL_INTEROP;
13
+ });
14
+ afterEach(() => {
15
+ vi.clearAllMocks();
16
+ });
17
+ describe('isWSL()', () => {
18
+ it('returns false on non-Linux platforms', () => {
19
+ const originalPlatform = Object.getOwnPropertyDescriptor(process, 'platform');
20
+ Object.defineProperty(process, 'platform', { value: 'win32', configurable: true });
21
+ try {
22
+ expect(isWSL()).toBe(false);
23
+ }
24
+ finally {
25
+ Object.defineProperty(process, 'platform', originalPlatform || {});
26
+ }
27
+ });
28
+ it('returns false on macOS', () => {
29
+ const originalPlatform = Object.getOwnPropertyDescriptor(process, 'platform');
30
+ Object.defineProperty(process, 'platform', { value: 'darwin', configurable: true });
31
+ try {
32
+ expect(isWSL()).toBe(false);
33
+ }
34
+ finally {
35
+ Object.defineProperty(process, 'platform', originalPlatform || {});
36
+ }
37
+ });
38
+ describe('on Linux platform', () => {
39
+ let originalPlatform;
40
+ beforeEach(() => {
41
+ originalPlatform = Object.getOwnPropertyDescriptor(process, 'platform');
42
+ Object.defineProperty(process, 'platform', { value: 'linux', configurable: true });
43
+ });
44
+ afterEach(() => {
45
+ if (originalPlatform) {
46
+ Object.defineProperty(process, 'platform', originalPlatform);
47
+ }
48
+ });
49
+ it('returns true when WSL_DISTRO_NAME env var is set', () => {
50
+ process.env.WSL_DISTRO_NAME = 'Ubuntu';
51
+ expect(isWSL()).toBe(true);
52
+ });
53
+ it('returns true when WSL_INTEROP env var is set', () => {
54
+ process.env.WSL_INTEROP = '1';
55
+ expect(isWSL()).toBe(true);
56
+ });
57
+ it('returns true when /proc/version contains "microsoft"', () => {
58
+ vi.mocked(fs.readFileSync).mockReturnValue('Linux version 4.19.128-microsoft (oe-user@oe-host) (gcc version 9.3.0 (GCC))');
59
+ expect(isWSL()).toBe(true);
60
+ });
61
+ it('returns true when /proc/version contains "Microsoft" (case-insensitive)', () => {
62
+ vi.mocked(fs.readFileSync).mockReturnValue('Linux version 4.19.128-Microsoft (oe-user@oe-host) (gcc version 9.3.0 (GCC))');
63
+ expect(isWSL()).toBe(true);
64
+ });
65
+ it('returns true when os.release() contains "microsoft"', () => {
66
+ vi.mocked(fs.readFileSync).mockImplementation(() => {
67
+ throw new Error('File not found');
68
+ });
69
+ vi.mocked(os.release).mockReturnValue('4.19.128-microsoft');
70
+ expect(isWSL()).toBe(true);
71
+ });
72
+ it('returns false on native Linux with no WSL indicators', () => {
73
+ vi.mocked(fs.readFileSync).mockReturnValue('Linux version 5.15.0-1234-generic (buildd@lcy02-amd64-001)');
74
+ vi.mocked(os.release).mockReturnValue('5.15.0-1234-generic');
75
+ expect(isWSL()).toBe(false);
76
+ });
77
+ it('returns false when /proc/version throws error and os.release() has no microsoft', () => {
78
+ vi.mocked(fs.readFileSync).mockImplementation(() => {
79
+ throw new Error('Permission denied');
80
+ });
81
+ vi.mocked(os.release).mockReturnValue('5.15.0-generic');
82
+ expect(isWSL()).toBe(false);
83
+ });
84
+ it('uses env var as fast path and skips file checks', () => {
85
+ process.env.WSL_DISTRO_NAME = 'Ubuntu';
86
+ expect(isWSL()).toBe(true);
87
+ expect(vi.mocked(fs.readFileSync)).not.toHaveBeenCalled();
88
+ });
89
+ it('falls back to /proc/version when env vars not set', () => {
90
+ vi.mocked(fs.readFileSync).mockReturnValue('Linux version 4.19.128-microsoft (oe-user@oe-host)');
91
+ expect(isWSL()).toBe(true);
92
+ expect(vi.mocked(fs.readFileSync)).toHaveBeenCalledWith('/proc/version', 'utf8');
93
+ });
94
+ it('falls back to os.release() when /proc/version not readable', () => {
95
+ vi.mocked(fs.readFileSync).mockImplementation(() => {
96
+ throw new Error('File not found');
97
+ });
98
+ vi.mocked(os.release).mockReturnValue('4.19.128-microsoft');
99
+ expect(isWSL()).toBe(true);
100
+ expect(vi.mocked(os.release)).toHaveBeenCalled();
101
+ });
102
+ it('handles case-insensitive matching for /proc/version', () => {
103
+ vi.mocked(fs.readFileSync).mockReturnValue('Linux version 4.19.128-MICROSOFT (oe-user@oe-host)');
104
+ expect(isWSL()).toBe(true);
105
+ });
106
+ it('handles case-insensitive matching for os.release()', () => {
107
+ vi.mocked(fs.readFileSync).mockImplementation(() => {
108
+ throw new Error('File not found');
109
+ });
110
+ vi.mocked(os.release).mockReturnValue('5.10.16.3-MICROSOFT-standard');
111
+ expect(isWSL()).toBe(true);
112
+ });
113
+ });
114
+ });
115
+ });
116
+ //# sourceMappingURL=wsl-detection.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wsl-detection.test.js","sourceRoot":"","sources":["../../../src/__tests__/utils/wsl-detection.test.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,7 @@ export interface ConnectionDiagnostics {
7
7
  reconnectAttempts: number;
8
8
  lastErrorMessage: string | null;
9
9
  url: string;
10
+ environment: 'wsl' | 'native';
10
11
  }
11
12
  export type HandshakeStatus = 'pending' | 'success' | 'failed' | 'timeout';
12
13
  export interface HandshakeResult {
@@ -35,11 +36,12 @@ export declare class GodotConnection extends EventEmitter {
35
36
  private lastErrorMessage;
36
37
  private currentState;
37
38
  private readonly host;
38
- private readonly port;
39
+ private readonly _port;
39
40
  private readonly autoReconnect;
40
41
  constructor(options?: GodotConnectionOptions);
41
42
  get isConnected(): boolean;
42
43
  get url(): string;
44
+ get port(): number;
43
45
  get addonVersion(): string | null;
44
46
  get projectPath(): string | null;
45
47
  get projectName(): string | null;
@@ -1 +1 @@
1
- {"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../../src/connection/websocket.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AA2BtC,MAAM,MAAM,gBAAgB,GACxB,iBAAiB,GACjB,yBAAyB,GACzB,oBAAoB,GACpB,iBAAiB,GACjB,iBAAiB,GACjB,OAAO,CAAC;AAEZ,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,WAAW,GAAG,cAAc,GAAG,YAAY,GAAG,cAAc,CAAC;IAC3E,oBAAoB,EAAE,gBAAgB,CAAC;IACvC,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE3E,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,eAAe,CAAC;CAClC;AAQD,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,eAAe,CAA0C;IACjE,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,gBAAgB,CAA+B;IACvD,OAAO,CAAC,YAAY,CAA+B;IACnD,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,eAAe,CAAgC;IAEvD,OAAO,CAAC,oBAAoB,CAAuC;IACnE,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,YAAY,CAAgF;IAEpG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;gBAE5B,OAAO,GAAE,sBAA2B;IAOhD,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,IAAI,GAAG,IAAI,MAAM,CAEhB;IAED,IAAI,YAAY,IAAI,MAAM,GAAG,IAAI,CAEhC;IAED,IAAI,WAAW,IAAI,MAAM,GAAG,IAAI,CAE/B;IAED,IAAI,WAAW,IAAI,MAAM,GAAG,IAAI,CAE/B;IAED,IAAI,YAAY,IAAI,MAAM,GAAG,IAAI,CAEhC;IAED,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED,IAAI,aAAa,IAAI,OAAO,CAG3B;IAED,cAAc,IAAI,qBAAqB;IAWvC,oBAAoB,IAAI,MAAM;IAgDxB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAgF9B,UAAU,IAAI,IAAI;IAWZ,WAAW,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,OAAO,CAAC,CAAC,CAAC;YAwBnF,gBAAgB;IAqD9B,OAAO,CAAC,aAAa;IA2CrB,OAAO,CAAC,iBAAiB;IAazB,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,gBAAgB;IAOxB,OAAO,CAAC,iBAAiB;IAwBzB,OAAO,CAAC,OAAO;CAehB;AAmBD,wBAAgB,kBAAkB,IAAI,eAAe,CAQpD;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CA0C1D"}
1
+ {"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../../src/connection/websocket.ts"],"names":[],"mappings":"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"}