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 @@ -332,9 +332,7 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
it.sessionId(responseContext.sessionId)
it.recommendationLatencyMilliseconds(e2eLatency)
it.triggerToResponseLatencyMilliseconds(requestContext.latencyContext.paginationFirstCompletionTime)
it.perceivedLatencyMilliseconds(
requestContext.latencyContext.getPerceivedLatency(requestContext.triggerTypeInfo.triggerType)
)
it.perceivedLatencyMilliseconds(requestContext.latencyContext.perceivedLatency)
it.suggestionState(suggestionState.toCodeWhispererSdkType())
it.timestamp(Instant.now())
it.suggestionReferenceCount(suggestionReferenceCount)
Expand Down Expand Up @@ -380,6 +378,7 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
it.sessionId(responseContext.sessionId)
it.recommendationLatencyMilliseconds(e2eLatency)
it.triggerToResponseLatencyMilliseconds(sessionContext.latencyContext.paginationFirstCompletionTime)
it.perceivedLatencyMilliseconds(sessionContext.latencyContext.perceivedLatency)
it.suggestionState(suggestionState.toCodeWhispererSdkType())
it.timestamp(Instant.now())
it.suggestionReferenceCount(suggestionReferenceCount)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,6 @@ data class SessionContextNew(
var popup: JBPopup? = null,
var selectedIndex: Int = -1,
val seen: MutableSet<Int> = mutableSetOf(),
var isFirstTimeShowingPopup: Boolean = true,
var toBeRemovedHighlighter: RangeHighlighter? = null,
var insertEndOffset: Int = -1,
var popupOffset: Int = -1,
Expand Down Expand Up @@ -278,6 +277,7 @@ data class LatencyContext(
var codewhispererPreprocessingEnd: Long = 0L,

var paginationFirstCompletionTime: Double = 0.0,
var perceivedLatency: Double = 0.0,

var codewhispererPostprocessingStart: Long = 0L,
var codewhispererPostprocessingEnd: Long = 0L,
Expand Down Expand Up @@ -316,10 +316,9 @@ data class LatencyContext(
if (triggerType == CodewhispererTriggerType.OnDemand) {
getCodeWhispererEndToEndLatency()
} else {
(
TimeUnit.NANOSECONDS.toMillis(codewhispererEndToEndEnd) -
CodeWhispererAutoTriggerService.getInstance().timeAtLastCharTyped.toEpochMilli()
).toDouble()
TimeUnit.NANOSECONDS.toMillis(
codewhispererEndToEndEnd - CodeWhispererAutoTriggerService.getInstance().timeAtLastCharTyped
).toDouble()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,12 +235,14 @@ class CodeWhispererPopupManager {
// emit any events.
// 4. User navigating through the completions or typing as the completion shows. We should not update the latency
// end time and should not emit any events in this case.
if (!CodeWhispererInvocationStatus.getInstance().isPopupActive()) {
states.requestContext.latencyContext.codewhispererPostprocessingEnd = System.nanoTime()
states.requestContext.latencyContext.codewhispererEndToEndEnd = System.nanoTime()
states.requestContext.latencyContext.perceivedLatency =
states.requestContext.latencyContext.getPerceivedLatency(states.requestContext.triggerTypeInfo.triggerType)
}
if (!isRecommendationAdded) {
showPopup(states, sessionContext, states.popup, caretPoint, overlappingLinesCount)
if (!isScrolling) {
states.requestContext.latencyContext.codewhispererPostprocessingEnd = System.nanoTime()
states.requestContext.latencyContext.codewhispererEndToEndEnd = System.nanoTime()
}
}
if (isScrolling ||
CodeWhispererInvocationStatus.getInstance().hasExistingServiceInvocation() ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ class CodeWhispererPopupManagerNew {
val selectedIndex = findNewSelectedIndex(isReverse, sessionContext.selectedIndex + indexChange)

sessionContext.selectedIndex = selectedIndex
sessionContext.isFirstTimeShowingPopup = false

ApplicationManager.getApplication().messageBus.syncPublisher(CODEWHISPERER_POPUP_STATE_CHANGED).stateChanged(
sessionContext
Expand All @@ -137,7 +136,6 @@ class CodeWhispererPopupManagerNew {
) {
if (!updateTypeahead(typeaheadChange, typeaheadAdded)) return
if (!updateSessionSelectedIndex(sessionContext)) return
sessionContext.isFirstTimeShowingPopup = false

ApplicationManager.getApplication().messageBus.syncPublisher(CODEWHISPERER_POPUP_STATE_CHANGED).stateChanged(
sessionContext
Expand All @@ -146,7 +144,6 @@ class CodeWhispererPopupManagerNew {

@RequiresEdt
fun changeStatesForShowing(sessionContext: SessionContextNew, states: InvocationContextNew, recommendationAdded: Boolean = false) {
sessionContext.isFirstTimeShowingPopup = !recommendationAdded
if (recommendationAdded) {
ApplicationManager.getApplication().messageBus.syncPublisher(CODEWHISPERER_POPUP_STATE_CHANGED)
.recommendationAdded(states, sessionContext)
Expand Down Expand Up @@ -210,7 +207,7 @@ class CodeWhispererPopupManagerNew {
updateCodeReferencePanel(sessionContext.project, previews[selectedIndex].detail.recommendation.references())
}

fun render(sessionContext: SessionContextNew, isRecommendationAdded: Boolean, isScrolling: Boolean) {
fun render(sessionContext: SessionContextNew, isRecommendationAdded: Boolean) {
updatePopupPanel(sessionContext)

// There are four cases that render() is called:
Expand All @@ -222,11 +219,16 @@ class CodeWhispererPopupManagerNew {
// emit any events.
// 4. User navigating through the completions or typing as the completion shows. We should not update the latency
// end time and should not emit any events in this case.
if (!CodeWhispererInvocationStatusNew.getInstance().isDisplaySessionActive()) {
sessionContext.latencyContext.codewhispererPostprocessingEnd = System.nanoTime()
sessionContext.latencyContext.codewhispererEndToEndEnd = System.nanoTime()
val triggerTypeOfLastTrigger = CodeWhispererServiceNew.getInstance().getAllPaginationSessions()
.values.filterNotNull().last().requestContext.triggerTypeInfo.triggerType
sessionContext.latencyContext.perceivedLatency =
sessionContext.latencyContext.getPerceivedLatency(triggerTypeOfLastTrigger)
}
if (isRecommendationAdded) return
showPopup(sessionContext)
if (isScrolling) return
sessionContext.latencyContext.codewhispererPostprocessingEnd = System.nanoTime()
sessionContext.latencyContext.codewhispererEndToEndEnd = System.nanoTime()
}

fun dontClosePopupAndRun(runnable: () -> Unit) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,18 +94,15 @@ class CodeWhispererUIChangeListenerNew : CodeWhispererPopupStateChangeListener {
CodeWhispererInlayManagerNew.getInstance().updateInlays(sessionContext, inlayChunks)
CodeWhispererPopupManagerNew.getInstance().render(
sessionContext,
isRecommendationAdded = false,
isScrolling = false
isRecommendationAdded = false
)
}

override fun scrolled(sessionContext: SessionContextNew) {
sessionContext.isFirstTimeShowingPopup = false
CodeWhispererPopupManagerNew.getInstance().render(sessionContext, isRecommendationAdded = false, isScrolling = true)
CodeWhispererPopupManagerNew.getInstance().render(sessionContext, isRecommendationAdded = false)
}

override fun recommendationAdded(states: InvocationContextNew, sessionContext: SessionContextNew) {
sessionContext.isFirstTimeShowingPopup = false
CodeWhispererPopupManagerNew.getInstance().render(sessionContext, isRecommendationAdded = true, isScrolling = false)
CodeWhispererPopupManagerNew.getInstance().render(sessionContext, isRecommendationAdded = true)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class CodeWhispererAutoTriggerService : CodeWhispererAutoTriggerHandler, Disposa

private var lastInvocationTime: Instant? = null
private var lastInvocationLineNum: Int? = null
var timeAtLastCharTyped: Instant = Instant.now()
var timeAtLastCharTyped: Long = System.nanoTime()
private set

init {
Expand All @@ -54,7 +54,7 @@ class CodeWhispererAutoTriggerService : CodeWhispererAutoTriggerHandler, Disposa
// a util wrapper
fun tryInvokeAutoTrigger(editor: Editor, triggerType: CodeWhispererAutomatedTriggerType): Job? {
// only needed for Classifier group, thus calculate it lazily
timeAtLastCharTyped = Instant.now()
timeAtLastCharTyped = System.nanoTime()
val classifierResult: ClassifierResult by lazy { shouldTriggerClassifier(editor, triggerType.telemetryType) }

// we need classifier result for any type of triggering for classifier group for supported languages
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import software.amazon.awssdk.services.codewhispererruntime.paginators.ListAvail
import software.aws.toolkits.jetbrains.core.MockClientManagerRule
import software.aws.toolkits.jetbrains.core.credentials.LegacyManagedBearerSsoConnection
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.SONO_URL
import software.aws.toolkits.jetbrains.services.amazonq.CodeWhispererFeatureConfigService
import kotlin.reflect.full.memberFunctions
Expand Down Expand Up @@ -69,6 +69,7 @@ class CodeWhispererFeatureConfigServiceTest {
}

@Test
@Ignore("Test setup isn't correctly for connection().create<Client>()")
fun `test customizationArnOverride returns non-empty for IdC users if arn in listAvailableCustomizations`() {
testCustomizationArnOverrideABHelper(isIdc = true, isInListAvailableCustomizations = true)
}
Expand Down Expand Up @@ -112,7 +113,7 @@ class CodeWhispererFeatureConfigServiceTest {

projectRule.project.replaceService(
ToolkitConnectionManager::class.java,
mock { on { activeConnectionForFeature(eq(CodeWhispererConnection.getInstance())) } doReturn mockSsoConnection },
mock { on { activeConnectionForFeature(eq(QConnection.getInstance())) } doReturn mockSsoConnection },
disposableRule.disposable
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ fun aRequestContext(
Random.nextLong(),
Random.nextLong(),
Random.nextDouble(),
Random.nextDouble(),
Random.nextLong(),
Random.nextLong(),
Random.nextLong(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ import software.amazon.awssdk.services.codewhispererruntime.CodeWhispererRuntime
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.error
import software.aws.toolkits.core.utils.getLogger
import software.aws.toolkits.jetbrains.core.awsClient
import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnectionManager
import software.aws.toolkits.jetbrains.core.credentials.pinning.QConnection
import software.aws.toolkits.jetbrains.utils.isQExpired

@Service
Expand All @@ -22,12 +25,17 @@ class CodeWhispererFeatureConfigService {
@RequiresBackgroundThread
fun fetchFeatureConfigs(project: Project) {
if (isQExpired(project)) return
val connection = connection(project)
if (connection == null) {
LOG.error { "No connection found even after validating Q connection" }
return
}

LOG.debug { "Fetching feature configs" }
try {
val response = project.awsClient<CodeWhispererRuntimeClient>().listFeatureEvaluations {
val response = connection.getConnectionSettings().awsClient<CodeWhispererRuntimeClient>().listFeatureEvaluations {
it.userContext(codeWhispererUserContext())
}
} ?: return

// Simply force overwrite feature configs from server response, no needed to check existing values.
response.featureEvaluations().forEach {
Expand All @@ -51,7 +59,7 @@ class CodeWhispererFeatureConfigService {
val availableCustomizations =
calculateIfIamIdentityCenterConnection(project) {
try {
project.awsClient<CodeWhispererRuntimeClient>().listAvailableCustomizationsPaginator(
connection.getConnectionSettings().awsClient<CodeWhispererRuntimeClient>().listAvailableCustomizationsPaginator(
ListAvailableCustomizationsRequest.builder().build()
)
.stream()
Expand Down Expand Up @@ -116,6 +124,9 @@ class CodeWhispererFeatureConfigService {
featureConfigs[name]?.value ?: FEATURE_DEFINITIONS[name]?.value
?: FeatureValue.builder().boolValue(false).build()

private fun connection(project: Project) =
ToolkitConnectionManager.getInstance(project).activeConnectionForFeature(QConnection.getInstance())

Comment on lines +127 to +129
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think codewhispererconnection is safer, not sure if population has aged out of that one yet

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are deprecating 233 I think it's probably safe by now

companion object {
fun getInstance(): CodeWhispererFeatureConfigService = service()
private const val TEST_FEATURE_NAME = "testFeature"
Expand Down
Loading