pushing new apis module for hermes (#547)

This commit is contained in:
Salman Paracha 2025-08-07 12:42:09 -07:00 committed by GitHub
parent 62a092fa63
commit 93ff4d7b1f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 3878 additions and 2 deletions

View file

@ -0,0 +1,130 @@
//! Supported endpoint registry for LLM APIs
//!
//! This module provides a simple registry to check which API endpoint paths
//! we support across different providers.
//!
//! # Examples
//!
//! ```rust
//! use hermesllm::clients::endpoints::{is_supported_endpoint, supported_endpoints};
//!
//! // Check if we support an endpoint
//! assert!(is_supported_endpoint("/v1/chat/completions"));
//! assert!(is_supported_endpoint("/v1/messages"));
//! assert!(!is_supported_endpoint("/v1/unknown"));
//!
//! // Get all supported endpoints
//! let endpoints = supported_endpoints();
//! assert_eq!(endpoints.len(), 2);
//! assert!(endpoints.contains(&"/v1/chat/completions"));
//! assert!(endpoints.contains(&"/v1/messages"));
//! ```
use crate::apis::{AnthropicApi, OpenAIApi, ApiDefinition};
/// Check if the given endpoint path is supported
pub fn is_supported_endpoint(endpoint: &str) -> bool {
// Try OpenAI APIs
if OpenAIApi::from_endpoint(endpoint).is_some() {
return true;
}
// Try Anthropic APIs
if AnthropicApi::from_endpoint(endpoint).is_some() {
return true;
}
false
}
/// Get all supported endpoint paths
pub fn supported_endpoints() -> Vec<&'static str> {
let mut endpoints = Vec::new();
// Add all OpenAI endpoints
for api in OpenAIApi::all_variants() {
endpoints.push(api.endpoint());
}
// Add all Anthropic endpoints
for api in AnthropicApi::all_variants() {
endpoints.push(api.endpoint());
}
endpoints
}
/// Identify which provider supports a given endpoint
pub fn identify_provider(endpoint: &str) -> Option<&'static str> {
if OpenAIApi::from_endpoint(endpoint).is_some() {
return Some("openai");
}
if AnthropicApi::from_endpoint(endpoint).is_some() {
return Some("anthropic");
}
None
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_is_supported_endpoint() {
// OpenAI endpoints
assert!(is_supported_endpoint("/v1/chat/completions"));
// Anthropic endpoints
assert!(is_supported_endpoint("/v1/messages"));
// Unsupported endpoints
assert!(!is_supported_endpoint("/v1/unknown"));
assert!(!is_supported_endpoint("/v2/chat"));
assert!(!is_supported_endpoint(""));
}
#[test]
fn test_supported_endpoints() {
let endpoints = supported_endpoints();
assert_eq!(endpoints.len(), 2);
assert!(endpoints.contains(&"/v1/chat/completions"));
assert!(endpoints.contains(&"/v1/messages"));
}
#[test]
fn test_identify_provider() {
assert_eq!(identify_provider("/v1/chat/completions"), Some("openai"));
assert_eq!(identify_provider("/v1/messages"), Some("anthropic"));
assert_eq!(identify_provider("/v1/unknown"), None);
}
#[test]
fn test_endpoints_generated_from_api_definitions() {
let endpoints = supported_endpoints();
// Verify that we get endpoints from all API variants
let openai_endpoints: Vec<_> = OpenAIApi::all_variants()
.iter()
.map(|api| api.endpoint())
.collect();
let anthropic_endpoints: Vec<_> = AnthropicApi::all_variants()
.iter()
.map(|api| api.endpoint())
.collect();
// All OpenAI endpoints should be in the result
for endpoint in openai_endpoints {
assert!(endpoints.contains(&endpoint), "Missing OpenAI endpoint: {}", endpoint);
}
// All Anthropic endpoints should be in the result
for endpoint in anthropic_endpoints {
assert!(endpoints.contains(&endpoint), "Missing Anthropic endpoint: {}", endpoint);
}
// Total should match
assert_eq!(endpoints.len(), OpenAIApi::all_variants().len() + AnthropicApi::all_variants().len());
}
}

View file

@ -0,0 +1,33 @@
//! Helper functions and utilities for API transformations
//! Contains error types and shared utilities
use thiserror::Error;
// ============================================================================
// ERROR TYPES
// ============================================================================
#[derive(Error, Debug)]
pub enum TransformError {
#[error("JSON serialization error: {0}")]
JsonError(#[from] serde_json::Error),
#[error("Unsupported content type: {0}")]
UnsupportedContent(String),
#[error("Invalid tool input format")]
InvalidToolInput,
#[error("Missing required field: {0}")]
MissingField(String),
#[error("Unsupported conversion: {0}")]
UnsupportedConversion(String),
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_types() {
let error = TransformError::MissingField("test".to_string());
assert!(matches!(error, TransformError::MissingField(_)));
}
}

View file

@ -0,0 +1,9 @@
pub mod lib;
pub mod transformer;
pub mod endpoints;
// Re-export the main items for easier access
pub use lib::*;
pub use endpoints::{is_supported_endpoint, supported_endpoints, identify_provider};
// Note: transformer module contains TryFrom trait implementations that are automatically available

File diff suppressed because it is too large Load diff