@spekoai/sdk 0.4.0 → 0.4.2

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 (49) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +32 -3
  3. package/dist/index.d.ts +1 -1
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/lib/client.d.ts +12 -6
  6. package/dist/lib/client.d.ts.map +1 -1
  7. package/dist/lib/client.js +20 -11
  8. package/dist/lib/http.d.ts +1 -0
  9. package/dist/lib/http.d.ts.map +1 -1
  10. package/dist/lib/http.js +4 -1
  11. package/dist/lib/resources/agents.d.ts +27 -10
  12. package/dist/lib/resources/agents.d.ts.map +1 -1
  13. package/dist/lib/resources/agents.js +58 -14
  14. package/dist/lib/resources/callbacks.d.ts +13 -0
  15. package/dist/lib/resources/callbacks.d.ts.map +1 -0
  16. package/dist/lib/resources/callbacks.js +26 -0
  17. package/dist/lib/resources/calls.d.ts +18 -0
  18. package/dist/lib/resources/calls.d.ts.map +1 -0
  19. package/dist/lib/resources/calls.js +33 -0
  20. package/dist/lib/resources/complete.d.ts +1 -1
  21. package/dist/lib/resources/complete.d.ts.map +1 -1
  22. package/dist/lib/resources/complete.js +9 -3
  23. package/dist/lib/resources/credits.d.ts.map +1 -1
  24. package/dist/lib/resources/knowledge-bases.d.ts +1 -1
  25. package/dist/lib/resources/knowledge-bases.d.ts.map +1 -1
  26. package/dist/lib/resources/knowledge-bases.js +1 -1
  27. package/dist/lib/resources/phone-numbers.d.ts +20 -6
  28. package/dist/lib/resources/phone-numbers.d.ts.map +1 -1
  29. package/dist/lib/resources/phone-numbers.js +27 -5
  30. package/dist/lib/resources/realtime.d.ts +1 -1
  31. package/dist/lib/resources/realtime.d.ts.map +1 -1
  32. package/dist/lib/resources/realtime.js +28 -3
  33. package/dist/lib/resources/synthesize.d.ts +1 -1
  34. package/dist/lib/resources/synthesize.d.ts.map +1 -1
  35. package/dist/lib/resources/synthesize.js +3 -1
  36. package/dist/lib/resources/transcribe.d.ts +1 -1
  37. package/dist/lib/resources/transcribe.d.ts.map +1 -1
  38. package/dist/lib/resources/transcribe.js +5 -2
  39. package/dist/lib/resources/usage.d.ts +1 -1
  40. package/dist/lib/resources/usage.d.ts.map +1 -1
  41. package/dist/lib/resources/voice.d.ts +3 -4
  42. package/dist/lib/resources/voice.d.ts.map +1 -1
  43. package/dist/lib/resources/voice.js +3 -4
  44. package/dist/lib/resources/voices.d.ts +27 -0
  45. package/dist/lib/resources/voices.d.ts.map +1 -0
  46. package/dist/lib/resources/voices.js +32 -0
  47. package/dist/lib/types/index.d.ts +561 -20
  48. package/dist/lib/types/index.d.ts.map +1 -1
  49. package/package.json +3 -3
@@ -2,8 +2,10 @@
2
2
  export interface SpekoClientOptions {
3
3
  /** API key for authentication. */
4
4
  apiKey: string;
5
- /** Base URL of the Speko API. Defaults to https://api.speko.ai */
5
+ /** Base URL of the Speko API. Defaults to https://api.speko.dev */
6
6
  baseUrl?: string;
7
+ /** Alias for {@link SpekoClientOptions.baseUrl}. If both are set, `baseUrl` wins. */
8
+ baseURL?: string;
7
9
  /** Request timeout in milliseconds. Defaults to 30000. */
8
10
  timeout?: number;
9
11
  }
