@voice-kit/core 0.1.1 → 0.1.3

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.
Files changed (45) hide show
  1. package/dist/index.cjs +2137 -0
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +1466 -3
  4. package/dist/index.d.ts +1466 -3
  5. package/dist/index.js +2102 -1
  6. package/dist/index.js.map +1 -1
  7. package/package.json +1 -26
  8. package/dist/compliance.cjs +0 -343
  9. package/dist/compliance.cjs.map +0 -1
  10. package/dist/compliance.d.cts +0 -163
  11. package/dist/compliance.d.ts +0 -163
  12. package/dist/compliance.js +0 -335
  13. package/dist/compliance.js.map +0 -1
  14. package/dist/errors.cjs +0 -284
  15. package/dist/errors.cjs.map +0 -1
  16. package/dist/errors.d.cts +0 -175
  17. package/dist/errors.d.ts +0 -175
  18. package/dist/errors.js +0 -262
  19. package/dist/errors.js.map +0 -1
  20. package/dist/index-CkTG6DOa.d.cts +0 -319
  21. package/dist/index-CkTG6DOa.d.ts +0 -319
  22. package/dist/memory.cjs +0 -121
  23. package/dist/memory.cjs.map +0 -1
  24. package/dist/memory.d.cts +0 -29
  25. package/dist/memory.d.ts +0 -29
  26. package/dist/memory.js +0 -115
  27. package/dist/memory.js.map +0 -1
  28. package/dist/observability.cjs +0 -229
  29. package/dist/observability.cjs.map +0 -1
  30. package/dist/observability.d.cts +0 -122
  31. package/dist/observability.d.ts +0 -122
  32. package/dist/observability.js +0 -222
  33. package/dist/observability.js.map +0 -1
  34. package/dist/stt.cjs +0 -828
  35. package/dist/stt.cjs.map +0 -1
  36. package/dist/stt.d.cts +0 -308
  37. package/dist/stt.d.ts +0 -308
  38. package/dist/stt.js +0 -815
  39. package/dist/stt.js.map +0 -1
  40. package/dist/tts.cjs +0 -429
  41. package/dist/tts.cjs.map +0 -1
  42. package/dist/tts.d.cts +0 -151
  43. package/dist/tts.d.ts +0 -151
  44. package/dist/tts.js +0 -418
  45. package/dist/tts.js.map +0 -1
@@ -1,229 +0,0 @@
1
- 'use strict';
2
-
3
- var lruCache = require('lru-cache');
4
- var pino = require('pino');
5
- var sdkTraceNode = require('@opentelemetry/sdk-trace-node');
6
- var exporterTraceOtlpHttp = require('@opentelemetry/exporter-trace-otlp-http');
7
- var sdkTraceBase = require('@opentelemetry/sdk-trace-base');
8
- var semanticConventions = require('@opentelemetry/semantic-conventions');
9
- var api = require('@opentelemetry/api');
10
- var resources = require('@opentelemetry/resources');
11
-
12
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
13
-
14
- var pino__default = /*#__PURE__*/_interopDefault(pino);
15
-
16
- // src/observability/metric/index.ts
17
- var logger = pino__default.default({ name: "@voice-kit/core:metrics" });
18
- var TOKEN_COSTS_PER_M = {
19
- "gpt-4o": { input: 5, output: 15 },
20
- "gpt-4o-mini": { input: 0.15, output: 0.6 },
21
- "claude-3-5-sonnet": { input: 3, output: 15 },
22
- "llama-3.3-70b": { input: 0.59, output: 0.79 }
23
- };
24
- function p95(values) {
25
- if (values.length === 0) return 0;
26
- const sorted = [...values].sort((a, b) => a - b);
27
- const idx = Math.floor(sorted.length * 0.95);
28
- return sorted[Math.min(idx, sorted.length - 1)] ?? 0;
29
- }
30
- function avg(values) {
31
- if (values.length === 0) return 0;
32
- return values.reduce((a, b) => a + b, 0) / values.length;
33
- }
34
- var CallMetrics = class {
35
- store;
36
- constructor() {
37
- this.store = new lruCache.LRUCache({
38
- max: 1e4,
39
- ttl: 2 * 60 * 60 * 1e3
40
- // 2 hours
41
- });
42
- }
43
- getOrCreate(callId) {
44
- const existing = this.store.get(callId);
45
- if (existing) return existing;
46
- const data = {
47
- sttFirstByteMs: [],
48
- ttsFirstByteMs: [],
49
- llmFirstTokenMs: [],
50
- turnLatencyMs: [],
51
- interruptionCount: 0,
52
- interruptionPositions: [],
53
- tokenCost: []
54
- };
55
- this.store.set(callId, data);
56
- return data;
57
- }
58
- /** Record time from audio start to first STT partial result. */
59
- recordSTTFirstByte(callId, ms) {
60
- this.getOrCreate(callId).sttFirstByteMs.push(ms);
61
- logger.debug({ callId, ms }, "Metric: STT TTFB");
62
- }
63
- /** Record time from TTS request to first audio chunk. */
64
- recordTTSFirstByte(callId, ms) {
65
- this.getOrCreate(callId).ttsFirstByteMs.push(ms);
66
- logger.debug({ callId, ms }, "Metric: TTS TTFB");
67
- }
68
- /** Record time from LLM request to first token. */
69
- recordLLMFirstToken(callId, ms) {
70
- this.getOrCreate(callId).llmFirstTokenMs.push(ms);
71
- logger.debug({ callId, ms }, "Metric: LLM first token");
72
- }
73
- /**
74
- * Record end-to-end turn latency: speech_end → first TTS audio byte.
75
- * This is the primary latency metric for voice agent quality.
76
- */
77
- recordTurnLatency(callId, ms) {
78
- this.getOrCreate(callId).turnLatencyMs.push(ms);
79
- logger.debug({ callId, ms }, "Metric: turn latency");
80
- }
81
- /**
82
- * Record an interruption event.
83
- *
84
- * @param callId Call identifier
85
- * @param positionPct 0–1, how far through the TTS stream the interruption occurred
86
- */
87
- recordInterruption(callId, positionPct) {
88
- const data = this.getOrCreate(callId);
89
- data.interruptionCount++;
90
- data.interruptionPositions.push(positionPct);
91
- logger.debug({ callId, positionPct }, "Metric: interruption");
92
- }
93
- /** Record token usage and estimated cost for a model call. */
94
- recordTokenCost(callId, model, inputTokens, outputTokens) {
95
- const costs = TOKEN_COSTS_PER_M[model] ?? { input: 0, output: 0 };
96
- const estimatedUsdCost = inputTokens / 1e6 * costs.input + outputTokens / 1e6 * costs.output;
97
- this.getOrCreate(callId).tokenCost.push({
98
- model,
99
- inputTokens,
100
- outputTokens,
101
- estimatedUsdCost
102
- });
103
- logger.debug({ callId, model, inputTokens, outputTokens, estimatedUsdCost }, "Metric: token cost");
104
- }
105
- /**
106
- * Get a full summary of metrics for a call.
107
- *
108
- * @param callId The call identifier
109
- * @returns Aggregated metrics summary
110
- */
111
- getCallSummary(callId) {
112
- const data = this.getOrCreate(callId);
113
- return {
114
- callId,
115
- sttFirstByteMs: [...data.sttFirstByteMs],
116
- ttsFirstByteMs: [...data.ttsFirstByteMs],
117
- llmFirstTokenMs: [...data.llmFirstTokenMs],
118
- turnLatencyMs: [...data.turnLatencyMs],
119
- interruptionCount: data.interruptionCount,
120
- interruptionPositions: [...data.interruptionPositions],
121
- tokenCost: [...data.tokenCost],
122
- avgTurnLatencyMs: Math.round(avg(data.turnLatencyMs)),
123
- p95TurnLatencyMs: Math.round(p95(data.turnLatencyMs))
124
- };
125
- }
126
- /** Remove metrics for a call. Call on call.ended to free memory. */
127
- clearCall(callId) {
128
- this.store.delete(callId);
129
- }
130
- };
131
- var logger2 = pino__default.default({ name: "@voice-kit/core:observability" });
132
- var _provider = null;
133
- function getOrInitProvider() {
134
- if (_provider) return _provider;
135
- const endpoint = process.env["OTEL_EXPORTER_OTLP_ENDPOINT"];
136
- _provider = new sdkTraceNode.NodeTracerProvider({
137
- resource: resources.resourceFromAttributes({
138
- [semanticConventions.ATTR_SERVICE_NAME]: "voice-kit"
139
- }),
140
- // Pass span processors directly in constructor — addSpanProcessor doesn't exist in this version
141
- spanProcessors: endpoint ? [new sdkTraceBase.SimpleSpanProcessor(new exporterTraceOtlpHttp.OTLPTraceExporter({ url: endpoint }))] : []
142
- });
143
- if (endpoint) {
144
- logger2.info({ endpoint }, "OTel OTLP exporter configured");
145
- }
146
- _provider.register();
147
- return _provider;
148
- }
149
- var VoiceSDKTracer = class {
150
- tracer;
151
- constructor() {
152
- getOrInitProvider();
153
- this.tracer = api.trace.getTracer("@voice-kit/core", "0.1.0");
154
- }
155
- /**
156
- * Trace an STT operation with provider + language attributes.
157
- */
158
- async traceSTT(fn, attrs) {
159
- return this.withSpan(`stt.${attrs.provider}`, fn, {
160
- "stt.provider": attrs.provider,
161
- "stt.language": attrs.language,
162
- ...attrs.callId && { "call.id": attrs.callId }
163
- });
164
- }
165
- /**
166
- * Trace a TTS synthesis operation.
167
- */
168
- async traceTTS(fn, attrs) {
169
- return this.withSpan(`tts.${attrs.provider}`, fn, {
170
- "tts.provider": attrs.provider,
171
- "tts.voice_id": attrs.voice,
172
- "tts.char_count": attrs.chars,
173
- ...attrs.callId && { "call.id": attrs.callId }
174
- });
175
- }
176
- /**
177
- * Trace an LLM generation call.
178
- */
179
- async traceLLM(fn, attrs) {
180
- return this.withSpan(`llm.${attrs.model}`, fn, {
181
- "llm.model": attrs.model,
182
- "llm.input_tokens": attrs.inputTokens,
183
- ...attrs.callId && { "call.id": attrs.callId }
184
- });
185
- }
186
- /**
187
- * Trace a full call lifecycle.
188
- */
189
- async traceCall(fn, attrs) {
190
- return this.withSpan("call", fn, {
191
- "call.id": attrs.callId,
192
- "call.direction": attrs.direction
193
- });
194
- }
195
- /**
196
- * Trace a single conversation turn.
197
- */
198
- async traceTurn(fn, attrs) {
199
- return this.withSpan("turn", fn, {
200
- "turn.index": attrs.turnIndex,
201
- "call.id": attrs.callId
202
- });
203
- }
204
- /** Generic span wrapper. @internal */
205
- async withSpan(name, fn, attributes) {
206
- const span = this.tracer.startSpan(name, { attributes });
207
- const startMs = Date.now();
208
- try {
209
- const result = await fn();
210
- span.setStatus({ code: api.SpanStatusCode.OK });
211
- span.setAttribute("duration_ms", Date.now() - startMs);
212
- return result;
213
- } catch (err) {
214
- span.setStatus({
215
- code: api.SpanStatusCode.ERROR,
216
- message: err instanceof Error ? err.message : String(err)
217
- });
218
- span.recordException(err instanceof Error ? err : new Error(String(err)));
219
- throw err;
220
- } finally {
221
- span.end();
222
- }
223
- }
224
- };
225
-
226
- exports.CallMetrics = CallMetrics;
227
- exports.VoiceSDKTracer = VoiceSDKTracer;
228
- //# sourceMappingURL=observability.cjs.map
229
- //# sourceMappingURL=observability.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/observability/metric/index.ts","../src/observability/tracer/index.ts"],"names":["pino","LRUCache","logger","NodeTracerProvider","Resource","ATTR_SERVICE_NAME","SimpleSpanProcessor","OTLPTraceExporter","trace","SpanStatusCode"],"mappings":"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","file":"observability.cjs","sourcesContent":["/**\r\n * @voice-kit/core — CallMetrics\r\n *\r\n * Records per-call performance metrics: TTFB, turn latency, token cost, interruption rate.\r\n * In-process LRU storage — exported via getCallSummary().\r\n */\r\n\r\nimport { LRUCache } from 'lru-cache'\r\nimport type { CallMetricsSummary } from '../../types'\r\nimport pino from 'pino'\r\n\r\nconst logger = pino({ name: '@voice-kit/core:metrics' })\r\n\r\n/** USD cost per 1M tokens by model. Approximate — update as pricing changes. */\r\nconst TOKEN_COSTS_PER_M: Record<string, { input: number; output: number }> = {\r\n 'gpt-4o': { input: 5.0, output: 15.0 },\r\n 'gpt-4o-mini': { input: 0.15, output: 0.6 },\r\n 'claude-3-5-sonnet': { input: 3.0, output: 15.0 },\r\n 'llama-3.3-70b': { input: 0.59, output: 0.79 },\r\n}\r\n\r\ninterface CallData {\r\n sttFirstByteMs: number[]\r\n ttsFirstByteMs: number[]\r\n llmFirstTokenMs: number[]\r\n turnLatencyMs: number[]\r\n interruptionCount: number\r\n interruptionPositions: number[]\r\n tokenCost: Array<{\r\n model: string\r\n inputTokens: number\r\n outputTokens: number\r\n estimatedUsdCost: number\r\n }>\r\n}\r\n\r\nfunction p95(values: number[]): number {\r\n if (values.length === 0) return 0\r\n const sorted = [...values].sort((a, b) => a - b)\r\n const idx = Math.floor(sorted.length * 0.95)\r\n return sorted[Math.min(idx, sorted.length - 1)] ?? 0\r\n}\r\n\r\nfunction avg(values: number[]): number {\r\n if (values.length === 0) return 0\r\n return values.reduce((a, b) => a + b, 0) / values.length\r\n}\r\n\r\n/**\r\n * Per-call performance metrics recorder.\r\n *\r\n * @example\r\n * ```ts\r\n * const metrics = new CallMetrics()\r\n * metrics.recordSTTFirstByte(callId, 180)\r\n * metrics.recordTurnLatency(callId, 340)\r\n * const summary = metrics.getCallSummary(callId)\r\n * console.log(summary.avgTurnLatencyMs) // 340\r\n * ```\r\n */\r\nexport class CallMetrics {\r\n private readonly store: LRUCache<string, CallData>\r\n\r\n constructor() {\r\n this.store = new LRUCache<string, CallData>({\r\n max: 10_000,\r\n ttl: 2 * 60 * 60 * 1_000, // 2 hours\r\n })\r\n }\r\n\r\n private getOrCreate(callId: string): CallData {\r\n const existing = this.store.get(callId)\r\n if (existing) return existing\r\n\r\n const data: CallData = {\r\n sttFirstByteMs: [],\r\n ttsFirstByteMs: [],\r\n llmFirstTokenMs: [],\r\n turnLatencyMs: [],\r\n interruptionCount: 0,\r\n interruptionPositions: [],\r\n tokenCost: [],\r\n }\r\n this.store.set(callId, data)\r\n return data\r\n }\r\n\r\n /** Record time from audio start to first STT partial result. */\r\n recordSTTFirstByte(callId: string, ms: number): void {\r\n this.getOrCreate(callId).sttFirstByteMs.push(ms)\r\n logger.debug({ callId, ms }, 'Metric: STT TTFB')\r\n }\r\n\r\n /** Record time from TTS request to first audio chunk. */\r\n recordTTSFirstByte(callId: string, ms: number): void {\r\n this.getOrCreate(callId).ttsFirstByteMs.push(ms)\r\n logger.debug({ callId, ms }, 'Metric: TTS TTFB')\r\n }\r\n\r\n /** Record time from LLM request to first token. */\r\n recordLLMFirstToken(callId: string, ms: number): void {\r\n this.getOrCreate(callId).llmFirstTokenMs.push(ms)\r\n logger.debug({ callId, ms }, 'Metric: LLM first token')\r\n }\r\n\r\n /**\r\n * Record end-to-end turn latency: speech_end → first TTS audio byte.\r\n * This is the primary latency metric for voice agent quality.\r\n */\r\n recordTurnLatency(callId: string, ms: number): void {\r\n this.getOrCreate(callId).turnLatencyMs.push(ms)\r\n logger.debug({ callId, ms }, 'Metric: turn latency')\r\n }\r\n\r\n /**\r\n * Record an interruption event.\r\n *\r\n * @param callId Call identifier\r\n * @param positionPct 0–1, how far through the TTS stream the interruption occurred\r\n */\r\n recordInterruption(callId: string, positionPct: number): void {\r\n const data = this.getOrCreate(callId)\r\n data.interruptionCount++\r\n data.interruptionPositions.push(positionPct)\r\n logger.debug({ callId, positionPct }, 'Metric: interruption')\r\n }\r\n\r\n /** Record token usage and estimated cost for a model call. */\r\n recordTokenCost(\r\n callId: string,\r\n model: string,\r\n inputTokens: number,\r\n outputTokens: number\r\n ): void {\r\n const costs = TOKEN_COSTS_PER_M[model] ?? { input: 0, output: 0 }\r\n const estimatedUsdCost =\r\n (inputTokens / 1_000_000) * costs.input +\r\n (outputTokens / 1_000_000) * costs.output\r\n\r\n this.getOrCreate(callId).tokenCost.push({\r\n model,\r\n inputTokens,\r\n outputTokens,\r\n estimatedUsdCost,\r\n })\r\n\r\n logger.debug({ callId, model, inputTokens, outputTokens, estimatedUsdCost }, 'Metric: token cost')\r\n }\r\n\r\n /**\r\n * Get a full summary of metrics for a call.\r\n *\r\n * @param callId The call identifier\r\n * @returns Aggregated metrics summary\r\n */\r\n getCallSummary(callId: string): CallMetricsSummary {\r\n const data = this.getOrCreate(callId)\r\n\r\n return {\r\n callId,\r\n sttFirstByteMs: [...data.sttFirstByteMs],\r\n ttsFirstByteMs: [...data.ttsFirstByteMs],\r\n llmFirstTokenMs: [...data.llmFirstTokenMs],\r\n turnLatencyMs: [...data.turnLatencyMs],\r\n interruptionCount: data.interruptionCount,\r\n interruptionPositions: [...data.interruptionPositions],\r\n tokenCost: [...data.tokenCost],\r\n avgTurnLatencyMs: Math.round(avg(data.turnLatencyMs)),\r\n p95TurnLatencyMs: Math.round(p95(data.turnLatencyMs)),\r\n }\r\n }\r\n\r\n /** Remove metrics for a call. Call on call.ended to free memory. */\r\n clearCall(callId: string): void {\r\n this.store.delete(callId)\r\n }\r\n}","/**\r\n * @voice-kit/core — OpenTelemetry tracing\r\n *\r\n * VoiceSDKTracer: wraps every external provider call with OTel spans.\r\n * Auto-exports to OTLP endpoint if OTEL_EXPORTER_OTLP_ENDPOINT is set.\r\n */\r\n\r\nimport { NodeTracerProvider } from '@opentelemetry/sdk-trace-node'\r\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'\r\nimport { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base'\r\nimport { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions'\r\nimport { trace, SpanStatusCode, type Tracer, type Span } from '@opentelemetry/api'\r\nimport { resourceFromAttributes as Resource } from '@opentelemetry/resources'\r\nimport pino from 'pino'\r\n\r\nconst logger = pino({ name: '@voice-kit/core:observability' })\r\n\r\nlet _provider: NodeTracerProvider | null = null\r\n\r\n/**\r\n * Initialize the global OTel trace provider.\r\n * Called once at SDK startup if OTEL_EXPORTER_OTLP_ENDPOINT is set.\r\n *\r\n * @internal\r\n */\r\nfunction getOrInitProvider(): NodeTracerProvider {\r\n if (_provider) return _provider\r\n\r\n const endpoint = process.env['OTEL_EXPORTER_OTLP_ENDPOINT']\r\n\r\n _provider = new NodeTracerProvider({\r\n resource: Resource({\r\n [ATTR_SERVICE_NAME]: 'voice-kit',\r\n }),\r\n // Pass span processors directly in constructor — addSpanProcessor doesn't exist in this version\r\n spanProcessors: endpoint\r\n ? [new SimpleSpanProcessor(new OTLPTraceExporter({ url: endpoint }))]\r\n : [],\r\n })\r\n\r\n if (endpoint) {\r\n logger.info({ endpoint }, 'OTel OTLP exporter configured')\r\n }\r\n\r\n _provider.register()\r\n return _provider\r\n}\r\n\r\n/**\r\n * OpenTelemetry tracer for VoiceKit. Wraps every external I/O with spans.\r\n *\r\n * @example\r\n * ```ts\r\n * const tracer = new VoiceSDKTracer()\r\n * const result = await tracer.traceSTT(\r\n * () => stt.transcribeBatch(audio),\r\n * { provider: 'deepgram', language: 'en-IN' }\r\n * )\r\n * ```\r\n */\r\nexport class VoiceSDKTracer {\r\n private readonly tracer: Tracer\r\n\r\n constructor() {\r\n getOrInitProvider()\r\n this.tracer = trace.getTracer('@voice-kit/core', '0.1.0')\r\n }\r\n\r\n /**\r\n * Trace an STT operation with provider + language attributes.\r\n */\r\n async traceSTT<T>(\r\n fn: () => Promise<T>,\r\n attrs: { provider: string; language: string; callId?: string }\r\n ): Promise<T> {\r\n return this.withSpan(`stt.${attrs.provider}`, fn, {\r\n 'stt.provider': attrs.provider,\r\n 'stt.language': attrs.language,\r\n ...(attrs.callId && { 'call.id': attrs.callId }),\r\n })\r\n }\r\n\r\n /**\r\n * Trace a TTS synthesis operation.\r\n */\r\n async traceTTS<T>(\r\n fn: () => Promise<T>,\r\n attrs: { provider: string; voice: string; chars: number; callId?: string }\r\n ): Promise<T> {\r\n return this.withSpan(`tts.${attrs.provider}`, fn, {\r\n 'tts.provider': attrs.provider,\r\n 'tts.voice_id': attrs.voice,\r\n 'tts.char_count': attrs.chars,\r\n ...(attrs.callId && { 'call.id': attrs.callId }),\r\n })\r\n }\r\n\r\n /**\r\n * Trace an LLM generation call.\r\n */\r\n async traceLLM<T>(\r\n fn: () => Promise<T>,\r\n attrs: { model: string; inputTokens: number; callId?: string }\r\n ): Promise<T> {\r\n return this.withSpan(`llm.${attrs.model}`, fn, {\r\n 'llm.model': attrs.model,\r\n 'llm.input_tokens': attrs.inputTokens,\r\n ...(attrs.callId && { 'call.id': attrs.callId }),\r\n })\r\n }\r\n\r\n /**\r\n * Trace a full call lifecycle.\r\n */\r\n async traceCall<T>(\r\n fn: () => Promise<T>,\r\n attrs: { callId: string; direction: 'inbound' | 'outbound' }\r\n ): Promise<T> {\r\n return this.withSpan('call', fn, {\r\n 'call.id': attrs.callId,\r\n 'call.direction': attrs.direction,\r\n })\r\n }\r\n\r\n /**\r\n * Trace a single conversation turn.\r\n */\r\n async traceTurn<T>(\r\n fn: () => Promise<T>,\r\n attrs: { turnIndex: number; callId: string }\r\n ): Promise<T> {\r\n return this.withSpan('turn', fn, {\r\n 'turn.index': attrs.turnIndex,\r\n 'call.id': attrs.callId,\r\n })\r\n }\r\n\r\n /** Generic span wrapper. @internal */\r\n private async withSpan<T>(\r\n name: string,\r\n fn: () => Promise<T>,\r\n attributes: Record<string, string | number | boolean>\r\n ): Promise<T> {\r\n const span: Span = this.tracer.startSpan(name, { attributes })\r\n const startMs = Date.now()\r\n\r\n try {\r\n const result = await fn()\r\n span.setStatus({ code: SpanStatusCode.OK })\r\n span.setAttribute('duration_ms', Date.now() - startMs)\r\n return result\r\n } catch (err) {\r\n span.setStatus({\r\n code: SpanStatusCode.ERROR,\r\n message: err instanceof Error ? err.message : String(err),\r\n })\r\n span.recordException(err instanceof Error ? err : new Error(String(err)))\r\n throw err\r\n } finally {\r\n span.end()\r\n }\r\n }\r\n}"]}
@@ -1,122 +0,0 @@
1
- import { d as CallMetricsSummary } from './index-CkTG6DOa.cjs';
2
- import 'ai';
3
-
4
- /**
5
- * @voice-kit/core — CallMetrics
6
- *
7
- * Records per-call performance metrics: TTFB, turn latency, token cost, interruption rate.
8
- * In-process LRU storage — exported via getCallSummary().
9
- */
10
-
11
- /**
12
- * Per-call performance metrics recorder.
13
- *
14
- * @example
15
- * ```ts
16
- * const metrics = new CallMetrics()
17
- * metrics.recordSTTFirstByte(callId, 180)
18
- * metrics.recordTurnLatency(callId, 340)
19
- * const summary = metrics.getCallSummary(callId)
20
- * console.log(summary.avgTurnLatencyMs) // 340
21
- * ```
22
- */
23
- declare class CallMetrics {
24
- private readonly store;
25
- constructor();
26
- private getOrCreate;
27
- /** Record time from audio start to first STT partial result. */
28
- recordSTTFirstByte(callId: string, ms: number): void;
29
- /** Record time from TTS request to first audio chunk. */
30
- recordTTSFirstByte(callId: string, ms: number): void;
31
- /** Record time from LLM request to first token. */
32
- recordLLMFirstToken(callId: string, ms: number): void;
33
- /**
34
- * Record end-to-end turn latency: speech_end → first TTS audio byte.
35
- * This is the primary latency metric for voice agent quality.
36
- */
37
- recordTurnLatency(callId: string, ms: number): void;
38
- /**
39
- * Record an interruption event.
40
- *
41
- * @param callId Call identifier
42
- * @param positionPct 0–1, how far through the TTS stream the interruption occurred
43
- */
44
- recordInterruption(callId: string, positionPct: number): void;
45
- /** Record token usage and estimated cost for a model call. */
46
- recordTokenCost(callId: string, model: string, inputTokens: number, outputTokens: number): void;
47
- /**
48
- * Get a full summary of metrics for a call.
49
- *
50
- * @param callId The call identifier
51
- * @returns Aggregated metrics summary
52
- */
53
- getCallSummary(callId: string): CallMetricsSummary;
54
- /** Remove metrics for a call. Call on call.ended to free memory. */
55
- clearCall(callId: string): void;
56
- }
57
-
58
- /**
59
- * @voice-kit/core — OpenTelemetry tracing
60
- *
61
- * VoiceSDKTracer: wraps every external provider call with OTel spans.
62
- * Auto-exports to OTLP endpoint if OTEL_EXPORTER_OTLP_ENDPOINT is set.
63
- */
64
- /**
65
- * OpenTelemetry tracer for VoiceKit. Wraps every external I/O with spans.
66
- *
67
- * @example
68
- * ```ts
69
- * const tracer = new VoiceSDKTracer()
70
- * const result = await tracer.traceSTT(
71
- * () => stt.transcribeBatch(audio),
72
- * { provider: 'deepgram', language: 'en-IN' }
73
- * )
74
- * ```
75
- */
76
- declare class VoiceSDKTracer {
77
- private readonly tracer;
78
- constructor();
79
- /**
80
- * Trace an STT operation with provider + language attributes.
81
- */
82
- traceSTT<T>(fn: () => Promise<T>, attrs: {
83
- provider: string;
84
- language: string;
85
- callId?: string;
86
- }): Promise<T>;
87
- /**
88
- * Trace a TTS synthesis operation.
89
- */
90
- traceTTS<T>(fn: () => Promise<T>, attrs: {
91
- provider: string;
92
- voice: string;
93
- chars: number;
94
- callId?: string;
95
- }): Promise<T>;
96
- /**
97
- * Trace an LLM generation call.
98
- */
99
- traceLLM<T>(fn: () => Promise<T>, attrs: {
100
- model: string;
101
- inputTokens: number;
102
- callId?: string;
103
- }): Promise<T>;
104
- /**
105
- * Trace a full call lifecycle.
106
- */
107
- traceCall<T>(fn: () => Promise<T>, attrs: {
108
- callId: string;
109
- direction: 'inbound' | 'outbound';
110
- }): Promise<T>;
111
- /**
112
- * Trace a single conversation turn.
113
- */
114
- traceTurn<T>(fn: () => Promise<T>, attrs: {
115
- turnIndex: number;
116
- callId: string;
117
- }): Promise<T>;
118
- /** Generic span wrapper. @internal */
119
- private withSpan;
120
- }
121
-
122
- export { CallMetrics, VoiceSDKTracer };
@@ -1,122 +0,0 @@
1
- import { d as CallMetricsSummary } from './index-CkTG6DOa.js';
2
- import 'ai';
3
-
4
- /**
5
- * @voice-kit/core — CallMetrics
6
- *
7
- * Records per-call performance metrics: TTFB, turn latency, token cost, interruption rate.
8
- * In-process LRU storage — exported via getCallSummary().
9
- */
10
-
11
- /**
12
- * Per-call performance metrics recorder.
13
- *
14
- * @example
15
- * ```ts
16
- * const metrics = new CallMetrics()
17
- * metrics.recordSTTFirstByte(callId, 180)
18
- * metrics.recordTurnLatency(callId, 340)
19
- * const summary = metrics.getCallSummary(callId)
20
- * console.log(summary.avgTurnLatencyMs) // 340
21
- * ```
22
- */
23
- declare class CallMetrics {
24
- private readonly store;
25
- constructor();
26
- private getOrCreate;
27
- /** Record time from audio start to first STT partial result. */
28
- recordSTTFirstByte(callId: string, ms: number): void;
29
- /** Record time from TTS request to first audio chunk. */
30
- recordTTSFirstByte(callId: string, ms: number): void;
31
- /** Record time from LLM request to first token. */
32
- recordLLMFirstToken(callId: string, ms: number): void;
33
- /**
34
- * Record end-to-end turn latency: speech_end → first TTS audio byte.
35
- * This is the primary latency metric for voice agent quality.
36
- */
37
- recordTurnLatency(callId: string, ms: number): void;
38
- /**
39
- * Record an interruption event.
40
- *
41
- * @param callId Call identifier
42
- * @param positionPct 0–1, how far through the TTS stream the interruption occurred
43
- */
44
- recordInterruption(callId: string, positionPct: number): void;
45
- /** Record token usage and estimated cost for a model call. */
46
- recordTokenCost(callId: string, model: string, inputTokens: number, outputTokens: number): void;
47
- /**
48
- * Get a full summary of metrics for a call.
49
- *
50
- * @param callId The call identifier
51
- * @returns Aggregated metrics summary
52
- */
53
- getCallSummary(callId: string): CallMetricsSummary;
54
- /** Remove metrics for a call. Call on call.ended to free memory. */
55
- clearCall(callId: string): void;
56
- }
57
-
58
- /**
59
- * @voice-kit/core — OpenTelemetry tracing
60
- *
61
- * VoiceSDKTracer: wraps every external provider call with OTel spans.
62
- * Auto-exports to OTLP endpoint if OTEL_EXPORTER_OTLP_ENDPOINT is set.
63
- */
64
- /**
65
- * OpenTelemetry tracer for VoiceKit. Wraps every external I/O with spans.
66
- *
67
- * @example
68
- * ```ts
69
- * const tracer = new VoiceSDKTracer()
70
- * const result = await tracer.traceSTT(
71
- * () => stt.transcribeBatch(audio),
72
- * { provider: 'deepgram', language: 'en-IN' }
73
- * )
74
- * ```
75
- */
76
- declare class VoiceSDKTracer {
77
- private readonly tracer;
78
- constructor();
79
- /**
80
- * Trace an STT operation with provider + language attributes.
81
- */
82
- traceSTT<T>(fn: () => Promise<T>, attrs: {
83
- provider: string;
84
- language: string;
85
- callId?: string;
86
- }): Promise<T>;
87
- /**
88
- * Trace a TTS synthesis operation.
89
- */
90
- traceTTS<T>(fn: () => Promise<T>, attrs: {
91
- provider: string;
92
- voice: string;
93
- chars: number;
94
- callId?: string;
95
- }): Promise<T>;
96
- /**
97
- * Trace an LLM generation call.
98
- */
99
- traceLLM<T>(fn: () => Promise<T>, attrs: {
100
- model: string;
101
- inputTokens: number;
102
- callId?: string;
103
- }): Promise<T>;
104
- /**
105
- * Trace a full call lifecycle.
106
- */
107
- traceCall<T>(fn: () => Promise<T>, attrs: {
108
- callId: string;
109
- direction: 'inbound' | 'outbound';
110
- }): Promise<T>;
111
- /**
112
- * Trace a single conversation turn.
113
- */
114
- traceTurn<T>(fn: () => Promise<T>, attrs: {
115
- turnIndex: number;
116
- callId: string;
117
- }): Promise<T>;
118
- /** Generic span wrapper. @internal */
119
- private withSpan;
120
- }
121
-
122
- export { CallMetrics, VoiceSDKTracer };