@prestyj/voice 4.3.191
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/LICENSE +21 -0
- package/README.md +79 -0
- package/dist/bridges/ezboss.cjs +96 -0
- package/dist/bridges/ezboss.cjs.map +1 -0
- package/dist/bridges/ezboss.d.cts +13 -0
- package/dist/bridges/ezboss.d.ts +13 -0
- package/dist/bridges/ezboss.js +70 -0
- package/dist/bridges/ezboss.js.map +1 -0
- package/dist/bridges/ezcoder-rpc.cjs +128 -0
- package/dist/bridges/ezcoder-rpc.cjs.map +1 -0
- package/dist/bridges/ezcoder-rpc.d.cts +18 -0
- package/dist/bridges/ezcoder-rpc.d.ts +18 -0
- package/dist/bridges/ezcoder-rpc.js +101 -0
- package/dist/bridges/ezcoder-rpc.js.map +1 -0
- package/dist/chunk-VJ6MPV2Z.js +225 -0
- package/dist/chunk-VJ6MPV2Z.js.map +1 -0
- package/dist/chunk-YLNKQ7CC.js +234 -0
- package/dist/chunk-YLNKQ7CC.js.map +1 -0
- package/dist/index.cjs +357 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +90 -0
- package/dist/index.d.ts +90 -0
- package/dist/index.js +109 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/openai-codex-realtime.cjs +362 -0
- package/dist/providers/openai-codex-realtime.cjs.map +1 -0
- package/dist/providers/openai-codex-realtime.d.cts +15 -0
- package/dist/providers/openai-codex-realtime.d.ts +15 -0
- package/dist/providers/openai-codex-realtime.js +31 -0
- package/dist/providers/openai-codex-realtime.js.map +1 -0
- package/dist/providers/openai-realtime.cjs +342 -0
- package/dist/providers/openai-realtime.cjs.map +1 -0
- package/dist/providers/openai-realtime.d.cts +34 -0
- package/dist/providers/openai-realtime.d.ts +34 -0
- package/dist/providers/openai-realtime.js +12 -0
- package/dist/providers/openai-realtime.js.map +1 -0
- package/dist/types-Dc4Q3Z6X.d.cts +257 -0
- package/dist/types-Dc4Q3Z6X.d.ts +257 -0
- package/package.json +63 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createVoiceSession,
|
|
3
|
+
normalizeVoiceProviderError,
|
|
4
|
+
voiceToolToRealtimeFunctionTool
|
|
5
|
+
} from "./chunk-YLNKQ7CC.js";
|
|
6
|
+
|
|
7
|
+
// src/providers/openai-realtime.ts
|
|
8
|
+
function createOpenAIRealtimeProvider(options = {}) {
|
|
9
|
+
return {
|
|
10
|
+
name: options.providerName ?? "openai-realtime",
|
|
11
|
+
async connect(connectOptions) {
|
|
12
|
+
if (!connectOptions.transport) {
|
|
13
|
+
throw new Error("OpenAI Realtime provider requires an injected VoiceTransport");
|
|
14
|
+
}
|
|
15
|
+
const sessionConfig = toOpenAISessionConfig(connectOptions.session);
|
|
16
|
+
await connectOptions.transport.connect(connectOptions);
|
|
17
|
+
return createVoiceSession({
|
|
18
|
+
id: createSessionId(connectOptions.session),
|
|
19
|
+
provider: options.providerName ?? "openai-realtime",
|
|
20
|
+
transport: createNormalizingTransport(connectOptions.transport),
|
|
21
|
+
metadata: createMetadata(connectOptions.session),
|
|
22
|
+
onSendToolResult: async (result, signal) => {
|
|
23
|
+
await connectOptions.transport?.send(
|
|
24
|
+
{ type: "tool_result", result: toOpenAIToolResult(result) },
|
|
25
|
+
signal
|
|
26
|
+
);
|
|
27
|
+
},
|
|
28
|
+
onUpdateConfig: async (config, signal) => {
|
|
29
|
+
await connectOptions.transport?.send(
|
|
30
|
+
{
|
|
31
|
+
type: "config",
|
|
32
|
+
config: { ...config, session: sessionConfig }
|
|
33
|
+
},
|
|
34
|
+
signal
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function toOpenAISessionConfig(config) {
|
|
42
|
+
const audio = {};
|
|
43
|
+
if (config.voice) {
|
|
44
|
+
audio.output = { voice: config.voice };
|
|
45
|
+
}
|
|
46
|
+
if (config.inputAudioFormat) {
|
|
47
|
+
audio.input = { format: config.inputAudioFormat };
|
|
48
|
+
}
|
|
49
|
+
if (config.outputAudioFormat) {
|
|
50
|
+
audio.output = {
|
|
51
|
+
...audio.output,
|
|
52
|
+
format: config.outputAudioFormat
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
if (config.turnDetection !== void 0) {
|
|
56
|
+
audio.input = {
|
|
57
|
+
...audio.input,
|
|
58
|
+
turn_detection: config.turnDetection
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
type: "realtime",
|
|
63
|
+
model: config.model,
|
|
64
|
+
...config.instructions ? { instructions: config.instructions } : {},
|
|
65
|
+
...Object.keys(audio).length > 0 ? { audio } : {},
|
|
66
|
+
...config.tools && config.tools.length > 0 ? { tools: config.tools.map((tool) => voiceToolToRealtimeFunctionTool(tool)) } : {},
|
|
67
|
+
...config.metadata ? { metadata: config.metadata } : {}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function normalizeOpenAIRealtimeEvent(event) {
|
|
71
|
+
if (!isJsonObject(event)) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
const type = typeof event.type === "string" ? event.type : "";
|
|
75
|
+
switch (type) {
|
|
76
|
+
case "session.created":
|
|
77
|
+
case "session.updated":
|
|
78
|
+
return {
|
|
79
|
+
type: "session_started",
|
|
80
|
+
session: normalizeSessionMetadata(event.session)
|
|
81
|
+
};
|
|
82
|
+
case "conversation.item.input_audio_transcription.delta":
|
|
83
|
+
return {
|
|
84
|
+
type: "input_transcript_delta",
|
|
85
|
+
delta: stringValue(event.delta),
|
|
86
|
+
itemId: stringOrUndefined(event.item_id)
|
|
87
|
+
};
|
|
88
|
+
case "conversation.item.input_audio_transcription.completed":
|
|
89
|
+
return {
|
|
90
|
+
type: "input_transcript_done",
|
|
91
|
+
text: stringValue(event.transcript),
|
|
92
|
+
itemId: stringOrUndefined(event.item_id)
|
|
93
|
+
};
|
|
94
|
+
case "response.output_audio_transcript.delta":
|
|
95
|
+
return {
|
|
96
|
+
type: "output_text_delta",
|
|
97
|
+
delta: stringValue(event.delta),
|
|
98
|
+
itemId: stringOrUndefined(event.item_id)
|
|
99
|
+
};
|
|
100
|
+
case "response.output_audio_transcript.done":
|
|
101
|
+
return {
|
|
102
|
+
type: "output_text_done",
|
|
103
|
+
text: stringValue(event.transcript),
|
|
104
|
+
itemId: stringOrUndefined(event.item_id)
|
|
105
|
+
};
|
|
106
|
+
case "response.output_text.delta":
|
|
107
|
+
case "response.text.delta":
|
|
108
|
+
return {
|
|
109
|
+
type: "output_text_delta",
|
|
110
|
+
delta: stringValue(event.delta),
|
|
111
|
+
itemId: stringOrUndefined(event.item_id)
|
|
112
|
+
};
|
|
113
|
+
case "response.output_text.done":
|
|
114
|
+
case "response.text.done":
|
|
115
|
+
return {
|
|
116
|
+
type: "output_text_done",
|
|
117
|
+
text: stringValue(event.text),
|
|
118
|
+
itemId: stringOrUndefined(event.item_id)
|
|
119
|
+
};
|
|
120
|
+
case "response.output_audio.delta":
|
|
121
|
+
case "response.audio.delta":
|
|
122
|
+
return {
|
|
123
|
+
type: "output_audio_delta",
|
|
124
|
+
chunk: { data: stringValue(event.delta), format: "base64" },
|
|
125
|
+
itemId: stringOrUndefined(event.item_id)
|
|
126
|
+
};
|
|
127
|
+
case "response.output_audio.done":
|
|
128
|
+
case "response.audio.done":
|
|
129
|
+
return { type: "output_audio_done", itemId: stringOrUndefined(event.item_id) };
|
|
130
|
+
case "response.function_call_arguments.done":
|
|
131
|
+
return { type: "tool_call", call: normalizeToolCall(event) };
|
|
132
|
+
case "error":
|
|
133
|
+
return {
|
|
134
|
+
type: "error",
|
|
135
|
+
error: normalizeVoiceProviderError(event.error ?? event),
|
|
136
|
+
recoverable: true
|
|
137
|
+
};
|
|
138
|
+
default:
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function createNormalizingTransport(transport) {
|
|
143
|
+
return {
|
|
144
|
+
kind: transport.kind,
|
|
145
|
+
connect: transport.connect.bind(transport),
|
|
146
|
+
send: transport.send.bind(transport),
|
|
147
|
+
close: transport.close.bind(transport),
|
|
148
|
+
onEvent(handler) {
|
|
149
|
+
return transport.onEvent((event) => {
|
|
150
|
+
handler(normalizeTransportEvent(event));
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
function normalizeTransportEvent(event) {
|
|
156
|
+
if (event.type !== "raw") {
|
|
157
|
+
return event;
|
|
158
|
+
}
|
|
159
|
+
const normalized = normalizeOpenAIRealtimeEvent(event.data);
|
|
160
|
+
return normalized ?? event;
|
|
161
|
+
}
|
|
162
|
+
function normalizeToolCall(event) {
|
|
163
|
+
const args = parseJsonObject(event.arguments);
|
|
164
|
+
return {
|
|
165
|
+
id: stringValue(event.call_id ?? event.item_id ?? event.event_id),
|
|
166
|
+
name: stringValue(event.name),
|
|
167
|
+
args,
|
|
168
|
+
providerCallId: stringOrUndefined(event.call_id),
|
|
169
|
+
raw: event
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
function toOpenAIToolResult(result) {
|
|
173
|
+
return result;
|
|
174
|
+
}
|
|
175
|
+
function createMetadata(config) {
|
|
176
|
+
return {
|
|
177
|
+
provider: "openai-realtime",
|
|
178
|
+
model: config.model,
|
|
179
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function createSessionId(config) {
|
|
183
|
+
const model = config.model.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
184
|
+
return `openai_${model}_${Date.now()}`;
|
|
185
|
+
}
|
|
186
|
+
function normalizeSessionMetadata(value) {
|
|
187
|
+
if (!isJsonObject(value)) {
|
|
188
|
+
return { provider: "openai-realtime" };
|
|
189
|
+
}
|
|
190
|
+
return {
|
|
191
|
+
sessionId: stringOrUndefined(value.id),
|
|
192
|
+
provider: "openai-realtime",
|
|
193
|
+
model: stringOrUndefined(value.model)
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
function parseJsonObject(value) {
|
|
197
|
+
if (isJsonObject(value)) {
|
|
198
|
+
return value;
|
|
199
|
+
}
|
|
200
|
+
if (typeof value !== "string") {
|
|
201
|
+
return {};
|
|
202
|
+
}
|
|
203
|
+
try {
|
|
204
|
+
const parsed = JSON.parse(value);
|
|
205
|
+
return isJsonObject(parsed) ? parsed : {};
|
|
206
|
+
} catch {
|
|
207
|
+
return {};
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
function stringValue(value) {
|
|
211
|
+
return typeof value === "string" ? value : "";
|
|
212
|
+
}
|
|
213
|
+
function stringOrUndefined(value) {
|
|
214
|
+
return typeof value === "string" ? value : void 0;
|
|
215
|
+
}
|
|
216
|
+
function isJsonObject(value) {
|
|
217
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export {
|
|
221
|
+
createOpenAIRealtimeProvider,
|
|
222
|
+
toOpenAISessionConfig,
|
|
223
|
+
normalizeOpenAIRealtimeEvent
|
|
224
|
+
};
|
|
225
|
+
//# sourceMappingURL=chunk-VJ6MPV2Z.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/providers/openai-realtime.ts"],"sourcesContent":["import { createVoiceSession, normalizeVoiceProviderError } from \"../session.js\";\nimport { voiceToolToRealtimeFunctionTool } from \"../tools.js\";\nimport type {\n JsonObject,\n RealtimeFunctionToolDefinition,\n VoiceEvent,\n VoiceProvider,\n VoiceProviderConnectOptions,\n VoiceSession,\n VoiceSessionConfig,\n VoiceSessionMetadata,\n VoiceToolCall,\n VoiceToolResult,\n VoiceTransport,\n VoiceTransportEvent,\n} from \"../types.js\";\n\nexport interface OpenAIRealtimeProviderOptions {\n readonly baseUrl?: string;\n readonly providerName?: string;\n}\n\nexport interface OpenAIRealtimeSessionConfig {\n readonly type: \"realtime\";\n readonly model: string;\n readonly instructions?: string;\n readonly audio?: JsonObject;\n readonly tools?: readonly RealtimeFunctionToolDefinition[];\n readonly metadata?: Readonly<Record<string, string>>;\n}\n\nexport interface OpenAIClientSecretRequest {\n readonly session: OpenAIRealtimeSessionConfig;\n}\n\nexport interface OpenAIRealtimeCallRequest {\n readonly sdp: string;\n readonly session: OpenAIRealtimeSessionConfig;\n}\n\nexport interface OpenAIRealtimeHttpClient {\n createClientSecret(\n request: OpenAIClientSecretRequest,\n options: { readonly signal?: AbortSignal },\n ): Promise<JsonObject>;\n createCall(\n request: OpenAIRealtimeCallRequest,\n options: { readonly signal?: AbortSignal },\n ): Promise<string>;\n}\n\nexport function createOpenAIRealtimeProvider(\n options: OpenAIRealtimeProviderOptions = {},\n): VoiceProvider {\n return {\n name: options.providerName ?? \"openai-realtime\",\n async connect(connectOptions: VoiceProviderConnectOptions): Promise<VoiceSession> {\n if (!connectOptions.transport) {\n throw new Error(\"OpenAI Realtime provider requires an injected VoiceTransport\");\n }\n const sessionConfig = toOpenAISessionConfig(connectOptions.session);\n await connectOptions.transport.connect(connectOptions);\n return createVoiceSession({\n id: createSessionId(connectOptions.session),\n provider: options.providerName ?? \"openai-realtime\",\n transport: createNormalizingTransport(connectOptions.transport),\n metadata: createMetadata(connectOptions.session),\n onSendToolResult: async (result, signal) => {\n await connectOptions.transport?.send(\n { type: \"tool_result\", result: toOpenAIToolResult(result) },\n signal,\n );\n },\n onUpdateConfig: async (config, signal) => {\n await connectOptions.transport?.send(\n {\n type: \"config\",\n config: { ...config, session: sessionConfig } as Partial<VoiceSessionConfig>,\n },\n signal,\n );\n },\n });\n },\n };\n}\n\nexport function toOpenAISessionConfig(config: VoiceSessionConfig): OpenAIRealtimeSessionConfig {\n const audio: JsonObject = {};\n if (config.voice) {\n audio.output = { voice: config.voice };\n }\n if (config.inputAudioFormat) {\n audio.input = { format: config.inputAudioFormat };\n }\n if (config.outputAudioFormat) {\n audio.output = {\n ...(audio.output as JsonObject | undefined),\n format: config.outputAudioFormat,\n };\n }\n if (config.turnDetection !== undefined) {\n audio.input = {\n ...(audio.input as JsonObject | undefined),\n turn_detection: config.turnDetection,\n };\n }\n\n return {\n type: \"realtime\",\n model: config.model,\n ...(config.instructions ? { instructions: config.instructions } : {}),\n ...(Object.keys(audio).length > 0 ? { audio } : {}),\n ...(config.tools && config.tools.length > 0\n ? { tools: config.tools.map((tool) => voiceToolToRealtimeFunctionTool(tool)) }\n : {}),\n ...(config.metadata ? { metadata: config.metadata } : {}),\n };\n}\n\nexport function normalizeOpenAIRealtimeEvent(event: unknown): VoiceEvent | null {\n if (!isJsonObject(event)) {\n return null;\n }\n const type = typeof event.type === \"string\" ? event.type : \"\";\n switch (type) {\n case \"session.created\":\n case \"session.updated\":\n return {\n type: \"session_started\",\n session: normalizeSessionMetadata(event.session),\n };\n case \"conversation.item.input_audio_transcription.delta\":\n return {\n type: \"input_transcript_delta\",\n delta: stringValue(event.delta),\n itemId: stringOrUndefined(event.item_id),\n };\n case \"conversation.item.input_audio_transcription.completed\":\n return {\n type: \"input_transcript_done\",\n text: stringValue(event.transcript),\n itemId: stringOrUndefined(event.item_id),\n };\n case \"response.output_audio_transcript.delta\":\n return {\n type: \"output_text_delta\",\n delta: stringValue(event.delta),\n itemId: stringOrUndefined(event.item_id),\n };\n case \"response.output_audio_transcript.done\":\n return {\n type: \"output_text_done\",\n text: stringValue(event.transcript),\n itemId: stringOrUndefined(event.item_id),\n };\n case \"response.output_text.delta\":\n case \"response.text.delta\":\n return {\n type: \"output_text_delta\",\n delta: stringValue(event.delta),\n itemId: stringOrUndefined(event.item_id),\n };\n case \"response.output_text.done\":\n case \"response.text.done\":\n return {\n type: \"output_text_done\",\n text: stringValue(event.text),\n itemId: stringOrUndefined(event.item_id),\n };\n case \"response.output_audio.delta\":\n case \"response.audio.delta\":\n return {\n type: \"output_audio_delta\",\n chunk: { data: stringValue(event.delta), format: \"base64\" },\n itemId: stringOrUndefined(event.item_id),\n };\n case \"response.output_audio.done\":\n case \"response.audio.done\":\n return { type: \"output_audio_done\", itemId: stringOrUndefined(event.item_id) };\n case \"response.function_call_arguments.done\":\n return { type: \"tool_call\", call: normalizeToolCall(event) };\n case \"error\":\n return {\n type: \"error\",\n error: normalizeVoiceProviderError(event.error ?? event),\n recoverable: true,\n };\n default:\n return null;\n }\n}\n\nfunction createNormalizingTransport(transport: VoiceTransport): VoiceTransport {\n return {\n kind: transport.kind,\n connect: transport.connect.bind(transport),\n send: transport.send.bind(transport),\n close: transport.close.bind(transport),\n onEvent(handler) {\n return transport.onEvent((event) => {\n handler(normalizeTransportEvent(event));\n });\n },\n };\n}\n\nfunction normalizeTransportEvent(event: VoiceTransportEvent): VoiceTransportEvent {\n if (event.type !== \"raw\") {\n return event;\n }\n const normalized = normalizeOpenAIRealtimeEvent(event.data);\n return normalized ?? event;\n}\n\nfunction normalizeToolCall(event: JsonObject): VoiceToolCall {\n const args = parseJsonObject(event.arguments);\n return {\n id: stringValue(event.call_id ?? event.item_id ?? event.event_id),\n name: stringValue(event.name),\n args,\n providerCallId: stringOrUndefined(event.call_id),\n raw: event,\n };\n}\n\nfunction toOpenAIToolResult(result: VoiceToolResult): VoiceToolResult {\n return result;\n}\n\nfunction createMetadata(config: VoiceSessionConfig): VoiceSessionMetadata {\n return {\n provider: \"openai-realtime\",\n model: config.model,\n createdAt: new Date().toISOString(),\n };\n}\n\nfunction createSessionId(config: VoiceSessionConfig): string {\n const model = config.model.replace(/[^a-zA-Z0-9_-]/g, \"_\");\n return `openai_${model}_${Date.now()}`;\n}\n\nfunction normalizeSessionMetadata(value: unknown): VoiceSessionMetadata {\n if (!isJsonObject(value)) {\n return { provider: \"openai-realtime\" };\n }\n return {\n sessionId: stringOrUndefined(value.id),\n provider: \"openai-realtime\",\n model: stringOrUndefined(value.model),\n };\n}\n\nfunction parseJsonObject(value: unknown): JsonObject {\n if (isJsonObject(value)) {\n return value;\n }\n if (typeof value !== \"string\") {\n return {};\n }\n try {\n const parsed: unknown = JSON.parse(value);\n return isJsonObject(parsed) ? parsed : {};\n } catch {\n return {};\n }\n}\n\nfunction stringValue(value: unknown): string {\n return typeof value === \"string\" ? value : \"\";\n}\n\nfunction stringOrUndefined(value: unknown): string | undefined {\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction isJsonObject(value: unknown): value is JsonObject {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
// src/session.ts
|
|
2
|
+
function createVoiceSession(options) {
|
|
3
|
+
return new VoiceSessionController(options);
|
|
4
|
+
}
|
|
5
|
+
function normalizeVoiceProviderError(error) {
|
|
6
|
+
if (error instanceof Error) {
|
|
7
|
+
return error;
|
|
8
|
+
}
|
|
9
|
+
if (typeof error === "string") {
|
|
10
|
+
return new Error(error);
|
|
11
|
+
}
|
|
12
|
+
return new Error("Voice provider error", { cause: error });
|
|
13
|
+
}
|
|
14
|
+
var VoiceSessionController = class {
|
|
15
|
+
id;
|
|
16
|
+
provider;
|
|
17
|
+
metadata;
|
|
18
|
+
#state = "connected";
|
|
19
|
+
#handlers = /* @__PURE__ */ new Set();
|
|
20
|
+
#unsubscribeTransport;
|
|
21
|
+
#options;
|
|
22
|
+
constructor(options) {
|
|
23
|
+
this.id = options.id;
|
|
24
|
+
this.provider = options.provider;
|
|
25
|
+
this.metadata = options.metadata ?? { sessionId: options.id, provider: options.provider };
|
|
26
|
+
this.#options = options;
|
|
27
|
+
this.#unsubscribeTransport = options.transport?.onEvent((event) => {
|
|
28
|
+
this.#handleTransportEvent(event);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
get state() {
|
|
32
|
+
return this.#state;
|
|
33
|
+
}
|
|
34
|
+
onEvent(handler) {
|
|
35
|
+
this.#handlers.add(handler);
|
|
36
|
+
return () => {
|
|
37
|
+
this.#handlers.delete(handler);
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
async sendAudio(chunk, signal) {
|
|
41
|
+
await this.#options.onSendAudio?.(chunk, signal);
|
|
42
|
+
await this.#options.transport?.send({ type: "audio", chunk }, signal);
|
|
43
|
+
}
|
|
44
|
+
async sendText(text, signal) {
|
|
45
|
+
await this.#options.onSendText?.(text, signal);
|
|
46
|
+
await this.#options.transport?.send({ type: "text", text }, signal);
|
|
47
|
+
}
|
|
48
|
+
async sendToolResult(result, signal) {
|
|
49
|
+
await this.#options.onSendToolResult?.(result, signal);
|
|
50
|
+
await this.#options.transport?.send({ type: "tool_result", result }, signal);
|
|
51
|
+
this.#emit({ type: "tool_result_sent", result });
|
|
52
|
+
}
|
|
53
|
+
async updateConfig(config, signal) {
|
|
54
|
+
await this.#options.onUpdateConfig?.(config, signal);
|
|
55
|
+
await this.#options.transport?.send({ type: "config", config }, signal);
|
|
56
|
+
}
|
|
57
|
+
async close(reason) {
|
|
58
|
+
if (this.#state === "closed" || this.#state === "closing") {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
this.#state = "closing";
|
|
62
|
+
await this.#options.onClose?.(reason);
|
|
63
|
+
await this.#options.transport?.close(reason);
|
|
64
|
+
this.#unsubscribeTransport?.();
|
|
65
|
+
this.#state = "closed";
|
|
66
|
+
this.#emit({ type: "closed", reason });
|
|
67
|
+
}
|
|
68
|
+
#handleTransportEvent(event) {
|
|
69
|
+
if (event.type === "raw") {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (event.type === "closed") {
|
|
73
|
+
this.#state = "closed";
|
|
74
|
+
}
|
|
75
|
+
this.#emit(event);
|
|
76
|
+
}
|
|
77
|
+
#emit(event) {
|
|
78
|
+
const handlers = [...this.#handlers];
|
|
79
|
+
for (const handler of handlers) {
|
|
80
|
+
handler(event);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// src/tools.ts
|
|
86
|
+
import { z } from "zod";
|
|
87
|
+
function ggAiToolToRealtimeFunctionTool(tool) {
|
|
88
|
+
return {
|
|
89
|
+
type: "function",
|
|
90
|
+
name: tool.name,
|
|
91
|
+
description: tool.description,
|
|
92
|
+
parameters: tool.rawInputSchema ?? zodToJsonSchemaObject(tool.parameters)
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function voiceToolToRealtimeFunctionTool(tool) {
|
|
96
|
+
return {
|
|
97
|
+
type: "function",
|
|
98
|
+
name: tool.name,
|
|
99
|
+
description: tool.description,
|
|
100
|
+
parameters: tool.parameters
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function ggAiToolToVoiceTool(tool) {
|
|
104
|
+
return {
|
|
105
|
+
name: tool.name,
|
|
106
|
+
description: tool.description,
|
|
107
|
+
parameters: tool.rawInputSchema ?? zodToJsonSchemaObject(tool.parameters)
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
function agentToolToVoiceTool(tool) {
|
|
111
|
+
return {
|
|
112
|
+
name: tool.name,
|
|
113
|
+
description: tool.description,
|
|
114
|
+
parameters: tool.rawInputSchema ?? zodToJsonSchemaObject(tool.parameters),
|
|
115
|
+
async execute(args, context) {
|
|
116
|
+
const parsed = tool.parameters.safeParse(args);
|
|
117
|
+
if (!parsed.success) {
|
|
118
|
+
return {
|
|
119
|
+
error: "Invalid tool arguments",
|
|
120
|
+
issues: parsed.error.issues
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
const agentContext = {
|
|
124
|
+
signal: context.signal,
|
|
125
|
+
toolCallId: context.toolCallId,
|
|
126
|
+
onUpdate: context.onUpdate
|
|
127
|
+
};
|
|
128
|
+
const result = await tool.execute(parsed.data, agentContext);
|
|
129
|
+
return normalizeAgentToolResult(result);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
async function executeVoiceToolCall(options) {
|
|
134
|
+
const tool = options.tools.find((candidate) => candidate.name === options.call.name);
|
|
135
|
+
if (!tool) {
|
|
136
|
+
return createErrorResult(options.call, {
|
|
137
|
+
type: "tool_not_found",
|
|
138
|
+
message: `Tool not found: ${options.call.name}`
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
const confirmation = await resolveConfirmation(tool, options.call, options.confirmation);
|
|
142
|
+
if (!confirmation.approved) {
|
|
143
|
+
return createErrorResult(options.call, {
|
|
144
|
+
type: "tool_confirmation_denied",
|
|
145
|
+
message: confirmation.reason
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
if (!tool.execute) {
|
|
149
|
+
return createErrorResult(options.call, {
|
|
150
|
+
type: "tool_execution_failed",
|
|
151
|
+
message: `Tool has no executor: ${tool.name}`
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
try {
|
|
155
|
+
const abortController = new AbortController();
|
|
156
|
+
const signal = options.signal ?? abortController.signal;
|
|
157
|
+
const content = await tool.execute(options.call.args, {
|
|
158
|
+
signal,
|
|
159
|
+
toolCallId: options.call.id,
|
|
160
|
+
confirmation: options.confirmation,
|
|
161
|
+
onUpdate: options.onUpdate
|
|
162
|
+
});
|
|
163
|
+
return {
|
|
164
|
+
toolCallId: options.call.id,
|
|
165
|
+
name: options.call.name,
|
|
166
|
+
content
|
|
167
|
+
};
|
|
168
|
+
} catch (error) {
|
|
169
|
+
return createErrorResult(options.call, {
|
|
170
|
+
type: "tool_execution_failed",
|
|
171
|
+
message: error instanceof Error ? error.message : "Tool execution failed",
|
|
172
|
+
cause: error
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
function zodToJsonSchemaObject(schema) {
|
|
177
|
+
const jsonSchema = z.toJSONSchema(schema);
|
|
178
|
+
const { $schema: _schema, ...rest } = jsonSchema;
|
|
179
|
+
return rest;
|
|
180
|
+
}
|
|
181
|
+
function normalizeAgentToolResult(result) {
|
|
182
|
+
if (typeof result === "string") {
|
|
183
|
+
return result;
|
|
184
|
+
}
|
|
185
|
+
if (typeof result.content === "string") {
|
|
186
|
+
if (result.details === void 0) {
|
|
187
|
+
return result.content;
|
|
188
|
+
}
|
|
189
|
+
return { content: result.content, details: result.details };
|
|
190
|
+
}
|
|
191
|
+
return { content: result.content, details: result.details };
|
|
192
|
+
}
|
|
193
|
+
async function resolveConfirmation(tool, call, confirmation) {
|
|
194
|
+
const policy = tool.confirmation ?? "never";
|
|
195
|
+
if (policy === "never") {
|
|
196
|
+
return { approved: true };
|
|
197
|
+
}
|
|
198
|
+
if (policy === "destructive" && !tool.destructive) {
|
|
199
|
+
return { approved: true };
|
|
200
|
+
}
|
|
201
|
+
if (typeof policy === "function") {
|
|
202
|
+
return policy({ call, tool });
|
|
203
|
+
}
|
|
204
|
+
if (!confirmation) {
|
|
205
|
+
return {
|
|
206
|
+
approved: false,
|
|
207
|
+
reason: `Tool requires confirmation: ${tool.name}`
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
return confirmation({ call, tool });
|
|
211
|
+
}
|
|
212
|
+
function createErrorResult(call, error) {
|
|
213
|
+
const content = {
|
|
214
|
+
error: error.message,
|
|
215
|
+
type: error.type
|
|
216
|
+
};
|
|
217
|
+
return {
|
|
218
|
+
toolCallId: call.id,
|
|
219
|
+
name: call.name,
|
|
220
|
+
content,
|
|
221
|
+
isError: true
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export {
|
|
226
|
+
createVoiceSession,
|
|
227
|
+
normalizeVoiceProviderError,
|
|
228
|
+
ggAiToolToRealtimeFunctionTool,
|
|
229
|
+
voiceToolToRealtimeFunctionTool,
|
|
230
|
+
ggAiToolToVoiceTool,
|
|
231
|
+
agentToolToVoiceTool,
|
|
232
|
+
executeVoiceToolCall
|
|
233
|
+
};
|
|
234
|
+
//# sourceMappingURL=chunk-YLNKQ7CC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/session.ts","../src/tools.ts"],"sourcesContent":["import type {\n AudioInputChunk,\n JsonObject,\n VoiceConnectionState,\n VoiceEvent,\n VoiceEventHandler,\n VoiceSession,\n VoiceSessionConfig,\n VoiceSessionMetadata,\n VoiceToolResult,\n VoiceTransport,\n VoiceTransportEvent,\n} from \"./types.js\";\n\nexport interface VoiceSessionControllerOptions {\n readonly id: string;\n readonly provider: string;\n readonly transport?: VoiceTransport;\n readonly metadata?: VoiceSessionMetadata;\n readonly onSendToolResult?: (result: VoiceToolResult, signal?: AbortSignal) => Promise<void>;\n readonly onSendAudio?: (chunk: AudioInputChunk, signal?: AbortSignal) => Promise<void>;\n readonly onSendText?: (text: string, signal?: AbortSignal) => Promise<void>;\n readonly onUpdateConfig?: (\n config: Partial<VoiceSessionConfig>,\n signal?: AbortSignal,\n ) => Promise<void>;\n readonly onClose?: (reason?: string) => Promise<void>;\n}\n\nexport function createVoiceSession(options: VoiceSessionControllerOptions): VoiceSession {\n return new VoiceSessionController(options);\n}\n\nexport function normalizeVoiceProviderError(error: unknown): Error {\n if (error instanceof Error) {\n return error;\n }\n if (typeof error === \"string\") {\n return new Error(error);\n }\n return new Error(\"Voice provider error\", { cause: error });\n}\n\nclass VoiceSessionController implements VoiceSession {\n readonly id: string;\n readonly provider: string;\n readonly metadata: VoiceSessionMetadata;\n #state: VoiceConnectionState = \"connected\";\n #handlers = new Set<VoiceEventHandler>();\n #unsubscribeTransport?: () => void;\n #options: VoiceSessionControllerOptions;\n\n constructor(options: VoiceSessionControllerOptions) {\n this.id = options.id;\n this.provider = options.provider;\n this.metadata = options.metadata ?? { sessionId: options.id, provider: options.provider };\n this.#options = options;\n this.#unsubscribeTransport = options.transport?.onEvent((event) => {\n this.#handleTransportEvent(event);\n });\n }\n\n get state(): VoiceConnectionState {\n return this.#state;\n }\n\n onEvent(handler: VoiceEventHandler): () => void {\n this.#handlers.add(handler);\n return () => {\n this.#handlers.delete(handler);\n };\n }\n\n async sendAudio(chunk: AudioInputChunk, signal?: AbortSignal): Promise<void> {\n await this.#options.onSendAudio?.(chunk, signal);\n await this.#options.transport?.send({ type: \"audio\", chunk }, signal);\n }\n\n async sendText(text: string, signal?: AbortSignal): Promise<void> {\n await this.#options.onSendText?.(text, signal);\n await this.#options.transport?.send({ type: \"text\", text }, signal);\n }\n\n async sendToolResult(result: VoiceToolResult, signal?: AbortSignal): Promise<void> {\n await this.#options.onSendToolResult?.(result, signal);\n await this.#options.transport?.send({ type: \"tool_result\", result }, signal);\n this.#emit({ type: \"tool_result_sent\", result });\n }\n\n async updateConfig(config: Partial<VoiceSessionConfig>, signal?: AbortSignal): Promise<void> {\n await this.#options.onUpdateConfig?.(config, signal);\n await this.#options.transport?.send({ type: \"config\", config }, signal);\n }\n\n async close(reason?: string): Promise<void> {\n if (this.#state === \"closed\" || this.#state === \"closing\") {\n return;\n }\n this.#state = \"closing\";\n await this.#options.onClose?.(reason);\n await this.#options.transport?.close(reason);\n this.#unsubscribeTransport?.();\n this.#state = \"closed\";\n this.#emit({ type: \"closed\", reason });\n }\n\n #handleTransportEvent(event: VoiceTransportEvent): void {\n if (event.type === \"raw\") {\n return;\n }\n if (event.type === \"closed\") {\n this.#state = \"closed\";\n }\n this.#emit(event);\n }\n\n #emit(event: VoiceEvent): void {\n const handlers = [...this.#handlers];\n for (const handler of handlers) {\n handler(event);\n }\n }\n}\n\nexport function isJsonObject(value: unknown): value is JsonObject {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import type { AgentTool, ToolContext, ToolExecuteResult } from \"@prestyj/agent\";\nimport type { Tool } from \"@prestyj/ai\";\nimport { z } from \"zod\";\nimport type {\n JsonObject,\n RealtimeFunctionToolDefinition,\n ToolConfirmationDecision,\n VoiceTool,\n VoiceToolCall,\n VoiceToolContext,\n VoiceToolExecutionError,\n VoiceToolExecutionResult,\n VoiceToolResult,\n} from \"./types.js\";\n\ntype ZodParseResult = { success: true; data: unknown } | { success: false; error: z.ZodError };\n\nexport type VoiceToolSource = VoiceTool | AgentTool | Tool;\n\nexport interface ExecuteVoiceToolCallOptions {\n readonly tools: readonly VoiceTool[];\n readonly call: VoiceToolCall;\n readonly signal?: AbortSignal;\n readonly confirmation?: VoiceToolContext[\"confirmation\"];\n readonly onUpdate?: VoiceToolContext[\"onUpdate\"];\n}\n\nexport function ggAiToolToRealtimeFunctionTool(tool: Tool): RealtimeFunctionToolDefinition {\n return {\n type: \"function\",\n name: tool.name,\n description: tool.description,\n parameters: tool.rawInputSchema ?? zodToJsonSchemaObject(tool.parameters),\n };\n}\n\nexport function voiceToolToRealtimeFunctionTool(tool: VoiceTool): RealtimeFunctionToolDefinition {\n return {\n type: \"function\",\n name: tool.name,\n description: tool.description,\n parameters: tool.parameters,\n };\n}\n\nexport function ggAiToolToVoiceTool(tool: Tool): VoiceTool {\n return {\n name: tool.name,\n description: tool.description,\n parameters: tool.rawInputSchema ?? zodToJsonSchemaObject(tool.parameters),\n };\n}\n\nexport function agentToolToVoiceTool<T extends z.ZodType>(tool: AgentTool<T>): VoiceTool {\n return {\n name: tool.name,\n description: tool.description,\n parameters: tool.rawInputSchema ?? zodToJsonSchemaObject(tool.parameters),\n async execute(args, context): Promise<VoiceToolExecutionResult> {\n const parsed = tool.parameters.safeParse(args) as ZodParseResult;\n if (!parsed.success) {\n return {\n error: \"Invalid tool arguments\",\n issues: parsed.error.issues,\n };\n }\n\n const agentContext: ToolContext = {\n signal: context.signal,\n toolCallId: context.toolCallId,\n onUpdate: context.onUpdate,\n };\n const result = await tool.execute(parsed.data as z.infer<T>, agentContext);\n return normalizeAgentToolResult(result);\n },\n };\n}\n\nexport async function executeVoiceToolCall(\n options: ExecuteVoiceToolCallOptions,\n): Promise<VoiceToolResult> {\n const tool = options.tools.find((candidate) => candidate.name === options.call.name);\n if (!tool) {\n return createErrorResult(options.call, {\n type: \"tool_not_found\",\n message: `Tool not found: ${options.call.name}`,\n });\n }\n\n const confirmation = await resolveConfirmation(tool, options.call, options.confirmation);\n if (!confirmation.approved) {\n return createErrorResult(options.call, {\n type: \"tool_confirmation_denied\",\n message: confirmation.reason,\n });\n }\n\n if (!tool.execute) {\n return createErrorResult(options.call, {\n type: \"tool_execution_failed\",\n message: `Tool has no executor: ${tool.name}`,\n });\n }\n\n try {\n const abortController = new AbortController();\n const signal = options.signal ?? abortController.signal;\n const content = await tool.execute(options.call.args, {\n signal,\n toolCallId: options.call.id,\n confirmation: options.confirmation,\n onUpdate: options.onUpdate,\n });\n return {\n toolCallId: options.call.id,\n name: options.call.name,\n content,\n };\n } catch (error) {\n return createErrorResult(options.call, {\n type: \"tool_execution_failed\",\n message: error instanceof Error ? error.message : \"Tool execution failed\",\n cause: error,\n });\n }\n}\n\nfunction zodToJsonSchemaObject(schema: z.ZodType): JsonObject {\n const jsonSchema = z.toJSONSchema(schema) as JsonObject;\n const { $schema: _schema, ...rest } = jsonSchema;\n return rest;\n}\n\nfunction normalizeAgentToolResult(result: ToolExecuteResult): VoiceToolExecutionResult {\n if (typeof result === \"string\") {\n return result;\n }\n if (typeof result.content === \"string\") {\n if (result.details === undefined) {\n return result.content;\n }\n return { content: result.content, details: result.details };\n }\n return { content: result.content, details: result.details };\n}\n\nasync function resolveConfirmation(\n tool: VoiceTool,\n call: VoiceToolCall,\n confirmation: VoiceToolContext[\"confirmation\"],\n): Promise<ToolConfirmationDecision> {\n const policy = tool.confirmation ?? \"never\";\n if (policy === \"never\") {\n return { approved: true };\n }\n if (policy === \"destructive\" && !tool.destructive) {\n return { approved: true };\n }\n if (typeof policy === \"function\") {\n return policy({ call, tool });\n }\n if (!confirmation) {\n return {\n approved: false,\n reason: `Tool requires confirmation: ${tool.name}`,\n };\n }\n return confirmation({ call, tool });\n}\n\nfunction createErrorResult(call: VoiceToolCall, error: VoiceToolExecutionError): VoiceToolResult {\n const content: JsonObject = {\n error: error.message,\n type: error.type,\n };\n return {\n toolCallId: call.id,\n name: call.name,\n content,\n isError: true,\n };\n}\n"],"mappings":"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","names":[]}
|