Fix: Copilot Chat is logged out (#21360)

Closes #21255

Release Notes:

- Fixed Copilot Chat OAuth Token parsing

---------

Co-authored-by: Bennet Bo Fenner <bennet@zed.dev>
This commit is contained in:
fred-sch 2024-12-02 10:35:29 +01:00 committed by GitHub
parent 89a56968f6
commit 380679fcc2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -197,7 +197,7 @@ pub fn init(fs: Arc<dyn Fs>, client: Arc<dyn HttpClient>, cx: &mut AppContext) {
cx.set_global(GlobalCopilotChat(copilot_chat));
}
fn copilot_chat_config_path() -> &'static PathBuf {
fn copilot_chat_config_dir() -> &'static PathBuf {
static COPILOT_CHAT_CONFIG_DIR: OnceLock<PathBuf> = OnceLock::new();
COPILOT_CHAT_CONFIG_DIR.get_or_init(|| {
@ -207,10 +207,14 @@ fn copilot_chat_config_path() -> &'static PathBuf {
home_dir().join(".config")
}
.join("github-copilot")
.join("hosts.json")
})
}
fn copilot_chat_config_paths() -> [PathBuf; 2] {
let base_dir = copilot_chat_config_dir();
[base_dir.join("hosts.json"), base_dir.join("apps.json")]
}
impl CopilotChat {
pub fn global(cx: &AppContext) -> Option<gpui::Model<Self>> {
cx.try_global::<GlobalCopilotChat>()
@ -218,13 +222,24 @@ impl CopilotChat {
}
pub fn new(fs: Arc<dyn Fs>, client: Arc<dyn HttpClient>, cx: &AppContext) -> Self {
let mut config_file_rx = watch_config_file(
cx.background_executor(),
fs,
copilot_chat_config_path().clone(),
);
let config_paths = copilot_chat_config_paths();
let resolve_config_path = {
let fs = fs.clone();
async move {
for config_path in config_paths.iter() {
if fs.metadata(config_path).await.is_ok_and(|v| v.is_some()) {
return config_path.clone();
}
}
config_paths[0].clone()
}
};
cx.spawn(|cx| async move {
let config_file = resolve_config_path.await;
let mut config_file_rx = watch_config_file(cx.background_executor(), fs, config_file);
while let Some(contents) = config_file_rx.next().await {
let oauth_token = extract_oauth_token(contents);
@ -318,9 +333,15 @@ async fn request_api_token(oauth_token: &str, client: Arc<dyn HttpClient>) -> Re
fn extract_oauth_token(contents: String) -> Option<String> {
serde_json::from_str::<serde_json::Value>(&contents)
.map(|v| {
v["github.com"]["oauth_token"]
.as_str()
.map(|v| v.to_string())
v.as_object().and_then(|obj| {
obj.iter().find_map(|(key, value)| {
if key.starts_with("github.com") {
value["oauth_token"].as_str().map(|v| v.to_string())
} else {
None
}
})
})
})
.ok()
.flatten()