@framers/agentos 0.1.111 → 0.1.113

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 (119) hide show
  1. package/dist/api/strategies/debate.d.ts +12 -1
  2. package/dist/api/strategies/debate.d.ts.map +1 -1
  3. package/dist/api/strategies/debate.js +41 -5
  4. package/dist/api/strategies/debate.js.map +1 -1
  5. package/dist/api/strategies/hierarchical.d.ts +15 -1
  6. package/dist/api/strategies/hierarchical.d.ts.map +1 -1
  7. package/dist/api/strategies/hierarchical.js +51 -7
  8. package/dist/api/strategies/hierarchical.js.map +1 -1
  9. package/dist/api/strategies/index.d.ts +26 -4
  10. package/dist/api/strategies/index.d.ts.map +1 -1
  11. package/dist/api/strategies/index.js +26 -4
  12. package/dist/api/strategies/index.js.map +1 -1
  13. package/dist/api/strategies/parallel.d.ts +15 -4
  14. package/dist/api/strategies/parallel.d.ts.map +1 -1
  15. package/dist/api/strategies/parallel.js +53 -16
  16. package/dist/api/strategies/parallel.js.map +1 -1
  17. package/dist/api/strategies/review-loop.d.ts +15 -1
  18. package/dist/api/strategies/review-loop.d.ts.map +1 -1
  19. package/dist/api/strategies/review-loop.js +36 -10
  20. package/dist/api/strategies/review-loop.js.map +1 -1
  21. package/dist/api/strategies/sequential.d.ts +11 -1
  22. package/dist/api/strategies/sequential.d.ts.map +1 -1
  23. package/dist/api/strategies/sequential.js +39 -8
  24. package/dist/api/strategies/sequential.js.map +1 -1
  25. package/dist/api/strategies/shared.d.ts +71 -7
  26. package/dist/api/strategies/shared.d.ts.map +1 -1
  27. package/dist/api/strategies/shared.js +89 -10
  28. package/dist/api/strategies/shared.js.map +1 -1
  29. package/dist/api/types.d.ts +54 -1
  30. package/dist/api/types.d.ts.map +1 -1
  31. package/dist/api/types.js.map +1 -1
  32. package/dist/memory/facade/Memory.d.ts.map +1 -1
  33. package/dist/memory/facade/Memory.js +8 -0
  34. package/dist/memory/facade/Memory.js.map +1 -1
  35. package/dist/memory/facade/types.d.ts +10 -0
  36. package/dist/memory/facade/types.d.ts.map +1 -1
  37. package/dist/memory/index.d.ts +6 -0
  38. package/dist/memory/index.d.ts.map +1 -1
  39. package/dist/memory/index.js +5 -0
  40. package/dist/memory/index.js.map +1 -1
  41. package/dist/memory/observation/MemoryObserver.d.ts +63 -1
  42. package/dist/memory/observation/MemoryObserver.d.ts.map +1 -1
  43. package/dist/memory/observation/MemoryObserver.js +115 -4
  44. package/dist/memory/observation/MemoryObserver.js.map +1 -1
  45. package/dist/memory/observation/ObservationCompressor.d.ts +88 -0
  46. package/dist/memory/observation/ObservationCompressor.d.ts.map +1 -0
  47. package/dist/memory/observation/ObservationCompressor.js +207 -0
  48. package/dist/memory/observation/ObservationCompressor.js.map +1 -0
  49. package/dist/memory/observation/ObservationReflector.d.ts +82 -0
  50. package/dist/memory/observation/ObservationReflector.d.ts.map +1 -0
  51. package/dist/memory/observation/ObservationReflector.js +212 -0
  52. package/dist/memory/observation/ObservationReflector.js.map +1 -0
  53. package/dist/memory/observation/temporal.d.ts +54 -0
  54. package/dist/memory/observation/temporal.d.ts.map +1 -0
  55. package/dist/memory/observation/temporal.js +115 -0
  56. package/dist/memory/observation/temporal.js.map +1 -0
  57. package/dist/orchestration/builders/VoiceNodeBuilder.d.ts +82 -25
  58. package/dist/orchestration/builders/VoiceNodeBuilder.d.ts.map +1 -1
  59. package/dist/orchestration/builders/VoiceNodeBuilder.js +86 -26
  60. package/dist/orchestration/builders/VoiceNodeBuilder.js.map +1 -1
  61. package/dist/orchestration/events/GraphEvent.d.ts +67 -5
  62. package/dist/orchestration/events/GraphEvent.d.ts.map +1 -1
  63. package/dist/orchestration/events/GraphEvent.js.map +1 -1
  64. package/dist/orchestration/runtime/VoiceNodeExecutor.d.ts +102 -25
  65. package/dist/orchestration/runtime/VoiceNodeExecutor.d.ts.map +1 -1
  66. package/dist/orchestration/runtime/VoiceNodeExecutor.js +133 -38
  67. package/dist/orchestration/runtime/VoiceNodeExecutor.js.map +1 -1
  68. package/dist/orchestration/runtime/VoiceTransportAdapter.d.ts +94 -32
  69. package/dist/orchestration/runtime/VoiceTransportAdapter.d.ts.map +1 -1
  70. package/dist/orchestration/runtime/VoiceTransportAdapter.js +82 -28
  71. package/dist/orchestration/runtime/VoiceTransportAdapter.js.map +1 -1
  72. package/dist/orchestration/runtime/VoiceTurnCollector.d.ts +73 -20
  73. package/dist/orchestration/runtime/VoiceTurnCollector.d.ts.map +1 -1
  74. package/dist/orchestration/runtime/VoiceTurnCollector.js +84 -23
  75. package/dist/orchestration/runtime/VoiceTurnCollector.js.map +1 -1
  76. package/dist/voice/CallManager.d.ts.map +1 -1
  77. package/dist/voice/CallManager.js +9 -1
  78. package/dist/voice/CallManager.js.map +1 -1
  79. package/dist/voice/MediaStreamParser.d.ts +115 -6
  80. package/dist/voice/MediaStreamParser.d.ts.map +1 -1
  81. package/dist/voice/MediaStreamParser.js +44 -0
  82. package/dist/voice/MediaStreamParser.js.map +1 -1
  83. package/dist/voice/TelephonyStreamTransport.d.ts +112 -20
  84. package/dist/voice/TelephonyStreamTransport.d.ts.map +1 -1
  85. package/dist/voice/TelephonyStreamTransport.js +136 -30
  86. package/dist/voice/TelephonyStreamTransport.js.map +1 -1
  87. package/dist/voice/parsers/PlivoMediaStreamParser.d.ts +64 -6
  88. package/dist/voice/parsers/PlivoMediaStreamParser.d.ts.map +1 -1
  89. package/dist/voice/parsers/PlivoMediaStreamParser.js +67 -6
  90. package/dist/voice/parsers/PlivoMediaStreamParser.js.map +1 -1
  91. package/dist/voice/parsers/TelnyxMediaStreamParser.d.ts +55 -8
  92. package/dist/voice/parsers/TelnyxMediaStreamParser.d.ts.map +1 -1
  93. package/dist/voice/parsers/TelnyxMediaStreamParser.js +60 -9
  94. package/dist/voice/parsers/TelnyxMediaStreamParser.js.map +1 -1
  95. package/dist/voice/parsers/TwilioMediaStreamParser.d.ts +73 -11
  96. package/dist/voice/parsers/TwilioMediaStreamParser.d.ts.map +1 -1
  97. package/dist/voice/parsers/TwilioMediaStreamParser.js +81 -12
  98. package/dist/voice/parsers/TwilioMediaStreamParser.js.map +1 -1
  99. package/dist/voice/providers/plivo.d.ts +108 -12
  100. package/dist/voice/providers/plivo.d.ts.map +1 -1
  101. package/dist/voice/providers/plivo.js +106 -9
  102. package/dist/voice/providers/plivo.js.map +1 -1
  103. package/dist/voice/providers/telnyx.d.ts +110 -20
  104. package/dist/voice/providers/telnyx.d.ts.map +1 -1
  105. package/dist/voice/providers/telnyx.js +111 -20
  106. package/dist/voice/providers/telnyx.js.map +1 -1
  107. package/dist/voice/providers/twilio.d.ts +91 -13
  108. package/dist/voice/providers/twilio.d.ts.map +1 -1
  109. package/dist/voice/providers/twilio.js +94 -14
  110. package/dist/voice/providers/twilio.js.map +1 -1
  111. package/dist/voice/twiml.d.ts +70 -12
  112. package/dist/voice/twiml.d.ts.map +1 -1
  113. package/dist/voice/twiml.js +70 -12
  114. package/dist/voice/twiml.js.map +1 -1
  115. package/dist/voice/types.d.ts +142 -15
  116. package/dist/voice/types.d.ts.map +1 -1
  117. package/dist/voice/types.js +34 -3
  118. package/dist/voice/types.js.map +1 -1
  119. package/package.json +1 -1
