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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "berget",
3
- "version": "1.3.0",
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
- process.stdout.write(chalk_1.default.blue('Assistant: '));
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: ') + assistantMessage);
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(30)) +
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
- models.data.forEach((model) => {
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
- console.log(model.id.padEnd(30) +
349
- model.owned_by.padEnd(25) +
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 OWNED BY CAPABILITIES');
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.id.padEnd(24)} ${model.owned_by.padEnd(25)} ${capabilities.join(', ')}`);
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.0",
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",
@@ -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
- process.stdout.write(chalk.blue('Assistant: '))
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: ') + assistantMessage)
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(30)) +
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
- models.data.forEach((model: any) => {
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
- model.id.padEnd(30) +
457
- model.owned_by.padEnd(25) +
458
- capabilities.join(', ')
472
+ modelId +
473
+ capabilities.join(', ')
459
474
  )
460
475
  })
461
476
  } catch (error) {
@@ -36,10 +36,10 @@ export function registerModelCommands(program: Command): void {
36
36
 
37
37
  console.log('Available Models:')
38
38
  console.log(
39
- 'ID OWNED BY CAPABILITIES'
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.id.padEnd(24)} ${model.owned_by.padEnd(
53
- 25
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
+ }