@absolutejs/voice 0.0.22-beta.582 → 0.0.22-beta.583
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/core/debugTiming.d.ts +11 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +49 -1
- package/dist/testing/index.js +34 -1
- package/package.json +1 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const logVoiceTiming: (sessionId: string, stage: string, elapsedMs: number, detail?: Record<string, unknown>) => void;
|
|
2
|
+
/**
|
|
3
|
+
* A per-turn stopwatch. `stamp(stage, detail?)` logs the elapsed since the timer
|
|
4
|
+
* was created, so one timer per turn lays every stage out on a single timeline:
|
|
5
|
+
*
|
|
6
|
+
* const stamp = startVoiceTimer(session.id);
|
|
7
|
+
* stamp("agent.system-resolved", { chars });
|
|
8
|
+
* stamp("agent.round0.generate-done", { ms });
|
|
9
|
+
*/
|
|
10
|
+
export declare const startVoiceTimer: (sessionId: string) => (stage: string, detail?: Record<string, unknown>) => void;
|
|
11
|
+
export declare const voiceTimingEnabled: () => boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -71,6 +71,7 @@ export { createVoiceSessionListRoutes, createVoiceSessionReplayHTMLHandler, crea
|
|
|
71
71
|
export { createVoiceAgent, createVoiceAgentSquad, createVoiceAgentTool, } from "./core/agent";
|
|
72
72
|
export { createPersonaVoiceCaller, createScriptedVoiceCaller, renderVoiceSimulationTranscript, runVoiceConversationSimulation, } from "./core/conversationSimulator";
|
|
73
73
|
export type { RunVoiceConversationSimulationInput, VoiceConversationSimulationEndedReason, VoiceConversationSimulationResult, VoicePersonaCallerCompletion, VoiceScriptedCallerStep, VoiceSimulatedSpeaker, VoiceSimulatedTurn, VoiceSimulatorCaller, VoiceSimulatorCallerModel, VoiceSimulatorCallerReply, } from "./core/conversationSimulator";
|
|
74
|
+
export { logVoiceTiming, startVoiceTimer, voiceTimingEnabled, } from "./core/debugTiming";
|
|
74
75
|
export { createVoiceMCPToolset } from "./core/mcpToolset";
|
|
75
76
|
export type { CreateVoiceMCPToolsetOptions, MCPClientLike, MCPToolCallResult, MCPToolContentBlock, MCPToolDefinition, VoiceMCPToolResult, } from "./core/mcpToolset";
|
|
76
77
|
export { createAIVoiceModel } from "./core/aiVoiceModel";
|
package/dist/index.js
CHANGED
|
@@ -3091,6 +3091,21 @@ var toVoiceSessionSummary = (session) => ({
|
|
|
3091
3091
|
// src/core/session.ts
|
|
3092
3092
|
import { Buffer as Buffer2 } from "buffer";
|
|
3093
3093
|
|
|
3094
|
+
// src/core/debugTiming.ts
|
|
3095
|
+
var timingEnabled = () => process.env.ABSOLUTEJS_VOICE_TIMING === "1" || process.env.ABSOLUTEJS_VOICE_TIMING === "true";
|
|
3096
|
+
var emitTiming = (sessionId, stage, elapsedMs, detail) => {
|
|
3097
|
+
if (!timingEnabled())
|
|
3098
|
+
return;
|
|
3099
|
+
const extra = detail ? ` ${JSON.stringify(detail)}` : "";
|
|
3100
|
+
console.info(`[voice][timing] session=${sessionId} ${stage} +${Math.round(elapsedMs)}ms${extra}`);
|
|
3101
|
+
};
|
|
3102
|
+
var logVoiceTiming = (sessionId, stage, elapsedMs, detail) => emitTiming(sessionId, stage, elapsedMs, detail);
|
|
3103
|
+
var startVoiceTimer = (sessionId) => {
|
|
3104
|
+
const startedAt = Date.now();
|
|
3105
|
+
return (stage, detail) => emitTiming(sessionId, stage, Date.now() - startedAt, detail);
|
|
3106
|
+
};
|
|
3107
|
+
var voiceTimingEnabled = () => timingEnabled();
|
|
3108
|
+
|
|
3094
3109
|
// src/core/backchannel.ts
|
|
3095
3110
|
var DEFAULT_CUES = [
|
|
3096
3111
|
{ text: "mm-hmm" },
|
|
@@ -5534,6 +5549,7 @@ var createVoiceSession = (options) => {
|
|
|
5534
5549
|
const onTurnTimeoutMs = options.routeOnTurnTimeoutMs ?? 45000;
|
|
5535
5550
|
let committedOutput;
|
|
5536
5551
|
const onTurnStartedAt = Date.now();
|
|
5552
|
+
logVoiceTiming(session.id, "session.commit-to-onturn", onTurnStartedAt - (turn.committedAt || onTurnStartedAt), { fillerScheduled: fillerTimer !== null });
|
|
5537
5553
|
try {
|
|
5538
5554
|
const onTurnPromise = options.route.onTurn({
|
|
5539
5555
|
api,
|
|
@@ -7446,7 +7462,9 @@ var createVoiceAgent = (options) => {
|
|
|
7446
7462
|
const maxToolRounds = Math.max(0, options.maxToolRounds ?? 2);
|
|
7447
7463
|
const audit = resolveVoiceAgentAuditLogger(options.audit);
|
|
7448
7464
|
const run = async (input) => {
|
|
7465
|
+
const stamp = startVoiceTimer(input.session.id);
|
|
7449
7466
|
const messages = input.messages ?? createHistoryMessages(input.session, input.turn);
|
|
7467
|
+
stamp("agent.history-built", { messages: messages.length });
|
|
7450
7468
|
const toolResults = [];
|
|
7451
7469
|
const baseSystem = typeof options.system === "function" ? await options.system({
|
|
7452
7470
|
context: input.context,
|
|
@@ -7456,9 +7474,11 @@ var createVoiceAgent = (options) => {
|
|
|
7456
7474
|
const system = [baseSystem, input.system].filter((value) => Boolean(value?.trim())).join(`
|
|
7457
7475
|
|
|
7458
7476
|
`) || undefined;
|
|
7477
|
+
stamp("agent.system-resolved", { systemChars: system?.length ?? 0 });
|
|
7459
7478
|
let output = {};
|
|
7460
7479
|
for (let round = 0;round <= maxToolRounds; round += 1) {
|
|
7461
7480
|
const modelStartedAt = Date.now();
|
|
7481
|
+
stamp(`agent.round${round}.generate-start`);
|
|
7462
7482
|
try {
|
|
7463
7483
|
output = await options.model.generate({
|
|
7464
7484
|
agentId: options.id,
|
|
@@ -7474,6 +7494,11 @@ var createVoiceAgent = (options) => {
|
|
|
7474
7494
|
})),
|
|
7475
7495
|
turn: input.turn
|
|
7476
7496
|
});
|
|
7497
|
+
stamp(`agent.round${round}.generate-done`, {
|
|
7498
|
+
ms: Date.now() - modelStartedAt,
|
|
7499
|
+
textChars: output.assistantText?.length ?? 0,
|
|
7500
|
+
toolCalls: output.toolCalls?.length ?? 0
|
|
7501
|
+
});
|
|
7477
7502
|
await audit?.providerCall({
|
|
7478
7503
|
actor: {
|
|
7479
7504
|
id: options.id,
|
|
@@ -7487,6 +7512,9 @@ var createVoiceAgent = (options) => {
|
|
|
7487
7512
|
sessionId: input.session.id
|
|
7488
7513
|
});
|
|
7489
7514
|
} catch (error) {
|
|
7515
|
+
stamp(`agent.round${round}.generate-error`, {
|
|
7516
|
+
ms: Date.now() - modelStartedAt
|
|
7517
|
+
});
|
|
7490
7518
|
await audit?.providerCall({
|
|
7491
7519
|
actor: {
|
|
7492
7520
|
id: options.id,
|
|
@@ -45368,6 +45396,7 @@ var createOpenAIVoiceAssistantModel = (options) => {
|
|
|
45368
45396
|
const timeoutMs = options.timeoutMs ?? 60000;
|
|
45369
45397
|
return {
|
|
45370
45398
|
generate: async (input) => {
|
|
45399
|
+
const stamp = startVoiceTimer(input.session.id);
|
|
45371
45400
|
const ac = new AbortController;
|
|
45372
45401
|
const timer = setTimeout(() => {
|
|
45373
45402
|
ac.abort(new Error(`OpenAI /responses timed out after ${timeoutMs}ms (no completion event received)`));
|
|
@@ -45408,6 +45437,10 @@ var createOpenAIVoiceAssistantModel = (options) => {
|
|
|
45408
45437
|
clearTimeout(timer);
|
|
45409
45438
|
throw error;
|
|
45410
45439
|
}
|
|
45440
|
+
stamp("openai.fetch-returned", {
|
|
45441
|
+
messages: input.messages.length,
|
|
45442
|
+
status: response.status
|
|
45443
|
+
});
|
|
45411
45444
|
if (!response.ok) {
|
|
45412
45445
|
clearTimeout(timer);
|
|
45413
45446
|
throw createHTTPError("OpenAI", response);
|
|
@@ -45415,11 +45448,23 @@ var createOpenAIVoiceAssistantModel = (options) => {
|
|
|
45415
45448
|
let assistantText;
|
|
45416
45449
|
let toolCalls;
|
|
45417
45450
|
let usage;
|
|
45451
|
+
let firstDeltaSeen = false;
|
|
45452
|
+
const onTextDelta = input.onTextDelta ? (delta) => {
|
|
45453
|
+
if (!firstDeltaSeen) {
|
|
45454
|
+
firstDeltaSeen = true;
|
|
45455
|
+
stamp("openai.first-delta");
|
|
45456
|
+
}
|
|
45457
|
+
input.onTextDelta?.(delta);
|
|
45458
|
+
} : undefined;
|
|
45418
45459
|
try {
|
|
45419
|
-
({ assistantText, toolCalls, usage } = await consumeOpenAIResponsesStream(response,
|
|
45460
|
+
({ assistantText, toolCalls, usage } = await consumeOpenAIResponsesStream(response, onTextDelta, {
|
|
45420
45461
|
signal: ac.signal,
|
|
45421
45462
|
inactivityMs: 1e4
|
|
45422
45463
|
}));
|
|
45464
|
+
stamp("openai.stream-done", {
|
|
45465
|
+
textChars: assistantText?.length ?? 0,
|
|
45466
|
+
toolCalls: toolCalls.length
|
|
45467
|
+
});
|
|
45423
45468
|
} finally {
|
|
45424
45469
|
clearTimeout(timer);
|
|
45425
45470
|
}
|
|
@@ -52391,6 +52436,7 @@ export {
|
|
|
52391
52436
|
wrapVoiceHTMLInHTMXContainer,
|
|
52392
52437
|
withVoiceOpsTaskId,
|
|
52393
52438
|
withVoiceIntegrationEventId,
|
|
52439
|
+
voiceTimingEnabled,
|
|
52394
52440
|
voiceTelephonyOutcomeToRouteResult,
|
|
52395
52441
|
voiceObservabilityExportSchemaVersion,
|
|
52396
52442
|
voiceObservabilityExportSchemaId,
|
|
@@ -52448,6 +52494,7 @@ export {
|
|
|
52448
52494
|
summarizeVoiceAuditSinkDeliveries,
|
|
52449
52495
|
summarizeVoiceAssistantRuns,
|
|
52450
52496
|
summarizeVoiceAssistantHealth,
|
|
52497
|
+
startVoiceTimer,
|
|
52451
52498
|
startVoiceOpsTask,
|
|
52452
52499
|
signVoiceWebhookBody,
|
|
52453
52500
|
signVoiceTwilioWebhook,
|
|
@@ -52648,6 +52695,7 @@ export {
|
|
|
52648
52695
|
matchesVoiceOpsTaskAssignmentRule,
|
|
52649
52696
|
markVoiceOpsTaskSLABreached,
|
|
52650
52697
|
mapVoiceProofTargetsWithConcurrency,
|
|
52698
|
+
logVoiceTiming,
|
|
52651
52699
|
loadVoiceRealCallProfileEvidenceFromTraceStore,
|
|
52652
52700
|
loadVoiceRealCallProfileEvidenceFromStore,
|
|
52653
52701
|
loadVoiceObservabilityExportReplaySource,
|
package/dist/testing/index.js
CHANGED
|
@@ -4195,6 +4195,21 @@ var createVoiceIOProviderFailureSimulator = (options) => {
|
|
|
4195
4195
|
run
|
|
4196
4196
|
};
|
|
4197
4197
|
};
|
|
4198
|
+
// src/core/debugTiming.ts
|
|
4199
|
+
var timingEnabled = () => process.env.ABSOLUTEJS_VOICE_TIMING === "1" || process.env.ABSOLUTEJS_VOICE_TIMING === "true";
|
|
4200
|
+
var emitTiming = (sessionId, stage, elapsedMs, detail) => {
|
|
4201
|
+
if (!timingEnabled())
|
|
4202
|
+
return;
|
|
4203
|
+
const extra = detail ? ` ${JSON.stringify(detail)}` : "";
|
|
4204
|
+
console.info(`[voice][timing] session=${sessionId} ${stage} +${Math.round(elapsedMs)}ms${extra}`);
|
|
4205
|
+
};
|
|
4206
|
+
var logVoiceTiming = (sessionId, stage, elapsedMs, detail) => emitTiming(sessionId, stage, elapsedMs, detail);
|
|
4207
|
+
var startVoiceTimer = (sessionId) => {
|
|
4208
|
+
const startedAt = Date.now();
|
|
4209
|
+
return (stage, detail) => emitTiming(sessionId, stage, Date.now() - startedAt, detail);
|
|
4210
|
+
};
|
|
4211
|
+
var voiceTimingEnabled = () => timingEnabled();
|
|
4212
|
+
|
|
4198
4213
|
// src/core/modelAdapters.ts
|
|
4199
4214
|
var isVoiceProviderRoutingPolicyPreset = (value) => value === "balanced" || value === "cost-cap" || value === "cost-first" || value === "latency-first" || value === "quality-first";
|
|
4200
4215
|
var resolveVoiceProviderRoutingPolicyPreset = (preset, options = {}) => {
|
|
@@ -4905,6 +4920,7 @@ var createOpenAIVoiceAssistantModel = (options) => {
|
|
|
4905
4920
|
const timeoutMs = options.timeoutMs ?? 60000;
|
|
4906
4921
|
return {
|
|
4907
4922
|
generate: async (input) => {
|
|
4923
|
+
const stamp = startVoiceTimer(input.session.id);
|
|
4908
4924
|
const ac = new AbortController;
|
|
4909
4925
|
const timer = setTimeout(() => {
|
|
4910
4926
|
ac.abort(new Error(`OpenAI /responses timed out after ${timeoutMs}ms (no completion event received)`));
|
|
@@ -4945,6 +4961,10 @@ var createOpenAIVoiceAssistantModel = (options) => {
|
|
|
4945
4961
|
clearTimeout(timer);
|
|
4946
4962
|
throw error;
|
|
4947
4963
|
}
|
|
4964
|
+
stamp("openai.fetch-returned", {
|
|
4965
|
+
messages: input.messages.length,
|
|
4966
|
+
status: response.status
|
|
4967
|
+
});
|
|
4948
4968
|
if (!response.ok) {
|
|
4949
4969
|
clearTimeout(timer);
|
|
4950
4970
|
throw createHTTPError("OpenAI", response);
|
|
@@ -4952,11 +4972,23 @@ var createOpenAIVoiceAssistantModel = (options) => {
|
|
|
4952
4972
|
let assistantText;
|
|
4953
4973
|
let toolCalls;
|
|
4954
4974
|
let usage;
|
|
4975
|
+
let firstDeltaSeen = false;
|
|
4976
|
+
const onTextDelta = input.onTextDelta ? (delta) => {
|
|
4977
|
+
if (!firstDeltaSeen) {
|
|
4978
|
+
firstDeltaSeen = true;
|
|
4979
|
+
stamp("openai.first-delta");
|
|
4980
|
+
}
|
|
4981
|
+
input.onTextDelta?.(delta);
|
|
4982
|
+
} : undefined;
|
|
4955
4983
|
try {
|
|
4956
|
-
({ assistantText, toolCalls, usage } = await consumeOpenAIResponsesStream(response,
|
|
4984
|
+
({ assistantText, toolCalls, usage } = await consumeOpenAIResponsesStream(response, onTextDelta, {
|
|
4957
4985
|
signal: ac.signal,
|
|
4958
4986
|
inactivityMs: 1e4
|
|
4959
4987
|
}));
|
|
4988
|
+
stamp("openai.stream-done", {
|
|
4989
|
+
textChars: assistantText?.length ?? 0,
|
|
4990
|
+
toolCalls: toolCalls.length
|
|
4991
|
+
});
|
|
4960
4992
|
} finally {
|
|
4961
4993
|
clearTimeout(timer);
|
|
4962
4994
|
}
|
|
@@ -7676,6 +7708,7 @@ var createVoiceSession = (options) => {
|
|
|
7676
7708
|
const onTurnTimeoutMs = options.routeOnTurnTimeoutMs ?? 45000;
|
|
7677
7709
|
let committedOutput;
|
|
7678
7710
|
const onTurnStartedAt = Date.now();
|
|
7711
|
+
logVoiceTiming(session.id, "session.commit-to-onturn", onTurnStartedAt - (turn.committedAt || onTurnStartedAt), { fillerScheduled: fillerTimer !== null });
|
|
7679
7712
|
try {
|
|
7680
7713
|
const onTurnPromise = options.route.onTurn({
|
|
7681
7714
|
api,
|