@@ -5,18 +5,31 @@
5
5
  * multiple exit conditions (hangup, turns exhausted, keyword, silence timeout,
6
6
  * barge-in abort) to determine when the voice node completes.
7
7
  *
8
+ * ## Design rationale
9
+ *
8
10
  * The executor follows the standard 2-arg `execute(node, state)` contract used by
9
- * {@link NodeExecutor}. It creates an internal `AbortController` for barge-in
11
+ * {@link NodeExecutor}. Internally it creates an `AbortController` for barge-in
10
12
  * support and optionally merges a parent abort signal from `state.scratch.abortSignal`.
11
13
  *
14
+ * Exit conditions are modelled as a **single `Promise.race`** rather than a state
15
+ * machine because the conditions are orthogonal and any one of them can fire at any
16
+ * time. The `settled` flag inside {@link raceExitConditions} guards against
17
+ * double-resolution when two conditions fire within the same microtask.
18
+ *
19
+ * ## State contract
20
+ *
12
21
  * Voice transport and session references are expected in `state.scratch`:
13
- * - `voiceTransport` the bidirectional transport EventEmitter (emits `close` / `disconnected`).
14
- * - `voiceTransport._voiceSession` the voice pipeline session EventEmitter that fires
22
+ * - `voiceTransport` -- the bidirectional transport EventEmitter (emits `close` / `disconnected`).
23
+ * - `voiceTransport._voiceSession` -- the voice pipeline session EventEmitter that fires
15
24
  * `final_transcript`, `turn_complete`, `speech_start`, and `barge_in` events.
