1use crate::DurationMs;
11use serde::{Deserialize, Serialize};
12use std::fmt;
13use std::str::FromStr;
14
15#[derive(Debug, Clone, PartialEq, Eq)]
25pub struct EnumParseError {
26 pub enum_name: &'static str,
28 pub input: String,
30}
31
32impl fmt::Display for EnumParseError {
33 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34 write!(f, "Unknown {} value: '{}'", self.enum_name, self.input)
35 }
36}
37
38impl std::error::Error for EnumParseError {}
39
40#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
47#[serde(rename_all = "snake_case")]
48#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
49pub enum TTL {
50 Persistent,
52 Session,
54 Scope,
56 Duration(DurationMs),
58 Ephemeral,
60 ShortTerm,
62 MediumTerm,
64 LongTerm,
66 Permanent,
68 Max(usize),
70}
71
72#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
74#[serde(rename_all = "snake_case")]
75#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
76pub enum EntityType {
77 Trajectory,
78 Scope,
79 Artifact,
80 Note,
81 Turn,
82 Tenant,
83 AgentWorkingSet,
84 Link,
85 Belief,
86 Goal,
87 Plan,
88 Lock,
89 Message,
90 Agent,
91 Delegation,
92 Handoff,
93 Config,
94 Conflict,
95 Edge,
96 EvolutionSnapshot,
97 SummarizationPolicy,
98 SummarizationRequest,
99 ToolExecution,
100 Event,
102}
103
104#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
106#[serde(rename_all = "snake_case")]
107#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
108pub enum MemoryCategory {
109 Ephemeral,
110 Working,
111 Episodic,
112 Semantic,
113 Procedural,
114 Meta,
115}
116
117#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
119#[serde(rename_all = "snake_case")]
120#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
121pub enum PrincipalType {
122 User,
123 Agent,
124 System,
125}
126
127impl PrincipalType {
128 pub fn as_db_str(&self) -> &'static str {
130 match self {
131 PrincipalType::User => "user",
132 PrincipalType::Agent => "agent",
133 PrincipalType::System => "system",
134 }
135 }
136}
137
138impl fmt::Display for PrincipalType {
139 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
140 f.write_str(self.as_db_str())
141 }
142}
143
144#[derive(Debug, Clone, PartialEq, Eq, Hash)]
147#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
148pub enum AgentType {
149 Tester,
150 Monitor,
151 Planner,
152 Executor,
153 Reviewer,
154 Custom(String),
155}
156
157impl AgentType {
158 pub fn as_str(&self) -> &str {
159 match self {
160 AgentType::Tester => "tester",
161 AgentType::Monitor => "monitor",
162 AgentType::Planner => "planner",
163 AgentType::Executor => "executor",
164 AgentType::Reviewer => "reviewer",
165 AgentType::Custom(s) => s.as_str(),
166 }
167 }
168}
169
170impl Serialize for AgentType {
171 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
172 where
173 S: serde::Serializer,
174 {
175 serializer.serialize_str(self.as_str())
176 }
177}
178
179impl<'de> Deserialize<'de> for AgentType {
180 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
181 where
182 D: serde::Deserializer<'de>,
183 {
184 let s = String::deserialize(deserializer)?;
185 Ok(match s.to_lowercase().as_str() {
186 "tester" => AgentType::Tester,
187 "monitor" => AgentType::Monitor,
188 "planner" => AgentType::Planner,
189 "executor" => AgentType::Executor,
190 "reviewer" => AgentType::Reviewer,
191 _ => AgentType::Custom(s),
192 })
193 }
194}
195
196impl fmt::Display for AgentType {
197 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
198 f.write_str(self.as_str())
199 }
200}
201
202impl FromStr for AgentType {
203 type Err = std::convert::Infallible;
204
205 fn from_str(s: &str) -> Result<Self, Self::Err> {
206 Ok(match s.to_lowercase().as_str() {
207 "tester" => AgentType::Tester,
208 "monitor" => AgentType::Monitor,
209 "planner" => AgentType::Planner,
210 "executor" => AgentType::Executor,
211 "reviewer" => AgentType::Reviewer,
212 _ => AgentType::Custom(s.to_string()),
213 })
214 }
215}
216
217impl From<&str> for AgentType {
218 fn from(s: &str) -> Self {
219 s.parse().unwrap()
220 }
221}
222
223#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
225#[serde(rename_all = "snake_case")]
226#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
227pub enum MemoryType {
228 Artifact,
229 Note,
230 Turn,
231 WorkingSet,
232 #[serde(rename = "*")]
234 All,
235}
236
237impl MemoryType {
238 pub fn as_db_str(&self) -> &'static str {
239 match self {
240 MemoryType::Artifact => "artifact",
241 MemoryType::Note => "note",
242 MemoryType::Turn => "turn",
243 MemoryType::WorkingSet => "working_set",
244 MemoryType::All => "*",
245 }
246 }
247}
248
249#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
251#[serde(rename_all = "snake_case")]
252#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
253pub enum ResourceType {
254 Trajectory,
255 Scope,
256 Artifact,
257 Note,
258 Agent,
259}
260
261impl ResourceType {
262 pub fn as_db_str(&self) -> &'static str {
263 match self {
264 ResourceType::Trajectory => "trajectory",
265 ResourceType::Scope => "scope",
266 ResourceType::Artifact => "artifact",
267 ResourceType::Note => "note",
268 ResourceType::Agent => "agent",
269 }
270 }
271}
272
273impl FromStr for ResourceType {
274 type Err = String;
275
276 fn from_str(s: &str) -> Result<Self, Self::Err> {
277 match normalize_token(s).as_str() {
278 "trajectory" => Ok(ResourceType::Trajectory),
279 "scope" => Ok(ResourceType::Scope),
280 "artifact" => Ok(ResourceType::Artifact),
281 "note" => Ok(ResourceType::Note),
282 "agent" => Ok(ResourceType::Agent),
283 _ => Err(format!("Invalid ResourceType: {}", s)),
284 }
285 }
286}
287
288#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
291#[serde(rename_all = "snake_case")]
292#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
293pub enum FieldType {
294 Uuid,
296 Text,
298 Int,
300 Float,
302 Bool,
304 Timestamp,
306 Json,
308 Embedding { dimensions: Option<usize> },
310 Enum { variants: Vec<String> },
312 Array(Box<FieldType>),
314}
315
316#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
318#[serde(rename_all = "snake_case")]
319#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
320pub enum TrajectoryStatus {
321 Active,
322 Completed,
323 Failed,
324 Suspended,
325}
326
327#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
329#[serde(rename_all = "snake_case")]
330#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
331pub enum OutcomeStatus {
332 Success,
333 Partial,
334 Failure,
335}
336
337#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
339#[serde(rename_all = "snake_case")]
340#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
341pub enum AgentStatus {
342 #[default]
344 Idle,
345 Active,
347 Blocked,
349 Failed,
351 Offline,
353}
354
355impl AgentStatus {
356 pub fn as_db_str(&self) -> &'static str {
358 match self {
359 AgentStatus::Idle => "idle",
360 AgentStatus::Active => "active",
361 AgentStatus::Blocked => "blocked",
362 AgentStatus::Failed => "failed",
363 AgentStatus::Offline => "offline",
364 }
365 }
366
367 pub fn from_db_str(s: &str) -> Result<Self, EnumParseError> {
369 match s.to_lowercase().as_str() {
370 "idle" => Ok(AgentStatus::Idle),
371 "active" => Ok(AgentStatus::Active),
372 "blocked" => Ok(AgentStatus::Blocked),
373 "failed" => Ok(AgentStatus::Failed),
374 "offline" => Ok(AgentStatus::Offline),
375 _ => Err(EnumParseError {
376 enum_name: "AgentStatus",
377 input: s.to_string(),
378 }),
379 }
380 }
381
382 pub fn can_accept_work(&self) -> bool {
384 matches!(self, AgentStatus::Idle)
385 }
386}
387
388impl fmt::Display for AgentStatus {
389 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
390 write!(f, "{}", self.as_db_str())
391 }
392}
393
394impl FromStr for AgentStatus {
395 type Err = EnumParseError;
396
397 fn from_str(s: &str) -> Result<Self, Self::Err> {
398 Self::from_db_str(s)
399 }
400}
401
402#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
404#[serde(rename_all = "snake_case")]
405#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
406pub enum SummarizationRequestStatus {
407 Pending,
408 InProgress,
409 Completed,
410 Failed,
411}
412
413impl SummarizationRequestStatus {
414 pub fn as_db_str(&self) -> &'static str {
415 match self {
416 SummarizationRequestStatus::Pending => "pending",
417 SummarizationRequestStatus::InProgress => "in_progress",
418 SummarizationRequestStatus::Completed => "completed",
419 SummarizationRequestStatus::Failed => "failed",
420 }
421 }
422
423 pub fn from_db_str(s: &str) -> Result<Self, EnumParseError> {
424 match s.to_lowercase().as_str() {
425 "pending" => Ok(SummarizationRequestStatus::Pending),
426 "inprogress" | "in_progress" | "in-progress" => {
427 Ok(SummarizationRequestStatus::InProgress)
428 }
429 "completed" | "complete" => Ok(SummarizationRequestStatus::Completed),
430 "failed" | "failure" => Ok(SummarizationRequestStatus::Failed),
431 _ => Err(EnumParseError {
432 enum_name: "SummarizationRequestStatus",
433 input: s.to_string(),
434 }),
435 }
436 }
437}
438
439impl fmt::Display for SummarizationRequestStatus {
440 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
441 write!(f, "{}", self.as_db_str())
442 }
443}
444
445impl FromStr for SummarizationRequestStatus {
446 type Err = EnumParseError;
447
448 fn from_str(s: &str) -> Result<Self, Self::Err> {
449 Self::from_db_str(s)
450 }
451}
452
453#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
455#[serde(rename_all = "snake_case")]
456#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
457pub enum ToolExecutionStatus {
458 Started,
459 Succeeded,
460 Failed,
461}
462
463impl ToolExecutionStatus {
464 pub fn as_db_str(&self) -> &'static str {
465 match self {
466 ToolExecutionStatus::Started => "started",
467 ToolExecutionStatus::Succeeded => "succeeded",
468 ToolExecutionStatus::Failed => "failed",
469 }
470 }
471
472 pub fn from_db_str(s: &str) -> Result<Self, EnumParseError> {
473 match s.to_lowercase().as_str() {
474 "started" | "start" => Ok(ToolExecutionStatus::Started),
475 "succeeded" | "success" => Ok(ToolExecutionStatus::Succeeded),
476 "failed" | "failure" => Ok(ToolExecutionStatus::Failed),
477 _ => Err(EnumParseError {
478 enum_name: "ToolExecutionStatus",
479 input: s.to_string(),
480 }),
481 }
482 }
483}
484
485impl fmt::Display for ToolExecutionStatus {
486 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
487 write!(f, "{}", self.as_db_str())
488 }
489}
490
491impl FromStr for ToolExecutionStatus {
492 type Err = EnumParseError;
493
494 fn from_str(s: &str) -> Result<Self, Self::Err> {
495 Self::from_db_str(s)
496 }
497}
498
499#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
501#[serde(rename_all = "snake_case")]
502#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
503pub enum TurnRole {
504 User,
505 Assistant,
506 System,
507 Tool,
508}
509
510#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
512#[serde(rename_all = "snake_case")]
513#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
514pub enum ArtifactType {
515 ErrorLog,
516 CodePatch,
517 DesignDecision,
518 UserPreference,
519 Fact,
520 Constraint,
521 ToolResult,
522 IntermediateOutput,
523 Custom,
524 Code,
525 Document,
526 Data,
527 Model,
528 Config,
529 Log,
530 Summary,
531 Decision,
532 Plan,
533 Audio,
535 Image,
536 Video,
537 Transcript,
538 Screenshot,
539}
540
541#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
543#[serde(rename_all = "snake_case")]
544#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
545pub enum ExtractionMethod {
546 Explicit,
548 Inferred,
550 UserProvided,
552 LlmExtraction,
554 ToolExtraction,
556 MemoryRecall,
558 ExternalApi,
560 #[default]
562 Unknown,
563}
564
565#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
567#[serde(rename_all = "snake_case")]
568#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
569pub enum NoteType {
570 Convention,
571 Strategy,
572 Gotcha,
573 Fact,
574 Preference,
575 Relationship,
576 Procedure,
577 Meta,
578 Insight,
579 Correction,
580 Summary,
581}
582
583#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
589#[serde(rename_all = "snake_case")]
590#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
591pub enum ProviderType {
592 #[serde(rename = "openai")]
593 OpenAI,
594 Anthropic,
595 OpenRouter,
596 Local,
597 Custom,
598}
599
600impl ProviderType {
601 pub fn as_db_str(&self) -> &'static str {
603 match self {
604 ProviderType::OpenAI => "openai",
605 ProviderType::Anthropic => "anthropic",
606 ProviderType::OpenRouter => "openrouter",
607 ProviderType::Local => "local",
608 ProviderType::Custom => "custom",
609 }
610 }
611
612 pub fn from_db_str(s: &str) -> Result<Self, EnumParseError> {
614 match s.to_lowercase().as_str() {
615 "openai" => Ok(ProviderType::OpenAI),
616 "anthropic" => Ok(ProviderType::Anthropic),
617 "openrouter" => Ok(ProviderType::OpenRouter),
618 "local" => Ok(ProviderType::Local),
619 "custom" => Ok(ProviderType::Custom),
620 _ => Err(EnumParseError {
621 enum_name: "ProviderType",
622 input: s.to_string(),
623 }),
624 }
625 }
626}
627
628impl fmt::Display for ProviderType {
629 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
630 write!(f, "{}", self.as_db_str())
631 }
632}
633
634impl FromStr for ProviderType {
635 type Err = EnumParseError;
636
637 fn from_str(s: &str) -> Result<Self, Self::Err> {
638 Self::from_db_str(s)
639 }
640}
641
642#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
644#[serde(rename_all = "snake_case")]
645#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
646pub enum EdgeType {
647 Supports,
648 Contradicts,
649 Supersedes,
650 DerivedFrom,
651 RelatesTo,
652 Temporal,
653 Causal,
654 SynthesizedFrom,
655 Grouped,
656 Compared,
657}
658
659#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
661#[serde(rename_all = "snake_case")]
662#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
663pub enum AbstractionLevel {
664 #[default]
665 Raw,
666 Summary,
667 Principle,
668}
669
670#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
672#[serde(rename_all = "snake_case")]
673#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
674pub enum EvolutionPhase {
675 #[default]
676 Online,
677 Frozen,
678 Evolving,
679}
680
681#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
683#[serde(rename_all = "snake_case")]
684#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
685pub enum SummarizationTrigger {
686 DosageThreshold { percent: u8 },
687 ScopeClose,
688 TurnCount { count: i32 },
689 ArtifactCount { count: i32 },
690 Manual,
691}
692
693fn normalize_token(input: &str) -> String {
698 input
699 .chars()
700 .filter(|c| *c != '_')
701 .map(|c| c.to_ascii_lowercase())
702 .collect()
703}
704
705impl EntityType {
706 pub fn as_db_str(&self) -> &'static str {
708 match self {
709 EntityType::Trajectory => "trajectory",
710 EntityType::Scope => "scope",
711 EntityType::Artifact => "artifact",
712 EntityType::Note => "note",
713 EntityType::Turn => "turn",
714 EntityType::Tenant => "tenant",
715 EntityType::AgentWorkingSet => "agent_working_set",
716 EntityType::Link => "link",
717 EntityType::Belief => "belief",
718 EntityType::Goal => "goal",
719 EntityType::Plan => "plan",
720 EntityType::Lock => "lock",
721 EntityType::Message => "message",
722 EntityType::Agent => "agent",
723 EntityType::Delegation => "delegation",
724 EntityType::Handoff => "handoff",
725 EntityType::Config => "config",
726 EntityType::Conflict => "conflict",
727 EntityType::Edge => "edge",
728 EntityType::EvolutionSnapshot => "evolution_snapshot",
729 EntityType::SummarizationPolicy => "summarization_policy",
730 EntityType::SummarizationRequest => "summarization_request",
731 EntityType::ToolExecution => "tool_execution",
732 EntityType::Event => "event",
733 }
734 }
735}
736
737impl fmt::Display for EntityType {
738 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
739 let value = match self {
740 EntityType::Trajectory => "Trajectory",
741 EntityType::Scope => "Scope",
742 EntityType::Artifact => "Artifact",
743 EntityType::Note => "Note",
744 EntityType::Turn => "Turn",
745 EntityType::Tenant => "Tenant",
746 EntityType::AgentWorkingSet => "AgentWorkingSet",
747 EntityType::Link => "Link",
748 EntityType::Belief => "Belief",
749 EntityType::Goal => "Goal",
750 EntityType::Plan => "Plan",
751 EntityType::Lock => "Lock",
752 EntityType::Message => "Message",
753 EntityType::Agent => "Agent",
754 EntityType::Delegation => "Delegation",
755 EntityType::Handoff => "Handoff",
756 EntityType::Config => "Config",
757 EntityType::Conflict => "Conflict",
758 EntityType::Edge => "Edge",
759 EntityType::EvolutionSnapshot => "EvolutionSnapshot",
760 EntityType::SummarizationPolicy => "SummarizationPolicy",
761 EntityType::SummarizationRequest => "SummarizationRequest",
762 EntityType::ToolExecution => "ToolExecution",
763 EntityType::Event => "Event",
764 };
765 write!(f, "{}", value)
766 }
767}
768
769impl FromStr for EntityType {
770 type Err = String;
771
772 fn from_str(s: &str) -> Result<Self, Self::Err> {
773 let normalized = normalize_token(s);
774 match normalized.as_str() {
775 "trajectory" => Ok(EntityType::Trajectory),
776 "scope" => Ok(EntityType::Scope),
777 "artifact" => Ok(EntityType::Artifact),
778 "note" => Ok(EntityType::Note),
779 "turn" => Ok(EntityType::Turn),
780 "tenant" => Ok(EntityType::Tenant),
781 "agentworkingset" => Ok(EntityType::AgentWorkingSet),
782 "link" => Ok(EntityType::Link),
783 "belief" => Ok(EntityType::Belief),
784 "goal" => Ok(EntityType::Goal),
785 "plan" => Ok(EntityType::Plan),
786 "lock" => Ok(EntityType::Lock),
787 "message" => Ok(EntityType::Message),
788 "agent" => Ok(EntityType::Agent),
789 "delegation" => Ok(EntityType::Delegation),
790 "handoff" => Ok(EntityType::Handoff),
791 "config" => Ok(EntityType::Config),
792 "conflict" => Ok(EntityType::Conflict),
793 "edge" => Ok(EntityType::Edge),
794 "evolutionsnapshot" => Ok(EntityType::EvolutionSnapshot),
795 "summarizationpolicy" => Ok(EntityType::SummarizationPolicy),
796 "summarizationrequest" => Ok(EntityType::SummarizationRequest),
797 "toolexecution" => Ok(EntityType::ToolExecution),
798 "event" => Ok(EntityType::Event),
799 _ => Err(format!("Invalid EntityType: {}", s)),
800 }
801 }
802}
803
804impl fmt::Display for TrajectoryStatus {
805 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
806 let value = match self {
807 TrajectoryStatus::Active => "active",
808 TrajectoryStatus::Completed => "completed",
809 TrajectoryStatus::Failed => "failed",
810 TrajectoryStatus::Suspended => "suspended",
811 };
812 write!(f, "{}", value)
813 }
814}
815
816impl FromStr for TrajectoryStatus {
817 type Err = String;
818
819 fn from_str(s: &str) -> Result<Self, Self::Err> {
820 match normalize_token(s).as_str() {
821 "active" => Ok(TrajectoryStatus::Active),
822 "completed" | "complete" => Ok(TrajectoryStatus::Completed),
823 "failed" | "failure" => Ok(TrajectoryStatus::Failed),
824 "suspended" => Ok(TrajectoryStatus::Suspended),
825 _ => Err(format!("Invalid TrajectoryStatus: {}", s)),
826 }
827 }
828}
829
830impl fmt::Display for OutcomeStatus {
831 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
832 let value = match self {
833 OutcomeStatus::Success => "Success",
834 OutcomeStatus::Partial => "Partial",
835 OutcomeStatus::Failure => "Failure",
836 };
837 write!(f, "{}", value)
838 }
839}
840
841impl FromStr for OutcomeStatus {
842 type Err = String;
843
844 fn from_str(s: &str) -> Result<Self, Self::Err> {
845 match normalize_token(s).as_str() {
846 "success" => Ok(OutcomeStatus::Success),
847 "partial" => Ok(OutcomeStatus::Partial),
848 "failure" | "failed" => Ok(OutcomeStatus::Failure),
849 _ => Err(format!("Invalid OutcomeStatus: {}", s)),
850 }
851 }
852}
853
854impl fmt::Display for TurnRole {
855 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
856 let value = match self {
857 TurnRole::User => "user",
858 TurnRole::Assistant => "assistant",
859 TurnRole::System => "system",
860 TurnRole::Tool => "tool",
861 };
862 write!(f, "{}", value)
863 }
864}
865
866impl FromStr for TurnRole {
867 type Err = String;
868
869 fn from_str(s: &str) -> Result<Self, Self::Err> {
870 match normalize_token(s).as_str() {
871 "user" => Ok(TurnRole::User),
872 "assistant" => Ok(TurnRole::Assistant),
873 "system" => Ok(TurnRole::System),
874 "tool" => Ok(TurnRole::Tool),
875 _ => Err(format!("Invalid TurnRole: {}", s)),
876 }
877 }
878}
879
880impl fmt::Display for ArtifactType {
881 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
882 let value = match self {
883 ArtifactType::ErrorLog => "ErrorLog",
884 ArtifactType::CodePatch => "CodePatch",
885 ArtifactType::DesignDecision => "DesignDecision",
886 ArtifactType::UserPreference => "UserPreference",
887 ArtifactType::Fact => "Fact",
888 ArtifactType::Constraint => "Constraint",
889 ArtifactType::ToolResult => "ToolResult",
890 ArtifactType::IntermediateOutput => "IntermediateOutput",
891 ArtifactType::Custom => "Custom",
892 ArtifactType::Code => "Code",
893 ArtifactType::Document => "Document",
894 ArtifactType::Data => "Data",
895 ArtifactType::Model => "Model",
896 ArtifactType::Config => "Config",
897 ArtifactType::Log => "Log",
898 ArtifactType::Summary => "Summary",
899 ArtifactType::Decision => "Decision",
900 ArtifactType::Plan => "Plan",
901 ArtifactType::Audio => "Audio",
902 ArtifactType::Image => "Image",
903 ArtifactType::Video => "Video",
904 ArtifactType::Transcript => "Transcript",
905 ArtifactType::Screenshot => "Screenshot",
906 };
907 write!(f, "{}", value)
908 }
909}
910
911impl FromStr for ArtifactType {
912 type Err = String;
913
914 fn from_str(s: &str) -> Result<Self, Self::Err> {
915 match normalize_token(s).as_str() {
916 "errorlog" => Ok(ArtifactType::ErrorLog),
917 "codepatch" => Ok(ArtifactType::CodePatch),
918 "designdecision" => Ok(ArtifactType::DesignDecision),
919 "userpreference" => Ok(ArtifactType::UserPreference),
920 "fact" => Ok(ArtifactType::Fact),
921 "constraint" => Ok(ArtifactType::Constraint),
922 "toolresult" => Ok(ArtifactType::ToolResult),
923 "intermediateoutput" => Ok(ArtifactType::IntermediateOutput),
924 "custom" => Ok(ArtifactType::Custom),
925 "code" => Ok(ArtifactType::Code),
926 "document" => Ok(ArtifactType::Document),
927 "data" => Ok(ArtifactType::Data),
928 "model" => Ok(ArtifactType::Model),
929 "config" => Ok(ArtifactType::Config),
930 "log" => Ok(ArtifactType::Log),
931 "summary" => Ok(ArtifactType::Summary),
932 "decision" => Ok(ArtifactType::Decision),
933 "plan" => Ok(ArtifactType::Plan),
934 "audio" => Ok(ArtifactType::Audio),
935 "image" => Ok(ArtifactType::Image),
936 "video" => Ok(ArtifactType::Video),
937 "transcript" => Ok(ArtifactType::Transcript),
938 "screenshot" => Ok(ArtifactType::Screenshot),
939 _ => Err(format!("Invalid ArtifactType: {}", s)),
940 }
941 }
942}
943
944impl fmt::Display for ExtractionMethod {
945 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
946 let value = match self {
947 ExtractionMethod::Explicit => "explicit",
948 ExtractionMethod::Inferred => "inferred",
949 ExtractionMethod::UserProvided => "user_provided",
950 ExtractionMethod::LlmExtraction => "llm_extraction",
951 ExtractionMethod::ToolExtraction => "tool_extraction",
952 ExtractionMethod::MemoryRecall => "memory_recall",
953 ExtractionMethod::ExternalApi => "external_api",
954 ExtractionMethod::Unknown => "unknown",
955 };
956 write!(f, "{}", value)
957 }
958}
959
960impl FromStr for ExtractionMethod {
961 type Err = String;
962
963 fn from_str(s: &str) -> Result<Self, Self::Err> {
964 match normalize_token(s).as_str() {
965 "explicit" => Ok(ExtractionMethod::Explicit),
966 "inferred" => Ok(ExtractionMethod::Inferred),
967 "userprovided" => Ok(ExtractionMethod::UserProvided),
968 "llmextraction" => Ok(ExtractionMethod::LlmExtraction),
969 "toolextraction" => Ok(ExtractionMethod::ToolExtraction),
970 "memoryrecall" => Ok(ExtractionMethod::MemoryRecall),
971 "externalapi" => Ok(ExtractionMethod::ExternalApi),
972 "unknown" => Ok(ExtractionMethod::Unknown),
973 _ => Err(format!("Invalid ExtractionMethod: {}", s)),
974 }
975 }
976}
977
978impl fmt::Display for NoteType {
979 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
980 let value = match self {
981 NoteType::Convention => "Convention",
982 NoteType::Strategy => "Strategy",
983 NoteType::Gotcha => "Gotcha",
984 NoteType::Fact => "Fact",
985 NoteType::Preference => "Preference",
986 NoteType::Relationship => "Relationship",
987 NoteType::Procedure => "Procedure",
988 NoteType::Meta => "Meta",
989 NoteType::Insight => "Insight",
990 NoteType::Correction => "Correction",
991 NoteType::Summary => "Summary",
992 };
993 write!(f, "{}", value)
994 }
995}
996
997impl FromStr for NoteType {
998 type Err = String;
999
1000 fn from_str(s: &str) -> Result<Self, Self::Err> {
1001 match normalize_token(s).as_str() {
1002 "convention" => Ok(NoteType::Convention),
1003 "strategy" => Ok(NoteType::Strategy),
1004 "gotcha" => Ok(NoteType::Gotcha),
1005 "fact" => Ok(NoteType::Fact),
1006 "preference" => Ok(NoteType::Preference),
1007 "relationship" => Ok(NoteType::Relationship),
1008 "procedure" => Ok(NoteType::Procedure),
1009 "meta" => Ok(NoteType::Meta),
1010 "insight" => Ok(NoteType::Insight),
1011 "correction" => Ok(NoteType::Correction),
1012 "summary" => Ok(NoteType::Summary),
1013 _ => Err(format!("Invalid NoteType: {}", s)),
1014 }
1015 }
1016}
1017
1018impl fmt::Display for EdgeType {
1019 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1020 let value = match self {
1021 EdgeType::Supports => "supports",
1022 EdgeType::Contradicts => "contradicts",
1023 EdgeType::Supersedes => "supersedes",
1024 EdgeType::DerivedFrom => "derived_from",
1025 EdgeType::RelatesTo => "relates_to",
1026 EdgeType::Temporal => "temporal",
1027 EdgeType::Causal => "causal",
1028 EdgeType::SynthesizedFrom => "synthesized_from",
1029 EdgeType::Grouped => "grouped",
1030 EdgeType::Compared => "compared",
1031 };
1032 write!(f, "{}", value)
1033 }
1034}
1035
1036impl FromStr for EdgeType {
1037 type Err = String;
1038
1039 fn from_str(s: &str) -> Result<Self, Self::Err> {
1040 match normalize_token(s).as_str() {
1041 "supports" => Ok(EdgeType::Supports),
1042 "contradicts" => Ok(EdgeType::Contradicts),
1043 "supersedes" => Ok(EdgeType::Supersedes),
1044 "derivedfrom" => Ok(EdgeType::DerivedFrom),
1045 "relatesto" => Ok(EdgeType::RelatesTo),
1046 "temporal" => Ok(EdgeType::Temporal),
1047 "causal" => Ok(EdgeType::Causal),
1048 "synthesizedfrom" => Ok(EdgeType::SynthesizedFrom),
1049 "grouped" => Ok(EdgeType::Grouped),
1050 "compared" => Ok(EdgeType::Compared),
1051 _ => Err(format!("Invalid EdgeType: {}", s)),
1052 }
1053 }
1054}
1055
1056impl fmt::Display for AbstractionLevel {
1057 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1058 let value = match self {
1059 AbstractionLevel::Raw => "Raw",
1060 AbstractionLevel::Summary => "Summary",
1061 AbstractionLevel::Principle => "Principle",
1062 };
1063 write!(f, "{}", value)
1064 }
1065}
1066
1067impl FromStr for AbstractionLevel {
1068 type Err = String;
1069
1070 fn from_str(s: &str) -> Result<Self, Self::Err> {
1071 match normalize_token(s).as_str() {
1072 "raw" | "l0" => Ok(AbstractionLevel::Raw),
1073 "summary" | "l1" => Ok(AbstractionLevel::Summary),
1074 "principle" | "l2" => Ok(AbstractionLevel::Principle),
1075 _ => Err(format!("Invalid AbstractionLevel: {}", s)),
1076 }
1077 }
1078}
1079
1080impl fmt::Display for EvolutionPhase {
1081 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1082 let value = match self {
1083 EvolutionPhase::Online => "Online",
1084 EvolutionPhase::Frozen => "Frozen",
1085 EvolutionPhase::Evolving => "Evolving",
1086 };
1087 write!(f, "{}", value)
1088 }
1089}
1090
1091impl FromStr for EvolutionPhase {
1092 type Err = String;
1093
1094 fn from_str(s: &str) -> Result<Self, Self::Err> {
1095 match normalize_token(s).as_str() {
1096 "online" => Ok(EvolutionPhase::Online),
1097 "frozen" | "freeze" => Ok(EvolutionPhase::Frozen),
1098 "evolving" | "evolve" => Ok(EvolutionPhase::Evolving),
1099 _ => Err(format!("Invalid EvolutionPhase: {}", s)),
1100 }
1101 }
1102}
1103
1104impl fmt::Display for SummarizationTrigger {
1105 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1106 match self {
1107 SummarizationTrigger::DosageThreshold { percent } => {
1108 write!(f, "DosageThreshold({}%)", percent)
1109 }
1110 SummarizationTrigger::ScopeClose => write!(f, "ScopeClose"),
1111 SummarizationTrigger::TurnCount { count } => write!(f, "TurnCount({})", count),
1112 SummarizationTrigger::ArtifactCount { count } => write!(f, "ArtifactCount({})", count),
1113 SummarizationTrigger::Manual => write!(f, "Manual"),
1114 }
1115 }
1116}
1117
1118#[cfg(test)]
1123mod tests {
1124 use super::*;
1125
1126 #[test]
1131 fn test_ttl_persistent_serde_roundtrip() {
1132 let original = TTL::Persistent;
1133 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1134 let restored: TTL =
1135 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1136 assert_eq!(original, restored);
1137 }
1138
1139 #[test]
1140 fn test_ttl_session_serde_roundtrip() {
1141 let original = TTL::Session;
1142 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1143 let restored: TTL =
1144 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1145 assert_eq!(original, restored);
1146 }
1147
1148 #[test]
1149 fn test_ttl_scope_serde_roundtrip() {
1150 let original = TTL::Scope;
1151 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1152 let restored: TTL =
1153 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1154 assert_eq!(original, restored);
1155 }
1156
1157 #[test]
1158 fn test_ttl_duration_serde_roundtrip() {
1159 let original = TTL::Duration(DurationMs::new(3600000));
1160 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1161 let restored: TTL =
1162 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1163 assert_eq!(original, restored);
1164 }
1165
1166 #[test]
1167 fn test_ttl_ephemeral_serde_roundtrip() {
1168 let original = TTL::Ephemeral;
1169 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1170 let restored: TTL =
1171 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1172 assert_eq!(original, restored);
1173 }
1174
1175 #[test]
1176 fn test_ttl_max_serde_roundtrip() {
1177 let original = TTL::Max(1000);
1178 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1179 let restored: TTL =
1180 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1181 assert_eq!(original, restored);
1182 }
1183
1184 #[test]
1185 fn test_ttl_short_term_serde_roundtrip() {
1186 let original = TTL::ShortTerm;
1187 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1188 let restored: TTL =
1189 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1190 assert_eq!(original, restored);
1191 }
1192
1193 #[test]
1194 fn test_ttl_medium_term_serde_roundtrip() {
1195 let original = TTL::MediumTerm;
1196 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1197 let restored: TTL =
1198 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1199 assert_eq!(original, restored);
1200 }
1201
1202 #[test]
1203 fn test_ttl_long_term_serde_roundtrip() {
1204 let original = TTL::LongTerm;
1205 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1206 let restored: TTL =
1207 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1208 assert_eq!(original, restored);
1209 }
1210
1211 #[test]
1212 fn test_ttl_permanent_serde_roundtrip() {
1213 let original = TTL::Permanent;
1214 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1215 let restored: TTL =
1216 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1217 assert_eq!(original, restored);
1218 }
1219
1220 #[test]
1225 fn test_entity_type_all_variants_serde_roundtrip() {
1226 let variants = [
1227 EntityType::Trajectory,
1228 EntityType::Scope,
1229 EntityType::Artifact,
1230 EntityType::Note,
1231 EntityType::Turn,
1232 EntityType::Tenant,
1233 EntityType::AgentWorkingSet,
1234 EntityType::Link,
1235 EntityType::Belief,
1236 EntityType::Goal,
1237 EntityType::Plan,
1238 EntityType::Lock,
1239 EntityType::Message,
1240 EntityType::Agent,
1241 EntityType::Delegation,
1242 EntityType::Handoff,
1243 EntityType::Config,
1244 EntityType::Conflict,
1245 EntityType::Edge,
1246 EntityType::EvolutionSnapshot,
1247 EntityType::SummarizationPolicy,
1248 EntityType::SummarizationRequest,
1249 EntityType::ToolExecution,
1250 EntityType::Event,
1251 ];
1252
1253 for original in variants {
1254 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1255 let restored: EntityType =
1256 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1257 assert_eq!(original, restored, "Failed for {:?}", original);
1258 }
1259 }
1260
1261 #[test]
1266 fn test_trajectory_status_all_variants_serde_roundtrip() {
1267 let variants = [
1268 TrajectoryStatus::Active,
1269 TrajectoryStatus::Completed,
1270 TrajectoryStatus::Failed,
1271 TrajectoryStatus::Suspended,
1272 ];
1273
1274 for original in variants {
1275 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1276 let restored: TrajectoryStatus =
1277 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1278 assert_eq!(original, restored);
1279 }
1280 }
1281
1282 #[test]
1287 fn test_agent_status_all_variants_serde_roundtrip() {
1288 let variants = [
1289 AgentStatus::Idle,
1290 AgentStatus::Active,
1291 AgentStatus::Blocked,
1292 AgentStatus::Failed,
1293 AgentStatus::Offline,
1294 ];
1295
1296 for original in variants {
1297 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1298 let restored: AgentStatus =
1299 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1300 assert_eq!(original, restored);
1301 }
1302 }
1303
1304 #[test]
1309 fn test_artifact_type_all_variants_serde_roundtrip() {
1310 let variants = [
1311 ArtifactType::ErrorLog,
1312 ArtifactType::CodePatch,
1313 ArtifactType::DesignDecision,
1314 ArtifactType::UserPreference,
1315 ArtifactType::Fact,
1316 ArtifactType::Constraint,
1317 ArtifactType::ToolResult,
1318 ArtifactType::IntermediateOutput,
1319 ArtifactType::Custom,
1320 ArtifactType::Code,
1321 ArtifactType::Document,
1322 ArtifactType::Data,
1323 ArtifactType::Model,
1324 ArtifactType::Config,
1325 ArtifactType::Log,
1326 ArtifactType::Summary,
1327 ArtifactType::Decision,
1328 ArtifactType::Plan,
1329 ];
1330
1331 for original in variants {
1332 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1333 let restored: ArtifactType =
1334 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1335 assert_eq!(original, restored);
1336 }
1337 }
1338
1339 #[test]
1344 fn test_extraction_method_all_variants_serde_roundtrip() {
1345 let variants = [
1346 ExtractionMethod::Explicit,
1347 ExtractionMethod::Inferred,
1348 ExtractionMethod::UserProvided,
1349 ExtractionMethod::LlmExtraction,
1350 ExtractionMethod::ToolExtraction,
1351 ExtractionMethod::MemoryRecall,
1352 ExtractionMethod::ExternalApi,
1353 ExtractionMethod::Unknown,
1354 ];
1355
1356 for original in variants {
1357 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1358 let restored: ExtractionMethod =
1359 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1360 assert_eq!(original, restored);
1361 }
1362 }
1363
1364 #[test]
1369 fn test_note_type_all_variants_serde_roundtrip() {
1370 let variants = [
1371 NoteType::Convention,
1372 NoteType::Strategy,
1373 NoteType::Gotcha,
1374 NoteType::Fact,
1375 NoteType::Preference,
1376 NoteType::Relationship,
1377 NoteType::Procedure,
1378 NoteType::Meta,
1379 NoteType::Insight,
1380 NoteType::Correction,
1381 NoteType::Summary,
1382 ];
1383
1384 for original in variants {
1385 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1386 let restored: NoteType =
1387 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1388 assert_eq!(original, restored);
1389 }
1390 }
1391
1392 #[test]
1397 fn test_edge_type_all_variants_serde_roundtrip() {
1398 let variants = [
1399 EdgeType::Supports,
1400 EdgeType::Contradicts,
1401 EdgeType::Supersedes,
1402 EdgeType::DerivedFrom,
1403 EdgeType::RelatesTo,
1404 EdgeType::Temporal,
1405 EdgeType::Causal,
1406 EdgeType::SynthesizedFrom,
1407 EdgeType::Grouped,
1408 EdgeType::Compared,
1409 ];
1410
1411 for original in variants {
1412 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1413 let restored: EdgeType =
1414 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1415 assert_eq!(original, restored);
1416 }
1417 }
1418
1419 #[test]
1424 fn test_abstraction_level_all_variants_serde_roundtrip() {
1425 let variants = [
1426 AbstractionLevel::Raw,
1427 AbstractionLevel::Summary,
1428 AbstractionLevel::Principle,
1429 ];
1430
1431 for original in variants {
1432 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1433 let restored: AbstractionLevel =
1434 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1435 assert_eq!(original, restored);
1436 }
1437 }
1438
1439 #[test]
1444 fn test_evolution_phase_all_variants_serde_roundtrip() {
1445 let variants = [
1446 EvolutionPhase::Online,
1447 EvolutionPhase::Frozen,
1448 EvolutionPhase::Evolving,
1449 ];
1450
1451 for original in variants {
1452 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1453 let restored: EvolutionPhase =
1454 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1455 assert_eq!(original, restored);
1456 }
1457 }
1458
1459 #[test]
1464 fn test_summarization_trigger_all_variants_serde_roundtrip() {
1465 let variants = [
1466 SummarizationTrigger::DosageThreshold { percent: 80 },
1467 SummarizationTrigger::ScopeClose,
1468 SummarizationTrigger::TurnCount { count: 10 },
1469 SummarizationTrigger::ArtifactCount { count: 5 },
1470 SummarizationTrigger::Manual,
1471 ];
1472
1473 for original in variants {
1474 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1475 let restored: SummarizationTrigger =
1476 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1477 assert_eq!(original, restored);
1478 }
1479 }
1480
1481 #[test]
1486 fn test_memory_category_all_variants_serde_roundtrip() {
1487 let variants = [
1488 MemoryCategory::Ephemeral,
1489 MemoryCategory::Working,
1490 MemoryCategory::Episodic,
1491 MemoryCategory::Semantic,
1492 MemoryCategory::Procedural,
1493 MemoryCategory::Meta,
1494 ];
1495
1496 for original in variants {
1497 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1498 let restored: MemoryCategory =
1499 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1500 assert_eq!(original, restored);
1501 }
1502 }
1503
1504 #[test]
1509 fn test_turn_role_all_variants_serde_roundtrip() {
1510 let variants = [
1511 TurnRole::User,
1512 TurnRole::Assistant,
1513 TurnRole::System,
1514 TurnRole::Tool,
1515 ];
1516
1517 for original in variants {
1518 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1519 let restored: TurnRole =
1520 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1521 assert_eq!(original, restored);
1522 }
1523 }
1524
1525 #[test]
1530 fn test_outcome_status_all_variants_serde_roundtrip() {
1531 let variants = [
1532 OutcomeStatus::Success,
1533 OutcomeStatus::Partial,
1534 OutcomeStatus::Failure,
1535 ];
1536
1537 for original in variants {
1538 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1539 let restored: OutcomeStatus =
1540 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1541 assert_eq!(original, restored);
1542 }
1543 }
1544
1545 #[test]
1550 fn test_field_type_simple_variants_serde_roundtrip() {
1551 let variants = [
1552 FieldType::Uuid,
1553 FieldType::Text,
1554 FieldType::Int,
1555 FieldType::Float,
1556 FieldType::Bool,
1557 FieldType::Timestamp,
1558 FieldType::Json,
1559 ];
1560
1561 for original in variants {
1562 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1563 let restored: FieldType =
1564 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1565 assert_eq!(original, restored);
1566 }
1567 }
1568
1569 #[test]
1570 fn test_field_type_embedding_serde_roundtrip() {
1571 let original = FieldType::Embedding {
1572 dimensions: Some(1536),
1573 };
1574 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1575 let restored: FieldType =
1576 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1577 assert_eq!(original, restored);
1578 }
1579
1580 #[test]
1581 fn test_field_type_enum_serde_roundtrip() {
1582 let original = FieldType::Enum {
1583 variants: vec!["A".to_string(), "B".to_string(), "C".to_string()],
1584 };
1585 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1586 let restored: FieldType =
1587 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1588 assert_eq!(original, restored);
1589 }
1590
1591 #[test]
1592 fn test_field_type_array_serde_roundtrip() {
1593 let original = FieldType::Array(Box::new(FieldType::Text));
1594 let json = serde_json::to_string(&original).expect("JSON serialization should succeed");
1595 let restored: FieldType =
1596 serde_json::from_str(&json).expect("JSON deserialization should succeed");
1597 assert_eq!(original, restored);
1598 }
1599
1600 #[test]
1605 fn test_entity_type_display_fromstr_roundtrip() {
1606 let variants = [
1607 EntityType::Trajectory,
1608 EntityType::Scope,
1609 EntityType::Artifact,
1610 EntityType::Note,
1611 EntityType::Turn,
1612 EntityType::Tenant,
1613 EntityType::AgentWorkingSet,
1614 EntityType::Link,
1615 EntityType::Belief,
1616 EntityType::Goal,
1617 EntityType::Plan,
1618 EntityType::Lock,
1619 EntityType::Message,
1620 EntityType::Agent,
1621 EntityType::Delegation,
1622 EntityType::Handoff,
1623 EntityType::Config,
1624 EntityType::Conflict,
1625 EntityType::Edge,
1626 EntityType::EvolutionSnapshot,
1627 EntityType::SummarizationPolicy,
1628 EntityType::SummarizationRequest,
1629 EntityType::ToolExecution,
1630 EntityType::Event,
1631 ];
1632
1633 for original in variants {
1634 let string = original.to_string();
1635 let restored: EntityType = string.parse().expect("EntityType roundtrip should succeed");
1636 assert_eq!(original, restored);
1637 }
1638 }
1639
1640 #[test]
1641 fn test_trajectory_status_display_fromstr_roundtrip() {
1642 let variants = [
1643 TrajectoryStatus::Active,
1644 TrajectoryStatus::Completed,
1645 TrajectoryStatus::Failed,
1646 TrajectoryStatus::Suspended,
1647 ];
1648
1649 for original in variants {
1650 let string = original.to_string();
1651 let restored: TrajectoryStatus = string
1652 .parse()
1653 .expect("TrajectoryStatus roundtrip should succeed");
1654 assert_eq!(original, restored);
1655 }
1656 }
1657
1658 #[test]
1659 fn test_agent_status_display_fromstr_roundtrip() {
1660 let variants = [
1661 AgentStatus::Idle,
1662 AgentStatus::Active,
1663 AgentStatus::Blocked,
1664 AgentStatus::Failed,
1665 AgentStatus::Offline,
1666 ];
1667
1668 for original in variants {
1669 let string = original.to_string();
1670 let restored: AgentStatus = string
1671 .parse()
1672 .expect("AgentStatus roundtrip should succeed");
1673 assert_eq!(original, restored);
1674 }
1675 }
1676
1677 #[test]
1678 fn test_artifact_type_display_fromstr_roundtrip() {
1679 let variants = [
1680 ArtifactType::ErrorLog,
1681 ArtifactType::CodePatch,
1682 ArtifactType::DesignDecision,
1683 ArtifactType::UserPreference,
1684 ArtifactType::Fact,
1685 ArtifactType::Constraint,
1686 ArtifactType::ToolResult,
1687 ArtifactType::IntermediateOutput,
1688 ArtifactType::Custom,
1689 ArtifactType::Code,
1690 ArtifactType::Document,
1691 ArtifactType::Data,
1692 ArtifactType::Model,
1693 ArtifactType::Config,
1694 ArtifactType::Log,
1695 ArtifactType::Summary,
1696 ArtifactType::Decision,
1697 ArtifactType::Plan,
1698 ];
1699
1700 for original in variants {
1701 let string = original.to_string();
1702 let restored: ArtifactType = string
1703 .parse()
1704 .expect("ArtifactType roundtrip should succeed");
1705 assert_eq!(original, restored);
1706 }
1707 }
1708
1709 #[test]
1710 fn test_extraction_method_display_fromstr_roundtrip() {
1711 let variants = [
1712 ExtractionMethod::Explicit,
1713 ExtractionMethod::Inferred,
1714 ExtractionMethod::UserProvided,
1715 ExtractionMethod::LlmExtraction,
1716 ExtractionMethod::ToolExtraction,
1717 ExtractionMethod::MemoryRecall,
1718 ExtractionMethod::ExternalApi,
1719 ExtractionMethod::Unknown,
1720 ];
1721
1722 for original in variants {
1723 let string = original.to_string();
1724 let restored: ExtractionMethod = string
1725 .parse()
1726 .expect("ExtractionMethod roundtrip should succeed");
1727 assert_eq!(original, restored);
1728 }
1729 }
1730
1731 #[test]
1732 fn test_note_type_display_fromstr_roundtrip() {
1733 let variants = [
1734 NoteType::Convention,
1735 NoteType::Strategy,
1736 NoteType::Gotcha,
1737 NoteType::Fact,
1738 NoteType::Preference,
1739 NoteType::Relationship,
1740 NoteType::Procedure,
1741 NoteType::Meta,
1742 NoteType::Insight,
1743 NoteType::Correction,
1744 NoteType::Summary,
1745 ];
1746
1747 for original in variants {
1748 let string = original.to_string();
1749 let restored: NoteType = string.parse().expect("NoteType roundtrip should succeed");
1750 assert_eq!(original, restored);
1751 }
1752 }
1753
1754 #[test]
1755 fn test_edge_type_display_fromstr_roundtrip() {
1756 let variants = [
1757 EdgeType::Supports,
1758 EdgeType::Contradicts,
1759 EdgeType::Supersedes,
1760 EdgeType::DerivedFrom,
1761 EdgeType::RelatesTo,
1762 EdgeType::Temporal,
1763 EdgeType::Causal,
1764 EdgeType::SynthesizedFrom,
1765 EdgeType::Grouped,
1766 EdgeType::Compared,
1767 ];
1768
1769 for original in variants {
1770 let string = original.to_string();
1771 let restored: EdgeType = string.parse().expect("EdgeType roundtrip should succeed");
1772 assert_eq!(original, restored);
1773 }
1774 }
1775
1776 #[test]
1777 fn test_abstraction_level_display_fromstr_roundtrip() {
1778 let variants = [
1779 AbstractionLevel::Raw,
1780 AbstractionLevel::Summary,
1781 AbstractionLevel::Principle,
1782 ];
1783
1784 for original in variants {
1785 let string = original.to_string();
1786 let restored: AbstractionLevel = string
1787 .parse()
1788 .expect("AbstractionLevel roundtrip should succeed");
1789 assert_eq!(original, restored);
1790 }
1791 }
1792
1793 #[test]
1794 fn test_evolution_phase_display_fromstr_roundtrip() {
1795 let variants = [
1796 EvolutionPhase::Online,
1797 EvolutionPhase::Frozen,
1798 EvolutionPhase::Evolving,
1799 ];
1800
1801 for original in variants {
1802 let string = original.to_string();
1803 let restored: EvolutionPhase = string
1804 .parse()
1805 .expect("EvolutionPhase roundtrip should succeed");
1806 assert_eq!(original, restored);
1807 }
1808 }
1809
1810 #[test]
1811 fn test_turn_role_display_fromstr_roundtrip() {
1812 let variants = [
1813 TurnRole::User,
1814 TurnRole::Assistant,
1815 TurnRole::System,
1816 TurnRole::Tool,
1817 ];
1818
1819 for original in variants {
1820 let string = original.to_string();
1821 let restored: TurnRole = string.parse().expect("TurnRole roundtrip should succeed");
1822 assert_eq!(original, restored);
1823 }
1824 }
1825
1826 #[test]
1827 fn test_outcome_status_display_fromstr_roundtrip() {
1828 let variants = [
1829 OutcomeStatus::Success,
1830 OutcomeStatus::Partial,
1831 OutcomeStatus::Failure,
1832 ];
1833
1834 for original in variants {
1835 let string = original.to_string();
1836 let restored: OutcomeStatus = string
1837 .parse()
1838 .expect("OutcomeStatus roundtrip should succeed");
1839 assert_eq!(original, restored);
1840 }
1841 }
1842
1843 #[test]
1848 fn test_abstraction_level_aliases() {
1849 assert_eq!(
1851 "raw"
1852 .parse::<AbstractionLevel>()
1853 .expect("parsing 'raw' should succeed"),
1854 AbstractionLevel::Raw
1855 );
1856 assert_eq!(
1857 "l0".parse::<AbstractionLevel>()
1858 .expect("parsing 'l0' should succeed"),
1859 AbstractionLevel::Raw
1860 );
1861
1862 assert_eq!(
1864 "summary"
1865 .parse::<AbstractionLevel>()
1866 .expect("parsing 'summary' should succeed"),
1867 AbstractionLevel::Summary
1868 );
1869 assert_eq!(
1870 "l1".parse::<AbstractionLevel>()
1871 .expect("parsing 'l1' should succeed"),
1872 AbstractionLevel::Summary
1873 );
1874
1875 assert_eq!(
1877 "principle"
1878 .parse::<AbstractionLevel>()
1879 .expect("parsing 'principle' should succeed"),
1880 AbstractionLevel::Principle
1881 );
1882 assert_eq!(
1883 "l2".parse::<AbstractionLevel>()
1884 .expect("parsing 'l2' should succeed"),
1885 AbstractionLevel::Principle
1886 );
1887 }
1888
1889 #[test]
1890 fn test_trajectory_status_aliases() {
1891 assert_eq!(
1892 "completed"
1893 .parse::<TrajectoryStatus>()
1894 .expect("parsing 'completed' should succeed"),
1895 TrajectoryStatus::Completed
1896 );
1897 assert_eq!(
1898 "complete"
1899 .parse::<TrajectoryStatus>()
1900 .expect("parsing 'complete' should succeed"),
1901 TrajectoryStatus::Completed
1902 );
1903 assert_eq!(
1904 "failed"
1905 .parse::<TrajectoryStatus>()
1906 .expect("parsing 'failed' should succeed"),
1907 TrajectoryStatus::Failed
1908 );
1909 assert_eq!(
1910 "failure"
1911 .parse::<TrajectoryStatus>()
1912 .expect("parsing 'failure' should succeed"),
1913 TrajectoryStatus::Failed
1914 );
1915 }
1916
1917 #[test]
1918 fn test_evolution_phase_aliases() {
1919 assert_eq!(
1920 "frozen"
1921 .parse::<EvolutionPhase>()
1922 .expect("parsing 'frozen' should succeed"),
1923 EvolutionPhase::Frozen
1924 );
1925 assert_eq!(
1926 "freeze"
1927 .parse::<EvolutionPhase>()
1928 .expect("parsing 'freeze' should succeed"),
1929 EvolutionPhase::Frozen
1930 );
1931 assert_eq!(
1932 "evolving"
1933 .parse::<EvolutionPhase>()
1934 .expect("parsing 'evolving' should succeed"),
1935 EvolutionPhase::Evolving
1936 );
1937 assert_eq!(
1938 "evolve"
1939 .parse::<EvolutionPhase>()
1940 .expect("parsing 'evolve' should succeed"),
1941 EvolutionPhase::Evolving
1942 );
1943 }
1944
1945 #[test]
1950 fn test_agent_status_default() {
1951 assert_eq!(AgentStatus::default(), AgentStatus::Idle);
1952 }
1953
1954 #[test]
1955 fn test_extraction_method_default() {
1956 assert_eq!(ExtractionMethod::default(), ExtractionMethod::Unknown);
1957 }
1958
1959 #[test]
1960 fn test_abstraction_level_default() {
1961 assert_eq!(AbstractionLevel::default(), AbstractionLevel::Raw);
1962 }
1963
1964 #[test]
1965 fn test_evolution_phase_default() {
1966 assert_eq!(EvolutionPhase::default(), EvolutionPhase::Online);
1967 }
1968
1969 #[test]
1974 fn test_agent_status_can_accept_work() {
1975 assert!(AgentStatus::Idle.can_accept_work());
1976 assert!(!AgentStatus::Active.can_accept_work());
1977 assert!(!AgentStatus::Blocked.can_accept_work());
1978 assert!(!AgentStatus::Failed.can_accept_work());
1979 assert!(!AgentStatus::Offline.can_accept_work());
1980 }
1981
1982 #[test]
1983 fn test_agent_status_as_db_str() {
1984 assert_eq!(AgentStatus::Idle.as_db_str(), "idle");
1985 assert_eq!(AgentStatus::Active.as_db_str(), "active");
1986 assert_eq!(AgentStatus::Blocked.as_db_str(), "blocked");
1987 assert_eq!(AgentStatus::Failed.as_db_str(), "failed");
1988 assert_eq!(AgentStatus::Offline.as_db_str(), "offline");
1989 }
1990
1991 #[test]
1992 fn test_agent_status_from_db_str() {
1993 assert_eq!(
1994 AgentStatus::from_db_str("idle").expect("parsing 'idle' should succeed"),
1995 AgentStatus::Idle
1996 );
1997 assert_eq!(
1998 AgentStatus::from_db_str("ACTIVE").expect("parsing 'ACTIVE' should succeed"),
1999 AgentStatus::Active
2000 );
2001 assert_eq!(
2002 AgentStatus::from_db_str("Blocked").expect("parsing 'Blocked' should succeed"),
2003 AgentStatus::Blocked
2004 );
2005 assert!(AgentStatus::from_db_str("invalid").is_err());
2006 }
2007
2008 #[test]
2013 fn test_entity_type_invalid_parse() {
2014 assert!("invalid".parse::<EntityType>().is_err());
2015 assert!("".parse::<EntityType>().is_err());
2016 }
2017
2018 #[test]
2019 fn test_trajectory_status_invalid_parse() {
2020 assert!("invalid".parse::<TrajectoryStatus>().is_err());
2021 }
2022
2023 #[test]
2024 fn test_artifact_type_invalid_parse() {
2025 assert!("invalid".parse::<ArtifactType>().is_err());
2026 }
2027
2028 #[test]
2029 fn test_note_type_invalid_parse() {
2030 assert!("invalid".parse::<NoteType>().is_err());
2031 }
2032
2033 #[test]
2034 fn test_edge_type_invalid_parse() {
2035 assert!("invalid".parse::<EdgeType>().is_err());
2036 }
2037
2038 #[test]
2043 fn test_parse_case_insensitive() {
2044 assert_eq!(
2045 "ACTIVE"
2046 .parse::<TrajectoryStatus>()
2047 .expect("parsing 'ACTIVE' should succeed"),
2048 TrajectoryStatus::Active
2049 );
2050 assert_eq!(
2051 "active"
2052 .parse::<TrajectoryStatus>()
2053 .expect("parsing 'active' should succeed"),
2054 TrajectoryStatus::Active
2055 );
2056 assert_eq!(
2057 "Active"
2058 .parse::<TrajectoryStatus>()
2059 .expect("parsing 'Active' should succeed"),
2060 TrajectoryStatus::Active
2061 );
2062 assert_eq!(
2063 "TRAJECTORY"
2064 .parse::<EntityType>()
2065 .expect("parsing 'TRAJECTORY' should succeed"),
2066 EntityType::Trajectory
2067 );
2068 assert_eq!(
2069 "trajectory"
2070 .parse::<EntityType>()
2071 .expect("parsing 'trajectory' should succeed"),
2072 EntityType::Trajectory
2073 );
2074 }
2075
2076 #[test]
2081 fn test_enum_parse_error_display() {
2082 let err = EnumParseError {
2083 enum_name: "AgentStatus",
2084 input: "invalid_status".to_string(),
2085 };
2086 let msg = format!("{}", err);
2087 assert!(msg.contains("invalid_status"));
2088 assert!(msg.contains("AgentStatus"));
2089 }
2090
2091 #[test]
2096 fn battle_intel_edge_type_variants() {
2097 let all_edge_types = vec![
2098 EdgeType::Supports,
2099 EdgeType::Contradicts,
2100 EdgeType::Supersedes,
2101 EdgeType::DerivedFrom,
2102 EdgeType::RelatesTo,
2103 EdgeType::Temporal,
2104 EdgeType::Causal,
2105 EdgeType::SynthesizedFrom,
2106 EdgeType::Grouped,
2107 EdgeType::Compared,
2108 ];
2109
2110 for edge_type in &all_edge_types {
2111 let serialized =
2112 serde_json::to_string(edge_type).expect("EdgeType should serialize to JSON");
2113 let deserialized: EdgeType =
2114 serde_json::from_str(&serialized).expect("EdgeType should deserialize from JSON");
2115 assert_eq!(
2116 *edge_type, deserialized,
2117 "EdgeType {:?} round-trip failed. Serialized: {}",
2118 edge_type, serialized
2119 );
2120 }
2121
2122 for edge_type in &all_edge_types {
2123 match edge_type {
2124 EdgeType::Supports
2125 | EdgeType::Contradicts
2126 | EdgeType::Supersedes
2127 | EdgeType::DerivedFrom
2128 | EdgeType::RelatesTo
2129 | EdgeType::Temporal
2130 | EdgeType::Causal
2131 | EdgeType::SynthesizedFrom
2132 | EdgeType::Grouped
2133 | EdgeType::Compared => {}
2134 }
2135 }
2136
2137 let synth = EdgeType::SynthesizedFrom;
2138 let json = serde_json::to_value(synth).expect("should serialize");
2139 assert_eq!(json, serde_json::json!("synthesized_from"));
2140 }
2141
2142 #[test]
2143 fn battle_intel_summarization_request_status_transitions() {
2144 let statuses = vec![
2145 SummarizationRequestStatus::Pending,
2146 SummarizationRequestStatus::InProgress,
2147 SummarizationRequestStatus::Completed,
2148 SummarizationRequestStatus::Failed,
2149 ];
2150
2151 for status in &statuses {
2152 let json = serde_json::to_string(status).expect("status should serialize");
2153 let back: SummarizationRequestStatus =
2154 serde_json::from_str(&json).expect("status should deserialize");
2155 assert_eq!(*status, back, "Status round-trip failed for {:?}", status);
2156 }
2157
2158 assert_eq!(SummarizationRequestStatus::Pending.as_db_str(), "pending");
2159 assert_eq!(
2160 SummarizationRequestStatus::InProgress.as_db_str(),
2161 "in_progress"
2162 );
2163 assert_eq!(
2164 SummarizationRequestStatus::Completed.as_db_str(),
2165 "completed"
2166 );
2167 assert_eq!(SummarizationRequestStatus::Failed.as_db_str(), "failed");
2168 }
2169}