Files
Teamup/src/Modules/TeamUp.Modules.Assembler/Runtime/AgentRunExecutor.cs
T

49 lines
1.9 KiB
C#
Raw Normal View History

using System.Text.Json;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using TeamUp.Modules.Assembler.Domain;
using TeamUp.Modules.Assembler.Persistence;
namespace TeamUp.Modules.Assembler.Runtime;
internal sealed record AgentRunPayload(Guid RunId);
/// <summary>
/// Processes one claimed job: drives the AgentRun lifecycle. In M4 Increment 1 it records a
/// placeholder; Increment 2 swaps the middle for the real assembler (assemble → model → parse).
/// </summary>
internal sealed class AgentRunExecutor(AssemblerDbContext db, TimeProvider clock, ILogger<AgentRunExecutor> logger)
{
public async Task ProcessAsync(Job job, CancellationToken cancellationToken = default)
{
try
{
var payload = JsonSerializer.Deserialize<AgentRunPayload>(job.Payload)
?? throw new InvalidOperationException("Invalid job payload.");
var run = await db.AgentRuns.FirstOrDefaultAsync(r => r.Id == payload.RunId, cancellationToken)
?? throw new InvalidOperationException($"AgentRun {payload.RunId} not found.");
run.Start(agentId: null, prompt: "[assembler pending — M4 Increment 2]", trace: null);
await db.SaveChangesAsync(cancellationToken);
// TODO (M4 Increment 2): assemble the prompt, call the model, parse into action + risk.
run.Complete(
output: "[assembler pending]",
actionType: "pending",
actionRisk: "read",
resultJson: null,
latencyMs: 0,
clock.GetUtcNow());
job.MarkDone(clock.GetUtcNow());
await db.SaveChangesAsync(cancellationToken);
}
catch (Exception ex)
{
job.MarkFailed(ex.Message, clock.GetUtcNow());
await db.SaveChangesAsync(cancellationToken);
logger.LogError(ex, "Agent-run job {JobId} failed.", job.Id);
}
}
}