Skip to content

Commit

Permalink
Merge branch 'main' into grouping-strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
ctlai95 authored Jan 31, 2025
2 parents 300e3e0 + a545699 commit 8f44dab
Show file tree
Hide file tree
Showing 45 changed files with 989 additions and 157 deletions.
29 changes: 29 additions & 0 deletions .changes/3.51.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"date" : "2025-01-29",
"version" : "3.51",
"entries" : [ {
"type" : "feature",
"description" : "Amazon Q: Now the Amazon Q suggestions can co-exist with Jetbrains suggestions, with tab behavior configurable in the settings."
}, {
"type" : "feature",
"description" : "Amazon Q: Amazon Q inline now has configurable shortcuts for various actions including accept and browsing through suggestions."
}, {
"type" : "feature",
"description" : "Add setting to allow Q /dev to run code and test commands"
}, {
"type" : "feature",
"description" : "Amazon Q: The suggestion popup will hide by default and will be displayed when the suggestion is being hovered over."
}, {
"type" : "bugfix",
"description" : "Amazon Q /doc: fix open diff in a tab when another modal is open"
}, {
"type" : "bugfix",
"description" : "Amazon Q /test: Fixed an issue which incorrectly caused payload size exceeded exception when collecting project payload files"
}, {
"type" : "bugfix",
"description" : "fix(amazonq): For security reasons, disabled auto linkify for link texts coming in markdown other than [TEXT](URL) format"
}, {
"type" : "bugfix",
"description" : "Fix UI freeze caused by updating workspace index on non background context"
} ]
}

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type" : "feature",
"description" : "Adds event listener for notifying UI that AB feature configurations have been resolved"
}

This file was deleted.

10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
# _3.51_ (2025-01-29)
- **(Feature)** Amazon Q: Now the Amazon Q suggestions can co-exist with Jetbrains suggestions, with tab behavior configurable in the settings.
- **(Feature)** Amazon Q: Amazon Q inline now has configurable shortcuts for various actions including accept and browsing through suggestions.
- **(Feature)** Add setting to allow Q /dev to run code and test commands
- **(Feature)** Amazon Q: The suggestion popup will hide by default and will be displayed when the suggestion is being hovered over.
- **(Bug Fix)** Amazon Q /doc: fix open diff in a tab when another modal is open
- **(Bug Fix)** Amazon Q /test: Fixed an issue which incorrectly caused payload size exceeded exception when collecting project payload files
- **(Bug Fix)** fix(amazonq): For security reasons, disabled auto linkify for link texts coming in markdown other than [TEXT](URL) format
- **(Bug Fix)** Fix UI freeze caused by updating workspace index on non background context

# _3.50_ (2025-01-23)
- **(Feature)** Amazon Q: Updated `/help` command to include re:invent 2024 features
- **(Feature)** Amazon Q: UI improvements through more accurate code syntax highlighting
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# SPDX-License-Identifier: Apache-2.0

# Toolkit Version
toolkitVersion=3.51-SNAPSHOT
toolkitVersion=3.52-SNAPSHOT

