Skip to content
Draft
Show file tree
Hide file tree
Changes from 4 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 @@ -11,6 +11,7 @@

import software.aws.toolkits.eclipse.amazonq.lsp.auth.model.SsoTokenChangedParams;
import software.aws.toolkits.eclipse.amazonq.lsp.model.ConnectionMetadata;
import software.aws.toolkits.eclipse.amazonq.lsp.model.NotificationParams;

public interface AmazonQLspClient extends LanguageClient {

Expand All @@ -19,5 +20,8 @@ public interface AmazonQLspClient extends LanguageClient {

@JsonNotification("aws/identity/ssoTokenChanged")
void ssoTokenChanged(SsoTokenChangedParams params);

@JsonNotification("aws/window/showNotification")
void showNotification(NotificationParams params);

Choose a reason for hiding this comment

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

Nothing to worry about now, but I may try to convert this to showNotifications (if Flare will agree) and send an array of Notification instead of just one.


}
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@
import org.eclipse.lsp4j.ProgressParams;
import org.eclipse.lsp4j.ShowDocumentParams;
import org.eclipse.lsp4j.ShowDocumentResult;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.lsp4j.MessageType;

import software.amazon.awssdk.services.toolkittelemetry.model.Sentiment;
import software.aws.toolkits.eclipse.amazonq.chat.ChatCommunicationManager;
Expand All @@ -28,6 +31,7 @@
import software.aws.toolkits.eclipse.amazonq.lsp.auth.model.SsoTokenChangedKind;
import software.aws.toolkits.eclipse.amazonq.lsp.auth.model.SsoTokenChangedParams;
import software.aws.toolkits.eclipse.amazonq.lsp.model.ConnectionMetadata;
import software.aws.toolkits.eclipse.amazonq.lsp.model.NotificationParams;
import software.aws.toolkits.eclipse.amazonq.lsp.model.SsoProfileData;
import software.aws.toolkits.eclipse.amazonq.lsp.model.TelemetryEvent;
import software.aws.toolkits.eclipse.amazonq.plugin.Activator;
Expand All @@ -37,6 +41,10 @@
import software.aws.toolkits.eclipse.amazonq.util.ObjectMapperFactory;
import software.aws.toolkits.eclipse.amazonq.views.model.Customization;
import software.aws.toolkits.eclipse.amazonq.util.ThreadingUtils;
import org.eclipse.mylyn.commons.ui.dialogs.AbstractNotificationPopup;
import software.aws.toolkits.eclipse.amazonq.util.PersistentToolkitNotification;
import software.aws.toolkits.eclipse.amazonq.util.ToolkitNotification;


@SuppressWarnings("restriction")
public class AmazonQLspClientImpl extends LanguageClientImpl implements AmazonQLspClient {
Expand Down Expand Up @@ -170,4 +178,92 @@ public final void ssoTokenChanged(final SsoTokenChangedParams params) {
Activator.getLogger().error("Error processing " + kind + " ssoTokenChanged notification", ex);
}
}
public enum NotificationSeverity {
LOW, MEDIUM, HIGH
}

/**
* Shows a notification to the user with the specified content and severity.
* This method is designed to be overridden by subclasses that need to customize
* the notification behavior.
*
* @param params The notification parameters containing the message type and content
*/
@Override
public final void showNotification(final NotificationParams params) {
Activator.getLogger().info("Received notification JSON: " + params.type().toString());
Display.getDefault().asyncExec(() -> {
String title = params.content().title() != null
? params.content().title()
: "AWS Notification";
String message = params.content().text();
NotificationSeverity severity = determineNotificationSeverity(params.type());
handleNotification(severity, title, message);
});
}

private NotificationSeverity determineNotificationSeverity(final MessageType type) {

Choose a reason for hiding this comment

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

Severity will be moved to a PresentationHint, which means you'll be able to define the string values however you want. Does Java have a way of parsing strings into enums? If so, this can probably be simplified when the notification protocol changes are made and the server starts sending the updated notification format.

Or based on breedloj@ comment below, maybe Severity isn't needed at all.

if (type == MessageType.Error) {
return NotificationSeverity.HIGH;
}
if (type == MessageType.Warning) {
return NotificationSeverity.MEDIUM;
}
if (type == MessageType.Info) {
return NotificationSeverity.LOW;
}
return null;
}

private void handleNotification(NotificationSeverity severity, final String title, final String message) {
if (severity == null) {
severity = NotificationSeverity.LOW; // Default to LOW if severity is null
Activator.getLogger().info("Null severity detected, defaulting to LOW");
}

switch (severity) {
case LOW:
AbstractNotificationPopup transientNotification = new ToolkitNotification(
Display.getCurrent(), title, message
);
transientNotification.open();
break;

case MEDIUM:
AbstractNotificationPopup persistentNotification = new PersistentToolkitNotification(
Display.getCurrent(),
title,
message,
checked -> {
if (checked) {
Activator.getPluginStore().put("notificationSkipFlag", "true");
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 we will need this to be more granular - e.g. per notification type.

} else {
Activator.getPluginStore().remove("notificationSkipFlag");
}
}
);
persistentNotification.setDelayClose(60000);
persistentNotification.open();
break;

case HIGH:
Display.getDefault().syncExec(() -> {
MessageDialog dialog = new MessageDialog(
Display.getCurrent().getActiveShell(),
title,
null,
message,
MessageDialog.WARNING,
new String[] {"Acknowledge"},
0
);
dialog.open();
});
break;

default:
Activator.getLogger().warn("Unexpected severity level encountered");
break;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,19 @@ private Map<String, Object> getInitializationOptions(final ClientMetadata metada
Map<String, Object> initOptions = new HashMap<>();
Map<String, Object> awsInitOptions = new HashMap<>();
Map<String, Object> extendedClientInfoOptions = new HashMap<>();
Map<String, Object> awsClientCapabilitiesOptions = new HashMap<>();
Map<String, String> windowOptions = new HashMap<>();
Map<String, String> extensionOptions = new HashMap<>();
extensionOptions.put("name", USER_AGENT_CLIENT_NAME);
extensionOptions.put("version", metadata.getPluginVersion());
extendedClientInfoOptions.put("extension", extensionOptions);
extendedClientInfoOptions.put("clientId", metadata.getClientId());
extendedClientInfoOptions.put("version", metadata.getIdeVersion());
extendedClientInfoOptions.put("name", metadata.getIdeName());
windowOptions.put("notifications", "true");
awsClientCapabilitiesOptions.put("window", windowOptions);
awsInitOptions.put("clientInfo", extendedClientInfoOptions);
awsInitOptions.put("awsClientCapabilities", awsClientCapabilitiesOptions);
initOptions.put("aws", awsInitOptions);
return initOptions;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ public QLspConnectionProvider() throws IOException {
var serverCommand = Paths.get(lspInstallResult.getServerDirectory(), lspInstallResult.getServerCommand());
List<String> commands = new ArrayList<>();
commands.add(serverCommand.toString());
commands.add(lspInstallResult.getServerCommandArgs());
//commands.add(lspInstallResult.getServerCommandArgs());

Choose a reason for hiding this comment

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

Be sure to add a comment here about you're doing this for development on the feature branch and this should not be checked into main. We don't want this making it into prod.

commands.add("--inspect=6012");
commands.add("/Users/aseemxs/Language-servers/language-servers/app/aws-lsp-notification-runtimes/out/standalone.js");
commands.add("--nolazy");
commands.add("--stdio");
commands.add("--set-credentials-encryption-key");
setCommands(commands);
Expand All @@ -55,6 +58,7 @@ protected final void addEnvironmentVariables(final Map<String, String> env) {
}
env.put("ENABLE_INLINE_COMPLETION", "true");
env.put("ENABLE_TOKEN_PROVIDER", "true");
env.put("AWS_Q_ENDPOINT_URL", "https://rts.gamma-us-east-1.codewhisperer.ai.aws.dev/");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package software.aws.toolkits.eclipse.amazonq.lsp.model;

public record EventIdentifier(String id) { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package software.aws.toolkits.eclipse.amazonq.lsp.model;

public record NotificationAction(String text, String type) { }

Choose a reason for hiding this comment

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

Notification actions may include a URI property (wait for the Flare protocol updates).

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package software.aws.toolkits.eclipse.amazonq.lsp.model;


public record NotificationContent(String text, String title) { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package software.aws.toolkits.eclipse.amazonq.lsp.model;

import java.util.List;

import org.eclipse.lsp4j.MessageType;

public record NotificationParams(
MessageType type,
NotificationContent content,
String id,
List<NotificationAction> actions
) { }
Loading