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
Expand Up @@ -7,7 +7,6 @@ import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.SystemInfo
import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider
import software.amazon.awssdk.services.codewhisperer.CodeWhispererClient
import software.amazon.awssdk.services.codewhisperer.model.CreateCodeScanRequest
Expand All @@ -25,13 +24,10 @@ import software.amazon.awssdk.services.codewhispererruntime.model.CreateUploadUr
import software.amazon.awssdk.services.codewhispererruntime.model.Dimension
import software.amazon.awssdk.services.codewhispererruntime.model.GenerateCompletionsRequest
import software.amazon.awssdk.services.codewhispererruntime.model.GenerateCompletionsResponse
import software.amazon.awssdk.services.codewhispererruntime.model.IdeCategory
import software.amazon.awssdk.services.codewhispererruntime.model.ListAvailableCustomizationsRequest
import software.amazon.awssdk.services.codewhispererruntime.model.ListFeatureEvaluationsResponse
import software.amazon.awssdk.services.codewhispererruntime.model.OperatingSystem
import software.amazon.awssdk.services.codewhispererruntime.model.SendTelemetryEventResponse
import software.amazon.awssdk.services.codewhispererruntime.model.SuggestionState
import software.amazon.awssdk.services.codewhispererruntime.model.UserContext
import software.amazon.awssdk.services.codewhispererruntime.model.UserIntent
import software.aws.toolkits.core.utils.debug
import software.aws.toolkits.core.utils.getLogger
Expand All @@ -43,6 +39,7 @@ import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnection
import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnectionManager
import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnectionManagerListener
import software.aws.toolkits.jetbrains.core.credentials.pinning.CodeWhispererConnection
import software.aws.toolkits.jetbrains.services.amazonq.codeWhispererUserContext
import software.aws.toolkits.jetbrains.services.codewhisperer.customization.CodeWhispererCustomization
import software.aws.toolkits.jetbrains.services.codewhisperer.explorer.CodeWhispererExplorerActionManager
import software.aws.toolkits.jetbrains.services.codewhisperer.language.CodeWhispererProgrammingLanguage
Expand All @@ -51,10 +48,8 @@ import software.aws.toolkits.jetbrains.services.codewhisperer.service.RequestCon
import software.aws.toolkits.jetbrains.services.codewhisperer.service.RequestContextNew
import software.aws.toolkits.jetbrains.services.codewhisperer.service.ResponseContext
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants.FEATURE_EVALUATION_PRODUCT_NAME
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererUtil.getTelemetryOptOutPreference
import software.aws.toolkits.jetbrains.services.codewhisperer.util.transform
import software.aws.toolkits.jetbrains.services.telemetry.ClientMetadata
import software.aws.toolkits.telemetry.CodewhispererCompletionType
import software.aws.toolkits.telemetry.CodewhispererSuggestionState
import java.time.Instant
Expand Down Expand Up @@ -201,24 +196,6 @@ interface CodeWhispererClientAdaptor : Disposable {
}

open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeWhispererClientAdaptor {
private val codeWhispererUserContext = ClientMetadata.getDefault().let {
val osForCodeWhisperer: 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(osForCodeWhisperer)
.product(FEATURE_EVALUATION_PRODUCT_NAME)
.clientId(it.clientId)
.ideVersion(it.awsVersion)
.build()
}

private val mySigv4Client by lazy { createUnmanagedSigv4Client() }

@Volatile
Expand Down Expand Up @@ -348,7 +325,7 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
}
}
requestBuilder.optOutPreference(getTelemetryOptOutPreference())
requestBuilder.userContext(codeWhispererUserContext)
requestBuilder.userContext(codeWhispererUserContext())
}
}

Expand Down Expand Up @@ -391,7 +368,7 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
}
}
requestBuilder.optOutPreference(getTelemetryOptOutPreference())
requestBuilder.userContext(codeWhispererUserContext)
requestBuilder.userContext(codeWhispererUserContext())
}
}

Expand All @@ -413,7 +390,7 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
}
}
requestBuilder.optOutPreference(getTelemetryOptOutPreference())
requestBuilder.userContext(codeWhispererUserContext)
requestBuilder.userContext(codeWhispererUserContext())
}

override fun sendUserModificationTelemetry(
Expand All @@ -440,7 +417,7 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
}
}
requestBuilder.optOutPreference(getTelemetryOptOutPreference())
requestBuilder.userContext(codeWhispererUserContext)
requestBuilder.userContext(codeWhispererUserContext())
}

override fun sendCodeScanTelemetry(
Expand All @@ -459,7 +436,7 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
}
}
requestBuilder.optOutPreference(getTelemetryOptOutPreference())
requestBuilder.userContext(codeWhispererUserContext)
requestBuilder.userContext(codeWhispererUserContext())
}
override fun sendCodeScanRemediationTelemetry(
language: CodeWhispererProgrammingLanguage?,
Expand Down Expand Up @@ -489,11 +466,11 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
}
}
requestBuilder.optOutPreference(getTelemetryOptOutPreference())
requestBuilder.userContext(codeWhispererUserContext)
requestBuilder.userContext(codeWhispererUserContext())
}

override fun listFeatureEvaluations(): ListFeatureEvaluationsResponse = bearerClient().listFeatureEvaluations {
it.userContext(codeWhispererUserContext)
it.userContext(codeWhispererUserContext())
}

override fun sendMetricDataTelemetry(eventName: String, metadata: Map<String, Any?>): SendTelemetryEventResponse =
Expand All @@ -507,7 +484,7 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
}
}
requestBuilder.optOutPreference(getTelemetryOptOutPreference())
requestBuilder.userContext(codeWhispererUserContext)
requestBuilder.userContext(codeWhispererUserContext())
}

override fun sendChatAddMessageTelemetry(
Expand Down Expand Up @@ -547,7 +524,7 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
}
}
requestBuilder.optOutPreference(getTelemetryOptOutPreference())
requestBuilder.userContext(codeWhispererUserContext)
requestBuilder.userContext(codeWhispererUserContext())
}

override fun sendChatInteractWithMessageTelemetry(
Expand Down Expand Up @@ -576,7 +553,7 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
telemetryEventBuilder.chatInteractWithMessageEvent(event)
}
requestBuilder.optOutPreference(getTelemetryOptOutPreference())
requestBuilder.userContext(codeWhispererUserContext)
requestBuilder.userContext(codeWhispererUserContext())
}

override fun sendChatUserModificationTelemetry(
Expand All @@ -602,7 +579,7 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
}
}
requestBuilder.optOutPreference(getTelemetryOptOutPreference())
requestBuilder.userContext(codeWhispererUserContext)
requestBuilder.userContext(codeWhispererUserContext())
}

override fun dispose() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ import com.intellij.util.xmlb.annotations.Property
import software.amazon.awssdk.services.codewhispererruntime.model.CodeWhispererRuntimeException
import software.aws.toolkits.core.utils.debug
import software.aws.toolkits.core.utils.getLogger
import software.aws.toolkits.jetbrains.services.amazonq.calculateIfIamIdentityCenterConnection
import software.aws.toolkits.jetbrains.services.codewhisperer.credentials.CodeWhispererClientAdaptor
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererFeatureConfigService
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants
import software.aws.toolkits.jetbrains.services.codewhisperer.util.calculateIfIamIdentityCenterConnection
import software.aws.toolkits.jetbrains.utils.notifyInfo
import software.aws.toolkits.jetbrains.utils.notifyWarn
import software.aws.toolkits.jetbrains.utils.pluginAwareExecuteOnPooledThread
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ import com.intellij.openapi.components.Service
import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread
import software.amazon.awssdk.services.codewhispererruntime.CodeWhispererRuntimeClient
import software.amazon.awssdk.services.codewhispererruntime.model.FeatureValue
import software.amazon.awssdk.services.codewhispererruntime.model.ListAvailableCustomizationsRequest
import software.aws.toolkits.core.utils.debug
import software.aws.toolkits.core.utils.getLogger
import software.aws.toolkits.jetbrains.services.codewhisperer.credentials.CodeWhispererClientAdaptor
import software.aws.toolkits.jetbrains.services.codewhisperer.util.calculateIfBIDConnection
import software.aws.toolkits.jetbrains.services.codewhisperer.util.calculateIfIamIdentityCenterConnection
import software.aws.toolkits.jetbrains.core.awsClient
import software.aws.toolkits.jetbrains.services.amazonq.calculateIfBIDConnection
import software.aws.toolkits.jetbrains.services.amazonq.calculateIfIamIdentityCenterConnection
import software.aws.toolkits.jetbrains.services.amazonq.codeWhispererUserContext
import software.aws.toolkits.jetbrains.utils.isQExpired

@Service
Expand All @@ -25,7 +28,9 @@ class CodeWhispererFeatureConfigService {

LOG.debug { "Fetching feature configs" }
try {
val response = CodeWhispererClientAdaptor.getInstance(project).listFeatureEvaluations()
val response = project.awsClient<CodeWhispererRuntimeClient>().listFeatureEvaluations {
it.userContext(codeWhispererUserContext())
}

// Simply force overwrite feature configs from server response, no needed to check existing values.
response.featureEvaluations().forEach {
Expand All @@ -49,7 +54,16 @@ class CodeWhispererFeatureConfigService {
val availableCustomizations =
calculateIfIamIdentityCenterConnection(project) {
try {
CodeWhispererClientAdaptor.getInstance(project).listAvailableCustomizations().map { c -> c.arn }
project.awsClient<CodeWhispererRuntimeClient>().listAvailableCustomizationsPaginator(
ListAvailableCustomizationsRequest.builder().build()
)
.stream()
.toList()
.flatMap { resp ->
resp.customizations().map {
it.arn()
}
}
} catch (e: Exception) {
LOG.debug(e) { "Failed to list available customizations" }
null
Expand All @@ -71,9 +85,11 @@ class CodeWhispererFeatureConfigService {
}

fun getFeatureConfigsTelemetry(): String =
"{${featureConfigs.entries.joinToString(", ") { (name, context) ->
"$name: ${context.variation}"
}}}"
"{${
featureConfigs.entries.joinToString(", ") { (name, context) ->
"$name: ${context.variation}"
}
}}"

// TODO: for all feature variations, define a contract that can be enforced upon the implementation of
// the business logic.
Expand All @@ -88,7 +104,8 @@ class CodeWhispererFeatureConfigService {
// 6) Add a test case for this feature.
fun getTestFeature(): String = getFeatureValueForKey(TEST_FEATURE_NAME).stringValue()

fun getIsDataCollectionEnabled(): Boolean = getFeatureValueForKey(DATA_COLLECTION_FEATURE).stringValue() == "data-collection"
fun getIsDataCollectionEnabled(): Boolean =
getFeatureValueForKey(DATA_COLLECTION_FEATURE).stringValue() == "data-collection"

fun getCustomizationArnOverride(): String = getFeatureValueForKey(CUSTOMIZATION_ARN_OVERRIDE_NAME).stringValue()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import software.aws.toolkits.jetbrains.core.coroutines.projectCoroutineScope
import software.aws.toolkits.jetbrains.services.amazonq.calculateIfIamIdentityCenterConnection
import software.aws.toolkits.jetbrains.services.codewhisperer.codescan.CodeWhispererCodeScanManager
import software.aws.toolkits.jetbrains.services.codewhisperer.customization.CodeWhispererModelConfigurator
import software.aws.toolkits.jetbrains.services.codewhisperer.explorer.CodeWhispererExplorerActionManager
Expand All @@ -20,7 +21,6 @@ import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispe
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants.FEATURE_CONFIG_POLL_INTERVAL_IN_MS
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererUtil.promptReAuth
import software.aws.toolkits.jetbrains.services.codewhisperer.util.calculateIfIamIdentityCenterConnection
import software.aws.toolkits.jetbrains.utils.isQConnected
import software.aws.toolkits.jetbrains.utils.isQExpired
import software.aws.toolkits.jetbrains.utils.pluginAwareExecuteOnPooledThread
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ object CodeWhispererConstants {
const val POPUP_DELAY_CHECK_INTERVAL: Long = 25
const val IDLE_TIME_CHECK_INTERVAL: Long = 25
const val SUPPLEMENTAL_CONTEXT_TIMEOUT = 50L
const val FEATURE_EVALUATION_PRODUCT_NAME = "CodeWhisperer"

val AWSTemplateKeyWordsRegex = Regex("(AWSTemplateFormatVersion|Resources|AWS::|Description)")
val AWSTemplateCaseInsensitiveKeyWordsRegex = Regex("(cloudformation|cfn|template|description)")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,27 +50,6 @@ import software.aws.toolkits.resources.message
import software.aws.toolkits.telemetry.CodewhispererCompletionType
import software.aws.toolkits.telemetry.CodewhispererGettingStartedTask

fun <T> calculateIfIamIdentityCenterConnection(project: Project, calculationTask: (connection: ToolkitConnection) -> T): T? =
ToolkitConnectionManager.getInstance(project).activeConnectionForFeature(CodeWhispererConnection.getInstance())?.let {
calculateIfIamIdentityCenterConnection(it, calculationTask)
}

fun <T> calculateIfIamIdentityCenterConnection(connection: ToolkitConnection, calculationTask: (connection: ToolkitConnection) -> T): T? =
if (connection.isSono()) {
null
} else {
calculationTask(connection)
}

fun <T> calculateIfBIDConnection(project: Project, calculationTask: (connection: ToolkitConnection) -> T): T? =
ToolkitConnectionManager.getInstance(project).activeConnectionForFeature(CodeWhispererConnection.getInstance())?.let {
if (it.isSono()) {
calculationTask(it)
} else {
null
}
}

// Controls the condition to send telemetry event to CodeWhisperer service, currently:
// 1. It will be sent for Builder ID users, only if they have optin telemetry sharing.
// 2. It will be sent for IdC users, regardless of telemetry optout status.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ import software.aws.toolkits.jetbrains.core.credentials.MockCredentialManagerRul
import software.aws.toolkits.jetbrains.core.credentials.MockToolkitAuthManagerRule
import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnectionManager
import software.aws.toolkits.jetbrains.core.credentials.sono.SONO_REGION
import software.aws.toolkits.jetbrains.services.amazonq.FEATURE_EVALUATION_PRODUCT_NAME
import software.aws.toolkits.jetbrains.services.codewhisperer.CodeWhispererTestUtil.metadata
import software.aws.toolkits.jetbrains.services.codewhisperer.CodeWhispererTestUtil.pythonRequest
import software.aws.toolkits.jetbrains.services.codewhisperer.CodeWhispererTestUtil.pythonResponseWithToken
Expand All @@ -87,7 +88,6 @@ import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispe
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererService
import software.aws.toolkits.jetbrains.services.codewhisperer.service.ResponseContext
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants.FEATURE_EVALUATION_PRODUCT_NAME
import software.aws.toolkits.jetbrains.settings.AwsSettings
import software.aws.toolkits.jetbrains.utils.rules.JavaCodeInsightTestFixtureRule
import software.aws.toolkits.telemetry.CodewhispererCompletionType
Expand Down
Loading
Loading