@satelliteoflove/godot-mcp 2.16.1 → 2.17.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/addon/command_router.gd +1 -0
- package/addon/commands/debug_commands.gd +0 -36
- package/addon/commands/profiler_commands.gd +143 -0
- package/addon/core/mcp_debugger_plugin.gd +52 -0
- package/addon/game_bridge/mcp_frame_profiler.gd +61 -0
- package/addon/game_bridge/mcp_game_bridge.gd +170 -0
- package/addon/plugin.cfg +1 -1
- package/dist/__tests__/tools/profiler-actions.test.d.ts +2 -0
- package/dist/__tests__/tools/profiler-actions.test.d.ts.map +1 -0
- package/dist/__tests__/tools/profiler-actions.test.js +95 -0
- package/dist/__tests__/tools/profiler-actions.test.js.map +1 -0
- package/dist/__tests__/tools/profiler.test.d.ts +2 -0
- package/dist/__tests__/tools/profiler.test.d.ts.map +1 -0
- package/dist/__tests__/tools/profiler.test.js +163 -0
- package/dist/__tests__/tools/profiler.test.js.map +1 -0
- package/dist/tools/editor.d.ts.map +1 -1
- package/dist/tools/editor.js +2 -1
- package/dist/tools/editor.js.map +1 -1
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +3 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/profiler.d.ts +54 -0
- package/dist/tools/profiler.d.ts.map +1 -0
- package/dist/tools/profiler.js +204 -0
- package/dist/tools/profiler.js.map +1 -0
- package/package.json +1 -1
package/addon/command_router.gd
CHANGED
|
@@ -20,6 +20,7 @@ func setup(plugin: EditorPlugin) -> void:
|
|
|
20
20
|
_register_handler(MCPResourceCommands.new(), plugin)
|
|
21
21
|
_register_handler(MCPScene3DCommands.new(), plugin)
|
|
22
22
|
_register_handler(MCPInputCommands.new(), plugin)
|
|
23
|
+
_register_handler(MCPProfilerCommands.new(), plugin)
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
func _register_handler(handler: MCPBaseCommand, plugin: EditorPlugin) -> void:
|
|
@@ -3,21 +3,16 @@ extends MCPBaseCommand
|
|
|
3
3
|
class_name MCPDebugCommands
|
|
4
4
|
|
|
5
5
|
const DEBUG_OUTPUT_TIMEOUT := 5.0
|
|
6
|
-
const PERFORMANCE_METRICS_TIMEOUT := 5.0
|
|
7
6
|
|
|
8
7
|
var _debug_output_result: PackedStringArray = []
|
|
9
8
|
var _debug_output_pending: bool = false
|
|
10
9
|
|
|
11
|
-
var _performance_metrics_result: Dictionary = {}
|
|
12
|
-
var _performance_metrics_pending: bool = false
|
|
13
|
-
|
|
14
10
|
|
|
15
11
|
func get_commands() -> Dictionary:
|
|
16
12
|
return {
|
|
17
13
|
"run_project": run_project,
|
|
18
14
|
"stop_project": stop_project,
|
|
19
15
|
"get_debug_output": get_debug_output,
|
|
20
|
-
"get_performance_metrics": get_performance_metrics,
|
|
21
16
|
"get_log_messages": get_log_messages,
|
|
22
17
|
"get_errors": get_errors,
|
|
23
18
|
"get_stack_trace": get_stack_trace,
|
|
@@ -100,37 +95,6 @@ func _on_debug_output_received(output: PackedStringArray) -> void:
|
|
|
100
95
|
_debug_output_result = output
|
|
101
96
|
|
|
102
97
|
|
|
103
|
-
func get_performance_metrics(_params: Dictionary) -> Dictionary:
|
|
104
|
-
if not EditorInterface.is_playing_scene():
|
|
105
|
-
return _error("NOT_RUNNING", "No game is currently running")
|
|
106
|
-
|
|
107
|
-
var debugger_plugin = _plugin.get_debugger_plugin() if _plugin else null
|
|
108
|
-
if debugger_plugin == null or not debugger_plugin.has_active_session():
|
|
109
|
-
return _error("NO_SESSION", "No active debug session")
|
|
110
|
-
|
|
111
|
-
_performance_metrics_pending = true
|
|
112
|
-
_performance_metrics_result = {}
|
|
113
|
-
|
|
114
|
-
debugger_plugin.performance_metrics_received.connect(_on_performance_metrics_received, CONNECT_ONE_SHOT)
|
|
115
|
-
debugger_plugin.request_performance_metrics()
|
|
116
|
-
|
|
117
|
-
var start_time := Time.get_ticks_msec()
|
|
118
|
-
while _performance_metrics_pending:
|
|
119
|
-
await Engine.get_main_loop().process_frame
|
|
120
|
-
if (Time.get_ticks_msec() - start_time) / 1000.0 > PERFORMANCE_METRICS_TIMEOUT:
|
|
121
|
-
_performance_metrics_pending = false
|
|
122
|
-
if debugger_plugin.performance_metrics_received.is_connected(_on_performance_metrics_received):
|
|
123
|
-
debugger_plugin.performance_metrics_received.disconnect(_on_performance_metrics_received)
|
|
124
|
-
return _error("TIMEOUT", "Timed out waiting for performance metrics")
|
|
125
|
-
|
|
126
|
-
return _success(_performance_metrics_result)
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
func _on_performance_metrics_received(metrics: Dictionary) -> void:
|
|
130
|
-
_performance_metrics_pending = false
|
|
131
|
-
_performance_metrics_result = metrics
|
|
132
|
-
|
|
133
|
-
|
|
134
98
|
func get_log_messages(params: Dictionary) -> Dictionary:
|
|
135
99
|
var clear: bool = params.get("clear", false)
|
|
136
100
|
var limit: int = params.get("limit", 50)
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
@tool
|
|
2
|
+
extends MCPBaseCommand
|
|
3
|
+
class_name MCPProfilerCommands
|
|
4
|
+
|
|
5
|
+
const PROFILER_TIMEOUT := 5.0
|
|
6
|
+
const GENERIC_TIMEOUT := 5.0
|
|
7
|
+
|
|
8
|
+
var _performance_metrics_pending: bool = false
|
|
9
|
+
var _performance_metrics_result: Dictionary = {}
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
func get_commands() -> Dictionary:
|
|
13
|
+
return {
|
|
14
|
+
"get_performance_metrics": get_performance_metrics,
|
|
15
|
+
"start_profiler": start_profiler,
|
|
16
|
+
"stop_profiler": stop_profiler,
|
|
17
|
+
"get_profiler_data": get_profiler_data,
|
|
18
|
+
"get_active_processes": get_active_processes,
|
|
19
|
+
"get_signal_connections": get_signal_connections,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
func get_performance_metrics(_params: Dictionary) -> Dictionary:
|
|
24
|
+
if not EditorInterface.is_playing_scene():
|
|
25
|
+
return _error("NOT_RUNNING", "No game is currently running")
|
|
26
|
+
|
|
27
|
+
var debugger_plugin = _plugin.get_debugger_plugin() if _plugin else null
|
|
28
|
+
if debugger_plugin == null or not debugger_plugin.has_active_session():
|
|
29
|
+
return _error("NO_SESSION", "No active debug session")
|
|
30
|
+
|
|
31
|
+
_performance_metrics_pending = true
|
|
32
|
+
_performance_metrics_result = {}
|
|
33
|
+
|
|
34
|
+
debugger_plugin.performance_metrics_received.connect(_on_performance_metrics_received, CONNECT_ONE_SHOT)
|
|
35
|
+
debugger_plugin.request_performance_metrics()
|
|
36
|
+
|
|
37
|
+
var start_time := Time.get_ticks_msec()
|
|
38
|
+
while _performance_metrics_pending:
|
|
39
|
+
await Engine.get_main_loop().process_frame
|
|
40
|
+
if (Time.get_ticks_msec() - start_time) / 1000.0 > PROFILER_TIMEOUT:
|
|
41
|
+
_performance_metrics_pending = false
|
|
42
|
+
if debugger_plugin.performance_metrics_received.is_connected(_on_performance_metrics_received):
|
|
43
|
+
debugger_plugin.performance_metrics_received.disconnect(_on_performance_metrics_received)
|
|
44
|
+
return _error("TIMEOUT", "Timed out waiting for performance metrics")
|
|
45
|
+
|
|
46
|
+
return _success(_performance_metrics_result)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
func _on_performance_metrics_received(metrics: Dictionary) -> void:
|
|
50
|
+
_performance_metrics_pending = false
|
|
51
|
+
_performance_metrics_result = metrics
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
func start_profiler(_params: Dictionary) -> Dictionary:
|
|
55
|
+
if not EditorInterface.is_playing_scene():
|
|
56
|
+
return _error("NOT_RUNNING", "No game is currently running")
|
|
57
|
+
|
|
58
|
+
var debugger_plugin = _plugin.get_debugger_plugin() if _plugin else null
|
|
59
|
+
if debugger_plugin == null or not debugger_plugin.has_active_session():
|
|
60
|
+
return _error("NO_SESSION", "No active debug session")
|
|
61
|
+
|
|
62
|
+
debugger_plugin.toggle_frame_profiler(true)
|
|
63
|
+
return _success({"message": "Frame profiler started"})
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
func stop_profiler(_params: Dictionary) -> Dictionary:
|
|
67
|
+
if not EditorInterface.is_playing_scene():
|
|
68
|
+
return _error("NOT_RUNNING", "No game is currently running")
|
|
69
|
+
|
|
70
|
+
var debugger_plugin = _plugin.get_debugger_plugin() if _plugin else null
|
|
71
|
+
if debugger_plugin == null or not debugger_plugin.has_active_session():
|
|
72
|
+
return _error("NO_SESSION", "No active debug session")
|
|
73
|
+
|
|
74
|
+
debugger_plugin.toggle_frame_profiler(false)
|
|
75
|
+
return _success({"message": "Frame profiler stopped"})
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
func get_profiler_data(_params: Dictionary) -> Dictionary:
|
|
79
|
+
var result = await _send_and_wait("get_profiler_data")
|
|
80
|
+
if result == null:
|
|
81
|
+
return _last_error
|
|
82
|
+
var result_dict: Dictionary
|
|
83
|
+
if result is Dictionary:
|
|
84
|
+
result_dict = result
|
|
85
|
+
else:
|
|
86
|
+
result_dict = {"data": result}
|
|
87
|
+
return _success(result_dict)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
func get_active_processes(_params: Dictionary) -> Dictionary:
|
|
91
|
+
var result = await _send_and_wait("get_active_processes")
|
|
92
|
+
if result == null:
|
|
93
|
+
return _last_error
|
|
94
|
+
var result_dict: Dictionary
|
|
95
|
+
if result is Dictionary:
|
|
96
|
+
result_dict = result
|
|
97
|
+
else:
|
|
98
|
+
result_dict = {"data": result}
|
|
99
|
+
return _success(result_dict)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
func get_signal_connections(params: Dictionary) -> Dictionary:
|
|
103
|
+
var node_path: String = params.get("node_path", "")
|
|
104
|
+
var result = await _send_and_wait("get_signal_connections", [node_path])
|
|
105
|
+
if result == null:
|
|
106
|
+
return _last_error
|
|
107
|
+
var result_dict: Dictionary
|
|
108
|
+
if result is Dictionary:
|
|
109
|
+
result_dict = result
|
|
110
|
+
else:
|
|
111
|
+
result_dict = {"data": result}
|
|
112
|
+
return _success(result_dict)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
var _last_error: Dictionary = {}
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
func _send_and_wait(msg_type: String, args: Array = []):
|
|
119
|
+
if not EditorInterface.is_playing_scene():
|
|
120
|
+
_last_error = _error("NOT_RUNNING", "No game is currently running")
|
|
121
|
+
return null
|
|
122
|
+
|
|
123
|
+
var debugger_plugin = _plugin.get_debugger_plugin() if _plugin else null
|
|
124
|
+
if debugger_plugin == null or not debugger_plugin.has_active_session():
|
|
125
|
+
_last_error = _error("NO_SESSION", "No active debug session")
|
|
126
|
+
return null
|
|
127
|
+
|
|
128
|
+
var sent: bool = debugger_plugin.send_game_message(msg_type, args)
|
|
129
|
+
if not sent:
|
|
130
|
+
_last_error = _error("SEND_FAILED", "Failed to send message to game")
|
|
131
|
+
return null
|
|
132
|
+
|
|
133
|
+
var start_time := Time.get_ticks_msec()
|
|
134
|
+
while not debugger_plugin.has_response(msg_type):
|
|
135
|
+
await Engine.get_main_loop().process_frame
|
|
136
|
+
if (Time.get_ticks_msec() - start_time) / 1000.0 > GENERIC_TIMEOUT:
|
|
137
|
+
debugger_plugin.clear_response(msg_type)
|
|
138
|
+
_last_error = _error("TIMEOUT", "Timed out waiting for %s response" % msg_type)
|
|
139
|
+
return null
|
|
140
|
+
|
|
141
|
+
var response = debugger_plugin.get_response(msg_type)
|
|
142
|
+
debugger_plugin.clear_response(msg_type)
|
|
143
|
+
return response
|
|
@@ -9,6 +9,7 @@ signal find_nodes_received(matches: Array, count: int, error: String)
|
|
|
9
9
|
signal input_map_received(actions: Array, error: String)
|
|
10
10
|
signal input_sequence_completed(result: Dictionary)
|
|
11
11
|
signal type_text_completed(result: Dictionary)
|
|
12
|
+
signal game_response(message_type: String, data: Variant)
|
|
12
13
|
|
|
13
14
|
var _active_session_id: int = -1
|
|
14
15
|
var _pending_screenshot: bool = false
|
|
@@ -18,6 +19,8 @@ var _pending_find_nodes: bool = false
|
|
|
18
19
|
var _pending_input_map: bool = false
|
|
19
20
|
var _pending_input_sequence: bool = false
|
|
20
21
|
var _pending_type_text: bool = false
|
|
22
|
+
var _pending_requests: Dictionary = {}
|
|
23
|
+
var _responses: Dictionary = {}
|
|
21
24
|
|
|
22
25
|
|
|
23
26
|
func _has_capture(prefix: String) -> bool:
|
|
@@ -47,6 +50,9 @@ func _capture(message: String, data: Array, session_id: int) -> bool:
|
|
|
47
50
|
"godot_mcp:type_text_result":
|
|
48
51
|
_handle_type_text_result(data)
|
|
49
52
|
return true
|
|
53
|
+
"godot_mcp:game_response":
|
|
54
|
+
_handle_game_response(data)
|
|
55
|
+
return true
|
|
50
56
|
return false
|
|
51
57
|
|
|
52
58
|
|
|
@@ -77,6 +83,9 @@ func _session_stopped() -> void:
|
|
|
77
83
|
if _pending_type_text:
|
|
78
84
|
_pending_type_text = false
|
|
79
85
|
type_text_completed.emit({"error": "Game session ended"})
|
|
86
|
+
for msg_type in _pending_requests:
|
|
87
|
+
_responses[msg_type] = {}
|
|
88
|
+
_pending_requests.clear()
|
|
80
89
|
|
|
81
90
|
|
|
82
91
|
func has_active_session() -> bool:
|
|
@@ -229,3 +238,46 @@ func _handle_type_text_result(data: Array) -> void:
|
|
|
229
238
|
_pending_type_text = false
|
|
230
239
|
var result: Dictionary = data[0] if data.size() > 0 else {}
|
|
231
240
|
type_text_completed.emit(result)
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
func send_game_message(msg_type: String, args: Array = []) -> bool:
|
|
244
|
+
if _active_session_id < 0:
|
|
245
|
+
return false
|
|
246
|
+
var session := get_session(_active_session_id)
|
|
247
|
+
if not session:
|
|
248
|
+
return false
|
|
249
|
+
_pending_requests[msg_type] = true
|
|
250
|
+
_responses.erase(msg_type)
|
|
251
|
+
session.send_message("godot_mcp:" + msg_type, args)
|
|
252
|
+
return true
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
func has_response(msg_type: String) -> bool:
|
|
256
|
+
return _responses.has(msg_type)
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
func get_response(msg_type: String) -> Variant:
|
|
260
|
+
return _responses.get(msg_type)
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
func clear_response(msg_type: String) -> void:
|
|
264
|
+
_responses.erase(msg_type)
|
|
265
|
+
_pending_requests.erase(msg_type)
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
func _handle_game_response(data: Array) -> void:
|
|
269
|
+
if data.size() < 2:
|
|
270
|
+
return
|
|
271
|
+
var msg_type: String = data[0]
|
|
272
|
+
var response_data: Variant = data[1]
|
|
273
|
+
_pending_requests.erase(msg_type)
|
|
274
|
+
_responses[msg_type] = response_data
|
|
275
|
+
game_response.emit(msg_type, response_data)
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
func toggle_frame_profiler(enable: bool) -> void:
|
|
279
|
+
if _active_session_id < 0:
|
|
280
|
+
return
|
|
281
|
+
var session := get_session(_active_session_id)
|
|
282
|
+
if session:
|
|
283
|
+
session.toggle_profiler("mcp_frame_profiler", enable)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
extends EngineProfiler
|
|
2
|
+
class_name MCPFrameProfiler
|
|
3
|
+
|
|
4
|
+
const MAX_FRAMES := 300
|
|
5
|
+
const MONITOR_SAMPLE_INTERVAL := 10
|
|
6
|
+
|
|
7
|
+
var _active := false
|
|
8
|
+
var _buffer: Array[Dictionary] = []
|
|
9
|
+
var _frame_index := 0
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
func _toggle(enable: bool, _options: Array) -> void:
|
|
13
|
+
_active = enable
|
|
14
|
+
if enable:
|
|
15
|
+
_buffer.clear()
|
|
16
|
+
_frame_index = 0
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
func _tick(frame_time: float, process_time: float, physics_time: float, physics_frame_time: float) -> void:
|
|
20
|
+
if not _active:
|
|
21
|
+
return
|
|
22
|
+
|
|
23
|
+
var entry := {
|
|
24
|
+
"ft": frame_time,
|
|
25
|
+
"pt": process_time,
|
|
26
|
+
"pht": physics_time,
|
|
27
|
+
"pft": physics_frame_time,
|
|
28
|
+
"i": _frame_index,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if _frame_index % MONITOR_SAMPLE_INTERVAL == 0:
|
|
32
|
+
entry["m"] = _snapshot_monitors()
|
|
33
|
+
|
|
34
|
+
_buffer.append(entry)
|
|
35
|
+
if _buffer.size() > MAX_FRAMES:
|
|
36
|
+
_buffer.pop_front()
|
|
37
|
+
|
|
38
|
+
_frame_index += 1
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
func get_buffer_data() -> Dictionary:
|
|
42
|
+
return {
|
|
43
|
+
"active": _active,
|
|
44
|
+
"frame_count": _buffer.size(),
|
|
45
|
+
"total_frames_collected": _frame_index,
|
|
46
|
+
"max_fps": Engine.max_fps,
|
|
47
|
+
"frames": _buffer.duplicate(),
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
func _snapshot_monitors() -> Dictionary:
|
|
52
|
+
return {
|
|
53
|
+
"fps": Performance.get_monitor(Performance.TIME_FPS),
|
|
54
|
+
"obj_count": int(Performance.get_monitor(Performance.OBJECT_COUNT)),
|
|
55
|
+
"node_count": int(Performance.get_monitor(Performance.OBJECT_NODE_COUNT)),
|
|
56
|
+
"orphan_nodes": int(Performance.get_monitor(Performance.OBJECT_ORPHAN_NODE_COUNT)),
|
|
57
|
+
"mem_static": int(Performance.get_monitor(Performance.MEMORY_STATIC)),
|
|
58
|
+
"render_objects": int(Performance.get_monitor(Performance.RENDER_TOTAL_OBJECTS_IN_FRAME)),
|
|
59
|
+
"render_draw_calls": int(Performance.get_monitor(Performance.RENDER_TOTAL_DRAW_CALLS_IN_FRAME)),
|
|
60
|
+
"render_primitives": int(Performance.get_monitor(Performance.RENDER_TOTAL_PRIMITIVES_IN_FRAME)),
|
|
61
|
+
}
|
|
@@ -4,6 +4,7 @@ class_name MCPGameBridge
|
|
|
4
4
|
const DEFAULT_MAX_WIDTH := 1920
|
|
5
5
|
|
|
6
6
|
var _logger: _MCPGameLogger
|
|
7
|
+
var _profiler: MCPFrameProfiler
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
func _ready() -> void:
|
|
@@ -11,6 +12,8 @@ func _ready() -> void:
|
|
|
11
12
|
return
|
|
12
13
|
_logger = _MCPGameLogger.new()
|
|
13
14
|
OS.add_logger(_logger)
|
|
15
|
+
_profiler = MCPFrameProfiler.new()
|
|
16
|
+
EngineDebugger.register_profiler("mcp_frame_profiler", _profiler)
|
|
14
17
|
EngineDebugger.register_message_capture("godot_mcp", _on_debugger_message)
|
|
15
18
|
MCPLog.info("Game bridge initialized")
|
|
16
19
|
|
|
@@ -18,6 +21,8 @@ func _ready() -> void:
|
|
|
18
21
|
func _exit_tree() -> void:
|
|
19
22
|
if EngineDebugger.is_active():
|
|
20
23
|
EngineDebugger.unregister_message_capture("godot_mcp")
|
|
24
|
+
if _profiler:
|
|
25
|
+
EngineDebugger.unregister_profiler("mcp_frame_profiler")
|
|
21
26
|
|
|
22
27
|
|
|
23
28
|
func _process(_delta: float) -> void:
|
|
@@ -75,6 +80,15 @@ func _on_debugger_message(message: String, data: Array) -> bool:
|
|
|
75
80
|
"type_text":
|
|
76
81
|
_handle_type_text(data)
|
|
77
82
|
return true
|
|
83
|
+
"get_profiler_data":
|
|
84
|
+
_handle_get_profiler_data()
|
|
85
|
+
return true
|
|
86
|
+
"get_active_processes":
|
|
87
|
+
_handle_get_active_processes()
|
|
88
|
+
return true
|
|
89
|
+
"get_signal_connections":
|
|
90
|
+
_handle_get_signal_connections(data)
|
|
91
|
+
return true
|
|
78
92
|
return false
|
|
79
93
|
|
|
80
94
|
|
|
@@ -191,19 +205,175 @@ func _handle_get_performance_metrics() -> void:
|
|
|
191
205
|
"render_objects": int(Performance.get_monitor(Performance.RENDER_TOTAL_OBJECTS_IN_FRAME)),
|
|
192
206
|
"render_draw_calls": int(Performance.get_monitor(Performance.RENDER_TOTAL_DRAW_CALLS_IN_FRAME)),
|
|
193
207
|
"render_primitives": int(Performance.get_monitor(Performance.RENDER_TOTAL_PRIMITIVES_IN_FRAME)),
|
|
208
|
+
"render_video_mem": int(Performance.get_monitor(Performance.RENDER_VIDEO_MEM_USED)),
|
|
209
|
+
"render_texture_mem": int(Performance.get_monitor(Performance.RENDER_TEXTURE_MEM_USED)),
|
|
210
|
+
"render_buffer_mem": int(Performance.get_monitor(Performance.RENDER_BUFFER_MEM_USED)),
|
|
194
211
|
"physics_2d_active_objects": int(Performance.get_monitor(Performance.PHYSICS_2D_ACTIVE_OBJECTS)),
|
|
195
212
|
"physics_2d_collision_pairs": int(Performance.get_monitor(Performance.PHYSICS_2D_COLLISION_PAIRS)),
|
|
196
213
|
"physics_2d_island_count": int(Performance.get_monitor(Performance.PHYSICS_2D_ISLAND_COUNT)),
|
|
214
|
+
"physics_3d_active_objects": int(Performance.get_monitor(Performance.PHYSICS_3D_ACTIVE_OBJECTS)),
|
|
215
|
+
"physics_3d_collision_pairs": int(Performance.get_monitor(Performance.PHYSICS_3D_COLLISION_PAIRS)),
|
|
216
|
+
"physics_3d_island_count": int(Performance.get_monitor(Performance.PHYSICS_3D_ISLAND_COUNT)),
|
|
217
|
+
"audio_output_latency": Performance.get_monitor(Performance.AUDIO_OUTPUT_LATENCY),
|
|
197
218
|
"object_count": int(Performance.get_monitor(Performance.OBJECT_COUNT)),
|
|
198
219
|
"object_resource_count": int(Performance.get_monitor(Performance.OBJECT_RESOURCE_COUNT)),
|
|
199
220
|
"object_node_count": int(Performance.get_monitor(Performance.OBJECT_NODE_COUNT)),
|
|
200
221
|
"object_orphan_node_count": int(Performance.get_monitor(Performance.OBJECT_ORPHAN_NODE_COUNT)),
|
|
201
222
|
"memory_static": int(Performance.get_monitor(Performance.MEMORY_STATIC)),
|
|
202
223
|
"memory_static_max": int(Performance.get_monitor(Performance.MEMORY_STATIC_MAX)),
|
|
224
|
+
"memory_msg_buffer_max": int(Performance.get_monitor(Performance.MEMORY_MESSAGE_BUFFER_MAX)),
|
|
225
|
+
"navigation_active_maps": int(Performance.get_monitor(Performance.NAVIGATION_ACTIVE_MAPS)),
|
|
226
|
+
"navigation_region_count": int(Performance.get_monitor(Performance.NAVIGATION_REGION_COUNT)),
|
|
227
|
+
"navigation_agent_count": int(Performance.get_monitor(Performance.NAVIGATION_AGENT_COUNT)),
|
|
228
|
+
"navigation_link_count": int(Performance.get_monitor(Performance.NAVIGATION_LINK_COUNT)),
|
|
229
|
+
"navigation_polygon_count": int(Performance.get_monitor(Performance.NAVIGATION_POLYGON_COUNT)),
|
|
230
|
+
"navigation_edge_count": int(Performance.get_monitor(Performance.NAVIGATION_EDGE_COUNT)),
|
|
231
|
+
"navigation_edge_merge_count": int(Performance.get_monitor(Performance.NAVIGATION_EDGE_MERGE_COUNT)),
|
|
232
|
+
"navigation_edge_connection_count": int(Performance.get_monitor(Performance.NAVIGATION_EDGE_CONNECTION_COUNT)),
|
|
233
|
+
"navigation_edge_free_count": int(Performance.get_monitor(Performance.NAVIGATION_EDGE_FREE_COUNT)),
|
|
234
|
+
"navigation_obstacle_count": int(Performance.get_monitor(Performance.NAVIGATION_OBSTACLE_COUNT)),
|
|
235
|
+
"pipeline_compilations_canvas": int(Performance.get_monitor(Performance.PIPELINE_COMPILATIONS_CANVAS)),
|
|
236
|
+
"pipeline_compilations_mesh": int(Performance.get_monitor(Performance.PIPELINE_COMPILATIONS_MESH)),
|
|
237
|
+
"pipeline_compilations_surface": int(Performance.get_monitor(Performance.PIPELINE_COMPILATIONS_SURFACE)),
|
|
238
|
+
"pipeline_compilations_draw": int(Performance.get_monitor(Performance.PIPELINE_COMPILATIONS_DRAW)),
|
|
239
|
+
"pipeline_compilations_specialization": int(Performance.get_monitor(Performance.PIPELINE_COMPILATIONS_SPECIALIZATION)),
|
|
203
240
|
}
|
|
241
|
+
|
|
242
|
+
var rid := get_viewport().get_viewport_rid()
|
|
243
|
+
metrics["viewport_render_cpu_ms"] = RenderingServer.viewport_get_measured_render_time_cpu(rid) + RenderingServer.viewport_get_measured_render_time_gpu(rid)
|
|
244
|
+
metrics["viewport_render_gpu_ms"] = RenderingServer.viewport_get_measured_render_time_gpu(rid)
|
|
245
|
+
|
|
204
246
|
EngineDebugger.send_message("godot_mcp:performance_metrics_result", [metrics])
|
|
205
247
|
|
|
206
248
|
|
|
249
|
+
func _handle_get_profiler_data() -> void:
|
|
250
|
+
var data := _profiler.get_buffer_data() if _profiler else {}
|
|
251
|
+
EngineDebugger.send_message("godot_mcp:game_response", ["get_profiler_data", data])
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
func _handle_get_active_processes() -> void:
|
|
255
|
+
var tree := get_tree()
|
|
256
|
+
var scene_root := tree.current_scene if tree else null
|
|
257
|
+
if not scene_root:
|
|
258
|
+
EngineDebugger.send_message("godot_mcp:game_response", ["get_active_processes", {"processes": []}])
|
|
259
|
+
return
|
|
260
|
+
|
|
261
|
+
var script_map: Dictionary = {}
|
|
262
|
+
_collect_processes(scene_root, scene_root, script_map)
|
|
263
|
+
|
|
264
|
+
var processes: Array = []
|
|
265
|
+
for script_path in script_map:
|
|
266
|
+
processes.append(script_map[script_path])
|
|
267
|
+
|
|
268
|
+
processes.sort_custom(func(a: Dictionary, b: Dictionary) -> bool:
|
|
269
|
+
return a.instance_count > b.instance_count
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
EngineDebugger.send_message("godot_mcp:game_response", ["get_active_processes", {"processes": processes}])
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
func _collect_processes(node: Node, scene_root: Node, script_map: Dictionary) -> void:
|
|
276
|
+
var is_proc := node.is_processing()
|
|
277
|
+
var is_phys := node.is_physics_processing()
|
|
278
|
+
|
|
279
|
+
if is_proc or is_phys:
|
|
280
|
+
var script_path := ""
|
|
281
|
+
var script := node.get_script()
|
|
282
|
+
if script and script is Script:
|
|
283
|
+
script_path = script.resource_path
|
|
284
|
+
if script_path.is_empty():
|
|
285
|
+
script_path = node.get_class()
|
|
286
|
+
|
|
287
|
+
if not script_map.has(script_path):
|
|
288
|
+
script_map[script_path] = {
|
|
289
|
+
"script_path": script_path,
|
|
290
|
+
"has_process": false,
|
|
291
|
+
"has_physics_process": false,
|
|
292
|
+
"instance_count": 0,
|
|
293
|
+
"example_paths": [],
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
var entry: Dictionary = script_map[script_path]
|
|
297
|
+
if is_proc:
|
|
298
|
+
entry.has_process = true
|
|
299
|
+
if is_phys:
|
|
300
|
+
entry.has_physics_process = true
|
|
301
|
+
entry.instance_count += 1
|
|
302
|
+
if entry.example_paths.size() < 3:
|
|
303
|
+
var path := "/root/" + scene_root.name
|
|
304
|
+
var relative := scene_root.get_path_to(node)
|
|
305
|
+
if relative != NodePath("."):
|
|
306
|
+
path += "/" + str(relative)
|
|
307
|
+
entry.example_paths.append(path)
|
|
308
|
+
|
|
309
|
+
for child in node.get_children():
|
|
310
|
+
_collect_processes(child, scene_root, script_map)
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
func _handle_get_signal_connections(data: Array) -> void:
|
|
314
|
+
var node_path: String = data[0] if data.size() > 0 else ""
|
|
315
|
+
|
|
316
|
+
var tree := get_tree()
|
|
317
|
+
var scene_root := tree.current_scene if tree else null
|
|
318
|
+
if not scene_root:
|
|
319
|
+
EngineDebugger.send_message("godot_mcp:game_response", ["get_signal_connections", {"connections": []}])
|
|
320
|
+
return
|
|
321
|
+
|
|
322
|
+
var search_root: Node = scene_root
|
|
323
|
+
if not node_path.is_empty():
|
|
324
|
+
search_root = _get_node_from_path(node_path, scene_root)
|
|
325
|
+
if not search_root:
|
|
326
|
+
EngineDebugger.send_message("godot_mcp:game_response", ["get_signal_connections", {"connections": [], "error": "Node not found: " + node_path}])
|
|
327
|
+
return
|
|
328
|
+
|
|
329
|
+
var connections: Array = []
|
|
330
|
+
_collect_signal_connections(search_root, scene_root, connections, 0)
|
|
331
|
+
|
|
332
|
+
EngineDebugger.send_message("godot_mcp:game_response", ["get_signal_connections", {"connections": connections}])
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
const MAX_SIGNAL_CONNECTIONS := 200
|
|
336
|
+
const MAX_SIGNAL_DEPTH := 20
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
func _collect_signal_connections(node: Node, scene_root: Node, connections: Array, depth: int) -> void:
|
|
340
|
+
if connections.size() >= MAX_SIGNAL_CONNECTIONS or depth > MAX_SIGNAL_DEPTH:
|
|
341
|
+
return
|
|
342
|
+
|
|
343
|
+
var source_path := _node_path_string(node, scene_root)
|
|
344
|
+
|
|
345
|
+
for sig_info in node.get_signal_list():
|
|
346
|
+
var sig_name: String = sig_info.name
|
|
347
|
+
for conn in node.get_signal_connection_list(sig_name):
|
|
348
|
+
if connections.size() >= MAX_SIGNAL_CONNECTIONS:
|
|
349
|
+
return
|
|
350
|
+
var target: Object = conn.callable.get_object()
|
|
351
|
+
var target_path := ""
|
|
352
|
+
if target is Node:
|
|
353
|
+
target_path = _node_path_string(target as Node, scene_root)
|
|
354
|
+
else:
|
|
355
|
+
target_path = str(target)
|
|
356
|
+
connections.append({
|
|
357
|
+
"source_path": source_path,
|
|
358
|
+
"signal_name": sig_name,
|
|
359
|
+
"target_path": target_path,
|
|
360
|
+
"method_name": conn.callable.get_method(),
|
|
361
|
+
})
|
|
362
|
+
|
|
363
|
+
for child in node.get_children():
|
|
364
|
+
if connections.size() >= MAX_SIGNAL_CONNECTIONS:
|
|
365
|
+
return
|
|
366
|
+
_collect_signal_connections(child, scene_root, connections, depth + 1)
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
func _node_path_string(node: Node, scene_root: Node) -> String:
|
|
370
|
+
var path := "/root/" + scene_root.name
|
|
371
|
+
var relative := scene_root.get_path_to(node)
|
|
372
|
+
if relative != NodePath("."):
|
|
373
|
+
path += "/" + str(relative)
|
|
374
|
+
return path
|
|
375
|
+
|
|
376
|
+
|
|
207
377
|
class _MCPGameLogger extends Logger:
|
|
208
378
|
var _output: PackedStringArray = []
|
|
209
379
|
var _max_lines := 1000
|
package/addon/plugin.cfg
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiler-actions.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/tools/profiler-actions.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
2
|
+
import { createMockGodot, createToolContext } from '../helpers/mock-godot.js';
|
|
3
|
+
import { profiler } from '../../tools/profiler.js';
|
|
4
|
+
describe('profiler tool actions', () => {
|
|
5
|
+
let mock;
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
mock = createMockGodot();
|
|
8
|
+
});
|
|
9
|
+
describe('get_active_processes', () => {
|
|
10
|
+
it('returns message when no processes found', async () => {
|
|
11
|
+
mock.mockResponse({ processes: [] });
|
|
12
|
+
const ctx = createToolContext(mock);
|
|
13
|
+
const result = await profiler.execute({ action: 'get_active_processes' }, ctx);
|
|
14
|
+
expect(result).toBe('No active _process or _physics_process functions found');
|
|
15
|
+
});
|
|
16
|
+
it('formats process list with script paths and instance counts', async () => {
|
|
17
|
+
mock.mockResponse({
|
|
18
|
+
processes: [
|
|
19
|
+
{
|
|
20
|
+
script_path: 'res://enemy.gd',
|
|
21
|
+
has_process: true,
|
|
22
|
+
has_physics_process: true,
|
|
23
|
+
instance_count: 5,
|
|
24
|
+
example_paths: ['/root/Main/Enemy1', '/root/Main/Enemy2'],
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
script_path: 'res://player.gd',
|
|
28
|
+
has_process: true,
|
|
29
|
+
has_physics_process: false,
|
|
30
|
+
instance_count: 1,
|
|
31
|
+
example_paths: ['/root/Main/Player'],
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
});
|
|
35
|
+
const ctx = createToolContext(mock);
|
|
36
|
+
const result = await profiler.execute({ action: 'get_active_processes' }, ctx);
|
|
37
|
+
expect(result).toContain('res://enemy.gd');
|
|
38
|
+
expect(result).toContain('_process');
|
|
39
|
+
expect(result).toContain('_physics_process');
|
|
40
|
+
expect(result).toContain('Instances: 5');
|
|
41
|
+
expect(result).toContain('res://player.gd');
|
|
42
|
+
expect(result).toContain('Instances: 1');
|
|
43
|
+
});
|
|
44
|
+
it('sends correct command to Godot', async () => {
|
|
45
|
+
mock.mockResponse({ processes: [] });
|
|
46
|
+
const ctx = createToolContext(mock);
|
|
47
|
+
await profiler.execute({ action: 'get_active_processes' }, ctx);
|
|
48
|
+
expect(mock.calls[0].command).toBe('get_active_processes');
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
describe('get_signal_connections', () => {
|
|
52
|
+
it('returns message when no connections found', async () => {
|
|
53
|
+
mock.mockResponse({ connections: [] });
|
|
54
|
+
const ctx = createToolContext(mock);
|
|
55
|
+
const result = await profiler.execute({ action: 'get_signal_connections' }, ctx);
|
|
56
|
+
expect(result).toBe('No signal connections found');
|
|
57
|
+
});
|
|
58
|
+
it('formats signal connection graph', async () => {
|
|
59
|
+
mock.mockResponse({
|
|
60
|
+
connections: [
|
|
61
|
+
{
|
|
62
|
+
source_path: '/root/Main/Button',
|
|
63
|
+
signal_name: 'pressed',
|
|
64
|
+
target_path: '/root/Main/Player',
|
|
65
|
+
method_name: '_on_button_pressed',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
source_path: '/root/Main/Timer',
|
|
69
|
+
signal_name: 'timeout',
|
|
70
|
+
target_path: '/root/Main/Spawner',
|
|
71
|
+
method_name: '_on_timer_timeout',
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
});
|
|
75
|
+
const ctx = createToolContext(mock);
|
|
76
|
+
const result = await profiler.execute({ action: 'get_signal_connections' }, ctx);
|
|
77
|
+
expect(result).toContain('Signal connections (2)');
|
|
78
|
+
expect(result).toContain('/root/Main/Button.pressed -> /root/Main/Player._on_button_pressed');
|
|
79
|
+
expect(result).toContain('/root/Main/Timer.timeout -> /root/Main/Spawner._on_timer_timeout');
|
|
80
|
+
});
|
|
81
|
+
it('passes node_path parameter to Godot', async () => {
|
|
82
|
+
mock.mockResponse({ connections: [] });
|
|
83
|
+
const ctx = createToolContext(mock);
|
|
84
|
+
await profiler.execute({ action: 'get_signal_connections', node_path: '/root/Main/UI' }, ctx);
|
|
85
|
+
expect(mock.calls[0].params.node_path).toBe('/root/Main/UI');
|
|
86
|
+
});
|
|
87
|
+
it('sends empty string when node_path not provided', async () => {
|
|
88
|
+
mock.mockResponse({ connections: [] });
|
|
89
|
+
const ctx = createToolContext(mock);
|
|
90
|
+
await profiler.execute({ action: 'get_signal_connections' }, ctx);
|
|
91
|
+
expect(mock.calls[0].params.node_path).toBe('');
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
//# sourceMappingURL=profiler-actions.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiler-actions.test.js","sourceRoot":"","sources":["../../../src/__tests__/tools/profiler-actions.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,MAAM,0BAA0B,CAAC;AACnG,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAEnD,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,IAAI,IAAyB,CAAC;IAE9B,UAAU,CAAC,GAAG,EAAE;QACd,IAAI,GAAG,eAAe,EAAE,CAAC;IAC3B,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;QACpC,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;YACvD,IAAI,CAAC,YAAY,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;YACrC,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,sBAAsB,EAAE,EAAE,GAAG,CAAC,CAAC;YAC/E,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,wDAAwD,CAAC,CAAC;QAChF,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;YAC1E,IAAI,CAAC,YAAY,CAAC;gBAChB,SAAS,EAAE;oBACT;wBACE,WAAW,EAAE,gBAAgB;wBAC7B,WAAW,EAAE,IAAI;wBACjB,mBAAmB,EAAE,IAAI;wBACzB,cAAc,EAAE,CAAC;wBACjB,aAAa,EAAE,CAAC,mBAAmB,EAAE,mBAAmB,CAAC;qBAC1D;oBACD;wBACE,WAAW,EAAE,iBAAiB;wBAC9B,WAAW,EAAE,IAAI;wBACjB,mBAAmB,EAAE,KAAK;wBAC1B,cAAc,EAAE,CAAC;wBACjB,aAAa,EAAE,CAAC,mBAAmB,CAAC;qBACrC;iBACF;aACF,CAAC,CAAC;YACH,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,sBAAsB,EAAE,EAAE,GAAG,CAAC,CAAC;YAC/E,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;YAC3C,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;YAC7C,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;YACzC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;YAC5C,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;YAC9C,IAAI,CAAC,YAAY,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;YACrC,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,sBAAsB,EAAE,EAAE,GAAG,CAAC,CAAC;YAChE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QAC7D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;QACtC,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;YACzD,IAAI,CAAC,YAAY,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;YACvC,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,wBAAwB,EAAE,EAAE,GAAG,CAAC,CAAC;YACjF,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;YAC/C,IAAI,CAAC,YAAY,CAAC;gBAChB,WAAW,EAAE;oBACX;wBACE,WAAW,EAAE,mBAAmB;wBAChC,WAAW,EAAE,SAAS;wBACtB,WAAW,EAAE,mBAAmB;wBAChC,WAAW,EAAE,oBAAoB;qBAClC;oBACD;wBACE,WAAW,EAAE,kBAAkB;wBAC/B,WAAW,EAAE,SAAS;wBACtB,WAAW,EAAE,oBAAoB;wBACjC,WAAW,EAAE,mBAAmB;qBACjC;iBACF;aACF,CAAC,CAAC;YACH,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,wBAAwB,EAAE,EAAE,GAAG,CAAC,CAAC;YACjF,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAAC;YACnD,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,mEAAmE,CAAC,CAAC;YAC9F,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,kEAAkE,CAAC,CAAC;QAC/F,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;YACnD,IAAI,CAAC,YAAY,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;YACvC,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,wBAAwB,EAAE,SAAS,EAAE,eAAe,EAAE,EAAE,GAAG,CAAC,CAAC;YAC9F,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC/D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;YAC9D,IAAI,CAAC,YAAY,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;YACvC,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,wBAAwB,EAAE,EAAE,GAAG,CAAC,CAAC;YAClE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiler.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/tools/profiler.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
2
|
+
import { createMockGodot, createToolContext } from '../helpers/mock-godot.js';
|
|
3
|
+
import { profiler, computePercentiles, detectSpikes, computeMonitorTrends, computeFrameBudget } from '../../tools/profiler.js';
|
|
4
|
+
describe('profiler tool', () => {
|
|
5
|
+
let mock;
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
mock = createMockGodot();
|
|
8
|
+
});
|
|
9
|
+
describe('schema validation', () => {
|
|
10
|
+
it('accepts valid actions', () => {
|
|
11
|
+
expect(profiler.schema.safeParse({ action: 'snapshot' }).success).toBe(true);
|
|
12
|
+
expect(profiler.schema.safeParse({ action: 'start' }).success).toBe(true);
|
|
13
|
+
expect(profiler.schema.safeParse({ action: 'stop' }).success).toBe(true);
|
|
14
|
+
expect(profiler.schema.safeParse({ action: 'get_data' }).success).toBe(true);
|
|
15
|
+
expect(profiler.schema.safeParse({ action: 'get_active_processes' }).success).toBe(true);
|
|
16
|
+
});
|
|
17
|
+
it('rejects node_path on non-signal actions', () => {
|
|
18
|
+
expect(profiler.schema.safeParse({ action: 'snapshot', node_path: '/root/Test' }).success).toBe(false);
|
|
19
|
+
});
|
|
20
|
+
it('accepts node_path on get_signal_connections', () => {
|
|
21
|
+
expect(profiler.schema.safeParse({ action: 'get_signal_connections', node_path: '/root/Test' }).success).toBe(true);
|
|
22
|
+
expect(profiler.schema.safeParse({ action: 'get_signal_connections' }).success).toBe(true);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
describe('snapshot', () => {
|
|
26
|
+
it('returns JSON with all performance metrics', async () => {
|
|
27
|
+
const metrics = { fps: 60, frame_time_ms: 16.6, memory_static: 1024 };
|
|
28
|
+
mock.mockResponse(metrics);
|
|
29
|
+
const ctx = createToolContext(mock);
|
|
30
|
+
const result = await profiler.execute({ action: 'snapshot' }, ctx);
|
|
31
|
+
expect(JSON.parse(result)).toEqual(metrics);
|
|
32
|
+
expect(mock.calls[0].command).toBe('get_performance_metrics');
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
describe('start/stop', () => {
|
|
36
|
+
it('returns confirmation messages', async () => {
|
|
37
|
+
const ctx = createToolContext(mock);
|
|
38
|
+
mock.mockResponse({ message: 'Frame profiler started' });
|
|
39
|
+
expect(await profiler.execute({ action: 'start' }, ctx)).toBe('Frame profiler started');
|
|
40
|
+
mock.mockResponse({ message: 'Frame profiler stopped' });
|
|
41
|
+
expect(await profiler.execute({ action: 'stop' }, ctx)).toBe('Frame profiler stopped');
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
describe('get_data', () => {
|
|
45
|
+
it('returns message when no frames collected', async () => {
|
|
46
|
+
mock.mockResponse({ active: false, frame_count: 0, total_frames_collected: 0, frames: [] });
|
|
47
|
+
const ctx = createToolContext(mock);
|
|
48
|
+
const result = await profiler.execute({ action: 'get_data' }, ctx);
|
|
49
|
+
const parsed = JSON.parse(result);
|
|
50
|
+
expect(parsed.frame_count).toBe(0);
|
|
51
|
+
expect(parsed.message).toContain('No frames collected');
|
|
52
|
+
});
|
|
53
|
+
it('computes statistics and spike detection from frame data', async () => {
|
|
54
|
+
const frames = [
|
|
55
|
+
{ ft: 0.016, pt: 0.008, pht: 0.004, pft: 0.004, i: 0, m: { fps: 60 } },
|
|
56
|
+
{ ft: 0.017, pt: 0.009, pht: 0.004, pft: 0.004, i: 1 },
|
|
57
|
+
{ ft: 0.050, pt: 0.030, pht: 0.004, pft: 0.004, i: 2 },
|
|
58
|
+
];
|
|
59
|
+
mock.mockResponse({ active: true, frame_count: 3, total_frames_collected: 3, frames });
|
|
60
|
+
const ctx = createToolContext(mock);
|
|
61
|
+
const result = await profiler.execute({ action: 'get_data' }, ctx);
|
|
62
|
+
const parsed = JSON.parse(result);
|
|
63
|
+
expect(parsed.statistics.frame_time).toBeDefined();
|
|
64
|
+
expect(parsed.statistics.frame_time.avg_ms).toBeGreaterThan(0);
|
|
65
|
+
expect(parsed.frame_budget).toBeDefined();
|
|
66
|
+
expect(parsed.frame_budget.target_fps).toBeGreaterThan(0);
|
|
67
|
+
expect(parsed.frame_budget.budget_usage_percent).toBeGreaterThan(0);
|
|
68
|
+
expect(parsed.physics_tick_ms).toBeDefined();
|
|
69
|
+
expect(parsed.spikes).toBeDefined();
|
|
70
|
+
expect(parsed.spikes.count).toBe(1);
|
|
71
|
+
expect(parsed.monitor_trends).toBeDefined();
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
describe('profiler statistics', () => {
|
|
76
|
+
describe('computePercentiles', () => {
|
|
77
|
+
it('returns zeros for empty array', () => {
|
|
78
|
+
const stats = computePercentiles([]);
|
|
79
|
+
expect(stats.avg_ms).toBe(0);
|
|
80
|
+
expect(stats.min_ms).toBe(0);
|
|
81
|
+
expect(stats.max_ms).toBe(0);
|
|
82
|
+
});
|
|
83
|
+
it('computes correct values for single element', () => {
|
|
84
|
+
const stats = computePercentiles([0.016]);
|
|
85
|
+
expect(stats.avg_ms).toBe(16);
|
|
86
|
+
expect(stats.min_ms).toBe(16);
|
|
87
|
+
expect(stats.max_ms).toBe(16);
|
|
88
|
+
expect(stats.p50_ms).toBe(16);
|
|
89
|
+
});
|
|
90
|
+
it('computes correct percentiles for multiple values', () => {
|
|
91
|
+
const values = [0.010, 0.016, 0.017, 0.020, 0.050];
|
|
92
|
+
const stats = computePercentiles(values);
|
|
93
|
+
expect(stats.avg_ms).toBeGreaterThan(0);
|
|
94
|
+
expect(stats.min_ms).toBe(10);
|
|
95
|
+
expect(stats.max_ms).toBe(50);
|
|
96
|
+
expect(stats.p50_ms).toBe(17);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
describe('detectSpikes', () => {
|
|
100
|
+
it('returns empty array when no spikes', () => {
|
|
101
|
+
const frames = [
|
|
102
|
+
{ ft: 0.016, pt: 0.008, pht: 0.004, pft: 0.004, i: 0 },
|
|
103
|
+
{ ft: 0.017, pt: 0.009, pht: 0.004, pft: 0.004, i: 1 },
|
|
104
|
+
];
|
|
105
|
+
expect(detectSpikes(frames, 0.0165)).toEqual([]);
|
|
106
|
+
});
|
|
107
|
+
it('detects frames exceeding 2x median', () => {
|
|
108
|
+
const frames = [
|
|
109
|
+
{ ft: 0.016, pt: 0.008, pht: 0.004, pft: 0.004, i: 0 },
|
|
110
|
+
{ ft: 0.050, pt: 0.030, pht: 0.004, pft: 0.004, i: 1, m: { fps: 20 } },
|
|
111
|
+
];
|
|
112
|
+
const spikes = detectSpikes(frames, 0.016);
|
|
113
|
+
expect(spikes.length).toBe(1);
|
|
114
|
+
expect(spikes[0].frame_index).toBe(1);
|
|
115
|
+
expect(spikes[0].monitors).toEqual({ fps: 20 });
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
describe('computeFrameBudget', () => {
|
|
119
|
+
it('computes budget stats for 60fps target', () => {
|
|
120
|
+
const frameTime = { avg_ms: 8, min_ms: 7, max_ms: 10, p50_ms: 8, p95_ms: 9, p99_ms: 10 };
|
|
121
|
+
const result = computeFrameBudget(frameTime, 60);
|
|
122
|
+
expect(result.target_fps).toBe(60);
|
|
123
|
+
expect(result.frame_budget_ms).toBeCloseTo(16.7, 1);
|
|
124
|
+
expect(result.actual_fps).toBe(125);
|
|
125
|
+
expect(result.budget_usage_percent).toBeCloseTo(47.9, 0);
|
|
126
|
+
});
|
|
127
|
+
it('handles 30fps target', () => {
|
|
128
|
+
const frameTime = { avg_ms: 30, min_ms: 28, max_ms: 35, p50_ms: 30, p95_ms: 33, p99_ms: 35 };
|
|
129
|
+
const result = computeFrameBudget(frameTime, 30);
|
|
130
|
+
expect(result.target_fps).toBe(30);
|
|
131
|
+
expect(result.frame_budget_ms).toBeCloseTo(33.3, 1);
|
|
132
|
+
expect(result.actual_fps).toBe(33);
|
|
133
|
+
});
|
|
134
|
+
it('handles 120fps target', () => {
|
|
135
|
+
const frameTime = { avg_ms: 7, min_ms: 6, max_ms: 9, p50_ms: 7, p95_ms: 8, p99_ms: 9 };
|
|
136
|
+
const result = computeFrameBudget(frameTime, 120);
|
|
137
|
+
expect(result.target_fps).toBe(120);
|
|
138
|
+
expect(result.frame_budget_ms).toBeCloseTo(8.3, 1);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
describe('computeMonitorTrends', () => {
|
|
142
|
+
it('returns empty for frames without monitors', () => {
|
|
143
|
+
const frames = [{ ft: 0.016, pt: 0.008, pht: 0.004, pft: 0.004, i: 0 }];
|
|
144
|
+
expect(computeMonitorTrends(frames)).toEqual({});
|
|
145
|
+
});
|
|
146
|
+
it('computes start/end/avg/max/change_percent for monitor values', () => {
|
|
147
|
+
const frames = [
|
|
148
|
+
{ ft: 0.016, pt: 0.008, pht: 0.004, pft: 0.004, i: 0, m: { fps: 60, node_count: 100 } },
|
|
149
|
+
{ ft: 0.016, pt: 0.008, pht: 0.004, pft: 0.004, i: 10, m: { fps: 30, node_count: 200 } },
|
|
150
|
+
];
|
|
151
|
+
const trends = computeMonitorTrends(frames);
|
|
152
|
+
expect(trends.fps.start).toBe(60);
|
|
153
|
+
expect(trends.fps.end).toBe(30);
|
|
154
|
+
expect(trends.fps.avg).toBe(45);
|
|
155
|
+
expect(trends.fps.max).toBe(60);
|
|
156
|
+
expect(trends.fps.change_percent).toBe(-50);
|
|
157
|
+
expect(trends.node_count.start).toBe(100);
|
|
158
|
+
expect(trends.node_count.end).toBe(200);
|
|
159
|
+
expect(trends.node_count.change_percent).toBe(100);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
//# sourceMappingURL=profiler.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiler.test.js","sourceRoot":"","sources":["../../../src/__tests__/tools/profiler.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../src/tools/editor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,iBAAiB,EAAyB,MAAM,kBAAkB,CAAC;AAmHjF,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../src/tools/editor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,iBAAiB,EAAyB,MAAM,kBAAkB,CAAC;AAmHjF,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA0IjB,CAAC;AAEH,eAAO,MAAM,WAAW,EAAe,iBAAiB,EAAE,CAAC"}
|
package/dist/tools/editor.js
CHANGED
|
@@ -135,8 +135,9 @@ export const editor = defineTool({
|
|
|
135
135
|
return JSON.stringify(result, null, 2);
|
|
136
136
|
}
|
|
137
137
|
case 'get_performance': {
|
|
138
|
+
const deprecation = '[DEPRECATED] get_performance is deprecated. Use profiler > snapshot instead for all 59 monitors + render timing.\n\n';
|
|
138
139
|
const result = await godot.sendCommand('get_performance_metrics');
|
|
139
|
-
return JSON.stringify(result, null, 2);
|
|
140
|
+
return deprecation + JSON.stringify(result, null, 2);
|
|
140
141
|
}
|
|
141
142
|
case 'screenshot_game': {
|
|
142
143
|
const result = await godot.sendCommand('capture_game_screenshot', { max_width: args.max_width });
|
package/dist/tools/editor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editor.js","sourceRoot":"","sources":["../../src/tools/editor.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"editor.js","sourceRoot":"","sources":["../../src/tools/editor.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAaA,wBAAgB,gBAAgB,IAAI,IAAI,CAYvC;AAED,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/tools/index.js
CHANGED
|
@@ -9,6 +9,7 @@ import { resourceTools } from './resource.js';
|
|
|
9
9
|
import { scene3dTools } from './scene3d.js';
|
|
10
10
|
import { docsTools } from './docs.js';
|
|
11
11
|
import { inputTools } from './input.js';
|
|
12
|
+
import { profilerTools } from './profiler.js';
|
|
12
13
|
export function registerAllTools() {
|
|
13
14
|
registry.registerTools(sceneTools);
|
|
14
15
|
registry.registerTools(nodeTools);
|
|
@@ -20,6 +21,7 @@ export function registerAllTools() {
|
|
|
20
21
|
registry.registerTools(scene3dTools);
|
|
21
22
|
registry.registerTools(docsTools);
|
|
22
23
|
registry.registerTools(inputTools);
|
|
24
|
+
registry.registerTools(profilerTools);
|
|
23
25
|
}
|
|
24
26
|
export { sceneTools } from './scene.js';
|
|
25
27
|
export { nodeTools } from './node.js';
|
|
@@ -31,4 +33,5 @@ export { resourceTools } from './resource.js';
|
|
|
31
33
|
export { scene3dTools } from './scene3d.js';
|
|
32
34
|
export { docsTools } from './docs.js';
|
|
33
35
|
export { inputTools } from './input.js';
|
|
36
|
+
export { profilerTools } from './profiler.js';
|
|
34
37
|
//# sourceMappingURL=index.js.map
|
package/dist/tools/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,UAAU,gBAAgB;IAC9B,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IACnC,QAAQ,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IAClC,QAAQ,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IACpC,QAAQ,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,QAAQ,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;IACvC,QAAQ,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;IACtC,QAAQ,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;IACrC,QAAQ,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IAClC,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IACnC,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;AACxC,CAAC;AAED,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { AnyToolDefinition } from '../core/types.js';
|
|
3
|
+
interface FrameEntry {
|
|
4
|
+
ft: number;
|
|
5
|
+
pt: number;
|
|
6
|
+
pht: number;
|
|
7
|
+
pft: number;
|
|
8
|
+
i: number;
|
|
9
|
+
m?: Record<string, number>;
|
|
10
|
+
}
|
|
11
|
+
export interface PercentileStats {
|
|
12
|
+
avg_ms: number;
|
|
13
|
+
min_ms: number;
|
|
14
|
+
max_ms: number;
|
|
15
|
+
p50_ms: number;
|
|
16
|
+
p95_ms: number;
|
|
17
|
+
p99_ms: number;
|
|
18
|
+
}
|
|
19
|
+
export declare function computePercentiles(values: number[]): PercentileStats;
|
|
20
|
+
export interface SpikeInfo {
|
|
21
|
+
frame_index: number;
|
|
22
|
+
frame_time_ms: number;
|
|
23
|
+
monitors?: Record<string, number>;
|
|
24
|
+
}
|
|
25
|
+
export declare function detectSpikes(frames: FrameEntry[], medianFrameTime: number): SpikeInfo[];
|
|
26
|
+
export interface MonitorTrend {
|
|
27
|
+
start: number;
|
|
28
|
+
end: number;
|
|
29
|
+
avg: number;
|
|
30
|
+
max: number;
|
|
31
|
+
change_percent: number;
|
|
32
|
+
}
|
|
33
|
+
export declare function computeMonitorTrends(frames: FrameEntry[]): Record<string, MonitorTrend>;
|
|
34
|
+
export interface FrameBudget {
|
|
35
|
+
target_fps: number;
|
|
36
|
+
actual_fps: number;
|
|
37
|
+
frame_budget_ms: number;
|
|
38
|
+
budget_usage_percent: number;
|
|
39
|
+
}
|
|
40
|
+
export declare function computeFrameBudget(frameTimeStats: PercentileStats, targetFps: number): FrameBudget;
|
|
41
|
+
export declare const profiler: import("../core/types.js").ToolDefinition<z.ZodObject<{
|
|
42
|
+
action: z.ZodEnum<{
|
|
43
|
+
stop: "stop";
|
|
44
|
+
snapshot: "snapshot";
|
|
45
|
+
start: "start";
|
|
46
|
+
get_data: "get_data";
|
|
47
|
+
get_active_processes: "get_active_processes";
|
|
48
|
+
get_signal_connections: "get_signal_connections";
|
|
49
|
+
}>;
|
|
50
|
+
node_path: z.ZodOptional<z.ZodString>;
|
|
51
|
+
}, z.core.$strip>>;
|
|
52
|
+
export declare const profilerTools: AnyToolDefinition[];
|
|
53
|
+
export {};
|
|
54
|
+
//# sourceMappingURL=profiler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiler.d.ts","sourceRoot":"","sources":["../../src/tools/profiler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,UAAU,UAAU;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC5B;AAyBD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAMD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,eAAe,CAgBpE;AAUD,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,eAAe,EAAE,MAAM,GAAG,SAAS,EAAE,CAkBvF;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAgCvF;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED,wBAAgB,kBAAkB,CAChC,cAAc,EAAE,eAAe,EAC/B,SAAS,EAAE,MAAM,GAChB,WAAW,CAWb;AA+BD,eAAO,MAAM,QAAQ;;;;;;;;;;kBAuHnB,CAAC;AAEH,eAAO,MAAM,aAAa,EAAiB,iBAAiB,EAAE,CAAC"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { defineTool } from '../core/define-tool.js';
|
|
3
|
+
function toMs(seconds) {
|
|
4
|
+
return Math.round(seconds * 100000) / 100;
|
|
5
|
+
}
|
|
6
|
+
export function computePercentiles(values) {
|
|
7
|
+
if (values.length === 0) {
|
|
8
|
+
return { avg_ms: 0, min_ms: 0, max_ms: 0, p50_ms: 0, p95_ms: 0, p99_ms: 0 };
|
|
9
|
+
}
|
|
10
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
11
|
+
const sum = sorted.reduce((a, b) => a + b, 0);
|
|
12
|
+
return {
|
|
13
|
+
avg_ms: toMs(sum / sorted.length),
|
|
14
|
+
min_ms: toMs(sorted[0]),
|
|
15
|
+
max_ms: toMs(sorted[sorted.length - 1]),
|
|
16
|
+
p50_ms: toMs(percentile(sorted, 50)),
|
|
17
|
+
p95_ms: toMs(percentile(sorted, 95)),
|
|
18
|
+
p99_ms: toMs(percentile(sorted, 99)),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function percentile(sorted, p) {
|
|
22
|
+
const index = (p / 100) * (sorted.length - 1);
|
|
23
|
+
const lower = Math.floor(index);
|
|
24
|
+
const upper = Math.ceil(index);
|
|
25
|
+
if (lower === upper)
|
|
26
|
+
return sorted[lower];
|
|
27
|
+
return sorted[lower] + (sorted[upper] - sorted[lower]) * (index - lower);
|
|
28
|
+
}
|
|
29
|
+
export function detectSpikes(frames, medianFrameTime) {
|
|
30
|
+
const threshold = medianFrameTime * 2;
|
|
31
|
+
const spikes = [];
|
|
32
|
+
for (const frame of frames) {
|
|
33
|
+
if (frame.ft > threshold) {
|
|
34
|
+
const spike = {
|
|
35
|
+
frame_index: frame.i,
|
|
36
|
+
frame_time_ms: toMs(frame.ft),
|
|
37
|
+
};
|
|
38
|
+
if (frame.m) {
|
|
39
|
+
spike.monitors = frame.m;
|
|
40
|
+
}
|
|
41
|
+
spikes.push(spike);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return spikes;
|
|
45
|
+
}
|
|
46
|
+
export function computeMonitorTrends(frames) {
|
|
47
|
+
const monitorFrames = frames.filter((f) => f.m);
|
|
48
|
+
if (monitorFrames.length === 0)
|
|
49
|
+
return {};
|
|
50
|
+
const allKeys = new Set();
|
|
51
|
+
for (const f of monitorFrames) {
|
|
52
|
+
for (const key of Object.keys(f.m)) {
|
|
53
|
+
allKeys.add(key);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const trends = {};
|
|
57
|
+
for (const key of allKeys) {
|
|
58
|
+
const values = monitorFrames.filter((f) => f.m[key] !== undefined).map((f) => f.m[key]);
|
|
59
|
+
if (values.length === 0)
|
|
60
|
+
continue;
|
|
61
|
+
const sum = values.reduce((a, b) => a + b, 0);
|
|
62
|
+
const start = values[0];
|
|
63
|
+
const end = values[values.length - 1];
|
|
64
|
+
const changePct = start === 0 ? (end === 0 ? 0 : 100) : ((end - start) / start) * 100;
|
|
65
|
+
trends[key] = {
|
|
66
|
+
start,
|
|
67
|
+
end,
|
|
68
|
+
avg: sum / values.length,
|
|
69
|
+
max: Math.max(...values),
|
|
70
|
+
change_percent: Math.round(changePct * 10) / 10,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
return trends;
|
|
74
|
+
}
|
|
75
|
+
export function computeFrameBudget(frameTimeStats, targetFps) {
|
|
76
|
+
const budgetMs = 1000 / targetFps;
|
|
77
|
+
const actualFps = frameTimeStats.avg_ms > 0 ? Math.round(1000 / frameTimeStats.avg_ms) : 0;
|
|
78
|
+
const budgetUsage = Math.round((frameTimeStats.avg_ms / budgetMs) * 1000) / 10;
|
|
79
|
+
return {
|
|
80
|
+
target_fps: targetFps,
|
|
81
|
+
actual_fps: actualFps,
|
|
82
|
+
frame_budget_ms: Math.round(budgetMs * 10) / 10,
|
|
83
|
+
budget_usage_percent: budgetUsage,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
const ProfilerSchema = z
|
|
87
|
+
.object({
|
|
88
|
+
action: z
|
|
89
|
+
.enum([
|
|
90
|
+
'snapshot',
|
|
91
|
+
'start',
|
|
92
|
+
'stop',
|
|
93
|
+
'get_data',
|
|
94
|
+
'get_active_processes',
|
|
95
|
+
'get_signal_connections',
|
|
96
|
+
])
|
|
97
|
+
.describe('Action: snapshot (full perf snapshot), start/stop/get_data (time series profiling), get_active_processes, get_signal_connections'),
|
|
98
|
+
node_path: z
|
|
99
|
+
.string()
|
|
100
|
+
.optional()
|
|
101
|
+
.describe('Node path for get_signal_connections (optional, defaults to scene root)'),
|
|
102
|
+
})
|
|
103
|
+
.refine((data) => {
|
|
104
|
+
if (data.node_path !== undefined && data.action !== 'get_signal_connections') {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
return true;
|
|
108
|
+
}, { message: 'node_path is only valid with get_signal_connections action' });
|
|
109
|
+
export const profiler = defineTool({
|
|
110
|
+
name: 'profiler',
|
|
111
|
+
description: 'Performance profiling and analysis: snapshot all engine metrics, collect per-frame time series data with spike detection, list active _process/_physics_process scripts, inspect signal connections',
|
|
112
|
+
schema: ProfilerSchema,
|
|
113
|
+
async execute(args, { godot }) {
|
|
114
|
+
switch (args.action) {
|
|
115
|
+
case 'snapshot': {
|
|
116
|
+
const result = await godot.sendCommand('get_performance_metrics');
|
|
117
|
+
return JSON.stringify(result, null, 2);
|
|
118
|
+
}
|
|
119
|
+
case 'start': {
|
|
120
|
+
const result = await godot.sendCommand('start_profiler');
|
|
121
|
+
return result.message;
|
|
122
|
+
}
|
|
123
|
+
case 'stop': {
|
|
124
|
+
const result = await godot.sendCommand('stop_profiler');
|
|
125
|
+
return result.message;
|
|
126
|
+
}
|
|
127
|
+
case 'get_data': {
|
|
128
|
+
const result = await godot.sendCommand('get_profiler_data');
|
|
129
|
+
const { frames } = result;
|
|
130
|
+
if (frames.length === 0) {
|
|
131
|
+
return JSON.stringify({
|
|
132
|
+
active: result.active,
|
|
133
|
+
frame_count: 0,
|
|
134
|
+
message: 'No frames collected. Start the profiler first with action: start',
|
|
135
|
+
}, null, 2);
|
|
136
|
+
}
|
|
137
|
+
const frameTimeStats = computePercentiles(frames.map((f) => f.ft));
|
|
138
|
+
const processTimeStats = computePercentiles(frames.map((f) => f.pt));
|
|
139
|
+
const physicsTimeStats = computePercentiles(frames.map((f) => f.pht));
|
|
140
|
+
const spikes = detectSpikes(frames, frameTimeStats.p50_ms / 1000);
|
|
141
|
+
const monitorTrends = computeMonitorTrends(frames);
|
|
142
|
+
const physicsTickMs = frames.length > 0 ? toMs(frames[0].pft) : 16.67;
|
|
143
|
+
const maxFps = result.max_fps || 0;
|
|
144
|
+
const targetFps = maxFps > 0 ? maxFps : Math.round(1000 / physicsTickMs);
|
|
145
|
+
const frameBudget = computeFrameBudget(frameTimeStats, targetFps);
|
|
146
|
+
return JSON.stringify({
|
|
147
|
+
active: result.active,
|
|
148
|
+
frame_count: result.frame_count,
|
|
149
|
+
total_frames_collected: result.total_frames_collected,
|
|
150
|
+
frame_budget: frameBudget,
|
|
151
|
+
statistics: {
|
|
152
|
+
frame_time: frameTimeStats,
|
|
153
|
+
process_time: processTimeStats,
|
|
154
|
+
physics_time: physicsTimeStats,
|
|
155
|
+
},
|
|
156
|
+
physics_tick_ms: physicsTickMs,
|
|
157
|
+
spikes: {
|
|
158
|
+
count: spikes.length,
|
|
159
|
+
threshold: `>${Math.round(frameTimeStats.p50_ms * 2 * 10) / 10}ms (2x median)`,
|
|
160
|
+
frames: spikes.slice(0, 20),
|
|
161
|
+
},
|
|
162
|
+
monitor_trends: monitorTrends,
|
|
163
|
+
}, null, 2);
|
|
164
|
+
}
|
|
165
|
+
case 'get_active_processes': {
|
|
166
|
+
const result = await godot.sendCommand('get_active_processes');
|
|
167
|
+
const { processes } = result;
|
|
168
|
+
if (processes.length === 0) {
|
|
169
|
+
return 'No active _process or _physics_process functions found';
|
|
170
|
+
}
|
|
171
|
+
const lines = [`Active processing scripts (${processes.length} scripts):\n`];
|
|
172
|
+
for (const entry of processes) {
|
|
173
|
+
const funcs = [];
|
|
174
|
+
if (entry.has_process)
|
|
175
|
+
funcs.push('_process');
|
|
176
|
+
if (entry.has_physics_process)
|
|
177
|
+
funcs.push('_physics_process');
|
|
178
|
+
lines.push(` ${entry.script_path}`);
|
|
179
|
+
lines.push(` Functions: ${funcs.join(', ')}`);
|
|
180
|
+
lines.push(` Instances: ${entry.instance_count}`);
|
|
181
|
+
if (entry.example_paths.length > 0) {
|
|
182
|
+
lines.push(` Examples: ${entry.example_paths.join(', ')}`);
|
|
183
|
+
}
|
|
184
|
+
lines.push('');
|
|
185
|
+
}
|
|
186
|
+
return lines.join('\n');
|
|
187
|
+
}
|
|
188
|
+
case 'get_signal_connections': {
|
|
189
|
+
const result = await godot.sendCommand('get_signal_connections', { node_path: args.node_path ?? '' });
|
|
190
|
+
const { connections } = result;
|
|
191
|
+
if (connections.length === 0) {
|
|
192
|
+
return 'No signal connections found';
|
|
193
|
+
}
|
|
194
|
+
const lines = [`Signal connections (${connections.length}):\n`];
|
|
195
|
+
for (const conn of connections) {
|
|
196
|
+
lines.push(` ${conn.source_path}.${conn.signal_name} -> ${conn.target_path}.${conn.method_name}`);
|
|
197
|
+
}
|
|
198
|
+
return lines.join('\n');
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
export const profilerTools = [profiler];
|
|
204
|
+
//# sourceMappingURL=profiler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiler.js","sourceRoot":"","sources":["../../src/tools/profiler.ts"],"names":[],"mappings":"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"}
|