Commit Graph

32 Commits

Author SHA1 Message Date
Ethanfel a37dd82ae3 fix: parse file list API response format correctly
API returns {"files": [{"name": "...", "data_type": "..."}]}, not a
plain array. Extract file names from the nested structure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 11:26:39 +01:00
Ethanfel 3b11a4e974 feat: file_name combo on ProjectSource, sequence_number output
- file_name is now a combo dropdown populated from the API when
  manager_url and project_name are set
- ProjectSource outputs sequence_number (INT) for downstream use
- Refreshes file list when project_name or manager_url changes
- Updated tests for new output and error-default behavior

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 11:20:41 +01:00
Ethanfel 5eb82f8ff6 fix: preserve saved combo value across load-order race
When ProjectKey configures before ProjectSource, _getSourceLabels
returns empty. replaceWithCombo now always keeps the saved value in
the options list so it survives the race condition.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 22:24:17 +01:00
Ethanfel bf598ebf80 fix: make key_name selection sticky, never auto-reset
The key_name combo now only updates its dropdown options from the API
but never changes the user's selected value. Only the output value
refreshes on execution.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 21:01:03 +01:00
Ethanfel 6e232da193 fix: remove _refreshKeys from onMouseDown to prevent key reset
The async _refreshKeys call on every mouse click caused a race condition
where clicking the key_name dropdown would trigger a re-fetch that
overwrote the user's selection. Keys are now only refreshed on source
label change and workflow load.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 21:00:19 +01:00
Ethanfel ff5802ab63 fix: don't crash on 404, add sync debug logging
ProjectKey.fetch_key now returns empty defaults instead of raising
RuntimeError on API errors. Added logging to _syncFromSource and
fetch_key to trace the seq=4001 vs seq=4 mismatch.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 20:58:42 +01:00
Ethanfel 413e1c09e9 fix: ProjectKey pulls fresh data on click, add debug logging
ProjectKey onMouseDown now triggers _syncFromSource + _refreshKeys so
clicking a relay always picks up source config changes. Added console
logs to notifyRelays and _refreshKeys for diagnosing sync issues.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 20:46:50 +01:00
Ethanfel 3dc91319a2 fix: notify relay nodes when source config changes
When ProjectSource widgets (url, project, file, sequence_number)
change, all ProjectKey nodes referencing that source now re-sync
and refresh their key dropdown immediately.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 12:43:05 +01:00
Ethanfel bd36b4b725 fix: prevent undefined in combo widgets with empty values
Combo widgets show "undefined" when values list is empty. Now ensures
at least one entry (empty string placeholder) and picks a valid default.
Also populates source labels immediately on node creation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 15:34:01 +01:00
Ethanfel 77eb3473ab fix: properly hide INT widgets and create real combo dropdowns
- INT widgets (sequence_number) now properly hidden using origType +
  hidden flag pattern from fast_saver.js
