@framers/agentos 0.1.75 → 0.1.76

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 (130) hide show
  1. package/README.md +139 -34
  2. package/dist/core/agency/AgentCommunicationBus.d.ts +1 -0
  3. package/dist/core/agency/AgentCommunicationBus.d.ts.map +1 -1
  4. package/dist/core/agency/AgentCommunicationBus.js +62 -8
  5. package/dist/core/agency/AgentCommunicationBus.js.map +1 -1
  6. package/dist/core/agency/IAgentCommunicationBus.d.ts +1 -1
  7. package/dist/core/agency/IAgentCommunicationBus.d.ts.map +1 -1
  8. package/dist/orchestration/runtime/LoopController.d.ts +10 -10
  9. package/dist/orchestration/runtime/LoopController.d.ts.map +1 -1
  10. package/dist/orchestration/runtime/LoopController.js +1 -1
  11. package/dist/orchestration/runtime/LoopController.js.map +1 -1
  12. package/dist/orchestration/runtime/index.d.ts +1 -1
  13. package/dist/orchestration/runtime/index.d.ts.map +1 -1
  14. package/dist/orchestration/runtime/index.js.map +1 -1
  15. package/dist/speech/FallbackProxy.d.ts +104 -0
  16. package/dist/speech/FallbackProxy.d.ts.map +1 -0
  17. package/dist/speech/FallbackProxy.js +151 -0
  18. package/dist/speech/FallbackProxy.js.map +1 -0
  19. package/dist/speech/SpeechProviderResolver.d.ts +103 -0
  20. package/dist/speech/SpeechProviderResolver.d.ts.map +1 -0
  21. package/dist/speech/SpeechProviderResolver.js +256 -0
  22. package/dist/speech/SpeechProviderResolver.js.map +1 -0
  23. package/dist/speech/SpeechRuntime.d.ts +23 -1
  24. package/dist/speech/SpeechRuntime.d.ts.map +1 -1
  25. package/dist/speech/SpeechRuntime.js +82 -8
  26. package/dist/speech/SpeechRuntime.js.map +1 -1
  27. package/dist/speech/index.d.ts +6 -0
  28. package/dist/speech/index.d.ts.map +1 -1
  29. package/dist/speech/index.js +6 -0
  30. package/dist/speech/index.js.map +1 -1
  31. package/dist/speech/providerCatalog.d.ts.map +1 -1
  32. package/dist/speech/providerCatalog.js +15 -1
  33. package/dist/speech/providerCatalog.js.map +1 -1
  34. package/dist/speech/providers/AssemblyAISTTProvider.d.ts +49 -0
  35. package/dist/speech/providers/AssemblyAISTTProvider.d.ts.map +1 -0
  36. package/dist/speech/providers/AssemblyAISTTProvider.js +151 -0
  37. package/dist/speech/providers/AssemblyAISTTProvider.js.map +1 -0
  38. package/dist/speech/providers/AzureSpeechSTTProvider.d.ts +48 -0
  39. package/dist/speech/providers/AzureSpeechSTTProvider.d.ts.map +1 -0
  40. package/dist/speech/providers/AzureSpeechSTTProvider.js +90 -0
  41. package/dist/speech/providers/AzureSpeechSTTProvider.js.map +1 -0
  42. package/dist/speech/providers/AzureSpeechTTSProvider.d.ts +60 -0
  43. package/dist/speech/providers/AzureSpeechTTSProvider.d.ts.map +1 -0
  44. package/dist/speech/providers/AzureSpeechTTSProvider.js +127 -0
  45. package/dist/speech/providers/AzureSpeechTTSProvider.js.map +1 -0
  46. package/dist/speech/providers/DeepgramBatchSTTProvider.d.ts +55 -0
  47. package/dist/speech/providers/DeepgramBatchSTTProvider.d.ts.map +1 -0
  48. package/dist/speech/providers/DeepgramBatchSTTProvider.js +102 -0
  49. package/dist/speech/providers/DeepgramBatchSTTProvider.js.map +1 -0
  50. package/dist/speech/types.d.ts +35 -0
  51. package/dist/speech/types.d.ts.map +1 -1
  52. package/dist/voice/CallManager.d.ts +1 -1
  53. package/dist/voice/CallManager.d.ts.map +1 -1
  54. package/dist/voice/CallManager.js +9 -0
  55. package/dist/voice/CallManager.js.map +1 -1
  56. package/dist/voice/MediaStreamParser.d.ts +83 -0
  57. package/dist/voice/MediaStreamParser.d.ts.map +1 -0
  58. package/dist/voice/MediaStreamParser.js +2 -0
  59. package/dist/voice/MediaStreamParser.js.map +1 -0
  60. package/dist/voice/TelephonyStreamTransport.d.ts +112 -0
  61. package/dist/voice/TelephonyStreamTransport.d.ts.map +1 -0
  62. package/dist/voice/TelephonyStreamTransport.js +208 -0
  63. package/dist/voice/TelephonyStreamTransport.js.map +1 -0
  64. package/dist/voice/index.d.ts +10 -0
  65. package/dist/voice/index.d.ts.map +1 -1
  66. package/dist/voice/index.js +11 -0
  67. package/dist/voice/index.js.map +1 -1
  68. package/dist/voice/parsers/PlivoMediaStreamParser.d.ts +43 -0
  69. package/dist/voice/parsers/PlivoMediaStreamParser.d.ts.map +1 -0
  70. package/dist/voice/parsers/PlivoMediaStreamParser.js +92 -0
  71. package/dist/voice/parsers/PlivoMediaStreamParser.js.map +1 -0
  72. package/dist/voice/parsers/TelnyxMediaStreamParser.d.ts +51 -0
  73. package/dist/voice/parsers/TelnyxMediaStreamParser.d.ts.map +1 -0
  74. package/dist/voice/parsers/TelnyxMediaStreamParser.js +103 -0
  75. package/dist/voice/parsers/TelnyxMediaStreamParser.js.map +1 -0
  76. package/dist/voice/parsers/TwilioMediaStreamParser.d.ts +50 -0
  77. package/dist/voice/parsers/TwilioMediaStreamParser.d.ts.map +1 -0
  78. package/dist/voice/parsers/TwilioMediaStreamParser.js +144 -0
  79. package/dist/voice/parsers/TwilioMediaStreamParser.js.map +1 -0
  80. package/dist/voice/providers/plivo.d.ts +77 -0
  81. package/dist/voice/providers/plivo.d.ts.map +1 -0
  82. package/dist/voice/providers/plivo.js +180 -0
  83. package/dist/voice/providers/plivo.js.map +1 -0
  84. package/dist/voice/providers/telnyx.d.ts +93 -0
  85. package/dist/voice/providers/telnyx.d.ts.map +1 -0
  86. package/dist/voice/providers/telnyx.js +193 -0
  87. package/dist/voice/providers/telnyx.js.map +1 -0
  88. package/dist/voice/providers/twilio.d.ts +79 -0
  89. package/dist/voice/providers/twilio.d.ts.map +1 -0
  90. package/dist/voice/providers/twilio.js +191 -0
  91. package/dist/voice/providers/twilio.js.map +1 -0
  92. package/dist/voice/twiml.d.ts +69 -0
  93. package/dist/voice/twiml.d.ts.map +1 -0
  94. package/dist/voice/twiml.js +92 -0
  95. package/dist/voice/twiml.js.map +1 -0
  96. package/dist/voice/types.d.ts +9 -1
  97. package/dist/voice/types.d.ts.map +1 -1
  98. package/dist/voice-pipeline/AcousticEndpointDetector.d.ts +90 -0
  99. package/dist/voice-pipeline/AcousticEndpointDetector.d.ts.map +1 -0
  100. package/dist/voice-pipeline/AcousticEndpointDetector.js +123 -0
  101. package/dist/voice-pipeline/AcousticEndpointDetector.js.map +1 -0
  102. package/dist/voice-pipeline/HardCutBargeinHandler.d.ts +67 -0
  103. package/dist/voice-pipeline/HardCutBargeinHandler.d.ts.map +1 -0
  104. package/dist/voice-pipeline/HardCutBargeinHandler.js +55 -0
  105. package/dist/voice-pipeline/HardCutBargeinHandler.js.map +1 -0
  106. package/dist/voice-pipeline/HeuristicEndpointDetector.d.ts +128 -0
  107. package/dist/voice-pipeline/HeuristicEndpointDetector.d.ts.map +1 -0
  108. package/dist/voice-pipeline/HeuristicEndpointDetector.js +240 -0
  109. package/dist/voice-pipeline/HeuristicEndpointDetector.js.map +1 -0
  110. package/dist/voice-pipeline/SoftFadeBargeinHandler.d.ts +96 -0
  111. package/dist/voice-pipeline/SoftFadeBargeinHandler.d.ts.map +1 -0
  112. package/dist/voice-pipeline/SoftFadeBargeinHandler.js +69 -0
  113. package/dist/voice-pipeline/SoftFadeBargeinHandler.js.map +1 -0
  114. package/dist/voice-pipeline/VoicePipelineOrchestrator.d.ts +122 -0
  115. package/dist/voice-pipeline/VoicePipelineOrchestrator.d.ts.map +1 -0
  116. package/dist/voice-pipeline/VoicePipelineOrchestrator.js +317 -0
  117. package/dist/voice-pipeline/VoicePipelineOrchestrator.js.map +1 -0
  118. package/dist/voice-pipeline/WebSocketStreamTransport.d.ts +148 -0
  119. package/dist/voice-pipeline/WebSocketStreamTransport.d.ts.map +1 -0
  120. package/dist/voice-pipeline/WebSocketStreamTransport.js +207 -0
  121. package/dist/voice-pipeline/WebSocketStreamTransport.js.map +1 -0
  122. package/dist/voice-pipeline/index.d.ts +13 -0
  123. package/dist/voice-pipeline/index.d.ts.map +1 -0
  124. package/dist/voice-pipeline/index.js +13 -0
  125. package/dist/voice-pipeline/index.js.map +1 -0
  126. package/dist/voice-pipeline/types.d.ts +905 -0
  127. package/dist/voice-pipeline/types.d.ts.map +1 -0
  128. package/dist/voice-pipeline/types.js +23 -0
  129. package/dist/voice-pipeline/types.js.map +1 -0
  130. package/package.json +6 -1
