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