@spekoai/sdk 0.4.3 → 0.5.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 (71) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +88 -0
  3. package/dist/index.d.ts +3 -1
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +1 -0
  6. package/dist/lib/client.d.ts +13 -1
  7. package/dist/lib/client.d.ts.map +1 -1
  8. package/dist/lib/client.js +22 -2
  9. package/dist/lib/http.d.ts +12 -4
  10. package/dist/lib/http.d.ts.map +1 -1
  11. package/dist/lib/http.js +31 -14
  12. package/dist/lib/resources/agents.d.ts +12 -2
  13. package/dist/lib/resources/agents.d.ts.map +1 -1
  14. package/dist/lib/resources/agents.js +12 -4
  15. package/dist/lib/resources/calls.d.ts +19 -1
  16. package/dist/lib/resources/calls.d.ts.map +1 -1
  17. package/dist/lib/resources/calls.js +22 -0
  18. package/dist/lib/resources/knowledge-bases.d.ts +1 -1
  19. package/dist/lib/resources/knowledge-bases.js +1 -1
  20. package/dist/lib/resources/phone-numbers.d.ts +2 -1
  21. package/dist/lib/resources/phone-numbers.d.ts.map +1 -1
  22. package/dist/lib/resources/phone-numbers.js +2 -1
  23. package/dist/lib/resources/realtime.d.ts +3 -5
  24. package/dist/lib/resources/realtime.d.ts.map +1 -1
  25. package/dist/lib/resources/realtime.js +829 -91
  26. package/dist/lib/resources/sessions.d.ts +53 -0
  27. package/dist/lib/resources/sessions.d.ts.map +1 -0
  28. package/dist/lib/resources/sessions.js +166 -0
  29. package/dist/lib/resources/sms.d.ts +80 -0
  30. package/dist/lib/resources/sms.d.ts.map +1 -0
  31. package/dist/lib/resources/sms.js +152 -0
  32. package/dist/lib/resources/synthesize.d.ts.map +1 -1
  33. package/dist/lib/resources/synthesize.js +12 -6
  34. package/dist/lib/resources/transcribe.d.ts.map +1 -1
  35. package/dist/lib/resources/transcribe.js +9 -2
  36. package/dist/lib/resources/voice.d.ts +283 -1
  37. package/dist/lib/resources/voice.d.ts.map +1 -1
  38. package/dist/lib/resources/voice.js +345 -0
  39. package/dist/lib/resources/webhooks.d.ts +25 -0
  40. package/dist/lib/resources/webhooks.d.ts.map +1 -0
  41. package/dist/lib/resources/webhooks.js +46 -0
  42. package/dist/lib/types/index.d.ts +998 -9
  43. package/dist/lib/types/index.d.ts.map +1 -1
  44. package/dist/lib/voice-contract.d.ts +280 -0
  45. package/dist/lib/voice-contract.d.ts.map +1 -0
  46. package/dist/lib/voice-contract.js +115 -0
  47. package/package.json +2 -1
  48. package/src/index.ts +212 -0
  49. package/src/lib/client.ts +169 -0
  50. package/src/lib/errors.ts +28 -0
  51. package/src/lib/http.ts +442 -0
  52. package/src/lib/resources/agents.ts +211 -0
  53. package/src/lib/resources/callbacks.ts +40 -0
  54. package/src/lib/resources/calls.ts +113 -0
  55. package/src/lib/resources/complete.ts +63 -0
  56. package/src/lib/resources/credits.ts +41 -0
  57. package/src/lib/resources/knowledge-bases.ts +199 -0
  58. package/src/lib/resources/phone-numbers.ts +109 -0
  59. package/src/lib/resources/realtime-globals.d.ts +31 -0
  60. package/src/lib/resources/realtime.spec.ts +565 -0
  61. package/src/lib/resources/realtime.ts +1169 -0
  62. package/src/lib/resources/sessions.ts +191 -0
  63. package/src/lib/resources/sms.ts +214 -0
  64. package/src/lib/resources/synthesize.ts +101 -0
  65. package/src/lib/resources/transcribe.ts +91 -0
  66. package/src/lib/resources/usage.ts +24 -0
  67. package/src/lib/resources/voice.ts +426 -0
  68. package/src/lib/resources/voices.ts +32 -0
  69. package/src/lib/resources/webhooks.ts +67 -0
  70. package/src/lib/types/index.ts +2409 -0
  71. package/src/lib/voice-contract.ts +358 -0
