feat: 新增方案 C 的 Handoff 路由宿主,并让抽城市支持自然语言。
把图 JSON 编译成 CreateHandoffBuilderWith + WithHandoff;Agent 固定 Id 以免交接工具名错位;DeepSeek 关闭 thinking,避免多轮丢掉 reasoning_content 导致 400。
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
namespace MAF1.Decisions;
|
||||
|
||||
/// <summary>
|
||||
/// CLI 版确认框。回车 / 1 = 结束查询;2 = 再输入城市;也可以直接打「成都」。
|
||||
/// ReadLine 和超时赛跑:到期返回 TimedOut,走默认方案。
|
||||
/// MAF1 工作流 CLI 与 MAF1.Route 共用。
|
||||
/// </summary>
|
||||
public static class ConsoleDecisionPrompt
|
||||
{
|
||||
public static async Task<DecisionAnswer> WaitAsync(DecisionRequest request)
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("[需要确认]");
|
||||
Console.WriteLine(request.Prompt);
|
||||
if (!string.IsNullOrWhiteSpace(request.Reason))
|
||||
{
|
||||
Console.WriteLine($"原因:{request.Reason}");
|
||||
}
|
||||
|
||||
Console.WriteLine($"未及时确认将使用默认方案。等待 {request.TimeoutSeconds} 秒。");
|
||||
for (int i = 0; i < request.Options.Count; i++)
|
||||
{
|
||||
DecisionOption option = request.Options[i];
|
||||
string mark = option.IsDefault ? " ← 默认" : "";
|
||||
Console.WriteLine($" {i + 1}) {option.Label}{mark}");
|
||||
if (!string.IsNullOrWhiteSpace(option.Description))
|
||||
{
|
||||
Console.WriteLine($" {option.Description}");
|
||||
}
|
||||
}
|
||||
|
||||
Console.Write("输入序号,或直接回车采用默认:");
|
||||
string? line = await ReadLineOrTimeoutAsync(request.Deadline);
|
||||
if (line is null)
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("未及时确认,采用默认方案:结束查询。");
|
||||
return new DecisionAnswer { OptionId = request.DefaultOptionId, TimedOut = true };
|
||||
}
|
||||
|
||||
line = line.Trim();
|
||||
if (line.Length == 0 || line is "1" || line.Equals("stop", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return new DecisionAnswer { OptionId = DecisionOptionIds.Stop };
|
||||
}
|
||||
|
||||
if (line is "2" || line.Equals(DecisionOptionIds.QueryCities, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
Console.Write("请输入城市名(例如 成都、北京):");
|
||||
string? cities = await ReadLineOrTimeoutAsync(request.Deadline);
|
||||
if (cities is null)
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("未及时输入城市,采用默认方案:结束查询。");
|
||||
return new DecisionAnswer { OptionId = DecisionOptionIds.Stop, TimedOut = true };
|
||||
}
|
||||
|
||||
if (EmptyCityDecision.ParseCities(cities).Count == 0)
|
||||
{
|
||||
Console.WriteLine("没有有效城市名,采用默认方案:结束查询。");
|
||||
return new DecisionAnswer { OptionId = DecisionOptionIds.Stop };
|
||||
}
|
||||
|
||||
return new DecisionAnswer { OptionId = DecisionOptionIds.QueryCities, Text = cities };
|
||||
}
|
||||
|
||||
if (EmptyCityDecision.ParseCities(line).Count > 0)
|
||||
{
|
||||
return new DecisionAnswer { OptionId = DecisionOptionIds.QueryCities, Text = line };
|
||||
}
|
||||
|
||||
Console.WriteLine("无法识别输入,采用默认方案:结束查询。");
|
||||
return new DecisionAnswer { OptionId = DecisionOptionIds.Stop };
|
||||
}
|
||||
|
||||
/// <summary>超时返回 null。注意:超时后后台的 ReadLine 仍可能阻塞,学习项目可接受。</summary>
|
||||
private static async Task<string?> ReadLineOrTimeoutAsync(DateTimeOffset deadline)
|
||||
{
|
||||
TimeSpan remain = deadline - DateTimeOffset.UtcNow;
|
||||
if (remain <= TimeSpan.Zero)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Task<string?> read = Task.Run(() => Console.ReadLine());
|
||||
Task delay = Task.Delay(remain);
|
||||
Task finished = await Task.WhenAny(read, delay);
|
||||
if (finished == delay)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return await read;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user