···11+# Gemini Live WebSocket notes
22+33+These notes capture the verified protocol target for the next implementation step.
44+55+## Verified target
66+77+Google AI documentation indicates Gemini Live supports:
88+99+- direct WebSocket sessions
1010+- stateful sessions
1111+- text and audio modalities
1212+- JavaScript SDK usage via `@google/genai`
1313+- raw WebSocket usage
1414+1515+## Verified endpoint shape
1616+1717+Raw WebSocket endpoint:
1818+1919+```text
2020+wss://generativelanguage.googleapis.com/ws/google.ai.generativelanguage.v1beta.GenerativeService.BidiGenerateContent?key=YOUR_API_KEY
2121+```
2222+2323+## Verified setup flow
2424+2525+The first client message must configure the session.
2626+2727+The documentation describes a first setup/config message and then subsequent turn content.
2828+2929+## Verified JS SDK direction
3030+3131+Docs show JavaScript examples using:
3232+3333+```ts
3434+import { GoogleGenAI, Modality } from '@google/genai';
3535+```
3636+3737+And a live connect flow shaped like:
3838+3939+```ts
4040+const session = await ai.live.connect({
4141+ model,
4242+ callbacks,
4343+ config,
4444+});
4545+```
4646+4747+## Verified model direction
4848+4949+Examples reference live-capable models such as:
5050+5151+- `gemini-3.1-flash-live-preview`
5252+5353+## Implication for this repo
5454+5555+The next implementation step should prefer:
5656+5757+1. adding `@google/genai`
5858+2. implementing `GeminiLiveProvider` with `ai.live.connect(...)`
5959+3. capturing streamed text/audio output into the local runtime event model
6060+6161+## Notes for runtime wiring
6262+6363+Desired mapping in this repo:
6464+6565+- incoming chat -> `GeminiLiveProvider.generateReply`
6666+- Gemini streamed text -> reply text
6767+- Gemini audio output -> OBS-capturable sink
6868+- Gemini affect/prosody -> avatar action cues for OpenVT bridge
6969+
···11+# Gemini Live + OpenVT + OBS + stream.place integration plan
22+33+## Objective
44+55+Connect these pieces into one loop:
66+77+1. stream.place chat arrives
88+2. chat triggers an agent response
99+3. Gemini Live API generates the live reply / speech stream
1010+4. OpenVT shows Haru as the avatar renderer
1111+5. OBS captures OpenVT and audio
1212+6. OBS streams to stream.place
1313+1414+## Current repo state
1515+1616+### Already present
1717+1818+- OpenVT local setup notes and launcher scripts
1919+- working Haru/OpenVT path in `vendor/open-vt`
2020+- simple chat runtime scaffold in `src/index.ts`
2121+- local chat simulation in `scripts/simulate-chat.ts`
2222+- architecture notes mentioning:
2323+ - stream.place chat
2424+ - LLM reply generation
2525+ - TTS
2626+ - avatar actions
2727+ - WHIP/RTMP uplink
2828+2929+### Not yet present
3030+3131+- real stream.place chat adapter
3232+- Gemini Live API client
3333+- agent orchestration layer
3434+- OpenVT control bridge from external runtime
3535+- OBS automation / obs-websocket control
3636+- actual stream.place ingest automation
3737+3838+## Minimal end-to-end architecture
3939+4040+```text
4141+stream.place chat
4242+ -> chat adapter
4343+ -> agent runtime
4444+ -> Gemini Live session
4545+ -> text reply
4646+ -> streaming audio reply
4747+ -> optional emotion tags / cues
4848+ -> avatar control bridge
4949+ -> OpenVT expression / motion triggers
5050+ -> OBS scene
5151+ -> captures OpenVT window or virtual camera
5252+ -> mixes Gemini audio output / mic
5353+ -> stream.place ingest (WHIP or RTMP)
5454+```
5555+5656+## Recommended practical split
5757+5858+### Process A: bot runtime
5959+6060+Responsible for:
6161+6262+- reading chat from stream.place
6363+- deciding whether to respond
6464+- calling the agent
6565+- opening / maintaining Gemini Live session
6666+- emitting:
6767+ - reply text
6868+ - audio stream or audio file
6969+ - avatar cues like `emotion:happy`, `gesture:nod`, `talk:start`
7070+7171+### Process B: OpenVT renderer
7272+7373+Responsible for:
7474+7575+- rendering Haru
7676+- microphone / lip sync path
7777+- avatar expressions / motions
7878+- outputting window / virtual camera feed
7979+8080+### Process C: OBS production
8181+8282+Responsible for:
8383+8484+- capturing OpenVT window or loopback webcam
8585+- ingesting Gemini audio output
8686+- mixing optional mic/music
8787+- sending program output to stream.place
8888+8989+## Critical integration gaps
9090+9191+### 1. Gemini Live client
9292+9393+Need a client that can:
9494+9595+- send text/chat turns
9696+- receive streaming text/audio
9797+- optionally maintain conversational session state
9898+9999+Likely implementation location:
100100+101101+- `src/gemini-live.ts`
102102+103103+### 2. Chat adapter for stream.place
104104+105105+Need a real adapter replacing the current scaffold.
106106+107107+Likely implementation location:
108108+109109+- `src/streamplace-chat.ts`
110110+111111+Expected responsibilities:
112112+113113+- subscribe to chat events (likely Jetstream / ATProto feed path)
114114+- normalize events into local `ChatMessage`
115115+- send replies back if desired
116116+117117+### 3. OpenVT control bridge
118118+119119+OpenVT currently supports internal blueprint / tracker-driven motion, but this repo does not yet expose an external API for:
120120+121121+- toggling expressions
122122+- triggering gestures / animations
123123+- setting mouth/talk state from external runtime
124124+125125+Likely easiest bridge options:
126126+127127+1. small local websocket server inside OpenVT, or
128128+2. local IPC / file / TCP bridge from external runtime into OpenVT tracker/action nodes
129129+130130+Likely implementation target:
131131+132132+- add a lightweight control node under `vendor/open-vt` or use a separate control process
133133+134134+### 4. OBS control
135135+136136+OBS can be kept manual at first, but for automation the likely path is:
137137+138138+- `obs-websocket`
139139+140140+It would allow:
141141+142142+- scene switching
143143+- source muting/unmuting
144144+- start/stop streaming
145145+146146+Likely implementation location:
147147+148148+- `src/obs-control.ts`
149149+150150+### 5. stream.place ingest
151151+152152+Docs in this repo already assume:
153153+154154+- WHIP if available
155155+- otherwise RTMP
156156+157157+Likely first step:
158158+159159+- manual OBS config for stream.place ingest
160160+161161+## Smallest viable path
162162+163163+To minimize scope, do this in order:
164164+165165+### Phase 1: fake chat -> fake reply -> OpenVT + OBS manual
166166+167167+- use local simulated chat
168168+- use deterministic local text reply
169169+- use existing OpenVT Haru setup
170170+- use OBS manual window capture
171171+- no Gemini yet
172172+173173+### Phase 2: Gemini Live reply + audio
174174+175175+- replace fake reply with Gemini Live
176176+- route Gemini audio to system audio or a known sink OBS can capture
177177+- keep OBS manual
178178+179179+### Phase 3: external avatar control
180180+181181+- map reply affect / punctuation / tags to:
182182+ - expression
183183+ - gesture
184184+ - talk state
185185+- send those cues into OpenVT
186186+187187+### Phase 4: real stream.place chat + real stream.place ingest
188188+189189+- replace simulated chat with stream.place adapter
190190+- optionally post replies back to chat
191191+192192+## Exact current blocker
193193+194194+The repo does not yet contain any real implementation for:
195195+196196+- Gemini Live API calls
197197+- stream.place chat subscription
198198+- OpenVT external control bridge
199199+- OBS websocket integration
200200+201201+So the task is not “wire existing modules together”; it is “build the missing connectors around the current OpenVT renderer path.”
202202+203203+## Recommended next implementation step
204204+205205+Build the first real connector:
206206+207207+1. `src/gemini-live.ts`
208208+2. `src/runtime.ts` orchestrator
209209+3. extend `scripts/simulate-chat.ts` to call the runtime
210210+211211+This gives:
212212+213213+- simulated chat
214214+- agent-triggered response
215215+- Gemini Live text/audio integration
216216+217217+Then the next connector should be:
218218+219219+- OpenVT control bridge for avatar cues
220220+
···11+# Live stack runbook
22+33+## Objective
44+55+Bring up the current integrated stack for:
66+77+- Jetstream/stream.place-style chat intake
88+- Gemini Live response generation
99+- OpenVT avatar control
1010+- OBS scene/text control
1111+1212+## Required environment
1313+1414+Set these before starting the live loop:
1515+1616+```bash
1717+export GEMINI_API_KEY=...
1818+export OBS_WS_URL=ws://127.0.0.1:4455
1919+export OBS_SCENE_NAME="Your Scene"
2020+export OBS_TEXT_INPUT_NAME="Your Text Source"
2121+# optional
2222+export OBS_WS_PASSWORD=...
2323+```
2424+2525+## Required running services
2626+2727+1. OpenVT running with runtime control listener enabled
2828+2. OBS running with obs-websocket enabled on port 4455
2929+3030+## Preflight check
3131+3232+```bash
3333+bun run check:live-stack
3434+```
3535+3636+Expected good state:
3737+3838+- `GEMINI_API_KEY: set`
3939+- `OBS websocket: open`
4040+- `OpenVT runtime control: open`
4141+4242+## Start the loop
4343+4444+```bash
4545+./scripts/run-live-stack.sh
4646+```
4747+4848+or:
4949+5050+```bash
5151+bun run src/index.ts --live
5252+```
5353+5454+## Current behavior
5555+5656+When chat arrives:
5757+5858+1. immediate OpenVT cues are sent:
5959+ - `talk:start`
6060+ - default `emotion:curious`
6161+2. runtime generates a reply
6262+3. reply text is sent to:
6363+ - OpenVT text control
6464+ - OBS text input (if configured)
6565+4. remaining avatar actions are sent to OpenVT
6666+6767+## What is still manual
6868+6969+- actual OBS source/scene setup
7070+- stream.place ingest configuration in OBS
7171+- real Gemini credential provisioning
7272+
···11+# OpenVT control bridge plan
22+33+## Objective
44+55+Take runtime outputs from this repo and make them actionable inside OpenVT.
66+77+Current runtime outputs already include:
88+99+- reply text
1010+- avatar actions such as:
1111+ - `talk:start`
1212+ - `talk:stop`
1313+ - `emotion:*`
1414+ - `gesture:*`
1515+1616+## Verified useful OpenVT primitives
1717+1818+### 1. TCP listener pattern already exists in OpenVT
1919+2020+OpenVT includes a reusable TCP server pattern in:
2121+2222+- `vendor/open-vt/lib/tracking/net/tcp_tracker.gd`
2323+2424+This means a local control bridge can likely be implemented in the same style as tracker ingestion.
2525+2626+### 2. JSON decoding already exists in multiple trackers
2727+2828+Examples:
2929+3030+- `vendor/open-vt/lib/tracking/camera/vts/vts_tracker.gd`
3131+- `vendor/open-vt/lib/tracking/camera/vts_blendshapes/vts_tracker.gd`
3232+3333+So a JSON-over-TCP control protocol is a natural fit.
3434+3535+### 3. Stage/model control entry points exist
3636+3737+Verified scene/controller anchors:
3838+3939+- `vendor/open-vt/studio/stage/stage.gd`
4040+- `vendor/open-vt/lib/model/vt_model.gd`
4141+4242+OpenVT already exposes model lifecycle and tracking update paths; a bridge can target the active model and/or stage.
4343+4444+## Recommended control protocol
4545+4646+Use a simple local TCP JSON protocol.
4747+4848+### Why this path
4949+5050+- matches existing OpenVT tracker infrastructure
5151+- avoids inventing an HTTP stack inside Godot
5252+- easy to emit from Bun/Node
5353+- good enough for localhost control from the runtime
5454+5555+## Suggested messages
5656+5757+```json
5858+{ "type": "talk", "state": "start" }
5959+{ "type": "talk", "state": "stop" }
6060+{ "type": "emotion", "value": "happy" }
6161+{ "type": "gesture", "value": "nod" }
6262+{ "type": "text", "value": "Hello chat!" }
6363+```
6464+6565+## Minimal OpenVT-side implementation plan
6666+6767+1. Add a new control node/script under OpenVT, for example:
6868+ - `vendor/open-vt/lib/control/runtime_control.gd`
6969+2. Reuse the TCP server pattern from `tcp_tracker.gd`
7070+3. Parse JSON messages
7171+4. Map actions to existing model/expression/animation hooks
7272+7373+## Minimal repo-side implementation plan
7474+7575+1. Add a Bun-side TCP client sender
7676+2. On each runtime output action, emit one JSON message to localhost
7777+3. Keep OBS separate from this bridge; OBS can continue to capture OpenVT visually
7878+7979+## Immediate next step
8080+8181+Implement the repo-side sender first:
8282+8383+- `src/openvt-control.ts`
8484+8585+That preserves the interface even before the OpenVT side is fully patched.
8686+
···11+# stream.place ingest checklist
22+33+## Objective
44+55+Verify the last leg of the stack:
66+77+- OBS program output reaches stream.place
88+99+## Current repo status
1010+1111+This repo currently provides:
1212+1313+- chat intake/runtime
1414+- Gemini Live seam
1515+- OpenVT control seam
1616+- OBS websocket seam
1717+1818+It does **not** yet automate stream.place ingest creation or credentials.
1919+2020+## Manual checklist
2121+2222+### 1. Configure OBS output
2323+2424+In OBS, set stream output using the stream.place-supported ingest path:
2525+2626+- WHIP if your stream.place setup provides WHIP
2727+- otherwise RTMP if your stream.place setup provides RTMP
2828+2929+Required values are expected to come from stream.place, for example:
3030+3131+- server / endpoint URL
3232+- stream key or bearer/auth material
3333+3434+### 2. Verify OBS scene contents
3535+3636+Minimum recommended scene:
3737+3838+- OpenVT capture source
3939+ - window capture, or
4040+ - virtual camera capture path if preferred
4141+- text source for replies
4242+- audio source for Gemini/system output
4343+4444+### 3. Verify OBS websocket is enabled
4545+4646+Expected local control port in this repo:
4747+4848+- `ws://127.0.0.1:4455`
4949+5050+### 4. Verify with repo preflight
5151+5252+Run:
5353+5454+```bash
5555+bun run check:live-stack
5656+```
5757+5858+### 5. Start runtime
5959+6060+Run:
6161+6262+```bash
6363+bun run run:live-stack
6464+```
6565+6666+### 6. Confirm end-to-end behavior
6767+6868+Look for all of the following:
6969+7070+- incoming chat event from Jetstream
7171+- immediate avatar action in OpenVT
7272+- reply text updated in OBS text source
7373+- Gemini-generated reply content
7474+- OBS program stream active to stream.place
7575+7676+## Missing automation
7777+7878+The following is still not implemented in code:
7979+8080+- automatic creation of stream.place ingest sessions
8181+- automatic writing of OBS stream settings from stream.place credentials
8282+- automatic verification that stream.place is receiving program output
8383+8484+## Best next implementation if needed
8585+8686+Add a small config layer for stream.place ingest values, for example:
8787+8888+- `STREAMPLACE_INGEST_URL`
8989+- `STREAMPLACE_STREAM_KEY`
9090+9191+and document how those feed OBS configuration.
9292+