Skip to content

Commit 13eb178

Browse files
committed
feat(feature dev): Add setting to opt in/out of QSDA auto build feature
1 parent db8acef commit 13eb178

File tree

10 files changed

+96
-4
lines changed

10 files changed

+96
-4
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Feature",
3+
"description": "Amazon Q Feature Dev: Add new setting to opt in/out auto build feature"
4+
}

packages/amazonq/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@
128128
"markdownDescription": "%AWS.configuration.description.amazonq%",
129129
"default": true
130130
},
131+
"amazonQ.autoBuildFeatureProjects": {
132+
"type": "object",
133+
"markdownDescription": "%AWS.configuration.description.autoBuildFeatureProjects%",
134+
"default": {}
135+
},
131136
"amazonQ.importRecommendationForInlineCodeSuggestions": {
132137
"type": "boolean",
133138
"description": "%AWS.configuration.description.amazonq.importRecommendation%",

packages/amazonq/test/unit/amazonqFeatureDev/session/session.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ import {
1717
sessionRegisterProvider,
1818
sessionWriteFile,
1919
assertTelemetry,
20+
getTestWorkspaceFolder,
2021
} from 'aws-core-vscode/test'
2122
import { CurrentWsFolders, CodeGenState, FeatureDevClient, Messenger } from 'aws-core-vscode/amazonqFeatureDev'
2223
import path from 'path'
2324
import { fs } from 'aws-core-vscode/shared'
25+
import { CodeWhispererSettings } from 'aws-core-vscode/codewhisperer'
2426

2527
describe('session', () => {
2628
const conversationID = '12345'
@@ -36,6 +38,7 @@ describe('session', () => {
3638

3739
describe('preloader', () => {
3840
it('emits start chat telemetry', async () => {
41+
await CodeWhispererSettings.instance.updateToAutoBuildFeatureProjects(getTestWorkspaceFolder(), false)
3942
const session = await createSession({ messenger, conversationID })
4043

4144
await session.preloader('implement twosum in typescript')

packages/core/package.nls.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"AWS.configuration.enableCodeLenses": "Enable SAM hints in source code and template.yaml files",
2121
"AWS.configuration.description.resources.enabledResources": "AWS resources to display in the 'Resources' portion of the explorer.",
2222
"AWS.configuration.description.experiments": "Try experimental features and give feedback. Note that experimental features may be removed at any time.\n * `jsonResourceModification` - Enables basic create, update, and delete support for cloud resources via the JSON Resources explorer component.\n * `samSyncCode` - Adds an additional code-only option when synchronizing SAM applications. Code-only synchronizations are faster but can cause drift in the CloudFormation stack. Does nothing when using the legacy SAM deploy feature.\n * `iamPolicyChecks` - Enables IAM Policy Checks feature, allowing users to validate IAM policies against IAM policy grammar, AWS best practices, and specified security standards.",
23+
"AWS.configuration.description.autoBuildFeatureProjects": "Projects with auto build feature enabled or disabled",
2324
"AWS.stepFunctions.asl.format.enable.desc": "Enables the default formatter used with Amazon States Language files",
2425
"AWS.stepFunctions.asl.maxItemsComputed.desc": "The maximum number of outline symbols and folding regions computed (limited for performance reasons).",
2526
"AWS.configuration.description.awssam.debug.api": "API Gateway configuration",

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

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import { getWorkspaceFoldersByPrefixes } from '../../../shared/utilities/workspa
4646
import { openDeletedDiff, openDiff } from '../../../amazonq/commons/diff'
4747
import { i18n } from '../../../shared/i18n-helper'
4848
import globals from '../../../shared/extensionGlobals'
49+
import { CodeWhispererSettings } from '../../../codewhisperer'
4950

5051
export const TotalSteps = 3
5152

@@ -122,7 +123,7 @@ export class FeatureDevController {
122123
getLogger().error('processChatItemFeedbackMessage failed: %s', (e as Error).message)
123124
})
124125
})
125-
this.chatControllerMessageListeners.followUpClicked.event((data) => {
126+
this.chatControllerMessageListeners.followUpClicked.event(async (data) => {
126127
switch (data.followUp.type) {
127128
case FollowUpTypes.InsertCode:
128129
return this.insertCode(data)
@@ -147,6 +148,12 @@ export class FeatureDevController {
147148
case FollowUpTypes.SendFeedback:
148149
this.sendFeedback()
149150
break
151+
case FollowUpTypes.AcceptAutoBuild:
152+
await this.processAutoBuildSetting(true)
153+
return this.retryRequest(data)
154+
case FollowUpTypes.DenyAutoBuild:
155+
await this.processAutoBuildSetting(false)
156+
return this.retryRequest(data)
150157
}
151158
})
152159
this.chatControllerMessageListeners.openDiff.event((data) => {
@@ -537,6 +544,16 @@ export class FeatureDevController {
537544
i18n('AWS.amazonq.featureDev.placeholder.additionalImprovements')
538545
)
539546
}
547+
548+
private async processAutoBuildSetting(setting: boolean) {
549+
const workspaceFolders = vscode.workspace.workspaceFolders
550+
const workspaceRoots = workspaceFolders?.map((f) => f.uri.fsPath)
551+
552+
if (workspaceRoots) {
553+
await CodeWhispererSettings.instance.updateToAutoBuildFeatureProjects(workspaceRoots[0], setting)
554+
}
555+
}
556+
540557
// TODO add type
541558
private async insertCode(message: any) {
542559
let session

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

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import * as path from 'path'
77

88
import { ConversationNotStartedState, PrepareCodeGenState } from './sessionState'
99
import {
10+
FollowUpTypes,
1011
type DeletedFileInfo,
1112
type Interaction,
1213
type NewFileInfo,
@@ -26,6 +27,8 @@ import { ReferenceLogViewProvider } from '../../codewhisperer/service/referenceL
2627
import { AuthUtil } from '../../codewhisperer/util/authUtil'
2728
import { getLogger } from '../../shared'
2829
import { logWithConversationId } from '../userFacingText'
30+
import { CodeWhispererSettings } from '../../codewhisperer'
31+
2932
export class Session {
3033
private _state?: SessionState | Omit<SessionState, 'uploadId'>
3134
private task: string = ''
@@ -59,14 +62,50 @@ export class Session {
5962
* Preload any events that have to run before a chat message can be sent
6063
*/
6164
async preloader(msg: string) {
62-
if (!this.preloaderFinished) {
65+
const root = this.config.workspaceRoots[0]
66+
const projects = CodeWhispererSettings.instance.getAutoBuildFeatureProjects()
67+
68+
if (Object.keys(projects).includes(root) && !this.preloaderFinished) {
6369
await this.setupConversation(msg)
6470
this.preloaderFinished = true
6571
this.messenger.sendAsyncEventProgress(this.tabID, true, undefined)
6672
await this.proxyClient.sendFeatureDevTelemetryEvent(this.conversationId) // send the event only once per conversation.
73+
} else {
74+
await this.promptUserConsent()
6775
}
6876
}
6977

78+
/**
79+
*
80+
*/
81+
82+
private async promptUserConsent() {
83+
this.messenger.sendAnswer({
84+
tabID: this.tabID,
85+
message:
86+
'Would you like to use the auto build feature that will allow Amazon Q feature development agent to build and test your project?',
87+
type: 'answer',
88+
})
89+
90+
this.messenger.sendAnswer({
91+
message: undefined,
92+
type: 'system-prompt',
93+
followUps: [
94+
{
95+
pillText: 'Accept for this project',
96+
type: FollowUpTypes.AcceptAutoBuild,
97+
status: 'info',
98+
},
99+
{
100+
pillText: 'Deny for this project',
101+
type: FollowUpTypes.DenyAutoBuild,
102+
status: 'info',
103+
},
104+
],
105+
tabID: this.tabID,
106+
})
107+
}
108+
70109
/**
71110
* setupConversation
72111
*

packages/core/src/amazonqFeatureDev/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ export enum FollowUpTypes {
4949
NewTask = 'NewTask',
5050
CloseSession = 'CloseSession',
5151
SendFeedback = 'SendFeedback',
52+
AcceptAutoBuild = 'AcceptAutoBuild',
53+
DenyAutoBuild = 'DenyAutoBuild',
5254
}
5355

5456
export type SessionStatePhase = DevPhase.INIT | DevPhase.CODEGEN

packages/core/src/amazonqFeatureDev/util/files.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { TelemetryHelper } from './telemetryHelper'
1919
import { maxRepoSizeBytes } from '../constants'
2020
import { isCodeFile } from '../../shared/filetypes'
2121
import { fs } from '../../shared'
22+
import { CodeWhispererSettings } from '../../codewhisperer'
2223

2324
const getSha256 = (file: Buffer) => createHash('sha256').update(file).digest('base64')
2425

@@ -34,16 +35,22 @@ export async function prepareRepoData(
3435
) {
3536
try {
3637
const files = await collectFiles(repoRootPaths, workspaceFolders, true, maxRepoSizeBytes)
38+
const zip = new AdmZip()
39+
const autoBuildFeatureProjects = CodeWhispererSettings.instance.getAutoBuildFeatureProjects()
40+
const useAutoBuildFeature = autoBuildFeatureProjects[repoRootPaths[0]] ?? false
41+
getLogger().info(`featureDev: useAutoBuildFeature: ${useAutoBuildFeature} - ${repoRootPaths[0]}`)
3742

3843
let totalBytes = 0
3944
const ignoredExtensionMap = new Map<string, number>()
4045

4146
for (const file of files) {
4247
const fileSize = (await fs.stat(file.fileUri)).size
4348
const isCodeFile_ = isCodeFile(file.relativeFilePath)
49+
// True only when the file is not a code file & auto build feature is not enabled
50+
const isFilterNonCodeFile = !useAutoBuildFeature && !isCodeFile_
4451

45-
if (fileSize >= maxFileSizeBytes || !isCodeFile_) {
46-
if (!isCodeFile_) {
52+
if (fileSize >= maxFileSizeBytes || isFilterNonCodeFile) {
53+
if (isFilterNonCodeFile) {
4754
const re = /(?:\.([^.]+))?$/
4855
const extensionArray = re.exec(file.relativeFilePath)
4956
const extension = extensionArray?.length ? extensionArray[1] : undefined

packages/core/src/codewhisperer/util/codewhispererSettings.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const description = {
1212
workspaceIndexWorkerThreads: Number,
1313
workspaceIndexUseGPU: Boolean,
1414
workspaceIndexMaxSize: Number,
15+
autoBuildFeatureProjects: Object,
1516
}
1617

1718
export class CodeWhispererSettings extends fromExtensionManifest('amazonQ', description) {
@@ -64,6 +65,18 @@ export class CodeWhispererSettings extends fromExtensionManifest('amazonQ', desc
6465
return Math.max(this.get('workspaceIndexMaxSize', 250), 1)
6566
}
6667

68+
public getAutoBuildFeatureProjects(): { [key: string]: boolean } {
69+
return this.get('autoBuildFeatureProjects', {})
70+
}
71+
72+
public async updateToAutoBuildFeatureProjects(projectName: string, setting: boolean) {
73+
const projects = this.getAutoBuildFeatureProjects()
74+
75+
projects[projectName] = setting
76+
77+
await this.update('autoBuildFeatureProjects', projects)
78+
}
79+
6780
static #instance: CodeWhispererSettings
6881

6982
public static get instance() {

packages/core/src/shared/settings-amazonq.gen.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export const amazonqSettings = {
2121
"ssoCacheError": {}
2222
},
2323
"amazonQ.showInlineCodeSuggestionsWithCodeReferences": {},
24+
"amazonQ.autoBuildFeatureProjects": {},
2425
"amazonQ.importRecommendationForInlineCodeSuggestions": {},
2526
"amazonQ.shareContentWithAWS": {},
2627
"amazonQ.workspaceIndex": {},

0 commit comments

Comments
 (0)