@kuralle-syrinx/realtime 4.4.0 → 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.
Files changed (44) hide show
  1. package/dist/base64.d.ts +3 -0
  2. package/dist/base64.d.ts.map +1 -0
  3. package/dist/base64.js +16 -0
  4. package/dist/base64.js.map +1 -0
  5. package/dist/from-gemini-live.d.ts +67 -0
  6. package/dist/from-gemini-live.d.ts.map +1 -0
  7. package/dist/from-gemini-live.js +299 -0
  8. package/dist/from-gemini-live.js.map +1 -0
  9. package/dist/from-openai-realtime.d.ts +49 -0
  10. package/dist/from-openai-realtime.d.ts.map +1 -0
  11. package/dist/from-openai-realtime.js +80 -0
  12. package/dist/from-openai-realtime.js.map +1 -0
  13. package/dist/gemini-translate.d.ts +17 -0
  14. package/dist/gemini-translate.d.ts.map +1 -0
  15. package/dist/gemini-translate.js +89 -0
  16. package/dist/gemini-translate.js.map +1 -0
  17. package/dist/index.d.ts +8 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +8 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/openai-compatible-realtime.d.ts +37 -0
  22. package/dist/openai-compatible-realtime.d.ts.map +1 -0
  23. package/dist/openai-compatible-realtime.js +416 -0
  24. package/dist/openai-compatible-realtime.js.map +1 -0
  25. package/dist/realtime-adapter.d.ts +100 -0
  26. package/dist/realtime-adapter.d.ts.map +1 -0
  27. package/dist/realtime-adapter.js +3 -0
  28. package/dist/realtime-adapter.js.map +1 -0
  29. package/dist/realtime-bridge.d.ts +130 -0
  30. package/dist/realtime-bridge.d.ts.map +1 -0
  31. package/dist/realtime-bridge.js +659 -0
  32. package/dist/realtime-bridge.js.map +1 -0
  33. package/dist/realtime-event-stream.d.ts +16 -0
  34. package/dist/realtime-event-stream.d.ts.map +1 -0
  35. package/dist/realtime-event-stream.js +47 -0
  36. package/dist/realtime-event-stream.js.map +1 -0
  37. package/package.json +13 -6
  38. package/src/edge-safety.test.ts +173 -0
  39. package/src/from-gemini-live.test.ts +366 -0
  40. package/src/from-openai-realtime.test.ts +769 -0
  41. package/src/gemini-translate.test.ts +82 -0
  42. package/src/openai-compatible-realtime.test.ts +293 -0
  43. package/src/realtime-bridge.test.ts +1573 -0
  44. package/src/workers-seam.test.ts +143 -0
