@sschepis/robodev 1.0.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.
- package/ai.mjs +8 -0
- package/package.json +48 -0
- package/src/cli/cli-interface.mjs +271 -0
- package/src/config.mjs +64 -0
- package/src/core/ai-assistant.mjs +540 -0
- package/src/core/ai-provider.mjs +579 -0
- package/src/core/history-manager.mjs +330 -0
- package/src/core/system-prompt.mjs +182 -0
- package/src/custom-tools/custom-tools-manager.mjs +310 -0
- package/src/execution/tool-executor.mjs +892 -0
- package/src/lib/README.md +114 -0
- package/src/lib/adapters/console-status-adapter.mjs +48 -0
- package/src/lib/adapters/network-llm-adapter.mjs +37 -0
- package/src/lib/index.mjs +101 -0
- package/src/lib/interfaces.d.ts +98 -0
- package/src/main.mjs +61 -0
- package/src/package/package-manager.mjs +223 -0
- package/src/quality/code-validator.mjs +126 -0
- package/src/quality/quality-evaluator.mjs +248 -0
- package/src/reasoning/reasoning-system.mjs +258 -0
- package/src/structured-dev/flow-manager.mjs +321 -0
- package/src/structured-dev/implementation-planner.mjs +223 -0
- package/src/structured-dev/manifest-manager.mjs +423 -0
- package/src/structured-dev/plan-executor.mjs +113 -0
- package/src/structured-dev/project-bootstrapper.mjs +523 -0
- package/src/tools/desktop-automation-tools.mjs +172 -0
- package/src/tools/file-tools.mjs +141 -0
- package/src/tools/tool-definitions.mjs +872 -0
- package/src/ui/console-styler.mjs +503 -0
- package/src/workspace/workspace-manager.mjs +215 -0
- package/themes.json +66 -0
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
// Enhanced Console Styling System
|
|
2
|
+
// Provides modern, themed terminal output with gradients, icons, and animations
|
|
3
|
+
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import gradient from 'gradient-string';
|
|
6
|
+
import boxen from 'boxen';
|
|
7
|
+
import ora from 'ora';
|
|
8
|
+
import figures from 'figures';
|
|
9
|
+
import fs from 'fs';
|
|
10
|
+
import path from 'path';
|
|
11
|
+
import { fileURLToPath } from 'url';
|
|
12
|
+
|
|
13
|
+
export class ConsoleStyler {
|
|
14
|
+
constructor(theme = 'cyberpunk') {
|
|
15
|
+
this.currentTheme = theme;
|
|
16
|
+
this.themes = this.initializeThemes();
|
|
17
|
+
this.icons = this.initializeIcons();
|
|
18
|
+
this.spinners = new Map(); // Track active spinners
|
|
19
|
+
this.listener = null; // Listener for redirecting output
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Set a listener to capture logs instead of printing to console
|
|
23
|
+
setListener(listener) {
|
|
24
|
+
this.listener = listener;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Initialize color themes
|
|
28
|
+
initializeThemes() {
|
|
29
|
+
// Default themes
|
|
30
|
+
let themes = {};
|
|
31
|
+
|
|
32
|
+
// Try to load themes from external file
|
|
33
|
+
try {
|
|
34
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
35
|
+
const scriptDir = path.dirname(path.dirname(path.dirname(__filename)));
|
|
36
|
+
const themesPath = path.join(scriptDir, 'themes.json');
|
|
37
|
+
|
|
38
|
+
if (fs.existsSync(themesPath)) {
|
|
39
|
+
const loadedThemes = JSON.parse(fs.readFileSync(themesPath, 'utf8'));
|
|
40
|
+
|
|
41
|
+
// Convert arrays of colors to gradient functions
|
|
42
|
+
for (const [name, colors] of Object.entries(loadedThemes)) {
|
|
43
|
+
themes[name] = {};
|
|
44
|
+
for (const [type, colorArray] of Object.entries(colors)) {
|
|
45
|
+
themes[name][type] = gradient(colorArray);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
} catch (error) {
|
|
50
|
+
// Fallback if file load fails
|
|
51
|
+
console.error('Failed to load themes.json:', error.message);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Ensure at least one default theme exists if loading failed
|
|
55
|
+
if (Object.keys(themes).length === 0) {
|
|
56
|
+
themes.cyberpunk = {
|
|
57
|
+
primary: gradient(['#ff0080', '#7928ca', '#0070f3']),
|
|
58
|
+
secondary: gradient(['#00d4ff', '#0070f3']),
|
|
59
|
+
success: gradient(['#00ff88', '#00d4aa']),
|
|
60
|
+
warning: gradient(['#ffaa00', '#ff6b35']),
|
|
61
|
+
error: gradient(['#ff4757', '#c44569']),
|
|
62
|
+
info: gradient(['#5352ed', '#3742fa']),
|
|
63
|
+
system: gradient(['#747d8c', '#57606f']),
|
|
64
|
+
accent: gradient(['#ffa502', '#ff6348']),
|
|
65
|
+
todo: gradient(['#ff6b9d', '#c44569']),
|
|
66
|
+
workspace: gradient(['#6c5ce7', '#a29bfe']),
|
|
67
|
+
tools: gradient(['#00cec9', '#00b894']),
|
|
68
|
+
reasoning: gradient(['#fd79a8', '#e84393']),
|
|
69
|
+
quality: gradient(['#fdcb6e', '#e17055']),
|
|
70
|
+
progress: gradient(['#74b9ff', '#0984e3'])
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return themes;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Initialize icons for different message types
|
|
78
|
+
initializeIcons() {
|
|
79
|
+
return {
|
|
80
|
+
user: 'đ¤',
|
|
81
|
+
ai: 'đ¤',
|
|
82
|
+
error: 'â',
|
|
83
|
+
warning: 'â ī¸',
|
|
84
|
+
success: 'â
',
|
|
85
|
+
info: 'âšī¸',
|
|
86
|
+
system: 'âī¸',
|
|
87
|
+
tools: 'đ§',
|
|
88
|
+
todo: 'đ',
|
|
89
|
+
workspace: 'đ ',
|
|
90
|
+
working: 'âĄ',
|
|
91
|
+
recovery: 'đ',
|
|
92
|
+
quality: 'đ¯',
|
|
93
|
+
tts: 'đ',
|
|
94
|
+
reasoning: 'đ§ ',
|
|
95
|
+
history: 'đ',
|
|
96
|
+
packages: 'đĻ',
|
|
97
|
+
progress: 'âŗ',
|
|
98
|
+
workCompleted: 'â¨',
|
|
99
|
+
custom: 'đ ī¸',
|
|
100
|
+
loading: 'âŗ',
|
|
101
|
+
check: figures.tick,
|
|
102
|
+
cross: figures.cross,
|
|
103
|
+
bullet: figures.bullet,
|
|
104
|
+
arrow: figures.arrowRight,
|
|
105
|
+
star: figures.star,
|
|
106
|
+
heart: figures.heart,
|
|
107
|
+
radioOn: figures.radioOn,
|
|
108
|
+
radioOff: figures.radioOff
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Set theme
|
|
113
|
+
setTheme(themeName) {
|
|
114
|
+
if (this.themes[themeName]) {
|
|
115
|
+
this.currentTheme = themeName;
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Get current theme colors
|
|
122
|
+
getTheme() {
|
|
123
|
+
return this.themes[this.currentTheme] || Object.values(this.themes)[0];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Enhanced startup banner
|
|
127
|
+
displayStartupBanner(workingDir) {
|
|
128
|
+
const theme = this.getTheme();
|
|
129
|
+
const banner = `
|
|
130
|
+
âââ âââ âââ âââââââ ââââââââââââââââââââââââââââââââââââ ââââââ ââââ ââââââââââââ
|
|
131
|
+
âââ âââ âââ âââââââââââââââââââââââââââââââââââââââââââââââââââââââââ ââââââââââââ
|
|
132
|
+
âââ âââ ââ âââ âââââââââââââââââââââââââââââââââââ âââ ââââââââââââââ âââ âââ
|
|
133
|
+
âââ ââââââââââ âââââââââââââââââââââââââââââââââââ âââ ââââââââââââââââââ âââ
|
|
134
|
+
ââââââââââââââââââ âââ ââââââââââââââââââââââââââââââ âââ âââ ââââââ ââââââ âââ
|
|
135
|
+
ââââââââ ââââââââ âââ ââââââââââââââââââââââââââââââ âââ âââ ââââââ âââââ âââ
|
|
136
|
+
`;
|
|
137
|
+
|
|
138
|
+
const styledBanner = theme.primary(banner);
|
|
139
|
+
|
|
140
|
+
const infoBox = boxen(
|
|
141
|
+
`${this.icons.system} Working Directory: ${chalk.cyan(workingDir)}\n` +
|
|
142
|
+
`${this.icons.ai} Theme: ${chalk.magenta(this.currentTheme)}`,
|
|
143
|
+
{
|
|
144
|
+
padding: 0,
|
|
145
|
+
margin: 1,
|
|
146
|
+
borderStyle: 'none',
|
|
147
|
+
borderColor: 'cyan',
|
|
148
|
+
backgroundColor: 'black'
|
|
149
|
+
}
|
|
150
|
+
);
|
|
151
|
+
console.clear();
|
|
152
|
+
console.log(styledBanner);
|
|
153
|
+
console.log(infoBox);
|
|
154
|
+
console.log(theme.accent('â'.repeat(80)));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Enhanced message formatting
|
|
158
|
+
formatMessage(type, content, options = {}) {
|
|
159
|
+
const theme = this.getTheme();
|
|
160
|
+
const icon = this.icons[type] || this.icons.info;
|
|
161
|
+
const timestamp = options.timestamp ? chalk.gray(`[${new Date().toLocaleTimeString()}] `) : '';
|
|
162
|
+
|
|
163
|
+
let colorFunc;
|
|
164
|
+
let label = '';
|
|
165
|
+
|
|
166
|
+
switch (type) {
|
|
167
|
+
case 'user':
|
|
168
|
+
colorFunc = theme.info;
|
|
169
|
+
label = 'YOU';
|
|
170
|
+
break;
|
|
171
|
+
case 'ai':
|
|
172
|
+
colorFunc = theme.success;
|
|
173
|
+
label = 'AI';
|
|
174
|
+
break;
|
|
175
|
+
case 'error':
|
|
176
|
+
colorFunc = theme.error;
|
|
177
|
+
label = 'ERROR';
|
|
178
|
+
break;
|
|
179
|
+
case 'warning':
|
|
180
|
+
colorFunc = theme.warning;
|
|
181
|
+
label = 'WARNING';
|
|
182
|
+
break;
|
|
183
|
+
case 'system':
|
|
184
|
+
colorFunc = theme.system;
|
|
185
|
+
label = 'SYSTEM';
|
|
186
|
+
break;
|
|
187
|
+
case 'tools':
|
|
188
|
+
colorFunc = theme.tools;
|
|
189
|
+
label = 'TOOLS';
|
|
190
|
+
break;
|
|
191
|
+
case 'todo':
|
|
192
|
+
colorFunc = theme.todo;
|
|
193
|
+
label = 'TODO';
|
|
194
|
+
break;
|
|
195
|
+
case 'workspace':
|
|
196
|
+
colorFunc = theme.workspace;
|
|
197
|
+
label = 'WORKSPACE';
|
|
198
|
+
break;
|
|
199
|
+
case 'working':
|
|
200
|
+
colorFunc = theme.accent;
|
|
201
|
+
label = 'WORKING';
|
|
202
|
+
break;
|
|
203
|
+
case 'recovery':
|
|
204
|
+
colorFunc = theme.error;
|
|
205
|
+
label = 'RECOVERY';
|
|
206
|
+
break;
|
|
207
|
+
case 'quality':
|
|
208
|
+
colorFunc = theme.quality;
|
|
209
|
+
label = 'QUALITY';
|
|
210
|
+
break;
|
|
211
|
+
case 'tts':
|
|
212
|
+
colorFunc = theme.info;
|
|
213
|
+
label = 'TTS';
|
|
214
|
+
break;
|
|
215
|
+
case 'reasoning':
|
|
216
|
+
colorFunc = theme.reasoning;
|
|
217
|
+
label = 'REASONING';
|
|
218
|
+
break;
|
|
219
|
+
case 'history':
|
|
220
|
+
colorFunc = theme.warning;
|
|
221
|
+
label = 'HISTORY';
|
|
222
|
+
break;
|
|
223
|
+
case 'packages':
|
|
224
|
+
colorFunc = theme.tools;
|
|
225
|
+
label = 'PACKAGES';
|
|
226
|
+
break;
|
|
227
|
+
case 'progress':
|
|
228
|
+
colorFunc = theme.progress;
|
|
229
|
+
label = 'PROGRESS';
|
|
230
|
+
break;
|
|
231
|
+
case 'workCompleted':
|
|
232
|
+
colorFunc = theme.success;
|
|
233
|
+
label = 'WORK COMPLETED';
|
|
234
|
+
break;
|
|
235
|
+
case 'custom':
|
|
236
|
+
colorFunc = theme.accent;
|
|
237
|
+
label = 'CUSTOM';
|
|
238
|
+
break;
|
|
239
|
+
default:
|
|
240
|
+
colorFunc = theme.info;
|
|
241
|
+
label = type.toUpperCase();
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const styledLabel = colorFunc(`[${label}]`);
|
|
245
|
+
const formattedContent = options.indent ? ` ${content}` : content;
|
|
246
|
+
|
|
247
|
+
if (options.box) {
|
|
248
|
+
return boxen(
|
|
249
|
+
`${icon} ${formattedContent}`,
|
|
250
|
+
{
|
|
251
|
+
padding: 1,
|
|
252
|
+
borderStyle: 'round',
|
|
253
|
+
borderColor: this.getBoxColor(type)
|
|
254
|
+
}
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return `${timestamp}${icon} ${styledLabel} ${formattedContent}`;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Get appropriate box color for message type
|
|
262
|
+
getBoxColor(type) {
|
|
263
|
+
const colorMap = {
|
|
264
|
+
error: 'red',
|
|
265
|
+
warning: 'yellow',
|
|
266
|
+
success: 'green',
|
|
267
|
+
info: 'blue',
|
|
268
|
+
system: 'gray',
|
|
269
|
+
tools: 'cyan',
|
|
270
|
+
todo: 'magenta',
|
|
271
|
+
workspace: 'blue',
|
|
272
|
+
quality: 'yellow'
|
|
273
|
+
};
|
|
274
|
+
return colorMap[type] || 'cyan';
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Enhanced progress display with spinners
|
|
278
|
+
createSpinner(text, type = 'dots') {
|
|
279
|
+
const theme = this.getTheme();
|
|
280
|
+
const spinner = ora({
|
|
281
|
+
text: theme.progress(text),
|
|
282
|
+
spinner: type,
|
|
283
|
+
color: 'cyan'
|
|
284
|
+
});
|
|
285
|
+
return spinner;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Start a named spinner
|
|
289
|
+
startSpinner(name, text, type = 'dots') {
|
|
290
|
+
const spinner = this.createSpinner(text, type);
|
|
291
|
+
this.spinners.set(name, spinner);
|
|
292
|
+
spinner.start();
|
|
293
|
+
return spinner;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Update spinner text
|
|
297
|
+
updateSpinner(name, text) {
|
|
298
|
+
const spinner = this.spinners.get(name);
|
|
299
|
+
if (spinner) {
|
|
300
|
+
const theme = this.getTheme();
|
|
301
|
+
spinner.text = theme.progress(text);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Stop spinner with success
|
|
306
|
+
succeedSpinner(name, text) {
|
|
307
|
+
const spinner = this.spinners.get(name);
|
|
308
|
+
if (spinner) {
|
|
309
|
+
const theme = this.getTheme();
|
|
310
|
+
spinner.succeed(theme.success(text));
|
|
311
|
+
this.spinners.delete(name);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// Stop spinner with failure
|
|
316
|
+
failSpinner(name, text) {
|
|
317
|
+
const spinner = this.spinners.get(name);
|
|
318
|
+
if (spinner) {
|
|
319
|
+
const theme = this.getTheme();
|
|
320
|
+
spinner.fail(theme.error(text));
|
|
321
|
+
this.spinners.delete(name);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Enhanced todo list display
|
|
326
|
+
formatTodoList(todoData) {
|
|
327
|
+
const theme = this.getTheme();
|
|
328
|
+
const { task, items } = todoData;
|
|
329
|
+
|
|
330
|
+
let output = boxen(
|
|
331
|
+
theme.todo(`${this.icons.todo} Task: ${task}`),
|
|
332
|
+
{
|
|
333
|
+
padding: 1,
|
|
334
|
+
borderStyle: 'round',
|
|
335
|
+
borderColor: 'magenta'
|
|
336
|
+
}
|
|
337
|
+
);
|
|
338
|
+
|
|
339
|
+
output += '\n\n';
|
|
340
|
+
|
|
341
|
+
items.forEach((item, index) => {
|
|
342
|
+
const number = chalk.gray(`${index + 1}.`);
|
|
343
|
+
let statusIcon;
|
|
344
|
+
let statusColor;
|
|
345
|
+
|
|
346
|
+
switch (item.status) {
|
|
347
|
+
case 'completed':
|
|
348
|
+
statusIcon = this.icons.check;
|
|
349
|
+
statusColor = theme.success;
|
|
350
|
+
break;
|
|
351
|
+
case 'in_progress':
|
|
352
|
+
statusIcon = this.icons.arrow;
|
|
353
|
+
statusColor = theme.warning;
|
|
354
|
+
break;
|
|
355
|
+
default:
|
|
356
|
+
statusIcon = this.icons.radioOff;
|
|
357
|
+
statusColor = theme.system;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const statusText = statusColor(`${statusIcon} ${item.step}`);
|
|
361
|
+
const result = item.result ? chalk.gray(` - ${item.result}`) : '';
|
|
362
|
+
|
|
363
|
+
output += `${number} ${statusText}${result}\n`;
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
return output;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// Enhanced error display
|
|
370
|
+
formatError(error, context = {}) {
|
|
371
|
+
const theme = this.getTheme();
|
|
372
|
+
const errorBox = boxen(
|
|
373
|
+
`${this.icons.error} ${theme.error('ERROR')}\n\n` +
|
|
374
|
+
`${chalk.red(error.message)}\n` +
|
|
375
|
+
(error.code ? `\nCode: ${chalk.yellow(error.code)}` : '') +
|
|
376
|
+
(context.suggestions ? `\n\n${this.icons.info} Suggestions:\n${context.suggestions.map(s => ` âĸ ${s}`).join('\n')}` : ''),
|
|
377
|
+
{
|
|
378
|
+
padding: 1,
|
|
379
|
+
borderStyle: 'double',
|
|
380
|
+
borderColor: 'red',
|
|
381
|
+
backgroundColor: 'black'
|
|
382
|
+
}
|
|
383
|
+
);
|
|
384
|
+
|
|
385
|
+
return errorBox;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Progress bar for long operations
|
|
389
|
+
createProgressBar(total, current = 0) {
|
|
390
|
+
const theme = this.getTheme();
|
|
391
|
+
const percentage = Math.round((current / total) * 100);
|
|
392
|
+
const barLength = 30;
|
|
393
|
+
const filledLength = Math.round((barLength * current) / total);
|
|
394
|
+
|
|
395
|
+
const filled = 'â'.repeat(filledLength);
|
|
396
|
+
const empty = 'â'.repeat(barLength - filledLength);
|
|
397
|
+
|
|
398
|
+
return theme.progress(`[${filled}${empty}] ${percentage}% (${current}/${total})`);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// Gradient text helper
|
|
402
|
+
applyGradient(text, colors) {
|
|
403
|
+
return gradient(colors)(text);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Log with enhanced styling
|
|
407
|
+
log(type, content, options = {}) {
|
|
408
|
+
if (this.listener && typeof this.listener.log === 'function') {
|
|
409
|
+
this.listener.log(type, content, options);
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
const formatted = this.formatMessage(type, content, options);
|
|
413
|
+
console.log(formatted);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// Clear all active spinners
|
|
417
|
+
clearAllSpinners() {
|
|
418
|
+
this.spinners.forEach(spinner => spinner.stop());
|
|
419
|
+
this.spinners.clear();
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// Available themes list
|
|
423
|
+
getAvailableThemes() {
|
|
424
|
+
return Object.keys(this.themes);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// Format markdown text for beautiful terminal display
|
|
428
|
+
formatMarkdown(content) {
|
|
429
|
+
const theme = this.getTheme();
|
|
430
|
+
|
|
431
|
+
// Convert markdown to formatted terminal output
|
|
432
|
+
let formatted = content
|
|
433
|
+
// Headers
|
|
434
|
+
.replace(/^### (.*$)/gm, (match, text) => theme.accent(`\n${this.icons.star} ${text}`))
|
|
435
|
+
.replace(/^## (.*$)/gm, (match, text) => theme.primary(`\n${this.icons.star} ${text.toUpperCase()}`))
|
|
436
|
+
.replace(/^# (.*$)/gm, (match, text) => theme.success(`\n${this.icons.star} ${text.toUpperCase()}`))
|
|
437
|
+
|
|
438
|
+
// Bold text
|
|
439
|
+
.replace(/\*\*(.*?)\*\*/g, (match, text) => chalk.bold(theme.accent(text)))
|
|
440
|
+
|
|
441
|
+
// Italic text
|
|
442
|
+
.replace(/\*(.*?)\*/g, (match, text) => chalk.italic(theme.secondary(text)))
|
|
443
|
+
|
|
444
|
+
// Inline code
|
|
445
|
+
.replace(/`(.*?)`/g, (match, code) => chalk.bgGray.black(` ${code} `))
|
|
446
|
+
|
|
447
|
+
// Lists
|
|
448
|
+
.replace(/^[\s]*[-*+] (.*$)/gm, (match, text) => ` ${this.icons.bullet} ${text}`)
|
|
449
|
+
.replace(/^[\s]*\d+\. (.*$)/gm, (match, text) => ` ${this.icons.arrow} ${text}`)
|
|
450
|
+
|
|
451
|
+
// Links (show URL)
|
|
452
|
+
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (match, text, url) =>
|
|
453
|
+
`${theme.info(text)} ${chalk.gray(`(${url})`)}`
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
// Checkboxes
|
|
457
|
+
.replace(/- \[x\] (.*$)/gm, (match, text) => ` ${this.icons.check} ${theme.success(text)}`)
|
|
458
|
+
.replace(/- \[ \] (.*$)/gm, (match, text) => ` ${this.icons.radioOff} ${text}`)
|
|
459
|
+
|
|
460
|
+
// Code blocks (simple highlighting)
|
|
461
|
+
.replace(/```[\s\S]*?```/g, (match) => {
|
|
462
|
+
const lines = match.split('\n');
|
|
463
|
+
const lang = lines[0].replace('```', '').trim();
|
|
464
|
+
const code = lines.slice(1, -1).join('\n');
|
|
465
|
+
|
|
466
|
+
return boxen(
|
|
467
|
+
chalk.gray(code),
|
|
468
|
+
{
|
|
469
|
+
padding: 1,
|
|
470
|
+
borderStyle: 'round',
|
|
471
|
+
borderColor: 'gray',
|
|
472
|
+
title: lang ? `${lang}` : 'Code',
|
|
473
|
+
titleAlignment: 'left'
|
|
474
|
+
}
|
|
475
|
+
);
|
|
476
|
+
})
|
|
477
|
+
|
|
478
|
+
// Horizontal rules
|
|
479
|
+
.replace(/^---+$/gm, theme.system('â'.repeat(60)))
|
|
480
|
+
|
|
481
|
+
// Clean up multiple newlines
|
|
482
|
+
.replace(/\n{3,}/g, '\n\n');
|
|
483
|
+
|
|
484
|
+
return formatted;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// Enhanced final response display
|
|
488
|
+
displayFinalResponse(content) {
|
|
489
|
+
const theme = this.getTheme();
|
|
490
|
+
|
|
491
|
+
console.log('\n' + theme.accent('â'.repeat(80)));
|
|
492
|
+
console.log(theme.success(`${this.icons.ai} AI ASSISTANT RESPONSE`));
|
|
493
|
+
console.log(theme.accent('â'.repeat(80)) + '\n');
|
|
494
|
+
|
|
495
|
+
const formattedContent = this.formatMarkdown(content);
|
|
496
|
+
console.log(formattedContent);
|
|
497
|
+
|
|
498
|
+
console.log('\n' + theme.accent('â'.repeat(80)));
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// Create singleton instance
|
|
503
|
+
export const consoleStyler = new ConsoleStyler();
|