44package software.aws.toolkits.jetbrains.services.codewhisperer.credentials
55
66import com.intellij.openapi.Disposable
7- import com.intellij.openapi.application.ApplicationManager
87import com.intellij.openapi.components.service
98import com.intellij.openapi.project.Project
109import com.intellij.util.text.nullize
@@ -39,14 +38,9 @@ import software.amazon.awssdk.services.codewhispererruntime.model.TargetCode
3938import software.amazon.awssdk.services.codewhispererruntime.model.UserIntent
4039import software.aws.toolkits.core.utils.debug
4140import software.aws.toolkits.core.utils.getLogger
42- import software.aws.toolkits.core.utils.warn
43- import software.aws.toolkits.jetbrains.core.AwsClientManager
4441import software.aws.toolkits.jetbrains.core.awsClient
45- import software.aws.toolkits.jetbrains.core.credentials.AwsBearerTokenConnection
46- import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnection
4742import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnectionManager
48- import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnectionManagerListener
49- import software.aws.toolkits.jetbrains.core.credentials.pinning.CodeWhispererConnection
43+ import software.aws.toolkits.jetbrains.core.credentials.pinning.QConnection
5044import software.aws.toolkits.jetbrains.services.amazonq.codeWhispererUserContext
5145import software.aws.toolkits.jetbrains.services.codewhisperer.customization.CodeWhispererCustomization
5246import software.aws.toolkits.jetbrains.services.codewhisperer.language.CodeWhispererProgrammingLanguage
@@ -63,7 +57,7 @@ import java.util.concurrent.TimeUnit
6357
6458// As the connection is project-level, we need to make this project-level too
6559@Deprecated(" Methods can throw a NullPointerException if callee does not check if connection is valid" )
66- interface CodeWhispererClientAdaptor : Disposable {
60+ interface CodeWhispererClientAdaptor {
6761 val project: Project
6862
6963 fun generateCompletionsPaginator (
@@ -262,31 +256,10 @@ interface CodeWhispererClientAdaptor : Disposable {
262256}
263257
264258open class CodeWhispererClientAdaptorImpl (override val project : Project ) : CodeWhispererClientAdaptor {
265- @Volatile
266- private var myBearerClient: CodeWhispererRuntimeClient ? = null
267-
268- init {
269- initClientUpdateListener()
270- }
271-
272- private fun initClientUpdateListener () {
273- ApplicationManager .getApplication().messageBus.connect(this ).subscribe(
274- ToolkitConnectionManagerListener .TOPIC ,
275- object : ToolkitConnectionManagerListener {
276- override fun activeConnectionChanged (newConnection : ToolkitConnection ? ) {
277- if (newConnection is AwsBearerTokenConnection ) {
278- myBearerClient = getBearerClient(newConnection.getConnectionSettings().providerId)
279- }
280- }
281- }
282- )
283- }
284-
285- private fun bearerClient (): CodeWhispererRuntimeClient {
286- if (myBearerClient != null ) return myBearerClient as CodeWhispererRuntimeClient
287- myBearerClient = getBearerClient()
288- return myBearerClient as CodeWhispererRuntimeClient
289- }
259+ fun bearerClient (): CodeWhispererRuntimeClient =
260+ ToolkitConnectionManager .getInstance(project).activeConnectionForFeature(QConnection .getInstance())?.getConnectionSettings()
261+ ?.awsClient<CodeWhispererRuntimeClient >()
262+ ? : throw Exception (" attempt to get bearer client while there is no valid credential" )
290263
291264 override fun generateCompletionsPaginator (firstRequest : GenerateCompletionsRequest ) = sequence<GenerateCompletionsResponse > {
292265 var nextToken: String? = firstRequest.nextToken()
@@ -809,41 +782,11 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
809782 requestBuilder.userContext(codeWhispererUserContext())
810783 }
811784
812- override fun dispose () {
813- myBearerClient?.close()
814- }
815-
816- /* *
817- * Every different SSO/AWS Builder ID connection requires a new client which has its corresponding bearer token provider,
818- * thus we have to create them dynamically.
819- * Invalidate and recycle the old client first, and create a new client with the new connection.
820- * This makes sure when we invoke CW, we always use the up-to-date connection.
821- * In case this fails to close the client, myBearerClient is already set to null thus next time when we invoke CW,
822- * it will go through this again which should get the current up-to-date connection. This stale client would be
823- * unused and stay in memory for a while until eventually closed by ToolkitClientManager.
824- */
825- open fun getBearerClient (oldProviderIdToRemove : String = ""): CodeWhispererRuntimeClient ? {
826- myBearerClient = null
827-
828- val connection = ToolkitConnectionManager .getInstance(project).activeConnectionForFeature(CodeWhispererConnection .getInstance())
829- connection as ? AwsBearerTokenConnection ? : run {
830- LOG .warn { " $connection is not a bearer token connection" }
831- return null
832- }
833-
834- return AwsClientManager .getInstance().getClient<CodeWhispererRuntimeClient >(connection.getConnectionSettings())
835- }
836-
837785 companion object {
838786 private val LOG = getLogger<CodeWhispererClientAdaptorImpl >()
839787 }
840788}
841789
842- class MockCodeWhispererClientAdaptor (override val project : Project ) : CodeWhispererClientAdaptorImpl(project) {
843- override fun getBearerClient (oldProviderIdToRemove : String ): CodeWhispererRuntimeClient = project.awsClient()
844- override fun dispose () {}
845- }
846-
847790private fun CodewhispererSuggestionState.toCodeWhispererSdkType () = when {
848791 this == CodewhispererSuggestionState .Accept -> SuggestionState .ACCEPT
849792 this == CodewhispererSuggestionState .Reject -> SuggestionState .REJECT
0 commit comments