@getpaseo/server 0.1.98 → 0.1.99
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server/server/agent/agent-manager.js +2 -2
- package/dist/server/server/agent/agent-sdk-types.d.ts +11 -6
- package/dist/server/server/agent/provider-registry.d.ts +6 -3
- package/dist/server/server/agent/provider-registry.js +48 -22
- package/dist/server/server/agent/provider-snapshot-manager.js +26 -14
- package/dist/server/server/agent/providers/acp-agent.d.ts +5 -3
- package/dist/server/server/agent/providers/acp-agent.js +32 -19
- package/dist/server/server/agent/providers/claude/agent.d.ts +2 -2
- package/dist/server/server/agent/providers/claude/agent.js +5 -25
- package/dist/server/server/agent/providers/codex-app-server-agent.d.ts +3 -2
- package/dist/server/server/agent/providers/codex-app-server-agent.js +6 -25
- package/dist/server/server/agent/providers/copilot-acp-agent.js +1 -31
- package/dist/server/server/agent/providers/generic-acp-agent.d.ts +0 -1
- package/dist/server/server/agent/providers/generic-acp-agent.js +2 -108
- package/dist/server/server/agent/providers/mock-load-test-agent.d.ts +2 -3
- package/dist/server/server/agent/providers/mock-load-test-agent.js +5 -5
- package/dist/server/server/agent/providers/mock-slow-provider.d.ts +2 -3
- package/dist/server/server/agent/providers/mock-slow-provider.js +2 -5
- package/dist/server/server/agent/providers/opencode-agent.d.ts +4 -3
- package/dist/server/server/agent/providers/opencode-agent.js +48 -99
- package/dist/server/server/agent/providers/pi/agent.d.ts +2 -3
- package/dist/server/server/agent/providers/pi/agent.js +8 -73
- package/dist/server/server/agent/providers/pi/cli-runtime.js +2 -2
- package/dist/server/server/agent/providers/pi/runtime.d.ts +1 -1
- package/dist/server/server/agent/providers/pi/test-utils/fake-pi.d.ts +1 -1
- package/dist/server/server/agent/providers/pi/test-utils/fake-pi.js +1 -1
- package/dist/server/server/session/agent-config/agent-config-session.d.ts +50 -0
- package/dist/server/server/session/agent-config/agent-config-session.js +98 -0
- package/dist/server/server/session/chat/chat-schedule-loop-session.d.ts +120 -0
- package/dist/server/server/session/chat/chat-schedule-loop-session.js +489 -0
- package/dist/server/server/session/checkout/checkout-session.d.ts +142 -0
- package/dist/server/server/session/checkout/checkout-session.js +925 -0
- package/dist/server/server/session/daemon/daemon-session.d.ts +50 -0
- package/dist/server/server/session/daemon/daemon-session.js +98 -0
- package/dist/server/server/session/files/workspace-files-session.d.ts +43 -0
- package/dist/server/server/session/files/workspace-files-session.js +218 -0
- package/dist/server/server/session/project-config/project-config-session.d.ts +34 -0
- package/dist/server/server/session/project-config/project-config-session.js +125 -0
- package/dist/server/server/session/provider/provider-catalog-session.d.ts +74 -0
- package/dist/server/server/session/provider/provider-catalog-session.js +339 -0
- package/dist/server/server/session/voice/voice-session.d.ts +166 -0
- package/dist/server/server/session/voice/voice-session.js +893 -0
- package/dist/server/server/{voice → session/voice}/voice-turn-controller.d.ts +2 -2
- package/dist/server/server/{voice → session/voice}/voice-turn-controller.js +2 -2
- package/dist/server/server/session.d.ts +13 -208
- package/dist/server/server/session.js +2132 -5105
- package/dist/server/utils/checkout-git.d.ts +6 -0
- package/package.json +5 -5
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
import { getErrorMessage } from "@getpaseo/protocol/error-utils";
|
|
2
|
+
import { resolveSnapshotCwd, } from "../../agent/provider-snapshot-manager.js";
|
|
3
|
+
import { expandTilde } from "../../../utils/path.js";
|
|
4
|
+
// COMPAT(customModeIcons): the only mode icons known to clients before v0.1.84. Any
|
|
5
|
+
// other icon name is downgraded to "ShieldCheck" for those clients.
|
|
6
|
+
const LEGACY_MODE_ICONS = new Set([
|
|
7
|
+
"ShieldCheck",
|
|
8
|
+
"ShieldAlert",
|
|
9
|
+
"ShieldOff",
|
|
10
|
+
"ShieldQuestionMark",
|
|
11
|
+
]);
|
|
12
|
+
/**
|
|
13
|
+
* A client's provider catalog surface: model / mode / feature listing, the providers
|
|
14
|
+
* snapshot push + pull, provider diagnostics, and usage. The snapshot PUSH (start) and
|
|
15
|
+
* every PULL handler gate visibility and downgrade mode icons through the SAME predicates,
|
|
16
|
+
* so an older client sees one consistent provider set across both paths — the COMPAT
|
|
17
|
+
* invariant the shell could only enforce by code proximity before this carve.
|
|
18
|
+
*/
|
|
19
|
+
export class ProviderCatalogSession {
|
|
20
|
+
constructor(options) {
|
|
21
|
+
this.unsubscribeSnapshotEvents = null;
|
|
22
|
+
this.host = options.host;
|
|
23
|
+
this.providerSnapshotManager = options.providerSnapshotManager;
|
|
24
|
+
this.providerUsageService = options.providerUsageService;
|
|
25
|
+
this.logger = options.logger;
|
|
26
|
+
}
|
|
27
|
+
start() {
|
|
28
|
+
const handleProviderSnapshotChange = (entries, cwd) => {
|
|
29
|
+
// COMPAT(providersSnapshot): keep provider visibility gating for older clients.
|
|
30
|
+
const visibleEntries = entries.filter((entry) => this.host.isProviderVisibleToClient(entry.provider));
|
|
31
|
+
const snapshotCwd = cwd === resolveSnapshotCwd() ? undefined : cwd;
|
|
32
|
+
this.host.emit({
|
|
33
|
+
type: "providers_snapshot_update",
|
|
34
|
+
payload: {
|
|
35
|
+
...(snapshotCwd ? { cwd: snapshotCwd } : {}),
|
|
36
|
+
entries: this.downgradeEntryModesForClient(visibleEntries),
|
|
37
|
+
generatedAt: new Date().toISOString(),
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
this.providerSnapshotManager.on("change", handleProviderSnapshotChange);
|
|
42
|
+
this.unsubscribeSnapshotEvents = () => {
|
|
43
|
+
this.providerSnapshotManager.off("change", handleProviderSnapshotChange);
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
dispose() {
|
|
47
|
+
if (this.unsubscribeSnapshotEvents) {
|
|
48
|
+
this.unsubscribeSnapshotEvents();
|
|
49
|
+
this.unsubscribeSnapshotEvents = null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// COMPAT(customModeIcons): rewrite icons unknown to v0.1.83 clients (whose MODE_ICONS
|
|
53
|
+
// map is a closed enum and would render `undefined`, crashing in render). Drop
|
|
54
|
+
// this and the cap gate when floor >= v0.1.84.
|
|
55
|
+
downgradeModeIconsForClient(modes) {
|
|
56
|
+
if (this.host.supportsCustomModeIcons())
|
|
57
|
+
return modes;
|
|
58
|
+
return modes.map((mode) => mode.icon && !LEGACY_MODE_ICONS.has(mode.icon) ? { ...mode, icon: "ShieldCheck" } : mode);
|
|
59
|
+
}
|
|
60
|
+
downgradeEntryModesForClient(entries) {
|
|
61
|
+
if (this.host.supportsCustomModeIcons())
|
|
62
|
+
return entries;
|
|
63
|
+
return entries.map((entry) => entry.modes ? { ...entry, modes: this.downgradeModeIconsForClient(entry.modes) } : entry);
|
|
64
|
+
}
|
|
65
|
+
emitProviderDisabledResponse(kind, provider, requestId, fetchedAt) {
|
|
66
|
+
const payload = {
|
|
67
|
+
provider,
|
|
68
|
+
error: `Provider ${provider} is disabled`,
|
|
69
|
+
fetchedAt,
|
|
70
|
+
requestId,
|
|
71
|
+
};
|
|
72
|
+
if (kind === "models") {
|
|
73
|
+
this.host.emit({ type: "list_provider_models_response", payload });
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
this.host.emit({ type: "list_provider_modes_response", payload });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
async handleListProviderModelsRequest(msg) {
|
|
80
|
+
const cwd = resolveSnapshotCwd(msg.cwd ? expandTilde(msg.cwd) : undefined);
|
|
81
|
+
const fetchedAt = new Date().toISOString();
|
|
82
|
+
const entry = await this.getProviderSnapshotEntryForRead(cwd, msg.provider);
|
|
83
|
+
if (!entry) {
|
|
84
|
+
this.host.emit({
|
|
85
|
+
type: "list_provider_models_response",
|
|
86
|
+
payload: {
|
|
87
|
+
provider: msg.provider,
|
|
88
|
+
error: `Unknown provider: ${msg.provider}`,
|
|
89
|
+
fetchedAt,
|
|
90
|
+
requestId: msg.requestId,
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (!entry.enabled) {
|
|
96
|
+
this.emitProviderDisabledResponse("models", msg.provider, msg.requestId, fetchedAt);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (entry.status === "ready") {
|
|
100
|
+
this.host.emit({
|
|
101
|
+
type: "list_provider_models_response",
|
|
102
|
+
payload: {
|
|
103
|
+
provider: msg.provider,
|
|
104
|
+
models: entry.models ?? [],
|
|
105
|
+
error: null,
|
|
106
|
+
fetchedAt: entry.fetchedAt ?? fetchedAt,
|
|
107
|
+
requestId: msg.requestId,
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const errorMessage = entry.status === "error"
|
|
113
|
+
? (entry.error ?? `Failed to list models for ${msg.provider}`)
|
|
114
|
+
: `Provider ${msg.provider} is not available`;
|
|
115
|
+
this.host.emit({
|
|
116
|
+
type: "list_provider_models_response",
|
|
117
|
+
payload: {
|
|
118
|
+
provider: msg.provider,
|
|
119
|
+
error: errorMessage,
|
|
120
|
+
fetchedAt,
|
|
121
|
+
requestId: msg.requestId,
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
async handleListProviderModesRequest(msg) {
|
|
126
|
+
const fetchedAt = new Date().toISOString();
|
|
127
|
+
const cwd = resolveSnapshotCwd(msg.cwd ? expandTilde(msg.cwd) : undefined);
|
|
128
|
+
const entry = await this.getProviderSnapshotEntryForRead(cwd, msg.provider);
|
|
129
|
+
if (!entry) {
|
|
130
|
+
this.host.emit({
|
|
131
|
+
type: "list_provider_modes_response",
|
|
132
|
+
payload: {
|
|
133
|
+
provider: msg.provider,
|
|
134
|
+
error: `Unknown provider: ${msg.provider}`,
|
|
135
|
+
fetchedAt,
|
|
136
|
+
requestId: msg.requestId,
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (!entry.enabled) {
|
|
142
|
+
this.emitProviderDisabledResponse("modes", msg.provider, msg.requestId, fetchedAt);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (entry.status === "ready") {
|
|
146
|
+
this.host.emit({
|
|
147
|
+
type: "list_provider_modes_response",
|
|
148
|
+
payload: {
|
|
149
|
+
provider: msg.provider,
|
|
150
|
+
modes: this.downgradeModeIconsForClient(entry.modes ?? []),
|
|
151
|
+
error: null,
|
|
152
|
+
fetchedAt: entry.fetchedAt ?? fetchedAt,
|
|
153
|
+
requestId: msg.requestId,
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const errorMessage = entry.status === "error"
|
|
159
|
+
? (entry.error ?? `Failed to list modes for ${msg.provider}`)
|
|
160
|
+
: `Provider ${msg.provider} is not available`;
|
|
161
|
+
this.host.emit({
|
|
162
|
+
type: "list_provider_modes_response",
|
|
163
|
+
payload: {
|
|
164
|
+
provider: msg.provider,
|
|
165
|
+
error: errorMessage,
|
|
166
|
+
fetchedAt,
|
|
167
|
+
requestId: msg.requestId,
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
async getProviderSnapshotEntryForRead(cwd, provider) {
|
|
172
|
+
const manager = this.providerSnapshotManager;
|
|
173
|
+
const findEntry = () => manager.getSnapshot(cwd).find((candidate) => candidate.provider === provider);
|
|
174
|
+
let entry = findEntry();
|
|
175
|
+
if (entry && !entry.enabled) {
|
|
176
|
+
return entry;
|
|
177
|
+
}
|
|
178
|
+
if (!entry || entry.status === "loading") {
|
|
179
|
+
// Awaits the in-flight warmup (deduped per-cwd) so old clients still get
|
|
180
|
+
// a resolved answer rather than a loading placeholder.
|
|
181
|
+
await manager.warmUpSnapshotForCwd({ cwd, providers: [provider] });
|
|
182
|
+
entry = findEntry();
|
|
183
|
+
}
|
|
184
|
+
return entry;
|
|
185
|
+
}
|
|
186
|
+
buildDraftAgentSessionConfig(draftConfig) {
|
|
187
|
+
return {
|
|
188
|
+
provider: draftConfig.provider,
|
|
189
|
+
cwd: expandTilde(draftConfig.cwd),
|
|
190
|
+
...(draftConfig.modeId ? { modeId: draftConfig.modeId } : {}),
|
|
191
|
+
...(draftConfig.model ? { model: draftConfig.model } : {}),
|
|
192
|
+
...(draftConfig.thinkingOptionId ? { thinkingOptionId: draftConfig.thinkingOptionId } : {}),
|
|
193
|
+
...(draftConfig.featureValues ? { featureValues: draftConfig.featureValues } : {}),
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
async handleListProviderFeaturesRequest(msg) {
|
|
197
|
+
const fetchedAt = new Date().toISOString();
|
|
198
|
+
try {
|
|
199
|
+
const sessionConfig = this.buildDraftAgentSessionConfig(msg.draftConfig);
|
|
200
|
+
const features = await this.host.listDraftFeatures(sessionConfig);
|
|
201
|
+
this.host.emit({
|
|
202
|
+
type: "list_provider_features_response",
|
|
203
|
+
payload: {
|
|
204
|
+
provider: msg.draftConfig.provider,
|
|
205
|
+
features,
|
|
206
|
+
error: null,
|
|
207
|
+
fetchedAt,
|
|
208
|
+
requestId: msg.requestId,
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
this.logger.error({ err: error, provider: msg.draftConfig.provider, draftConfig: msg.draftConfig }, `Failed to list features for ${msg.draftConfig.provider}`);
|
|
214
|
+
this.host.emit({
|
|
215
|
+
type: "list_provider_features_response",
|
|
216
|
+
payload: {
|
|
217
|
+
provider: msg.draftConfig.provider,
|
|
218
|
+
error: getErrorMessage(error),
|
|
219
|
+
fetchedAt,
|
|
220
|
+
requestId: msg.requestId,
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
async handleListAvailableProvidersRequest(msg) {
|
|
226
|
+
const fetchedAt = new Date().toISOString();
|
|
227
|
+
try {
|
|
228
|
+
const providers = (await this.host.listProviderAvailability()).filter((provider) => this.host.isProviderVisibleToClient(provider.provider));
|
|
229
|
+
this.host.emit({
|
|
230
|
+
type: "list_available_providers_response",
|
|
231
|
+
payload: {
|
|
232
|
+
providers,
|
|
233
|
+
error: null,
|
|
234
|
+
fetchedAt,
|
|
235
|
+
requestId: msg.requestId,
|
|
236
|
+
},
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
catch (error) {
|
|
240
|
+
this.logger.error({ err: error }, "Failed to list provider availability");
|
|
241
|
+
this.host.emit({
|
|
242
|
+
type: "list_available_providers_response",
|
|
243
|
+
payload: {
|
|
244
|
+
providers: [],
|
|
245
|
+
error: getErrorMessage(error),
|
|
246
|
+
fetchedAt,
|
|
247
|
+
requestId: msg.requestId,
|
|
248
|
+
},
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
async handleGetProvidersSnapshotRequest(msg) {
|
|
253
|
+
// COMPAT(providersSnapshot): keep legacy provider-list RPCs alongside snapshot flow.
|
|
254
|
+
const entries = this.providerSnapshotManager
|
|
255
|
+
.getSnapshot(msg.cwd ? expandTilde(msg.cwd) : undefined)
|
|
256
|
+
.filter((entry) => this.host.isProviderVisibleToClient(entry.provider));
|
|
257
|
+
this.host.emit({
|
|
258
|
+
type: "get_providers_snapshot_response",
|
|
259
|
+
payload: {
|
|
260
|
+
entries: this.downgradeEntryModesForClient(entries),
|
|
261
|
+
generatedAt: new Date().toISOString(),
|
|
262
|
+
requestId: msg.requestId,
|
|
263
|
+
},
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
async handleRefreshProvidersSnapshotRequest(msg) {
|
|
267
|
+
if (msg.cwd) {
|
|
268
|
+
await this.providerSnapshotManager.refreshSnapshotForCwd({
|
|
269
|
+
cwd: expandTilde(msg.cwd),
|
|
270
|
+
providers: msg.providers,
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
await this.providerSnapshotManager.refreshSettingsSnapshot({
|
|
275
|
+
providers: msg.providers,
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
this.host.emit({
|
|
279
|
+
type: "refresh_providers_snapshot_response",
|
|
280
|
+
payload: {
|
|
281
|
+
acknowledged: true,
|
|
282
|
+
requestId: msg.requestId,
|
|
283
|
+
},
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
async handleProviderDiagnosticRequest(msg) {
|
|
287
|
+
try {
|
|
288
|
+
const { diagnostic } = await this.providerSnapshotManager.getProviderDiagnostic(msg.provider);
|
|
289
|
+
this.host.emit({
|
|
290
|
+
type: "provider_diagnostic_response",
|
|
291
|
+
payload: {
|
|
292
|
+
provider: msg.provider,
|
|
293
|
+
diagnostic,
|
|
294
|
+
requestId: msg.requestId,
|
|
295
|
+
},
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
catch (error) {
|
|
299
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
300
|
+
this.logger.error({ err, provider: msg.provider }, `Failed to get provider diagnostic for ${msg.provider}`);
|
|
301
|
+
this.host.emit({
|
|
302
|
+
type: "rpc_error",
|
|
303
|
+
payload: {
|
|
304
|
+
requestId: msg.requestId,
|
|
305
|
+
requestType: msg.type,
|
|
306
|
+
error: `Failed to get provider diagnostic: ${err.message}`,
|
|
307
|
+
code: "provider_diagnostic_failed",
|
|
308
|
+
},
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
async handleProviderUsageListRequest(msg) {
|
|
313
|
+
try {
|
|
314
|
+
const usage = await this.providerUsageService.listUsage();
|
|
315
|
+
this.host.emit({
|
|
316
|
+
type: "provider.usage.list.response",
|
|
317
|
+
payload: {
|
|
318
|
+
requestId: msg.requestId,
|
|
319
|
+
fetchedAt: usage.fetchedAt,
|
|
320
|
+
providers: usage.providers,
|
|
321
|
+
},
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
catch (error) {
|
|
325
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
326
|
+
this.logger.error({ err }, "Failed to list provider usage");
|
|
327
|
+
this.host.emit({
|
|
328
|
+
type: "rpc_error",
|
|
329
|
+
payload: {
|
|
330
|
+
requestId: msg.requestId,
|
|
331
|
+
requestType: msg.type,
|
|
332
|
+
error: `Failed to list provider usage: ${err.message}`,
|
|
333
|
+
code: "provider_usage_list_failed",
|
|
334
|
+
},
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
//# sourceMappingURL=provider-catalog-session.js.map
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import type pino from "pino";
|
|
2
|
+
import type { SessionInboundMessage, SessionOutboundMessage } from "../../messages.js";
|
|
3
|
+
import type { SpeechToTextProvider, TextToSpeechProvider } from "../../speech/speech-provider.js";
|
|
4
|
+
import type { TurnDetectionProvider } from "../../speech/turn-detection-provider.js";
|
|
5
|
+
import type { VoiceCallerContext, VoiceSpeakHandler } from "../../voice-types.js";
|
|
6
|
+
import type { ManagedAgent } from "../../agent/agent-manager.js";
|
|
7
|
+
import type { AgentSessionConfig } from "../../agent/agent-sdk-types.js";
|
|
8
|
+
import { type Resolvable } from "../../speech/provider-resolver.js";
|
|
9
|
+
import type { SpeechReadinessSnapshot } from "../../speech/speech-runtime.js";
|
|
10
|
+
/**
|
|
11
|
+
* The agent-facing operations VoiceSession needs from the session that owns it.
|
|
12
|
+
* VoiceSession owns all voice/audio state; it reaches back through this narrow
|
|
13
|
+
* seam only to deliver transcripts to the agent, drive TTS playback, and
|
|
14
|
+
* abort/inspect the active agent run.
|
|
15
|
+
*/
|
|
16
|
+
export interface VoiceSessionHost {
|
|
17
|
+
emit(msg: SessionOutboundMessage): void;
|
|
18
|
+
loadAgent(agentId: string): Promise<ManagedAgent>;
|
|
19
|
+
reloadAgentSession(agentId: string, overrides: Partial<AgentSessionConfig>): Promise<ManagedAgent>;
|
|
20
|
+
sendSpokenInput(agentId: string, text: string): Promise<void>;
|
|
21
|
+
interruptAgentIfRunning(agentId: string): Promise<void>;
|
|
22
|
+
hasActiveAgentRun(agentId: string | null): boolean;
|
|
23
|
+
}
|
|
24
|
+
export interface VoiceSessionOptions {
|
|
25
|
+
host: VoiceSessionHost;
|
|
26
|
+
logger: pino.Logger;
|
|
27
|
+
sessionId: string;
|
|
28
|
+
sttLanguage?: string;
|
|
29
|
+
tts: Resolvable<TextToSpeechProvider | null>;
|
|
30
|
+
stt: Resolvable<SpeechToTextProvider | null>;
|
|
31
|
+
voice?: {
|
|
32
|
+
turnDetection?: Resolvable<TurnDetectionProvider | null>;
|
|
33
|
+
};
|
|
34
|
+
voiceBridge?: {
|
|
35
|
+
registerVoiceSpeakHandler?: (agentId: string, handler: VoiceSpeakHandler) => void;
|
|
36
|
+
unregisterVoiceSpeakHandler?: (agentId: string) => void;
|
|
37
|
+
registerVoiceCallerContext?: (agentId: string, context: VoiceCallerContext) => void;
|
|
38
|
+
unregisterVoiceCallerContext?: (agentId: string) => void;
|
|
39
|
+
};
|
|
40
|
+
dictation?: {
|
|
41
|
+
finalTimeoutMs?: number;
|
|
42
|
+
stt?: Resolvable<SpeechToTextProvider | null>;
|
|
43
|
+
sttLanguage?: string;
|
|
44
|
+
getSpeechReadiness?: () => SpeechReadinessSnapshot;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Owns the voice half of a client session: speech-to-text/text-to-speech
|
|
49
|
+
* managers, dictation streaming, the barge-in audio-buffering state machine,
|
|
50
|
+
* voice-turn detection, and the MCP voice bridge. The session delegates the
|
|
51
|
+
* voice/dictation/abort message types here and otherwise knows nothing about
|
|
52
|
+
* audio buffering or processing phases.
|
|
53
|
+
*/
|
|
54
|
+
export declare class VoiceSession {
|
|
55
|
+
private readonly host;
|
|
56
|
+
private readonly sessionLogger;
|
|
57
|
+
private readonly sessionId;
|
|
58
|
+
private readonly sttLanguage;
|
|
59
|
+
private abortController;
|
|
60
|
+
private processingPhase;
|
|
61
|
+
private isVoiceMode;
|
|
62
|
+
private speechInProgress;
|
|
63
|
+
private readonly dictationStreamManager;
|
|
64
|
+
private readonly resolveVoiceTurnDetection;
|
|
65
|
+
private voiceTurnController;
|
|
66
|
+
private voiceInputChunkCount;
|
|
67
|
+
private voiceInputBytes;
|
|
68
|
+
private voiceInputWindowStartedAt;
|
|
69
|
+
private pendingAudioSegments;
|
|
70
|
+
private bufferTimeout;
|
|
71
|
+
private audioBuffer;
|
|
72
|
+
private readonly ttsDebugStreams;
|
|
73
|
+
private readonly ttsManager;
|
|
74
|
+
private readonly sttManager;
|
|
75
|
+
private readonly registerVoiceSpeakHandler?;
|
|
76
|
+
private readonly unregisterVoiceSpeakHandler?;
|
|
77
|
+
private readonly registerVoiceCallerContext?;
|
|
78
|
+
private readonly unregisterVoiceCallerContext?;
|
|
79
|
+
private readonly getSpeechReadiness?;
|
|
80
|
+
private voiceModeAgentId;
|
|
81
|
+
private voiceModeBaseConfig;
|
|
82
|
+
constructor(options: VoiceSessionOptions);
|
|
83
|
+
isActiveForAgent(agentId: string): boolean;
|
|
84
|
+
handleDictationChunk(params: {
|
|
85
|
+
dictationId: string;
|
|
86
|
+
seq: number;
|
|
87
|
+
audioBase64: string;
|
|
88
|
+
format: string;
|
|
89
|
+
}): Promise<void>;
|
|
90
|
+
handleDictationFinish(dictationId: string, finalSeq: number): Promise<void>;
|
|
91
|
+
handleDictationCancel(dictationId: string): void;
|
|
92
|
+
handleDictationStreamStart(msg: Extract<SessionInboundMessage, {
|
|
93
|
+
type: "dictation_stream_start";
|
|
94
|
+
}>): Promise<void>;
|
|
95
|
+
private toVoiceFeatureUnavailableContext;
|
|
96
|
+
private resolveModeReadinessState;
|
|
97
|
+
private getVoiceFeatureUnavailableResponseMetadata;
|
|
98
|
+
private resolveVoiceFeatureUnavailableContext;
|
|
99
|
+
/**
|
|
100
|
+
* Handle voice mode toggle
|
|
101
|
+
*/
|
|
102
|
+
handleSetVoiceMode(enabled: boolean, agentId?: string, requestId?: string): Promise<void>;
|
|
103
|
+
private parseVoiceTargetAgentId;
|
|
104
|
+
private enableVoiceModeForAgent;
|
|
105
|
+
private disableVoiceModeForActiveAgent;
|
|
106
|
+
private handleDictationManagerMessage;
|
|
107
|
+
private startVoiceTurnController;
|
|
108
|
+
private stopVoiceTurnController;
|
|
109
|
+
private handleVoiceSpeechStopped;
|
|
110
|
+
private ensureAudioBufferForFormat;
|
|
111
|
+
private forwardAudioChunkToVoiceTurn;
|
|
112
|
+
handleAudioChunk(msg: Extract<SessionInboundMessage, {
|
|
113
|
+
type: "voice_audio_chunk";
|
|
114
|
+
}>): Promise<void>;
|
|
115
|
+
private finalizeBufferedAudio;
|
|
116
|
+
private processCompletedAudio;
|
|
117
|
+
private flushPendingAudioSegments;
|
|
118
|
+
/**
|
|
119
|
+
* Process audio through STT and then LLM
|
|
120
|
+
*/
|
|
121
|
+
private processAudio;
|
|
122
|
+
private handleTranscriptionResultPayload;
|
|
123
|
+
private registerVoiceBridgeForAgent;
|
|
124
|
+
/**
|
|
125
|
+
* Handle abort request from client
|
|
126
|
+
*/
|
|
127
|
+
handleAbort(): Promise<void>;
|
|
128
|
+
/**
|
|
129
|
+
* Handle audio playback confirmation from client
|
|
130
|
+
*/
|
|
131
|
+
handleAudioPlayed(id: string): void;
|
|
132
|
+
/**
|
|
133
|
+
* Mark speech detection start and abort any active playback/agent run.
|
|
134
|
+
*/
|
|
135
|
+
private handleVoiceSpeechStart;
|
|
136
|
+
/**
|
|
137
|
+
* Clear speech-in-progress flag once the user turn has completed
|
|
138
|
+
*/
|
|
139
|
+
private clearSpeechInProgress;
|
|
140
|
+
/**
|
|
141
|
+
* Create new AbortController, aborting the previous one
|
|
142
|
+
*/
|
|
143
|
+
private createAbortController;
|
|
144
|
+
/**
|
|
145
|
+
* Set the processing phase
|
|
146
|
+
*/
|
|
147
|
+
private setPhase;
|
|
148
|
+
/**
|
|
149
|
+
* Set timeout to process buffered audio segments
|
|
150
|
+
*/
|
|
151
|
+
private setBufferTimeout;
|
|
152
|
+
/**
|
|
153
|
+
* Clear buffer timeout
|
|
154
|
+
*/
|
|
155
|
+
private clearBufferTimeout;
|
|
156
|
+
/**
|
|
157
|
+
* Emit a message to the client. Captures TTS audio_output frames for optional
|
|
158
|
+
* debug persistence before forwarding to the session emitter.
|
|
159
|
+
*/
|
|
160
|
+
private emit;
|
|
161
|
+
/**
|
|
162
|
+
* Tear down all voice resources.
|
|
163
|
+
*/
|
|
164
|
+
cleanup(): Promise<void>;
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=voice-session.d.ts.map
|