Skip to content

Commit bf77749

Browse files
Merge branch 'master' into feature/hybridChat
2 parents 1e45112 + 638778b commit bf77749

File tree

13 files changed

+148
-43
lines changed

13 files changed

+148
-43
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Bug Fix",
3+
"description": "Toast message to warn users if Developer Profile is not selected"
4+
}

packages/amazonq/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@
135135
"amazonQChatPairProgramming": {
136136
"type": "boolean",
137137
"default": false
138+
},
139+
"amazonQSelectDeveloperProfile": {
140+
"type": "boolean",
141+
"default": false
138142
}
139143
},
140144
"additionalProperties": false

packages/amazonq/test/e2e/inline/inline.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ describe('Amazon Q Inline', async function () {
122122
.query({
123123
metricName: 'codewhisperer_userTriggerDecision',
124124
})
125-
.map((e) => collectionUtil.partialClone(e, 3, ['credentialStartUrl'], '[omitted]'))
125+
.map((e) => collectionUtil.partialClone(e, 3, ['credentialStartUrl'], { replacement: '[omitted]' }))
126126
}
127127

128128
for (const [name, invokeCompletion] of [

packages/core/src/auth/sso/clients.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ function addLoggingMiddleware(client: SSOOIDCClient) {
258258
args.input as unknown as Record<string, unknown>,
259259
3,
260260
['clientSecret', 'accessToken', 'refreshToken'],
261-
'[omitted]'
261+
{ replacement: '[omitted]' }
262262
)
263263
getLogger().debug('API request (%s %s): %O', hostname, path, input)
264264
}
@@ -288,7 +288,7 @@ function addLoggingMiddleware(client: SSOOIDCClient) {
288288
result.output as unknown as Record<string, unknown>,
289289
3,
290290
['clientSecret', 'accessToken', 'refreshToken'],
291-
'[omitted]'
291+
{ replacement: '[omitted]' }
292292
)
293293
getLogger().debug('API response (%s %s): %O', hostname, path, output)
294294
}

packages/core/src/codewhisperer/activation.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ import { SecurityIssueTreeViewProvider } from './service/securityIssueTreeViewPr
9595
import { setContext } from '../shared/vscode/setContext'
9696
import { syncSecurityIssueWebview } from './views/securityIssue/securityIssueWebview'
9797
import { detectCommentAboveLine } from '../shared/utilities/commentUtils'
98+
import { notifySelectDeveloperProfile } from './region/utils'
9899

99100
let localize: nls.LocalizeFunc
100101

@@ -380,6 +381,10 @@ export async function activate(context: ExtContext): Promise<void> {
380381
await auth.notifySessionConfiguration()
381382
}
382383
}
384+
385+
if (auth.requireProfileSelection()) {
386+
await notifySelectDeveloperProfile()
387+
}
383388
},
384389
{ emit: false, functionId: { name: 'activateCwCore' } }
385390
)

packages/core/src/codewhisperer/commands/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ export const firstStartUpSource = ExtStartUpSources.firstStartUp
1818
export const cwEllipsesMenu = 'ellipsesMenu'
1919
/** Indicates a CodeWhisperer command was executed from the command palette */
2020
export const commandPalette = 'commandPalette'
21+
/** Indicates a CodeWhisperer command was executed as a result of a toast message interaction */
22+
export const toastMessage = 'toastMessage'
2123

2224
/**
2325
* Indicates what caused the CodeWhisperer command to be executed, since a command can be executed from different "sources"
@@ -35,3 +37,4 @@ export type CodeWhispererSource =
3537
| typeof firstStartUpSource
3638
| typeof cwEllipsesMenu
3739
| typeof commandPalette
40+
| typeof toastMessage
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
import * as nls from 'vscode-nls'
6+
const localize = nls.loadMessageBundle()
7+
import { AmazonQPromptSettings } from '../../shared/settings'
8+
import { telemetry } from '../../shared/telemetry/telemetry'
9+
import vscode from 'vscode'
10+
import { selectRegionProfileCommand } from '../commands/basicCommands'
11+
import { placeholder } from '../../shared/vscode/commands2'
12+
import { toastMessage } from '../commands/types'
13+
14+
/**
15+
* Creates a toast message telling the user they need to select a Developer Profile
16+
*/
17+
export async function notifySelectDeveloperProfile() {
18+
const suppressId = 'amazonQSelectDeveloperProfile'
19+
const settings = AmazonQPromptSettings.instance
20+
const shouldShow = settings.isPromptEnabled(suppressId)
21+
if (!shouldShow) {
22+
return
23+
}
24+
25+
const message = localize(
26+
'aws.amazonq.profile.mustSelectMessage',
27+
'You must select a Q Developer Profile for Amazon Q features to work.'
28+
)
29+
const selectProfile = 'Select Profile'
30+
const dontShowAgain = 'Dont Show Again'
31+
32+
await telemetry.toolkit_showNotification.run(async () => {
33+
telemetry.record({ id: 'mustSelectDeveloperProfileMessage' })
34+
void vscode.window.showWarningMessage(message, selectProfile, dontShowAgain).then(async (resp) => {
35+
await telemetry.toolkit_invokeAction.run(async () => {
36+
if (resp === selectProfile) {
37+
// Show Profile
38+
telemetry.record({ action: 'select' })
39+
void selectRegionProfileCommand.execute(placeholder, toastMessage)
40+
} else if (resp === dontShowAgain) {
41+
telemetry.record({ action: 'dontShowAgain' })
42+
await settings.disablePrompt(suppressId)
43+
} else {
44+
telemetry.record({ action: 'ignore' })
45+
}
46+
})
47+
})
48+
})
49+
}

