realtime-voice-agents 2.0.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/LICENSE +21 -0
- package/README.md +298 -0
- package/assets/elevator-jazz.ulaw +1 -0
- package/assets/keyboard-typing.ulaw +1 -0
- package/assets/lofi.ulaw +1 -0
- package/assets/ringing.ulaw +1 -0
- package/assets/thinking-hum.ulaw +1 -0
- package/dist/BackgroundAudioPlayer-iMcivjis.mjs +282 -0
- package/dist/BackgroundAudioPlayer-jfRULWKC.cjs +313 -0
- package/dist/BaseRealtimeProvider-BQigr5mB.mjs +62 -0
- package/dist/BaseRealtimeProvider-BehPNT1r.d.cts +239 -0
- package/dist/BaseRealtimeProvider-ClP8Wx1X.d.mts +239 -0
- package/dist/BaseRealtimeProvider-DI4pKtOb.cjs +91 -0
- package/dist/GeminiLiveProvider-DvkTgzjG.d.cts +101 -0
- package/dist/GeminiLiveProvider-x2nyx5aO.d.mts +101 -0
- package/dist/InMemorySessionStore-B0_i-DOU.cjs +34 -0
- package/dist/InMemorySessionStore-B5_rq61L.d.cts +83 -0
- package/dist/InMemorySessionStore-B5_rq61L.d.mts +83 -0
- package/dist/InMemorySessionStore-DYParOJO.mjs +29 -0
- package/dist/OpenAICompatibleProvider-Bdtl-UXH.mjs +402 -0
- package/dist/OpenAICompatibleProvider-NS4cKVQj.cjs +409 -0
- package/dist/audio.cjs +21 -0
- package/dist/audio.d.cts +165 -0
- package/dist/audio.d.mts +165 -0
- package/dist/audio.mjs +4 -0
- package/dist/env-DSnGaERV.cjs +19 -0
- package/dist/env-DUwUWTsg.mjs +14 -0
- package/dist/events-BUMYdETO.d.cts +24 -0
- package/dist/events-BUMYdETO.d.mts +24 -0
- package/dist/events-BxDTIKKq.cjs +48 -0
- package/dist/events-BylBSBW-.mjs +43 -0
- package/dist/gemini.cjs +401 -0
- package/dist/gemini.d.cts +41 -0
- package/dist/gemini.d.mts +41 -0
- package/dist/gemini.mjs +395 -0
- package/dist/index.cjs +2142 -0
- package/dist/index.d.cts +920 -0
- package/dist/index.d.mts +920 -0
- package/dist/index.mjs +2113 -0
- package/dist/mulaw--cwU2c9L.mjs +64 -0
- package/dist/mulaw-DLUObjdP.cjs +117 -0
- package/dist/openai.cjs +61 -0
- package/dist/openai.d.cts +121 -0
- package/dist/openai.d.mts +121 -0
- package/dist/openai.mjs +53 -0
- package/dist/presets-Bf75YXs5.d.cts +24 -0
- package/dist/presets-Bf75YXs5.d.mts +24 -0
- package/dist/rest-BYqiVOhe.mjs +265 -0
- package/dist/rest-BvUKut_k.cjs +300 -0
- package/dist/rolldown-runtime-VH7oDXx4.cjs +28 -0
- package/dist/session-config-BVLl7-ha.mjs +74 -0
- package/dist/session-config-c8sOw1XL.cjs +85 -0
- package/dist/store.cjs +3 -0
- package/dist/store.d.cts +2 -0
- package/dist/store.d.mts +2 -0
- package/dist/store.mjs +2 -0
- package/dist/testing.cjs +544 -0
- package/dist/testing.d.cts +191 -0
- package/dist/testing.d.mts +191 -0
- package/dist/testing.mjs +538 -0
- package/dist/transcode-C9aJG7_W.cjs +215 -0
- package/dist/transcode-CsAp97G9.mjs +198 -0
- package/dist/transport-B_PJFIVd.d.cts +155 -0
- package/dist/transport-CEaLFV4E.d.mts +155 -0
- package/dist/twilio.cjs +8 -0
- package/dist/twilio.d.cts +3 -0
- package/dist/twilio.d.mts +3 -0
- package/dist/twilio.mjs +2 -0
- package/dist/twiml-z9LjoF4_.d.cts +67 -0
- package/dist/twiml-z9LjoF4_.d.mts +67 -0
- package/dist/xai.cjs +92 -0
- package/dist/xai.d.cts +35 -0
- package/dist/xai.d.mts +35 -0
- package/dist/xai.mjs +86 -0
- package/package.json +183 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { c as VadConfig, h as Logger, i as ProviderSessionInit, m as ProviderCapabilities, o as SendTextOptions, s as SendToolResultOptions, t as BaseRealtimeProvider } from "./BaseRealtimeProvider-ClP8Wx1X.mjs";
|
|
2
|
+
//#region src/providers/gemini/GeminiLiveProvider.d.ts
|
|
3
|
+
/** Structural slice of @google/genai's live session (also what fakes implement). */
|
|
4
|
+
interface GeminiLiveSessionLike {
|
|
5
|
+
sendRealtimeInput(input: {
|
|
6
|
+
audio: {
|
|
7
|
+
data: string;
|
|
8
|
+
mimeType: string;
|
|
9
|
+
};
|
|
10
|
+
}): void;
|
|
11
|
+
sendClientContent(content: {
|
|
12
|
+
turns: Array<Record<string, unknown>>;
|
|
13
|
+
turnComplete?: boolean;
|
|
14
|
+
}): void;
|
|
15
|
+
sendToolResponse(response: {
|
|
16
|
+
functionResponses: Array<Record<string, unknown>>;
|
|
17
|
+
}): void;
|
|
18
|
+
close(): void;
|
|
19
|
+
}
|
|
20
|
+
interface GeminiConnectParams {
|
|
21
|
+
model: string;
|
|
22
|
+
config: Record<string, unknown>;
|
|
23
|
+
callbacks: {
|
|
24
|
+
onopen?: () => void;
|
|
25
|
+
onmessage: (message: any) => void;
|
|
26
|
+
onerror?: (error: any) => void;
|
|
27
|
+
onclose?: (event: {
|
|
28
|
+
code?: number;
|
|
29
|
+
reason?: string;
|
|
30
|
+
}) => void;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
type GeminiLiveConnector = (params: GeminiConnectParams) => Promise<GeminiLiveSessionLike>;
|
|
34
|
+
interface GeminiLiveProviderConfig {
|
|
35
|
+
/** API-key auth (Google AI Studio). Ignored when `vertex` is set. */
|
|
36
|
+
apiKey?: string;
|
|
37
|
+
/** Vertex AI auth (uses Application Default Credentials). */
|
|
38
|
+
vertex?: {
|
|
39
|
+
project: string;
|
|
40
|
+
location: string;
|
|
41
|
+
};
|
|
42
|
+
model: string;
|
|
43
|
+
voice?: string;
|
|
44
|
+
languageCode?: string;
|
|
45
|
+
defaultVad?: VadConfig | null;
|
|
46
|
+
/** Input/output transcription toggles. Default both on. */
|
|
47
|
+
transcription?: {
|
|
48
|
+
input?: boolean;
|
|
49
|
+
output?: boolean;
|
|
50
|
+
} | false;
|
|
51
|
+
/** Use session resumption handles across reconnects. Default true. */
|
|
52
|
+
resumption?: boolean;
|
|
53
|
+
/** Ask Gemini to compress old context instead of dying at the token limit. */
|
|
54
|
+
contextWindowCompression?: boolean;
|
|
55
|
+
/** Provider-native `config` fields, deep-merged last (escape hatch). */
|
|
56
|
+
extraConfig?: Record<string, unknown>;
|
|
57
|
+
connectTimeoutMs?: number;
|
|
58
|
+
/** Test seam: replaces `new GoogleGenAI(...).live.connect`. */
|
|
59
|
+
connector?: GeminiLiveConnector;
|
|
60
|
+
}
|
|
61
|
+
declare class GeminiLiveProvider extends BaseRealtimeProvider {
|
|
62
|
+
readonly name = "gemini";
|
|
63
|
+
readonly capabilities: ProviderCapabilities;
|
|
64
|
+
private readonly config;
|
|
65
|
+
private readonly logger;
|
|
66
|
+
private session;
|
|
67
|
+
private sessionInit;
|
|
68
|
+
private ready;
|
|
69
|
+
private intentionalClose;
|
|
70
|
+
private readonly inbound;
|
|
71
|
+
private readonly outbound;
|
|
72
|
+
private turnCounter;
|
|
73
|
+
private currentTurnId;
|
|
74
|
+
private userTranscriptBuffer;
|
|
75
|
+
private agentTranscriptBuffer;
|
|
76
|
+
private resumptionHandle;
|
|
77
|
+
private resumed;
|
|
78
|
+
constructor(config: GeminiLiveProviderConfig, logger?: Logger);
|
|
79
|
+
get isConnected(): boolean;
|
|
80
|
+
/** True when the last connect restored server-side context via a handle. */
|
|
81
|
+
get didResume(): boolean;
|
|
82
|
+
connect(init: ProviderSessionInit): Promise<void>;
|
|
83
|
+
private defaultConnector;
|
|
84
|
+
private buildConfig;
|
|
85
|
+
close(): Promise<void>;
|
|
86
|
+
sendAudio(base64Mulaw: string): void;
|
|
87
|
+
sendText(text: string, options?: SendTextOptions): void;
|
|
88
|
+
sendToolResult(callId: string, output: unknown, options?: SendToolResultOptions): void;
|
|
89
|
+
createResponse(options?: {
|
|
90
|
+
instructions?: string;
|
|
91
|
+
}): void;
|
|
92
|
+
updateSession(_patch: Partial<ProviderSessionInit>): Promise<void>;
|
|
93
|
+
private handleMessage;
|
|
94
|
+
private readonly callNames;
|
|
95
|
+
private toolNameForCall;
|
|
96
|
+
private ensureTurn;
|
|
97
|
+
private flushUserTranscript;
|
|
98
|
+
private flushAgentTranscript;
|
|
99
|
+
}
|
|
100
|
+
//#endregion
|
|
101
|
+
export { GeminiLiveSessionLike as a, GeminiLiveProviderConfig as i, GeminiLiveConnector as n, GeminiLiveProvider as r, GeminiConnectParams as t };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
//#region src/session/InMemorySessionStore.ts
|
|
2
|
+
var InMemorySessionStore = class {
|
|
3
|
+
snapshots = /* @__PURE__ */ new Map();
|
|
4
|
+
maxEntries;
|
|
5
|
+
constructor(options = {}) {
|
|
6
|
+
this.maxEntries = options.maxEntries ?? 1e3;
|
|
7
|
+
}
|
|
8
|
+
async save(snapshot) {
|
|
9
|
+
this.snapshots.set(snapshot.callSid, structuredClone(snapshot));
|
|
10
|
+
while (this.snapshots.size > this.maxEntries) {
|
|
11
|
+
const oldest = this.snapshots.keys().next().value;
|
|
12
|
+
if (oldest === void 0) break;
|
|
13
|
+
this.snapshots.delete(oldest);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
async load(callSid) {
|
|
17
|
+
const snapshot = this.snapshots.get(callSid);
|
|
18
|
+
return snapshot ? structuredClone(snapshot) : null;
|
|
19
|
+
}
|
|
20
|
+
async delete(callSid) {
|
|
21
|
+
this.snapshots.delete(callSid);
|
|
22
|
+
}
|
|
23
|
+
/** All stored snapshots (testing/debugging). */
|
|
24
|
+
list() {
|
|
25
|
+
return [...this.snapshots.values()].map((s) => structuredClone(s));
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
//#endregion
|
|
29
|
+
Object.defineProperty(exports, "InMemorySessionStore", {
|
|
30
|
+
enumerable: true,
|
|
31
|
+
get: function() {
|
|
32
|
+
return InMemorySessionStore;
|
|
33
|
+
}
|
|
34
|
+
});
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
//#region src/session/transcript.d.ts
|
|
2
|
+
interface TranscriptEntry {
|
|
3
|
+
role: 'user' | 'agent';
|
|
4
|
+
text: string;
|
|
5
|
+
/** Milliseconds since call start. */
|
|
6
|
+
timestampMs: number;
|
|
7
|
+
/** Which agent spoke / was active (multi-agent calls). */
|
|
8
|
+
agentId?: string;
|
|
9
|
+
/** The caller cut this utterance off mid-playback. */
|
|
10
|
+
interrupted?: boolean;
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/session/usage.d.ts
|
|
14
|
+
/** Accumulated token consumption for a call, normalized across providers. */
|
|
15
|
+
interface UsageInfo {
|
|
16
|
+
inputTokens: number;
|
|
17
|
+
outputTokens: number;
|
|
18
|
+
totalTokens: number;
|
|
19
|
+
inputTokenDetails: {
|
|
20
|
+
textTokens: number;
|
|
21
|
+
audioTokens: number;
|
|
22
|
+
cachedTokens: number;
|
|
23
|
+
};
|
|
24
|
+
outputTokenDetails: {
|
|
25
|
+
textTokens: number;
|
|
26
|
+
audioTokens: number;
|
|
27
|
+
};
|
|
28
|
+
/** Number of model responses accounted. */
|
|
29
|
+
responses: number;
|
|
30
|
+
}
|
|
31
|
+
declare function emptyUsage(): UsageInfo;
|
|
32
|
+
//#endregion
|
|
33
|
+
//#region src/session/snapshot.d.ts
|
|
34
|
+
/** Serializable checkpoint of a call, written to the SessionStore. */
|
|
35
|
+
interface CallSnapshot {
|
|
36
|
+
callSid: string;
|
|
37
|
+
streamSid: string | null;
|
|
38
|
+
state: string;
|
|
39
|
+
activeAgentId: string;
|
|
40
|
+
transcript: TranscriptEntry[];
|
|
41
|
+
usage: UsageInfo;
|
|
42
|
+
context: Record<string, unknown>;
|
|
43
|
+
handoffHistory: Array<{
|
|
44
|
+
from: string;
|
|
45
|
+
to: string;
|
|
46
|
+
atMs: number;
|
|
47
|
+
}>;
|
|
48
|
+
/** Gemini session-resumption handle, when the provider supplies one. */
|
|
49
|
+
resumptionHandle?: string;
|
|
50
|
+
startedAtMs: number;
|
|
51
|
+
endedAtMs?: number;
|
|
52
|
+
endReason?: string;
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
//#region src/session/SessionStore.d.ts
|
|
56
|
+
/**
|
|
57
|
+
* Durable checkpoint store (LangGraph-checkpointer-inspired). Snapshots are
|
|
58
|
+
* written at call start, agent handoff, tool completion, and call end — never
|
|
59
|
+
* read on the audio hot path. Implement over Redis/Postgres for multi-instance
|
|
60
|
+
* observability and post-call processing; the in-memory default suffices for
|
|
61
|
+
* single-process deployments.
|
|
62
|
+
*/
|
|
63
|
+
interface SessionStore {
|
|
64
|
+
save(snapshot: CallSnapshot): Promise<void>;
|
|
65
|
+
load(callSid: string): Promise<CallSnapshot | null>;
|
|
66
|
+
delete(callSid: string): Promise<void>;
|
|
67
|
+
}
|
|
68
|
+
//#endregion
|
|
69
|
+
//#region src/session/InMemorySessionStore.d.ts
|
|
70
|
+
declare class InMemorySessionStore implements SessionStore {
|
|
71
|
+
private readonly snapshots;
|
|
72
|
+
private readonly maxEntries;
|
|
73
|
+
constructor(options?: {
|
|
74
|
+
maxEntries?: number;
|
|
75
|
+
});
|
|
76
|
+
save(snapshot: CallSnapshot): Promise<void>;
|
|
77
|
+
load(callSid: string): Promise<CallSnapshot | null>;
|
|
78
|
+
delete(callSid: string): Promise<void>;
|
|
79
|
+
/** All stored snapshots (testing/debugging). */
|
|
80
|
+
list(): CallSnapshot[];
|
|
81
|
+
}
|
|
82
|
+
//#endregion
|
|
83
|
+
export { emptyUsage as a, UsageInfo as i, SessionStore as n, TranscriptEntry as o, CallSnapshot as r, InMemorySessionStore as t };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
//#region src/session/transcript.d.ts
|
|
2
|
+
interface TranscriptEntry {
|
|
3
|
+
role: 'user' | 'agent';
|
|
4
|
+
text: string;
|
|
5
|
+
/** Milliseconds since call start. */
|
|
6
|
+
timestampMs: number;
|
|
7
|
+
/** Which agent spoke / was active (multi-agent calls). */
|
|
8
|
+
agentId?: string;
|
|
9
|
+
/** The caller cut this utterance off mid-playback. */
|
|
10
|
+
interrupted?: boolean;
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/session/usage.d.ts
|
|
14
|
+
/** Accumulated token consumption for a call, normalized across providers. */
|
|
15
|
+
interface UsageInfo {
|
|
16
|
+
inputTokens: number;
|
|
17
|
+
outputTokens: number;
|
|
18
|
+
totalTokens: number;
|
|
19
|
+
inputTokenDetails: {
|
|
20
|
+
textTokens: number;
|
|
21
|
+
audioTokens: number;
|
|
22
|
+
cachedTokens: number;
|
|
23
|
+
};
|
|
24
|
+
outputTokenDetails: {
|
|
25
|
+
textTokens: number;
|
|
26
|
+
audioTokens: number;
|
|
27
|
+
};
|
|
28
|
+
/** Number of model responses accounted. */
|
|
29
|
+
responses: number;
|
|
30
|
+
}
|
|
31
|
+
declare function emptyUsage(): UsageInfo;
|
|
32
|
+
//#endregion
|
|
33
|
+
//#region src/session/snapshot.d.ts
|
|
34
|
+
/** Serializable checkpoint of a call, written to the SessionStore. */
|
|
35
|
+
interface CallSnapshot {
|
|
36
|
+
callSid: string;
|
|
37
|
+
streamSid: string | null;
|
|
38
|
+
state: string;
|
|
39
|
+
activeAgentId: string;
|
|
40
|
+
transcript: TranscriptEntry[];
|
|
41
|
+
usage: UsageInfo;
|
|
42
|
+
context: Record<string, unknown>;
|
|
43
|
+
handoffHistory: Array<{
|
|
44
|
+
from: string;
|
|
45
|
+
to: string;
|
|
46
|
+
atMs: number;
|
|
47
|
+
}>;
|
|
48
|
+
/** Gemini session-resumption handle, when the provider supplies one. */
|
|
49
|
+
resumptionHandle?: string;
|
|
50
|
+
startedAtMs: number;
|
|
51
|
+
endedAtMs?: number;
|
|
52
|
+
endReason?: string;
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
//#region src/session/SessionStore.d.ts
|
|
56
|
+
/**
|
|
57
|
+
* Durable checkpoint store (LangGraph-checkpointer-inspired). Snapshots are
|
|
58
|
+
* written at call start, agent handoff, tool completion, and call end — never
|
|
59
|
+
* read on the audio hot path. Implement over Redis/Postgres for multi-instance
|
|
60
|
+
* observability and post-call processing; the in-memory default suffices for
|
|
61
|
+
* single-process deployments.
|
|
62
|
+
*/
|
|
63
|
+
interface SessionStore {
|
|
64
|
+
save(snapshot: CallSnapshot): Promise<void>;
|
|
65
|
+
load(callSid: string): Promise<CallSnapshot | null>;
|
|
66
|
+
delete(callSid: string): Promise<void>;
|
|
67
|
+
}
|
|
68
|
+
//#endregion
|
|
69
|
+
//#region src/session/InMemorySessionStore.d.ts
|
|
70
|
+
declare class InMemorySessionStore implements SessionStore {
|
|
71
|
+
private readonly snapshots;
|
|
72
|
+
private readonly maxEntries;
|
|
73
|
+
constructor(options?: {
|
|
74
|
+
maxEntries?: number;
|
|
75
|
+
});
|
|
76
|
+
save(snapshot: CallSnapshot): Promise<void>;
|
|
77
|
+
load(callSid: string): Promise<CallSnapshot | null>;
|
|
78
|
+
delete(callSid: string): Promise<void>;
|
|
79
|
+
/** All stored snapshots (testing/debugging). */
|
|
80
|
+
list(): CallSnapshot[];
|
|
81
|
+
}
|
|
82
|
+
//#endregion
|
|
83
|
+
export { emptyUsage as a, UsageInfo as i, SessionStore as n, TranscriptEntry as o, CallSnapshot as r, InMemorySessionStore as t };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
//#region src/session/InMemorySessionStore.ts
|
|
2
|
+
var InMemorySessionStore = class {
|
|
3
|
+
snapshots = /* @__PURE__ */ new Map();
|
|
4
|
+
maxEntries;
|
|
5
|
+
constructor(options = {}) {
|
|
6
|
+
this.maxEntries = options.maxEntries ?? 1e3;
|
|
7
|
+
}
|
|
8
|
+
async save(snapshot) {
|
|
9
|
+
this.snapshots.set(snapshot.callSid, structuredClone(snapshot));
|
|
10
|
+
while (this.snapshots.size > this.maxEntries) {
|
|
11
|
+
const oldest = this.snapshots.keys().next().value;
|
|
12
|
+
if (oldest === void 0) break;
|
|
13
|
+
this.snapshots.delete(oldest);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
async load(callSid) {
|
|
17
|
+
const snapshot = this.snapshots.get(callSid);
|
|
18
|
+
return snapshot ? structuredClone(snapshot) : null;
|
|
19
|
+
}
|
|
20
|
+
async delete(callSid) {
|
|
21
|
+
this.snapshots.delete(callSid);
|
|
22
|
+
}
|
|
23
|
+
/** All stored snapshots (testing/debugging). */
|
|
24
|
+
list() {
|
|
25
|
+
return [...this.snapshots.values()].map((s) => structuredClone(s));
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
//#endregion
|
|
29
|
+
export { InMemorySessionStore as t };
|