V13-FE-011: finalize search list layout slice
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
using Dapper;
|
||||
using FastEndpoints;
|
||||
using KBX.Shared.Experience;
|
||||
using Npgsql;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace KBX.Modules.Common.Ai.Ask;
|
||||
|
||||
public sealed record Request(string Question, AiScreenContext Context);
|
||||
|
||||
public sealed class Endpoint(IKbxAiAssistantProvider assistant, NpgsqlDataSource dataSource) : Endpoint<Request, AiAnswer>
|
||||
{
|
||||
public override void Configure()
|
||||
{
|
||||
Post("/api/common/ai/ask");
|
||||
Permissions("common.ai.use");
|
||||
}
|
||||
|
||||
public override async Task HandleAsync(Request req, CancellationToken ct)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(req.Question) || req.Question.Length > 2000)
|
||||
{
|
||||
AddError(r => r.Question, "질문을 1~2000자로 입력하세요.");
|
||||
await Send.ErrorsAsync(cancellation: ct);
|
||||
return;
|
||||
}
|
||||
|
||||
// Host application replaces this with authenticated claims resolution.
|
||||
var tenantId = Guid.Empty;
|
||||
var userId = Guid.Empty;
|
||||
var sw = Stopwatch.StartNew();
|
||||
var answer = await assistant.AskAsync(tenantId, userId, new AiAskCommand(req.Question.Trim(), req.Context), ct);
|
||||
sw.Stop();
|
||||
|
||||
await using var connection = await dataSource.OpenConnectionAsync(ct);
|
||||
await connection.ExecuteAsync(new CommandDefinition("""
|
||||
insert into kbx.ai_interactions
|
||||
(id, tenant_id, user_id, screen_id, screen_version, capability, result_kind, provider, duration_ms)
|
||||
values
|
||||
(@Id, @TenantId, @UserId, @ScreenId, @ScreenVersion, 'explain', @ResultKind, @Provider, @DurationMs)
|
||||
""", new
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
TenantId = tenantId,
|
||||
UserId = userId,
|
||||
req.Context.ScreenId,
|
||||
req.Context.ScreenVersion,
|
||||
ResultKind = answer.Proposal is null ? "answer" : "proposal",
|
||||
Provider = assistant.GetType().Name,
|
||||
DurationMs = (int)sw.ElapsedMilliseconds,
|
||||
}, cancellationToken: ct));
|
||||
|
||||
await Send.OkAsync(answer, ct);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user