nika 0.35.4

Semantic YAML workflow engine for AI tasks - DAG execution, MCP integration, multi-provider LLM support
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
//! # Cosmic Tailwind Design System 🦋🌌
//!
//! Modular token-based design system for Nika TUI.
//!
//! ## Architecture
//!
//! ```text
//! ┌─────────────────────────────────────────────────────────────────────────┐
//! │  Level 1: ColorPalette      Raw Tailwind colors (Slate, Violet, etc.)  │
//! │  Level 2: SemanticColors    Purpose-driven colors (bg, text, verbs)    │
//! │  Level 3: ComponentTokens   UI element colors (button, panel, etc.)    │
//! │  Level 4: ThemeVariants     Dark/Light/Cosmic configurations           │
//! │  Level 5: TokenResolver     Runtime resolution with mode detection     │
//! └─────────────────────────────────────────────────────────────────────────┘
//! ```
//!
//! ## Cosmic Tailwind Philosophy
//!
//! - **Slate palette**: Blue-tinted neutrals (not pure gray) for depth
//! - **Violet primary**: 🦋 Nika brand accent
//! - **Cyan secondary**: 🌌 Cosmic glow effects
//! - **Pink accent**: Nebula highlights
//!
//! ## Usage
//!
//! ```rust,ignore
//! use nika::tui::tokens::{CosmicTheme, TokenResolver};
//!
//! let resolver = TokenResolver::cosmic_dark();
//! let bg = resolver.bg_primary();
//! let text = resolver.text_primary();
//! ```

pub mod colors;
pub mod compat;
pub mod semantic;

pub use colors::*;
pub use compat::*;
pub use semantic::*;

use ratatui::style::Color;

// ═══════════════════════════════════════════════════════════════════════════════
// COSMIC THEME PRESETS
// ═══════════════════════════════════════════════════════════════════════════════

/// Cosmic theme variant selector
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum CosmicVariant {
    /// 🌌 Cosmic Dark - Deep space with nebula accents
    #[default]
    CosmicDark,
    /// 🌅 Cosmic Light - Aurora borealis on light background
    CosmicLight,
    /// 🦋 Cosmic Violet - Full violet immersion
    CosmicViolet,
}

impl CosmicVariant {
    /// Create theme resolver for this variant
    pub fn resolver(&self) -> TokenResolver {
        match self {
            Self::CosmicDark => TokenResolver::cosmic_dark(),
            Self::CosmicLight => TokenResolver::cosmic_light(),
            Self::CosmicViolet => TokenResolver::cosmic_violet(),
        }
    }

    /// Cycle to next variant
    pub fn cycle(&self) -> Self {
        match self {
            Self::CosmicDark => Self::CosmicLight,
            Self::CosmicLight => Self::CosmicViolet,
            Self::CosmicViolet => Self::CosmicDark,
        }
    }

    /// Display label with emoji
    pub fn label(&self) -> &'static str {
        match self {
            Self::CosmicDark => "🌌 Cosmic Dark",
            Self::CosmicLight => "🌅 Cosmic Light",
            Self::CosmicViolet => "🦋 Cosmic Violet",
        }
    }

    /// Create variant from index (0=Dark, 1=Light, 2=Violet)
    ///
    /// Used by Settings view for direct theme selection via `[1][2][3]` keys.
    pub fn from_index(index: u8) -> Option<Self> {
        match index {
            0 => Some(Self::CosmicDark),
            1 => Some(Self::CosmicLight),
            2 => Some(Self::CosmicViolet),
            _ => None,
        }
    }
}

// ═══════════════════════════════════════════════════════════════════════════════
// TOKEN RESOLVER (Level 5)
// ═══════════════════════════════════════════════════════════════════════════════

/// Runtime token resolver with cached semantic colors
///
/// Resolves design tokens to actual colors based on theme variant.
/// Caches computed values for performance.
#[derive(Debug, Clone)]
pub struct TokenResolver {
    palette: ColorPalette,
    semantic: SemanticColors,
    variant: CosmicVariant,
}

impl Default for TokenResolver {
    fn default() -> Self {
        Self::cosmic_dark()
    }
}

impl TokenResolver {
    /// Create Cosmic Dark resolver 🌌
    pub fn cosmic_dark() -> Self {
        let palette = ColorPalette::tailwind();
        let semantic = SemanticColors::cosmic_dark(&palette);
        Self {
            palette,
            semantic,
            variant: CosmicVariant::CosmicDark,
        }
    }

    /// Create Cosmic Light resolver 🌅
    pub fn cosmic_light() -> Self {
        let palette = ColorPalette::tailwind();
        let semantic = SemanticColors::cosmic_light(&palette);
        Self {
            palette,
            semantic,
            variant: CosmicVariant::CosmicLight,
        }
    }

    /// Create Cosmic Violet resolver 🦋
    pub fn cosmic_violet() -> Self {
        let palette = ColorPalette::tailwind();
        let semantic = SemanticColors::cosmic_violet(&palette);
        Self {
            palette,
            semantic,
            variant: CosmicVariant::CosmicViolet,
        }
    }

    // ═══════════════════════════════════════════════════════════════════════════
    // BACKGROUND TOKENS
    // ═══════════════════════════════════════════════════════════════════════════

    /// Primary background (main canvas)
    pub fn bg_primary(&self) -> Color {
        self.semantic.bg_primary
    }

    /// Secondary background (elevated surfaces)
    pub fn bg_secondary(&self) -> Color {
        self.semantic.bg_secondary
    }

    /// Tertiary background (cards, panels)
    pub fn bg_tertiary(&self) -> Color {
        self.semantic.bg_tertiary
    }

    /// Hover state background
    pub fn bg_hover(&self) -> Color {
        self.semantic.bg_hover
    }

    /// Active/selected state background
    pub fn bg_active(&self) -> Color {
        self.semantic.bg_active
    }

    // ═══════════════════════════════════════════════════════════════════════════
    // TEXT TOKENS
    // ═══════════════════════════════════════════════════════════════════════════

    /// Primary text (main content)
    pub fn text_primary(&self) -> Color {
        self.semantic.text_primary
    }

    /// Secondary text (descriptions, labels)
    pub fn text_secondary(&self) -> Color {
        self.semantic.text_secondary
    }

    /// Muted text (hints, placeholders)
    pub fn text_muted(&self) -> Color {
        self.semantic.text_muted
    }

    /// Disabled text
    pub fn text_disabled(&self) -> Color {
        self.semantic.text_disabled
    }

    /// Inverse text (on accent backgrounds)
    pub fn text_inverse(&self) -> Color {
        self.semantic.text_inverse
    }

    // ═══════════════════════════════════════════════════════════════════════════
    // BORDER TOKENS
    // ═══════════════════════════════════════════════════════════════════════════

    /// Default border
    pub fn border_default(&self) -> Color {
        self.semantic.border_default
    }

    /// Focused border (with accent)
    pub fn border_focused(&self) -> Color {
        self.semantic.border_focused
    }

    /// Subtle border (dividers)
    pub fn border_subtle(&self) -> Color {
        self.semantic.border_subtle
    }

    // ═══════════════════════════════════════════════════════════════════════════
    // ACCENT TOKENS
    // ═══════════════════════════════════════════════════════════════════════════

    /// Primary accent (🦋 Violet)
    pub fn accent_primary(&self) -> Color {
        self.semantic.accent_primary
    }

    /// Secondary accent (🌌 Cyan)
    pub fn accent_secondary(&self) -> Color {
        self.semantic.accent_secondary
    }

    /// Tertiary accent (Pink nebula)
    pub fn accent_tertiary(&self) -> Color {
        self.semantic.accent_tertiary
    }

    // ═══════════════════════════════════════════════════════════════════════════
    // STATUS TOKENS
    // ═══════════════════════════════════════════════════════════════════════════

    /// Success color (green)
    pub fn status_success(&self) -> Color {
        self.semantic.status_success
    }

    /// Warning color (amber)
    pub fn status_warning(&self) -> Color {
        self.semantic.status_warning
    }

    /// Error color (red)
    pub fn status_error(&self) -> Color {
        self.semantic.status_error
    }

    /// Info color (blue)
    pub fn status_info(&self) -> Color {
        self.semantic.status_info
    }

    // ═══════════════════════════════════════════════════════════════════════════
    // VERB TOKENS (5 semantic verbs)
    // ═══════════════════════════════════════════════════════════════════════════

