use bitflags::bitflags;
use serde::{Deserialize, Serialize};
use crate::Json;
use crate::api::event::PendingMarkSpec;
pub const TOOL_EXECUTION_RESULT_SCHEMA: &str = "nemo.relay.ToolExecutionResult@1";
pub const TOOL_EXECUTION_INTERCEPT_OUTCOME_SCHEMA: &str =
"nemo.relay.ToolExecutionInterceptOutcome@2";
fn normalize_annotation(annotation: Option<Json>) -> Option<Json> {
annotation.filter(|value| !value.is_null())
}
fn normalized_annotation(annotation: &Option<Json>) -> Option<&Json> {
annotation.as_ref().filter(|value| !value.is_null())
}
fn annotation_is_absent(annotation: &Option<Json>) -> bool {
normalized_annotation(annotation).is_none()
}
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct ToolAttributes: u32 {
const REMOTE = 0b01;
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolExecutionResult {
pub result: Json,
#[serde(default, skip_serializing_if = "annotation_is_absent")]
pub annotation: Option<Json>,
}
impl ToolExecutionResult {
pub fn new(result: Json) -> Self {
Self {
result,
annotation: None,
}
}
pub fn annotated(result: Json, annotation: Json) -> Self {
Self {
result,
annotation: normalize_annotation(Some(annotation)),
}
}
#[must_use]
pub fn with_annotation(mut self, annotation: Json) -> Self {
self.annotation = normalize_annotation(Some(annotation));
self
}
#[must_use]
pub fn without_annotation(mut self) -> Self {
self.annotation = None;
self
}
}
impl PartialEq for ToolExecutionResult {
fn eq(&self, other: &Self) -> bool {
self.result == other.result
&& normalized_annotation(&self.annotation) == normalized_annotation(&other.annotation)
}
}
impl From<Json> for ToolExecutionResult {
fn from(result: Json) -> Self {
Self::new(result)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolExecutionInterceptOutcome {
pub result: Json,
#[serde(default, skip_serializing_if = "annotation_is_absent")]
pub annotation: Option<Json>,
#[serde(default)]
pub pending_marks: Vec<PendingMarkSpec>,
}
impl ToolExecutionInterceptOutcome {
pub fn new(result: Json) -> Self {
Self {
result,
annotation: None,
pending_marks: Vec::new(),
}
}
pub fn annotated(result: Json, annotation: Json) -> Self {
Self {
result,
annotation: normalize_annotation(Some(annotation)),
pending_marks: Vec::new(),
}
}
#[must_use]
pub fn with_annotation(mut self, annotation: Json) -> Self {
self.annotation = normalize_annotation(Some(annotation));
self
}
#[must_use]
pub fn without_annotation(mut self) -> Self {
self.annotation = None;
self
}
pub fn into_execution_result(self) -> ToolExecutionResult {
ToolExecutionResult {
result: self.result,
annotation: normalize_annotation(self.annotation),
}
}
#[must_use]
pub fn with_pending_mark(mut self, mark: PendingMarkSpec) -> Self {
self.pending_marks.push(mark);
self
}
}
impl PartialEq for ToolExecutionInterceptOutcome {
fn eq(&self, other: &Self) -> bool {
self.result == other.result
&& normalized_annotation(&self.annotation) == normalized_annotation(&other.annotation)
&& self.pending_marks == other.pending_marks
}
}
impl From<Json> for ToolExecutionInterceptOutcome {
fn from(result: Json) -> Self {
Self::new(result)
}
}
impl From<ToolExecutionResult> for ToolExecutionInterceptOutcome {
fn from(result: ToolExecutionResult) -> Self {
Self {
result: result.result,
annotation: normalize_annotation(result.annotation),
pending_marks: Vec::new(),
}
}
}