@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.
- package/CHANGELOG.md +77 -0
- package/LICENSE +21 -0
- package/README.md +4397 -2
- package/dist/agents-web-components.bundle.js +5708 -0
- package/dist/agents-web-components.bundle.js.map +7 -0
- package/dist/bundle.d.ts +3 -0
- package/dist/bundle.d.ts.map +1 -0
- package/dist/chat.d.ts +3 -0
- package/dist/chat.d.ts.map +1 -0
- package/dist/chat.js +16373 -0
- package/dist/chat.js.map +7 -0
- package/dist/chunk-ARNLFGCC.js +7715 -0
- package/dist/chunk-ARNLFGCC.js.map +7 -0
- package/dist/constants.d.ts +575 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/core/activity_registration.d.ts +19 -0
- package/dist/core/activity_registration.d.ts.map +1 -0
- package/dist/core/activity_registry.d.ts +46 -0
- package/dist/core/activity_registry.d.ts.map +1 -0
- package/dist/core/activity_renderer.d.ts +20 -0
- package/dist/core/activity_renderer.d.ts.map +1 -0
- package/dist/core/ag_ui_chat.d.ts +836 -0
- package/dist/core/ag_ui_chat.d.ts.map +1 -0
- package/dist/core/agui_client.d.ts +370 -0
- package/dist/core/agui_client.d.ts.map +1 -0
- package/dist/core/attachment.d.ts +42 -0
- package/dist/core/attachment.d.ts.map +1 -0
- package/dist/core/chat_registry.d.ts +23 -0
- package/dist/core/chat_registry.d.ts.map +1 -0
- package/dist/core/client_seed.d.ts +27 -0
- package/dist/core/client_seed.d.ts.map +1 -0
- package/dist/core/conversation_store.d.ts +195 -0
- package/dist/core/conversation_store.d.ts.map +1 -0
- package/dist/core/create_http_agent.d.ts +57 -0
- package/dist/core/create_http_agent.d.ts.map +1 -0
- package/dist/core/define_chat.d.ts +13 -0
- package/dist/core/define_chat.d.ts.map +1 -0
- package/dist/core/events/attachments_detail.d.ts +9 -0
- package/dist/core/events/attachments_detail.d.ts.map +1 -0
- package/dist/core/events/bar_height_detail.d.ts +6 -0
- package/dist/core/events/bar_height_detail.d.ts.map +1 -0
- package/dist/core/events/custom_agent_detail.d.ts +8 -0
- package/dist/core/events/custom_agent_detail.d.ts.map +1 -0
- package/dist/core/events/dock_width_detail.d.ts +8 -0
- package/dist/core/events/dock_width_detail.d.ts.map +1 -0
- package/dist/core/events/feedback_detail.d.ts +28 -0
- package/dist/core/events/feedback_detail.d.ts.map +1 -0
- package/dist/core/events/invalidate_detail.d.ts +16 -0
- package/dist/core/events/invalidate_detail.d.ts.map +1 -0
- package/dist/core/events/maximize_detail.d.ts +5 -0
- package/dist/core/events/maximize_detail.d.ts.map +1 -0
- package/dist/core/events/run_finished_detail.d.ts +36 -0
- package/dist/core/events/run_finished_detail.d.ts.map +1 -0
- package/dist/core/events/state_detail.d.ts +5 -0
- package/dist/core/events/state_detail.d.ts.map +1 -0
- package/dist/core/events/submit_detail.d.ts +8 -0
- package/dist/core/events/submit_detail.d.ts.map +1 -0
- package/dist/core/events/thread_detail.d.ts +27 -0
- package/dist/core/events/thread_detail.d.ts.map +1 -0
- package/dist/core/events/thread_title_detail.d.ts +8 -0
- package/dist/core/events/thread_title_detail.d.ts.map +1 -0
- package/dist/core/events/toggle_detail.d.ts +5 -0
- package/dist/core/events/toggle_detail.d.ts.map +1 -0
- package/dist/core/events/tool_run.d.ts +11 -0
- package/dist/core/events/tool_run.d.ts.map +1 -0
- package/dist/core/events/unread_detail.d.ts +11 -0
- package/dist/core/events/unread_detail.d.ts.map +1 -0
- package/dist/core/message_role.d.ts +4 -0
- package/dist/core/message_role.d.ts.map +1 -0
- package/dist/core/read_flag.d.ts +11 -0
- package/dist/core/read_flag.d.ts.map +1 -0
- package/dist/core/read_json_attribute.d.ts +15 -0
- package/dist/core/read_json_attribute.d.ts.map +1 -0
- package/dist/core/read_max_tool_rounds.d.ts +9 -0
- package/dist/core/read_max_tool_rounds.d.ts.map +1 -0
- package/dist/core/remote_conversation_store.d.ts +71 -0
- package/dist/core/remote_conversation_store.d.ts.map +1 -0
- package/dist/core/run_handlers.d.ts +85 -0
- package/dist/core/run_handlers.d.ts.map +1 -0
- package/dist/core/run_index.d.ts +58 -0
- package/dist/core/run_index.d.ts.map +1 -0
- package/dist/core/storage_scope.d.ts +118 -0
- package/dist/core/storage_scope.d.ts.map +1 -0
- package/dist/core/tool_outcome.d.ts +27 -0
- package/dist/core/tool_outcome.d.ts.map +1 -0
- package/dist/core/transcribe_audio.d.ts +32 -0
- package/dist/core/transcribe_audio.d.ts.map +1 -0
- package/dist/core/upload_attachment.d.ts +44 -0
- package/dist/core/upload_attachment.d.ts.map +1 -0
- package/dist/core/utils.d.ts +117 -0
- package/dist/core/utils.d.ts.map +1 -0
- package/dist/dom/animations.d.ts +122 -0
- package/dist/dom/animations.d.ts.map +1 -0
- package/dist/dom/dom_driver.d.ts +28 -0
- package/dist/dom/dom_driver.d.ts.map +1 -0
- package/dist/dom/highlight_overlay.d.ts +39 -0
- package/dist/dom/highlight_overlay.d.ts.map +1 -0
- package/dist/dom/native_setter.d.ts +5 -0
- package/dist/dom/native_setter.d.ts.map +1 -0
- package/dist/dom/ring_color.d.ts +16 -0
- package/dist/dom/ring_color.d.ts.map +1 -0
- package/dist/dom/utils.d.ts +3 -0
- package/dist/dom/utils.d.ts.map +1 -0
- package/dist/index.d.ts +62 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +223 -0
- package/dist/index.js.map +7 -0
- package/dist/skills/fill_template.d.ts +16 -0
- package/dist/skills/fill_template.d.ts.map +1 -0
- package/dist/skills/parse_skills.d.ts +8 -0
- package/dist/skills/parse_skills.d.ts.map +1 -0
- package/dist/skills/skill.d.ts +33 -0
- package/dist/skills/skill.d.ts.map +1 -0
- package/dist/skills/skill_catalog.d.ts +69 -0
- package/dist/skills/skill_catalog.d.ts.map +1 -0
- package/dist/skills/skill_name_from.d.ts +12 -0
- package/dist/skills/skill_name_from.d.ts.map +1 -0
- package/dist/tools/chat_surface_tools.d.ts +77 -0
- package/dist/tools/chat_surface_tools.d.ts.map +1 -0
- package/dist/tools/client_tool_registry.d.ts +58 -0
- package/dist/tools/client_tool_registry.d.ts.map +1 -0
- package/dist/tools/is_destructive.d.ts +14 -0
- package/dist/tools/is_destructive.d.ts.map +1 -0
- package/dist/tools/is_navigates.d.ts +9 -0
- package/dist/tools/is_navigates.d.ts.map +1 -0
- package/dist/tools/page_action_tools.d.ts +30 -0
- package/dist/tools/page_action_tools.d.ts.map +1 -0
- package/dist/tools/page_map.d.ts +16 -0
- package/dist/tools/page_map.d.ts.map +1 -0
- package/dist/tools/page_state.d.ts +27 -0
- package/dist/tools/page_state.d.ts.map +1 -0
- package/dist/tools/parse_tool_catalog.d.ts +21 -0
- package/dist/tools/parse_tool_catalog.d.ts.map +1 -0
- package/dist/tools/route_map.d.ts +37 -0
- package/dist/tools/route_map.d.ts.map +1 -0
- package/dist/tools/tool_catalog.d.ts +86 -0
- package/dist/tools/tool_catalog.d.ts.map +1 -0
- package/dist/tools/tool_dispatch.d.ts +82 -0
- package/dist/tools/tool_dispatch.d.ts.map +1 -0
- package/dist/ui/charts/chart_block.d.ts +57 -0
- package/dist/ui/charts/chart_block.d.ts.map +1 -0
- package/dist/ui/charts/chart_spec_from.d.ts +12 -0
- package/dist/ui/charts/chart_spec_from.d.ts.map +1 -0
- package/dist/ui/charts/chart_styles.d.ts +2 -0
- package/dist/ui/charts/chart_styles.d.ts.map +1 -0
- package/dist/ui/charts/chart_tool.d.ts +15 -0
- package/dist/ui/charts/chart_tool.d.ts.map +1 -0
- package/dist/ui/composer/attachment_styles.d.ts +2 -0
- package/dist/ui/composer/attachment_styles.d.ts.map +1 -0
- package/dist/ui/composer/attachment_tray.d.ts +53 -0
- package/dist/ui/composer/attachment_tray.d.ts.map +1 -0
- package/dist/ui/composer/auto_grow.d.ts +10 -0
- package/dist/ui/composer/auto_grow.d.ts.map +1 -0
- package/dist/ui/composer/build_composer.d.ts +32 -0
- package/dist/ui/composer/build_composer.d.ts.map +1 -0
- package/dist/ui/composer/composer_attachments.d.ts +57 -0
- package/dist/ui/composer/composer_attachments.d.ts.map +1 -0
- package/dist/ui/composer/composer_styles.d.ts +2 -0
- package/dist/ui/composer/composer_styles.d.ts.map +1 -0
- package/dist/ui/composer/composer_voice.d.ts +48 -0
- package/dist/ui/composer/composer_voice.d.ts.map +1 -0
- package/dist/ui/composer/skill_styles.d.ts +2 -0
- package/dist/ui/composer/skill_styles.d.ts.map +1 -0
- package/dist/ui/composer/skills_menu.d.ts +34 -0
- package/dist/ui/composer/skills_menu.d.ts.map +1 -0
- package/dist/ui/composer/voice_input.d.ts +46 -0
- package/dist/ui/composer/voice_input.d.ts.map +1 -0
- package/dist/ui/excerpts/attach_copy_buttons.d.ts +13 -0
- package/dist/ui/excerpts/attach_copy_buttons.d.ts.map +1 -0
- package/dist/ui/excerpts/copy_payload.d.ts +30 -0
- package/dist/ui/excerpts/copy_payload.d.ts.map +1 -0
- package/dist/ui/excerpts/page_quote_offer.d.ts +33 -0
- package/dist/ui/excerpts/page_quote_offer.d.ts.map +1 -0
- package/dist/ui/excerpts/place_offer.d.ts +9 -0
- package/dist/ui/excerpts/place_offer.d.ts.map +1 -0
- package/dist/ui/excerpts/quote_selection.d.ts +66 -0
- package/dist/ui/excerpts/quote_selection.d.ts.map +1 -0
- package/dist/ui/excerpts/transcript_quote_offer.d.ts +57 -0
- package/dist/ui/excerpts/transcript_quote_offer.d.ts.map +1 -0
- package/dist/ui/fill_ui_string.d.ts +32 -0
- package/dist/ui/fill_ui_string.d.ts.map +1 -0
- package/dist/ui/history/checkpoint_menu.d.ts +41 -0
- package/dist/ui/history/checkpoint_menu.d.ts.map +1 -0
- package/dist/ui/history/conversation_history.d.ts +317 -0
- package/dist/ui/history/conversation_history.d.ts.map +1 -0
- package/dist/ui/history/history_styles.d.ts +2 -0
- package/dist/ui/history/history_styles.d.ts.map +1 -0
- package/dist/ui/history/relative_time.d.ts +23 -0
- package/dist/ui/history/relative_time.d.ts.map +1 -0
- package/dist/ui/history/thread_drawer.d.ts +64 -0
- package/dist/ui/history/thread_drawer.d.ts.map +1 -0
- package/dist/ui/history/utils.d.ts +2 -0
- package/dist/ui/history/utils.d.ts.map +1 -0
- package/dist/ui/interrupts/approval_card.d.ts +64 -0
- package/dist/ui/interrupts/approval_card.d.ts.map +1 -0
- package/dist/ui/interrupts/approval_styles.d.ts +2 -0
- package/dist/ui/interrupts/approval_styles.d.ts.map +1 -0
- package/dist/ui/interrupts/confirmation_card.d.ts +51 -0
- package/dist/ui/interrupts/confirmation_card.d.ts.map +1 -0
- package/dist/ui/interrupts/confirmation_styles.d.ts +2 -0
- package/dist/ui/interrupts/confirmation_styles.d.ts.map +1 -0
- package/dist/ui/interrupts/pending_decision.d.ts +22 -0
- package/dist/ui/interrupts/pending_decision.d.ts.map +1 -0
- package/dist/ui/interrupts/question_card.d.ts +49 -0
- package/dist/ui/interrupts/question_card.d.ts.map +1 -0
- package/dist/ui/interrupts/question_styles.d.ts +2 -0
- package/dist/ui/interrupts/question_styles.d.ts.map +1 -0
- package/dist/ui/place/place.d.ts +17 -0
- package/dist/ui/place/place.d.ts.map +1 -0
- package/dist/ui/place/place_chip.d.ts +26 -0
- package/dist/ui/place/place_chip.d.ts.map +1 -0
- package/dist/ui/place/place_from_route.d.ts +9 -0
- package/dist/ui/place/place_from_route.d.ts.map +1 -0
- package/dist/ui/place/place_styles.d.ts +2 -0
- package/dist/ui/place/place_styles.d.ts.map +1 -0
- package/dist/ui/placement/clamp_launcher.d.ts +20 -0
- package/dist/ui/placement/clamp_launcher.d.ts.map +1 -0
- package/dist/ui/placement/clamp_panel.d.ts +13 -0
- package/dist/ui/placement/clamp_panel.d.ts.map +1 -0
- package/dist/ui/placement/collapse_styles.d.ts +2 -0
- package/dist/ui/placement/collapse_styles.d.ts.map +1 -0
- package/dist/ui/placement/dock_styles.d.ts +2 -0
- package/dist/ui/placement/dock_styles.d.ts.map +1 -0
- package/dist/ui/placement/embedded_styles.d.ts +2 -0
- package/dist/ui/placement/embedded_styles.d.ts.map +1 -0
- package/dist/ui/placement/launcher_drag.d.ts +49 -0
- package/dist/ui/placement/launcher_drag.d.ts.map +1 -0
- package/dist/ui/placement/launcher_placement.d.ts +77 -0
- package/dist/ui/placement/launcher_placement.d.ts.map +1 -0
- package/dist/ui/placement/launcher_styles.d.ts +2 -0
- package/dist/ui/placement/launcher_styles.d.ts.map +1 -0
- package/dist/ui/placement/page_styles.d.ts +2 -0
- package/dist/ui/placement/page_styles.d.ts.map +1 -0
- package/dist/ui/placement/panel_drag.d.ts +40 -0
- package/dist/ui/placement/panel_drag.d.ts.map +1 -0
- package/dist/ui/placement/panel_placement.d.ts +173 -0
- package/dist/ui/placement/panel_placement.d.ts.map +1 -0
- package/dist/ui/placement/place_widget.d.ts +31 -0
- package/dist/ui/placement/place_widget.d.ts.map +1 -0
- package/dist/ui/placement/preset_styles.d.ts +2 -0
- package/dist/ui/placement/preset_styles.d.ts.map +1 -0
- package/dist/ui/placement/resize_handle.d.ts +78 -0
- package/dist/ui/placement/resize_handle.d.ts.map +1 -0
- package/dist/ui/placement/resize_styles.d.ts +2 -0
- package/dist/ui/placement/resize_styles.d.ts.map +1 -0
- package/dist/ui/placement/sidebar_styles.d.ts +2 -0
- package/dist/ui/placement/sidebar_styles.d.ts.map +1 -0
- package/dist/ui/placement/small_viewport_styles.d.ts +2 -0
- package/dist/ui/placement/small_viewport_styles.d.ts.map +1 -0
- package/dist/ui/placement/surface_for.d.ts +93 -0
- package/dist/ui/placement/surface_for.d.ts.map +1 -0
- package/dist/ui/progress/prettify_tool_name.d.ts +11 -0
- package/dist/ui/progress/prettify_tool_name.d.ts.map +1 -0
- package/dist/ui/progress/run_announcer.d.ts +41 -0
- package/dist/ui/progress/run_announcer.d.ts.map +1 -0
- package/dist/ui/progress/run_notice.d.ts +21 -0
- package/dist/ui/progress/run_notice.d.ts.map +1 -0
- package/dist/ui/progress/run_notice_styles.d.ts +2 -0
- package/dist/ui/progress/run_notice_styles.d.ts.map +1 -0
- package/dist/ui/progress/subagent_panel.d.ts +101 -0
- package/dist/ui/progress/subagent_panel.d.ts.map +1 -0
- package/dist/ui/progress/subagent_progress.d.ts +57 -0
- package/dist/ui/progress/subagent_progress.d.ts.map +1 -0
- package/dist/ui/progress/subagent_update.d.ts +28 -0
- package/dist/ui/progress/subagent_update.d.ts.map +1 -0
- package/dist/ui/progress/thoughts_block.d.ts +57 -0
- package/dist/ui/progress/thoughts_block.d.ts.map +1 -0
- package/dist/ui/progress/thoughts_styles.d.ts +2 -0
- package/dist/ui/progress/thoughts_styles.d.ts.map +1 -0
- package/dist/ui/progress/tool_call_card.d.ts +167 -0
- package/dist/ui/progress/tool_call_card.d.ts.map +1 -0
- package/dist/ui/progress/tool_group_styles.d.ts +2 -0
- package/dist/ui/progress/tool_group_styles.d.ts.map +1 -0
- package/dist/ui/progress/tool_step_group.d.ts +50 -0
- package/dist/ui/progress/tool_step_group.d.ts.map +1 -0
- package/dist/ui/progress/tool_step_styles.d.ts +2 -0
- package/dist/ui/progress/tool_step_styles.d.ts.map +1 -0
- package/dist/ui/shell/adopt_styles.d.ts +28 -0
- package/dist/ui/shell/adopt_styles.d.ts.map +1 -0
- package/dist/ui/shell/build_header.d.ts +45 -0
- package/dist/ui/shell/build_header.d.ts.map +1 -0
- package/dist/ui/shell/build_launcher.d.ts +33 -0
- package/dist/ui/shell/build_launcher.d.ts.map +1 -0
- package/dist/ui/shell/collapse_glyph.d.ts +14 -0
- package/dist/ui/shell/collapse_glyph.d.ts.map +1 -0
- package/dist/ui/shell/frame_styles.d.ts +2 -0
- package/dist/ui/shell/frame_styles.d.ts.map +1 -0
- package/dist/ui/shell/glyph_slot.d.ts +7 -0
- package/dist/ui/shell/glyph_slot.d.ts.map +1 -0
- package/dist/ui/shell/header_button.d.ts +11 -0
- package/dist/ui/shell/header_button.d.ts.map +1 -0
- package/dist/ui/shell/icon_element.d.ts +12 -0
- package/dist/ui/shell/icon_element.d.ts.map +1 -0
- package/dist/ui/shell/is_unread_badge_enabled.d.ts +10 -0
- package/dist/ui/shell/is_unread_badge_enabled.d.ts.map +1 -0
- package/dist/ui/shell/read_launcher_icon_url.d.ts +8 -0
- package/dist/ui/shell/read_launcher_icon_url.d.ts.map +1 -0
- package/dist/ui/shell/theme_styles.d.ts +2 -0
- package/dist/ui/shell/theme_styles.d.ts.map +1 -0
- package/dist/ui/shell/token_styles.d.ts +2 -0
- package/dist/ui/shell/token_styles.d.ts.map +1 -0
- package/dist/ui/styles.d.ts +2 -0
- package/dist/ui/styles.d.ts.map +1 -0
- package/dist/ui/themes/classic_styles.d.ts +2 -0
- package/dist/ui/themes/classic_styles.d.ts.map +1 -0
- package/dist/ui/themes/classic_tokens.d.ts +2 -0
- package/dist/ui/themes/classic_tokens.d.ts.map +1 -0
- package/dist/ui/themes/code_tokens.d.ts +2 -0
- package/dist/ui/themes/code_tokens.d.ts.map +1 -0
- package/dist/ui/themes/ledger_styles.d.ts +2 -0
- package/dist/ui/themes/ledger_styles.d.ts.map +1 -0
- package/dist/ui/themes/ledger_tokens.d.ts +2 -0
- package/dist/ui/themes/ledger_tokens.d.ts.map +1 -0
- package/dist/ui/themes/modern_styles.d.ts +2 -0
- package/dist/ui/themes/modern_styles.d.ts.map +1 -0
- package/dist/ui/themes/quiet_styles.d.ts +2 -0
- package/dist/ui/themes/quiet_styles.d.ts.map +1 -0
- package/dist/ui/themes/scheme_styles.d.ts +2 -0
- package/dist/ui/themes/scheme_styles.d.ts.map +1 -0
- package/dist/ui/themes/soft_styles.d.ts +2 -0
- package/dist/ui/themes/soft_styles.d.ts.map +1 -0
- package/dist/ui/themes/soft_tokens.d.ts +2 -0
- package/dist/ui/themes/soft_tokens.d.ts.map +1 -0
- package/dist/ui/themes/theme_hosts.d.ts +15 -0
- package/dist/ui/themes/theme_hosts.d.ts.map +1 -0
- package/dist/ui/transcript/answer_actions.d.ts +50 -0
- package/dist/ui/transcript/answer_actions.d.ts.map +1 -0
- package/dist/ui/transcript/answer_stream.d.ts +56 -0
- package/dist/ui/transcript/answer_stream.d.ts.map +1 -0
- package/dist/ui/transcript/attachment_chip_styles.d.ts +2 -0
- package/dist/ui/transcript/attachment_chip_styles.d.ts.map +1 -0
- package/dist/ui/transcript/attachment_chips.d.ts +21 -0
- package/dist/ui/transcript/attachment_chips.d.ts.map +1 -0
- package/dist/ui/transcript/build_transcript.d.ts +21 -0
- package/dist/ui/transcript/build_transcript.d.ts.map +1 -0
- package/dist/ui/transcript/greeting_styles.d.ts +2 -0
- package/dist/ui/transcript/greeting_styles.d.ts.map +1 -0
- package/dist/ui/transcript/groups_tool_steps.d.ts +13 -0
- package/dist/ui/transcript/groups_tool_steps.d.ts.map +1 -0
- package/dist/ui/transcript/message_action_styles.d.ts +2 -0
- package/dist/ui/transcript/message_action_styles.d.ts.map +1 -0
- package/dist/ui/transcript/message_actions.d.ts +74 -0
- package/dist/ui/transcript/message_actions.d.ts.map +1 -0
- package/dist/ui/transcript/message_styles.d.ts +2 -0
- package/dist/ui/transcript/message_styles.d.ts.map +1 -0
- package/dist/ui/transcript/render_markdown.d.ts +40 -0
- package/dist/ui/transcript/render_markdown.d.ts.map +1 -0
- package/dist/ui/transcript/render_or_warn.d.ts +16 -0
- package/dist/ui/transcript/render_or_warn.d.ts.map +1 -0
- package/dist/ui/transcript/reveal_words.d.ts +8 -0
- package/dist/ui/transcript/reveal_words.d.ts.map +1 -0
- package/dist/ui/transcript/starter_chips.d.ts +21 -0
- package/dist/ui/transcript/starter_chips.d.ts.map +1 -0
- package/dist/ui/transcript/stick_to_bottom.d.ts +55 -0
- package/dist/ui/transcript/stick_to_bottom.d.ts.map +1 -0
- package/dist/ui/transcript/suggestion_chips.d.ts +29 -0
- package/dist/ui/transcript/suggestion_chips.d.ts.map +1 -0
- package/dist/ui/transcript/transcript.d.ts +196 -0
- package/dist/ui/transcript/transcript.d.ts.map +1 -0
- package/dist/ui/transcript/transcript_styles.d.ts +2 -0
- package/dist/ui/transcript/transcript_styles.d.ts.map +1 -0
- package/dist/ui/ui_strings.d.ts +352 -0
- package/dist/ui/ui_strings.d.ts.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/package.json +86 -3
- package/src/bundle.ts +2 -0
- package/src/chat.ts +2 -0
- package/src/constants.ts +650 -0
- package/src/core/activity_registration.ts +19 -0
- package/src/core/activity_registry.ts +133 -0
- package/src/core/activity_renderer.ts +19 -0
- package/src/core/ag_ui_chat.ts +3966 -0
- package/src/core/agui_client.ts +1028 -0
- package/src/core/attachment.ts +62 -0
- package/src/core/chat_registry.ts +53 -0
- package/src/core/client_seed.ts +27 -0
- package/src/core/conversation_store.ts +478 -0
- package/src/core/create_http_agent.ts +97 -0
- package/src/core/define_chat.ts +25 -0
- package/src/core/events/attachments_detail.ts +9 -0
- package/src/core/events/bar_height_detail.ts +5 -0
- package/src/core/events/custom_agent_detail.ts +7 -0
- package/src/core/events/dock_width_detail.ts +7 -0
- package/src/core/events/feedback_detail.ts +27 -0
- package/src/core/events/invalidate_detail.ts +15 -0
- package/src/core/events/maximize_detail.ts +4 -0
- package/src/core/events/run_finished_detail.ts +36 -0
- package/src/core/events/state_detail.ts +4 -0
- package/src/core/events/submit_detail.ts +8 -0
- package/src/core/events/thread_detail.ts +26 -0
- package/src/core/events/thread_title_detail.ts +7 -0
- package/src/core/events/toggle_detail.ts +4 -0
- package/src/core/events/tool_run.ts +10 -0
- package/src/core/events/unread_detail.ts +10 -0
- package/src/core/message_role.ts +4 -0
- package/src/core/read_flag.ts +13 -0
- package/src/core/read_json_attribute.ts +30 -0
- package/src/core/read_max_tool_rounds.ts +13 -0
- package/src/core/remote_conversation_store.ts +279 -0
- package/src/core/run_handlers.ts +524 -0
- package/src/core/run_index.ts +114 -0
- package/src/core/storage_scope.ts +291 -0
- package/src/core/tool_outcome.ts +39 -0
- package/src/core/transcribe_audio.ts +76 -0
- package/src/core/upload_attachment.ts +130 -0
- package/src/core/utils.ts +230 -0
- package/src/dom/animations.ts +341 -0
- package/src/dom/dom_driver.ts +91 -0
- package/src/dom/highlight_overlay.ts +204 -0
- package/src/dom/native_setter.ts +40 -0
- package/src/dom/ring_color.ts +206 -0
- package/src/dom/utils.ts +5 -0
- package/src/index.ts +220 -0
- package/src/skills/fill_template.ts +31 -0
- package/src/skills/parse_skills.ts +31 -0
- package/src/skills/skill.ts +32 -0
- package/src/skills/skill_catalog.ts +172 -0
- package/src/skills/skill_name_from.ts +19 -0
- package/src/tools/chat_surface_tools.ts +183 -0
- package/src/tools/client_tool_registry.ts +80 -0
- package/src/tools/is_destructive.ts +17 -0
- package/src/tools/is_navigates.ts +12 -0
- package/src/tools/page_action_tools.ts +123 -0
- package/src/tools/page_map.ts +26 -0
- package/src/tools/page_state.ts +57 -0
- package/src/tools/parse_tool_catalog.ts +41 -0
- package/src/tools/route_map.ts +132 -0
- package/src/tools/tool_catalog.ts +334 -0
- package/src/tools/tool_dispatch.ts +453 -0
- package/src/ui/charts/chart_block.ts +519 -0
- package/src/ui/charts/chart_spec_from.ts +125 -0
- package/src/ui/charts/chart_styles.ts +63 -0
- package/src/ui/charts/chart_tool.ts +72 -0
- package/src/ui/composer/attachment_styles.ts +71 -0
- package/src/ui/composer/attachment_tray.ts +295 -0
- package/src/ui/composer/auto_grow.ts +12 -0
- package/src/ui/composer/build_composer.ts +114 -0
- package/src/ui/composer/composer_attachments.ts +324 -0
- package/src/ui/composer/composer_styles.ts +177 -0
- package/src/ui/composer/composer_voice.ts +93 -0
- package/src/ui/composer/skill_styles.ts +120 -0
- package/src/ui/composer/skills_menu.ts +188 -0
- package/src/ui/composer/voice_input.ts +282 -0
- package/src/ui/excerpts/attach_copy_buttons.ts +73 -0
- package/src/ui/excerpts/copy_payload.ts +156 -0
- package/src/ui/excerpts/page_quote_offer.ts +203 -0
- package/src/ui/excerpts/place_offer.ts +24 -0
- package/src/ui/excerpts/quote_selection.ts +345 -0
- package/src/ui/excerpts/transcript_quote_offer.ts +175 -0
- package/src/ui/fill_ui_string.ts +41 -0
- package/src/ui/history/checkpoint_menu.ts +300 -0
- package/src/ui/history/conversation_history.ts +1169 -0
- package/src/ui/history/history_styles.ts +492 -0
- package/src/ui/history/relative_time.ts +50 -0
- package/src/ui/history/thread_drawer.ts +471 -0
- package/src/ui/history/utils.ts +11 -0
- package/src/ui/interrupts/approval_card.ts +202 -0
- package/src/ui/interrupts/approval_styles.ts +52 -0
- package/src/ui/interrupts/confirmation_card.ts +138 -0
- package/src/ui/interrupts/confirmation_styles.ts +114 -0
- package/src/ui/interrupts/pending_decision.ts +33 -0
- package/src/ui/interrupts/question_card.ts +213 -0
- package/src/ui/interrupts/question_styles.ts +73 -0
- package/src/ui/place/place.ts +16 -0
- package/src/ui/place/place_chip.ts +146 -0
- package/src/ui/place/place_from_route.ts +27 -0
- package/src/ui/place/place_styles.ts +108 -0
- package/src/ui/placement/clamp_launcher.ts +38 -0
- package/src/ui/placement/clamp_panel.ts +30 -0
- package/src/ui/placement/collapse_styles.ts +472 -0
- package/src/ui/placement/dock_styles.ts +116 -0
- package/src/ui/placement/embedded_styles.ts +14 -0
- package/src/ui/placement/launcher_drag.ts +206 -0
- package/src/ui/placement/launcher_placement.ts +133 -0
- package/src/ui/placement/launcher_styles.ts +189 -0
- package/src/ui/placement/page_styles.ts +47 -0
- package/src/ui/placement/panel_drag.ts +138 -0
- package/src/ui/placement/panel_placement.ts +1975 -0
- package/src/ui/placement/place_widget.ts +64 -0
- package/src/ui/placement/preset_styles.ts +49 -0
- package/src/ui/placement/resize_handle.ts +229 -0
- package/src/ui/placement/resize_styles.ts +201 -0
- package/src/ui/placement/sidebar_styles.ts +113 -0
- package/src/ui/placement/small_viewport_styles.ts +70 -0
- package/src/ui/placement/surface_for.ts +183 -0
- package/src/ui/progress/prettify_tool_name.ts +16 -0
- package/src/ui/progress/run_announcer.ts +67 -0
- package/src/ui/progress/run_notice.ts +61 -0
- package/src/ui/progress/run_notice_styles.ts +52 -0
- package/src/ui/progress/subagent_panel.ts +227 -0
- package/src/ui/progress/subagent_progress.ts +200 -0
- package/src/ui/progress/subagent_update.ts +89 -0
- package/src/ui/progress/thoughts_block.ts +165 -0
- package/src/ui/progress/thoughts_styles.ts +74 -0
- package/src/ui/progress/tool_call_card.ts +429 -0
- package/src/ui/progress/tool_group_styles.ts +313 -0
- package/src/ui/progress/tool_step_group.ts +317 -0
- package/src/ui/progress/tool_step_styles.ts +486 -0
- package/src/ui/shell/adopt_styles.ts +34 -0
- package/src/ui/shell/build_header.ts +121 -0
- package/src/ui/shell/build_launcher.ts +79 -0
- package/src/ui/shell/collapse_glyph.ts +42 -0
- package/src/ui/shell/frame_styles.ts +147 -0
- package/src/ui/shell/glyph_slot.ts +12 -0
- package/src/ui/shell/header_button.ts +22 -0
- package/src/ui/shell/icon_element.ts +33 -0
- package/src/ui/shell/is_unread_badge_enabled.ts +11 -0
- package/src/ui/shell/read_launcher_icon_url.ts +9 -0
- package/src/ui/shell/theme_styles.ts +11 -0
- package/src/ui/shell/token_styles.ts +480 -0
- package/src/ui/styles.ts +110 -0
- package/src/ui/themes/classic_styles.ts +32 -0
- package/src/ui/themes/classic_tokens.ts +51 -0
- package/src/ui/themes/code_tokens.ts +21 -0
- package/src/ui/themes/ledger_styles.ts +169 -0
- package/src/ui/themes/ledger_tokens.ts +33 -0
- package/src/ui/themes/modern_styles.ts +80 -0
- package/src/ui/themes/quiet_styles.ts +118 -0
- package/src/ui/themes/scheme_styles.ts +26 -0
- package/src/ui/themes/soft_styles.ts +149 -0
- package/src/ui/themes/soft_tokens.ts +29 -0
- package/src/ui/themes/theme_hosts.ts +14 -0
- package/src/ui/transcript/answer_actions.ts +165 -0
- package/src/ui/transcript/answer_stream.ts +123 -0
- package/src/ui/transcript/attachment_chip_styles.ts +116 -0
- package/src/ui/transcript/attachment_chips.ts +82 -0
- package/src/ui/transcript/build_transcript.ts +67 -0
- package/src/ui/transcript/greeting_styles.ts +171 -0
- package/src/ui/transcript/groups_tool_steps.ts +16 -0
- package/src/ui/transcript/message_action_styles.ts +155 -0
- package/src/ui/transcript/message_actions.ts +234 -0
- package/src/ui/transcript/message_styles.ts +262 -0
- package/src/ui/transcript/render_markdown.ts +181 -0
- package/src/ui/transcript/render_or_warn.ts +22 -0
- package/src/ui/transcript/reveal_words.ts +41 -0
- package/src/ui/transcript/starter_chips.ts +42 -0
- package/src/ui/transcript/stick_to_bottom.ts +126 -0
- package/src/ui/transcript/suggestion_chips.ts +73 -0
- package/src/ui/transcript/transcript.ts +555 -0
- package/src/ui/transcript/transcript_styles.ts +153 -0
- package/src/ui/ui_strings.ts +550 -0
- 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
|
+
}
|