Compare commits

..

2 Commits

Author SHA1 Message Date
GitHub Action
fb22b831c7 [automated] Apply ESLint and Oxfmt fixes 2026-04-09 02:48:56 +00:00
MillerMedia
4d0cb38095 [chore] Update Ingest API types from cloud@48d94b7 2026-04-09 02:45:54 +00:00
5 changed files with 650 additions and 263 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

@@ -1,103 +0,0 @@
import { createTestingPinia } from '@pinia/testing'
import { setActivePinia } from 'pinia'
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
import { LGraph, LGraphNode, LiteGraph } from '@/lib/litegraph/src/litegraph'
import type { ComfyNodeDef } from '@/schemas/nodeDefSchema'
import { app } from '@/scripts/app'
import { useExtensionStore } from '@/stores/extensionStore'
import type { ComfyExtension } from '@/types/comfy'
const TEST_CUSTOM_COMBO_TYPE = 'test/CustomComboCopyPaste'
class TestCustomComboNode extends LGraphNode {
static override title = 'CustomCombo'
constructor() {
super('CustomCombo')
this.serialize_widgets = true
this.addOutput('value', '*')
this.addWidget('combo', 'value', '', () => {}, {
values: [] as string[]
})
}
}
function findWidget(node: LGraphNode, name: string) {
return node.widgets?.find((widget) => widget.name === name)
}
function getCustomWidgetsExtension(): ComfyExtension {
const extension = useExtensionStore().extensions.find(
(candidate) => candidate.name === 'Comfy.CustomWidgets'
)
if (!extension) {
throw new Error('Comfy.CustomWidgets extension was not registered')
}
return extension
}
describe('CustomCombo copy/paste', () => {
beforeAll(async () => {
setActivePinia(createTestingPinia({ stubActions: false }))
await import('./customWidgets')
const extension = getCustomWidgetsExtension()
await extension.beforeRegisterNodeDef?.(
TestCustomComboNode,
{ name: 'CustomCombo' } as ComfyNodeDef,
app
)
if (LiteGraph.registered_node_types[TEST_CUSTOM_COMBO_TYPE]) {
LiteGraph.unregisterNodeType(TEST_CUSTOM_COMBO_TYPE)
}
LiteGraph.registerNodeType(TEST_CUSTOM_COMBO_TYPE, TestCustomComboNode)
})
afterAll(() => {
if (LiteGraph.registered_node_types[TEST_CUSTOM_COMBO_TYPE]) {
LiteGraph.unregisterNodeType(TEST_CUSTOM_COMBO_TYPE)
}
})
it('preserves combo options and selected value through clone and paste', () => {
const graph = new LGraph()
type AppWithRootGraph = { rootGraphInternal?: LGraph }
const appWithRootGraph = app as unknown as AppWithRootGraph
const previousRootGraph = appWithRootGraph.rootGraphInternal
appWithRootGraph.rootGraphInternal = graph
try {
const original = LiteGraph.createNode(TEST_CUSTOM_COMBO_TYPE)!
graph.add(original)
findWidget(original, 'option1')!.value = 'alpha'
findWidget(original, 'option2')!.value = 'beta'
findWidget(original, 'option3')!.value = 'gamma'
findWidget(original, 'value')!.value = 'beta'
const clonedSerialised = original.clone()?.serialize()
expect(clonedSerialised).toBeDefined()
const pasted = LiteGraph.createNode(TEST_CUSTOM_COMBO_TYPE)!
pasted.configure(clonedSerialised!)
graph.add(pasted)
expect(findWidget(pasted, 'value')!.value).toBe('beta')
expect(findWidget(pasted, 'option1')!.value).toBe('alpha')
expect(findWidget(pasted, 'option2')!.value).toBe('beta')
expect(findWidget(pasted, 'option3')!.value).toBe('gamma')
expect(findWidget(pasted, 'value')!.options.values).toEqual([
'alpha',
'beta',
'gamma'
])
} finally {
appWithRootGraph.rootGraphInternal = previousRootGraph
}
})
})

View File

@@ -63,7 +63,7 @@ function onCustomComboCreated(this: LGraphNode) {
(w) => w.name.startsWith('option') && w.value
).map((w) => `${w.value}`)
)
if (app.configuringGraph || !this.graph) return
if (app.configuringGraph) return
if (values.includes(`${comboWidget.value}`)) return
comboWidget.value = values[0] ?? ''
comboWidget.callback?.(comboWidget.value)
@@ -71,9 +71,6 @@ function onCustomComboCreated(this: LGraphNode) {
comboWidget.callback = useChainCallback(comboWidget.callback, () =>
this.applyToGraph!()
)
this.onAdded = useChainCallback(this.onAdded, function () {
updateCombo()
})
function addOption(node: LGraphNode) {
if (!node.widgets) return
@@ -81,17 +78,16 @@ function onCustomComboCreated(this: LGraphNode) {
const widgetName = `option${newCount}`
const widget = node.addWidget('string', widgetName, '', () => {})
if (!widget) return
let localValue = `${widget.value ?? ''}`
Object.defineProperty(widget, 'value', {
get() {
return (
useWidgetValueStore().getWidget(app.rootGraph.id, node.id, widgetName)
?.value ?? localValue
)
return useWidgetValueStore().getWidget(
app.rootGraph.id,
node.id,
widgetName
)?.value
},
set(v: string) {
localValue = v
const state = useWidgetValueStore().getWidget(
app.rootGraph.id,
node.id,