use std::fmt;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Agent {
pub id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
pub model: ModelConfig,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub system: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub tools: Vec<serde_json::Value>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub mcp_servers: Vec<McpServerConfig>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub skills: Vec<serde_json::Value>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub version: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub created_at: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub updated_at: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub archived_at: Option<String>,
#[serde(flatten)]
pub extra: serde_json::Map<String, serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct CreateAgentParams {
pub name: String,
pub model: serde_json::Value,
#[serde(skip_serializing_if = "Option::is_none")]
pub system: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub tools: Vec<serde_json::Value>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub mcp_servers: Vec<serde_json::Value>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub skills: Vec<serde_json::Value>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub multiagent: Option<serde_json::Value>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub metadata: Option<serde_json::Map<String, serde_json::Value>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ModelConfig {
pub id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub speed: Option<String>,
}
impl ModelConfig {
pub fn new(id: impl Into<String>) -> Self {
Self { id: id.into(), speed: None }
}
}
pub struct ToolConfig;
impl ToolConfig {
pub fn agent_toolset() -> serde_json::Value {
serde_json::json!({"type": "agent_toolset_20260401"})
}
pub fn custom(
name: impl Into<String>,
description: impl Into<String>,
input_schema: serde_json::Value,
) -> serde_json::Value {
serde_json::json!({
"type": "custom",
"name": name.into(),
"description": description.into(),
"input_schema": input_schema,
})
}
pub fn mcp_toolset(mcp_server_name: impl Into<String>) -> serde_json::Value {
serde_json::json!({
"type": "mcp_toolset",
"mcp_server_name": mcp_server_name.into(),
})
}
pub fn mcp_toolset_with_policy(
mcp_server_name: impl Into<String>,
policy: impl Into<String>,
) -> serde_json::Value {
serde_json::json!({
"type": "mcp_toolset",
"mcp_server_name": mcp_server_name.into(),
"default_config": {
"permission_policy": {"type": policy.into()}
},
})
}
pub fn mcp_toolset_with_configs(
mcp_server_name: impl Into<String>,
configs: Vec<serde_json::Value>,
) -> serde_json::Value {
serde_json::json!({
"type": "mcp_toolset",
"mcp_server_name": mcp_server_name.into(),
"configs": configs,
})
}
pub fn agent_toolset_with_policy(policy: impl Into<String>) -> serde_json::Value {
serde_json::json!({
"type": "agent_toolset_20260401",
"default_config": {
"permission_policy": {"type": policy.into()}
},
})
}
}
pub struct McpServer;
impl McpServer {
pub fn url(name: impl Into<String>, url: impl Into<String>) -> serde_json::Value {
serde_json::json!({
"type": "url",
"name": name.into(),
"url": url.into(),
})
}
}
#[derive(Clone, Serialize, Deserialize, PartialEq)]
pub struct McpServerConfig {
#[serde(rename = "type", default = "default_mcp_type")]
pub server_type: String,
pub name: String,
pub url: String,
}
fn default_mcp_type() -> String {
"url".to_string()
}
#[derive(Clone, Serialize, Deserialize, PartialEq)]
pub struct McpAuth {
#[serde(rename = "type")]
pub auth_type: String,
pub token: String,
}
impl fmt::Debug for McpServerConfig {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("McpServerConfig")
.field("type", &self.server_type)
.field("name", &self.name)
.field("url", &self.url)
.finish()
}
}
impl fmt::Debug for McpAuth {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("McpAuth")
.field("auth_type", &self.auth_type)
.field("token", &"[REDACTED]")
.finish()
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Environment {
pub id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub config: Option<serde_json::Value>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub state: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub created_at: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub updated_at: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub archived_at: Option<String>,
#[serde(flatten)]
pub extra: serde_json::Map<String, serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct CreateEnvironmentParams {
pub name: String,
pub config: serde_json::Value,
}
impl CreateEnvironmentParams {
pub fn cloud(name: impl Into<String>) -> Self {
Self {
name: name.into(),
config: serde_json::json!({
"type": "cloud",
"networking": {"type": "unrestricted"}
}),
}
}
pub fn cloud_with_config(name: impl Into<String>, config: serde_json::Value) -> Self {
Self { name: name.into(), config }
}
pub fn self_hosted(name: impl Into<String>) -> Self {
Self { name: name.into(), config: serde_json::json!({"type": "self_hosted"}) }
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Session {
pub id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub agent: Option<serde_json::Value>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub environment_id: Option<String>,
pub status: SessionStatus,
#[serde(default)]
pub usage: UsageTracking,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub created_at: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub updated_at: Option<String>,
#[serde(flatten)]
pub extra: serde_json::Map<String, serde_json::Value>,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum SessionStatus {
Idle,
Running,
Rescheduling,
Terminated,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
pub struct UsageTracking {
#[serde(default)]
pub input_tokens: u64,
#[serde(default)]
pub output_tokens: u64,
#[serde(default)]
pub cache_read_input_tokens: u64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cache_creation: Option<serde_json::Value>,
#[serde(default)]
pub cache_creation_input_tokens: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct CreateSessionParams {
pub agent: serde_json::Value,
pub environment_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub title: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub vault_ids: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub resources: Vec<serde_json::Value>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub metadata: Option<serde_json::Map<String, serde_json::Value>>,
}
impl CreateSessionParams {
pub fn new(agent_id: impl Into<String>, environment_id: impl Into<String>) -> Self {
Self {
agent: serde_json::Value::String(agent_id.into()),
environment_id: environment_id.into(),
title: None,
vault_ids: vec![],
resources: vec![],
metadata: None,
}
}
pub fn with_metadata(mut self, metadata: serde_json::Map<String, serde_json::Value>) -> Self {
self.metadata = Some(metadata);
self
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
pub struct ListSessionsParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub agent_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub limit: Option<u32>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub(crate) struct ListResponse<T> {
pub data: Vec<T>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct SessionResource {
#[serde(rename = "type")]
pub resource_type: String,
pub file_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub mount_path: Option<String>,
}
impl SessionResource {
pub fn file(file_id: impl Into<String>) -> serde_json::Value {
serde_json::json!({
"type": "file",
"file_id": file_id.into(),
})
}
pub fn file_at(file_id: impl Into<String>, mount_path: impl Into<String>) -> serde_json::Value {
serde_json::json!({
"type": "file",
"file_id": file_id.into(),
"mount_path": mount_path.into(),
})
}
pub fn github_repo(
url: impl Into<String>,
mount_path: impl Into<String>,
token: impl Into<String>,
) -> serde_json::Value {
serde_json::json!({
"type": "github_repository",
"url": url.into(),
"mount_path": mount_path.into(),
"authorization_token": token.into(),
})
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct SessionResourceResponse {
pub id: String,
#[serde(rename = "type", default, skip_serializing_if = "Option::is_none")]
pub resource_type: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub file_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub mount_path: Option<String>,
#[serde(flatten)]
pub extra: serde_json::Map<String, serde_json::Value>,
}
pub struct Multiagent;
impl Multiagent {
pub fn coordinator(agents: Vec<serde_json::Value>) -> serde_json::Value {
serde_json::json!({
"type": "coordinator",
"agents": agents,
})
}
pub fn agent_ref(agent_id: impl Into<String>) -> serde_json::Value {
serde_json::json!({
"type": "agent",
"id": agent_id.into(),
})
}
pub fn agent_ref_versioned(agent_id: impl Into<String>, version: u64) -> serde_json::Value {
serde_json::json!({
"type": "agent",
"id": agent_id.into(),
"version": version,
})
}
pub fn self_ref() -> serde_json::Value {
serde_json::json!({"type": "self"})
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct SessionThread {
pub id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub agent: Option<serde_json::Value>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub parent_thread_id: Option<String>,
#[serde(flatten)]
pub extra: serde_json::Map<String, serde_json::Value>,
}