@automattic/jetpack-ai-client 0.33.31 → 0.34.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 +16 -0
- package/build/components/message/index.js +1 -1
- package/build/hooks/use-ai-feature/index.d.ts +0 -1
- package/build/hooks/use-ai-suggestions/index.d.ts +2 -2
- package/build/hooks/use-ai-suggestions/index.js +5 -15
- package/build/index.d.ts +0 -4
- package/build/index.js +0 -4
- package/build/types.d.ts +1 -42
- package/build/types.js +0 -1
- package/declarations.d.ts +5 -0
- package/package.json +22 -22
- package/src/components/message/index.tsx +4 -1
- package/src/hooks/use-ai-suggestions/index.ts +6 -17
- package/src/index.ts +0 -5
- package/src/types.ts +0 -46
- package/build/chrome-ai/factory.d.ts +0 -9
- package/build/chrome-ai/factory.js +0 -150
- package/build/chrome-ai/get-availability.d.ts +0 -7
- package/build/chrome-ai/get-availability.js +0 -67
- package/build/chrome-ai/index.d.ts +0 -2
- package/build/chrome-ai/index.js +0 -2
- package/build/chrome-ai/suggestions.d.ts +0 -38
- package/build/chrome-ai/suggestions.js +0 -160
- package/src/chrome-ai/factory.ts +0 -199
- package/src/chrome-ai/get-availability.ts +0 -105
- package/src/chrome-ai/index.ts +0 -2
- package/src/chrome-ai/suggestions.ts +0 -235
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
import { EventSourceMessage } from '@microsoft/fetch-event-source';
|
|
2
|
-
import debugFactory from 'debug';
|
|
3
|
-
import { PROMPT_TYPE_CHANGE_LANGUAGE, PROMPT_TYPE_SUMMARIZE } from '../constants.ts';
|
|
4
|
-
import { getErrorData } from '../hooks/use-ai-suggestions/index.ts';
|
|
5
|
-
import { renderHTMLFromMarkdown, renderMarkdownFromHTML } from '../libs/markdown/index.ts';
|
|
6
|
-
import { AiModelTypeProp, ERROR_RESPONSE, ERROR_NETWORK } from '../types.ts';
|
|
7
|
-
|
|
8
|
-
type ChromeAISuggestionsEventSourceConstructorArgs = {
|
|
9
|
-
content: string;
|
|
10
|
-
promptType: string;
|
|
11
|
-
options?: {
|
|
12
|
-
postId?: number | string;
|
|
13
|
-
feature?: 'ai-assistant-experimental' | string | undefined;
|
|
14
|
-
|
|
15
|
-
// translation
|
|
16
|
-
sourceLanguage?: string;
|
|
17
|
-
targetLanguage?: string;
|
|
18
|
-
|
|
19
|
-
// summarization
|
|
20
|
-
tone?: string;
|
|
21
|
-
wordCount?: number;
|
|
22
|
-
|
|
23
|
-
// not sure if we need these
|
|
24
|
-
functions?: Array< object >;
|
|
25
|
-
model?: AiModelTypeProp;
|
|
26
|
-
};
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
type ChromeAIEvent = {
|
|
30
|
-
type: string;
|
|
31
|
-
message: string;
|
|
32
|
-
complete?: boolean;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
type FunctionCallProps = {
|
|
36
|
-
name?: string;
|
|
37
|
-
arguments?: string;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
const debug = debugFactory( 'ai-client:chrome-ai-suggestions' );
|
|
41
|
-
|
|
42
|
-
export default class ChromeAISuggestionsEventSource extends EventTarget {
|
|
43
|
-
fullMessage: string;
|
|
44
|
-
fullFunctionCall: FunctionCallProps;
|
|
45
|
-
isPromptClear: boolean;
|
|
46
|
-
controller: AbortController;
|
|
47
|
-
|
|
48
|
-
errorUnclearPromptTriggered: boolean;
|
|
49
|
-
|
|
50
|
-
constructor( data: ChromeAISuggestionsEventSourceConstructorArgs ) {
|
|
51
|
-
super();
|
|
52
|
-
this.fullMessage = '';
|
|
53
|
-
this.fullFunctionCall = {
|
|
54
|
-
name: '',
|
|
55
|
-
arguments: '',
|
|
56
|
-
};
|
|
57
|
-
this.isPromptClear = false;
|
|
58
|
-
|
|
59
|
-
this.controller = new AbortController();
|
|
60
|
-
|
|
61
|
-
this.initSource( data );
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
initSource( {
|
|
65
|
-
content,
|
|
66
|
-
promptType,
|
|
67
|
-
options = {},
|
|
68
|
-
}: ChromeAISuggestionsEventSourceConstructorArgs ) {
|
|
69
|
-
debug( 'initSource', content, promptType, options );
|
|
70
|
-
if ( promptType === PROMPT_TYPE_CHANGE_LANGUAGE ) {
|
|
71
|
-
this.translate( content, options.targetLanguage, options.sourceLanguage );
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if ( promptType === PROMPT_TYPE_SUMMARIZE ) {
|
|
75
|
-
this.summarize( content, options.tone, options.wordCount );
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
async initEventSource() {}
|
|
80
|
-
|
|
81
|
-
close() {}
|
|
82
|
-
|
|
83
|
-
checkForUnclearPrompt() {}
|
|
84
|
-
|
|
85
|
-
processEvent( e: EventSourceMessage ) {
|
|
86
|
-
let data: ChromeAIEvent;
|
|
87
|
-
debug( 'processEvent', e );
|
|
88
|
-
try {
|
|
89
|
-
data = JSON.parse( e.data );
|
|
90
|
-
} catch ( err ) {
|
|
91
|
-
this.processErrorEvent( err );
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if ( e.event === 'translation' || e.event === 'summary' ) {
|
|
96
|
-
this.dispatchEvent( new CustomEvent( 'suggestion', { detail: data.message } ) );
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if ( data.complete ) {
|
|
100
|
-
this.dispatchEvent(
|
|
101
|
-
new CustomEvent( 'done', { detail: { message: data.message, source: 'chromeAI' } } )
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
processErrorEvent( e ) {
|
|
107
|
-
debug( 'processErrorEvent', e );
|
|
108
|
-
// Dispatch a generic network error event
|
|
109
|
-
this.dispatchEvent( new CustomEvent( ERROR_NETWORK, { detail: e } ) );
|
|
110
|
-
this.dispatchEvent(
|
|
111
|
-
new CustomEvent( ERROR_RESPONSE, {
|
|
112
|
-
detail: getErrorData( ERROR_NETWORK ),
|
|
113
|
-
} )
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// use the Chrome AI translator
|
|
118
|
-
async translate( text: string, target: string, source: string = '' ) {
|
|
119
|
-
if ( ! ( 'Translator' in self ) ) {
|
|
120
|
-
return;
|
|
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
|
-
|
|
136
|
-
const translator = await self.Translator.create( {
|
|
137
|
-
sourceLanguage: source,
|
|
138
|
-
targetLanguage: target,
|
|
139
|
-
} );
|
|
140
|
-
|
|
141
|
-
if ( ! translator ) {
|
|
142
|
-
this.processErrorEvent( {
|
|
143
|
-
message: 'Translator failed to initialize',
|
|
144
|
-
} );
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
try {
|
|
149
|
-
const translation = await translator.translate( renderHTMLFromMarkdown( { content: text } ) );
|
|
150
|
-
|
|
151
|
-
this.processEvent( {
|
|
152
|
-
id: '',
|
|
153
|
-
event: 'translation',
|
|
154
|
-
data: JSON.stringify( {
|
|
155
|
-
message: renderMarkdownFromHTML( { content: translation } ),
|
|
156
|
-
complete: true,
|
|
157
|
-
} ),
|
|
158
|
-
} );
|
|
159
|
-
} catch ( error ) {
|
|
160
|
-
this.processErrorEvent( error );
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// Helper function to format summarizer options
|
|
165
|
-
private getSummarizerOptions( tone?: string, wordCount?: number ) {
|
|
166
|
-
let sharedContext = `The summary you write should contain strictly less than ${
|
|
167
|
-
wordCount ?? 50
|
|
168
|
-
} words. Strive for precision in word count without compromising clarity and significance`;
|
|
169
|
-
|
|
170
|
-
if ( tone ) {
|
|
171
|
-
sharedContext += `\n - Write with a ${ tone } tone.\n`;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
const options = {
|
|
175
|
-
sharedContext: sharedContext,
|
|
176
|
-
type: 'teaser',
|
|
177
|
-
format: 'plain-text',
|
|
178
|
-
length: 'medium',
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
return options;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// use the Chrome AI summarizer
|
|
185
|
-
async summarize( text: string, tone?: string, wordCount?: number ) {
|
|
186
|
-
debug( 'summarize', text, tone, wordCount );
|
|
187
|
-
if ( ! ( 'Summarizer' in self ) ) {
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
const availability = await self.Summarizer.availability();
|
|
192
|
-
|
|
193
|
-
if ( availability === 'unavailable' ) {
|
|
194
|
-
this.processErrorEvent( {
|
|
195
|
-
data: { message: 'Summarizer is unavailable' },
|
|
196
|
-
} );
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
const summarizerOptions = this.getSummarizerOptions( tone, wordCount );
|
|
201
|
-
|
|
202
|
-
const summarizer = await self.Summarizer.create( summarizerOptions );
|
|
203
|
-
|
|
204
|
-
if ( availability !== 'available' ) {
|
|
205
|
-
debug( 'awaiting summarizer ready' );
|
|
206
|
-
await summarizer.ready;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
try {
|
|
210
|
-
const context = `Write with a ${ tone } tone.`;
|
|
211
|
-
debug( 'context', context );
|
|
212
|
-
let summary = await summarizer.summarize( text, { context: context } );
|
|
213
|
-
debug( 'summary', summary );
|
|
214
|
-
wordCount = wordCount ?? 50;
|
|
215
|
-
|
|
216
|
-
// gemini-nano has a tendency to exceed the word count, so we need to check and summarize again if necessary
|
|
217
|
-
if ( summary.split( ' ' ).length > wordCount ) {
|
|
218
|
-
debug( 'summary exceeds word count' );
|
|
219
|
-
summary = await summarizer.summarize( summary, { context: context } );
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
this.processEvent( {
|
|
223
|
-
id: '',
|
|
224
|
-
event: 'summary',
|
|
225
|
-
data: JSON.stringify( {
|
|
226
|
-
message: summary,
|
|
227
|
-
complete: true,
|
|
228
|
-
} ),
|
|
229
|
-
} );
|
|
230
|
-
} catch ( error ) {
|
|
231
|
-
debug( 'error', error );
|
|
232
|
-
this.processErrorEvent( error );
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|