gencode-ai 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (274) hide show
  1. package/.env.example +11 -0
  2. package/CLAUDE.md +70 -0
  3. package/LICENSE +21 -0
  4. package/README.md +117 -0
  5. package/dist/agent/agent.d.ts +84 -0
  6. package/dist/agent/agent.d.ts.map +1 -0
  7. package/dist/agent/agent.js +233 -0
  8. package/dist/agent/agent.js.map +1 -0
  9. package/dist/agent/index.d.ts +6 -0
  10. package/dist/agent/index.d.ts.map +1 -0
  11. package/dist/agent/index.js +6 -0
  12. package/dist/agent/index.js.map +1 -0
  13. package/dist/agent/types.d.ts +47 -0
  14. package/dist/agent/types.d.ts.map +1 -0
  15. package/dist/agent/types.js +5 -0
  16. package/dist/agent/types.js.map +1 -0
  17. package/dist/cli/components/App.d.ts +14 -0
  18. package/dist/cli/components/App.d.ts.map +1 -0
  19. package/dist/cli/components/App.js +395 -0
  20. package/dist/cli/components/App.js.map +1 -0
  21. package/dist/cli/components/CommandSuggestions.d.ts +13 -0
  22. package/dist/cli/components/CommandSuggestions.d.ts.map +1 -0
  23. package/dist/cli/components/CommandSuggestions.js +32 -0
  24. package/dist/cli/components/CommandSuggestions.js.map +1 -0
  25. package/dist/cli/components/Header.d.ts +9 -0
  26. package/dist/cli/components/Header.d.ts.map +1 -0
  27. package/dist/cli/components/Header.js +13 -0
  28. package/dist/cli/components/Header.js.map +1 -0
  29. package/dist/cli/components/Input.d.ts +13 -0
  30. package/dist/cli/components/Input.d.ts.map +1 -0
  31. package/dist/cli/components/Input.js +27 -0
  32. package/dist/cli/components/Input.js.map +1 -0
  33. package/dist/cli/components/Logo.d.ts +2 -0
  34. package/dist/cli/components/Logo.d.ts.map +1 -0
  35. package/dist/cli/components/Logo.js +8 -0
  36. package/dist/cli/components/Logo.js.map +1 -0
  37. package/dist/cli/components/Messages.d.ts +37 -0
  38. package/dist/cli/components/Messages.d.ts.map +1 -0
  39. package/dist/cli/components/Messages.js +106 -0
  40. package/dist/cli/components/Messages.js.map +1 -0
  41. package/dist/cli/components/ModelSelector.d.ts +13 -0
  42. package/dist/cli/components/ModelSelector.d.ts.map +1 -0
  43. package/dist/cli/components/ModelSelector.js +72 -0
  44. package/dist/cli/components/ModelSelector.js.map +1 -0
  45. package/dist/cli/components/Spinner.d.ts +12 -0
  46. package/dist/cli/components/Spinner.d.ts.map +1 -0
  47. package/dist/cli/components/Spinner.js +45 -0
  48. package/dist/cli/components/Spinner.js.map +1 -0
  49. package/dist/cli/components/index.d.ts +12 -0
  50. package/dist/cli/components/index.d.ts.map +1 -0
  51. package/dist/cli/components/index.js +12 -0
  52. package/dist/cli/components/index.js.map +1 -0
  53. package/dist/cli/components/theme.d.ts +31 -0
  54. package/dist/cli/components/theme.d.ts.map +1 -0
  55. package/dist/cli/components/theme.js +36 -0
  56. package/dist/cli/components/theme.js.map +1 -0
  57. package/dist/cli/index-legacy.d.ts +7 -0
  58. package/dist/cli/index-legacy.d.ts.map +1 -0
  59. package/dist/cli/index-legacy.js +431 -0
  60. package/dist/cli/index-legacy.js.map +1 -0
  61. package/dist/cli/index.d.ts +7 -0
  62. package/dist/cli/index.d.ts.map +1 -0
  63. package/dist/cli/index.js +116 -0
  64. package/dist/cli/index.js.map +1 -0
  65. package/dist/cli/ink-cli.d.ts +7 -0
  66. package/dist/cli/ink-cli.d.ts.map +1 -0
  67. package/dist/cli/ink-cli.js +105 -0
  68. package/dist/cli/ink-cli.js.map +1 -0
  69. package/dist/cli/session-picker.d.ts +16 -0
  70. package/dist/cli/session-picker.d.ts.map +1 -0
  71. package/dist/cli/session-picker.js +280 -0
  72. package/dist/cli/session-picker.js.map +1 -0
  73. package/dist/cli/ui.d.ts +61 -0
  74. package/dist/cli/ui.d.ts.map +1 -0
  75. package/dist/cli/ui.js +364 -0
  76. package/dist/cli/ui.js.map +1 -0
  77. package/dist/config/index.d.ts +7 -0
  78. package/dist/config/index.d.ts.map +1 -0
  79. package/dist/config/index.js +6 -0
  80. package/dist/config/index.js.map +1 -0
  81. package/dist/config/manager.d.ts +31 -0
  82. package/dist/config/manager.d.ts.map +1 -0
  83. package/dist/config/manager.js +65 -0
  84. package/dist/config/manager.js.map +1 -0
  85. package/dist/config/types.d.ts +22 -0
  86. package/dist/config/types.d.ts.map +1 -0
  87. package/dist/config/types.js +6 -0
  88. package/dist/config/types.js.map +1 -0
  89. package/dist/index.d.ts +12 -0
  90. package/dist/index.d.ts.map +1 -0
  91. package/dist/index.js +21 -0
  92. package/dist/index.js.map +1 -0
  93. package/dist/memory/index.d.ts +10 -0
  94. package/dist/memory/index.d.ts.map +1 -0
  95. package/dist/memory/index.js +9 -0
  96. package/dist/memory/index.js.map +1 -0
  97. package/dist/memory/init.d.ts +20 -0
  98. package/dist/memory/init.d.ts.map +1 -0
  99. package/dist/memory/init.js +332 -0
  100. package/dist/memory/init.js.map +1 -0
  101. package/dist/memory/manager.d.ts +85 -0
  102. package/dist/memory/manager.d.ts.map +1 -0
  103. package/dist/memory/manager.js +234 -0
  104. package/dist/memory/manager.js.map +1 -0
  105. package/dist/memory/types.d.ts +74 -0
  106. package/dist/memory/types.d.ts.map +1 -0
  107. package/dist/memory/types.js +6 -0
  108. package/dist/memory/types.js.map +1 -0
  109. package/dist/permissions/index.d.ts +7 -0
  110. package/dist/permissions/index.d.ts.map +1 -0
  111. package/dist/permissions/index.js +6 -0
  112. package/dist/permissions/index.js.map +1 -0
  113. package/dist/permissions/manager.d.ts +32 -0
  114. package/dist/permissions/manager.d.ts.map +1 -0
  115. package/dist/permissions/manager.js +79 -0
  116. package/dist/permissions/manager.js.map +1 -0
  117. package/dist/permissions/types.d.ts +14 -0
  118. package/dist/permissions/types.d.ts.map +1 -0
  119. package/dist/permissions/types.js +17 -0
  120. package/dist/permissions/types.js.map +1 -0
  121. package/dist/providers/anthropic.d.ts +20 -0
  122. package/dist/providers/anthropic.d.ts.map +1 -0
  123. package/dist/providers/anthropic.js +185 -0
  124. package/dist/providers/anthropic.js.map +1 -0
  125. package/dist/providers/gemini.d.ts +21 -0
  126. package/dist/providers/gemini.d.ts.map +1 -0
  127. package/dist/providers/gemini.js +241 -0
  128. package/dist/providers/gemini.js.map +1 -0
  129. package/dist/providers/index.d.ts +34 -0
  130. package/dist/providers/index.d.ts.map +1 -0
  131. package/dist/providers/index.js +72 -0
  132. package/dist/providers/index.js.map +1 -0
  133. package/dist/providers/openai.d.ts +19 -0
  134. package/dist/providers/openai.d.ts.map +1 -0
  135. package/dist/providers/openai.js +221 -0
  136. package/dist/providers/openai.js.map +1 -0
  137. package/dist/providers/types.d.ts +125 -0
  138. package/dist/providers/types.d.ts.map +1 -0
  139. package/dist/providers/types.js +6 -0
  140. package/dist/providers/types.js.map +1 -0
  141. package/dist/session/index.d.ts +6 -0
  142. package/dist/session/index.d.ts.map +1 -0
  143. package/dist/session/index.js +6 -0
  144. package/dist/session/index.js.map +1 -0
  145. package/dist/session/manager.d.ts +101 -0
  146. package/dist/session/manager.d.ts.map +1 -0
  147. package/dist/session/manager.js +295 -0
  148. package/dist/session/manager.js.map +1 -0
  149. package/dist/session/types.d.ts +39 -0
  150. package/dist/session/types.d.ts.map +1 -0
  151. package/dist/session/types.js +10 -0
  152. package/dist/session/types.js.map +1 -0
  153. package/dist/tools/builtin/bash.d.ts +7 -0
  154. package/dist/tools/builtin/bash.d.ts.map +1 -0
  155. package/dist/tools/builtin/bash.js +80 -0
  156. package/dist/tools/builtin/bash.js.map +1 -0
  157. package/dist/tools/builtin/edit.d.ts +7 -0
  158. package/dist/tools/builtin/edit.d.ts.map +1 -0
  159. package/dist/tools/builtin/edit.js +32 -0
  160. package/dist/tools/builtin/edit.js.map +1 -0
  161. package/dist/tools/builtin/glob.d.ts +7 -0
  162. package/dist/tools/builtin/glob.d.ts.map +1 -0
  163. package/dist/tools/builtin/glob.js +36 -0
  164. package/dist/tools/builtin/glob.js.map +1 -0
  165. package/dist/tools/builtin/grep.d.ts +7 -0
  166. package/dist/tools/builtin/grep.d.ts.map +1 -0
  167. package/dist/tools/builtin/grep.js +59 -0
  168. package/dist/tools/builtin/grep.js.map +1 -0
  169. package/dist/tools/builtin/read.d.ts +7 -0
  170. package/dist/tools/builtin/read.d.ts.map +1 -0
  171. package/dist/tools/builtin/read.js +29 -0
  172. package/dist/tools/builtin/read.js.map +1 -0
  173. package/dist/tools/builtin/write.d.ts +7 -0
  174. package/dist/tools/builtin/write.d.ts.map +1 -0
  175. package/dist/tools/builtin/write.js +24 -0
  176. package/dist/tools/builtin/write.js.map +1 -0
  177. package/dist/tools/index.d.ts +38 -0
  178. package/dist/tools/index.d.ts.map +1 -0
  179. package/dist/tools/index.js +32 -0
  180. package/dist/tools/index.js.map +1 -0
  181. package/dist/tools/registry.d.ts +22 -0
  182. package/dist/tools/registry.d.ts.map +1 -0
  183. package/dist/tools/registry.js +71 -0
  184. package/dist/tools/registry.js.map +1 -0
  185. package/dist/tools/types.d.ts +62 -0
  186. package/dist/tools/types.d.ts.map +1 -0
  187. package/dist/tools/types.js +126 -0
  188. package/dist/tools/types.js.map +1 -0
  189. package/docs/README.md +16 -0
  190. package/docs/proposals/0001-web-fetch-tool.md +293 -0
  191. package/docs/proposals/0002-web-search-tool.md +306 -0
  192. package/docs/proposals/0003-task-subagents.md +333 -0
  193. package/docs/proposals/0004-plan-mode.md +338 -0
  194. package/docs/proposals/0005-todo-system.md +299 -0
  195. package/docs/proposals/0006-memory-system.md +539 -0
  196. package/docs/proposals/0007-context-management.md +429 -0
  197. package/docs/proposals/0008-checkpointing.md +327 -0
  198. package/docs/proposals/0009-hooks-system.md +343 -0
  199. package/docs/proposals/0010-mcp-integration.md +382 -0
  200. package/docs/proposals/0011-custom-commands.md +374 -0
  201. package/docs/proposals/0012-ask-user-question.md +317 -0
  202. package/docs/proposals/0013-multi-edit-tool.md +345 -0
  203. package/docs/proposals/0014-lsp-tool.md +478 -0
  204. package/docs/proposals/0015-ls-tool.md +407 -0
  205. package/docs/proposals/0016-kill-shell-tool.md +455 -0
  206. package/docs/proposals/0017-background-tasks.md +489 -0
  207. package/docs/proposals/0018-parallel-tool-execution.md +415 -0
  208. package/docs/proposals/0019-session-enhancements.md +462 -0
  209. package/docs/proposals/0020-session-summarization.md +447 -0
  210. package/docs/proposals/0021-skills-system.md +409 -0
  211. package/docs/proposals/0022-plugin-system.md +467 -0
  212. package/docs/proposals/0023-permission-enhancements.md +470 -0
  213. package/docs/proposals/0024-keyboard-shortcuts.md +443 -0
  214. package/docs/proposals/0025-cost-tracking.md +447 -0
  215. package/docs/proposals/0026-git-integration.md +475 -0
  216. package/docs/proposals/0027-enhanced-read-tool.md +514 -0
  217. package/docs/proposals/0028-enhanced-bash-tool.md +511 -0
  218. package/docs/proposals/0029-notebook-edit-tool.md +413 -0
  219. package/docs/proposals/0030-plugin-marketplace.md +360 -0
  220. package/docs/proposals/0031-command-suggestions.md +295 -0
  221. package/docs/proposals/0032-ide-integrations.md +328 -0
  222. package/docs/proposals/0033-enterprise-deployment.md +221 -0
  223. package/docs/proposals/0034-sandboxing.md +273 -0
  224. package/docs/proposals/0035-auto-updater.md +311 -0
  225. package/docs/proposals/0036-enhanced-glob-tool.md +267 -0
  226. package/docs/proposals/0037-enhanced-grep-tool.md +360 -0
  227. package/docs/proposals/0038-interactive-cli-ui.md +373 -0
  228. package/docs/proposals/0039-streaming-enhancements.md +359 -0
  229. package/docs/proposals/0040-multi-provider-enhancements.md +369 -0
  230. package/docs/proposals/README.md +84 -0
  231. package/docs/proposals/TEMPLATE.md +57 -0
  232. package/docs/proposals/research/claude-code-research.md +307 -0
  233. package/examples/agent-demo.ts +115 -0
  234. package/examples/basic.ts +166 -0
  235. package/package.json +50 -0
  236. package/src/agent/agent.ts +276 -0
  237. package/src/agent/index.ts +6 -0
  238. package/src/agent/types.ts +62 -0
  239. package/src/cli/components/App.tsx +565 -0
  240. package/src/cli/components/CommandSuggestions.tsx +58 -0
  241. package/src/cli/components/Header.tsx +36 -0
  242. package/src/cli/components/Input.tsx +60 -0
  243. package/src/cli/components/Logo.tsx +16 -0
  244. package/src/cli/components/Messages.tsx +210 -0
  245. package/src/cli/components/ModelSelector.tsx +135 -0
  246. package/src/cli/components/Spinner.tsx +72 -0
  247. package/src/cli/components/index.ts +21 -0
  248. package/src/cli/components/theme.ts +36 -0
  249. package/src/cli/index.tsx +136 -0
  250. package/src/config/index.ts +7 -0
  251. package/src/config/manager.ts +77 -0
  252. package/src/config/types.ts +25 -0
  253. package/src/index.ts +86 -0
  254. package/src/permissions/index.ts +7 -0
  255. package/src/permissions/manager.ts +97 -0
  256. package/src/permissions/types.ts +29 -0
  257. package/src/providers/anthropic.ts +224 -0
  258. package/src/providers/gemini.ts +295 -0
  259. package/src/providers/index.ts +97 -0
  260. package/src/providers/openai.ts +261 -0
  261. package/src/providers/types.ts +181 -0
  262. package/src/session/index.ts +6 -0
  263. package/src/session/manager.ts +354 -0
  264. package/src/session/types.ts +49 -0
  265. package/src/tools/builtin/bash.ts +92 -0
  266. package/src/tools/builtin/edit.ts +37 -0
  267. package/src/tools/builtin/glob.ts +42 -0
  268. package/src/tools/builtin/grep.ts +67 -0
  269. package/src/tools/builtin/read.ts +34 -0
  270. package/src/tools/builtin/write.ts +27 -0
  271. package/src/tools/index.ts +36 -0
  272. package/src/tools/registry.ts +83 -0
  273. package/src/tools/types.ts +172 -0
  274. package/tsconfig.json +21 -0
