@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,432 @@
1
+ import { E as Expressivity } from './types-BKJtOUbE.cjs';
2
+ export { A as AUDIO_TAGS, a as AUDIO_TAG_GROUPS, b as AudioTag, c as AudioTagGroup, C as CONVAI_SUPPORTED_TTS_MODELS, d as CONVAI_TTS_MODEL_FALLBACK, e as Companion, f as CompanionStore, g as ConvaiClientTool, h as CreateAgentParams, i as CreateCompanionBody, D as DEFAULT_ALLOWED_TAGS, j as DEFAULT_ELEVENLABS_BASE_URL, k as DEFAULT_VOICE_SETTINGS, l as EXPRESSIVITY_BLOCK_CLOSE, m as EXPRESSIVITY_BLOCK_OPEN, n as EXPRESSIVITY_OPTIONS, o as ElevenLabsApiError, p as ElevenLabsClient, q as ElevenLabsClientConfig, M as MEMORY_CLIENT_TOOLS, P as PatchAgentParams, r as PatchCompanionBody, T as TextToSpeechParams, s as TtsPreviewBody, V as VoiceMemoryStore, t as VoiceSettings, u as VoiceUser, v as buildPreviewLine, w as composeExpressivityBlock, x as normalizeAudioTags, y as normalizeExpressivity, z as normalizeVoiceSettings, B as readAudioTags, F as readExpressivity, G as readVoiceSettings, H as resolveConvaiTtsModel, I as stripAudioTags, J as stripExpressivityBlock } from './types-BKJtOUbE.cjs';
3
+
4
+ /**
5
+ * System-prompt composer for the voice agent.
6
+ *
7
+ * Layers three concerns on top of the caller's base prompt:
8
+ * 1. Expressivity block (audio tags allow-list + usage rules)
9
+ * 2. Memory block (`{{user_context}}` placeholder + `add_memory` tool doc)
10
+ *
11
+ * Each block is wrapped in a delimiter comment so repeated calls remain
12
+ * idempotent — calling `composeAgentPrompt` on an already-composed prompt
13
+ * produces the same output because the old blocks are stripped first.
14
+ */
15
+
16
+ /** Default memory guidance appended when memory tools are enabled. */
17
+ declare const DEFAULT_MEMORY_BLOCK = "# Memory\n\nKnown context about this user from past conversations:\n{{user_context}}\n\nMemory retrieval is automatic \u2014 the top matching facts are already injected above. Never say \"let me check my memory\" or \"searching memories.\"\n\nYou have one tool:\n- add_memory(fact): save a concise, canonical fact about the user \u2014 preferences, decisions, personal details, follow-ups. Use short normalized phrasings like \"favorite color: green\" or \"lives in Honolulu\". Always call it when the user explicitly asks you to remember something.";
18
+ /**
19
+ * Strip a previously-appended memory block from a prompt so we can re-append
20
+ * cleanly. Handles both the exact heading we emit and the older `<!-- zix-memory-vN -->`
21
+ * marker for backwards compatibility.
22
+ */
23
+ declare function stripMemoryBlock(prompt: string): string;
24
+ interface ComposeAgentPromptOptions {
25
+ /** `off` disables the expressivity block entirely. Default: `subtle`. */
26
+ expressivity?: Expressivity;
27
+ /** Allowed audio tags. `null` ⇒ use DEFAULT_ALLOWED_TAGS. */
28
+ audioTags?: string[] | null;
29
+ /**
30
+ * Memory guidance appended to the end of the prompt. Pass `null` to omit
31
+ * the memory block entirely (useful for agents that don't use memory tools).
32
+ * Default: {@link DEFAULT_MEMORY_BLOCK}.
33
+ */
34
+ memoryBlock?: string | null;
35
+ }
36
+ /**
37
+ * Strip the expressivity + memory blocks from an arbitrary prompt, returning
38
+ * the base prompt the app originally supplied.
39
+ */
40
+ declare function extractBasePrompt(prompt: string): string;
41
+ /**
42
+ * Compose the final system prompt that gets sent to ElevenLabs. Idempotent:
43
+ * passing an already-composed prompt back in produces the same output.
44
+ */
45
+ declare function composeAgentPrompt(basePrompt: string, options?: ComposeAgentPromptOptions): string;
46
+
47
+ /**
48
+ * Thin `fetch`-based Twilio REST client used by Mode A of the SDK's
49
+ * `TelephonyClient` (self-hosted / BYO keys). Intentionally duplicates
50
+ * the essential pieces of the server-side client in
51
+ * `apps/api/src/lib/twilio.ts` instead of importing it — the SDK must
52
+ * remain server-independent and have zero dependency on the Shogo API
53
+ * or the `twilio` npm package.
54
+ *
55
+ * Only the endpoints currently needed by the SDK are modelled:
56
+ * - AvailablePhoneNumbers/{country}/Local → search
57
+ * - IncomingPhoneNumbers → purchase
58
+ * - IncomingPhoneNumbers/{sid} → release
59
+ */
60
+ declare const DEFAULT_TWILIO_BASE_URL = "https://api.twilio.com";
61
+ declare class TwilioApiError extends Error {
62
+ readonly status: number;
63
+ readonly body: string;
64
+ constructor(message: string, status: number, body: string);
65
+ }
66
+ interface TwilioClientConfig {
67
+ accountSid: string;
68
+ authToken: string;
69
+ /** Override for tests. Defaults to the public API. */
70
+ baseUrl?: string;
71
+ /** Custom fetch (for tests). Defaults to the global `fetch`. */
72
+ fetch?: typeof fetch;
73
+ }
74
+ interface AvailableNumber {
75
+ phoneNumber: string;
76
+ friendlyName: string;
77
+ region?: string;
78
+ locality?: string;
79
+ isoCountry?: string;
80
+ }
81
+ interface IncomingNumber {
82
+ sid: string;
83
+ phoneNumber: string;
84
+ friendlyName: string;
85
+ voiceUrl?: string;
86
+ }
87
+ declare class TwilioClient {
88
+ private readonly config;
89
+ private readonly baseUrl;
90
+ private readonly fetchImpl;
91
+ private readonly basicAuth;
92
+ constructor(config: TwilioClientConfig);
93
+ private accountUrl;
94
+ private headers;
95
+ searchAvailable(params?: {
96
+ country?: string;
97
+ areaCode?: string;
98
+ contains?: string;
99
+ limit?: number;
100
+ }): Promise<AvailableNumber[]>;
101
+ purchaseNumber(params: {
102
+ phoneNumber: string;
103
+ friendlyName?: string;
104
+ voiceUrl?: string;
105
+ }): Promise<IncomingNumber>;
106
+ releaseNumber(sid: string): Promise<void>;
107
+ }
108
+
109
+ /**
110
+ * Dual-mode telephony client.
111
+ *
112
+ * The SDK exposes a single `TelephonyClient` interface with two
113
+ * implementations behind it:
114
+ *
115
+ * - `HostedTelephonyClient` (Mode B) — proxies every call through
116
+ * Shogo's API using a `shogo_sk_*` bearer. Shogo owns the EL +
117
+ * Twilio accounts, provisions resources per project, and meters
118
+ * usage against the workspace's USD usage wallet (raw provider
119
+ * cost + 20% markup).
120
+ *
121
+ * - `DirectTelephonyClient` (Mode A) — talks directly to Twilio REST
122
+ * and ElevenLabs REST using developer-provided credentials. Shogo's
123
+ * API is not involved; the developer pays EL + Twilio directly.
124
+ *
125
+ * Consumers never construct these directly; `createTelephonyClient()`
126
+ * (called by `createClient()`) picks the right implementation based on
127
+ * the supplied options.
128
+ */
129
+ interface ProvisionNumberOptions {
130
+ /** US area code preference (e.g. '415'). Hosted + Direct. */
131
+ areaCode?: string;
132
+ /** ISO country code (defaults to US). */
133
+ country?: string;
134
+ /** Human-friendly label stored with the number. */
135
+ friendlyName?: string;
136
+ }
137
+ interface ProvisionNumberResult {
138
+ phoneNumber: string;
139
+ twilioPhoneSid: string;
140
+ elevenlabsPhoneId: string;
141
+ /** USD billed (raw provider cost + 20% markup) for setup (Mode B only). */
142
+ setupBilledUsd?: number;
143
+ /** USD billed for the first monthly number fee (Mode B only). */
144
+ monthlyBilledUsd?: number;
145
+ /** Whether each debit succeeded against the workspace's usage wallet. */
146
+ usageDebited?: {
147
+ setup: boolean;
148
+ monthly: boolean;
149
+ };
150
+ }
151
+ interface OutboundCallOptions {
152
+ to: string;
153
+ dynamicVariables?: Record<string, string>;
154
+ }
155
+ interface OutboundCallResult {
156
+ callSid: string;
157
+ conversationId: string;
158
+ /** Pre-flight USD estimate for one minute outbound (Mode B only). */
159
+ estimatedBilledUsd?: number;
160
+ /** USD per minute outbound, billed rate (raw + markup). */
161
+ billedUsdPerMinute?: number;
162
+ }
163
+ interface VoiceUsageRange {
164
+ from?: string;
165
+ to?: string;
166
+ }
167
+ /**
168
+ * Aggregated voice usage for a project. Shape mirrors
169
+ * `GET /api/voice/usage/:projectId`. `events` is the underlying raw
170
+ * `UsageEvent` list (capped at 1000) for consumers that want to build
171
+ * a per-day chart themselves.
172
+ */
173
+ interface VoiceUsageSummary {
174
+ projectId: string;
175
+ range: {
176
+ from: string | null;
177
+ to: string | null;
178
+ };
179
+ totals: {
180
+ minutesInbound: number;
181
+ minutesOutbound: number;
182
+ /** USD billed (raw + markup) for inbound minutes. */
183
+ billedUsdInbound: number;
184
+ /** USD billed for outbound minutes. */
185
+ billedUsdOutbound: number;
186
+ /** USD billed for number setup + monthly fees. */
187
+ billedUsdNumbers: number;
188
+ /** Grand total USD billed across all voice usage. */
189
+ billedUsd: number;
190
+ calls: number;
191
+ inboundCalls: number;
192
+ outboundCalls: number;
193
+ };
194
+ events: Array<{
195
+ id: string;
196
+ actionType: string;
197
+ actionMetadata: unknown;
198
+ /** Raw provider cost in USD, before markup. */
199
+ rawUsd: number;
200
+ /** Amount billed to the workspace in USD (raw + markup). */
201
+ billedUsd: number;
202
+ createdAt: string;
203
+ }>;
204
+ }
205
+ interface ReleaseNumberResult {
206
+ released: boolean;
207
+ }
208
+ /**
209
+ * Single turn of an ElevenLabs post-call transcript.
210
+ * Mirrors the `transcript` array items in the `post_call_transcription`
211
+ * webhook payload. Extra provider-specific fields are preserved on the
212
+ * index signature so consumers can surface them if needed.
213
+ */
214
+ interface VoiceTranscriptTurn {
215
+ role: 'agent' | 'user' | string;
216
+ message?: string | null;
217
+ time_in_call_secs?: number;
218
+ [key: string]: unknown;
219
+ }
220
+ /**
221
+ * Summary row returned by `GET /api/voice/calls/:projectId`. When
222
+ * `includeTranscript=true` is passed to `listCalls`, each row also
223
+ * includes the full `transcript` array.
224
+ */
225
+ interface VoiceCallSummary {
226
+ id: string;
227
+ conversationId: string | null;
228
+ callSid: string | null;
229
+ direction: 'inbound' | 'outbound' | string;
230
+ durationSeconds: number;
231
+ billedMinutes: number;
232
+ startedAt: string | null;
233
+ endedAt: string | null;
234
+ createdAt: string;
235
+ billed: boolean;
236
+ hasTranscript: boolean;
237
+ transcriptSummary: string | null;
238
+ transcript?: VoiceTranscriptTurn[] | null;
239
+ }
240
+ /**
241
+ * Detailed single-call row from `GET /api/voice/calls/:projectId/:callId`
242
+ * — always includes the full transcript when EL has delivered one.
243
+ */
244
+ interface VoiceCallDetail extends Omit<VoiceCallSummary, 'hasTranscript'> {
245
+ transcript: VoiceTranscriptTurn[] | null;
246
+ }
247
+ interface ListCallsOptions {
248
+ limit?: number;
249
+ includeTranscript?: boolean;
250
+ }
251
+ interface TelephonyClient {
252
+ readonly mode: 'hosted' | 'direct' | 'mock';
253
+ provisionNumber(opts?: ProvisionNumberOptions): Promise<ProvisionNumberResult>;
254
+ outboundCall(opts: OutboundCallOptions): Promise<OutboundCallResult>;
255
+ releaseNumber(): Promise<ReleaseNumberResult>;
256
+ /** Mode A throws; usage is not tracked on Shogo's side. */
257
+ getUsage(range?: VoiceUsageRange): Promise<VoiceUsageSummary>;
258
+ /**
259
+ * List recent calls for this project with optional transcripts.
260
+ * Mode A throws — Shogo's API doesn't see these calls.
261
+ */
262
+ listCalls(opts?: ListCallsOptions): Promise<VoiceCallSummary[]>;
263
+ /**
264
+ * Fetch a single call (by VoiceCallMeter id, EL conversation id, or
265
+ * Twilio CallSid) including the full transcript. Mode A throws.
266
+ */
267
+ getCall(callId: string): Promise<VoiceCallDetail>;
268
+ }
269
+ declare class TelephonyConfigError extends Error {
270
+ constructor(message: string);
271
+ }
272
+ declare class TelephonyApiError extends Error {
273
+ readonly status: number;
274
+ readonly body: unknown;
275
+ constructor(message: string, status: number, body: unknown);
276
+ }
277
+ interface HostedTelephonyOptions {
278
+ shogoApiKey: string;
279
+ projectId: string;
280
+ apiUrl: string;
281
+ fetch?: typeof fetch;
282
+ }
283
+ declare class HostedTelephonyClient implements TelephonyClient {
284
+ private readonly opts;
285
+ readonly mode = "hosted";
286
+ private readonly fetchImpl;
287
+ constructor(opts: HostedTelephonyOptions);
288
+ private url;
289
+ private request;
290
+ provisionNumber(opts?: ProvisionNumberOptions): Promise<ProvisionNumberResult>;
291
+ outboundCall(opts: OutboundCallOptions): Promise<OutboundCallResult>;
292
+ releaseNumber(): Promise<ReleaseNumberResult>;
293
+ getUsage(range?: VoiceUsageRange): Promise<VoiceUsageSummary>;
294
+ listCalls(opts?: ListCallsOptions): Promise<VoiceCallSummary[]>;
295
+ getCall(callId: string): Promise<VoiceCallDetail>;
296
+ }
297
+ interface HostedRuntimeTokenOptions {
298
+ /**
299
+ * Per-project runtime token — the value of `process.env.RUNTIME_AUTH_SECRET`
300
+ * injected into every Shogo-managed pod. This is **not** a user API key;
301
+ * it's a deterministic HMAC-derived capability scoped to exactly one
302
+ * `projectId`. Never ship this value to the browser bundle.
303
+ */
304
+ runtimeToken: string;
305
+ projectId: string;
306
+ apiUrl: string;
307
+ fetch?: typeof fetch;
308
+ }
309
+ /**
310
+ * Hosted telephony client that authenticates via `x-runtime-token` instead
311
+ * of a `shogo_sk_*` bearer. Used by generated pod apps: every pod already
312
+ * has `RUNTIME_AUTH_SECRET` + `PROJECT_ID` in env, so `createClient()` can
313
+ * pick this implementation automatically — the developer never mints a key.
314
+ *
315
+ * Wire-compat with {@link HostedTelephonyClient}: same endpoints, same
316
+ * response shapes. The only differences are:
317
+ *
318
+ * 1. `Authorization` is replaced with `x-runtime-token`.
319
+ * 2. Every request URL carries `?projectId=<pid>` so the Shogo API's
320
+ * `authMiddleware` can re-derive and validate the token.
321
+ */
322
+ declare class HostedRuntimeTokenClient implements TelephonyClient {
323
+ private readonly opts;
324
+ readonly mode = "hosted";
325
+ private readonly fetchImpl;
326
+ constructor(opts: HostedRuntimeTokenOptions);
327
+ private url;
328
+ private request;
329
+ provisionNumber(opts?: ProvisionNumberOptions): Promise<ProvisionNumberResult>;
330
+ outboundCall(opts: OutboundCallOptions): Promise<OutboundCallResult>;
331
+ releaseNumber(): Promise<ReleaseNumberResult>;
332
+ getUsage(range?: VoiceUsageRange): Promise<VoiceUsageSummary>;
333
+ listCalls(opts?: ListCallsOptions): Promise<VoiceCallSummary[]>;
334
+ getCall(callId: string): Promise<VoiceCallDetail>;
335
+ }
336
+ interface DirectTelephonyOptions {
337
+ projectId?: string;
338
+ elevenlabs: {
339
+ apiKey: string;
340
+ agentId: string;
341
+ /** Existing EL phone-number resource id. If omitted, `provisionNumber`
342
+ * will create one; `outboundCall` / `releaseNumber` will 409 until
343
+ * one exists. */
344
+ phoneNumberId?: string;
345
+ baseUrl?: string;
346
+ };
347
+ twilio: {
348
+ accountSid: string;
349
+ authToken: string;
350
+ /**
351
+ * E.164 number to use as the caller id. Required for
352
+ * `outboundCall`. If you want `provisionNumber` to buy a new
353
+ * number, leave this unset.
354
+ */
355
+ fromNumber?: string;
356
+ /** Optional pre-existing Twilio IncomingPhoneNumber sid. */
357
+ phoneSid?: string;
358
+ baseUrl?: string;
359
+ };
360
+ fetch?: typeof fetch;
361
+ }
362
+ declare class DirectTelephonyClient implements TelephonyClient {
363
+ private readonly opts;
364
+ readonly mode = "direct";
365
+ private readonly el;
366
+ private readonly tw;
367
+ private state;
368
+ constructor(opts: DirectTelephonyOptions);
369
+ provisionNumber(opts?: ProvisionNumberOptions): Promise<ProvisionNumberResult>;
370
+ outboundCall(opts: OutboundCallOptions): Promise<OutboundCallResult>;
371
+ releaseNumber(): Promise<ReleaseNumberResult>;
372
+ getUsage(): Promise<VoiceUsageSummary>;
373
+ listCalls(): Promise<VoiceCallSummary[]>;
374
+ getCall(): Promise<VoiceCallDetail>;
375
+ }
376
+ type CreateTelephonyOptions = ({
377
+ mode: 'hosted';
378
+ } & HostedTelephonyOptions) | ({
379
+ mode: 'runtime-token';
380
+ } & HostedRuntimeTokenOptions) | ({
381
+ mode: 'direct';
382
+ } & DirectTelephonyOptions);
383
+ declare function createTelephonyClient(opts: CreateTelephonyOptions): TelephonyClient;
384
+
385
+ /**
386
+ * MockTelephonyClient
387
+ *
388
+ * In-process telephony stub used by demo recordings (Playwright) and
389
+ * any environment that sets `process.env.SHOGO_VOICE_MODE=mock`.
390
+ *
391
+ * Returns deterministic, hand-crafted fixture data for every method on
392
+ * the {@link TelephonyClient} interface. Performs zero network I/O — no
393
+ * Shogo API call, no Twilio call, no ElevenLabs call. Calling
394
+ * `outboundCall()` is therefore safe in any context (no real phones
395
+ * ring, no usage wallet is debited).
396
+ *
397
+ * Wire-compat with the real clients: same method shapes, same return
398
+ * types. Generated app code that uses
399
+ * `shogo.voice.telephony.outboundCall(...)` does not need to know it's
400
+ * running against the mock.
401
+ */
402
+
403
+ interface MockTelephonyOptions {
404
+ /** Project the mock pretends to belong to. Defaults to 'demo-project'. */
405
+ projectId?: string;
406
+ /** Override the placeholder outbound number. */
407
+ phoneNumber?: string;
408
+ /** Override the rotating call fixtures (advanced). */
409
+ callFixtures?: VoiceCallSummary[];
410
+ }
411
+ declare class MockTelephonyClient implements TelephonyClient {
412
+ readonly mode: "mock";
413
+ private readonly projectId;
414
+ private readonly phoneNumber;
415
+ private readonly fixtures;
416
+ private callCounter;
417
+ constructor(opts?: MockTelephonyOptions);
418
+ provisionNumber(_opts?: ProvisionNumberOptions): Promise<ProvisionNumberResult>;
419
+ outboundCall(_opts: OutboundCallOptions): Promise<OutboundCallResult>;
420
+ releaseNumber(): Promise<ReleaseNumberResult>;
421
+ getUsage(_range?: VoiceUsageRange): Promise<VoiceUsageSummary>;
422
+ listCalls(opts?: ListCallsOptions): Promise<VoiceCallSummary[]>;
423
+ getCall(callId: string): Promise<VoiceCallDetail>;
424
+ }
425
+ /**
426
+ * Convenience: returns true when SHOGO_VOICE_MODE is set to one of the
427
+ * recognized mock-mode aliases. Other modules in the SDK use this to
428
+ * branch their telephony selection.
429
+ */
430
+ declare function isVoiceMockEnv(): boolean;
431
+
432
+ export { type AvailableNumber, type ComposeAgentPromptOptions, type CreateTelephonyOptions, DEFAULT_MEMORY_BLOCK, DEFAULT_TWILIO_BASE_URL, DirectTelephonyClient, type DirectTelephonyOptions, Expressivity, HostedRuntimeTokenClient, type HostedRuntimeTokenOptions, HostedTelephonyClient, type HostedTelephonyOptions, type IncomingNumber, MockTelephonyClient, type OutboundCallOptions, type OutboundCallResult, type ProvisionNumberOptions, type ProvisionNumberResult, type ReleaseNumberResult, TelephonyApiError, type TelephonyClient, TelephonyConfigError, TwilioApiError, TwilioClient, type TwilioClientConfig, type VoiceUsageRange, type VoiceUsageSummary, composeAgentPrompt, createTelephonyClient, extractBasePrompt, isVoiceMockEnv, stripMemoryBlock };