@absolutejs/voice 0.0.22-beta.322 → 0.0.22-beta.324

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.
@@ -2186,6 +2186,63 @@ var stringStat = (stat, key) => {
2186
2186
  };
2187
2187
  var statKey = (stat) => String(stat.id ?? stringStat(stat, "ssrc") ?? numericStat(stat, "ssrc") ?? stringStat(stat, "trackIdentifier") ?? stringStat(stat, "mid") ?? "unknown");
2188
2188
  var secondsToMs = (value) => value === undefined ? undefined : value * 1000;
2189
+ var DEFAULT_TELEPHONY_FORMAT = {
2190
+ channels: 1,
2191
+ container: "raw",
2192
+ encoding: "mulaw",
2193
+ sampleRateHz: 8000
2194
+ };
2195
+ var bytesToBase64 = (audio) => {
2196
+ const bytes = audio instanceof ArrayBuffer ? new Uint8Array(audio) : new Uint8Array(audio.buffer, audio.byteOffset, audio.byteLength);
2197
+ return Buffer.from(bytes).toString("base64");
2198
+ };
2199
+ var base64ToBytes = (value) => new Uint8Array(Buffer.from(value, "base64"));
2200
+ var unknownRecord = (value) => value && typeof value === "object" ? value : {};
2201
+ var firstString = (records, keys) => {
2202
+ for (const record of records) {
2203
+ for (const key of keys) {
2204
+ const value = record[key];
2205
+ if (typeof value === "string" && value.length > 0) {
2206
+ return value;
2207
+ }
2208
+ if (typeof value === "number" && Number.isFinite(value)) {
2209
+ return String(value);
2210
+ }
2211
+ }
2212
+ }
2213
+ return;
2214
+ };
2215
+ var firstNumber = (records, keys) => {
2216
+ for (const record of records) {
2217
+ for (const key of keys) {
2218
+ const value = record[key];
2219
+ if (typeof value === "number" && Number.isFinite(value)) {
2220
+ return value;
2221
+ }
2222
+ if (typeof value === "string") {
2223
+ const parsed = Number(value);
2224
+ if (Number.isFinite(parsed)) {
2225
+ return parsed;
2226
+ }
2227
+ }
2228
+ }
2229
+ }
2230
+ return;
2231
+ };
2232
+ var telephonyDirection = (track) => {
2233
+ const normalized = track?.toLowerCase();
2234
+ if (!normalized) {
2235
+ return "unknown";
2236
+ }
2237
+ if (normalized.includes("inbound") || normalized.includes("caller") || normalized.includes("in")) {
2238
+ return "inbound";
2239
+ }
2240
+ if (normalized.includes("outbound") || normalized.includes("assistant") || normalized.includes("out")) {
2241
+ return "outbound";
2242
+ }
2243
+ return "unknown";
2244
+ };
2245
+ var telephonyFrameKind = (direction) => direction === "outbound" ? "assistant-audio" : "input-audio";
2189
2246
  var normalizeWebRTCStat = (stat) => {
2190
2247
  const sample = {};
2191
2248
  for (const [key, value] of Object.entries(stat)) {
@@ -2195,6 +2252,113 @@ var normalizeWebRTCStat = (stat) => {
2195
2252
  }
2196
2253
  return sample;
2197
2254
  };
2255
+ var parseTelephonyMediaFrame = (input) => {
2256
+ const envelope = input.envelope;
2257
+ const media = unknownRecord(envelope.media);
2258
+ const payload = firstString([media, envelope], ["payload", "audio", "data"]) ?? firstString([unknownRecord(envelope.message)], ["payload"]);
2259
+ if (!payload) {
2260
+ return;
2261
+ }
2262
+ const carrier = input.carrier ?? firstString([envelope], ["provider"]) ?? "telephony";
2263
+ const streamId = firstString([media, envelope], ["streamSid", "stream_id", "streamId", "streamId", "callSid", "call_id"]);
2264
+ const sequenceNumber = firstString([media, envelope], ["sequenceNumber", "sequence_number", "chunk"]);
2265
+ const track = firstString([media, envelope], ["track", "direction"]);
2266
+ const direction = telephonyDirection(track);
2267
+ const timestamp = firstNumber([media, envelope], ["timestamp", "time", "startedAt"]);
2268
+ return {
2269
+ at: timestamp,
2270
+ audio: base64ToBytes(payload),
2271
+ format: input.format ?? DEFAULT_TELEPHONY_FORMAT,
2272
+ id: [
2273
+ carrier,
2274
+ streamId ?? input.sessionId ?? "stream",
2275
+ sequenceNumber ?? timestamp ?? Date.now()
2276
+ ].join(":"),
2277
+ kind: telephonyFrameKind(direction),
2278
+ metadata: {
2279
+ carrier,
2280
+ direction,
2281
+ event: firstString([envelope], ["event", "type"]),
2282
+ sequenceNumber,
2283
+ streamId,
2284
+ track
2285
+ },
2286
+ sessionId: input.sessionId ?? streamId,
2287
+ source: "telephony"
2288
+ };
2289
+ };
2290
+ var serializeTelephonyMediaFrame = (input) => {
2291
+ const carrier = input.carrier ?? input.frame.metadata?.carrier ?? "telephony";
2292
+ const streamId = input.streamId ?? (typeof input.frame.metadata?.streamId === "string" ? input.frame.metadata.streamId : input.frame.sessionId);
2293
+ const sequenceNumber = input.sequenceNumber ?? (typeof input.frame.metadata?.sequenceNumber === "string" || typeof input.frame.metadata?.sequenceNumber === "number" ? input.frame.metadata.sequenceNumber : undefined);
2294
+ const direction = input.frame.kind === "assistant-audio" ? "outbound" : "inbound";
2295
+ const payload = input.frame.audio ? bytesToBase64(input.frame.audio) : "";
2296
+ if (carrier === "twilio") {
2297
+ return {
2298
+ event: "media",
2299
+ sequenceNumber,
2300
+ streamSid: streamId,
2301
+ media: {
2302
+ payload,
2303
+ timestamp: input.frame.at,
2304
+ track: direction
2305
+ }
2306
+ };
2307
+ }
2308
+ if (carrier === "telnyx") {
2309
+ return {
2310
+ event: "media",
2311
+ stream_id: streamId,
2312
+ sequence_number: sequenceNumber,
2313
+ media: {
2314
+ payload,
2315
+ timestamp: input.frame.at,
2316
+ track: direction
2317
+ }
2318
+ };
2319
+ }
2320
+ if (carrier === "plivo") {
2321
+ return {
2322
+ event: "media",
2323
+ streamId,
2324
+ sequenceNumber,
2325
+ media: {
2326
+ payload,
2327
+ timestamp: input.frame.at,
2328
+ track: direction
2329
+ }
2330
+ };
2331
+ }
2332
+ return {
2333
+ event: "media",
2334
+ provider: carrier,
2335
+ sequenceNumber,
2336
+ streamId,
2337
+ media: {
2338
+ payload,
2339
+ timestamp: input.frame.at,
2340
+ track: direction
2341
+ }
2342
+ };
2343
+ };
2344
+ var createTelephonyMediaSerializer = (input) => {
2345
+ const format = input.format ?? DEFAULT_TELEPHONY_FORMAT;
2346
+ return {
2347
+ carrier: input.carrier,
2348
+ format,
2349
+ parse: (envelope) => parseTelephonyMediaFrame({
2350
+ carrier: input.carrier,
2351
+ envelope,
2352
+ format,
2353
+ sessionId: input.sessionId ?? input.streamId
2354
+ }),
2355
+ serialize: (frame) => serializeTelephonyMediaFrame({
2356
+ carrier: input.carrier,
2357
+ frame,
2358
+ streamId: input.streamId
2359
+ })
2360
+ };
2361
+ };
2198
2362
  var buildMediaResamplingPlan = (input) => {
2199
2363
  const required = !formatMatches(input.inputFormat, input.outputFormat);
2200
2364
  return {
@@ -8899,7 +9063,7 @@ var assertVoiceTelephonyWebhookNormalizationEvidence = (input = {}) => {
8899
9063
  return assertion;
8900
9064
  };
8901
9065
  var normalizeToken = (value) => typeof value === "string" ? value.trim().toLowerCase().replace(/\s+/g, "-").replace(/_+/g, "-") : undefined;
8902
- var firstString = (source, keys) => {
9066
+ var firstString2 = (source, keys) => {
8903
9067
  for (const key of keys) {
8904
9068
  const value = source[key];
8905
9069
  if (typeof value === "string" && value.trim()) {
@@ -8910,7 +9074,7 @@ var firstString = (source, keys) => {
8910
9074
  }
8911
9075
  }
8912
9076
  };
8913
- var firstNumber = (source, keys) => {
9077
+ var firstNumber2 = (source, keys) => {
8914
9078
  for (const key of keys) {
8915
9079
  const value = source[key];
8916
9080
  if (typeof value === "number" && Number.isFinite(value)) {
@@ -9271,8 +9435,8 @@ var verifyVoiceTelephonyWebhook = async (input) => {
9271
9435
  var durationMsFromSeconds = (value) => typeof value === "number" ? value * 1000 : undefined;
9272
9436
  var parseVoiceTelephonyWebhookEvent = (input) => {
9273
9437
  const payload = flattenPayload(input.body);
9274
- const provider = firstString(payload, ["provider", "Provider"]) ?? input.provider;
9275
- const status = firstString(payload, [
9438
+ const provider = firstString2(payload, ["provider", "Provider"]) ?? input.provider;
9439
+ const status = firstString2(payload, [
9276
9440
  "CallStatus",
9277
9441
  "call_status",
9278
9442
  "callStatus",
@@ -9282,7 +9446,7 @@ var parseVoiceTelephonyWebhookEvent = (input) => {
9282
9446
  "event_type",
9283
9447
  "type"
9284
9448
  ]);
9285
- const durationMs = firstNumber(payload, ["durationMs", "duration_ms"]) ?? durationMsFromSeconds(firstNumber(payload, [
9449
+ const durationMs = firstNumber2(payload, ["durationMs", "duration_ms"]) ?? durationMsFromSeconds(firstNumber2(payload, [
9286
9450
  "CallDuration",
9287
9451
  "call_duration",
9288
9452
  "callDuration",
@@ -9290,16 +9454,16 @@ var parseVoiceTelephonyWebhookEvent = (input) => {
9290
9454
  "dial_call_duration",
9291
9455
  "duration"
9292
9456
  ]));
9293
- const sipCode = firstNumber(payload, [
9457
+ const sipCode = firstNumber2(payload, [
9294
9458
  "SipResponseCode",
9295
9459
  "sip_response_code",
9296
9460
  "sipCode",
9297
9461
  "sip_code",
9298
9462
  "hangupCauseCode"
9299
9463
  ]);
9300
- const from = firstString(payload, ["From", "from", "caller_id", "callerId"]);
9301
- const to = firstString(payload, ["To", "to", "called_number", "calledNumber"]);
9302
- const target = firstString(payload, [
9464
+ const from = firstString2(payload, ["From", "from", "caller_id", "callerId"]);
9465
+ const to = firstString2(payload, ["To", "to", "called_number", "calledNumber"]);
9466
+ const target = firstString2(payload, [
9303
9467
  "transferTarget",
9304
9468
  "TransferTarget",
9305
9469
  "target",
@@ -9307,7 +9471,7 @@ var parseVoiceTelephonyWebhookEvent = (input) => {
9307
9471
  "department"
9308
9472
  ]);
9309
9473
  return {
9310
- answeredBy: firstString(payload, [
9474
+ answeredBy: firstString2(payload, [
9311
9475
  "AnsweredBy",
9312
9476
  "answered_by",
9313
9477
  "answeredBy",
@@ -9321,7 +9485,7 @@ var parseVoiceTelephonyWebhookEvent = (input) => {
9321
9485
  ...payload
9322
9486
  },
9323
9487
  provider,
9324
- reason: firstString(payload, [
9488
+ reason: firstString2(payload, [
9325
9489
  "Reason",
9326
9490
  "reason",
9327
9491
  "HangupCause",
@@ -9337,7 +9501,7 @@ var parseVoiceTelephonyWebhookEvent = (input) => {
9337
9501
  var defaultSessionId = (input) => {
9338
9502
  const payload = flattenPayload(input.body);
9339
9503
  const metadataSessionId = input.event.metadata?.sessionId;
9340
- return firstString(input.query, ["sessionId", "session_id"]) ?? firstString(payload, [
9504
+ return firstString2(input.query, ["sessionId", "session_id"]) ?? firstString2(payload, [
9341
9505
  "sessionId",
9342
9506
  "session_id",
9343
9507
  "SessionId",
@@ -9352,7 +9516,7 @@ var defaultSessionId = (input) => {
9352
9516
  };
9353
9517
  var defaultIdempotencyKey = (input) => {
9354
9518
  const payload = flattenPayload(input.body);
9355
- const eventId = firstString(payload, [
9519
+ const eventId = firstString2(payload, [
9356
9520
  "id",
9357
9521
  "event_id",
9358
9522
  "eventId",
package/dist/vue/index.js CHANGED
@@ -4768,6 +4768,63 @@ var stringStat = (stat, key) => {
4768
4768
  };
4769
4769
  var statKey = (stat) => String(stat.id ?? stringStat(stat, "ssrc") ?? numericStat(stat, "ssrc") ?? stringStat(stat, "trackIdentifier") ?? stringStat(stat, "mid") ?? "unknown");
4770
4770
  var secondsToMs = (value) => value === undefined ? undefined : value * 1000;
4771
+ var DEFAULT_TELEPHONY_FORMAT = {
4772
+ channels: 1,
4773
+ container: "raw",
4774
+ encoding: "mulaw",
4775
+ sampleRateHz: 8000
4776
+ };
4777
+ var bytesToBase64 = (audio) => {
4778
+ const bytes = audio instanceof ArrayBuffer ? new Uint8Array(audio) : new Uint8Array(audio.buffer, audio.byteOffset, audio.byteLength);
4779
+ return Buffer.from(bytes).toString("base64");
4780
+ };
4781
+ var base64ToBytes = (value) => new Uint8Array(Buffer.from(value, "base64"));
4782
+ var unknownRecord = (value) => value && typeof value === "object" ? value : {};
4783
+ var firstString = (records, keys) => {
4784
+ for (const record of records) {
4785
+ for (const key of keys) {
4786
+ const value = record[key];
4787
+ if (typeof value === "string" && value.length > 0) {
4788
+ return value;
4789
+ }
4790
+ if (typeof value === "number" && Number.isFinite(value)) {
4791
+ return String(value);
4792
+ }
4793
+ }
4794
+ }
4795
+ return;
4796
+ };
4797
+ var firstNumber = (records, keys) => {
4798
+ for (const record of records) {
4799
+ for (const key of keys) {
4800
+ const value = record[key];
4801
+ if (typeof value === "number" && Number.isFinite(value)) {
4802
+ return value;
4803
+ }
4804
+ if (typeof value === "string") {
4805
+ const parsed = Number(value);
4806
+ if (Number.isFinite(parsed)) {
4807
+ return parsed;
4808
+ }
4809
+ }
4810
+ }
4811
+ }
4812
+ return;
4813
+ };
4814
+ var telephonyDirection = (track) => {
4815
+ const normalized = track?.toLowerCase();
4816
+ if (!normalized) {
4817
+ return "unknown";
4818
+ }
4819
+ if (normalized.includes("inbound") || normalized.includes("caller") || normalized.includes("in")) {
4820
+ return "inbound";
4821
+ }
4822
+ if (normalized.includes("outbound") || normalized.includes("assistant") || normalized.includes("out")) {
4823
+ return "outbound";
4824
+ }
4825
+ return "unknown";
4826
+ };
4827
+ var telephonyFrameKind = (direction) => direction === "outbound" ? "assistant-audio" : "input-audio";
4771
4828
  var normalizeWebRTCStat = (stat) => {
4772
4829
  const sample = {};
4773
4830
  for (const [key, value] of Object.entries(stat)) {
@@ -4777,6 +4834,113 @@ var normalizeWebRTCStat = (stat) => {
4777
4834
  }
4778
4835
  return sample;
4779
4836
  };
4837
+ var parseTelephonyMediaFrame = (input) => {
4838
+ const envelope = input.envelope;
4839
+ const media = unknownRecord(envelope.media);
4840
+ const payload = firstString([media, envelope], ["payload", "audio", "data"]) ?? firstString([unknownRecord(envelope.message)], ["payload"]);
4841
+ if (!payload) {
4842
+ return;
4843
+ }
4844
+ const carrier = input.carrier ?? firstString([envelope], ["provider"]) ?? "telephony";
4845
+ const streamId = firstString([media, envelope], ["streamSid", "stream_id", "streamId", "streamId", "callSid", "call_id"]);
4846
+ const sequenceNumber = firstString([media, envelope], ["sequenceNumber", "sequence_number", "chunk"]);
4847
+ const track = firstString([media, envelope], ["track", "direction"]);
4848
+ const direction = telephonyDirection(track);
4849
+ const timestamp = firstNumber([media, envelope], ["timestamp", "time", "startedAt"]);
4850
+ return {
4851
+ at: timestamp,
4852
+ audio: base64ToBytes(payload),
4853
+ format: input.format ?? DEFAULT_TELEPHONY_FORMAT,
4854
+ id: [
4855
+ carrier,
4856
+ streamId ?? input.sessionId ?? "stream",
4857
+ sequenceNumber ?? timestamp ?? Date.now()
4858
+ ].join(":"),
4859
+ kind: telephonyFrameKind(direction),
4860
+ metadata: {
4861
+ carrier,
4862
+ direction,
4863
+ event: firstString([envelope], ["event", "type"]),
4864
+ sequenceNumber,
4865
+ streamId,
4866
+ track
4867
+ },
4868
+ sessionId: input.sessionId ?? streamId,
4869
+ source: "telephony"
4870
+ };
4871
+ };
4872
+ var serializeTelephonyMediaFrame = (input) => {
4873
+ const carrier = input.carrier ?? input.frame.metadata?.carrier ?? "telephony";
4874
+ const streamId = input.streamId ?? (typeof input.frame.metadata?.streamId === "string" ? input.frame.metadata.streamId : input.frame.sessionId);
4875
+ const sequenceNumber = input.sequenceNumber ?? (typeof input.frame.metadata?.sequenceNumber === "string" || typeof input.frame.metadata?.sequenceNumber === "number" ? input.frame.metadata.sequenceNumber : undefined);
4876
+ const direction = input.frame.kind === "assistant-audio" ? "outbound" : "inbound";
4877
+ const payload = input.frame.audio ? bytesToBase64(input.frame.audio) : "";
4878
+ if (carrier === "twilio") {
4879
+ return {
4880
+ event: "media",
4881
+ sequenceNumber,
4882
+ streamSid: streamId,
4883
+ media: {
4884
+ payload,
4885
+ timestamp: input.frame.at,
4886
+ track: direction
4887
+ }
4888
+ };
4889
+ }
4890
+ if (carrier === "telnyx") {
4891
+ return {
4892
+ event: "media",
4893
+ stream_id: streamId,
4894
+ sequence_number: sequenceNumber,
4895
+ media: {
4896
+ payload,
4897
+ timestamp: input.frame.at,
4898
+ track: direction
4899
+ }
4900
+ };
4901
+ }
4902
+ if (carrier === "plivo") {
4903
+ return {
4904
+ event: "media",
4905
+ streamId,
4906
+ sequenceNumber,
4907
+ media: {
4908
+ payload,
4909
+ timestamp: input.frame.at,
4910
+ track: direction
4911
+ }
4912
+ };
4913
+ }
4914
+ return {
4915
+ event: "media",
4916
+ provider: carrier,
4917
+ sequenceNumber,
4918
+ streamId,
4919
+ media: {
4920
+ payload,
4921
+ timestamp: input.frame.at,
4922
+ track: direction
4923
+ }
4924
+ };
4925
+ };
4926
+ var createTelephonyMediaSerializer = (input) => {
4927
+ const format = input.format ?? DEFAULT_TELEPHONY_FORMAT;
4928
+ return {
4929
+ carrier: input.carrier,
4930
+ format,
4931
+ parse: (envelope) => parseTelephonyMediaFrame({
4932
+ carrier: input.carrier,
4933
+ envelope,
4934
+ format,
4935
+ sessionId: input.sessionId ?? input.streamId
4936
+ }),
4937
+ serialize: (frame) => serializeTelephonyMediaFrame({
4938
+ carrier: input.carrier,
4939
+ frame,
4940
+ streamId: input.streamId
4941
+ })
4942
+ };
4943
+ };
4780
4944
  var buildMediaResamplingPlan = (input) => {
4781
4945
  const required = !formatMatches(input.inputFormat, input.outputFormat);
4782
4946
  return {
@@ -57,6 +57,7 @@ export declare const useVoiceReadinessFailures: (path?: string, options?: VoiceR
57
57
  readonly opsRecovery?: string | undefined;
58
58
  readonly phoneAgentSmoke?: string | undefined;
59
59
  readonly telephonyWebhookSecurity?: string | undefined;
60
+ readonly telephonyMedia?: string | undefined;
60
61
  readonly providerContracts?: string | undefined;
61
62
  readonly providerOrchestration?: string | undefined;
62
63
  readonly providerRoutingContracts?: string | undefined;
@@ -373,6 +374,14 @@ export declare const useVoiceReadinessFailures: (path?: string, options?: VoiceR
373
374
  readonly status: import("..").VoiceProductionReadinessStatus;
374
375
  readonly warned: number;
375
376
  } | undefined;
377
+ readonly telephonyMedia?: {
378
+ readonly audioBytes: number;
379
+ readonly carriers: number;
380
+ readonly failed: number;
381
+ readonly issues: number;
382
+ readonly passed: number;
383
+ readonly status: import("..").VoiceProductionReadinessStatus;
384
+ } | undefined;
376
385
  readonly providerRoutingContracts?: {
377
386
  readonly failed: number;
378
387
  readonly passed: number;
@@ -471,6 +480,7 @@ export declare const useVoiceReadinessFailures: (path?: string, options?: VoiceR
471
480
  readonly opsRecovery?: string | undefined;
472
481
  readonly phoneAgentSmoke?: string | undefined;
473
482
  readonly telephonyWebhookSecurity?: string | undefined;
483
+ readonly telephonyMedia?: string | undefined;
474
484
  readonly providerContracts?: string | undefined;
475
485
  readonly providerOrchestration?: string | undefined;
476
486
  readonly providerRoutingContracts?: string | undefined;
@@ -787,6 +797,14 @@ export declare const useVoiceReadinessFailures: (path?: string, options?: VoiceR
787
797
  readonly status: import("..").VoiceProductionReadinessStatus;
788
798
  readonly warned: number;
789
799
  } | undefined;
800
+ readonly telephonyMedia?: {
801
+ readonly audioBytes: number;
802
+ readonly carriers: number;
803
+ readonly failed: number;
804
+ readonly issues: number;
805
+ readonly passed: number;
806
+ readonly status: import("..").VoiceProductionReadinessStatus;
807
+ } | undefined;
790
808
  readonly providerRoutingContracts?: {
791
809
  readonly failed: number;
792
810
  readonly passed: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.322",
3
+ "version": "0.0.22-beta.324",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",
@@ -246,7 +246,7 @@
246
246
  }
247
247
  },
248
248
  "dependencies": {
249
- "@absolutejs/media": "0.0.1-beta.5"
249
+ "@absolutejs/media": "0.0.1-beta.6"
250
250
  },
251
251
  "devDependencies": {
252
252
  "@absolutejs/absolute": "0.19.0-beta.646",