[backport core/1.42] fix: restore is_template tracking for app mode templates (#10878)

Backport of #10252 to `core/1.42`

Automatically created by backport workflow.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-10878-backport-core-1-42-fix-restore-is_template-tracking-for-app-mode-templates-33a6d73d365081aa966df374a3e061fe)
by [Unito](https://www.unito.io)

Co-authored-by: ComfyUI Wiki <contact@comfyui-wiki.com>
This commit is contained in:
Comfy Org PR Bot
2026-04-07 06:30:10 +09:00
committed by GitHub
parent 5698ed88c9
commit 56eb72bddb
2 changed files with 73 additions and 11 deletions

View File

@@ -24,7 +24,13 @@ vi.mock('@/platform/telemetry/topupTracker', () => ({
const hoisted = vi.hoisted(() => ({
mockNodeDefsByName: {} as Record<string, unknown>,
mockNodes: [] as Pick<LGraphNode, 'type' | 'isSubgraphNode'>[]
mockNodes: [] as Pick<LGraphNode, 'type' | 'isSubgraphNode'>[],
mockActiveWorkflow: null as null | {
filename: string
fullFilename: string
},
mockKnownTemplateNames: new Set<string>(),
mockTemplateByName: null as null | { sourceModule?: string }
}))
vi.mock('@/stores/nodeDefStore', () => ({
@@ -35,7 +41,9 @@ vi.mock('@/stores/nodeDefStore', () => ({
vi.mock('@/platform/workflow/management/stores/workflowStore', () => ({
useWorkflowStore: () => ({
activeWorkflow: null
get activeWorkflow() {
return hoisted.mockActiveWorkflow
}
})
}))
@@ -43,7 +51,11 @@ vi.mock(
'@/platform/workflow/templates/repositories/workflowTemplatesStore',
() => ({
useWorkflowTemplatesStore: () => ({
knownTemplateNames: new Set()
get knownTemplateNames() {
return hoisted.mockKnownTemplateNames
},
getTemplateByName: (_name: string) => hoisted.mockTemplateByName,
getEnglishMetadata: () => null
})
})
)
@@ -85,6 +97,9 @@ describe('getExecutionContext', () => {
for (const key of Object.keys(hoisted.mockNodeDefsByName)) {
delete hoisted.mockNodeDefsByName[key]
}
hoisted.mockActiveWorkflow = null
hoisted.mockKnownTemplateNames = new Set()
hoisted.mockTemplateByName = null
})
it('returns has_toolkit_nodes false when no toolkit nodes are present', () => {
@@ -175,4 +190,50 @@ describe('getExecutionContext', () => {
expect(context.has_toolkit_nodes).toBe(true)
expect(context.toolkit_node_names).toEqual(['ImageCrop'])
})
describe('template detection', () => {
it('detects a regular template by name', () => {
hoisted.mockKnownTemplateNames = new Set(['flux-dev'])
hoisted.mockTemplateByName = { sourceModule: 'default' }
hoisted.mockActiveWorkflow = {
filename: 'flux-dev',
fullFilename: 'flux-dev.json'
}
const context = getExecutionContext()
expect(context.is_template).toBe(true)
expect(context.workflow_name).toBe('flux-dev')
})
it('detects an app mode template whose name ends with .app', () => {
hoisted.mockKnownTemplateNames = new Set([
'templates-qwen_multiangle.app'
])
hoisted.mockTemplateByName = { sourceModule: 'default' }
// getFilenameDetails strips ".app.json" as a compound extension, yielding
// filename = "templates-qwen_multiangle" — the previous code would fail here.
hoisted.mockActiveWorkflow = {
filename: 'templates-qwen_multiangle',
fullFilename: 'templates-qwen_multiangle.app.json'
}
const context = getExecutionContext()
expect(context.is_template).toBe(true)
expect(context.workflow_name).toBe('templates-qwen_multiangle.app')
})
it('does not flag a non-template workflow as a template', () => {
hoisted.mockKnownTemplateNames = new Set(['flux-dev'])
hoisted.mockActiveWorkflow = {
filename: 'my-custom-workflow',
fullFilename: 'my-custom-workflow.json'
}
const context = getExecutionContext()
expect(context.is_template).toBe(false)
})
})
})

View File

@@ -80,20 +80,21 @@ export function getExecutionContext(): ExecutionContext {
)
if (activeWorkflow?.filename) {
const isTemplate = templatesStore.knownTemplateNames.has(
activeWorkflow.filename
)
// Use fullFilename minus .json to reconstruct the template name, which
// preserves compound suffixes like ".app" (e.g. "foo.app.json" → "foo.app").
// Using just `filename` strips ".app.json" entirely (e.g. "foo"), which
// won't match knownTemplateNames entries like "foo.app".
const templateName = activeWorkflow.fullFilename.replace(/\.json$/i, '')
const isTemplate = templatesStore.knownTemplateNames.has(templateName)
if (isTemplate) {
const template = templatesStore.getTemplateByName(activeWorkflow.filename)
const template = templatesStore.getTemplateByName(templateName)
const englishMetadata = templatesStore.getEnglishMetadata(
activeWorkflow.filename
)
const englishMetadata = templatesStore.getEnglishMetadata(templateName)
return {
is_template: true,
workflow_name: activeWorkflow.filename,
workflow_name: templateName,
template_source: template?.sourceModule,
template_category: englishMetadata?.category ?? template?.category,
template_tags: englishMetadata?.tags ?? template?.tags,