@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,345 @@
1
+ /**
2
+ * Reading a text selection out of the shadow tree, and shaping it for the
3
+ * composer.
4
+ *
5
+ * Selection is the one DOM API shadow encapsulation genuinely broke, and it
6
+ * broke it in two different directions. WebKit rescopes a selection made inside
7
+ * a shadow tree to the **host** element, so `document.getSelection()` reports
8
+ * the whole widget and none of the words; Chromium exposes the shadow nodes
9
+ * directly, so the same call reports exactly the words. `getComposedRanges` is
10
+ * the settled answer to both -- it hands back real endpoints for each shadow
11
+ * root it is *given permission to see* -- but it is recent enough that the
12
+ * direct read has to stay behind it.
13
+ */
14
+
15
+ /**
16
+ * The longest quotation put into the composer, in characters.
17
+ *
18
+ * A cap rather than no cap because the point of a quotation is to say *which*
19
+ * part of an answer the next question is about. Select-all-then-quote is a
20
+ * gesture the transcript already answers -- it is the whole conversation, which
21
+ * the model has -- and pasting it back costs the user tokens to say nothing.
22
+ */
23
+ export const MAX_QUOTE_CHARS = 500;
24
+
25
+ /** A selection worth offering to quote. */
26
+ export interface QuotableSelection {
27
+ /** The selected text, trimmed. Never empty. */
28
+ readonly text: string;
29
+ /**
30
+ * One **line** of the selection, for placing the affordance beside it.
31
+ *
32
+ * Deliberately not the selection's bounding box. See {@link lineToHangFrom}:
33
+ * the union of a selection spanning several elements has a centre with no
34
+ * selected text anywhere near it.
35
+ */
36
+ readonly rect: DOMRect;
37
+ }
38
+
39
+ /** Where a gesture ended, in viewport coordinates. */
40
+ export interface Point {
41
+ readonly x: number;
42
+ readonly y: number;
43
+ }
44
+
45
+ /** A `Selection` on an engine new enough to reach into a shadow tree. */
46
+ type ComposedSelection = Selection & {
47
+ getComposedRanges?: (...args: readonly unknown[]) => readonly AbstractRange[];
48
+ };
49
+
50
+ /**
51
+ * The current selection, when it lies wholly inside `container`.
52
+ *
53
+ * `roots` are the shadow roots the read is allowed to look inside, in the shape
54
+ * `getComposedRanges` itself takes. Pass the one holding `container` for a
55
+ * selection made in a shadow tree, or nothing at all for one made in the page.
56
+ *
57
+ * `near` is where the gesture ended, when a pointer made it -- it decides which
58
+ * line of a multi-line selection the offer is hung from.
59
+ *
60
+ * `null` for no selection, a collapsed one, whitespace only, or one that
61
+ * starts or ends outside `container` -- a drag that ran off the transcript and
62
+ * into the page is not a quotation from the transcript.
63
+ */
64
+ export function quotableSelection(
65
+ container: HTMLElement,
66
+ roots: readonly ShadowRoot[] = [],
67
+ near?: Point,
68
+ ): QuotableSelection | null {
69
+ for (const endpoints of endpointCandidates(roots)) {
70
+ if (!container.contains(endpoints.startContainer)) {
71
+ continue;
72
+ }
73
+ if (!container.contains(endpoints.endContainer)) {
74
+ continue;
75
+ }
76
+ // A live `Range` regardless of what the engine handed back: `getComposedRanges`
77
+ // returns `StaticRange`s, which carry endpoints and nothing else -- no text,
78
+ // no geometry. Both are what this is for.
79
+ const range = document.createRange();
80
+ range.setStart(endpoints.startContainer, endpoints.startOffset);
81
+ range.setEnd(endpoints.endContainer, endpoints.endOffset);
82
+ const text = renderedText(range).trim();
83
+ if (text === "") {
84
+ continue;
85
+ }
86
+ return { text, rect: lineToHangFrom(range, near) };
87
+ }
88
+ return null;
89
+ }
90
+
91
+ /**
92
+ * Wrap `text` as a markdown blockquote, ready to be followed by a question.
93
+ *
94
+ * Markdown rather than a bespoke fence because the transcript renders markdown
95
+ * and the server reads markdown: a quotation that survives both ends without a
96
+ * convention to agree on first. The trailing blank line is what leaves the
97
+ * caret on a fresh paragraph, which is the whole point of quoting into a
98
+ * composer rather than sending straight away.
99
+ */
100
+ export function asQuote(text: string): string {
101
+ const lines = tidy(text);
102
+ if (lines.length === 0) {
103
+ return "";
104
+ }
105
+ const capped = cap(lines.join("\n"));
106
+ const quoted = capped
107
+ .split("\n")
108
+ // `trimEnd` so a blank line inside the selection becomes a bare ">" rather
109
+ // than "> " -- trailing whitespace markdown treats as a line break.
110
+ .map((line) => `> ${line}`.trimEnd())
111
+ .join("\n");
112
+ return `${quoted}\n\n`;
113
+ }
114
+
115
+ /**
116
+ * The selection's lines, with the *markup's* whitespace taken back out.
117
+ *
118
+ * A selection crossing block elements carries the source's own layout with it:
119
+ * every newline and every run of indentation between one element and the next
120
+ * is a text node like any other. Quoting a form as marked up produced twenty-
121
+ * four lines of which twelve were a bare ">", the rest indented by wherever
122
+ * they happened to sit in the HTML. That is not a quotation of anything.
123
+ *
124
+ * Two rules, and deliberately only two. Runs of blank lines collapse to one,
125
+ * because the gap between two blocks is one gap however it was written. And the
126
+ * indentation every line shares is removed, not each line's own -- a quotation
127
+ * from a code block keeps its shape, which trimming each line would flatten.
128
+ */
129
+ function tidy(text: string): readonly string[] {
130
+ const lines = text.split(/\r\n?|\n/).map((line) => line.trimEnd());
131
+ const indents = lines.filter((line) => line !== "").map(indentOf);
132
+ const shared = indents.length === 0 ? 0 : Math.min(...indents);
133
+ const kept: string[] = [];
134
+ for (const line of lines) {
135
+ const dedented = line.slice(shared);
136
+ // No leading blank lines, and never two in a row.
137
+ if (dedented === "" && (kept.length === 0 || kept[kept.length - 1] === "")) {
138
+ continue;
139
+ }
140
+ kept.push(dedented);
141
+ }
142
+ while (kept[kept.length - 1] === "") {
143
+ kept.pop();
144
+ }
145
+ return kept;
146
+ }
147
+
148
+ /** How many spaces of indentation `line` opens with. */
149
+ function indentOf(line: string): number {
150
+ return line.length - line.trimStart().length;
151
+ }
152
+
153
+ /** `text`, cut to {@link MAX_QUOTE_CHARS} if it runs past it. */
154
+ function cap(text: string): string {
155
+ return text.length > MAX_QUOTE_CHARS ? `${text.slice(0, MAX_QUOTE_CHARS).trimEnd()}...` : text;
156
+ }
157
+
158
+ /**
159
+ * The selected text **as rendered**, which is not what `Range.toString()` says.
160
+ *
161
+ * `toString()` concatenates the text nodes in the range and asks no questions
162
+ * about CSS, so a drag across an ordinary form quotes back the values of every
163
+ * `<option>` in a closed `<select>` -- words the user has never seen, presented
164
+ * to the model as something they pointed at. `checkVisibility()` is the
165
+ * platform's own answer to "is this actually rendered", and it reports exactly
166
+ * those options as hidden.
167
+ *
168
+ * Older engines without it keep the previous behaviour rather than a guess:
169
+ * quoting a few invisible words is a smaller failure than dropping visible ones
170
+ * because a hand-rolled visibility test was wrong.
171
+ */
172
+ function renderedText(range: Range): string {
173
+ let text = "";
174
+ for (const node of textNodesIn(range)) {
175
+ // The element carries the styles; the text node has none of its own.
176
+ const parent = node.parentElement as HTMLElement;
177
+ if (!isRendered(parent)) {
178
+ continue;
179
+ }
180
+ // The end nodes are only partly inside the range; everything between them
181
+ // is wholly inside it.
182
+ const from = node === range.startContainer ? range.startOffset : 0;
183
+ const to = node === range.endContainer ? range.endOffset : node.data.length;
184
+ text += collapse(node.data.slice(from, to), parent);
185
+ }
186
+ return text;
187
+ }
188
+
189
+ /**
190
+ * Squeeze the runs of spaces the renderer squeezes, and keep the ones it keeps.
191
+ *
192
+ * Indentation between block elements is markup, not content: it is in the DOM
193
+ * as text nodes and it is on screen as nothing at all, because a collapsing
194
+ * `white-space` reduces it. Carrying it into a quotation is not merely untidy --
195
+ * four leading spaces inside a blockquote is a markdown **code block**, so a
196
+ * form quoted as marked up renders as source listing.
197
+ *
198
+ * Newlines survive on purpose, where CSS would collapse those too. They are the
199
+ * only record left of where one block ended and the next began, and a quotation
200
+ * of six form rows run together on one line is worse than one that keeps them
201
+ * apart. Preformatted text is passed through untouched: there the indentation
202
+ * *is* the content.
203
+ */
204
+ function collapse(text: string, parent: HTMLElement): string {
205
+ if (PREFORMATTED.has(whiteSpaceOf(parent))) {
206
+ return text;
207
+ }
208
+ return (
209
+ text
210
+ // Whitespace *around* a newline goes with it. Leaving a space behind
211
+ // would indent every line of the quotation by one, for nothing.
212
+ .replace(/[^\S\n]*\n[^\S\n]*/g, "\n")
213
+ .replace(/[^\S\n]+/g, " ")
214
+ );
215
+ }
216
+
217
+ /** The `white-space` values under which every space is content. */
218
+ const PREFORMATTED = new Set(["pre", "pre-wrap", "break-spaces"]);
219
+
220
+ /** The computed `white-space` of `element`, or `""` where it cannot be read. */
221
+ function whiteSpaceOf(element: HTMLElement): string {
222
+ return window.getComputedStyle(element).whiteSpace;
223
+ }
224
+
225
+ /** Every text node the range touches, in document order. */
226
+ function textNodesIn(range: Range): readonly Text[] {
227
+ const root = range.commonAncestorContainer;
228
+ // A selection inside a single text node has that node as its own common
229
+ // ancestor, and a `TreeWalker` never visits its root.
230
+ if (root.nodeType === Node.TEXT_NODE) {
231
+ return [root as Text];
232
+ }
233
+ const found: Text[] = [];
234
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
235
+ for (let node = walker.nextNode(); node !== null; node = walker.nextNode()) {
236
+ // The walker covers the whole subtree, which reaches past both ends of the
237
+ // range -- a sibling paragraph above the selection is in it too.
238
+ if (range.intersectsNode(node)) {
239
+ found.push(node as Text);
240
+ }
241
+ }
242
+ return found;
243
+ }
244
+
245
+ /** Whether `element` is actually drawn, where the engine will say. */
246
+ function isRendered(element: HTMLElement): boolean {
247
+ if (typeof element.checkVisibility !== "function") {
248
+ return true;
249
+ }
250
+ return element.checkVisibility({
251
+ contentVisibilityAuto: true,
252
+ opacityProperty: true,
253
+ visibilityProperty: true,
254
+ });
255
+ }
256
+
257
+ /**
258
+ * The line of the selection to hang the offer from.
259
+ *
260
+ * **Not the bounding box.** A drag from a narrow column of a form down to a
261
+ * full-width line running under the chat panel beside it produced a union
262
+ * reaching from the column's left edge to the far end of that line -- and its
263
+ * centre landed most of the way across the page, behind the panel, on a line
264
+ * the user had not been looking at, while the pointer had let go by the column.
265
+ *
266
+ * Note what the fix is *not*: that centre was over selected text. It was over
267
+ * selected text nobody could see. A union is a shape the selection does not
268
+ * have, so no point derived from it belongs to any particular line.
269
+ *
270
+ * `near` is where the pointer let go. The line under it is where the user is
271
+ * looking, and it needs no engine-specific way to ask which end of the
272
+ * selection is its focus -- which the shadow-aware read does not carry anyway.
273
+ * Without a pointer -- a keyboard selection -- the first line is the one that
274
+ * exists whichever way the selection was made.
275
+ *
276
+ * The bounding box remains the fallback for a range that reports no line boxes
277
+ * at all, which is what a DOM with no layout does.
278
+ */
279
+ function lineToHangFrom(range: Range, near: Point | undefined): DOMRect {
280
+ const lines = [...range.getClientRects()];
281
+ if (lines.length === 0) {
282
+ return range.getBoundingClientRect();
283
+ }
284
+ if (near === undefined) {
285
+ return lines[0] as DOMRect;
286
+ }
287
+ let closest = lines[0] as DOMRect;
288
+ let shortest = distanceTo(closest, near);
289
+ for (const line of lines.slice(1)) {
290
+ const distance = distanceTo(line, near);
291
+ if (distance < shortest) {
292
+ shortest = distance;
293
+ closest = line;
294
+ }
295
+ }
296
+ return closest;
297
+ }
298
+
299
+ /** How far `point` is from the nearest edge of `rect`, or 0 inside it. */
300
+ function distanceTo(rect: DOMRect, point: Point): number {
301
+ const dx = Math.max(rect.left - point.x, 0, point.x - rect.right);
302
+ const dy = Math.max(rect.top - point.y, 0, point.y - rect.bottom);
303
+ return Math.hypot(dx, dy);
304
+ }
305
+
306
+ /**
307
+ * Endpoint pairs to consider, best first.
308
+ *
309
+ * Both reads are offered rather than one being chosen, because which is correct
310
+ * is a property of the engine *and* of where the user dragged: an engine that
311
+ * rescopes to the host returns endpoints outside the transcript, and the caller
312
+ * rejects those on the same test it uses for a selection that genuinely ran off
313
+ * the transcript. One rule, no engine sniffing.
314
+ */
315
+ function endpointCandidates(roots: readonly ShadowRoot[]): readonly AbstractRange[] {
316
+ const selection = window.getSelection();
317
+ if (selection === null) {
318
+ return [];
319
+ }
320
+ const candidates = [...composedRanges(selection, roots)];
321
+ if (selection.rangeCount > 0) {
322
+ candidates.push(selection.getRangeAt(0));
323
+ }
324
+ return candidates;
325
+ }
326
+
327
+ /** The shadow-aware read, or nothing on an engine that does not have it. */
328
+ function composedRanges(
329
+ selection: Selection,
330
+ roots: readonly ShadowRoot[],
331
+ ): readonly AbstractRange[] {
332
+ const composed = (selection as ComposedSelection).getComposedRanges;
333
+ if (composed === undefined) {
334
+ return [];
335
+ }
336
+ try {
337
+ return composed.call(selection, { shadowRoots: roots });
338
+ } catch {
339
+ // The method shipped first with the shadow roots as rest parameters and
340
+ // only later as a dictionary member, and the earlier form rejects the
341
+ // options object outright rather than ignoring it. Lexical resolves the
342
+ // same split the same way, by trying both shapes at runtime.
343
+ return composed.call(selection, ...roots);
344
+ }
345
+ }
@@ -0,0 +1,175 @@
1
+ import type { UiStrings } from "../ui_strings.js";
2
+ import { attachQuoteOffer, type PageQuoteOffer } from "./page_quote_offer.js";
3
+ import { placeOffer } from "./place_offer.js";
4
+ import { asQuote, quotableSelection } from "./quote_selection.js";
5
+
6
+ /** What the quote offer needs from the element that owns it. */
7
+ export interface TranscriptQuoteHost {
8
+ /** The custom element: its opt-out attribute, and what a page offer excludes. */
9
+ readonly element: HTMLElement;
10
+ /** The shadow root a transcript selection is read through. */
11
+ readonly root: ShadowRoot;
12
+ /** The transcript, whose selections are offered. */
13
+ readonly messages: HTMLElement;
14
+ /** The transcript's positioning box, which the offer floats inside. */
15
+ readonly messagesWrap: HTMLElement;
16
+ /** The composer a quotation is written into. */
17
+ readonly input: HTMLTextAreaElement;
18
+ /** The resolved string table. */
19
+ readonly strings: () => UiStrings;
20
+ /** Resize the composer to what it now holds. */
21
+ readonly autoGrow: () => void;
22
+ /** The element's public `quote`, so a host that replaced it is the one called. */
23
+ readonly quote: (text: string) => void;
24
+ }
25
+
26
+ /**
27
+ * Quoting a selection into the composer: the offer floated beside a selection
28
+ * in the transcript, the same offer over the host page, and the quotation
29
+ * itself.
30
+ *
31
+ * Owned one-to-one by an `<ag-ui-chat>`, and holding no state outside the
32
+ * instance.
33
+ */
34
+ export class TranscriptQuoteOffer {
35
+ /**
36
+ * Offer to quote the current selection, floated beside it.
37
+ *
38
+ * Shares the transcript's positioning box with the jump button for the same
39
+ * reason: it is positioned against the transcript, and must not scroll away
40
+ * with the words it is pointing at.
41
+ */
42
+ readonly button: HTMLButtonElement = document.createElement("button");
43
+
44
+ readonly #host: TranscriptQuoteHost;
45
+ /** What {@link button} would quote, while it is showing. */
46
+ #quoting = "";
47
+ /** The host-page offer, while one is attached; see {@link offerInPage}. */
48
+ #pageQuote: PageQuoteOffer | null = null;
49
+
50
+ constructor(host: TranscriptQuoteHost) {
51
+ this.#host = host;
52
+ }
53
+
54
+ /** The quotation behind `AgUiChat.quote`, whose doc is the contract. */
55
+ insert(text: string): void {
56
+ const quoted = asQuote(text);
57
+ if (quoted === "") {
58
+ return;
59
+ }
60
+ const input = this.#host.input;
61
+ // Appended after whatever is already typed, on a fresh paragraph: a second
62
+ // quotation is a second thing being asked about, not a replacement for the
63
+ // first. Trailing blank lines are dropped so repeated quoting does not
64
+ // accumulate gaps.
65
+ const current = input.value.replace(/\s+$/, "");
66
+ input.value = current === "" ? quoted : `${current}\n\n${quoted}`;
67
+ this.#host.autoGrow();
68
+ input.focus();
69
+ const end = input.value.length;
70
+ input.setSelectionRange(end, end);
71
+ }
72
+
73
+ /** The offer behind `AgUiChat.offerQuoteInPage`, whose doc is the contract. */
74
+ offerInPage(within: HTMLElement): () => void {
75
+ this.#pageQuote?.detach();
76
+ const offer = attachQuoteOffer({
77
+ within,
78
+ label: this.#host.strings().quoteSelection,
79
+ exclude: this.#host.element,
80
+ onQuote: (text) => this.#host.quote(text),
81
+ });
82
+ this.#pageQuote = offer;
83
+ return () => {
84
+ offer.detach();
85
+ if (this.#pageQuote === offer) {
86
+ this.#pageQuote = null;
87
+ }
88
+ };
89
+ }
90
+
91
+ /**
92
+ * Take the host-page offer down. It listens on the host's document, not on
93
+ * anything of ours, so nothing else would ever take it down.
94
+ */
95
+ detachPageOffer(): void {
96
+ this.#pageQuote?.detach();
97
+ this.#pageQuote = null;
98
+ }
99
+
100
+ /**
101
+ * Build the offer and listen for settled selections in the transcript.
102
+ *
103
+ * The button and the transcript outlive a connection, so the listeners go
104
+ * under `signal`, which the element aborts when it leaves the document.
105
+ */
106
+ mount(signal: AbortSignal): void {
107
+ const button = this.button;
108
+ button.className = "quote-selection";
109
+ button.type = "button";
110
+ button.setAttribute("part", "quote-selection");
111
+ button.textContent = this.#host.strings().quoteSelection;
112
+ button.hidden = true;
113
+ // `mousedown` rather than `click`: pressing anywhere else collapses the
114
+ // selection first, and by the time a click lands there is nothing left to
115
+ // quote. Preventing the default keeps the selection alive long enough to
116
+ // read it.
117
+ button.addEventListener(
118
+ "mousedown",
119
+ (event) => {
120
+ event.preventDefault();
121
+ },
122
+ { signal },
123
+ );
124
+ button.addEventListener(
125
+ "click",
126
+ () => {
127
+ this.#host.quote(this.#quoting);
128
+ window.getSelection()?.removeAllRanges();
129
+ this.#hide();
130
+ },
131
+ { signal },
132
+ );
133
+
134
+ // A settled selection, by either input. `mouseup` rather than
135
+ // `selectionchange` so the offer does not chase the pointer mid-drag; the
136
+ // second half of the same gesture, `mousedown`, retires the previous offer
137
+ // before the new selection exists.
138
+ const messages = this.#host.messages;
139
+ messages.addEventListener("mouseup", (event) => this.#onSelectionSettled(event), { signal });
140
+ messages.addEventListener("keyup", () => this.#onSelectionSettled(), { signal });
141
+ messages.addEventListener("mousedown", () => this.#hide(), { signal });
142
+ }
143
+
144
+ /** Whether the transcript offers to quote what the user selects. */
145
+ #enabled(): boolean {
146
+ return this.#host.element.getAttribute("data-quote-selection") !== "false";
147
+ }
148
+
149
+ /**
150
+ * Offer to quote the settled selection, or retire the offer.
151
+ *
152
+ * `event` is passed for its coordinates and only those: they say which line
153
+ * of a selection spanning several messages the offer should hang from. A
154
+ * keyboard selection has none, and the first line is used instead.
155
+ */
156
+ #onSelectionSettled(event?: MouseEvent): void {
157
+ if (!this.#enabled()) {
158
+ return;
159
+ }
160
+ const near = event === undefined ? undefined : { x: event.clientX, y: event.clientY };
161
+ const selected = quotableSelection(this.#host.messages, [this.#host.root], near);
162
+ if (selected === null) {
163
+ this.#hide();
164
+ return;
165
+ }
166
+ this.#quoting = selected.text;
167
+ placeOffer(this.button, selected.rect, this.#host.messagesWrap.getBoundingClientRect());
168
+ }
169
+
170
+ /** Retire the offer, and forget what it was pointing at. */
171
+ #hide(): void {
172
+ this.button.hidden = true;
173
+ this.#quoting = "";
174
+ }
175
+ }
@@ -0,0 +1,41 @@
1
+ /** A `{token}` placeholder, named the way every key in the string table names one. */
2
+ const TOKEN_RE = /\{([a-zA-Z_][a-zA-Z0-9_]*)\}/g;
3
+
4
+ /**
5
+ * Fill the `{token}` placeholders of a string-table template.
6
+ *
7
+ * Every string-table template goes through here rather than through
8
+ * `template.replace("{token}", value)`, which was wrong in two ways at once:
9
+ *
10
+ * - **A string replacement interprets dollar patterns in the value.** `$&`
11
+ * inserts the matched token, and `` $` `` and `$'` the text either side of it,
12
+ * so a queued message reading `costs $& more` was labelled
13
+ * `Do not send "costs {text} more"`. Several of these values are text a user
14
+ * or a server wrote -- a queued message, a tool name, a skill title, an
15
+ * agent name -- so the value has to land verbatim. A replacer function's
16
+ * return value is never interpreted, which is the whole fix.
17
+ * - **A string pattern replaces only the first occurrence**, so a translation
18
+ * that uses a token twice was left half filled.
19
+ *
20
+ * One pass over the template, so a value that itself contains a `{token}` is
21
+ * inserted as written rather than filled in turn: a skill titled
22
+ * `Fill {fields}` stays that, where chained replacements filled it twice.
23
+ *
24
+ * A token with no entry in `values` is left as written. Every call site passes
25
+ * the tokens its key documents, so that is a translation carrying a token the
26
+ * call site does not know, and printing it is more honest than dropping it.
27
+ * `skills/fill_template.ts` is the prompt-side counterpart, and its contract is
28
+ * different on purpose: a prompt reports what it could not fill so a send can
29
+ * be refused.
30
+ *
31
+ * @param template - A string-table value, e.g. `strings.removeQueued`.
32
+ * @param values - The value for each token the template's key documents.
33
+ */
34
+ export function fillUiString(
35
+ template: string,
36
+ values: Readonly<Record<string, string | number>>,
37
+ ): string {
38
+ return template.replace(TOKEN_RE, (token, key: string) =>
39
+ Object.hasOwn(values, key) ? String(values[key]) : token,
40
+ );
41
+ }