# Publish Settings
publishToken=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ import software.aws.toolkits.core.utils.warn
import software.aws.toolkits.jetbrains.core.credentials.AwsBearerTokenConnection
import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnectionManager
import software.aws.toolkits.jetbrains.core.credentials.pinning.QConnection
import software.aws.toolkits.jetbrains.core.credentials.sono.isInternalUser
import software.aws.toolkits.jetbrains.core.gettingstarted.emitUserState
import software.aws.toolkits.jetbrains.services.amazonq.CodeWhispererFeatureConfigService
import software.aws.toolkits.jetbrains.services.amazonq.project.ProjectContextController
import software.aws.toolkits.jetbrains.services.amazonq.toolwindow.AmazonQToolWindow
import software.aws.toolkits.jetbrains.services.amazonq.toolwindow.AmazonQToolWindowFactory
Expand All @@ -36,7 +36,7 @@ class AmazonQStartupActivity : ProjectActivity {
if (ApplicationManager.getApplication().isUnitTestMode) return

ToolkitConnectionManager.getInstance(project).activeConnectionForFeature(QConnection.getInstance())?.let {
if (it is AwsBearerTokenConnection && isInternalUser(it.startUrl)) {
if (it is AwsBearerTokenConnection && CodeWhispererFeatureConfigService.getInstance().getChatWSContext()) {
CodeWhispererSettings.getInstance().toggleProjectContextEnabled(value = true, passive = true)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
package software.aws.toolkits.jetbrains.services.amazonqDoc.controller

import com.intellij.diff.DiffContentFactory
import com.intellij.diff.DiffManager
import com.intellij.diff.chains.SimpleDiffRequestChain
import com.intellij.diff.contents.EmptyContent
import com.intellij.diff.editor.ChainDiffVirtualFile
import com.intellij.diff.editor.DiffEditorTabFilesManager
import com.intellij.diff.requests.SimpleDiffRequest
import com.intellij.diff.util.DiffUserDataKeys
import com.intellij.ide.BrowserUtil
Expand Down Expand Up @@ -398,7 +400,8 @@ class DocController(
val request = SimpleDiffRequest(message.filePath, leftDiffContent, rightDiffContent, null, null)
request.putUserData(DiffUserDataKeys.FORCE_READ_ONLY, true)

DiffManager.getInstance().showDiff(project, request)
val newDiff = ChainDiffVirtualFile(SimpleDiffRequestChain(request), message.filePath)
DiffEditorTabFilesManager.getInstance(context.project).showDiffFile(newDiff, true)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class PrepareDocGenerationState(
var zipFileLength: Long? = null
val nextState: SessionState
try {
val repoZipResult = config.repoContext.getProjectZip()
val repoZipResult = config.repoContext.getProjectZip(false)
val zipFileChecksum = repoZipResult.checksum
zipFileLength = repoZipResult.contentLength
val fileToUpload = repoZipResult.payload
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ const val FEATURE_EVALUATION_PRODUCT_NAME = "FeatureDev"

const val FEATURE_NAME = "Amazon Q Developer Agent for software development"

@Suppress("MaxLineLength")
const val GENERATE_DEV_FILE_PROMPT = "generate a devfile in my repository. Note that you should only use devfile version 2.0.0 and the only supported commands are install, build and test (are all optional). so you may have to bundle some commands together using '&&'. also you can use \"public.ecr.aws/aws-mde/universal-image:latest\" as universal image if you aren’t sure which image to use. here is an example for a node repository (but don't assume it's always a node project. look at the existing repository structure before generating the devfile): schemaVersion: 2.0.0 components: - name: dev container: image: public.ecr.aws/aws-mde/universal-image:latest commands: - id: install exec: component: dev commandLine: \"npm install\" - id: build exec: component: dev commandLine: \"npm run build\" - id: test exec: component: dev commandLine: \"npm run test\""

// Max number of times a user can attempt to retry a code generation request if it fails
const val CODE_GENERATION_RETRY_LIMIT = 3

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,13 @@ import software.aws.toolkits.jetbrains.core.coroutines.EDT
import software.aws.toolkits.jetbrains.services.amazonq.RepoSizeError
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.messages.MessagePublisher
import software.aws.toolkits.jetbrains.services.amazonq.toolwindow.AmazonQToolWindowFactory
import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.CodeIterationLimitException
import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.DEFAULT_RETRY_LIMIT
import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.FEATURE_NAME
import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.FeatureDevException
import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.GENERATE_DEV_FILE_PROMPT
import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.InboundAppMessagesHandler
import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.ModifySourceFolderErrorReason
import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.MonthlyConversationLimitError
Expand Down Expand Up @@ -77,6 +79,7 @@ import software.aws.toolkits.jetbrains.services.codewhisperer.util.content
import software.aws.toolkits.jetbrains.services.cwc.controller.chat.telemetry.FeedbackComment
import software.aws.toolkits.jetbrains.services.cwc.controller.chat.telemetry.getStartUrl
import software.aws.toolkits.jetbrains.services.telemetry.TelemetryService
import software.aws.toolkits.jetbrains.settings.CodeWhispererSettings
import software.aws.toolkits.jetbrains.ui.feedback.FeatureDevFeedbackDialog
import software.aws.toolkits.jetbrains.utils.notifyError
import software.aws.toolkits.resources.message
Expand Down Expand Up @@ -135,6 +138,16 @@ class FeatureDevController(
FollowUpTypes.PROVIDE_FEEDBACK_AND_REGENERATE_CODE -> provideFeedbackAndRegenerateCode(message.tabId)
FollowUpTypes.NEW_TASK -> newTask(message.tabId)
FollowUpTypes.CLOSE_SESSION -> closeSession(message.tabId)
FollowUpTypes.ACCEPT_AUTO_BUILD -> handleDevCommandUserSetting(message.tabId, true)
FollowUpTypes.DENY_AUTO_BUILD -> handleDevCommandUserSetting(message.tabId, false)
FollowUpTypes.GENERATE_DEV_FILE -> {
messenger.sendAnswer(
tabId = message.tabId,
messageType = FeatureDevMessageType.SystemPrompt,
message = message("amazonqFeatureDev.follow_up.generate_dev_file")
)
newTask(tabId = message.tabId, prefilledPrompt = GENERATE_DEV_FILE_PROMPT)
}
}
}

Expand Down Expand Up @@ -440,20 +453,38 @@ class FeatureDevController(
canBeVoted = true
)

messenger.sendSystemPrompt(
tabId = tabId,
followUp = listOf(
FollowUp(
pillText = message("amazonqFeatureDev.follow_up.new_task"),
type = FollowUpTypes.NEW_TASK,
status = FollowUpStatusType.Info
),
val followUps = mutableListOf(
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
),
)

if (!session.context.checkForDevFile()) {
followUps.add(
FollowUp(
pillText = message("amazonqFeatureDev.follow_up.close_session"),
type = FollowUpTypes.CLOSE_SESSION,
pillText = message("amazonqFeatureDev.follow_up.generate_dev_file"),
type = FollowUpTypes.GENERATE_DEV_FILE,
status = FollowUpStatusType.Info
)
)

messenger.sendAnswer(
tabId = tabId,
message = message("amazonqFeatureDev.chat_message.generate_dev_file"),
messageType = FeatureDevMessageType.Answer
)
}

messenger.sendSystemPrompt(
tabId = tabId,
followUp = followUps
)

messenger.sendUpdatePlaceholder(
Expand All @@ -471,9 +502,7 @@ class FeatureDevController(
}
}

private suspend fun newTask(tabId: String, isException: Boolean? = false) {
this.disablePreviousFileList(tabId)

private suspend fun newTask(tabId: String, isException: Boolean? = false, prefilledPrompt: String? = null) {
val session = getSessionInfo(tabId)
val sessionLatency = System.currentTimeMillis() - session.sessionStartTime

Expand All @@ -485,15 +514,30 @@ class FeatureDevController(
chatSessionStorage.deleteSession(tabId)

newTabOpened(tabId)
if (isException != null && !isException) {
messenger.sendAnswer(
tabId = tabId,
messageType = FeatureDevMessageType.Answer,
message = message("amazonqFeatureDev.chat_message.ask_for_new_task")
)

if (prefilledPrompt != null && isException != null && !isException) {
handleChat(tabId = tabId, message = prefilledPrompt)
} else {
if (isException != null && !isException) {
messenger.sendAnswer(
tabId = tabId,
messageType = FeatureDevMessageType.Answer,
message = message("amazonqFeatureDev.chat_message.ask_for_new_task")
)
}
messenger.sendUpdatePlaceholder(tabId = tabId, newPlaceholder = message("amazonqFeatureDev.placeholder.new_plan"))
messenger.sendChatInputEnabledMessage(tabId = tabId, enabled = true)
}
messenger.sendUpdatePlaceholder(tabId = tabId, newPlaceholder = message("amazonqFeatureDev.placeholder.new_plan"))
messenger.sendChatInputEnabledMessage(tabId = tabId, enabled = true)
}

private suspend fun handleDevCommandUserSetting(tabId: String, value: Boolean) {
CodeWhispererSettings.getInstance().toggleAutoBuildFeature(context.project.basePath, value)
messenger.sendAnswer(
tabId = tabId,
message = message("amazonqFeatureDev.chat_message.setting_updated"),
messageType = FeatureDevMessageType.Answer,
)
this.retryRequests(tabId)
}

private suspend fun closeSession(tabId: String) {
Expand Down Expand Up @@ -670,6 +714,7 @@ class FeatureDevController(
try {
logger.debug { "$FEATURE_NAME: Processing message: $message" }
session = getSessionInfo(tabId)
session.latestMessage = message

val credentialState = authController.getAuthNeededStates(context.project).amazonQ
if (credentialState != null) {
Expand All @@ -682,8 +727,18 @@ class FeatureDevController(
return
}

session.preloader(message, messenger)
val codeWhispererSettings = CodeWhispererSettings.getInstance().getAutoBuildSetting()
val hasDevFile = session.context.checkForDevFile()
val isPromptedForAutoBuildFeature = codeWhispererSettings.containsKey(session.context.getWorkspaceRoot())

if (hasDevFile && !isPromptedForAutoBuildFeature) {
promptAllowQCommandsConsent(messenger, tabId)
return
}

session.preloader(messenger)
broadcastQEvent(QFeatureEvent.INVOCATION)

when (session.sessionState.phase) {
SessionStatePhase.CODEGEN -> onCodeGeneration(session, message, tabId)
else -> null
Expand All @@ -696,6 +751,30 @@ class FeatureDevController(
}
}

private suspend fun promptAllowQCommandsConsent(messenger: MessagePublisher, tabID: String) {
messenger.sendAnswer(
tabId = tabID,
message = message("amazonqFeatureDev.chat_message.devFileInRepository"),
messageType = FeatureDevMessageType.Answer
)
messenger.sendAnswer(
tabId = tabID,
messageType = FeatureDevMessageType.SystemPrompt,
followUp = listOf(
FollowUp(
pillText = message("amazonqFeatureDev.follow_up.accept_for_project"),
type = FollowUpTypes.ACCEPT_AUTO_BUILD,
status = FollowUpStatusType.Success
),
FollowUp(
pillText = message("amazonqFeatureDev.follow_up.decline_for_project"),
type = FollowUpTypes.DENY_AUTO_BUILD,
status = FollowUpStatusType.Error
)
)
)
}

private suspend fun retryRequests(tabId: String) {
var session: Session? = null
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,9 @@ enum class FollowUpTypes(
PROVIDE_FEEDBACK_AND_REGENERATE_CODE("ProvideFeedbackAndRegenerateCode"),
NEW_TASK("NewTask"),
CLOSE_SESSION("CloseSession"),
ACCEPT_AUTO_BUILD("AcceptAutoBuild"),
DENY_AUTO_BUILD("DenyAutoBuild"),
GENERATE_DEV_FILE("GenerateDevFile"),
}

// Util classes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util.Cancellat
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
import software.aws.toolkits.jetbrains.settings.CodeWhispererSettings
import software.aws.toolkits.resources.message
import software.aws.toolkits.telemetry.AmazonqTelemetry
import software.aws.toolkits.telemetry.AmazonqUploadIntent
Expand Down Expand Up @@ -48,7 +49,8 @@ class PrepareCodeGenerationState(
messenger.sendAnswerPart(tabId = this.tabID, message = message("amazonqFeatureDev.chat_message.uploading_code"))
messenger.sendUpdatePlaceholder(tabId = this.tabID, newPlaceholder = message("amazonqFeatureDev.chat_message.uploading_code"))

val repoZipResult = config.repoContext.getProjectZip()
val isAutoBuildFeatureEnabled = CodeWhispererSettings.getInstance().isAutoBuildFeatureEnabled(this.config.repoContext.getWorkspaceRoot())
val repoZipResult = config.repoContext.getProjectZip(isAutoBuildFeatureEnabled = isAutoBuildFeatureEnabled)
val zipFileChecksum = repoZipResult.checksum
zipFileLength = repoZipResult.contentLength
val fileToUpload = repoZipResult.payload
Expand Down Expand Up @@ -96,7 +98,7 @@ class PrepareCodeGenerationState(
credentialStartUrl = getStartUrl(config.featureDevService.project)
)
}
// It is essential to interact with the next state outside of try-catch block for the telemetry to capture events for the states separately
// It is essential to interact with the next state outside try-catch block for the telemetry to capture events for the states separately
return nextState.interact(action)
}
}
Loading

0 comments on commit 8f44dab

Please sign in to comment.