objectiveai_sdk/functions/inventions/response/streaming/
function_invention_chunk.rs1use crate::{agent, error, functions};
2use serde::{Deserialize, Serialize};
3use schemars::JsonSchema;
4
5#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema, arbitrary::Arbitrary)]
6#[schemars(rename = "functions.inventions.response.streaming.FunctionInventionChunk")]
7pub struct FunctionInventionChunk {
8 pub id: String,
9 pub completions: Vec<super::AgentCompletionChunk>,
10 #[serde(skip_serializing_if = "Option::is_none")]
12 #[schemars(extend("omitempty" = true))]
13 pub state: Option<functions::inventions::State>,
14 #[serde(skip_serializing_if = "Option::is_none")]
16 #[schemars(extend("omitempty" = true))]
17 pub path: Option<crate::RemotePath>,
18 #[serde(skip_serializing_if = "Option::is_none")]
19 #[schemars(extend("omitempty" = true))]
20 pub function: Option<functions::FullRemoteFunction>,
21 #[arbitrary(with = crate::arbitrary_util::arbitrary_u64)]
22 pub created: u64,
23 pub object: super::Object,
24 #[serde(skip_serializing_if = "Option::is_none")]
25 #[schemars(extend("omitempty" = true))]
26 pub usage: Option<agent::completions::response::Usage>,
27 #[serde(skip_serializing_if = "Option::is_none")]
28 #[schemars(extend("omitempty" = true))]
29 pub error: Option<error::ResponseError>,
30}
31
32impl FunctionInventionChunk {
33 pub fn inner_errors(&self) -> impl Iterator<Item = super::InnerError<'_>> {
41 self.completions.iter().filter_map(|c| {
42 c.inner.error.as_ref().map(|error| super::InnerError {
43 agent_completion_index: c.index,
44 error: std::borrow::Cow::Borrowed(error),
45 })
46 })
47 }
48
49 pub fn push(
50 &mut self,
51 FunctionInventionChunk {
52 completions,
53 state,
54 path,
55 function,
56 usage,
57 error,
58 ..
59 }: &FunctionInventionChunk,
60 ) {
61 self.push_completions(completions);
62 if let Some(state) = state {
63 self.state = Some(state.clone());
64 }
65 if let Some(path) = path {
66 self.path = Some(path.clone());
67 }
68 if let Some(function) = function {
69 self.function = Some(function.clone());
70 }
71 match (&mut self.usage, usage) {
72 (Some(self_usage), Some(other_usage)) => {
73 self_usage.push(other_usage);
74 }
75 (None, Some(other_usage)) => {
76 self.usage = Some(other_usage.clone());
77 }
78 _ => {}
79 }
80 if let Some(error) = error {
81 self.error = Some(error.clone());
82 }
83 }
84
85 fn push_completions(
86 &mut self,
87 other_completions: &[super::AgentCompletionChunk],
88 ) {
89 fn push_completion(
90 completions: &mut Vec<super::AgentCompletionChunk>,
91 other: &super::AgentCompletionChunk,
92 ) {
93 fn find_completion(
94 completions: &mut Vec<super::AgentCompletionChunk>,
95 index: u64,
96 ) -> Option<&mut super::AgentCompletionChunk> {
97 for completion in completions {
98 if completion.index == index {
99 return Some(completion);
100 }
101 }
102 None
103 }
104 if let Some(completion) = find_completion(completions, other.index)
105 {
106 completion.push(other);
107 } else {
108 completions.push(other.clone());
109 }
110 }
111 for other_completion in other_completions {
112 push_completion(&mut self.completions, other_completion);
113 }
114 }
115
116 #[cfg(feature = "filesystem")]
120 pub fn produce_files(&self) -> Option<(serde_json::Value, Vec<crate::filesystem::logs::LogFile>)> {
121 use crate::filesystem::logs::LogFile;
122 const ROUTE: &str = "functions/inventions";
123
124 let id = &self.id;
125 if id.is_empty() {
126 return None;
127 }
128
129 let mut files: Vec<LogFile> = Vec::new();
130 let mut completion_refs: Vec<serde_json::Value> = Vec::new();
131
132 for completion in &self.completions {
133 let (reference, completion_files) = completion.produce_files();
134 completion_refs.push(reference);
135 files.extend(completion_files);
136 }
137
138 let shell = FunctionInventionChunk {
140 id: self.id.clone(),
141 completions: Vec::new(),
142 state: self.state.clone(),
143 path: self.path.clone(),
144 function: self.function.clone(),
145 created: self.created,
146 object: self.object,
147 usage: self.usage.clone(),
148 error: self.error.clone(),
149 };
150 let mut root = serde_json::to_value(&shell).unwrap();
151 root["completions"] = serde_json::Value::Array(completion_refs);
152
153 let root_file = LogFile {
154 route: ROUTE.to_string(),
155 id: id.clone(),
156 message_index: None,
157 media_index: None,
158 extension: "json".to_string(),
159 content: serde_json::to_vec_pretty(&root).unwrap(),
160 };
161 let reference = serde_json::json!({ "type": "reference", "path": root_file.path() });
162 files.push(root_file);
163
164 Some((reference, files))
165 }
166}