Skip to content

copilot_chat: Support SDK auth.db and reload via LSP didChangeStatus#57758

Closed
eodus wants to merge 1 commit into
zed-industries:mainfrom
eodus:fix/copilot-auth-db-fallback
Closed

copilot_chat: Support SDK auth.db and reload via LSP didChangeStatus#57758
eodus wants to merge 1 commit into
zed-industries:mainfrom
eodus:fix/copilot-auth-db-fallback

Conversation

@eodus

@eodus eodus commented May 26, 2026

Copy link
Copy Markdown
Contributor

Summary

The GitHub Copilot SDK migrated its OAuth token storage from JSON files (apps.json / hosts.json) to a SQLite database (auth.db) under the same github-copilot config directory. Zed only knew about the JSON files, so users on a fresh SDK install saw an empty Copilot Chat model dropdown even though they were signed in via the LSP (edit predictions worked fine, since those go through the LSP directly).

This PR teaches copilot_chat to read auth.db, and replaces the previous filesystem watcher with an LSP-driven reload triggered by didChangeStatus from the copilot crate.

Related: #57219 (same user-visible symptom; different root cause from #57738 — both fixes are needed depending on which SDK build the user has).

Changes

  • extract_oauth_token_from_db() reads token_ciphertext from the oauth_tokens table via the existing sqlez dependency. The column stores the raw ghu_... OAuth token as text on current SDK builds. Format is validated (prefix + length ≥ 36 + ASCII alphanumeric/underscore) so we fail closed if the SDK changes the schema again.
  • CopilotChat::reload_auth(cx) is a small public method that re-reads the token. On sign-out it also clears api_endpoint and models so a subsequent sign-in re-discovers them rather than reusing stale state.
  • notify_copilot_chat_auth_changed() in copilot.rs calls reload_auth whenever update_sign_in_status would emit CopilotAuthSignedIn / CopilotAuthSignedOut. The copilot crate already depends on copilot_chat, so this is the clean direction of the cross-crate poke.
  • Removed the previous fs.watch() loop on the config directory.

Why not just keep the filesystem watcher?

It was flaky on Windows specifically because of how SQLite finalises writes:

  • The WAL is written alongside the main file and finalised with rename/replace; some commits surfaced as multiple watcher events, others as none.
  • The watcher sometimes fired before the new token row was committed — we read None, then the LSP told us we were signed in.
  • A 100 ms debounce papered over the symptom but not the cause.

Why not sqlite3_update_hook / commit_hook?

Investigated and rejected. SQLite update/commit hooks are per-connection, in-process callbacks: they fire only when your own connection writes the DB. They're not an IPC mechanism. The Copilot LSP writes auth.db from a different process — our connection would never see those writes regardless of how many hooks we register. SQLite has no LISTEN/NOTIFY equivalent; that's a deliberate library-not-server design choice.

Why the LSP signal?

The Copilot LSP already has the ground-truth event — didChangeStatus. It's the same notification VS Code's Copilot extension subscribes to internally. Tapping the producer's semantic signal beats watching its incidental filesystem side-effects: it works the same way on Windows / macOS / Linux, and it fires after the token is durably written.

Testing

Tested on Windows 11 with the official Copilot SDK build that ships auth.db:

  • Cold sign-in: model dropdown populates within a couple of seconds of the LSP reporting Authorized, no restart needed.
  • Sign-out: model list clears; subsequent sign-in re-fetches endpoint + models.
  • Legacy apps.json / hosts.json users: unaffected (JSON path is tried first).

Notes for reviewers

  • The token-format check (ghu_ prefix, length ≥ 36, ASCII alnum/_) is intentional defence-in-depth in case the SDK eventually starts storing actually-ciphertext in token_ciphertext. If that happens, we log a warning and return None rather than passing garbage to the API.
  • No new dependencies — sqlez is already a workspace member.

Release Notes:

  • Fixed GitHub Copilot Chat showing an empty model dropdown for users on newer Copilot SDK builds that store the OAuth token in auth.db instead of apps.json/hosts.json, and made the model list refresh automatically after signing in or out without requiring a restart.

@cla-bot cla-bot Bot added the cla-signed The user has signed the Contributor License Agreement label May 26, 2026
@zed-community-bot zed-community-bot Bot added the first contribution the author's first pull request to Zed. NOTE: the label application is automated via github actions label May 26, 2026
@maxdeviant maxdeviant changed the title copilot_chat: support SDK auth.db and reload via LSP didChangeStatus copilot_chat: Support SDK auth.db and reload via LSP didChangeStatus May 26, 2026
@zed-industries-bot

Copy link
Copy Markdown
Contributor
Warnings
⚠️

This PR is missing release notes.

Please add a "Release Notes" section that describes the change:

Release Notes:

- Added/Fixed/Improved ...

If your change is not user-facing, you can use "N/A" for the entry:

Release Notes:

- N/A

Generated by 🚫 dangerJS against ed4c004

