mirror of
https://github.com/nexu-io/open-design.git
synced 2026-07-07 23:09:34 +08:00
* feat(media): integrate OpenRouter as BYOK provider for image and video generation This commit restores the OpenRouter integration originally proposed in PR #1040, resolving the conflicts that caused the previous PR to be closed. Changes: - Re-added OpenRouter image and video models to `models.ts` and `media-models.ts`. - Implemented `renderOpenRouterImage` and `renderOpenRouterVideo` in `media.ts`, supporting 30-minute polling timeout for long video generations. - Wired OpenRouter attribution headers (X-Title, HTTP-Referer) across the proxy, connection test, and media dispatcher loops. - Added regression tests in `media-openrouter.test.ts` to verify OpenRouter functionality, including asserting that API keys are not leaked via `Authorization` headers to third-party CDNs. - Registered `openrouter` in `media-config.ts` ENV_KEYS for environment variable overrides. Fixes #1040. * fix(media): respect model-alias contract in OpenRouter renderers and restore 30-min poll ceiling - Derive outbound model from credentials.model || ctx.wireModel (matching ImageRouter pattern) so OD_MEDIA_MODEL_ALIASES and stored aliases are honoured. Strip openrouter/ prefix from the resolved value, not ctx.model. - Restore default poll ceiling to 30 minutes to match PR-documented contract. - Add alias regression tests for both image and video OpenRouter renderers. - Add timeout contract regression test. * feat(media): add OpenRouter resolution variants and multi-image i2v support - Add 480p/720p/1080p resolution variants for Seedance 2.0 (default: 1080p). Resolution is encoded as a model ID suffix (e.g. :1080p) and parsed by renderOpenRouterVideo before sending the resolution parameter to OpenRouter. - Add Kling v3.0 Pro as an OpenRouter-routed video model. - Extend generateMedia API with images[] array parameter for multi-image i2v flows. First image goes to frame_images[first_frame], additional images go to input_references for style/content guidance. - Broaden the NewProjectPanel supportedModels whitelist to include openrouter, imagerouter, leonardo, and custom-image providers for both image and video surfaces. - Add regression tests for OpenRouter visibility in image/video pickers. * fix(test): update quick-fill provider index after OpenRouter insertion Adding OpenRouter as an openai-protocol quick-fill provider shifted DeepSeek from index 1 to index 2 in the provider dropdown, causing the 'updates model and base URL when quick fill provider changes' test to select OpenRouter instead of DeepSeek. * fix(media): sync daemon media-models with web model registry - Add OpenRouter resolution variants (:1080p, :480p) and kwaivgi/kling-v3.0-pro to the daemon's media-models registry mirror. This prevents the daemon from rejecting the model IDs as unknown. - Add unit tests verifying resolution suffix parsing and defaulting for OpenRouter video models in media-openrouter.test.ts. - Pass verify-media-models script drift check.
34 lines
1.5 KiB
TypeScript
34 lines
1.5 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
|
|
import { supportedModels } from '../../src/components/NewProjectPanel';
|
|
import { AUDIO_MODELS_BY_KIND, IMAGE_MODELS, VIDEO_MODELS } from '../../src/media/models';
|
|
|
|
describe('NewProjectPanel image provider visibility', () => {
|
|
it('shows Nano Banana in supported image models', () => {
|
|
const models = supportedModels('image', IMAGE_MODELS);
|
|
expect(models.some((model) => model.provider === 'nanobanana')).toBe(true);
|
|
expect(models.some((model) => model.id === 'gemini-3.1-flash-image-preview')).toBe(true);
|
|
});
|
|
|
|
it('shows ElevenLabs speech models in supported audio models', () => {
|
|
const models = supportedModels('audio', AUDIO_MODELS_BY_KIND.speech);
|
|
expect(models.some((model) => model.provider === 'elevenlabs')).toBe(true);
|
|
expect(models.some((model) => model.id === 'elevenlabs-v3')).toBe(true);
|
|
});
|
|
|
|
it('shows ElevenLabs sound effects models in supported audio models', () => {
|
|
const models = supportedModels('audio', AUDIO_MODELS_BY_KIND.sfx);
|
|
expect(models.some((model) => model.id === 'elevenlabs-sfx')).toBe(true);
|
|
});
|
|
|
|
it('shows OpenRouter in supported image models', () => {
|
|
const models = supportedModels('image', IMAGE_MODELS);
|
|
expect(models.some((model) => model.provider === 'openrouter')).toBe(true);
|
|
});
|
|
|
|
it('shows OpenRouter in supported video models', () => {
|
|
const models = supportedModels('video', VIDEO_MODELS);
|
|
expect(models.some((model) => model.provider === 'openrouter')).toBe(true);
|
|
});
|
|
});
|