@absolutejs/voice 0.0.22-beta.322 → 0.0.22-beta.323
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/angular/index.js +164 -0
- package/dist/client/index.js +164 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +730 -437
- package/dist/react/index.js +164 -0
- package/dist/svelte/index.js +164 -0
- package/dist/telephonyMediaRoutes.d.ts +63 -0
- package/dist/testing/index.js +177 -13
- package/dist/vue/index.js +164 -0
- package/package.json +2 -2
package/dist/angular/index.js
CHANGED
|
@@ -1414,6 +1414,63 @@ var stringStat = (stat, key) => {
|
|
|
1414
1414
|
};
|
|
1415
1415
|
var statKey = (stat) => String(stat.id ?? stringStat(stat, "ssrc") ?? numericStat(stat, "ssrc") ?? stringStat(stat, "trackIdentifier") ?? stringStat(stat, "mid") ?? "unknown");
|
|
1416
1416
|
var secondsToMs = (value) => value === undefined ? undefined : value * 1000;
|
|
1417
|
+
var DEFAULT_TELEPHONY_FORMAT = {
|
|
1418
|
+
channels: 1,
|
|
1419
|
+
container: "raw",
|
|
1420
|
+
encoding: "mulaw",
|
|
1421
|
+
sampleRateHz: 8000
|
|
1422
|
+
};
|
|
1423
|
+
var bytesToBase64 = (audio) => {
|
|
1424
|
+
const bytes = audio instanceof ArrayBuffer ? new Uint8Array(audio) : new Uint8Array(audio.buffer, audio.byteOffset, audio.byteLength);
|
|
1425
|
+
return Buffer.from(bytes).toString("base64");
|
|
1426
|
+
};
|
|
1427
|
+
var base64ToBytes = (value) => new Uint8Array(Buffer.from(value, "base64"));
|
|
1428
|
+
var unknownRecord = (value) => value && typeof value === "object" ? value : {};
|
|
1429
|
+
var firstString = (records, keys) => {
|
|
1430
|
+
for (const record of records) {
|
|
1431
|
+
for (const key of keys) {
|
|
1432
|
+
const value = record[key];
|
|
1433
|
+
if (typeof value === "string" && value.length > 0) {
|
|
1434
|
+
return value;
|
|
1435
|
+
}
|
|
1436
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
1437
|
+
return String(value);
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
return;
|
|
1442
|
+
};
|
|
1443
|
+
var firstNumber = (records, keys) => {
|
|
1444
|
+
for (const record of records) {
|
|
1445
|
+
for (const key of keys) {
|
|
1446
|
+
const value = record[key];
|
|
1447
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
1448
|
+
return value;
|
|
1449
|
+
}
|
|
1450
|
+
if (typeof value === "string") {
|
|
1451
|
+
const parsed = Number(value);
|
|
1452
|
+
if (Number.isFinite(parsed)) {
|
|
1453
|
+
return parsed;
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
return;
|
|
1459
|
+
};
|
|
1460
|
+
var telephonyDirection = (track) => {
|
|
1461
|
+
const normalized = track?.toLowerCase();
|
|
1462
|
+
if (!normalized) {
|
|
1463
|
+
return "unknown";
|
|
1464
|
+
}
|
|
1465
|
+
if (normalized.includes("inbound") || normalized.includes("caller") || normalized.includes("in")) {
|
|
1466
|
+
return "inbound";
|
|
1467
|
+
}
|
|
1468
|
+
if (normalized.includes("outbound") || normalized.includes("assistant") || normalized.includes("out")) {
|
|
1469
|
+
return "outbound";
|
|
1470
|
+
}
|
|
1471
|
+
return "unknown";
|
|
1472
|
+
};
|
|
1473
|
+
var telephonyFrameKind = (direction) => direction === "outbound" ? "assistant-audio" : "input-audio";
|
|
1417
1474
|
var normalizeWebRTCStat = (stat) => {
|
|
1418
1475
|
const sample = {};
|
|
1419
1476
|
for (const [key, value] of Object.entries(stat)) {
|
|
@@ -1423,6 +1480,113 @@ var normalizeWebRTCStat = (stat) => {
|
|
|
1423
1480
|
}
|
|
1424
1481
|
return sample;
|
|
1425
1482
|
};
|
|
1483
|
+
var parseTelephonyMediaFrame = (input) => {
|
|
1484
|
+
const envelope = input.envelope;
|
|
1485
|
+
const media = unknownRecord(envelope.media);
|
|
1486
|
+
const payload = firstString([media, envelope], ["payload", "audio", "data"]) ?? firstString([unknownRecord(envelope.message)], ["payload"]);
|
|
1487
|
+
if (!payload) {
|
|
1488
|
+
return;
|
|
1489
|
+
}
|
|
1490
|
+
const carrier = input.carrier ?? firstString([envelope], ["provider"]) ?? "telephony";
|
|
1491
|
+
const streamId = firstString([media, envelope], ["streamSid", "stream_id", "streamId", "streamId", "callSid", "call_id"]);
|
|
1492
|
+
const sequenceNumber = firstString([media, envelope], ["sequenceNumber", "sequence_number", "chunk"]);
|
|
1493
|
+
const track = firstString([media, envelope], ["track", "direction"]);
|
|
1494
|
+
const direction = telephonyDirection(track);
|
|
1495
|
+
const timestamp = firstNumber([media, envelope], ["timestamp", "time", "startedAt"]);
|
|
1496
|
+
return {
|
|
1497
|
+
at: timestamp,
|
|
1498
|
+
audio: base64ToBytes(payload),
|
|
1499
|
+
format: input.format ?? DEFAULT_TELEPHONY_FORMAT,
|
|
1500
|
+
id: [
|
|
1501
|
+
carrier,
|
|
1502
|
+
streamId ?? input.sessionId ?? "stream",
|
|
1503
|
+
sequenceNumber ?? timestamp ?? Date.now()
|
|
1504
|
+
].join(":"),
|
|
1505
|
+
kind: telephonyFrameKind(direction),
|
|
1506
|
+
metadata: {
|
|
1507
|
+
carrier,
|
|
1508
|
+
direction,
|
|
1509
|
+
event: firstString([envelope], ["event", "type"]),
|
|
1510
|
+
sequenceNumber,
|
|
1511
|
+
streamId,
|
|
1512
|
+
track
|
|
1513
|
+
},
|
|
1514
|
+
sessionId: input.sessionId ?? streamId,
|
|
1515
|
+
source: "telephony"
|
|
1516
|
+
};
|
|
1517
|
+
};
|
|
1518
|
+
var serializeTelephonyMediaFrame = (input) => {
|
|
1519
|
+
const carrier = input.carrier ?? input.frame.metadata?.carrier ?? "telephony";
|
|
1520
|
+
const streamId = input.streamId ?? (typeof input.frame.metadata?.streamId === "string" ? input.frame.metadata.streamId : input.frame.sessionId);
|
|
1521
|
+
const sequenceNumber = input.sequenceNumber ?? (typeof input.frame.metadata?.sequenceNumber === "string" || typeof input.frame.metadata?.sequenceNumber === "number" ? input.frame.metadata.sequenceNumber : undefined);
|
|
1522
|
+
const direction = input.frame.kind === "assistant-audio" ? "outbound" : "inbound";
|
|
1523
|
+
const payload = input.frame.audio ? bytesToBase64(input.frame.audio) : "";
|
|
1524
|
+
if (carrier === "twilio") {
|
|
1525
|
+
return {
|
|
1526
|
+
event: "media",
|
|
1527
|
+
sequenceNumber,
|
|
1528
|
+
streamSid: streamId,
|
|
1529
|
+
media: {
|
|
1530
|
+
payload,
|
|
1531
|
+
timestamp: input.frame.at,
|
|
1532
|
+
track: direction
|
|
1533
|
+
}
|
|
1534
|
+
};
|
|
1535
|
+
}
|
|
1536
|
+
if (carrier === "telnyx") {
|
|
1537
|
+
return {
|
|
1538
|
+
event: "media",
|
|
1539
|
+
stream_id: streamId,
|
|
1540
|
+
sequence_number: sequenceNumber,
|
|
1541
|
+
media: {
|
|
1542
|
+
payload,
|
|
1543
|
+
timestamp: input.frame.at,
|
|
1544
|
+
track: direction
|
|
1545
|
+
}
|
|
1546
|
+
};
|
|
1547
|
+
}
|
|
1548
|
+
if (carrier === "plivo") {
|
|
1549
|
+
return {
|
|
1550
|
+
event: "media",
|
|
1551
|
+
streamId,
|
|
1552
|
+
sequenceNumber,
|
|
1553
|
+
media: {
|
|
1554
|
+
payload,
|
|
1555
|
+
timestamp: input.frame.at,
|
|
1556
|
+
track: direction
|
|
1557
|
+
}
|
|
1558
|
+
};
|
|
1559
|
+
}
|
|
1560
|
+
return {
|
|
1561
|
+
event: "media",
|
|
1562
|
+
provider: carrier,
|
|
1563
|
+
sequenceNumber,
|
|
1564
|
+
streamId,
|
|
1565
|
+
media: {
|
|
1566
|
+
payload,
|
|
1567
|
+
timestamp: input.frame.at,
|
|
1568
|
+
track: direction
|
|
1569
|
+
}
|
|
1570
|
+
};
|
|
1571
|
+
};
|
|
1572
|
+
var createTelephonyMediaSerializer = (input) => {
|
|
1573
|
+
const format = input.format ?? DEFAULT_TELEPHONY_FORMAT;
|
|
1574
|
+
return {
|
|
1575
|
+
carrier: input.carrier,
|
|
1576
|
+
format,
|
|
1577
|
+
parse: (envelope) => parseTelephonyMediaFrame({
|
|
1578
|
+
carrier: input.carrier,
|
|
1579
|
+
envelope,
|
|
1580
|
+
format,
|
|
1581
|
+
sessionId: input.sessionId ?? input.streamId
|
|
1582
|
+
}),
|
|
1583
|
+
serialize: (frame) => serializeTelephonyMediaFrame({
|
|
1584
|
+
carrier: input.carrier,
|
|
1585
|
+
frame,
|
|
1586
|
+
streamId: input.streamId
|
|
1587
|
+
})
|
|
1588
|
+
};
|
|
1589
|
+
};
|
|
1426
1590
|
var buildMediaResamplingPlan = (input) => {
|
|
1427
1591
|
const required = !formatMatches(input.inputFormat, input.outputFormat);
|
|
1428
1592
|
return {
|
package/dist/client/index.js
CHANGED
|
@@ -807,6 +807,63 @@ var stringStat = (stat, key) => {
|
|
|
807
807
|
};
|
|
808
808
|
var statKey = (stat) => String(stat.id ?? stringStat(stat, "ssrc") ?? numericStat(stat, "ssrc") ?? stringStat(stat, "trackIdentifier") ?? stringStat(stat, "mid") ?? "unknown");
|
|
809
809
|
var secondsToMs = (value) => value === undefined ? undefined : value * 1000;
|
|
810
|
+
var DEFAULT_TELEPHONY_FORMAT = {
|
|
811
|
+
channels: 1,
|
|
812
|
+
container: "raw",
|
|
813
|
+
encoding: "mulaw",
|
|
814
|
+
sampleRateHz: 8000
|
|
815
|
+
};
|
|
816
|
+
var bytesToBase64 = (audio) => {
|
|
817
|
+
const bytes = audio instanceof ArrayBuffer ? new Uint8Array(audio) : new Uint8Array(audio.buffer, audio.byteOffset, audio.byteLength);
|
|
818
|
+
return Buffer.from(bytes).toString("base64");
|
|
819
|
+
};
|
|
820
|
+
var base64ToBytes = (value) => new Uint8Array(Buffer.from(value, "base64"));
|
|
821
|
+
var unknownRecord = (value) => value && typeof value === "object" ? value : {};
|
|
822
|
+
var firstString = (records, keys) => {
|
|
823
|
+
for (const record of records) {
|
|
824
|
+
for (const key of keys) {
|
|
825
|
+
const value = record[key];
|
|
826
|
+
if (typeof value === "string" && value.length > 0) {
|
|
827
|
+
return value;
|
|
828
|
+
}
|
|
829
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
830
|
+
return String(value);
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
return;
|
|
835
|
+
};
|
|
836
|
+
var firstNumber = (records, keys) => {
|
|
837
|
+
for (const record of records) {
|
|
838
|
+
for (const key of keys) {
|
|
839
|
+
const value = record[key];
|
|
840
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
841
|
+
return value;
|
|
842
|
+
}
|
|
843
|
+
if (typeof value === "string") {
|
|
844
|
+
const parsed = Number(value);
|
|
845
|
+
if (Number.isFinite(parsed)) {
|
|
846
|
+
return parsed;
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
return;
|
|
852
|
+
};
|
|
853
|
+
var telephonyDirection = (track) => {
|
|
854
|
+
const normalized = track?.toLowerCase();
|
|
855
|
+
if (!normalized) {
|
|
856
|
+
return "unknown";
|
|
857
|
+
}
|
|
858
|
+
if (normalized.includes("inbound") || normalized.includes("caller") || normalized.includes("in")) {
|
|
859
|
+
return "inbound";
|
|
860
|
+
}
|
|
861
|
+
if (normalized.includes("outbound") || normalized.includes("assistant") || normalized.includes("out")) {
|
|
862
|
+
return "outbound";
|
|
863
|
+
}
|
|
864
|
+
return "unknown";
|
|
865
|
+
};
|
|
866
|
+
var telephonyFrameKind = (direction) => direction === "outbound" ? "assistant-audio" : "input-audio";
|
|
810
867
|
var normalizeWebRTCStat = (stat) => {
|
|
811
868
|
const sample = {};
|
|
812
869
|
for (const [key, value] of Object.entries(stat)) {
|
|
@@ -816,6 +873,113 @@ var normalizeWebRTCStat = (stat) => {
|
|
|
816
873
|
}
|
|
817
874
|
return sample;
|
|
818
875
|
};
|
|
876
|
+
var parseTelephonyMediaFrame = (input) => {
|
|
877
|
+
const envelope = input.envelope;
|
|
878
|
+
const media = unknownRecord(envelope.media);
|
|
879
|
+
const payload = firstString([media, envelope], ["payload", "audio", "data"]) ?? firstString([unknownRecord(envelope.message)], ["payload"]);
|
|
880
|
+
if (!payload) {
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
883
|
+
const carrier = input.carrier ?? firstString([envelope], ["provider"]) ?? "telephony";
|
|
884
|
+
const streamId = firstString([media, envelope], ["streamSid", "stream_id", "streamId", "streamId", "callSid", "call_id"]);
|
|
885
|
+
const sequenceNumber = firstString([media, envelope], ["sequenceNumber", "sequence_number", "chunk"]);
|
|
886
|
+
const track = firstString([media, envelope], ["track", "direction"]);
|
|
887
|
+
const direction = telephonyDirection(track);
|
|
888
|
+
const timestamp = firstNumber([media, envelope], ["timestamp", "time", "startedAt"]);
|
|
889
|
+
return {
|
|
890
|
+
at: timestamp,
|
|
891
|
+
audio: base64ToBytes(payload),
|
|
892
|
+
format: input.format ?? DEFAULT_TELEPHONY_FORMAT,
|
|
893
|
+
id: [
|
|
894
|
+
carrier,
|
|
895
|
+
streamId ?? input.sessionId ?? "stream",
|
|
896
|
+
sequenceNumber ?? timestamp ?? Date.now()
|
|
897
|
+
].join(":"),
|
|
898
|
+
kind: telephonyFrameKind(direction),
|
|
899
|
+
metadata: {
|
|
900
|
+
carrier,
|
|
901
|
+
direction,
|
|
902
|
+
event: firstString([envelope], ["event", "type"]),
|
|
903
|
+
sequenceNumber,
|
|
904
|
+
streamId,
|
|
905
|
+
track
|
|
906
|
+
},
|
|
907
|
+
sessionId: input.sessionId ?? streamId,
|
|
908
|
+
source: "telephony"
|
|
909
|
+
};
|
|
910
|
+
};
|
|
911
|
+
var serializeTelephonyMediaFrame = (input) => {
|
|
912
|
+
const carrier = input.carrier ?? input.frame.metadata?.carrier ?? "telephony";
|
|
913
|
+
const streamId = input.streamId ?? (typeof input.frame.metadata?.streamId === "string" ? input.frame.metadata.streamId : input.frame.sessionId);
|
|
914
|
+
const sequenceNumber = input.sequenceNumber ?? (typeof input.frame.metadata?.sequenceNumber === "string" || typeof input.frame.metadata?.sequenceNumber === "number" ? input.frame.metadata.sequenceNumber : undefined);
|
|
915
|
+
const direction = input.frame.kind === "assistant-audio" ? "outbound" : "inbound";
|
|
916
|
+
const payload = input.frame.audio ? bytesToBase64(input.frame.audio) : "";
|
|
917
|
+
if (carrier === "twilio") {
|
|
918
|
+
return {
|
|
919
|
+
event: "media",
|
|
920
|
+
sequenceNumber,
|
|
921
|
+
streamSid: streamId,
|
|
922
|
+
media: {
|
|
923
|
+
payload,
|
|
924
|
+
timestamp: input.frame.at,
|
|
925
|
+
track: direction
|
|
926
|
+
}
|
|
927
|
+
};
|
|
928
|
+
}
|
|
929
|
+
if (carrier === "telnyx") {
|
|
930
|
+
return {
|
|
931
|
+
event: "media",
|
|
932
|
+
stream_id: streamId,
|
|
933
|
+
sequence_number: sequenceNumber,
|
|
934
|
+
media: {
|
|
935
|
+
payload,
|
|
936
|
+
timestamp: input.frame.at,
|
|
937
|
+
track: direction
|
|
938
|
+
}
|
|
939
|
+
};
|
|
940
|
+
}
|
|
941
|
+
if (carrier === "plivo") {
|
|
942
|
+
return {
|
|
943
|
+
event: "media",
|
|
944
|
+
streamId,
|
|
945
|
+
sequenceNumber,
|
|
946
|
+
media: {
|
|
947
|
+
payload,
|
|
948
|
+
timestamp: input.frame.at,
|
|
949
|
+
track: direction
|
|
950
|
+
}
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
return {
|
|
954
|
+
event: "media",
|
|
955
|
+
provider: carrier,
|
|
956
|
+
sequenceNumber,
|
|
957
|
+
streamId,
|
|
958
|
+
media: {
|
|
959
|
+
payload,
|
|
960
|
+
timestamp: input.frame.at,
|
|
961
|
+
track: direction
|
|
962
|
+
}
|
|
963
|
+
};
|
|
964
|
+
};
|
|
965
|
+
var createTelephonyMediaSerializer = (input) => {
|
|
966
|
+
const format = input.format ?? DEFAULT_TELEPHONY_FORMAT;
|
|
967
|
+
return {
|
|
968
|
+
carrier: input.carrier,
|
|
969
|
+
format,
|
|
970
|
+
parse: (envelope) => parseTelephonyMediaFrame({
|
|
971
|
+
carrier: input.carrier,
|
|
972
|
+
envelope,
|
|
973
|
+
format,
|
|
974
|
+
sessionId: input.sessionId ?? input.streamId
|
|
975
|
+
}),
|
|
976
|
+
serialize: (frame) => serializeTelephonyMediaFrame({
|
|
977
|
+
carrier: input.carrier,
|
|
978
|
+
frame,
|
|
979
|
+
streamId: input.streamId
|
|
980
|
+
})
|
|
981
|
+
};
|
|
982
|
+
};
|
|
819
983
|
var buildMediaResamplingPlan = (input) => {
|
|
820
984
|
const required = !formatMatches(input.inputFormat, input.outputFormat);
|
|
821
985
|
return {
|
package/dist/index.d.ts
CHANGED
|
@@ -16,8 +16,10 @@ export { assertVoiceRealtimeProviderContractEvidence, buildVoiceRealtimeProvider
|
|
|
16
16
|
export type { VoiceRealtimeProviderContractAssertionInput, VoiceRealtimeProviderContractAssertionReport, VoiceRealtimeProviderContractCapability, VoiceRealtimeProviderContractCheck, VoiceRealtimeProviderContractDefinition, VoiceRealtimeProviderContractMatrixPresetOptions, VoiceRealtimeProviderContractMatrixInput, VoiceRealtimeProviderContractMatrixReport, VoiceRealtimeProviderContractRoutesOptions, VoiceRealtimeProviderContractRow, VoiceRealtimeProviderPresetProvider, VoiceRealtimeProviderContractStatus } from './realtimeProviderContracts';
|
|
17
17
|
export { buildVoiceDiagnosticsMarkdown, createVoiceDiagnosticsRoutes, resolveVoiceDiagnosticsTraceFilter } from './diagnosticsRoutes';
|
|
18
18
|
export { assertVoiceMediaPipelineEvidence, buildVoiceMediaPipelineReport, createVoiceMediaPipelineRoutes, evaluateVoiceMediaPipelineEvidence, renderVoiceMediaPipelineHTML, renderVoiceMediaPipelineMarkdown } from './mediaPipelineRoutes';
|
|
19
|
+
export { buildVoiceTelephonyMediaReport, createVoiceTelephonyMediaRoutes, renderVoiceTelephonyMediaHTML } from './telephonyMediaRoutes';
|
|
19
20
|
export { createVoiceBrowserMediaRoutes, getLatestVoiceBrowserMediaReport, renderVoiceBrowserMediaHTML, summarizeVoiceBrowserMedia } from './browserMediaRoutes';
|
|
20
21
|
export type { VoiceMediaPipelineAssertionInput, VoiceMediaPipelineAssertionReport, VoiceMediaPipelineReport, VoiceMediaPipelineReportOptions, VoiceMediaPipelineRoutesOptions } from './mediaPipelineRoutes';
|
|
22
|
+
export type { VoiceTelephonyMediaCarrierInput, VoiceTelephonyMediaCarrierReport, VoiceTelephonyMediaReport, VoiceTelephonyMediaRoutesOptions, VoiceTelephonyMediaStatus } from './telephonyMediaRoutes';
|
|
21
23
|
export type { VoiceBrowserMediaReport, VoiceBrowserMediaRoutesOptions, VoiceBrowserMediaSample, VoiceBrowserMediaStatus } from './browserMediaRoutes';
|
|
22
24
|
export { buildVoiceDemoReadyReport, createVoiceDemoReadyRoutes, renderVoiceDemoReadyHTML } from './demoReadyRoutes';
|
|
23
25
|
export { buildVoiceDeliverySinkReport, createVoiceDeliverySinkDescriptor, createVoiceDeliverySinkPair, createVoiceDeliverySinkRoutes, createVoiceFileDeliverySink, createVoicePostgresDeliverySink, createVoiceS3DeliverySink, createVoiceSQLiteDeliverySink, createVoiceWebhookDeliverySink, renderVoiceDeliverySinkHTML } from './deliverySinkRoutes';
|