The GitHub Copilot SDK migrated its OAuth token storage from JSON files (apps.json / hosts.json) to a SQLite database (auth.db) under the same github-copilot config directory. Zed only knew about the JSON files, so users on a fresh SDK install saw an empty Copilot Chat model dropdown even though they were signed in via the LSP.

Changes:

* Add extract_oauth_token_from_db() which reads token_ciphertext from the oauth_tokens table via the existing sqlez dependency. The column stores the raw 'ghu_...' OAuth token as text on current SDK builds; format is validated (prefix + length + charset) so we fail closed if the SDK changes the schema.

* Replace the previous fs.watch() loop on the config directory with an LSP-driven reload. The copilot crate already receives didChangeStatus notifications from the Copilot language server; we now route those through a small public CopilotChat::reload_auth() method. SQLite's WAL writes interact poorly with directory watchers (we observed both spurious early fires and missed commits on Windows), and the LSP gives us a clean, semantic, cross-platform signal that fires after the token is durable.

* Sign-out clears api_endpoint and the model catalogue so a subsequent sign-in re-discovers them rather than reusing stale state.

Tested on Windows 11 with the official Copilot SDK build that ships auth.db; cold sign-in now populates the model list within a couple of seconds of the LSP reporting Authorized status, with no manual restart.
@eodus eodus force-pushed the fix/copilot-auth-db-fallback branch from ed4c004 to 1268a3d Compare May 26, 2026 19:48
@Anthony-Eid Anthony-Eid mentioned this pull request May 26, 2026
5 tasks
@Anthony-Eid

Copy link
Copy Markdown
Contributor

@eodus Could you please give me permission to push to your Zed fork? I want to look at your other PR and get it merged soon, but there's some changes that I want to make to it first.

Also, I made a PR based on this one because I could push up my changes directly. #57764, if I get permission soon ish or you cherry pick my changes I'll merge yours instead

@smitbarmase smitbarmase added the area:ai/copilot AI feedback for GitHub Copilot via ACP label May 27, 2026
niallobrien pushed a commit to niallobrien/zed that referenced this pull request May 28, 2026
This PR uses zed-industries#57758 as a base
and adds tests, cleans up the comments, and checks changes the database
query used in auth.db to include oauth key.

Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Closes #ISSUE

Release Notes:

- Fixed GitHub Copilot Chat showing an empty model dropdown for users on
newer Copilot SDK builds

---------

Co-authored-by: Alexander Shlemov <eodus@users.noreply.github.com>
Co-authored-by: cameron <cameron.studdstreet@gmail.com>
zed-zippy Bot added a commit that referenced this pull request May 28, 2026
Cherry-pick of #57764 to stable

----
This PR uses #57758 as a base
and adds tests, cleans up the comments, and checks changes the database
query used in auth.db to include oauth key.

Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX

checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Closes #ISSUE

Release Notes:

- Fixed GitHub Copilot Chat showing an empty model dropdown for users on
newer Copilot SDK builds

---------

Co-authored-by: Alexander Shlemov <eodus@users.noreply.github.com>
Co-authored-by: cameron <cameron.studdstreet@gmail.com>

Co-authored-by: Anthony Eid <56899983+Anthony-Eid@users.noreply.github.com>
Co-authored-by: Alexander Shlemov <eodus@users.noreply.github.com>
Co-authored-by: cameron <cameron.studdstreet@gmail.com>
zed-zippy Bot added a commit that referenced this pull request May 28, 2026
Cherry-pick of #57764 to preview

----
This PR uses #57758 as a base
and adds tests, cleans up the comments, and checks changes the database
query used in auth.db to include oauth key.

Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX

checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Closes #ISSUE

Release Notes:

- Fixed GitHub Copilot Chat showing an empty model dropdown for users on
newer Copilot SDK builds

---------

Co-authored-by: Alexander Shlemov <eodus@users.noreply.github.com>
Co-authored-by: cameron <cameron.studdstreet@gmail.com>

Co-authored-by: Anthony Eid <56899983+Anthony-Eid@users.noreply.github.com>
Co-authored-by: Alexander Shlemov <eodus@users.noreply.github.com>
Co-authored-by: cameron <cameron.studdstreet@gmail.com>
@eodus

eodus commented May 28, 2026

Copy link
Copy Markdown
Contributor Author

Fixed and merged by the repo owners

@eodus eodus closed this May 28, 2026
TomPlanche pushed a commit to TomPlanche/zed that referenced this pull request Jun 2, 2026
This PR uses zed-industries#57758 as a base
and adds tests, cleans up the comments, and checks changes the database
query used in auth.db to include oauth key.

Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Closes #ISSUE

Release Notes:

- Fixed GitHub Copilot Chat showing an empty model dropdown for users on
newer Copilot SDK builds

---------

Co-authored-by: Alexander Shlemov <eodus@users.noreply.github.com>
Co-authored-by: cameron <cameron.studdstreet@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:ai/copilot AI feedback for GitHub Copilot via ACP cla-signed The user has signed the Contributor License Agreement first contribution the author's first pull request to Zed. NOTE: the label application is automated via github actions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants