Files
buzz/desktop/src/shared/api/tauriWorkflows.ts
T
2cc0eb5396 perf(desktop): GUI performance sweep — async offload, poll reduction, render stabilization (#1641)
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: npub17jjz49l9jjmhhk7cac63j8yt9z555n9cw8vk7v5jz4vzw4ppld5qgj57cc <f4a42a97e594b77bdbd8ee35191c8b28a94a4cb871d96f32921558275421fb68@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1cc3ha7z055mu0rwwu7806t2wt8mj3pvu0uv5mfp2c50dahaqhczshdalg6 <c6237ef84fa537c78dcee78efd2d4e59f728859c7f194da42ac51ededfa0be05@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1jh9wn95s0472h86ahapupaf7m6kx4v9sx2n0atj2hltcfer8k06s5n3pyf <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1t2tgm7d8f995uqvmnm8h88sg3wnpp9a5xysjf6dg3tjmgt3ltulqdp8ehr <5a968df9a7494b4e019b9ecf739e088ba61097b4312124e9a88ae5b42e3f5f3e@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1jmc9dt2lyvzu3h0kxlwxt5zg4fxp9476awyxw6gwxn72g6cw7exqs64whm <96f056ad5f2305c8ddf637dc65d048aa4c12d7daeb8867690e34fca46b0ef64c@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@sprout-oss.stage.blox.sqprod.co>
2026-07-08 14:58:27 -04:00

272 lines
6.8 KiB
TypeScript

import { invokeTauri } from "@/shared/api/tauri";
import type {
ApprovalActionResponse,
TriggerWorkflowResponse,
Workflow,
WorkflowApproval,
WorkflowRun,
WorkflowSaveResult,
TraceEntry,
} from "@/shared/api/types";
// ── Raw types (snake_case from backend) ───────────────────────────────────
type RawWorkflow = {
id: string;
name: string;
owner_pubkey: string;
channel_id: string | null;
definition: Record<string, unknown>;
status: Workflow["status"];
created_at: number;
updated_at: number;
};
type RawWorkflowSaveResponse = RawWorkflow & {
webhook_secret?: string | null;
};
type RawTraceEntry = {
step_id: string;
status: string;
output?: Record<string, unknown>;
started_at?: number | null;
completed_at?: number | null;
error?: string | null;
};
type RawWorkflowRun = {
id: string;
workflow_id: string;
status: WorkflowRun["status"];
current_step: number | null;
execution_trace: RawTraceEntry[];
started_at: number | null;
completed_at: number | null;
error_message: string | null;
created_at: number;
};
type RawWorkflowApproval = {
token: string;
workflow_id: string;
run_id: string;
step_id: string;
step_index: number;
approver_spec: string;
status: WorkflowApproval["status"];
approver_pubkey: string | null;
note: string | null;
expires_at: string;
created_at: number;
};
type RawTriggerWorkflowResponse = {
run_id: string;
workflow_id: string;
status: string;
};
type RawApprovalActionResponse = {
token: string;
status: string;
run_id: string;
workflow_id: string;
};
// ── Conversion functions ──────────────────────────────────────────────────
function fromRawWorkflow(raw: RawWorkflow): Workflow {
return {
id: raw.id,
name: raw.name,
ownerPubkey: raw.owner_pubkey,
channelId: raw.channel_id,
definition: raw.definition,
status: raw.status,
createdAt: raw.created_at,
updatedAt: raw.updated_at,
};
}
function fromRawWorkflowSave(raw: RawWorkflowSaveResponse): WorkflowSaveResult {
return {
workflow: fromRawWorkflow(raw),
webhookSecret: raw.webhook_secret ?? null,
};
}
function fromRawTraceEntry(raw: RawTraceEntry): TraceEntry {
return {
stepId: raw.step_id,
status: raw.status,
output: raw.output ?? {},
startedAt: raw.started_at ?? null,
completedAt: raw.completed_at ?? null,
error: raw.error ?? null,
};
}
function fromRawWorkflowRun(raw: RawWorkflowRun): WorkflowRun {
return {
id: raw.id,
workflowId: raw.workflow_id,
status: raw.status,
currentStep: raw.current_step,
executionTrace: raw.execution_trace.map(fromRawTraceEntry),
startedAt: raw.started_at,
completedAt: raw.completed_at,
errorMessage: raw.error_message,
createdAt: raw.created_at,
};
}
export function fromRawApproval(raw: RawWorkflowApproval): WorkflowApproval {
return {
token: raw.token,
workflowId: raw.workflow_id,
runId: raw.run_id,
stepId: raw.step_id,
stepIndex: raw.step_index,
approverSpec: raw.approver_spec,
status: raw.status,
approverPubkey: raw.approver_pubkey,
note: raw.note,
expiresAt: raw.expires_at,
createdAt: raw.created_at,
};
}
function fromRawTriggerResponse(
raw: RawTriggerWorkflowResponse,
): TriggerWorkflowResponse {
return {
runId: raw.run_id,
workflowId: raw.workflow_id,
status: raw.status,
};
}
function fromRawApprovalResponse(
raw: RawApprovalActionResponse,
): ApprovalActionResponse {
return {
token: raw.token,
status: raw.status,
runId: raw.run_id,
workflowId: raw.workflow_id,
};
}
// ── Tauri invoke wrappers ─────────────────────────────────────────────────
export async function getChannelWorkflows(
channelId: string,
): Promise<Workflow[]> {
const raw = await invokeTauri<RawWorkflow[]>("get_channel_workflows", {
channelId,
});
return raw.map(fromRawWorkflow);
}
/**
* Fetch workflows across many channels in a single relay round-trip.
*
* Replaces the per-channel `Promise.all(getChannelWorkflows)` fanout on the
* Workflows overview: the backend `#h` filter matches any listed channel, and
* each returned workflow carries its own `channelId` so callers can group.
*/
export async function getChannelsWorkflows(
channelIds: string[],
): Promise<Workflow[]> {
const raw = await invokeTauri<RawWorkflow[]>("get_channels_workflows", {
channelIds,
});
return raw.map(fromRawWorkflow);
}
export async function getWorkflow(workflowId: string): Promise<Workflow> {
const raw = await invokeTauri<RawWorkflow>("get_workflow", { workflowId });
return fromRawWorkflow(raw);
}
export async function createWorkflow(
channelId: string,
yamlDefinition: string,
): Promise<WorkflowSaveResult> {
const raw = await invokeTauri<RawWorkflowSaveResponse>("create_workflow", {
channelId,
yamlDefinition,
});
return fromRawWorkflowSave(raw);
}
export async function updateWorkflow(
workflowId: string,
yamlDefinition: string,
): Promise<WorkflowSaveResult> {
const raw = await invokeTauri<RawWorkflowSaveResponse>("update_workflow", {
workflowId,
yamlDefinition,
});
return fromRawWorkflowSave(raw);
}
export async function deleteWorkflow(workflowId: string): Promise<void> {
await invokeTauri("delete_workflow", { workflowId });
}
export async function getWorkflowRuns(
workflowId: string,
limit?: number,
): Promise<WorkflowRun[]> {
const raw = await invokeTauri<RawWorkflowRun[]>("get_workflow_runs", {
workflowId,
limit: limit ?? null,
});
return raw.map(fromRawWorkflowRun);
}
export async function getRunApprovals(
workflowId: string,
runId: string,
): Promise<WorkflowApproval[]> {
const raw = await invokeTauri<RawWorkflowApproval[]>("get_run_approvals", {
workflowId,
runId,
});
return raw.map(fromRawApproval);
}
export async function triggerWorkflow(
workflowId: string,
): Promise<TriggerWorkflowResponse> {
const raw = await invokeTauri<RawTriggerWorkflowResponse>(
"trigger_workflow",
{ workflowId },
);
return fromRawTriggerResponse(raw);
}
export async function grantApproval(
token: string,
note?: string,
): Promise<ApprovalActionResponse> {
const raw = await invokeTauri<RawApprovalActionResponse>("grant_approval", {
token,
note: note ?? null,
});
return fromRawApprovalResponse(raw);
}
export async function denyApproval(
token: string,
note?: string,
): Promise<ApprovalActionResponse> {
const raw = await invokeTauri<RawApprovalActionResponse>("deny_approval", {
token,
note: note ?? null,
});
return fromRawApprovalResponse(raw);
}