16
25
  *
17
26
  * Checkpoint data is stored in `state.scratch[nodeId]` as a {@link VoiceNodeCheckpoint},
18
27
  * enabling the graph runtime to resume a voice session from the exact turn index where
19
28
  * it was previously suspended.
29
+ *
30
+ * @see {@link VoiceTurnCollector} for transcript buffering and event bridging.
31
+ * @see {@link VoiceTransportAdapter} for how graph I/O is wrapped at the transport level.
32
+ * @see {@link VoiceInterruptError} for the structured barge-in error type.
20
33
  */
21
34
  import type { GraphNode, GraphState, VoiceNodeConfig } from '../ir/types.js';
22
35
  import type { GraphEvent } from '../events/GraphEvent.js';
@@ -27,21 +40,44 @@ import type { NodeExecutionResult } from './NodeExecutor.js';
27
40
  * The graph runtime persists this structure so that a subsequent invocation of the
28
41
  * same voice node (e.g. after a graph loop or checkpoint restore) can continue the
29
42
  * conversation from `turnIndex` rather than resetting to zero.
43
+ *
44
+ * @example
45
+ * ```ts
46
+ * // Restoring from a checkpoint:
47
+ * const checkpoint = state.scratch['voice-1'] as VoiceNodeCheckpoint;
48
+ * const resumedTurnIndex = checkpoint.turnIndex; // e.g. 5
49
+ * ```
30
50
  */
31
51
  export interface VoiceNodeCheckpoint {
32
52
  /** Number of turns completed when the checkpoint was captured. */
33
53
  turnIndex: number;
34
- /** Full transcript buffer at the time of checkpoint. */
54
+ /**
55
+ * Full transcript buffer at the time of checkpoint.
56
+ *
57
+ * Each entry records a confirmed (final) utterance with its speaker label
58
+ * and wall-clock timestamp, preserving the full conversation history for
59
+ * downstream summarisation or analytics.
60
+ */
35
61
  transcript: Array<{
36
62
  speaker: string;
37
63
  text: string;
38
64
  timestamp: number;
39
65
  }>;
40
- /** Exit reason that caused the voice node to complete (`null` if still in progress). */
66
+ /**
67
+ * Exit reason that caused the voice node to complete.
68
+ * `null` when the checkpoint was captured mid-session (e.g. process crash).
69
+ */
41
70
  lastExitReason: string | null;
42
- /** Maps diarization speaker labels to human-readable names (reserved for future use). */
71
+ /**
72
+ * Maps diarization speaker labels to human-readable names.
73
+ * Reserved for future use -- populated as an empty object today.
74
+ */
43
75
  speakerMap: Record<string, string>;
44
- /** The voice config that was active when this checkpoint was created. */
76
+ /**
77
+ * The voice config that was active when this checkpoint was created.
78
+ * Stored so that a resumed session can verify config compatibility before
79
+ * continuing from the persisted turn index.
80
+ */
45
81
  sessionConfig: VoiceNodeConfig;
46
82
  }
47
83
  /**
@@ -49,55 +85,96 @@ export interface VoiceNodeCheckpoint {
49
85
  * multiple exit conditions to determine when the node is done.
50
86
  *
51
87
  * Exit conditions are evaluated concurrently via a single `Promise` race:
52
- * - **Hangup** transport emits `close` or `disconnected`.
53
- * - **Turns exhausted** session emits `turn_complete` and the collector's count
88
+ * - **Hangup** -- transport emits `close` or `disconnected`.
89
+ * - **Turns exhausted** -- session emits `turn_complete` and the collector's count
54
90
  * reaches `config.maxTurns`.
55
- * - **Keyword** a `final_transcript` event contains one of `config.exitKeywords`.
56
- * - **Silence timeout** no speech activity for 30 seconds (when `exitOn: 'silence-timeout'`).
57
- * - **Abort/barge-in** the internal `AbortController` is signalled, either by a
91
+ * - **Keyword** -- a `final_transcript` event contains one of `config.exitKeywords`.
92
+ * - **Silence timeout** -- no speech activity for 30 seconds (when `exitOn: 'silence-timeout'`).
93
+ * - **Abort/barge-in** -- the internal `AbortController` is signalled, either by a
58
94
  * parent abort signal or a `VoiceInterruptError`.
59
95
  *
60
96
  * @example
61
97
  * ```ts
62
98
  * const executor = new VoiceNodeExecutor((event) => emitter.emit(event));
63
99
  * const result = await executor.execute(voiceNode, graphState);
64
- * console.log(result.output.exitReason); // 'turns-exhausted' | 'hangup' | 'keyword:goodbye' | ...
100
+ * console.log(result.output.exitReason);
101
+ * // 'turns-exhausted' | 'hangup' | 'keyword:goodbye' | 'silence-timeout' | 'interrupted'
65
102
  * ```
103
+ *
104
+ * @see {@link VoiceTurnCollector} -- subscribes to session events and buffers transcript.
105
+ * @see {@link VoiceInterruptError} -- structured barge-in error that triggers the `interrupted` path.
66
106
  */
