@automattic/jetpack-ai-client 0.10.0 → 0.11.0
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 +15 -0
- package/build/components/ai-control/index.js +5 -6
- package/build/hooks/use-image-generator/index.d.ts +6 -4
- package/build/hooks/use-image-generator/index.js +18 -4
- package/package.json +17 -16
- package/src/components/ai-control/index.tsx +6 -7
- package/src/hooks/use-image-generator/index.ts +24 -5
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,19 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.11.0] - 2024-04-01
|
|
9
|
+
### Added
|
|
10
|
+
- AI Client: include prompt to generate featured image based on post content. [#36591]
|
|
11
|
+
- Support different responses in image hook [#36626]
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
- AI Client: fix a bug where quick prompts would not work after getting suggested content [#36651]
|
|
15
|
+
- AI Client: set request content type as JSON on image generation hook and use rectangular images instead of square images. [#36620]
|
|
16
|
+
|
|
17
|
+
## [0.10.1] - 2024-03-27
|
|
18
|
+
### Changed
|
|
19
|
+
- Updated package dependencies. [#36539, #36585]
|
|
20
|
+
|
|
8
21
|
## [0.10.0] - 2024-03-18
|
|
9
22
|
### Added
|
|
10
23
|
- Add image generator hook [#36415]
|
|
@@ -259,6 +272,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
259
272
|
- Updated package dependencies. [#31659]
|
|
260
273
|
- Updated package dependencies. [#31785]
|
|
261
274
|
|
|
275
|
+
[0.11.0]: https://github.com/Automattic/jetpack-ai-client/compare/v0.10.1...v0.11.0
|
|
276
|
+
[0.10.1]: https://github.com/Automattic/jetpack-ai-client/compare/v0.10.0...v0.10.1
|
|
262
277
|
[0.10.0]: https://github.com/Automattic/jetpack-ai-client/compare/v0.9.0...v0.10.0
|
|
263
278
|
[0.9.0]: https://github.com/Automattic/jetpack-ai-client/compare/v0.8.2...v0.9.0
|
|
264
279
|
[0.8.2]: https://github.com/Automattic/jetpack-ai-client/compare/v0.8.1...v0.8.2
|
|
@@ -9,8 +9,8 @@ import { useImperativeHandle, useRef, useEffect, useCallback } from '@wordpress/
|
|
|
9
9
|
import { __ } from '@wordpress/i18n';
|
|
10
10
|
import { Icon, closeSmall, check, arrowUp, trash, reusableBlock } from '@wordpress/icons';
|
|
11
11
|
import classNames from 'classnames';
|
|
12
|
-
import
|
|
13
|
-
import React from 'react';
|
|
12
|
+
import debugFactory from 'debug';
|
|
13
|
+
import React, { forwardRef } from 'react';
|
|
14
14
|
/**
|
|
15
15
|
* Internal dependencies
|
|
16
16
|
*/
|
|
@@ -19,6 +19,7 @@ import AiStatusIndicator from '../ai-status-indicator/index.js';
|
|
|
19
19
|
import { GuidelineMessage } from './message.js';
|
|
20
20
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
21
21
|
const noop = () => { };
|
|
22
|
+
const debug = debugFactory('jetpack-ai-client:ai-control');
|
|
22
23
|
/**
|
|
23
24
|
* AI Control component.
|
|
24
25
|
*
|
|
@@ -35,10 +36,7 @@ export function AIControl({ disabled = false, value = '', placeholder = '', show
|
|
|
35
36
|
if (editRequest) {
|
|
36
37
|
promptUserInputRef?.current?.focus();
|
|
37
38
|
}
|
|
38
|
-
|
|
39
|
-
onChange?.(lastValue);
|
|
40
|
-
}
|
|
41
|
-
}, [editRequest, lastValue, value]);
|
|
39
|
+
}, [editRequest]);
|
|
42
40
|
const sendRequest = useCallback(() => {
|
|
43
41
|
setLastValue(value);
|
|
44
42
|
setEditRequest(false);
|
|
@@ -62,6 +60,7 @@ export function AIControl({ disabled = false, value = '', placeholder = '', show
|
|
|
62
60
|
onDiscard?.();
|
|
63
61
|
}, []);
|
|
64
62
|
const cancelEdit = useCallback(() => {
|
|
63
|
+
debug('cancelEdit, revert to last value', lastValue);
|
|
65
64
|
onChange(lastValue || '');
|
|
66
65
|
setEditRequest(false);
|
|
67
66
|
}, [lastValue]);
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
declare const useImageGenerator: () => {
|
|
2
|
-
generateImage: ({ feature, }: {
|
|
2
|
+
generateImage: ({ feature, postContent, responseFormat, }: {
|
|
3
3
|
feature: string;
|
|
4
|
+
postContent: string;
|
|
5
|
+
responseFormat?: 'url' | 'b64_json';
|
|
4
6
|
}) => Promise<{
|
|
5
|
-
data:
|
|
6
|
-
|
|
7
|
-
}
|
|
7
|
+
data: {
|
|
8
|
+
[key: string]: string;
|
|
9
|
+
}[];
|
|
8
10
|
}>;
|
|
9
11
|
};
|
|
10
12
|
export default useImageGenerator;
|
|
@@ -8,7 +8,7 @@ import debugFactory from 'debug';
|
|
|
8
8
|
import requestJwt from '../../jwt/index.js';
|
|
9
9
|
const debug = debugFactory('ai-client:use-image-generator');
|
|
10
10
|
const useImageGenerator = () => {
|
|
11
|
-
const generateImage = async function ({ feature, }) {
|
|
11
|
+
const generateImage = async function ({ feature, postContent, responseFormat = 'url', }) {
|
|
12
12
|
let token = '';
|
|
13
13
|
try {
|
|
14
14
|
token = (await requestJwt()).token;
|
|
@@ -19,16 +19,30 @@ const useImageGenerator = () => {
|
|
|
19
19
|
}
|
|
20
20
|
try {
|
|
21
21
|
debug('Generating image');
|
|
22
|
-
// TODO:
|
|
23
|
-
const imageGenerationPrompt =
|
|
22
|
+
// TODO: fine tune the prompt as we move forward
|
|
23
|
+
const imageGenerationPrompt = `I need a cover image for a blog post.
|
|
24
|
+
Before creating the image, identify the main topic of the content and only represent it.
|
|
25
|
+
Do not represent the whole content in one image, keep it simple and just represent one single idea.
|
|
26
|
+
Do not add details, detailed explanations or highlights from the content, just represent the main idea as if it was a photograph.
|
|
27
|
+
Do not use collages or compositions with multiple elements or scenes. Stick to one single scene. Do not compose unrealistic scenes.
|
|
28
|
+
If the content describes facts, objects or concepts from the real world, represent them on a realistic style and do not make unreal compositions.
|
|
29
|
+
If the content is more abstract, use a more abstract style to represent the main idea.
|
|
30
|
+
Make sure the light and the style are visually appealing.
|
|
31
|
+
Do not add text to the image.
|
|
32
|
+
|
|
33
|
+
This is the post content:
|
|
34
|
+
|
|
35
|
+
` + postContent;
|
|
24
36
|
const URL = 'https://public-api.wordpress.com/wpcom/v2/jetpack-ai-image';
|
|
25
37
|
const body = {
|
|
26
38
|
prompt: imageGenerationPrompt,
|
|
27
|
-
response_format:
|
|
39
|
+
response_format: responseFormat,
|
|
28
40
|
feature,
|
|
41
|
+
size: '1792x1024',
|
|
29
42
|
};
|
|
30
43
|
const headers = {
|
|
31
44
|
Authorization: `Bearer ${token}`,
|
|
45
|
+
'Content-Type': 'application/json',
|
|
32
46
|
};
|
|
33
47
|
const data = await fetch(URL, {
|
|
34
48
|
method: 'POST',
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"private": false,
|
|
3
3
|
"name": "@automattic/jetpack-ai-client",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.11.0",
|
|
5
5
|
"description": "A JS client for consuming Jetpack AI services",
|
|
6
6
|
"homepage": "https://github.com/Automattic/jetpack/tree/HEAD/projects/js-packages/ai-client/#readme",
|
|
7
7
|
"bugs": {
|
|
@@ -18,13 +18,14 @@
|
|
|
18
18
|
"build": "pnpm run clean && pnpm run compile-ts",
|
|
19
19
|
"clean": "rm -rf build/",
|
|
20
20
|
"compile-ts": "tsc --pretty",
|
|
21
|
-
"test": "NODE_OPTIONS=--experimental-vm-modules jest"
|
|
21
|
+
"test": "NODE_OPTIONS=--experimental-vm-modules jest",
|
|
22
|
+
"watch": "tsc --watch --pretty"
|
|
22
23
|
},
|
|
23
24
|
"type": "module",
|
|
24
25
|
"devDependencies": {
|
|
25
|
-
"@storybook/addon-actions": "
|
|
26
|
-
"@storybook/blocks": "
|
|
27
|
-
"@storybook/react": "
|
|
26
|
+
"@storybook/addon-actions": "8.0.4",
|
|
27
|
+
"@storybook/blocks": "8.0.4",
|
|
28
|
+
"@storybook/react": "8.0.4",
|
|
28
29
|
"jest": "^29.6.2",
|
|
29
30
|
"jest-environment-jsdom": "29.7.0",
|
|
30
31
|
"typescript": "5.0.4"
|
|
@@ -38,19 +39,19 @@
|
|
|
38
39
|
"main": "./build/index.js",
|
|
39
40
|
"types": "./build/index.d.ts",
|
|
40
41
|
"dependencies": {
|
|
41
|
-
"@automattic/jetpack-base-styles": "^0.6.
|
|
42
|
-
"@automattic/jetpack-connection": "^0.33.
|
|
43
|
-
"@automattic/jetpack-shared-extension-utils": "^0.14.
|
|
42
|
+
"@automattic/jetpack-base-styles": "^0.6.20",
|
|
43
|
+
"@automattic/jetpack-connection": "^0.33.5",
|
|
44
|
+
"@automattic/jetpack-shared-extension-utils": "^0.14.8",
|
|
44
45
|
"@microsoft/fetch-event-source": "2.0.1",
|
|
45
46
|
"@types/react": "18.2.61",
|
|
46
|
-
"@wordpress/api-fetch": "6.
|
|
47
|
-
"@wordpress/block-editor": "12.
|
|
48
|
-
"@wordpress/components": "27.
|
|
49
|
-
"@wordpress/compose": "6.
|
|
50
|
-
"@wordpress/data": "9.
|
|
51
|
-
"@wordpress/element": "5.
|
|
52
|
-
"@wordpress/i18n": "4.
|
|
53
|
-
"@wordpress/icons": "9.
|
|
47
|
+
"@wordpress/api-fetch": "6.51.0",
|
|
48
|
+
"@wordpress/block-editor": "12.22.0",
|
|
49
|
+
"@wordpress/components": "27.2.0",
|
|
50
|
+
"@wordpress/compose": "6.31.0",
|
|
51
|
+
"@wordpress/data": "9.24.0",
|
|
52
|
+
"@wordpress/element": "5.31.0",
|
|
53
|
+
"@wordpress/i18n": "4.54.0",
|
|
54
|
+
"@wordpress/icons": "9.45.0",
|
|
54
55
|
"classnames": "2.3.2",
|
|
55
56
|
"debug": "4.3.4",
|
|
56
57
|
"react": "18.2.0",
|
|
@@ -8,8 +8,8 @@ import { useImperativeHandle, useRef, useEffect, useCallback } from '@wordpress/
|
|
|
8
8
|
import { __ } from '@wordpress/i18n';
|
|
9
9
|
import { Icon, closeSmall, check, arrowUp, trash, reusableBlock } from '@wordpress/icons';
|
|
10
10
|
import classNames from 'classnames';
|
|
11
|
-
import
|
|
12
|
-
import React from 'react';
|
|
11
|
+
import debugFactory from 'debug';
|
|
12
|
+
import React, { forwardRef } from 'react';
|
|
13
13
|
/**
|
|
14
14
|
* Internal dependencies
|
|
15
15
|
*/
|
|
@@ -45,6 +45,8 @@ type AiControlProps = {
|
|
|
45
45
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
46
46
|
const noop = () => {};
|
|
47
47
|
|
|
48
|
+
const debug = debugFactory( 'jetpack-ai-client:ai-control' );
|
|
49
|
+
|
|
48
50
|
/**
|
|
49
51
|
* AI Control component.
|
|
50
52
|
*
|
|
@@ -84,11 +86,7 @@ export function AIControl(
|
|
|
84
86
|
if ( editRequest ) {
|
|
85
87
|
promptUserInputRef?.current?.focus();
|
|
86
88
|
}
|
|
87
|
-
|
|
88
|
-
if ( ! editRequest && lastValue !== null && value !== lastValue ) {
|
|
89
|
-
onChange?.( lastValue );
|
|
90
|
-
}
|
|
91
|
-
}, [ editRequest, lastValue, value ] );
|
|
89
|
+
}, [ editRequest ] );
|
|
92
90
|
|
|
93
91
|
const sendRequest = useCallback( () => {
|
|
94
92
|
setLastValue( value );
|
|
@@ -119,6 +117,7 @@ export function AIControl(
|
|
|
119
117
|
}, [] );
|
|
120
118
|
|
|
121
119
|
const cancelEdit = useCallback( () => {
|
|
120
|
+
debug( 'cancelEdit, revert to last value', lastValue );
|
|
122
121
|
onChange( lastValue || '' );
|
|
123
122
|
setEditRequest( false );
|
|
124
123
|
}, [ lastValue ] );
|
|
@@ -12,9 +12,13 @@ const debug = debugFactory( 'ai-client:use-image-generator' );
|
|
|
12
12
|
const useImageGenerator = () => {
|
|
13
13
|
const generateImage = async function ( {
|
|
14
14
|
feature,
|
|
15
|
+
postContent,
|
|
16
|
+
responseFormat = 'url',
|
|
15
17
|
}: {
|
|
16
18
|
feature: string;
|
|
17
|
-
|
|
19
|
+
postContent: string;
|
|
20
|
+
responseFormat?: 'url' | 'b64_json';
|
|
21
|
+
} ): Promise< { data: Array< { [ key: string ]: string } > } > {
|
|
18
22
|
let token = '';
|
|
19
23
|
|
|
20
24
|
try {
|
|
@@ -27,19 +31,34 @@ const useImageGenerator = () => {
|
|
|
27
31
|
try {
|
|
28
32
|
debug( 'Generating image' );
|
|
29
33
|
|
|
30
|
-
// TODO:
|
|
31
|
-
const imageGenerationPrompt =
|
|
34
|
+
// TODO: fine tune the prompt as we move forward
|
|
35
|
+
const imageGenerationPrompt =
|
|
36
|
+
`I need a cover image for a blog post.
|
|
37
|
+
Before creating the image, identify the main topic of the content and only represent it.
|
|
38
|
+
Do not represent the whole content in one image, keep it simple and just represent one single idea.
|
|
39
|
+
Do not add details, detailed explanations or highlights from the content, just represent the main idea as if it was a photograph.
|
|
40
|
+
Do not use collages or compositions with multiple elements or scenes. Stick to one single scene. Do not compose unrealistic scenes.
|
|
41
|
+
If the content describes facts, objects or concepts from the real world, represent them on a realistic style and do not make unreal compositions.
|
|
42
|
+
If the content is more abstract, use a more abstract style to represent the main idea.
|
|
43
|
+
Make sure the light and the style are visually appealing.
|
|
44
|
+
Do not add text to the image.
|
|
45
|
+
|
|
46
|
+
This is the post content:
|
|
47
|
+
|
|
48
|
+
` + postContent;
|
|
32
49
|
|
|
33
50
|
const URL = 'https://public-api.wordpress.com/wpcom/v2/jetpack-ai-image';
|
|
34
51
|
|
|
35
52
|
const body = {
|
|
36
53
|
prompt: imageGenerationPrompt,
|
|
37
|
-
response_format:
|
|
54
|
+
response_format: responseFormat,
|
|
38
55
|
feature,
|
|
56
|
+
size: '1792x1024',
|
|
39
57
|
};
|
|
40
58
|
|
|
41
59
|
const headers = {
|
|
42
60
|
Authorization: `Bearer ${ token }`,
|
|
61
|
+
'Content-Type': 'application/json',
|
|
43
62
|
};
|
|
44
63
|
|
|
45
64
|
const data = await fetch( URL, {
|
|
@@ -48,7 +67,7 @@ const useImageGenerator = () => {
|
|
|
48
67
|
body: JSON.stringify( body ),
|
|
49
68
|
} ).then( response => response.json() );
|
|
50
69
|
|
|
51
|
-
return data as { data: {
|
|
70
|
+
return data as { data: { [ key: string ]: string }[] };
|
|
52
71
|
} catch ( error ) {
|
|
53
72
|
return;
|
|
54
73
|
}
|