-
Notifications
You must be signed in to change notification settings - Fork 23
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
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this 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 |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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? |
There was a problem hiding this comment.
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
@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) | ||
} | ||
|
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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() { |
There was a problem hiding this comment.
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)?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
private val cardPanel = JPanel(cardLayout) | ||
val allContentPanel: JComponent = JPanel(GridLayout(1, 1)) | ||
val allContentPanel: JComponent = JPanel(CardLayout()) | ||
private val mainPanel = JPanel(GridBagLayout()) |
There was a problem hiding this comment.
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.)
There was a problem hiding this comment.
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?> { |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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") |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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() |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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() |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this 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") |
There was a problem hiding this comment.
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.
7a32f34
to
a856cfd
Compare
48da69c
to
1aaddb9
Compare
1aaddb9
to
3a8922f
Compare
@@ -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...")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
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") { |
There was a problem hiding this comment.
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 😕
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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? 🙏
There was a problem hiding this comment.
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
## 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.
Test plan
Full QA, I will add more instructions later.
Depends on: