@absolutejs/voice 0.0.22-beta.521 → 0.0.22-beta.523
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +6 -0
- package/dist/index.js +183 -0
- package/dist/mcpToolset.d.ts +58 -0
- package/dist/variableAnalytics.d.ts +47 -0
- package/dist/zeroDataRetention.d.ts +41 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -71,6 +71,8 @@ export { createVoiceSessionListRoutes, createVoiceSessionReplayHTMLHandler, crea
|
|
|
71
71
|
export { createVoiceAgent, createVoiceAgentSquad, createVoiceAgentTool, } from "./agent";
|
|
72
72
|
export { createPersonaVoiceCaller, createScriptedVoiceCaller, renderVoiceSimulationTranscript, runVoiceConversationSimulation, } from "./conversationSimulator";
|
|
73
73
|
export type { RunVoiceConversationSimulationInput, VoiceConversationSimulationEndedReason, VoiceConversationSimulationResult, VoicePersonaCallerCompletion, VoiceScriptedCallerStep, VoiceSimulatedSpeaker, VoiceSimulatedTurn, VoiceSimulatorCaller, VoiceSimulatorCallerModel, VoiceSimulatorCallerReply, } from "./conversationSimulator";
|
|
74
|
+
export { createVoiceMCPToolset } from "./mcpToolset";
|
|
75
|
+
export type { CreateVoiceMCPToolsetOptions, MCPClientLike, MCPToolCallResult, MCPToolContentBlock, MCPToolDefinition, VoiceMCPToolResult, } from "./mcpToolset";
|
|
74
76
|
export { createAIVoiceModel } from "./aiVoiceModel";
|
|
75
77
|
export type { CreateAIVoiceModelOptions } from "./aiVoiceModel";
|
|
76
78
|
export { createVoiceAIJudgeCompletion, createVoiceLLMJudge, } from "./llmJudge";
|
|
@@ -79,6 +81,10 @@ export { DEFAULT_VOICE_REDACTION_PATTERNS, createVoiceTranscriptRedactor, redact
|
|
|
79
81
|
export type { CreateVoiceTranscriptRedactorOptions, VoiceRedactionPattern, VoiceTranscriptRedactor, } from "./redaction";
|
|
80
82
|
export { deriveVoiceRecordingRedactionRanges, redactVoiceRecording, } from "./recordingRedaction";
|
|
81
83
|
export type { DeriveVoiceRecordingRedactionRangesInput, RedactVoiceRecordingInput, RedactVoiceRecordingResult, VoiceRecordingRedactionRange, } from "./recordingRedaction";
|
|
84
|
+
export { buildVoiceVariableAnalytics } from "./variableAnalytics";
|
|
85
|
+
export type { BuildVoiceVariableAnalyticsInput, VoiceAnalyticsCall, VoiceAnalyticsVariableValue, VoiceVariableAnalyticsReport, VoiceVariableBreakdown, VoiceVariableValueStats, } from "./variableAnalytics";
|
|
86
|
+
export { VOICE_ZERO_DATA_RETENTION_REDACTION_MARKER, createVoiceZeroDataRetentionPolicy, isVoiceZeroDataRetentionActive, scrubVoiceTraceForZeroDataRetention, scrubVoiceTurnForZeroDataRetention, shouldRetainVoiceRecording, shouldRetainVoiceTranscript, } from "./zeroDataRetention";
|
|
87
|
+
export type { CreateVoiceZeroDataRetentionPolicyOptions, VoiceZeroDataRetentionMode, VoiceZeroDataRetentionPolicy, VoiceZeroDataRetentionRetainFlags, } from "./zeroDataRetention";
|
|
82
88
|
export { DEFAULT_VOICE_PRICE_BOOK, createVoiceCostAccountant, } from "./costAccounting";
|
|
83
89
|
export type { CreateVoiceCostAccountantOptions, VoiceCostAccountant, VoiceCostBreakdown, VoiceCostLLMRecord, VoiceCostSTTRecord, VoiceCostTTSRecord, VoiceCostTelephonyRecord, VoicePriceBook, VoiceProviderRates, } from "./costAccounting";
|
|
84
90
|
export { describeVoiceAssistantMode, resolveVoiceAssistantMode, } from "./assistantMode";
|
package/dist/index.js
CHANGED
|
@@ -35415,6 +35415,52 @@ Respond with only your spoken line. When your goal is met or you want to hang up
|
|
|
35415
35415
|
persona: options.persona
|
|
35416
35416
|
};
|
|
35417
35417
|
};
|
|
35418
|
+
// src/mcpToolset.ts
|
|
35419
|
+
var flattenContent = (result) => {
|
|
35420
|
+
const blocks = result.content ?? [];
|
|
35421
|
+
const text = blocks.filter((block) => block.type === "text" && typeof block.text === "string").map((block) => block.text).join(`
|
|
35422
|
+
`).trim();
|
|
35423
|
+
if (text.length > 0)
|
|
35424
|
+
return text;
|
|
35425
|
+
if (result.structuredContent !== undefined) {
|
|
35426
|
+
return JSON.stringify(result.structuredContent);
|
|
35427
|
+
}
|
|
35428
|
+
return "";
|
|
35429
|
+
};
|
|
35430
|
+
var createVoiceMCPToolset = async (options) => {
|
|
35431
|
+
const prefix = options.namePrefix ?? "";
|
|
35432
|
+
const allowed = options.allowedTools ? new Set(options.allowedTools) : undefined;
|
|
35433
|
+
const blocked = options.blockedTools ? new Set(options.blockedTools) : undefined;
|
|
35434
|
+
const listed = await Promise.resolve(options.client.listTools());
|
|
35435
|
+
const tools = [];
|
|
35436
|
+
for (const definition of listed.tools) {
|
|
35437
|
+
if (allowed && !allowed.has(definition.name))
|
|
35438
|
+
continue;
|
|
35439
|
+
if (blocked && blocked.has(definition.name))
|
|
35440
|
+
continue;
|
|
35441
|
+
const exposedName = `${prefix}${definition.name}`;
|
|
35442
|
+
tools.push(createVoiceAgentTool({
|
|
35443
|
+
...definition.description !== undefined ? { description: definition.description } : {},
|
|
35444
|
+
execute: async ({ args }) => {
|
|
35445
|
+
const raw = await Promise.resolve(options.client.callTool({
|
|
35446
|
+
arguments: args,
|
|
35447
|
+
name: definition.name
|
|
35448
|
+
}));
|
|
35449
|
+
const result = {
|
|
35450
|
+
isError: raw.isError === true,
|
|
35451
|
+
raw,
|
|
35452
|
+
text: flattenContent(raw),
|
|
35453
|
+
...raw.structuredContent !== undefined ? { structuredContent: raw.structuredContent } : {}
|
|
35454
|
+
};
|
|
35455
|
+
return result;
|
|
35456
|
+
},
|
|
35457
|
+
name: exposedName,
|
|
35458
|
+
...definition.inputSchema !== undefined ? { parameters: definition.inputSchema } : {},
|
|
35459
|
+
resultToMessage: options.resultToMessage ?? ((result) => result.isError ? `Tool error: ${result.text || "unknown error"}` : result.text || "(no output)")
|
|
35460
|
+
}));
|
|
35461
|
+
}
|
|
35462
|
+
return tools;
|
|
35463
|
+
};
|
|
35418
35464
|
// src/aiVoiceModel.ts
|
|
35419
35465
|
var toProviderMessages = (messages) => {
|
|
35420
35466
|
const out = [];
|
|
@@ -35748,6 +35794,134 @@ var redactVoiceRecording = (input) => {
|
|
|
35748
35794
|
redactedCount: ranges.length
|
|
35749
35795
|
};
|
|
35750
35796
|
};
|
|
35797
|
+
// src/variableAnalytics.ts
|
|
35798
|
+
var stringifyValue = (value) => {
|
|
35799
|
+
if (value === null || value === undefined)
|
|
35800
|
+
return "(none)";
|
|
35801
|
+
return String(value);
|
|
35802
|
+
};
|
|
35803
|
+
var mean = (values) => values.length === 0 ? null : values.reduce((sum, value) => sum + value, 0) / values.length;
|
|
35804
|
+
var successRateFor = (calls, successOutcomes) => {
|
|
35805
|
+
const flagged = calls.filter((call) => call.success !== undefined || call.outcome !== undefined);
|
|
35806
|
+
if (flagged.length === 0)
|
|
35807
|
+
return null;
|
|
35808
|
+
const successes = flagged.filter((call) => call.success !== undefined ? call.success : call.outcome !== undefined && successOutcomes.has(call.outcome.toLowerCase())).length;
|
|
35809
|
+
return successes / flagged.length;
|
|
35810
|
+
};
|
|
35811
|
+
var buildVoiceVariableAnalytics = (input) => {
|
|
35812
|
+
const successOutcomes = new Set((input.successOutcomes ?? ["won", "resolved", "qualified", "completed", "booked"]).map((outcome) => outcome.toLowerCase()));
|
|
35813
|
+
const totalCalls = input.calls.length;
|
|
35814
|
+
const overall = {
|
|
35815
|
+
avgCostUsd: mean(input.calls.map((call) => call.costUsd).filter((cost) => typeof cost === "number")),
|
|
35816
|
+
avgDurationSeconds: mean(input.calls.map((call) => call.durationSeconds).filter((duration) => typeof duration === "number")),
|
|
35817
|
+
successRate: successRateFor(input.calls, successOutcomes)
|
|
35818
|
+
};
|
|
35819
|
+
const byVariable = {};
|
|
35820
|
+
for (const variable of input.variables) {
|
|
35821
|
+
const groups = new Map;
|
|
35822
|
+
let missingCount = 0;
|
|
35823
|
+
for (const call of input.calls) {
|
|
35824
|
+
const raw = call.variables[variable];
|
|
35825
|
+
if (raw === undefined || raw === null) {
|
|
35826
|
+
missingCount += 1;
|
|
35827
|
+
continue;
|
|
35828
|
+
}
|
|
35829
|
+
const key = stringifyValue(raw);
|
|
35830
|
+
const bucket = groups.get(key) ?? [];
|
|
35831
|
+
bucket.push(call);
|
|
35832
|
+
groups.set(key, bucket);
|
|
35833
|
+
}
|
|
35834
|
+
let values = [];
|
|
35835
|
+
for (const [value, calls] of groups) {
|
|
35836
|
+
const outcomes = {};
|
|
35837
|
+
for (const call of calls) {
|
|
35838
|
+
if (call.outcome) {
|
|
35839
|
+
outcomes[call.outcome] = (outcomes[call.outcome] ?? 0) + 1;
|
|
35840
|
+
}
|
|
35841
|
+
}
|
|
35842
|
+
values.push({
|
|
35843
|
+
avgCostUsd: mean(calls.map((call) => call.costUsd).filter((cost) => typeof cost === "number")),
|
|
35844
|
+
avgDurationSeconds: mean(calls.map((call) => call.durationSeconds).filter((d) => typeof d === "number")),
|
|
35845
|
+
count: calls.length,
|
|
35846
|
+
outcomes,
|
|
35847
|
+
share: totalCalls === 0 ? 0 : calls.length / totalCalls,
|
|
35848
|
+
successRate: successRateFor(calls, successOutcomes),
|
|
35849
|
+
value
|
|
35850
|
+
});
|
|
35851
|
+
}
|
|
35852
|
+
values.sort((left, right) => right.count - left.count);
|
|
35853
|
+
if (input.topValuesPerVariable !== undefined) {
|
|
35854
|
+
values = values.slice(0, input.topValuesPerVariable);
|
|
35855
|
+
}
|
|
35856
|
+
byVariable[variable] = {
|
|
35857
|
+
distinctValues: groups.size,
|
|
35858
|
+
missingCount,
|
|
35859
|
+
values,
|
|
35860
|
+
variable
|
|
35861
|
+
};
|
|
35862
|
+
}
|
|
35863
|
+
return { byVariable, overall, totalCalls };
|
|
35864
|
+
};
|
|
35865
|
+
// src/zeroDataRetention.ts
|
|
35866
|
+
var RETAIN_ALL = {
|
|
35867
|
+
assistantText: true,
|
|
35868
|
+
metadata: true,
|
|
35869
|
+
recordings: true,
|
|
35870
|
+
traceText: true,
|
|
35871
|
+
transcriptText: true
|
|
35872
|
+
};
|
|
35873
|
+
var RETAIN_NONE = {
|
|
35874
|
+
assistantText: false,
|
|
35875
|
+
metadata: false,
|
|
35876
|
+
recordings: false,
|
|
35877
|
+
traceText: false,
|
|
35878
|
+
transcriptText: false
|
|
35879
|
+
};
|
|
35880
|
+
var REDACTED = "[redacted:zdr]";
|
|
35881
|
+
var createVoiceZeroDataRetentionPolicy = (options = {}) => {
|
|
35882
|
+
const mode = options.mode ?? "off";
|
|
35883
|
+
const base = mode === "strict" ? RETAIN_NONE : mode === "off" ? RETAIN_ALL : RETAIN_ALL;
|
|
35884
|
+
return {
|
|
35885
|
+
mode,
|
|
35886
|
+
retain: { ...base, ...options.retain ?? {} }
|
|
35887
|
+
};
|
|
35888
|
+
};
|
|
35889
|
+
var isVoiceZeroDataRetentionActive = (policy) => policy.mode !== "off" && Object.values(policy.retain).some((retain) => retain === false);
|
|
35890
|
+
var shouldRetainVoiceRecording = (policy) => policy.retain.recordings;
|
|
35891
|
+
var shouldRetainVoiceTranscript = (policy) => policy.retain.transcriptText;
|
|
35892
|
+
var scrubVoiceTurnForZeroDataRetention = (turn, policy) => {
|
|
35893
|
+
if (!isVoiceZeroDataRetentionActive(policy))
|
|
35894
|
+
return turn;
|
|
35895
|
+
const scrubbed = {
|
|
35896
|
+
...turn,
|
|
35897
|
+
text: policy.retain.transcriptText ? turn.text : REDACTED,
|
|
35898
|
+
transcripts: policy.retain.transcriptText ? turn.transcripts : turn.transcripts.map((transcript) => ({
|
|
35899
|
+
...transcript,
|
|
35900
|
+
text: REDACTED
|
|
35901
|
+
}))
|
|
35902
|
+
};
|
|
35903
|
+
if (!policy.retain.assistantText && scrubbed.assistantText !== undefined) {
|
|
35904
|
+
scrubbed.assistantText = REDACTED;
|
|
35905
|
+
}
|
|
35906
|
+
if (!policy.retain.metadata) {
|
|
35907
|
+
delete scrubbed.attachments;
|
|
35908
|
+
}
|
|
35909
|
+
return scrubbed;
|
|
35910
|
+
};
|
|
35911
|
+
var scrubVoiceTraceForZeroDataRetention = (event, policy) => {
|
|
35912
|
+
if (!isVoiceZeroDataRetentionActive(policy) || policy.retain.traceText) {
|
|
35913
|
+
return event;
|
|
35914
|
+
}
|
|
35915
|
+
const payload = event.payload;
|
|
35916
|
+
if (!payload || typeof payload !== "object")
|
|
35917
|
+
return event;
|
|
35918
|
+
const scrubbedPayload = {};
|
|
35919
|
+
for (const [key, value] of Object.entries(payload)) {
|
|
35920
|
+
scrubbedPayload[key] = typeof value === "string" ? REDACTED : value;
|
|
35921
|
+
}
|
|
35922
|
+
return { ...event, payload: scrubbedPayload };
|
|
35923
|
+
};
|
|
35924
|
+
var VOICE_ZERO_DATA_RETENTION_REDACTION_MARKER = REDACTED;
|
|
35751
35925
|
// src/costAccounting.ts
|
|
35752
35926
|
var DEFAULT_VOICE_PRICE_BOOK = {
|
|
35753
35927
|
"anthropic:claude-opus-4-5": {
|
|
@@ -51867,8 +52041,12 @@ export {
|
|
|
51867
52041
|
signVoiceTwilioWebhook,
|
|
51868
52042
|
signVoicePlivoWebhook,
|
|
51869
52043
|
shouldRetryCampaignAttempt,
|
|
52044
|
+
shouldRetainVoiceTranscript,
|
|
52045
|
+
shouldRetainVoiceRecording,
|
|
51870
52046
|
shapeTelephonyAssistantText,
|
|
51871
52047
|
selectVoiceTraceEventsForPrune,
|
|
52048
|
+
scrubVoiceTurnForZeroDataRetention,
|
|
52049
|
+
scrubVoiceTraceForZeroDataRetention,
|
|
51872
52050
|
scoreVoiceNoShowRisk,
|
|
51873
52051
|
saveVoiceIncidentBundleArtifact,
|
|
51874
52052
|
runVoiceToolContractSuite,
|
|
@@ -52070,6 +52248,7 @@ export {
|
|
|
52070
52248
|
listVoiceProviderDecisionTraces,
|
|
52071
52249
|
listVoiceOpsTasks,
|
|
52072
52250
|
isWithinCampaignWindow,
|
|
52251
|
+
isVoiceZeroDataRetentionActive,
|
|
52073
52252
|
isVoiceOpsTaskOverdue,
|
|
52074
52253
|
isPhoneOnDNC,
|
|
52075
52254
|
interleaveStereoPcm,
|
|
@@ -52156,6 +52335,7 @@ export {
|
|
|
52156
52335
|
decodeTwilioMulawBase64,
|
|
52157
52336
|
deadLetterVoiceOpsTask,
|
|
52158
52337
|
createVoiceZeroRetentionPolicy,
|
|
52338
|
+
createVoiceZeroDataRetentionPolicy,
|
|
52159
52339
|
createVoiceZendeskTicketUpdateSink,
|
|
52160
52340
|
createVoiceZendeskTicketSyncSinks,
|
|
52161
52341
|
createVoiceZendeskTicketSink,
|
|
@@ -52389,6 +52569,7 @@ export {
|
|
|
52389
52569
|
createVoiceMemoryAuditEventStore,
|
|
52390
52570
|
createVoiceMemoryAssistantMemoryStore,
|
|
52391
52571
|
createVoiceMediaPipelineRoutes,
|
|
52572
|
+
createVoiceMCPToolset,
|
|
52392
52573
|
createVoiceLiveOpsRoutes,
|
|
52393
52574
|
createVoiceLiveOpsController,
|
|
52394
52575
|
createVoiceLiveMonitorRoutes,
|
|
@@ -52564,6 +52745,7 @@ export {
|
|
|
52564
52745
|
collectVoiceDTMFInput,
|
|
52565
52746
|
collectVoiceCampaignTemplateVariables,
|
|
52566
52747
|
claimVoiceOpsTask,
|
|
52748
|
+
buildVoiceVariableAnalytics,
|
|
52567
52749
|
buildVoiceTraceReplay,
|
|
52568
52750
|
buildVoiceTraceDeliveryReport,
|
|
52569
52751
|
buildVoiceTelephonyWebhookSecurityReport,
|
|
@@ -52713,6 +52895,7 @@ export {
|
|
|
52713
52895
|
appendVoiceIOProviderRouterTraceEvent,
|
|
52714
52896
|
aggregateVoiceTurnLatencySpans,
|
|
52715
52897
|
acknowledgeVoiceMonitorIssue,
|
|
52898
|
+
VOICE_ZERO_DATA_RETENTION_REDACTION_MARKER,
|
|
52716
52899
|
VOICE_WEBHOOK_TIMESTAMP_HEADER,
|
|
52717
52900
|
VOICE_WEBHOOK_SIGNATURE_HEADER,
|
|
52718
52901
|
VOICE_TCPA_DEFAULT_WINDOW,
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { type VoiceAgentTool } from "./agent";
|
|
2
|
+
import type { VoiceSessionRecord } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* Minimal structural shapes from the Model Context Protocol. Any MCP client
|
|
5
|
+
* (`@modelcontextprotocol/sdk` over stdio / SSE / streamable-HTTP, or a custom
|
|
6
|
+
* transport) that exposes `listTools` + `callTool` satisfies this — voice does
|
|
7
|
+
* not bundle an MCP SDK.
|
|
8
|
+
*/
|
|
9
|
+
export type MCPToolDefinition = {
|
|
10
|
+
name: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
inputSchema?: Record<string, unknown>;
|
|
13
|
+
};
|
|
14
|
+
export type MCPToolContentBlock = {
|
|
15
|
+
type: "text";
|
|
16
|
+
text: string;
|
|
17
|
+
} | {
|
|
18
|
+
type: string;
|
|
19
|
+
[key: string]: unknown;
|
|
20
|
+
};
|
|
21
|
+
export type MCPToolCallResult = {
|
|
22
|
+
content?: MCPToolContentBlock[];
|
|
23
|
+
structuredContent?: unknown;
|
|
24
|
+
isError?: boolean;
|
|
25
|
+
};
|
|
26
|
+
export type MCPClientLike = {
|
|
27
|
+
listTools: () => Promise<{
|
|
28
|
+
tools: MCPToolDefinition[];
|
|
29
|
+
}> | {
|
|
30
|
+
tools: MCPToolDefinition[];
|
|
31
|
+
};
|
|
32
|
+
callTool: (input: {
|
|
33
|
+
name: string;
|
|
34
|
+
arguments?: Record<string, unknown>;
|
|
35
|
+
}) => Promise<MCPToolCallResult> | MCPToolCallResult;
|
|
36
|
+
};
|
|
37
|
+
export type VoiceMCPToolResult = {
|
|
38
|
+
text: string;
|
|
39
|
+
structuredContent?: unknown;
|
|
40
|
+
isError: boolean;
|
|
41
|
+
raw: MCPToolCallResult;
|
|
42
|
+
};
|
|
43
|
+
export type CreateVoiceMCPToolsetOptions = {
|
|
44
|
+
client: MCPClientLike;
|
|
45
|
+
/** Prefix applied to every exposed tool name (e.g. "mcp_"). */
|
|
46
|
+
namePrefix?: string;
|
|
47
|
+
/** Only expose tools whose (unprefixed) name is in this allow-list. */
|
|
48
|
+
allowedTools?: ReadonlyArray<string>;
|
|
49
|
+
/** Drop tools whose (unprefixed) name is in this block-list. */
|
|
50
|
+
blockedTools?: ReadonlyArray<string>;
|
|
51
|
+
/** Override how an MCP result is flattened to the assistant-visible string. */
|
|
52
|
+
resultToMessage?: (result: VoiceMCPToolResult) => string;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Bridges the tools exposed by an MCP server into `VoiceAgentTool`s. Call once
|
|
56
|
+
* at setup; the returned array spreads straight into `createVoiceAgent({ tools })`.
|
|
57
|
+
*/
|
|
58
|
+
export declare const createVoiceMCPToolset: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord>(options: CreateVoiceMCPToolsetOptions) => Promise<VoiceAgentTool<TContext, TSession, Record<string, unknown>, VoiceMCPToolResult>[]>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export type VoiceAnalyticsVariableValue = string | number | boolean | null;
|
|
2
|
+
export type VoiceAnalyticsCall = {
|
|
3
|
+
sessionId: string;
|
|
4
|
+
variables: Record<string, VoiceAnalyticsVariableValue>;
|
|
5
|
+
durationSeconds?: number;
|
|
6
|
+
costUsd?: number;
|
|
7
|
+
outcome?: string;
|
|
8
|
+
success?: boolean;
|
|
9
|
+
at?: number;
|
|
10
|
+
};
|
|
11
|
+
export type VoiceVariableValueStats = {
|
|
12
|
+
value: string;
|
|
13
|
+
count: number;
|
|
14
|
+
share: number;
|
|
15
|
+
successRate: number | null;
|
|
16
|
+
avgDurationSeconds: number | null;
|
|
17
|
+
avgCostUsd: number | null;
|
|
18
|
+
outcomes: Record<string, number>;
|
|
19
|
+
};
|
|
20
|
+
export type VoiceVariableBreakdown = {
|
|
21
|
+
variable: string;
|
|
22
|
+
distinctValues: number;
|
|
23
|
+
missingCount: number;
|
|
24
|
+
values: VoiceVariableValueStats[];
|
|
25
|
+
};
|
|
26
|
+
export type VoiceVariableAnalyticsReport = {
|
|
27
|
+
totalCalls: number;
|
|
28
|
+
overall: {
|
|
29
|
+
successRate: number | null;
|
|
30
|
+
avgDurationSeconds: number | null;
|
|
31
|
+
avgCostUsd: number | null;
|
|
32
|
+
};
|
|
33
|
+
byVariable: Record<string, VoiceVariableBreakdown>;
|
|
34
|
+
};
|
|
35
|
+
export type BuildVoiceVariableAnalyticsInput = {
|
|
36
|
+
calls: ReadonlyArray<VoiceAnalyticsCall>;
|
|
37
|
+
/** Variable keys to break analytics down by. */
|
|
38
|
+
variables: ReadonlyArray<string>;
|
|
39
|
+
/**
|
|
40
|
+
* Treat these outcome strings as successes when a call has no explicit
|
|
41
|
+
* `success` flag. Case-insensitive.
|
|
42
|
+
*/
|
|
43
|
+
successOutcomes?: ReadonlyArray<string>;
|
|
44
|
+
/** Cap the values returned per variable (highest count first). */
|
|
45
|
+
topValuesPerVariable?: number;
|
|
46
|
+
};
|
|
47
|
+
export declare const buildVoiceVariableAnalytics: (input: BuildVoiceVariableAnalyticsInput) => VoiceVariableAnalyticsReport;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { VoiceTraceEvent } from "./trace";
|
|
2
|
+
import type { VoiceTurnRecord } from "./types";
|
|
3
|
+
export type VoiceZeroDataRetentionMode = "off" | "strict" | "custom";
|
|
4
|
+
export type VoiceZeroDataRetentionRetainFlags = {
|
|
5
|
+
/** Persist committed/partial transcript text. */
|
|
6
|
+
transcriptText: boolean;
|
|
7
|
+
/** Persist assistant response text. */
|
|
8
|
+
assistantText: boolean;
|
|
9
|
+
/** Persist recorded audio artifacts. */
|
|
10
|
+
recordings: boolean;
|
|
11
|
+
/** Persist free-text payloads on trace events. */
|
|
12
|
+
traceText: boolean;
|
|
13
|
+
/** Persist arbitrary session/turn metadata. */
|
|
14
|
+
metadata: boolean;
|
|
15
|
+
};
|
|
16
|
+
export type VoiceZeroDataRetentionPolicy = {
|
|
17
|
+
mode: VoiceZeroDataRetentionMode;
|
|
18
|
+
retain: VoiceZeroDataRetentionRetainFlags;
|
|
19
|
+
};
|
|
20
|
+
export type CreateVoiceZeroDataRetentionPolicyOptions = {
|
|
21
|
+
mode?: VoiceZeroDataRetentionMode;
|
|
22
|
+
/** Per-flag overrides; only meaningful with mode "custom" (or to relax "strict"). */
|
|
23
|
+
retain?: Partial<VoiceZeroDataRetentionRetainFlags>;
|
|
24
|
+
};
|
|
25
|
+
export declare const createVoiceZeroDataRetentionPolicy: (options?: CreateVoiceZeroDataRetentionPolicyOptions) => VoiceZeroDataRetentionPolicy;
|
|
26
|
+
export declare const isVoiceZeroDataRetentionActive: (policy: VoiceZeroDataRetentionPolicy) => boolean;
|
|
27
|
+
export declare const shouldRetainVoiceRecording: (policy: VoiceZeroDataRetentionPolicy) => boolean;
|
|
28
|
+
export declare const shouldRetainVoiceTranscript: (policy: VoiceZeroDataRetentionPolicy) => boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Returns a scrubbed copy of a turn record honoring the ZDR policy. Structural
|
|
31
|
+
* fields (ids, timestamps, transcript count, citation ids) are preserved;
|
|
32
|
+
* content fields are replaced with a redaction marker or dropped.
|
|
33
|
+
*/
|
|
34
|
+
export declare const scrubVoiceTurnForZeroDataRetention: <TResult = unknown>(turn: VoiceTurnRecord<TResult>, policy: VoiceZeroDataRetentionPolicy) => VoiceTurnRecord<TResult>;
|
|
35
|
+
/**
|
|
36
|
+
* Returns a scrubbed copy of a trace event honoring the ZDR policy. Drops or
|
|
37
|
+
* masks free-text payload fields while keeping the event type, ids, and
|
|
38
|
+
* timestamps so observability/lifecycle accounting still works.
|
|
39
|
+
*/
|
|
40
|
+
export declare const scrubVoiceTraceForZeroDataRetention: (event: VoiceTraceEvent, policy: VoiceZeroDataRetentionPolicy) => VoiceTraceEvent;
|
|
41
|
+
export declare const VOICE_ZERO_DATA_RETENTION_REDACTION_MARKER = "[redacted:zdr]";
|