@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,171 @@
1
+ // The empty state: the greeting over an empty conversation, and the
2
+ // composer's travel from the centre to the foot on the first send.
3
+ export const GREETING_STYLES: string = `
4
+ /* Empty-state region (slot): centred while it's the only thing in the
5
+ list, hidden as soon as a message, card, or pending indicator renders. */
6
+ .empty {
7
+ margin: auto;
8
+ text-align: center;
9
+ color: var(--_muted);
10
+ }
11
+
12
+ .empty[hidden] {
13
+ display: none;
14
+ }
15
+
16
+ /* The greeting layout: a greeting over an empty conversation, and the
17
+ composer centred beneath it until the conversation has something in it.
18
+
19
+ On by default for the page placement, where a conversation is the whole
20
+ route; data-greeting="off" turns it off there. An embedded panel opts in
21
+ with any other data-greeting value. No other placement has it: a panel
22
+ opened from a launcher is already mid-task, and a greeting in a corner
23
+ panel costs space and says little.
24
+
25
+ The greeting itself renders under every placement and is hidden here, so a
26
+ placement switch at runtime needs nothing from script. */
27
+ .greeting {
28
+ display: none;
29
+ }
30
+
31
+ :host([placement="page"]:not([data-greeting="off"])) .greeting,
32
+ :host([placement="embedded"][data-greeting]:not([data-greeting="off"])) .greeting {
33
+ display: block;
34
+ margin-block-end: calc(var(--_space) * 2);
35
+ font-family: var(--_greeting-font);
36
+ font-size: var(--_greeting-size);
37
+ font-weight: 500;
38
+ line-height: 1.2;
39
+ color: var(--_fg);
40
+ overflow-wrap: anywhere;
41
+ }
42
+
43
+ /* Centring is two equal flexible boxes either side of the composer rows: the
44
+ transcript above, which already grows, and this one below. Equal zero bases
45
+ make the two halves the same height whatever they hold, so the rows sit in
46
+ the middle of the panel below its header, and stay there as a draft, an
47
+ attachment tray or a hint grows them, because growth splits into both
48
+ halves at once.
49
+
50
+ A pseudo element rather than a node, so no host layout and nothing that
51
+ counts children can see it. It exists whether or not the conversation is
52
+ empty and only its growth changes, because a box that appears and
53
+ disappears is a box nothing can ever transition.
54
+
55
+ Only the rule that generates it names the placements. The one that grows it
56
+ needs nothing but the state: where the first rule does not apply there is no
57
+ box to grow. The box is empty, so its automatic basis is already zero, the
58
+ same as the transcript's; nothing here writes the flex shorthand, because
59
+ this selector is the more specific of the two and a shorthand would win
60
+ over the growth. */
61
+ :host([placement="page"]:not([data-greeting="off"])) .chat::after,
62
+ :host([placement="embedded"][data-greeting]:not([data-greeting="off"])) .chat::after {
63
+ content: "";
64
+ }
65
+
66
+ /* Not while a restore is in flight: a conversation a remote store is still
67
+ fetching is more likely to have messages than not, and centring it first
68
+ would drop the composer the moment they land. */
69
+ :host([data-empty]:not([data-restoring])) .chat::after {
70
+ flex-grow: 1;
71
+ }
72
+
73
+ /* Only the send that leaves the empty state travels. The element arms this for
74
+ that one change and disarms it whenever the transcript is cleared, so a
75
+ restored conversation, a thread switch and a new chat all snap. Growth rather
76
+ than a transform, because the rows between the transcript and the composer
77
+ move with it, and growth is continuous where a reorder is not. Reduced motion
78
+ needs no rule of its own: the motion token already collapses to a frame
79
+ there.
80
+
81
+ The rule over the composer fades in over the same stretch. Appearing at once,
82
+ it was drawn across the page at the composer's destination while the
83
+ composer was still on its way there. */
84
+ :host([data-composer-settling]) .chat::after {
85
+ transition: flex-grow var(--_motion) var(--_ease);
86
+ }
87
+
88
+ :host([data-composer-settling]) .input-row {
89
+ transition: border-color var(--_motion) var(--_ease);
90
+ }
91
+
92
+ /* The greeting and whatever the host slotted sit at the foot of the upper
93
+ half, directly over the composer, rather than floating in its middle. The
94
+ region is hidden once the conversation has content, so this needs no state
95
+ of its own. */
96
+ :host([placement="page"]:not([data-greeting="off"]):not([data-restoring])) .empty,
97
+ :host([placement="embedded"][data-greeting]:not([data-greeting="off"]):not([data-restoring])) .empty {
98
+ margin: auto auto 0;
99
+ }
100
+
101
+ /* The rule over the composer separates it from a transcript. Over nothing it
102
+ is a line drawn across the middle of the page. */
103
+ :host([placement="page"][data-empty]:not([data-greeting="off"]):not([data-restoring])) .input-row,
104
+ :host([placement="embedded"][data-greeting][data-empty]:not([data-greeting="off"]):not([data-restoring])) .input-row {
105
+ border-block-start-color: transparent;
106
+ }
107
+
108
+ /* On a phone the composer stays at the foot and the greeting takes the room
109
+ above it, which is the other way round from everything above.
110
+
111
+ Centring is a shape for a screen with room to spare: the composer reads as
112
+ the one thing on the page, and whichever way the rows grow there is space
113
+ left on both sides of them. A phone has no space to spare, and the keyboard
114
+ is what takes it -- opening one leaves a 426px-tall visible area with the
115
+ composer halfway up it and an empty band underneath, which is the half of
116
+ the screen a thumb is already resting on. Docked, the field sits directly
117
+ over the keyboard, where every chat on the platform puts it, and the
118
+ greeting keeps the rest.
119
+
120
+ Both rules restate the selector they override, with the breakpoint's own
121
+ opt-out added: this is part of the shape a host keeps its desktop layout
122
+ instead of, so it goes the same way as the rest of that shape. Restating
123
+ rather than adding conditions to the originals keeps each of those rules
124
+ readable as one decision, and source order settles the pair. */
125
+ @media (max-width: 600px) {
126
+ :host([data-empty]:not([data-restoring]):not([data-small-viewport="off"])) .chat::after {
127
+ flex-grow: 0;
128
+ }
129
+
130
+ /* The empty region fills the transcript instead of being centred in it as a
131
+ block, so the two things in it can go to different places: the prompts the
132
+ host offers to the foot, against the composer, and the greeting to the
133
+ middle of what they leave.
134
+
135
+ A prompt chip is a way into the conversation. Against the field it starts,
136
+ it reads as one; under the greeting halfway up the panel, with the field
137
+ at the foot, it reads as decoration next to something else. Nothing here
138
+ moves them on a screen where the composer is still centred: there the
139
+ whole region hangs at the foot of the upper half, directly over the
140
+ composer, and the prompts are already against it.
141
+
142
+ Auto block margins on the greeting are what centre it, and they take the
143
+ free space whether or not there are prompts below to leave any, so a host
144
+ that offers none gets a greeting in the middle of the transcript rather
145
+ than one clinging to the composer.
146
+ The region declares a display here, which outranks the rule collapsing a
147
+ hidden one, so it says it is not hidden itself. Nothing sets the two
148
+ apart today -- the transcript writes the hidden property and the host's
149
+ data-empty from one expression -- and that is exactly why: a rule holding
150
+ because of how a method in another file happens to be written is a rule
151
+ holding by luck. */
152
+ :host([placement="page"][data-empty]:not([data-greeting="off"]):not([data-restoring]):not([data-small-viewport="off"])) .empty:not([hidden]),
153
+ :host([placement="embedded"][data-greeting][data-empty]:not([data-greeting="off"]):not([data-restoring]):not([data-small-viewport="off"])) .empty:not([hidden]) {
154
+ margin: 0;
155
+ flex: 1;
156
+ display: flex;
157
+ flex-direction: column;
158
+ }
159
+
160
+ :host([placement="page"][data-empty]:not([data-greeting="off"]):not([data-restoring]):not([data-small-viewport="off"])) .greeting,
161
+ :host([placement="embedded"][data-greeting][data-empty]:not([data-greeting="off"]):not([data-restoring]):not([data-small-viewport="off"])) .greeting {
162
+ margin-block: auto;
163
+ }
164
+ }
165
+
166
+ /* Nor does the greeting paint while a restore is in flight. Hidden rather than
167
+ removed, so it keeps its place and nothing around it moves when it shows. */
168
+ :host([data-restoring]) .greeting {
169
+ visibility: hidden;
170
+ }
171
+ `;
@@ -0,0 +1,16 @@
1
+ import { TOOL_DISPLAY } from "../../constants.js";
2
+ import type { ToolDisplayMode } from "../progress/tool_call_card.js";
3
+
4
+ /**
5
+ * Whether a new tool call folds into a step group, given the element's
6
+ * `toolDisplay`.
7
+ *
8
+ * The display mode alone decides, whatever the theme: `grouped` (the default,
9
+ * and what an unknown value reads as) folds, and the four card modes keep
10
+ * per-call cards. Asked as each card is built, so switching to `grouped`
11
+ * folds only the calls drawn afterwards; switching away flattens the groups
12
+ * already drawn, which the shadow CSS does from the host attribute.
13
+ */
14
+ export function groupsToolSteps(mode: ToolDisplayMode): boolean {
15
+ return mode === TOOL_DISPLAY.GROUPED;
16
+ }
@@ -0,0 +1,155 @@
1
+ // The action row under a message: copy, retry, feedback and the rest.
2
+ // Guest: the whole coarse-pointer block near the end (the resize handle hidden,
3
+ // the 44px touch-target tokens on :host, the 16px composer font floor).
4
+ export const MESSAGE_ACTION_STYLES: string = `
5
+ The wrap is insurance rather than a fix: these buttons are glyph-only, so at
6
+ every width tested they fit on one line and removing the wrap changes
7
+ nothing. It is here because the confirmation row one release earlier did
8
+ overflow when it gained a third button, off the left edge and outside its own
9
+ card, and the difference between the two rows is only that this one's labels
10
+ are icons today. */
11
+ .message-actions {
12
+ display: flex;
13
+ flex-wrap: wrap;
14
+ gap: 4px;
15
+ /* Negative, and that is the point. The answer group is a flex column with its
16
+ own gap, so a positive margin here pushes the row further from the message
17
+ it acts on than the next card is below it -- the buttons then read as
18
+ belonging to whatever follows. Pulling back inside the gap is what makes
19
+ them the message's own. */
20
+ margin-top: -6px;
21
+ }
22
+
23
+ /* The row's controls are icon-only, so the box is the whole target. Sized from
24
+ a variable a host can raise, with a floor rather than a fixed height: the
25
+ compact density shrinks the font, and a target that shrinks with it lands
26
+ under the 24px minimum that makes a control reliably tappable. It used to,
27
+ at roughly 20px square. */
28
+ .message-action {
29
+ display: inline-flex;
30
+ align-items: center;
31
+ justify-content: center;
32
+ box-sizing: border-box;
33
+ min-width: var(--_action-size);
34
+ min-height: var(--_action-size);
35
+ padding: 4px;
36
+ border: none;
37
+ border-radius: 6px;
38
+ font: inherit;
39
+ line-height: 1.2;
40
+ cursor: pointer;
41
+ background: transparent;
42
+ color: var(--_muted);
43
+ opacity: 0.75;
44
+ /* The tooltip below is positioned against this box. */
45
+ position: relative;
46
+ }
47
+
48
+ .message-action:hover,
49
+ .message-action:focus-visible {
50
+ opacity: 1;
51
+ background: var(--_border);
52
+ }
53
+
54
+ .message-action-icon {
55
+ display: inline-flex;
56
+ width: var(--_action-icon-size);
57
+ height: var(--_action-icon-size);
58
+ }
59
+
60
+ .message-action-icon .glyph {
61
+ width: 100%;
62
+ height: 100%;
63
+ }
64
+
65
+ /* The label, drawn rather than left to the browser.
66
+
67
+ A title attribute is the usual answer and covers only half the readers: it
68
+ never appears on keyboard focus, so tabbing onto an icon-only control shows
69
+ nothing at all. The attribute stays for the pointer users who expect it, and
70
+ this shows the same words on hover and on focus alike.
71
+
72
+ Left-aligned rather than centred because the row sits at the left edge of an
73
+ answer inside a scrolling column, and a centred tooltip on the first control
74
+ is clipped by that column. Growing rightward keeps it inside.
75
+
76
+ Not exposed to assistive technology: the button already carries the same
77
+ string as its accessible name, and this would be a second copy of it. */
78
+ .message-action::after {
79
+ content: attr(data-tooltip);
80
+ position: absolute;
81
+ bottom: calc(100% + 4px);
82
+ left: 0;
83
+ z-index: 3;
84
+ padding: 3px 6px;
85
+ border-radius: 4px;
86
+ background: var(--_tooltip-bg);
87
+ color: var(--_tooltip-fg);
88
+ font-size: 11px;
89
+ line-height: 1.4;
90
+ white-space: nowrap;
91
+ pointer-events: none;
92
+ opacity: 0;
93
+ transition: opacity var(--_motion) var(--_ease);
94
+ }
95
+
96
+ .message-action:hover::after,
97
+ .message-action:focus-visible::after {
98
+ opacity: 1;
99
+ }
100
+
101
+ /* Touch has no hover to reveal it, and a tooltip that latches open under a
102
+ finger covers the answer it belongs to. */
103
+ @media (hover: none) {
104
+ .message-action::after {
105
+ content: none;
106
+ }
107
+ }
108
+
109
+ /* Touch. Separate from the width breakpoint in the small-viewport placement
110
+ rules on purpose: width decides the layout, the pointer decides which
111
+ controls make sense, and a touch laptop is coarse-pointered and wide while a
112
+ narrow desktop window is fine-pointered and small. */
113
+ @media (pointer: coarse) {
114
+ /* A 6px edge strip is not a control, it is a trap that eats a scroll. The
115
+ corners are 14px, still under the 24px floor a target is meant to clear,
116
+ and the panel has other ways to be resized on a device that has a pointer
117
+ precise enough to grab one. */
118
+ .resize-handle {
119
+ display: none;
120
+ }
121
+
122
+ /* Platform guidance is 44pt on iOS and 48dp on Android. These sit at 28-30px,
123
+ which clears the WCAG minimum and misses both. */
124
+ :host {
125
+ --_action-size: var(--ag-ui-action-size, 44px);
126
+ --_tool-btn-size: var(--ag-ui-tool-btn-size, 44px);
127
+ --_send-size: var(--ag-ui-send-size, 44px);
128
+ /* Missed the first time these were raised, which left the header -- the
129
+ widget's primary controls, and the only way to reach history, a new chat
130
+ or the collapse -- at half the size of everything beside it. */
131
+ --_header-btn-size: var(--ag-ui-header-btn-size, 44px);
132
+ --_header-gap: var(--ag-ui-header-gap, 6px);
133
+ }
134
+
135
+ /* iOS Safari zooms the page when a control under 16px takes focus, which
136
+ drags the whole fixed panel with it and leaves the user pinching back out
137
+ of a chat they only wanted to type into. The composer inherits the widget
138
+ font, which is 14px by default and 13px at compact density, so it has to
139
+ say 16 outright -- and only ever upward, so a host that has deliberately
140
+ set something larger keeps it. */
141
+ .input {
142
+ font-size: max(16px, var(--_font-size));
143
+ }
144
+ }
145
+
146
+ .message-action[aria-pressed="true"] {
147
+ opacity: 1;
148
+ color: var(--_accent);
149
+ }
150
+
151
+ .message-action--confirmed {
152
+ opacity: 1;
153
+ color: var(--_accent);
154
+ }
155
+ `;
@@ -0,0 +1,234 @@
1
+ import { ICON_COPY, ICON_THUMB_DOWN, ICON_THUMB_UP } from "../../constants.js";
2
+ import type { UiStrings } from "../ui_strings.js";
3
+
4
+ /** How long a button shows its confirmation before reverting. */
5
+ const CONFIRM_MS = 1500;
6
+
7
+ /** What an action bar can do, beyond copying. */
8
+ export interface MessageActionsOptions {
9
+ /** Localized strings. */
10
+ strings: UiStrings;
11
+ /**
12
+ * The text Copy puts on the clipboard. Absent means no copy button.
13
+ *
14
+ * A function rather than a string because a bubble's content is rewritten
15
+ * while it streams. Each button's option is also the statement that the
16
+ * button belongs, so no second flag can disagree with it.
17
+ */
18
+ text?: () => string;
19
+ /**
20
+ * The rich flavour to copy alongside `text`, as an HTML fragment. Absent
21
+ * means plain text only.
22
+ *
23
+ * It is what makes a copied table paste as a table: a spreadsheet or a chat
24
+ * client reads `text/html` when offered and falls back to the plain flavour.
25
+ */
26
+ html?: () => string;
27
+ /**
28
+ * Report a rating for this message. Absent means no feedback buttons.
29
+ *
30
+ * The component stores nothing: a rating is the host's to keep, and a
31
+ * write-only table nobody reads is not worth a schema.
32
+ */
33
+ onFeedback?: (rating: "up" | "down") => void;
34
+ }
35
+
36
+ /**
37
+ * Give one finished message bubble its row of actions.
38
+ *
39
+ * **Finished** is load-bearing. A streaming bubble reassigns its `innerHTML` on
40
+ * every delta, so anything attached mid-stream is discarded and rebuilt for
41
+ * each one -- the same constraint `attachCopyButtons` records, one level up.
42
+ *
43
+ * Retry is deliberately **not** here: it belongs to the last turn only, so the
44
+ * element owns it and moves it as the transcript grows. Everything on this bar
45
+ * is safe to offer on any message, however old.
46
+ *
47
+ * Idempotent -- a bubble already given a bar is skipped, so a re-render or a
48
+ * second call cannot stack rows.
49
+ *
50
+ * Passing neither `text` nor `onFeedback` builds an empty row; the element
51
+ * skips the call when a host has turned both off.
52
+ */
53
+ export function attachMessageActions(bubble: HTMLElement, options: MessageActionsOptions): void {
54
+ if (existingBar(bubble) !== null) {
55
+ return;
56
+ }
57
+ const bar = messageActionBar(bubble, options.strings);
58
+ const text = options.text;
59
+ if (text !== undefined) {
60
+ bar.appendChild(copyButton(options.strings, text, options.html));
61
+ }
62
+ if (options.onFeedback !== undefined) {
63
+ bar.append(
64
+ feedbackButton("up", options.strings.feedbackUp, options.onFeedback),
65
+ feedbackButton("down", options.strings.feedbackDown, options.onFeedback),
66
+ );
67
+ }
68
+ }
69
+
70
+ /**
71
+ * The empty action row on `bubble`, created if it has none yet.
72
+ *
73
+ * Shared so a bubble that wants *only* Retry -- a failed run, which has nothing
74
+ * worth copying and nothing to rate -- gets the same row, the same part name
75
+ * and the same accessible grouping as every other message, rather than a
76
+ * second thing that looks like one.
77
+ */
78
+ export function messageActionBar(bubble: HTMLElement, strings: UiStrings): HTMLElement {
79
+ const existing = existingBar(bubble);
80
+ if (existing !== null) {
81
+ return existing;
82
+ }
83
+ const bar = document.createElement("div");
84
+ bar.className = "message-actions";
85
+ bar.setAttribute("part", "message-actions");
86
+ // A group rather than a toolbar: these are independent actions on the message
87
+ // above, not a set the user arrows between.
88
+ bar.setAttribute("role", "group");
89
+ bar.setAttribute("aria-label", strings.messageActions);
90
+ // A **sibling**, never a child. Inside the bubble the buttons join its
91
+ // `textContent`, which is what Copy reads, what history persists and what
92
+ // every existing assertion about a message's text compares against -- so an
93
+ // answer would be copied back with the glyphs of the buttons that copied it.
94
+ // The bubble must therefore already be in the tree when this is called.
95
+ bubble.after(bar);
96
+ return bar;
97
+ }
98
+
99
+ /** The action row belonging to `bubble`, if it has one. */
100
+ function existingBar(bubble: HTMLElement): HTMLElement | null {
101
+ const next = bubble.nextElementSibling;
102
+ return next?.classList.contains("message-actions") === true ? (next as HTMLElement) : null;
103
+ }
104
+
105
+ /**
106
+ * Build one action button, labelled for screen readers rather than by glyph.
107
+ *
108
+ * `icon` is icon markup rather than a text glyph: the copy mark in particular
109
+ * has no font behind it on most systems.
110
+ *
111
+ * The label is carried three ways, and each has a reader the others miss:
112
+ * `aria-label` for assistive technology, `title` for the browser's own
113
+ * tooltip, and `data-tooltip` for the one this component draws. The last is
114
+ * not redundant with the second -- a `title` never appears on keyboard focus,
115
+ * so without it a keyboard user has no way to see what the control does.
116
+ *
117
+ * The icon sits in its own part, so a host can restyle or replace it. A slot
118
+ * would be the better channel and cannot be used here: these repeat once per
119
+ * message, and a named slot can only be filled once.
120
+ */
121
+ export function messageActionButton(
122
+ modifier: string,
123
+ label: string,
124
+ icon: string,
125
+ ): HTMLButtonElement {
126
+ const button = document.createElement("button");
127
+ button.type = "button";
128
+ button.className = `message-action message-action--${modifier}`;
129
+ button.setAttribute("part", `message-action message-action-${modifier}`);
130
+ setLabel(button, label);
131
+ const holder = document.createElement("span");
132
+ holder.className = "message-action-icon";
133
+ holder.setAttribute("part", `message-action-icon message-action-icon-${modifier}`);
134
+ holder.setAttribute("aria-hidden", "true");
135
+ // Author-written markup from constants, never message content.
136
+ holder.innerHTML = icon;
137
+ button.appendChild(holder);
138
+ return button;
139
+ }
140
+
141
+ /** Put `label` on every channel that names this button. */
142
+ function setLabel(button: HTMLButtonElement, label: string): void {
143
+ button.title = label;
144
+ button.setAttribute("aria-label", label);
145
+ button.dataset["tooltip"] = label;
146
+ }
147
+
148
+ function copyButton(
149
+ strings: UiStrings,
150
+ text: () => string,
151
+ html: (() => string) | undefined,
152
+ ): HTMLButtonElement {
153
+ const button = messageActionButton("copy", strings.copyMessage, ICON_COPY);
154
+ button.addEventListener("click", () => {
155
+ void write(text(), html?.()).then((ok) => {
156
+ // A denied clipboard permission is the common case, not an exception:
157
+ // say so on the button rather than throwing into an unhandled rejection.
158
+ flash(button, ok ? strings.copied : strings.copyFailed, strings.copyMessage);
159
+ });
160
+ });
161
+ return button;
162
+ }
163
+
164
+ /**
165
+ * Put the message on the clipboard, richest flavour first.
166
+ *
167
+ * Writing both flavours needs `ClipboardItem`, which not every engine that has
168
+ * `writeText` also has -- and even where the constructor exists the write can
169
+ * be refused. Neither is a failure worth reporting as one while the plain text
170
+ * would still have landed, so both fall through to `writeText` and only that
171
+ * decides what the button says.
172
+ */
173
+ async function write(text: string, html: string | undefined): Promise<boolean> {
174
+ const clipboard = navigator.clipboard;
175
+ if (clipboard === undefined) {
176
+ return false;
177
+ }
178
+ if (html !== undefined && typeof ClipboardItem === "function") {
179
+ try {
180
+ await clipboard.write([
181
+ new ClipboardItem({
182
+ "text/plain": new Blob([text], { type: "text/plain" }),
183
+ "text/html": new Blob([html], { type: "text/html" }),
184
+ }),
185
+ ]);
186
+ return true;
187
+ } catch {
188
+ // Fall through to the plain flavour.
189
+ }
190
+ }
191
+ try {
192
+ await clipboard.writeText(text);
193
+ return true;
194
+ } catch {
195
+ return false;
196
+ }
197
+ }
198
+
199
+ function feedbackButton(
200
+ rating: "up" | "down",
201
+ label: string,
202
+ report: (rating: "up" | "down") => void,
203
+ ): HTMLButtonElement {
204
+ const button = messageActionButton(
205
+ rating,
206
+ label,
207
+ rating === "up" ? ICON_THUMB_UP : ICON_THUMB_DOWN,
208
+ );
209
+ button.addEventListener("click", () => {
210
+ // Pressed rather than removed: the rating is a standing statement about the
211
+ // message, and a button that vanishes leaves no record of what was said.
212
+ const pressed = button.getAttribute("aria-pressed") === "true";
213
+ button.setAttribute("aria-pressed", pressed ? "false" : "true");
214
+ report(rating);
215
+ });
216
+ button.setAttribute("aria-pressed", "false");
217
+ return button;
218
+ }
219
+
220
+ /**
221
+ * Flash `message` on the button, then restore `label`.
222
+ *
223
+ * The label to restore is passed rather than read back off the element: the
224
+ * caller is the one that set it, and reading it would introduce a null arm that
225
+ * cannot happen and cannot be covered.
226
+ */
227
+ function flash(button: HTMLButtonElement, message: string, label: string): void {
228
+ setLabel(button, message);
229
+ button.classList.add("message-action--confirmed");
230
+ setTimeout(() => {
231
+ setLabel(button, label);
232
+ button.classList.remove("message-action--confirmed");
233
+ }, CONFIRM_MS);
234
+ }