Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prefetch next inline recommendation #5290

Draft
wants to merge 133 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 132 commits
Commits
Show all changes
133 commits
Select commit Hold shift + click to select a range
d3ba908
reinvent 2024
samgst-amazon Dec 3, 2024
2b4656e
Updating version to 3.43
Dec 3, 2024
e0ddf0b
Updating SNAPSHOT version to 3.44-SNAPSHOT
Dec 3, 2024
b779722
Merge public/main to private/staging
aws-toolkit-automation Dec 3, 2024
f9284bd
Merge public/main to private/staging
aws-toolkit-automation Dec 3, 2024
75ff2a8
Merge public/main to private/staging
aws-toolkit-automation Dec 3, 2024
7a4693f
Merge public/main to private/staging
aws-toolkit-automation Dec 3, 2024
88347ed
Merge public/main to private/staging
aws-toolkit-automation Dec 3, 2024
3c886d2
Merge public/main to private/staging
aws-toolkit-automation Dec 3, 2024
4a946b9
Merge public/main to private/staging
aws-toolkit-automation Dec 3, 2024
f54fc34
Merge public/main to private/staging
aws-toolkit-automation Dec 3, 2024
43fc8d5
Merge public/main to private/staging
aws-toolkit-automation Dec 3, 2024
af913a2
Merge public/main to private/staging
aws-toolkit-automation Dec 4, 2024
a57190f
Merge public/main to private/staging
aws-toolkit-automation Dec 4, 2024
84aa418
Merge public/main to private/staging
aws-toolkit-automation Dec 4, 2024
142c94f
Merge public/main to private/staging
aws-toolkit-automation Dec 5, 2024
a87d570
Merge public/main to private/staging
aws-toolkit-automation Dec 5, 2024
da8644b
Merge public/main to private/staging
aws-toolkit-automation Dec 6, 2024
f3096cc
Merge public/main to private/staging
aws-toolkit-automation Dec 6, 2024
cf53dce
Merge public/main to private/staging
aws-toolkit-automation Dec 6, 2024
99d07db
Merge public/main to private/staging
aws-toolkit-automation Dec 6, 2024
cd084e1
Merge public/main to private/staging
aws-toolkit-automation Dec 6, 2024
397812b
Merge public/main to private/staging
aws-toolkit-automation Dec 6, 2024
cc908ef
Merge public/main to private/staging
aws-toolkit-automation Dec 9, 2024
0f1cbde
Merge public/main to private/staging
aws-toolkit-automation Dec 9, 2024
8704181
Merge public/main to private/staging
aws-toolkit-automation Dec 9, 2024
73a77f1
Merge public/main to private/staging
aws-toolkit-automation Dec 9, 2024
4fa59f2
Merge public/main to private/staging
aws-toolkit-automation Dec 9, 2024
0f84fc9
Merge public/main to private/staging
aws-toolkit-automation Dec 9, 2024
a558734
Merge public/main to private/staging
aws-toolkit-automation Dec 10, 2024
eb58762
Merge public/main to private/staging
aws-toolkit-automation Dec 11, 2024
a797dd4
Merge public/main to private/staging
aws-toolkit-automation Dec 11, 2024
fb8785b
Merge public/main to private/staging
aws-toolkit-automation Dec 11, 2024
c0f22e2
Merge public/main to private/staging
aws-toolkit-automation Dec 11, 2024
ed30848
Merge public/main to private/staging
aws-toolkit-automation Dec 11, 2024
18a3a1a
Merge public/main to private/staging
aws-toolkit-automation Dec 12, 2024
88f63b4
Merge public/main to private/staging
aws-toolkit-automation Dec 12, 2024
8f13841
Merge public/main to private/staging
aws-toolkit-automation Dec 12, 2024
4a9595b
Merge public/main to private/staging
aws-toolkit-automation Dec 12, 2024
f0659dc
Merge public/main to private/staging
aws-toolkit-automation Dec 12, 2024
e0819c2
Merge public/main to private/staging
aws-toolkit-automation Dec 12, 2024
ea4c279
Merge public/main to private/staging
aws-toolkit-automation Dec 13, 2024
3e817df
Merge public/main to private/staging
aws-toolkit-automation Dec 13, 2024
07741c1
Merge public/main to private/staging
aws-toolkit-automation Dec 13, 2024
d9795fb
Merge public/main to private/staging
aws-toolkit-automation Dec 13, 2024
b1b5c4d
Merge public/main to private/staging
aws-toolkit-automation Dec 14, 2024
2f801e6
Merge public/main to private/staging
aws-toolkit-automation Dec 17, 2024
7c119b6
Merge public/main to private/staging
aws-toolkit-automation Dec 18, 2024
a38455d
Merge public/main to private/staging
aws-toolkit-automation Dec 19, 2024
6e19c00
Merge public/main to private/staging
aws-toolkit-automation Dec 19, 2024
e44dc3a
Merge public/main to private/staging
aws-toolkit-automation Dec 20, 2024
8bd524f
Merge public/main to private/staging
aws-toolkit-automation Dec 23, 2024
b8f5ca9
Merge public/main to private/staging
aws-toolkit-automation Dec 24, 2024
8f38495
Merge public/main to private/staging
aws-toolkit-automation Dec 31, 2024
2806ffb
Merge public/main to private/staging
aws-toolkit-automation Jan 3, 2025
3f0a5e7
Merge public/main to private/staging
aws-toolkit-automation Jan 3, 2025
60b7039
Merge public/main to private/staging
aws-toolkit-automation Jan 7, 2025
59a79a6
Merge public/main to private/staging
aws-toolkit-automation Jan 7, 2025
fd901db
Merge public/main to private/staging
aws-toolkit-automation Jan 7, 2025
fba3832
Merge public/main to private/staging
aws-toolkit-automation Jan 7, 2025
aab84a7
Merge public/main to private/staging
aws-toolkit-automation Jan 8, 2025
53ea267
add main functions, but with bug that next popup doesn't work
evanliu048 Jan 8, 2025
9499ea0
Merge public/main to private/staging
aws-toolkit-automation Jan 8, 2025
9978b8e
Merge public/main to private/staging
aws-toolkit-automation Jan 8, 2025
1e28cd1
finish funcitnal parts
evanliu048 Jan 8, 2025
4942279
Merge public/main to private/staging
aws-toolkit-automation Jan 8, 2025
221ba69
reconstruct request
evanliu048 Jan 9, 2025
daf9688
Merge public/main to private/staging
aws-toolkit-automation Jan 9, 2025
3a430cc
Merge public/main to private/staging
aws-toolkit-automation Jan 9, 2025
9723e2a
Merge public/main to private/staging
aws-toolkit-automation Jan 9, 2025
639db28
Merge public/main to private/staging
aws-toolkit-automation Jan 9, 2025
d9f4083
fix sendServiceInvocationEvent(with 4 qs)
evanliu048 Jan 9, 2025
0128423
Merge public/main to private/staging
aws-toolkit-automation Jan 9, 2025
e38b3cf
Merge public/main to private/staging
aws-toolkit-automation Jan 9, 2025
1b1f8db
finish basic telemetry need to handle subsequent response
evanliu048 Jan 10, 2025
4b8e310
Merge public/main to private/staging
aws-toolkit-automation Jan 10, 2025
3e5a6e9
Merge public/main to private/staging
aws-toolkit-automation Jan 10, 2025
1f62c49
Merge public/main to private/staging
aws-toolkit-automation Jan 10, 2025
4b9993a
Merge public/main to private/staging
aws-toolkit-automation Jan 10, 2025
629e929
add user&triggerdecision event for edge cases
evanliu048 Jan 10, 2025
b6564fa
delete print
evanliu048 Jan 10, 2025
df3cab4
Merge public/main to private/staging
aws-toolkit-automation Jan 10, 2025
d50a7bb
revise formart
evanliu048 Jan 10, 2025
30168ae
revise code quality
evanliu048 Jan 10, 2025
fe1bf11
Merge public/main to private/staging
aws-toolkit-automation Jan 13, 2025
b8ab355
Merge branch 'staging' into aldabraInOldService
evanliu048 Jan 13, 2025
cc8288f
delete adding one next line logic when calculation next caret
evanliu048 Jan 13, 2025
14ff542
Merge branch 'aldabraInOldService' of github.com:evanliu048/aws-toolk…
evanliu048 Jan 13, 2025
c2b0d56
Merge public/main to private/staging
aws-toolkit-automation Jan 13, 2025
f117d68
revise decision event for next session, add it when current event is …
evanliu048 Jan 13, 2025
e2e056e
Merge public/main to private/staging
aws-toolkit-automation Jan 14, 2025
38799b2
Merge public/main to private/staging
aws-toolkit-automation Jan 14, 2025
b4cbaab
Merge public/main to private/staging
aws-toolkit-automation Jan 14, 2025
45fccd2
Merge public/main to private/staging
aws-toolkit-automation Jan 14, 2025
73b2505
send next session event when suggestion state is reject
evanliu048 Jan 14, 2025
ed941b6
Merge public/main to private/staging
aws-toolkit-automation Jan 14, 2025
c7a8cce
fix CodeWhispererTelemetryTest
evanliu048 Jan 14, 2025
a49dc99
Merge public/main to private/staging
aws-toolkit-automation Jan 14, 2025
e6e79c1
Use the lambda version of LOG.debug
evanliu048 Jan 14, 2025
c545e48
Merge public/main to private/staging
aws-toolkit-automation Jan 14, 2025
c3ddd40
Merge public/main to private/staging
aws-toolkit-automation Jan 15, 2025
33e8530
Merge public/main to private/staging
aws-toolkit-automation Jan 15, 2025
a6bc09c
Merge public/main to private/staging
aws-toolkit-automation Jan 15, 2025
7f85f6d
Merge public/main to private/staging
aws-toolkit-automation Jan 15, 2025
8144e20
fix acceptTest UT
evanliu048 Jan 15, 2025
adca8f3
using ?. to avoid npe
evanliu048 Jan 15, 2025
eb5d551
Merge public/main to private/staging
aws-toolkit-automation Jan 15, 2025
62749e6
revise calculating next caret postion to show new popup correctlu
evanliu048 Jan 15, 2025
5bed72d
mock cws fucniton in unit test instead of testBase
evanliu048 Jan 16, 2025
f806491
Merge public/main to private/staging
aws-toolkit-automation Jan 16, 2025
2b6ce05
Merge public/main to private/staging
aws-toolkit-automation Jan 16, 2025
9c9fa32
Merge public/main to private/staging
aws-toolkit-automation Jan 17, 2025
cad3f25
Merge public/main to private/staging
aws-toolkit-automation Jan 17, 2025
957e329
Merge public/main to private/staging
aws-toolkit-automation Jan 17, 2025
d6f3a2d
Merge public/main to private/staging
aws-toolkit-automation Jan 18, 2025
5219ed9
Update plugins/amazonq/codewhisperer/jetbrains-community/src/software…
evanliu048 Jan 18, 2025
917ce5d
revise sending decision event, avoiding circular dependency between c…
evanliu048 Jan 18, 2025
15d7cd1
Merge branch 'aldabraInOldService' of github.com:evanliu048/aws-toolk…
evanliu048 Jan 18, 2025
e604b8b
Merge public/main to private/staging
aws-toolkit-automation Jan 18, 2025
d2667f1
revise format: instead of return a log
evanliu048 Jan 18, 2025
29205ed
Merge public/main to private/staging
aws-toolkit-automation Jan 21, 2025
1d11b7d
Merge public/main to private/staging
aws-toolkit-automation Jan 21, 2025
7877e7b
Merge public/main to private/staging
aws-toolkit-automation Jan 21, 2025
df5deae
delete spy in telemetryServiceTest since sendUserDecisionForNextSessi…
evanliu048 Jan 21, 2025
33a1b8e
Merge public/main to private/staging
aws-toolkit-automation Jan 21, 2025
cb0e587
Merge public/main to private/staging
aws-toolkit-automation Jan 21, 2025
0d02b1b
Merge public/main to private/staging
aws-toolkit-automation Jan 21, 2025
3d75a4f
Merge branch 'staging' into aldabraInOldService
evanliu048 Jan 21, 2025
7e2e46a
make codewhispererservice spy on testBase
evanliu048 Jan 22, 2025
5dd4c0c
delete prefetch method
evanliu048 Jan 22, 2025
a64d783
delete comment
evanliu048 Jan 22, 2025
054f88f
Merge branch 'main' into prefechNextInlineRecommendation
evanliu048 Jan 23, 2025
71bd5a2
delete unused imports
evanliu048 Jan 23, 2025
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 @@ -76,6 +76,10 @@ interface CodeWhispererClientAdaptor : Disposable {
firstRequest: GenerateCompletionsRequest,
): Sequence<GenerateCompletionsResponse>

