aboutsummaryrefslogtreecommitdiffstats
path: root/src/openrouter/mod.rs
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-07-13 17:21:21 +0200
committersalmonik <salmonik@tuta.io>2026-07-13 17:21:21 +0200
commit4961aae1737b77ff77102d37bf5f37f31a43824e (patch)
treee344777946a6d4354312ffb638ece6e9cbbf3a0e /src/openrouter/mod.rs
parentmake cron follow local time zone (diff)
downloadsenator-sperma-4961aae1737b77ff77102d37bf5f37f31a43824e.tar.gz
senator-sperma-4961aae1737b77ff77102d37bf5f37f31a43824e.zip
fix assistant and senator
Signed-off-by: salmonik <salmonik@tuta.io>
Diffstat (limited to '')
-rw-r--r--src/openrouter/mod.rs88
1 files changed, 41 insertions, 47 deletions
diff --git a/src/openrouter/mod.rs b/src/openrouter/mod.rs
index 31cee85..1d3b443 100644
--- a/src/openrouter/mod.rs
+++ b/src/openrouter/mod.rs
@@ -1,3 +1,5 @@
1use tracing::info;
2
1use reqwest::Client; 3use reqwest::Client;
2use serde::{Deserialize, Serialize}; 4use serde::{Deserialize, Serialize};
3 5
@@ -7,6 +9,7 @@ use crate::lang;
7pub struct OpenRouterClient { 9pub struct OpenRouterClient {
8 api_key: String, 10 api_key: String,
9 model: String, 11 model: String,
12 api_url: String,
10 client: Client, 13 client: Client,
11} 14}
12 15
@@ -39,14 +42,49 @@ struct MessageContent {
39} 42}
40 43
41impl OpenRouterClient { 44impl OpenRouterClient {
42 pub fn new(api_key: String, model: String) -> Self { 45 /// `api_url` is the full URL including `/chat/completions` path.
46 pub fn new(api_url: String, api_key: String, model: String) -> Self {
47 info!("LLM client: url={api_url}, model={model}");
43 Self { 48 Self {
44 api_key, 49 api_key,
45 model, 50 model,
51 api_url,
46 client: Client::new(), 52 client: Client::new(),
47 } 53 }
48 } 54 }
49 55
56 async fn do_request(&self, body: &ChatRequest) -> Result<String> {
57 let mut req = self
58 .client
59 .post(&self.api_url)
60 .header("Content-Type", "application/json")
61 .json(body);
62
63 if !self.api_key.is_empty() {
64 req = req.header("Authorization", format!("Bearer {}", self.api_key));
65 }
66
67 let resp = req.send().await?;
68
69 if !resp.status().is_success() {
70 let status = resp.status();
71 let text = resp.text().await.unwrap_or_default();
72 return Err(crate::error::Error::Custom(lang::fmt_llm_err(
73 &self.api_url,
74 &status,
75 &text,
76 )));
77 }
78
79 let chat_resp: ChatResponse = resp.json().await?;
80 Ok(chat_resp
81 .choices
82 .into_iter()
83 .next()
84 .map(|c| c.message.content)
85 .unwrap_or_default())
86 }
87
50 pub async fn chat(&self, system_prompt: &str, user_message: &str) -> Result<String> { 88 pub async fn chat(&self, system_prompt: &str, user_message: &str) -> Result<String> {
51 let body = ChatRequest { 89 let body = ChatRequest {
52 model: self.model.clone(), 90 model: self.model.clone(),
@@ -63,29 +101,7 @@ impl OpenRouterClient {
63 max_tokens: 500, 101 max_tokens: 500,
64 }; 102 };
65 103
66 let resp = self 104 self.do_request(&body).await
67 .client
68 .post("https://openrouter.ai/api/v1/chat/completions")
69 .header("Authorization", format!("Bearer {}", self.api_key))
70 .json(&body)
71 .send()
72 .await?;
73
74 if !resp.status().is_success() {
75 let status = resp.status();
76 let text = resp.text().await.unwrap_or_default();
77 return Err(crate::error::Error::Custom(lang::fmt_openrouter_err(
78 &status, &text,
79 )));
80 }
81
82 let chat_resp: ChatResponse = resp.json().await?;
83 Ok(chat_resp
84 .choices
85 .into_iter()
86 .next()
87 .map(|c| c.message.content)
88 .unwrap_or_default())
89 } 105 }
90 106
91 pub async fn chat_with_history( 107 pub async fn chat_with_history(
@@ -107,28 +123,6 @@ impl OpenRouterClient {
107 max_tokens: 500, 123 max_tokens: 500,
108 }; 124 };
109 125
110 let resp = self 126 self.do_request(&body).await
111 .client
112 .post("https://openrouter.ai/api/v1/chat/completions")
113 .header("Authorization", format!("Bearer {}", self.api_key))
114 .json(&body)
115 .send()
116 .await?;
117
118 if !resp.status().is_success() {
119 let status = resp.status();
120 let text = resp.text().await.unwrap_or_default();
121 return Err(crate::error::Error::Custom(lang::fmt_openrouter_err(
122 &status, &text,
123 )));
124 }
125
126 let chat_resp: ChatResponse = resp.json().await?;
127 Ok(chat_resp
128 .choices
129 .into_iter()
130 .next()
131 .map(|c| c.message.content)
132 .unwrap_or_default())
133 } 127 }
134} 128}