@@ -0,0 +1,148 @@
1
+ /**
2
+ * @module voice-pipeline/WebSocketStreamTransport
3
+ *
4
+ * A concrete {@link IStreamTransport} implementation that wraps a WebSocket
5
+ * connection (or any WebSocket-compatible object). Binary messages are decoded
6
+ * as Float32Array audio frames; text messages are parsed as
7
+ * {@link ClientTextMessage} control envelopes.
8
+ *
9
+ * The transport is intentionally transport-agnostic: it accepts any object that
10
+ * exposes the `ws` package's `WebSocket` interface (readyState, send, close, and
11
+ * the standard event emitter surface). This makes it trivially testable with a
12
+ * plain `EventEmitter` mock.
13
+ */
14
+ import { EventEmitter } from 'node:events';
15
+ import type { IStreamTransport, AudioFrame, EncodedAudioChunk, TransportControlMessage, ServerTextMessage } from './types.js';
16
+ /**
17
+ * Subset of the WebSocket API required by {@link WebSocketStreamTransport}.
18
+ * Both the `ws` npm package and the browser's native WebSocket satisfy this.
19
+ */
20
+ export interface WebSocketLike extends NodeJS.EventEmitter {
21
+ /** WebSocket ready-state constant for the OPEN state (= 1). */
22
+ readonly OPEN?: number;
23
+ /** WebSocket ready-state constant for the CLOSED state (= 3). */
24
+ readonly CLOSED?: number;
25
+ /** Current ready state of the socket. */
26
+ readonly readyState: number;
27
+ /**
28
+ * Send data over the socket.
29
+ *
30
+ * @param data — Binary `Buffer` or text `string` payload.
31
+ * @param cb — Optional completion callback used by the `ws` library.
32
+ */
33
+ send(data: Buffer | string, cb?: (err?: Error) => void): void;
34
+ /**
35
+ * Initiate a graceful close handshake.
36
+ *
37
+ * @param code — Optional numeric close code (default 1000).
38
+ * @param reason — Optional human-readable reason string.
39
+ */
40
+ close(code?: number, reason?: string): void;
41
+ }
42
+ /**
43
+ * Constructor options for {@link WebSocketStreamTransport}.
44
+ */
45
+ export interface WebSocketStreamTransportConfig {
46
+ /**
47
+ * Sample rate (in Hz) used to populate {@link AudioFrame.sampleRate} on
48
+ * inbound binary messages. Must match the rate the remote client is sending.
49
+ * @example 16000
50
+ */
51
+ sampleRate: number;
52
+ }
53
+ /**
54
+ * Bidirectional voice pipeline transport backed by a WebSocket connection.
55
+ *
56
+ * ### Inbound wire format
57
+ * - **Binary frame** → decoded as a `Float32Array` view, wrapped in an
58
+ * {@link AudioFrame}, and re-emitted as `'audio_frame'`.
59
+ * - **Text frame** → `JSON.parse()`d and re-emitted as `'control'` carrying
60
+ * the raw {@link ClientTextMessage} object.
61
+ *
62
+ * ### Outbound API
63
+ * - {@link sendAudio} — serialises an {@link EncodedAudioChunk} or
64
+ * {@link AudioFrame} to a binary `Buffer` and calls `ws.send()`.
65
+ * - {@link sendControl} — JSON-stringifies a {@link TransportControlMessage}
66
+ * or {@link ServerTextMessage} and calls `ws.send()`.
67
+ *
68
+ * ### Lifecycle events (re-emitted on `this`)
69
+ * | WS event | Transport emission |
70
+ * |----------|--------------------|
71
+ * | `open` | `'connected'` |
72
+ * | `close` | `'disconnected'` |
73
+ * | `error` | `'error'` |
74
+ *
75
+ * @fires audio_frame — `(frame: AudioFrame)` for every inbound binary message.
76
+ * @fires control — `(msg: ClientTextMessage)` for every inbound text message.
77
+ * @fires connected — Socket transitioned to OPEN state.
78
+ * @fires disconnected — Socket has been fully closed.
79
+ * @fires error — Socket-level error occurred.
80
+ */
81
+ export declare class WebSocketStreamTransport extends EventEmitter implements IStreamTransport {
82
+ /** Stable UUID assigned at construction time. */
83
+ readonly id: string;
84
+ /** Current connection state. Updated in response to WebSocket events. */
85
+ private _state;
86
+ /** The underlying WebSocket connection. */
87
+ private readonly _ws;
88
+ /** Audio sample rate propagated into every decoded {@link AudioFrame}. */
89
+ private readonly _sampleRate;
90
+ /**
91
+ * Create a new transport wrapping an existing WebSocket connection.
92
+ *
93
+ * The constructor inspects `ws.readyState` to determine the initial
94
+ * {@link state}: if the socket is already OPEN (readyState === 1) the state
95
+ * is set to `'open'`; otherwise it is set to `'connecting'` and will
96
+ * transition to `'open'` when the `'open'` event fires.
97
+ *
98
+ * @param ws — WebSocket connection (or compatible mock).
99
+ * @param config — Transport-level configuration.
100
+ */
101
+ constructor(ws: WebSocketLike, config: WebSocketStreamTransportConfig);
102
+ /**
103
+ * Current connection state of the underlying WebSocket.
104
+ * Read-only from the outside; updated internally by WS event handlers.
105
+ */
106
+ get state(): 'connecting' | 'open' | 'closing' | 'closed';
107
+ /**
108
+ * Send a synthesised audio chunk to the remote client for playback.
109
+ *
110
+ * If `chunk` carries an {@link EncodedAudioChunk} (has an `audio` Buffer
111
+ * property), that buffer is sent directly. If it carries an {@link AudioFrame}
112
+ * (has a `samples` Float32Array), the samples are copied into a new `Buffer`
113
+ * and sent.
114
+ *
115
+ * @param chunk — Encoded audio chunk or raw PCM frame to deliver.
116
+ * @returns Resolves once the data has been handed to the OS socket buffer.
117
+ */
118
+ sendAudio(chunk: EncodedAudioChunk | AudioFrame): Promise<void>;
119
+ /**
120
+ * Send a JSON control message to the remote client.
121
+ *
122
+ * The message is JSON-stringified before transmission. Both
123
+ * {@link TransportControlMessage} and {@link ServerTextMessage} are accepted
124
+ * since they share the same serialisation path.
125
+ *
126
+ * @param msg — Server-side protocol message.
127
+ * @returns Resolves once the message has been handed to the OS socket buffer.
128
+ */
129
+ sendControl(msg: TransportControlMessage | ServerTextMessage): Promise<void>;
130
+ /**
131
+ * Initiate a graceful close of the transport.
132
+ *
133
+ * Sets internal state to `'closing'` immediately, then delegates to the
134
+ * underlying WebSocket's `close()` method. The `'disconnected'` event will
135
+ * fire once the socket's `'close'` event is received.
136
+ *
137
+ * @param code — Optional numeric WebSocket close code (default 1000).
138
+ * @param reason — Optional human-readable close reason.
139
+ */
140
+ close(code?: number, reason?: string): void;
141
+ /**
142
+ * Attach listeners to the underlying WebSocket for the events that matter to
143
+ * the voice pipeline. All listener state is contained here; no cleanup method
144
+ * is currently needed since the transport's lifetime is tied to the socket's.
145
+ */
146
+ private _attachWsListeners;
147
+ }
148
+ //# sourceMappingURL=WebSocketStreamTransport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebSocketStreamTransport.d.ts","sourceRoot":"","sources":["../../src/voice-pipeline/WebSocketStreamTransport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,EACV,gBAAgB,EAChB,UAAU,EACV,iBAAiB,EACjB,uBAAuB,EAEvB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAOpB;;;GAGG;AACH,MAAM,WAAW,aAAc,SAAQ,MAAM,CAAC,YAAY;IACxD,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,iEAAiE;IACjE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,yCAAyC;IACzC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B;;;;;OAKG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;IAC9D;;;;;OAKG;IACH,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7C;AAMD;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC7C;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,wBAAyB,SAAQ,YAAa,YAAW,gBAAgB;IAKpF,iDAAiD;IACjD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB,yEAAyE;IACzE,OAAO,CAAC,MAAM,CAA+C;IAM7D,2CAA2C;IAC3C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAgB;IAEpC,0EAA0E;IAC1E,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IAMrC;;;;;;;;;;OAUG;gBACS,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,8BAA8B;IAkBrE;;;OAGG;IACH,IAAI,KAAK,IAAI,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAExD;IAED;;;;;;;;;;OAUG;IACH,SAAS,CAAC,KAAK,EAAE,iBAAiB,GAAG,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAwB/D;;;;;;;;;OASG;IACH,WAAW,CAAC,GAAG,EAAE,uBAAuB,GAAG,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAS5E;;;;;;;;;OASG;IACH,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAS3C;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;CAyD3B"}
@@ -0,0 +1,207 @@
1
+ /**
2
+ * @module voice-pipeline/WebSocketStreamTransport
3
+ *
4
+ * A concrete {@link IStreamTransport} implementation that wraps a WebSocket
5
+ * connection (or any WebSocket-compatible object). Binary messages are decoded
6
+ * as Float32Array audio frames; text messages are parsed as
7
+ * {@link ClientTextMessage} control envelopes.
8
+ *
9
+ * The transport is intentionally transport-agnostic: it accepts any object that
10
+ * exposes the `ws` package's `WebSocket` interface (readyState, send, close, and
11
+ * the standard event emitter surface). This makes it trivially testable with a
12
+ * plain `EventEmitter` mock.
13
+ */
14
+ import { EventEmitter } from 'node:events';
15
+ import { randomUUID } from 'node:crypto';
16
+ // ---------------------------------------------------------------------------
17
+ // Implementation
18
+ // ---------------------------------------------------------------------------
19
+ /**
20
+ * Bidirectional voice pipeline transport backed by a WebSocket connection.
21
+ *
22
+ * ### Inbound wire format
23
+ * - **Binary frame** → decoded as a `Float32Array` view, wrapped in an
24
+ * {@link AudioFrame}, and re-emitted as `'audio_frame'`.
25
+ * - **Text frame** → `JSON.parse()`d and re-emitted as `'control'` carrying
26
+ * the raw {@link ClientTextMessage} object.
27
+ *
28
+ * ### Outbound API
29
+ * - {@link sendAudio} — serialises an {@link EncodedAudioChunk} or
30
+ * {@link AudioFrame} to a binary `Buffer` and calls `ws.send()`.
31
+ * - {@link sendControl} — JSON-stringifies a {@link TransportControlMessage}
32
+ * or {@link ServerTextMessage} and calls `ws.send()`.
33
+ *
34
+ * ### Lifecycle events (re-emitted on `this`)
35
+ * | WS event | Transport emission |
36
+ * |----------|--------------------|
37
+ * | `open` | `'connected'` |
38
+ * | `close` | `'disconnected'` |
39
+ * | `error` | `'error'` |
40
+ *
41
+ * @fires audio_frame — `(frame: AudioFrame)` for every inbound binary message.
42
+ * @fires control — `(msg: ClientTextMessage)` for every inbound text message.
43
+ * @fires connected — Socket transitioned to OPEN state.
44
+ * @fires disconnected — Socket has been fully closed.
45
+ * @fires error — Socket-level error occurred.
46
+ */
47
+ export class WebSocketStreamTransport extends EventEmitter {
48
+ // -------------------------------------------------------------------------
49
+ // Constructor
50
+ // -------------------------------------------------------------------------
51
+ /**
52
+ * Create a new transport wrapping an existing WebSocket connection.
53
+ *
54
+ * The constructor inspects `ws.readyState` to determine the initial
55
+ * {@link state}: if the socket is already OPEN (readyState === 1) the state
56
+ * is set to `'open'`; otherwise it is set to `'connecting'` and will
57
+ * transition to `'open'` when the `'open'` event fires.
58
+ *
59
+ * @param ws — WebSocket connection (or compatible mock).
60
+ * @param config — Transport-level configuration.
61
+ */
62
+ constructor(ws, config) {
63
+ super();
64
+ this._ws = ws;
65
+ this._sampleRate = config.sampleRate;
66
+ this.id = randomUUID();
67
+ // Determine initial state from the socket's current ready-state value.
68
+ // The `ws` package uses numeric constants; OPEN = 1, CLOSED = 3.
69
+ const OPEN_STATE = ws.OPEN ?? 1;
70
+ this._state = ws.readyState === OPEN_STATE ? 'open' : 'connecting';
71
+ this._attachWsListeners();
72
+ }
73
+ // -------------------------------------------------------------------------
74
+ // IStreamTransport — public surface
75
+ // -------------------------------------------------------------------------
76
+ /**
77
+ * Current connection state of the underlying WebSocket.
78
+ * Read-only from the outside; updated internally by WS event handlers.
79
+ */
80
+ get state() {
81
+ return this._state;
82
+ }
83
+ /**
84
+ * Send a synthesised audio chunk to the remote client for playback.
85
+ *
86
+ * If `chunk` carries an {@link EncodedAudioChunk} (has an `audio` Buffer
87
+ * property), that buffer is sent directly. If it carries an {@link AudioFrame}
88
+ * (has a `samples` Float32Array), the samples are copied into a new `Buffer`
89
+ * and sent.
90
+ *
91
+ * @param chunk — Encoded audio chunk or raw PCM frame to deliver.
92
+ * @returns Resolves once the data has been handed to the OS socket buffer.
93
+ */
94
+ sendAudio(chunk) {
95
+ return new Promise((resolve, reject) => {
96
+ let binary;
97
+ if ('audio' in chunk) {
98
+ // EncodedAudioChunk — already a Buffer
99
+ binary = chunk.audio;
100
+ }
101
+ else {
102
+ // AudioFrame — convert Float32Array samples to a byte Buffer
103
+ const frame = chunk;
104
+ binary = Buffer.from(frame.samples.buffer, frame.samples.byteOffset, frame.samples.byteLength);
105
+ }
106
+ this._ws.send(binary, (err) => {
107
+ if (err)
108
+ reject(err);
109
+ else
110
+ resolve();
111
+ });
112
+ });
113
+ }
114
+ /**
115
+ * Send a JSON control message to the remote client.
116
+ *
117
+ * The message is JSON-stringified before transmission. Both
118
+ * {@link TransportControlMessage} and {@link ServerTextMessage} are accepted
119
+ * since they share the same serialisation path.
120
+ *
121
+ * @param msg — Server-side protocol message.
122
+ * @returns Resolves once the message has been handed to the OS socket buffer.
123
+ */
124
+ sendControl(msg) {
125
+ return new Promise((resolve, reject) => {
126
+ this._ws.send(JSON.stringify(msg), (err) => {
127
+ if (err)
128
+ reject(err);
129
+ else
130
+ resolve();
131
+ });
132
+ });
133
+ }
134
+ /**
135
+ * Initiate a graceful close of the transport.
136
+ *
137
+ * Sets internal state to `'closing'` immediately, then delegates to the
138
+ * underlying WebSocket's `close()` method. The `'disconnected'` event will
139
+ * fire once the socket's `'close'` event is received.
140
+ *
141
+ * @param code — Optional numeric WebSocket close code (default 1000).
142
+ * @param reason — Optional human-readable close reason.
143
+ */
144
+ close(code, reason) {
145
+ this._state = 'closing';
146
+ this._ws.close(code, reason);
147
+ }
148
+ // -------------------------------------------------------------------------
149
+ // Private helpers
150
+ // -------------------------------------------------------------------------
151
+ /**
152
+ * Attach listeners to the underlying WebSocket for the events that matter to
153
+ * the voice pipeline. All listener state is contained here; no cleanup method
154
+ * is currently needed since the transport's lifetime is tied to the socket's.
155
+ */
156
+ _attachWsListeners() {
157
+ // `message` — inbound data from the remote peer
158
+ this._ws.on('message', (data) => {
159
+ if (typeof data === 'string') {
160
+ // Text frame — parse as ClientTextMessage and propagate as 'control'
161
+ try {
162
+ const msg = JSON.parse(data);
163
+ this.emit('control', msg);
164
+ }
165
+ catch (err) {
166
+ // Malformed JSON — emit as an error but do not crash the transport
167
+ this.emit('error', new Error(`WebSocketStreamTransport: failed to parse text message: ${String(err)}`));
168
+ }
169
+ }
170
+ else {
171
+ // Binary frame — interpret bytes as a Float32Array PCM sample buffer
172
+ let buffer;
173
+ if (Buffer.isBuffer(data)) {
174
+ buffer = data;
175
+ }
176
+ else {
177
+ // ArrayBuffer (browser-style)
178
+ buffer = Buffer.from(data);
179
+ }
180
+ // Create a Float32Array view over the underlying ArrayBuffer.
181
+ // We use byteOffset/length to handle sliced Buffers correctly.
182
+ const samples = new Float32Array(buffer.buffer, buffer.byteOffset, buffer.byteLength / Float32Array.BYTES_PER_ELEMENT);
183
+ const frame = {
184
+ samples,
185
+ sampleRate: this._sampleRate,
186
+ timestamp: Date.now(),
187
+ };
188
+ this.emit('audio_frame', frame);
189
+ }
190
+ });
191
+ // `open` — socket handshake complete
192
+ this._ws.on('open', () => {
193
+ this._state = 'open';
194
+ this.emit('connected');
195
+ });
196
+ // `close` — socket has been fully closed (either side)
197
+ this._ws.on('close', () => {
198
+ this._state = 'closed';
199
+ this.emit('disconnected');
200
+ });
201
+ // `error` — transport-level socket error
202
+ this._ws.on('error', (err) => {
203
+ this.emit('error', err);
204
+ });
205
+ }
206
+ }
207
+ //# sourceMappingURL=WebSocketStreamTransport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebSocketStreamTransport.js","sourceRoot":"","sources":["../../src/voice-pipeline/WebSocketStreamTransport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Barrel exports for the AgentOS streaming voice pipeline.
3
+ *
4
+ * @module @framers/agentos/voice-pipeline
5
+ */
6
+ export * from './types.js';
7
+ export { HardCutBargeinHandler } from './HardCutBargeinHandler.js';
8
+ export { SoftFadeBargeinHandler } from './SoftFadeBargeinHandler.js';
9
+ export { HeuristicEndpointDetector } from './HeuristicEndpointDetector.js';
10
+ export { AcousticEndpointDetector } from './AcousticEndpointDetector.js';
11
+ export { WebSocketStreamTransport } from './WebSocketStreamTransport.js';
12
+ export { VoicePipelineOrchestrator } from './VoicePipelineOrchestrator.js';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/voice-pipeline/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Barrel exports for the AgentOS streaming voice pipeline.
3
+ *
4
+ * @module @framers/agentos/voice-pipeline
5
+ */
6
+ export * from './types.js';
7
+ export { HardCutBargeinHandler } from './HardCutBargeinHandler.js';
8
+ export { SoftFadeBargeinHandler } from './SoftFadeBargeinHandler.js';
9
+ export { HeuristicEndpointDetector } from './HeuristicEndpointDetector.js';
10
+ export { AcousticEndpointDetector } from './AcousticEndpointDetector.js';
11
+ export { WebSocketStreamTransport } from './WebSocketStreamTransport.js';
12
+ export { VoicePipelineOrchestrator } from './VoicePipelineOrchestrator.js';
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/voice-pipeline/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC"}