Files
tekton/addons/godot_ai/tool_catalog.gd
T

87 lines
4.1 KiB
GDScript

@tool
class_name McpToolCatalog
extends RefCounted
## Mirror of src/godot_ai/tools/domains.py — drives the dock's Tools tab
## so the UI can render checkboxes, tool counts, and tooltips without
## round-tripping to a running server.
##
## DO NOT EDIT by hand. tests/unit/test_tool_domains.py verifies this file
## against actual tool registration and fails CI when they drift; the
## failure message prints the up-to-date catalog body for paste-over.
##
## The four core tools are always registered and cannot be excluded — they
## render as a single grayed-out "Core" row in the UI. Each non-core domain
## now exposes one or two named verbs plus a single rolled-up
## `<domain>_manage` tool.
const CORE_TOOLS := [
"editor_state",
"node_get_properties",
"scene_get_hierarchy",
"session_activate",
]
## Ordered list of user-toggleable domains. Each entry:
## id: matches the name passed to `--exclude-domains`
## label: human-friendly display (same as id for now, kept separate so
## a future renaming doesn't break the setting)
## count: number of NON-CORE tools in this domain
## tools: flat list of tool names registered by this domain (non-core only)
const DOMAINS := [
{"id": "animation", "label": "animation", "count": 2, "tools": ["animation_create", "animation_manage"]},
{"id": "api", "label": "api", "count": 1, "tools": ["api_manage"]},
{"id": "audio", "label": "audio", "count": 1, "tools": ["audio_manage"]},
{"id": "autoload", "label": "autoload", "count": 1, "tools": ["autoload_manage"]},
{"id": "batch", "label": "batch", "count": 1, "tools": ["batch_execute"]},
{"id": "camera", "label": "camera", "count": 1, "tools": ["camera_manage"]},
{"id": "client", "label": "client", "count": 1, "tools": ["client_manage"]},
{"id": "editor", "label": "editor", "count": 4, "tools": ["editor_manage", "editor_reload_plugin", "editor_screenshot", "logs_read"]},
{"id": "filesystem", "label": "filesystem", "count": 1, "tools": ["filesystem_manage"]},
{"id": "game", "label": "game", "count": 1, "tools": ["game_manage"]},
{"id": "input_map", "label": "input_map", "count": 1, "tools": ["input_map_manage"]},
{"id": "material", "label": "material", "count": 1, "tools": ["material_manage"]},
{"id": "node", "label": "node", "count": 4, "tools": ["node_create", "node_find", "node_manage", "node_set_property"]},
{"id": "particle", "label": "particle", "count": 1, "tools": ["particle_manage"]},
{"id": "project", "label": "project", "count": 2, "tools": ["project_manage", "project_run"]},
{"id": "resource", "label": "resource", "count": 1, "tools": ["resource_manage"]},
{"id": "scene", "label": "scene", "count": 3, "tools": ["scene_manage", "scene_open", "scene_save"]},
{"id": "script", "label": "script", "count": 4, "tools": ["script_attach", "script_create", "script_manage", "script_patch"]},
{"id": "signal", "label": "signal", "count": 1, "tools": ["signal_manage"]},
{"id": "testing", "label": "testing", "count": 2, "tools": ["test_manage", "test_run"]},
{"id": "theme", "label": "theme", "count": 1, "tools": ["theme_manage"]},
{"id": "ui", "label": "ui", "count": 1, "tools": ["ui_manage"]},
]
## Total tool count when no domains are excluded. Used for the "Enabled: N / M"
## readout in the Tools tab without looping the catalog on every repaint.
static func total_tool_count() -> int:
var n := CORE_TOOLS.size()
for d in DOMAINS:
n += int(d["count"])
return n
## Tool count remaining after excluding the given set of domain ids.
static func enabled_tool_count(excluded: PackedStringArray) -> int:
var n := CORE_TOOLS.size()
for d in DOMAINS:
if excluded.find(d["id"]) == -1:
n += int(d["count"])
return n
## Canonical comma-separated string for a set of domain ids — sorted and
## deduplicated so two equivalent settings (entered in different orders)
## hash to the same EditorSetting value. Matches `excluded_domains()` in
## client_configurator.gd.
static func canonical(excluded: PackedStringArray) -> String:
var seen := PackedStringArray()
for e in excluded:
var t := e.strip_edges()
if not t.is_empty() and seen.find(t) == -1:
seen.append(t)
seen.sort()
return ",".join(seen)