@absolutejs/voice 0.0.22-beta.184 → 0.0.22-beta.185

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,66 @@
1
+ import { Elysia } from 'elysia';
2
+ import { type VoiceOperationsRecord, type VoiceOperationsRecordOptions } from './operationsRecord';
3
+ import { type VoiceTraceRedactionConfig } from './trace';
4
+ export type VoiceIncidentBundleFormat = 'json' | 'markdown';
5
+ export type VoiceIncidentBundle = {
6
+ auditMarkdown?: string;
7
+ exportedAt: number;
8
+ formatVersion: 1;
9
+ markdown: string;
10
+ record: VoiceOperationsRecord;
11
+ redacted: boolean;
12
+ sessionId: string;
13
+ summary: VoiceIncidentBundleSummary;
14
+ traceMarkdown: string;
15
+ };
16
+ export type VoiceIncidentBundleSummary = {
17
+ auditEvents: number;
18
+ durationMs?: number;
19
+ errors: number;
20
+ handoffs: number;
21
+ providers: string[];
22
+ sessionId: string;
23
+ status: VoiceOperationsRecord['status'];
24
+ tools: number;
25
+ traceEvents: number;
26
+ turns: number;
27
+ };
28
+ export type VoiceIncidentBundleOptions = VoiceOperationsRecordOptions & {
29
+ redact?: VoiceTraceRedactionConfig;
30
+ title?: string;
31
+ };
32
+ export type VoiceIncidentBundleRoutesOptions = Omit<VoiceIncidentBundleOptions, 'sessionId'> & {
33
+ headers?: HeadersInit;
34
+ markdownPath?: false | string;
35
+ name?: string;
36
+ path?: string;
37
+ };
38
+ export declare const buildVoiceIncidentBundle: (options: VoiceIncidentBundleOptions) => Promise<VoiceIncidentBundle>;
39
+ export declare const createVoiceIncidentBundleRoutes: (options: VoiceIncidentBundleRoutesOptions) => Elysia<"", {
40
+ decorator: {};
41
+ store: {};
42
+ derive: {};
43
+ resolve: {};
44
+ }, {
45
+ typebox: {};
46
+ error: {};
47
+ }, {
48
+ schema: {};
49
+ standaloneSchema: {};
50
+ macro: {};
51
+ macroFn: {};
52
+ parser: {};
53
+ response: {};
54
+ }, {}, {
55
+ derive: {};
56
+ resolve: {};
57
+ schema: {};
58
+ standaloneSchema: {};
59
+ response: {};
60
+ }, {
61
+ derive: {};
62
+ resolve: {};
63
+ schema: {};
64
+ standaloneSchema: {};
65
+ response: {};
66
+ }>;
package/dist/index.d.ts CHANGED
@@ -49,6 +49,7 @@ export { createVoiceReadinessProfile, recommendVoiceReadinessProfile } from './r
49
49
  export { buildVoiceProviderContractMatrix, createVoiceProviderContractMatrixHTMLHandler, createVoiceProviderContractMatrixJSONHandler, createVoiceProviderContractMatrixPreset, createVoiceProviderContractMatrixRoutes, evaluateVoiceProviderStackGaps, renderVoiceProviderContractMatrixHTML, recommendVoiceProviderStack } from './providerStackRecommendations';
50
50
  export { buildVoiceOpsConsoleReport, createVoiceOpsConsoleRoutes, renderVoiceOpsConsoleHTML } from './opsConsoleRoutes';
51
51
  export { buildVoiceOperationsRecord, createVoiceOperationsRecordRoutes, renderVoiceOperationsRecordHTML } from './operationsRecord';
52
+ export { buildVoiceIncidentBundle, createVoiceIncidentBundleRoutes } from './incidentBundle';
52
53
  export { summarizeVoiceOpsStatus } from './opsStatus';
53
54
  export { createVoiceOpsStatusRoutes, renderVoiceOpsStatusHTML } from './opsStatusRoutes';
54
55
  export { createVoiceQualityRoutes, evaluateVoiceQuality, renderVoiceQualityHTML } from './qualityRoutes';
@@ -109,6 +110,7 @@ export type { VoiceProductionReadinessAction, VoiceProductionReadinessAuditOptio
109
110
  export type { VoiceReadinessProfileName, VoiceReadinessProfileOptions, VoiceReadinessProfileRecommendation, VoiceReadinessProfileRecommendationScore, VoiceReadinessProfileRoutesOptions } from './readinessProfiles';
110
111
  export type { VoiceProviderStackChoice, VoiceProviderStackCapabilities, VoiceProviderStackCapabilityGap, VoiceProviderStackCapabilityGapInput, VoiceProviderStackCapabilityGapReport, VoiceProviderContractCheck, VoiceProviderContractCheckStatus, VoiceProviderContractDefinition, VoiceProviderContractMatrixHandlerOptions, VoiceProviderContractMatrixHTMLHandlerOptions, VoiceProviderContractMatrixInput, VoiceProviderContractMatrixPresetOptions, VoiceProviderContractMatrixReport, VoiceProviderContractMatrixRoutesOptions, VoiceProviderContractMatrixRow, VoiceProviderStackInput, VoiceProviderStackKind, VoiceProviderStackRecommendation } from './providerStackRecommendations';
111
112
  export type { VoiceOperationsRecord, VoiceOperationsRecordAgentHandoff, VoiceOperationsRecordAuditSummary, VoiceOperationsRecordOptions, VoiceOperationsRecordOutcome, VoiceOperationsRecordRoutesOptions, VoiceOperationsRecordStatus, VoiceOperationsRecordTool } from './operationsRecord';
113
+ export type { VoiceIncidentBundle, VoiceIncidentBundleFormat, VoiceIncidentBundleOptions, VoiceIncidentBundleRoutesOptions, VoiceIncidentBundleSummary } from './incidentBundle';
112
114
  export type { VoiceQualityLink, VoiceQualityMetric, VoiceQualityReport, VoiceQualityRoutesOptions, VoiceQualityStatus, VoiceQualityThresholds } from './qualityRoutes';
113
115
  export type { VoiceResilienceIOSimulator, VoiceResilienceLink, VoiceResiliencePageData, VoiceResilienceRoutesOptions, VoiceResilienceSimulationProvider, VoiceRoutingKindSummary, VoiceRoutingDecisionSummary, VoiceRoutingDecisionSummaryOptions, VoiceRoutingEvent, VoiceRoutingEventKind, VoiceRoutingSessionSummary, VoiceRoutingSessionSummaryOptions } from './resilienceRoutes';
114
116
  export type { VoiceIOProviderRouterEvent, VoiceIOProviderRouterOptions, VoiceIOProviderRouterPolicy, VoiceIOProviderRouterPolicyConfig, VoiceSTTProviderRouterOptions, VoiceTTSProviderRouterOptions } from './providerAdapters';
package/dist/index.js CHANGED
@@ -22644,6 +22644,159 @@ var createVoiceOperationsRecordRoutes = (options) => {
22644
22644
  }
22645
22645
  return routes;
22646
22646
  };
22647
+ // src/incidentBundle.ts
22648
+ import { Elysia as Elysia38 } from "elysia";
22649
+ var buildSummary = (record) => ({
22650
+ auditEvents: record.audit?.total ?? 0,
22651
+ durationMs: record.summary.callDurationMs,
22652
+ errors: record.summary.errorCount,
22653
+ handoffs: record.handoffs.length,
22654
+ providers: record.providers.map((provider) => provider.provider),
22655
+ sessionId: record.sessionId,
22656
+ status: record.status,
22657
+ tools: record.tools.length,
22658
+ traceEvents: record.traceEvents.length,
22659
+ turns: record.summary.turnCount
22660
+ });
22661
+ var renderIncidentMarkdown = (input) => {
22662
+ const lines = [
22663
+ `# ${input.title ?? `Voice Incident ${input.summary.sessionId}`}`,
22664
+ "",
22665
+ `Session: ${input.summary.sessionId}`,
22666
+ `Status: ${input.summary.status}`,
22667
+ `Trace events: ${input.summary.traceEvents}`,
22668
+ `Audit events: ${input.summary.auditEvents}`,
22669
+ `Turns: ${input.summary.turns}`,
22670
+ `Errors: ${input.summary.errors}`,
22671
+ `Handoffs: ${input.summary.handoffs}`,
22672
+ `Tools: ${input.summary.tools}`,
22673
+ `Providers: ${input.summary.providers.join(", ") || "none"}`,
22674
+ input.summary.durationMs === undefined ? undefined : `Duration: ${input.summary.durationMs}ms`,
22675
+ "",
22676
+ "## Outcome",
22677
+ "",
22678
+ `- Assistant replies: ${input.record.outcome.assistantReplies}`,
22679
+ `- Complete: ${input.record.outcome.complete ? "yes" : "no"}`,
22680
+ `- Escalated: ${input.record.outcome.escalated ? "yes" : "no"}`,
22681
+ `- Transferred: ${input.record.outcome.transferred ? "yes" : "no"}`,
22682
+ `- Voicemail: ${input.record.outcome.voicemail ? "yes" : "no"}`,
22683
+ `- No answer: ${input.record.outcome.noAnswer ? "yes" : "no"}`,
22684
+ "",
22685
+ "## Handoffs",
22686
+ "",
22687
+ ...input.record.handoffs.length ? input.record.handoffs.map((handoff) => `- ${handoff.fromAgentId ?? "unknown"} -> ${handoff.targetAgentId ?? "unknown"} ${handoff.status ?? ""} ${handoff.summary ?? handoff.reason ?? ""}`.trim()) : ["- none"],
22688
+ "",
22689
+ "## Tools",
22690
+ "",
22691
+ ...input.record.tools.length ? input.record.tools.map((tool) => `- ${tool.toolName ?? "tool"} ${tool.status ?? ""} ${tool.elapsedMs === undefined ? "" : `${tool.elapsedMs}ms`} ${tool.error ?? ""}`.trim()) : ["- none"],
22692
+ "",
22693
+ "## Trace Evidence",
22694
+ "",
22695
+ input.traceMarkdown,
22696
+ ""
22697
+ ].filter((line) => line !== undefined);
22698
+ if (input.auditMarkdown) {
22699
+ lines.push("## Audit Evidence", "", input.auditMarkdown);
22700
+ }
22701
+ return lines.join(`
22702
+ `);
22703
+ };
22704
+ var redactRecordValue = (value, redactedEvents, redact) => {
22705
+ if (!redact) {
22706
+ return value;
22707
+ }
22708
+ if (Array.isArray(value)) {
22709
+ return value.map((item) => redactRecordValue(item, redactedEvents, redact));
22710
+ }
22711
+ if (typeof value === "string") {
22712
+ return redactVoiceTraceText(value, redact);
22713
+ }
22714
+ if (typeof value === "object" && value) {
22715
+ return Object.fromEntries(Object.entries(value).map(([key, entryValue]) => [
22716
+ key,
22717
+ key === "events" || key === "traceEvents" ? redactedEvents : redactRecordValue(entryValue, redactedEvents, redact)
22718
+ ]));
22719
+ }
22720
+ return value;
22721
+ };
22722
+ var redactOperationsRecord = (record, input) => ({
22723
+ ...redactRecordValue(record, input.traceEvents, input.redact),
22724
+ audit: record.audit ? {
22725
+ ...record.audit,
22726
+ events: input.auditEvents ?? []
22727
+ } : undefined,
22728
+ traceEvents: input.traceEvents
22729
+ });
22730
+ var buildVoiceIncidentBundle = async (options) => {
22731
+ const record = await buildVoiceOperationsRecord(options);
22732
+ const redactedTraceEvents = options.redact ? redactVoiceTraceEvents(record.traceEvents, options.redact) : record.traceEvents;
22733
+ const redactedAuditEvents = options.redact && record.audit ? redactVoiceAuditEvents(record.audit.events, options.redact) : record.audit?.events;
22734
+ const redactedRecord = redactOperationsRecord(record, {
22735
+ auditEvents: redactedAuditEvents,
22736
+ redact: options.redact,
22737
+ traceEvents: redactedTraceEvents
22738
+ });
22739
+ const summary = buildSummary(redactedRecord);
22740
+ const traceMarkdown = renderVoiceTraceMarkdown(record.traceEvents, {
22741
+ evaluation: options.evaluation,
22742
+ redact: options.redact,
22743
+ title: `Voice Incident Trace ${options.sessionId}`
22744
+ });
22745
+ const auditMarkdown = record.audit ? renderVoiceAuditMarkdown(record.audit.events, {
22746
+ redact: options.redact,
22747
+ title: `Voice Incident Audit ${options.sessionId}`
22748
+ }) : undefined;
22749
+ const markdown = renderIncidentMarkdown({
22750
+ auditMarkdown,
22751
+ record: redactedRecord,
22752
+ summary,
22753
+ title: options.title,
22754
+ traceMarkdown
22755
+ });
22756
+ return {
22757
+ auditMarkdown,
22758
+ exportedAt: Date.now(),
22759
+ formatVersion: 1,
22760
+ markdown,
22761
+ record: redactedRecord,
22762
+ redacted: Boolean(options.redact),
22763
+ sessionId: options.sessionId,
22764
+ summary,
22765
+ traceMarkdown
22766
+ };
22767
+ };
22768
+ var createVoiceIncidentBundleRoutes = (options) => {
22769
+ const path = options.path ?? "/api/voice-incidents/:sessionId";
22770
+ const markdownPath = options.markdownPath === undefined ? "/voice-incidents/:sessionId/markdown" : options.markdownPath;
22771
+ const routes = new Elysia38({
22772
+ name: options.name ?? "absolutejs-voice-incident-bundle"
22773
+ });
22774
+ const getSessionId = (params) => params.sessionId ?? "";
22775
+ const buildBundle = (sessionId) => buildVoiceIncidentBundle({
22776
+ audit: options.audit,
22777
+ evaluation: options.evaluation,
22778
+ events: options.events,
22779
+ redact: options.redact,
22780
+ sessionId,
22781
+ store: options.store,
22782
+ title: options.title
22783
+ });
22784
+ routes.get(path, async ({ params }) => Response.json(await buildBundle(getSessionId(params)), {
22785
+ headers: options.headers
22786
+ }));
22787
+ if (markdownPath) {
22788
+ routes.get(markdownPath, async ({ params }) => {
22789
+ const bundle = await buildBundle(getSessionId(params));
22790
+ return new Response(bundle.markdown, {
22791
+ headers: {
22792
+ "Content-Type": "text/markdown; charset=utf-8",
22793
+ ...options.headers
22794
+ }
22795
+ });
22796
+ });
22797
+ }
22798
+ return routes;
22799
+ };
22647
22800
  // src/opsStatus.ts
