objectiveai_sdk/functions/inventions/recursive/response/streaming/
function_invention_recursive_chunk.rs1use crate::agent;
2use serde::{Deserialize, Serialize};
3use schemars::JsonSchema;
4
5#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema, arbitrary::Arbitrary)]
6#[schemars(rename = "functions.inventions.recursive.response.streaming.FunctionInventionRecursiveChunk")]
7pub struct FunctionInventionRecursiveChunk {
8 pub id: String,
9 pub inventions: Vec<super::FunctionInventionChunk>,
10 #[serde(skip_serializing_if = "Option::is_none")]
11 #[schemars(extend("omitempty" = true))]
12 pub inventions_errors: Option<bool>,
13 #[arbitrary(with = crate::arbitrary_util::arbitrary_u64)]
14 pub created: u64,
15 pub object: super::Object,
16 #[serde(skip_serializing_if = "Option::is_none")]
17 #[schemars(extend("omitempty" = true))]
18 pub usage: Option<agent::completions::response::Usage>,
19}
20
21impl FunctionInventionRecursiveChunk {
22 pub fn inner_errors(&self) -> impl Iterator<Item = super::InnerError<'_>> {
36 self.inventions.iter().flat_map(|wrapper| {
37 let function_invention_index = wrapper.index;
38 let own = wrapper.inner.error.as_ref().map(move |error| super::InnerError {
39 function_invention_index,
40 agent_completion_index: None,
41 error: std::borrow::Cow::Borrowed(error),
42 });
43 let nested = wrapper.inner.inner_errors().map(move |non_recursive| {
44 super::InnerError {
45 function_invention_index,
46 agent_completion_index: Some(non_recursive.agent_completion_index),
47 error: non_recursive.error,
48 }
49 });
50 own.into_iter().chain(nested)
51 })
52 }
53
54 pub fn push(
55 &mut self,
56 FunctionInventionRecursiveChunk {
57 inventions,
58 inventions_errors,
59 usage,
60 ..
61 }: &FunctionInventionRecursiveChunk,
62 ) {
63 self.push_inventions(inventions);
64 if let Some(true) = inventions_errors {
65 self.inventions_errors = Some(true);
66 }
67 match (&mut self.usage, usage) {
68 (Some(self_usage), Some(other_usage)) => {
69 self_usage.push(other_usage);
70 }
71 (None, Some(other_usage)) => {
72 self.usage = Some(other_usage.clone());
73 }
74 _ => {}
75 }
76 }
77
78 fn push_inventions(
79 &mut self,
80 other_inventions: &[super::FunctionInventionChunk],
81 ) {
82 fn push_invention(
83 inventions: &mut Vec<super::FunctionInventionChunk>,
84 other: &super::FunctionInventionChunk,
85 ) {
86 fn find_invention(
87 inventions: &mut Vec<super::FunctionInventionChunk>,
88 index: u64,
89 ) -> Option<&mut super::FunctionInventionChunk> {
90 for invention in inventions {
91 if invention.index == index {
92 return Some(invention);
93 }
94 }
95 None
96 }
97 if let Some(existing) = find_invention(inventions, other.index) {
98 existing.push(other);
99 } else {
100 inventions.push(other.clone());
101 }
102 }
103 for other in other_inventions {
104 push_invention(&mut self.inventions, other);
105 }
106 }
107
108 #[cfg(feature = "filesystem")]
112 pub fn produce_files(&self) -> Option<(serde_json::Value, Vec<crate::filesystem::logs::LogFile>)> {
113 use crate::filesystem::logs::LogFile;
114 const ROUTE: &str = "functions/inventions/recursive";
115
116 let id = &self.id;
117 if id.is_empty() {
118 return None;
119 }
120
121 let mut files: Vec<LogFile> = Vec::new();
122 let mut invention_refs: Vec<serde_json::Value> = Vec::new();
123
124 for invention in &self.inventions {
125 let (reference, invention_files) = invention.produce_files();
126 invention_refs.push(reference);
127 files.extend(invention_files);
128 }
129
130 let shell = FunctionInventionRecursiveChunk {
132 id: self.id.clone(),
133 inventions: Vec::new(),
134 inventions_errors: self.inventions_errors,
135 created: self.created,
136 object: self.object,
137 usage: self.usage.clone(),
138 };
139 let mut root = serde_json::to_value(&shell).unwrap();
140 root["inventions"] = serde_json::Value::Array(invention_refs);
141
142 let root_file = LogFile {
143 route: ROUTE.to_string(),
144 id: id.clone(),
145 message_index: None,
146 media_index: None,
147 extension: "json".to_string(),
148 content: serde_json::to_vec_pretty(&root).unwrap(),
149 };
150 let reference = serde_json::json!({ "type": "reference", "path": root_file.path() });
151 files.push(root_file);
152
153 Some((reference, files))
154 }
155}