@absolutejs/voice 0.0.22-beta.514 → 0.0.22-beta.515
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/callerCRMLinker.d.ts +29 -0
- package/dist/crmCallLogger.d.ts +37 -0
- package/dist/crmContract.d.ts +70 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +157 -0
- package/package.json +1 -1
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { VoiceCallerIdentity } from "./callerMemory";
|
|
2
|
+
import type { VoiceCRMContactSummary, VoiceCRMContract } from "./crmContract";
|
|
3
|
+
export type VoiceCallerCRMLinkRecord = {
|
|
4
|
+
callerKey: string;
|
|
5
|
+
vendor: string;
|
|
6
|
+
contactId: string;
|
|
7
|
+
contact: VoiceCRMContactSummary;
|
|
8
|
+
resolvedAt: number;
|
|
9
|
+
source: "memory" | "phone-lookup" | "email-lookup" | "manual";
|
|
10
|
+
};
|
|
11
|
+
export type VoiceCallerCRMLinkCacheStore = {
|
|
12
|
+
get(key: string): Promise<VoiceCallerCRMLinkRecord | null> | VoiceCallerCRMLinkRecord | null;
|
|
13
|
+
put(record: VoiceCallerCRMLinkRecord): Promise<void> | void;
|
|
14
|
+
remove(key: string): Promise<boolean> | boolean;
|
|
15
|
+
};
|
|
16
|
+
export type CreateVoiceCallerCRMLinkerOptions = {
|
|
17
|
+
contract: VoiceCRMContract;
|
|
18
|
+
cache?: VoiceCallerCRMLinkCacheStore;
|
|
19
|
+
staleAfterMs?: number;
|
|
20
|
+
now?: () => number;
|
|
21
|
+
};
|
|
22
|
+
export declare const createInMemoryVoiceCallerCRMLinkCache: () => VoiceCallerCRMLinkCacheStore;
|
|
23
|
+
export declare const createVoiceCallerCRMLinker: (options: CreateVoiceCallerCRMLinkerOptions) => {
|
|
24
|
+
associate: (identity: VoiceCallerIdentity, contact: VoiceCRMContactSummary) => Promise<VoiceCallerCRMLinkRecord>;
|
|
25
|
+
contract: VoiceCRMContract;
|
|
26
|
+
invalidate: (identity: VoiceCallerIdentity) => Promise<boolean>;
|
|
27
|
+
resolve: (identity: VoiceCallerIdentity) => Promise<VoiceCallerCRMLinkRecord | null>;
|
|
28
|
+
};
|
|
29
|
+
export type VoiceCallerCRMLinker = ReturnType<typeof createVoiceCallerCRMLinker>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { VoiceCRMContract } from "./crmContract";
|
|
2
|
+
export type VoiceCRMCallLoggerInput = {
|
|
3
|
+
sessionId: string;
|
|
4
|
+
contactId?: string;
|
|
5
|
+
startedAt: number;
|
|
6
|
+
endedAt?: number;
|
|
7
|
+
durationSeconds?: number;
|
|
8
|
+
summary?: string;
|
|
9
|
+
disposition?: string;
|
|
10
|
+
recordingUrl?: string;
|
|
11
|
+
transcriptUrl?: string;
|
|
12
|
+
metadata?: Record<string, unknown>;
|
|
13
|
+
};
|
|
14
|
+
export type VoiceCRMCallLogResult = {
|
|
15
|
+
activityId: string;
|
|
16
|
+
vendor: string;
|
|
17
|
+
loggedAt: number;
|
|
18
|
+
};
|
|
19
|
+
export type VoiceCRMCallLogErrorPolicy = "throw" | "swallow" | "queue";
|
|
20
|
+
export type CreateVoiceCRMCallLoggerOptions = {
|
|
21
|
+
contract: VoiceCRMContract;
|
|
22
|
+
errorPolicy?: VoiceCRMCallLogErrorPolicy;
|
|
23
|
+
onError?: (error: Error, input: VoiceCRMCallLoggerInput) => void | Promise<void>;
|
|
24
|
+
enqueueOnFailure?: (input: VoiceCRMCallLoggerInput) => Promise<void> | void;
|
|
25
|
+
now?: () => number;
|
|
26
|
+
};
|
|
27
|
+
export declare const createVoiceCRMCallLogger: (options: CreateVoiceCRMCallLoggerOptions) => {
|
|
28
|
+
contract: VoiceCRMContract;
|
|
29
|
+
logCallEnd: (input: VoiceCRMCallLoggerInput) => Promise<VoiceCRMCallLogResult | null>;
|
|
30
|
+
noteOnContact: (input: {
|
|
31
|
+
contactId: string;
|
|
32
|
+
body: string;
|
|
33
|
+
}) => Promise<{
|
|
34
|
+
noteId: string;
|
|
35
|
+
} | null>;
|
|
36
|
+
};
|
|
37
|
+
export type VoiceCRMCallLogger = ReturnType<typeof createVoiceCRMCallLogger>;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
export type VoiceCRMContactSummary = {
|
|
2
|
+
id: string;
|
|
3
|
+
vendor?: string;
|
|
4
|
+
firstName?: string;
|
|
5
|
+
lastName?: string;
|
|
6
|
+
email?: string;
|
|
7
|
+
phone?: string;
|
|
8
|
+
jobTitle?: string;
|
|
9
|
+
metadata?: Record<string, unknown>;
|
|
10
|
+
};
|
|
11
|
+
export type VoiceCRMLeadInput = {
|
|
12
|
+
firstName?: string;
|
|
13
|
+
lastName?: string;
|
|
14
|
+
email?: string;
|
|
15
|
+
phone?: string;
|
|
16
|
+
company?: string;
|
|
17
|
+
jobTitle?: string;
|
|
18
|
+
source?: string;
|
|
19
|
+
notes?: string;
|
|
20
|
+
metadata?: Record<string, unknown>;
|
|
21
|
+
};
|
|
22
|
+
export type VoiceCRMCallActivityInput = {
|
|
23
|
+
contactId?: string;
|
|
24
|
+
sessionId: string;
|
|
25
|
+
startedAt: number;
|
|
26
|
+
endedAt: number;
|
|
27
|
+
durationSeconds: number;
|
|
28
|
+
summary?: string;
|
|
29
|
+
disposition?: string;
|
|
30
|
+
recordingUrl?: string;
|
|
31
|
+
transcriptUrl?: string;
|
|
32
|
+
metadata?: Record<string, unknown>;
|
|
33
|
+
};
|
|
34
|
+
export type VoiceCRMNoteInput = {
|
|
35
|
+
contactId: string;
|
|
36
|
+
body: string;
|
|
37
|
+
metadata?: Record<string, unknown>;
|
|
38
|
+
};
|
|
39
|
+
export type VoiceCRMTaskInput = {
|
|
40
|
+
contactId?: string;
|
|
41
|
+
subject: string;
|
|
42
|
+
description?: string;
|
|
43
|
+
dueAt?: number;
|
|
44
|
+
priority?: "low" | "normal" | "high";
|
|
45
|
+
};
|
|
46
|
+
export type VoiceCRMContract = {
|
|
47
|
+
readonly vendor: string;
|
|
48
|
+
lookupByPhone(phone: string): Promise<VoiceCRMContactSummary | null>;
|
|
49
|
+
lookupByEmail(email: string): Promise<VoiceCRMContactSummary | null>;
|
|
50
|
+
createLead(input: VoiceCRMLeadInput): Promise<VoiceCRMContactSummary>;
|
|
51
|
+
logCall(input: VoiceCRMCallActivityInput): Promise<{
|
|
52
|
+
activityId: string;
|
|
53
|
+
}>;
|
|
54
|
+
addNote(input: VoiceCRMNoteInput): Promise<{
|
|
55
|
+
noteId: string;
|
|
56
|
+
}>;
|
|
57
|
+
createTask?(input: VoiceCRMTaskInput): Promise<{
|
|
58
|
+
taskId: string;
|
|
59
|
+
}>;
|
|
60
|
+
};
|
|
61
|
+
export type VoiceCRMRegistry = {
|
|
62
|
+
default(): VoiceCRMContract | null;
|
|
63
|
+
get(vendor: string): VoiceCRMContract | null;
|
|
64
|
+
list(): VoiceCRMContract[];
|
|
65
|
+
};
|
|
66
|
+
export type CreateVoiceCRMRegistryOptions = {
|
|
67
|
+
contracts: VoiceCRMContract[];
|
|
68
|
+
defaultVendor?: string;
|
|
69
|
+
};
|
|
70
|
+
export declare const createVoiceCRMRegistry: (options: CreateVoiceCRMRegistryOptions) => VoiceCRMRegistry;
|
package/dist/index.d.ts
CHANGED
|
@@ -351,4 +351,10 @@ export { compileVoicePathwayToAssistant } from "./pathwayCompiler";
|
|
|
351
351
|
export type { CompileVoicePathwayOptions, VoicePathwayCompiledAssistant, VoicePathwayCompilerToolDefinition, } from "./pathwayCompiler";
|
|
352
352
|
export { renderVoicePathwayMermaid, renderVoicePathwayText, visualizeVoicePathway, } from "./pathwayVisualizer";
|
|
353
353
|
export type { VoicePathwayVisualization } from "./pathwayVisualizer";
|
|
354
|
+
export { createVoiceCRMRegistry } from "./crmContract";
|
|
355
|
+
export type { CreateVoiceCRMRegistryOptions, VoiceCRMCallActivityInput, VoiceCRMContactSummary, VoiceCRMContract, VoiceCRMLeadInput, VoiceCRMNoteInput, VoiceCRMRegistry, VoiceCRMTaskInput, } from "./crmContract";
|
|
356
|
+
export { createInMemoryVoiceCallerCRMLinkCache, createVoiceCallerCRMLinker, } from "./callerCRMLinker";
|
|
357
|
+
export type { CreateVoiceCallerCRMLinkerOptions, VoiceCallerCRMLinkCacheStore, VoiceCallerCRMLinker, VoiceCallerCRMLinkRecord, } from "./callerCRMLinker";
|
|
358
|
+
export { createVoiceCRMCallLogger } from "./crmCallLogger";
|
|
359
|
+
export type { CreateVoiceCRMCallLoggerOptions, VoiceCRMCallLogErrorPolicy, VoiceCRMCallLogger, VoiceCRMCallLoggerInput, VoiceCRMCallLogResult, } from "./crmCallLogger";
|
|
354
360
|
export * from "./types";
|
package/dist/index.js
CHANGED
|
@@ -51360,6 +51360,159 @@ var visualizeVoicePathway = (pathway) => ({
|
|
|
51360
51360
|
mermaid: renderVoicePathwayMermaid(pathway),
|
|
51361
51361
|
text: renderVoicePathwayText(pathway)
|
|
51362
51362
|
});
|
|
51363
|
+
// src/crmContract.ts
|
|
51364
|
+
var createVoiceCRMRegistry = (options) => {
|
|
51365
|
+
const byVendor = new Map;
|
|
51366
|
+
for (const contract of options.contracts) {
|
|
51367
|
+
byVendor.set(contract.vendor, contract);
|
|
51368
|
+
}
|
|
51369
|
+
const defaultVendor = options.defaultVendor ?? options.contracts[0]?.vendor ?? null;
|
|
51370
|
+
return {
|
|
51371
|
+
default() {
|
|
51372
|
+
return defaultVendor ? byVendor.get(defaultVendor) ?? null : null;
|
|
51373
|
+
},
|
|
51374
|
+
get(vendor) {
|
|
51375
|
+
return byVendor.get(vendor) ?? null;
|
|
51376
|
+
},
|
|
51377
|
+
list() {
|
|
51378
|
+
return Array.from(byVendor.values());
|
|
51379
|
+
}
|
|
51380
|
+
};
|
|
51381
|
+
};
|
|
51382
|
+
// src/callerCRMLinker.ts
|
|
51383
|
+
var cacheKeyFor = (identity, vendor) => {
|
|
51384
|
+
const id = identity.externalId ?? identity.phone ?? identity.email ?? "anonymous";
|
|
51385
|
+
return `${vendor}::${id}`;
|
|
51386
|
+
};
|
|
51387
|
+
var createInMemoryVoiceCallerCRMLinkCache = () => {
|
|
51388
|
+
const store = new Map;
|
|
51389
|
+
return {
|
|
51390
|
+
get: (key) => store.get(key) ?? null,
|
|
51391
|
+
put: (record) => {
|
|
51392
|
+
store.set(record.callerKey, { ...record });
|
|
51393
|
+
},
|
|
51394
|
+
remove: (key) => store.delete(key)
|
|
51395
|
+
};
|
|
51396
|
+
};
|
|
51397
|
+
var createVoiceCallerCRMLinker = (options) => {
|
|
51398
|
+
const now = options.now ?? (() => Date.now());
|
|
51399
|
+
const cache = options.cache ?? createInMemoryVoiceCallerCRMLinkCache();
|
|
51400
|
+
const staleAfter = options.staleAfterMs ?? 24 * 60 * 60 * 1000;
|
|
51401
|
+
const isFresh = (record) => now() - record.resolvedAt < staleAfter;
|
|
51402
|
+
const resolve3 = async (identity) => {
|
|
51403
|
+
const key = cacheKeyFor(identity, options.contract.vendor);
|
|
51404
|
+
const cached = await Promise.resolve(cache.get(key));
|
|
51405
|
+
if (cached && isFresh(cached)) {
|
|
51406
|
+
return cached;
|
|
51407
|
+
}
|
|
51408
|
+
let contact = null;
|
|
51409
|
+
let source = null;
|
|
51410
|
+
if (identity.phone) {
|
|
51411
|
+
contact = await options.contract.lookupByPhone(identity.phone);
|
|
51412
|
+
if (contact)
|
|
51413
|
+
source = "phone-lookup";
|
|
51414
|
+
}
|
|
51415
|
+
if (!contact && identity.email) {
|
|
51416
|
+
contact = await options.contract.lookupByEmail(identity.email);
|
|
51417
|
+
if (contact)
|
|
51418
|
+
source = "email-lookup";
|
|
51419
|
+
}
|
|
51420
|
+
if (!contact || !source)
|
|
51421
|
+
return null;
|
|
51422
|
+
const record = {
|
|
51423
|
+
callerKey: key,
|
|
51424
|
+
contact,
|
|
51425
|
+
contactId: contact.id,
|
|
51426
|
+
resolvedAt: now(),
|
|
51427
|
+
source,
|
|
51428
|
+
vendor: options.contract.vendor
|
|
51429
|
+
};
|
|
51430
|
+
await Promise.resolve(cache.put(record));
|
|
51431
|
+
return record;
|
|
51432
|
+
};
|
|
51433
|
+
const associate = async (identity, contact) => {
|
|
51434
|
+
const key = cacheKeyFor(identity, options.contract.vendor);
|
|
51435
|
+
const record = {
|
|
51436
|
+
callerKey: key,
|
|
51437
|
+
contact,
|
|
51438
|
+
contactId: contact.id,
|
|
51439
|
+
resolvedAt: now(),
|
|
51440
|
+
source: "manual",
|
|
51441
|
+
vendor: options.contract.vendor
|
|
51442
|
+
};
|
|
51443
|
+
await Promise.resolve(cache.put(record));
|
|
51444
|
+
return record;
|
|
51445
|
+
};
|
|
51446
|
+
const invalidate = async (identity) => {
|
|
51447
|
+
const key = cacheKeyFor(identity, options.contract.vendor);
|
|
51448
|
+
return Promise.resolve(cache.remove(key));
|
|
51449
|
+
};
|
|
51450
|
+
return {
|
|
51451
|
+
associate,
|
|
51452
|
+
contract: options.contract,
|
|
51453
|
+
invalidate,
|
|
51454
|
+
resolve: resolve3
|
|
51455
|
+
};
|
|
51456
|
+
};
|
|
51457
|
+
// src/crmCallLogger.ts
|
|
51458
|
+
var createVoiceCRMCallLogger = (options) => {
|
|
51459
|
+
const now = options.now ?? (() => Date.now());
|
|
51460
|
+
const errorPolicy = options.errorPolicy ?? "swallow";
|
|
51461
|
+
const logCallEnd = async (input) => {
|
|
51462
|
+
const endedAt = input.endedAt ?? now();
|
|
51463
|
+
const duration = input.durationSeconds ?? Math.max(0, Math.round((endedAt - input.startedAt) / 1000));
|
|
51464
|
+
const payload = {
|
|
51465
|
+
durationSeconds: duration,
|
|
51466
|
+
endedAt,
|
|
51467
|
+
sessionId: input.sessionId,
|
|
51468
|
+
startedAt: input.startedAt,
|
|
51469
|
+
...input.contactId !== undefined ? { contactId: input.contactId } : {},
|
|
51470
|
+
...input.summary !== undefined ? { summary: input.summary } : {},
|
|
51471
|
+
...input.disposition !== undefined ? { disposition: input.disposition } : {},
|
|
51472
|
+
...input.recordingUrl !== undefined ? { recordingUrl: input.recordingUrl } : {},
|
|
51473
|
+
...input.transcriptUrl !== undefined ? { transcriptUrl: input.transcriptUrl } : {},
|
|
51474
|
+
...input.metadata !== undefined ? { metadata: input.metadata } : {}
|
|
51475
|
+
};
|
|
51476
|
+
try {
|
|
51477
|
+
const result = await options.contract.logCall(payload);
|
|
51478
|
+
return {
|
|
51479
|
+
activityId: result.activityId,
|
|
51480
|
+
loggedAt: now(),
|
|
51481
|
+
vendor: options.contract.vendor
|
|
51482
|
+
};
|
|
51483
|
+
} catch (rawError) {
|
|
51484
|
+
const error = rawError instanceof Error ? rawError : new Error(String(rawError));
|
|
51485
|
+
await options.onError?.(error, input);
|
|
51486
|
+
if (errorPolicy === "queue") {
|
|
51487
|
+
await options.enqueueOnFailure?.(input);
|
|
51488
|
+
return null;
|
|
51489
|
+
}
|
|
51490
|
+
if (errorPolicy === "throw")
|
|
51491
|
+
throw error;
|
|
51492
|
+
return null;
|
|
51493
|
+
}
|
|
51494
|
+
};
|
|
51495
|
+
const noteOnContact = async (input) => {
|
|
51496
|
+
try {
|
|
51497
|
+
return await options.contract.addNote(input);
|
|
51498
|
+
} catch (rawError) {
|
|
51499
|
+
const error = rawError instanceof Error ? rawError : new Error(String(rawError));
|
|
51500
|
+
await options.onError?.(error, {
|
|
51501
|
+
sessionId: "(note)",
|
|
51502
|
+
startedAt: now(),
|
|
51503
|
+
...input
|
|
51504
|
+
});
|
|
51505
|
+
if (errorPolicy === "throw")
|
|
51506
|
+
throw error;
|
|
51507
|
+
return null;
|
|
51508
|
+
}
|
|
51509
|
+
};
|
|
51510
|
+
return {
|
|
51511
|
+
contract: options.contract,
|
|
51512
|
+
logCallEnd,
|
|
51513
|
+
noteOnContact
|
|
51514
|
+
};
|
|
51515
|
+
};
|
|
51363
51516
|
export {
|
|
51364
51517
|
writeVoiceProofPack,
|
|
51365
51518
|
writeVoiceMediaPipelineArtifacts,
|
|
@@ -52031,6 +52184,7 @@ export {
|
|
|
52031
52184
|
createVoiceCampaign,
|
|
52032
52185
|
createVoiceCallingWindow,
|
|
52033
52186
|
createVoiceCallerMemoryNamespace,
|
|
52187
|
+
createVoiceCallerCRMLinker,
|
|
52034
52188
|
createVoiceCallReviewRecorder,
|
|
52035
52189
|
createVoiceCallReviewFromSession,
|
|
52036
52190
|
createVoiceCallReviewFromLiveTelephonyReport,
|
|
@@ -52038,6 +52192,8 @@ export {
|
|
|
52038
52192
|
createVoiceCallDispositionTagger,
|
|
52039
52193
|
createVoiceCallDebuggerRoutes,
|
|
52040
52194
|
createVoiceCallCompletedEvent,
|
|
52195
|
+
createVoiceCRMRegistry,
|
|
52196
|
+
createVoiceCRMCallLogger,
|
|
52041
52197
|
createVoiceCRMActivitySink,
|
|
52042
52198
|
createVoiceBrowserMediaRoutes,
|
|
52043
52199
|
createVoiceBrowserCallProfileRoutes,
|
|
@@ -52098,6 +52254,7 @@ export {
|
|
|
52098
52254
|
createLiveCallViewerFromOptions,
|
|
52099
52255
|
createLiveCallViewer,
|
|
52100
52256
|
createJSONVoiceAssistantModel,
|
|
52257
|
+
createInMemoryVoiceCallerCRMLinkCache,
|
|
52101
52258
|
createInMemoryVoiceCallQuota,
|
|
52102
52259
|
createInMemoryDNCList,
|
|
52103
52260
|
createId,
|