mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-04 16:37:46 +08:00
feat(security): harden gateway boundaries and usage policies
Consolidate subscription usage policy enforcement, privacy-safe persistence, and gateway security hardening into one reviewable change. Includes bounded HTTP and execution envelopes, header and protocol guards, DNS and relay validation, authentication and secret projection hardening, secure backup/install paths, and regression coverage.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
use std::collections::{BTreeMap, BTreeSet, VecDeque};
|
||||
use std::fmt;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{json, Map, Value};
|
||||
@@ -57,7 +58,7 @@ pub enum CanonicalStopReason {
|
||||
Unknown,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(tag = "type", rename_all = "snake_case")]
|
||||
pub enum CanonicalToolChoice {
|
||||
Auto,
|
||||
@@ -66,7 +67,7 @@ pub enum CanonicalToolChoice {
|
||||
Tool { name: String },
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(tag = "type", rename_all = "snake_case")]
|
||||
pub enum CanonicalContentBlock {
|
||||
Text {
|
||||
@@ -148,7 +149,7 @@ pub enum CanonicalContentBlock {
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct CanonicalInstruction {
|
||||
pub role: CanonicalRole,
|
||||
#[serde(default)]
|
||||
@@ -157,7 +158,7 @@ pub struct CanonicalInstruction {
|
||||
pub extensions: BTreeMap<String, Value>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct CanonicalMessage {
|
||||
pub role: CanonicalRole,
|
||||
#[serde(default)]
|
||||
@@ -166,7 +167,7 @@ pub struct CanonicalMessage {
|
||||
pub extensions: BTreeMap<String, Value>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Default, PartialEq, Serialize, Deserialize)]
|
||||
pub struct CanonicalGenerationConfig {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub max_tokens: Option<u64>,
|
||||
@@ -192,7 +193,7 @@ pub struct CanonicalGenerationConfig {
|
||||
pub top_logprobs: Option<u64>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct CanonicalToolDefinition {
|
||||
pub name: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
@@ -205,7 +206,7 @@ pub struct CanonicalToolDefinition {
|
||||
pub extensions: BTreeMap<String, Value>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct CanonicalThinkingConfig {
|
||||
#[serde(default)]
|
||||
pub enabled: bool,
|
||||
@@ -215,7 +216,7 @@ pub struct CanonicalThinkingConfig {
|
||||
pub extensions: BTreeMap<String, Value>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct CanonicalResponseFormat {
|
||||
pub format_type: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
@@ -224,7 +225,7 @@ pub struct CanonicalResponseFormat {
|
||||
pub extensions: BTreeMap<String, Value>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Default, PartialEq, Serialize, Deserialize)]
|
||||
pub struct CanonicalUsage {
|
||||
#[serde(default)]
|
||||
pub input_tokens: u64,
|
||||
@@ -254,7 +255,7 @@ fn is_false(value: &bool) -> bool {
|
||||
!*value
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum CanonicalEmbeddingInput {
|
||||
String(String),
|
||||
@@ -264,7 +265,7 @@ pub enum CanonicalEmbeddingInput {
|
||||
Multimodal(Vec<CanonicalEmbeddingContent>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct CanonicalEmbeddingContent {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub text: Option<String>,
|
||||
@@ -336,7 +337,7 @@ impl CanonicalEmbeddingContent {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct CanonicalEmbeddingRequest {
|
||||
pub input: CanonicalEmbeddingInput,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
@@ -353,7 +354,7 @@ pub struct CanonicalEmbeddingRequest {
|
||||
pub extensions: BTreeMap<String, Value>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct CanonicalRerankRequest {
|
||||
pub query: String,
|
||||
#[serde(default)]
|
||||
@@ -374,7 +375,7 @@ impl CanonicalRerankRequest {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct CanonicalEmbedding {
|
||||
#[serde(default)]
|
||||
pub index: usize,
|
||||
@@ -384,7 +385,7 @@ pub struct CanonicalEmbedding {
|
||||
pub extensions: BTreeMap<String, Value>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct CanonicalEmbeddingResponse {
|
||||
pub id: String,
|
||||
pub model: String,
|
||||
@@ -396,7 +397,7 @@ pub struct CanonicalEmbeddingResponse {
|
||||
pub extensions: BTreeMap<String, Value>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Default, PartialEq, Serialize, Deserialize)]
|
||||
pub struct CanonicalRequest {
|
||||
#[serde(default)]
|
||||
pub model: String,
|
||||
@@ -428,7 +429,7 @@ pub struct CanonicalRequest {
|
||||
pub extensions: BTreeMap<String, Value>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct CanonicalResponseOutput {
|
||||
#[serde(default)]
|
||||
pub index: usize,
|
||||
@@ -454,7 +455,7 @@ impl Default for CanonicalResponseOutput {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct CanonicalResponse {
|
||||
pub id: String,
|
||||
pub model: String,
|
||||
@@ -470,6 +471,425 @@ pub struct CanonicalResponse {
|
||||
pub extensions: BTreeMap<String, Value>,
|
||||
}
|
||||
|
||||
fn debug_json_bytes(value: &Value) -> Option<usize> {
|
||||
serde_json::to_vec(value).ok().map(|bytes| bytes.len())
|
||||
}
|
||||
|
||||
fn debug_json_map_bytes(value: &Map<String, Value>) -> Option<usize> {
|
||||
serde_json::to_vec(value).ok().map(|bytes| bytes.len())
|
||||
}
|
||||
|
||||
fn debug_json_option_bytes(value: Option<&Value>) -> Option<usize> {
|
||||
value.and_then(debug_json_bytes)
|
||||
}
|
||||
|
||||
fn debug_string_len(value: Option<&str>) -> Option<usize> {
|
||||
value.map(str::len)
|
||||
}
|
||||
|
||||
fn debug_string_list_summary(value: Option<&Vec<String>>) -> Option<(usize, usize)> {
|
||||
value.map(|values| (values.len(), values.iter().map(String::len).sum::<usize>()))
|
||||
}
|
||||
|
||||
fn debug_json_list_summary(value: &[Value]) -> (usize, usize) {
|
||||
(
|
||||
value.len(),
|
||||
value.iter().filter_map(debug_json_bytes).sum::<usize>(),
|
||||
)
|
||||
}
|
||||
|
||||
impl fmt::Debug for CanonicalToolChoice {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut debug = formatter.debug_struct("CanonicalToolChoice");
|
||||
match self {
|
||||
Self::Auto => debug.field("kind", &"auto"),
|
||||
Self::None => debug.field("kind", &"none"),
|
||||
Self::Required => debug.field("kind", &"required"),
|
||||
Self::Tool { name } => debug.field("kind", &"tool").field("name_len", &name.len()),
|
||||
}
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CanonicalContentBlock {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut debug = formatter.debug_struct("CanonicalContentBlock");
|
||||
match self {
|
||||
Self::Text { text, extensions } => debug
|
||||
.field("kind", &"text")
|
||||
.field("text_len", &text.len())
|
||||
.field("extension_count", &extensions.len()),
|
||||
Self::Thinking {
|
||||
text,
|
||||
signature,
|
||||
encrypted_content,
|
||||
extensions,
|
||||
} => debug
|
||||
.field("kind", &"thinking")
|
||||
.field("text_len", &text.len())
|
||||
.field("signature_len", &debug_string_len(signature.as_deref()))
|
||||
.field(
|
||||
"encrypted_content_len",
|
||||
&debug_string_len(encrypted_content.as_deref()),
|
||||
)
|
||||
.field("extension_count", &extensions.len()),
|
||||
Self::Image {
|
||||
data,
|
||||
url,
|
||||
media_type,
|
||||
detail,
|
||||
extensions,
|
||||
} => debug
|
||||
.field("kind", &"image")
|
||||
.field("data_len", &debug_string_len(data.as_deref()))
|
||||
.field("url_len", &debug_string_len(url.as_deref()))
|
||||
.field("media_type", media_type)
|
||||
.field("detail", detail)
|
||||
.field("extension_count", &extensions.len()),
|
||||
Self::File {
|
||||
data,
|
||||
file_id,
|
||||
file_url,
|
||||
media_type,
|
||||
filename,
|
||||
extensions,
|
||||
} => debug
|
||||
.field("kind", &"file")
|
||||
.field("data_len", &debug_string_len(data.as_deref()))
|
||||
.field("file_id_len", &debug_string_len(file_id.as_deref()))
|
||||
.field("file_url_len", &debug_string_len(file_url.as_deref()))
|
||||
.field("media_type", media_type)
|
||||
.field("filename_len", &debug_string_len(filename.as_deref()))
|
||||
.field("extension_count", &extensions.len()),
|
||||
Self::Audio {
|
||||
data,
|
||||
media_type,
|
||||
format,
|
||||
extensions,
|
||||
} => debug
|
||||
.field("kind", &"audio")
|
||||
.field("data_len", &debug_string_len(data.as_deref()))
|
||||
.field("media_type", media_type)
|
||||
.field("format", format)
|
||||
.field("extension_count", &extensions.len()),
|
||||
Self::ToolUse {
|
||||
id,
|
||||
name,
|
||||
input,
|
||||
extensions,
|
||||
} => debug
|
||||
.field("kind", &"tool_use")
|
||||
.field("id_len", &id.len())
|
||||
.field("name_len", &name.len())
|
||||
.field("input_bytes", &debug_json_bytes(input))
|
||||
.field("extension_count", &extensions.len()),
|
||||
Self::ToolResult {
|
||||
tool_use_id,
|
||||
name,
|
||||
output,
|
||||
content_text,
|
||||
is_error,
|
||||
extensions,
|
||||
} => debug
|
||||
.field("kind", &"tool_result")
|
||||
.field("tool_use_id_len", &tool_use_id.len())
|
||||
.field("name_len", &debug_string_len(name.as_deref()))
|
||||
.field("output_bytes", &debug_json_option_bytes(output.as_ref()))
|
||||
.field(
|
||||
"content_text_len",
|
||||
&debug_string_len(content_text.as_deref()),
|
||||
)
|
||||
.field("is_error", is_error)
|
||||
.field("extension_count", &extensions.len()),
|
||||
Self::Unknown {
|
||||
raw_type,
|
||||
payload,
|
||||
extensions,
|
||||
} => debug
|
||||
.field("kind", &"unknown")
|
||||
.field("raw_type_len", &raw_type.len())
|
||||
.field("payload_bytes", &debug_json_bytes(payload))
|
||||
.field("extension_count", &extensions.len()),
|
||||
}
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CanonicalInstruction {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter
|
||||
.debug_struct("CanonicalInstruction")
|
||||
.field("role", &self.role)
|
||||
.field("text_len", &self.text.len())
|
||||
.field("extension_count", &self.extensions.len())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CanonicalMessage {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter
|
||||
.debug_struct("CanonicalMessage")
|
||||
.field("role", &self.role)
|
||||
.field("content_count", &self.content.len())
|
||||
.field("extension_count", &self.extensions.len())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CanonicalGenerationConfig {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter
|
||||
.debug_struct("CanonicalGenerationConfig")
|
||||
.field("max_tokens", &self.max_tokens)
|
||||
.field("temperature", &self.temperature)
|
||||
.field("top_p", &self.top_p)
|
||||
.field("top_k", &self.top_k)
|
||||
.field(
|
||||
"stop_sequences",
|
||||
&debug_string_list_summary(self.stop_sequences.as_ref()),
|
||||
)
|
||||
.field("n", &self.n)
|
||||
.field("presence_penalty", &self.presence_penalty)
|
||||
.field("frequency_penalty", &self.frequency_penalty)
|
||||
.field("seed", &self.seed)
|
||||
.field("logprobs", &self.logprobs)
|
||||
.field("top_logprobs", &self.top_logprobs)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CanonicalToolDefinition {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter
|
||||
.debug_struct("CanonicalToolDefinition")
|
||||
.field("name_len", &self.name.len())
|
||||
.field(
|
||||
"description_len",
|
||||
&debug_string_len(self.description.as_deref()),
|
||||
)
|
||||
.field(
|
||||
"parameters_bytes",
|
||||
&debug_json_option_bytes(self.parameters.as_ref()),
|
||||
)
|
||||
.field("strict", &self.strict)
|
||||
.field("extension_count", &self.extensions.len())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CanonicalThinkingConfig {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter
|
||||
.debug_struct("CanonicalThinkingConfig")
|
||||
.field("enabled", &self.enabled)
|
||||
.field("budget_tokens", &self.budget_tokens)
|
||||
.field("extension_count", &self.extensions.len())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CanonicalResponseFormat {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter
|
||||
.debug_struct("CanonicalResponseFormat")
|
||||
.field("format_type_len", &self.format_type.len())
|
||||
.field(
|
||||
"json_schema_bytes",
|
||||
&debug_json_option_bytes(self.json_schema.as_ref()),
|
||||
)
|
||||
.field("extension_count", &self.extensions.len())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CanonicalUsage {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter
|
||||
.debug_struct("CanonicalUsage")
|
||||
.field("input_tokens", &self.input_tokens)
|
||||
.field(
|
||||
"input_tokens_include_cache",
|
||||
&self.input_tokens_include_cache,
|
||||
)
|
||||
.field("output_tokens", &self.output_tokens)
|
||||
.field("total_tokens", &self.total_tokens)
|
||||
.field("cache_read_tokens", &self.cache_read_tokens)
|
||||
.field("cache_write_tokens", &self.cache_write_tokens)
|
||||
.field(
|
||||
"cache_creation_ephemeral_5m_tokens",
|
||||
&self.cache_creation_ephemeral_5m_tokens,
|
||||
)
|
||||
.field(
|
||||
"cache_creation_ephemeral_1h_tokens",
|
||||
&self.cache_creation_ephemeral_1h_tokens,
|
||||
)
|
||||
.field("reasoning_tokens", &self.reasoning_tokens)
|
||||
.field("extension_count", &self.extensions.len())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CanonicalEmbeddingInput {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut debug = formatter.debug_struct("CanonicalEmbeddingInput");
|
||||
match self {
|
||||
Self::String(value) => debug
|
||||
.field("kind", &"string")
|
||||
.field("item_count", &1)
|
||||
.field("total_text_bytes", &value.len()),
|
||||
Self::StringArray(values) => debug
|
||||
.field("kind", &"string_array")
|
||||
.field("item_count", &values.len())
|
||||
.field(
|
||||
"total_text_bytes",
|
||||
&values.iter().map(String::len).sum::<usize>(),
|
||||
),
|
||||
Self::TokenArray(values) => debug
|
||||
.field("kind", &"token_array")
|
||||
.field("item_count", &values.len()),
|
||||
Self::TokenArrayArray(values) => debug
|
||||
.field("kind", &"token_array_array")
|
||||
.field("item_count", &values.len())
|
||||
.field(
|
||||
"total_token_count",
|
||||
&values.iter().map(Vec::len).sum::<usize>(),
|
||||
),
|
||||
Self::Multimodal(values) => debug
|
||||
.field("kind", &"multimodal")
|
||||
.field("item_count", &values.len()),
|
||||
}
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CanonicalEmbeddingContent {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter
|
||||
.debug_struct("CanonicalEmbeddingContent")
|
||||
.field("text_len", &debug_string_len(self.text.as_deref()))
|
||||
.field("image_len", &debug_string_len(self.image.as_deref()))
|
||||
.field("video_len", &debug_string_len(self.video.as_deref()))
|
||||
.field(
|
||||
"multi_images_summary",
|
||||
&self
|
||||
.multi_images
|
||||
.as_ref()
|
||||
.map(|images| (images.len(), images.iter().map(String::len).sum::<usize>())),
|
||||
)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CanonicalEmbeddingRequest {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter
|
||||
.debug_struct("CanonicalEmbeddingRequest")
|
||||
.field("input", &self.input)
|
||||
.field("encoding_format", &self.encoding_format)
|
||||
.field("dimensions", &self.dimensions)
|
||||
.field("task_len", &debug_string_len(self.task.as_deref()))
|
||||
.field("user_len", &debug_string_len(self.user.as_deref()))
|
||||
.field(
|
||||
"parameters_bytes",
|
||||
&self.parameters.as_ref().and_then(debug_json_map_bytes),
|
||||
)
|
||||
.field("parameter_count", &self.parameters.as_ref().map(Map::len))
|
||||
.field("extension_count", &self.extensions.len())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CanonicalRerankRequest {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter
|
||||
.debug_struct("CanonicalRerankRequest")
|
||||
.field("query_len", &self.query.len())
|
||||
.field("documents", &debug_json_list_summary(&self.documents))
|
||||
.field("top_n", &self.top_n)
|
||||
.field("return_documents", &self.return_documents)
|
||||
.field("extension_count", &self.extensions.len())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CanonicalEmbedding {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter
|
||||
.debug_struct("CanonicalEmbedding")
|
||||
.field("index", &self.index)
|
||||
.field("embedding_len", &self.embedding.len())
|
||||
.field("extension_count", &self.extensions.len())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CanonicalEmbeddingResponse {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter
|
||||
.debug_struct("CanonicalEmbeddingResponse")
|
||||
.field("id_len", &self.id.len())
|
||||
.field("model_len", &self.model.len())
|
||||
.field("embedding_count", &self.embeddings.len())
|
||||
.field("usage", &self.usage)
|
||||
.field("extension_count", &self.extensions.len())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CanonicalRequest {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter
|
||||
.debug_struct("CanonicalRequest")
|
||||
.field("model_len", &self.model.len())
|
||||
.field("instruction_count", &self.instructions.len())
|
||||
.field("system_len", &debug_string_len(self.system.as_deref()))
|
||||
.field("message_count", &self.messages.len())
|
||||
.field("embedding", &self.embedding)
|
||||
.field("rerank", &self.rerank)
|
||||
.field("generation", &self.generation)
|
||||
.field("tool_count", &self.tools.len())
|
||||
.field("tool_choice", &self.tool_choice)
|
||||
.field("thinking", &self.thinking)
|
||||
.field("response_format", &self.response_format)
|
||||
.field("parallel_tool_calls", &self.parallel_tool_calls)
|
||||
.field(
|
||||
"metadata_bytes",
|
||||
&debug_json_option_bytes(self.metadata.as_ref()),
|
||||
)
|
||||
.field("extension_count", &self.extensions.len())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CanonicalResponseOutput {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter
|
||||
.debug_struct("CanonicalResponseOutput")
|
||||
.field("index", &self.index)
|
||||
.field("role", &self.role)
|
||||
.field("content_count", &self.content.len())
|
||||
.field("stop_reason", &self.stop_reason)
|
||||
.field("extension_count", &self.extensions.len())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for CanonicalResponse {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter
|
||||
.debug_struct("CanonicalResponse")
|
||||
.field("id_len", &self.id.len())
|
||||
.field("model_len", &self.model.len())
|
||||
.field("output_count", &self.outputs.len())
|
||||
.field("content_count", &self.content.len())
|
||||
.field("stop_reason", &self.stop_reason)
|
||||
.field("usage", &self.usage)
|
||||
.field("extension_count", &self.extensions.len())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_openai_chat_to_canonical_request(body_json: &Value) -> Option<CanonicalRequest> {
|
||||
crate::formats::openai::chat::request::from_raw(body_json)
|
||||
}
|
||||
@@ -4531,7 +4951,7 @@ pub(crate) type GeminiCanonicalTools = (
|
||||
Option<Value>,
|
||||
);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct GeminiGoogleSearchGrounding {
|
||||
pub source_field: &'static str,
|
||||
pub source_dialect: &'static str,
|
||||
@@ -4541,6 +4961,23 @@ pub(crate) struct GeminiGoogleSearchGrounding {
|
||||
pub output_payload: Value,
|
||||
}
|
||||
|
||||
impl fmt::Debug for GeminiGoogleSearchGrounding {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter
|
||||
.debug_struct("GeminiGoogleSearchGrounding")
|
||||
.field("source_field", &self.source_field)
|
||||
.field("source_dialect", &self.source_dialect)
|
||||
.field("legacy", &self.legacy)
|
||||
.field("payload_bytes", &debug_json_bytes(&self.payload))
|
||||
.field("raw_payload_bytes", &debug_json_bytes(&self.raw_payload))
|
||||
.field(
|
||||
"output_payload_bytes",
|
||||
&debug_json_bytes(&self.output_payload),
|
||||
)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn gemini_google_search_grounding(
|
||||
tool_object: &Map<String, Value>,
|
||||
) -> Option<GeminiGoogleSearchGrounding> {
|
||||
|
||||
Reference in New Issue
Block a user