节点在线、应用在线、配置在线使用令牌查询
大石头 authored at 2021-12-16 19:49:30
3.35 KiB
Stardust
using System.Text.Json;
using NewLife;
using Stardust;
using Stardust.Data.Nodes;

using Stardust.Data.Platform;

namespace Stardust.Web.Mcp.Actions.Nodes;

/// <summary>升级指定节点上的StarAgent。通过StarFactory下发node/upgrade命令</summary>
public class NodeUpgradeAction : McpActionBase
{
    private readonly StarFactory _starFactory;

    /// <summary>构造函数注入StarFactory</summary>
    public NodeUpgradeAction(StarFactory starFactory) => _starFactory = starFactory;

    /// <summary>动作名</summary>
    public override String Name => "node_upgrade";

    /// <summary>动作描述</summary>
    public override String Description => "升级指定节点上的StarAgent到最新版本(异步执行)。需要Token已授权该节点。";

    /// <summary>所属模块</summary>
    public override McpModuleType Module => McpModuleType.Node;

    /// <summary>所需资源授权。框架层校验node_id在授权范围</summary>
    public override ResourceRequirement? RequiredResource => new()
    {
        Type = McpResourceType.Node.ToWireName(),
        Field = "node_id",
    };

    /// <summary>输入参数JSON Schema</summary>
    public override JsonElement InputSchema
    {
        get
        {
            var json = """
            {
              "type": "object",
              "properties": {
                "node_id": {"type": "integer", "description": "节点ID"},
                "channel": {"type": "string", "description": "可选,升级通道(如 stable/preview),不传使用节点默认通道"},
                "expire": {"type": "integer", "description": "可选,命令过期时间(秒),默认600"},
                "timeout": {"type": "integer", "description": "可选,等待回复超时(秒),默认0(不等待)"}
              },
              "required": ["node_id"]
            }
            """;
            using var doc = JsonDocument.Parse(json);
            return doc.RootElement.Clone();
        }
    }

    /// <summary>调用动作</summary>
    public override async Task<Object> InvokeAsync(JsonElement @params, McpContext context)
    {
        var nodeId = GetInt32(@params, "node_id");
        if (nodeId <= 0) throw new McpException(-32602, "Invalid params: node_id must be a positive integer");

        var channel = GetString(@params, "channel");
        var expire = GetInt32(@params, "expire"); if (expire <= 0) expire = 600;
        var timeout = GetInt32(@params, "timeout"); // 0表示不等待回复

        // 根据node_id查找节点Code
        var node = Node.FindByID(nodeId);
        if (node == null) throw new McpException(-32601, $"Node not found: id={nodeId}");
        if (node.Code.IsNullOrEmpty()) throw new McpException(-32603, $"Node has no Code: id={nodeId}");
        if (!node.Enable) throw new McpException(-32603, $"Node is disabled: id={nodeId}");

        // 下发升级命令:node/upgrade,channel作为argument传入
        var reply = await _starFactory.SendNodeCommandAsync(node.Code, "node/upgrade", channel, 0, expire, timeout);

        return new
        {
            node_id = nodeId,
            node_code = node.Code,
            node_name = node.Name,
            current_version = node.Version,
            channel = channel,
            expire,
            timeout,
            reply = reply?.Data,
            status = reply?.Status.ToString(),
        };
    }
}