Files
ComfyUI_frontend/src/platform/assets/composables/media/assetMappers.ts
Hunter 63c36d3f2f feat: display original asset names instead of hashes in assets panel (#9626)
## Problem
Output assets in the assets panel show content hashes (e.g.,
`a1b2c3d4.png`) instead of display names (e.g., `ComfyUI_00001_.png`).

## Root Cause
Cloud inference replaces `filename` with the content hash in the output
transform pipeline. The hashed filename gets stored in the jobs table's
`preview_output` JSONB. The frontend uses this hash as the display name.

## Solution
- Add `display_name` field to `AssetItem` schema and `ResultItemImpl`
- Backend (cloud PR) joins job→assets table to resolve the original name
and injects `display_name` into job responses
- Frontend prefers `display_name` over `name` **only for display text
and download filenames**
- `asset.name` remains unchanged (the hash) for URLs, drag-to-canvas,
export filters, and output key dedup

## Backwards Compatible
- OSS: `display_name` is undefined, falls back to `asset.name` (which is
already the real filename in OSS)
- Cloud pre-deploy: `display_name` absent from API, falls back
gracefully
- Old jobs with no assets: `display_name` not injected, no change

## Cloud PR
https://github.com/Comfy-Org/cloud/pull/2747



https://github.com/user-attachments/assets/8a4c9cac-4ade-4ea2-9a70-9af240a56602
2026-03-09 01:06:28 -04:00

77 lines
2.3 KiB
TypeScript

import type { AssetItem } from '@/platform/assets/schemas/assetSchema'
import type { OutputAssetMetadata } from '@/platform/assets/schemas/assetMetadataSchema'
import type { AssetContext } from '@/platform/assets/schemas/mediaAssetSchema'
import { appendCloudResParam } from '@/platform/distribution/cloudPreviewUtil'
import { api } from '@/scripts/api'
import type { ResultItemImpl, TaskItemImpl } from '@/stores/queueStore'
/**
* Extract asset type from tags array
* @param tags The tags array from AssetItem
* @returns The asset type ('input' or 'output')
*/
export function getAssetType(tags?: string[]): AssetContext['type'] {
const tag = tags?.[0]
if (tag === 'output') return 'output'
return 'input'
}
/**
* Maps a TaskItemImpl output to an AssetItem format
* @param taskItem The task item containing execution data
* @param output The output from the task
* @param useDisplayName Whether to truncate the filename for display
* @returns AssetItem formatted object
*/
export function mapTaskOutputToAssetItem(
taskItem: TaskItemImpl,
output: ResultItemImpl
): AssetItem {
const metadata: OutputAssetMetadata = {
jobId: taskItem.jobId,
nodeId: output.nodeId,
subfolder: output.subfolder,
executionTimeInSeconds: taskItem.executionTimeInSeconds,
format: output.format,
create_time: taskItem.createTime
}
return {
id: taskItem.jobId,
name: output.filename,
display_name: output.display_name,
size: 0,
created_at: taskItem.executionStartTimestamp
? new Date(taskItem.executionStartTimestamp).toISOString()
: new Date().toISOString(),
tags: ['output'],
preview_url: output.previewUrl,
user_metadata: metadata
}
}
/**
* Maps input directory file to AssetItem format
* @param filename The filename
* @param index File index for unique ID
* @param directory The directory type
* @returns AssetItem formatted object
*/
export function mapInputFileToAssetItem(
filename: string,
index: number,
directory: 'input' | 'output' = 'input'
): AssetItem {
const params = new URLSearchParams({ filename, type: directory })
appendCloudResParam(params, filename)
return {
id: `${directory}-${index}-${filename}`,
name: filename,
size: 0,
created_at: new Date().toISOString(),
tags: [directory],
preview_url: api.apiURL(`/view?${params}`)
}
}