@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,72 @@
1
+ /**
2
+ * The built-in `render_chart` tool: the agent-called route to a chart.
3
+ *
4
+ * A thin thing on purpose. It carries no `handler` of its own beyond reporting
5
+ * back to the model, because everything it does is drawing — which lives in
6
+ * `render`, the half the component replays. A consumer wanting charts gets this
7
+ * without writing a renderer; a consumer wanting something else writes their own
8
+ * tool against the same seam.
9
+ */
10
+
11
+ import type { ClientTool } from "../../tools/client_tool_registry.js";
12
+ import { renderChart } from "./chart_block.js";
13
+ import { chartSpecFrom } from "./chart_spec_from.js";
14
+
15
+ /** The name the built-in chart tool registers under. */
16
+ export const CHART_TOOL_NAME = "render_chart";
17
+
18
+ function draw(args: Record<string, unknown>): HTMLDivElement | null {
19
+ const spec = chartSpecFrom(args);
20
+ return spec === null ? null : renderChart(spec);
21
+ }
22
+
23
+ /** Whether these arguments would produce a chart, without producing one. */
24
+ function drawable(args: Record<string, unknown>): boolean {
25
+ const spec = chartSpecFrom(args);
26
+ return spec !== null && spec.labels.length > 0 && spec.series.length > 0;
27
+ }
28
+
29
+ const REJECTED =
30
+ "chart not rendered: expected labels (strings) and series, each with one finite number per label";
31
+
32
+ /** The built-in chart tool. */
33
+ export function createChartTool(): ClientTool {
34
+ return {
35
+ name: CHART_TOOL_NAME,
36
+ description:
37
+ "Show a chart in the conversation. Supply the data and the page draws it. " +
38
+ "Every series must have exactly one point per label.",
39
+ parameters: {
40
+ type: "object",
41
+ properties: {
42
+ kind: { type: "string", enum: ["bar", "line", "pie", "scatter", "stacked"] },
43
+ title: { type: "string" },
44
+ labels: { type: "array", items: { type: "string" } },
45
+ series: {
46
+ type: "array",
47
+ items: {
48
+ type: "object",
49
+ properties: {
50
+ label: { type: "string" },
51
+ points: { type: "array", items: { type: "number" } },
52
+ },
53
+ required: ["points"],
54
+ },
55
+ },
56
+ },
57
+ required: ["labels", "series"],
58
+ "x-summary": "Draw a chart",
59
+ },
60
+ // Says what happened and nothing else; the drawing is `render`'s job. Told
61
+ // plainly when the arguments are unusable, because the model can fix that
62
+ // and retry — a silent no-op would leave it believing the chart is on screen.
63
+ // Answers on what will actually be drawn, not on what validated: a spec can
64
+ // pass validation and still have nothing to show, and reporting success
65
+ // then would leave the model believing a chart is on screen. Asks the
66
+ // question without building the chart, because `render` is about to build
67
+ // the same one a moment later and drawing it twice is pure waste on a spec
68
+ // large enough to matter.
69
+ handler: (args: Record<string, unknown>) => (drawable(args) ? "chart rendered" : REJECTED),
70
+ render: draw,
71
+ };
72
+ }
@@ -0,0 +1,71 @@
1
+ // The composer's attachment picker, voice button and attachment tray.
2
+ export const ATTACHMENT_STYLES: string = `
3
+ /* ── File attachments ───────────────────────────────────────────────────── */
4
+ /* The picker button sits in the composer's tool row; hidden until
5
+ data-attachments-url. */
6
+ .attach-input {
7
+ display: none;
8
+ }
9
+
10
+ /* The mic button's mount point; filled only once ComposerVoice.wire mounts
11
+ the control, which it skips unless transcription is configured. */
12
+ .voice-slot {
13
+ display: contents;
14
+ }
15
+
16
+ /* Recording: a red tint + a gentle pulse so it's clearly "live". */
17
+ .voice-btn[data-state="recording"] {
18
+ background: var(--_danger);
19
+ color: var(--_on-danger);
20
+ animation: ag-ui-voice-pulse 1.2s ease-in-out infinite;
21
+ }
22
+
23
+ .voice-btn[data-state="recording"]:hover {
24
+ background: var(--_danger);
25
+ color: var(--_on-danger);
26
+ }
27
+
28
+ @keyframes ag-ui-voice-pulse {
29
+ 0%, 100% { opacity: 1; }
30
+ 50% { opacity: 0.6; }
31
+ }
32
+
33
+ @media (prefers-reduced-motion: reduce) {
34
+ .voice-btn[data-state="recording"] {
35
+ animation: none;
36
+ }
37
+ }
38
+
39
+ /* Pending-attachments tray, above the input row; collapses (hidden) when empty. */
40
+ .attachment-slot {
41
+ display: contents;
42
+ }
43
+
44
+ /* The padding is the only separation the tray gets: its slot is display:
45
+ contents, so the tray is a direct child of the .chat column, and that column
46
+ sets no gap. The bottom value keeps a chip off the composer's top edge.
47
+ The inline value here is only the default: the page placement overrides
48
+ padding-inline further down to compute its reading-column gutter, and wins
49
+ on specificity whichever way this declaration is written. Read the two
50
+ together before changing either. */
51
+ .attachment-tray {
52
+ display: flex;
53
+ flex-wrap: wrap;
54
+ gap: 6px;
55
+ padding: 8px 12px;
56
+ }
57
+
58
+ /* The tray sets the hidden property while empty, and an author display beats
59
+ the UA stylesheet's rule for it, so without this the empty tray keeps
60
+ laying out and its padding is permanent dead space above the composer. */
61
+ .attachment-tray[hidden] {
62
+ display: none;
63
+ }
64
+
65
+ .attachment-chips {
66
+ display: flex;
67
+ flex-wrap: wrap;
68
+ gap: 6px;
69
+ margin-top: 6px;
70
+ }
71
+ `;
@@ -0,0 +1,295 @@
1
+ import { randomUUID } from "@ag-ui/client";
2
+ import { ATTACHMENT_STATUS } from "../../constants.js";
3
+ import type { AttachmentRef } from "../../core/attachment.js";
4
+ import type { UploadHandler } from "../../core/upload_attachment.js";
5
+ import { commaTokens } from "../../core/utils.js";
6
+ import { fillUiString } from "../fill_ui_string.js";
7
+ import { formatBytes, iconFor } from "../transcript/attachment_chips.js";
8
+ import { DEFAULT_UI_STRINGS, type UiStrings } from "../ui_strings.js";
9
+
10
+ /** Status of a pending tray chip. */
11
+ type AttachmentStatus = (typeof ATTACHMENT_STATUS)[keyof typeof ATTACHMENT_STATUS];
12
+
13
+ /** Config the host ({@link AgUiChat}) hands the tray. */
14
+ export interface AttachmentTrayConfig {
15
+ /** Upload one file, reporting `0..1` progress; resolves to a durable ref. */
16
+ readonly upload: UploadHandler;
17
+ /** Client-side size cap in bytes (`0` = no cap). The server stays authoritative. */
18
+ readonly maxBytes: number;
19
+ /** Client-side accept list (`<input accept>` syntax; `""` = any). */
20
+ readonly accept: string;
21
+ /** Fired when the set of attachments changes (add / settle / remove). */
22
+ readonly onChange?: () => void;
23
+ /** Localized strings; defaults to the English {@link DEFAULT_UI_STRINGS}. */
24
+ readonly strings?: UiStrings;
25
+ }
26
+
27
+ /** One pending file in the tray, from pick to ready/error. */
28
+ interface TrayItem {
29
+ readonly localId: string;
30
+ readonly file: File;
31
+ status: AttachmentStatus;
32
+ progress: number;
33
+ ref: AttachmentRef | null;
34
+ error: string;
35
+ /** Aborts the in-flight upload when the chip is removed / the tray cleared. */
36
+ controller: AbortController | null;
37
+ }
38
+
39
+ /**
40
+ * The composer's pending-attachments tray: a chip per picked file with a
41
+ * progress bar while it uploads, settling to a ready chip holding the durable
42
+ * ref or an error chip with retry. A stateful view like {@link ThreadDrawer}:
43
+ * the host appends {@link element}, calls {@link add} on pick or drop, reads
44
+ * {@link readyRefs} on send, and clears it.
45
+ *
46
+ * Client-side size and type guards reject a bad file into an error chip without
47
+ * uploading, for instant feedback, but the server stays the authority.
48
+ */
49
+ export class AttachmentTray {
50
+ /** The tray root; append above the input row. Hidden while empty. */
51
+ readonly element: HTMLDivElement;
52
+
53
+ readonly #config: AttachmentTrayConfig;
54
+ readonly #strings: UiStrings;
55
+ #items: TrayItem[] = [];
56
+
57
+ constructor(config: AttachmentTrayConfig) {
58
+ this.#config = config;
59
+ this.#strings = config.strings ?? DEFAULT_UI_STRINGS;
60
+ this.element = document.createElement("div");
61
+ this.element.className = "attachment-tray";
62
+ this.element.setAttribute("part", "attachment-tray");
63
+ this.element.hidden = true;
64
+ }
65
+
66
+ /** Queue a file: reject oversize/disallowed into an error chip, else upload. */
67
+ add(file: File): void {
68
+ const item: TrayItem = {
69
+ localId: randomUUID(),
70
+ file,
71
+ status: ATTACHMENT_STATUS.UPLOADING,
72
+ progress: 0,
73
+ ref: null,
74
+ error: "",
75
+ controller: null,
76
+ };
77
+ this.#items.push(item);
78
+ const rejection = this.#reject(file);
79
+ if (rejection !== null) {
80
+ item.status = ATTACHMENT_STATUS.ERROR;
81
+ item.error = rejection;
82
+ this.#render();
83
+ this.#config.onChange?.();
84
+ return;
85
+ }
86
+ this.#render();
87
+ this.#config.onChange?.();
88
+ this.#upload(item);
89
+ }
90
+
91
+ /** The durable refs of every chip that finished uploading. */
92
+ readyRefs(): readonly AttachmentRef[] {
93
+ const refs: AttachmentRef[] = [];
94
+ for (const item of this.#items) {
95
+ if (item.ref !== null) {
96
+ refs.push(item.ref);
97
+ }
98
+ }
99
+ return refs;
100
+ }
101
+
102
+ /** Whether any chip is still uploading (a send would drop nothing if false). */
103
+ hasPending(): boolean {
104
+ return this.#items.some((item) => item.status === ATTACHMENT_STATUS.UPLOADING);
105
+ }
106
+
107
+ /** How many chips are still uploading — the count a send-time notice names. */
108
+ pendingCount(): number {
109
+ return this.#items.filter((item) => item.status === ATTACHMENT_STATUS.UPLOADING).length;
110
+ }
111
+
112
+ /** Whether the tray holds no chips. */
113
+ isEmpty(): boolean {
114
+ return this.#items.length === 0;
115
+ }
116
+
117
+ /** Drop the settled (ready / error) chips, leaving any still uploading. */
118
+ clearReady(): void {
119
+ this.#items = this.#items.filter((item) => item.status === ATTACHMENT_STATUS.UPLOADING);
120
+ this.#render();
121
+ }
122
+
123
+ /** Drop every chip (a reset / new-chat), aborting any in-flight upload. */
124
+ clear(): void {
125
+ for (const item of this.#items) {
126
+ item.controller?.abort();
127
+ }
128
+ this.#items = [];
129
+ this.#render();
130
+ }
131
+
132
+ /**
133
+ * Abort every in-flight upload without touching the rendered chips — the
134
+ * teardown path when the host element is removed mid-upload, so a cancelled
135
+ * transfer doesn't orphan a server-side file.
136
+ */
137
+ dispose(): void {
138
+ for (const item of this.#items) {
139
+ item.controller?.abort();
140
+ }
141
+ }
142
+
143
+ /** The size/type rejection reason for a file, or `null` when accepted. */
144
+ #reject(file: File): string | null {
145
+ if (this.#config.maxBytes > 0 && file.size > this.#config.maxBytes) {
146
+ return fillUiString(this.#strings.tooLarge, { size: formatBytes(this.#config.maxBytes) });
147
+ }
148
+ if (!accepts(this.#config.accept, file)) {
149
+ return this.#strings.fileTypeNotAllowed;
150
+ }
151
+ return null;
152
+ }
153
+
154
+ #upload(item: TrayItem): void {
155
+ // Re-apply the client guard on every attempt, not just the first `add` — an
156
+ // ERROR chip always renders retry, so without this a size/type-rejected file
157
+ // would upload in full on ↻.
158
+ const rejection = this.#reject(item.file);
159
+ if (rejection !== null) {
160
+ item.status = ATTACHMENT_STATUS.ERROR;
161
+ item.error = rejection;
162
+ this.#render();
163
+ this.#config.onChange?.();
164
+ return;
165
+ }
166
+ item.status = ATTACHMENT_STATUS.UPLOADING;
167
+ item.progress = 0;
168
+ item.error = "";
169
+ const controller = new AbortController();
170
+ item.controller = controller;
171
+ this.#render();
172
+ this.#config
173
+ .upload(
174
+ item.file,
175
+ (fraction) => {
176
+ item.progress = fraction;
177
+ this.#render();
178
+ },
179
+ controller.signal,
180
+ )
181
+ .then((ref) => {
182
+ item.status = ATTACHMENT_STATUS.READY;
183
+ item.ref = ref;
184
+ })
185
+ .catch((error: unknown) => {
186
+ item.status = ATTACHMENT_STATUS.ERROR;
187
+ item.error = error instanceof Error ? error.message : this.#strings.uploadFailed;
188
+ })
189
+ .finally(() => {
190
+ item.controller = null;
191
+ this.#render();
192
+ this.#config.onChange?.();
193
+ });
194
+ }
195
+
196
+ #remove(item: TrayItem): void {
197
+ // Abort an in-flight upload so removing its chip doesn't orphan the file.
198
+ item.controller?.abort();
199
+ this.#items = this.#items.filter((other) => other !== item);
200
+ this.#render();
201
+ this.#config.onChange?.();
202
+ }
203
+
204
+ #render(): void {
205
+ this.element.replaceChildren();
206
+ this.element.hidden = this.#items.length === 0;
207
+ for (const item of this.#items) {
208
+ this.element.appendChild(this.#renderChip(item));
209
+ }
210
+ }
211
+
212
+ #renderChip(item: TrayItem): HTMLDivElement {
213
+ const chip = document.createElement("div");
214
+ chip.className = `attachment-chip attachment-chip--${item.status}`;
215
+ chip.setAttribute("part", "attachment-chip");
216
+
217
+ const icon = document.createElement("span");
218
+ icon.className = "attachment-chip-icon";
219
+ icon.setAttribute("part", "attachment-chip-icon");
220
+ // Author-written glyph markup, selected by MIME family — see iconFor.
221
+ icon.innerHTML = iconFor(item.file.type);
222
+ icon.setAttribute("aria-hidden", "true");
223
+
224
+ const name = document.createElement("span");
225
+ name.className = "attachment-chip-name";
226
+ name.setAttribute("part", "attachment-chip-name");
227
+ name.textContent = item.file.name;
228
+ name.title = item.file.name;
229
+
230
+ const meta = document.createElement("span");
231
+ meta.className = "attachment-chip-size";
232
+ meta.setAttribute("part", "attachment-chip-size");
233
+ meta.textContent =
234
+ item.status === ATTACHMENT_STATUS.ERROR ? item.error : formatBytes(item.file.size);
235
+
236
+ chip.append(icon, name, meta);
237
+
238
+ if (item.status === ATTACHMENT_STATUS.UPLOADING) {
239
+ const bar = document.createElement("div");
240
+ bar.className = "attachment-chip-bar";
241
+ bar.setAttribute("part", "attachment-chip-bar");
242
+ const fill = document.createElement("div");
243
+ fill.className = "attachment-chip-bar-fill";
244
+ fill.setAttribute("part", "attachment-chip-bar-fill");
245
+ fill.style.width = `${Math.round(item.progress * 100)}%`;
246
+ bar.appendChild(fill);
247
+ chip.appendChild(bar);
248
+ }
249
+
250
+ if (item.status === ATTACHMENT_STATUS.ERROR) {
251
+ const retry = document.createElement("button");
252
+ retry.type = "button";
253
+ retry.className = "attachment-chip-retry";
254
+ retry.setAttribute("part", "attachment-chip-retry");
255
+ retry.title = this.#strings.retry;
256
+ retry.setAttribute("aria-label", this.#strings.retryUpload);
257
+ retry.textContent = "↻";
258
+ retry.addEventListener("click", () => this.#upload(item));
259
+ chip.appendChild(retry);
260
+ }
261
+
262
+ const remove = document.createElement("button");
263
+ remove.type = "button";
264
+ remove.className = "attachment-chip-remove";
265
+ remove.setAttribute("part", "attachment-chip-remove");
266
+ remove.title = this.#strings.remove;
267
+ remove.setAttribute("aria-label", this.#strings.removeAttachment);
268
+ remove.textContent = "✕";
269
+ remove.addEventListener("click", () => this.#remove(item));
270
+ chip.appendChild(remove);
271
+
272
+ return chip;
273
+ }
274
+ }
275
+
276
+ /** Whether `file` matches an `<input accept>` list (`""` accepts anything). */
277
+ function accepts(accept: string, file: File): boolean {
278
+ // Lower-cased after the shared split rather than before the filter: no
279
+ // non-empty token lower-cases to an empty one, so the order cannot matter.
280
+ const tokens = commaTokens(accept).map((token) => token.toLowerCase());
281
+ if (tokens.length === 0) {
282
+ return true;
283
+ }
284
+ const mime = file.type.toLowerCase();
285
+ const name = file.name.toLowerCase();
286
+ return tokens.some((token) => {
287
+ if (token.startsWith(".")) {
288
+ return name.endsWith(token);
289
+ }
290
+ if (token.endsWith("/*")) {
291
+ return mime.startsWith(token.slice(0, -1));
292
+ }
293
+ return mime === token;
294
+ });
295
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Size the field to its content: one row when empty, growing with what is
3
+ * typed until the CSS ceiling takes over and it scrolls.
4
+ *
5
+ * Resetting to `auto` first is what makes it shrink again — `scrollHeight`
6
+ * never reports less than the current height, so measuring without the reset
7
+ * would ratchet the composer taller and never back down.
8
+ */
9
+ export function autoGrow(input: HTMLTextAreaElement): void {
10
+ input.style.height = "auto";
11
+ input.style.height = `${input.scrollHeight}px`;
12
+ }
@@ -0,0 +1,114 @@
1
+ import { ICON_ATTACH, ICON_SEND, ICON_STOP } from "../../constants.js";
2
+ import { glyphSlot } from "../shell/glyph_slot.js";
3
+ import type { UiStrings } from "../ui_strings.js";
4
+
5
+ /** The composer's parts, owned by the element, and what they call back into. */
6
+ export interface ComposerOptions {
7
+ readonly input: HTMLTextAreaElement;
8
+ readonly send: HTMLButtonElement;
9
+ readonly attachButton: HTMLButtonElement;
10
+ readonly fileInput: HTMLInputElement;
11
+ readonly voiceSlot: HTMLElement;
12
+ /** The place chip; sits in the tool row between the voice slot and Send. */
13
+ readonly place: HTMLElement;
14
+ /** The line saying what the composer still needs; sits above the input. */
15
+ readonly hint: HTMLElement;
16
+ /** The queued-message row; sits above the input beside the tray. */
17
+ readonly queuedRow: HTMLElement;
18
+ /** Where the attachment tray mounts; sits above the input. */
19
+ readonly attachSlot: HTMLElement;
20
+ readonly strings: UiStrings;
21
+ readonly signal: AbortSignal;
22
+ readonly onKeydown: (event: KeyboardEvent) => void;
23
+ readonly onInput: () => void;
24
+ /** Send while idle, Stop while a run is in flight: the element decides. */
25
+ readonly onSend: () => void;
26
+ readonly onFilesPicked: () => void;
27
+ }
28
+
29
+ /**
30
+ * Build the composer row -- the field, and the tool row under it with the
31
+ * attach and voice controls, the place chip and Send -- and ready the composer surfaces the
32
+ * element mounts above it: the hint, the queued row and the attachment slot.
33
+ * Returns the row; the element places it and the surfaces.
34
+ */
35
+ export function buildComposer(options: ComposerOptions): HTMLElement {
36
+ const { input, send, attachButton, fileInput, strings, signal } = options;
37
+
38
+ const queued = options.queuedRow;
39
+ queued.className = "queued";
40
+ queued.setAttribute("part", "queued");
41
+ queued.setAttribute("role", "group");
42
+ queued.setAttribute("aria-label", strings.queued);
43
+ queued.hidden = true;
44
+
45
+ const inputRow = document.createElement("div");
46
+ inputRow.className = "input-row";
47
+ inputRow.setAttribute("part", "composer");
48
+
49
+ // One bordered surface holds the field and the tool row under it, so the
50
+ // icon buttons stop competing with the field for weight.
51
+ const composer = document.createElement("div");
52
+ composer.className = "composer";
53
+ composer.setAttribute("part", "composer-surface");
54
+
55
+ const tools = document.createElement("div");
56
+ tools.className = "composer-tools";
57
+ tools.setAttribute("part", "composer-tools");
58
+
59
+ input.className = "input";
60
+ input.setAttribute("part", "input");
61
+ input.setAttribute("aria-label", strings.message);
62
+ input.rows = 1;
63
+ input.placeholder = strings.inputPlaceholder;
64
+ input.addEventListener("keydown", options.onKeydown, { signal });
65
+ input.addEventListener("input", options.onInput, { signal });
66
+
67
+ // Icon-only, with both glyphs mounted at once and CSS showing the one the
68
+ // state calls for — swapping a single glyph would leave a host that slotted
69
+ // its own Send mark holding a stop icon mid-run.
70
+ send.className = "send";
71
+ send.type = "button";
72
+ send.setAttribute("part", "send");
73
+ send.replaceChildren(
74
+ glyphSlot("icon-send", "send-send", ICON_SEND),
75
+ glyphSlot("icon-stop", "send-stop", ICON_STOP),
76
+ );
77
+ send.title = strings.send;
78
+ send.setAttribute("aria-label", strings.send);
79
+ send.dataset["state"] = "idle";
80
+ send.addEventListener("click", options.onSend, { signal });
81
+
82
+ const hint = options.hint;
83
+ hint.className = "skill-hint";
84
+ hint.setAttribute("part", "skill-hint");
85
+ hint.hidden = true;
86
+
87
+ // File-upload affordance: a paperclip button (hidden until
88
+ // `data-attachments-url` is wired) opening a hidden multi-file input.
89
+ // Drag-and-drop covers the whole shell (wired by ComposerAttachments).
90
+ attachButton.className = "attach-btn";
91
+ attachButton.type = "button";
92
+ attachButton.setAttribute("part", "attach-button");
93
+ attachButton.replaceChildren(glyphSlot("icon-attach", "attach-glyph", ICON_ATTACH));
94
+ attachButton.title = strings.attachFiles;
95
+ attachButton.setAttribute("aria-label", strings.attachFiles);
96
+ attachButton.hidden = true;
97
+ attachButton.addEventListener("click", () => fileInput.click(), { signal });
98
+
99
+ fileInput.className = "attach-input";
100
+ fileInput.type = "file";
101
+ fileInput.multiple = true;
102
+ fileInput.hidden = true;
103
+ fileInput.addEventListener("change", options.onFilesPicked, { signal });
104
+
105
+ options.attachSlot.className = "attachment-slot";
106
+
107
+ // Mic button mount point (kept empty until ComposerVoice mounts the control).
108
+ options.voiceSlot.className = "voice-slot";
109
+
110
+ tools.append(attachButton, options.voiceSlot, options.place, send);
111
+ composer.append(input, tools);
112
+ inputRow.append(composer, fileInput);
113
+ return inputRow;
114
+ }