diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 18550d56..d4f6f299 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "2.0.4" + ".": "3.0.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b21136f..dc724ff4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## [3.0.0](https://github.com/zbirenbaum/copilot.lua/compare/v2.0.4...v3.0.0) (2026-06-11) + + +### ⚠ BREAKING CHANGES + +* remove support for apps.json as it is not used anymore by LSP + +### Bug Fixes + +* remove support for apps.json as it is not used anymore by LSP ([6afee36](https://github.com/zbirenbaum/copilot.lua/commit/6afee363c52b6063a11b409ed20a3f1ab95325ab)) + ## [2.0.4](https://github.com/zbirenbaum/copilot.lua/compare/v2.0.3...v2.0.4) (2026-05-15) diff --git a/README.md b/README.md index 1dd5b95b..c0c3c8fb 100644 --- a/README.md +++ b/README.md @@ -97,15 +97,15 @@ To sign in with a different account: :Copilot auth signin ``` -To view your current authentication token information: +To view your current authentication status: ``` :Copilot auth info ``` -Credentials are stored in: -- **Linux/macOS:** `~/.config/github-copilot/apps.json` (or `$XDG_CONFIG_HOME/github-copilot/apps.json`) -- **Windows:** `~/AppData/Local/github-copilot/apps.json` +Credentials are stored by the Copilot Language Server in: +- **Linux/macOS:** `~/.config/github-copilot/auth.db` (or `$XDG_CONFIG_HOME/github-copilot/auth.db`) +- **Windows:** `~/AppData/Local/github-copilot/auth.db` diff --git a/lua/copilot/auth/init.lua b/lua/copilot/auth/init.lua index c9d60a50..14a165ef 100644 --- a/lua/copilot/auth/init.lua +++ b/lua/copilot/auth/init.lua @@ -152,34 +152,26 @@ function M.find_config_path() logger.error("could not find config path") end ----@return table|nil -function M.get_creds() - local filename = M.find_config_path() .. "/github-copilot/apps.json" - - if vim.fn.filereadable(filename) == 0 then - logger.error("Copilot auth file could not be read from:" .. filename) - return - end - - local filedata = vim.api.nvim_eval("readfile('" .. filename .. "')") - - if not filedata or #filedata == 0 then - logger.error("Copilot's apps.json file not found or empty, make sure to sign in first") - return - end - - local appsdata = vim.json.decode(filedata[1]) - return appsdata -end - function M.info() - local info = M.get_creds() - if not info then - logger.error("no GitHub Copilot token found, make sure to sign in first") - return - end + c.use_client(function(client) + api.check_status( + client, + {}, + ---@param status copilot_check_status_data + function(err, status) + if err then + logger.error("failed to retrieve authentication status: " .. tostring(err)) + return + end - logger.notify("GitHub Copilot token information: ", info) + if status.user then + logger.notify("Authenticated as GitHub user: " .. status.user .. " (status: " .. status.status .. ")") + else + logger.error("not authenticated (status: " .. status.status .. "), make sure to sign in first") + end + end + ) + end) end ---@class copilot_auth_cache diff --git a/lua/copilot/health.lua b/lua/copilot/health.lua index ee13b117..7742267f 100644 --- a/lua/copilot/health.lua +++ b/lua/copilot/health.lua @@ -1,5 +1,6 @@ local M = {} +local api = require("copilot.api") local auth = require("copilot.auth") local c = require("copilot.client") local config = require("copilot.config") @@ -35,13 +36,13 @@ function M.check() end local config_path = auth.find_config_path() - local creds_ok, creds = pcall(auth.get_creds) - if creds_ok and creds then - ok("Local credentials file found") - info("Location: `" .. (config_path or "unknown") .. "/github-copilot/apps.json`") + local auth_db_path = (config_path or "unknown") .. "/github-copilot/auth.db" + if config_path and vim.fn.filereadable(auth_db_path) == 1 then + ok("Local credentials found") + info("Location: `" .. auth_db_path .. "`") else - info("No local credentials file found") - info("Expected location: `" .. (config_path or "unknown") .. "/github-copilot/apps.json`") + info("No local credentials found") + info("Expected location: `" .. auth_db_path .. "`") info("Run `:Copilot auth` to authenticate") end @@ -63,11 +64,39 @@ function M.check() ok("LSP client is available and running") info("Client ID: " .. tostring(client.id)) - local lsp_authenticated = auth.is_authenticated() - if lsp_authenticated then - ok("LSP authentication status: authenticated") + vim.wait(2000, function() + return c.initialized + end, 50) + + if not c.initialized then + warn("LSP client is running but has not finished initializing") + info("This is not an authentication problem, retry `:checkhealth copilot` once Copilot is active") else - warn("LSP authentication status: not authenticated") + local done = false + local status_err, status = nil, nil + api.check_status( + client, + {}, + ---@param status_data copilot_check_status_data + function(err, status_data) + status_err, status = err, status_data + done = true + end + ) + vim.wait(5000, function() + return done + end, 50) + + if not done then + warn("LSP authentication status: no response from server (timed out)") + elseif status_err then + warn("LSP authentication status: " .. tostring(status_err)) + elseif status and status.user then + ok("LSP authentication status: authenticated as `" .. status.user .. "`") + else + warn("LSP authentication status: not authenticated (status: " .. (status and status.status or "unknown") .. ")") + info("Run `:Copilot auth signin` to authenticate") + end end info("For detailed authentication status, run `:Copilot status`") diff --git a/tests/stubs/lsp_server.lua b/tests/stubs/lsp_server.lua index 314ee79e..5c5712da 100644 --- a/tests/stubs/lsp_server.lua +++ b/tests/stubs/lsp_server.lua @@ -2,6 +2,12 @@ local logger = require("copilot.logger") local M = {} M.messages = {} + +local numbers_as_arrays_text = " 19,20,21\n 22,23,24\n 25,26,27\n}\n{\n" + .. " 28,29,30\n 31,32,33\n 34,35,36\n}\n{\n" + .. " 37,38,39\n 40,41,42\n 43,44,45\n}\n{\n" + .. " 46,47,48\n 49,50,51\n 52,53,54\n}" + M.completion_responses = { ["numbers_with_spaces.txt"] = { completions = { @@ -78,7 +84,7 @@ M.completion_responses = { ["numbers_as_arrays.txt"] = { completions = { { - displayText = " 19,20,21\n 22,23,24\n 25,26,27\n}\n{\n 28,29,30\n 31,32,33\n 34,35,36\n}\n{\n 37,38,39\n 40,41,42\n 43,44,45\n}\n{\n 46,47,48\n 49,50,51\n 52,53,54\n}", + displayText = numbers_as_arrays_text, docVersion = 30, position = { character = 0, @@ -94,7 +100,7 @@ M.completion_responses = { line = 11, }, }, - text = " 19,20,21\n 22,23,24\n 25,26,27\n}\n{\n 28,29,30\n 31,32,33\n 34,35,36\n}\n{\n 37,38,39\n 40,41,42\n 43,44,45\n}\n{\n 46,47,48\n 49,50,51\n 52,53,54\n}", + text = numbers_as_arrays_text, uuid = "1df58ae9-3e93-4e6a-b514-218a9fe7e816", }, }, diff --git a/tests/test_auth.lua b/tests/test_auth.lua index e96043fe..c51a7276 100644 --- a/tests/test_auth.lua +++ b/tests/test_auth.lua @@ -31,7 +31,7 @@ T["auth()"]["auth before attaching, should not give error"] = function() return has_passed() end, 50) - return messages + return messages ]]) u.expect_match(messages, ".*Authenticated as GitHub user.*") @@ -66,12 +66,33 @@ T["auth()"]["auth issue replication"] = function() return has_passed() end, 50) - return messages + return messages ]]) u.expect_match(messages, ".*Online.*") end +T["auth()"]["auth info reports authentication status from the LSP"] = function() + child.configure_copilot() + child.cmd("Copilot auth info") + + local messages = child.lua([[ + local messages = "" + local function has_passed() + messages = vim.api.nvim_exec("messages", { output = true }) or "" + return string.find(messages, ".*Authenticated as GitHub user: someUser.*") ~= nil + end + + vim.wait(5000, function() + return has_passed() + end, 50) + + return messages + ]]) + + u.expect_match(messages, ".*Authenticated as GitHub user: someUser.*") +end + T["auth()"]["is_authenticated when not authed returns false"] = function() child.configure_copilot() diff --git a/tests/test_client_lifecycle.lua b/tests/test_client_lifecycle.lua index f540782d..601d0cde 100644 --- a/tests/test_client_lifecycle.lua +++ b/tests/test_client_lifecycle.lua @@ -1,6 +1,5 @@ local child_helper = require("tests.child_helper") local child = child_helper.new_child_neovim("test_client_lifecycle") -local u = require("tests.utils") local eq = MiniTest.expect.equality local T = MiniTest.new_set({ @@ -31,9 +30,6 @@ T["client lifecycle()"]["ensure_client_started with starting guard prevents dupl -- Simulate the guard being set (as if startup is in progress) child.lua("c.client_starting = true") - -- Store original client id - local original_id = child.lua("return c.id") - -- Try to start another client - should be blocked by the guard child.lua([[ c.id = nil diff --git a/tests/test_health.lua b/tests/test_health.lua index 46274d3d..d0f28f98 100644 --- a/tests/test_health.lua +++ b/tests/test_health.lua @@ -1,6 +1,7 @@ local eq = MiniTest.expect.equality local child_helper = require("tests.child_helper") local child = child_helper.new_child_neovim("test_health") +local u = require("tests.utils") local T = MiniTest.new_set({ hooks = { @@ -33,6 +34,28 @@ T["health()"]["check runs without error when client is not started"] = function( eq(result, true) end +T["health()"]["reports auth.db as local credentials location"] = function() + child.configure_copilot() + child.cmd("checkhealth copilot") + + local output = child.lua([[ + return table.concat(vim.api.nvim_buf_get_lines(0, 0, -1, false), "\n") + ]]) + + u.expect_match(output, "auth%.db") +end + +T["health()"]["reports LSP authentication status without requiring a buffer attach"] = function() + child.configure_copilot() + child.cmd("checkhealth copilot") + + local output = child.lua([[ + return table.concat(vim.api.nvim_buf_get_lines(0, 0, -1, false), "\n") + ]]) + + u.expect_match(output, "authentication status: authenticated as `someUser`") +end + T["health()"]["check runs without error when client is disabled"] = function() child.lua([[ local lsp = require("copilot.lsp") diff --git a/tests/test_panel.lua b/tests/test_panel.lua index 187d58ed..44616299 100644 --- a/tests/test_panel.lua +++ b/tests/test_panel.lua @@ -57,7 +57,7 @@ end T["panel.utils()"] = MiniTest.new_set() T["panel.utils()"]["panel_uri_from_doc_uri"] = function() - local panel_uri = "" + local panel_uri if vim.fn.has("win32") > 0 then panel_uri = "copilot:///C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua/lua/copilot/suggestion/init.lua" @@ -75,7 +75,7 @@ T["panel.utils()"]["panel_uri_from_doc_uri"] = function() end T["panel.utils()"]["panel_uri_to_doc_uri"] = function() - local doc_uri = "" + local doc_uri if vim.fn.has("win32") > 0 then doc_uri = "file:///C:/Users/antoi/AppData/Local/nvim-data/lazy/copilot.lua/lua/copilot/suggestion/init.lua"