1use chrono::{DateTime, Utc};
6use everruns_core::network_access::NetworkAccessList;
7use everruns_core::{
8 Agent, AgentCapabilityConfig, AgentId, AgentStatus, DEFAULT_ORG_PUBLIC_ID, Harness, HarnessId,
9 HarnessStatus, ModelId, PrincipalId, ScopedMcpServers, Session, SessionId, SessionStatus,
10 ToolDefinition,
11};
12use uuid::Uuid;
13
14#[derive(Debug, Clone)]
20pub struct HarnessBuilder {
21 id: HarnessId,
22 name: String,
23 display_name: Option<String>,
24 description: Option<String>,
25 system_prompt: String,
26 parent_harness_id: Option<HarnessId>,
27 default_model_id: Option<ModelId>,
28 tags: Vec<String>,
29 capabilities: Vec<AgentCapabilityConfig>,
30 initial_files: Vec<everruns_core::InitialFile>,
31 network_access: Option<NetworkAccessList>,
32 mcp_servers: ScopedMcpServers,
33 is_built_in: bool,
34 status: HarnessStatus,
35 created_at: Option<DateTime<Utc>>,
36 updated_at: Option<DateTime<Utc>>,
37}
38
39impl HarnessBuilder {
40 pub fn new(name: impl Into<String>, system_prompt: impl Into<String>) -> Self {
42 Self {
43 id: HarnessId::new(),
44 name: name.into(),
45 display_name: None,
46 description: None,
47 system_prompt: system_prompt.into(),
48 parent_harness_id: None,
49 default_model_id: None,
50 tags: Vec::new(),
51 capabilities: Vec::new(),
52 initial_files: Vec::new(),
53 network_access: None,
54 mcp_servers: ScopedMcpServers::default(),
55 is_built_in: false,
56 status: HarnessStatus::Active,
57 created_at: None,
58 updated_at: None,
59 }
60 }
61
62 pub fn id(mut self, id: HarnessId) -> Self {
64 self.id = id;
65 self
66 }
67
68 pub fn harness_id(&self) -> HarnessId {
70 self.id
71 }
72
73 pub fn name(mut self, name: impl Into<String>) -> Self {
74 self.name = name.into();
75 self
76 }
77
78 pub fn display_name(mut self, display_name: impl Into<String>) -> Self {
79 self.display_name = Some(display_name.into());
80 self
81 }
82
83 pub fn description(mut self, description: impl Into<String>) -> Self {
84 self.description = Some(description.into());
85 self
86 }
87
88 pub fn system_prompt(mut self, system_prompt: impl Into<String>) -> Self {
89 self.system_prompt = system_prompt.into();
90 self
91 }
92
93 pub fn parent_harness_id(mut self, parent_harness_id: HarnessId) -> Self {
94 self.parent_harness_id = Some(parent_harness_id);
95 self
96 }
97
98 pub fn default_model_id(mut self, default_model_id: ModelId) -> Self {
99 self.default_model_id = Some(default_model_id);
100 self
101 }
102
103 pub fn tag(mut self, tag: impl Into<String>) -> Self {
104 self.tags.push(tag.into());
105 self
106 }
107
108 pub fn tags<I, S>(mut self, tags: I) -> Self
109 where
110 I: IntoIterator<Item = S>,
111 S: Into<String>,
112 {
113 self.tags.extend(tags.into_iter().map(Into::into));
114 self
115 }
116
117 pub fn capability(mut self, capability: impl Into<AgentCapabilityConfig>) -> Self {
118 self.capabilities.push(capability.into());
119 self
120 }
121
122 pub fn with_capability(self, capability: impl Into<AgentCapabilityConfig>) -> Self {
123 self.capability(capability)
124 }
125
126 pub fn capabilities<I, C>(mut self, capabilities: I) -> Self
127 where
128 I: IntoIterator<Item = C>,
129 C: Into<AgentCapabilityConfig>,
130 {
131 self.capabilities
132 .extend(capabilities.into_iter().map(Into::into));
133 self
134 }
135
136 pub fn initial_file(mut self, file: everruns_core::InitialFile) -> Self {
137 self.initial_files.push(file);
138 self
139 }
140
141 pub fn network_access(mut self, network_access: NetworkAccessList) -> Self {
142 self.network_access = Some(network_access);
143 self
144 }
145
146 pub fn mcp_servers(mut self, mcp_servers: ScopedMcpServers) -> Self {
147 self.mcp_servers = mcp_servers;
148 self
149 }
150
151 pub fn is_built_in(mut self, is_built_in: bool) -> Self {
152 self.is_built_in = is_built_in;
153 self
154 }
155
156 pub fn status(mut self, status: HarnessStatus) -> Self {
157 self.status = status;
158 self
159 }
160
161 pub fn created_at(mut self, created_at: DateTime<Utc>) -> Self {
162 self.created_at = Some(created_at);
163 self
164 }
165
166 pub fn updated_at(mut self, updated_at: DateTime<Utc>) -> Self {
167 self.updated_at = Some(updated_at);
168 self
169 }
170
171 pub fn build(self) -> Harness {
173 let created_at = self.created_at.unwrap_or_else(Utc::now);
174 let updated_at = self.updated_at.unwrap_or(created_at);
175
176 Harness {
177 id: self.id,
178 name: self.name,
179 display_name: self.display_name,
180 description: self.description,
181 system_prompt: self.system_prompt,
182 parent_harness_id: self.parent_harness_id,
183 default_model_id: self.default_model_id,
184 tags: self.tags,
185 capabilities: self.capabilities,
186 initial_files: self.initial_files,
187 network_access: self.network_access,
188 mcp_servers: self.mcp_servers,
189 is_built_in: self.is_built_in,
190 status: self.status,
191 created_at,
192 updated_at,
193 archived_at: None,
194 deleted_at: None,
195 }
196 }
197}
198
199#[derive(Debug, Clone)]
201pub struct AgentBuilder {
202 id: AgentId,
203 name: String,
204 display_name: Option<String>,
205 description: Option<String>,
206 system_prompt: String,
207 default_model_id: Option<ModelId>,
208 tags: Vec<String>,
209 capabilities: Vec<AgentCapabilityConfig>,
210 initial_files: Vec<everruns_core::InitialFile>,
211 network_access: Option<NetworkAccessList>,
212 max_iterations: Option<usize>,
213 tools: Vec<ToolDefinition>,
214 mcp_servers: ScopedMcpServers,
215 status: AgentStatus,
216 created_at: Option<DateTime<Utc>>,
217 updated_at: Option<DateTime<Utc>>,
218}
219
220impl AgentBuilder {
221 pub fn new(name: impl Into<String>, system_prompt: impl Into<String>) -> Self {
223 Self {
224 id: AgentId::new(),
225 name: name.into(),
226 display_name: None,
227 description: None,
228 system_prompt: system_prompt.into(),
229 default_model_id: None,
230 tags: Vec::new(),
231 capabilities: Vec::new(),
232 initial_files: Vec::new(),
233 network_access: None,
234 max_iterations: None,
235 tools: Vec::new(),
236 mcp_servers: ScopedMcpServers::default(),
237 status: AgentStatus::Active,
238 created_at: None,
239 updated_at: None,
240 }
241 }
242
243 pub fn id(mut self, id: AgentId) -> Self {
245 self.id = id;
246 self
247 }
248
249 pub fn agent_id(&self) -> AgentId {
251 self.id
252 }
253
254 pub fn name(mut self, name: impl Into<String>) -> Self {
255 self.name = name.into();
256 self
257 }
258
259 pub fn display_name(mut self, display_name: impl Into<String>) -> Self {
260 self.display_name = Some(display_name.into());
261 self
262 }
263
264 pub fn description(mut self, description: impl Into<String>) -> Self {
265 self.description = Some(description.into());
266 self
267 }
268
269 pub fn system_prompt(mut self, system_prompt: impl Into<String>) -> Self {
270 self.system_prompt = system_prompt.into();
271 self
272 }
273
274 pub fn default_model_id(mut self, default_model_id: ModelId) -> Self {
275 self.default_model_id = Some(default_model_id);
276 self
277 }
278
279 pub fn tag(mut self, tag: impl Into<String>) -> Self {
280 self.tags.push(tag.into());
281 self
282 }
283
284 pub fn tags<I, S>(mut self, tags: I) -> Self
285 where
286 I: IntoIterator<Item = S>,
287 S: Into<String>,
288 {
289 self.tags.extend(tags.into_iter().map(Into::into));
290 self
291 }
292
293 pub fn capability(mut self, capability: impl Into<AgentCapabilityConfig>) -> Self {
294 self.capabilities.push(capability.into());
295 self
296 }
297
298 pub fn with_capability(self, capability: impl Into<AgentCapabilityConfig>) -> Self {
299 self.capability(capability)
300 }
301
302 pub fn capabilities<I, C>(mut self, capabilities: I) -> Self
303 where
304 I: IntoIterator<Item = C>,
305 C: Into<AgentCapabilityConfig>,
306 {
307 self.capabilities
308 .extend(capabilities.into_iter().map(Into::into));
309 self
310 }
311
312 pub fn initial_file(mut self, file: everruns_core::InitialFile) -> Self {
313 self.initial_files.push(file);
314 self
315 }
316
317 pub fn network_access(mut self, network_access: NetworkAccessList) -> Self {
318 self.network_access = Some(network_access);
319 self
320 }
321
322 pub fn max_iterations(mut self, max_iterations: usize) -> Self {
323 self.max_iterations = Some(max_iterations);
324 self
325 }
326
327 pub fn tool(mut self, tool: ToolDefinition) -> Self {
328 self.tools.push(tool);
329 self
330 }
331
332 pub fn tools<I>(mut self, tools: I) -> Self
333 where
334 I: IntoIterator<Item = ToolDefinition>,
335 {
336 self.tools.extend(tools);
337 self
338 }
339
340 pub fn mcp_servers(mut self, mcp_servers: ScopedMcpServers) -> Self {
341 self.mcp_servers = mcp_servers;
342 self
343 }
344
345 pub fn status(mut self, status: AgentStatus) -> Self {
346 self.status = status;
347 self
348 }
349
350 pub fn created_at(mut self, created_at: DateTime<Utc>) -> Self {
351 self.created_at = Some(created_at);
352 self
353 }
354
355 pub fn updated_at(mut self, updated_at: DateTime<Utc>) -> Self {
356 self.updated_at = Some(updated_at);
357 self
358 }
359
360 pub fn build(self) -> Agent {
362 let created_at = self.created_at.unwrap_or_else(Utc::now);
363 let updated_at = self.updated_at.unwrap_or(created_at);
364
365 Agent {
366 public_id: self.id,
367 internal_id: Uuid::nil(),
368 name: self.name,
369 display_name: self.display_name,
370 description: self.description,
371 system_prompt: self.system_prompt,
372 default_model_id: self.default_model_id,
373 default_version_id: None,
374 forked_from_agent_id: None,
375 forked_from_version_id: None,
376 root_agent_id: None,
377 tags: self.tags,
378 capabilities: self.capabilities,
379 initial_files: self.initial_files,
380 network_access: self.network_access,
381 max_iterations: self.max_iterations,
382 tools: self.tools,
383 mcp_servers: self.mcp_servers,
384 status: self.status,
385 created_at,
386 updated_at,
387 archived_at: None,
388 deleted_at: None,
389 usage: None,
390 }
391 }
392}
393
394#[derive(Debug, Clone)]
396pub struct SessionBuilder {
397 id: SessionId,
398 organization_id: String,
399 harness_id: HarnessId,
400 agent_id: Option<AgentId>,
401 owner_principal_id: PrincipalId,
402 title: Option<String>,
403 locale: Option<String>,
404 tags: Vec<String>,
405 model_id: Option<ModelId>,
406 capabilities: Vec<AgentCapabilityConfig>,
407 tools: Vec<ToolDefinition>,
408 mcp_servers: ScopedMcpServers,
409 system_prompt: Option<String>,
410 initial_files: Vec<everruns_core::InitialFile>,
411 network_access: Option<NetworkAccessList>,
412 max_iterations: Option<usize>,
413 status: SessionStatus,
414 created_at: Option<DateTime<Utc>>,
415 updated_at: Option<DateTime<Utc>>,
416}
417
418impl SessionBuilder {
419 pub fn new(harness_id: HarnessId) -> Self {
421 Self {
422 id: SessionId::new(),
423 organization_id: DEFAULT_ORG_PUBLIC_ID.to_string(),
424 harness_id,
425 agent_id: None,
426 owner_principal_id: PrincipalId::from_seed(1),
427 title: None,
428 locale: None,
429 tags: Vec::new(),
430 model_id: None,
431 capabilities: Vec::new(),
432 tools: Vec::new(),
433 mcp_servers: ScopedMcpServers::default(),
434 system_prompt: None,
435 initial_files: Vec::new(),
436 network_access: None,
437 max_iterations: None,
438 status: SessionStatus::Started,
439 created_at: None,
440 updated_at: None,
441 }
442 }
443
444 pub fn id(mut self, id: SessionId) -> Self {
446 self.id = id;
447 self
448 }
449
450 pub fn session_id(&self) -> SessionId {
452 self.id
453 }
454
455 pub fn organization_id(mut self, organization_id: impl Into<String>) -> Self {
456 self.organization_id = organization_id.into();
457 self
458 }
459
460 pub fn harness(mut self, harness_id: HarnessId) -> Self {
461 self.harness_id = harness_id;
462 self
463 }
464
465 pub fn agent(mut self, agent_id: AgentId) -> Self {
466 self.agent_id = Some(agent_id);
467 self
468 }
469
470 pub fn owner_principal_id(mut self, owner_principal_id: PrincipalId) -> Self {
471 self.owner_principal_id = owner_principal_id;
472 self
473 }
474
475 pub fn title(mut self, title: impl Into<String>) -> Self {
476 self.title = Some(title.into());
477 self
478 }
479
480 pub fn locale(mut self, locale: impl Into<String>) -> Self {
481 self.locale = Some(locale.into());
482 self
483 }
484
485 pub fn tag(mut self, tag: impl Into<String>) -> Self {
486 self.tags.push(tag.into());
487 self
488 }
489
490 pub fn tags<I, S>(mut self, tags: I) -> Self
491 where
492 I: IntoIterator<Item = S>,
493 S: Into<String>,
494 {
495 self.tags.extend(tags.into_iter().map(Into::into));
496 self
497 }
498
499 pub fn model_id(mut self, model_id: ModelId) -> Self {
500 self.model_id = Some(model_id);
501 self
502 }
503
504 pub fn capability(mut self, capability: impl Into<AgentCapabilityConfig>) -> Self {
505 self.capabilities.push(capability.into());
506 self
507 }
508
509 pub fn with_capability(self, capability: impl Into<AgentCapabilityConfig>) -> Self {
510 self.capability(capability)
511 }
512
513 pub fn capabilities<I, C>(mut self, capabilities: I) -> Self
514 where
515 I: IntoIterator<Item = C>,
516 C: Into<AgentCapabilityConfig>,
517 {
518 self.capabilities
519 .extend(capabilities.into_iter().map(Into::into));
520 self
521 }
522
523 pub fn tool(mut self, tool: ToolDefinition) -> Self {
524 self.tools.push(tool);
525 self
526 }
527
528 pub fn tools<I>(mut self, tools: I) -> Self
529 where
530 I: IntoIterator<Item = ToolDefinition>,
531 {
532 self.tools.extend(tools);
533 self
534 }
535
536 pub fn mcp_servers(mut self, mcp_servers: ScopedMcpServers) -> Self {
537 self.mcp_servers = mcp_servers;
538 self
539 }
540
541 pub fn system_prompt(mut self, system_prompt: impl Into<String>) -> Self {
542 self.system_prompt = Some(system_prompt.into());
543 self
544 }
545
546 pub fn initial_file(mut self, file: everruns_core::InitialFile) -> Self {
547 self.initial_files.push(file);
548 self
549 }
550
551 pub fn network_access(mut self, network_access: NetworkAccessList) -> Self {
552 self.network_access = Some(network_access);
553 self
554 }
555
556 pub fn max_iterations(mut self, max_iterations: usize) -> Self {
557 self.max_iterations = Some(max_iterations);
558 self
559 }
560
561 pub fn status(mut self, status: SessionStatus) -> Self {
562 self.status = status;
563 self
564 }
565
566 pub fn created_at(mut self, created_at: DateTime<Utc>) -> Self {
567 self.created_at = Some(created_at);
568 self
569 }
570
571 pub fn updated_at(mut self, updated_at: DateTime<Utc>) -> Self {
572 self.updated_at = Some(updated_at);
573 self
574 }
575
576 pub fn build(self) -> Session {
578 let created_at = self.created_at.unwrap_or_else(Utc::now);
579 let updated_at = self.updated_at.unwrap_or(created_at);
580
581 Session {
582 id: self.id,
583 organization_id: self.organization_id,
584 harness_id: self.harness_id,
585 agent_id: self.agent_id,
586 agent_version_id: None,
587 agent_identity_id: None,
588 owner_principal_id: self.owner_principal_id,
589 resolved_owner_user_id: None,
590 owner: None,
591 effective_owner: None,
592 title: self.title,
593 locale: self.locale,
594 preview: None,
595 output_preview: None,
596 tags: self.tags,
597 model_id: self.model_id,
598 capabilities: self.capabilities,
599 tools: self.tools,
600 mcp_servers: self.mcp_servers,
601 system_prompt: self.system_prompt,
602 initial_files: self.initial_files,
603 hints: None,
604 network_access: self.network_access,
605 max_iterations: self.max_iterations,
606 status: self.status,
607 created_at,
608 updated_at,
609 started_at: None,
610 finished_at: None,
611 usage: None,
612 is_pinned: None,
613 active_schedule_count: None,
614 features: Vec::new(),
615 parent_session_id: None,
616 subagent_name: None,
617 subagent_task: None,
618 subagent_status: None,
619 blueprint_id: None,
620 blueprint_config: None,
621 }
622 }
623}
624
625#[derive(Debug, Clone)]
630pub struct SingleSessionBuilder {
631 harness: HarnessBuilder,
632 agent: AgentBuilder,
633 session: SessionBuilder,
634}
635
636impl Default for SingleSessionBuilder {
637 fn default() -> Self {
638 let harness = HarnessBuilder::new("embedded-harness", "");
639 let agent = AgentBuilder::new("embedded-agent", "");
640 let session = SessionBuilder::new(harness.harness_id()).agent(agent.agent_id());
641 Self {
642 harness,
643 agent,
644 session,
645 }
646 }
647}
648
649impl SingleSessionBuilder {
650 pub fn harness(mut self, name: impl Into<String>, system_prompt: impl Into<String>) -> Self {
654 let harness_id = self.harness.harness_id();
655 self.harness = self.harness.name(name).system_prompt(system_prompt);
656 self.session = self.session.harness(harness_id);
657 self
658 }
659
660 pub fn agent(mut self, name: impl Into<String>, system_prompt: impl Into<String>) -> Self {
664 let agent_id = self.agent.agent_id();
665 self.agent = self.agent.name(name).system_prompt(system_prompt);
666 self.session = self.session.agent(agent_id);
667 self
668 }
669
670 pub fn with_capability(self, capability: impl Into<AgentCapabilityConfig>) -> Self {
672 self.harness_capability(capability)
673 }
674
675 pub fn harness_capability(mut self, capability: impl Into<AgentCapabilityConfig>) -> Self {
677 self.harness = self.harness.capability(capability);
678 self
679 }
680
681 pub fn agent_capability(mut self, capability: impl Into<AgentCapabilityConfig>) -> Self {
683 self.agent = self.agent.capability(capability);
684 self
685 }
686
687 pub fn session_capability(mut self, capability: impl Into<AgentCapabilityConfig>) -> Self {
689 self.session = self.session.capability(capability);
690 self
691 }
692
693 pub fn session_mcp_servers(mut self, mcp_servers: ScopedMcpServers) -> Self {
696 self.session = self.session.mcp_servers(mcp_servers);
697 self
698 }
699
700 pub fn harness_display_name(mut self, display_name: impl Into<String>) -> Self {
701 self.harness = self.harness.display_name(display_name);
702 self
703 }
704
705 pub fn agent_display_name(mut self, display_name: impl Into<String>) -> Self {
706 self.agent = self.agent.display_name(display_name);
707 self
708 }
709
710 pub fn harness_description(mut self, description: impl Into<String>) -> Self {
711 self.harness = self.harness.description(description);
712 self
713 }
714
715 pub fn agent_description(mut self, description: impl Into<String>) -> Self {
716 self.agent = self.agent.description(description);
717 self
718 }
719
720 pub fn session_title(mut self, title: impl Into<String>) -> Self {
721 self.session = self.session.title(title);
722 self
723 }
724
725 pub fn locale(mut self, locale: impl Into<String>) -> Self {
726 self.session = self.session.locale(locale);
727 self
728 }
729
730 pub fn tag(mut self, tag: impl Into<String>) -> Self {
731 let tag = tag.into();
732 self.harness = self.harness.tag(tag.clone());
733 self.agent = self.agent.tag(tag.clone());
734 self.session = self.session.tag(tag);
735 self
736 }
737
738 pub fn session_model_id(mut self, model_id: ModelId) -> Self {
739 self.session = self.session.model_id(model_id);
740 self
741 }
742
743 pub fn harness_default_model_id(mut self, model_id: ModelId) -> Self {
744 self.harness = self.harness.default_model_id(model_id);
745 self
746 }
747
748 pub fn agent_default_model_id(mut self, model_id: ModelId) -> Self {
749 self.agent = self.agent.default_model_id(model_id);
750 self
751 }
752
753 pub fn agent_max_iterations(mut self, max_iterations: usize) -> Self {
754 self.agent = self.agent.max_iterations(max_iterations);
755 self
756 }
757
758 pub fn session_max_iterations(mut self, max_iterations: usize) -> Self {
759 self.session = self.session.max_iterations(max_iterations);
760 self
761 }
762
763 pub fn agent_tool(mut self, tool: ToolDefinition) -> Self {
764 self.agent = self.agent.tool(tool);
765 self
766 }
767
768 pub fn session_tool(mut self, tool: ToolDefinition) -> Self {
769 self.session = self.session.tool(tool);
770 self
771 }
772
773 pub fn harness_initial_file(mut self, file: everruns_core::InitialFile) -> Self {
774 self.harness = self.harness.initial_file(file);
775 self
776 }
777
778 pub fn agent_initial_file(mut self, file: everruns_core::InitialFile) -> Self {
779 self.agent = self.agent.initial_file(file);
780 self
781 }
782
783 pub fn session_initial_file(mut self, file: everruns_core::InitialFile) -> Self {
784 self.session = self.session.initial_file(file);
785 self
786 }
787
788 pub fn harness_network_access(mut self, network_access: NetworkAccessList) -> Self {
789 self.harness = self.harness.network_access(network_access);
790 self
791 }
792
793 pub fn agent_network_access(mut self, network_access: NetworkAccessList) -> Self {
794 self.agent = self.agent.network_access(network_access);
795 self
796 }
797
798 pub fn session_network_access(mut self, network_access: NetworkAccessList) -> Self {
799 self.session = self.session.network_access(network_access);
800 self
801 }
802
803 pub fn harness_id(&self) -> HarnessId {
804 self.harness.harness_id()
805 }
806
807 pub fn agent_id(&self) -> AgentId {
808 self.agent.agent_id()
809 }
810
811 pub fn session_id(mut self, id: SessionId) -> Self {
818 self.session = self.session.id(id);
819 self
820 }
821
822 pub(crate) fn build(self) -> (Harness, Agent, Session, SessionId) {
823 let session_id = self.session.session_id();
824 (
825 self.harness.build(),
826 self.agent.build(),
827 self.session.build(),
828 session_id,
829 )
830 }
831}