@artooi/agents-web-components 0.0.0-stage → 0.1.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 (543) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/LICENSE +21 -0
  3. package/README.md +4397 -2
  4. package/dist/agents-web-components.bundle.js +5708 -0
  5. package/dist/agents-web-components.bundle.js.map +7 -0
  6. package/dist/bundle.d.ts +3 -0
  7. package/dist/bundle.d.ts.map +1 -0
  8. package/dist/chat.d.ts +3 -0
  9. package/dist/chat.d.ts.map +1 -0
  10. package/dist/chat.js +16373 -0
  11. package/dist/chat.js.map +7 -0
  12. package/dist/chunk-ARNLFGCC.js +7715 -0
  13. package/dist/chunk-ARNLFGCC.js.map +7 -0
  14. package/dist/constants.d.ts +575 -0
  15. package/dist/constants.d.ts.map +1 -0
  16. package/dist/core/activity_registration.d.ts +19 -0
  17. package/dist/core/activity_registration.d.ts.map +1 -0
  18. package/dist/core/activity_registry.d.ts +46 -0
  19. package/dist/core/activity_registry.d.ts.map +1 -0
  20. package/dist/core/activity_renderer.d.ts +20 -0
  21. package/dist/core/activity_renderer.d.ts.map +1 -0
  22. package/dist/core/ag_ui_chat.d.ts +836 -0
  23. package/dist/core/ag_ui_chat.d.ts.map +1 -0
  24. package/dist/core/agui_client.d.ts +370 -0
  25. package/dist/core/agui_client.d.ts.map +1 -0
  26. package/dist/core/attachment.d.ts +42 -0
  27. package/dist/core/attachment.d.ts.map +1 -0
  28. package/dist/core/chat_registry.d.ts +23 -0
  29. package/dist/core/chat_registry.d.ts.map +1 -0
  30. package/dist/core/client_seed.d.ts +27 -0
  31. package/dist/core/client_seed.d.ts.map +1 -0
  32. package/dist/core/conversation_store.d.ts +195 -0
  33. package/dist/core/conversation_store.d.ts.map +1 -0
  34. package/dist/core/create_http_agent.d.ts +57 -0
  35. package/dist/core/create_http_agent.d.ts.map +1 -0
  36. package/dist/core/define_chat.d.ts +13 -0
  37. package/dist/core/define_chat.d.ts.map +1 -0
  38. package/dist/core/events/attachments_detail.d.ts +9 -0
  39. package/dist/core/events/attachments_detail.d.ts.map +1 -0
  40. package/dist/core/events/bar_height_detail.d.ts +6 -0
  41. package/dist/core/events/bar_height_detail.d.ts.map +1 -0
  42. package/dist/core/events/custom_agent_detail.d.ts +8 -0
  43. package/dist/core/events/custom_agent_detail.d.ts.map +1 -0
  44. package/dist/core/events/dock_width_detail.d.ts +8 -0
  45. package/dist/core/events/dock_width_detail.d.ts.map +1 -0
  46. package/dist/core/events/feedback_detail.d.ts +28 -0
  47. package/dist/core/events/feedback_detail.d.ts.map +1 -0
  48. package/dist/core/events/invalidate_detail.d.ts +16 -0
  49. package/dist/core/events/invalidate_detail.d.ts.map +1 -0
  50. package/dist/core/events/maximize_detail.d.ts +5 -0
  51. package/dist/core/events/maximize_detail.d.ts.map +1 -0
  52. package/dist/core/events/run_finished_detail.d.ts +36 -0
  53. package/dist/core/events/run_finished_detail.d.ts.map +1 -0
  54. package/dist/core/events/state_detail.d.ts +5 -0
  55. package/dist/core/events/state_detail.d.ts.map +1 -0
  56. package/dist/core/events/submit_detail.d.ts +8 -0
  57. package/dist/core/events/submit_detail.d.ts.map +1 -0
  58. package/dist/core/events/thread_detail.d.ts +27 -0
  59. package/dist/core/events/thread_detail.d.ts.map +1 -0
  60. package/dist/core/events/thread_title_detail.d.ts +8 -0
  61. package/dist/core/events/thread_title_detail.d.ts.map +1 -0
  62. package/dist/core/events/toggle_detail.d.ts +5 -0
  63. package/dist/core/events/toggle_detail.d.ts.map +1 -0
  64. package/dist/core/events/tool_run.d.ts +11 -0
  65. package/dist/core/events/tool_run.d.ts.map +1 -0
  66. package/dist/core/events/unread_detail.d.ts +11 -0
  67. package/dist/core/events/unread_detail.d.ts.map +1 -0
  68. package/dist/core/message_role.d.ts +4 -0
  69. package/dist/core/message_role.d.ts.map +1 -0
  70. package/dist/core/read_flag.d.ts +11 -0
  71. package/dist/core/read_flag.d.ts.map +1 -0
  72. package/dist/core/read_json_attribute.d.ts +15 -0
  73. package/dist/core/read_json_attribute.d.ts.map +1 -0
  74. package/dist/core/read_max_tool_rounds.d.ts +9 -0
  75. package/dist/core/read_max_tool_rounds.d.ts.map +1 -0
  76. package/dist/core/remote_conversation_store.d.ts +71 -0
  77. package/dist/core/remote_conversation_store.d.ts.map +1 -0
  78. package/dist/core/run_handlers.d.ts +85 -0
  79. package/dist/core/run_handlers.d.ts.map +1 -0
  80. package/dist/core/run_index.d.ts +58 -0
  81. package/dist/core/run_index.d.ts.map +1 -0
  82. package/dist/core/storage_scope.d.ts +118 -0
  83. package/dist/core/storage_scope.d.ts.map +1 -0
  84. package/dist/core/tool_outcome.d.ts +27 -0
  85. package/dist/core/tool_outcome.d.ts.map +1 -0
  86. package/dist/core/transcribe_audio.d.ts +32 -0
  87. package/dist/core/transcribe_audio.d.ts.map +1 -0
  88. package/dist/core/upload_attachment.d.ts +44 -0
  89. package/dist/core/upload_attachment.d.ts.map +1 -0
  90. package/dist/core/utils.d.ts +117 -0
  91. package/dist/core/utils.d.ts.map +1 -0
  92. package/dist/dom/animations.d.ts +122 -0
  93. package/dist/dom/animations.d.ts.map +1 -0
  94. package/dist/dom/dom_driver.d.ts +28 -0
  95. package/dist/dom/dom_driver.d.ts.map +1 -0
  96. package/dist/dom/highlight_overlay.d.ts +39 -0
  97. package/dist/dom/highlight_overlay.d.ts.map +1 -0
  98. package/dist/dom/native_setter.d.ts +5 -0
  99. package/dist/dom/native_setter.d.ts.map +1 -0
  100. package/dist/dom/ring_color.d.ts +16 -0
  101. package/dist/dom/ring_color.d.ts.map +1 -0
  102. package/dist/dom/utils.d.ts +3 -0
  103. package/dist/dom/utils.d.ts.map +1 -0
  104. package/dist/index.d.ts +62 -0
  105. package/dist/index.d.ts.map +1 -0
  106. package/dist/index.js +223 -0
  107. package/dist/index.js.map +7 -0
  108. package/dist/skills/fill_template.d.ts +16 -0
  109. package/dist/skills/fill_template.d.ts.map +1 -0
  110. package/dist/skills/parse_skills.d.ts +8 -0
  111. package/dist/skills/parse_skills.d.ts.map +1 -0
  112. package/dist/skills/skill.d.ts +33 -0
  113. package/dist/skills/skill.d.ts.map +1 -0
  114. package/dist/skills/skill_catalog.d.ts +69 -0
  115. package/dist/skills/skill_catalog.d.ts.map +1 -0
  116. package/dist/skills/skill_name_from.d.ts +12 -0
  117. package/dist/skills/skill_name_from.d.ts.map +1 -0
  118. package/dist/tools/chat_surface_tools.d.ts +77 -0
  119. package/dist/tools/chat_surface_tools.d.ts.map +1 -0
  120. package/dist/tools/client_tool_registry.d.ts +58 -0
  121. package/dist/tools/client_tool_registry.d.ts.map +1 -0
  122. package/dist/tools/is_destructive.d.ts +14 -0
  123. package/dist/tools/is_destructive.d.ts.map +1 -0
  124. package/dist/tools/is_navigates.d.ts +9 -0
  125. package/dist/tools/is_navigates.d.ts.map +1 -0
  126. package/dist/tools/page_action_tools.d.ts +30 -0
  127. package/dist/tools/page_action_tools.d.ts.map +1 -0
  128. package/dist/tools/page_map.d.ts +16 -0
  129. package/dist/tools/page_map.d.ts.map +1 -0
  130. package/dist/tools/page_state.d.ts +27 -0
  131. package/dist/tools/page_state.d.ts.map +1 -0
  132. package/dist/tools/parse_tool_catalog.d.ts +21 -0
  133. package/dist/tools/parse_tool_catalog.d.ts.map +1 -0
  134. package/dist/tools/route_map.d.ts +37 -0
  135. package/dist/tools/route_map.d.ts.map +1 -0
  136. package/dist/tools/tool_catalog.d.ts +86 -0
  137. package/dist/tools/tool_catalog.d.ts.map +1 -0
  138. package/dist/tools/tool_dispatch.d.ts +82 -0
  139. package/dist/tools/tool_dispatch.d.ts.map +1 -0
  140. package/dist/ui/charts/chart_block.d.ts +57 -0
  141. package/dist/ui/charts/chart_block.d.ts.map +1 -0
  142. package/dist/ui/charts/chart_spec_from.d.ts +12 -0
  143. package/dist/ui/charts/chart_spec_from.d.ts.map +1 -0
  144. package/dist/ui/charts/chart_styles.d.ts +2 -0
  145. package/dist/ui/charts/chart_styles.d.ts.map +1 -0
  146. package/dist/ui/charts/chart_tool.d.ts +15 -0
  147. package/dist/ui/charts/chart_tool.d.ts.map +1 -0
  148. package/dist/ui/composer/attachment_styles.d.ts +2 -0
  149. package/dist/ui/composer/attachment_styles.d.ts.map +1 -0
  150. package/dist/ui/composer/attachment_tray.d.ts +53 -0
  151. package/dist/ui/composer/attachment_tray.d.ts.map +1 -0
  152. package/dist/ui/composer/auto_grow.d.ts +10 -0
  153. package/dist/ui/composer/auto_grow.d.ts.map +1 -0
  154. package/dist/ui/composer/build_composer.d.ts +32 -0
  155. package/dist/ui/composer/build_composer.d.ts.map +1 -0
  156. package/dist/ui/composer/composer_attachments.d.ts +57 -0
  157. package/dist/ui/composer/composer_attachments.d.ts.map +1 -0
  158. package/dist/ui/composer/composer_styles.d.ts +2 -0
  159. package/dist/ui/composer/composer_styles.d.ts.map +1 -0
  160. package/dist/ui/composer/composer_voice.d.ts +48 -0
  161. package/dist/ui/composer/composer_voice.d.ts.map +1 -0
  162. package/dist/ui/composer/skill_styles.d.ts +2 -0
  163. package/dist/ui/composer/skill_styles.d.ts.map +1 -0
  164. package/dist/ui/composer/skills_menu.d.ts +34 -0
  165. package/dist/ui/composer/skills_menu.d.ts.map +1 -0
  166. package/dist/ui/composer/voice_input.d.ts +46 -0
  167. package/dist/ui/composer/voice_input.d.ts.map +1 -0
  168. package/dist/ui/excerpts/attach_copy_buttons.d.ts +13 -0
  169. package/dist/ui/excerpts/attach_copy_buttons.d.ts.map +1 -0
  170. package/dist/ui/excerpts/copy_payload.d.ts +30 -0
  171. package/dist/ui/excerpts/copy_payload.d.ts.map +1 -0
  172. package/dist/ui/excerpts/page_quote_offer.d.ts +33 -0
  173. package/dist/ui/excerpts/page_quote_offer.d.ts.map +1 -0
  174. package/dist/ui/excerpts/place_offer.d.ts +9 -0
  175. package/dist/ui/excerpts/place_offer.d.ts.map +1 -0
  176. package/dist/ui/excerpts/quote_selection.d.ts +66 -0
  177. package/dist/ui/excerpts/quote_selection.d.ts.map +1 -0
  178. package/dist/ui/excerpts/transcript_quote_offer.d.ts +57 -0
  179. package/dist/ui/excerpts/transcript_quote_offer.d.ts.map +1 -0
  180. package/dist/ui/fill_ui_string.d.ts +32 -0
  181. package/dist/ui/fill_ui_string.d.ts.map +1 -0
  182. package/dist/ui/history/checkpoint_menu.d.ts +41 -0
  183. package/dist/ui/history/checkpoint_menu.d.ts.map +1 -0
  184. package/dist/ui/history/conversation_history.d.ts +317 -0
  185. package/dist/ui/history/conversation_history.d.ts.map +1 -0
  186. package/dist/ui/history/history_styles.d.ts +2 -0
  187. package/dist/ui/history/history_styles.d.ts.map +1 -0
  188. package/dist/ui/history/relative_time.d.ts +23 -0
  189. package/dist/ui/history/relative_time.d.ts.map +1 -0
  190. package/dist/ui/history/thread_drawer.d.ts +64 -0
  191. package/dist/ui/history/thread_drawer.d.ts.map +1 -0
  192. package/dist/ui/history/utils.d.ts +2 -0
  193. package/dist/ui/history/utils.d.ts.map +1 -0
  194. package/dist/ui/interrupts/approval_card.d.ts +64 -0
  195. package/dist/ui/interrupts/approval_card.d.ts.map +1 -0
  196. package/dist/ui/interrupts/approval_styles.d.ts +2 -0
  197. package/dist/ui/interrupts/approval_styles.d.ts.map +1 -0
  198. package/dist/ui/interrupts/confirmation_card.d.ts +51 -0
  199. package/dist/ui/interrupts/confirmation_card.d.ts.map +1 -0
  200. package/dist/ui/interrupts/confirmation_styles.d.ts +2 -0
  201. package/dist/ui/interrupts/confirmation_styles.d.ts.map +1 -0
  202. package/dist/ui/interrupts/pending_decision.d.ts +22 -0
  203. package/dist/ui/interrupts/pending_decision.d.ts.map +1 -0
  204. package/dist/ui/interrupts/question_card.d.ts +49 -0
  205. package/dist/ui/interrupts/question_card.d.ts.map +1 -0
  206. package/dist/ui/interrupts/question_styles.d.ts +2 -0
  207. package/dist/ui/interrupts/question_styles.d.ts.map +1 -0
  208. package/dist/ui/place/place.d.ts +17 -0
  209. package/dist/ui/place/place.d.ts.map +1 -0
  210. package/dist/ui/place/place_chip.d.ts +26 -0
  211. package/dist/ui/place/place_chip.d.ts.map +1 -0
  212. package/dist/ui/place/place_from_route.d.ts +9 -0
  213. package/dist/ui/place/place_from_route.d.ts.map +1 -0
  214. package/dist/ui/place/place_styles.d.ts +2 -0
  215. package/dist/ui/place/place_styles.d.ts.map +1 -0
  216. package/dist/ui/placement/clamp_launcher.d.ts +20 -0
  217. package/dist/ui/placement/clamp_launcher.d.ts.map +1 -0
  218. package/dist/ui/placement/clamp_panel.d.ts +13 -0
  219. package/dist/ui/placement/clamp_panel.d.ts.map +1 -0
  220. package/dist/ui/placement/collapse_styles.d.ts +2 -0
  221. package/dist/ui/placement/collapse_styles.d.ts.map +1 -0
  222. package/dist/ui/placement/dock_styles.d.ts +2 -0
  223. package/dist/ui/placement/dock_styles.d.ts.map +1 -0
  224. package/dist/ui/placement/embedded_styles.d.ts +2 -0
  225. package/dist/ui/placement/embedded_styles.d.ts.map +1 -0
  226. package/dist/ui/placement/launcher_drag.d.ts +49 -0
  227. package/dist/ui/placement/launcher_drag.d.ts.map +1 -0
  228. package/dist/ui/placement/launcher_placement.d.ts +77 -0
  229. package/dist/ui/placement/launcher_placement.d.ts.map +1 -0
  230. package/dist/ui/placement/launcher_styles.d.ts +2 -0
  231. package/dist/ui/placement/launcher_styles.d.ts.map +1 -0
  232. package/dist/ui/placement/page_styles.d.ts +2 -0
  233. package/dist/ui/placement/page_styles.d.ts.map +1 -0
  234. package/dist/ui/placement/panel_drag.d.ts +40 -0
  235. package/dist/ui/placement/panel_drag.d.ts.map +1 -0
  236. package/dist/ui/placement/panel_placement.d.ts +173 -0
  237. package/dist/ui/placement/panel_placement.d.ts.map +1 -0
  238. package/dist/ui/placement/place_widget.d.ts +31 -0
  239. package/dist/ui/placement/place_widget.d.ts.map +1 -0
  240. package/dist/ui/placement/preset_styles.d.ts +2 -0
  241. package/dist/ui/placement/preset_styles.d.ts.map +1 -0
  242. package/dist/ui/placement/resize_handle.d.ts +78 -0
  243. package/dist/ui/placement/resize_handle.d.ts.map +1 -0
  244. package/dist/ui/placement/resize_styles.d.ts +2 -0
  245. package/dist/ui/placement/resize_styles.d.ts.map +1 -0
  246. package/dist/ui/placement/sidebar_styles.d.ts +2 -0
  247. package/dist/ui/placement/sidebar_styles.d.ts.map +1 -0
  248. package/dist/ui/placement/small_viewport_styles.d.ts +2 -0
  249. package/dist/ui/placement/small_viewport_styles.d.ts.map +1 -0
  250. package/dist/ui/placement/surface_for.d.ts +93 -0
  251. package/dist/ui/placement/surface_for.d.ts.map +1 -0
  252. package/dist/ui/progress/prettify_tool_name.d.ts +11 -0
  253. package/dist/ui/progress/prettify_tool_name.d.ts.map +1 -0
  254. package/dist/ui/progress/run_announcer.d.ts +41 -0
  255. package/dist/ui/progress/run_announcer.d.ts.map +1 -0
  256. package/dist/ui/progress/run_notice.d.ts +21 -0
  257. package/dist/ui/progress/run_notice.d.ts.map +1 -0
  258. package/dist/ui/progress/run_notice_styles.d.ts +2 -0
  259. package/dist/ui/progress/run_notice_styles.d.ts.map +1 -0
  260. package/dist/ui/progress/subagent_panel.d.ts +101 -0
  261. package/dist/ui/progress/subagent_panel.d.ts.map +1 -0
  262. package/dist/ui/progress/subagent_progress.d.ts +57 -0
  263. package/dist/ui/progress/subagent_progress.d.ts.map +1 -0
  264. package/dist/ui/progress/subagent_update.d.ts +28 -0
  265. package/dist/ui/progress/subagent_update.d.ts.map +1 -0
  266. package/dist/ui/progress/thoughts_block.d.ts +57 -0
  267. package/dist/ui/progress/thoughts_block.d.ts.map +1 -0
  268. package/dist/ui/progress/thoughts_styles.d.ts +2 -0
  269. package/dist/ui/progress/thoughts_styles.d.ts.map +1 -0
  270. package/dist/ui/progress/tool_call_card.d.ts +167 -0
  271. package/dist/ui/progress/tool_call_card.d.ts.map +1 -0
  272. package/dist/ui/progress/tool_group_styles.d.ts +2 -0
  273. package/dist/ui/progress/tool_group_styles.d.ts.map +1 -0
  274. package/dist/ui/progress/tool_step_group.d.ts +50 -0
  275. package/dist/ui/progress/tool_step_group.d.ts.map +1 -0
  276. package/dist/ui/progress/tool_step_styles.d.ts +2 -0
  277. package/dist/ui/progress/tool_step_styles.d.ts.map +1 -0
  278. package/dist/ui/shell/adopt_styles.d.ts +28 -0
  279. package/dist/ui/shell/adopt_styles.d.ts.map +1 -0
  280. package/dist/ui/shell/build_header.d.ts +45 -0
  281. package/dist/ui/shell/build_header.d.ts.map +1 -0
  282. package/dist/ui/shell/build_launcher.d.ts +33 -0
  283. package/dist/ui/shell/build_launcher.d.ts.map +1 -0
  284. package/dist/ui/shell/collapse_glyph.d.ts +14 -0
  285. package/dist/ui/shell/collapse_glyph.d.ts.map +1 -0
  286. package/dist/ui/shell/frame_styles.d.ts +2 -0
  287. package/dist/ui/shell/frame_styles.d.ts.map +1 -0
  288. package/dist/ui/shell/glyph_slot.d.ts +7 -0
  289. package/dist/ui/shell/glyph_slot.d.ts.map +1 -0
  290. package/dist/ui/shell/header_button.d.ts +11 -0
  291. package/dist/ui/shell/header_button.d.ts.map +1 -0
  292. package/dist/ui/shell/icon_element.d.ts +12 -0
  293. package/dist/ui/shell/icon_element.d.ts.map +1 -0
  294. package/dist/ui/shell/is_unread_badge_enabled.d.ts +10 -0
  295. package/dist/ui/shell/is_unread_badge_enabled.d.ts.map +1 -0
  296. package/dist/ui/shell/read_launcher_icon_url.d.ts +8 -0
  297. package/dist/ui/shell/read_launcher_icon_url.d.ts.map +1 -0
  298. package/dist/ui/shell/theme_styles.d.ts +2 -0
  299. package/dist/ui/shell/theme_styles.d.ts.map +1 -0
  300. package/dist/ui/shell/token_styles.d.ts +2 -0
  301. package/dist/ui/shell/token_styles.d.ts.map +1 -0
  302. package/dist/ui/styles.d.ts +2 -0
  303. package/dist/ui/styles.d.ts.map +1 -0
  304. package/dist/ui/themes/classic_styles.d.ts +2 -0
  305. package/dist/ui/themes/classic_styles.d.ts.map +1 -0
  306. package/dist/ui/themes/classic_tokens.d.ts +2 -0
  307. package/dist/ui/themes/classic_tokens.d.ts.map +1 -0
  308. package/dist/ui/themes/code_tokens.d.ts +2 -0
  309. package/dist/ui/themes/code_tokens.d.ts.map +1 -0
  310. package/dist/ui/themes/ledger_styles.d.ts +2 -0
  311. package/dist/ui/themes/ledger_styles.d.ts.map +1 -0
  312. package/dist/ui/themes/ledger_tokens.d.ts +2 -0
  313. package/dist/ui/themes/ledger_tokens.d.ts.map +1 -0
  314. package/dist/ui/themes/modern_styles.d.ts +2 -0
  315. package/dist/ui/themes/modern_styles.d.ts.map +1 -0
  316. package/dist/ui/themes/quiet_styles.d.ts +2 -0
  317. package/dist/ui/themes/quiet_styles.d.ts.map +1 -0
  318. package/dist/ui/themes/scheme_styles.d.ts +2 -0
  319. package/dist/ui/themes/scheme_styles.d.ts.map +1 -0
  320. package/dist/ui/themes/soft_styles.d.ts +2 -0
  321. package/dist/ui/themes/soft_styles.d.ts.map +1 -0
  322. package/dist/ui/themes/soft_tokens.d.ts +2 -0
  323. package/dist/ui/themes/soft_tokens.d.ts.map +1 -0
  324. package/dist/ui/themes/theme_hosts.d.ts +15 -0
  325. package/dist/ui/themes/theme_hosts.d.ts.map +1 -0
  326. package/dist/ui/transcript/answer_actions.d.ts +50 -0
  327. package/dist/ui/transcript/answer_actions.d.ts.map +1 -0
  328. package/dist/ui/transcript/answer_stream.d.ts +56 -0
  329. package/dist/ui/transcript/answer_stream.d.ts.map +1 -0
  330. package/dist/ui/transcript/attachment_chip_styles.d.ts +2 -0
  331. package/dist/ui/transcript/attachment_chip_styles.d.ts.map +1 -0
  332. package/dist/ui/transcript/attachment_chips.d.ts +21 -0
  333. package/dist/ui/transcript/attachment_chips.d.ts.map +1 -0
  334. package/dist/ui/transcript/build_transcript.d.ts +21 -0
  335. package/dist/ui/transcript/build_transcript.d.ts.map +1 -0
  336. package/dist/ui/transcript/greeting_styles.d.ts +2 -0
  337. package/dist/ui/transcript/greeting_styles.d.ts.map +1 -0
  338. package/dist/ui/transcript/groups_tool_steps.d.ts +13 -0
  339. package/dist/ui/transcript/groups_tool_steps.d.ts.map +1 -0
  340. package/dist/ui/transcript/message_action_styles.d.ts +2 -0
  341. package/dist/ui/transcript/message_action_styles.d.ts.map +1 -0
  342. package/dist/ui/transcript/message_actions.d.ts +74 -0
  343. package/dist/ui/transcript/message_actions.d.ts.map +1 -0
  344. package/dist/ui/transcript/message_styles.d.ts +2 -0
  345. package/dist/ui/transcript/message_styles.d.ts.map +1 -0
  346. package/dist/ui/transcript/render_markdown.d.ts +40 -0
  347. package/dist/ui/transcript/render_markdown.d.ts.map +1 -0
  348. package/dist/ui/transcript/render_or_warn.d.ts +16 -0
  349. package/dist/ui/transcript/render_or_warn.d.ts.map +1 -0
  350. package/dist/ui/transcript/reveal_words.d.ts +8 -0
  351. package/dist/ui/transcript/reveal_words.d.ts.map +1 -0
  352. package/dist/ui/transcript/starter_chips.d.ts +21 -0
  353. package/dist/ui/transcript/starter_chips.d.ts.map +1 -0
  354. package/dist/ui/transcript/stick_to_bottom.d.ts +55 -0
  355. package/dist/ui/transcript/stick_to_bottom.d.ts.map +1 -0
  356. package/dist/ui/transcript/suggestion_chips.d.ts +29 -0
  357. package/dist/ui/transcript/suggestion_chips.d.ts.map +1 -0
  358. package/dist/ui/transcript/transcript.d.ts +196 -0
  359. package/dist/ui/transcript/transcript.d.ts.map +1 -0
  360. package/dist/ui/transcript/transcript_styles.d.ts +2 -0
  361. package/dist/ui/transcript/transcript_styles.d.ts.map +1 -0
  362. package/dist/ui/ui_strings.d.ts +352 -0
  363. package/dist/ui/ui_strings.d.ts.map +1 -0
  364. package/dist/version.d.ts +2 -0
  365. package/dist/version.d.ts.map +1 -0
  366. package/package.json +86 -3
  367. package/src/bundle.ts +2 -0
  368. package/src/chat.ts +2 -0
  369. package/src/constants.ts +650 -0
  370. package/src/core/activity_registration.ts +19 -0
  371. package/src/core/activity_registry.ts +133 -0
  372. package/src/core/activity_renderer.ts +19 -0
  373. package/src/core/ag_ui_chat.ts +3966 -0
  374. package/src/core/agui_client.ts +1028 -0
  375. package/src/core/attachment.ts +62 -0
  376. package/src/core/chat_registry.ts +53 -0
  377. package/src/core/client_seed.ts +27 -0
  378. package/src/core/conversation_store.ts +478 -0
  379. package/src/core/create_http_agent.ts +97 -0
  380. package/src/core/define_chat.ts +25 -0
  381. package/src/core/events/attachments_detail.ts +9 -0
  382. package/src/core/events/bar_height_detail.ts +5 -0
  383. package/src/core/events/custom_agent_detail.ts +7 -0
  384. package/src/core/events/dock_width_detail.ts +7 -0
  385. package/src/core/events/feedback_detail.ts +27 -0
  386. package/src/core/events/invalidate_detail.ts +15 -0
  387. package/src/core/events/maximize_detail.ts +4 -0
  388. package/src/core/events/run_finished_detail.ts +36 -0
  389. package/src/core/events/state_detail.ts +4 -0
  390. package/src/core/events/submit_detail.ts +8 -0
  391. package/src/core/events/thread_detail.ts +26 -0
  392. package/src/core/events/thread_title_detail.ts +7 -0
  393. package/src/core/events/toggle_detail.ts +4 -0
  394. package/src/core/events/tool_run.ts +10 -0
  395. package/src/core/events/unread_detail.ts +10 -0
  396. package/src/core/message_role.ts +4 -0
  397. package/src/core/read_flag.ts +13 -0
  398. package/src/core/read_json_attribute.ts +30 -0
  399. package/src/core/read_max_tool_rounds.ts +13 -0
  400. package/src/core/remote_conversation_store.ts +279 -0
  401. package/src/core/run_handlers.ts +524 -0
  402. package/src/core/run_index.ts +114 -0
  403. package/src/core/storage_scope.ts +291 -0
  404. package/src/core/tool_outcome.ts +39 -0
  405. package/src/core/transcribe_audio.ts +76 -0
  406. package/src/core/upload_attachment.ts +130 -0
  407. package/src/core/utils.ts +230 -0
  408. package/src/dom/animations.ts +341 -0
  409. package/src/dom/dom_driver.ts +91 -0
  410. package/src/dom/highlight_overlay.ts +204 -0
  411. package/src/dom/native_setter.ts +40 -0
  412. package/src/dom/ring_color.ts +206 -0
  413. package/src/dom/utils.ts +5 -0
  414. package/src/index.ts +220 -0
  415. package/src/skills/fill_template.ts +31 -0
  416. package/src/skills/parse_skills.ts +31 -0
  417. package/src/skills/skill.ts +32 -0
  418. package/src/skills/skill_catalog.ts +172 -0
  419. package/src/skills/skill_name_from.ts +19 -0
  420. package/src/tools/chat_surface_tools.ts +183 -0
  421. package/src/tools/client_tool_registry.ts +80 -0
  422. package/src/tools/is_destructive.ts +17 -0
  423. package/src/tools/is_navigates.ts +12 -0
  424. package/src/tools/page_action_tools.ts +123 -0
  425. package/src/tools/page_map.ts +26 -0
  426. package/src/tools/page_state.ts +57 -0
  427. package/src/tools/parse_tool_catalog.ts +41 -0
  428. package/src/tools/route_map.ts +132 -0
  429. package/src/tools/tool_catalog.ts +334 -0
  430. package/src/tools/tool_dispatch.ts +453 -0
  431. package/src/ui/charts/chart_block.ts +519 -0
  432. package/src/ui/charts/chart_spec_from.ts +125 -0
  433. package/src/ui/charts/chart_styles.ts +63 -0
  434. package/src/ui/charts/chart_tool.ts +72 -0
  435. package/src/ui/composer/attachment_styles.ts +71 -0
  436. package/src/ui/composer/attachment_tray.ts +295 -0
  437. package/src/ui/composer/auto_grow.ts +12 -0
  438. package/src/ui/composer/build_composer.ts +114 -0
  439. package/src/ui/composer/composer_attachments.ts +324 -0
  440. package/src/ui/composer/composer_styles.ts +177 -0
  441. package/src/ui/composer/composer_voice.ts +93 -0
  442. package/src/ui/composer/skill_styles.ts +120 -0
  443. package/src/ui/composer/skills_menu.ts +188 -0
  444. package/src/ui/composer/voice_input.ts +282 -0
  445. package/src/ui/excerpts/attach_copy_buttons.ts +73 -0
  446. package/src/ui/excerpts/copy_payload.ts +156 -0
  447. package/src/ui/excerpts/page_quote_offer.ts +203 -0
  448. package/src/ui/excerpts/place_offer.ts +24 -0
  449. package/src/ui/excerpts/quote_selection.ts +345 -0
  450. package/src/ui/excerpts/transcript_quote_offer.ts +175 -0
  451. package/src/ui/fill_ui_string.ts +41 -0
  452. package/src/ui/history/checkpoint_menu.ts +300 -0
  453. package/src/ui/history/conversation_history.ts +1169 -0
  454. package/src/ui/history/history_styles.ts +492 -0
  455. package/src/ui/history/relative_time.ts +50 -0
  456. package/src/ui/history/thread_drawer.ts +471 -0
  457. package/src/ui/history/utils.ts +11 -0
  458. package/src/ui/interrupts/approval_card.ts +202 -0
  459. package/src/ui/interrupts/approval_styles.ts +52 -0
  460. package/src/ui/interrupts/confirmation_card.ts +138 -0
  461. package/src/ui/interrupts/confirmation_styles.ts +114 -0
  462. package/src/ui/interrupts/pending_decision.ts +33 -0
  463. package/src/ui/interrupts/question_card.ts +213 -0
  464. package/src/ui/interrupts/question_styles.ts +73 -0
  465. package/src/ui/place/place.ts +16 -0
  466. package/src/ui/place/place_chip.ts +146 -0
  467. package/src/ui/place/place_from_route.ts +27 -0
  468. package/src/ui/place/place_styles.ts +108 -0
  469. package/src/ui/placement/clamp_launcher.ts +38 -0
  470. package/src/ui/placement/clamp_panel.ts +30 -0
  471. package/src/ui/placement/collapse_styles.ts +472 -0
  472. package/src/ui/placement/dock_styles.ts +116 -0
  473. package/src/ui/placement/embedded_styles.ts +14 -0
  474. package/src/ui/placement/launcher_drag.ts +206 -0
  475. package/src/ui/placement/launcher_placement.ts +133 -0
  476. package/src/ui/placement/launcher_styles.ts +189 -0
  477. package/src/ui/placement/page_styles.ts +47 -0
  478. package/src/ui/placement/panel_drag.ts +138 -0
  479. package/src/ui/placement/panel_placement.ts +1975 -0
  480. package/src/ui/placement/place_widget.ts +64 -0
  481. package/src/ui/placement/preset_styles.ts +49 -0
  482. package/src/ui/placement/resize_handle.ts +229 -0
  483. package/src/ui/placement/resize_styles.ts +201 -0
  484. package/src/ui/placement/sidebar_styles.ts +113 -0
  485. package/src/ui/placement/small_viewport_styles.ts +70 -0
  486. package/src/ui/placement/surface_for.ts +183 -0
  487. package/src/ui/progress/prettify_tool_name.ts +16 -0
  488. package/src/ui/progress/run_announcer.ts +67 -0
  489. package/src/ui/progress/run_notice.ts +61 -0
  490. package/src/ui/progress/run_notice_styles.ts +52 -0
  491. package/src/ui/progress/subagent_panel.ts +227 -0
  492. package/src/ui/progress/subagent_progress.ts +200 -0
  493. package/src/ui/progress/subagent_update.ts +89 -0
  494. package/src/ui/progress/thoughts_block.ts +165 -0
  495. package/src/ui/progress/thoughts_styles.ts +74 -0
  496. package/src/ui/progress/tool_call_card.ts +429 -0
  497. package/src/ui/progress/tool_group_styles.ts +313 -0
  498. package/src/ui/progress/tool_step_group.ts +317 -0
  499. package/src/ui/progress/tool_step_styles.ts +486 -0
  500. package/src/ui/shell/adopt_styles.ts +34 -0
  501. package/src/ui/shell/build_header.ts +121 -0
  502. package/src/ui/shell/build_launcher.ts +79 -0
  503. package/src/ui/shell/collapse_glyph.ts +42 -0
  504. package/src/ui/shell/frame_styles.ts +147 -0
  505. package/src/ui/shell/glyph_slot.ts +12 -0
  506. package/src/ui/shell/header_button.ts +22 -0
  507. package/src/ui/shell/icon_element.ts +33 -0
  508. package/src/ui/shell/is_unread_badge_enabled.ts +11 -0
  509. package/src/ui/shell/read_launcher_icon_url.ts +9 -0
  510. package/src/ui/shell/theme_styles.ts +11 -0
  511. package/src/ui/shell/token_styles.ts +480 -0
  512. package/src/ui/styles.ts +110 -0
  513. package/src/ui/themes/classic_styles.ts +32 -0
  514. package/src/ui/themes/classic_tokens.ts +51 -0
  515. package/src/ui/themes/code_tokens.ts +21 -0
  516. package/src/ui/themes/ledger_styles.ts +169 -0
  517. package/src/ui/themes/ledger_tokens.ts +33 -0
  518. package/src/ui/themes/modern_styles.ts +80 -0
  519. package/src/ui/themes/quiet_styles.ts +118 -0
  520. package/src/ui/themes/scheme_styles.ts +26 -0
  521. package/src/ui/themes/soft_styles.ts +149 -0
  522. package/src/ui/themes/soft_tokens.ts +29 -0
  523. package/src/ui/themes/theme_hosts.ts +14 -0
  524. package/src/ui/transcript/answer_actions.ts +165 -0
  525. package/src/ui/transcript/answer_stream.ts +123 -0
  526. package/src/ui/transcript/attachment_chip_styles.ts +116 -0
  527. package/src/ui/transcript/attachment_chips.ts +82 -0
  528. package/src/ui/transcript/build_transcript.ts +67 -0
  529. package/src/ui/transcript/greeting_styles.ts +171 -0
  530. package/src/ui/transcript/groups_tool_steps.ts +16 -0
  531. package/src/ui/transcript/message_action_styles.ts +155 -0
  532. package/src/ui/transcript/message_actions.ts +234 -0
  533. package/src/ui/transcript/message_styles.ts +262 -0
  534. package/src/ui/transcript/render_markdown.ts +181 -0
  535. package/src/ui/transcript/render_or_warn.ts +22 -0
  536. package/src/ui/transcript/reveal_words.ts +41 -0
  537. package/src/ui/transcript/starter_chips.ts +42 -0
  538. package/src/ui/transcript/stick_to_bottom.ts +126 -0
  539. package/src/ui/transcript/suggestion_chips.ts +73 -0
  540. package/src/ui/transcript/transcript.ts +555 -0
  541. package/src/ui/transcript/transcript_styles.ts +153 -0
  542. package/src/ui/ui_strings.ts +550 -0
  543. package/src/version.ts +1 -0
