@signalcore/ui 0.1.0 → 1.0.0-beta.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 (611) hide show
  1. package/README.md +896 -513
  2. package/dist/AgentAbout.d.ts +186 -0
  3. package/dist/AgentAbout.js +1020 -0
  4. package/dist/AgentAbout.js.map +1 -0
  5. package/dist/AgentCard.d.ts +49 -0
  6. package/dist/AgentCard.js +77 -0
  7. package/dist/AgentCard.js.map +1 -0
  8. package/dist/AgentChat.d.ts +233 -0
  9. package/dist/AgentChat.js +1119 -0
  10. package/dist/AgentChat.js.map +1 -0
  11. package/dist/AgentSpace.d.ts +112 -0
  12. package/dist/AgentSpace.js +339 -0
  13. package/dist/AgentSpace.js.map +1 -0
  14. package/dist/AgentTasks.d.ts +48 -0
  15. package/dist/AgentTasks.js +120 -0
  16. package/dist/AgentTasks.js.map +1 -0
  17. package/dist/BrowserView.d.ts +52 -0
  18. package/dist/BrowserView.js +328 -0
  19. package/dist/BrowserView.js.map +1 -0
  20. package/dist/FileView.d.ts +63 -0
  21. package/dist/FileView.js +449 -0
  22. package/dist/FileView.js.map +1 -0
  23. package/dist/Modes.d.ts +13 -0
  24. package/dist/Modes.js +75 -0
  25. package/dist/Modes.js.map +1 -0
  26. package/dist/VoiceCall.d.ts +91 -0
  27. package/dist/VoiceCall.js +302 -0
  28. package/dist/VoiceCall.js.map +1 -0
  29. package/dist/about.d.ts +212 -0
  30. package/dist/about.js +136 -0
  31. package/dist/about.js.map +1 -0
  32. package/dist/agentIcons.d.ts +33 -0
  33. package/dist/agentIcons.js +36 -0
  34. package/dist/agentIcons.js.map +1 -0
  35. package/dist/automation/Automation.d.ts +35 -0
  36. package/dist/automation/Automation.js +268 -0
  37. package/dist/automation/Automation.js.map +1 -0
  38. package/dist/automation/RunView.d.ts +25 -0
  39. package/dist/automation/RunView.js +187 -0
  40. package/dist/automation/RunView.js.map +1 -0
  41. package/dist/automation/cron.d.ts +41 -0
  42. package/dist/automation/cron.js +169 -0
  43. package/dist/automation/cron.js.map +1 -0
  44. package/dist/automation/marks.js +121 -0
  45. package/dist/automation/marks.js.map +1 -0
  46. package/dist/automation/messages.d.ts +113 -0
  47. package/dist/automation/messages.js +113 -0
  48. package/dist/automation/messages.js.map +1 -0
  49. package/dist/automation/record.d.ts +47 -0
  50. package/dist/automation/record.js +177 -0
  51. package/dist/automation/record.js.map +1 -0
  52. package/dist/automation/types.d.ts +143 -0
  53. package/dist/automation/when.d.ts +36 -0
  54. package/dist/automation/when.js +168 -0
  55. package/dist/automation/when.js.map +1 -0
  56. package/dist/blocks.d.ts +185 -0
  57. package/dist/browser.js +292 -0
  58. package/dist/browser.js.map +1 -0
  59. package/dist/call.d.ts +89 -0
  60. package/dist/call.js +218 -0
  61. package/dist/call.js.map +1 -0
  62. package/dist/channelParts.js +26 -0
  63. package/dist/channelParts.js.map +1 -0
  64. package/dist/classes.js +8 -3
  65. package/dist/classes.js.map +1 -0
  66. package/dist/client.d.ts +146 -54
  67. package/dist/client.js +204 -1
  68. package/dist/client.js.map +1 -0
  69. package/dist/conversationFiles.js +46 -0
  70. package/dist/conversationFiles.js.map +1 -0
  71. package/dist/credentials.d.ts +45 -0
  72. package/dist/credentials.js +98 -0
  73. package/dist/credentials.js.map +1 -0
  74. package/dist/dev.js +17 -0
  75. package/dist/dev.js.map +1 -0
  76. package/dist/es.d.ts +17 -0
  77. package/dist/es.js +382 -0
  78. package/dist/es.js.map +1 -0
  79. package/dist/files.d.ts +21 -0
  80. package/dist/files.js +214 -0
  81. package/dist/files.js.map +1 -0
  82. package/dist/frames.d.ts +115 -0
  83. package/dist/frames.js +219 -0
  84. package/dist/frames.js.map +1 -0
  85. package/dist/icons.js +29 -0
  86. package/dist/icons.js.map +1 -0
  87. package/dist/index.d.ts +63 -60
  88. package/dist/index.js +59 -45
  89. package/dist/kit/AudioPlayer.d.ts +20 -0
  90. package/dist/kit/AudioPlayer.js +116 -0
  91. package/dist/kit/AudioPlayer.js.map +1 -0
  92. package/dist/kit/Button.d.ts +29 -0
  93. package/dist/kit/Button.js +59 -0
  94. package/dist/kit/Button.js.map +1 -0
  95. package/dist/kit/Card.d.ts +16 -0
  96. package/dist/kit/Card.js +36 -0
  97. package/dist/kit/Card.js.map +1 -0
  98. package/dist/kit/Chart.js +152 -0
  99. package/dist/kit/Chart.js.map +1 -0
  100. package/dist/kit/Choices.d.ts +21 -0
  101. package/dist/kit/Choices.js +99 -0
  102. package/dist/kit/Choices.js.map +1 -0
  103. package/dist/kit/Combobox.d.ts +26 -0
  104. package/dist/kit/Combobox.js +190 -0
  105. package/dist/kit/Combobox.js.map +1 -0
  106. package/dist/kit/DateField.d.ts +17 -0
  107. package/dist/kit/DateField.js +133 -0
  108. package/dist/kit/DateField.js.map +1 -0
  109. package/dist/kit/Field.d.ts +40 -0
  110. package/dist/kit/Field.js +98 -0
  111. package/dist/kit/Field.js.map +1 -0
  112. package/dist/kit/FileField.d.ts +113 -0
  113. package/dist/kit/FileField.js +341 -0
  114. package/dist/kit/FileField.js.map +1 -0
  115. package/dist/kit/FileMark.d.ts +15 -0
  116. package/dist/kit/FileMark.js +39 -0
  117. package/dist/kit/FileMark.js.map +1 -0
  118. package/dist/kit/Inputs.d.ts +59 -0
  119. package/dist/kit/Inputs.js +205 -0
  120. package/dist/kit/Inputs.js.map +1 -0
  121. package/dist/kit/List.d.ts +47 -0
  122. package/dist/kit/List.js +85 -0
  123. package/dist/kit/List.js.map +1 -0
  124. package/dist/kit/Mark.d.ts +30 -0
  125. package/dist/kit/Mark.js +27 -0
  126. package/dist/kit/Mark.js.map +1 -0
  127. package/dist/kit/MarkStack.d.ts +15 -0
  128. package/dist/kit/MarkStack.js +26 -0
  129. package/dist/kit/MarkStack.js.map +1 -0
  130. package/dist/kit/Note.d.ts +11 -0
  131. package/dist/kit/Note.js +31 -0
  132. package/dist/kit/Note.js.map +1 -0
  133. package/dist/kit/Popover.js +90 -0
  134. package/dist/kit/Popover.js.map +1 -0
  135. package/dist/kit/RangeField.d.ts +14 -0
  136. package/dist/kit/RangeField.js +47 -0
  137. package/dist/kit/RangeField.js.map +1 -0
  138. package/dist/kit/RatingField.d.ts +14 -0
  139. package/dist/kit/RatingField.js +50 -0
  140. package/dist/kit/RatingField.js.map +1 -0
  141. package/dist/kit/Stat.d.ts +26 -0
  142. package/dist/kit/Stat.js +46 -0
  143. package/dist/kit/Stat.js.map +1 -0
  144. package/dist/kit/Switch.d.ts +14 -0
  145. package/dist/kit/Switch.js +21 -0
  146. package/dist/kit/Switch.js.map +1 -0
  147. package/dist/kit/Tag.d.ts +16 -0
  148. package/dist/kit/Tag.js +20 -0
  149. package/dist/kit/Tag.js.map +1 -0
  150. package/dist/kit/Tile.d.ts +34 -0
  151. package/dist/kit/Tile.js +52 -0
  152. package/dist/kit/Tile.js.map +1 -0
  153. package/dist/kit/TimeField.d.ts +31 -0
  154. package/dist/kit/TimeField.js +109 -0
  155. package/dist/kit/TimeField.js.map +1 -0
  156. package/dist/kit/context.d.ts +22 -0
  157. package/dist/kit/context.js +46 -0
  158. package/dist/kit/context.js.map +1 -0
  159. package/dist/kit/dates.d.ts +14 -0
  160. package/dist/kit/dates.js +129 -0
  161. package/dist/kit/dates.js.map +1 -0
  162. package/dist/kit/messages.d.ts +99 -0
  163. package/dist/kit/messages.js +66 -0
  164. package/dist/kit/messages.js.map +1 -0
  165. package/dist/kit/numbers.d.ts +12 -0
  166. package/dist/kit/numbers.js +40 -0
  167. package/dist/kit/numbers.js.map +1 -0
  168. package/dist/kit/options.d.ts +10 -0
  169. package/dist/kit/options.js +23 -0
  170. package/dist/kit/options.js.map +1 -0
  171. package/dist/kit/uploads.d.ts +42 -0
  172. package/dist/kit/uploads.js +165 -0
  173. package/dist/kit/uploads.js.map +1 -0
  174. package/dist/kit/waveform.js +76 -0
  175. package/dist/kit/waveform.js.map +1 -0
  176. package/dist/locale.d.ts +1 -0
  177. package/dist/locale.js +1 -0
  178. package/dist/markdown.js +84 -0
  179. package/dist/markdown.js.map +1 -0
  180. package/dist/marks.js +217 -0
  181. package/dist/marks.js.map +1 -0
  182. package/dist/reveal.js +48 -0
  183. package/dist/reveal.js.map +1 -0
  184. package/dist/stepGlyphs.js +62 -0
  185. package/dist/stepGlyphs.js.map +1 -0
  186. package/dist/surface/Form.js +264 -0
  187. package/dist/surface/Form.js.map +1 -0
  188. package/dist/surface/Markdown.js +42 -0
  189. package/dist/surface/Markdown.js.map +1 -0
  190. package/dist/surface/Surface.d.ts +31 -17
  191. package/dist/surface/Surface.js +480 -57
  192. package/dist/surface/Surface.js.map +1 -0
  193. package/dist/surface/scope.d.ts +32 -0
  194. package/dist/surface/scope.js +23 -0
  195. package/dist/surface/scope.js.map +1 -0
  196. package/dist/surface/values.d.ts +44 -0
  197. package/dist/surface/values.js +237 -0
  198. package/dist/surface/values.js.map +1 -0
  199. package/dist/tint.d.ts +10 -0
  200. package/dist/tint.js +19 -0
  201. package/dist/tint.js.map +1 -0
  202. package/dist/types.d.ts +534 -0
  203. package/dist/types.js +16 -0
  204. package/dist/types.js.map +1 -0
  205. package/dist/useAgentFace.d.ts +18 -0
  206. package/dist/useAgentFace.js +45 -0
  207. package/dist/useAgentFace.js.map +1 -0
  208. package/dist/useCall.d.ts +39 -0
  209. package/dist/useCall.js +273 -0
  210. package/dist/useCall.js.map +1 -0
  211. package/dist/useConversation.d.ts +77 -0
  212. package/dist/useConversation.js +523 -0
  213. package/dist/useConversation.js.map +1 -0
  214. package/dist/useDictation.d.ts +17 -0
  215. package/dist/useDictation.js +68 -0
  216. package/dist/useDictation.js.map +1 -0
  217. package/dist/useLive.d.ts +26 -0
  218. package/dist/useLive.js +88 -0
  219. package/dist/useLive.js.map +1 -0
  220. package/dist/usePolled.js +68 -0
  221. package/dist/usePolled.js.map +1 -0
  222. package/dist/voice/Orb.d.ts +10 -9
  223. package/dist/voice/Orb.js +43 -39
  224. package/dist/voice/Orb.js.map +1 -0
  225. package/dist/voice/StillOrb.js +33 -0
  226. package/dist/voice/StillOrb.js.map +1 -0
  227. package/dist/voice/WebGLOrb.js +98 -0
  228. package/dist/voice/WebGLOrb.js.map +1 -0
  229. package/dist/voice/fluidDots.js +161 -0
  230. package/dist/voice/fluidDots.js.map +1 -0
  231. package/dist/voice/motion.js +84 -0
  232. package/dist/voice/motion.js.map +1 -0
  233. package/dist/voice/orbs.d.ts +32 -0
  234. package/dist/voice/orbs.js +16 -0
  235. package/dist/voice/orbs.js.map +1 -0
  236. package/dist/voice/useReducedMotion.js +16 -16
  237. package/dist/voice/useReducedMotion.js.map +1 -0
  238. package/dist/voice/wave.js +116 -0
  239. package/dist/voice/wave.js.map +1 -0
  240. package/dist/voice/webgl.js +177 -0
  241. package/dist/voice/webgl.js.map +1 -0
  242. package/dist/widget.js +284 -8
  243. package/package.json +49 -39
  244. package/src/AgentAbout.tsx +1621 -0
  245. package/src/AgentCard.tsx +123 -0
  246. package/src/AgentChat.tsx +1795 -0
  247. package/src/AgentSpace.tsx +540 -0
  248. package/src/AgentTasks.tsx +163 -0
  249. package/src/BrowserView.tsx +442 -0
  250. package/src/FileView.tsx +620 -0
  251. package/src/Modes.tsx +112 -0
  252. package/src/VoiceCall.tsx +411 -0
  253. package/src/about.ts +355 -0
  254. package/src/agentIcons.ts +56 -0
  255. package/src/automation/Automation.tsx +308 -0
  256. package/src/automation/RunView.tsx +213 -0
  257. package/src/automation/cron.ts +196 -0
  258. package/src/automation/marks.tsx +144 -0
  259. package/src/automation/messages.ts +231 -0
  260. package/src/automation/record.ts +206 -0
  261. package/src/automation/types.ts +146 -0
  262. package/src/automation/when.ts +195 -0
  263. package/src/blocks.ts +249 -0
  264. package/src/browser.ts +334 -0
  265. package/src/call.ts +300 -0
  266. package/src/channelParts.ts +17 -0
  267. package/src/classes.ts +10 -0
  268. package/src/client.ts +397 -0
  269. package/src/conversationFiles.ts +54 -0
  270. package/src/credentials.ts +158 -0
  271. package/src/dev.ts +20 -0
  272. package/src/es.ts +423 -0
  273. package/src/files.ts +238 -0
  274. package/src/frames.ts +291 -0
  275. package/src/icons.tsx +49 -0
  276. package/src/index.ts +270 -0
  277. package/src/kit/AudioPlayer.tsx +129 -0
  278. package/src/kit/Button.tsx +97 -0
  279. package/src/kit/Card.tsx +47 -0
  280. package/src/kit/Chart.tsx +129 -0
  281. package/src/kit/Choices.tsx +131 -0
  282. package/src/kit/Combobox.tsx +247 -0
  283. package/src/kit/DateField.tsx +156 -0
  284. package/src/kit/Field.tsx +137 -0
  285. package/src/kit/FileField.tsx +492 -0
  286. package/src/kit/FileMark.tsx +56 -0
  287. package/src/kit/Inputs.tsx +250 -0
  288. package/src/kit/List.tsx +135 -0
  289. package/src/kit/Mark.tsx +64 -0
  290. package/src/kit/MarkStack.tsx +29 -0
  291. package/src/kit/Note.tsx +42 -0
  292. package/src/kit/Popover.tsx +121 -0
  293. package/src/kit/RangeField.tsx +53 -0
  294. package/src/kit/RatingField.tsx +62 -0
  295. package/src/kit/Stat.tsx +60 -0
  296. package/src/kit/Switch.tsx +28 -0
  297. package/src/kit/Tag.tsx +32 -0
  298. package/src/kit/Tile.tsx +74 -0
  299. package/src/kit/TimeField.tsx +157 -0
  300. package/src/kit/context.tsx +246 -0
  301. package/src/kit/dates.ts +150 -0
  302. package/src/kit/messages.ts +160 -0
  303. package/src/kit/numbers.ts +44 -0
  304. package/src/kit/options.ts +30 -0
  305. package/src/kit/uploads.ts +244 -0
  306. package/src/kit/waveform.ts +84 -0
  307. package/src/locale.ts +6 -0
  308. package/src/markdown.ts +69 -0
  309. package/src/marks.tsx +328 -0
  310. package/src/reveal.ts +52 -0
  311. package/src/stepGlyphs.ts +83 -0
  312. package/src/styles.css +6961 -0
  313. package/src/surface/Form.tsx +299 -0
  314. package/src/surface/Markdown.tsx +55 -0
  315. package/src/surface/Surface.tsx +605 -0
  316. package/src/surface/scope.ts +82 -0
  317. package/src/surface/values.ts +361 -0
  318. package/src/tint.ts +14 -0
  319. package/src/types.ts +596 -0
  320. package/src/useAgentFace.ts +47 -0
  321. package/src/useCall.ts +292 -0
  322. package/src/useConversation.ts +627 -0
  323. package/src/useDictation.ts +83 -0
  324. package/src/useLive.ts +115 -0
  325. package/src/usePolled.ts +60 -0
  326. package/src/voice/Orb.tsx +45 -0
  327. package/src/voice/StillOrb.tsx +29 -0
  328. package/src/voice/WebGLOrb.tsx +98 -0
  329. package/src/voice/fluidDots.tsx +171 -0
  330. package/src/voice/motion.ts +112 -0
  331. package/src/voice/orbs.ts +39 -0
  332. package/src/voice/useReducedMotion.ts +24 -0
  333. package/src/voice/wave.tsx +129 -0
  334. package/src/voice/webgl.ts +209 -0
  335. package/src/widget/css.d.ts +5 -0
  336. package/src/widget/element.tsx +535 -0
  337. package/src/widget/index.ts +10 -0
  338. package/src/widget/mount.ts +27 -0
  339. package/src/widget/widget.css +253 -0
  340. package/dist/SignalcoreProvider.d.ts +0 -113
  341. package/dist/SignalcoreProvider.js +0 -84
  342. package/dist/automations/AppMarks.d.ts +0 -11
  343. package/dist/automations/AppMarks.js +0 -18
  344. package/dist/automations/AutomationCard.d.ts +0 -27
  345. package/dist/automations/AutomationCard.js +0 -53
  346. package/dist/automations/AutomationsWindow.d.ts +0 -38
  347. package/dist/automations/AutomationsWindow.js +0 -57
  348. package/dist/automations/Card.d.ts +0 -46
  349. package/dist/automations/Card.js +0 -45
  350. package/dist/automations/ScheduleMarks.d.ts +0 -13
  351. package/dist/automations/ScheduleMarks.js +0 -24
  352. package/dist/automations/presentationIcons.d.ts +0 -7
  353. package/dist/automations/presentationIcons.js +0 -67
  354. package/dist/automations/schedule.d.ts +0 -25
  355. package/dist/automations/schedule.js +0 -59
  356. package/dist/automations/time.d.ts +0 -3
  357. package/dist/automations/time.js +0 -25
  358. package/dist/browser/BrowserView.d.ts +0 -43
  359. package/dist/browser/BrowserView.js +0 -94
  360. package/dist/browser/room.d.ts +0 -21
  361. package/dist/browser/room.js +0 -33
  362. package/dist/browser/useBrowserSession.d.ts +0 -17
  363. package/dist/browser/useBrowserSession.js +0 -67
  364. package/dist/builder/BuilderChat.d.ts +0 -32
  365. package/dist/builder/BuilderChat.js +0 -41
  366. package/dist/builder/BuilderTranscript.d.ts +0 -49
  367. package/dist/builder/BuilderTranscript.js +0 -62
  368. package/dist/builder/StatusLine.d.ts +0 -8
  369. package/dist/builder/StatusLine.js +0 -17
  370. package/dist/builder/answer.d.ts +0 -7
  371. package/dist/builder/answer.js +0 -8
  372. package/dist/builder/blocks.d.ts +0 -31
  373. package/dist/builder/blocks.js +0 -74
  374. package/dist/builder/items.d.ts +0 -15
  375. package/dist/builder/items.js +0 -21
  376. package/dist/builder/steps.d.ts +0 -20
  377. package/dist/builder/steps.js +0 -120
  378. package/dist/builder/time.d.ts +0 -4
  379. package/dist/builder/time.js +0 -24
  380. package/dist/builder/useBuildSession.d.ts +0 -36
  381. package/dist/builder/useBuildSession.js +0 -130
  382. package/dist/builder/workingOn.d.ts +0 -7
  383. package/dist/builder/workingOn.js +0 -15
  384. package/dist/chat/AgentChat.d.ts +0 -37
  385. package/dist/chat/AgentChat.js +0 -21
  386. package/dist/chat/ChatView.d.ts +0 -25
  387. package/dist/chat/ChatView.js +0 -34
  388. package/dist/chat/Composer.d.ts +0 -20
  389. package/dist/chat/Composer.js +0 -22
  390. package/dist/chat/MessageRow.d.ts +0 -22
  391. package/dist/chat/MessageRow.js +0 -32
  392. package/dist/chat/arrival.d.ts +0 -15
  393. package/dist/chat/arrival.js +0 -25
  394. package/dist/chat/history.d.ts +0 -24
  395. package/dist/chat/history.js +0 -45
  396. package/dist/chat/moments.d.ts +0 -25
  397. package/dist/chat/moments.js +0 -72
  398. package/dist/chat/types.d.ts +0 -12
  399. package/dist/chat/types.js +0 -1
  400. package/dist/chat/useComposer.d.ts +0 -46
  401. package/dist/chat/useComposer.js +0 -62
  402. package/dist/chat/useConversation.d.ts +0 -35
  403. package/dist/chat/useConversation.js +0 -71
  404. package/dist/chat/useStickToBottom.d.ts +0 -9
  405. package/dist/chat/useStickToBottom.js +0 -33
  406. package/dist/chat/useTurns.d.ts +0 -49
  407. package/dist/chat/useTurns.js +0 -111
  408. package/dist/classes.d.ts +0 -2
  409. package/dist/development.d.ts +0 -5
  410. package/dist/development.js +0 -8
  411. package/dist/flow/FlowWindow.d.ts +0 -42
  412. package/dist/flow/FlowWindow.js +0 -126
  413. package/dist/flow/index.d.ts +0 -16
  414. package/dist/flow/index.js +0 -16
  415. package/dist/flow/kinds.d.ts +0 -23
  416. package/dist/flow/kinds.js +0 -48
  417. package/dist/flow/map.d.ts +0 -44
  418. package/dist/flow/map.js +0 -225
  419. package/dist/flow/nodePaths.d.ts +0 -7
  420. package/dist/flow/nodePaths.js +0 -17
  421. package/dist/flow/relations.d.ts +0 -42
  422. package/dist/flow/relations.js +0 -174
  423. package/dist/host.d.ts +0 -124
  424. package/dist/host.js +0 -1
  425. package/dist/live/LiveView.d.ts +0 -28
  426. package/dist/live/LiveView.js +0 -55
  427. package/dist/live/capture.d.ts +0 -20
  428. package/dist/live/capture.js +0 -100
  429. package/dist/live/follow.d.ts +0 -26
  430. package/dist/live/follow.js +0 -72
  431. package/dist/live/paint.d.ts +0 -13
  432. package/dist/live/paint.js +0 -77
  433. package/dist/live/useLiveStream.d.ts +0 -16
  434. package/dist/live/useLiveStream.js +0 -57
  435. package/dist/look.d.ts +0 -33
  436. package/dist/look.js +0 -241
  437. package/dist/messages/en.d.ts +0 -3
  438. package/dist/messages/en.js +0 -251
  439. package/dist/messages/es.d.ts +0 -3
  440. package/dist/messages/es.js +0 -251
  441. package/dist/messages/index.d.ts +0 -16
  442. package/dist/messages/index.js +0 -33
  443. package/dist/messages/types.d.ts +0 -246
  444. package/dist/messages/types.js +0 -1
  445. package/dist/parts/Button.d.ts +0 -18
  446. package/dist/parts/Button.js +0 -17
  447. package/dist/parts/Icon.d.ts +0 -39
  448. package/dist/parts/Icon.js +0 -37
  449. package/dist/parts/Input.d.ts +0 -6
  450. package/dist/parts/Input.js +0 -11
  451. package/dist/parts/Spinner.d.ts +0 -2
  452. package/dist/parts/Spinner.js +0 -7
  453. package/dist/patterns.d.ts +0 -15
  454. package/dist/patterns.js +0 -5
  455. package/dist/presets.d.ts +0 -82
  456. package/dist/presets.js +0 -81
  457. package/dist/primitives.d.ts +0 -22
  458. package/dist/primitives.js +0 -58
  459. package/dist/request/RequestCard.d.ts +0 -34
  460. package/dist/request/RequestCard.js +0 -101
  461. package/dist/request/approval/ApprovalPreview.d.ts +0 -5
  462. package/dist/request/approval/ApprovalPreview.js +0 -27
  463. package/dist/request/approval/shapes.d.ts +0 -32
  464. package/dist/request/approval/shapes.js +0 -68
  465. package/dist/request/apps.d.ts +0 -11
  466. package/dist/request/apps.js +0 -27
  467. package/dist/request/cards.d.ts +0 -12
  468. package/dist/request/cards.js +0 -24
  469. package/dist/request/deliver.d.ts +0 -12
  470. package/dist/request/deliver.js +0 -21
  471. package/dist/request/handOver.d.ts +0 -18
  472. package/dist/request/handOver.js +0 -33
  473. package/dist/request/kinds/Approval.d.ts +0 -3
  474. package/dist/request/kinds/Approval.js +0 -9
  475. package/dist/request/kinds/Choice.d.ts +0 -3
  476. package/dist/request/kinds/Choice.js +0 -8
  477. package/dist/request/kinds/Connect.d.ts +0 -9
  478. package/dist/request/kinds/Connect.js +0 -119
  479. package/dist/request/kinds/FreeText.d.ts +0 -3
  480. package/dist/request/kinds/FreeText.js +0 -20
  481. package/dist/request/kinds/HandOver.d.ts +0 -13
  482. package/dist/request/kinds/HandOver.js +0 -20
  483. package/dist/request/kinds/Secret.d.ts +0 -7
  484. package/dist/request/kinds/Secret.js +0 -49
  485. package/dist/request/kinds/Upload.d.ts +0 -6
  486. package/dist/request/kinds/Upload.js +0 -47
  487. package/dist/request/types.d.ts +0 -83
  488. package/dist/request/types.js +0 -1
  489. package/dist/safeUrl.d.ts +0 -6
  490. package/dist/safeUrl.js +0 -8
  491. package/dist/stream/builder.d.ts +0 -176
  492. package/dist/stream/builder.js +0 -202
  493. package/dist/stream/reduce.d.ts +0 -51
  494. package/dist/stream/reduce.js +0 -58
  495. package/dist/stream/untilAborted.d.ts +0 -7
  496. package/dist/stream/untilAborted.js +0 -32
  497. package/dist/stream/useRunStream.d.ts +0 -26
  498. package/dist/stream/useRunStream.js +0 -137
  499. package/dist/styles.css +0 -2318
  500. package/dist/surface/HostNode.d.ts +0 -14
  501. package/dist/surface/HostNode.js +0 -30
  502. package/dist/surface/Node.d.ts +0 -7
  503. package/dist/surface/Node.js +0 -49
  504. package/dist/surface/SurfaceBoundary.d.ts +0 -26
  505. package/dist/surface/SurfaceBoundary.js +0 -20
  506. package/dist/surface/bindings.d.ts +0 -14
  507. package/dist/surface/bindings.js +0 -37
  508. package/dist/surface/check.d.ts +0 -27
  509. package/dist/surface/check.js +0 -102
  510. package/dist/surface/format.d.ts +0 -10
  511. package/dist/surface/format.js +0 -32
  512. package/dist/surface/hosts.d.ts +0 -6
  513. package/dist/surface/hosts.js +0 -11
  514. package/dist/surface/scene.d.ts +0 -21
  515. package/dist/surface/scene.js +0 -8
  516. package/dist/surface/templates/Browser.d.ts +0 -6
  517. package/dist/surface/templates/Browser.js +0 -11
  518. package/dist/surface/templates/Chart.d.ts +0 -6
  519. package/dist/surface/templates/Chart.js +0 -13
  520. package/dist/surface/templates/Choices.d.ts +0 -3
  521. package/dist/surface/templates/Choices.js +0 -12
  522. package/dist/surface/templates/Form.d.ts +0 -3
  523. package/dist/surface/templates/Form.js +0 -44
  524. package/dist/surface/templates/KeyValue.d.ts +0 -3
  525. package/dist/surface/templates/KeyValue.js +0 -7
  526. package/dist/surface/templates/Layout.d.ts +0 -5
  527. package/dist/surface/templates/Layout.js +0 -16
  528. package/dist/surface/templates/Live.d.ts +0 -6
  529. package/dist/surface/templates/Live.js +0 -9
  530. package/dist/surface/templates/Media.d.ts +0 -5
  531. package/dist/surface/templates/Media.js +0 -13
  532. package/dist/surface/templates/Slots.d.ts +0 -3
  533. package/dist/surface/templates/Slots.js +0 -19
  534. package/dist/surface/templates/Table.d.ts +0 -3
  535. package/dist/surface/templates/Table.js +0 -12
  536. package/dist/surface/templates/Text.d.ts +0 -4
  537. package/dist/surface/templates/Text.js +0 -15
  538. package/dist/surface/templates/index.d.ts +0 -7
  539. package/dist/surface/templates/index.js +0 -32
  540. package/dist/surface/types.d.ts +0 -68
  541. package/dist/surface/types.js +0 -6
  542. package/dist/theme.d.ts +0 -62
  543. package/dist/theme.js +0 -9
  544. package/dist/useTokens.d.ts +0 -7
  545. package/dist/useTokens.js +0 -41
  546. package/dist/voice/VoiceWindow.d.ts +0 -18
  547. package/dist/voice/VoiceWindow.js +0 -35
  548. package/dist/voice/index.d.ts +0 -13
  549. package/dist/voice/index.js +0 -12
  550. package/dist/voice/meter.d.ts +0 -16
  551. package/dist/voice/meter.js +0 -52
  552. package/dist/voice/orbColors.d.ts +0 -16
  553. package/dist/voice/orbColors.js +0 -75
  554. package/dist/voice/pushable.d.ts +0 -16
  555. package/dist/voice/pushable.js +0 -56
  556. package/dist/voice/useDictation.d.ts +0 -24
  557. package/dist/voice/useDictation.js +0 -60
  558. package/dist/voice/useReducedMotion.d.ts +0 -5
  559. package/dist/voice/useVoice.d.ts +0 -70
  560. package/dist/voice/useVoice.js +0 -197
  561. package/dist/voice/useVoicePrimitives.d.ts +0 -7
  562. package/dist/voice/useVoicePrimitives.js +0 -11
  563. package/dist/voice/voice.d.ts +0 -55
  564. package/dist/voice/voice.js +0 -9
  565. package/dist/voice/webSpeech.d.ts +0 -33
  566. package/dist/voice/webSpeech.js +0 -258
  567. package/dist/widget.js.map +0 -1
  568. package/dist/windows/AgentSpace.d.ts +0 -78
  569. package/dist/windows/AgentSpace.js +0 -135
  570. package/dist/windows/Captions.d.ts +0 -13
  571. package/dist/windows/Captions.js +0 -22
  572. package/dist/windows/Dock.d.ts +0 -37
  573. package/dist/windows/Dock.js +0 -22
  574. package/dist/windows/Journal.d.ts +0 -15
  575. package/dist/windows/Journal.js +0 -19
  576. package/dist/windows/KindMark.d.ts +0 -7
  577. package/dist/windows/KindMark.js +0 -31
  578. package/dist/windows/Pending.d.ts +0 -8
  579. package/dist/windows/Pending.js +0 -17
  580. package/dist/windows/Stage.d.ts +0 -18
  581. package/dist/windows/Stage.js +0 -21
  582. package/dist/windows/StatusLabel.d.ts +0 -9
  583. package/dist/windows/StatusLabel.js +0 -7
  584. package/dist/windows/Strip.d.ts +0 -17
  585. package/dist/windows/Strip.js +0 -42
  586. package/dist/windows/SurfaceWindow.d.ts +0 -20
  587. package/dist/windows/SurfaceWindow.js +0 -12
  588. package/dist/windows/WindowFrame.d.ts +0 -23
  589. package/dist/windows/WindowFrame.js +0 -22
  590. package/dist/windows/hearing.d.ts +0 -11
  591. package/dist/windows/hearing.js +0 -26
  592. package/dist/windows/kinds.d.ts +0 -47
  593. package/dist/windows/kinds.js +0 -28
  594. package/dist/windows/reduce.d.ts +0 -98
  595. package/dist/windows/reduce.js +0 -151
  596. package/dist/windows/registry.d.ts +0 -18
  597. package/dist/windows/registry.js +0 -61
  598. package/dist/windows/reveal.d.ts +0 -9
  599. package/dist/windows/reveal.js +0 -6
  600. package/dist/windows/space.d.ts +0 -21
  601. package/dist/windows/space.js +0 -6
  602. package/dist/windows/status.d.ts +0 -11
  603. package/dist/windows/status.js +0 -30
  604. package/dist/windows/types.d.ts +0 -15
  605. package/dist/windows/types.js +0 -1
  606. package/dist/windows/useLoaded.d.ts +0 -44
  607. package/dist/windows/useLoaded.js +0 -58
  608. package/dist/windows/useUnread.d.ts +0 -7
  609. package/dist/windows/useUnread.js +0 -21
  610. package/dist/windows/useWindows.d.ts +0 -70
  611. package/dist/windows/useWindows.js +0 -60
