@holostaff/sdk 0.9.12 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,50 @@
1
+ /**
2
+ * holostaff-avatar (AVTR-1) face — prd-avatar-selfhost.md §5.3.
3
+ *
4
+ * The self-hosted replacement for anamFace. Unlike Anam (text in → native
5
+ * TTS), AVTR-1 is AUDIO-driven: the Realtime model speaks, and we forward its
6
+ * PCM to the avatar service over a control WebSocket. The service returns a
7
+ * lip-synced video+audio LiveKit room — the user hears the AVATAR'S audio
8
+ * track (paced with the video, so lip-sync holds), NOT the Realtime track
9
+ * (which is only forwarded here, through a silent sink).
10
+ *
11
+ * Wire contract (docs/INTEGRATION.md in the service repo):
12
+ * - LiveKit room out: VP8 720x1280 video + Opus audio.
13
+ * - control WS in: {agent.speak, audio:b64 PCM16 24kHz} chunks, bounded by
14
+ * {agent.speak_end}; {agent.interrupt} for barge-in; {listener.audio} for
15
+ * active-listening motion from the user's mic.
16
+ * - WS out: {agent.speak_started|speak_ended} drive the "speaking" UI state.
17
+ *
18
+ * `livekit-client` is an OPTIONAL peer dependency, lazy-loaded only when a
19
+ * holostaff-avatar Stage opens (keeps the base SDK lean — like @anam-ai/js-sdk
20
+ * and rrweb). Resolved via injected module → global UMD → dynamic import.
21
+ */
22
+ export interface AvtrFace {
23
+ /** Forward the Realtime model's audio as the avatar's voice (once). */
24
+ attachRealtimeAudio(remoteStream: MediaStream): Promise<void>;
25
+ /** Feed the user's mic to drive active-listening motion (optional). */
26
+ attachMic(micStream: MediaStream): Promise<void>;
27
+ /** Open a new spoken turn (a fresh speak event id). */
28
+ beginTurn(): void;
29
+ /** Close the current spoken turn. */
30
+ speakEnd(): void;
31
+ /** Barge-in: stop the avatar speaking now and drop the turn. */
32
+ interrupt(): void;
33
+ stop(): void;
34
+ }
35
+ export declare function startAvtrFace(opts: {
36
+ livekitUrl: string;
37
+ livekitToken: string;
38
+ /** Absolute wss:// control-WS URL from the mint. */
39
+ wsUrl: string;
40
+ videoEl: HTMLVideoElement;
41
+ /** <audio> sink for the avatar's (lip-synced) voice track. */
42
+ audioEl: HTMLAudioElement;
43
+ /** Fired once the avatar's video track subscribes (clears first-frame timer). */
44
+ onVideo?: () => void;
45
+ /** speak_started / speak_ended → drive the UI speaking state. */
46
+ onSpeaking?: (speaking: boolean) => void;
47
+ onError?: (err: Error) => void;
48
+ onClosed?: () => void;
49
+ }): Promise<AvtrFace>;
50
+ //# sourceMappingURL=avtrFace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"avtrFace.d.ts","sourceRoot":"","sources":["../../src/stage/avtrFace.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAOH,MAAM,WAAW,QAAQ;IACvB,uEAAuE;IACvE,mBAAmB,CAAC,YAAY,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7D,uEAAuE;IACvE,SAAS,CAAC,SAAS,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAChD,uDAAuD;IACvD,SAAS,IAAI,IAAI,CAAA;IACjB,qCAAqC;IACrC,QAAQ,IAAI,IAAI,CAAA;IAChB,gEAAgE;IAChE,SAAS,IAAI,IAAI,CAAA;IACjB,IAAI,IAAI,IAAI,CAAA;CACb;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,gBAAgB,CAAA;IACzB,8DAA8D;IAC9D,OAAO,EAAE,gBAAgB,CAAA;IACzB,iFAAiF;IACjF,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,iEAAiE;IACjE,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAA;IACxC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAA;IAC9B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;CACtB,GAAG,OAAO,CAAC,QAAQ,CAAC,CA6FpB"}
@@ -0,0 +1,252 @@
1
+ /**
2
+ * holostaff-avatar (AVTR-1) face — prd-avatar-selfhost.md §5.3.
3
+ *
4
+ * The self-hosted replacement for anamFace. Unlike Anam (text in → native
5
+ * TTS), AVTR-1 is AUDIO-driven: the Realtime model speaks, and we forward its
6
+ * PCM to the avatar service over a control WebSocket. The service returns a
7
+ * lip-synced video+audio LiveKit room — the user hears the AVATAR'S audio
8
+ * track (paced with the video, so lip-sync holds), NOT the Realtime track
9
+ * (which is only forwarded here, through a silent sink).
10
+ *
11
+ * Wire contract (docs/INTEGRATION.md in the service repo):
12
+ * - LiveKit room out: VP8 720x1280 video + Opus audio.
13
+ * - control WS in: {agent.speak, audio:b64 PCM16 24kHz} chunks, bounded by
14
+ * {agent.speak_end}; {agent.interrupt} for barge-in; {listener.audio} for
15
+ * active-listening motion from the user's mic.
16
+ * - WS out: {agent.speak_started|speak_ended} drive the "speaking" UI state.
17
+ *
18
+ * `livekit-client` is an OPTIONAL peer dependency, lazy-loaded only when a
19
+ * holostaff-avatar Stage opens (keeps the base SDK lean — like @anam-ai/js-sdk
20
+ * and rrweb). Resolved via injected module → global UMD → dynamic import.
21
+ */
22
+ const TARGET_SR = 24000;
23
+ const SAMPLES_PER_CHUNK = 2400; // ~100ms @ 24kHz — small chunks keep latency low
24
+ /** Reset the service idle timer well inside its 5-min default. */
25
+ const KEEPALIVE_MS = 60000;
26
+ export async function startAvtrFace(opts) {
27
+ // ── 1. LiveKit media (video + avatar audio) ──────────────────────────
28
+ const lk = await loadLiveKit();
29
+ const { Room, RoomEvent, Track } = lk;
30
+ // The avatar publishes exactly one fixed 720p layer — disable adaptive
31
+ // stream / dynacast renegotiation (matches the service SDK's defaults).
32
+ const room = new Room({ adaptiveStream: false, dynacast: false });
33
+ room.on(RoomEvent.TrackSubscribed, (track) => {
34
+ if (track.kind === Track.Kind.Video) {
35
+ track.attach(opts.videoEl);
36
+ opts.onVideo?.();
37
+ }
38
+ else if (track.kind === Track.Kind.Audio) {
39
+ track.attach(opts.audioEl);
40
+ }
41
+ });
42
+ room.on(RoomEvent.Disconnected, () => opts.onClosed?.());
43
+ await room.connect(opts.livekitUrl, opts.livekitToken);
44
+ // ── 2. Control WebSocket (audio in + speak/interrupt events) ─────────
45
+ const ws = new WebSocket(opts.wsUrl);
46
+ let wsOpen = false;
47
+ const outbox = [];
48
+ const wsSend = (obj) => {
49
+ const line = JSON.stringify(obj);
50
+ if (wsOpen && ws.readyState === WebSocket.OPEN) {
51
+ try {
52
+ ws.send(line);
53
+ }
54
+ catch { /* raced closed */ }
55
+ }
56
+ else {
57
+ outbox.push(line);
58
+ }
59
+ };
60
+ ws.addEventListener('open', () => {
61
+ wsOpen = true;
62
+ for (const line of outbox.splice(0)) {
63
+ try {
64
+ ws.send(line);
65
+ }
66
+ catch { /* */ }
67
+ }
68
+ });
69
+ ws.addEventListener('message', (ev) => {
70
+ let msg = {};
71
+ try {
72
+ msg = JSON.parse(ev.data);
73
+ }
74
+ catch {
75
+ return;
76
+ }
77
+ if (msg.type === 'agent.speak_started')
78
+ opts.onSpeaking?.(true);
79
+ else if (msg.type === 'agent.speak_ended')
80
+ opts.onSpeaking?.(false);
81
+ else if (msg.type === 'error')
82
+ opts.onError?.(new Error(`avatar ws: ${ev.data.slice(0, 200)}`));
83
+ });
84
+ ws.addEventListener('close', () => { wsOpen = false; opts.onClosed?.(); });
85
+ ws.addEventListener('error', () => opts.onError?.(new Error('avatar control WS error')));
86
+ const keepAlive = setInterval(() => wsSend({ type: 'session.keep_alive' }), KEEPALIVE_MS);
87
+ // ── 3. Turn/speak state + audio forwarders ───────────────────────────
88
+ let speaking = false;
89
+ let eventId = '';
90
+ let speechFwd = null;
91
+ let micFwd = null;
92
+ const mintEventId = () => `hs-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`;
93
+ return {
94
+ async attachRealtimeAudio(remoteStream) {
95
+ if (speechFwd)
96
+ return;
97
+ speechFwd = new PcmForwarder();
98
+ // Only emit speak frames while a turn is open; between turns the model's
99
+ // track is silent anyway, but gating keeps speak/speak_end well-formed.
100
+ speechFwd.onChunk = (b64) => { if (speaking)
101
+ wsSend({ type: 'agent.speak', audio: b64, event_id: eventId }); };
102
+ await speechFwd.start(remoteStream);
103
+ },
104
+ async attachMic(micStream) {
105
+ if (micFwd)
106
+ return;
107
+ micFwd = new PcmForwarder();
108
+ micFwd.onChunk = (b64) => wsSend({ type: 'listener.audio', audio: b64 });
109
+ await micFwd.start(micStream);
110
+ },
111
+ beginTurn() {
112
+ speaking = true;
113
+ eventId = mintEventId();
114
+ },
115
+ speakEnd() {
116
+ if (!speaking)
117
+ return;
118
+ speaking = false;
119
+ wsSend({ type: 'agent.speak_end', event_id: eventId });
120
+ },
121
+ interrupt() {
122
+ speaking = false;
123
+ wsSend({ type: 'agent.interrupt' });
124
+ },
125
+ stop() {
126
+ speaking = false;
127
+ clearInterval(keepAlive);
128
+ try {
129
+ speechFwd?.stop();
130
+ }
131
+ catch { /* */ }
132
+ try {
133
+ micFwd?.stop();
134
+ }
135
+ catch { /* */ }
136
+ try {
137
+ ws.close(1000, 'stage closed');
138
+ }
139
+ catch { /* */ }
140
+ try {
141
+ void room.disconnect();
142
+ }
143
+ catch { /* */ }
144
+ try {
145
+ opts.videoEl.srcObject = null;
146
+ }
147
+ catch { /* */ }
148
+ try {
149
+ opts.audioEl.srcObject = null;
150
+ }
151
+ catch { /* */ }
152
+ },
153
+ };
154
+ }
155
+ // -------------------------------------------------------------------------
156
+ // PCM forwarder — taps a MediaStream, emits base64 PCM16 24kHz mono chunks.
157
+ // Ported from the widget's AudioForwarder (src/engine/audioForwarder.ts).
158
+ // -------------------------------------------------------------------------
159
+ const WORKLET_CODE = /* js */ `
160
+ class HsPcmProcessor extends AudioWorkletProcessor {
161
+ constructor() { super(); this._buf = new Float32Array(0); this._n = ${SAMPLES_PER_CHUNK} }
162
+ process(inputs) {
163
+ const ch = inputs[0] && inputs[0][0]
164
+ if (!ch) return true
165
+ const nb = new Float32Array(this._buf.length + ch.length)
166
+ nb.set(this._buf); nb.set(ch, this._buf.length); this._buf = nb
167
+ while (this._buf.length >= this._n) {
168
+ const c = this._buf.slice(0, this._n); this._buf = this._buf.slice(this._n)
169
+ this.port.postMessage({ samples: c })
170
+ }
171
+ return true
172
+ }
173
+ }
174
+ registerProcessor('hs-pcm-processor', HsPcmProcessor)
175
+ `;
176
+ class PcmForwarder {
177
+ constructor() {
178
+ this.onChunk = null;
179
+ this.ctx = null;
180
+ this.src = null;
181
+ this.node = null;
182
+ this.started = false;
183
+ }
184
+ async start(stream) {
185
+ if (this.started)
186
+ return;
187
+ // 24kHz context → the Realtime API's native rate; no resample needed, and
188
+ // AVTR-1 downsamples to 16kHz internally for its HuBERT encoder.
189
+ this.ctx = new AudioContext({ sampleRate: TARGET_SR });
190
+ const blob = new Blob([WORKLET_CODE], { type: 'application/javascript' });
191
+ const url = URL.createObjectURL(blob);
192
+ await this.ctx.audioWorklet.addModule(url);
193
+ URL.revokeObjectURL(url);
194
+ this.src = this.ctx.createMediaStreamSource(stream);
195
+ this.node = new AudioWorkletNode(this.ctx, 'hs-pcm-processor');
196
+ this.node.port.onmessage = (e) => {
197
+ const f32 = e.data.samples;
198
+ this.onChunk?.(pcm16Base64(f32));
199
+ };
200
+ // Keep the graph processing without local playback: worklet → muted sink.
201
+ const sink = this.ctx.createGain();
202
+ sink.gain.value = 0;
203
+ this.src.connect(this.node);
204
+ this.node.connect(sink);
205
+ sink.connect(this.ctx.destination);
206
+ this.started = true;
207
+ }
208
+ stop() {
209
+ if (!this.started)
210
+ return;
211
+ try {
212
+ this.node?.disconnect();
213
+ }
214
+ catch { /* */ }
215
+ try {
216
+ this.src?.disconnect();
217
+ }
218
+ catch { /* */ }
219
+ try {
220
+ void this.ctx?.close();
221
+ }
222
+ catch { /* */ }
223
+ this.node = null;
224
+ this.src = null;
225
+ this.ctx = null;
226
+ this.started = false;
227
+ }
228
+ }
229
+ /** Float32 [-1,1] → base64 of Int16-LE PCM. */
230
+ function pcm16Base64(f32) {
231
+ const i16 = new Int16Array(f32.length);
232
+ for (let i = 0; i < f32.length; i++) {
233
+ const s = Math.max(-1, Math.min(1, f32[i] ?? 0));
234
+ i16[i] = s < 0 ? s * 0x8000 : s * 0x7fff;
235
+ }
236
+ const bytes = new Uint8Array(i16.buffer);
237
+ let bin = '';
238
+ for (let i = 0; i < bytes.length; i++)
239
+ bin += String.fromCharCode(bytes[i] ?? 0);
240
+ return btoa(bin);
241
+ }
242
+ async function loadLiveKit() {
243
+ const g = globalThis.LivekitClient;
244
+ if (g)
245
+ return g;
246
+ // @ts-ignore — optional peer dependency; provided by the host app.
247
+ const mod = await import('livekit-client');
248
+ if (!mod?.Room)
249
+ throw new Error('livekit-client not found (install it or load its UMD build)');
250
+ return mod;
251
+ }
252
+ //# sourceMappingURL=avtrFace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"avtrFace.js","sourceRoot":"","sources":["../../src/stage/avtrFace.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/stage/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAkB,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAKzD,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,eAAe,CAAA;IACpB,YAAY,EAAE,MAAM,MAAM,CAAA;IAC1B,SAAS,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACxC,QAAQ,EAAE,eAAe,CAAA;IACzB,uEAAuE;IACvE,OAAO,EAAE,cAAc,GAAG,IAAI,CAAA;IAC9B,IAAI,EAAE,UAAU,CAAA;IAChB,iEAAiE;IACjE,wBAAwB,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAA;CACpD;AAED,MAAM,WAAW,SAAS;IACxB,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IAC5B,KAAK,IAAI,IAAI,CAAA;IACb,MAAM,IAAI,OAAO,CAAA;IACjB;;;;sCAIkC;IAClC,gBAAgB,IAAI,iBAAiB,GAAG,IAAI,CAAA;IAC5C,+DAA+D;IAC/D,gBAAgB,IAAI,IAAI,CAAA;IACxB,OAAO,IAAI,IAAI,CAAA;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,gBAAgB,CAAA;IACvB,2DAA2D;IAC3D,QAAQ,EAAE,OAAO,CAAA;CAClB;AAyBD,wBAAgB,UAAU,CAAC,IAAI,EAAE,SAAS,GAAG,YAAY,CAgLxD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/stage/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAkB,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAMzD,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,eAAe,CAAA;IACpB,YAAY,EAAE,MAAM,MAAM,CAAA;IAC1B,SAAS,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACxC,QAAQ,EAAE,eAAe,CAAA;IACzB,uEAAuE;IACvE,OAAO,EAAE,cAAc,GAAG,IAAI,CAAA;IAC9B,IAAI,EAAE,UAAU,CAAA;IAChB,iEAAiE;IACjE,wBAAwB,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAA;CACpD;AAED,MAAM,WAAW,SAAS;IACxB,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IAC5B,KAAK,IAAI,IAAI,CAAA;IACb,MAAM,IAAI,OAAO,CAAA;IACjB;;;;sCAIkC;IAClC,gBAAgB,IAAI,iBAAiB,GAAG,IAAI,CAAA;IAC5C,+DAA+D;IAC/D,gBAAgB,IAAI,IAAI,CAAA;IACxB,OAAO,IAAI,IAAI,CAAA;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,gBAAgB,CAAA;IACvB,2DAA2D;IAC3D,QAAQ,EAAE,OAAO,CAAA;CAClB;AAsCD,wBAAgB,UAAU,CAAC,IAAI,EAAE,SAAS,GAAG,YAAY,CA2SxD"}
@@ -13,6 +13,7 @@
13
13
  import { postJsonResult } from '../transport.js';
