Initial commit to new repository
This commit is contained in:
104
src/AxCopilot/Services/Agent/UserAskTool.cs
Normal file
104
src/AxCopilot/Services/Agent/UserAskTool.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
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("사용자 입력 콜백이 등록되지 않았습니다.");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user