Skip to content

feat(python-sdk): add OpenRouter video generation via async polling (#464)#479

Merged
santoshkumarradha merged 3 commits intodev/add-videofrom
feat/464-openrouter-video
Apr 18, 2026
Merged

feat(python-sdk): add OpenRouter video generation via async polling (#464)#479
santoshkumarradha merged 3 commits intodev/add-videofrom
feat/464-openrouter-video

Conversation

@santoshkumarradha
Copy link
Copy Markdown
Member

Summary

  • Add OpenRouterProvider.generate_video() with async polling workflow: POST submit -> poll until completed/failed -> download MP4
  • Add VideoOutput model to multimodal_response.py with save/get_bytes support
  • Add videos field to MultimodalResponse (alongside existing files)
  • Route openrouter/ prefixed models in AgentAI.ai_generate_video() to OpenRouterProvider
  • Update supported_modalities to return ["image", "video"] for OpenRouter

Test plan

  • Happy path: submit -> poll -> download -> MultimodalResponse with files[] and videos[]
  • Multi-poll: pending -> in_progress -> completed transitions
  • Timeout handling raises TimeoutError
  • Failed job status raises RuntimeError with error detail
  • HTTP error mapping (400/401/402/429)
  • Model prefix stripping (openrouter/ removed before API call)
  • No API key raises ValueError
  • VideoOutput model fields and get_bytes
  • MultimodalResponse.has_videos, .videos, repr
  • Existing test suite passes (updated error message assertions)

@santoshkumarradha santoshkumarradha requested review from a team and AbirAbbas as code owners April 18, 2026 10:03
)

CR-01: Add image_url to request body (was silently dropped)
CR-02: Validate job_id format + enforce HTTPS-only video download URL
HI-01: Add MAX_VIDEO_BYTES (500MB) size limit on video downloads
HI-02: Add comment clarifying download uses no auth headers
HI-03: Add transient poll error retry (max 3 consecutive 502/503/504)
MD-01: Fix duration type to Optional[float], remove int() cast in agent_ai
MD-03: Move poll sleep to end of loop (poll immediately on first iteration)
LO-01: Truncate error response bodies to 500 chars
LO-02: Move _error_messages to class constant _VIDEO_ERROR_MESSAGES
IN-02: Add test for image_url passthrough in request body
Resolve conflicts from merging dev/add-video (which includes audio/music
#465, Go SDK #468, TS SDK #467) into the video generation branch:

- Combine supported_modalities: ["image", "video", "audio", "music"]
- Use MediaRouter for video routing (from #463) instead of manual prefix checks
- Remove duplicate VideoOutput class (keep richer version with resolution/aspect_ratio)
- Standardize has_videos property name (plural, consistent with has_images/has_files)
- Update test error message assertions to match MediaRouter's ValueError
@santoshkumarradha santoshkumarradha merged commit be83fb9 into dev/add-video Apr 18, 2026
8 checks passed
@github-actions
Copy link
Copy Markdown
Contributor

Performance

SDK Memory Δ Latency Δ Tests Status
Python 7.9 KB -13% 0.30 µs -14%

✓ No regressions detected

@github-actions
Copy link
Copy Markdown
Contributor

📊 Coverage gate

Thresholds from .coverage-gate.toml: per-surface ≥ 86%, aggregate ≥ 88%, max per-surface regression ≤ 1.0 pp, max aggregate regression ≤ 0.50 pp.

Surface Current Baseline Δ
control-plane 87.30% 87.30% → +0.00 pp 🟡
sdk-go 90.00% 90.70% ↓ -0.70 pp 🟢
sdk-python 93.63% 93.63% ↑ +0.00 pp 🟢
sdk-typescript 92.67% 92.56% ↑ +0.11 pp 🟢
web-ui 90.02% 90.01% ↑ +0.01 pp 🟢
aggregate 89.02% 89.01% ↑ +0.01 pp 🟡

✅ Gate passed

No surface regressed past the allowed threshold and the aggregate stayed above the floor.

@github-actions
Copy link
Copy Markdown
Contributor

📐 Patch coverage gate

Threshold: 80% on lines this PR touches vs origin/main (from .coverage-gate.toml:thresholds.min_patch).

Surface Touched lines Patch coverage Status
control-plane 0 ➖ no changes
sdk-go 377 66.00%
sdk-python 0 ➖ no changes
sdk-typescript 237 95.00%
web-ui 0 ➖ no changes

❌ Patch gate failed

sdk-go — 66.00% on 377 touched lines (128 uncovered):

File Patch coverage Missing lines
sdk/go/ai/openrouter_media.go 64.5% 62, 90, 91, 92, 93, 94, 95, 96, 97, 98 …(+118 more)
sdk/go/ai/media_provider.go 100.0%

How to fix

  1. For each file listed above, add tests that exercise the missing line numbers in this same PR.
  2. Re-run locally: ./scripts/coverage-summary.sh && ./scripts/patch-coverage-gate.sh.
  3. Do not lower min_patch in .coverage-gate.toml to silence this — the floor is the contract.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant