4
4
package software.aws.toolkits.jetbrains.services.codewhisperer.credentials
5
5
6
6
import com.intellij.openapi.Disposable
7
- import com.intellij.openapi.application.ApplicationManager
8
7
import com.intellij.openapi.components.service
9
8
import com.intellij.openapi.project.Project
10
9
import com.intellij.util.text.nullize
@@ -39,14 +38,9 @@ import software.amazon.awssdk.services.codewhispererruntime.model.TargetCode
39
38
import software.amazon.awssdk.services.codewhispererruntime.model.UserIntent
40
39
import software.aws.toolkits.core.utils.debug
41
40
import software.aws.toolkits.core.utils.getLogger
42
- import software.aws.toolkits.core.utils.warn
43
- import software.aws.toolkits.jetbrains.core.AwsClientManager
44
41
import software.aws.toolkits.jetbrains.core.awsClient
45
- import software.aws.toolkits.jetbrains.core.credentials.AwsBearerTokenConnection
46
- import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnection
47
42
import 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
50
44
import software.aws.toolkits.jetbrains.services.amazonq.codeWhispererUserContext
51
45
import software.aws.toolkits.jetbrains.services.codewhisperer.customization.CodeWhispererCustomization
52
46
import software.aws.toolkits.jetbrains.services.codewhisperer.language.CodeWhispererProgrammingLanguage
@@ -63,7 +57,7 @@ import java.util.concurrent.TimeUnit
63
57
64
58
// As the connection is project-level, we need to make this project-level too
65
59
@Deprecated(" Methods can throw a NullPointerException if callee does not check if connection is valid" )
66
- interface CodeWhispererClientAdaptor : Disposable {
60
+ interface CodeWhispererClientAdaptor {
67
61
val project: Project
68
62
69
63
fun generateCompletionsPaginator (
@@ -262,31 +256,10 @@ interface CodeWhispererClientAdaptor : Disposable {
262
256
}
263
257
264
258
open 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" )
290
263
291
264
override fun generateCompletionsPaginator (firstRequest : GenerateCompletionsRequest ) = sequence<GenerateCompletionsResponse > {
292
265
var nextToken: String? = firstRequest.nextToken()
@@ -809,41 +782,11 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
809
782
requestBuilder.userContext(codeWhispererUserContext())
810
783
}
811
784
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
-
837
785
companion object {
838
786
private val LOG = getLogger<CodeWhispererClientAdaptorImpl >()
839
787
}
840
788
}
841
789
842
- class MockCodeWhispererClientAdaptor (override val project : Project ) : CodeWhispererClientAdaptorImpl(project) {
843
- override fun getBearerClient (oldProviderIdToRemove : String ): CodeWhispererRuntimeClient = project.awsClient()
844
- override fun dispose () {}
845
- }
846
-
847
790
private fun CodewhispererSuggestionState.toCodeWhispererSdkType () = when {
848
791
this == CodewhispererSuggestionState .Accept -> SuggestionState .ACCEPT
849
792
this == CodewhispererSuggestionState .Reject -> SuggestionState .REJECT
0 commit comments