- source_label and key_name are now replaced with real combo widgets
  via addWidget("combo") instead of just setting type="combo" on
  STRING widgets, which didn't produce working dropdowns

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 15:27:52 +01:00
Ethanfel 545b864c08 feat: add ProjectKey JS extension with source/key dropdowns
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 11:39:48 +01:00
Ethanfel ad6cd76b08 feat: add ProjectSource JS extension with label title sync
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 11:36:29 +01:00
Ethanfel 1b8d13f7c4 Fix 7 bugs: bounds checks, deepcopy, time import, JS keys, unused import
- Add bounds check on src_batch index in add_from_source and copy_source
- Guard delete callback against stale index after rapid clicks
- Replace __import__('time').time() with time.time() in sync_to_db
- Use deepcopy(DEFAULTS) consistently in utils.py and main.py
- Use JSON.stringify in JS onConfigure fallback path for key storage
- Read state.show_comfy_monitor for checkbox initial value
- Remove unused KEY_BATCH_DATA import from tab_projects_ng

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 20:41:00 +01:00
Ethanfel 497e6b06fb Fix 7 bugs: async proxies, mode default, JS key serialization, validation
- Use asyncio.to_thread for proxy endpoints to avoid blocking event loop
- Add mode to DEFAULTS so it doesn't silently insert 0
- Use JSON serialization for keys in project_dynamic.js (with comma fallback)
- Validate path exists in change_path, friendly error on duplicate rename
- Remove unused exp param from rename closure
- Use deepcopy for DEFAULTS consistently

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 20:29:24 +01:00
Ethanfel dc8f44f02b Add refresh input to ProjectLoaderDynamic to force re-fetch
Changing the refresh value triggers the node to re-fetch keys from
the API, picking up any new or modified fields in the data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 14:27:51 +01:00
Ethanfel 187b85b054 Clean up: remove unnecessary info.outputs logic, set label on reused slots
The actual fix was setting slot.label alongside slot.name. Reverted
onConfigure to read from widget values (which work correctly) and
ensured label is set on both new and reused output slots.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 00:12:30 +01:00
Ethanfel a0d8cb8bbf Fix: set output label alongside name for LiteGraph rendering
LiteGraph renders slot.label over slot.name — we were updating name
but the display uses label.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 00:10:50 +01:00
Ethanfel d55b3198e8 Fix output names not surviving page refresh in ProjectLoaderDynamic
Read output names from info.outputs (serialized node data) instead of
hidden widget values, which ComfyUI may not persist across reloads.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 23:43:34 +01:00
Ethanfel bf2fca53e0 Remove JSONLoaderDynamic, handled by ComfyUI-JSON-Dynamic extension
The separate ComfyUI-JSON-Dynamic extension provides the same node.
Removes json_loader.py, web/json_dynamic.js, and their tests. Only
ProjectLoaderDynamic remains in this extension.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 23:18:39 +01:00
Ethanfel 5b71d1b276 Fix output name persistence: use comma-separated like reference impl
JSON.stringify format for hidden widget values didn't survive ComfyUI's
serialization round-trip. Switch to comma-separated strings matching
the proven ComfyUI-JSON-Dynamic implementation. Remove properties-based
approach in favor of the simpler, working pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 23:11:04 +01:00
Ethanfel 027ef8e78a Fix ProjectLoaderDynamic output names lost on page reload
Hidden widget values for output_keys/output_types were not reliably
restored by ComfyUI on workflow reload. Store keys/types in
node.properties (always persisted by LiteGraph) as primary storage,
with hidden widgets as fallback.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 23:04:14 +01:00
Ethanfel 4b5fff5c6e Improve ProjectLoaderDynamic UX: single node, error feedback, auto-refresh
Remove 3 redundant hardcoded nodes (Standard/VACE/LoRA), keeping only the
Dynamic node. Add total_sequences INT output (slot 0) for loop counting.
Add structured error handling: _fetch_json returns typed error dicts,
load_dynamic raises RuntimeError with descriptive messages, JS shows
red border/title on errors. Add 500ms debounced auto-refresh on widget
changes. Add 404s for missing project/file in API endpoints.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:16:08 +01:00
Ethanfel c4d107206f Fix 4 bugs from third code review
- Fix delete_proj not persisting cleared current_project to config:
  page reload after deleting active project restored deleted name,
  silently breaking all DB sync
- Fix sync_to_db crash on non-dict batch_data items: add isinstance
  guard matching import_json_file
- Fix output_types ignored in load_dynamic: parse declared types and
  use to_int()/to_float() to coerce values, so downstream ComfyUI
  nodes receive correct types even when API returns strings
- Fix backward-compat comma-split for types not trimming whitespace:
  legacy workflows with "STRING, INT" got types " INT" breaking
  ComfyUI connection type-matching

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 21:38:37 +01:00
Ethanfel b499eb4dfd Fix 8 bugs from second code review
HIGH:
- Fix JS TypeError on empty API response: validate keys/types are arrays
  before using them; add HTTP status check (resp.ok)
