@@ -655,6 +655,51 @@ M.append_selection = function(params, origin_buf, target_buf)
655
655
vim .api .nvim_buf_set_lines (target_buf , last_content_line , - 1 , false , lines )
656
656
end
657
657
658
+ function M .refresh_copilot_bearer ()
659
+ if not M .providers .copilot or not M .providers .copilot .secret then
660
+ return
661
+ end
662
+ local secret = M .providers .copilot .secret
663
+
664
+ local bearer = M ._state .copilot_bearer or {}
665
+ if bearer .token and bearer .expires_at and bearer .expires_at > os.time () then
666
+ return
667
+ end
668
+
669
+ local curl_params = vim .deepcopy (M .config .curl_params or {})
670
+ local args = {
671
+ " -s" ,
672
+ " -v" ,
673
+ " https://api.github.com/copilot_internal/v2/token" ,
674
+ " -H" ,
675
+ " Content-Type: application/json" ,
676
+ " -H" ,
677
+ " accept: */*" ,
678
+ " -H" ,
679
+ " authorization: token " .. secret ,
680
+ " -H" ,
681
+ " editor-version: vscode/1.85.1" ,
682
+ " -H" ,
683
+ " editor-plugin-version: copilot-chat/0.12.2023120701" ,
684
+ " -H" ,
685
+ " user-agent: GitHubCopilotChat/0.12.2023120701" ,
686
+ }
687
+
688
+ for _ , arg in ipairs (args ) do
689
+ table.insert (curl_params , arg )
690
+ end
691
+
692
+ M ._H .process (nil , " curl" , curl_params , function (code , signal , stdout , stderr )
693
+ if code ~= 0 then
694
+ M .error (string.format (" Copilot bearer resolve exited: %d, %d" , code , signal ))
695
+ return
696
+ end
697
+
698
+ M ._state .copilot_bearer = vim .json .decode (stdout )
699
+ M .refresh_state ()
700
+ end , nil , nil )
701
+ end
702
+
658
703
-- setup function
659
704
M ._setup_called = false
660
705
--- @param opts table | nil # table with options
@@ -674,12 +719,12 @@ M.setup = function(opts)
674
719
M .config = vim .deepcopy (config )
675
720
676
721
-- merge nested tables
677
- local mergeTables = { " hooks" , " agents" , " image_agents" }
722
+ local mergeTables = { " hooks" , " agents" , " image_agents" , " providers " }
678
723
for _ , tbl in ipairs (mergeTables ) do
679
724
M [tbl ] = M [tbl ] or {}
680
725
--- @diagnostic disable-next-line : param-type-mismatch
681
726
for k , v in pairs (M .config [tbl ]) do
682
- if tbl == " hooks" then
727
+ if tbl == " hooks" or tbl == " providers " then
683
728
M [tbl ][k ] = v
684
729
elseif tbl == " agents" or tbl == " image_agents" then
685
730
M [tbl ][v .name ] = v
@@ -689,7 +734,7 @@ M.setup = function(opts)
689
734
690
735
opts [tbl ] = opts [tbl ] or {}
691
736
for k , v in pairs (opts [tbl ]) do
692
- if tbl == " hooks" then
737
+ if tbl == " hooks" or tbl == " providers " then
693
738
M [tbl ][k ] = v
694
739
elseif tbl == " agents" or tbl == " image_agents" then
695
740
M [tbl ][v .name ] = v
@@ -753,6 +798,13 @@ M.setup = function(opts)
753
798
end
754
799
end
755
800
801
+ -- remove invalid providers
802
+ for name , provider in pairs (M .providers ) do
803
+ if type (provider ) ~= " table" or not provider .endpoint then
804
+ M .providers [name ] = nil
805
+ end
806
+ end
807
+
756
808
-- prepare agent completions
757
809
M ._chat_agents = {}
758
810
M ._command_agents = {}
@@ -828,9 +880,29 @@ M.setup = function(opts)
828
880
M .error (" curl is not installed, run :checkhealth gp" )
829
881
end
830
882
831
- if type (M .config .openai_api_key ) == " table" then
883
+ for name , _ in pairs (M .providers ) do
884
+ M .resolve_secret (name )
885
+ end
886
+
887
+ -- M.resolve_secret(M.config, "openai_api_key")
888
+ -- M.valid_api_key()
889
+ end
890
+
891
+ --- @provider string # provider name
892
+ function M .resolve_secret (provider )
893
+ local post_process = function (name )
894
+ local p = M .providers [name ]
895
+ if p .secret and type (p .secret ) == " string" then
896
+ p .secret = p .secret :gsub (" ^%s*(.-)%s*$" , " %1" )
897
+ end
898
+
899
+ M .refresh_copilot_bearer ()
900
+ end
901
+
902
+ local secret = M .providers [provider ].secret
903
+ if secret and type (secret ) == " table" then
832
904
--- @diagnostic disable-next-line : param-type-mismatch
833
- local copy = vim .deepcopy (M . config . openai_api_key )
905
+ local copy = vim .deepcopy (secret )
834
906
--- @diagnostic disable-next-line : param-type-mismatch
835
907
local cmd = table.remove (copy , 1 )
836
908
local args = copy
@@ -840,18 +912,23 @@ M.setup = function(opts)
840
912
local content = stdout_data :match (" ^%s*(.-)%s*$" )
841
913
if not string.match (content , " %S" ) then
842
914
M .warning (
843
- " response from the config.openai_api_key command "
844
- .. vim .inspect (M .config .openai_api_key )
915
+ " response from the config.providers."
916
+ .. provider
917
+ .. " .secret command "
918
+ .. vim .inspect (secret )
845
919
.. " is empty"
846
920
)
847
921
return
848
922
end
849
- M .config .openai_api_key = content
923
+ M .providers [provider ].secret = content
924
+ post_process (provider )
850
925
else
851
926
M .warning (
852
- " config.openai_api_key command "
853
- .. vim .inspect (M .config .openai_api_key )
854
- .. " to retrieve openai_api_key failed:\n code: "
927
+ " config.providers."
928
+ .. provider
929
+ .. " .secret command "
930
+ .. vim .inspect (secret )
931
+ .. " to retrieve the secret failed:\n code: "
855
932
.. code
856
933
.. " , signal: "
857
934
.. signal
@@ -863,7 +940,7 @@ M.setup = function(opts)
863
940
end
864
941
end )
865
942
else
866
- M . valid_api_key ( )
943
+ post_process ( provider )
867
944
end
868
945
end
869
946
@@ -903,6 +980,8 @@ M.refresh_state = function()
903
980
M ._state .image_agent = M ._image_agents [1 ]
904
981
end
905
982
983
+ M ._state .copilot_bearer = M ._state .copilot_bearer or state .copilot_bearer or nil
984
+
906
985
M .table_to_file (M ._state , state_file )
907
986
908
987
M .prepare_commands ()
0 commit comments