@alexkroman1/aai 0.4.0 → 0.6.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 (249) hide show
  1. package/README.md +0 -6
  2. package/dist/aai.js +3 -0
  3. package/dist/cli.js +244 -245
  4. package/dist/sdk/_internal_types.d.ts +73 -0
  5. package/dist/sdk/_internal_types.d.ts.map +1 -0
  6. package/dist/sdk/_internal_types.js +24 -0
  7. package/dist/sdk/_internal_types.js.map +1 -0
  8. package/dist/sdk/_mock_ws.d.ts +105 -0
  9. package/dist/sdk/_mock_ws.d.ts.map +1 -0
  10. package/dist/sdk/_mock_ws.js +154 -0
  11. package/dist/sdk/_mock_ws.js.map +1 -0
  12. package/dist/sdk/_timeout.d.ts +14 -0
  13. package/dist/sdk/_timeout.d.ts.map +1 -0
  14. package/{sdk/_timeout.ts → dist/sdk/_timeout.js} +9 -9
  15. package/dist/sdk/_timeout.js.map +1 -0
  16. package/dist/sdk/builtin_tools.d.ts +33 -0
  17. package/dist/sdk/builtin_tools.d.ts.map +1 -0
  18. package/dist/sdk/builtin_tools.js +263 -0
  19. package/dist/sdk/builtin_tools.js.map +1 -0
  20. package/dist/sdk/capnweb.d.ts +69 -0
  21. package/dist/sdk/capnweb.d.ts.map +1 -0
  22. package/dist/sdk/capnweb.js +291 -0
  23. package/dist/sdk/capnweb.js.map +1 -0
  24. package/dist/sdk/define_agent.d.ts +36 -0
  25. package/dist/sdk/define_agent.d.ts.map +1 -0
  26. package/dist/sdk/define_agent.js +63 -0
  27. package/dist/sdk/define_agent.js.map +1 -0
  28. package/dist/sdk/direct_executor.d.ts +42 -0
  29. package/dist/sdk/direct_executor.d.ts.map +1 -0
  30. package/dist/sdk/direct_executor.js +143 -0
  31. package/dist/sdk/direct_executor.js.map +1 -0
  32. package/dist/sdk/kv.d.ts +123 -0
  33. package/dist/sdk/kv.d.ts.map +1 -0
  34. package/dist/sdk/kv.js +91 -0
  35. package/dist/sdk/kv.js.map +1 -0
  36. package/{sdk/mod.ts → dist/sdk/mod.d.ts} +2 -11
  37. package/dist/sdk/mod.d.ts.map +1 -0
  38. package/dist/sdk/mod.js +26 -0
  39. package/dist/sdk/mod.js.map +1 -0
  40. package/dist/sdk/protocol.d.ts +218 -0
  41. package/dist/sdk/protocol.d.ts.map +1 -0
  42. package/dist/sdk/protocol.js +140 -0
  43. package/dist/sdk/protocol.js.map +1 -0
  44. package/dist/sdk/runtime.d.ts +35 -0
  45. package/dist/sdk/runtime.d.ts.map +1 -0
  46. package/dist/sdk/runtime.js +46 -0
  47. package/dist/sdk/runtime.js.map +1 -0
  48. package/dist/sdk/s2s.d.ts +60 -0
  49. package/dist/sdk/s2s.d.ts.map +1 -0
  50. package/dist/sdk/s2s.js +171 -0
  51. package/dist/sdk/s2s.js.map +1 -0
  52. package/dist/sdk/server.d.ts +51 -0
  53. package/dist/sdk/server.d.ts.map +1 -0
  54. package/dist/sdk/server.js +145 -0
  55. package/dist/sdk/server.js.map +1 -0
  56. package/dist/sdk/session.d.ts +66 -0
  57. package/dist/sdk/session.d.ts.map +1 -0
  58. package/dist/sdk/session.js +324 -0
  59. package/dist/sdk/session.js.map +1 -0
  60. package/dist/sdk/system_prompt.d.ts +6 -0
  61. package/dist/sdk/system_prompt.d.ts.map +1 -0
  62. package/dist/sdk/system_prompt.js +35 -0
  63. package/dist/sdk/system_prompt.js.map +1 -0
  64. package/dist/sdk/types.d.ts +326 -0
  65. package/dist/sdk/types.d.ts.map +1 -0
  66. package/dist/sdk/types.js +38 -0
  67. package/dist/sdk/types.js.map +1 -0
  68. package/dist/sdk/vector.d.ts +90 -0
  69. package/dist/sdk/vector.d.ts.map +1 -0
  70. package/dist/sdk/vector.js +61 -0
  71. package/dist/sdk/vector.js.map +1 -0
  72. package/dist/sdk/winterc_server.d.ts +53 -0
  73. package/dist/sdk/winterc_server.d.ts.map +1 -0
  74. package/dist/sdk/winterc_server.js +82 -0
  75. package/dist/sdk/winterc_server.js.map +1 -0
  76. package/dist/sdk/worker_entry.d.ts +48 -0
  77. package/dist/sdk/worker_entry.d.ts.map +1 -0
  78. package/dist/sdk/worker_entry.js +67 -0
  79. package/dist/sdk/worker_entry.js.map +1 -0
  80. package/dist/sdk/worker_shim.d.ts +20 -0
  81. package/dist/sdk/worker_shim.d.ts.map +1 -0
  82. package/dist/sdk/worker_shim.js +132 -0
  83. package/dist/sdk/worker_shim.js.map +1 -0
  84. package/dist/sdk/ws_handler.d.ts +50 -0
  85. package/dist/sdk/ws_handler.d.ts.map +1 -0
  86. package/dist/sdk/ws_handler.js +156 -0
  87. package/dist/sdk/ws_handler.js.map +1 -0
  88. package/dist/ui/_components/app.d.ts +3 -0
  89. package/dist/ui/_components/app.d.ts.map +1 -0
  90. package/dist/ui/_components/app.js +14 -0
  91. package/dist/ui/_components/app.js.map +1 -0
  92. package/dist/ui/_components/chat_view.d.ts +3 -0
  93. package/dist/ui/_components/chat_view.d.ts.map +1 -0
  94. package/dist/ui/_components/chat_view.js +14 -0
  95. package/dist/ui/_components/chat_view.js.map +1 -0
  96. package/dist/ui/_components/controls.d.ts +2 -0
  97. package/dist/ui/_components/controls.d.ts.map +1 -0
  98. package/dist/ui/_components/controls.js +11 -0
  99. package/dist/ui/_components/controls.js.map +1 -0
  100. package/dist/ui/_components/error_banner.d.ts +7 -0
  101. package/dist/ui/_components/error_banner.d.ts.map +1 -0
  102. package/dist/ui/_components/error_banner.js +7 -0
  103. package/dist/ui/_components/error_banner.js.map +1 -0
  104. package/dist/ui/_components/message_bubble.d.ts +6 -0
  105. package/dist/ui/_components/message_bubble.d.ts.map +1 -0
  106. package/dist/ui/_components/message_bubble.js +9 -0
  107. package/dist/ui/_components/message_bubble.js.map +1 -0
  108. package/dist/ui/_components/message_list.d.ts +2 -0
  109. package/dist/ui/_components/message_list.d.ts.map +1 -0
  110. package/dist/ui/_components/message_list.js +48 -0
  111. package/dist/ui/_components/message_list.js.map +1 -0
  112. package/dist/ui/_components/state_indicator.d.ts +7 -0
  113. package/dist/ui/_components/state_indicator.d.ts.map +1 -0
  114. package/dist/ui/_components/state_indicator.js +5 -0
  115. package/dist/ui/_components/state_indicator.js.map +1 -0
  116. package/dist/ui/_components/thinking_indicator.d.ts +3 -0
  117. package/dist/ui/_components/thinking_indicator.d.ts.map +1 -0
  118. package/dist/ui/_components/thinking_indicator.js +8 -0
  119. package/dist/ui/_components/thinking_indicator.js.map +1 -0
  120. package/dist/ui/_components/tool_call_block.d.ts +6 -0
  121. package/dist/ui/_components/tool_call_block.d.ts.map +1 -0
  122. package/dist/ui/_components/tool_call_block.js +58 -0
  123. package/dist/ui/_components/tool_call_block.js.map +1 -0
  124. package/dist/ui/_components/tool_icons.d.ts +18 -0
  125. package/dist/ui/_components/tool_icons.d.ts.map +1 -0
  126. package/dist/ui/_components/tool_icons.js +26 -0
  127. package/dist/ui/_components/tool_icons.js.map +1 -0
  128. package/dist/ui/_components/transcript.d.ts +6 -0
  129. package/dist/ui/_components/transcript.d.ts.map +1 -0
  130. package/dist/ui/_components/transcript.js +8 -0
  131. package/dist/ui/_components/transcript.js.map +1 -0
  132. package/dist/ui/_dom_shim.d.ts +7 -0
  133. package/dist/ui/_dom_shim.d.ts.map +1 -0
  134. package/dist/ui/_dom_shim.js +21 -0
  135. package/dist/ui/_dom_shim.js.map +1 -0
  136. package/dist/ui/_test_utils.js +272 -0
  137. package/dist/ui/_test_utils.js.map +1 -0
  138. package/dist/ui/audio.d.ts +46 -0
  139. package/dist/ui/audio.d.ts.map +1 -0
  140. package/dist/ui/audio.js +130 -0
  141. package/dist/ui/audio.js.map +1 -0
  142. package/dist/ui/components.d.ts +36 -0
  143. package/dist/ui/components.d.ts.map +1 -0
  144. package/dist/ui/components.js +32 -0
  145. package/dist/ui/components.js.map +1 -0
  146. package/{ui/components_mod.ts → dist/ui/components_mod.d.ts} +3 -18
  147. package/dist/ui/components_mod.d.ts.map +1 -0
  148. package/dist/ui/components_mod.js +20 -0
  149. package/dist/ui/components_mod.js.map +1 -0
  150. package/dist/ui/mod.d.ts +21 -0
  151. package/dist/ui/mod.d.ts.map +1 -0
  152. package/{ui/mod.ts → dist/ui/mod.js} +3 -29
  153. package/dist/ui/mod.js.map +1 -0
  154. package/dist/ui/mount.d.ts +56 -0
  155. package/dist/ui/mount.d.ts.map +1 -0
  156. package/dist/ui/mount.js +60 -0
  157. package/dist/ui/mount.js.map +1 -0
  158. package/dist/ui/mount_context.d.ts +10 -0
  159. package/dist/ui/mount_context.d.ts.map +1 -0
  160. package/dist/ui/mount_context.js +10 -0
  161. package/dist/ui/mount_context.js.map +1 -0
  162. package/dist/ui/session.d.ts +91 -0
  163. package/dist/ui/session.d.ts.map +1 -0
  164. package/dist/ui/session.js +366 -0
  165. package/dist/ui/session.js.map +1 -0
  166. package/{ui/session_mod.ts → dist/ui/session_mod.d.ts} +2 -10
  167. package/dist/ui/session_mod.d.ts.map +1 -0
  168. package/dist/ui/session_mod.js +18 -0
  169. package/dist/ui/session_mod.js.map +1 -0
  170. package/dist/ui/signals.d.ts +61 -0
  171. package/dist/ui/signals.d.ts.map +1 -0
  172. package/dist/ui/signals.js +74 -0
  173. package/dist/ui/signals.js.map +1 -0
  174. package/dist/ui/types.d.ts +36 -0
  175. package/dist/ui/types.d.ts.map +1 -0
  176. package/dist/ui/types.js +4 -0
  177. package/dist/ui/types.js.map +1 -0
  178. package/package.json +103 -28
  179. package/sdk/_internal_types.ts +0 -89
  180. package/sdk/_mock_ws.ts +0 -172
  181. package/sdk/builtin_tools.ts +0 -309
  182. package/sdk/capnweb.ts +0 -341
  183. package/sdk/define_agent.ts +0 -70
  184. package/sdk/direct_executor.ts +0 -195
  185. package/sdk/kv.ts +0 -183
  186. package/sdk/protocol.ts +0 -313
  187. package/sdk/runtime.ts +0 -65
  188. package/sdk/s2s.ts +0 -271
  189. package/sdk/server.ts +0 -198
  190. package/sdk/session.ts +0 -438
  191. package/sdk/system_prompt.ts +0 -47
  192. package/sdk/types.ts +0 -406
  193. package/sdk/vector.ts +0 -133
  194. package/sdk/winterc_server.ts +0 -141
  195. package/sdk/worker_entry.ts +0 -99
  196. package/sdk/worker_shim.ts +0 -170
  197. package/sdk/ws_handler.ts +0 -190
  198. package/templates/_shared/.env.example +0 -5
  199. package/templates/_shared/package.json +0 -17
  200. package/templates/code-interpreter/agent.ts +0 -27
  201. package/templates/code-interpreter/client.tsx +0 -2
  202. package/templates/dispatch-center/agent.ts +0 -1536
  203. package/templates/dispatch-center/client.tsx +0 -504
  204. package/templates/embedded-assets/agent.ts +0 -49
  205. package/templates/embedded-assets/client.tsx +0 -2
  206. package/templates/embedded-assets/knowledge.json +0 -20
  207. package/templates/health-assistant/agent.ts +0 -160
  208. package/templates/health-assistant/client.tsx +0 -2
  209. package/templates/infocom-adventure/agent.ts +0 -164
  210. package/templates/infocom-adventure/client.tsx +0 -299
  211. package/templates/math-buddy/agent.ts +0 -21
  212. package/templates/math-buddy/client.tsx +0 -2
  213. package/templates/memory-agent/agent.ts +0 -74
  214. package/templates/memory-agent/client.tsx +0 -2
  215. package/templates/night-owl/agent.ts +0 -98
  216. package/templates/night-owl/client.tsx +0 -28
  217. package/templates/personal-finance/agent.ts +0 -26
  218. package/templates/personal-finance/client.tsx +0 -2
  219. package/templates/simple/agent.ts +0 -6
  220. package/templates/simple/client.tsx +0 -2
  221. package/templates/smart-research/agent.ts +0 -164
  222. package/templates/smart-research/client.tsx +0 -2
  223. package/templates/support/README.md +0 -62
  224. package/templates/support/agent.ts +0 -19
  225. package/templates/support/client.tsx +0 -2
  226. package/templates/travel-concierge/agent.ts +0 -29
  227. package/templates/travel-concierge/client.tsx +0 -2
  228. package/templates/web-researcher/agent.ts +0 -17
  229. package/templates/web-researcher/client.tsx +0 -2
  230. package/ui/_components/app.tsx +0 -37
  231. package/ui/_components/chat_view.tsx +0 -36
  232. package/ui/_components/controls.tsx +0 -32
  233. package/ui/_components/error_banner.tsx +0 -18
  234. package/ui/_components/message_bubble.tsx +0 -21
  235. package/ui/_components/message_list.tsx +0 -61
  236. package/ui/_components/state_indicator.tsx +0 -17
  237. package/ui/_components/thinking_indicator.tsx +0 -19
  238. package/ui/_components/tool_call_block.tsx +0 -110
  239. package/ui/_components/tool_icons.tsx +0 -101
  240. package/ui/_components/transcript.tsx +0 -20
  241. package/ui/audio.ts +0 -170
  242. package/ui/components.ts +0 -49
  243. package/ui/mount.tsx +0 -112
  244. package/ui/mount_context.ts +0 -19
  245. package/ui/session.ts +0 -456
  246. package/ui/signals.ts +0 -111
  247. package/ui/types.ts +0 -50
  248. package/ui/worklets/capture-processor.js +0 -62
  249. package/ui/worklets/playback-processor.js +0 -110
