22// Use of this source code is governed by a BSD-style license that can be
33// found in the LICENSE file.
44
5+ import * as Host from '../../core/host/host.js' ;
56import * as Root from '../../core/root/root.js' ;
67
78let builtInAiInstance : BuiltInAi | undefined ;
8- let availability = '' ;
9+ let availability : LanguageModelAvailability | undefined ;
910let hasGpu : boolean | undefined ;
11+ let isFirstRun = true ;
1012
1113export interface LanguageModel {
1214 promptStreaming : ( arg0 : string , opts ?: {
@@ -16,20 +18,33 @@ export interface LanguageModel {
1618 destroy : ( ) => void ;
1719}
1820
21+ export const enum LanguageModelAvailability {
22+ UNAVAILABLE = 'unavailable' ,
23+ DOWNLOADABLE = 'downloadable' ,
24+ DOWNLOADING = 'downloading' ,
25+ AVAILABLE = 'available' ,
26+ DISABLED = 'disabled' ,
27+ }
28+
1929export class BuiltInAi {
2030 #consoleInsightsSession: LanguageModel ;
2131
22- static async isAvailable ( ) : Promise < boolean > {
32+ static async getLanguageModelAvailability ( ) : Promise < LanguageModelAvailability > {
2333 if ( ! Root . Runtime . hostConfig . devToolsAiPromptApi ?. enabled ) {
24- return false ;
34+ return LanguageModelAvailability . DISABLED ;
35+ }
36+ try {
37+ // @ts -expect-error
38+ availability = await window . LanguageModel . availability ( { expectedOutputs : [ { type : 'text' , languages : [ 'en' ] } ] } ) as
39+ LanguageModelAvailability ;
40+ return availability ;
41+ } catch {
42+ return LanguageModelAvailability . UNAVAILABLE ;
2543 }
26- // @ts -expect-error
27- availability = await window . LanguageModel . availability ( { expectedOutputs : [ { type : 'text' , languages : [ 'en' ] } ] } ) ;
28- return availability === 'available' ;
2944 }
3045
3146 static cachedIsAvailable ( ) : boolean {
32- return availability === 'available' ;
47+ return availability === LanguageModelAvailability . AVAILABLE ;
3348 }
3449
3550 static isGpuAvailable ( ) : boolean {
@@ -67,43 +82,97 @@ export class BuiltInAi {
6782
6883 static async instance ( ) : Promise < BuiltInAi | undefined > {
6984 if ( builtInAiInstance === undefined ) {
70- if ( ! Root . Runtime . hostConfig . devToolsAiPromptApi ?. allowWithoutGpu && ! BuiltInAi . isGpuAvailable ( ) ) {
71- return undefined ;
85+ if ( isFirstRun ) {
86+ const languageModelAvailability = await BuiltInAi . getLanguageModelAvailability ( ) ;
87+ const hasGpu = BuiltInAi . isGpuAvailable ( ) ;
88+ if ( hasGpu ) {
89+ switch ( languageModelAvailability ) {
90+ case LanguageModelAvailability . UNAVAILABLE :
91+ Host . userMetrics . builtInAiAvailability ( Host . UserMetrics . BuiltInAiAvailability . UNAVAILABLE_HAS_GPU ) ;
92+ break ;
93+ case LanguageModelAvailability . DOWNLOADABLE :
94+ Host . userMetrics . builtInAiAvailability ( Host . UserMetrics . BuiltInAiAvailability . DOWNLOADABLE_HAS_GPU ) ;
95+ break ;
96+ case LanguageModelAvailability . DOWNLOADING :
97+ Host . userMetrics . builtInAiAvailability ( Host . UserMetrics . BuiltInAiAvailability . DOWNLOADING_HAS_GPU ) ;
98+ break ;
99+ case LanguageModelAvailability . AVAILABLE :
100+ Host . userMetrics . builtInAiAvailability ( Host . UserMetrics . BuiltInAiAvailability . AVAILABLE_HAS_GPU ) ;
101+ break ;
102+ case LanguageModelAvailability . DISABLED :
103+ Host . userMetrics . builtInAiAvailability ( Host . UserMetrics . BuiltInAiAvailability . DISABLED_HAS_GPU ) ;
104+ break ;
105+ }
106+ } else {
107+ switch ( languageModelAvailability ) {
108+ case LanguageModelAvailability . UNAVAILABLE :
109+ Host . userMetrics . builtInAiAvailability ( Host . UserMetrics . BuiltInAiAvailability . UNAVAILABLE_NO_GPU ) ;
110+ break ;
111+ case LanguageModelAvailability . DOWNLOADABLE :
112+ Host . userMetrics . builtInAiAvailability ( Host . UserMetrics . BuiltInAiAvailability . DOWNLOADABLE_NO_GPU ) ;
113+ break ;
114+ case LanguageModelAvailability . DOWNLOADING :
115+ Host . userMetrics . builtInAiAvailability ( Host . UserMetrics . BuiltInAiAvailability . DOWNLOADING_NO_GPU ) ;
116+ break ;
117+ case LanguageModelAvailability . AVAILABLE :
118+ Host . userMetrics . builtInAiAvailability ( Host . UserMetrics . BuiltInAiAvailability . AVAILABLE_NO_GPU ) ;
119+ break ;
120+ case LanguageModelAvailability . DISABLED :
121+ Host . userMetrics . builtInAiAvailability ( Host . UserMetrics . BuiltInAiAvailability . DISABLED_NO_GPU ) ;
122+ break ;
123+ }
124+ }
125+ isFirstRun = false ;
126+ if ( ! Root . Runtime . hostConfig . devToolsAiPromptApi ?. allowWithoutGpu && ! hasGpu ) {
127+ return undefined ;
128+ }
129+ if ( languageModelAvailability !== LanguageModelAvailability . AVAILABLE ) {
130+ return undefined ;
131+ }
132+ } else {
133+ if ( ! Root . Runtime . hostConfig . devToolsAiPromptApi ?. allowWithoutGpu && ! BuiltInAi . isGpuAvailable ( ) ) {
134+ return undefined ;
135+ }
136+ if ( ( await BuiltInAi . getLanguageModelAvailability ( ) ) !== LanguageModelAvailability . AVAILABLE ) {
137+ return undefined ;
138+ }
72139 }
73- if ( ! ( await BuiltInAi . isAvailable ( ) ) ) {
140+
141+ try {
142+ // @ts -expect-error
143+ const consoleInsightsSession = await window . LanguageModel . create ( {
144+ initialPrompts : [ {
145+ role : 'system' ,
146+ content : `
147+ You are an expert web developer. Your goal is to help a human web developer who
148+ is using Chrome DevTools to debug a web site or web app. The Chrome DevTools
149+ console is showing a message which is either an error or a warning. Please help
150+ the user understand the problematic console message.
151+
152+ Your instructions are as follows:
153+ - Explain the reason why the error or warning is showing up.
154+ - The explanation has a maximum length of 200 characters. Anything beyond this
155+ length will be cut off. Make sure that your explanation is at most 200 characters long.
156+ - Your explanation should not end in the middle of a sentence.
157+ - Your explanation should consist of a single paragraph only. Do not include any
158+ headings or code blocks. Only write a single paragraph of text.
159+ - Your response should be concise and to the point. Avoid lengthy explanations
160+ or unnecessary details.
161+ `
162+ } ] ,
163+ expectedInputs : [ {
164+ type : 'text' ,
165+ languages : [ 'en' ] ,
166+ } ] ,
167+ expectedOutputs : [ {
168+ type : 'text' ,
169+ languages : [ 'en' ] ,
170+ } ] ,
171+ } ) as LanguageModel ;
172+ builtInAiInstance = new BuiltInAi ( consoleInsightsSession ) ;
173+ } catch {
74174 return undefined ;
75175 }
76- // @ts -expect-error
77- const consoleInsightsSession = await window . LanguageModel . create ( {
78- initialPrompts : [ {
79- role : 'system' ,
80- content : `
81- You are an expert web developer. Your goal is to help a human web developer who
82- is using Chrome DevTools to debug a web site or web app. The Chrome DevTools
83- console is showing a message which is either an error or a warning. Please help
84- the user understand the problematic console message.
85-
86- Your instructions are as follows:
87- - Explain the reason why the error or warning is showing up.
88- - The explanation has a maximum length of 200 characters. Anything beyond this
89- length will be cut off. Make sure that your explanation is at most 200 characters long.
90- - Your explanation should not end in the middle of a sentence.
91- - Your explanation should consist of a single paragraph only. Do not include any
92- headings or code blocks. Only write a single paragraph of text.
93- - Your response should be concise and to the point. Avoid lengthy explanations
94- or unnecessary details.
95- `
96- } ] ,
97- expectedInputs : [ {
98- type : 'text' ,
99- languages : [ 'en' ] ,
100- } ] ,
101- expectedOutputs : [ {
102- type : 'text' ,
103- languages : [ 'en' ] ,
104- } ] ,
105- } ) as LanguageModel ;
106- builtInAiInstance = new BuiltInAi ( consoleInsightsSession ) ;
107176 }
108177 return builtInAiInstance ;
109178 }
0 commit comments