@absolutejs/voice 0.0.22-beta.302 → 0.0.22-beta.303

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 CHANGED
@@ -10,7 +10,7 @@ export { createVoiceAuditHTTPSink, createVoiceAuditS3Sink, createVoiceAuditSinkD
10
10
  export { buildVoiceAuditDeliveryReport, createVoiceAuditDeliveryHTMLHandler, createVoiceAuditDeliveryJSONHandler, createVoiceAuditDeliveryRoutes, renderVoiceAuditDeliveryHTML, resolveVoiceAuditDeliveryFilter } from './auditDeliveryRoutes';
11
11
  export { createVoiceBargeInRoutes, renderVoiceBargeInHTML, summarizeVoiceBargeIn } from './bargeInRoutes';
12
12
  export { createVoiceReconnectContractRoutes, renderVoiceReconnectContractHTML, summarizeVoiceReconnectContractSnapshots, runVoiceReconnectContract } from './reconnectContract';
13
- export { assertVoiceRealtimeChannelEvidence, buildVoiceRealtimeChannelReport, createVoiceRealtimeChannelRoutes, evaluateVoiceRealtimeChannelEvidence, renderVoiceRealtimeChannelHTML, renderVoiceRealtimeChannelMarkdown } from './realtimeChannel';
13
+ export { assertVoiceRealtimeChannelEvidence, buildVoiceRealtimeChannelRuntimeSamplesFromTrace, buildVoiceRealtimeChannelReport, createVoiceRealtimeChannelRoutes, evaluateVoiceRealtimeChannelEvidence, renderVoiceRealtimeChannelHTML, renderVoiceRealtimeChannelMarkdown } from './realtimeChannel';
14
14
  export type { VoiceRealtimeChannelAssertionInput, VoiceRealtimeChannelAssertionReport, VoiceRealtimeChannelBrowserCapture, VoiceRealtimeChannelIssue, VoiceRealtimeChannelReport, VoiceRealtimeChannelReportOptions, VoiceRealtimeChannelRoutesOptions, VoiceRealtimeChannelRuntimeSample, VoiceRealtimeChannelStatus } from './realtimeChannel';
15
15
  export { buildVoiceDiagnosticsMarkdown, createVoiceDiagnosticsRoutes, resolveVoiceDiagnosticsTraceFilter } from './diagnosticsRoutes';
16
16
  export { buildVoiceDemoReadyReport, createVoiceDemoReadyRoutes, renderVoiceDemoReadyHTML } from './demoReadyRoutes';
package/dist/index.js CHANGED
@@ -10954,6 +10954,77 @@ var validateFormat = (label, actual, expected, issues) => {
10954
10954
  });
10955
10955
  }
10956
10956
  };
