diff --git a/src/platform/remote/comfyui/jobs/fetchJobs.ts b/src/platform/remote/comfyui/jobs/fetchJobs.ts index 136f683d6..5d8859d3b 100644 --- a/src/platform/remote/comfyui/jobs/fetchJobs.ts +++ b/src/platform/remote/comfyui/jobs/fetchJobs.ts @@ -1,11 +1,3 @@ -/** - * @fileoverview Jobs API Fetchers - * @module platform/remote/comfyui/jobs/fetchJobs - * - * Unified jobs API fetcher for history, queue, and job details. - * All distributions use the /jobs endpoint. - */ - import type { PromptId } from '@/schemas/apiSchema' import type { @@ -14,7 +6,7 @@ import type { JobStatus, RawJobListItem } from './jobTypes' -import { zJobDetail, zJobsListResponse, zWorkflowContainer } from './jobTypes' +import { zJobDetail, zJobsListResponse } from './jobTypes' interface FetchJobsRawResult { jobs: RawJobListItem[] @@ -94,7 +86,7 @@ export async function fetchQueue( const { jobs } = await fetchJobsRaw( fetchApi, ['in_progress', 'pending'], - 200, + 50, 0 ) @@ -134,13 +126,14 @@ export async function fetchJobDetail( } } -/** - * Extracts workflow from job detail response. - * The workflow is nested at: workflow.extra_data.extra_pnginfo.workflow - * Full workflow validation happens downstream via validateComfyWorkflow. - */ +/** Extracts workflow from job detail response */ export function extractWorkflow(job: JobDetail | undefined): unknown { - const parsed = zWorkflowContainer.safeParse(job?.workflow) - if (!parsed.success) return undefined - return parsed.data.extra_data?.extra_pnginfo?.workflow + const workflow = job?.workflow + if (!workflow || typeof workflow !== 'object') return undefined + const container = workflow as Record + const extraData = container.extra_data + if (!extraData || typeof extraData !== 'object') return undefined + const pnginfo = (extraData as Record).extra_pnginfo + if (!pnginfo || typeof pnginfo !== 'object') return undefined + return (pnginfo as Record).workflow } diff --git a/src/platform/remote/comfyui/jobs/jobTypes.ts b/src/platform/remote/comfyui/jobs/jobTypes.ts index 314ba549e..9ff392c0b 100644 --- a/src/platform/remote/comfyui/jobs/jobTypes.ts +++ b/src/platform/remote/comfyui/jobs/jobTypes.ts @@ -1,11 +1,3 @@ -/** - * @fileoverview Jobs API types - Backend job API format - * @module platform/remote/comfyui/jobs/jobTypes - * - * These types represent the jobs API format returned by the backend. - * Jobs API provides a memory-optimized alternative to history API. - */ - import { z } from 'zod' import { resultItemType, zTaskOutput } from '@/schemas/apiSchema' @@ -25,57 +17,49 @@ const zPreviewOutput = z.object({ }) /** - * Execution error details for error jobs. + * Execution error details for failed jobs. * Contains the same structure as ExecutionErrorWsMessage from WebSocket. */ -const zExecutionError = z - .object({ - prompt_id: z.string().optional(), - timestamp: z.number().optional(), - node_id: z.string(), - node_type: z.string(), - executed: z.array(z.string()).optional(), - exception_message: z.string(), - exception_type: z.string(), - traceback: z.array(z.string()), - current_inputs: z.record(z.string(), z.unknown()), - current_outputs: z.record(z.string(), z.unknown()) - }) - .passthrough() +const zExecutionError = z.object({ + prompt_id: z.string().optional(), + timestamp: z.number().optional(), + node_id: z.string(), + node_type: z.string(), + executed: z.array(z.string()).optional(), + exception_message: z.string(), + exception_type: z.string(), + traceback: z.array(z.string()), + current_inputs: z.record(z.string(), z.unknown()), + current_outputs: z.record(z.string(), z.unknown()) +}) export type ExecutionError = z.infer -/** - * Raw job from API - uses passthrough to allow extra fields - */ -const zRawJobListItem = z - .object({ - id: z.string(), - status: zJobStatus, - create_time: z.number(), - execution_start_time: z.number().optional(), - execution_end_time: z.number().optional(), - preview_output: zPreviewOutput.optional(), - outputs_count: z.number().optional(), - execution_error: zExecutionError.optional(), - workflow_id: z.string().optional(), - priority: z.number().optional() - }) - .passthrough() +/** Raw job from API list endpoint */ +const zRawJobListItem = z.object({ + id: z.string(), + status: zJobStatus, + create_time: z.number(), + execution_start_time: z.number().optional(), + execution_end_time: z.number().optional(), + preview_output: zPreviewOutput.optional(), + outputs_count: z.number().optional(), + execution_error: zExecutionError.optional(), + workflow_id: z.string().optional(), + priority: z.number().optional() +}) /** * Job detail - returned by GET /api/jobs/{job_id} (detail endpoint) * Includes full workflow and outputs for re-execution and downloads */ -export const zJobDetail = zRawJobListItem - .extend({ - workflow: z.unknown().optional(), - outputs: zTaskOutput.optional(), - update_time: z.number().optional(), - execution_status: z.unknown().optional(), - execution_meta: z.unknown().optional() - }) - .passthrough() +export const zJobDetail = zRawJobListItem.extend({ + workflow: z.unknown().optional(), + outputs: zTaskOutput.optional(), + update_time: z.number().optional(), + execution_status: z.unknown().optional(), + execution_meta: z.unknown().optional() +}) const zPaginationInfo = z.object({ offset: z.number(), @@ -89,19 +73,6 @@ export const zJobsListResponse = z.object({ pagination: zPaginationInfo }) -/** Schema for workflow container structure in job detail responses */ -export const zWorkflowContainer = z.object({ - extra_data: z - .object({ - extra_pnginfo: z - .object({ - workflow: z.unknown() - }) - .optional() - }) - .optional() -}) - export type JobStatus = z.infer export type RawJobListItem = z.infer /** Job list item with priority always set (server-provided or synthetic) */ diff --git a/tests-ui/tests/platform/remote/comfyui/jobs/fetchJobs.test.ts b/tests-ui/tests/platform/remote/comfyui/jobs/fetchJobs.test.ts index a25497863..7c0ce9527 100644 --- a/tests-ui/tests/platform/remote/comfyui/jobs/fetchJobs.test.ts +++ b/tests-ui/tests/platform/remote/comfyui/jobs/fetchJobs.test.ts @@ -169,7 +169,7 @@ describe('fetchJobs', () => { const result = await fetchQueue(mockFetch) expect(mockFetch).toHaveBeenCalledWith( - '/jobs?status=in_progress,pending&limit=200&offset=0' + '/jobs?status=in_progress,pending&limit=50&offset=0' ) expect(result.Running).toHaveLength(1) expect(result.Pending).toHaveLength(2)