Skip to main content

objectiveai_sdk/functions/inventions/recursive/response/streaming/
function_invention_recursive_chunk.rs

1use crate::agent;
2use crate::agent::completions::response::streaming::AgentCompletionIds;
3use schemars::JsonSchema;
4use serde::{Deserialize, Serialize};
5
6#[derive(
7    Debug,
8    Clone,
9    PartialEq,
10    Serialize,
11    Deserialize,
12    JsonSchema,
13    arbitrary::Arbitrary,
14)]
15#[schemars(
16    rename = "functions.inventions.recursive.response.streaming.FunctionInventionRecursiveChunk"
17)]
18pub struct FunctionInventionRecursiveChunk {
19    pub id: String,
20    pub inventions: Vec<super::FunctionInventionChunk>,
21    #[serde(skip_serializing_if = "Option::is_none")]
22    #[schemars(extend("omitempty" = true))]
23    pub inventions_errors: Option<bool>,
24    #[arbitrary(with = crate::arbitrary_util::arbitrary_u64)]
25    pub created: u64,
26    pub object: super::Object,
27    #[serde(skip_serializing_if = "Option::is_none")]
28    #[schemars(extend("omitempty" = true))]
29    pub usage: Option<agent::completions::response::Usage>,
30}
31
32impl AgentCompletionIds for FunctionInventionRecursiveChunk {
33    fn agent_completion_ids(&self) -> impl Iterator<Item = &str> + Send {
34        self.inventions
35            .iter()
36            .flat_map(|i| i.agent_completion_ids())
37    }
38}
39
40
41impl FunctionInventionRecursiveChunk {
42    /// Yields each inner error from the recursive chunk's wrapped
43    /// non-recursive `FunctionInventionChunk`s.
44    ///
45    /// For each wrapped invention:
46    /// 1. If the wrapped invention has its own `.error`, yields one item
47    ///    with `agent_completion_index: None`.
48    /// 2. Then yields each item from the wrapped invention's
49    ///    `inner_errors()`, re-tagged with this wrapper's
50    ///    `function_invention_index` and `agent_completion_index:
51    ///    Some(non_recursive.agent_completion_index)`.
52    ///
53    /// Lazy and zero-allocation; collect with `.collect::<Vec<_>>()` if
54    /// you need to retain the items past the chunk's lifetime.
55    pub fn inner_errors(&self) -> impl Iterator<Item = super::InnerError<'_>> {
56        self.inventions.iter().flat_map(|wrapper| {
57            let function_invention_index = wrapper.index;
58            let own = wrapper.inner.error.as_ref().map(move |error| {
59                super::InnerError {
60                    function_invention_index,
61                    agent_completion_index: None,
62                    error: std::borrow::Cow::Borrowed(error),
63                }
64            });
65            let nested =
66                wrapper.inner.inner_errors().map(move |non_recursive| {
67                    super::InnerError {
68                        function_invention_index,
69                        agent_completion_index: Some(
70                            non_recursive.agent_completion_index,
71                        ),
72                        error: non_recursive.error,
73                    }
74                });
75            own.into_iter().chain(nested)
76        })
77    }
78
79    pub fn push(
80        &mut self,
81        FunctionInventionRecursiveChunk {
82            inventions,
83            inventions_errors,
84            usage,
85            ..
86        }: &FunctionInventionRecursiveChunk,
87    ) {
88        self.push_inventions(inventions);
89        if let Some(true) = inventions_errors {
90            self.inventions_errors = Some(true);
91        }
92        match (&mut self.usage, usage) {
93            (Some(self_usage), Some(other_usage)) => {
94                self_usage.push(other_usage);
95            }
96            (None, Some(other_usage)) => {
97                self.usage = Some(other_usage.clone());
98            }
99            _ => {}
100        }
101    }
102
103    fn push_inventions(
104        &mut self,
105        other_inventions: &[super::FunctionInventionChunk],
106    ) {
107        fn push_invention(
108            inventions: &mut Vec<super::FunctionInventionChunk>,
109            other: &super::FunctionInventionChunk,
110        ) {
111            fn find_invention(
112                inventions: &mut Vec<super::FunctionInventionChunk>,
113                index: u64,
114            ) -> Option<&mut super::FunctionInventionChunk> {
115                for invention in inventions {
116                    if invention.index == index {
117                        return Some(invention);
118                    }
119                }
120                None
121            }
122            if let Some(existing) = find_invention(inventions, other.index) {
123                existing.push(other);
124            } else {
125                inventions.push(other.clone());
126            }
127        }
128        for other in other_inventions {
129            push_invention(&mut self.inventions, other);
130        }
131    }
132
133}