Commit Graph

276 Commits

Author SHA1 Message Date
calesthio
2d3ebfefd5 fix(backlot): no-cache header for UI pages and assets
The board is a long-lived SPA tab; browsers heuristically cache /ui
assets, so UI fixes did not show up on plain refresh. Cache-Control:
no-cache forces conditional revalidation (cheap ETag 304s) for /, /p/*,
and /ui/* while leaving media and thumbnail caching untouched.
2026-07-10 15:56:25 -07:00
calesthio
d3a8fcf3bc fix(backlot): keep storyboard beside decisions rail; portrait-aware render player
- Storyboard, found-media, and renders sections now render inside the main
  column instead of after the .board grid, so a tall decisions rail no longer
  pushes them below the fold (they flow beside the rail).
- Render hero player: preload=metadata so the video has its intrinsic aspect
  ratio (and a poster frame) before playback, and natural-width centering so
  a 9:16 render displays as a portrait frame instead of a letterboxed
  landscape box. Degraded (no-grid) view keeps the old full-width flow.
2026-07-10 15:27:44 -07:00
Calesthio
2ab5773ef7 Merge pull request #270 from kweinmeister/main
feat(tools): add Google Lyria and direct Google Veo generation tools
2026-07-09 07:36:45 -07:00
calesthio
ad02ce3639 fix(ci): stabilize character HyperFrames contract test 2026-07-09 07:32:21 -07:00
calesthio
505c0faaf5 fix(ci): install Google GenAI SDK 2026-07-09 07:16:01 -07:00
Karl Weinmeister
d3d77bcc30 docs: update PROVIDERS.md with google_music and veo_video capabilities 2026-07-09 07:13:23 -07:00
Karl Weinmeister
30018a6a8f feat(tools): add Google Lyria and direct Google Veo generation tools 2026-07-09 07:11:06 -07:00
Calesthio
1a76073505 Merge pull request #333 from calesthio/feat/gemini-omni-provider
feat(video): add Gemini Omni Flash provider with conversational editing
2026-07-09 07:02:39 -07:00
calesthio
2ef18e77a9 fix(video): normalize Gemini Omni file URIs; document provider in PROVIDERS.md
Review findings from PR #333:

P1: _download_via_uri assumed output_video.uri is always files/<id>.
The API can return a full resource URI or a ready-made
.../files/<id>:download?alt=media download URL, which produced an
invalid poll path with a second :download appended. New
_file_id_from_uri() extracts the bare id from every documented shape;
regression tests cover the full-URL form plus a parametrized matrix of
URI shapes.

P2: docs/PROVIDERS.md still described the Google key as TTS + Imagen
only. The shared-key section now covers gemini_omni_video (model id,
~$0.10/sec pricing table, paid-tier-only, edit-turn billing note), and
the env snippet, provider-to-tool mapping, and capability coverage
tables include the new provider.
2026-07-08 23:45:47 -07:00
calesthio
34d1053526 feat(video): add Gemini Omni Flash provider with conversational editing
Add gemini_omni_video, a native Gemini API provider wrapping
gemini-omni-flash-preview via the Interactions API. Text-to-video,
image/reference-to-video with <FIRST_FRAME>/<IMAGE_REF_N> prompt tags,
and stateful edit_video turns via previous_interaction_id — the only
provider in the fleet that can refine a clip without regenerating it.
Reuses the existing GOOGLE_API_KEY / GEMINI_API_KEY, so one Google key
now unlocks images, TTS, and video.

- New Layer 3 skill .agents/skills/gemini-omni (prompting, edit-loop
  rules, tag/timecode syntax, preview limits) sourced from official
  Google docs; linked via agent_skills and the AGENT_GUIDE Layer 3 map
- ai-video-gen gains the Gemini API gateway row + editing pointer
- veo_video/sora_video fallback lists and video_selector agent_skills
  reference the new provider; quality_score 0.85 with rationale
- Contract tests: registry discovery, selector routing, status from
  env keys, uri + inline delivery, edit turns, typed image parts,
  store=false editability, cost clamp
2026-07-08 11:00:57 -07:00
Calesthio
de348f15e3 Merge pull request #322 from calesthio/codex/fix-ci-requests-isolation
[codex] Fix CI requests module isolation
2026-07-06 22:49:53 -07:00
calesthio
015809c103 fix(ci): isolate requests module tests 2026-07-06 22:36:03 -07:00
Calesthio
9566c3488f Merge pull request #317 from ziyu4huang/fix/music-gen-force-instrumental
fix(music_gen): send force_instrumental per music-gen-usage mandate (§8 #8)
2026-07-06 21:47:32 -07:00
Calesthio
ecd43c9107 Merge pull request #316 from ziyu4huang/fix/env-example-drift
docs(env): add missing FAL_AI_API_KEY alias, REPLICATE_API_TOKEN, HIGGSFIELD credentials (§8 #11)
2026-07-06 21:43:26 -07:00
Calesthio
0c0780b00d Merge pull request #319 from ziyu4huang/fix/audio-mixer-loudnorm-target
fix(audio_mixer): parameterize loudnorm LUFS target (§8 #1)
2026-07-06 21:35:29 -07:00
Calesthio
ec8f1ba99b Merge pull request #318 from ziyu4huang/fix/grok-video-quality-score
fix(grok_video): set quality_score=0.9 to stop under-ranking (§8 #6)
2026-07-06 21:35:13 -07:00
Calesthio
5dcc364fca Merge pull request #321 from ziyu4huang/fix/cogvideo-2b-i2v-variant
fix(cogvideo_video): consult variant i2v flag instead of advertising it unconditionally (§8 #4)
2026-07-06 21:22:52 -07:00
Calesthio
0e69906e36 Merge pull request #320 from ziyu4huang/fix/video-selector-routing
fix(video_selector): dedup race + preferred-provider gap + motion-aware fallback (§8 #3,#5,#7,#10)
2026-07-06 21:22:38 -07:00
Calesthio
cadff79217 Merge pull request #263 from mojahurtowniapl/claude/distracted-morse-47198e
Clamp Pixabay per_page to API-required 3-200 range
2026-07-06 18:39:26 -07:00
Calesthio
796f5d7c6e Merge pull request #281 from scorp323/oracle/batch-b-safe-hardening-20260703
fix: harden tool governance and subprocess safety
2026-07-06 18:17:08 -07:00
Calesthio
f9f53ecbcf Merge pull request #286 from drainsmichael-tech/claude/eloquent-feistel-40f311
fix: check ffmpeg availability via shutil.which instead of hardcoding True
2026-07-06 17:59:42 -07:00
Ziyu Huang
dbc639f608 fix(music_gen): send force_instrumental per music-gen-usage mandate
skills/creative/music-gen-usage.md mandates 'Always set
force_instrumental=true for video background', but music_gen.py never
sent the kwarg, so ElevenLabs could return vocal tracks that collide
with narration/dialogue.

- Add force_instrumental to input_schema (default True) so the mandate
  holds by default; callers may opt out only with an explicit False.
- Include force_instrumental in the /v1/music payload.
- Add tests pinning: kwarg sent True by default, explicit opt-out
  honored, and the schema default.

Refs: docs/REVIEW-image-to-video-voice.md §8 #8

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-07 07:42:35 +08:00
Ziyu Huang
5cc144f232 fix(cogvideo_video): consult variant i2v flag instead of advertising it unconditionally
COGVIDEO_VARIANTS declares cogvideo-2b i2v=False (it is t2v-only), but
cogvideo_video advertised image_to_video + reference_image unconditionally
and the variant flag was never consulted. An image_to_video brief against
the 2B variant reached the diffusion pipeline and failed opaquely.

- Add is_operation_available(operation) that derives capability from the
  variant table (the selector calls it without inputs, so it reports the
  DEFAULT variant cogvideo-5b: t2v + i2v both True). This replaces an
  implicit unconditional-True.
- Add an execute()-time guard that consults the CALLER's chosen variant
  and fails fast with a clear error when it lacks the requested mode
  (2B + image_to_video), instead of dropping into generate_local_video.
- Add _variant_for(inputs) helper shared by estimate_runtime / the guard.

Tests pin: the 2B premise (i2v=False), default-variant capability
reporting, fast-fail for 2B+i2v (generation never runs), and that 5B+i2v
still routes through to generate_local_video.

Refs: docs/REVIEW-image-to-video-voice.md §8 #4

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-07 07:38:52 +08:00
Ziyu Huang
712a54bea9 fix(video_selector): dedup race + preferred-provider gap + motion-aware fallback
Three routing defects in video_selector, none previously covered by
tests (REVIEW §8 #3, #5, #7); plus the routing-test coverage itself (#10).

#3 Seedance dedup race
  tool_by_provider keyed by provider STRING, so two tools legitimately
  sharing provider="seedance" (seedance_video=fal, seedance_replicate)
  collided — only the first-registered was ever selectable; the other
  was invisible to the selector regardless of rank. Key selectable tools
  by NAME instead; ranking picks the best of the shared-provider backends.

#5 preferred_provider had no score-gap gate
  The selector returned the preferred provider on the first ranking match
  no matter how far below the top it scored (the comment claimed "unless
  drastically worse" but nothing enforced it). Add a configurable
  preferred_provider_gap (default 0.15): honor the preference only when
  its best ranked tool is within the gap of the overall top, else yield
  to the top-ranked provider.

#7 fallback_tools appended image_selector unconditionally
  The motion-required prohibition lived only in director skills, so a
  direct caller could silently fall back to an image-only tool for an
  image_to_video / reference_to_video brief. Add input-aware
  fallback_tools_for(inputs) that drops image_selector for
  motion-required operations; keep the static fallback_tools property
  (with image_selector) for external consumers / contracts.

#10 routing coverage
  First routing tests for video_selector: dedup reachability, the gap
  gate (honored / ignored / configurable), motion-aware fallback, and
  estimate_cost / estimate_runtime delegation. 13 tests, scoring patched
  for determinism so they test routing logic, not the scorer.

Full tools + contracts suite green (638 passed, 6 skipped).

Refs: docs/REVIEW-image-to-video-voice.md §8 #3, #5, #7, #10

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-07 07:36:59 +08:00
Ziyu Huang
0ab9779a04 fix(audio_mixer): parameterize loudnorm LUFS target
audio_mixer hard-coded loudnorm I=-16 (Apple Podcasts) in both _mix
and _full_mix. sound-design.md targets -14 for YouTube/TikTok/IG, and
edit_decisions.metadata.loudnorm_target is the declarative form — but
the mixer never read it, so the executed loudness silently defaulted
to podcast levels regardless of the target platform.

- Add loudnorm_target to input_schema (default -16, clamped to [-40, 0]).
- Extract _loudnorm_filter() helper and use it in _mix and _full_mix so
  a director can forward edit_decisions.metadata.loudnorm_target (or a
  caller can pass it directly) to hit the right platform target.
- Add tests pinning: default -16, -14 honored, out-of-range clamped,
  non-numeric fallback, and the schema default.

Refs: docs/REVIEW-image-to-video-voice.md §8 #1

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-07 07:32:44 +08:00
Ziyu Huang
6e10038d0e fix(grok_video): set quality_score=0.9 to stop under-ranking
Every premium video provider sets quality_score (seedance 0.95, runway /
higgsfield 0.9) so the scorer ranks them above stock/local options.
grok_video had none, so it was scored only on supports/stability flags
despite shipping native synchronized audio (lip-sync + dialogue + SFX
in a single generation pass) — likely under-ranked.

Set quality_score=0.9, on par with the other native-audio premium
providers. Add a regression pinning the field and its get_info() surface.

Refs: docs/REVIEW-image-to-video-voice.md §8 #6

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-07 07:31:33 +08:00
Ziyu Huang
14eccccb09 docs(env): add missing FAL_AI_API_KEY alias, REPLICATE_API_TOKEN, HIGGSFIELD credentials
The provider tools read these env vars but .env.example never listed
them, so a fresh setup silently misses them:

- FAL_AI_API_KEY — read by kling/minimax/veo/seedance/recraft/flux
  as an alias for FAL_KEY (os.environ.get('FAL_KEY') or FAL_AI_API_KEY),
  but only FAL_KEY was documented.
- REPLICATE_API_TOKEN — required by seedance_replicate; without it the
  Replicate-backed Seedance path stays unselectable.
- HIGGSFIELD_API_KEY / _API_SECRET / HIGGSFIELD_KEY — the three forms
  higgsfield_video.py accepts (combined key:secret vs split pair).

Doc-only, zero runtime change.

Refs: docs/REVIEW-image-to-video-voice.md §8 #11

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-07 07:29:28 +08:00
Calesthio
a2652b4c12 Merge pull request #312 from mandaar17/fix/wan22-t2v-vae-mismatch
fix(comfyui): T2V workflow pairs 14B models with the 5B VAE, breaking every run at VAEDecode
2026-07-06 12:06:37 -07:00
Calesthio
2df6d47884 Merge pull request #309 from 0xDevNinja/fix/image-multiout-and-segmented-music-volume
fix: openai_image returns all n images; segmented_music stops halving narration
2026-07-06 12:06:13 -07:00
0xDevNinja
4c10481011 fix(audio_mixer): stop segmented_music from halving narration volume
`_segmented_music` mixed the video's audio with the shaped music via
`amix=inputs=2`, whose default `normalize=1` scales every input by 1/inputs
(x0.5, -6 dB). Unlike `_mix` and `_full_mix`, this path has no `loudnorm` stage
afterward to re-normalize, so the narration was permanently attenuated across
the entire timeline — including the stretches where the music volume expression
evaluates to 0. A one-second music segment quietly dropped the narration by
~6 dB for the whole video.

Add `normalize=0` to the amix: the music is already scaled to `music_volume`
by the `volume` expression, so speech passes at unity. Verified with ffmpeg —
narration in a no-music region tracks the stereo/aac conversion baseline
instead of sitting 6 dB below it.
2026-07-06 13:12:33 +05:30
0xDevNinja
7fff88af3c fix(openai_image): return all n generated images, not just the first
The tool advertised `multiple_outputs: True`, accepted `n` (1-4) in its schema,
requested `n` images from the API, and scaled `estimate_cost` by `n` — but the
result handling was hardcoded to `response.data[0]`. Images 1..n-1 were decoded
never, written never, and absent from `artifacts`, so a caller who set `n=4`
paid for four images and received one.

Iterate over `response.data`, writing each image to a distinct path (suffixed
`_1`, `_2`, … when several are requested, mirroring `grok_image` /
`dashscope_image`), and return `outputs` / `images_generated` alongside the
full `artifacts` list. A single image keeps its exact requested path.
2026-07-06 13:12:33 +05:30
Calesthio
89d5f1f88b Merge pull request #293 from ketpatil77/codex/openmontage-wan22-vae
fix(comfyui): use 14B-compatible VAE for wan22 t2v
2026-07-05 11:04:27 -07:00
Calesthio
97c9ca1840 Merge pull request #255 from calesthio/codex/sora-dotenv-discovery
[codex] Add first-class Sora video provider
2026-07-05 10:56:56 -07:00
calesthio
0eaef99902 Merge main into Sora provider branch 2026-07-05 07:03:26 -07:00
Calesthio
ce11f6a24f Merge pull request #285 from calesthio/codex/taste-governance
Add taste direction governance
2026-07-05 06:58:18 -07:00
Calesthio
c3c6b03877 Merge pull request #252 from 0xDevNinja/fix/issue-219-math-animate-codeexec
fix(math_animate): gate caller-supplied scene_code execution (#219)
2026-07-05 06:48:40 -07:00
Calesthio
97fa905ded Merge pull request #266 from 0xDevNinja/fix/audio-mixer-ducking-filtergraph
fix: three independent zero-key correctness bugs (audio_mixer ducking, scene-variation run count, source-media schema)
2026-07-05 06:48:28 -07:00
Calesthio
6809c7e052 Merge pull request #289 from ketpatil77/codex/openmontage-source-led-motion
fix(delivery): recompute motion requirement after source-led override
2026-07-05 06:37:55 -07:00
Calesthio
6e67e2f7d7 Merge pull request #288 from ketpatil77/codex/openmontage-scoring-tokenizer-punctuation
fix(scoring): strip trailing punctuation from tokens
2026-07-05 06:32:03 -07:00
Mandaar
37e4ef7831 fix(comfyui): use WAN 2.1 VAE in bundled 14B T2V workflow
The bundled wan22-t2v-4step.json workflow loads the 14B FP8 diffusion
pair (wan2.2_t2v_high/low_noise_14B_fp8_scaled.safetensors), which
produce 16-channel latents, but its VAELoader referenced
wan2.2_vae.safetensors — the WAN 2.2 5B model's VAE, which expects
48-channel latents. Every T2V run therefore failed at VAEDecode with:

  Expected tensor to have size 48 at dimension 1, but got size 16

Switch the workflow to wan_2.1_vae.safetensors, matching the 14B
models and the sibling wan22-i2v-4step.json, and update the T2V
required-models list in tools/video/comfyui_video.py to match so
preflight checks for the VAE that is actually used.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 13:59:27 +05:30
Your Name
2beda014be fix(comfyui): pair wan22 t2v workflow with 14b-compatible vae 2026-07-04 19:45:47 +05:30
Your Name
84532dae63 fix(delivery): recompute motion requirement after source-led override 2026-07-04 19:37:33 +05:30
MVizu
dc25d6d60a fix: check ffmpeg availability via shutil.which instead of hardcoding True
video_compose.get_info() reported render_engines.ffmpeg as always
available, unlike the real availability checks used for remotion and
hyperframes. On a machine without ffmpeg on PATH, preflight would
falsely report ffmpeg as usable, letting render_runtime="ffmpeg" get
locked at proposal time only to fail at compose.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 23:09:09 -04:00
calesthio
fd086a38c6 Add taste direction governance 2026-07-03 19:01:10 -07:00
Calesthio
e09afaa280 Merge pull request #240 from yiyabo/feat/dashscope-integration
Add DashScope (Alibaba Cloud Bailian) provider: image gen + TTS + ASR
2026-07-03 18:04:53 -07:00
calesthio
0bfa7f1f8c test: include dashscope in tts provider contract 2026-07-03 18:00:18 -07:00
Your Name
32d34a7ca8 fix(scoring): strip trailing punctuation from tokens 2026-07-03 20:15:17 +05:30
Calesthio
f4b8b90a24 Merge pull request #273 from calesthio/feat/backlot-living-storyboard
Release Backlot: the living storyboard for OpenMontage
2026-07-03 07:29:04 -07:00
calesthio
4f9c612b28 backlot: address review findings (SVG visuals, decision-key doc, tests)
From an independent review of the branch:

- Regression: existing non-raster-but-showable visuals (.svg diagrams) were
  dropped by the renderable filter — they were served fine before via <img>
  (/thumb passes SVG through). Add .svg to MEDIA_IMAGE_EXT.
- Doc accuracy: the board dedupes decisions by (category, subject), not category
  alone (category-only would wrongly merge distinct decisions that share a
  category, e.g. TTS vs image provider_selection). Correct AGENT_GUIDE to say
  the pair is the key and to reuse the same subject when re-logging.
- Coverage: the new visual-selection logic was untested (which let the earlier
  missing-file regression through). Add TestStoryboardVisualSelection covering
  the .tsx-animation exclusion, snapshot fallback (exact + <id>_* match), SVG
  renderability, the preserved missing-file indicator, and takes = renderable.

Not changed (reviewed, deliberate): .narr clamp at --fs-scale 1.16 degrades
gracefully via the fade + click-to-expand modal; decision dedupe stays keyed on
(category, subject) as the more-correct behavior.
2026-07-03 07:25:39 -07:00
calesthio
9f77aa2519 backlot: keep the missing-file visual indicator
The renderable-only filter from the previous commit also dropped assets whose
file is missing, so the storyboard lost its "asset in manifest, file missing"
slot (broke tests/backlot/test_state.py::test_full_project).

Distinguish the two cases: a missing image/video/diagram still surfaces as the
missing indicator; only an asset that EXISTS but can't be shown (a .tsx atelier
composition) falls back to a per-scene snapshot/placeholder.
2026-07-03 07:10:56 -07:00