Skip to content

Commit 5456fa0

Browse files
authored
feat(amazonq): workspace context settings & workspaceId (#5526)
1. Add the settings of workspace context. (String of the settings to be adjusted based on product spec) 2. Let inline completion use workspaceId. Before launch date, future workspace context PRs will target branch feature/q-lsp directly. VSC ref: aws/aws-toolkit-vscode#6894
1 parent 3abcd1f commit 5456fa0

File tree

15 files changed

+123
-9
lines changed

15 files changed

+123
-9
lines changed

plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/service/CodeWhispererService.kt

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnection
5353
import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnectionManager
5454
import software.aws.toolkits.jetbrains.core.credentials.pinning.CodeWhispererConnection
5555
import software.aws.toolkits.jetbrains.services.amazonq.SUPPLEMENTAL_CONTEXT_TIMEOUT
56+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.AmazonQLspService
57+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.GetConfigurationFromServerParams
58+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.LspServerConfigurations
5659
import software.aws.toolkits.jetbrains.services.codewhisperer.credentials.CodeWhispererClientAdaptor
5760
import software.aws.toolkits.jetbrains.services.codewhisperer.customization.CodeWhispererModelConfigurator
5861
import software.aws.toolkits.jetbrains.services.codewhisperer.editor.CodeWhispererEditorManager
@@ -91,6 +94,9 @@ import software.aws.toolkits.resources.message
9194
import software.aws.toolkits.telemetry.CodewhispererCompletionType
9295
import software.aws.toolkits.telemetry.CodewhispererSuggestionState
9396
import software.aws.toolkits.telemetry.CodewhispererTriggerType
97+
import java.net.URI
98+
import java.nio.file.Paths
99+
import java.util.concurrent.CompletableFuture
94100
import java.util.concurrent.TimeUnit
95101

96102
@Service
@@ -231,7 +237,8 @@ class CodeWhispererService(private val cs: CoroutineScope) : Disposable {
231237
buildCodeWhispererRequest(
232238
requestContext.fileContextInfo,
233239
requestContext.awaitSupplementalContext(),
234-
requestContext.customizationArn
240+
requestContext.customizationArn,
241+
requestContext.workspaceId
235242
)
236243
)
237244

@@ -666,7 +673,33 @@ class CodeWhispererService(private val cs: CoroutineScope) : Disposable {
666673
// 5. customization
667674
val customizationArn = CodeWhispererModelConfigurator.getInstance().activeCustomization(project)?.arn
668675

669-
return RequestContext(project, editor, triggerTypeInfo, caretPosition, fileContext, supplementalContext, connection, latencyContext, customizationArn)
676+
var workspaceId: String? = null
677+
try {
678+
val workspacesInfos = getWorkspaceIds(project).get().workspaces
679+
for (workspaceInfo in workspacesInfos) {
680+
val workspaceRootPath = Paths.get(URI(workspaceInfo.workspaceRoot)).toString()
681+
if (psiFile.virtualFile.path.startsWith(workspaceRootPath)) {
682+
workspaceId = workspaceInfo.workspaceId
683+
LOG.info { "Found workspaceId from LSP '$workspaceId'" }
684+
break
685+
}
686+
}
687+
} catch (e: Exception) {
688+
LOG.warn { "Cannot get workspaceId from LSP'$e'" }
689+
}
690+
return RequestContext(
691+
project, editor, triggerTypeInfo, caretPosition,
692+
fileContext, supplementalContext, connection, latencyContext, customizationArn, workspaceId
693+
)
694+
}
695+
696+
private fun getWorkspaceIds(project: Project): CompletableFuture<LspServerConfigurations> {
697+
val payload = GetConfigurationFromServerParams(
698+
section = "aws.q.workspaceContext"
699+
)
700+
return AmazonQLspService.executeIfRunning(project) { server ->
701+
server.getConfigurationFromServer(payload)
702+
} ?: (CompletableFuture.failedFuture(IllegalStateException("LSP Server not running")))
670703
}
671704

672705
fun validateResponse(response: GenerateCompletionsResponse): GenerateCompletionsResponse {
@@ -800,6 +833,7 @@ class CodeWhispererService(private val cs: CoroutineScope) : Disposable {
800833
fileContextInfo: FileContextInfo,
801834
supplementalContext: SupplementalContextInfo?,
802835
customizationArn: String?,
836+
workspaceId: String?,
803837
): GenerateCompletionsRequest {
804838
val programmingLanguage = ProgrammingLanguage.builder()
805839
.languageName(fileContextInfo.programmingLanguage.toCodeWhispererRuntimeLanguage().languageId)
@@ -828,6 +862,7 @@ class CodeWhispererService(private val cs: CoroutineScope) : Disposable {
828862
.referenceTrackerConfiguration { it.recommendationsWithReferences(includeCodeWithReference) }
829863
.customizationArn(customizationArn)
830864
.optOutPreference(getTelemetryOptOutPreference())
865+
.workspaceId(workspaceId)
831866
.build()
832867
}
833868
}
@@ -843,6 +878,7 @@ data class RequestContext(
843878
val connection: ToolkitConnection?,
844879
val latencyContext: LatencyContext,
845880
val customizationArn: String?,
881+
val workspaceId: String?,
846882
) {
847883
// TODO: should make the entire getRequestContext() suspend function instead of making supplemental context only
848884
var supplementalContext: SupplementalContextInfo? = null

plugins/amazonq/codewhisperer/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codewhisperer/settings/CodeWhispererConfigurable.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,20 @@ class CodeWhispererConfigurable(private val project: Project) :
138138
}
139139

140140
group(message("aws.settings.codewhisperer.group.q_chat")) {
141+
row {
142+
checkBox(message("aws.settings.codewhisperer.workspace_context")).apply {
143+
connect.subscribe(
144+
ToolkitConnectionManagerListener.TOPIC,
145+
object : ToolkitConnectionManagerListener {
146+
override fun activeConnectionChanged(newConnection: ToolkitConnection?) {
147+
enabled(isCodeWhispererEnabled(project))
148+
}
149+
}
150+
)
151+
enabled(invoke)
152+
bindSelected(codeWhispererSettings::isWorkspaceContextEnabled, codeWhispererSettings::toggleWorkspaceContextEnabled)
153+
}.comment(message("aws.settings.codewhisperer.workspace_context.tooltip"))
154+
}
141155
row {
142156
checkBox(message("aws.settings.codewhisperer.project_context")).apply {
143157
connect.subscribe(

plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererCodeCoverageTrackerTest.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,8 @@ internal class CodeWhispererCodeCoverageTrackerTestPython : CodeWhispererCodeCov
176176
},
177177
null,
178178
mock(),
179-
aString()
179+
aString(),
180+
null
180181
)
181182
val responseContext = ResponseContext("sessionId")
182183
val recommendationContext = RecommendationContext(

plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererConfigurableTest.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,18 @@ class CodeWhispererConfigurableTest : CodeWhispererTestBase() {
3939

4040
val checkboxes = panel.components.filterIsInstance<JCheckBox>()
4141

42-
assertThat(checkboxes.size).isEqualTo(5)
42+
assertThat(checkboxes.size).isEqualTo(6)
4343
assertThat(checkboxes.map { it.text }).containsExactlyInAnyOrder(
4444
message("aws.settings.codewhisperer.include_code_with_reference"),
4545
message("aws.settings.codewhisperer.configurable.opt_out.title"),
4646
message("aws.settings.codewhisperer.automatic_import_adder"),
47+
"Workspace context",
4748
message("aws.settings.codewhisperer.project_context"),
4849
message("aws.settings.codewhisperer.project_context_gpu")
4950
)
5051

5152
val comments = panel.components.filterIsInstance<DslLabel>()
52-
assertThat(comments.size).isEqualTo(8)
53+
assertThat(comments.size).isEqualTo(9)
5354

5455
mockCodeWhispererEnabledStatus(false)
5556
ApplicationManager.getApplication().messageBus.syncPublisher(ToolkitConnectionManagerListener.TOPIC)

plugins/amazonq/codewhisperer/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererServiceTest.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,8 @@ class CodeWhispererServiceTest {
212212
supplementalContextDeferred = async { mockSupContext },
213213
connection = ToolkitConnectionManager.getInstance(projectRule.project).activeConnection(),
214214
latencyContext = LatencyContext(),
215-
customizationArn = "fake-arn"
215+
customizationArn = "fake-arn",
216+
workspaceId = null
216217
)
217218
)
218219

plugins/amazonq/codewhisperer/jetbrains-community/tstFixtures/software/aws/toolkits/jetbrains/services/codewhisperer/CodeWhispererTestUtil.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,8 @@ fun aRequestContext(
257257
Random.nextLong(),
258258
aString()
259259
),
260-
customizationArn = null
260+
customizationArn = null,
261+
workspaceId = null
261262
)
262263
}
263264

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageClientImpl.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ class AmazonQLanguageClientImpl(private val project: Project) : AmazonQLanguageC
8484
CodeWhispererLspConfiguration(
8585
shouldShareData = CodeWhispererSettings.getInstance().isMetricOptIn(),
8686
shouldShareCodeReferences = CodeWhispererSettings.getInstance().isIncludeCodeWithReference(),
87+
shouldEnableWorkspaceContext = CodeWhispererSettings.getInstance().isWorkspaceContextEnabled()
8788
)
8889
)
8990
}

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLanguageServer.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import org.eclipse.lsp4j.jsonrpc.messages.ResponseMessage
77
import org.eclipse.lsp4j.jsonrpc.services.JsonNotification
88
import org.eclipse.lsp4j.jsonrpc.services.JsonRequest
99
import org.eclipse.lsp4j.services.LanguageServer
10+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.GetConfigurationFromServerParams
11+
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.LspServerConfigurations
1012
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.credentials.UpdateCredentialsPayload
1113
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.dependencies.DidChangeDependencyPathsParams
1214
import java.util.concurrent.CompletableFuture
@@ -24,4 +26,7 @@ interface AmazonQLanguageServer : LanguageServer {
2426

2527
@JsonNotification("aws/credentials/token/delete")
2628
fun deleteTokenCredentials(): CompletableFuture<Unit>
29+
30+
@JsonRequest("aws/getConfigurationFromServer")
31+
fun getConfigurationFromServer(params: GetConfigurationFromServerParams): CompletableFuture<LspServerConfigurations>
2732
}

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/AmazonQLspConstants.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ object AmazonQLspConstants {
88
const val LSP_CW_CONFIGURATION_KEY = "aws.codeWhisperer"
99
const val LSP_CW_OPT_OUT_KEY = "shareCodeWhispererContentWithAWS"
1010
const val LSP_CODE_REFERENCES_OPT_OUT_KEY = "includeSuggestionsWithCodeReferences"
11+
const val LSP_WORKSPACE_CONTEXT_ENABLED_KEY = "workspaceContext"
1112
}

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/CodeWhispererLspConfiguration.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ data class CodeWhispererLspConfiguration(
99
@SerializedName(AmazonQLspConstants.LSP_CW_OPT_OUT_KEY)
1010
val shouldShareData: Boolean? = null,
1111

12+
@SerializedName(AmazonQLspConstants.LSP_WORKSPACE_CONTEXT_ENABLED_KEY)
13+
val shouldEnableWorkspaceContext: Boolean? = null,
14+
1215
@SerializedName(AmazonQLspConstants.LSP_CODE_REFERENCES_OPT_OUT_KEY)
1316
val shouldShareCodeReferences: Boolean? = null,
1417
)

0 commit comments

Comments
 (0)