fun generateCompletions(
firstRequest: GenerateCompletionsRequest,
): GenerateCompletionsResponse

fun createUploadUrl(
request: CreateUploadUrlRequest,
): CreateUploadUrlResponse
Expand Down Expand Up @@ -322,6 +326,8 @@ open class CodeWhispererClientAdaptorImpl(override val project: Project) : CodeW
yield(response)
} while (!nextToken.isNullOrEmpty())
}
override fun generateCompletions(firstRequest: GenerateCompletionsRequest): GenerateCompletionsResponse =
bearerClient().generateCompletions(firstRequest)

override fun createUploadUrl(request: CreateUploadUrlRequest): CreateUploadUrlResponse =
bearerClient().createUploadUrl(request)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.intellij.openapi.ui.popup.JBPopupListener
import com.intellij.openapi.ui.popup.LightweightWindowEvent
import software.aws.toolkits.jetbrains.services.codewhisperer.model.InvocationContext
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererInvocationStatus
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererService
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererServiceNew
import software.aws.toolkits.jetbrains.services.codewhisperer.telemetry.CodeWhispererTelemetryService
import java.time.Duration
Expand All @@ -27,7 +28,8 @@ class CodeWhispererPopupListener(private val states: InvocationContext) : JBPopu
recommendationContext,
CodeWhispererPopupManager.getInstance().sessionContext,
event.isOk,
CodeWhispererInvocationStatus.getInstance().popupStartTimestamp?.let { Duration.between(it, Instant.now()) }
CodeWhispererInvocationStatus.getInstance().popupStartTimestamp?.let { Duration.between(it, Instant.now()) },
CodeWhispererService.getInstance().getNextInvocationContext()
)

