@automattic/jetpack-ai-client 0.32.0 → 0.32.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
CHANGED
|
@@ -5,6 +5,10 @@ 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.32.1] - 2025-06-24
|
|
9
|
+
### Added
|
|
10
|
+
- Improve error handling on Chrome AI events. [#44048]
|
|
11
|
+
|
|
8
12
|
## [0.32.0] - 2025-06-23
|
|
9
13
|
### Changed
|
|
10
14
|
- AI Assistant: Add A/B test for Chrome AI API features. [#43690]
|
|
@@ -646,6 +650,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
646
650
|
- AI Client: stop using smart document visibility handling on the fetchEventSource library, so it does not restart the completion when changing tabs. [#32004]
|
|
647
651
|
- Updated package dependencies. [#31468] [#31659] [#31785]
|
|
648
652
|
|
|
653
|
+
[0.32.1]: https://github.com/Automattic/jetpack-ai-client/compare/v0.32.0...v0.32.1
|
|
649
654
|
[0.32.0]: https://github.com/Automattic/jetpack-ai-client/compare/v0.31.2...v0.32.0
|
|
650
655
|
[0.31.2]: https://github.com/Automattic/jetpack-ai-client/compare/v0.31.1...v0.31.2
|
|
651
656
|
[0.31.1]: https://github.com/Automattic/jetpack-ai-client/compare/v0.31.0...v0.31.1
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
|
-
import { initializeExPlat,
|
|
4
|
+
import { initializeExPlat, loadExperimentAssignmentWithAuth } from '@automattic/jetpack-explat';
|
|
5
5
|
import { select } from '@wordpress/data';
|
|
6
6
|
import debugFactory from 'debug';
|
|
7
7
|
const debug = debugFactory('ai-client:chrome-ai-availability');
|
|
@@ -28,7 +28,7 @@ export async function isChromeAIAvailable() {
|
|
|
28
28
|
}
|
|
29
29
|
initializeExPlat();
|
|
30
30
|
debug('initialized explat');
|
|
31
|
-
const { variationName } = await
|
|
31
|
+
const { variationName } = await loadExperimentAssignmentWithAuth('calypso_jetpack_ai_gemini_api_202503_v1');
|
|
32
32
|
debug('variationName', variationName);
|
|
33
33
|
return variationName === 'treatment';
|
|
34
34
|
}
|
|
@@ -22,6 +22,7 @@ export default class ChromeAISuggestionsEventSource extends EventTarget {
|
|
|
22
22
|
this.initSource(data);
|
|
23
23
|
}
|
|
24
24
|
initSource({ content, promptType, options = {}, }) {
|
|
25
|
+
debug('initSource', content, promptType, options);
|
|
25
26
|
if (promptType === PROMPT_TYPE_CHANGE_LANGUAGE) {
|
|
26
27
|
this.translate(content, options.targetLanguage, options.sourceLanguage);
|
|
27
28
|
}
|
|
@@ -62,11 +63,25 @@ export default class ChromeAISuggestionsEventSource extends EventTarget {
|
|
|
62
63
|
if (!('Translator' in self)) {
|
|
63
64
|
return;
|
|
64
65
|
}
|
|
66
|
+
const translatorAvailability = await self.Translator.availability({
|
|
67
|
+
sourceLanguage: source,
|
|
68
|
+
targetLanguage: target,
|
|
69
|
+
});
|
|
70
|
+
if (translatorAvailability === 'unavailable') {
|
|
71
|
+
debug('awaiting translator ready');
|
|
72
|
+
this.processErrorEvent({
|
|
73
|
+
message: 'Translator is unavailable',
|
|
74
|
+
});
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
65
77
|
const translator = await self.Translator.create({
|
|
66
78
|
sourceLanguage: source,
|
|
67
79
|
targetLanguage: target,
|
|
68
80
|
});
|
|
69
81
|
if (!translator) {
|
|
82
|
+
this.processErrorEvent({
|
|
83
|
+
message: 'Translator failed to initialize',
|
|
84
|
+
});
|
|
70
85
|
return;
|
|
71
86
|
}
|
|
72
87
|
try {
|
|
@@ -100,24 +115,32 @@ export default class ChromeAISuggestionsEventSource extends EventTarget {
|
|
|
100
115
|
}
|
|
101
116
|
// use the Chrome AI summarizer
|
|
102
117
|
async summarize(text, tone, wordCount) {
|
|
118
|
+
debug('summarize', text, tone, wordCount);
|
|
103
119
|
if (!('Summarizer' in self)) {
|
|
104
120
|
return;
|
|
105
121
|
}
|
|
106
122
|
const availability = await self.Summarizer.availability();
|
|
107
123
|
if (availability === 'unavailable') {
|
|
124
|
+
this.processErrorEvent({
|
|
125
|
+
data: { message: 'Summarizer is unavailable' },
|
|
126
|
+
});
|
|
108
127
|
return;
|
|
109
128
|
}
|
|
110
129
|
const summarizerOptions = this.getSummarizerOptions(tone, wordCount);
|
|
111
130
|
const summarizer = await self.Summarizer.create(summarizerOptions);
|
|
112
131
|
if (availability !== 'available') {
|
|
132
|
+
debug('awaiting summarizer ready');
|
|
113
133
|
await summarizer.ready;
|
|
114
134
|
}
|
|
115
135
|
try {
|
|
116
136
|
const context = `Write with a ${tone} tone.`;
|
|
137
|
+
debug('context', context);
|
|
117
138
|
let summary = await summarizer.summarize(text, { context: context });
|
|
139
|
+
debug('summary', summary);
|
|
118
140
|
wordCount = wordCount ?? 50;
|
|
119
141
|
// gemini-nano has a tendency to exceed the word count, so we need to check and summarize again if necessary
|
|
120
142
|
if (summary.split(' ').length > wordCount) {
|
|
143
|
+
debug('summary exceeds word count');
|
|
121
144
|
summary = await summarizer.summarize(summary, { context: context });
|
|
122
145
|
}
|
|
123
146
|
this.processEvent({
|
|
@@ -130,6 +153,7 @@ export default class ChromeAISuggestionsEventSource extends EventTarget {
|
|
|
130
153
|
});
|
|
131
154
|
}
|
|
132
155
|
catch (error) {
|
|
156
|
+
debug('error', error);
|
|
133
157
|
this.processErrorEvent(error);
|
|
134
158
|
}
|
|
135
159
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"private": false,
|
|
3
3
|
"name": "@automattic/jetpack-ai-client",
|
|
4
|
-
"version": "0.32.
|
|
4
|
+
"version": "0.32.1",
|
|
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": {
|
|
@@ -46,11 +46,11 @@
|
|
|
46
46
|
"types": "./build/index.d.ts",
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@automattic/jetpack-base-styles": "^1.0.1",
|
|
49
|
-
"@automattic/jetpack-components": "^1.1.
|
|
50
|
-
"@automattic/jetpack-connection": "^1.2.
|
|
51
|
-
"@automattic/jetpack-script-data": "^0.4.
|
|
49
|
+
"@automattic/jetpack-components": "^1.1.6",
|
|
50
|
+
"@automattic/jetpack-connection": "^1.2.6",
|
|
51
|
+
"@automattic/jetpack-script-data": "^0.4.4",
|
|
52
52
|
"@automattic/jetpack-explat": "workspace:*",
|
|
53
|
-
"@automattic/jetpack-shared-extension-utils": "^1.2.
|
|
53
|
+
"@automattic/jetpack-shared-extension-utils": "^1.2.1",
|
|
54
54
|
"@microsoft/fetch-event-source": "2.0.1",
|
|
55
55
|
"@types/jest": "30.0.0",
|
|
56
56
|
"@types/react": "18.3.23",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
|
-
import { initializeExPlat,
|
|
4
|
+
import { initializeExPlat, loadExperimentAssignmentWithAuth } from '@automattic/jetpack-explat';
|
|
5
5
|
import { select } from '@wordpress/data';
|
|
6
6
|
import debugFactory from 'debug';
|
|
7
7
|
|
|
@@ -48,7 +48,7 @@ export async function isChromeAIAvailable() {
|
|
|
48
48
|
initializeExPlat();
|
|
49
49
|
debug( 'initialized explat' );
|
|
50
50
|
|
|
51
|
-
const { variationName } = await
|
|
51
|
+
const { variationName } = await loadExperimentAssignmentWithAuth(
|
|
52
52
|
'calypso_jetpack_ai_gemini_api_202503_v1'
|
|
53
53
|
);
|
|
54
54
|
|
|
@@ -66,6 +66,7 @@ export default class ChromeAISuggestionsEventSource extends EventTarget {
|
|
|
66
66
|
promptType,
|
|
67
67
|
options = {},
|
|
68
68
|
}: ChromeAISuggestionsEventSourceConstructorArgs ) {
|
|
69
|
+
debug( 'initSource', content, promptType, options );
|
|
69
70
|
if ( promptType === PROMPT_TYPE_CHANGE_LANGUAGE ) {
|
|
70
71
|
this.translate( content, options.targetLanguage, options.sourceLanguage );
|
|
71
72
|
}
|
|
@@ -119,12 +120,28 @@ export default class ChromeAISuggestionsEventSource extends EventTarget {
|
|
|
119
120
|
return;
|
|
120
121
|
}
|
|
121
122
|
|
|
123
|
+
const translatorAvailability = await self.Translator.availability( {
|
|
124
|
+
sourceLanguage: source,
|
|
125
|
+
targetLanguage: target,
|
|
126
|
+
} );
|
|
127
|
+
|
|
128
|
+
if ( translatorAvailability === 'unavailable' ) {
|
|
129
|
+
debug( 'awaiting translator ready' );
|
|
130
|
+
this.processErrorEvent( {
|
|
131
|
+
message: 'Translator is unavailable',
|
|
132
|
+
} );
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
122
136
|
const translator = await self.Translator.create( {
|
|
123
137
|
sourceLanguage: source,
|
|
124
138
|
targetLanguage: target,
|
|
125
139
|
} );
|
|
126
140
|
|
|
127
141
|
if ( ! translator ) {
|
|
142
|
+
this.processErrorEvent( {
|
|
143
|
+
message: 'Translator failed to initialize',
|
|
144
|
+
} );
|
|
128
145
|
return;
|
|
129
146
|
}
|
|
130
147
|
|
|
@@ -166,6 +183,7 @@ export default class ChromeAISuggestionsEventSource extends EventTarget {
|
|
|
166
183
|
|
|
167
184
|
// use the Chrome AI summarizer
|
|
168
185
|
async summarize( text: string, tone?: string, wordCount?: number ) {
|
|
186
|
+
debug( 'summarize', text, tone, wordCount );
|
|
169
187
|
if ( ! ( 'Summarizer' in self ) ) {
|
|
170
188
|
return;
|
|
171
189
|
}
|
|
@@ -173,6 +191,9 @@ export default class ChromeAISuggestionsEventSource extends EventTarget {
|
|
|
173
191
|
const availability = await self.Summarizer.availability();
|
|
174
192
|
|
|
175
193
|
if ( availability === 'unavailable' ) {
|
|
194
|
+
this.processErrorEvent( {
|
|
195
|
+
data: { message: 'Summarizer is unavailable' },
|
|
196
|
+
} );
|
|
176
197
|
return;
|
|
177
198
|
}
|
|
178
199
|
|
|
@@ -181,17 +202,20 @@ export default class ChromeAISuggestionsEventSource extends EventTarget {
|
|
|
181
202
|
const summarizer = await self.Summarizer.create( summarizerOptions );
|
|
182
203
|
|
|
183
204
|
if ( availability !== 'available' ) {
|
|
205
|
+
debug( 'awaiting summarizer ready' );
|
|
184
206
|
await summarizer.ready;
|
|
185
207
|
}
|
|
186
208
|
|
|
187
209
|
try {
|
|
188
210
|
const context = `Write with a ${ tone } tone.`;
|
|
211
|
+
debug( 'context', context );
|
|
189
212
|
let summary = await summarizer.summarize( text, { context: context } );
|
|
190
|
-
|
|
213
|
+
debug( 'summary', summary );
|
|
191
214
|
wordCount = wordCount ?? 50;
|
|
192
215
|
|
|
193
216
|
// gemini-nano has a tendency to exceed the word count, so we need to check and summarize again if necessary
|
|
194
217
|
if ( summary.split( ' ' ).length > wordCount ) {
|
|
218
|
+
debug( 'summary exceeds word count' );
|
|
195
219
|
summary = await summarizer.summarize( summary, { context: context } );
|
|
196
220
|
}
|
|
197
221
|
|
|
@@ -204,6 +228,7 @@ export default class ChromeAISuggestionsEventSource extends EventTarget {
|
|
|
204
228
|
} ),
|
|
205
229
|
} );
|
|
206
230
|
} catch ( error ) {
|
|
231
|
+
debug( 'error', error );
|
|
207
232
|
this.processErrorEvent( error );
|
|
208
233
|
}
|
|
209
234
|
}
|