supafone-labs 0.5.0 → 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.
- package/README.md +4 -0
- package/dist/cjs/index.d.ts +64 -0
- package/dist/cjs/index.js +58 -0
- package/dist/index.d.ts +64 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +58 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +153 -0
package/src/index.ts
CHANGED
|
@@ -287,16 +287,38 @@ export interface LabsVoiceProviderTraits {
|
|
|
287
287
|
is_owner?: boolean | null;
|
|
288
288
|
}
|
|
289
289
|
|
|
290
|
+
/** Stable provider presentation metadata returned by the hosted catalog. */
|
|
291
|
+
export interface LabsVoiceProviderBrand {
|
|
292
|
+
/** Canonical provider key used for filtering and grouping. */
|
|
293
|
+
key: string;
|
|
294
|
+
/** Human-readable provider/company name. */
|
|
295
|
+
name: string;
|
|
296
|
+
/** Stable local asset slug when Supafone has an official provider mark. */
|
|
297
|
+
logo_slug?: string | null;
|
|
298
|
+
/** Absolute, browser-ready provider logo URL. */
|
|
299
|
+
logo_url?: string | null;
|
|
300
|
+
/** Provider's official product or company website. */
|
|
301
|
+
website_url?: string | null;
|
|
302
|
+
}
|
|
303
|
+
|
|
290
304
|
export interface LabsVoiceCatalogItem {
|
|
291
305
|
/** Stable runtime reference, including provider prefix when required. */
|
|
292
306
|
id: string;
|
|
293
307
|
voice_id: string;
|
|
294
308
|
/** Human-readable provider display name. */
|
|
295
309
|
provider: string;
|
|
310
|
+
/** Canonical brand display name for the synthesis provider. */
|
|
311
|
+
provider_label?: string;
|
|
312
|
+
/** Browser-ready official provider mark, or null for an unknown provider. */
|
|
313
|
+
provider_logo_url?: string | null;
|
|
314
|
+
/** Branding for the provider that renders the voice. */
|
|
315
|
+
provider_brand?: LabsVoiceProviderBrand;
|
|
296
316
|
/** Canonical SDK/runtime provider key. */
|
|
297
317
|
provider_key: string;
|
|
298
318
|
/** Runtime adapter used to place the voice on an Ultravox call. */
|
|
299
319
|
runtime_provider_key: string;
|
|
320
|
+
/** Branding for the realtime runtime, which can differ from synthesis. */
|
|
321
|
+
runtime_provider_brand?: LabsVoiceProviderBrand;
|
|
300
322
|
/** Actual TTS engine behind the voice (can differ for Ultravox built-ins). */
|
|
301
323
|
synthesis_provider_key: string;
|
|
302
324
|
/** Raw identifier used by the provider API. */
|
|
@@ -980,6 +1002,30 @@ export interface LabsAgentLifecycleResponse {
|
|
|
980
1002
|
[extra: string]: unknown;
|
|
981
1003
|
}
|
|
982
1004
|
|
|
1005
|
+
export interface LabsKnowledgeSyncRequest {
|
|
1006
|
+
websiteUrl?: string;
|
|
1007
|
+
website_url?: string;
|
|
1008
|
+
url?: string;
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
export interface LabsKnowledgeSyncResponse {
|
|
1012
|
+
agent: LabsAgentResponse;
|
|
1013
|
+
chunks_indexed?: number;
|
|
1014
|
+
scraped_ok?: boolean;
|
|
1015
|
+
last_error?: string | null;
|
|
1016
|
+
website_detached?: boolean;
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
export interface LabsKnowledgeChatTurn {
|
|
1020
|
+
role: "user" | "assistant";
|
|
1021
|
+
content: string;
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
export interface LabsKnowledgeChatResponse {
|
|
1025
|
+
reply: string;
|
|
1026
|
+
sources: string[];
|
|
1027
|
+
}
|
|
1028
|
+
|
|
983
1029
|
export interface LabsCapabilitiesResponse {
|
|
984
1030
|
product: string;
|
|
985
1031
|
api_namespace: string;
|
|
@@ -1034,7 +1080,10 @@ export interface LabsVoiceListResponse {
|
|
|
1034
1080
|
configured: boolean;
|
|
1035
1081
|
voice_count: number;
|
|
1036
1082
|
error?: string | null;
|
|
1083
|
+
brand?: LabsVoiceProviderBrand;
|
|
1037
1084
|
}>;
|
|
1085
|
+
/** Distinct synthesis-provider brands represented in the complete result. */
|
|
1086
|
+
provider_brands?: LabsVoiceProviderBrand[];
|
|
1038
1087
|
provider_accounts?: Record<string, unknown>;
|
|
1039
1088
|
errors?: Record<string, string>;
|
|
1040
1089
|
catalog?: {
|
|
@@ -1942,6 +1991,37 @@ export class SupafoneLabs {
|
|
|
1942
1991
|
}
|
|
1943
1992
|
}
|
|
1944
1993
|
|
|
1994
|
+
/** @internal Multipart upload to the Supafone product API with the Labs key. */
|
|
1995
|
+
async requestSupafoneUpload<T>(
|
|
1996
|
+
path: string,
|
|
1997
|
+
file: Uint8Array | ArrayBuffer | Blob,
|
|
1998
|
+
filename: string,
|
|
1999
|
+
): Promise<T> {
|
|
2000
|
+
const ctrl = new AbortController();
|
|
2001
|
+
const timer = setTimeout(() => ctrl.abort(), Math.max(this.timeoutMs, 120_000));
|
|
2002
|
+
try {
|
|
2003
|
+
const safeFilename = filename.replace(/["\\\r\n]/g, "").slice(0, 120) || "document.txt";
|
|
2004
|
+
const blob = file instanceof Blob ? file : new Blob([file as BlobPart]);
|
|
2005
|
+
const form = new FormData();
|
|
2006
|
+
form.append("file", blob, safeFilename);
|
|
2007
|
+
const res = await fetch(this.supafoneApiBaseUrl + path, {
|
|
2008
|
+
method: "POST",
|
|
2009
|
+
signal: ctrl.signal,
|
|
2010
|
+
headers: { Authorization: `Bearer ${this.supafoneApiKey}` },
|
|
2011
|
+
body: form,
|
|
2012
|
+
});
|
|
2013
|
+
const text = await res.text();
|
|
2014
|
+
const parsed = text ? safeJson(text) : {};
|
|
2015
|
+
if (!res.ok) {
|
|
2016
|
+
const detail = (parsed as { detail?: string })?.detail ?? text ?? `HTTP ${res.status}`;
|
|
2017
|
+
throw new SupafoneLabsError(`POST ${path}: ${detail}`, res.status, parsed);
|
|
2018
|
+
}
|
|
2019
|
+
return parsed as T;
|
|
2020
|
+
} finally {
|
|
2021
|
+
clearTimeout(timer);
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
|
|
1945
2025
|
/** @internal Authenticated binary request to the Supafone app API. */
|
|
1946
2026
|
async requestSupafoneBinary(path: string): Promise<LabsVoicePreview> {
|
|
1947
2027
|
const ctrl = new AbortController();
|
|
@@ -3153,6 +3233,26 @@ class LabsAgentsNamespace {
|
|
|
3153
3233
|
);
|
|
3154
3234
|
}
|
|
3155
3235
|
|
|
3236
|
+
/** Scrape a website and rebuild this agent's managed knowledge corpus. */
|
|
3237
|
+
syncKnowledge(
|
|
3238
|
+
agentId: string,
|
|
3239
|
+
input: LabsKnowledgeSyncRequest = {},
|
|
3240
|
+
): Promise<LabsKnowledgeSyncResponse> {
|
|
3241
|
+
return this.sm.requestSupafoneApi<LabsKnowledgeSyncResponse>(
|
|
3242
|
+
"POST",
|
|
3243
|
+
`/api/v1/agents/${encodeURIComponent(agentId)}/sync-knowledge`,
|
|
3244
|
+
{ url: input.url ?? input.website_url ?? input.websiteUrl ?? "" },
|
|
3245
|
+
);
|
|
3246
|
+
}
|
|
3247
|
+
|
|
3248
|
+
/** Remove website knowledge while preserving uploaded documents and notes. */
|
|
3249
|
+
detachWebsiteKnowledge(agentId: string): Promise<LabsKnowledgeSyncResponse> {
|
|
3250
|
+
return this.sm.requestSupafoneApi<LabsKnowledgeSyncResponse>(
|
|
3251
|
+
"DELETE",
|
|
3252
|
+
`/api/v1/agents/${encodeURIComponent(agentId)}/knowledge/website`,
|
|
3253
|
+
);
|
|
3254
|
+
}
|
|
3255
|
+
|
|
3156
3256
|
/** Ask the managed server whether this agent is ready to activate. */
|
|
3157
3257
|
readiness(agentKey: string, opts: GetLabsAgentOptions = {}): Promise<LabsAgentReadiness> {
|
|
3158
3258
|
const q = new URLSearchParams();
|
|
@@ -3192,6 +3292,56 @@ class LabsAgentsNamespace {
|
|
|
3192
3292
|
);
|
|
3193
3293
|
}
|
|
3194
3294
|
|
|
3295
|
+
/** Start the native provider-neutral browser voice session for this agent. */
|
|
3296
|
+
startWebRtcCall(agentId: string): Promise<WebRtcCallResult> {
|
|
3297
|
+
return this.sm.startWebRtcCall({ agentId });
|
|
3298
|
+
}
|
|
3299
|
+
|
|
3300
|
+
/** Rebuild retrieval data from the agent's already saved knowledge sources. */
|
|
3301
|
+
reindexKnowledge(agentId: string): Promise<Record<string, unknown>> {
|
|
3302
|
+
return this.sm.requestSupafoneApi(
|
|
3303
|
+
"POST",
|
|
3304
|
+
`/api/v1/agents/${encodeURIComponent(agentId)}/knowledge/reindex`,
|
|
3305
|
+
);
|
|
3306
|
+
}
|
|
3307
|
+
|
|
3308
|
+
/** Upload and index a txt, md, csv, or PDF knowledge document. */
|
|
3309
|
+
uploadKnowledgeDocument(
|
|
3310
|
+
agentId: string,
|
|
3311
|
+
file: Uint8Array | ArrayBuffer | Blob,
|
|
3312
|
+
filename: string,
|
|
3313
|
+
): Promise<{ agent: LabsAgentResponse }> {
|
|
3314
|
+
return this.sm.requestSupafoneUpload(
|
|
3315
|
+
`/api/v1/agents/${encodeURIComponent(agentId)}/knowledge/upload`,
|
|
3316
|
+
file,
|
|
3317
|
+
filename,
|
|
3318
|
+
);
|
|
3319
|
+
}
|
|
3320
|
+
|
|
3321
|
+
/** Delete one document and rebuild the agent's managed corpus. */
|
|
3322
|
+
deleteKnowledgeDocument(
|
|
3323
|
+
agentId: string,
|
|
3324
|
+
documentId: string,
|
|
3325
|
+
): Promise<{ agent: LabsAgentResponse }> {
|
|
3326
|
+
return this.sm.requestSupafoneApi(
|
|
3327
|
+
"DELETE",
|
|
3328
|
+
`/api/v1/agents/${encodeURIComponent(agentId)}/knowledge/docs/${encodeURIComponent(documentId)}`,
|
|
3329
|
+
);
|
|
3330
|
+
}
|
|
3331
|
+
|
|
3332
|
+
/** Ask a grounded question against the same corpus used during calls. */
|
|
3333
|
+
chatKnowledge(
|
|
3334
|
+
agentId: string,
|
|
3335
|
+
message: string,
|
|
3336
|
+
history: LabsKnowledgeChatTurn[] = [],
|
|
3337
|
+
): Promise<LabsKnowledgeChatResponse> {
|
|
3338
|
+
return this.sm.requestSupafoneApi(
|
|
3339
|
+
"POST",
|
|
3340
|
+
`/api/v1/agents/${encodeURIComponent(agentId)}/knowledge-chat`,
|
|
3341
|
+
{ message, history },
|
|
3342
|
+
);
|
|
3343
|
+
}
|
|
3344
|
+
|
|
3195
3345
|
/** Delete an agent. Optionally ask the backend to release assigned numbers. */
|
|
3196
3346
|
delete(agentKey: string, opts: DeleteLabsAgentOptions = {}): Promise<DeleteLabsAgentResponse> {
|
|
3197
3347
|
const q = new URLSearchParams();
|
|
@@ -4206,6 +4356,9 @@ function languageProfilesPayload(
|
|
|
4206
4356
|
input?: LabsLanguageVoiceProfile[],
|
|
4207
4357
|
): Record<string, unknown>[] | undefined {
|
|
4208
4358
|
if (!Array.isArray(input)) return undefined;
|
|
4359
|
+
if (input.length > 4) {
|
|
4360
|
+
throw new SupafoneLabsError("languageProfiles supports at most four profiles");
|
|
4361
|
+
}
|
|
4209
4362
|
const profiles = input.map((profile) => compact({
|
|
4210
4363
|
language: profile.language,
|
|
4211
4364
|
language_hint: profile.language_hint ?? profile.languageHint,
|