@artooi/agents-web-components 0.0.0-stage → 0.1.1

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 +77 -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,471 @@
1
+ import type { ThreadMeta } from "../../core/conversation_store.js";
2
+ import { DEFAULT_UI_STRINGS, type UiStrings } from "../ui_strings.js";
3
+ import { type RelativeTimeFormatter, relativeTime } from "./relative_time.js";
4
+ import { openerElement } from "./utils.js";
5
+
6
+ /**
7
+ * How many conversations there have to be before the filter appears.
8
+ *
9
+ * A search box above a list you can already read in one glance is a control
10
+ * asking to be used on nothing.
11
+ */
12
+ export const FILTER_FROM = 8;
13
+
14
+ /**
15
+ * When the search box shows: from {@link FILTER_FROM} conversations (`auto`),
16
+ * over any list (`always`), or not at all (`never`).
17
+ */
18
+ export type ThreadsSearch = "auto" | "always" | "never";
19
+
20
+ const DAY_MS = 24 * 60 * 60 * 1000;
21
+
22
+ /** Actions the host ({@link AgUiChat}) wires to the drawer's rows. */
23
+ export interface ThreadDrawerCallbacks {
24
+ /** A row was picked — load that thread and make it active. */
25
+ readonly onSelect: (threadId: string) => void;
26
+ /** The "New chat" action — start a fresh thread. */
27
+ readonly onNew: () => void;
28
+ /** A row was renamed to `title`. */
29
+ readonly onRename: (threadId: string, title: string) => void;
30
+ /** A row was deleted (after the inline confirm). */
31
+ readonly onDelete: (threadId: string) => void;
32
+ }
33
+
34
+ /**
35
+ * The chat-history drawer: a slide-over listing the user's threads (title,
36
+ * relative time, preview), with select / new / rename / delete actions and an
37
+ * empty state. Pure DOM, like {@link SkillsMenu}: the host appends
38
+ * {@link element}, toggles it, feeds rows via {@link setThreads}, and acts on
39
+ * the callbacks.
40
+ *
41
+ * A view only — it never mutates the store. After a callback the host updates
42
+ * the store and calls {@link setThreads} to refresh. All visible text comes
43
+ * from {@link UiStrings}; {@link setStrings} re-localizes a drawer built before
44
+ * its strings resolved.
45
+ */
46
+ export class ThreadDrawer {
47
+ /** The drawer root (backdrop + panel). Append to the chat shell; hidden until opened. */
48
+ readonly element: HTMLDivElement;
49
+
50
+ readonly #callbacks: ThreadDrawerCallbacks;
51
+ readonly #panel: HTMLDivElement;
52
+ readonly #heading: HTMLSpanElement;
53
+ readonly #newButton: HTMLButtonElement;
54
+ readonly #list: HTMLDivElement;
55
+ #formatRelativeTime: RelativeTimeFormatter | null = null;
56
+ #strings: UiStrings;
57
+ #threads: readonly ThreadMeta[] = [];
58
+ #activeId = "";
59
+ /** Dismisses the list without starting a new conversation. */
60
+ #closeButton: HTMLButtonElement;
61
+ /** Narrows the list. Only rendered once there is enough of a list to narrow. */
62
+ #filter: HTMLInputElement;
63
+ /** The current filter text, lowercased once rather than per row. */
64
+ #query = "";
65
+ #search: ThreadsSearch = "auto";
66
+
67
+ /** The element focused before the drawer opened, restored on close. */
68
+ #lastFocused: HTMLElement | null = null;
69
+
70
+ constructor(callbacks: ThreadDrawerCallbacks, strings: UiStrings = DEFAULT_UI_STRINGS) {
71
+ this.#callbacks = callbacks;
72
+ this.#strings = strings;
73
+
74
+ this.element = document.createElement("div");
75
+ this.element.className = "drawer";
76
+ this.element.setAttribute("part", "drawer");
77
+ this.element.hidden = true;
78
+
79
+ const backdrop = document.createElement("div");
80
+ backdrop.className = "drawer-backdrop";
81
+ backdrop.setAttribute("part", "drawer-backdrop");
82
+ backdrop.addEventListener("click", () => this.close());
83
+
84
+ this.#panel = document.createElement("div");
85
+ this.#panel.className = "drawer-panel";
86
+ this.#panel.setAttribute("part", "drawer-panel");
87
+ this.#panel.setAttribute("role", "dialog");
88
+ this.#panel.setAttribute("aria-modal", "true");
89
+ this.#panel.setAttribute("aria-label", strings.chatHistory);
90
+ // Escape closes the drawer; Tab is trapped within the panel while it's open.
91
+ this.#panel.addEventListener("keydown", (event) => this.#onPanelKeydown(event));
92
+
93
+ const header = document.createElement("div");
94
+ header.className = "drawer-header";
95
+ header.setAttribute("part", "drawer-header");
96
+ this.#heading = document.createElement("span");
97
+ this.#heading.className = "drawer-title";
98
+ this.#heading.setAttribute("part", "drawer-title");
99
+ this.#heading.textContent = strings.chats;
100
+ this.#newButton = document.createElement("button");
101
+ this.#newButton.type = "button";
102
+ this.#newButton.className = "drawer-new";
103
+ this.#newButton.setAttribute("part", "drawer-new");
104
+ this.#newButton.textContent = strings.newChat;
105
+ this.#newButton.addEventListener("click", () => {
106
+ this.close();
107
+ this.#callbacks.onNew();
108
+ });
109
+ // An explicit way back. The backdrop closes on click, which is enough
110
+ // wherever a strip of it is showing -- but the embedded placement widens
111
+ // the panel to the full width of the host's box, so there is no backdrop
112
+ // left to hit and the only exits were Escape, picking a row, or starting a
113
+ // new conversation. The first is invisible and the last is destructive of
114
+ // the thing you were looking at.
115
+ this.#closeButton = document.createElement("button");
116
+ this.#closeButton.type = "button";
117
+ this.#closeButton.className = "drawer-close";
118
+ this.#closeButton.setAttribute("part", "drawer-close");
119
+ this.#closeButton.title = strings.closeHistory;
120
+ this.#closeButton.setAttribute("aria-label", strings.closeHistory);
121
+ this.#closeButton.append(document.createTextNode("\u00d7"));
122
+ this.#closeButton.addEventListener("click", () => this.close());
123
+ header.append(this.#heading, this.#newButton, this.#closeButton);
124
+
125
+ // Hidden until the list is long enough to be worth narrowing. A search box
126
+ // above four conversations is a control asking to be used on something
127
+ // already entirely visible.
128
+ this.#filter = document.createElement("input");
129
+ this.#filter.type = "search";
130
+ this.#filter.className = "drawer-filter";
131
+ this.#filter.setAttribute("part", "drawer-filter");
132
+ this.#filter.placeholder = strings.searchConversations;
133
+ this.#filter.setAttribute("aria-label", strings.searchConversations);
134
+ this.#filter.addEventListener("input", () => {
135
+ this.#query = this.#filter.value.trim().toLowerCase();
136
+ this.#renderList();
137
+ });
138
+
139
+ this.#list = document.createElement("div");
140
+ this.#list.className = "drawer-list";
141
+ this.#list.setAttribute("part", "drawer-list");
142
+
143
+ this.#panel.append(header, this.#filter, this.#list);
144
+ this.element.append(backdrop, this.#panel);
145
+ }
146
+
147
+ /** Re-localize the drawer's chrome and rows (the host calls this on connect). */
148
+ /**
149
+ * Replace the timestamp formatter, or restore the built-in with `null`.
150
+ *
151
+ * The built-in is deliberately locale-neutral -- there is no `Intl` anywhere
152
+ * in this component, so it never disagrees with a host's own formatting by
153
+ * guessing a locale. That is a defensible default and a poor requirement, so
154
+ * this is the way out.
155
+ */
156
+ setRelativeTimeFormatter(format: RelativeTimeFormatter | null): void {
157
+ this.#formatRelativeTime = format;
158
+ }
159
+
160
+ /** This row's timestamp, through the host's formatter when it set one. */
161
+ #formatTime(timestamp: number): string {
162
+ return this.#formatRelativeTime !== null
163
+ ? this.#formatRelativeTime(timestamp)
164
+ : relativeTime(timestamp, undefined, this.#strings);
165
+ }
166
+
167
+ setStrings(strings: UiStrings): void {
168
+ this.#strings = strings;
169
+ this.#panel.setAttribute("aria-label", strings.chatHistory);
170
+ this.#heading.textContent = strings.chats;
171
+ this.#newButton.textContent = strings.newChat;
172
+ this.#closeButton.title = strings.closeHistory;
173
+ this.#closeButton.setAttribute("aria-label", strings.closeHistory);
174
+ this.#filter.placeholder = strings.searchConversations;
175
+ this.#filter.setAttribute("aria-label", strings.searchConversations);
176
+ this.#renderList();
177
+ }
178
+
179
+ isOpen(): boolean {
180
+ return !this.element.hidden;
181
+ }
182
+
183
+ open(): void {
184
+ if (this.isOpen()) {
185
+ return;
186
+ }
187
+ // Remember what had focus so it's restored on close, then move focus into
188
+ // the panel (its first control) so keyboard users land inside the dialog.
189
+ this.#lastFocused = openerElement(
190
+ this.element.getRootNode() as Document | ShadowRoot,
191
+ ) as HTMLElement | null;
192
+ this.element.hidden = false;
193
+ this.#newButton.focus();
194
+ }
195
+
196
+ close(): void {
197
+ if (!this.isOpen()) {
198
+ return;
199
+ }
200
+ this.element.hidden = true;
201
+ this.#lastFocused?.focus();
202
+ this.#lastFocused = null;
203
+ }
204
+
205
+ toggle(): void {
206
+ if (this.isOpen()) {
207
+ this.close();
208
+ } else {
209
+ this.open();
210
+ }
211
+ }
212
+
213
+ /** The currently-focused element within the drawer's root (shadow-aware). */
214
+ #activeElement(): Element | null {
215
+ return (this.element.getRootNode() as Document | ShadowRoot).activeElement;
216
+ }
217
+
218
+ /** Escape-to-close and a Tab focus trap while the dialog is open. */
219
+ #onPanelKeydown(event: KeyboardEvent): void {
220
+ if (event.key === "Escape") {
221
+ event.preventDefault();
222
+ this.close();
223
+ return;
224
+ }
225
+ if (event.key !== "Tab") {
226
+ return;
227
+ }
228
+ const focusables = Array.from(
229
+ this.#panel.querySelectorAll<HTMLElement>("button, input, [tabindex]"),
230
+ ).filter((el) => !el.hidden);
231
+ const first = focusables[0];
232
+ const last = focusables[focusables.length - 1];
233
+ const active = this.#activeElement();
234
+ if (event.shiftKey && active === first) {
235
+ event.preventDefault();
236
+ last?.focus();
237
+ } else if (!event.shiftKey && active === last) {
238
+ event.preventDefault();
239
+ first?.focus();
240
+ }
241
+ }
242
+
243
+ /** Choose when the search box shows; the host's `data-threads-search`. */
244
+ setSearchMode(mode: ThreadsSearch): void {
245
+ this.#search = mode;
246
+ this.#renderList();
247
+ }
248
+
249
+ /** Render the rows (or the empty state), highlighting the active thread. */
250
+ setThreads(threads: readonly ThreadMeta[], activeId: string): void {
251
+ this.#threads = threads;
252
+ this.#activeId = activeId;
253
+ this.#renderList();
254
+ }
255
+
256
+ #renderList(): void {
257
+ this.#list.replaceChildren();
258
+ const hideFilter =
259
+ this.#search === "auto" ? this.#threads.length < FILTER_FROM : this.#search === "never";
260
+ this.#filter.hidden = hideFilter;
261
+ // Cleared as it goes, or the query outlives the control that set it: a
262
+ // list that drops below the threshold while a query matches nothing shows
263
+ // "no conversations match that" over conversations that are right there,
264
+ // with nothing left on screen to clear. Reopening does not help either --
265
+ // only a new drawer would.
266
+ if (hideFilter && this.#query !== "") {
267
+ this.#filter.value = "";
268
+ this.#query = "";
269
+ }
270
+ const shown = this.#matching();
271
+ if (shown.length === 0) {
272
+ const empty = document.createElement("div");
273
+ empty.className = "drawer-empty";
274
+ empty.setAttribute("part", "drawer-empty");
275
+ // Two different situations wearing one sentence would be a small lie:
276
+ // "no conversations yet" reads as data loss when what happened is that a
277
+ // filter matched nothing.
278
+ empty.textContent =
279
+ this.#threads.length === 0 ? this.#strings.noConversations : this.#strings.noMatches;
280
+ this.#list.appendChild(empty);
281
+ return;
282
+ }
283
+ const groups = this.#groups(shown);
284
+ for (const [label, metas] of groups) {
285
+ // One group would label the whole list, which says nothing the rows do not.
286
+ if (groups.length > 1) {
287
+ const heading = document.createElement("div");
288
+ heading.className = "drawer-group-label";
289
+ heading.setAttribute("part", "drawer-group-label");
290
+ heading.setAttribute("role", "heading");
291
+ heading.setAttribute("aria-level", "3");
292
+ heading.textContent = label;
293
+ this.#list.appendChild(heading);
294
+ }
295
+ for (const meta of metas) {
296
+ this.#list.appendChild(this.#renderRow(meta));
297
+ }
298
+ }
299
+ }
300
+
301
+ /**
302
+ * The rows by age from local midnight, in list order within each group, empty
303
+ * groups dropped. A date that does not parse is never today, so it lands in Older.
304
+ */
305
+ #groups(shown: readonly ThreadMeta[]): [string, ThreadMeta[]][] {
306
+ const now = new Date();
307
+ const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();
308
+ const recent: ThreadMeta[] = [];
309
+ const week: ThreadMeta[] = [];
310
+ const older: ThreadMeta[] = [];
311
+ for (const meta of shown) {
312
+ const at = meta.updatedAt;
313
+ (at >= today ? recent : at >= today - 7 * DAY_MS ? week : older).push(meta);
314
+ }
315
+ const groups: [string, ThreadMeta[]][] = [
316
+ [this.#strings.threadsToday, recent],
317
+ [this.#strings.threadsPreviousWeek, week],
318
+ [this.#strings.threadsOlder, older],
319
+ ];
320
+ return groups.filter(([, metas]) => metas.length > 0);
321
+ }
322
+
323
+ /**
324
+ * The rows the filter leaves.
325
+ *
326
+ * Title and preview both, because the title is often the model's summary of
327
+ * a conversation and the thing being looked for is as likely to be a phrase
328
+ * from inside it. Client-side over what the drawer already holds: the server
329
+ * index is fetched whole, so a query would be a round trip to filter a list
330
+ * already in memory.
331
+ */
332
+ #matching(): readonly ThreadMeta[] {
333
+ if (this.#query === "") {
334
+ return this.#threads;
335
+ }
336
+ return this.#threads.filter(
337
+ (meta) =>
338
+ meta.title.toLowerCase().includes(this.#query) ||
339
+ meta.preview.toLowerCase().includes(this.#query),
340
+ );
341
+ }
342
+
343
+ #renderRow(meta: ThreadMeta): HTMLDivElement {
344
+ const row = document.createElement("div");
345
+ row.className = "drawer-row";
346
+ row.setAttribute("part", "drawer-row");
347
+ if (meta.threadId === this.#activeId) {
348
+ row.classList.add("drawer-row--active");
349
+ }
350
+
351
+ const select = document.createElement("button");
352
+ select.type = "button";
353
+ select.className = "drawer-row-select";
354
+ select.setAttribute("part", "drawer-row-select");
355
+ const title = document.createElement("span");
356
+ title.className = "drawer-row-title";
357
+ title.setAttribute("part", "drawer-row-title");
358
+ title.textContent = meta.title;
359
+ const time = document.createElement("span");
360
+ time.className = "drawer-row-time";
361
+ time.setAttribute("part", "drawer-row-time");
362
+ time.textContent = this.#formatTime(meta.updatedAt);
363
+ const preview = document.createElement("span");
364
+ preview.className = "drawer-row-preview";
365
+ preview.setAttribute("part", "drawer-row-preview");
366
+ preview.textContent = meta.preview;
367
+ select.append(title, time, preview);
368
+ select.addEventListener("click", () => {
369
+ this.close();
370
+ this.#callbacks.onSelect(meta.threadId);
371
+ });
372
+
373
+ const rename = document.createElement("button");
374
+ rename.type = "button";
375
+ rename.className = "drawer-row-rename";
376
+ rename.setAttribute("part", "drawer-row-rename");
377
+ rename.title = this.#strings.rename;
378
+ rename.setAttribute("aria-label", this.#strings.renameConversation);
379
+ rename.textContent = "✎";
380
+ rename.addEventListener("click", () => this.#startRename(row, meta));
381
+
382
+ const remove = document.createElement("button");
383
+ remove.type = "button";
384
+ remove.className = "drawer-row-delete";
385
+ remove.setAttribute("part", "drawer-row-delete");
386
+ remove.title = this.#strings.delete;
387
+ remove.setAttribute("aria-label", this.#strings.deleteConversation);
388
+ remove.textContent = "🗑";
389
+ remove.addEventListener("click", () => this.#confirmDelete(row, meta));
390
+
391
+ const actions = document.createElement("div");
392
+ actions.className = "drawer-row-actions";
393
+ actions.setAttribute("part", "drawer-row-actions");
394
+ actions.append(rename, remove);
395
+
396
+ row.append(select, actions);
397
+ return row;
398
+ }
399
+
400
+ /** Swap a row for an inline rename input; Enter/blur commits, Escape cancels. */
401
+ #startRename(row: HTMLDivElement, meta: ThreadMeta): void {
402
+ const input = document.createElement("input");
403
+ input.type = "text";
404
+ input.className = "drawer-rename-input";
405
+ input.setAttribute("part", "drawer-rename-input");
406
+ input.value = meta.title;
407
+ // One-shot: Enter, Escape, and blur can all fire for a single edit (Enter
408
+ // commits and re-renders, which blurs the detached input); the flag makes
409
+ // the later events no-ops so a rename isn't submitted twice.
410
+ let done = false;
411
+ const commit = (): void => {
412
+ if (done) {
413
+ return;
414
+ }
415
+ done = true;
416
+ const value = input.value.trim();
417
+ if (value === "" || value === meta.title) {
418
+ this.#renderList();
419
+ } else {
420
+ this.#callbacks.onRename(meta.threadId, value);
421
+ }
422
+ };
423
+ const cancel = (): void => {
424
+ if (done) {
425
+ return;
426
+ }
427
+ done = true;
428
+ this.#renderList();
429
+ };
430
+ input.addEventListener("keydown", (event) => {
431
+ if (event.key === "Enter") {
432
+ event.preventDefault();
433
+ commit();
434
+ } else if (event.key === "Escape") {
435
+ // Stop the panel's Escape handler from also closing the drawer.
436
+ event.preventDefault();
437
+ event.stopPropagation();
438
+ cancel();
439
+ }
440
+ });
441
+ input.addEventListener("blur", () => commit());
442
+ row.replaceChildren(input);
443
+ input.focus();
444
+ input.select();
445
+ }
446
+
447
+ /** Swap a row for an inline "Delete? [Delete] [Cancel]" confirm. */
448
+ #confirmDelete(row: HTMLDivElement, meta: ThreadMeta): void {
449
+ const confirm = document.createElement("div");
450
+ confirm.className = "drawer-confirm";
451
+ confirm.setAttribute("part", "drawer-confirm");
452
+ const label = document.createElement("span");
453
+ label.className = "drawer-confirm-label";
454
+ label.setAttribute("part", "drawer-confirm-label");
455
+ label.textContent = this.#strings.deletePrompt;
456
+ const yes = document.createElement("button");
457
+ yes.type = "button";
458
+ yes.className = "drawer-confirm-yes";
459
+ yes.setAttribute("part", "drawer-confirm-yes");
460
+ yes.textContent = this.#strings.delete;
461
+ yes.addEventListener("click", () => this.#callbacks.onDelete(meta.threadId));
462
+ const no = document.createElement("button");
463
+ no.type = "button";
464
+ no.className = "drawer-confirm-no";
465
+ no.setAttribute("part", "drawer-confirm-no");
466
+ no.textContent = this.#strings.cancel;
467
+ no.addEventListener("click", () => this.#renderList());
468
+ confirm.append(label, yes, no);
469
+ row.replaceChildren(confirm);
470
+ }
471
+ }
@@ -0,0 +1,11 @@
1
+ export function openerElement(root: Document | ShadowRoot): Element | null {
2
+ const inside = root.activeElement;
3
+ if (inside !== null) {
4
+ return inside;
5
+ }
6
+ let active: Element | null = document.activeElement;
7
+ while (active?.shadowRoot?.activeElement) {
8
+ active = active.shadowRoot.activeElement;
9
+ }
10
+ return active === document.body ? null : active;
11
+ }
@@ -0,0 +1,202 @@
1
+ import { DEFAULT_UI_STRINGS, type UiStrings } from "../ui_strings.js";
2
+
3
+ /** What the inline approval card displays for one server-side-tool interrupt. */
4
+ export interface ApprovalRequest {
5
+ /**
6
+ * Human-readable prompt from the AG-UI interrupt (e.g.
7
+ * `Approve delete_thing({…})?`). Falls back to the generic
8
+ * {@link UiStrings.approvalPrompt} when the interrupt carries no message.
9
+ */
10
+ message?: string;
11
+ /** Tool name, surfaced as a `data-tool-name` attribute for styling/tests. */
12
+ toolName?: string;
13
+ /**
14
+ * The call's arguments, shown for editing when {@link ApprovalOptions.onEdit}
15
+ * is set. Omitted when the interrupt names no call whose arguments are known.
16
+ */
17
+ args?: Record<string, unknown>;
18
+ }
19
+
20
+ /** Build a labelled action button. */
21
+ function actionButton(modifier: string, label: string): HTMLButtonElement {
22
+ const button = document.createElement("button");
23
+ button.type = "button";
24
+ button.className = `approval-btn approval-btn--${modifier}`;
25
+ button.setAttribute("part", `approval-button approval-${modifier}`);
26
+ button.textContent = label;
27
+ return button;
28
+ }
29
+
30
+ /** Options for {@link requestApproval}. */
31
+ export interface ApprovalOptions {
32
+ /**
33
+ * Aborting this signal resolves the card as denied, with buttons disabled and
34
+ * `data-resolved="denied"` — how a Stop control dismisses a pending approval.
35
+ */
36
+ signal?: AbortSignal;
37
+ /** Localized strings; defaults to the English {@link DEFAULT_UI_STRINGS}. */
38
+ strings?: UiStrings;
39
+ /**
40
+ * Offer the call's arguments for editing, and receive what the user approved.
41
+ *
42
+ * Called **only** on approval, and only when the text parses and differs from
43
+ * what was proposed -- an untouched call resolves as a plain approval, so a
44
+ * server sees `editedArgs` exactly when something was actually edited.
45
+ *
46
+ * Absent means no editor, which is deliberate: AG-UI gates this on the
47
+ * agent's own `approveWithEdits` capability, and a card that let a user
48
+ * rewrite arguments a server will discard is worse than one that does not
49
+ * offer to.
50
+ */
51
+ onEdit?: (args: Record<string, unknown>) => void;
52
+ }
53
+
54
+ /**
55
+ * A fully custom renderer for a server-side-tool approval, set via
56
+ * `AgUiChat.approvalRenderer`. Receives the {@link ApprovalRequest} and an
57
+ * `AbortSignal` that fires when the run is stopped, and resolves `true` to
58
+ * approve or `false` to deny. Replaces the built-in {@link requestApproval}
59
+ * card entirely, the host owning the DOM; to restyle the built-in card instead,
60
+ * use the `strings` and `::part()` seams.
61
+ */
62
+ export type ApprovalRenderer = (
63
+ request: ApprovalRequest,
64
+ options: { signal: AbortSignal },
65
+ ) => Promise<boolean>;
66
+
67
+ /**
68
+ * Append an inline approval card to `host` and resolve `true` to run a gated
69
+ * server-side tool or `false` to deny it.
70
+ *
71
+ * Distinct from the client-tool confirmation card
72
+ * ({@link requestConfirmation}): a gated server tool defers instead of
73
+ * executing, so the run finishes on an AG-UI interrupt the client answers with
74
+ * `resume[]`, and this is the browser half of that loop. Unlike the
75
+ * confirmation card, this one stays in the transcript as a resolved record,
76
+ * buttons disabled and `data-resolved` set.
77
+ */
78
+ export function requestApproval(
79
+ host: Node & ParentNode,
80
+ request: ApprovalRequest,
81
+ options: ApprovalOptions = {},
82
+ ): Promise<boolean> {
83
+ const strings = options.strings ?? DEFAULT_UI_STRINGS;
84
+ return new Promise<boolean>((resolve) => {
85
+ const card = document.createElement("div");
86
+ card.className = "approval";
87
+ card.setAttribute("part", "approval");
88
+ if (request.toolName !== undefined) {
89
+ card.setAttribute("data-tool-name", request.toolName);
90
+ }
91
+ card.setAttribute("role", "group");
92
+ card.setAttribute("aria-label", strings.approveAction);
93
+
94
+ const body = document.createElement("div");
95
+ body.className = "approval-body";
96
+ body.setAttribute("part", "approval-body");
97
+ body.textContent = request.message ?? strings.approvalPrompt;
98
+
99
+ const editor = buildEditor(request, options, strings);
100
+
101
+ const actions = document.createElement("div");
102
+ actions.className = "approval-actions";
103
+ actions.setAttribute("part", "approval-actions");
104
+
105
+ const deny = actionButton("deny", strings.deny);
106
+ const approve = actionButton("approve", strings.approve);
107
+
108
+ let settled = false;
109
+ const close = (approved: boolean): void => {
110
+ if (settled) {
111
+ return;
112
+ }
113
+ settled = true;
114
+ deny.disabled = true;
115
+ approve.disabled = true;
116
+ card.setAttribute("data-resolved", approved ? "approved" : "denied");
117
+ resolve(approved);
118
+ };
119
+
120
+ deny.addEventListener("click", () => close(false));
121
+ approve.addEventListener("click", () => {
122
+ if (editor !== null && !editor.commit()) {
123
+ // Unparseable JSON: say so on the card and stay open. Approving what
124
+ // the user did not write -- the original arguments -- would be the one
125
+ // outcome they cannot see coming.
126
+ return;
127
+ }
128
+ close(true);
129
+ });
130
+ options.signal?.addEventListener("abort", () => close(false), { once: true });
131
+
132
+ actions.append(deny, approve);
133
+ card.append(body, ...(editor === null ? [] : [editor.root]), actions);
134
+ host.appendChild(card);
135
+ if (options.signal?.aborted === true) {
136
+ // The run was cancelled before the card could ask; record the denial.
137
+ close(false);
138
+ return;
139
+ }
140
+ approve.focus();
141
+ });
142
+ }
143
+
144
+ /** The editable-arguments region, or `null` when this card does not offer one. */
145
+ function buildEditor(
146
+ request: ApprovalRequest,
147
+ options: ApprovalOptions,
148
+ strings: UiStrings,
149
+ ): { root: HTMLElement; commit: () => boolean } | null {
150
+ const { onEdit } = options;
151
+ if (onEdit === undefined || request.args === undefined) {
152
+ return null;
153
+ }
154
+ const original = JSON.stringify(request.args, null, 2);
155
+ const root = document.createElement("div");
156
+ root.className = "approval-edit";
157
+ root.setAttribute("part", "approval-edit");
158
+
159
+ const field = document.createElement("textarea");
160
+ field.className = "approval-args";
161
+ field.setAttribute("part", "approval-args");
162
+ field.setAttribute("aria-label", strings.approvalEditArgs);
163
+ field.rows = Math.min(10, original.split("\n").length);
164
+ field.value = original;
165
+
166
+ const error = document.createElement("div");
167
+ error.className = "approval-error";
168
+ error.setAttribute("part", "approval-error");
169
+ // A live region: it appears in response to pressing Approve, and a message
170
+ // that only exists visually leaves a screen-reader user with a button that
171
+ // silently did nothing.
172
+ error.setAttribute("role", "alert");
173
+ error.hidden = true;
174
+
175
+ root.append(field, error);
176
+ return {
177
+ root,
178
+ commit: () => {
179
+ if (field.value === original) {
180
+ return true;
181
+ }
182
+ let parsed: unknown;
183
+ try {
184
+ parsed = JSON.parse(field.value);
185
+ } catch {
186
+ error.textContent = strings.approvalArgsInvalid;
187
+ error.hidden = false;
188
+ field.focus();
189
+ return false;
190
+ }
191
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
192
+ error.textContent = strings.approvalArgsNotAnObject;
193
+ error.hidden = false;
194
+ field.focus();
195
+ return false;
196
+ }
197
+ error.hidden = true;
198
+ onEdit(parsed as Record<string, unknown>);
199
+ return true;
200
+ },
201
+ };
202
+ }