14
14
  import { connectRealtime } from './realtime.js';
15
15
  import { startAnamFace } from './anamFace.js';
16
+ import { startAvtrFace } from './avtrFace.js';
16
17
  import { startStageUi } from './ui.js';
17
18
  const PRESENT_TOOL = {
18
19
  name: 'present',
@@ -35,7 +36,11 @@ export function startStage(deps) {
35
36
  }
36
37
  let open = false;
37
38
  let ui = null;
38
- let face = null;
39
+ let face = null; // provider==='anam'
40
+ let avtr = null; // provider==='holostaff'
41
+ let avatarSessionId = null; // for the voice-stop reap
42
+ let voiceAudioEl = null; // avatar voice + fallback sink
43
+ let firstFrameTimer = null;
39
44
  let realtime = null;
40
45
  let micStream = null;
41
46
  let sentenceBuf = '';
@@ -50,6 +55,10 @@ export function startStage(deps) {
50
55
  const teardown = () => {
51
56
  open = false;
52
57
  deps.reportConversationActive(false);
58
+ if (firstFrameTimer) {
59
+ clearTimeout(firstFrameTimer);
60
+ firstFrameTimer = null;
61
+ }
53
62
  try {
54
63
  realtime?.close();
55
64
  }
@@ -58,16 +67,31 @@ export function startStage(deps) {
58
67
  face?.stop();
59
68
  }
60
69
  catch { /* */ }
70
+ try {
71
+ avtr?.stop();
72
+ }
73
+ catch { /* */ }
74
+ // Release the scarce GPU avatar session server-side (best-effort).
75
+ if (avatarSessionId) {
76
+ void postJsonResult(deps.cfg, `/api/runtime/sessions/${deps.getSessionId()}/voice-stop`, { ...deps.buildBody(), avatarSessionId });
77
+ }
61
78
  try {
62
79
  micStream?.getTracks().forEach(t => t.stop());
63
80
  }
64
81
  catch { /* */ }
82
+ try {
83
+ voiceAudioEl?.remove();
84
+ }
85
+ catch { /* */ }
65
86
  try {
66
87
  ui?.destroy();
67
88
  }
68
89
  catch { /* */ }
69
90
  realtime = null;
70
91
  face = null;
92
+ avtr = null;
93
+ avatarSessionId = null;
94
+ voiceAudioEl = null;
71
95
  micStream = null;
72
96
  ui = null;
73
97
  sentenceBuf = '';
@@ -102,11 +126,18 @@ export function startStage(deps) {
102
126
  return;
103
127
  }
104
128
  const mint = await postJsonResult(deps.cfg, `/api/runtime/sessions/${deps.getSessionId()}/voice`, deps.buildBody());
105
- if (!mint || !mint.ephemeralKey || !mint.anamSessionToken) {
129
+ if (!mint || !mint.ephemeralKey) {
106
130
  reportErr(new Error('voice mint failed or returned incomplete session'));
107
131
  teardown();
108
132
  return;
109
133
  }
134
+ const provider = mint.provider ?? 'anam';
135
+ const faceTokenOk = provider === 'holostaff' ? !!mint.avatar : !!mint.anamSessionToken;
136
+ if (!faceTokenOk) {
137
+ reportErr(new Error('voice mint returned no face session'));
138
+ teardown();
139
+ return;
140
+ }
110
141
  const copilot = deps.presence.getCopilot();
111
142
  ui = startStageUi({
112
143
  dock: deps.dock,
@@ -115,74 +146,182 @@ export function startStage(deps) {
115
146
  onClose: () => close(),
116
147
  });
117
148
  ui.setState('connecting');
149
+ // The present() tool handler is provider-agnostic.
150
+ const onToolCall = ({ name, args, callId }) => {
151
+ if (name === 'present' && deps.theater) {
152
+ const intent = typeof args.intent === 'string' ? args.intent : '';
153
+ const context = typeof args.context === 'string' ? args.context : undefined;
154
+ if (intent)
155
+ deps.theater.present({ intent, context });
156
+ realtime?.sendToolResult(callId, { ok: true });
157
+ }
158
+ else {
159
+ realtime?.sendToolResult(callId, { error: `unknown tool ${name}` });
160
+ }
161
+ };
162
+ const seedMessage = seed?.intent
163
+ ? `The visitor tapped "Talk" on your suggestion: "${seed.intent}". Open the conversation on that.`
164
+ : undefined;
118
165
  try {
119
- face = await startAnamFace({ sessionToken: mint.anamSessionToken, videoEl: ui.video, onError: reportErr });
120
- }
121
- catch (err) {
122
- reportErr(err instanceof Error ? err : new Error('anam connect failed'));
123
- teardown();
124
- return;
125
- }
126
- try {
127
- realtime = await connectRealtime({
128
- ephemeralKey: mint.ephemeralKey,
129
- realtimeUrl: mint.realtimeUrl,
130
- realtimeModel: mint.realtimeModel,
131
- instructions: mint.instructions,
132
- tools: [PRESENT_TOOL],
133
- micStream,
134
- seedMessage: seed?.intent
135
- ? `The visitor tapped "Talk" on your suggestion: "${seed.intent}". Open the conversation on that.`
136
- : undefined,
137
- }, {
138
- onTextDelta: (delta, turnId) => {
139
- lastTurnId = turnId;
140
- // Drop trailing deltas from a turn the user barged in on.
141
- if (turnId === mutedTurnId)
142
- return;
143
- ui?.setState('speaking');
144
- sentenceBuf += delta;
145
- ui?.appendCaption(delta);
146
- flushSentences(false);
147
- },
148
- onTurnDone: (turnId) => {
149
- if (turnId === mutedTurnId) {
150
- mutedTurnId = null;
151
- return;
152
- }
153
- flushSentences(true);
154
- ui?.setState('listening');
155
- },
156
- onUserSpeechStarted: () => {
157
- // Barge-in: mute the in-flight turn, stop generation, stop the
158
- // avatar, drop the half-formed sentence.
159
- mutedTurnId = lastTurnId;
160
- sentenceBuf = '';
161
- realtime?.cancelResponse();
162
- face?.interrupt();
163
- ui?.setState('listening');
164
- },
165
- onToolCall: ({ name, args, callId }) => {
166
- if (name === 'present' && deps.theater) {
167
- const intent = typeof args.intent === 'string' ? args.intent : '';
168
- const context = typeof args.context === 'string' ? args.context : undefined;
169
- if (intent)
170
- deps.theater.present({ intent, context });
171
- realtime?.sendToolResult(callId, { ok: true });
172
- }
173
- else {
174
- realtime?.sendToolResult(callId, { error: `unknown tool ${name}` });
175
- }
176
- },
177
- onError: reportErr,
178
- });
166
+ if (provider === 'holostaff')
167
+ await connectAvtr(mint, seedMessage, onToolCall);
168
+ else
169
+ await connectAnam(mint, seedMessage, onToolCall);
179
170
  ui?.setState('listening');
180
171
  }
181
172
  catch (err) {
182
- reportErr(err instanceof Error ? err : new Error('realtime connect failed'));
173
+ reportErr(err instanceof Error ? err : new Error('voice connect failed'));
183
174
  teardown();
184
175
  }
185
176
  };
177
+ // ── Path A: Anam face (text-mode Realtime → Anam native TTS) ──────────
178
+ const connectAnam = async (mint, seedMessage, onToolCall) => {
179
+ if (!ui || !micStream)
180
+ throw new Error('stage not ready');
181
+ face = await startAnamFace({ sessionToken: mint.anamSessionToken, videoEl: ui.video, onError: reportErr });
182
+ realtime = await connectRealtime({
183
+ ephemeralKey: mint.ephemeralKey,
184
+ realtimeUrl: mint.realtimeUrl,
185
+ realtimeModel: mint.realtimeModel,
186
+ instructions: mint.instructions,
187
+ tools: [PRESENT_TOOL],
188
+ micStream,
189
+ seedMessage,
190
+ }, {
191
+ onTextDelta: (delta, turnId) => {
192
+ lastTurnId = turnId;
193
+ if (turnId === mutedTurnId)
194
+ return; // drop barged-in trailing deltas
195
+ ui?.setState('speaking');
196
+ sentenceBuf += delta;
197
+ ui?.appendCaption(delta);
198
+ flushSentences(false);
199
+ },
200
+ onTurnDone: (turnId) => {
201
+ if (turnId === mutedTurnId) {
202
+ mutedTurnId = null;
203
+ return;
204
+ }
205
+ flushSentences(true);
206
+ ui?.setState('listening');
207
+ },
208
+ onUserSpeechStarted: () => {
209
+ mutedTurnId = lastTurnId;
210
+ sentenceBuf = '';
211
+ realtime?.cancelResponse();
212
+ face?.interrupt();
213
+ ui?.setState('listening');
214
+ },
215
+ onToolCall,
216
+ onError: reportErr,
217
+ });
218
+ };
219
+ // ── holostaff-avatar (audio-mode Realtime → AVTR-1 lip-sync) ──────────
220
+ const connectAvtr = async (mint, seedMessage, onToolCall) => {
221
+ if (!ui || !micStream)
222
+ throw new Error('stage not ready');
223
+ const av = mint.avatar;
224
+ avatarSessionId = av.sessionId;
225
+ // Hidden <audio> sink: carries the avatar's lip-synced voice track
226
+ // normally, and the raw Realtime audio if we degrade to voice-only.
227
+ voiceAudioEl = document.createElement('audio');
228
+ voiceAudioEl.autoplay = true;
229
+ voiceAudioEl.setAttribute('playsinline', '');
230
+ voiceAudioEl.style.display = 'none';
231
+ document.body.appendChild(voiceAudioEl);
232
+ let firstFrame = false;
233
+ let realtimeStream = null;
234
+ const degradeToVoiceOnly = () => {
235
+ if (firstFrame)
236
+ return;
237
+ // LiveKit media blocked (no video in the window) — drop the face and
238
+ // play the Realtime audio directly; the chip/living-portrait is the
239
+ // visual (prd-avatar-selfhost.md §5.4).
240
+ reportErr(new Error('avatar media blocked — continuing voice-only'));
241
+ try {
242
+ avtr?.stop();
243
+ }
244
+ catch { /* */ }
245
+ avtr = null;
246
+ if (realtimeStream && voiceAudioEl) {
247
+ try {
248
+ voiceAudioEl.srcObject = realtimeStream;
249
+ }
250
+ catch { /* */ }
251
+ }
252
+ };
253
+ avtr = await startAvtrFace({
254
+ livekitUrl: av.livekitUrl,
255
+ livekitToken: av.livekitToken,
256
+ wsUrl: av.wsUrl,
257
+ videoEl: ui.video,
258
+ audioEl: voiceAudioEl,
259
+ onVideo: () => {
260
+ firstFrame = true;
261
+ if (firstFrameTimer) {
262
+ clearTimeout(firstFrameTimer);
263
+ firstFrameTimer = null;
264
+ }
265
+ },
266
+ onSpeaking: (sp) => ui?.setState(sp ? 'speaking' : 'listening'),
267
+ onError: reportErr,
268
+ });
269
+ // Guard against UDP-blocked / no-simulcast networks: freeze-not-degrade
270
+ // means the only defense is a first-frame deadline.
271
+ firstFrameTimer = setTimeout(degradeToVoiceOnly, 6000);
272
+ realtime = await connectRealtime({
273
+ ephemeralKey: mint.ephemeralKey,
274
+ realtimeUrl: mint.realtimeUrl,
275
+ realtimeModel: mint.realtimeModel,
276
+ instructions: mint.instructions,
277
+ tools: [PRESENT_TOOL],
278
+ micStream,
279
+ seedMessage,
280
+ audioOut: true,
281
+ voice: mint.voiceId ?? undefined,
282
+ }, {
283
+ onTextDelta: (delta, turnId) => {
284
+ if (turnId !== lastTurnId)
285
+ avtr?.beginTurn(); // open the avatar turn
286
+ lastTurnId = turnId;
287
+ if (turnId === mutedTurnId)
288
+ return;
289
+ ui?.setState('speaking');
290
+ ui?.appendCaption(delta); // captions from the audio transcript
291
+ },
292
+ onTurnDone: (turnId) => {
293
+ if (turnId === mutedTurnId) {
294
+ mutedTurnId = null;
295
+ return;
296
+ }
297
+ avtr?.speakEnd();
298
+ ui?.setState('listening');
299
+ },
300
+ onUserSpeechStarted: () => {
301
+ mutedTurnId = lastTurnId;
302
+ realtime?.cancelResponse();
303
+ avtr?.interrupt();
304
+ ui?.setState('listening');
305
+ },
306
+ onRemoteAudio: (stream) => {
307
+ realtimeStream = stream;
308
+ if (avtr)
309
+ void avtr.attachRealtimeAudio(stream);
310
+ else if (voiceAudioEl) {
311
+ // Already degraded before the track arrived — play it directly.
312
+ try {
313
+ voiceAudioEl.srcObject = stream;
314
+ }
315
+ catch { /* */ }
316
+ }
317
+ },
318
+ onToolCall,
319
+ onError: reportErr,
320
+ });
321
+ // The user's mic drives active-listening motion (head turns, gaze).
322
+ if (avtr)
323
+ void avtr.attachMic(micStream);
324
+ };
186
325
  const close = () => { if (open)
187
326
  teardown(); };
188
327
  let presenterLent = false;
@@ -197,7 +336,8 @@ export function startStage(deps) {
197
336
  close,
198
337
  isOpen: () => open,
199
338
  acquirePresenter() {
200
- if (!open || !ui || !face)
339
+ // Either face drives ui.video; the Theater borrows it the same way.
340
+ if (!open || !ui || (!face && !avtr))
201
341
  return null;
202
342
  const video = ui.detachVideo();
203
343
  // Measure while still in the (visible) sheet — this is the FLIP source.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/stage/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/stage/index.ts"],"names":[],"mappings":"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"}
@@ -2,11 +2,19 @@
2
2
  * Realtime session — P6 (copilot-voice-stage-design.md §1, §2).
3
3
  *
4
4
  * The conversational brain + ears: GPT/Azure Realtime over WebRTC. It
5
- * owns the mic (STT), runs the LLM, does turn-taking / VAD / barge-in,
6
- * and — in **text mode** (modalities: ['text']) — emits TEXT deltas +
7
- * tool calls over the data channel. NO audio output: the spoken voice is
8
- * Anam's native TTS, fed the text (Path A). This is the de-Vue-ified
9
- * port of tutorLM's useWebRTC + useToolDataChannel.
5
+ * owns the mic (STT), runs the LLM, does turn-taking / VAD / barge-in.
6
+ *
7
+ * Two output modes, chosen by `audioOut`:
8
+ * - text mode (default, Anam face): modalities ['text'] emits TEXT
9
+ * deltas; Anam does native TTS from the text (Path A).
10
+ * - audio mode (holostaff-avatar face): modalities ['audio','text'] —
11
+ * the model speaks; its remote audio track (`onRemoteAudio`) is
12
+ * forwarded to the avatar service for lip-sync, and the text deltas
13
+ * (audio transcript) still drive captions + the Theater. The chosen
14
+ * `voice` is the copilot's OpenAI voice — finally audible (it was a
15
+ * no-op in the Anam text path).
16
+ *
17
+ * This is the de-Vue-ified port of tutorLM's useWebRTC + useToolDataChannel.
10
18
  */
11
19
  export interface RealtimeTool {
12
20
  name: string;
@@ -25,6 +33,11 @@ export interface RealtimeConnectOptions {
25
33
  /** When opened from a note's "Talk", seed the opening turn so the
26
34
  * copilot speaks to that suggestion (design §2.3). */
27
35
  seedMessage?: string;
36
+ /** holostaff-avatar path: have the model SPEAK (audio modality) so its
37
+ * audio can be forwarded to the avatar service. Default false (Anam). */
38
+ audioOut?: boolean;
39
+ /** OpenAI voice for audio mode (copilot's voiceId). Ignored in text mode. */
40
+ voice?: string;
28
41
  }
29
42
  export interface RealtimeCallbacks {
30
43
  /** A text delta from the model (sentence-chunk → Anam). */
@@ -39,6 +52,8 @@ export interface RealtimeCallbacks {
39
52
  args: Record<string, unknown>;
40
53
  callId: string;
41
54
  }): void;
55
+ /** Audio mode only: the model's remote audio track (forward to the avatar). */
56
+ onRemoteAudio?(stream: MediaStream): void;
42
57
  onError(err: Error): void;
43
58
  }
44
59
  export interface RealtimeSession {
@@ -1 +1 @@
1
- {"version":3,"file":"realtime.d.ts","sourceRoot":"","sources":["../../src/stage/realtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACpC;AAED,MAAM,WAAW,sBAAsB;IACrC,YAAY,EAAE,MAAM,CAAA;IACpB,6CAA6C;IAC7C,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,yEAAyE;IACzE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,KAAK,EAAE,YAAY,EAAE,CAAA;IACrB,SAAS,EAAE,WAAW,CAAA;IACtB;2DACuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,2DAA2D;IAC3D,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IAChD,6DAA6D;IAC7D,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,gEAAgE;IAChE,mBAAmB,IAAI,IAAI,CAAA;IAC3B,gCAAgC;IAChC,UAAU,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IACvF,OAAO,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,CAAA;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAAA;IACrD,yEAAyE;IACzE,cAAc,IAAI,IAAI,CAAA;IACtB,KAAK,IAAI,IAAI,CAAA;CACd;AAED,wBAAsB,eAAe,CACnC,IAAI,EAAE,sBAAsB,EAC5B,EAAE,EAAE,iBAAiB,GACpB,OAAO,CAAC,eAAe,CAAC,CA8H1B"}
1
+ {"version":3,"file":"realtime.d.ts","sourceRoot":"","sources":["../../src/stage/realtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACpC;AAED,MAAM,WAAW,sBAAsB;IACrC,YAAY,EAAE,MAAM,CAAA;IACpB,6CAA6C;IAC7C,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,yEAAyE;IACzE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,KAAK,EAAE,YAAY,EAAE,CAAA;IACrB,SAAS,EAAE,WAAW,CAAA;IACtB;2DACuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;8EAC0E;IAC1E,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,2DAA2D;IAC3D,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IAChD,6DAA6D;IAC7D,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,gEAAgE;IAChE,mBAAmB,IAAI,IAAI,CAAA;IAC3B,gCAAgC;IAChC,UAAU,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IACvF,+EAA+E;IAC/E,aAAa,CAAC,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAA;IACzC,OAAO,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,CAAA;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAAA;IACrD,yEAAyE;IACzE,cAAc,IAAI,IAAI,CAAA;IACtB,KAAK,IAAI,IAAI,CAAA;CACd;AAED,wBAAsB,eAAe,CACnC,IAAI,EAAE,sBAAsB,EAC5B,EAAE,EAAE,iBAAiB,GACpB,OAAO,CAAC,eAAe,CAAC,CAkJ1B"}
@@ -2,17 +2,32 @@
2
2
  * Realtime session — P6 (copilot-voice-stage-design.md §1, §2).
3
3
  *
4
4
  * The conversational brain + ears: GPT/Azure Realtime over WebRTC. It
5
- * owns the mic (STT), runs the LLM, does turn-taking / VAD / barge-in,
6
- * and — in **text mode** (modalities: ['text']) — emits TEXT deltas +
7
- * tool calls over the data channel. NO audio output: the spoken voice is
8
- * Anam's native TTS, fed the text (Path A). This is the de-Vue-ified
9
- * port of tutorLM's useWebRTC + useToolDataChannel.
5
+ * owns the mic (STT), runs the LLM, does turn-taking / VAD / barge-in.
6
+ *
7
+ * Two output modes, chosen by `audioOut`:
8
+ * - text mode (default, Anam face): modalities ['text'] emits TEXT
9
+ * deltas; Anam does native TTS from the text (Path A).
10
+ * - audio mode (holostaff-avatar face): modalities ['audio','text'] —
11
+ * the model speaks; its remote audio track (`onRemoteAudio`) is
12
+ * forwarded to the avatar service for lip-sync, and the text deltas
13
+ * (audio transcript) still drive captions + the Theater. The chosen
14
+ * `voice` is the copilot's OpenAI voice — finally audible (it was a
15
+ * no-op in the Anam text path).
16
+ *
17
+ * This is the de-Vue-ified port of tutorLM's useWebRTC + useToolDataChannel.
10
18
  */
11
19
  export async function connectRealtime(opts, cb) {
12
20
  const pc = new RTCPeerConnection();
13
- // Mic in (STT). No remote audio track is consumed text mode.
21
+ // Mic in (STT) sendrecv, so in audio mode the model's voice returns on
22
+ // the same transceiver (text mode simply never gets a remote track).
14
23
  for (const track of opts.micStream.getAudioTracks())
15
24
  pc.addTrack(track, opts.micStream);
25
+ if (opts.audioOut) {
26
+ pc.addEventListener('track', (ev) => {
27
+ if (ev.track.kind === 'audio' && ev.streams[0])
28
+ cb.onRemoteAudio?.(ev.streams[0]);
29
+ });
30
+ }
16
31
  const dc = pc.createDataChannel('oai-events');
17
32
  let turnId = mintTurnId();
18
33
  const send = (obj) => {
@@ -28,7 +43,8 @@ export async function connectRealtime(opts, cb) {
28
43
  send({
29
44
  type: 'session.update',
30
45
  session: {
31
- modalities: ['text'],
46
+ modalities: opts.audioOut ? ['audio', 'text'] : ['text'],
47
+ ...(opts.audioOut && opts.voice ? { voice: opts.voice } : {}),
32
48
  ...(opts.instructions ? { instructions: opts.instructions } : {}),
33
49
  tools: opts.tools.map(t => ({
34
50
  type: 'function',
@@ -67,14 +83,19 @@ export async function connectRealtime(opts, cb) {
67
83
  });
68
84
  const handleServerEvent = (msg) => {
69
85
  switch (msg.type) {
70
- // Text deltas — naming varies across Realtime versions.
86
+ // Text deltas — naming varies across Realtime versions. In audio mode
87
+ // the spoken words arrive as the audio transcript; treat both the same
88
+ // (captions + Theater work identically, avatar lip-sync is driven by
89
+ // the audio track, not this text).
71
90
  case 'response.text.delta':
72
91
  case 'response.output_text.delta':
92
+ case 'response.audio_transcript.delta':
73
93
  if (typeof msg.delta === 'string')
74
94
  cb.onTextDelta(msg.delta, turnId);
75
95
  break;
76
96
  case 'response.text.done':
77
97
  case 'response.output_text.done':
98
+ case 'response.audio_transcript.done':
78
99
  case 'response.done':
79
100
  cb.onTurnDone(turnId);
80
101
  turnId = mintTurnId();
@@ -105,7 +126,14 @@ export async function connectRealtime(opts, cb) {
105
126
  const offer = await pc.createOffer();
106
127
  await pc.setLocalDescription(offer);
107
128
  await waitForIceGathering(pc);
108
- const sdpRes = await fetch(`${opts.realtimeUrl}?model=${encodeURIComponent(opts.realtimeModel)}`, {
129
+ // The GA WebRTC endpoints (OpenAI …/v1/realtime/calls, Azure …/openai/v1/realtime/calls)
130
+ // take NO query params — the model is baked into the ephemeral token's session
131
+ // config. Only the legacy preview endpoint (…/v1/realtime) needs ?model=.
132
+ const isGaCalls = /\/realtime\/calls(?:\?|$)/i.test(opts.realtimeUrl);
133
+ const sdpUrl = isGaCalls
134
+ ? opts.realtimeUrl
135
+ : `${opts.realtimeUrl}?model=${encodeURIComponent(opts.realtimeModel)}`;
136
+ const sdpRes = await fetch(sdpUrl, {
109
137
  method: 'POST',
110
138
  headers: {
111
139
  Authorization: `Bearer ${opts.ephemeralKey}`,
@@ -1 +1 @@
1
- {"version":3,"file":"realtime.js","sourceRoot":"","sources":["../../src/stage/realtime.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"realtime.js","sourceRoot":"","sources":["../../src/stage/realtime.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@holostaff/sdk",
3
- "version": "0.9.12",
3
+ "version": "0.10.0",
4
4
  "description": "Holostaff SDK — lifetime identity, stage detection, custom signal probes, and the living-portrait presence layer (chip, note, Theater, voice Stage) for the Holostaff runtime.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://docs.holostaff.ai",
@@ -43,11 +43,15 @@
43
43
  "rrweb": "^2.0.0-alpha.4"
44
44
  },
45
45
  "peerDependencies": {
46
- "@anam-ai/js-sdk": ">=3"
46
+ "@anam-ai/js-sdk": ">=3",
47
+ "livekit-client": ">=2"
47
48
  },
48
49
  "peerDependenciesMeta": {
49
50
  "@anam-ai/js-sdk": {
50
51
  "optional": true
52
+ },
53
+ "livekit-client": {
54
+ "optional": true
51
55
  }
52
56
  }
53
57
  }