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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type" : "feature",
"description" : "Amazon Q inline: now display completions much more consistently at the user's current caret position"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type" : "feature",
"description" : "Amazon Q inline: now Q completions can co-exist with JetBrains' native IntelliSense completions, when both are showing, press Tab or your customized key shortcuts to accept Q completions and press Enter to accept IntelliSense completions."
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type" : "feature",
"description" : "Amazon Q inline: now shows in a JetBrains native UX of popup and inlay text style"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type" : "feature",
"description" : "Amazon Q inline: The new UX allows configurable shortcuts for accepting completions and navigating through completions. *Caveat: for users using the previous versions, if you have configured your custom key shortcuts for the Q inline before, you will have to re-configure them again in Amazon Q settings due to a change in the keymap actions."
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,34 +26,24 @@ class AuthController {
*/
fun getAuthNeededStates(project: Project): AuthNeededStates {
val connectionState = checkBearerConnectionValidity(project, BearerTokenFeatureSet.Q)
val codeWhispererState = checkBearerConnectionValidity(project, BearerTokenFeatureSet.CODEWHISPERER)

// CW chat is enabled for Builder and IDC users, same for Amazon Q
return AuthNeededStates(
chat = getAuthNeededState(connectionState, codeWhispererState),
amazonQ = getAuthNeededState(connectionState, codeWhispererState)
chat = getAuthNeededState(connectionState),
amazonQ = getAuthNeededState(connectionState)
)
}

private fun getAuthNeededState(
amazonqConnectionState: ActiveConnection,
codeWhispererConnectionState: ActiveConnection,
onlyIamIdcConnection: Boolean = false,
): AuthNeededState? =
when (amazonqConnectionState) {
ActiveConnection.NotConnected -> {
if (codeWhispererConnectionState == ActiveConnection.NotConnected) {
AuthNeededState(
message = message("q.connection.disconnected"),
authType = AuthFollowUpType.FullAuth,
)
} else {
// There is a connection for codewhisperer, but it's not valid for Q
AuthNeededState(
message = message("q.connection.need_scopes"),
authType = AuthFollowUpType.MissingScopes,
)
}
AuthNeededState(
message = message("q.connection.disconnected"),
authType = AuthFollowUpType.FullAuth,
)
}

is ActiveConnection.ValidBearer -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,10 @@
instance="software.aws.toolkits.jetbrains.services.codewhisperer.settings.CodeWhispererConfigurable"
/>

<typedHandler implementation="software.aws.toolkits.jetbrains.services.codewhisperer.editor.CodeWhispererTypedHandler"/>
<editorActionHandler action="EditorEnter" implementationClass="software.aws.toolkits.jetbrains.services.codewhisperer.editor.CodeWhispererEnterHandler"
order="first, before editorEnter"/>
<actionPromoter order="last" implementation="software.aws.toolkits.jetbrains.services.codewhisperer.actions.CodeWhispererActionPromoter"/>
<fileEditorProvider implementation="software.aws.toolkits.jetbrains.services.codewhisperer.learn.LearnCodeWhispererEditorProvider"/>

<!-- Inline Completion Provider -->
<inline.completion.provider id="amazon.q" implementation="software.aws.toolkits.jetbrains.services.codewhisperer.popup.QInlineCompletionProvider"/>
</extensions>

<extensions defaultExtensionNs="aws.toolkit.core">
Expand Down Expand Up @@ -90,29 +89,6 @@
text="Invoke Amazon Q Inline Suggestions">
<keyboard-shortcut keymap="$default" first-keystroke="alt C"/>
</action>
<action id="codewhisperer.inline.navigate.previous"
class="software.aws.toolkits.jetbrains.services.codewhisperer.actions.CodeWhispererNavigatePrevAction"
text="Navigate to Previous Inline Suggestion" description="Navigate to previous inline suggestion">
<keyboard-shortcut keymap="$default" first-keystroke="alt OPEN_BRACKET"/>
</action>
<action id="codewhisperer.inline.navigate.next"
class="software.aws.toolkits.jetbrains.services.codewhisperer.actions.CodeWhispererNavigateNextAction"
text="Navigate to Next Inline Suggestion" description="Navigate to next inline suggestion">
<keyboard-shortcut keymap="$default" first-keystroke="alt CLOSE_BRACKET"/>
</action>
<action id="codewhisperer.inline.accept"
class="software.aws.toolkits.jetbrains.services.codewhisperer.actions.CodeWhispererAcceptAction"
text="Accept the Current Inline Suggestion" description="Accept the current inline suggestions">
<keyboard-shortcut keymap="$default" first-keystroke="TAB"/>
</action>
<action id="codewhisperer.inline.force.accept"
class="software.aws.toolkits.jetbrains.services.codewhisperer.actions.CodeWhispererForceAcceptAction"
text="Force Accept the Current Amazon Q Suggestion" description="Force accept the current Amazon Q suggestion">
<keyboard-shortcut keymap="Mac OS X" first-keystroke="alt TAB"/>
<keyboard-shortcut keymap="Mac OS X 10.5+" first-keystroke="alt TAB"/>
<keyboard-shortcut keymap="$default" first-keystroke="alt ENTER"/>
</action>


<group id="aws.toolkit.codewhisperer.toolbar.security">
<group id="codewhisperer.toolbar.security.group" icon="AllIcons.Actions.GroupBy" text="Group" popup="true">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.codewhisperer.popup
import com.intellij.codeInsight.inline.completion.InlineCompletionEvent
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor
import software.aws.toolkits.jetbrains.services.codewhisperer.popup.QInlineCompletionProvider.Companion.DATA_KEY_Q_AUTO_TRIGGER_INTELLISENSE

fun InlineCompletionEvent.isManualCall(): Boolean =
this is InlineCompletionEvent.DirectCall && this.context?.getData(DATA_KEY_Q_AUTO_TRIGGER_INTELLISENSE) == false

fun getManualCallEvent(editor: Editor, isIntelliSenseAccept: Boolean): InlineCompletionEvent {
val dataContext = DataContext { dataId ->
when (dataId) {
DATA_KEY_Q_AUTO_TRIGGER_INTELLISENSE.name -> isIntelliSenseAccept
else -> null
}
}
return InlineCompletionEvent.DirectCall(editor, editor.caretModel.currentCaret, dataContext)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.codewhisperer.popup
import com.intellij.codeInsight.inline.completion.InlineCompletionEvent
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.util.UserDataHolderBase
import software.aws.toolkits.jetbrains.services.codewhisperer.popup.QInlineCompletionProvider.Companion.KEY_Q_AUTO_TRIGGER_INTELLISENSE
import software.aws.toolkits.jetbrains.services.codewhisperer.popup.QInlineCompletionProvider.Companion.Q_INLINE_PROVIDER_ID

fun InlineCompletionEvent.isManualCall(): Boolean =
this is InlineCompletionEvent.ManualCall && this.additionalData.getUserData(KEY_Q_AUTO_TRIGGER_INTELLISENSE) == false

fun getManualCallEvent(editor: Editor, isIntelliSenseAccept: Boolean): InlineCompletionEvent {
val data = UserDataHolderBase().apply { this.putUserData(KEY_Q_AUTO_TRIGGER_INTELLISENSE, isIntelliSenseAccept) }
return InlineCompletionEvent.ManualCall(editor, Q_INLINE_PROVIDER_ID, data)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,9 @@ import com.intellij.openapi.components.State
import com.intellij.openapi.components.Storage
import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import org.jetbrains.annotations.ApiStatus
import software.aws.toolkits.core.utils.getLogger
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.CodeWhispererConnection
import software.aws.toolkits.jetbrains.core.credentials.pinning.QConnection
import software.aws.toolkits.jetbrains.core.credentials.sono.isSono
import software.aws.toolkits.jetbrains.core.credentials.sso.bearer.BearerTokenAuthState
import software.aws.toolkits.jetbrains.core.credentials.sso.bearer.BearerTokenProvider
Expand All @@ -38,7 +35,7 @@ class CodeWhispererExplorerActionManager : PersistentStateComponent<CodeWhispere
}

private fun getCodeWhispererConnectionStartUrl(project: Project): String {
val connection = ToolkitConnectionManager.getInstance(project).activeConnectionForFeature(CodeWhispererConnection.getInstance())
val connection = ToolkitConnectionManager.getInstance(project).activeConnectionForFeature(QConnection.getInstance())
return getConnectionStartUrl(connection) ?: CodeWhispererConstants.ACCOUNTLESS_START_URL
}

Expand Down Expand Up @@ -95,22 +92,8 @@ class CodeWhispererExplorerActionManager : PersistentStateComponent<CodeWhispere
actionState.value[CodeWhispererExploreStateType.IsFirstRestartAfterQInstall] = isFirstRestartAfterQInstall
}

@Deprecated("Accountless credential will be removed soon")
@ApiStatus.ScheduledForRemoval
// Will keep it for existing accountless users
/**
* Will be called from CodeWhispererService.showRecommendationInPopup()
* Caller (e.x. CodeWhispererService) should take care if null value returned, popup a notification/hint window or dialog etc.
*/
fun resolveAccessToken(): String? {
if (actionState.token == null) {
LOG.warn { "Logical Error: Try to get access token before token initialization" }
}
return actionState.token
}

fun checkActiveCodeWhispererConnectionType(project: Project): CodeWhispererLoginType {
val conn = ToolkitConnectionManager.getInstance(project).activeConnectionForFeature(CodeWhispererConnection.getInstance()) as? AwsBearerTokenConnection
val conn = ToolkitConnectionManager.getInstance(project).activeConnectionForFeature(QConnection.getInstance()) as? AwsBearerTokenConnection
return conn?.let {
val provider = (it.getConnectionSettings().tokenProvider.delegate as? BearerTokenProvider) ?: return@let CodeWhispererLoginType.Logout

Expand Down Expand Up @@ -148,7 +131,5 @@ class CodeWhispererExplorerActionManager : PersistentStateComponent<CodeWhispere
companion object {
@JvmStatic
fun getInstance(): CodeWhispererExplorerActionManager = service()

private val LOG = getLogger<CodeWhispererExplorerActionManager>()
}
}

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Loading
Loading