Merge branch 'main' into bl/assets-sidebar-test-foundation

This commit is contained in:
Alexander Brown
2026-04-09 16:29:20 -07:00
committed by GitHub
6 changed files with 662 additions and 159 deletions

View File

@@ -134,6 +134,9 @@ export type {
DeleteHubWorkflowErrors,
DeleteHubWorkflowResponse,
DeleteHubWorkflowResponses,
DeleteMonitoringTasksSubpathData,
DeleteMonitoringTasksSubpathErrors,
DeleteMonitoringTasksSubpathResponses,
DeleteSecretData,
DeleteSecretError,
DeleteSecretErrors,
@@ -196,6 +199,9 @@ export type {
GetAllSettingsErrors,
GetAllSettingsResponse,
GetAllSettingsResponses,
GetApiViewVideoAliasData,
GetApiViewVideoAliasErrors,
GetApiViewVideoAliasResponses,
GetAssetByIdData,
GetAssetByIdError,
GetAssetByIdErrors,
@@ -236,6 +242,8 @@ export type {
GetDeletionRequestErrors,
GetDeletionRequestResponse,
GetDeletionRequestResponses,
GetExtensionsData,
GetExtensionsResponses,
GetFeaturesData,
GetFeaturesResponse,
GetFeaturesResponses,
@@ -254,6 +262,9 @@ export type {
GetGlobalSubgraphsErrors,
GetGlobalSubgraphsResponse,
GetGlobalSubgraphsResponses,
GetHealthData,
GetHealthErrors,
GetHealthResponses,
GetHistoryData,
GetHistoryError,
GetHistoryErrors,
@@ -317,6 +328,12 @@ export type {
GetModelsInFolderErrors,
GetModelsInFolderResponse,
GetModelsInFolderResponses,
GetMonitoringTasksData,
GetMonitoringTasksErrors,
GetMonitoringTasksResponses,
GetMonitoringTasksSubpathData,
GetMonitoringTasksSubpathErrors,
GetMonitoringTasksSubpathResponses,
GetMyHubProfileData,
GetMyHubProfileError,
GetMyHubProfileErrors,
@@ -325,11 +342,19 @@ export type {
GetNodeInfoData,
GetNodeInfoResponse,
GetNodeInfoResponses,
GetOpenapiSpecData,
GetOpenapiSpecResponses,
GetPaymentPortalData,
GetPaymentPortalError,
GetPaymentPortalErrors,
GetPaymentPortalResponse,
GetPaymentPortalResponses,
GetPprofData,
GetPprofProfileData,
GetPprofProfileResponses,
GetPprofResponses,
GetPprofTraceData,
GetPprofTraceResponses,
GetPromptInfoData,
GetPromptInfoError,
GetPromptInfoErrors,
@@ -345,11 +370,6 @@ export type {
GetQueueInfoErrors,
GetQueueInfoResponse,
GetQueueInfoResponses,
GetRawLogsData,
GetRawLogsError,
GetRawLogsErrors,
GetRawLogsResponse,
GetRawLogsResponses,
GetRemoteAssetMetadataData,
GetRemoteAssetMetadataError,
GetRemoteAssetMetadataErrors,
@@ -365,6 +385,9 @@ export type {
GetSettingByKeyErrors,
GetSettingByKeyResponse,
GetSettingByKeyResponses,
GetStaticExtensionsData,
GetStaticExtensionsErrors,
GetStaticExtensionsResponses,
GetSystemStatsData,
GetSystemStatsError,
GetSystemStatsErrors,
@@ -375,6 +398,8 @@ export type {
GetTaskErrors,
GetTaskResponse,
GetTaskResponses,
GetTemplateProxyData,
GetTemplateProxyErrors,
GetUserData,
GetUserdataData,
GetUserdataError,
@@ -397,6 +422,23 @@ export type {
GetUserErrors,
GetUserResponse,
GetUserResponses,
GetUsersRawData,
GetUsersRawErrors,
GetUsersRawResponses,
GetVhsQueryVideoData,
GetVhsQueryVideoErrors,
GetVhsQueryVideoResponses,
GetVhsViewAudioData,
GetVhsViewAudioErrors,
GetVhsViewAudioResponses,
GetVhsViewVideoData,
GetVhsViewVideoErrors,
GetVhsViewVideoResponses,
GetViewCompatAliasData,
GetViewCompatAliasErrors,
GetViewCompatAliasResponses,
GetWebsocketData,
GetWebsocketErrors,
GetWorkflowContentData,
GetWorkflowContentError,
GetWorkflowContentErrors,
@@ -526,7 +568,6 @@ export type {
ListWorkspacesResponse2,
ListWorkspacesResponses,
LogsResponse,
LogsSubscribeRequest,
ManageHistoryData,
ManageHistoryError,
ManageHistoryErrors,
@@ -560,6 +601,11 @@ export type {
PostAssetsFromWorkflowErrors,
PostAssetsFromWorkflowResponse,
PostAssetsFromWorkflowResponses,
PostMonitoringTasksSubpathData,
PostMonitoringTasksSubpathErrors,
PostMonitoringTasksSubpathResponses,
PostPprofSymbolData,
PostPprofSymbolResponses,
PostUserdataFileData,
PostUserdataFileError,
PostUserdataFileErrors,
@@ -593,7 +639,6 @@ export type {
QueueInfo,
QueueManageRequest,
QueueManageResponse,
RawLogsResponse,
RemoveAssetTagsData,
RemoveAssetTagsError,
RemoveAssetTagsErrors,
@@ -649,11 +694,6 @@ export type {
SubscribeResponse,
SubscribeResponse2,
SubscribeResponses,
SubscribeToLogsData,
SubscribeToLogsError,
SubscribeToLogsErrors,
SubscribeToLogsResponse,
SubscribeToLogsResponses,
SubscriptionDuration,
SubscriptionTier,
SystemStatsResponse,

View File

@@ -1961,35 +1961,6 @@ export type SystemStatsResponse = {
}>
}
export type LogsSubscribeRequest = {
/**
* Whether to enable or disable log subscription
*/
enabled: boolean
}
/**
* Raw logs response with entries and size
*/
export type RawLogsResponse = {
entries?: Array<{
/**
* Log message
*/
m?: string
}>
size?: {
/**
* Terminal column size
*/
cols?: number
/**
* Terminal row size
*/
rows?: number
}
}
/**
* System logs response
*/
@@ -5276,7 +5247,7 @@ export type GetLogsData = {
body?: never
path?: never
query?: never
url: '/internal/logs'
url: '/api/logs'
}
export type GetLogsErrors = {
@@ -5297,67 +5268,6 @@ export type GetLogsResponses = {
export type GetLogsResponse = GetLogsResponses[keyof GetLogsResponses]
export type GetRawLogsData = {
body?: never
path?: never
query?: never
url: '/internal/logs/raw'
}
export type GetRawLogsErrors = {
/**
* Unauthorized
*/
401: ErrorResponse
}
export type GetRawLogsError = GetRawLogsErrors[keyof GetRawLogsErrors]
export type GetRawLogsResponses = {
/**
* Success
*/
200: RawLogsResponse
}
export type GetRawLogsResponse = GetRawLogsResponses[keyof GetRawLogsResponses]
export type SubscribeToLogsData = {
body: LogsSubscribeRequest
path?: never
query?: never
url: '/internal/logs/subscribe'
}
export type SubscribeToLogsErrors = {
/**
* Bad request
*/
400: ErrorResponse
/**
* Unauthorized
*/
401: ErrorResponse
}
export type SubscribeToLogsError =
SubscribeToLogsErrors[keyof SubscribeToLogsErrors]
export type SubscribeToLogsResponses = {
/**
* Success
*/
200: {
/**
* Whether logs subscription is enabled
*/
enabled?: boolean
}
}
export type SubscribeToLogsResponse =
SubscribeToLogsResponses[keyof SubscribeToLogsResponses]
export type GetSystemStatsData = {
body?: never
path?: never
@@ -7692,3 +7602,444 @@ export type GetPublishedWorkflowResponses = {
export type GetPublishedWorkflowResponse =
GetPublishedWorkflowResponses[keyof GetPublishedWorkflowResponses]
export type GetExtensionsData = {
body?: never
path?: never
query?: never
url: '/api/extensions'
}
export type GetExtensionsResponses = {
/**
* JSON array of extension file paths
*/
200: unknown
}
export type GetVhsViewVideoData = {
body?: never
path?: never
query: {
/**
* Name of the video file to view
*/
filename: string
/**
* Type of file (e.g., output, input, temp)
*/
type?: string
/**
* Subfolder path where the file is located
*/
subfolder?: string
}
url: '/api/vhs/viewvideo'
}
export type GetVhsViewVideoErrors = {
/**
* Unauthorized
*/
401: unknown
}
export type GetVhsViewVideoResponses = {
/**
* Video stream
*/
200: unknown
}
export type GetVhsViewAudioData = {
body?: never
path?: never
query: {
/**
* Name of the audio file to view
*/
filename: string
/**
* Type of file (e.g., output, input, temp)
*/
type?: string
/**
* Subfolder path where the file is located
*/
subfolder?: string
}
url: '/api/vhs/viewaudio'
}
export type GetVhsViewAudioErrors = {
/**
* Unauthorized
*/
401: unknown
}
export type GetVhsViewAudioResponses = {
/**
* Audio stream
*/
200: unknown
}
export type GetVhsQueryVideoData = {
body?: never
path?: never
query: {
/**
* Name of the video file to query
*/
filename: string
}
url: '/api/vhs/queryvideo'
}
export type GetVhsQueryVideoErrors = {
/**
* Unauthorized
*/
401: unknown
}
export type GetVhsQueryVideoResponses = {
/**
* Video metadata
*/
200: unknown
}
export type GetUsersRawData = {
body?: never
path?: never
query?: never
url: '/api/users'
}
export type GetUsersRawErrors = {
/**
* Unauthorized
*/
401: unknown
}
export type GetUsersRawResponses = {
/**
* User list
*/
200: unknown
}
export type GetApiViewVideoAliasData = {
body?: never
path?: never
query: {
/**
* Name of the file to view (see `/api/view` for the full handler contract)
*/
filename: string
}
url: '/api/viewvideo'
}
export type GetApiViewVideoAliasErrors = {
/**
* Unauthorized
*/
401: unknown
}
export type GetApiViewVideoAliasResponses = {
/**
* File stream
*/
200: unknown
}
export type GetViewCompatAliasData = {
body?: never
path?: never
query: {
/**
* Name of the file to view (see `/api/view` for the full handler contract)
*/
filename: string
}
url: '/view'
}
export type GetViewCompatAliasErrors = {
/**
* Unauthorized
*/
401: unknown
}
export type GetViewCompatAliasResponses = {
/**
* File stream
*/
200: unknown
}
export type GetWebsocketData = {
body?: never
path?: never
query?: {
/**
* Stable client identifier used to associate the WebSocket
* connection with the frontend session. If omitted, the server
* generates one.
*
*/
clientId?: string
}
url: '/ws'
}
export type GetWebsocketErrors = {
/**
* Unauthorized
*/
401: unknown
}
export type GetTemplateProxyData = {
body?: never
path: {
path: string
}
query?: never
url: '/templates/{path}'
}
export type GetTemplateProxyErrors = {
/**
* Template not found
*/
404: unknown
}
export type GetHealthData = {
body?: never
path?: never
query?: never
url: '/health'
}
export type GetHealthErrors = {
/**
* Service is unhealthy
*/
503: unknown
}
export type GetHealthResponses = {
/**
* Service is healthy
*/
200: unknown
}
export type GetOpenapiSpecData = {
body?: never
path?: never
query?: never
url: '/openapi'
}
export type GetOpenapiSpecResponses = {
/**
* OpenAPI specification document
*/
200: unknown
}
export type GetMonitoringTasksData = {
body?: never
path?: never
query?: never
url: '/monitoring/tasks'
}
export type GetMonitoringTasksErrors = {
/**
* Unauthorized
*/
401: unknown
/**
* Forbidden
*/
403: unknown
}
export type GetMonitoringTasksResponses = {
/**
* HTML dashboard
*/
200: unknown
}
export type DeleteMonitoringTasksSubpathData = {
body?: never
path: {
path: string
}
query?: never
url: '/monitoring/tasks/{path}'
}
export type DeleteMonitoringTasksSubpathErrors = {
/**
* Unauthorized
*/
401: unknown
/**
* Forbidden
*/
403: unknown
}
export type DeleteMonitoringTasksSubpathResponses = {
/**
* Deletion result
*/
200: unknown
}
export type GetMonitoringTasksSubpathData = {
body?: never
path: {
path: string
}
query?: never
url: '/monitoring/tasks/{path}'
}
export type GetMonitoringTasksSubpathErrors = {
/**
* Unauthorized
*/
401: unknown
/**
* Forbidden
*/
403: unknown
}
export type GetMonitoringTasksSubpathResponses = {
/**
* Subpath response (asynqmon-determined content type)
*/
200: unknown
}
export type PostMonitoringTasksSubpathData = {
body?: never
path: {
path: string
}
query?: never
url: '/monitoring/tasks/{path}'
}
export type PostMonitoringTasksSubpathErrors = {
/**
* Unauthorized
*/
401: unknown
/**
* Forbidden
*/
403: unknown
}
export type PostMonitoringTasksSubpathResponses = {
/**
* Action result
*/
200: unknown
}
export type GetPprofData = {
body?: never
path: {
path: string
}
query?: never
url: '/debug/pprof/{path}'
}
export type GetPprofResponses = {
/**
* Profile data
*/
200: unknown
}
export type GetPprofProfileData = {
body?: never
path?: never
query?: never
url: '/debug/pprof/profile'
}
export type GetPprofProfileResponses = {
/**
* CPU profile data
*/
200: unknown
}
export type GetPprofTraceData = {
body?: never
path?: never
query?: never
url: '/debug/pprof/trace'
}
export type GetPprofTraceResponses = {
/**
* Execution trace data
*/
200: unknown
}
export type PostPprofSymbolData = {
body?: never
path?: never
query?: never
url: '/debug/pprof/symbol'
}
export type PostPprofSymbolResponses = {
/**
* Resolved symbols
*/
200: unknown
}
export type GetStaticExtensionsData = {
body?: never
path: {
path: string
}
query?: never
url: '/extensions/{path}'
}
export type GetStaticExtensionsErrors = {
/**
* File not found
*/
404: unknown
}
export type GetStaticExtensionsResponses = {
/**
* Static file
*/
200: unknown
}

View File

@@ -1070,29 +1070,6 @@ export const zSystemStatsResponse = z.object({
)
})
export const zLogsSubscribeRequest = z.object({
enabled: z.boolean()
})
/**
* Raw logs response with entries and size
*/
export const zRawLogsResponse = z.object({
entries: z
.array(
z.object({
m: z.string().optional()
})
)
.optional(),
size: z
.object({
cols: z.number().int().optional(),
rows: z.number().int().optional()
})
.optional()
})
/**
* System logs response
*/
@@ -2248,30 +2225,6 @@ export const zGetLogsData = z.object({
*/
export const zGetLogsResponse = zLogsResponse
export const zGetRawLogsData = z.object({
body: z.never().optional(),
path: z.never().optional(),
query: z.never().optional()
})
/**
* Success
*/
export const zGetRawLogsResponse = zRawLogsResponse
export const zSubscribeToLogsData = z.object({
body: zLogsSubscribeRequest,
path: z.never().optional(),
query: z.never().optional()
})
/**
* Success
*/
export const zSubscribeToLogsResponse = z.object({
enabled: z.boolean().optional()
})
export const zGetSystemStatsData = z.object({
body: z.never().optional(),
path: z.never().optional(),
@@ -3031,3 +2984,153 @@ export const zGetPublishedWorkflowData = z.object({
* Published workflow details with asset statuses
*/
export const zGetPublishedWorkflowResponse = zPublishedWorkflowDetail
export const zGetExtensionsData = z.object({
body: z.never().optional(),
path: z.never().optional(),
query: z.never().optional()
})
export const zGetVhsViewVideoData = z.object({
body: z.never().optional(),
path: z.never().optional(),
query: z.object({
filename: z.string(),
type: z.string().optional(),
subfolder: z.string().optional()
})
})
export const zGetVhsViewAudioData = z.object({
body: z.never().optional(),
path: z.never().optional(),
query: z.object({
filename: z.string(),
type: z.string().optional(),
subfolder: z.string().optional()
})
})
export const zGetVhsQueryVideoData = z.object({
body: z.never().optional(),
path: z.never().optional(),
query: z.object({
filename: z.string()
})
})
export const zGetUsersRawData = z.object({
body: z.never().optional(),
path: z.never().optional(),
query: z.never().optional()
})
export const zGetApiViewVideoAliasData = z.object({
body: z.never().optional(),
path: z.never().optional(),
query: z.object({
filename: z.string()
})
})
export const zGetViewCompatAliasData = z.object({
body: z.never().optional(),
path: z.never().optional(),
query: z.object({
filename: z.string()
})
})
export const zGetWebsocketData = z.object({
body: z.never().optional(),
path: z.never().optional(),
query: z
.object({
clientId: z.string().optional()
})
.optional()
})
export const zGetTemplateProxyData = z.object({
body: z.never().optional(),
path: z.object({
path: z.string()
}),
query: z.never().optional()
})
export const zGetHealthData = z.object({
body: z.never().optional(),
path: z.never().optional(),
query: z.never().optional()
})
export const zGetOpenapiSpecData = z.object({
body: z.never().optional(),
path: z.never().optional(),
query: z.never().optional()
})
export const zGetMonitoringTasksData = z.object({
body: z.never().optional(),
path: z.never().optional(),
query: z.never().optional()
})
export const zDeleteMonitoringTasksSubpathData = z.object({
body: z.never().optional(),
path: z.object({
path: z.string()
}),
query: z.never().optional()
})
export const zGetMonitoringTasksSubpathData = z.object({
body: z.never().optional(),
path: z.object({
path: z.string()
}),
query: z.never().optional()
})
export const zPostMonitoringTasksSubpathData = z.object({
body: z.never().optional(),
path: z.object({
path: z.string()
}),
query: z.never().optional()
})
export const zGetPprofData = z.object({
body: z.never().optional(),
path: z.object({
path: z.string()
}),
query: z.never().optional()
})
export const zGetPprofProfileData = z.object({
body: z.never().optional(),
path: z.never().optional(),
query: z.never().optional()
})
export const zGetPprofTraceData = z.object({
body: z.never().optional(),
path: z.never().optional(),
query: z.never().optional()
})
export const zPostPprofSymbolData = z.object({
body: z.never().optional(),
path: z.never().optional(),
query: z.never().optional()
})
export const zGetStaticExtensionsData = z.object({
body: z.never().optional(),
path: z.object({
path: z.string()
}),
query: z.never().optional()
})

View File

@@ -159,7 +159,7 @@ import { useI18n } from 'vue-i18n'
import PuzzleIcon from '@/components/icons/PuzzleIcon.vue'
import { useExternalLink } from '@/composables/useExternalLink'
import { isCloud, isDesktop } from '@/platform/distribution/types'
import { isCloud, isDesktop, isNightly } from '@/platform/distribution/types'
import { useSettingStore } from '@/platform/settings/settingStore'
import { useTelemetry } from '@/platform/telemetry'
import type { ReleaseNote } from '@/platform/updates/common/releaseService'
@@ -299,9 +299,18 @@ const menuItems = computed<MenuItem[]>(() => {
type: 'item',
icon: 'icon-[lucide--clipboard-pen]',
label: t('helpCenter.feedback'),
showExternalIcon: isCloud || isNightly,
action: () => {
trackResourceClick('help_feedback', false)
void commandStore.execute('Comfy.ContactSupport')
trackResourceClick('help_feedback', isCloud || isNightly)
if (isCloud || isNightly) {
window.open(
'https://form.typeform.com/to/q7azbWPi',
'_blank',
'noopener,noreferrer'
)
} else {
void commandStore.execute('Comfy.ContactSupport')
}
emit('close')
}
},

View File

@@ -1,10 +1,9 @@
import { t } from '@/i18n'
import { useSettingStore } from '@/platform/settings/settingStore'
import { buildFeedbackUrl } from '@/platform/support/config'
import { useExtensionService } from '@/services/extensionService'
import type { ActionBarButton } from '@/types/comfy'
const feedbackUrl = buildFeedbackUrl()
const TYPEFORM_SURVEY_URL = 'https://form.typeform.com/to/q7azbWPi'
const buttons: ActionBarButton[] = [
{
@@ -12,7 +11,7 @@ const buttons: ActionBarButton[] = [
label: t('actionbar.feedback'),
tooltip: t('actionbar.feedbackTooltip'),
onClick: () => {
window.open(feedbackUrl, '_blank', 'noopener,noreferrer')
window.open(TYPEFORM_SURVEY_URL, '_blank', 'noopener,noreferrer')
}
}
]

View File

@@ -143,9 +143,10 @@ app.registerExtension({
throw new Error(err)
}
const data = await resp.json()
const serverName = data.name ?? name
const subfolder = data.subfolder ?? 'webcam'
return `${subfolder}/${serverName} [temp]`
const serverName = data.name || name
const subfolder = data.subfolder || 'webcam'
const type = data.type || 'temp'
return `${subfolder}/${serverName} [${type}]`
}
// @ts-expect-error fixme ts strict error