berget 1.3.0 → 1.3.1
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/package.json +5 -1
- package/dist/src/commands/chat.js +19 -7
- package/dist/src/commands/models.js +2 -2
- package/dist/src/utils/markdown-renderer.js +73 -0
- package/package.json +5 -1
- package/src/commands/chat.ts +23 -8
- package/src/commands/models.ts +4 -4
- package/src/utils/markdown-renderer.ts +68 -0
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "berget",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"bin": {
|
|
6
6
|
"berget": "dist/index.js"
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
"license": "MIT",
|
|
20
20
|
"description": "This is a cli command for interacting with the AI infrastructure provider Berget",
|
|
21
21
|
"devDependencies": {
|
|
22
|
+
"@types/marked": "^5.0.2",
|
|
23
|
+
"@types/marked-terminal": "^6.1.1",
|
|
22
24
|
"@types/node": "^20.11.20",
|
|
23
25
|
"tsx": "^4.19.3",
|
|
24
26
|
"typescript": "^5.3.3"
|
|
@@ -27,6 +29,8 @@
|
|
|
27
29
|
"chalk": "^4.1.2",
|
|
28
30
|
"commander": "^12.0.0",
|
|
29
31
|
"fs-extra": "^11.3.0",
|
|
32
|
+
"marked": "^9.1.6",
|
|
33
|
+
"marked-terminal": "^6.2.0",
|
|
30
34
|
"open": "^9.1.0",
|
|
31
35
|
"openapi-fetch": "^0.9.1",
|
|
32
36
|
"openapi-typescript": "^6.7.4",
|
|
@@ -21,6 +21,7 @@ const api_key_service_1 = require("../services/api-key-service");
|
|
|
21
21
|
const auth_service_1 = require("../services/auth-service");
|
|
22
22
|
const error_handler_1 = require("../utils/error-handler");
|
|
23
23
|
const default_api_key_1 = require("../utils/default-api-key");
|
|
24
|
+
const markdown_renderer_1 = require("../utils/markdown-renderer");
|
|
24
25
|
/**
|
|
25
26
|
* Helper function to get user confirmation
|
|
26
27
|
*/
|
|
@@ -214,7 +215,9 @@ function registerChatCommands(program) {
|
|
|
214
215
|
// Add streaming support
|
|
215
216
|
if (options.stream) {
|
|
216
217
|
let assistantResponse = '';
|
|
217
|
-
|
|
218
|
+
console.log(chalk_1.default.blue('Assistant: '));
|
|
219
|
+
// For streaming, we'll collect the response and render it at the end
|
|
220
|
+
// since markdown needs the complete text to render properly
|
|
218
221
|
completionOptions.onChunk = (chunk) => {
|
|
219
222
|
if (chunk.choices && chunk.choices[0] && chunk.choices[0].delta && chunk.choices[0].delta.content) {
|
|
220
223
|
const content = chunk.choices[0].delta.content;
|
|
@@ -256,7 +259,14 @@ function registerChatCommands(program) {
|
|
|
256
259
|
content: assistantMessage,
|
|
257
260
|
});
|
|
258
261
|
// Display the response
|
|
259
|
-
console.log(chalk_1.default.blue('Assistant: ')
|
|
262
|
+
console.log(chalk_1.default.blue('Assistant: '));
|
|
263
|
+
// Check if the response contains markdown and render it if it does
|
|
264
|
+
if ((0, markdown_renderer_1.containsMarkdown)(assistantMessage)) {
|
|
265
|
+
console.log((0, markdown_renderer_1.renderMarkdown)(assistantMessage));
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
console.log(assistantMessage);
|
|
269
|
+
}
|
|
260
270
|
console.log(); // Empty line for better readability
|
|
261
271
|
// Continue the conversation
|
|
262
272
|
askQuestion();
|
|
@@ -333,11 +343,12 @@ function registerChatCommands(program) {
|
|
|
333
343
|
}
|
|
334
344
|
console.log(chalk_1.default.bold('Available Chat Models:'));
|
|
335
345
|
console.log(chalk_1.default.dim('─'.repeat(70)));
|
|
336
|
-
console.log(chalk_1.default.dim('MODEL ID'.padEnd(
|
|
337
|
-
chalk_1.default.dim('OWNER'.padEnd(25)) +
|
|
346
|
+
console.log(chalk_1.default.dim('MODEL ID'.padEnd(40)) +
|
|
338
347
|
chalk_1.default.dim('CAPABILITIES'));
|
|
339
348
|
console.log(chalk_1.default.dim('─'.repeat(70)));
|
|
340
|
-
|
|
349
|
+
// Filter to only show active models
|
|
350
|
+
const activeModels = models.data.filter((model) => model.active === true);
|
|
351
|
+
activeModels.forEach((model) => {
|
|
341
352
|
const capabilities = [];
|
|
342
353
|
if (model.capabilities.vision)
|
|
343
354
|
capabilities.push('vision');
|
|
@@ -345,8 +356,9 @@ function registerChatCommands(program) {
|
|
|
345
356
|
capabilities.push('function_calling');
|
|
346
357
|
if (model.capabilities.json_mode)
|
|
347
358
|
capabilities.push('json_mode');
|
|
348
|
-
|
|
349
|
-
|
|
359
|
+
// Format model ID in Huggingface compatible format (owner/model)
|
|
360
|
+
const modelId = `${model.owned_by.toLowerCase()}/${model.id}`.padEnd(40);
|
|
361
|
+
console.log(modelId +
|
|
350
362
|
capabilities.join(', '));
|
|
351
363
|
});
|
|
352
364
|
}
|
|
@@ -44,7 +44,7 @@ function registerModelCommands(program) {
|
|
|
44
44
|
throw new Error(JSON.stringify(error));
|
|
45
45
|
response = data;
|
|
46
46
|
console.log('Available Models:');
|
|
47
|
-
console.log('ID
|
|
47
|
+
console.log('ID OWNED BY CAPABILITIES');
|
|
48
48
|
// Ensure response has the expected structure
|
|
49
49
|
const modelData = response;
|
|
50
50
|
if (modelData.data) {
|
|
@@ -56,7 +56,7 @@ function registerModelCommands(program) {
|
|
|
56
56
|
capabilities.push('function_calling');
|
|
57
57
|
if (model.capabilities.json_mode)
|
|
58
58
|
capabilities.push('json_mode');
|
|
59
|
-
console.log(`${model.
|
|
59
|
+
console.log(`${model.root.padEnd(50)} ${model.owned_by.padEnd(24)} ${capabilities.join(', ')}`);
|
|
60
60
|
});
|
|
61
61
|
}
|
|
62
62
|
}
|
|
@@ -0,0 +1,73 @@
|
|
|
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.containsMarkdown = exports.renderMarkdown = void 0;
|
|
7
|
+
const marked_1 = require("marked");
|
|
8
|
+
const marked_terminal_1 = __importDefault(require("marked-terminal"));
|
|
9
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
10
|
+
// Configure marked to use the terminal renderer
|
|
11
|
+
marked_1.marked.setOptions({
|
|
12
|
+
renderer: new marked_terminal_1.default({
|
|
13
|
+
// Customize the rendering options
|
|
14
|
+
code: chalk_1.default.cyan,
|
|
15
|
+
blockquote: chalk_1.default.gray.italic,
|
|
16
|
+
table: chalk_1.default.white,
|
|
17
|
+
listitem: chalk_1.default.yellow,
|
|
18
|
+
strong: chalk_1.default.bold,
|
|
19
|
+
em: chalk_1.default.italic,
|
|
20
|
+
heading: chalk_1.default.bold.blueBright,
|
|
21
|
+
hr: chalk_1.default.gray,
|
|
22
|
+
link: chalk_1.default.blue.underline,
|
|
23
|
+
// Adjust the width to fit the terminal
|
|
24
|
+
width: process.stdout.columns || 80,
|
|
25
|
+
// Customize code block rendering
|
|
26
|
+
codespan: chalk_1.default.cyan
|
|
27
|
+
})
|
|
28
|
+
});
|
|
29
|
+
/**
|
|
30
|
+
* Render markdown text to terminal-friendly formatted text
|
|
31
|
+
* @param markdown The markdown text to render
|
|
32
|
+
* @returns Formatted text for terminal display
|
|
33
|
+
*/
|
|
34
|
+
function renderMarkdown(markdown) {
|
|
35
|
+
if (!markdown)
|
|
36
|
+
return '';
|
|
37
|
+
try {
|
|
38
|
+
// Convert markdown to terminal-friendly text
|
|
39
|
+
return (0, marked_1.marked)(markdown);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
// If rendering fails, return the original text
|
|
43
|
+
console.error(`Error rendering markdown: ${error}`);
|
|
44
|
+
return markdown;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
exports.renderMarkdown = renderMarkdown;
|
|
48
|
+
/**
|
|
49
|
+
* Check if a string contains markdown formatting
|
|
50
|
+
* @param text The text to check
|
|
51
|
+
* @returns True if the text contains markdown formatting
|
|
52
|
+
*/
|
|
53
|
+
function containsMarkdown(text) {
|
|
54
|
+
if (!text)
|
|
55
|
+
return false;
|
|
56
|
+
// Check for common markdown patterns
|
|
57
|
+
const markdownPatterns = [
|
|
58
|
+
/^#+\s+/m, // Headers
|
|
59
|
+
/\*\*.*?\*\*/, // Bold
|
|
60
|
+
/\*.*?\*/, // Italic
|
|
61
|
+
/`.*?`/, // Inline code
|
|
62
|
+
/```[\s\S]*?```/, // Code blocks
|
|
63
|
+
/\[.*?\]\(.*?\)/, // Links
|
|
64
|
+
/^\s*[-*+]\s+/m, // Lists
|
|
65
|
+
/^\s*\d+\.\s+/m, // Numbered lists
|
|
66
|
+
/^\s*>\s+/m, // Blockquotes
|
|
67
|
+
/\|.*\|.*\|/, // Tables
|
|
68
|
+
/^---+$/m, // Horizontal rules
|
|
69
|
+
/^===+$/m // Alternative headers
|
|
70
|
+
];
|
|
71
|
+
return markdownPatterns.some(pattern => pattern.test(text));
|
|
72
|
+
}
|
|
73
|
+
exports.containsMarkdown = containsMarkdown;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "berget",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"bin": {
|
|
6
6
|
"berget": "dist/index.js"
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
"license": "MIT",
|
|
20
20
|
"description": "This is a cli command for interacting with the AI infrastructure provider Berget",
|
|
21
21
|
"devDependencies": {
|
|
22
|
+
"@types/marked": "^5.0.2",
|
|
23
|
+
"@types/marked-terminal": "^6.1.1",
|
|
22
24
|
"@types/node": "^20.11.20",
|
|
23
25
|
"tsx": "^4.19.3",
|
|
24
26
|
"typescript": "^5.3.3"
|
|
@@ -27,6 +29,8 @@
|
|
|
27
29
|
"chalk": "^4.1.2",
|
|
28
30
|
"commander": "^12.0.0",
|
|
29
31
|
"fs-extra": "^11.3.0",
|
|
32
|
+
"marked": "^9.1.6",
|
|
33
|
+
"marked-terminal": "^6.2.0",
|
|
30
34
|
"open": "^9.1.0",
|
|
31
35
|
"openapi-fetch": "^0.9.1",
|
|
32
36
|
"openapi-typescript": "^6.7.4",
|
package/src/commands/chat.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { ApiKeyService } from '../services/api-key-service'
|
|
|
7
7
|
import { AuthService } from '../services/auth-service'
|
|
8
8
|
import { handleError } from '../utils/error-handler'
|
|
9
9
|
import { DefaultApiKeyManager } from '../utils/default-api-key'
|
|
10
|
+
import { renderMarkdown, containsMarkdown } from '../utils/markdown-renderer'
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Helper function to get user confirmation
|
|
@@ -272,8 +273,10 @@ export function registerChatCommands(program: Command): void {
|
|
|
272
273
|
// Add streaming support
|
|
273
274
|
if (options.stream) {
|
|
274
275
|
let assistantResponse = ''
|
|
275
|
-
|
|
276
|
+
console.log(chalk.blue('Assistant: '))
|
|
276
277
|
|
|
278
|
+
// For streaming, we'll collect the response and render it at the end
|
|
279
|
+
// since markdown needs the complete text to render properly
|
|
277
280
|
completionOptions.onChunk = (chunk: any) => {
|
|
278
281
|
if (chunk.choices && chunk.choices[0] && chunk.choices[0].delta && chunk.choices[0].delta.content) {
|
|
279
282
|
const content = chunk.choices[0].delta.content
|
|
@@ -332,7 +335,15 @@ export function registerChatCommands(program: Command): void {
|
|
|
332
335
|
})
|
|
333
336
|
|
|
334
337
|
// Display the response
|
|
335
|
-
console.log(chalk.blue('Assistant: ')
|
|
338
|
+
console.log(chalk.blue('Assistant: '))
|
|
339
|
+
|
|
340
|
+
// Check if the response contains markdown and render it if it does
|
|
341
|
+
if (containsMarkdown(assistantMessage)) {
|
|
342
|
+
console.log(renderMarkdown(assistantMessage))
|
|
343
|
+
} else {
|
|
344
|
+
console.log(assistantMessage)
|
|
345
|
+
}
|
|
346
|
+
|
|
336
347
|
console.log() // Empty line for better readability
|
|
337
348
|
|
|
338
349
|
// Continue the conversation
|
|
@@ -439,23 +450,27 @@ export function registerChatCommands(program: Command): void {
|
|
|
439
450
|
console.log(chalk.bold('Available Chat Models:'))
|
|
440
451
|
console.log(chalk.dim('─'.repeat(70)))
|
|
441
452
|
console.log(
|
|
442
|
-
chalk.dim('MODEL ID'.padEnd(
|
|
443
|
-
chalk.dim('OWNER'.padEnd(25)) +
|
|
453
|
+
chalk.dim('MODEL ID'.padEnd(40)) +
|
|
444
454
|
chalk.dim('CAPABILITIES')
|
|
445
455
|
)
|
|
446
456
|
console.log(chalk.dim('─'.repeat(70)))
|
|
447
457
|
|
|
448
|
-
|
|
458
|
+
// Filter to only show active models
|
|
459
|
+
const activeModels = models.data.filter((model: any) => model.active === true);
|
|
460
|
+
|
|
461
|
+
activeModels.forEach((model: any) => {
|
|
449
462
|
const capabilities = []
|
|
450
463
|
if (model.capabilities.vision) capabilities.push('vision')
|
|
451
464
|
if (model.capabilities.function_calling)
|
|
452
465
|
capabilities.push('function_calling')
|
|
453
466
|
if (model.capabilities.json_mode) capabilities.push('json_mode')
|
|
454
467
|
|
|
468
|
+
// Format model ID in Huggingface compatible format (owner/model)
|
|
469
|
+
const modelId = `${model.owned_by.toLowerCase()}/${model.id}`.padEnd(40)
|
|
470
|
+
|
|
455
471
|
console.log(
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
capabilities.join(', ')
|
|
472
|
+
modelId +
|
|
473
|
+
capabilities.join(', ')
|
|
459
474
|
)
|
|
460
475
|
})
|
|
461
476
|
} catch (error) {
|
package/src/commands/models.ts
CHANGED
|
@@ -36,10 +36,10 @@ export function registerModelCommands(program: Command): void {
|
|
|
36
36
|
|
|
37
37
|
console.log('Available Models:')
|
|
38
38
|
console.log(
|
|
39
|
-
'ID
|
|
39
|
+
'ID OWNED BY CAPABILITIES'
|
|
40
40
|
)
|
|
41
41
|
// Ensure response has the expected structure
|
|
42
|
-
const modelData = response as { data?: any[] }
|
|
42
|
+
const modelData = response as { data?: any[] }
|
|
43
43
|
if (modelData.data) {
|
|
44
44
|
modelData.data.forEach((model: any) => {
|
|
45
45
|
const capabilities = []
|
|
@@ -49,8 +49,8 @@ export function registerModelCommands(program: Command): void {
|
|
|
49
49
|
if (model.capabilities.json_mode) capabilities.push('json_mode')
|
|
50
50
|
|
|
51
51
|
console.log(
|
|
52
|
-
`${model.
|
|
53
|
-
|
|
52
|
+
`${model.root.padEnd(50)} ${model.owned_by.padEnd(
|
|
53
|
+
24
|
|
54
54
|
)} ${capabilities.join(', ')}`
|
|
55
55
|
)
|
|
56
56
|
})
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { marked } from 'marked'
|
|
2
|
+
import TerminalRenderer from 'marked-terminal'
|
|
3
|
+
import chalk from 'chalk'
|
|
4
|
+
|
|
5
|
+
// Configure marked to use the terminal renderer
|
|
6
|
+
marked.setOptions({
|
|
7
|
+
renderer: new TerminalRenderer({
|
|
8
|
+
// Customize the rendering options
|
|
9
|
+
code: chalk.cyan,
|
|
10
|
+
blockquote: chalk.gray.italic,
|
|
11
|
+
table: chalk.white,
|
|
12
|
+
listitem: chalk.yellow,
|
|
13
|
+
strong: chalk.bold,
|
|
14
|
+
em: chalk.italic,
|
|
15
|
+
heading: chalk.bold.blueBright,
|
|
16
|
+
hr: chalk.gray,
|
|
17
|
+
link: chalk.blue.underline,
|
|
18
|
+
// Adjust the width to fit the terminal
|
|
19
|
+
width: process.stdout.columns || 80,
|
|
20
|
+
// Customize code block rendering
|
|
21
|
+
codespan: chalk.cyan
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Render markdown text to terminal-friendly formatted text
|
|
27
|
+
* @param markdown The markdown text to render
|
|
28
|
+
* @returns Formatted text for terminal display
|
|
29
|
+
*/
|
|
30
|
+
export function renderMarkdown(markdown: string): string {
|
|
31
|
+
if (!markdown) return ''
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
// Convert markdown to terminal-friendly text
|
|
35
|
+
return marked(markdown)
|
|
36
|
+
} catch (error) {
|
|
37
|
+
// If rendering fails, return the original text
|
|
38
|
+
console.error(`Error rendering markdown: ${error}`)
|
|
39
|
+
return markdown
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Check if a string contains markdown formatting
|
|
45
|
+
* @param text The text to check
|
|
46
|
+
* @returns True if the text contains markdown formatting
|
|
47
|
+
*/
|
|
48
|
+
export function containsMarkdown(text: string): boolean {
|
|
49
|
+
if (!text) return false
|
|
50
|
+
|
|
51
|
+
// Check for common markdown patterns
|
|
52
|
+
const markdownPatterns = [
|
|
53
|
+
/^#+\s+/m, // Headers
|
|
54
|
+
/\*\*.*?\*\*/, // Bold
|
|
55
|
+
/\*.*?\*/, // Italic
|
|
56
|
+
/`.*?`/, // Inline code
|
|
57
|
+
/```[\s\S]*?```/, // Code blocks
|
|
58
|
+
/\[.*?\]\(.*?\)/, // Links
|
|
59
|
+
/^\s*[-*+]\s+/m, // Lists
|
|
60
|
+
/^\s*\d+\.\s+/m, // Numbered lists
|
|
61
|
+
/^\s*>\s+/m, // Blockquotes
|
|
62
|
+
/\|.*\|.*\|/, // Tables
|
|
63
|
+
/^---+$/m, // Horizontal rules
|
|
64
|
+
/^===+$/m // Alternative headers
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
return markdownPatterns.some(pattern => pattern.test(text))
|
|
68
|
+
}
|