mod convert;
mod formatter;
mod mapper;
mod query;
mod tabular;
pub use convert::{
detect_format, encode_to_format, parse_auto, parse_input, to_json, to_toml, to_toon, to_yaml,
Format, InputFormat, OutputFormat,
};
pub use formatter::{
command_formatter, read_note_formatter, search_formatter, ContentFormatter, FieldFormat,
};
pub use mapper::{
default_registry, ChainMapper, FieldSelectMapper, IdentityMapper, JqMapper, LimitMapper,
Mapper, MapperRegistry, TruncateMapper,
};
pub use query::{compile_filter, run_filter, CompiledFilter};
pub use tabular::encode_table;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum OqError {
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("JSON parse error: {0}")]
JsonParse(#[from] serde_json::Error),
#[error("YAML parse error: {0}")]
YamlParse(#[from] serde_yaml::Error),
#[error("TOML parse error: {0}")]
TomlParse(String),
#[error("TOON parse error: {0}")]
ToonParse(String),
#[error("Filter error: {0}")]
Filter(String),
#[error("Query compile error: {0}")]
Compile(String),
}
pub fn json_to_toon(value: serde_json::Value) -> Result<String, OqError> {
toon_format::encode_default(&value).map_err(|e| OqError::ToonParse(e.to_string()))
}
pub fn json_to_toon_with_mapper(
value: serde_json::Value,
tool_name: &str,
registry: &MapperRegistry,
) -> Result<String, OqError> {
let transformed = registry.transform(tool_name, value)?;
json_to_toon(transformed)
}
pub fn format_tool_response(value: &serde_json::Value) -> String {
toon_format::encode_default(value).unwrap_or_else(|_| {
serde_json::to_string_pretty(value).unwrap_or_else(|_| value.to_string())
})
}
pub fn format_tool_response_smart(value: &serde_json::Value) -> String {
let formatter = ContentFormatter::new().with_default_threshold(200);
formatter
.format(value)
.unwrap_or_else(|_| format_tool_response(value))
}
pub fn format_tool_response_with(value: &serde_json::Value, tool_type: ToolType) -> String {
let formatter = match tool_type {
ToolType::ReadFile => read_note_formatter(),
ToolType::Search => search_formatter(),
ToolType::Command => command_formatter(),
ToolType::Generic => ContentFormatter::new().with_default_threshold(200),
};
formatter
.format(value)
.unwrap_or_else(|_| format_tool_response(value))
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ToolType {
ReadFile,
Search,
Command,
Generic,
}
impl ToolType {
pub fn from_name(name: &str) -> Self {
let name_lower = name.to_lowercase();
if name_lower.contains("search")
|| name_lower.contains("find")
|| name_lower.contains("grep")
{
ToolType::Search
} else if name_lower.contains("exec")
|| name_lower.contains("run")
|| name_lower.contains("shell")
|| name_lower.contains("command")
{
ToolType::Command
} else if name_lower.contains("read")
|| name_lower.contains("file")
|| (name_lower.contains("note") && name_lower.contains("get"))
|| (name_lower.contains("note") && name_lower.contains("content"))
{
ToolType::ReadFile
} else {
ToolType::Generic
}
}
}
pub fn try_parse_json(input: &str) -> serde_json::Value {
serde_json::from_str(input).unwrap_or_else(|_| serde_json::Value::String(input.to_string()))
}
pub fn format_content(input: &str) -> String {
let value = try_parse_json(input);
format_tool_response(&value)
}
pub fn format_content_smart(input: &str) -> String {
let value = try_parse_json(input);
format_tool_response_smart(&value)
}