@schlessera/brain-ui-react 0.4.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 (311) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +70 -0
  3. package/dist/components/chat/ask-user-card.d.ts +12 -0
  4. package/dist/components/chat/ask-user-card.d.ts.map +1 -0
  5. package/dist/components/chat/ask-user-card.js +185 -0
  6. package/dist/components/chat/ask-user-card.js.map +1 -0
  7. package/dist/components/chat/brain-markdown.d.ts +35 -0
  8. package/dist/components/chat/brain-markdown.d.ts.map +1 -0
  9. package/dist/components/chat/brain-markdown.js +363 -0
  10. package/dist/components/chat/brain-markdown.js.map +1 -0
  11. package/dist/components/chat/chat-page.d.ts +2 -0
  12. package/dist/components/chat/chat-page.d.ts.map +1 -0
  13. package/dist/components/chat/chat-page.js +442 -0
  14. package/dist/components/chat/chat-page.js.map +1 -0
  15. package/dist/components/chat/command-palette.d.ts +5 -0
  16. package/dist/components/chat/command-palette.d.ts.map +1 -0
  17. package/dist/components/chat/command-palette.js +18 -0
  18. package/dist/components/chat/command-palette.js.map +1 -0
  19. package/dist/components/chat/markdown-content.d.ts +4 -0
  20. package/dist/components/chat/markdown-content.d.ts.map +1 -0
  21. package/dist/components/chat/markdown-content.js +6 -0
  22. package/dist/components/chat/markdown-content.js.map +1 -0
  23. package/dist/components/chat/message-bubble.d.ts +9 -0
  24. package/dist/components/chat/message-bubble.d.ts.map +1 -0
  25. package/dist/components/chat/message-bubble.js +129 -0
  26. package/dist/components/chat/message-bubble.js.map +1 -0
  27. package/dist/components/chat/message-share.d.ts +10 -0
  28. package/dist/components/chat/message-share.d.ts.map +1 -0
  29. package/dist/components/chat/message-share.js +65 -0
  30. package/dist/components/chat/message-share.js.map +1 -0
  31. package/dist/components/chat/renderers/claude-tools.d.ts +3 -0
  32. package/dist/components/chat/renderers/claude-tools.d.ts.map +1 -0
  33. package/dist/components/chat/renderers/claude-tools.js +38 -0
  34. package/dist/components/chat/renderers/claude-tools.js.map +1 -0
  35. package/dist/components/chat/renderers/generic.d.ts +9 -0
  36. package/dist/components/chat/renderers/generic.d.ts.map +1 -0
  37. package/dist/components/chat/renderers/generic.js +68 -0
  38. package/dist/components/chat/renderers/generic.js.map +1 -0
  39. package/dist/components/chat/renderers/index.d.ts +5 -0
  40. package/dist/components/chat/renderers/index.d.ts.map +1 -0
  41. package/dist/components/chat/renderers/index.js +17 -0
  42. package/dist/components/chat/renderers/index.js.map +1 -0
  43. package/dist/components/chat/risk-hints.d.ts +20 -0
  44. package/dist/components/chat/risk-hints.d.ts.map +1 -0
  45. package/dist/components/chat/risk-hints.js +81 -0
  46. package/dist/components/chat/risk-hints.js.map +1 -0
  47. package/dist/components/chat/session-drawer.d.ts +6 -0
  48. package/dist/components/chat/session-drawer.d.ts.map +1 -0
  49. package/dist/components/chat/session-drawer.js +96 -0
  50. package/dist/components/chat/session-drawer.js.map +1 -0
  51. package/dist/components/chat/share-block.d.ts +9 -0
  52. package/dist/components/chat/share-block.d.ts.map +1 -0
  53. package/dist/components/chat/share-block.js +70 -0
  54. package/dist/components/chat/share-block.js.map +1 -0
  55. package/dist/components/chat/tool-call-timeline.d.ts +8 -0
  56. package/dist/components/chat/tool-call-timeline.d.ts.map +1 -0
  57. package/dist/components/chat/tool-call-timeline.js +100 -0
  58. package/dist/components/chat/tool-call-timeline.js.map +1 -0
  59. package/dist/components/chat/tool-views.d.ts +116 -0
  60. package/dist/components/chat/tool-views.d.ts.map +1 -0
  61. package/dist/components/chat/tool-views.js +628 -0
  62. package/dist/components/chat/tool-views.js.map +1 -0
  63. package/dist/components/chat/welcome-state.d.ts +4 -0
  64. package/dist/components/chat/welcome-state.d.ts.map +1 -0
  65. package/dist/components/chat/welcome-state.js +10 -0
  66. package/dist/components/chat/welcome-state.js.map +1 -0
  67. package/dist/components/connectivity/connection-gate.d.ts +5 -0
  68. package/dist/components/connectivity/connection-gate.d.ts.map +1 -0
  69. package/dist/components/connectivity/connection-gate.js +42 -0
  70. package/dist/components/connectivity/connection-gate.js.map +1 -0
  71. package/dist/components/connectivity/login-screen.d.ts +9 -0
  72. package/dist/components/connectivity/login-screen.d.ts.map +1 -0
  73. package/dist/components/connectivity/login-screen.js +99 -0
  74. package/dist/components/connectivity/login-screen.js.map +1 -0
  75. package/dist/components/files/file-panel.d.ts +5 -0
  76. package/dist/components/files/file-panel.d.ts.map +1 -0
  77. package/dist/components/files/file-panel.js +46 -0
  78. package/dist/components/files/file-panel.js.map +1 -0
  79. package/dist/components/files/file-tree.d.ts +2 -0
  80. package/dist/components/files/file-tree.d.ts.map +1 -0
  81. package/dist/components/files/file-tree.js +63 -0
  82. package/dist/components/files/file-tree.js.map +1 -0
  83. package/dist/components/files/file-viewer-binary.d.ts +5 -0
  84. package/dist/components/files/file-viewer-binary.d.ts.map +1 -0
  85. package/dist/components/files/file-viewer-binary.js +20 -0
  86. package/dist/components/files/file-viewer-binary.js.map +1 -0
  87. package/dist/components/files/file-viewer-html.d.ts +4 -0
  88. package/dist/components/files/file-viewer-html.d.ts.map +1 -0
  89. package/dist/components/files/file-viewer-html.js +5 -0
  90. package/dist/components/files/file-viewer-html.js.map +1 -0
  91. package/dist/components/files/file-viewer-markdown.d.ts +4 -0
  92. package/dist/components/files/file-viewer-markdown.d.ts.map +1 -0
  93. package/dist/components/files/file-viewer-markdown.js +10 -0
  94. package/dist/components/files/file-viewer-markdown.js.map +1 -0
  95. package/dist/components/files/file-viewer-raw.d.ts +5 -0
  96. package/dist/components/files/file-viewer-raw.d.ts.map +1 -0
  97. package/dist/components/files/file-viewer-raw.js +15 -0
  98. package/dist/components/files/file-viewer-raw.js.map +1 -0
  99. package/dist/components/files/file-viewer.d.ts +2 -0
  100. package/dist/components/files/file-viewer.d.ts.map +1 -0
  101. package/dist/components/files/file-viewer.js +175 -0
  102. package/dist/components/files/file-viewer.js.map +1 -0
  103. package/dist/components/files/frontmatter-panel.d.ts +5 -0
  104. package/dist/components/files/frontmatter-panel.d.ts.map +1 -0
  105. package/dist/components/files/frontmatter-panel.js +12 -0
  106. package/dist/components/files/frontmatter-panel.js.map +1 -0
  107. package/dist/components/layout/app-shell.d.ts +5 -0
  108. package/dist/components/layout/app-shell.d.ts.map +1 -0
  109. package/dist/components/layout/app-shell.js +10 -0
  110. package/dist/components/layout/app-shell.js.map +1 -0
  111. package/dist/components/layout/mobile-tab-bar.d.ts +2 -0
  112. package/dist/components/layout/mobile-tab-bar.d.ts.map +1 -0
  113. package/dist/components/layout/mobile-tab-bar.js +16 -0
  114. package/dist/components/layout/mobile-tab-bar.js.map +1 -0
  115. package/dist/components/layout/side-rail.d.ts +2 -0
  116. package/dist/components/layout/side-rail.d.ts.map +1 -0
  117. package/dist/components/layout/side-rail.js +26 -0
  118. package/dist/components/layout/side-rail.js.map +1 -0
  119. package/dist/components/layout/slide-panel.d.ts +9 -0
  120. package/dist/components/layout/slide-panel.d.ts.map +1 -0
  121. package/dist/components/layout/slide-panel.js +18 -0
  122. package/dist/components/layout/slide-panel.js.map +1 -0
  123. package/dist/components/quick-actions/streaming-modal.d.ts +8 -0
  124. package/dist/components/quick-actions/streaming-modal.d.ts.map +1 -0
  125. package/dist/components/quick-actions/streaming-modal.js +92 -0
  126. package/dist/components/quick-actions/streaming-modal.js.map +1 -0
  127. package/dist/components/quick-actions/whatsup-modal.d.ts +5 -0
  128. package/dist/components/quick-actions/whatsup-modal.d.ts.map +1 -0
  129. package/dist/components/quick-actions/whatsup-modal.js +82 -0
  130. package/dist/components/quick-actions/whatsup-modal.js.map +1 -0
  131. package/dist/components/settings/passkey-panel.d.ts +10 -0
  132. package/dist/components/settings/passkey-panel.d.ts.map +1 -0
  133. package/dist/components/settings/passkey-panel.js +118 -0
  134. package/dist/components/settings/passkey-panel.js.map +1 -0
  135. package/dist/components/share/share-menu.d.ts +23 -0
  136. package/dist/components/share/share-menu.d.ts.map +1 -0
  137. package/dist/components/share/share-menu.js +58 -0
  138. package/dist/components/share/share-menu.js.map +1 -0
  139. package/dist/components/voice/dictation-sheet.d.ts +6 -0
  140. package/dist/components/voice/dictation-sheet.d.ts.map +1 -0
  141. package/dist/components/voice/dictation-sheet.js +91 -0
  142. package/dist/components/voice/dictation-sheet.js.map +1 -0
  143. package/dist/components/voice/mic-button.d.ts +6 -0
  144. package/dist/components/voice/mic-button.d.ts.map +1 -0
  145. package/dist/components/voice/mic-button.js +9 -0
  146. package/dist/components/voice/mic-button.js.map +1 -0
  147. package/dist/components/voice/review-card.d.ts +8 -0
  148. package/dist/components/voice/review-card.d.ts.map +1 -0
  149. package/dist/components/voice/review-card.js +8 -0
  150. package/dist/components/voice/review-card.js.map +1 -0
  151. package/dist/config.d.ts +19 -0
  152. package/dist/config.d.ts.map +1 -0
  153. package/dist/config.js +10 -0
  154. package/dist/config.js.map +1 -0
  155. package/dist/hooks/use-vpn-status.d.ts +2 -0
  156. package/dist/hooks/use-vpn-status.d.ts.map +1 -0
  157. package/dist/hooks/use-vpn-status.js +71 -0
  158. package/dist/hooks/use-vpn-status.js.map +1 -0
  159. package/dist/hooks/use-websocket.d.ts +8 -0
  160. package/dist/hooks/use-websocket.d.ts.map +1 -0
  161. package/dist/hooks/use-websocket.js +366 -0
  162. package/dist/hooks/use-websocket.js.map +1 -0
  163. package/dist/index.d.ts +25 -0
  164. package/dist/index.d.ts.map +1 -0
  165. package/dist/index.js +31 -0
  166. package/dist/index.js.map +1 -0
  167. package/dist/lib/api-client.d.ts +115 -0
  168. package/dist/lib/api-client.d.ts.map +1 -0
  169. package/dist/lib/api-client.js +70 -0
  170. package/dist/lib/api-client.js.map +1 -0
  171. package/dist/lib/backend.d.ts +7 -0
  172. package/dist/lib/backend.d.ts.map +1 -0
  173. package/dist/lib/backend.js +33 -0
  174. package/dist/lib/backend.js.map +1 -0
  175. package/dist/lib/frontmatter.d.ts +21 -0
  176. package/dist/lib/frontmatter.d.ts.map +1 -0
  177. package/dist/lib/frontmatter.js +88 -0
  178. package/dist/lib/frontmatter.js.map +1 -0
  179. package/dist/lib/image-attachments.d.ts +36 -0
  180. package/dist/lib/image-attachments.d.ts.map +1 -0
  181. package/dist/lib/image-attachments.js +175 -0
  182. package/dist/lib/image-attachments.js.map +1 -0
  183. package/dist/lib/passkeys.d.ts +18 -0
  184. package/dist/lib/passkeys.d.ts.map +1 -0
  185. package/dist/lib/passkeys.js +36 -0
  186. package/dist/lib/passkeys.js.map +1 -0
  187. package/dist/lib/share.d.ts +53 -0
  188. package/dist/lib/share.d.ts.map +1 -0
  189. package/dist/lib/share.js +144 -0
  190. package/dist/lib/share.js.map +1 -0
  191. package/dist/lib/strip-markdown.d.ts +10 -0
  192. package/dist/lib/strip-markdown.d.ts.map +1 -0
  193. package/dist/lib/strip-markdown.js +37 -0
  194. package/dist/lib/strip-markdown.js.map +1 -0
  195. package/dist/lib/tool-names.d.ts +17 -0
  196. package/dist/lib/tool-names.d.ts.map +1 -0
  197. package/dist/lib/tool-names.js +23 -0
  198. package/dist/lib/tool-names.js.map +1 -0
  199. package/dist/lib/utils.d.ts +3 -0
  200. package/dist/lib/utils.d.ts.map +1 -0
  201. package/dist/lib/utils.js +6 -0
  202. package/dist/lib/utils.js.map +1 -0
  203. package/dist/lib/ws-client.d.ts +26 -0
  204. package/dist/lib/ws-client.d.ts.map +1 -0
  205. package/dist/lib/ws-client.js +93 -0
  206. package/dist/lib/ws-client.js.map +1 -0
  207. package/dist/stores/chat-store.d.ts +131 -0
  208. package/dist/stores/chat-store.d.ts.map +1 -0
  209. package/dist/stores/chat-store.js +376 -0
  210. package/dist/stores/chat-store.js.map +1 -0
  211. package/dist/stores/connection-store.d.ts +11 -0
  212. package/dist/stores/connection-store.d.ts.map +1 -0
  213. package/dist/stores/connection-store.js +8 -0
  214. package/dist/stores/connection-store.js.map +1 -0
  215. package/dist/stores/file-store.d.ts +53 -0
  216. package/dist/stores/file-store.d.ts.map +1 -0
  217. package/dist/stores/file-store.js +284 -0
  218. package/dist/stores/file-store.js.map +1 -0
  219. package/dist/stores/provider-store.d.ts +24 -0
  220. package/dist/stores/provider-store.d.ts.map +1 -0
  221. package/dist/stores/provider-store.js +56 -0
  222. package/dist/stores/provider-store.js.map +1 -0
  223. package/dist/stores/ui-store.d.ts +21 -0
  224. package/dist/stores/ui-store.d.ts.map +1 -0
  225. package/dist/stores/ui-store.js +23 -0
  226. package/dist/stores/ui-store.js.map +1 -0
  227. package/dist/styles.css +2 -0
  228. package/dist/voice/asr-clients.d.ts +2 -0
  229. package/dist/voice/asr-clients.d.ts.map +1 -0
  230. package/dist/voice/asr-clients.js +33 -0
  231. package/dist/voice/asr-clients.js.map +1 -0
  232. package/dist/voice/asr-deepgram.d.ts +38 -0
  233. package/dist/voice/asr-deepgram.d.ts.map +1 -0
  234. package/dist/voice/asr-deepgram.js +307 -0
  235. package/dist/voice/asr-deepgram.js.map +1 -0
  236. package/dist/voice/asr-webspeech.d.ts +23 -0
  237. package/dist/voice/asr-webspeech.d.ts.map +1 -0
  238. package/dist/voice/asr-webspeech.js +93 -0
  239. package/dist/voice/asr-webspeech.js.map +1 -0
  240. package/dist/voice/use-dictation.d.ts +6 -0
  241. package/dist/voice/use-dictation.d.ts.map +1 -0
  242. package/dist/voice/use-dictation.js +174 -0
  243. package/dist/voice/use-dictation.js.map +1 -0
  244. package/dist/voice/voice-store.d.ts +26 -0
  245. package/dist/voice/voice-store.d.ts.map +1 -0
  246. package/dist/voice/voice-store.js +27 -0
  247. package/dist/voice/voice-store.js.map +1 -0
  248. package/package.json +71 -0
  249. package/src/components/chat/ask-user-card.tsx +451 -0
  250. package/src/components/chat/brain-markdown.tsx +547 -0
  251. package/src/components/chat/chat-page.tsx +820 -0
  252. package/src/components/chat/command-palette.tsx +68 -0
  253. package/src/components/chat/markdown-content.tsx +5 -0
  254. package/src/components/chat/message-bubble.tsx +362 -0
  255. package/src/components/chat/message-share.ts +78 -0
  256. package/src/components/chat/renderers/claude-tools.tsx +53 -0
  257. package/src/components/chat/renderers/generic.tsx +85 -0
  258. package/src/components/chat/renderers/index.ts +19 -0
  259. package/src/components/chat/risk-hints.ts +95 -0
  260. package/src/components/chat/session-drawer.tsx +213 -0
  261. package/src/components/chat/share-block.tsx +128 -0
  262. package/src/components/chat/tool-call-timeline.tsx +322 -0
  263. package/src/components/chat/tool-views.tsx +898 -0
  264. package/src/components/chat/welcome-state.tsx +105 -0
  265. package/src/components/connectivity/connection-gate.tsx +137 -0
  266. package/src/components/connectivity/login-screen.tsx +169 -0
  267. package/src/components/files/file-panel.tsx +116 -0
  268. package/src/components/files/file-tree.tsx +143 -0
  269. package/src/components/files/file-viewer-binary.tsx +63 -0
  270. package/src/components/files/file-viewer-html.tsx +10 -0
  271. package/src/components/files/file-viewer-markdown.tsx +14 -0
  272. package/src/components/files/file-viewer-raw.tsx +44 -0
  273. package/src/components/files/file-viewer.tsx +290 -0
  274. package/src/components/files/frontmatter-panel.tsx +78 -0
  275. package/src/components/layout/app-shell.tsx +25 -0
  276. package/src/components/layout/mobile-tab-bar.tsx +54 -0
  277. package/src/components/layout/side-rail.tsx +128 -0
  278. package/src/components/layout/slide-panel.tsx +64 -0
  279. package/src/components/quick-actions/streaming-modal.tsx +168 -0
  280. package/src/components/quick-actions/whatsup-modal.tsx +149 -0
  281. package/src/components/settings/passkey-panel.tsx +281 -0
  282. package/src/components/share/share-menu.tsx +121 -0
  283. package/src/components/voice/dictation-sheet.tsx +217 -0
  284. package/src/components/voice/mic-button.tsx +31 -0
  285. package/src/components/voice/review-card.tsx +66 -0
  286. package/src/config.ts +27 -0
  287. package/src/hooks/use-vpn-status.ts +75 -0
  288. package/src/hooks/use-websocket.ts +403 -0
  289. package/src/index.ts +46 -0
  290. package/src/lib/api-client.ts +173 -0
  291. package/src/lib/backend.ts +35 -0
  292. package/src/lib/frontmatter.ts +99 -0
  293. package/src/lib/image-attachments.ts +221 -0
  294. package/src/lib/passkeys.ts +50 -0
  295. package/src/lib/share.ts +167 -0
  296. package/src/lib/strip-markdown.ts +38 -0
  297. package/src/lib/tool-names.ts +27 -0
  298. package/src/lib/utils.ts +6 -0
  299. package/src/lib/ws-client.ts +109 -0
  300. package/src/stores/chat-store.ts +619 -0
  301. package/src/stores/connection-store.ts +23 -0
  302. package/src/stores/file-store.ts +344 -0
  303. package/src/stores/provider-store.ts +85 -0
  304. package/src/stores/ui-store.ts +48 -0
  305. package/src/styles.css +4 -0
  306. package/src/theme.css +425 -0
  307. package/src/voice/asr-clients.ts +45 -0
  308. package/src/voice/asr-deepgram.ts +325 -0
  309. package/src/voice/asr-webspeech.ts +135 -0
  310. package/src/voice/use-dictation.ts +187 -0
  311. package/src/voice/voice-store.ts +55 -0
