Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/setup-release-candidate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ jobs:
run: |
echo "BRANCH_NAME=release/rc-$(date +%Y%m%d)" >> $GITHUB_OUTPUT

- name: Install dependencies
run: npm ci

- name: Generate license attribution
run: npm run scan-licenses

- name: Create RC Branch
env:
BRANCH_NAME: ${{ steps.branch-name.outputs.BRANCH_NAME }}
Expand All @@ -41,5 +47,9 @@ jobs:
# Create RC branch from specified commit
git checkout -b $BRANCH_NAME

# Add generated license files
git add LICENSE-THIRD-PARTY
git commit -m "Update third-party license attribution for $BRANCH_NAME"

# Push RC branch
git push origin $BRANCH_NAME
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,6 @@ packages/*/resources/css/icons.css

# Created by `npm run webRun` when testing extension in web mode
.vscode-test-web

# License scanning output
licenses-full.json
10,428 changes: 10,428 additions & 0 deletions LICENSE-THIRD-PARTY

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,22 @@ We want your feedback!
- [File an issue](https://github.com/aws/aws-toolkit-vscode/issues/new?labels=bug&template=bug_report.md)
- Or [send a pull request](CONTRIBUTING.md)!

## License Scanning

To generate license reports and attribution documents for third-party dependencies:

```bash
npm run scan-licenses

# Or run directly
./scripts/scan-licenses.sh
```

This generates:

- `LICENSE-THIRD-PARTY` - Attribution document for distribution
- `licenses-full.json` - Complete license data

## License

This project and the subprojects within **(AWS Toolkit for Visual Studio Code, Amazon Q for Visual Studio Code)** is distributed under the [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0).
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
"reset": "npm run clean && ts-node ./scripts/clean.ts node_modules && npm install",
"generateNonCodeFiles": "npm run generateNonCodeFiles -w packages/ --if-present",
"mergeReports": "ts-node ./scripts/mergeReports.ts",
"skippedTestReport": "ts-node ./scripts/skippedTestReport.ts ./packages/amazonq/test/e2e/"
"skippedTestReport": "ts-node ./scripts/skippedTestReport.ts ./packages/amazonq/test/e2e/",
"scan-licenses": "ts-node ./scripts/scan-licenses.ts"
},
"devDependencies": {
"@aws-toolkits/telemetry": "^1.0.329",
Expand Down
5 changes: 5 additions & 0 deletions packages/amazonq/.changes/1.97.0.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"date": "2025-09-29",
"version": "1.97.0",
"entries": []
}
5 changes: 5 additions & 0 deletions packages/amazonq/.changes/1.98.0.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"date": "2025-10-02",
"version": "1.98.0",
"entries": []
}
8 changes: 8 additions & 0 deletions packages/amazonq/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## 1.98.0 2025-10-02

- Miscellaneous non-user-facing changes

## 1.97.0 2025-09-29

- Miscellaneous non-user-facing changes

## 1.96.0 2025-09-25

- **Bug Fix** Amazon Q support web/container environments running Ubuntu/Linux, even when the host machine is Amazon Linux 2.
Expand Down
2 changes: 1 addition & 1 deletion packages/amazonq/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "amazon-q-vscode",
"displayName": "Amazon Q",
"description": "The most capable generative AI–powered assistant for software development.",
"version": "1.97.0-SNAPSHOT",
"version": "1.99.0-SNAPSHOT",
"extensionKind": [
"workspace"
],
Expand Down
21 changes: 17 additions & 4 deletions packages/amazonq/src/app/inline/EditRendering/displayImage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,11 @@ export class EditDecorationManager {
newCode: string,
originalCodeHighlightRanges: Array<{ line: number; start: number; end: number }>
): Promise<void> {
await this.clearDecorations(editor)

await setContext('aws.amazonq.editSuggestionActive' as any, true)
EditSuggestionState.setEditSuggestionActive(true)
// Clear old decorations but don't reset state (state is already set in displaySvgDecoration)
editor.setDecorations(this.imageDecorationType, [])
editor.setDecorations(this.removedCodeDecorationType, [])
this.currentImageDecoration = undefined
this.currentRemovedCodeDecorations = []

this.acceptHandler = onAccept
this.rejectHandler = onReject
Expand Down Expand Up @@ -313,8 +314,16 @@ export async function displaySvgDecoration(
) {
const originalCode = editor.document.getText()

// Set edit state immediately to prevent race condition with completion requests
await setContext('aws.amazonq.editSuggestionActive' as any, true)
EditSuggestionState.setEditSuggestionActive(true)

// Check if a completion suggestion is currently active - if so, discard edit suggestion
if (inlineCompletionProvider && (await inlineCompletionProvider.isCompletionActive())) {
// Clean up state since we're not showing the edit
await setContext('aws.amazonq.editSuggestionActive' as any, false)
EditSuggestionState.setEditSuggestionActive(false)

// Emit DISCARD telemetry for edit suggestion that can't be shown due to active completion
const params = createDiscardTelemetryParams(session, item)
languageClient.sendNotification('aws/logInlineCompletionSessionResults', params)
Expand All @@ -326,6 +335,10 @@ export async function displaySvgDecoration(

const isPatchValid = applyPatch(editor.document.getText(), item.insertText as string)
if (!isPatchValid) {
// Clean up state since we're not showing the edit
await setContext('aws.amazonq.editSuggestionActive' as any, false)
EditSuggestionState.setEditSuggestionActive(false)

const params = createDiscardTelemetryParams(session, item)
// TODO: this session is closed on flare side hence discarded is not emitted in flare
languageClient.sendNotification('aws/logInlineCompletionSessionResults', params)
Expand Down
5 changes: 4 additions & 1 deletion packages/amazonq/src/app/inline/recommendationService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ export class RecommendationService {
* Completions use PartialResultToken with single 1 call of [getAllRecommendations].
* Edits leverage partialResultToken to achieve EditStreak such that clients can pull all continuous suggestions generated by the model within 1 EOS block.
*/
if (!isTriggerByDeletion && !request.partialResultToken) {
if (!isTriggerByDeletion && !request.partialResultToken && !EditSuggestionState.isEditSuggestionActive()) {
const completionPromise: Promise<InlineCompletionListWithReferences> = languageClient.sendRequest(
inlineCompletionWithReferencesRequestType.method,
request,
Expand Down Expand Up @@ -189,6 +189,9 @@ export class RecommendationService {
})

if (result.items.length > 0 && result.items[0].isInlineEdit === false) {
if (isTriggerByDeletion) {
return []
}
// Completion will not be rendered if an edit suggestion has been active for longer than 1 second
if (EditSuggestionState.isEditSuggestionDisplayingOverOneSecond()) {
const session = this.sessionManager.getActiveSession()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ describe('RecommendationService', () => {
}
})

it('should make completion request when edit suggestion is active', async () => {
it('should not make completion request when edit suggestion is active', async () => {
// Mock EditSuggestionState to return true (edit suggestion is active)
sandbox.stub(EditSuggestionState, 'isEditSuggestionActive').returns(true)

Expand All @@ -360,13 +360,15 @@ describe('RecommendationService', () => {
const completionCalls = cs.filter((c) => c.firstArg === completionApi)
const editCalls = cs.filter((c) => c.firstArg === editApi)

assert.strictEqual(cs.length, 2) // Only edit call
assert.strictEqual(completionCalls.length, 1) // No completion calls
assert.strictEqual(cs.length, 1) // Only edit call
assert.strictEqual(completionCalls.length, 0) // No completion calls
assert.strictEqual(editCalls.length, 1) // One edit call
})

it('should make completion request when edit suggestion is not active', async () => {
// Mock EditSuggestionState to return false (no edit suggestion active)
sandbox.stub(EditSuggestionState, 'isEditSuggestionActive').returns(false)

const mockResult = {
sessionId: 'test-session',
items: [mockInlineCompletionItemOne],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@ import {
session,
AuthUtil,
DefaultCodeWhispererClient,
RecommendationsList,
ConfigurationEntry,
RecommendationHandler,
CodeWhispererCodeCoverageTracker,
supplementalContextUtil,
} from 'aws-core-vscode/codewhisperer'
import {
Expand Down Expand Up @@ -54,35 +52,35 @@ describe('recommendationHandler', function () {
sinon.restore()
})

it('should assign correct recommendations given input', async function () {
assert.strictEqual(CodeWhispererCodeCoverageTracker.instances.size, 0)
assert.strictEqual(
CodeWhispererCodeCoverageTracker.getTracker(mockEditor.document.languageId)?.serviceInvocationCount,
0
)
// it('should assign correct recommendations given input', async function () {
// assert.strictEqual(CodeWhispererCodeCoverageTracker.instances.size, 0)
// assert.strictEqual(
// CodeWhispererCodeCoverageTracker.getTracker(mockEditor.document.languageId)?.serviceInvocationCount,
// 0
// )

const mockServerResult = {
recommendations: [{ content: "print('Hello World!')" }, { content: '' }],
$response: {
requestId: 'test_request',
httpResponse: {
headers: {
'x-amzn-sessionid': 'test_request',
},
},
},
}
const handler = new RecommendationHandler()
sinon.stub(handler, 'getServerResponse').resolves(mockServerResult)
await handler.getRecommendations(mockClient, mockEditor, 'AutoTrigger', config, 'Enter', false)
const actual = session.recommendations
const expected: RecommendationsList = [{ content: "print('Hello World!')" }, { content: '' }]
assert.deepStrictEqual(actual, expected)
assert.strictEqual(
CodeWhispererCodeCoverageTracker.getTracker(mockEditor.document.languageId)?.serviceInvocationCount,
1
)
})
// const mockServerResult = {
// recommendations: [{ content: "print('Hello World!')" }, { content: '' }],
// $response: {
// requestId: 'test_request',
// httpResponse: {
// headers: {
// 'x-amzn-sessionid': 'test_request',
// },
// },
// },
// }
// const handler = new RecommendationHandler()
// sinon.stub(handler, 'getServerResponse').resolves(mockServerResult)
// await handler.getRecommendations(mockClient, mockEditor, 'AutoTrigger', config, 'Enter', false)
// const actual = session.recommendations
// const expected: RecommendationsList = [{ content: "print('Hello World!')" }, { content: '' }]
// assert.deepStrictEqual(actual, expected)
// assert.strictEqual(
// CodeWhispererCodeCoverageTracker.getTracker(mockEditor.document.languageId)?.serviceInvocationCount,
// 1
// )
// })

it('should assign request id correctly', async function () {
const mockServerResult = {
Expand Down
Loading
Loading