@jchaffin/voicekit 0.2.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 +369 -0
- package/dist/adapters/deepgram.d.mts +43 -0
- package/dist/adapters/deepgram.d.ts +43 -0
- package/dist/adapters/deepgram.js +216 -0
- package/dist/adapters/deepgram.mjs +162 -0
- package/dist/adapters/elevenlabs.d.mts +41 -0
- package/dist/adapters/elevenlabs.d.ts +41 -0
- package/dist/adapters/elevenlabs.js +304 -0
- package/dist/adapters/elevenlabs.mjs +250 -0
- package/dist/adapters/livekit.d.mts +44 -0
- package/dist/adapters/livekit.d.ts +44 -0
- package/dist/adapters/livekit.js +225 -0
- package/dist/adapters/livekit.mjs +161 -0
- package/dist/adapters/openai.d.mts +41 -0
- package/dist/adapters/openai.d.ts +41 -0
- package/dist/adapters/openai.js +350 -0
- package/dist/adapters/openai.mjs +294 -0
- package/dist/chunk-22WLZIXO.mjs +33 -0
- package/dist/chunk-T3II3DRG.mjs +178 -0
- package/dist/chunk-UZ2VGPZD.mjs +33 -0
- package/dist/chunk-Y6FXYEAI.mjs +10 -0
- package/dist/index.d.mts +693 -0
- package/dist/index.d.ts +693 -0
- package/dist/index.js +1838 -0
- package/dist/index.mjs +1593 -0
- package/dist/server.d.mts +80 -0
- package/dist/server.d.ts +80 -0
- package/dist/server.js +147 -0
- package/dist/server.mjs +119 -0
- package/dist/types-DY31oVB1.d.mts +150 -0
- package/dist/types-DY31oVB1.d.ts +150 -0
- package/dist/types-mThnXW9S.d.mts +150 -0
- package/dist/types-mThnXW9S.d.ts +150 -0
- package/dist/types-uLnzb8NE.d.mts +150 -0
- package/dist/types-uLnzb8NE.d.ts +150 -0
- package/package.json +100 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
export { S as ServerAdapter, g as ServerSessionConfig } from './types-DY31oVB1.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Server-side utilities for VoiceKit
|
|
5
|
+
* Use these in your API routes (Next.js, Express, etc.)
|
|
6
|
+
*
|
|
7
|
+
* This module provides the legacy OpenAI-specific helpers.
|
|
8
|
+
* For provider-agnostic server adapters, import from the adapter entrypoints:
|
|
9
|
+
* import { openaiServer } from '@jchaffin/voicekit/openai'
|
|
10
|
+
* import { livekitServer } from '@jchaffin/voicekit/livekit'
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
interface SessionConfig {
|
|
14
|
+
/** OpenAI API key (defaults to OPENAI_API_KEY env var) */
|
|
15
|
+
apiKey?: string;
|
|
16
|
+
/** Model to use */
|
|
17
|
+
model?: string;
|
|
18
|
+
/** Voice ID */
|
|
19
|
+
voice?: string;
|
|
20
|
+
/** Instructions for the agent */
|
|
21
|
+
instructions?: string;
|
|
22
|
+
/** Expiration time in seconds (default: 600 = 10 minutes) */
|
|
23
|
+
expiresIn?: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Create an ephemeral session key for OpenAI Realtime API
|
|
27
|
+
*
|
|
28
|
+
* @example Next.js App Router
|
|
29
|
+
* ```ts
|
|
30
|
+
* // app/api/session/route.ts
|
|
31
|
+
* import { createSessionHandler } from '@jchaffin/voicekit/server';
|
|
32
|
+
* export const POST = createSessionHandler();
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @example Next.js with config
|
|
36
|
+
* ```ts
|
|
37
|
+
* export const POST = createSessionHandler({
|
|
38
|
+
* model: 'gpt-realtime',
|
|
39
|
+
* voice: 'alloy'
|
|
40
|
+
* });
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
declare function createSessionHandler(config?: SessionConfig): (request?: Request) => Promise<Response>;
|
|
44
|
+
/**
|
|
45
|
+
* Get an ephemeral key directly (for custom server implementations)
|
|
46
|
+
*
|
|
47
|
+
* @example Express
|
|
48
|
+
* ```ts
|
|
49
|
+
* import { getEphemeralKey } from '@jchaffin/voicekit/server';
|
|
50
|
+
*
|
|
51
|
+
* app.post('/api/session', async (req, res) => {
|
|
52
|
+
* const result = await getEphemeralKey();
|
|
53
|
+
* if (result.error) {
|
|
54
|
+
* return res.status(500).json({ error: result.error });
|
|
55
|
+
* }
|
|
56
|
+
* res.json({ ephemeralKey: result.ephemeralKey });
|
|
57
|
+
* });
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
declare function getEphemeralKey(config?: SessionConfig): Promise<{
|
|
61
|
+
ephemeralKey: string;
|
|
62
|
+
error?: never;
|
|
63
|
+
} | {
|
|
64
|
+
ephemeralKey?: never;
|
|
65
|
+
error: string;
|
|
66
|
+
}>;
|
|
67
|
+
/**
|
|
68
|
+
* Create CORS headers for API routes
|
|
69
|
+
*/
|
|
70
|
+
declare function corsHeaders(origin?: string): {
|
|
71
|
+
'Access-Control-Allow-Origin': string;
|
|
72
|
+
'Access-Control-Allow-Methods': string;
|
|
73
|
+
'Access-Control-Allow-Headers': string;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Handle OPTIONS preflight request
|
|
77
|
+
*/
|
|
78
|
+
declare function handleOptions(origin?: string): Response;
|
|
79
|
+
|
|
80
|
+
export { type SessionConfig, corsHeaders, createSessionHandler, getEphemeralKey, handleOptions };
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
export { S as ServerAdapter, g as ServerSessionConfig } from './types-DY31oVB1.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Server-side utilities for VoiceKit
|
|
5
|
+
* Use these in your API routes (Next.js, Express, etc.)
|
|
6
|
+
*
|
|
7
|
+
* This module provides the legacy OpenAI-specific helpers.
|
|
8
|
+
* For provider-agnostic server adapters, import from the adapter entrypoints:
|
|
9
|
+
* import { openaiServer } from '@jchaffin/voicekit/openai'
|
|
10
|
+
* import { livekitServer } from '@jchaffin/voicekit/livekit'
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
interface SessionConfig {
|
|
14
|
+
/** OpenAI API key (defaults to OPENAI_API_KEY env var) */
|
|
15
|
+
apiKey?: string;
|
|
16
|
+
/** Model to use */
|
|
17
|
+
model?: string;
|
|
18
|
+
/** Voice ID */
|
|
19
|
+
voice?: string;
|
|
20
|
+
/** Instructions for the agent */
|
|
21
|
+
instructions?: string;
|
|
22
|
+
/** Expiration time in seconds (default: 600 = 10 minutes) */
|
|
23
|
+
expiresIn?: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Create an ephemeral session key for OpenAI Realtime API
|
|
27
|
+
*
|
|
28
|
+
* @example Next.js App Router
|
|
29
|
+
* ```ts
|
|
30
|
+
* // app/api/session/route.ts
|
|
31
|
+
* import { createSessionHandler } from '@jchaffin/voicekit/server';
|
|
32
|
+
* export const POST = createSessionHandler();
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @example Next.js with config
|
|
36
|
+
* ```ts
|
|
37
|
+
* export const POST = createSessionHandler({
|
|
38
|
+
* model: 'gpt-realtime',
|
|
39
|
+
* voice: 'alloy'
|
|
40
|
+
* });
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
declare function createSessionHandler(config?: SessionConfig): (request?: Request) => Promise<Response>;
|
|
44
|
+
/**
|
|
45
|
+
* Get an ephemeral key directly (for custom server implementations)
|
|
46
|
+
*
|
|
47
|
+
* @example Express
|
|
48
|
+
* ```ts
|
|
49
|
+
* import { getEphemeralKey } from '@jchaffin/voicekit/server';
|
|
50
|
+
*
|
|
51
|
+
* app.post('/api/session', async (req, res) => {
|
|
52
|
+
* const result = await getEphemeralKey();
|
|
53
|
+
* if (result.error) {
|
|
54
|
+
* return res.status(500).json({ error: result.error });
|
|
55
|
+
* }
|
|
56
|
+
* res.json({ ephemeralKey: result.ephemeralKey });
|
|
57
|
+
* });
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
declare function getEphemeralKey(config?: SessionConfig): Promise<{
|
|
61
|
+
ephemeralKey: string;
|
|
62
|
+
error?: never;
|
|
63
|
+
} | {
|
|
64
|
+
ephemeralKey?: never;
|
|
65
|
+
error: string;
|
|
66
|
+
}>;
|
|
67
|
+
/**
|
|
68
|
+
* Create CORS headers for API routes
|
|
69
|
+
*/
|
|
70
|
+
declare function corsHeaders(origin?: string): {
|
|
71
|
+
'Access-Control-Allow-Origin': string;
|
|
72
|
+
'Access-Control-Allow-Methods': string;
|
|
73
|
+
'Access-Control-Allow-Headers': string;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Handle OPTIONS preflight request
|
|
77
|
+
*/
|
|
78
|
+
declare function handleOptions(origin?: string): Response;
|
|
79
|
+
|
|
80
|
+
export { type SessionConfig, corsHeaders, createSessionHandler, getEphemeralKey, handleOptions };
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/server.ts
|
|
21
|
+
var server_exports = {};
|
|
22
|
+
__export(server_exports, {
|
|
23
|
+
corsHeaders: () => corsHeaders,
|
|
24
|
+
createSessionHandler: () => createSessionHandler,
|
|
25
|
+
getEphemeralKey: () => getEphemeralKey,
|
|
26
|
+
handleOptions: () => handleOptions
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(server_exports);
|
|
29
|
+
function createSessionHandler(config = {}) {
|
|
30
|
+
return async function handler(request) {
|
|
31
|
+
try {
|
|
32
|
+
const apiKey = config.apiKey || process.env.OPENAI_API_KEY;
|
|
33
|
+
if (!apiKey) {
|
|
34
|
+
return Response.json(
|
|
35
|
+
{ error: "OpenAI API key not configured" },
|
|
36
|
+
{ status: 500 }
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
const response = await fetch("https://api.openai.com/v1/realtime/client_secrets", {
|
|
40
|
+
method: "POST",
|
|
41
|
+
headers: {
|
|
42
|
+
"Authorization": `Bearer ${apiKey}`,
|
|
43
|
+
"Content-Type": "application/json"
|
|
44
|
+
},
|
|
45
|
+
body: JSON.stringify({
|
|
46
|
+
expires_after: {
|
|
47
|
+
anchor: "created_at",
|
|
48
|
+
seconds: config.expiresIn || 600
|
|
49
|
+
},
|
|
50
|
+
session: {
|
|
51
|
+
type: "realtime",
|
|
52
|
+
model: config.model || "gpt-realtime",
|
|
53
|
+
...config.voice && {
|
|
54
|
+
audio: {
|
|
55
|
+
output: { voice: config.voice }
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
...config.instructions && { instructions: config.instructions }
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
});
|
|
62
|
+
if (!response.ok) {
|
|
63
|
+
const error = await response.text();
|
|
64
|
+
console.error("OpenAI client_secrets error:", error);
|
|
65
|
+
return Response.json(
|
|
66
|
+
{ error: `OpenAI API error: ${response.status}` },
|
|
67
|
+
{ status: 500 }
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
const data = await response.json();
|
|
71
|
+
if (!data.value) {
|
|
72
|
+
return Response.json(
|
|
73
|
+
{ error: "Invalid response from OpenAI" },
|
|
74
|
+
{ status: 500 }
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
return Response.json({ ephemeralKey: data.value });
|
|
78
|
+
} catch (error) {
|
|
79
|
+
console.error("Session handler error:", error);
|
|
80
|
+
return Response.json(
|
|
81
|
+
{ error: "Internal server error" },
|
|
82
|
+
{ status: 500 }
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
async function getEphemeralKey(config = {}) {
|
|
88
|
+
try {
|
|
89
|
+
const apiKey = config.apiKey || process.env.OPENAI_API_KEY;
|
|
90
|
+
if (!apiKey) {
|
|
91
|
+
return { error: "OpenAI API key not configured" };
|
|
92
|
+
}
|
|
93
|
+
const response = await fetch("https://api.openai.com/v1/realtime/client_secrets", {
|
|
94
|
+
method: "POST",
|
|
95
|
+
headers: {
|
|
96
|
+
"Authorization": `Bearer ${apiKey}`,
|
|
97
|
+
"Content-Type": "application/json"
|
|
98
|
+
},
|
|
99
|
+
body: JSON.stringify({
|
|
100
|
+
expires_after: {
|
|
101
|
+
anchor: "created_at",
|
|
102
|
+
seconds: config.expiresIn || 600
|
|
103
|
+
},
|
|
104
|
+
session: {
|
|
105
|
+
type: "realtime",
|
|
106
|
+
model: config.model || "gpt-realtime",
|
|
107
|
+
...config.voice && {
|
|
108
|
+
audio: {
|
|
109
|
+
output: { voice: config.voice }
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
...config.instructions && { instructions: config.instructions }
|
|
113
|
+
}
|
|
114
|
+
})
|
|
115
|
+
});
|
|
116
|
+
if (!response.ok) {
|
|
117
|
+
return { error: `OpenAI API error: ${response.status}` };
|
|
118
|
+
}
|
|
119
|
+
const data = await response.json();
|
|
120
|
+
if (!data.value) {
|
|
121
|
+
return { error: "Invalid response from OpenAI" };
|
|
122
|
+
}
|
|
123
|
+
return { ephemeralKey: data.value };
|
|
124
|
+
} catch (error) {
|
|
125
|
+
return { error: String(error) };
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function corsHeaders(origin = "*") {
|
|
129
|
+
return {
|
|
130
|
+
"Access-Control-Allow-Origin": origin,
|
|
131
|
+
"Access-Control-Allow-Methods": "POST, OPTIONS",
|
|
132
|
+
"Access-Control-Allow-Headers": "Content-Type"
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function handleOptions(origin = "*") {
|
|
136
|
+
return new Response(null, {
|
|
137
|
+
status: 200,
|
|
138
|
+
headers: corsHeaders(origin)
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
142
|
+
0 && (module.exports = {
|
|
143
|
+
corsHeaders,
|
|
144
|
+
createSessionHandler,
|
|
145
|
+
getEphemeralKey,
|
|
146
|
+
handleOptions
|
|
147
|
+
});
|
package/dist/server.mjs
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// src/server.ts
|
|
2
|
+
function createSessionHandler(config = {}) {
|
|
3
|
+
return async function handler(request) {
|
|
4
|
+
try {
|
|
5
|
+
const apiKey = config.apiKey || process.env.OPENAI_API_KEY;
|
|
6
|
+
if (!apiKey) {
|
|
7
|
+
return Response.json(
|
|
8
|
+
{ error: "OpenAI API key not configured" },
|
|
9
|
+
{ status: 500 }
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
const response = await fetch("https://api.openai.com/v1/realtime/client_secrets", {
|
|
13
|
+
method: "POST",
|
|
14
|
+
headers: {
|
|
15
|
+
"Authorization": `Bearer ${apiKey}`,
|
|
16
|
+
"Content-Type": "application/json"
|
|
17
|
+
},
|
|
18
|
+
body: JSON.stringify({
|
|
19
|
+
expires_after: {
|
|
20
|
+
anchor: "created_at",
|
|
21
|
+
seconds: config.expiresIn || 600
|
|
22
|
+
},
|
|
23
|
+
session: {
|
|
24
|
+
type: "realtime",
|
|
25
|
+
model: config.model || "gpt-realtime",
|
|
26
|
+
...config.voice && {
|
|
27
|
+
audio: {
|
|
28
|
+
output: { voice: config.voice }
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
...config.instructions && { instructions: config.instructions }
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
});
|
|
35
|
+
if (!response.ok) {
|
|
36
|
+
const error = await response.text();
|
|
37
|
+
console.error("OpenAI client_secrets error:", error);
|
|
38
|
+
return Response.json(
|
|
39
|
+
{ error: `OpenAI API error: ${response.status}` },
|
|
40
|
+
{ status: 500 }
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
const data = await response.json();
|
|
44
|
+
if (!data.value) {
|
|
45
|
+
return Response.json(
|
|
46
|
+
{ error: "Invalid response from OpenAI" },
|
|
47
|
+
{ status: 500 }
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
return Response.json({ ephemeralKey: data.value });
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.error("Session handler error:", error);
|
|
53
|
+
return Response.json(
|
|
54
|
+
{ error: "Internal server error" },
|
|
55
|
+
{ status: 500 }
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
async function getEphemeralKey(config = {}) {
|
|
61
|
+
try {
|
|
62
|
+
const apiKey = config.apiKey || process.env.OPENAI_API_KEY;
|
|
63
|
+
if (!apiKey) {
|
|
64
|
+
return { error: "OpenAI API key not configured" };
|
|
65
|
+
}
|
|
66
|
+
const response = await fetch("https://api.openai.com/v1/realtime/client_secrets", {
|
|
67
|
+
method: "POST",
|
|
68
|
+
headers: {
|
|
69
|
+
"Authorization": `Bearer ${apiKey}`,
|
|
70
|
+
"Content-Type": "application/json"
|
|
71
|
+
},
|
|
72
|
+
body: JSON.stringify({
|
|
73
|
+
expires_after: {
|
|
74
|
+
anchor: "created_at",
|
|
75
|
+
seconds: config.expiresIn || 600
|
|
76
|
+
},
|
|
77
|
+
session: {
|
|
78
|
+
type: "realtime",
|
|
79
|
+
model: config.model || "gpt-realtime",
|
|
80
|
+
...config.voice && {
|
|
81
|
+
audio: {
|
|
82
|
+
output: { voice: config.voice }
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
...config.instructions && { instructions: config.instructions }
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
});
|
|
89
|
+
if (!response.ok) {
|
|
90
|
+
return { error: `OpenAI API error: ${response.status}` };
|
|
91
|
+
}
|
|
92
|
+
const data = await response.json();
|
|
93
|
+
if (!data.value) {
|
|
94
|
+
return { error: "Invalid response from OpenAI" };
|
|
95
|
+
}
|
|
96
|
+
return { ephemeralKey: data.value };
|
|
97
|
+
} catch (error) {
|
|
98
|
+
return { error: String(error) };
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function corsHeaders(origin = "*") {
|
|
102
|
+
return {
|
|
103
|
+
"Access-Control-Allow-Origin": origin,
|
|
104
|
+
"Access-Control-Allow-Methods": "POST, OPTIONS",
|
|
105
|
+
"Access-Control-Allow-Headers": "Content-Type"
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function handleOptions(origin = "*") {
|
|
109
|
+
return new Response(null, {
|
|
110
|
+
status: 200,
|
|
111
|
+
headers: corsHeaders(origin)
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
export {
|
|
115
|
+
corsHeaders,
|
|
116
|
+
createSessionHandler,
|
|
117
|
+
getEphemeralKey,
|
|
118
|
+
handleOptions
|
|
119
|
+
};
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
type VoiceStatus$1 = 'DISCONNECTED' | 'CONNECTING' | 'CONNECTED';
|
|
2
|
+
interface TranscriptMessage {
|
|
3
|
+
id: string;
|
|
4
|
+
role: 'user' | 'assistant';
|
|
5
|
+
text: string;
|
|
6
|
+
timestamp: Date;
|
|
7
|
+
status: 'pending' | 'complete';
|
|
8
|
+
}
|
|
9
|
+
type ToolParamType = 'string' | 'number' | 'boolean' | 'array' | 'object';
|
|
10
|
+
interface ToolParamDefinition {
|
|
11
|
+
type: ToolParamType;
|
|
12
|
+
description?: string;
|
|
13
|
+
enum?: string[];
|
|
14
|
+
default?: unknown;
|
|
15
|
+
}
|
|
16
|
+
interface ToolDefinition<TParams = Record<string, unknown>, TResult = unknown> {
|
|
17
|
+
name: string;
|
|
18
|
+
description: string;
|
|
19
|
+
parameters: {
|
|
20
|
+
type: 'object';
|
|
21
|
+
properties: Record<string, ToolParamDefinition>;
|
|
22
|
+
required?: string[];
|
|
23
|
+
};
|
|
24
|
+
execute: (params: TParams) => Promise<TResult> | TResult;
|
|
25
|
+
}
|
|
26
|
+
interface AgentConfig {
|
|
27
|
+
name: string;
|
|
28
|
+
instructions: string;
|
|
29
|
+
tools?: ToolDefinition[];
|
|
30
|
+
voice?: string;
|
|
31
|
+
}
|
|
32
|
+
interface VoiceConfig {
|
|
33
|
+
/** API endpoint that returns session token */
|
|
34
|
+
sessionEndpoint?: string;
|
|
35
|
+
/** Model identifier (provider-specific) */
|
|
36
|
+
model?: string;
|
|
37
|
+
/** Audio codec preference */
|
|
38
|
+
codec?: 'opus' | 'pcmu' | 'pcma';
|
|
39
|
+
/** Language for transcription */
|
|
40
|
+
language?: string;
|
|
41
|
+
onStatusChange?: (status: VoiceStatus$1) => void;
|
|
42
|
+
onTranscriptUpdate?: (messages: TranscriptMessage[]) => void;
|
|
43
|
+
onToolCall?: (toolName: string, params: unknown, result: unknown) => void;
|
|
44
|
+
onError?: (error: Error) => void;
|
|
45
|
+
}
|
|
46
|
+
interface VoiceProviderProps extends VoiceConfig {
|
|
47
|
+
/** Provider adapter (e.g. openai(), livekit(), deepgram()) */
|
|
48
|
+
adapter: VoiceAdapter;
|
|
49
|
+
/** Agent configuration */
|
|
50
|
+
agent: VoiceAgentConfig;
|
|
51
|
+
children: React.ReactNode;
|
|
52
|
+
}
|
|
53
|
+
interface VoiceContextValue {
|
|
54
|
+
status: VoiceStatus$1;
|
|
55
|
+
connect: () => Promise<void>;
|
|
56
|
+
disconnect: () => Promise<void>;
|
|
57
|
+
transcript: TranscriptMessage[];
|
|
58
|
+
clearTranscript: () => void;
|
|
59
|
+
sendMessage: (text: string) => void;
|
|
60
|
+
interrupt: () => void;
|
|
61
|
+
mute: (muted: boolean) => void;
|
|
62
|
+
isMuted: boolean;
|
|
63
|
+
agent: VoiceAgentConfig;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
type VoiceStatus = 'DISCONNECTED' | 'CONNECTING' | 'CONNECTED';
|
|
67
|
+
interface VoiceAgentConfig {
|
|
68
|
+
name: string;
|
|
69
|
+
instructions: string;
|
|
70
|
+
tools?: ToolDefinition[];
|
|
71
|
+
voice?: string;
|
|
72
|
+
handoffs?: VoiceAgentConfig[];
|
|
73
|
+
}
|
|
74
|
+
interface SessionEvents {
|
|
75
|
+
[event: string]: (...args: any[]) => void;
|
|
76
|
+
status_change: (status: VoiceStatus) => void;
|
|
77
|
+
user_speech_started: () => void;
|
|
78
|
+
user_transcript: (data: TranscriptData) => void;
|
|
79
|
+
assistant_transcript: (data: TranscriptData) => void;
|
|
80
|
+
tool_call_start: (name: string, input: unknown) => void;
|
|
81
|
+
tool_call_end: (name: string, input: unknown, output: unknown) => void;
|
|
82
|
+
agent_handoff: (from: string, to: string) => void;
|
|
83
|
+
guardrail_tripped: (info: unknown) => void;
|
|
84
|
+
audio_delta: (itemId: string, delta: string) => void;
|
|
85
|
+
error: (error: Error) => void;
|
|
86
|
+
/** Escape hatch for provider-specific events not covered by normalized types */
|
|
87
|
+
raw_event: (event: unknown) => void;
|
|
88
|
+
}
|
|
89
|
+
interface TranscriptData {
|
|
90
|
+
itemId: string;
|
|
91
|
+
delta?: string;
|
|
92
|
+
text?: string;
|
|
93
|
+
isFinal: boolean;
|
|
94
|
+
}
|
|
95
|
+
interface VoiceSession {
|
|
96
|
+
connect(config: ConnectConfig): Promise<void>;
|
|
97
|
+
disconnect(): Promise<void>;
|
|
98
|
+
sendMessage(text: string): void | Promise<void>;
|
|
99
|
+
interrupt(): void;
|
|
100
|
+
mute(muted: boolean): void;
|
|
101
|
+
sendRawEvent?(event: Record<string, unknown>): void;
|
|
102
|
+
on<E extends string & keyof SessionEvents>(event: E, handler: SessionEvents[E]): void;
|
|
103
|
+
off<E extends string & keyof SessionEvents>(event: E, handler: SessionEvents[E]): void;
|
|
104
|
+
}
|
|
105
|
+
interface ConnectConfig {
|
|
106
|
+
/** Authentication token/key obtained from server handler */
|
|
107
|
+
authToken: string;
|
|
108
|
+
/** HTML audio element for playback */
|
|
109
|
+
audioElement?: HTMLAudioElement;
|
|
110
|
+
/** Extra context passed to the session */
|
|
111
|
+
context?: Record<string, unknown>;
|
|
112
|
+
/** Output guardrails */
|
|
113
|
+
outputGuardrails?: unknown[];
|
|
114
|
+
}
|
|
115
|
+
interface SessionOptions {
|
|
116
|
+
model?: string;
|
|
117
|
+
language?: string;
|
|
118
|
+
codec?: string;
|
|
119
|
+
voice?: string;
|
|
120
|
+
/** Provider-specific options */
|
|
121
|
+
[key: string]: unknown;
|
|
122
|
+
}
|
|
123
|
+
interface VoiceAdapter {
|
|
124
|
+
/** Unique name for this adapter (e.g. 'openai', 'livekit') */
|
|
125
|
+
readonly name: string;
|
|
126
|
+
/** Create a session for the given agent */
|
|
127
|
+
createSession(agent: VoiceAgentConfig, options?: SessionOptions): VoiceSession;
|
|
128
|
+
}
|
|
129
|
+
interface ServerSessionConfig {
|
|
130
|
+
/** Provider-specific API key */
|
|
131
|
+
apiKey?: string;
|
|
132
|
+
model?: string;
|
|
133
|
+
voice?: string;
|
|
134
|
+
instructions?: string;
|
|
135
|
+
expiresIn?: number;
|
|
136
|
+
/** Provider-specific options */
|
|
137
|
+
[key: string]: unknown;
|
|
138
|
+
}
|
|
139
|
+
interface ServerAdapter {
|
|
140
|
+
createSessionHandler(config?: ServerSessionConfig): (request?: Request) => Promise<Response>;
|
|
141
|
+
getSessionToken(config?: ServerSessionConfig): Promise<{
|
|
142
|
+
token: string;
|
|
143
|
+
error?: string;
|
|
144
|
+
} | {
|
|
145
|
+
token?: string;
|
|
146
|
+
error: string;
|
|
147
|
+
}>;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export type { AgentConfig as A, ConnectConfig as C, ServerAdapter as S, TranscriptMessage as T, VoiceProviderProps as V, VoiceContextValue as a, VoiceAgentConfig as b, ToolDefinition as c, ToolParamDefinition as d, VoiceAdapter as e, VoiceStatus$1 as f, ServerSessionConfig as g, SessionEvents as h, SessionOptions as i, TranscriptData as j, VoiceConfig as k, VoiceSession as l };
|