feat: add minimum API and web GUI

This commit is contained in:
chungyeong
2026-05-14 01:16:41 +09:00
parent e5020a59f0
commit c9fed71cc9
21 changed files with 3757 additions and 11 deletions

View File

@@ -648,7 +648,7 @@ export class DbRunEngine implements RunEngine {
await eventRepository.appendInTransaction(tx, {
runId,
type: "run.resumed",
payload: { cause },
payload: { cause, resumedTo: nextState },
idempotencyKey: `run.resumed:${runId}:${cause}`,
});
shouldAdvance = nextState === "executing" || nextState === "planning";
@@ -1103,7 +1103,7 @@ export class DbRunEngine implements RunEngine {
await eventRepository.appendInTransaction(tx, {
runId,
type: "run.resumed",
payload: { cause: `approval:${approvalRequestId}:${action}` },
payload: { cause: `approval:${approvalRequestId}:${action}`, resumedTo: "executing" },
idempotencyKey: `run.resumed:${runId}:approval:${approvalRequestId}:${action}`,
});
return { replayed: false };
@@ -1125,7 +1125,7 @@ export class DbRunEngine implements RunEngine {
await eventRepository.appendInTransaction(tx, {
runId,
type: "run.resumed",
payload: { cause: `approval:${approvalRequestId}:${action}` },
payload: { cause: `approval:${approvalRequestId}:${action}`, resumedTo: "planning" },
idempotencyKey: `run.resumed:${runId}:approval:${approvalRequestId}:${action}`,
});
return { replayed: false };

View File

@@ -1280,7 +1280,12 @@ async function tryStartPhaseAndRecord(
runId: input.runId,
phaseId: input.phaseId,
type: "phase.started",
payload: { phaseKey: input.phaseKey, attempt: updatedPhase.attempts, ...payload },
payload: {
phaseKey: input.phaseKey,
attempt: updatedPhase.attempts,
runState: run.state,
...payload,
},
idempotencyKey: `phase.started:${input.phaseId}:${updatedPhase.attempts}`,
});
return updatedPhase.attempts;
@@ -1657,7 +1662,14 @@ async function requestWorkflowApproval(
});
}
await appendHumanGateRequestedEventInTransaction(input, eventRepository, tx, request, gateKey);
await appendHumanGateRequestedEventInTransaction(input, eventRepository, tx, request, gateKey, {
runState: "awaiting_approval",
phaseState: "awaiting_approval",
sessionState: "WAITING_FOR_APPROVAL",
sessionId,
roleId: input.roleId,
phaseKey: input.phaseKey,
});
});
}
@@ -2158,6 +2170,15 @@ interface ArtifactRecord {
validationError: unknown;
}
interface ApprovalRequestedStatePayload {
runState?: string;
phaseState?: string;
sessionState?: string;
sessionId?: string;
roleId?: string;
phaseKey?: string;
}
async function waitForAndValidateArtifact(
input: CanonicalRunSingleFakePhaseInput,
eventRepository: RunEventRepository,
@@ -2879,6 +2900,7 @@ async function appendHumanGateRequestedEventInTransaction(
tx: TransactionDb,
request: HumanGateRequest,
gateKey: string,
statePayload: ApprovalRequestedStatePayload = {},
) {
await eventRepository.appendInTransaction(tx, {
runId: input.runId,
@@ -2888,6 +2910,7 @@ async function appendHumanGateRequestedEventInTransaction(
approvalRequestId: request.id,
approvalIdempotencyKey: request.idempotencyKey,
gateKey,
...statePayload,
},
idempotencyKey: `approval.requested:${request.idempotencyKey}`,
});