@kuralle-syrinx/realtime 4.4.1 → 4.5.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/dist/base64.d.ts +3 -0
- package/dist/base64.d.ts.map +1 -0
- package/dist/base64.js +16 -0
- package/dist/base64.js.map +1 -0
- package/dist/from-gemini-live.d.ts +67 -0
- package/dist/from-gemini-live.d.ts.map +1 -0
- package/dist/from-gemini-live.js +299 -0
- package/dist/from-gemini-live.js.map +1 -0
- package/dist/from-openai-realtime.d.ts +49 -0
- package/dist/from-openai-realtime.d.ts.map +1 -0
- package/dist/from-openai-realtime.js +80 -0
- package/dist/from-openai-realtime.js.map +1 -0
- package/dist/gemini-translate.d.ts +17 -0
- package/dist/gemini-translate.d.ts.map +1 -0
- package/dist/gemini-translate.js +89 -0
- package/dist/gemini-translate.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/openai-compatible-realtime.d.ts +37 -0
- package/dist/openai-compatible-realtime.d.ts.map +1 -0
- package/dist/openai-compatible-realtime.js +416 -0
- package/dist/openai-compatible-realtime.js.map +1 -0
- package/dist/realtime-adapter.d.ts +100 -0
- package/dist/realtime-adapter.d.ts.map +1 -0
- package/dist/realtime-adapter.js +3 -0
- package/dist/realtime-adapter.js.map +1 -0
- package/dist/realtime-bridge.d.ts +130 -0
- package/dist/realtime-bridge.d.ts.map +1 -0
- package/dist/realtime-bridge.js +659 -0
- package/dist/realtime-bridge.js.map +1 -0
- package/dist/realtime-event-stream.d.ts +16 -0
- package/dist/realtime-event-stream.d.ts.map +1 -0
- package/dist/realtime-event-stream.js +47 -0
- package/dist/realtime-event-stream.js.map +1 -0
- package/package.json +13 -6
- package/src/edge-safety.test.ts +173 -0
- package/src/from-gemini-live.test.ts +366 -0
- package/src/from-openai-realtime.test.ts +769 -0
- package/src/gemini-translate.test.ts +82 -0
- package/src/openai-compatible-realtime.test.ts +293 -0
- package/src/realtime-bridge.test.ts +1573 -0
- package/src/workers-seam.test.ts +143 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
import { bytesToBase64, base64ToBytes } from "./base64.js";
|
|
3
|
+
const DEFAULT_MODEL = "gemini-3.5-live-translate-preview";
|
|
4
|
+
const OUTPUT_SAMPLE_RATE_HZ = 24_000;
|
|
5
|
+
export async function createGeminiTranslateSession(opts) {
|
|
6
|
+
const { GoogleGenAI, Modality } = await import("@google/genai");
|
|
7
|
+
const ai = new GoogleGenAI({
|
|
8
|
+
apiKey: opts.apiKey,
|
|
9
|
+
httpOptions: { apiVersion: "v1alpha" },
|
|
10
|
+
});
|
|
11
|
+
const session = await ai.live.connect({
|
|
12
|
+
model: DEFAULT_MODEL,
|
|
13
|
+
config: {
|
|
14
|
+
responseModalities: [Modality.AUDIO],
|
|
15
|
+
inputAudioTranscription: {},
|
|
16
|
+
outputAudioTranscription: {},
|
|
17
|
+
translationConfig: {
|
|
18
|
+
targetLanguageCode: opts.targetLanguageCode,
|
|
19
|
+
echoTargetLanguage: opts.echoTargetLanguage ?? true,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
callbacks: {
|
|
23
|
+
onmessage: (msg) => handleTranslateMessage(msg, opts),
|
|
24
|
+
onerror: (ev) => {
|
|
25
|
+
const cause = ev instanceof Error ? ev : new Error(String(ev));
|
|
26
|
+
opts.onError?.(cause);
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
// Gemini Live Translate needs ~100ms input chunks. Feeding the engine's native 20ms frames
|
|
31
|
+
// intermittently makes the model echo the SOURCE language instead of translating (~20-33%,
|
|
32
|
+
// verified deterministically via Deepgram detect_language). Coalesce to 100ms here so callers
|
|
33
|
+
// can keep sending 20ms frames. 100ms @ 16kHz PCM16 = 1600 samples = 3200 bytes (sample-aligned).
|
|
34
|
+
const INPUT_CHUNK_BYTES = 3200;
|
|
35
|
+
let buf = new Uint8Array(0);
|
|
36
|
+
const flushChunk = (chunk) => {
|
|
37
|
+
session.sendRealtimeInput({ audio: { data: bytesToBase64(chunk), mimeType: "audio/pcm;rate=16000" } });
|
|
38
|
+
};
|
|
39
|
+
const flushRemainder = () => {
|
|
40
|
+
if (buf.length > 0) {
|
|
41
|
+
flushChunk(buf);
|
|
42
|
+
buf = new Uint8Array(0);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
return {
|
|
46
|
+
sendAudio(pcm16) {
|
|
47
|
+
const merged = new Uint8Array(buf.length + pcm16.length);
|
|
48
|
+
merged.set(buf, 0);
|
|
49
|
+
merged.set(pcm16, buf.length);
|
|
50
|
+
buf = merged;
|
|
51
|
+
while (buf.length >= INPUT_CHUNK_BYTES) {
|
|
52
|
+
flushChunk(buf.subarray(0, INPUT_CHUNK_BYTES));
|
|
53
|
+
buf = buf.slice(INPUT_CHUNK_BYTES);
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
signalAudioStreamEnd() {
|
|
57
|
+
flushRemainder();
|
|
58
|
+
session.sendRealtimeInput({ audioStreamEnd: true });
|
|
59
|
+
},
|
|
60
|
+
async close() {
|
|
61
|
+
flushRemainder();
|
|
62
|
+
session.close();
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function handleTranslateMessage(msg, opts) {
|
|
67
|
+
const content = msg.serverContent;
|
|
68
|
+
if (!content)
|
|
69
|
+
return;
|
|
70
|
+
if (content.inputTranscription?.text && opts.onText) {
|
|
71
|
+
opts.onText(content.inputTranscription.text, "input", content.inputTranscription.finished ?? false);
|
|
72
|
+
}
|
|
73
|
+
if (content.outputTranscription?.text && opts.onText) {
|
|
74
|
+
opts.onText(content.outputTranscription.text, "output", content.outputTranscription.finished ?? false);
|
|
75
|
+
}
|
|
76
|
+
const parts = content.modelTurn?.parts;
|
|
77
|
+
if (!parts)
|
|
78
|
+
return;
|
|
79
|
+
for (const part of parts) {
|
|
80
|
+
const inline = part.inlineData;
|
|
81
|
+
if (inline?.data && inline.mimeType?.startsWith("audio/")) {
|
|
82
|
+
const rateMatch = /rate=(\d+)/.exec(inline.mimeType);
|
|
83
|
+
const sampleRateHz = rateMatch ? Number(rateMatch[1]) : OUTPUT_SAMPLE_RATE_HZ;
|
|
84
|
+
opts.onAudio(base64ToBytes(inline.data), sampleRateHz);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
export { DEFAULT_MODEL as GEMINI_TRANSLATE_MODEL };
|
|
89
|
+
//# sourceMappingURL=gemini-translate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini-translate.js","sourceRoot":"","sources":["../src/gemini-translate.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type { RealtimeAdapter, RealtimeEvent, RealtimeResumeMessage, RealtimeToolDef, } from "./realtime-adapter.js";
|
|
2
|
+
export { bytesToBase64, base64ToBytes } from "./base64.js";
|
|
3
|
+
export { createOpenAiCompatibleRealtimeAdapter, type OpenAiCompatibleRealtimeConfig, } from "./openai-compatible-realtime.js";
|
|
4
|
+
export { fromOpenAIRealtime, type OpenAIRealtimeOptions } from "./from-openai-realtime.js";
|
|
5
|
+
export { fromGeminiLive, type GeminiLiveOptions, type GeminiLiveSpeechConfig, type GeminiLiveTranscriptionOptions, } from "./from-gemini-live.js";
|
|
6
|
+
export { createGeminiTranslateSession, GEMINI_TRANSLATE_MODEL, type GeminiTranslateSession, type GeminiTranslateSessionOptions, } from "./gemini-translate.js";
|
|
7
|
+
export { RealtimeBridge, type DelegateResultEnvelope, type RealtimeBridgeOptions, } from "./realtime-bridge.js";
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,YAAY,EACV,eAAe,EACf,aAAa,EACb,qBAAqB,EACrB,eAAe,GAChB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EACL,qCAAqC,EACrC,KAAK,8BAA8B,GACpC,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,KAAK,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAC3F,OAAO,EACL,cAAc,EACd,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,EAC3B,KAAK,8BAA8B,GACpC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,4BAA4B,EAC5B,sBAAsB,EACtB,KAAK,sBAAsB,EAC3B,KAAK,6BAA6B,GACnC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,cAAc,EACd,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,GAC3B,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
export { bytesToBase64, base64ToBytes } from "./base64.js";
|
|
3
|
+
export { createOpenAiCompatibleRealtimeAdapter, } from "./openai-compatible-realtime.js";
|
|
4
|
+
export { fromOpenAIRealtime } from "./from-openai-realtime.js";
|
|
5
|
+
export { fromGeminiLive, } from "./from-gemini-live.js";
|
|
6
|
+
export { createGeminiTranslateSession, GEMINI_TRANSLATE_MODEL, } from "./gemini-translate.js";
|
|
7
|
+
export { RealtimeBridge, } from "./realtime-bridge.js";
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAQ/B,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EACL,qCAAqC,GAEtC,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAA8B,MAAM,2BAA2B,CAAC;AAC3F,OAAO,EACL,cAAc,GAIf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,4BAA4B,EAC5B,sBAAsB,GAGvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,cAAc,GAGf,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { SocketFactory } from "@kuralle-syrinx/ws";
|
|
2
|
+
import type { RealtimeAdapter, RealtimeEvent, RealtimeResumeMessage } from "./realtime-adapter.js";
|
|
3
|
+
export interface OpenAiCompatibleRealtimeConfig {
|
|
4
|
+
readonly apiKey: string;
|
|
5
|
+
readonly socketFactory: SocketFactory;
|
|
6
|
+
readonly debug?: boolean;
|
|
7
|
+
readonly debugLogPrefix?: string;
|
|
8
|
+
readonly defaultModel: string;
|
|
9
|
+
readonly model?: string;
|
|
10
|
+
readonly url?: () => string;
|
|
11
|
+
readonly buildUrl?: (model: string) => string;
|
|
12
|
+
readonly caps: RealtimeAdapter["caps"];
|
|
13
|
+
readonly buildSessionUpdate: () => Record<string, unknown>;
|
|
14
|
+
/**
|
|
15
|
+
* Optional fields merged into `session.update.session` after `buildSessionUpdate()`.
|
|
16
|
+
* Use for provider-specific knobs the adapter does not enumerate (mirrors TTS `extra_body`).
|
|
17
|
+
*/
|
|
18
|
+
readonly sessionExtra?: Record<string, unknown> | (() => Record<string, unknown>);
|
|
19
|
+
/**
|
|
20
|
+
* G4 resume-by-replay: returns the prior conversation to re-create as
|
|
21
|
+
* `conversation.item.create` items after each (re)connect's `session.update` —
|
|
22
|
+
* these providers have no native resume, so the transcript is replayed. Item
|
|
23
|
+
* creation never triggers a response (no `response.create`), so a resumed
|
|
24
|
+
* session cannot double-answer (R6). Called on the initial connect AND every
|
|
25
|
+
* reconnect, so return the *current* durable history, not a snapshot.
|
|
26
|
+
*/
|
|
27
|
+
readonly buildResumeItems?: () => readonly RealtimeResumeMessage[];
|
|
28
|
+
readonly supportsTruncate: boolean;
|
|
29
|
+
readonly requiresResponseCreateAfterToolOutput?: boolean;
|
|
30
|
+
readonly defaultErrorMessage: string;
|
|
31
|
+
readonly extendServerMessage?: (type: string, msg: Record<string, unknown>, ctx: {
|
|
32
|
+
push: (event: RealtimeEvent) => void;
|
|
33
|
+
caps: RealtimeAdapter["caps"];
|
|
34
|
+
}) => boolean;
|
|
35
|
+
}
|
|
36
|
+
export declare function createOpenAiCompatibleRealtimeAdapter(config: OpenAiCompatibleRealtimeConfig): RealtimeAdapter;
|
|
37
|
+
//# sourceMappingURL=openai-compatible-realtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-compatible-realtime.d.ts","sourceRoot":"","sources":["../src/openai-compatible-realtime.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAKxD,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,qBAAqB,EAAiB,MAAM,uBAAuB,CAAC;AAElH,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC9C,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;IACvC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3D;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAClF;;;;;;;OAOG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,SAAS,qBAAqB,EAAE,CAAC;IACnE,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;IACnC,QAAQ,CAAC,qCAAqC,CAAC,EAAE,OAAO,CAAC;IACzD,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAC7B,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,GAAG,EAAE;QACH,IAAI,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;QACrC,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;KAC/B,KACE,OAAO,CAAC;CACd;AA8aD,wBAAgB,qCAAqC,CACnD,MAAM,EAAE,8BAA8B,GACrC,eAAe,CAEjB"}
|
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
import { RealtimeSocket } from "@kuralle-syrinx/ws/realtime";
|
|
3
|
+
import { base64ToBytes, bytesToBase64 } from "./base64.js";
|
|
4
|
+
import { RealtimeEventStream } from "./realtime-event-stream.js";
|
|
5
|
+
class OpenAiCompatibleRealtimeAdapter {
|
|
6
|
+
config;
|
|
7
|
+
caps;
|
|
8
|
+
events;
|
|
9
|
+
stream = new RealtimeEventStream();
|
|
10
|
+
socket = null;
|
|
11
|
+
abortHandler = null;
|
|
12
|
+
openResolver = null;
|
|
13
|
+
openRejecter = null;
|
|
14
|
+
currentAssistantItemId = null;
|
|
15
|
+
assistantTranscript = "";
|
|
16
|
+
activeResponse = false;
|
|
17
|
+
pendingResponseCreate = false;
|
|
18
|
+
opened = false;
|
|
19
|
+
constructor(config) {
|
|
20
|
+
this.config = config;
|
|
21
|
+
this.events = this.stream;
|
|
22
|
+
this.caps = config.caps;
|
|
23
|
+
}
|
|
24
|
+
async open(signal) {
|
|
25
|
+
const model = this.config.model ?? this.config.defaultModel;
|
|
26
|
+
const url = this.config.url ??
|
|
27
|
+
(this.config.buildUrl
|
|
28
|
+
? () => this.config.buildUrl(model)
|
|
29
|
+
: () => `wss://api.openai.com/v1/realtime?model=${encodeURIComponent(model)}`);
|
|
30
|
+
this.socket = new RealtimeSocket({
|
|
31
|
+
url,
|
|
32
|
+
headers: {
|
|
33
|
+
Authorization: `Bearer ${this.config.apiKey}`,
|
|
34
|
+
},
|
|
35
|
+
socketFactory: this.config.socketFactory,
|
|
36
|
+
onMessage: (json) => this.handleServerMessage(json),
|
|
37
|
+
// Re-applied on EVERY (re)connection. WebSocketConnection auto-reconnects after a mid-call
|
|
38
|
+
// drop; without re-sending session.update the fresh provider session comes back with no
|
|
39
|
+
// tools and default instructions — the front model silently loses its persona and the
|
|
40
|
+
// delegate tool (delegation permanently dead). onReady fires after the socket is verified
|
|
41
|
+
// and before replay frames flush, so config lands ahead of any buffered audio.
|
|
42
|
+
onReady: () => this.applySessionConfig(),
|
|
43
|
+
onConnectionLost: (err) => {
|
|
44
|
+
this.stream.push({ type: "error", cause: err, recoverable: true });
|
|
45
|
+
this.rejectOpen(err);
|
|
46
|
+
},
|
|
47
|
+
onUnrecoverable: (err) => {
|
|
48
|
+
this.stream.push({ type: "error", cause: err, recoverable: false });
|
|
49
|
+
this.rejectOpen(err);
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
const openPromise = new Promise((resolve, reject) => {
|
|
53
|
+
this.openResolver = resolve;
|
|
54
|
+
this.openRejecter = reject;
|
|
55
|
+
});
|
|
56
|
+
this.abortHandler = () => {
|
|
57
|
+
void this.close();
|
|
58
|
+
this.rejectOpen(new Error("Realtime adapter open aborted"));
|
|
59
|
+
};
|
|
60
|
+
signal.addEventListener("abort", this.abortHandler, { once: true });
|
|
61
|
+
// connect() invokes onReady synchronously once the socket is open, which sends the first
|
|
62
|
+
// session.update; every subsequent reconnect re-invokes onReady and re-applies it.
|
|
63
|
+
await this.socket.connect();
|
|
64
|
+
await openPromise;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* (Re)configure the provider session — model, audio formats, turn detection, tools,
|
|
68
|
+
* instructions. Fired on the initial connect and on every reconnect. On a reconnect the provider
|
|
69
|
+
* session is brand new: config + tools are restored here, but the prior conversation history is
|
|
70
|
+
* gone, so surface that as a recoverable error rather than silently continuing amnesiac.
|
|
71
|
+
*/
|
|
72
|
+
applySessionConfig() {
|
|
73
|
+
const reconnected = this.opened;
|
|
74
|
+
this.opened = true;
|
|
75
|
+
const session = this.config.buildSessionUpdate();
|
|
76
|
+
const extra = typeof this.config.sessionExtra === "function"
|
|
77
|
+
? this.config.sessionExtra()
|
|
78
|
+
: this.config.sessionExtra;
|
|
79
|
+
this.socket?.send({
|
|
80
|
+
type: "session.update",
|
|
81
|
+
session: extra ? { ...session, ...extra } : session,
|
|
82
|
+
});
|
|
83
|
+
// G4 resume-by-replay: re-create the prior conversation as items. Providers
|
|
84
|
+
// without native resume start every (re)connection amnesiac; replaying the
|
|
85
|
+
// transcript here restores context. No response.create — replay must never
|
|
86
|
+
// make the model speak (R6).
|
|
87
|
+
const resumeItems = this.config.buildResumeItems?.() ?? [];
|
|
88
|
+
for (const message of resumeItems) {
|
|
89
|
+
this.socket?.send({
|
|
90
|
+
type: "conversation.item.create",
|
|
91
|
+
item: {
|
|
92
|
+
type: "message",
|
|
93
|
+
role: message.role,
|
|
94
|
+
content: [
|
|
95
|
+
message.role === "user"
|
|
96
|
+
? { type: "input_text", text: message.content }
|
|
97
|
+
: { type: "text", text: message.content },
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
if (reconnected && !this.config.buildResumeItems) {
|
|
103
|
+
this.stream.push({
|
|
104
|
+
type: "error",
|
|
105
|
+
cause: new Error("Realtime session reconnected: model config and tools restored, but prior conversation history was lost"),
|
|
106
|
+
recoverable: true,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
sendAudio(pcm16) {
|
|
111
|
+
this.requireSocket().send({
|
|
112
|
+
type: "input_audio_buffer.append",
|
|
113
|
+
audio: bytesToBase64(pcm16),
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
sendText(text) {
|
|
117
|
+
const socket = this.requireSocket();
|
|
118
|
+
socket.send({
|
|
119
|
+
type: "conversation.item.create",
|
|
120
|
+
item: {
|
|
121
|
+
type: "message",
|
|
122
|
+
role: "user",
|
|
123
|
+
content: [{ type: "input_text", text }],
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
this.requestResponseCreate();
|
|
127
|
+
}
|
|
128
|
+
injectContext(text) {
|
|
129
|
+
this.requireSocket().send({
|
|
130
|
+
type: "conversation.item.create",
|
|
131
|
+
item: {
|
|
132
|
+
type: "message",
|
|
133
|
+
role: "system",
|
|
134
|
+
content: [{ type: "input_text", text }],
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
requestResponse() {
|
|
139
|
+
this.requireSocket().send({ type: "input_audio_buffer.commit" });
|
|
140
|
+
this.requestResponseCreate();
|
|
141
|
+
}
|
|
142
|
+
cancelResponse(audioEndMs) {
|
|
143
|
+
if (!this.activeResponse)
|
|
144
|
+
return;
|
|
145
|
+
const socket = this.requireSocket();
|
|
146
|
+
socket.send({ type: "response.cancel" });
|
|
147
|
+
if (this.config.supportsTruncate && this.currentAssistantItemId) {
|
|
148
|
+
socket.send({
|
|
149
|
+
type: "conversation.item.truncate",
|
|
150
|
+
item_id: this.currentAssistantItemId,
|
|
151
|
+
content_index: 0,
|
|
152
|
+
audio_end_ms: audioEndMs,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
if (this.config.supportsTruncate) {
|
|
156
|
+
this.currentAssistantItemId = null;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
injectToolResult(toolId, text) {
|
|
160
|
+
const socket = this.requireSocket();
|
|
161
|
+
socket.send({
|
|
162
|
+
type: "conversation.item.create",
|
|
163
|
+
item: {
|
|
164
|
+
type: "function_call_output",
|
|
165
|
+
call_id: toolId,
|
|
166
|
+
output: text,
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
if (this.config.requiresResponseCreateAfterToolOutput !== false) {
|
|
170
|
+
this.requestResponseCreate();
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
async close() {
|
|
174
|
+
await this.socket?.close();
|
|
175
|
+
this.socket = null;
|
|
176
|
+
this.stream.close();
|
|
177
|
+
}
|
|
178
|
+
requestResponseCreate() {
|
|
179
|
+
if (this.activeResponse) {
|
|
180
|
+
this.pendingResponseCreate = true;
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
this.requireSocket().send({ type: "response.create" });
|
|
184
|
+
this.pendingResponseCreate = false;
|
|
185
|
+
}
|
|
186
|
+
completeResponse() {
|
|
187
|
+
this.activeResponse = false;
|
|
188
|
+
if (this.config.supportsTruncate) {
|
|
189
|
+
this.currentAssistantItemId = null;
|
|
190
|
+
}
|
|
191
|
+
if (this.pendingResponseCreate) {
|
|
192
|
+
this.pendingResponseCreate = false;
|
|
193
|
+
this.requireSocket().send({ type: "response.create" });
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
requireSocket() {
|
|
197
|
+
if (!this.socket)
|
|
198
|
+
throw new Error("Realtime adapter is not open");
|
|
199
|
+
return this.socket;
|
|
200
|
+
}
|
|
201
|
+
rejectOpen(err) {
|
|
202
|
+
this.openRejecter?.(err);
|
|
203
|
+
this.openResolver = null;
|
|
204
|
+
this.openRejecter = null;
|
|
205
|
+
}
|
|
206
|
+
resolveOpen() {
|
|
207
|
+
this.openResolver?.();
|
|
208
|
+
this.openResolver = null;
|
|
209
|
+
this.openRejecter = null;
|
|
210
|
+
}
|
|
211
|
+
handleServerMessage(json) {
|
|
212
|
+
let msg;
|
|
213
|
+
try {
|
|
214
|
+
msg = JSON.parse(json);
|
|
215
|
+
}
|
|
216
|
+
catch (err) {
|
|
217
|
+
this.stream.push({
|
|
218
|
+
type: "error",
|
|
219
|
+
cause: err instanceof Error ? err : new Error(String(err)),
|
|
220
|
+
recoverable: false,
|
|
221
|
+
});
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
const type = typeof msg["type"] === "string" ? msg["type"] : "";
|
|
225
|
+
if (this.config.debug) {
|
|
226
|
+
console.error(`${this.config.debugLogPrefix ?? "[raw]"} ${type}`);
|
|
227
|
+
}
|
|
228
|
+
if (this.config.extendServerMessage?.(type, msg, { push: (e) => this.stream.push(e), caps: this.caps })) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
switch (type) {
|
|
232
|
+
case "session.created":
|
|
233
|
+
case "session.updated":
|
|
234
|
+
this.resolveOpen();
|
|
235
|
+
break;
|
|
236
|
+
case "response.created":
|
|
237
|
+
this.assistantTranscript = "";
|
|
238
|
+
if (this.config.supportsTruncate) {
|
|
239
|
+
this.currentAssistantItemId = null;
|
|
240
|
+
}
|
|
241
|
+
this.activeResponse = true;
|
|
242
|
+
this.stream.push({ type: "response_started" });
|
|
243
|
+
break;
|
|
244
|
+
case "response.output_item.added": {
|
|
245
|
+
if (!this.config.supportsTruncate)
|
|
246
|
+
break;
|
|
247
|
+
const item = msg["item"];
|
|
248
|
+
if (item && typeof item === "object") {
|
|
249
|
+
const record = item;
|
|
250
|
+
if (record["type"] === "message" && typeof record["id"] === "string") {
|
|
251
|
+
this.currentAssistantItemId = record["id"];
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
break;
|
|
255
|
+
}
|
|
256
|
+
case "response.output_audio.delta": {
|
|
257
|
+
const delta = msg["delta"];
|
|
258
|
+
if (typeof delta === "string" && delta.length > 0) {
|
|
259
|
+
this.stream.push({
|
|
260
|
+
type: "audio",
|
|
261
|
+
pcm16: base64ToBytes(delta),
|
|
262
|
+
sampleRateHz: this.caps.outputSampleRateHz,
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
case "input_audio_buffer.speech_started":
|
|
268
|
+
this.stream.push({ type: "speech_started" });
|
|
269
|
+
break;
|
|
270
|
+
case "input_audio_buffer.speech_stopped":
|
|
271
|
+
this.stream.push({ type: "speech_stopped" });
|
|
272
|
+
break;
|
|
273
|
+
case "response.output_audio_transcript.delta": {
|
|
274
|
+
const delta = msg["delta"];
|
|
275
|
+
if (typeof delta === "string" && delta.length > 0) {
|
|
276
|
+
this.assistantTranscript += delta;
|
|
277
|
+
this.stream.push({
|
|
278
|
+
type: "transcript",
|
|
279
|
+
role: "assistant",
|
|
280
|
+
text: delta,
|
|
281
|
+
final: false,
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
case "response.output_audio_transcript.done": {
|
|
287
|
+
const transcript = typeof msg["transcript"] === "string" ? msg["transcript"] : this.assistantTranscript;
|
|
288
|
+
this.stream.push({
|
|
289
|
+
type: "transcript",
|
|
290
|
+
role: "assistant",
|
|
291
|
+
text: transcript,
|
|
292
|
+
final: true,
|
|
293
|
+
});
|
|
294
|
+
this.assistantTranscript = "";
|
|
295
|
+
break;
|
|
296
|
+
}
|
|
297
|
+
case "response.output_text.delta": {
|
|
298
|
+
const delta = msg["delta"];
|
|
299
|
+
if (typeof delta === "string" && delta.length > 0) {
|
|
300
|
+
this.assistantTranscript += delta;
|
|
301
|
+
this.stream.push({
|
|
302
|
+
type: "transcript",
|
|
303
|
+
role: "assistant",
|
|
304
|
+
text: delta,
|
|
305
|
+
final: false,
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
break;
|
|
309
|
+
}
|
|
310
|
+
case "response.output_text.done": {
|
|
311
|
+
const t = typeof msg["text"] === "string" ? msg["text"] : this.assistantTranscript;
|
|
312
|
+
this.stream.push({
|
|
313
|
+
type: "transcript",
|
|
314
|
+
role: "assistant",
|
|
315
|
+
text: t,
|
|
316
|
+
final: true,
|
|
317
|
+
});
|
|
318
|
+
this.assistantTranscript = "";
|
|
319
|
+
break;
|
|
320
|
+
}
|
|
321
|
+
case "conversation.item.input_audio_transcription.completed": {
|
|
322
|
+
// User-side transcript (requires input transcription enabled in session config).
|
|
323
|
+
const transcript = typeof msg["transcript"] === "string" ? msg["transcript"] : "";
|
|
324
|
+
if (transcript.trim()) {
|
|
325
|
+
this.stream.push({ type: "transcript", role: "user", text: transcript, final: true });
|
|
326
|
+
}
|
|
327
|
+
break;
|
|
328
|
+
}
|
|
329
|
+
case "response.done": {
|
|
330
|
+
this.completeResponse();
|
|
331
|
+
const toolCall = extractFunctionCall(msg["response"]);
|
|
332
|
+
if (toolCall) {
|
|
333
|
+
this.stream.push(toolCall);
|
|
334
|
+
}
|
|
335
|
+
// response.usage is snake_case token counts; forward so the bridge can meter
|
|
336
|
+
// the native front (previously native turns produced NO usage at all).
|
|
337
|
+
const usage = extractRealtimeUsage(msg["response"]);
|
|
338
|
+
this.stream.push(usage ? { type: "response_done", usage } : { type: "response_done" });
|
|
339
|
+
break;
|
|
340
|
+
}
|
|
341
|
+
case "error": {
|
|
342
|
+
const errObj = msg["error"];
|
|
343
|
+
const message = errObj && typeof errObj === "object" && typeof errObj["message"] === "string"
|
|
344
|
+
? String(errObj["message"])
|
|
345
|
+
: this.config.defaultErrorMessage;
|
|
346
|
+
const code = errObj && typeof errObj === "object" ? errObj["code"] : undefined;
|
|
347
|
+
// A `response.cancel` that raced a just-completed response ("no active response found")
|
|
348
|
+
// is benign — the cancel is a server-side no-op. This is the multi-turn barge-in cancel
|
|
349
|
+
// race (a new turn's speech_started fires a cancel as the prior response completes). Do
|
|
350
|
+
// NOT surface it: it would trip strict consumers and pollute error-rate monitoring.
|
|
351
|
+
const codeStr = typeof code === "string" ? code : "";
|
|
352
|
+
if (codeStr === "response_cancel_not_active" || /no active response|cancellation failed/i.test(message)) {
|
|
353
|
+
break;
|
|
354
|
+
}
|
|
355
|
+
const recoverable = code !== "invalid_api_key" && code !== "authentication_failed";
|
|
356
|
+
this.stream.push({
|
|
357
|
+
type: "error",
|
|
358
|
+
cause: new Error(message),
|
|
359
|
+
recoverable,
|
|
360
|
+
});
|
|
361
|
+
break;
|
|
362
|
+
}
|
|
363
|
+
default:
|
|
364
|
+
break;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
/** Pull snake_case token counts off a realtime response.usage object, when present. */
|
|
369
|
+
function extractRealtimeUsage(response) {
|
|
370
|
+
if (!response || typeof response !== "object")
|
|
371
|
+
return undefined;
|
|
372
|
+
const usage = response["usage"];
|
|
373
|
+
if (!usage || typeof usage !== "object")
|
|
374
|
+
return undefined;
|
|
375
|
+
const u = usage;
|
|
376
|
+
const num = (v) => (typeof v === "number" ? v : undefined);
|
|
377
|
+
const out = {
|
|
378
|
+
...(num(u["input_tokens"]) !== undefined ? { inputTokens: num(u["input_tokens"]) } : {}),
|
|
379
|
+
...(num(u["output_tokens"]) !== undefined ? { outputTokens: num(u["output_tokens"]) } : {}),
|
|
380
|
+
...(num(u["total_tokens"]) !== undefined ? { totalTokens: num(u["total_tokens"]) } : {}),
|
|
381
|
+
};
|
|
382
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
383
|
+
}
|
|
384
|
+
function extractFunctionCall(response) {
|
|
385
|
+
if (!response || typeof response !== "object")
|
|
386
|
+
return null;
|
|
387
|
+
const output = response["output"];
|
|
388
|
+
if (!Array.isArray(output))
|
|
389
|
+
return null;
|
|
390
|
+
for (const item of output) {
|
|
391
|
+
if (!item || typeof item !== "object")
|
|
392
|
+
continue;
|
|
393
|
+
const record = item;
|
|
394
|
+
if (record["type"] !== "function_call")
|
|
395
|
+
continue;
|
|
396
|
+
const toolId = typeof record["call_id"] === "string" ? record["call_id"] : "";
|
|
397
|
+
const toolName = typeof record["name"] === "string" ? record["name"] : "";
|
|
398
|
+
const argsRaw = typeof record["arguments"] === "string" ? record["arguments"] : "{}";
|
|
399
|
+
if (!toolId || !toolName)
|
|
400
|
+
continue;
|
|
401
|
+
let args;
|
|
402
|
+
try {
|
|
403
|
+
const parsed = JSON.parse(argsRaw);
|
|
404
|
+
args = parsed && typeof parsed === "object" ? parsed : {};
|
|
405
|
+
}
|
|
406
|
+
catch {
|
|
407
|
+
args = {};
|
|
408
|
+
}
|
|
409
|
+
return { type: "tool_call", toolId, toolName, args };
|
|
410
|
+
}
|
|
411
|
+
return null;
|
|
412
|
+
}
|
|
413
|
+
export function createOpenAiCompatibleRealtimeAdapter(config) {
|
|
414
|
+
return new OpenAiCompatibleRealtimeAdapter(config);
|
|
415
|
+
}
|
|
416
|
+
//# sourceMappingURL=openai-compatible-realtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-compatible-realtime.js","sourceRoot":"","sources":["../src/openai-compatible-realtime.ts"],"names":[],"mappings":"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"}
|