M4: agent-run job queue + worker drain (Increment 1)
SharedKernel: IWorkerModule seam (RegisterWorker runs in the worker host only).
Bootstrap: AddTeamUpWorkerServices; the worker host now wires it.
Assembler module (schema "assembler", InitialAssembler migration):
- Job (Pending→Processing→Done/Failed) + AgentRun (Queued→Running→Completed/Failed) entities.
- JobQueue: enqueue + ClaimNextAsync using `FOR UPDATE SKIP LOCKED` in a transaction.
- AgentRunExecutor (Increment-1 placeholder — real assemble/model/parse lands in Increment 2).
- JobProcessor BackgroundService drains the queue on the worker host (web off the model path).
- POST /api/assembler/runs enqueues a run; GET /api/assembler/runs/{id} reads it.
Verified: build green; ArchitectureTests 8/8 (Assembler references only SharedKernel);
IntegrationTests 28/28 incl. enqueue→claim(SKIP LOCKED)→process→Completed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
using TeamUp.SharedKernel.Domain;
|
||||
|
||||
namespace TeamUp.Modules.Assembler.Domain;
|
||||
|
||||
internal enum AgentRunStatus
|
||||
{
|
||||
Queued,
|
||||
Running,
|
||||
Completed,
|
||||
Failed,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// One execution of an AI seat against a task: the assembled prompt, the raw model output, the
|
||||
/// parsed action + risk tag, and the reasoning/assembly trace. Nothing executes off this in M4 —
|
||||
/// the action gate (M5) decides whether the parsed action runs or waits in review.
|
||||
/// </summary>
|
||||
internal sealed class AgentRun : Entity
|
||||
{
|
||||
public Guid SeatId { get; private set; }
|
||||
public Guid WorkItemId { get; private set; }
|
||||
public Guid? AgentId { get; private set; }
|
||||
public AgentRunStatus Status { get; private set; }
|
||||
public string? Prompt { get; private set; }
|
||||
public string? Output { get; private set; }
|
||||
public string? ActionType { get; private set; }
|
||||
public string? ActionRisk { get; private set; }
|
||||
public string? ResultJson { get; private set; }
|
||||
public string? Trace { get; private set; }
|
||||
public string? Error { get; private set; }
|
||||
public long? LatencyMs { get; private set; }
|
||||
public DateTimeOffset CreatedAtUtc { get; private set; }
|
||||
public DateTimeOffset? CompletedAtUtc { get; private set; }
|
||||
|
||||
private AgentRun()
|
||||
{
|
||||
}
|
||||
|
||||
public AgentRun(Guid seatId, Guid workItemId, DateTimeOffset createdAtUtc)
|
||||
{
|
||||
SeatId = seatId;
|
||||
WorkItemId = workItemId;
|
||||
Status = AgentRunStatus.Queued;
|
||||
CreatedAtUtc = createdAtUtc;
|
||||
}
|
||||
|
||||
public void Start(Guid? agentId, string prompt, string? trace)
|
||||
{
|
||||
Status = AgentRunStatus.Running;
|
||||
AgentId = agentId;
|
||||
Prompt = prompt;
|
||||
Trace = trace;
|
||||
}
|
||||
|
||||
public void Complete(string output, string actionType, string actionRisk, string? resultJson, long latencyMs, DateTimeOffset nowUtc)
|
||||
{
|
||||
Status = AgentRunStatus.Completed;
|
||||
Output = output;
|
||||
ActionType = actionType;
|
||||
ActionRisk = actionRisk;
|
||||
ResultJson = resultJson;
|
||||
LatencyMs = latencyMs;
|
||||
CompletedAtUtc = nowUtc;
|
||||
}
|
||||
|
||||
public void Fail(string error, DateTimeOffset nowUtc)
|
||||
{
|
||||
Status = AgentRunStatus.Failed;
|
||||
Error = error;
|
||||
CompletedAtUtc = nowUtc;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user