@theoremjs/react 0.0.0-stage → 0.3.1

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 (320) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +772 -2
  3. package/client/attachment-hover-preview.d.ts +11 -0
  4. package/client/attachment-hover-preview.js +36 -0
  5. package/client/audio-level.d.ts +5 -0
  6. package/client/audio-level.js +24 -0
  7. package/client/composer-attachments.d.ts +30 -0
  8. package/client/composer-attachments.js +33 -0
  9. package/client/composer-drawer.d.ts +19 -0
  10. package/client/composer-drawer.js +15 -0
  11. package/client/composer-hints.d.ts +25 -0
  12. package/client/composer-hints.js +20 -0
  13. package/client/composer-primary.d.ts +16 -0
  14. package/client/composer-primary.js +25 -0
  15. package/client/decision-images.d.ts +76 -0
  16. package/client/decision-images.js +139 -0
  17. package/client/decision-transport.d.ts +70 -0
  18. package/client/decision-transport.js +175 -0
  19. package/client/decode-composer-draft.d.ts +11 -0
  20. package/client/decode-composer-draft.js +12 -0
  21. package/client/embedding-input.d.ts +84 -0
  22. package/client/embedding-input.js +194 -0
  23. package/client/embedding-space.d.ts +82 -0
  24. package/client/embedding-space.js +389 -0
  25. package/client/embedding-transport.d.ts +40 -0
  26. package/client/embedding-transport.js +71 -0
  27. package/client/encode-composer-draft.d.ts +9 -0
  28. package/client/encode-composer-draft.js +34 -0
  29. package/client/encode-files.d.ts +18 -0
  30. package/client/encode-files.js +54 -0
  31. package/client/failure.d.ts +29 -0
  32. package/client/failure.js +34 -0
  33. package/client/generation-selection.d.ts +15 -0
  34. package/client/generation-selection.js +24 -0
  35. package/client/host-call.d.ts +51 -0
  36. package/client/host-call.js +47 -0
  37. package/client/host-transport.d.ts +70 -0
  38. package/client/host-transport.js +75 -0
  39. package/client/image-output.d.ts +6 -0
  40. package/client/image-output.js +13 -0
  41. package/client/index.d.ts +28 -0
  42. package/client/index.js +22 -0
  43. package/client/ink-waveform.d.ts +17 -0
  44. package/client/ink-waveform.js +68 -0
  45. package/client/live/apply-live-turn-tool-event.d.ts +14 -0
  46. package/client/live/apply-live-turn-tool-event.js +39 -0
  47. package/client/live/live-captions.d.ts +53 -0
  48. package/client/live/live-captions.js +174 -0
  49. package/client/live/live-mic-forward.d.ts +30 -0
  50. package/client/live/live-mic-forward.js +46 -0
  51. package/client/live/live-page-tool.d.ts +34 -0
  52. package/client/live/live-page-tool.js +11 -0
  53. package/client/live/live-state.d.ts +13 -0
  54. package/client/live/live-state.js +22 -0
  55. package/client/live/live-tool.d.ts +11 -0
  56. package/client/live/live-tool.js +1 -0
  57. package/client/live/live-video.d.ts +10 -0
  58. package/client/live/live-video.js +71 -0
  59. package/client/live/run-live-tool-call.d.ts +22 -0
  60. package/client/live/run-live-tool-call.js +70 -0
  61. package/client/live/use-live-caption-log.d.ts +17 -0
  62. package/client/live/use-live-caption-log.js +51 -0
  63. package/client/live-client.d.ts +189 -0
  64. package/client/live-client.js +829 -0
  65. package/client/live-errors.d.ts +2 -0
  66. package/client/live-errors.js +9 -0
  67. package/client/live-messages.d.ts +148 -0
  68. package/client/live-messages.js +100 -0
  69. package/client/mic-capture.d.ts +4 -0
  70. package/client/mic-capture.js +6 -0
  71. package/client/oauth-popup.d.ts +26 -0
  72. package/client/oauth-popup.js +30 -0
  73. package/client/page-dispatch.d.ts +15 -0
  74. package/client/page-dispatch.js +63 -0
  75. package/client/pcm-downsample.d.ts +4 -0
  76. package/client/pcm-downsample.js +45 -0
  77. package/client/run-commit.d.ts +34 -0
  78. package/client/run-commit.js +49 -0
  79. package/client/run-session.d.ts +79 -0
  80. package/client/run-session.js +207 -0
  81. package/client/schema-fields.d.ts +63 -0
  82. package/client/schema-fields.js +199 -0
  83. package/client/shaped-data.d.ts +118 -0
  84. package/client/shaped-data.js +343 -0
  85. package/client/source-citations.d.ts +13 -0
  86. package/client/source-citations.js +56 -0
  87. package/client/space-geometry.d.ts +39 -0
  88. package/client/space-geometry.js +183 -0
  89. package/client/state-fields.d.ts +16 -0
  90. package/client/state-fields.js +44 -0
  91. package/client/tool-result.d.ts +78 -0
  92. package/client/tool-result.js +293 -0
  93. package/client/tool-resume.d.ts +50 -0
  94. package/client/tool-resume.js +14 -0
  95. package/client/trace-feed.d.ts +13 -0
  96. package/client/trace-feed.js +18 -0
  97. package/client/trace-story.d.ts +163 -0
  98. package/client/trace-story.js +440 -0
  99. package/client/trace-view.d.ts +130 -0
  100. package/client/trace-view.js +333 -0
  101. package/client/transcript-groups.d.ts +140 -0
  102. package/client/transcript-groups.js +217 -0
  103. package/client/transcript-schema.d.ts +10 -0
  104. package/client/transcript-schema.js +120 -0
  105. package/client/transcript-scroll.d.ts +7 -0
  106. package/client/transcript-scroll.js +6 -0
  107. package/client/transport.d.ts +264 -0
  108. package/client/transport.js +330 -0
  109. package/client/turn-client.d.ts +44 -0
  110. package/client/turn-client.js +88 -0
  111. package/client/voice-label.d.ts +2 -0
  112. package/client/voice-label.js +15 -0
  113. package/client/voice-recorder.d.ts +27 -0
  114. package/client/voice-recorder.js +162 -0
  115. package/client/wire-line.d.ts +56 -0
  116. package/client/wire-line.js +90 -0
  117. package/client/worklets/mic-capture.js +16 -0
  118. package/components/InkWaveform.d.ts +21 -0
  119. package/components/InkWaveform.js +131 -0
  120. package/components/live/use-live-runner-controls.d.ts +47 -0
  121. package/components/live/use-live-runner-controls.js +96 -0
  122. package/components/live/use-live-runner-model.d.ts +49 -0
  123. package/components/live/use-live-runner-model.js +190 -0
  124. package/components/live/use-live-runner-ui.d.ts +67 -0
  125. package/components/live/use-live-runner-ui.js +167 -0
  126. package/components/live/use-live-session-client.d.ts +41 -0
  127. package/components/live/use-live-session-client.js +126 -0
  128. package/components/use-composer-voice.d.ts +28 -0
  129. package/components/use-composer-voice.js +90 -0
  130. package/components/use-editor-selection.d.ts +3 -0
  131. package/components/use-editor-selection.js +19 -0
  132. package/components/use-voice-playback.d.ts +17 -0
  133. package/components/use-voice-playback.js +68 -0
  134. package/hooks/use-described.d.ts +12 -0
  135. package/hooks/use-described.js +25 -0
  136. package/hooks/use-embedding-index.d.ts +27 -0
  137. package/hooks/use-embedding-index.js +43 -0
  138. package/hooks/use-one-call.d.ts +31 -0
  139. package/hooks/use-one-call.js +76 -0
  140. package/hooks/use-page-tool-warnings.d.ts +6 -0
  141. package/hooks/use-page-tool-warnings.js +25 -0
  142. package/hooks/use-second-ticker.d.ts +2 -0
  143. package/hooks/use-second-ticker.js +13 -0
  144. package/hooks/use-theorem-chat-actions.d.ts +79 -0
  145. package/hooks/use-theorem-chat-actions.js +287 -0
  146. package/hooks/use-theorem-chat-state.d.ts +66 -0
  147. package/hooks/use-theorem-chat-state.js +122 -0
  148. package/hooks/use-theorem-chat.d.ts +97 -0
  149. package/hooks/use-theorem-chat.js +528 -0
  150. package/hooks/use-theorem-decision.d.ts +18 -0
  151. package/hooks/use-theorem-decision.js +12 -0
  152. package/hooks/use-theorem-embedding.d.ts +18 -0
  153. package/hooks/use-theorem-embedding.js +12 -0
  154. package/hooks/use-theorem-host.d.ts +45 -0
  155. package/hooks/use-theorem-host.js +135 -0
  156. package/hooks/use-theorem-interface.d.ts +22 -0
  157. package/hooks/use-theorem-interface.js +15 -0
  158. package/hooks/use-trace-records.d.ts +4 -0
  159. package/hooks/use-trace-records.js +7 -0
  160. package/index.d.ts +17 -0
  161. package/index.js +17 -0
  162. package/live.d.ts +9 -0
  163. package/live.js +10 -0
  164. package/package.json +74 -4
  165. package/server/checkpoint-ownership.d.ts +6 -0
  166. package/server/checkpoint-ownership.js +42 -0
  167. package/server/conversation-store.d.ts +92 -0
  168. package/server/conversation-store.js +131 -0
  169. package/server/conversation.d.ts +193 -0
  170. package/server/conversation.js +552 -0
  171. package/server/credential-store.d.ts +24 -0
  172. package/server/credential-store.js +14 -0
  173. package/server/decision-handler.d.ts +42 -0
  174. package/server/decision-handler.js +46 -0
  175. package/server/embedding-handler.d.ts +33 -0
  176. package/server/embedding-handler.js +45 -0
  177. package/server/handler.d.ts +152 -0
  178. package/server/handler.js +771 -0
  179. package/server/json-response.d.ts +2 -0
  180. package/server/json-response.js +7 -0
  181. package/server/mod.d.ts +25 -0
  182. package/server/mod.js +23 -0
  183. package/server/page-dispatch.d.ts +22 -0
  184. package/server/page-dispatch.js +127 -0
  185. package/server/request-body.d.ts +2 -0
  186. package/server/request-body.js +42 -0
  187. package/server/request-check.d.ts +21 -0
  188. package/server/request-check.js +49 -0
  189. package/server/session-authority.d.ts +8 -0
  190. package/server/session-authority.js +78 -0
  191. package/server/session-boundary.d.ts +26 -0
  192. package/server/session-boundary.js +64 -0
  193. package/server/session-identity.d.ts +16 -0
  194. package/server/session-identity.js +41 -0
  195. package/server/session-limits.d.ts +12 -0
  196. package/server/session-limits.js +59 -0
  197. package/server/session-store.d.ts +123 -0
  198. package/server/session-store.js +264 -0
  199. package/server/single-action.d.ts +21 -0
  200. package/server/single-action.js +30 -0
  201. package/server/steer-inbox.d.ts +35 -0
  202. package/server/steer-inbox.js +52 -0
  203. package/server/tool-operations.d.ts +6 -0
  204. package/server/tool-operations.js +132 -0
  205. package/server/turn-input.d.ts +10 -0
  206. package/server/turn-input.js +29 -0
  207. package/styles/ink-controls.css +134 -0
  208. package/ui/CardWall.d.ts +10 -0
  209. package/ui/CardWall.js +61 -0
  210. package/ui/ChatComposerBar.d.ts +62 -0
  211. package/ui/ChatComposerBar.js +306 -0
  212. package/ui/ChatTranscript.d.ts +43 -0
  213. package/ui/ChatTranscript.js +527 -0
  214. package/ui/ConsoleFrame.d.ts +104 -0
  215. package/ui/ConsoleFrame.js +146 -0
  216. package/ui/DecisionAnswers.d.ts +53 -0
  217. package/ui/DecisionAnswers.js +233 -0
  218. package/ui/DecisionImages.d.ts +16 -0
  219. package/ui/DecisionImages.js +46 -0
  220. package/ui/EmbeddingDocuments.d.ts +78 -0
  221. package/ui/EmbeddingDocuments.js +278 -0
  222. package/ui/EmbeddingQuery.d.ts +27 -0
  223. package/ui/EmbeddingQuery.js +95 -0
  224. package/ui/EmbeddingResults.d.ts +41 -0
  225. package/ui/EmbeddingResults.js +165 -0
  226. package/ui/EmbeddingSpace.d.ts +26 -0
  227. package/ui/EmbeddingSpace.js +106 -0
  228. package/ui/LiveCaptionsPanel.d.ts +22 -0
  229. package/ui/LiveCaptionsPanel.js +27 -0
  230. package/ui/LiveRunner.d.ts +30 -0
  231. package/ui/LiveRunner.js +180 -0
  232. package/ui/PaneState.d.ts +33 -0
  233. package/ui/PaneState.js +50 -0
  234. package/ui/SchemaFields.d.ts +10 -0
  235. package/ui/SchemaFields.js +150 -0
  236. package/ui/ShapedData.d.ts +11 -0
  237. package/ui/ShapedData.js +196 -0
  238. package/ui/SidePanel.d.ts +126 -0
  239. package/ui/SidePanel.js +123 -0
  240. package/ui/StateFields.d.ts +44 -0
  241. package/ui/StateFields.js +139 -0
  242. package/ui/TheoremChat.d.ts +122 -0
  243. package/ui/TheoremChat.js +134 -0
  244. package/ui/TheoremDecision.d.ts +30 -0
  245. package/ui/TheoremDecision.js +130 -0
  246. package/ui/TheoremEmbedding.d.ts +27 -0
  247. package/ui/TheoremEmbedding.js +122 -0
  248. package/ui/TheoremHost.d.ts +55 -0
  249. package/ui/TheoremHost.js +240 -0
  250. package/ui/ToolGateCard.d.ts +32 -0
  251. package/ui/ToolGateCard.js +107 -0
  252. package/ui/ToolResult.d.ts +10 -0
  253. package/ui/ToolResult.js +62 -0
  254. package/ui/ToolResultCharts.d.ts +5 -0
  255. package/ui/ToolResultCharts.js +103 -0
  256. package/ui/TraceCharts.d.ts +13 -0
  257. package/ui/TraceCharts.js +266 -0
  258. package/ui/TraceGuardrails.d.ts +11 -0
  259. package/ui/TraceGuardrails.js +74 -0
  260. package/ui/TraceInspector.d.ts +16 -0
  261. package/ui/TraceInspector.js +206 -0
  262. package/ui/TraceInspectorPanel.d.ts +46 -0
  263. package/ui/TraceInspectorPanel.js +95 -0
  264. package/ui/TraceOverview.d.ts +38 -0
  265. package/ui/TraceOverview.js +126 -0
  266. package/ui/TraceSpanDetail.d.ts +10 -0
  267. package/ui/TraceSpanDetail.js +190 -0
  268. package/ui/TraceStory.d.ts +20 -0
  269. package/ui/TraceStory.js +108 -0
  270. package/ui/TraceValues.d.ts +36 -0
  271. package/ui/TraceValues.js +123 -0
  272. package/ui/TraceWaterfall.d.ts +13 -0
  273. package/ui/TraceWaterfall.js +135 -0
  274. package/ui/VoiceNote.d.ts +12 -0
  275. package/ui/VoiceNote.js +28 -0
  276. package/ui/approval-heading.d.ts +4 -0
  277. package/ui/approval-heading.js +9 -0
  278. package/ui/arrive.d.ts +18 -0
  279. package/ui/arrive.js +46 -0
  280. package/ui/built/theme.css +792 -0
  281. package/ui/built/theme.css.d.ts +9 -0
  282. package/ui/built/theorem.d.ts +13 -0
  283. package/ui/built/theorem.js +660 -0
  284. package/ui/built/theorem.variants.d.ts +22 -0
  285. package/ui/code-language.d.ts +12 -0
  286. package/ui/code-language.js +50 -0
  287. package/ui/disclosure-motion.d.ts +6 -0
  288. package/ui/disclosure-motion.js +207 -0
  289. package/ui/embedding-space-gl.d.ts +37 -0
  290. package/ui/embedding-space-gl.js +663 -0
  291. package/ui/embedding-space-view.d.ts +8 -0
  292. package/ui/embedding-space-view.js +8 -0
  293. package/ui/glide.d.ts +7 -0
  294. package/ui/glide.js +44 -0
  295. package/ui/icons.d.ts +4 -0
  296. package/ui/icons.js +38 -0
  297. package/ui/index.d.ts +36 -0
  298. package/ui/index.js +39 -0
  299. package/ui/labels-provider.d.ts +16 -0
  300. package/ui/labels-provider.js +64 -0
  301. package/ui/labels.d.ts +1442 -0
  302. package/ui/labels.js +1443 -0
  303. package/ui/markdown-plugins.d.ts +9 -0
  304. package/ui/markdown-plugins.js +13 -0
  305. package/ui/mcp-icon.d.ts +6 -0
  306. package/ui/mcp-icon.js +8 -0
  307. package/ui/row-keys.d.ts +19 -0
  308. package/ui/row-keys.js +33 -0
  309. package/ui/theme.d.ts +10 -0
  310. package/ui/theme.js +13 -0
  311. package/ui/theorem-theme.d.ts +10 -0
  312. package/ui/theorem-theme.js +105 -0
  313. package/ui/trace-palette.d.ts +10 -0
  314. package/ui/trace-palette.js +10 -0
  315. package/ui/trace-patterns.d.ts +40 -0
  316. package/ui/trace-patterns.js +57 -0
  317. package/ui/transcript-copy-text.d.ts +4 -0
  318. package/ui/transcript-copy-text.js +40 -0
  319. package/ui/wall-columns.d.ts +8 -0
  320. package/ui/wall-columns.js +19 -0
