feat: z.ai + more models

This commit is contained in:
2026-10-09 02:19:53 -04:00
parent 9dd13f374f
commit f2108ae35a
4 changed files with 57 additions and 54 deletions

View File

@@ -96,11 +96,15 @@ impl Shortcut {
(P::GoogleAiStudio, "gemini-3.5-flash-lite".into()),
(P::OpenRouter, "apodex/apodex-1.1-mini:free".into()),
(P::HuggingFace, "Qwen/Qwen3.6-35B-A3B".into()),
(P::OpenRouter, "poolside/laguna-xs-2.1:free".into()),
(P::OpenRouter, "cohere/north-mini-code:free".into()),
(P::OpenRouter, "nvidia/nemotron-3.5-lightning:free".into()),
(P::GoogleAiStudio, "gemma-4-26b-a4b-it".into()),
(P::OpenRouter, "google/gemma-4-26b-a4b-it:free".into()),
(P::HuggingFace, "google/gemma-4-26B-A4B-it".into()),
(P::OpenRouter, "poolside/laguna-xs-2.1:free".into()),
(P::ZAi, "glm-4.7-flash".into()),
(P::OpenRouter, "cohere/north-mini-code:free".into()),
(P::OpenRouter, "nvidia/nemotron-3.5-lightning:free".into()),
(P::ZAi, "glm-4.6v-flash".into()),
(P::ZAi, "glm-4.5-flash".into()),
(P::OpenRouter, "poolside/laguna-xs.2:free".into()),
(
P::OpenRouter,
@@ -121,6 +125,7 @@ impl Shortcut {
(P::Groq, "qwen/qwen3.8-27b".into()),
(P::HuggingFace, "Qwen/Qwen3.8-27B".into()),
(P::HuggingFace, "meta-models/Muse-Glimmer-30B".into()),
(P::GoogleAiStudio, "gemma-4-31b-it".into()),
(P::OpenRouter, "google/gemma-4-31b-it:free".into()),
(P::HuggingFace, "google/gemma-4-31B-it".into()),
(P::Mistral, "mistral-small-2603".into()),
@@ -172,6 +177,7 @@ impl Shortcut {
(P::HuggingFace, "Qwen/Qwen3.8-2.4T-A95B".into()),
(P::OpenRouter, "thinkingmachines/inkling:free".into()),
(P::HuggingFace, "thinkingmachines/Inkling".into()),
(P::GoogleAiStudio, "gemini-3.1-pro-preview".into()),
],
S::Experimental => vec![(P::OpenRouter, "space-bunny-alpha".into())],
@@ -260,8 +266,8 @@ pub async fn create_chat_completion(
api_key,
}| {
Upstream::builder()
.base_url(
format!("https://api.cloudflare.com/client/v4/accounts/{account_id}/ai")
.url(
format!("https://api.cloudflare.com/client/v4/accounts/{account_id}/ai/v1/chat/completions")
.parse()
.expect("TODO"),
)
@@ -277,8 +283,8 @@ pub async fn create_chat_completion(
.cloned()
.map(|api_key| {
Upstream::builder()
.base_url(
"https://generativelanguage.googleapis.com/v1beta/openai"
.url(
"https://generativelanguage.googleapis.com/v1beta/openai/v1/chat/completions"
.parse()
.expect("TODO"),
)
@@ -293,7 +299,7 @@ pub async fn create_chat_completion(
.cloned()
.map(|api_key| {
Upstream::builder()
.base_url("https://api.groq.com/openai".parse().expect("TODO"))
.url("https://api.groq.com/openai/v1/chat/completions".parse().expect("TODO"))
.api_key(api_key)
.build()
})
@@ -305,7 +311,7 @@ pub async fn create_chat_completion(
.cloned()
.map(|api_key| {
Upstream::builder()
.base_url("https://router.huggingface.co".parse().expect("TODO"))
.url("https://router.huggingface.co/v1/chat/completions".parse().expect("TODO"))
.api_key(api_key)
.build()
})
@@ -317,7 +323,7 @@ pub async fn create_chat_completion(
.cloned()
.map(|api_key| {
Upstream::builder()
.base_url("https://api.mistral.ai".parse().expect("TODO"))
.url("https://api.mistral.ai/v1/chat/completions".parse().expect("TODO"))
.api_key(api_key)
.build()
})
@@ -329,7 +335,19 @@ pub async fn create_chat_completion(
.cloned()
.map(|api_key| {
Upstream::builder()
.base_url("https://openrouter.ai/api".parse().expect("TODO"))
.url("https://openrouter.ai/api/v1/chat/completions".parse().expect("TODO"))
.api_key(api_key)
.build()
})
.collect(),
Provider::ZAi => state
.app_args
.z_ai_api_key
.iter()
.cloned()
.map(|api_key| {
Upstream::builder()
.url("https://api.z.ai/api/paas/v4/chat/completions".parse().expect("TODO"))
.api_key(api_key)
.build()
})
@@ -441,23 +459,7 @@ pub async fn create_chat_completion(
.expect("TODO");
let mut upstream_request = client
.post({
let mut url = upstream.base_url;
{
let mut path_segments = url.path_segments_mut().expect("TODO");
let s = V1ChatCompletionsPath.to_string();
let s = s.strip_prefix("/").unwrap_or(&s);
let s = s.strip_suffix("/").unwrap_or(&s);
path_segments.extend(s.split("/"));
}
tracing::info!(?url);
url
})
.post(upstream.url)
.json(&request);
if let Some(api_key) = upstream.api_key {

View File

@@ -94,8 +94,8 @@ pub async fn create_embeddings(
api_key,
}| {
Upstream::builder()
.base_url(
format!("https://api.cloudflare.com/client/v4/accounts/{account_id}/ai")
.url(
format!("https://api.cloudflare.com/client/v4/accounts/{account_id}/ai/v1/embeddings")
.parse()
.expect("TODO"),
)
@@ -111,8 +111,8 @@ pub async fn create_embeddings(
.cloned()
.map(|api_key| {
Upstream::builder()
.base_url(
"https://generativelanguage.googleapis.com/v1beta/openai"
.url(
"https://generativelanguage.googleapis.com/v1beta/openai/v1/embeddings"
.parse()
.expect("TODO"),
)
@@ -127,7 +127,7 @@ pub async fn create_embeddings(
.cloned()
.map(|api_key| {
Upstream::builder()
.base_url("https://api.groq.com/openai".parse().expect("TODO"))
.url("https://api.groq.com/openai/v1/embeddings".parse().expect("TODO"))
.api_key(api_key)
.build()
})
@@ -139,7 +139,7 @@ pub async fn create_embeddings(
.cloned()
.map(|api_key| {
Upstream::builder()
.base_url("https://router.huggingface.co".parse().expect("TODO"))
.url("https://router.huggingface.co/v1/embeddings".parse().expect("TODO"))
.api_key(api_key)
.build()
})
@@ -151,7 +151,7 @@ pub async fn create_embeddings(
.cloned()
.map(|api_key| {
Upstream::builder()
.base_url("https://api.mistral.ai".parse().expect("TODO"))
.url("https://api.mistral.ai/v1/embeddings".parse().expect("TODO"))
.api_key(api_key)
.build()
})
@@ -163,7 +163,20 @@ pub async fn create_embeddings(
.cloned()
.map(|api_key| {
Upstream::builder()
.base_url("https://openrouter.ai/api".parse().expect("TODO"))
.url("https://openrouter.ai/api/v1/embeddings".parse().expect("TODO"))
.api_key(api_key)
.build()
})
.collect(),
Provider::ZAi => state
.app_args
.z_ai_api_key
.iter()
.cloned()
.map(|api_key| {
Upstream::builder()
// TODO: doesn't exist
.url("https://api.z.ai/api/paas/v4/embeddings".parse().expect("TODO"))
.api_key(api_key)
.build()
})
@@ -210,23 +223,7 @@ pub async fn create_embeddings(
.expect("TODO");
let mut upstream_request = client
.post({
let mut url = upstream.base_url;
{
let mut path_segments = url.path_segments_mut().expect("TODO");
let s = V1EmbeddingsPath.to_string();
let s = s.strip_prefix("/").unwrap_or(&s);
let s = s.strip_suffix("/").unwrap_or(&s);
path_segments.extend(s.split("/"));
}
tracing::info!(?url);
url
})
.post(upstream.url)
.json(&request);
if let Some(api_key) = upstream.api_key {

View File

@@ -26,6 +26,7 @@ enum Provider {
HuggingFace,
Mistral,
OpenRouter,
ZAi,
}
fn take_random_by_swapping<T>(mut vec1: Vec1<T>, mut rng: impl Rng) -> (T, Option<Vec1<T>>) {
@@ -42,7 +43,7 @@ fn take_random_by_swapping<T>(mut vec1: Vec1<T>, mut rng: impl Rng) -> (T, Optio
#[derive(Debug, TypedBuilder)]
struct Upstream {
base_url: Url,
url: Url,
#[builder(setter(strip_option))]
api_key: Option<SecretString>,