@framers/agentos 0.1.83 → 0.1.85
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/orchestration/builders/VoiceNodeBuilder.d.ts +116 -0
- package/dist/orchestration/builders/VoiceNodeBuilder.d.ts.map +1 -0
- package/dist/orchestration/builders/VoiceNodeBuilder.js +140 -0
- package/dist/orchestration/builders/VoiceNodeBuilder.js.map +1 -0
- package/dist/orchestration/builders/WorkflowBuilder.d.ts +40 -1
- package/dist/orchestration/builders/WorkflowBuilder.d.ts.map +1 -1
- package/dist/orchestration/builders/WorkflowBuilder.js +47 -0
- package/dist/orchestration/builders/WorkflowBuilder.js.map +1 -1
- package/dist/orchestration/events/GraphEvent.d.ts +39 -0
- package/dist/orchestration/events/GraphEvent.d.ts.map +1 -1
- package/dist/orchestration/events/GraphEvent.js.map +1 -1
- package/dist/orchestration/ir/types.d.ts +34 -1
- package/dist/orchestration/ir/types.d.ts.map +1 -1
- package/dist/orchestration/runtime/NodeExecutor.d.ts +6 -0
- package/dist/orchestration/runtime/NodeExecutor.d.ts.map +1 -1
- package/dist/orchestration/runtime/NodeExecutor.js +5 -0
- package/dist/orchestration/runtime/NodeExecutor.js.map +1 -1
- package/dist/orchestration/runtime/VoiceNodeExecutor.d.ts +105 -0
- package/dist/orchestration/runtime/VoiceNodeExecutor.d.ts.map +1 -0
- package/dist/orchestration/runtime/VoiceNodeExecutor.js +232 -0
- package/dist/orchestration/runtime/VoiceNodeExecutor.js.map +1 -0
- package/dist/orchestration/runtime/VoiceTransportAdapter.d.ts +157 -0
- package/dist/orchestration/runtime/VoiceTransportAdapter.d.ts.map +1 -0
- package/dist/orchestration/runtime/VoiceTransportAdapter.js +193 -0
- package/dist/orchestration/runtime/VoiceTransportAdapter.js.map +1 -0
- package/dist/orchestration/runtime/VoiceTurnCollector.d.ts +95 -0
- package/dist/orchestration/runtime/VoiceTurnCollector.d.ts.map +1 -0
- package/dist/orchestration/runtime/VoiceTurnCollector.js +148 -0
- package/dist/orchestration/runtime/VoiceTurnCollector.js.map +1 -0
- package/dist/voice-pipeline/VoiceInterruptError.d.ts +52 -0
- package/dist/voice-pipeline/VoiceInterruptError.d.ts.map +1 -0
- package/dist/voice-pipeline/VoiceInterruptError.js +43 -0
- package/dist/voice-pipeline/VoiceInterruptError.js.map +1 -0
- package/dist/voice-pipeline/VoicePipelineOrchestrator.d.ts +44 -1
- package/dist/voice-pipeline/VoicePipelineOrchestrator.d.ts.map +1 -1
- package/dist/voice-pipeline/VoicePipelineOrchestrator.js +63 -0
- package/dist/voice-pipeline/VoicePipelineOrchestrator.js.map +1 -1
- package/dist/voice-pipeline/index.d.ts +1 -0
- package/dist/voice-pipeline/index.d.ts.map +1 -1
- package/dist/voice-pipeline/index.js +1 -0
- package/dist/voice-pipeline/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file VoiceTransportAdapter.ts
|
|
3
|
+
* @description Bridges graph I/O to the voice pipeline when a workflow runs in
|
|
4
|
+
* voice transport mode.
|
|
5
|
+
*
|
|
6
|
+
* `VoiceTransportAdapter` wraps a graph's input/output cycle so that:
|
|
7
|
+
* - **Node input** is obtained by waiting for the user's next speech turn
|
|
8
|
+
* (`waitForUserTurn()` on the underlying `VoicePipelineOrchestrator`).
|
|
9
|
+
* - **Node output** is delivered to the TTS engine (`pushToTTS()` on the
|
|
10
|
+
* underlying `VoicePipelineOrchestrator`).
|
|
11
|
+
*
|
|
12
|
+
* The adapter is lazy — it does not create a `VoicePipelineOrchestrator` until
|
|
13
|
+
* `init()` is called. The pipeline reference is `any` typed to avoid a hard
|
|
14
|
+
* import cycle with the voice subsystem; callers that want stronger types may
|
|
15
|
+
* cast.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* const adapter = new VoiceTransportAdapter(
|
|
20
|
+
* { stt: 'deepgram', tts: 'openai' },
|
|
21
|
+
* transport,
|
|
22
|
+
* (event) => eventBus.emit(event),
|
|
23
|
+
* );
|
|
24
|
+
*
|
|
25
|
+
* await adapter.init(state);
|
|
26
|
+
* const userInput = await adapter.getNodeInput('greet');
|
|
27
|
+
* await adapter.deliverNodeOutput('greet', 'Hello, how can I help you today?');
|
|
28
|
+
* await adapter.dispose();
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// VoiceTransportAdapter
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
/**
|
|
35
|
+
* Adapts a compiled graph's I/O cycle to the real-time voice pipeline.
|
|
36
|
+
*
|
|
37
|
+
* Lifecycle:
|
|
38
|
+
* 1. Construct with {@link VoiceTransportConfig}, an `IStreamTransport`, and an
|
|
39
|
+
* event sink callback.
|
|
40
|
+
* 2. Call `init()` once before the graph starts running.
|
|
41
|
+
* 3. Use `getNodeInput()` to obtain the user's transcribed speech for a node.
|
|
42
|
+
* 4. Use `deliverNodeOutput()` to send the node's response to TTS.
|
|
43
|
+
* 5. Call `dispose()` to clean up resources when the session ends.
|
|
44
|
+
*/
|
|
45
|
+
export class VoiceTransportAdapter {
|
|
46
|
+
/**
|
|
47
|
+
* @param config - Voice pipeline configuration knobs.
|
|
48
|
+
* @param transport - Bidirectional audio/control stream transport (`IStreamTransport`).
|
|
49
|
+
* @param eventSink - Callback receiving all `GraphEvent` values emitted by this adapter.
|
|
50
|
+
*/
|
|
51
|
+
constructor(config, transport, // IStreamTransport
|
|
52
|
+
eventSink) {
|
|
53
|
+
this.config = config;
|
|
54
|
+
this.transport = transport;
|
|
55
|
+
this.eventSink = eventSink;
|
|
56
|
+
/**
|
|
57
|
+
* Lazily-initialised `VoicePipelineOrchestrator` instance.
|
|
58
|
+
* Typed as `any` to avoid a hard import cycle with the voice subsystem.
|
|
59
|
+
* In a full implementation this would be `VoicePipelineOrchestrator | null`.
|
|
60
|
+
*/
|
|
61
|
+
this.pipeline = null; // VoicePipelineOrchestrator (lazy)
|
|
62
|
+
/** Tracks whether `init()` has been called successfully. */
|
|
63
|
+
this.initialized = false;
|
|
64
|
+
}
|
|
65
|
+
// -------------------------------------------------------------------------
|
|
66
|
+
// Lifecycle
|
|
67
|
+
// -------------------------------------------------------------------------
|
|
68
|
+
/**
|
|
69
|
+
* Initialise the adapter.
|
|
70
|
+
*
|
|
71
|
+
* Injects the `IStreamTransport` instance into `state.scratch.voiceTransport` so
|
|
72
|
+
* that graph nodes can access it if needed, then emits a `voice_session` started
|
|
73
|
+
* event to signal that the voice session is live.
|
|
74
|
+
*
|
|
75
|
+
* Must be called exactly once before {@link getNodeInput} or
|
|
76
|
+
* {@link deliverNodeOutput}.
|
|
77
|
+
*
|
|
78
|
+
* @param state - Mutable `GraphState` (or partial) for the current run.
|
|
79
|
+
* `state.scratch` is created lazily if absent.
|
|
80
|
+
*/
|
|
81
|
+
async init(state) {
|
|
82
|
+
var _a;
|
|
83
|
+
// Lazily create the scratch bag if the caller passed a partial state.
|
|
84
|
+
const scratch = ((_a = state).scratch ?? (_a.scratch = {}));
|
|
85
|
+
scratch.voiceTransport = this.transport;
|
|
86
|
+
this.initialized = true;
|
|
87
|
+
this.eventSink({
|
|
88
|
+
type: 'voice_session',
|
|
89
|
+
nodeId: '__transport__',
|
|
90
|
+
action: 'started',
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Wait for the user's next speech turn and return the transcript text.
|
|
95
|
+
*
|
|
96
|
+
* In a full production implementation this delegates to
|
|
97
|
+
* `VoicePipelineOrchestrator.waitForUserTurn()`. In the current implementation
|
|
98
|
+
* it listens for a single `'turn_complete'` event from the underlying transport
|
|
99
|
+
* and resolves with the transcript text.
|
|
100
|
+
*
|
|
101
|
+
* Also emits a {@link GraphEvent} of type `voice_turn_complete` so that the
|
|
102
|
+
* runtime event bus stays in sync.
|
|
103
|
+
*
|
|
104
|
+
* @param nodeId - The id of the graph node requesting input; used to tag the emitted event.
|
|
105
|
+
* @returns Resolved transcript string from the user's speech turn.
|
|
106
|
+
* @throws {Error} If called before `init()`.
|
|
107
|
+
*/
|
|
108
|
+
async getNodeInput(nodeId) {
|
|
109
|
+
if (!this.initialized) {
|
|
110
|
+
throw new Error('VoiceTransportAdapter not initialized');
|
|
111
|
+
}
|
|
112
|
+
// In real implementation: this.pipeline.waitForUserTurn()
|
|
113
|
+
// For now, listen directly to transport events.
|
|
114
|
+
return new Promise((resolve) => {
|
|
115
|
+
this.transport.once('turn_complete', (evt) => {
|
|
116
|
+
const transcript = evt?.transcript ?? evt?.text ?? '';
|
|
117
|
+
this.eventSink({
|
|
118
|
+
type: 'voice_turn_complete',
|
|
119
|
+
nodeId,
|
|
120
|
+
transcript,
|
|
121
|
+
turnIndex: 0,
|
|
122
|
+
endpointReason: evt?.reason ?? 'unknown',
|
|
123
|
+
});
|
|
124
|
+
resolve(transcript);
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Deliver a node's text output to the TTS engine.
|
|
130
|
+
*
|
|
131
|
+
* Accepts either a plain `string` or an `AsyncIterable<string>` of token
|
|
132
|
+
* chunks (e.g. a streaming LLM response). In a full production implementation
|
|
133
|
+
* this delegates to `VoicePipelineOrchestrator.pushToTTS(output)`.
|
|
134
|
+
*
|
|
135
|
+
* Emits a {@link GraphEvent} of type `voice_audio` (direction `'outbound'`)
|
|
136
|
+
* so that the runtime event bus records the TTS delivery.
|
|
137
|
+
*
|
|
138
|
+
* @param nodeId - The id of the graph node delivering the output.
|
|
139
|
+
* @param output - Text or async token stream to synthesise as speech.
|
|
140
|
+
* @throws {Error} If called before `init()`.
|
|
141
|
+
*/
|
|
142
|
+
async deliverNodeOutput(nodeId, output) {
|
|
143
|
+
if (!this.initialized) {
|
|
144
|
+
throw new Error('VoiceTransportAdapter not initialized');
|
|
145
|
+
}
|
|
146
|
+
// In real implementation: this.pipeline.pushToTTS(output)
|
|
147
|
+
// For now, emit the event to signal delivery.
|
|
148
|
+
this.eventSink({
|
|
149
|
+
type: 'voice_audio',
|
|
150
|
+
nodeId,
|
|
151
|
+
direction: 'outbound',
|
|
152
|
+
format: 'tts',
|
|
153
|
+
durationMs: 0,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
// -------------------------------------------------------------------------
|
|
157
|
+
// Barge-in
|
|
158
|
+
// -------------------------------------------------------------------------
|
|
159
|
+
/**
|
|
160
|
+
* Handle a user barge-in at the transport level.
|
|
161
|
+
*
|
|
162
|
+
* Should be called by the runtime or transport layer when the user starts
|
|
163
|
+
* speaking while the agent is mid-utterance. Emits a `voice_barge_in` event
|
|
164
|
+
* so that graph event consumers can react (e.g. cancel pending tool calls).
|
|
165
|
+
*/
|
|
166
|
+
handleBargeIn() {
|
|
167
|
+
this.eventSink({
|
|
168
|
+
type: 'voice_barge_in',
|
|
169
|
+
nodeId: '__transport__',
|
|
170
|
+
interruptedText: '',
|
|
171
|
+
userSpeech: '',
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
// -------------------------------------------------------------------------
|
|
175
|
+
// Disposal
|
|
176
|
+
// -------------------------------------------------------------------------
|
|
177
|
+
/**
|
|
178
|
+
* Dispose the adapter and emit a `voice_session` ended event.
|
|
179
|
+
*
|
|
180
|
+
* Marks the adapter as uninitialised so subsequent calls to `getNodeInput()`
|
|
181
|
+
* or `deliverNodeOutput()` will throw, preventing accidental use after teardown.
|
|
182
|
+
*/
|
|
183
|
+
async dispose() {
|
|
184
|
+
this.eventSink({
|
|
185
|
+
type: 'voice_session',
|
|
186
|
+
nodeId: '__transport__',
|
|
187
|
+
action: 'ended',
|
|
188
|
+
exitReason: 'transport-disposed',
|
|
189
|
+
});
|
|
190
|
+
this.initialized = false;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=VoiceTransportAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VoiceTransportAdapter.js","sourceRoot":"","sources":["../../../src/orchestration/runtime/VoiceTransportAdapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AA2CH,8EAA8E;AAC9E,wBAAwB;AACxB,8EAA8E;AAE9E;;;;;;;;;;GAUG;AACH,MAAM,OAAO,qBAAqB;IAWhC;;;;OAIG;IACH,YACmB,MAA4B,EAC5B,SAAc,EAAE,mBAAmB;IACnC,SAAsC;QAFtC,WAAM,GAAN,MAAM,CAAsB;QAC5B,cAAS,GAAT,SAAS,CAAK;QACd,cAAS,GAAT,SAAS,CAA6B;QAlBzD;;;;WAIG;QACK,aAAQ,GAAe,IAAI,CAAC,CAAC,mCAAmC;QAExE,4DAA4D;QACpD,gBAAW,GAAG,KAAK,CAAC;IAWzB,CAAC;IAEJ,4EAA4E;IAC5E,YAAY;IACZ,4EAA4E;IAE5E;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,IAAI,CAAC,KAA0B;;QACnC,sEAAsE;QACtE,MAAM,OAAO,GAAG,OAAE,KAAa,EAAC,OAAO,QAAP,OAAO,GAAK,EAAE,EAAC,CAAC;QAChD,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC;QACxC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QAExB,IAAI,CAAC,SAAS,CAAC;YACb,IAAI,EAAE,eAAe;YACrB,MAAM,EAAE,eAAe;YACvB,MAAM,EAAE,SAAS;SAClB,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,YAAY,CAAC,MAAc;QAC/B,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC3D,CAAC;QAED,0DAA0D;QAC1D,gDAAgD;QAChD,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;YACrC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,GAAQ,EAAE,EAAE;gBAChD,MAAM,UAAU,GAAW,GAAG,EAAE,UAAU,IAAI,GAAG,EAAE,IAAI,IAAI,EAAE,CAAC;gBAE9D,IAAI,CAAC,SAAS,CAAC;oBACb,IAAI,EAAE,qBAAqB;oBAC3B,MAAM;oBACN,UAAU;oBACV,SAAS,EAAE,CAAC;oBACZ,cAAc,EAAE,GAAG,EAAE,MAAM,IAAI,SAAS;iBACzC,CAAC,CAAC;gBAEH,OAAO,CAAC,UAAU,CAAC,CAAC;YACtB,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,iBAAiB,CAAC,MAAc,EAAE,MAAsC;QAC5E,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC3D,CAAC;QAED,0DAA0D;QAC1D,8CAA8C;QAC9C,IAAI,CAAC,SAAS,CAAC;YACb,IAAI,EAAE,aAAa;YACnB,MAAM;YACN,SAAS,EAAE,UAAU;YACrB,MAAM,EAAE,KAAK;YACb,UAAU,EAAE,CAAC;SACd,CAAC,CAAC;IACL,CAAC;IAED,4EAA4E;IAC5E,WAAW;IACX,4EAA4E;IAE5E;;;;;;OAMG;IACH,aAAa;QACX,IAAI,CAAC,SAAS,CAAC;YACb,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,eAAe;YACvB,eAAe,EAAE,EAAE;YACnB,UAAU,EAAE,EAAE;SACf,CAAC,CAAC;IACL,CAAC;IAED,4EAA4E;IAC5E,WAAW;IACX,4EAA4E;IAE5E;;;;;OAKG;IACH,KAAK,CAAC,OAAO;QACX,IAAI,CAAC,SAAS,CAAC;YACb,IAAI,EAAE,eAAe;YACrB,MAAM,EAAE,eAAe;YACvB,MAAM,EAAE,OAAO;YACf,UAAU,EAAE,oBAAoB;SACjC,CAAC,CAAC;QACH,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;IAC3B,CAAC;CACF"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file VoiceTurnCollector.ts
|
|
3
|
+
* @description Subscribes to voice pipeline session events and maintains a
|
|
4
|
+
* running transcript buffer, turn counter, and last-speaker tracker.
|
|
5
|
+
*
|
|
6
|
+
* The collector bridges the raw EventEmitter-based voice pipeline session into
|
|
7
|
+
* the typed `GraphEvent` stream consumed by the graph runtime. Four session
|
|
8
|
+
* events are handled:
|
|
9
|
+
*
|
|
10
|
+
* - `interim_transcript` — partial STT result; forwarded as a non-final
|
|
11
|
+
* `voice_transcript` GraphEvent but **not** buffered (too noisy).
|
|
12
|
+
* - `final_transcript` — confirmed STT result; buffered in `transcript` and
|
|
13
|
+
* forwarded as a final `voice_transcript` GraphEvent.
|
|
14
|
+
* - `turn_complete` — endpoint detection fired; increments `turnCount` and
|
|
15
|
+
* emits a `voice_turn_complete` GraphEvent.
|
|
16
|
+
* - `barge_in` — user interrupted the agent mid-speech; emits a
|
|
17
|
+
* `voice_barge_in` GraphEvent.
|
|
18
|
+
*
|
|
19
|
+
* The `initialTurnCount` constructor parameter enables checkpoint restore:
|
|
20
|
+
* pass the previously persisted count so that `turnIndex` values continue
|
|
21
|
+
* from where the session left off rather than resetting to zero.
|
|
22
|
+
*/
|
|
23
|
+
import { EventEmitter } from 'events';
|
|
24
|
+
import type { GraphEvent } from '../events/GraphEvent.js';
|
|
25
|
+
/**
|
|
26
|
+
* A single confirmed (final) utterance captured from the voice pipeline.
|
|
27
|
+
*
|
|
28
|
+
* Only `final_transcript` events populate this buffer — interim partials are
|
|
29
|
+
* discarded to keep the transcript clean and avoid duplicate entries.
|
|
30
|
+
*/
|
|
31
|
+
export interface TranscriptEntry {
|
|
32
|
+
/** Speaker identifier as reported by the STT service (e.g. `"Speaker_0"`). */
|
|
33
|
+
speaker: string;
|
|
34
|
+
/** Recognised text for this utterance. */
|
|
35
|
+
text: string;
|
|
36
|
+
/**
|
|
37
|
+
* Wall-clock timestamp (milliseconds since Unix epoch) recorded at the
|
|
38
|
+
* moment the `final_transcript` event was processed.
|
|
39
|
+
*/
|
|
40
|
+
timestamp: number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Stateful collector that subscribes to a voice pipeline session and routes
|
|
44
|
+
* session events into the AgentOS `GraphEvent` stream.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* const collector = new VoiceTurnCollector(
|
|
49
|
+
* session,
|
|
50
|
+
* (evt) => graphEventEmitter.emit(evt),
|
|
51
|
+
* 'voice-node-1',
|
|
52
|
+
* );
|
|
53
|
+
*
|
|
54
|
+
* // After the conversation:
|
|
55
|
+
* console.log(collector.getTurnCount()); // number of completed turns
|
|
56
|
+
* console.log(collector.getTranscript()); // full buffered transcript
|
|
57
|
+
* console.log(collector.getLastSpeaker()); // last identified speaker
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare class VoiceTurnCollector {
|
|
61
|
+
private readonly eventSink;
|
|
62
|
+
private readonly nodeId;
|
|
63
|
+
/** Buffered confirmed utterances in chronological order. */
|
|
64
|
+
private transcript;
|
|
65
|
+
/** Running count of completed turns (endpoint-detected). */
|
|
66
|
+
private turnCount;
|
|
67
|
+
/** Speaker identifier from the most recent `final_transcript` event. */
|
|
68
|
+
private lastSpeaker;
|
|
69
|
+
/**
|
|
70
|
+
* @param session - The voice pipeline `EventEmitter` to subscribe to.
|
|
71
|
+
* @param eventSink - Callback invoked synchronously for every emitted `GraphEvent`.
|
|
72
|
+
* @param nodeId - Identifies the owning graph node in every emitted event.
|
|
73
|
+
* @param initialTurnCount - Seed value for `turnCount`; pass a persisted value to
|
|
74
|
+
* resume from a checkpoint rather than starting at zero.
|
|
75
|
+
*/
|
|
76
|
+
constructor(session: EventEmitter, eventSink: (event: GraphEvent) => void, nodeId: string, initialTurnCount?: number);
|
|
77
|
+
/**
|
|
78
|
+
* Returns the total number of completed turns since construction (or since the
|
|
79
|
+
* provided `initialTurnCount` when restoring from a checkpoint).
|
|
80
|
+
*/
|
|
81
|
+
getTurnCount(): number;
|
|
82
|
+
/**
|
|
83
|
+
* Returns a shallow copy of the buffered transcript entries.
|
|
84
|
+
*
|
|
85
|
+
* A copy is returned to prevent external callers from mutating the internal
|
|
86
|
+
* buffer — entries are append-only and must remain ordered.
|
|
87
|
+
*/
|
|
88
|
+
getTranscript(): TranscriptEntry[];
|
|
89
|
+
/**
|
|
90
|
+
* Returns the speaker identifier from the most recent `final_transcript` event,
|
|
91
|
+
* or an empty string if no final transcript has been received yet.
|
|
92
|
+
*/
|
|
93
|
+
getLastSpeaker(): string;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=VoiceTurnCollector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VoiceTurnCollector.d.ts","sourceRoot":"","sources":["../../../src/orchestration/runtime/VoiceTurnCollector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAM1D;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,8EAA8E;IAC9E,OAAO,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,kBAAkB;IAmB3B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAnBzB,4DAA4D;IAC5D,OAAO,CAAC,UAAU,CAAyB;IAE3C,4DAA4D;IAC5D,OAAO,CAAC,SAAS,CAAS;IAE1B,wEAAwE;IACxE,OAAO,CAAC,WAAW,CAAM;IAEzB;;;;;;OAMG;gBAED,OAAO,EAAE,YAAY,EACJ,SAAS,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,EACtC,MAAM,EAAE,MAAM,EAC/B,gBAAgB,SAAI;IA6EtB;;;OAGG;IACH,YAAY,IAAI,MAAM;IAItB;;;;;OAKG;IACH,aAAa,IAAI,eAAe,EAAE;IAIlC;;;OAGG;IACH,cAAc,IAAI,MAAM;CAGzB"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file VoiceTurnCollector.ts
|
|
3
|
+
* @description Subscribes to voice pipeline session events and maintains a
|
|
4
|
+
* running transcript buffer, turn counter, and last-speaker tracker.
|
|
5
|
+
*
|
|
6
|
+
* The collector bridges the raw EventEmitter-based voice pipeline session into
|
|
7
|
+
* the typed `GraphEvent` stream consumed by the graph runtime. Four session
|
|
8
|
+
* events are handled:
|
|
9
|
+
*
|
|
10
|
+
* - `interim_transcript` — partial STT result; forwarded as a non-final
|
|
11
|
+
* `voice_transcript` GraphEvent but **not** buffered (too noisy).
|
|
12
|
+
* - `final_transcript` — confirmed STT result; buffered in `transcript` and
|
|
13
|
+
* forwarded as a final `voice_transcript` GraphEvent.
|
|
14
|
+
* - `turn_complete` — endpoint detection fired; increments `turnCount` and
|
|
15
|
+
* emits a `voice_turn_complete` GraphEvent.
|
|
16
|
+
* - `barge_in` — user interrupted the agent mid-speech; emits a
|
|
17
|
+
* `voice_barge_in` GraphEvent.
|
|
18
|
+
*
|
|
19
|
+
* The `initialTurnCount` constructor parameter enables checkpoint restore:
|
|
20
|
+
* pass the previously persisted count so that `turnIndex` values continue
|
|
21
|
+
* from where the session left off rather than resetting to zero.
|
|
22
|
+
*/
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// VoiceTurnCollector
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
/**
|
|
27
|
+
* Stateful collector that subscribes to a voice pipeline session and routes
|
|
28
|
+
* session events into the AgentOS `GraphEvent` stream.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* const collector = new VoiceTurnCollector(
|
|
33
|
+
* session,
|
|
34
|
+
* (evt) => graphEventEmitter.emit(evt),
|
|
35
|
+
* 'voice-node-1',
|
|
36
|
+
* );
|
|
37
|
+
*
|
|
38
|
+
* // After the conversation:
|
|
39
|
+
* console.log(collector.getTurnCount()); // number of completed turns
|
|
40
|
+
* console.log(collector.getTranscript()); // full buffered transcript
|
|
41
|
+
* console.log(collector.getLastSpeaker()); // last identified speaker
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export class VoiceTurnCollector {
|
|
45
|
+
/**
|
|
46
|
+
* @param session - The voice pipeline `EventEmitter` to subscribe to.
|
|
47
|
+
* @param eventSink - Callback invoked synchronously for every emitted `GraphEvent`.
|
|
48
|
+
* @param nodeId - Identifies the owning graph node in every emitted event.
|
|
49
|
+
* @param initialTurnCount - Seed value for `turnCount`; pass a persisted value to
|
|
50
|
+
* resume from a checkpoint rather than starting at zero.
|
|
51
|
+
*/
|
|
52
|
+
constructor(session, eventSink, nodeId, initialTurnCount = 0) {
|
|
53
|
+
this.eventSink = eventSink;
|
|
54
|
+
this.nodeId = nodeId;
|
|
55
|
+
/** Buffered confirmed utterances in chronological order. */
|
|
56
|
+
this.transcript = [];
|
|
57
|
+
/** Speaker identifier from the most recent `final_transcript` event. */
|
|
58
|
+
this.lastSpeaker = '';
|
|
59
|
+
this.turnCount = initialTurnCount;
|
|
60
|
+
// ------------------------------------------------------------------
|
|
61
|
+
// interim_transcript — partial STT result, forwarded but not buffered
|
|
62
|
+
// ------------------------------------------------------------------
|
|
63
|
+
session.on('interim_transcript', (evt) => {
|
|
64
|
+
this.eventSink({
|
|
65
|
+
type: 'voice_transcript',
|
|
66
|
+
nodeId: this.nodeId,
|
|
67
|
+
text: evt.text ?? '',
|
|
68
|
+
isFinal: false,
|
|
69
|
+
speaker: evt.speaker,
|
|
70
|
+
confidence: evt.confidence ?? 0,
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
// ------------------------------------------------------------------
|
|
74
|
+
// final_transcript — confirmed utterance, buffered and forwarded
|
|
75
|
+
// ------------------------------------------------------------------
|
|
76
|
+
session.on('final_transcript', (evt) => {
|
|
77
|
+
const speaker = evt.speaker ?? 'user';
|
|
78
|
+
// Buffer the confirmed entry for downstream consumers.
|
|
79
|
+
this.transcript.push({
|
|
80
|
+
speaker,
|
|
81
|
+
text: evt.text ?? '',
|
|
82
|
+
timestamp: Date.now(),
|
|
83
|
+
});
|
|
84
|
+
// Track the most recent speaker for quick access without iterating the buffer.
|
|
85
|
+
this.lastSpeaker = speaker;
|
|
86
|
+
this.eventSink({
|
|
87
|
+
type: 'voice_transcript',
|
|
88
|
+
nodeId: this.nodeId,
|
|
89
|
+
text: evt.text ?? '',
|
|
90
|
+
isFinal: true,
|
|
91
|
+
speaker,
|
|
92
|
+
confidence: evt.confidence ?? 0,
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
// ------------------------------------------------------------------
|
|
96
|
+
// turn_complete — endpoint detection fired; advance the turn counter
|
|
97
|
+
// ------------------------------------------------------------------
|
|
98
|
+
session.on('turn_complete', (evt) => {
|
|
99
|
+
// Increment before emitting so that turnIndex reflects the new count.
|
|
100
|
+
this.turnCount++;
|
|
101
|
+
this.eventSink({
|
|
102
|
+
type: 'voice_turn_complete',
|
|
103
|
+
nodeId: this.nodeId,
|
|
104
|
+
transcript: evt.transcript ?? '',
|
|
105
|
+
turnIndex: this.turnCount,
|
|
106
|
+
endpointReason: evt.reason ?? 'unknown',
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
// ------------------------------------------------------------------
|
|
110
|
+
// barge_in — user interrupted agent mid-speech
|
|
111
|
+
// ------------------------------------------------------------------
|
|
112
|
+
session.on('barge_in', (evt) => {
|
|
113
|
+
this.eventSink({
|
|
114
|
+
type: 'voice_barge_in',
|
|
115
|
+
nodeId: this.nodeId,
|
|
116
|
+
interruptedText: evt.interruptedText ?? '',
|
|
117
|
+
userSpeech: evt.userSpeech ?? '',
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
// ---------------------------------------------------------------------------
|
|
122
|
+
// Accessors
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
/**
|
|
125
|
+
* Returns the total number of completed turns since construction (or since the
|
|
126
|
+
* provided `initialTurnCount` when restoring from a checkpoint).
|
|
127
|
+
*/
|
|
128
|
+
getTurnCount() {
|
|
129
|
+
return this.turnCount;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Returns a shallow copy of the buffered transcript entries.
|
|
133
|
+
*
|
|
134
|
+
* A copy is returned to prevent external callers from mutating the internal
|
|
135
|
+
* buffer — entries are append-only and must remain ordered.
|
|
136
|
+
*/
|
|
137
|
+
getTranscript() {
|
|
138
|
+
return [...this.transcript];
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Returns the speaker identifier from the most recent `final_transcript` event,
|
|
142
|
+
* or an empty string if no final transcript has been received yet.
|
|
143
|
+
*/
|
|
144
|
+
getLastSpeaker() {
|
|
145
|
+
return this.lastSpeaker;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=VoiceTurnCollector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VoiceTurnCollector.js","sourceRoot":"","sources":["../../../src/orchestration/runtime/VoiceTurnCollector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module voice-pipeline/VoiceInterruptError
|
|
3
|
+
*
|
|
4
|
+
* Typed error thrown when a voice session is interrupted by user barge-in.
|
|
5
|
+
* Used by VoiceNodeExecutor to catch barge-in AbortSignal and return
|
|
6
|
+
* a structured result instead of propagating the error.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Structured error representing a user barge-in interruption during TTS playback.
|
|
10
|
+
*
|
|
11
|
+
* Thrown (or returned as a typed sentinel) when the user speaks over the agent.
|
|
12
|
+
* Consumers can inspect `interruptedText`, `userSpeech`, and `playedDurationMs`
|
|
13
|
+
* to decide how to resume or branch the conversation graph.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* try {
|
|
18
|
+
* await voiceNode.run(context);
|
|
19
|
+
* } catch (err) {
|
|
20
|
+
* if (err instanceof VoiceInterruptError) {
|
|
21
|
+
* console.log(`Interrupted after ${err.playedDurationMs}ms`);
|
|
22
|
+
* await handleBargein(err.userSpeech);
|
|
23
|
+
* }
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare class VoiceInterruptError extends Error {
|
|
28
|
+
/** Discriminant name — always `'VoiceInterruptError'` for `instanceof`-free checks. */
|
|
29
|
+
readonly name = "VoiceInterruptError";
|
|
30
|
+
/** The text the agent was speaking when interrupted. */
|
|
31
|
+
readonly interruptedText: string;
|
|
32
|
+
/** What the user said that caused the interruption. */
|
|
33
|
+
readonly userSpeech: string;
|
|
34
|
+
/**
|
|
35
|
+
* How much of the agent's response was already played (ms).
|
|
36
|
+
* Derived from the cumulative `durationMs` of `EncodedAudioChunk`s sent
|
|
37
|
+
* to the transport before the barge-in was detected.
|
|
38
|
+
*/
|
|
39
|
+
readonly playedDurationMs: number;
|
|
40
|
+
/**
|
|
41
|
+
* @param context - Barge-in context captured at the moment of interruption.
|
|
42
|
+
* @param context.interruptedText - Full TTS text the agent was speaking.
|
|
43
|
+
* @param context.userSpeech - Transcript of the user's barge-in utterance.
|
|
44
|
+
* @param context.playedDurationMs - Milliseconds of audio already played.
|
|
45
|
+
*/
|
|
46
|
+
constructor(context: {
|
|
47
|
+
interruptedText: string;
|
|
48
|
+
userSpeech: string;
|
|
49
|
+
playedDurationMs: number;
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=VoiceInterruptError.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VoiceInterruptError.d.ts","sourceRoot":"","sources":["../../src/voice-pipeline/VoiceInterruptError.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,uFAAuF;IACvF,QAAQ,CAAC,IAAI,yBAAyB;IAEtC,wDAAwD;IACxD,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IAEjC,uDAAuD;IACvD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAE5B;;;;OAIG;IACH,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAElC;;;;;OAKG;gBACS,OAAO,EAAE;QACnB,eAAe,EAAE,MAAM,CAAC;QACxB,UAAU,EAAE,MAAM,CAAC;QACnB,gBAAgB,EAAE,MAAM,CAAC;KAC1B;CAMF"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module voice-pipeline/VoiceInterruptError
|
|
3
|
+
*
|
|
4
|
+
* Typed error thrown when a voice session is interrupted by user barge-in.
|
|
5
|
+
* Used by VoiceNodeExecutor to catch barge-in AbortSignal and return
|
|
6
|
+
* a structured result instead of propagating the error.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Structured error representing a user barge-in interruption during TTS playback.
|
|
10
|
+
*
|
|
11
|
+
* Thrown (or returned as a typed sentinel) when the user speaks over the agent.
|
|
12
|
+
* Consumers can inspect `interruptedText`, `userSpeech`, and `playedDurationMs`
|
|
13
|
+
* to decide how to resume or branch the conversation graph.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* try {
|
|
18
|
+
* await voiceNode.run(context);
|
|
19
|
+
* } catch (err) {
|
|
20
|
+
* if (err instanceof VoiceInterruptError) {
|
|
21
|
+
* console.log(`Interrupted after ${err.playedDurationMs}ms`);
|
|
22
|
+
* await handleBargein(err.userSpeech);
|
|
23
|
+
* }
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export class VoiceInterruptError extends Error {
|
|
28
|
+
/**
|
|
29
|
+
* @param context - Barge-in context captured at the moment of interruption.
|
|
30
|
+
* @param context.interruptedText - Full TTS text the agent was speaking.
|
|
31
|
+
* @param context.userSpeech - Transcript of the user's barge-in utterance.
|
|
32
|
+
* @param context.playedDurationMs - Milliseconds of audio already played.
|
|
33
|
+
*/
|
|
34
|
+
constructor(context) {
|
|
35
|
+
super('Voice session interrupted by user');
|
|
36
|
+
/** Discriminant name — always `'VoiceInterruptError'` for `instanceof`-free checks. */
|
|
37
|
+
this.name = 'VoiceInterruptError';
|
|
38
|
+
this.interruptedText = context.interruptedText;
|
|
39
|
+
this.userSpeech = context.userSpeech;
|
|
40
|
+
this.playedDurationMs = context.playedDurationMs;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=VoiceInterruptError.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VoiceInterruptError.js","sourceRoot":"","sources":["../../src/voice-pipeline/VoiceInterruptError.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAiB5C;;;;;OAKG;IACH,YAAY,OAIX;QACC,KAAK,CAAC,mCAAmC,CAAC,CAAC;QA3B7C,uFAAuF;QAC9E,SAAI,GAAG,qBAAqB,CAAC;QA2BpC,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC;QAC/C,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QACrC,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IACnD,CAAC;CACF"}
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* ```
|
|
17
17
|
*/
|
|
18
18
|
import { EventEmitter } from 'node:events';
|
|
19
|
-
import type { IBargeinHandler, IDiarizationEngine, IEndpointDetector, IStreamTransport, IStreamingSTT, IStreamingTTS, IVoicePipelineAgentSession, PipelineState, VoicePipelineConfig, VoicePipelineSession } from './types.js';
|
|
19
|
+
import type { IBargeinHandler, IDiarizationEngine, IEndpointDetector, IStreamTransport, IStreamingSTT, IStreamingTTS, IVoicePipelineAgentSession, PipelineState, TurnCompleteEvent, VoicePipelineConfig, VoicePipelineSession } from './types.js';
|
|
20
20
|
/**
|
|
21
21
|
* Overrides for injecting pre-built components (primarily for testing).
|
|
22
22
|
* In production, components would be resolved from ExtensionManager.
|
|
@@ -78,6 +78,49 @@ export declare class VoicePipelineOrchestrator extends EventEmitter {
|
|
|
78
78
|
* @param reason - Optional human-readable reason for diagnostics.
|
|
79
79
|
*/
|
|
80
80
|
stopSession(reason?: string): Promise<void>;
|
|
81
|
+
/**
|
|
82
|
+
* Wait for the next user turn to complete.
|
|
83
|
+
*
|
|
84
|
+
* Wraps the internal `'turn_complete'` event in a one-shot Promise so that
|
|
85
|
+
* graph nodes (via VoiceTransportAdapter) can `await` user input without
|
|
86
|
+
* having to manage raw EventEmitter subscriptions themselves.
|
|
87
|
+
*
|
|
88
|
+
* Resolves with the first `TurnCompleteEvent` fired after this call.
|
|
89
|
+
* If the session is closed before a turn completes, the Promise will never
|
|
90
|
+
* resolve — callers should race it against a session-close signal if needed.
|
|
91
|
+
*
|
|
92
|
+
* @returns A Promise that resolves with the completed turn event.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```typescript
|
|
96
|
+
* const turn = await orchestrator.waitForUserTurn();
|
|
97
|
+
* console.log('User said:', turn.transcript);
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
waitForUserTurn(): Promise<TurnCompleteEvent>;
|
|
101
|
+
/**
|
|
102
|
+
* Push text to the active TTS session.
|
|
103
|
+
*
|
|
104
|
+
* Accepts either a plain string or an `AsyncIterable<string>` of token chunks
|
|
105
|
+
* (e.g. a streaming LLM response). Calls `pushTokens()` on the active TTS
|
|
106
|
+
* session for each token, then calls `flush()` to signal end-of-utterance.
|
|
107
|
+
*
|
|
108
|
+
* Used by VoiceTransportAdapter to deliver graph node output as speech
|
|
109
|
+
* without the caller needing a direct reference to the TTS session.
|
|
110
|
+
*
|
|
111
|
+
* @param text - A complete string, or an async iterable of string tokens.
|
|
112
|
+
* @throws {Error} If there is no active TTS session (i.e. session not started).
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```typescript
|
|
116
|
+
* // Plain string
|
|
117
|
+
* await orchestrator.pushToTTS('Hello, how can I help?');
|
|
118
|
+
*
|
|
119
|
+
* // Streaming tokens from an LLM
|
|
120
|
+
* await orchestrator.pushToTTS(llm.streamTokens(prompt));
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
pushToTTS(text: string | AsyncIterable<string>): Promise<void>;
|
|
81
124
|
/**
|
|
82
125
|
* Forward audio frames from transport to STT session.
|
|
83
126
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VoicePipelineOrchestrator.d.ts","sourceRoot":"","sources":["../../src/voice-pipeline/VoicePipelineOrchestrator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,OAAO,KAAK,EAGV,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,0BAA0B,EAC1B,aAAa,
|
|
1
|
+
{"version":3,"file":"VoicePipelineOrchestrator.d.ts","sourceRoot":"","sources":["../../src/voice-pipeline/VoicePipelineOrchestrator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,OAAO,KAAK,EAGV,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,0BAA0B,EAC1B,aAAa,EAIb,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EAErB,MAAM,YAAY,CAAC;AAEpB;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC,wCAAwC;IACxC,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B,wCAAwC;IACxC,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B,mCAAmC;IACnC,gBAAgB,CAAC,EAAE,iBAAiB,CAAC;IACrC,kCAAkC;IAClC,cAAc,CAAC,EAAE,eAAe,CAAC;IACjC,oCAAoC;IACpC,iBAAiB,CAAC,EAAE,kBAAkB,CAAC;CACxC;AAED;;;;;;;;GAQG;AACH,qBAAa,yBAA0B,SAAQ,YAAY;IA0B7C,OAAO,CAAC,QAAQ,CAAC,MAAM;IAzBnC,8BAA8B;IAC9B,OAAO,CAAC,MAAM,CAAyB;IAEvC,mEAAmE;IACnE,OAAO,CAAC,WAAW,CAAoC;IACvD,OAAO,CAAC,WAAW,CAAoC;IACvD,OAAO,CAAC,iBAAiB,CAAkC;IAC3D,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,UAAU,CAAiC;IACnD,OAAO,CAAC,aAAa,CAA2C;IAEhE,+CAA+C;IAC/C,OAAO,CAAC,cAAc,CAA8C;IAEpE,uDAAuD;IACvD,OAAO,CAAC,eAAe,CAAM;IAE7B,8DAA8D;IAC9D,OAAO,CAAC,gBAAgB,CAAK;IAE7B,0CAA0C;IAC1C,IAAI,KAAK,IAAI,aAAa,CAEzB;gBAE4B,MAAM,EAAE,mBAAmB;IAIxD;;;;;;;;OAQG;IACG,YAAY,CAChB,SAAS,EAAE,gBAAgB,EAC3B,YAAY,EAAE,0BAA0B,EACxC,SAAS,CAAC,EAAE,sBAAsB,GACjC,OAAO,CAAC,oBAAoB,CAAC;IAiEhC;;;;OAIG;IACG,WAAW,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBjD;;;;;;;;;;;;;;;;;;OAkBG;IACG,eAAe,IAAI,OAAO,CAAC,iBAAiB,CAAC;IAMnD;;;;;;;;;;;;;;;;;;;;;OAqBG;IACG,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBpE;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAS3B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAgB1B;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAuCzB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAyB3B;;;OAGG;IACH,OAAO,CAAC,YAAY;IA8CpB;;OAEG;IACH,OAAO,CAAC,eAAe;IAiBvB;;OAEG;IACH,OAAO,CAAC,SAAS;IAWjB;;;;OAIG;IACH,OAAO,CAAC,cAAc;IActB;;OAEG;IACH,OAAO,CAAC,cAAc;CAMvB"}
|