@absolutejs/voice 0.0.22-beta.519 → 0.0.22-beta.520
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/conversationSimulator.d.ts +73 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +122 -0
- package/package.json +1 -1
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { VoiceAgent, VoiceAgentRunResult } from "./agent";
|
|
2
|
+
import type { VoiceSessionRecord } from "./types";
|
|
3
|
+
export type VoiceSimulatedSpeaker = "caller" | "agent";
|
|
4
|
+
export type VoiceSimulatedTurn = {
|
|
5
|
+
role: VoiceSimulatedSpeaker;
|
|
6
|
+
text: string;
|
|
7
|
+
at: number;
|
|
8
|
+
};
|
|
9
|
+
export type VoiceSimulatorCallerReply = {
|
|
10
|
+
text: string;
|
|
11
|
+
/** When true the synthetic caller ends the call after this utterance. */
|
|
12
|
+
done?: boolean;
|
|
13
|
+
};
|
|
14
|
+
export type VoiceSimulatorCallerModel = (input: {
|
|
15
|
+
persona: string;
|
|
16
|
+
transcript: ReadonlyArray<VoiceSimulatedTurn>;
|
|
17
|
+
turnIndex: number;
|
|
18
|
+
}) => Promise<VoiceSimulatorCallerReply> | VoiceSimulatorCallerReply;
|
|
19
|
+
export type VoiceSimulatorCaller = {
|
|
20
|
+
kind: "script";
|
|
21
|
+
/** Fixed caller utterances, delivered in order. */
|
|
22
|
+
utterances: ReadonlyArray<string>;
|
|
23
|
+
} | {
|
|
24
|
+
kind: "model";
|
|
25
|
+
/** System description of who the caller is and what they want. */
|
|
26
|
+
persona: string;
|
|
27
|
+
model: VoiceSimulatorCallerModel;
|
|
28
|
+
/** Hard cap on caller turns (defaults to maxTurns). */
|
|
29
|
+
maxCallerTurns?: number;
|
|
30
|
+
};
|
|
31
|
+
export type VoiceConversationSimulationEndedReason = "agent-complete" | "caller-hung-up" | "max-turns" | "script-exhausted";
|
|
32
|
+
export type VoiceConversationSimulationResult<TResult = unknown> = {
|
|
33
|
+
transcript: VoiceSimulatedTurn[];
|
|
34
|
+
turnCount: number;
|
|
35
|
+
endedReason: VoiceConversationSimulationEndedReason;
|
|
36
|
+
agentResults: VoiceAgentRunResult<TResult>[];
|
|
37
|
+
};
|
|
38
|
+
export type RunVoiceConversationSimulationInput<TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown> = {
|
|
39
|
+
agent: Pick<VoiceAgent<TContext, TSession, TResult>, "run">;
|
|
40
|
+
caller: VoiceSimulatorCaller;
|
|
41
|
+
context?: TContext;
|
|
42
|
+
session?: TSession;
|
|
43
|
+
sessionId?: string;
|
|
44
|
+
/** Hard cap on caller↔agent exchanges (default 12). */
|
|
45
|
+
maxTurns?: number;
|
|
46
|
+
/** Stop early when the agent route returns `complete: true` (default true). */
|
|
47
|
+
stopOnAgentComplete?: boolean;
|
|
48
|
+
now?: () => number;
|
|
49
|
+
generateId?: () => string;
|
|
50
|
+
};
|
|
51
|
+
export declare const runVoiceConversationSimulation: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown>(input: RunVoiceConversationSimulationInput<TContext, TSession, TResult>) => Promise<VoiceConversationSimulationResult<TResult>>;
|
|
52
|
+
export declare const renderVoiceSimulationTranscript: (transcript: ReadonlyArray<VoiceSimulatedTurn>, labels?: {
|
|
53
|
+
caller?: string;
|
|
54
|
+
agent?: string;
|
|
55
|
+
}) => string;
|
|
56
|
+
export type VoiceScriptedCallerStep = string;
|
|
57
|
+
/** Convenience: build a deterministic scripted caller from a list of lines. */
|
|
58
|
+
export declare const createScriptedVoiceCaller: (utterances: ReadonlyArray<VoiceScriptedCallerStep>) => VoiceSimulatorCaller;
|
|
59
|
+
export type VoicePersonaCallerCompletion = (input: {
|
|
60
|
+
prompt: string;
|
|
61
|
+
systemPrompt: string;
|
|
62
|
+
}) => Promise<string>;
|
|
63
|
+
/**
|
|
64
|
+
* Builds an LLM-backed synthetic caller. The completion returns the caller's
|
|
65
|
+
* next line; appending the sentinel `[[END]]` (case-insensitive) signals the
|
|
66
|
+
* caller wants to hang up.
|
|
67
|
+
*/
|
|
68
|
+
export declare const createPersonaVoiceCaller: (options: {
|
|
69
|
+
persona: string;
|
|
70
|
+
completion: VoicePersonaCallerCompletion;
|
|
71
|
+
maxCallerTurns?: number;
|
|
72
|
+
endSentinel?: string;
|
|
73
|
+
}) => VoiceSimulatorCaller;
|
package/dist/index.d.ts
CHANGED
|
@@ -69,6 +69,8 @@ export { assertVoiceSimulationSuiteEvidence, createVoiceSimulationSuiteRoutes, e
|
|
|
69
69
|
export { createVoiceWorkflowContract, createVoiceWorkflowContractHandler, createVoiceWorkflowContractPreset, createVoiceWorkflowScenario, recordVoiceWorkflowContractTrace, validateVoiceWorkflowRouteResult, } from "./workflowContract";
|
|
70
70
|
export { createVoiceSessionListRoutes, createVoiceSessionReplayHTMLHandler, createVoiceSessionReplayJSONHandler, createVoiceSessionReplayRoutes, createVoiceSessionsHTMLHandler, createVoiceSessionsJSONHandler, renderVoiceSessionsHTML, summarizeVoiceProviderFallbackRecovery, summarizeVoiceSessions, summarizeVoiceSessionReplay, } from "./sessionReplay";
|
|
71
71
|
export { createVoiceAgent, createVoiceAgentSquad, createVoiceAgentTool, } from "./agent";
|
|
72
|
+
export { createPersonaVoiceCaller, createScriptedVoiceCaller, renderVoiceSimulationTranscript, runVoiceConversationSimulation, } from "./conversationSimulator";
|
|
73
|
+
export type { RunVoiceConversationSimulationInput, VoiceConversationSimulationEndedReason, VoiceConversationSimulationResult, VoicePersonaCallerCompletion, VoiceScriptedCallerStep, VoiceSimulatedSpeaker, VoiceSimulatedTurn, VoiceSimulatorCaller, VoiceSimulatorCallerModel, VoiceSimulatorCallerReply, } from "./conversationSimulator";
|
|
72
74
|
export { createAIVoiceModel } from "./aiVoiceModel";
|
|
73
75
|
export type { CreateAIVoiceModelOptions } from "./aiVoiceModel";
|
|
74
76
|
export { createVoiceAIJudgeCompletion, createVoiceLLMJudge, } from "./llmJudge";
|
package/dist/index.js
CHANGED
|
@@ -35297,6 +35297,124 @@ var createVoiceWorkflowContractHandler = (input) => {
|
|
|
35297
35297
|
return result;
|
|
35298
35298
|
};
|
|
35299
35299
|
};
|
|
35300
|
+
// src/conversationSimulator.ts
|
|
35301
|
+
var createStubApi = (sessionId) => ({ id: sessionId });
|
|
35302
|
+
var callerTurnText = async (caller, transcript, turnIndex) => {
|
|
35303
|
+
if (caller.kind === "script") {
|
|
35304
|
+
const text = caller.utterances[turnIndex];
|
|
35305
|
+
if (text === undefined)
|
|
35306
|
+
return null;
|
|
35307
|
+
return {
|
|
35308
|
+
done: turnIndex === caller.utterances.length - 1,
|
|
35309
|
+
text
|
|
35310
|
+
};
|
|
35311
|
+
}
|
|
35312
|
+
const cap = caller.maxCallerTurns;
|
|
35313
|
+
if (cap !== undefined && turnIndex >= cap)
|
|
35314
|
+
return null;
|
|
35315
|
+
return Promise.resolve(caller.model({ persona: caller.persona, transcript, turnIndex }));
|
|
35316
|
+
};
|
|
35317
|
+
var runVoiceConversationSimulation = async (input) => {
|
|
35318
|
+
const now = input.now ?? (() => Date.now());
|
|
35319
|
+
const generateId = input.generateId ?? (() => `sim_${Math.random().toString(36).slice(2, 10)}`);
|
|
35320
|
+
const maxTurns = input.maxTurns ?? 12;
|
|
35321
|
+
const stopOnComplete = input.stopOnAgentComplete !== false;
|
|
35322
|
+
const sessionId = input.sessionId ?? `sim-${generateId()}`;
|
|
35323
|
+
const session = input.session ?? createVoiceSessionRecord(sessionId);
|
|
35324
|
+
const context = input.context ?? {};
|
|
35325
|
+
const api = createStubApi(sessionId);
|
|
35326
|
+
const transcript = [];
|
|
35327
|
+
const agentResults = [];
|
|
35328
|
+
let endedReason = "max-turns";
|
|
35329
|
+
for (let turnIndex = 0;turnIndex < maxTurns; turnIndex += 1) {
|
|
35330
|
+
const callerReply = await callerTurnText(input.caller, transcript, turnIndex);
|
|
35331
|
+
if (!callerReply) {
|
|
35332
|
+
endedReason = input.caller.kind === "script" ? "script-exhausted" : "max-turns";
|
|
35333
|
+
break;
|
|
35334
|
+
}
|
|
35335
|
+
const callerAt = now();
|
|
35336
|
+
transcript.push({ at: callerAt, role: "caller", text: callerReply.text });
|
|
35337
|
+
const userTranscript = {
|
|
35338
|
+
id: generateId(),
|
|
35339
|
+
isFinal: true,
|
|
35340
|
+
startedAtMs: callerAt,
|
|
35341
|
+
endedAtMs: callerAt,
|
|
35342
|
+
text: callerReply.text
|
|
35343
|
+
};
|
|
35344
|
+
const turn = {
|
|
35345
|
+
committedAt: callerAt,
|
|
35346
|
+
id: generateId(),
|
|
35347
|
+
text: callerReply.text,
|
|
35348
|
+
transcripts: [userTranscript]
|
|
35349
|
+
};
|
|
35350
|
+
const result = await input.agent.run({
|
|
35351
|
+
api,
|
|
35352
|
+
context,
|
|
35353
|
+
session,
|
|
35354
|
+
turn
|
|
35355
|
+
});
|
|
35356
|
+
agentResults.push(result);
|
|
35357
|
+
const assistantText = result.assistantText ?? "";
|
|
35358
|
+
if (assistantText.trim().length > 0) {
|
|
35359
|
+
transcript.push({ at: now(), role: "agent", text: assistantText });
|
|
35360
|
+
}
|
|
35361
|
+
const committedTurn = {
|
|
35362
|
+
...turn,
|
|
35363
|
+
assistantText: assistantText || undefined,
|
|
35364
|
+
...result.citations && result.citations.length > 0 ? { citations: [...result.citations] } : {}
|
|
35365
|
+
};
|
|
35366
|
+
session.turns = [...session.turns, committedTurn];
|
|
35367
|
+
if (stopOnComplete && result.complete) {
|
|
35368
|
+
endedReason = "agent-complete";
|
|
35369
|
+
break;
|
|
35370
|
+
}
|
|
35371
|
+
if (callerReply.done) {
|
|
35372
|
+
endedReason = "caller-hung-up";
|
|
35373
|
+
break;
|
|
35374
|
+
}
|
|
35375
|
+
}
|
|
35376
|
+
return {
|
|
35377
|
+
agentResults,
|
|
35378
|
+
endedReason,
|
|
35379
|
+
transcript,
|
|
35380
|
+
turnCount: agentResults.length
|
|
35381
|
+
};
|
|
35382
|
+
};
|
|
35383
|
+
var renderVoiceSimulationTranscript = (transcript, labels = {}) => {
|
|
35384
|
+
const callerLabel = labels.caller ?? "Caller";
|
|
35385
|
+
const agentLabel = labels.agent ?? "Agent";
|
|
35386
|
+
return transcript.map((turn) => `${turn.role === "caller" ? callerLabel : agentLabel}: ${turn.text}`).join(`
|
|
35387
|
+
`);
|
|
35388
|
+
};
|
|
35389
|
+
var createScriptedVoiceCaller = (utterances) => ({
|
|
35390
|
+
kind: "script",
|
|
35391
|
+
utterances
|
|
35392
|
+
});
|
|
35393
|
+
var createPersonaVoiceCaller = (options) => {
|
|
35394
|
+
const endSentinel = options.endSentinel ?? "[[END]]";
|
|
35395
|
+
return {
|
|
35396
|
+
kind: "model",
|
|
35397
|
+
...options.maxCallerTurns !== undefined ? { maxCallerTurns: options.maxCallerTurns } : {},
|
|
35398
|
+
model: async ({ persona, transcript }) => {
|
|
35399
|
+
const history = transcript.map((turn) => `${turn.role === "caller" ? "You" : "Agent"}: ${turn.text}`).join(`
|
|
35400
|
+
`);
|
|
35401
|
+
const raw = await options.completion({
|
|
35402
|
+
prompt: history.length > 0 ? `Conversation so far:
|
|
35403
|
+
${history}
|
|
35404
|
+
|
|
35405
|
+
Your next line:` : "Start the call with your opening line:",
|
|
35406
|
+
systemPrompt: `You are role-playing a caller in a voice conversation. ${persona}
|
|
35407
|
+
Respond with only your spoken line. When your goal is met or you want to hang up, end your line with ${endSentinel}.`
|
|
35408
|
+
});
|
|
35409
|
+
const done = raw.includes(endSentinel);
|
|
35410
|
+
return {
|
|
35411
|
+
done,
|
|
35412
|
+
text: raw.replaceAll(endSentinel, "").trim()
|
|
35413
|
+
};
|
|
35414
|
+
},
|
|
35415
|
+
persona: options.persona
|
|
35416
|
+
};
|
|
35417
|
+
};
|
|
35300
35418
|
// src/aiVoiceModel.ts
|
|
35301
35419
|
var toProviderMessages = (messages) => {
|
|
35302
35420
|
const out = [];
|
|
@@ -51657,6 +51775,7 @@ export {
|
|
|
51657
51775
|
runVoicePhoneAgentProductionSmokeContract,
|
|
51658
51776
|
runVoiceOutcomeContractSuite,
|
|
51659
51777
|
runVoiceMultilingualProof,
|
|
51778
|
+
runVoiceConversationSimulation,
|
|
51660
51779
|
runVoiceCommandProofTargets,
|
|
51661
51780
|
runVoiceCommandProofTarget,
|
|
51662
51781
|
runVoiceCampaignReadinessProof,
|
|
@@ -51702,6 +51821,7 @@ export {
|
|
|
51702
51821
|
renderVoiceSloReadinessThresholdMarkdown,
|
|
51703
51822
|
renderVoiceSloReadinessThresholdHTML,
|
|
51704
51823
|
renderVoiceSloCalibrationMarkdown,
|
|
51824
|
+
renderVoiceSimulationTranscript,
|
|
51705
51825
|
renderVoiceSimulationSuiteHTML,
|
|
51706
51826
|
renderVoiceSessionsHTML,
|
|
51707
51827
|
renderVoiceSessionObservabilityMarkdown,
|
|
@@ -52292,6 +52412,7 @@ export {
|
|
|
52292
52412
|
createStoredVoiceIncidentBundleArtifact,
|
|
52293
52413
|
createStoredVoiceExternalObjectMap,
|
|
52294
52414
|
createStoredVoiceCallReviewArtifact,
|
|
52415
|
+
createScriptedVoiceCaller,
|
|
52295
52416
|
createRiskyTurnCorrectionHandler,
|
|
52296
52417
|
createRegexSemanticTurnDetector,
|
|
52297
52418
|
createPunctuationSemanticTurnDetector,
|
|
@@ -52299,6 +52420,7 @@ export {
|
|
|
52299
52420
|
createPlivoVoiceResponse,
|
|
52300
52421
|
createPlivoMediaStreamBridge,
|
|
52301
52422
|
createPhraseHintCorrectionHandler,
|
|
52423
|
+
createPersonaVoiceCaller,
|
|
52302
52424
|
createOpenAIVoiceTTS,
|
|
52303
52425
|
createOpenAIVoiceAssistantModel,
|
|
52304
52426
|
createMonologueAMDDetector,
|