|
| 1 | +import type { CommandDefinition } from "./tui-types"; |
| 2 | + |
| 3 | +export const INPUT_MIN_LINES = 1; |
| 4 | +export const INPUT_MAX_LINES = 6; |
| 5 | +export const INPUT_PROMPT_PREFIX = "› "; |
| 6 | +export const FRAME_RESERVED_COLUMNS = 4; |
| 7 | +export const INPUT_BOX_HORIZONTAL_CHROME = 4; // left/right border plus padding |
| 8 | +export const INK_RENDER_SAFETY_ROWS = 1; |
| 9 | +// The header is rendered as the top of the scrollable transcript region so it |
| 10 | +// scrolls away as content grows. It occupies a fixed block: two content rows |
| 11 | +// (badges + meta), a top and bottom border, and one bottom margin row. |
| 12 | +export const HEADER_ROWS = 5; |
| 13 | +export const OVERLAY_SUGGESTION_MIN_ROWS = 4; |
| 14 | +export const OVERLAY_SUGGESTION_MAX_ROWS = 12; |
| 15 | +export const PET_PANEL_MIN_WIDTH = 28; |
| 16 | +export const PET_PANEL_MAX_WIDTH = 42; |
| 17 | +export const RUN_SPINNER_FRAMES = [ |
| 18 | + "⠋", |
| 19 | + "⠙", |
| 20 | + "⠹", |
| 21 | + "⠸", |
| 22 | + "⠼", |
| 23 | + "⠴", |
| 24 | + "⠦", |
| 25 | + "⠧", |
| 26 | + "⠇", |
| 27 | + "⠏", |
| 28 | +] as const; |
| 29 | +export const COLLAPSED_TEXT_LINE_LIMIT = 10; |
| 30 | +export const COLLAPSIBLE_TEXT_LINE_THRESHOLD = 18; |
| 31 | +export const COLLAPSIBLE_TEXT_CHAR_THRESHOLD = 2400; |
| 32 | +export const RESTORED_TEXT_CHUNK_LINE_LIMIT = 12; |
| 33 | +export const RESTORED_TEXT_CHUNK_CHAR_LIMIT = 1800; |
| 34 | +export const TOOL_DETAIL_CHAR_LIMIT = 320; |
| 35 | +export const TRANSCRIPT_MOUSE_WHEEL_ROWS = 4; |
| 36 | +export const IMAGE_PREVIEW_MAX_COLS = 72; |
| 37 | +export const IMAGE_PREVIEW_MAX_ROWS = 12; |
| 38 | +export const IMAGE_PREVIEW_MIN_COLS = 12; |
| 39 | +export const IMAGE_PREVIEW_MIN_ROWS = 4; |
| 40 | +export const IMAGE_PREVIEW_VIEWPORT_CHROME_ROWS = 4; |
| 41 | +export const RUN_STATUS_ANIMATION_MS = 140; |
| 42 | +export const RUN_STATUS_HIGHLIGHT_COLOR = "#ffffff"; |
| 43 | +export const DEFAULT_STREAM_FLUSH_MS = 1000; |
| 44 | +export const STREAM_FLUSH_MIN_CHARS = 600; |
| 45 | +export const STREAM_FLUSH_MAX_WAIT_MS = 2500; |
| 46 | +export const PET_SNAPSHOT_FLUSH_MS = 1000; |
| 47 | +export const TUI_ANIMATIONS_ENABLED = |
| 48 | + process.env.BRAINCODE_TUI_ANIMATIONS === "true"; |
| 49 | + |
| 50 | +export function isTruthyEnv(value: string | undefined): boolean { |
| 51 | + if (!value) return false; |
| 52 | + return ["1", "true", "yes", "on"].includes(value.trim().toLowerCase()); |
| 53 | +} |
| 54 | + |
| 55 | +// Mouse-wheel scrolling is on by default. In the alternate screen there is no |
| 56 | +// native terminal scrollback, so the wheel drives the in-app transcript scroll. |
| 57 | +// Set BRAINCODE_TUI_MOUSE=false (or 0) to release the mouse if you prefer your |
| 58 | +// terminal's drag-to-select without holding Shift. Unset keeps it enabled. |
| 59 | +export const TUI_MOUSE_ENABLED = process.env.BRAINCODE_TUI_MOUSE |
| 60 | + ? isTruthyEnv(process.env.BRAINCODE_TUI_MOUSE) |
| 61 | + : true; |
| 62 | + |
| 63 | +export const BRAIN_LOGO: ReadonlyArray<string> = [ |
| 64 | + " ██████╗ ██████╗ █████╗ ██╗███╗ ██╗", |
| 65 | + " ██╔══██╗██╔══██╗██╔══██╗██║████╗ ██║", |
| 66 | + " ██████╔╝██████╔╝███████║██║██╔██╗ ██║", |
| 67 | + " ██╔══██╗██╔══██╗██╔══██║██║██║╚██╗██║", |
| 68 | + " ██████╔╝██║ ██║██║ ██║██║██║ ╚████║", |
| 69 | + " ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝", |
| 70 | +]; |
| 71 | + |
| 72 | +export const COMMANDS: CommandDefinition[] = [ |
| 73 | + { name: "help", label: "/help", hint: "List all slash commands" }, |
| 74 | + { |
| 75 | + name: "plan", |
| 76 | + label: "/plan", |
| 77 | + hint: "Preview routeBrain planning; add --heuristic for diagnostics", |
| 78 | + insert: "/plan ", |
| 79 | + }, |
| 80 | + { |
| 81 | + name: "intent", |
| 82 | + label: "/intent", |
| 83 | + hint: "Show the current task decomposition and dependency graph", |
| 84 | + }, |
| 85 | + { name: "mcp", label: "/mcp", hint: "Interactive MCP control panel" }, |
| 86 | + { name: "hooks", label: "/hooks", hint: "Interactive hooks control panel" }, |
| 87 | + { name: "sessions", label: "/sessions", hint: "Browse recent sessions" }, |
| 88 | + { |
| 89 | + name: "resume", |
| 90 | + label: "/resume", |
| 91 | + hint: "Resume a session by id", |
| 92 | + insert: "/resume ", |
| 93 | + }, |
| 94 | + { |
| 95 | + name: "new", |
| 96 | + label: "/new", |
| 97 | + hint: "Start a fresh session (clears transcript)", |
| 98 | + }, |
| 99 | + { |
| 100 | + name: "handoff", |
| 101 | + label: "/handoff", |
| 102 | + hint: "Fork a new session (or pass <session-id> to summarize another)", |
| 103 | + insert: "/handoff ", |
| 104 | + }, |
| 105 | + { |
| 106 | + name: "brain", |
| 107 | + label: "/brain", |
| 108 | + hint: "View Brain catalog and switch default brain", |
| 109 | + }, |
| 110 | + { |
| 111 | + name: "mode", |
| 112 | + label: "/mode", |
| 113 | + hint: "View or switch execution mode: auto/radical", |
| 114 | + insert: "/mode ", |
| 115 | + }, |
| 116 | + { name: "theme", label: "/theme", hint: "Show the system-resolved theme" }, |
| 117 | + { |
| 118 | + name: "image", |
| 119 | + label: "/image", |
| 120 | + hint: "Preview an image in the terminal (kitty/ghostty or text fallback)", |
| 121 | + insert: "/image ", |
| 122 | + }, |
| 123 | + { name: "auto", label: "/auto", hint: "Switch execution mode to auto" }, |
| 124 | + { |
| 125 | + name: "radical", |
| 126 | + label: "/radical", |
| 127 | + hint: "Switch execution mode to radical", |
| 128 | + }, |
| 129 | + { |
| 130 | + name: "team-test", |
| 131 | + label: "/team-test", |
| 132 | + hint: "Diagnostic: force every role to run the prompt in parallel", |
| 133 | + insert: "/team-test ", |
| 134 | + }, |
| 135 | + { |
| 136 | + name: "skill", |
| 137 | + label: "/skill", |
| 138 | + hint: "List project skills (.agents/skills)", |
| 139 | + }, |
| 140 | + { |
| 141 | + name: "agents", |
| 142 | + label: "/agents", |
| 143 | + hint: "Show AGENTS.md location and length", |
| 144 | + }, |
| 145 | + { name: "files", label: "/files", hint: "Refresh the @file index" }, |
| 146 | + { name: "clear", label: "/clear", hint: "Clear transcript" }, |
| 147 | + { name: "exit", label: "/exit", hint: "Quit the TUI" }, |
| 148 | +]; |
| 149 | + |
| 150 | +export const ANSI_RESET = "\x1b[39m"; |
| 151 | +export const ANSI_INVERSE = "\x1b[7m"; |
| 152 | +export const ANSI_INVERSE_OFF = "\x1b[27m"; |
| 153 | + |
| 154 | +export const INTENT_BIT_UP = 1; |
| 155 | +export const INTENT_BIT_RIGHT = 2; |
| 156 | +export const INTENT_BIT_DOWN = 4; |
| 157 | +export const INTENT_BIT_LEFT = 8; |
| 158 | + |
| 159 | +export const INTENT_BIT_CHARS: Record<number, string> = { |
| 160 | + 0: " ", |
| 161 | + 1: "│", |
| 162 | + 2: "─", |
| 163 | + 3: "└", |
| 164 | + 4: "│", |
| 165 | + 5: "│", |
| 166 | + 6: "┌", |
| 167 | + 7: "├", |
| 168 | + 8: "─", |
| 169 | + 9: "┘", |
| 170 | + 10: "─", |
| 171 | + 11: "┴", |
| 172 | + 12: "┐", |
| 173 | + 13: "┤", |
| 174 | + 14: "┬", |
| 175 | + 15: "┼", |
| 176 | +}; |
0 commit comments