@spekoai/sdk 0.0.3 → 0.3.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +5 -6
  3. package/dist/index.d.ts +1 -1
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/lib/client.d.ts +9 -5
  6. package/dist/lib/client.d.ts.map +1 -1
  7. package/dist/lib/client.js +13 -6
  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 +3 -0
  11. package/dist/lib/resources/complete.d.ts +2 -2
  12. package/dist/lib/resources/complete.js +2 -2
  13. package/dist/lib/resources/credits.d.ts +28 -0
  14. package/dist/lib/resources/credits.d.ts.map +1 -0
  15. package/dist/lib/resources/credits.js +37 -0
  16. package/dist/lib/resources/phone-numbers.d.ts +49 -0
  17. package/dist/lib/resources/phone-numbers.d.ts.map +1 -0
  18. package/dist/lib/resources/phone-numbers.js +66 -0
  19. package/dist/lib/resources/realtime.d.ts +15 -0
  20. package/dist/lib/resources/realtime.d.ts.map +1 -0
  21. package/dist/lib/resources/realtime.js +173 -0
  22. package/dist/lib/resources/synthesize.d.ts +1 -2
  23. package/dist/lib/resources/synthesize.d.ts.map +1 -1
  24. package/dist/lib/resources/synthesize.js +4 -3
  25. package/dist/lib/resources/transcribe.d.ts +1 -2
  26. package/dist/lib/resources/transcribe.d.ts.map +1 -1
  27. package/dist/lib/resources/transcribe.js +8 -5
  28. package/dist/lib/resources/voice.d.ts +29 -0
  29. package/dist/lib/resources/voice.d.ts.map +1 -0
  30. package/dist/lib/resources/voice.js +30 -0
  31. package/dist/lib/types/index.d.ts +233 -52
  32. package/dist/lib/types/index.d.ts.map +1 -1
  33. package/package.json +1 -1
  34. package/dist/lib/resources/sessions.d.ts +0 -44
  35. package/dist/lib/resources/sessions.d.ts.map +0 -1
  36. package/dist/lib/resources/sessions.js +0 -46
