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

Switch to webview-based sign-in flow #2382

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

pkukielka
Copy link
Contributor

@pkukielka pkukielka commented Oct 3, 2024

@pkukielka pkukielka changed the title Switch to webview-based sign-iin flow Switch to webview-based sign-in flow Oct 3, 2024
@pkukielka pkukielka marked this pull request as draft October 3, 2024 15:02
Copy link
Contributor

@mkondratek mkondratek left a comment

Choose a reason for hiding this comment

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

in general looks good - I will try it in the morning 🌅

import com.sourcegraph.cody.telemetry.TelemetryV2
import com.sourcegraph.cody.vscode.InlineCompletionTriggerKind
import com.sourcegraph.utils.CodyEditorUtil

class CodyDocumentListener(val project: Project) : BulkAwareDocumentListener {

// TODO: Looks like this functionality is broken after the migration to webview
Copy link
Contributor

@mkondratek mkondratek Oct 3, 2024

Choose a reason for hiding this comment

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

  • let us have a linear issue for this one

codyAccountManager.getAccounts().forEach { oldAccount ->
val token = codyAccountManager.getTokenForAccount(oldAccount)
if (token != null) {
CodyAccount(oldAccount.server).storeToken(token)
Copy link
Contributor

Choose a reason for hiding this comment

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

nice

val id: String,
val username: String,
val displayName: String?,
val avatarURL: String?
Copy link
Contributor

Choose a reason for hiding this comment

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

we do not use avatarURL anymore - I think we can remove it

Comment on lines +133 to +153
@JsonRequest("secrets/get")
fun secrets_get(params: Secrets_GetParams): CompletableFuture<String?> {
return CompletableFuture.completedFuture(
CodyAccount(SourcegraphServerPath(params.key)).getToken())
}

@JsonRequest("secrets/store")
fun secrets_store(params: Secrets_StoreParams): CompletableFuture<Null?> {
CodyAccount(SourcegraphServerPath(params.key)).storeToken(params.value)
return CompletableFuture.completedFuture(null)
}

@JsonRequest("secrets/delete")
fun secrets_delete(params: Secrets_DeleteParams): CompletableFuture<Null?> {
CodyAccount(SourcegraphServerPath(params.key)).storeToken(null)
return CompletableFuture.completedFuture(null)
}

Copy link
Contributor

Choose a reason for hiding this comment

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

maybe a stupid question but... is it safe? are there any security issues? would the secrets be present in the trace logs?

Copy link
Contributor

Choose a reason for hiding this comment

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

We log the secrets in the agent trace, not the log. You have to set an extra environment variable to turn on that level of logging... I think it should be fine.

We already log tokens in that file today... the ExtensionConfiguration message from JetBrains to Agent has the token in it... see build/sourcegraph/cody-agent-trace.json after a debugging session.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is a s Dominic said :)

@@ -79,15 +64,4 @@ public void actionPerformed(@NotNull AnActionEvent anActionEvent) {
notification.addAction(neverShowAgainAction);
Notifications.Bus.notify(notification);
}

private void showMissingTokenNotification() {
Copy link
Contributor

Choose a reason for hiding this comment

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

btw, I wonder... what if the token expires (or is removed)? 🤔 what will happen (with chat, with autocomplete)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will test this scenario today. In general I think we should then (if user try to call some action explicitly) show cody panel, and it should be showing login panel.

Copy link
Contributor

Choose a reason for hiding this comment

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

By the way, VSCode has various APIs for showing views, we don't implement them. If we need to show the view, we should see if the extension is trying to do it anyway. Maybe we just need to implement a couple of those methods/properties in the VSCode shim.

Copy link
Contributor

Choose a reason for hiding this comment

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

Don't we want to keep this action? I know it is possible to export chats from History tab in the webview. Simply, this action is an actual jetbrains action and can be searched for and run from anywhere

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, for now we should keep this, and Explain, etc.

It would be a nice cleanup project later to ingest the VSCode package.json and consider wiring up those commands automatically--or at least linting that we have them.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I reverted that changes.

@dominiccooney dominiccooney self-requested a review October 4, 2024 00:41
private val cardPanel = JPanel(cardLayout)
val allContentPanel: JComponent = JPanel(GridLayout(1, 1))
val allContentPanel: JComponent = JPanel(CardLayout())
private val mainPanel = JPanel(GridBagLayout())
Copy link
Contributor

Choose a reason for hiding this comment

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

We were using the cardlayout to swap between the loading, login and onboarding components.

We can't put the webview in a CardLayout because JetBrains remote doesn't render it, so we are swapping the components.

But now there are only two components to swap: Loading and webview. So we don't need this panel anymore.

Let's just have allContentPanel with whatever trivial layout (GridLayout(1,1) etc.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So this is weird, because I tried to simplify it at the start but it was not working without CardLayout.
But maybe it was error on my side, I will check again :)

}

@JsonRequest("secrets/store")
fun secrets_store(params: Secrets_StoreParams): CompletableFuture<Null?> {
Copy link
Contributor

Choose a reason for hiding this comment

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

A nullable null... Why not a nullable nullable null 🤔


@JsonNotification("window/didChangeContext")
fun window_didChangeContext(params: Window_DidChangeContextParams) {
println(params)
Copy link
Contributor

@dominiccooney dominiccooney Oct 4, 2024

Choose a reason for hiding this comment

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

Let's not spam the console. Info logging it might be fine.

Is this, in fact, important for refreshing the status bar icon? "cody.activated" will be true when the extension thinks it is good to go.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, refreshing status icon bar is part I/ know I missed but I forget to add it at the end.
Thanks, I will add it now!

@@ -0,0 +1,101 @@
package com.sourcegraph.cody.auth.depracated
Copy link
Contributor

Choose a reason for hiding this comment

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

Spelling: deprecated


@RequiresEdt
internal fun updateAccountToken(account: DeprecatedCodyAccount, newToken: String) {
service<DeprecatedCodyPersistentAccounts>().accounts = (getAccounts() - account) + account
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems tricky, maybe the method should be called addOrUpdateAccountToken or something?

@@ -172,7 +172,7 @@ class CodyAutocompleteManager {

val textDocument: TextDocument = IntelliJTextDocument(editor, project)

if (isTriggeredExplicitly && CodyAuthenticationManager.getInstance().hasNoActiveAccount()) {
if (isTriggeredExplicitly && !CodyAccount.hasActiveAccount()) {
HintManager.getInstance().showErrorHint(editor, "Cody: Sign in to use autocomplete")
Copy link
Contributor

Choose a reason for hiding this comment

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

Ugh, we should link to the sign in panel here! Maybe add a TODO?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually I think we should just show it.
I will do the changes, thanks!

@@ -1,8 +0,0 @@
package com.sourcegraph.cody.chat.actions
Copy link
Contributor

Choose a reason for hiding this comment

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

This too, I believe we should keep these commands.

@@ -12,8 +12,7 @@ class NewChatAction : DumbAwareEDTAction() {
}

override fun update(event: AnActionEvent) {
val hasActiveAccount = CodyAuthenticationManager.getInstance().hasActiveAccount()
event.presentation.isEnabled = hasActiveAccount
event.presentation.isEnabled = CodyAccount.hasActiveAccount()
Copy link
Contributor

Choose a reason for hiding this comment

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

This CodyAccount.hasActiveAccount, we should be using the flag we got from window/didChangeContext "cody.activated" instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree in principle, but it is not as simple.
I need to also know account, in particular to be able to check if it's enterprise/pro/free, which in turn I need to properly render LLM selection in edit window.
But now I think maybe we should add additional flag to the model, and avoid this problem in the first place.
It would allow us to remove quite a bit of code on the jetbrains side.

Copy link
Contributor

Choose a reason for hiding this comment

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

OK. Let's work out a practical split to get this landed, because there's a lot of great cleanup here. And we can smooth out the details later.

I agree for chat/models returning the models with the flag sounds good.

I tend to disagree in the specific case of NewChatAction, all we need to know is whether we have an active account. But let's land this first and take a fresh look at account type dependencies after this change is done.

RunOnceUtil.runOnceForProject(project, "CodyMigrateChatHistory-v2") {
ChatHistoryMigration.migrate(project)
}
RunOnceUtil.runOnceForProject(project, "AccountsToCodyMigration") {
AccountsMigration.migrate()
Copy link
Contributor

Choose a reason for hiding this comment

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

Just curious but are these guaranteed to run in this order? Is it important?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

AFAIR their are, this code is synchronous.

Copy link
Contributor

@dominiccooney dominiccooney left a comment

Choose a reason for hiding this comment

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

Feedback inline, please take a look.

Approving to unblock since you have multiple sides to land.

We can go further than this, I think, by listening to window/didChangeContext and hooking a notification to the AuthStatus observer, but we can work on those in follow up patches if it is easier.

println(params)
}

@JsonNotification("globalStorage/didChange")
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's not sniff global storage for this. We should be listening to the configuration observable and pushing a semantic, application-level message to the IDE.

@pkukielka pkukielka force-pushed the pkukielka/switch-to-webview-signin-panel branch from 1aaddb9 to 3a8922f Compare October 17, 2024 09:02
@@ -30,7 +29,6 @@ public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindo
content.setPreferredFocusableComponent(null);
toolWindow.getContentManager().addContent(content);
DefaultActionGroup customCodySettings = new DefaultActionGroup();
customCodySettings.add(new OpenPluginSettingsAction("Cody Settings..."));
Copy link
Contributor

Choose a reason for hiding this comment

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

image

Probably this is not an item for this PR but our settings seems to be orphaned now 😢 Can we still have them under Tools > Sourcegraph & Cody?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for spotting it!
It is definitely for this PR, in fact I removed too much (update channel selection).
I added it back now.

if ((command == "auth" && decodedJson.get("authKind")?.asString == "signout") ||
(isCommand && id == "cody.auth.signout")) {
CodyAuthenticationManager.getInstance().setActiveAccount(null)
} else if (isCommand && id == "cody.auth.switchAccount") {
Copy link
Contributor

Choose a reason for hiding this comment

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

cody.auth.switchAccount - we do not handle this command now 😕

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because it shouldn't handled by JetBrains anymore.
JetBrains is now only responsible for storing the tokens in the secure store.
Other than that all account management is done by Cody and we just receive notifications about it.

import com.sourcegraph.cody.telemetry.TelemetryV2
import com.sourcegraph.cody.vscode.InlineCompletionTriggerKind
import com.sourcegraph.utils.CodyEditorUtil

class CodyDocumentListener(val project: Project) : BulkAwareDocumentListener {

// TODO: Looks like this functionality is broken after the migration to webview
Copy link
Contributor

Choose a reason for hiding this comment

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

is it still broken or did you manage fix it? if it need more attention can you pls create an issue for that? 🙏

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's still broken, fix will be a bit more involved, I linked an linear issue

pkukielka added a commit to sourcegraph/cody that referenced this pull request Oct 17, 2024
## Changes

I've added `cody.serverEndpoint` context variable, which on the clients
side is received through `window/didChangeContext` notification. We need
it on the jetbrains side in few places, e.g. when we are checking if
current account is a dotcom account.

I think it might be better idea to replace this with a dedicated
endpoint, but I'm not sure if `cody.activated` is currently used
anywhere?
@dominiccooney @sqs WDYT?



## Test plan

Full QA with sourcegraph/jetbrains#2382 is
needed.
It does not change anything on the Cody side.
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