dvgateway-sdk 1.0.0
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/README.md +615 -0
- package/dist/audio/codec.d.ts +44 -0
- package/dist/audio/codec.d.ts.map +1 -0
- package/dist/audio/codec.js +136 -0
- package/dist/audio/codec.js.map +1 -0
- package/dist/audio/codec.test.d.ts +2 -0
- package/dist/audio/codec.test.d.ts.map +1 -0
- package/dist/audio/codec.test.js +155 -0
- package/dist/audio/codec.test.js.map +1 -0
- package/dist/auth/manager.d.ts +34 -0
- package/dist/auth/manager.d.ts.map +1 -0
- package/dist/auth/manager.js +122 -0
- package/dist/auth/manager.js.map +1 -0
- package/dist/auth/manager.test.d.ts +2 -0
- package/dist/auth/manager.test.d.ts.map +1 -0
- package/dist/auth/manager.test.js +147 -0
- package/dist/auth/manager.test.js.map +1 -0
- package/dist/client.d.ts +154 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +218 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/dist/minutes/manager.d.ts +43 -0
- package/dist/minutes/manager.d.ts.map +1 -0
- package/dist/minutes/manager.js +71 -0
- package/dist/minutes/manager.js.map +1 -0
- package/dist/observability/logger.d.ts +19 -0
- package/dist/observability/logger.d.ts.map +1 -0
- package/dist/observability/logger.js +70 -0
- package/dist/observability/logger.js.map +1 -0
- package/dist/observability/metrics.d.ts +53 -0
- package/dist/observability/metrics.d.ts.map +1 -0
- package/dist/observability/metrics.js +143 -0
- package/dist/observability/metrics.js.map +1 -0
- package/dist/observability/metrics.test.d.ts +2 -0
- package/dist/observability/metrics.test.d.ts.map +1 -0
- package/dist/observability/metrics.test.js +122 -0
- package/dist/observability/metrics.test.js.map +1 -0
- package/dist/pipeline/builder.d.ts +111 -0
- package/dist/pipeline/builder.d.ts.map +1 -0
- package/dist/pipeline/builder.js +323 -0
- package/dist/pipeline/builder.js.map +1 -0
- package/dist/session/manager.d.ts +21 -0
- package/dist/session/manager.d.ts.map +1 -0
- package/dist/session/manager.js +52 -0
- package/dist/session/manager.js.map +1 -0
- package/dist/streams/audio-stream.d.ts +29 -0
- package/dist/streams/audio-stream.d.ts.map +1 -0
- package/dist/streams/audio-stream.js +118 -0
- package/dist/streams/audio-stream.js.map +1 -0
- package/dist/streams/call-events.d.ts +32 -0
- package/dist/streams/call-events.d.ts.map +1 -0
- package/dist/streams/call-events.js +140 -0
- package/dist/streams/call-events.js.map +1 -0
- package/dist/streams/tts-stream.d.ts +46 -0
- package/dist/streams/tts-stream.d.ts.map +1 -0
- package/dist/streams/tts-stream.js +102 -0
- package/dist/streams/tts-stream.js.map +1 -0
- package/dist/transport/http-client.d.ts +36 -0
- package/dist/transport/http-client.d.ts.map +1 -0
- package/dist/transport/http-client.js +102 -0
- package/dist/transport/http-client.js.map +1 -0
- package/dist/transport/http-client.test.d.ts +2 -0
- package/dist/transport/http-client.test.d.ts.map +1 -0
- package/dist/transport/http-client.test.js +172 -0
- package/dist/transport/http-client.test.js.map +1 -0
- package/dist/transport/ws-pool.d.ts +34 -0
- package/dist/transport/ws-pool.d.ts.map +1 -0
- package/dist/transport/ws-pool.js +123 -0
- package/dist/transport/ws-pool.js.map +1 -0
- package/dist/types/index.d.ts +378 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +25 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +81 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured JSON logger with PII redaction support.
|
|
3
|
+
* Implements the Logger interface — swap to any log library (pino, winston) as needed.
|
|
4
|
+
*/
|
|
5
|
+
const PII_PATTERNS = [
|
|
6
|
+
// Korean mobile numbers: 010-1234-5678 or 01012345678
|
|
7
|
+
{ pattern: /\b(010|011|016|017|018|019)[-.]?\d{3,4}[-.]?\d{4}\b/g, replacement: '***-****' },
|
|
8
|
+
// General phone numbers: +82-10-1234-5678
|
|
9
|
+
{ pattern: /\+?\d{1,3}[-.\s]?\(?\d{1,4}\)?[-.\s]?\d{1,4}[-.\s]?\d{1,9}/g, replacement: '[PHONE]' },
|
|
10
|
+
];
|
|
11
|
+
function redactPii(value) {
|
|
12
|
+
if (typeof value === 'string') {
|
|
13
|
+
let result = value;
|
|
14
|
+
for (const { pattern, replacement } of PII_PATTERNS) {
|
|
15
|
+
result = result.replace(pattern, replacement);
|
|
16
|
+
}
|
|
17
|
+
return result;
|
|
18
|
+
}
|
|
19
|
+
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
20
|
+
const redacted = {};
|
|
21
|
+
for (const [k, v] of Object.entries(value)) {
|
|
22
|
+
// Never log these fields at any level
|
|
23
|
+
if (['caller', 'callee', 'transcript', 'text', 'password', 'secret', 'token'].includes(k)) {
|
|
24
|
+
redacted[k] = '[REDACTED]';
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
redacted[k] = redactPii(v);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return redacted;
|
|
31
|
+
}
|
|
32
|
+
return value;
|
|
33
|
+
}
|
|
34
|
+
const LEVEL_VALUES = {
|
|
35
|
+
debug: 10,
|
|
36
|
+
info: 20,
|
|
37
|
+
warn: 30,
|
|
38
|
+
error: 40,
|
|
39
|
+
};
|
|
40
|
+
export function createLogger(opts = {}) {
|
|
41
|
+
const minLevel = LEVEL_VALUES[opts.level ?? 'info'];
|
|
42
|
+
const shouldRedact = opts.redactPii !== false;
|
|
43
|
+
function write(level, ctx, msg) {
|
|
44
|
+
if (LEVEL_VALUES[level] < minLevel)
|
|
45
|
+
return;
|
|
46
|
+
const entry = {
|
|
47
|
+
level,
|
|
48
|
+
time: new Date().toISOString(),
|
|
49
|
+
msg,
|
|
50
|
+
...opts.baseContext,
|
|
51
|
+
...(shouldRedact ? redactPii(ctx) : ctx),
|
|
52
|
+
};
|
|
53
|
+
const line = JSON.stringify(entry);
|
|
54
|
+
if (level === 'error' || level === 'warn') {
|
|
55
|
+
process.stderr.write(line + '\n');
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
process.stdout.write(line + '\n');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
debug: (ctx, msg) => write('debug', ctx, msg),
|
|
63
|
+
info: (ctx, msg) => write('info', ctx, msg),
|
|
64
|
+
warn: (ctx, msg) => write('warn', ctx, msg),
|
|
65
|
+
error: (ctx, msg) => write('error', ctx, msg),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/** Default singleton logger */
|
|
69
|
+
export const defaultLogger = createLogger({ level: 'info', redactPii: true });
|
|
70
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/observability/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK Metrics
|
|
3
|
+
*
|
|
4
|
+
* Lightweight pipeline latency and throughput tracking.
|
|
5
|
+
* Emits OpenTelemetry-compatible spans when an OTel tracer is provided,
|
|
6
|
+
* otherwise records to in-memory histograms for Prometheus scraping.
|
|
7
|
+
*
|
|
8
|
+
* GenAI Semantic Conventions (OTel v1.37+):
|
|
9
|
+
* gen_ai.operation.name, gen_ai.system, gen_ai.request.model,
|
|
10
|
+
* gen_ai.usage.input_tokens, gen_ai.usage.output_tokens
|
|
11
|
+
*/
|
|
12
|
+
import type { Logger } from '../types/index.js';
|
|
13
|
+
export declare class Histogram {
|
|
14
|
+
private readonly buckets;
|
|
15
|
+
private readonly counts;
|
|
16
|
+
private sum;
|
|
17
|
+
private count;
|
|
18
|
+
constructor(buckets?: number[]);
|
|
19
|
+
observe(value: number): void;
|
|
20
|
+
/** Returns p50, p95, p99 in ms */
|
|
21
|
+
percentiles(): {
|
|
22
|
+
p50: number;
|
|
23
|
+
p95: number;
|
|
24
|
+
p99: number;
|
|
25
|
+
mean: number;
|
|
26
|
+
};
|
|
27
|
+
private percentile;
|
|
28
|
+
toPrometheus(name: string, labels?: Record<string, string>): string;
|
|
29
|
+
}
|
|
30
|
+
export declare class Counter {
|
|
31
|
+
private value;
|
|
32
|
+
increment(by?: number): void;
|
|
33
|
+
get(): number;
|
|
34
|
+
reset(): void;
|
|
35
|
+
}
|
|
36
|
+
export declare class PipelineMetrics {
|
|
37
|
+
readonly sttLatency: Histogram;
|
|
38
|
+
readonly llmTtft: Histogram;
|
|
39
|
+
readonly ttsLatency: Histogram;
|
|
40
|
+
readonly e2eLatency: Histogram;
|
|
41
|
+
readonly transcriptsTotal: Counter;
|
|
42
|
+
readonly ttsInjectionsTotal: Counter;
|
|
43
|
+
readonly errorsTotal: Counter;
|
|
44
|
+
readonly activeCalls: Counter;
|
|
45
|
+
private readonly logger;
|
|
46
|
+
constructor(logger: Logger);
|
|
47
|
+
/** Start a latency measurement; returns a function to stop it */
|
|
48
|
+
startTimer(): () => number;
|
|
49
|
+
logSummary(): void;
|
|
50
|
+
/** Prometheus text format for scraping */
|
|
51
|
+
toPrometheus(): string;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=metrics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/observability/metrics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAIhD,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAW;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAW;IAClC,OAAO,CAAC,GAAG,CAAK;IAChB,OAAO,CAAC,KAAK,CAAK;gBAEN,OAAO,GAAE,MAAM,EAA8C;IAKzE,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAkB5B,kCAAkC;IAClC,WAAW,IAAI;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE;IAUtE,OAAO,CAAC,UAAU;IAUlB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAAG,MAAM;CAwBxE;AAED,qBAAa,OAAO;IAClB,OAAO,CAAC,KAAK,CAAK;IAElB,SAAS,CAAC,EAAE,SAAI,GAAG,IAAI;IAIvB,GAAG,IAAI,MAAM;IAIb,KAAK,IAAI,IAAI;CAGd;AAID,qBAAa,eAAe;IAC1B,QAAQ,CAAC,UAAU,YAAkD;IACrE,QAAQ,CAAC,OAAO,YAAuD;IACvE,QAAQ,CAAC,UAAU,YAAiD;IACpE,QAAQ,CAAC,UAAU,YAAwD;IAE3E,QAAQ,CAAC,gBAAgB,UAAmB;IAC5C,QAAQ,CAAC,kBAAkB,UAAiB;IAC5C,QAAQ,CAAC,WAAW,UAAwB;IAC5C,QAAQ,CAAC,WAAW,UAAwB;IAE5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEpB,MAAM,EAAE,MAAM;IAI1B,iEAAiE;IACjE,UAAU,IAAI,MAAM,MAAM;IAK1B,UAAU,IAAI,IAAI;IAiBlB,0CAA0C;IAC1C,YAAY,IAAI,MAAM;CAYvB"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK Metrics
|
|
3
|
+
*
|
|
4
|
+
* Lightweight pipeline latency and throughput tracking.
|
|
5
|
+
* Emits OpenTelemetry-compatible spans when an OTel tracer is provided,
|
|
6
|
+
* otherwise records to in-memory histograms for Prometheus scraping.
|
|
7
|
+
*
|
|
8
|
+
* GenAI Semantic Conventions (OTel v1.37+):
|
|
9
|
+
* gen_ai.operation.name, gen_ai.system, gen_ai.request.model,
|
|
10
|
+
* gen_ai.usage.input_tokens, gen_ai.usage.output_tokens
|
|
11
|
+
*/
|
|
12
|
+
// ─── Histogram (fixed buckets, zero dependencies) ─────────────────────────
|
|
13
|
+
export class Histogram {
|
|
14
|
+
buckets;
|
|
15
|
+
counts;
|
|
16
|
+
sum = 0;
|
|
17
|
+
count = 0;
|
|
18
|
+
constructor(buckets = [10, 50, 100, 200, 500, 1000, 2000, 5000]) {
|
|
19
|
+
this.buckets = [...buckets].sort((a, b) => a - b);
|
|
20
|
+
this.counts = new Array(buckets.length + 1).fill(0);
|
|
21
|
+
}
|
|
22
|
+
observe(value) {
|
|
23
|
+
this.sum += value;
|
|
24
|
+
this.count++;
|
|
25
|
+
let placed = false;
|
|
26
|
+
for (let i = 0; i < this.buckets.length; i++) {
|
|
27
|
+
if (value <= this.buckets[i]) {
|
|
28
|
+
this.counts[i] = (this.counts[i] ?? 0) + 1;
|
|
29
|
+
placed = true;
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (!placed) {
|
|
34
|
+
const last = this.counts.length - 1;
|
|
35
|
+
this.counts[last] = (this.counts[last] ?? 0) + 1;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** Returns p50, p95, p99 in ms */
|
|
39
|
+
percentiles() {
|
|
40
|
+
if (this.count === 0)
|
|
41
|
+
return { p50: 0, p95: 0, p99: 0, mean: 0 };
|
|
42
|
+
return {
|
|
43
|
+
p50: this.percentile(0.50),
|
|
44
|
+
p95: this.percentile(0.95),
|
|
45
|
+
p99: this.percentile(0.99),
|
|
46
|
+
mean: this.sum / this.count,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
percentile(p) {
|
|
50
|
+
const target = Math.ceil(p * this.count);
|
|
51
|
+
let cumulative = 0;
|
|
52
|
+
for (let i = 0; i < this.buckets.length; i++) {
|
|
53
|
+
cumulative += this.counts[i] ?? 0;
|
|
54
|
+
if (cumulative >= target)
|
|
55
|
+
return this.buckets[i] ?? 0;
|
|
56
|
+
}
|
|
57
|
+
return this.buckets[this.buckets.length - 1] ?? 0;
|
|
58
|
+
}
|
|
59
|
+
toPrometheus(name, labels = {}) {
|
|
60
|
+
const labelStr = Object.entries(labels)
|
|
61
|
+
.map(([k, v]) => `${k}="${v}"`)
|
|
62
|
+
.join(',');
|
|
63
|
+
const l = labelStr ? `{${labelStr}}` : '';
|
|
64
|
+
const lines = [];
|
|
65
|
+
let cumulative = 0;
|
|
66
|
+
for (let i = 0; i < this.buckets.length; i++) {
|
|
67
|
+
cumulative += this.counts[i] ?? 0;
|
|
68
|
+
const bucketLabel = labelStr
|
|
69
|
+
? `{${labelStr},le="${this.buckets[i]}"}`
|
|
70
|
+
: `{le="${this.buckets[i]}"}`;
|
|
71
|
+
lines.push(`${name}_bucket${bucketLabel} ${cumulative}`);
|
|
72
|
+
}
|
|
73
|
+
cumulative += this.counts[this.counts.length - 1] ?? 0;
|
|
74
|
+
const infLabel = labelStr
|
|
75
|
+
? `{${labelStr},le="+Inf"}`
|
|
76
|
+
: `{le="+Inf"}`;
|
|
77
|
+
lines.push(`${name}_bucket${infLabel} ${cumulative}`);
|
|
78
|
+
lines.push(`${name}_sum${l} ${this.sum}`);
|
|
79
|
+
lines.push(`${name}_count${l} ${this.count}`);
|
|
80
|
+
return lines.join('\n');
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export class Counter {
|
|
84
|
+
value = 0;
|
|
85
|
+
increment(by = 1) {
|
|
86
|
+
this.value += by;
|
|
87
|
+
}
|
|
88
|
+
get() {
|
|
89
|
+
return this.value;
|
|
90
|
+
}
|
|
91
|
+
reset() {
|
|
92
|
+
this.value = 0;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// ─── Pipeline Metrics Registry ────────────────────────────────────────────
|
|
96
|
+
export class PipelineMetrics {
|
|
97
|
+
sttLatency = new Histogram([50, 100, 200, 500, 1000, 2000]);
|
|
98
|
+
llmTtft = new Histogram([20, 50, 80, 120, 200, 500, 1000]);
|
|
99
|
+
ttsLatency = new Histogram([50, 100, 150, 300, 500, 1000]);
|
|
100
|
+
e2eLatency = new Histogram([100, 200, 300, 500, 700, 1000, 2000]);
|
|
101
|
+
transcriptsTotal = new Counter();
|
|
102
|
+
ttsInjectionsTotal = new Counter();
|
|
103
|
+
errorsTotal = new Counter();
|
|
104
|
+
activeCalls = new Counter();
|
|
105
|
+
logger;
|
|
106
|
+
constructor(logger) {
|
|
107
|
+
this.logger = logger;
|
|
108
|
+
}
|
|
109
|
+
/** Start a latency measurement; returns a function to stop it */
|
|
110
|
+
startTimer() {
|
|
111
|
+
const start = Date.now();
|
|
112
|
+
return () => Date.now() - start;
|
|
113
|
+
}
|
|
114
|
+
logSummary() {
|
|
115
|
+
const stt = this.sttLatency.percentiles();
|
|
116
|
+
const llm = this.llmTtft.percentiles();
|
|
117
|
+
const tts = this.ttsLatency.percentiles();
|
|
118
|
+
const e2e = this.e2eLatency.percentiles();
|
|
119
|
+
this.logger.info({
|
|
120
|
+
stt_p50_ms: stt.p50, stt_p95_ms: stt.p95,
|
|
121
|
+
llm_ttft_p50_ms: llm.p50, llm_ttft_p95_ms: llm.p95,
|
|
122
|
+
tts_p50_ms: tts.p50, tts_p95_ms: tts.p95,
|
|
123
|
+
e2e_p50_ms: e2e.p50, e2e_p95_ms: e2e.p95,
|
|
124
|
+
transcripts: this.transcriptsTotal.get(),
|
|
125
|
+
tts_injections: this.ttsInjectionsTotal.get(),
|
|
126
|
+
errors: this.errorsTotal.get(),
|
|
127
|
+
}, 'DVGateway SDK metrics summary');
|
|
128
|
+
}
|
|
129
|
+
/** Prometheus text format for scraping */
|
|
130
|
+
toPrometheus() {
|
|
131
|
+
return [
|
|
132
|
+
this.sttLatency.toPrometheus('dvgw_stt_latency_ms'),
|
|
133
|
+
this.llmTtft.toPrometheus('dvgw_llm_ttft_ms'),
|
|
134
|
+
this.ttsLatency.toPrometheus('dvgw_tts_latency_ms'),
|
|
135
|
+
this.e2eLatency.toPrometheus('dvgw_e2e_latency_ms'),
|
|
136
|
+
`dvgw_transcripts_total ${this.transcriptsTotal.get()}`,
|
|
137
|
+
`dvgw_tts_injections_total ${this.ttsInjectionsTotal.get()}`,
|
|
138
|
+
`dvgw_errors_total ${this.errorsTotal.get()}`,
|
|
139
|
+
`dvgw_active_calls ${this.activeCalls.get()}`,
|
|
140
|
+
].join('\n');
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=metrics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../src/observability/metrics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.test.d.ts","sourceRoot":"","sources":["../../src/observability/metrics.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { Histogram, Counter, PipelineMetrics } from './metrics.js';
|
|
2
|
+
const mockLogger = {
|
|
3
|
+
debug: jest.fn(),
|
|
4
|
+
info: jest.fn(),
|
|
5
|
+
warn: jest.fn(),
|
|
6
|
+
error: jest.fn(),
|
|
7
|
+
};
|
|
8
|
+
describe('Counter', () => {
|
|
9
|
+
it('should start at 0', () => {
|
|
10
|
+
const c = new Counter();
|
|
11
|
+
expect(c.get()).toBe(0);
|
|
12
|
+
});
|
|
13
|
+
it('should increment by 1 by default', () => {
|
|
14
|
+
const c = new Counter();
|
|
15
|
+
c.increment();
|
|
16
|
+
c.increment();
|
|
17
|
+
expect(c.get()).toBe(2);
|
|
18
|
+
});
|
|
19
|
+
it('should increment by custom amount', () => {
|
|
20
|
+
const c = new Counter();
|
|
21
|
+
c.increment(5);
|
|
22
|
+
c.increment(3);
|
|
23
|
+
expect(c.get()).toBe(8);
|
|
24
|
+
});
|
|
25
|
+
it('should reset to 0', () => {
|
|
26
|
+
const c = new Counter();
|
|
27
|
+
c.increment(10);
|
|
28
|
+
c.reset();
|
|
29
|
+
expect(c.get()).toBe(0);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
describe('Histogram', () => {
|
|
33
|
+
it('should return zeros when empty', () => {
|
|
34
|
+
const h = new Histogram();
|
|
35
|
+
const p = h.percentiles();
|
|
36
|
+
expect(p.p50).toBe(0);
|
|
37
|
+
expect(p.p95).toBe(0);
|
|
38
|
+
expect(p.p99).toBe(0);
|
|
39
|
+
expect(p.mean).toBe(0);
|
|
40
|
+
});
|
|
41
|
+
it('should track a single observation', () => {
|
|
42
|
+
const h = new Histogram([10, 50, 100]);
|
|
43
|
+
h.observe(25);
|
|
44
|
+
const p = h.percentiles();
|
|
45
|
+
expect(p.p50).toBe(50); // falls in ≤50 bucket
|
|
46
|
+
expect(p.mean).toBe(25);
|
|
47
|
+
});
|
|
48
|
+
it('should compute percentiles over multiple observations', () => {
|
|
49
|
+
const h = new Histogram([100, 200, 500, 1000]);
|
|
50
|
+
// 50 observations at 50ms, 40 at 300ms, 10 at 800ms
|
|
51
|
+
for (let i = 0; i < 50; i++)
|
|
52
|
+
h.observe(50);
|
|
53
|
+
for (let i = 0; i < 40; i++)
|
|
54
|
+
h.observe(300);
|
|
55
|
+
for (let i = 0; i < 10; i++)
|
|
56
|
+
h.observe(800);
|
|
57
|
+
const p = h.percentiles();
|
|
58
|
+
expect(p.p50).toBe(100); // 50th of 100: target=50, cumulative at bucket ≤100 = 50 → matches
|
|
59
|
+
expect(p.p95).toBe(1000); // 95th of 100: target=95, cumulative at ≤500 = 90 → next bucket ≤1000
|
|
60
|
+
expect(p.p99).toBe(1000); // 99th of 100: target=99, in bucket ≤1000
|
|
61
|
+
});
|
|
62
|
+
it('should handle values above the largest bucket', () => {
|
|
63
|
+
const h = new Histogram([10, 100]);
|
|
64
|
+
h.observe(9999);
|
|
65
|
+
const p = h.percentiles();
|
|
66
|
+
expect(p.p50).toBe(100); // falls into the overflow bucket, percentile returns last bucket
|
|
67
|
+
expect(p.mean).toBe(9999);
|
|
68
|
+
});
|
|
69
|
+
it('should produce Prometheus text output', () => {
|
|
70
|
+
const h = new Histogram([10, 100]);
|
|
71
|
+
h.observe(5);
|
|
72
|
+
h.observe(50);
|
|
73
|
+
const text = h.toPrometheus('test_latency');
|
|
74
|
+
expect(text).toContain('test_latency_bucket{le="10"} 1');
|
|
75
|
+
expect(text).toContain('test_latency_bucket{le="100"} 2');
|
|
76
|
+
expect(text).toContain('test_latency_bucket{le="+Inf"} 2');
|
|
77
|
+
expect(text).toContain('test_latency_sum 55');
|
|
78
|
+
expect(text).toContain('test_latency_count 2');
|
|
79
|
+
});
|
|
80
|
+
it('should produce Prometheus text with labels', () => {
|
|
81
|
+
const h = new Histogram([100]);
|
|
82
|
+
h.observe(50);
|
|
83
|
+
const text = h.toPrometheus('test_latency', { provider: 'deepgram' });
|
|
84
|
+
expect(text).toContain('provider="deepgram"');
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
describe('PipelineMetrics', () => {
|
|
88
|
+
it('should have all histogram and counter instances', () => {
|
|
89
|
+
const m = new PipelineMetrics(mockLogger);
|
|
90
|
+
expect(m.sttLatency).toBeInstanceOf(Histogram);
|
|
91
|
+
expect(m.llmTtft).toBeInstanceOf(Histogram);
|
|
92
|
+
expect(m.ttsLatency).toBeInstanceOf(Histogram);
|
|
93
|
+
expect(m.e2eLatency).toBeInstanceOf(Histogram);
|
|
94
|
+
expect(m.transcriptsTotal).toBeInstanceOf(Counter);
|
|
95
|
+
expect(m.ttsInjectionsTotal).toBeInstanceOf(Counter);
|
|
96
|
+
expect(m.errorsTotal).toBeInstanceOf(Counter);
|
|
97
|
+
expect(m.activeCalls).toBeInstanceOf(Counter);
|
|
98
|
+
});
|
|
99
|
+
it('should measure timer duration', async () => {
|
|
100
|
+
const m = new PipelineMetrics(mockLogger);
|
|
101
|
+
const stop = m.startTimer();
|
|
102
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
103
|
+
const elapsed = stop();
|
|
104
|
+
expect(elapsed).toBeGreaterThanOrEqual(40);
|
|
105
|
+
expect(elapsed).toBeLessThan(200);
|
|
106
|
+
});
|
|
107
|
+
it('should produce Prometheus output', () => {
|
|
108
|
+
const m = new PipelineMetrics(mockLogger);
|
|
109
|
+
m.sttLatency.observe(100);
|
|
110
|
+
m.transcriptsTotal.increment();
|
|
111
|
+
const output = m.toPrometheus();
|
|
112
|
+
expect(output).toContain('dvgw_stt_latency_ms');
|
|
113
|
+
expect(output).toContain('dvgw_transcripts_total 1');
|
|
114
|
+
});
|
|
115
|
+
it('should log summary without errors', () => {
|
|
116
|
+
const m = new PipelineMetrics(mockLogger);
|
|
117
|
+
m.sttLatency.observe(100);
|
|
118
|
+
m.logSummary();
|
|
119
|
+
expect(mockLogger.info).toHaveBeenCalled();
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
//# sourceMappingURL=metrics.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.test.js","sourceRoot":"","sources":["../../src/observability/metrics.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGnE,MAAM,UAAU,GAAW;IACzB,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE;IAChB,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;IACf,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;IACf,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE;CACjB,CAAC;AAEF,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;IACvB,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;QAC3B,MAAM,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC;QACxB,CAAC,CAAC,SAAS,EAAE,CAAC;QACd,CAAC,CAAC,SAAS,EAAE,CAAC;QACd,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC;QACxB,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QACf,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QACf,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;QAC3B,MAAM,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC;QACxB,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAChB,CAAC,CAAC,KAAK,EAAE,CAAC;QACV,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;IACzB,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,MAAM,CAAC,GAAG,IAAI,SAAS,EAAE,CAAC;QAC1B,MAAM,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;QAC1B,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,CAAC,GAAG,IAAI,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC;QACvC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACd,MAAM,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;QAC1B,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,sBAAsB;QAC9C,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,MAAM,CAAC,GAAG,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;QAC/C,oDAAoD;QACpD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE;YAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC3C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE;YAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE;YAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAE5C,MAAM,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;QAC1B,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,mEAAmE;QAC5F,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,sEAAsE;QAChG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,0CAA0C;IACtE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,CAAC,GAAG,IAAI,SAAS,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC;QACnC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAChB,MAAM,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;QAC1B,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,iEAAiE;QAC1F,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,CAAC,GAAG,IAAI,SAAS,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC;QACnC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACb,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACd,MAAM,IAAI,GAAG,CAAC,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,gCAAgC,CAAC,CAAC;QACzD,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,iCAAiC,CAAC,CAAC;QAC1D,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,kCAAkC,CAAC,CAAC;QAC3D,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;QAC9C,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,CAAC,GAAG,IAAI,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/B,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACd,MAAM,IAAI,GAAG,CAAC,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC;QACtE,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,CAAC,GAAG,IAAI,eAAe,CAAC,UAAU,CAAC,CAAC;QAC1C,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QAC/C,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QAC5C,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QAC/C,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QAC/C,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QACnD,MAAM,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QACrD,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAC9C,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;QAC7C,MAAM,CAAC,GAAG,IAAI,eAAe,CAAC,UAAU,CAAC,CAAC;QAC1C,MAAM,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,CAAC;QAC5B,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC5C,MAAM,OAAO,GAAG,IAAI,EAAE,CAAC;QACvB,MAAM,CAAC,OAAO,CAAC,CAAC,sBAAsB,CAAC,EAAE,CAAC,CAAC;QAC3C,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,CAAC,GAAG,IAAI,eAAe,CAAC,UAAU,CAAC,CAAC;QAC1C,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,CAAC,CAAC,YAAY,EAAE,CAAC;QAChC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;QAChD,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,CAAC,GAAG,IAAI,eAAe,CAAC,UAAU,CAAC,CAAC;QAC1C,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC,CAAC,UAAU,EAAE,CAAC;QACf,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,gBAAgB,EAAE,CAAC;IAC7C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VoiceAI Pipeline Builder
|
|
3
|
+
*
|
|
4
|
+
* High-level fluent API for wiring STT → LLM → TTS pipelines.
|
|
5
|
+
* Handles the entire lifecycle: call events, audio streaming, AI processing,
|
|
6
|
+
* and TTS injection — all with a single .start() call.
|
|
7
|
+
*
|
|
8
|
+
* Architecture (2026 cascaded pipeline pattern):
|
|
9
|
+
*
|
|
10
|
+
* Inbound call
|
|
11
|
+
* ↓
|
|
12
|
+
* AudioStream (WebSocket, slin16 → Float32)
|
|
13
|
+
* ↓
|
|
14
|
+
* [VAD filter] (optional, reduces STT API cost)
|
|
15
|
+
* ↓
|
|
16
|
+
* SttAdapter.startStream() → onTranscript(isFinal=true)
|
|
17
|
+
* ↓
|
|
18
|
+
* LlmAdapter.chat() → streaming tokens
|
|
19
|
+
* ↓ (first token triggers TTS immediately)
|
|
20
|
+
* TtsAdapter.synthesize() → PCM chunks
|
|
21
|
+
* ↓
|
|
22
|
+
* TtsInjector.injectStreaming()
|
|
23
|
+
* ↓
|
|
24
|
+
* Call audio (Asterisk)
|
|
25
|
+
*
|
|
26
|
+
* Latency budget target: <500ms end-to-end (STT ~200ms, LLM TTFT ~80ms, TTS TTFA ~150ms)
|
|
27
|
+
*/
|
|
28
|
+
import type { SttAdapter, TtsAdapter, LlmAdapter, CallSession, TranscriptResult, StreamDir, Logger } from '../types/index.js';
|
|
29
|
+
import type { CallEventStream } from '../streams/call-events.js';
|
|
30
|
+
import type { TtsInjector } from '../streams/tts-stream.js';
|
|
31
|
+
import type { WsPool } from '../transport/ws-pool.js';
|
|
32
|
+
declare class WithFallback<T extends SttAdapter | TtsAdapter | LlmAdapter> {
|
|
33
|
+
readonly primary: T;
|
|
34
|
+
readonly fallback?: T | undefined;
|
|
35
|
+
constructor(primary: T, fallback?: T | undefined);
|
|
36
|
+
}
|
|
37
|
+
export interface FallbackAdapter<T> {
|
|
38
|
+
fallback(adapter: T): this;
|
|
39
|
+
}
|
|
40
|
+
declare class SttStage implements FallbackAdapter<SttAdapter> {
|
|
41
|
+
private readonly _adapter;
|
|
42
|
+
private _fallback;
|
|
43
|
+
private readonly _builder;
|
|
44
|
+
constructor(_adapter: SttAdapter, _fallback: SttAdapter | undefined, _builder: PipelineBuilder);
|
|
45
|
+
fallback(adapter: SttAdapter): this;
|
|
46
|
+
toWrapped(): WithFallback<SttAdapter>;
|
|
47
|
+
llm(adapter: LlmAdapter): LlmStage;
|
|
48
|
+
forConference(): ConferencePipelineBuilder;
|
|
49
|
+
}
|
|
50
|
+
declare class LlmStage implements FallbackAdapter<LlmAdapter> {
|
|
51
|
+
private readonly _adapter;
|
|
52
|
+
private _fallback;
|
|
53
|
+
private readonly _stt;
|
|
54
|
+
private readonly _builder;
|
|
55
|
+
constructor(_adapter: LlmAdapter, _fallback: LlmAdapter | undefined, _stt: WithFallback<SttAdapter>, _builder: PipelineBuilder);
|
|
56
|
+
fallback(adapter: LlmAdapter): this;
|
|
57
|
+
tts(adapter: TtsAdapter): TtsStage;
|
|
58
|
+
toWrapped(): WithFallback<LlmAdapter>;
|
|
59
|
+
}
|
|
60
|
+
declare class TtsStage implements FallbackAdapter<TtsAdapter> {
|
|
61
|
+
private readonly _adapter;
|
|
62
|
+
private _fallback;
|
|
63
|
+
private readonly _stt;
|
|
64
|
+
private readonly _llm;
|
|
65
|
+
private readonly _builder;
|
|
66
|
+
constructor(_adapter: TtsAdapter, _fallback: TtsAdapter | undefined, _stt: WithFallback<SttAdapter>, _llm: WithFallback<LlmAdapter>, _builder: PipelineBuilder);
|
|
67
|
+
fallback(adapter: TtsAdapter): this;
|
|
68
|
+
audioFilter(opts: {
|
|
69
|
+
dir: StreamDir;
|
|
70
|
+
}): this;
|
|
71
|
+
onNewCall(handler: (session: CallSession) => void | Promise<void>): this;
|
|
72
|
+
onCallEnded(handler: (linkedId: string, durationSec: number) => void | Promise<void>): this;
|
|
73
|
+
onTranscript(handler: (result: TranscriptResult, session: CallSession) => void | Promise<void>): this;
|
|
74
|
+
onError(handler: (err: Error, linkedId?: string) => void | Promise<void>): this;
|
|
75
|
+
start(): Promise<void>;
|
|
76
|
+
stop(): Promise<void>;
|
|
77
|
+
}
|
|
78
|
+
export declare class ConferencePipelineBuilder {
|
|
79
|
+
private readonly _builder;
|
|
80
|
+
private readonly _stt;
|
|
81
|
+
private _onTranscript?;
|
|
82
|
+
private _onError?;
|
|
83
|
+
constructor(_builder: PipelineBuilder, _stt: WithFallback<SttAdapter>);
|
|
84
|
+
onTranscript(handler: (result: TranscriptResult, session: CallSession) => void | Promise<void>): this;
|
|
85
|
+
onError(handler: (err: Error, linkedId?: string) => void | Promise<void>): this;
|
|
86
|
+
start(): Promise<void>;
|
|
87
|
+
}
|
|
88
|
+
export declare class PipelineBuilder {
|
|
89
|
+
private readonly wsPool;
|
|
90
|
+
private readonly callEvents;
|
|
91
|
+
private readonly ttsInjector;
|
|
92
|
+
private readonly logger;
|
|
93
|
+
private _dir;
|
|
94
|
+
private _onNewCall?;
|
|
95
|
+
private _onCallEnded?;
|
|
96
|
+
private _onTranscript?;
|
|
97
|
+
private _onError?;
|
|
98
|
+
private _activeCalls;
|
|
99
|
+
private _running;
|
|
100
|
+
constructor(wsPool: WsPool, callEvents: CallEventStream, ttsInjector: TtsInjector, logger: Logger);
|
|
101
|
+
/** Set the STT adapter (first step in fluent chain) */
|
|
102
|
+
stt(adapter: SttAdapter): SttStage;
|
|
103
|
+
private setLlm;
|
|
104
|
+
private setTts;
|
|
105
|
+
private startPipeline;
|
|
106
|
+
private handleCall;
|
|
107
|
+
private startConferencePipeline;
|
|
108
|
+
private stopPipeline;
|
|
109
|
+
}
|
|
110
|
+
export {};
|
|
111
|
+
//# sourceMappingURL=builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/pipeline/builder.ts"],"names":[],"mappings":"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"}
|