- 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>
- Remove unused `random` import and `KEY_PROMPT_HISTORY` from app.py
- Remove dead session state keys: edit_history_idx, append_prompt, rand_seed
- Clean up extra blank lines in json_loader.py
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
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>
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>
get_batch_item now searches for the item whose sequence_number field
matches the requested number, instead of using array position. Falls
back to index-based lookup for data without sequence_number fields.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- save_json() now writes to a temp file then uses os.replace() for atomic writes
- Replace hardcoded "batch_data", "history_tree", "prompt_history", "sequence_number"
strings with constants (KEY_BATCH_DATA, etc.) across all modules
- Add 29 unit tests for history_tree, utils, and json_loader
- Add type hints to public functions in utils.py, json_loader.py, history_tree.py
- Remove ALLOWED_BASE_DIR restriction that blocked navigating outside app CWD
- Fix path text input not updating on navigation by using session state key
- Add unpin button (❌) for removing pinned folders
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace bare except clauses with specific exceptions (JSONDecodeError, IOError, ValueError, TypeError)
- Add path traversal protection restricting navigation to ALLOWED_BASE_DIR
- Sanitize iframe URLs with scheme validation and html.escape to prevent XSS
- Extract duplicate to_float/to_int to module-level helpers in json_loader.py
- Replace silent modulo wrapping with clamped bounds checking via get_batch_item()
- Remove hardcoded IP 192.168.1.51:5800, default to empty string
- Add try/except around fragile batch history string parsing
- Add JSON schema validation (dict type check) in read_json_data()
- Add Python logging framework, replace print() calls
- Consolidate session state initialization into loop with defaults dict
- Guard streamlit_agraph import with try/except ImportError
- Add backup snapshot before history node deletion
- Add cycle detection in HistoryTree.commit()
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>