diff --git a/packages/agents-manager/src/components/agent-dock/index.tsx b/packages/agents-manager/src/components/agent-dock/index.tsx index 093d158f6960..8585d730ba5b 100644 --- a/packages/agents-manager/src/components/agent-dock/index.tsx +++ b/packages/agents-manager/src/components/agent-dock/index.tsx @@ -10,9 +10,11 @@ import { } from '@automattic/agenttic-ui'; import { useManagedOdieChat } from '@automattic/odie-client'; import { useDispatch, useSelect } from '@wordpress/data'; +import { useState, useMemo } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { comment, drawerRight, login } from '@wordpress/icons'; import { Routes, Route, Navigate, useLocation, useNavigate } from 'react-router-dom'; +import { LOCAL_TOOL_RUNNING_MESSAGE } from '../../constants'; import useAdminBarIntegration from '../../hooks/use-admin-bar-integration'; import useAgentLayoutManager from '../../hooks/use-agent-layout-manager'; import useConversation from '../../hooks/use-conversation'; @@ -46,7 +48,7 @@ interface AgentDockProps { markdownExtensions?: MarkdownExtensions; /** Navigation continuation hook for post-navigation conversation resumption. */ useNavigationContinuation?: NavigationContinuationHook; - /** Setup hook to register hook-dependent abilities. */ + /** Hook for setting up abilities that utilize React context. Invoked after custom actions registration. */ useAbilitiesSetup?: AbilitiesSetupHook; } @@ -61,6 +63,8 @@ export default function AgentDock( { useNavigationContinuation, useAbilitiesSetup, }: AgentDockProps ) { + const [ isThinking, setIsThinking ] = useState( false ); + const [ deletedMessageIds, setDeletedMessageIds ] = useState< Set< string > >( new Set() ); const { setIsOpen, setIsDocked } = useDispatch( AGENTS_MANAGER_STORE ); const { hasLoaded: isStoreReady, @@ -86,6 +90,7 @@ export default function AgentDock( { } ); const { + addMessage, messages, suggestions, isProcessing, @@ -93,6 +98,7 @@ export default function AgentDock( { loadMessages, onSubmit, abortCurrentRequest, + clearSuggestions, } = useAgentChat( agentConfig ); const { @@ -136,9 +142,20 @@ export default function AgentDock( { navigate, } ); - // Call setup hook to register hook-dependent abilities - // The hook is stable after loadedProviders is set (AgentDock only renders after providers load) - useAbilitiesSetup?.(); + // Invoke abilities setup hook to register hook-based abilities that utilize React context. + // Provides custom action handlers for agent and chat interaction within Big Sky's AI store. + // The hook is stable as `AgentDock` only renders after external providers have been loaded. + useAbilitiesSetup?.( { + addMessage, + clearSuggestions, + getAgentManager, + setIsThinking, + deleteMarkedMessages: ( msgs ) => { + setDeletedMessageIds( + ( prevIds ) => new Set( [ ...prevIds, ...msgs.map( ( msg ) => msg.id ) ] ) + ); + }, + } ); const handleNewChat = () => { navigate( '/' ); @@ -161,13 +178,6 @@ export default function AgentDock( { icon: login, title: __( 'Pop out sidebar', '__i18n_text_domain__' ), onClick: () => { - // TODO: Persist floating chat position... - try { - window.localStorage?.setItem( 'agenttic-chat-position', 'right' ); - } catch ( err ) { - // Ignore errors - } - undock(); setIsDocked( false ); }, @@ -192,11 +202,23 @@ export default function AgentDock( { return options; }; + // Filter out deleted messages and local tool running messages + const visibleMessages = useMemo( + () => + messages.filter( + ( message ) => + ! deletedMessageIds.has( message.id ) && + ! message.content?.some( ( content ) => content?.text === LOCAL_TOOL_RUNNING_MESSAGE ) + ), + [ messages, deletedMessageIds ] + ); + const Chat = ( ); diff --git a/packages/agents-manager/src/constants.ts b/packages/agents-manager/src/constants.ts index 8bbb6db3ceec..b9a9260d28a9 100644 --- a/packages/agents-manager/src/constants.ts +++ b/packages/agents-manager/src/constants.ts @@ -2,3 +2,5 @@ export const API_BASE_URL = 'https://public-api.wordpress.com'; export const ORCHESTRATOR_AGENT_URL = `${ API_BASE_URL }/wpcom/v2/ai/agent`; export const ORCHESTRATOR_AGENT_ID = 'wp-orchestrator'; + +export const LOCAL_TOOL_RUNNING_MESSAGE = 'local_tool_running'; diff --git a/packages/agents-manager/src/hooks/use-agent-layout-manager/style.scss b/packages/agents-manager/src/hooks/use-agent-layout-manager/style.scss index c128ffdeb759..69ad897aa05d 100644 --- a/packages/agents-manager/src/hooks/use-agent-layout-manager/style.scss +++ b/packages/agents-manager/src/hooks/use-agent-layout-manager/style.scss @@ -66,8 +66,8 @@ $agents-manager-z-index-docked: 999999; } // Reposition the editor's template save confirmation panel -@mixin editor-save-panel-open( $save-panel-selector ) { - #{$save-panel-selector} { +@mixin editor-save-panel-open() { + .admin-ui-navigable-region.interface-interface-skeleton__actions { margin: $layout-spacing 0; right: $sidebar-width; overflow: hidden; @@ -258,9 +258,7 @@ body.next-admin.agents-manager-sidebar-container { &.agents-manager-sidebar-container--sidebar-open { @include sidebar-open-base( '.next-admin-layout__canvas.is-full-canvas' ); - @include editor-save-panel-open( - '.admin-ui-navigable-region.interface-interface-skeleton__actions' - ); + @include editor-save-panel-open(); } } @@ -275,9 +273,7 @@ body.site-editor-php.agents-manager-sidebar-container { &.agents-manager-sidebar-container--sidebar-open { @include sidebar-open-base( '.edit-site-layout__canvas' ); - @include editor-save-panel-open( - '.interface-navigable-region.interface-interface-skeleton__actions' - ); + @include editor-save-panel-open(); // Override canvas styles when the site editor navigation menu is open .edit-site-layout:not( .is-full-canvas ) .edit-site-layout__canvas { @@ -297,9 +293,7 @@ body.post-php.agents-manager-sidebar-container { &.agents-manager-sidebar-container--sidebar-open { @include sidebar-open-base( '.edit-post-layout' ); - @include editor-save-panel-open( - '.interface-navigable-region.interface-interface-skeleton__actions' - ); + @include editor-save-panel-open(); } } @@ -506,8 +500,6 @@ body.post-php.agents-manager-sidebar-container { .edit-site-global-styles-variations_item-preview { outline: 1px solid $gray-400; outline-offset: 1px; - outline-color: #ccc; - outline-width: -wp-admin-border-width-focus; } } @@ -518,7 +510,7 @@ body.post-php.agents-manager-sidebar-container { } .edit-site-global-styles-variations_item-preview { - outline-color: #545454; + outline: 1px solid #545454; overflow: hidden; } } @@ -696,4 +688,24 @@ body.post-php.agents-manager-sidebar-container { .agents-manager-chat--undocked .agenttic.Chat-module_container.Chat-module_floating { // Fix the undocked chat overlapping with the nav menu z-index: 9999; + + .big-sky__dock__menu__variation-picker .edit-site-global-styles-variations_item { + &.is-active, + &:focus-visible { + .edit-site-global-styles-variations_item-preview { + outline: 1px solid #0000001a; + } + } + + &:not( .is-active ):hover { + .edit-site-global-styles-variations_item-preview { + outline-color: #00000080; + } + } + + .edit-site-global-styles-variations_item-preview { + outline: 1px solid #0000004d; + overflow: hidden; + } + } } diff --git a/packages/agents-manager/src/utils/load-external-providers.ts b/packages/agents-manager/src/utils/load-external-providers.ts index a07f37538939..2a055f5ae39d 100644 --- a/packages/agents-manager/src/utils/load-external-providers.ts +++ b/packages/agents-manager/src/utils/load-external-providers.ts @@ -5,8 +5,9 @@ * PHP filter. Each provider module should export toolProvider and/or contextProvider. */ +import { getAgentManager } from '@automattic/agenttic-client'; import type { ToolProvider, ContextProvider, Suggestion } from '../types'; -import type { SubmitOptions } from '@automattic/agenttic-client'; +import type { SubmitOptions, UseAgentChatReturn } from '@automattic/agenttic-client'; import type { MarkdownComponents, MarkdownExtensions } from '@automattic/agenttic-ui'; /** @@ -14,7 +15,6 @@ import type { MarkdownComponents, MarkdownExtensions } from '@automattic/agentti * * This is used on wp-admin environments (Atomic, Garden, Simple sites) where * the flag is injected server-side by Jetpack's Agents Manager. - * * @returns The useUnifiedExperience value, or undefined if not available. */ export function getUseUnifiedExperienceFromInlineData(): boolean | undefined { @@ -37,11 +37,17 @@ export type NavigationContinuationHook = ( props: { } ) => void; /** - * Abilities setup hook type - provided by environments that need to register - * hook-dependent abilities (abilities that require React context to work). - * Called from AgentDock component to provide React context. + * Abilities setup hook type - for registering hook-based abilities that utilize React + * context. Invoked after custom actions registration with Big Sky's AI store. Receives + * action handlers that will be used for agent and chat interaction. */ -export type AbilitiesSetupHook = () => void; +export type AbilitiesSetupHook = ( actions: { + addMessage: UseAgentChatReturn[ 'addMessage' ]; + clearSuggestions: UseAgentChatReturn[ 'clearSuggestions' ]; + getAgentManager: typeof getAgentManager; + setIsThinking: ( isThinking: boolean ) => void; + deleteMarkedMessages: ( messages: Record< 'id', string >[] ) => void; +} ) => void; export interface LoadedProviders { toolProvider?: ToolProvider;