package/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ ## 0.3.0 (2026-05-02)
2
+
3
+ ### 🚀 Features
4
+
5
+ - **adapter-livekit:** wire tool calls through /v1/complete ([#105](https://github.com/SpekoAI/platform/pull/105))
6
+ - **dashboard:** /phone-numbers page — buy + edit + release US numbers ([ec3d541](https://github.com/SpekoAI/platform/commit/ec3d541))
7
+ - **telephony:** Telnyx outbound + inbound + phone number CRUD ([c5cc1f0](https://github.com/SpekoAI/platform/commit/c5cc1f0))
8
+
9
+ ### ❤️ Thank You
10
+
11
+ - Baymurat785 @Baymurat785
12
+ - Claude Opus 4.7 (1M context)
13
+
1
14
  # Changelog
2
15
 
3
16
  All notable changes to `@spekoai/sdk` will be documented in this file.
@@ -7,6 +20,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
20
 
8
21
  ## [Unreleased]
9
22
 
23
+ ## [0.2.1] - 2026-04-26
24
+
25
+ ### Added
26
+
27
+ - `RoutingIntent.region` — optional string forwarded to the gateway as
28
+ `intent.region`. Set when latency to a specific geography matters
29
+ (e.g. `'us-east4'`, `'eu-west1'`); STT/TTS rankings differ per
30
+ region. Omitting it preserves the previous behaviour: the server
31
+ defaults to `'global'`, which surfaces the region-agnostic (batch)
32
+ benchmark rows. Plumbed through `transcribe()`, `synthesize()`, and
33
+ `complete({ intent })`.
34
+
35
+ ## [0.2.0] - 2026-04-26
36
+
37
+ ### Removed
38
+
39
+ - **BREAKING**: `RoutingIntent.vertical` removed (and the `Vertical`
40
+ union type along with it). The router now ranks on
41
+ `(language, optimizeFor)` only. Callers passing `vertical` will fail
42
+ to type-check; the gateway also rejects the field. Old persisted
43
+ session pipeline configs containing `vertical` are tolerated server-
44
+ side.
45
+
10
46
  ## [0.0.3] - 2026-04-13
11
47
 
12
48
  ### Fixed
package/README.md CHANGED
@@ -3,8 +3,8 @@
3
3
  Official TypeScript SDK for [Speko](https://speko.ai) — one API, every voice provider.
4
4
 
5
5
  Speko is a voice AI gateway that benchmarks every STT, LLM, and TTS provider
6
- across languages and verticals, then routes each request to the best provider
7
- in real time. Failover is handled. You write one integration; Speko picks the
6
+ across languages, then routes each request to the best provider in real
7
+ time. Failover is handled. You write one integration; Speko picks the
8
8
  right provider for every call.
9
9
 
10
10
  ## Installation
@@ -25,23 +25,22 @@ import { readFile } from 'node:fs/promises';
25
25
 
26
26
  const speko = new Speko({ apiKey: process.env.SPEKO_API_KEY });
27
27
 
28
- // Transcribe — best STT provider auto-routed for your language + vertical
28
+ // Transcribe — best STT provider auto-routed for your language
29
29
  const audio = await readFile('./call.wav');
30
30
  const { text, provider, confidence } = await speko.transcribe(audio, {
31
31
  language: 'es-MX',
32
- vertical: 'healthcare',
32
+ region: 'us-east4', // optional — rank streaming providers in this region
33
33
  });
34
34
 
35
35
  // Synthesize — best TTS provider auto-routed
36
36
  const speech = await speko.synthesize('Hello world', {
37
37
  language: 'en',
38
- vertical: 'general',
39
38
  });
40
39
 
41
40
  // Complete — best LLM provider auto-routed
42
41
  const { text: reply } = await speko.complete({
43
42
  messages: [{ role: 'user', content: 'Hi!' }],
44
- intent: { language: 'en', vertical: 'general' },
43
+ intent: { language: 'en' },
45
44
  });
46
45
  ```
47
46
 
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { Speko } from './lib/client.js';
2
2
  export { SpekoApiError, SpekoAuthError, SpekoRateLimitError } from './lib/errors.js';
3
- export type { SpekoClientOptions, PipelineConfig, CreateSessionParams, Session, SessionDetail, UsageSummary, UsageByProvider, UsageQueryParams, Vertical, OptimizeFor, RoutingIntent, TranscribeOptions, TranscribeResult, SynthesizeOptions, SynthesizeResult, ChatMessage, CompleteParams, CompleteResult, } from './lib/types/index.js';
3
+ export type { SpekoClientOptions, KeySource, UsageSummary, UsageByProvider, UsageQueryParams, OrganizationBalance, CreditLedgerEntry, CreditLedgerKind, CreditLedgerPage, CreditLedgerQueryParams, OptimizeFor, RoutingIntent, PipelineConstraints, TranscribeOptions, TranscribeResult, SynthesizeOptions, SynthesizeResult, ChatMessage, ChatTool, ChatToolCall, ChatToolChoice, CompleteParams, CompleteResult, RealtimeProvider, RealtimeToolSpec, RealtimeConnectParams, RealtimeFrame, RealtimeEventHandler, RealtimeSessionHandle, VoiceDialParams, VoiceDialResult, PhoneNumberDirection, PhoneNumberRow, PhoneNumberCreateParams, PhoneNumberUpdateParams, AvailablePhoneNumber, PhoneNumberSearchParams, } from './lib/types/index.js';
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACrF,YAAY,EACV,kBAAkB,EAClB,cAAc,EACd,mBAAmB,EACnB,OAAO,EACP,aAAa,EACb,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,QAAQ,EACR,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,cAAc,GACf,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACrF,YAAY,EACV,kBAAkB,EAClB,SAAS,EACT,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,uBAAuB,EACvB,WAAW,EACX,aAAa,EACb,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,qBAAqB,EACrB,aAAa,EACb,oBAAoB,EACpB,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,oBAAoB,EACpB,cAAc,EACd,uBAAuB,EACvB,uBAAuB,EACvB,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,sBAAsB,CAAC"}
@@ -1,6 +1,9 @@
1
1
  import type { CompleteParams, CompleteResult, SpekoClientOptions, SynthesizeOptions, SynthesizeResult, TranscribeOptions, TranscribeResult } from './types/index.js';
2
- import { Sessions } from './resources/sessions.js';
3
2
  import { Usage } from './resources/usage.js';
3
+ import { Credits } from './resources/credits.js';
4
+ import { Realtime } from './resources/realtime.js';
5
+ import { Voice } from './resources/voice.js';
6
+ import { PhoneNumbers } from './resources/phone-numbers.js';
4
7
  /**
5
8
  * Speko client — one API, every voice provider.
6
9
  *
@@ -12,21 +15,22 @@ import { Usage } from './resources/usage.js';
12
15
  *
13
16
  * const { text, provider } = await speko.transcribe(audioBytes, {
14
17
  * language: 'es-MX',
15
- * vertical: 'healthcare',
16
18
  * });
17
19
  * ```
18
20
  */
19
21
  export declare class Speko {
20
- /** Real-time voice sessions over LiveKit (back-compat path). */
21
- readonly sessions: Sessions;
22
22
  readonly usage: Usage;
23
+ readonly credits: Credits;
24
+ readonly realtime: Realtime;
25
+ readonly voice: Voice;
26
+ readonly phoneNumbers: PhoneNumbers;
23
27
  private readonly transcribeResource;
24
28
  private readonly synthesizeResource;
25
29
  private readonly completeResource;
26
30
  constructor(options: SpekoClientOptions);
27
31
  /**
28
32
  * Transcribe audio. The router picks the best STT provider for your
29
- * `(language, vertical, optimizeFor)` and fails over automatically.
33
+ * `(language, optimizeFor)` and fails over automatically.
30
34
  *
31
35
  * Pass an `AbortSignal` to cancel the in-flight request — useful when a
32
36
  * calling framework (e.g. LiveKit Agents) tears down a session mid-call.
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/lib/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAQ7C;;;;;;;;;;;;;;GAcG;AACH,qBAAa,KAAK;IAChB,gEAAgE;IAChE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAEtB,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAa;IAChD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAa;IAChD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAW;gBAEhC,OAAO,EAAE,kBAAkB;IAoBvC;;;;;;OAMG;IACH,UAAU,CACR,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,iBAAiB,EAC1B,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,gBAAgB,CAAC;IAI5B;;;;OAIG;IACH,UAAU,CACR,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,iBAAiB,EAC1B,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,gBAAgB,CAAC;IAI5B;;;OAGG;IACH,QAAQ,CACN,MAAM,EAAE,cAAc,EACtB,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,cAAc,CAAC;CAG3B"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/lib/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAIjD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAK5D;;;;;;;;;;;;;GAaG;AACH,qBAAa,KAAK;IAChB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IAEpC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAa;IAChD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAa;IAChD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAW;gBAEhC,OAAO,EAAE,kBAAkB;IAuBvC;;;;;;OAMG;IACH,UAAU,CACR,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,iBAAiB,EAC1B,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,gBAAgB,CAAC;IAI5B;;;;OAIG;IACH,UAAU,CACR,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,iBAAiB,EAC1B,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,gBAAgB,CAAC;IAI5B;;;OAGG;IACH,QAAQ,CACN,MAAM,EAAE,cAAc,EACtB,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,cAAc,CAAC;CAG3B"}
@@ -1,9 +1,12 @@
1
1
  import { HttpClient } from './http.js';
2
- import { Sessions } from './resources/sessions.js';
3
2
  import { Usage } from './resources/usage.js';
3
+ import { Credits } from './resources/credits.js';
4
4
  import { Transcribe } from './resources/transcribe.js';
5
5
  import { Synthesize } from './resources/synthesize.js';
6
6
  import { Complete } from './resources/complete.js';
7
+ import { Realtime } from './resources/realtime.js';
8
+ import { Voice } from './resources/voice.js';
9
+ import { PhoneNumbers } from './resources/phone-numbers.js';
7
10
  const DEFAULT_BASE_URL = 'https://api.speko.ai';
8
11
  const DEFAULT_TIMEOUT = 30_000;
9
12
  /**
@@ -17,14 +20,15 @@ const DEFAULT_TIMEOUT = 30_000;
17
20
  *
18
21
  * const { text, provider } = await speko.transcribe(audioBytes, {
19
22
  * language: 'es-MX',
20
- * vertical: 'healthcare',
21
23
  * });
22
24
  * ```
23
25
  */
24
26
  export class Speko {
25
- /** Real-time voice sessions over LiveKit (back-compat path). */
26
- sessions;
27
27
  usage;
28
+ credits;
29
+ realtime;
30
+ voice;
31
+ phoneNumbers;
28
32
  transcribeResource;
29
33
  synthesizeResource;
30
34
  completeResource;
@@ -37,15 +41,18 @@ export class Speko {
37
41
  apiKey: options.apiKey,
38
42
  timeout: options.timeout ?? DEFAULT_TIMEOUT,
39
43
  });
40
- this.sessions = new Sessions(http);
41
44
  this.usage = new Usage(http);
45
+ this.credits = new Credits(http);
46
+ this.realtime = new Realtime(http);
47
+ this.voice = new Voice(http);
48
+ this.phoneNumbers = new PhoneNumbers(http);
42
49
  this.transcribeResource = new Transcribe(http);
43
50
  this.synthesizeResource = new Synthesize(http);
44
51
  this.completeResource = new Complete(http);
45
52
  }
46
53
  /**
47
54
  * Transcribe audio. The router picks the best STT provider for your
48
- * `(language, vertical, optimizeFor)` and fails over automatically.
55
+ * `(language, optimizeFor)` and fails over automatically.
49
56
  *
50
57
  * Pass an `AbortSignal` to cancel the in-flight request — useful when a
51
58
  * calling framework (e.g. LiveKit Agents) tears down a session mid-call.
@@ -13,6 +13,7 @@ export declare class HttpClient {
13
13
  get<T>(path: string, externalSignal?: AbortSignal): Promise<T>;
14
14
  post<T>(path: string, body: unknown, externalSignal?: AbortSignal): Promise<T>;
15
15
  delete<T>(path: string, externalSignal?: AbortSignal): Promise<T>;
16
+ patch<T>(path: string, body: unknown, externalSignal?: AbortSignal): Promise<T>;
16
17
  /**
17
18
  * Send raw bytes as the request body and parse a JSON response.
18
19
  * Used by `speko.transcribe()` to upload audio and receive a transcript.
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/lib/http.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAID,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAyB;IACrD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,OAAO,EAAE,iBAAiB;IAWhC,OAAO,CAAC,CAAC,EACb,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,OAAO,EACd,cAAc,CAAC,EAAE,WAAW,GAC3B,OAAO,CAAC,CAAC,CAAC;IAsBP,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC;IAI9D,IAAI,CAAC,CAAC,EACV,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,OAAO,EACb,cAAc,CAAC,EAAE,WAAW,GAC3B,OAAO,CAAC,CAAC,CAAC;IAIP,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC;IAIvE;;;OAGG;IACG,UAAU,CAAC,CAAC,EAChB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,UAAU,EACrB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,cAAc,CAAC,EAAE,WAAW,GAC3B,OAAO,CAAC,CAAC,CAAC;IA4Bb;;;;OAIG;IACG,aAAa,CACjB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,OAAO,EACb,cAAc,CAAC,EAAE,WAAW,GAC3B,OAAO,CAAC;QAAE,KAAK,EAAE,UAAU,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAC;IA4BlE;;;;OAIG;IACH,OAAO,CAAC,WAAW;YA6BL,WAAW;CA4B1B"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/lib/http.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAID,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAyB;IACrD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,OAAO,EAAE,iBAAiB;IAWhC,OAAO,CAAC,CAAC,EACb,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,OAAO,EACd,cAAc,CAAC,EAAE,WAAW,GAC3B,OAAO,CAAC,CAAC,CAAC;IAsBP,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC;IAI9D,IAAI,CAAC,CAAC,EACV,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,OAAO,EACb,cAAc,CAAC,EAAE,WAAW,GAC3B,OAAO,CAAC,CAAC,CAAC;IAIP,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC;IAIjE,KAAK,CAAC,CAAC,EACX,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,OAAO,EACb,cAAc,CAAC,EAAE,WAAW,GAC3B,OAAO,CAAC,CAAC,CAAC;IAIb;;;OAGG;IACG,UAAU,CAAC,CAAC,EAChB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,UAAU,EACrB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,cAAc,CAAC,EAAE,WAAW,GAC3B,OAAO,CAAC,CAAC,CAAC;IA4Bb;;;;OAIG;IACG,aAAa,CACjB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,OAAO,EACb,cAAc,CAAC,EAAE,WAAW,GAC3B,OAAO,CAAC;QAAE,KAAK,EAAE,UAAU,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAC;IA4BlE;;;;OAIG;IACH,OAAO,CAAC,WAAW;YA6BL,WAAW;CA4B1B"}
package/dist/lib/http.js CHANGED
@@ -43,6 +43,9 @@ export class HttpClient {
43
43
  async delete(path, externalSignal) {
44
44
  return this.request('DELETE', path, undefined, externalSignal);
45
45
  }
46
+ async patch(path, body, externalSignal) {
47
+ return this.request('PATCH', path, body, externalSignal);
48
+ }
46
49
  /**
47
50
  * Send raw bytes as the request body and parse a JSON response.
48
51
  * Used by `speko.transcribe()` to upload audio and receive a transcript.
@@ -5,13 +5,13 @@ export declare class Complete {
5
5
  constructor(http: HttpClient);
6
6
  /**
7
7
  * Run an LLM completion. The Speko router picks the best provider for your
8
- * `(language, vertical, optimizeFor)` and falls over automatically.
8
+ * `(language, optimizeFor)` and falls over automatically.
9
9
  *
10
10
  * @example
11
11
  * ```ts
12
12
  * const { text, provider } = await speko.complete({
13
13
  * messages: [{ role: 'user', content: 'Hi!' }],
14
- * intent: { language: 'en', vertical: 'general' },
14
+ * intent: { language: 'en' },
15
15
  * });
16
16
  * ```
17
17
  */
@@ -5,13 +5,13 @@ export class Complete {
5
5
  }
6
6
  /**
7
7
  * Run an LLM completion. The Speko router picks the best provider for your
8
- * `(language, vertical, optimizeFor)` and falls over automatically.
8
+ * `(language, optimizeFor)` and falls over automatically.
9
9
  *
10
10
  * @example
11
11
  * ```ts
12
12
  * const { text, provider } = await speko.complete({
13
13
  * messages: [{ role: 'user', content: 'Hi!' }],
14
- * intent: { language: 'en', vertical: 'general' },
14
+ * intent: { language: 'en' },
15
15
  * });
16
16
  * ```
17
17
  */
@@ -0,0 +1,28 @@
1
+ import type { HttpClient } from '../http.js';
2
+ import type { CreditLedgerPage, CreditLedgerQueryParams, OrganizationBalance } from '../types/index.js';
3
+ /**
4
+ * Prepaid credit balance + append-only ledger. Balance is reported in
5
+ * micro-USD (`1_000_000` µ$ = $1) alongside a float USD helper.
6
+ */
7
+ export declare class Credits {
8
+ private readonly http;
9
+ constructor(http: HttpClient);
10
+ /**
11
+ * Current credit balance for the caller's organization.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * const { balanceUsd } = await speko.credits.getBalance();
16
+ * if (balanceUsd < 0.5) showLowBalanceBanner();
17
+ * ```
18
+ */
19
+ getBalance(): Promise<OrganizationBalance>;
20
+ /**
21
+ * Most-recent-first page of credit movements (grants, debits, topups,
22
+ * refunds, adjustments). `nextCursor` is the `createdAt` of the last
23
+ * entry on the current page — pass it back as `cursor` to fetch the
24
+ * next page; `null` means no more pages.
25
+ */
26
+ getLedger(params?: CreditLedgerQueryParams): Promise<CreditLedgerPage>;
27
+ }
28
+ //# sourceMappingURL=credits.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credits.d.ts","sourceRoot":"","sources":["../../../src/lib/resources/credits.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EACV,gBAAgB,EAChB,uBAAuB,EACvB,mBAAmB,EACpB,MAAM,mBAAmB,CAAC;AAE3B;;;GAGG;AACH,qBAAa,OAAO;IACN,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAE7C;;;;;;;;OAQG;IACH,UAAU,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAI1C;;;;;OAKG;IACH,SAAS,CAAC,MAAM,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAUvE"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Prepaid credit balance + append-only ledger. Balance is reported in
3
+ * micro-USD (`1_000_000` µ$ = $1) alongside a float USD helper.
4
+ */
5
+ export class Credits {
6
+ http;
7
+ constructor(http) {
8
+ this.http = http;
9
+ }
10
+ /**
11
+ * Current credit balance for the caller's organization.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * const { balanceUsd } = await speko.credits.getBalance();
16
+ * if (balanceUsd < 0.5) showLowBalanceBanner();
17
+ * ```
18
+ */
19
+ getBalance() {
20
+ return this.http.get('/v1/credits/balance');
21
+ }
22
+ /**
23
+ * Most-recent-first page of credit movements (grants, debits, topups,
24
+ * refunds, adjustments). `nextCursor` is the `createdAt` of the last
25
+ * entry on the current page — pass it back as `cursor` to fetch the
26
+ * next page; `null` means no more pages.
27
+ */
28
+ getLedger(params) {
29
+ const query = new URLSearchParams();
30
+ if (params?.limit)
31
+ query.set('limit', String(params.limit));
32
+ if (params?.cursor)
33
+ query.set('cursor', params.cursor);
34
+ const qs = query.toString();
35
+ return this.http.get(`/v1/credits/ledger${qs ? `?${qs}` : ''}`);
36
+ }
37
+ }
@@ -0,0 +1,49 @@
1
+ import type { HttpClient } from '../http.js';
2
+ import type { AvailablePhoneNumber, PhoneNumberCreateParams, PhoneNumberRow, PhoneNumberSearchParams, PhoneNumberUpdateParams } from '../types/index.js';
3
+ /**
4
+ * Phone numbers Speko has provisioned (or imported) on Telnyx for your
5
+ * organization. Each number can be used for outbound dialing and/or
6
+ * inbound, and carries an optional metadata template that's merged into
7
+ * the worker dispatch payload when the number is used.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * // List org's numbers
12
+ * const numbers = await speko.phoneNumbers.list();
13
+ *
14
+ * // Provision a new US local number
15
+ * const num = await speko.phoneNumbers.create({
16
+ * e164: '+12015551234',
17
+ * direction: 'both',
18
+ * label: 'Sales line',
19
+ * dispatchMetadataTemplate: {
20
+ * intent: { language: 'en', optimizeFor: 'latency' },
21
+ * systemPrompt: 'You are a helpful sales agent for Acme.',
22
+ * },
23
+ * });
24
+ * ```
25
+ */
26
+ export declare class PhoneNumbers {
27
+ private readonly http;
28
+ constructor(http: HttpClient);
29
+ list(): Promise<PhoneNumberRow[]>;
30
+ /**
31
+ * Search Telnyx's pool for orderable US numbers. Filter by area code
32
+ * and/or locality. Results include cost so you can preview "$1 upfront +
33
+ * $1/month" before committing to {@link create}.
34
+ *
35
+ * @example
36
+ * ```ts
37
+ * const candidates = await speko.phoneNumbers.searchAvailable({ areaCode: '415' });
38
+ * console.log(candidates[0].friendlyName); // "+1 (415) 555-0123"
39
+ * ```
40
+ */
41
+ searchAvailable(params?: PhoneNumberSearchParams): Promise<AvailablePhoneNumber[]>;
42
+ get(id: string): Promise<PhoneNumberRow>;
43
+ create(params: PhoneNumberCreateParams): Promise<PhoneNumberRow>;
44
+ update(id: string, params: PhoneNumberUpdateParams): Promise<PhoneNumberRow>;
45
+ delete(id: string): Promise<{
46
+ released: boolean;
47
+ }>;
48
+ }
49
+ //# sourceMappingURL=phone-numbers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"phone-numbers.d.ts","sourceRoot":"","sources":["../../../src/lib/resources/phone-numbers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EACV,oBAAoB,EACpB,uBAAuB,EACvB,cAAc,EACd,uBAAuB,EACvB,uBAAuB,EACxB,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,YAAY;IACX,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAE7C,IAAI,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAIjC;;;;;;;;;;OAUG;IACH,eAAe,CACb,MAAM,GAAE,uBAA4B,GACnC,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAWlC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAMxC,MAAM,CAAC,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC,cAAc,CAAC;IAIhE,MAAM,CACJ,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,uBAAuB,GAC9B,OAAO,CAAC,cAAc,CAAC;IAO1B,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;CAKnD"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Phone numbers Speko has provisioned (or imported) on Telnyx for your
3
+ * organization. Each number can be used for outbound dialing and/or
4
+ * inbound, and carries an optional metadata template that's merged into
5
+ * the worker dispatch payload when the number is used.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * // List org's numbers
10
+ * const numbers = await speko.phoneNumbers.list();
11
+ *
12
+ * // Provision a new US local number
13
+ * const num = await speko.phoneNumbers.create({
14
+ * e164: '+12015551234',
15
+ * direction: 'both',
16
+ * label: 'Sales line',
17
+ * dispatchMetadataTemplate: {
18
+ * intent: { language: 'en', optimizeFor: 'latency' },
19
+ * systemPrompt: 'You are a helpful sales agent for Acme.',
20
+ * },
21
+ * });
22
+ * ```
23
+ */
24
+ export class PhoneNumbers {
25
+ http;
26
+ constructor(http) {
27
+ this.http = http;
28
+ }
29
+ list() {
30
+ return this.http.get('/v1/phone-numbers');
31
+ }
32
+ /**
33
+ * Search Telnyx's pool for orderable US numbers. Filter by area code
34
+ * and/or locality. Results include cost so you can preview "$1 upfront +
35
+ * $1/month" before committing to {@link create}.
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * const candidates = await speko.phoneNumbers.searchAvailable({ areaCode: '415' });
40
+ * console.log(candidates[0].friendlyName); // "+1 (415) 555-0123"
41
+ * ```
42
+ */
43
+ searchAvailable(params = {}) {
44
+ const query = new URLSearchParams();
45
+ if (params.areaCode)
46
+ query.set('areaCode', params.areaCode);
47
+ if (params.locality)
48
+ query.set('locality', params.locality);
49
+ if (params.limit !== undefined)
50
+ query.set('limit', String(params.limit));
51
+ const qs = query.toString();
52
+ return this.http.get(`/v1/phone-numbers/available${qs ? `?${qs}` : ''}`);
53
+ }
54
+ get(id) {
55
+ return this.http.get(`/v1/phone-numbers/${encodeURIComponent(id)}`);
56
+ }
57
+ create(params) {
58
+ return this.http.post('/v1/phone-numbers', params);
59
+ }
60
+ update(id, params) {
61
+ return this.http.patch(`/v1/phone-numbers/${encodeURIComponent(id)}`, params);
62
+ }
63
+ delete(id) {
64
+ return this.http.delete(`/v1/phone-numbers/${encodeURIComponent(id)}`);
65
+ }
66
+ }
@@ -0,0 +1,15 @@
1
+ import type { HttpClient } from '../http.js';
2
+ import type { RealtimeConnectParams, RealtimeSessionHandle } from '../types/index.js';
3
+ export declare class Realtime {
4
+ private readonly http;
5
+ constructor(http: HttpClient);
6
+ /**
7
+ * Open a speech-to-speech session. Posts `/v1/sessions` with `mode: 's2s'`
8
+ * to mint a short-lived WebSocket token, then opens a direct WS to the
9
+ * server's S2S proxy. The proxy bridges to the underlying provider
10
+ * (OpenAI Realtime, Gemini Live, xAI Grok Voice) so the client sees a
11
+ * single transport regardless of which backend is in use.
12
+ */
13
+ connect(params: RealtimeConnectParams): Promise<RealtimeSessionHandle>;
14
+ }
15
+ //# sourceMappingURL=realtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime.d.ts","sourceRoot":"","sources":["../../../src/lib/resources/realtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EACV,qBAAqB,EAGrB,qBAAqB,EACtB,MAAM,mBAAmB,CAAC;AAU3B,qBAAa,QAAQ;IACP,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAE7C;;;;;;OAMG;IACG,OAAO,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,qBAAqB,CAAC;CA2B7E"}
@@ -0,0 +1,173 @@
1
+ export class Realtime {
2
+ http;
3
+ constructor(http) {
4
+ this.http = http;
5
+ }
6
+ /**
7
+ * Open a speech-to-speech session. Posts `/v1/sessions` with `mode: 's2s'`
8
+ * to mint a short-lived WebSocket token, then opens a direct WS to the
9
+ * server's S2S proxy. The proxy bridges to the underlying provider
10
+ * (OpenAI Realtime, Gemini Live, xAI Grok Voice) so the client sees a
11
+ * single transport regardless of which backend is in use.
12
+ */
13
+ async connect(params) {
14
+ const response = await this.http.post('/v1/sessions', {
15
+ mode: 's2s',
16
+ s2s: {
17
+ provider: params.provider,
18
+ model: params.model,
19
+ voice: params.voice,
20
+ systemPrompt: params.systemPrompt,
21
+ temperature: params.temperature,
22
+ inputSampleRate: params.inputSampleRate,
23
+ outputSampleRate: params.outputSampleRate,
24
+ tools: params.tools,
25
+ },
26
+ metadata: params.metadata,
27
+ ttlSeconds: params.ttlSeconds,
28
+ });
29
+ return new BrowserRealtimeHandle(response.sessionId, response.wsUrl, response.wsToken, response.expiresAt);
30
+ }
31
+ }
32
+ class BrowserRealtimeHandle {
33
+ sessionId;
34
+ expiresAt;
35
+ ws;
36
+ handlers = new Set();
37
+ closed = false;
38
+ constructor(sessionId, wsUrl, wsToken, expiresAt) {
39
+ this.sessionId = sessionId;
40
+ this.expiresAt = expiresAt;
41
+ // Pass the token as the first subprotocol — browsers can't set headers
42
+ // on `new WebSocket()`, so subprotocol is the only auth carrier that
43
+ // doesn't leak through URL params.
44
+ this.ws = new WebSocket(wsUrl, [wsToken]);
45
+ this.ws.binaryType = 'arraybuffer';
46
+ this.ws.addEventListener('message', (evt) => {
47
+ this.dispatchIncoming(evt.data);
48
+ });
49
+ this.ws.addEventListener('close', (evt) => {
50
+ this.closed = true;
51
+ this.emit({ type: 'close', code: evt.code, reason: evt.reason });
52
+ });
53
+ this.ws.addEventListener('error', () => {
54
+ this.emit({
55
+ type: 'error',
56
+ code: 'WS_ERROR',
57
+ message: 'WebSocket transport error',
58
+ });
59
+ });
60
+ }
61
+ sendAudio(pcm) {
62
+ if (this.closed || this.ws.readyState !== 1)
63
+ return;
64
+ // Copy to ensure we send a plain ArrayBuffer, not a typed-array view that
65
+ // might alias a SharedArrayBuffer.
66
+ const copy = new Uint8Array(pcm.byteLength);
67
+ copy.set(pcm);
68
+ this.ws.send(copy.buffer);
69
+ }
70
+ commit() {
71
+ this.sendControl('commit');
72
+ }
73
+ interrupt() {
74
+ this.sendJson({ t: 'interrupt' });
75
+ }
76
+ sendToolResult(callId, output) {
77
+ this.sendJson({ t: 'tool_result', callId, output });
78
+ }
79
+ on(handler) {
80
+ this.handlers.add(handler);
81
+ return () => {
82
+ this.handlers.delete(handler);
83
+ };
84
+ }
85
+ close(code = 1000, reason = 'client_closed') {
86
+ if (this.closed)
87
+ return;
88
+ this.closed = true;
89
+ try {
90
+ this.ws.close(code, reason);
91
+ }
92
+ catch {
93
+ // ignore
94
+ }
95
+ }
96
+ sendControl(action) {
97
+ this.sendJson({ t: 'control', action });
98
+ }
99
+ sendJson(payload) {
100
+ if (this.closed || this.ws.readyState !== 1)
101
+ return;
102
+ try {
103
+ this.ws.send(JSON.stringify(payload));
104
+ }
105
+ catch {
106
+ // ignore
107
+ }
108
+ }
109
+ dispatchIncoming(data) {
110
+ if (data instanceof ArrayBuffer) {
111
+ this.emit({
112
+ type: 'audio',
113
+ pcm: new Uint8Array(data),
114
+ sampleRate: 24000,
115
+ });
116
+ return;
117
+ }
118
+ if (typeof data !== 'string')
119
+ return;
120
+ let parsed;
121
+ try {
122
+ parsed = JSON.parse(data);
123
+ }
124
+ catch {
125
+ return;
126
+ }
127
+ const t = parsed['t'];
128
+ switch (t) {
129
+ case 'transcript':
130
+ this.emit({
131
+ type: 'transcript',
132
+ role: parsed['role'],
133
+ text: String(parsed['text'] ?? ''),
134
+ final: Boolean(parsed['final']),
135
+ });
136
+ break;
137
+ case 'tool_call':
138
+ this.emit({
139
+ type: 'tool_call',
140
+ callId: String(parsed['callId'] ?? ''),
141
+ name: String(parsed['name'] ?? ''),
142
+ arguments: String(parsed['arguments'] ?? ''),
143
+ });
144
+ break;
145
+ case 'usage':
146
+ this.emit({
147
+ type: 'usage',
148
+ inputAudioTokens: Number(parsed['inputAudioTokens'] ?? 0),
149
+ outputAudioTokens: Number(parsed['outputAudioTokens'] ?? 0),
150
+ });
151
+ break;
152
+ case 'error':
153
+ this.emit({
154
+ type: 'error',
155
+ code: String(parsed['code'] ?? 'UNKNOWN'),
156
+ message: String(parsed['message'] ?? ''),
157
+ });
158
+ break;
159
+ default:
160
+ break;
161
+ }
162
+ }
163
+ emit(frame) {
164
+ for (const handler of this.handlers) {
165
+ try {
166
+ handler(frame);
167
+ }
168
+ catch {
169
+ // swallow — a misbehaving handler shouldn't break the pump
170
+ }
171
+ }
172
+ }
173
+ }