@@ -0,0 +1,53 @@
1
+ import type { HttpClient } from '../http.js';
2
+ import type { EndCallResult, SessionStreamEvent, SessionStreamOptions, SessionTranscript } from '../types/index.js';
3
+ /**
4
+ * Session-scoped reads. A `sessionId` is the id returned by
5
+ * `voice.dial(...)` / session create — the same id `calls.*` accepts.
6
+ */
7
+ export declare class Sessions {
8
+ private readonly http;
9
+ constructor(http: HttpClient);
10
+ /**
11
+ * End a live session now (kill switch): tears the room down, which drops
12
+ * every participant; the normal close + metering flow runs server-side.
13
+ * Works for any session kind — browser/WebRTC sessions included. Alias of
14
+ * `calls.end()`, which accepts the same session id. Resolves with
15
+ * `status: 'ending'` once teardown is requested, or
16
+ * `status: 'already_ended'` if the session was over. Use this from your
17
+ * backend to stop billing for a session your client can no longer reach
18
+ * (for example an abandoned browser tab).
19
+ */
20
+ end(sessionId: string): Promise<EndCallResult>;
21
+ /**
22
+ * Transcript of a session, oldest turn first — the point-in-time snapshot.
23
+ * For live consumption prefer `stream()`, which pushes each turn as it
24
+ * lands; this endpoint stays the final word on per-turn latency numbers
25
+ * (legs keep enriching after a turn is first written).
26
+ */
27
+ transcript(sessionId: string): Promise<SessionTranscript>;
28
+ /**
29
+ * Observe a session live: transcript turns, call events, and status changes
30
+ * pushed as they happen (SSE under the hood). Iterate until `end` — the
31
+ * SDK reconnects through server stream rotations and transient drops with
32
+ * an internal cursor, so consumers never poll and never see duplicates.
33
+ *
34
+ * ```ts
35
+ * for await (const ev of speko.sessions.stream(sessionId)) {
36
+ * if (ev.type === 'transcript') render(ev.turn);
37
+ * if (ev.type === 'event') timeline(ev.event.event_type);
38
+ * if (ev.type === 'end') break; // session over
39
+ * }
40
+ * ```
41
+ *
42
+ * A stream opened on an already-ended session replays the backlog and then
43
+ * ends, so late subscribers converge on the same picture.
44
+ *
45
+ * The no-duplicates guarantee holds per iterator: reconnects re-read a
46
+ * short server-side overlap window, and this iterator filters the replays
47
+ * by event id. A brand-new iterator resumed via `options.cursor` (process
48
+ * restart) starts with no memory and may replay up to ~2 s of events —
49
+ * dedupe by `event.id` if that matters to you.
50
+ */
51
+ stream(sessionId: string, options?: SessionStreamOptions): AsyncIterableIterator<SessionStreamEvent>;
52
+ }
53
+ //# sourceMappingURL=sessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../../src/lib/resources/sessions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAEV,aAAa,EACb,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EAElB,MAAM,mBAAmB,CAAC;AAW3B;;;GAGG;AACH,qBAAa,QAAQ;IACP,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAE7C;;;;;;;;;OASG;IACH,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAI9C;;;;;OAKG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAMzD;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACI,MAAM,CACX,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,oBAAyB,GACjC,qBAAqB,CAAC,kBAAkB,CAAC;CA+G7C"}
@@ -0,0 +1,166 @@
1
+ import { SpekoApiError } from '../errors.js';
2
+ /** Consecutive failed connect attempts (no frame received) before giving up. */
3
+ const MAX_RECONNECT_ATTEMPTS = 10;
4
+ /**
5
+ * Per-connection cap, above the server's own stream rotation (10 min +
6
+ * `end {reason:'timeout'}`) so the server always rotates first and this
7
+ * client-side abort only nets a server that went quiet.
8
+ */
9
+ const STREAM_REQUEST_TIMEOUT_MS = 15 * 60_000;
10
+ /**
11
+ * Session-scoped reads. A `sessionId` is the id returned by
12
+ * `voice.dial(...)` / session create — the same id `calls.*` accepts.
13
+ */
14
+ export class Sessions {
15
+ http;
16
+ constructor(http) {
17
+ this.http = http;
18
+ }
19
+ /**
20
+ * End a live session now (kill switch): tears the room down, which drops
21
+ * every participant; the normal close + metering flow runs server-side.
22
+ * Works for any session kind — browser/WebRTC sessions included. Alias of
23
+ * `calls.end()`, which accepts the same session id. Resolves with
24
+ * `status: 'ending'` once teardown is requested, or
25
+ * `status: 'already_ended'` if the session was over. Use this from your
26
+ * backend to stop billing for a session your client can no longer reach
27
+ * (for example an abandoned browser tab).
28
+ */
29
+ end(sessionId) {
30
+ return this.http.post(`/v1/calls/${encodeURIComponent(sessionId)}/end`, {});
31
+ }
32
+ /**
33
+ * Transcript of a session, oldest turn first — the point-in-time snapshot.
34
+ * For live consumption prefer `stream()`, which pushes each turn as it
35
+ * lands; this endpoint stays the final word on per-turn latency numbers
36
+ * (legs keep enriching after a turn is first written).
37
+ */
38
+ transcript(sessionId) {
39
+ return this.http.get(`/v1/sessions/${encodeURIComponent(sessionId)}/transcript`);
40
+ }
41
+ /**
42
+ * Observe a session live: transcript turns, call events, and status changes
43
+ * pushed as they happen (SSE under the hood). Iterate until `end` — the
44
+ * SDK reconnects through server stream rotations and transient drops with
45
+ * an internal cursor, so consumers never poll and never see duplicates.
46
+ *
47
+ * ```ts
48
+ * for await (const ev of speko.sessions.stream(sessionId)) {
49
+ * if (ev.type === 'transcript') render(ev.turn);
50
+ * if (ev.type === 'event') timeline(ev.event.event_type);
51
+ * if (ev.type === 'end') break; // session over
52
+ * }
53
+ * ```
54
+ *
55
+ * A stream opened on an already-ended session replays the backlog and then
56
+ * ends, so late subscribers converge on the same picture.
57
+ *
58
+ * The no-duplicates guarantee holds per iterator: reconnects re-read a
59
+ * short server-side overlap window, and this iterator filters the replays
60
+ * by event id. A brand-new iterator resumed via `options.cursor` (process
61
+ * restart) starts with no memory and may replay up to ~2 s of events —
62
+ * dedupe by `event.id` if that matters to you.
63
+ */
64
+ async *stream(sessionId, options = {}) {
65
+ // Cursor is derived from payloads (max turn index / max event created_at),
66
+ // so resume needs no SSE `id:` plumbing in the shared HTTP client.
67
+ let turnIndex = -1;
68
+ let eventMs = 0;
69
+ if (options.cursor) {
70
+ const m = /^(-?\d+):(\d+)$/.exec(options.cursor.trim());
71
+ if (m?.[1] !== undefined && m[2] !== undefined) {
72
+ turnIndex = Number(m[1]);
73
+ eventMs = Number(m[2]);
74
+ }
75
+ }
76
+ // Every reconnect re-reads the server's overlap window (its own dedupe
77
+ // state dies with the response), so the iterator remembers delivered
78
+ // event ids to keep replays away from the consumer. Retention is by the
79
+ // EVENT's timestamp falling behind the cursor window — the same invariant
80
+ // the server uses — never by count: a capacity ring can evict ids that a
81
+ // reconnect is still allowed to replay (a >capacity burst inside the
82
+ // overlap window), reintroducing duplicates. All timestamps are
83
+ // DB-stamped, so no client clock is involved; the horizon just needs to
84
+ // comfortably exceed the server's 2 s overlap re-read. Turns need no
85
+ // dedupe — their cursor (`index`) is exact and resumed with strict `>`.
86
+ const SEEN_EVENT_WINDOW_MS = 10_000;
87
+ const seenEvents = new Map();
88
+ const rememberEvent = (id, createdMs) => {
89
+ seenEvents.set(id, Number.isFinite(createdMs) ? createdMs : eventMs);
90
+ for (const [seenId, seenMs] of seenEvents) {
91
+ if (seenMs < eventMs - SEEN_EVENT_WINDOW_MS)
92
+ seenEvents.delete(seenId);
93
+ }
94
+ };
95
+ let failedAttempts = 0;
96
+ while (true) {
97
+ if (options.signal?.aborted)
98
+ return;
99
+ let receivedFrame = false;
100
+ try {
101
+ const path = `/v1/sessions/${encodeURIComponent(sessionId)}/stream` +
102
+ `?cursor=${turnIndex}:${eventMs}`;
103
+ const frames = this.http.requestSse('GET', path, undefined, options.signal, { Accept: 'text/event-stream' }, STREAM_REQUEST_TIMEOUT_MS);
104
+ for await (const frame of frames) {
105
+ receivedFrame = true;
106
+ failedAttempts = 0;
107
+ switch (frame.event) {
108
+ case 'status': {
109
+ const data = frame.data;
110
+ yield { type: 'status', status: data.status, endedAt: data.endedAt ?? null };
111
+ break;
112
+ }
113
+ case 'transcript': {
114
+ const turn = frame.data;
115
+ turnIndex = Math.max(turnIndex, turn.index);
116
+ yield { type: 'transcript', turn };
117
+ break;
118
+ }
119
+ case 'event': {
120
+ const event = frame.data;
121
+ const createdMs = Date.parse(event.created_at);
122
+ if (Number.isFinite(createdMs))
123
+ eventMs = Math.max(eventMs, createdMs);
124
+ if (seenEvents.has(event.id))
125
+ break;
126
+ rememberEvent(event.id, createdMs);
127
+ yield { type: 'event', event };
128
+ break;
129
+ }
130
+ case 'end': {
131
+ const data = frame.data;
132
+ if (data.reason === 'session_ended') {
133
+ yield { type: 'end', reason: 'session_ended' };
134
+ return;
135
+ }
136
+ // 'timeout' is the server rotating a long response — reconnect.
137
+ break;
138
+ }
139
+ default:
140
+ // 'error' or unknown frame: the server closes after these;
141
+ // fall through to the reconnect path below.
142
+ break;
143
+ }
144
+ }
145
+ }
146
+ catch (err) {
147
+ if (options.signal?.aborted)
148
+ return;
149
+ // Auth failures and unknown sessions are not transient — surface them.
150
+ if (err instanceof SpekoApiError && err.status >= 400 && err.status < 500) {
151
+ throw err;
152
+ }
153
+ // Anything else (network drop, mid-stream abort) → reconnect below.
154
+ }
155
+ if (options.signal?.aborted)
156
+ return;
157
+ if (!receivedFrame) {
158
+ failedAttempts += 1;
159
+ if (failedAttempts >= MAX_RECONNECT_ATTEMPTS) {
160
+ throw new SpekoApiError(`session stream: ${MAX_RECONNECT_ATTEMPTS} consecutive reconnect attempts failed`, 0, 'STREAM_DISCONNECTED');
161
+ }
162
+ }
163
+ await new Promise((resolve) => setTimeout(resolve, Math.min(500 * Math.max(failedAttempts, 1), 5000)));
164
+ }
165
+ }
166
+ }
@@ -0,0 +1,80 @@
1
+ import type { HttpClient } from '../http.js';
2
+ import type { SmsBatch, SmsBatchCreateParams, SmsConsent, SmsConsentInput, SmsConsentListParams, SmsConversation, SmsConversationListParams, SmsConversationNote, SmsConversationSendParams, SmsConversationUpdate, SmsMessage, SmsMessageListParams, SmsPage, SmsSendParams, SmsSettings, SmsSettingsUpdate, SmsStreamEvent, SmsSuppression } from '../types/index.js';
3
+ export declare class Sms {
4
+ private readonly http;
5
+ readonly messages: SmsMessages;
6
+ readonly batches: SmsBatches;
7
+ readonly conversations: SmsConversations;
8
+ readonly consents: SmsConsents;
9
+ readonly suppressions: SmsSuppressions;
10
+ readonly settings: SmsSettingsResource;
11
+ constructor(http: HttpClient);
12
+ stream(options?: {
13
+ lastEventId?: string;
14
+ signal?: AbortSignal;
15
+ }): AsyncIterableIterator<SmsStreamEvent>;
16
+ }
17
+ export declare class SmsMessages {
18
+ private readonly http;
19
+ constructor(http: HttpClient);
20
+ send(params: SmsSendParams): Promise<SmsMessage>;
21
+ list(params?: SmsMessageListParams): Promise<SmsPage<SmsMessage>>;
22
+ get(messageId: string): Promise<SmsMessage>;
23
+ cancel(messageId: string): Promise<SmsMessage>;
24
+ }
25
+ export declare class SmsBatches {
26
+ private readonly http;
27
+ constructor(http: HttpClient);
28
+ create(params: SmsBatchCreateParams): Promise<SmsBatch>;
29
+ get(batchId: string): Promise<SmsBatch>;
30
+ messages(batchId: string, params?: {
31
+ cursor?: string;
32
+ limit?: number;
33
+ }): Promise<SmsPage<SmsMessage>>;
34
+ cancel(batchId: string): Promise<SmsBatch>;
35
+ }
36
+ export declare class SmsConversations {
37
+ private readonly http;
38
+ constructor(http: HttpClient);
39
+ list(params?: SmsConversationListParams): Promise<SmsPage<SmsConversation>>;
40
+ get(conversationId: string): Promise<SmsConversation>;
41
+ messages(conversationId: string, params?: {
42
+ cursor?: string;
43
+ limit?: number;
44
+ }): Promise<SmsPage<SmsMessage>>;
45
+ send(conversationId: string, params: SmsConversationSendParams): Promise<SmsMessage>;
46
+ update(conversationId: string, params: SmsConversationUpdate): Promise<SmsConversation>;
47
+ markRead(conversationId: string): Promise<SmsConversation>;
48
+ addNote(conversationId: string, body: string): Promise<SmsConversationNote>;
49
+ notes(conversationId: string, params?: {
50
+ limit?: number;
51
+ }): Promise<SmsPage<SmsConversationNote>>;
52
+ redact(conversationId: string): Promise<void>;
53
+ }
54
+ export declare class SmsConsents {
55
+ private readonly http;
56
+ constructor(http: HttpClient);
57
+ list(params?: SmsConsentListParams): Promise<SmsPage<SmsConsent>>;
58
+ create(params: SmsConsentInput): Promise<SmsConsent>;
59
+ import(records: readonly SmsConsentInput[]): Promise<{
60
+ data: SmsConsent[];
61
+ imported: number;
62
+ }>;
63
+ revoke(consentId: string, reason?: string): Promise<SmsConsent>;
64
+ }
65
+ export declare class SmsSuppressions {
66
+ private readonly http;
67
+ constructor(http: HttpClient);
68
+ list(params?: {
69
+ recipient?: string;
70
+ active?: boolean;
71
+ limit?: number;
72
+ }): Promise<SmsPage<SmsSuppression>>;
73
+ }
74
+ export declare class SmsSettingsResource {
75
+ private readonly http;
76
+ constructor(http: HttpClient);
77
+ get(): Promise<SmsSettings | null>;
78
+ update(params: SmsSettingsUpdate): Promise<SmsSettings>;
79
+ }
80
+ //# sourceMappingURL=sms.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sms.d.ts","sourceRoot":"","sources":["../../../src/lib/resources/sms.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,152 @@
1
+ export class Sms {
2
+ http;
3
+ messages;
4
+ batches;
5
+ conversations;
6
+ consents;
7
+ suppressions;
8
+ settings;
9
+ constructor(http) {
10
+ this.http = http;
11
+ this.messages = new SmsMessages(http);
12
+ this.batches = new SmsBatches(http);
13
+ this.conversations = new SmsConversations(http);
14
+ this.consents = new SmsConsents(http);
15
+ this.suppressions = new SmsSuppressions(http);
16
+ this.settings = new SmsSettingsResource(http);
17
+ }
18
+ async *stream(options = {}) {
19
+ const headers = options.lastEventId ? { 'Last-Event-ID': options.lastEventId } : undefined;
20
+ for await (const event of this.http.requestSse('GET', '/v1/sms/stream', undefined, options.signal, headers, 0)) {
21
+ if (event.event === 'heartbeat')
22
+ continue;
23
+ const data = event.data;
24
+ yield { event: event.event, ...(event.id ? { id: event.id } : {}), ...data };
25
+ }
26
+ }
27
+ }
28
+ export class SmsMessages {
29
+ http;
30
+ constructor(http) {
31
+ this.http = http;
32
+ }
33
+ send(params) {
34
+ const { idempotencyKey, ...body } = params;
35
+ return this.http.post('/v1/sms/messages', body, undefined, {
36
+ 'Idempotency-Key': idempotencyKey,
37
+ });
38
+ }
39
+ list(params = {}) {
40
+ return this.http.get(`/v1/sms/messages${query(params)}`);
41
+ }
42
+ get(messageId) {
43
+ return this.http.get(`/v1/sms/messages/${encodeURIComponent(messageId)}`);
44
+ }
45
+ cancel(messageId) {
46
+ return this.http.post(`/v1/sms/messages/${encodeURIComponent(messageId)}/cancel`, {});
47
+ }
48
+ }
49
+ export class SmsBatches {
50
+ http;
51
+ constructor(http) {
52
+ this.http = http;
53
+ }
54
+ create(params) {
55
+ const { idempotencyKey, ...body } = params;
56
+ return this.http.post('/v1/sms/batches', body, undefined, {
57
+ 'Idempotency-Key': idempotencyKey,
58
+ });
59
+ }
60
+ get(batchId) {
61
+ return this.http.get(`/v1/sms/batches/${encodeURIComponent(batchId)}`);
62
+ }
63
+ messages(batchId, params = {}) {
64
+ return this.http.get(`/v1/sms/batches/${encodeURIComponent(batchId)}/messages${query(params)}`);
65
+ }
66
+ cancel(batchId) {
67
+ return this.http.post(`/v1/sms/batches/${encodeURIComponent(batchId)}/cancel`, {});
68
+ }
69
+ }
70
+ export class SmsConversations {
71
+ http;
72
+ constructor(http) {
73
+ this.http = http;
74
+ }
75
+ list(params = {}) {
76
+ return this.http.get(`/v1/sms/conversations${query(params)}`);
77
+ }
78
+ get(conversationId) {
79
+ return this.http.get(`/v1/sms/conversations/${encodeURIComponent(conversationId)}`);
80
+ }
81
+ messages(conversationId, params = {}) {
82
+ return this.http.get(`/v1/sms/conversations/${encodeURIComponent(conversationId)}/messages${query(params)}`);
83
+ }
84
+ send(conversationId, params) {
85
+ const { idempotencyKey, ...body } = params;
86
+ return this.http.post(`/v1/sms/conversations/${encodeURIComponent(conversationId)}/messages`, body, undefined, { 'Idempotency-Key': idempotencyKey });
87
+ }
88
+ update(conversationId, params) {
89
+ return this.http.patch(`/v1/sms/conversations/${encodeURIComponent(conversationId)}`, params);
90
+ }
91
+ markRead(conversationId) {
92
+ return this.http.post(`/v1/sms/conversations/${encodeURIComponent(conversationId)}/read`, {});
93
+ }
94
+ addNote(conversationId, body) {
95
+ return this.http.post(`/v1/sms/conversations/${encodeURIComponent(conversationId)}/notes`, {
96
+ body,
97
+ });
98
+ }
99
+ notes(conversationId, params = {}) {
100
+ return this.http.get(`/v1/sms/conversations/${encodeURIComponent(conversationId)}/notes${query(params)}`);
101
+ }
102
+ async redact(conversationId) {
103
+ await this.http.delete(`/v1/sms/conversations/${encodeURIComponent(conversationId)}`);
104
+ }
105
+ }
106
+ export class SmsConsents {
107
+ http;
108
+ constructor(http) {
109
+ this.http = http;
110
+ }
111
+ list(params = {}) {
112
+ return this.http.get(`/v1/sms/consents${query(params)}`);
113
+ }
114
+ create(params) {
115
+ return this.http.post('/v1/sms/consents', params);
116
+ }
117
+ import(records) {
118
+ return this.http.post('/v1/sms/consents/import', { records });
119
+ }
120
+ revoke(consentId, reason = 'manual_revocation') {
121
+ return this.http.post(`/v1/sms/consents/${encodeURIComponent(consentId)}/revoke`, { reason });
122
+ }
123
+ }
124
+ export class SmsSuppressions {
125
+ http;
126
+ constructor(http) {
127
+ this.http = http;
128
+ }
129
+ list(params = {}) {
130
+ return this.http.get(`/v1/sms/suppressions${query(params)}`);
131
+ }
132
+ }
133
+ export class SmsSettingsResource {
134
+ http;
135
+ constructor(http) {
136
+ this.http = http;
137
+ }
138
+ get() {
139
+ return this.http.get('/v1/sms/settings');
140
+ }
141
+ update(params) {
142
+ return this.http.patch('/v1/sms/settings', params);
143
+ }
144
+ }
145
+ function query(params) {
146
+ const search = new URLSearchParams();
147
+ for (const [key, value] of Object.entries(params)) {
148
+ if (value !== undefined && value !== null)
149
+ search.set(key, String(value));
150
+ }
151
+ return search.size ? `?${search.toString()}` : '';
152
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"synthesize.d.ts","sourceRoot":"","sources":["../../../src/lib/resources/synthesize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAChB,sBAAsB,EACvB,MAAM,mBAAmB,CAAC;AAE3B,qBAAa,UAAU;IACT,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAE7C;;;;;;;;;;;;;;;OAeG;IACG,IAAI,CACR,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,iBAAiB,EAC1B,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,gBAAgB,CAAC;IAiBtB,MAAM,CACV,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,iBAAiB,EAC1B,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,sBAAsB,CAAC;CAiCnC"}
1
+ {"version":3,"file":"synthesize.d.ts","sourceRoot":"","sources":["../../../src/lib/resources/synthesize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAChB,sBAAsB,EACvB,MAAM,mBAAmB,CAAC;AAE3B,qBAAa,UAAU;IACT,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAE7C;;;;;;;;;;;;;;;OAeG;IACG,IAAI,CACR,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,iBAAiB,EAC1B,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,gBAAgB,CAAC;IAiBtB,MAAM,CACV,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,iBAAiB,EAC1B,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,sBAAsB,CAAC;CAsCnC"}
@@ -35,6 +35,8 @@ export class Synthesize {
35
35
  };
36
36
  }
37
37
  async stream(text, options, abortSignal) {
38
+ const trimmedSessionId = options.sessionId?.trim();
39
+ const requestHeaders = trimmedSessionId ? { 'x-session-id': trimmedSessionId } : undefined;
38
40
  const intent = {
39
41
  language: options.language,
40
42
  ...(options.region !== undefined && { region: options.region }),
@@ -47,15 +49,19 @@ export class Synthesize {
47
49
  body['model'] = options.model;
48
50
  if (options.speed !== undefined)
49
51
  body['speed'] = options.speed;
52
+ if (options.instructions !== undefined)
53
+ body['instructions'] = options.instructions;
54
+ if (options.spokenForm !== undefined)
55
+ body['spokenForm'] = options.spokenForm;
50
56
  if (options.constraints !== undefined)
51
57
  body['constraints'] = options.constraints;
52
- const { chunks, headers } = await this.http.requestBinaryStream('POST', '/v1/synthesize', body, abortSignal);
58
+ const { chunks, headers: responseHeaders } = await this.http.requestBinaryStream('POST', '/v1/synthesize', body, abortSignal, requestHeaders);
53
59
  const result = {
54
- contentType: headers['content-type'] ?? 'application/octet-stream',
55
- provider: headers['x-speko-provider'] ?? 'unknown',
56
- model: headers['x-speko-model'] ?? 'unknown',
57
- failoverCount: parseInt(headers['x-speko-failover-count'] ?? '0', 10),
58
- scoresRunId: headers['x-speko-scores-run-id'] || null,
60
+ contentType: responseHeaders['content-type'] ?? 'application/octet-stream',
61
+ provider: responseHeaders['x-speko-provider'] ?? 'unknown',
62
+ model: responseHeaders['x-speko-model'] ?? 'unknown',
63
+ failoverCount: parseInt(responseHeaders['x-speko-failover-count'] ?? '0', 10),
64
+ scoresRunId: responseHeaders['x-speko-scores-run-id'] || null,
59
65
  [Symbol.asyncIterator]() {
60
66
  return chunks;
61
67
  },
@@ -1 +1 @@
1
- {"version":3,"file":"transcribe.d.ts","sourceRoot":"","sources":["../../../src/lib/resources/transcribe.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAEpG,qBAAa,UAAU;IACT,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAE7C;;;;;;;;;;;OAWG;IACG,IAAI,CACR,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,iBAAiB,EAC1B,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,gBAAgB,CAAC;IAsBrB,MAAM,CACX,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,iBAAiB,EAC1B,WAAW,CAAC,EAAE,WAAW,GACxB,qBAAqB,CAAC,qBAAqB,CAAC;CAkChD"}
1
+ {"version":3,"file":"transcribe.d.ts","sourceRoot":"","sources":["../../../src/lib/resources/transcribe.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAEpG,qBAAa,UAAU;IACT,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAE7C;;;;;;;;;;;OAWG;IACG,IAAI,CACR,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,iBAAiB,EAC1B,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,gBAAgB,CAAC;IAsBrB,MAAM,CACX,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,iBAAiB,EAC1B,WAAW,CAAC,EAAE,WAAW,GACxB,qBAAqB,CAAC,qBAAqB,CAAC;CAyChD"}
@@ -48,12 +48,19 @@ export class Transcribe {
48
48
  'Content-Type': options.contentType ?? 'audio/wav',
49
49
  'X-Speko-Intent': JSON.stringify(intent),
50
50
  };
51
+ const trimmedSessionId = options.sessionId?.trim();
52
+ if (trimmedSessionId) {
53
+ headers['x-session-id'] = trimmedSessionId;
54
+ }
51
55
  if (options.constraints) {
52
56
  headers['X-Speko-Constraints'] = JSON.stringify(options.constraints);
53
57
  }
54
- if (options.keywords && options.keywords.length > 0) {
58
+ const keywords = options.keywords && options.keywords.length > 0 ? options.keywords : undefined;
59
+ const sttLanguage = options.sttOptions?.language;
60
+ if (keywords !== undefined || sttLanguage !== undefined) {
55
61
  headers['X-Speko-Stt-Options'] = JSON.stringify({
56
- keywords: [...options.keywords],
62
+ ...(keywords !== undefined && { keywords: [...keywords] }),
63
+ ...(sttLanguage !== undefined && { language: sttLanguage }),
57
64
  });
58
65
  }
59
66
  const stream = await this.http.requestRawSse('POST', '/v1/transcribe', audio, headers, abortSignal);