@tool
extends RefCounted
## Tool definitions in OpenAI-compatible JSON Schema format for the agent loop.
## Source of truth: golem_mcp.py @mcp.tool decorators (26 tools).
## Names drop the "godot_" prefix to save tokens.

const TOOL_DEFS: Array[Dictionary] = [
	# ============================================================
	# Core — read & observe
	# ============================================================
	{
		"type": "function",
		"function": {
			"name": "get_scene_tree",
			"description": "Get the full node hierarchy of the currently edited scene. Returns the tree with indentation showing parent-child relationships. Safe to call while a game is running (reads the editor scene, not the running game).",
			"parameters": {
				"type": "object",
				"properties": {
					"detail_level": {
						"type": "string",
						"enum": ["full", "summary"],
						"description": "full (default) includes script paths. summary shows only names and types.",
					},
				},
				"required": [],
			},
		},
	},
	{
		"type": "function",
		"function": {
			"name": "inspect_node",
			"description": "Get all properties, signals, and groups of a specific node in the edited scene. Use '.' for the root node.",
			"parameters": {
				"type": "object",
				"properties": {
					"path": {
						"type": "string",
						"description": "Node path relative to scene root. '.' for root, 'Player' for direct child, 'Player/Sprite' for nested.",
					},
					"detail_level": {
						"type": "string",
						"enum": ["full", "summary"],
						"description": "full shows all properties. summary shows only transform properties.",
					},
				},
				"required": ["path"],
			},
		},
	},
	{
		"type": "function",
		"function": {
			"name": "get_editor_screenshot",
			"description": "Capture a screenshot of the Godot editor's 2D/3D viewport (not the running game).",
			"parameters": {"type": "object", "properties": {}, "required": []},
		},
	},
	{
		"type": "function",
		"function": {
			"name": "get_game_screenshot",
			"description": "Capture a screenshot of the running game window. Game must be playing (call play_scene first). May take 1-2 seconds.",
			"parameters": {"type": "object", "properties": {}, "required": []},
		},
	},
	{
		"type": "function",
		"function": {
			"name": "get_errors",
			"description": "Get GDScript compilation errors and runtime errors captured by the editor.",
			"parameters": {"type": "object", "properties": {}, "required": []},
		},
	},
	{
		"type": "function",
		"function": {
			"name": "get_logs",
			"description": "Get logs from the running game or Godot engine. INCREMENTAL: each call returns only NEW lines since last call. Game logs require GolemCapture.game_log() in scripts.",
			"parameters": {
				"type": "object",
				"properties": {
					"max_lines": {
						"type": "integer",
						"description": "Maximum log lines to return. Default 100.",
					},
					"source": {
						"type": "string",
						"enum": ["game", "engine", "all"],
						"description": "game for GolemCapture output, engine for Godot logs, all for both.",
					},
				},
				"required": [],
			},
		},
	},
	{
		"type": "function",
		"function": {
			"name": "clear_logs",
			"description": "Clear all error records, game logs, engine log cursors, and input simulation files.",
			"parameters": {"type": "object", "properties": {}, "required": []},
		},
	},
	{
		"type": "function",
		"function": {
			"name": "project_context",
			"description": "Get a comprehensive project overview: name, viewport size, renderer, autoloads, input actions, and file lists. Ideal as a first call.",
			"parameters": {"type": "object", "properties": {}, "required": []},
		},
	},
	{
		"type": "function",
		"function": {
			"name": "get_input_map",
			"description": "Get all custom input actions and their key/button bindings from Project Settings.",
			"parameters": {"type": "object", "properties": {}, "required": []},
		},
	},
	# ============================================================
	# Run — play, stop, input
	# ============================================================
	{
		"type": "function",
		"function": {
			"name": "play_scene",
			"description": "Start playing a scene (F5/F6). Only one scene at a time. Save first with save_scene.",
			"parameters": {
				"type": "object",
				"properties": {
					"path": {
						"type": "string",
						"description": "Scene path (e.g. 'res://scenes/main.tscn'). Empty plays current scene.",
					},
				},
				"required": [],
			},
		},
	},
	{
		"type": "function",
		"function": {
			"name": "stop_scene",
			"description": "Stop the currently running game scene. Waits until Godot has fully torn down.",
			"parameters": {"type": "object", "properties": {}, "required": []},
		},
	},
	{
		"type": "function",
		"function": {
			"name": "simulate_input",
			"description": "Simulate input actions in the running game via GolemCapture. Only named Input Map actions, not raw events. Game must be playing.",
			"parameters": {
				"type": "object",
				"properties": {
					"sequence": {
						"type": "array",
						"description": "Array of steps. Each: {action, duration} for hold, {action, pressed: bool} for toggle, {wait: float} for pause.",
						"items": {"type": "object"},
					},
					"loop": {
						"type": "integer",
						"description": "Repeat count. Default 1.",
					},
				},
				"required": ["sequence"],
			},
		},
	},
	# ============================================================
	# Scene manipulation
	# ============================================================
	{
		"type": "function",
		"function": {
			"name": "add_node",
			"description": "Add a single new node to the edited scene. Use add_nodes for batch creation. Call save_scene after.",
			"parameters": {
				"type": "object",
				"properties": {
					"type": {
						"type": "string",
						"description": "Godot node class (e.g. 'Sprite2D', 'CharacterBody2D').",
					},
					"name": {
						"type": "string",
						"description": "Node name. Auto-generated if empty.",
					},
					"parent": {
						"type": "string",
						"description": "Parent path relative to scene root. Empty = root.",
					},
				},
				"required": [],
			},
		},
	},
	{
		"type": "function",
		"function": {
			"name": "add_nodes",
			"description": "Create an entire node hierarchy in one call (batch). Supports nested children and properties with auto type conversion. Call save_scene after.",
			"parameters": {
				"type": "object",
				"properties": {
					"nodes": {
						"type": "array",
						"description": "Array of node specs: {name, type, parent, properties, children}.",
						"items": {"type": "object"},
					},
				},
				"required": ["nodes"],
			},
		},
	},
	{
		"type": "function",
		"function": {
			"name": "delete_node",
			"description": "Delete a node and all its children. Cannot delete root. Call save_scene after.",
			"parameters": {
				"type": "object",
				"properties": {
					"path": {
						"type": "string",
						"description": "Node path relative to scene root.",
					},
				},
				"required": ["path"],
			},
		},
	},
	{
		"type": "function",
		"function": {
			"name": "move_node",
			"description": "Reparent a node to a different parent in the scene tree. Call save_scene after.",
			"parameters": {
				"type": "object",
				"properties": {
					"path": {
						"type": "string",
						"description": "Current node path.",
					},
					"new_parent": {
						"type": "string",
						"description": "New parent path.",
					},
				},
				"required": ["path", "new_parent"],
			},
		},
	},
	{
		"type": "function",
		"function": {
			"name": "duplicate_node",
			"description": "Duplicate a node and its children as a sibling. Call save_scene after.",
			"parameters": {
				"type": "object",
				"properties": {
					"path": {
						"type": "string",
						"description": "Node path to duplicate.",
					},
				},
				"required": ["path"],
			},
		},
	},
	{
		"type": "function",
		"function": {
			"name": "update_property",
			"description": "Set a property on a node. Supports auto type conversion: arrays -> Vector2/Color, strings -> Color/Resource. Call save_scene after.",
			"parameters": {
				"type": "object",
				"properties": {
					"path": {
						"type": "string",
						"description": "Node path. '.' for root.",
					},
					"property": {
						"type": "string",
						"description": "Property name (e.g. 'position', 'modulate', 'text').",
					},
					"value": {
						"description": "New value. Vector2: [x,y], Color: '#ff0000' or [r,g,b,a], Resource: 'res://path'.",
					},
				},
				"required": ["path", "property", "value"],
			},
		},
	},
	{
		"type": "function",
		"function": {
			"name": "create_scene",
			"description": "Create a new .tscn scene file, save it, and open it in the editor.",
			"parameters": {
				"type": "object",
				"properties": {
					"path": {
						"type": "string",
						"description": "Scene path (e.g. 'res://scenes/main.tscn').",
					},
					"root_type": {
						"type": "string",
						"description": "Root node class. Default 'Node2D'.",
					},
					"root_name": {
						"type": "string",
						"description": "Root node name. Default from filename.",
					},
				},
				"required": ["path"],
			},
		},
	},
	{
		"type": "function",
		"function": {
			"name": "open_scene",
			"description": "Open an existing .tscn scene file in the editor.",
			"parameters": {
				"type": "object",
				"properties": {
					"path": {
						"type": "string",
						"description": "Scene path (e.g. 'res://scenes/main.tscn').",
					},
				},
				"required": ["path"],
			},
		},
	},
	{
		"type": "function",
		"function": {
			"name": "find_nodes",
			"description": "Search the edited scene for nodes matching filters (type, group, name pattern, script). At least one filter required.",
			"parameters": {
				"type": "object",
				"properties": {
					"type": {
						"type": "string",
						"description": "Godot class name. Matches subclasses.",
					},
					"group": {
						"type": "string",
						"description": "Group name.",
					},
					"name": {
						"type": "string",
						"description": "Name pattern with * wildcards. Case-insensitive.",
					},
					"script": {
						"type": "string",
						"description": "Script filename suffix (e.g. 'player.gd').",
					},
					"max_results": {
						"type": "integer",
						"description": "Max nodes to return. Default 50.",
					},
				},
				"required": [],
			},
		},
	},
	# ============================================================
	# Scripts
	# ============================================================
	{
		"type": "function",
		"function": {
			"name": "execute_script",
			"description": "Execute GDScript in the EDITOR context. Use 'return <value>' to get results. No await allowed. Keep scripts simple.",
			"parameters": {
				"type": "object",
				"properties": {
					"code": {
						"type": "string",
						"description": "GDScript code body. Wrapped in a function.",
					},
				},
				"required": ["code"],
			},
		},
	},
	{
		"type": "function",
		"function": {
			"name": "view_script",
			"description": "Read the content of a .gd or .gdshader file from the project.",
			"parameters": {
				"type": "object",
				"properties": {
					"path": {
						"type": "string",
						"description": "Script path (e.g. 'res://scripts/player.gd').",
					},
				},
				"required": ["path"],
			},
		},
	},
	{
		"type": "function",
		"function": {
			"name": "write_script",
			"description": "Write or overwrite a GDScript file. Godot auto-reloads. Attach to a node with attach_script if new.",
			"parameters": {
				"type": "object",
				"properties": {
					"path": {
						"type": "string",
						"description": "File path (e.g. 'res://scripts/player.gd').",
					},
					"content": {
						"type": "string",
						"description": "Full GDScript source code.",
					},
				},
				"required": ["path", "content"],
			},
		},
	},
	{
		"type": "function",
		"function": {
			"name": "attach_script",
			"description": "Attach an existing .gd file to a node. Script must exist (use write_script first). Call save_scene after.",
			"parameters": {
				"type": "object",
				"properties": {
					"node": {
						"type": "string",
						"description": "Node path (e.g. 'Player'). '.' for root.",
					},
					"script": {
						"type": "string",
						"description": "Script path (e.g. 'res://scripts/player.gd').",
					},
				},
				"required": ["node", "script"],
			},
		},
	},
	# ============================================================
	# Project settings
	# ============================================================
	{
		"type": "function",
		"function": {
			"name": "project_settings",
			"description": "Read or modify Godot project settings. Use full path keys: 'display/window/size/viewport_width'.",
			"parameters": {
				"type": "object",
				"properties": {
					"action": {
						"type": "string",
						"enum": ["list", "get", "set"],
						"description": "list shows common settings, get reads one, set modifies one.",
					},
					"key": {
						"type": "string",
						"description": "Full setting key path. Required for get/set.",
					},
					"value": {
						"description": "New value (only for set). Must match expected type.",
					},
				},
				"required": ["action"],
			},
		},
	},
	{
		"type": "function",
		"function": {
			"name": "save_scene",
			"description": "Save the currently edited scene to disk. REQUIRED after any scene modification.",
			"parameters": {"type": "object", "properties": {}, "required": []},
		},
	},
]


static func get_tools_array() -> Array:
	return TOOL_DEFS


static func get_tool_names() -> PackedStringArray:
	var names: PackedStringArray = []
	for def in TOOL_DEFS:
		var fn: Dictionary = def.get("function", {})
		names.append(fn.get("name", ""))
	return names
