@absolutejs/voice 0.0.22-beta.496 → 0.0.22-beta.498
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/assistant.d.ts +1 -2
- package/dist/callQuota.d.ts +54 -0
- package/dist/client/costDashboard.d.ts +27 -0
- package/dist/client/liveCallViewer.d.ts +42 -0
- package/dist/client/replayTimeline.d.ts +26 -0
- package/dist/defineVoiceAssistant.d.ts +68 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +605 -37
- package/dist/recordingRedaction.d.ts +18 -0
- package/dist/retention.d.ts +37 -0
- package/dist/routeAuth.d.ts +58 -0
- package/dist/testing/index.js +1 -0
- package/dist/types.d.ts +14 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4916,6 +4916,7 @@ var createVoiceSession = (options) => {
|
|
|
4916
4916
|
ttsSessionPromise = (async () => {
|
|
4917
4917
|
const openedSession = await ttsAdapter.open({
|
|
4918
4918
|
lexicon,
|
|
4919
|
+
prosody: options.prosody,
|
|
4919
4920
|
sessionId: options.id
|
|
4920
4921
|
});
|
|
4921
4922
|
ttsSession = openedSession;
|
|
@@ -35231,6 +35232,44 @@ var createVoiceTranscriptRedactor = (options = {}) => {
|
|
|
35231
35232
|
};
|
|
35232
35233
|
};
|
|
35233
35234
|
var redactVoiceTranscript = (transcript, patterns = DEFAULT_VOICE_REDACTION_PATTERNS) => createVoiceTranscriptRedactor({ patterns })(transcript);
|
|
35235
|
+
// src/recordingRedaction.ts
|
|
35236
|
+
var matchesAnyPattern = (text, patterns) => {
|
|
35237
|
+
for (const pattern of patterns) {
|
|
35238
|
+
pattern.regex.lastIndex = 0;
|
|
35239
|
+
if (pattern.regex.test(text)) {
|
|
35240
|
+
pattern.regex.lastIndex = 0;
|
|
35241
|
+
return pattern;
|
|
35242
|
+
}
|
|
35243
|
+
}
|
|
35244
|
+
return;
|
|
35245
|
+
};
|
|
35246
|
+
var deriveVoiceRecordingRedactionRanges = (input) => {
|
|
35247
|
+
const patterns = input.patterns ?? DEFAULT_VOICE_REDACTION_PATTERNS;
|
|
35248
|
+
const padding = Math.max(0, input.paddingMs ?? 100);
|
|
35249
|
+
const baseEpoch = input.recordingStartedAtEpochMs;
|
|
35250
|
+
const out = [];
|
|
35251
|
+
for (const transcript of input.transcripts) {
|
|
35252
|
+
if (!transcript.isFinal)
|
|
35253
|
+
continue;
|
|
35254
|
+
if (typeof transcript.startedAtMs !== "number")
|
|
35255
|
+
continue;
|
|
35256
|
+
if (typeof transcript.endedAtMs !== "number")
|
|
35257
|
+
continue;
|
|
35258
|
+
const matched = matchesAnyPattern(transcript.text, patterns);
|
|
35259
|
+
if (!matched)
|
|
35260
|
+
continue;
|
|
35261
|
+
const absStart = transcript.startedAtMs;
|
|
35262
|
+
const absEnd = transcript.endedAtMs;
|
|
35263
|
+
const start = typeof baseEpoch === "number" && absStart >= baseEpoch ? absStart - baseEpoch : absStart;
|
|
35264
|
+
const end = typeof baseEpoch === "number" && absEnd >= baseEpoch ? absEnd - baseEpoch : absEnd;
|
|
35265
|
+
out.push({
|
|
35266
|
+
endMs: end + padding,
|
|
35267
|
+
label: matched.label,
|
|
35268
|
+
startMs: Math.max(0, start - padding)
|
|
35269
|
+
});
|
|
35270
|
+
}
|
|
35271
|
+
return out;
|
|
35272
|
+
};
|
|
35234
35273
|
// src/costAccounting.ts
|
|
35235
35274
|
var DEFAULT_VOICE_PRICE_BOOK = {
|
|
35236
35275
|
"anthropic:claude-opus-4-5": {
|
|
@@ -36480,6 +36519,524 @@ var createVoiceApiRequestTool = (options) => {
|
|
|
36480
36519
|
resultToMessage: options.formatResult ?? ((result) => result.ok ? `API request ${options.name} succeeded (${String(result.status)}).` : `API request ${options.name} failed with status ${String(result.status)}.`)
|
|
36481
36520
|
});
|
|
36482
36521
|
};
|
|
36522
|
+
// src/defineVoiceAssistant.ts
|
|
36523
|
+
var DEFAULT_SPEECH_THRESHOLD2 = 0.015;
|
|
36524
|
+
var DEFAULT_SILENCE_MS2 = 700;
|
|
36525
|
+
var DEFAULT_TRANSCRIPT_STABILITY_MS2 = 200;
|
|
36526
|
+
var resolveTurnDetection = (input) => ({
|
|
36527
|
+
profile: input?.profile ?? "balanced",
|
|
36528
|
+
qualityProfile: input?.qualityProfile ?? "general",
|
|
36529
|
+
silenceMs: input?.silenceMs ?? DEFAULT_SILENCE_MS2,
|
|
36530
|
+
speechThreshold: input?.speechThreshold ?? DEFAULT_SPEECH_THRESHOLD2,
|
|
36531
|
+
transcriptStabilityMs: input?.transcriptStabilityMs ?? DEFAULT_TRANSCRIPT_STABILITY_MS2
|
|
36532
|
+
});
|
|
36533
|
+
var resolveReconnect = (input) => ({
|
|
36534
|
+
maxAttempts: input?.maxAttempts ?? 3,
|
|
36535
|
+
strategy: input?.strategy ?? "resume-last-turn",
|
|
36536
|
+
timeout: input?.timeout ?? 30000
|
|
36537
|
+
});
|
|
36538
|
+
var buildAssistantOptions = (def) => ({
|
|
36539
|
+
...def.agent,
|
|
36540
|
+
guardrails: def.guardrails,
|
|
36541
|
+
id: def.id,
|
|
36542
|
+
memory: def.memory,
|
|
36543
|
+
memoryLifecycle: def.memoryLifecycle,
|
|
36544
|
+
ops: def.ops
|
|
36545
|
+
});
|
|
36546
|
+
var defineVoiceAssistant = (definition) => {
|
|
36547
|
+
const assistantOptions = buildAssistantOptions(definition);
|
|
36548
|
+
const assistant = createVoiceAssistant(assistantOptions);
|
|
36549
|
+
return {
|
|
36550
|
+
assistant,
|
|
36551
|
+
definition,
|
|
36552
|
+
id: definition.id,
|
|
36553
|
+
toSessionOptions: (input) => {
|
|
36554
|
+
const route = assistant.route(definition.route ?? {});
|
|
36555
|
+
const observability = definition.observability ?? {};
|
|
36556
|
+
return {
|
|
36557
|
+
amd: definition.amd,
|
|
36558
|
+
assistantMode: definition.assistantMode,
|
|
36559
|
+
audioConditioning: definition.audioConditioning,
|
|
36560
|
+
callSilenceTimeoutMs: definition.callSilenceTimeoutMs,
|
|
36561
|
+
context: input.context,
|
|
36562
|
+
costAccountant: observability.costAccountant,
|
|
36563
|
+
costTelephony: observability.costTelephony,
|
|
36564
|
+
id: input.id,
|
|
36565
|
+
languageStrategy: definition.languageStrategy,
|
|
36566
|
+
lexicon: definition.lexicon,
|
|
36567
|
+
modalities: definition.modalities,
|
|
36568
|
+
phraseHints: definition.phraseHints,
|
|
36569
|
+
prosody: definition.voice.prosody,
|
|
36570
|
+
realtime: definition.voice.realtime,
|
|
36571
|
+
realtimeInputFormat: definition.voice.realtimeInputFormat,
|
|
36572
|
+
reconnect: resolveReconnect(input.reconnect),
|
|
36573
|
+
recording: observability.recording,
|
|
36574
|
+
redact: definition.redact,
|
|
36575
|
+
route,
|
|
36576
|
+
scenarioId: input.scenarioId,
|
|
36577
|
+
semanticTurnDetector: definition.semanticTurnDetector,
|
|
36578
|
+
sessionMetadata: { ...definition.metadata, ...input.sessionMetadata },
|
|
36579
|
+
socket: input.socket,
|
|
36580
|
+
store: input.store,
|
|
36581
|
+
stt: definition.voice.stt,
|
|
36582
|
+
sttFallback: definition.voice.sttFallback,
|
|
36583
|
+
sttLifecycle: input.sttLifecycle ?? "continuous",
|
|
36584
|
+
trace: observability.trace,
|
|
36585
|
+
tts: definition.voice.tts,
|
|
36586
|
+
turnDetection: resolveTurnDetection(definition.turnDetection)
|
|
36587
|
+
};
|
|
36588
|
+
}
|
|
36589
|
+
};
|
|
36590
|
+
};
|
|
36591
|
+
// src/callQuota.ts
|
|
36592
|
+
var monthBucketKey = (epochMs) => {
|
|
36593
|
+
const date = new Date(epochMs);
|
|
36594
|
+
return `${date.getUTCFullYear()}-${String(date.getUTCMonth() + 1).padStart(2, "0")}`;
|
|
36595
|
+
};
|
|
36596
|
+
var createInMemoryVoiceCallQuota = (options) => {
|
|
36597
|
+
const tiers = new Map(options.tiers.map((tier) => [tier.customerId, tier]));
|
|
36598
|
+
const activeCalls = new Map;
|
|
36599
|
+
const monthlyUsage = new Map;
|
|
36600
|
+
const usageFor = (customerId) => {
|
|
36601
|
+
const key = monthBucketKey(Date.now());
|
|
36602
|
+
let bucket = monthlyUsage.get(customerId);
|
|
36603
|
+
if (!bucket) {
|
|
36604
|
+
bucket = new Map;
|
|
36605
|
+
monthlyUsage.set(customerId, bucket);
|
|
36606
|
+
}
|
|
36607
|
+
return { bucket, key };
|
|
36608
|
+
};
|
|
36609
|
+
return {
|
|
36610
|
+
describe: (customerId) => {
|
|
36611
|
+
const tier = tiers.get(customerId);
|
|
36612
|
+
if (!tier)
|
|
36613
|
+
return;
|
|
36614
|
+
const active = activeCalls.get(customerId)?.size ?? 0;
|
|
36615
|
+
const { bucket, key } = usageFor(customerId);
|
|
36616
|
+
return {
|
|
36617
|
+
activeCalls: active,
|
|
36618
|
+
burstAllowance: tier.burstAllowance ?? 0,
|
|
36619
|
+
monthlyMinutesUsed: bucket.get(key) ?? 0,
|
|
36620
|
+
reservedConcurrent: tier.reservedConcurrent,
|
|
36621
|
+
tier
|
|
36622
|
+
};
|
|
36623
|
+
},
|
|
36624
|
+
recordMinutes: ({ customerId, minutes }) => {
|
|
36625
|
+
const { bucket, key } = usageFor(customerId);
|
|
36626
|
+
bucket.set(key, (bucket.get(key) ?? 0) + Math.max(0, minutes));
|
|
36627
|
+
},
|
|
36628
|
+
reserve: ({ callId, customerId }) => {
|
|
36629
|
+
const tier = tiers.get(customerId);
|
|
36630
|
+
if (!tier) {
|
|
36631
|
+
if (options.strict) {
|
|
36632
|
+
return {
|
|
36633
|
+
ok: false,
|
|
36634
|
+
rejection: { customerId, reason: "customer-not-found" }
|
|
36635
|
+
};
|
|
36636
|
+
}
|
|
36637
|
+
return {
|
|
36638
|
+
ok: true,
|
|
36639
|
+
reservation: {
|
|
36640
|
+
callId,
|
|
36641
|
+
customerId,
|
|
36642
|
+
release: () => {},
|
|
36643
|
+
reservedAt: Date.now()
|
|
36644
|
+
}
|
|
36645
|
+
};
|
|
36646
|
+
}
|
|
36647
|
+
const limit = tier.reservedConcurrent + (tier.burstAllowance ?? 0);
|
|
36648
|
+
const set = activeCalls.get(customerId) ?? new Set;
|
|
36649
|
+
if (set.size >= limit) {
|
|
36650
|
+
return {
|
|
36651
|
+
ok: false,
|
|
36652
|
+
rejection: {
|
|
36653
|
+
customerId,
|
|
36654
|
+
reason: "concurrency-exceeded",
|
|
36655
|
+
retryAfterMs: 30000
|
|
36656
|
+
}
|
|
36657
|
+
};
|
|
36658
|
+
}
|
|
36659
|
+
if (typeof tier.monthlyMinutes === "number") {
|
|
36660
|
+
const { bucket, key } = usageFor(customerId);
|
|
36661
|
+
if ((bucket.get(key) ?? 0) >= tier.monthlyMinutes) {
|
|
36662
|
+
return {
|
|
36663
|
+
ok: false,
|
|
36664
|
+
rejection: {
|
|
36665
|
+
customerId,
|
|
36666
|
+
reason: "monthly-minutes-exceeded"
|
|
36667
|
+
}
|
|
36668
|
+
};
|
|
36669
|
+
}
|
|
36670
|
+
}
|
|
36671
|
+
set.add(callId);
|
|
36672
|
+
activeCalls.set(customerId, set);
|
|
36673
|
+
return {
|
|
36674
|
+
ok: true,
|
|
36675
|
+
reservation: {
|
|
36676
|
+
callId,
|
|
36677
|
+
customerId,
|
|
36678
|
+
release: () => {
|
|
36679
|
+
set.delete(callId);
|
|
36680
|
+
if (set.size === 0)
|
|
36681
|
+
activeCalls.delete(customerId);
|
|
36682
|
+
},
|
|
36683
|
+
reservedAt: Date.now()
|
|
36684
|
+
}
|
|
36685
|
+
};
|
|
36686
|
+
}
|
|
36687
|
+
};
|
|
36688
|
+
};
|
|
36689
|
+
// src/routeAuth.ts
|
|
36690
|
+
import { Elysia as Elysia53 } from "elysia";
|
|
36691
|
+
var createVoiceBearerAuthVerifier = (input) => {
|
|
36692
|
+
const headerName = (input.headerName ?? "authorization").toLowerCase();
|
|
36693
|
+
const expected = `Bearer ${input.expectedToken}`;
|
|
36694
|
+
return ({ headers }) => {
|
|
36695
|
+
const value = headers.get(headerName);
|
|
36696
|
+
if (!value) {
|
|
36697
|
+
return { allow: false, reason: "missing-bearer", status: 401 };
|
|
36698
|
+
}
|
|
36699
|
+
if (value !== expected) {
|
|
36700
|
+
return { allow: false, reason: "bearer-mismatch", status: 401 };
|
|
36701
|
+
}
|
|
36702
|
+
return { allow: true };
|
|
36703
|
+
};
|
|
36704
|
+
};
|
|
36705
|
+
var createVoiceHMACAuthVerifier = (input) => {
|
|
36706
|
+
return async ({ body, headers }) => {
|
|
36707
|
+
const { signature, timestamp } = extractVoiceWebhookSignatureFromHeaders(headers);
|
|
36708
|
+
const result = await verifyVoiceWebhookSignature({
|
|
36709
|
+
body: body ?? "",
|
|
36710
|
+
secret: input.secret,
|
|
36711
|
+
signature,
|
|
36712
|
+
timestamp,
|
|
36713
|
+
toleranceMs: input.toleranceMs
|
|
36714
|
+
});
|
|
36715
|
+
if (!result.ok) {
|
|
36716
|
+
return { allow: false, reason: result.reason, status: 401 };
|
|
36717
|
+
}
|
|
36718
|
+
return { allow: true };
|
|
36719
|
+
};
|
|
36720
|
+
};
|
|
36721
|
+
var isBypassed = (bypassPaths, url) => {
|
|
36722
|
+
for (const path of bypassPaths) {
|
|
36723
|
+
if (url.includes(path))
|
|
36724
|
+
return true;
|
|
36725
|
+
}
|
|
36726
|
+
return false;
|
|
36727
|
+
};
|
|
36728
|
+
var createVoiceRouteAuth = (options) => {
|
|
36729
|
+
const bypassPaths = options.bypassPaths ?? [];
|
|
36730
|
+
return new Elysia53({ name: options.name ?? "voice-route-auth" }).onRequest(async ({ request, set }) => {
|
|
36731
|
+
const url = request.url;
|
|
36732
|
+
if (isBypassed(bypassPaths, url))
|
|
36733
|
+
return;
|
|
36734
|
+
const cloned = request.clone();
|
|
36735
|
+
const body = request.method === "GET" || request.method === "HEAD" ? "" : await cloned.text().catch(() => "");
|
|
36736
|
+
const decision = await Promise.resolve(options.verify({
|
|
36737
|
+
body,
|
|
36738
|
+
headers: request.headers,
|
|
36739
|
+
method: request.method,
|
|
36740
|
+
url
|
|
36741
|
+
}));
|
|
36742
|
+
if (!decision.allow) {
|
|
36743
|
+
set.status = decision.status ?? 401;
|
|
36744
|
+
return new Response(JSON.stringify({ error: decision.reason, ok: false }), {
|
|
36745
|
+
headers: { "content-type": "application/json" },
|
|
36746
|
+
status: decision.status ?? 401
|
|
36747
|
+
});
|
|
36748
|
+
}
|
|
36749
|
+
});
|
|
36750
|
+
};
|
|
36751
|
+
// src/client/costDashboard.ts
|
|
36752
|
+
var padTwo = (value) => String(value).padStart(2, "0");
|
|
36753
|
+
var formatBucketKey = (epochMs, bucketBy) => {
|
|
36754
|
+
const date = new Date(epochMs);
|
|
36755
|
+
const y = date.getUTCFullYear();
|
|
36756
|
+
const m = padTwo(date.getUTCMonth() + 1);
|
|
36757
|
+
const d = padTwo(date.getUTCDate());
|
|
36758
|
+
const h = padTwo(date.getUTCHours());
|
|
36759
|
+
if (bucketBy === "month")
|
|
36760
|
+
return `${y}-${m}`;
|
|
36761
|
+
if (bucketBy === "day")
|
|
36762
|
+
return `${y}-${m}-${d}`;
|
|
36763
|
+
return `${y}-${m}-${d}T${h}`;
|
|
36764
|
+
};
|
|
36765
|
+
var isCostBreakdown = (value) => Boolean(value) && typeof value === "object" && typeof value.totalUsd === "number";
|
|
36766
|
+
var emptyBucket = (bucketKey2) => ({
|
|
36767
|
+
bucketKey: bucketKey2,
|
|
36768
|
+
callCount: 0,
|
|
36769
|
+
llmUsd: 0,
|
|
36770
|
+
sttUsd: 0,
|
|
36771
|
+
telephonyMinutes: 0,
|
|
36772
|
+
telephonyUsd: 0,
|
|
36773
|
+
totalUsd: 0,
|
|
36774
|
+
ttsUsd: 0
|
|
36775
|
+
});
|
|
36776
|
+
var accumulate = (bucket, payload) => {
|
|
36777
|
+
bucket.callCount += 1;
|
|
36778
|
+
bucket.llmUsd += payload.llm.usd;
|
|
36779
|
+
bucket.sttUsd += payload.stt.usd;
|
|
36780
|
+
bucket.ttsUsd += payload.tts.usd;
|
|
36781
|
+
bucket.telephonyUsd += payload.telephony.usd;
|
|
36782
|
+
bucket.telephonyMinutes += payload.telephony.minutes;
|
|
36783
|
+
bucket.totalUsd += payload.totalUsd;
|
|
36784
|
+
};
|
|
36785
|
+
var roundCurrency = (bucket) => {
|
|
36786
|
+
bucket.llmUsd = Math.round(bucket.llmUsd * 1e6) / 1e6;
|
|
36787
|
+
bucket.sttUsd = Math.round(bucket.sttUsd * 1e6) / 1e6;
|
|
36788
|
+
bucket.ttsUsd = Math.round(bucket.ttsUsd * 1e6) / 1e6;
|
|
36789
|
+
bucket.telephonyUsd = Math.round(bucket.telephonyUsd * 1e6) / 1e6;
|
|
36790
|
+
bucket.totalUsd = Math.round(bucket.totalUsd * 1e6) / 1e6;
|
|
36791
|
+
};
|
|
36792
|
+
var buildVoiceCostDashboardReport = (options) => {
|
|
36793
|
+
const bucketBy = options.bucketBy ?? "day";
|
|
36794
|
+
const fromMs = options.fromMs ?? Number.NEGATIVE_INFINITY;
|
|
36795
|
+
const toMs = options.toMs ?? Number.POSITIVE_INFINITY;
|
|
36796
|
+
const buckets = new Map;
|
|
36797
|
+
const grandTotal = emptyBucket("total");
|
|
36798
|
+
let minMs = Number.POSITIVE_INFINITY;
|
|
36799
|
+
let maxMs = Number.NEGATIVE_INFINITY;
|
|
36800
|
+
for (const event of options.events) {
|
|
36801
|
+
if (event.type !== "cost.ready")
|
|
36802
|
+
continue;
|
|
36803
|
+
if (event.at < fromMs || event.at > toMs)
|
|
36804
|
+
continue;
|
|
36805
|
+
if (!isCostBreakdown(event.payload))
|
|
36806
|
+
continue;
|
|
36807
|
+
minMs = Math.min(minMs, event.at);
|
|
36808
|
+
maxMs = Math.max(maxMs, event.at);
|
|
36809
|
+
const bucketKey2 = formatBucketKey(event.at, bucketBy);
|
|
36810
|
+
let bucket = buckets.get(bucketKey2);
|
|
36811
|
+
if (!bucket) {
|
|
36812
|
+
bucket = emptyBucket(bucketKey2);
|
|
36813
|
+
buckets.set(bucketKey2, bucket);
|
|
36814
|
+
}
|
|
36815
|
+
accumulate(bucket, event.payload);
|
|
36816
|
+
accumulate(grandTotal, event.payload);
|
|
36817
|
+
}
|
|
36818
|
+
for (const bucket of buckets.values()) {
|
|
36819
|
+
roundCurrency(bucket);
|
|
36820
|
+
}
|
|
36821
|
+
roundCurrency(grandTotal);
|
|
36822
|
+
return {
|
|
36823
|
+
buckets: Array.from(buckets.values()).sort((a, b) => a.bucketKey.localeCompare(b.bucketKey)),
|
|
36824
|
+
generatedAt: Date.now(),
|
|
36825
|
+
grandTotal,
|
|
36826
|
+
windowEndMs: Number.isFinite(maxMs) ? maxMs : 0,
|
|
36827
|
+
windowStartMs: Number.isFinite(minMs) ? minMs : 0
|
|
36828
|
+
};
|
|
36829
|
+
};
|
|
36830
|
+
// src/client/liveCallViewer.ts
|
|
36831
|
+
var EVENT_BUFFER_LIMIT = 200;
|
|
36832
|
+
var createLiveCallViewer = (options) => {
|
|
36833
|
+
const bufferLimit = options.bufferLimit ?? EVENT_BUFFER_LIMIT;
|
|
36834
|
+
const subscribers = new Set;
|
|
36835
|
+
let state = {
|
|
36836
|
+
agentState: "idle",
|
|
36837
|
+
callDurationMs: 0,
|
|
36838
|
+
events: [],
|
|
36839
|
+
isConnected: true,
|
|
36840
|
+
isLiveListening: true,
|
|
36841
|
+
partialTranscript: "",
|
|
36842
|
+
sessionId: options.sessionId
|
|
36843
|
+
};
|
|
36844
|
+
const startedAt = options.startedAt ?? Date.now();
|
|
36845
|
+
const notify = () => {
|
|
36846
|
+
for (const subscriber of subscribers)
|
|
36847
|
+
subscriber();
|
|
36848
|
+
};
|
|
36849
|
+
const update = (next) => {
|
|
36850
|
+
state = { ...state, ...next };
|
|
36851
|
+
state.callDurationMs = Math.max(0, Date.now() - startedAt);
|
|
36852
|
+
state.agentState = deriveVoiceAgentUIState({
|
|
36853
|
+
hasActivePartial: state.partialTranscript.length > 0,
|
|
36854
|
+
isConnected: state.isConnected,
|
|
36855
|
+
isPlaying: false,
|
|
36856
|
+
isRecording: state.isLiveListening,
|
|
36857
|
+
lastAssistantAt: state.lastAssistantAt,
|
|
36858
|
+
lastTranscriptAt: state.lastTranscriptAt
|
|
36859
|
+
});
|
|
36860
|
+
notify();
|
|
36861
|
+
};
|
|
36862
|
+
const pushEvent = (event) => {
|
|
36863
|
+
const next = state.events.concat(event);
|
|
36864
|
+
if (next.length > bufferLimit) {
|
|
36865
|
+
next.splice(0, next.length - bufferLimit);
|
|
36866
|
+
}
|
|
36867
|
+
update({ events: next });
|
|
36868
|
+
};
|
|
36869
|
+
return {
|
|
36870
|
+
applyControl: (control) => {
|
|
36871
|
+
pushEvent({
|
|
36872
|
+
at: Date.now(),
|
|
36873
|
+
detail: control.reason,
|
|
36874
|
+
kind: "lifecycle",
|
|
36875
|
+
title: `control:${control.type}`
|
|
36876
|
+
});
|
|
36877
|
+
},
|
|
36878
|
+
applyEvent: pushEvent,
|
|
36879
|
+
applyMonitorEvent: ({ payload, type }) => {
|
|
36880
|
+
pushEvent({
|
|
36881
|
+
at: Date.now(),
|
|
36882
|
+
detail: JSON.stringify(payload).slice(0, 240),
|
|
36883
|
+
kind: type === "call.lifecycle" ? "lifecycle" : "lifecycle",
|
|
36884
|
+
title: type
|
|
36885
|
+
});
|
|
36886
|
+
},
|
|
36887
|
+
getState: () => state,
|
|
36888
|
+
noteAgentAudio: (at) => {
|
|
36889
|
+
const ts = at ?? Date.now();
|
|
36890
|
+
update({ lastAssistantAt: ts });
|
|
36891
|
+
pushEvent({
|
|
36892
|
+
at: ts,
|
|
36893
|
+
kind: "agent_audio",
|
|
36894
|
+
title: "Agent audio frame"
|
|
36895
|
+
});
|
|
36896
|
+
},
|
|
36897
|
+
notePartial: (text, at) => {
|
|
36898
|
+
update({ partialTranscript: text });
|
|
36899
|
+
if (text) {
|
|
36900
|
+
pushEvent({
|
|
36901
|
+
at: at ?? Date.now(),
|
|
36902
|
+
detail: text,
|
|
36903
|
+
kind: "transcript",
|
|
36904
|
+
title: "Partial"
|
|
36905
|
+
});
|
|
36906
|
+
}
|
|
36907
|
+
},
|
|
36908
|
+
noteTranscript: (text, at) => {
|
|
36909
|
+
const ts = at ?? Date.now();
|
|
36910
|
+
update({ lastTranscriptAt: ts, partialTranscript: "" });
|
|
36911
|
+
pushEvent({
|
|
36912
|
+
at: ts,
|
|
36913
|
+
detail: text,
|
|
36914
|
+
kind: "transcript",
|
|
36915
|
+
title: "Final transcript"
|
|
36916
|
+
});
|
|
36917
|
+
},
|
|
36918
|
+
reset: (sessionId, startedAtOverride) => {
|
|
36919
|
+
state = {
|
|
36920
|
+
agentState: "idle",
|
|
36921
|
+
callDurationMs: 0,
|
|
36922
|
+
events: [],
|
|
36923
|
+
isConnected: true,
|
|
36924
|
+
isLiveListening: true,
|
|
36925
|
+
partialTranscript: "",
|
|
36926
|
+
sessionId
|
|
36927
|
+
};
|
|
36928
|
+
if (typeof startedAtOverride === "number") {}
|
|
36929
|
+
notify();
|
|
36930
|
+
},
|
|
36931
|
+
subscribe: (subscriber) => {
|
|
36932
|
+
subscribers.add(subscriber);
|
|
36933
|
+
return () => subscribers.delete(subscriber);
|
|
36934
|
+
}
|
|
36935
|
+
};
|
|
36936
|
+
};
|
|
36937
|
+
// src/client/replayTimeline.ts
|
|
36938
|
+
var categorize = (entry) => {
|
|
36939
|
+
const event = entry.event.toLowerCase();
|
|
36940
|
+
if (event.startsWith("stt.") || event.includes("user"))
|
|
36941
|
+
return "user";
|
|
36942
|
+
if (event.startsWith("tts.") || event.includes("assistant") || event.includes("agent"))
|
|
36943
|
+
return "agent";
|
|
36944
|
+
if (event.startsWith("tool.") || event.includes("tool"))
|
|
36945
|
+
return "tool";
|
|
36946
|
+
return "lifecycle";
|
|
36947
|
+
};
|
|
36948
|
+
var buildReplayTimelineReport = (input) => {
|
|
36949
|
+
const events = [];
|
|
36950
|
+
let summaryAgentTurns = 0;
|
|
36951
|
+
let summaryUserTurns = 0;
|
|
36952
|
+
let summaryToolCalls = 0;
|
|
36953
|
+
for (const entry of input.artifact.timeline ?? []) {
|
|
36954
|
+
const category = categorize(entry);
|
|
36955
|
+
if (category === "user")
|
|
36956
|
+
summaryUserTurns += 1;
|
|
36957
|
+
if (category === "agent")
|
|
36958
|
+
summaryAgentTurns += 1;
|
|
36959
|
+
if (category === "tool")
|
|
36960
|
+
summaryToolCalls += 1;
|
|
36961
|
+
events.push({
|
|
36962
|
+
at: entry.atMs,
|
|
36963
|
+
category,
|
|
36964
|
+
detail: entry.text ?? entry.reason,
|
|
36965
|
+
durationMs: entry.chunkDurationMs,
|
|
36966
|
+
label: entry.event
|
|
36967
|
+
});
|
|
36968
|
+
}
|
|
36969
|
+
events.sort((a, b) => a.at - b.at);
|
|
36970
|
+
const first = events[0]?.at ?? 0;
|
|
36971
|
+
const last = events.at(-1)?.at ?? first;
|
|
36972
|
+
return {
|
|
36973
|
+
duration: last - first,
|
|
36974
|
+
events,
|
|
36975
|
+
metadata: {
|
|
36976
|
+
artifactId: input.artifact.id ?? "",
|
|
36977
|
+
title: input.artifact.title
|
|
36978
|
+
},
|
|
36979
|
+
startedAt: first,
|
|
36980
|
+
summary: {
|
|
36981
|
+
agentTurns: summaryAgentTurns,
|
|
36982
|
+
toolCalls: summaryToolCalls,
|
|
36983
|
+
userTurns: summaryUserTurns
|
|
36984
|
+
}
|
|
36985
|
+
};
|
|
36986
|
+
};
|
|
36987
|
+
// src/retention.ts
|
|
36988
|
+
var defaultResolveAt = (event) => {
|
|
36989
|
+
if (!event || typeof event !== "object")
|
|
36990
|
+
return;
|
|
36991
|
+
const value = event.at;
|
|
36992
|
+
return typeof value === "number" ? value : undefined;
|
|
36993
|
+
};
|
|
36994
|
+
var purgeVoiceRetentionStore = async (store, options, now = Date.now()) => {
|
|
36995
|
+
const resolveAt = options.resolveAt ?? defaultResolveAt;
|
|
36996
|
+
const cutoff = now - Math.max(0, options.maxAgeMs);
|
|
36997
|
+
const records = await Promise.resolve(store.list());
|
|
36998
|
+
const purgedIds = [];
|
|
36999
|
+
let attempted = 0;
|
|
37000
|
+
let removed = 0;
|
|
37001
|
+
let failed = 0;
|
|
37002
|
+
for (const record of records) {
|
|
37003
|
+
const at = resolveAt(record);
|
|
37004
|
+
if (typeof at !== "number" || at >= cutoff)
|
|
37005
|
+
continue;
|
|
37006
|
+
attempted += 1;
|
|
37007
|
+
try {
|
|
37008
|
+
await Promise.resolve(store.remove(record.id));
|
|
37009
|
+
purgedIds.push(record.id);
|
|
37010
|
+
removed += 1;
|
|
37011
|
+
} catch {
|
|
37012
|
+
failed += 1;
|
|
37013
|
+
}
|
|
37014
|
+
}
|
|
37015
|
+
return { attempted, failed, purgedIds, reason: "expired", removed };
|
|
37016
|
+
};
|
|
37017
|
+
var createVoiceRetentionScheduler = (options) => {
|
|
37018
|
+
const intervalMs = Math.max(60000, options.intervalMs ?? 6 * 60 * 60000);
|
|
37019
|
+
let timer;
|
|
37020
|
+
const run = async () => {
|
|
37021
|
+
const report = await purgeVoiceRetentionStore(options.store, options.policy);
|
|
37022
|
+
options.onReport?.(report);
|
|
37023
|
+
};
|
|
37024
|
+
return {
|
|
37025
|
+
start: () => {
|
|
37026
|
+
if (timer)
|
|
37027
|
+
return;
|
|
37028
|
+
timer = setInterval(() => {
|
|
37029
|
+
run();
|
|
37030
|
+
}, intervalMs);
|
|
37031
|
+
},
|
|
37032
|
+
stop: () => {
|
|
37033
|
+
if (!timer)
|
|
37034
|
+
return;
|
|
37035
|
+
clearInterval(timer);
|
|
37036
|
+
timer = undefined;
|
|
37037
|
+
}
|
|
37038
|
+
};
|
|
37039
|
+
};
|
|
36483
37040
|
// src/vapiAdapter.ts
|
|
36484
37041
|
var VAPI_BUILT_IN_VARIABLES = {
|
|
36485
37042
|
date: () => new Date().toISOString().slice(0, 10),
|
|
@@ -37063,7 +37620,7 @@ var assertVoiceAgentSquadContractEvidence = (reports, input = {}) => {
|
|
|
37063
37620
|
return report;
|
|
37064
37621
|
};
|
|
37065
37622
|
// src/turnLatency.ts
|
|
37066
|
-
import { Elysia as
|
|
37623
|
+
import { Elysia as Elysia54 } from "elysia";
|
|
37067
37624
|
var DEFAULT_WARN_AFTER_MS2 = 1800;
|
|
37068
37625
|
var DEFAULT_FAIL_AFTER_MS2 = 3200;
|
|
37069
37626
|
var escapeHtml50 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
@@ -37223,7 +37780,7 @@ var createVoiceTurnLatencyHTMLHandler = (options) => async () => {
|
|
|
37223
37780
|
var createVoiceTurnLatencyRoutes = (options) => {
|
|
37224
37781
|
const path = options.path ?? "/api/turn-latency";
|
|
37225
37782
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
37226
|
-
const routes = new
|
|
37783
|
+
const routes = new Elysia54({
|
|
37227
37784
|
name: options.name ?? "absolutejs-voice-turn-latency"
|
|
37228
37785
|
}).get(path, createVoiceTurnLatencyJSONHandler(options));
|
|
37229
37786
|
if (htmlPath) {
|
|
@@ -37232,7 +37789,7 @@ var createVoiceTurnLatencyRoutes = (options) => {
|
|
|
37232
37789
|
return routes;
|
|
37233
37790
|
};
|
|
37234
37791
|
// src/liveLatency.ts
|
|
37235
|
-
import { Elysia as
|
|
37792
|
+
import { Elysia as Elysia55 } from "elysia";
|
|
37236
37793
|
var escapeHtml51 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
37237
37794
|
var percentile6 = (values, percentileValue) => {
|
|
37238
37795
|
if (values.length === 0) {
|
|
@@ -37306,7 +37863,7 @@ await traceStore.append({
|
|
|
37306
37863
|
var createVoiceLiveLatencyRoutes = (options) => {
|
|
37307
37864
|
const path = options.path ?? "/api/live-latency";
|
|
37308
37865
|
const htmlPath = options.htmlPath === undefined ? "/live-latency" : options.htmlPath;
|
|
37309
|
-
const routes = new
|
|
37866
|
+
const routes = new Elysia55({
|
|
37310
37867
|
name: options.name ?? "absolutejs-voice-live-latency"
|
|
37311
37868
|
}).get(path, () => summarizeVoiceLiveLatency(options));
|
|
37312
37869
|
if (htmlPath) {
|
|
@@ -37323,7 +37880,7 @@ var createVoiceLiveLatencyRoutes = (options) => {
|
|
|
37323
37880
|
return routes;
|
|
37324
37881
|
};
|
|
37325
37882
|
// src/turnQuality.ts
|
|
37326
|
-
import { Elysia as
|
|
37883
|
+
import { Elysia as Elysia56 } from "elysia";
|
|
37327
37884
|
var DEFAULT_CONFIDENCE_WARN_THRESHOLD = 0.72;
|
|
37328
37885
|
var escapeHtml52 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
37329
37886
|
var getTurnLatencyMs = (turn) => {
|
|
@@ -37429,7 +37986,7 @@ var createVoiceTurnQualityHTMLHandler = (options) => async () => {
|
|
|
37429
37986
|
var createVoiceTurnQualityRoutes = (options) => {
|
|
37430
37987
|
const path = options.path ?? "/api/turn-quality";
|
|
37431
37988
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
37432
|
-
const routes = new
|
|
37989
|
+
const routes = new Elysia56({
|
|
37433
37990
|
name: options.name ?? "absolutejs-voice-turn-quality"
|
|
37434
37991
|
}).get(path, createVoiceTurnQualityJSONHandler(options));
|
|
37435
37992
|
if (htmlPath) {
|
|
@@ -37438,10 +37995,10 @@ var createVoiceTurnQualityRoutes = (options) => {
|
|
|
37438
37995
|
return routes;
|
|
37439
37996
|
};
|
|
37440
37997
|
// src/phoneAgent.ts
|
|
37441
|
-
import { Elysia as
|
|
37998
|
+
import { Elysia as Elysia58 } from "elysia";
|
|
37442
37999
|
|
|
37443
38000
|
// src/phoneAgentProductionSmoke.ts
|
|
37444
|
-
import { Elysia as
|
|
38001
|
+
import { Elysia as Elysia57 } from "elysia";
|
|
37445
38002
|
var defaultRequirements = [
|
|
37446
38003
|
"media-started",
|
|
37447
38004
|
"transcript",
|
|
@@ -37584,7 +38141,7 @@ var createVoicePhoneAgentProductionSmokeHTMLHandler = (options) => async ({
|
|
|
37584
38141
|
var createVoicePhoneAgentProductionSmokeRoutes = (options) => {
|
|
37585
38142
|
const path = options.path ?? "/api/voice/phone/smoke-contract";
|
|
37586
38143
|
const htmlPath = options.htmlPath === undefined ? "/voice/phone/smoke-contract" : options.htmlPath;
|
|
37587
|
-
const routes = new
|
|
38144
|
+
const routes = new Elysia57({
|
|
37588
38145
|
name: options.name ?? "absolutejs-voice-phone-smoke-contract"
|
|
37589
38146
|
}).get(path, createVoicePhoneAgentProductionSmokeJSONHandler(options));
|
|
37590
38147
|
if (htmlPath) {
|
|
@@ -37915,7 +38472,7 @@ var createVoicePhoneAgent = (options) => {
|
|
|
37915
38472
|
setupPath: resolveSetupPath(carrier),
|
|
37916
38473
|
smokePath: resolveSmokePath(carrier)
|
|
37917
38474
|
}));
|
|
37918
|
-
const app = new
|
|
38475
|
+
const app = new Elysia58({
|
|
37919
38476
|
name: options.name ?? "absolutejs-voice-phone-agent"
|
|
37920
38477
|
});
|
|
37921
38478
|
for (const carrier of options.carriers) {
|
|
@@ -39724,7 +40281,7 @@ var createOpenAIVoiceTTS = (options) => {
|
|
|
39724
40281
|
};
|
|
39725
40282
|
};
|
|
39726
40283
|
// src/providerCapabilities.ts
|
|
39727
|
-
import { Elysia as
|
|
40284
|
+
import { Elysia as Elysia59 } from "elysia";
|
|
39728
40285
|
var escapeHtml55 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
39729
40286
|
var fromProviderList = (kind, providers, options) => (providers ?? []).map((provider) => ({
|
|
39730
40287
|
configured: true,
|
|
@@ -39827,7 +40384,7 @@ var createVoiceProviderCapabilityHTMLHandler = (options) => async () => {
|
|
|
39827
40384
|
var createVoiceProviderCapabilityRoutes = (options) => {
|
|
39828
40385
|
const path = options.path ?? "/api/provider-capabilities";
|
|
39829
40386
|
const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
|
|
39830
|
-
const routes = new
|
|
40387
|
+
const routes = new Elysia59({
|
|
39831
40388
|
name: options.name ?? "absolutejs-voice-provider-capabilities"
|
|
39832
40389
|
}).get(path, createVoiceProviderCapabilityJSONHandler(options));
|
|
39833
40390
|
if (htmlPath) {
|
|
@@ -39836,7 +40393,7 @@ var createVoiceProviderCapabilityRoutes = (options) => {
|
|
|
39836
40393
|
return routes;
|
|
39837
40394
|
};
|
|
39838
40395
|
// src/providerOrchestration.ts
|
|
39839
|
-
import { Elysia as
|
|
40396
|
+
import { Elysia as Elysia60 } from "elysia";
|
|
39840
40397
|
var defaultRequirement = {
|
|
39841
40398
|
minProviders: 1,
|
|
39842
40399
|
requireBudgetPolicy: false,
|
|
@@ -40012,7 +40569,7 @@ var createVoiceProviderOrchestrationRoutes = (options) => {
|
|
|
40012
40569
|
const path = options.path ?? "/api/voice/provider-orchestration";
|
|
40013
40570
|
const htmlPath = options.htmlPath === undefined ? "/voice/provider-orchestration" : options.htmlPath;
|
|
40014
40571
|
const markdownPath = options.markdownPath === undefined ? "/voice/provider-orchestration.md" : options.markdownPath;
|
|
40015
|
-
const routes = new
|
|
40572
|
+
const routes = new Elysia60({
|
|
40016
40573
|
name: options.name ?? "absolutejs-voice-provider-orchestration"
|
|
40017
40574
|
}).get(path, () => buildVoiceProviderOrchestrationReport(options));
|
|
40018
40575
|
if (htmlPath) {
|
|
@@ -40185,7 +40742,7 @@ var assertVoiceProviderRoutingContractEvidence = (reports, input = {}) => {
|
|
|
40185
40742
|
return report;
|
|
40186
40743
|
};
|
|
40187
40744
|
// src/voiceMonitoring.ts
|
|
40188
|
-
import { Elysia as
|
|
40745
|
+
import { Elysia as Elysia61 } from "elysia";
|
|
40189
40746
|
var escapeHtml57 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
40190
40747
|
var issueIdForRun = (run) => `voice-monitor:${run.id}:${run.impactedSessions?.[0] ?? "global"}`;
|
|
40191
40748
|
var rollupStatus5 = (runs) => runs.some((run) => run.status === "fail") ? "fail" : runs.some((run) => run.status === "warn") ? "warn" : "pass";
|
|
@@ -40470,7 +41027,7 @@ var createVoiceMonitorRoutes = (options) => {
|
|
|
40470
41027
|
monitors: options.monitors,
|
|
40471
41028
|
now: options.now
|
|
40472
41029
|
});
|
|
40473
|
-
const routes = new
|
|
41030
|
+
const routes = new Elysia61({
|
|
40474
41031
|
name: options.name ?? "absolutejs-voice-monitoring"
|
|
40475
41032
|
}).get(path, report).get(`${path}.md`, async () => {
|
|
40476
41033
|
return new Response(renderVoiceMonitorMarkdown(await report()), {
|
|
@@ -40517,7 +41074,7 @@ var createVoiceMonitorRoutes = (options) => {
|
|
|
40517
41074
|
};
|
|
40518
41075
|
var createVoiceMonitorRunnerRoutes = (options) => {
|
|
40519
41076
|
const path = options.path ?? "/api/voice/monitor-runner";
|
|
40520
|
-
return new
|
|
41077
|
+
return new Elysia61({
|
|
40521
41078
|
name: options.name ?? "absolutejs-voice-monitor-runner"
|
|
40522
41079
|
}).get(path, () => ({
|
|
40523
41080
|
isRunning: options.runner.isRunning()
|
|
@@ -40905,7 +41462,7 @@ var recommendVoiceReadinessProfile = (options) => {
|
|
|
40905
41462
|
};
|
|
40906
41463
|
};
|
|
40907
41464
|
// src/providerStackRecommendations.ts
|
|
40908
|
-
import { Elysia as
|
|
41465
|
+
import { Elysia as Elysia62 } from "elysia";
|
|
40909
41466
|
var escapeHtml58 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
40910
41467
|
var profileProviderPriorities = {
|
|
40911
41468
|
"meeting-recorder": {
|
|
@@ -41267,7 +41824,7 @@ var createVoiceProviderContractMatrixHTMLHandler = (options) => async () => {
|
|
|
41267
41824
|
var createVoiceProviderContractMatrixRoutes = (options) => {
|
|
41268
41825
|
const path = options.path ?? "/api/provider-contracts";
|
|
41269
41826
|
const htmlPath = options.htmlPath ?? "/provider-contracts";
|
|
41270
|
-
const routes = new
|
|
41827
|
+
const routes = new Elysia62({
|
|
41271
41828
|
name: options.name ?? "absolutejs-voice-provider-contract-matrix"
|
|
41272
41829
|
});
|
|
41273
41830
|
const jsonHandler = createVoiceProviderContractMatrixJSONHandler(options.matrix);
|
|
@@ -41385,7 +41942,7 @@ var assertVoiceProviderStackEvidence = (report, input = {}) => {
|
|
|
41385
41942
|
return assertion;
|
|
41386
41943
|
};
|
|
41387
41944
|
// src/opsConsoleRoutes.ts
|
|
41388
|
-
import { Elysia as
|
|
41945
|
+
import { Elysia as Elysia63 } from "elysia";
|
|
41389
41946
|
var DEFAULT_LINKS = [
|
|
41390
41947
|
{
|
|
41391
41948
|
description: "Quality gates for CI, deploy checks, and production readiness.",
|
|
@@ -41502,7 +42059,7 @@ var renderVoiceOpsConsoleHTML = (report, options = {}) => {
|
|
|
41502
42059
|
};
|
|
41503
42060
|
var createVoiceOpsConsoleRoutes = (options) => {
|
|
41504
42061
|
const path = options.path ?? "/ops-console";
|
|
41505
|
-
const routes = new
|
|
42062
|
+
const routes = new Elysia63({
|
|
41506
42063
|
name: options.name ?? "absolutejs-voice-ops-console"
|
|
41507
42064
|
});
|
|
41508
42065
|
const getReport = () => buildVoiceOpsConsoleReport(options);
|
|
@@ -41519,7 +42076,7 @@ var createVoiceOpsConsoleRoutes = (options) => {
|
|
|
41519
42076
|
return routes;
|
|
41520
42077
|
};
|
|
41521
42078
|
// src/incidentBundle.ts
|
|
41522
|
-
import { Elysia as
|
|
42079
|
+
import { Elysia as Elysia64 } from "elysia";
|
|
41523
42080
|
var filterIncidentBundleArtifacts = (artifacts, filter = {}) => artifacts.filter((artifact) => {
|
|
41524
42081
|
if (filter.sessionId && artifact.sessionId !== filter.sessionId) {
|
|
41525
42082
|
return false;
|
|
@@ -41736,7 +42293,7 @@ var buildVoiceIncidentBundle = async (options) => {
|
|
|
41736
42293
|
var createVoiceIncidentBundleRoutes = (options) => {
|
|
41737
42294
|
const path = options.path ?? "/api/voice-incidents/:sessionId";
|
|
41738
42295
|
const markdownPath = options.markdownPath === undefined ? "/voice-incidents/:sessionId/markdown" : options.markdownPath;
|
|
41739
|
-
const routes = new
|
|
42296
|
+
const routes = new Elysia64({
|
|
41740
42297
|
name: options.name ?? "absolutejs-voice-incident-bundle"
|
|
41741
42298
|
});
|
|
41742
42299
|
const getSessionId = (params) => params.sessionId ?? "";
|
|
@@ -41937,7 +42494,7 @@ var summarizeVoiceOpsStatus = async (options) => {
|
|
|
41937
42494
|
};
|
|
41938
42495
|
};
|
|
41939
42496
|
// src/opsStatusRoutes.ts
|
|
41940
|
-
import { Elysia as
|
|
42497
|
+
import { Elysia as Elysia65 } from "elysia";
|
|
41941
42498
|
var escapeHtml60 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
41942
42499
|
var renderVoiceOpsStatusHTML = (report, options = {}) => {
|
|
41943
42500
|
const title = options.title ?? "AbsoluteJS Voice Ops Status";
|
|
@@ -41949,7 +42506,7 @@ var renderVoiceOpsStatusHTML = (report, options = {}) => {
|
|
|
41949
42506
|
};
|
|
41950
42507
|
var createVoiceOpsStatusRoutes = (options) => {
|
|
41951
42508
|
const path = options.path ?? "/api/voice/ops-status";
|
|
41952
|
-
const routes = new
|
|
42509
|
+
const routes = new Elysia65({
|
|
41953
42510
|
name: options.name ?? "absolutejs-voice-ops-status"
|
|
41954
42511
|
});
|
|
41955
42512
|
routes.get(path, async () => summarizeVoiceOpsStatus(options));
|
|
@@ -42382,7 +42939,7 @@ var createVoiceTTSProviderRouter = (options) => {
|
|
|
42382
42939
|
};
|
|
42383
42940
|
};
|
|
42384
42941
|
// src/traceDeliveryRoutes.ts
|
|
42385
|
-
import { Elysia as
|
|
42942
|
+
import { Elysia as Elysia66 } from "elysia";
|
|
42386
42943
|
var escapeHtml61 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
42387
42944
|
var getString20 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
42388
42945
|
var getNumber12 = (value) => {
|
|
@@ -42491,7 +43048,7 @@ var createVoiceTraceDeliveryRoutes = (options) => {
|
|
|
42491
43048
|
const path = options.path ?? "/api/voice-trace-deliveries";
|
|
42492
43049
|
const htmlPath = options.htmlPath === undefined ? "/traces/deliveries" : options.htmlPath;
|
|
42493
43050
|
const workerPath = options.workerPath === undefined ? `${path}/drain` : options.workerPath;
|
|
42494
|
-
const routes = new
|
|
43051
|
+
const routes = new Elysia66({
|
|
42495
43052
|
name: options.name ?? "absolutejs-voice-trace-deliveries"
|
|
42496
43053
|
}).get(path, createVoiceTraceDeliveryJSONHandler(options));
|
|
42497
43054
|
if (htmlPath !== false) {
|
|
@@ -42644,7 +43201,7 @@ var createVoiceMemoryStore = () => {
|
|
|
42644
43201
|
return { get, getOrCreate, list, remove, set };
|
|
42645
43202
|
};
|
|
42646
43203
|
// src/opsWebhook.ts
|
|
42647
|
-
import { Elysia as
|
|
43204
|
+
import { Elysia as Elysia67 } from "elysia";
|
|
42648
43205
|
var toHex7 = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
42649
43206
|
var signVoiceOpsWebhookBody = async (input) => {
|
|
42650
43207
|
const encoder2 = new TextEncoder;
|
|
@@ -42774,7 +43331,7 @@ var verifyVoiceOpsWebhookSignature = async (input) => {
|
|
|
42774
43331
|
};
|
|
42775
43332
|
var createVoiceOpsWebhookReceiverRoutes = (options = {}) => {
|
|
42776
43333
|
const path = options.path ?? "/api/voice-ops/webhook";
|
|
42777
|
-
return new
|
|
43334
|
+
return new Elysia67().post(path, async ({ body, request, set }) => {
|
|
42778
43335
|
const bodyText = typeof body === "string" ? body : JSON.stringify(body);
|
|
42779
43336
|
if (options.signingSecret) {
|
|
42780
43337
|
const verification = await verifyVoiceOpsWebhookSignature({
|
|
@@ -43229,7 +43786,7 @@ var resolveVoiceOpsPreset = (name, overrides = {}) => {
|
|
|
43229
43786
|
};
|
|
43230
43787
|
};
|
|
43231
43788
|
// src/postCallAnalysis.ts
|
|
43232
|
-
import { Elysia as
|
|
43789
|
+
import { Elysia as Elysia68 } from "elysia";
|
|
43233
43790
|
var isStore = (value) => Boolean(value) && typeof value === "object" && value !== null && ("list" in value);
|
|
43234
43791
|
var asArray = async (value) => Array.isArray(value) ? value : isStore(value) ? await value.list() : [];
|
|
43235
43792
|
var getPathValue3 = (source, path) => {
|
|
@@ -43408,7 +43965,7 @@ var resolvePostCallAnalysisReport = async (options, input) => {
|
|
|
43408
43965
|
};
|
|
43409
43966
|
var createVoicePostCallAnalysisRoutes = (options = {}) => {
|
|
43410
43967
|
const path = options.path ?? "/api/voice/post-call-analysis";
|
|
43411
|
-
const routes = new
|
|
43968
|
+
const routes = new Elysia68({
|
|
43412
43969
|
name: options.name ?? "absolutejs-voice-post-call-analysis"
|
|
43413
43970
|
});
|
|
43414
43971
|
routes.get(path, async ({ query }) => {
|
|
@@ -43433,7 +43990,7 @@ var createVoicePostCallAnalysisRoutes = (options = {}) => {
|
|
|
43433
43990
|
return routes;
|
|
43434
43991
|
};
|
|
43435
43992
|
// src/guardrails.ts
|
|
43436
|
-
import { Elysia as
|
|
43993
|
+
import { Elysia as Elysia69 } from "elysia";
|
|
43437
43994
|
var stringifyContent = (value) => typeof value === "string" ? value : JSON.stringify(value) ?? "";
|
|
43438
43995
|
var appliesToStage = (rule, stage) => !rule.stages || rule.stages.length === 0 || rule.stages.includes(stage);
|
|
43439
43996
|
var matchesRule = async (rule, input) => {
|
|
@@ -43735,7 +44292,7 @@ var resolveGuardrailReport = async (options, input) => {
|
|
|
43735
44292
|
};
|
|
43736
44293
|
var createVoiceGuardrailRoutes = (options = {}) => {
|
|
43737
44294
|
const path = options.path ?? "/api/voice/guardrails";
|
|
43738
|
-
const routes = new
|
|
44295
|
+
const routes = new Elysia69({
|
|
43739
44296
|
name: options.name ?? "absolutejs-voice-guardrails"
|
|
43740
44297
|
});
|
|
43741
44298
|
routes.all(path, async ({ request }) => {
|
|
@@ -44514,7 +45071,7 @@ var shapeTelephonyAssistantText = (text, options = {}) => {
|
|
|
44514
45071
|
return ensureTerminalPunctuation(normalizeWhitespace(limitedChars));
|
|
44515
45072
|
};
|
|
44516
45073
|
// src/proofPack.ts
|
|
44517
|
-
import { Elysia as
|
|
45074
|
+
import { Elysia as Elysia70 } from "elysia";
|
|
44518
45075
|
import { mkdir as mkdir5 } from "fs/promises";
|
|
44519
45076
|
import { dirname as dirname3, join as join4 } from "path";
|
|
44520
45077
|
var toGeneratedAt = (value) => value === undefined ? new Date().toISOString() : typeof value === "number" ? new Date(value).toISOString() : value;
|
|
@@ -45100,7 +45657,7 @@ var createVoiceProofPackArtifacts = (input) => [
|
|
|
45100
45657
|
var createVoiceProofPackRoutes = (options) => {
|
|
45101
45658
|
const jsonPath = options.jsonPath ?? "/api/voice/proof-pack";
|
|
45102
45659
|
const markdownPath = options.markdownPath ?? "/voice/proof-pack.md";
|
|
45103
|
-
const app = new
|
|
45660
|
+
const app = new Elysia70({ name: options.name ?? "voice-proof-pack" });
|
|
45104
45661
|
if (jsonPath !== false) {
|
|
45105
45662
|
app.get(jsonPath, async () => new Response(JSON.stringify(await resolveProofPack(options.source), null, 2), {
|
|
45106
45663
|
headers: {
|
|
@@ -46201,7 +46758,7 @@ var buildVoiceMultilingualProofReadinessCheck = (report, options = {}) => {
|
|
|
46201
46758
|
};
|
|
46202
46759
|
};
|
|
46203
46760
|
// src/monitor.ts
|
|
46204
|
-
import { Elysia as
|
|
46761
|
+
import { Elysia as Elysia71 } from "elysia";
|
|
46205
46762
|
var buildAudioFanout = () => {
|
|
46206
46763
|
const handlers = new Set;
|
|
46207
46764
|
return {
|
|
@@ -46490,7 +47047,7 @@ var createVoiceLiveMonitorRoutes = (options) => {
|
|
|
46490
47047
|
transfer: options.controlHandlers?.transfer ?? buildDefaultControlHandler("transfer"),
|
|
46491
47048
|
voicemail: options.controlHandlers?.voicemail ?? buildDefaultControlHandler("voicemail")
|
|
46492
47049
|
};
|
|
46493
|
-
const app = new
|
|
47050
|
+
const app = new Elysia71({ name: "absolutejs-voice-monitor" });
|
|
46494
47051
|
const unsubscribers = new WeakMap;
|
|
46495
47052
|
if (listenPath !== false && listenPath.length > 0) {
|
|
46496
47053
|
app.ws(`/${listenPath.replace(/^\/+/, "")}`, {
|
|
@@ -46888,6 +47445,7 @@ export {
|
|
|
46888
47445
|
recommendVoiceProviderStack,
|
|
46889
47446
|
recommendVoiceProfileSwitch,
|
|
46890
47447
|
readVoiceProofTrendReportFile,
|
|
47448
|
+
purgeVoiceRetentionStore,
|
|
46891
47449
|
pruneVoiceTraceEvents,
|
|
46892
47450
|
pruneVoiceIncidentBundleArtifacts,
|
|
46893
47451
|
parseVoiceTelephonyWebhookEvent,
|
|
@@ -46968,6 +47526,7 @@ export {
|
|
|
46968
47526
|
describeVoiceIVRPlan,
|
|
46969
47527
|
describeVoiceAssistantMode,
|
|
46970
47528
|
describeVoiceAgentUIState,
|
|
47529
|
+
deriveVoiceRecordingRedactionRanges,
|
|
46971
47530
|
deriveVoiceAgentUIState,
|
|
46972
47531
|
deliverVoiceTraceEventsToSinks,
|
|
46973
47532
|
deliverVoiceObservabilityExport,
|
|
@@ -46977,6 +47536,7 @@ export {
|
|
|
46977
47536
|
deliverVoiceHandoffDelivery,
|
|
46978
47537
|
deliverVoiceHandoff,
|
|
46979
47538
|
deliverVoiceAuditEventsToSinks,
|
|
47539
|
+
defineVoiceAssistant,
|
|
46980
47540
|
decodeTwilioMulawBase64,
|
|
46981
47541
|
deadLetterVoiceOpsTask,
|
|
46982
47542
|
createVoiceZeroRetentionPolicy,
|
|
@@ -47076,7 +47636,9 @@ export {
|
|
|
47076
47636
|
createVoiceS3RecordingStore,
|
|
47077
47637
|
createVoiceS3DeliverySink,
|
|
47078
47638
|
createVoiceRoutingDecisionSummary,
|
|
47639
|
+
createVoiceRouteAuth,
|
|
47079
47640
|
createVoiceReviewSavedEvent,
|
|
47641
|
+
createVoiceRetentionScheduler,
|
|
47080
47642
|
createVoiceResilienceRoutes,
|
|
47081
47643
|
createVoiceRedisTelnyxWebhookEventStore,
|
|
47082
47644
|
createVoiceRedisTelephonyWebhookIdempotencyStore,
|
|
@@ -47225,6 +47787,7 @@ export {
|
|
|
47225
47787
|
createVoiceHandoffDeliveryWorkerLoop,
|
|
47226
47788
|
createVoiceHandoffDeliveryWorker,
|
|
47227
47789
|
createVoiceHandoffDeliveryRecord,
|
|
47790
|
+
createVoiceHMACAuthVerifier,
|
|
47228
47791
|
createVoiceGuardrailRuntime,
|
|
47229
47792
|
createVoiceGuardrailRoutes,
|
|
47230
47793
|
createVoiceGuardrailPolicy,
|
|
@@ -47279,6 +47842,7 @@ export {
|
|
|
47279
47842
|
createVoiceCRMActivitySink,
|
|
47280
47843
|
createVoiceBrowserMediaRoutes,
|
|
47281
47844
|
createVoiceBrowserCallProfileRoutes,
|
|
47845
|
+
createVoiceBearerAuthVerifier,
|
|
47282
47846
|
createVoiceBargeInRoutes,
|
|
47283
47847
|
createVoiceBackchannelDriver,
|
|
47284
47848
|
createVoiceAuditTrailRoutes,
|
|
@@ -47329,7 +47893,9 @@ export {
|
|
|
47329
47893
|
createMemoryVoiceTelnyxWebhookEventStore,
|
|
47330
47894
|
createMemoryVoiceTelephonyWebhookIdempotencyStore,
|
|
47331
47895
|
createMemoryVoicePlivoWebhookNonceStore,
|
|
47896
|
+
createLiveCallViewer,
|
|
47332
47897
|
createJSONVoiceAssistantModel,
|
|
47898
|
+
createInMemoryVoiceCallQuota,
|
|
47333
47899
|
createInMemoryDNCList,
|
|
47334
47900
|
createId,
|
|
47335
47901
|
createGeminiVoiceAssistantModel,
|
|
@@ -47423,6 +47989,7 @@ export {
|
|
|
47423
47989
|
buildVoiceDeliveryRuntimeReport,
|
|
47424
47990
|
buildVoiceDataRetentionPlan,
|
|
47425
47991
|
buildVoiceDataControlReport,
|
|
47992
|
+
buildVoiceCostDashboardReport,
|
|
47426
47993
|
buildVoiceCompetitiveCoverageReport,
|
|
47427
47994
|
buildVoiceCampaignObservabilityReport,
|
|
47428
47995
|
buildVoiceCallerMemoryNamespace,
|
|
@@ -47431,6 +47998,7 @@ export {
|
|
|
47431
47998
|
buildVoiceAuditTrailReport,
|
|
47432
47999
|
buildVoiceAuditExport,
|
|
47433
48000
|
buildVoiceAuditDeliveryReport,
|
|
48001
|
+
buildReplayTimelineReport,
|
|
47434
48002
|
buildOTELTraceId,
|
|
47435
48003
|
buildOTELSpanId,
|
|
47436
48004
|
buildEmptyVoiceProofTrendReport,
|