@memberjunction/ai-agents 5.40.2 → 5.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -0
- package/dist/AgentRunner.d.ts +5 -2
- package/dist/AgentRunner.d.ts.map +1 -1
- package/dist/AgentRunner.js +14 -4
- package/dist/AgentRunner.js.map +1 -1
- package/dist/MemoryWriteManager.d.ts +188 -0
- package/dist/MemoryWriteManager.d.ts.map +1 -0
- package/dist/MemoryWriteManager.js +299 -0
- package/dist/MemoryWriteManager.js.map +1 -0
- package/dist/agent-context-injector.d.ts +29 -0
- package/dist/agent-context-injector.d.ts.map +1 -1
- package/dist/agent-context-injector.js +90 -32
- package/dist/agent-context-injector.js.map +1 -1
- package/dist/agent-memory-context-builder.d.ts +100 -0
- package/dist/agent-memory-context-builder.d.ts.map +1 -0
- package/dist/agent-memory-context-builder.js +172 -0
- package/dist/agent-memory-context-builder.js.map +1 -0
- package/dist/agent-types/index.d.ts +1 -0
- package/dist/agent-types/index.d.ts.map +1 -1
- package/dist/agent-types/index.js +1 -0
- package/dist/agent-types/index.js.map +1 -1
- package/dist/agent-types/loop-agent-response-type.d.ts +12 -1
- package/dist/agent-types/loop-agent-response-type.d.ts.map +1 -1
- package/dist/agent-types/loop-agent-response-type.js.map +1 -1
- package/dist/agent-types/loop-agent-type.d.ts.map +1 -1
- package/dist/agent-types/loop-agent-type.js +4 -0
- package/dist/agent-types/loop-agent-type.js.map +1 -1
- package/dist/agent-types/realtime-agent-type.d.ts +146 -0
- package/dist/agent-types/realtime-agent-type.d.ts.map +1 -0
- package/dist/agent-types/realtime-agent-type.js +176 -0
- package/dist/agent-types/realtime-agent-type.js.map +1 -0
- package/dist/base-agent.d.ts +386 -39
- package/dist/base-agent.d.ts.map +1 -1
- package/dist/base-agent.js +1121 -261
- package/dist/base-agent.js.map +1 -1
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -1
- package/dist/memory-manager-agent.d.ts +99 -4
- package/dist/memory-manager-agent.d.ts.map +1 -1
- package/dist/memory-manager-agent.js +349 -117
- package/dist/memory-manager-agent.js.map +1 -1
- package/dist/realtime/bridge-realtime-session-factory.d.ts +111 -0
- package/dist/realtime/bridge-realtime-session-factory.d.ts.map +1 -0
- package/dist/realtime/bridge-realtime-session-factory.js +163 -0
- package/dist/realtime/bridge-realtime-session-factory.js.map +1 -0
- package/dist/realtime/bridge-room-transcript-sink.d.ts +58 -0
- package/dist/realtime/bridge-room-transcript-sink.d.ts.map +1 -0
- package/dist/realtime/bridge-room-transcript-sink.js +127 -0
- package/dist/realtime/bridge-room-transcript-sink.js.map +1 -0
- package/dist/realtime/meeting-controls-channel-server.d.ts +198 -0
- package/dist/realtime/meeting-controls-channel-server.d.ts.map +1 -0
- package/dist/realtime/meeting-controls-channel-server.js +319 -0
- package/dist/realtime/meeting-controls-channel-server.js.map +1 -0
- package/dist/realtime/meeting-controls-state.d.ts +191 -0
- package/dist/realtime/meeting-controls-state.d.ts.map +1 -0
- package/dist/realtime/meeting-controls-state.js +219 -0
- package/dist/realtime/meeting-controls-state.js.map +1 -0
- package/dist/realtime/realtime-channel-server-host.d.ts +166 -0
- package/dist/realtime/realtime-channel-server-host.d.ts.map +1 -0
- package/dist/realtime/realtime-channel-server-host.js +378 -0
- package/dist/realtime/realtime-channel-server-host.js.map +1 -0
- package/dist/realtime/realtime-client-session-service.d.ts +1026 -0
- package/dist/realtime/realtime-client-session-service.d.ts.map +1 -0
- package/dist/realtime/realtime-client-session-service.js +1607 -0
- package/dist/realtime/realtime-client-session-service.js.map +1 -0
- package/dist/realtime/realtime-coagent-config.d.ts +258 -0
- package/dist/realtime/realtime-coagent-config.d.ts.map +1 -0
- package/dist/realtime/realtime-coagent-config.js +408 -0
- package/dist/realtime/realtime-coagent-config.js.map +1 -0
- package/dist/realtime/realtime-narration.d.ts +67 -0
- package/dist/realtime/realtime-narration.d.ts.map +1 -0
- package/dist/realtime/realtime-narration.js +127 -0
- package/dist/realtime/realtime-narration.js.map +1 -0
- package/dist/realtime/realtime-session-runner.d.ts +383 -0
- package/dist/realtime/realtime-session-runner.d.ts.map +1 -0
- package/dist/realtime/realtime-session-runner.js +532 -0
- package/dist/realtime/realtime-session-runner.js.map +1 -0
- package/dist/realtime/realtime-tool-broker.d.ts +294 -0
- package/dist/realtime/realtime-tool-broker.d.ts.map +1 -0
- package/dist/realtime/realtime-tool-broker.js +206 -0
- package/dist/realtime/realtime-tool-broker.js.map +1 -0
- package/dist/realtime/whiteboard-channel-server.d.ts +50 -0
- package/dist/realtime/whiteboard-channel-server.d.ts.map +1 -0
- package/dist/realtime/whiteboard-channel-server.js +85 -0
- package/dist/realtime/whiteboard-channel-server.js.map +1 -0
- package/package.json +17 -17
|
@@ -0,0 +1,532 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Dependency-injected orchestrator that drives a `BaseRealtimeModel` session for
|
|
3
|
+
* the {@link RealtimeAgentType} (Realtime Co-Agent).
|
|
4
|
+
*
|
|
5
|
+
* The {@link RealtimeSessionRunner} owns the lifecycle of a single full-duplex
|
|
6
|
+
* {@link IRealtimeSession}: it opens the session, registers a **stable, target-independent** tool
|
|
7
|
+
* set (always including `invoke-target-agent`), wires the provider event handlers, routes tool
|
|
8
|
+
* calls (invoke-target → delegate to the target agent; others → an injected tool executor),
|
|
9
|
+
* persists each transcript turn as a conversation detail, accumulates usage and checkpoints it on
|
|
10
|
+
* a debounced cadence, and aborts any in-flight delegated run on barge-in.
|
|
11
|
+
*
|
|
12
|
+
* **Why dependency injection.** Every collaborator that would otherwise pull in `BaseAgent`,
|
|
13
|
+
* metadata, or the database is injected via {@link RealtimeSessionRunnerDeps}. That keeps the
|
|
14
|
+
* runner fully unit-testable against a mock realtime model and mock collaborators (this is the
|
|
15
|
+
* P2b-i deliverable). In P2b-ii, `BaseAgent` supplies the real implementations (model resolution
|
|
16
|
+
* from agent metadata, the `ExecuteSubAgent`-backed delegate, `ConversationDetail` persistence,
|
|
17
|
+
* and the `AIPromptRun` usage checkpoint).
|
|
18
|
+
*
|
|
19
|
+
* @module @memberjunction/ai-agents
|
|
20
|
+
* @author MemberJunction.com
|
|
21
|
+
*/
|
|
22
|
+
import { RealtimeToolBroker, INVOKE_TARGET_AGENT_TOOL_NAME } from './realtime-tool-broker.js';
|
|
23
|
+
import { BuildServerNarrationInstructions } from './realtime-narration.js';
|
|
24
|
+
// Re-surface the shared tool-execution contract under this module so existing consumers and tests
|
|
25
|
+
// keep their import paths. The single source of truth is `realtime-tool-broker.ts`.
|
|
26
|
+
export { INVOKE_TARGET_AGENT_TOOL_NAME };
|
|
27
|
+
/**
|
|
28
|
+
* Orchestrates a single `BaseRealtimeModel` duplex session for the Realtime agent type.
|
|
29
|
+
*
|
|
30
|
+
* Construct with a fully-populated {@link RealtimeSessionRunnerDeps}, then call {@link Run} to
|
|
31
|
+
* drive the session to completion, or {@link Start}/{@link Stop} to control it explicitly.
|
|
32
|
+
*/
|
|
33
|
+
export class RealtimeSessionRunner {
|
|
34
|
+
// ── Delegated-run progress narration (server-bridged B3) ──────────────────
|
|
35
|
+
/** First spoken update fires no earlier than this long after a delegation burst starts. */
|
|
36
|
+
static { this.FirstNarrationDelayMs = 5000; }
|
|
37
|
+
/** Minimum gap between SUBSEQUENT spoken updates (floods aggregate into one digest). */
|
|
38
|
+
static { this.NarrationIntervalMs = 8000; }
|
|
39
|
+
/** Max progress messages aggregated into one spoken digest. */
|
|
40
|
+
static { this.MaxDigestMessages = 4; }
|
|
41
|
+
/**
|
|
42
|
+
* Progress steps worth narrating — mirrors the client-direct resolver's filter so both
|
|
43
|
+
* topologies narrate the same signal and drop the same initialization/finalization noise.
|
|
44
|
+
*/
|
|
45
|
+
static { this.SignificantProgressSteps = [
|
|
46
|
+
'prompt_execution', 'action_execution', 'subagent_execution', 'decision_processing'
|
|
47
|
+
]; }
|
|
48
|
+
/**
|
|
49
|
+
* @param deps The injected collaborators that drive the session.
|
|
50
|
+
*/
|
|
51
|
+
constructor(deps) {
|
|
52
|
+
this.session = null;
|
|
53
|
+
/** Accumulated usage across all `OnUsage` deltas, flushed to the checkpoint on debounce/close. */
|
|
54
|
+
this.accumulatedUsage = { InputTokens: 0, OutputTokens: 0 };
|
|
55
|
+
/** Whether there is accumulated usage that has not yet been checkpointed. */
|
|
56
|
+
this.usageDirty = false;
|
|
57
|
+
/** Pending debounce timer handle for usage checkpoints. */
|
|
58
|
+
this.usageDebounceTimer = null;
|
|
59
|
+
/** Count of delegations currently in flight (anchors the narration burst lifecycle). */
|
|
60
|
+
this.activeDelegations = 0;
|
|
61
|
+
/** Epoch ms when the current delegation burst began (first in-flight delegation). */
|
|
62
|
+
this.narrationBurstStartedAt = 0;
|
|
63
|
+
/** Epoch ms of the last spoken update; 0 = never. SESSION-global spacing floor. */
|
|
64
|
+
this.lastNarrationAt = 0;
|
|
65
|
+
/** Spoken updates so far in the current burst (1-based numbering for the instructions). */
|
|
66
|
+
this.narrationCount = 0;
|
|
67
|
+
/** Aggregation buffer: distinct progress messages since the last spoken update (oldest first). */
|
|
68
|
+
this.pendingNarrationMessages = [];
|
|
69
|
+
/** Tail message of the last digest, so an identical trailing progress event isn't re-buffered. */
|
|
70
|
+
this.lastNarratedTail = '';
|
|
71
|
+
/** Pending deferred-narration timer; cancelled when the delegation finishes / barge-in lands. */
|
|
72
|
+
this.narrationTimer = null;
|
|
73
|
+
/** Count of transcript turns persisted, surfaced in the result. */
|
|
74
|
+
this.transcriptTurnCount = 0;
|
|
75
|
+
/** Whether {@link Stop} has been initiated, to make finalization idempotent. */
|
|
76
|
+
this.stopped = false;
|
|
77
|
+
this.deps = deps;
|
|
78
|
+
this.toolBroker = new RealtimeToolBroker({
|
|
79
|
+
// Wrapped so the runner can (a) anchor the narration burst lifecycle around each
|
|
80
|
+
// delegated run and (b) thread its own OnProgress into the delegate — the production
|
|
81
|
+
// delegate (BaseAgent.delegateRealtimeToTarget) passes it into the child RunAgent.
|
|
82
|
+
DelegateToTarget: (request) => this.runDelegateWithNarration(request),
|
|
83
|
+
// Route non-target tool calls through the runner so server-channel tools execute via
|
|
84
|
+
// their dedicated handler before falling back to the generic executor.
|
|
85
|
+
ExecuteTool: (call) => this.executeNonTargetTool(call),
|
|
86
|
+
LogStatus: deps.LogStatus,
|
|
87
|
+
LogError: deps.LogError
|
|
88
|
+
});
|
|
89
|
+
// The set of server-channel tool names (by Name) routed to ExecuteServerChannelTool. Built
|
|
90
|
+
// once from the contributed definitions so per-call routing is an O(1) membership test.
|
|
91
|
+
this.serverChannelToolNames = new Set((deps.ServerChannelTools ?? []).map((t) => t.Name));
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Routes a non-target tool call: a contributed server-channel tool goes to the channel handler
|
|
95
|
+
* ({@link RealtimeSessionRunnerDeps.ExecuteServerChannelTool}); everything else goes to the
|
|
96
|
+
* generic {@link RealtimeSessionRunnerDeps.ExecuteTool}. When a tool is a server-channel tool but
|
|
97
|
+
* no channel handler is wired, it falls through to the generic executor (defensive).
|
|
98
|
+
*
|
|
99
|
+
* @param call The non-target tool call emitted by the model.
|
|
100
|
+
* @returns The tool execution result.
|
|
101
|
+
*/
|
|
102
|
+
async executeNonTargetTool(call) {
|
|
103
|
+
if (this.serverChannelToolNames.has(call.ToolName) && this.deps.ExecuteServerChannelTool) {
|
|
104
|
+
return this.deps.ExecuteServerChannelTool(call);
|
|
105
|
+
}
|
|
106
|
+
return this.deps.ExecuteTool(call);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* The debounce window (ms) for usage checkpoints, defaulting to 5000ms.
|
|
110
|
+
*/
|
|
111
|
+
get debounceMs() {
|
|
112
|
+
return this.deps.UsageCheckpointDebounceMs ?? 5000;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Builds the realtime tool set registered with the provider.
|
|
116
|
+
*
|
|
117
|
+
* Always includes the stable, target-independent {@link INVOKE_TARGET_AGENT_TOOL_NAME} tool,
|
|
118
|
+
* followed by any {@link RealtimeSessionRunnerDeps.ExtraTools} and then any contributed
|
|
119
|
+
* {@link RealtimeSessionRunnerDeps.ServerChannelTools} (the server-side interactive channels'
|
|
120
|
+
* dynamic vocabulary). This is the full set the provider sees — everything target-specific runs
|
|
121
|
+
* *inside* the delegated agent's own run and is never registered on the realtime socket.
|
|
122
|
+
*
|
|
123
|
+
* @returns The ordered tool definitions to register.
|
|
124
|
+
*/
|
|
125
|
+
BuildToolSet() {
|
|
126
|
+
const invokeTargetSchema = {
|
|
127
|
+
type: 'object',
|
|
128
|
+
properties: {
|
|
129
|
+
request: {
|
|
130
|
+
type: 'string',
|
|
131
|
+
description: 'The natural-language request to hand to the target agent to perform real work.'
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
required: ['request']
|
|
135
|
+
};
|
|
136
|
+
const invokeTargetTool = {
|
|
137
|
+
Name: INVOKE_TARGET_AGENT_TOOL_NAME,
|
|
138
|
+
Description: 'Invoke the target agent to perform real work (seconds to minutes). Use this whenever ' +
|
|
139
|
+
'actual work is needed beyond conversation; narrate while it runs.',
|
|
140
|
+
ParametersSchema: invokeTargetSchema
|
|
141
|
+
};
|
|
142
|
+
return [
|
|
143
|
+
invokeTargetTool,
|
|
144
|
+
...(this.deps.ExtraTools ?? []),
|
|
145
|
+
...(this.deps.ServerChannelTools ?? [])
|
|
146
|
+
];
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Opens the session, registers tools, and wires all provider event handlers.
|
|
150
|
+
*
|
|
151
|
+
* Idempotent guard: throws if the session is already started. After this resolves, the session
|
|
152
|
+
* is live and streaming; call {@link Stop} (or {@link Run}, which awaits closure) to finalize.
|
|
153
|
+
*
|
|
154
|
+
* @throws If the model fails to start a session.
|
|
155
|
+
*/
|
|
156
|
+
async Start() {
|
|
157
|
+
if (this.session) {
|
|
158
|
+
throw new Error('RealtimeSessionRunner.Start called but a session is already active.');
|
|
159
|
+
}
|
|
160
|
+
const tools = this.BuildToolSet();
|
|
161
|
+
const params = { ...this.deps.SessionParams, Tools: tools };
|
|
162
|
+
// The tool set rides StartSession params — the canonical (and for connect-bound
|
|
163
|
+
// providers like Gemini Live, the ONLY effective) registration path. A post-start
|
|
164
|
+
// RegisterTools with the identical set would be a contract-mandated no-op, so the
|
|
165
|
+
// runner does not make that redundant call.
|
|
166
|
+
this.session = await this.deps.Model.StartSession(params);
|
|
167
|
+
this.wireHandlers(this.session);
|
|
168
|
+
this.deps.LogStatus?.(`🎙️ Realtime session started with ${tools.length} tool(s) (target-independent set).`, true);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Registers the provider event handlers on the live session.
|
|
172
|
+
*
|
|
173
|
+
* @param session The active session to wire.
|
|
174
|
+
*/
|
|
175
|
+
wireHandlers(session) {
|
|
176
|
+
session.OnTranscript((t) => void this.handleTranscript(t));
|
|
177
|
+
session.OnToolCall((call) => void this.handleToolCall(call));
|
|
178
|
+
session.OnUsage((u) => this.handleUsage(u));
|
|
179
|
+
session.OnInterruption(() => this.handleInterruption());
|
|
180
|
+
session.OnError((error) => this.handleSessionError(error));
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Handles a session error per the {@link IRealtimeSession.OnError} fatality contract:
|
|
184
|
+
* - `Fatal: true` (transport/socket failure, credential expiry, unexpected close) — the
|
|
185
|
+
* session is unusable, so the runner finalizes cleanly via {@link Stop} (final usage
|
|
186
|
+
* flush, delegated-run abort, idempotent teardown) instead of idling on a dead socket.
|
|
187
|
+
* - `Fatal: false` — a provider-reported, recoverable error frame; logged, session
|
|
188
|
+
* continues.
|
|
189
|
+
*
|
|
190
|
+
* @param error The error surfaced by the live session.
|
|
191
|
+
*/
|
|
192
|
+
handleSessionError(error) {
|
|
193
|
+
const code = error.Code ? ` [${error.Code}]` : '';
|
|
194
|
+
if (error.Fatal) {
|
|
195
|
+
this.deps.LogError?.(`Fatal realtime session error${code} — finalizing session: ${error.Message}`);
|
|
196
|
+
void this.Stop();
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
this.deps.LogError?.(`Realtime session error (non-fatal)${code}: ${error.Message}`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Persists a transcript turn via the injected persistence collaborator.
|
|
204
|
+
*
|
|
205
|
+
* @param transcript The transcript event (partial or final) emitted by the model.
|
|
206
|
+
*/
|
|
207
|
+
async handleTranscript(transcript) {
|
|
208
|
+
try {
|
|
209
|
+
await this.deps.PersistTranscript(transcript);
|
|
210
|
+
this.transcriptTurnCount++;
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
this.logError(error, 'persisting transcript');
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Routes a tool call through the shared {@link RealtimeToolBroker} and feeds its serialized
|
|
218
|
+
* result back to the model.
|
|
219
|
+
*
|
|
220
|
+
* The broker performs identical routing for both topologies (`invoke-target-agent` → delegate;
|
|
221
|
+
* everything else → the tool executor), owns the per-call abort controller, and serializes the
|
|
222
|
+
* success/error result. The runner only relays the broker's `ResultJson` over the live session
|
|
223
|
+
* via {@link IRealtimeSession.SendToolResult}.
|
|
224
|
+
*
|
|
225
|
+
* @param call The tool-call request emitted by the model.
|
|
226
|
+
*/
|
|
227
|
+
async handleToolCall(call) {
|
|
228
|
+
const executed = await this.toolBroker.ExecuteToolCall(call);
|
|
229
|
+
await this.dispatchToolResult(call.CallID, executed.ResultJson, 'sending tool result');
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Sends a serialized tool result to the live session, logging (but not rethrowing) any failure.
|
|
233
|
+
*
|
|
234
|
+
* @param callID The originating tool call's id.
|
|
235
|
+
* @param resultJson The JSON-stringified result to send.
|
|
236
|
+
* @param operation A short description of the send operation, used in error logging.
|
|
237
|
+
*/
|
|
238
|
+
async dispatchToolResult(callID, resultJson, operation) {
|
|
239
|
+
if (!this.session) {
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
try {
|
|
243
|
+
await this.session.SendToolResult(callID, resultJson);
|
|
244
|
+
}
|
|
245
|
+
catch (error) {
|
|
246
|
+
this.logError(error, operation);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Accumulates a usage delta and schedules a debounced checkpoint.
|
|
251
|
+
*
|
|
252
|
+
* @param usage The incremental usage update reported by the provider.
|
|
253
|
+
*/
|
|
254
|
+
handleUsage(usage) {
|
|
255
|
+
this.accumulatedUsage = {
|
|
256
|
+
InputTokens: this.accumulatedUsage.InputTokens + usage.InputTokens,
|
|
257
|
+
OutputTokens: this.accumulatedUsage.OutputTokens + usage.OutputTokens
|
|
258
|
+
};
|
|
259
|
+
this.usageDirty = true;
|
|
260
|
+
this.scheduleUsageCheckpoint();
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Schedules a single debounced usage checkpoint. Repeated calls within the window coalesce
|
|
264
|
+
* into one flush, bounding write frequency during a token-heavy turn.
|
|
265
|
+
*/
|
|
266
|
+
scheduleUsageCheckpoint() {
|
|
267
|
+
if (this.usageDebounceTimer) {
|
|
268
|
+
return; // a flush is already pending
|
|
269
|
+
}
|
|
270
|
+
this.usageDebounceTimer = setTimeout(() => {
|
|
271
|
+
this.usageDebounceTimer = null;
|
|
272
|
+
void this.flushUsage();
|
|
273
|
+
}, this.debounceMs);
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Flushes the accumulated usage to the checkpoint collaborator if there is anything new.
|
|
277
|
+
*
|
|
278
|
+
* Sends a snapshot of the *cumulative* total (matching the plan's "finalize from the
|
|
279
|
+
* last-persisted values" contract) and clears the dirty flag.
|
|
280
|
+
*/
|
|
281
|
+
async flushUsage() {
|
|
282
|
+
if (!this.usageDirty) {
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
this.usageDirty = false;
|
|
286
|
+
const snapshot = {
|
|
287
|
+
InputTokens: this.accumulatedUsage.InputTokens,
|
|
288
|
+
OutputTokens: this.accumulatedUsage.OutputTokens
|
|
289
|
+
};
|
|
290
|
+
try {
|
|
291
|
+
await this.deps.CheckpointUsage(snapshot);
|
|
292
|
+
}
|
|
293
|
+
catch (error) {
|
|
294
|
+
// Re-mark dirty so the next debounce/close attempt retries the flush.
|
|
295
|
+
this.usageDirty = true;
|
|
296
|
+
this.logError(error, 'checkpointing usage');
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Handles a provider-detected interruption (barge-in).
|
|
301
|
+
*
|
|
302
|
+
* Aborts the in-flight delegated run's controller (if any) so a stale delegated result is
|
|
303
|
+
* never narrated into a conversation that has moved on. Turn detection / VAD and stopping the
|
|
304
|
+
* model's current turn are owned by the provider; the consequence for delegated work is ours.
|
|
305
|
+
*/
|
|
306
|
+
handleInterruption() {
|
|
307
|
+
this.deps.LogStatus?.('✋ Barge-in detected — aborting in-flight delegated run if any.', true);
|
|
308
|
+
this.toolBroker.AbortInFlight();
|
|
309
|
+
// The user took the floor — any pending spoken progress update is stale.
|
|
310
|
+
this.cancelPendingNarration();
|
|
311
|
+
}
|
|
312
|
+
// ── Delegated-run progress narration (server-bridged B3) ──────────────────
|
|
313
|
+
/**
|
|
314
|
+
* Runs one delegated call through the injected delegate while owning the NARRATION burst
|
|
315
|
+
* around it: progress events are threaded back via {@link DelegateToTargetRequest.OnProgress},
|
|
316
|
+
* and when the delegation finishes (success, failure, or abort) any still-pending spoken
|
|
317
|
+
* update is cancelled — the final tool result is about to be voiced, so an interim "still
|
|
318
|
+
* working…" line is moot.
|
|
319
|
+
*/
|
|
320
|
+
async runDelegateWithNarration(request) {
|
|
321
|
+
this.beginDelegationBurst();
|
|
322
|
+
try {
|
|
323
|
+
return await this.deps.DelegateToTarget({
|
|
324
|
+
...request,
|
|
325
|
+
OnProgress: (progress) => this.handleDelegationProgress(progress)
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
finally {
|
|
329
|
+
this.endDelegation();
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Anchors a fresh narration burst when no other delegation is in flight. Deliberately NOT
|
|
334
|
+
* reset across bursts: {@link lastNarrationAt} (the ~8s spacing floor is SESSION-global, so
|
|
335
|
+
* sequential tool calls seconds apart can never narrate faster than the interval).
|
|
336
|
+
*/
|
|
337
|
+
beginDelegationBurst() {
|
|
338
|
+
if (this.activeDelegations === 0) {
|
|
339
|
+
this.narrationBurstStartedAt = Date.now();
|
|
340
|
+
this.narrationCount = 0;
|
|
341
|
+
this.pendingNarrationMessages = [];
|
|
342
|
+
this.lastNarratedTail = '';
|
|
343
|
+
}
|
|
344
|
+
this.activeDelegations++;
|
|
345
|
+
}
|
|
346
|
+
/** Closes one delegation; when none remain in flight, pending narration is cancelled. */
|
|
347
|
+
endDelegation() {
|
|
348
|
+
this.activeDelegations = Math.max(0, this.activeDelegations - 1);
|
|
349
|
+
if (this.activeDelegations === 0) {
|
|
350
|
+
this.cancelPendingNarration();
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Consumes one delegated-run progress event:
|
|
355
|
+
* - significant steps only (mirrors the client-direct resolver's filter);
|
|
356
|
+
* - the message is ALWAYS injected as a background context note (feature-detected —
|
|
357
|
+
* {@link IRealtimeSession.SendContextNote} is an optional capability) so the model can
|
|
358
|
+
* draw on it whenever it next speaks;
|
|
359
|
+
* - a THROTTLED spoken update is scheduled (feature-detected —
|
|
360
|
+
* {@link IRealtimeSession.RequestSpokenUpdate} is optional): first at ~5s into the burst,
|
|
361
|
+
* then every ~8s, with floods aggregated into ONE digest. Collision with an in-flight
|
|
362
|
+
* model response is the DRIVER's obligation (queue or skip) per the
|
|
363
|
+
* `RequestSpokenUpdate` contract, so the runner does not gate on busy state.
|
|
364
|
+
*/
|
|
365
|
+
handleDelegationProgress(progress) {
|
|
366
|
+
if (!RealtimeSessionRunner.SignificantProgressSteps.includes(progress.step)) {
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
const session = this.session;
|
|
370
|
+
if (!session || this.activeDelegations === 0) {
|
|
371
|
+
return; // session gone / delegation already finished — stale event
|
|
372
|
+
}
|
|
373
|
+
session.SendContextNote?.(`[delegated-agent progress] ${progress.message}`);
|
|
374
|
+
if (!session.RequestSpokenUpdate) {
|
|
375
|
+
return; // provider can't voice an instructed one-off update — context note only
|
|
376
|
+
}
|
|
377
|
+
this.bufferNarrationMessage(progress.message);
|
|
378
|
+
if (this.pendingNarrationMessages.length > 0 && !this.narrationTimer) {
|
|
379
|
+
this.narrationTimer = setTimeout(() => this.fireDeferredNarration(), this.nextNarrationDelayMs());
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
/** Adds a progress message to the digest buffer (deduped, capped, oldest-first). */
|
|
383
|
+
bufferNarrationMessage(message) {
|
|
384
|
+
if (message === this.lastNarratedTail || this.pendingNarrationMessages.includes(message)) {
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
this.pendingNarrationMessages.push(message);
|
|
388
|
+
if (this.pendingNarrationMessages.length > RealtimeSessionRunner.MaxDigestMessages) {
|
|
389
|
+
this.pendingNarrationMessages.shift();
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* ms until the next spoken update is allowed. Two constraints, BOTH enforced:
|
|
394
|
+
* - first update of a burst: no earlier than ~5s after the burst started;
|
|
395
|
+
* - ~8s since the last spoken update, SESSION-global.
|
|
396
|
+
*/
|
|
397
|
+
nextNarrationDelayMs() {
|
|
398
|
+
const now = Date.now();
|
|
399
|
+
const firstAnchor = this.narrationCount === 0
|
|
400
|
+
? this.narrationBurstStartedAt + RealtimeSessionRunner.FirstNarrationDelayMs
|
|
401
|
+
: 0;
|
|
402
|
+
const spacingFloor = this.lastNarrationAt > 0
|
|
403
|
+
? this.lastNarrationAt + this.narrationIntervalMs()
|
|
404
|
+
: 0;
|
|
405
|
+
return Math.max(50, Math.max(firstAnchor, spacingFloor) - now);
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* The effective spoken-update spacing: the deps' configuration-driven
|
|
409
|
+
* {@link RealtimeSessionRunnerDeps.NarrationPaceMs} when it is a positive finite number,
|
|
410
|
+
* else the built-in {@link RealtimeSessionRunner.NarrationIntervalMs} default.
|
|
411
|
+
*/
|
|
412
|
+
narrationIntervalMs() {
|
|
413
|
+
const pace = this.deps.NarrationPaceMs;
|
|
414
|
+
return typeof pace === 'number' && Number.isFinite(pace) && pace > 0
|
|
415
|
+
? pace
|
|
416
|
+
: RealtimeSessionRunner.NarrationIntervalMs;
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Speaks the aggregated progress digest — unless the work already finished (buffer cancelled)
|
|
420
|
+
* or the session is gone. Per-turn collision safety is the driver's `RequestSpokenUpdate`
|
|
421
|
+
* obligation (queue or skip), so no busy gate is needed here.
|
|
422
|
+
*/
|
|
423
|
+
fireDeferredNarration() {
|
|
424
|
+
this.narrationTimer = null;
|
|
425
|
+
const session = this.session;
|
|
426
|
+
if (!session?.RequestSpokenUpdate || this.pendingNarrationMessages.length === 0 || this.activeDelegations === 0) {
|
|
427
|
+
this.pendingNarrationMessages = [];
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
const digest = this.pendingNarrationMessages.join(' → ');
|
|
431
|
+
this.lastNarratedTail = this.pendingNarrationMessages[this.pendingNarrationMessages.length - 1];
|
|
432
|
+
this.pendingNarrationMessages = [];
|
|
433
|
+
this.narrationCount++;
|
|
434
|
+
this.lastNarrationAt = Date.now();
|
|
435
|
+
session.RequestSpokenUpdate(BuildServerNarrationInstructions(this.deps.NarrationInstructionsTemplate, digest, this.narrationCount));
|
|
436
|
+
}
|
|
437
|
+
/** Cancels any deferred spoken update and drops the digest buffer. */
|
|
438
|
+
cancelPendingNarration() {
|
|
439
|
+
if (this.narrationTimer) {
|
|
440
|
+
clearTimeout(this.narrationTimer);
|
|
441
|
+
this.narrationTimer = null;
|
|
442
|
+
}
|
|
443
|
+
this.pendingNarrationMessages = [];
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Closes the session and finalizes usage. Idempotent: a second call is a no-op.
|
|
447
|
+
*
|
|
448
|
+
* Cancels any pending debounce timer, performs a final synchronous-cadence usage flush so no
|
|
449
|
+
* partial usage is lost, closes the underlying session, and returns the run result.
|
|
450
|
+
*
|
|
451
|
+
* @returns The final {@link RealtimeSessionResult}.
|
|
452
|
+
*/
|
|
453
|
+
async Stop() {
|
|
454
|
+
if (this.stopped) {
|
|
455
|
+
return this.buildResult(true);
|
|
456
|
+
}
|
|
457
|
+
this.stopped = true;
|
|
458
|
+
// Cancel any pending debounce and force a final flush so partial usage is never lost.
|
|
459
|
+
if (this.usageDebounceTimer) {
|
|
460
|
+
clearTimeout(this.usageDebounceTimer);
|
|
461
|
+
this.usageDebounceTimer = null;
|
|
462
|
+
}
|
|
463
|
+
await this.flushUsage();
|
|
464
|
+
// A pending spoken progress update is meaningless on a closing session.
|
|
465
|
+
this.cancelPendingNarration();
|
|
466
|
+
// Abort any still-in-flight delegation before tearing down.
|
|
467
|
+
this.toolBroker.AbortInFlight();
|
|
468
|
+
let errorMessage;
|
|
469
|
+
try {
|
|
470
|
+
await this.session?.Close();
|
|
471
|
+
}
|
|
472
|
+
catch (error) {
|
|
473
|
+
errorMessage = error instanceof Error ? error.message : String(error);
|
|
474
|
+
this.logError(error, 'closing session');
|
|
475
|
+
}
|
|
476
|
+
finally {
|
|
477
|
+
this.session = null;
|
|
478
|
+
}
|
|
479
|
+
this.deps.LogStatus?.('🛑 Realtime session finalized.', true);
|
|
480
|
+
return this.buildResult(!errorMessage, errorMessage);
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Builds the run result from the current accumulated state.
|
|
484
|
+
*
|
|
485
|
+
* @param success Whether the session is considered successful.
|
|
486
|
+
* @param errorMessage Optional error message to attach.
|
|
487
|
+
* @returns The result object.
|
|
488
|
+
*/
|
|
489
|
+
buildResult(success, errorMessage) {
|
|
490
|
+
return {
|
|
491
|
+
Success: success,
|
|
492
|
+
FinalUsage: {
|
|
493
|
+
InputTokens: this.accumulatedUsage.InputTokens,
|
|
494
|
+
OutputTokens: this.accumulatedUsage.OutputTokens
|
|
495
|
+
},
|
|
496
|
+
TranscriptTurnCount: this.transcriptTurnCount,
|
|
497
|
+
ErrorMessage: errorMessage
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Convenience lifecycle: starts the session and immediately finalizes it.
|
|
502
|
+
*
|
|
503
|
+
* This is primarily useful for tests and for callers that drive the session entirely through
|
|
504
|
+
* the injected handlers (which fire between {@link Start} and {@link Stop}). Most real callers
|
|
505
|
+
* will use {@link Start} then later {@link Stop} when the user hangs up or the session times
|
|
506
|
+
* out. If start fails, a failed result is returned with the error.
|
|
507
|
+
*
|
|
508
|
+
* @returns The final {@link RealtimeSessionResult}.
|
|
509
|
+
*/
|
|
510
|
+
async Run() {
|
|
511
|
+
try {
|
|
512
|
+
await this.Start();
|
|
513
|
+
}
|
|
514
|
+
catch (error) {
|
|
515
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
516
|
+
this.logError(error, 'starting session');
|
|
517
|
+
return this.buildResult(false, errorMessage);
|
|
518
|
+
}
|
|
519
|
+
return this.Stop();
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Logs an error via the injected logger (if any), prefixed with the failing operation.
|
|
523
|
+
*
|
|
524
|
+
* @param error The thrown error or message.
|
|
525
|
+
* @param operation A short description of what was being attempted.
|
|
526
|
+
*/
|
|
527
|
+
logError(error, operation) {
|
|
528
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
529
|
+
this.deps.LogError?.(`RealtimeSessionRunner error while ${operation}: ${message}`);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
//# sourceMappingURL=realtime-session-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realtime-session-runner.js","sourceRoot":"","sources":["../../src/realtime/realtime-session-runner.ts"],"names":[],"mappings":"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"}
|