105 lines
3.7 KiB
C#
105 lines
3.7 KiB
C#
using System.Text.Json;
|
|
|
|
namespace AxCopilot.Services.Agent;
|
|
|
|
/// <summary>에이전트가 사용자에게 질문하고 응답을 대기하는 도구.</summary>
|
|
public class UserAskTool : IAgentTool
|
|
{
|
|
public string Name => "user_ask";
|
|
public string Description =>
|
|
"Ask the user a question and wait for their response. " +
|
|
"Use when you need clarification, confirmation, or a choice from the user. " +
|
|
"Optionally provide predefined options for the user to pick from. " +
|
|
"The user can select from options OR type a custom response.";
|
|
|
|
public ToolParameterSchema Parameters => new()
|
|
{
|
|
Properties = new()
|
|
{
|
|
["question"] = new()
|
|
{
|
|
Type = "string",
|
|
Description = "The question to ask the user",
|
|
},
|
|
["options"] = new()
|
|
{
|
|
Type = "array",
|
|
Description = "Optional list of choices for the user (e.g. ['Option A', 'Option B'])",
|
|
Items = new() { Type = "string", Description = "Choice option" },
|
|
},
|
|
["default_value"] = new()
|
|
{
|
|
Type = "string",
|
|
Description = "Default value if user doesn't specify",
|
|
},
|
|
},
|
|
Required = ["question"],
|
|
};
|
|
|
|
public async Task<ToolResult> ExecuteAsync(JsonElement args, AgentContext context, CancellationToken ct = default)
|
|
{
|
|
var question = args.GetProperty("question").GetString() ?? "";
|
|
var defaultVal = args.TryGetProperty("default_value", out var dv) ? dv.GetString() ?? "" : "";
|
|
|
|
var options = new List<string>();
|
|
if (args.TryGetProperty("options", out var opts) && opts.ValueKind == JsonValueKind.Array)
|
|
{
|
|
foreach (var o in opts.EnumerateArray())
|
|
{
|
|
var s = o.GetString();
|
|
if (!string.IsNullOrEmpty(s)) options.Add(s);
|
|
}
|
|
}
|
|
|
|
// UserAskCallback 사용 (커스텀 대화 상자)
|
|
if (context.UserAskCallback != null)
|
|
{
|
|
try
|
|
{
|
|
var response = await context.UserAskCallback(question, options, defaultVal);
|
|
if (response == null)
|
|
return ToolResult.Fail("사용자가 응답을 취소했습니다.");
|
|
|
|
return ToolResult.Ok($"사용자 응답: {response}");
|
|
}
|
|
catch (OperationCanceledException)
|
|
{
|
|
return ToolResult.Fail("사용자가 응답을 취소했습니다.");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return ToolResult.Fail($"사용자 입력 오류: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
// 폴백: UserDecision 콜백
|
|
if (context.UserDecision != null)
|
|
{
|
|
try
|
|
{
|
|
var prompt = question;
|
|
if (!string.IsNullOrEmpty(defaultVal))
|
|
prompt += $"\n(기본값: {defaultVal})";
|
|
|
|
var effectiveOptions = options.Count > 0 ? options : new List<string> { "확인" };
|
|
var response = await context.UserDecision(prompt, effectiveOptions);
|
|
|
|
if (string.IsNullOrEmpty(response) && !string.IsNullOrEmpty(defaultVal))
|
|
response = defaultVal;
|
|
|
|
return ToolResult.Ok($"사용자 응답: {response}");
|
|
}
|
|
catch (OperationCanceledException)
|
|
{
|
|
return ToolResult.Fail("사용자가 응답을 취소했습니다.");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return ToolResult.Fail($"사용자 입력 오류: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
return ToolResult.Fail("사용자 입력 콜백이 등록되지 않았습니다.");
|
|
}
|
|
}
|