Skip to content

Commit bd8e663

Browse files
committed
Merge remote-tracking branch 'upstream/master' into nep
2 parents 4959444 + c59b435 commit bd8e663

File tree

26 files changed

+730
-468
lines changed

26 files changed

+730
-468
lines changed

.github/workflows/setup-release-candidate.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ jobs:
4949
5050
# Add generated license files
5151
git add LICENSE-THIRD-PARTY
52-
git commit -m "Update third-party license attribution for $BRANCH_NAME"
52+
# If there are no changes, then we don't need a new attribution commit
53+
git commit -m "Update third-party license attribution for $BRANCH_NAME" || true
5354
5455
# Push RC branch
5556
git push origin $BRANCH_NAME

LICENSE-THIRD-PARTY

Lines changed: 396 additions & 396 deletions
Large diffs are not rendered by default.

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"date": "2025-10-10",
3+
"version": "1.99.0",
4+
"entries": []
5+
}

packages/amazonq/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 1.99.0 2025-10-10
2+
3+
- Miscellaneous non-user-facing changes
4+
15
## 1.98.0 2025-10-02
26

37
- Miscellaneous non-user-facing changes

packages/amazonq/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "amazon-q-vscode",
33
"displayName": "Amazon Q",
44
"description": "The most capable generative AI–powered assistant for software development.",
5-
"version": "1.99.0-SNAPSHOT",
5+
"version": "1.100.0-SNAPSHOT",
66
"extensionKind": [
77
"workspace"
88
],

packages/amazonq/src/app/inline/EditRendering/displayImage.ts

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import type { AmazonQInlineCompletionItemProvider } from '../completion'
1717
import { vsCodeState } from 'aws-core-vscode/codewhisperer'
1818

1919
const autoRejectEditCursorDistance = 25
20+
const autoDiscardEditCursorDistance = 10
2021

