@theoremjs/web 0.0.0-stage → 0.3.4-next.375.ga2d1878

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 (128) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +493 -2
  3. package/client/audio-level.d.ts +5 -0
  4. package/client/audio-level.js +24 -0
  5. package/client/chat.d.ts +144 -0
  6. package/client/chat.js +760 -0
  7. package/client/composer-drawer.d.ts +19 -0
  8. package/client/composer-drawer.js +15 -0
  9. package/client/composer-hints.d.ts +25 -0
  10. package/client/composer-hints.js +20 -0
  11. package/client/composer-primary.d.ts +18 -0
  12. package/client/composer-primary.js +29 -0
  13. package/client/decision-transport.d.ts +70 -0
  14. package/client/decision-transport.js +175 -0
  15. package/client/decode-composer-draft.d.ts +11 -0
  16. package/client/decode-composer-draft.js +12 -0
  17. package/client/embedding-input.d.ts +84 -0
  18. package/client/embedding-input.js +194 -0
  19. package/client/embedding-space.d.ts +82 -0
  20. package/client/embedding-space.js +389 -0
  21. package/client/embedding-transport.d.ts +40 -0
  22. package/client/embedding-transport.js +71 -0
  23. package/client/encode-composer-draft.d.ts +9 -0
  24. package/client/encode-composer-draft.js +34 -0
  25. package/client/encode-files.d.ts +18 -0
  26. package/client/encode-files.js +54 -0
  27. package/client/failure.d.ts +29 -0
  28. package/client/failure.js +34 -0
  29. package/client/generation-selection.d.ts +15 -0
  30. package/client/generation-selection.js +24 -0
  31. package/client/host-transport.d.ts +70 -0
  32. package/client/host-transport.js +75 -0
  33. package/client/index.d.ts +37 -0
  34. package/client/index.js +31 -0
  35. package/client/live/live-mic-forward.d.ts +30 -0
  36. package/client/live/live-mic-forward.js +46 -0
  37. package/client/live/live-page-tool.d.ts +39 -0
  38. package/client/live/live-page-tool.js +26 -0
  39. package/client/live/live-state.d.ts +13 -0
  40. package/client/live/live-state.js +22 -0
  41. package/client/live/live-tool.d.ts +11 -0
  42. package/client/live/live-tool.js +1 -0
  43. package/client/live-client.d.ts +189 -0
  44. package/client/live-client.js +829 -0
  45. package/client/live-errors.d.ts +2 -0
  46. package/client/live-errors.js +9 -0
  47. package/client/live-messages.d.ts +148 -0
  48. package/client/live-messages.js +100 -0
  49. package/client/mic-capture.d.ts +4 -0
  50. package/client/mic-capture.js +6 -0
  51. package/client/oauth-popup.d.ts +26 -0
  52. package/client/oauth-popup.js +30 -0
  53. package/client/page-dispatch.d.ts +15 -0
  54. package/client/page-dispatch.js +63 -0
  55. package/client/pcm-downsample.d.ts +4 -0
  56. package/client/pcm-downsample.js +45 -0
  57. package/client/run-commit.d.ts +34 -0
  58. package/client/run-commit.js +49 -0
  59. package/client/run-session.d.ts +79 -0
  60. package/client/run-session.js +207 -0
  61. package/client/schema-fields.d.ts +63 -0
  62. package/client/schema-fields.js +199 -0
  63. package/client/shaped-data.d.ts +118 -0
  64. package/client/shaped-data.js +343 -0
  65. package/client/source-citations.d.ts +13 -0
  66. package/client/source-citations.js +56 -0
  67. package/client/space-geometry.d.ts +39 -0
  68. package/client/space-geometry.js +183 -0
  69. package/client/tool-result.d.ts +78 -0
  70. package/client/tool-result.js +293 -0
  71. package/client/tool-resume.d.ts +50 -0
  72. package/client/tool-resume.js +14 -0
  73. package/client/trace-feed.d.ts +13 -0
  74. package/client/trace-feed.js +18 -0
  75. package/client/transcript-schema.d.ts +10 -0
  76. package/client/transcript-schema.js +120 -0
  77. package/client/transport.d.ts +264 -0
  78. package/client/transport.js +330 -0
  79. package/client/turn-client.d.ts +44 -0
  80. package/client/turn-client.js +88 -0
  81. package/client/wire-line.d.ts +56 -0
  82. package/client/wire-line.js +90 -0
  83. package/client/worklets/mic-capture.js +16 -0
  84. package/package.json +28 -4
  85. package/server/checkpoint-ownership.d.ts +6 -0
  86. package/server/checkpoint-ownership.js +42 -0
  87. package/server/conversation-store.d.ts +92 -0
  88. package/server/conversation-store.js +131 -0
  89. package/server/conversation.d.ts +193 -0
  90. package/server/conversation.js +552 -0
  91. package/server/credential-store.d.ts +24 -0
  92. package/server/credential-store.js +14 -0
  93. package/server/decision-handler.d.ts +42 -0
  94. package/server/decision-handler.js +46 -0
  95. package/server/embedding-handler.d.ts +33 -0
  96. package/server/embedding-handler.js +45 -0
  97. package/server/handler.d.ts +158 -0
  98. package/server/handler.js +775 -0
  99. package/server/json-response.d.ts +2 -0
  100. package/server/json-response.js +7 -0
  101. package/server/mcp-handler.d.ts +46 -0
  102. package/server/mcp-handler.js +312 -0
  103. package/server/mod.d.ts +27 -0
  104. package/server/mod.js +25 -0
  105. package/server/page-dispatch.d.ts +22 -0
  106. package/server/page-dispatch.js +127 -0
  107. package/server/request-body.d.ts +2 -0
  108. package/server/request-body.js +42 -0
  109. package/server/request-check.d.ts +21 -0
  110. package/server/request-check.js +49 -0
  111. package/server/session-authority.d.ts +8 -0
  112. package/server/session-authority.js +78 -0
  113. package/server/session-boundary.d.ts +26 -0
  114. package/server/session-boundary.js +64 -0
  115. package/server/session-identity.d.ts +16 -0
  116. package/server/session-identity.js +41 -0
  117. package/server/session-limits.d.ts +12 -0
  118. package/server/session-limits.js +59 -0
  119. package/server/session-store.d.ts +123 -0
  120. package/server/session-store.js +264 -0
  121. package/server/single-action.d.ts +21 -0
  122. package/server/single-action.js +30 -0
  123. package/server/steer-inbox.d.ts +35 -0
  124. package/server/steer-inbox.js +52 -0
  125. package/server/tool-operations.d.ts +6 -0
  126. package/server/tool-operations.js +132 -0
  127. package/server/turn-input.d.ts +10 -0
  128. package/server/turn-input.js +29 -0
