typesec_agent/interop/
dialects.rs1use serde_json::Value;
5
6use super::call::{GuardedToolCall, InteropError, ToolCallRequest};
7use super::{anthropic, langchain, mcp, openai, pydantic_ai};
8
9pub type ParseFn = fn(&Value) -> Result<Vec<ToolCallRequest>, InteropError>;
11pub type DenialFn = fn(&GuardedToolCall) -> Option<Value>;
13pub type FilterFn = fn(&Value, &dyn Fn(&str) -> bool) -> Value;
15
16pub struct Dialect {
18 pub name: &'static str,
21 pub parse: ParseFn,
23 pub denial: DenialFn,
25 pub filter: FilterFn,
27}
28
29pub const DIALECTS: &[Dialect] = &[
31 Dialect {
32 name: openai::DIALECT,
33 parse: openai::parse_tool_calls,
34 denial: openai::denial,
35 filter: openai::filter_tools,
36 },
37 Dialect {
38 name: anthropic::DIALECT,
39 parse: anthropic::parse_tool_calls,
40 denial: anthropic::denial,
41 filter: anthropic::filter_tools,
42 },
43 Dialect {
44 name: langchain::DIALECT,
45 parse: langchain::parse_tool_calls,
46 denial: langchain::denial,
47 filter: langchain::filter_tools,
48 },
49 Dialect {
50 name: pydantic_ai::DIALECT,
51 parse: pydantic_ai::parse_tool_calls,
52 denial: pydantic_ai::denial,
53 filter: pydantic_ai::filter_tools,
54 },
55 Dialect {
56 name: mcp::DIALECT,
57 parse: mcp::parse_tool_calls,
58 denial: mcp::denial,
59 filter: mcp::filter_tools,
60 },
61];
62
63pub fn dialect(name: &str) -> Option<&'static Dialect> {
65 let canonical = if name == "pydantic_ai" {
66 "pydantic-ai"
67 } else {
68 name
69 };
70 DIALECTS.iter().find(|dialect| dialect.name == canonical)
71}
72
73pub fn unknown_dialect_message(name: &str) -> String {
75 format!("unknown dialect '{name}' (expected openai, anthropic, langchain, pydantic-ai, or mcp)")
76}