@absolutejs/voice 0.0.22-beta.19 → 0.0.22-beta.20

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
@@ -1,6 +1,7 @@
1
1
  export { voice } from './plugin';
2
2
  export { createVoiceAssistant, createVoiceExperiment, summarizeVoiceAssistantRuns } from './assistant';
3
3
  export { createVoiceAssistantHealthHTMLHandler, createVoiceAssistantHealthJSONHandler, createVoiceAssistantHealthRoutes, renderVoiceAssistantHealthHTML, summarizeVoiceAssistantHealth } from './assistantHealth';
4
+ export { createVoiceSessionReplayHTMLHandler, createVoiceSessionReplayJSONHandler, createVoiceSessionReplayRoutes, summarizeVoiceSessionReplay } from './sessionReplay';
4
5
  export { createVoiceAgent, createVoiceAgentSquad, createVoiceAgentTool } from './agent';
5
6
  export { createStoredVoiceCallReviewArtifact, createStoredVoiceExternalObjectMap, createStoredVoiceIntegrationEvent, createStoredVoiceOpsTask, createVoiceFileExternalObjectMapStore, createVoiceFileAssistantMemoryStore, createVoiceFileIntegrationEventStore, createVoiceFileReviewStore, createVoiceFileRuntimeStorage, createVoiceFileSessionStore, createVoiceFileTaskStore, createVoiceFileTraceSinkDeliveryStore, createVoiceFileTraceEventStore } from './fileStore';
6
7
  export { createVoiceAssistantMemoryHandle, createVoiceAssistantMemoryRecord, createVoiceMemoryAssistantMemoryStore, resolveVoiceAssistantMemoryNamespace } from './assistantMemory';
@@ -29,6 +30,7 @@ export { createVoiceCallReviewFromLiveTelephonyReport, createVoiceCallReviewReco
29
30
  export type { VoiceAssistant, VoiceAssistantArtifactPlan, VoiceAssistantExperiment, VoiceAssistantExperimentOptions, VoiceAssistantGuardrailInput, VoiceAssistantGuardrails, VoiceAssistantMemoryLifecycle, VoiceAssistantMemoryLifecycleInput, VoiceAssistantOptions, VoiceAssistantOutputGuardrailInput, VoiceAssistantPreset, VoiceAssistantRunsSummary, VoiceAssistantRunSummary, VoiceAssistantVariant } from './assistant';
30
31
  export type { VoiceAssistantHealthFailure, VoiceAssistantHealthHTMLHandlerOptions, VoiceAssistantHealthRoutesOptions, VoiceAssistantHealthSummary, VoiceAssistantHealthSummaryOptions } from './assistantHealth';
31
32
  export type { VoiceAssistantMemoryBinding, VoiceAssistantMemoryHandle, VoiceAssistantMemoryOptions, VoiceAssistantMemoryRecord, VoiceAssistantMemoryStore } from './assistantMemory';
33
+ export type { VoiceSessionReplay, VoiceSessionReplayHTMLHandlerOptions, VoiceSessionReplayOptions, VoiceSessionReplayRoutesOptions, VoiceSessionReplayTurn } from './sessionReplay';
32
34
  export type { AnthropicVoiceAssistantModelOptions, GeminiVoiceAssistantModelOptions, OpenAIVoiceAssistantModelOptions, VoiceProviderRouterEvent, VoiceProviderRouterFallbackMode, VoiceProviderRouterHealthOptions, VoiceProviderRouterOptions, VoiceProviderRouterPolicy, VoiceProviderRouterProviderHealth, VoiceProviderRouterProviderProfile, VoiceJSONAssistantModelHandler, VoiceJSONAssistantModelOptions } from './modelAdapters';
33
35
  export type { VoiceProviderHealthStatus, VoiceProviderHealthSummary, VoiceProviderHealthSummaryOptions } from './providerHealth';
34
36
  export type { VoiceAgent, VoiceAgentMessage, VoiceAgentMessageRole, VoiceAgentModel, VoiceAgentModelInput, VoiceAgentModelOutput, VoiceAgentOptions, VoiceAgentRunResult, VoiceAgentSquadOptions, VoiceAgentTool, VoiceAgentToolCall, VoiceAgentToolResult } from './agent';
package/dist/index.js CHANGED
@@ -6387,9 +6387,8 @@ var createVoiceAssistantHealthRoutes = (options) => {
6387
6387
  }
6388
6388
  return routes;
6389
6389
  };
6390
- // src/fileStore.ts
6391
- import { mkdir, readFile, readdir, rename, rm, writeFile } from "fs/promises";
6392
- import { join } from "path";
6390
+ // src/sessionReplay.ts
6391
+ import { Elysia as Elysia4 } from "elysia";
6393
6392
 
6394
6393
  // src/trace.ts
6395
6394
  var createVoiceTraceEventId = (event) => [
@@ -7055,7 +7054,119 @@ var buildVoiceTraceReplay = (events, options = {}) => ({
7055
7054
  summary: summarizeVoiceTrace(options.redact ? redactVoiceTraceEvents(events, options.redact) : events)
7056
7055
  });
7057
7056
 
7057
+ // src/sessionReplay.ts
7058
+ var getString3 = (value) => typeof value === "string" ? value : undefined;
7059
+ var buildReplayTurns = (events) => {
7060
+ const turns = new Map;
7061
+ const getTurn = (turnId) => {
7062
+ const existing = turns.get(turnId);
7063
+ if (existing) {
7064
+ return existing;
7065
+ }
7066
+ const turn = {
7067
+ assistantReplies: [],
7068
+ errors: [],
7069
+ id: turnId,
7070
+ modelCalls: [],
7071
+ tools: [],
7072
+ transcripts: []
7073
+ };
7074
+ turns.set(turnId, turn);
7075
+ return turn;
7076
+ };
7077
+ for (const event of events) {
7078
+ const turnId = event.turnId ?? "session";
7079
+ const turn = getTurn(turnId);
7080
+ switch (event.type) {
7081
+ case "turn.transcript":
7082
+ turn.transcripts.push({
7083
+ isFinal: event.payload.isFinal === true,
7084
+ text: getString3(event.payload.text)
7085
+ });
7086
+ break;
7087
+ case "turn.committed":
7088
+ turn.committedText = getString3(event.payload.text);
7089
+ break;
7090
+ case "turn.assistant": {
7091
+ const text = getString3(event.payload.text);
7092
+ if (text) {
7093
+ turn.assistantReplies.push(text);
7094
+ }
7095
+ break;
7096
+ }
7097
+ case "agent.model":
7098
+ case "assistant.run":
7099
+ turn.modelCalls.push(event.payload);
7100
+ break;
7101
+ case "agent.tool":
7102
+ turn.tools.push(event.payload);
7103
+ break;
7104
+ case "session.error":
7105
+ turn.errors.push(event.payload);
7106
+ break;
7107
+ }
7108
+ }
7109
+ return [...turns.values()];
7110
+ };
7111
+ var summarizeVoiceSessionReplay = async (options) => {
7112
+ const sourceEvents = options.events ?? await options.store?.list({ sessionId: options.sessionId }) ?? [];
7113
+ const events = filterVoiceTraceEvents(sourceEvents, {
7114
+ sessionId: options.sessionId
7115
+ });
7116
+ const replay = buildVoiceTraceReplay(events, {
7117
+ evaluation: options.evaluation,
7118
+ redact: options.redact,
7119
+ title: options.title ?? `Voice Session ${options.sessionId}`
7120
+ });
7121
+ const startedAt = replay.summary.startedAt;
7122
+ return {
7123
+ evaluation: replay.evaluation,
7124
+ events,
7125
+ html: replay.html,
7126
+ markdown: replay.markdown,
7127
+ sessionId: options.sessionId,
7128
+ summary: replay.summary,
7129
+ timeline: events.map((event) => ({
7130
+ at: event.at,
7131
+ offsetMs: startedAt === undefined ? undefined : Math.max(0, event.at - startedAt),
7132
+ payload: event.payload,
7133
+ turnId: event.turnId,
7134
+ type: event.type
7135
+ })),
7136
+ turns: buildReplayTurns(events)
7137
+ };
7138
+ };
7139
+ var createVoiceSessionReplayJSONHandler = (options) => async ({ params }) => summarizeVoiceSessionReplay({
7140
+ ...options,
7141
+ sessionId: params.sessionId ?? ""
7142
+ });
7143
+ var createVoiceSessionReplayHTMLHandler = (options) => async ({ params }) => {
7144
+ const replay = await summarizeVoiceSessionReplay({
7145
+ ...options,
7146
+ sessionId: params.sessionId ?? ""
7147
+ });
7148
+ const body = await (options.render?.(replay) ?? replay.html);
7149
+ return new Response(body, {
7150
+ headers: {
7151
+ "Content-Type": "text/html; charset=utf-8",
7152
+ ...options.headers
7153
+ }
7154
+ });
7155
+ };
7156
+ var createVoiceSessionReplayRoutes = (options) => {
7157
+ const path = options.path ?? "/api/voice-sessions/:sessionId/replay";
7158
+ const htmlPath = options.htmlPath === undefined ? `${path}/htmx` : options.htmlPath;
7159
+ const routes = new Elysia4({
7160
+ name: options.name ?? "absolutejs-voice-session-replay"
7161
+ }).get(path, createVoiceSessionReplayJSONHandler(options));
7162
+ if (htmlPath) {
7163
+ routes.get(htmlPath, createVoiceSessionReplayHTMLHandler(options));
7164
+ }
7165
+ return routes;
7166
+ };
7058
7167
  // src/fileStore.ts
7168
+ import { mkdir, readFile, readdir, rename, rm, writeFile } from "fs/promises";
7169
+ import { join } from "path";
7059
7170
  var listJsonFiles = async (directory) => {
7060
7171
  try {
7061
7172
  const entries = await readdir(directory, {
@@ -10591,6 +10702,7 @@ export {
10591
10702
  transcodePCMToTwilioOutboundPayload,
10592
10703
  summarizeVoiceTraceSinkDeliveries,
10593
10704
  summarizeVoiceTrace,
10705
+ summarizeVoiceSessionReplay,
10594
10706
  summarizeVoiceProviderHealth,
10595
10707
  summarizeVoiceOpsTasks,
10596
10708
  summarizeVoiceOpsTaskQueue,
@@ -10657,6 +10769,9 @@ export {
10657
10769
  createVoiceTaskUpdatedEvent,
10658
10770
  createVoiceTaskSLABreachedEvent,
10659
10771
  createVoiceTaskCreatedEvent,
10772
+ createVoiceSessionReplayRoutes,
10773
+ createVoiceSessionReplayJSONHandler,
10774
+ createVoiceSessionReplayHTMLHandler,
10660
10775
  createVoiceSessionRecord,
10661
10776
  createVoiceSession,
10662
10777
  createVoiceSTTRoutingCorrectionHandler,
@@ -0,0 +1,94 @@
1
+ import { Elysia } from 'elysia';
2
+ import { type StoredVoiceTraceEvent, type VoiceTraceEvaluationOptions, type VoiceTraceEventStore, type VoiceTraceRedactionConfig, type VoiceTraceSummary, type VoiceTraceEvaluation } from './trace';
3
+ export type VoiceSessionReplayTurn = {
4
+ assistantReplies: string[];
5
+ committedText?: string;
6
+ errors: Array<Record<string, unknown>>;
7
+ id: string;
8
+ modelCalls: Array<Record<string, unknown>>;
9
+ tools: Array<Record<string, unknown>>;
10
+ transcripts: Array<{
11
+ isFinal: boolean;
12
+ text?: string;
13
+ }>;
14
+ };
15
+ export type VoiceSessionReplay = {
16
+ evaluation: VoiceTraceEvaluation;
17
+ events: StoredVoiceTraceEvent[];
18
+ html: string;
19
+ markdown: string;
20
+ sessionId: string;
21
+ summary: VoiceTraceSummary;
22
+ timeline: Array<{
23
+ at: number;
24
+ offsetMs?: number;
25
+ payload: Record<string, unknown>;
26
+ turnId?: string;
27
+ type: StoredVoiceTraceEvent['type'];
28
+ }>;
29
+ turns: VoiceSessionReplayTurn[];
30
+ };
31
+ export type VoiceSessionReplayOptions = {
32
+ evaluation?: VoiceTraceEvaluationOptions;
33
+ events?: StoredVoiceTraceEvent[];
34
+ redact?: VoiceTraceRedactionConfig;
35
+ sessionId: string;
36
+ store?: VoiceTraceEventStore;
37
+ title?: string;
38
+ };
39
+ export type VoiceSessionReplayHTMLHandlerOptions = Omit<VoiceSessionReplayOptions, 'sessionId'> & {
40
+ headers?: HeadersInit;
41
+ render?: (replay: VoiceSessionReplay) => string | Promise<string>;
42
+ };
43
+ export type VoiceSessionReplayRoutesOptions = VoiceSessionReplayHTMLHandlerOptions & {
44
+ htmlPath?: false | string;
45
+ name?: string;
46
+ path?: string;
47
+ };
48
+ export declare const summarizeVoiceSessionReplay: (options: VoiceSessionReplayOptions) => Promise<VoiceSessionReplay>;
49
+ export declare const createVoiceSessionReplayJSONHandler: (options: Omit<VoiceSessionReplayOptions, "sessionId">) => ({ params }: {
50
+ params: Record<string, string | undefined>;
51
+ }) => Promise<VoiceSessionReplay>;
52
+ export declare const createVoiceSessionReplayHTMLHandler: (options: VoiceSessionReplayHTMLHandlerOptions) => ({ params }: {
53
+ params: Record<string, string | undefined>;
54
+ }) => Promise<Response>;
55
+ export declare const createVoiceSessionReplayRoutes: (options: VoiceSessionReplayRoutesOptions) => Elysia<"", {
56
+ decorator: {};
57
+ store: {};
58
+ derive: {};
59
+ resolve: {};
60
+ }, {
61
+ typebox: {};
62
+ error: {};
63
+ }, {
64
+ schema: {};
65
+ standaloneSchema: {};
66
+ macro: {};
67
+ macroFn: {};
68
+ parser: {};
69
+ response: {};
70
+ }, {
71
+ [x: string]: {
72
+ get: {
73
+ body: unknown;
74
+ params: {};
75
+ query: unknown;
76
+ headers: unknown;
77
+ response: {
78
+ 200: VoiceSessionReplay;
79
+ };
80
+ };
81
+ };
82
+ }, {
83
+ derive: {};
84
+ resolve: {};
85
+ schema: {};
86
+ standaloneSchema: {};
87
+ response: {};
88
+ }, {
89
+ derive: {};
90
+ resolve: {};
91
+ schema: {};
92
+ standaloneSchema: {};
93
+ response: {};
94
+ }>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.19",
3
+ "version": "0.0.22-beta.20",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",