@@ -0,0 +1,523 @@
1
+ import { createScreen } from "./browser.js";
2
+ import { sayOf, toolResultOf } from "./frames.js";
3
+ import { note } from "./dev.js";
4
+ import { useLive } from "./useLive.js";
5
+ import { useEffect, useReducer, useRef, useState } from "react";
6
+ //#region src/useConversation.ts
7
+ const EMPTY = {
8
+ messages: [],
9
+ pending: false,
10
+ draft: "",
11
+ awaiting: null,
12
+ loaded: false,
13
+ error: null,
14
+ browser: null,
15
+ holder: null,
16
+ handovers: [],
17
+ tools: [],
18
+ answered: null
19
+ };
20
+ /**
21
+ * Errors told only to the socket that sent something (the agent still replying, a frame it did
22
+ * not understand, a turn waiting on a surface, files it can't carry, what only the channel or the
23
+ * business answers, a tool's answer no call waits on: nothing was stored): the turn, if there is
24
+ * one, goes on. Any other error ends it.
25
+ */
26
+ const ASIDE = /* @__PURE__ */ new Set([
27
+ "busy",
28
+ "unknown",
29
+ "pending",
30
+ "files",
31
+ "channel",
32
+ "business",
33
+ "tool"
34
+ ]);
35
+ /**
36
+ * Told when the page answered a host's tool no call waits on any more (answered already, from
37
+ * another tab or before a reload; or late): nothing for the person to hear.
38
+ */
39
+ const STALE = "tool";
40
+ /** Whether a step's state is its last: done, or failed. */
41
+ const settled = (step) => step?.state === "done" || step?.state === "failed";
42
+ /**
43
+ * The turn, one step at a time, from what the socket says alone, so a page opened mid-turn (a
44
+ * reload, another tab) reads it as the one that sent. The person's message opens it (their words,
45
+ * or their answer on a surface); on a channel, where the reply comes on its own time, its first
46
+ * words or step do. `done`, `stopped` or an error closes it, and either way the
47
+ * draft goes: the reply now lives in the messages, and after an error there is none (on a
48
+ * refusal the partial text was never one). A reply that calls actions is stored before they run,
49
+ * so what `step`, `ui` and `request` frames say lands on its steps: the message is the one place
50
+ * a step is drawn from, live or read back. The socket opening afresh empties the draft too, since
51
+ * the turn so far is then told again. Who answers the conversation is the read's, then each
52
+ * `holder` frame's: its change kept once beside those read, in order, and who answers taken from
53
+ * it only when it is the newest; a `decision` lands on its message (null clears it). A host's
54
+ * tool the page runs (`tool`) is its step working, and a turn under way until its step is done
55
+ * or failed, whatever `done` said meanwhile. A yes the business gives (`decides: "business"`)
56
+ * waits on its step without stopping the turn or holding the person; one the person gave and the
57
+ * API refused as the business's (`business`) waits for the business again.
58
+ */
59
+ function reduce(state, action) {
60
+ switch (action.type) {
61
+ case "reset": return {
62
+ ...state,
63
+ pending: false,
64
+ draft: "",
65
+ awaiting: null,
66
+ browser: null,
67
+ tools: [],
68
+ answered: null
69
+ };
70
+ case "history": {
71
+ const read = action.handovers ?? [];
72
+ const handovers = withHandovers(read, state.handovers);
73
+ const heard = handovers.length > read.length ? handovers.at(-1)?.holder : void 0;
74
+ return {
75
+ ...state,
76
+ messages: withMessages(action.messages, state.messages),
77
+ awaiting: action.pending ? awaited(action.messages) : null,
78
+ loaded: true,
79
+ error: null,
80
+ holder: heard ?? action.holder ?? state.holder,
81
+ handovers
82
+ };
83
+ }
84
+ case "failed": return {
85
+ ...state,
86
+ error: action.error
87
+ };
88
+ case "working": return {
89
+ ...state,
90
+ pending: true
91
+ };
92
+ case "text": return {
93
+ ...state,
94
+ pending: true,
95
+ draft: state.draft + action.delta
96
+ };
97
+ case "message": {
98
+ const { message } = action;
99
+ const messages = withStored(state.messages, message);
100
+ if (message.author === "contact" || message.author === "operator") return {
101
+ ...state,
102
+ messages
103
+ };
104
+ if (message.role === "assistant") return {
105
+ ...state,
106
+ messages,
107
+ draft: ""
108
+ };
109
+ return {
110
+ ...state,
111
+ messages: message.action ? answered(messages, message.action) : messages,
112
+ pending: true,
113
+ draft: ""
114
+ };
115
+ }
116
+ case "ui": return {
117
+ ...state,
118
+ messages: withStep(state.messages, action.id, (step) => ({
119
+ ...step,
120
+ surface: action.surface,
121
+ awaits: action.awaits
122
+ })),
123
+ awaiting: action.awaits ? action.id : state.awaiting
124
+ };
125
+ case "step": {
126
+ const waits = action.state === "waiting";
127
+ const ended = action.state === "done" || action.state === "failed";
128
+ return {
129
+ ...state,
130
+ pending: state.pending || action.state === "running",
131
+ messages: withStep(state.messages, action.id, (step) => ({
132
+ ...step,
133
+ state: action.state,
134
+ output: action.output ?? step.output,
135
+ awaits: waits || step.awaits
136
+ })),
137
+ awaiting: waits ? action.id : ended && state.awaiting === action.id ? null : state.awaiting,
138
+ tools: ended ? state.tools.filter((id) => id !== action.id) : state.tools,
139
+ answered: state.answered?.id === action.id ? null : state.answered
140
+ };
141
+ }
142
+ case "tool":
143
+ if (settled(stepOf(state.messages, action.id))) return state;
144
+ return {
145
+ ...state,
146
+ pending: true,
147
+ awaiting: state.awaiting === action.id ? null : state.awaiting,
148
+ messages: withStep(state.messages, action.id, (step) => ({
149
+ ...step,
150
+ state: "running",
151
+ awaits: false
152
+ })),
153
+ tools: state.tools.includes(action.id) ? state.tools : [...state.tools, action.id]
154
+ };
155
+ case "request": {
156
+ const { id, action: name, input, decides = "person" } = action;
157
+ const theirs = decides === "person";
158
+ return {
159
+ ...state,
160
+ awaiting: theirs ? id : state.awaiting,
161
+ messages: withStep(state.messages, id, (step) => ({
162
+ ...step,
163
+ state: "waiting",
164
+ awaits: theirs,
165
+ request: {
166
+ action: name,
167
+ input,
168
+ decides
169
+ }
170
+ }))
171
+ };
172
+ }
173
+ case "acted": {
174
+ const { surface } = action.action;
175
+ const request = stepOf(state.messages, surface)?.request ?? null;
176
+ return {
177
+ ...state,
178
+ awaiting: surface === state.awaiting ? null : state.awaiting,
179
+ messages: withStep(state.messages, surface, (step) => ({
180
+ ...step,
181
+ request: null
182
+ })),
183
+ answered: request === null ? state.answered : {
184
+ id: surface,
185
+ request
186
+ }
187
+ };
188
+ }
189
+ case "handoff": return state;
190
+ case "holder": {
191
+ const handovers = withHandovers(state.handovers, [action.handover]);
192
+ const newest = handovers.at(-1) === action.handover;
193
+ return {
194
+ ...state,
195
+ holder: newest ? action.handled_by : state.holder,
196
+ handovers
197
+ };
198
+ }
199
+ case "decision": return {
200
+ ...state,
201
+ messages: withMessage(state.messages, action.message_id, (message) => ({
202
+ ...message,
203
+ decision: action.decision
204
+ }))
205
+ };
206
+ case "done": return {
207
+ ...state,
208
+ pending: state.tools.length > 0,
209
+ draft: ""
210
+ };
211
+ case "stopped": return {
212
+ ...state,
213
+ pending: false,
214
+ draft: "",
215
+ tools: []
216
+ };
217
+ case "error":
218
+ if (action.code === "business" && state.answered !== null) {
219
+ const { id, request } = state.answered;
220
+ return {
221
+ ...state,
222
+ answered: null,
223
+ messages: withStep(state.messages, id, (step) => ({
224
+ ...step,
225
+ awaits: false,
226
+ request: {
227
+ ...request,
228
+ decides: "business"
229
+ }
230
+ }))
231
+ };
232
+ }
233
+ return ASIDE.has(action.code) ? state : {
234
+ ...state,
235
+ pending: false,
236
+ draft: "",
237
+ awaiting: null,
238
+ tools: [],
239
+ answered: null
240
+ };
241
+ case "browser":
242
+ if (!action.open) return {
243
+ ...state,
244
+ browser: null
245
+ };
246
+ return {
247
+ ...state,
248
+ browser: {
249
+ url: action.url,
250
+ title: action.title,
251
+ where: action.where,
252
+ control: action.control,
253
+ reason: action.reason,
254
+ wait: action.wait,
255
+ width: action.width,
256
+ height: action.height
257
+ }
258
+ };
259
+ case "browser.frame": return state;
260
+ }
261
+ }
262
+ /**
263
+ * `known` with whatever of `more` it lacks, at the end, by id: a message is kept once however
264
+ * many times it is heard (stored live, then read in the history, or told again on a reconnect).
265
+ */
266
+ function withMessages(known, more) {
267
+ const ids = new Set(known.map((message) => message.id));
268
+ const missing = more.filter((message) => !ids.has(message.id));
269
+ return missing.length === 0 ? known : [...known, ...missing];
270
+ }
271
+ /** What going out on a channel changes of a message once it is stored, as it goes. */
272
+ const OUTGOING = [
273
+ "delivery",
274
+ "delivery_error",
275
+ "pieces",
276
+ "sent_parts",
277
+ "voice"
278
+ ];
279
+ /**
280
+ * `known` with a message stored: one it lacks joins at the end; one it holds takes what going out
281
+ * on its channel changed since (where it got to, its parts, its voice note) and keeps the rest as
282
+ * this page has it (its steps, moved by their own frames); untouched when nothing changed.
283
+ */
284
+ function withStored(known, stored) {
285
+ const held = known.find((message) => message.id === stored.id);
286
+ if (held === void 0) return [...known, stored];
287
+ if (OUTGOING.every((field) => isEqual(held[field], stored[field]))) return known;
288
+ const outgoing = Object.fromEntries(OUTGOING.map((field) => [field, stored[field]]));
289
+ return known.map((message) => message === held ? {
290
+ ...held,
291
+ ...outgoing
292
+ } : message);
293
+ }
294
+ /** The same value, told again: equal by what it holds. */
295
+ const isEqual = (one, other) => JSON.stringify(one ?? null) === JSON.stringify(other ?? null);
296
+ /** A change of who answers, as one however it was told: its moment, and to whom. */
297
+ const handoverKey = ({ at, holder }) => `${Date.parse(at)} ${holder}`;
298
+ /**
299
+ * `known` with whatever of `more` it lacks, in the order they were made: a change is kept once
300
+ * however often, and by whatever, it is told (the read, a frame, the host's own request).
301
+ */
302
+ function withHandovers(known, more) {
303
+ const keys = new Set(known.map(handoverKey));
304
+ const missing = more.filter((handover) => !keys.has(handoverKey(handover)));
305
+ if (missing.length === 0) return known;
306
+ return [...known, ...missing].sort((one, other) => Date.parse(one.at) - Date.parse(other.at));
307
+ }
308
+ /** The messages with message `id` changed; untouched when none is it. */
309
+ function withMessage(messages, id, change) {
310
+ const at = messages.findIndex((message) => message.id === id);
311
+ const message = messages[at];
312
+ return message ? messages.with(at, change(message)) : messages;
313
+ }
314
+ /** Step `id`, wherever it is; none when no message holds it. */
315
+ function stepOf(messages, id) {
316
+ return messages.flatMap((message) => message.steps).findLast((step) => step.id === id);
317
+ }
318
+ /** The messages with step `id` changed, wherever it is; untouched when no message holds it. */
319
+ function withStep(messages, id, change) {
320
+ const at = messages.findLastIndex((message) => message.steps.some((step) => step.id === id));
321
+ const message = messages[at];
322
+ if (!message) return messages;
323
+ const steps = message.steps.map((step) => step.id === id ? change(step) : step);
324
+ return messages.with(at, {
325
+ ...message,
326
+ steps
327
+ });
328
+ }
329
+ /** The surface a stopped turn waits on, as the history tells it. */
330
+ function awaited(messages) {
331
+ return messages.flatMap((message) => message.steps).find((step) => step.awaits)?.id ?? null;
332
+ }
333
+ /**
334
+ * The person's answer, landed on the step that waited for it: a question is done with their
335
+ * words as its output (what the history reads back); an action they allowed or declined was
336
+ * already told its own state.
337
+ */
338
+ function answered(messages, action) {
339
+ return withStep(messages, action.surface, (step) => step.state === "waiting" ? {
340
+ ...step,
341
+ state: "done",
342
+ output: action.label,
343
+ awaits: false,
344
+ request: null
345
+ } : {
346
+ ...step,
347
+ awaits: false,
348
+ request: null
349
+ });
350
+ }
351
+ /** How often the history is read again while something goes out on a channel. */
352
+ const DELIVERY_EVERY = 3e3;
353
+ /** How long a message sent is watched for its receipt before the next read brings it. */
354
+ const RECEIPT_WITHIN = 6e4;
355
+ /**
356
+ * Whether a message is still on its way to the person on a channel: waiting to go, or gone a
357
+ * moment ago and not yet received. What it gets to moves without a frame, so it is read again.
358
+ */
359
+ function onItsWay(message, now) {
360
+ if (message.delivery === "queued") return true;
361
+ return message.delivery === "sent" && now - Date.parse(message.created_at) < RECEIPT_WITHIN;
362
+ }
363
+ /** What the page answers a tool of the host's when it runs none (no `onTool`), for the agent. */
364
+ const NO_TOOL = "This page can't do that";
365
+ const refuse = () => Promise.reject(/* @__PURE__ */ new Error(NO_TOOL));
366
+ /**
367
+ * Conversation `conversationId` as the person sees it: the history, kept live by the socket.
368
+ * Each time the socket opens the history is read, with the socket already listening, so nothing
369
+ * stored can fall between the two; what came live meanwhile is kept. `onError` hears each
370
+ * error's code (the socket's, or `load` for a history that could not be read): the host words
371
+ * it, this hook shows no text; but `tool`, the page's answer to a call no longer waiting (one it
372
+ * answered already, told again), which is let pass (noted in development). `onHolder` hears each
373
+ * change of who answers it, live, for the host's own views of it; `handover` is the last change
374
+ * the host knows of (one it made itself, as its request answered), taken at once, so it shows
375
+ * whether or not the socket tells it.
376
+ * `onStep` hears each step the agent starts, live, by its action's name, for the host's own
377
+ * views of it (the builder's column, opened as the agent asks it).
378
+ * `onTool` runs the host's own tools the agent calls in the page (a `tool` frame), and its answer
379
+ * goes up (`tool_result`); each call runs once, and one told again while it waits (the socket
380
+ * opened anew) is answered again with what it gave. Without `onTool`, each is refused with
381
+ * `NO_TOOL`, so the turn never waits on a page that can't run it. One conversation per mount: key
382
+ * the component on the id.
383
+ */
384
+ function useConversation(client, conversationId, { onError, onHolder, onStep, handover, onTool } = {}) {
385
+ const [state, dispatch] = useReducer(reduce, EMPTY);
386
+ const told = handover ?? null;
387
+ const toldKey = told === null ? null : handoverKey(told);
388
+ useEffect(() => {
389
+ if (told !== null) dispatch({
390
+ type: "holder",
391
+ handled_by: told.holder,
392
+ handover: told
393
+ });
394
+ }, [toldKey]);
395
+ const [screen] = useState(createScreen);
396
+ const reads = useRef(0);
397
+ useEffect(() => () => {
398
+ reads.current += 1;
399
+ }, [client, conversationId]);
400
+ const read = () => {
401
+ const run = ++reads.current;
402
+ client.conversations.get(conversationId).then(({ messages, pending, handled_by, handovers = [] }) => {
403
+ if (run !== reads.current) return;
404
+ dispatch({
405
+ type: "history",
406
+ messages,
407
+ pending,
408
+ holder: handled_by,
409
+ handovers
410
+ });
411
+ }, (error) => {
412
+ if (run !== reads.current) return;
413
+ dispatch({
414
+ type: "failed",
415
+ error
416
+ });
417
+ onError?.("load");
418
+ });
419
+ };
420
+ const tools = useRef(/* @__PURE__ */ new Map());
421
+ const runTool = ({ id, name, input }) => {
422
+ const known = tools.current.get(id);
423
+ if (known !== void 0) {
424
+ if (known !== null) live.send(known);
425
+ return;
426
+ }
427
+ tools.current.set(id, null);
428
+ Promise.resolve({
429
+ id,
430
+ name,
431
+ input
432
+ }).then(onTool ?? refuse).then((value) => ({
433
+ status: "fulfilled",
434
+ value
435
+ }), (reason) => ({
436
+ status: "rejected",
437
+ reason
438
+ })).then((settled) => {
439
+ const answer = toolResultOf(id, settled);
440
+ tools.current.set(id, answer);
441
+ live.send(answer);
442
+ });
443
+ };
444
+ const live = useLive(client, conversationId, {
445
+ onFrame: (frame) => {
446
+ if (frame.type === "browser.frame") {
447
+ screen.show({
448
+ jpeg: frame.jpeg,
449
+ width: frame.width,
450
+ height: frame.height
451
+ });
452
+ return;
453
+ }
454
+ if (frame.type === "error" && frame.code === STALE) {
455
+ note("A host's tool answer was let pass:", frame.detail);
456
+ return;
457
+ }
458
+ if (frame.type === "browser" && !frame.open) screen.clear();
459
+ dispatch(frame);
460
+ if (frame.type === "error") onError?.(frame.code);
461
+ if (frame.type === "holder") onHolder?.(frame.handled_by, frame.handover);
462
+ if (frame.type === "step" && frame.state === "running" && frame.action !== void 0) onStep?.(frame.action);
463
+ if (frame.type === "tool") runTool(frame);
464
+ },
465
+ onOpen: () => {
466
+ dispatch({ type: "reset" });
467
+ read();
468
+ }
469
+ });
470
+ const travelling = state.messages.some((message) => onItsWay(message, Date.now()));
471
+ useEffect(() => {
472
+ if (!travelling || !live.open) return void 0;
473
+ const again = setInterval(read, DELIVERY_EVERY);
474
+ return () => {
475
+ clearInterval(again);
476
+ };
477
+ }, [travelling, live.open]);
478
+ const say = (text, files = []) => {
479
+ const frame = sayOf(text, files);
480
+ if (frame === null || state.pending || state.awaiting !== null) return false;
481
+ return live.send(frame);
482
+ };
483
+ const act = (action) => {
484
+ if (!live.send({
485
+ type: "action",
486
+ ...action
487
+ })) return false;
488
+ dispatch({
489
+ type: "acted",
490
+ action
491
+ });
492
+ return true;
493
+ };
494
+ return {
495
+ messages: state.messages,
496
+ draft: state.draft,
497
+ pending: state.pending,
498
+ awaiting: state.awaiting,
499
+ open: live.open,
500
+ loading: !state.loaded,
501
+ error: state.error,
502
+ say,
503
+ act,
504
+ stop: () => live.send({ type: "stop" }),
505
+ browser: state.browser,
506
+ watchScreen: screen.watch,
507
+ control: (to) => live.send({
508
+ type: "browser.control",
509
+ to
510
+ }),
511
+ closeBrowser: () => live.send({ type: "browser.close" }),
512
+ input: (event) => live.send({
513
+ type: "browser.input",
514
+ event
515
+ }),
516
+ holder: state.holder,
517
+ handovers: state.handovers
518
+ };
519
+ }
520
+ //#endregion
521
+ export { EMPTY, NO_TOOL, onItsWay, reduce, useConversation };
522
+
523
+ //# sourceMappingURL=useConversation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useConversation.js","names":[],"sources":["../src/useConversation.ts"],"sourcesContent":["import { useEffect, useReducer, useRef, useState } from \"react\";\n\nimport { createScreen, type Screen } from \"./browser\";\nimport type { Client } from \"./client\";\nimport { note } from \"./dev\";\nimport { sayOf, toolResultOf, type Frame, type ToolResult } from \"./frames\";\nimport type {\n Action,\n BrowserControl,\n BrowserFrame,\n BrowserInput,\n BrowserState,\n Handover,\n Holder,\n Message,\n Request,\n Step,\n ToolCall,\n} from \"./types\";\nimport { useLive } from \"./useLive\";\n\n/**\n * Where a conversation stands: its stored messages, the turn (whether a reply is on its way, what\n * of it has come so far, and what it waits on), and what its history read has said.\n */\nexport interface ConversationState {\n messages: Message[];\n pending: boolean;\n draft: string;\n /** The step the turn stopped on (a surface to answer, or an action to allow), until the person acts. */\n awaiting: string | null;\n /** Whether the history has landed once; until then an empty list means nothing. */\n loaded: boolean;\n /** What the last read threw; null once one lands. */\n error: unknown;\n /** The conversation's browser while it is open. */\n browser: BrowserState | null;\n /** Who answers it now; null until the history lands. */\n holder: Holder | null;\n /** Every change of who answers it, in order: read with the history, then heard live. */\n handovers: Handover[];\n /**\n * The host's tools the page runs now, by the call's id: the turn is under way while one runs\n * (its `done` said only that it stopped to wait for them), until its step is done or failed.\n */\n tools: string[];\n /**\n * The yes or no the person just gave, until the step's own frames say what came of it: what\n * the API refuses as the business's (`business`) is drawn as waiting for the business again.\n */\n answered: { id: string; request: Request } | null;\n}\n\nexport const EMPTY: ConversationState = {\n messages: [],\n pending: false,\n draft: \"\",\n awaiting: null,\n loaded: false,\n error: null,\n browser: null,\n holder: null,\n handovers: [],\n tools: [],\n answered: null,\n};\n\n/**\n * What moves the state: the socket opening afresh, a read landing (with who answers it, and its\n * changes, when the API tells them) or failing, the person acting on a surface, or a frame.\n */\nexport type ConversationAction =\n | { type: \"reset\" }\n | {\n type: \"history\";\n messages: Message[];\n pending: boolean;\n holder?: Holder;\n handovers?: Handover[];\n }\n | { type: \"failed\"; error: unknown }\n | { type: \"acted\"; action: Action }\n | Frame;\n\n/**\n * Errors told only to the socket that sent something (the agent still replying, a frame it did\n * not understand, a turn waiting on a surface, files it can't carry, what only the channel or the\n * business answers, a tool's answer no call waits on: nothing was stored): the turn, if there is\n * one, goes on. Any other error ends it.\n */\nconst ASIDE: ReadonlySet<string> = new Set([\n \"busy\",\n \"unknown\",\n \"pending\",\n \"files\",\n \"channel\",\n \"business\",\n \"tool\",\n]);\n\n/**\n * Told when the page answered a host's tool no call waits on any more (answered already, from\n * another tab or before a reload; or late): nothing for the person to hear.\n */\nconst STALE = \"tool\";\n\n/** Whether a step's state is its last: done, or failed. */\nconst settled = (step: Step | undefined): boolean =>\n step?.state === \"done\" || step?.state === \"failed\";\n\n/**\n * The turn, one step at a time, from what the socket says alone, so a page opened mid-turn (a\n * reload, another tab) reads it as the one that sent. The person's message opens it (their words,\n * or their answer on a surface); on a channel, where the reply comes on its own time, its first\n * words or step do. `done`, `stopped` or an error closes it, and either way the\n * draft goes: the reply now lives in the messages, and after an error there is none (on a\n * refusal the partial text was never one). A reply that calls actions is stored before they run,\n * so what `step`, `ui` and `request` frames say lands on its steps: the message is the one place\n * a step is drawn from, live or read back. The socket opening afresh empties the draft too, since\n * the turn so far is then told again. Who answers the conversation is the read's, then each\n * `holder` frame's: its change kept once beside those read, in order, and who answers taken from\n * it only when it is the newest; a `decision` lands on its message (null clears it). A host's\n * tool the page runs (`tool`) is its step working, and a turn under way until its step is done\n * or failed, whatever `done` said meanwhile. A yes the business gives (`decides: \"business\"`)\n * waits on its step without stopping the turn or holding the person; one the person gave and the\n * API refused as the business's (`business`) waits for the business again.\n */\nexport function reduce(state: ConversationState, action: ConversationAction): ConversationState {\n switch (action.type) {\n case \"reset\":\n // The socket that opens is told the browser again, if there is one, and the tools awaited.\n return {\n ...state,\n pending: false,\n draft: \"\",\n awaiting: null,\n browser: null,\n tools: [],\n answered: null,\n };\n case \"history\": {\n // A change heard while the read was on its way is newer than what it says.\n const read = action.handovers ?? [];\n const handovers = withHandovers(read, state.handovers);\n const heard = handovers.length > read.length ? handovers.at(-1)?.holder : undefined;\n return {\n ...state,\n messages: withMessages(action.messages, state.messages),\n awaiting: action.pending ? awaited(action.messages) : null,\n loaded: true,\n error: null,\n holder: heard ?? action.holder ?? state.holder,\n handovers,\n };\n }\n case \"failed\":\n return { ...state, error: action.error };\n case \"working\":\n // The agent began its reply: told first to a socket that opens while it thinks.\n return { ...state, pending: true };\n case \"text\":\n return { ...state, pending: true, draft: state.draft + action.delta };\n case \"message\": {\n const { message } = action;\n const messages = withStored(state.messages, message);\n // On a channel the turn is no one's message's: the person's words wait for the agent's\n // reply on its own time, and the business's own go out beside the turn, never in it.\n if (message.author === \"contact\" || message.author === \"operator\") {\n return { ...state, messages };\n }\n if (message.role === \"assistant\") return { ...state, messages, draft: \"\" };\n return {\n ...state,\n messages: message.action ? answered(messages, message.action) : messages,\n pending: true,\n draft: \"\",\n };\n }\n case \"ui\":\n return {\n ...state,\n messages: withStep(state.messages, action.id, (step) => ({\n ...step,\n surface: action.surface,\n awaits: action.awaits,\n })),\n awaiting: action.awaits ? action.id : state.awaiting,\n };\n case \"step\": {\n // A step that waits holds the turn until the person answers, as the history reads it; one\n // that runs says a turn is under way (on a channel, nobody's message told so before).\n const waits = action.state === \"waiting\";\n const ended = action.state === \"done\" || action.state === \"failed\";\n return {\n ...state,\n pending: state.pending || action.state === \"running\",\n messages: withStep(state.messages, action.id, (step) => ({\n ...step,\n state: action.state,\n output: action.output ?? step.output,\n awaits: waits || step.awaits,\n })),\n // One answered elsewhere (another screen, the owner's own Chrome) ends here too.\n awaiting: waits ? action.id : ended && state.awaiting === action.id ? null : state.awaiting,\n tools: ended ? state.tools.filter((id) => id !== action.id) : state.tools,\n answered: state.answered?.id === action.id ? null : state.answered,\n };\n }\n case \"tool\":\n // Told again once its answer is in (a socket opening as it went): nothing runs anew.\n if (settled(stepOf(state.messages, action.id))) return state;\n // The page runs it now: its step works like any step, until the step's own frames move it,\n // and it is never the person's to answer.\n return {\n ...state,\n pending: true,\n awaiting: state.awaiting === action.id ? null : state.awaiting,\n messages: withStep(state.messages, action.id, (step) => ({\n ...step,\n state: \"running\",\n awaits: false,\n })),\n tools: state.tools.includes(action.id) ? state.tools : [...state.tools, action.id],\n };\n case \"request\": {\n const { id, action: name, input, decides = \"person\" } = action;\n // The business's yes: the turn went on, and nothing waits on the person.\n const theirs = decides === \"person\";\n return {\n ...state,\n awaiting: theirs ? id : state.awaiting,\n messages: withStep(state.messages, id, (step) => ({\n ...step,\n state: \"waiting\",\n awaits: theirs,\n request: { action: name, input, decides },\n })),\n };\n }\n case \"acted\": {\n const { surface } = action.action;\n const request = stepOf(state.messages, surface)?.request ?? null;\n return {\n ...state,\n awaiting: surface === state.awaiting ? null : state.awaiting,\n // Leave given or refused: the card goes at once; the step's own frames say what came of it.\n messages: withStep(state.messages, surface, (step) => ({ ...step, request: null })),\n answered: request === null ? state.answered : { id: surface, request },\n };\n }\n case \"handoff\":\n // Nothing to keep: the reply's `escalate` step says it, live (its `done` follows this\n // frame) and read back alike; who answers now comes in its `holder` frame.\n return state;\n case \"holder\": {\n const handovers = withHandovers(state.handovers, [action.handover]);\n // One older than a change known says nothing of who answers now.\n const newest = handovers.at(-1) === action.handover;\n return { ...state, holder: newest ? action.handled_by : state.holder, handovers };\n }\n case \"decision\":\n return {\n ...state,\n messages: withMessage(state.messages, action.message_id, (message) => ({\n ...message,\n decision: action.decision,\n })),\n };\n case \"done\":\n // The turn ended, or stopped to wait: on the host's tools the page still runs, it goes on.\n return { ...state, pending: state.tools.length > 0, draft: \"\" };\n case \"stopped\":\n return { ...state, pending: false, draft: \"\", tools: [] };\n case \"error\":\n if (action.code === \"business\" && state.answered !== null) {\n // The person's yes or no on what the business decides: it waits for the business again.\n const { id, request } = state.answered;\n return {\n ...state,\n answered: null,\n messages: withStep(state.messages, id, (step) => ({\n ...step,\n awaits: false,\n request: { ...request, decides: \"business\" },\n })),\n };\n }\n return ASIDE.has(action.code)\n ? state\n : { ...state, pending: false, draft: \"\", awaiting: null, tools: [], answered: null };\n case \"browser\":\n if (!action.open) return { ...state, browser: null };\n return {\n ...state,\n browser: {\n url: action.url,\n title: action.title,\n where: action.where,\n control: action.control,\n reason: action.reason,\n wait: action.wait,\n width: action.width,\n height: action.height,\n },\n };\n case \"browser.frame\":\n // Pictures repaint the screen, never the conversation (`Screen`).\n return state;\n }\n}\n\n/**\n * `known` with whatever of `more` it lacks, at the end, by id: a message is kept once however\n * many times it is heard (stored live, then read in the history, or told again on a reconnect).\n */\nfunction withMessages(known: Message[], more: Message[]): Message[] {\n const ids = new Set(known.map((message) => message.id));\n const missing = more.filter((message) => !ids.has(message.id));\n return missing.length === 0 ? known : [...known, ...missing];\n}\n\n/** What going out on a channel changes of a message once it is stored, as it goes. */\nconst OUTGOING = [\"delivery\", \"delivery_error\", \"pieces\", \"sent_parts\", \"voice\"] as const;\n\n/**\n * `known` with a message stored: one it lacks joins at the end; one it holds takes what going out\n * on its channel changed since (where it got to, its parts, its voice note) and keeps the rest as\n * this page has it (its steps, moved by their own frames); untouched when nothing changed.\n */\nfunction withStored(known: Message[], stored: Message): Message[] {\n const held = known.find((message) => message.id === stored.id);\n if (held === undefined) return [...known, stored];\n if (OUTGOING.every((field) => isEqual(held[field], stored[field]))) return known;\n const outgoing = Object.fromEntries(OUTGOING.map((field) => [field, stored[field]]));\n return known.map((message) => (message === held ? { ...held, ...outgoing } : message));\n}\n\n/** The same value, told again: equal by what it holds. */\nconst isEqual = (one: unknown, other: unknown): boolean =>\n JSON.stringify(one ?? null) === JSON.stringify(other ?? null);\n\n/** A change of who answers, as one however it was told: its moment, and to whom. */\nconst handoverKey = ({ at, holder }: Handover): string => `${Date.parse(at)} ${holder}`;\n\n/**\n * `known` with whatever of `more` it lacks, in the order they were made: a change is kept once\n * however often, and by whatever, it is told (the read, a frame, the host's own request).\n */\nfunction withHandovers(known: Handover[], more: Handover[]): Handover[] {\n const keys = new Set(known.map(handoverKey));\n const missing = more.filter((handover) => !keys.has(handoverKey(handover)));\n if (missing.length === 0) return known;\n return [...known, ...missing].sort((one, other) => Date.parse(one.at) - Date.parse(other.at));\n}\n\n/** The messages with message `id` changed; untouched when none is it. */\nfunction withMessage(\n messages: Message[],\n id: string,\n change: (message: Message) => Message,\n): Message[] {\n const at = messages.findIndex((message) => message.id === id);\n const message = messages[at];\n return message ? messages.with(at, change(message)) : messages;\n}\n\n/** Step `id`, wherever it is; none when no message holds it. */\nfunction stepOf(messages: Message[], id: string): Step | undefined {\n return messages.flatMap((message) => message.steps).findLast((step) => step.id === id);\n}\n\n/** The messages with step `id` changed, wherever it is; untouched when no message holds it. */\nfunction withStep(messages: Message[], id: string, change: (step: Step) => Step): Message[] {\n const at = messages.findLastIndex((message) => message.steps.some((step) => step.id === id));\n const message = messages[at];\n if (!message) return messages;\n const steps = message.steps.map((step) => (step.id === id ? change(step) : step));\n return messages.with(at, { ...message, steps });\n}\n\n/** The surface a stopped turn waits on, as the history tells it. */\nfunction awaited(messages: Message[]): string | null {\n return messages.flatMap((message) => message.steps).find((step) => step.awaits)?.id ?? null;\n}\n\n/**\n * The person's answer, landed on the step that waited for it: a question is done with their\n * words as its output (what the history reads back); an action they allowed or declined was\n * already told its own state.\n */\nfunction answered(messages: Message[], action: Action): Message[] {\n return withStep(messages, action.surface, (step) =>\n step.state === \"waiting\"\n ? { ...step, state: \"done\", output: action.label, awaits: false, request: null }\n : { ...step, awaits: false, request: null },\n );\n}\n\n/** How often the history is read again while something goes out on a channel. */\nconst DELIVERY_EVERY = 3_000;\n/** How long a message sent is watched for its receipt before the next read brings it. */\nconst RECEIPT_WITHIN = 60_000;\n\n/**\n * Whether a message is still on its way to the person on a channel: waiting to go, or gone a\n * moment ago and not yet received. What it gets to moves without a frame, so it is read again.\n */\nexport function onItsWay(message: Message, now: number): boolean {\n if (message.delivery === \"queued\") return true;\n return message.delivery === \"sent\" && now - Date.parse(message.created_at) < RECEIPT_WITHIN;\n}\n\n/**\n * Runs one of the host's own tools in the page, for the agent: what it resolves to goes back as\n * the tool's output, what it rejects with as why it failed (an error's message).\n */\nexport type ToolHandler = (call: ToolCall) => Promise<unknown>;\n\n/** What the page answers a tool of the host's when it runs none (no `onTool`), for the agent. */\nexport const NO_TOOL = \"This page can't do that\";\n\nconst refuse = (): Promise<never> => Promise.reject(new Error(NO_TOOL));\n\n/** A conversation, live: its messages, where its turn stands, and the ways to speak. */\nexport interface LiveConversation {\n messages: Message[];\n draft: string;\n pending: boolean;\n /**\n * The step the turn waits on: a surface to answer, or an action the person allows (its\n * `request`, `decides: \"person\"`; `act` on its id with `approve` or `decline`). Nothing else\n * goes until the person acts. A yes the business gives holds nothing.\n */\n awaiting: string | null;\n open: boolean;\n /** Until the history has landed once. */\n loading: boolean;\n /** What the last history read threw, if it failed. */\n error: unknown;\n /**\n * Says something: words, the ids of files uploaded to the conversation for it, or both; false\n * when it cannot go now: nothing to say, a turn running or waiting, the socket closed.\n */\n say: (text: string, files?: readonly string[]) => boolean;\n /** What the person did on a surface; false when the socket is closed. */\n act: (action: Action) => boolean;\n /** Stops the reply on its way; false when the socket is closed. */\n stop: () => boolean;\n /** The conversation's browser while it is open: where it is, who holds it. */\n browser: BrowserState | null;\n /** Hears each picture of the browser's screen, the latest at once; returns how to stop. */\n watchScreen: (listener: (frame: BrowserFrame) => void) => () => void;\n /** Takes the browser from the agent, or gives it back; false when the socket is closed. */\n control: (to: BrowserControl) => boolean;\n /** Closes the browser now (it stops being billed); false when the socket is closed. */\n closeBrowser: () => boolean;\n /** What the person does on the browser's screen while they hold it. */\n input: (event: BrowserInput) => boolean;\n /** Who answers it now: its agent, a person of the business, or nobody; null until the history lands. */\n holder: Holder | null;\n /** Every change of who answers it, in order, kept live. */\n handovers: Handover[];\n}\n\n/**\n * Conversation `conversationId` as the person sees it: the history, kept live by the socket.\n * Each time the socket opens the history is read, with the socket already listening, so nothing\n * stored can fall between the two; what came live meanwhile is kept. `onError` hears each\n * error's code (the socket's, or `load` for a history that could not be read): the host words\n * it, this hook shows no text; but `tool`, the page's answer to a call no longer waiting (one it\n * answered already, told again), which is let pass (noted in development). `onHolder` hears each\n * change of who answers it, live, for the host's own views of it; `handover` is the last change\n * the host knows of (one it made itself, as its request answered), taken at once, so it shows\n * whether or not the socket tells it.\n * `onStep` hears each step the agent starts, live, by its action's name, for the host's own\n * views of it (the builder's column, opened as the agent asks it).\n * `onTool` runs the host's own tools the agent calls in the page (a `tool` frame), and its answer\n * goes up (`tool_result`); each call runs once, and one told again while it waits (the socket\n * opened anew) is answered again with what it gave. Without `onTool`, each is refused with\n * `NO_TOOL`, so the turn never waits on a page that can't run it. One conversation per mount: key\n * the component on the id.\n */\nexport function useConversation(\n client: Client,\n conversationId: string,\n {\n onError,\n onHolder,\n onStep,\n handover,\n onTool,\n }: {\n onError?: ((code: string) => void) | undefined;\n onHolder?: ((holder: Holder, handover: Handover) => void) | undefined;\n onStep?: ((action: string) => void) | undefined;\n handover?: Handover | null | undefined;\n onTool?: ToolHandler | undefined;\n } = {},\n): LiveConversation {\n const [state, dispatch] = useReducer(reduce, EMPTY);\n // The host's change, taken once by what it is: the same one told again changes nothing.\n const told = handover ?? null;\n const toldKey = told === null ? null : handoverKey(told);\n useEffect(() => {\n if (told !== null) dispatch({ type: \"holder\", handled_by: told.holder, handover: told });\n }, [toldKey]);\n // The browser's pictures, out of the state: each repaints its screen alone.\n const [screen] = useState<Screen>(createScreen);\n // Reads are numbered: one that lands after a newer one began, or after the conversation went,\n // is dropped on the floor.\n const reads = useRef(0);\n useEffect(\n () => () => {\n reads.current += 1;\n },\n [client, conversationId],\n );\n\n const read = () => {\n const run = ++reads.current;\n client.conversations.get(conversationId).then(\n ({ messages, pending, handled_by, handovers = [] }) => {\n if (run !== reads.current) return;\n dispatch({ type: \"history\", messages, pending, holder: handled_by, handovers });\n },\n (error: unknown) => {\n if (run !== reads.current) return;\n dispatch({ type: \"failed\", error });\n onError?.(\"load\");\n },\n );\n };\n\n // The host's tools the agent called, by the call's id: running (null), or what each answered.\n const tools = useRef(new Map<string, ToolResult | null>());\n const runTool = ({ id, name, input }: ToolCall) => {\n const known = tools.current.get(id);\n if (known !== undefined) {\n if (known !== null) live.send(known);\n return;\n }\n tools.current.set(id, null);\n void Promise.resolve({ id, name, input })\n .then(onTool ?? refuse)\n .then(\n (value): PromiseSettledResult<unknown> => ({ status: \"fulfilled\", value }),\n (reason: unknown): PromiseSettledResult<unknown> => ({ status: \"rejected\", reason }),\n )\n .then((settled) => {\n const answer = toolResultOf(id, settled);\n tools.current.set(id, answer);\n // A socket closed now hears it when it opens: the call is told again while it waits.\n live.send(answer);\n });\n };\n\n const live = useLive(client, conversationId, {\n onFrame: (frame: Frame) => {\n if (frame.type === \"browser.frame\") {\n screen.show({ jpeg: frame.jpeg, width: frame.width, height: frame.height });\n return;\n }\n if (frame.type === \"error\" && frame.code === STALE) {\n // An answer of the page's that no call waits on any more: nothing for the person.\n note(\"A host's tool answer was let pass:\", frame.detail);\n return;\n }\n if (frame.type === \"browser\" && !frame.open) screen.clear();\n dispatch(frame);\n if (frame.type === \"error\") onError?.(frame.code);\n if (frame.type === \"holder\") onHolder?.(frame.handled_by, frame.handover);\n if (frame.type === \"step\" && frame.state === \"running\" && frame.action !== undefined) {\n onStep?.(frame.action);\n }\n if (frame.type === \"tool\") runTool(frame);\n },\n onOpen: () => {\n dispatch({ type: \"reset\" });\n read();\n },\n });\n\n // On a channel, while something of the business's is on its way to the person, the history is\n // read again every few seconds: where it got to (sent, delivered, read, failed) comes no other\n // way. Each read is a new state, so the question is asked again after it.\n const travelling = state.messages.some((message) => onItsWay(message, Date.now()));\n useEffect(() => {\n if (!travelling || !live.open) return undefined;\n const again = setInterval(read, DELIVERY_EVERY);\n return () => {\n clearInterval(again);\n };\n // `read` does the same work from any render: what it reads is in refs and the dispatch.\n }, [travelling, live.open]);\n\n const say = (text: string, files: readonly string[] = []): boolean => {\n const frame = sayOf(text, files);\n if (frame === null || state.pending || state.awaiting !== null) return false;\n return live.send(frame);\n };\n\n const act = (action: Action): boolean => {\n if (!live.send({ type: \"action\", ...action })) return false;\n dispatch({ type: \"acted\", action });\n return true;\n };\n\n return {\n messages: state.messages,\n draft: state.draft,\n pending: state.pending,\n awaiting: state.awaiting,\n open: live.open,\n loading: !state.loaded,\n error: state.error,\n say,\n act,\n stop: () => live.send({ type: \"stop\" }),\n browser: state.browser,\n watchScreen: screen.watch,\n control: (to) => live.send({ type: \"browser.control\", to }),\n closeBrowser: () => live.send({ type: \"browser.close\" }),\n input: (event) => live.send({ type: \"browser.input\", event }),\n holder: state.holder,\n handovers: state.handovers,\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ //#region src/useDictation.d.ts
2
+ /** Turns a recording into words: the host's (its server's speech to text). */
3
+ export type Dictate = (audio: Blob) => Promise<string>;
4
+ /** Where a dictation is: nothing, the microphone open, the words on their way, or refused. */
5
+ export type Dictation = "idle" | "listening" | "writing" | "failed";
6
+ /**
7
+ * Dictation in the composer: a press opens the microphone, the next one closes it and hands the
8
+ * recording to the host's `dictate`, whose words go to `onWords`. Without `dictate`, or in a
9
+ * browser that cannot record, it is not `available`. Leaving mid-recording stops the microphone.
10
+ */
11
+ export declare function useDictation(dictate: Dictate | undefined, onWords: (words: string) => void): {
12
+ available: boolean;
13
+ state: Dictation;
14
+ toggle: () => void;
15
+ };
16
+ //#endregion
17
+ //# sourceMappingURL=useDictation.d.ts.map