From 0bc2312792b5f88f032a36f75211e222545a64f3 Mon Sep 17 00:00:00 2001 From: Christian Gastrell Date: Wed, 6 Dec 2023 15:44:09 -0300 Subject: [PATCH] AI Assistant: add prompt to attributes (#34438) * add userPrompt to the block's attributes * set last value to default to initial prop * add requestingState to attributes to keep consistency between reloads * add changelog entry --- .../ai-client/changelog/add-ai-prompt-to-attr | 4 +++ .../src/components/ai-control/index.tsx | 2 +- .../jetpack/changelog/add-ai-prompt-to-attr | 4 +++ .../extensions/blocks/ai-assistant/block.json | 8 ++++++ .../extensions/blocks/ai-assistant/edit.js | 18 ++++++++----- .../use-suggestions-from-openai/index.js | 27 ++++++++++--------- 6 files changed, 43 insertions(+), 20 deletions(-) create mode 100644 projects/js-packages/ai-client/changelog/add-ai-prompt-to-attr create mode 100644 projects/plugins/jetpack/changelog/add-ai-prompt-to-attr diff --git a/projects/js-packages/ai-client/changelog/add-ai-prompt-to-attr b/projects/js-packages/ai-client/changelog/add-ai-prompt-to-attr new file mode 100644 index 0000000000000..73f5072032938 --- /dev/null +++ b/projects/js-packages/ai-client/changelog/add-ai-prompt-to-attr @@ -0,0 +1,4 @@ +Significance: minor +Type: added + +AI Client: add requesting state to attributes diff --git a/projects/js-packages/ai-client/src/components/ai-control/index.tsx b/projects/js-packages/ai-client/src/components/ai-control/index.tsx index fd60332190029..acabab2521c8a 100644 --- a/projects/js-packages/ai-client/src/components/ai-control/index.tsx +++ b/projects/js-packages/ai-client/src/components/ai-control/index.tsx @@ -97,7 +97,7 @@ export function AIControl( const promptUserInputRef = useRef( null ); const loading = state === 'requesting' || state === 'suggesting'; const [ editRequest, setEditRequest ] = React.useState( false ); - const [ lastValue, setLastValue ] = React.useState( '' ); + const [ lastValue, setLastValue ] = React.useState( value || '' ); useEffect( () => { if ( editRequest ) { diff --git a/projects/plugins/jetpack/changelog/add-ai-prompt-to-attr b/projects/plugins/jetpack/changelog/add-ai-prompt-to-attr new file mode 100644 index 0000000000000..4237a86156369 --- /dev/null +++ b/projects/plugins/jetpack/changelog/add-ai-prompt-to-attr @@ -0,0 +1,4 @@ +Significance: minor +Type: other + +AI Assistant: add userPrompt to block's attributes diff --git a/projects/plugins/jetpack/extensions/blocks/ai-assistant/block.json b/projects/plugins/jetpack/extensions/blocks/ai-assistant/block.json index 9e5713e2db039..4eac3cf686345 100644 --- a/projects/plugins/jetpack/extensions/blocks/ai-assistant/block.json +++ b/projects/plugins/jetpack/extensions/blocks/ai-assistant/block.json @@ -50,6 +50,14 @@ "customSystemPrompt": { "type": "string", "default": "" + }, + "userPrompt": { + "type": "string", + "default": "" + }, + "requestingState": { + "type": "string", + "default": "init" } }, "example": { diff --git a/projects/plugins/jetpack/extensions/blocks/ai-assistant/edit.js b/projects/plugins/jetpack/extensions/blocks/ai-assistant/edit.js index d652070a38f7b..c5d521679d1a2 100644 --- a/projects/plugins/jetpack/extensions/blocks/ai-assistant/edit.js +++ b/projects/plugins/jetpack/extensions/blocks/ai-assistant/edit.js @@ -52,7 +52,6 @@ const isPlaygroundVisible = window?.Jetpack_Editor_Initial_State?.[ 'ai-assistant' ]?.[ 'is-playground-visible' ]; export default function AIAssistantEdit( { attributes, setAttributes, clientId, isSelected } ) { - const [ userPrompt, setUserPrompt ] = useState(); const [ errorData, setError ] = useState( {} ); const [ loadingImages, setLoadingImages ] = useState( false ); const [ resultImages, setResultImages ] = useState( [] ); @@ -125,8 +124,9 @@ export default function AIAssistantEdit( { attributes, setAttributes, clientId, content: attributes.content, setError, tracks, - userPrompt, + userPrompt: attributes.userPrompt, requireUpgrade, + requestingState: attributes.requestingState, } ); const connected = isUserConnected(); @@ -219,6 +219,10 @@ export default function AIAssistantEdit( { attributes, setAttributes, clientId, return () => clearInterval( interval ); }, [ promptPlaceholder, currentIndex ] ); + useEffect( () => { + setAttributes( { requestingState } ); + }, [ requestingState, setAttributes ] ); + const saveImage = async image => { if ( loadingImages ) { return; @@ -311,7 +315,7 @@ export default function AIAssistantEdit( { attributes, setAttributes, clientId, const handleChange = value => { setErrorDismissed( true ); - setUserPrompt( value ); + setAttributes( { userPrompt: value } ); }; const handleSend = () => { @@ -387,7 +391,9 @@ export default function AIAssistantEdit( { attributes, setAttributes, clientId, setError( {} ); getImagesFromOpenAI( - userPrompt.trim() === '' ? __( 'What would you like to see?', 'jetpack' ) : userPrompt, + attributes.userPrompt.trim() === '' + ? __( 'What would you like to see?', 'jetpack' ) + : attributes.userPrompt, setAttributes, setLoadingImages, setResultImages, @@ -551,7 +557,7 @@ export default function AIAssistantEdit( { attributes, setAttributes, clientId, // Add a typing effect in the text area for ( let i = 0; i < prompt.length; i++ ) { setTimeout( () => { - setUserPrompt( prompt.slice( 0, i + 1 ) ); + setAttributes( { userPrompt: prompt.slice( 0, i + 1 ) } ); }, 25 * i ); } } } @@ -562,7 +568,7 @@ export default function AIAssistantEdit( { attributes, setAttributes, clientId, { const [ isLoadingCategories, setIsLoadingCategories ] = useState( false ); const [ isLoadingCompletion, setIsLoadingCompletion ] = useState( false ); @@ -41,7 +42,7 @@ const useSuggestionsFromOpenAI = ( { const { updateBlockAttributes } = useDispatch( 'core/block-editor' ); const { dequeueAiAssistantFeatureAyncRequest, setAiAssistantFeatureRequireUpgrade } = useDispatch( 'wordpress-com/plans' ); - const [ requestingState, setRequestingState ] = useState( 'init' ); + const [ requestState, setRequestState ] = useState( requestingState || 'init' ); const source = useRef(); // Let's grab post data so that we can do something smart. @@ -139,7 +140,7 @@ const useSuggestionsFromOpenAI = ( { * let's set the error and return an `undefined` event source. */ if ( requireUpgrade ) { - setRequestingState( 'error' ); + setRequestState( 'error' ); setIsLoadingCompletion( false ); setWasCompletionJustRequested( false ); setShowRetry( false ); @@ -226,7 +227,7 @@ const useSuggestionsFromOpenAI = ( { debugPrompt( '(%s/%s) %o\n%s', i + 1, prompt.length, `[${ role }]`, promptContent ) ); - setRequestingState( 'requesting' ); + setRequestState( 'requesting' ); source.current = await askQuestion( prompt, { postId, @@ -235,7 +236,7 @@ const useSuggestionsFromOpenAI = ( { functions: options?.functions, } ); - setRequestingState( 'suggesting' ); + setRequestState( 'suggesting' ); } catch ( err ) { if ( err.message ) { setError( { message: err.message, code: err?.code || 'unknown', status: 'error' } ); @@ -309,7 +310,7 @@ const useSuggestionsFromOpenAI = ( { const onDone = e => { const { detail } = e; - setRequestingState( 'done' ); + setRequestState( 'done' ); // Remove the delimiter from the suggestion. const assistantResponse = detail.replaceAll( delimiter, '' ); @@ -355,7 +356,7 @@ const useSuggestionsFromOpenAI = ( { }; const onErrorUnclearPrompt = () => { - setRequestingState( 'error' ); + setRequestState( 'error' ); source?.current?.close(); setIsLoadingCompletion( false ); setWasCompletionJustRequested( false ); @@ -368,7 +369,7 @@ const useSuggestionsFromOpenAI = ( { }; const onErrorContextTooLarge = () => { - setRequestingState( 'error' ); + setRequestState( 'error' ); source?.current?.close(); setIsLoadingCompletion( false ); setWasCompletionJustRequested( false ); @@ -384,7 +385,7 @@ const useSuggestionsFromOpenAI = ( { }; const onErrorNetwork = ( { detail: error } ) => { - setRequestingState( 'error' ); + setRequestState( 'error' ); const { name: errorName, message: errorMessage } = error; if ( errorName === 'TypeError' && errorMessage === 'Failed to fetch' ) { /* @@ -430,7 +431,7 @@ const useSuggestionsFromOpenAI = ( { }; const onErrorServiceUnavailable = () => { - setRequestingState( 'error' ); + setRequestState( 'error' ); source?.current?.close(); setIsLoadingCompletion( false ); setWasCompletionJustRequested( false ); @@ -446,7 +447,7 @@ const useSuggestionsFromOpenAI = ( { }; const onErrorQuotaExceeded = () => { - setRequestingState( 'error' ); + setRequestState( 'error' ); source?.current?.close(); setIsLoadingCompletion( false ); setWasCompletionJustRequested( false ); @@ -463,7 +464,7 @@ const useSuggestionsFromOpenAI = ( { }; const onErrorModeration = () => { - setRequestingState( 'error' ); + setRequestState( 'error' ); source?.current?.close(); setIsLoadingCompletion( false ); setWasCompletionJustRequested( false ); @@ -527,7 +528,7 @@ const useSuggestionsFromOpenAI = ( { onSuggestionDone?.(); // Set requesting state to done since the suggestion stopped. - setRequestingState( 'done' ); + setRequestState( 'done' ); } return { @@ -540,7 +541,7 @@ const useSuggestionsFromOpenAI = ( { postTitle: currentPostTitle, contentBefore: getPartialContentToBlock( clientId ), wholeContent: getContentFromBlocks(), - requestingState, + requestingState: requestState, getSuggestionFromOpenAI: getStreamedSuggestionFromOpenAI, stopSuggestion,