2122
export class EditDecorationManager {
2223
private imageDecorationType: vscode.TextEditorDecorationType
@@ -312,6 +313,18 @@ export async function displaySvgDecoration(
312313
item: InlineCompletionItemWithReferences,
313314
inlineCompletionProvider?: AmazonQInlineCompletionItemProvider
314315
) {
316+
// Check if edit is too far from current cursor position
317+
const currentCursorLine = editor.selection.active.line
318+
if (Math.abs(startLine - currentCursorLine) >= autoDiscardEditCursorDistance) {
319+
// Emit DISCARD telemetry for edit suggestion that can't be shown because the suggestion is too far away
320+
const params = createDiscardTelemetryParams(session, item)
321+
languageClient.sendNotification('aws/logInlineCompletionSessionResults', params)
322+
getLogger('nextEditPrediction').debug(
323+
`Auto discarded edit suggestion for suggestion that is too far away: ${item.insertText as string}`
324+
)
325+
return
326+
}
327+
315328
const originalCode = editor.document.getText()
316329

317330
// Set edit state immediately to prevent race condition with completion requests
@@ -399,9 +412,6 @@ export async function displaySvgDecoration(
399412
const endPosition = getEndOfEditPosition(originalCode, newCode)
400413
editor.selection = new vscode.Selection(endPosition, endPosition)
401414

402-
// Move cursor to end of the actual changed content
403-
editor.selection = new vscode.Selection(endPosition, endPosition)
404-
405415
await decorationManager.clearDecorations(editor)
406416
documentChangeListener.dispose()
407417
cursorChangeListener.dispose()
@@ -420,19 +430,6 @@ export async function displaySvgDecoration(
420430
}
421431
languageClient.sendNotification('aws/logInlineCompletionSessionResults', params)
422432
// session.triggerOnAcceptance = true
423-
// VS Code triggers suggestion on every keystroke, temporarily disable trigger on acceptance
424-
// if (inlineCompletionProvider && session.editsStreakPartialResultToken) {
425-
// await inlineCompletionProvider.provideInlineCompletionItems(
426-
// editor.document,
427-
// endPosition,
428-
// {
429-
// triggerKind: vscode.InlineCompletionTriggerKind.Automatic,
430-
// selectedCompletionInfo: undefined,
431-
// },
432-
// new vscode.CancellationTokenSource().token,
433-
// { emitTelemetry: false, showUi: false, editsStreakToken: session.editsStreakPartialResultToken }
434-
// )
435-
// }
436433
},
437434
async (isDiscard: boolean) => {
438435
// Handle reject

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

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,8 @@ export class InlineCompletionManager implements Disposable {
213213

214214
export class AmazonQInlineCompletionItemProvider implements InlineCompletionItemProvider {
215215
private logger = getLogger()
216+
private pendingRequest: Promise<InlineCompletionItem[]> | undefined
217+
216218
constructor(
217219
private readonly languageClient: LanguageClient,
218220
private readonly recommendationService: RecommendationService,
@@ -300,6 +302,48 @@ export class AmazonQInlineCompletionItemProvider implements InlineCompletionItem
300302
options: JSON.stringify(getAllRecommendationsOptions),
301303
})
302304

305+
// If there's already a pending request, wait for it to complete instead of starting a new one
306+
// This prevents race conditions where multiple concurrent calls cause the later (empty) response
307+
// to override the earlier (valid) response
308+
if (this.pendingRequest) {
309+
getLogger().info('Reusing pending inline completion request to avoid race condition')
310+
try {
311+
const result = await this.pendingRequest
312+
// Check if THIS call's token was cancelled (not the original call's token)
313+
if (token.isCancellationRequested) {
314+
getLogger().info('Reused request completed but this call was cancelled')
315+
return []
316+
}
317+
return result
318+
} catch (e) {
319+
// If the pending request failed, continue with a new request
320+
getLogger().info('Pending request failed, starting new request: %O', e)
321+
}
322+
}
323+
324+
// Start a new request and track it
325+
this.pendingRequest = this._provideInlineCompletionItemsImpl(
326+
document,
327+
position,
328+
context,
329+
token,
330+
getAllRecommendationsOptions
331+
)
332+
333+
try {
334+
return await this.pendingRequest
335+
} finally {
336+
this.pendingRequest = undefined
337+
}
338+
}
339+
340+
private async _provideInlineCompletionItemsImpl(
341+
document: TextDocument,
342+
position: Position,
343+
context: InlineCompletionContext,
344+
token: CancellationToken,
345+
getAllRecommendationsOptions?: GetAllRecommendationsOptions
346+
): Promise<InlineCompletionItem[]> {
303347
if (vsCodeState.isCodeWhispererEditing) {
304348
getLogger().info('Q is editing, returning empty')
305349
return []

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

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ export interface GetAllRecommendationsOptions {
3535
}
3636

3737
export class RecommendationService {
38+
private logger = getLogger()
39+
3840
constructor(
3941
private readonly sessionManager: SessionManager,
4042
private cursorUpdateRecorder?: ICursorUpdateRecorder
@@ -117,7 +119,7 @@ export class RecommendationService {
117119
}
118120

119121
// Handle first request
120-
getLogger().info('Sending inline completion request: %O', {
122+
this.logger.info('Sending inline completion request: %O', {
121123
method: inlineCompletionWithReferencesRequestType.method,
122124
request: {
123125
textDocument: request.textDocument,
@@ -174,7 +176,7 @@ export class RecommendationService {
174176
}
175177
}
176178

177-
getLogger().info('Received inline completion response from LSP: %O', {
179+
this.logger.info('Received inline completion response from LSP: %O', {
178180
sessionId: result.sessionId,
179181
latency: Date.now() - t0,
180182
itemCount: result.items?.length || 0,
@@ -190,12 +192,14 @@ export class RecommendationService {
190192

191193
if (result.items.length > 0 && result.items[0].isInlineEdit === false) {
192194
if (isTriggerByDeletion) {
195+
this.logger.info(`Suggestions were discarded; reason: triggerByDeletion`)
193196
return []
194197
}
195198
// Completion will not be rendered if an edit suggestion has been active for longer than 1 second
196199
if (EditSuggestionState.isEditSuggestionDisplayingOverOneSecond()) {
197200
const session = this.sessionManager.getActiveSession()
198201
if (!session) {
202+
this.logger.error(`Suggestions were discarded; reason: undefined conflicting session`)
199203
return []
200204
}
201205
const params: LogInlineCompletionSessionResultsParams = {
@@ -213,14 +217,14 @@ export class RecommendationService {
213217
}
214218
languageClient.sendNotification('aws/logInlineCompletionSessionResults', params)
215219
this.sessionManager.clear()
216-
getLogger().info(
217-
'Completion discarded due to active edit suggestion displayed longer than 1 second'
220+
this.logger.info(
221+
'Suggetions were discarded; reason: active edit suggestion displayed longer than 1 second'
218222
)
219223
return []
220224
} else if (EditSuggestionState.isEditSuggestionActive()) {
221225
// discard the current edit suggestion if its display time is less than 1 sec
222226
await commands.executeCommand('aws.amazonq.inline.rejectEdit', true)
223-
getLogger().info('Discarding active edit suggestion displaying less than 1 second')
227+
this.logger.info('Discarding active edit suggestion displaying less than 1 second')
224228
}
225229
}
226230

@@ -244,24 +248,25 @@ export class RecommendationService {
244248

245249
// TODO: question, is it possible that the first request returns empty suggestion but has non-empty next token?
246250
if (result.partialResultToken) {
251+
let logstr = `found non null next token; `
247252
if (!isInlineEdit) {
248253
// If the suggestion is COMPLETIONS and there are more results to fetch, handle them in the background
249-
getLogger().info(
250-
'Suggestion type is COMPLETIONS. Start fetching for more items if partialResultToken exists.'
251-
)
252-
// this.processRemainingRequests(languageClient, request, result, token).catch((error) => {
253-
// languageClient.warn(`Error when getting suggestions: ${error}`)
254-
// })
254+
logstr += 'Suggestion type is COMPLETIONS. Start pulling more items'
255+
this.processRemainingRequests(languageClient, request, result, token).catch((error) => {
256+
languageClient.warn(`Error when getting suggestions: ${error}`)
257+
})
255258
} else {
256259
// Skip fetching for more items if the suggesion is EDITS. If it is EDITS suggestion, only fetching for more
257260
// suggestions when the user start to accept a suggesion.
258261
// Save editsStreakPartialResultToken for the next EDITS suggestion trigger if user accepts.
259-
getLogger().info('Suggestion type is EDITS. Skip fetching for more items.')
262+
logstr += 'Suggestion type is EDITS. Skip pulling more items'
260263
this.sessionManager.updateActiveEditsStreakToken(result.partialResultToken)
261264
}
265+
266+
this.logger.info(logstr)
262267
}
263268
} catch (error: any) {
264-
getLogger().error('Error getting recommendations: %O', error)
269+
this.logger.error('Error getting recommendations: %O', error)
265270
// bearer token expired
266271
if (error.data && error.data.awsErrorCode === 'E_AMAZON_Q_CONNECTION_EXPIRED') {
267272
// ref: https://github.com/aws/aws-toolkit-vscode/blob/amazonq/v1.74.0/packages/core/src/codewhisperer/service/inlineCompletionService.ts#L104

0 commit comments

Comments
 (0)