@@ -0,0 +1,39 @@
1
+ /** The page's result for a call: the tool's output schema checks it, then the model reads it. */
2
+ export type PageToolAnswer = {
3
+ output: unknown;
4
+ };
5
+ /** One page tool: what the page does for a call the model made, and what it tells the model. */
6
+ export type PageTool = (args: Record<string, unknown>, call: {
7
+ callId: string;
8
+ operationId: string;
9
+ }) => PageToolAnswer | Promise<PageToolAnswer>;
10
+ /**
11
+ * The page's tools, by name: each answers a tool the profile declares with
12
+ * `answeredBy: 'page'`. Any other tool runs on the relay, gates and all.
13
+ */
14
+ export type PageTools = Record<string, PageTool>;
15
+ /** What a host gives a live call. */
16
+ export type LiveCallOptions = {
17
+ /** The value chosen for each of the profile's `inputs.slots`, read as the call starts. */
18
+ slots?: Record<string, string>;
19
+ /**
20
+ * What the page tells the agent: any JSON. It goes with the call's opening, and
21
+ * again whenever it changes, as background the agent reads without replying.
22
+ */
23
+ context?: unknown;
24
+ pageTools?: PageTools;
25
+ };
26
+ /**
27
+ * Where the page's tools and the profile's disagree, for the builder: a page
28
+ * tool with no handler here leaves the model unanswered, and a handler for a
29
+ * tool the profile does not give the page never runs.
30
+ */
31
+ export declare function pageToolMismatch(declared: readonly string[], handled: readonly string[]): {
32
+ unanswered: string[];
33
+ unused: string[];
34
+ };
35
+ /**
36
+ * Says in the console where the page's tools and the profile's disagree. A wrong name is the
37
+ * builder's to fix, so it is never said to the visitor.
38
+ */
39
+ export declare function warnPageToolMismatch(declared: readonly string[], handled: readonly string[]): void;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Where the page's tools and the profile's disagree, for the builder: a page
3
+ * tool with no handler here leaves the model unanswered, and a handler for a
4
+ * tool the profile does not give the page never runs.
5
+ */
6
+ export function pageToolMismatch(declared, handled) {
7
+ return {
8
+ unanswered: declared.filter((name) => !handled.includes(name)),
9
+ unused: handled.filter((name) => !declared.includes(name)),
10
+ };
11
+ }
12
+ /**
13
+ * Says in the console where the page's tools and the profile's disagree. A wrong name is the
14
+ * builder's to fix, so it is never said to the visitor.
15
+ */
16
+ export function warnPageToolMismatch(declared, handled) {
17
+ const { unanswered, unused } = pageToolMismatch(declared, handled);
18
+ for (const name of unanswered) {
19
+ // labels-exempt: builder diagnostic
20
+ console.warn(`Theorem: page tool '${name}' has no handler in pageTools; the agent gets no answer.`);
21
+ }
22
+ for (const name of unused) {
23
+ // labels-exempt: builder diagnostic
24
+ console.warn(`Theorem: pageTools has '${name}', which the profile does not declare answeredBy: 'page'.`);
25
+ }
26
+ }
@@ -0,0 +1,13 @@
1
+ export type LiveSessionStatus = 'disconnected' | 'connecting'
2
+ /** The call dropped and the client is taking it up again. */
3
+ | 'reconnecting' | 'ready' | 'listening' | 'speaking' | 'working' | 'error';
4
+ export type LiveConnectPhase = 'socket' | 'microphone';
5
+ /** What a live call is doing, for its status line; the UI words it. */
6
+ export type LiveState = 'calling_tool' | 'connecting' | 'reconnecting' | 'requesting_mic' | 'speaking' | 'connected' | 'muted' | 'listening' | 'error' | 'ended';
7
+ export declare function liveState(args: {
8
+ status: LiveSessionStatus;
9
+ connectPhase: LiveConnectPhase | null;
10
+ toolName: string | null;
11
+ isMuted: boolean;
12
+ voiceEnabled?: boolean;
13
+ }): LiveState;
@@ -0,0 +1,22 @@
1
+ export function liveState(args) {
2
+ if (args.status === 'reconnecting')
3
+ return 'reconnecting';
4
+ if (args.toolName)
5
+ return 'calling_tool';
6
+ if (args.connectPhase === 'socket')
7
+ return 'connecting';
8
+ if (args.connectPhase === 'microphone')
9
+ return 'requesting_mic';
10
+ if (args.status === 'speaking')
11
+ return 'speaking';
12
+ if (args.status === 'listening' || args.status === 'ready') {
13
+ if (args.voiceEnabled === false)
14
+ return 'connected';
15
+ return args.isMuted ? 'muted' : 'listening';
16
+ }
17
+ if (args.status === 'connecting')
18
+ return 'connecting';
19
+ if (args.status === 'error')
20
+ return 'error';
21
+ return 'ended';
22
+ }
@@ -0,0 +1,11 @@
1
+ import type { ToolGate } from '@theoremjs/agents/kernel';
2
+ import type { ToolGateResolution } from '../tool-resume.ts';
3
+ /** A gate the user is asked to answer, for the model's call `callId`. */
4
+ export type LiveToolGatePrompt = {
5
+ callId: string;
6
+ toolName: string;
7
+ input: Record<string, unknown>;
8
+ gate: ToolGate;
9
+ };
10
+ /** The user's answer to a live gate, or `withdrawn`: the model cancelled the call, so nothing is asked. */
11
+ export type LiveGateAnswer = ToolGateResolution | 'withdrawn';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Pure client-side SDK for THEOREM Gemini 3.1 Flash Live sessions over WebSocket relay.
3
+ *
4
+ * Handles:
5
+ * - Bidirectional WebSocket connection to `/api/live/relay`.
6
+ * - 16-bit 16kHz PCM microphone audio recording & streaming.
7
+ * - Gapless 24kHz PCM / WAV model voice playback scheduling.
8
+ * - Barge-in interruption cancellation (instant audio queue flush).
9
+ * - Quiet-mic gate while model audio plays (reduces false barge-in from speaker bleed).
10
+ * - UI tool execution and response routing.
11
+ *
12
+ * @module
13
+ */
14
+ import { type SessionEventOf, type TraceRecord } from '@theoremjs/agents';
15
+ import type { LiveConnectPhase, LiveSessionStatus } from './live/live-state.ts';
16
+ import { type ExecuteToolOnRelay, type LiveToolStep } from './live-messages.ts';
17
+ import { type ClientTurnEvent } from './transport.ts';
18
+ export type { LiveConnection, LiveSocket } from './live-messages.ts';
19
+ import type { LiveSocket } from './live-messages.ts';
20
+ export interface LiveClientOptions {
21
+ profile?: string;
22
+ /** The host's own JSON for its relay, sent as the open message's `host`. */
23
+ openMessage?: Record<string, unknown>;
24
+ /** The value chosen for each of the profile's `inputs.slots`, fixed for the call. */
25
+ slots?: Record<string, string>;
26
+ /** What the page tells the agent as the call opens; `setContext` replaces it during the call. */
27
+ context?: unknown;
28
+ relayUrl?: string;
29
+ /** In-process connections reuse the same microphone, playback, and tool client. */
30
+ createSocket?: () => LiveSocket;
31
+ /** When false, skip microphone capture; session still receives model audio. */
32
+ voiceIngress?: boolean;
33
+ onStatusChange?: (status: LiveSessionStatus) => void;
34
+ onConnectPhase?: (phase: LiveConnectPhase | null) => void;
35
+ onTranscript?: (text: string, isUser: boolean, meta?: {
36
+ interim?: boolean;
37
+ }) => void;
38
+ /**
39
+ * Every event the session sends, `unsupported` for a kind this client does
40
+ * not know, and `malformed` for one that failed its check (left out; the call goes on).
41
+ */
42
+ onTurnEvent?: (event: ClientTurnEvent) => void;
43
+ /** A trace record the session wrote, when the relay delivers them. */
44
+ onTrace?: (record: TraceRecord) => void;
45
+ /** A failure, typed by kind; word it with `clientFailure` and the interface's `labels`. */
46
+ onError?: (error: Error) => void;
47
+ /** Provider signalled the upstream session is draining (e.g. goAway). */
48
+ onSessionClosing?: (timeLeftMs?: number) => void;
49
+ /**
50
+ * The provider ended the session after warning it would: not a failure.
51
+ * `session.message` is the user's line; `session.ended` the close, for the builder.
52
+ */
53
+ onSessionEnded?: (session: SessionEventOf<'ended'>) => void;
54
+ /**
55
+ * The model called a tool. The host runs it with `executeToolOnRelay` and
56
+ * answers its gates; the session answers the model. A throw reaches `onError`.
57
+ */
58
+ onToolCall: (name: string, args: Record<string, unknown>, meta: {
59
+ callId: string;
60
+ operationId: string;
61
+ }) => Promise<void>;
62
+ /** The relay opened the call: the id it gave the call, and the profile it runs. */
63
+ onSessionReady?: (info: {
64
+ sessionId?: string;
65
+ profile?: string;
66
+ }) => void;
67
+ onVolumeLevel?: (level: number, isUser: boolean) => void;
68
+ }
69
+ export declare class LiveSessionClient {
70
+ private ws;
71
+ private audioContext;
72
+ private micStream;
73
+ private micSource;
74
+ private micWorklet;
75
+ private micWorkletModuleLoaded;
76
+ private playbackNodes;
77
+ private playbackBus;
78
+ private playbackAnalyser;
79
+ private playbackMeterFrame;
80
+ private playbackMeterBuffer;
81
+ private nextPlaybackTime;
82
+ private status;
83
+ /** Server reported background work (reasoning / async tools) still in flight. */
84
+ private serverWorking;
85
+ private micActivating;
86
+ private connectTimeout;
87
+ private isMuted;
88
+ private options;
89
+ /** Serialize control-plane handling (tools / status) without waiting on audio decode. */
90
+ private inboundChain;
91
+ /** Ordered model-audio playback queue (separate so tools are not stuck behind decode). */
92
+ private audioChain;
93
+ /**
94
+ * Tool calls, one at a time in the order the model made them. Apart from
95
+ * `inboundChain`: a call waits on the relay's reply, which arrives inbound.
96
+ */
97
+ private toolChain;
98
+ /** Bumped on barge-in / cancel so stale audioChain work is skipped. */
99
+ private audioEpoch;
100
+ private pendingExecuteResults;
101
+ /** The page's context package, and the JSON of the one the relay last got. */
102
+ private context;
103
+ private sentContext;
104
+ /** The provider's latest handle for taking this call up again after a drop. */
105
+ private history;
106
+ private providerState;
107
+ /** The session said it ended, or failed: a close after that is the end, not a drop. */
108
+ private sessionOver;
109
+ /** When the call dropped, for the time away a resume reports. */
110
+ private droppedAt;
111
+ /** When the call that could not reconnect dropped: the next call takes it up again. */
112
+ private lostAt;
113
+ private reconnectTries;
114
+ private reconnectTimer;
115
+ constructor(options: LiveClientOptions);
116
+ private setStatus;
117
+ /** Still opening: the first connect, or a try at taking a dropped call up again. */
118
+ private get opening();
119
+ private setConnectPhase;
120
+ private clearConnectTimeout;
121
+ private detachWebSocket;
122
+ private clearReconnect;
123
+ private teardownConnection;
124
+ /** End the session on `error`: a failed connect or a lost socket. */
125
+ private failSession;
126
+ private createSocket;
127
+ /**
128
+ * Start a call. After one that dropped and could not reconnect, it takes that call up again,
129
+ * so the agent neither greets twice nor forgets; after a hang-up it is a new call.
130
+ */
131
+ connect(): Promise<void>;
132
+ /** A lost call that cannot be taken up again, its handle refused or expired, starts as a new one. */
133
+ private startOver;
134
+ /** The first message: the call's values, and the handle and time away when it takes a dropped call up again. */
135
+ private openMessage;
136
+ /** The socket closed while the call was open: take it up again if the provider gave a handle, else end. */
137
+ private handleDrop;
138
+ private scheduleReconnect;
139
+ /** A try at opening failed: a reconnect waits and tries again, a first connect fails the call. */
140
+ private failOpen;
141
+ private open;
142
+ private ensureAudioContext;
143
+ private activateMicrophone;
144
+ private sendMicFrame;
145
+ private reportMicVolume;
146
+ private forwardMicBuffer;
147
+ private setupMicrophonePipeline;
148
+ private ensurePlaybackBus;
149
+ private stopPlaybackMeter;
150
+ private startPlaybackMeter;
151
+ private processServerEnvelope;
152
+ private enqueueServerMessage;
153
+ private handleReadyEnvelope;
154
+ /** The call is open, first or again: the page's context catches up with what changed meanwhile. */
155
+ private becomeReady;
156
+ private handleExecuteToolResultEnvelope;
157
+ private tryHandleControlEnvelope;
158
+ private collectInboundTurn;
159
+ private processTurnEvent;
160
+ private handleEvidenceTurnEvent;
161
+ private handleSessionTurnEvent;
162
+ /** Hand the session's closing and end to the host; `true` when it was one of them. */
163
+ private notifySessionLifecycle;
164
+ /** Status to settle into once model speech stops. */
165
+ private restingStatus;
166
+ private collectMediaTurnEvent;
167
+ private handleDoneTurnEvent;
168
+ private scheduleMediaChunks;
169
+ /** The relay runs `LiveSession.executeTool`; see `ExecuteToolOnRelay`. */
170
+ executeToolOnRelay(args: Parameters<ExecuteToolOnRelay>[0]): Promise<LiveToolStep>;
171
+ private enqueueAudioChunk;
172
+ cancelPlayback(): void;
173
+ toggleMute(): boolean;
174
+ sendText(text: string): void;
175
+ /**
176
+ * The call's slot values. An open call is taken up again with them when the provider gave a
177
+ * handle; with none, the next call has them.
178
+ */
179
+ setSlots(slots: Record<string, string> | undefined): void;
180
+ /**
181
+ * Replace the page's context package. In a call it reaches the agent as
182
+ * background, with no reply; before one, it goes with the call's opening.
183
+ */
184
+ setContext(context: unknown): void;
185
+ private flushContext;
186
+ sendVideo(data: string, mimeType?: string): void;
187
+ disconnect(): void;
188
+ private cleanupAudio;
189
+ }