From 0b3d9a2c997c705f12686a20638ca74f0d5fc392 Mon Sep 17 00:00:00 2001 From: Douglas Date: Wed, 1 May 2024 14:31:28 -0300 Subject: [PATCH 1/7] remove block ref --- .../ai-assistant/inline-extensions/with-ai-extension.tsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/with-ai-extension.tsx b/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/with-ai-extension.tsx index a56e504aa1f14..05d096a04e3ab 100644 --- a/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/with-ai-extension.tsx +++ b/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/with-ai-extension.tsx @@ -36,7 +36,6 @@ const blockEditWithAiComponents = createHigherOrderComponent( BlockEdit => { const controlRef: React.MutableRefObject< HTMLDivElement | null > = useRef( null ); const controlObserver = useRef< ResizeObserver | null >( null ); const blockStyle = useRef< string >( '' ); - const [ block, setBlock ] = useState< HTMLElement | null >( null ); // Only extend the allowed block types. const possibleToExtendBlock = isPossibleToExtendBlock( { @@ -91,11 +90,8 @@ const blockEditWithAiComponents = createHigherOrderComponent( BlockEdit => { const { id } = useBlockProps(); useEffect( () => { - // Keep the block reference. - setBlock( document.getElementById( id ) ); - }, [ id ] ); + const block = document.getElementById( id ); - useEffect( () => { if ( ! block ) { return; } @@ -123,7 +119,7 @@ const blockEditWithAiComponents = createHigherOrderComponent( BlockEdit => { controlObserver.current.disconnect(); controlObserver.current = null; } - }, [ block, clientId, controlObserver, id, showAiControl ] ); + }, [ clientId, controlObserver, id, showAiControl ] ); // Only extend the target block. if ( ! possibleToExtendBlock ) { From 7629e45af1558585b07ef7b7bb9507d70af0a7de Mon Sep 17 00:00:00 2001 From: Douglas Date: Wed, 1 May 2024 16:26:20 -0300 Subject: [PATCH 2/7] fix input state --- .../components/ai-assistant-input/index.tsx | 11 ++++++- .../inline-extensions/with-ai-extension.tsx | 29 ++++++++++++------- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/components/ai-assistant-input/index.tsx b/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/components/ai-assistant-input/index.tsx index 0d4ef1edbc686..9ecb83c52834f 100644 --- a/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/components/ai-assistant-input/index.tsx +++ b/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/components/ai-assistant-input/index.tsx @@ -2,7 +2,8 @@ * External dependencies */ import { ExtensionAIControl } from '@automattic/jetpack-ai-client'; -import { useState } from '@wordpress/element'; +import { useState, useEffect } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; import React from 'react'; /* * Types @@ -52,8 +53,16 @@ export default function AiAssistantInput( { throw new Error( 'Function not implemented.' ); } + // Clear the input value on reset and when the request is done. + useEffect( () => { + if ( [ 'init', 'done' ].includes( requestingState ) ) { + setValue( '' ); + } + }, [ requestingState ] ); + return ( { // Data and functions with block-specific implementations. const { onSuggestion } = blockHandler( blockName, clientId ); - const { request, stopSuggestion, requestingState, error, suggestion } = useAiSuggestions( { + const { + request, + stopSuggestion, + requestingState, + error, + suggestion, + reset: resetSuggestions, + } = useAiSuggestions( { onSuggestion, onDone, onError, @@ -79,14 +86,6 @@ const blockEditWithAiComponents = createHigherOrderComponent( BlockEdit => { }, } ); - // Close the AI Control if the block is deselected. - useEffect( () => { - if ( ! isSelected ) { - setShowAiControl( false ); - // TODO: reset all extension data. - } - }, [ isSelected ] ); - const { id } = useBlockProps(); useEffect( () => { @@ -141,9 +140,17 @@ const blockEditWithAiComponents = createHigherOrderComponent( BlockEdit => { debug( 'onRequestSuggestion', promptType, options ); }; - const onClose = () => { + const onClose = useCallback( () => { setShowAiControl( false ); - }; + resetSuggestions(); + }, [ resetSuggestions ] ); + + // Close the AI Control if the block is deselected. + useEffect( () => { + if ( ! isSelected ) { + onClose(); + } + }, [ isSelected, onClose ] ); const onUndo = () => { // TODO: handle the undo action. From 566f33429eec817be7ddbfa4ad6f9daa220952a0 Mon Sep 17 00:00:00 2001 From: Douglas Date: Wed, 1 May 2024 17:26:53 -0300 Subject: [PATCH 3/7] show quick action text on input --- .../dropdown-content.tsx | 28 ++++++--- .../i18n-dropdown-control/index.tsx | 30 ++++------ .../tone-dropdown-control/index.tsx | 60 ++----------------- .../components/ai-assistant-input/index.tsx | 7 +++ .../ai-assistant-toolbar-dropdown/index.tsx | 4 +- .../inline-extensions/with-ai-extension.tsx | 11 +++- .../ai-assistant/lib/utils/capitalize.ts | 7 +++ 7 files changed, 65 insertions(+), 82 deletions(-) create mode 100644 projects/plugins/jetpack/extensions/blocks/ai-assistant/lib/utils/capitalize.ts diff --git a/projects/plugins/jetpack/extensions/blocks/ai-assistant/components/ai-assistant-toolbar-dropdown/dropdown-content.tsx b/projects/plugins/jetpack/extensions/blocks/ai-assistant/components/ai-assistant-toolbar-dropdown/dropdown-content.tsx index 88c5ad2927f4a..f17b9ebee6c8b 100644 --- a/projects/plugins/jetpack/extensions/blocks/ai-assistant/components/ai-assistant-toolbar-dropdown/dropdown-content.tsx +++ b/projects/plugins/jetpack/extensions/blocks/ai-assistant/components/ai-assistant-toolbar-dropdown/dropdown-content.tsx @@ -18,8 +18,9 @@ import { PROMPT_TYPE_CHANGE_LANGUAGE, PROMPT_TYPE_USER_PROMPT, } from '../../lib/prompt'; -import { I18nMenuDropdown } from '../i18n-dropdown-control'; -import { ToneDropdownMenu } from '../tone-dropdown-control'; +import { capitalize } from '../../lib/utils/capitalize'; +import { I18nMenuDropdown, TRANSLATE_LABEL } from '../i18n-dropdown-control'; +import { TONE_LABEL, ToneDropdownMenu } from '../tone-dropdown-control'; import './style.scss'; /** * Types and constants @@ -112,7 +113,8 @@ export type AiAssistantDropdownOnChangeOptionsArgProps = { export type OnRequestSuggestion = ( promptType: PromptTypeProp, - options?: AiAssistantDropdownOnChangeOptionsArgProps + options?: AiAssistantDropdownOnChangeOptionsArgProps, + humanText?: string ) => void; type AiAssistantToolbarDropdownContentProps = { @@ -162,7 +164,11 @@ export default function AiAssistantToolbarDropdownContent( { iconPosition="left" key={ `key-${ quickAction.key }` } onClick={ () => { - onRequestSuggestion( quickAction.aiSuggestion, { ...( quickAction.options ?? {} ) } ); + onRequestSuggestion( + quickAction.aiSuggestion, + { ...( quickAction.options ?? {} ) }, + quickAction.name + ); } } disabled={ disabled } > @@ -172,14 +178,22 @@ export default function AiAssistantToolbarDropdownContent( { { - onRequestSuggestion( PROMPT_TYPE_CHANGE_TONE, { tone } ); + onRequestSuggestion( + PROMPT_TYPE_CHANGE_TONE, + { tone }, + `${ TONE_LABEL }: ${ capitalize( tone ) }` + ); } } disabled={ disabled } /> { - onRequestSuggestion( PROMPT_TYPE_CHANGE_LANGUAGE, { language } ); + onChange={ ( language, name ) => { + onRequestSuggestion( + PROMPT_TYPE_CHANGE_LANGUAGE, + { language }, + `${ TRANSLATE_LABEL }: ${ name }` + ); } } disabled={ disabled } /> diff --git a/projects/plugins/jetpack/extensions/blocks/ai-assistant/components/i18n-dropdown-control/index.tsx b/projects/plugins/jetpack/extensions/blocks/ai-assistant/components/i18n-dropdown-control/index.tsx index 147f51b92ecc1..8307184f2eddb 100644 --- a/projects/plugins/jetpack/extensions/blocks/ai-assistant/components/i18n-dropdown-control/index.tsx +++ b/projects/plugins/jetpack/extensions/blocks/ai-assistant/components/i18n-dropdown-control/index.tsx @@ -13,6 +13,7 @@ import { import { __ } from '@wordpress/i18n'; import { Icon, chevronRight } from '@wordpress/icons'; import { globe } from '@wordpress/icons'; +import React from 'react'; /* * Internal dependencies */ @@ -38,7 +39,7 @@ export type LanguageProp = ( typeof LANGUAGE_LIST )[ number ]; type LanguageDropdownControlProps = { value?: LanguageProp; - onChange: ( value: string ) => void; + onChange: ( value: string, name?: string ) => void; label?: string; disabled?: boolean; }; @@ -46,7 +47,7 @@ type LanguageDropdownControlProps = { const defaultLanguageLocale = window?.Jetpack_Editor_Initial_State?.siteLocale || navigator?.language; -const defaultLabel = __( 'Translate', 'jetpack' ); +export const TRANSLATE_LABEL = __( 'Translate', 'jetpack' ); export const defaultLanguage = ( defaultLanguageLocale?.split( '-' )[ 0 ] || 'en' ) as LanguageProp; @@ -89,16 +90,6 @@ export const LANGUAGE_MAP = { ko: { label: __( 'Korean', 'jetpack' ), }, - - id: { - label: __( 'Indonesian', 'jetpack' ), - }, - tl: { - label: __( 'Filipino', 'jetpack' ), - }, - vi: { - label: __( 'Vietnamese', 'jetpack' ), - }, }; export const I18nMenuGroup = ( { @@ -117,7 +108,12 @@ export const I18nMenuGroup = ( { return ( onChange( language + ' (' + LANGUAGE_MAP[ language ].label + ')' ) } + onClick={ () => + onChange( + language + ' (' + LANGUAGE_MAP[ language ].label + ')', + LANGUAGE_MAP[ language ].label + ) + } isSelected={ value === language } > { LANGUAGE_MAP[ language ].label } @@ -130,7 +126,7 @@ export const I18nMenuGroup = ( { export default function I18nDropdownControl( { value = defaultLanguage, - label = defaultLabel, + label = TRANSLATE_LABEL, onChange, disabled = false, }: LanguageDropdownControlProps ) { @@ -164,7 +160,7 @@ export default function I18nDropdownControl( { export function I18nMenuDropdown( { value = defaultLanguage, - label = defaultLabel, + label = TRANSLATE_LABEL, onChange, disabled = false, }: Pick< LanguageDropdownControlProps, 'label' | 'onChange' | 'value' | 'disabled' > & { @@ -187,8 +183,8 @@ export function I18nMenuDropdown( { > { ( { onClose } ) => ( { - onChange( newLanguage ); + onChange={ ( ...args ) => { + onChange( ...args ); onClose(); } } value={ value } diff --git a/projects/plugins/jetpack/extensions/blocks/ai-assistant/components/tone-dropdown-control/index.tsx b/projects/plugins/jetpack/extensions/blocks/ai-assistant/components/tone-dropdown-control/index.tsx index e45244050f254..cf88111776f0c 100644 --- a/projects/plugins/jetpack/extensions/blocks/ai-assistant/components/tone-dropdown-control/index.tsx +++ b/projects/plugins/jetpack/extensions/blocks/ai-assistant/components/tone-dropdown-control/index.tsx @@ -14,6 +14,7 @@ import { } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { chevronRight } from '@wordpress/icons'; +import React from 'react'; /** * Internal dependencies */ @@ -23,27 +24,19 @@ const PROMPT_TONES_LIST = [ 'formal', 'informal', 'optimistic', - // 'pessimistic', 'humorous', 'serious', 'skeptical', 'empathetic', - // 'enthusiastic', - // 'neutral', 'confident', - // 'curious', - // 'respectful', 'passionate', - // 'cautious', 'provocative', - // 'inspirational', - // 'satirical', - // 'dramatic', - // 'mysterious', ] as const; export const DEFAULT_PROMPT_TONE = 'formal'; +export const TONE_LABEL = __( 'Change tone', 'jetpack' ); + export const PROMPT_TONES_MAP = { formal: { label: __( 'Formal', 'jetpack' ), @@ -57,10 +50,6 @@ export const PROMPT_TONES_MAP = { label: __( 'Optimistic', 'jetpack' ), emoji: '๐Ÿ˜ƒ', }, - // pessimistic: { - // label: __( 'Pessimistic', 'jetpack' ), - // emoji: 'โ˜น๏ธ', - // }, humorous: { label: __( 'Humorous', 'jetpack' ), emoji: '๐Ÿ˜‚', @@ -77,54 +66,18 @@ export const PROMPT_TONES_MAP = { label: __( 'Empathetic', 'jetpack' ), emoji: '๐Ÿ’—', }, - // enthusiastic: { - // label: __( 'Enthusiastic', 'jetpack' ), - // emoji: '๐Ÿคฉ', - // }, - // neutral: { - // label: __( 'Neutral', 'jetpack' ), - // emoji: '๐Ÿ˜ถ', - // }, confident: { label: __( 'Confident', 'jetpack' ), emoji: '๐Ÿ˜Ž', }, - // curious: { - // label: __( 'Curious', 'jetpack' ), - // emoji: '๐Ÿง', - // }, - // respectful: { - // label: __( 'Respectful', 'jetpack' ), - // emoji: '๐Ÿ™', - // }, passionate: { label: __( 'Passionate', 'jetpack' ), emoji: 'โค๏ธ', }, - // cautious: { - // label: __( 'Cautious', 'jetpack' ), - // emoji: '๐Ÿšง', - // }, provocative: { label: __( 'Provocative', 'jetpack' ), emoji: '๐Ÿ”ฅ', }, - // inspirational: { - // label: __( 'Inspirational', 'jetpack' ), - // emoji: 'โœจ', - // }, - // satirical: { - // label: __( 'Satirical', 'jetpack' ), - // emoji: '๐Ÿƒ', - // }, - // dramatic: { - // label: __( 'Dramatic', 'jetpack' ), - // emoji: '๐ŸŽญ', - // }, - // mysterious: { - // label: __( 'Mysterious', 'jetpack' ), - // emoji: '๐Ÿ”ฎ', - // }, }; export type ToneProp = ( typeof PROMPT_TONES_LIST )[ number ]; @@ -153,7 +106,7 @@ const ToneMenuGroup = ( { value, onChange }: ToneToolbarDropdownMenuProps ) => ( ); export function ToneDropdownMenu( { - label = __( 'Change tone', 'jetpack' ), + label = TONE_LABEL, value = DEFAULT_PROMPT_TONE, onChange, disabled = false, @@ -194,7 +147,6 @@ export default function ToneToolbarDropdownMenu( { onChange, disabled = false, }: ToneToolbarDropdownMenuProps ) { - const label = __( 'Change tone', 'jetpack' ); const { tracks } = useAnalytics(); const toggleHandler = isOpen => { @@ -204,7 +156,7 @@ export default function ToneToolbarDropdownMenu( { }; return disabled ? ( - + @@ -212,7 +164,7 @@ export default function ToneToolbarDropdownMenu( { ) : ( ; + action?: string; request: ( question: string ) => void; stopSuggestion?: () => void; close?: () => void; @@ -60,6 +62,11 @@ export default function AiAssistantInput( { } }, [ requestingState ] ); + // Set the value to the quick action text once it changes. + useEffect( () => { + setValue( action || '' ); + }, [ action ] ); + return ( { - onRequestSuggestion?.( promptType, options ); + const handleRequestSuggestion: OnRequestSuggestion = ( ...args ) => { + onRequestSuggestion?.( ...args ); onClose?.(); }; diff --git a/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/with-ai-extension.tsx b/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/with-ai-extension.tsx index 42d81d8fd860e..629fe17f3e087 100644 --- a/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/with-ai-extension.tsx +++ b/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/with-ai-extension.tsx @@ -36,6 +36,7 @@ const blockEditWithAiComponents = createHigherOrderComponent( BlockEdit => { const controlRef: React.MutableRefObject< HTMLDivElement | null > = useRef( null ); const controlObserver = useRef< ResizeObserver | null >( null ); const blockStyle = useRef< string >( '' ); + const [ action, setAction ] = useState< string >( '' ); // Only extend the allowed block types. const possibleToExtendBlock = isPossibleToExtendBlock( { @@ -134,15 +135,20 @@ const blockEditWithAiComponents = createHigherOrderComponent( BlockEdit => { setShowAiControl( true ); }; - const onRequestSuggestion: OnRequestSuggestion = ( promptType, options ) => { + const onRequestSuggestion: OnRequestSuggestion = ( promptType, options, humanText ) => { setShowAiControl( true ); + + if ( humanText ) { + setAction( humanText ); + } // TODO: handle the promptType and options to request the suggestion. - debug( 'onRequestSuggestion', promptType, options ); + debug( 'onRequestSuggestion', promptType, options, humanText ); }; const onClose = useCallback( () => { setShowAiControl( false ); resetSuggestions(); + setAction( '' ); }, [ resetSuggestions ] ); // Close the AI Control if the block is deselected. @@ -169,6 +175,7 @@ const blockEditWithAiComponents = createHigherOrderComponent( BlockEdit => { requestingError={ error } suggestion={ suggestion } wrapperRef={ controlRef } + action={ action } request={ request } stopSuggestion={ stopSuggestion } close={ onClose } diff --git a/projects/plugins/jetpack/extensions/blocks/ai-assistant/lib/utils/capitalize.ts b/projects/plugins/jetpack/extensions/blocks/ai-assistant/lib/utils/capitalize.ts new file mode 100644 index 0000000000000..d6bcdb9145fd8 --- /dev/null +++ b/projects/plugins/jetpack/extensions/blocks/ai-assistant/lib/utils/capitalize.ts @@ -0,0 +1,7 @@ +export function capitalize( text: string ) { + if ( ! text || typeof text !== 'string' ) { + return ''; + } + + return text.charAt( 0 ).toUpperCase() + text.slice( 1 ); +} From 58b0fc337af0b2b7d85f3a0a3418e7f4ab7d02a1 Mon Sep 17 00:00:00 2001 From: Douglas Date: Wed, 1 May 2024 18:10:22 -0300 Subject: [PATCH 4/7] add getContent to block handler --- .../ai-assistant/inline-extensions/block-handler.tsx | 1 + .../ai-assistant/inline-extensions/heading/index.tsx | 8 ++++++-- .../blocks/ai-assistant/inline-extensions/types.ts | 1 + .../ai-assistant/inline-extensions/with-ai-extension.tsx | 8 ++++++-- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/block-handler.tsx b/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/block-handler.tsx index 57eee1a4cb199..f8e9739d149ee 100644 --- a/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/block-handler.tsx +++ b/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/block-handler.tsx @@ -33,5 +33,6 @@ export function blockHandler( return { onSuggestion: handler.onSuggestion.bind( handler ), + getContent: handler.getContent.bind( handler ), }; } diff --git a/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/heading/index.tsx b/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/heading/index.tsx index 68bd951729293..c0191fcfe8661 100644 --- a/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/heading/index.tsx +++ b/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/heading/index.tsx @@ -2,7 +2,7 @@ * External dependencies */ import { renderMarkdownFromHTML, renderHTMLFromMarkdown } from '@automattic/jetpack-ai-client'; -import { rawHandler } from '@wordpress/blocks'; +import { rawHandler, getBlockContent } from '@wordpress/blocks'; import { select, dispatch } from '@wordpress/data'; /** * Types @@ -10,7 +10,7 @@ import { select, dispatch } from '@wordpress/data'; import type { BlockEditorSelect, IBlockHandler } from '../types'; import type { Block } from '@automattic/jetpack-ai-client'; -export function getContent( html ) { +export function getMarkdown( html ) { return renderMarkdownFromHTML( { content: html } ); } @@ -26,6 +26,10 @@ export class HeadingHandler implements IBlockHandler { this.block = getBlock( clientId ); } + public getContent() { + return getMarkdown( getBlockContent( this.block ) ); + } + public onSuggestion( suggestion: string ): void { // Adjust suggestion if it does not start with a hash. if ( ! suggestion.startsWith( '#' ) ) { diff --git a/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/types.ts b/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/types.ts index a5800c8e936f3..75645e9647ce9 100644 --- a/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/types.ts +++ b/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/types.ts @@ -7,6 +7,7 @@ export type OnSuggestion = ( suggestion: string ) => void; export interface IBlockHandler { onSuggestion: OnSuggestion; + getContent: () => string; } export type BlockEditorSelect = { diff --git a/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/with-ai-extension.tsx b/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/with-ai-extension.tsx index 629fe17f3e087..0eff155a3fefe 100644 --- a/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/with-ai-extension.tsx +++ b/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/with-ai-extension.tsx @@ -68,7 +68,7 @@ const blockEditWithAiComponents = createHigherOrderComponent( BlockEdit => { ); // Data and functions with block-specific implementations. - const { onSuggestion } = blockHandler( blockName, clientId ); + const { onSuggestion, getContent } = blockHandler( blockName, clientId ); const { request, @@ -141,8 +141,12 @@ const blockEditWithAiComponents = createHigherOrderComponent( BlockEdit => { if ( humanText ) { setAction( humanText ); } + + // Get the block's content + const content = getContent(); + // TODO: handle the promptType and options to request the suggestion. - debug( 'onRequestSuggestion', promptType, options, humanText ); + debug( 'onRequestSuggestion', promptType, options, content ); }; const onClose = useCallback( () => { From 7c99bddce07268acd8ab1573e7b00b907fbd3626 Mon Sep 17 00:00:00 2001 From: Douglas Date: Wed, 1 May 2024 19:32:12 -0300 Subject: [PATCH 5/7] add buildPromptForExtensions function --- .../ai-assistant/lib/prompt/backend-prompt.ts | 4 +- .../blocks/ai-assistant/lib/prompt/index.ts | 45 ++++++++++++++++++- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/projects/plugins/jetpack/extensions/blocks/ai-assistant/lib/prompt/backend-prompt.ts b/projects/plugins/jetpack/extensions/blocks/ai-assistant/lib/prompt/backend-prompt.ts index 20266d0c9f082..96f8b76d08aee 100644 --- a/projects/plugins/jetpack/extensions/blocks/ai-assistant/lib/prompt/backend-prompt.ts +++ b/projects/plugins/jetpack/extensions/blocks/ai-assistant/lib/prompt/backend-prompt.ts @@ -50,7 +50,7 @@ export function buildInitialMessageForBackendPrompt( promptType: PromptTypeProp * @param {string} relevantContent - The relevant content. * @returns {PromptItemProps} The initial message. */ -function buildRelevantContentMessageForBackendPrompt( +export function buildRelevantContentMessageForBackendPrompt( isContentGenerated?: boolean, relevantContent?: string | null ): PromptItemProps | null { @@ -172,7 +172,7 @@ function getSubject( * @param {BuildPromptProps} options - The prompt options. * @returns {object} The context. */ -function buildMessageContextForUserPrompt( { +export function buildMessageContextForUserPrompt( { options, type, userPrompt, diff --git a/projects/plugins/jetpack/extensions/blocks/ai-assistant/lib/prompt/index.ts b/projects/plugins/jetpack/extensions/blocks/ai-assistant/lib/prompt/index.ts index a966f4f6f622b..fdaba3a24908e 100644 --- a/projects/plugins/jetpack/extensions/blocks/ai-assistant/lib/prompt/index.ts +++ b/projects/plugins/jetpack/extensions/blocks/ai-assistant/lib/prompt/index.ts @@ -4,7 +4,9 @@ import { ToneProp } from '../../components/tone-dropdown-control'; import { buildInitialMessageForBackendPrompt, + buildMessageContextForUserPrompt, buildMessagesForBackendPrompt, + buildRelevantContentMessageForBackendPrompt, } from './backend-prompt'; /** * Types & consts @@ -108,7 +110,7 @@ export type BuildPromptOptionsProps = { }; export type BuildPromptProps = { - generatedContent: string; + generatedContent?: string; allPostContent?: string; postContentAbove?: string; currentPostTitle?: string; @@ -153,3 +155,44 @@ export function buildPromptForBlock( { return [ initialMessage, ...userMessages ]; } + +export type BuildExtensionPromptProps = { + blockContent: string; + options: BuildPromptOptionsProps; + type: PromptTypeProp; + userPrompt?: string; +}; + +/** + * Builds a prompt based on the type of prompt. + * Meant for use by the extensions. + * + * @param {BuildPromptProps} options - The prompt options. + * @returns {Array< PromptItemProps >} The prompt. + * @throws {Error} If the type is not recognized. + */ +export function buildPromptForExtensions( { + blockContent, + options, + type, + userPrompt, +}: BuildExtensionPromptProps ): Array< PromptItemProps > { + const messages = [ buildInitialMessageForBackendPrompt( type ) ]; + + const relevantContentMessage = buildRelevantContentMessageForBackendPrompt( false, blockContent ); + + if ( relevantContentMessage ) { + messages.push( relevantContentMessage ); + } + + messages.push( { + role: 'jetpack-ai' as const, + context: buildMessageContextForUserPrompt( { + options, + type, + userPrompt, + } ), + } ); + + return messages; +} From 42309886411e47a260dd2e0db6d6bbf326afbf60 Mon Sep 17 00:00:00 2001 From: Douglas Date: Wed, 1 May 2024 19:34:10 -0300 Subject: [PATCH 6/7] link toolbar requests to content --- .../inline-extensions/with-ai-extension.tsx | 50 ++++++++++++++++--- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/with-ai-extension.tsx b/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/with-ai-extension.tsx index 0eff155a3fefe..2e00607d22414 100644 --- a/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/with-ai-extension.tsx +++ b/projects/plugins/jetpack/extensions/blocks/ai-assistant/inline-extensions/with-ai-extension.tsx @@ -17,6 +17,7 @@ import React from 'react'; * Internal dependencies */ import { EXTENDED_INLINE_BLOCKS } from '../extensions/ai-assistant'; +import { BuildPromptOptionsProps, buildPromptForExtensions } from '../lib/prompt'; import { blockHandler } from './block-handler'; import AiAssistantInput from './components/ai-assistant-input'; import AiAssistantExtensionToolbarDropdown from './components/ai-assistant-toolbar-dropdown'; @@ -24,8 +25,12 @@ import { isPossibleToExtendBlock } from './lib/is-possible-to-extend-block'; /* * Types */ -import type { OnRequestSuggestion } from '../components/ai-assistant-toolbar-dropdown/dropdown-content'; +import type { + AiAssistantDropdownOnChangeOptionsArgProps, + OnRequestSuggestion, +} from '../components/ai-assistant-toolbar-dropdown/dropdown-content'; import type { ExtendedInlineBlockProp } from '../extensions/ai-assistant'; +import type { PromptTypeProp } from '../lib/prompt'; const debug = debugFactory( 'jetpack-ai-assistant:extensions:with-ai-extension' ); @@ -135,6 +140,31 @@ const blockEditWithAiComponents = createHigherOrderComponent( BlockEdit => { setShowAiControl( true ); }; + const getRequestMessages = ( { + promptType, + options, + userPrompt, + }: { + promptType: PromptTypeProp; + options?: AiAssistantDropdownOnChangeOptionsArgProps; + userPrompt?: string; + } ) => { + const blockContent = getContent(); + + const promptOptions: BuildPromptOptionsProps = { + tone: options?.tone, + language: options?.language, + fromExtension: true, + }; + + return buildPromptForExtensions( { + blockContent, + options: promptOptions, + type: promptType, + userPrompt, + } ); + }; + const onRequestSuggestion: OnRequestSuggestion = ( promptType, options, humanText ) => { setShowAiControl( true ); @@ -142,11 +172,11 @@ const blockEditWithAiComponents = createHigherOrderComponent( BlockEdit => { setAction( humanText ); } - // Get the block's content - const content = getContent(); + const messages = getRequestMessages( { promptType, options } ); + + debug( 'onRequestSuggestion', promptType, options ); - // TODO: handle the promptType and options to request the suggestion. - debug( 'onRequestSuggestion', promptType, options, content ); + request( messages ); }; const onClose = useCallback( () => { @@ -155,6 +185,14 @@ const blockEditWithAiComponents = createHigherOrderComponent( BlockEdit => { setAction( '' ); }, [ resetSuggestions ] ); + const onUserRequest = ( userPrompt: string ) => { + const promptType = 'userPrompt'; + const options = {}; + const messages = getRequestMessages( { promptType, options, userPrompt } ); + + request( messages ); + }; + // Close the AI Control if the block is deselected. useEffect( () => { if ( ! isSelected ) { @@ -180,7 +218,7 @@ const blockEditWithAiComponents = createHigherOrderComponent( BlockEdit => { suggestion={ suggestion } wrapperRef={ controlRef } action={ action } - request={ request } + request={ onUserRequest } stopSuggestion={ stopSuggestion } close={ onClose } undo={ onUndo } From feee0a6d1cf2cf0b23f6f495e3017c7dd3e948b2 Mon Sep 17 00:00:00 2001 From: Douglas Date: Wed, 1 May 2024 19:35:26 -0300 Subject: [PATCH 7/7] changelog --- .../changelog/update-jetpack-ai-inline-extensions-input-state | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 projects/plugins/jetpack/changelog/update-jetpack-ai-inline-extensions-input-state diff --git a/projects/plugins/jetpack/changelog/update-jetpack-ai-inline-extensions-input-state b/projects/plugins/jetpack/changelog/update-jetpack-ai-inline-extensions-input-state new file mode 100644 index 0000000000000..00b95c548c131 --- /dev/null +++ b/projects/plugins/jetpack/changelog/update-jetpack-ai-inline-extensions-input-state @@ -0,0 +1,4 @@ +Significance: patch +Type: other + +AI Assistant: Link toolbar actions to requests on inline extensions