Skip to main content

agent/orbs/
types.rs

1//! Public types shared by the animation engine and the GPUI widget.
2
3/// The twelve shipped states — each a hand-tuned animation.
4///
5/// Marked `#[non_exhaustive]`: matching on this from another crate needs a
6/// wildcard arm, so shipping a tenth state is not a breaking change. Prefer
7/// [`OrbState::label`] / [`OrbState::as_str`] over matching where you can.
8#[non_exhaustive]
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
10pub enum OrbState {
11    /// Particles on tilted orbits.
12    #[default]
13    Working,
14    /// A scan meridian sweeps a dotted globe.
15    Searching,
16    /// Bands scramble in quarter turns, then click back.
17    Solving,
18    /// A waveform rolls through latitude rings.
19    Listening,
20    /// A constellation wires itself, packets running the edges.
21    Connecting,
22    /// Three strands plait around the sphere.
23    Weaving,
24    /// An undulating multi-band sash.
25    Composing,
26    /// A face-on ring slowly morphing.
27    Breathing,
28    /// A dotted outline morphs circle → triangle → square.
29    Shaping,
30    /// An iris of particles converges and relaxes around a focal point.
31    Focusing,
32    /// Counter-rotating great circles form a reasoning gyroscope.
33    Reasoning,
34    /// Concentric memory echoes travel out from a steady core.
35    Recalling,
36}
37
38impl OrbState {
39    /// All states in playground / gallery order.
40    ///
41    /// This is a slice so adding future states does not change its public type.
42    pub const ALL_STATES: &'static [OrbState] = &[
43        OrbState::Working,
44        OrbState::Searching,
45        OrbState::Solving,
46        OrbState::Listening,
47        OrbState::Connecting,
48        OrbState::Weaving,
49        OrbState::Composing,
50        OrbState::Breathing,
51        OrbState::Shaping,
52        OrbState::Focusing,
53        OrbState::Reasoning,
54        OrbState::Recalling,
55    ];
56
57    /// The original nine-state gallery.
58    ///
59    /// Kept at its original array type for source compatibility. New code
60    /// should iterate [`Self::ALL_STATES`].
61    #[deprecated(since = "0.2.0", note = "use OrbState::ALL_STATES")]
62    pub const ALL: [OrbState; 9] = [
63        OrbState::Working,
64        OrbState::Searching,
65        OrbState::Solving,
66        OrbState::Listening,
67        OrbState::Connecting,
68        OrbState::Weaving,
69        OrbState::Composing,
70        OrbState::Breathing,
71        OrbState::Shaping,
72    ];
73
74    /// Human-readable status label (matches upstream aria defaults).
75    pub fn label(self) -> &'static str {
76        match self {
77            OrbState::Working => "Working…",
78            OrbState::Searching => "Searching…",
79            OrbState::Solving => "Solving…",
80            OrbState::Listening => "Listening…",
81            OrbState::Connecting => "Connecting…",
82            OrbState::Weaving => "Weaving…",
83            OrbState::Composing => "Composing…",
84            OrbState::Breathing => "Thinking…",
85            OrbState::Shaping => "Shaping…",
86            OrbState::Focusing => "Focusing…",
87            OrbState::Reasoning => "Reasoning…",
88            OrbState::Recalling => "Recalling…",
89        }
90    }
91
92    /// Stable snake_case name (matches the web package `state` prop).
93    pub fn as_str(self) -> &'static str {
94        match self {
95            OrbState::Working => "working",
96            OrbState::Searching => "searching",
97            OrbState::Solving => "solving",
98            OrbState::Listening => "listening",
99            OrbState::Connecting => "connecting",
100            OrbState::Weaving => "weaving",
101            OrbState::Composing => "composing",
102            OrbState::Breathing => "breathing",
103            OrbState::Shaping => "shaping",
104            OrbState::Focusing => "focusing",
105            OrbState::Reasoning => "reasoning",
106            OrbState::Recalling => "recalling",
107        }
108    }
109}
110
111/// Rendered size in logical pixels. Four tuned presets ship: inline (20),
112/// avatar (64), large (96), and hero (128). Larger sizes add detail gradually
113/// instead of merely stretching the 64 px artwork.
114#[non_exhaustive]
115#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
116pub enum OrbSize {
117    /// Chat-avatar scale (64 logical px).
118    #[default]
119    Avatar,
120    /// Inline-text scale (20 logical px).
121    Inline,
122    /// Prominent status / card scale (96 logical px).
123    Large,
124    /// Hero / empty-state scale (128 logical px).
125    Hero,
126}
127
128impl OrbSize {
129    /// All sizes in compact-to-prominent gallery order.
130    pub const ALL_SIZES: &'static [OrbSize] = &[
131        OrbSize::Inline,
132        OrbSize::Avatar,
133        OrbSize::Large,
134        OrbSize::Hero,
135    ];
136
137    /// Logical pixel edge length of the orb.
138    pub fn pixels(self) -> f32 {
139        match self {
140            OrbSize::Inline => 20.0,
141            OrbSize::Avatar => 64.0,
142            OrbSize::Large => 96.0,
143            OrbSize::Hero => 128.0,
144        }
145    }
146
147    /// Stable lowercase name for controls and command-line arguments.
148    pub fn as_str(self) -> &'static str {
149        match self {
150            OrbSize::Inline => "inline",
151            OrbSize::Avatar => "avatar",
152            OrbSize::Large => "large",
153            OrbSize::Hero => "hero",
154        }
155    }
156
157    /// Compact playground label.
158    pub fn label(self) -> &'static str {
159        match self {
160            OrbSize::Inline => "20 · inline",
161            OrbSize::Avatar => "64 · avatar",
162            OrbSize::Large => "96 · large",
163            OrbSize::Hero => "128 · hero",
164        }
165    }
166}
167
168/// Theme mode for monochrome ink on transparent canvas.
169#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
170pub enum OrbTheme {
171    /// Resolve from the window appearance (GPUI `WindowAppearance`).
172    #[default]
173    Auto,
174    /// Light ink for dark backgrounds.
175    Dark,
176    /// Dark ink for light backgrounds.
177    Light,
178}
179
180/// Internal mode keys — one painter per key. Grows in lockstep with
181/// [`OrbState`], hence `#[non_exhaustive]`.
182#[non_exhaustive]
183#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
184pub enum ModeKey {
185    Orbits,
186    Globe,
187    Rubik,
188    Wave,
189    Web,
190    Braid,
191    Ribbon,
192    Ring,
193    Morph,
194    Focus,
195    Gyroscope,
196    Echo,
197}
198
199impl ModeKey {
200    pub fn from_state(state: OrbState) -> Self {
201        match state {
202            OrbState::Working => ModeKey::Orbits,
203            OrbState::Searching => ModeKey::Globe,
204            OrbState::Solving => ModeKey::Rubik,
205            OrbState::Listening => ModeKey::Wave,
206            OrbState::Connecting => ModeKey::Web,
207            OrbState::Weaving => ModeKey::Braid,
208            OrbState::Composing => ModeKey::Ribbon,
209            OrbState::Breathing => ModeKey::Ring,
210            OrbState::Shaping => ModeKey::Morph,
211            OrbState::Focusing => ModeKey::Focus,
212            OrbState::Reasoning => ModeKey::Gyroscope,
213            OrbState::Recalling => ModeKey::Echo,
214        }
215    }
216}