/* ┌──────────────────────────────────────────────────────────────────┐ │ Author: Ivan Murzak (https://github.com/IvanMurzak) │ │ Repository: GitHub (https://github.com/IvanMurzak/Unity-MCP) │ │ Copyright (c) 2025 Ivan Murzak │ │ Licensed under the Apache License, Version 2.0. │ │ See the LICENSE file in the project root for more information. │ └──────────────────────────────────────────────────────────────────┘ */ #nullable enable using System; using System.Collections.Generic; using System.Linq; using System.Text.Json.Nodes; using com.IvanMurzak.McpPlugin; using com.IvanMurzak.ReflectorNet.Utils; using com.IvanMurzak.Unity.MCP.Editor.Utils; using Extensions.Unity.PlayerPrefsEx; using Microsoft.Extensions.Logging; using R3; using UnityEngine.UIElements; namespace com.IvanMurzak.Unity.MCP.Editor.UI { public class McpPromptsWindow : McpListWindowBase { private static readonly string[] _windowUxmlPaths = EditorAssetLoader.GetEditorAssetPaths("Editor/UI/uxml/McpPromptsWindow.uxml"); private static readonly string[] _itemUxmlPaths = EditorAssetLoader.GetEditorAssetPaths("Editor/UI/uxml/PromptItem.uxml"); private static readonly string[] _windowUssPaths = EditorAssetLoader.GetEditorAssetPaths("Editor/UI/uss/McpPromptsWindow.uss"); protected override string[] WindowUxmlPaths => _windowUxmlPaths; protected override string[] ItemUxmlPaths => _itemUxmlPaths; protected override string[] WindowUssPaths => _windowUssPaths; protected override string WindowTitle => "MCP Prompts"; protected override string MissingTemplateMessage => "PromptItem template is missing. Please ensure PromptItem.uxml exists in the package or the Packages/com.ivanmurzak.unity.mcp folder."; public static McpPromptsWindow ShowWindow() { var window = GetWindow("MCP Prompts"); window.SetupWindowWithIcon(); window.Show(); window.Focus(); return window; } protected override Observable? GetOnUpdatedObservable(IMcpPlugin plugin) => plugin.McpManager.PromptManager?.OnPromptsUpdated; protected override void RefreshItems() { var promptManager = UnityMcpPluginEditor.Instance.Prompts; var refreshed = new List(); if (promptManager != null) { foreach (var prompt in promptManager.GetAllPrompts().Where(prompt => prompt != null)) { refreshed.Add(new PromptViewModel(promptManager, prompt)); } } allItems = refreshed; } protected override void OnItemToggleChanged(PromptViewModel viewModel, bool isEnabled) { var promptManager = UnityMcpPluginEditor.Instance.Prompts; if (promptManager == null) { Logger.LogError("{method} PromptManager is not available.", nameof(OnItemToggleChanged)); return; } viewModel.IsEnabled = isEnabled; if (!string.IsNullOrWhiteSpace(viewModel.Name)) { Logger.LogTrace("{method} Setting prompt '{name}' enabled state to {enabled}.", nameof(OnItemToggleChanged), viewModel.Name, isEnabled); promptManager.SetPromptEnabled(viewModel.Name, isEnabled); UnityMcpPluginEditor.Instance.Save(); } } protected override void OnFoldoutChanged(PromptViewModel viewModel, string foldoutName, bool isExpanded) { switch (foldoutName) { case "description-foldout": viewModel.descriptionExpanded.Value = isExpanded; break; case "arguments-foldout": viewModel.argumentsExpanded.Value = isExpanded; break; } } protected override void BindItem(VisualElement element, PromptViewModel viewModel) { BindCommonItemFields(element, viewModel); BindDescriptionFoldout(element, viewModel, viewModel.descriptionExpanded.Value); var roleLabel = element.Q