From 5953408f40f9e00db2fae720b077268a56e99500 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 24 Feb 2026 14:47:10 +0000 Subject: [PATCH 1/3] feat(sdk): add portrait mode support for realtime models Co-Authored-By: Claude Opus 4.6 --- packages/sdk/src/index.ts | 1 + packages/sdk/src/shared/model.ts | 31 ++++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index caddfa2..3aef58b 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -56,6 +56,7 @@ export { type Model, type ModelDefinition, models, + type RealtimeModelOptions, type RealTimeModels, type VideoModelDefinition, type VideoModels, diff --git a/packages/sdk/src/shared/model.ts b/packages/sdk/src/shared/model.ts index d2f6d4b..d6d0152 100644 --- a/packages/sdk/src/shared/model.ts +++ b/packages/sdk/src/shared/model.ts @@ -378,12 +378,41 @@ const _models = { }, } as const; +/** + * Options for configuring realtime model output. + */ +export type RealtimeModelOptions = { + /** The orientation of the output. When `"portrait"`, width and height are swapped. Defaults to `"landscape"`. */ + orientation?: "landscape" | "portrait"; +}; + export const models = { - realtime: (model: T): ModelDefinition => { + /** + * Get a realtime model definition. + * + * Available models: + * - `"mirage"` - Mirage v1 + * - `"mirage_v2"` - Mirage v2 + * - `"lucy_v2v_720p_rt"` - Lucy v2v 720p realtime + * - `"lucy_2_rt"` - Lucy 2 realtime + * - `"live_avatar"` - Live avatar + * + * @param model - The realtime model to use. + * @param options - Optional configuration. Set `orientation` to `"portrait"` to swap width and height. + * @returns The model definition, with dimensions adjusted for the requested orientation. + */ + realtime: (model: T, options?: RealtimeModelOptions): ModelDefinition => { const modelDefinition = _models.realtime[model]; if (!modelDefinition) { throw createModelNotFoundError(model); } + if (options?.orientation === "portrait") { + return { + ...modelDefinition, + width: modelDefinition.height, + height: modelDefinition.width, + } as ModelDefinition; + } return modelDefinition as ModelDefinition; }, /** From aacb87b56e6b5af614095988aa2b247ac06f5220 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 24 Feb 2026 15:09:46 +0000 Subject: [PATCH 2/3] fix(sdk): correct lucy_2_rt resolution to 1088x624 Co-Authored-By: Claude Opus 4.6 --- packages/sdk/src/shared/model.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/sdk/src/shared/model.ts b/packages/sdk/src/shared/model.ts index d6d0152..3d7e9ab 100644 --- a/packages/sdk/src/shared/model.ts +++ b/packages/sdk/src/shared/model.ts @@ -269,8 +269,8 @@ const _models = { urlPath: "/v1/stream", name: "lucy_2_rt" as const, fps: 20, - width: 1280, - height: 720, + width: 1088, + height: 624, inputSchema: z.object({}), }, live_avatar: { From 068c2b05ec4917334330f6a1bf6d3c036570eff8 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 24 Feb 2026 15:22:16 +0000 Subject: [PATCH 3/3] feat(sdk): finalize portrait mode - tests, docs, reverted resolution Co-Authored-By: Claude Opus 4.6 --- packages/sdk/README.md | 10 ++++++++ packages/sdk/src/shared/model.ts | 4 ++-- packages/sdk/tests/unit.test.ts | 39 ++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/packages/sdk/README.md b/packages/sdk/README.md index feffdf4..c96cee6 100644 --- a/packages/sdk/README.md +++ b/packages/sdk/README.md @@ -62,6 +62,16 @@ realtimeClient.setPrompt("Cyberpunk city"); realtimeClient.disconnect(); ``` +#### Portrait mode + +Pass `{ orientation: "portrait" }` to swap width and height for vertical streams: + +```typescript +const model = models.realtime("lucy_2_rt", { orientation: "portrait" }); +// model.width → 720 +// model.height → 1280 +``` + ### Async Processing (Queue API) For video generation jobs, use the queue API to submit jobs and poll for results: diff --git a/packages/sdk/src/shared/model.ts b/packages/sdk/src/shared/model.ts index 3d7e9ab..d6d0152 100644 --- a/packages/sdk/src/shared/model.ts +++ b/packages/sdk/src/shared/model.ts @@ -269,8 +269,8 @@ const _models = { urlPath: "/v1/stream", name: "lucy_2_rt" as const, fps: 20, - width: 1088, - height: 624, + width: 1280, + height: 720, inputSchema: z.object({}), }, live_avatar: { diff --git a/packages/sdk/tests/unit.test.ts b/packages/sdk/tests/unit.test.ts index 627303e..866e6f0 100644 --- a/packages/sdk/tests/unit.test.ts +++ b/packages/sdk/tests/unit.test.ts @@ -990,6 +990,45 @@ describe("Lucy 2 realtime", () => { }); }); +describe("models.realtime", () => { + it("returns correct landscape dimensions by default", () => { + const model = models.realtime("lucy_2_rt"); + expect(model.width).toBe(1280); + expect(model.height).toBe(720); + expect(model.fps).toBe(20); + }); + + it("returns correct landscape dimensions when explicitly set", () => { + const model = models.realtime("lucy_2_rt", { orientation: "landscape" }); + expect(model.width).toBe(1280); + expect(model.height).toBe(720); + expect(model.fps).toBe(20); + }); + + it("returns swapped dimensions in portrait mode", () => { + const model = models.realtime("lucy_2_rt", { orientation: "portrait" }); + expect(model.width).toBe(720); + expect(model.height).toBe(1280); + expect(model.fps).toBe(20); + }); + + it("portrait mode preserves model name and urlPath", () => { + const model = models.realtime("lucy_2_rt", { orientation: "portrait" }); + expect(model.name).toBe("lucy_2_rt"); + expect(model.urlPath).toBe("/v1/stream"); + }); + + it("throws on unknown model", () => { + expect(() => models.realtime("nonexistent_model" as any)).toThrow(); + }); + + it("swaps dimensions for mirage in portrait mode", () => { + const model = models.realtime("mirage", { orientation: "portrait" }); + expect(model.width).toBe(704); + expect(model.height).toBe(1280); + }); +}); + describe("WebRTCConnection", () => { describe("setImageBase64", () => { it("rejects immediately when WebSocket is not open", async () => {