@absolutejs/voice 0.0.22-beta.70 → 0.0.22-beta.71
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/dist/index.d.ts +2 -2
- package/dist/index.js +125 -14
- package/dist/telephonyOutcome.d.ts +36 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export { createVoiceToolIdempotencyKey, createVoiceToolRuntime } from './toolRun
|
|
|
11
11
|
export { createVoiceToolContract, createVoiceToolContractHTMLHandler, createVoiceToolContractJSONHandler, createVoiceToolContractRoutes, createVoiceToolRuntimeContractDefaults, renderVoiceToolContractHTML, runVoiceToolContractSuite, runVoiceToolContract } from './toolContract';
|
|
12
12
|
export { createVoiceTurnQualityHTMLHandler, createVoiceTurnQualityJSONHandler, createVoiceTurnQualityRoutes, renderVoiceTurnQualityHTML, summarizeVoiceTurnQuality } from './turnQuality';
|
|
13
13
|
export { createVoiceOutcomeContractHTMLHandler, createVoiceOutcomeContractJSONHandler, createVoiceOutcomeContractRoutes, renderVoiceOutcomeContractHTML, runVoiceOutcomeContractSuite } from './outcomeContract';
|
|
14
|
-
export { applyVoiceTelephonyOutcome, createVoiceTelephonyOutcomePolicy, createVoiceTelephonyWebhookHandler, createVoiceTelephonyWebhookRoutes, parseVoiceTelephonyWebhookEvent, resolveVoiceTelephonyOutcome, voiceTelephonyOutcomeToRouteResult } from './telephonyOutcome';
|
|
14
|
+
export { applyVoiceTelephonyOutcome, createVoiceTelephonyOutcomePolicy, createVoiceTelephonyWebhookHandler, createVoiceTelephonyWebhookRoutes, parseVoiceTelephonyWebhookEvent, resolveVoiceTelephonyOutcome, signVoiceTwilioWebhook, verifyVoiceTwilioWebhookSignature, voiceTelephonyOutcomeToRouteResult } from './telephonyOutcome';
|
|
15
15
|
export { createStoredVoiceCallReviewArtifact, createStoredVoiceExternalObjectMap, createStoredVoiceIntegrationEvent, createStoredVoiceOpsTask, createVoiceFileExternalObjectMapStore, createVoiceFileAssistantMemoryStore, createVoiceFileIntegrationEventStore, createVoiceFileReviewStore, createVoiceFileRuntimeStorage, createVoiceFileSessionStore, createVoiceFileTaskStore, createVoiceFileTraceSinkDeliveryStore, createVoiceFileTraceEventStore } from './fileStore';
|
|
16
16
|
export { createVoiceAssistantMemoryHandle, createVoiceAssistantMemoryRecord, createVoiceMemoryAssistantMemoryStore, resolveVoiceAssistantMemoryNamespace } from './assistantMemory';
|
|
17
17
|
export { createAnthropicVoiceAssistantModel, createGeminiVoiceAssistantModel, createJSONVoiceAssistantModel, createOpenAIVoiceAssistantModel, resolveVoiceProviderRoutingPolicyPreset, createVoiceProviderRouter } from './modelAdapters';
|
|
@@ -57,7 +57,7 @@ export type { VoiceProviderHealthStatus, VoiceProviderHealthSummary, VoiceProvid
|
|
|
57
57
|
export type { VoiceProviderCapabilityDefinition, VoiceProviderCapabilityHandlerOptions, VoiceProviderCapabilityHTMLHandlerOptions, VoiceProviderCapabilityKind, VoiceProviderCapabilityOptions, VoiceProviderCapabilityReport, VoiceProviderCapabilityRoutesOptions, VoiceProviderCapabilitySummary } from './providerCapabilities';
|
|
58
58
|
export type { VoiceTurnQualityHTMLHandlerOptions, VoiceTurnQualityItem, VoiceTurnQualityOptions, VoiceTurnQualityReport, VoiceTurnQualityRoutesOptions, VoiceTurnQualityStatus } from './turnQuality';
|
|
59
59
|
export type { VoiceOutcomeContractDefinition, VoiceOutcomeContractHTMLHandlerOptions, VoiceOutcomeContractIssue, VoiceOutcomeContractOptions, VoiceOutcomeContractReport, VoiceOutcomeContractRoutesOptions, VoiceOutcomeContractStatus, VoiceOutcomeContractSuiteReport } from './outcomeContract';
|
|
60
|
-
export type { VoiceTelephonyOutcomeAction, VoiceTelephonyOutcomeDecision, VoiceTelephonyOutcomePolicy, VoiceTelephonyOutcomeProviderEvent, VoiceTelephonyOutcomeRouteResult, VoiceTelephonyOutcomeStatusDecision, VoiceTelephonyWebhookDecision, VoiceTelephonyWebhookHandlerOptions, VoiceTelephonyWebhookParseInput, VoiceTelephonyWebhookProvider, VoiceTelephonyWebhookRoutesOptions } from './telephonyOutcome';
|
|
60
|
+
export type { VoiceTelephonyOutcomeAction, VoiceTelephonyOutcomeDecision, VoiceTelephonyOutcomePolicy, VoiceTelephonyOutcomeProviderEvent, VoiceTelephonyOutcomeRouteResult, VoiceTelephonyOutcomeStatusDecision, VoiceTelephonyWebhookDecision, VoiceTelephonyWebhookHandlerOptions, VoiceTelephonyWebhookParseInput, VoiceTelephonyWebhookProvider, VoiceTelephonyWebhookRoutesOptions, VoiceTelephonyWebhookVerificationResult } from './telephonyOutcome';
|
|
61
61
|
export type { VoiceOpsConsoleLink, VoiceOpsConsoleReport, VoiceOpsConsoleRoutesOptions } from './opsConsoleRoutes';
|
|
62
62
|
export type { VoiceQualityLink, VoiceQualityMetric, VoiceQualityReport, VoiceQualityRoutesOptions, VoiceQualityStatus, VoiceQualityThresholds } from './qualityRoutes';
|
|
63
63
|
export type { VoiceResilienceIOSimulator, VoiceResilienceLink, VoiceResiliencePageData, VoiceResilienceRoutesOptions, VoiceResilienceSimulationProvider, VoiceRoutingDecisionSummary, VoiceRoutingDecisionSummaryOptions, VoiceRoutingEvent, VoiceRoutingEventKind } from './resilienceRoutes';
|
package/dist/index.js
CHANGED
|
@@ -2990,7 +2990,7 @@ var toVoiceSessionSummary = (session) => ({
|
|
|
2990
2990
|
});
|
|
2991
2991
|
|
|
2992
2992
|
// src/session.ts
|
|
2993
|
-
import { Buffer } from "buffer";
|
|
2993
|
+
import { Buffer as Buffer2 } from "buffer";
|
|
2994
2994
|
|
|
2995
2995
|
// src/handoff.ts
|
|
2996
2996
|
var toHex3 = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
@@ -3425,7 +3425,7 @@ var createEmptyCurrentTurn = () => ({
|
|
|
3425
3425
|
transcripts: []
|
|
3426
3426
|
});
|
|
3427
3427
|
var cloneTranscript = (transcript) => ({ ...transcript });
|
|
3428
|
-
var encodeBase64 = (chunk) =>
|
|
3428
|
+
var encodeBase64 = (chunk) => Buffer2.from(chunk).toString("base64");
|
|
3429
3429
|
var countWords2 = (text) => text.trim().split(/\s+/).filter(Boolean).length;
|
|
3430
3430
|
var normalizeText2 = (text) => text.trim().replace(/\s+/g, " ");
|
|
3431
3431
|
var getAudioChunkDurationMs = (chunk) => chunk.byteLength / (DEFAULT_FORMAT.sampleRateHz * DEFAULT_FORMAT.channels * 2) * 1000;
|
|
@@ -10601,6 +10601,15 @@ var DEFAULT_MACHINE_VOICEMAIL_VALUES = [
|
|
|
10601
10601
|
];
|
|
10602
10602
|
var DEFAULT_NO_ANSWER_SIP_CODES = [408, 480, 486, 487, 603];
|
|
10603
10603
|
var isRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
10604
|
+
|
|
10605
|
+
class VoiceTelephonyWebhookVerificationError extends Error {
|
|
10606
|
+
result;
|
|
10607
|
+
constructor(result) {
|
|
10608
|
+
super(result.ok ? "telephony webhook verified" : result.reason);
|
|
10609
|
+
this.name = "VoiceTelephonyWebhookVerificationError";
|
|
10610
|
+
this.result = result;
|
|
10611
|
+
}
|
|
10612
|
+
}
|
|
10604
10613
|
var normalizeToken = (value) => typeof value === "string" ? value.trim().toLowerCase().replace(/\s+/g, "-").replace(/_+/g, "-") : undefined;
|
|
10605
10614
|
var firstString = (source, keys) => {
|
|
10606
10615
|
for (const key of keys) {
|
|
@@ -10649,6 +10658,30 @@ var flattenPayload = (value) => {
|
|
|
10649
10658
|
...isRecord(data?.payload) ? data.payload : undefined
|
|
10650
10659
|
};
|
|
10651
10660
|
};
|
|
10661
|
+
var toBase64 = (bytes) => Buffer.from(new Uint8Array(bytes)).toString("base64");
|
|
10662
|
+
var timingSafeEqual = (left, right) => {
|
|
10663
|
+
const encoder = new TextEncoder;
|
|
10664
|
+
const leftBytes = encoder.encode(left);
|
|
10665
|
+
const rightBytes = encoder.encode(right);
|
|
10666
|
+
if (leftBytes.length !== rightBytes.length) {
|
|
10667
|
+
return false;
|
|
10668
|
+
}
|
|
10669
|
+
let diff = 0;
|
|
10670
|
+
for (let index = 0;index < leftBytes.length; index += 1) {
|
|
10671
|
+
diff |= leftBytes[index] ^ rightBytes[index];
|
|
10672
|
+
}
|
|
10673
|
+
return diff === 0;
|
|
10674
|
+
};
|
|
10675
|
+
var signHmacSHA1Base64 = async (secret, payload) => {
|
|
10676
|
+
const encoder = new TextEncoder;
|
|
10677
|
+
const key = await crypto.subtle.importKey("raw", encoder.encode(secret), {
|
|
10678
|
+
hash: "SHA-1",
|
|
10679
|
+
name: "HMAC"
|
|
10680
|
+
}, false, ["sign"]);
|
|
10681
|
+
const signature = await crypto.subtle.sign("HMAC", key, encoder.encode(payload));
|
|
10682
|
+
return toBase64(signature);
|
|
10683
|
+
};
|
|
10684
|
+
var sortedParamsForSignature = (body) => Object.entries(flattenPayload(body)).filter(([, value]) => value !== undefined && value !== null).sort(([left], [right]) => left.localeCompare(right)).map(([key, value]) => `${key}${String(value)}`).join("");
|
|
10652
10685
|
var normalizeList = (values, fallback) => new Set((values ?? fallback).map(normalizeToken).filter(Boolean));
|
|
10653
10686
|
var metadataValue = (metadata, keys) => {
|
|
10654
10687
|
for (const key of keys) {
|
|
@@ -10882,9 +10915,8 @@ var applyVoiceTelephonyOutcome = async (api, decision, result) => {
|
|
|
10882
10915
|
break;
|
|
10883
10916
|
}
|
|
10884
10917
|
};
|
|
10885
|
-
var
|
|
10886
|
-
const contentType
|
|
10887
|
-
const text = await request.text();
|
|
10918
|
+
var parseRequestBodyText = (input) => {
|
|
10919
|
+
const { contentType, text } = input;
|
|
10888
10920
|
if (!text) {
|
|
10889
10921
|
return {};
|
|
10890
10922
|
}
|
|
@@ -10896,6 +10928,58 @@ var parseRequestBody = async (request) => {
|
|
|
10896
10928
|
}
|
|
10897
10929
|
return parseMaybeJSON(text) ?? Object.fromEntries(new URLSearchParams(text));
|
|
10898
10930
|
};
|
|
10931
|
+
var readRequestBody = async (request) => {
|
|
10932
|
+
const contentType = request.headers.get("content-type") ?? "";
|
|
10933
|
+
const text = await request.text();
|
|
10934
|
+
return {
|
|
10935
|
+
body: parseRequestBodyText({ contentType, text }),
|
|
10936
|
+
rawBody: text
|
|
10937
|
+
};
|
|
10938
|
+
};
|
|
10939
|
+
var signVoiceTwilioWebhook = async (input) => signHmacSHA1Base64(input.authToken, `${input.url}${sortedParamsForSignature(input.body ?? {})}`);
|
|
10940
|
+
var verifyVoiceTwilioWebhookSignature = async (input) => {
|
|
10941
|
+
if (!input.authToken) {
|
|
10942
|
+
return { ok: false, reason: "missing-secret" };
|
|
10943
|
+
}
|
|
10944
|
+
const signature = input.headers.get("x-twilio-signature");
|
|
10945
|
+
if (!signature) {
|
|
10946
|
+
return { ok: false, reason: "missing-signature" };
|
|
10947
|
+
}
|
|
10948
|
+
const expected = await signVoiceTwilioWebhook({
|
|
10949
|
+
authToken: input.authToken,
|
|
10950
|
+
body: input.body,
|
|
10951
|
+
url: input.url
|
|
10952
|
+
});
|
|
10953
|
+
return timingSafeEqual(signature, expected) ? { ok: true } : { ok: false, reason: "invalid-signature" };
|
|
10954
|
+
};
|
|
10955
|
+
var resolveVerificationUrl = (option, input) => typeof option === "function" ? option(input) : option ?? input.request.url;
|
|
10956
|
+
var verifyVoiceTelephonyWebhook = async (input) => {
|
|
10957
|
+
if (input.options.verify) {
|
|
10958
|
+
return input.options.verify({
|
|
10959
|
+
body: input.body,
|
|
10960
|
+
headers: input.request.headers,
|
|
10961
|
+
provider: input.provider,
|
|
10962
|
+
query: input.query,
|
|
10963
|
+
rawBody: input.rawBody,
|
|
10964
|
+
request: input.request
|
|
10965
|
+
});
|
|
10966
|
+
}
|
|
10967
|
+
if (!input.options.signingSecret) {
|
|
10968
|
+
return input.options.requireVerification ? { ok: false, reason: "missing-secret" } : { ok: true };
|
|
10969
|
+
}
|
|
10970
|
+
if (input.provider !== "twilio") {
|
|
10971
|
+
return { ok: false, reason: "unsupported-provider" };
|
|
10972
|
+
}
|
|
10973
|
+
return verifyVoiceTwilioWebhookSignature({
|
|
10974
|
+
authToken: input.options.signingSecret,
|
|
10975
|
+
body: input.body,
|
|
10976
|
+
headers: input.request.headers,
|
|
10977
|
+
url: resolveVerificationUrl(input.options.verificationUrl, {
|
|
10978
|
+
query: input.query,
|
|
10979
|
+
request: input.request
|
|
10980
|
+
})
|
|
10981
|
+
});
|
|
10982
|
+
};
|
|
10899
10983
|
var durationMsFromSeconds = (value) => typeof value === "number" ? value * 1000 : undefined;
|
|
10900
10984
|
var parseVoiceTelephonyWebhookEvent = (input) => {
|
|
10901
10985
|
const payload = flattenPayload(input.body);
|
|
@@ -10978,7 +11062,18 @@ var defaultSessionId = (input) => {
|
|
|
10978
11062
|
var createVoiceTelephonyWebhookHandler = (options = {}) => async (input) => {
|
|
10979
11063
|
const provider = options.provider ?? "generic";
|
|
10980
11064
|
const query = input.query ?? {};
|
|
10981
|
-
const body = await
|
|
11065
|
+
const { body, rawBody } = await readRequestBody(input.request);
|
|
11066
|
+
const verification = await verifyVoiceTelephonyWebhook({
|
|
11067
|
+
body,
|
|
11068
|
+
options,
|
|
11069
|
+
provider,
|
|
11070
|
+
query,
|
|
11071
|
+
rawBody,
|
|
11072
|
+
request: input.request
|
|
11073
|
+
});
|
|
11074
|
+
if (!verification.ok) {
|
|
11075
|
+
throw new VoiceTelephonyWebhookVerificationError(verification);
|
|
11076
|
+
}
|
|
10982
11077
|
const event = options.parse ? await options.parse({
|
|
10983
11078
|
body,
|
|
10984
11079
|
headers: input.request.headers,
|
|
@@ -11046,7 +11141,21 @@ var createVoiceTelephonyWebhookRoutes = (options = {}) => {
|
|
|
11046
11141
|
const handler = createVoiceTelephonyWebhookHandler(options);
|
|
11047
11142
|
return new Elysia16({
|
|
11048
11143
|
name: options.name ?? "absolutejs-voice-telephony-webhooks"
|
|
11049
|
-
}).post(path, async ({ query, request }) =>
|
|
11144
|
+
}).post(path, async ({ query, request }) => {
|
|
11145
|
+
try {
|
|
11146
|
+
return await handler({ query, request });
|
|
11147
|
+
} catch (error) {
|
|
11148
|
+
if (error instanceof VoiceTelephonyWebhookVerificationError) {
|
|
11149
|
+
return new Response(JSON.stringify({ verification: error.result }), {
|
|
11150
|
+
headers: {
|
|
11151
|
+
"content-type": "application/json"
|
|
11152
|
+
},
|
|
11153
|
+
status: 401
|
|
11154
|
+
});
|
|
11155
|
+
}
|
|
11156
|
+
throw error;
|
|
11157
|
+
}
|
|
11158
|
+
});
|
|
11050
11159
|
};
|
|
11051
11160
|
// src/fileStore.ts
|
|
11052
11161
|
import { mkdir as mkdir2, readFile, readdir, rename, rm, writeFile } from "fs/promises";
|
|
@@ -13152,7 +13261,7 @@ var signVoiceOpsWebhookBody = async (input) => {
|
|
|
13152
13261
|
const signature = await crypto.subtle.sign("HMAC", key, encoder.encode(`${input.timestamp}.${input.body}`));
|
|
13153
13262
|
return `sha256=${toHex5(new Uint8Array(signature))}`;
|
|
13154
13263
|
};
|
|
13155
|
-
var
|
|
13264
|
+
var timingSafeEqual2 = (left, right) => {
|
|
13156
13265
|
const encoder = new TextEncoder;
|
|
13157
13266
|
const leftBytes = encoder.encode(left);
|
|
13158
13267
|
const rightBytes = encoder.encode(right);
|
|
@@ -13259,7 +13368,7 @@ var verifyVoiceOpsWebhookSignature = async (input) => {
|
|
|
13259
13368
|
secret: input.secret,
|
|
13260
13369
|
timestamp: input.timestamp
|
|
13261
13370
|
});
|
|
13262
|
-
if (!
|
|
13371
|
+
if (!timingSafeEqual2(expected, input.signature)) {
|
|
13263
13372
|
return {
|
|
13264
13373
|
ok: false,
|
|
13265
13374
|
reason: "invalid-signature"
|
|
@@ -14978,7 +15087,7 @@ var createVoiceSTTRoutingCorrectionHandler = (mode = "generic") => {
|
|
|
14978
15087
|
return createPhraseHintCorrectionHandler();
|
|
14979
15088
|
};
|
|
14980
15089
|
// src/telephony/twilio.ts
|
|
14981
|
-
import { Buffer as
|
|
15090
|
+
import { Buffer as Buffer3 } from "buffer";
|
|
14982
15091
|
var TWILIO_MULAW_SAMPLE_RATE = 8000;
|
|
14983
15092
|
var VOICE_PCM_SAMPLE_RATE = 16000;
|
|
14984
15093
|
var escapeXml2 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
@@ -15083,7 +15192,7 @@ var bytesToInt16Array = (bytes) => {
|
|
|
15083
15192
|
return output;
|
|
15084
15193
|
};
|
|
15085
15194
|
var decodeTwilioMulawBase64 = (payload) => {
|
|
15086
|
-
const bytes = Uint8Array.from(
|
|
15195
|
+
const bytes = Uint8Array.from(Buffer3.from(payload, "base64"));
|
|
15087
15196
|
const samples = new Int16Array(bytes.length);
|
|
15088
15197
|
for (let index = 0;index < bytes.length; index += 1) {
|
|
15089
15198
|
samples[index] = decodeMulawSample(bytes[index] ?? 0);
|
|
@@ -15095,7 +15204,7 @@ var encodeTwilioMulawBase64 = (samples) => {
|
|
|
15095
15204
|
for (let index = 0;index < samples.length; index += 1) {
|
|
15096
15205
|
bytes[index] = encodeMulawSample(samples[index] ?? 0);
|
|
15097
15206
|
}
|
|
15098
|
-
return
|
|
15207
|
+
return Buffer3.from(bytes).toString("base64");
|
|
15099
15208
|
};
|
|
15100
15209
|
var transcodeTwilioInboundPayloadToPCM16 = (payload) => {
|
|
15101
15210
|
const narrowband = decodeTwilioMulawBase64(payload);
|
|
@@ -15104,7 +15213,7 @@ var transcodeTwilioInboundPayloadToPCM16 = (payload) => {
|
|
|
15104
15213
|
};
|
|
15105
15214
|
var transcodePCMToTwilioOutboundPayload = (chunk, format) => {
|
|
15106
15215
|
if (format.container === "raw" && format.encoding === "mulaw" && format.channels === 1 && format.sampleRateHz === TWILIO_MULAW_SAMPLE_RATE) {
|
|
15107
|
-
return
|
|
15216
|
+
return Buffer3.from(chunk).toString("base64");
|
|
15108
15217
|
}
|
|
15109
15218
|
if (format.encoding !== "pcm_s16le") {
|
|
15110
15219
|
throw new Error(`Unsupported outbound telephony audio format: ${format.container}/${format.encoding}`);
|
|
@@ -15145,7 +15254,7 @@ var createTwilioSocketAdapter = (socket, getState) => ({
|
|
|
15145
15254
|
return;
|
|
15146
15255
|
}
|
|
15147
15256
|
if (message.type === "audio") {
|
|
15148
|
-
const payload = transcodePCMToTwilioOutboundPayload(Uint8Array.from(
|
|
15257
|
+
const payload = transcodePCMToTwilioOutboundPayload(Uint8Array.from(Buffer3.from(message.chunkBase64, "base64")), message.format);
|
|
15149
15258
|
state.hasOutboundAudioSinceLastInbound = true;
|
|
15150
15259
|
state.reviewRecorder?.recordTwilioOutbound({
|
|
15151
15260
|
bytes: payload.length,
|
|
@@ -15415,6 +15524,7 @@ export {
|
|
|
15415
15524
|
withVoiceIntegrationEventId,
|
|
15416
15525
|
voiceTelephonyOutcomeToRouteResult,
|
|
15417
15526
|
voice,
|
|
15527
|
+
verifyVoiceTwilioWebhookSignature,
|
|
15418
15528
|
verifyVoiceOpsWebhookSignature,
|
|
15419
15529
|
validateVoiceWorkflowRouteResult,
|
|
15420
15530
|
transcodeTwilioInboundPayloadToPCM16,
|
|
@@ -15437,6 +15547,7 @@ export {
|
|
|
15437
15547
|
summarizeVoiceAssistantHealth,
|
|
15438
15548
|
summarizeVoiceAppKitStatus,
|
|
15439
15549
|
startVoiceOpsTask,
|
|
15550
|
+
signVoiceTwilioWebhook,
|
|
15440
15551
|
shapeTelephonyAssistantText,
|
|
15441
15552
|
selectVoiceTraceEventsForPrune,
|
|
15442
15553
|
runVoiceToolContractSuite,
|
|
@@ -59,6 +59,12 @@ export type VoiceTelephonyWebhookDecision<TResult = unknown> = {
|
|
|
59
59
|
routeResult: VoiceTelephonyOutcomeRouteResult<TResult>;
|
|
60
60
|
sessionId?: string;
|
|
61
61
|
};
|
|
62
|
+
export type VoiceTelephonyWebhookVerificationResult = {
|
|
63
|
+
ok: true;
|
|
64
|
+
} | {
|
|
65
|
+
ok: false;
|
|
66
|
+
reason: 'invalid-signature' | 'missing-secret' | 'missing-signature' | 'unsupported-provider';
|
|
67
|
+
};
|
|
62
68
|
export type VoiceTelephonyWebhookHandlerOptions<TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown> = {
|
|
63
69
|
apply?: boolean | ((input: VoiceTelephonyWebhookDecision<TResult>) => boolean);
|
|
64
70
|
context?: TContext;
|
|
@@ -76,6 +82,7 @@ export type VoiceTelephonyWebhookHandlerOptions<TContext = unknown, TSession ext
|
|
|
76
82
|
parse?: (input: VoiceTelephonyWebhookParseInput) => Promise<VoiceTelephonyOutcomeProviderEvent> | VoiceTelephonyOutcomeProviderEvent;
|
|
77
83
|
policy?: VoiceTelephonyOutcomePolicy;
|
|
78
84
|
provider?: VoiceTelephonyWebhookProvider;
|
|
85
|
+
requireVerification?: boolean;
|
|
79
86
|
resolveSessionId?: (input: {
|
|
80
87
|
body: unknown;
|
|
81
88
|
event: VoiceTelephonyOutcomeProviderEvent;
|
|
@@ -87,15 +94,43 @@ export type VoiceTelephonyWebhookHandlerOptions<TContext = unknown, TSession ext
|
|
|
87
94
|
event: VoiceTelephonyOutcomeProviderEvent;
|
|
88
95
|
sessionId?: string;
|
|
89
96
|
}) => Promise<TResult | undefined> | TResult | undefined);
|
|
97
|
+
signingSecret?: string;
|
|
98
|
+
verificationUrl?: string | ((input: {
|
|
99
|
+
query: Record<string, unknown>;
|
|
100
|
+
request: Request;
|
|
101
|
+
}) => string);
|
|
102
|
+
verify?: (input: {
|
|
103
|
+
body: unknown;
|
|
104
|
+
headers: Headers;
|
|
105
|
+
provider: VoiceTelephonyWebhookProvider;
|
|
106
|
+
query: Record<string, unknown>;
|
|
107
|
+
rawBody: string;
|
|
108
|
+
request: Request;
|
|
109
|
+
}) => Promise<VoiceTelephonyWebhookVerificationResult> | VoiceTelephonyWebhookVerificationResult;
|
|
90
110
|
};
|
|
91
111
|
export type VoiceTelephonyWebhookRoutesOptions<TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown> = VoiceTelephonyWebhookHandlerOptions<TContext, TSession, TResult> & {
|
|
92
112
|
name?: string;
|
|
93
113
|
path?: string;
|
|
94
114
|
};
|
|
115
|
+
export declare class VoiceTelephonyWebhookVerificationError extends Error {
|
|
116
|
+
result: VoiceTelephonyWebhookVerificationResult;
|
|
117
|
+
constructor(result: VoiceTelephonyWebhookVerificationResult);
|
|
118
|
+
}
|
|
95
119
|
export declare const createVoiceTelephonyOutcomePolicy: (policy?: VoiceTelephonyOutcomePolicy) => Required<Pick<VoiceTelephonyOutcomePolicy, "completedStatuses" | "escalationStatuses" | "failedAsNoAnswer" | "failedStatuses" | "includeProviderPayload" | "machineDetectionVoicemailValues" | "noAnswerOnZeroDuration" | "noAnswerSipCodes" | "noAnswerStatuses" | "transferStatuses" | "voicemailStatuses">> & VoiceTelephonyOutcomePolicy;
|
|
96
120
|
export declare const resolveVoiceTelephonyOutcome: (event: VoiceTelephonyOutcomeProviderEvent, policyInput?: VoiceTelephonyOutcomePolicy) => VoiceTelephonyOutcomeDecision;
|
|
97
121
|
export declare const voiceTelephonyOutcomeToRouteResult: <TResult = unknown>(decision: VoiceTelephonyOutcomeDecision, result?: TResult) => VoiceTelephonyOutcomeRouteResult<TResult>;
|
|
98
122
|
export declare const applyVoiceTelephonyOutcome: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown>(api: VoiceSessionHandle<TContext, TSession, TResult>, decision: VoiceTelephonyOutcomeDecision, result?: TResult) => Promise<void>;
|
|
123
|
+
export declare const signVoiceTwilioWebhook: (input: {
|
|
124
|
+
authToken: string;
|
|
125
|
+
body?: unknown;
|
|
126
|
+
url: string;
|
|
127
|
+
}) => Promise<string>;
|
|
128
|
+
export declare const verifyVoiceTwilioWebhookSignature: (input: {
|
|
129
|
+
authToken?: string;
|
|
130
|
+
body?: unknown;
|
|
131
|
+
headers: Headers;
|
|
132
|
+
url: string;
|
|
133
|
+
}) => Promise<VoiceTelephonyWebhookVerificationResult>;
|
|
99
134
|
export declare const parseVoiceTelephonyWebhookEvent: (input: VoiceTelephonyWebhookParseInput) => VoiceTelephonyOutcomeProviderEvent;
|
|
100
135
|
export declare const createVoiceTelephonyWebhookHandler: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown>(options?: VoiceTelephonyWebhookHandlerOptions<TContext, TSession, TResult>) => (input: {
|
|
101
136
|
query?: Record<string, unknown>;
|
|
@@ -124,7 +159,7 @@ export declare const createVoiceTelephonyWebhookRoutes: <TContext = unknown, TSe
|
|
|
124
159
|
query: unknown;
|
|
125
160
|
headers: unknown;
|
|
126
161
|
response: {
|
|
127
|
-
200: VoiceTelephonyWebhookDecision<TResult>;
|
|
162
|
+
200: Response | VoiceTelephonyWebhookDecision<TResult>;
|
|
128
163
|
};
|
|
129
164
|
};
|
|
130
165
|
};
|