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

Create Q Customization Server #462

Merged
merged 7 commits into from
Sep 27, 2024
Merged

Create Q Customization Server #462

merged 7 commits into from
Sep 27, 2024

Conversation

ege0zcan
Copy link
Contributor

@ege0zcan ege0zcan commented Sep 19, 2024

Description

  • Added Q configuration server that responds to get configuration requests with customization information
  • Updated the sample extension with a command to get customizations from the server as well as setting customization through workspace configuration
  • Refactored the updateConfiguration logic in the inline completion server and tidied up the code

License

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

lsp.extensions.onGetConfigurationFromServer(
async (params: GetConfigurationFromServerParams, token: CancellationToken) => {
if (params.section === Q_CUSTOMIZATION_CONFIGURATION_SECTION) {
const customizations = (await codeWhispererService.listAvailableCustomizations({ maxResults: 10 }))
Copy link
Contributor

Choose a reason for hiding this comment

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

Why we limit to 10 here? Can we return all and let client decide how many to display?

@@ -260,18 +261,6 @@ const mergeSuggestionsWithRightContext = (
})
}

// Checks if any suggestion in list of suggestions matches with left context of the file
const hasLeftContextMatch = (suggestions: Suggestion[], leftFileContent: string): boolean => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Did you intentionally remove this function?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, it was unused

import { getUserAgent } from '../utils'

// The configuration section that the customization server will register and listen to
export const Q_CUSTOMIZATION_CONFIGURATION_SECTION = 'aws.q.customization'
Copy link
Contributor

Choose a reason for hiding this comment

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

How many levels of nested sections should we allow servers to register and handle?
Registering this server to 3 levels deep section seems to be too granular - what if we need to fetch other more configs, other that customizations? Will we have to register another aws.q.$sectionname section for this server?

Can we instead make this more generic amazonQConfigurationServer, and let it handle whole aws.q section of configs? Then it can be extended easier in the future without much refactoring.

Additionally, we can still allow clients to request more detailed section, like aws.q.customization and return filtered object for only requested subsection. This filtering can be done in the runtime proxying getConfigurationFromServer request, so logic is uniform for all servers.

@ege0zcan ege0zcan marked this pull request as ready for review September 25, 2024 16:27
@ege0zcan ege0zcan requested review from a team as code owners September 25, 2024 16:27
.catch(reason => logging.log(`Error in GetConfiguration: ${reason}`))
const updateConfiguration = async () => {
try {
const qConfig = await lsp.workspace.getConfiguration(Q_CONFIGURATION_SECTION)
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 here we just need to make sure we send the request with the correct parameters. According to LSP spec, https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#configurationParams an array of items has to be sent.

Copy link
Contributor

Choose a reason for hiding this comment

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

I checked locally and it seems internally it somehow sends the request in the expected correct format. Can ignore this comment.

Copy link
Contributor

Choose a reason for hiding this comment

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

FYI, under the hood getConfiguration is handled by this implementation, which converts arguments to LSP params
https://github.com/microsoft/vscode-languageserver-node/blob/f58f4dff16ad2760028bb1cb95e882de30a1000f/server/src/common/configuration.ts#L4

Copy link
Contributor

Choose a reason for hiding this comment

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

thanks for sharing the link Viktor.

logging.log(`Inline completion configuration updated to use ${qConfig.customization}`)
}

const config = await lsp.workspace.getConfiguration('aws.codeWhisperer')
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: it should be possible to request multiple configuration sections with one getConfiguration call, instead of 2 https://github.com/microsoft/vscode-languageserver-node/blob/f58f4dff16ad2760028bb1cb95e882de30a1000f/server/src/common/configuration.ts#L18.

Our Workspace.getConfiguration proxy handler only supports section though, so it will need to be extended. Could be done as a follow-up.

import { getUserAgent } from '../utils'

// The configuration section that the server will register and listen to
export const Q_CONFIGURATION_SECTION = 'aws.q'
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you add documentation for QConfigurationServerToken to README with an configuration key it supports and data type of response it provides?
Also you can define a Typescript type for onGetConfigurationFromServer response, and it will serve as a documentation as well.

@@ -330,6 +339,18 @@ export class ChatController implements ChatHandlers {
return chatEventParser.getChatResult()
}

updateConfiguration = async () => {
try {
const qCustomizationConfig = await this.#features.lsp.workspace.getConfiguration(Q_CONFIGURATION_SECTION)
Copy link
Contributor

Choose a reason for hiding this comment

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

The Typescript type for expected configuration object defined in #462 (comment) can be used in calls to read documentation like here.

@ege0zcan ege0zcan merged commit 0ca73ac into main Sep 27, 2024
5 checks passed
@ege0zcan ege0zcan deleted the qCustomization branch September 27, 2024 13:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants