Skip to content

Commit 80ca615

Browse files
committed
feat: verbose mode
better format files
1 parent 5b54522 commit 80ca615

File tree

6 files changed

+348
-301
lines changed

6 files changed

+348
-301
lines changed

src/api/client.v

+131-118
Original file line numberDiff line numberDiff line change
@@ -1,173 +1,186 @@
11
module api
22

3-
import net.http
3+
import display
44
import json
5+
import log
6+
import net.http
57
import os
6-
import display
78

89
const config_file = os.join_path(os.home_dir(), '.config', 'jarvis', 'config.toml')
9-
const system_prompt = 'You are a helpful assistant named Jarvis, who helps developers to make their life easier every day through the CLI. You make clear, concise, and structured answers, easy to read in a command line interface.'
10+
const system_prompt = 'You are a helpful assistant named Jarvis, who helps developers to make their life easier every day through the CLI.
11+
You make clear, concise, and structured answers, easy to read in a command line interface.'
12+
1013
const temperature = 1.0
14+
const timeout_seconds = 30
1115

1216
pub struct Config {
1317
pub:
14-
api_host string
15-
api_port string
16-
api_key string
17-
api_model string
18-
api_tls bool
18+
api_host string
19+
api_port string
20+
api_key string
21+
api_model string
22+
api_tls bool
1923
}
2024

2125
pub struct Client {
2226
pub:
23-
config Config
27+
config Config
2428
}
2529

2630
struct Message {
27-
role string
28-
content string
31+
role string
32+
content string
2933
}
3034

3135
struct CompletionRequest {
32-
model string
33-
messages []Message
34-
temperature f64
35-
stream bool
36+
model string
37+
messages []Message
38+
temperature f64
39+
stream bool
3640
}
3741

3842
struct ChatChoice {
39-
delta struct {
40-
content string
41-
}
42-
finish_reason string
43+
delta struct {
44+
content string
45+
}
46+
finish_reason string
4347
}
4448

4549
struct ChatResponse {
46-
id string
47-
object string
48-
created int
49-
model string
50-
choices []ChatChoice
50+
id string
51+
object string
52+
created int
53+
model string
54+
choices []ChatChoice
5155
}
5256

5357
pub fn new_client(config Config) !Client {
54-
return Client{
55-
config: config
56-
}
58+
return Client{
59+
config: config
60+
}
5761
}
5862

5963
pub fn (c Client) stream_completion(prompt string) ! {
60-
request := CompletionRequest{
61-
model: c.config.api_model
62-
messages: [
63-
Message{
64-
role: 'system'
65-
content: system_prompt
66-
},
67-
Message{
68-
role: 'user'
69-
content: prompt
70-
}
71-
]
72-
temperature: temperature
73-
stream: true
74-
}
75-
76-
request_data := json.encode(request)
77-
78-
mut headers := []string{}
79-
headers << 'POST /v1/chat/completions HTTP/1.1'
80-
headers << 'Host: ${c.config.api_host}'
81-
if c.config.api_key.len > 0 {
82-
headers << 'Authorization: Bearer ${c.config.api_key}'
83-
}
84-
headers << 'Content-Type: application/json'
85-
headers << 'Accept: text/event-stream'
86-
headers << 'Content-Length: ${request_data.len}'
87-
headers << 'Connection: close'
88-
headers << ''
89-
headers << request_data
90-
91-
request_str := headers.join('\r\n')
92-
93-
mut stream := new_stream_reader(c.config.api_host, c.config.api_port, c.config.api_tls)!
94-
defer { stream.close() }
95-
96-
stream.send_request(request_str)!
97-
98-
mut response_received := []bool{len: 1, init: false}
99-
100-
stream.read_stream(fn [response_received] (line_data string) ! {
101-
chat_response := json.decode(ChatResponse, line_data) or {
102-
eprintln('Decoding error: ${err}')
103-
return
104-
}
105-
106-
if chat_response.choices.len > 0 {
107-
if chat_response.choices[0].finish_reason == 'stop' {
108-
return
109-
}
110-
if chat_response.choices[0].delta.content.len > 0 {
111-
content := chat_response.choices[0].delta.content
112-
print(content)
113-
flush_stdout()
114-
unsafe {
115-
response_received[0] = true
116-
}
117-
}
118-
}
119-
})!
120-
121-
if !response_received[0] {
122-
return error('Aucune réponse reçue de l\'API. Vérifiez votre configuration dans ${config_file}')
123-
}
124-
125-
println('')
64+
request := CompletionRequest{
65+
model: c.config.api_model
66+
messages: [
67+
Message{
68+
role: 'system'
69+
content: system_prompt
70+
},
71+
Message{
72+
role: 'user'
73+
content: prompt
74+
},
75+
]
76+
temperature: temperature
77+
stream: true
78+
}
79+
80+
request_data := json.encode(request)
81+
protocol := if c.config.api_tls { 'https' } else { 'http' }
82+
log.debug('Connecting to ${protocol}://${c.config.api_host}:${c.config.api_port}')
83+
84+
mut headers := []string{}
85+
headers << 'POST /v1/chat/completions HTTP/1.1'
86+
headers << 'Host: ${c.config.api_host}'
87+
if c.config.api_key.len > 0 {
88+
headers << 'Authorization: Bearer ${c.config.api_key}'
89+
}
90+
headers << 'Content-Type: application/json'
91+
headers << 'Accept: text/event-stream'
92+
headers << 'Content-Length: ${request_data.len}'
93+
headers << 'Connection: close'
94+
headers << ''
95+
headers << request_data
96+
97+
request_str := headers.join('\r\n')
98+
99+
mut stream := new_stream_reader(c.config.api_host, c.config.api_port, c.config.api_tls)!
100+
defer { stream.close() }
101+
102+
stream.send_request(request_str) or {
103+
log.error('Failed to send request: ${err}')
104+
return err
105+
}
106+
107+
mut response_received := []bool{len: 1, init: false}
108+
109+
stream.read_stream(fn [response_received] (line_data string) ! {
110+
chat_response := json.decode(ChatResponse, line_data) or {
111+
eprintln('Decoding error: ${err}')
112+
return
113+
}
114+
115+
if chat_response.choices.len > 0 {
116+
if chat_response.choices[0].finish_reason == 'stop' {
117+
return
118+
}
119+
if chat_response.choices[0].delta.content.len > 0 {
120+
content := chat_response.choices[0].delta.content
121+
print(content)
122+
flush_stdout()
123+
unsafe {
124+
response_received[0] = true
125+
}
126+
}
127+
}
128+
}) or {
129+
log.error('Stream read error: ${err}')
130+
return err
131+
}
132+
133+
if !response_received[0] {
134+
return error('No response received from the API. Check your configuration in ${config_file}')
135+
}
136+
137+
println('')
126138
}
127139

128140
struct ModelsResponse {
129-
data []Model
141+
data []Model
130142
}
131143

132144
struct Model {
133-
id string
145+
id string
134146
}
135147

136148
pub fn (c Client) list_models() ![]string {
137-
protocol := if c.config.api_tls { 'https' } else { 'http' }
138-
url := '${protocol}://${c.config.api_host}:${c.config.api_port}/v1/models'
149+
protocol := if c.config.api_tls { 'https' } else { 'http' }
150+
url := '${protocol}://${c.config.api_host}:${c.config.api_port}/v1/models'
139151

140-
mut req := http.new_request(.get, url, '')
141-
if c.config.api_key.len > 0 {
142-
req.header.add(http.CommonHeader.authorization, 'Bearer ${c.config.api_key}')
143-
}
152+
mut req := http.new_request(.get, url, '')
153+
if c.config.api_key.len > 0 {
154+
req.header.add(http.CommonHeader.authorization, 'Bearer ${c.config.api_key}')
155+
}
144156

145-
resp := req.do()!
157+
log.debug('Request: ${req}')
158+
resp := req.do() or { return error('Models API error: ${err}') }
146159

147-
if resp.status_code != 200 {
148-
return error('Erreur API (${resp.status_code}): ${resp.body}')
149-
}
160+
if resp.status_code != 200 {
161+
return error('Models API error (${resp.status_code}): ${resp.body}')
162+
}
150163

151-
models := json.decode(ModelsResponse, resp.body)!
152-
return models.data.map(it.id)
164+
models := json.decode(ModelsResponse, resp.body)!
165+
return models.data.map(it.id)
153166
}
154167

155168
pub fn (c Client) is_model_supported(model_name string) !bool {
156-
models := c.list_models()!
157-
return model_name in models
169+
models := c.list_models()!
170+
return model_name in models
158171
}
159172

160173
pub fn (c Client) validate_model(model_name string) ! {
161-
models := c.list_models()!
162-
if model_name !in models {
163-
mut error_msg := 'The model "${model_name}" is not supported.\n'
164-
display.models_list(models)
165-
return error(error_msg)
166-
}
174+
models := c.list_models()!
175+
if model_name !in models {
176+
mut error_msg := 'The model "${model_name}" is not supported.\n'
177+
display.models_list(models)
178+
return error(error_msg)
179+
}
167180
}
168181

169182
fn flush_stdout() {
170-
unsafe {
171-
C.fflush(C.stdout)
172-
}
183+
unsafe {
184+
C.fflush(C.stdout)
185+
}
173186
}

0 commit comments

Comments
 (0)