Skip to content

Commit aabf20f

Browse files
committed
fix(amazonq): don't call completions when edits active
1 parent e4c0cbc commit aabf20f

File tree

3 files changed

+89
-11
lines changed

3 files changed

+89
-11
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { getLogger } from 'aws-core-vscode/shared'
2424
import { DocumentEventListener } from './documentEventListener'
2525
import { getOpenFilesInWindow } from 'aws-core-vscode/utils'
2626
import { asyncCallWithTimeout } from '../../util/timeoutUtil'
27+
import { EditSuggestionState } from './editSuggestionState'
2728

2829
export interface GetAllRecommendationsOptions {
2930
emitTelemetry?: boolean
@@ -132,7 +133,7 @@ export class RecommendationService {
132133
* Completions use PartialResultToken with single 1 call of [getAllRecommendations].
133134
* Edits leverage partialResultToken to achieve EditStreak such that clients can pull all continuous suggestions generated by the model within 1 EOS block.
134135
*/
135-
if (!isTriggerByDeletion && !request.partialResultToken) {
136+
if (!isTriggerByDeletion && !request.partialResultToken && !EditSuggestionState.isEditSuggestionActive()) {
136137
const completionPromise: Promise<InlineCompletionListWithReferences> = languageClient.sendRequest(
137138
inlineCompletionWithReferencesRequestType.method,
138139
request,

packages/amazonq/test/unit/amazonq/apps/inline/completion.test.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -443,16 +443,20 @@ describe('InlineCompletionManager', () => {
443443
// Should return empty array
444444
assert.deepStrictEqual(result, [])
445445

446-
// Should emit telemetry for each completion suggestion
447-
assert.strictEqual(sendNotificationStub.callCount, 2) // For both mockSuggestions
448-
449-
// Verify telemetry parameters for first call
450-
const firstCall = sendNotificationStub.getCall(0)
451-
assert.strictEqual(firstCall.args[0], 'aws/logInlineCompletionSessionResults')
452-
const sessionResult = Object.values(firstCall.args[1].completionSessionResult)[0] as any
453-
assert.strictEqual(sessionResult.seen, false)
454-
assert.strictEqual(sessionResult.accepted, false)
455-
assert.strictEqual(sessionResult.discarded, true)
446+
// Should emit single batched telemetry for both completion suggestions
447+
assert.strictEqual(sendNotificationStub.callCount, 1)
448+
449+
// Verify telemetry parameters
450+
const call = sendNotificationStub.getCall(0)
451+
assert.strictEqual(call.args[0], 'aws/logInlineCompletionSessionResults')
452+
const completionSessionResult = call.args[1].completionSessionResult
453+
const sessionResults = Object.values(completionSessionResult) as any[]
454+
assert.strictEqual(sessionResults.length, 2) // Both mockSuggestions should be included
455+
sessionResults.forEach((result) => {
456+
assert.strictEqual(result.seen, false)
457+
assert.strictEqual(result.accepted, false)
458+
assert.strictEqual(result.discarded, true)
459+
})
456460
})
457461

458462
it('should only emit telemetry for non-inline-edit items when edit is active', async () => {

packages/amazonq/test/unit/amazonq/apps/inline/recommendationService.test.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { CursorUpdateManager } from '../../../../../src/app/inline/cursorUpdateM
1515
import { CodeWhispererStatusBarManager } from 'aws-core-vscode/codewhisperer'
1616
import { globals } from 'aws-core-vscode/shared'
1717
import { DocumentEventListener } from '../../../../../src/app/inline/documentEventListener'
18+
import { EditSuggestionState } from '../../../../../src/app/inline/editSuggestionState'
1819

1920
const completionApi = 'aws/textDocument/inlineCompletionWithReferences'
2021
const editApi = 'aws/textDocument/editCompletion'
@@ -325,5 +326,77 @@ describe('RecommendationService', () => {
325326
console.error = originalConsoleError
326327
}
327328
})
329+
330+
it('should not make completion request when edit suggestion is active', async () => {
331+
// Mock EditSuggestionState to return true (edit suggestion is active)
332+
const isEditSuggestionActiveStub = sandbox.stub(EditSuggestionState, 'isEditSuggestionActive').returns(true)
333+
334+
const mockResult = {
335+
sessionId: 'test-session',
336+
items: [mockInlineCompletionItemOne],
337+
partialResultToken: undefined,
338+
}
339+
340+
sendRequestStub.resolves(mockResult)
341+
342+
await service.getAllRecommendations(
343+
languageClient,
344+
mockDocument,
345+
mockPosition,
346+
mockContext,
347+
mockToken,
348+
true,
349+
mockDocumentEventListener
350+
)
351+
352+
// Verify sendRequest was called only for edit API, not completion API
353+
const cs = sendRequestStub.getCalls()
354+
const completionCalls = cs.filter((c) => c.firstArg === completionApi)
355+
const editCalls = cs.filter((c) => c.firstArg === editApi)
356+
357+
assert.strictEqual(cs.length, 1) // Only edit call
358+
assert.strictEqual(completionCalls.length, 0) // No completion calls
359+
assert.strictEqual(editCalls.length, 1) // One edit call
360+
361+
// Verify the stub was called
362+
sinon.assert.calledOnce(isEditSuggestionActiveStub)
363+
})
364+
365+
it('should make completion request when edit suggestion is not active', async () => {
366+
// Mock EditSuggestionState to return false (no edit suggestion active)
367+
const isEditSuggestionActiveStub = sandbox
368+
.stub(EditSuggestionState, 'isEditSuggestionActive')
369+
.returns(false)
370+
371+
const mockResult = {
372+
sessionId: 'test-session',
373+
items: [mockInlineCompletionItemOne],
374+
partialResultToken: undefined,
375+
}
376+
377+
sendRequestStub.resolves(mockResult)
378+
379+
await service.getAllRecommendations(
380+
languageClient,
381+
mockDocument,
382+
mockPosition,
383+
mockContext,
384+
mockToken,
385+
true,
386+
mockDocumentEventListener
387+
)
388+
389+
// Verify sendRequest was called for both APIs
390+
const cs = sendRequestStub.getCalls()
391+
const completionCalls = cs.filter((c) => c.firstArg === completionApi)
392+
const editCalls = cs.filter((c) => c.firstArg === editApi)
393+
394+
assert.strictEqual(cs.length, 2) // Both calls
395+
assert.strictEqual(completionCalls.length, 1) // One completion call
396+
assert.strictEqual(editCalls.length, 1) // One edit call
397+
398+
// Verify the stub was called
399+
sinon.assert.calledOnce(isEditSuggestionActiveStub)
400+
})
328401
})
329402
})

0 commit comments

Comments
 (0)