@@ -0,0 +1,324 @@
1
+ import {
2
+ ATTACHMENT_EVENT,
3
+ DEFAULT_ATTACHMENT_MAX_BYTES,
4
+ PASTE_ATTACH_CHARS,
5
+ } from "../../constants.js";
6
+ import type { AttachmentsDetail } from "../../core/events/attachments_detail.js";
7
+ import { type UploadHandler, uploadAttachment } from "../../core/upload_attachment.js";
8
+ import type { UiStrings } from "../ui_strings.js";
9
+ import { AttachmentTray } from "./attachment_tray.js";
10
+
11
+ /** What the composer's attachments need from the element that owns them. */
12
+ export interface ComposerAttachmentsHost {
13
+ /** The custom element: its upload attributes, and where the event is dispatched. */
14
+ readonly element: HTMLElement;
15
+ /** The chat shell, which a file can be dropped or pasted anywhere on. */
16
+ readonly chat: HTMLElement;
17
+ /** Where the tray mounts, above the composer. */
18
+ readonly slot: HTMLElement;
19
+ /** The hidden multi-file input the paperclip opens. */
20
+ readonly fileInput: HTMLInputElement;
21
+ /** The paperclip, revealed once uploads are possible. */
22
+ readonly button: HTMLButtonElement;
23
+ /** The resolved string table. */
24
+ readonly strings: () => UiStrings;
25
+ /** The host's `uploadHandler`, read when the tray is wired. */
26
+ readonly uploadHandler: () => UploadHandler | null;
27
+ /** The headers a request to `url` carries. */
28
+ readonly headersFor: (url: string) => Record<string, string>;
29
+ /** The cookie policy every request carries, when one is configured. */
30
+ readonly credentialsOption: () => { credentials?: RequestCredentials };
31
+ }
32
+
33
+ /**
34
+ * Files handed to the composer: the tray they upload through, and the four
35
+ * ways into it -- the picker, a drop, a paste, and a host's `attachFile`.
36
+ *
37
+ * Owned one-to-one by an `<ag-ui-chat>`, and holding no state outside the
38
+ * instance.
39
+ */
40
+ export class ComposerAttachments {
41
+ readonly #host: ComposerAttachmentsHost;
42
+ /** Upload tray; created on connect only when `data-attachments-url` is set. */
43
+ #tray: AttachmentTray | null = null;
44
+
45
+ constructor(host: ComposerAttachmentsHost) {
46
+ this.#host = host;
47
+ }
48
+
49
+ /** The tray, once uploads are wired; `null` while the chat is text-only. */
50
+ get tray(): AttachmentTray | null {
51
+ return this.#tray;
52
+ }
53
+
54
+ /**
55
+ * Enable the composer's file-upload tray when uploads are possible — either a
56
+ * custom `uploadHandler` is set or `data-attachments-url` provides the
57
+ * built-in multipart endpoint: reveal the 📎 button, wire the hidden file
58
+ * input + drag-and-drop, and mount the tray. With neither, the affordance
59
+ * stays hidden and the chat degrades to text-only.
60
+ *
61
+ * Called on every connect, so it starts by taking down the tray the last
62
+ * connection mounted: that one was disposed when the element left, and the
63
+ * attributes that decide whether there is a tray at all may have changed
64
+ * since. The shell outlives a connection, so its listeners go under `signal`.
65
+ */
66
+ wire(signal: AbortSignal): void {
67
+ this.#tray?.element.remove();
68
+ this.#tray = null;
69
+ const url = this.#host.element.getAttribute("data-attachments-url");
70
+ const upload = this.#host.uploadHandler() ?? this.#defaultUploadHandler(url);
71
+ if (upload === null) {
72
+ return;
73
+ }
74
+ const accept = this.#host.element.getAttribute("data-attachment-accept") ?? "";
75
+ // Bound to the local rather than the field: the hook can only fire from a
76
+ // tray that exists, so passing it removes a null check no caller can reach.
77
+ const tray: AttachmentTray = new AttachmentTray({
78
+ upload,
79
+ maxBytes: this.#maxBytes(),
80
+ accept,
81
+ strings: this.#host.strings(),
82
+ // The tray's change hook, surfaced to the host as an event. A host
83
+ // driving its own composer could otherwise not tell a settled upload from
84
+ // one still in flight, which is the state sendMessage() has to be called
85
+ // with knowledge of.
86
+ onChange: () => this.#dispatch(tray),
87
+ });
88
+ this.#tray = tray;
89
+ this.#host.slot.appendChild(this.#tray.element);
90
+ this.#host.fileInput.accept = accept;
91
+ this.#host.button.hidden = false;
92
+ this.#enableDragAndDrop(signal);
93
+ this.#enablePaste(tray, signal);
94
+ }
95
+
96
+ /** The queueing behind `AgUiChat.attachFile`, whose doc is the contract. */
97
+ attach(file: File): boolean {
98
+ if (this.#tray === null) {
99
+ return false;
100
+ }
101
+ this.#tray.add(file);
102
+ return true;
103
+ }
104
+
105
+ /** Queue every file from the picker into the tray, then reset the input. */
106
+ onFilesPicked(): void {
107
+ const input = this.#host.fileInput;
108
+ const files = input.files;
109
+ if (files !== null) {
110
+ for (const file of Array.from(files)) {
111
+ this.#tray?.add(file);
112
+ }
113
+ }
114
+ // Reset so re-picking the same file fires `change` again.
115
+ input.value = "";
116
+ }
117
+
118
+ /** The built-in multipart upload handler for `data-attachments-url`, or `null`. */
119
+ #defaultUploadHandler(url: string | null): UploadHandler | null {
120
+ if (url === null) {
121
+ return null;
122
+ }
123
+ // Forward the tray's abort signal so removing a chip (or tearing the
124
+ // element down) cancels the XHR.
125
+ return (file, onProgress, signal) =>
126
+ uploadAttachment(file, {
127
+ url,
128
+ headers: this.#host.headersFor(url),
129
+ ...this.#host.credentialsOption(),
130
+ onProgress,
131
+ signal,
132
+ });
133
+ }
134
+
135
+ /** The client-side upload size cap from `data-attachment-max-bytes`. */
136
+ #maxBytes(): number {
137
+ const attr = this.#host.element.getAttribute("data-attachment-max-bytes");
138
+ if (attr === null) {
139
+ return DEFAULT_ATTACHMENT_MAX_BYTES;
140
+ }
141
+ const parsed = Number.parseInt(attr, 10);
142
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : DEFAULT_ATTACHMENT_MAX_BYTES;
143
+ }
144
+
145
+ /** Accept files dropped anywhere on the chat shell into the tray. */
146
+ #enableDragAndDrop(signal: AbortSignal): void {
147
+ const chat = this.#host.chat;
148
+ chat.addEventListener(
149
+ "dragover",
150
+ (event) => {
151
+ event.preventDefault();
152
+ chat.classList.add("chat--dragover");
153
+ },
154
+ { signal },
155
+ );
156
+ chat.addEventListener(
157
+ "dragleave",
158
+ () => {
159
+ chat.classList.remove("chat--dragover");
160
+ },
161
+ { signal },
162
+ );
163
+ chat.addEventListener(
164
+ "drop",
165
+ (event) => {
166
+ event.preventDefault();
167
+ chat.classList.remove("chat--dragover");
168
+ const files = event.dataTransfer?.files;
169
+ if (files !== undefined) {
170
+ for (const file of Array.from(files)) {
171
+ this.#tray?.add(file);
172
+ }
173
+ }
174
+ },
175
+ { signal },
176
+ );
177
+ }
178
+
179
+ /**
180
+ * Turn a very long text paste into an attachment instead of a wall of text.
181
+ *
182
+ * A composer capped at `40vh` is not where forty thousand characters go: the
183
+ * user cannot read what they pasted, cannot edit around it, and sends one
184
+ * enormous turn. As a file it stays whole, the model still receives it, and
185
+ * the box is left for the question about it.
186
+ *
187
+ * Only where the host has configured uploads -- and structurally so, rather
188
+ * than by a check here: the paste listener is wired inside the attachment
189
+ * setup, so with no tray there is no listener at all and an ordinary paste is
190
+ * untouched. Quietly dropping a paste for being long would be far worse than
191
+ * an awkward composer. The tray is passed rather than read off the field for
192
+ * the same reason its `onChange` hook is: it can only be called from one that
193
+ * exists, so taking it as an argument removes a null check no caller can
194
+ * reach.
195
+ *
196
+ * Nothing is lost by removing the chip: the text is still on the clipboard,
197
+ * so pasting again brings it back. That is why this needs no undo of its own.
198
+ */
199
+ #pasteLongTextAsFile(event: ClipboardEvent, clipboard: DataTransfer, tray: AttachmentTray): void {
200
+ const threshold = this.#pasteAttachThreshold();
201
+ const text = clipboard.getData("text/plain");
202
+ if (threshold === null || text.length < threshold) {
203
+ return;
204
+ }
205
+ event.preventDefault();
206
+ tray.add(new File([text], `pasted-${pasteStamp()}.txt`, { type: "text/plain" }));
207
+ }
208
+
209
+ /**
210
+ * How long a pasted string has to be before it becomes a file, or `null` to
211
+ * leave every paste in the composer.
212
+ *
213
+ * One attribute with three answers rather than three attributes: absent is
214
+ * the default, `off` refuses, and a number states the threshold. A value that
215
+ * is neither says so, because a typo silently meaning "off" is the failure
216
+ * this whole release keeps finding.
217
+ */
218
+ #pasteAttachThreshold(): number | null {
219
+ const raw = this.#host.element.getAttribute("data-paste-attach");
220
+ if (raw === null) {
221
+ return PASTE_ATTACH_CHARS;
222
+ }
223
+ if (raw === "off") {
224
+ return null;
225
+ }
226
+ const stated = Number.parseInt(raw, 10);
227
+ if (Number.isNaN(stated) || stated <= 0) {
228
+ console.warn(
229
+ `<ag-ui-chat>: data-paste-attach="${raw}" is neither "off" nor a positive ` +
230
+ `number of characters, so the default of ${PASTE_ATTACH_CHARS} is used.`,
231
+ );
232
+ return PASTE_ATTACH_CHARS;
233
+ }
234
+ return stated;
235
+ }
236
+
237
+ /**
238
+ * Accept files pasted into the composer.
239
+ *
240
+ * The whole tray already exists behind this: a paste is one more way to hand
241
+ * it a `File`, alongside the picker and a drop.
242
+ *
243
+ * Two rules keep it from stealing a paste that was never about files.
244
+ * `clipboardData.files` is empty for text, so ordinary pasting is untouched.
245
+ * And the default is only prevented when the clipboard carries **no text**:
246
+ * copying a rich selection that happens to contain an image puts both on the
247
+ * clipboard, and swallowing the words someone meant to paste in order to
248
+ * attach a picture they did not is the worse of the two failures.
249
+ */
250
+ #enablePaste(tray: AttachmentTray, signal: AbortSignal): void {
251
+ this.#host.chat.addEventListener(
252
+ "paste",
253
+ (event: ClipboardEvent) => {
254
+ // Nullish rather than a null check: the property is typed as nullable,
255
+ // and an engine that fires a plain Event for a paste leaves it absent
256
+ // instead, which is not the same value and is the same situation.
257
+ const clipboard = event.clipboardData ?? null;
258
+ if (clipboard === null) {
259
+ return;
260
+ }
261
+ const files = Array.from(clipboard.files);
262
+ if (files.length === 0) {
263
+ this.#pasteLongTextAsFile(event, clipboard, tray);
264
+ return;
265
+ }
266
+ if (clipboard.getData("text/plain") === "") {
267
+ event.preventDefault();
268
+ }
269
+ for (const file of files) {
270
+ this.#tray?.add(named(file));
271
+ }
272
+ },
273
+ { signal },
274
+ );
275
+ }
276
+
277
+ /** Tell the host what the tray now holds — see {@link ATTACHMENT_EVENT}. */
278
+ #dispatch(tray: AttachmentTray): void {
279
+ this.#host.element.dispatchEvent(
280
+ new CustomEvent<AttachmentsDetail>(ATTACHMENT_EVENT, {
281
+ detail: { attachments: tray.readyRefs(), pending: tray.pendingCount() },
282
+ bubbles: true,
283
+ composed: true,
284
+ }),
285
+ );
286
+ }
287
+ }
288
+
289
+ /**
290
+ * The moment of a paste, as a string a filename can carry.
291
+ *
292
+ * ISO 8601 with its colons and the decimal point replaced, because both are
293
+ * reserved in a filename on at least one platform a download lands on. Shared
294
+ * by the two paste paths, so a pasted image and a long text pasted as a file
295
+ * are named the same way.
296
+ */
297
+ function pasteStamp(): string {
298
+ return new Date().toISOString().replace(/[:.]/g, "-");
299
+ }
300
+
301
+ /**
302
+ * A pasted file, guaranteed to have a name.
303
+ *
304
+ * A file dropped or picked always carries one; a pasted one need not. Some
305
+ * engines hand over a blob with an empty name, which travels all the way to
306
+ * the upload as an empty `filename` and lands on the server as a file nobody
307
+ * can identify -- while the chip in the tray shows an empty label. A file that
308
+ * already has a name keeps it, including the generic one Chrome gives a pasted
309
+ * screenshot: it is at least what the file is, and the chip shows the size
310
+ * beside it.
311
+ */
312
+ function named(file: File): File {
313
+ if (file.name !== "") {
314
+ return file;
315
+ }
316
+ // The subtype is the extension for every clipboard image type worth naming.
317
+ // A type with no slash in it falls back to the whole string, and an absent
318
+ // one leaves a bare stamp rather than a name ending in a dot.
319
+ const subtype = file.type.split("/")[1] ?? file.type;
320
+ const stamp = pasteStamp();
321
+ return new File([file], subtype === "" ? `pasted-${stamp}` : `pasted-${stamp}.${subtype}`, {
322
+ type: file.type,
323
+ });
324
+ }
@@ -0,0 +1,177 @@
1
+ // The composer: field, tool row, icon buttons, send and stop, and the glyph
2
+ // class every icon button and icon holder paints with.
3
+ export const COMPOSER_STYLES: string = `
4
+ /* ── Composer ───────────────────────────────────────────────────────────────
5
+ One surface owns the border, the background and the focus ring; the field
6
+ and its tool row sit inside it, rather than being siblings stretched to the
7
+ textarea's height. */
8
+ .input-row {
9
+ display: flex;
10
+ padding: 12px;
11
+ border-top: 1px solid var(--_border);
12
+ }
13
+
14
+ .composer {
15
+ flex: 1;
16
+ min-width: 0;
17
+ display: flex;
18
+ flex-direction: column;
19
+ gap: 4px;
20
+ padding: 6px 6px 6px 10px;
21
+ background: var(--_input-bg);
22
+ border: 1px solid var(--_border);
23
+ border-radius: var(--_composer-radius);
24
+ transition: border-color var(--_motion) var(--_ease);
25
+ }
26
+
27
+ .composer:focus-within {
28
+ border-color: var(--_accent);
29
+ }
30
+
31
+ /* The field grows with its content (sized by #autoGrow) up to the ceiling,
32
+ then scrolls. border-box keeps that measurement stable: with content-box the
33
+ padding would be added to every scrollHeight read and the field would creep
34
+ taller on each keystroke. */
35
+ .input {
36
+ box-sizing: border-box;
37
+ resize: none;
38
+ max-height: var(--_composer-max-height);
39
+ overflow-y: auto;
40
+ /* Scrolling past the end of this must not scroll the page behind it. */
41
+ overscroll-behavior: contain;
42
+ padding: 6px 4px 2px;
43
+ background: transparent;
44
+ border: none;
45
+ font: inherit;
46
+ color: inherit;
47
+ outline: none;
48
+ }
49
+
50
+ .composer-tools {
51
+ display: flex;
52
+ align-items: center;
53
+ gap: 2px;
54
+ }
55
+
56
+ /* Icon buttons: quiet at rest, so the field is what the eye lands on. They
57
+ keep their size when the row is short of width: the place chip beside them
58
+ is what gives way. */
59
+ .attach-btn,
60
+ .voice-btn {
61
+ display: inline-flex;
62
+ align-items: center;
63
+ justify-content: center;
64
+ flex: none;
65
+ width: var(--_tool-btn-size);
66
+ height: var(--_tool-btn-size);
67
+ padding: 0;
68
+ border: none;
69
+ border-radius: 8px;
70
+ background: transparent;
71
+ color: var(--_muted);
72
+ font: inherit;
73
+ line-height: 1;
74
+ cursor: pointer;
75
+ transition:
76
+ background-color var(--_motion) var(--_ease),
77
+ color var(--_motion) var(--_ease);
78
+ }
79
+
80
+ .attach-btn:hover,
81
+ .voice-btn:hover {
82
+ background: var(--_hover);
83
+ color: var(--_fg);
84
+ }
85
+
86
+ .attach-btn:disabled,
87
+ .voice-btn:disabled {
88
+ cursor: default;
89
+ opacity: 0.6;
90
+ }
91
+
92
+ /* The same trap the attachment tray carries a note about, two rules along: an
93
+ author display beats the UA stylesheet's rule for the hidden property, so a
94
+ button the element has explicitly hidden keeps laying out and painting. The
95
+ clip is hidden until a host supplies an upload handler or an attachments URL,
96
+ and without this it is a visible control that cannot do anything.
97
+
98
+ The mic needs no such rule, and the asymmetry is worth knowing before adding
99
+ one: it is not hidden when unconfigured, it is never built. The voice wiring
100
+ returns before constructing the button, leaving only an empty voice slot that
101
+ is display: contents. A hidden-state rule for the mic would match nothing. */
102
+ .attach-btn[hidden] {
103
+ display: none;
104
+ }
105
+
106
+ /* Send closes the row on the right: a circle, the only filled control in the
107
+ composer, so "the thing that acts" reads at a glance. */
108
+ .send {
109
+ margin-left: auto;
110
+ display: inline-flex;
111
+ align-items: center;
112
+ justify-content: center;
113
+ flex: none;
114
+ width: var(--_send-size);
115
+ height: var(--_send-size);
116
+ padding: 0;
117
+ border: none;
118
+ border-radius: 50%;
119
+ background: var(--_accent);
120
+ color: var(--_on-accent);
121
+ font: inherit;
122
+ line-height: 1;
123
+ cursor: pointer;
124
+ transition:
125
+ background-color var(--_motion) var(--_ease),
126
+ transform var(--_motion) var(--_ease-pop);
127
+ }
128
+
129
+ .send:hover {
130
+ transform: scale(1.08);
131
+ }
132
+
133
+ .send:active {
134
+ transform: scale(0.92);
135
+ }
136
+
137
+ .send:disabled {
138
+ opacity: 0.5;
139
+ cursor: default;
140
+ transform: none;
141
+ }
142
+
143
+ /* The composer button doubles as the Stop control while a run is in flight —
144
+ same circle, different glyph, so nothing moves when a run starts. */
145
+ .send[data-state="running"] {
146
+ background: var(--_muted);
147
+ }
148
+
149
+ .send[data-state="idle"] .send-stop,
150
+ .send[data-state="running"] .send-send {
151
+ display: none;
152
+ }
153
+
154
+ /* Glyphs — one class, painted from the button's own colour so every state
155
+ (hover, recording, running) carries the icon with it. */
156
+ .glyph {
157
+ width: var(--_glyph-size);
158
+ height: var(--_glyph-size);
159
+ fill: none;
160
+ stroke: currentColor;
161
+ stroke-width: var(--_glyph-stroke);
162
+ stroke-linecap: round;
163
+ stroke-linejoin: round;
164
+ }
165
+
166
+ .glyph--solid {
167
+ fill: currentColor;
168
+ stroke: none;
169
+ }
170
+
171
+ /* In an icon holder (header brand, launcher) the glyph takes the holder's size
172
+ rather than the composer's. */
173
+ .icon-holder .glyph {
174
+ width: 100%;
175
+ height: 100%;
176
+ }
177
+ `;
@@ -0,0 +1,93 @@
1
+ import { type TranscribeHandler, transcribeAudio } from "../../core/transcribe_audio.js";
2
+ import type { UiStrings } from "../ui_strings.js";
3
+ import { VoiceInput } from "./voice_input.js";
4
+
5
+ /** What the composer's mic needs from the element that owns it. */
6
+ export interface ComposerVoiceHost {
7
+ /** The custom element, whose `data-transcribe-url` names the built-in endpoint. */
8
+ readonly element: HTMLElement;
9
+ /** Where the mic button mounts, in the composer's tool row. */
10
+ readonly slot: HTMLElement;
11
+ /** The composer a transcript is written into. */
12
+ readonly input: HTMLTextAreaElement;
13
+ /** The resolved string table. */
14
+ readonly strings: () => UiStrings;
15
+ /** The host's `transcribeHandler`, read when the mic is wired. */
16
+ readonly transcribeHandler: () => TranscribeHandler | null;
17
+ /** The headers a request to `url` carries. */
18
+ readonly headersFor: (url: string) => Record<string, string>;
19
+ /** The cookie policy every request carries, when one is configured. */
20
+ readonly credentialsOption: () => { credentials?: RequestCredentials };
21
+ /** React to the composer's value changing, as typing does. */
22
+ readonly onInput: () => void;
23
+ }
24
+
25
+ /**
26
+ * The composer's mic: mounted when transcription is possible, and what a
27
+ * transcript does to the composer.
28
+ *
29
+ * Owned one-to-one by an `<ag-ui-chat>`, and holding no state outside the
30
+ * instance.
31
+ */
32
+ export class ComposerVoice {
33
+ readonly #host: ComposerVoiceHost;
34
+ /** Voice-input control; created on connect when transcription is available. */
35
+ #voice: VoiceInput | null = null;
36
+
37
+ constructor(host: ComposerVoiceHost) {
38
+ this.#host = host;
39
+ }
40
+
41
+ /**
42
+ * Reveal the composer's 🎤 mic button when transcription is possible — either
43
+ * a custom `transcribeHandler` is set or `data-transcribe-url` provides the
44
+ * built-in POST endpoint. The control records via `MediaRecorder` and drops
45
+ * the transcript into the composer; with neither configured the mic stays
46
+ * hidden and the chat is text-only.
47
+ *
48
+ * Called on every connect, so it starts by taking down the mic the last
49
+ * connection mounted, which was released when the element left.
50
+ */
51
+ wire(): void {
52
+ this.#voice?.element.remove();
53
+ this.#voice = null;
54
+ const url = this.#host.element.getAttribute("data-transcribe-url");
55
+ const transcribe = this.#host.transcribeHandler() ?? this.#defaultTranscribeHandler(url);
56
+ if (transcribe === null) {
57
+ return;
58
+ }
59
+ this.#voice = new VoiceInput({
60
+ transcribe,
61
+ onText: (text) => this.#insertText(text),
62
+ strings: this.#host.strings(),
63
+ });
64
+ this.#host.slot.appendChild(this.#voice.element);
65
+ }
66
+
67
+ /** Release the mic, so the browser's recording indicator clears. */
68
+ dispose(): void {
69
+ this.#voice?.dispose();
70
+ }
71
+
72
+ /** The built-in transcription handler for `data-transcribe-url`, or `null`. */
73
+ #defaultTranscribeHandler(url: string | null): TranscribeHandler | null {
74
+ if (url === null) {
75
+ return null;
76
+ }
77
+ return (audio) =>
78
+ transcribeAudio(audio, {
79
+ url,
80
+ headers: this.#host.headersFor(url),
81
+ ...this.#host.credentialsOption(),
82
+ });
83
+ }
84
+
85
+ /** Drop a voice transcript into the composer (appended to any typed text). */
86
+ #insertText(text: string): void {
87
+ const input = this.#host.input;
88
+ const current = input.value.trim();
89
+ input.value = current === "" ? text : `${current} ${text}`;
90
+ this.#host.onInput();
91
+ input.focus();
92
+ }
93
+ }