gopeak 2.3.7 → 2.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +279 -411
- package/build/addon/auto_reload/auto_reload.gd +126 -126
- package/build/addon/auto_reload/plugin.cfg +7 -7
- package/build/addon/godot_mcp_editor/mcp_client.gd +178 -178
- package/build/addon/godot_mcp_editor/plugin.cfg +6 -6
- package/build/addon/godot_mcp_editor/plugin.gd +84 -84
- package/build/addon/godot_mcp_editor/tool_executor.gd +114 -114
- package/build/addon/godot_mcp_editor/tools/animation_tools.gd +502 -502
- package/build/addon/godot_mcp_editor/tools/resource_tools.gd +425 -425
- package/build/addon/godot_mcp_editor/tools/scene_tools.gd +761 -761
- package/build/addon/godot_mcp_runtime/godot_mcp_runtime.gd +33 -33
- package/build/addon/godot_mcp_runtime/mcp_runtime_autoload.gd +671 -619
- package/build/addon/godot_mcp_runtime/plugin.cfg +7 -7
- package/build/cli/notify.js +4 -3
- package/build/cli.js +18 -18
- package/build/godot-bridge.js +11 -11
- package/build/index.js +238 -123
- package/build/scripts/godot_operations.gd +6823 -6823
- package/build/visualizer/events.js +19 -19
- package/build/visualizer/panel.js +34 -34
- package/build/visualizer/usages.js +14 -14
- package/build/visualizer-server.js +11 -11
- package/build/visualizer.html +2596 -2596
- package/package.json +106 -107
- package/scripts/postinstall.mjs +29 -29
|
@@ -1,84 +1,84 @@
|
|
|
1
|
-
@tool
|
|
2
|
-
extends EditorPlugin
|
|
3
|
-
|
|
4
|
-
const MCPEditorClientScript = preload("mcp_client.gd")
|
|
5
|
-
const MCPToolExecutorScript = preload("tool_executor.gd")
|
|
6
|
-
|
|
7
|
-
var _mcp_client: Node
|
|
8
|
-
var _tool_executor: Node
|
|
9
|
-
var _status_label: Label
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
func _enter_tree() -> void:
|
|
13
|
-
_mcp_client = MCPEditorClientScript.new()
|
|
14
|
-
_mcp_client.name = "MCPEditorClient"
|
|
15
|
-
add_child(_mcp_client)
|
|
16
|
-
|
|
17
|
-
_tool_executor = MCPToolExecutorScript.new()
|
|
18
|
-
_tool_executor.name = "MCPToolExecutor"
|
|
19
|
-
add_child(_tool_executor)
|
|
20
|
-
_tool_executor.set_editor_plugin(self)
|
|
21
|
-
|
|
22
|
-
_mcp_client.connected.connect(_on_connected)
|
|
23
|
-
_mcp_client.disconnected.connect(_on_disconnected)
|
|
24
|
-
_mcp_client.tool_requested.connect(_on_tool_requested)
|
|
25
|
-
|
|
26
|
-
_setup_status_indicator()
|
|
27
|
-
_mcp_client.connect_to_server()
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
func _exit_tree() -> void:
|
|
31
|
-
if _mcp_client:
|
|
32
|
-
if _mcp_client.connected.is_connected(_on_connected):
|
|
33
|
-
_mcp_client.connected.disconnect(_on_connected)
|
|
34
|
-
if _mcp_client.disconnected.is_connected(_on_disconnected):
|
|
35
|
-
_mcp_client.disconnected.disconnect(_on_disconnected)
|
|
36
|
-
if _mcp_client.tool_requested.is_connected(_on_tool_requested):
|
|
37
|
-
_mcp_client.tool_requested.disconnect(_on_tool_requested)
|
|
38
|
-
_mcp_client.disconnect_from_server()
|
|
39
|
-
_mcp_client.queue_free()
|
|
40
|
-
_mcp_client = null
|
|
41
|
-
|
|
42
|
-
if _tool_executor:
|
|
43
|
-
_tool_executor.queue_free()
|
|
44
|
-
_tool_executor = null
|
|
45
|
-
|
|
46
|
-
if _status_label:
|
|
47
|
-
remove_control_from_container(CONTAINER_TOOLBAR, _status_label)
|
|
48
|
-
_status_label.queue_free()
|
|
49
|
-
_status_label = null
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
func _setup_status_indicator() -> void:
|
|
53
|
-
_status_label = Label.new()
|
|
54
|
-
_status_label.text = "MCP: Connecting..."
|
|
55
|
-
_status_label.add_theme_color_override("font_color", Color.YELLOW)
|
|
56
|
-
_status_label.add_theme_font_size_override("font_size", 12)
|
|
57
|
-
add_control_to_container(CONTAINER_TOOLBAR, _status_label)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
func _on_connected() -> void:
|
|
61
|
-
if _status_label:
|
|
62
|
-
_status_label.text = "MCP: Connected"
|
|
63
|
-
_status_label.add_theme_color_override("font_color", Color.GREEN)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
func _on_disconnected() -> void:
|
|
67
|
-
if _status_label:
|
|
68
|
-
_status_label.text = "MCP: Disconnected"
|
|
69
|
-
_status_label.add_theme_color_override("font_color", Color.RED)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
func _on_tool_requested(request_id: String, tool_name: String, args: Dictionary) -> void:
|
|
73
|
-
if _tool_executor == null or _mcp_client == null:
|
|
74
|
-
return
|
|
75
|
-
|
|
76
|
-
var result: Dictionary = _tool_executor.execute_tool(tool_name, args)
|
|
77
|
-
var success: bool = result.get("ok", false)
|
|
78
|
-
|
|
79
|
-
if success:
|
|
80
|
-
var payload := result.duplicate(true)
|
|
81
|
-
payload.erase("ok")
|
|
82
|
-
_mcp_client.send_tool_result(request_id, true, payload, "")
|
|
83
|
-
else:
|
|
84
|
-
_mcp_client.send_tool_result(request_id, false, null, str(result.get("error", "Unknown error")))
|
|
1
|
+
@tool
|
|
2
|
+
extends EditorPlugin
|
|
3
|
+
|
|
4
|
+
const MCPEditorClientScript = preload("mcp_client.gd")
|
|
5
|
+
const MCPToolExecutorScript = preload("tool_executor.gd")
|
|
6
|
+
|
|
7
|
+
var _mcp_client: Node
|
|
8
|
+
var _tool_executor: Node
|
|
9
|
+
var _status_label: Label
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
func _enter_tree() -> void:
|
|
13
|
+
_mcp_client = MCPEditorClientScript.new()
|
|
14
|
+
_mcp_client.name = "MCPEditorClient"
|
|
15
|
+
add_child(_mcp_client)
|
|
16
|
+
|
|
17
|
+
_tool_executor = MCPToolExecutorScript.new()
|
|
18
|
+
_tool_executor.name = "MCPToolExecutor"
|
|
19
|
+
add_child(_tool_executor)
|
|
20
|
+
_tool_executor.set_editor_plugin(self)
|
|
21
|
+
|
|
22
|
+
_mcp_client.connected.connect(_on_connected)
|
|
23
|
+
_mcp_client.disconnected.connect(_on_disconnected)
|
|
24
|
+
_mcp_client.tool_requested.connect(_on_tool_requested)
|
|
25
|
+
|
|
26
|
+
_setup_status_indicator()
|
|
27
|
+
_mcp_client.connect_to_server()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
func _exit_tree() -> void:
|
|
31
|
+
if _mcp_client:
|
|
32
|
+
if _mcp_client.connected.is_connected(_on_connected):
|
|
33
|
+
_mcp_client.connected.disconnect(_on_connected)
|
|
34
|
+
if _mcp_client.disconnected.is_connected(_on_disconnected):
|
|
35
|
+
_mcp_client.disconnected.disconnect(_on_disconnected)
|
|
36
|
+
if _mcp_client.tool_requested.is_connected(_on_tool_requested):
|
|
37
|
+
_mcp_client.tool_requested.disconnect(_on_tool_requested)
|
|
38
|
+
_mcp_client.disconnect_from_server()
|
|
39
|
+
_mcp_client.queue_free()
|
|
40
|
+
_mcp_client = null
|
|
41
|
+
|
|
42
|
+
if _tool_executor:
|
|
43
|
+
_tool_executor.queue_free()
|
|
44
|
+
_tool_executor = null
|
|
45
|
+
|
|
46
|
+
if _status_label:
|
|
47
|
+
remove_control_from_container(CONTAINER_TOOLBAR, _status_label)
|
|
48
|
+
_status_label.queue_free()
|
|
49
|
+
_status_label = null
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
func _setup_status_indicator() -> void:
|
|
53
|
+
_status_label = Label.new()
|
|
54
|
+
_status_label.text = "MCP: Connecting..."
|
|
55
|
+
_status_label.add_theme_color_override("font_color", Color.YELLOW)
|
|
56
|
+
_status_label.add_theme_font_size_override("font_size", 12)
|
|
57
|
+
add_control_to_container(CONTAINER_TOOLBAR, _status_label)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
func _on_connected() -> void:
|
|
61
|
+
if _status_label:
|
|
62
|
+
_status_label.text = "MCP: Connected"
|
|
63
|
+
_status_label.add_theme_color_override("font_color", Color.GREEN)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
func _on_disconnected() -> void:
|
|
67
|
+
if _status_label:
|
|
68
|
+
_status_label.text = "MCP: Disconnected"
|
|
69
|
+
_status_label.add_theme_color_override("font_color", Color.RED)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
func _on_tool_requested(request_id: String, tool_name: String, args: Dictionary) -> void:
|
|
73
|
+
if _tool_executor == null or _mcp_client == null:
|
|
74
|
+
return
|
|
75
|
+
|
|
76
|
+
var result: Dictionary = _tool_executor.execute_tool(tool_name, args)
|
|
77
|
+
var success: bool = result.get("ok", false)
|
|
78
|
+
|
|
79
|
+
if success:
|
|
80
|
+
var payload := result.duplicate(true)
|
|
81
|
+
payload.erase("ok")
|
|
82
|
+
_mcp_client.send_tool_result(request_id, true, payload, "")
|
|
83
|
+
else:
|
|
84
|
+
_mcp_client.send_tool_result(request_id, false, null, str(result.get("error", "Unknown error")))
|
|
@@ -1,114 +1,114 @@
|
|
|
1
|
-
@tool
|
|
2
|
-
extends Node
|
|
3
|
-
class_name MCPToolExecutor
|
|
4
|
-
|
|
5
|
-
var _editor_plugin: EditorPlugin = null
|
|
6
|
-
|
|
7
|
-
var _scene_tools: Node = null
|
|
8
|
-
var _resource_tools: Node = null
|
|
9
|
-
var _animation_tools: Node = null
|
|
10
|
-
|
|
11
|
-
var _tool_map: Dictionary = {}
|
|
12
|
-
var _initialized := false
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
func set_editor_plugin(plugin: EditorPlugin) -> void:
|
|
16
|
-
_editor_plugin = plugin
|
|
17
|
-
_init_tools()
|
|
18
|
-
|
|
19
|
-
if _scene_tools and _scene_tools.has_method("set_editor_plugin"):
|
|
20
|
-
_scene_tools.set_editor_plugin(plugin)
|
|
21
|
-
if _resource_tools and _resource_tools.has_method("set_editor_plugin"):
|
|
22
|
-
_resource_tools.set_editor_plugin(plugin)
|
|
23
|
-
if _animation_tools and _animation_tools.has_method("set_editor_plugin"):
|
|
24
|
-
_animation_tools.set_editor_plugin(plugin)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
func _init_tools() -> void:
|
|
28
|
-
if _initialized:
|
|
29
|
-
return
|
|
30
|
-
_initialized = true
|
|
31
|
-
|
|
32
|
-
var base_path: String = get_script().resource_path.get_base_dir()
|
|
33
|
-
var scene_tools_path := "%s/tools/scene_tools.gd" % base_path
|
|
34
|
-
var resource_tools_path := "%s/tools/resource_tools.gd" % base_path
|
|
35
|
-
var animation_tools_path := "%s/tools/animation_tools.gd" % base_path
|
|
36
|
-
|
|
37
|
-
if ResourceLoader.exists(scene_tools_path):
|
|
38
|
-
var scene_script: Script = load(scene_tools_path)
|
|
39
|
-
if scene_script:
|
|
40
|
-
_scene_tools = scene_script.new()
|
|
41
|
-
_scene_tools.name = "SceneTools"
|
|
42
|
-
add_child(_scene_tools)
|
|
43
|
-
|
|
44
|
-
if ResourceLoader.exists(resource_tools_path):
|
|
45
|
-
var resource_script: Script = load(resource_tools_path)
|
|
46
|
-
if resource_script:
|
|
47
|
-
_resource_tools = resource_script.new()
|
|
48
|
-
_resource_tools.name = "ResourceTools"
|
|
49
|
-
add_child(_resource_tools)
|
|
50
|
-
|
|
51
|
-
if ResourceLoader.exists(animation_tools_path):
|
|
52
|
-
var animation_script: Script = load(animation_tools_path)
|
|
53
|
-
if animation_script:
|
|
54
|
-
_animation_tools = animation_script.new()
|
|
55
|
-
_animation_tools.name = "AnimationTools"
|
|
56
|
-
add_child(_animation_tools)
|
|
57
|
-
|
|
58
|
-
_tool_map = {
|
|
59
|
-
# Scene tools
|
|
60
|
-
"create_scene": [_scene_tools, "create_scene"],
|
|
61
|
-
"list_scene_nodes": [_scene_tools, "list_scene_nodes"],
|
|
62
|
-
"add_node": [_scene_tools, "add_node"],
|
|
63
|
-
"delete_node": [_scene_tools, "delete_node"],
|
|
64
|
-
"duplicate_node": [_scene_tools, "duplicate_node"],
|
|
65
|
-
"reparent_node": [_scene_tools, "reparent_node"],
|
|
66
|
-
"set_node_properties": [_scene_tools, "set_node_properties"],
|
|
67
|
-
"get_node_properties": [_scene_tools, "get_node_properties"],
|
|
68
|
-
"load_sprite": [_scene_tools, "load_sprite"],
|
|
69
|
-
"save_scene": [_scene_tools, "save_scene"],
|
|
70
|
-
"connect_signal": [_scene_tools, "connect_signal"],
|
|
71
|
-
"disconnect_signal": [_scene_tools, "disconnect_signal"],
|
|
72
|
-
"list_connections": [_scene_tools, "list_connections"],
|
|
73
|
-
|
|
74
|
-
# Resource tools
|
|
75
|
-
"create_resource": [_resource_tools, "create_resource"],
|
|
76
|
-
"modify_resource": [_resource_tools, "modify_resource"],
|
|
77
|
-
"create_material": [_resource_tools, "create_material"],
|
|
78
|
-
"create_shader": [_resource_tools, "create_shader"],
|
|
79
|
-
"create_tileset": [_resource_tools, "create_tileset"],
|
|
80
|
-
"set_tilemap_cells": [_resource_tools, "set_tilemap_cells"],
|
|
81
|
-
"set_theme_color": [_resource_tools, "set_theme_color"],
|
|
82
|
-
"set_theme_font_size": [_resource_tools, "set_theme_font_size"],
|
|
83
|
-
"apply_theme_shader": [_resource_tools, "apply_theme_shader"],
|
|
84
|
-
|
|
85
|
-
# Animation tools
|
|
86
|
-
"create_animation": [_animation_tools, "create_animation"],
|
|
87
|
-
"add_animation_track": [_animation_tools, "add_animation_track"],
|
|
88
|
-
"create_animation_tree": [_animation_tools, "create_animation_tree"],
|
|
89
|
-
"add_animation_state": [_animation_tools, "add_animation_state"],
|
|
90
|
-
"connect_animation_states": [_animation_tools, "connect_animation_states"],
|
|
91
|
-
"create_navigation_region": [_animation_tools, "create_navigation_region"],
|
|
92
|
-
"create_navigation_agent": [_animation_tools, "create_navigation_agent"]
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
func execute_tool(tool_name: String, args: Dictionary) -> Dictionary:
|
|
97
|
-
if not _tool_map.has(tool_name):
|
|
98
|
-
return {"ok": false, "error": "Unknown tool: " + tool_name}
|
|
99
|
-
|
|
100
|
-
var handler: Array = _tool_map[tool_name]
|
|
101
|
-
var node: Node = handler[0]
|
|
102
|
-
var method: String = handler[1]
|
|
103
|
-
|
|
104
|
-
if node == null:
|
|
105
|
-
return {"ok": false, "error": "Tool handler unavailable: " + tool_name}
|
|
106
|
-
|
|
107
|
-
if not node.has_method(method):
|
|
108
|
-
return {"ok": false, "error": "Tool method not found: %s.%s" % [node.name, method]}
|
|
109
|
-
|
|
110
|
-
var result = node.call(method, args)
|
|
111
|
-
if result is Dictionary:
|
|
112
|
-
return result
|
|
113
|
-
|
|
114
|
-
return {"ok": false, "error": "Invalid tool result from: " + tool_name}
|
|
1
|
+
@tool
|
|
2
|
+
extends Node
|
|
3
|
+
class_name MCPToolExecutor
|
|
4
|
+
|
|
5
|
+
var _editor_plugin: EditorPlugin = null
|
|
6
|
+
|
|
7
|
+
var _scene_tools: Node = null
|
|
8
|
+
var _resource_tools: Node = null
|
|
9
|
+
var _animation_tools: Node = null
|
|
10
|
+
|
|
11
|
+
var _tool_map: Dictionary = {}
|
|
12
|
+
var _initialized := false
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
func set_editor_plugin(plugin: EditorPlugin) -> void:
|
|
16
|
+
_editor_plugin = plugin
|
|
17
|
+
_init_tools()
|
|
18
|
+
|
|
19
|
+
if _scene_tools and _scene_tools.has_method("set_editor_plugin"):
|
|
20
|
+
_scene_tools.set_editor_plugin(plugin)
|
|
21
|
+
if _resource_tools and _resource_tools.has_method("set_editor_plugin"):
|
|
22
|
+
_resource_tools.set_editor_plugin(plugin)
|
|
23
|
+
if _animation_tools and _animation_tools.has_method("set_editor_plugin"):
|
|
24
|
+
_animation_tools.set_editor_plugin(plugin)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
func _init_tools() -> void:
|
|
28
|
+
if _initialized:
|
|
29
|
+
return
|
|
30
|
+
_initialized = true
|
|
31
|
+
|
|
32
|
+
var base_path: String = get_script().resource_path.get_base_dir()
|
|
33
|
+
var scene_tools_path := "%s/tools/scene_tools.gd" % base_path
|
|
34
|
+
var resource_tools_path := "%s/tools/resource_tools.gd" % base_path
|
|
35
|
+
var animation_tools_path := "%s/tools/animation_tools.gd" % base_path
|
|
36
|
+
|
|
37
|
+
if ResourceLoader.exists(scene_tools_path):
|
|
38
|
+
var scene_script: Script = load(scene_tools_path)
|
|
39
|
+
if scene_script:
|
|
40
|
+
_scene_tools = scene_script.new()
|
|
41
|
+
_scene_tools.name = "SceneTools"
|
|
42
|
+
add_child(_scene_tools)
|
|
43
|
+
|
|
44
|
+
if ResourceLoader.exists(resource_tools_path):
|
|
45
|
+
var resource_script: Script = load(resource_tools_path)
|
|
46
|
+
if resource_script:
|
|
47
|
+
_resource_tools = resource_script.new()
|
|
48
|
+
_resource_tools.name = "ResourceTools"
|
|
49
|
+
add_child(_resource_tools)
|
|
50
|
+
|
|
51
|
+
if ResourceLoader.exists(animation_tools_path):
|
|
52
|
+
var animation_script: Script = load(animation_tools_path)
|
|
53
|
+
if animation_script:
|
|
54
|
+
_animation_tools = animation_script.new()
|
|
55
|
+
_animation_tools.name = "AnimationTools"
|
|
56
|
+
add_child(_animation_tools)
|
|
57
|
+
|
|
58
|
+
_tool_map = {
|
|
59
|
+
# Scene tools
|
|
60
|
+
"create_scene": [_scene_tools, "create_scene"],
|
|
61
|
+
"list_scene_nodes": [_scene_tools, "list_scene_nodes"],
|
|
62
|
+
"add_node": [_scene_tools, "add_node"],
|
|
63
|
+
"delete_node": [_scene_tools, "delete_node"],
|
|
64
|
+
"duplicate_node": [_scene_tools, "duplicate_node"],
|
|
65
|
+
"reparent_node": [_scene_tools, "reparent_node"],
|
|
66
|
+
"set_node_properties": [_scene_tools, "set_node_properties"],
|
|
67
|
+
"get_node_properties": [_scene_tools, "get_node_properties"],
|
|
68
|
+
"load_sprite": [_scene_tools, "load_sprite"],
|
|
69
|
+
"save_scene": [_scene_tools, "save_scene"],
|
|
70
|
+
"connect_signal": [_scene_tools, "connect_signal"],
|
|
71
|
+
"disconnect_signal": [_scene_tools, "disconnect_signal"],
|
|
72
|
+
"list_connections": [_scene_tools, "list_connections"],
|
|
73
|
+
|
|
74
|
+
# Resource tools
|
|
75
|
+
"create_resource": [_resource_tools, "create_resource"],
|
|
76
|
+
"modify_resource": [_resource_tools, "modify_resource"],
|
|
77
|
+
"create_material": [_resource_tools, "create_material"],
|
|
78
|
+
"create_shader": [_resource_tools, "create_shader"],
|
|
79
|
+
"create_tileset": [_resource_tools, "create_tileset"],
|
|
80
|
+
"set_tilemap_cells": [_resource_tools, "set_tilemap_cells"],
|
|
81
|
+
"set_theme_color": [_resource_tools, "set_theme_color"],
|
|
82
|
+
"set_theme_font_size": [_resource_tools, "set_theme_font_size"],
|
|
83
|
+
"apply_theme_shader": [_resource_tools, "apply_theme_shader"],
|
|
84
|
+
|
|
85
|
+
# Animation tools
|
|
86
|
+
"create_animation": [_animation_tools, "create_animation"],
|
|
87
|
+
"add_animation_track": [_animation_tools, "add_animation_track"],
|
|
88
|
+
"create_animation_tree": [_animation_tools, "create_animation_tree"],
|
|
89
|
+
"add_animation_state": [_animation_tools, "add_animation_state"],
|
|
90
|
+
"connect_animation_states": [_animation_tools, "connect_animation_states"],
|
|
91
|
+
"create_navigation_region": [_animation_tools, "create_navigation_region"],
|
|
92
|
+
"create_navigation_agent": [_animation_tools, "create_navigation_agent"]
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
func execute_tool(tool_name: String, args: Dictionary) -> Dictionary:
|
|
97
|
+
if not _tool_map.has(tool_name):
|
|
98
|
+
return {"ok": false, "error": "Unknown tool: " + tool_name}
|
|
99
|
+
|
|
100
|
+
var handler: Array = _tool_map[tool_name]
|
|
101
|
+
var node: Node = handler[0]
|
|
102
|
+
var method: String = handler[1]
|
|
103
|
+
|
|
104
|
+
if node == null:
|
|
105
|
+
return {"ok": false, "error": "Tool handler unavailable: " + tool_name}
|
|
106
|
+
|
|
107
|
+
if not node.has_method(method):
|
|
108
|
+
return {"ok": false, "error": "Tool method not found: %s.%s" % [node.name, method]}
|
|
109
|
+
|
|
110
|
+
var result = node.call(method, args)
|
|
111
|
+
if result is Dictionary:
|
|
112
|
+
return result
|
|
113
|
+
|
|
114
|
+
return {"ok": false, "error": "Invalid tool result from: " + tool_name}
|