import { apiRequest, createUuid } from "./_shared"; import type { ScriptType } from "./scripts"; import type { CronPreview, PythonVersion, Schedule, ScheduleNodeRunArtifacts, ScheduleRunDetail, ScheduleRunStatus, ScheduleRunSummary, } from "./schedules"; export type ScheduleNode = { node_id: string; schedule_id: string; node_key: string; node_name: string; versions_id: string; timeout_seconds: number; retry_count: number; retry_interval_sec: number; position_x: number; position_y: number; arguments_json: Record; env_refs_json: Record; python_version: PythonVersion; created_at: string; updated_at: string; version: { versions_id: string; version_label: string; script_id: string; script_name: string; script_type: ScriptType; content_hash: string; created_at: string; }; }; export type ScheduleEdge = { edge_id: string; schedule_id: string; source_node_id: string; target_node_id: string; condition_expr: string | null; created_at: string; }; export type DagValidation = { valid: boolean; node_count: number; edge_count: number; root_node_ids: string[]; leaf_node_ids: string[]; topological_order: string[]; errors: Array<{ code: string; message: string; edge_id?: string; node_ids?: string[]; }>; }; export type ScheduleNodeRunStatus = | ScheduleRunStatus | "skipped"; export type ScheduleNodeRun = { node_run_id: string; run_id: string; node_id: string; versions_id: string; attempt_no: number; node_status: ScheduleNodeRunStatus; state_version: number; started_at: string | null; finished_at: string | null; duration_ms: number | null; exit_code: number | null; message: string | null; logs_object_id: string | null; result_object_id: string | null; }; export async function createScheduleNode( workspaceId: string, scheduleId: string, input: { workflow_version: number; node_key: string; node_name: string; versions_id: string; timeout_seconds?: number; retry_count?: number; retry_interval_sec?: number; position_x?: number; position_y?: number; arguments_json?: Record; env_refs_json?: Record; python_version?: PythonVersion; }, ): Promise { return apiRequest( `/api/v1/schedules/${scheduleId}/nodes`, { method: "POST", body: JSON.stringify(input) }, workspaceId, ); } export async function updateScheduleNode( workspaceId: string, scheduleId: string, nodeId: string, input: { workflow_version: number; node_name?: string; versions_id?: string; timeout_seconds?: number; retry_count?: number; retry_interval_sec?: number; position_x?: number; position_y?: number; arguments_json?: Record; env_refs_json?: Record; python_version?: PythonVersion; }, ): Promise { return apiRequest( `/api/v1/schedules/${scheduleId}/nodes/${nodeId}`, { method: "PUT", body: JSON.stringify(input) }, workspaceId, ); } export async function deleteScheduleNode( workspaceId: string, scheduleId: string, nodeId: string, workflowVersion: number, options: { delete_execution_history?: boolean } = {}, ): Promise { return apiRequest( `/api/v1/schedules/${scheduleId}/nodes/${nodeId}`, { method: "DELETE", body: JSON.stringify({ workflow_version: workflowVersion, ...options }), }, workspaceId, ); } export async function createScheduleEdge( workspaceId: string, scheduleId: string, input: { workflow_version: number; source_node_id: string; target_node_id: string; condition_expr?: string | null; }, ): Promise { return apiRequest( `/api/v1/schedules/${scheduleId}/edges`, { method: "POST", body: JSON.stringify(input) }, workspaceId, ); } export async function deleteScheduleEdge( workspaceId: string, scheduleId: string, edgeId: string, workflowVersion: number, ): Promise { return apiRequest( `/api/v1/schedules/${scheduleId}/edges/${edgeId}`, { method: "DELETE", body: JSON.stringify({ workflow_version: workflowVersion }) }, workspaceId, ); } export async function validateSchedule( workspaceId: string, scheduleId: string, ): Promise { return apiRequest( `/api/v1/schedules/${scheduleId}/validate`, { method: "POST" }, workspaceId, ); } export async function previewCron( workspaceId: string, input: { cron_expression: string; timezone: string; count?: number; base_time?: string; }, ): Promise { return apiRequest( "/api/v1/cron/preview", { method: "POST", body: JSON.stringify(input) }, workspaceId, ); } export async function runScheduleNow( workspaceId: string, scheduleId: string, ): Promise { return apiRequest( `/api/v1/schedules/${scheduleId}/run`, { method: "POST", headers: { "Idempotency-Key": createUuid(), }, body: JSON.stringify({ reason: "manual_run" }), }, workspaceId, ); } export async function listScheduleRuns( workspaceId: string, input: { scheduleId?: string; status?: ScheduleRunStatus; limit?: number; } = {}, ): Promise { const query = new URLSearchParams(); if (input.scheduleId) query.set("schedule_id", input.scheduleId); if (input.status) query.set("status", input.status); query.set("limit", String(input.limit ?? 20)); return apiRequest( `/api/v1/schedule-runs?${query.toString()}`, {}, workspaceId, ); } export async function getScheduleRun( workspaceId: string, runId: string, ): Promise { return apiRequest( `/api/v1/schedule-runs/${runId}`, {}, workspaceId, ); } export async function getScheduleNodeRunArtifacts( workspaceId: string, runId: string, nodeRunId: string, ): Promise { return apiRequest( `/api/v1/schedule-runs/${runId}/node-runs/${nodeRunId}/artifacts`, {}, workspaceId, ); } // ----------------------------------------------------------------------------