@@ -0,0 +1,373 @@
1
+ # Proposal: Interactive CLI UI
2
+
3
+ - **Proposal ID**: 0038
4
+ - **Author**: mycode team
5
+ - **Status**: Draft
6
+ - **Created**: 2025-01-15
7
+ - **Updated**: 2025-01-15
8
+
9
+ ## Summary
10
+
11
+ Implement rich interactive CLI UI components including progress indicators, spinners, tables, syntax highlighting, and markdown rendering for an enhanced terminal experience.
12
+
13
+ ## Motivation
14
+
15
+ Current CLI output is basic:
16
+
17
+ 1. **Plain text**: No formatting or colors
18
+ 2. **No progress**: Long operations show nothing
19
+ 3. **No highlighting**: Code not colored
20
+ 4. **No structure**: Tables are plain text
21
+ 5. **Limited feedback**: Minimal visual cues
22
+
23
+ Rich UI improves comprehension and experience.
24
+
25
+ ## Detailed Design
26
+
27
+ ### API Design
28
+
29
+ ```typescript
30
+ // src/cli/ui/types.ts
31
+ interface Theme {
32
+ primary: string;
33
+ secondary: string;
34
+ success: string;
35
+ warning: string;
36
+ error: string;
37
+ muted: string;
38
+ code: string;
39
+ heading: string;
40
+ }
41
+
42
+ interface SpinnerOptions {
43
+ text: string;
44
+ spinner?: 'dots' | 'line' | 'arc' | 'pulse';
45
+ color?: string;
46
+ }
47
+
48
+ interface ProgressOptions {
49
+ total: number;
50
+ format?: string;
51
+ barWidth?: number;
52
+ showPercent?: boolean;
53
+ showEta?: boolean;
54
+ }
55
+
56
+ interface TableOptions {
57
+ columns: ColumnDef[];
58
+ rows: unknown[][];
59
+ style?: 'simple' | 'box' | 'rounded' | 'minimal';
60
+ maxWidth?: number;
61
+ }
62
+
63
+ interface ColumnDef {
64
+ header: string;
65
+ width?: number | 'auto';
66
+ align?: 'left' | 'center' | 'right';
67
+ formatter?: (value: unknown) => string;
68
+ }
69
+
70
+ interface SyntaxHighlightOptions {
71
+ language: string;
72
+ theme?: 'dark' | 'light' | 'monokai' | 'github';
73
+ lineNumbers?: boolean;
74
+ startLine?: number;
75
+ }
76
+ ```
77
+
78
+ ### UI Components
79
+
80
+ ```typescript
81
+ // src/cli/ui/components.ts
82
+ import chalk from 'chalk';
83
+ import ora from 'ora';
84
+ import { marked } from 'marked';
85
+ import { highlight } from 'cli-highlight';
86
+
87
+ class UIComponents {
88
+ private theme: Theme;
89
+
90
+ constructor(theme?: Partial<Theme>) {
91
+ this.theme = {
92
+ primary: '#3b82f6',
93
+ secondary: '#6b7280',
94
+ success: '#22c55e',
95
+ warning: '#eab308',
96
+ error: '#ef4444',
97
+ muted: '#9ca3af',
98
+ code: '#a855f7',
99
+ heading: '#f59e0b',
100
+ ...theme
101
+ };
102
+ }
103
+
104
+ // Spinner
105
+ spinner(options: SpinnerOptions): Spinner {
106
+ return ora({
107
+ text: options.text,
108
+ spinner: options.spinner || 'dots',
109
+ color: 'cyan'
110
+ });
111
+ }
112
+
113
+ // Progress bar
114
+ progress(options: ProgressOptions): ProgressBar {
115
+ return new ProgressBar({
116
+ total: options.total,
117
+ width: options.barWidth || 40,
118
+ format: options.format || '[:bar] :percent :eta',
119
+ complete: chalk.green('█'),
120
+ incomplete: chalk.gray('░')
121
+ });
122
+ }
123
+
124
+ // Table
125
+ table(options: TableOptions): string {
126
+ const { columns, rows, style = 'rounded' } = options;
127
+
128
+ // Calculate column widths
129
+ const widths = columns.map((col, i) => {
130
+ if (col.width === 'auto') {
131
+ const maxContent = Math.max(
132
+ col.header.length,
133
+ ...rows.map(row => String(row[i]).length)
134
+ );
135
+ return Math.min(maxContent, 40);
136
+ }
137
+ return col.width || 15;
138
+ });
139
+
140
+ // Border characters
141
+ const borders = {
142
+ rounded: { tl: '╭', tr: '╮', bl: '╰', br: '╯', h: '─', v: '│', t: '┬', b: '┴', l: '├', r: '┤', c: '┼' },
143
+ box: { tl: '┌', tr: '┐', bl: '└', br: '┘', h: '─', v: '│', t: '┬', b: '┴', l: '├', r: '┤', c: '┼' },
144
+ simple: { tl: '+', tr: '+', bl: '+', br: '+', h: '-', v: '|', t: '+', b: '+', l: '+', r: '+', c: '+' },
145
+ minimal: { tl: '', tr: '', bl: '', br: '', h: '─', v: ' ', t: '', b: '', l: '', r: '', c: '' }
146
+ }[style];
147
+
148
+ // Build table
149
+ const lines: string[] = [];
150
+
151
+ // Top border
152
+ if (borders.tl) {
153
+ lines.push(borders.tl + widths.map(w => borders.h.repeat(w + 2)).join(borders.t) + borders.tr);
154
+ }
155
+
156
+ // Header
157
+ const headerCells = columns.map((col, i) =>
158
+ this.padCell(chalk.bold(col.header), widths[i], col.align)
159
+ );
160
+ lines.push(borders.v + headerCells.map(c => ` ${c} `).join(borders.v) + borders.v);
161
+
162
+ // Header separator
163
+ lines.push(borders.l + widths.map(w => borders.h.repeat(w + 2)).join(borders.c) + borders.r);
164
+
165
+ // Rows
166
+ for (const row of rows) {
167
+ const cells = row.map((cell, i) => {
168
+ const formatted = columns[i].formatter
169
+ ? columns[i].formatter(cell)
170
+ : String(cell);
171
+ return this.padCell(formatted, widths[i], columns[i].align);
172
+ });
173
+ lines.push(borders.v + cells.map(c => ` ${c} `).join(borders.v) + borders.v);
174
+ }
175
+
176
+ // Bottom border
177
+ if (borders.bl) {
178
+ lines.push(borders.bl + widths.map(w => borders.h.repeat(w + 2)).join(borders.b) + borders.br);
179
+ }
180
+
181
+ return lines.join('\n');
182
+ }
183
+
184
+ // Syntax highlighting
185
+ highlightCode(code: string, options: SyntaxHighlightOptions): string {
186
+ const highlighted = highlight(code, {
187
+ language: options.language,
188
+ theme: {
189
+ keyword: chalk.magenta,
190
+ string: chalk.green,
191
+ number: chalk.cyan,
192
+ comment: chalk.gray,
193
+ function: chalk.yellow,
194
+ class: chalk.blue.bold
195
+ }
196
+ });
197
+
198
+ if (options.lineNumbers) {
199
+ const lines = highlighted.split('\n');
200
+ const startLine = options.startLine || 1;
201
+ const padding = String(startLine + lines.length - 1).length;
202
+
203
+ return lines.map((line, i) => {
204
+ const lineNum = chalk.gray(String(startLine + i).padStart(padding) + '│');
205
+ return `${lineNum} ${line}`;
206
+ }).join('\n');
207
+ }
208
+
209
+ return highlighted;
210
+ }
211
+
212
+ // Markdown rendering
213
+ renderMarkdown(markdown: string): string {
214
+ // Custom renderer for terminal
215
+ const renderer = new marked.Renderer();
216
+
217
+ renderer.heading = (text, level) => {
218
+ const prefix = '#'.repeat(level);
219
+ return chalk.hex(this.theme.heading).bold(`${prefix} ${text}\n\n`);
220
+ };
221
+
222
+ renderer.code = (code, language) => {
223
+ const highlighted = this.highlightCode(code, { language: language || 'text' });
224
+ return `\n${chalk.gray('```' + (language || ''))}\n${highlighted}\n${chalk.gray('```')}\n`;
225
+ };
226
+
227
+ renderer.codespan = (code) => {
228
+ return chalk.hex(this.theme.code)(`\`${code}\``);
229
+ };
230
+
231
+ renderer.strong = (text) => chalk.bold(text);
232
+ renderer.em = (text) => chalk.italic(text);
233
+
234
+ renderer.list = (body, ordered) => {
235
+ return body + '\n';
236
+ };
237
+
238
+ renderer.listitem = (text) => {
239
+ return ` • ${text}\n`;
240
+ };
241
+
242
+ renderer.link = (href, title, text) => {
243
+ return chalk.blue.underline(text) + chalk.gray(` (${href})`);
244
+ };
245
+
246
+ marked.setOptions({ renderer });
247
+ return marked(markdown);
248
+ }
249
+
250
+ // Box/panel
251
+ box(content: string, title?: string, style: 'single' | 'double' | 'rounded' = 'rounded'): string {
252
+ const lines = content.split('\n');
253
+ const maxWidth = Math.max(...lines.map(l => l.length), title?.length || 0);
254
+
255
+ const borders = {
256
+ rounded: { tl: '╭', tr: '╮', bl: '╰', br: '╯', h: '─', v: '│' },
257
+ single: { tl: '┌', tr: '┐', bl: '└', br: '┘', h: '─', v: '│' },
258
+ double: { tl: '╔', tr: '╗', bl: '╚', br: '╝', h: '═', v: '║' }
259
+ }[style];
260
+
261
+ const result: string[] = [];
262
+
263
+ // Top with optional title
264
+ if (title) {
265
+ result.push(borders.tl + borders.h + ` ${title} ` + borders.h.repeat(maxWidth - title.length - 1) + borders.tr);
266
+ } else {
267
+ result.push(borders.tl + borders.h.repeat(maxWidth + 2) + borders.tr);
268
+ }
269
+
270
+ // Content
271
+ for (const line of lines) {
272
+ result.push(borders.v + ' ' + line.padEnd(maxWidth) + ' ' + borders.v);
273
+ }
274
+
275
+ // Bottom
276
+ result.push(borders.bl + borders.h.repeat(maxWidth + 2) + borders.br);
277
+
278
+ return result.join('\n');
279
+ }
280
+
281
+ private padCell(text: string, width: number, align: string = 'left'): string {
282
+ const stripped = text.replace(/\x1b\[[0-9;]*m/g, '');
283
+ const padding = width - stripped.length;
284
+
285
+ if (padding <= 0) return text.slice(0, width);
286
+
287
+ switch (align) {
288
+ case 'right':
289
+ return ' '.repeat(padding) + text;
290
+ case 'center':
291
+ const left = Math.floor(padding / 2);
292
+ return ' '.repeat(left) + text + ' '.repeat(padding - left);
293
+ default:
294
+ return text + ' '.repeat(padding);
295
+ }
296
+ }
297
+ }
298
+
299
+ export const ui = new UIComponents();
300
+ ```
301
+
302
+ ### File Changes
303
+
304
+ | File | Action | Description |
305
+ |------|--------|-------------|
306
+ | `src/cli/ui/types.ts` | Create | Type definitions |
307
+ | `src/cli/ui/components.ts` | Create | UI components |
308
+ | `src/cli/ui/themes.ts` | Create | Theme definitions |
309
+ | `src/cli/ui/markdown.ts` | Create | Markdown renderer |
310
+ | `src/cli/ui/syntax.ts` | Create | Syntax highlighting |
311
+ | `package.json` | Modify | Add chalk, ora, marked |
312
+
313
+ ## User Experience
314
+
315
+ ### Progress Bar
316
+ ```
317
+ Installing dependencies...
318
+ ████████████████████░░░░░░░░░░░░░░░░░░░░ 52% | ETA: 15s
319
+ ```
320
+
321
+ ### Spinner
322
+ ```
323
+ ⠋ Analyzing codebase...
324
+ ⠙ Analyzing codebase...
325
+ ⠹ Analyzing codebase...
326
+ ✓ Analysis complete
327
+ ```
328
+
329
+ ### Syntax Highlighted Code
330
+ ```
331
+ 1│ import { Agent } from './agent';
332
+ 2│
333
+ 3│ async function main() {
334
+ 4│ const agent = new Agent({
335
+ 5│ provider: 'anthropic',
336
+ 6│ model: 'claude-sonnet-4'
337
+ 7│ });
338
+ 8│
339
+ 9│ await agent.run();
340
+ 10│ }
341
+ ```
342
+
343
+ ### Formatted Table
344
+ ```
345
+ ╭────────────────┬──────────┬────────────╮
346
+ │ File │ Status │ Lines │
347
+ ├────────────────┼──────────┼────────────┤
348
+ │ src/index.ts │ Modified │ +45 / -12 │
349
+ │ src/agent.ts │ Modified │ +123 / -67 │
350
+ │ src/cli.ts │ Added │ +89 / -0 │
351
+ ╰────────────────┴──────────┴────────────╯
352
+ ```
353
+
354
+ ## Security Considerations
355
+
356
+ 1. Escape ANSI sequences in user input
357
+ 2. Limit output width/height
358
+ 3. Handle terminal resize
359
+
360
+ ## Migration Path
361
+
362
+ 1. **Phase 1**: Spinners and progress
363
+ 2. **Phase 2**: Tables
364
+ 3. **Phase 3**: Syntax highlighting
365
+ 4. **Phase 4**: Markdown rendering
366
+ 5. **Phase 5**: Themes
367
+
368
+ ## References
369
+
370
+ - [chalk](https://github.com/chalk/chalk)
371
+ - [ora](https://github.com/sindresorhus/ora)
372
+ - [marked](https://github.com/markedjs/marked)
373
+ - [cli-highlight](https://github.com/felixfbecker/cli-highlight)