From 85e566657e08c9cd6767bf5308230e7219713759 Mon Sep 17 00:00:00 2001 From: Tomer Shlasky Date: Wed, 25 Feb 2026 10:05:50 +0200 Subject: [PATCH 1/5] feat(realtime): add resetInput() to reset to passthrough mode at runtime --- packages/sdk/src/realtime/client.ts | 4 +++- packages/sdk/src/realtime/methods.ts | 8 +++++++- packages/sdk/src/realtime/webrtc-manager.ts | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/sdk/src/realtime/client.ts b/packages/sdk/src/realtime/client.ts index f1869b0..19c7421 100644 --- a/packages/sdk/src/realtime/client.ts +++ b/packages/sdk/src/realtime/client.ts @@ -109,6 +109,7 @@ export type Events = { export type RealTimeClient = { set: (input: SetInput) => Promise; setPrompt: (prompt: string, { enhance }?: { enhance?: boolean }) => Promise; + resetInput: () => Promise; isConnected: () => boolean; getConnectionState: () => ConnectionState; disconnect: () => void; @@ -118,7 +119,7 @@ export type RealTimeClient = { subscribeToken: string | null; setImage: ( image: Blob | File | string | null, - options?: { prompt?: string; enhance?: boolean; timeout?: number }, + options?: { prompt?: string | null; enhance?: boolean; timeout?: number }, ) => Promise; playAudio?: (audio: Blob | File | ArrayBuffer) => Promise; }; @@ -329,6 +330,7 @@ export const createRealTimeClient = (opts: RealTimeClientOptions) => { const client: RealTimeClient = { set: methods.set, setPrompt: methods.setPrompt, + resetInput: methods.resetInput, isConnected: () => manager.isConnected(), getConnectionState: () => manager.getConnectionState(), disconnect: () => { diff --git a/packages/sdk/src/realtime/methods.ts b/packages/sdk/src/realtime/methods.ts index 6755d41..39b6cde 100644 --- a/packages/sdk/src/realtime/methods.ts +++ b/packages/sdk/src/realtime/methods.ts @@ -7,7 +7,7 @@ const UPDATE_TIMEOUT_MS = 30 * 1000; const setInputSchema = z .object({ - prompt: z.string().min(1).optional(), + prompt: z.union([z.string().min(1), z.null()]).optional(), enhance: z.boolean().optional().default(true), image: z.union([z.instanceof(Blob), z.instanceof(File), z.string(), z.null()]).optional(), }) @@ -109,8 +109,14 @@ export const realtimeMethods = ( } }; + const resetInput = async (): Promise => { + assertConnected(); + await webrtcManager.setImage(null, { prompt: null, timeout: UPDATE_TIMEOUT_MS }); + }; + return { set, setPrompt, + resetInput, }; }; diff --git a/packages/sdk/src/realtime/webrtc-manager.ts b/packages/sdk/src/realtime/webrtc-manager.ts index 71408fb..1efca07 100644 --- a/packages/sdk/src/realtime/webrtc-manager.ts +++ b/packages/sdk/src/realtime/webrtc-manager.ts @@ -246,7 +246,7 @@ export class WebRTCManager { setImage( imageBase64: string | null, - options?: { prompt?: string; enhance?: boolean; timeout?: number }, + options?: { prompt?: string | null; enhance?: boolean; timeout?: number }, ): Promise { return this.connection.setImageBase64(imageBase64, options); } From 3cac81b316e0e4f9b9d3e2db46396d77c5db3c6b Mon Sep 17 00:00:00 2001 From: Tomer Shlasky Date: Wed, 25 Feb 2026 11:55:30 +0200 Subject: [PATCH 2/5] Fix setImage implementation signature to accept prompt: null --- packages/sdk/src/realtime/client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sdk/src/realtime/client.ts b/packages/sdk/src/realtime/client.ts index 19c7421..f31f6e8 100644 --- a/packages/sdk/src/realtime/client.ts +++ b/packages/sdk/src/realtime/client.ts @@ -350,7 +350,7 @@ export const createRealTimeClient = (opts: RealTimeClientOptions) => { }, setImage: async ( image: Blob | File | string | null, - options?: { prompt?: string; enhance?: boolean; timeout?: number }, + options?: { prompt?: string | null; enhance?: boolean; timeout?: number }, ) => { if (image === null) { return manager.setImage(null, options); From 9160bda98ad2e4b9fc78a4a2b42db7b021b4a31d Mon Sep 17 00:00:00 2001 From: Tomer Shlasky Date: Wed, 25 Feb 2026 12:59:34 +0200 Subject: [PATCH 3/5] Add resetInput tests and fix setImage implementation signature --- packages/sdk/tests/unit.test.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/packages/sdk/tests/unit.test.ts b/packages/sdk/tests/unit.test.ts index 627303e..aca56aa 100644 --- a/packages/sdk/tests/unit.test.ts +++ b/packages/sdk/tests/unit.test.ts @@ -1422,6 +1422,28 @@ describe("set()", () => { timeout: 30000, }); }); + + it("set({ prompt: null }) resets to passthrough", async () => { + await methods.set({ prompt: null }); + expect(mockManager.setImage).toHaveBeenCalledWith(null, { + prompt: null, + enhance: true, + timeout: 30000, + }); + }); + + it("resetInput sends passthrough signal", async () => { + await methods.resetInput(); + expect(mockManager.setImage).toHaveBeenCalledWith(null, { + prompt: null, + timeout: 30000, + }); + }); + + it("resetInput rejects when not connected", async () => { + mockManager.getConnectionState.mockReturnValue("disconnected"); + await expect(methods.resetInput()).rejects.toThrow("Cannot send message: connection is disconnected"); + }); }); describe("Subscribe Token", () => { From 49bc538784c6b651b12c7b2fe4de60ed8d877828 Mon Sep 17 00:00:00 2001 From: Tomer Shlasky Date: Wed, 25 Feb 2026 13:06:54 +0200 Subject: [PATCH 4/5] Add resetInput button to playground and unit tests --- packages/sdk/index.html | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/packages/sdk/index.html b/packages/sdk/index.html index dcc9b62..8259ba7 100644 --- a/packages/sdk/index.html +++ b/packages/sdk/index.html @@ -273,6 +273,7 @@

Prompt Control

+
@@ -386,6 +387,7 @@

Console Logs

remoteVideo: document.getElementById('remote-video'), promptInput: document.getElementById('prompt-input'), sendPrompt: document.getElementById('send-prompt'), + resetInput: document.getElementById('reset-input'), enrichToggle: document.getElementById('enrich-toggle'), // Promise-based prompt elements promisePromptInput: document.getElementById('promise-prompt-input'), @@ -546,6 +548,7 @@

Console Logs

elements.disconnectBtn.disabled = false; elements.promptInput.disabled = false; elements.sendPrompt.disabled = false; + elements.resetInput.disabled = false; elements.promisePromptInput.disabled = false; elements.sendPromisePrompt.disabled = false; elements.referenceImage.disabled = false; @@ -599,6 +602,7 @@

Console Logs

elements.disconnectBtn.disabled = true; elements.promptInput.disabled = true; elements.sendPrompt.disabled = true; + elements.resetInput.disabled = true; elements.promptInput.value = ''; elements.promisePromptInput.disabled = true; elements.sendPromisePrompt.disabled = true; @@ -641,6 +645,25 @@

Console Logs

// Send prompt on button click elements.sendPrompt.addEventListener('click', sendPrompt); + // Reset input (back to passthrough) + elements.resetInput.addEventListener('click', async () => { + if (!decartRealtime || !isConnected) { + addLog('Not connected to Decart', 'error'); + return; + } + try { + elements.resetInput.disabled = true; + addLog('Resetting input to passthrough...', 'info'); + await decartRealtime.resetInput(); + addLog('Reset to passthrough mode', 'success'); + elements.promptInput.value = ''; + } catch (error) { + addLog(`Failed to reset input: ${error.message}`, 'error'); + } finally { + elements.resetInput.disabled = false; + } + }); + // Send prompt on Enter key elements.promptInput.addEventListener('keypress', (e) => { if (e.key === 'Enter' && !elements.sendPrompt.disabled) { From b8f713d18fe2be6e2352be558c4ca3c7fadb5090 Mon Sep 17 00:00:00 2001 From: Tomer Shlasky Date: Wed, 25 Feb 2026 13:08:06 +0200 Subject: [PATCH 5/5] Fix Reset Input button showing blue when disabled --- packages/sdk/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sdk/index.html b/packages/sdk/index.html index 8259ba7..c17d138 100644 --- a/packages/sdk/index.html +++ b/packages/sdk/index.html @@ -273,7 +273,7 @@

Prompt Control

- +