10957
+ var readString = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
10958
+ var readNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
10959
+ var eventHasRealtimeAssistantProof = (event) => event.type === "turn.assistant" && (event.payload.realtimeConfigured === true || event.payload.mode === "realtime" || event.metadata?.realtime === true);
10960
+ var buildVoiceRealtimeChannelRuntimeSamplesFromTrace = (events, options = {}) => {
10961
+ const format = options.format ?? DEFAULT_REALTIME_FORMAT2;
10962
+ const source = options.source ?? "trace-store";
10963
+ const samples = [];
10964
+ const stagesByTurn = new Map;
10965
+ for (const event of events) {
10966
+ if (event.type !== "turn_latency.stage" || !event.turnId) {
10967
+ continue;
10968
+ }
10969
+ const stage = readString(event.payload.stage);
10970
+ if (!stage) {
10971
+ continue;
10972
+ }
10973
+ const stages = stagesByTurn.get(event.turnId) ?? new Map;
10974
+ stages.set(stage, event.at);
10975
+ stagesByTurn.set(event.turnId, stages);
10976
+ }
10977
+ for (const event of [...events].sort((left, right) => left.at - right.at)) {
10978
+ if (event.type === "turn.committed") {
10979
+ samples.push({
10980
+ format,
10981
+ kind: "input-audio",
10982
+ observedAt: event.at,
10983
+ ok: true,
10984
+ sessionId: event.sessionId,
10985
+ source,
10986
+ turnId: event.turnId
10987
+ });
10988
+ samples.push({
10989
+ kind: "turn-commit",
10990
+ observedAt: event.at,
10991
+ ok: true,
10992
+ sessionId: event.sessionId,
10993
+ source,
10994
+ turnId: event.turnId
10995
+ });
10996
+ continue;
10997
+ }
10998
+ if (eventHasRealtimeAssistantProof(event)) {
10999
+ const stages = event.turnId ? stagesByTurn.get(event.turnId) : undefined;
11000
+ const committedAt = stages?.get("turn_committed");
11001
+ const audioAt = stages?.get("assistant_audio_received") ?? stages?.get("tts_send_completed") ?? stages?.get("assistant_text_started") ?? event.at;
11002
+ const latencyMs = committedAt !== undefined ? Math.max(0, audioAt - committedAt) : readNumber(event.payload.elapsedMs);
11003
+ samples.push({
11004
+ format,
11005
+ kind: "assistant-audio",
11006
+ latencyMs,
11007
+ observedAt: event.at,
11008
+ ok: event.payload.status !== "realtime-send-failed",
11009
+ sessionId: event.sessionId,
11010
+ source,
11011
+ turnId: event.turnId
11012
+ });
11013
+ continue;
11014
+ }
11015
+ if (event.type === "client.reconnect") {
11016
+ samples.push({
11017
+ kind: "reconnect",
11018
+ observedAt: event.at,
11019
+ ok: event.payload.status !== "failed",
11020
+ sessionId: event.sessionId,
11021
+ source,
11022
+ turnId: event.turnId
11023
+ });
11024
+ }
11025
+ }
11026
+ return samples;
11027
+ };
10957
11028
  var buildVoiceRealtimeChannelReport = (options) => {
10958
11029
  const expectedInputFormat = options.expectedInputFormat ?? DEFAULT_REALTIME_FORMAT2;
10959
11030
  const expectedOutputFormat = options.expectedOutputFormat ?? expectedInputFormat;
@@ -11121,8 +11192,26 @@ var createVoiceRealtimeChannelRoutes = (options) => {
11121
11192
  const markdownPath = options.markdownPath ?? "/voice/realtime-channel.md";
11122
11193
  const headers = options.headers ?? {};
11123
11194
  const title = options.title ?? "Voice Realtime Channel Proof";
11124
- const report = () => buildVoiceRealtimeChannelReport(options);
11125
- const app = new Elysia9({ name: options.name ?? "voice-realtime-channel" }).get(path, () => new Response(JSON.stringify(report(), null, 2), {
11195
+ const resolveOptions = async () => {
11196
+ const source = typeof options.source === "function" ? await options.source() : options.source ?? options;
11197
+ const {
11198
+ headers: _headers,
11199
+ htmlPath: _htmlPath,
11200
+ markdownPath: _markdownPath,
11201
+ name: _name,
11202
+ path: _path,
11203
+ render: _render,
11204
+ source: _source,
11205
+ title: _title,
11206
+ ...reportOptions
11207
+ } = {
11208
+ ...options,
11209
+ ...source
11210
+ };
11211
+ return reportOptions;
11212
+ };
11213
+ const report = async () => buildVoiceRealtimeChannelReport(await resolveOptions());
11214
+ const app = new Elysia9({ name: options.name ?? "voice-realtime-channel" }).get(path, async () => new Response(JSON.stringify(await report(), null, 2), {
11126
11215
  headers: {
11127
11216
  "content-type": "application/json; charset=utf-8",
11128
11217
  ...headers
@@ -11130,7 +11219,7 @@ var createVoiceRealtimeChannelRoutes = (options) => {
11130
11219
  }));
11131
11220
  if (htmlPath !== false) {
11132
11221
  app.get(htmlPath, async () => {
11133
- const current = report();
11222
+ const current = await report();
11134
11223
  const body = options.render ? await options.render(current) : renderVoiceRealtimeChannelHTML(current, title);
11135
11224
  return new Response(body, {
11136
11225
  headers: {
@@ -11141,7 +11230,7 @@ var createVoiceRealtimeChannelRoutes = (options) => {
11141
11230
  });
11142
11231
  }
11143
11232
  if (markdownPath !== false) {
11144
- app.get(markdownPath, () => new Response(renderVoiceRealtimeChannelMarkdown(report()), {
11233
+ app.get(markdownPath, async () => new Response(renderVoiceRealtimeChannelMarkdown(await report()), {
11145
11234
  headers: {
11146
11235
  "content-type": "text/markdown; charset=utf-8",
11147
11236
  ...headers
@@ -34683,6 +34772,7 @@ export {
34683
34772
  buildVoiceTelephonyWebhookSecurityReport,
34684
34773
  buildVoiceSloReadinessThresholdReport,
34685
34774
  buildVoiceSloCalibrationReport,
34775
+ buildVoiceRealtimeChannelRuntimeSamplesFromTrace,
34686
34776
  buildVoiceRealtimeChannelReport,
34687
34777
  buildVoiceProviderSloReport,
34688
34778
  buildVoiceProviderOrchestrationReport,
@@ -1,12 +1,16 @@
1
1
  import { Elysia } from 'elysia';
2
2
  import type { AudioFormat } from './types';
3
+ import type { StoredVoiceTraceEvent } from './trace';
3
4
  export type VoiceRealtimeChannelStatus = 'fail' | 'pass' | 'warn';
4
5
  export type VoiceRealtimeChannelRuntimeSample = {
5
6
  format?: AudioFormat;
7
+ observedAt?: number;
6
8
  kind: 'assistant-audio' | 'browser-capture' | 'input-audio' | 'reconnect' | 'turn-commit';
7
9
  latencyMs?: number;
8
10
  ok?: boolean;
11
+ sessionId?: string;
9
12
  source?: string;
13
+ turnId?: string;
10
14
  };
11
15
  export type VoiceRealtimeChannelBrowserCapture = {
12
16
  audioContextSampleRateHz?: number;
@@ -78,8 +82,13 @@ export type VoiceRealtimeChannelRoutesOptions = VoiceRealtimeChannelReportOption
78
82
  name?: string;
79
83
  path?: string;
80
84
  render?: (report: VoiceRealtimeChannelReport) => Promise<string> | string;
85
+ source?: (() => Promise<VoiceRealtimeChannelReportOptions> | VoiceRealtimeChannelReportOptions) | VoiceRealtimeChannelReportOptions;
81
86
  title?: string;
82
87
  };
88
+ export declare const buildVoiceRealtimeChannelRuntimeSamplesFromTrace: (events: readonly StoredVoiceTraceEvent[], options?: {
89
+ format?: AudioFormat;
90
+ source?: string;
91
+ }) => VoiceRealtimeChannelRuntimeSample[];
83
92
  export declare const buildVoiceRealtimeChannelReport: (options: VoiceRealtimeChannelReportOptions) => VoiceRealtimeChannelReport;
84
93
  export declare const evaluateVoiceRealtimeChannelEvidence: (report: VoiceRealtimeChannelReport, input?: VoiceRealtimeChannelAssertionInput) => VoiceRealtimeChannelAssertionReport;
85
94
  export declare const assertVoiceRealtimeChannelEvidence: (report: VoiceRealtimeChannelReport, input?: VoiceRealtimeChannelAssertionInput) => VoiceRealtimeChannelAssertionReport;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.302",
3
+ "version": "0.0.22-beta.303",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",