@@ -0,0 +1,2 @@
1
+ /** Whether a DOM/media error indicates the user denied microphone access. */
2
+ export declare function isPermissionDeniedError(err: unknown): boolean;
@@ -0,0 +1,9 @@
1
+ /** Whether a DOM/media error indicates the user denied microphone access. */
2
+ export function isPermissionDeniedError(err) {
3
+ if (!(err instanceof Error))
4
+ return false;
5
+ const name = 'name' in err && typeof err.name === 'string' ? err.name : '';
6
+ return (name === 'NotAllowedError' ||
7
+ name === 'PermissionDeniedError' ||
8
+ /permission|not allowed|denied/i.test(err.message));
9
+ }
@@ -0,0 +1,148 @@
1
+ import { type ProviderCheckpoint } from '@theoremjs/agents';
2
+ /**
3
+ * The live wire between the browser and a host's relay: the messages the live
4
+ * client sends (a relay reads them with `parseLiveClientMessage`) and the envelopes it reads
5
+ * back, each checked against its schema.
6
+ *
7
+ * @module
8
+ */
9
+ import { type GateDecision, type ToolGate, type TraceRecord, type TurnEvent, type TurnHistoryMessage, z } from '@theoremjs/agents';
10
+ import { type HostErrorBody } from './transport.ts';
11
+ import { type MalformedEvent, type UnsupportedEvent } from './wire-line.ts';
12
+ /**
13
+ * The live client's first message, before the relay opens the session: the
14
+ * values the call starts with. A relay reads it with `parseLiveOpenMessage`.
15
+ */
16
+ export type LiveOpenMessage = {
17
+ type: 'open';
18
+ history?: TurnHistoryMessage[];
19
+ /** The value chosen for each of the profile's `inputs.slots`. */
20
+ slots?: Record<string, string>;
21
+ /** What the page tells the agent as the call opens: the client's context package. */
22
+ context?: unknown;
23
+ /** A call that dropped, taken up again: the provider's handle, and how long the caller was away. */
24
+ resume?: {
25
+ providerState: ProviderCheckpoint;
26
+ awayMs: number;
27
+ };
28
+ /** The host's own `openMessage`, for its relay to read. */
29
+ host?: Record<string, unknown>;
30
+ };
31
+ /** The live client's first message, as `parseLiveOpenMessage` checks it for a relay. */
32
+ export declare const liveOpenMessageSchema: z.ZodType<LiveOpenMessage>;
33
+ /** What the live client sends its relay once the call is open. */
34
+ export type LiveClientMessage = {
35
+ type: 'audio';
36
+ data: string;
37
+ } | {
38
+ type: 'video';
39
+ data: string;
40
+ mimeType: string;
41
+ } | {
42
+ type: 'text';
43
+ text: string;
44
+ }
45
+ /** The page's context package, replacing the last: background the model reads without replying. */
46
+ | {
47
+ type: 'context';
48
+ context: unknown;
49
+ }
50
+ /** Run a call the model made, by its id; the live session holds its name, input, and gate. */
51
+ | {
52
+ type: 'executeTool';
53
+ callId: string;
54
+ operationId: string;
55
+ decision?: GateDecision;
56
+ input?: unknown;
57
+ secret?: string;
58
+ /** What the browser did for a tool that runs there; a relay hands it to the session as `page.output`. */
59
+ output?: unknown;
60
+ grantId?: string;
61
+ unanswered?: true;
62
+ };
63
+ /** The live client's messages, as `parseLiveClientMessage` checks them for a relay. */
64
+ export declare const liveClientMessageSchema: z.ZodType<LiveClientMessage>;
65
+ /** The envelopes a relay sends the live client. */
66
+ export type LiveServerEnvelope = {
67
+ type: 'ready';
68
+ profile?: string;
69
+ sessionId?: string;
70
+ }
71
+ /** The session's events; one of a kind this client does not know arrives as `unsupported`, one that fails its check as `malformed`. */
72
+ | {
73
+ type: 'events';
74
+ events: (TurnEvent | UnsupportedEvent | MalformedEvent)[];
75
+ }
76
+ /** A trace record the session wrote, from a relay that delivers its traces (the studio). */
77
+ | {
78
+ type: 'trace';
79
+ record: TraceRecord;
80
+ }
81
+ /** The relay's error body, read as a host error. */
82
+ | ({
83
+ type: 'error';
84
+ } & HostErrorBody)
85
+ /**
86
+ * The relay's answer to the browser's `executeTool`: the session settled the
87
+ * call (its tool events carry what happened), holds it on a gate, or refused
88
+ * the message (the relay's error body, read as a host error).
89
+ */
90
+ | {
91
+ type: 'executeToolResult';
92
+ callId: string;
93
+ operationId: string;
94
+ status: 'settled';
95
+ } | {
96
+ type: 'executeToolResult';
97
+ callId: string;
98
+ operationId: string;
99
+ status: 'dispatched';
100
+ grantId: string;
101
+ arguments: Record<string, unknown>;
102
+ } | {
103
+ type: 'executeToolResult';
104
+ callId: string;
105
+ operationId: string;
106
+ status: 'gated';
107
+ gate: ToolGate;
108
+ } | {
109
+ type: 'executeToolResult';
110
+ callId: string;
111
+ operationId: string;
112
+ status: 'refused';
113
+ body: HostErrorBody;
114
+ };
115
+ /**
116
+ * One envelope's text from the relay, checked: an envelope or event of a kind
117
+ * this client does not know is `unsupported`, and one that fails its check is
118
+ * `malformed`. A malformed event leaves the envelope's other events standing.
119
+ */
120
+ export declare function parseLiveServerEnvelope(text: string): LiveServerEnvelope | UnsupportedEvent | MalformedEvent;
121
+ /** What the session did with an `executeTool`: settled the call, or holds it on a gate. */
122
+ export type LiveToolStep = {
123
+ status: 'settled';
124
+ } | {
125
+ status: 'gated';
126
+ gate: ToolGate;
127
+ } | {
128
+ status: 'dispatched';
129
+ grantId: string;
130
+ arguments: Record<string, unknown>;
131
+ };
132
+ /**
133
+ * Ask the relay to run `LiveSession.executeTool` for a call the model made.
134
+ * `decision` answers its gate; `input` is the user's edit to an approval;
135
+ * `secret` is the key the user typed at a sign-in gate, sent once: the
136
+ * session makes it the credential for the gate's slot. `output` is the
137
+ * browser's result for a tool the page answers (`answeredBy: 'page'`).
138
+ */
139
+ export type ExecuteToolOnRelay = (args: Omit<Extract<LiveClientMessage, {
140
+ type: 'executeTool';
141
+ }>, 'type'>) => Promise<LiveToolStep>;
142
+ export type LiveSocket = Pick<WebSocket, 'readyState' | 'binaryType' | 'send' | 'close' | 'onopen' | 'onmessage' | 'onclose' | 'onerror'>;
143
+ /** What a call connects to: a profile the relay knows by id, or the host's own message for its relay. */
144
+ export type LiveConnection = {
145
+ profile?: string;
146
+ openMessage?: Record<string, unknown>;
147
+ createSocket?: () => LiveSocket;
148
+ };
@@ -0,0 +1,100 @@
1
+ import { providerCheckpointSchema } from '@theoremjs/agents';
2
+ /**
3
+ * The live wire between the browser and a host's relay: the messages the live
4
+ * client sends (a relay reads them with `parseLiveClientMessage`) and the envelopes it reads
5
+ * back, each checked against its schema.
6
+ *
7
+ * @module
8
+ */
9
+ import { GATE_DECISIONS, TURN_EVENT_SCHEMAS, toolGateSchema, traceRecordSchema, turnHistoryMessageSchema, z, } from '@theoremjs/agents';
10
+ import { hostErrorBodySchema } from "./transport.js";
11
+ import { readWireLine, readWireValue, } from "./wire-line.js";
12
+ const liveOpenMessage = z.object({
13
+ type: z.literal('open'),
14
+ history: z.array(turnHistoryMessageSchema).optional(),
15
+ slots: z.record(z.string(), z.string()).optional(),
16
+ context: z.unknown().optional(),
17
+ resume: z
18
+ .object({ providerState: providerCheckpointSchema, awayMs: z.number().nonnegative() })
19
+ .optional(),
20
+ host: z.record(z.string(), z.unknown()).optional(),
21
+ });
22
+ true;
23
+ /** The live client's first message, as `parseLiveOpenMessage` checks it for a relay. */
24
+ export const liveOpenMessageSchema = liveOpenMessage;
25
+ const liveClientMessage = z.discriminatedUnion('type', [
26
+ z.object({ type: z.literal('audio'), data: z.string() }),
27
+ z.object({ type: z.literal('video'), data: z.string(), mimeType: z.string() }),
28
+ z.object({ type: z.literal('text'), text: z.string() }),
29
+ z.object({ type: z.literal('context'), context: z.unknown() }),
30
+ z.object({
31
+ type: z.literal('executeTool'),
32
+ callId: z.string().min(1),
33
+ operationId: z.string().min(1).max(256),
34
+ decision: z.enum(GATE_DECISIONS).optional(),
35
+ input: z.unknown().optional(),
36
+ secret: z.string().optional(),
37
+ output: z.unknown().optional(),
38
+ grantId: z.string().min(1).optional(),
39
+ unanswered: z.literal(true).optional(),
40
+ }),
41
+ ]);
42
+ true;
43
+ /** The live client's messages, as `parseLiveClientMessage` checks them for a relay. */
44
+ export const liveClientMessageSchema = liveClientMessage;
45
+ const liveServerEnvelopeKinds = {
46
+ ready: z.object({
47
+ type: z.literal('ready'),
48
+ profile: z.string().optional(),
49
+ sessionId: z.string().optional(),
50
+ }),
51
+ events: z.object({ type: z.literal('events'), events: z.array(z.unknown()) }),
52
+ trace: z.object({ type: z.literal('trace'), record: traceRecordSchema }),
53
+ error: z.object({ type: z.literal('error') }).and(hostErrorBodySchema),
54
+ executeToolResult: z.discriminatedUnion('status', [
55
+ z.object({
56
+ type: z.literal('executeToolResult'),
57
+ callId: z.string().min(1),
58
+ operationId: z.string().min(1).max(256),
59
+ status: z.literal('dispatched'),
60
+ grantId: z.string().min(1),
61
+ arguments: z.record(z.string(), z.unknown()),
62
+ }),
63
+ z.object({
64
+ type: z.literal('executeToolResult'),
65
+ callId: z.string(),
66
+ status: z.literal('settled'),
67
+ operationId: z.string().min(1).max(256),
68
+ }),
69
+ z.object({
70
+ type: z.literal('executeToolResult'),
71
+ callId: z.string(),
72
+ status: z.literal('gated'),
73
+ operationId: z.string().min(1).max(256),
74
+ gate: toolGateSchema,
75
+ }),
76
+ z.object({
77
+ type: z.literal('executeToolResult'),
78
+ callId: z.string(),
79
+ status: z.literal('refused'),
80
+ operationId: z.string().min(1).max(256),
81
+ body: hostErrorBodySchema,
82
+ }),
83
+ ]),
84
+ };
85
+ true;
86
+ const liveServerEnvelopeLines = liveServerEnvelopeKinds;
87
+ /**
88
+ * One envelope's text from the relay, checked: an envelope or event of a kind
89
+ * this client does not know is `unsupported`, and one that fails its check is
90
+ * `malformed`. A malformed event leaves the envelope's other events standing.
91
+ */
92
+ export function parseLiveServerEnvelope(text) {
93
+ const envelope = readWireLine(liveServerEnvelopeLines, text);
94
+ if (envelope.type !== 'events')
95
+ return envelope;
96
+ return {
97
+ type: 'events',
98
+ events: envelope.events.map((event) => readWireValue(TURN_EVENT_SCHEMAS, event)),
99
+ };
100
+ }
@@ -0,0 +1,4 @@
1
+ /** The processor name `worklets/mic-capture.js` registers, for `AudioWorkletNode`. */
2
+ export declare const MIC_CAPTURE_PROCESSOR = "mic-capture-processor";
3
+ /** The worklet module for `audioWorklet.addModule`; bundlers ship it as an asset. */
4
+ export declare function micCaptureWorkletUrl(): URL;
@@ -0,0 +1,6 @@
1
+ /** The processor name `worklets/mic-capture.js` registers, for `AudioWorkletNode`. */
2
+ export const MIC_CAPTURE_PROCESSOR = 'mic-capture-processor';
3
+ /** The worklet module for `audioWorklet.addModule`; bundlers ship it as an asset. */
4
+ export function micCaptureWorkletUrl() {
5
+ return new URL('./worklets/mic-capture.js', import.meta.url);
6
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * The OAuth sign-in popup's word back to the chat that opened it.
3
+ *
4
+ * The host's callback route saves the token on the server, then its page calls
5
+ * `notifyOAuthComplete(slot)`. The chat takes the message only from the popup
6
+ * it opened, on its own origin, for the slot its gate waits for, and resumes
7
+ * the gate: no token ever reaches the browser.
8
+ *
9
+ * @module
10
+ */
11
+ /**
12
+ * Tell the chat that opened this popup that `slot`'s token is saved. Call it on
13
+ * the callback page once the credential is in the host's credential store. On a
14
+ * page no chat opened, it does nothing.
15
+ */
16
+ export declare function notifyOAuthComplete(slot: string): void;
17
+ /** The message is `popup`'s, from `origin` (the chat page's own), saying `slot` is signed in. */
18
+ export declare function isOAuthComplete(event: {
19
+ data: unknown;
20
+ source: unknown;
21
+ origin: string;
22
+ }, expected: {
23
+ popup: unknown;
24
+ slot: string;
25
+ origin: string;
26
+ }): boolean;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * The OAuth sign-in popup's word back to the chat that opened it.
3
+ *
4
+ * The host's callback route saves the token on the server, then its page calls
5
+ * `notifyOAuthComplete(slot)`. The chat takes the message only from the popup
6
+ * it opened, on its own origin, for the slot its gate waits for, and resumes
7
+ * the gate: no token ever reaches the browser.
8
+ *
9
+ * @module
10
+ */
11
+ import { isRecord } from '@theoremjs/agents/kernel';
12
+ const OAUTH_COMPLETE = 'theorem.oauth_complete';
13
+ /**
14
+ * Tell the chat that opened this popup that `slot`'s token is saved. Call it on
15
+ * the callback page once the credential is in the host's credential store. On a
16
+ * page no chat opened, it does nothing.
17
+ */
18
+ export function notifyOAuthComplete(slot) {
19
+ const opener = Reflect.get(globalThis, 'opener');
20
+ if (!isRecord(opener) || typeof opener.postMessage !== 'function')
21
+ return;
22
+ opener.postMessage({ type: OAUTH_COMPLETE, slot }, globalThis.location.origin);
23
+ }
24
+ /** The message is `popup`'s, from `origin` (the chat page's own), saying `slot` is signed in. */
25
+ export function isOAuthComplete(event, expected) {
26
+ if (event.source !== expected.popup || event.origin !== expected.origin)
27
+ return false;
28
+ const data = event.data;
29
+ return isRecord(data) && data.type === OAUTH_COMPLETE && data.slot === expected.slot;
30
+ }
@@ -0,0 +1,15 @@
1
+ import type { HostTransport } from './host-transport.ts';
2
+ import type { PageTools } from './live/live-page-tool.ts';
3
+ import type { TheoremTransport } from './transport.ts';
4
+ export type PageDispatchResult = {
5
+ callId: string;
6
+ operationId: string;
7
+ grantId: string;
8
+ page: {
9
+ output: unknown;
10
+ } | {
11
+ unanswered: true;
12
+ };
13
+ };
14
+ export declare function withPageToolDispatch(transport: TheoremTransport, tools?: PageTools): TheoremTransport;
15
+ export declare function withPageToolDispatch(transport: HostTransport, tools?: PageTools): HostTransport;
@@ -0,0 +1,63 @@
1
+ import { errorKind, publicError } from '@theoremjs/agents';
2
+ export function withPageToolDispatch(transport, tools) {
3
+ const sink = (onEvent, signal) => {
4
+ const dispatched = new Set();
5
+ return (event) => {
6
+ onEvent(event);
7
+ if (event.type !== 'tool' || event.tool.phase !== 'dispatch')
8
+ return;
9
+ const { tool } = event;
10
+ if (!transport.pageResult || !tool.operationId || signal?.aborted)
11
+ return;
12
+ const key = JSON.stringify([tool.operationId, tool.grantId]);
13
+ if (dispatched.has(key))
14
+ return;
15
+ dispatched.add(key);
16
+ const callback = tools && Object.hasOwn(tools, tool.name) ? tools[tool.name] : undefined;
17
+ const reference = {
18
+ callId: tool.callId,
19
+ operationId: tool.operationId,
20
+ grantId: tool.grantId,
21
+ };
22
+ void Promise.resolve()
23
+ .then(async () => {
24
+ if (signal?.aborted)
25
+ return;
26
+ const page = callback
27
+ ? await Promise.resolve()
28
+ .then(() => callback(tool.arguments, reference))
29
+ .catch(() => ({ unanswered: true }))
30
+ : { unanswered: true };
31
+ await transport.pageResult?.({ ...reference, page }, signal);
32
+ })
33
+ .catch((error) => {
34
+ if (!signal?.aborted)
35
+ onEvent({ type: 'error', errorKind: errorKind(error), error: publicError(error) });
36
+ });
37
+ };
38
+ };
39
+ // why: A chat's stream also carries the conversation's ref, which no page tool reads.
40
+ const chatSink = (onLine, signal) => {
41
+ const events = sink(onLine, signal);
42
+ return (line) => (line.type === 'conversation' ? onLine(line) : events(line));
43
+ };
44
+ if ('call' in transport) {
45
+ const host = {
46
+ ...transport,
47
+ describe: transport.describe.bind(transport),
48
+ invoke: (request, onEvent, signal) => transport.invoke(request, sink(onEvent, signal), signal),
49
+ call: (request, onEvent, signal) => transport.call(request, sink(onEvent, signal), signal),
50
+ };
51
+ return host;
52
+ }
53
+ const chat = {
54
+ ...transport,
55
+ describe: transport.describe.bind(transport),
56
+ invoke: (request, onLine, signal) => transport.invoke(request, chatSink(onLine, signal), signal),
57
+ turn: (request, onLine, signal) => transport.turn(request, chatSink(onLine, signal), signal),
58
+ steer: transport.steer.bind(transport),
59
+ conversation: transport.conversation.bind(transport),
60
+ rewind: transport.rewind.bind(transport),
61
+ };
62
+ return chat;
63
+ }
@@ -0,0 +1,4 @@
1
+ /** Resample Float32 audio buffer from inputRate to outputRate and convert to Int16 PCM. */
2
+ export declare function downsampleAndConvertToInt16(inputData: Float32Array, inputRate: number, outputRate?: number): Int16Array;
3
+ /** Decode little-endian PCM16 bytes to Float32 samples in [-1, 1]. */
4
+ export declare function pcm16BytesToFloat32(bytes: Uint8Array<ArrayBufferLike>): Float32Array;
@@ -0,0 +1,45 @@
1
+ /** Resample Float32 audio buffer from inputRate to outputRate and convert to Int16 PCM. */
2
+ export function downsampleAndConvertToInt16(inputData, inputRate, outputRate = 16000) {
3
+ if (inputRate === outputRate) {
4
+ return float32ToInt16(inputData);
5
+ }
6
+ const ratio = inputRate / outputRate;
7
+ const newLength = Math.round(inputData.length / ratio);
8
+ const result = new Int16Array(newLength);
9
+ let offsetResult = 0;
10
+ let offsetInput = 0;
11
+ while (offsetResult < result.length) {
12
+ const nextOffsetInput = Math.round((offsetResult + 1) * ratio);
13
+ let accum = 0;
14
+ let count = 0;
15
+ for (let i = offsetInput; i < nextOffsetInput && i < inputData.length; i++) {
16
+ accum += inputData[i] ?? 0;
17
+ count++;
18
+ }
19
+ result[offsetResult] = floatSampleToInt16(count > 0 ? accum / count : 0);
20
+ offsetResult++;
21
+ offsetInput = nextOffsetInput;
22
+ }
23
+ return result;
24
+ }
25
+ function float32ToInt16(inputData) {
26
+ const result = new Int16Array(inputData.length);
27
+ for (let i = 0; i < inputData.length; i++) {
28
+ result[i] = floatSampleToInt16(inputData[i] ?? 0);
29
+ }
30
+ return result;
31
+ }
32
+ function floatSampleToInt16(val) {
33
+ const s = Math.max(-1, Math.min(1, val));
34
+ return s < 0 ? s * 0x8000 : s * 0x7fff;
35
+ }
36
+ /** Decode little-endian PCM16 bytes to Float32 samples in [-1, 1]. */
37
+ export function pcm16BytesToFloat32(bytes) {
38
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
39
+ const float32 = new Float32Array(bytes.byteLength / 2);
40
+ for (let i = 0; i < float32.length; i++) {
41
+ const sample = view.getInt16(i * 2, true);
42
+ float32[i] = sample / (sample < 0 ? 0x8000 : 0x7fff);
43
+ }
44
+ return float32;
45
+ }
@@ -0,0 +1,34 @@
1
+ import type { TheoremError, TurnEvent } from '@theoremjs/agents';
2
+ import { type ComposerProfileInterface, type InterfaceTurnSession, type TranscriptBlock } from '@theoremjs/agents/interface';
3
+ import type { ChatLineSink, ConversationLine } from './transport.ts';
4
+ /**
5
+ * The session once a reply's events are in: a reply that waits on a gate
6
+ * keeps its events beside the transcript until the gate settles; any other is over.
7
+ */
8
+ export declare function sessionAfter(session: InterfaceTurnSession, events: readonly TurnEvent[]): InterfaceTurnSession;
9
+ /** Where a run shows itself as it streams: the reply so far, and each line the stream left out. */
10
+ export type StreamView = {
11
+ blocks(blocks: TranscriptBlock[]): void;
12
+ /** A `malformed` line: left out, and the reply goes on. */
13
+ skipped(error: TheoremError): void;
14
+ };
15
+ /**
16
+ * Streams into `events`, which the caller owns, so a stream that fails still
17
+ * leaves what it delivered. A `conversation` line goes to `onConversation`. An
18
+ * `unsupported` line is the host's to read on its own transport, and a
19
+ * `malformed` one goes to `view.skipped`: neither enters the reply.
20
+ */
21
+ export declare function streamFoldedTurn(args: {
22
+ iface: ComposerProfileInterface;
23
+ view: StreamView;
24
+ /** Seeded by the caller, and filled as the stream delivers. */
25
+ events: TurnEvent[];
26
+ /** The page adopts each ref from its transport; a run reads them only to know its message posted. */
27
+ onConversation?(line: ConversationLine): void;
28
+ stream: (onLine: ChatLineSink) => Promise<void>;
29
+ }): Promise<void>;
30
+ /** `blocks` with its last `turn-done` carrying the reply's work. */
31
+ export declare function stampWorked(blocks: TranscriptBlock[], worked: {
32
+ workedMs: number;
33
+ endedAt: number;
34
+ }): TranscriptBlock[];
@@ -0,0 +1,49 @@
1
+ import { applyTurnEventsToSession, gatedToolFromEvents, } from '@theoremjs/agents/interface';
2
+ import { foldAssistantTurn } from "./turn-client.js";
3
+ /**
4
+ * The session once a reply's events are in: a reply that waits on a gate
5
+ * keeps its events beside the transcript until the gate settles; any other is over.
6
+ */
7
+ export function sessionAfter(session, events) {
8
+ const applied = applyTurnEventsToSession(session, events);
9
+ const gatedTool = gatedToolFromEvents(events);
10
+ if (gatedTool)
11
+ return { ...applied, gatedTool, assistantEvents: [...events] };
12
+ return {
13
+ ...applied,
14
+ gatedTool: null,
15
+ assistantEvents: [],
16
+ pendingUserDraft: null,
17
+ toolSnapshot: undefined,
18
+ promotedToolIds: [],
19
+ };
20
+ }
21
+ /**
22
+ * Streams into `events`, which the caller owns, so a stream that fails still
23
+ * leaves what it delivered. A `conversation` line goes to `onConversation`. An
24
+ * `unsupported` line is the host's to read on its own transport, and a
25
+ * `malformed` one goes to `view.skipped`: neither enters the reply.
26
+ */
27
+ export function streamFoldedTurn(args) {
28
+ return args.stream((line) => {
29
+ if (line.type === 'conversation') {
30
+ args.onConversation?.(line);
31
+ return;
32
+ }
33
+ if (line.type === 'unsupported')
34
+ return;
35
+ if (line.type === 'malformed') {
36
+ args.view.skipped(line.error);
37
+ return;
38
+ }
39
+ args.events.push(line);
40
+ args.view.blocks(foldAssistantTurn(args.iface, args.events));
41
+ });
42
+ }
43
+ /** `blocks` with its last `turn-done` carrying the reply's work. */
44
+ export function stampWorked(blocks, worked) {
45
+ const last = blocks.findLastIndex((block) => block.kind === 'turn-done');
46
+ if (last < 0)
47
+ return blocks;
48
+ return blocks.map((block, index) => (index === last ? { ...block, ...worked } : block));
49
+ }
@@ -0,0 +1,79 @@
1
+ import { type TurnEvent } from '@theoremjs/agents';
2
+ import { type ComposerProfileInterface, type InterfaceTurnSession, type TranscriptBlock, type UserTurnDraft } from '@theoremjs/agents/interface';
3
+ import { type TurnFailure } from './failure.ts';
4
+ import { type StreamView } from './run-commit.ts';
5
+ import { type ToolGateResolution } from './tool-resume.ts';
6
+ import { type TheoremTransport } from './transport.ts';
7
+ import { type RunScope } from './turn-client.ts';
8
+ export type { TurnFailure } from './failure.ts';
9
+ export type { StreamView } from './run-commit.ts';
10
+ /**
11
+ * Whether the host keeps this chat's conversation. A stateless profile keeps
12
+ * none: the page holds its transcript, and nothing goes on from a ref.
13
+ */
14
+ export declare function keepsConversation(iface: ComposerProfileInterface): boolean;
15
+ /**
16
+ * What one run left. A host that keeps the conversation is the truth for the
17
+ * rest: the page draws it again from the last ref the stream carried. A
18
+ * stateless chat keeps the reply as the run streamed it.
19
+ */
20
+ export type RunOutcome = {
21
+ /** The session the run went out from, with any permission the answer granted. */
22
+ session: InterfaceTurnSession;
23
+ /** The reply's events: a gate's answer starts from the paused reply's. */
24
+ events: TurnEvent[];
25
+ /** The message reached the conversation: the host's when it keeps one (the ref marked `posted`), else the page's. */
26
+ posted: boolean;
27
+ failure?: TurnFailure;
28
+ };
29
+ export type StreamInterfaceTurnBaseArgs = {
30
+ iface: ComposerProfileInterface;
31
+ transport: TheoremTransport;
32
+ session: InterfaceTurnSession;
33
+ scope: RunScope;
34
+ view: StreamView;
35
+ /**
36
+ * Fires once the message posts, with the blocks the transcript gains: a
37
+ * walked-away reply's settled blocks, then the message's own (with media
38
+ * preview data). Walking away, it posts once the host has it.
39
+ */
40
+ onUserBlocks: (blocks: TranscriptBlock[]) => void;
41
+ signal?: AbortSignal;
42
+ /**
43
+ * Send while the reply waits on gates: the message walks away from every
44
+ * waiting call in its own request, and the host settles each one cancelled
45
+ * ahead of the reply. Without it, or in a chat the host keeps no
46
+ * conversation for, a waiting session refuses the send (`session.gate_pending`).
47
+ */
48
+ walkAway?: boolean;
49
+ /**
50
+ * The transcript before this message. Sent once, only when the host answers that it can no
51
+ * longer open the conversation, so a host that restores from it (the studio) goes on.
52
+ */
53
+ transcript?: readonly TranscriptBlock[];
54
+ };
55
+ export type StreamInterfaceTurnArgs = StreamInterfaceTurnBaseArgs & {
56
+ text: string;
57
+ pendingFiles: readonly File[];
58
+ pendingVoice: readonly File[];
59
+ };
60
+ export type StreamInterfaceDraftTurnArgs = StreamInterfaceTurnBaseArgs & {
61
+ draft: UserTurnDraft;
62
+ };
63
+ export declare function streamInterfaceTurn(args: StreamInterfaceTurnArgs): Promise<RunOutcome>;
64
+ /** Send a turn from an already-encoded pending draft (queue drain / send now). */
65
+ export declare function streamInterfaceDraftTurn(args: StreamInterfaceDraftTurnArgs): Promise<RunOutcome>;
66
+ /**
67
+ * Send the user's answer to the gate the session waits on. The host settles
68
+ * the call either way (an approval runs it; a refusal records it declined), so
69
+ * the model and the trace read what the user chose. A host that keeps the
70
+ * conversation goes on with the reply in the same stream once no call waits.
71
+ */
72
+ export declare function resumeInterfaceTool(args: {
73
+ iface: ComposerProfileInterface;
74
+ transport: TheoremTransport;
75
+ session: InterfaceTurnSession;
76
+ scope: RunScope;
77
+ resolution: ToolGateResolution;
78
+ view: StreamView;
79
+ }): Promise<RunOutcome>;