Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ response.

For a Tiny Humans API key, use `ClientConfig::tinyhumans_openrouter("<key>")`,
which explicitly targets
`https://api.tinyhumans.ai/agent-integrations/openrouter/v1/systemone`.
`https://api.tinyhumans.ai/agent-integrations/openrouter/systemone`.

Remote API roots must use HTTPS; HTTP is reserved for literal loopback IPs.
Failed evaluations retain their classified error, attempt count, and elapsed
Expand Down
2 changes: 1 addition & 1 deletion crates/tinyjevclient/src/client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ are terminal, and automatic redirects are disabled.
`https://openrouter.ai/api/v1/systemone`.

`ClientConfig::tinyhumans_openrouter` targets the Tiny Humans OpenRouter proxy
at `https://api.tinyhumans.ai/agent-integrations/openrouter/v1/systemone`.
at `https://api.tinyhumans.ai/agent-integrations/openrouter/systemone`.
3 changes: 1 addition & 2 deletions crates/tinyjevclient/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use reqwest::{StatusCode, header::RETRY_AFTER};

use crate::{Error, EvaluationRequest, EvaluationResponse, Result};

const SYSTEM_ONE_PATH: &str = "v1/systemone";
const MAX_RETRIES: u32 = 100;

impl Client {
Expand Down Expand Up @@ -113,7 +112,7 @@ impl Client {
let url = format!(
"{}/{}",
self.config.base_url.trim_end_matches('/'),
SYSTEM_ONE_PATH
self.config.system_one_path
);
let response = self
.http
Expand Down
9 changes: 5 additions & 4 deletions crates/tinyjevclient/src/client/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ async fn openrouter_uses_system_one_and_accepts_a_resolved_jev_model() {
}

#[tokio::test]
async fn tinyhumans_proxy_uses_the_compatibility_system_one_path() {
async fn tinyhumans_proxy_uses_the_direct_system_one_path() {
let (base_url, requests) = server(vec![response(
200,
&success().replace("jev-latest", "typesafe/jev-1.13-20260917"),
Expand All @@ -173,7 +173,7 @@ async fn tinyhumans_proxy_uses_the_compatibility_system_one_path() {
.lock()
.await
.join("")
.starts_with("POST /v1/systemone HTTP/1.1")
.starts_with("POST /agent-integrations/openrouter/systemone HTTP/1.1")
);
}

Expand Down Expand Up @@ -272,9 +272,10 @@ fn validates_every_configuration_bound_and_redacted_key_replacement() {
assert_eq!(openrouter.base_url, "https://openrouter.ai/api");
assert_eq!(openrouter.provider, Provider::OpenRouter);
let tinyhumans = ClientConfig::tinyhumans_openrouter("key");
assert_eq!(tinyhumans.base_url, "https://api.tinyhumans.ai");
assert_eq!(
tinyhumans.base_url,
"https://api.tinyhumans.ai/agent-integrations/openrouter"
tinyhumans.system_one_path,
"agent-integrations/openrouter/systemone"
);
assert_eq!(tinyhumans.provider, Provider::OpenRouter);
let mut ipv6_loopback = ClientConfig::new("key");
Expand Down
13 changes: 11 additions & 2 deletions crates/tinyjevclient/src/client/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ use std::{fmt, time::Duration};

use crate::{Error, EvaluationResponse};

const DEFAULT_SYSTEM_ONE_PATH: &str = "v1/systemone";
const TINYHUMANS_SYSTEM_ONE_PATH: &str = "agent-integrations/openrouter/systemone";

/// System One API provider.
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub enum Provider {
Expand Down Expand Up @@ -33,8 +36,10 @@ impl fmt::Debug for Client {
#[derive(Clone)]
pub struct ClientConfig {
pub(super) api_key: ApiKey,
/// API root without the versioned endpoint path.
/// API origin or path prefix without the System One endpoint path.
pub base_url: String,
/// Provider-specific System One endpoint path.
pub(super) system_one_path: &'static str,
/// Provider-specific response validation behavior.
pub provider: Provider,
/// Total timeout for one HTTP attempt.
Expand All @@ -50,6 +55,7 @@ impl ClientConfig {
Self {
api_key: ApiKey(api_key.into()),
base_url: "https://api.typesafe.ai".to_owned(),
system_one_path: DEFAULT_SYSTEM_ONE_PATH,
provider: Provider::TypeSafe,
timeout: Duration::from_secs(30),
retry: RetryPolicy::default(),
Expand All @@ -62,6 +68,7 @@ impl ClientConfig {
Self {
api_key: ApiKey(api_key.into()),
base_url: "https://openrouter.ai/api".to_owned(),
system_one_path: DEFAULT_SYSTEM_ONE_PATH,
provider: Provider::OpenRouter,
timeout: Duration::from_secs(30),
retry: RetryPolicy::default(),
Expand All @@ -76,7 +83,8 @@ impl ClientConfig {
pub fn tinyhumans_openrouter(api_key: impl Into<String>) -> Self {
Self {
api_key: ApiKey(api_key.into()),
base_url: "https://api.tinyhumans.ai/agent-integrations/openrouter".to_owned(),
base_url: "https://api.tinyhumans.ai".to_owned(),
system_one_path: TINYHUMANS_SYSTEM_ONE_PATH,
provider: Provider::OpenRouter,
timeout: Duration::from_secs(30),
retry: RetryPolicy::default(),
Expand All @@ -96,6 +104,7 @@ impl fmt::Debug for ClientConfig {
f.debug_struct("ClientConfig")
.field("api_key", &"[REDACTED]")
.field("base_url", &self.base_url)
.field("system_one_path", &self.system_one_path)
.field("provider", &self.provider)
.field("timeout", &self.timeout)
.field("retry", &self.retry)
Expand Down
6 changes: 3 additions & 3 deletions docs/specs/system-one-client.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ loopback IP addresses used by local test servers.
`https://openrouter.ai/api`. The first-party constructor and `Client::from_env`
retain the `TypeSafe` endpoint and `TYPESAFE_API_KEY` behavior.

`ClientConfig::tinyhumans_openrouter` uses Tiny Humans' OpenRouter proxy base
URL, `https://api.tinyhumans.ai/agent-integrations/openrouter`, and
accepts the key supplied explicitly to its constructor.
`ClientConfig::tinyhumans_openrouter` uses the Tiny Humans OpenRouter System One
endpoint, `https://api.tinyhumans.ai/agent-integrations/openrouter/systemone`,
and accepts the key supplied explicitly to its constructor.

Authentication, request validation, response decoding, and non-connect
transport failures are terminal. Timeouts, connection-establishment failures,
Expand Down
Loading