Skip to content

Commit dc27545

Browse files
authored
Merge branch 'github:release' into release
2 parents ce7085e + 79e1a89 commit dc27545

8 files changed

Lines changed: 487 additions & 358 deletions

File tree

autoload/copilot.vim

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,6 @@ function! copilot#Dismiss() abort
148148
endfunction
149149

150150
let s:filetype_defaults = {
151-
\ 'yaml': 0,
152-
\ 'markdown': 0,
153-
\ 'help': 0,
154151
\ 'gitcommit': 0,
155152
\ 'gitrebase': 0,
156153
\ 'hgcommit': 0,
@@ -226,7 +223,7 @@ function! s:SuggestionTextWithAdjustments() abort
226223
endif
227224
let line = getline('.')
228225
let offset = col('.') - 1
229-
let choice_text = strpart(line, 0, copilot#doc#UTF16ToByteIdx(line, choice.range.start.character)) . choice.text
226+
let choice_text = strpart(line, 0, copilot#doc#UTF16ToByteIdx(line, choice.range.start.character)) . substitute(choice.text, "\n*$", '', '')
230227
let typed = strpart(line, 0, offset)
231228
let end_offset = copilot#doc#UTF16ToByteIdx(line, choice.range.end.character)
232229
if end_offset < 0
@@ -654,20 +651,16 @@ function! s:commands.setup(opts) abort
654651
let @+ = data.userCode
655652
let @* = data.userCode
656653
endif
657-
call s:Echo("First copy your one-time code: " . data.userCode)
654+
let codemsg = "First copy your one-time code: " . data.userCode . "\n"
658655
try
659656
if len(&mouse)
660657
let mouse = &mouse
661658
set mouse=
662659
endif
663660
if get(a:opts, 'bang')
664-
call s:Echo("In your browser, visit " . uri)
661+
call s:Echo(codemsg . "In your browser, visit " . uri)
665662
elseif len(browser)
666-
call s:Echo("Press ENTER to open GitHub in your browser")
667-
let c = getchar()
668-
while c isnot# 13 && c isnot# 10 && c isnot# 0
669-
let c = getchar()
670-
endwhile
663+
call input(codemsg . "Press ENTER to open GitHub in your browser")
671664
let status = {}
672665
call copilot#job#Stream(browser + [uri], v:null, v:null, function('s:BrowserCallback', [status]))
673666
let time = reltime()
@@ -680,9 +673,9 @@ function! s:commands.setup(opts) abort
680673
call s:Echo("Opened " . uri)
681674
endif
682675
else
683-
call s:Echo("Could not find browser. Visit " . uri)
676+
call s:Echo(codemsg . "Could not find browser. Visit " . uri)
684677
endif
685-
call s:Echo("Waiting (could take up to 5 seconds)")
678+
call s:Echo("Waiting (could take up to 10 seconds)")
686679
let request = copilot#Request('signInConfirm', {'userCode': data.userCode}).Wait()
687680
finally
688681
if exists('mouse')

autoload/copilot/agent.vim

Lines changed: 60 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,19 @@ if has('nvim')
1515
lua package.loaded._copilot = nil
1616
endif
1717

18-
let s:jobstop = function(exists('*jobstop') ? 'jobstop' : 'job_stop')
19-
function! s:Kill(agent, ...) abort
20-
if has_key(a:agent, 'job')
21-
call s:jobstop(a:agent.job)
22-
endif
23-
endfunction
24-
2518
function! s:AgentClose() dict abort
2619
if !has_key(self, 'job')
2720
return
2821
endif
29-
if exists('*chanclose')
30-
call chanclose(self.job, 'stdin')
31-
else
32-
call ch_close_in(self.job)
22+
let job = self.job
23+
if has_key(self, 'shutdown')
24+
call job_stop(job, 'kill')
25+
call copilot#logger#Warn('agent forcefully terminated')
26+
return
3327
endif
34-
call copilot#logger#Info('agent stopped')
35-
call timer_start(2000, function('s:Kill', [self]))
28+
let self.shutdown = self.Request('shutdown', {}, function(self.Notify, ['exit']))
29+
call timer_start(2000, { _ -> job_stop(job, 'kill') })
30+
call copilot#logger#Debug('agent shutdown initiated')
3631
endfunction
3732

3833
function! s:LogSend(request, line) abort
@@ -151,7 +146,7 @@ function! s:BufferText(bufnr) abort
151146
endfunction
152147

153148
function! s:LogMessage(params) abort
154-
call copilot#logger#Raw(get(a:params, 'level', 3), get(a:params, 'message', ''))
149+
call copilot#logger#Raw(get(a:params, 'type', 6), get(a:params, 'message', ''))
155150
endfunction
156151

157152
function! s:ShowMessageRequest(params) abort
@@ -294,7 +289,9 @@ function! s:OnResponse(agent, response, ...) abort
294289
endfunction
295290

296291
function! s:OnErr(agent, line, ...) abort
297-
call copilot#logger#Debug('<-! ' . a:line)
292+
if !has_key(a:agent, 'capabilities')
293+
call copilot#logger#Bare('<-! ' . a:line)
294+
endif
298295
endfunction
299296

300297
function! s:OnExit(agent, code, ...) abort
@@ -318,7 +315,7 @@ function! copilot#agent#LspInit(agent_id, initialize_result) abort
318315
return
319316
endif
320317
let instance = s:instances[a:agent_id]
321-
call timer_start(0, { _ -> s:GetCapabilitiesResult(a:initialize_result, instance)})
318+
call timer_start(0, { _ -> s:InitializeResult(a:initialize_result, instance)})
322319
endfunction
323320

324321
function! copilot#agent#LspExit(agent_id, code, signal) abort
@@ -383,11 +380,16 @@ function! s:Command() abort
383380
return [v:null, '', 'Vim version too old']
384381
endif
385382
let agent = get(g:, 'copilot_agent_command', '')
386-
if empty(agent) || !filereadable(agent)
387-
let agent = s:root . '/dist/agent.js'
388-
if !filereadable(agent)
383+
if type(agent) == type('')
384+
let agent = [expand(agent)]
385+
endif
386+
if empty(agent) || !filereadable(agent[0])
387+
let agent = [s:root . '/dist/agent.js']
388+
if !filereadable(agent[0])
389389
return [v:null, '', 'Could not find dist/agent.js (bad install?)']
390390
endif
391+
elseif agent[0] !~# '\.js$'
392+
return [agent + ['--stdio'], '', '']
391393
endif
392394
let node = get(g:, 'copilot_node_command', '')
393395
if empty(node)
@@ -403,7 +405,7 @@ function! s:Command() abort
403405
endif
404406
endif
405407
if get(g:, 'copilot_ignore_node_version')
406-
return [node + [agent, '--stdio'], '', '']
408+
return [node + agent + ['--stdio'], '', '']
407409
endif
408410
let node_version = s:GetNodeVersion(node)
409411
let warning = ''
@@ -426,57 +428,50 @@ function! s:Command() abort
426428
return [v:null, node_version.string, 'Node.js version 18.x or newer required but found ' . node_version.string]
427429
endif
428430
endif
429-
return [node + [agent, '--stdio'], node_version.string, warning]
431+
return [node + agent + ['--stdio'], node_version.string, warning]
430432
endfunction
431433

432434
function! s:UrlDecode(str) abort
433435
return substitute(a:str, '%\(\x\x\)', '\=iconv(nr2char("0x".submatch(1)), "utf-8", "latin1")', 'g')
434436
endfunction
435437

436-
function! copilot#agent#EditorInfo() abort
438+
function! s:EditorInfo() abort
437439
if !exists('s:editor_version')
438440
if has('nvim')
439441
let s:editor_version = matchstr(execute('version'), 'NVIM v\zs[^[:space:]]\+')
440442
else
441443
let s:editor_version = (v:version / 100) . '.' . (v:version % 100) . (exists('v:versionlong') ? printf('.%04d', v:versionlong % 1000) : '')
442444
endif
443445
endif
444-
let info = {
445-
\ 'editorInfo': {'name': has('nvim') ? 'Neovim': 'Vim', 'version': s:editor_version},
446-
\ 'editorPluginInfo': {'name': 'copilot.vim', 'version': s:plugin_version}}
447-
if type(get(g:, 'copilot_proxy')) == v:t_string
448-
let proxy = g:copilot_proxy
449-
else
450-
let proxy = ''
451-
endif
452-
let match = matchlist(proxy, '\c^\%([^:]\+://\)\=\%(\([^/#]\+@\)\)\=\%(\([^/:#]\+\)\|\[\([[:xdigit:]:]\+\)\]\)\%(:\(\d\+\)\)\=\%(/\|$\|?strict_\=ssl=\(.*\)\)')
453-
if !empty(match)
454-
let info.networkProxy = {'host': match[2] . match[3], 'port': empty(match[4]) ? 80 : +match[4]}
455-
if match[5] =~? '^[0f]'
456-
let info.networkProxy.rejectUnauthorized = v:false
457-
elseif match[5] =~? '^[1t]'
458-
let info.networkProxy.rejectUnauthorized = v:true
459-
elseif exists('g:copilot_proxy_strict_ssl')
460-
let info.networkProxy.rejectUnauthorized = empty(g:copilot_proxy_strict_ssl) ? v:false : v:true
461-
endif
462-
if !empty(match[1])
463-
let info.networkProxy.username = s:UrlDecode(matchstr(match[1], '^[^:@]*'))
464-
let info.networkProxy.password = s:UrlDecode(matchstr(match[1], ':\zs[^@]*'))
465-
endif
446+
return {'name': has('nvim') ? 'Neovim': 'Vim', 'version': s:editor_version}
447+
endfunction
448+
449+
function! copilot#agent#Settings() abort
450+
let settings = {
451+
\ 'http': {
452+
\ 'proxy': get(g:, 'copilot_proxy', v:null),
453+
\ 'proxyStrictSSL': get(g:, 'copilot_proxy_strict_ssl', v:null)},
454+
\ 'github-enterprise': {'uri': get(g:, 'copilot_auth_provider_url', v:null)},
455+
\ }
456+
if type(settings.http.proxy) ==# v:t_string && settings.http.proxy =~# '^[^/]\+$'
457+
let settings.http.proxy = 'http://' . settings.http.proxy
466458
endif
467-
if type(get(g:, 'copilot_auth_provider_url')) == v:t_string
468-
let info.authProvider = {'url': g:copilot_auth_provider_url}
459+
if type(get(g:, 'copilot_settings')) == v:t_dict
460+
call extend(settings, g:copilot_settings)
469461
endif
470-
return info
462+
return settings
471463
endfunction
472464

473-
function! s:GetCapabilitiesResult(result, agent) abort
465+
function! s:InitializeResult(result, agent) abort
474466
let a:agent.capabilities = get(a:result, 'capabilities', {})
475-
let info = copilot#agent#EditorInfo()
476-
call a:agent.Request('setEditorInfo', extend({'editorConfiguration': a:agent.editorConfiguration}, info))
467+
let info = {
468+
\ 'editorInfo': s:EditorInfo(),
469+
\ 'editorPluginInfo': {'name': 'copilot.vim', 'version': s:plugin_version},
470+
\ 'editorConfiguration': extend(copilot#agent#Settings(), a:agent.editorConfiguration)}
471+
call a:agent.Request('setEditorInfo', info)
477472
endfunction
478473

479-
function! s:GetCapabilitiesError(error, agent) abort
474+
function! s:InitializeError(error, agent) abort
480475
if a:error.code == s:error_exit
481476
let a:agent.startup_error = 'Agent exited with status ' . a:error.data.status
482477
else
@@ -508,7 +503,6 @@ function! copilot#agent#New(...) abort
508503
\ 'StartupError': function('s:AgentStartupError'),
509504
\ }
510505
let instance.methods = extend({
511-
\ 'LogMessage': function('s:LogMessage'),
512506
\ 'window/logMessage': function('s:LogMessage'),
513507
\ }, get(opts, 'methods', {}))
514508
let [command, node_version, command_error] = s:Command()
@@ -524,12 +518,18 @@ function! copilot#agent#New(...) abort
524518
if !empty(node_version)
525519
let instance.node_version = node_version
526520
endif
521+
let initializationOptions = {'copilotCapabilities': {}}
522+
for name in keys(instance.methods)
523+
if name =~# '^copilot/'
524+
let initializationOptions.copilotCapabilities[matchstr(name, '/\zs.*')] = v:true
525+
endif
526+
endfor
527527
if has('nvim')
528528
call extend(instance, {
529529
\ 'Close': function('s:LspClose'),
530530
\ 'Notify': function('s:LspNotify'),
531531
\ 'Request': function('s:LspRequest')})
532-
let instance.client_id = eval("v:lua.require'_copilot'.lsp_start_client(command, keys(instance.methods))")
532+
let instance.client_id = eval("v:lua.require'_copilot'.lsp_start_client(command, keys(instance.methods), initializationOptions)")
533533
let instance.id = instance.client_id
534534
else
535535
let state = {'headers': {}, 'mode': 'headers', 'buffer': ''}
@@ -543,14 +543,13 @@ function! copilot#agent#New(...) abort
543543
\ 'err_cb': { j, d -> timer_start(0, function('s:OnErr', [instance, d])) },
544544
\ 'exit_cb': { j, d -> timer_start(0, function('s:OnExit', [instance, d])) },
545545
\ })
546-
let instance.id = exists('*jobpid') ? jobpid(instance.job) : job_info(instance.job).process
547-
let capabilities = {'workspace': {'workspaceFolders': v:true}, 'copilot': {}}
548-
for name in keys(instance.methods)
549-
if name =~# '^copilot/'
550-
let capabilities.copilot[matchstr(name, '/\zs.*')] = v:true
551-
endif
552-
endfor
553-
let request = instance.Request('initialize', {'capabilities': capabilities}, function('s:GetCapabilitiesResult'), function('s:GetCapabilitiesError'), instance)
546+
let instance.id = job_info(instance.job).process
547+
let opts = {
548+
\ 'capabilities': {'workspace': {'workspaceFolders': v:true}},
549+
\ 'initializationOptions': initializationOptions,
550+
\ 'processId': getpid(),
551+
\ }
552+
let request = instance.Request('initialize', opts, function('s:InitializeResult'), function('s:InitializeError'), instance)
554553
endif
555554
let s:instances[instance.id] = instance
556555
return instance

autoload/copilot/logger.vim

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,14 @@ function! copilot#logger#File() abort
1010
return s:log_file
1111
endfunction
1212

13+
let s:level_prefixes = ['', '[ERROR] ', '[WARN] ', '[INFO] ', '[DEBUG] ', '[TRACE] ']
14+
1315
function! copilot#logger#Raw(level, message) abort
14-
if $COPILOT_AGENT_VERBOSE !~# '^\%(1\|true\)$' && a:level < 1
16+
if $COPILOT_AGENT_VERBOSE !~# '^\%(1\|true\)$' && a:level > 3
1517
return
1618
endif
1719
let lines = type(a:message) == v:t_list ? copy(a:message) : split(a:message, "\n", 1)
20+
let lines[0] = strftime('[%Y-%m-%dT%H:%M:%S] ') . get(s:level_prefixes, a:level, '[UNKNOWN] ') . get(lines, 0, '')
1821
try
1922
if !filewritable(s:log_file)
2023
return
@@ -26,23 +29,27 @@ function! copilot#logger#Raw(level, message) abort
2629
endfunction
2730

2831
function! copilot#logger#Trace(...) abort
29-
call copilot#logger#Raw(-1, a:000)
32+
call copilot#logger#Raw(5, a:000)
3033
endfunction
3134

3235
function! copilot#logger#Debug(...) abort
33-
call copilot#logger#Raw(0, a:000)
36+
call copilot#logger#Raw(4, a:000)
3437
endfunction
3538

3639
function! copilot#logger#Info(...) abort
37-
call copilot#logger#Raw(1, a:000)
40+
call copilot#logger#Raw(3, a:000)
3841
endfunction
3942

4043
function! copilot#logger#Warn(...) abort
4144
call copilot#logger#Raw(2, a:000)
4245
endfunction
4346

4447
function! copilot#logger#Error(...) abort
45-
call copilot#logger#Raw(3, a:000)
48+
call copilot#logger#Raw(1, a:000)
49+
endfunction
50+
51+
function! copilot#logger#Bare(...) abort
52+
call copilot#logger#Raw(0, a:000)
4653
endfunction
4754

4855
function! copilot#logger#Exception(...) abort

autoload/copilot/version.vim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
function! copilot#version#String() abort
2-
return '1.17.0'
2+
return '1.19.1'
33
endfunction

dist/agent.js

Lines changed: 394 additions & 264 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/agent.js.map

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

doc/copilot.txt

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,13 @@ g:copilot_node_command Tell Copilot what `node` binary to use with
7575
\ "~/.nodenv/versions/18.18.0/bin/node"
7676
<
7777
*g:copilot_proxy*
78-
g:copilot_proxy Tell Copilot what proxy server to use. This is a
79-
string in the format of `hostname:port` or
80-
`username:password@host:port`.
78+
g:copilot_proxy Tell Copilot what proxy server to use.
8179
>
82-
let g:copilot_proxy = 'localhost:3128'
80+
let g:copilot_proxy = 'http://localhost:3128'
8381
<
82+
If this is not set, Copilot will use the value of
83+
environment variables like $HTTPS_PROXY.
84+
8485
*g:copilot_proxy_strict_ssl*
8586
g:copilot_proxy_strict_ssl
8687
Corporate proxies sometimes use a man-in-the-middle
@@ -90,6 +91,10 @@ g:copilot_proxy_strict_ssl
9091
>
9192
let g:copilot_proxy_strict_ssl = v:false
9293
<
94+
You can also tell Node.js to disable SSL verification
95+
by setting the $NODE_TLS_REJECT_UNAUTHORIZED
96+
environment variable to "0".
97+
9398
MAPS *copilot-maps*
9499

95100
*copilot-i_<Tab>*

lua/_copilot.lua

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
local copilot = {}
22

3-
copilot.lsp_start_client = function(cmd, handler_names)
4-
local capabilities = vim.lsp.protocol.make_client_capabilities()
3+
copilot.lsp_start_client = function(cmd, handler_names, init_options)
54
local handlers = {}
65
local id
76
for _, name in ipairs(handler_names) do
@@ -13,16 +12,12 @@ copilot.lsp_start_client = function(cmd, handler_names)
1312
end
1413
end
1514
end
16-
if name:match('^copilot/') then
17-
capabilities.copilot = capabilities.copilot or {}
18-
capabilities.copilot[name:match('^copilot/(.*)$')] = true
19-
end
2015
end
2116
id = vim.lsp.start_client({
2217
cmd = cmd,
2318
cmd_cwd = vim.call('copilot#job#Cwd'),
2419
name = 'copilot',
25-
capabilities = capabilities,
20+
init_options = init_options,
2621
handlers = handlers,
2722
get_language_id = function(bufnr, filetype)
2823
return vim.call('copilot#doc#LanguageForFileType', filetype)

0 commit comments

Comments
 (0)