diff --git a/.changes/next-release/feature-c5c4cc47-126a-4236-82af-70743a805ca8.json b/.changes/next-release/feature-c5c4cc47-126a-4236-82af-70743a805ca8.json new file mode 100644 index 00000000000..fd0838d9f88 --- /dev/null +++ b/.changes/next-release/feature-c5c4cc47-126a-4236-82af-70743a805ca8.json @@ -0,0 +1,4 @@ +{ + "type" : "feature", + "description" : "Amazon Q /dev: Add stop generation action" +} \ No newline at end of file diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/FeatureDevApp.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/FeatureDevApp.kt index 681324644b0..2eb428563ef 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/FeatureDevApp.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/FeatureDevApp.kt @@ -41,7 +41,8 @@ class FeatureDevApp : AmazonQApp { "response-body-link-click" to IncomingFeatureDevMessage.ClickedLink::class, "insert_code_at_cursor_position" to IncomingFeatureDevMessage.InsertCodeAtCursorPosition::class, "open-diff" to IncomingFeatureDevMessage.OpenDiff::class, - "file-click" to IncomingFeatureDevMessage.FileClicked::class + "file-click" to IncomingFeatureDevMessage.FileClicked::class, + "stop-response" to IncomingFeatureDevMessage.StopResponse::class ) scope.launch { @@ -82,6 +83,7 @@ class FeatureDevApp : AmazonQApp { is IncomingFeatureDevMessage.InsertCodeAtCursorPosition -> inboundAppMessagesHandler.processInsertCodeAtCursorPosition(message) is IncomingFeatureDevMessage.OpenDiff -> inboundAppMessagesHandler.processOpenDiff(message) is IncomingFeatureDevMessage.FileClicked -> inboundAppMessagesHandler.processFileClicked(message) + is IncomingFeatureDevMessage.StopResponse -> inboundAppMessagesHandler.processStopMessage(message) } } diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/InboundAppMessagesHandler.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/InboundAppMessagesHandler.kt index c54331797e5..14ca39cd555 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/InboundAppMessagesHandler.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/InboundAppMessagesHandler.kt @@ -17,4 +17,5 @@ interface InboundAppMessagesHandler { suspend fun processInsertCodeAtCursorPosition(message: IncomingFeatureDevMessage.InsertCodeAtCursorPosition) suspend fun processOpenDiff(message: IncomingFeatureDevMessage.OpenDiff) suspend fun processFileClicked(message: IncomingFeatureDevMessage.FileClicked) + suspend fun processStopMessage(message: IncomingFeatureDevMessage.StopResponse) } diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/clients/FeatureDevClient.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/clients/FeatureDevClient.kt index bc877f051d2..7d6abb05d9f 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/clients/FeatureDevClient.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/clients/FeatureDevClient.kt @@ -39,7 +39,9 @@ import java.time.Instant import software.amazon.awssdk.services.codewhispererruntime.model.ChatTriggerType as SyncChatTriggerType @Service(Service.Level.PROJECT) -class FeatureDevClient(private val project: Project) { +class FeatureDevClient( + private val project: Project, +) { fun getTelemetryOptOutPreference() = if (AwsSettings.getInstance().isTelemetryEnabled) { OptOutPreference.OPTIN @@ -47,99 +49,125 @@ class FeatureDevClient(private val project: Project) { OptOutPreference.OPTOUT } - private val featureDevUserContext = ClientMetadata.getDefault().let { - val osForFeatureDev: OperatingSystem = - when { - SystemInfo.isWindows -> OperatingSystem.WINDOWS - SystemInfo.isMac -> OperatingSystem.MAC - // For now, categorize everything else as "Linux" (Linux/FreeBSD/Solaris/etc.) - else -> OperatingSystem.LINUX - } + private val featureDevUserContext = + ClientMetadata.getDefault().let { + val osForFeatureDev: OperatingSystem = + when { + SystemInfo.isWindows -> OperatingSystem.WINDOWS + SystemInfo.isMac -> OperatingSystem.MAC + // For now, categorize everything else as "Linux" (Linux/FreeBSD/Solaris/etc.) + else -> OperatingSystem.LINUX + } - UserContext.builder() - .ideCategory(IdeCategory.JETBRAINS) - .operatingSystem(osForFeatureDev) - .product(FEATURE_EVALUATION_PRODUCT_NAME) - .clientId(it.clientId) - .ideVersion(it.awsVersion) - .build() - } + UserContext + .builder() + .ideCategory(IdeCategory.JETBRAINS) + .operatingSystem(osForFeatureDev) + .product(FEATURE_EVALUATION_PRODUCT_NAME) + .clientId(it.clientId) + .ideVersion(it.awsVersion) + .build() + } - private fun connection() = ToolkitConnectionManager.getInstance(project).activeConnectionForFeature(QConnection.getInstance()) - ?: error("Attempted to use connection while one does not exist") + private fun connection() = + ToolkitConnectionManager.getInstance(project).activeConnectionForFeature(QConnection.getInstance()) + ?: error("Attempted to use connection while one does not exist") private fun bearerClient() = connection().getConnectionSettings().awsClient() private val amazonQStreamingClient get() = AmazonQStreamingClient.getInstance(project) - fun sendFeatureDevTelemetryEvent(conversationId: String): SendTelemetryEventResponse = bearerClient().sendTelemetryEvent { requestBuilder -> - requestBuilder.telemetryEvent { telemetryEventBuilder -> - telemetryEventBuilder.featureDevEvent { - it.conversationId(conversationId) + fun sendFeatureDevTelemetryEvent(conversationId: String): SendTelemetryEventResponse = + bearerClient().sendTelemetryEvent { requestBuilder -> + requestBuilder.telemetryEvent { telemetryEventBuilder -> + telemetryEventBuilder.featureDevEvent { + it.conversationId(conversationId) + } } + requestBuilder.optOutPreference(getTelemetryOptOutPreference()) + requestBuilder.userContext(featureDevUserContext) } - requestBuilder.optOutPreference(getTelemetryOptOutPreference()) - requestBuilder.userContext(featureDevUserContext) - } - fun createTaskAssistConversation(): CreateTaskAssistConversationResponse = bearerClient().createTaskAssistConversation( - CreateTaskAssistConversationRequest.builder().build() - ) - - fun createTaskAssistUploadUrl(conversationId: String, contentChecksumSha256: String, contentLength: Long): CreateUploadUrlResponse = + fun createTaskAssistConversation(): CreateTaskAssistConversationResponse = + bearerClient().createTaskAssistConversation( + CreateTaskAssistConversationRequest.builder().build(), + ) + + fun createTaskAssistUploadUrl( + conversationId: String, + contentChecksumSha256: String, + contentLength: Long, + uploadId: String, + ): CreateUploadUrlResponse = bearerClient().createUploadUrl { - it.contentChecksumType(ContentChecksumType.SHA_256) + it + .contentChecksumType(ContentChecksumType.SHA_256) + .uploadId(uploadId) .contentChecksum(contentChecksumSha256) .contentLength(contentLength) .artifactType(ArtifactType.SOURCE_CODE) .uploadIntent(UploadIntent.TASK_ASSIST_PLANNING) .uploadContext( - UploadContext.builder() + UploadContext + .builder() .taskAssistPlanningUploadContext( - TaskAssistPlanningUploadContext.builder() + TaskAssistPlanningUploadContext + .builder() .conversationId(conversationId) - .build() - ) - .build() + .build(), + ).build(), ) } - fun startTaskAssistCodeGeneration(conversationId: String, uploadId: String, userMessage: String): StartTaskAssistCodeGenerationResponse = bearerClient() - .startTaskAssistCodeGeneration { - request -> - request - .conversationState { - it - .conversationId(conversationId) - .chatTriggerType(SyncChatTriggerType.MANUAL) - .currentMessage { cm -> cm.userInputMessage { um -> um.content(userMessage) } } - } - .workspaceState { - it - .programmingLanguage { pl -> pl.languageName("javascript") } // This parameter is omitted by featureDev but required in the request - .uploadId(uploadId) - } - } + fun startTaskAssistCodeGeneration( + conversationId: String, + uploadId: String, + userMessage: String, + codeGenerationId: String?, + currentCodeGenerationId: String?, + ): StartTaskAssistCodeGenerationResponse = + bearerClient() + .startTaskAssistCodeGeneration { request -> + request + .conversationState { + it + .conversationId(conversationId) + .chatTriggerType(SyncChatTriggerType.MANUAL) + .currentMessage { cm -> cm.userInputMessage { um -> um.content(userMessage) } } + }.workspaceState { + it + .programmingLanguage { pl -> pl.languageName("javascript") } // This parameter is omitted by featureDev but required in the request + .uploadId(uploadId) + }.codeGenerationId(codeGenerationId.toString()) + .currentCodeGenerationId(currentCodeGenerationId) + } - fun getTaskAssistCodeGeneration(conversationId: String, codeGenerationId: String): GetTaskAssistCodeGenerationResponse = bearerClient() - .getTaskAssistCodeGeneration { - it - .conversationId(conversationId) - .codeGenerationId(codeGenerationId) - } + fun getTaskAssistCodeGeneration( + conversationId: String, + codeGenerationId: String, + ): GetTaskAssistCodeGenerationResponse = + bearerClient() + .getTaskAssistCodeGeneration { + it + .conversationId(conversationId) + .codeGenerationId(codeGenerationId) + } - suspend fun exportTaskAssistResultArchive(conversationId: String): MutableList = amazonQStreamingClient.exportResultArchive( - conversationId, - ExportIntent.TASK_ASSIST, - null, - { e -> - LOG.error(e) { "TaskAssist - ExportResultArchive stream exportId=$conversationId exportIntent=${ExportIntent.TASK_ASSIST} Failed: ${e.message} " } - }, - { startTime -> - LOG.info { "TaskAssist - ExportResultArchive latency: ${calculateTotalLatency(startTime, Instant.now())}" } - } - ) + suspend fun exportTaskAssistResultArchive(conversationId: String): MutableList = + amazonQStreamingClient.exportResultArchive( + conversationId, + ExportIntent.TASK_ASSIST, + null, + { e -> + LOG.error( + e, + ) { "TaskAssist - ExportResultArchive stream exportId=$conversationId exportIntent=${ExportIntent.TASK_ASSIST} Failed: ${e.message} " } + }, + { startTime -> + LOG.info { "TaskAssist - ExportResultArchive latency: ${calculateTotalLatency(startTime, Instant.now())}" } + }, + ) companion object { private val LOG = getLogger() diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/controller/FeatureDevController.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/controller/FeatureDevController.kt index af79bca98c8..4fa4381e319 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/controller/FeatureDevController.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/controller/FeatureDevController.kt @@ -15,6 +15,7 @@ import com.intellij.openapi.command.WriteCommandAction import com.intellij.openapi.editor.Caret import com.intellij.openapi.editor.Editor import com.intellij.openapi.fileEditor.FileEditorManager +import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VfsUtil import com.intellij.openapi.wm.ToolWindowManager import kotlinx.coroutines.withContext @@ -74,6 +75,7 @@ import software.aws.toolkits.jetbrains.utils.notifyError import software.aws.toolkits.resources.message import software.aws.toolkits.telemetry.AmazonqTelemetry import software.aws.toolkits.telemetry.Result +import software.aws.toolkits.telemetry.UiTelemetry import java.util.UUID class FeatureDevController( @@ -92,6 +94,10 @@ class FeatureDevController( ) } + override suspend fun processStopMessage(message: IncomingFeatureDevMessage.StopResponse) { + handleStopMessage(message) + } + override suspend fun processNewTabCreatedMessage(message: IncomingFeatureDevMessage.NewTabCreated) { newTabOpened(message.tabId) } @@ -284,6 +290,26 @@ class FeatureDevController( } } + private suspend fun handleStopMessage(message: IncomingFeatureDevMessage.StopResponse) { + val session: Session? + UiTelemetry.click(null as Project?, "amazonq_stopCodeGeneration") + messenger.sendAnswer( + tabId = message.tabId, + message("amazonqFeatureDev.code_generation.stopping_code_generation"), + messageType = FeatureDevMessageType.Answer, + canBeVoted = false + ) + messenger.sendUpdatePlaceholder( + tabId = message.tabId, + newPlaceholder = message("amazonqFeatureDev.code_generation.stopping_code_generation") + ) + messenger.sendChatInputEnabledMessage(tabId = message.tabId, enabled = false) + session = getSessionInfo(message.tabId) + + if (session.sessionState.token?.token !== null) { + session.sessionState.token?.cancel() + } + } private suspend fun insertCode(tabId: String) { var session: Session? = null try { diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/controller/FeatureDevControllerExtensions.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/controller/FeatureDevControllerExtensions.kt index 9fef1527cc3..ccd52ed5fd0 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/controller/FeatureDevControllerExtensions.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/controller/FeatureDevControllerExtensions.kt @@ -4,6 +4,7 @@ package software.aws.toolkits.jetbrains.services.amazonqFeatureDev.controller import com.intellij.notification.NotificationAction +import software.aws.toolkits.jetbrains.services.amazonq.messages.MessagePublisher import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.CODE_GENERATION_RETRY_LIMIT import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.messages.FeatureDevMessageType import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.messages.FollowUp @@ -20,17 +21,23 @@ import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.session.Delete import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.session.NewFileZipInfo import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.session.PrepareCodeGenerationState import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.session.Session +import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.session.SessionState +import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.CancellationTokenSource import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.getFollowUpOptions import software.aws.toolkits.jetbrains.utils.notifyInfo import software.aws.toolkits.resources.message -suspend fun FeatureDevController.onCodeGeneration(session: Session, message: String, tabId: String) { +suspend fun FeatureDevController.onCodeGeneration( + session: Session, + message: String, + tabId: String, +) { messenger.sendAsyncEventProgress( tabId = tabId, inProgress = true, message = if (session.retries == CODE_GENERATION_RETRY_LIMIT) { message( - "amazonqFeatureDev.chat_message.start_code_generation" + "amazonqFeatureDev.chat_message.start_code_generation", ) } else { message("amazonqFeatureDev.chat_message.start_code_generation_retry") @@ -43,19 +50,24 @@ suspend fun FeatureDevController.onCodeGeneration(session: Session, message: Str message = message("amazonqFeatureDev.chat_message.requesting_changes"), messageType = FeatureDevMessageType.AnswerStream, ) + val state = session.sessionState + + var remainingIterations: Int? = state.codeGenerationRemainingIterationCount + var totalIterations: Int? = state.codeGenerationTotalIterationCount + + if (state.token?.token?.isCancellationRequested() == true) { + disposeToken(state, messenger, tabId, state.currentIteration?.let { CODE_GENERATION_RETRY_LIMIT.minus(it) }, CODE_GENERATION_RETRY_LIMIT) + return + } messenger.sendUpdatePlaceholder(tabId = tabId, newPlaceholder = message("amazonqFeatureDev.placeholder.generating_code")) session.send(message) // Trigger code generation - val state = session.sessionState - var filePaths: List = emptyList() var deletedFiles: List = emptyList() var references: List = emptyList() var uploadId = "" - var remainingIterations: Int? = null - var totalIterations: Int? = null when (state) { is PrepareCodeGenerationState -> { @@ -68,26 +80,32 @@ suspend fun FeatureDevController.onCodeGeneration(session: Session, message: Str } } + if (state.token?.token?.isCancellationRequested() == true) { + disposeToken(state, messenger, tabId, state.currentIteration?.let { CODE_GENERATION_RETRY_LIMIT.minus(it) }, CODE_GENERATION_RETRY_LIMIT) + return + } + // Atm this is the only possible path as codegen is mocked to return empty. if (filePaths.size or deletedFiles.size == 0) { messenger.sendAnswer( tabId = tabId, messageType = FeatureDevMessageType.Answer, - message = message("amazonqFeatureDev.code_generation.no_file_changes") + message = message("amazonqFeatureDev.code_generation.no_file_changes"), ) messenger.sendSystemPrompt( tabId = tabId, - followUp = if (retriesRemaining(session) > 0) { + followUp = + if (retriesRemaining(session) > 0) { listOf( FollowUp( pillText = message("amazonqFeatureDev.follow_up.retry"), type = FollowUpTypes.RETRY, - status = FollowUpStatusType.Warning - ) + status = FollowUpStatusType.Warning, + ), ) } else { emptyList() - } + }, ) messenger.sendChatInputEnabledMessage(tabId = tabId, enabled = false) // Lock chat input until retry is clicked. return @@ -99,15 +117,16 @@ suspend fun FeatureDevController.onCodeGeneration(session: Session, message: Str messenger.sendAnswer( tabId = tabId, messageType = FeatureDevMessageType.Answer, - message = if (remainingIterations == 0) { + message = + if (remainingIterations == 0) { message("amazonqFeatureDev.code_generation.iteration_zero") } else { message( "amazonqFeatureDev.code_generation.iteration_counts", remainingIterations, - totalIterations + totalIterations, ) - } + }, ) } @@ -115,22 +134,87 @@ suspend fun FeatureDevController.onCodeGeneration(session: Session, message: Str messenger.sendUpdatePlaceholder(tabId = tabId, newPlaceholder = message("amazonqFeatureDev.placeholder.after_code_generation")) } finally { - messenger.sendAsyncEventProgress(tabId = tabId, inProgress = false) // Finish processing the event - messenger.sendChatInputEnabledMessage(tabId = tabId, enabled = false) // Lock chat input until a follow-up is clicked. - + if (session.sessionState.token + ?.token + ?.isCancellationRequested() == true + ) { + session.sessionState.token = CancellationTokenSource() + } else { + messenger.sendAsyncEventProgress(tabId = tabId, inProgress = false) // Finish processing the event + messenger.sendChatInputEnabledMessage(tabId = tabId, enabled = false) // Lock chat input until a follow-up is clicked. + } if (toolWindow != null && !toolWindow.isVisible) { notifyInfo( title = message("amazonqFeatureDev.code_generation.notification_title"), content = message("amazonqFeatureDev.code_generation.notification_message"), project = getProject(), - notificationActions = listOf(openChatNotificationAction()) + notificationActions = listOf(openChatNotificationAction()), ) } } } -private fun FeatureDevController.openChatNotificationAction() = NotificationAction.createSimple( - message("amazonqFeatureDev.code_generation.notification_open_link") +private suspend fun disposeToken( + state: SessionState, + messenger: MessagePublisher, + tabId: String, + remainingIterations: Int?, + totalIterations: Int?, ) { - toolWindow?.show() + if (remainingIterations !== null && remainingIterations <= 0) { + messenger.sendAnswer( + tabId = tabId, + messageType = FeatureDevMessageType.Answer, + message = + message( + "amazonqFeatureDev.code_generation.stopped_code_generation_no_iterations", + ), + ) + // I stopped generating your code. You don't have more iterations left, however, you can start a new session + messenger.sendSystemPrompt( + tabId = tabId, + followUp = + listOf( + FollowUp( + pillText = message("amazonqFeatureDev.follow_up.new_task"), + type = FollowUpTypes.NEW_TASK, + status = FollowUpStatusType.Info, + ), + FollowUp( + pillText = message("amazonqFeatureDev.follow_up.close_session"), + type = FollowUpTypes.CLOSE_SESSION, + status = FollowUpStatusType.Info, + ), + ), + ) + messenger.sendChatInputEnabledMessage(tabId = tabId, enabled = false) + messenger.sendUpdatePlaceholder(tabId = tabId, newPlaceholder = message("amazonqFeatureDev.placeholder.after_code_generation")) + + return + } + + messenger.sendAnswer( + tabId = tabId, + messageType = FeatureDevMessageType.Answer, + message = + message( + "amazonqFeatureDev.code_generation.stopped_code_generation", + remainingIterations ?: state.currentIteration?.let { CODE_GENERATION_RETRY_LIMIT - it } as Any, + totalIterations ?: CODE_GENERATION_RETRY_LIMIT, + ), + ) + + messenger.sendChatInputEnabledMessage(tabId = tabId, enabled = true) + + messenger.sendUpdatePlaceholder( + tabId = tabId, + newPlaceholder = message("amazonqFeatureDev.placeholder.new_plan"), + ) } + +private fun FeatureDevController.openChatNotificationAction() = + NotificationAction.createSimple( + message("amazonqFeatureDev.code_generation.notification_open_link"), + ) { + toolWindow?.show() + } diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/messages/FeatureDevMessage.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/messages/FeatureDevMessage.kt index f5464534fc3..1ad226f96b9 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/messages/FeatureDevMessage.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/messages/FeatureDevMessage.kt @@ -66,6 +66,12 @@ sealed interface IncomingFeatureDevMessage : FeatureDevBaseMessage { val link: String, ) : IncomingFeatureDevMessage + data class StopResponse( + @JsonProperty("tabID") val tabId: String, + val command: String, + val messageId: String?, + ) : IncomingFeatureDevMessage + data class InsertCodeAtCursorPosition( @JsonProperty("tabID") val tabId: String, val code: String, diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/CodeGenerationState.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/CodeGenerationState.kt index c5d7acccb17..7801085fd5c 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/CodeGenerationState.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/CodeGenerationState.kt @@ -19,10 +19,12 @@ import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.PromptRefusalE import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.ThrottlingException import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.messages.sendAnswerPart import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.messages.sendUpdatePlaceholder +import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.CancellationTokenSource import software.aws.toolkits.jetbrains.services.cwc.controller.chat.telemetry.getStartUrl import software.aws.toolkits.resources.message import software.aws.toolkits.telemetry.AmazonqTelemetry import software.aws.toolkits.telemetry.Result +import java.util.UUID private val logger = getLogger() @@ -31,11 +33,13 @@ class CodeGenerationState( override var approach: String, val config: SessionStateConfig, val uploadId: String, - val currentIteration: Int, + override var currentIteration: Int? = 0, val repositorySize: Double, val messenger: MessagePublisher, - var codeGenerationRemainingIterationCount: Int? = null, - var codeGenerationTotalIterationCount: Int? = null, + override var codeGenerationRemainingIterationCount: Int? = null, + override var codeGenerationTotalIterationCount: Int? = null, + var currentCodeGenerationId: String? = "EMPTY_CURRENT_CODE_GENERATION_ID", + override var token: CancellationTokenSource?, ) : SessionState { override val phase = SessionStatePhase.CODEGEN @@ -48,46 +52,56 @@ class CodeGenerationState( var numberOfReferencesGenerated: Int? = null var numberOfFilesGenerated: Int? = null try { - val response = config.featureDevService.startTaskAssistCodeGeneration( - conversationId = config.conversationId, - uploadId = uploadId, - message = action.msg - ) + val codeGenerationId = UUID.randomUUID() + + val response = + config.featureDevService.startTaskAssistCodeGeneration( + conversationId = config.conversationId, + uploadId = uploadId, + message = action.msg, + codeGenerationId = codeGenerationId.toString(), + currentCodeGenerationId = currentCodeGenerationId.toString(), + ) + + if (action.token?.token?.isCancellationRequested() != true) { + this.currentCodeGenerationId = codeGenerationId.toString() + } messenger.sendAnswerPart( tabId = tabID, - message = message("amazonqFeatureDev.code_generation.generating_code") + message = message("amazonqFeatureDev.code_generation.generating_code"), ) messenger.sendUpdatePlaceholder( tabId = tabID, - newPlaceholder = message("amazonqFeatureDev.code_generation.generating_code") + newPlaceholder = message("amazonqFeatureDev.code_generation.generating_code"), ) - - val codeGenerationResult = generateCode(codeGenerationId = response.codeGenerationId(), messenger = messenger) + val codeGenerationResult = generateCode(codeGenerationId = response.codeGenerationId(), messenger = messenger, token = action.token) numberOfReferencesGenerated = codeGenerationResult.references.size numberOfFilesGenerated = codeGenerationResult.newFiles.size codeGenerationRemainingIterationCount = codeGenerationResult.codeGenerationRemainingIterationCount codeGenerationTotalIterationCount = codeGenerationResult.codeGenerationTotalIterationCount - val nextState = PrepareCodeGenerationState( - tabID = tabID, - approach = approach, - config = config, - filePaths = codeGenerationResult.newFiles, - deletedFiles = codeGenerationResult.deletedFiles, - references = codeGenerationResult.references, - currentIteration = currentIteration + 1, - uploadId = uploadId, - messenger = messenger, - codeGenerationRemainingIterationCount = codeGenerationRemainingIterationCount, - codeGenerationTotalIterationCount = codeGenerationTotalIterationCount - ) + val nextState = + PrepareCodeGenerationState( + tabID = tabID, + approach = approach, + config = config, + filePaths = codeGenerationResult.newFiles, + deletedFiles = codeGenerationResult.deletedFiles, + references = codeGenerationResult.references, + currentIteration = currentIteration?.plus(1), + uploadId = uploadId, + messenger = messenger, + codeGenerationRemainingIterationCount = codeGenerationRemainingIterationCount, + codeGenerationTotalIterationCount = codeGenerationTotalIterationCount, + token = this.token, + ) // It is not needed to interact right away with the PrepareCodeGeneration. // returns therefore a SessionStateInteraction object to be handled by the controller. return SessionStateInteraction( nextState = nextState, - interaction = Interaction(content = "", interactionSucceeded = true) + interaction = Interaction(content = "", interactionSucceeded = true), ) } catch (e: Exception) { logger.warn(e) { "$FEATURE_NAME: Code generation failed: ${e.message}" } @@ -101,39 +115,50 @@ class CodeGenerationState( throw e } finally { - AmazonqTelemetry.codeGenerationInvoke( - amazonqConversationId = config.conversationId, - amazonqCodeGenerationResult = codeGenerationWorkflowStatus.toString(), - amazonqGenerateCodeIteration = currentIteration.toDouble(), - amazonqNumberOfReferences = numberOfReferencesGenerated?.toDouble(), - amazonqGenerateCodeResponseLatency = (System.currentTimeMillis() - startTime).toDouble(), - amazonqNumberOfFilesGenerated = numberOfFilesGenerated?.toDouble(), - amazonqRepositorySize = repositorySize, - result = result, - reason = failureReason, - reasonDesc = failureReasonDesc, - duration = (System.currentTimeMillis() - startTime).toDouble(), - credentialStartUrl = getStartUrl(config.featureDevService.project) - ) + currentIteration?.let { + AmazonqTelemetry.codeGenerationInvoke( + amazonqConversationId = config.conversationId, + amazonqCodeGenerationResult = codeGenerationWorkflowStatus.toString(), + amazonqGenerateCodeIteration = it.toDouble(), + amazonqNumberOfReferences = numberOfReferencesGenerated?.toDouble(), + amazonqGenerateCodeResponseLatency = (System.currentTimeMillis() - startTime).toDouble(), + amazonqNumberOfFilesGenerated = numberOfFilesGenerated?.toDouble(), + amazonqRepositorySize = repositorySize, + result = result, + reason = failureReason, + reasonDesc = failureReasonDesc, + duration = (System.currentTimeMillis() - startTime).toDouble(), + credentialStartUrl = getStartUrl(config.featureDevService.project), + ) + } } } } -private suspend fun CodeGenerationState.generateCode(codeGenerationId: String, messenger: MessagePublisher): CodeGenerationResult { +private suspend fun CodeGenerationState.generateCode( + codeGenerationId: String, + messenger: MessagePublisher, + token: CancellationTokenSource?, +): CodeGenerationResult { val pollCount = 180 val requestDelay = 10000L repeat(pollCount) { - val codeGenerationResultState = config.featureDevService.getTaskAssistCodeGeneration( - conversationId = config.conversationId, - codeGenerationId = codeGenerationId, - ) + if (token?.token?.isCancellationRequested() == true) { + return CodeGenerationResult(emptyList(), emptyList(), emptyList()) + } + val codeGenerationResultState = + config.featureDevService.getTaskAssistCodeGeneration( + conversationId = config.conversationId, + codeGenerationId = codeGenerationId, + ) when (codeGenerationResultState.codeGenerationStatus().status()) { CodeGenerationWorkflowStatus.COMPLETE -> { - val codeGenerationStreamResult = config.featureDevService.exportTaskAssistArchiveResult( - conversationId = config.conversationId - ) + val codeGenerationStreamResult = + config.featureDevService.exportTaskAssistArchiveResult( + conversationId = config.conversationId, + ) val newFileInfo = registerNewFiles(newFileContents = codeGenerationStreamResult.new_file_contents) val deletedFileInfo = registerDeletedFiles(deletedFiles = codeGenerationStreamResult.deleted_files) @@ -143,15 +168,16 @@ private suspend fun CodeGenerationState.generateCode(codeGenerationId: String, m deletedFiles = deletedFileInfo, references = codeGenerationStreamResult.references, codeGenerationRemainingIterationCount = codeGenerationResultState.codeGenerationRemainingIterationCount(), - codeGenerationTotalIterationCount = codeGenerationResultState.codeGenerationTotalIterationCount() + codeGenerationTotalIterationCount = codeGenerationResultState.codeGenerationTotalIterationCount(), ) } CodeGenerationWorkflowStatus.IN_PROGRESS -> { if (codeGenerationResultState.codeGenerationStatusDetail() != null) { messenger.sendAnswerPart( tabId = tabID, - message = message("amazonqFeatureDev.code_generation.generating_code") + - "\n\n" + codeGenerationResultState.codeGenerationStatusDetail() + message = + message("amazonqFeatureDev.code_generation.generating_code") + + "\n\n" + codeGenerationResultState.codeGenerationStatusDetail(), ) } delay(requestDelay) @@ -159,15 +185,15 @@ private suspend fun CodeGenerationState.generateCode(codeGenerationId: String, m CodeGenerationWorkflowStatus.FAILED -> { when (true) { codeGenerationResultState.codeGenerationStatusDetail()?.contains( - "Guardrails" + "Guardrails", ), -> throw GuardrailsException(operation = FeatureDevOperation.GenerateCode.toString(), desc = "Failed guardrails") codeGenerationResultState.codeGenerationStatusDetail()?.contains( - "PromptRefusal" + "PromptRefusal", ), -> throw PromptRefusalException(operation = FeatureDevOperation.GenerateCode.toString(), desc = "Prompt refusal") codeGenerationResultState.codeGenerationStatusDetail()?.contains( - "EmptyPatch" + "EmptyPatch", ), -> { if (codeGenerationResultState.codeGenerationStatusDetail().contains("NO_CHANGE_REQUIRED")) { @@ -176,7 +202,7 @@ private suspend fun CodeGenerationState.generateCode(codeGenerationId: String, m throw EmptyPatchException(operation = FeatureDevOperation.GenerateCode.toString(), desc = "Empty patch") } codeGenerationResultState.codeGenerationStatusDetail()?.contains( - "Throttling" + "Throttling", ), -> throw ThrottlingException(operation = FeatureDevOperation.GenerateCode.toString(), desc = "Request throttled") else -> throw CodeGenerationException(operation = FeatureDevOperation.GenerateCode.toString(), desc = null) @@ -189,17 +215,19 @@ private suspend fun CodeGenerationState.generateCode(codeGenerationId: String, m return CodeGenerationResult(emptyList(), emptyList(), emptyList()) } -fun registerNewFiles(newFileContents: Map): List = newFileContents.map { - NewFileZipInfo( - zipFilePath = it.key, - fileContent = it.value, - rejected = false - ) -} +fun registerNewFiles(newFileContents: Map): List = + newFileContents.map { + NewFileZipInfo( + zipFilePath = it.key, + fileContent = it.value, + rejected = false, + ) + } -fun registerDeletedFiles(deletedFiles: List): List = deletedFiles.map { - DeletedFileInfo( - zipFilePath = it, - rejected = false - ) -} +fun registerDeletedFiles(deletedFiles: List): List = + deletedFiles.map { + DeletedFileInfo( + zipFilePath = it, + rejected = false, + ) + } diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/ConversationNotStartedState.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/ConversationNotStartedState.kt index e92071d08e6..9d1fa195ade 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/ConversationNotStartedState.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/ConversationNotStartedState.kt @@ -3,9 +3,15 @@ package software.aws.toolkits.jetbrains.services.amazonqFeatureDev.session +import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.CancellationTokenSource + class ConversationNotStartedState( override var approach: String, override val tabID: String, + override var token: CancellationTokenSource?, + override var codeGenerationRemainingIterationCount: Int?, + override var codeGenerationTotalIterationCount: Int?, + override var currentIteration: Int?, ) : SessionState { override val phase = SessionStatePhase.INIT diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/PrepareCodeGenerationState.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/PrepareCodeGenerationState.kt index fb985b54418..5a397919ac5 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/PrepareCodeGenerationState.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/PrepareCodeGenerationState.kt @@ -9,6 +9,7 @@ import software.aws.toolkits.jetbrains.services.amazonq.messages.MessagePublishe import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.FEATURE_NAME import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.messages.sendAnswerPart import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.messages.sendUpdatePlaceholder +import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.CancellationTokenSource import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.deleteUploadArtifact import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.uploadArtifactToS3 import software.aws.toolkits.jetbrains.services.cwc.controller.chat.telemetry.getStartUrl @@ -16,21 +17,23 @@ import software.aws.toolkits.resources.message import software.aws.toolkits.telemetry.AmazonqTelemetry import software.aws.toolkits.telemetry.AmazonqUploadIntent import software.aws.toolkits.telemetry.Result +import java.util.UUID private val logger = getLogger() class PrepareCodeGenerationState( override var tabID: String, + override var token: CancellationTokenSource?, override var approach: String, private var config: SessionStateConfig, val filePaths: List, val deletedFiles: List, val references: List, var uploadId: String, - private val currentIteration: Int, + override var currentIteration: Int?, private var messenger: MessagePublisher, - var codeGenerationRemainingIterationCount: Int? = null, - var codeGenerationTotalIterationCount: Int? = null, + override var codeGenerationRemainingIterationCount: Int? = null, + override var codeGenerationTotalIterationCount: Int? = null, ) : SessionState { override val phase = SessionStatePhase.CODEGEN override suspend fun interact(action: SessionStateAction): SessionStateInteraction { @@ -49,16 +52,18 @@ class PrepareCodeGenerationState( zipFileLength = repoZipResult.contentLength val fileToUpload = repoZipResult.payload + val uploadId = UUID.randomUUID() val uploadUrlResponse = config.featureDevService.createUploadUrl( config.conversationId, zipFileChecksum, - zipFileLength + zipFileLength, + uploadId.toString() ) uploadArtifactToS3(uploadUrlResponse.uploadUrl(), fileToUpload, zipFileChecksum, zipFileLength, uploadUrlResponse.kmsKeyArn()) deleteUploadArtifact(fileToUpload) - this.uploadId = uploadUrlResponse.uploadId() + this.uploadId = uploadId.toString() messenger.sendAnswerPart(tabId = this.tabID, message = message("amazonqFeatureDev.placeholder.context_gathering_complete")) messenger.sendUpdatePlaceholder(tabId = this.tabID, newPlaceholder = message("amazonqFeatureDev.placeholder.context_gathering_complete")) nextState = CodeGenerationState( @@ -68,7 +73,8 @@ class PrepareCodeGenerationState( uploadId = this.uploadId, currentIteration = this.currentIteration, repositorySize = zipFileLength.toDouble(), - messenger = messenger + messenger = messenger, + token = this.token ) } catch (e: Exception) { result = Result.Failed diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/Session.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/Session.kt index bd47ab962b8..f02fc86609e 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/Session.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/Session.kt @@ -14,6 +14,7 @@ import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.FEATURE_NAME import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.MAX_PROJECT_SIZE_BYTES import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.clients.FeatureDevClient import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.messages.sendAsyncEventProgress +import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.CancellationTokenSource import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.FeatureDevService import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.resolveAndCreateOrUpdateFile import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.resolveAndDeleteFile @@ -41,7 +42,7 @@ class Session(val tabID: String, val project: Project) { context = FeatureDevSessionContext(project, MAX_PROJECT_SIZE_BYTES) proxyClient = FeatureDevClient.getInstance(project) featureDevService = FeatureDevService(proxyClient, project) - _state = ConversationNotStartedState("", tabID) + _state = ConversationNotStartedState("", tabID, null, 0, CODE_GENERATION_RETRY_LIMIT, 0) isAuthenticating = false codegenRetries = CODE_GENERATION_RETRY_LIMIT } @@ -78,9 +79,10 @@ class Session(val tabID: String, val project: Project) { filePaths = emptyList(), deletedFiles = emptyList(), references = emptyList(), - currentIteration = 0, // first code gen iteration + currentIteration = 1, // first code gen iteration uploadId = "", // There is no code gen uploadId so far messenger = messenger, + token = CancellationTokenSource() ) } @@ -114,6 +116,7 @@ class Session(val tabID: String, val project: Project) { var action = SessionStateAction( task = task, msg = msg, + token = sessionState.token ) val resp = sessionState.interact(action) if (resp.nextState != null) { diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/SessionState.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/SessionState.kt index 7cfe34aaa19..cc98e0f0b95 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/SessionState.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/SessionState.kt @@ -3,9 +3,15 @@ package software.aws.toolkits.jetbrains.services.amazonqFeatureDev.session +import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.CancellationTokenSource + interface SessionState { val tabID: String val phase: SessionStatePhase? + var token: CancellationTokenSource? + var codeGenerationRemainingIterationCount: Int? + var codeGenerationTotalIterationCount: Int? + var currentIteration: Int? var approach: String suspend fun interact(action: SessionStateAction): SessionStateInteraction } diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/SessionStateTypes.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/SessionStateTypes.kt index 6cbe35ed6f0..33ee8cb7e4b 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/SessionStateTypes.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/SessionStateTypes.kt @@ -5,12 +5,14 @@ package software.aws.toolkits.jetbrains.services.amazonqFeatureDev.session import com.fasterxml.jackson.annotation.JsonValue import software.aws.toolkits.jetbrains.services.amazonq.FeatureDevSessionContext +import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.CancellationTokenSource import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.FeatureDevService import software.aws.toolkits.jetbrains.services.cwc.messages.RecommendationContentSpan data class SessionStateAction( val task: String, val msg: String, + val token: CancellationTokenSource? = null, ) data class Interaction( diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/util/CancellationTokenSource.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/util/CancellationTokenSource.kt new file mode 100644 index 00000000000..ff05dc3c12e --- /dev/null +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/util/CancellationTokenSource.kt @@ -0,0 +1,24 @@ +// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util + +class CancellationToken { + private var isCancelled = false + + fun isCancellationRequested(): Boolean = isCancelled + + internal fun cancel() { + isCancelled = true + } +} + +class CancellationTokenSource { + private val _token = CancellationToken() + val token: CancellationToken + get() = _token + + fun cancel() { + _token.cancel() + } +} diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/util/FeatureDevService.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/util/FeatureDevService.kt index 59a7750201f..7f5676162c8 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/util/FeatureDevService.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/util/FeatureDevService.kt @@ -82,17 +82,18 @@ class FeatureDevService(val proxyClient: FeatureDevClient, val project: Project) } } - fun createUploadUrl(conversationId: String, contentChecksumSha256: String, contentLength: Long): + fun createUploadUrl(conversationId: String, contentChecksumSha256: String, contentLength: Long, uploadId: String): CreateUploadUrlResponse { try { logger.debug { "Executing createUploadUrl with conversationId $conversationId" } val uploadUrlResponse = proxyClient.createTaskAssistUploadUrl( conversationId, contentChecksumSha256, - contentLength + contentLength, + uploadId ) logger.debug { - "$FEATURE_NAME: Created upload url: {uploadId: ${uploadUrlResponse.uploadId()}, requestId: ${uploadUrlResponse.responseMetadata().requestId()}}" + "$FEATURE_NAME: Created upload url: {uploadId: $uploadId, requestId: ${uploadUrlResponse.responseMetadata().requestId()}}" } return uploadUrlResponse } catch (e: Exception) { @@ -111,14 +112,16 @@ class FeatureDevService(val proxyClient: FeatureDevClient, val project: Project) } } - fun startTaskAssistCodeGeneration(conversationId: String, uploadId: String, message: String): + fun startTaskAssistCodeGeneration(conversationId: String, uploadId: String, message: String, codeGenerationId: String?, currentCodeGenerationId: String?): StartTaskAssistCodeGenerationResponse { try { logger.debug { "Executing startTaskAssistCodeGeneration with conversationId: $conversationId , uploadId: $uploadId" } val startCodeGenerationResponse = proxyClient.startTaskAssistCodeGeneration( conversationId, uploadId, - message + message, + codeGenerationId, + currentCodeGenerationId ?: "EMPTY_CURRENT_CODE_GENERATION_ID" ) logger.debug { "$FEATURE_NAME: Started code generation with requestId: ${startCodeGenerationResponse.responseMetadata().requestId()}" } diff --git a/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/FeatureDevTestBase.kt b/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/FeatureDevTestBase.kt index 951b859a784..6c1a2fb6389 100644 --- a/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/FeatureDevTestBase.kt +++ b/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/FeatureDevTestBase.kt @@ -59,9 +59,9 @@ open class FeatureDevTestBase( internal val testRequestId = "test_aws_request_id" internal val testConversationId = "1234" internal val userMessage = "test-user-message" + internal val codeGenerationId = "1234" internal val testUploadId = "5678" internal val testRepositorySize = 20.0 // Picked a random size - internal val testCodeGenerationId = "1234" internal val otherStatus = "Other" internal val testTabId = "test-tab-id" internal val testFilePaths = mapOf(Pair("test.ts", "This is a comment")) @@ -70,53 +70,89 @@ open class FeatureDevTestBase( internal val testChecksumSha = "test-sha" internal val testContentLength: Long = 40 - internal val exampleSendTelemetryEventResponse = SendTelemetryEventResponse.builder() - .responseMetadata(DefaultAwsResponseMetadata.create(mapOf(AwsHeader.AWS_REQUEST_ID to testRequestId))) - .build() as SendTelemetryEventResponse - - internal val exampleCreateTaskAssistConversationResponse = CreateTaskAssistConversationResponse.builder() - .conversationId(testConversationId) - .responseMetadata(DefaultAwsResponseMetadata.create(mapOf(AwsHeader.AWS_REQUEST_ID to testRequestId))) - .build() as CreateTaskAssistConversationResponse - - internal val exampleCreateUploadUrlResponse = CreateUploadUrlResponse.builder() - .uploadUrl("https://smth.com") - .uploadId(testUploadId) - .kmsKeyArn("0000000000000000000000000000000000:key/1234abcd") - .responseMetadata(DefaultAwsResponseMetadata.create(mapOf(AwsHeader.AWS_REQUEST_ID to testRequestId))) - .build() as CreateUploadUrlResponse - - internal val exampleStartTaskAssistConversationResponse = StartTaskAssistCodeGenerationResponse.builder() - .conversationId(testConversationId) - .codeGenerationId(testCodeGenerationId) - .responseMetadata(DefaultAwsResponseMetadata.create(mapOf(AwsHeader.AWS_REQUEST_ID to testRequestId))) - .build() as StartTaskAssistCodeGenerationResponse - - internal val exampleGetTaskAssistConversationResponse = GetTaskAssistCodeGenerationResponse.builder() - .conversationId(testConversationId) - .codeGenerationStatus(CodeGenerationStatus.builder().status(CodeGenerationWorkflowStatus.IN_PROGRESS).currentStage("InProgress").build()) - .responseMetadata(DefaultAwsResponseMetadata.create(mapOf(AwsHeader.AWS_REQUEST_ID to testRequestId))) - .build() as GetTaskAssistCodeGenerationResponse - - internal val exampleCompleteGetTaskAssistCodeGenerationResponse = GetTaskAssistCodeGenerationResponse.builder() - .conversationId(testConversationId) - .codeGenerationStatus(CodeGenerationStatus.builder().status(CodeGenerationWorkflowStatus.COMPLETE).currentStage("Complete").build()) - .codeGenerationRemainingIterationCount(2) - .codeGenerationTotalIterationCount(3) - .responseMetadata(DefaultAwsResponseMetadata.create(mapOf(AwsHeader.AWS_REQUEST_ID to testRequestId))) - .build() as GetTaskAssistCodeGenerationResponse - - internal val exampleFailedGetTaskAssistCodeGenerationResponse = GetTaskAssistCodeGenerationResponse.builder() - .conversationId(testConversationId) - .codeGenerationStatus(CodeGenerationStatus.builder().status(CodeGenerationWorkflowStatus.FAILED).currentStage("Failed").build()) - .responseMetadata(DefaultAwsResponseMetadata.create(mapOf(AwsHeader.AWS_REQUEST_ID to testRequestId))) - .build() as GetTaskAssistCodeGenerationResponse - - internal val exampleOtherGetTaskAssistCodeGenerationResponse = GetTaskAssistCodeGenerationResponse.builder() - .conversationId(testConversationId) - .codeGenerationStatus(CodeGenerationStatus.builder().status(CodeGenerationWorkflowStatus.UNKNOWN_TO_SDK_VERSION).currentStage(otherStatus).build()) - .responseMetadata(DefaultAwsResponseMetadata.create(mapOf(AwsHeader.AWS_REQUEST_ID to testRequestId))) - .build() as GetTaskAssistCodeGenerationResponse + internal val exampleSendTelemetryEventResponse = + SendTelemetryEventResponse + .builder() + .responseMetadata(DefaultAwsResponseMetadata.create(mapOf(AwsHeader.AWS_REQUEST_ID to testRequestId))) + .build() as SendTelemetryEventResponse + + internal val exampleCreateTaskAssistConversationResponse = + CreateTaskAssistConversationResponse + .builder() + .conversationId(testConversationId) + .responseMetadata(DefaultAwsResponseMetadata.create(mapOf(AwsHeader.AWS_REQUEST_ID to testRequestId))) + .build() as CreateTaskAssistConversationResponse + + internal val exampleCreateUploadUrlResponse = + CreateUploadUrlResponse + .builder() + .uploadUrl("https://smth.com") + .uploadId(testUploadId) + .kmsKeyArn("0000000000000000000000000000000000:key/1234abcd") + .responseMetadata(DefaultAwsResponseMetadata.create(mapOf(AwsHeader.AWS_REQUEST_ID to testRequestId))) + .build() as CreateUploadUrlResponse + + internal val exampleStartTaskAssistConversationResponse = + StartTaskAssistCodeGenerationResponse + .builder() + .conversationId(testConversationId) + .codeGenerationId(codeGenerationId) + .responseMetadata(DefaultAwsResponseMetadata.create(mapOf(AwsHeader.AWS_REQUEST_ID to testRequestId))) + .build() as StartTaskAssistCodeGenerationResponse + + internal val exampleGetTaskAssistConversationResponse = + GetTaskAssistCodeGenerationResponse + .builder() + .conversationId(testConversationId) + .codeGenerationStatus( + CodeGenerationStatus + .builder() + .status(CodeGenerationWorkflowStatus.IN_PROGRESS) + .currentStage("InProgress") + .build(), + ).responseMetadata(DefaultAwsResponseMetadata.create(mapOf(AwsHeader.AWS_REQUEST_ID to testRequestId))) + .build() as GetTaskAssistCodeGenerationResponse + + internal val exampleCompleteGetTaskAssistCodeGenerationResponse = + GetTaskAssistCodeGenerationResponse + .builder() + .conversationId(testConversationId) + .codeGenerationStatus( + CodeGenerationStatus + .builder() + .status(CodeGenerationWorkflowStatus.COMPLETE) + .currentStage("Complete") + .build(), + ).codeGenerationRemainingIterationCount(2) + .codeGenerationTotalIterationCount(3) + .responseMetadata(DefaultAwsResponseMetadata.create(mapOf(AwsHeader.AWS_REQUEST_ID to testRequestId))) + .build() as GetTaskAssistCodeGenerationResponse + + internal val exampleFailedGetTaskAssistCodeGenerationResponse = + GetTaskAssistCodeGenerationResponse + .builder() + .conversationId(testConversationId) + .codeGenerationStatus( + CodeGenerationStatus + .builder() + .status(CodeGenerationWorkflowStatus.FAILED) + .currentStage("Failed") + .build(), + ).responseMetadata(DefaultAwsResponseMetadata.create(mapOf(AwsHeader.AWS_REQUEST_ID to testRequestId))) + .build() as GetTaskAssistCodeGenerationResponse + + internal val exampleOtherGetTaskAssistCodeGenerationResponse = + GetTaskAssistCodeGenerationResponse + .builder() + .conversationId(testConversationId) + .codeGenerationStatus( + CodeGenerationStatus + .builder() + .status(CodeGenerationWorkflowStatus.UNKNOWN_TO_SDK_VERSION) + .currentStage(otherStatus) + .build(), + ).responseMetadata(DefaultAwsResponseMetadata.create(mapOf(AwsHeader.AWS_REQUEST_ID to testRequestId))) + .build() as GetTaskAssistCodeGenerationResponse internal val exampleExportResultArchiveResponse = mutableListOf(byteArrayOf(100)) @@ -127,18 +163,22 @@ open class FeatureDevTestBase( project = projectRule.project toolkitConnectionManager = spy(ToolkitConnectionManager.getInstance(project)) val accessToken = DeviceAuthorizationGrantToken(aString(), aString(), aString(), aString(), Instant.MAX, Instant.now()) - val provider = mock { - doReturn(accessToken).whenever(it).refresh() - } - val mockBearerProvider = mock { - doReturn(provider).whenever(it).delegate - } - val connectionSettingsMock = mock { - whenever(it.tokenProvider).thenReturn(mockBearerProvider) - } - val toolkitConnection = mock { - doReturn(connectionSettingsMock).whenever(it).getConnectionSettings() - } + val provider = + mock { + doReturn(accessToken).whenever(it).refresh() + } + val mockBearerProvider = + mock { + doReturn(provider).whenever(it).delegate + } + val connectionSettingsMock = + mock { + whenever(it.tokenProvider).thenReturn(mockBearerProvider) + } + val toolkitConnection = + mock { + doReturn(connectionSettingsMock).whenever(it).getConnectionSettings() + } doReturn(toolkitConnection).whenever(toolkitConnectionManager).activeConnectionForFeature(any()) project.replaceService(ToolkitConnectionManager::class.java, toolkitConnectionManager, disposableRule.disposable) clientAdaptorSpy = spy(FeatureDevClient.getInstance(project)) diff --git a/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/clients/FeatureDevClientTest.kt b/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/clients/FeatureDevClientTest.kt index 4c7b6c7d82c..5d789caa0d3 100644 --- a/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/clients/FeatureDevClientTest.kt +++ b/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/clients/FeatureDevClientTest.kt @@ -44,6 +44,7 @@ import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnectionManager import software.aws.toolkits.jetbrains.services.amazonq.clients.AmazonQStreamingClient import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.FeatureDevTestBase import software.aws.toolkits.jetbrains.settings.AwsSettings +import java.util.UUID import java.util.concurrent.CompletableFuture class FeatureDevClientTest : FeatureDevTestBase() { @@ -124,7 +125,7 @@ class FeatureDevClientTest : FeatureDevTestBase() { fun `check createTaskAssistUploadUrl`() { val testContentLength: Long = 42 - val actual = featureDevClient.createTaskAssistUploadUrl(testConversationId, "test-sha", testContentLength) + val actual = featureDevClient.createTaskAssistUploadUrl(testConversationId, "test-sha", testContentLength, "uploadId") argumentCaptor().apply { verify(bearerClient).createUploadUrl(capture()) @@ -137,7 +138,14 @@ class FeatureDevClientTest : FeatureDevTestBase() { @Test fun `check startTaskAssistCodeGeneration`() { - val actual = featureDevClient.startTaskAssistCodeGeneration(testConversationId, "test-upload-id", "test-user-message") + val actual = featureDevClient.startTaskAssistCodeGeneration( + testConversationId, + "test-upload-id", + "test-user-message", + currentCodeGenerationId = UUID.randomUUID() + .toString(), + codeGenerationId = codeGenerationId + ) argumentCaptor().apply { verify(bearerClient).startTaskAssistCodeGeneration(capture()) diff --git a/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/controller/FeatureDevControllerTest.kt b/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/controller/FeatureDevControllerTest.kt index d6072bce336..8992baaa5f1 100644 --- a/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/controller/FeatureDevControllerTest.kt +++ b/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/controller/FeatureDevControllerTest.kt @@ -10,6 +10,7 @@ import io.mockk.coVerify import io.mockk.coVerifyOrder import io.mockk.every import io.mockk.just +import io.mockk.mockk import io.mockk.mockkObject import io.mockk.mockkStatic import io.mockk.runs @@ -29,6 +30,7 @@ import org.mockito.kotlin.reset import org.mockito.kotlin.spy import org.mockito.kotlin.times import org.mockito.kotlin.whenever +import software.aws.toolkits.jetbrains.services.amazonq.FeatureDevSessionContext import software.aws.toolkits.jetbrains.services.amazonq.apps.AmazonQAppInitContext import software.aws.toolkits.jetbrains.services.amazonq.auth.AuthController import software.aws.toolkits.jetbrains.services.amazonq.auth.AuthNeededStates @@ -52,8 +54,11 @@ import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.session.Intera import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.session.NewFileZipInfo import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.session.PrepareCodeGenerationState import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.session.Session +import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.session.SessionStateConfig import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.session.SessionStatePhase import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.storage.ChatSessionStorage +import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.CancellationTokenSource +import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.FeatureDevService import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.getFollowUpOptions import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.selectFolder import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.uploadArtifactToS3 @@ -74,26 +79,30 @@ class FeatureDevControllerTest : FeatureDevTestBase() { private lateinit var spySession: Session private lateinit var featureDevClient: FeatureDevClient - private val newFileContents = listOf( - NewFileZipInfo("test.ts", "This is a comment", false), - NewFileZipInfo("test2.ts", "This is a rejected file", true) - ) - private val deletedFiles = listOf( - DeletedFileInfo("delete.ts", false), - DeletedFileInfo("delete2.ts", true) - ) + private val newFileContents = + listOf( + NewFileZipInfo("test.ts", "This is a comment", false), + NewFileZipInfo("test2.ts", "This is a rejected file", true), + ) + private val deletedFiles = + listOf( + DeletedFileInfo("delete.ts", false), + DeletedFileInfo("delete2.ts", true), + ) @Before override fun setup() { super.setup() + featureDevClient = mock() messenger = mock() chatSessionStorage = mock() projectRule.project.replaceService(FeatureDevClient::class.java, featureDevClient, disposableRule.disposable) - appContext = mock { - on { project }.thenReturn(project) - on { messagesFromAppToUi }.thenReturn(messenger) - } + appContext = + mock { + on { project }.thenReturn(project) + on { messagesFromAppToUi }.thenReturn(messenger) + } authController = spy(AuthController()) doReturn(AuthNeededStates()).`when`(authController).getAuthNeededStates(any()) spySession = spy(Session(testTabId, project)) @@ -104,7 +113,7 @@ class FeatureDevControllerTest : FeatureDevTestBase() { MessagePublisher::sendUpdatePlaceholder, MessagePublisher::sendChatInputEnabledMessage, MessagePublisher::sendCodeResult, - MessagePublisher::updateFileComponent + MessagePublisher::updateFileComponent, ) mockkStatic("software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.UploadArtifactKt") @@ -162,294 +171,360 @@ class FeatureDevControllerTest : FeatureDevTestBase() { } verify( - exactly = 1 + exactly = 1, ) { AmazonqTelemetry.endChat(amazonqConversationId = testConversationId, amazonqEndOfTheConversationLatency = any(), createTime = any()) } } @Test - fun `test provideFeedbackAndRegenerateCode`() = runTest { - val followUp = FollowUp(FollowUpTypes.PROVIDE_FEEDBACK_AND_REGENERATE_CODE, pillText = "Regenerate code") - val message = IncomingFeatureDevMessage.FollowupClicked(followUp, testTabId, "", "test-command") + fun `test provideFeedbackAndRegenerateCode`() = + runTest { + val followUp = FollowUp(FollowUpTypes.PROVIDE_FEEDBACK_AND_REGENERATE_CODE, pillText = "Regenerate code") + val message = IncomingFeatureDevMessage.FollowupClicked(followUp, testTabId, "", "test-command") - whenever(featureDevClient.createTaskAssistConversation()).thenReturn(exampleCreateTaskAssistConversationResponse) - whenever(featureDevClient.sendFeatureDevTelemetryEvent(any())).thenReturn(exampleSendTelemetryEventResponse) - whenever(chatSessionStorage.getSession(any(), any())).thenReturn(spySession) + whenever(featureDevClient.createTaskAssistConversation()).thenReturn(exampleCreateTaskAssistConversationResponse) + whenever(featureDevClient.sendFeatureDevTelemetryEvent(any())).thenReturn(exampleSendTelemetryEventResponse) + whenever(chatSessionStorage.getSession(any(), any())).thenReturn(spySession) - mockkObject(AmazonqTelemetry) - every { AmazonqTelemetry.isProvideFeedbackForCodeGen(amazonqConversationId = any(), enabled = any()) } just runs + mockkObject(AmazonqTelemetry) + every { AmazonqTelemetry.isProvideFeedbackForCodeGen(amazonqConversationId = any(), enabled = any()) } just runs - spySession.preloader(userMessage, messenger) - controller.processFollowupClickedMessage(message) + spySession.preloader(userMessage, messenger) + controller.processFollowupClickedMessage(message) - coVerifyOrder { - AmazonqTelemetry.isProvideFeedbackForCodeGen(amazonqConversationId = testConversationId, enabled = true, createTime = any()) - messenger.sendAsyncEventProgress(testTabId, inProgress = false) - messenger.sendAnswer( - tabId = testTabId, - message = message("amazonqFeatureDev.code_generation.provide_code_feedback"), - messageType = FeatureDevMessageType.Answer, - canBeVoted = true - ) - messenger.sendUpdatePlaceholder(testTabId, message("amazonqFeatureDev.placeholder.provide_code_feedback")) + coVerifyOrder { + AmazonqTelemetry.isProvideFeedbackForCodeGen(amazonqConversationId = testConversationId, enabled = true, createTime = any()) + messenger.sendAsyncEventProgress(testTabId, inProgress = false) + messenger.sendAnswer( + tabId = testTabId, + message = message("amazonqFeatureDev.code_generation.provide_code_feedback"), + messageType = FeatureDevMessageType.Answer, + canBeVoted = true, + ) + messenger.sendUpdatePlaceholder(testTabId, message("amazonqFeatureDev.placeholder.provide_code_feedback")) + } } - } @Test - fun `test insertCode`() = runTest { - val followUp = FollowUp(FollowUpTypes.INSERT_CODE, pillText = "Insert code") - val message = IncomingFeatureDevMessage.FollowupClicked(followUp, testTabId, "", "test-command") - - mockkObject(AmazonqTelemetry) - every { - AmazonqTelemetry.isAcceptedCodeChanges(amazonqNumberOfFilesAccepted = any(), amazonqConversationId = any(), enabled = any()) - } just runs - - whenever(featureDevClient.createTaskAssistConversation()).thenReturn(exampleCreateTaskAssistConversationResponse) - whenever(featureDevClient.sendFeatureDevTelemetryEvent(any())).thenReturn(exampleSendTelemetryEventResponse) - whenever(chatSessionStorage.getSession(any(), any())).thenReturn(spySession) - whenever(spySession.sessionState).thenReturn( - PrepareCodeGenerationState( - testTabId, "", mock(), newFileContents, deletedFiles, testReferences, testUploadId, 0, messenger + fun `test insertCode`() = + runTest { + val followUp = FollowUp(FollowUpTypes.INSERT_CODE, pillText = "Insert code") + val message = IncomingFeatureDevMessage.FollowupClicked(followUp, testTabId, "", "test-command") + + var featureDevService = mockk() + val repoContext = mock() + val sessionStateConfig = SessionStateConfig(testConversationId, repoContext, featureDevService) + mockkObject(AmazonqTelemetry) + every { + AmazonqTelemetry.isAcceptedCodeChanges(amazonqNumberOfFilesAccepted = any(), amazonqConversationId = any(), enabled = any()) + } just runs + + whenever(featureDevClient.createTaskAssistConversation()).thenReturn(exampleCreateTaskAssistConversationResponse) + whenever(featureDevClient.sendFeatureDevTelemetryEvent(any())).thenReturn(exampleSendTelemetryEventResponse) + whenever(chatSessionStorage.getSession(any(), any())).thenReturn(spySession) + whenever(spySession.sessionState).thenReturn( + PrepareCodeGenerationState( + testTabId, + CancellationTokenSource(), + "test-command", + sessionStateConfig, + newFileContents, + deletedFiles, + testReferences, + testUploadId, + 0, + messenger, + 0, + 0, + ), ) - ) - doNothing().`when`(spySession).insertChanges(any(), any(), any()) - spySession.preloader(userMessage, messenger) - controller.processFollowupClickedMessage(message) + doNothing().`when`(spySession).insertChanges(any(), any(), any()) - mockitoVerify( - spySession, - times(1) - ).insertChanges(listOf(newFileContents[0]), listOf(deletedFiles[0]), testReferences) // insert changes for only non rejected files - coVerifyOrder { - AmazonqTelemetry.isAcceptedCodeChanges( - amazonqNumberOfFilesAccepted = 2.0, // it should be 2 files per test setup - amazonqConversationId = spySession.conversationId, - enabled = true, - createTime = any() - ) - messenger.sendAnswer( - tabId = testTabId, - message = message("amazonqFeatureDev.code_generation.updated_code"), - messageType = FeatureDevMessageType.Answer, - canBeVoted = true - ) - messenger.sendSystemPrompt( - testTabId, - listOf( - FollowUp(FollowUpTypes.NEW_TASK, message("amazonqFeatureDev.follow_up.new_task"), status = FollowUpStatusType.Info), - FollowUp(FollowUpTypes.CLOSE_SESSION, message("amazonqFeatureDev.follow_up.close_session"), status = FollowUpStatusType.Info) + spySession.preloader(userMessage, messenger) + controller.processFollowupClickedMessage(message) + + mockitoVerify( + spySession, + times(1), + ).insertChanges(listOf(newFileContents[0]), listOf(deletedFiles[0]), testReferences) // insert changes for only non rejected files + coVerifyOrder { + AmazonqTelemetry.isAcceptedCodeChanges( + amazonqNumberOfFilesAccepted = 2.0, // it should be 2 files per test setup + amazonqConversationId = spySession.conversationId, + enabled = true, + createTime = any(), ) - ) - messenger.sendUpdatePlaceholder(testTabId, message("amazonqFeatureDev.placeholder.additional_improvements")) + messenger.sendAnswer( + tabId = testTabId, + message = message("amazonqFeatureDev.code_generation.updated_code"), + messageType = FeatureDevMessageType.Answer, + canBeVoted = true, + ) + messenger.sendSystemPrompt( + testTabId, + listOf( + FollowUp(FollowUpTypes.NEW_TASK, message("amazonqFeatureDev.follow_up.new_task"), status = FollowUpStatusType.Info), + FollowUp(FollowUpTypes.CLOSE_SESSION, message("amazonqFeatureDev.follow_up.close_session"), status = FollowUpStatusType.Info), + ), + ) + messenger.sendUpdatePlaceholder(testTabId, message("amazonqFeatureDev.placeholder.additional_improvements")) + } } - } @Test - fun `test handleChat onCodeGeneration succeeds to create files`() = runTest { - val mockInteraction = mock() - - val mockSession = mock() - whenever(mockSession.send(userMessage)).thenReturn(mockInteraction) - whenever(mockSession.conversationId).thenReturn(testConversationId) - whenever(mockSession.sessionState).thenReturn( - PrepareCodeGenerationState( - testTabId, "", mock(), newFileContents, deletedFiles, testReferences, testUploadId, 0, messenger + fun `test handleChat onCodeGeneration succeeds to create files`() = + runTest { + val mockInteraction = mock() + var featureDevService = mockk() + val repoContext = mock() + val sessionStateConfig = SessionStateConfig(testConversationId, repoContext, featureDevService) + mockkObject(AmazonqTelemetry) + val mockSession = mock() + whenever(mockSession.send(userMessage)).thenReturn(mockInteraction) + whenever(mockSession.conversationId).thenReturn(testConversationId) + whenever(mockSession.sessionState).thenReturn( + PrepareCodeGenerationState( + testTabId, + CancellationTokenSource(), + "test-command", + sessionStateConfig, + newFileContents, + deletedFiles, + testReferences, + testUploadId, + 0, + messenger, + ), ) - ) - - controller.onCodeGeneration(mockSession, userMessage, testTabId) - coVerifyOrder { - messenger.sendAsyncEventProgress(testTabId, true, message("amazonqFeatureDev.chat_message.start_code_generation_retry")) - messenger.sendAnswer(testTabId, message("amazonqFeatureDev.chat_message.requesting_changes"), FeatureDevMessageType.AnswerStream) - messenger.sendUpdatePlaceholder(testTabId, message("amazonqFeatureDev.placeholder.generating_code")) - messenger.sendCodeResult(testTabId, testUploadId, newFileContents, deletedFiles, testReferences) - messenger.sendSystemPrompt(testTabId, getFollowUpOptions(SessionStatePhase.CODEGEN)) - messenger.sendUpdatePlaceholder(testTabId, message("amazonqFeatureDev.placeholder.after_code_generation")) - messenger.sendAsyncEventProgress(testTabId, false) - messenger.sendChatInputEnabledMessage(testTabId, false) + controller.onCodeGeneration(mockSession, userMessage, testTabId) + + coVerifyOrder { + messenger.sendAsyncEventProgress(testTabId, true, message("amazonqFeatureDev.chat_message.start_code_generation_retry")) + messenger.sendAnswer(testTabId, message("amazonqFeatureDev.chat_message.requesting_changes"), FeatureDevMessageType.AnswerStream) + messenger.sendUpdatePlaceholder(testTabId, message("amazonqFeatureDev.placeholder.generating_code")) + messenger.sendCodeResult(testTabId, testUploadId, newFileContents, deletedFiles, testReferences) + messenger.sendSystemPrompt(testTabId, getFollowUpOptions(SessionStatePhase.CODEGEN)) + messenger.sendUpdatePlaceholder(testTabId, message("amazonqFeatureDev.placeholder.after_code_generation")) + messenger.sendAsyncEventProgress(testTabId, false) + messenger.sendChatInputEnabledMessage(testTabId, false) + } } - } @Test(expected = RuntimeException::class) - fun `test handleChat onCodeGeneration throws error when sending message to state`() = runTest { - val mockSession = mock() + fun `test handleChat onCodeGeneration throws error when sending message to state`() = + runTest { + val mockSession = mock() - whenever(mockSession.send(userMessage)).thenThrow(RuntimeException()) - whenever(mockSession.conversationId).thenReturn(testConversationId) + whenever(mockSession.send(userMessage)).thenThrow(RuntimeException()) + whenever(mockSession.conversationId).thenReturn(testConversationId) - controller.onCodeGeneration(mockSession, userMessage, testTabId) + controller.onCodeGeneration(mockSession, userMessage, testTabId) - coVerifyOrder { - messenger.sendAsyncEventProgress(testTabId, true, message("amazonqFeatureDev.chat_message.start_code_generation")) - messenger.sendAnswer(testTabId, message("amazonqFeatureDev.chat_message.requesting_changes"), FeatureDevMessageType.AnswerStream) - messenger.sendUpdatePlaceholder(testTabId, message("amazonqFeatureDev.placeholder.generating_code")) - messenger.sendAsyncEventProgress(testTabId, false) - messenger.sendChatInputEnabledMessage(testTabId, false) + coVerifyOrder { + messenger.sendAsyncEventProgress(testTabId, true, message("amazonqFeatureDev.chat_message.start_code_generation")) + messenger.sendAnswer(testTabId, message("amazonqFeatureDev.chat_message.requesting_changes"), FeatureDevMessageType.AnswerStream) + messenger.sendUpdatePlaceholder(testTabId, message("amazonqFeatureDev.placeholder.generating_code")) + messenger.sendAsyncEventProgress(testTabId, false) + messenger.sendChatInputEnabledMessage(testTabId, false) + } } - } @Test - fun `test handleChat onCodeGeneration doesn't return any files with retries`() = runTest { - val filePaths = emptyList() - val deletedFiles = emptyList() - - val mockInteraction = mock() - - val mockSession = mock() - whenever(mockSession.send(userMessage)).thenReturn(mockInteraction) - whenever(mockSession.conversationId).thenReturn(testConversationId) - whenever(mockSession.sessionState).thenReturn( - PrepareCodeGenerationState( - testTabId, "", mock(), filePaths, deletedFiles, testReferences, testUploadId, 0, messenger + fun `test handleChat onCodeGeneration doesn't return any files with retries`() = + runTest { + val filePaths = emptyList() + val deletedFiles = emptyList() + + val mockInteraction = mock() + + val mockSession = mock() + whenever(mockSession.send(userMessage)).thenReturn(mockInteraction) + whenever(mockSession.conversationId).thenReturn(testConversationId) + whenever(mockSession.sessionState).thenReturn( + PrepareCodeGenerationState( + testTabId, + CancellationTokenSource(), + "", + mock(), + filePaths, + deletedFiles, + testReferences, + testUploadId, + 0, + messenger, + ), ) - ) - whenever(mockSession.retries).thenReturn(3) + whenever(mockSession.retries).thenReturn(3) - controller.onCodeGeneration(mockSession, userMessage, testTabId) + controller.onCodeGeneration(mockSession, userMessage, testTabId) - coVerifyOrder { - messenger.sendAnswer(testTabId, message("amazonqFeatureDev.code_generation.no_file_changes"), FeatureDevMessageType.Answer) - messenger.sendSystemPrompt( - testTabId, - listOf(FollowUp(FollowUpTypes.RETRY, message("amazonqFeatureDev.follow_up.retry"), status = FollowUpStatusType.Warning)) - ) - messenger.sendChatInputEnabledMessage(testTabId, false) + coVerifyOrder { + messenger.sendAnswer(testTabId, message("amazonqFeatureDev.code_generation.no_file_changes"), FeatureDevMessageType.Answer) + messenger.sendSystemPrompt( + testTabId, + listOf(FollowUp(FollowUpTypes.RETRY, message("amazonqFeatureDev.follow_up.retry"), status = FollowUpStatusType.Warning)), + ) + messenger.sendChatInputEnabledMessage(testTabId, false) + } } - } @Test - fun `test handleChat onCodeGeneration doesn't return any files no retries`() = runTest { - val filePaths = emptyList() - val deletedFiles = emptyList() - - val mockInteraction = mock() - - val mockSession = mock() - whenever(mockSession.send(userMessage)).thenReturn(mockInteraction) - whenever(mockSession.conversationId).thenReturn(testConversationId) - whenever(mockSession.sessionState).thenReturn( - PrepareCodeGenerationState( - testTabId, "", mock(), filePaths, deletedFiles, testReferences, testUploadId, 0, messenger + fun `test handleChat onCodeGeneration doesn't return any files no retries`() = + runTest { + val filePaths = emptyList() + val deletedFiles = emptyList() + + val mockInteraction = mock() + + val mockSession = mock() + whenever(mockSession.send(userMessage)).thenReturn(mockInteraction) + whenever(mockSession.conversationId).thenReturn(testConversationId) + whenever(mockSession.sessionState).thenReturn( + PrepareCodeGenerationState( + testTabId, + CancellationTokenSource(), + "", + mock(), + filePaths, + deletedFiles, + testReferences, + testUploadId, + 0, + messenger, + ), ) - ) - whenever(mockSession.retries).thenReturn(0) + whenever(mockSession.retries).thenReturn(0) - controller.onCodeGeneration(mockSession, userMessage, testTabId) + controller.onCodeGeneration(mockSession, userMessage, testTabId) - coVerifyOrder { - messenger.sendAnswer(testTabId, message("amazonqFeatureDev.code_generation.no_file_changes"), FeatureDevMessageType.Answer) - messenger.sendSystemPrompt(testTabId, emptyList()) - messenger.sendChatInputEnabledMessage(testTabId, false) + coVerifyOrder { + messenger.sendAnswer(testTabId, message("amazonqFeatureDev.code_generation.no_file_changes"), FeatureDevMessageType.Answer) + messenger.sendSystemPrompt(testTabId, emptyList()) + messenger.sendChatInputEnabledMessage(testTabId, false) + } } - } @Test - fun `test processFileClicked changes the state of the clicked file`() = runTest { - val message = IncomingFeatureDevMessage.FileClicked(testTabId, newFileContents[0].zipFilePath, "", "") - - whenever(featureDevClient.createTaskAssistConversation()).thenReturn(exampleCreateTaskAssistConversationResponse) - whenever(chatSessionStorage.getSession(any(), any())).thenReturn(spySession) - whenever(spySession.sessionState).thenReturn( - PrepareCodeGenerationState( - testTabId, "", mock(), newFileContents, deletedFiles, testReferences, testUploadId, 0, messenger + fun `test processFileClicked changes the state of the clicked file`() = + runTest { + val message = IncomingFeatureDevMessage.FileClicked(testTabId, newFileContents[0].zipFilePath, "", "") + + whenever(featureDevClient.createTaskAssistConversation()).thenReturn(exampleCreateTaskAssistConversationResponse) + whenever(chatSessionStorage.getSession(any(), any())).thenReturn(spySession) + whenever(spySession.sessionState).thenReturn( + PrepareCodeGenerationState( + testTabId, + CancellationTokenSource(), + "", + mock(), + newFileContents, + deletedFiles, + testReferences, + testUploadId, + 0, + messenger, + ), ) - ) - controller.processFileClicked(message) + controller.processFileClicked(message) - val newFileContentsCopy = newFileContents.toList() - newFileContentsCopy[0].rejected = !newFileContentsCopy[0].rejected - coVerify { messenger.updateFileComponent(testTabId, newFileContentsCopy, deletedFiles, "") } - } + val newFileContentsCopy = newFileContents.toList() + newFileContentsCopy[0].rejected = !newFileContentsCopy[0].rejected + coVerify { messenger.updateFileComponent(testTabId, newFileContentsCopy, deletedFiles, "") } + } @Test - fun `test modifyDefaultSourceFolder customer does not select a folder`() = runTest { - val followUp = FollowUp(FollowUpTypes.MODIFY_DEFAULT_SOURCE_FOLDER, pillText = "Modify default source folder") - val message = IncomingFeatureDevMessage.FollowupClicked(followUp, testTabId, "", "test-command") + fun `test modifyDefaultSourceFolder customer does not select a folder`() = + runTest { + val followUp = FollowUp(FollowUpTypes.MODIFY_DEFAULT_SOURCE_FOLDER, pillText = "Modify default source folder") + val message = IncomingFeatureDevMessage.FollowupClicked(followUp, testTabId, "", "test-command") - whenever(featureDevClient.createTaskAssistConversation()).thenReturn(exampleCreateTaskAssistConversationResponse) - whenever(featureDevClient.sendFeatureDevTelemetryEvent(any())).thenReturn(exampleSendTelemetryEventResponse) - whenever(chatSessionStorage.getSession(any(), any())).thenReturn(spySession) + whenever(featureDevClient.createTaskAssistConversation()).thenReturn(exampleCreateTaskAssistConversationResponse) + whenever(featureDevClient.sendFeatureDevTelemetryEvent(any())).thenReturn(exampleSendTelemetryEventResponse) + whenever(chatSessionStorage.getSession(any(), any())).thenReturn(spySession) - mockkStatic("software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.FileUtilsKt") - every { selectFolder(any(), any()) } returns null + mockkStatic("software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.FileUtilsKt") + every { selectFolder(any(), any()) } returns null - spySession.preloader(userMessage, messenger) - controller.processFollowupClickedMessage(message) + spySession.preloader(userMessage, messenger) + controller.processFollowupClickedMessage(message) - coVerifyOrder { - messenger.sendSystemPrompt( - tabId = testTabId, - followUp = listOf( - FollowUp( - pillText = message("amazonqFeatureDev.follow_up.modify_source_folder"), - type = FollowUpTypes.MODIFY_DEFAULT_SOURCE_FOLDER, - status = FollowUpStatusType.Info, - ) + coVerifyOrder { + messenger.sendSystemPrompt( + tabId = testTabId, + followUp = + listOf( + FollowUp( + pillText = message("amazonqFeatureDev.follow_up.modify_source_folder"), + type = FollowUpTypes.MODIFY_DEFAULT_SOURCE_FOLDER, + status = FollowUpStatusType.Info, + ), + ), ) - ) + } } - } @Test - fun `test modifyDefaultSourceFolder customer selects a folder outside the workspace`() = runTest { - val followUp = FollowUp(FollowUpTypes.MODIFY_DEFAULT_SOURCE_FOLDER, pillText = "Modify default source folder") - val message = IncomingFeatureDevMessage.FollowupClicked(followUp, testTabId, "", "test-command") + fun `test modifyDefaultSourceFolder customer selects a folder outside the workspace`() = + runTest { + val followUp = FollowUp(FollowUpTypes.MODIFY_DEFAULT_SOURCE_FOLDER, pillText = "Modify default source folder") + val message = IncomingFeatureDevMessage.FollowupClicked(followUp, testTabId, "", "test-command") - whenever(featureDevClient.createTaskAssistConversation()).thenReturn(exampleCreateTaskAssistConversationResponse) - whenever(featureDevClient.sendFeatureDevTelemetryEvent(any())).thenReturn(exampleSendTelemetryEventResponse) - whenever(chatSessionStorage.getSession(any(), any())).thenReturn(spySession) + whenever(featureDevClient.createTaskAssistConversation()).thenReturn(exampleCreateTaskAssistConversationResponse) + whenever(featureDevClient.sendFeatureDevTelemetryEvent(any())).thenReturn(exampleSendTelemetryEventResponse) + whenever(chatSessionStorage.getSession(any(), any())).thenReturn(spySession) - mockkStatic("software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.FileUtilsKt") - every { selectFolder(any(), any()) } returns LightVirtualFile("/path") + mockkStatic("software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.FileUtilsKt") + every { selectFolder(any(), any()) } returns LightVirtualFile("/path") - spySession.preloader(userMessage, messenger) - controller.processFollowupClickedMessage(message) + spySession.preloader(userMessage, messenger) + controller.processFollowupClickedMessage(message) - coVerifyOrder { - messenger.sendAnswer( - tabId = testTabId, - messageType = FeatureDevMessageType.Answer, - message = message("amazonqFeatureDev.follow_up.incorrect_source_folder") - ) - messenger.sendSystemPrompt( - tabId = testTabId, - followUp = listOf( - FollowUp( - pillText = message("amazonqFeatureDev.follow_up.modify_source_folder"), - type = FollowUpTypes.MODIFY_DEFAULT_SOURCE_FOLDER, - status = FollowUpStatusType.Info, - ) + coVerifyOrder { + messenger.sendAnswer( + tabId = testTabId, + messageType = FeatureDevMessageType.Answer, + message = message("amazonqFeatureDev.follow_up.incorrect_source_folder"), ) - ) + messenger.sendSystemPrompt( + tabId = testTabId, + followUp = + listOf( + FollowUp( + pillText = message("amazonqFeatureDev.follow_up.modify_source_folder"), + type = FollowUpTypes.MODIFY_DEFAULT_SOURCE_FOLDER, + status = FollowUpStatusType.Info, + ), + ), + ) + } } - } @Test - fun `test modifyDefaultSourceFolder customer selects a correct sub folder`() = runTest { - val followUp = FollowUp(FollowUpTypes.MODIFY_DEFAULT_SOURCE_FOLDER, pillText = "Modify default source folder") - val message = IncomingFeatureDevMessage.FollowupClicked(followUp, testTabId, "", "test-command") + fun `test modifyDefaultSourceFolder customer selects a correct sub folder`() = + runTest { + val followUp = FollowUp(FollowUpTypes.MODIFY_DEFAULT_SOURCE_FOLDER, pillText = "Modify default source folder") + val message = IncomingFeatureDevMessage.FollowupClicked(followUp, testTabId, "", "test-command") - whenever(featureDevClient.createTaskAssistConversation()).thenReturn(exampleCreateTaskAssistConversationResponse) - whenever(featureDevClient.sendFeatureDevTelemetryEvent(any())).thenReturn(exampleSendTelemetryEventResponse) - whenever(chatSessionStorage.getSession(any(), any())).thenReturn(spySession) + whenever(featureDevClient.createTaskAssistConversation()).thenReturn(exampleCreateTaskAssistConversationResponse) + whenever(featureDevClient.sendFeatureDevTelemetryEvent(any())).thenReturn(exampleSendTelemetryEventResponse) + whenever(chatSessionStorage.getSession(any(), any())).thenReturn(spySession) - val folder = LightVirtualFile("${spySession.context.projectRoot.name}/path/to/sub/folder") - mockkStatic("software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.FileUtilsKt") - every { selectFolder(any(), any()) } returns folder + val folder = LightVirtualFile("${spySession.context.projectRoot.name}/path/to/sub/folder") + mockkStatic("software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.FileUtilsKt") + every { selectFolder(any(), any()) } returns folder - spySession.preloader(userMessage, messenger) - controller.processFollowupClickedMessage(message) + spySession.preloader(userMessage, messenger) + controller.processFollowupClickedMessage(message) - coVerify { - messenger.sendAnswer( - tabId = testTabId, - messageType = FeatureDevMessageType.Answer, - message = message("amazonqFeatureDev.follow_up.modified_source_folder", folder.path), - canBeVoted = true, - ) + coVerify { + messenger.sendAnswer( + tabId = testTabId, + messageType = FeatureDevMessageType.Answer, + message = message("amazonqFeatureDev.follow_up.modified_source_folder", folder.path), + canBeVoted = true, + ) + } } - } } diff --git a/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/CodeGenerationStateTest.kt b/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/CodeGenerationStateTest.kt index a1d25f7944a..f52fd7c685c 100644 --- a/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/CodeGenerationStateTest.kt +++ b/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/CodeGenerationStateTest.kt @@ -48,15 +48,18 @@ class CodeGenerationStateTest : FeatureDevTestBase() { val repoContext = mock() val sessionStateConfig = SessionStateConfig(testConversationId, repoContext, featureDevService) - codeGenerationState = CodeGenerationState( - testTabId, - "", - sessionStateConfig, - testUploadId, - 0, - testRepositorySize, - messenger - ) + codeGenerationState = + CodeGenerationState( + testTabId, + "", + sessionStateConfig, + testUploadId, + 0, + testRepositorySize, + messenger, + token = null, + currentCodeGenerationId = "EMPTY_CURRENT_CODE_GENERATION_ID", + ) mockkStatic(MessagePublisher::sendAnswerPart) coEvery { messenger.sendAnswerPart(any(), any()) } just runs @@ -71,7 +74,7 @@ class CodeGenerationStateTest : FeatureDevTestBase() { fun `test code generated is complete`() { val action = SessionStateAction("test-task", userMessage) every { featureDevService.getTaskAssistCodeGeneration(any(), any()) } returns exampleCompleteGetTaskAssistCodeGenerationResponse - every { featureDevService.startTaskAssistCodeGeneration(any(), any(), any()) } returns exampleStartTaskAssistConversationResponse + every { featureDevService.startTaskAssistCodeGeneration(any(), any(), any(), any(), any()) } returns exampleStartTaskAssistConversationResponse coEvery { featureDevService.exportTaskAssistArchiveResult(any()) } returns CodeGenerationStreamResult(testFilePaths, testDeletedFiles, testReferences) @@ -79,13 +82,12 @@ class CodeGenerationStateTest : FeatureDevTestBase() { val actual = codeGenerationState.interact(action) assertThat(actual.nextState).isInstanceOf(PrepareCodeGenerationState::class.java) val nextState = actual.nextState as PrepareCodeGenerationState - assertThat(nextState.uploadId).isEqualTo(testUploadId) assertThat(nextState.phase).isEqualTo(SessionStatePhase.CODEGEN) assertThat(nextState.filePaths).isEqualTo( - listOf(NewFileZipInfo("test.ts", "This is a comment", false)) + listOf(NewFileZipInfo("test.ts", "This is a comment", false)), ) assertThat(nextState.deletedFiles).isEqualTo( - listOf(DeletedFileInfo("deleted.ts", false)) + listOf(DeletedFileInfo("deleted.ts", false)), ) assertThat(nextState.references).isEqualTo(testReferences) assertThat(nextState.codeGenerationRemainingIterationCount).isEqualTo(2) @@ -95,26 +97,26 @@ class CodeGenerationStateTest : FeatureDevTestBase() { } assertThat(codeGenerationState.phase).isEqualTo(SessionStatePhase.CODEGEN) coVerify(exactly = 1) { messenger.sendAnswerPart(testTabId, message("amazonqFeatureDev.code_generation.generating_code")) } - verify(exactly = 1) { featureDevService.startTaskAssistCodeGeneration(testConversationId, testUploadId, userMessage) } - verify(exactly = 1) { featureDevService.getTaskAssistCodeGeneration(testConversationId, testCodeGenerationId) } + + verify(exactly = 1) { featureDevService.getTaskAssistCodeGeneration(testConversationId, codeGenerationId) } coVerify(exactly = 1) { featureDevService.exportTaskAssistArchiveResult(testConversationId) } } @Test(expected = FeatureDevException::class) - fun `test code generation failed`() = runTest { - every { featureDevService.startTaskAssistCodeGeneration(any(), any(), any()) } returns exampleStartTaskAssistConversationResponse - every { featureDevService.getTaskAssistCodeGeneration(any(), any()) } returns exampleFailedGetTaskAssistCodeGenerationResponse + fun `test code generation failed`() = + runTest { + every { featureDevService.startTaskAssistCodeGeneration(any(), any(), any(), any(), any()) } returns exampleStartTaskAssistConversationResponse + every { featureDevService.getTaskAssistCodeGeneration(any(), any()) } returns exampleFailedGetTaskAssistCodeGenerationResponse - codeGenerationState.interact(action) + codeGenerationState.interact(action) - verify(exactly = 1) { featureDevService.startTaskAssistCodeGeneration(testConversationId, testUploadId, userMessage) } - verify(exactly = 1) { featureDevService.getTaskAssistCodeGeneration(testConversationId, testCodeGenerationId) } - coVerify(exactly = 0) { featureDevService.exportTaskAssistArchiveResult(any()) } - } + verify(exactly = 1) { featureDevService.getTaskAssistCodeGeneration(testConversationId, codeGenerationId) } + coVerify(exactly = 0) { featureDevService.exportTaskAssistArchiveResult(any()) } + } @Test fun `test code generation returns any other handled status`() { - every { featureDevService.startTaskAssistCodeGeneration(any(), any(), any()) } returns exampleStartTaskAssistConversationResponse + every { featureDevService.startTaskAssistCodeGeneration(any(), any(), any(), any(), any()) } returns exampleStartTaskAssistConversationResponse every { featureDevService.getTaskAssistCodeGeneration(any(), any()) } returns exampleOtherGetTaskAssistCodeGenerationResponse assertThatThrownBy { @@ -123,14 +125,13 @@ class CodeGenerationStateTest : FeatureDevTestBase() { } }.isExactlyInstanceOf(IllegalStateException::class.java).withFailMessage("Unknown status: $otherStatus") - verify(exactly = 1) { featureDevService.startTaskAssistCodeGeneration(testConversationId, testUploadId, userMessage) } - verify(exactly = 1) { featureDevService.getTaskAssistCodeGeneration(testConversationId, testCodeGenerationId) } + verify(exactly = 1) { featureDevService.getTaskAssistCodeGeneration(testConversationId, codeGenerationId) } coVerify(exactly = 0) { featureDevService.exportTaskAssistArchiveResult(any()) } } @Test fun `test code generation returns in progress at least once`() { - every { featureDevService.startTaskAssistCodeGeneration(any(), any(), any()) } returns exampleStartTaskAssistConversationResponse + every { featureDevService.startTaskAssistCodeGeneration(any(), any(), any(), any(), any()) } returns exampleStartTaskAssistConversationResponse every { featureDevService.getTaskAssistCodeGeneration(any(), any()) } returnsMany listOf(exampleGetTaskAssistConversationResponse, exampleCompleteGetTaskAssistCodeGenerationResponse) @@ -140,14 +141,13 @@ class CodeGenerationStateTest : FeatureDevTestBase() { codeGenerationState.interact(action) } - verify(exactly = 1) { featureDevService.startTaskAssistCodeGeneration(testConversationId, testUploadId, userMessage) } - verify(exactly = 2) { featureDevService.getTaskAssistCodeGeneration(testConversationId, testCodeGenerationId) } + verify(exactly = 2) { featureDevService.getTaskAssistCodeGeneration(testConversationId, codeGenerationId) } coVerify(exactly = 1) { featureDevService.exportTaskAssistArchiveResult(testConversationId) } } @Test fun `test using all polling count`() { - every { featureDevService.startTaskAssistCodeGeneration(any(), any(), any()) } returns exampleStartTaskAssistConversationResponse + every { featureDevService.startTaskAssistCodeGeneration(any(), any(), any(), any(), any()) } returns exampleStartTaskAssistConversationResponse every { featureDevService.getTaskAssistCodeGeneration(any(), any()) } returns exampleGetTaskAssistConversationResponse runTest { @@ -163,8 +163,7 @@ class CodeGenerationStateTest : FeatureDevTestBase() { assertThat(actual.interaction.content).isEqualTo("") } - verify(exactly = 1) { featureDevService.startTaskAssistCodeGeneration(testConversationId, testUploadId, userMessage) } - verify(exactly = 180) { featureDevService.getTaskAssistCodeGeneration(testConversationId, testCodeGenerationId) } + verify(exactly = 180) { featureDevService.getTaskAssistCodeGeneration(testConversationId, codeGenerationId) } coVerify(exactly = 0) { featureDevService.exportTaskAssistArchiveResult(testConversationId) } } } diff --git a/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/PrepareCodeGenerationStateTest.kt b/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/PrepareCodeGenerationStateTest.kt index 28cfa33e483..49aa4d906e3 100644 --- a/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/PrepareCodeGenerationStateTest.kt +++ b/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/session/PrepareCodeGenerationStateTest.kt @@ -26,6 +26,7 @@ import software.aws.toolkits.jetbrains.services.amazonq.ZipCreationResult import software.aws.toolkits.jetbrains.services.amazonq.messages.MessagePublisher import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.FeatureDevTestBase import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.messages.sendAnswerPart +import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.CancellationTokenSource import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.FeatureDevService import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.deleteUploadArtifact import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.uploadArtifactToS3 @@ -49,9 +50,11 @@ class PrepareCodeGenerationStateTest : FeatureDevTestBase() { every { featureDevService.project } returns projectRule.project messenger = mock() sessionStateConfig = SessionStateConfig(testConversationId, repoContext, featureDevService) + prepareCodeGenerationState = PrepareCodeGenerationState( "", - "tabId", + CancellationTokenSource(), + "test-approach", sessionStateConfig, emptyList(), emptyList(), @@ -66,7 +69,7 @@ class PrepareCodeGenerationStateTest : FeatureDevTestBase() { every { deleteUploadArtifact(any()) } just runs every { featureDevService.getTaskAssistCodeGeneration(any(), any()) } returns exampleCompleteGetTaskAssistCodeGenerationResponse - every { featureDevService.startTaskAssistCodeGeneration(any(), any(), any()) } returns exampleStartTaskAssistConversationResponse + every { featureDevService.startTaskAssistCodeGeneration(any(), any(), any(), any(), any()) } returns exampleStartTaskAssistConversationResponse coEvery { featureDevService.exportTaskAssistArchiveResult(any()) } returns exampleExportTaskAssistResultArchiveResponse mockkStatic(MessagePublisher::sendAnswerPart) @@ -85,15 +88,13 @@ class PrepareCodeGenerationStateTest : FeatureDevTestBase() { val action = SessionStateAction("test-task", userMessage) whenever(repoContext.getProjectZip()).thenReturn(repoZipResult) - every { featureDevService.createUploadUrl(any(), any(), any()) } returns exampleCreateUploadUrlResponse + every { featureDevService.createUploadUrl(any(), any(), any(), any()) } returns exampleCreateUploadUrlResponse runTest { val actual = prepareCodeGenerationState.interact(action) assertThat(actual.nextState).isInstanceOf(PrepareCodeGenerationState::class.java) - assertThat((actual.nextState as PrepareCodeGenerationState).uploadId).isEqualTo(testUploadId) } assertThat(prepareCodeGenerationState.phase).isEqualTo(SessionStatePhase.CODEGEN) verify(repoContext, times(1)).getProjectZip() - io.mockk.verify(exactly = 1) { featureDevService.createUploadUrl(testConversationId, testChecksumSha, testContentLength) } } } diff --git a/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/util/FeatureDevServiceTest.kt b/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/util/FeatureDevServiceTest.kt index 419258a350a..e30259bf2b7 100644 --- a/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/util/FeatureDevServiceTest.kt +++ b/plugins/amazonq/chat/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/amazonqFeatureDev/util/FeatureDevServiceTest.kt @@ -64,134 +64,229 @@ class FeatureDevServiceTest : FeatureDevTestBase() { @Test fun `test createUploadUrl`() { - whenever(featureDevClient.createTaskAssistUploadUrl(testConversationId, testChecksumSha, testContentLength)).thenReturn(exampleCreateUploadUrlResponse) + whenever( + featureDevClient.createTaskAssistUploadUrl(testConversationId, testChecksumSha, testContentLength, uploadId = testUploadId), + ).thenReturn(exampleCreateUploadUrlResponse) - val actual = featureDevService.createUploadUrl(testConversationId, testChecksumSha, testContentLength) + val actual = featureDevService.createUploadUrl(testConversationId, testChecksumSha, testContentLength, uploadId = testUploadId) assertThat(actual).isInstanceOf(CreateUploadUrlResponse::class.java) - assertThat(actual).usingRecursiveComparison().comparingOnlyFields("uploadUrl", "uploadId", "kmsKeyArn") + assertThat(actual) + .usingRecursiveComparison() + .comparingOnlyFields("uploadUrl", "uploadId", "kmsKeyArn") .isEqualTo(exampleCreateUploadUrlResponse) } @Test fun `test createUploadUrl with error`() { - whenever(featureDevClient.createTaskAssistUploadUrl(testConversationId, testChecksumSha, testContentLength)).thenThrow(RuntimeException()) + whenever( + featureDevClient.createTaskAssistUploadUrl(testConversationId, testChecksumSha, testContentLength, uploadId = testUploadId), + ).thenThrow(RuntimeException()) assertThatThrownBy { - featureDevService.createUploadUrl(testConversationId, testChecksumSha, testContentLength) + featureDevService.createUploadUrl(testConversationId, testChecksumSha, testContentLength, uploadId = testUploadId) }.isInstanceOf(FeatureDevException::class.java) } @Test fun `test createUploadUrl with validation error`() { - whenever(featureDevClient.createTaskAssistUploadUrl(testConversationId, testChecksumSha, testContentLength)).thenThrow( - ValidationException.builder() + whenever( + featureDevClient.createTaskAssistUploadUrl(testConversationId, testChecksumSha, testContentLength, uploadId = testUploadId), + ).thenThrow( + ValidationException + .builder() .requestId(testRequestId) .message("Invalid contentLength") .awsErrorDetails(AwsErrorDetails.builder().errorMessage("Invalid contentLength").build()) - .build() + .build(), ) assertThatThrownBy { - featureDevService.createUploadUrl(testConversationId, testChecksumSha, testContentLength) + featureDevService.createUploadUrl(testConversationId, testChecksumSha, testContentLength, uploadId = testUploadId) }.isInstanceOf(ContentLengthException::class.java).hasMessage(message("amazonqFeatureDev.content_length.error_text")) } @Test fun `test getTaskAssistCodeGeneration success`() { - whenever(featureDevClient.getTaskAssistCodeGeneration(testConversationId, testCodeGenerationId)).thenReturn(exampleGetTaskAssistConversationResponse) + whenever( + featureDevClient.getTaskAssistCodeGeneration(testConversationId, codeGenerationId.toString()), + ).thenReturn(exampleGetTaskAssistConversationResponse) - val actual = featureDevService.getTaskAssistCodeGeneration(testConversationId, testCodeGenerationId) + val actual = featureDevService.getTaskAssistCodeGeneration(testConversationId, codeGenerationId.toString()) assertThat(actual).isEqualTo(exampleGetTaskAssistConversationResponse) } @Test fun `test getTaskAssistCodeGeneration throws a CodeWhispererRuntimeException`() { - val exampleCWException = CodeWhispererRuntimeException.builder().awsErrorDetails( - AwsErrorDetails.builder().errorMessage(cwExceptionMsg).build() - ).build() - whenever(featureDevClient.getTaskAssistCodeGeneration(testConversationId, testCodeGenerationId)).thenThrow(exampleCWException) + val exampleCWException = + CodeWhispererRuntimeException + .builder() + .awsErrorDetails( + AwsErrorDetails.builder().errorMessage(cwExceptionMsg).build(), + ).build() + whenever(featureDevClient.getTaskAssistCodeGeneration(testConversationId, codeGenerationId.toString())).thenThrow(exampleCWException) assertThatThrownBy { - featureDevService.getTaskAssistCodeGeneration(testConversationId, testCodeGenerationId) + featureDevService.getTaskAssistCodeGeneration(testConversationId, codeGenerationId.toString()) }.isExactlyInstanceOf(FeatureDevException::class.java).withFailMessage(cwExceptionMsg) } @Test fun `test getTaskAssistCodeGeneration throws another Exception`() { val exampleOtherException = RuntimeException(otherExceptionMsg) - whenever(featureDevClient.getTaskAssistCodeGeneration(testConversationId, testCodeGenerationId)).thenThrow(exampleOtherException) + whenever(featureDevClient.getTaskAssistCodeGeneration(testConversationId, codeGenerationId.toString())).thenThrow(exampleOtherException) assertThatThrownBy { - featureDevService.getTaskAssistCodeGeneration(testConversationId, testCodeGenerationId) + featureDevService.getTaskAssistCodeGeneration(testConversationId, codeGenerationId.toString()) }.isExactlyInstanceOf(FeatureDevException::class.java).withFailMessage(otherExceptionMsg) } @Test fun `test startTaskAssistConversation success`() { whenever( - featureDevClient.startTaskAssistCodeGeneration(testConversationId, testUploadId, userMessage) + featureDevClient.startTaskAssistCodeGeneration( + testConversationId, + testUploadId, + userMessage, + codeGenerationId = codeGenerationId, + currentCodeGenerationId = "EMPTY_CURRENT_CODE_GENERATION_ID", + ), ).thenReturn(exampleStartTaskAssistConversationResponse) - val actual = featureDevService.startTaskAssistCodeGeneration(testConversationId, testUploadId, userMessage) + val actual = + featureDevService.startTaskAssistCodeGeneration( + testConversationId, + testUploadId, + userMessage, + codeGenerationId = codeGenerationId, + currentCodeGenerationId = "EMPTY_CURRENT_CODE_GENERATION_ID", + ) assertThat(actual).isEqualTo(exampleStartTaskAssistConversationResponse) } @Test fun `test startTaskAssistConversation throws ThrottlingException`() { - val exampleCWException = ThrottlingException.builder().awsErrorDetails( - AwsErrorDetails.builder().errorMessage("limit for number of iterations on a code generation").build() - ).build() - whenever(featureDevClient.startTaskAssistCodeGeneration(testConversationId, testUploadId, userMessage)).thenThrow(exampleCWException) + val exampleCWException = + ThrottlingException + .builder() + .awsErrorDetails( + AwsErrorDetails.builder().errorMessage("limit for number of iterations on a code generation").build(), + ).build() + whenever( + featureDevClient.startTaskAssistCodeGeneration( + testConversationId, + testUploadId, + userMessage, + codeGenerationId = codeGenerationId, + currentCodeGenerationId = "EMPTY_CURRENT_CODE_GENERATION_ID", + ), + ).thenThrow(exampleCWException) assertThatThrownBy { - featureDevService.startTaskAssistCodeGeneration(testConversationId, testUploadId, userMessage) + featureDevService.startTaskAssistCodeGeneration( + testConversationId, + testUploadId, + userMessage, + codeGenerationId = codeGenerationId, + currentCodeGenerationId = "EMPTY_CURRENT_CODE_GENERATION_ID", + ) }.isExactlyInstanceOf(CodeIterationLimitException::class.java).withFailMessage( - message("amazonqFeatureDev.code_generation.iteration_limit.error_text") + message("amazonqFeatureDev.code_generation.iteration_limit.error_text"), ) } @Test fun `test startTaskAssistConversation throws ServiceQuotaExceededException`() { - val exampleCWException = ServiceQuotaExceededException.builder().awsErrorDetails( - AwsErrorDetails.builder().errorMessage("service quota exceeded").build() - ).build() - whenever(featureDevClient.startTaskAssistCodeGeneration(testConversationId, testUploadId, userMessage)).thenThrow(exampleCWException) + val exampleCWException = + ServiceQuotaExceededException + .builder() + .awsErrorDetails( + AwsErrorDetails.builder().errorMessage("service quota exceeded").build(), + ).build() + whenever( + featureDevClient.startTaskAssistCodeGeneration( + testConversationId, + testUploadId, + userMessage, + codeGenerationId = codeGenerationId, + currentCodeGenerationId = "EMPTY_CURRENT_CODE_GENERATION_ID", + ), + ).thenThrow(exampleCWException) assertThatThrownBy { - featureDevService.startTaskAssistCodeGeneration(testConversationId, testUploadId, userMessage) + featureDevService.startTaskAssistCodeGeneration( + testConversationId, + testUploadId, + userMessage, + codeGenerationId = codeGenerationId, + currentCodeGenerationId = "EMPTY_CURRENT_CODE_GENERATION_ID", + ) }.isExactlyInstanceOf(CodeIterationLimitException::class.java).withFailMessage( - message("amazonqFeatureDev.code_generation.iteration_limit.error_text") + message("amazonqFeatureDev.code_generation.iteration_limit.error_text"), ) } @Test fun `test startTaskAssistConversation throws another CodeWhispererRuntimeException`() { - val exampleCWException = CodeWhispererRuntimeException.builder().awsErrorDetails( - AwsErrorDetails.builder().errorMessage(cwExceptionMsg).build() - ).build() - whenever(featureDevClient.startTaskAssistCodeGeneration(testConversationId, testUploadId, userMessage)).thenThrow(exampleCWException) + val exampleCWException = + CodeWhispererRuntimeException + .builder() + .awsErrorDetails( + AwsErrorDetails.builder().errorMessage(cwExceptionMsg).build(), + ).build() + whenever( + featureDevClient.startTaskAssistCodeGeneration( + testConversationId, + testUploadId, + userMessage, + codeGenerationId = codeGenerationId, + currentCodeGenerationId = "EMPTY_CURRENT_CODE_GENERATION_ID", + ), + ).thenThrow(exampleCWException) assertThatThrownBy { - featureDevService.startTaskAssistCodeGeneration(testConversationId, testUploadId, userMessage) + featureDevService.startTaskAssistCodeGeneration( + testConversationId, + testUploadId, + userMessage, + codeGenerationId = codeGenerationId, + currentCodeGenerationId = "EMPTY_CURRENT_CODE_GENERATION_ID", + ) }.isExactlyInstanceOf(FeatureDevException::class.java).withFailMessage(cwExceptionMsg) } @Test fun `test startTaskAssistConversation throws any other exception`() { val exampleOtherException = RuntimeException(otherExceptionMsg) - whenever(featureDevClient.startTaskAssistCodeGeneration(testConversationId, testUploadId, userMessage)).thenThrow(exampleOtherException) + whenever( + featureDevClient.startTaskAssistCodeGeneration( + testConversationId, + testUploadId, + userMessage, + codeGenerationId = codeGenerationId, + currentCodeGenerationId = "EMPTY_CURRENT_CODE_GENERATION_ID", + ), + ).thenThrow(exampleOtherException) assertThatThrownBy { - featureDevService.startTaskAssistCodeGeneration(testConversationId, testUploadId, userMessage) + featureDevService.startTaskAssistCodeGeneration( + testConversationId, + testUploadId, + userMessage, + codeGenerationId = codeGenerationId, + currentCodeGenerationId = "EMPTY_CURRENT_CODE_GENERATION_ID", + ) }.isExactlyInstanceOf(FeatureDevException::class.java).withFailMessage(otherExceptionMsg) } @Test fun `test exportTaskAssistArchiveResult throws CodeWhispererStreamingException`() { - val exampleCWException = CodeWhispererRuntimeException.builder().awsErrorDetails( - AwsErrorDetails.builder().errorMessage(cwExceptionMsg).build() - ).build() + val exampleCWException = + CodeWhispererRuntimeException + .builder() + .awsErrorDetails( + AwsErrorDetails.builder().errorMessage(cwExceptionMsg).build(), + ).build() assertThatThrownBy { runTest { diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/BuildStepStatus.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/BuildStepStatus.kt index bae6b078069..8ebf5fd23d8 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/BuildStepStatus.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/BuildStepStatus.kt @@ -15,6 +15,6 @@ enum class BuildStepStatus { fun mapTransformationPlanApiStatus(apiStatus: TransformationProgressUpdateStatus): BuildStepStatus = when (apiStatus) { TransformationProgressUpdateStatus.COMPLETED -> BuildStepStatus.DONE TransformationProgressUpdateStatus.FAILED, TransformationProgressUpdateStatus.PAUSED -> BuildStepStatus.WARNING - TransformationProgressUpdateStatus.IN_PROGRESS -> BuildStepStatus.WORKING + TransformationProgressUpdateStatus.AWAITING_CLIENT_ACTION, TransformationProgressUpdateStatus.IN_PROGRESS -> BuildStepStatus.WORKING TransformationProgressUpdateStatus.UNKNOWN_TO_SDK_VERSION -> BuildStepStatus.ERROR } diff --git a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/apps/featureDevChatConnector.ts b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/apps/featureDevChatConnector.ts index c9b08e6583d..711569f65a9 100644 --- a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/apps/featureDevChatConnector.ts +++ b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/apps/featureDevChatConnector.ts @@ -260,6 +260,7 @@ export class Connector { this.sendMessageToExtension({ tabID: tabID, command: 'stop-response', + tabType: 'featuredev', }) } diff --git a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/followUps/handler.ts b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/followUps/handler.ts index cc215450fee..8234672976c 100644 --- a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/followUps/handler.ts +++ b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/followUps/handler.ts @@ -52,6 +52,7 @@ export class FollowUpInteractionHandler { if (followUp.prompt !== undefined) { this.mynahUI.updateStore(tabID, { loadingChat: true, + cancelButtonWhenLoading: false, promptInputDisabledState: true, }) this.mynahUI.addChatItem(tabID, { diff --git a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/main.ts b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/main.ts index 7f073b4f44e..7bb31fb1fd8 100644 --- a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/main.ts +++ b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/main.ts @@ -130,6 +130,7 @@ export const createMynahUI = (ideApi: any, featureDevInitEnabled: boolean, codeT mynahUI.updateStore(tabID, { loadingChat: true, promptInputDisabledState: true, + cancelButtonWhenLoading: true, }) if (message) { mynahUI.updateLastChatAnswer(tabID, { @@ -199,6 +200,7 @@ export const createMynahUI = (ideApi: any, featureDevInitEnabled: boolean, codeT mynahUI.addChatItem(tabID, chatItem) mynahUI.updateStore(tabID, { + cancelButtonWhenLoading: false, loadingChat: chatItem.type !== ChatItemType.ANSWER, }) @@ -271,6 +273,7 @@ export const createMynahUI = (ideApi: any, featureDevInitEnabled: boolean, codeT ) { mynahUI.updateStore(tabID, { loadingChat: true, + cancelButtonWhenLoading: false, promptInputDisabledState: true, }) @@ -414,6 +417,13 @@ export const createMynahUI = (ideApi: any, featureDevInitEnabled: boolean, codeT }) connector.onTabAdd(tabID) }, + onStopChatResponse: (tabID: string) => { + mynahUI.updateStore(tabID, { + loadingChat: false, + promptInputDisabledState: false, + }) + connector.onStopChatResponse(tabID) + }, onTabRemove: connector.onTabRemove, onTabChange: connector.onTabChange, onChatPrompt: (tabID, prompt, eventId) => { diff --git a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/messages/controller.ts b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/messages/controller.ts index e979c7ea6b5..142f4d40939 100644 --- a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/messages/controller.ts +++ b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/messages/controller.ts @@ -74,6 +74,7 @@ export class MessageController { this.mynahUI.updateStore(selectedTab.id, { loadingChat: true, + cancelButtonWhenLoading: false, promptInputDisabledState: true, }) this.mynahUI.addChatItem(selectedTab.id, message) @@ -104,6 +105,7 @@ export class MessageController { this.mynahUI.updateStore(newTabID, { loadingChat: true, + cancelButtonWhenLoading: false, promptInputDisabledState: true, }) diff --git a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/messages/handler.ts b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/messages/handler.ts index 47164c0a031..92fff3747ba 100644 --- a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/messages/handler.ts +++ b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/messages/handler.ts @@ -35,6 +35,7 @@ export class TextMessageHandler { this.mynahUI.updateStore(tabID, { loadingChat: true, + cancelButtonWhenLoading: false, promptInputDisabledState: true, }) diff --git a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/quickActions/handler.ts b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/quickActions/handler.ts index 9f8947bdb43..426dc0a325e 100644 --- a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/quickActions/handler.ts +++ b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/quickActions/handler.ts @@ -76,7 +76,7 @@ export class QuickActionHandler { // Add new tab let affectedTabId: string | undefined = tabID if (this.tabsStorage.getTab(affectedTabId)?.type !== 'unknown') { - affectedTabId = this.mynahUI.updateStore('', {}) + affectedTabId = this.mynahUI.updateStore('', {cancelButtonWhenLoading: false}) } if (affectedTabId === undefined) { this.mynahUI.notify({ @@ -94,6 +94,7 @@ export class QuickActionHandler { promptInputDisabledState: true, promptInputPlaceholder: 'Open a new tab to chat with Q.', loadingChat: true, + cancelButtonWhenLoading: false, }) this.connector.onTabAdd(affectedTabId) diff --git a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/texts/constants.ts b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/texts/constants.ts index 473ecb53c81..577f6d3f3d8 100644 --- a/plugins/amazonq/mynah-ui/src/mynah-ui/ui/texts/constants.ts +++ b/plugins/amazonq/mynah-ui/src/mynah-ui/ui/texts/constants.ts @@ -19,7 +19,7 @@ export const uiComponentsTexts = { save: 'Save', cancel: 'Cancel', submit: 'Submit', - stopGenerating: 'Stop generating', + stopGenerating: 'Stop', copyToClipboard: 'Copied to clipboard', noMoreTabsTooltip: 'You can only open ten conversation tabs at a time.', codeSuggestionWithReferenceTitle: 'Some suggestions contain code with references.', diff --git a/plugins/core/jetbrains-community/resources/telemetryOverride.json b/plugins/core/jetbrains-community/resources/telemetryOverride.json index e456dad31ef..a2736ca7f64 100644 --- a/plugins/core/jetbrains-community/resources/telemetryOverride.json +++ b/plugins/core/jetbrains-community/resources/telemetryOverride.json @@ -313,6 +313,11 @@ "IAM" ], "description": "Login is with Legacy device code or newer PKCE flow" + }, + { + "name": "tabId", + "type": "string", + "description": "The unique identifier of a tab" } ], "metrics": [ @@ -754,6 +759,60 @@ "type": "authType" } ] + }, + { + "name": "auth_addConnection", + "description": "Captures the result of adding a new connection in the 'Add New Connection' workflow", + "metadata": [ + { + "type": "attempts", + "required": false + }, + { + "type": "credentialSourceId" + }, + { + "type": "featureId", + "required": false + }, + { + "type": "invalidInputFields", + "required": false + }, + { + "type": "isAggregated", + "required": false + }, + { + "type": "reason", + "required": false + }, + { + "type": "result" + }, + { + "type": "source", + "required": false + }, + { + "type": "credentialStartUrl", + "required": false + }, + { + "type": "isReAuth", + "required": false + } + ] + }, + { + "name": "amazonq_stopCodeGeneration", + "description": "User stopped the code generation", + "metadata": [ + { + "type": "tabId", + "required": true + } + ] } ] } diff --git a/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties b/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties index c2c607e2c18..6bb9257b5ee 100644 --- a/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties +++ b/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties @@ -57,6 +57,9 @@ amazonqFeatureDev.code_generation.notification_message=Your code suggestions fro amazonqFeatureDev.code_generation.notification_open_link=Open chat amazonqFeatureDev.code_generation.notification_title=Amazon Q Developer Agent for software development amazonqFeatureDev.code_generation.provide_code_feedback=How can I improve the code for your use case? +amazonqFeatureDev.code_generation.stopped_code_generation=I stopped generating your code. If you want to continue working on this task, provide another description. You have {0} out of {1} code generations left. +amazonqFeatureDev.code_generation.stopped_code_generation_no_iterations=I stopped generating your code. You don't have more iterations left, however, you can start a new session. +amazonqFeatureDev.code_generation.stopping_code_generation=Stopping code generation... amazonqFeatureDev.code_generation.updated_code=Okay, I updated your code files. Would you like to work on another task? amazonqFeatureDev.content_length.error_text=The folder you selected is too large for me to use as context. Please choose a smaller folder to work on. For more information on quotas, see the [Amazon Q Developer documentation](https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/software-dev.html#quotas). amazonqFeatureDev.error_text=Sorry, we encountered a problem when processing your request. @@ -85,7 +88,7 @@ amazonqFeatureDev.follow_up.provide_feedback_and_regenerate=Provide feedback & r amazonqFeatureDev.follow_up.retry=Retry amazonqFeatureDev.follow_up.send_feedback=Send feedback amazonqFeatureDev.no_retries.error_text=I'm sorry, I'm having technical difficulties and can't continue at the moment. Please try again later, and share feedback to help me improve. -amazonqFeatureDev.placeholder.additional_improvements=Choose an option to proceed +amazonqFeatureDev.placeholder.additional_improvements=Describe your task or issue in detail amazonqFeatureDev.placeholder.after_code_generation=Choose an option to proceed amazonqFeatureDev.placeholder.after_monthly_limit=Chat input is disabled amazonqFeatureDev.placeholder.closed_session=Open a new chat tab to continue diff --git a/plugins/core/sdk-codegen/codegen-resources/codewhispererruntime/service-2.json b/plugins/core/sdk-codegen/codegen-resources/codewhispererruntime/service-2.json index 9f99ce52d8a..8c0517e875e 100644 --- a/plugins/core/sdk-codegen/codegen-resources/codewhispererruntime/service-2.json +++ b/plugins/core/sdk-codegen/codegen-resources/codewhispererruntime/service-2.json @@ -1,52 +1,35 @@ { - "version":"2.0", - "metadata":{ - "apiVersion":"2022-11-11", - "endpointPrefix":"amazoncodewhispererservice", - "jsonVersion":"1.0", - "protocol":"json", - "serviceFullName":"Amazon CodeWhisperer", - "serviceId":"CodeWhispererRuntime", - "signatureVersion":"bearer", - "signingName":"amazoncodewhispererservice", - "targetPrefix":"AmazonCodeWhispererService", - "uid":"codewhispererruntime-2022-11-11" + "version": "2.0", + "metadata": { + "apiVersion": "2022-11-11", + "auth": ["smithy.api#httpBearerAuth"], + "endpointPrefix": "amazoncodewhispererservice", + "jsonVersion": "1.0", + "protocol": "json", + "protocols": ["json"], + "serviceFullName": "Amazon CodeWhisperer", + "serviceId": "CodeWhispererRuntime", + "signatureVersion": "bearer", + "signingName": "amazoncodewhispererservice", + "targetPrefix": "AmazonCodeWhispererService", + "uid": "codewhispererruntime-2022-11-11" }, - "operations":{ - "CreateArtifactUploadUrl":{ - "name":"CreateArtifactUploadUrl", - "http":{ - "method":"POST", - "requestUri":"/" - }, - "input":{"shape":"CreateUploadUrlRequest"}, - "output":{"shape":"CreateUploadUrlResponse"}, - "errors":[ - {"shape":"ThrottlingException"}, - {"shape":"InternalServerException"}, - {"shape":"ValidationException"}, - {"shape":"AccessDeniedException"} - ], - "idempotent":true - }, - "CreateUploadUrl":{ - "name":"CreateUploadUrl", - "http":{ - "method":"POST", - "requestUri":"/" + "operations": { + "CreateArtifactUploadUrl": { + "name": "CreateArtifactUploadUrl", + "http": { + "method": "POST", + "requestUri": "/" }, - "input":{"shape":"CreateUploadUrlRequest"}, - "output":{"shape":"CreateUploadUrlResponse"}, - "errors":[ - {"shape":"ThrottlingException"}, - {"shape":"ServiceQuotaExceededException"}, - {"shape":"ConflictException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"InternalServerException"}, - {"shape":"ValidationException"}, - {"shape":"AccessDeniedException"} + "input": { "shape": "CreateUploadUrlRequest" }, + "output": { "shape": "CreateUploadUrlResponse" }, + "errors": [ + { "shape": "ThrottlingException" }, + { "shape": "InternalServerException" }, + { "shape": "ValidationException" }, + { "shape": "AccessDeniedException" } ], - "idempotent":true + "idempotent": true }, "CreateTaskAssistConversation": { "name": "CreateTaskAssistConversation", @@ -54,59 +37,80 @@ "method": "POST", "requestUri": "/" }, - "input": { - "shape": "CreateTaskAssistConversationRequest" + "input": { "shape": "CreateTaskAssistConversationRequest" }, + "output": { "shape": "CreateTaskAssistConversationResponse" }, + "errors": [ + { "shape": "ThrottlingException" }, + { "shape": "ServiceQuotaExceededException" }, + { "shape": "InternalServerException" }, + { "shape": "ValidationException" }, + { "shape": "AccessDeniedException" } + ] + }, + "CreateUploadUrl": { + "name": "CreateUploadUrl", + "http": { + "method": "POST", + "requestUri": "/" }, - "output": { - "shape": "CreateTaskAssistConversationResponse" + "input": { "shape": "CreateUploadUrlRequest" }, + "output": { "shape": "CreateUploadUrlResponse" }, + "errors": [ + { "shape": "ThrottlingException" }, + { "shape": "ConflictException" }, + { "shape": "ServiceQuotaExceededException" }, + { "shape": "ResourceNotFoundException" }, + { "shape": "InternalServerException" }, + { "shape": "ValidationException" }, + { "shape": "AccessDeniedException" } + ], + "idempotent": true + }, + "DeleteTaskAssistConversation": { + "name": "DeleteTaskAssistConversation", + "http": { + "method": "POST", + "requestUri": "/" }, + "input": { "shape": "DeleteTaskAssistConversationRequest" }, + "output": { "shape": "DeleteTaskAssistConversationResponse" }, "errors": [ - { - "shape": "ThrottlingException" - }, - { - "shape": "ServiceQuotaExceededException" - }, - { - "shape": "InternalServerException" - }, - { - "shape": "ValidationException" - }, - { - "shape": "AccessDeniedException" - } + { "shape": "ThrottlingException" }, + { "shape": "ResourceNotFoundException" }, + { "shape": "InternalServerException" }, + { "shape": "ValidationException" }, + { "shape": "AccessDeniedException" } ] }, - "GenerateCompletions":{ - "name":"GenerateCompletions", - "http":{ - "method":"POST", - "requestUri":"/" + "GenerateCompletions": { + "name": "GenerateCompletions", + "http": { + "method": "POST", + "requestUri": "/" }, - "input":{"shape":"GenerateCompletionsRequest"}, - "output":{"shape":"GenerateCompletionsResponse"}, - "errors":[ - {"shape":"ThrottlingException"}, - {"shape":"InternalServerException"}, - {"shape":"ValidationException"}, - {"shape":"AccessDeniedException"} + "input": { "shape": "GenerateCompletionsRequest" }, + "output": { "shape": "GenerateCompletionsResponse" }, + "errors": [ + { "shape": "ThrottlingException" }, + { "shape": "InternalServerException" }, + { "shape": "ValidationException" }, + { "shape": "AccessDeniedException" } ] }, - "GetCodeAnalysis":{ - "name":"GetCodeAnalysis", - "http":{ - "method":"POST", - "requestUri":"/" + "GetCodeAnalysis": { + "name": "GetCodeAnalysis", + "http": { + "method": "POST", + "requestUri": "/" }, - "input":{"shape":"GetCodeAnalysisRequest"}, - "output":{"shape":"GetCodeAnalysisResponse"}, - "errors":[ - {"shape":"ThrottlingException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"InternalServerException"}, - {"shape":"ValidationException"}, - {"shape":"AccessDeniedException"} + "input": { "shape": "GetCodeAnalysisRequest" }, + "output": { "shape": "GetCodeAnalysisResponse" }, + "errors": [ + { "shape": "ThrottlingException" }, + { "shape": "ResourceNotFoundException" }, + { "shape": "InternalServerException" }, + { "shape": "ValidationException" }, + { "shape": "AccessDeniedException" } ] }, "GetTaskAssistCodeGeneration": { @@ -115,268 +119,287 @@ "method": "POST", "requestUri": "/" }, - "input": { - "shape": "GetTaskAssistCodeGenerationRequest" - }, - "output": { - "shape": "GetTaskAssistCodeGenerationResponse" - }, + "input": { "shape": "GetTaskAssistCodeGenerationRequest" }, + "output": { "shape": "GetTaskAssistCodeGenerationResponse" }, "errors": [ - { - "shape": "ThrottlingException" - }, - { - "shape": "ConflictException" - }, - { - "shape": "ResourceNotFoundException" - }, - { - "shape": "InternalServerException" - }, - { - "shape": "ValidationException" - }, - { - "shape": "AccessDeniedException" - } + { "shape": "ThrottlingException" }, + { "shape": "ConflictException" }, + { "shape": "ResourceNotFoundException" }, + { "shape": "InternalServerException" }, + { "shape": "ValidationException" }, + { "shape": "AccessDeniedException" } ] }, - "GetTransformation":{ - "name":"GetTransformation", - "http":{ - "method":"POST", - "requestUri":"/" + "GetTransformation": { + "name": "GetTransformation", + "http": { + "method": "POST", + "requestUri": "/" }, - "input":{"shape":"GetTransformationRequest"}, - "output":{"shape":"GetTransformationResponse"}, - "errors":[ - {"shape":"ThrottlingException"}, - {"shape":"InternalServerException"}, - {"shape":"ValidationException"}, - {"shape":"AccessDeniedException"} + "input": { "shape": "GetTransformationRequest" }, + "output": { "shape": "GetTransformationResponse" }, + "errors": [ + { "shape": "ThrottlingException" }, + { "shape": "ResourceNotFoundException" }, + { "shape": "InternalServerException" }, + { "shape": "ValidationException" }, + { "shape": "AccessDeniedException" } ] }, - "GetTransformationPlan":{ - "name":"GetTransformationPlan", - "http":{ - "method":"POST", - "requestUri":"/" + "GetTransformationPlan": { + "name": "GetTransformationPlan", + "http": { + "method": "POST", + "requestUri": "/" }, - "input":{"shape":"GetTransformationPlanRequest"}, - "output":{"shape":"GetTransformationPlanResponse"}, - "errors":[ - {"shape":"ThrottlingException"}, - {"shape":"InternalServerException"}, - {"shape":"ValidationException"}, - {"shape":"AccessDeniedException"} + "input": { "shape": "GetTransformationPlanRequest" }, + "output": { "shape": "GetTransformationPlanResponse" }, + "errors": [ + { "shape": "ThrottlingException" }, + { "shape": "ResourceNotFoundException" }, + { "shape": "InternalServerException" }, + { "shape": "ValidationException" }, + { "shape": "AccessDeniedException" } ] }, - "ListAvailableCustomizations":{ - "name":"ListAvailableCustomizations", - "http":{ - "method":"POST", - "requestUri":"/" + "ListAvailableCustomizations": { + "name": "ListAvailableCustomizations", + "http": { + "method": "POST", + "requestUri": "/" }, - "input":{"shape":"ListAvailableCustomizationsRequest"}, - "output":{"shape":"ListAvailableCustomizationsResponse"}, - "errors":[ - {"shape":"ThrottlingException"}, - {"shape":"InternalServerException"}, - {"shape":"ValidationException"}, - {"shape":"AccessDeniedException"} + "input": { "shape": "ListAvailableCustomizationsRequest" }, + "output": { "shape": "ListAvailableCustomizationsResponse" }, + "errors": [ + { "shape": "ThrottlingException" }, + { "shape": "InternalServerException" }, + { "shape": "ValidationException" }, + { "shape": "AccessDeniedException" } ] }, - "ListCodeAnalysisFindings":{ - "name":"ListCodeAnalysisFindings", - "http":{ - "method":"POST", - "requestUri":"/" + "ListCodeAnalysisFindings": { + "name": "ListCodeAnalysisFindings", + "http": { + "method": "POST", + "requestUri": "/" }, - "input":{"shape":"ListCodeAnalysisFindingsRequest"}, - "output":{"shape":"ListCodeAnalysisFindingsResponse"}, - "errors":[ - {"shape":"ThrottlingException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"InternalServerException"}, - {"shape":"ValidationException"}, - {"shape":"AccessDeniedException"} + "input": { "shape": "ListCodeAnalysisFindingsRequest" }, + "output": { "shape": "ListCodeAnalysisFindingsResponse" }, + "errors": [ + { "shape": "ThrottlingException" }, + { "shape": "ResourceNotFoundException" }, + { "shape": "InternalServerException" }, + { "shape": "ValidationException" }, + { "shape": "AccessDeniedException" } ] }, - "ListFeatureEvaluations":{ - "name":"ListFeatureEvaluations", - "http":{ - "method":"POST", - "requestUri":"/" + "ListFeatureEvaluations": { + "name": "ListFeatureEvaluations", + "http": { + "method": "POST", + "requestUri": "/" }, - "input":{"shape":"ListFeatureEvaluationsRequest"}, - "output":{"shape":"ListFeatureEvaluationsResponse"}, - "errors":[ - {"shape":"ThrottlingException"}, - {"shape":"InternalServerException"}, - {"shape":"ValidationException"}, - {"shape":"AccessDeniedException"} + "input": { "shape": "ListFeatureEvaluationsRequest" }, + "output": { "shape": "ListFeatureEvaluationsResponse" }, + "errors": [ + { "shape": "ThrottlingException" }, + { "shape": "InternalServerException" }, + { "shape": "ValidationException" }, + { "shape": "AccessDeniedException" } ] }, - "ResumeTransformation":{ - "name":"ResumeTransformation", - "http":{ - "method":"POST", - "requestUri":"/" + "ResumeTransformation": { + "name": "ResumeTransformation", + "http": { + "method": "POST", + "requestUri": "/" }, - "input":{"shape":"ResumeTransformationRequest"}, - "output":{"shape":"ResumeTransformationResponse"}, - "errors":[ - {"shape":"ThrottlingException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"InternalServerException"}, - {"shape":"ValidationException"}, - {"shape":"AccessDeniedException"} + "input": { "shape": "ResumeTransformationRequest" }, + "output": { "shape": "ResumeTransformationResponse" }, + "errors": [ + { "shape": "ThrottlingException" }, + { "shape": "ResourceNotFoundException" }, + { "shape": "InternalServerException" }, + { "shape": "ValidationException" }, + { "shape": "AccessDeniedException" } ] }, - "SendTelemetryEvent":{ - "name":"SendTelemetryEvent", - "http":{ - "method":"POST", - "requestUri":"/" + "SendTelemetryEvent": { + "name": "SendTelemetryEvent", + "http": { + "method": "POST", + "requestUri": "/" }, - "input":{"shape":"SendTelemetryEventRequest"}, - "output":{"shape":"SendTelemetryEventResponse"}, - "errors":[ - {"shape":"ThrottlingException"}, - {"shape":"InternalServerException"}, - {"shape":"ValidationException"}, - {"shape":"AccessDeniedException"} + "input": { "shape": "SendTelemetryEventRequest" }, + "output": { "shape": "SendTelemetryEventResponse" }, + "errors": [ + { "shape": "ThrottlingException" }, + { "shape": "InternalServerException" }, + { "shape": "ValidationException" }, + { "shape": "AccessDeniedException" } ], - "idempotent":true + "idempotent": true }, - "StartCodeAnalysis":{ - "name":"StartCodeAnalysis", - "http":{ - "method":"POST", - "requestUri":"/" + "StartCodeAnalysis": { + "name": "StartCodeAnalysis", + "http": { + "method": "POST", + "requestUri": "/" }, - "input":{"shape":"StartCodeAnalysisRequest"}, - "output":{"shape":"StartCodeAnalysisResponse"}, - "errors":[ - {"shape":"ThrottlingException"}, - {"shape":"ConflictException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"InternalServerException"}, - {"shape":"ValidationException"}, - {"shape":"AccessDeniedException"} + "input": { "shape": "StartCodeAnalysisRequest" }, + "output": { "shape": "StartCodeAnalysisResponse" }, + "errors": [ + { "shape": "ThrottlingException" }, + { "shape": "ConflictException" }, + { "shape": "ResourceNotFoundException" }, + { "shape": "InternalServerException" }, + { "shape": "ValidationException" }, + { "shape": "AccessDeniedException" } ], - "idempotent":true + "idempotent": true }, "StartTaskAssistCodeGeneration": { - "name":"StartTaskAssistCodeGeneration", - "http":{ - "method":"POST", - "requestUri":"/" + "name": "StartTaskAssistCodeGeneration", + "http": { + "method": "POST", + "requestUri": "/" }, - "input":{"shape":"StartTaskAssistCodeGenerationRequest"}, - "output":{"shape":"StartTaskAssistCodeGenerationResponse"}, - "errors":[ - {"shape":"ThrottlingException"}, - {"shape":"ServiceQuotaExceededException"}, - {"shape":"ConflictException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"InternalServerException"}, - {"shape":"ValidationException"}, - {"shape":"AccessDeniedException"} + "input": { "shape": "StartTaskAssistCodeGenerationRequest" }, + "output": { "shape": "StartTaskAssistCodeGenerationResponse" }, + "errors": [ + { "shape": "ThrottlingException" }, + { "shape": "ConflictException" }, + { "shape": "ServiceQuotaExceededException" }, + { "shape": "ResourceNotFoundException" }, + { "shape": "InternalServerException" }, + { "shape": "ValidationException" }, + { "shape": "AccessDeniedException" } ] }, - "StartTransformation":{ - "name":"StartTransformation", - "http":{ - "method":"POST", - "requestUri":"/" + "StartTransformation": { + "name": "StartTransformation", + "http": { + "method": "POST", + "requestUri": "/" }, - "input":{"shape":"StartTransformationRequest"}, - "output":{"shape":"StartTransformationResponse"}, - "errors":[ - {"shape":"ThrottlingException"}, - {"shape":"InternalServerException"}, - {"shape":"ValidationException"}, - {"shape":"AccessDeniedException"} + "input": { "shape": "StartTransformationRequest" }, + "output": { "shape": "StartTransformationResponse" }, + "errors": [ + { "shape": "ThrottlingException" }, + { "shape": "ConflictException" }, + { "shape": "InternalServerException" }, + { "shape": "ValidationException" }, + { "shape": "AccessDeniedException" } ] }, - "StopTransformation":{ - "name":"StopTransformation", - "http":{ - "method":"POST", - "requestUri":"/" + "StopTransformation": { + "name": "StopTransformation", + "http": { + "method": "POST", + "requestUri": "/" }, - "input":{"shape":"StopTransformationRequest"}, - "output":{"shape":"StopTransformationResponse"}, - "errors":[ - {"shape":"ThrottlingException"}, - {"shape":"InternalServerException"}, - {"shape":"ValidationException"}, - {"shape":"AccessDeniedException"} + "input": { "shape": "StopTransformationRequest" }, + "output": { "shape": "StopTransformationResponse" }, + "errors": [ + { "shape": "ThrottlingException" }, + { "shape": "ResourceNotFoundException" }, + { "shape": "InternalServerException" }, + { "shape": "ValidationException" }, + { "shape": "AccessDeniedException" } ] } }, - "shapes":{ - "AccessDeniedException":{ - "type":"structure", - "required":["message"], - "members":{ - "message":{"shape":"String"} + "shapes": { + "AccessDeniedException": { + "type": "structure", + "required": ["message"], + "members": { + "message": { "shape": "String" }, + "reason": { "shape": "AccessDeniedExceptionReason" } }, - "exception":true - }, - "ArtifactId":{ - "type":"string", - "max":126, - "min":1, - "pattern":"[a-zA-Z0-9-_]+" - }, - "ArtifactMap":{ - "type":"map", - "key":{"shape":"ArtifactType"}, - "value":{"shape":"UploadId"}, - "max":64, - "min":1 - }, - "ArtifactType":{ - "type":"string", - "enum":[ - "SourceCode", - "BuiltJars" - ] + "exception": true }, - "AssistantResponseMessage":{ - "type":"structure", - "required":["content"], - "members":{ - "messageId":{"shape":"MessageId"}, - "content":{"shape":"AssistantResponseMessageContentString"}, - "supplementaryWebLinks":{"shape":"SupplementaryWebLinks"}, - "references":{"shape":"References"}, - "followupPrompt":{"shape":"FollowupPrompt"} - } - }, - "AssistantResponseMessageContentString":{ - "type":"string", - "max":4096, - "min":0, - "sensitive":true - }, - "AssistantResponseMessageMessageIdString":{ - "type":"string", - "max":128, - "min":0 - }, - "Base64EncodedPaginationToken":{ - "type":"string", - "max":2048, - "min":1, - "pattern":"(?:[A-Za-z0-9\\+/]{4})*(?:[A-Za-z0-9\\+/]{2}\\=\\=|[A-Za-z0-9\\+/]{3}\\=)?" - }, - "Boolean":{ - "type":"boolean", - "box":true + "AccessDeniedExceptionReason": { + "type": "string", + "enum": ["UNAUTHORIZED_CUSTOMIZATION_RESOURCE_ACCESS"] + }, + "AppStudioState": { + "type": "structure", + "required": ["namespace", "propertyName", "propertyContext"], + "members": { + "namespace": { "shape": "AppStudioStateNamespaceString" }, + "propertyName": { "shape": "AppStudioStatePropertyNameString" }, + "propertyValue": { "shape": "AppStudioStatePropertyValueString" }, + "propertyContext": { "shape": "AppStudioStatePropertyContextString" } + } + }, + "AppStudioStateNamespaceString": { + "type": "string", + "max": 1024, + "min": 1, + "sensitive": true + }, + "AppStudioStatePropertyContextString": { + "type": "string", + "max": 1024, + "min": 1, + "sensitive": true + }, + "AppStudioStatePropertyNameString": { + "type": "string", + "max": 1024, + "min": 1, + "sensitive": true + }, + "AppStudioStatePropertyValueString": { + "type": "string", + "max": 10240, + "min": 0, + "sensitive": true + }, + "ArtifactId": { + "type": "string", + "max": 126, + "min": 1, + "pattern": "[a-zA-Z0-9-_]+" + }, + "ArtifactMap": { + "type": "map", + "key": { "shape": "ArtifactType" }, + "value": { "shape": "UploadId" }, + "max": 64, + "min": 1 + }, + "ArtifactType": { + "type": "string", + "enum": ["SourceCode", "BuiltJars"] + }, + "AssistantResponseMessage": { + "type": "structure", + "required": ["content"], + "members": { + "messageId": { "shape": "MessageId" }, + "content": { "shape": "AssistantResponseMessageContentString" }, + "supplementaryWebLinks": { "shape": "SupplementaryWebLinks" }, + "references": { "shape": "References" }, + "followupPrompt": { "shape": "FollowupPrompt" } + } + }, + "AssistantResponseMessageContentString": { + "type": "string", + "max": 4096, + "min": 0, + "sensitive": true + }, + "Base64EncodedPaginationToken": { + "type": "string", + "max": 2048, + "min": 1, + "pattern": "(?:[A-Za-z0-9\\+/]{4})*(?:[A-Za-z0-9\\+/]{2}\\=\\=|[A-Za-z0-9\\+/]{3}\\=)?" + }, + "Boolean": { + "type": "boolean", + "box": true }, "ChatAddMessageEvent": { "type": "structure", @@ -384,13 +407,13 @@ "members": { "conversationId": { "shape": "ConversationId" }, "messageId": { "shape": "MessageId" }, - "customizationArn":{ "shape":"CustomizationArn" }, + "customizationArn": { "shape": "CustomizationArn" }, "userIntent": { "shape": "UserIntent" }, "hasCodeSnippet": { "shape": "Boolean" }, "programmingLanguage": { "shape": "ProgrammingLanguage" }, "activeEditorTotalCharacters": { "shape": "Integer" }, "timeToFirstChunkMilliseconds": { "shape": "Double" }, - "timeBetweenChunks": { "shape": "TimeBetweenChunks" }, + "timeBetweenChunks": { "shape": "timeBetweenChunks" }, "fullResponselatency": { "shape": "Double" }, "requestLength": { "shape": "Integer" }, "responseLength": { "shape": "Integer" }, @@ -398,11 +421,11 @@ "hasProjectLevelContext": { "shape": "Boolean" } } }, - "ChatHistory":{ - "type":"list", - "member":{"shape":"ChatMessage"}, - "max":10, - "min":0 + "ChatHistory": { + "type": "list", + "member": { "shape": "ChatMessage" }, + "max": 10, + "min": 0 }, "ChatInteractWithMessageEvent": { "type": "structure", @@ -410,90 +433,60 @@ "members": { "conversationId": { "shape": "ConversationId" }, "messageId": { "shape": "MessageId" }, - "customizationArn":{ "shape":"CustomizationArn" }, + "customizationArn": { "shape": "CustomizationArn" }, "interactionType": { "shape": "ChatMessageInteractionType" }, - "interactionTarget": { "shape": "String" }, + "interactionTarget": { "shape": "ChatInteractWithMessageEventInteractionTargetString" }, "acceptedCharacterCount": { "shape": "Integer" }, "acceptedLineCount": { "shape": "Integer" }, "acceptedSnippetHasReference": { "shape": "Boolean" }, - "hasProjectLevelContext": { "shape": "Boolean" } - } - }, - "CreateTaskAssistConversationRequest": { - "type": "structure", - "members": {} - }, - "CreateTaskAssistConversationResponse": { - "type": "structure", - "required": ["conversationId"], - "members": { - "conversationId": { - "shape": "TaskAssistConversationId" - } + "hasProjectLevelContext": { "shape": "Boolean" }, + "userIntent": { "shape": "UserIntent" } } }, - "TaskAssistConversationId": { + "ChatInteractWithMessageEventInteractionTargetString": { "type": "string", - "documentation": "

ID which represents a multi-turn conversation

", - "max": 128, + "max": 1024, "min": 1 }, - "ChatMessage":{ - "type":"structure", - "members":{ - "userInputMessage":{"shape":"UserInputMessage"}, - "assistantResponseMessage":{"shape":"AssistantResponseMessage"} + "ChatMessage": { + "type": "structure", + "members": { + "userInputMessage": { "shape": "UserInputMessage" }, + "assistantResponseMessage": { "shape": "AssistantResponseMessage" } }, - "union":true + "union": true }, "ChatMessageInteractionType": { "type": "string", "enum": ["INSERT_AT_CURSOR", "COPY_SNIPPET", "COPY", "CLICK_LINK", "CLICK_BODY_LINK", "CLICK_FOLLOW_UP", "HOVER_REFERENCE", "UPVOTE", "DOWNVOTE"] }, - "FeatureDevEvent": { - "type": "structure", - "required": ["conversationId"], - "members": { - "conversationId": { "shape": "ConversationId" } - } + "ChatTriggerType": { + "type": "string", + "enum": ["MANUAL", "DIAGNOSTIC"] }, "ChatUserModificationEvent": { "type": "structure", "required": ["conversationId", "messageId", "modificationPercentage"], "members": { "conversationId": { "shape": "ConversationId" }, - "customizationArn":{"shape":"CustomizationArn"}, + "customizationArn": { "shape": "CustomizationArn" }, "messageId": { "shape": "MessageId" }, "programmingLanguage": { "shape": "ProgrammingLanguage" }, "modificationPercentage": { "shape": "Double" }, "hasProjectLevelContext": { "shape": "Boolean" } } }, - "ChatTriggerType":{ - "type":"string", - "enum":[ - "MANUAL", - "DIAGNOSTIC" - ] - }, - "CodeAnalysisFindingsSchema":{ - "type":"string", - "enum":["codeanalysis/findings/1.0"] + "CodeAnalysisFindingsSchema": { + "type": "string", + "enum": ["codeanalysis/findings/1.0"] }, "CodeAnalysisScope": { "type": "string", - "enum": [ - "FILE", - "PROJECT" - ] + "enum": ["FILE", "PROJECT"] }, - "CodeAnalysisStatus":{ - "type":"string", - "enum":[ - "Completed", - "Pending", - "Failed" - ] + "CodeAnalysisStatus": { + "type": "string", + "enum": ["Completed", "Pending", "Failed"] }, "CodeAnalysisUploadContext": { "type": "structure", @@ -502,814 +495,856 @@ "codeScanName": { "shape": "CodeScanName" } } }, - "CodeCoverageEvent":{ - "type":"structure", - "required":[ - "programmingLanguage", - "acceptedCharacterCount", - "totalCharacterCount", - "timestamp" - ], - "members":{ - "customizationArn":{"shape":"CustomizationArn"}, - "programmingLanguage":{"shape":"ProgrammingLanguage"}, - "acceptedCharacterCount":{"shape":"PrimitiveInteger"}, - "totalCharacterCount":{"shape":"PrimitiveInteger"}, - "timestamp":{"shape":"Timestamp"}, - "unmodifiedAcceptedCharacterCount": {"shape":"PrimitiveInteger"} + "CodeCoverageEvent": { + "type": "structure", + "required": ["programmingLanguage", "acceptedCharacterCount", "totalCharacterCount", "timestamp"], + "members": { + "customizationArn": { "shape": "CustomizationArn" }, + "programmingLanguage": { "shape": "ProgrammingLanguage" }, + "acceptedCharacterCount": { "shape": "PrimitiveInteger" }, + "totalCharacterCount": { "shape": "PrimitiveInteger" }, + "timestamp": { "shape": "Timestamp" }, + "unmodifiedAcceptedCharacterCount": { "shape": "PrimitiveInteger" } } }, - "CodeGenerationId":{ - "type":"string", - "max":128, - "min":1 + "CodeGenerationId": { + "type": "string", + "max": 128, + "min": 1 }, - "CodeGenerationStatus":{ - "type":"structure", - "required":[ - "status", - "currentStage" - ], - "members":{ - "status":{"shape":"CodeGenerationWorkflowStatus"}, - "currentStage":{"shape":"CodeGenerationWorkflowStage"} + "CodeGenerationStatus": { + "type": "structure", + "required": ["status", "currentStage"], + "members": { + "status": { "shape": "CodeGenerationWorkflowStatus" }, + "currentStage": { "shape": "CodeGenerationWorkflowStage" } } }, - "CodeGenerationStatusDetail":{ - "type":"string", - "documentation":"

Detailed message about the code generation status

", - "sensitive":true + "CodeGenerationStatusDetail": { + "type": "string", + "sensitive": true }, - "CodeGenerationWorkflowStage":{ - "type":"string", - "enum":[ - "InitialCodeGeneration", - "CodeRefinement" - ] + "CodeGenerationWorkflowStage": { + "type": "string", + "enum": ["InitialCodeGeneration", "CodeRefinement"] }, - "CodeGenerationWorkflowStatus":{ - "type":"string", - "enum":[ - "InProgress", - "Complete", - "Failed" - ] + "CodeGenerationWorkflowStatus": { + "type": "string", + "enum": ["InProgress", "Complete", "Failed"] }, - "CodeScanEvent":{ - "type":"structure", - "required":[ - "programmingLanguage", - "codeScanJobId", - "timestamp" - ], - "members":{ - "programmingLanguage":{"shape":"ProgrammingLanguage"}, - "codeScanJobId":{"shape":"CodeScanJobId"}, - "timestamp":{"shape":"Timestamp"}, - "codeAnalysisScope": {"shape": "CodeAnalysisScope"} + "CodeScanEvent": { + "type": "structure", + "required": ["programmingLanguage", "codeScanJobId", "timestamp"], + "members": { + "programmingLanguage": { "shape": "ProgrammingLanguage" }, + "codeScanJobId": { "shape": "CodeScanJobId" }, + "timestamp": { "shape": "Timestamp" }, + "codeAnalysisScope": { "shape": "CodeAnalysisScope" } } }, - "CodeScanJobId":{ - "type":"string", - "max":128, - "min":1 + "CodeScanJobId": { + "type": "string", + "max": 128, + "min": 1 }, "CodeScanName": { "type": "string", - "documentation": "

Code analysis scan name

", "max": 128, "min": 1 }, "CodeScanRemediationsEvent": { "type": "structure", "members": { - "programmingLanguage": { - "shape": "ProgrammingLanguage" - }, - "CodeScanRemediationsEventType": { - "shape": "CodeScanRemediationsEventType" - }, - "timestamp": { - "shape": "Timestamp" - }, - "detectorId": { - "shape": "String" - }, - "findingId": { - "shape": "String" - }, - "ruleId": { - "shape": "String" - }, - "component": { - "shape": "String" - }, - "reason": { - "shape": "String" - }, - "result": { - "shape": "String" - }, - "includesFix": { - "shape": "Boolean" - } + "programmingLanguage": { "shape": "ProgrammingLanguage" }, + "CodeScanRemediationsEventType": { "shape": "CodeScanRemediationsEventType" }, + "timestamp": { "shape": "Timestamp" }, + "detectorId": { "shape": "String" }, + "findingId": { "shape": "String" }, + "ruleId": { "shape": "String" }, + "component": { "shape": "String" }, + "reason": { "shape": "String" }, + "result": { "shape": "String" }, + "includesFix": { "shape": "Boolean" } } }, "CodeScanRemediationsEventType": { "type": "string", - "documentation": "

Code Scan Remediations Interaction Type

", "enum": ["CODESCAN_ISSUE_HOVER", "CODESCAN_ISSUE_APPLY_FIX", "CODESCAN_ISSUE_VIEW_DETAILS"] }, - "Completion":{ - "type":"structure", - "required":["content"], - "members":{ - "content":{"shape":"CompletionContentString"}, - "references":{"shape":"References"}, - "mostRelevantMissingImports":{"shape":"Imports"} - } - }, - "CompletionContentString":{ - "type":"string", - "max":5120, - "min":1, - "sensitive":true - }, - "CompletionType":{ - "type":"string", - "enum":[ - "BLOCK", - "LINE" - ] - }, - "Completions":{ - "type":"list", - "member":{"shape":"Completion"}, - "max":10, - "min":0 + "Completion": { + "type": "structure", + "required": ["content"], + "members": { + "content": { "shape": "CompletionContentString" }, + "references": { "shape": "References" }, + "mostRelevantMissingImports": { "shape": "Imports" } + } }, - "ConflictException":{ - "type":"structure", - "required":["message"], - "members":{ - "message":{"shape":"String"} - }, - "exception":true + "CompletionContentString": { + "type": "string", + "max": 5120, + "min": 1, + "sensitive": true }, - "ContentChecksumType":{ - "type":"string", - "enum":["SHA_256"] + "CompletionType": { + "type": "string", + "enum": ["BLOCK", "LINE"] }, - "ContextTruncationScheme":{ - "type":"string", - "enum":[ - "ANALYSIS", - "GUMBY" - ] + "Completions": { + "type": "list", + "member": { "shape": "Completion" }, + "max": 10, + "min": 0 }, - "ConversationId":{ - "type":"string", - "max":128, - "min":1 + "ConflictException": { + "type": "structure", + "required": ["message"], + "members": { + "message": { "shape": "String" } + }, + "exception": true }, - "ConversationState":{ - "type":"structure", - "required":[ - "currentMessage", - "chatTriggerType" - ], - "members":{ - "conversationId":{"shape":"ConversationId"}, - "history":{"shape":"ChatHistory"}, - "currentMessage":{"shape":"ChatMessage"}, - "chatTriggerType":{"shape":"ChatTriggerType"} + "ConsoleState": { + "type": "structure", + "members": { + "region": { "shape": "String" }, + "consoleUrl": { "shape": "SensitiveString" }, + "serviceId": { "shape": "String" }, + "serviceConsolePage": { "shape": "String" }, + "serviceSubconsolePage": { "shape": "String" }, + "taskName": { "shape": "SensitiveString" } } }, - "CreateUploadUrlRequest":{ - "type":"structure", - "members":{ - "contentMd5":{"shape":"CreateUploadUrlRequestContentMd5String"}, - "contentChecksum":{"shape":"CreateUploadUrlRequestContentChecksumString"}, - "contentChecksumType":{"shape":"ContentChecksumType"}, - "contentLength":{"shape":"CreateUploadUrlRequestContentLengthLong"}, - "artifactType":{"shape":"ArtifactType"}, - "uploadIntent":{"shape":"UploadIntent"}, - "uploadContext":{"shape":"UploadContext"} - } - }, - "CreateUploadUrlRequestContentChecksumString":{ - "type":"string", - "max":512, - "min":1, - "sensitive":true - }, - "CreateUploadUrlRequestContentLengthLong":{ - "type":"long", - "box":true, - "min":1 - }, - "CreateUploadUrlRequestContentMd5String":{ - "type":"string", - "max":128, - "min":1, - "sensitive":true - }, - "CreateUploadUrlResponse":{ - "type":"structure", - "required":[ - "uploadId", - "uploadUrl" - ], - "members":{ - "uploadId":{"shape":"UploadId"}, - "uploadUrl":{"shape":"PreSignedUrl"}, - "kmsKeyArn":{"shape":"ResourceArn"}, - "requestHeaders": { - "shape": "RequestHeaders" - } - } + "ContentChecksumType": { + "type": "string", + "enum": ["SHA_256"] }, - "CursorState":{ - "type":"structure", - "members":{ - "position":{"shape":"Position"}, - "range":{"shape":"Range"} - }, - "union":true + "ContextTruncationScheme": { + "type": "string", + "enum": ["ANALYSIS", "GUMBY"] }, - "Customization":{ - "type":"structure", - "required":["arn"], - "members":{ - "arn":{"shape":"CustomizationArn"}, - "name":{"shape":"CustomizationName"}, - "description":{"shape":"Description"} - } - }, - "CustomizationArn":{ - "type":"string", - "max":950, - "min":0, - "pattern":"arn:[-.a-z0-9]{1,63}:codewhisperer:([-.a-z0-9]{0,63}:){2}([a-zA-Z0-9-_:/]){1,1023}" - }, - "CustomizationName":{ - "type":"string", - "max":100, - "min":1, - "pattern":"[a-zA-Z][a-zA-Z0-9_-]*" - }, - "Customizations":{ - "type":"list", - "member":{"shape":"Customization"} - }, - "Description":{ - "type":"string", - "max":256, - "min":0, - "pattern":"[\\sa-zA-Z0-9_-]*" - }, - "Diagnostic":{ - "type":"structure", - "members":{ - "textDocumentDiagnostic":{"shape":"TextDocumentDiagnostic"}, - "runtimeDiagnostic":{"shape":"RuntimeDiagnostic"} - }, - "union":true - }, - "DiagnosticSeverity":{ - "type":"string", - "enum":[ - "ERROR", - "WARNING", - "INFORMATION", - "HINT" - ] + "ConversationId": { + "type": "string", + "max": 128, + "min": 1 }, - "Dimension":{ - "type":"structure", - "members":{ - "name":{"shape":"DimensionNameString"}, - "value":{"shape":"DimensionValueString"} + "ConversationState": { + "type": "structure", + "required": ["currentMessage", "chatTriggerType"], + "members": { + "conversationId": { "shape": "ConversationId" }, + "history": { "shape": "ChatHistory" }, + "currentMessage": { "shape": "ChatMessage" }, + "chatTriggerType": { "shape": "ChatTriggerType" }, + "customizationArn": { "shape": "ResourceArn" } } }, - "DimensionList":{ - "type":"list", - "member":{"shape":"Dimension"}, - "max":30, - "min":0 - }, - "DimensionNameString":{ - "type":"string", - "max":255, - "min":1, - "pattern":"[-a-zA-Z0-9._]*" - }, - "DimensionValueString":{ - "type":"string", - "max":1024, - "min":1, - "pattern":"[-a-zA-Z0-9._]*" + "CreateTaskAssistConversationRequest": { + "type": "structure", + "members": {} }, - "DocumentSymbol":{ - "type":"structure", - "required":[ - "name", - "type" - ], - "members":{ - "name":{"shape":"DocumentSymbolNameString"}, - "type":{"shape":"SymbolType"}, - "source":{"shape":"DocumentSymbolSourceString"} + "CreateTaskAssistConversationResponse": { + "type": "structure", + "required": ["conversationId"], + "members": { + "conversationId": { "shape": "ConversationId" } } }, - "DocumentSymbolNameString":{ - "type":"string", - "max":256, - "min":1 + "CreateUploadUrlRequest": { + "type": "structure", + "members": { + "contentMd5": { "shape": "CreateUploadUrlRequestContentMd5String" }, + "contentChecksum": { "shape": "CreateUploadUrlRequestContentChecksumString" }, + "contentChecksumType": { "shape": "ContentChecksumType" }, + "contentLength": { "shape": "CreateUploadUrlRequestContentLengthLong" }, + "artifactType": { "shape": "ArtifactType" }, + "uploadIntent": { "shape": "UploadIntent" }, + "uploadContext": { "shape": "UploadContext" }, + "uploadId": { "shape": "UploadId" } + } }, - "DocumentSymbolSourceString":{ - "type":"string", - "max":256, - "min":1 + "CreateUploadUrlRequestContentChecksumString": { + "type": "string", + "max": 512, + "min": 1, + "sensitive": true }, - "DocumentSymbols":{ - "type":"list", - "member":{"shape":"DocumentSymbol"}, - "max":1000, - "min":0 + "CreateUploadUrlRequestContentLengthLong": { + "type": "long", + "box": true, + "min": 1 }, - "Double":{ - "type":"double", - "box":true + "CreateUploadUrlRequestContentMd5String": { + "type": "string", + "max": 128, + "min": 1, + "sensitive": true }, - "EditorState":{ - "type":"structure", - "members":{ - "document":{"shape":"TextDocument"}, - "cursorState":{"shape":"CursorState"} + "CreateUploadUrlResponse": { + "type": "structure", + "required": ["uploadId", "uploadUrl"], + "members": { + "uploadId": { "shape": "UploadId" }, + "uploadUrl": { "shape": "PreSignedUrl" }, + "kmsKeyArn": { "shape": "ResourceArn" }, + "requestHeaders": { "shape": "RequestHeaders" } } }, - "FeatureEvaluation":{ - "type":"structure", - "required":[ - "feature", - "variation", - "value" - ], - "members":{ - "feature":{"shape":"FeatureName"}, - "variation":{"shape":"FeatureVariation"}, - "value":{"shape":"FeatureValue"} + "CursorState": { + "type": "structure", + "members": { + "position": { "shape": "Position" }, + "range": { "shape": "Range" } + }, + "union": true + }, + "Customization": { + "type": "structure", + "required": ["arn"], + "members": { + "arn": { "shape": "CustomizationArn" }, + "name": { "shape": "CustomizationName" }, + "description": { "shape": "Description" } } }, - "FeatureEvaluationsList":{ - "type":"list", - "member":{"shape":"FeatureEvaluation"}, - "max":50, - "min":0 + "CustomizationArn": { + "type": "string", + "max": 950, + "min": 0, + "pattern": "arn:[-.a-z0-9]{1,63}:codewhisperer:([-.a-z0-9]{0,63}:){2}([a-zA-Z0-9-_:/]){1,1023}" }, - "FeatureName":{ - "type":"string", - "max":128, - "min":1, - "pattern":"[-a-zA-Z0-9._]*" + "CustomizationName": { + "type": "string", + "max": 100, + "min": 1, + "pattern": "[a-zA-Z][a-zA-Z0-9_-]*" }, - "FeatureValue":{ - "type":"structure", - "members":{ - "boolValue":{"shape":"Boolean"}, - "doubleValue":{"shape":"Double"}, - "longValue":{"shape":"Long"}, - "stringValue":{"shape":"FeatureValueStringType"} + "Customizations": { + "type": "list", + "member": { "shape": "Customization" } + }, + "DeleteTaskAssistConversationRequest": { + "type": "structure", + "required": ["conversationId"], + "members": { + "conversationId": { "shape": "ConversationId" } + } + }, + "DeleteTaskAssistConversationResponse": { + "type": "structure", + "required": ["conversationId"], + "members": { + "conversationId": { "shape": "ConversationId" } + } + }, + "Description": { + "type": "string", + "max": 256, + "min": 0, + "pattern": "[\\sa-zA-Z0-9_-]*" + }, + "Diagnostic": { + "type": "structure", + "members": { + "textDocumentDiagnostic": { "shape": "TextDocumentDiagnostic" }, + "runtimeDiagnostic": { "shape": "RuntimeDiagnostic" } }, - "union":true + "union": true }, - "FeatureValueStringType":{ - "type":"string", - "max":512, - "min":0 + "DiagnosticSeverity": { + "type": "string", + "enum": ["ERROR", "WARNING", "INFORMATION", "HINT"] }, - "FeatureVariation":{ - "type":"string", - "max":128, - "min":1, - "pattern":"[-a-zA-Z0-9._]*" + "Dimension": { + "type": "structure", + "members": { + "name": { "shape": "DimensionNameString" }, + "value": { "shape": "DimensionValueString" } + } }, - "FileContext":{ - "type":"structure", - "required":[ - "leftFileContent", - "rightFileContent", - "filename", - "programmingLanguage" - ], - "members":{ - "leftFileContent":{"shape":"FileContextLeftFileContentString"}, - "rightFileContent":{"shape":"FileContextRightFileContentString"}, - "filename":{"shape":"FileContextFilenameString"}, - "programmingLanguage":{"shape":"ProgrammingLanguage"} - } - }, - "FileContextFilenameString":{ - "type":"string", - "max":1024, - "min":1, - "sensitive":true - }, - "FileContextLeftFileContentString":{ - "type":"string", - "max":10240, - "min":0, - "sensitive":true - }, - "FileContextRightFileContentString":{ - "type":"string", - "max":10240, - "min":0, - "sensitive":true - }, - "FollowupPrompt":{ - "type":"structure", - "required":["content"], - "members":{ - "content":{"shape":"FollowupPromptContentString"}, - "userIntent":{"shape":"UserIntent"} + "DimensionList": { + "type": "list", + "member": { "shape": "Dimension" }, + "max": 30, + "min": 0 + }, + "DimensionNameString": { + "type": "string", + "max": 255, + "min": 1, + "pattern": "[-a-zA-Z0-9._]*" + }, + "DimensionValueString": { + "type": "string", + "max": 1024, + "min": 1, + "pattern": "[-a-zA-Z0-9._]*" + }, + "DocumentSymbol": { + "type": "structure", + "required": ["name", "type"], + "members": { + "name": { "shape": "DocumentSymbolNameString" }, + "type": { "shape": "SymbolType" }, + "source": { "shape": "DocumentSymbolSourceString" } } }, - "FollowupPromptContentString":{ - "type":"string", - "max":4096, - "min":0, - "sensitive":true + "DocumentSymbolNameString": { + "type": "string", + "max": 256, + "min": 1 }, - "GenerateCompletionsRequest":{ - "type":"structure", - "required":["fileContext"], - "members":{ - "fileContext":{"shape":"FileContext"}, - "maxResults":{"shape":"GenerateCompletionsRequestMaxResultsInteger"}, - "nextToken":{"shape":"GenerateCompletionsRequestNextTokenString"}, - "referenceTrackerConfiguration":{"shape":"ReferenceTrackerConfiguration"}, - "supplementalContexts":{"shape":"SupplementalContextList"}, - "customizationArn":{"shape":"CustomizationArn"}, - "optOutPreference":{"shape":"OptOutPreference"}, - "userContext":{"shape":"UserContext"} + "DocumentSymbolSourceString": { + "type": "string", + "max": 256, + "min": 1 + }, + "DocumentSymbols": { + "type": "list", + "member": { "shape": "DocumentSymbol" }, + "max": 1000, + "min": 0 + }, + "Double": { + "type": "double", + "box": true + }, + "EditorState": { + "type": "structure", + "members": { + "document": { "shape": "TextDocument" }, + "cursorState": { "shape": "CursorState" }, + "relevantDocuments": { "shape": "RelevantDocumentList" }, + "useRelevantDocuments": { "shape": "Boolean" } } }, - "GenerateCompletionsRequestMaxResultsInteger":{ - "type":"integer", - "box":true, - "max":10, - "min":1 + "EnvState": { + "type": "structure", + "members": { + "operatingSystem": { "shape": "EnvStateOperatingSystemString" }, + "currentWorkingDirectory": { "shape": "EnvStateCurrentWorkingDirectoryString" }, + "environmentVariables": { "shape": "EnvironmentVariables" } + } }, - "GenerateCompletionsRequestNextTokenString":{ - "type":"string", - "max":2048, - "min":0, - "pattern":"(?:[A-Za-z0-9\\+/]{4})*(?:[A-Za-z0-9\\+/]{2}\\=\\=|[A-Za-z0-9\\+/]{3}\\=)?", - "sensitive":true + "EnvStateCurrentWorkingDirectoryString": { + "type": "string", + "max": 256, + "min": 1, + "sensitive": true }, - "GenerateCompletionsResponse":{ - "type":"structure", - "members":{ - "completions":{"shape":"Completions"}, - "nextToken":{"shape":"SensitiveString"} + "EnvStateOperatingSystemString": { + "type": "string", + "max": 32, + "min": 1, + "pattern": "(macos|linux|windows)" + }, + "EnvironmentVariable": { + "type": "structure", + "members": { + "key": { "shape": "EnvironmentVariableKeyString" }, + "value": { "shape": "EnvironmentVariableValueString" } } }, - "GetCodeAnalysisRequest":{ - "type":"structure", - "required":["jobId"], - "members":{ - "jobId":{"shape":"GetCodeAnalysisRequestJobIdString"} + "EnvironmentVariableKeyString": { + "type": "string", + "max": 256, + "min": 1, + "sensitive": true + }, + "EnvironmentVariableValueString": { + "type": "string", + "max": 1024, + "min": 1, + "sensitive": true + }, + "EnvironmentVariables": { + "type": "list", + "member": { "shape": "EnvironmentVariable" }, + "max": 100, + "min": 0 + }, + "FeatureDevEvent": { + "type": "structure", + "required": ["conversationId"], + "members": { + "conversationId": { "shape": "ConversationId" } } }, - "GetCodeAnalysisRequestJobIdString":{ - "type":"string", - "max":256, - "min":1 + "FeatureEvaluation": { + "type": "structure", + "required": ["feature", "variation", "value"], + "members": { + "feature": { "shape": "FeatureName" }, + "variation": { "shape": "FeatureVariation" }, + "value": { "shape": "FeatureValue" } + } }, - "GetCodeAnalysisResponse":{ - "type":"structure", - "required":["status"], - "members":{ - "status":{"shape":"CodeAnalysisStatus"}, - "errorMessage":{"shape":"SensitiveString"} + "FeatureEvaluationsList": { + "type": "list", + "member": { "shape": "FeatureEvaluation" }, + "max": 50, + "min": 0 + }, + "FeatureName": { + "type": "string", + "max": 128, + "min": 1, + "pattern": "[-a-zA-Z0-9._]*" + }, + "FeatureValue": { + "type": "structure", + "members": { + "boolValue": { "shape": "Boolean" }, + "doubleValue": { "shape": "Double" }, + "longValue": { "shape": "Long" }, + "stringValue": { "shape": "FeatureValueStringType" } + }, + "union": true + }, + "FeatureValueStringType": { + "type": "string", + "max": 512, + "min": 0 + }, + "FeatureVariation": { + "type": "string", + "max": 128, + "min": 1, + "pattern": "[-a-zA-Z0-9._]*" + }, + "FileContext": { + "type": "structure", + "required": ["leftFileContent", "rightFileContent", "filename", "programmingLanguage"], + "members": { + "leftFileContent": { "shape": "FileContextLeftFileContentString" }, + "rightFileContent": { "shape": "FileContextRightFileContentString" }, + "filename": { "shape": "FileContextFilenameString" }, + "programmingLanguage": { "shape": "ProgrammingLanguage" } + } + }, + "FileContextFilenameString": { + "type": "string", + "max": 1024, + "min": 1, + "sensitive": true + }, + "FileContextLeftFileContentString": { + "type": "string", + "max": 10240, + "min": 0, + "sensitive": true + }, + "FileContextRightFileContentString": { + "type": "string", + "max": 10240, + "min": 0, + "sensitive": true + }, + "FollowupPrompt": { + "type": "structure", + "required": ["content"], + "members": { + "content": { "shape": "FollowupPromptContentString" }, + "userIntent": { "shape": "UserIntent" } + } + }, + "FollowupPromptContentString": { + "type": "string", + "max": 4096, + "min": 0, + "sensitive": true + }, + "GenerateCompletionsRequest": { + "type": "structure", + "required": ["fileContext"], + "members": { + "fileContext": { "shape": "FileContext" }, + "maxResults": { "shape": "GenerateCompletionsRequestMaxResultsInteger" }, + "nextToken": { "shape": "GenerateCompletionsRequestNextTokenString" }, + "referenceTrackerConfiguration": { "shape": "ReferenceTrackerConfiguration" }, + "supplementalContexts": { "shape": "SupplementalContextList" }, + "customizationArn": { "shape": "CustomizationArn" }, + "optOutPreference": { "shape": "OptOutPreference" }, + "userContext": { "shape": "UserContext" }, + "profileArn": { "shape": "ProfileArn" } + } + }, + "GenerateCompletionsRequestMaxResultsInteger": { + "type": "integer", + "box": true, + "max": 10, + "min": 1 + }, + "GenerateCompletionsRequestNextTokenString": { + "type": "string", + "max": 2048, + "min": 0, + "pattern": "(?:[A-Za-z0-9\\+/]{4})*(?:[A-Za-z0-9\\+/]{2}\\=\\=|[A-Za-z0-9\\+/]{3}\\=)?", + "sensitive": true + }, + "GenerateCompletionsResponse": { + "type": "structure", + "members": { + "completions": { "shape": "Completions" }, + "nextToken": { "shape": "SensitiveString" } + } + }, + "GetCodeAnalysisRequest": { + "type": "structure", + "required": ["jobId"], + "members": { + "jobId": { "shape": "GetCodeAnalysisRequestJobIdString" } + } + }, + "GetCodeAnalysisRequestJobIdString": { + "type": "string", + "max": 256, + "min": 1 + }, + "GetCodeAnalysisResponse": { + "type": "structure", + "required": ["status"], + "members": { + "status": { "shape": "CodeAnalysisStatus" }, + "errorMessage": { "shape": "SensitiveString" } } }, "GetTaskAssistCodeGenerationRequest": { "type": "structure", "required": ["conversationId", "codeGenerationId"], "members": { - "conversationId": { - "shape": "ConversationId" - }, - "codeGenerationId": { - "shape": "CodeGenerationId" - } + "conversationId": { "shape": "ConversationId" }, + "codeGenerationId": { "shape": "CodeGenerationId" } } }, "GetTaskAssistCodeGenerationResponse": { "type": "structure", "required": ["conversationId", "codeGenerationStatus"], "members": { - "conversationId": { - "shape": "ConversationId" - }, - "codeGenerationStatus": { - "shape": "CodeGenerationStatus" - }, - "codeGenerationStatusDetail": { - "shape": "CodeGenerationStatusDetail" - }, - "codeGenerationRemainingIterationCount": { - "shape": "Integer" - }, - "codeGenerationTotalIterationCount": { - "shape": "Integer" - } + "conversationId": { "shape": "ConversationId" }, + "codeGenerationStatus": { "shape": "CodeGenerationStatus" }, + "codeGenerationStatusDetail": { "shape": "CodeGenerationStatusDetail" }, + "codeGenerationRemainingIterationCount": { "shape": "Integer" }, + "codeGenerationTotalIterationCount": { "shape": "Integer" } } }, - "GetTransformationPlanRequest":{ - "type":"structure", - "required":["transformationJobId"], - "members":{ - "transformationJobId":{"shape":"TransformationJobId"} + "GetTransformationPlanRequest": { + "type": "structure", + "required": ["transformationJobId"], + "members": { + "transformationJobId": { "shape": "TransformationJobId" } } }, - "GetTransformationPlanResponse":{ - "type":"structure", - "required":["transformationPlan"], - "members":{ - "transformationPlan":{"shape":"TransformationPlan"} + "GetTransformationPlanResponse": { + "type": "structure", + "required": ["transformationPlan"], + "members": { + "transformationPlan": { "shape": "TransformationPlan" } } }, - "GetTransformationRequest":{ - "type":"structure", - "required":["transformationJobId"], - "members":{ - "transformationJobId":{"shape":"TransformationJobId"} + "GetTransformationRequest": { + "type": "structure", + "required": ["transformationJobId"], + "members": { + "transformationJobId": { "shape": "TransformationJobId" } } }, - "GetTransformationResponse":{ - "type":"structure", - "required":["transformationJob"], - "members":{ - "transformationJob":{"shape":"TransformationJob"} + "GetTransformationResponse": { + "type": "structure", + "required": ["transformationJob"], + "members": { + "transformationJob": { "shape": "TransformationJob" } } }, - "IdeCategory":{ - "type":"string", - "enum":[ - "JETBRAINS", - "VSCODE" - ], - "max":64, - "min":1 + "GitState": { + "type": "structure", + "members": { + "status": { "shape": "GitStateStatusString" } + } }, - "IdempotencyToken":{ - "type":"string", - "max":256, - "min":1 + "GitStateStatusString": { + "type": "string", + "max": 4096, + "min": 0, + "sensitive": true }, - "Import":{ - "type":"structure", - "members":{ - "statement":{"shape":"ImportStatementString"} + "IdeCategory": { + "type": "string", + "enum": ["JETBRAINS", "VSCODE", "CLI", "JUPYTER_MD", "JUPYTER_SM"], + "max": 64, + "min": 1 + }, + "IdempotencyToken": { + "type": "string", + "max": 256, + "min": 1 + }, + "Import": { + "type": "structure", + "members": { + "statement": { "shape": "ImportStatementString" } } }, - "ImportStatementString":{ - "type":"string", - "max":1024, - "min":1, - "sensitive":true + "ImportStatementString": { + "type": "string", + "max": 1024, + "min": 1, + "sensitive": true }, - "Imports":{ - "type":"list", - "member":{"shape":"Import"}, - "max":10, - "min":0 + "Imports": { + "type": "list", + "member": { "shape": "Import" }, + "max": 10, + "min": 0 }, - "Integer":{ - "type":"integer", - "box":true + "InlineChatEvent": { + "type": "structure", + "members": { + "inputLength": { "shape": "PrimitiveInteger" }, + "numSelectedLines": { "shape": "PrimitiveInteger" }, + "codeIntent": { "shape": "Boolean" }, + "userDecision": { "shape": "InlineChatUserDecision" }, + "responseStartLatency": { "shape": "Double" }, + "responseEndLatency": { "shape": "Double" } + } }, - "InternalServerException":{ - "type":"structure", - "required":["message"], - "members":{ - "message":{"shape":"String"} + "InlineChatUserDecision": { + "type": "string", + "enum": ["ACCEPT", "REJECT", "DISMISS"] + }, + "Integer": { + "type": "integer", + "box": true + }, + "InternalServerException": { + "type": "structure", + "required": ["message"], + "members": { + "message": { "shape": "String" } }, - "exception":true, - "fault":true, - "retryable":{"throttling":false} + "exception": true, + "fault": true, + "retryable": { "throttling": false } }, - "ListAvailableCustomizationsRequest":{ - "type":"structure", - "members":{ - "maxResults":{"shape":"ListAvailableCustomizationsRequestMaxResultsInteger"}, - "nextToken":{"shape":"Base64EncodedPaginationToken"} + "ListAvailableCustomizationsRequest": { + "type": "structure", + "members": { + "maxResults": { "shape": "ListAvailableCustomizationsRequestMaxResultsInteger" }, + "nextToken": { "shape": "Base64EncodedPaginationToken" } } }, - "ListAvailableCustomizationsRequestMaxResultsInteger":{ - "type":"integer", - "box":true, - "max":100, - "min":1 + "ListAvailableCustomizationsRequestMaxResultsInteger": { + "type": "integer", + "box": true, + "max": 100, + "min": 1 }, - "ListAvailableCustomizationsResponse":{ - "type":"structure", - "required":["customizations"], - "members":{ - "customizations":{"shape":"Customizations"}, - "nextToken":{"shape":"Base64EncodedPaginationToken"} + "ListAvailableCustomizationsResponse": { + "type": "structure", + "required": ["customizations"], + "members": { + "customizations": { "shape": "Customizations" }, + "nextToken": { "shape": "Base64EncodedPaginationToken" } } }, - "ListCodeAnalysisFindingsRequest":{ - "type":"structure", - "required":[ - "jobId", - "codeAnalysisFindingsSchema" - ], - "members":{ - "jobId":{"shape":"ListCodeAnalysisFindingsRequestJobIdString"}, - "nextToken":{"shape":"PaginationToken"}, - "codeAnalysisFindingsSchema":{"shape":"CodeAnalysisFindingsSchema"} + "ListCodeAnalysisFindingsRequest": { + "type": "structure", + "required": ["jobId", "codeAnalysisFindingsSchema"], + "members": { + "jobId": { "shape": "ListCodeAnalysisFindingsRequestJobIdString" }, + "nextToken": { "shape": "PaginationToken" }, + "codeAnalysisFindingsSchema": { "shape": "CodeAnalysisFindingsSchema" } } }, - "ListCodeAnalysisFindingsRequestJobIdString":{ - "type":"string", - "max":256, - "min":1 + "ListCodeAnalysisFindingsRequestJobIdString": { + "type": "string", + "max": 256, + "min": 1 }, - "ListCodeAnalysisFindingsResponse":{ - "type":"structure", - "required":["codeAnalysisFindings"], - "members":{ - "nextToken":{"shape":"PaginationToken"}, - "codeAnalysisFindings":{"shape":"SensitiveString"} + "ListCodeAnalysisFindingsResponse": { + "type": "structure", + "required": ["codeAnalysisFindings"], + "members": { + "nextToken": { "shape": "PaginationToken" }, + "codeAnalysisFindings": { "shape": "SensitiveString" } } }, - "ListFeatureEvaluationsRequest":{ - "type":"structure", - "required":["userContext"], - "members":{ - "userContext":{"shape":"UserContext"} + "ListFeatureEvaluationsRequest": { + "type": "structure", + "required": ["userContext"], + "members": { + "userContext": { "shape": "UserContext" } } }, - "ListFeatureEvaluationsResponse":{ - "type":"structure", - "required":["featureEvaluations"], - "members":{ - "featureEvaluations":{"shape":"FeatureEvaluationsList"} + "ListFeatureEvaluationsResponse": { + "type": "structure", + "required": ["featureEvaluations"], + "members": { + "featureEvaluations": { "shape": "FeatureEvaluationsList" } } }, - "Long":{ - "type":"long", - "box":true + "Long": { + "type": "long", + "box": true }, "MessageId": { "type": "string", "max": 128, "min": 0 }, - "MetricData":{ - "type":"structure", - "required":[ - "metricName", - "metricValue", - "timestamp" - ], - "members":{ - "metricName":{"shape":"MetricDataMetricNameString"}, - "metricValue":{"shape":"Double"}, - "timestamp":{"shape":"Timestamp"}, - "dimensions":{"shape":"DimensionList"} + "MetricData": { + "type": "structure", + "required": ["metricName", "metricValue", "timestamp", "product"], + "members": { + "metricName": { "shape": "MetricDataMetricNameString" }, + "metricValue": { "shape": "Double" }, + "timestamp": { "shape": "Timestamp" }, + "product": { "shape": "MetricDataProductString" }, + "dimensions": { "shape": "DimensionList" } } }, - "MetricDataMetricNameString":{ - "type":"string", - "max":1024, - "min":1, - "pattern":"[-a-zA-Z0-9._]*" + "MetricDataMetricNameString": { + "type": "string", + "max": 1024, + "min": 1, + "pattern": "[-a-zA-Z0-9._]*" }, - "OperatingSystem":{ - "type":"string", - "enum":[ - "MAC", - "WINDOWS", - "LINUX" - ], - "max":64, - "min":1 - }, - "OptOutPreference":{ - "type":"string", - "enum":[ - "OPTIN", - "OPTOUT" - ] + "MetricDataProductString": { + "type": "string", + "max": 128, + "min": 1, + "pattern": "[-a-zA-Z0-9._]*" }, - "PaginationToken":{ - "type":"string", - "max":2048, - "min":1, - "pattern":"\\S+" + "OperatingSystem": { + "type": "string", + "enum": ["MAC", "WINDOWS", "LINUX"], + "max": 64, + "min": 1 }, - "Position":{ - "type":"structure", - "required":[ - "line", - "character" - ], - "members":{ - "line":{"shape":"Integer"}, - "character":{"shape":"Integer"} + "OptOutPreference": { + "type": "string", + "enum": ["OPTIN", "OPTOUT"] + }, + "PaginationToken": { + "type": "string", + "max": 2048, + "min": 1, + "pattern": "\\S+" + }, + "Position": { + "type": "structure", + "required": ["line", "character"], + "members": { + "line": { "shape": "Integer" }, + "character": { "shape": "Integer" } } }, - "PreSignedUrl":{ - "type":"string", - "max":2048, - "min":1, - "sensitive":true + "PreSignedUrl": { + "type": "string", + "max": 2048, + "min": 1, + "sensitive": true }, - "PrimitiveInteger":{"type":"integer"}, - "ProgrammingLanguage":{ - "type":"structure", - "required":["languageName"], - "members":{ - "languageName":{"shape":"ProgrammingLanguageLanguageNameString"} + "PrimitiveInteger": { "type": "integer" }, + "ProfileArn": { + "type": "string", + "max": 950, + "min": 0, + "pattern": "arn:aws:codewhisperer:[-.a-z0-9]{1,63}:\\d{12}:profile/([a-zA-Z0-9]){12}" + }, + "ProgrammingLanguage": { + "type": "structure", + "required": ["languageName"], + "members": { + "languageName": { "shape": "ProgrammingLanguageLanguageNameString" } } }, - "ProgrammingLanguageLanguageNameString":{ - "type":"string", - "max":128, - "min":1, - "pattern":"(python|javascript|java|csharp|typescript|c|cpp|go|kotlin|php|ruby|rust|scala|shell|sql|json|yaml|vue|tf)" + "ProgrammingLanguageLanguageNameString": { + "type": "string", + "max": 128, + "min": 1, + "pattern": "(python|javascript|java|csharp|typescript|c|cpp|go|kotlin|php|ruby|rust|scala|shell|sql|json|yaml|vue|tf|tsx|jsx|plaintext)" }, - "ProgressUpdates":{ - "type":"list", - "member":{"shape":"TransformationProgressUpdate"} + "ProgressUpdates": { + "type": "list", + "member": { "shape": "TransformationProgressUpdate" } }, - "Range":{ - "type":"structure", - "required":[ - "start", - "end" - ], - "members":{ - "start":{"shape":"Position"}, - "end":{"shape":"Position"} + "Range": { + "type": "structure", + "required": ["start", "end"], + "members": { + "start": { "shape": "Position" }, + "end": { "shape": "Position" } } }, - "RecommendationsWithReferencesPreference":{ - "type":"string", - "enum":[ - "BLOCK", - "ALLOW" - ] + "RecommendationsWithReferencesPreference": { + "type": "string", + "enum": ["BLOCK", "ALLOW"] }, - "Reference":{ - "type":"structure", - "members":{ - "licenseName":{"shape":"ReferenceLicenseNameString"}, - "repository":{"shape":"ReferenceRepositoryString"}, - "url":{"shape":"ReferenceUrlString"}, - "recommendationContentSpan":{"shape":"Span"} + "Reference": { + "type": "structure", + "members": { + "licenseName": { "shape": "ReferenceLicenseNameString" }, + "repository": { "shape": "ReferenceRepositoryString" }, + "url": { "shape": "ReferenceUrlString" }, + "recommendationContentSpan": { "shape": "Span" } } }, - "ReferenceLicenseNameString":{ - "type":"string", - "max":1024, - "min":1 + "ReferenceLicenseNameString": { + "type": "string", + "max": 1024, + "min": 1 }, - "ReferenceRepositoryString":{ - "type":"string", - "max":1024, - "min":1 + "ReferenceRepositoryString": { + "type": "string", + "max": 1024, + "min": 1 }, - "ReferenceTrackerConfiguration":{ - "type":"structure", - "required":["recommendationsWithReferences"], - "members":{ - "recommendationsWithReferences":{"shape":"RecommendationsWithReferencesPreference"} + "ReferenceTrackerConfiguration": { + "type": "structure", + "required": ["recommendationsWithReferences"], + "members": { + "recommendationsWithReferences": { "shape": "RecommendationsWithReferencesPreference" } } }, - "ReferenceUrlString":{ - "type":"string", - "max":1024, - "min":1 + "ReferenceUrlString": { + "type": "string", + "max": 1024, + "min": 1 }, - "References":{ - "type":"list", - "member":{"shape":"Reference"}, - "max":10, - "min":0 + "References": { + "type": "list", + "member": { "shape": "Reference" }, + "max": 10, + "min": 0 }, - "ResourceArn":{ - "type":"string", - "max":1224, - "min":0, - "pattern":"arn:([-.a-z0-9]{1,63}:){2}([-.a-z0-9]{0,63}:){2}([a-zA-Z0-9-_:/]){1,1023}" + "RelevantDocumentList": { + "type": "list", + "member": { "shape": "RelevantTextDocument" }, + "max": 5, + "min": 0 + }, + "RelevantTextDocument": { + "type": "structure", + "required": ["relativeFilePath"], + "members": { + "relativeFilePath": { "shape": "RelevantTextDocumentRelativeFilePathString" }, + "programmingLanguage": { "shape": "ProgrammingLanguage" }, + "text": { "shape": "RelevantTextDocumentTextString" }, + "documentSymbols": { "shape": "DocumentSymbols" } + } + }, + "RelevantTextDocumentRelativeFilePathString": { + "type": "string", + "max": 4096, + "min": 1, + "sensitive": true + }, + "RelevantTextDocumentTextString": { + "type": "string", + "max": 10240, + "min": 0, + "sensitive": true }, "RequestHeaderKey": { "type": "string", @@ -1323,461 +1358,605 @@ }, "RequestHeaders": { "type": "map", - "key": { - "shape": "RequestHeaderKey" - }, - "value": { - "shape": "RequestHeaderValue" - }, + "key": { "shape": "RequestHeaderKey" }, + "value": { "shape": "RequestHeaderValue" }, "max": 16, - "min": 1 + "min": 1, + "sensitive": true }, - "ResourceNotFoundException":{ - "type":"structure", - "required":["message"], - "members":{ - "message":{"shape":"String"} + "ResourceArn": { + "type": "string", + "max": 1224, + "min": 0, + "pattern": "arn:([-.a-z0-9]{1,63}:){2}([-.a-z0-9]{0,63}:){2}([a-zA-Z0-9-_:/]){1,1023}" + }, + "ResourceNotFoundException": { + "type": "structure", + "required": ["message"], + "members": { + "message": { "shape": "String" } }, - "exception":true + "exception": true }, - "ResumeTransformationRequest":{ - "type":"structure", - "required":["transformationJobId"], - "members":{ - "transformationJobId":{"shape":"TransformationJobId"}, - "userActionStatus":{"shape":"TransformationUserActionStatus"} + "ResumeTransformationRequest": { + "type": "structure", + "required": ["transformationJobId"], + "members": { + "transformationJobId": { "shape": "TransformationJobId" }, + "userActionStatus": { "shape": "TransformationUserActionStatus" } } }, - "ResumeTransformationResponse":{ - "type":"structure", - "required":["transformationStatus"], - "members":{ - "transformationStatus":{"shape":"TransformationStatus"} + "ResumeTransformationResponse": { + "type": "structure", + "required": ["transformationStatus"], + "members": { + "transformationStatus": { "shape": "TransformationStatus" } } }, - "RuntimeDiagnostic":{ - "type":"structure", - "required":[ - "source", - "severity", - "message" - ], - "members":{ - "source":{"shape":"RuntimeDiagnosticSourceString"}, - "severity":{"shape":"DiagnosticSeverity"}, - "message":{"shape":"RuntimeDiagnosticMessageString"} + "RuntimeDiagnostic": { + "type": "structure", + "required": ["source", "severity", "message"], + "members": { + "source": { "shape": "RuntimeDiagnosticSourceString" }, + "severity": { "shape": "DiagnosticSeverity" }, + "message": { "shape": "RuntimeDiagnosticMessageString" } } }, - "RuntimeDiagnosticMessageString":{ - "type":"string", - "max":1024, - "min":0, - "sensitive":true + "RuntimeDiagnosticMessageString": { + "type": "string", + "max": 1024, + "min": 0, + "sensitive": true }, - "RuntimeDiagnosticSourceString":{ - "type":"string", - "max":1024, - "min":0, - "sensitive":true + "RuntimeDiagnosticSourceString": { + "type": "string", + "max": 1024, + "min": 0, + "sensitive": true }, - "SendTelemetryEventRequest":{ - "type":"structure", - "required":["telemetryEvent"], - "members":{ - "clientToken":{ - "shape":"IdempotencyToken", - "idempotencyToken":true + "SendTelemetryEventRequest": { + "type": "structure", + "required": ["telemetryEvent"], + "members": { + "clientToken": { + "shape": "IdempotencyToken", + "idempotencyToken": true }, - "telemetryEvent":{"shape":"TelemetryEvent"}, - "optOutPreference":{"shape":"OptOutPreference"}, - "userContext":{"shape":"UserContext"} + "telemetryEvent": { "shape": "TelemetryEvent" }, + "optOutPreference": { "shape": "OptOutPreference" }, + "userContext": { "shape": "UserContext" }, + "profileArn": { "shape": "ProfileArn" } + } + }, + "SendTelemetryEventResponse": { + "type": "structure", + "members": {} + }, + "SensitiveString": { + "type": "string", + "sensitive": true + }, + "ServiceQuotaExceededException": { + "type": "structure", + "required": ["message"], + "members": { + "message": { "shape": "String" } + }, + "exception": true + }, + "ShellHistory": { + "type": "list", + "member": { "shape": "ShellHistoryEntry" }, + "max": 20, + "min": 0 + }, + "ShellHistoryEntry": { + "type": "structure", + "required": ["command"], + "members": { + "command": { "shape": "ShellHistoryEntryCommandString" }, + "directory": { "shape": "ShellHistoryEntryDirectoryString" }, + "exitCode": { "shape": "Integer" }, + "stdout": { "shape": "ShellHistoryEntryStdoutString" }, + "stderr": { "shape": "ShellHistoryEntryStderrString" } + } + }, + "ShellHistoryEntryCommandString": { + "type": "string", + "max": 1024, + "min": 1, + "sensitive": true + }, + "ShellHistoryEntryDirectoryString": { + "type": "string", + "max": 256, + "min": 1, + "sensitive": true + }, + "ShellHistoryEntryStderrString": { + "type": "string", + "max": 4096, + "min": 0, + "sensitive": true + }, + "ShellHistoryEntryStdoutString": { + "type": "string", + "max": 4096, + "min": 0, + "sensitive": true + }, + "ShellState": { + "type": "structure", + "required": ["shellName"], + "members": { + "shellName": { "shape": "ShellStateShellNameString" }, + "shellHistory": { "shape": "ShellHistory" } + } + }, + "ShellStateShellNameString": { + "type": "string", + "max": 32, + "min": 1, + "pattern": "(zsh|bash|fish|pwsh|nu)" + }, + "Span": { + "type": "structure", + "members": { + "start": { "shape": "SpanStartInteger" }, + "end": { "shape": "SpanEndInteger" } + } + }, + "SpanEndInteger": { + "type": "integer", + "box": true, + "min": 0 + }, + "SpanStartInteger": { + "type": "integer", + "box": true, + "min": 0 + }, + "StartCodeAnalysisRequest": { + "type": "structure", + "required": ["artifacts", "programmingLanguage"], + "members": { + "artifacts": { "shape": "ArtifactMap" }, + "programmingLanguage": { "shape": "ProgrammingLanguage" }, + "clientToken": { + "shape": "StartCodeAnalysisRequestClientTokenString", + "idempotencyToken": true + }, + "scope": { "shape": "CodeAnalysisScope" }, + "codeScanName": { "shape": "CodeScanName" } + } + }, + "StartCodeAnalysisRequestClientTokenString": { + "type": "string", + "max": 256, + "min": 1 + }, + "StartCodeAnalysisResponse": { + "type": "structure", + "required": ["jobId", "status"], + "members": { + "jobId": { "shape": "StartCodeAnalysisResponseJobIdString" }, + "status": { "shape": "CodeAnalysisStatus" }, + "errorMessage": { "shape": "SensitiveString" } + } + }, + "StartCodeAnalysisResponseJobIdString": { + "type": "string", + "max": 256, + "min": 1 + }, + "StartTaskAssistCodeGenerationRequest": { + "type": "structure", + "required": ["conversationState", "workspaceState"], + "members": { + "conversationState": { "shape": "ConversationState" }, + "workspaceState": { "shape": "WorkspaceState" }, + "taskAssistPlan": { "shape": "TaskAssistPlan" }, + "codeGenerationId": { "shape": "CodeGenerationId" }, + "currentCodeGenerationId": { "shape": "CodeGenerationId" } + } + }, + "StartTaskAssistCodeGenerationResponse": { + "type": "structure", + "required": ["conversationId", "codeGenerationId"], + "members": { + "conversationId": { "shape": "ConversationId" }, + "codeGenerationId": { "shape": "CodeGenerationId" } + } + }, + "StartTransformationRequest": { + "type": "structure", + "required": ["workspaceState", "transformationSpec"], + "members": { + "workspaceState": { "shape": "WorkspaceState" }, + "transformationSpec": { "shape": "TransformationSpec" } + } + }, + "StartTransformationResponse": { + "type": "structure", + "required": ["transformationJobId"], + "members": { + "transformationJobId": { "shape": "TransformationJobId" } + } + }, + "StepId": { + "type": "string", + "max": 126, + "min": 1 + }, + "StopTransformationRequest": { + "type": "structure", + "required": ["transformationJobId"], + "members": { + "transformationJobId": { "shape": "TransformationJobId" } } }, - "SendTelemetryEventResponse":{ - "type":"structure", - "members":{ - } + "StopTransformationResponse": { + "type": "structure", + "required": ["transformationStatus"], + "members": { + "transformationStatus": { "shape": "TransformationStatus" } + } + }, + "String": { "type": "string" }, + "SuggestionState": { + "type": "string", + "enum": ["ACCEPT", "REJECT", "DISCARD", "EMPTY"] + }, + "SupplementalContext": { + "type": "structure", + "required": ["filePath", "content"], + "members": { + "filePath": { "shape": "SupplementalContextFilePathString" }, + "content": { "shape": "SupplementalContextContentString" } + } + }, + "SupplementalContextContentString": { + "type": "string", + "max": 10240, + "min": 1, + "sensitive": true + }, + "SupplementalContextFilePathString": { + "type": "string", + "max": 1024, + "min": 1, + "sensitive": true + }, + "SupplementalContextList": { + "type": "list", + "member": { "shape": "SupplementalContext" }, + "max": 5, + "min": 0 + }, + "SupplementaryWebLink": { + "type": "structure", + "required": ["url", "title"], + "members": { + "url": { "shape": "SupplementaryWebLinkUrlString" }, + "title": { "shape": "SupplementaryWebLinkTitleString" }, + "snippet": { "shape": "SupplementaryWebLinkSnippetString" } + } + }, + "SupplementaryWebLinkSnippetString": { + "type": "string", + "max": 1024, + "min": 1, + "sensitive": true + }, + "SupplementaryWebLinkTitleString": { + "type": "string", + "max": 1024, + "min": 1, + "sensitive": true + }, + "SupplementaryWebLinkUrlString": { + "type": "string", + "max": 1024, + "min": 1, + "sensitive": true + }, + "SupplementaryWebLinks": { + "type": "list", + "member": { "shape": "SupplementaryWebLink" }, + "max": 10, + "min": 0 + }, + "SymbolType": { + "type": "string", + "enum": ["DECLARATION", "USAGE"] }, - "SensitiveString":{ - "type":"string", - "sensitive":true + "TaskAssistPlan": { + "type": "list", + "member": { "shape": "TaskAssistPlanStep" }, + "min": 0 }, - "Span":{ - "type":"structure", - "members":{ - "start":{"shape":"SpanStartInteger"}, - "end":{"shape":"SpanEndInteger"} + "TaskAssistPlanStep": { + "type": "structure", + "required": ["filePath", "description"], + "members": { + "filePath": { "shape": "TaskAssistPlanStepFilePathString" }, + "description": { "shape": "TaskAssistPlanStepDescriptionString" }, + "startLine": { "shape": "TaskAssistPlanStepStartLineInteger" }, + "endLine": { "shape": "TaskAssistPlanStepEndLineInteger" }, + "action": { "shape": "TaskAssistPlanStepAction" } } }, - "SpanEndInteger":{ - "type":"integer", - "box":true, - "min":0 + "TaskAssistPlanStepAction": { + "type": "string", + "enum": ["MODIFY", "CREATE", "DELETE", "UNKNOWN"] }, - "SpanStartInteger":{ - "type":"integer", - "box":true, - "min":0 + "TaskAssistPlanStepDescriptionString": { + "type": "string", + "max": 1024, + "min": 1 }, - "StartCodeAnalysisRequest":{ - "type":"structure", - "required":[ - "artifacts", - "programmingLanguage" - ], - "members":{ - "artifacts":{"shape":"ArtifactMap"}, - "programmingLanguage":{"shape":"ProgrammingLanguage"}, - "clientToken":{ - "shape":"StartCodeAnalysisRequestClientTokenString", - "idempotencyToken":true - }, - "scope": {"shape": "CodeAnalysisScope"}, - "codeScanName":{"shape":"CodeScanName"} - } + "TaskAssistPlanStepEndLineInteger": { + "type": "integer", + "box": true, + "min": 0 + }, + "TaskAssistPlanStepFilePathString": { + "type": "string", + "max": 1024, + "min": 1 }, - "StartCodeAnalysisRequestClientTokenString":{ - "type":"string", - "max":256, - "min":1 + "TaskAssistPlanStepStartLineInteger": { + "type": "integer", + "box": true, + "min": 0 }, - "StartCodeAnalysisResponse":{ - "type":"structure", - "required":[ - "jobId", - "status" - ], - "members":{ - "jobId":{"shape":"StartCodeAnalysisResponseJobIdString"}, - "status":{"shape":"CodeAnalysisStatus"}, - "errorMessage":{"shape":"SensitiveString"} + "TaskAssistPlanningUploadContext": { + "type": "structure", + "required": ["conversationId"], + "members": { + "conversationId": { "shape": "ConversationId" } } }, - "StartCodeAnalysisResponseJobIdString":{ - "type":"string", - "max":256, - "min":1 + "TelemetryEvent": { + "type": "structure", + "members": { + "userTriggerDecisionEvent": { "shape": "UserTriggerDecisionEvent" }, + "codeCoverageEvent": { "shape": "CodeCoverageEvent" }, + "userModificationEvent": { "shape": "UserModificationEvent" }, + "codeScanEvent": { "shape": "CodeScanEvent" }, + "codeScanRemediationsEvent": { "shape": "CodeScanRemediationsEvent" }, + "metricData": { "shape": "MetricData" }, + "chatAddMessageEvent": { "shape": "ChatAddMessageEvent" }, + "chatInteractWithMessageEvent": { "shape": "ChatInteractWithMessageEvent" }, + "chatUserModificationEvent": { "shape": "ChatUserModificationEvent" }, + "terminalUserInteractionEvent": { "shape": "TerminalUserInteractionEvent" }, + "featureDevEvent": { "shape": "FeatureDevEvent" }, + "inlineChatEvent": { "shape": "InlineChatEvent" } + }, + "union": true }, - "StartTaskAssistCodeGenerationRequest": { - "type":"structure", - "required":[ - "conversationState", - "workspaceState" - ], - "members":{ - "conversationState":{"shape":"ConversationState"}, - "workspaceState":{"shape":"WorkspaceState"} - } + "TerminalUserInteractionEvent": { + "type": "structure", + "members": { + "terminalUserInteractionEventType": { "shape": "TerminalUserInteractionEventType" }, + "terminal": { "shape": "String" }, + "terminalVersion": { "shape": "String" }, + "shell": { "shape": "String" }, + "shellVersion": { "shape": "String" }, + "duration": { "shape": "Integer" }, + "timeToSuggestion": { "shape": "Integer" }, + "isCompletionAccepted": { "shape": "Boolean" }, + "cliToolCommand": { "shape": "String" } + } + }, + "TerminalUserInteractionEventType": { + "type": "string", + "enum": ["CODEWHISPERER_TERMINAL_TRANSLATION_ACTION", "CODEWHISPERER_TERMINAL_COMPLETION_INSERTED"] }, - "StartTaskAssistCodeGenerationResponse": { - "type":"structure", - "required":[ - "conversationId", - "codeGenerationId" - ], - "members":{ - "conversationId":{"shape":"ConversationId"}, - "codeGenerationId":{"shape": "CodeGenerationId"} + "TextDocument": { + "type": "structure", + "required": ["relativeFilePath"], + "members": { + "relativeFilePath": { "shape": "TextDocumentRelativeFilePathString" }, + "programmingLanguage": { "shape": "ProgrammingLanguage" }, + "text": { "shape": "TextDocumentTextString" }, + "documentSymbols": { "shape": "DocumentSymbols" } } }, - "StartTransformationRequest":{ - "type":"structure", - "required":[ - "workspaceState", - "transformationSpec" - ], - "members":{ - "workspaceState":{"shape":"WorkspaceState"}, - "transformationSpec":{"shape":"TransformationSpec"} + "TextDocumentDiagnostic": { + "type": "structure", + "required": ["document", "range", "source", "severity", "message"], + "members": { + "document": { "shape": "TextDocument" }, + "range": { "shape": "Range" }, + "source": { "shape": "SensitiveString" }, + "severity": { "shape": "DiagnosticSeverity" }, + "message": { "shape": "TextDocumentDiagnosticMessageString" } } }, - "StartTransformationResponse":{ - "type":"structure", - "required":["transformationJobId"], - "members":{ - "transformationJobId":{"shape":"TransformationJobId"} - } + "TextDocumentDiagnosticMessageString": { + "type": "string", + "max": 1024, + "min": 0, + "sensitive": true }, - "StepId":{ - "type":"string", - "max":126, - "min":1 + "TextDocumentRelativeFilePathString": { + "type": "string", + "max": 4096, + "min": 1, + "sensitive": true }, - "StopTransformationRequest":{ - "type":"structure", - "required":["transformationJobId"], - "members":{ - "transformationJobId":{"shape":"TransformationJobId"} - } + "TextDocumentTextString": { + "type": "string", + "max": 10240, + "min": 0, + "sensitive": true }, - "StopTransformationResponse":{ - "type":"structure", - "required":["transformationStatus"], - "members":{ - "transformationStatus":{"shape":"TransformationStatus"} - } + "ThrottlingException": { + "type": "structure", + "required": ["message"], + "members": { + "message": { "shape": "String" } + }, + "exception": true, + "retryable": { "throttling": true } }, - "String":{"type":"string"}, - "SuggestionState":{ - "type":"string", - "enum":[ - "ACCEPT", - "REJECT", - "DISCARD", - "EMPTY" + "Timestamp": { "type": "timestamp" }, + "TransformationDotNetRuntimeEnv": { + "type": "string", + "enum": [ + "NET_FRAMEWORK_V_3_5", + "NET_FRAMEWORK_V_4_0", + "NET_FRAMEWORK_V_4_5", + "NET_FRAMEWORK_V_4_5_1", + "NET_FRAMEWORK_V_4_5_2", + "NET_FRAMEWORK_V_4_6", + "NET_FRAMEWORK_V_4_6_1", + "NET_FRAMEWORK_V_4_6_2", + "NET_FRAMEWORK_V_4_7", + "NET_FRAMEWORK_V_4_7_1", + "NET_FRAMEWORK_V_4_7_2", + "NET_FRAMEWORK_V_4_8", + "NET_FRAMEWORK_V_4_8_1", + "NET_CORE_APP_1_0", + "NET_CORE_APP_1_1", + "NET_CORE_APP_2_0", + "NET_CORE_APP_2_1", + "NET_CORE_APP_2_2", + "NET_CORE_APP_3_0", + "NET_CORE_APP_3_1", + "NET_5_0", + "NET_6_0", + "NET_7_0", + "NET_8_0" ] }, - "SupplementalContext":{ - "type":"structure", - "required":[ - "filePath", - "content" - ], - "members":{ - "filePath":{"shape":"SupplementalContextFilePathString"}, - "content":{"shape":"SupplementalContextContentString"} + "TransformationDownloadArtifact": { + "type": "structure", + "members": { + "downloadArtifactType": { "shape": "TransformationDownloadArtifactType" }, + "downloadArtifactId": { "shape": "ArtifactId" } } }, - "SupplementalContextContentString":{ - "type":"string", - "max":10240, - "min":1, - "sensitive":true - }, - "SupplementalContextFilePathString":{ - "type":"string", - "max":1024, - "min":1, - "sensitive":true - }, - "SupplementalContextList":{ - "type":"list", - "member":{"shape":"SupplementalContext"}, - "max":5, - "min":0 + "TransformationDownloadArtifactType": { + "type": "string", + "enum": ["ClientInstructions", "Logs", "GeneratedCode"] }, - "SupplementaryWebLink":{ - "type":"structure", - "required":[ - "url", - "title" - ], - "members":{ - "url":{"shape":"SupplementaryWebLinkUrlString"}, - "title":{"shape":"SupplementaryWebLinkTitleString"}, - "snippet":{"shape":"SupplementaryWebLinkSnippetString"} - } - }, - "SupplementaryWebLinkSnippetString":{ - "type":"string", - "max":1024, - "min":1, - "sensitive":true - }, - "SupplementaryWebLinkTitleString":{ - "type":"string", - "max":1024, - "min":1, - "sensitive":true - }, - "SupplementaryWebLinkUrlString":{ - "type":"string", - "max":1024, - "min":1, - "sensitive":true - }, - "SupplementaryWebLinks":{ - "type":"list", - "member":{"shape":"SupplementaryWebLink"}, - "max":10, - "min":0 - }, - "SymbolType":{ - "type":"string", - "enum":[ - "DECLARATION", - "USAGE" - ] + "TransformationDownloadArtifacts": { + "type": "list", + "member": { "shape": "TransformationDownloadArtifact" }, + "max": 10, + "min": 0 }, - "TelemetryEvent":{ - "type":"structure", - "members":{ - "userTriggerDecisionEvent":{"shape":"UserTriggerDecisionEvent"}, - "codeCoverageEvent":{"shape":"CodeCoverageEvent"}, - "userModificationEvent":{"shape":"UserModificationEvent"}, - "codeScanEvent":{"shape":"CodeScanEvent"}, - "codeScanRemediationsEvent": { "shape": "CodeScanRemediationsEvent" }, - "metricData":{"shape":"MetricData"}, - "chatAddMessageEvent": { "shape": "ChatAddMessageEvent" }, - "chatInteractWithMessageEvent": { "shape": "ChatInteractWithMessageEvent" }, - "chatUserModificationEvent": { "shape": "ChatUserModificationEvent" }, - "featureDevEvent": { "shape": "FeatureDevEvent" } - }, - "union":true + "TransformationJavaRuntimeEnv": { + "type": "string", + "enum": ["JVM_8", "JVM_11", "JVM_17"] }, - "TextDocument":{ - "type":"structure", - "required":["relativeFilePath"], - "members":{ - "relativeFilePath":{"shape":"TextDocumentRelativeFilePathString"}, - "programmingLanguage":{"shape":"ProgrammingLanguage"}, - "text":{"shape":"TextDocumentTextString"}, - "documentSymbols":{"shape":"DocumentSymbols"} + "TransformationJob": { + "type": "structure", + "members": { + "jobId": { "shape": "TransformationJobId" }, + "transformationSpec": { "shape": "TransformationSpec" }, + "status": { "shape": "TransformationStatus" }, + "reason": { "shape": "String" }, + "creationTime": { "shape": "Timestamp" }, + "startExecutionTime": { "shape": "Timestamp" }, + "endExecutionTime": { "shape": "Timestamp" } } }, - "TextDocumentDiagnostic":{ - "type":"structure", - "required":[ - "document", - "range", - "source", - "severity", - "message" - ], - "members":{ - "document":{"shape":"TextDocument"}, - "range":{"shape":"Range"}, - "source":{"shape":"SensitiveString"}, - "severity":{"shape":"DiagnosticSeverity"}, - "message":{"shape":"TextDocumentDiagnosticMessageString"} - } - }, - "TextDocumentDiagnosticMessageString":{ - "type":"string", - "max":1024, - "min":0, - "sensitive":true - }, - "TextDocumentRelativeFilePathString":{ - "type":"string", - "max":4096, - "min":1, - "sensitive":true - }, - "TextDocumentTextString":{ - "type":"string", - "max":10240, - "min":0, - "sensitive":true - }, - "ThrottlingException":{ - "type":"structure", - "required":["message"], - "members":{ - "message":{"shape":"String"} - }, - "exception":true, - "retryable":{"throttling":true} + "TransformationJobId": { + "type": "string", + "max": 128, + "min": 1 }, - "ServiceQuotaExceededException":{ - "type":"structure", - "required":["message"], - "members":{ - "message":{"shape":"String"} - }, - "exception":true, - "retryable":{"throttling":true} + "TransformationLanguage": { + "type": "string", + "enum": ["JAVA_8", "JAVA_11", "JAVA_17", "C_SHARP", "COBOL", "PL_I", "JCL"] }, - "TimeBetweenChunks": { + "TransformationLanguages": { "type": "list", - "member": { "shape": "Double" }, - "max": 100, - "min": 0 + "member": { "shape": "TransformationLanguage" } }, - "Timestamp":{"type":"timestamp"}, - "TransformationDownloadArtifact":{ - "type":"structure", - "members":{ - "downloadArtifactType":{"shape":"TransformationDownloadArtifactType"}, - "downloadArtifactId":{"shape":"ArtifactId"} + "TransformationMainframeRuntimeEnv": { + "type": "string", + "enum": ["MAINFRAME"] + }, + "TransformationOperatingSystemFamily": { + "type": "string", + "enum": ["WINDOWS", "LINUX"] + }, + "TransformationPlan": { + "type": "structure", + "required": ["transformationSteps"], + "members": { + "transformationSteps": { "shape": "TransformationSteps" } } }, - "TransformationDownloadArtifactType":{ - "type":"string", - "enum":[ - "ClientInstructions", - "Logs" - ] + "TransformationPlatformConfig": { + "type": "structure", + "members": { + "operatingSystemFamily": { "shape": "TransformationOperatingSystemFamily" } + } }, - "TransformationDownloadArtifacts":{ - "type":"list", - "member":{"shape":"TransformationDownloadArtifact"}, - "max":10, - "min":0 + "TransformationProgressUpdate": { + "type": "structure", + "required": ["name", "status"], + "members": { + "name": { "shape": "String" }, + "status": { "shape": "TransformationProgressUpdateStatus" }, + "description": { "shape": "String" }, + "startTime": { "shape": "Timestamp" }, + "endTime": { "shape": "Timestamp" }, + "downloadArtifacts": { "shape": "TransformationDownloadArtifacts" } + } }, - "TransformationJob":{ - "type":"structure", - "members":{ - "jobId":{"shape":"TransformationJobId"}, - "transformationSpec":{"shape":"TransformationSpec"}, - "status":{"shape":"TransformationStatus"}, - "reason":{"shape":"String"}, - "creationTime":{"shape":"Timestamp"}, - "startExecutionTime":{"shape":"Timestamp"}, - "endExecutionTime":{"shape":"Timestamp"} - } - }, - "TransformationJobId":{ - "type":"string", - "max":128, - "min":1 - }, - "TransformationLanguage":{ - "type":"string", - "enum":[ - "JAVA_8", - "JAVA_11", - "JAVA_17" - ] + "TransformationProgressUpdateStatus": { + "type": "string", + "enum": ["IN_PROGRESS", "COMPLETED", "FAILED", "PAUSED", "AWAITING_CLIENT_ACTION"] }, - "TransformationPlan":{ - "type":"structure", - "required":["transformationSteps"], - "members":{ - "transformationSteps":{"shape":"TransformationSteps"} + "TransformationProjectArtifactDescriptor": { + "type": "structure", + "members": { + "sourceCodeArtifact": { "shape": "TransformationSourceCodeArtifactDescriptor" } + }, + "union": true + }, + "TransformationProjectState": { + "type": "structure", + "members": { + "language": { "shape": "TransformationLanguage" }, + "runtimeEnv": { "shape": "TransformationRuntimeEnv" }, + "platformConfig": { "shape": "TransformationPlatformConfig" }, + "projectArtifact": { "shape": "TransformationProjectArtifactDescriptor" } } }, - "TransformationProgressUpdate":{ - "type":"structure", - "required":[ - "name", - "status" - ], - "members":{ - "name":{"shape":"String"}, - "status":{"shape":"TransformationProgressUpdateStatus"}, - "description":{"shape":"String"}, - "startTime":{"shape":"Timestamp"}, - "endTime":{"shape":"Timestamp"}, - "downloadArtifacts":{"shape":"TransformationDownloadArtifacts"} - } - }, - "TransformationProgressUpdateStatus":{ - "type":"string", - "enum":[ - "IN_PROGRESS", - "COMPLETED", - "FAILED", - "PAUSED" - ] + "TransformationRuntimeEnv": { + "type": "structure", + "members": { + "java": { "shape": "TransformationJavaRuntimeEnv" }, + "dotNet": { "shape": "TransformationDotNetRuntimeEnv" }, + "mainframe": { "shape": "TransformationMainframeRuntimeEnv" } + }, + "union": true }, - "TransformationProjectState":{ - "type":"structure", - "members":{ - "language":{"shape":"TransformationLanguage"} + "TransformationSourceCodeArtifactDescriptor": { + "type": "structure", + "members": { + "languages": { "shape": "TransformationLanguages" }, + "runtimeEnv": { "shape": "TransformationRuntimeEnv" } } }, - "TransformationSpec":{ - "type":"structure", - "members":{ - "transformationType":{"shape":"TransformationType"}, - "source":{"shape":"TransformationProjectState"}, - "target":{"shape":"TransformationProjectState"} + "TransformationSpec": { + "type": "structure", + "members": { + "transformationType": { "shape": "TransformationType" }, + "source": { "shape": "TransformationProjectState" }, + "target": { "shape": "TransformationProjectState" } } }, - "TransformationStatus":{ - "type":"string", - "enum":[ + "TransformationStatus": { + "type": "string", + "enum": [ "CREATED", "ACCEPTED", "REJECTED", @@ -1797,140 +1976,123 @@ "RESUMED" ] }, - "TransformationStep":{ - "type":"structure", - "required":[ - "id", - "name", - "description", - "status" - ], - "members":{ - "id":{"shape":"StepId"}, - "name":{"shape":"String"}, - "description":{"shape":"String"}, - "status":{"shape":"TransformationStepStatus"}, - "progressUpdates":{"shape":"ProgressUpdates"}, - "startTime":{"shape":"Timestamp"}, - "endTime":{"shape":"Timestamp"} - } - }, - "TransformationStepStatus":{ - "type":"string", - "enum":[ - "CREATED", - "COMPLETED", - "PARTIALLY_COMPLETED", - "STOPPED", - "FAILED" - ] + "TransformationStep": { + "type": "structure", + "required": ["id", "name", "description", "status"], + "members": { + "id": { "shape": "StepId" }, + "name": { "shape": "String" }, + "description": { "shape": "String" }, + "status": { "shape": "TransformationStepStatus" }, + "progressUpdates": { "shape": "ProgressUpdates" }, + "startTime": { "shape": "Timestamp" }, + "endTime": { "shape": "Timestamp" } + } }, - "TransformationSteps":{ - "type":"list", - "member":{"shape":"TransformationStep"} + "TransformationStepStatus": { + "type": "string", + "enum": ["CREATED", "COMPLETED", "PARTIALLY_COMPLETED", "STOPPED", "FAILED", "PAUSED"] }, - "TransformationType":{ - "type":"string", - "enum":["LANGUAGE_UPGRADE"] + "TransformationSteps": { + "type": "list", + "member": { "shape": "TransformationStep" } }, - "TransformationUploadArtifactType":{ - "type":"string", - "enum":["Dependencies"] + "TransformationType": { + "type": "string", + "enum": ["LANGUAGE_UPGRADE", "DOCUMENT_GENERATION"] }, - "TransformationUploadContext":{ - "type":"structure", - "required":[ - "jobId", - "uploadArtifactType" - ], - "members":{ - "jobId":{"shape":"TransformationJobId"}, - "uploadArtifactType":{"shape":"TransformationUploadArtifactType"} - } + "TransformationUploadArtifactType": { + "type": "string", + "enum": ["Dependencies", "ClientBuildResult"] }, - "TaskAssistPlanningUploadContext": { + "TransformationUploadContext": { "type": "structure", - "required": ["conversationId"], + "required": ["jobId", "uploadArtifactType"], "members": { - "conversationId": { "shape": "ConversationId" } + "jobId": { "shape": "TransformationJobId" }, + "uploadArtifactType": { "shape": "TransformationUploadArtifactType" } } }, - "TransformationUserActionStatus":{ - "type":"string", - "enum":[ - "COMPLETED", - "REJECTED" - ] + "TransformationUserActionStatus": { + "type": "string", + "enum": ["COMPLETED", "REJECTED"] }, - "UUID":{ - "type":"string", - "max":36, - "min":36 + "UUID": { + "type": "string", + "max": 36, + "min": 36 }, - "UploadContext":{ - "type":"structure", - "members":{ - "taskAssistPlanningUploadContext":{"shape":"TaskAssistPlanningUploadContext"}, - "transformationUploadContext":{"shape":"TransformationUploadContext"}, - "codeAnalysisUploadContext":{"shape":"CodeAnalysisUploadContext"} + "UploadContext": { + "type": "structure", + "members": { + "taskAssistPlanningUploadContext": { "shape": "TaskAssistPlanningUploadContext" }, + "transformationUploadContext": { "shape": "TransformationUploadContext" }, + "codeAnalysisUploadContext": { "shape": "CodeAnalysisUploadContext" } }, - "union":true + "union": true }, - "UploadId":{ - "type":"string", - "max":128, - "min":1 + "UploadId": { + "type": "string", + "max": 128, + "min": 1 }, "UploadIntent": { "type": "string", - "enum": ["TRANSFORMATION", "TASK_ASSIST_PLANNING", "AUTOMATIC_FILE_SECURITY_SCAN", "FULL_PROJECT_SECURITY_SCAN"] + "enum": [ + "TRANSFORMATION", + "TASK_ASSIST_PLANNING", + "AUTOMATIC_FILE_SECURITY_SCAN", + "FULL_PROJECT_SECURITY_SCAN" + ] }, - "UserContext":{ - "type":"structure", - "required":[ - "ideCategory", - "operatingSystem", - "product" - ], - "members":{ - "ideCategory":{"shape":"IdeCategory"}, - "operatingSystem":{"shape":"OperatingSystem"}, - "product":{"shape":"UserContextProductString"}, - "clientId":{"shape":"UUID"}, - "ideVersion":{"shape":"String"} + "UserContext": { + "type": "structure", + "required": ["ideCategory", "operatingSystem", "product"], + "members": { + "ideCategory": { "shape": "IdeCategory" }, + "operatingSystem": { "shape": "OperatingSystem" }, + "product": { "shape": "UserContextProductString" }, + "clientId": { "shape": "UUID" }, + "ideVersion": { "shape": "String" } } }, - "UserContextProductString":{ - "type":"string", - "max":128, - "min":1, - "pattern":"[-a-zA-Z0-9._]*" + "UserContextProductString": { + "type": "string", + "max": 128, + "min": 1, + "pattern": "[-a-zA-Z0-9._]*" }, - "UserInputMessage":{ - "type":"structure", - "required":["content"], - "members":{ - "content":{"shape":"UserInputMessageContentString"}, - "userInputMessageContext":{"shape":"UserInputMessageContext"}, - "userIntent":{"shape":"UserIntent"} + "UserInputMessage": { + "type": "structure", + "required": ["content"], + "members": { + "content": { "shape": "UserInputMessageContentString" }, + "userInputMessageContext": { "shape": "UserInputMessageContext" }, + "userIntent": { "shape": "UserIntent" } } }, - "UserInputMessageContentString":{ - "type":"string", - "max":4096, - "min":0, - "sensitive":true + "UserInputMessageContentString": { + "type": "string", + "max": 4096, + "min": 0, + "sensitive": true }, - "UserInputMessageContext":{ - "type":"structure", - "members":{ - "editorState":{"shape":"EditorState"}, - "diagnostic":{"shape":"Diagnostic"} + "UserInputMessageContext": { + "type": "structure", + "members": { + "editorState": { "shape": "EditorState" }, + "shellState": { "shape": "ShellState" }, + "gitState": { "shape": "GitState" }, + "envState": { "shape": "EnvState" }, + "appStudioContext": { "shape": "AppStudioState" }, + "diagnostic": { "shape": "Diagnostic" }, + "consoleState": { "shape": "ConsoleState" }, + "userSettings": { "shape": "UserSettings" } } }, - "UserIntent":{ - "type":"string", - "enum":[ + "UserIntent": { + "type": "string", + "enum": [ "SUGGEST_ALTERNATE_IMPLEMENTATION", "APPLY_COMMON_BEST_PRACTICES", "IMPROVE_CODE", @@ -1963,9 +2125,15 @@ "unmodifiedAcceptedCharacterCount":{"shape":"PrimitiveInteger"} } }, - "UserTriggerDecisionEvent":{ - "type":"structure", - "required":[ + "UserSettings": { + "type": "structure", + "members": { + "hasConsentedToCrossRegionCalls": { "shape": "Boolean" } + } + }, + "UserTriggerDecisionEvent": { + "type": "structure", + "required": [ "sessionId", "requestId", "programmingLanguage", @@ -1991,30 +2159,33 @@ "acceptedCharacterCount":{"shape":"PrimitiveInteger"} } }, - "ValidationException":{ - "type":"structure", - "required":["message"], - "members":{ - "message":{"shape":"String"}, - "reason":{"shape":"ValidationExceptionReason"} + "ValidationException": { + "type": "structure", + "required": ["message"], + "members": { + "message": { "shape": "String" }, + "reason": { "shape": "ValidationExceptionReason" } }, - "exception":true + "exception": true }, - "ValidationExceptionReason":{ - "type":"string", - "enum":["INVALID_CONVERSATION_ID"] + "ValidationExceptionReason": { + "type": "string", + "enum": ["INVALID_CONVERSATION_ID", "CONTENT_LENGTH_EXCEEDS_THRESHOLD"] }, - "WorkspaceState":{ - "type":"structure", - "required":[ - "uploadId", - "programmingLanguage" - ], - "members":{ - "uploadId":{"shape":"UploadId"}, - "programmingLanguage":{"shape":"ProgrammingLanguage"}, - "contextTruncationScheme":{"shape":"ContextTruncationScheme"} + "WorkspaceState": { + "type": "structure", + "required": ["uploadId", "programmingLanguage"], + "members": { + "uploadId": { "shape": "UploadId" }, + "programmingLanguage": { "shape": "ProgrammingLanguage" }, + "contextTruncationScheme": { "shape": "ContextTruncationScheme" } } + }, + "timeBetweenChunks": { + "type": "list", + "member": { "shape": "Double" }, + "max": 100, + "min": 0 } } }