With an unreachable LLM endpoint the Review-prompt modal fired duplicate
long-hanging requests and left Generate impossible. Preview resolves now
fire exactly once per scene, the H3 rewrite times out after 30s and falls
back to the deterministic template, and on failure the modal populates the
editor with raw scene text so the user can edit + Generate or retry.
The old 2.20.x range carried high-severity npm audit advisories
(CSRF, dev-mode 404 XSS, handle-hook DoS), which pushed users toward
npm audit fix --force — a command that downgrades kit to a 2021
pre-release and breaks the install (issue #38). Bumping within the
major plus the safe audit fixes leaves only 3 low-severity transitives,
all requiring major downgrades. Recovery steps for affected users are
in the changelog.
Issues #27/#33/#28. Generate now resolves the prompt first (saved draft
or H3 rewrite) and opens an editable review modal before enqueueing;
job history drawer shows each render's exact payload with copy-to-form.
ComfyUI 400s surface error.type + per-node messages; audio uploads go
flat and VHS audio: widgets are patched. Per-scene video settings
persist via scenes.video_settings_json (additive migration) and batch
generate honors them. Version bumped to 1.3.0.
The native select was too cramped for a project with many clips. Replace
it with a wide modal (Auto / Upload file / clip grid with thumbnails).
Clip options now cover any scene in the timeline, not just earlier ones,
and uploads wire through a hidden input. Also fix the Choose-Video modal
rendering blank under Clips/Uploads tabs: duplicate asset paths crashed
Svelte's keyed each mid-render — dedupe by path and clamp the active tab
when a tile's kind changes.
With preload="metadata" browsers paint NOTHING until playback, so the Video
tab's hero monitor and every filmstrip thumbnail sat black — clips looked
missing while their audio played fine ('no picture, but sound'). The media
fragment makes the browser seek and paint the frame at 0.1 s without playing.
Verified in-browser: fresh load paints hero + all thumbnails; selecting a
scene paints its first frame immediately.
(cherry picked from commit a81280b1543b9f6aa913be8373f0a390d3db5871)
Some exceptions stringify EMPTY (httpx.ReadTimeout/ReadError, TimeoutError):
a sub-agent killed mid-stream by a backend restart reported 'Sub-agent
failed: ' with nothing after the colon, and no traceback was logged anywhere
(observed live 2026-08-25). The handler now logger.exception()s and formats
'Type: message' (or bare 'Type' when the message is empty).
(cherry picked from commit ff138a9a01a93714dc6d8d2bce3ee57ace03647d)
The destructive guard only gated replace=true — an unconfirmed
generate_story(replace=false) on a non-empty project silently APPENDED a
duplicate 25-beat set (25 -> 50, observed live 2026-08-25), and the guard's
own message recommended exactly that escape. Both modes are now gated on a
non-empty project with mode-specific messages that point at the granular
tools; 'append' joins the confirmation cues.
And the granular tools now exist for beats: add_beat (insert-with-shift, or
append when order_index omitted), update_beat (project-scoped id check),
delete_beat (destructive-flagged; later beats renumber to close the gap) —
before this, bulk regeneration was the only way to change a beat, which is
what boxed the story sub-agent into the append in the first place. The story
role's allowlist gains all three.
(cherry picked from commit 14ca52f5c02d1e8dd52e0f58e5fd0b8593816c9b)
On a large project (43 scenes with full action paragraphs) get_workspace
serializes past the 4000-char tool-result cap, so the tail-chop landed
mid-beats and characters/locations/items were ALWAYS below the waterline —
observed live: an assets sub-agent re-called get_workspace in a loop, blind
to the sections it needed, with no editor tools in its allowlist anyway.
- get_workspace gains sections=[beats|characters|locations|items|scenes];
project + stats always included; omitted sections listed; invalid sections
error names the valid set; no-arg call unchanged (back-compat).
- All three truncation sites share TRUNCATE_NOTE, which names the way out
(sections=[...], scoped tools) instead of a bare '[truncated]'.
- The assets role gains update_character / update_location / update_item
(deletes deliberately excluded).
(cherry picked from commit 9460b6c2e398bad5403ff73e4e8e7d2a96478821)
Once a session linked to a project, the agent could neither create a fresh
project (create_project is sandbox-only) nor switch (link_project is
sandbox-only) — and no unlink existed. Observed live: a linked agent burned
three failed tool calls and ~7 minutes of reasoning discovering the box, then
overwrote the linked project as its only option.
unlink_project (linked-only) clears the session binding and nothing else; the
blind_only rejection message now points to it, so the model recovers in one
step; link_project's description documents the switch path.
(cherry picked from commit f4fc7cde6461529177563d58383c5c50287026e1)
The packaged FastAPI static mount returned JSON 404 for /project/{id}. Serve the SvelteKit fallback page for client routes, and point README at source until a zip is trustworthy.
Extends the 1.2.1 Agent-loop fix to every LLM caller: with completions
streamed internally, the 120 s httpx timeout bounds the gap BETWEEN chunks
(liveness) instead of total generation time, so a thinking model that
streams reasoning_content can legitimately work past 120 s while a dead
server still fails fast. chat_stream gains response_format= with an
in-stream HTTP-400 drop-ladder (response_format first, then tools); servers
that reject stream:true entirely fall back to one plain blocking POST.
A reasoning-only stream (zero content accumulated) raises ValueError so
generate_structured's json_object retry fires instead of returning blank.