@@ -17,32 +17,6 @@
17
17
  *
18
18
  * @module
19
19
  */
20
-
21
- export {
22
- App,
23
- ChatView,
24
- createSessionControls,
25
- ErrorBanner,
26
- MessageBubble,
27
- type MountConfig,
28
- type MountHandle,
29
- type MountOptions,
30
- type MountTheme,
31
- mount,
32
- SessionProvider,
33
- type SessionSignals,
34
- StateIndicator,
35
- ThinkingIndicator,
36
- Transcript,
37
- useMountConfig,
38
- useSession,
39
- } from "./components_mod.ts";
40
- export {
41
- type AgentState,
42
- createVoiceSession,
43
- type Message,
44
- type SessionError,
45
- type SessionErrorCode,
46
- type SessionOptions,
47
- type VoiceSession,
48
- } from "./session_mod.ts";
20
+ export { App, ChatView, createSessionControls, ErrorBanner, MessageBubble, mount, SessionProvider, StateIndicator, ThinkingIndicator, Transcript, useMountConfig, useSession, } from "./components_mod.js";
21
+ export { createVoiceSession, } from "./session_mod.js";
22
+ //# sourceMappingURL=mod.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.js","sourceRoot":"","sources":["../../ui/mod.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACL,GAAG,EACH,QAAQ,EACR,qBAAqB,EACrB,WAAW,EACX,aAAa,EAKb,KAAK,EACL,eAAe,EAEf,cAAc,EACd,iBAAiB,EACjB,UAAU,EACV,cAAc,EACd,UAAU,GACX,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAEL,kBAAkB,GAMnB,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,56 @@
1
+ import type { ComponentType } from "preact";
2
+ import { type VoiceSession } from "./session.ts";
3
+ import { type SessionSignals } from "./signals.ts";
4
+ /** Theme overrides for the default UI. Applied as CSS custom properties. */
5
+ export type MountTheme = {
6
+ /** Background color. Default: `#101010`. */
7
+ bg?: string;
8
+ /** Primary accent color. Default: `#fab283`. */
9
+ primary?: string;
10
+ /** Main text color. */
11
+ text?: string;
12
+ /** Surface/card color. */
13
+ surface?: string;
14
+ /** Border color. */
15
+ border?: string;
16
+ };
17
+ /** Options for {@linkcode mount}. */
18
+ export type MountOptions = {
19
+ /** CSS selector or DOM element to render into. Defaults to `"#app"`. */
20
+ target?: string | HTMLElement;
21
+ /** Base URL of the AAI platform server. Derived from `location.href` by default. */
22
+ platformUrl?: string;
23
+ /** Agent title shown in the header and start screen. */
24
+ title?: string;
25
+ /** Theme color overrides. */
26
+ theme?: MountTheme;
27
+ };
28
+ /**
29
+ * Handle returned by {@linkcode mount} for cleanup.
30
+ *
31
+ * Implements {@linkcode Disposable} so it can be used with `using`.
32
+ */
33
+ export type MountHandle = {
34
+ /** The underlying voice session. */
35
+ session: VoiceSession;
36
+ /** Reactive session controls for the mounted UI. */
37
+ signals: SessionSignals;
38
+ /** Unmount the UI, remove injected styles, and disconnect the session. */
39
+ dispose(): void;
40
+ /** Alias for {@linkcode dispose} for use with `using`. */
41
+ [Symbol.dispose](): void;
42
+ };
43
+ /**
44
+ * Mount a Preact component with voice session wiring.
45
+ *
46
+ * Creates a {@linkcode VoiceSession}, wraps it in
47
+ * {@linkcode SessionSignals}, and renders the component
48
+ * inside a {@linkcode SessionProvider}.
49
+ *
50
+ * @param Component - The Preact component to render.
51
+ * @param options - Mount options (target element, platform URL).
52
+ * @returns A {@linkcode MountHandle} for cleanup.
53
+ * @throws {Error} If the target element is not found in the DOM.
54
+ */
55
+ export declare function mount(Component: ComponentType, options?: MountOptions): MountHandle;
56
+ //# sourceMappingURL=mount.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../../ui/mount.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAG5C,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,EAA0C,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAE3F,4EAA4E;AAC5E,MAAM,MAAM,UAAU,GAAG;IACvB,4CAA4C;IAC5C,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uBAAuB;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0BAA0B;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oBAAoB;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,qCAAqC;AACrC,MAAM,MAAM,YAAY,GAAG;IACzB,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IAC9B,oFAAoF;IACpF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wDAAwD;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,KAAK,CAAC,EAAE,UAAU,CAAC;CACpB,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,oCAAoC;IACpC,OAAO,EAAE,YAAY,CAAC;IACtB,oDAAoD;IACpD,OAAO,EAAE,cAAc,CAAC;IACxB,0EAA0E;IAC1E,OAAO,IAAI,IAAI,CAAC;IAChB,0DAA0D;IAC1D,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;CAC1B,CAAC;AAQF;;;;;;;;;;;GAWG;AACH,wBAAgB,KAAK,CAAC,SAAS,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,WAAW,CA2CnF"}
@@ -0,0 +1,60 @@
1
+ import { jsx as _jsx } from "preact/jsx-runtime";
2
+ import { render } from "preact";
3
+ import { MountConfigProvider } from "./mount_context.js";
4
+ import { createVoiceSession } from "./session.js";
5
+ import { createSessionControls, SessionProvider } from "./signals.js";
6
+ function resolveContainer(target = "#app") {
7
+ const el = typeof target === "string" ? document.querySelector(target) : target;
8
+ if (!el)
9
+ throw new Error(`Element not found: ${target}`);
10
+ return el;
11
+ }
12
+ /**
13
+ * Mount a Preact component with voice session wiring.
14
+ *
15
+ * Creates a {@linkcode VoiceSession}, wraps it in
16
+ * {@linkcode SessionSignals}, and renders the component
17
+ * inside a {@linkcode SessionProvider}.
18
+ *
19
+ * @param Component - The Preact component to render.
20
+ * @param options - Mount options (target element, platform URL).
21
+ * @returns A {@linkcode MountHandle} for cleanup.
22
+ * @throws {Error} If the target element is not found in the DOM.
23
+ */
24
+ export function mount(Component, options) {
25
+ const container = resolveContainer(options?.target);
26
+ const platformUrl = options?.platformUrl ?? globalThis.location.origin + globalThis.location.pathname;
27
+ const session = createVoiceSession({ platformUrl });
28
+ const signals = createSessionControls(session);
29
+ const mountConfig = { title: options?.title, theme: options?.theme };
30
+ // Apply theme overrides as CSS custom properties on the container.
31
+ if (options?.theme) {
32
+ const t = options.theme;
33
+ const el = container;
34
+ if (t.bg)
35
+ el.style.setProperty("--color-aai-bg", t.bg);
36
+ if (t.primary)
37
+ el.style.setProperty("--color-aai-primary", t.primary);
38
+ if (t.text)
39
+ el.style.setProperty("--color-aai-text", t.text);
40
+ if (t.surface)
41
+ el.style.setProperty("--color-aai-surface", t.surface);
42
+ if (t.border)
43
+ el.style.setProperty("--color-aai-border", t.border);
44
+ }
45
+ render(_jsx(MountConfigProvider, { value: mountConfig, children: _jsx(SessionProvider, { value: signals, children: _jsx(Component, {}) }) }), container);
46
+ const handle = {
47
+ session,
48
+ signals,
49
+ dispose() {
50
+ render(null, container);
51
+ signals.dispose();
52
+ session.disconnect();
53
+ },
54
+ [Symbol.dispose]() {
55
+ handle.dispose();
56
+ },
57
+ };
58
+ return handle;
59
+ }
60
+ //# sourceMappingURL=mount.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mount.js","sourceRoot":"","sources":["../../ui/mount.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAqB,MAAM,cAAc,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAuB,MAAM,cAAc,CAAC;AA4C3F,SAAS,gBAAgB,CAAC,SAA+B,MAAM;IAC7D,MAAM,EAAE,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAChF,IAAI,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,MAAM,EAAE,CAAC,CAAC;IACzD,OAAO,EAAiB,CAAC;AAC3B,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,KAAK,CAAC,SAAwB,EAAE,OAAsB;IACpE,MAAM,SAAS,GAAG,gBAAgB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAEpD,MAAM,WAAW,GACf,OAAO,EAAE,WAAW,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC;IACpF,MAAM,OAAO,GAAG,kBAAkB,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAE/C,MAAM,WAAW,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAErE,mEAAmE;IACnE,IAAI,OAAO,EAAE,KAAK,EAAE,CAAC;QACnB,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC;QACxB,MAAM,EAAE,GAAG,SAAwB,CAAC;QACpC,IAAI,CAAC,CAAC,EAAE;YAAE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,gBAAgB,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QACvD,IAAI,CAAC,CAAC,OAAO;YAAE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,qBAAqB,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;QACtE,IAAI,CAAC,CAAC,IAAI;YAAE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,kBAAkB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QAC7D,IAAI,CAAC,CAAC,OAAO;YAAE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,qBAAqB,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;QACtE,IAAI,CAAC,CAAC,MAAM;YAAE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,oBAAoB,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IACrE,CAAC;IAED,MAAM,CACJ,KAAC,mBAAmB,IAAC,KAAK,EAAE,WAAW,YACrC,KAAC,eAAe,IAAC,KAAK,EAAE,OAAO,YAC7B,KAAC,SAAS,KAAG,GACG,GACE,EACtB,SAAS,CACV,CAAC;IAEF,MAAM,MAAM,GAAgB;QAC1B,OAAO;QACP,OAAO;QACP,OAAO;YACL,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YACxB,OAAO,CAAC,OAAO,EAAE,CAAC;YAClB,OAAO,CAAC,UAAU,EAAE,CAAC;QACvB,CAAC;QACD,CAAC,MAAM,CAAC,OAAO,CAAC;YACd,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,CAAC;KACF,CAAC;IACF,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { MountTheme } from "./mount.tsx";
2
+ /** Resolved mount-level configuration available to default UI components. */
3
+ export type MountConfig = {
4
+ title?: string | undefined;
5
+ theme?: MountTheme | undefined;
6
+ };
7
+ export declare const MountConfigProvider: import("preact").Provider<MountConfig>;
8
+ /** Read mount config (title, theme) from the nearest provider. */
9
+ export declare function useMountConfig(): MountConfig;
10
+ //# sourceMappingURL=mount_context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mount_context.d.ts","sourceRoot":"","sources":["../../ui/mount_context.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,6EAA6E;AAC7E,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,KAAK,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CAChC,CAAC;AAIF,eAAO,MAAM,mBAAmB,wCAAe,CAAC;AAEhD,kEAAkE;AAClE,wBAAgB,cAAc,IAAI,WAAW,CAE5C"}
@@ -0,0 +1,10 @@
1
+ // Copyright 2025 the AAI authors. MIT license.
2
+ import { createContext } from "preact";
3
+ import { useContext } from "preact/hooks";
4
+ const Ctx = createContext({});
5
+ export const MountConfigProvider = Ctx.Provider;
6
+ /** Read mount config (title, theme) from the nearest provider. */
7
+ export function useMountConfig() {
8
+ return useContext(Ctx);
9
+ }
10
+ //# sourceMappingURL=mount_context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mount_context.js","sourceRoot":"","sources":["../../ui/mount_context.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAS1C,MAAM,GAAG,GAAG,aAAa,CAAc,EAAE,CAAC,CAAC;AAE3C,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC,QAAQ,CAAC;AAEhD,kEAAkE;AAClE,MAAM,UAAU,cAAc;IAC5B,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC"}
@@ -0,0 +1,91 @@
1
+ import { type Signal } from "@preact/signals";
2
+ import type { ClientEvent, ReadyConfig } from "../sdk/protocol.ts";
3
+ import type { VoiceIO } from "./audio.ts";
4
+ import type { AgentState, Message, SessionError, SessionOptions, ToolCallInfo } from "./types.ts";
5
+ /**
6
+ * A reactive voice session that manages WebSocket communication,
7
+ * audio capture/playback, and agent state transitions.
8
+ *
9
+ * Uses plain JSON text frames and binary audio frames for communication
10
+ * and native WebSocket for the connection.
11
+ *
12
+ * Implements {@linkcode Disposable} for resource cleanup via `using`.
13
+ */
14
+ export type VoiceSession = {
15
+ /** Current agent state (connecting, listening, thinking, etc.). */
16
+ readonly state: Signal<AgentState>;
17
+ /** Chat message history for the session. */
18
+ readonly messages: Signal<Message[]>;
19
+ /** Active tool calls for the current turn. */
20
+ readonly toolCalls: Signal<ToolCallInfo[]>;
21
+ /**
22
+ * Live user utterance from STT/VAD.
23
+ * `null` = not speaking, `""` = speech detected but no text yet,
24
+ * non-empty string = partial/final transcript text.
25
+ */
26
+ readonly userUtterance: Signal<string | null>;
27
+ /** Current session error, or `null` if no error. */
28
+ readonly error: Signal<SessionError | null>;
29
+ /** Disconnection info, or `null` if connected. */
30
+ readonly disconnected: Signal<{
31
+ intentional: boolean;
32
+ } | null>;
33
+ /**
34
+ * Open a WebSocket connection to the server and begin audio capture.
35
+ *
36
+ * @param options - Optional connection options.
37
+ * @param options.signal - An AbortSignal that, when aborted, disconnects the session.
38
+ */
39
+ connect(options?: {
40
+ signal?: AbortSignal;
41
+ }): void;
42
+ /** Cancel the current agent turn and discard in-flight TTS audio. */
43
+ cancel(): void;
44
+ /** Clear messages, transcript, and error state without disconnecting. */
45
+ resetState(): void;
46
+ /** Reset the session: clear state and reconnect. */
47
+ reset(): void;
48
+ /** Close the WebSocket and release all audio resources. */
49
+ disconnect(): void;
50
+ /** Alias for {@linkcode disconnect} for use with `using`. */
51
+ [Symbol.dispose](): void;
52
+ };
53
+ /**
54
+ * Handles server→client messages and updates reactive Preact signals
55
+ * accordingly (state transitions, transcripts, messages, audio playback).
56
+ */
57
+ /** @internal Exported for testing only. */
58
+ export declare class ClientHandler {
59
+ #private;
60
+ constructor(opts: {
61
+ state: Signal<AgentState>;
62
+ messages: Signal<Message[]>;
63
+ toolCalls: Signal<ToolCallInfo[]>;
64
+ userUtterance: Signal<string | null>;
65
+ error: Signal<SessionError | null>;
66
+ voiceIO: () => VoiceIO | null;
67
+ });
68
+ /** Single entry point for all server→client session events. */
69
+ /** Sentinel value indicating speech detected but no transcript yet. */
70
+ static readonly speechActive = "\0";
71
+ event(e: ClientEvent): void;
72
+ playAudioChunk(chunk: Uint8Array): void;
73
+ playAudioDone(): void;
74
+ /**
75
+ * Dispatch an incoming WebSocket message (text or binary).
76
+ *
77
+ * Returns the parsed config if the message is a `config` message,
78
+ * otherwise `null`.
79
+ */
80
+ handleMessage(data: string | ArrayBuffer): ReadyConfig | null;
81
+ }
82
+ /**
83
+ * Create a voice session that connects to an AAI server via WebSocket.
84
+ *
85
+ * Uses plain JSON text frames and binary audio frames for communication.
86
+ *
87
+ * @param options - Session configuration including the platform server URL.
88
+ * @returns A {@linkcode VoiceSession} handle for controlling the session.
89
+ */
90
+ export declare function createVoiceSession(options: SessionOptions): VoiceSession;
91
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../ui/session.ts"],"names":[],"mappings":"AAEA,OAAO,EAAS,KAAK,MAAM,EAAU,MAAM,iBAAiB,CAAC;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAiB,WAAW,EAAiB,MAAM,oBAAoB,CAAC;AAKjG,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAElG;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,mEAAmE;IACnE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IACnC,4CAA4C;IAC5C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IACrC,8CAA8C;IAC9C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;IAC3C;;;;OAIG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC9C,oDAAoD;IACpD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAC5C,kDAAkD;IAClD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;QAAE,WAAW,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IAC/D;;;;;OAKG;IACH,OAAO,CAAC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,IAAI,CAAC;IAClD,qEAAqE;IACrE,MAAM,IAAI,IAAI,CAAC;IACf,yEAAyE;IACzE,UAAU,IAAI,IAAI,CAAC;IACnB,oDAAoD;IACpD,KAAK,IAAI,IAAI,CAAC;IACd,2DAA2D;IAC3D,UAAU,IAAI,IAAI,CAAC;IACnB,6DAA6D;IAC7D,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;CAC1B,CAAC;AAEF;;;GAGG;AACH,2CAA2C;AAC3C,qBAAa,aAAa;;gBASZ,IAAI,EAAE;QAChB,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;QAC1B,QAAQ,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5B,SAAS,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;QAClC,aAAa,EAAE,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;QACrC,KAAK,EAAE,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;QACnC,OAAO,EAAE,MAAM,OAAO,GAAG,IAAI,CAAC;KAC/B;IASD,+DAA+D;IAC/D,uEAAuE;IACvE,MAAM,CAAC,QAAQ,CAAC,YAAY,QAAU;IAEtC,KAAK,CAAC,CAAC,EAAE,WAAW,GAAG,IAAI;IAgF3B,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAQvC,aAAa,IAAI,IAAI;IAarB;;;;;OAKG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,WAAW,GAAG,IAAI;CA6B9D;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,cAAc,GAAG,YAAY,CA2NxE"}
@@ -0,0 +1,366 @@
1
+ // Copyright 2025 the AAI authors. MIT license.
2
+ import { batch, signal } from "@preact/signals";
3
+ import { PROTOCOL_VERSION } from "../sdk/protocol.js";
4
+ const SUPPORTED_PROTOCOL_VERSION = PROTOCOL_VERSION;
5
+ /**
6
+ * Handles server→client messages and updates reactive Preact signals
7
+ * accordingly (state transitions, transcripts, messages, audio playback).
8
+ */
9
+ /** @internal Exported for testing only. */
10
+ export class ClientHandler {
11
+ #state;
12
+ #messages;
13
+ #toolCalls;
14
+ #userUtterance;
15
+ #error;
16
+ #voiceIO;
17
+ /** Incremented on each turn boundary — stale async callbacks compare against this. */
18
+ #generation = 0;
19
+ constructor(opts) {
20
+ this.#state = opts.state;
21
+ this.#messages = opts.messages;
22
+ this.#toolCalls = opts.toolCalls;
23
+ this.#userUtterance = opts.userUtterance;
24
+ this.#error = opts.error;
25
+ this.#voiceIO = opts.voiceIO;
26
+ }
27
+ /** Single entry point for all server→client session events. */
28
+ /** Sentinel value indicating speech detected but no transcript yet. */
29
+ static speechActive = "\x00";
30
+ event(e) {
31
+ switch (e.type) {
32
+ case "speech_started":
33
+ this.#userUtterance.value = "";
34
+ break;
35
+ case "speech_stopped":
36
+ // VAD detected end of speech — processing will follow.
37
+ break;
38
+ case "transcript":
39
+ this.#userUtterance.value = e.text;
40
+ break;
41
+ case "turn":
42
+ this.#generation++;
43
+ batch(() => {
44
+ this.#userUtterance.value = null;
45
+ this.#messages.value = [...this.#messages.value, { role: "user", text: e.text }];
46
+ this.#state.value = "thinking";
47
+ });
48
+ break;
49
+ case "chat":
50
+ this.#messages.value = [...this.#messages.value, { role: "assistant", text: e.text }];
51
+ break;
52
+ case "tool_call_start":
53
+ this.#toolCalls.value = [
54
+ ...this.#toolCalls.value,
55
+ {
56
+ toolCallId: e.toolCallId,
57
+ toolName: e.toolName,
58
+ args: e.args,
59
+ status: "pending",
60
+ afterMessageIndex: this.#messages.value.length - 1,
61
+ },
62
+ ];
63
+ break;
64
+ case "tool_call_done": {
65
+ const tcs = this.#toolCalls.value;
66
+ const idx = tcs.findIndex((tc) => tc.toolCallId === e.toolCallId);
67
+ if (idx !== -1) {
68
+ const updated = [...tcs];
69
+ updated[idx] = { ...updated[idx], status: "done", result: e.result };
70
+ this.#toolCalls.value = updated;
71
+ }
72
+ break;
73
+ }
74
+ case "tts_done":
75
+ // No-audio turns (empty LLM result) still use this event
76
+ // to transition back to listening. Audio turns signal via stream end.
77
+ this.#state.value = "listening";
78
+ break;
79
+ case "cancelled":
80
+ this.#generation++;
81
+ this.#voiceIO()?.flush();
82
+ this.#userUtterance.value = null;
83
+ this.#state.value = "listening";
84
+ break;
85
+ case "reset": {
86
+ this.#generation++;
87
+ this.#voiceIO()?.flush();
88
+ batch(() => {
89
+ this.#messages.value = [];
90
+ this.#toolCalls.value = [];
91
+ this.#userUtterance.value = null;
92
+ this.#error.value = null;
93
+ this.#state.value = "listening";
94
+ });
95
+ break;
96
+ }
97
+ case "error":
98
+ console.error("Agent error:", e.message);
99
+ batch(() => {
100
+ this.#error.value = {
101
+ code: e.code,
102
+ message: e.message,
103
+ };
104
+ this.#state.value = "error";
105
+ });
106
+ break;
107
+ }
108
+ }
109
+ playAudioChunk(chunk) {
110
+ if (this.#state.value === "error")
111
+ return;
112
+ if (this.#state.value !== "speaking") {
113
+ this.#state.value = "speaking";
114
+ }
115
+ this.#voiceIO()?.enqueue(chunk.buffer);
116
+ }
117
+ playAudioDone() {
118
+ const gen = this.#generation;
119
+ const io = this.#voiceIO();
120
+ if (io) {
121
+ void io.done().then(() => {
122
+ if (this.#generation !== gen)
123
+ return;
124
+ this.#state.value = "listening";
125
+ });
126
+ }
127
+ else {
128
+ this.#state.value = "listening";
129
+ }
130
+ }
131
+ /**
132
+ * Dispatch an incoming WebSocket message (text or binary).
133
+ *
134
+ * Returns the parsed config if the message is a `config` message,
135
+ * otherwise `null`.
136
+ */
137
+ handleMessage(data) {
138
+ // Binary frame → raw PCM16 TTS audio
139
+ if (data instanceof ArrayBuffer) {
140
+ this.playAudioChunk(new Uint8Array(data));
141
+ return null;
142
+ }
143
+ // Text frame → JSON message
144
+ let msg;
145
+ try {
146
+ msg = JSON.parse(data);
147
+ }
148
+ catch {
149
+ return null;
150
+ }
151
+ if (msg.type === "config") {
152
+ const { type: _, ...config } = msg;
153
+ return config;
154
+ }
155
+ if (msg.type === "audio_done") {
156
+ this.playAudioDone();
157
+ return null;
158
+ }
159
+ // All other messages are ClientEvent
160
+ this.event(msg);
161
+ return null;
162
+ }
163
+ }
164
+ /**
165
+ * Create a voice session that connects to an AAI server via WebSocket.
166
+ *
167
+ * Uses plain JSON text frames and binary audio frames for communication.
168
+ *
169
+ * @param options - Session configuration including the platform server URL.
170
+ * @returns A {@linkcode VoiceSession} handle for controlling the session.
171
+ */
172
+ export function createVoiceSession(options) {
173
+ const state = signal("disconnected");
174
+ const messages = signal([]);
175
+ const toolCalls = signal([]);
176
+ const userUtterance = signal(null);
177
+ const error = signal(null);
178
+ const disconnected = signal(null);
179
+ let ws = null;
180
+ let voiceIO = null;
181
+ let connectionController = null;
182
+ let hasConnected = false;
183
+ let audioSetupInFlight = false;
184
+ function cleanupAudio() {
185
+ audioSetupInFlight = false;
186
+ void voiceIO?.close();
187
+ voiceIO = null;
188
+ }
189
+ function resetState() {
190
+ batch(() => {
191
+ messages.value = [];
192
+ toolCalls.value = [];
193
+ userUtterance.value = null;
194
+ error.value = null;
195
+ });
196
+ }
197
+ function send(msg) {
198
+ if (ws && ws.readyState === WebSocket.OPEN) {
199
+ ws.send(JSON.stringify(msg));
200
+ }
201
+ }
202
+ function sendBinary(data) {
203
+ if (ws && ws.readyState === WebSocket.OPEN) {
204
+ ws.send(data);
205
+ }
206
+ }
207
+ async function handleReady(msg) {
208
+ if (audioSetupInFlight)
209
+ return;
210
+ // Protocol version check
211
+ if (msg.protocolVersion !== SUPPORTED_PROTOCOL_VERSION) {
212
+ batch(() => {
213
+ error.value = {
214
+ code: "protocol",
215
+ message: `Server protocol v${msg.protocolVersion} is not compatible with client v${SUPPORTED_PROTOCOL_VERSION}. Please redeploy your agent.`,
216
+ };
217
+ state.value = "error";
218
+ });
219
+ return;
220
+ }
221
+ audioSetupInFlight = true;
222
+ try {
223
+ const [{ createVoiceIO }, captureWorklet, playbackWorklet] = await Promise.all([
224
+ import("./audio.js"),
225
+ import("./worklets/capture-processor.js").then((m) => m.default),
226
+ import("./worklets/playback-processor.js").then((m) => m.default),
227
+ ]);
228
+ const io = await createVoiceIO({
229
+ sttSampleRate: msg.sampleRate,
230
+ ttsSampleRate: msg.ttsSampleRate,
231
+ captureWorkletSrc: captureWorklet,
232
+ playbackWorkletSrc: playbackWorklet,
233
+ onMicData: (pcm16) => {
234
+ // Always stream audio — S2S handles VAD natively.
235
+ try {
236
+ sendBinary(pcm16);
237
+ }
238
+ catch {
239
+ /* connection may be closed */
240
+ }
241
+ },
242
+ });
243
+ if (!ws || ws.readyState !== WebSocket.OPEN) {
244
+ io.close();
245
+ return;
246
+ }
247
+ voiceIO = io;
248
+ send({ type: "audio_ready" });
249
+ state.value = "listening";
250
+ }
251
+ catch (err) {
252
+ if (!ws || ws.readyState !== WebSocket.OPEN)
253
+ return;
254
+ batch(() => {
255
+ error.value = {
256
+ code: "audio",
257
+ message: `Microphone access failed: ${err instanceof Error ? err.message : String(err)}`,
258
+ };
259
+ state.value = "error";
260
+ });
261
+ }
262
+ finally {
263
+ audioSetupInFlight = false;
264
+ }
265
+ }
266
+ function connect(opts) {
267
+ disconnected.value = null;
268
+ state.value = "connecting";
269
+ connectionController?.abort();
270
+ const controller = new AbortController();
271
+ connectionController = controller;
272
+ const { signal: sig } = controller;
273
+ if (opts?.signal) {
274
+ opts.signal.addEventListener("abort", () => disconnect(), {
275
+ signal: sig,
276
+ });
277
+ }
278
+ const base = options.platformUrl;
279
+ const wsUrl = new URL("websocket", base.endsWith("/") ? base : `${base}/`);
280
+ wsUrl.protocol = wsUrl.protocol === "https:" ? "wss:" : "ws:";
281
+ if (hasConnected)
282
+ wsUrl.searchParams.set("resume", "1");
283
+ const socket = new WebSocket(wsUrl.toString());
284
+ socket.binaryType = "arraybuffer";
285
+ ws = socket;
286
+ const handler = new ClientHandler({
287
+ state,
288
+ messages,
289
+ toolCalls,
290
+ userUtterance,
291
+ error,
292
+ voiceIO: () => voiceIO,
293
+ });
294
+ socket.addEventListener("open", () => {
295
+ state.value = "ready";
296
+ }, { signal: sig });
297
+ socket.addEventListener("message", (event) => {
298
+ const msgEvent = event;
299
+ const config = handler.handleMessage(msgEvent.data);
300
+ if (config) {
301
+ hasConnected = true;
302
+ void handleReady(config);
303
+ // Send history if reconnecting
304
+ if (hasConnected && messages.value.length > 0) {
305
+ send({
306
+ type: "history",
307
+ messages: messages.value.map((m) => ({
308
+ role: m.role,
309
+ text: m.text,
310
+ })),
311
+ });
312
+ }
313
+ }
314
+ }, { signal: sig });
315
+ socket.addEventListener("close", () => {
316
+ if (sig.aborted) {
317
+ return;
318
+ }
319
+ controller.abort();
320
+ disconnected.value = { intentional: false };
321
+ cleanupAudio();
322
+ state.value = "disconnected";
323
+ }, { signal: sig });
324
+ }
325
+ function cancel() {
326
+ voiceIO?.flush();
327
+ state.value = "listening";
328
+ send({ type: "cancel" });
329
+ }
330
+ function reset() {
331
+ voiceIO?.flush();
332
+ if (ws && ws.readyState === WebSocket.OPEN) {
333
+ send({ type: "reset" });
334
+ return;
335
+ }
336
+ resetState();
337
+ disconnect();
338
+ connect();
339
+ }
340
+ function disconnect() {
341
+ connectionController?.abort();
342
+ connectionController = null;
343
+ cleanupAudio();
344
+ ws?.close();
345
+ ws = null;
346
+ state.value = "disconnected";
347
+ disconnected.value = { intentional: true };
348
+ }
349
+ return {
350
+ state,
351
+ messages,
352
+ toolCalls,
353
+ userUtterance,
354
+ error,
355
+ disconnected,
356
+ connect,
357
+ cancel,
358
+ resetState,
359
+ reset,
360
+ disconnect,
361
+ [Symbol.dispose]() {
362
+ disconnect();
363
+ },
364
+ };
365
+ }
366
+ //# sourceMappingURL=session.js.map