@@ -0,0 +1,100 @@
1
+ export interface RealtimeAdapter {
2
+ readonly caps: {
3
+ readonly inputSampleRateHz: number;
4
+ readonly outputSampleRateHz: number;
5
+ readonly supportsConcurrentToolAudio: boolean;
6
+ readonly supportsTruncate: boolean;
7
+ readonly emitsServerSpeechStarted: boolean;
8
+ /**
9
+ * G4: the provider resumes a prior session server-side from a handle (Gemini Live
10
+ * `sessionResumption`). Absent/false → resuming requires the host to replay the
11
+ * transcript (e.g. OpenAI `resumeHistory`). A native-resume provider must NOT also
12
+ * be replayed — that would double-apply history (RFC bimodel-delegate-seam R6).
13
+ */
14
+ readonly supportsNativeResume?: boolean;
15
+ /** The front model owns full-duplex interaction decisions (turn-taking, barge-in). When true,
16
+ * Syrinx's InteractionPolicy runs observe-only and does not drive its own turn/interrupt decisions
17
+ * (RFC InteractionPolicy REQ-4). Absent/false → Syrinx drives. No current adapter sets this. */
18
+ readonly supportsFullDuplex?: boolean;
19
+ /** The front emits its own backchannels ("mhmm"). When true, Syrinx suppresses its own backchannel
20
+ * cues (RFC InteractionPolicy REQ-4). Absent/false → Syrinx may emit. */
21
+ readonly emitsBackchannel?: boolean;
22
+ /** Half-cascade: provider can run text-only modality (`modalities:["text"]`) so Syrinx TTS
23
+ * drives speech from assistant transcript events. Absent/false → no text-only half-cascade. */
24
+ readonly supportsTextOnlyModality?: boolean;
25
+ };
26
+ open(signal: AbortSignal): Promise<void>;
27
+ sendAudio(pcm16: Uint8Array): void;
28
+ /**
29
+ * Send a typed user turn to the front model and request a response. Optional: adapters whose
30
+ * provider cannot accept text input omit it, and the bridge silently ignores typed turns for them.
31
+ */
32
+ sendText?(text: string): void;
33
+ /** Inject transient context without requesting a provider response. */
34
+ injectContext?(text: string): void;
35
+ /**
36
+ * Commit any buffered user input and request a response. For Syrinx-OWNED turn detection
37
+ * (provider server VAD disabled via turnDetection:null): the host calls this when its own
38
+ * endpointing (InteractionPolicy / VAD) signals end-of-turn. Optional — adapters without
39
+ * manual turn control omit it.
40
+ */
41
+ requestResponse?(): void;
42
+ cancelResponse(audioEndMs: number): void;
43
+ injectToolResult(toolId: string, text: string): void;
44
+ /** Close the provider socket and end the event stream. */
45
+ close(): Promise<void>;
46
+ readonly events: AsyncIterable<RealtimeEvent>;
47
+ }
48
+ /**
49
+ * A function tool advertised to the front model so it can decide when to delegate. Domain-neutral:
50
+ * the caller (example/app) supplies these — the provider adapter never hardcodes any tool.
51
+ */
52
+ export interface RealtimeToolDef {
53
+ readonly name: string;
54
+ readonly description: string;
55
+ /** JSON Schema for the tool arguments. */
56
+ readonly parameters: Record<string, unknown>;
57
+ }
58
+ /** A prior-conversation message replayed into a front model on resume (G4). */
59
+ export interface RealtimeResumeMessage {
60
+ readonly role: "user" | "assistant";
61
+ readonly content: string;
62
+ }
63
+ /** Token usage a realtime provider reports on response completion (e.g. OpenAI response.done). */
64
+ export interface RealtimeUsage {
65
+ readonly inputTokens?: number;
66
+ readonly outputTokens?: number;
67
+ readonly totalTokens?: number;
68
+ }
69
+ export type RealtimeEvent = {
70
+ type: "audio";
71
+ pcm16: Uint8Array;
72
+ sampleRateHz: number;
73
+ } | {
74
+ type: "speech_started";
75
+ } | {
76
+ type: "speech_stopped";
77
+ } | {
78
+ type: "transcript";
79
+ role: "user" | "assistant";
80
+ text: string;
81
+ final: boolean;
82
+ } | {
83
+ type: "tool_call";
84
+ toolId: string;
85
+ toolName: string;
86
+ args: Record<string, unknown>;
87
+ } | {
88
+ type: "response_started";
89
+ } | {
90
+ type: "response_done";
91
+ usage?: RealtimeUsage;
92
+ } | {
93
+ type: "resumption_handle";
94
+ handle: string;
95
+ } | {
96
+ type: "error";
97
+ cause: Error;
98
+ recoverable: boolean;
99
+ };
100
+ //# sourceMappingURL=realtime-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime-adapter.d.ts","sourceRoot":"","sources":["../src/realtime-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ // SPDX-License-Identifier: MIT
2
+ export {};
3
+ //# sourceMappingURL=realtime-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime-adapter.js","sourceRoot":"","sources":["../src/realtime-adapter.ts"],"names":[],"mappings":"AAAA,+BAA+B"}
@@ -0,0 +1,130 @@
1
+ import { type PipelineBus, type PluginConfig, type Reasoner, type ReasonerMessage, type VoicePlugin } from "@kuralle-syrinx/core";
2
+ import type { RealtimeAdapter } from "./realtime-adapter.js";
3
+ /**
4
+ * G1 — the structured delegate-result envelope (RFC bimodel-delegate-seam §4).
5
+ * The bridge wraps the accumulated reasoner answer in this JSON shape before
6
+ * `injectToolResult`, so the front model treats it as authoritative tool data
7
+ * and repeats it faithfully instead of paraphrasing or inventing facts. Field
8
+ * names mirror OpenAI's Realtime Prompting Guide "Tool Output Formatting"
9
+ * (`response_text` + `require_repeat_verbatim`) — the only field-validated
10
+ * envelope shape, and gpt-realtime is the primary front (OQ1).
11
+ */
12
+ export interface DelegateResultEnvelope {
13
+ /** The authoritative answer — the front model's ONLY source of facts for the turn. */
14
+ readonly response_text: string;
15
+ readonly require_repeat_verbatim: true;
16
+ /** Optional app directive the front prompt keys on, e.g. "translate_faithfully". */
17
+ readonly render?: string;
18
+ }
19
+ export interface RealtimeBridgeOptions {
20
+ readonly debug?: boolean;
21
+ /**
22
+ * How the delegate answer reaches the front model at `injectToolResult` time.
23
+ * `"envelope"` (default) wraps it as a {@link DelegateResultEnvelope}; `"string"`
24
+ * injects the raw answer (pre-envelope behavior). The envelope is applied to the
25
+ * already-buffered delegate answer — a synchronous JSON.stringify, no added latency
26
+ * (R2) — and never touches the cascade text-delta path. Bus packets
27
+ * (`llm.tool_result`, `delegate.result`) always carry the raw answer.
28
+ */
29
+ readonly toolResultFormat?: "envelope" | "string";
30
+ /**
31
+ * Optional `render` directive included in the envelope (e.g. `"translate_faithfully"`),
32
+ * for front prompts that key a rendering rule on it. Ignored with `toolResultFormat: "string"`.
33
+ */
34
+ readonly renderDirective?: string;
35
+ /**
36
+ * Supplies prior conversation context for delegate Reasoner turns. When omitted the delegate is
37
+ * stateless — each tool call receives only the query extracted from the front-model tool args.
38
+ */
39
+ readonly contextProvider?: () => readonly ReasonerMessage[];
40
+ /**
41
+ * Name of the front-model tool argument that carries the user's query for the delegate Reasoner.
42
+ * Must match the argument name in the registered delegate tool's schema. Defaults to "query".
43
+ */
44
+ readonly delegateQueryArg?: string;
45
+ /**
46
+ * Handle a front-model tool call whose name is NOT the delegate tool — front-level tools like
47
+ * `wait_for_user`, `escalate_to_human`, or `finish_session` that must not hit the reasoner.
48
+ * Return the string to inject back to the front model as the tool result (default `""`). When
49
+ * omitted, a non-delegate tool call remains a recoverable error (the prior behavior).
50
+ */
51
+ readonly onFrontToolCall?: (call: {
52
+ readonly toolId: string;
53
+ readonly toolName: string;
54
+ readonly args: Record<string, unknown>;
55
+ }) => string | undefined | Promise<string | undefined>;
56
+ /**
57
+ * Half-cascade text-only mode: stream assistant transcript into the cascade
58
+ * `llm.delta → segmenter → tts.text` path and ignore provider audio.
59
+ * REQUIRES a TTS plugin registered on the session bus (the bridge does not own the registry).
60
+ */
61
+ readonly textOnly?: boolean;
62
+ /**
63
+ * Syrinx-owned turn detection (REQ-6): on `eos.turn_complete`, call
64
+ * `adapter.requestResponse` so Syrinx endpointing/VAD/InteractionPolicy drives
65
+ * the provider response instead of server VAD.
66
+ *
67
+ * MUST be paired with `turnDetection: null` on the adapter — otherwise the
68
+ * provider's server VAD and Syrinx would BOTH trigger responses (double-turn).
69
+ * Native mode (`syrinxTurns` absent/false) is unchanged.
70
+ */
71
+ readonly syrinxTurns?: boolean;
72
+ }
73
+ export declare class RealtimeBridge implements VoicePlugin {
74
+ private readonly adapter;
75
+ private readonly reasoner?;
76
+ private readonly delegateToolName;
77
+ private readonly opts;
78
+ private bus;
79
+ private contextId;
80
+ private turnUserText;
81
+ /** Authoritative full assistant transcript(s) — providers that emit a final transcript (OpenAI). */
82
+ private turnAssistantText;
83
+ /** Concatenated streamed transcript fragments — providers that emit deltas only, no final (Gemini Live). */
84
+ private turnAssistantDeltas;
85
+ private pendingSpeechEndedAtMs;
86
+ private sessionAbort;
87
+ private inflight;
88
+ private delegateTask;
89
+ private playedMs;
90
+ private audioRemainder;
91
+ private readonly disposers;
92
+ constructor(adapter: RealtimeAdapter, reasoner?: Reasoner | undefined, delegateToolName?: string, opts?: RealtimeBridgeOptions);
93
+ injectContext(text: string): void;
94
+ initialize(bus: PipelineBus, _cfg: PluginConfig): Promise<void>;
95
+ close(): Promise<void>;
96
+ private pump;
97
+ private handleEvent;
98
+ private handleToolCall;
99
+ private handleFrontTool;
100
+ /**
101
+ * Start the reasoner delegate OFF the serial event pump. The pump must keep draining adapter
102
+ * events during the multi-second reasoner "thinking gap" — above all `speech_started`, so a
103
+ * barge-in mid-delegate still fires `interrupt.detected` and (via `interrupt.tts`) aborts the
104
+ * now-unwanted delegate before its answer is voiced over the user. Awaiting the delegate inside
105
+ * the pump loop (the old shape) froze barge-in for the entire gap. `runDelegate` sets
106
+ * `this.inflight` synchronously before its first await, so a subsequently-pumped barge-in sees
107
+ * a live controller to abort.
108
+ */
109
+ private dispatchDelegate;
110
+ private runDelegate;
111
+ /** G1: wrap the buffered delegate answer for the front model (synchronous — R2). */
112
+ private formatToolResult;
113
+ private onSpeechStarted;
114
+ private onSpeechStopped;
115
+ private onResponseStarted;
116
+ private onAudio;
117
+ private onFinalTranscript;
118
+ /**
119
+ * textOnly: stream assistant transcript into the cascade LLM→segmenter→TTS path.
120
+ * Non-final deltas drive `llm.delta` immediately (no buffer). Final emits `llm.done` only —
121
+ * the C0 adapter's final carries the full accumulated text, so re-emitting as delta would
122
+ * duplicate every streamed fragment.
123
+ */
124
+ private onTextOnlyAssistantTranscript;
125
+ private onResponseDone;
126
+ private emitCoalescedAudio;
127
+ private pushAudioFrame;
128
+ private onError;
129
+ }
130
+ //# sourceMappingURL=realtime-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime-bridge.d.ts","sourceRoot":"","sources":["../src/realtime-bridge.ts"],"names":[],"mappings":"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"}