Skip to main content

objectiveai_sdk/agent/
agent.rs

1//! Core Agent types — unified enum dispatching to per-upstream implementations.
2
3use schemars::JsonSchema;
4use serde::{Deserialize, Serialize};
5
6// ── Pre-validation types (no computed ID) ──────────────────────────
7
8/// The base inline configuration for an Agent (without computed ID or metadata).
9///
10/// This is an untagged enum that dispatches to the per-upstream AgentBase.
11/// Deserialization tries each variant in order until one matches.
12#[derive(
13    Clone,
14    Debug,
15    PartialEq,
16    Serialize,
17    Deserialize,
18    JsonSchema,
19    arbitrary::Arbitrary,
20)]
21#[serde(untagged)]
22#[schemars(rename = "agent.InlineAgentBase")]
23pub enum InlineAgentBase {
24    #[schemars(title = "Openrouter")]
25    Openrouter(super::openrouter::AgentBase),
26    #[schemars(title = "ClaudeAgentSdk")]
27    ClaudeAgentSdk(super::claude_agent_sdk::AgentBase),
28    #[schemars(title = "CodexSdk")]
29    CodexSdk(super::codex_sdk::AgentBase),
30    #[schemars(title = "Mock")]
31    Mock(super::mock::AgentBase),
32}
33
34impl InlineAgentBase {
35    pub fn as_ref(&self) -> InlineAgentRef<'_> {
36        match self {
37            InlineAgentBase::Openrouter(b) => InlineAgentRef::Openrouter(b),
38            InlineAgentBase::ClaudeAgentSdk(b) => {
39                InlineAgentRef::ClaudeAgentSdk(b)
40            }
41            InlineAgentBase::CodexSdk(b) => InlineAgentRef::CodexSdk(b),
42            InlineAgentBase::Mock(b) => InlineAgentRef::Mock(b),
43        }
44    }
45
46    pub fn model(&self) -> &str {
47        self.as_ref().model()
48    }
49
50    pub fn upstream(&self) -> super::Upstream {
51        self.as_ref().upstream()
52    }
53
54    pub fn output_mode(&self) -> super::OutputMode {
55        self.as_ref().output_mode()
56    }
57
58    pub fn mcp_servers(&self) -> Option<&super::McpServers> {
59        self.as_ref().mcp_servers()
60    }
61
62    pub fn client_objectiveai_mcp(
63        &self,
64    ) -> Option<&super::ClientObjectiveaiMcp> {
65        self.as_ref().client_objectiveai_mcp()
66    }
67
68    pub fn prepare(&mut self) {
69        match self {
70            InlineAgentBase::Openrouter(b) => b.prepare(),
71            InlineAgentBase::ClaudeAgentSdk(b) => b.prepare(),
72            InlineAgentBase::CodexSdk(b) => b.prepare(),
73            InlineAgentBase::Mock(b) => b.prepare(),
74        }
75    }
76
77    pub fn validate(&self) -> Result<(), String> {
78        match self {
79            InlineAgentBase::Openrouter(b) => b.validate(),
80            InlineAgentBase::ClaudeAgentSdk(b) => b.validate(),
81            InlineAgentBase::CodexSdk(b) => b.validate(),
82            InlineAgentBase::Mock(b) => b.validate(),
83        }
84    }
85
86    pub fn id(&self) -> String {
87        match self {
88            InlineAgentBase::Openrouter(b) => b.id(),
89            InlineAgentBase::ClaudeAgentSdk(b) => b.id(),
90            InlineAgentBase::CodexSdk(b) => b.id(),
91            InlineAgentBase::Mock(b) => b.id(),
92        }
93    }
94
95    /// Validates and converts to an [`InlineAgent`] with computed ID.
96    pub fn convert(self) -> Result<InlineAgent, String> {
97        match self {
98            InlineAgentBase::Openrouter(b) => {
99                Ok(InlineAgent::Openrouter(b.try_into()?))
100            }
101            InlineAgentBase::ClaudeAgentSdk(b) => {
102                Ok(InlineAgent::ClaudeAgentSdk(b.try_into()?))
103            }
104            InlineAgentBase::CodexSdk(b) => {
105                Ok(InlineAgent::CodexSdk(b.try_into()?))
106            }
107            InlineAgentBase::Mock(b) => Ok(InlineAgent::Mock(b.try_into()?)),
108        }
109    }
110}
111
112/// A remote agent base definition with metadata.
113///
114/// Like [`InlineAgentBase`] but includes a description field for remote storage.
115#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
116#[schemars(rename = "agent.RemoteAgentBase")]
117pub struct RemoteAgentBase {
118    pub description: String,
119    #[serde(flatten)]
120    #[schemars(schema_with = "crate::flatten_schema::<InlineAgentBase>")]
121    pub inner: InlineAgentBase,
122}
123
124impl RemoteAgentBase {
125    pub fn as_ref(&self) -> InlineAgentRef<'_> {
126        self.inner.as_ref()
127    }
128
129    pub fn model(&self) -> &str {
130        self.inner.model()
131    }
132
133    pub fn upstream(&self) -> super::Upstream {
134        self.inner.upstream()
135    }
136
137    pub fn output_mode(&self) -> super::OutputMode {
138        self.inner.output_mode()
139    }
140
141    pub fn mcp_servers(&self) -> Option<&super::McpServers> {
142        self.inner.mcp_servers()
143    }
144
145    pub fn client_objectiveai_mcp(
146        &self,
147    ) -> Option<&super::ClientObjectiveaiMcp> {
148        self.inner.client_objectiveai_mcp()
149    }
150
151    pub fn prepare(&mut self) {
152        self.inner.prepare()
153    }
154
155    pub fn validate(&self) -> Result<(), String> {
156        self.inner.validate()
157    }
158
159    pub fn id(&self) -> String {
160        self.inner.id()
161    }
162
163    /// Validates and converts to a [`RemoteAgent`] with computed ID.
164    pub fn convert(self) -> Result<RemoteAgent, String> {
165        Ok(RemoteAgent {
166            description: self.description,
167            inner: self.inner.convert()?,
168        })
169    }
170}
171
172/// An Agent base definition, either remote (with metadata) or inline.
173#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
174#[serde(untagged)]
175#[schemars(rename = "agent.AgentBase")]
176pub enum AgentBase {
177    #[schemars(title = "Remote")]
178    Remote(RemoteAgentBase),
179    #[schemars(title = "Inline")]
180    Inline(InlineAgentBase),
181}
182
183impl AgentBase {
184    pub fn as_ref(&self) -> InlineAgentRef<'_> {
185        match self {
186            AgentBase::Remote(r) => r.as_ref(),
187            AgentBase::Inline(i) => i.as_ref(),
188        }
189    }
190
191    pub fn model(&self) -> &str {
192        match self {
193            AgentBase::Remote(r) => r.model(),
194            AgentBase::Inline(i) => i.model(),
195        }
196    }
197
198    pub fn upstream(&self) -> super::Upstream {
199        match self {
200            AgentBase::Remote(r) => r.upstream(),
201            AgentBase::Inline(i) => i.upstream(),
202        }
203    }
204
205    pub fn output_mode(&self) -> super::OutputMode {
206        match self {
207            AgentBase::Remote(r) => r.output_mode(),
208            AgentBase::Inline(i) => i.output_mode(),
209        }
210    }
211
212    pub fn mcp_servers(&self) -> Option<&super::McpServers> {
213        match self {
214            AgentBase::Remote(r) => r.mcp_servers(),
215            AgentBase::Inline(i) => i.mcp_servers(),
216        }
217    }
218
219    pub fn client_objectiveai_mcp(
220        &self,
221    ) -> Option<&super::ClientObjectiveaiMcp> {
222        match self {
223            AgentBase::Remote(r) => r.client_objectiveai_mcp(),
224            AgentBase::Inline(i) => i.client_objectiveai_mcp(),
225        }
226    }
227
228    pub fn prepare(&mut self) {
229        match self {
230            AgentBase::Remote(r) => r.prepare(),
231            AgentBase::Inline(i) => i.prepare(),
232        }
233    }
234
235    pub fn validate(&self) -> Result<(), String> {
236        match self {
237            AgentBase::Remote(r) => r.validate(),
238            AgentBase::Inline(i) => i.validate(),
239        }
240    }
241
242    pub fn id(&self) -> String {
243        match self {
244            AgentBase::Remote(r) => r.id(),
245            AgentBase::Inline(i) => i.id(),
246        }
247    }
248
249    /// Validates and converts to an [`Agent`] with computed ID.
250    pub fn convert(self) -> Result<Agent, String> {
251        match self {
252            AgentBase::Remote(r) => Ok(Agent::Remote(r.convert()?)),
253            AgentBase::Inline(i) => Ok(Agent::Inline(i.convert()?)),
254        }
255    }
256}
257
258// ── Ref types ──────────────────────────────────────────────────────
259
260/// A borrowed reference into an [`InlineAgentBase`] variant.
261#[derive(Clone, Copy, Debug)]
262pub enum InlineAgentRef<'a> {
263    Openrouter(&'a super::openrouter::AgentBase),
264    ClaudeAgentSdk(&'a super::claude_agent_sdk::AgentBase),
265    CodexSdk(&'a super::codex_sdk::AgentBase),
266    Mock(&'a super::mock::AgentBase),
267}
268
269impl<'a> InlineAgentRef<'a> {
270    pub fn to_owned(self) -> InlineAgentBase {
271        match self {
272            InlineAgentRef::Openrouter(b) => {
273                InlineAgentBase::Openrouter(b.clone())
274            }
275            InlineAgentRef::ClaudeAgentSdk(b) => {
276                InlineAgentBase::ClaudeAgentSdk(b.clone())
277            }
278            InlineAgentRef::CodexSdk(b) => InlineAgentBase::CodexSdk(b.clone()),
279            InlineAgentRef::Mock(b) => InlineAgentBase::Mock(b.clone()),
280        }
281    }
282
283    pub fn model(&self) -> &'a str {
284        match self {
285            InlineAgentRef::Openrouter(b) => &b.model,
286            InlineAgentRef::ClaudeAgentSdk(b) => &b.model,
287            InlineAgentRef::CodexSdk(b) => &b.model,
288            InlineAgentRef::Mock(_) => super::mock::AgentBase::model(),
289        }
290    }
291
292    pub fn upstream(&self) -> super::Upstream {
293        match self {
294            InlineAgentRef::Openrouter(_) => super::Upstream::Openrouter,
295            InlineAgentRef::ClaudeAgentSdk(_) => {
296                super::Upstream::ClaudeAgentSdk
297            }
298            InlineAgentRef::CodexSdk(_) => super::Upstream::CodexSdk,
299            InlineAgentRef::Mock(_) => super::Upstream::Mock,
300        }
301    }
302
303    pub fn output_mode(&self) -> super::OutputMode {
304        match self {
305            InlineAgentRef::Openrouter(b) => b.output_mode.into(),
306            InlineAgentRef::ClaudeAgentSdk(b) => b.output_mode.into(),
307            InlineAgentRef::CodexSdk(b) => b.output_mode.into(),
308            InlineAgentRef::Mock(b) => b.output_mode.into(),
309        }
310    }
311
312    pub fn mcp_servers(&self) -> Option<&'a super::McpServers> {
313        match self {
314            InlineAgentRef::Openrouter(b) => b.mcp_servers.as_ref(),
315            InlineAgentRef::ClaudeAgentSdk(b) => b.mcp_servers.as_ref(),
316            InlineAgentRef::CodexSdk(b) => b.mcp_servers.as_ref(),
317            InlineAgentRef::Mock(b) => b.mcp_servers.as_ref(),
318        }
319    }
320
321    pub fn client_objectiveai_mcp(
322        &self,
323    ) -> Option<&'a super::ClientObjectiveaiMcp> {
324        match self {
325            InlineAgentRef::Openrouter(b) => b.client_objectiveai_mcp.as_ref(),
326            InlineAgentRef::ClaudeAgentSdk(b) => {
327                b.client_objectiveai_mcp.as_ref()
328            }
329            InlineAgentRef::CodexSdk(b) => b.client_objectiveai_mcp.as_ref(),
330            InlineAgentRef::Mock(b) => b.client_objectiveai_mcp.as_ref(),
331        }
332    }
333
334    pub fn top_logprobs(&self) -> Option<u64> {
335        match self {
336            InlineAgentRef::Openrouter(b) => b.top_logprobs,
337            InlineAgentRef::ClaudeAgentSdk(_) => None,
338            InlineAgentRef::CodexSdk(_) => None,
339            InlineAgentRef::Mock(b) => b.top_logprobs,
340        }
341    }
342
343    pub fn merged_messages(
344        &self,
345        messages: Vec<super::completions::message::Message>,
346    ) -> Vec<super::completions::message::Message> {
347        match self {
348            InlineAgentRef::Openrouter(b) => b.merged_messages(messages),
349            InlineAgentRef::ClaudeAgentSdk(b) => b.merged_messages(messages),
350            InlineAgentRef::CodexSdk(b) => b.merged_messages(messages),
351            InlineAgentRef::Mock(b) => b.merged_messages(messages),
352        }
353    }
354}
355
356// ── Post-validation types (with computed ID) ───────────────────────
357
358/// A validated inline Agent with its computed content-addressed ID.
359///
360/// This is an untagged enum that dispatches to the per-upstream Agent.
361#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
362#[serde(untagged)]
363#[schemars(rename = "agent.InlineAgent")]
364pub enum InlineAgent {
365    #[schemars(title = "Openrouter")]
366    Openrouter(super::openrouter::Agent),
367    #[schemars(title = "ClaudeAgentSdk")]
368    ClaudeAgentSdk(super::claude_agent_sdk::Agent),
369    #[schemars(title = "CodexSdk")]
370    CodexSdk(super::codex_sdk::Agent),
371    #[schemars(title = "Mock")]
372    Mock(super::mock::Agent),
373}
374
375impl InlineAgent {
376    pub fn id(&self) -> &str {
377        match self {
378            InlineAgent::Openrouter(a) => &a.id,
379            InlineAgent::ClaudeAgentSdk(a) => &a.id,
380            InlineAgent::CodexSdk(a) => &a.id,
381            InlineAgent::Mock(a) => &a.id,
382        }
383    }
384
385    pub fn base(&self) -> InlineAgentRef<'_> {
386        match self {
387            InlineAgent::Openrouter(a) => InlineAgentRef::Openrouter(&a.base),
388            InlineAgent::ClaudeAgentSdk(a) => {
389                InlineAgentRef::ClaudeAgentSdk(&a.base)
390            }
391            InlineAgent::CodexSdk(a) => InlineAgentRef::CodexSdk(&a.base),
392            InlineAgent::Mock(a) => InlineAgentRef::Mock(&a.base),
393        }
394    }
395
396    pub fn into_base(self) -> InlineAgentBase {
397        match self {
398            InlineAgent::Openrouter(a) => InlineAgentBase::Openrouter(a.base),
399            InlineAgent::ClaudeAgentSdk(a) => {
400                InlineAgentBase::ClaudeAgentSdk(a.base)
401            }
402            InlineAgent::CodexSdk(a) => InlineAgentBase::CodexSdk(a.base),
403            InlineAgent::Mock(a) => InlineAgentBase::Mock(a.base),
404        }
405    }
406
407    pub fn top_logprobs(&self) -> Option<u64> {
408        self.base().top_logprobs()
409    }
410}
411
412/// A validated remote Agent with metadata and computed content-addressed ID.
413#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
414#[schemars(rename = "agent.RemoteAgent")]
415pub struct RemoteAgent {
416    pub description: String,
417    #[serde(flatten)]
418    #[schemars(schema_with = "crate::flatten_schema::<InlineAgent>")]
419    pub inner: InlineAgent,
420}
421
422impl RemoteAgent {
423    pub fn id(&self) -> &str {
424        self.inner.id()
425    }
426
427    pub fn base(&self) -> InlineAgentRef<'_> {
428        self.inner.base()
429    }
430
431    pub fn into_base(self) -> RemoteAgentBase {
432        RemoteAgentBase {
433            description: self.description,
434            inner: self.inner.into_base(),
435        }
436    }
437
438    pub fn top_logprobs(&self) -> Option<u64> {
439        self.inner.top_logprobs()
440    }
441}
442
443/// A validated Agent, either remote (with metadata) or inline.
444#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
445#[serde(untagged)]
446#[schemars(rename = "agent.Agent")]
447pub enum Agent {
448    #[schemars(title = "Remote")]
449    Remote(RemoteAgent),
450    #[schemars(title = "Inline")]
451    Inline(InlineAgent),
452}
453
454impl Agent {
455    pub fn id(&self) -> &str {
456        match self {
457            Agent::Remote(a) => a.inner.id(),
458            Agent::Inline(a) => a.id(),
459        }
460    }
461
462    pub fn base(&self) -> InlineAgentRef<'_> {
463        match self {
464            Agent::Remote(a) => a.inner.base(),
465            Agent::Inline(a) => a.base(),
466        }
467    }
468
469    pub fn into_base(self) -> AgentBase {
470        match self {
471            Agent::Remote(a) => AgentBase::Remote(RemoteAgentBase {
472                description: a.description,
473                inner: a.inner.into_base(),
474            }),
475            Agent::Inline(a) => AgentBase::Inline(a.into_base()),
476        }
477    }
478
479    pub fn top_logprobs(&self) -> Option<u64> {
480        self.base().top_logprobs()
481    }
482}
483
484// ── WithFallbacks types ────────────────────────────────────────────
485
486/// An [`InlineAgentBase`] with optional fallbacks (no description).
487#[derive(
488    Clone,
489    Debug,
490    PartialEq,
491    Serialize,
492    Deserialize,
493    JsonSchema,
494    arbitrary::Arbitrary,
495)]
496#[schemars(rename = "agent.InlineAgentBaseWithFallbacks")]
497pub struct InlineAgentBaseWithFallbacks {
498    /// The primary agent configuration.
499    #[serde(flatten)]
500    #[schemars(schema_with = "crate::flatten_schema::<InlineAgentBase>")]
501    pub inner: InlineAgentBase,
502    /// Fallback agents to try if the primary fails.
503    #[serde(skip_serializing_if = "Option::is_none")]
504    #[schemars(extend("omitempty" = true))]
505    pub fallbacks: Option<Vec<InlineAgentBase>>,
506}
507
508impl InlineAgentBaseWithFallbacks {
509    /// Validates and converts to an [`InlineAgentWithFallbacks`] with computed IDs.
510    pub fn convert(self) -> Result<InlineAgentWithFallbacks, String> {
511        let inner = self.inner.convert()?;
512        let fallbacks = match self.fallbacks {
513            Some(fallbacks) if !fallbacks.is_empty() => {
514                let mut converted = Vec::with_capacity(fallbacks.len());
515                for fallback in fallbacks {
516                    converted.push(fallback.convert()?);
517                }
518                Some(converted)
519            }
520            _ => None,
521        };
522        Ok(InlineAgentWithFallbacks { inner, fallbacks })
523    }
524}
525
526/// A validated [`InlineAgent`] with optional fallbacks (no description).
527#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
528#[schemars(rename = "agent.InlineAgentWithFallbacks")]
529pub struct InlineAgentWithFallbacks {
530    /// The primary agent configuration.
531    #[serde(flatten)]
532    #[schemars(schema_with = "crate::flatten_schema::<InlineAgent>")]
533    pub inner: InlineAgent,
534    /// Fallback agents to try if the primary fails.
535    #[serde(skip_serializing_if = "Option::is_none")]
536    #[schemars(extend("omitempty" = true))]
537    pub fallbacks: Option<Vec<InlineAgent>>,
538}
539
540impl InlineAgentWithFallbacks {
541    /// Returns the concatenated IDs of the primary agent and all fallbacks.
542    ///
543    /// Used by swarms to compute their content-addressed ID.
544    pub fn full_id(&self) -> String {
545        match &self.fallbacks {
546            Some(fallbacks) => {
547                let id = self.inner.id();
548                let mut full_id =
549                    String::with_capacity(id.len() + fallbacks.len() * 22);
550                full_id.push_str(id);
551                for fallback in fallbacks {
552                    full_id.push_str(fallback.id());
553                }
554                full_id
555            }
556            None => self.inner.id().to_owned(),
557        }
558    }
559
560    /// Returns an iterator over the IDs of the primary agent and all fallbacks.
561    pub fn ids(&self) -> impl Iterator<Item = &str> + Send {
562        std::iter::once(self.inner.id()).chain(
563            self.fallbacks.as_ref().into_iter().flat_map(|fallbacks| {
564                fallbacks.iter().map(|fallback| fallback.id())
565            }),
566        )
567    }
568}
569
570/// A remote agent base definition with description and optional fallbacks.
571#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
572#[schemars(rename = "agent.RemoteAgentBaseWithFallbacks")]
573pub struct RemoteAgentBaseWithFallbacks {
574    pub description: String,
575    #[serde(flatten)]
576    #[schemars(
577        schema_with = "crate::flatten_schema::<InlineAgentBaseWithFallbacks>"
578    )]
579    pub inner: InlineAgentBaseWithFallbacks,
580}
581
582impl RemoteAgentBaseWithFallbacks {
583    /// Validates and converts to a [`RemoteAgentWithFallbacks`].
584    pub fn convert(self) -> Result<RemoteAgentWithFallbacks, String> {
585        Ok(RemoteAgentWithFallbacks {
586            description: self.description,
587            inner: self.inner.convert()?,
588        })
589    }
590}
591
592/// A validated remote agent with description and optional fallbacks.
593#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
594#[schemars(rename = "agent.RemoteAgentWithFallbacks")]
595pub struct RemoteAgentWithFallbacks {
596    pub description: String,
597    #[serde(flatten)]
598    #[schemars(
599        schema_with = "crate::flatten_schema::<InlineAgentWithFallbacks>"
600    )]
601    pub inner: InlineAgentWithFallbacks,
602}
603
604impl RemoteAgentWithFallbacks {
605    /// Returns the concatenated IDs of the primary agent and all fallbacks.
606    pub fn full_id(&self) -> String {
607        self.inner.full_id()
608    }
609
610    /// Returns an iterator over the IDs of the primary agent and all fallbacks.
611    pub fn ids(&self) -> impl Iterator<Item = &str> + Send {
612        self.inner.ids()
613    }
614}
615
616/// A validated agent with optional fallbacks, either remote (with description) or inline.
617#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
618#[serde(untagged)]
619#[schemars(rename = "agent.AgentWithFallbacks")]
620pub enum AgentWithFallbacks {
621    #[schemars(title = "Remote")]
622    Remote(RemoteAgentWithFallbacks),
623    #[schemars(title = "Inline")]
624    Inline(InlineAgentWithFallbacks),
625}
626
627impl AgentWithFallbacks {
628    /// Returns the inner `InlineAgentWithFallbacks` regardless of variant.
629    pub fn inline(&self) -> &InlineAgentWithFallbacks {
630        match self {
631            AgentWithFallbacks::Remote(a) => &a.inner,
632            AgentWithFallbacks::Inline(a) => a,
633        }
634    }
635
636    /// Returns the primary agent.
637    pub fn agent(&self) -> &InlineAgent {
638        &self.inline().inner
639    }
640
641    /// Returns the fallback agents.
642    pub fn fallbacks(&self) -> Option<&Vec<InlineAgent>> {
643        self.inline().fallbacks.as_ref()
644    }
645
646    /// Returns the concatenated IDs of the primary agent and all fallbacks.
647    pub fn full_id(&self) -> String {
648        self.inline().full_id()
649    }
650
651    /// Returns an iterator over the IDs of the primary agent and all fallbacks.
652    pub fn ids(&self) -> impl Iterator<Item = &str> + Send {
653        self.inline().ids()
654    }
655
656    pub fn id(&self) -> &str {
657        self.agent().id()
658    }
659
660    pub fn base(&self) -> InlineAgentRef<'_> {
661        self.agent().base()
662    }
663
664    pub fn top_logprobs(&self) -> Option<u64> {
665        self.agent().top_logprobs()
666    }
667}
668
669// ── InlineAgentBaseWithFallbacksOrRemote ─────────────────────────────────
670
671/// An agent specification that is either an inline agent base with fallbacks
672/// or a remote path reference.
673///
674/// Used in swarm definitions to allow agents to be specified inline
675/// (with optional fallbacks) or resolved from a remote source via a
676/// hashmap during conversion.
677#[derive(
678    Clone,
679    Debug,
680    PartialEq,
681    Serialize,
682    Deserialize,
683    JsonSchema,
684    arbitrary::Arbitrary,
685)]
686#[serde(untagged)]
687#[schemars(rename = "agent.InlineAgentBaseWithFallbacksOrRemote")]
688pub enum InlineAgentBaseWithFallbacksOrRemote {
689    #[schemars(title = "AgentBase")]
690    AgentBase(InlineAgentBaseWithFallbacks),
691    #[schemars(title = "Remote")]
692    Remote(crate::RemotePath),
693}
694
695/// Like [`InlineAgentBaseWithFallbacksOrRemote`] but with optional commit.
696/// Used in request types where commit resolution happens server-side.
697#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
698#[serde(untagged)]
699#[schemars(rename = "agent.InlineAgentBaseWithFallbacksOrRemoteCommitOptional")]
700pub enum InlineAgentBaseWithFallbacksOrRemoteCommitOptional {
701    #[schemars(title = "AgentBase")]
702    AgentBase(InlineAgentBaseWithFallbacks),
703    #[schemars(title = "Remote")]
704    Remote(crate::RemotePathCommitOptional),
705}
706
707// ── WithCount types (for swarm agent slots) ────────────────────────
708
709fn default_count() -> u64 {
710    1
711}
712
713/// An [`InlineAgentBaseWithFallbacksOrRemote`] with a count
714/// (pre-validation swarm agent slot).
715#[derive(
716    Clone,
717    Debug,
718    PartialEq,
719    Serialize,
720    Deserialize,
721    JsonSchema,
722    arbitrary::Arbitrary,
723)]
724#[schemars(rename = "agent.InlineAgentBaseWithFallbacksOrRemoteWithCount")]
725pub struct InlineAgentBaseWithFallbacksOrRemoteWithCount {
726    /// Number of instances of this agent in the swarm. Defaults to 1.
727    #[serde(default = "default_count")]
728    #[arbitrary(with = crate::arbitrary_util::arbitrary_u64)]
729    pub count: u64,
730    /// The agent configuration.
731    #[serde(flatten)]
732    #[schemars(
733        schema_with = "crate::flatten_schema::<InlineAgentBaseWithFallbacksOrRemote>"
734    )]
735    pub inner: InlineAgentBaseWithFallbacksOrRemote,
736}
737
738/// An [`AgentWithFallbacks`] with a count (post-validation swarm agent slot).
739#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
740#[schemars(rename = "agent.AgentWithFallbacksWithCount")]
741pub struct AgentWithFallbacksWithCount {
742    /// Number of instances of this agent in the swarm. Defaults to 1.
743    #[serde(default = "default_count")]
744    pub count: u64,
745    /// The validated agent configuration.
746    #[serde(flatten)]
747    #[schemars(schema_with = "crate::flatten_schema::<AgentWithFallbacks>")]
748    pub inner: AgentWithFallbacks,
749}