Skip to content

Commit d2cde47

Browse files
authored
fix(amazonq): max 20k char for inline supplementalContext (#6366)
## Problem In some rare cases, the total supplementalContext length exceeds 20k character. With recent service side changes, we need to make sure the total supplementalContext length do not exceed 20k in any situation. ## Solution Make sure the total supplementalContext length do not exceed 20k in any situation. Drop when necessary. This is not customer facing so no change log is attached. --- - Treat all work as PUBLIC. Private `feature/x` branches will not be squash-merged at release time. - Your code changes must meet the guidelines in [CONTRIBUTING.md](https://github.com/aws/aws-toolkit-vscode/blob/master/CONTRIBUTING.md#guidelines). - License: I confirm that my contribution is made under the terms of the Apache 2.0 license.
1 parent e5425e6 commit d2cde47

File tree

5 files changed

+41
-11
lines changed

5 files changed

+41
-11
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": "Fix inline completion supplementalContext length exceeding maximum in certain cases"
4+
}

packages/amazonq/test/unit/codewhisperer/util/crossFileContextUtil.test.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@ import * as FakeTimers from '@sinonjs/fake-timers'
88
import * as vscode from 'vscode'
99
import * as sinon from 'sinon'
1010
import * as crossFile from 'aws-core-vscode/codewhisperer'
11-
import { aStringWithLineCount, createMockTextEditor, installFakeClock } from 'aws-core-vscode/test'
11+
import {
12+
aLongStringWithLineCount,
13+
aStringWithLineCount,
14+
createMockTextEditor,
15+
installFakeClock,
16+
} from 'aws-core-vscode/test'
1217
import { FeatureConfigProvider, crossFileContextConfig } from 'aws-core-vscode/codewhisperer'
1318
import {
1419
assertTabCount,
@@ -71,8 +76,8 @@ describe('crossFileContextUtil', function () {
7176
assert.strictEqual(actual.supplementalContextItems[2].content.split('\n').length, 50)
7277
})
7378

74-
it('for t1 group, should return repomap + opentabs context', async function () {
75-
await toTextEditor(aStringWithLineCount(200), 'CrossFile.java', tempFolder, { preview: false })
79+
it('for t1 group, should return repomap + opentabs context, should not exceed 20k total length', async function () {
80+
await toTextEditor(aLongStringWithLineCount(200), 'CrossFile.java', tempFolder, { preview: false })
7681
const myCurrentEditor = await toTextEditor('', 'TargetFile.java', tempFolder, {
7782
preview: false,
7883
})
@@ -85,25 +90,23 @@ describe('crossFileContextUtil', function () {
8590
.withArgs(sinon.match.any, sinon.match.any, 'codemap')
8691
.resolves([
8792
{
88-
content: 'foo',
93+
content: 'foo'.repeat(3000),
8994
score: 0,
9095
filePath: 'q-inline',
9196
},
9297
])
9398

9499
const actual = await crossFile.fetchSupplementalContextForSrc(myCurrentEditor, fakeCancellationToken)
95100
assert.ok(actual)
96-
assert.strictEqual(actual.supplementalContextItems.length, 4)
101+
assert.strictEqual(actual.supplementalContextItems.length, 3)
97102
assert.strictEqual(actual?.strategy, 'codemap')
98103
assert.deepEqual(actual?.supplementalContextItems[0], {
99-
content: 'foo',
104+
content: 'foo'.repeat(3000),
100105
score: 0,
101106
filePath: 'q-inline',
102107
})
103-
104108
assert.strictEqual(actual.supplementalContextItems[1].content.split('\n').length, 50)
105109
assert.strictEqual(actual.supplementalContextItems[2].content.split('\n').length, 50)
106-
assert.strictEqual(actual.supplementalContextItems[3].content.split('\n').length, 50)
107110
})
108111

109112
it.skip('for t2 group, should return global bm25 context and no repomap', async function () {

packages/core/src/codewhisperer/models/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ export const lineBreakWin = '\r\n'
8484

8585
export const supplementalContextTimeoutInMs = 100
8686

87+
export const supplementalContextMaxTotalLength = 20480
8788
/**
8889
* Ux of recommendations
8990
*/

packages/core/src/codewhisperer/util/supplementalContext/crossFileContextUtil.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ import * as vscode from 'vscode'
77
import { FeatureConfigProvider, fs } from '../../../shared'
88
import path = require('path')
99
import { BM25Document, BM25Okapi } from './rankBm25'
10-
import { crossFileContextConfig, supplementalContextTimeoutInMs } from '../../models/constants'
10+
import {
11+
crossFileContextConfig,
12+
supplementalContextTimeoutInMs,
13+
supplementalContextMaxTotalLength,
14+
} from '../../models/constants'
1115
import { isTestFile } from './codeParsingUtil'
1216
import { getFileDistance } from '../../../shared/filesystemUtilities'
1317
import { getOpenFilesInWindow } from '../../../shared/utilities/editorUtilities'
@@ -99,13 +103,22 @@ export async function fetchSupplementalContextForSrc(
99103
const opentabsContext = await fetchOpentabsContext(editor, cancellationToken)
100104
const codemap = await fetchProjectContext(editor, 'codemap')
101105

106+
function addToResult(items: CodeWhispererSupplementalContextItem[]) {
107+
for (const item of items) {
108+
const curLen = result.reduce((acc, i) => acc + i.content.length, 0)
109+
if (curLen + item.content.length < supplementalContextMaxTotalLength) {
110+
result.push(item)
111+
}
112+
}
113+
}
114+
102115
if (codemap && codemap.length > 0) {
103-
result.push(...codemap)
116+
addToResult(codemap)
104117
hasCodemap = true
105118
}
106119

107120
if (opentabsContext && opentabsContext.length > 0) {
108-
result.push(...opentabsContext)
121+
addToResult(opentabsContext)
109122
hasOpentabs = true
110123
}
111124

packages/core/src/test/codewhisperer/testUtil.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,3 +329,12 @@ export function aStringWithLineCount(lineCount: number, start: number = 0): stri
329329

330330
return s.trimEnd()
331331
}
332+
333+
export function aLongStringWithLineCount(lineCount: number, start: number = 0): string {
334+
let s = ''
335+
for (let i = start; i < start + lineCount; i++) {
336+
s += `a`.repeat(100) + `line${i}\n`
337+
}
338+
339+
return s.trimEnd()
340+
}

0 commit comments

Comments
 (0)