- Fix BEGIN IMMEDIATE conflict: set isolation_level=None (autocommit) on
  SQLite connection so explicit transactions work without implicit ones

MEDIUM:
- Fix import_json_file non-atomic: wrap entire operation in BEGIN/COMMIT
  with ROLLBACK on error — no more partial imports
- Fix crash on non-dict batch_data items: skip non-dict elements
- Fix comma-in-key corruption: store keys/types as JSON arrays in hidden
  widgets instead of comma-delimited strings (backward-compat fallback)
- Fix blocking I/O in API routes: change async def to def so FastAPI
  auto-threads the synchronous SQLite calls

LOW:
- Fix missing ?. on app.graph.setDirtyCanvas in refreshDynamicOutputs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 21:32:35 +01:00
Ethanfel 6b7e9ea682 Port dynamic node improvements from ComfyUI-JSON-Dynamic
- Deferred output cleanup (_configured flag + queueMicrotask) to prevent
  breaking links when other nodes (e.g. Kijai Set/Get) resolve outputs
  during graph loading
- file_not_found error handling in refresh to keep existing outputs intact
- Fallback widget sync in onConfigure when widget values are empty but
  serialized outputs exist

Applied to both json_dynamic.js and project_dynamic.js.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 21:15:56 +01:00
Ethanfel c15bec98ce Add SQLite project database + ComfyUI connector nodes
- db.py: ProjectDB class with SQLite schema (projects, data_files,
  sequences, history_trees), WAL mode, CRUD, import, and query helpers
- api_routes.py: REST API endpoints on NiceGUI/FastAPI for ComfyUI
  to query project data over the network
- project_loader.py: ComfyUI nodes (ProjectLoaderDynamic, Standard,
  VACE, LoRA) that fetch data from NiceGUI REST API via HTTP
- web/project_dynamic.js: Frontend JS for dynamic project loader node
- tab_projects_ng.py: Projects management tab in NiceGUI UI
- state.py: Added db, current_project, db_enabled fields
- main.py: DB init, API route registration, projects tab
- utils.py: sync_to_db() dual-write helper
- tab_batch_ng.py, tab_raw_ng.py, tab_timeline_ng.py: dual-write
  sync calls after save_json when project DB is enabled
- __init__.py: Merged project node class mappings
- tests/test_db.py: 30 tests for database layer
- tests/test_project_loader.py: 17 tests for ComfyUI connector nodes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 21:12:05 +01:00
Ethanfel a747f86daa Persist output types across save/load via hidden output_types widget
Types were lost on workflow reload because only key names were stored.
Now both keys and types are saved in hidden widgets and restored by
onConfigure, so colored connector dots persist without needing Refresh.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 16:16:50 +01:00
Ethanfel f5e242950d Auto-detect output types (INT, FLOAT, STRING) on dynamic node refresh
API route now returns types alongside keys. JS sets output slot type
accordingly, giving correct colored dots and type-safe connections.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 16:11:30 +01:00
Ethanfel a08f2676f5 Fix tall node on creation by resizing after removing default outputs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 16:01:01 +01:00
Ethanfel 3255fe76dc Preserve connections on Refresh when keys are added or reordered
Diff new keys against existing outputs instead of remove-all/add-all.
Reuses slot objects for matching key names so links stay connected.
Only disconnects links on keys that were actually removed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 16:00:16 +01:00
Ethanfel 0d44944192 Fix dynamic node outputs using LiteGraph removeOutput/addOutput API
Direct array manipulation bypassed LiteGraph's internal slot tracking,
causing output names to show as defaults instead of JSON key names.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 15:57:06 +01:00
Ethanfel e841e9b76b Add JSONLoaderDynamic node with JS frontend for auto-discovered outputs
Dynamic node reads JSON keys and exposes them as outputs automatically
via 32 AnyType slots managed by a JS extension (show/hide/rename).
Includes /json_manager/get_keys API route, bool-safe type handling,
and workflow save/reload support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 15:47:22 +01:00