- Watcher: a sidecar JSON created or edited next to an unchanged media
file now invalidates that file's metadata cache and scan journal and
forces a re-extraction; a non-incremental re-index no longer skips
assets that already have a metadata row when the cache was cleared.
- Merge index rows that are one file under different Windows path
spellings at startup, keeping the best rating, all tags, the stack
cover, execution ids and the vector embedding.
- Remove deleted/removed assets from the generated feed too.
- Scope the floating viewer's single-letter shortcuts to the viewer
(pointer, focus or pop-out) instead of the whole page.
- Take LGraph/LGraphCanvas types from comfyui-frontend-types and drop
@comfyorg/litegraph; delete five dead frontend files.
- Fix an order-dependent test that leaked an input-directory override.
- Search: tokens were filtered down to nothing for inputs like "at-7",
"(2)", "AND", a single letter or a lone quote, producing an empty FTS
MATCH and "Invalid search query syntax". Fall back to the raw words,
treat punctuation-only input as browse-all, keep non-Latin scripts and
fold accents on Latin letters only (as FTS5 unicode61 does).
- Sidecar JSON (<file>.<ext>.json, then <stem>.json) now supplies the
workflow/prompt/generation data of images, videos and audio when none
is embedded; shared with the 3D extractor; BOM tolerated.
- Workflow tab: skip hidden folders (.history version snapshots were
listed as workflows), only list UI exports, API prompts and wrappers,
read with utf-8-sig, drop invalid JSON from the index (version 5),
and load API-format workflows with app.loadApiJson.
- Floating viewer: release (not just pause) videos before re-rendering
and on dispose, so Live mode no longer accumulates media players.
- Clicking a duplicate-stack badge could freeze ComfyUI: displayAssets,
the per-card ref callback (syncRenderedDuplicateCards) and the live
upsert dedupe each rewrote _mjrDupStack/_mjrDupMembers on reactive
assets read by the grid template, with a new array every pass and
conflicting representatives. The ref callback ran on every render, so
each write scheduled another render (no recursion limit in prod Vue).
- Compute duplicate stacks only in buildDisplayAssets with change-guarded
writes and stable member arrays; keep one ref callback per card; stop
the other passes from touching duplicate fields.
- A duplicate is now the same name in the same source/root/subfolder:
files sharing a name in different folders are no longer stacked,
hidden from the grid or given another file's generation time.
- The duplicates view lists every copy using cycle-free member copies.
- Add regression tests (render-loop idempotence, folder scoping).
- Fix assets_fts triggers: the external-content FTS5 table was updated
with plain UPDATE/DELETE, so every rename or move failed with
"database disk image is malformed" and the watcher fell back to
delete + re-index, losing ratings, tags and collections. Use the FTS5
'delete' command, limit the update trigger to filename/subfolder and
repair existing databases (plus an FTS rebuild) at startup.
- Wait for the prompt history entry before post-execution ingestion:
ComfyUI fires on_prompt_end before task_done() stores history, so
outputs of prompts queued from the API or another client could be
missed.
- Scan prune only removes assets whose absence is confirmed; a stat
error or an unreadable scan root no longer deletes user data. Report
pruned assets instead of SQLite change counts.
- Emit mjr-assets-removed for watcher deletes and scan prunes and
mjr-asset-updated for moves so open grids update in place.
- Annotate mjr-scan-complete with origin and needs_refresh; reload the
grid once when live events cannot cover a change and summarise a
finished directory scan in one ComfyUI core toast.
- Document the comparison with ComfyUI core's asset system.
- Use the typed ToastManager API (success/error/info/warning/loading)
instead of the deprecated add(); add() stays as a fallback for older
frontends.
- Accept a toast manager without add() so toasts keep working once
ComfyUI drops the deprecated methods.
- Tracked operations (DB restore/reset, vector backfill) show one
loading toast updated in place via its ToastId instead of stacking a
toast per step; dismiss them on extension teardown.
- Persistent toasts use the largest safe timer delay instead of
Infinity; history action links become native toast action buttons
(http(s) or same-origin paths only).
- Route genInfoOverridePicker and comfyAlert through the core toast API;
drop the app.ui.toast fallback, the no-op fallback dismisser and the
unused .mjr-toast CSS.
- Keep the Majoor message center as a read-only history; it no longer
pops open by itself on reset/backfill.
- Document the notification audit.
- Move the read-only OpenAPI compat surface from /api/v2/assets to
/mjr/am/compat/assets so it never squats ComfyUI core's /api namespace;
the legacy alias is opt-in via MJR_AM_LEGACY_API_V2_ASSETS=1.
- Allow Python 3.14 (requires-python <3.15) and add 3.14 to CI and tox.
- Stop wrapping api.queuePrompt: progress tracking now resolves the
running prompt from the core Jobs API (getJobDetail), then /queue and
/history, driven by websocket events. Remove wrapHostQueuePrompt.
- Add opt-in Majoor.Integration.HideNativeAssetsTab setting that hides
ComfyUI's native Assets sidebar tab through the official
getSidebarTabs/unregisterSidebarTab API and restores it when disabled.
- Fix all 913 type errors in tsconfig.test.json and type-check tests in
CI; drop a duplicated `stubs` key in asset_card_inner test; make
addToastHistory's type argument optional for the object form.
- Update audit report, changelog, API reference and env var docs.
- hostAdapter: serialize the root graph instead of calling the now-async
graphToPrompt() synchronously (avoids exporting only the open subgraph
and an unhandled rejection); read dirty state from the workflow store.
- Bump @comfyorg/comfyui-frontend-types to ^1.60.0: 1.57.3 was published
without index.d.ts, so the official ComfyApp type was silently lost.
- Backend: typed aiohttp request keys (web.RequestKey when available)
to silence NotAppKeyWarning on aiohttp >= 3.13 and avoid key clashes.
- Fix ruff import-order failures; rebuild dist bundle.
- Add docs/COMFYUI_INTEGRATION_AUDIT.md with remaining conflict risks
and an integration roadmap.
Save Image gains format, input_color_space and crf options backed by the core Save Image (Advanced) encoders. Save Video gains mp4/mkv/webm with H.264 or AV1 and keeps the source bit depth and HDR colour space. Both nodes return their frames, and the video sidecar PNG now honours --disable-metadata.
The frontend called checkMajoorVersion() unconditionally on startup,
and the backend /mjr/am/releases endpoint made outbound requests to
api.github.com to power it. This violates the no-internet-requests
policy for core ComfyUI code, even for update checks framed as
diagnostic or opt-out. Removes the endpoint, the frontend check, the
now-dead version-update badge dot in HeaderSection.vue, and associated
tests/docs.
The unanchored `tools/` pattern matched that directory at any depth,
stripping the ExifTool/FFProbe adapters out of published packages and
causing ModuleNotFoundError at startup. Anchored to /tools/ so only
the root-level dev-scripts folder is excluded. Bump to 2.5.3.
Exclude development-only content from Registry packages while retaining runtime
docs and vendor assets. Centralize environment access and media process execution,
validate filesystem inputs, and restrict nested media protocols.
Route update checks through the backend GitHub boundary and read version metadata
without spawning Git. Preserve annotated-tag priority over lightweight nightly
tags, including packed refs, with regression coverage. Rebuild the frontend bundle.
Validation: Python tests with coverage, JS tests, targeted media/version regression
tests, and the canonical Python quality gate.
Docs:
- Fix stale version/date banner in docs/DOCUMENTATION_INDEX.md (2.4.9 -> 2.5.1)
- Normalize CHANGELOG.md section headers to plain text (strip inconsistent
emoji prefixes used in older entries)
- Add missing diacritics in French command labels (locales/fr/commands.json)
- Add ToC anchors for nested Installation subsections in README.md
Backend:
- Document the comfy_entrypoint() wrapper's rationale in __init__.py
Frontend:
- Wire tsconfig.strict.json into an actual npm script (typecheck:js:strict,
now part of quality:strict) instead of leaving it dead/unenforced
- Fix the 8 strict-mode type errors this surfaced across
comfyWorkflowParser.ts, canvasLoaderNode.ts, FloatingViewer.impl.ts and
workflowGraphMapActions.ts
- Rebuild dist/ to match source
Deferred (too large/risky to blind-fix in this pass):
- ui/vue/** ESLint+Vue+TS linting: typescript-eslint currently has no
compatible release for this repo's typescript@7.0.2, so adding
eslint-plugin-vue/typescript-eslint is blocked upstream
- Converting all 44 .vue SFCs to lang="ts" with typed defineProps
- Eliminating the ~230 any/as any occurrences under ui/vue
- Auditing/reducing the ~1082 except Exception: blocks repo-wide
- Default 'Show folders in Input / Output panels' (browser.showFolders) to
disabled: fresh installs keep the classic flat grid until the user opts in
(backend settings service, frontend defaults, settings UI toggle).
- Gate the root-level 'Create folder here' context menu on the setting.
- Kick off a throttled incremental background scan when browse mode serves
the first page, so unindexed files get indexed/enriched and asset status
dots resolve instead of staying pending (blue).
- Document the feature and setting in README, CHANGELOG, and
docs/SETTINGS_CONFIGURATION.md.
- ImageOps preview bridge: stream cropped contain-fit rect of __imageops_state.canvas (removes square scope/letterbox); fall back to full canvas when user pan/zoom is active. Signature-cached encode (WeakMap) avoids re-encoding on every poll tick.
- Floating viewer: skip metadata enrichment for imageops-live-preview source; preserve user pan/zoom across stream frames of the same node; remove inline CSS overrides that blocked the MFV transform.
- Workflow Nodes panel: graph-selected node is auto-expanded, promoted to first position in its container, scrolled into view, and gets a subtle blue highlight (is-selected-from-graph).
Remove PLAN_REFACTO_COMPLET, PLAN_REFACTO_V2_LONG_TERME, and VUE_MIGRATION_PLAN
as they are internal development artifacts not relevant to end users.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- nodes.py: MajoorSaveImage (PNG with generation_time_ms in text chunks) and MajoorSaveVideo (MP4 via PyAV, GIF, WebP with metadata persistence)
- extractors_png.py: read generation_time_ms from PNG text chunks
- extractors.py: extract generation_time_ms from merged EXIF data into metadata dict
- extractors_video.py: extract generation_time_ms from ffprobe format tags
- messageCenter.js: add generation-time-persistence tip and topbar MFV button announcement
- CHANGELOG.md: document topbar MFV button and custom nodes
- README.md: add Custom Nodes section with input tables
- docs/CUSTOM_NODES.md: full node reference and extraction pipeline docs
- docs/DOCUMENTATION_INDEX.md: add CUSTOM_NODES.md entry
- FloatingViewer.impl.js: add missing _resetMfvZoom() method (was called
from floatingViewerLoader/Mode but never defined on the class)
- viewerShell.js: return genInfoTitle + genInfoTitleLeft from createViewerStageShell
- ViewerRuntime.js: destructure genInfoTitle + genInfoTitleLeft (were undefined
=> gen info body was never populated)
- floatingViewerPopout.js: inject document.documentElement.style.cssText as
:root{...} in popup head so ComfyUI CSS vars are available; set body
background to #0d0d0d; remove broken history.replaceState (Chrome blocks
it from about:blank)
- __init__.py: remove unused FailureSeverity/StageStatus imports
- Hook canvas.onNodeDeselected (was missing) so sidebar clears when
deselecting all nodes (click on empty canvas)
- Add DOM-level pointerup listener on canvas.canvas as fallback for
ComfyUI selection paths that bypass LiteGraph callbacks
- Add requestAnimationFrame retry in open() if canvas is null at call time
- Write widget values in real-time on input event (number + textarea)
instead of only on change/blur; partial states (-/./empty) are skipped
for number inputs; blur still clamps and syncs displayed value
- Multi-Pin references: toggle buttons A/B/C/D to pin up to 4 images
- Node Parameters sidebar: view/edit workflow node widgets inside MFV
- Run button in viewer toolbar for immediate re-queue
- Expandable text areas for long prompts
- Sidebar position setting (right/left/bottom) via Settings
- Toolbar layout: Run and Node Parameters pushed to far right
- Message Center: 2 new announcements for the features
- Docs: VIEWER_FEATURE_TUTORIAL, FLOATING_VIEWER_WORKFLOW_SIDEBAR
- CHANGELOG v2.4.5, README aligned