Skip to content

Commit

Permalink
feat(feature dev): Add setting to opt in/out of QSDA auto build feature
Browse files Browse the repository at this point in the history
  • Loading branch information
willyyhuang committed Oct 25, 2024
1 parent 7cceffe commit 39f4bc4
Show file tree
Hide file tree
Showing 11 changed files with 102 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type": "Feature",
"description": "Amazon Q Feature Dev: Add new setting to opt in/out auto build feature"
}
5 changes: 5 additions & 0 deletions packages/amazonq/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,11 @@
"markdownDescription": "%AWS.configuration.description.amazonq%",
"default": true
},
"amazonQ.autoBuildFeatureProjects": {
"type": "object",
"markdownDescription": "%AWS.configuration.description.autoBuildFeatureProjects%",
"default": {}
},
"amazonQ.importRecommendationForInlineCodeSuggestions": {
"type": "boolean",
"description": "%AWS.configuration.description.amazonq.importRecommendation%",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ import {
sessionRegisterProvider,
sessionWriteFile,
assertTelemetry,
getTestWorkspaceFolder,
} from 'aws-core-vscode/test'
import { CurrentWsFolders, CodeGenState, FeatureDevClient, Messenger } from 'aws-core-vscode/amazonqFeatureDev'
import path from 'path'
import { fs } from 'aws-core-vscode/shared'
import { CodeWhispererSettings } from 'aws-core-vscode/codewhisperer'

describe('session', () => {
const conversationID = '12345'
Expand All @@ -36,6 +38,7 @@ describe('session', () => {

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

await session.preloader('implement twosum in typescript')
Expand Down
1 change: 1 addition & 0 deletions packages/core/package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"AWS.configuration.enableCodeLenses": "Enable SAM hints in source code and template.yaml files",
"AWS.configuration.description.resources.enabledResources": "AWS resources to display in the 'Resources' portion of the explorer.",
"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.",
"AWS.configuration.description.autoBuildFeatureProjects": "Projects with auto build feature enabled or disabled",
"AWS.stepFunctions.asl.format.enable.desc": "Enables the default formatter used with Amazon States Language files",
"AWS.stepFunctions.asl.maxItemsComputed.desc": "The maximum number of outline symbols and folding regions computed (limited for performance reasons).",
"AWS.configuration.description.awssam.debug.api": "API Gateway configuration",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import { getWorkspaceFoldersByPrefixes } from '../../../shared/utilities/workspa
import { openDeletedDiff, openDiff } from '../../../amazonq/commons/diff'
import { i18n } from '../../../shared/i18n-helper'
import globals from '../../../shared/extensionGlobals'
import { CodeWhispererSettings } from '../../../codewhisperer'

export const TotalSteps = 3

Expand Down Expand Up @@ -122,7 +123,7 @@ export class FeatureDevController {
getLogger().error('processChatItemFeedbackMessage failed: %s', (e as Error).message)
})
})
this.chatControllerMessageListeners.followUpClicked.event((data) => {
this.chatControllerMessageListeners.followUpClicked.event(async (data) => {
switch (data.followUp.type) {
case FollowUpTypes.InsertCode:
return this.insertCode(data)
Expand All @@ -147,6 +148,12 @@ export class FeatureDevController {
case FollowUpTypes.SendFeedback:
this.sendFeedback()
break
case FollowUpTypes.AcceptAutoBuild:
await this.processAutoBuildSetting(true)
return this.retryRequest(data)
case FollowUpTypes.DenyAutoBuild:
await this.processAutoBuildSetting(false)
return this.retryRequest(data)
}
})
this.chatControllerMessageListeners.openDiff.event((data) => {
Expand Down Expand Up @@ -537,6 +544,16 @@ export class FeatureDevController {
i18n('AWS.amazonq.featureDev.placeholder.additionalImprovements')
)
}

private async processAutoBuildSetting(setting: boolean) {
const workspaceFolders = vscode.workspace.workspaceFolders
const workspaceRoots = workspaceFolders?.map((f) => f.uri.fsPath)

if (workspaceRoots) {
await CodeWhispererSettings.instance.updateToAutoBuildFeatureProjects(workspaceRoots[0], setting)
}
}

// TODO add type
private async insertCode(message: any) {
let session
Expand Down
41 changes: 40 additions & 1 deletion packages/core/src/amazonqFeatureDev/session/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as path from 'path'

import { ConversationNotStartedState, PrepareCodeGenState } from './sessionState'
import {
FollowUpTypes,
type DeletedFileInfo,
type Interaction,
type NewFileInfo,
Expand All @@ -26,6 +27,8 @@ import { ReferenceLogViewProvider } from '../../codewhisperer/service/referenceL
import { AuthUtil } from '../../codewhisperer/util/authUtil'
import { getLogger } from '../../shared'
import { logWithConversationId } from '../userFacingText'
import { CodeWhispererSettings } from '../../codewhisperer'

export class Session {
private _state?: SessionState | Omit<SessionState, 'uploadId'>
private task: string = ''
Expand Down Expand Up @@ -59,14 +62,50 @@ export class Session {
* Preload any events that have to run before a chat message can be sent
*/
async preloader(msg: string) {
if (!this.preloaderFinished) {
const root = this.config.workspaceRoots[0]
const projects = CodeWhispererSettings.instance.getAutoBuildFeatureProjects()

if (Object.keys(projects).includes(root) && !this.preloaderFinished) {
await this.setupConversation(msg)
this.preloaderFinished = true
this.messenger.sendAsyncEventProgress(this.tabID, true, undefined)
await this.proxyClient.sendFeatureDevTelemetryEvent(this.conversationId) // send the event only once per conversation.
} else {
await this.promptUserConsent()
}
}

/**
*
*/

private async promptUserConsent() {
this.messenger.sendAnswer({
tabID: this.tabID,
message:
'Would you like to use the auto build feature that will allow Amazon Q feature development agent to build and test your project?',
type: 'answer',
})

this.messenger.sendAnswer({
message: undefined,
type: 'system-prompt',
followUps: [
{
pillText: 'Accept for this project',
type: FollowUpTypes.AcceptAutoBuild,
status: 'info',
},
{
pillText: 'Deny for this project',
type: FollowUpTypes.DenyAutoBuild,
status: 'info',
},
],
tabID: this.tabID,
})
}

/**
* setupConversation
*
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/amazonqFeatureDev/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ export enum FollowUpTypes {
NewTask = 'NewTask',
CloseSession = 'CloseSession',
SendFeedback = 'SendFeedback',
AcceptAutoBuild = 'AcceptAutoBuild',
DenyAutoBuild = 'DenyAutoBuild',
}

export type SessionStatePhase = DevPhase.INIT | DevPhase.CODEGEN
Expand Down
8 changes: 7 additions & 1 deletion packages/core/src/amazonqFeatureDev/util/files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { TelemetryHelper } from './telemetryHelper'
import { maxRepoSizeBytes } from '../constants'
import { isCodeFile } from '../../shared/filetypes'
import { fs } from '../../shared'
import { CodeWhispererSettings } from '../../codewhisperer'

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

Expand All @@ -34,15 +35,20 @@ export async function prepareRepoData(
) {
try {
const files = await collectFiles(repoRootPaths, workspaceFolders, true, maxRepoSizeBytes)
const zip = new AdmZip()
const autoBuildFeatureProjects = CodeWhispererSettings.instance.getAutoBuildFeatureProjects()
const useAutoBuildFeature = autoBuildFeatureProjects[repoRootPaths[0]] ?? false

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

for (const file of files) {
const fileSize = (await fs.stat(file.fileUri)).size
const isCodeFile_ = isCodeFile(file.relativeFilePath)
// exclude user's devfile if `useAutoBuildFeature` is set to false
const excludeDevFile = useAutoBuildFeature ? false : file.relativeFilePath === 'devfile.yaml'

if (fileSize >= maxFileSizeBytes || !isCodeFile_) {
if (fileSize >= maxFileSizeBytes || !isCodeFile_ || excludeDevFile) {
if (!isCodeFile_) {
const re = /(?:\.([^.]+))?$/
const extensionArray = re.exec(file.relativeFilePath)
Expand Down
13 changes: 13 additions & 0 deletions packages/core/src/codewhisperer/util/codewhispererSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const description = {
workspaceIndexWorkerThreads: Number,
workspaceIndexUseGPU: Boolean,
workspaceIndexMaxSize: Number,
autoBuildFeatureProjects: Object,
}

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

public getAutoBuildFeatureProjects(): { [key: string]: boolean } {
return this.get('autoBuildFeatureProjects', {})
}

public async updateToAutoBuildFeatureProjects(projectName: string, setting: boolean) {
const projects = this.getAutoBuildFeatureProjects()

projects[projectName] = setting

await this.update('autoBuildFeatureProjects', projects)
}

static #instance: CodeWhispererSettings

public static get instance() {
Expand Down
8 changes: 8 additions & 0 deletions packages/core/src/shared/filetypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ export const codefileExtensions = new Set([
'.cbl',
'.cc',
'.cfc',
'.cfg',
'.cfm',
'.cjs',
'.clj',
Expand All @@ -175,6 +176,7 @@ export const codefileExtensions = new Set([
'.cob',
'.cobra',
'.coffee',
'.config',
'.cpp',
'.cpy',
'.cr',
Expand All @@ -189,6 +191,7 @@ export const codefileExtensions = new Set([
'.e',
'.el',
'.elm',
'.env',
'.erl',
'.ex',
'.exs',
Expand All @@ -204,6 +207,7 @@ export const codefileExtensions = new Set([
'.fsi',
'.fsx',
'.gd',
'.gitignore',
'.go',
'.gql',
'.graphql',
Expand All @@ -223,6 +227,7 @@ export const codefileExtensions = new Set([
'.html',
'.hy',
'.idl',
'.ini',
'.io',
'.jar',
'.java',
Expand All @@ -236,6 +241,7 @@ export const codefileExtensions = new Set([
'.lgt',
'.lhs',
'.lisp',
'.lock',
'.logtalk',
'.lsp',
'.lua',
Expand Down Expand Up @@ -324,10 +330,12 @@ export const codefileExtensions = new Set([
'.t',
'.tcl',
'.tf',
'.toml',
'.trigger',
'.ts',
'.tsx',
'.tu',
'.txt',
'.v',
'.vala',
'.vapi',
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/shared/settings-amazonq.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const amazonqSettings = {
"ssoCacheError": {}
},
"amazonQ.showInlineCodeSuggestionsWithCodeReferences": {},
"amazonQ.autoBuildFeatureProjects": {},
"amazonQ.importRecommendationForInlineCodeSuggestions": {},
"amazonQ.shareContentWithAWS": {},
"amazonQ.workspaceIndex": {},
Expand Down

0 comments on commit 39f4bc4

Please sign in to comment.