Compare commits

...

5 Commits

Author SHA1 Message Date
Christian Byrne
aeedb60628 fix(ci): resolve pnpm version in release workflow for frontend/ checkout path (#11224)
The release workflow checks out to `frontend/` subdirectory, but
`pnpm/action-setup` looks for `package.json` at the repo root by
default. This causes `No pnpm version is specified` failures.

Adds `package_json_file: frontend/package.json` so the action can read
the `packageManager` field. Same pattern used in #10972 for the
version-bump workflow.

┆Issue is synchronized with this [Notion
page](https://app.notion.com/p/PR-11224-fix-ci-resolve-pnpm-version-in-release-workflow-for-frontend-checkout-path-3426d73d365081c28d16cb01bf8218ef)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
2026-04-13 21:41:22 -07:00
Christian Byrne
43fb5a8b19 ops: add patch release support to ComfyUI release workflow (#11223)
## Summary

Add `release_type` input (`minor`/`patch`) to the release workflow so
patch releases can target the current production branch instead of
always preferring the next minor.

## Problem

When a patch release is needed for `core/1.42` but `core/1.43` already
exists, the resolver always prefers `1.43`. There was no way to do a
patch release with PyPI publish + ComfyUI PR for the current production
version.

## Changes

- Rename workflow from "Release: Bi-weekly ComfyUI" → "Release: ComfyUI"
(serves both cadences)
- Add `release_type` choice input: `minor` (default, bi-weekly) vs
`patch` (hotfix for current production version)
- Update `resolve-comfyui-release.ts` to read `RELEASE_TYPE` env var for
branch targeting
- Scheduled runs continue to work as before (default to `minor`)

## Usage

```bash
# Bi-weekly minor release (or just let the schedule run)
gh workflow run release-biweekly-comfyui.yaml --ref main

# Patch release for current production version
gh workflow run release-biweekly-comfyui.yaml --ref main --field release_type=patch
```

┆Issue is synchronized with this [Notion
page](https://app.notion.com/p/PR-11223-ops-add-patch-release-support-to-ComfyUI-release-workflow-3426d73d365081498c15ff978a7f1116)
by [Unito](https://www.unito.io)
2026-04-13 21:10:17 -07:00
Christian Byrne
c484c3984f fix: remove appendTo override from FormDropdown to restore correct positioning (#11147)
## Problem

PR #10338 added `useTransformCompatOverlayProps()` to FormDropdown and
FormDropdownMenuActions, which sets `appendTo: 'self'` in graph mode.
This breaks PrimeVue Popover positioning inside CSS-transformed
containers — the dropdown appears at incorrect Y positions.

## Root Cause

PrimeVue Popover with `appendTo: 'self'` renders the overlay inside the
component's DOM, inheriting parent CSS transforms. This causes the
popover to miscalculate its position when the parent has `transform:
scale()` or `translate()`.

## Fix

Remove the `appendTo` override from both FormDropdown and
FormDropdownMenuActions. PrimeVue defaults to `appendTo: 'body'`, which
teleports the popover to `<body>` — correctly positioning it outside any
CSS transform context.

- **Graph mode**: restores pre-#10338 behavior (`appendTo: 'body'`
default)
- **App mode**: unaffected — `'body'` is exactly what app mode needs
(prevents sidebar overflow clipping)

## Testing

- Existing unit tests pass (5/5)
- Typecheck clean
- Lint clean
- **E2E test rationale**: No E2E test added — this is a pure removal of
a prop override (reverting to PrimeVue defaults). The positioning bug
requires CSS transforms at specific viewport scales which are
impractical to assert reliably in Playwright. The existing
`subgraph-dom-widget-clipping` perf test exercises dropdown rendering in
transformed contexts and shows no regression.

Fixes #10499
Supersedes #11001 (temporary hotfix for backport)

---------

Co-authored-by: GitHub Action <action@github.com>
2026-04-13 20:02:39 -07:00
Dante
2524846f5c fix: guard progress_text before canvas init (#11174)
## Summary
Prevent early `progress_text` websocket events from throwing before the
graph canvas is initialized.

## Changes
- **What**: Guard `handleProgressText()` until `canvasStore.canvas`
exists, and add a regression test for a startup-time `progress_text`
event arriving before `GraphCanvas` finishes initialization.

## Review Focus
Confirm this is the right guard point for the startup race between
`GraphView` websocket binding and `GraphCanvas` async setup, and that
progress text behavior is unchanged once the canvas is ready.

## Validation
- `pnpm exec eslint src/stores/executionStore.ts
src/stores/executionStore.test.ts`
- `pnpm exec vitest run src/stores/executionStore.test.ts -t "should
ignore progress_text before the canvas is initialized"`
- `pnpm test:unit -- --run src/stores/executionStore.test.ts` still
reports one unrelated isolated-file failure in
`nodeLocatorIdToExecutionId` on current `main`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11174-fix-guard-progress_text-before-canvas-init-3406d73d3650813dad23d511fb51add5)
by [Unito](https://www.unito.io)
2026-04-13 23:47:14 +00:00
Comfy Org PR Bot
12f578870e 1.44.4 (#11177)
Patch version increment to 1.44.4

**Base branch:** `main`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11177-1-44-4-3416d73d365081c0a2e0def7071c1441)
by [Unito](https://www.unito.io)

---------

Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
2026-04-13 23:19:20 +00:00
18 changed files with 256 additions and 34 deletions

View File

@@ -1,14 +1,23 @@
# Automated bi-weekly workflow to bump ComfyUI frontend RC releases
name: 'Release: Bi-weekly ComfyUI'
# Release workflow for ComfyUI frontend: version bump → PyPI publish → ComfyUI PR.
# Runs on a bi-weekly schedule for minor releases, or manually for patch/hotfix releases.
name: 'Release: ComfyUI'
on:
# Schedule for Monday at 12:00 PM PST (20:00 UTC)
# Bi-weekly schedule: Monday at 20:00 UTC
schedule:
- cron: '0 20 * * 1'
# Allow manual triggering (bypasses bi-weekly check)
# Manual trigger for both on-demand minor and patch/hotfix releases
workflow_dispatch:
inputs:
release_type:
description: 'minor = next minor version (bi-weekly cadence), patch = hotfix for current production version'
required: true
default: 'minor'
type: choice
options:
- minor
- patch
comfyui_fork:
description: 'ComfyUI fork to use for PR (e.g., Comfy-Org/ComfyUI)'
required: false
@@ -41,10 +50,11 @@ jobs:
- name: Summary
run: |
echo "## Bi-weekly Check" >> $GITHUB_STEP_SUMMARY
echo "## Release Check" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- Is release week: ${{ steps.check.outputs.is_release_week }}" >> $GITHUB_STEP_SUMMARY
echo "- Manual trigger: ${{ github.event_name == 'workflow_dispatch' }}" >> $GITHUB_STEP_SUMMARY
echo "- Release type: ${{ inputs.release_type || 'minor (scheduled)' }}" >> $GITHUB_STEP_SUMMARY
resolve-version:
needs: check-release-week
@@ -76,6 +86,8 @@ jobs:
- name: Install pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0
with:
package_json_file: frontend/package.json
- name: Setup Node.js
uses: actions/setup-node@v6
@@ -89,6 +101,8 @@ jobs:
- name: Resolve release information
id: resolve
working-directory: frontend
env:
RELEASE_TYPE: ${{ inputs.release_type || 'minor' }}
run: |
set -euo pipefail

View File

@@ -1,6 +1,6 @@
{
"name": "@comfyorg/comfyui-frontend",
"version": "1.44.3",
"version": "1.44.4",
"private": true,
"description": "Official front-end implementation of ComfyUI",
"homepage": "https://comfy.org",

View File

@@ -137,35 +137,71 @@ function resolveRelease(
// Fetch all branches
exec('git fetch origin', frontendRepoPath)
// Try next minor first, fall back to current minor if not available
let targetMinor = currentMinor + 1
let targetBranch = `core/1.${targetMinor}`
// Determine target branch based on release type:
// 'patch' → target current minor (hotfix for production version)
// 'minor' → try next minor, fall back to current minor (bi-weekly cadence)
const releaseTypeInput =
process.env.RELEASE_TYPE?.trim().toLowerCase() || 'minor'
if (releaseTypeInput !== 'minor' && releaseTypeInput !== 'patch') {
console.error(
`Invalid RELEASE_TYPE: "${releaseTypeInput}". Expected "minor" or "patch"`
)
return null
}
const releaseType: 'minor' | 'patch' = releaseTypeInput
let targetMinor: number
let targetBranch: string
const nextMinorExists = exec(
`git rev-parse --verify origin/${targetBranch}`,
frontendRepoPath
)
if (!nextMinorExists) {
// Fall back to current minor for patch releases
if (releaseType === 'patch') {
targetMinor = currentMinor
targetBranch = `core/1.${targetMinor}`
const currentMinorExists = exec(
const branchExists = exec(
`git rev-parse --verify origin/${targetBranch}`,
frontendRepoPath
)
if (!currentMinorExists) {
if (!branchExists) {
console.error(
`Neither core/1.${currentMinor + 1} nor core/1.${currentMinor} branches exist in frontend repo`
`Patch release requested but branch ${targetBranch} does not exist`
)
return null
}
console.error(
`Next minor branch core/1.${currentMinor + 1} not found, falling back to core/1.${currentMinor} for patch release`
`Patch release: targeting current production branch ${targetBranch}`
)
} else {
// Try next minor first, fall back to current minor if not available
targetMinor = currentMinor + 1
targetBranch = `core/1.${targetMinor}`
const nextMinorExists = exec(
`git rev-parse --verify origin/${targetBranch}`,
frontendRepoPath
)
if (!nextMinorExists) {
// Fall back to current minor for minor release
targetMinor = currentMinor
targetBranch = `core/1.${targetMinor}`
const currentMinorExists = exec(
`git rev-parse --verify origin/${targetBranch}`,
frontendRepoPath
)
if (!currentMinorExists) {
console.error(
`Neither core/1.${currentMinor + 1} nor core/1.${currentMinor} branches exist in frontend repo`
)
return null
}
console.error(
`Next minor branch core/1.${currentMinor + 1} not found, falling back to core/1.${currentMinor} for minor release`
)
}
}
// Get latest patch tag for target minor
@@ -264,7 +300,7 @@ if (!releaseInfo) {
}
// Output as JSON for GitHub Actions
// oxlint-disable-next-line no-console -- stdout is captured by the workflow
console.log(JSON.stringify(releaseInfo, null, 2))
export { resolveRelease }

View File

@@ -1642,9 +1642,18 @@
"exportRecording": "تصدير التسجيل",
"exportingModel": "جارٍ تصدير النموذج...",
"fov": "مجال الرؤية (FOV)",
"hdri": {
"changeFile": "تغيير HDRI",
"intensity": "الشدة",
"label": "بيئة HDRI",
"removeFile": "إزالة HDRI",
"showAsBackground": "عرض كخلفية",
"uploadFile": "رفع HDRI (.hdr, .exr)"
},
"light": "الإضاءة",
"lightIntensity": "شدة الإضاءة",
"loadingBackgroundImage": "جارٍ تحميل صورة الخلفية",
"loadingHDRI": "جارٍ تحميل HDRI...",
"loadingModel": "جارٍ تحميل النموذج ثلاثي الأبعاد...",
"materialMode": "وضع المادة",
"materialModes": {
@@ -3431,6 +3440,7 @@
"failedToInitiateCreditPurchase": "فشل في بدء شراء الرصيد: {error}",
"failedToInitiateSubscription": "فشل في بدء الاشتراك: {error}",
"failedToLoadBackgroundImage": "فشل في تحميل صورة الخلفية",
"failedToLoadHDRI": "فشل في تحميل ملف HDRI",
"failedToLoadModel": "فشل في تحميل النموذج ثلاثي الأبعاد",
"failedToPurchaseCredits": "فشل في شراء الرصيد: {error}",
"failedToQueue": "فشل في الإضافة إلى قائمة الانتظار",
@@ -3466,6 +3476,7 @@
"pleaseSelectOutputNodes": "يرجى اختيار عقد الإخراج",
"unableToGetModelFilePath": "غير قادر على الحصول على مسار ملف النموذج",
"unauthorizedDomain": "النطاق الخاص بك {domain} غير مخول لاستخدام هذه الخدمة. يرجى الاتصال بـ {email} لإضافة النطاق إلى القائمة البيضاء.",
"unsupportedHDRIFormat": "تنسيق الملف غير مدعوم. يرجى رفع ملف .hdr أو .exr.",
"updateRequested": "تم طلب التحديث",
"useApiKeyTip": "نصيحة: لا يمكنك الدخول عبر تسجيل الدخول العادي؟ استخدم خيار مفتاح API الخاص بـ Comfy.",
"userNotAuthenticated": "المستخدم غير مصدق"

View File

@@ -1642,9 +1642,18 @@
"exportRecording": "Exportar grabación",
"exportingModel": "Exportando modelo...",
"fov": "FOV",
"hdri": {
"changeFile": "Cambiar HDRI",
"intensity": "Intensidad",
"label": "Entorno HDRI",
"removeFile": "Eliminar HDRI",
"showAsBackground": "Mostrar como fondo",
"uploadFile": "Subir HDRI (.hdr, .exr)"
},
"light": "Luz",
"lightIntensity": "Intensidad de luz",
"loadingBackgroundImage": "Cargando imagen de fondo",
"loadingHDRI": "Cargando HDRI...",
"loadingModel": "Cargando modelo 3D...",
"materialMode": "Modo de material",
"materialModes": {
@@ -3431,6 +3440,7 @@
"failedToInitiateCreditPurchase": "No se pudo iniciar la compra de créditos: {error}",
"failedToInitiateSubscription": "Error al iniciar la suscripción: {error}",
"failedToLoadBackgroundImage": "Error al cargar la imagen de fondo",
"failedToLoadHDRI": "No se pudo cargar el archivo HDRI",
"failedToLoadModel": "Error al cargar el modelo 3D",
"failedToPurchaseCredits": "No se pudo comprar créditos: {error}",
"failedToQueue": "Error al encolar",
@@ -3466,6 +3476,7 @@
"pleaseSelectOutputNodes": "Por favor, selecciona los nodos de salida",
"unableToGetModelFilePath": "No se puede obtener la ruta del archivo del modelo",
"unauthorizedDomain": "Tu dominio {domain} no está autorizado para usar este servicio. Por favor, contacta a {email} para agregar tu dominio a la lista blanca.",
"unsupportedHDRIFormat": "Formato de archivo no compatible. Por favor, sube un archivo .hdr o .exr.",
"updateRequested": "Actualización solicitada",
"useApiKeyTip": "Consejo: ¿No puedes acceder al inicio de sesión normal? Usa la opción de clave API de Comfy.",
"userNotAuthenticated": "Usuario no autenticado"

View File

@@ -1642,9 +1642,18 @@
"exportRecording": "خروجی گرفتن ضبط",
"exportingModel": "در حال خروجی گرفتن مدل...",
"fov": "زاویه دید (FOV)",
"hdri": {
"changeFile": "تغییر HDRI",
"intensity": "شدت",
"label": "محیط HDRI",
"removeFile": "حذف HDRI",
"showAsBackground": "نمایش به عنوان پس‌زمینه",
"uploadFile": "بارگذاری HDRI (.hdr، .exr)"
},
"light": "نور",
"lightIntensity": "شدت نور",
"loadingBackgroundImage": "در حال بارگذاری تصویر پس‌زمینه",
"loadingHDRI": "در حال بارگذاری HDRI...",
"loadingModel": "در حال بارگذاری مدل سه‌بعدی...",
"materialMode": "حالت متریال",
"materialModes": {
@@ -3443,6 +3452,7 @@
"failedToInitiateCreditPurchase": "آغاز خرید اعتبار انجام نشد: {error}",
"failedToInitiateSubscription": "آغاز اشتراک انجام نشد: {error}",
"failedToLoadBackgroundImage": "بارگذاری تصویر پس‌زمینه انجام نشد",
"failedToLoadHDRI": "بارگذاری فایل HDRI ناموفق بود",
"failedToLoadModel": "بارگذاری مدل سه‌بعدی انجام نشد",
"failedToPurchaseCredits": "خرید اعتبار انجام نشد: {error}",
"failedToQueue": "صف‌بندی انجام نشد",
@@ -3478,6 +3488,7 @@
"pleaseSelectOutputNodes": "لطفاً nodeهای خروجی را انتخاب کنید",
"unableToGetModelFilePath": "امکان دریافت مسیر فایل مدل وجود ندارد",
"unauthorizedDomain": "دامنه شما ({domain}) مجاز به استفاده از این سرویس نیست. لطفاً برای افزودن دامنه خود به لیست سفید با {email} تماس بگیرید.",
"unsupportedHDRIFormat": "فرمت فایل پشتیبانی نمی‌شود. لطفاً یک فایل .hdr یا .exr بارگذاری کنید.",
"updateRequested": "درخواست به‌روزرسانی ثبت شد",
"useApiKeyTip": "نکته: به ورود عادی دسترسی ندارید؟ از گزینه Comfy API Key استفاده کنید.",
"userNotAuthenticated": "کاربر احراز هویت نشده است"

View File

@@ -1642,9 +1642,18 @@
"exportRecording": "Exporter l'enregistrement",
"exportingModel": "Exportation du modèle en cours...",
"fov": "FOV",
"hdri": {
"changeFile": "Changer l'HDRI",
"intensity": "Intensité",
"label": "Environnement HDRI",
"removeFile": "Supprimer l'HDRI",
"showAsBackground": "Afficher comme arrière-plan",
"uploadFile": "Télécharger un HDRI (.hdr, .exr)"
},
"light": "Lumière",
"lightIntensity": "Intensité de la lumière",
"loadingBackgroundImage": "Chargement de limage darrière-plan",
"loadingHDRI": "Chargement de l'HDRI...",
"loadingModel": "Chargement du modèle 3D...",
"materialMode": "Mode Matériel",
"materialModes": {
@@ -3431,6 +3440,7 @@
"failedToInitiateCreditPurchase": "Échec de l'initiation de l'achat de crédits : {error}",
"failedToInitiateSubscription": "Échec de l'initialisation de l'abonnement : {error}",
"failedToLoadBackgroundImage": "Échec du chargement de l'image d'arrière-plan",
"failedToLoadHDRI": "Échec du chargement du fichier HDRI",
"failedToLoadModel": "Échec du chargement du modèle 3D",
"failedToPurchaseCredits": "Échec de l'achat de crédits : {error}",
"failedToQueue": "Échec de la mise en file d'attente",
@@ -3466,6 +3476,7 @@
"pleaseSelectOutputNodes": "Veuillez sélectionner les nœuds de sortie",
"unableToGetModelFilePath": "Impossible d'obtenir le chemin du fichier modèle",
"unauthorizedDomain": "Votre domaine {domain} n'est pas autorisé à utiliser ce service. Veuillez contacter {email} pour ajouter votre domaine à la liste blanche.",
"unsupportedHDRIFormat": "Format de fichier non pris en charge. Veuillez télécharger un fichier .hdr ou .exr.",
"updateRequested": "Mise à jour demandée",
"useApiKeyTip": "Astuce : Vous ne pouvez pas accéder à la connexion normale ? Utilisez loption Clé API Comfy.",
"userNotAuthenticated": "Utilisateur non authentifié"

View File

@@ -1642,9 +1642,18 @@
"exportRecording": "録画をエクスポート",
"exportingModel": "モデルをエクスポート中...",
"fov": "FOV",
"hdri": {
"changeFile": "HDRIを変更",
"intensity": "強度",
"label": "HDRI環境",
"removeFile": "HDRIを削除",
"showAsBackground": "背景として表示",
"uploadFile": "HDRIをアップロード.hdr、.exr"
},
"light": "ライト",
"lightIntensity": "光の強度",
"loadingBackgroundImage": "背景画像を読み込んでいます",
"loadingHDRI": "HDRIを読み込み中...",
"loadingModel": "3Dモデルを読み込んでいます...",
"materialMode": "マテリアルモード",
"materialModes": {
@@ -3431,6 +3440,7 @@
"failedToInitiateCreditPurchase": "クレジット購入の開始に失敗しました: {error}",
"failedToInitiateSubscription": "サブスクリプションの開始に失敗しました: {error}",
"failedToLoadBackgroundImage": "背景画像の読み込みに失敗しました",
"failedToLoadHDRI": "HDRIファイルの読み込みに失敗しました",
"failedToLoadModel": "3Dモデルの読み込みに失敗しました",
"failedToPurchaseCredits": "クレジットの購入に失敗しました: {error}",
"failedToQueue": "キューに追加できませんでした",
@@ -3466,6 +3476,7 @@
"pleaseSelectOutputNodes": "出力ノードを選択してください",
"unableToGetModelFilePath": "モデルファイルのパスを取得できません",
"unauthorizedDomain": "あなたのドメイン {domain} はこのサービスを利用する権限がありません。ご利用のドメインをホワイトリストに追加するには、{email} までご連絡ください。",
"unsupportedHDRIFormat": "サポートされていないファイル形式です。.hdrまたは.exrファイルをアップロードしてください。",
"updateRequested": "更新が要求されました",
"useApiKeyTip": "ヒント通常のログインにアクセスできませんかComfy APIキーオプションを使用してください。",
"userNotAuthenticated": "ユーザーが認証されていません"

View File

@@ -1642,9 +1642,18 @@
"exportRecording": "녹화 내보내기",
"exportingModel": "모델 내보내기 중...",
"fov": "FOV",
"hdri": {
"changeFile": "HDRI 변경",
"intensity": "강도",
"label": "HDRI 환경",
"removeFile": "HDRI 제거",
"showAsBackground": "배경으로 표시",
"uploadFile": "HDRI 업로드 (.hdr, .exr)"
},
"light": "빛",
"lightIntensity": "조명 강도",
"loadingBackgroundImage": "배경 이미지 불러오는 중",
"loadingHDRI": "HDRI 불러오는 중...",
"loadingModel": "3D 모델 로딩 중...",
"materialMode": "재질 모드",
"materialModes": {
@@ -3431,6 +3440,7 @@
"failedToInitiateCreditPurchase": "크레딧 구매를 시작하지 못했습니다: {error}",
"failedToInitiateSubscription": "구독을 시작하지 못함: {error}",
"failedToLoadBackgroundImage": "배경 이미지를 로드하지 못함",
"failedToLoadHDRI": "HDRI 파일을 불러오지 못했습니다",
"failedToLoadModel": "3D 모델을 로드하지 못함",
"failedToPurchaseCredits": "크레딧 구매에 실패했습니다: {error}",
"failedToQueue": "대기열 추가 실패",
@@ -3466,6 +3476,7 @@
"pleaseSelectOutputNodes": "출력 노드를 선택해 주세요",
"unableToGetModelFilePath": "모델 파일 경로를 가져올 수 없습니다",
"unauthorizedDomain": "귀하의 도메인 {domain}은(는) 이 서비스를 사용할 수 있는 권한이 없습니다. 도메인을 허용 목록에 추가하려면 {email}로 문의해 주세요.",
"unsupportedHDRIFormat": "지원되지 않는 파일 형식입니다. .hdr 또는 .exr 파일을 업로드해 주세요.",
"updateRequested": "업데이트 요청됨",
"useApiKeyTip": "팁: 일반 로그인을 사용할 수 없나요? Comfy API Key 옵션을 사용하세요.",
"userNotAuthenticated": "사용자가 인증되지 않았습니다"

View File

@@ -1642,9 +1642,18 @@
"exportRecording": "Exportar Gravação",
"exportingModel": "Exportando modelo...",
"fov": "Campo de Visão (FOV)",
"hdri": {
"changeFile": "Alterar HDRI",
"intensity": "Intensidade",
"label": "Ambiente HDRI",
"removeFile": "Remover HDRI",
"showAsBackground": "Exibir como fundo",
"uploadFile": "Enviar HDRI (.hdr, .exr)"
},
"light": "Luz",
"lightIntensity": "Intensidade da Luz",
"loadingBackgroundImage": "Carregando Imagem de Fundo",
"loadingHDRI": "Carregando HDRI...",
"loadingModel": "Carregando Modelo 3D...",
"materialMode": "Modo de Material",
"materialModes": {
@@ -3443,6 +3452,7 @@
"failedToInitiateCreditPurchase": "Falha ao iniciar compra de créditos: {error}",
"failedToInitiateSubscription": "Falha ao iniciar assinatura: {error}",
"failedToLoadBackgroundImage": "Falha ao carregar imagem de fundo",
"failedToLoadHDRI": "Falha ao carregar o arquivo HDRI",
"failedToLoadModel": "Falha ao carregar modelo 3D",
"failedToPurchaseCredits": "Falha ao comprar créditos: {error}",
"failedToQueue": "Falha ao enfileirar",
@@ -3478,6 +3488,7 @@
"pleaseSelectOutputNodes": "Por favor, selecione os nós de saída",
"unableToGetModelFilePath": "Não foi possível obter o caminho do arquivo do modelo",
"unauthorizedDomain": "Seu domínio {domain} não está autorizado a usar este serviço. Por favor, entre em contato com {email} para adicionar seu domínio à lista de permissões.",
"unsupportedHDRIFormat": "Formato de arquivo não suportado. Por favor, envie um arquivo .hdr ou .exr.",
"updateRequested": "Atualização solicitada",
"useApiKeyTip": "Dica: Não consegue acessar o login normal? Use a opção Comfy API Key.",
"userNotAuthenticated": "Usuário não autenticado"

View File

@@ -1642,9 +1642,18 @@
"exportRecording": "Экспортировать запись",
"exportingModel": "Экспорт модели...",
"fov": "Угол обзора",
"hdri": {
"changeFile": "Сменить HDRI",
"intensity": "Интенсивность",
"label": "HDRI-окружение",
"removeFile": "Удалить HDRI",
"showAsBackground": "Показать как фон",
"uploadFile": "Загрузить HDRI (.hdr, .exr)"
},
"light": "Свет",
"lightIntensity": "Интенсивность света",
"loadingBackgroundImage": "Загрузка фонового изображения",
"loadingHDRI": "Загрузка HDRI...",
"loadingModel": "Загрузка 3D модели...",
"materialMode": "Режим Материала",
"materialModes": {
@@ -3431,6 +3440,7 @@
"failedToInitiateCreditPurchase": "Не удалось начать покупку кредитов: {error}",
"failedToInitiateSubscription": "Не удалось инициировать подписку: {error}",
"failedToLoadBackgroundImage": "Не удалось загрузить фоновое изображение",
"failedToLoadHDRI": "Не удалось загрузить файл HDRI",
"failedToLoadModel": "Не удалось загрузить 3D-модель",
"failedToPurchaseCredits": "Не удалось купить кредиты: {error}",
"failedToQueue": "Не удалось поставить в очередь",
@@ -3466,6 +3476,7 @@
"pleaseSelectOutputNodes": "Пожалуйста, выберите выходные узлы",
"unableToGetModelFilePath": "Не удалось получить путь к файлу модели",
"unauthorizedDomain": "Ваш домен {domain} не авторизован для использования этого сервиса. Пожалуйста, свяжитесь с {email}, чтобы добавить ваш домен в белый список.",
"unsupportedHDRIFormat": "Неподдерживаемый формат файла. Пожалуйста, загрузите файл .hdr или .exr.",
"updateRequested": "Запрошено обновление",
"useApiKeyTip": "Совет: Нет доступа к обычному входу? Используйте опцию Comfy API Key.",
"userNotAuthenticated": "Пользователь не аутентифицирован"

View File

@@ -1642,9 +1642,18 @@
"exportRecording": "Kaydı Dışa Aktar",
"exportingModel": "Model dışa aktarılıyor...",
"fov": "FOV",
"hdri": {
"changeFile": "HDRI Değiştir",
"intensity": "Yoğunluk",
"label": "HDRI Ortamı",
"removeFile": "HDRI Kaldır",
"showAsBackground": "Arka Plan Olarak Göster",
"uploadFile": "HDRI Yükle (.hdr, .exr)"
},
"light": "Işık",
"lightIntensity": "Işık Yoğunluğu",
"loadingBackgroundImage": "Arka Plan Resmi Yükleniyor",
"loadingHDRI": "HDRI Yükleniyor...",
"loadingModel": "3D Model Yükleniyor...",
"materialMode": "Malzeme Modu",
"materialModes": {
@@ -3431,6 +3440,7 @@
"failedToInitiateCreditPurchase": "Kredi satın alma başlatılamadı: {error}",
"failedToInitiateSubscription": "Abonelik başlatılamadı: {error}",
"failedToLoadBackgroundImage": "Arka plan görseli yüklenemedi",
"failedToLoadHDRI": "HDRI dosyası yüklenemedi",
"failedToLoadModel": "3B model yüklenemedi",
"failedToPurchaseCredits": "Kredi satın alınamadı: {error}",
"failedToQueue": "Kuyruğa alınamadı",
@@ -3466,6 +3476,7 @@
"pleaseSelectOutputNodes": "Lütfen çıktı düğümlerini seçin",
"unableToGetModelFilePath": "Model dosyası yolu alınamıyor",
"unauthorizedDomain": "{domain} alan adınız bu hizmeti kullanma yetkisine sahip değil. Alan adınızı beyaz listeye eklemek için lütfen {email} ile iletişime geçin.",
"unsupportedHDRIFormat": "Desteklenmeyen dosya formatı. Lütfen .hdr veya .exr dosyası yükleyin.",
"updateRequested": "Güncelleme istendi",
"useApiKeyTip": "İpucu: Normal girişe erişemiyor musunuz? Comfy API Anahtarı seçeneğini kullanın.",
"userNotAuthenticated": "Kullanıcı doğrulanmadı"

View File

@@ -1642,9 +1642,18 @@
"exportRecording": "匯出錄影",
"exportingModel": "正在匯出模型...",
"fov": "視野角度",
"hdri": {
"changeFile": "更換 HDRI",
"intensity": "強度",
"label": "HDRI 環境",
"removeFile": "移除 HDRI",
"showAsBackground": "作為背景顯示",
"uploadFile": "上傳 HDRI.hdr, .exr"
},
"light": "光源",
"lightIntensity": "光源強度",
"loadingBackgroundImage": "正在載入背景圖片",
"loadingHDRI": "正在載入 HDRI...",
"loadingModel": "正在載入 3D 模型...",
"materialMode": "材質模式",
"materialModes": {
@@ -3431,6 +3440,7 @@
"failedToInitiateCreditPurchase": "啟動點數購買失敗:{error}",
"failedToInitiateSubscription": "無法啟用訂閱:{error}",
"failedToLoadBackgroundImage": "無法載入背景圖片",
"failedToLoadHDRI": "載入 HDRI 檔案失敗",
"failedToLoadModel": "無法載入 3D 模型",
"failedToPurchaseCredits": "購買點數失敗:{error}",
"failedToQueue": "加入佇列失敗",
@@ -3466,6 +3476,7 @@
"pleaseSelectOutputNodes": "請選擇輸出節點",
"unableToGetModelFilePath": "無法取得模型檔案路徑",
"unauthorizedDomain": "您的網域 {domain} 未被授權使用此服務。請聯絡 {email} 以將您的網域加入白名單。",
"unsupportedHDRIFormat": "不支援的檔案格式。請上傳 .hdr 或 .exr 檔案。",
"updateRequested": "已請求更新",
"useApiKeyTip": "提示:無法正常登入?請使用 Comfy API 金鑰選項。",
"userNotAuthenticated": "使用者未驗證"

View File

@@ -1642,9 +1642,18 @@
"exportRecording": "导出录制",
"exportingModel": "正在导出模型...",
"fov": "视场",
"hdri": {
"changeFile": "更换HDRI",
"intensity": "强度",
"label": "HDRI环境",
"removeFile": "移除HDRI",
"showAsBackground": "作为背景显示",
"uploadFile": "上传HDRI.hdr, .exr"
},
"light": "灯光",
"lightIntensity": "光照强度",
"loadingBackgroundImage": "正在加载背景图像",
"loadingHDRI": "正在加载HDRI...",
"loadingModel": "正在加载3D模型...",
"materialMode": "材质模式",
"materialModes": {
@@ -3443,6 +3452,7 @@
"failedToInitiateCreditPurchase": "发起积分购买失败:{error}",
"failedToInitiateSubscription": "订阅启动失败:{error}",
"failedToLoadBackgroundImage": "无法加载背景图片",
"failedToLoadHDRI": "HDRI文件加载失败",
"failedToLoadModel": "无法加载3D模型",
"failedToPurchaseCredits": "购买积分失败:{error}",
"failedToQueue": "排队失败",
@@ -3478,6 +3488,7 @@
"pleaseSelectOutputNodes": "请选择输出节点",
"unableToGetModelFilePath": "无法获取模型文件路径",
"unauthorizedDomain": "您的域名 {domain} 未被授权使用此服务。请联系 {email} 将您的域名添加到白名单。",
"unsupportedHDRIFormat": "不支持的文件格式。请上传.hdr或.exr文件。",
"updateRequested": "已请求更新",
"useApiKeyTip": "提示:无法正常登录?请使用 Comfy API Key 选项。",
"userNotAuthenticated": "用户未认证"

View File

@@ -4,7 +4,6 @@ import Popover from 'primevue/popover'
import { computed, ref, useTemplateRef } from 'vue'
import { useI18n } from 'vue-i18n'
import { useTransformCompatOverlayProps } from '@/composables/useTransformCompatOverlayProps'
import { useToastStore } from '@/platform/updates/common/toastStore'
import type {
@@ -51,7 +50,6 @@ interface Props {
}
const { t } = useI18n()
const overlayProps = useTransformCompatOverlayProps()
const {
placeholder,
@@ -211,7 +209,6 @@ function handleSelection(item: FormDropdownItem, index: number) {
ref="popoverRef"
:dismissable="true"
:close-on-escape="true"
:append-to="overlayProps.appendTo"
unstyled
:pt="{
root: {

View File

@@ -4,7 +4,6 @@ import { ref, useTemplateRef } from 'vue'
import { useI18n } from 'vue-i18n'
import Button from '@/components/ui/button/Button.vue'
import { useTransformCompatOverlayProps } from '@/composables/useTransformCompatOverlayProps'
import type {
FilterOption,
OwnershipFilterOption,
@@ -16,7 +15,6 @@ import FormSearchInput from '../FormSearchInput.vue'
import type { LayoutMode, SortOption } from './types'
const { t } = useI18n()
const overlayProps = useTransformCompatOverlayProps()
defineProps<{
sortOptions: SortOption[]
@@ -135,7 +133,6 @@ function toggleBaseModelSelection(item: FilterOption) {
ref="sortPopoverRef"
:dismissable="true"
:close-on-escape="true"
:append-to="overlayProps.appendTo"
unstyled
:pt="{
root: {
@@ -198,7 +195,6 @@ function toggleBaseModelSelection(item: FilterOption) {
ref="ownershipPopoverRef"
:dismissable="true"
:close-on-escape="true"
:append-to="overlayProps.appendTo"
unstyled
:pt="{
root: {
@@ -261,7 +257,6 @@ function toggleBaseModelSelection(item: FilterOption) {
ref="baseModelPopoverRef"
:dismissable="true"
:close-on-escape="true"
:append-to="overlayProps.appendTo"
unstyled
:pt="{
root: {

View File

@@ -7,12 +7,21 @@ import { useMissingNodesErrorStore } from '@/platform/nodeReplacement/missingNod
import { executionIdToNodeLocatorId } from '@/utils/graphTraversalUtil'
// Create mock functions that will be shared
const mockNodeExecutionIdToNodeLocatorId = vi.fn()
const mockNodeIdToNodeLocatorId = vi.fn()
const mockNodeLocatorIdToNodeExecutionId = vi.fn()
const {
mockNodeExecutionIdToNodeLocatorId,
mockNodeIdToNodeLocatorId,
mockNodeLocatorIdToNodeExecutionId,
mockShowTextPreview
} = vi.hoisted(() => ({
mockNodeExecutionIdToNodeLocatorId: vi.fn(),
mockNodeIdToNodeLocatorId: vi.fn(),
mockNodeLocatorIdToNodeExecutionId: vi.fn(),
mockShowTextPreview: vi.fn()
}))
import type * as WorkflowStoreModule from '@/platform/workflow/management/stores/workflowStore'
import type { NodeProgressState } from '@/schemas/apiSchema'
import type { LGraphCanvas } from '@/lib/litegraph/src/LGraphCanvas'
import { createMockLGraphNode } from '@/utils/__tests__/litegraphTestUtils'
import { createTestingPinia } from '@pinia/testing'
@@ -38,7 +47,7 @@ declare global {
vi.mock('@/composables/node/useNodeProgressText', () => ({
useNodeProgressText: () => ({
showTextPreview: vi.fn()
showTextPreview: mockShowTextPreview
})
}))
@@ -431,6 +440,56 @@ describe('useExecutionStore - reconcileInitializingJobs', () => {
})
})
describe('useExecutionStore - progress_text startup guard', () => {
let store: ReturnType<typeof useExecutionStore>
function fireProgressText(detail: {
nodeId: string
text: string
prompt_id?: string
}) {
const handler = apiEventHandlers.get('progress_text')
if (!handler) throw new Error('progress_text handler not bound')
handler(new CustomEvent('progress_text', { detail }))
}
beforeEach(() => {
vi.clearAllMocks()
apiEventHandlers.clear()
setActivePinia(createTestingPinia({ stubActions: false }))
store = useExecutionStore()
store.bindExecutionEvents()
})
it('should ignore progress_text before the canvas is initialized', async () => {
const { useCanvasStore } =
await import('@/renderer/core/canvas/canvasStore')
useCanvasStore().canvas = null
expect(() =>
fireProgressText({
nodeId: '1',
text: 'warming up'
})
).not.toThrow()
expect(mockShowTextPreview).not.toHaveBeenCalled()
})
it('should call showTextPreview when canvas is available', async () => {
const mockNode = createMockLGraphNode({ id: 1 })
const { useCanvasStore } =
await import('@/renderer/core/canvas/canvasStore')
useCanvasStore().canvas = {
graph: { getNodeById: vi.fn(() => mockNode) }
} as unknown as LGraphCanvas
fireProgressText({ nodeId: '1', text: 'warming up' })
expect(mockShowTextPreview).toHaveBeenCalledWith(mockNode, 'warming up')
})
})
describe('useExecutionErrorStore - Node Error Lookups', () => {
let store: ReturnType<typeof useExecutionErrorStore>

View File

@@ -527,7 +527,7 @@ export const useExecutionStore = defineStore('execution', () => {
// Handle execution node IDs for subgraphs
const currentId = getNodeIdIfExecuting(nodeId)
if (!currentId) return
const node = canvasStore.getCanvas().graph?.getNodeById(currentId)
const node = canvasStore.canvas?.graph?.getNodeById(currentId)
if (!node) return
useNodeProgressText().showTextPreview(node, text)