1#![allow(
2 missing_docs,
3 clippy::expect_used,
4 dead_code,
5 unused_imports,
6 unexpected_cfgs
7)]
8#![allow(
9 clippy::let_and_return,
10 clippy::borrow_interior_mutable_const,
11 clippy::derivable_impls
12)]
13pub mod ui_protocol;
20pub mod constants {
25 pub mod ui {
26 pub const TOOL_OUTPUT_MODE_COMPACT: &str = "compact";
27 pub const TOOL_OUTPUT_MODE_FULL: &str = "full";
28 pub const DEFAULT_REASONING_VISIBLE: bool = false;
29 pub const INLINE_PTY_PLACEHOLDER: &str = "...";
30 pub const INLINE_PTY_STATUS_DONE: &str = "DONE";
31 pub const HEADER_UNKNOWN_PLACEHOLDER: &str = "\u{2014}";
32 pub const HEADER_GIT_DIRTY_SUFFIX: &str = "*";
33 pub const CHAT_INPUT_PLACEHOLDER_BOOTSTRAP: &str =
34 "Describe what you want to build\u{2026}";
35 pub const CHAT_INPUT_PLACEHOLDER_FOLLOW_UP: &str = "Follow-up\u{2026}";
36 pub const WELCOME_TEXT_WIDTH: usize = 72;
37 pub const WELCOME_SHORTCUT_SECTION_TITLE: &str = "Shortcuts";
38 pub const WELCOME_SHORTCUT_HINT_PREFIX: &str = " ";
39 pub const WELCOME_SHORTCUT_SEPARATOR: &str = " \u{2022} ";
40 pub const WELCOME_SHORTCUT_INDENT: &str = " ";
41 pub const WELCOME_SLASH_COMMAND_SECTION_TITLE: &str = "Commands";
42 pub const WELCOME_SLASH_COMMAND_LIMIT: usize = 20;
43 pub const WELCOME_SLASH_COMMAND_PREFIX: &str = " /";
44 pub const WELCOME_SLASH_COMMAND_INTRO: &str = "Use / to open the command palette";
45 pub const WELCOME_SLASH_COMMAND_INDENT: &str = " ";
46 pub const INLINE_USER_PREFIX: &str = " ";
47 pub const HEADER_SHORTCUT_HINT: &str = "";
48 pub const HEADER_META_SEPARATOR: &str = " ";
49
50 pub const THEME_RELATIVE_LUMINANCE_CUTOFF: f32 = 0.03928;
51 pub const THEME_RELATIVE_LUMINANCE_LOW_FACTOR: f32 = 12.92;
52 pub const THEME_RELATIVE_LUMINANCE_OFFSET: f32 = 0.055;
53 pub const THEME_RELATIVE_LUMINANCE_EXPONENT: f32 = 2.4;
54 pub const THEME_RED_LUMINANCE_COEFFICIENT: f32 = 0.2126;
55 pub const THEME_GREEN_LUMINANCE_COEFFICIENT: f32 = 0.7152;
56 pub const THEME_BLUE_LUMINANCE_COEFFICIENT: f32 = 0.0722;
57 pub const THEME_CONTRAST_RATIO_OFFSET: f32 = 0.05;
58 pub const THEME_MIX_RATIO_MIN: f32 = 0.0;
59 pub const THEME_MIX_RATIO_MAX: f32 = 1.0;
60 pub const THEME_BLEND_CLAMP_MIN: f32 = 0.0;
61 pub const THEME_BLEND_CLAMP_MAX: f32 = 255.0;
62 pub const THEME_COLOR_WHITE_RED: f32 = 1.0;
63 pub const THEME_COLOR_WHITE_GREEN: f32 = 1.0;
64 pub const THEME_COLOR_WHITE_BLUE: f32 = 1.0;
65 pub const THEME_LOGO_ACCENT_BANNER_LIGHTEN_RATIO: f32 = 0.15;
66 pub const THEME_PRIMARY_STATUS_SECONDARY_LIGHTEN_RATIO: f32 = 0.7;
67 pub const THEME_LOGO_ACCENT_BANNER_SECONDARY_LIGHTEN_RATIO: f32 = 0.5;
68 pub const THEME_MIN_CONTRAST_RATIO: f32 = 3.0;
69 pub const THEME_FOREGROUND_LIGHTEN_RATIO: f32 = 0.2;
70 pub const THEME_SECONDARY_LIGHTEN_RATIO: f32 = 0.8;
71 pub const THEME_MIX_RATIO: f32 = 0.0;
72 pub const THEME_TOOL_BODY_LIGHTEN_RATIO: f32 = 0.1;
73 pub const THEME_TOOL_BODY_MIX_RATIO: f32 = 0.0;
74 pub const THEME_PTY_OUTPUT_MIX_RATIO: f32 = 0.0;
75 pub const THEME_RESPONSE_COLOR_LIGHTEN_RATIO: f32 = 0.1;
76 pub const THEME_USER_COLOR_LIGHTEN_RATIO: f32 = 0.1;
77 pub const THEME_SECONDARY_USER_COLOR_LIGHTEN_RATIO: f32 = 0.3;
78 pub const THEME_LUMINANCE_LIGHTEN_RATIO: f32 = 0.1;
79 pub const THEME_PRIMARY_STATUS_LIGHTEN_RATIO: f32 = 0.3;
80 pub const THEME_LOGO_ACCENT_BANNER_RATIO: f32 = 0.15;
81
82 pub const HEADER_STATUS_LABEL: &str = "Status";
83 pub const HEADER_STATUS_ACTIVE: &str = "Active";
84 pub const HEADER_STATUS_PAUSED: &str = "Paused";
85 pub const MODAL_LIST_HIGHLIGHT_SYMBOL: &str = "\u{2502}";
86 pub const MODAL_LIST_HIGHLIGHT_FULL: &str = "\u{2502} ";
87 pub const INLINE_FILE_PICKER_TREE_PREFIX: &str = "\u{25B8} ";
88 pub const NAVIGATION_BLOCK_TITLE: &str = "Timeline";
89 pub const NAVIGATION_BLOCK_SHORTCUT_NOTE: &str = "Ctrl+T";
90 pub const NAVIGATION_EMPTY_LABEL: &str = "Waiting for activity";
91 pub const SLASH_PALETTE_MIN_WIDTH: u16 = 40;
92 pub const SLASH_PALETTE_MIN_HEIGHT: u16 = 9;
93 pub const DEFAULT_INLINE_VIEWPORT_ROWS: u16 = 16;
94 pub fn agent_mode_hue(_token: &str) -> Option<&str> {
96 None
97 }
98 pub const AGENT_COLOR_AUTO: &str = "auto";
100 pub const AGENT_COLOR_BUILD: &str = "build";
101 pub const AGENT_COLOR_DUCK: &str = "duck";
102 pub const AGENT_COLOR_PLAN: &str = "plan";
103 }
104
105 pub mod defaults {
106 pub fn default_provider() -> String {
107 "openai".into()
108 }
109 pub fn default_model() -> String {
110 "gpt-4o".into()
111 }
112 pub const DEFAULT_THEME: &str = "oxi";
113 }
114
115 pub mod tools {
116 pub const GREP_FILE: &str = "grep_file";
117 pub const LIST_FILES: &str = "list_files";
118 pub const READ_FILE: &str = "read_file";
119 pub const EDIT_FILE: &str = "edit_file";
120 pub const WRITE_FILE: &str = "write_file";
121 pub const CREATE_FILE: &str = "create_file";
122 pub const APPLY_PATCH: &str = "apply_patch";
123 pub const SEARCH_REPLACE: &str = "search_replace";
124 pub const DELETE_FILE: &str = "delete_file";
125 pub const UNIFIED_FILE: &str = "unified_file";
126 }
127}
128
129pub mod core {
131 pub mod tools {
132 #[derive(
134 Debug, Clone, Copy, PartialEq, Eq, Default, serde::Serialize, serde::Deserialize,
135 )]
136 pub enum ToolPolicy {
137 #[default]
138 Allow,
139 Ask,
140 Prompt,
141 Deny,
142 }
143 }
144}
145
146pub mod types {
148 #[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
149 #[serde(rename_all = "snake_case")]
150 pub enum SystemPromptMode {
151 Default,
152 Compact,
153 }
154
155 #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, serde::Serialize, serde::Deserialize)]
156 pub enum ToolDocumentationMode {
157 #[default]
158 Full,
159 Compact,
160 Progressive,
161 None,
162 }
163
164 #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, serde::Serialize, serde::Deserialize)]
165 pub enum VerbosityLevel {
166 #[default]
167 Quiet,
168 Normal,
169 Medium,
170 Verbose,
171 }
172}
173
174pub mod reasoning {
176 #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, serde::Serialize, serde::Deserialize)]
177 pub enum ReasoningEffortLevel {
178 #[default]
179 Low,
180 Medium,
181 High,
182 }
183}
184
185pub mod stop_hints {
186 pub const STOP_HINT_COMPACT: &str = "\u{2026}";
187 pub const STOP_HINT_INLINE: &str = "\u{2026}";
188}
189
190pub mod terminal_detection {
191 pub fn is_ghostty_terminal(_term_program: Option<&str>, _term: Option<&str>) -> bool {
192 false
193 }
194}
195
196pub mod trace_flush {
197 pub fn flush_trace_log() {}
198}
199
200pub mod exclusions {
201 pub fn is_sensitive_file(_file_name: &str) -> bool {
202 false
203 }
204}
205
206pub mod color_policy {
207 pub fn no_color_env_active() -> bool {
208 false
209 }
210}
211
212pub mod formatting {
213 pub fn clean_reasoning_text(text: &str) -> String {
214 text.to_string()
215 }
216}
217
218pub mod ansi_codes {
219 pub const RESET: &str = "\x1b[0m";
220}
221
222pub mod editor {
223 pub fn normalize_editor_hash_fragment(_text: &str) -> String {
224 String::new()
225 }
226 pub fn parse_editor_target(_s: &str) -> Option<EditorTarget> {
227 None
228 }
229
230 #[derive(Debug, Clone)]
231 pub struct EditorTarget {
232 pub path: String,
233 pub line: Option<usize>,
234 pub col: Option<usize>,
235 }
236 impl EditorTarget {
237 pub fn path(&self) -> &std::path::Path {
238 std::path::Path::new(&self.path)
239 }
240 pub fn canonical_string(&self) -> String {
241 let mut s = self.path.clone();
242 if let Some(line) = self.line {
243 s.push_str(&format!(":{}", line));
244 if let Some(col) = self.col {
245 s.push_str(&format!(":{}", col));
246 }
247 }
248 s
249 }
250 }
251
252 #[derive(Debug, Clone)]
253 pub struct EditorPoint {
254 pub path: String,
255 pub line: usize,
256 pub col: usize,
257 }
258}
259
260pub mod color256_theme {
261 use anstyle::RgbColor;
262 pub fn rgb_to_ansi256_for_theme(_rgb: RgbColor, _light: bool) -> Option<u8> {
263 None
264 }
265}
266
267pub mod errors {
268 pub type MultiErrors = Vec<anyhow::Error>;
269}
270pub use errors::MultiErrors;
271
272pub mod ansi {
274 pub fn strip_ansi(s: &str) -> String {
276 let re = regex::Regex::new("\x1b\\[[0-9;]*[a-zA-Z]").unwrap();
277 re.replace_all(s, "").to_string()
278 }
279 pub fn strip_ansi_codes(s: &str) -> String {
280 strip_ansi(s)
281 }
282}
283
284pub mod ansi_capabilities {
286 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
287 pub enum ColorScheme {
288 Light,
289 Dark,
290 Unknown,
291 }
292 pub fn detect_color_scheme() -> ColorScheme {
293 ColorScheme::Dark
294 }
295}
296
297pub mod colors {
299 use anstyle::{AnsiColor, Color, RgbColor};
300 pub fn blend_colors(a: Color, b: Color, _ratio: f32) -> Color {
301 if _ratio > 0.5 { b } else { a }
304 }
305}
306
307pub mod diff {
309 #[derive(Clone, Debug)]
310 pub struct DiffOptions {
311 pub context: usize,
312 pub old_label: Option<String>,
313 pub new_label: Option<String>,
314 pub missing_newline_hint: Option<String>,
315 }
316 impl Default for DiffOptions {
317 fn default() -> Self {
318 Self {
319 context: 3,
320 old_label: None,
321 new_label: None,
322 missing_newline_hint: None,
323 }
324 }
325 }
326 #[derive(Clone, Debug)]
327 pub enum DiffLineKind {
328 Context,
329 Addition,
330 Deletion,
331 }
332 #[derive(Clone, Debug)]
333 pub struct DiffLine {
334 pub kind: DiffLineKind,
335 pub text: String,
336 pub content: String,
337 }
338 #[derive(Clone, Debug)]
339 pub struct DiffHunk {
340 pub old_start: usize,
341 pub new_start: usize,
342 pub old_lines: Vec<DiffLine>,
343 pub new_lines: Vec<DiffLine>,
344 pub lines: Vec<DiffLine>,
345 }
346 #[derive(Clone, Debug)]
347 pub struct DiffBundle {
348 pub old_path: Option<String>,
349 pub new_path: Option<String>,
350 pub hunks: Vec<DiffHunk>,
351 pub formatted: String,
352 }
353 #[derive(Clone, Debug)]
354 pub struct Chunk {
355 pub lines: Vec<DiffLine>,
356 }
357 pub fn compute_diff(old: &[String], new: &[String], opts: &DiffOptions) -> DiffBundle {
358 let _ = (old, new, opts);
359 DiffBundle {
360 old_path: None,
361 new_path: None,
362 hunks: vec![],
363 formatted: String::new(),
364 }
365 }
366 pub fn compute_diff_chunks(
367 _old: &[String],
368 _new_lines: &[String],
369 _opts: &DiffOptions,
370 ) -> Vec<Chunk> {
371 vec![]
372 }
373}
374
375pub mod diff_paths {
376 pub fn is_diff_addition_line(_line: &str) -> bool {
377 false
378 }
379 pub fn is_diff_deletion_line(_line: &str) -> bool {
380 false
381 }
382 pub fn language_hint_from_path(_path: &str) -> Option<&'static str> {
383 None
384 }
385 pub fn is_diff_header_line(_line: &str) -> bool {
386 false
387 }
388 pub fn is_diff_new_file_marker_line(_line: &str) -> bool {
389 false
390 }
391 pub fn looks_like_diff_content(_text: &str) -> bool {
392 false
393 }
394 pub fn parse_diff_git_path(_line: &str) -> Option<String> {
395 None
396 }
397 pub fn parse_diff_marker_path(_line: &str) -> Option<String> {
398 None
399 }
400 pub fn format_start_only_hunk_header(_old: usize, _new: usize) -> String {
401 String::new()
402 }
403}
404
405pub mod diff_preview {
406 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
407 pub enum DiffDisplayKind {
408 Unified,
409 Split,
410 }
411 pub fn count_diff_changes(_lines: &[String]) -> (usize, usize) {
412 (0, 0)
413 }
414 pub fn display_lines_from_hunks(_hunks: &[()], _kind: DiffDisplayKind) -> Vec<String> {
415 vec![]
416 }
417}
418
419pub mod diff_theme {
420 use crate::styling::DiffColorPalette;
421 use anstyle::{AnsiColor, Color};
422
423 #[derive(Clone, Debug)]
424 pub struct DiffTheme {
425 pub add_fg: Color,
426 pub add_bg: Color,
427 pub del_fg: Color,
428 pub del_bg: Color,
429 pub hunk_fg: Color,
430 pub hunk_bg: Color,
431 pub gutter_add_bg_light: Color,
432 pub gutter_del_bg_light: Color,
433 pub gutter_fg_light: Color,
434 }
435 impl Default for DiffTheme {
436 fn default() -> Self {
437 Self {
438 add_fg: Color::Ansi(AnsiColor::Green),
439 add_bg: Color::Ansi(AnsiColor::Black),
440 del_fg: Color::Ansi(AnsiColor::Red),
441 del_bg: Color::Ansi(AnsiColor::Black),
442 hunk_fg: Color::Ansi(AnsiColor::Cyan),
443 hunk_bg: Color::Ansi(AnsiColor::Black),
444 gutter_add_bg_light: Color::Ansi(AnsiColor::Black),
445 gutter_del_bg_light: Color::Ansi(AnsiColor::Black),
446 gutter_fg_light: Color::Ansi(AnsiColor::Black),
447 }
448 }
449 }
450
451 #[derive(Clone, Copy, Debug)]
452 pub enum DiffColorLevel {
453 Full,
454 Ansi256,
455 Ansi16,
456 None,
457 }
458
459 pub fn diff_add_bg(_level: DiffColorLevel) -> Color {
460 DiffTheme::default().add_bg
461 }
462 pub fn diff_del_bg(_level: DiffColorLevel) -> Color {
463 DiffTheme::default().del_bg
464 }
465 pub fn diff_gutter_bg_add_light(_level: DiffColorLevel) -> Color {
466 DiffTheme::default().gutter_add_bg_light
467 }
468 pub fn diff_gutter_bg_del_light(_level: DiffColorLevel) -> Color {
469 DiffTheme::default().gutter_del_bg_light
470 }
471 pub fn diff_gutter_fg_light(_level: DiffColorLevel) -> Color {
472 DiffTheme::default().gutter_fg_light
473 }
474
475 pub fn default_diff_palette() -> DiffColorPalette {
476 DiffColorPalette::default()
477 }
478}
479
480pub mod styling {
482 use anstyle::{AnsiColor, Color, RgbColor};
483
484 #[derive(Debug, Clone)]
485 pub struct ColorPalette {
486 pub primary: Color,
487 pub secondary: Color,
488 pub background: Color,
489 pub foreground: Color,
490 pub error: Color,
491 pub warning: Color,
492 pub success: Color,
493 }
494
495 impl Default for ColorPalette {
496 fn default() -> Self {
497 Self {
498 primary: Color::Ansi(AnsiColor::Blue),
499 secondary: Color::Ansi(AnsiColor::Cyan),
500 background: Color::Rgb(RgbColor(30, 30, 30)),
501 foreground: Color::Ansi(AnsiColor::White),
502 error: Color::Ansi(AnsiColor::Red),
503 warning: Color::Ansi(AnsiColor::Yellow),
504 success: Color::Ansi(AnsiColor::Green),
505 }
506 }
507 }
508
509 #[derive(Debug, Clone)]
511 pub struct DiffColorPalette {
512 pub addition_fg: Color,
513 pub addition_bg: Color,
514 pub deletion_fg: Color,
515 pub deletion_bg: Color,
516 pub hunk_header: Color,
517 pub context: Color,
518 }
519
520 impl Default for DiffColorPalette {
521 fn default() -> Self {
522 Self {
523 addition_fg: Color::Rgb(RgbColor(0x50, 0xFA, 0x7B)),
524 addition_bg: Color::Rgb(RgbColor(0x1B, 0x3B, 0x20)),
525 deletion_fg: Color::Rgb(RgbColor(0xFF, 0x55, 0x55)),
526 deletion_bg: Color::Rgb(RgbColor(0x3B, 0x1B, 0x1B)),
527 hunk_header: Color::Ansi(AnsiColor::Cyan),
528 context: Color::Rgb(RgbColor(128, 128, 128)),
529 }
530 }
531 }
532}
533
534pub mod fs {
536 use std::path::Path;
537
538 pub fn read_file_with_context_sync(
539 path: &Path,
540 _context_lines: usize,
541 ) -> anyhow::Result<String> {
542 Ok(std::fs::read_to_string(path)?)
543 }
544
545 pub fn write_file_with_context_sync(path: &Path, _content: &str) -> anyhow::Result<()> {
546 if let Some(parent) = path.parent() {
547 std::fs::create_dir_all(parent)?;
548 }
549 std::fs::write(path, _content)?;
550 Ok(())
551 }
552
553 pub fn is_image_path(_path: &str) -> bool {
554 false
555 }
556
557 pub fn trim_trailing_image_path_str(_s: &str) -> String {
558 _s.to_string()
559 }
560
561 pub fn unescape_whitespace(s: &str) -> String {
562 s.replace("\\n", "\n").replace("\\t", "\t")
563 }
564}
565
566pub mod lr_map {
568 pub struct LrMap<'a, K, V> {
571 _phantom: std::marker::PhantomData<&'a (K, V)>,
572 }
573
574 impl<'a, K, V> LrMap<'a, K, V> {
575 pub fn new() -> Self {
576 Self {
577 _phantom: std::marker::PhantomData,
578 }
579 }
580 pub fn insert(&self, _key: K, _value: V) {}
581 pub fn refresh(&self) {}
582 }
583 impl<'a, K, V> LrMap<'a, K, V> {
584 pub fn get(&self, _key: &K) -> Option<&V> {
585 None
586 }
587 }
588
589 impl<'a, K, V> Default for LrMap<'a, K, V> {
590 fn default() -> Self {
591 Self::new()
592 }
593 }
594
595 impl<'a, K, V> Clone for LrMap<'a, K, V> {
596 fn clone(&self) -> Self {
597 Self {
598 _phantom: std::marker::PhantomData,
599 }
600 }
601 }
602}
603
604pub mod preview;
606
607pub use colors::blend_colors;
609pub use editor::{EditorPoint, EditorTarget, normalize_editor_hash_fragment, parse_editor_target};
610pub use stop_hints::STOP_HINT_COMPACT;
611pub use styling::DiffColorPalette;