@shogo-ai/voice 1.4.1

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.
Files changed (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +30 -0
  3. package/dist/chunk-D2EVSUZX.js +27 -0
  4. package/dist/chunk-Q3TJAJ54.js +165 -0
  5. package/dist/chunk-QHDIEE7O.js +453 -0
  6. package/dist/chunk-S3S2RNO6.js +671 -0
  7. package/dist/chunk-ZGYHDC5G.js +423 -0
  8. package/dist/index.cjs +1316 -0
  9. package/dist/index.d.cts +432 -0
  10. package/dist/index.d.ts +432 -0
  11. package/dist/index.js +735 -0
  12. package/dist/native/index.cjs +1667 -0
  13. package/dist/native/index.d.cts +285 -0
  14. package/dist/native/index.d.ts +285 -0
  15. package/dist/native/index.js +949 -0
  16. package/dist/organicParticlesShaders-DIva0vBO.d.cts +693 -0
  17. package/dist/organicParticlesShaders-DIva0vBO.d.ts +693 -0
  18. package/dist/react/index.cjs +1670 -0
  19. package/dist/react/index.d.cts +423 -0
  20. package/dist/react/index.d.ts +423 -0
  21. package/dist/react/index.js +952 -0
  22. package/dist/route/agent.cjs +981 -0
  23. package/dist/route/agent.d.cts +20 -0
  24. package/dist/route/agent.d.ts +20 -0
  25. package/dist/route/agent.js +17 -0
  26. package/dist/route/audio-tags.cjs +975 -0
  27. package/dist/route/audio-tags.d.cts +16 -0
  28. package/dist/route/audio-tags.d.ts +16 -0
  29. package/dist/route/audio-tags.js +13 -0
  30. package/dist/route/index.cjs +987 -0
  31. package/dist/route/index.d.cts +115 -0
  32. package/dist/route/index.d.ts +115 -0
  33. package/dist/route/index.js +12 -0
  34. package/dist/route/signed-url.cjs +975 -0
  35. package/dist/route/signed-url.d.cts +12 -0
  36. package/dist/route/signed-url.d.ts +12 -0
  37. package/dist/route/signed-url.js +13 -0
  38. package/dist/route/tts-preview.cjs +975 -0
  39. package/dist/route/tts-preview.d.cts +17 -0
  40. package/dist/route/tts-preview.d.ts +17 -0
  41. package/dist/route/tts-preview.js +13 -0
  42. package/dist/server.cjs +999 -0
  43. package/dist/server.d.cts +88 -0
  44. package/dist/server.d.ts +88 -0
  45. package/dist/server.js +11 -0
  46. package/dist/types-BKJtOUbE.d.cts +352 -0
  47. package/dist/types-BKJtOUbE.d.ts +352 -0
  48. package/package.json +148 -0
@@ -0,0 +1,423 @@
1
+ import { B as BaseVoiceConversationOptions, a as BaseVoiceConversationResult, b as BaseChatConversationOptions, c as BaseChatConversationResult, O as OrganicSphereConfig, d as OrganicParticlesConfig } from '../organicParticlesShaders-DIva0vBO.js';
2
+ export { e as BandReactivity, C as ChatClientToolFn, f as ChatConversationStatus, g as ChatToolDescriptor, D as DEFAULT_ORGANIC_PARTICLES_CONFIG, h as DEFAULT_ORGANIC_SPHERE_CONFIG, i as ORGANIC_PARTICLES_FRAGMENT_SHADER, j as ORGANIC_PARTICLES_VERTEX_SHADER, k as ORGANIC_SPHERE_FRAGMENT_SHADER, l as ORGANIC_SPHERE_VERTEX_SHADER, P as PERLIN_4D, r as resolveOrganicParticlesConfig, m as resolveOrganicSphereConfig } from '../organicParticlesShaders-DIva0vBO.js';
3
+ import * as React from 'react';
4
+ import React__default from 'react';
5
+ import * as react_jsx_runtime from 'react/jsx-runtime';
6
+ import 'ai';
7
+
8
+ /**
9
+ * `useVoiceConversation` (web) — drop-in React hook wrapping
10
+ * `@elevenlabs/react`'s `useConversation` with batteries included:
11
+ *
12
+ * 1. Fetches a signed URL from the consumer's server (default: `/api/voice/signed-url`).
13
+ * 2. Registers the canonical `add_memory` client tool (POST-es to `/api/memory/add`).
14
+ * 3. Auto-injects relevant memory as a contextual update on each user message
15
+ * (POST `/api/memory/retrieve`).
16
+ * 4. Accumulates a plain-text transcript and calls `onTranscript` on disconnect,
17
+ * plus a `pagehide` `navigator.sendBeacon` fallback so nothing is lost on
18
+ * tab close.
19
+ *
20
+ * Consumers can mix in additional `clientTools` and override every path.
21
+ *
22
+ * Requires the caller's app to have `@elevenlabs/react` installed (optional
23
+ * peer dependency). For React Native, import from
24
+ * `@shogo-ai/sdk/voice/native` instead.
25
+ */
26
+
27
+ type UseVoiceConversationOptions = BaseVoiceConversationOptions;
28
+ type UseVoiceConversationResult = BaseVoiceConversationResult;
29
+ /**
30
+ * Hook that owns the voice session lifecycle end-to-end. See module docblock
31
+ * for the wire format of the various server endpoints.
32
+ */
33
+ declare function useVoiceConversation(options: UseVoiceConversationOptions): UseVoiceConversationResult;
34
+
35
+ /**
36
+ * `useShogoVoice` — zero-config voice hook for generated pod apps.
37
+ *
38
+ * This is a thin alias around {@link useVoiceConversation} with the
39
+ * pod-friendly defaults pre-applied:
40
+ *
41
+ * - `characterName: 'Shogo'`
42
+ * - `signedUrlPath: '/api/voice/signed-url'` — served same-origin by
43
+ * the app's own Hono/Next route, which in turn proxies through the
44
+ * Shogo API via the pod's runtime token. No API key is read by the
45
+ * browser and no `Authorization` header is sent — the pod handles
46
+ * auth server-side.
47
+ * - `fetchCredentials: 'same-origin'`
48
+ *
49
+ * Provider requirement
50
+ * --------------------
51
+ * `@elevenlabs/react` ≥ 1.1 requires every `useConversation` caller —
52
+ * which includes this hook — to live under a `<ConversationProvider>`
53
+ * ancestor. The SDK re-exports that provider as `<ShogoVoiceProvider>`
54
+ * so consumer apps don't have to import from `@elevenlabs/react`
55
+ * directly. Without the provider you'll get:
56
+ *
57
+ * useRegisterCallbacks must be used within a ConversationProvider
58
+ *
59
+ * Mount the provider once near the root of your app (NOT around each
60
+ * component individually — sibling voice components only share session
61
+ * state when they live under the same provider, so mounting separate
62
+ * providers around `<VoiceButton>` and `<VoiceSphere>` will give them
63
+ * disconnected sessions and the sphere will never visualize the
64
+ * button's audio).
65
+ *
66
+ * For third-party / external embeds (not pod-native), keep using
67
+ * `useVoiceConversation({ shogoApiKey, projectId })` — the bearer path
68
+ * is the correct choice when same-origin fetch can't reach the Shogo
69
+ * API directly. The provider requirement is the same.
70
+ *
71
+ * @example Minimum viable usage
72
+ * ```tsx
73
+ * import {
74
+ * ShogoVoiceProvider,
75
+ * useShogoVoice,
76
+ * } from '@shogo-ai/sdk/voice/react'
77
+ *
78
+ * function VoiceButton() {
79
+ * const { start, end, status } = useShogoVoice()
80
+ * const active = status === 'connected' || status === 'connecting'
81
+ * return (
82
+ * <button onClick={active ? end : start}>
83
+ * {active ? 'End call' : 'Talk to Shogo'}
84
+ * </button>
85
+ * )
86
+ * }
87
+ *
88
+ * export default function App() {
89
+ * return (
90
+ * <ShogoVoiceProvider>
91
+ * <VoiceButton />
92
+ * </ShogoVoiceProvider>
93
+ * )
94
+ * }
95
+ * ```
96
+ *
97
+ * @example Named secondary agents
98
+ * Declare additional agents in `shogo.config.json#agents`, run
99
+ * `bunx shogo deploy`, then pick which one a component talks to via
100
+ * `agentName`. Both `useShogoVoice({ agentName: 'architect' })` and
101
+ * `useShogoChat({ agentName: 'architect' })` resolve to the SAME
102
+ * `ProjectAgent` row, so voice + text can share one persona /
103
+ * tool-allowlist.
104
+ *
105
+ * ```jsonc
106
+ * // shogo.config.json
107
+ * {
108
+ * "agents": {
109
+ * "architect": {
110
+ * "systemPrompt": "You design system architectures.",
111
+ * "tools": ["lookup_user"],
112
+ * "model": "claude-sonnet-4-5"
113
+ * },
114
+ * "narrator": {
115
+ * "systemPrompt": "You narrate system events out loud.",
116
+ * "voiceId": "voice_id_here",
117
+ * "firstMessage": "Hi, I'll narrate updates."
118
+ * }
119
+ * }
120
+ * }
121
+ * ```
122
+ *
123
+ * ```tsx
124
+ * function NarratorButton() {
125
+ * const v = useShogoVoice({ agentName: 'narrator' })
126
+ * return <button onClick={v.start}>Start narration</button>
127
+ * }
128
+ * ```
129
+ *
130
+ * Tool contract: the manifest declares the tools the agent is allowed
131
+ * to invoke — including the full `description` + JSON `inputSchema`
132
+ * for each — and the consumer's React code provides the matching
133
+ * handler implementations via `clientTools`. Manifest schemas win
134
+ * server-side, so a `shogo deploy` is a single source of truth for
135
+ * BOTH ElevenLabs (voice) AND `streamText` (chat).
136
+ *
137
+ * @example Per-user dynamic variables
138
+ * Surface fields from your own `Companion` row to the agent prompt
139
+ * via `dynamicVariables`. The values land in EL as
140
+ * `dynamic_variables` and the agent prompt can reference them via
141
+ * `{{user_display_name}}` etc. (assuming the variables are declared
142
+ * on the agent in `dynamic_variable_placeholders` at deploy time).
143
+ *
144
+ * The SDK's built-ins (`character_name`, `user_context`,
145
+ * `conversation_id`) always win on collision so you can't
146
+ * accidentally override them.
147
+ *
148
+ * ```tsx
149
+ * function NarratorButton() {
150
+ * const companion = useCompanion() // your store
151
+ * const v = useShogoVoice({
152
+ * agentName: 'narrator',
153
+ * dynamicVariables: {
154
+ * user_display_name: companion.userDisplayName,
155
+ * relationship_stage: companion.relationshipStage,
156
+ * greeting_token: companion.firstMessage ?? '',
157
+ * },
158
+ * })
159
+ * return <button onClick={v.start}>Start narration</button>
160
+ * }
161
+ * ```
162
+ */
163
+
164
+ type UseShogoVoiceOptions = Partial<UseVoiceConversationOptions>;
165
+ declare function useShogoVoice(opts?: UseShogoVoiceOptions): UseVoiceConversationResult;
166
+
167
+ /**
168
+ * `useChatConversation` (web) — text-only sibling of
169
+ * {@link useVoiceConversation}.
170
+ *
171
+ * Wraps `@ai-sdk/react`'s `useChat` hook, pointed at a Shogo streaming
172
+ * chat endpoint (default `/api/chat/turn`). The same agent persona +
173
+ * memory + project context the voice hook drives over an ElevenLabs
174
+ * Convai websocket is reachable here over a plain HTTPS POST + SSE
175
+ * stream — no microphone, no `getUserMedia`, no audio context.
176
+ *
177
+ * Why a sibling instead of a flag on `useVoiceConversation`: the wire
178
+ * shapes are different enough (no signed URL, no audio frames, no
179
+ * `firstMessage`/`characterName` dynamic variables, no `setMuted`)
180
+ * that a single hook would have a surface area split-brain. The auth
181
+ * surface (`shogoApiKey` + `projectId` or session cookie) is shared
182
+ * verbatim, and `BaseChatConversationOptions.conversationId` lines up
183
+ * with the new `BaseVoiceConversationResult.conversationId` so a
184
+ * consumer can stitch a single logical conversation across both
185
+ * transports — see `packages/sdk/README.md` §"Voice + text bridge".
186
+ *
187
+ * Streaming + tool-calls
188
+ * ----------------------
189
+ * The server declares any caller-registered tools WITHOUT an `execute`
190
+ * function, so each tool call is streamed back to the client as a
191
+ * `tool-call` UI part. The hook resolves it by running the matching
192
+ * entry from `clientTools`, then forwards the result via
193
+ * `addToolOutput`. The wire pattern matches the existing internal
194
+ * `useTranslatorChat` (apps/mobile) — see that file for a longer
195
+ * walk-through of the AI-SDK callback flow.
196
+ *
197
+ * Provider requirement
198
+ * --------------------
199
+ * No provider required. Unlike `useVoiceConversation`, this hook
200
+ * doesn't depend on `@elevenlabs/react`'s `ConversationProvider`.
201
+ *
202
+ * Consumers should still mount `<ShogoVoiceProvider>` near the root
203
+ * if they're ALSO using `useShogoVoice`; that's the voice-side
204
+ * requirement and is unrelated to the chat path.
205
+ *
206
+ * Requires the host app to install `@ai-sdk/react` and `ai` as
207
+ * peer deps; both are optional from the SDK's perspective.
208
+ *
209
+ * @experimental V1 surface — shape may evolve before promotion.
210
+ */
211
+
212
+ type UseChatConversationOptions = BaseChatConversationOptions;
213
+ type UseChatConversationResult = BaseChatConversationResult;
214
+ /**
215
+ * Hook that owns the text-chat session lifecycle end-to-end.
216
+ *
217
+ * Returns the message list plus imperative helpers (`sendMessage`,
218
+ * `setMessages`, `appendAssistantMessage`, `appendUserMessage`) and
219
+ * the AI-SDK status. State management is in-memory only — for durable
220
+ * threads, persist `messages` yourself (e.g. on `status === 'ready'`)
221
+ * and rehydrate via `setMessages(...)` on next mount.
222
+ */
223
+ declare function useChatConversation(options?: UseChatConversationOptions): UseChatConversationResult;
224
+
225
+ /**
226
+ * `useShogoChat` — zero-config text-chat hook for generated pod apps.
227
+ *
228
+ * Thin alias around {@link useChatConversation} with the pod-friendly
229
+ * defaults pre-applied:
230
+ *
231
+ * - `api: '/api/chat/turn'` — served same-origin by the app's own
232
+ * Hono/Next route, which proxies through the Shogo API via the
233
+ * pod's runtime token. No API key is read by the browser.
234
+ * - `fetchCredentials: 'same-origin'`
235
+ *
236
+ * For external / third-party SDK consumers, drive
237
+ * `useChatConversation({ shogoApiKey, projectId, ... })` directly —
238
+ * the bearer path is the right choice when the chat endpoint can't
239
+ * be reached same-origin.
240
+ *
241
+ * @example Minimum viable usage
242
+ * ```tsx
243
+ * import { useShogoChat } from '@shogo-ai/sdk/voice/react'
244
+ *
245
+ * function ChatBox() {
246
+ * const { messages, sendMessage, status } = useShogoChat()
247
+ * const [draft, setDraft] = useState('')
248
+ * return (
249
+ * <>
250
+ * {messages.map((m) => <div key={m.id}>{m.parts.map(p => p.type === 'text' ? p.text : '').join('')}</div>)}
251
+ * <input value={draft} onChange={(e) => setDraft(e.target.value)} />
252
+ * <button onClick={() => { void sendMessage(draft); setDraft('') }} disabled={status === 'streaming'}>
253
+ * Send
254
+ * </button>
255
+ * </>
256
+ * )
257
+ * }
258
+ * ```
259
+ *
260
+ * @example Named secondary agents
261
+ * Pass `agentName` to drive a project-specific persona declared in
262
+ * `shogo.config.json#agents` and reconciled to the cloud via
263
+ * `bunx shogo deploy`. Voice + text share one row per name — the
264
+ * same `agentName` reaches the same record from
265
+ * `useShogoVoice({ agentName })`.
266
+ *
267
+ * ```tsx
268
+ * function ArchitectChat() {
269
+ * const chat = useShogoChat({ agentName: 'architect' })
270
+ * // ...
271
+ * }
272
+ * ```
273
+ *
274
+ * Tool contract: the manifest's `tools: [...]` list is the
275
+ * server-enforced allowlist. The hook's `clientTools` map holds the
276
+ * matching handler implementations. Tools the hook registers that
277
+ * aren't on the manifest's allowlist are silently dropped server-
278
+ * side.
279
+ *
280
+ * @example Voice + text bridge (the customer use case)
281
+ * ```tsx
282
+ * const voice = useShogoVoice({ shogoApiKey, projectId })
283
+ * const chat = useShogoChat({
284
+ * shogoApiKey,
285
+ * projectId,
286
+ * conversationId: voice.conversationId ?? undefined,
287
+ * })
288
+ *
289
+ * // When the user types while voice is active, mirror it as
290
+ * // contextual input to the live voice agent rather than going
291
+ * // through the LLM:
292
+ * async function send(text) {
293
+ * if (voice.status === 'connected') {
294
+ * voice.sendContextualUpdate(text)
295
+ * chat.appendUserMessage(text) // local-only echo for the bubble
296
+ * return
297
+ * }
298
+ * await chat.sendMessage(text)
299
+ * }
300
+ *
301
+ * // When the voice agent speaks, mirror it into the text thread:
302
+ * useShogoVoice({
303
+ * onMessage: ({ source, message }) => {
304
+ * if (source === 'agent') chat.appendAssistantMessage(message)
305
+ * },
306
+ * })
307
+ * ```
308
+ *
309
+ * @experimental V1 surface — shape may evolve before promotion.
310
+ */
311
+
312
+ type UseShogoChatOptions = Partial<UseChatConversationOptions>;
313
+ declare function useShogoChat(opts?: UseShogoChatOptions): UseChatConversationResult;
314
+
315
+ /**
316
+ * `ShogoVoiceProvider` — root provider that every `useShogoVoice` /
317
+ * `useVoiceConversation` caller needs to live under.
318
+ *
319
+ * Why this exists
320
+ * ---------------
321
+ * `@elevenlabs/react` ≥ 1.1 split `useConversation` into a
322
+ * provider-backed API: every caller of the hook (and therefore every
323
+ * caller of our `useVoiceConversation` / `useShogoVoice` wrapper) must
324
+ * have a `<ConversationProvider>` somewhere above it in the tree.
325
+ * Without it the underlying `useRegisterCallbacks` throws:
326
+ *
327
+ * useRegisterCallbacks must be used within a ConversationProvider
328
+ *
329
+ * Re-exporting the provider here keeps consumer code free of a direct
330
+ * `@elevenlabs/react` import — pods only ever import from
331
+ * `@shogo-ai/sdk/voice/react`, which means we can swap providers (or
332
+ * upgrade across breaking versions) without touching every app.
333
+ *
334
+ * Usage
335
+ * -----
336
+ * Wrap the SDK's voice-aware tree once, near the root of your app:
337
+ *
338
+ * ```tsx
339
+ * import { ShogoVoiceProvider } from '@shogo-ai/sdk/voice/react'
340
+ *
341
+ * export default function Root({ children }: { children: React.ReactNode }) {
342
+ * return <ShogoVoiceProvider>{children}</ShogoVoiceProvider>
343
+ * }
344
+ * ```
345
+ *
346
+ * One provider is enough for an entire app — sibling components that
347
+ * use the voice hook share the same underlying convai session context.
348
+ * Mounting multiple providers is supported but isolates their
349
+ * sessions, so do that intentionally (e.g. two completely separate
350
+ * voice surfaces in one shell).
351
+ */
352
+
353
+ interface ShogoVoiceProviderProps {
354
+ children: React.ReactNode;
355
+ }
356
+ declare function ShogoVoiceProvider(props: ShogoVoiceProviderProps): React.ReactElement;
357
+
358
+ interface OrganicSphereProps {
359
+ /**
360
+ * Returns the current agent-output frequency buffer (length = fftSize,
361
+ * values 0–255). Typically `useVoiceConversation().getOutputByteFrequencyData`.
362
+ *
363
+ * Can also be pointed at `analyserNode.getByteFrequencyData` from any
364
+ * WebAudio graph for non-ElevenLabs callers.
365
+ */
366
+ getFrequencyData?: () => Uint8Array | null;
367
+ /**
368
+ * Whether audio is live. When `false` the sphere settles into its
369
+ * idle pose (no pulsing). Purely cosmetic — the component keeps the
370
+ * render loop running either way.
371
+ *
372
+ * @default true
373
+ */
374
+ active?: boolean;
375
+ /**
376
+ * Full configuration object (partial). Any unspecified keys fall back
377
+ * to `DEFAULT_ORGANIC_SPHERE_CONFIG`. Individual convenience props
378
+ * below (e.g. `lightAColor`) take precedence over the same key inside
379
+ * `config`, so you can combine a base preset with a single override.
380
+ */
381
+ config?: Partial<OrganicSphereConfig>;
382
+ /** Overrides `config.lightAColor`. */
383
+ lightAColor?: string;
384
+ /** Overrides `config.lightBColor`. */
385
+ lightBColor?: string;
386
+ /** Overrides `config.rimColor`. */
387
+ rimColor?: string;
388
+ /** Overrides `config.rimThreshold`. */
389
+ rimThreshold?: number;
390
+ /** Overrides `config.rimPower`. */
391
+ rimPower?: number;
392
+ /** Overrides `config.backgroundColor`. */
393
+ backgroundColor?: string | null;
394
+ /** Overrides `config.subdivisions` (re-init on change). */
395
+ subdivisions?: number;
396
+ /** Overrides `config.maxPixelRatio` (re-init on change). */
397
+ maxPixelRatio?: number;
398
+ /**
399
+ * Extra classes merged onto the wrapping `<div>`. Size the parent
400
+ * element; the canvas fills it.
401
+ */
402
+ className?: string;
403
+ /** Inline style override for the wrapping `<div>`. */
404
+ style?: React__default.CSSProperties;
405
+ }
406
+ /**
407
+ * Audio-reactive organic sphere. See the module docblock for usage.
408
+ */
409
+ declare function OrganicSphere({ getFrequencyData, active, config: configProp, lightAColor, lightBColor, rimColor, rimThreshold, rimPower, backgroundColor, subdivisions, maxPixelRatio, className, style, }: OrganicSphereProps): react_jsx_runtime.JSX.Element;
410
+
411
+ interface OrganicParticlesProps {
412
+ getFrequencyData?: () => Uint8Array | null;
413
+ active?: boolean;
414
+ config?: Partial<OrganicParticlesConfig>;
415
+ className?: string;
416
+ style?: React__default.CSSProperties;
417
+ }
418
+ /**
419
+ * Audio-reactive particle cloud. See the module docblock for usage.
420
+ */
421
+ declare function OrganicParticles({ getFrequencyData, active, config: configProp, className, style, }: OrganicParticlesProps): react_jsx_runtime.JSX.Element;
422
+
423
+ export { BaseChatConversationOptions, BaseChatConversationResult, OrganicParticles, OrganicParticlesConfig, type OrganicParticlesProps, OrganicSphere, OrganicSphereConfig, type OrganicSphereProps, ShogoVoiceProvider, type ShogoVoiceProviderProps, type UseChatConversationOptions, type UseChatConversationResult, type UseShogoChatOptions, type UseShogoVoiceOptions, type UseVoiceConversationOptions, type UseVoiceConversationResult, useChatConversation, useShogoChat, useShogoVoice, useVoiceConversation };