51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
# File 'lib/copilot2gpt/app.rb', line 51
def complete(args)
github_token = request.env['HTTP_AUTHORIZATION'].to_s.sub('Bearer ', '')
if github_token.empty?
halt 401, {'Content-Type' => 'application/json'}, {:message => 'Unauthorized'}.to_json
end
@copilot_token = Copilot2gpt::Token.get_copilot_token(github_token)
content = params['content']
url = "https://api.githubcopilot.com/chat/completions"
chat_request = Copilot2GPT::ChatRequest.with_default(content, args)
conn = Faraday.new(url: url)
if !chat_request.one_time_return
stream do |response_stream|
resp = conn.post do |req|
req. = (@copilot_token)
req.body = chat_request.to_json
buffered_line = ""
req.options.on_data = Proc.new do |chunk, overall_received_bytes, env|
chunk.each_line do |line|
line.chomp!
next unless line.present?
if line.start_with?("data: ")
buffered_line = line
message = JSON.parse(line.sub(/^data: /, '')) rescue next
else
buffered_line += line
message = JSON.parse(buffered_line.sub(/^data: /, '')) rescue next
end
message = message.with_indifferent_access
if @chatbox
message[:choices].select! do |choice|
choice.dig(:delta, :content)
end
next unless message[:choices].any?
end
if @mock_ai_gateway
message.merge!(object: "chat.completion.chunk", model: "gpt-4")
end
message_json = message.to_json + "\n\n"
message_json = "data: " + message_json unless @mock_ai_gateway
response_stream << message_json
end
end
end
if resp.status != 200
halt resp.status, {'Content-Type' => 'application/json'}, {:error => resp.body}.to_json
return
end
end
else
resp = conn.post do |req|
req. = (@copilot_token)
req.body = chat_request.to_json
end
if resp.status != 200
halt resp.status, {'Content-Type' => 'application/json'}, {:error => resp.body}.to_json
return
end
buffer = ""
resp.body.each_line do |line|
if line.start_with?("data: ")
data = line.sub("data: ", "")
obj = JSON.parse(data) rescue next
if obj.key?("choices") && obj["choices"].is_a?(Array) && !obj["choices"].empty?
choice = obj["choices"][0]
if choice.is_a?(Hash) && choice.key?("delta") && choice["delta"].is_a?(Hash)
delta = choice["delta"]
if delta.key?("content") && delta["content"].is_a?(String)
buffer += delta["content"]
end
end
end
end
end
return [200, {'Content-Type' => 'text/event-stream; charset=utf-8'}, buffer]
end
end
|