packages/core/src/codewhisperer/util/authUtil.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import { withTelemetryContext } from '../../shared/telemetry/util'
4646
import { focusAmazonQPanel } from '../../codewhispererChat/commands/registerCommands'
4747
import { throttle } from 'lodash'
4848
import { RegionProfileManager } from '../region/regionProfileManager'
49+
4950
/** Backwards compatibility for connections w pre-chat scopes */
5051
export const codeWhispererCoreScopes = [...scopesCodeWhispererCore]
5152
export const codeWhispererChatScopes = [...codeWhispererCoreScopes, ...scopesCodeWhispererChat]

packages/core/src/shared/settings-amazonq.gen.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ export const amazonqSettings = {
2222
"amazonQLspManifestMessage": {},
2323
"amazonQWorkspaceLspManifestMessage": {},
2424
"amazonQChatDisclaimer": {},
25-
"amazonQChatPairProgramming": {}
25+
"amazonQChatPairProgramming": {},
26+
"amazonQSelectDeveloperProfile": {}
2627
},
2728
"amazonQ.showCodeWithReferences": {},
2829
"amazonQ.allowFeatureDevelopmentToRunCodeAndTests": {},

packages/core/src/shared/utilities/collectionUtils.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { isWeb } from '../extensionGlobals'
77
import { inspect as nodeInspect } from 'util'
88
import { AsyncCollection, toCollection } from './asyncCollection'
99
import { SharedProp, AccumulableKeys, Coalesce, isNonNullable } from './tsUtils'
10+
import { truncate } from './textUtilities'
1011

1112
export function union<T>(a: Iterable<T>, b: Iterable<T>): Set<T> {
1213
const result = new Set<T>()
@@ -304,26 +305,38 @@ export function assign<T extends Record<any, any>, U extends Partial<T>>(data: T
304305
* @param depth
305306
* @param omitKeys Omit properties matching these names (at any depth).
306307
* @param replacement Replacement for object whose fields extend beyond `depth`, and properties matching `omitKeys`.
308+
* @param maxStringLength truncates string values that exceed this threshold (includes values in nested arrays)
307309
*/
308-
export function partialClone(obj: any, depth: number = 3, omitKeys: string[] = [], replacement?: any): any {
310+
export function partialClone(
311+
obj: any,
312+
depth: number = 3,
313+
omitKeys: string[] = [],
314+
options?: {
315+
replacement?: any
316+
maxStringLength?: number
317+
}
318+
): any {
309319
// Base case: If input is not an object or has no children, return it.
310320
if (typeof obj !== 'object' || obj === null || 0 === Object.getOwnPropertyNames(obj).length) {
321+
if (typeof obj === 'string' && options?.maxStringLength) {
322+
return truncate(obj, options?.maxStringLength, '...')
323+
}
311324
return obj
312325
}
313326

314327
// Create a new object of the same type as the input object.
315328
const clonedObj = Array.isArray(obj) ? [] : {}
316329

317330
if (depth === 0) {
318-
return replacement ? replacement : clonedObj
331+
return options?.replacement ? options.replacement : clonedObj
319332
}
320333

321334
// Recursively clone properties of the input object
322335
for (const key in obj) {
323336
if (omitKeys.includes(key)) {
324-
;(clonedObj as any)[key] = replacement ? replacement : Array.isArray(obj) ? [] : {}
337+
;(clonedObj as any)[key] = options?.replacement ? options.replacement : Array.isArray(obj) ? [] : {}
325338
} else if (Object.prototype.hasOwnProperty.call(obj, key)) {
326-
;(clonedObj as any)[key] = partialClone(obj[key], depth - 1, omitKeys, replacement)
339+
;(clonedObj as any)[key] = partialClone(obj[key], depth - 1, omitKeys, options)
327340
}
328341
}
329342

0 commit comments

Comments
 (0)