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