prab-cli 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/dist/lib/ui.js ADDED
@@ -0,0 +1,578 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.StreamFormatter = exports.formatMarkdown = exports.showToolProgress = exports.showTodoList = exports.showDiff = exports.banner = exports.log = void 0;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const diff_1 = require("diff");
9
+ // Syntax highlighting color schemes for different languages
10
+ const syntaxColors = {
11
+ keyword: chalk_1.default.magenta,
12
+ string: chalk_1.default.green,
13
+ number: chalk_1.default.yellow,
14
+ comment: chalk_1.default.gray,
15
+ function: chalk_1.default.cyan,
16
+ variable: chalk_1.default.white,
17
+ operator: chalk_1.default.yellow,
18
+ punctuation: chalk_1.default.white,
19
+ type: chalk_1.default.blue,
20
+ };
21
+ // Common keywords for different languages
22
+ const keywords = new Set([
23
+ // JavaScript/TypeScript
24
+ 'const', 'let', 'var', 'function', 'return', 'if', 'else', 'for', 'while', 'do',
25
+ 'switch', 'case', 'break', 'continue', 'try', 'catch', 'finally', 'throw',
26
+ 'class', 'extends', 'new', 'this', 'super', 'import', 'export', 'from', 'as',
27
+ 'default', 'async', 'await', 'yield', 'typeof', 'instanceof', 'in', 'of',
28
+ 'true', 'false', 'null', 'undefined', 'void', 'delete', 'static', 'get', 'set',
29
+ 'interface', 'type', 'enum', 'implements', 'private', 'public', 'protected',
30
+ // Python
31
+ 'def', 'class', 'import', 'from', 'as', 'if', 'elif', 'else', 'for', 'while',
32
+ 'try', 'except', 'finally', 'raise', 'with', 'lambda', 'return', 'yield',
33
+ 'True', 'False', 'None', 'and', 'or', 'not', 'is', 'in', 'pass', 'global',
34
+ 'nonlocal', 'assert', 'break', 'continue', 'self', 'async', 'await',
35
+ // Go
36
+ 'func', 'package', 'import', 'type', 'struct', 'interface', 'map', 'chan',
37
+ 'go', 'defer', 'select', 'range', 'make', 'append', 'len', 'cap', 'nil',
38
+ // Rust
39
+ 'fn', 'let', 'mut', 'pub', 'mod', 'use', 'struct', 'enum', 'impl', 'trait',
40
+ 'match', 'loop', 'move', 'ref', 'self', 'Self', 'where', 'unsafe', 'async',
41
+ // Common
42
+ 'print', 'println', 'printf', 'console', 'log', 'error', 'warn',
43
+ ]);
44
+ /**
45
+ * Truncate output for brief display
46
+ */
47
+ const truncateOutput = (text, maxLen) => {
48
+ const firstLine = text.split('\n')[0];
49
+ if (firstLine.length > maxLen) {
50
+ return firstLine.substring(0, maxLen) + '...';
51
+ }
52
+ return firstLine;
53
+ };
54
+ /**
55
+ * Format diff output with colors
56
+ */
57
+ const formatDiffOutput = (output) => {
58
+ const lines = output.split('\n');
59
+ return lines.map(line => {
60
+ // File headers
61
+ if (line.startsWith('diff --git')) {
62
+ return chalk_1.default.bold.white(line);
63
+ }
64
+ if (line.startsWith('index ')) {
65
+ return chalk_1.default.gray(line);
66
+ }
67
+ if (line.startsWith('---')) {
68
+ return chalk_1.default.red.bold(line);
69
+ }
70
+ if (line.startsWith('+++')) {
71
+ return chalk_1.default.green.bold(line);
72
+ }
73
+ // Hunk headers
74
+ if (line.startsWith('@@')) {
75
+ return chalk_1.default.cyan(line);
76
+ }
77
+ // Added lines
78
+ if (line.startsWith('+')) {
79
+ return chalk_1.default.green(line);
80
+ }
81
+ // Removed lines
82
+ if (line.startsWith('-')) {
83
+ return chalk_1.default.red(line);
84
+ }
85
+ // Context lines
86
+ return chalk_1.default.gray(line);
87
+ }).join('\n');
88
+ };
89
+ /**
90
+ * Format git log output with colors
91
+ */
92
+ const formatGitLogOutput = (output) => {
93
+ const lines = output.split('\n');
94
+ return lines.map(line => {
95
+ // Commit hash
96
+ if (line.match(/^[a-f0-9]{7,40}\s/)) {
97
+ const parts = line.split(' ');
98
+ const hash = parts[0];
99
+ const rest = parts.slice(1).join(' ');
100
+ return chalk_1.default.yellow(hash) + ' ' + rest;
101
+ }
102
+ // Date lines
103
+ if (line.match(/^\d{4}-\d{2}-\d{2}/)) {
104
+ return chalk_1.default.blue(line);
105
+ }
106
+ // Author
107
+ if (line.toLowerCase().includes('author:')) {
108
+ return chalk_1.default.cyan(line);
109
+ }
110
+ // Commit message (indented)
111
+ if (line.startsWith(' ')) {
112
+ return chalk_1.default.white(line);
113
+ }
114
+ return line;
115
+ }).join('\n');
116
+ };
117
+ /**
118
+ * Format git status output with colors
119
+ */
120
+ const formatGitStatusOutput = (output) => {
121
+ const lines = output.split('\n');
122
+ return lines.map(line => {
123
+ // Branch info
124
+ if (line.startsWith('On branch') || line.startsWith('HEAD detached')) {
125
+ return chalk_1.default.cyan.bold(line);
126
+ }
127
+ // Modified files
128
+ if (line.includes('modified:')) {
129
+ return chalk_1.default.yellow(line);
130
+ }
131
+ // New files
132
+ if (line.includes('new file:')) {
133
+ return chalk_1.default.green(line);
134
+ }
135
+ // Deleted files
136
+ if (line.includes('deleted:')) {
137
+ return chalk_1.default.red(line);
138
+ }
139
+ // Untracked files header
140
+ if (line.includes('Untracked files:')) {
141
+ return chalk_1.default.magenta.bold(line);
142
+ }
143
+ // Staged changes header
144
+ if (line.includes('Changes to be committed:')) {
145
+ return chalk_1.default.green.bold(line);
146
+ }
147
+ // Unstaged changes header
148
+ if (line.includes('Changes not staged')) {
149
+ return chalk_1.default.yellow.bold(line);
150
+ }
151
+ // File status indicators (M, A, D, ??)
152
+ if (line.match(/^\s*[MADRCU?]{1,2}\s+/)) {
153
+ const status = line.match(/^\s*([MADRCU?]{1,2})\s+(.*)$/);
154
+ if (status) {
155
+ const indicator = status[1];
156
+ const filename = status[2];
157
+ let color = chalk_1.default.white;
158
+ if (indicator.includes('M'))
159
+ color = chalk_1.default.yellow;
160
+ if (indicator.includes('A'))
161
+ color = chalk_1.default.green;
162
+ if (indicator.includes('D'))
163
+ color = chalk_1.default.red;
164
+ if (indicator.includes('?'))
165
+ color = chalk_1.default.gray;
166
+ return color(` ${indicator} ${filename}`);
167
+ }
168
+ }
169
+ return chalk_1.default.gray(line);
170
+ }).join('\n');
171
+ };
172
+ /**
173
+ * Apply syntax highlighting to a line of code
174
+ */
175
+ const highlightCodeLine = (line) => {
176
+ // Handle comments
177
+ const commentMatch = line.match(/^(\s*)(\/\/.*|#.*|\/\*.*\*\/|<!--.*-->)$/);
178
+ if (commentMatch) {
179
+ return commentMatch[1] + syntaxColors.comment(commentMatch[2]);
180
+ }
181
+ let result = line;
182
+ // Highlight strings (single, double, template)
183
+ result = result.replace(/(["'`])(?:(?!\1|\\).|\\.)*\1/g, (match) => syntaxColors.string(match));
184
+ // Highlight numbers
185
+ result = result.replace(/\b(\d+\.?\d*)\b/g, (match) => syntaxColors.number(match));
186
+ // Highlight keywords
187
+ const words = result.split(/(\s+|[^\w])/);
188
+ result = words
189
+ .map((word) => {
190
+ if (keywords.has(word)) {
191
+ return syntaxColors.keyword(word);
192
+ }
193
+ return word;
194
+ })
195
+ .join("");
196
+ // Highlight function calls
197
+ result = result.replace(/\b([a-zA-Z_]\w*)\s*\(/g, (match, name) => syntaxColors.function(name) + "(");
198
+ return result;
199
+ };
200
+ /**
201
+ * Format file content with line numbers and syntax highlighting
202
+ */
203
+ const formatFileContent = (content, filename) => {
204
+ const lines = content.split('\n');
205
+ const lineNumWidth = String(lines.length).length;
206
+ return lines.map((line, idx) => {
207
+ const lineNum = String(idx + 1).padStart(lineNumWidth, ' ');
208
+ const highlighted = highlightCodeLine(line);
209
+ return chalk_1.default.gray(`${lineNum} │ `) + highlighted;
210
+ }).join('\n');
211
+ };
212
+ /**
213
+ * Format bash command output
214
+ */
215
+ const formatBashOutput = (output) => {
216
+ // Check if it looks like a diff
217
+ if (output.includes('diff --git') || output.includes('@@') && (output.includes('+') || output.includes('-'))) {
218
+ return formatDiffOutput(output);
219
+ }
220
+ // Check if it looks like git log
221
+ if (output.match(/^[a-f0-9]{7,40}\s+\d{4}-\d{2}-\d{2}/m)) {
222
+ return formatGitLogOutput(output);
223
+ }
224
+ // Generic output with some highlighting
225
+ const lines = output.split('\n');
226
+ return lines.map(line => {
227
+ // Error messages
228
+ if (line.toLowerCase().includes('error') || line.toLowerCase().includes('failed')) {
229
+ return chalk_1.default.red(line);
230
+ }
231
+ // Warning messages
232
+ if (line.toLowerCase().includes('warning') || line.toLowerCase().includes('warn')) {
233
+ return chalk_1.default.yellow(line);
234
+ }
235
+ // Success messages
236
+ if (line.toLowerCase().includes('success') || line.toLowerCase().includes('done') || line.toLowerCase().includes('passed')) {
237
+ return chalk_1.default.green(line);
238
+ }
239
+ // Paths
240
+ if (line.match(/^[./~]/)) {
241
+ return chalk_1.default.cyan(line);
242
+ }
243
+ return line;
244
+ }).join('\n');
245
+ };
246
+ /**
247
+ * Format tool output based on tool type
248
+ */
249
+ const formatToolOutput = (toolName, output) => {
250
+ if (!output || output.trim() === '') {
251
+ return chalk_1.default.gray(' (no output)');
252
+ }
253
+ const separator = chalk_1.default.gray('─'.repeat(60));
254
+ let formatted;
255
+ switch (toolName.toLowerCase()) {
256
+ case 'git_diff':
257
+ case 'gitdiff':
258
+ formatted = formatDiffOutput(output);
259
+ break;
260
+ case 'git_log':
261
+ case 'gitlog':
262
+ formatted = formatGitLogOutput(output);
263
+ break;
264
+ case 'git_status':
265
+ case 'gitstatus':
266
+ formatted = formatGitStatusOutput(output);
267
+ break;
268
+ case 'read_file':
269
+ case 'readfile':
270
+ formatted = formatFileContent(output);
271
+ break;
272
+ case 'bash':
273
+ case 'shell':
274
+ formatted = formatBashOutput(output);
275
+ break;
276
+ case 'glob':
277
+ case 'grep':
278
+ // File lists - highlight paths
279
+ formatted = output.split('\n').map(line => {
280
+ if (line.includes(':')) {
281
+ const [path, ...rest] = line.split(':');
282
+ return chalk_1.default.cyan(path) + ':' + chalk_1.default.white(rest.join(':'));
283
+ }
284
+ return chalk_1.default.cyan(line);
285
+ }).join('\n');
286
+ break;
287
+ default:
288
+ formatted = output;
289
+ }
290
+ return `\n${chalk_1.default.gray('Output:')}\n${formatted}`;
291
+ };
292
+ exports.log = {
293
+ info: (msg) => console.log(chalk_1.default.blue("ℹ"), msg),
294
+ success: (msg) => console.log(chalk_1.default.green("✔"), msg),
295
+ warning: (msg) => console.log(chalk_1.default.yellow("⚠"), msg),
296
+ error: (msg) => console.log(chalk_1.default.red("✖"), msg),
297
+ code: (msg) => console.log(chalk_1.default.gray(msg)),
298
+ // Tool feedback methods
299
+ tool: (name, action) => {
300
+ console.log(chalk_1.default.cyan("🔧"), `Tool: ${chalk_1.default.bold(name)} - ${action}`);
301
+ },
302
+ toolResult: (success, message) => {
303
+ if (success) {
304
+ console.log(chalk_1.default.green(" ✓"), chalk_1.default.gray(truncateOutput(message, 100)));
305
+ }
306
+ else {
307
+ console.log(chalk_1.default.red(" ✗"), chalk_1.default.gray(message));
308
+ }
309
+ },
310
+ // Display formatted tool output
311
+ toolOutput: (toolName, output) => {
312
+ const formatted = formatToolOutput(toolName, output);
313
+ console.log(formatted);
314
+ },
315
+ };
316
+ const banner = (modelName, toolCount) => {
317
+ console.log(chalk_1.default.bold.cyan(`
318
+ ____ __ ________ ____
319
+ / __ \\_________ _/ /_ / ____/ / / _/
320
+ / /_/ / ___/ __ \`/ __ \\ / / / / / /
321
+ / ____/ / / /_/ / /_/ / / /___/ /____/ /
322
+ /_/ /_/ \\__,_/_.___/ \\____/_____/___/
323
+ `));
324
+ if (modelName) {
325
+ console.log(chalk_1.default.gray(` Active Model: ${chalk_1.default.cyan(modelName)}`));
326
+ }
327
+ if (toolCount !== undefined) {
328
+ console.log(chalk_1.default.gray(` Available Tools: ${chalk_1.default.cyan(toolCount.toString())}`));
329
+ }
330
+ console.log("");
331
+ };
332
+ exports.banner = banner;
333
+ /**
334
+ * Display a diff between two strings
335
+ */
336
+ const showDiff = (before, after, filename) => {
337
+ if (filename) {
338
+ console.log(chalk_1.default.bold(`\nDiff for ${filename}:`));
339
+ }
340
+ const diff = (0, diff_1.diffLines)(before, after);
341
+ diff.forEach((part) => {
342
+ const color = part.added
343
+ ? chalk_1.default.green
344
+ : part.removed
345
+ ? chalk_1.default.red
346
+ : chalk_1.default.gray;
347
+ const prefix = part.added ? "+ " : part.removed ? "- " : " ";
348
+ const lines = part.value.split("\n");
349
+ lines.forEach((line) => {
350
+ if (line) {
351
+ console.log(color(prefix + line));
352
+ }
353
+ });
354
+ });
355
+ console.log("");
356
+ };
357
+ exports.showDiff = showDiff;
358
+ /**
359
+ * Display todo list
360
+ */
361
+ const showTodoList = (todos) => {
362
+ if (todos.length === 0) {
363
+ console.log(chalk_1.default.gray(" No todos"));
364
+ return;
365
+ }
366
+ console.log(chalk_1.default.bold("\n📋 Todo List:"));
367
+ todos.forEach((todo, index) => {
368
+ const status = todo.status === "completed"
369
+ ? chalk_1.default.green("✓")
370
+ : todo.status === "in_progress"
371
+ ? chalk_1.default.yellow("⋯")
372
+ : chalk_1.default.gray("○");
373
+ const text = todo.status === "in_progress" ? todo.activeForm : todo.content;
374
+ const textColor = todo.status === "completed"
375
+ ? chalk_1.default.gray
376
+ : todo.status === "in_progress"
377
+ ? chalk_1.default.cyan
378
+ : chalk_1.default.white;
379
+ console.log(` ${status} ${textColor(text)}`);
380
+ });
381
+ console.log("");
382
+ };
383
+ exports.showTodoList = showTodoList;
384
+ /**
385
+ * Show tool execution progress
386
+ */
387
+ const showToolProgress = (toolName, status) => {
388
+ const icon = status === "started" ? "⏳" : status === "completed" ? "✓" : "✗";
389
+ const color = status === "started"
390
+ ? chalk_1.default.yellow
391
+ : status === "completed"
392
+ ? chalk_1.default.green
393
+ : chalk_1.default.red;
394
+ console.log(color(`${icon} ${toolName} ${status}`));
395
+ };
396
+ exports.showToolProgress = showToolProgress;
397
+ /**
398
+ * Format a code block with syntax highlighting and borders
399
+ */
400
+ const formatCodeBlock = (code, language) => {
401
+ const lines = code.split("\n");
402
+ const maxLineLen = Math.max(...lines.map((l) => l.length), 40);
403
+ const boxWidth = Math.min(maxLineLen + 4, 80);
404
+ const langLabel = language ? chalk_1.default.cyan.bold(` ${language} `) : "";
405
+ const topBorder = chalk_1.default.gray("╭") + langLabel + chalk_1.default.gray("─".repeat(Math.max(0, boxWidth - language.length - 3))) + chalk_1.default.gray("╮");
406
+ const bottomBorder = chalk_1.default.gray("╰" + "─".repeat(boxWidth - 1) + "╯");
407
+ const formattedLines = lines.map((line) => {
408
+ const highlighted = highlightCodeLine(line);
409
+ return chalk_1.default.gray("│ ") + highlighted;
410
+ });
411
+ return [
412
+ "",
413
+ topBorder,
414
+ ...formattedLines,
415
+ bottomBorder,
416
+ "",
417
+ ].join("\n");
418
+ };
419
+ /**
420
+ * Format markdown text with colors for terminal display
421
+ */
422
+ const formatMarkdown = (text) => {
423
+ let result = text;
424
+ // Extract and format code blocks first (to avoid processing their content)
425
+ const codeBlocks = [];
426
+ let blockIndex = 0;
427
+ result = result.replace(/```(\w*)\n([\s\S]*?)```/g, (_, lang, code) => {
428
+ const placeholder = `__CODE_BLOCK_${blockIndex}__`;
429
+ codeBlocks.push({
430
+ placeholder,
431
+ formatted: formatCodeBlock(code.trimEnd(), lang || ""),
432
+ });
433
+ blockIndex++;
434
+ return placeholder;
435
+ });
436
+ // Format inline code
437
+ result = result.replace(/`([^`]+)`/g, (_, code) => {
438
+ return chalk_1.default.bgGray.white(` ${code} `);
439
+ });
440
+ // Format headers
441
+ result = result.replace(/^### (.+)$/gm, (_, text) => {
442
+ return chalk_1.default.cyan.bold(` ${text}`);
443
+ });
444
+ result = result.replace(/^## (.+)$/gm, (_, text) => {
445
+ return chalk_1.default.cyan.bold(` ${text}`);
446
+ });
447
+ result = result.replace(/^# (.+)$/gm, (_, text) => {
448
+ return chalk_1.default.cyan.bold.underline(text);
449
+ });
450
+ // Format bold text
451
+ result = result.replace(/\*\*([^*]+)\*\*/g, (_, text) => {
452
+ return chalk_1.default.bold(text);
453
+ });
454
+ // Format italic text
455
+ result = result.replace(/\*([^*]+)\*/g, (_, text) => {
456
+ return chalk_1.default.italic(text);
457
+ });
458
+ // Format bullet points
459
+ result = result.replace(/^(\s*)[-*] (.+)$/gm, (_, indent, text) => {
460
+ return indent + chalk_1.default.yellow("•") + " " + text;
461
+ });
462
+ // Format numbered lists
463
+ result = result.replace(/^(\s*)(\d+)\. (.+)$/gm, (_, indent, num, text) => {
464
+ return indent + chalk_1.default.yellow(num + ".") + " " + text;
465
+ });
466
+ // Format blockquotes
467
+ result = result.replace(/^> (.+)$/gm, (_, text) => {
468
+ return chalk_1.default.gray("│ ") + chalk_1.default.italic.gray(text);
469
+ });
470
+ // Format horizontal rules
471
+ result = result.replace(/^---+$/gm, () => {
472
+ return chalk_1.default.gray("─".repeat(50));
473
+ });
474
+ // Restore code blocks
475
+ for (const block of codeBlocks) {
476
+ result = result.replace(block.placeholder, block.formatted);
477
+ }
478
+ return result;
479
+ };
480
+ exports.formatMarkdown = formatMarkdown;
481
+ /**
482
+ * Stream formatter for real-time markdown rendering
483
+ * Handles partial chunks and code block detection
484
+ */
485
+ class StreamFormatter {
486
+ constructor() {
487
+ this.buffer = "";
488
+ this.inCodeBlock = false;
489
+ this.codeBlockLang = "";
490
+ this.codeBlockContent = "";
491
+ }
492
+ /**
493
+ * Process a chunk of streaming text and return formatted output
494
+ */
495
+ processChunk(chunk) {
496
+ this.buffer += chunk;
497
+ let output = "";
498
+ // Process complete lines
499
+ while (this.buffer.includes("\n")) {
500
+ const newlineIndex = this.buffer.indexOf("\n");
501
+ const line = this.buffer.slice(0, newlineIndex);
502
+ this.buffer = this.buffer.slice(newlineIndex + 1);
503
+ output += this.processLine(line) + "\n";
504
+ }
505
+ return output;
506
+ }
507
+ /**
508
+ * Flush remaining buffer content
509
+ */
510
+ flush() {
511
+ if (this.buffer.length > 0) {
512
+ const remaining = this.processLine(this.buffer);
513
+ this.buffer = "";
514
+ return remaining;
515
+ }
516
+ return "";
517
+ }
518
+ processLine(line) {
519
+ // Check for code block start
520
+ if (line.startsWith("```") && !this.inCodeBlock) {
521
+ this.inCodeBlock = true;
522
+ this.codeBlockLang = line.slice(3).trim();
523
+ this.codeBlockContent = "";
524
+ return ""; // Don't output yet
525
+ }
526
+ // Check for code block end
527
+ if (line === "```" && this.inCodeBlock) {
528
+ this.inCodeBlock = false;
529
+ const formatted = formatCodeBlock(this.codeBlockContent.trimEnd(), this.codeBlockLang);
530
+ this.codeBlockContent = "";
531
+ this.codeBlockLang = "";
532
+ return formatted;
533
+ }
534
+ // Inside code block - accumulate
535
+ if (this.inCodeBlock) {
536
+ this.codeBlockContent += line + "\n";
537
+ return ""; // Don't output yet
538
+ }
539
+ // Regular line - format it
540
+ return this.formatLine(line);
541
+ }
542
+ formatLine(line) {
543
+ // Format inline code
544
+ let result = line.replace(/`([^`]+)`/g, (_, code) => {
545
+ return chalk_1.default.bgGray.white(` ${code} `);
546
+ });
547
+ // Format headers
548
+ if (result.startsWith("### ")) {
549
+ return chalk_1.default.cyan.bold(" " + result.slice(4));
550
+ }
551
+ if (result.startsWith("## ")) {
552
+ return chalk_1.default.cyan.bold(" " + result.slice(3));
553
+ }
554
+ if (result.startsWith("# ")) {
555
+ return chalk_1.default.cyan.bold.underline(result.slice(2));
556
+ }
557
+ // Format bold
558
+ result = result.replace(/\*\*([^*]+)\*\*/g, (_, text) => chalk_1.default.bold(text));
559
+ // Format italic
560
+ result = result.replace(/\*([^*]+)\*/g, (_, text) => chalk_1.default.italic(text));
561
+ // Format bullets
562
+ if (/^\s*[-*] /.test(result)) {
563
+ result = result.replace(/^(\s*)[-*] /, (_, indent) => indent + chalk_1.default.yellow("•") + " ");
564
+ }
565
+ // Format numbered lists
566
+ result = result.replace(/^(\s*)(\d+)\. /, (_, indent, num) => indent + chalk_1.default.yellow(num + ".") + " ");
567
+ // Format blockquotes
568
+ if (result.startsWith("> ")) {
569
+ return chalk_1.default.gray("│ ") + chalk_1.default.italic.gray(result.slice(2));
570
+ }
571
+ // Format horizontal rules
572
+ if (/^---+$/.test(result)) {
573
+ return chalk_1.default.gray("─".repeat(50));
574
+ }
575
+ return result;
576
+ }
577
+ }
578
+ exports.StreamFormatter = StreamFormatter;