CodeWhispererInvocationStatus.getInstance().setPopupActive(false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ import software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners.Co
import software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners.CodeWhispererPrevButtonActionListener
import software.aws.toolkits.jetbrains.services.codewhisperer.popup.listeners.CodeWhispererScrollListener
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererInvocationStatus
import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererService
import software.aws.toolkits.jetbrains.services.codewhisperer.telemetry.CodeWhispererTelemetryService
import software.aws.toolkits.jetbrains.services.codewhisperer.toolwindow.CodeWhispererCodeReferenceManager
import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererColorUtil.POPUP_DIM_HEX
Expand Down Expand Up @@ -455,6 +456,9 @@ class CodeWhispererPopupManager {
CodeWhispererEditorManager.getInstance().updateEditorWithRecommendation(states, sessionContext)
}
closePopup(states.popup)
if (sessionContext.selectedIndex == 0) {
CodeWhispererService.getInstance().promoteNextInvocationIfAvailable()
}
}
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.VisualPosition
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.popup.JBPopup
import com.intellij.openapi.ui.popup.JBPopupFactory
import com.intellij.openapi.util.Disposer
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiFile
Expand All @@ -24,6 +25,7 @@ import com.intellij.util.messages.Topic
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
Expand Down Expand Up @@ -98,6 +100,7 @@ import java.util.concurrent.TimeUnit
class CodeWhispererService(private val cs: CoroutineScope) : Disposable {
private val codeInsightSettingsFacade = CodeInsightsSettingsFacade()
private var refreshFailure: Int = 0
private var nextInvocationContext: InvocationContext? = null

init {
Disposer.register(this, codeInsightSettingsFacade)
Expand Down Expand Up @@ -209,7 +212,110 @@ class CodeWhispererService(private val cs: CoroutineScope) : Disposable {
invokeCodeWhispererInBackground(requestContext)
}

internal suspend fun invokeCodeWhispererInBackground(requestContext: RequestContext): Job {
internal suspend fun invokeCodeWhispererInBackground(
requestContext: RequestContext,
isPrefetch: Boolean = false,
currStates: InvocationContext? = null,
): Job {
if (isPrefetch && currStates?.recommendationContext?.details?.isNotEmpty() == true) {
val firstValidRecommendation = currStates.recommendationContext.details
.firstOrNull {
!it.isDiscarded && it.recommendation.content().isNotEmpty()
} ?: return SupervisorJob().apply { complete() }
val job = cs.launch(getCoroutineBgContext()) {
val latencyContext = LatencyContext().apply {
codewhispererPreprocessingStart = System.nanoTime()
codewhispererEndToEndStart = System.nanoTime()
}

val nextCaretPosition = calculateNextCaretPosition(requestContext, firstValidRecommendation)
val nextFileContextInfo = createNextFileContextInfo(requestContext, firstValidRecommendation)

val nextRequestContext = requestContext.copy(
caretPosition = nextCaretPosition,
fileContextInfo = nextFileContextInfo,
latencyContext = latencyContext
)
val newVisualPosition = withContext(EDT) {
runReadAction {
nextRequestContext.editor.offsetToVisualPosition(nextRequestContext.caretPosition.offset)
}
}
try {
val nextResponse = CodeWhispererClientAdaptor
.getInstance(nextRequestContext.project)
.generateCompletions(
buildCodeWhispererRequest(
nextRequestContext.fileContextInfo,
nextRequestContext.awaitSupplementalContext(),
nextRequestContext.customizationArn
)
)
val startTime = System.nanoTime()
nextRequestContext.latencyContext.codewhispererPreprocessingEnd = System.nanoTime()
nextRequestContext.latencyContext.paginationAllCompletionsStart = System.nanoTime()
CodeWhispererInvocationStatus.getInstance().setInvocationStart()
nextResponse.let {
val endTime = System.nanoTime()
val latency = TimeUnit.NANOSECONDS.toMillis(endTime - startTime).toDouble()
val requestId = nextResponse.responseMetadata().requestId()
val sessionId = nextResponse.sdkHttpResponse().headers().getOrDefault(KET_SESSION_ID, listOf(requestId))[0]

nextRequestContext.latencyContext.apply {
codewhispererPostprocessingStart = System.nanoTime()
paginationFirstCompletionTime = (endTime - codewhispererEndToEndStart).toDouble()
firstRequestId = requestId
}

CodeWhispererInvocationStatus.getInstance().setInvocationSessionId(sessionId)

val nextResponseContext = ResponseContext(sessionId)
CodeWhispererTelemetryService.getInstance().sendServiceInvocationEvent(
nextResponse.responseMetadata().requestId(),
nextRequestContext,
nextResponseContext,
nextResponse.completions().size,
true,
latency,
null
)
val validatedResponse = validateResponse(it)
val detailContexts = withContext(EDT) {
runReadAction {
CodeWhispererRecommendationManager.getInstance().buildDetailContext(
nextRequestContext,
"",
validatedResponse.completions(),
validatedResponse.responseMetadata().requestId()
)
}
}
val nextRecommendationContext = RecommendationContext(detailContexts, "", "", newVisualPosition)
val newPopup = withContext(EDT) {
JBPopupFactory.getInstance().createMessage("Dummy popup")
}

// send userDecision and trigger decision when next recommendation haven't been seen
if (currStates.popup.isDisposed) {
CodeWhispererTelemetryService.getInstance().sendUserDecisionEventForAll(
nextRequestContext,
nextResponseContext,
nextRecommendationContext,
SessionContext(),
false
)
} else {
nextInvocationContext = InvocationContext(nextRequestContext, nextResponseContext, nextRecommendationContext, newPopup)
}
LOG.debug { "Prefetched next invocation stored in nextInvocationContext" }
}
} catch (ex: Exception) {
LOG.warn { "Failed to prefetch next codewhisperer invocation: ${ex.message}" }
}
}
return job
}

val popup = withContext(EDT) {
CodeWhispererPopupManager.getInstance().initPopup().also {
Disposer.register(it) { CodeWhispererInvocationStatus.getInstance().finishInvocation() }
Expand Down Expand Up @@ -491,6 +597,9 @@ class CodeWhispererService(private val cs: CoroutineScope) : Disposable {
CodeWhispererPopupManager.getInstance().cancelPopup(popup)
return null
}
cs.launch(getCoroutineBgContext()) {
invokeCodeWhispererInBackground(requestContext, true, nextStates)
}
} else {
// subsequent responses
nextStates = updateStates(currStates, response)
Expand Down Expand Up @@ -621,6 +730,67 @@ class CodeWhispererService(private val cs: CoroutineScope) : Disposable {
CodeWhispererPopupManager.getInstance().changeStates(states, 0, "", true, recommendationAdded)
}

fun promoteNextInvocationIfAvailable() {
val nextStates = nextInvocationContext ?: run {
LOG.debug { "No nextInvocationContext found, nothing to promote." }
return
}
nextInvocationContext?.popup?.let { Disposer.dispose(it) }
nextInvocationContext = null

runInEdt {
val newPopup = CodeWhispererPopupManager.getInstance().initPopup()
val updatedNextStates = nextStates.copy(popup = newPopup).also {
addPopupChildDisposables(it.popup)
Disposer.register(newPopup, it)
}
CodeWhispererPopupManager.getInstance().initPopupListener(updatedNextStates)
CodeWhispererPopupManager.getInstance().changeStates(
updatedNextStates,
0,
"",
typeaheadAdded = true,
recommendationAdded = false
)
cs.launch(getCoroutineBgContext()) {
invokeCodeWhispererInBackground(updatedNextStates.requestContext, true, updatedNextStates)
}
}

LOG.debug { "Promoted nextInvocationContext to current session and displayed next recommendation." }
}

private fun calculateNextCaretPosition(
currentRequestContext: RequestContext,
firstValidRecommendation: DetailContext,
): CaretPosition {
val indent = currentRequestContext.fileContextInfo.caretContext.leftContextOnCurrentLine
.takeWhile { it.isWhitespace() }
val recommendedText = buildString {
append(indent)
append(firstValidRecommendation.recommendation.content())
if (!endsWith("\n")) {
append("\n")
}
}
val lineCount = recommendedText.count { it == '\n' }

return CaretPosition(
line = currentRequestContext.caretPosition.line + lineCount,
offset = currentRequestContext.caretPosition.offset + recommendedText.length
)
}

private fun createNextFileContextInfo(
requestContext: RequestContext,
firstValidRecommendation: DetailContext,
): FileContextInfo {
val updatedCaretContext = requestContext.fileContextInfo.caretContext.copy(
leftFileContext = requestContext.fileContextInfo.caretContext.leftFileContext + firstValidRecommendation.recommendation.content()
)
return requestContext.fileContextInfo.copy(caretContext = updatedCaretContext)
}

private fun sendDiscardedUserDecisionEventForAll(
requestContext: RequestContext,
responseContext: ResponseContext,
Expand Down Expand Up @@ -781,6 +951,8 @@ class CodeWhispererService(private val cs: CoroutineScope) : Disposable {

override fun dispose() {}

fun getNextInvocationContext(): InvocationContext? = nextInvocationContext

companion object {
private val LOG = getLogger<CodeWhispererService>()
private const val MAX_REFRESH_ATTEMPT = 3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,7 @@ class CodeWhispererTelemetryService {
sessionContext: SessionContext,
hasUserAccepted: Boolean,
popupShownTime: Duration? = null,
nextInvocationContext: InvocationContext? = null,
) {
val detailContexts = recommendationContext.details
val decisions = mutableListOf<CodewhispererSuggestionState>()
Expand Down Expand Up @@ -500,6 +501,19 @@ class CodeWhispererTelemetryService {
previousUserTriggerDecisions.add(this)
// we need this as well because AutotriggerService will reset the queue periodically
CodeWhispererAutoTriggerService.getInstance().addPreviousDecision(this)
// send possible next session event if current action is reject and next popup haven't shown up
if (CodewhispererSuggestionState.from(this.toString()) == CodewhispererSuggestionState.Reject) {
nextInvocationContext?.let {
sendUserDecisionEventForAll(
it.requestContext,
it.responseContext,
it.recommendationContext,
SessionContext(),
false,
nextInvocationContext = null
)
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,11 @@ import kotlin.test.fail

class CodeWhispererSettingsTest : CodeWhispererTestBase() {

private lateinit var codewhispererServiceSpy: CodeWhispererService
private lateinit var toolWindowHeadlessManager: ToolWindowHeadlessManagerImpl

@Before
override fun setUp() {
super.setUp()
codewhispererServiceSpy = spy(codewhispererService)
ApplicationManager.getApplication().replaceService(CodeWhispererService::class.java, codewhispererServiceSpy, disposableRule.disposable)

// Create a mock ToolWindowManager with working implementation of setAvailable() and isAvailable()
toolWindowHeadlessManager = object : ToolWindowHeadlessManagerImpl(projectRule.project) {
Expand Down Expand Up @@ -83,7 +80,7 @@ class CodeWhispererSettingsTest : CodeWhispererTestBase() {
whenever(stateManager.checkActiveCodeWhispererConnectionType(projectRule.project)).thenReturn(CodeWhispererLoginType.Logout)
assertThat(isCodeWhispererEnabled(projectRule.project)).isFalse
invokeCodeWhispererService()
verify(codewhispererServiceSpy, never()).showRecommendationsInPopup(any(), any(), any())
verify(codewhispererService, never()).showRecommendationsInPopup(any(), any(), any())
}

@Test
Expand All @@ -92,7 +89,7 @@ class CodeWhispererSettingsTest : CodeWhispererTestBase() {
assertThat(stateManager.isAutoEnabled()).isFalse
runInEdtAndWait {
projectRule.fixture.type(':')
verify(codewhispererServiceSpy, never()).showRecommendationsInPopup(any(), any(), any())
verify(codewhispererService, never()).showRecommendationsInPopup(any(), any(), any())
}
}

Expand Down
Loading
Loading