Skip to main content

kindling_types/
capsule.rs

1use serde::{Deserialize, Serialize};
2
3#[cfg(feature = "ts-rs")]
4use ts_rs::TS;
5
6use crate::common::{Id, ScopeIds, Timestamp};
7
8/// Types of capsules.
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
10#[cfg_attr(feature = "ts-rs", derive(TS), ts(export, export_to = "../bindings/"))]
11#[serde(rename_all = "snake_case")]
12pub enum CapsuleType {
13    Session,
14    PocketflowNode,
15}
16
17impl CapsuleType {
18    pub const ALL: &'static [CapsuleType] = &[CapsuleType::Session, CapsuleType::PocketflowNode];
19}
20
21/// Capsule lifecycle status.
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
23#[cfg_attr(feature = "ts-rs", derive(TS), ts(export, export_to = "../bindings/"))]
24#[serde(rename_all = "snake_case")]
25pub enum CapsuleStatus {
26    Open,
27    Closed,
28}
29
30impl CapsuleStatus {
31    pub const ALL: &'static [CapsuleStatus] = &[CapsuleStatus::Open, CapsuleStatus::Closed];
32}
33
34/// Bounded unit of meaning grouping related observations.
35///
36/// Mirrors `Capsule` in `packages/kindling-core/src/types/capsule.ts`.
37#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
38#[cfg_attr(feature = "ts-rs", derive(TS), ts(export, export_to = "../bindings/"))]
39#[serde(rename_all = "camelCase")]
40pub struct Capsule {
41    pub id: Id,
42    #[serde(rename = "type")]
43    #[cfg_attr(feature = "ts-rs", ts(rename = "type"))]
44    pub kind: CapsuleType,
45    pub intent: String,
46    pub status: CapsuleStatus,
47    #[cfg_attr(feature = "ts-rs", ts(type = "number"))]
48    pub opened_at: Timestamp,
49    #[serde(default, skip_serializing_if = "Option::is_none")]
50    #[cfg_attr(feature = "ts-rs", ts(optional, type = "number"))]
51    pub closed_at: Option<Timestamp>,
52    pub scope_ids: ScopeIds,
53    pub observation_ids: Vec<Id>,
54    #[serde(default, skip_serializing_if = "Option::is_none")]
55    #[cfg_attr(feature = "ts-rs", ts(optional))]
56    pub summary_id: Option<Id>,
57}
58
59/// Input for creating a new capsule. Optional fields are auto-generated.
60#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
61#[cfg_attr(feature = "ts-rs", derive(TS), ts(export, export_to = "../bindings/"))]
62#[serde(rename_all = "camelCase")]
63pub struct CapsuleInput {
64    #[serde(default, skip_serializing_if = "Option::is_none")]
65    #[cfg_attr(feature = "ts-rs", ts(optional))]
66    pub id: Option<Id>,
67    #[serde(rename = "type")]
68    #[cfg_attr(feature = "ts-rs", ts(rename = "type"))]
69    pub kind: CapsuleType,
70    pub intent: String,
71    #[serde(default, skip_serializing_if = "Option::is_none")]
72    #[cfg_attr(feature = "ts-rs", ts(optional))]
73    pub status: Option<CapsuleStatus>,
74    #[serde(default, skip_serializing_if = "Option::is_none")]
75    #[cfg_attr(feature = "ts-rs", ts(optional, type = "number"))]
76    pub opened_at: Option<Timestamp>,
77    #[serde(default, skip_serializing_if = "Option::is_none")]
78    #[cfg_attr(feature = "ts-rs", ts(optional, type = "number"))]
79    pub closed_at: Option<Timestamp>,
80    pub scope_ids: ScopeIds,
81    #[serde(default, skip_serializing_if = "Option::is_none")]
82    #[cfg_attr(feature = "ts-rs", ts(optional))]
83    pub observation_ids: Option<Vec<Id>>,
84    #[serde(default, skip_serializing_if = "Option::is_none")]
85    #[cfg_attr(feature = "ts-rs", ts(optional))]
86    pub summary_id: Option<Id>,
87}