初始提交
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
.env
|
||||
**/bin/
|
||||
**/obj/
|
||||
@@ -0,0 +1,20 @@
|
||||
# 插件目录
|
||||
|
||||
每个子文件夹是一个插件。软件启动后扫描**执行目录**下的 `plugins/`(即 `MAF1.exe` 旁边),不是源码目录。
|
||||
|
||||
## 必备文件
|
||||
|
||||
- `plugin.json`:id、启动命令、凭据声明、inputs、outputs
|
||||
- `README.md`:给使用者看的说明
|
||||
- 可执行文件 / 脚本 / 源码:由 `launch.command` + `launch.args` 原样启动
|
||||
|
||||
## 凭据(不要写进 plugin.json)
|
||||
|
||||
n8n / Dify 一类产品把 API Key 放在宿主凭据库,节点只声明「我需要哪种凭据」。本项目同样:
|
||||
|
||||
- Key 和 endpoint 配在宿主的环境变量或 `appsettings.json`
|
||||
- 节点可选 `credentialId`(默认 `llm-default`)
|
||||
- 启动子进程时注入环境变量,并在 stdin JSON 的 `credentials` 里再传一份
|
||||
- 浏览器和流程图 JSON **不会**包含 apiKey
|
||||
|
||||
第三方若要用自己的模型,可在插件目录放 `.env`(不要提交)。节点选中的宿主凭据会覆盖其中的同名变量。
|
||||
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\MAF1.Core\MAF1.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="plugin.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="README.md">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,11 @@
|
||||
using MAF1.Agents.FileCity;
|
||||
using MAF1.PluginContract;
|
||||
using MAF1.Utils;
|
||||
|
||||
PluginRequest request = await PluginStdio.ReadRequestAsync();
|
||||
PluginStdio.ApplyCredentialsToEnvironment(request.Credentials);
|
||||
|
||||
AgentFactory factory = new(AgentFactory.Load(PluginStdio.LoadHostConfiguration()));
|
||||
var result = await FileCityAgent.RunAsync(FileCityAgent.Create(factory), request.Inputs);
|
||||
await PluginStdio.WriteOutputsAsync(result.Outputs);
|
||||
return 0;
|
||||
@@ -0,0 +1,34 @@
|
||||
# FileCity 插件
|
||||
|
||||
独立进程。宿主只读取本目录的 `plugin.json`,按 `launch` 原样启动,不会替你拼命令。
|
||||
|
||||
## 输入 / 输出
|
||||
|
||||
字段名必须和 `plugin.json` 以及 `Program.cs` 里读写的 JSON 键一致。
|
||||
|
||||
- 输入 `filePath`
|
||||
- 输出 `hasValidCities`、`cities`、`reason`、`raw`
|
||||
|
||||
## 凭据
|
||||
|
||||
不要把 API Key 写进 `plugin.json` 或流程图。本插件声明需要 `openai-compatible` 凭据。运行时宿主会:
|
||||
|
||||
1. 把选中的凭据写入本进程环境变量 `OPENAI_ENDPOINT` / `OPENAI_API_KEY` / `OPENAI_CHAT_MODEL`
|
||||
2. 通过 stdin JSON 的 `credentials.llm` 再传一份
|
||||
|
||||
可选:在本目录放 `.env` 作为插件自己的默认环境(适合第三方自带模型)。节点上选中的宿主凭据会覆盖 `.env` 里的同名变量。
|
||||
|
||||
## 协议
|
||||
|
||||
stdin:
|
||||
|
||||
```json
|
||||
{
|
||||
"inputs": { "filePath": "Data/cities.txt" },
|
||||
"credentials": {
|
||||
"llm": { "id": "llm-default", "type": "openai-compatible", "endpoint": "...", "apiKey": "...", "model": "..." }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
stdout:单个 JSON 对象,字段等于 outputs。日志请写 stderr。
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"id": "fileCity",
|
||||
"name": "FileCityAgent",
|
||||
"description": "读取指定文本文件,判断并抽出有效城市名。",
|
||||
"version": "1.0.0",
|
||||
"timeoutSeconds": 120,
|
||||
"launch": {
|
||||
"command": "dotnet",
|
||||
"args": ["FileCityPlugin.dll"]
|
||||
},
|
||||
"credentials": [
|
||||
{
|
||||
"name": "llm",
|
||||
"type": "openai-compatible",
|
||||
"required": true,
|
||||
"description": "由宿主注入 OpenAI 兼容的 endpoint / apiKey / model,不要写进本文件。"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"name": "filePath",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"description": "本地文件路径,例如 Data/cities.txt"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{ "name": "hasValidCities", "type": "bool", "description": "是否存在有效城市" },
|
||||
{ "name": "cities", "type": "string[]", "description": "有效城市名列表" },
|
||||
{ "name": "reason", "type": "string", "description": "判断说明" },
|
||||
{ "name": "raw", "type": "string", "description": "Agent 原始文本" }
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using MAF1.Agents.Weather;
|
||||
using MAF1.PluginContract;
|
||||
using MAF1.Tools;
|
||||
using MAF1.Utils;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
PluginRequest request = await PluginStdio.ReadRequestAsync();
|
||||
PluginStdio.ApplyCredentialsToEnvironment(request.Credentials);
|
||||
|
||||
IConfiguration config = PluginStdio.LoadHostConfiguration();
|
||||
AgentFactory factory = new(AgentFactory.Load(config));
|
||||
WeatherOptions weatherOptions = config.GetSection("Weather").Get<WeatherOptions>() ?? new WeatherOptions();
|
||||
using HttpClient http = WeatherTools.CreateHttpClient();
|
||||
var result = await WeatherAgent.RunAsync(
|
||||
WeatherAgent.Create(factory, new WeatherTools(weatherOptions, http)),
|
||||
request.Inputs);
|
||||
await PluginStdio.WriteOutputsAsync(result.Outputs);
|
||||
return 0;
|
||||
@@ -0,0 +1,12 @@
|
||||
# Weather 插件
|
||||
|
||||
独立进程。启动命令只看 `plugin.json` 的 `launch`。
|
||||
|
||||
## 输入 / 输出
|
||||
|
||||
- 输入 `cities`(字符串数组,与代码、清单同名)
|
||||
- 输出 `summary`
|
||||
|
||||
## 凭据
|
||||
|
||||
LLM 的 endpoint / apiKey 由宿主注入,不出现在流程图端口上。天气 HTTP 配置走宿主 `appsettings.json`(通过环境变量 `MAF1_CONTENT_ROOT` 定位)。
|
||||
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\MAF1.Core\MAF1.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="plugin.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="README.md">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"id": "weather",
|
||||
"name": "WeatherAgent",
|
||||
"description": "按城市列表查询天气并汇总。",
|
||||
"version": "1.0.0",
|
||||
"timeoutSeconds": 180,
|
||||
"launch": {
|
||||
"command": "dotnet",
|
||||
"args": ["WeatherPlugin.dll"]
|
||||
},
|
||||
"credentials": [
|
||||
{
|
||||
"name": "llm",
|
||||
"type": "openai-compatible",
|
||||
"required": true,
|
||||
"description": "由宿主注入 OpenAI 兼容的 endpoint / apiKey / model,不要写进本文件。"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"name": "cities",
|
||||
"type": "string[]",
|
||||
"required": true,
|
||||
"description": "要查询的城市名列表"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{ "name": "summary", "type": "string", "description": "天气汇总文本" }
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user