Skip to content

Commit b2f6727

Browse files
authored
Merge branch 'aws:master' into code-review-tool
2 parents 989ad78 + 41019e6 commit b2f6727

File tree

11 files changed

+240
-711
lines changed

11 files changed

+240
-711
lines changed

P261194666.md

Lines changed: 0 additions & 630 deletions
This file was deleted.

packages/amazonq/package.json

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,21 @@
560560
]
561561
},
562562
"commands": [
563+
{
564+
"command": "aws.amazonq.stopCmdExecution",
565+
"title": "Stop Amazon Q Command Execution",
566+
"category": "%AWS.amazonq.title%"
567+
},
568+
{
569+
"command": "aws.amazonq.runCmdExecution",
570+
"title": "Run Amazon Q Command Execution",
571+
"category": "%AWS.amazonq.title%"
572+
},
573+
{
574+
"command": "aws.amazonq.rejectCmdExecution",
575+
"title": "Reject Amazon Q Command Execution",
576+
"category": "%AWS.amazonq.title%"
577+
},
563578
{
564579
"command": "_aws.amazonq.notifications.dismiss",
565580
"title": "%AWS.generic.dismiss%",
@@ -850,6 +865,24 @@
850865
}
851866
],
852867
"keybindings": [
868+
{
869+
"command": "aws.amazonq.stopCmdExecution",
870+
"key": "ctrl+shift+backspace",
871+
"mac": "cmd+shift+backspace",
872+
"when": "aws.amazonq.amazonqChatLSP.isFocus"
873+
},
874+
{
875+
"command": "aws.amazonq.runCmdExecution",
876+
"key": "ctrl+shift+enter",
877+
"mac": "cmd+shift+enter",
878+
"when": "aws.amazonq.amazonqChatLSP.isFocus"
879+
},
880+
{
881+
"command": "aws.amazonq.rejectCmdExecution",
882+
"key": "ctrl+shift+r",
883+
"mac": "cmd+shift+r",
884+
"when": "aws.amazonq.amazonqChatLSP.isFocus"
885+
},
853886
{
854887
"command": "_aws.amazonq.focusChat.keybinding",
855888
"win": "win+alt+i",

packages/amazonq/src/app/inline/completion.ts

Lines changed: 73 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ import {
3434
vsCodeState,
3535
inlineCompletionsDebounceDelay,
3636
noInlineSuggestionsMsg,
37-
ReferenceInlineProvider,
3837
getDiagnosticsDifferences,
3938
getDiagnosticsOfCurrentFile,
4039
toIdeDiagnostics,
@@ -111,88 +110,88 @@ export class InlineCompletionManager implements Disposable {
111110
startLine: number,
112111
firstCompletionDisplayLatency?: number
113112
) => {
114-
// TODO: also log the seen state for other suggestions in session
115-
// Calculate timing metrics before diagnostic delay
116-
const totalSessionDisplayTime = performance.now() - requestStartTime
117-
await sleep(1000)
118-
const diagnosticDiff = getDiagnosticsDifferences(
119-
this.sessionManager.getActiveSession()?.diagnosticsBeforeAccept,
120-
getDiagnosticsOfCurrentFile()
121-
)
122-
const params: LogInlineCompletionSessionResultsParams = {
123-
sessionId: sessionId,
124-
completionSessionResult: {
125-
[item.itemId]: {
126-
seen: true,
127-
accepted: true,
128-
discarded: false,
129-
},
130-
},
131-
totalSessionDisplayTime: totalSessionDisplayTime,
132-
firstCompletionDisplayLatency: firstCompletionDisplayLatency,
133-
addedDiagnostics: diagnosticDiff.added.map((it) => toIdeDiagnostics(it)),
134-
removedDiagnostics: diagnosticDiff.removed.map((it) => toIdeDiagnostics(it)),
135-
}
136-
this.languageClient.sendNotification(this.logSessionResultMessageName, params)
137-
this.disposable.dispose()
138-
this.disposable = languages.registerInlineCompletionItemProvider(
139-
CodeWhispererConstants.platformLanguageIds,
140-
this.inlineCompletionProvider
141-
)
142-
if (item.references && item.references.length) {
143-
const referenceLog = ReferenceLogViewProvider.getReferenceLog(
144-
item.insertText as string,
145-
item.references,
146-
editor
113+
try {
114+
vsCodeState.isCodeWhispererEditing = true
115+
// TODO: also log the seen state for other suggestions in session
116+
// Calculate timing metrics before diagnostic delay
117+
const totalSessionDisplayTime = performance.now() - requestStartTime
118+
await sleep(500)
119+
const diagnosticDiff = getDiagnosticsDifferences(
120+
this.sessionManager.getActiveSession()?.diagnosticsBeforeAccept,
121+
getDiagnosticsOfCurrentFile()
147122
)
148-
ReferenceLogViewProvider.instance.addReferenceLog(referenceLog)
149-
ReferenceHoverProvider.instance.addCodeReferences(item.insertText as string, item.references)
150-
151-
// Show codelense for 5 seconds.
152-
ReferenceInlineProvider.instance.setInlineReference(
153-
startLine,
154-
item.insertText as string,
155-
item.references
123+
const params: LogInlineCompletionSessionResultsParams = {
124+
sessionId: sessionId,
125+
completionSessionResult: {
126+
[item.itemId]: {
127+
seen: true,
128+
accepted: true,
129+
discarded: false,
130+
},
131+
},
132+
totalSessionDisplayTime: totalSessionDisplayTime,
133+
firstCompletionDisplayLatency: firstCompletionDisplayLatency,
134+
addedDiagnostics: diagnosticDiff.added.map((it) => toIdeDiagnostics(it)),
135+
removedDiagnostics: diagnosticDiff.removed.map((it) => toIdeDiagnostics(it)),
136+
}
137+
this.languageClient.sendNotification(this.logSessionResultMessageName, params)
138+
this.disposable.dispose()
139+
this.disposable = languages.registerInlineCompletionItemProvider(
140+
CodeWhispererConstants.platformLanguageIds,
141+
this.inlineCompletionProvider
156142
)
157-
setTimeout(() => {
158-
ReferenceInlineProvider.instance.removeInlineReference()
159-
}, 5000)
160-
}
161-
if (item.mostRelevantMissingImports?.length) {
162-
await ImportAdderProvider.instance.onAcceptRecommendation(editor, item, startLine)
143+
if (item.references && item.references.length) {
144+
const referenceLog = ReferenceLogViewProvider.getReferenceLog(
145+
item.insertText as string,
146+
item.references,
147+
editor
148+
)
149+
ReferenceLogViewProvider.instance.addReferenceLog(referenceLog)
150+
ReferenceHoverProvider.instance.addCodeReferences(item.insertText as string, item.references)
151+
}
152+
if (item.mostRelevantMissingImports?.length) {
153+
await ImportAdderProvider.instance.onAcceptRecommendation(editor, item, startLine)
154+
}
155+
this.sessionManager.incrementSuggestionCount()
156+
// clear session manager states once accepted
157+
this.sessionManager.clear()
158+
} finally {
159+
vsCodeState.isCodeWhispererEditing = false
163160
}
164-
this.sessionManager.incrementSuggestionCount()
165-
// clear session manager states once accepted
166-
this.sessionManager.clear()
167161
}
168162
commands.registerCommand('aws.amazonq.acceptInline', onInlineAcceptance)
169163

170164
const onInlineRejection = async () => {
171-
await commands.executeCommand('editor.action.inlineSuggest.hide')
172-
// TODO: also log the seen state for other suggestions in session
173-
this.disposable.dispose()
174-
this.disposable = languages.registerInlineCompletionItemProvider(
175-
CodeWhispererConstants.platformLanguageIds,
176-
this.inlineCompletionProvider
177-
)
178-
const sessionId = this.sessionManager.getActiveSession()?.sessionId
179-
const itemId = this.sessionManager.getActiveRecommendation()[0]?.itemId
180-
if (!sessionId || !itemId) {
181-
return
182-
}
183-
const params: LogInlineCompletionSessionResultsParams = {
184-
sessionId: sessionId,
185-
completionSessionResult: {
186-
[itemId]: {
187-
seen: true,
188-
accepted: false,
189-
discarded: false,
165+
try {
166+
vsCodeState.isCodeWhispererEditing = true
167+
await commands.executeCommand('editor.action.inlineSuggest.hide')
168+
// TODO: also log the seen state for other suggestions in session
169+
this.disposable.dispose()
170+
this.disposable = languages.registerInlineCompletionItemProvider(
171+
CodeWhispererConstants.platformLanguageIds,
172+
this.inlineCompletionProvider
173+
)
174+
const sessionId = this.sessionManager.getActiveSession()?.sessionId
175+
const itemId = this.sessionManager.getActiveRecommendation()[0]?.itemId
176+
if (!sessionId || !itemId) {
177+
return
178+
}
179+
const params: LogInlineCompletionSessionResultsParams = {
180+
sessionId: sessionId,
181+
completionSessionResult: {
182+
[itemId]: {
183+
seen: true,
184+
accepted: false,
185+
discarded: false,
186+
},
190187
},
191-
},
188+
}
189+
this.languageClient.sendNotification(this.logSessionResultMessageName, params)
190+
// clear session manager states once rejected
191+
this.sessionManager.clear()
192+
} finally {
193+
vsCodeState.isCodeWhispererEditing = false
192194
}
193-
this.languageClient.sendNotification(this.logSessionResultMessageName, params)
194-
// clear session manager states once rejected
195-
this.sessionManager.clear()
196195
}
197196
commands.registerCommand('aws.amazonq.rejectCodeSuggestion', onInlineRejection)
198197
}

packages/amazonq/src/lsp/chat/commands.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,10 @@ export function registerCommands(provider: AmazonQChatViewProvider) {
6363
params: {},
6464
})
6565
})
66-
})
66+
}),
67+
registerShellCommandShortCut('aws.amazonq.runCmdExecution', 'run-shell-command', provider),
68+
registerShellCommandShortCut('aws.amazonq.rejectCmdExecution', 'reject-shell-command', provider),
69+
registerShellCommandShortCut('aws.amazonq.stopCmdExecution', 'stop-shell-command', provider)
6770
)
6871
if (codeReviewInChat) {
6972
globals.context.subscriptions.push(
@@ -176,3 +179,14 @@ export async function focusAmazonQPanel() {
176179
await Commands.tryExecute('aws.amazonq.AmazonQChatView.focus')
177180
await Commands.tryExecute('aws.amazonq.AmazonCommonAuth.focus')
178181
}
182+
183+
function registerShellCommandShortCut(commandName: string, buttonId: string, provider: AmazonQChatViewProvider) {
184+
return Commands.register(commandName, async () => {
185+
void focusAmazonQPanel().then(() => {
186+
void provider.webview?.postMessage({
187+
command: 'aws/chat/executeShellCommandShortCut',
188+
params: { id: buttonId },
189+
})
190+
})
191+
})
192+
}

packages/amazonq/src/lsp/chat/messages.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ import {
8888
openUrl,
8989
isTextEditor,
9090
globals,
91+
setContext,
9192
} from 'aws-core-vscode/shared'
9293
import {
9394
DefaultAmazonQAppInitContext,
@@ -490,6 +491,11 @@ export function registerMessageListeners(
490491
}
491492
default:
492493
if (isServerEvent(message.command)) {
494+
if (enterFocus(message.params)) {
495+
await setContext('aws.amazonq.amazonqChatLSP.isFocus', true)
496+
} else if (exitFocus(message.params)) {
497+
await setContext('aws.amazonq.amazonqChatLSP.isFocus', false)
498+
}
493499
languageClient.sendNotification(message.command, message.params)
494500
}
495501
break
@@ -699,6 +705,14 @@ function isServerEvent(command: string) {
699705
return command.startsWith('aws/chat/') || command === 'telemetry/event'
700706
}
701707

708+
function enterFocus(params: any) {
709+
return params.name === 'enterFocus'
710+
}
711+
712+
function exitFocus(params: any) {
713+
return params.name === 'exitFocus'
714+
}
715+
702716
/**
703717
* Decodes partial chat responses from the language server before sending them to mynah UI
704718
*/

packages/amazonq/src/lsp/chat/webviewProvider.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
Webview,
1414
} from 'vscode'
1515
import * as path from 'path'
16+
import * as os from 'os'
1617
import {
1718
globals,
1819
isSageMaker,
@@ -149,7 +150,7 @@ export class AmazonQChatViewProvider implements WebviewViewProvider {
149150
const vscodeApi = acquireVsCodeApi()
150151
const hybridChatConnector = new HybridChatAdapter(${(await AuthUtil.instance.getChatAuthState()).amazonQ === 'connected'},${featureConfigData},${welcomeCount},${disclaimerAcknowledged},${regionProfileString},${disabledCommands},${isSMUS},${isSM},vscodeApi.postMessage)
151152
const commands = [hybridChatConnector.initialQuickActions[0]]
152-
qChat = amazonQChat.createChat(vscodeApi, {disclaimerAcknowledged: ${disclaimerAcknowledged}, pairProgrammingAcknowledged: ${pairProgrammingAcknowledged}, agenticMode: true, quickActionCommands: commands, modelSelectionEnabled: ${modelSelectionEnabled}}, hybridChatConnector, ${JSON.stringify(featureConfigData)});
153+
qChat = amazonQChat.createChat(vscodeApi, {os: "${os.platform()}", disclaimerAcknowledged: ${disclaimerAcknowledged}, pairProgrammingAcknowledged: ${pairProgrammingAcknowledged}, agenticMode: true, quickActionCommands: commands, modelSelectionEnabled: ${modelSelectionEnabled}}, hybridChatConnector, ${JSON.stringify(featureConfigData)});
153154
}
154155
window.addEventListener('message', (event) => {
155156
/**

packages/amazonq/src/lsp/client.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ export async function startLanguageServer(
166166
pinnedContextEnabled: true,
167167
imageContextEnabled: true,
168168
mcp: true,
169+
shortcut: true,
169170
reroute: true,
170171
modelSelection: true,
171172
workspaceFilePath: vscode.workspace.workspaceFile?.fsPath,

0 commit comments

Comments
 (0)