@absolutejs/voice 0.0.22-beta.486 → 0.0.22-beta.488
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/callerMemory.d.ts +37 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +182 -0
- package/dist/ivrPlan.d.ts +40 -0
- package/package.json +1 -1
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Transcript, VoiceSessionRecord, VoiceTurnRecord } from "./types";
|
|
2
|
+
import type { VoiceAssistantMemoryNamespaceInput } from "./assistantMemory";
|
|
3
|
+
export type VoiceCallerIdentity = {
|
|
4
|
+
email?: string;
|
|
5
|
+
externalId?: string;
|
|
6
|
+
phone?: string;
|
|
7
|
+
};
|
|
8
|
+
export type VoiceCallerMemorySnapshot = {
|
|
9
|
+
facts: Record<string, string>;
|
|
10
|
+
identity: VoiceCallerIdentity;
|
|
11
|
+
lastSessionAt: number;
|
|
12
|
+
openActions: string[];
|
|
13
|
+
summary: string;
|
|
14
|
+
};
|
|
15
|
+
export declare const VOICE_CALLER_MEMORY_KEY = "caller-memory-snapshot";
|
|
16
|
+
export declare const buildVoiceCallerMemoryNamespace: (identity: VoiceCallerIdentity | undefined, prefix?: string) => string;
|
|
17
|
+
export type CreateVoiceCallerMemoryNamespaceOptions<TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord> = {
|
|
18
|
+
identifyCaller: (input: VoiceAssistantMemoryNamespaceInput<TContext, TSession>) => Promise<VoiceCallerIdentity | undefined> | VoiceCallerIdentity | undefined;
|
|
19
|
+
prefix?: string;
|
|
20
|
+
};
|
|
21
|
+
export declare const createVoiceCallerMemoryNamespace: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord>(options: CreateVoiceCallerMemoryNamespaceOptions<TContext, TSession>) => (input: VoiceAssistantMemoryNamespaceInput<TContext, TSession>) => Promise<string>;
|
|
22
|
+
export type VoiceCallerMemoryCompletion = (input: {
|
|
23
|
+
prompt: string;
|
|
24
|
+
systemPrompt?: string;
|
|
25
|
+
}) => Promise<string>;
|
|
26
|
+
export type SummarizeVoiceCallerTranscriptOptions = {
|
|
27
|
+
completion: VoiceCallerMemoryCompletion;
|
|
28
|
+
previousSnapshot?: VoiceCallerMemorySnapshot;
|
|
29
|
+
systemPrompt?: string;
|
|
30
|
+
};
|
|
31
|
+
export type VoiceCallerMemorySummarizerInput = {
|
|
32
|
+
identity: VoiceCallerIdentity;
|
|
33
|
+
options: SummarizeVoiceCallerTranscriptOptions;
|
|
34
|
+
transcripts?: Transcript[];
|
|
35
|
+
turns: VoiceTurnRecord[];
|
|
36
|
+
};
|
|
37
|
+
export declare const summarizeVoiceCallerTranscript: (input: VoiceCallerMemorySummarizerInput) => Promise<VoiceCallerMemorySnapshot>;
|
package/dist/index.d.ts
CHANGED
|
@@ -81,6 +81,10 @@ export { describeVoiceAssistantMode, resolveVoiceAssistantMode, } from "./assist
|
|
|
81
81
|
export type { VoiceAssistantMode, VoiceAssistantModality, VoiceAssistantModeDescriptor, VoiceSemanticVADConfig, } from "./assistantMode";
|
|
82
82
|
export { createPunctuationSemanticTurnDetector, createRegexSemanticTurnDetector, } from "./semanticTurn";
|
|
83
83
|
export { VOICE_WEBHOOK_SIGNATURE_HEADER, VOICE_WEBHOOK_TIMESTAMP_HEADER, extractVoiceWebhookSignatureFromHeaders, signVoiceWebhookBody, verifyVoiceWebhookSignature, } from "./webhookVerification";
|
|
84
|
+
export { createVoiceIVRSession, describeVoiceIVRPlan, evaluateVoiceIVRPlan, } from "./ivrPlan";
|
|
85
|
+
export type { VoiceIVRBranch, VoiceIVRDecision, VoiceIVRInput, VoiceIVRMatch, VoiceIVRPlan, VoiceIVRSession, } from "./ivrPlan";
|
|
86
|
+
export { VOICE_CALLER_MEMORY_KEY, buildVoiceCallerMemoryNamespace, createVoiceCallerMemoryNamespace, summarizeVoiceCallerTranscript, } from "./callerMemory";
|
|
87
|
+
export type { CreateVoiceCallerMemoryNamespaceOptions, SummarizeVoiceCallerTranscriptOptions, VoiceCallerIdentity, VoiceCallerMemoryCompletion, VoiceCallerMemorySnapshot, VoiceCallerMemorySummarizerInput, } from "./callerMemory";
|
|
84
88
|
export { aggregateVoiceTurnLatencySpans, buildOTELSpanId, buildOTELTraceId, buildVoiceOTELPayload, createVoiceOTELHTTPExporter, } from "./otelExporter";
|
|
85
89
|
export type { VoiceOTELAttribute, VoiceOTELExporter, VoiceOTELExporterOptions, VoiceOTELPayload, VoiceOTELResourceSpans, VoiceOTELSpan, VoiceTurnLatencySpanSet, VoiceTurnLatencySpanStage, } from "./otelExporter";
|
|
86
90
|
export type { VoiceWebhookVerificationInput, VoiceWebhookVerificationReason, VoiceWebhookVerificationResult, } from "./webhookVerification";
|
package/dist/index.js
CHANGED
|
@@ -35475,6 +35475,181 @@ var extractVoiceWebhookSignatureFromHeaders = (headers) => {
|
|
|
35475
35475
|
timestamp: get(VOICE_WEBHOOK_TIMESTAMP_HEADER)
|
|
35476
35476
|
};
|
|
35477
35477
|
};
|
|
35478
|
+
// src/ivrPlan.ts
|
|
35479
|
+
var speechMatchesPattern = (pattern, speech) => {
|
|
35480
|
+
const normalized = speech.toLowerCase().trim();
|
|
35481
|
+
if (pattern instanceof RegExp) {
|
|
35482
|
+
return pattern.test(normalized);
|
|
35483
|
+
}
|
|
35484
|
+
const target = pattern.toLowerCase().trim();
|
|
35485
|
+
if (!target) {
|
|
35486
|
+
return false;
|
|
35487
|
+
}
|
|
35488
|
+
return normalized.includes(target);
|
|
35489
|
+
};
|
|
35490
|
+
var digitsMatchPattern = (pattern, input) => {
|
|
35491
|
+
return input === pattern;
|
|
35492
|
+
};
|
|
35493
|
+
var branchMatches = (branch, input) => {
|
|
35494
|
+
const matcher = branch.match;
|
|
35495
|
+
if (matcher.digit && input.digits) {
|
|
35496
|
+
if (input.digits === matcher.digit) {
|
|
35497
|
+
return true;
|
|
35498
|
+
}
|
|
35499
|
+
}
|
|
35500
|
+
if (matcher.digits && input.digits) {
|
|
35501
|
+
if (digitsMatchPattern(matcher.digits, input.digits)) {
|
|
35502
|
+
return true;
|
|
35503
|
+
}
|
|
35504
|
+
}
|
|
35505
|
+
if (matcher.speech && input.speech) {
|
|
35506
|
+
if (speechMatchesPattern(matcher.speech, input.speech)) {
|
|
35507
|
+
return true;
|
|
35508
|
+
}
|
|
35509
|
+
}
|
|
35510
|
+
return false;
|
|
35511
|
+
};
|
|
35512
|
+
var evaluateVoiceIVRPlan = (plan, input) => {
|
|
35513
|
+
if (!input.digits && !input.speech) {
|
|
35514
|
+
return { reason: "timeout" };
|
|
35515
|
+
}
|
|
35516
|
+
for (const branch of plan.branches) {
|
|
35517
|
+
if (branchMatches(branch, input)) {
|
|
35518
|
+
return { branch, reason: "matched" };
|
|
35519
|
+
}
|
|
35520
|
+
}
|
|
35521
|
+
if (plan.fallbackBranchId) {
|
|
35522
|
+
const fallback = plan.branches.find((branch) => branch.id === plan.fallbackBranchId);
|
|
35523
|
+
if (fallback) {
|
|
35524
|
+
return { branch: fallback, reason: "fallback" };
|
|
35525
|
+
}
|
|
35526
|
+
}
|
|
35527
|
+
return { reason: "no-match" };
|
|
35528
|
+
};
|
|
35529
|
+
var createVoiceIVRSession = (plan) => {
|
|
35530
|
+
const maxAttempts = plan.maxAttempts ?? 3;
|
|
35531
|
+
let attempts = 0;
|
|
35532
|
+
return {
|
|
35533
|
+
attempt: () => attempts,
|
|
35534
|
+
decide: (input) => {
|
|
35535
|
+
attempts += 1;
|
|
35536
|
+
return evaluateVoiceIVRPlan(plan, input);
|
|
35537
|
+
},
|
|
35538
|
+
exhausted: () => attempts >= maxAttempts,
|
|
35539
|
+
reset: () => {
|
|
35540
|
+
attempts = 0;
|
|
35541
|
+
}
|
|
35542
|
+
};
|
|
35543
|
+
};
|
|
35544
|
+
var describeVoiceIVRPlan = (plan) => {
|
|
35545
|
+
const lines = [plan.greeting];
|
|
35546
|
+
for (const branch of plan.branches) {
|
|
35547
|
+
const triggers = [];
|
|
35548
|
+
if (branch.match.digit) {
|
|
35549
|
+
triggers.push(`press ${branch.match.digit}`);
|
|
35550
|
+
}
|
|
35551
|
+
if (branch.match.digits) {
|
|
35552
|
+
triggers.push(`press ${branch.match.digits}`);
|
|
35553
|
+
}
|
|
35554
|
+
if (branch.match.speech) {
|
|
35555
|
+
triggers.push(`say "${branch.match.speech instanceof RegExp ? branch.match.speech.source : branch.match.speech}"`);
|
|
35556
|
+
}
|
|
35557
|
+
lines.push(`- ${branch.label}: ${triggers.join(" or ")}`);
|
|
35558
|
+
}
|
|
35559
|
+
return lines.join(`
|
|
35560
|
+
`);
|
|
35561
|
+
};
|
|
35562
|
+
// src/callerMemory.ts
|
|
35563
|
+
var VOICE_CALLER_MEMORY_KEY = "caller-memory-snapshot";
|
|
35564
|
+
var normalizeIdentifier = (value) => value.trim().replace(/[^a-zA-Z0-9+@._-]/g, "-").toLowerCase();
|
|
35565
|
+
var buildVoiceCallerMemoryNamespace = (identity, prefix = "caller") => {
|
|
35566
|
+
const identifier = identity?.externalId ?? identity?.phone ?? identity?.email ?? "anonymous";
|
|
35567
|
+
return `${prefix}:${normalizeIdentifier(identifier)}`;
|
|
35568
|
+
};
|
|
35569
|
+
var createVoiceCallerMemoryNamespace = (options) => async (input) => {
|
|
35570
|
+
const identity = await Promise.resolve(options.identifyCaller(input));
|
|
35571
|
+
return buildVoiceCallerMemoryNamespace(identity, options.prefix);
|
|
35572
|
+
};
|
|
35573
|
+
var DEFAULT_SYSTEM_PROMPT2 = "You write structured caller memory snapshots for a voice agent. " + "Given the latest call transcript (and an optional previous snapshot), " + "merge them into JSON with shape " + '{"summary":"\u2026","facts":{"key":"value"},"openActions":["\u2026"]}. ' + "Keep summary under 240 chars. Facts must be short value strings (name, plan, last_issue). " + "openActions are concrete follow-ups still pending. JSON only.";
|
|
35574
|
+
var buildTranscriptBlock = (turns) => turns.map((turn, index) => {
|
|
35575
|
+
const userText = turn.text.trim();
|
|
35576
|
+
const assistantText = typeof turn.assistantText === "string" ? turn.assistantText.trim() : "";
|
|
35577
|
+
const lines = [`Turn ${index + 1}:`];
|
|
35578
|
+
if (userText) {
|
|
35579
|
+
lines.push(` user: ${userText}`);
|
|
35580
|
+
}
|
|
35581
|
+
if (assistantText) {
|
|
35582
|
+
lines.push(` agent: ${assistantText}`);
|
|
35583
|
+
}
|
|
35584
|
+
return lines.join(`
|
|
35585
|
+
`);
|
|
35586
|
+
}).join(`
|
|
35587
|
+
`);
|
|
35588
|
+
var extractJson2 = (raw) => {
|
|
35589
|
+
const trimmed = raw.trim();
|
|
35590
|
+
if (!trimmed) {
|
|
35591
|
+
throw new Error("Caller-memory summarizer returned empty response");
|
|
35592
|
+
}
|
|
35593
|
+
const fenced = /```(?:json)?\s*([\s\S]*?)```/i.exec(trimmed);
|
|
35594
|
+
const candidate = fenced ? fenced[1].trim() : trimmed;
|
|
35595
|
+
try {
|
|
35596
|
+
return JSON.parse(candidate);
|
|
35597
|
+
} catch {
|
|
35598
|
+
const start = candidate.indexOf("{");
|
|
35599
|
+
const end = candidate.lastIndexOf("}");
|
|
35600
|
+
if (start >= 0 && end > start) {
|
|
35601
|
+
return JSON.parse(candidate.slice(start, end + 1));
|
|
35602
|
+
}
|
|
35603
|
+
throw new Error("Caller-memory response was not valid JSON");
|
|
35604
|
+
}
|
|
35605
|
+
};
|
|
35606
|
+
var coerceFacts = (input) => {
|
|
35607
|
+
if (!input || typeof input !== "object") {
|
|
35608
|
+
return {};
|
|
35609
|
+
}
|
|
35610
|
+
const out = {};
|
|
35611
|
+
for (const [key, value] of Object.entries(input)) {
|
|
35612
|
+
if (typeof value === "string") {
|
|
35613
|
+
out[key] = value;
|
|
35614
|
+
} else if (value !== null && value !== undefined) {
|
|
35615
|
+
out[key] = String(value);
|
|
35616
|
+
}
|
|
35617
|
+
}
|
|
35618
|
+
return out;
|
|
35619
|
+
};
|
|
35620
|
+
var coerceActions = (input) => {
|
|
35621
|
+
if (!Array.isArray(input)) {
|
|
35622
|
+
return [];
|
|
35623
|
+
}
|
|
35624
|
+
return input.map((value) => typeof value === "string" ? value.trim() : "").filter((value) => value.length > 0);
|
|
35625
|
+
};
|
|
35626
|
+
var summarizeVoiceCallerTranscript = async (input) => {
|
|
35627
|
+
const transcriptBlock = buildTranscriptBlock(input.turns);
|
|
35628
|
+
const previousBlock = input.options.previousSnapshot ? `Previous snapshot:
|
|
35629
|
+
${JSON.stringify(input.options.previousSnapshot, null, 2)}
|
|
35630
|
+
|
|
35631
|
+
` : "";
|
|
35632
|
+
const prompt = `${previousBlock}Latest call transcript:
|
|
35633
|
+
${transcriptBlock}
|
|
35634
|
+
|
|
35635
|
+
Return JSON only.`;
|
|
35636
|
+
const raw = await input.options.completion({
|
|
35637
|
+
prompt,
|
|
35638
|
+
systemPrompt: input.options.systemPrompt ?? DEFAULT_SYSTEM_PROMPT2
|
|
35639
|
+
});
|
|
35640
|
+
const parsed = extractJson2(raw);
|
|
35641
|
+
if (!parsed || typeof parsed !== "object") {
|
|
35642
|
+
throw new Error("Caller-memory summarizer returned non-object JSON");
|
|
35643
|
+
}
|
|
35644
|
+
const record = parsed;
|
|
35645
|
+
return {
|
|
35646
|
+
facts: coerceFacts(record.facts),
|
|
35647
|
+
identity: input.identity,
|
|
35648
|
+
lastSessionAt: Date.now(),
|
|
35649
|
+
openActions: coerceActions(record.openActions ?? record.open_actions),
|
|
35650
|
+
summary: typeof record.summary === "string" ? record.summary : ""
|
|
35651
|
+
};
|
|
35652
|
+
};
|
|
35478
35653
|
// src/otelExporter.ts
|
|
35479
35654
|
var SCOPE_NAME = "@absolutejs/voice";
|
|
35480
35655
|
var SPAN_KIND_INTERNAL = 1;
|
|
@@ -46222,6 +46397,7 @@ export {
|
|
|
46222
46397
|
summarizeVoiceHandoffHealth,
|
|
46223
46398
|
summarizeVoiceHandoffDeliveries,
|
|
46224
46399
|
summarizeVoiceCampaigns,
|
|
46400
|
+
summarizeVoiceCallerTranscript,
|
|
46225
46401
|
summarizeVoiceBrowserMedia,
|
|
46226
46402
|
summarizeVoiceBargeIn,
|
|
46227
46403
|
summarizeVoiceAuditTrail,
|
|
@@ -46461,6 +46637,7 @@ export {
|
|
|
46461
46637
|
evaluateVoiceMediaPipelineEvidence,
|
|
46462
46638
|
evaluateVoiceLiveOpsEvidence,
|
|
46463
46639
|
evaluateVoiceLiveOpsControlEvidence,
|
|
46640
|
+
evaluateVoiceIVRPlan,
|
|
46464
46641
|
evaluateVoiceGuardrailPolicy,
|
|
46465
46642
|
evaluateVoiceDataControlEvidence,
|
|
46466
46643
|
evaluateVoiceCompetitiveCoverage,
|
|
@@ -46470,6 +46647,7 @@ export {
|
|
|
46470
46647
|
evaluateVoiceAgentSquadContractEvidence,
|
|
46471
46648
|
encodeTwilioMulawBase64,
|
|
46472
46649
|
encodePcmAsWav,
|
|
46650
|
+
describeVoiceIVRPlan,
|
|
46473
46651
|
describeVoiceAssistantMode,
|
|
46474
46652
|
deliverVoiceTraceEventsToSinks,
|
|
46475
46653
|
deliverVoiceObservabilityExport,
|
|
@@ -46715,6 +46893,7 @@ export {
|
|
|
46715
46893
|
createVoiceIncidentBundleRoutes,
|
|
46716
46894
|
createVoiceInMemoryRealCallProfileRecoveryJobStore,
|
|
46717
46895
|
createVoiceInMemoryMonitorRegistry,
|
|
46896
|
+
createVoiceIVRSession,
|
|
46718
46897
|
createVoiceHubSpotTaskUpdateSink,
|
|
46719
46898
|
createVoiceHubSpotTaskSyncSinks,
|
|
46720
46899
|
createVoiceHubSpotTaskSink,
|
|
@@ -46770,6 +46949,7 @@ export {
|
|
|
46770
46949
|
createVoiceCampaignTelephonyOutcomeHandler,
|
|
46771
46950
|
createVoiceCampaignRoutes,
|
|
46772
46951
|
createVoiceCampaign,
|
|
46952
|
+
createVoiceCallerMemoryNamespace,
|
|
46773
46953
|
createVoiceCallReviewRecorder,
|
|
46774
46954
|
createVoiceCallReviewFromSession,
|
|
46775
46955
|
createVoiceCallReviewFromLiveTelephonyReport,
|
|
@@ -46922,6 +47102,7 @@ export {
|
|
|
46922
47102
|
buildVoiceDataControlReport,
|
|
46923
47103
|
buildVoiceCompetitiveCoverageReport,
|
|
46924
47104
|
buildVoiceCampaignObservabilityReport,
|
|
47105
|
+
buildVoiceCallerMemoryNamespace,
|
|
46925
47106
|
buildVoiceCallDebuggerReport,
|
|
46926
47107
|
buildVoiceBrowserCallProfileReport,
|
|
46927
47108
|
buildVoiceAuditTrailReport,
|
|
@@ -46984,6 +47165,7 @@ export {
|
|
|
46984
47165
|
VOICE_WEBHOOK_TIMESTAMP_HEADER,
|
|
46985
47166
|
VOICE_WEBHOOK_SIGNATURE_HEADER,
|
|
46986
47167
|
VOICE_LIVE_OPS_ACTIONS,
|
|
47168
|
+
VOICE_CALLER_MEMORY_KEY,
|
|
46987
47169
|
TURN_PROFILE_DEFAULTS,
|
|
46988
47170
|
DEFAULT_VOICE_REDACTION_PATTERNS,
|
|
46989
47171
|
DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS,
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export type VoiceIVRMatch = {
|
|
2
|
+
digit?: string;
|
|
3
|
+
digits?: string;
|
|
4
|
+
speech?: string | RegExp;
|
|
5
|
+
};
|
|
6
|
+
export type VoiceIVRBranch = {
|
|
7
|
+
assistantId?: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
id: string;
|
|
10
|
+
label: string;
|
|
11
|
+
match: VoiceIVRMatch;
|
|
12
|
+
metadata?: Record<string, unknown>;
|
|
13
|
+
target?: string;
|
|
14
|
+
};
|
|
15
|
+
export type VoiceIVRPlan = {
|
|
16
|
+
branches: readonly VoiceIVRBranch[];
|
|
17
|
+
fallbackBranchId?: string;
|
|
18
|
+
greeting: string;
|
|
19
|
+
maxAttempts?: number;
|
|
20
|
+
noMatchPrompt?: string;
|
|
21
|
+
timeoutMs?: number;
|
|
22
|
+
timeoutPrompt?: string;
|
|
23
|
+
};
|
|
24
|
+
export type VoiceIVRInput = {
|
|
25
|
+
digits?: string;
|
|
26
|
+
speech?: string;
|
|
27
|
+
};
|
|
28
|
+
export type VoiceIVRDecision = {
|
|
29
|
+
branch?: VoiceIVRBranch;
|
|
30
|
+
reason: "matched" | "no-match" | "fallback" | "timeout";
|
|
31
|
+
};
|
|
32
|
+
export declare const evaluateVoiceIVRPlan: (plan: VoiceIVRPlan, input: VoiceIVRInput) => VoiceIVRDecision;
|
|
33
|
+
export type VoiceIVRSession = {
|
|
34
|
+
attempt: () => number;
|
|
35
|
+
decide: (input: VoiceIVRInput) => VoiceIVRDecision;
|
|
36
|
+
exhausted: () => boolean;
|
|
37
|
+
reset: () => void;
|
|
38
|
+
};
|
|
39
|
+
export declare const createVoiceIVRSession: (plan: VoiceIVRPlan) => VoiceIVRSession;
|
|
40
|
+
export declare const describeVoiceIVRPlan: (plan: VoiceIVRPlan) => string;
|