fix: make zPreviewOutput accept text-only job outputs (#9724)

## Summary

Fixes Zod validation crash when the jobs batch contains text-only
preview outputs (e.g. from LLM nodes), which caused the entire Assets
sidebar to show nothing.

## Changes

- **What**: Made `filename`, `subfolder`, and `type` optional in
`zPreviewOutput` and added `.passthrough()` for extra fields like
`content`. Text-only jobs are safely filtered out downstream by
`supportsPreview`.
- Added tests in `fetchJobs.test.ts` verifying a mixed batch (image +
text-only + no-preview) parses successfully.
- Added test in `assetsStore.test.ts` verifying text-only jobs are
skipped without breaking sibling image jobs. Improved `TaskItemImpl`
mock to realistically handle media types.

## Review Focus

- The `zPreviewOutput` schema now uses `.passthrough()` to allow extra
fields from new preview types (like `content` on text previews). This is
consistent with `zRawJobListItem` and `zExecutionError` which also use
`.passthrough()`.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9724-fix-make-zPreviewOutput-accept-text-only-job-outputs-31f6d73d36508119a7aef99f9b765ecd)
by [Unito](https://www.unito.io)
This commit is contained in:
Luke Mino-Altherr
2026-03-10 18:18:54 -07:00
committed by GitHub
parent dc3e455993
commit 9ecb100d11
4 changed files with 108 additions and 16 deletions

View File

@@ -150,6 +150,41 @@ describe('fetchJobs', () => {
expect(result).toEqual([])
})
it('parses batch containing text-only preview outputs', async () => {
const mockFetch = vi.fn().mockResolvedValue({
ok: true,
json: () =>
Promise.resolve(
createMockResponse([
createMockJob('image-job', 'completed', {
preview_output: {
filename: 'output.png',
subfolder: '',
type: 'output',
nodeId: '1',
mediaType: 'images'
}
}),
createMockJob('text-job', 'completed', {
preview_output: {
content: 'some generated text',
nodeId: '5',
mediaType: 'text'
}
}),
createMockJob('no-preview-job', 'completed')
])
)
})
const result = await fetchHistory(mockFetch)
expect(result).toHaveLength(3)
expect(result[0].id).toBe('image-job')
expect(result[1].id).toBe('text-job')
expect(result[2].id).toBe('no-preview-job')
})
})
describe('fetchQueue', () => {

View File

@@ -18,14 +18,16 @@ const zJobStatus = z.enum([
'cancelled'
])
const zPreviewOutput = z.object({
filename: z.string(),
subfolder: z.string(),
type: resultItemType,
nodeId: z.string(),
mediaType: z.string(),
display_name: z.string().optional()
})
const zPreviewOutput = z
.object({
filename: z.string().optional(),
subfolder: z.string().optional(),
type: resultItemType.optional(),
nodeId: z.string(),
mediaType: z.string(),
display_name: z.string().optional()
})
.passthrough()
/**
* Execution error from Jobs API.