Files
admin777 b631acd42e feat: 将插件 stdin 协议定为 v1,并按声明注入凭据
进程外插件改为只读环境变量和自身配置,避免读宿主 appsettings;宿主按 plugin.json 声明注入 LLM / OpenWeather 等凭据。
2026-09-11 10:46:52 +08:00

48 lines
3.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MAF1 — Agent Instructions
.NET 10 多智能体工作流编排演示仓库(Microsoft Agents AI + ASP.NET Core + 进程外插件)。完整文档见 [README.md](README.md) 和 [plugins/README.md](Plugins/README.md)。
## 项目结构(6 个工程,`MAF1.slnx`
| 工程 | 作用 |
|------|------|
| `MAF1.Core` | 唯一共享层:Agent、Tool、LLM 工厂、插件协议。所有工程都引用它 |
| `MAF1` | 命令行工作流(`node`/`edge` 两种条件写法) |
| `MAF1.Route` | 命令行路由(方案 C`WithHandoff` 交接) |
| `MAF1.Web` | ASP.NET Core Minimal API 可视化编排器 + `wwwroot`(原生 JS,无 npm |
| `Plugins/file-city``Plugins/weather` | 进程外插件(stdin/stdout JSON |
## 构建 / 运行
```powershell
dotnet build # 还原 + 编译(在仓库根目录)
dotnet run --project MAF1 -- node Data/cities.txt
dotnet run --project MAF1 -- edge Data/not-cities.txt
dotnet run --project MAF1.Route -- Graphs/city-weather.json
dotnet run --project MAF1.Web # 浏览器 http://127.0.0.1:5288
```
没有测试工程。验证靠 UI 示例图 + 两个 CLI 命令。解决方案是 `MAF1.slnx`**不是 `.sln`**)。
## 关键陷阱(改代码前必读)
1. **插件运行时读的是 bin 输出,不是源码树**`PluginScanner` 扫描 `MAF1.Web.exe` 旁的 `plugins/`。改完 `Plugins/` 源码必须重新 `dotnet build`(靠 `MAF1.Web.csproj``PublishPluginFolders` 目标复制)或点前端「刷新节点」。
2. **不要提交 API Key**Key 走环境变量或 `appsettings.json``Llm` / `Credentials` 段(环境变量优先)。注意 `**/Properties/launchSettings.json` 里目前硬编码了一个真实 Key,新增/修改配置时切勿再写入真实密钥,也勿把含 Key 的版本提交。
3. **插件 stdout 只能输出一行 JSON**:日志和提示走 stderr,否则宿主 `ParseOutputs` 会解析失败。
4. **天气查询必须用 `WeatherTools.CreateHttpClient()`**:带 20s 超时和正确 User-Agent,直接 `new HttpClient()` 可能被 wttr.in 拒绝。
5. **LLM 输出解析前先过 `JsonText.UnwrapObject`**:剥离模型回复的 ```json ``` 围栏后再反序列化。
6. **进程外插件不要读宿主 appsettings**LLM 用 `AgentFactory.LoadFromEnvironment()`;其它配置用插件目录自己的 json。stdin 协议见 `docs/plugin-protocol-v1.schema.json``protocolVersion` 1)。
## 约定
- **JSON 序列化**camelCase + 反射(无 source gen)。统一入口 `MAF1.PluginContract.PluginJson.Options`Web 用 `ConfigureHttpJsonOptions`。个别类用 `[JsonPropertyName(...)]` 显式标注。
- **LLM 创建只经 `AgentFactory.Load` / `AgentFactory.CreateAgent`**`MAF1.Core/Utils/AgentFactory.cs`)。识别环境变量 `OPENAI_API_KEY` / `OPENAI_ENDPOINT`(或 `OPENAI_BASE_URL`/ `OPENAI_CHAT_MODEL`DeepSeek endpoint 会自动禁用 thinking`DeepSeekThinking.Disable`)。
- **每个 `Program.cs` 第一行调用 `WindowsConsole.EnableUtf8()`**(避免中文乱码)。
- **Agent 用静态工厂**`FileCityAgent.Create` / `WeatherAgent.Create`,业务逻辑集中在 `RunAsync`。CLI、Web 系统节点、插件三处复用同一套。
- **文件组织**:多数一文件一类;但 `PluginManifest.cs``DecisionModels.cs``RouteGraph.cs` 等有意把多个紧相关小类放一个文件,属惯例。
- **命名空间与目录不严格对应**:如 `MAF1.Web/PluginHost/*.cs``MAF1.Plugins`Core 里 `Agents/FileCity``MAF1.Agents.FileCity`,而 `AgentStepResult.cs``MAF1.Core.Agents`
## 建议的上手路径
`README.md``MAF1.Core/Utils/AgentFactory.cs`LLM 配置)→ `FileCityAgent.cs` / `WeatherAgent.cs`Agent 写法)→ `PluginContract/PluginStdio.cs` + `MAF1.Web/PluginHost/PluginProcessRunner.cs`(插件协议两端)→ `MAF1/Workflows/CityWeatherWorkflow.cs`Workflow 用法)→ `MAF1.Route/HandoffGraphBuilder.cs`Handoff 用法)。