22648
22801
  var DEFAULT_LINKS2 = [
22649
22802
  {
@@ -22816,7 +22969,7 @@ var summarizeVoiceOpsStatus = async (options) => {
22816
22969
  };
22817
22970
  };
22818
22971
  // src/opsStatusRoutes.ts
22819
- import { Elysia as Elysia38 } from "elysia";
22972
+ import { Elysia as Elysia39 } from "elysia";
22820
22973
  var escapeHtml40 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
22821
22974
  var renderVoiceOpsStatusHTML = (report, options = {}) => {
22822
22975
  const title = options.title ?? "AbsoluteJS Voice Ops Status";
@@ -22828,7 +22981,7 @@ var renderVoiceOpsStatusHTML = (report, options = {}) => {
22828
22981
  };
22829
22982
  var createVoiceOpsStatusRoutes = (options) => {
22830
22983
  const path = options.path ?? "/api/voice/ops-status";
22831
- const routes = new Elysia38({
22984
+ const routes = new Elysia39({
22832
22985
  name: options.name ?? "absolutejs-voice-ops-status"
22833
22986
  });
22834
22987
  routes.get(path, async () => summarizeVoiceOpsStatus(options));
@@ -23261,7 +23414,7 @@ var createVoiceTTSProviderRouter = (options) => {
23261
23414
  };
23262
23415
  };
23263
23416
  // src/traceDeliveryRoutes.ts
23264
- import { Elysia as Elysia39 } from "elysia";
23417
+ import { Elysia as Elysia40 } from "elysia";
23265
23418
  var escapeHtml41 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
23266
23419
  var getString15 = (value) => typeof value === "string" && value.trim() ? value.trim() : undefined;
23267
23420
  var getNumber10 = (value) => {
@@ -23370,7 +23523,7 @@ var createVoiceTraceDeliveryRoutes = (options) => {
23370
23523
  const path = options.path ?? "/api/voice-trace-deliveries";
23371
23524
  const htmlPath = options.htmlPath === undefined ? "/traces/deliveries" : options.htmlPath;
23372
23525
  const workerPath = options.workerPath === undefined ? `${path}/drain` : options.workerPath;
23373
- const routes = new Elysia39({
23526
+ const routes = new Elysia40({
23374
23527
  name: options.name ?? "absolutejs-voice-trace-deliveries"
23375
23528
  }).get(path, createVoiceTraceDeliveryJSONHandler(options));
23376
23529
  if (htmlPath !== false) {
@@ -23994,7 +24147,7 @@ var createVoiceMemoryStore = () => {
23994
24147
  return { get, getOrCreate, list, remove, set };
23995
24148
  };
23996
24149
  // src/opsWebhook.ts
23997
- import { Elysia as Elysia40 } from "elysia";
24150
+ import { Elysia as Elysia41 } from "elysia";
23998
24151
  var toHex6 = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
23999
24152
  var signVoiceOpsWebhookBody = async (input) => {
24000
24153
  const encoder = new TextEncoder;
@@ -24124,7 +24277,7 @@ var verifyVoiceOpsWebhookSignature = async (input) => {
24124
24277
  };
24125
24278
  var createVoiceOpsWebhookReceiverRoutes = (options = {}) => {
24126
24279
  const path = options.path ?? "/api/voice-ops/webhook";
24127
- return new Elysia40().post(path, async ({ body, request, set }) => {
24280
+ return new Elysia41().post(path, async ({ body, request, set }) => {
24128
24281
  const bodyText = typeof body === "string" ? body : JSON.stringify(body);
24129
24282
  if (options.signingSecret) {
24130
24283
  const verification = await verifyVoiceOpsWebhookSignature({
@@ -25272,6 +25425,7 @@ export {
25272
25425
  createVoiceIntegrationSinkWorker,
25273
25426
  createVoiceIntegrationHTTPSink,
25274
25427
  createVoiceIntegrationEvent,
25428
+ createVoiceIncidentBundleRoutes,
25275
25429
  createVoiceHubSpotTaskUpdateSink,
25276
25430
  createVoiceHubSpotTaskSyncSinks,
25277
25431
  createVoiceHubSpotTaskSink,
@@ -25381,6 +25535,7 @@ export {
25381
25535
  buildVoiceOpsConsoleReport,
25382
25536
  buildVoiceOpsActionHistoryReport,
25383
25537
  buildVoiceOperationsRecord,
25538
+ buildVoiceIncidentBundle,
25384
25539
  buildVoiceDiagnosticsMarkdown,
25385
25540
  buildVoiceDemoReadyReport,
25386
25541
  buildVoiceDeliverySinkReport,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.184",
3
+ "version": "0.0.22-beta.185",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",