Skip to content

Commit 398744e

Browse files
Getting Started for CodeWhisperer (#3805)
* Initial commit with getting Started Node featuring Resources Shortcuts Scan Code and Learn Node * Updated Feedback Logic & Generate suggestions Tab * feature: Banner visible only for 1st time Signin * Added Workshop and implemented create and save Files * CW: Code Refactoring and Revised CSS * CW: Revised CSS * feature: Banner in Getting Started Page is visible only once to new and existing users * CW: Refactored Code * CW: Various changes in CSS and Telemetry * CW: Revised Code changes * CW: Revised code * CW: Telemetry changes for Getting Started - Try Example * CW: State changes comments * Revised changes * Delete Unwanted Settings.json file * Revised code changes * CR Changes * Telemetry metric name changes * CW: Telemetry Revised Changes * Revised Changes * Revised Changed after F&F * CW: Dogfooding Changes * CW: Revised Telemetry Changes * CW: Revised Changes in Scan Code * CW: Changes in Comments: * CW: Changes in Telemetry names * CW: Changes in Generate Code Suggestions * PR Changes --------- Co-authored-by: aws-toolkit-automation <[email protected]>
1 parent 8fe1b35 commit 398744e

27 files changed

+1563
-93
lines changed

package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,10 @@
218218
"type": "boolean",
219219
"default": false
220220
},
221+
"codeWhispererNewWelcomeMessage": {
222+
"type": "boolean",
223+
"default": false
224+
},
221225
"codeWhispererConnectionExpired": {
222226
"type": "boolean",
223227
"default": false
@@ -3452,103 +3456,110 @@
34523456
"fontCharacter": "\\f1ae"
34533457
}
34543458
},
3455-
"aws-ecr-registry": {
3459+
"aws-codewhisperer-learn": {
34563460
"description": "AWS Contributed Icon",
34573461
"default": {
34583462
"fontPath": "./resources/fonts/aws-toolkit-icons.woff",
34593463
"fontCharacter": "\\f1af"
34603464
}
34613465
},
3462-
"aws-ecs-cluster": {
3466+
"aws-ecr-registry": {
34633467
"description": "AWS Contributed Icon",
34643468
"default": {
34653469
"fontPath": "./resources/fonts/aws-toolkit-icons.woff",
34663470
"fontCharacter": "\\f1b0"
34673471
}
34683472
},
3469-
"aws-ecs-container": {
3473+
"aws-ecs-cluster": {
34703474
"description": "AWS Contributed Icon",
34713475
"default": {
34723476
"fontPath": "./resources/fonts/aws-toolkit-icons.woff",
34733477
"fontCharacter": "\\f1b1"
34743478
}
34753479
},
3476-
"aws-ecs-service": {
3480+
"aws-ecs-container": {
34773481
"description": "AWS Contributed Icon",
34783482
"default": {
34793483
"fontPath": "./resources/fonts/aws-toolkit-icons.woff",
34803484
"fontCharacter": "\\f1b2"
34813485
}
34823486
},
3483-
"aws-generic-attach-file": {
3487+
"aws-ecs-service": {
34843488
"description": "AWS Contributed Icon",
34853489
"default": {
34863490
"fontPath": "./resources/fonts/aws-toolkit-icons.woff",
34873491
"fontCharacter": "\\f1b3"
34883492
}
34893493
},
3490-
"aws-iot-certificate": {
3494+
"aws-generic-attach-file": {
34913495
"description": "AWS Contributed Icon",
34923496
"default": {
34933497
"fontPath": "./resources/fonts/aws-toolkit-icons.woff",
34943498
"fontCharacter": "\\f1b4"
34953499
}
34963500
},
3497-
"aws-iot-policy": {
3501+
"aws-iot-certificate": {
34983502
"description": "AWS Contributed Icon",
34993503
"default": {
35003504
"fontPath": "./resources/fonts/aws-toolkit-icons.woff",
35013505
"fontCharacter": "\\f1b5"
35023506
}
35033507
},
3504-
"aws-iot-thing": {
3508+
"aws-iot-policy": {
35053509
"description": "AWS Contributed Icon",
35063510
"default": {
35073511
"fontPath": "./resources/fonts/aws-toolkit-icons.woff",
35083512
"fontCharacter": "\\f1b6"
35093513
}
35103514
},
3511-
"aws-lambda-function": {
3515+
"aws-iot-thing": {
35123516
"description": "AWS Contributed Icon",
35133517
"default": {
35143518
"fontPath": "./resources/fonts/aws-toolkit-icons.woff",
35153519
"fontCharacter": "\\f1b7"
35163520
}
35173521
},
3518-
"aws-s3-bucket": {
3522+
"aws-lambda-function": {
35193523
"description": "AWS Contributed Icon",
35203524
"default": {
35213525
"fontPath": "./resources/fonts/aws-toolkit-icons.woff",
35223526
"fontCharacter": "\\f1b8"
35233527
}
35243528
},
3525-
"aws-s3-create-bucket": {
3529+
"aws-s3-bucket": {
35263530
"description": "AWS Contributed Icon",
35273531
"default": {
35283532
"fontPath": "./resources/fonts/aws-toolkit-icons.woff",
35293533
"fontCharacter": "\\f1b9"
35303534
}
35313535
},
3532-
"aws-schemas-registry": {
3536+
"aws-s3-create-bucket": {
35333537
"description": "AWS Contributed Icon",
35343538
"default": {
35353539
"fontPath": "./resources/fonts/aws-toolkit-icons.woff",
35363540
"fontCharacter": "\\f1ba"
35373541
}
35383542
},
3539-
"aws-schemas-schema": {
3543+
"aws-schemas-registry": {
35403544
"description": "AWS Contributed Icon",
35413545
"default": {
35423546
"fontPath": "./resources/fonts/aws-toolkit-icons.woff",
35433547
"fontCharacter": "\\f1bb"
35443548
}
35453549
},
3546-
"aws-stepfunctions-preview": {
3550+
"aws-schemas-schema": {
35473551
"description": "AWS Contributed Icon",
35483552
"default": {
35493553
"fontPath": "./resources/fonts/aws-toolkit-icons.woff",
35503554
"fontCharacter": "\\f1bc"
35513555
}
3556+
},
3557+
"aws-stepfunctions-preview": {
3558+
"description": "AWS Contributed Icon",
3559+
"default": {
3560+
"fontPath": "./resources/fonts/aws-toolkit-icons.woff",
3561+
"fontCharacter": "\\f1bd"
3562+
}
35523563
}
35533564
}
35543565
},
@@ -3583,7 +3594,7 @@
35833594
"report": "nyc report --reporter=html --reporter=json"
35843595
},
35853596
"devDependencies": {
3586-
"@aws-toolkits/telemetry": "^1.0.143",
3597+
"@aws-toolkits/telemetry": "^1.0.144",
35873598
"@cspotcode/source-map-support": "^0.8.1",
35883599
"@sinonjs/fake-timers": "^10.0.2",
35893600
"@types/adm-zip": "^0.4.34",
Lines changed: 3 additions & 0 deletions
Loading

src/awsexplorer/activation.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,12 @@ async function registerAwsExplorerCommands(
119119
telemetry.vscode_activeRegions.emit({ value: awsExplorer.getRegionNodesSize() })
120120
}
121121
}),
122-
Commands.register({ id: 'aws.submitFeedback', autoconnect: false }, async () => {
123-
await submitFeedback(context)
122+
Commands.register({ id: 'aws.submitFeedback', autoconnect: false }, async id => {
123+
if (id === 'CodeWhisperer') {
124+
await submitFeedback(context, 'CodeWhisperer')
125+
} else {
126+
await submitFeedback(context, 'AWS Toolkit')
127+
}
124128
}),
125129
Commands.register({ id: 'aws.refreshAwsExplorer', autoconnect: true }, async (passive: boolean = false) => {
126130
awsExplorer.refresh()

src/codewhisperer/activation.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,15 @@ import { ReferenceInlineProvider } from './service/referenceInlineProvider'
4141
import { SecurityPanelViewProvider } from './views/securityPanelViewProvider'
4242
import { disposeSecurityDiagnostic } from './service/diagnosticsProvider'
4343
import { RecommendationHandler } from './service/recommendationHandler'
44-
import { Commands } from '../shared/vscode/commands2'
44+
import { Commands, registerCommandsWithVSCode } from '../shared/vscode/commands2'
4545
import { InlineCompletionService } from './service/inlineCompletionService'
4646
import { isInlineCompletionEnabled } from './util/commonUtil'
4747
import { CodeWhispererCodeCoverageTracker } from './tracker/codewhispererCodeCoverageTracker'
4848
import { AuthUtil } from './util/authUtil'
4949
import { ImportAdderProvider } from './service/importAdderProvider'
5050
import { TelemetryHelper } from './util/telemetryHelper'
5151
import { openUrl } from '../shared/utilities/vsCodeUtils'
52-
52+
import { CodeWhispererCommandBackend, CodeWhispererCommandDeclarations } from './commands/gettingStartedPageCommands'
5353
const performance = globalThis.performance ?? require('perf_hooks').performance
5454

5555
export async function activate(context: ExtContext): Promise<void> {
@@ -64,6 +64,12 @@ export async function activate(context: ExtContext): Promise<void> {
6464
await enableDefaultConfigCloud9()
6565
}
6666

67+
registerCommandsWithVSCode(
68+
context.extensionContext,
69+
CodeWhispererCommandDeclarations.instance,
70+
new CodeWhispererCommandBackend(context.extensionContext)
71+
)
72+
6773
/**
6874
* CodeWhisperer security panel
6975
*/

src/codewhisperer/commands/basicCommands.ts

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ import { AuthUtil } from '../util/authUtil'
1919
import { isCloud9 } from '../../shared/extensionUtilities'
2020
import { InlineCompletionService } from '../service/inlineCompletionService'
2121
import { openUrl } from '../../shared/utilities/vsCodeUtils'
22+
import { CodeWhispererCommandDeclarations } from '../commands/gettingStartedPageCommands'
23+
import { getIcon } from '../../shared/icons'
24+
import { localize } from '../../shared/utilities/vsCodeUtils'
25+
import { PromptSettings } from '../../shared/settings'
2226

2327
export const toggleCodeSuggestions = Commands.declare(
2428
'aws.codeWhisperer.toggleCodeSuggestion',
@@ -35,21 +39,31 @@ export const toggleCodeSuggestions = Commands.declare(
3539
})
3640
}
3741
)
42+
/*
43+
createGettingStartedNode(Learn) will be a childnode of CodeWhisperer
44+
onClick on this "Learn" Node will open the Learn CodeWhisperer Page.
45+
*/
46+
export const createGettingStartedNode = () =>
47+
CodeWhispererCommandDeclarations.instance.declared.showGettingStartedPage
48+
.build('codewhispererDeveloperTools')
49+
.asTreeNode({
50+
label: localize('AWS.explorerNode.codewhispererGettingStartedNode.label', 'Learn'),
51+
iconPath: getIcon('aws-codewhisperer-learn'),
52+
})
3853

3954
export const enableCodeSuggestions = Commands.declare(
4055
'aws.codeWhisperer.enableCodeSuggestions',
4156
(context: ExtContext) => async () => {
4257
await set(CodeWhispererConstants.autoTriggerEnabledKey, true, context.extensionContext.globalState)
4358
await vscode.commands.executeCommand('setContext', 'CODEWHISPERER_ENABLED', true)
4459
await vscode.commands.executeCommand('aws.codeWhisperer.refresh')
60+
const prompts = PromptSettings.instance
4561

46-
const hasShownWelcomeMsgBefore = get(
47-
CodeWhispererConstants.welcomeMessageKey,
48-
context.extensionContext.globalState
49-
)
50-
if (!hasShownWelcomeMsgBefore) {
51-
showCodeWhispererWelcomeMessage(context)
52-
await set(CodeWhispererConstants.welcomeMessageKey, true, context.extensionContext.globalState)
62+
const shouldShow = await prompts.isPromptEnabled('codeWhispererNewWelcomeMessage')
63+
//If user login old or new, If welcome message is not shown then open the Getting Started Page after this mark it as SHOWN.
64+
if (shouldShow) {
65+
vscode.commands.executeCommand('aws.codeWhisperer.gettingStarted', createGettingStartedNode())
66+
prompts.update('codeWhispererNewWelcomeMessage', true)
5367
}
5468
if (!isCloud9()) {
5569
await vscode.commands.executeCommand('aws.codeWhisperer.refreshStatusBar')
@@ -132,14 +146,6 @@ export const updateReferenceLog = Commands.declare(
132146
}
133147
)
134148

135-
async function showCodeWhispererWelcomeMessage(context: ExtContext): Promise<void> {
136-
const filePath = isCloud9()
137-
? context.extensionContext.asAbsolutePath(CodeWhispererConstants.welcomeCodeWhispererCloud9Readme)
138-
: context.extensionContext.asAbsolutePath(CodeWhispererConstants.welcomeCodeWhispererReadmeFileSource)
139-
const readmeUri = vscode.Uri.file(filePath)
140-
await vscode.commands.executeCommand('markdown.showPreviewToSide', readmeUri)
141-
}
142-
143149
export const refreshStatusBar = Commands.declare(
144150
{ id: 'aws.codeWhisperer.refreshStatusBar', logging: false },
145151
() => () => {
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
import * as vscode from 'vscode'
6+
import { CommandDeclarations, Commands } from '../../shared/vscode/commands2'
7+
import { showCodeWhispererWebview, CodeWhispererSource } from '../vue/backend'
8+
import { telemetry } from '../../shared/telemetry/telemetry'
9+
/**
10+
* The methods with backend logic for the Codewhisperer Getting Started Page commands.
11+
*/
12+
export class CodeWhispererCommandBackend {
13+
constructor(private readonly extContext: vscode.ExtensionContext) {}
14+
public showGettingStartedPage(source: CodeWhispererSource) {
15+
telemetry.ui_click.emit({ elementId: 'codewhisperer_Learn_ButtonClick', passive: true })
16+
return showCodeWhispererWebview(this.extContext, source)
17+
}
18+
}
19+
/**
20+
* Declared commands related to CodeWhisperer in the toolkit.
21+
*/
22+
export class CodeWhispererCommandDeclarations implements CommandDeclarations<CodeWhispererCommandBackend> {
23+
static #instance: CodeWhispererCommandDeclarations
24+
25+
static get instance(): CodeWhispererCommandDeclarations {
26+
return (this.#instance ??= new CodeWhispererCommandDeclarations())
27+
}
28+
public readonly declared = {
29+
showGettingStartedPage: Commands.from(CodeWhispererCommandBackend).declareShowGettingStartedPage(
30+
'aws.codeWhisperer.gettingStarted'
31+
),
32+
} as const
33+
}

src/codewhisperer/explorer/codewhispererNode.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
createFreeTierLimitMetNode,
1616
createReconnectNode,
1717
} from './codewhispererChildrenNodes'
18+
import { createGettingStartedNode } from '../commands/basicCommands'
1819
import { Commands } from '../../shared/vscode/commands2'
1920
import { RootNode } from '../../awsexplorer/localExplorer'
2021
import { isCloud9 } from '../../shared/extensionUtilities'
@@ -87,6 +88,7 @@ export class CodeWhispererNode implements RootNode {
8788
createAutoSuggestionsNode(autoTriggerEnabled),
8889
createSecurityScanNode(),
8990
createOpenReferenceLogNode(),
91+
createGettingStartedNode(), // "Learn" node : opens Learn CodeWhisperer page
9092
]
9193
}
9294
}

src/codewhisperer/models/constants.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,6 @@ export const welcomeCodeWhispererReadmeFileSource = 'resources/markdown/WelcomeT
123123

124124
export const welcomeCodeWhispererCloud9Readme = 'resources/markdown/WelcomeToCodeWhispererCloud9.md'
125125

126-
export const welcomeMessageKey = 'CODEWHISPERER_WELCOME_MESSAGE'
127-
128126
/**
129127
* Key bindings JSON file path
130128
*/

src/codewhisperer/service/recommendationHandler.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { showTimedMessage } from '../../shared/utilities/messages'
2424
import {
2525
CodewhispererAutomatedTriggerType,
2626
CodewhispererCompletionType,
27+
CodewhispererGettingStartedTask,
2728
CodewhispererTriggerType,
2829
telemetry,
2930
} from '../../shared/telemetry/telemetry'
@@ -134,6 +135,20 @@ export class RecommendationHandler {
134135
}
135136
}
136137

138+
async getTaskTypeFromEditorFileName(fileName: string): Promise<CodewhispererGettingStartedTask> {
139+
if (fileName.startsWith('CodeWhisperer_generate_suggestion')) {
140+
return 'autoTrigger'
141+
} else if (fileName.startsWith('CodeWhisperer_manual_invoke')) {
142+
return 'manualTrigger'
143+
} else if (fileName.startsWith('CodeWhisperer_use_comments')) {
144+
return 'commentAsPrompt'
145+
} else if (fileName.startsWith('CodeWhisperer_navigate_suggestions')) {
146+
return 'navigation'
147+
} else {
148+
return 'unitTest'
149+
}
150+
}
151+
137152
async getRecommendations(
138153
client: DefaultCodeWhispererClient,
139154
editor: vscode.TextEditor,
@@ -161,6 +176,7 @@ export class RecommendationHandler {
161176
let nextToken = ''
162177
let shouldRecordServiceInvocation = true
163178
session.language = runtimeLanguageContext.getLanguageContext(editor.document.languageId).language
179+
session.taskType = await this.getTaskTypeFromEditorFileName(editor.document.fileName)
164180

165181
if (pagination) {
166182
if (page === 0) {

0 commit comments

Comments
 (0)