mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-27 21:08:00 +00:00
fix(agentbox): normalize GMI_MAAS_BASE_URL with trailing /v1 (#5091)
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -13,6 +13,7 @@ describe('builtinCloudProviders', () => {
|
||||
});
|
||||
|
||||
it.each([
|
||||
['gmi', 'https://api.gmi-serving.com/v1', 'bearer'],
|
||||
['groq', 'https://api.groq.com/openai/v1', 'bearer'],
|
||||
['deepseek', 'https://api.deepseek.com/v1', 'bearer'],
|
||||
['minimax', 'https://api.minimax.io/v1', 'bearer'],
|
||||
|
||||
@@ -64,7 +64,7 @@ export const BUILTIN_CLOUD_PROVIDERS: BuiltinCloudProvider[] = [
|
||||
endpoint: 'https://api.gmi-serving.com/v1',
|
||||
authStyle: 'bearer',
|
||||
tone: TONE.fuchsia,
|
||||
keyPlaceholder: 'gmi-...',
|
||||
keyPlaceholder: 'eyJ....',
|
||||
},
|
||||
{
|
||||
slug: 'fireworks',
|
||||
|
||||
@@ -79,12 +79,23 @@ where
|
||||
return Err(format!("missing/blank: {}", missing.join(", ")));
|
||||
}
|
||||
Ok(GmiConfig {
|
||||
base_url: base_url.unwrap(),
|
||||
base_url: normalize_gmi_maas_base_url(&base_url.unwrap()),
|
||||
api_key: api_key.unwrap(),
|
||||
model: model.unwrap(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Normalize `GMI_MAAS_BASE_URL` to an OpenAI-compatible `/v1` base URL.
|
||||
///
|
||||
/// AgentBox injects a host-only URL (no `/v1`). `OpenAiModel` appends
|
||||
/// `/chat/completions` but does not add `/v1`, so marketplace inference
|
||||
/// 404s without this step. Idempotent for already-correct inputs.
|
||||
pub fn normalize_gmi_maas_base_url(url: &str) -> String {
|
||||
let trimmed = url.trim().trim_end_matches('/');
|
||||
let without_v1 = trimmed.strip_suffix("/v1").unwrap_or(trimmed);
|
||||
format!("{}/v1", without_v1.trim_end_matches('/'))
|
||||
}
|
||||
|
||||
fn nonblank<F: Fn(&str) -> Option<String>>(get: &F, key: &str) -> Option<String> {
|
||||
get(key)
|
||||
.map(|v| v.trim().to_string())
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
use super::env::{agentbox_mode_enabled, collect_gmi_config, GmiConfig, AGENTBOX_MODE_ENV_VAR};
|
||||
use super::env::{
|
||||
agentbox_mode_enabled, collect_gmi_config, normalize_gmi_maas_base_url, GmiConfig,
|
||||
AGENTBOX_MODE_ENV_VAR,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn collect_returns_some_when_all_three_vars_present() {
|
||||
@@ -11,7 +14,7 @@ fn collect_returns_some_when_all_three_vars_present() {
|
||||
assert_eq!(
|
||||
cfg,
|
||||
Ok(GmiConfig {
|
||||
base_url: "https://api.gmi-serving.com".into(),
|
||||
base_url: "https://api.gmi-serving.com/v1".into(),
|
||||
api_key: "sk-test".into(),
|
||||
model: "deepseek-ai/DeepSeek-V4-Pro".into(),
|
||||
})
|
||||
@@ -86,9 +89,41 @@ fn collect_trims_leading_and_trailing_whitespace() {
|
||||
assert_eq!(
|
||||
cfg,
|
||||
Ok(GmiConfig {
|
||||
base_url: "https://api.gmi-serving.com".into(),
|
||||
base_url: "https://api.gmi-serving.com/v1".into(),
|
||||
api_key: "sk-test".into(),
|
||||
model: "deepseek-ai/DeepSeek-V4-Pro".into(),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn normalize_gmi_maas_base_url_appends_v1() {
|
||||
assert_eq!(
|
||||
normalize_gmi_maas_base_url("https://api.gmi-serving.com"),
|
||||
"https://api.gmi-serving.com/v1"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn normalize_gmi_maas_base_url_strips_trailing_slash() {
|
||||
assert_eq!(
|
||||
normalize_gmi_maas_base_url("https://api.gmi-serving.com/"),
|
||||
"https://api.gmi-serving.com/v1"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn normalize_gmi_maas_base_url_keeps_existing_v1() {
|
||||
assert_eq!(
|
||||
normalize_gmi_maas_base_url("https://api.gmi-serving.com/v1"),
|
||||
"https://api.gmi-serving.com/v1"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn normalize_gmi_maas_base_url_strips_v1_trailing_slash() {
|
||||
assert_eq!(
|
||||
normalize_gmi_maas_base_url("https://api.gmi-serving.com/v1/"),
|
||||
"https://api.gmi-serving.com/v1"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ mod tests {
|
||||
assert!(status.provider_configured);
|
||||
let provider = status.provider.expect("provider populated");
|
||||
assert_eq!(provider.slug, GMI_MAAS_SLUG);
|
||||
assert_eq!(provider.base_url, "https://api.gmi-serving.com");
|
||||
assert_eq!(provider.base_url, "https://api.gmi-serving.com/v1");
|
||||
assert_eq!(provider.model, "deepseek-ai/DeepSeek-V4-Pro");
|
||||
|
||||
// Defense-in-depth: the serialized status must never carry the key.
|
||||
|
||||
Reference in New Issue
Block a user