A bucket file that parsed as a JSON array or other non-object was treated
as empty and then overwritten on the next save, so the previous contents
were gone. Those files are now moved aside like invalid JSON. A backup
created in the same second no longer replaces an existing one.
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: AE <by-ae@users.noreply.github.com>
The per-bucket lock was inserted without synchronization. Two first
writers could take different locks and overwrite each other's preset
file. Lock creation now happens under a guard lock.
Co-authored-by: AE <by-ae@users.noreply.github.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
- Allow Unicode letters/numbers in preset names (e.g. 角色, Персонаж, Émilie)
- Add thread-safe locking per bucket to prevent race conditions during concurrent writes
- Use mkstemp() for atomic temp file creation to avoid tmp file name collisions
- Add tests demonstrating the bugs and verifying the fixes
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
- Add error handling for JSONDecodeError and UnicodeDecodeError in _read_json
- Move corrupt files to timestamped backup (e.g. characters.json.corrupt-1234567890)
- Treat corrupt bucket as empty, allowing other buckets to continue working
- Clean up temp files if _write_json fails
- Log warnings for corrupt file recovery and errors for backup failures
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Ensures data is written to disk before the atomic rename. The write
was already atomic (tmp + os.replace), but adding fsync prevents
preset corruption if the process is killed between json.dump and
the file system sync.
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Fork of KJNodes' Ideogram 4 Prompt Builder with stores, multi-select, scene save/load, live background preview, and separate width/height outputs.
Co-authored-by: Cursor <cursoragent@cursor.com>