@absolutejs/voice 0.0.22-beta.490 → 0.0.22-beta.492

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.
@@ -0,0 +1,37 @@
1
+ import type { VoiceCampaign, VoiceCampaignAttemptStatus, VoiceCampaignRecipient, VoiceCampaignRecord, VoiceCampaignTimeWindow } from "./campaign";
2
+ export type VoiceCampaignDisposition = "answered" | "busy" | "failed" | "no-answer" | "voicemail";
3
+ export type VoiceCampaignDispositionRetryRule = {
4
+ backoffMs?: number;
5
+ maxAttempts?: number;
6
+ retry?: boolean;
7
+ };
8
+ export type VoiceCampaignDispositionRetryPolicy = Partial<Record<VoiceCampaignDisposition, VoiceCampaignDispositionRetryRule>>;
9
+ export type VoiceDNCList = {
10
+ contains: (phone: string) => boolean | Promise<boolean>;
11
+ };
12
+ export declare const normalizePhoneNumber: (phone: string) => string;
13
+ export declare const createInMemoryDNCList: (phones: ReadonlyArray<string>) => VoiceDNCList;
14
+ export declare const isPhoneOnDNC: (phone: string, list: VoiceDNCList) => Promise<boolean>;
15
+ export type VoiceCampaignWindowCheckInput = {
16
+ now?: Date;
17
+ window: VoiceCampaignTimeWindow;
18
+ };
19
+ export declare const isWithinCampaignWindow: (input: VoiceCampaignWindowCheckInput) => boolean;
20
+ export declare const shouldRetryCampaignAttempt: (input: {
21
+ attempts: number;
22
+ campaign: Pick<VoiceCampaign, "maxAttempts">;
23
+ disposition?: VoiceCampaignDisposition;
24
+ policy?: VoiceCampaignDispositionRetryPolicy;
25
+ }) => {
26
+ backoffMs?: number;
27
+ retry: boolean;
28
+ };
29
+ export type VoiceCampaignDispositionSummary = {
30
+ attempts: number;
31
+ byDisposition: Partial<Record<VoiceCampaignDisposition, number>>;
32
+ byStatus: Record<VoiceCampaignAttemptStatus, number>;
33
+ campaignId: string;
34
+ recipientsByStatus: Record<VoiceCampaignRecipient["status"], number>;
35
+ totalRecipients: number;
36
+ };
37
+ export declare const summarizeVoiceCampaignDispositions: (record: VoiceCampaignRecord) => VoiceCampaignDispositionSummary;
package/dist/index.d.ts CHANGED
@@ -83,6 +83,8 @@ export { createPunctuationSemanticTurnDetector, createRegexSemanticTurnDetector,
83
83
  export { VOICE_WEBHOOK_SIGNATURE_HEADER, VOICE_WEBHOOK_TIMESTAMP_HEADER, extractVoiceWebhookSignatureFromHeaders, signVoiceWebhookBody, verifyVoiceWebhookSignature, } from "./webhookVerification";
84
84
  export { describeVoiceAgentUIState, deriveVoiceAgentUIState, voiceAgentUIStateOrder, } from "./agentState";
85
85
  export type { VoiceAgentUIInput, VoiceAgentUIState, } from "./agentState";
86
+ export { createInMemoryDNCList, isPhoneOnDNC, isWithinCampaignWindow, normalizePhoneNumber, shouldRetryCampaignAttempt, summarizeVoiceCampaignDispositions, } from "./campaignControls";
87
+ export type { VoiceCampaignDisposition, VoiceCampaignDispositionRetryPolicy, VoiceCampaignDispositionRetryRule, VoiceCampaignDispositionSummary, VoiceCampaignWindowCheckInput, VoiceDNCList, } from "./campaignControls";
86
88
  export { createVoiceBackchannelDriver } from "./backchannel";
87
89
  export type { VoiceBackchannelCue, VoiceBackchannelDriver, VoiceBackchannelDriverOptions, } from "./backchannel";
88
90
  export { createVoiceIVRSession, describeVoiceIVRPlan, evaluateVoiceIVRPlan, } from "./ivrPlan";
@@ -95,8 +97,8 @@ export type { VoiceWebhookVerificationInput, VoiceWebhookVerificationReason, Voi
95
97
  export type { CreatePunctuationSemanticTurnDetectorOptions, CreateRegexSemanticTurnDetectorOptions, VoiceSemanticTurnDetector, VoiceSemanticTurnInput, VoiceSemanticTurnVerdict, } from "./semanticTurn";
96
98
  export { createMonologueAMDDetector } from "./amdDetector";
97
99
  export type { MonologueAMDDetectorOptions, VoiceAMDDetector, VoiceAMDDetectorInput, VoiceAMDVerdict, } from "./amdDetector";
98
- export { createVoiceRAGTool } from "./ragTool";
99
- export type { VoiceRAGCollectionLike, VoiceRAGQueryResult, VoiceRAGSearchInput, VoiceRAGToolArgs, VoiceRAGToolOptions, VoiceRAGToolResult, } from "./ragTool";
100
+ export { createVoiceRAGTool, extractVoiceRAGCitations } from "./ragTool";
101
+ export type { VoiceRAGCitationSummary, VoiceRAGCollectionLike, VoiceRAGQueryResult, VoiceRAGSearchInput, VoiceRAGToolArgs, VoiceRAGToolOptions, VoiceRAGToolResult, } from "./ragTool";
100
102
  export { createVoiceApiRequestTool, createVoiceDTMFTool, createVoiceEndCallTool, createVoiceTransferCallTool, createVoiceVoicemailDetectionTool, } from "./agentTools";
101
103
  export { fromVapiAssistantConfig } from "./vapiAdapter";
102
104
  export type { VapiAssistantConfig, VapiAssistantConfigModel, VapiAssistantConfigTool, VapiAssistantConfigTranscriber, VapiAssistantConfigTransferDestination, VapiAssistantConfigVoice, VapiAssistantMessage, VoiceFromVapiAssistantOptions, VoiceFromVapiAssistantResult, VoiceFromVapiCustomToolFactory, VoiceFromVapiCustomToolInput, VoiceFromVapiDTMFFactory, VoiceFromVapiKnowledgeBase, VoiceFromVapiModelFactory, VoiceFromVapiModelFactoryInput, VoiceFromVapiRouteHints, VoiceFromVapiUnsupportedReason, } from "./vapiAdapter";
package/dist/index.js CHANGED
@@ -35515,6 +35515,90 @@ var voiceAgentUIStateOrder = [
35515
35515
  "thinking",
35516
35516
  "speaking"
35517
35517
  ];
35518
+ // src/campaignControls.ts
35519
+ var normalizePhoneNumber = (phone) => phone.replace(/[\s()-]/g, "").trim();
35520
+ var createInMemoryDNCList = (phones) => {
35521
+ const set = new Set(phones.map(normalizePhoneNumber));
35522
+ return {
35523
+ contains: (phone) => set.has(normalizePhoneNumber(phone))
35524
+ };
35525
+ };
35526
+ var isPhoneOnDNC = async (phone, list) => Promise.resolve(list.contains(phone));
35527
+ var isWithinCampaignWindow = (input) => {
35528
+ const now = input.now ?? new Date;
35529
+ const offsetMinutes = input.window.timeZoneOffsetMinutes ?? 0;
35530
+ const shifted = new Date(now.getTime() + offsetMinutes * 60000);
35531
+ const day = shifted.getUTCDay();
35532
+ if (input.window.daysOfWeek && !input.window.daysOfWeek.includes(day)) {
35533
+ return false;
35534
+ }
35535
+ const hour = shifted.getUTCHours();
35536
+ if (input.window.startHour <= input.window.endHour) {
35537
+ return hour >= input.window.startHour && hour < input.window.endHour;
35538
+ }
35539
+ return hour >= input.window.startHour || hour < input.window.endHour;
35540
+ };
35541
+ var shouldRetryCampaignAttempt = (input) => {
35542
+ if (input.attempts >= input.campaign.maxAttempts) {
35543
+ return { retry: false };
35544
+ }
35545
+ const rule = input.disposition ? input.policy?.[input.disposition] : undefined;
35546
+ if (rule && rule.retry === false) {
35547
+ return { retry: false };
35548
+ }
35549
+ if (rule?.maxAttempts !== undefined && input.attempts >= rule.maxAttempts) {
35550
+ return { retry: false };
35551
+ }
35552
+ return { backoffMs: rule?.backoffMs, retry: true };
35553
+ };
35554
+ var dispositionFromAttempt = (attempt) => {
35555
+ const metadata = attempt.metadata;
35556
+ if (metadata && typeof metadata.disposition === "string") {
35557
+ return metadata.disposition;
35558
+ }
35559
+ if (attempt.status === "failed") {
35560
+ return "failed";
35561
+ }
35562
+ if (attempt.status === "succeeded") {
35563
+ return "answered";
35564
+ }
35565
+ return;
35566
+ };
35567
+ var summarizeVoiceCampaignDispositions = (record) => {
35568
+ const byStatus = {
35569
+ canceled: 0,
35570
+ failed: 0,
35571
+ queued: 0,
35572
+ running: 0,
35573
+ succeeded: 0
35574
+ };
35575
+ const byDisposition = {};
35576
+ for (const attempt of record.attempts) {
35577
+ byStatus[attempt.status] = (byStatus[attempt.status] ?? 0) + 1;
35578
+ const disposition = dispositionFromAttempt(attempt);
35579
+ if (disposition) {
35580
+ byDisposition[disposition] = (byDisposition[disposition] ?? 0) + 1;
35581
+ }
35582
+ }
35583
+ const recipientsByStatus = {
35584
+ canceled: 0,
35585
+ completed: 0,
35586
+ failed: 0,
35587
+ pending: 0,
35588
+ queued: 0
35589
+ };
35590
+ for (const recipient of record.recipients) {
35591
+ recipientsByStatus[recipient.status] = (recipientsByStatus[recipient.status] ?? 0) + 1;
35592
+ }
35593
+ return {
35594
+ attempts: record.attempts.length,
35595
+ byDisposition,
35596
+ byStatus,
35597
+ campaignId: record.campaign.id,
35598
+ recipientsByStatus,
35599
+ totalRecipients: record.recipients.length
35600
+ };
35601
+ };
35518
35602
  // src/backchannel.ts
35519
35603
  var DEFAULT_CUES = [
35520
35604
  { text: "mm-hmm" },
@@ -35922,6 +36006,28 @@ var createMonologueAMDDetector = (options = {}) => {
35922
36006
  };
35923
36007
  };
35924
36008
  // src/ragTool.ts
36009
+ var extractVoiceRAGCitations = (toolResults, toolName = "searchKnowledgeBase") => {
36010
+ const out = [];
36011
+ for (const entry of toolResults) {
36012
+ if (entry.toolName !== toolName) {
36013
+ continue;
36014
+ }
36015
+ const result = entry.result;
36016
+ const citations = result?.citations;
36017
+ if (!Array.isArray(citations)) {
36018
+ continue;
36019
+ }
36020
+ for (const citation of citations) {
36021
+ out.push({
36022
+ chunkId: citation.chunkId,
36023
+ score: citation.score,
36024
+ source: citation.source,
36025
+ title: citation.title
36026
+ });
36027
+ }
36028
+ }
36029
+ return out;
36030
+ };
35925
36031
  var DEFAULT_TOOL_NAME = "searchKnowledgeBase";
35926
36032
  var DEFAULT_DESCRIPTION = "Search the knowledge base and return short grounded citations. Use this whenever the caller asks a question that may be answered by indexed reference material.";
35927
36033
  var DEFAULT_TOP_K = 6;
@@ -46502,6 +46608,7 @@ export {
46502
46608
  summarizeVoiceHandoffHealth,
46503
46609
  summarizeVoiceHandoffDeliveries,
46504
46610
  summarizeVoiceCampaigns,
46611
+ summarizeVoiceCampaignDispositions,
46505
46612
  summarizeVoiceCallerTranscript,
46506
46613
  summarizeVoiceBrowserMedia,
46507
46614
  summarizeVoiceBargeIn,
@@ -46513,6 +46620,7 @@ export {
46513
46620
  signVoiceWebhookBody,
46514
46621
  signVoiceTwilioWebhook,
46515
46622
  signVoicePlivoWebhook,
46623
+ shouldRetryCampaignAttempt,
46516
46624
  shapeTelephonyAssistantText,
46517
46625
  selectVoiceTraceEventsForPrune,
46518
46626
  saveVoiceIncidentBundleArtifact,
@@ -46684,6 +46792,7 @@ export {
46684
46792
  parseVoiceTelephonyWebhookEvent,
46685
46793
  parseVoiceSessionSnapshot,
46686
46794
  normalizeVoiceProofTrendReport,
46795
+ normalizePhoneNumber,
46687
46796
  muteVoiceMonitorIssue,
46688
46797
  matchesVoiceOpsTaskAssignmentRule,
46689
46798
  markVoiceOpsTaskSLABreached,
@@ -46694,7 +46803,9 @@ export {
46694
46803
  listVoiceRoutingEvents,
46695
46804
  listVoiceProviderDecisionTraces,
46696
46805
  listVoiceOpsTasks,
46806
+ isWithinCampaignWindow,
46697
46807
  isVoiceOpsTaskOverdue,
46808
+ isPhoneOnDNC,
46698
46809
  importVoiceCampaignRecipients,
46699
46810
  heartbeatVoiceOpsTask,
46700
46811
  hasVoiceOpsTaskSLABreach,
@@ -46711,6 +46822,7 @@ export {
46711
46822
  fetchVoiceProofTarget,
46712
46823
  failVoiceOpsTask,
46713
46824
  extractVoiceWebhookSignatureFromHeaders,
46825
+ extractVoiceRAGCitations,
46714
46826
  extractVoiceMediaPipelineIssueEntries,
46715
46827
  exportVoiceTrace,
46716
46828
  exportVoiceAuditTrail,
@@ -47116,6 +47228,7 @@ export {
47116
47228
  createMemoryVoiceTelephonyWebhookIdempotencyStore,
47117
47229
  createMemoryVoicePlivoWebhookNonceStore,
47118
47230
  createJSONVoiceAssistantModel,
47231
+ createInMemoryDNCList,
47119
47232
  createId,
47120
47233
  createGeminiVoiceAssistantModel,
47121
47234
  createDomainPhraseHints,
package/dist/ragTool.d.ts CHANGED
@@ -29,6 +29,16 @@ export type VoiceRAGToolResult = {
29
29
  query: string;
30
30
  topK: number;
31
31
  };
32
+ export type VoiceRAGCitationSummary = {
33
+ chunkId: string;
34
+ score: number;
35
+ source?: string;
36
+ title?: string;
37
+ };
38
+ export declare const extractVoiceRAGCitations: (toolResults: ReadonlyArray<{
39
+ result?: unknown;
40
+ toolName: string;
41
+ }>, toolName?: string) => VoiceRAGCitationSummary[];
32
42
  export type VoiceRAGToolOptions<TContext = unknown> = {
33
43
  allowedFilterKeys?: readonly string[];
34
44
  description?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.490",
3
+ "version": "0.0.22-beta.492",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",