docs: 为 CLI、网页编排器和插件协议补充学习向注释
在核心类型、图执行器、stdio 插件和前端入口写清职责与对照路径,不改运行行为。
This commit is contained in:
@@ -9,6 +9,11 @@ using Microsoft.Agents.AI;
|
||||
|
||||
namespace MAF1.Web;
|
||||
|
||||
/// <summary>
|
||||
/// 网页自己的图执行器(不是 Microsoft Agents AI Workflow)。
|
||||
/// 流程:拓扑排序 → 按边接线组装输入 → 跑系统节点或插件进程 → 若抽城市失败则暂停等人。
|
||||
/// 和 CLI 对照:这里用 DAG + when 条件,CLI 用 WorkflowBuilder 的 Executor 图。
|
||||
/// </summary>
|
||||
public sealed class ConfigurableWorkflowRunner(
|
||||
AIAgent fileCityAgent,
|
||||
AIAgent weatherAgent,
|
||||
@@ -17,6 +22,7 @@ public sealed class ConfigurableWorkflowRunner(
|
||||
WorkflowRunStore runs,
|
||||
int decisionTimeoutSeconds)
|
||||
{
|
||||
/// <summary>这些 config 键不是业务输入端口,接线时不要当 filePath 那样传给 Agent。</summary>
|
||||
private static readonly HashSet<string> ReservedConfigKeys = new(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
"credentialId",
|
||||
@@ -24,6 +30,7 @@ public sealed class ConfigurableWorkflowRunner(
|
||||
"decisionTimeoutSeconds",
|
||||
};
|
||||
|
||||
/// <summary>开始一次运行。后面若暂停,用同一 runId 继续 DecideAsync。</summary>
|
||||
public async Task<WorkflowRunResult> RunAsync(WorkflowGraph graph, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
@@ -62,6 +69,7 @@ public sealed class ConfigurableWorkflowRunner(
|
||||
return await ResolveAsync(session, answer, cancellationToken, session.Pending?.Id);
|
||||
}
|
||||
|
||||
/// <summary>从 session.NextIndex 接着跑。条件不满足的节点记 Skipped,不调用 LLM。</summary>
|
||||
private async Task<WorkflowRunResult> ContinueAsync(WorkflowSession session, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
@@ -107,6 +115,7 @@ public sealed class ConfigurableWorkflowRunner(
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>返回 needsDecision,并在后台倒计时到点后按默认方案 ResolveAsync。</summary>
|
||||
private WorkflowRunResult PauseForEmptyCities(WorkflowSession session, WorkflowNode node, NodeRunLog log)
|
||||
{
|
||||
string? reason = ReadString(log.Outputs, "reason");
|
||||
@@ -167,6 +176,7 @@ public sealed class ConfigurableWorkflowRunner(
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>把确认结果写回该节点的 outputs(例如改写 cities),然后继续后续节点。</summary>
|
||||
private async Task<WorkflowRunResult> ResolveAsync(
|
||||
WorkflowSession session,
|
||||
DecisionAnswer answer,
|
||||
@@ -319,6 +329,7 @@ public sealed class ConfigurableWorkflowRunner(
|
||||
Steps = steps ?? [],
|
||||
};
|
||||
|
||||
/// <summary>节点输出了 hasValidCities=false,且后面还有节点时,默认要弹确认。config 可关。</summary>
|
||||
private static bool ShouldAskEmptyCities(WorkflowNode node, NodeRunLog log)
|
||||
{
|
||||
if (log.Skipped)
|
||||
@@ -340,6 +351,7 @@ public sealed class ConfigurableWorkflowRunner(
|
||||
return !ReadBool(log.Outputs, "hasValidCities");
|
||||
}
|
||||
|
||||
/// <summary>插件 id 优先于系统节点。系统节点按 Handler 调 FileCityAgent / WeatherAgent。</summary>
|
||||
private async Task<NodeRunLog> RunNodeAsync(
|
||||
NodeCatalogSnapshot snapshot,
|
||||
WorkflowNode node,
|
||||
@@ -439,6 +451,7 @@ public sealed class ConfigurableWorkflowRunner(
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Kahn 算法拓扑排序。有环则无法确定执行顺序。</summary>
|
||||
private static List<string> TopologicalOrder(WorkflowGraph graph)
|
||||
{
|
||||
Dictionary<string, int> indegree = graph.Nodes.ToDictionary(n => n.Id, _ => 0);
|
||||
@@ -473,6 +486,7 @@ public sealed class ConfigurableWorkflowRunner(
|
||||
return order;
|
||||
}
|
||||
|
||||
/// <summary>先填节点 Config,再用入边把上游输出端口覆盖到下游输入端口(连线优先)。</summary>
|
||||
private static Dictionary<string, object?> ResolveInputs(
|
||||
WorkflowGraph graph,
|
||||
WorkflowNode node,
|
||||
@@ -505,6 +519,7 @@ public sealed class ConfigurableWorkflowRunner(
|
||||
return inputs;
|
||||
}
|
||||
|
||||
/// <summary>入边 When 不满足则跳过本节点。当前只实现 hasValidCities 这一类条件。</summary>
|
||||
private static bool PassEdgeConditions(
|
||||
WorkflowGraph graph,
|
||||
WorkflowNode node,
|
||||
|
||||
Reference in New Issue
Block a user