Skip to content

Commit 4b87932

Browse files
siakmun-awskaranA-aws
authored andcommitted
fix(amazonq): use server-side data to decide remaining code generations aws#6370
Previously remaining code generation iterations are always displayed. Only display when it goes down to 2 or less.
1 parent ba205b9 commit 4b87932

File tree

5 files changed

+116
-62
lines changed

5 files changed

+116
-62
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": "Amazon q /dev: Remove hard-coded limits and instead rely server-side data to communicate number of code generations remaining"
4+
}

packages/core/src/amazonqFeatureDev/controllers/chat/controller.ts

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@ import { FollowUpTypes } from '../../../amazonq/commons/types'
5050
import { Messenger } from '../../../amazonq/commons/connector/baseMessenger'
5151
import { BaseChatSessionStorage } from '../../../amazonq/commons/baseChatStorage'
5252

53-
export const TotalSteps = 3
54-
5553
export interface ChatControllerEventEmitters {
5654
readonly processHumanChatMessage: EventEmitter<any>
5755
readonly followUpClicked: EventEmitter<any>
@@ -513,12 +511,17 @@ export class FeatureDevController {
513511

514512
if (remainingIterations !== undefined && totalIterations !== undefined) {
515513
this.messenger.sendAnswer({
516-
type: 'answer',
514+
type: 'answer' as const,
517515
tabID: tabID,
518-
message:
519-
remainingIterations === 0
520-
? 'Would you like to add this code to your project?'
521-
: `Would you like to add this code to your project, or provide feedback for new code? You have ${remainingIterations} out of ${totalIterations} code generations left.`,
516+
message: (() => {
517+
if (remainingIterations > 2) {
518+
return 'Would you like me to add this code to your project, or provide feedback for new code?'
519+
} else if (remainingIterations > 0) {
520+
return `Would you like me to add this code to your project, or provide feedback for new code? You have ${remainingIterations} out of ${totalIterations} code generations left.`
521+
} else {
522+
return 'Would you like me to add this code to your project?'
523+
}
524+
})(),
522525
})
523526
}
524527

@@ -569,9 +572,8 @@ export class FeatureDevController {
569572
if (session?.state?.tokenSource?.token.isCancellationRequested) {
570573
await this.workOnNewTask(
571574
session.tabID,
572-
session.state.codeGenerationRemainingIterationCount ||
573-
TotalSteps - (session.state?.currentIteration || 0),
574-
session.state.codeGenerationTotalIterationCount || TotalSteps,
575+
session.state.codeGenerationRemainingIterationCount,
576+
session.state.codeGenerationTotalIterationCount,
575577
session?.state?.tokenSource?.token.isCancellationRequested
576578
)
577579
this.disposeToken(session)
@@ -616,10 +618,16 @@ export class FeatureDevController {
616618

617619
if (isStoppedGeneration) {
618620
this.messenger.sendAnswer({
619-
message:
620-
(remainingIterations ?? 0) <= 0
621-
? "I stopped generating your code. You don't have more iterations left, however, you can start a new session."
622-
: `I stopped generating your code. If you want to continue working on this task, provide another description. You have ${remainingIterations} out of ${totalIterations} code generations left.`,
621+
message: ((remainingIterations) => {
622+
if (remainingIterations && totalIterations) {
623+
if (remainingIterations <= 0) {
624+
return "I stopped generating your code. You don't have more iterations left, however, you can start a new session."
625+
} else if (remainingIterations <= 2) {
626+
return `I stopped generating your code. If you want to continue working on this task, provide another description. You have ${remainingIterations} out of ${totalIterations} code generations left.`
627+
}
628+
}
629+
return 'I stopped generating your code. If you want to continue working on this task, provide another description.'
630+
})(remainingIterations),
623631
type: 'answer-part',
624632
tabID,
625633
})

packages/core/src/amazonqFeatureDev/session/sessionState.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,14 +175,16 @@ abstract class CodeGenBase {
175175
codeGenerationRemainingIterationCount?: number
176176
codeGenerationTotalIterationCount?: number
177177
}> {
178+
let codeGenerationRemainingIterationCount = undefined
179+
let codeGenerationTotalIterationCount = undefined
178180
for (
179181
let pollingIteration = 0;
180182
pollingIteration < this.pollCount && !this.isCancellationRequested;
181183
++pollingIteration
182184
) {
183185
const codegenResult = await this.config.proxyClient.getCodeGeneration(this.conversationId, codeGenerationId)
184-
const codeGenerationRemainingIterationCount = codegenResult.codeGenerationRemainingIterationCount
185-
const codeGenerationTotalIterationCount = codegenResult.codeGenerationTotalIterationCount
186+
codeGenerationRemainingIterationCount = codegenResult.codeGenerationRemainingIterationCount
187+
codeGenerationTotalIterationCount = codegenResult.codeGenerationTotalIterationCount
186188

187189
getLogger().debug(`Codegen response: %O`, codegenResult)
188190
telemetry.setCodeGenerationResult(codegenResult.codeGenerationStatus.status)
@@ -272,6 +274,8 @@ abstract class CodeGenBase {
272274
newFiles: [],
273275
deletedFiles: [],
274276
references: [],
277+
codeGenerationRemainingIterationCount: codeGenerationRemainingIterationCount,
278+
codeGenerationTotalIterationCount: codeGenerationTotalIterationCount,
275279
}
276280
}
277281
}
@@ -345,8 +349,13 @@ export class CodeGenState extends CodeGenBase implements SessionState {
345349
this.filePaths = codeGeneration.newFiles
346350
this.deletedFiles = codeGeneration.deletedFiles
347351
this.references = codeGeneration.references
352+
348353
this.codeGenerationRemainingIterationCount = codeGeneration.codeGenerationRemainingIterationCount
349354
this.codeGenerationTotalIterationCount = codeGeneration.codeGenerationTotalIterationCount
355+
this.currentIteration =
356+
this.codeGenerationRemainingIterationCount && this.codeGenerationTotalIterationCount
357+
? this.codeGenerationTotalIterationCount - this.codeGenerationRemainingIterationCount
358+
: this.currentIteration + 1
350359

351360
if (action.uploadHistory && !action.uploadHistory[codeGenerationId] && codeGenerationId) {
352361
action.uploadHistory[codeGenerationId] = {
@@ -366,7 +375,7 @@ export class CodeGenState extends CodeGenBase implements SessionState {
366375
this.deletedFiles,
367376
this.references,
368377
this.tabID,
369-
this.currentIteration + 1,
378+
this.currentIteration,
370379
this.codeGenerationRemainingIterationCount,
371380
this.codeGenerationTotalIterationCount,
372381
action.uploadHistory,

packages/core/src/test/amazonqFeatureDev/controllers/chat/controller.test.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,29 @@ describe('Controller', () => {
531531
await waitUntil(() => Promise.resolve(sendMetricDataTelemetrySpy.callCount >= 2), {})
532532
}
533533

534+
async function verifyAddCodeMessage(
535+
remainingIterations: number,
536+
totalIterations: number,
537+
expectedMessage: string
538+
) {
539+
sinon.stub(session, 'send').resolves()
540+
sinon.stub(session, 'sendLinesOfCodeGeneratedTelemetry').resolves() // Avoid sending extra telemetry
541+
const sendAnswerSpy = sinon.stub(controllerSetup.messenger, 'sendAnswer')
542+
sinon.stub(session.state, 'codeGenerationRemainingIterationCount').value(remainingIterations)
543+
sinon.stub(session.state, 'codeGenerationTotalIterationCount').value(totalIterations)
544+
545+
await fireChatMessage(session)
546+
await verifyMetricsCalled()
547+
548+
assert.ok(
549+
sendAnswerSpy.calledWith({
550+
type: 'answer',
551+
tabID,
552+
message: expectedMessage,
553+
})
554+
)
555+
}
556+
534557
beforeEach(async () => {
535558
session = await createCodeGenState()
536559
sinon.stub(session, 'preloader').resolves()
@@ -563,6 +586,23 @@ describe('Controller', () => {
563586
await verifyException(error)
564587
})
565588
}
589+
590+
// Using 3 to avoid spamming the tests
591+
for (let remainingIterations = 0; remainingIterations <= 3; remainingIterations++) {
592+
it(`verifies add code messages for remaining iterations at ${remainingIterations}`, async () => {
593+
const totalIterations = 10
594+
const expectedMessage = (() => {
595+
if (remainingIterations > 2) {
596+
return 'Would you like me to add this code to your project, or provide feedback for new code?'
597+
} else if (remainingIterations > 0) {
598+
return `Would you like me to add this code to your project, or provide feedback for new code? You have ${remainingIterations} out of ${totalIterations} code generations left.`
599+
} else {
600+
return 'Would you like me to add this code to your project?'
601+
}
602+
})()
603+
await verifyAddCodeMessage(remainingIterations, totalIterations, expectedMessage)
604+
})
605+
}
566606
})
567607

568608
describe('processErrorChatMessage', function () {

0 commit comments

Comments
 (0)