@@ -12,9 +12,16 @@ import {
1212 WebviewViewResolveContext ,
1313 Uri ,
1414} from 'vscode'
15- import { QuickActionCommandGroup } from '@aws/mynah-ui'
1615import * as path from 'path'
17- import { AmazonQPromptSettings , LanguageServerResolver } from 'aws-core-vscode/shared'
16+ import {
17+ globals ,
18+ isSageMaker ,
19+ AmazonQPromptSettings ,
20+ LanguageServerResolver ,
21+ amazonqMark ,
22+ } from 'aws-core-vscode/shared'
23+ import { AuthUtil , RegionProfile } from 'aws-core-vscode/codewhisperer'
24+ import { featureConfig } from 'aws-core-vscode/amazonq'
1825
1926export class AmazonQChatViewProvider implements WebviewViewProvider {
2027 public static readonly viewType = 'aws.amazonq.AmazonQChatView'
@@ -23,24 +30,6 @@ export class AmazonQChatViewProvider implements WebviewViewProvider {
2330
2431 webview : Webview | undefined
2532
26- private readonly quickActionCommands : QuickActionCommandGroup [ ] = [
27- {
28- groupName : 'Quick Actions' ,
29- commands : [
30- {
31- command : '/help' ,
32- icon : 'help' ,
33- description : 'Learn more about Amazon Q' ,
34- } ,
35- {
36- command : '/clear' ,
37- icon : 'trash' ,
38- description : 'Clear this session' ,
39- } ,
40- ] ,
41- } ,
42- ]
43-
4433 constructor ( private readonly mynahUIPath : string ) { }
4534
4635 public async resolveWebviewView (
@@ -51,25 +40,60 @@ export class AmazonQChatViewProvider implements WebviewViewProvider {
5140 this . webview = webviewView . webview
5241
5342 const lspDir = Uri . parse ( LanguageServerResolver . defaultDir )
43+ const dist = Uri . joinPath ( globals . context . extensionUri , 'dist' )
5444 webviewView . webview . options = {
5545 enableScripts : true ,
5646 enableCommandUris : true ,
57- localResourceRoots : [ lspDir , Uri . parse ( path . dirname ( this . mynahUIPath ) ) ] ,
47+ localResourceRoots : [ lspDir , dist ] ,
5848 }
5949
50+ const source = 'vue/src/amazonq/webview/ui/amazonq-ui-connector-adapter.js' // Sent to dist/vue folder in webpack.
51+ const serverHostname = process . env . WEBPACK_DEVELOPER_SERVER
52+ const connectorAdapterPath =
53+ serverHostname !== undefined
54+ ? Uri . parse ( serverHostname )
55+ . with ( { path : `/${ source } ` } )
56+ . toString ( )
57+ : webviewView . webview . asWebviewUri ( Uri . parse ( path . join ( dist . fsPath , source ) ) ) . toString ( )
6058 const uiPath = webviewView . webview . asWebviewUri ( Uri . parse ( this . mynahUIPath ) ) . toString ( )
61- webviewView . webview . html = await this . getWebviewContent ( uiPath )
59+ webviewView . webview . html = await this . getWebviewContent ( uiPath , connectorAdapterPath )
6260
6361 this . onDidResolveWebviewEmitter . fire ( )
62+ performance . mark ( amazonqMark . open )
6463 }
6564
66- private async getWebviewContent ( mynahUIPath : string ) {
65+ private async getWebviewContent ( mynahUIPath : string , hybridChatConnector : string ) {
66+ const featureConfigData = await featureConfig . getFeatureConfigs ( )
67+
68+ const isSM = isSageMaker ( 'SMAI' )
69+ const isSMUS = isSageMaker ( 'SMUS' )
70+ const disabledCommands = isSM ? `['/dev', '/transform', '/test', '/review', '/doc']` : '[]'
6771 const disclaimerAcknowledged = AmazonQPromptSettings . instance . isPromptEnabled ( 'amazonQChatDisclaimer' )
72+ const welcomeCount = globals . globalState . tryGet ( 'aws.amazonq.welcomeChatShowCount' , Number , 0 )
73+
74+ // only show profile card when the two conditions
75+ // 1. profile count >= 2
76+ // 2. not default (fallback) which has empty arn
77+ let regionProfile : RegionProfile | undefined = AuthUtil . instance . regionProfileManager . activeRegionProfile
78+ if ( AuthUtil . instance . regionProfileManager . profiles . length === 1 ) {
79+ regionProfile = undefined
80+ }
81+
82+ const regionProfileString : string = JSON . stringify ( regionProfile )
83+
84+ const entrypoint = process . env . WEBPACK_DEVELOPER_SERVER
85+ ? 'http: localhost'
86+ : 'https: file+.vscode-resources.vscode-cdn.net'
87+
88+ const contentPolicy = `default-src ${ entrypoint } data: blob: 'unsafe-inline';
89+ script-src ${ entrypoint } filesystem: ws: wss: 'unsafe-inline';`
90+
6891 return `
6992 <!DOCTYPE html>
7093 <html lang="en">
7194 <head>
7295 <meta charset="UTF-8">
96+ <meta http-equiv="Content-Security-Policy" content="${ contentPolicy } ">
7397 <meta name="viewport" content="width=device-width, initial-scale=1.0">
7498 <title>Chat</title>
7599 <style>
@@ -87,9 +111,27 @@ export class AmazonQChatViewProvider implements WebviewViewProvider {
87111 </head>
88112 <body>
89113 <script type="text/javascript" src="${ mynahUIPath . toString ( ) } " defer onload="init()"></script>
114+ <script type="text/javascript" src="${ hybridChatConnector . toString ( ) } "></script>
90115 <script type="text/javascript">
91116 const init = () => {
92- amazonQChat.createChat(acquireVsCodeApi(), { disclaimerAcknowledged: ${ disclaimerAcknowledged } , quickActionCommands: ${ JSON . stringify ( this . quickActionCommands ) } });
117+ const vscodeApi = acquireVsCodeApi()
118+ const hybridChatConnector = new HybridChatAdapter(${ ( await AuthUtil . instance . getChatAuthState ( ) ) . amazonQ === 'connected' } ,${ featureConfigData } ,${ welcomeCount } ,${ disclaimerAcknowledged } ,${ regionProfileString } ,${ disabledCommands } ,${ isSMUS } ,${ isSM } ,vscodeApi.postMessage)
119+ const commands = [hybridChatConnector.initialQuickActions[0], {
120+ groupName: 'Quick Actions',
121+ commands: [
122+ {
123+ command: '/help',
124+ icon: 'help',
125+ description: 'Learn more about Amazon Q',
126+ },
127+ {
128+ command: '/clear',
129+ icon: 'trash',
130+ description: 'Clear this session 2',
131+ },
132+ ],
133+ }]
134+ amazonQChat.createChat(vscodeApi, {disclaimerAcknowledged: ${ disclaimerAcknowledged } , quickActionCommands: commands}, hybridChatConnector);
93135 }
94136 </script>
95137 </body>
0 commit comments