feat(workflow): orchestrate resumable dataflow handoffs
This commit is contained in:
@@ -84,6 +84,75 @@ export type WorkflowGovernance = {
|
||||
automation_runtime_reason?: string | null;
|
||||
};
|
||||
|
||||
export type WorkflowInstanceStatus =
|
||||
| "running"
|
||||
| "waiting"
|
||||
| "completed"
|
||||
| "failed"
|
||||
| "cancelled";
|
||||
|
||||
export type WorkflowStepStatus =
|
||||
| "running"
|
||||
| "waiting"
|
||||
| "completed"
|
||||
| "failed"
|
||||
| "cancelled"
|
||||
| "superseded";
|
||||
|
||||
export type WorkflowInstanceStep = {
|
||||
id: string;
|
||||
sequence: number;
|
||||
node_id: string;
|
||||
node_type: string;
|
||||
status: WorkflowStepStatus;
|
||||
attempt: number;
|
||||
input: Record<string, unknown>;
|
||||
output: Record<string, unknown>;
|
||||
handoff: Record<string, unknown>;
|
||||
external_ref?: string | null;
|
||||
started_at?: string | null;
|
||||
finished_at?: string | null;
|
||||
error?: string | null;
|
||||
completed_by?: string | null;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
};
|
||||
|
||||
export type WorkflowInstanceEvent = {
|
||||
id: string;
|
||||
sequence: number;
|
||||
step_id?: string | null;
|
||||
kind: string;
|
||||
actor_id?: string | null;
|
||||
payload: Record<string, unknown>;
|
||||
created_at: string;
|
||||
};
|
||||
|
||||
export type WorkflowInstance = {
|
||||
id: string;
|
||||
definition_id: string;
|
||||
definition_name: string;
|
||||
definition_revision: number;
|
||||
definition_hash: string;
|
||||
status: WorkflowInstanceStatus;
|
||||
idempotency_key: string;
|
||||
correlation_id?: string | null;
|
||||
current_step_id?: string | null;
|
||||
input: Record<string, unknown>;
|
||||
context: Record<string, unknown>;
|
||||
output: Record<string, unknown>;
|
||||
started_at: string;
|
||||
finished_at?: string | null;
|
||||
cancellation_requested_at?: string | null;
|
||||
error?: string | null;
|
||||
created_by?: string | null;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
steps: WorkflowInstanceStep[];
|
||||
events: WorkflowInstanceEvent[];
|
||||
replayed: boolean;
|
||||
};
|
||||
|
||||
export type WorkflowDefinitionPayload = {
|
||||
name: string;
|
||||
description?: string | null;
|
||||
@@ -232,3 +301,89 @@ export function workflowScopeReferenceProvider(
|
||||
{ scope_type: scopeType }
|
||||
);
|
||||
}
|
||||
|
||||
export async function listWorkflowInstances(
|
||||
settings: ApiSettings,
|
||||
definitionId?: string | null
|
||||
): Promise<WorkflowInstance[]> {
|
||||
const params = new URLSearchParams();
|
||||
if (definitionId) params.set("definition_id", definitionId);
|
||||
const query = params.size ? `?${params.toString()}` : "";
|
||||
const response = await apiFetch<{ instances: WorkflowInstance[] }>(
|
||||
settings,
|
||||
`/api/v1/workflow/instances${query}`
|
||||
);
|
||||
return response.instances;
|
||||
}
|
||||
|
||||
export function startWorkflowInstance(
|
||||
settings: ApiSettings,
|
||||
definitionId: string,
|
||||
payload: {
|
||||
idempotency_key: string;
|
||||
input?: Record<string, unknown>;
|
||||
correlation_id?: string | null;
|
||||
}
|
||||
): Promise<WorkflowInstance> {
|
||||
return apiFetch(
|
||||
settings,
|
||||
`/api/v1/workflow/definitions/${encodeURIComponent(definitionId)}/instances`,
|
||||
{
|
||||
method: "POST",
|
||||
body: JSON.stringify(payload)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export function getWorkflowInstance(
|
||||
settings: ApiSettings,
|
||||
instanceId: string
|
||||
): Promise<WorkflowInstance> {
|
||||
return apiFetch(
|
||||
settings,
|
||||
`/api/v1/workflow/instances/${encodeURIComponent(instanceId)}`
|
||||
);
|
||||
}
|
||||
|
||||
export function reconcileWorkflowInstance(
|
||||
settings: ApiSettings,
|
||||
instanceId: string
|
||||
): Promise<WorkflowInstance> {
|
||||
return apiFetch(
|
||||
settings,
|
||||
`/api/v1/workflow/instances/${encodeURIComponent(instanceId)}/reconcile`,
|
||||
{ method: "POST" }
|
||||
);
|
||||
}
|
||||
|
||||
export function resolveWorkflowStep(
|
||||
settings: ApiSettings,
|
||||
instanceId: string,
|
||||
stepId: string,
|
||||
payload: {
|
||||
action: "complete" | "approve" | "changes" | "reject" | "resume" | "retry" | "cancel";
|
||||
output?: Record<string, unknown>;
|
||||
evidence?: string[];
|
||||
comment?: string | null;
|
||||
}
|
||||
): Promise<WorkflowInstance> {
|
||||
return apiFetch(
|
||||
settings,
|
||||
`/api/v1/workflow/instances/${encodeURIComponent(instanceId)}/steps/${encodeURIComponent(stepId)}/actions`,
|
||||
{
|
||||
method: "POST",
|
||||
body: JSON.stringify(payload)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export function cancelWorkflowInstance(
|
||||
settings: ApiSettings,
|
||||
instanceId: string
|
||||
): Promise<WorkflowInstance> {
|
||||
return apiFetch(
|
||||
settings,
|
||||
`/api/v1/workflow/instances/${encodeURIComponent(instanceId)}/cancel`,
|
||||
{ method: "POST" }
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user