Files
MAF1/MAF1.Core/Decisions/DecisionModels.cs
T
admin777 a3cca78592 feat: 拆分 CLI 与网页宿主,并在无有效城市时暂停等人确认
将原单体 MAF1 拆成 MAF1(控制台工作流)和 MAF1.Web(可视化编排)。
抽城市失败时暂停:网页弹确认、CLI 控制台询问,超时采用默认结束查询;
也可改填城市后继续。共享决策模型放在 MAF1.Core。
2026-08-28 10:43:57 +08:00

98 lines
3.1 KiB
C#

using MAF1.Agents;
namespace MAF1.Decisions;
public sealed class DecisionRequest
{
public string Id { get; set; } = "";
public string NodeId { get; set; } = "";
public string Prompt { get; set; } = "";
public string? Reason { get; set; }
public List<DecisionOption> Options { get; set; } = [];
public string DefaultOptionId { get; set; } = "";
public int TimeoutSeconds { get; set; }
public DateTimeOffset Deadline { get; set; }
}
public sealed class DecisionOption
{
public string Id { get; set; } = "";
public string Label { get; set; } = "";
public string? Description { get; set; }
public bool RequiresText { get; set; }
public string? TextPlaceholder { get; set; }
public bool IsDefault { get; set; }
}
public sealed class DecisionAnswer
{
public string OptionId { get; set; } = "";
public string? Text { get; set; }
public bool TimedOut { get; set; }
}
public static class DecisionOptionIds
{
public const string Stop = "stop";
public const string QueryCities = "query-cities";
}
public static class EmptyCityDecision
{
public static DecisionRequest Create(string nodeId, string? reason, int timeoutSeconds)
{
int seconds = Math.Clamp(timeoutSeconds, 1, 600);
return new DecisionRequest
{
Id = Guid.NewGuid().ToString("n")[..12],
NodeId = nodeId,
Reason = reason,
Prompt = "没有读到有效城市。默认结束后续查询;也可以改填其它城市后继续。超时将自动采用默认方案。",
DefaultOptionId = DecisionOptionIds.Stop,
TimeoutSeconds = seconds,
Deadline = DateTimeOffset.UtcNow.AddSeconds(seconds),
Options =
[
new DecisionOption
{
Id = DecisionOptionIds.Stop,
Label = "结束查询(默认)",
Description = "保持当前结果,跳过需要城市的后续节点。",
IsDefault = true,
},
new DecisionOption
{
Id = DecisionOptionIds.QueryCities,
Label = "改查其它城市",
Description = "手动输入城市名,下游天气节点会按这份名单继续。",
RequiresText = true,
TextPlaceholder = "例如:成都、北京",
},
],
};
}
public static bool TryContinueWithCities(DecisionAnswer answer, out List<string> cities)
{
cities = [];
if (answer.TimedOut)
{
return false;
}
bool queryCities = answer.OptionId.Equals(DecisionOptionIds.QueryCities, StringComparison.OrdinalIgnoreCase);
if (!queryCities)
{
return false;
}
cities = ParseCities(answer.Text);
return cities.Count > 0;
}
public static List<string> ParseCities(string? text)
=> AgentInputs.ReadStringList(
new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase) { ["cities"] = text },
"cities");
}