@@ -0,0 +1,144 @@
1
+ import { API_BASE } from "./backend.js";
2
+ /**
3
+ * True when the browser supports navigator.share at all. Note this doesn't
4
+ * guarantee that a specific payload is shareable — call canShareFiles too.
5
+ */
6
+ export function isShareSupported() {
7
+ return typeof navigator !== "undefined" && typeof navigator.share === "function";
8
+ }
9
+ function canShareFiles(files) {
10
+ if (typeof navigator === "undefined" || typeof navigator.canShare !== "function")
11
+ return false;
12
+ try {
13
+ return navigator.canShare({ files });
14
+ }
15
+ catch {
16
+ return false;
17
+ }
18
+ }
19
+ function triggerDownload(file) {
20
+ const url = URL.createObjectURL(file);
21
+ const a = document.createElement("a");
22
+ a.href = url;
23
+ a.download = file.name;
24
+ document.body.appendChild(a);
25
+ a.click();
26
+ a.remove();
27
+ setTimeout(() => URL.revokeObjectURL(url), 5_000);
28
+ }
29
+ /**
30
+ * Share a File via the OS share sheet. Falls back to a browser download
31
+ * when the platform can't share files (desktop Chrome / Firefox).
32
+ *
33
+ * Returns true if the share dialog (or fallback) was triggered, false if
34
+ * the user dismissed it.
35
+ */
36
+ export async function shareFile(file, opts = {}) {
37
+ if (isShareSupported() && canShareFiles([file])) {
38
+ try {
39
+ await navigator.share({ files: [file], title: opts.title, text: opts.text });
40
+ return true;
41
+ }
42
+ catch (err) {
43
+ // AbortError = user cancelled; anything else falls through to download
44
+ if (err instanceof DOMException && err.name === "AbortError")
45
+ return false;
46
+ console.warn("[share] navigator.share failed, falling back to download:", err);
47
+ }
48
+ }
49
+ triggerDownload(file);
50
+ return true;
51
+ }
52
+ /**
53
+ * Share plain text / a URL via the OS share sheet. Falls back to clipboard
54
+ * copy when unavailable.
55
+ */
56
+ export async function shareText(data) {
57
+ if (isShareSupported()) {
58
+ try {
59
+ await navigator.share({ title: data.title, text: data.text, url: data.url });
60
+ return true;
61
+ }
62
+ catch (err) {
63
+ if (err instanceof DOMException && err.name === "AbortError")
64
+ return false;
65
+ console.warn("[share] navigator.share text failed, falling back to clipboard:", err);
66
+ }
67
+ }
68
+ try {
69
+ await navigator.clipboard.writeText(data.url ? `${data.text}\n${data.url}` : data.text);
70
+ return true;
71
+ }
72
+ catch (err) {
73
+ console.warn("[share] clipboard.writeText failed:", err);
74
+ return false;
75
+ }
76
+ }
77
+ /**
78
+ * Copy rich text (HTML + plain) to the clipboard. Best-effort: on browsers
79
+ * that don't support ClipboardItem, falls back to plain text only.
80
+ */
81
+ export async function copyRichText(html, plain) {
82
+ try {
83
+ if (typeof ClipboardItem !== "undefined" && navigator.clipboard?.write) {
84
+ const item = new ClipboardItem({
85
+ "text/html": new Blob([html], { type: "text/html" }),
86
+ "text/plain": new Blob([plain], { type: "text/plain" }),
87
+ });
88
+ await navigator.clipboard.write([item]);
89
+ return true;
90
+ }
91
+ await navigator.clipboard.writeText(plain);
92
+ return true;
93
+ }
94
+ catch (err) {
95
+ console.warn("[share] copyRichText failed:", err);
96
+ return false;
97
+ }
98
+ }
99
+ /**
100
+ * Fetch a URL into a File. Used to wrap the existing
101
+ * /api/files/content?raw=1 endpoint for share-the-bytes flows.
102
+ */
103
+ export async function fetchAsFile(url, filename, mime) {
104
+ const res = await fetch(url);
105
+ if (!res.ok)
106
+ throw new Error(`fetch failed: ${res.status} ${res.statusText}`);
107
+ const blob = await res.blob();
108
+ return new File([blob], filename, { type: mime ?? blob.type ?? "application/octet-stream" });
109
+ }
110
+ /**
111
+ * POST to /api/render and return the resulting File. Throws on non-2xx.
112
+ */
113
+ export async function renderToFile(req, filename) {
114
+ const res = await fetch(`${API_BASE}/render`, {
115
+ method: "POST",
116
+ headers: { "Content-Type": "application/json" },
117
+ body: JSON.stringify(req),
118
+ });
119
+ if (!res.ok) {
120
+ let detail = res.statusText;
121
+ try {
122
+ const j = await res.json();
123
+ detail = j.detail ?? j.error ?? detail;
124
+ }
125
+ catch {
126
+ // ignore
127
+ }
128
+ throw new Error(`Render failed (${res.status}): ${detail}`);
129
+ }
130
+ const blob = await res.blob();
131
+ const ext = req.format === "png" ? "png" : "pdf";
132
+ const safeBase = filename.replace(/\.(png|pdf|md|html?|txt)$/i, "");
133
+ return new File([blob], `${safeBase}.${ext}`, {
134
+ type: req.format === "png" ? "image/png" : "application/pdf",
135
+ });
136
+ }
137
+ /**
138
+ * One-call helper: render content to PNG/PDF and dispatch the share sheet.
139
+ */
140
+ export async function renderAndShare(opts) {
141
+ const file = await renderToFile({ content: opts.content, contentType: opts.contentType, format: opts.format, title: opts.title }, opts.filename);
142
+ return shareFile(file, { title: opts.title, text: opts.text });
143
+ }
144
+ //# sourceMappingURL=share.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"share.js","sourceRoot":"","sources":["../../src/lib/share.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Best-effort markdown → plain text for sharing. Keeps list structure
3
+ * (lines starting with "- ") and headings (as bare lines), drops syntax.
4
+ *
5
+ * Not a full markdown parser; intended for short snippets pasted into
6
+ * messengers. For correctness we'd want to render to HTML and grab
7
+ * textContent, but that requires a DOM round-trip.
8
+ */
9
+ export declare function stripMarkdown(md: string): string;
10
+ //# sourceMappingURL=strip-markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strip-markdown.d.ts","sourceRoot":"","sources":["../../src/lib/strip-markdown.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CA6BhD"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Best-effort markdown → plain text for sharing. Keeps list structure
3
+ * (lines starting with "- ") and headings (as bare lines), drops syntax.
4
+ *
5
+ * Not a full markdown parser; intended for short snippets pasted into
6
+ * messengers. For correctness we'd want to render to HTML and grab
7
+ * textContent, but that requires a DOM round-trip.
8
+ */
9
+ export function stripMarkdown(md) {
10
+ let s = md;
11
+ // Code fences — keep contents, drop the ``` and language hint
12
+ s = s.replace(/```[a-zA-Z0-9_+-]*\n([\s\S]*?)```/g, (_m, body) => body);
13
+ // Inline code
14
+ s = s.replace(/`([^`\n]+)`/g, "$1");
15
+ // Images: ![alt](url) → alt (or just drop if no alt)
16
+ s = s.replace(/!\[([^\]]*)\]\([^)]*\)/g, (_m, alt) => alt || "");
17
+ // Links: [text](url) → text (url)
18
+ s = s.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_m, text, url) => {
19
+ return text === url ? text : `${text} (${url})`;
20
+ });
21
+ // Bold / italic / strike — drop markers, keep text
22
+ s = s.replace(/(\*\*|__)(.+?)\1/g, "$2");
23
+ s = s.replace(/(\*|_)(.+?)\1/g, "$2");
24
+ s = s.replace(/~~(.+?)~~/g, "$1");
25
+ // Headings: # text → text
26
+ s = s.replace(/^#{1,6}\s+/gm, "");
27
+ // Blockquotes: leading "> "
28
+ s = s.replace(/^>\s?/gm, "");
29
+ // Horizontal rules
30
+ s = s.replace(/^---+$/gm, "");
31
+ // Wikilinks [[slug]] or [[slug|label]] → label or slug
32
+ s = s.replace(/\[\[([^\[\]\n|]+?)(?:\|([^\[\]\n]+?))?\]\]/g, (_m, target, label) => label?.trim() ?? target.trim());
33
+ // Collapse 3+ blank lines to 2
34
+ s = s.replace(/\n{3,}/g, "\n\n");
35
+ return s.trim();
36
+ }
37
+ //# sourceMappingURL=strip-markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strip-markdown.js","sourceRoot":"","sources":["../../src/lib/strip-markdown.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,EAAU;IACtC,IAAI,CAAC,GAAG,EAAE,CAAC;IAEX,8DAA8D;IAC9D,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,oCAAoC,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;IACxE,cAAc;IACd,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;IACpC,qDAAqD;IACrD,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,yBAAyB,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;IACjE,kCAAkC;IAClC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,0BAA0B,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;QAC1D,OAAO,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,GAAG,GAAG,CAAC;IAClD,CAAC,CAAC,CAAC;IACH,mDAAmD;IACnD,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,mBAAmB,EAAE,IAAI,CAAC,CAAC;IACzC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;IACtC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IAClC,0BAA0B;IAC1B,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;IAClC,4BAA4B;IAC5B,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IAC7B,mBAAmB;IACnB,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC9B,uDAAuD;IACvD,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,6CAA6C,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACpH,+BAA+B;IAC/B,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAEjC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;AAClB,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * MCP-prefixed names of brain-ui's own in-process tools, as they appear in the
3
+ * tool-call stream. Kept in one place so the timeline, history reconstruction,
4
+ * and per-tool rendering all agree on the identifiers.
5
+ */
6
+ export declare const ASK_USER_TOOL_NAME = "mcp__brain-ui__ask_user";
7
+ export declare const GET_LOCATION_TOOL_NAME = "mcp__brain-ui__get_current_location";
8
+ /**
9
+ * Pre-rename transcripts used the `mcp__brain_ui__` server prefix; the server is
10
+ * now `mcp__brain-ui__`. Normalize the legacy prefix so old tool calls resolve
11
+ * to the same identifiers (special-card renderers, icons) as new ones instead of
12
+ * falling back to a raw JSON blob.
13
+ */
14
+ export declare function normalizeToolName(name: string): string;
15
+ export declare const isAskUserTool: (name: string | undefined) => boolean;
16
+ export declare const isLocationTool: (name: string | undefined) => boolean;
17
+ //# sourceMappingURL=tool-names.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-names.d.ts","sourceRoot":"","sources":["../../src/lib/tool-names.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,4BAA4B,CAAC;AAC5D,eAAO,MAAM,sBAAsB,wCAAwC,CAAC;AAK5E;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAItD;AAED,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,GAAG,SAAS,KAAG,OACC,CAAC;AAC3D,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,GAAG,SAAS,KAAG,OACI,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * MCP-prefixed names of brain-ui's own in-process tools, as they appear in the
3
+ * tool-call stream. Kept in one place so the timeline, history reconstruction,
4
+ * and per-tool rendering all agree on the identifiers.
5
+ */
6
+ export const ASK_USER_TOOL_NAME = "mcp__brain-ui__ask_user";
7
+ export const GET_LOCATION_TOOL_NAME = "mcp__brain-ui__get_current_location";
8
+ const LEGACY_MCP_PREFIX = "mcp__brain_ui__";
9
+ const MCP_PREFIX = "mcp__brain-ui__";
10
+ /**
11
+ * Pre-rename transcripts used the `mcp__brain_ui__` server prefix; the server is
12
+ * now `mcp__brain-ui__`. Normalize the legacy prefix so old tool calls resolve
13
+ * to the same identifiers (special-card renderers, icons) as new ones instead of
14
+ * falling back to a raw JSON blob.
15
+ */
16
+ export function normalizeToolName(name) {
17
+ return name.startsWith(LEGACY_MCP_PREFIX)
18
+ ? MCP_PREFIX + name.slice(LEGACY_MCP_PREFIX.length)
19
+ : name;
20
+ }
21
+ export const isAskUserTool = (name) => !!name && normalizeToolName(name) === ASK_USER_TOOL_NAME;
22
+ export const isLocationTool = (name) => !!name && normalizeToolName(name) === GET_LOCATION_TOOL_NAME;
23
+ //# sourceMappingURL=tool-names.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-names.js","sourceRoot":"","sources":["../../src/lib/tool-names.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,yBAAyB,CAAC;AAC5D,MAAM,CAAC,MAAM,sBAAsB,GAAG,qCAAqC,CAAC;AAE5E,MAAM,iBAAiB,GAAG,iBAAiB,CAAC;AAC5C,MAAM,UAAU,GAAG,iBAAiB,CAAC;AAErC;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC;QACvC,CAAC,CAAC,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,MAAM,CAAC;QACnD,CAAC,CAAC,IAAI,CAAC;AACX,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,IAAwB,EAAW,EAAE,CACjE,CAAC,CAAC,IAAI,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,kBAAkB,CAAC;AAC3D,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,IAAwB,EAAW,EAAE,CAClE,CAAC,CAAC,IAAI,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,sBAAsB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type ClassValue } from "clsx";
2
+ export declare function cn(...inputs: ClassValue[]): string;
3
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,UAAU,EAAE,MAAM,MAAM,CAAC;AAG7C,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,UAEzC"}
@@ -0,0 +1,6 @@
1
+ import { clsx } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+ export function cn(...inputs) {
4
+ return twMerge(clsx(inputs));
5
+ }
6
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAmB,MAAM,MAAM,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC,MAAM,UAAU,EAAE,CAAC,GAAG,MAAoB;IACxC,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { ClientMessage, ServerMessage } from "@schlessera/brain-ui-sdk/protocol";
2
+ type MessageHandler = (msg: ServerMessage) => void;
3
+ type StatusHandler = (status: "connecting" | "connected" | "disconnected") => void;
4
+ export declare class WSClient {
5
+ private ws;
6
+ private url;
7
+ private onMessage;
8
+ private onStatusChange;
9
+ private reconnectAttempt;
10
+ private reconnectTimer;
11
+ private closed;
12
+ constructor(url: string, onMessage: MessageHandler, onStatusChange: StatusHandler);
13
+ connect(): void;
14
+ send(msg: ClientMessage): void;
15
+ close(): void;
16
+ get isConnected(): boolean;
17
+ /**
18
+ * Skip the remaining backoff and reconnect immediately (e.g. when the
19
+ * browser fires an `online` event). No-op if open/connecting or closed
20
+ * deliberately.
21
+ */
22
+ reconnectNow(): void;
23
+ private scheduleReconnect;
24
+ }
25
+ export {};
26
+ //# sourceMappingURL=ws-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ws-client.d.ts","sourceRoot":"","sources":["../../src/lib/ws-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAEtF,KAAK,cAAc,GAAG,CAAC,GAAG,EAAE,aAAa,KAAK,IAAI,CAAC;AACnD,KAAK,aAAa,GAAG,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW,GAAG,cAAc,KAAK,IAAI,CAAC;AAEnF,qBAAa,QAAQ;IACnB,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,SAAS,CAAiB;IAClC,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,MAAM,CAAS;gBAGrB,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,cAAc,EACzB,cAAc,EAAE,aAAa;IAO/B,OAAO;IAuCP,IAAI,CAAC,GAAG,EAAE,aAAa;IAMvB,KAAK;IAUL,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED;;;;OAIG;IACH,YAAY;IAYZ,OAAO,CAAC,iBAAiB;CAQ1B"}
@@ -0,0 +1,93 @@
1
+ export class WSClient {
2
+ ws = null;
3
+ url;
4
+ onMessage;
5
+ onStatusChange;
6
+ reconnectAttempt = 0;
7
+ reconnectTimer = null;
8
+ closed = false;
9
+ constructor(url, onMessage, onStatusChange) {
10
+ this.url = url;
11
+ this.onMessage = onMessage;
12
+ this.onStatusChange = onStatusChange;
13
+ }
14
+ connect() {
15
+ this.closed = false;
16
+ this.onStatusChange("connecting");
17
+ try {
18
+ this.ws = new WebSocket(this.url);
19
+ this.ws.onopen = () => {
20
+ this.reconnectAttempt = 0;
21
+ this.onStatusChange("connected");
22
+ };
23
+ this.ws.onmessage = (evt) => {
24
+ try {
25
+ const msg = JSON.parse(evt.data);
26
+ this.onMessage(msg);
27
+ }
28
+ catch {
29
+ console.error("[ws] Failed to parse message:", evt.data);
30
+ }
31
+ };
32
+ this.ws.onclose = () => {
33
+ this.onStatusChange("disconnected");
34
+ if (!this.closed) {
35
+ this.scheduleReconnect();
36
+ }
37
+ };
38
+ this.ws.onerror = () => {
39
+ // onclose will fire after onerror
40
+ };
41
+ }
42
+ catch {
43
+ this.onStatusChange("disconnected");
44
+ if (!this.closed) {
45
+ this.scheduleReconnect();
46
+ }
47
+ }
48
+ }
49
+ send(msg) {
50
+ if (this.ws?.readyState === WebSocket.OPEN) {
51
+ this.ws.send(JSON.stringify(msg));
52
+ }
53
+ }
54
+ close() {
55
+ this.closed = true;
56
+ if (this.reconnectTimer) {
57
+ clearTimeout(this.reconnectTimer);
58
+ this.reconnectTimer = null;
59
+ }
60
+ this.ws?.close();
61
+ this.ws = null;
62
+ }
63
+ get isConnected() {
64
+ return this.ws?.readyState === WebSocket.OPEN;
65
+ }
66
+ /**
67
+ * Skip the remaining backoff and reconnect immediately (e.g. when the
68
+ * browser fires an `online` event). No-op if open/connecting or closed
69
+ * deliberately.
70
+ */
71
+ reconnectNow() {
72
+ if (this.closed)
73
+ return;
74
+ const state = this.ws?.readyState;
75
+ if (state === WebSocket.OPEN || state === WebSocket.CONNECTING)
76
+ return;
77
+ if (this.reconnectTimer) {
78
+ clearTimeout(this.reconnectTimer);
79
+ this.reconnectTimer = null;
80
+ }
81
+ this.reconnectAttempt = 0;
82
+ this.connect();
83
+ }
84
+ scheduleReconnect() {
85
+ const delay = Math.min(1000 * 2 ** this.reconnectAttempt, 30000);
86
+ this.reconnectAttempt++;
87
+ this.reconnectTimer = setTimeout(() => {
88
+ this.reconnectTimer = null;
89
+ this.connect();
90
+ }, delay);
91
+ }
92
+ }
93
+ //# sourceMappingURL=ws-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ws-client.js","sourceRoot":"","sources":["../../src/lib/ws-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,131 @@
1
+ import type { MessageSource, MessagePart, AskUserQuestion, AskUserAnnotation } from "@schlessera/brain-ui-sdk/protocol";
2
+ export type { MessagePart };
3
+ export interface ChatMessage {
4
+ id: string;
5
+ role: "user" | "assistant";
6
+ content: string;
7
+ thinking?: string;
8
+ toolCalls: ToolCall[];
9
+ /**
10
+ * Chronological thinking/text/tool segments, in arrival order. `content`,
11
+ * `thinking` and `toolCalls` remain the aggregated views (used for sharing
12
+ * and tool state); `parts` drives rendering order.
13
+ */
14
+ parts: MessagePart[];
15
+ isStreaming: boolean;
16
+ timestamp: number;
17
+ source?: MessageSource;
18
+ /** AskUserQuestion exchanges raised during this assistant turn. */
19
+ askUserExchanges?: AskUserExchange[];
20
+ /**
21
+ * Image attachments on a user message. Live messages carry a local
22
+ * `previewUrl` (object URL, revoked on clear). History-loaded messages
23
+ * carry no data — only `attachmentCount` — since base64 is never replayed.
24
+ */
25
+ attachments?: MessageAttachment[];
26
+ /** Attachment count for history-loaded messages without preview data. */
27
+ attachmentCount?: number;
28
+ }
29
+ export interface MessageAttachment {
30
+ previewUrl: string;
31
+ mediaType: string;
32
+ }
33
+ export interface ToolCall {
34
+ id: string;
35
+ name: string;
36
+ input: Record<string, unknown>;
37
+ inputJson: string;
38
+ output?: string;
39
+ isError?: boolean;
40
+ status: "streaming" | "pending_approval" | "approved" | "denied" | "complete";
41
+ /**
42
+ * Execution timing for the duration badge. `startedAt` is (re)stamped when
43
+ * the input finishes streaming or an approval is granted — so approval
44
+ * wait time doesn't inflate the reported duration. `endedAt` is stamped by
45
+ * the tool result. History-loaded messages carry no timing.
46
+ */
47
+ startedAt?: number;
48
+ endedAt?: number;
49
+ }
50
+ export interface AskUserExchange {
51
+ requestId: string;
52
+ questions: AskUserQuestion[];
53
+ /** Filled in once the user submits. Keyed by question text. */
54
+ answers?: Record<string, string>;
55
+ annotations?: Record<string, AskUserAnnotation>;
56
+ cancelled?: boolean;
57
+ }
58
+ /**
59
+ * One session's live transcript state. Every session the user has viewed (or
60
+ * that bound from the draft) keeps its own buffer, so frames from a background
61
+ * session accumulate in THAT session's transcript instead of being discarded —
62
+ * the multi-session contract the old single-active-buffer store violated.
63
+ */
64
+ export interface SessionChat {
65
+ messages: ChatMessage[];
66
+ isStreaming: boolean;
67
+ /**
68
+ * The currently-pending ask-user exchange in this session (no answers yet).
69
+ * Mirrors the same exchange that lives on the streaming assistant message;
70
+ * held here for fast lookup by hooks/components.
71
+ */
72
+ askUser: AskUserExchange | null;
73
+ /** LRU stamp for buffer eviction. */
74
+ lastTouched: number;
75
+ }
76
+ /**
77
+ * Buffer key: a server sessionId, or null for the DRAFT buffer — the new
78
+ * conversation that has no server identity yet. `session_info` re-keys the
79
+ * draft onto its real sessionId via bindDraftSession().
80
+ */
81
+ export type ChatKey = string | null;
82
+ interface ChatState {
83
+ /** Per-session transcript buffers, keyed by server sessionId. */
84
+ buffers: Record<string, SessionChat>;
85
+ /** The unbound new-conversation buffer, if one is in progress. */
86
+ draft: SessionChat | null;
87
+ /** The session in view; null = the draft / new-chat view. */
88
+ activeSessionId: string | null;
89
+ /**
90
+ * Live run-state per session id, for the session-list badges. Maintained for
91
+ * every session frame regardless of whether a buffer exists. "idle" is the
92
+ * absence of a running/queued turn.
93
+ */
94
+ runStates: Record<string, "streaming" | "queued" | "idle">;
95
+ addUserMessage: (key: ChatKey, text: string, source?: MessageSource, attachments?: MessageAttachment[]) => void;
96
+ startAssistantMessage: (key: ChatKey) => void;
97
+ appendText: (key: ChatKey, text: string) => void;
98
+ appendThinking: (key: ChatKey, text: string) => void;
99
+ startToolCall: (key: ChatKey, toolUseId: string, toolName: string) => void;
100
+ appendToolInput: (key: ChatKey, partialJson: string) => void;
101
+ completeToolCall: (key: ChatKey, toolUseId: string, toolName: string, input: Record<string, unknown>) => void;
102
+ requestToolApproval: (key: ChatKey, toolUseId: string, toolName: string, input: Record<string, unknown>, description?: string) => void;
103
+ resolveToolApproval: (key: ChatKey, toolUseId: string, approved: boolean) => void;
104
+ setToolResult: (key: ChatKey, toolUseId: string, output: string, isError: boolean) => void;
105
+ setAskUserRequest: (key: ChatKey, requestId: string, questions: AskUserQuestion[]) => void;
106
+ submitAskUserAnswers: (key: ChatKey, requestId: string, answers: Record<string, string>, annotations?: Record<string, AskUserAnnotation>) => void;
107
+ cancelAskUser: (key: ChatKey, requestId: string) => void;
108
+ clearAskUser: (key: ChatKey) => void;
109
+ finishAssistantMessage: (key: ChatKey) => void;
110
+ setStreaming: (key: ChatKey, streaming: boolean) => void;
111
+ /** Replace a session's transcript (first replayed history chunk). Creates the buffer. */
112
+ setMessages: (key: ChatKey, messages: ChatMessage[]) => void;
113
+ /** Concatenate a continuation chunk of replayed history. Creates the buffer. */
114
+ appendMessages: (key: ChatKey, messages: ChatMessage[]) => void;
115
+ /**
116
+ * Adopt the draft buffer as `sessionId` (the server just named the session).
117
+ * If the draft view is active, the view follows. No-op draft = empty buffer.
118
+ */
119
+ bindDraftSession: (sessionId: string) => void;
120
+ /** Switch the view to a session (creating an empty buffer if none), or to the draft (null). */
121
+ setActiveSession: (sessionId: string | null) => void;
122
+ /** New chat: drop the draft, unbind the view, unpin the provider. */
123
+ clearMessages: () => void;
124
+ setRunState: (sessionId: string, state: "streaming" | "queued" | "idle") => void;
125
+ }
126
+ /** The buffer currently in view (draft when no session is bound). */
127
+ export declare function activeChat(state: ChatState): SessionChat;
128
+ /** True when ANY buffer is streaming (service-worker busy check, etc.). */
129
+ export declare function anyStreaming(state: ChatState): boolean;
130
+ export declare const useChatStore: import("zustand").UseBoundStore<import("zustand").StoreApi<ChatState>>;
131
+ //# sourceMappingURL=chat-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-store.d.ts","sourceRoot":"","sources":["../../src/stores/chat-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,aAAa,EACb,WAAW,EACX,eAAe,EACf,iBAAiB,EAClB,MAAM,mCAAmC,CAAC;AAG3C,YAAY,EAAE,WAAW,EAAE,CAAC;AAE5B,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB;;;;OAIG;IACH,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAC;IACrC;;;;OAIG;IACH,WAAW,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAClC,yEAAyE;IACzE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,WAAW,GAAG,kBAAkB,GAAG,UAAU,GAAG,QAAQ,GAAG,UAAU,CAAC;IAC9E;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAChD,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,WAAW,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,OAAO,EAAE,eAAe,GAAG,IAAI,CAAC;IAChC,qCAAqC;IACrC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;AAKpC,UAAU,SAAS;IACjB,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACrC,kEAAkE;IAClE,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;IAC1B,6DAA6D;IAC7D,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAE/B;;;;OAIG;IACH,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAC,CAAC;IAG3D,cAAc,EAAE,CACd,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,aAAa,EACtB,WAAW,CAAC,EAAE,iBAAiB,EAAE,KAC9B,IAAI,CAAC;IACV,qBAAqB,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9C,UAAU,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,cAAc,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrD,aAAa,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3E,eAAe,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7D,gBAAgB,EAAE,CAChB,GAAG,EAAE,OAAO,EACZ,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC3B,IAAI,CAAC;IACV,mBAAmB,EAAE,CACnB,GAAG,EAAE,OAAO,EACZ,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,WAAW,CAAC,EAAE,MAAM,KACjB,IAAI,CAAC;IACV,mBAAmB,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAClF,aAAa,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3F,iBAAiB,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,KAAK,IAAI,CAAC;IAC3F,oBAAoB,EAAE,CACpB,GAAG,EAAE,OAAO,EACZ,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,KAC5C,IAAI,CAAC;IACV,aAAa,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,YAAY,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IACrC,sBAAsB,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/C,YAAY,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IACzD,yFAAyF;IACzF,WAAW,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,IAAI,CAAC;IAC7D,gFAAgF;IAChF,cAAc,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,IAAI,CAAC;IAGhE;;;OAGG;IACH,gBAAgB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,+FAA+F;IAC/F,gBAAgB,EAAE,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACrD,qEAAqE;IACrE,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,QAAQ,GAAG,MAAM,KAAK,IAAI,CAAC;CAClF;AAqCD,qEAAqE;AACrE,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,WAAW,CAGxD;AAED,2EAA2E;AAC3E,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAGtD;AA0CD,eAAO,MAAM,YAAY,wEAgWvB,CAAC"}