Copilot: handle "ok" status message when no user is set (#8116)

Thorsten Ball created

In #6954 a user has trouble using copilot. We haven't gotten to the
bottom of the problem, but one problem is that apparently sometimes (I'm
going to find out when) copilot sends an `"OK"` status message without a
username. This is from the user's logs:

2024-02-20T15:28:41-03:00 [ERROR] failed to deserialize response from
language server: missing field `user`. Response from language server:
"{\"status\":\"OK\"}"

The official `copilot.vim` plugin handles this as if the user is not
authenticated (!= authorized):


https://github.com/github/copilot.vim/blob/1a284014d2e0baf367706a94b2a9ee5fd56fd457/autoload/copilot.vim#L574-L579

So that's what I'm doing here too.

Release Notes:

- Fixed wrong handling of Copilot sign-in status in rare cases.

Change summary

crates/copilot/src/copilot.rs | 6 +++---
crates/copilot/src/request.rs | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)

Detailed changes

crates/copilot/src/copilot.rs 🔗

@@ -512,7 +512,7 @@ impl Copilot {
                                     .await?;
                                 match sign_in {
                                     request::SignInInitiateResult::AlreadySignedIn { user } => {
-                                        Ok(request::SignInStatus::Ok { user })
+                                        Ok(request::SignInStatus::Ok { user: Some(user) })
                                     }
                                     request::SignInInitiateResult::PromptUserDeviceFlow(flow) => {
                                         this.update(&mut cx, |this, cx| {
@@ -920,7 +920,7 @@ impl Copilot {
 
         if let Ok(server) = self.server.as_running() {
             match lsp_status {
-                request::SignInStatus::Ok { .. }
+                request::SignInStatus::Ok { user: Some(_) }
                 | request::SignInStatus::MaybeOk { .. }
                 | request::SignInStatus::AlreadySignedIn { .. } => {
                     server.sign_in_status = SignInStatus::Authorized;
@@ -936,7 +936,7 @@ impl Copilot {
                         self.unregister_buffer(&buffer);
                     }
                 }
-                request::SignInStatus::NotSignedIn => {
+                request::SignInStatus::Ok { user: None } | request::SignInStatus::NotSignedIn => {
                     server.sign_in_status = SignInStatus::SignedOut;
                     for buffer in self.buffers.iter().cloned().collect::<Vec<_>>() {
                         self.unregister_buffer(&buffer);

crates/copilot/src/request.rs 🔗

@@ -52,7 +52,7 @@ pub struct SignInConfirmParams {
 pub enum SignInStatus {
     #[serde(rename = "OK")]
     Ok {
-        user: String,
+        user: Option<String>,
     },
     MaybeOk {
         user: String,