@osmapi/osmtalk-sdk 0.2.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.
- package/README.md +159 -0
- package/dist/index.d.mts +520 -0
- package/dist/index.d.ts +520 -0
- package/dist/index.js +450 -0
- package/dist/index.mjs +422 -0
- package/package.json +47 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
Osmtalk: () => Osmtalk,
|
|
24
|
+
OsmtalkError: () => OsmtalkError,
|
|
25
|
+
default: () => index_default,
|
|
26
|
+
verifyWebhookSignature: () => verifyWebhookSignature,
|
|
27
|
+
verifyWebhookSignatureAsync: () => verifyWebhookSignatureAsync
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(index_exports);
|
|
30
|
+
var OsmtalkError = class extends Error {
|
|
31
|
+
status;
|
|
32
|
+
body;
|
|
33
|
+
constructor(status, body) {
|
|
34
|
+
super(body?.error || body?.message || `osmTalk API error: ${status}`);
|
|
35
|
+
this.name = "OsmtalkError";
|
|
36
|
+
this.status = status;
|
|
37
|
+
this.body = body;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
var HttpClient = class {
|
|
41
|
+
baseUrl;
|
|
42
|
+
apiKey;
|
|
43
|
+
timeoutMs;
|
|
44
|
+
fetchImpl;
|
|
45
|
+
constructor(opts) {
|
|
46
|
+
this.apiKey = opts.apiKey;
|
|
47
|
+
this.baseUrl = (opts.baseUrl ?? "https://api.osmtalk.com").replace(/\/$/, "");
|
|
48
|
+
this.timeoutMs = opts.timeoutMs ?? 3e4;
|
|
49
|
+
this.fetchImpl = opts.fetch ?? (typeof fetch !== "undefined" ? fetch.bind(globalThis) : void 0);
|
|
50
|
+
if (!this.fetchImpl) throw new Error("No fetch implementation available \u2014 provide one in OsmtalkOptions.fetch");
|
|
51
|
+
if (!opts.apiKey) throw new Error("apiKey is required");
|
|
52
|
+
}
|
|
53
|
+
async request(method, path, body, extraHeaders, idempotencyKey) {
|
|
54
|
+
const ctrl = new AbortController();
|
|
55
|
+
const timer = setTimeout(() => ctrl.abort(), this.timeoutMs);
|
|
56
|
+
const headers = {
|
|
57
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
58
|
+
...body !== void 0 ? { "Content-Type": "application/json" } : {},
|
|
59
|
+
...idempotencyKey ? { "Idempotency-Key": idempotencyKey } : {},
|
|
60
|
+
...extraHeaders ?? {}
|
|
61
|
+
};
|
|
62
|
+
let res;
|
|
63
|
+
try {
|
|
64
|
+
res = await this.fetchImpl(`${this.baseUrl}${path}`, {
|
|
65
|
+
method,
|
|
66
|
+
headers,
|
|
67
|
+
body: body === void 0 ? void 0 : typeof body === "string" ? body : JSON.stringify(body),
|
|
68
|
+
signal: ctrl.signal
|
|
69
|
+
});
|
|
70
|
+
} finally {
|
|
71
|
+
clearTimeout(timer);
|
|
72
|
+
}
|
|
73
|
+
const text = await res.text();
|
|
74
|
+
const parsed = text ? (() => {
|
|
75
|
+
try {
|
|
76
|
+
return JSON.parse(text);
|
|
77
|
+
} catch {
|
|
78
|
+
return text;
|
|
79
|
+
}
|
|
80
|
+
})() : null;
|
|
81
|
+
if (!res.ok) {
|
|
82
|
+
throw new OsmtalkError(res.status, parsed ?? { error: text });
|
|
83
|
+
}
|
|
84
|
+
return parsed;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
var AgentsResource = class {
|
|
88
|
+
constructor(http) {
|
|
89
|
+
this.http = http;
|
|
90
|
+
}
|
|
91
|
+
http;
|
|
92
|
+
list() {
|
|
93
|
+
return this.http.request("GET", "/api/agents");
|
|
94
|
+
}
|
|
95
|
+
get(id) {
|
|
96
|
+
return this.http.request("GET", `/api/agents/${id}`);
|
|
97
|
+
}
|
|
98
|
+
create(input) {
|
|
99
|
+
return this.http.request("POST", "/api/agents", input);
|
|
100
|
+
}
|
|
101
|
+
update(id, input) {
|
|
102
|
+
return this.http.request("PUT", `/api/agents/${id}`, input);
|
|
103
|
+
}
|
|
104
|
+
delete(id) {
|
|
105
|
+
return this.http.request("DELETE", `/api/agents/${id}`);
|
|
106
|
+
}
|
|
107
|
+
// Versioning
|
|
108
|
+
publishVersion(id, opts) {
|
|
109
|
+
return this.http.request(
|
|
110
|
+
"POST",
|
|
111
|
+
`/api/agents/${id}/versions`,
|
|
112
|
+
opts ?? {}
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
listVersions(id) {
|
|
116
|
+
return this.http.request(
|
|
117
|
+
"GET",
|
|
118
|
+
`/api/agents/${id}/versions`
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
getVersion(id, version) {
|
|
122
|
+
return this.http.request(
|
|
123
|
+
"GET",
|
|
124
|
+
`/api/agents/${id}/versions/${version}`
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
rollbackToVersion(id, version) {
|
|
128
|
+
return this.http.request(
|
|
129
|
+
"POST",
|
|
130
|
+
`/api/agents/${id}/versions/${version}/rollback`
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
// Connect (start a web voice session)
|
|
134
|
+
connect(id, opts) {
|
|
135
|
+
return this.http.request(
|
|
136
|
+
"POST",
|
|
137
|
+
`/api/agents/${id}/connect`,
|
|
138
|
+
opts ?? {}
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
var CallsResource = class {
|
|
143
|
+
constructor(http) {
|
|
144
|
+
this.http = http;
|
|
145
|
+
}
|
|
146
|
+
http;
|
|
147
|
+
list() {
|
|
148
|
+
return this.http.request("GET", "/api/calls");
|
|
149
|
+
}
|
|
150
|
+
get(id) {
|
|
151
|
+
return this.http.request("GET", `/api/calls/${id}`);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Place an outbound call. Optionally pass `idempotencyKey` so retries
|
|
155
|
+
* within 24h return the same response instead of placing a duplicate call.
|
|
156
|
+
*/
|
|
157
|
+
outbound(input, opts) {
|
|
158
|
+
return this.http.request(
|
|
159
|
+
"POST",
|
|
160
|
+
"/api/calls/outbound",
|
|
161
|
+
input,
|
|
162
|
+
void 0,
|
|
163
|
+
opts?.idempotencyKey
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
end(id) {
|
|
167
|
+
return this.http.request("POST", `/api/calls/${id}/end`);
|
|
168
|
+
}
|
|
169
|
+
transfer(id, destination, summary) {
|
|
170
|
+
return this.http.request("POST", `/api/calls/${id}/transfer`, { destination, summary });
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
var PlatformResource = class {
|
|
174
|
+
constructor(http) {
|
|
175
|
+
this.http = http;
|
|
176
|
+
}
|
|
177
|
+
http;
|
|
178
|
+
/** Live platform constants — USD-to-INR rate and the minimum charge per call. */
|
|
179
|
+
getRates() {
|
|
180
|
+
return this.http.request("GET", "/api/providers/rates");
|
|
181
|
+
}
|
|
182
|
+
/** Catalog of available LLM/STT/TTS providers + models. */
|
|
183
|
+
listProviders() {
|
|
184
|
+
return this.http.request("GET", "/api/providers");
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Quality presets (Fast / Balanced / Premium) with live per-minute
|
|
188
|
+
* cost estimates derived from the same rate tables we bill with.
|
|
189
|
+
* `costEstimate.{low, typical, high}` are INR per minute and account
|
|
190
|
+
* for typical 250 / 900 / 2500 prompt-token usage patterns.
|
|
191
|
+
*
|
|
192
|
+
* @param channel "phone" (default) includes SIP minutes; "web" or
|
|
193
|
+
* "chat" exclude SIP for cheaper web-only deployments.
|
|
194
|
+
*/
|
|
195
|
+
getPresets(channel = "phone") {
|
|
196
|
+
return this.http.request("GET", `/api/providers/presets?channel=${channel}`);
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Per-provider health snapshot. Cached server-side for 60s.
|
|
200
|
+
* Use this before launching a call to detect "sometimes works"
|
|
201
|
+
* provider issues (key revoked, region outage, ToS not accepted).
|
|
202
|
+
*/
|
|
203
|
+
getModelHealth() {
|
|
204
|
+
return this.http.request(
|
|
205
|
+
"GET",
|
|
206
|
+
"/api/health/models"
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Industry-organized agent templates (support, sales, healthcare,
|
|
211
|
+
* real-estate, etc.). When called with a valid session/API key, the
|
|
212
|
+
* response includes your org's custom-saved templates merged ahead
|
|
213
|
+
* of the built-ins; anonymous calls return built-ins only.
|
|
214
|
+
*/
|
|
215
|
+
getTemplates(params) {
|
|
216
|
+
const qs = new URLSearchParams();
|
|
217
|
+
if (params?.category) qs.set("category", params.category);
|
|
218
|
+
if (params?.q) qs.set("q", params.q);
|
|
219
|
+
const suffix = qs.toString();
|
|
220
|
+
return this.http.request("GET", `/api/templates${suffix ? `?${suffix}` : ""}`);
|
|
221
|
+
}
|
|
222
|
+
getTemplate(id) {
|
|
223
|
+
return this.http.request("GET", `/api/templates/${encodeURIComponent(id)}`);
|
|
224
|
+
}
|
|
225
|
+
/** Save a custom template (org-scoped, requires auth). */
|
|
226
|
+
saveTemplate(data) {
|
|
227
|
+
return this.http.request("POST", "/api/templates", data);
|
|
228
|
+
}
|
|
229
|
+
deleteTemplate(id) {
|
|
230
|
+
return this.http.request(
|
|
231
|
+
"DELETE",
|
|
232
|
+
`/api/templates/${encodeURIComponent(id)}`
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
function verifyWebhookSignature(rawBody, signatureHeader, secret) {
|
|
237
|
+
if (!signatureHeader || !secret) return false;
|
|
238
|
+
const sig = Array.isArray(signatureHeader) ? signatureHeader[0] : signatureHeader;
|
|
239
|
+
if (typeof sig !== "string") return false;
|
|
240
|
+
const m = /^sha256=([0-9a-f]{64})$/i.exec(sig);
|
|
241
|
+
if (!m) return false;
|
|
242
|
+
const providedHex = m[1].toLowerCase();
|
|
243
|
+
try {
|
|
244
|
+
const isNode = !!globalThis.process?.versions?.node;
|
|
245
|
+
if (isNode) {
|
|
246
|
+
const req = new Function("return require")();
|
|
247
|
+
const nodeCrypto = req("node:crypto");
|
|
248
|
+
const expected = nodeCrypto.createHmac("sha256", secret).update(rawBody).digest("hex");
|
|
249
|
+
return timingSafeEqualHex(providedHex, expected);
|
|
250
|
+
}
|
|
251
|
+
} catch {
|
|
252
|
+
}
|
|
253
|
+
throw new Error(
|
|
254
|
+
"verifyWebhookSignature: node:crypto unavailable in this runtime; use verifyWebhookSignatureAsync() instead"
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
async function verifyWebhookSignatureAsync(rawBody, signatureHeader, secret) {
|
|
258
|
+
if (!signatureHeader || !secret) return false;
|
|
259
|
+
const sig = Array.isArray(signatureHeader) ? signatureHeader[0] : signatureHeader;
|
|
260
|
+
if (typeof sig !== "string") return false;
|
|
261
|
+
const m = /^sha256=([0-9a-f]{64})$/i.exec(sig);
|
|
262
|
+
if (!m) return false;
|
|
263
|
+
const providedHex = m[1].toLowerCase();
|
|
264
|
+
const enc = new TextEncoder();
|
|
265
|
+
const keyBytes = new Uint8Array(enc.encode(secret));
|
|
266
|
+
const key = await crypto.subtle.importKey(
|
|
267
|
+
"raw",
|
|
268
|
+
keyBytes,
|
|
269
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
270
|
+
false,
|
|
271
|
+
["sign"]
|
|
272
|
+
);
|
|
273
|
+
const body = typeof rawBody === "string" ? new Uint8Array(enc.encode(rawBody)) : new Uint8Array(rawBody);
|
|
274
|
+
const macBuf = await crypto.subtle.sign("HMAC", key, body);
|
|
275
|
+
const expected = Array.from(new Uint8Array(macBuf)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
276
|
+
return timingSafeEqualHex(providedHex, expected);
|
|
277
|
+
}
|
|
278
|
+
function timingSafeEqualHex(a, b) {
|
|
279
|
+
if (a.length !== b.length) return false;
|
|
280
|
+
let diff = 0;
|
|
281
|
+
for (let i = 0; i < a.length; i++) diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
282
|
+
return diff === 0;
|
|
283
|
+
}
|
|
284
|
+
var CampaignsResource = class {
|
|
285
|
+
constructor(http) {
|
|
286
|
+
this.http = http;
|
|
287
|
+
}
|
|
288
|
+
http;
|
|
289
|
+
list(opts) {
|
|
290
|
+
const q = opts?.status ? `?status=${encodeURIComponent(opts.status)}` : "";
|
|
291
|
+
return this.http.request("GET", `/api/campaigns${q}`);
|
|
292
|
+
}
|
|
293
|
+
get(id) {
|
|
294
|
+
return this.http.request("GET", `/api/campaigns/${id}`);
|
|
295
|
+
}
|
|
296
|
+
create(input) {
|
|
297
|
+
return this.http.request("POST", "/api/campaigns", input);
|
|
298
|
+
}
|
|
299
|
+
update(id, input) {
|
|
300
|
+
return this.http.request("PUT", `/api/campaigns/${id}`, input);
|
|
301
|
+
}
|
|
302
|
+
delete(id) {
|
|
303
|
+
return this.http.request("DELETE", `/api/campaigns/${id}`);
|
|
304
|
+
}
|
|
305
|
+
start(id) {
|
|
306
|
+
return this.http.request("POST", `/api/campaigns/${id}/start`);
|
|
307
|
+
}
|
|
308
|
+
pause(id) {
|
|
309
|
+
return this.http.request("POST", `/api/campaigns/${id}/pause`);
|
|
310
|
+
}
|
|
311
|
+
resume(id) {
|
|
312
|
+
return this.http.request("POST", `/api/campaigns/${id}/resume`);
|
|
313
|
+
}
|
|
314
|
+
stop(id) {
|
|
315
|
+
return this.http.request("POST", `/api/campaigns/${id}/stop`);
|
|
316
|
+
}
|
|
317
|
+
report(id) {
|
|
318
|
+
return this.http.request("GET", `/api/campaigns/${id}/report`);
|
|
319
|
+
}
|
|
320
|
+
// Lead uploads
|
|
321
|
+
uploadLeadsCsv(id, csv) {
|
|
322
|
+
return this.http.request(
|
|
323
|
+
"POST",
|
|
324
|
+
`/api/campaigns/${id}/leads`,
|
|
325
|
+
csv,
|
|
326
|
+
{ "Content-Type": "text/csv" }
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
uploadLeads(id, leads) {
|
|
330
|
+
return this.http.request(
|
|
331
|
+
"POST",
|
|
332
|
+
`/api/campaigns/${id}/leads`,
|
|
333
|
+
{ leads }
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
listLeads(id, opts) {
|
|
337
|
+
const q = new URLSearchParams();
|
|
338
|
+
if (opts?.status) q.set("status", opts.status);
|
|
339
|
+
if (opts?.limit) q.set("limit", String(opts.limit));
|
|
340
|
+
if (opts?.offset) q.set("offset", String(opts.offset));
|
|
341
|
+
const suffix = q.toString() ? `?${q}` : "";
|
|
342
|
+
return this.http.request("GET", `/api/campaigns/${id}/leads${suffix}`);
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
var DncResource = class {
|
|
346
|
+
constructor(http) {
|
|
347
|
+
this.http = http;
|
|
348
|
+
}
|
|
349
|
+
http;
|
|
350
|
+
list() {
|
|
351
|
+
return this.http.request("GET", "/api/campaigns/dnc");
|
|
352
|
+
}
|
|
353
|
+
add(phoneNumber, opts) {
|
|
354
|
+
return this.http.request("POST", "/api/campaigns/dnc", { phoneNumber, ...opts });
|
|
355
|
+
}
|
|
356
|
+
bulkAdd(entries) {
|
|
357
|
+
return this.http.request("POST", "/api/campaigns/dnc/bulk", { entries });
|
|
358
|
+
}
|
|
359
|
+
remove(id) {
|
|
360
|
+
return this.http.request("DELETE", `/api/campaigns/dnc/${id}`);
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
var EvalResource = class {
|
|
364
|
+
constructor(http) {
|
|
365
|
+
this.http = http;
|
|
366
|
+
}
|
|
367
|
+
http;
|
|
368
|
+
simulate(agentId, mockTurns, opts) {
|
|
369
|
+
return this.http.request(
|
|
370
|
+
"POST",
|
|
371
|
+
`/api/agents/${agentId}/simulate`,
|
|
372
|
+
{ mockTurns, ...opts }
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
createTestCase(agentId, input) {
|
|
376
|
+
return this.http.request("POST", `/api/agents/${agentId}/test-cases`, input);
|
|
377
|
+
}
|
|
378
|
+
listTestCases(agentId) {
|
|
379
|
+
return this.http.request("GET", `/api/agents/${agentId}/test-cases`);
|
|
380
|
+
}
|
|
381
|
+
runTestCase(agentId, testCaseId) {
|
|
382
|
+
return this.http.request("POST", `/api/agents/${agentId}/test-cases/${testCaseId}/run`);
|
|
383
|
+
}
|
|
384
|
+
runAll(agentId) {
|
|
385
|
+
return this.http.request(
|
|
386
|
+
"POST",
|
|
387
|
+
`/api/agents/${agentId}/eval`
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
listRuns(agentId) {
|
|
391
|
+
return this.http.request("GET", `/api/agents/${agentId}/eval/runs`);
|
|
392
|
+
}
|
|
393
|
+
getRun(runId) {
|
|
394
|
+
return this.http.request("GET", `/api/eval/runs/${runId}`);
|
|
395
|
+
}
|
|
396
|
+
};
|
|
397
|
+
var SettingsResource = class {
|
|
398
|
+
constructor(http) {
|
|
399
|
+
this.http = http;
|
|
400
|
+
}
|
|
401
|
+
http;
|
|
402
|
+
get() {
|
|
403
|
+
return this.http.request("GET", "/api/settings");
|
|
404
|
+
}
|
|
405
|
+
getStorage() {
|
|
406
|
+
return this.http.request("GET", "/api/settings/storage");
|
|
407
|
+
}
|
|
408
|
+
updateStorage(input) {
|
|
409
|
+
return this.http.request("PUT", "/api/settings/storage", input);
|
|
410
|
+
}
|
|
411
|
+
getWebhook() {
|
|
412
|
+
return this.http.request("GET", "/api/settings/webhook");
|
|
413
|
+
}
|
|
414
|
+
updateWebhook(input) {
|
|
415
|
+
return this.http.request("PUT", "/api/settings/webhook", input);
|
|
416
|
+
}
|
|
417
|
+
getCompliance() {
|
|
418
|
+
return this.http.request("GET", "/api/settings/compliance");
|
|
419
|
+
}
|
|
420
|
+
updateCompliance(input) {
|
|
421
|
+
return this.http.request("PUT", "/api/settings/compliance", input);
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
var Osmtalk = class {
|
|
425
|
+
agents;
|
|
426
|
+
calls;
|
|
427
|
+
campaigns;
|
|
428
|
+
dnc;
|
|
429
|
+
eval;
|
|
430
|
+
settings;
|
|
431
|
+
platform;
|
|
432
|
+
constructor(opts) {
|
|
433
|
+
const http = new HttpClient(opts);
|
|
434
|
+
this.agents = new AgentsResource(http);
|
|
435
|
+
this.calls = new CallsResource(http);
|
|
436
|
+
this.campaigns = new CampaignsResource(http);
|
|
437
|
+
this.dnc = new DncResource(http);
|
|
438
|
+
this.eval = new EvalResource(http);
|
|
439
|
+
this.settings = new SettingsResource(http);
|
|
440
|
+
this.platform = new PlatformResource(http);
|
|
441
|
+
}
|
|
442
|
+
};
|
|
443
|
+
var index_default = Osmtalk;
|
|
444
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
445
|
+
0 && (module.exports = {
|
|
446
|
+
Osmtalk,
|
|
447
|
+
OsmtalkError,
|
|
448
|
+
verifyWebhookSignature,
|
|
449
|
+
verifyWebhookSignatureAsync
|
|
450
|
+
});
|