67
107
  export declare class VoiceNodeExecutor {
68
108
  private readonly eventSink;
69
109
  /**
110
+ * Creates a new VoiceNodeExecutor.
111
+ *
70
112
  * @param eventSink - Callback invoked synchronously for every emitted {@link GraphEvent}.
71
- * Typically bound to the graph runtime's event emitter.
113
+ * Typically bound to the graph runtime's event emitter so that
114
+ * voice lifecycle events (`voice_session`, `voice_transcript`, etc.)
115
+ * are visible to all graph event consumers.
72
116
  */
73
117
  constructor(eventSink: (event: GraphEvent) => void);
74
118
  /**
75
119
  * Execute a voice node. Matches the standard 2-arg `execute(node, state)` signature
76
120
  * used throughout the orchestration runtime.
77
121
  *
78
- * Creates an internal `AbortController` for barge-in, wires up a
79
- * {@link VoiceTurnCollector} on the session, and races exit conditions to
80
- * determine when the node completes.
122
+ * ## Lifecycle
123
+ *
124
+ * 1. Validates that `node.executorConfig.type` is `'voice'`.
125
+ * 2. Creates an internal `AbortController` for barge-in, wiring it to any parent
126
+ * abort signal in `state.scratch.abortSignal`.
127
+ * 3. Extracts the `voiceTransport` from `state.scratch` (must be pre-placed by
128
+ * the graph runtime or {@link VoiceTransportAdapter}).
129
+ * 4. Checks for a {@link VoiceNodeCheckpoint} to resume from.
130
+ * 5. Emits a `voice_session` started event.
131
+ * 6. Wires a {@link VoiceTurnCollector} onto the session and races exit conditions.
132
+ * 7. Resolves the exit reason to a route target via the node's edge map.
133
+ * 8. Returns a {@link NodeExecutionResult} with transcript, exit reason, checkpoint,
134
+ * and optional route target.
81
135
  *
82
136
  * @param node - Immutable voice node descriptor from the compiled graph IR.
137
+ * Must have `executorConfig.type === 'voice'`.
83
138
  * @param state - Current (partial) graph state threaded from the runtime.
139
+ * Must contain `scratch.voiceTransport` for the voice session.
84
140
  * @returns A {@link NodeExecutionResult} with transcript, exit reason, and optional route target.
141
+ * On success, `output` contains `{ transcript, turns, exitReason, lastSpeaker, interruptedText }`.
142
+ * `scratchUpdate` carries the {@link VoiceNodeCheckpoint} keyed by node id.
143
+ * @throws Never -- all errors are caught and returned as `{ success: false, error }`.
144
+ * {@link VoiceInterruptError} is caught and mapped to `exitReason: 'interrupted'`.
145
+ *
146
+ * @see {@link raceExitConditions} for the concurrent exit condition implementation.
85
147
  */
86
148
  execute(node: GraphNode, state: Partial<GraphState>): Promise<NodeExecutionResult>;
87
149
  /**
88
150
  * Races all configured exit conditions against each other and resolves with
89
151
  * the first one that fires.
90
152
  *
91
- * Listeners are attached to the session and transport EventEmitters. The
92
- * `AbortController` signal is also monitored — if it fires with a
93
- * {@link VoiceInterruptError} the Promise rejects (handled by the caller),
94
- * otherwise it resolves with `{ reason: 'interrupted' }`.
153
+ * ## How it works
154
+ *
155
+ * Each exit condition is wired as a listener on either the `session` or
156
+ * `transport` EventEmitter. All listeners call a shared `settleWith()` helper
157
+ * that resolves the outer Promise exactly once (guarded by a `settled` boolean).
158
+ *
159
+ * The `AbortController` signal is also monitored -- if it fires with a
160
+ * {@link VoiceInterruptError} the Promise rejects (handled by the caller's
161
+ * catch block), otherwise it resolves with `{ reason: 'interrupted' }`.
162
+ *
163
+ * ## Why a Promise race instead of a state machine?
164
+ *
165
+ * The exit conditions are independent and asynchronous. A Promise-based race
166
+ * avoids complex state transitions and lets each condition be a simple
167
+ * event listener. The `settled` guard handles the only tricky case: two
168
+ * conditions firing in the same microtask.
95
169
  *
96
- * @param session - Voice pipeline session EventEmitter.
97
- * @param collector - Active turn collector tracking turn count.
98
- * @param config - Voice node configuration with exit settings.
170
+ * @param session - Voice pipeline session EventEmitter that fires
171
+ * `turn_complete`, `final_transcript`, `speech_start`, `barge_in`.
172
+ * @param collector - Active turn collector tracking turn count and transcript.
173
+ * @param config - Voice node configuration with exit settings (`maxTurns`,
174
+ * `exitOn`, `exitKeywords`).
99
175
  * @param controller - Internal AbortController for barge-in signalling.
100
- * @param transport - Bidirectional transport EventEmitter.
176
+ * @param transport - Bidirectional transport EventEmitter that fires `close`
177
+ * and `disconnected` on hangup.
101
178
  * @returns The winning exit condition's reason string and optional interrupted text.
102
179
  */
103
180
  private raceExitConditions;
@@ -1 +1 @@
1
- {"version":3,"file":"VoiceNodeExecutor.d.ts","sourceRoot":"","sources":["../../../src/orchestration/runtime/VoiceNodeExecutor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAQ7D;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,UAAU,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxE,wFAAwF;IACxF,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,yFAAyF;IACzF,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,yEAAyE;IACzE,aAAa,EAAE,eAAe,CAAC;CAChC;AAMD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,iBAAiB;IAM1B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAL5B;;;OAGG;gBAEgB,SAAS,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI;IAGzD;;;;;;;;;;;OAWG;IACG,OAAO,CACX,IAAI,EAAE,SAAS,EACf,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,GACzB,OAAO,CAAC,mBAAmB,CAAC;IA0G/B;;;;;;;;;;;;;;;OAeG;YACW,kBAAkB;CA2EjC"}
1
+ {"version":3,"file":"VoiceNodeExecutor.d.ts","sourceRoot":"","sources":["../../../src/orchestration/runtime/VoiceNodeExecutor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAQ7D;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,mBAAmB;IAClC,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAElB;;;;;;OAMG;IACH,UAAU,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAExE;;;OAGG;IACH,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAE9B;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEnC;;;;OAIG;IACH,aAAa,EAAE,eAAe,CAAC;CAChC;AAMD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,iBAAiB;IAU1B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAT5B;;;;;;;OAOG;gBAEgB,SAAS,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI;IAGzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACG,OAAO,CACX,IAAI,EAAE,SAAS,EACf,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,GACzB,OAAO,CAAC,mBAAmB,CAAC;IAiI/B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;YACW,kBAAkB;CA+FjC"}
@@ -5,18 +5,31 @@
5
5
  * multiple exit conditions (hangup, turns exhausted, keyword, silence timeout,
6
6
  * barge-in abort) to determine when the voice node completes.
7
7
  *
8
+ * ## Design rationale
9
+ *
8
10
  * The executor follows the standard 2-arg `execute(node, state)` contract used by
9
- * {@link NodeExecutor}. It creates an internal `AbortController` for barge-in
11
+ * {@link NodeExecutor}. Internally it creates an `AbortController` for barge-in
10
12
  * support and optionally merges a parent abort signal from `state.scratch.abortSignal`.
11
13
  *
14
+ * Exit conditions are modelled as a **single `Promise.race`** rather than a state
15
+ * machine because the conditions are orthogonal and any one of them can fire at any
16
+ * time. The `settled` flag inside {@link raceExitConditions} guards against
17
+ * double-resolution when two conditions fire within the same microtask.
18
+ *
19
+ * ## State contract
20
+ *
12
21
  * Voice transport and session references are expected in `state.scratch`:
13
- * - `voiceTransport` the bidirectional transport EventEmitter (emits `close` / `disconnected`).
14
- * - `voiceTransport._voiceSession` the voice pipeline session EventEmitter that fires
22
+ * - `voiceTransport` -- the bidirectional transport EventEmitter (emits `close` / `disconnected`).
23
+ * - `voiceTransport._voiceSession` -- the voice pipeline session EventEmitter that fires
15
24
  * `final_transcript`, `turn_complete`, `speech_start`, and `barge_in` events.
16
25
  *
17
26
  * Checkpoint data is stored in `state.scratch[nodeId]` as a {@link VoiceNodeCheckpoint},
18
27
  * enabling the graph runtime to resume a voice session from the exact turn index where
19
28
  * it was previously suspended.
29
+ *
30
+ * @see {@link VoiceTurnCollector} for transcript buffering and event bridging.
31
+ * @see {@link VoiceTransportAdapter} for how graph I/O is wrapped at the transport level.
32
+ * @see {@link VoiceInterruptError} for the structured barge-in error type.
20
33
  */
21
34
  import { EventEmitter } from 'events';
22
35
  import { VoiceTurnCollector } from './VoiceTurnCollector.js';
@@ -29,25 +42,33 @@ import { VoiceInterruptError } from '../../voice-pipeline/VoiceInterruptError.js
29
42
  * multiple exit conditions to determine when the node is done.
30
43
  *
31
44
  * Exit conditions are evaluated concurrently via a single `Promise` race:
32
- * - **Hangup** transport emits `close` or `disconnected`.
33
- * - **Turns exhausted** session emits `turn_complete` and the collector's count
45
+ * - **Hangup** -- transport emits `close` or `disconnected`.
46
+ * - **Turns exhausted** -- session emits `turn_complete` and the collector's count
34
47
  * reaches `config.maxTurns`.
35
- * - **Keyword** a `final_transcript` event contains one of `config.exitKeywords`.
36
- * - **Silence timeout** no speech activity for 30 seconds (when `exitOn: 'silence-timeout'`).
37
- * - **Abort/barge-in** the internal `AbortController` is signalled, either by a
48
+ * - **Keyword** -- a `final_transcript` event contains one of `config.exitKeywords`.
49
+ * - **Silence timeout** -- no speech activity for 30 seconds (when `exitOn: 'silence-timeout'`).
50
+ * - **Abort/barge-in** -- the internal `AbortController` is signalled, either by a
38
51
  * parent abort signal or a `VoiceInterruptError`.
39
52
  *
40
53
  * @example
41
54
  * ```ts
42
55
  * const executor = new VoiceNodeExecutor((event) => emitter.emit(event));
43
56
  * const result = await executor.execute(voiceNode, graphState);
44
- * console.log(result.output.exitReason); // 'turns-exhausted' | 'hangup' | 'keyword:goodbye' | ...
57
+ * console.log(result.output.exitReason);
58
+ * // 'turns-exhausted' | 'hangup' | 'keyword:goodbye' | 'silence-timeout' | 'interrupted'
45
59
  * ```
60
+ *
61
+ * @see {@link VoiceTurnCollector} -- subscribes to session events and buffers transcript.
62
+ * @see {@link VoiceInterruptError} -- structured barge-in error that triggers the `interrupted` path.
46
63
  */
47
64
  export class VoiceNodeExecutor {
48
65
  /**
66
+ * Creates a new VoiceNodeExecutor.
67
+ *
49
68
  * @param eventSink - Callback invoked synchronously for every emitted {@link GraphEvent}.
50
- * Typically bound to the graph runtime's event emitter.
69
+ * Typically bound to the graph runtime's event emitter so that
70
+ * voice lifecycle events (`voice_session`, `voice_transcript`, etc.)
71
+ * are visible to all graph event consumers.
51
72
  */
52
73
  constructor(eventSink) {
53
74
  this.eventSink = eventSink;
@@ -56,49 +77,85 @@ export class VoiceNodeExecutor {
56
77
  * Execute a voice node. Matches the standard 2-arg `execute(node, state)` signature
57
78
  * used throughout the orchestration runtime.
58
79
  *
59
- * Creates an internal `AbortController` for barge-in, wires up a
60
- * {@link VoiceTurnCollector} on the session, and races exit conditions to
61
- * determine when the node completes.
80
+ * ## Lifecycle
81
+ *
82
+ * 1. Validates that `node.executorConfig.type` is `'voice'`.
83
+ * 2. Creates an internal `AbortController` for barge-in, wiring it to any parent
84
+ * abort signal in `state.scratch.abortSignal`.
85
+ * 3. Extracts the `voiceTransport` from `state.scratch` (must be pre-placed by
86
+ * the graph runtime or {@link VoiceTransportAdapter}).
87
+ * 4. Checks for a {@link VoiceNodeCheckpoint} to resume from.
88
+ * 5. Emits a `voice_session` started event.
89
+ * 6. Wires a {@link VoiceTurnCollector} onto the session and races exit conditions.
90
+ * 7. Resolves the exit reason to a route target via the node's edge map.
91
+ * 8. Returns a {@link NodeExecutionResult} with transcript, exit reason, checkpoint,
92
+ * and optional route target.
62
93
  *
63
94
  * @param node - Immutable voice node descriptor from the compiled graph IR.
95
+ * Must have `executorConfig.type === 'voice'`.
64
96
  * @param state - Current (partial) graph state threaded from the runtime.
97
+ * Must contain `scratch.voiceTransport` for the voice session.
65
98
  * @returns A {@link NodeExecutionResult} with transcript, exit reason, and optional route target.
99
+ * On success, `output` contains `{ transcript, turns, exitReason, lastSpeaker, interruptedText }`.
100
+ * `scratchUpdate` carries the {@link VoiceNodeCheckpoint} keyed by node id.
101
+ * @throws Never -- all errors are caught and returned as `{ success: false, error }`.
102
+ * {@link VoiceInterruptError} is caught and mapped to `exitReason: 'interrupted'`.
103
+ *
104
+ * @see {@link raceExitConditions} for the concurrent exit condition implementation.
66
105
  */
67
106
  async execute(node, state) {
68
107
  const config = node.executorConfig;
108
+ // Guard: only voice nodes should reach this executor.
69
109
  if (config.type !== 'voice') {
70
110
  return { success: false, error: 'VoiceNodeExecutor received non-voice node' };
71
111
  }
72
112
  const voiceConfig = config.voiceConfig;
73
- // Internal AbortController for barge-in or parent cancellation.
113
+ // Create an internal AbortController so barge-in events or parent cancellation
114
+ // can terminate the exit condition race without waiting for a session event.
74
115
  const controller = new AbortController();
75
- // If a parent abort signal exists in scratch, forward its abort to ours.
116
+ // If a parent abort signal exists in scratch (e.g. from a graph-level timeout
117
+ // or manual cancellation), forward its abort to our internal controller so that
118
+ // the voice session is cancelled when the parent cancels.
76
119
  const parentSignal = state?.scratch?.abortSignal;
77
120
  if (parentSignal) {
78
121
  parentSignal.addEventListener('abort', () => controller.abort(parentSignal.reason), { once: true });
79
122
  }
80
- // Voice transport must be pre-placed in state.scratch by the graph runtime.
123
+ // The voice transport must be pre-placed in state.scratch by the graph runtime
124
+ // or VoiceTransportAdapter before executing a voice node. Without it we cannot
125
+ // receive session events or detect hangup.
81
126
  const transport = state?.scratch?.voiceTransport;
82
127
  if (!transport) {
83
128
  return { success: false, error: 'Voice node requires voiceTransport in state.scratch' };
84
129
  }
85
- // Check for checkpoint restore continue from a prior turn index.
130
+ // Check for checkpoint restore -- if the node was previously executed and the
131
+ // graph was suspended/restored, the prior turn count is in the checkpoint.
132
+ // This lets the turn counter continue from where it left off rather than
133
+ // resetting to zero, which would cause premature exits on maxTurns.
86
134
  const checkpoint = state?.scratch?.[node.id];
87
135
  const initialTurnCount = checkpoint?.turnIndex ?? 0;
88
- // Emit session lifecycle event: started.
136
+ // Signal that the voice session is now active for this node.
89
137
  this.eventSink({ type: 'voice_session', nodeId: node.id, action: 'started' });
90
138
  try {
91
139
  // The voice session EventEmitter is expected on transport._voiceSession.
92
- // In production this is the VoicePipelineSession; in tests it can be a plain EventEmitter.
140
+ // In production this is the VoicePipelineSession; in tests it can be a
141
+ // plain EventEmitter. Fallback to a fresh emitter avoids null dereferences
142
+ // when the transport doesn't have an attached session.
93
143
  const session = transport._voiceSession ?? new EventEmitter();
94
- // Create the turn collector it subscribes to session events and buffers transcript.
144
+ // Create the turn collector -- it subscribes to session events (interim_transcript,
145
+ // final_transcript, turn_complete, barge_in) and bridges them into GraphEvents
146
+ // while maintaining a running transcript buffer and turn counter.
95
147
  const collector = new VoiceTurnCollector(session, this.eventSink, node.id, initialTurnCount);
96
- // Race all exit conditions against each other.
148
+ // Race all exit conditions against each other. The first condition to fire
149
+ // determines exitReason and ends the voice node.
97
150
  const result = await this.raceExitConditions(session, collector, voiceConfig, controller, transport);
98
- // Resolve exitReason routeTarget from node edges.
151
+ // Map the exitReason string to a target node id using the edge map.
152
+ // This is how voice nodes implement conditional routing: different exit
153
+ // conditions route to different downstream nodes.
99
154
  const edges = node.edges ?? {};
100
155
  const routeTarget = typeof edges === 'object' ? edges[result.reason] : undefined;
101
- // Build checkpoint for scratch so the runtime can persist/restore later.
156
+ // Build the checkpoint so the runtime can persist and restore later.
157
+ // This is written into scratchUpdate and merged back into state.scratch
158
+ // by the graph runtime after execution completes.
102
159
  const voiceCheckpoint = {
103
160
  turnIndex: collector.getTurnCount(),
104
161
  transcript: collector.getTranscript(),
@@ -106,7 +163,7 @@ export class VoiceNodeExecutor {
106
163
  speakerMap: {},
107
164
  sessionConfig: voiceConfig,
108
165
  };
109
- // Emit session lifecycle event: ended.
166
+ // Signal that the voice session has ended for this node.
110
167
  this.eventSink({ type: 'voice_session', nodeId: node.id, action: 'ended', exitReason: result.reason });
111
168
  return {
112
169
  success: true,
@@ -122,8 +179,10 @@ export class VoiceNodeExecutor {
122
179
  };
123
180
  }
124
181
  catch (err) {
125
- // VoiceInterruptError is a structured barge-in treat as a successful exit
126
- // with exitReason: 'interrupted' so the graph can route accordingly.
182
+ // VoiceInterruptError is a structured barge-in -- the user spoke over the
183
+ // agent. This is not an error condition; it's a valid exit path that the
184
+ // graph should be able to route on. We convert it to a successful result
185
+ // with exitReason: 'interrupted' so edge routing works as expected.
127
186
  if (err instanceof VoiceInterruptError) {
128
187
  const edges = node.edges ?? {};
129
188
  const routeTarget = edges['interrupted'];
@@ -140,7 +199,8 @@ export class VoiceNodeExecutor {
140
199
  routeTarget,
141
200
  };
142
201
  }
143
- // Unhandled error surface as a failed result.
202
+ // Unhandled error -- surface as a failed result so the graph runtime can
203
+ // decide whether to retry, reroute, or halt.
144
204
  this.eventSink({ type: 'voice_session', nodeId: node.id, action: 'ended', exitReason: 'error' });
145
205
  return { success: false, error: String(err) };
146
206
  }
@@ -152,25 +212,42 @@ export class VoiceNodeExecutor {
152
212
  * Races all configured exit conditions against each other and resolves with
153
213
  * the first one that fires.
154
214
  *
155
- * Listeners are attached to the session and transport EventEmitters. The
156
- * `AbortController` signal is also monitored — if it fires with a
157
- * {@link VoiceInterruptError} the Promise rejects (handled by the caller),
158
- * otherwise it resolves with `{ reason: 'interrupted' }`.
215
+ * ## How it works
216
+ *
217
+ * Each exit condition is wired as a listener on either the `session` or
218
+ * `transport` EventEmitter. All listeners call a shared `settleWith()` helper
219
+ * that resolves the outer Promise exactly once (guarded by a `settled` boolean).
220
+ *
221
+ * The `AbortController` signal is also monitored -- if it fires with a
222
+ * {@link VoiceInterruptError} the Promise rejects (handled by the caller's
223
+ * catch block), otherwise it resolves with `{ reason: 'interrupted' }`.
224
+ *
225
+ * ## Why a Promise race instead of a state machine?
226
+ *
227
+ * The exit conditions are independent and asynchronous. A Promise-based race
228
+ * avoids complex state transitions and lets each condition be a simple
229
+ * event listener. The `settled` guard handles the only tricky case: two
230
+ * conditions firing in the same microtask.
159
231
  *
160
- * @param session - Voice pipeline session EventEmitter.
161
- * @param collector - Active turn collector tracking turn count.
162
- * @param config - Voice node configuration with exit settings.
232
+ * @param session - Voice pipeline session EventEmitter that fires
233
+ * `turn_complete`, `final_transcript`, `speech_start`, `barge_in`.
234
+ * @param collector - Active turn collector tracking turn count and transcript.
235
+ * @param config - Voice node configuration with exit settings (`maxTurns`,
236
+ * `exitOn`, `exitKeywords`).
163
237
  * @param controller - Internal AbortController for barge-in signalling.
164
- * @param transport - Bidirectional transport EventEmitter.
238
+ * @param transport - Bidirectional transport EventEmitter that fires `close`
239
+ * and `disconnected` on hangup.
165
240
  * @returns The winning exit condition's reason string and optional interrupted text.
166
241
  */
167
242
  async raceExitConditions(session, collector, config, controller, transport) {
168
243
  return new Promise((resolve, reject) => {
169
- /** Prevent double-resolution from multiple conditions firing simultaneously. */
244
+ /** Prevents double-resolution when multiple conditions fire simultaneously. */
170
245
  let settled = false;
171
246
  /**
172
247
  * Settle the promise with a resolve value, guarding against double-settle.
173
- * @param result - The exit condition result.
248
+ * Every exit condition calls this instead of `resolve()` directly.
249
+ *
250
+ * @param result - The exit condition result containing the reason string.
174
251
  */
175
252
  const settleWith = (result) => {
176
253
  if (settled)
@@ -179,10 +256,16 @@ export class VoiceNodeExecutor {
179
256
  resolve(result);
180
257
  };
181
258
  // -- Hangup: transport disconnects -----------------------------------
259
+ // Both `close` and `disconnected` events indicate the transport is gone.
260
+ // We listen for both because different transport implementations emit
261
+ // different event names (WebSocket uses `close`, telephony uses `disconnected`).
182
262
  const onDisconnect = () => settleWith({ reason: 'hangup' });
183
263
  transport.on('close', onDisconnect);
184
264
  transport.on('disconnected', onDisconnect);
185
265
  // -- Turns exhausted -------------------------------------------------
266
+ // Only armed when maxTurns is a positive number. We check the collector's
267
+ // count (not a local counter) because the collector may have been seeded
268
+ // with an initialTurnCount from a checkpoint restore.
186
269
  if (config.maxTurns && config.maxTurns > 0) {
187
270
  session.on('turn_complete', () => {
188
271
  if (collector.getTurnCount() >= config.maxTurns) {
@@ -191,6 +274,9 @@ export class VoiceNodeExecutor {
191
274
  });
192
275
  }
193
276
  // -- Keyword detection -----------------------------------------------
277
+ // Only armed when exitOn is 'keyword' and at least one keyword is provided.
278
+ // The keyword check is case-insensitive and uses substring matching so that
279
+ // "goodbye" matches "okay goodbye then".
194
280
  if (config.exitOn === 'keyword' && config.exitKeywords?.length) {
195
281
  session.on('final_transcript', (evt) => {
196
282
  const text = (evt.text ?? '').toLowerCase();
@@ -203,20 +289,29 @@ export class VoiceNodeExecutor {
203
289
  });
204
290
  }
205
291
  // -- Silence timeout (default 30 s) ----------------------------------
292
+ // Only armed when exitOn is 'silence-timeout'. A watchdog timer is reset
293
+ // on every speech activity event. If the timer fires without being reset,
294
+ // the user has been silent for too long and the session ends.
206
295
  if (config.exitOn === 'silence-timeout') {
207
296
  let silenceTimer = null;
208
297
  const timeoutMs = 30000;
209
- /** Reset the silence watchdog called on any speech activity. */
298
+ /** Reset the silence watchdog -- called on any speech activity. */
210
299
  const resetTimer = () => {
211
300
  if (silenceTimer)
212
301
  clearTimeout(silenceTimer);
213
302
  silenceTimer = setTimeout(() => settleWith({ reason: 'silence-timeout' }), timeoutMs);
214
303
  };
304
+ // Reset on both speech_start (user began talking) and turn_complete
305
+ // (user finished a turn) to cover all speech activity signals.
215
306
  session.on('speech_start', resetTimer);
216
307
  session.on('turn_complete', resetTimer);
217
308
  resetTimer(); // Start the initial timer immediately.
218
309
  }
219
310
  // -- Abort signal (barge-in or parent cancellation) ------------------
311
+ // If the abort reason is a VoiceInterruptError, we reject the Promise
312
+ // (the caller's catch block converts it to exitReason: 'interrupted').
313
+ // For any other abort reason (e.g. parent timeout), we resolve normally
314
+ // with reason: 'interrupted'.
220
315
  controller.signal.addEventListener('abort', () => {
221
316
  const reason = controller.signal.reason;
222
317
  if (reason instanceof VoiceInterruptError) {
@@ -1 +1 @@
1
- {"version":3,"file":"VoiceNodeExecutor.js","sourceRoot":"","sources":["../../../src/orchestration/runtime/VoiceNodeExecutor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"VoiceNodeExecutor.js","sourceRoot":"","sources":["../../../src/orchestration/runtime/VoiceNodeExecutor.ts"],"names":[],"mappings":"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"}