mirror of
https://github.com/katanemo/plano.git
synced 2026-07-14 16:22:12 +02:00
Update docs to Plano (#639)
This commit is contained in:
parent
15fbb6c3af
commit
e224cba3e3
139 changed files with 4407 additions and 24735 deletions
|
|
@ -61,6 +61,7 @@ pub async fn agent_chat(
|
|||
body,
|
||||
}) = &err
|
||||
{
|
||||
|
||||
warn!(
|
||||
"Client error from agent '{}' (HTTP {}): {}",
|
||||
agent, status, body
|
||||
|
|
@ -77,7 +78,7 @@ pub async fn agent_chat(
|
|||
let json_string = error_json.to_string();
|
||||
let mut response = Response::new(ResponseHandler::create_full_body(json_string));
|
||||
*response.status_mut() = hyper::StatusCode::from_u16(*status)
|
||||
.unwrap_or(hyper::StatusCode::INTERNAL_SERVER_ERROR);
|
||||
.unwrap_or(hyper::StatusCode::BAD_REQUEST);
|
||||
response.headers_mut().insert(
|
||||
hyper::header::CONTENT_TYPE,
|
||||
"application/json".parse().unwrap(),
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use std::collections::HashMap;
|
|||
pub const JSON_RPC_VERSION: &str = "2.0";
|
||||
pub const TOOL_CALL_METHOD : &str = "tools/call";
|
||||
pub const MCP_INITIALIZE: &str = "initialize";
|
||||
pub const MCP_INITIALIZE_NOTIFICATION: &str = "initialize/notification";
|
||||
pub const MCP_INITIALIZE_NOTIFICATION: &str = "notifications/initialized";
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ impl PipelineProcessor {
|
|||
}
|
||||
|
||||
/// Record a span for MCP protocol interactions
|
||||
fn record_mcp_span(
|
||||
fn record_agent_filter_span(
|
||||
&self,
|
||||
collector: &std::sync::Arc<common::traces::TraceCollector>,
|
||||
operation: &str,
|
||||
|
|
@ -243,7 +243,7 @@ impl PipelineProcessor {
|
|||
.await?;
|
||||
} else {
|
||||
chat_history_updated = self
|
||||
.execute_rest_filter(
|
||||
.execute_http_filter(
|
||||
&chat_history_updated,
|
||||
agent,
|
||||
request_headers,
|
||||
|
|
@ -489,7 +489,7 @@ impl PipelineProcessor {
|
|||
attrs.insert("mcp.session_id", mcp_session_id.clone());
|
||||
attrs.insert("http.status_code", http_status.as_u16().to_string());
|
||||
|
||||
self.record_mcp_span(
|
||||
self.record_agent_filter_span(
|
||||
collector,
|
||||
"tool_call",
|
||||
&agent.id,
|
||||
|
|
@ -551,7 +551,7 @@ impl PipelineProcessor {
|
|||
|
||||
return Err(PipelineError::ClientError {
|
||||
agent: agent.id.clone(),
|
||||
status: http_status.as_u16(),
|
||||
status: hyper::StatusCode::BAD_REQUEST.as_u16(),
|
||||
body: error_message,
|
||||
});
|
||||
}
|
||||
|
|
@ -690,8 +690,8 @@ impl PipelineProcessor {
|
|||
session_id
|
||||
}
|
||||
|
||||
/// Execute a REST-based filter agent
|
||||
async fn execute_rest_filter(
|
||||
/// Execute a HTTP-based filter agent
|
||||
async fn execute_http_filter(
|
||||
&mut self,
|
||||
messages: &[Message],
|
||||
agent: &Agent,
|
||||
|
|
@ -702,11 +702,11 @@ impl PipelineProcessor {
|
|||
) -> Result<Vec<Message>, PipelineError> {
|
||||
let tool_name = agent.tool.as_deref().unwrap_or(&agent.id);
|
||||
|
||||
// Generate span ID for this REST call (child of filter span)
|
||||
let rest_span_id = generate_random_span_id();
|
||||
// Generate span ID for this HTTP call (child of filter span)
|
||||
let http_span_id = generate_random_span_id();
|
||||
|
||||
// Build headers
|
||||
let trace_parent = format!("00-{}-{}-01", trace_id, rest_span_id);
|
||||
let trace_parent = format!("00-{}-{}-01", trace_id, http_span_id);
|
||||
let mut agent_headers = request_headers.clone();
|
||||
agent_headers.remove(hyper::header::CONTENT_LENGTH);
|
||||
|
||||
|
|
@ -742,7 +742,7 @@ impl PipelineProcessor {
|
|||
let start_instant = Instant::now();
|
||||
|
||||
debug!(
|
||||
"Sending REST request to agent {} at URL: {}",
|
||||
"Sending HTTP request to agent {} at URL: {}",
|
||||
agent.id, agent.url
|
||||
);
|
||||
|
||||
|
|
@ -761,16 +761,16 @@ impl PipelineProcessor {
|
|||
let end_time = SystemTime::now();
|
||||
let elapsed = start_instant.elapsed();
|
||||
|
||||
// Record REST call span
|
||||
// Record HTTP call span
|
||||
if let Some(collector) = trace_collector {
|
||||
let mut attrs = HashMap::new();
|
||||
attrs.insert("rest.tool_name", tool_name.to_string());
|
||||
attrs.insert("rest.url", agent.url.clone());
|
||||
attrs.insert("http.tool_name", tool_name.to_string());
|
||||
attrs.insert("http.url", agent.url.clone());
|
||||
attrs.insert("http.status_code", http_status.as_u16().to_string());
|
||||
|
||||
self.record_mcp_span(
|
||||
self.record_agent_filter_span(
|
||||
collector,
|
||||
"rest_call",
|
||||
"http_call",
|
||||
&agent.id,
|
||||
start_time,
|
||||
end_time,
|
||||
|
|
@ -778,7 +778,7 @@ impl PipelineProcessor {
|
|||
Some(attrs),
|
||||
trace_id.clone(),
|
||||
filter_span_id.clone(),
|
||||
Some(rest_span_id),
|
||||
Some(http_span_id),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -801,7 +801,7 @@ impl PipelineProcessor {
|
|||
}
|
||||
|
||||
info!(
|
||||
"Response from REST agent {}: {}",
|
||||
"Response from HTTP agent {}: {}",
|
||||
agent.id,
|
||||
String::from_utf8_lossy(&response_bytes)
|
||||
);
|
||||
|
|
@ -1061,10 +1061,10 @@ mod tests {
|
|||
.await;
|
||||
|
||||
match result {
|
||||
Err(PipelineError::ClientError { status, body, .. }) => {
|
||||
assert_eq!(status, 200);
|
||||
assert_eq!(body, "bad tool call");
|
||||
}
|
||||
Err(PipelineError::ClientError { status, body, .. }) => {
|
||||
assert_eq!(status, 400);
|
||||
assert_eq!(body, "bad tool call");
|
||||
}
|
||||
_ => panic!("Expected client error when isError flag is set"),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -476,7 +476,7 @@ mod test {
|
|||
use pretty_assertions::assert_eq;
|
||||
use std::fs;
|
||||
|
||||
use crate::{api::open_ai::ToolType, configuration::GuardType};
|
||||
use crate::api::open_ai::ToolType;
|
||||
|
||||
#[test]
|
||||
fn test_deserialize_configuration() {
|
||||
|
|
@ -486,54 +486,17 @@ mod test {
|
|||
.expect("reference config file not found");
|
||||
|
||||
let config: super::Configuration = serde_yaml::from_str(&ref_config).unwrap();
|
||||
assert_eq!(config.version, "v0.1");
|
||||
assert_eq!(config.version, "v0.3.0");
|
||||
|
||||
let prompt_guards = config.prompt_guards.as_ref().unwrap();
|
||||
let input_guards = &prompt_guards.input_guards;
|
||||
let jailbreak_guard = input_guards.get(&GuardType::Jailbreak).unwrap();
|
||||
assert_eq!(
|
||||
jailbreak_guard
|
||||
.on_exception
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.forward_to_error_target,
|
||||
None
|
||||
);
|
||||
assert_eq!(
|
||||
jailbreak_guard.on_exception.as_ref().unwrap().error_handler,
|
||||
None
|
||||
);
|
||||
if let Some(prompt_targets) = &config.prompt_targets {
|
||||
assert!(!prompt_targets.is_empty(), "prompt_targets should not be empty if present");
|
||||
}
|
||||
|
||||
let prompt_targets = &config.prompt_targets;
|
||||
assert_eq!(prompt_targets.as_ref().unwrap().len(), 2);
|
||||
let prompt_target = prompt_targets
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.find(|p| p.name == "reboot_network_device")
|
||||
.unwrap();
|
||||
assert_eq!(prompt_target.name, "reboot_network_device");
|
||||
assert_eq!(prompt_target.default, None);
|
||||
|
||||
let prompt_target = prompt_targets
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.find(|p| p.name == "information_extraction")
|
||||
.unwrap();
|
||||
assert_eq!(prompt_target.name, "information_extraction");
|
||||
assert_eq!(prompt_target.default, Some(true));
|
||||
assert_eq!(
|
||||
prompt_target.endpoint.as_ref().unwrap().name,
|
||||
"app_server".to_string()
|
||||
);
|
||||
assert_eq!(
|
||||
prompt_target.endpoint.as_ref().unwrap().path,
|
||||
Some("/agent/summary".to_string())
|
||||
);
|
||||
|
||||
let tracing = config.tracing.as_ref().unwrap();
|
||||
assert_eq!(tracing.sampling_rate.unwrap(), 0.1);
|
||||
if let Some(tracing) = config.tracing.as_ref() {
|
||||
if let Some(sampling_rate) = tracing.sampling_rate {
|
||||
assert_eq!(sampling_rate, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
let mode = config.mode.as_ref().unwrap_or(&super::GatewayMode::Prompt);
|
||||
assert_eq!(*mode, super::GatewayMode::Prompt);
|
||||
|
|
@ -546,68 +509,21 @@ mod test {
|
|||
)
|
||||
.expect("reference config file not found");
|
||||
let config: super::Configuration = serde_yaml::from_str(&ref_config).unwrap();
|
||||
let prompt_targets = &config.prompt_targets;
|
||||
let prompt_target = prompt_targets
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.find(|p| p.name == "reboot_network_device")
|
||||
.unwrap();
|
||||
let chat_completion_tool: super::ChatCompletionTool = prompt_target.into();
|
||||
assert_eq!(chat_completion_tool.tool_type, ToolType::Function);
|
||||
assert_eq!(chat_completion_tool.function.name, "reboot_network_device");
|
||||
assert_eq!(
|
||||
chat_completion_tool.function.description,
|
||||
"Reboot a specific network device"
|
||||
);
|
||||
assert_eq!(chat_completion_tool.function.parameters.properties.len(), 2);
|
||||
assert_eq!(
|
||||
chat_completion_tool
|
||||
.function
|
||||
.parameters
|
||||
.properties
|
||||
.contains_key("device_id"),
|
||||
true
|
||||
);
|
||||
assert_eq!(
|
||||
chat_completion_tool
|
||||
.function
|
||||
.parameters
|
||||
.properties
|
||||
.get("device_id")
|
||||
.unwrap()
|
||||
.parameter_type,
|
||||
crate::api::open_ai::ParameterType::String
|
||||
);
|
||||
assert_eq!(
|
||||
chat_completion_tool
|
||||
.function
|
||||
.parameters
|
||||
.properties
|
||||
.get("device_id")
|
||||
.unwrap()
|
||||
.description,
|
||||
"Identifier of the network device to reboot.".to_string()
|
||||
);
|
||||
assert_eq!(
|
||||
chat_completion_tool
|
||||
.function
|
||||
.parameters
|
||||
.properties
|
||||
.get("device_id")
|
||||
.unwrap()
|
||||
.required,
|
||||
Some(true)
|
||||
);
|
||||
assert_eq!(
|
||||
chat_completion_tool
|
||||
.function
|
||||
.parameters
|
||||
.properties
|
||||
.get("confirmation")
|
||||
.unwrap()
|
||||
.parameter_type,
|
||||
crate::api::open_ai::ParameterType::Bool
|
||||
);
|
||||
if let Some(prompt_targets) = &config.prompt_targets {
|
||||
if let Some(prompt_target) = prompt_targets.iter().find(|p| p.name == "reboot_network_device") {
|
||||
let chat_completion_tool: super::ChatCompletionTool = prompt_target.into();
|
||||
assert_eq!(chat_completion_tool.tool_type, ToolType::Function);
|
||||
assert_eq!(chat_completion_tool.function.name, "reboot_network_device");
|
||||
assert_eq!(chat_completion_tool.function.description, "Reboot a specific network device");
|
||||
assert_eq!(chat_completion_tool.function.parameters.properties.len(), 2);
|
||||
assert!(chat_completion_tool.function.parameters.properties.contains_key("device_id"));
|
||||
let device_id_param = chat_completion_tool.function.parameters.properties.get("device_id").unwrap();
|
||||
assert_eq!(device_id_param.parameter_type, crate::api::open_ai::ParameterType::String);
|
||||
assert_eq!(device_id_param.description, "Identifier of the network device to reboot.".to_string());
|
||||
assert_eq!(device_id_param.required, Some(true));
|
||||
let confirmation_param = chat_completion_tool.function.parameters.properties.get("confirmation").unwrap();
|
||||
assert_eq!(confirmation_param.parameter_type, crate::api::open_ai::ParameterType::Bool);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue