From a71cb8334a90d7bfba8f213dea6761be4af4e54e Mon Sep 17 00:00:00 2001 From: snowspeeder Date: Thu, 6 Aug 2026 12:09:34 -0400 Subject: [PATCH] feat: extend voice API workspace and speech controls --- docs/voice-api.md | 2 +- src/server/voiceApi.ts | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/voice-api.md b/docs/voice-api.md index 3d3ba15..9a24578 100644 --- a/docs/voice-api.md +++ b/docs/voice-api.md @@ -1,6 +1,6 @@ # Voice Conversation API (v1) -`/api/v1/voice` is a server-side device API for native iOS and Echo-style clients. It is separate from the browser voice feature. Azure credentials remain on the PI WEB host. +`/api/v1/voice` is a server-side device API for native iOS and Echo-style clients. It is separate from the browser voice feature. Azure credentials remain on the PI WEB host. Every voice turn automatically includes server-side instructions to produce concise, natural DragonHD-friendly speech without Markdown or visual-only formatting. ## Security and provisioning diff --git a/src/server/voiceApi.ts b/src/server/voiceApi.ts index 5e58497..d19e4a8 100644 --- a/src/server/voiceApi.ts +++ b/src/server/voiceApi.ts @@ -31,6 +31,7 @@ const EVENT_OPEN_TIMEOUT_MS = 10_000; const TURN_TIMEOUT_MS = 120_000; const WORKING_PROGRESS_INTERVAL_MS = 15_000; const DEVICE_WORKSPACE_ROOT = "/home/hope/workspaces"; +const VOICE_CONVERSATION_INSTRUCTIONS = "This is a voice conversation. Respond in natural, concise spoken language suitable for Azure DragonHD text-to-speech. Do not use Markdown, headings, tables, bullet lists, code fences, URLs unless explicitly requested, or visual-only references. Speak punctuation naturally and expand ambiguous symbols when useful."; interface TokenRecord { id: string; hash: string; @@ -608,7 +609,11 @@ async function runTurn( speech: VoiceSpeechGateway, text: string ): Promise { - const prompt = conversation.context === undefined ? text : `${conversation.context}\n\n${text}`; + const prompt = [ + VOICE_CONVERSATION_INSTRUCTIONS, + ...(conversation.context === undefined ? [] : [conversation.context]), + text, + ].join("\n\n"); // The event subscription is fully open before the prompt is submitted, so // a fast Pi run cannot emit agent_settled before this device starts waiting. const { settled } = await startSettledWaiter(