@@ -117,9 +119,9 @@ export type TranscribeStreamEvent = {
117
119
  text: string;
118
120
  isFinal: boolean;
119
121
  confidence: number;
120
- } | TranscribeResult & {
122
+ } | (TranscribeResult & {
121
123
  type: 'done';
122
- } | {
124
+ }) | {
123
125
  type: 'error';
124
126
  error: string;
125
127
  code: string;
@@ -127,6 +129,15 @@ export type TranscribeStreamEvent = {
127
129
  export interface SynthesizeOptions extends RoutingIntent {
128
130
  /** Optional voice override. Otherwise the SDK uses each provider's default. */
129
131
  voice?: string;
132
+ /**
133
+ * Optional upstream model name to use for synthesis (e.g.
134
+ * `eleven_multilingual_v2`, `sonic-2`, `gpt-4o-mini-tts`,
135
+ * `qwen3-tts-flash`). When omitted, the router picks the best-ranked
136
+ * model for the chosen provider. When set, applies to the primary
137
+ * candidate only — failover candidates still use the selector's model
138
+ * so a model intended for provider A isn't sent to provider B.
139
+ */
140
+ model?: string;
130
141
  speed?: number;
131
142
  constraints?: PipelineConstraints;
132
143
  }
@@ -147,6 +158,36 @@ export interface SynthesizeStreamResult extends AsyncIterable<Uint8Array> {
147
158
  failoverCount: number;
148
159
  scoresRunId: string | null;
149
160
  }
161
+ export interface VoiceCatalogEntry {
162
+ /** Routing-key vendor (matches `allowedProviders.tts` entries). */
163
+ vendor: string;
164
+ /** Voice id passed through to the provider's TTS API. */
165
+ id: string;
166
+ /** Human-readable label. */
167
+ name: string;
168
+ }
169
+ export interface VoicesProviderEntry {
170
+ key: string;
171
+ name: string;
172
+ models: readonly string[];
173
+ /**
174
+ * `true` when the provider's voice library is account-scoped and must
175
+ * be fetched live from the provider (currently only ElevenLabs).
176
+ */
177
+ voicesFetchedLive: boolean;
178
+ }
179
+ export interface VoicesListResult {
180
+ voices: readonly VoiceCatalogEntry[];
181
+ providers: readonly VoicesProviderEntry[];
182
+ }
183
+ export interface VoicesListParams {
184
+ /**
185
+ * Filter to a single provider's voices. Accepts either the routing key
186
+ * (`cartesia`, `xai`, `alibaba`, `openai`, `inworld`, `elevenlabs`) or the
187
+ * catalog suffix form (`xai-tts`, `alibaba-tts`, `openai-tts`).
188
+ */
189
+ provider?: string;
190
+ }
150
191
  /**
151
192
  * One LLM-emitted tool invocation. `args` is a JSON-encoded string (LLMs may
152
193
  * stream partial JSON; the proxy guarantees a complete, parseable string).
@@ -177,14 +218,15 @@ export interface ChatMessage {
177
218
  * Speko's server-side execution: the proxy POSTs a Standard-Webhooks-
178
219
  * signed request to your URL, folds the result back into the next
179
220
  * provider turn, and only returns to you when the model emits final
180
- * text or hands back an inline tool call. `builtin` reserves a slot
181
- * for managed tools (e.g. `search_knowledge_base`) — handlers ship in
182
- * a follow-on release.
221
+ * text or hands back an inline tool call. `builtin` runs Speko-managed
222
+ * primitives (e.g. `search_knowledge_base`, `transfer_call`, `end_call`).
223
+ * `integration` runs an
224
+ * org-installed Speko app action such as Google Calendar or Slack.
183
225
  */
184
- export type ChatToolExecutionMode = 'inline' | 'webhook' | 'builtin';
226
+ export type ChatToolExecutionMode = 'inline' | 'webhook' | 'builtin' | 'integration';
185
227
  /**
186
228
  * Source-of-execution config. Required when `executionMode` is
187
- * `webhook` or `builtin`. Mirrors the SpekoTool `source` shape inside
229
+ * `webhook`, `builtin`, or `integration`. Mirrors the SpekoTool `source` shape inside
188
230
  * `@spekoai/tool-execution`.
189
231
  */
190
232
  export type ChatToolSource = {
@@ -196,10 +238,20 @@ export type ChatToolSource = {
196
238
  secretRef: string;
197
239
  headers?: Record<string, string>;
198
240
  timeoutMs?: number;
241
+ /** `async` returns `asyncAck` immediately while Speko dispatches the webhook in the background. */
242
+ responseMode?: 'sync' | 'async';
243
+ /** LLM-facing acknowledgement used when `responseMode` is `async`. */
244
+ asyncAck?: string;
199
245
  } | {
200
246
  kind: 'builtin';
201
247
  name: string;
202
248
  config?: unknown;
249
+ } | {
250
+ kind: 'integration';
251
+ installationId: string;
252
+ appKey: string;
253
+ actionKey: string;
254
+ config?: unknown;
203
255
  };
204
256
  /**
205
257
  * Tool definition exposed to the LLM. `parameters` is a JSON Schema (draft-7)
@@ -208,8 +260,8 @@ export type ChatToolSource = {
208
260
  *
209
261
  * `executionMode` and `source` are optional and back-compat: omitting
210
262
  * both preserves the v0.3 inline behavior. Set `executionMode: 'webhook'`
211
- * with a matching `source: { kind: 'webhook', ... }` to opt into
212
- * server-managed execution.
263
+ * with a matching `source: { kind: 'webhook', ... }` or
264
+ * `source: { kind: 'integration', ... }` to opt into server-managed execution.
213
265
  */
214
266
  export interface ChatTool {
215
267
  name: string;
@@ -225,12 +277,20 @@ export type ChatToolChoice = 'auto' | 'none' | 'required' | {
225
277
  name: string;
226
278
  };
227
279
  };
280
+ export type ReasoningEffort = 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';
228
281
  export interface CompleteParams {
229
282
  messages: ChatMessage[];
230
283
  intent: RoutingIntent;
284
+ /**
285
+ * Optional voice/session identifier forwarded as `x-session-id` for
286
+ * server-executed tools. The value is intentionally carried out-of-band
287
+ * so `/v1/complete` request bodies stay provider-shaped.
288
+ */
289
+ sessionId?: string;
231
290
  systemPrompt?: string;
232
291
  temperature?: number;
233
292
  maxTokens?: number;
293
+ reasoningEffort?: ReasoningEffort;
234
294
  constraints?: PipelineConstraints;
235
295
  tools?: ChatTool[];
236
296
  toolChoice?: ChatToolChoice;
@@ -282,7 +342,7 @@ export type CompleteStreamEvent = {
282
342
  error: string;
283
343
  code: string;
284
344
  };
285
- export type RealtimeProvider = 'openai' | 'google' | 'xai' | 'inworld';
345
+ export type RealtimeProvider = 'openai' | 'google' | 'xai' | 'inworld' | 'alibaba';
286
346
  export interface RealtimeToolSpec {
287
347
  name: string;
288
348
  description: string;
@@ -306,6 +366,10 @@ export interface RealtimeConnectParams {
306
366
  * as `audio` frames; text control messages come through typed variants.
307
367
  */
308
368
  export type RealtimeFrame = {
369
+ type: 'ready';
370
+ inputSampleRate: 16000 | 24000;
371
+ outputSampleRate: 16000 | 24000;
372
+ } | {
309
373
  type: 'audio';
310
374
  pcm: Uint8Array;
311
375
  sampleRate: number;
@@ -323,6 +387,14 @@ export type RealtimeFrame = {
323
387
  type: 'usage';
324
388
  inputAudioTokens: number;
325
389
  outputAudioTokens: number;
390
+ } | {
391
+ type: 'interruption';
392
+ at: 'user' | 'assistant';
393
+ } | {
394
+ type: 'server_tool_call';
395
+ id: string;
396
+ name: string;
397
+ status: 'started' | 'completed' | 'failed';
326
398
  } | {
327
399
  type: 'error';
328
400
  code: string;
@@ -336,6 +408,8 @@ export type RealtimeEventHandler = (frame: RealtimeFrame) => void;
336
408
  export interface RealtimeSessionHandle {
337
409
  readonly sessionId: string;
338
410
  readonly expiresAt: string;
411
+ readonly inputSampleRate: 16000 | 24000;
412
+ readonly outputSampleRate: 16000 | 24000;
339
413
  /** Send a PCM16 audio chunk up to the model. */
340
414
  sendAudio(pcm: Uint8Array): void;
341
415
  /** Signal user-turn boundary / commit the input buffer. */
@@ -354,13 +428,17 @@ export interface VoiceDialParams {
354
428
  to: string;
355
429
  /** Caller ID. Falls back to the org default if omitted server-side. */
356
430
  from?: string;
431
+ /** Persisted assistant to run for this call. When supplied, `intent` can be omitted. */
432
+ agentId?: string;
357
433
  /** Routing intent — language is required, optimizeFor optional. */
358
- intent: RoutingIntent;
434
+ intent?: RoutingIntent;
359
435
  constraints?: PipelineConstraints;
360
436
  /** TTS voice id passed through to the picked TTS provider. */
361
437
  voice?: string;
362
438
  /** Agent system prompt. */
363
439
  systemPrompt?: string;
440
+ /** Optional first utterance. `null` is not accepted by phone dial; omit to use the agent default. */
441
+ firstMessage?: string;
364
442
  llm?: {
365
443
  temperature?: number;
366
444
  maxTokens?: number;
@@ -369,6 +447,17 @@ export interface VoiceDialParams {
369
447
  sampleRate?: number;
370
448
  speed?: number;
371
449
  };
450
+ sttOptions?: {
451
+ keywords?: string[];
452
+ };
453
+ /** Optional per-call SIP routing hints. Carrier AMD requires trunk/provider support. */
454
+ telephony?: {
455
+ region?: string;
456
+ amd?: {
457
+ mode?: 'agent' | 'carrier' | 'disabled';
458
+ timeoutSeconds?: number;
459
+ };
460
+ };
372
461
  /** Free-form metadata round-tripped to your webhooks. */
373
462
  metadata?: Record<string, unknown>;
374
463
  }
@@ -376,42 +465,89 @@ export interface VoiceDialResult {
376
465
  sessionId: string;
377
466
  callControlId: string;
378
467
  roomName: string;
379
- /** 'dialing' on a real call, 'dialing-stub' if Telnyx isn't configured. */
468
+ /** 'dialing' on a real call, 'dialing-stub' if managed telephony isn't configured. */
380
469
  status: 'dialing' | 'dialing-stub';
381
470
  to: string;
382
471
  from: string;
383
472
  }
384
473
  export type PhoneNumberDirection = 'inbound' | 'outbound' | 'both';
474
+ export type PhoneNumberSource = 'managed' | 'sip_trunk';
475
+ export type PhoneNumberSmsAssignmentStatus = 'FAILED_ASSIGNMENT' | 'PENDING_ASSIGNMENT' | 'ASSIGNED' | 'PENDING_UNASSIGNMENT' | 'FAILED_UNASSIGNMENT';
476
+ export interface PhoneNumberSetupStatus {
477
+ status: 'ready' | 'action_required' | 'suspended';
478
+ inboundReady: boolean;
479
+ outboundReady: boolean;
480
+ agentReady: boolean;
481
+ forwardingRequired: boolean;
482
+ sipConnectionReady: boolean;
483
+ issues: string[];
484
+ }
385
485
  export interface PhoneNumberRow {
386
486
  id: string;
387
487
  organizationId: string;
388
488
  e164: string;
489
+ source: PhoneNumberSource;
490
+ /** Platform-neutral resource id for a platform-managed number. */
491
+ providerResourceId: string | null;
492
+ /** @deprecated Use `providerResourceId`. */
389
493
  telnyxPhoneNumberId: string | null;
494
+ /** @deprecated LiveKit trunk IDs are internal and no longer exposed. */
495
+ sipTrunkId: string | null;
496
+ sipConnectionInstallationId: string | null;
497
+ sipProviderName: string | null;
390
498
  direction: PhoneNumberDirection;
391
499
  dispatchMetadataTemplate: Record<string, unknown> | null;
392
500
  label: string | null;
501
+ sms10dlcProfileId: string | null;
502
+ smsCampaignId: string | null;
503
+ smsAssignmentStatus: PhoneNumberSmsAssignmentStatus | null;
504
+ smsAssignmentUpdatedAt: string | null;
393
505
  /**
394
506
  * 1:1 link to a persisted agent. When set, inbound calls hydrate
395
507
  * pipeline config from the agent row instead of (or alongside) the
396
508
  * dispatch_metadata_template.
397
509
  */
398
510
  agentId: string | null;
511
+ setupStatus: PhoneNumberSetupStatus;
512
+ nextChargeAt: string;
513
+ lastChargedAt: string | null;
514
+ suspendedAt: string | null;
399
515
  createdAt: string;
400
516
  updatedAt: string;
401
517
  }
402
518
  export interface PhoneNumberCreateParams {
403
519
  e164: string;
404
520
  direction?: PhoneNumberDirection;
405
- /** LiveKit dispatch metadata template (variables `{{var}}` resolved at dial). */
521
+ /** Dispatch metadata template (variables `{{var}}` resolved at dial). */
406
522
  dispatchMetadataTemplate?: Record<string, unknown>;
407
523
  label?: string;
408
524
  /** 1:1 link to an agent in the same org. */
409
525
  agentId?: string;
410
526
  }
411
- export interface PhoneNumberUpdateParams {
527
+ export type PhoneNumberImportSipTrunkParams = {
528
+ e164: string;
529
+ /** Optional provider/account label for display. */
530
+ sipProviderName?: string;
412
531
  direction?: PhoneNumberDirection;
532
+ /** Dispatch metadata template (variables `{{var}}` resolved at dial). */
413
533
  dispatchMetadataTemplate?: Record<string, unknown>;
414
534
  label?: string;
535
+ /** 1:1 link to an agent in the same org. */
536
+ agentId?: string;
537
+ } & ({
538
+ /** Installed SIP connection integration id. Preferred for productized SIP connections. */
539
+ sipConnectionInstallationId: string;
540
+ /** Legacy LiveKit outbound trunk id. Ignored when `sipConnectionInstallationId` is present. */
541
+ sipTrunkId?: string;
542
+ } | {
543
+ /** Legacy LiveKit outbound trunk id. Use `sipConnectionInstallationId` for new integrations. */
544
+ sipTrunkId: string;
545
+ sipConnectionInstallationId?: string;
546
+ });
547
+ export interface PhoneNumberUpdateParams {
548
+ direction?: PhoneNumberDirection;
549
+ dispatchMetadataTemplate?: Record<string, unknown> | null;
550
+ label?: string | null;
415
551
  /** Pass `null` to unlink, a string to relink. */
416
552
  agentId?: string | null;
417
553
  }
@@ -432,9 +568,75 @@ export interface PhoneNumberSearchParams {
432
568
  areaCode?: string;
433
569
  /** Optional locality filter, e.g. "San Francisco". */
434
570
  locality?: string;
435
- /** Max results — Telnyx caps at 50. Default 10. */
571
+ /** Max results. Default 10. */
436
572
  limit?: number;
437
573
  }
574
+ export type PhoneNumberKybStatus = 'missing' | 'draft' | 'submitted' | 'approved' | 'rejected' | 'revoked';
575
+ export type PhoneNumberKybSubmissionStatus = Exclude<PhoneNumberKybStatus, 'missing'>;
576
+ export type PhoneNumberKybSlackNotificationStatus = 'not_queued' | 'queued' | 'enqueue_failed';
577
+ export interface PhoneNumberKybBusinessProfile {
578
+ legalName: string;
579
+ displayName: string;
580
+ entityType: string;
581
+ country: string;
582
+ registrationId?: string;
583
+ website: string;
584
+ address: {
585
+ street: string;
586
+ city: string;
587
+ state: string;
588
+ postalCode: string;
589
+ country: string;
590
+ };
591
+ useCase: string;
592
+ expectedUsage: string;
593
+ }
594
+ export interface PhoneNumberKybAuthorizedRepresentative {
595
+ name: string;
596
+ title: string;
597
+ email: string;
598
+ phone?: string;
599
+ }
600
+ export interface PhoneNumberKybDraftParams {
601
+ businessProfile: PhoneNumberKybBusinessProfile;
602
+ authorizedRepresentative: PhoneNumberKybAuthorizedRepresentative;
603
+ attestationAccepted?: boolean;
604
+ }
605
+ export interface PhoneNumberKybSubmitParams {
606
+ businessProfile: PhoneNumberKybBusinessProfile;
607
+ authorizedRepresentative: PhoneNumberKybAuthorizedRepresentative;
608
+ attestationAccepted: true;
609
+ }
610
+ export interface PhoneNumberKybSubmission {
611
+ id: string;
612
+ organizationId: string;
613
+ status: PhoneNumberKybSubmissionStatus;
614
+ businessProfile: PhoneNumberKybBusinessProfile | null;
615
+ authorizedRepresentative: PhoneNumberKybAuthorizedRepresentative | null;
616
+ attestationAccepted: boolean;
617
+ attestedAt: string | null;
618
+ submittedByUserId: string | null;
619
+ submittedByEmail: string | null;
620
+ submittedByApiKeyId: string | null;
621
+ submittedAt: string | null;
622
+ reviewerUserId: string | null;
623
+ reviewerEmail: string | null;
624
+ reviewedAt: string | null;
625
+ rejectionReason: string | null;
626
+ slackNotificationStatus: PhoneNumberKybSlackNotificationStatus;
627
+ slackNotificationJobId: string | null;
628
+ slackNotificationError: string | null;
629
+ createdAt: string;
630
+ updatedAt: string;
631
+ }
632
+ export interface PhoneNumberKybOverview {
633
+ status: PhoneNumberKybStatus;
634
+ submission: PhoneNumberKybSubmission | null;
635
+ prefill: {
636
+ businessProfile: PhoneNumberKybBusinessProfile;
637
+ authorizedRepresentative: PhoneNumberKybAuthorizedRepresentative;
638
+ } | null;
639
+ }
438
640
  /**
439
641
  * Routing intent for an agent's voice pipeline. Narrower than the
440
642
  * top-level {@link RoutingIntent} — the agents API specifically
@@ -462,6 +664,71 @@ export interface AgentSttOptions {
462
664
  /** Vocabulary keywords forwarded to whichever STT provider the router picks. */
463
665
  keywords?: string[];
464
666
  }
667
+ /**
668
+ * Built-in ambience clip ids supported by the hosted worker. Custom clip
669
+ * uploads are intentionally not yet supported — pinning to the built-ins
670
+ * keeps the v1 API simple and lets the worker map straight to the
671
+ * `BuiltinAudioClip` enum.
672
+ */
673
+ export type AgentAmbientClip = 'office-ambience' | 'keyboard-typing' | 'keyboard-typing2';
674
+ /**
675
+ * Per-agent background audio. Today only ambient (continuous loop) is
676
+ * supported. The ambience plays on a separate media track mixed
677
+ * server-side, so it reaches both browser (WebRTC) and phone (SIP) callers
678
+ * without any client-side change.
679
+ */
680
+ export interface AgentBackgroundAudio {
681
+ ambient?: {
682
+ clip: AgentAmbientClip;
683
+ /** Linear gain in [0, 1]. Defaults to 1.0 (clip's natural level). */
684
+ volume?: number;
685
+ };
686
+ }
687
+ export interface AgentSpeechNormalization {
688
+ pronunciationDictionary?: Record<string, string>;
689
+ textReplacements?: Record<string, string>;
690
+ }
691
+ export interface AgentLifecycleWebhookCreate {
692
+ url: string;
693
+ /** Deprecated. Lifecycle webhooks use the org-level signing secret from API keys. */
694
+ secret?: string;
695
+ headers?: Record<string, string>;
696
+ timeoutMs?: number;
697
+ responseMode?: 'sync' | 'async';
698
+ asyncAck?: string;
699
+ }
700
+ export interface AgentLifecycleWebhookUpdate {
701
+ url: string;
702
+ /** Deprecated. Lifecycle webhooks use the org-level signing secret from API keys. */
703
+ secret?: string;
704
+ headers?: Record<string, string>;
705
+ timeoutMs?: number;
706
+ responseMode?: 'sync' | 'async';
707
+ asyncAck?: string;
708
+ }
709
+ export interface AgentLifecycleWebhookSerialized {
710
+ url: string;
711
+ secretRef: string;
712
+ headers?: Record<string, string>;
713
+ timeoutMs?: number;
714
+ responseMode?: 'sync' | 'async';
715
+ asyncAck?: string;
716
+ }
717
+ export interface AgentWebhooksSerialized {
718
+ preCall?: AgentLifecycleWebhookSerialized;
719
+ postCall?: AgentLifecycleWebhookSerialized;
720
+ status?: AgentLifecycleWebhookSerialized;
721
+ }
722
+ export interface AgentWebhooksCreate {
723
+ preCall?: AgentLifecycleWebhookCreate;
724
+ postCall?: AgentLifecycleWebhookCreate;
725
+ status?: AgentLifecycleWebhookCreate;
726
+ }
727
+ export interface AgentWebhooksUpdate {
728
+ preCall?: AgentLifecycleWebhookUpdate | null;
729
+ postCall?: AgentLifecycleWebhookUpdate | null;
730
+ status?: AgentLifecycleWebhookUpdate | null;
731
+ }
465
732
  export interface AgentRow {
466
733
  id: string;
467
734
  organizationId: string;
@@ -472,6 +739,9 @@ export interface AgentRow {
472
739
  llmOptions: AgentLlmOptions | null;
473
740
  stackPreferences: AgentStackPreferences | null;
474
741
  sttOptions: AgentSttOptions | null;
742
+ backgroundAudio: AgentBackgroundAudio | null;
743
+ speechNormalization: AgentSpeechNormalization | null;
744
+ webhooks: AgentWebhooksSerialized | null;
475
745
  createdAt: string;
476
746
  updatedAt: string;
477
747
  }
@@ -483,8 +753,252 @@ export interface AgentCreateParams {
483
753
  llmOptions?: AgentLlmOptions;
484
754
  stackPreferences?: AgentStackPreferences;
485
755
  sttOptions?: AgentSttOptions;
756
+ backgroundAudio?: AgentBackgroundAudio;
757
+ speechNormalization?: AgentSpeechNormalization;
758
+ webhooks?: AgentWebhooksCreate;
759
+ }
760
+ export type AgentUpdateParams = Partial<Omit<AgentCreateParams, 'webhooks'>> & {
761
+ webhooks?: AgentWebhooksUpdate | null;
762
+ };
763
+ export interface CallTranscriptEntry {
764
+ id: string;
765
+ index: number;
766
+ source: 'user' | 'agent' | 'system';
767
+ text: string;
768
+ started_at: string;
769
+ ended_at: string | null;
770
+ provider: string | null;
771
+ model: string | null;
772
+ metadata: Record<string, unknown>;
773
+ }
774
+ export interface CallCostLine {
775
+ provider: string;
776
+ metric: string;
777
+ quantity: number;
778
+ keySource: KeySource;
779
+ costMicroUsd: string;
780
+ }
781
+ export interface CallReport {
782
+ session_id: string;
783
+ organization_id: string;
784
+ summary: string;
785
+ outcome: string;
786
+ structured_data: Record<string, unknown>;
787
+ transcript: {
788
+ entries: CallTranscriptEntry[];
789
+ };
790
+ cost_micro_usd: string;
791
+ cost_breakdown: CallCostLine[];
792
+ artifacts: Record<string, unknown>;
793
+ metadata: Record<string, unknown>;
794
+ scheduled_callback: ScheduledCallback | Record<string, unknown> | null;
795
+ analysis_status: 'heuristic' | 'completed' | 'failed';
796
+ analysis_provider: string | null;
797
+ analysis_model: string | null;
798
+ analysis_error: string | null;
799
+ analysis_completed_at: string | null;
800
+ post_call_webhook_status: 'not_configured' | 'pending' | 'delivered' | 'failed';
801
+ post_call_webhook_attempts: number;
802
+ post_call_webhook_next_retry_at: string | null;
803
+ post_call_webhook_delivered_at: string | null;
804
+ post_call_webhook_error: string | null;
805
+ created_at: string;
806
+ updated_at: string;
807
+ }
808
+ export type ScheduledCallbackStatus = 'scheduled' | 'dispatching' | 'dispatched' | 'cancelled' | 'failed';
809
+ export interface ScheduledCallback {
810
+ id: string;
811
+ organization_id: string;
812
+ source_session_id: string | null;
813
+ created_session_id: string | null;
814
+ agent_id: string | null;
815
+ phone_number_id: string | null;
816
+ to_number: string;
817
+ from_number: string | null;
818
+ scheduled_at: string;
819
+ status: ScheduledCallbackStatus;
820
+ reason: string | null;
821
+ instructions: string | null;
822
+ summary: string | null;
823
+ pipeline_config: Record<string, unknown>;
824
+ metadata: Record<string, unknown>;
825
+ failure_cause: string | null;
826
+ attempted_at: string | null;
827
+ dispatched_at: string | null;
828
+ cancelled_at: string | null;
829
+ created_at: string;
830
+ updated_at: string;
831
+ }
832
+ export interface ScheduledCallbacksListParams {
833
+ status?: ScheduledCallbackStatus;
834
+ sourceSessionId?: string;
835
+ limit?: number;
836
+ }
837
+ export interface CancelScheduledCallbackParams {
838
+ reason?: string;
839
+ }
840
+ export interface FinalizeCallReportParams {
841
+ forceAnalysis?: boolean;
842
+ retryWebhook?: boolean;
843
+ }
844
+ export interface FinalizeCallReportResult {
845
+ session_id: string;
846
+ summary: string;
847
+ outcome: string;
848
+ cost_micro_usd: string;
849
+ webhook: unknown;
850
+ }
851
+ export interface CallRecording {
852
+ url: string;
853
+ }
854
+ export interface CallEvent {
855
+ id: string;
856
+ session_id: string | null;
857
+ organization_id: string;
858
+ provider: 'livekit' | 'telnyx' | 'speko' | string;
859
+ event_type: string;
860
+ status: string | null;
861
+ failure_cause: string | null;
862
+ sip_status_code: number | null;
863
+ sip_status: string | null;
864
+ occurred_at: string;
865
+ payload: Record<string, unknown>;
866
+ created_at: string;
867
+ }
868
+ export interface CallTransfer {
869
+ id: string;
870
+ session_id: string;
871
+ organization_id: string;
872
+ kind: 'blind' | 'warm';
873
+ status: 'requested' | 'screening' | 'bridging' | 'completed' | 'failed' | 'cancelled';
874
+ transfer_to: string;
875
+ from_room_name: string | null;
876
+ consultation_room_name: string | null;
877
+ caller_participant_identity: string | null;
878
+ recipient_participant_identity: string | null;
879
+ outbound_trunk_id: string | null;
880
+ screening_prompt: string | null;
881
+ summary: string | null;
882
+ failure_cause: string | null;
883
+ metadata: Record<string, unknown>;
884
+ created_at: string;
885
+ updated_at: string;
886
+ completed_at: string | null;
887
+ }
888
+ export interface CallTransferResponse extends CallTransfer {
889
+ routing_attempts?: (CallTransfer | null)[];
890
+ next_transfer?: CallTransfer | null;
891
+ fallback?: WarmTransferFallbackResult | null;
892
+ }
893
+ export interface CallDetail {
894
+ id: string;
895
+ call_id: string;
896
+ resource_uri: string;
897
+ agent_id: string | null;
898
+ status: string;
899
+ kind: string;
900
+ room_name: string | null;
901
+ language: string;
902
+ pipeline_config: Record<string, unknown>;
903
+ metadata: Record<string, unknown>;
904
+ created_at: string;
905
+ updated_at: string;
906
+ ended_at: string | null;
907
+ duration_seconds: number | null;
908
+ recording_status: string | null;
909
+ recording_duration_ms: number | null;
910
+ recording_resource_uri: string;
911
+ report: CallReport | null;
912
+ transfers: CallTransfer[];
913
+ transcript: {
914
+ entries: CallTranscriptEntry[];
915
+ };
916
+ span_tree: Record<string, unknown>;
917
+ }
918
+ export interface BlindTransferParams {
919
+ to: string;
920
+ participantIdentity?: string;
921
+ playDialtone?: boolean;
922
+ ringingTimeout?: number;
923
+ headers?: Record<string, string>;
924
+ }
925
+ export interface WarmTransferDestination {
926
+ to: string;
927
+ label?: string;
928
+ outboundTrunkId?: string;
929
+ screeningPrompt?: string;
930
+ summary?: string;
931
+ metadata?: Record<string, unknown>;
932
+ }
933
+ export interface WarmTransferFallback {
934
+ strategy?: 'return_to_assistant' | 'take_message' | 'end_call';
935
+ message?: string;
936
+ takeMessagePrompt?: string;
937
+ holdAudioUrl?: string;
938
+ }
939
+ export interface WarmTransferVoicemailDetection {
940
+ mode?: 'agent' | 'amd' | 'disabled';
941
+ enabled?: boolean;
942
+ timeoutSeconds?: number;
943
+ }
944
+ export interface WarmTransferFallbackResult {
945
+ action: 'return_to_assistant' | 'take_message' | 'end_call';
946
+ message: string;
947
+ take_message_prompt: string | null;
948
+ hold_audio_url: string | null;
949
+ voicemail_detected: boolean;
950
+ }
951
+ export interface WarmTransferParams {
952
+ to?: string;
953
+ destinations?: WarmTransferDestination[];
954
+ from?: string;
955
+ participantIdentity?: string;
956
+ outboundTrunkId?: string;
957
+ screeningPrompt?: string;
958
+ summary?: string;
959
+ ringingTimeout?: number;
960
+ waitUntilAnswered?: boolean;
961
+ fallback?: WarmTransferFallback;
962
+ voicemailDetection?: WarmTransferVoicemailDetection;
963
+ metadata?: Record<string, unknown>;
964
+ }
965
+ export interface CompleteWarmTransferParams {
966
+ recipientParticipantIdentity?: string;
967
+ summary?: string;
968
+ }
969
+ export interface CancelWarmTransferParams {
970
+ reason?: string;
971
+ summary?: string;
972
+ tryNext?: boolean;
973
+ voicemailDetected?: boolean;
974
+ }
975
+ export interface AgentCallListParams {
976
+ /** Max rows. Default 50, server-capped at 100. */
977
+ limit?: number;
978
+ /** ISO timestamp returned as `next_cursor` from the previous page. */
979
+ cursor?: string;
980
+ /** ISO timestamp lower bound for calls to include. */
981
+ since?: string;
982
+ }
983
+ export interface AgentCallListEntry {
984
+ id: string;
985
+ call_id: string;
986
+ resource_uri: string;
987
+ agent_id: string;
988
+ status: string;
989
+ kind: string;
990
+ room_name: string | null;
991
+ language: string;
992
+ created_at: string;
993
+ ended_at: string | null;
994
+ duration_seconds: number | null;
995
+ recording_status: string | null;
996
+ }
997
+ export interface AgentCallListPage {
998
+ calls: AgentCallListEntry[];
999
+ entries: AgentCallListEntry[];
1000
+ next_cursor: string | null;
486
1001
  }
487
- export type AgentUpdateParams = Partial<AgentCreateParams>;
488
1002
  export interface AgentToolSourceInline {
489
1003
  kind: 'inline';
490
1004
  }
@@ -518,8 +1032,35 @@ export interface AgentToolSourceBuiltin {
518
1032
  name: string;
519
1033
  config?: unknown;
520
1034
  }
521
- export type AgentToolSourceCreate = AgentToolSourceInline | AgentToolSourceWebhookCreate | AgentToolSourceBuiltin;
522
- export type AgentToolSourceSerialized = AgentToolSourceInline | AgentToolSourceWebhookSerialized | AgentToolSourceBuiltin;
1035
+ /**
1036
+ * Integration source binds the tool to an org-installed Speko app action
1037
+ * (e.g. Google Calendar `create_event`). Speko resolves the installation and
1038
+ * runs the action server-side at completion time. The shape is identical on
1039
+ * create and in the serialized row (there is no secret to strip).
1040
+ */
1041
+ export interface AgentToolSourceIntegration {
1042
+ kind: 'integration';
1043
+ installationId: string;
1044
+ appKey: string;
1045
+ actionKey: string;
1046
+ config?: unknown;
1047
+ }
1048
+ /**
1049
+ * Webhook source as sent to {@link AgentTools.update}. Unlike the create
1050
+ * shape, `secret` is optional: omit it to keep the existing encrypted secret
1051
+ * untouched, or supply a new one to rotate it.
1052
+ */
1053
+ export interface AgentToolSourceWebhookUpdate {
1054
+ kind: 'webhook';
1055
+ url: string;
1056
+ /** Plaintext shared secret. Omit to keep the existing stored secret; supply to rotate. */
1057
+ secret?: string;
1058
+ headers?: Record<string, string>;
1059
+ timeoutMs?: number;
1060
+ }
1061
+ export type AgentToolSourceCreate = AgentToolSourceInline | AgentToolSourceWebhookCreate | AgentToolSourceBuiltin | AgentToolSourceIntegration;
1062
+ export type AgentToolSourceSerialized = AgentToolSourceInline | AgentToolSourceWebhookSerialized | AgentToolSourceBuiltin | AgentToolSourceIntegration;
1063
+ export type AgentToolSourceUpdate = AgentToolSourceInline | AgentToolSourceWebhookUpdate | AgentToolSourceBuiltin | AgentToolSourceIntegration;
523
1064
  export interface AgentToolRow {
524
1065
  id: string;
525
1066
  agentId: string;
@@ -539,7 +1080,7 @@ export interface AgentToolCreateParams {
539
1080
  export interface AgentToolUpdateParams {
540
1081
  description?: string;
541
1082
  parameters?: Record<string, unknown>;
542
- source?: AgentToolSourceCreate;
1083
+ source?: AgentToolSourceUpdate;
543
1084
  }
544
1085
  export interface KnowledgeBaseRow {
545
1086
  id: string;