2026-08-26 18:06:02 +08:00
|
|
|
using System.Text.Json.Serialization;
|
|
|
|
|
|
|
|
|
|
namespace MAF1.PluginContract;
|
|
|
|
|
|
2026-08-28 11:51:48 +08:00
|
|
|
/// <summary>
|
|
|
|
|
/// 每个插件目录里的 plugin.json。网页宿主扫描这个文件来画节点端口,不会加载插件 DLL。
|
|
|
|
|
/// Id 会出现在画布节点的 Type 上。
|
|
|
|
|
/// </summary>
|
2026-08-26 18:06:02 +08:00
|
|
|
public sealed class PluginManifest
|
|
|
|
|
{
|
|
|
|
|
public string Id { get; set; } = "";
|
|
|
|
|
public string Name { get; set; } = "";
|
|
|
|
|
public string Description { get; set; } = "";
|
|
|
|
|
public string Version { get; set; } = "1.0.0";
|
|
|
|
|
public PluginLaunch Launch { get; set; } = new();
|
|
|
|
|
public int TimeoutSeconds { get; set; }
|
|
|
|
|
public Dictionary<string, string> Env { get; set; } = new(StringComparer.OrdinalIgnoreCase);
|
|
|
|
|
public List<PluginCredentialNeed> Credentials { get; set; } = [];
|
|
|
|
|
public List<PluginPort> Inputs { get; set; } = [];
|
|
|
|
|
public List<PluginPort> Outputs { get; set; } = [];
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-28 11:51:48 +08:00
|
|
|
/// <summary>如何启动插件进程。Command 可以是相对插件目录的 exe,或 dotnet + dll。</summary>
|
2026-08-26 18:06:02 +08:00
|
|
|
public sealed class PluginLaunch
|
|
|
|
|
{
|
|
|
|
|
public string Command { get; set; } = "";
|
|
|
|
|
public List<string> Args { get; set; } = [];
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-28 11:51:48 +08:00
|
|
|
/// <summary>画布上的一个输入或输出端口。Name 必须和代码里读写的字段一致。</summary>
|
2026-08-26 18:06:02 +08:00
|
|
|
public sealed class PluginPort
|
|
|
|
|
{
|
|
|
|
|
public string Name { get; set; } = "";
|
|
|
|
|
public string Type { get; set; } = "string";
|
|
|
|
|
public string Description { get; set; } = "";
|
|
|
|
|
public bool Required { get; set; }
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-28 11:51:48 +08:00
|
|
|
/// <summary>插件声明「我需要哪种凭据」。宿主按 Type 注入,Key 不进流程图 JSON。</summary>
|
2026-08-26 18:06:02 +08:00
|
|
|
public sealed class PluginCredentialNeed
|
|
|
|
|
{
|
|
|
|
|
public string Name { get; set; } = "";
|
|
|
|
|
public string Type { get; set; } = "";
|
|
|
|
|
public bool Required { get; set; } = true;
|
|
|
|
|
public string Description { get; set; } = "";
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-28 11:51:48 +08:00
|
|
|
/// <summary>宿主写入插件 stdin 的整包请求:业务输入 + 凭据。</summary>
|
2026-08-26 18:06:02 +08:00
|
|
|
public sealed class PluginRequest
|
|
|
|
|
{
|
|
|
|
|
public Dictionary<string, object?> Inputs { get; set; } = new(StringComparer.OrdinalIgnoreCase);
|
|
|
|
|
|
|
|
|
|
[JsonPropertyName("credentials")]
|
|
|
|
|
public Dictionary<string, PluginCredentialPayload> Credentials { get; set; } = new(StringComparer.OrdinalIgnoreCase);
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-28 11:51:48 +08:00
|
|
|
/// <summary>实际的 endpoint / apiKey / model。只在宿主→插件进程之间传递。</summary>
|
2026-08-26 18:06:02 +08:00
|
|
|
public sealed class PluginCredentialPayload
|
|
|
|
|
{
|
|
|
|
|
public string Id { get; set; } = "";
|
|
|
|
|
public string Type { get; set; } = "";
|
|
|
|
|
public string? Endpoint { get; set; }
|
|
|
|
|
public string? ApiKey { get; set; }
|
|
|
|
|
public string? Model { get; set; }
|
|
|
|
|
public Dictionary<string, string> Extra { get; set; } = new(StringComparer.OrdinalIgnoreCase);
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-28 11:51:48 +08:00
|
|
|
/// <summary>插件 JSON 统一 camelCase,和网页前端字段名对齐。</summary>
|
2026-08-26 18:06:02 +08:00
|
|
|
public static class PluginJson
|
|
|
|
|
{
|
|
|
|
|
public static readonly System.Text.Json.JsonSerializerOptions Options = new()
|
|
|
|
|
{
|
|
|
|
|
PropertyNameCaseInsensitive = true,
|
|
|
|
|
PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase,
|
|
|
|
|
WriteIndented = false,
|
|
|
|
|
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
|
|
|
|
};
|
|
|
|
|
}
|