    /// Infer verb color (Violet)
    pub fn verb_infer(&self) -> Color {
        self.semantic.verb_infer
    }

    /// Exec verb color (Amber)
    pub fn verb_exec(&self) -> Color {
        self.semantic.verb_exec
    }

    /// Fetch verb color (Cyan)
    pub fn verb_fetch(&self) -> Color {
        self.semantic.verb_fetch
    }

    /// Invoke verb color (Emerald)
    pub fn verb_invoke(&self) -> Color {
        self.semantic.verb_invoke
    }

    /// Agent verb color (Rose)
    pub fn verb_agent(&self) -> Color {
        self.semantic.verb_agent
    }

    /// Get verb color by name
    pub fn verb_color(&self, verb: &str) -> Color {
        match verb.to_lowercase().as_str() {
            "infer" => self.verb_infer(),
            "exec" => self.verb_exec(),
            "fetch" => self.verb_fetch(),
            "invoke" => self.verb_invoke(),
            "agent" => self.verb_agent(),
            _ => self.text_muted(),
        }
    }

    // ═══════════════════════════════════════════════════════════════════════════
    // RAW PALETTE ACCESS
    // ═══════════════════════════════════════════════════════════════════════════

    /// Access raw color palette for custom combinations
    pub fn palette(&self) -> &ColorPalette {
        &self.palette
    }

    /// Access semantic colors
    pub fn semantic(&self) -> &SemanticColors {
        &self.semantic
    }

    /// Get current variant
    pub fn variant(&self) -> CosmicVariant {
        self.variant
    }
}

// ═══════════════════════════════════════════════════════════════════════════════
// TESTS
// ═══════════════════════════════════════════════════════════════════════════════

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_cosmic_dark_resolver() {
        let resolver = TokenResolver::cosmic_dark();
        assert_eq!(resolver.variant(), CosmicVariant::CosmicDark);
        // Slate-900 background
        assert_eq!(resolver.bg_primary(), Color::Rgb(15, 23, 42));
    }

    #[test]
    fn test_cosmic_light_resolver() {
        let resolver = TokenResolver::cosmic_light();
        assert_eq!(resolver.variant(), CosmicVariant::CosmicLight);
        // Slate-50 background
        assert_eq!(resolver.bg_primary(), Color::Rgb(248, 250, 252));
    }

    #[test]
    fn test_cosmic_violet_resolver() {
        let resolver = TokenResolver::cosmic_violet();
        assert_eq!(resolver.variant(), CosmicVariant::CosmicViolet);
    }

    #[test]
    fn test_verb_colors() {
        let resolver = TokenResolver::cosmic_dark();
        // Violet for infer
        assert_eq!(resolver.verb_infer(), Color::Rgb(139, 92, 246));
        // Amber for exec
        assert_eq!(resolver.verb_exec(), Color::Rgb(245, 158, 11));
    }

    #[test]
    fn test_variant_cycle() {
        let v = CosmicVariant::CosmicDark;
        assert_eq!(v.cycle(), CosmicVariant::CosmicLight);
        assert_eq!(v.cycle().cycle(), CosmicVariant::CosmicViolet);
        assert_eq!(v.cycle().cycle().cycle(), CosmicVariant::CosmicDark);
    }

    #[test]
    fn test_variant_labels() {
        assert_eq!(CosmicVariant::CosmicDark.label(), "🌌 Cosmic Dark");
        assert_eq!(CosmicVariant::CosmicLight.label(), "🌅 Cosmic Light");
        assert_eq!(CosmicVariant::CosmicViolet.label(), "🦋 Cosmic Violet");
    }

    #[test]
    fn test_variant_from_index_valid() {
        assert_eq!(
            CosmicVariant::from_index(0),
            Some(CosmicVariant::CosmicDark)
        );
        assert_eq!(
            CosmicVariant::from_index(1),
            Some(CosmicVariant::CosmicLight)
        );
        assert_eq!(
            CosmicVariant::from_index(2),
            Some(CosmicVariant::CosmicViolet)
        );
    }

    #[test]
    fn test_variant_from_index_invalid() {
        assert_eq!(CosmicVariant::from_index(3), None);
        assert_eq!(CosmicVariant::from_index(255), None);
    }
}