berget 2.0.4 → 2.0.6

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/index.js CHANGED
@@ -31,15 +31,9 @@ Version: ${package_json_1.version}`)
31
31
  // Check for .bergetconfig if not running a command
32
32
  if (process.argv.length <= 2) {
33
33
  (0, config_checker_1.checkBergetConfig)();
34
- // Show helpful welcome message
35
- console.log(chalk_1.default.blue('\nWelcome to the Berget CLI!'));
36
- console.log(chalk_1.default.blue('Common commands:'));
37
- console.log(chalk_1.default.blue(` ${chalk_1.default.bold('berget auth login')} - Log in to Berget`));
38
- console.log(chalk_1.default.blue(` ${chalk_1.default.bold('berget models list')} - List available AI models`));
39
- console.log(chalk_1.default.blue(` ${chalk_1.default.bold('berget chat run')} - Start a chat session`));
40
- console.log(chalk_1.default.blue(` ${chalk_1.default.bold('berget code init')} - Initialize AI coding assistant`));
41
- console.log(chalk_1.default.blue(` ${chalk_1.default.bold('berget api-keys list')} - List your API keys`));
42
- console.log(chalk_1.default.blue(`\nRun ${chalk_1.default.bold('berget --help')} for a complete list of commands.`));
34
+ // Show the full help (including logo and commands)
35
+ commander_1.program.outputHelp();
36
+ process.exit(0);
43
37
  }
44
38
  // Add helpful suggestions for common command mistakes
45
39
  const commonMistakes = {
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "berget",
3
- "version": "2.0.4",
3
+ "version": "2.0.6",
4
4
  "main": "dist/index.js",
5
5
  "bin": {
6
6
  "berget": "dist/index.js"
@@ -17,6 +17,41 @@ const chalk_1 = __importDefault(require("chalk"));
17
17
  const api_key_service_1 = require("../services/api-key-service");
18
18
  const error_handler_1 = require("../utils/error-handler");
19
19
  const default_api_key_1 = require("../utils/default-api-key");
20
+ // Helper functions for better date formatting
21
+ function formatDate(dateString) {
22
+ const date = new Date(dateString);
23
+ const now = new Date();
24
+ const diffTime = Math.abs(now.getTime() - date.getTime());
25
+ const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
26
+ if (diffDays === 0)
27
+ return chalk_1.default.green('Today');
28
+ if (diffDays === 1)
29
+ return chalk_1.default.yellow('Yesterday');
30
+ if (diffDays < 7)
31
+ return chalk_1.default.yellow(`${diffDays} days ago`);
32
+ if (diffDays < 30)
33
+ return chalk_1.default.blue(`${Math.floor(diffDays / 7)} weeks ago`);
34
+ if (diffDays < 365)
35
+ return chalk_1.default.magenta(`${Math.floor(diffDays / 30)} months ago`);
36
+ return chalk_1.default.gray(`${Math.floor(diffDays / 365)} years ago`);
37
+ }
38
+ function formatLastUsed(dateString) {
39
+ const date = new Date(dateString);
40
+ const now = new Date();
41
+ const diffTime = Math.abs(now.getTime() - date.getTime());
42
+ const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
43
+ if (diffDays === 0)
44
+ return chalk_1.default.green('Today');
45
+ if (diffDays === 1)
46
+ return chalk_1.default.yellow('Yesterday');
47
+ if (diffDays < 7)
48
+ return chalk_1.default.yellow(`${diffDays} days ago`);
49
+ if (diffDays < 30)
50
+ return chalk_1.default.blue(`${Math.floor(diffDays / 7)} weeks ago`);
51
+ if (diffDays < 365)
52
+ return chalk_1.default.magenta(`${Math.floor(diffDays / 30)} months ago`);
53
+ return chalk_1.default.gray(`${Math.floor(diffDays / 365)} years ago`);
54
+ }
20
55
  /**
21
56
  * Register API key commands
22
57
  */
@@ -35,34 +70,46 @@ function registerApiKeyCommands(program) {
35
70
  console.log(chalk_1.default.yellow('No API keys found. Create one with `berget api-key create --name <name>`'));
36
71
  return;
37
72
  }
38
- console.log(chalk_1.default.bold('Your API keys:'));
73
+ console.log(chalk_1.default.bold('šŸ”‘ Your API keys:'));
39
74
  console.log('');
40
- // Create a table-like format with headers
41
- console.log(chalk_1.default.dim('ID (8)'.padEnd(8)) +
42
- chalk_1.default.dim('NAME'.padEnd(25)) +
43
- chalk_1.default.dim('PREFIX'.padEnd(12)) +
44
- chalk_1.default.dim('STATUS'.padEnd(12)) +
45
- chalk_1.default.dim('CREATED'.padEnd(12)) +
75
+ // Create a more readable table with better spacing and colors
76
+ const idWidth = 10;
77
+ const nameWidth = 30;
78
+ const prefixWidth = 20;
79
+ const statusWidth = 12;
80
+ const createdWidth = 12;
81
+ const usedWidth = 15;
82
+ console.log(chalk_1.default.dim('ID'.padEnd(idWidth)) +
83
+ chalk_1.default.dim('NAME'.padEnd(nameWidth)) +
84
+ chalk_1.default.dim('PREFIX'.padEnd(prefixWidth)) +
85
+ chalk_1.default.dim('STATUS'.padEnd(statusWidth)) +
86
+ chalk_1.default.dim('CREATED'.padEnd(createdWidth)) +
46
87
  chalk_1.default.dim('LAST USED'));
47
- console.log(chalk_1.default.dim('─'.repeat(85)));
88
+ console.log(chalk_1.default.dim('─'.repeat(idWidth + nameWidth + prefixWidth + statusWidth + createdWidth + usedWidth + 5)));
48
89
  keys.forEach((key) => {
49
90
  const lastUsed = key.lastUsed
50
- ? key.lastUsed.substring(0, 10)
51
- : 'Never';
91
+ ? formatLastUsed(key.lastUsed)
92
+ : chalk_1.default.yellow('Never used');
52
93
  const status = key.active
53
94
  ? chalk_1.default.green('ā— Active')
54
95
  : chalk_1.default.red('ā— Inactive');
55
96
  // Show only first 8 characters of ID for easier reading
56
- const shortId = String(key.id).substring(0, 8);
57
- // Format the prefix to ensure it's not too long
58
- const prefixStr = key.prefix.length > 12
59
- ? key.prefix.substring(0, 12) + '...'
60
- : key.prefix;
61
- console.log(shortId.padEnd(8) +
62
- key.name.padEnd(25) +
63
- prefixStr.padEnd(15) +
64
- status.padEnd(12) +
65
- key.created.substring(0, 10).padEnd(12) +
97
+ const shortId = chalk_1.default.cyan(String(key.id).substring(0, 8));
98
+ // Format the prefix with better truncation
99
+ const prefixStr = key.prefix.length > prefixWidth
100
+ ? key.prefix.substring(0, prefixWidth - 3) + '...'
101
+ : chalk_1.default.gray(key.prefix);
102
+ // Truncate name if too long
103
+ const nameStr = key.name.length > nameWidth
104
+ ? key.name.substring(0, nameWidth - 3) + '...'
105
+ : key.name;
106
+ // Format created date
107
+ const createdDate = formatDate(key.created);
108
+ console.log(shortId.padEnd(idWidth) +
109
+ nameStr.padEnd(nameWidth) +
110
+ prefixStr.padEnd(prefixWidth) +
111
+ status.padEnd(statusWidth) +
112
+ createdDate.padEnd(createdWidth) +
66
113
  lastUsed);
67
114
  });
68
115
  console.log('');
@@ -56,15 +56,15 @@ function registerChatCommands(program) {
56
56
  chat
57
57
  .command(command_structure_1.SUBCOMMANDS.CHAT.RUN)
58
58
  .description('Run a chat session with a specified model')
59
- .argument('[model]', 'Model to use (default: openai/gpt-oss)')
60
59
  .argument('[message]', 'Message to send directly (skips interactive mode)')
61
- .option('-s, --system <message>', 'System message')
60
+ .option('-m, --model <model>', 'Model to use (default: deepseek-r1)')
61
+ .option('--no-reasoning', 'Disable reasoning mode (adds </think> to messages)')
62
62
  .option('-t, --temperature <temp>', 'Temperature (0-1)', parseFloat)
63
- .option('-m, --max-tokens <tokens>', 'Maximum tokens to generate', parseInt)
63
+ .option('--max-tokens <tokens>', 'Maximum tokens to generate', parseInt)
64
64
  .option('-k, --api-key <key>', 'API key to use for this chat session')
65
65
  .option('--api-key-id <id>', 'ID of the API key to use from your saved keys')
66
66
  .option('--no-stream', 'Disable streaming (streaming is enabled by default)')
67
- .action((model, message, options) => __awaiter(this, void 0, void 0, function* () {
67
+ .action((message, options) => __awaiter(this, void 0, void 0, function* () {
68
68
  var _a, e_1, _b, _c;
69
69
  try {
70
70
  const chatService = chat_service_1.ChatService.getInstance();
@@ -226,7 +226,7 @@ function registerChatCommands(program) {
226
226
  try {
227
227
  // Call the API
228
228
  const completionOptions = {
229
- model: model || 'openai/gpt-oss',
229
+ model: options.model || 'openai/gpt-oss',
230
230
  messages: messages,
231
231
  temperature: options.temperature !== undefined ? options.temperature : 0.7,
232
232
  max_tokens: options.maxTokens || 4096,
@@ -334,7 +334,7 @@ function registerChatCommands(program) {
334
334
  try {
335
335
  // Call the API
336
336
  const completionOptions = {
337
- model: model || 'openai/gpt-oss',
337
+ model: options.model || 'openai/gpt-oss',
338
338
  messages: messages,
339
339
  temperature: options.temperature !== undefined ? options.temperature : 0.7,
340
340
  max_tokens: options.maxTokens || 4096,
@@ -9,44 +9,120 @@ const chalk_1 = __importDefault(require("chalk"));
9
9
  * Formats and prints error messages in a consistent way
10
10
  */
11
11
  function handleError(message, error) {
12
- console.error(chalk_1.default.red(`Error: ${message}`));
12
+ console.error(chalk_1.default.red(`āŒ Error: ${message}`));
13
+ let errorDetails = '';
14
+ let errorCode = '';
15
+ let errorType = '';
13
16
  // If the error is a string (like JSON.stringify(error))
14
17
  if (typeof error === 'string') {
15
18
  try {
16
19
  // Try to parse it as JSON
17
20
  const parsedError = JSON.parse(error);
18
21
  if (parsedError.error) {
19
- console.error(chalk_1.default.dim(`Details: ${parsedError.error}`));
20
- if (parsedError.code) {
21
- console.error(chalk_1.default.dim(`Code: ${parsedError.code}`));
22
- }
22
+ errorDetails = parsedError.error.message || parsedError.error;
23
+ errorCode = parsedError.error.code || parsedError.code;
24
+ errorType = parsedError.error.type || '';
23
25
  }
24
26
  else {
25
- console.error(chalk_1.default.dim(`Details: ${error}`));
27
+ errorDetails = error;
26
28
  }
27
29
  }
28
30
  catch (_a) {
29
31
  // If it's not valid JSON, just print the string
30
- console.error(chalk_1.default.dim(`Details: ${error}`));
32
+ errorDetails = error;
31
33
  }
32
34
  }
33
35
  else if (error && error.message) {
34
36
  // If it's an Error object
35
- console.error(chalk_1.default.dim(`Details: ${error.message}`));
36
- }
37
- // Check for authentication errors
38
- if ((typeof error === 'string' &&
39
- (error.includes('Unauthorized') ||
40
- error.includes('Authentication failed'))) ||
41
- (error &&
42
- error.message &&
43
- (error.message.includes('Unauthorized') ||
44
- error.message.includes('Authentication failed'))) ||
45
- (error &&
46
- error.code &&
47
- (error.code === 401 || error.code === 'AUTH_FAILED'))) {
48
- console.error(chalk_1.default.yellow('\nYou need to be logged in to use this command.'));
49
- console.error(chalk_1.default.yellow('Run `berget auth login` to authenticate.'));
37
+ errorDetails = error.message;
38
+ errorCode = error.code;
39
+ errorType = error.type;
50
40
  }
41
+ // Print error details
42
+ if (errorDetails) {
43
+ console.error(chalk_1.default.dim(`šŸ“ Details: ${errorDetails}`));
44
+ }
45
+ if (errorCode) {
46
+ console.error(chalk_1.default.dim(`šŸ”¢ Code: ${errorCode}`));
47
+ }
48
+ // Provide helpful troubleshooting based on error type
49
+ provideTroubleshootingTips(errorType, errorCode, errorDetails);
51
50
  }
52
51
  exports.handleError = handleError;
52
+ /**
53
+ * Provides helpful troubleshooting tips based on error type
54
+ */
55
+ function provideTroubleshootingTips(errorType, errorCode, errorDetails) {
56
+ console.error(chalk_1.default.blue('\nšŸ’” Troubleshooting tips:'));
57
+ // Authentication errors
58
+ if (errorType === 'authentication_error' ||
59
+ errorCode === 'AUTH_FAILED' ||
60
+ (errorDetails === null || errorDetails === void 0 ? void 0 : errorDetails.includes('Unauthorized')) ||
61
+ (errorDetails === null || errorDetails === void 0 ? void 0 : errorDetails.includes('Authentication failed'))) {
62
+ console.error(chalk_1.default.yellow(' šŸ” Authentication issue detected:'));
63
+ console.error(chalk_1.default.white(' • Run `berget auth login` to log in'));
64
+ console.error(chalk_1.default.white(' • Check if your session has expired'));
65
+ console.error(chalk_1.default.white(' • Verify you have the correct permissions'));
66
+ }
67
+ // Network/connection errors
68
+ if ((errorDetails === null || errorDetails === void 0 ? void 0 : errorDetails.includes('fetch failed')) ||
69
+ (errorDetails === null || errorDetails === void 0 ? void 0 : errorDetails.includes('ECONNREFUSED')) ||
70
+ (errorDetails === null || errorDetails === void 0 ? void 0 : errorDetails.includes('ENOTFOUND')) ||
71
+ (errorDetails === null || errorDetails === void 0 ? void 0 : errorDetails.includes('network'))) {
72
+ console.error(chalk_1.default.yellow(' 🌐 Network issue detected:'));
73
+ console.error(chalk_1.default.white(' • Check your internet connection'));
74
+ console.error(chalk_1.default.white(' • Verify you can reach api.berget.ai'));
75
+ console.error(chalk_1.default.white(' • Try again in a few minutes'));
76
+ console.error(chalk_1.default.white(' • Check if any firewall is blocking the request'));
77
+ }
78
+ // API key errors
79
+ if ((errorCode === null || errorCode === void 0 ? void 0 : errorCode.includes('API_KEY')) ||
80
+ (errorDetails === null || errorDetails === void 0 ? void 0 : errorDetails.includes('API key')) ||
81
+ errorType === 'invalid_request_error') {
82
+ console.error(chalk_1.default.yellow(' šŸ”‘ API key issue detected:'));
83
+ console.error(chalk_1.default.white(' • Run `berget api-keys list` to check your keys'));
84
+ console.error(chalk_1.default.white(' • Create a new key with `berget api-keys create --name "My Key"`'));
85
+ console.error(chalk_1.default.white(' • Set a default key with `berget api-keys set-default <id>`'));
86
+ console.error(chalk_1.default.white(' • Check if your API key has expired'));
87
+ }
88
+ // Rate limiting
89
+ if (errorCode === 'RATE_LIMIT_EXCEEDED' ||
90
+ (errorDetails === null || errorDetails === void 0 ? void 0 : errorDetails.includes('rate limit')) ||
91
+ (errorDetails === null || errorDetails === void 0 ? void 0 : errorDetails.includes('too many requests'))) {
92
+ console.error(chalk_1.default.yellow(' ā±ļø Rate limit exceeded:'));
93
+ console.error(chalk_1.default.white(' • Wait a few minutes before trying again'));
94
+ console.error(chalk_1.default.white(' • Consider upgrading your plan for higher limits'));
95
+ console.error(chalk_1.default.white(' • Use `berget billing get-usage` to check your usage'));
96
+ }
97
+ // Server errors
98
+ if ((errorCode === null || errorCode === void 0 ? void 0 : errorCode.includes('SERVER_ERROR')) ||
99
+ errorType === 'server_error' ||
100
+ (errorCode && parseInt(errorCode) >= 500)) {
101
+ console.error(chalk_1.default.yellow(' šŸ–„ļø Server issue detected:'));
102
+ console.error(chalk_1.default.white(' • This is a temporary problem on our end'));
103
+ console.error(chalk_1.default.white(' • Try again in a few minutes'));
104
+ console.error(chalk_1.default.white(' • Check status.berget.ai for service status'));
105
+ console.error(chalk_1.default.white(' • Contact support if the problem persists'));
106
+ }
107
+ // Cluster errors
108
+ if ((errorCode === null || errorCode === void 0 ? void 0 : errorCode.includes('CLUSTERS')) ||
109
+ (errorDetails === null || errorDetails === void 0 ? void 0 : errorDetails.includes('cluster'))) {
110
+ console.error(chalk_1.default.yellow(' šŸ—ļø Cluster issue detected:'));
111
+ console.error(chalk_1.default.white(' • Clusters may be temporarily unavailable'));
112
+ console.error(chalk_1.default.white(' • Try again later or contact support'));
113
+ console.error(chalk_1.default.white(' • Check your cluster permissions'));
114
+ }
115
+ // Generic fallback
116
+ if (!(errorType === null || errorType === void 0 ? void 0 : errorType.includes('authentication')) &&
117
+ !(errorDetails === null || errorDetails === void 0 ? void 0 : errorDetails.includes('fetch failed')) &&
118
+ !(errorCode === null || errorCode === void 0 ? void 0 : errorCode.includes('API_KEY')) &&
119
+ !(errorCode === null || errorCode === void 0 ? void 0 : errorCode.includes('RATE_LIMIT')) &&
120
+ !(errorCode === null || errorCode === void 0 ? void 0 : errorCode.includes('SERVER_ERROR')) &&
121
+ !(errorCode === null || errorCode === void 0 ? void 0 : errorCode.includes('CLUSTERS'))) {
122
+ console.error(chalk_1.default.yellow(' ā“ General issue:'));
123
+ console.error(chalk_1.default.white(' • Try running the command with --debug for more info'));
124
+ console.error(chalk_1.default.white(' • Check your configuration with `berget auth whoami`'));
125
+ console.error(chalk_1.default.white(' • Contact support if the problem persists'));
126
+ }
127
+ console.error(chalk_1.default.dim('\nNeed more help? Visit https://docs.berget.ai or contact support@berget.ai'));
128
+ }
package/index.ts CHANGED
@@ -33,37 +33,9 @@ registerCommands(program)
33
33
  if (process.argv.length <= 2) {
34
34
  checkBergetConfig()
35
35
 
36
- // Show helpful welcome message
37
- console.log(chalk.blue('\nWelcome to the Berget CLI!'))
38
- console.log(chalk.blue('Common commands:'))
39
- console.log(
40
- chalk.blue(` ${chalk.bold('berget auth login')} - Log in to Berget`)
41
- )
42
- console.log(
43
- chalk.blue(
44
- ` ${chalk.bold('berget models list')} - List available AI models`
45
- )
46
- )
47
- console.log(
48
- chalk.blue(
49
- ` ${chalk.bold('berget chat run')} - Start a chat session`
50
- )
51
- )
52
- console.log(
53
- chalk.blue(
54
- ` ${chalk.bold(
55
- 'berget code init'
56
- )} - Initialize AI coding assistant`
57
- )
58
- )
59
- console.log(
60
- chalk.blue(` ${chalk.bold('berget api-keys list')} - List your API keys`)
61
- )
62
- console.log(
63
- chalk.blue(
64
- `\nRun ${chalk.bold('berget --help')} for a complete list of commands.`
65
- )
66
- )
36
+ // Show the full help (including logo and commands)
37
+ program.outputHelp()
38
+ process.exit(0)
67
39
  }
68
40
 
69
41
  // Add helpful suggestions for common command mistakes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "berget",
3
- "version": "2.0.4",
3
+ "version": "2.0.6",
4
4
  "main": "dist/index.js",
5
5
  "bin": {
6
6
  "berget": "dist/index.js"
@@ -4,6 +4,35 @@ import { ApiKeyService, ApiKey } from '../services/api-key-service'
4
4
  import { handleError } from '../utils/error-handler'
5
5
  import { DefaultApiKeyManager } from '../utils/default-api-key'
6
6
 
7
+ // Helper functions for better date formatting
8
+ function formatDate(dateString: string): string {
9
+ const date = new Date(dateString)
10
+ const now = new Date()
11
+ const diffTime = Math.abs(now.getTime() - date.getTime())
12
+ const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24))
13
+
14
+ if (diffDays === 0) return chalk.green('Today')
15
+ if (diffDays === 1) return chalk.yellow('Yesterday')
16
+ if (diffDays < 7) return chalk.yellow(`${diffDays} days ago`)
17
+ if (diffDays < 30) return chalk.blue(`${Math.floor(diffDays / 7)} weeks ago`)
18
+ if (diffDays < 365) return chalk.magenta(`${Math.floor(diffDays / 30)} months ago`)
19
+ return chalk.gray(`${Math.floor(diffDays / 365)} years ago`)
20
+ }
21
+
22
+ function formatLastUsed(dateString: string): string {
23
+ const date = new Date(dateString)
24
+ const now = new Date()
25
+ const diffTime = Math.abs(now.getTime() - date.getTime())
26
+ const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24))
27
+
28
+ if (diffDays === 0) return chalk.green('Today')
29
+ if (diffDays === 1) return chalk.yellow('Yesterday')
30
+ if (diffDays < 7) return chalk.yellow(`${diffDays} days ago`)
31
+ if (diffDays < 30) return chalk.blue(`${Math.floor(diffDays / 7)} weeks ago`)
32
+ if (diffDays < 365) return chalk.magenta(`${Math.floor(diffDays / 30)} months ago`)
33
+ return chalk.gray(`${Math.floor(diffDays / 365)} years ago`)
34
+ }
35
+
7
36
  /**
8
37
  * Register API key commands
9
38
  */
@@ -29,45 +58,59 @@ export function registerApiKeyCommands(program: Command): void {
29
58
  return
30
59
  }
31
60
 
32
- console.log(chalk.bold('Your API keys:'))
61
+ console.log(chalk.bold('šŸ”‘ Your API keys:'))
33
62
  console.log('')
34
63
 
35
- // Create a table-like format with headers
64
+ // Create a more readable table with better spacing and colors
65
+ const idWidth = 10
66
+ const nameWidth = 30
67
+ const prefixWidth = 20
68
+ const statusWidth = 12
69
+ const createdWidth = 12
70
+ const usedWidth = 15
71
+
36
72
  console.log(
37
- chalk.dim('ID (8)'.padEnd(8)) +
38
- chalk.dim('NAME'.padEnd(25)) +
39
- chalk.dim('PREFIX'.padEnd(12)) +
40
- chalk.dim('STATUS'.padEnd(12)) +
41
- chalk.dim('CREATED'.padEnd(12)) +
42
- chalk.dim('LAST USED'),
73
+ chalk.dim('ID'.padEnd(idWidth)) +
74
+ chalk.dim('NAME'.padEnd(nameWidth)) +
75
+ chalk.dim('PREFIX'.padEnd(prefixWidth)) +
76
+ chalk.dim('STATUS'.padEnd(statusWidth)) +
77
+ chalk.dim('CREATED'.padEnd(createdWidth)) +
78
+ chalk.dim('LAST USED')
43
79
  )
44
80
 
45
- console.log(chalk.dim('─'.repeat(85)))
81
+ console.log(chalk.dim('─'.repeat(idWidth + nameWidth + prefixWidth + statusWidth + createdWidth + usedWidth + 5)))
46
82
 
47
83
  keys.forEach((key: ApiKey) => {
48
84
  const lastUsed = key.lastUsed
49
- ? key.lastUsed.substring(0, 10)
50
- : 'Never'
85
+ ? formatLastUsed(key.lastUsed)
86
+ : chalk.yellow('Never used')
51
87
  const status = key.active
52
88
  ? chalk.green('ā— Active')
53
89
  : chalk.red('ā— Inactive')
54
90
 
55
91
  // Show only first 8 characters of ID for easier reading
56
- const shortId = String(key.id).substring(0, 8)
92
+ const shortId = chalk.cyan(String(key.id).substring(0, 8))
93
+
94
+ // Format the prefix with better truncation
95
+ const prefixStr = key.prefix.length > prefixWidth
96
+ ? key.prefix.substring(0, prefixWidth - 3) + '...'
97
+ : chalk.gray(key.prefix)
98
+
99
+ // Truncate name if too long
100
+ const nameStr = key.name.length > nameWidth
101
+ ? key.name.substring(0, nameWidth - 3) + '...'
102
+ : key.name
57
103
 
58
- // Format the prefix to ensure it's not too long
59
- const prefixStr =
60
- key.prefix.length > 12
61
- ? key.prefix.substring(0, 12) + '...'
62
- : key.prefix
104
+ // Format created date
105
+ const createdDate = formatDate(key.created)
63
106
 
64
107
  console.log(
65
- shortId.padEnd(8) +
66
- key.name.padEnd(25) +
67
- prefixStr.padEnd(15) +
68
- status.padEnd(12) +
69
- key.created.substring(0, 10).padEnd(12) +
70
- lastUsed,
108
+ shortId.padEnd(idWidth) +
109
+ nameStr.padEnd(nameWidth) +
110
+ prefixStr.padEnd(prefixWidth) +
111
+ status.padEnd(statusWidth) +
112
+ createdDate.padEnd(createdWidth) +
113
+ lastUsed
71
114
  )
72
115
  })
73
116
 
@@ -41,11 +41,11 @@ export function registerChatCommands(program: Command): void {
41
41
  chat
42
42
  .command(SUBCOMMANDS.CHAT.RUN)
43
43
  .description('Run a chat session with a specified model')
44
- .argument('[model]', 'Model to use (default: openai/gpt-oss)')
45
44
  .argument('[message]', 'Message to send directly (skips interactive mode)')
46
- .option('-s, --system <message>', 'System message')
45
+ .option('-m, --model <model>', 'Model to use (default: deepseek-r1)')
46
+ .option('--no-reasoning', 'Disable reasoning mode (adds </think> to messages)')
47
47
  .option('-t, --temperature <temp>', 'Temperature (0-1)', parseFloat)
48
- .option('-m, --max-tokens <tokens>', 'Maximum tokens to generate', parseInt)
48
+ .option('--max-tokens <tokens>', 'Maximum tokens to generate', parseInt)
49
49
  .option('-k, --api-key <key>', 'API key to use for this chat session')
50
50
  .option(
51
51
  '--api-key-id <id>',
@@ -55,7 +55,7 @@ export function registerChatCommands(program: Command): void {
55
55
  '--no-stream',
56
56
  'Disable streaming (streaming is enabled by default)',
57
57
  )
58
- .action(async (model, message, options) => {
58
+ .action(async (message, options) => {
59
59
  try {
60
60
  const chatService = ChatService.getInstance()
61
61
 
@@ -279,7 +279,7 @@ export function registerChatCommands(program: Command): void {
279
279
  try {
280
280
  // Call the API
281
281
  const completionOptions: ChatCompletionOptions = {
282
- model: model || 'openai/gpt-oss',
282
+ model: options.model || 'openai/gpt-oss',
283
283
  messages: messages,
284
284
  temperature:
285
285
  options.temperature !== undefined ? options.temperature : 0.7,
@@ -415,7 +415,7 @@ export function registerChatCommands(program: Command): void {
415
415
  try {
416
416
  // Call the API
417
417
  const completionOptions: ChatCompletionOptions = {
418
- model: model || 'openai/gpt-oss',
418
+ model: options.model || 'openai/gpt-oss',
419
419
  messages: messages,
420
420
  temperature:
421
421
  options.temperature !== undefined ? options.temperature : 0.7,
@@ -4,7 +4,11 @@ import chalk from 'chalk'
4
4
  * Formats and prints error messages in a consistent way
5
5
  */
6
6
  export function handleError(message: string, error: any): void {
7
- console.error(chalk.red(`Error: ${message}`))
7
+ console.error(chalk.red(`āŒ Error: ${message}`))
8
+
9
+ let errorDetails = ''
10
+ let errorCode = ''
11
+ let errorType = ''
8
12
 
9
13
  // If the error is a string (like JSON.stringify(error))
10
14
  if (typeof error === 'string') {
@@ -12,38 +16,131 @@ export function handleError(message: string, error: any): void {
12
16
  // Try to parse it as JSON
13
17
  const parsedError = JSON.parse(error)
14
18
  if (parsedError.error) {
15
- console.error(chalk.dim(`Details: ${parsedError.error}`))
16
- if (parsedError.code) {
17
- console.error(chalk.dim(`Code: ${parsedError.code}`))
18
- }
19
+ errorDetails = parsedError.error.message || parsedError.error
20
+ errorCode = parsedError.error.code || parsedError.code
21
+ errorType = parsedError.error.type || ''
19
22
  } else {
20
- console.error(chalk.dim(`Details: ${error}`))
23
+ errorDetails = error
21
24
  }
22
25
  } catch {
23
26
  // If it's not valid JSON, just print the string
24
- console.error(chalk.dim(`Details: ${error}`))
27
+ errorDetails = error
25
28
  }
26
29
  } else if (error && error.message) {
27
30
  // If it's an Error object
28
- console.error(chalk.dim(`Details: ${error.message}`))
31
+ errorDetails = error.message
32
+ errorCode = error.code
33
+ errorType = error.type
34
+ }
35
+
36
+ // Print error details
37
+ if (errorDetails) {
38
+ console.error(chalk.dim(`šŸ“ Details: ${errorDetails}`))
39
+ }
40
+ if (errorCode) {
41
+ console.error(chalk.dim(`šŸ”¢ Code: ${errorCode}`))
42
+ }
43
+
44
+ // Provide helpful troubleshooting based on error type
45
+ provideTroubleshootingTips(errorType, errorCode, errorDetails)
46
+ }
47
+
48
+ /**
49
+ * Provides helpful troubleshooting tips based on error type
50
+ */
51
+ function provideTroubleshootingTips(errorType: string, errorCode: string, errorDetails: string): void {
52
+ console.error(chalk.blue('\nšŸ’” Troubleshooting tips:'))
53
+
54
+ // Authentication errors
55
+ if (
56
+ errorType === 'authentication_error' ||
57
+ errorCode === 'AUTH_FAILED' ||
58
+ errorDetails?.includes('Unauthorized') ||
59
+ errorDetails?.includes('Authentication failed')
60
+ ) {
61
+ console.error(chalk.yellow(' šŸ” Authentication issue detected:'))
62
+ console.error(chalk.white(' • Run `berget auth login` to log in'))
63
+ console.error(chalk.white(' • Check if your session has expired'))
64
+ console.error(chalk.white(' • Verify you have the correct permissions'))
65
+ }
66
+
67
+ // Network/connection errors
68
+ if (
69
+ errorDetails?.includes('fetch failed') ||
70
+ errorDetails?.includes('ECONNREFUSED') ||
71
+ errorDetails?.includes('ENOTFOUND') ||
72
+ errorDetails?.includes('network')
73
+ ) {
74
+ console.error(chalk.yellow(' 🌐 Network issue detected:'))
75
+ console.error(chalk.white(' • Check your internet connection'))
76
+ console.error(chalk.white(' • Verify you can reach api.berget.ai'))
77
+ console.error(chalk.white(' • Try again in a few minutes'))
78
+ console.error(chalk.white(' • Check if any firewall is blocking the request'))
29
79
  }
30
80
 
31
- // Check for authentication errors
81
+ // API key errors
32
82
  if (
33
- (typeof error === 'string' &&
34
- (error.includes('Unauthorized') ||
35
- error.includes('Authentication failed'))) ||
36
- (error &&
37
- error.message &&
38
- (error.message.includes('Unauthorized') ||
39
- error.message.includes('Authentication failed'))) ||
40
- (error &&
41
- error.code &&
42
- (error.code === 401 || error.code === 'AUTH_FAILED'))
83
+ errorCode?.includes('API_KEY') ||
84
+ errorDetails?.includes('API key') ||
85
+ errorType === 'invalid_request_error'
43
86
  ) {
44
- console.error(
45
- chalk.yellow('\nYou need to be logged in to use this command.'),
46
- )
47
- console.error(chalk.yellow('Run `berget auth login` to authenticate.'))
87
+ console.error(chalk.yellow(' šŸ”‘ API key issue detected:'))
88
+ console.error(chalk.white(' • Run `berget api-keys list` to check your keys'))
89
+ console.error(chalk.white(' • Create a new key with `berget api-keys create --name "My Key"`'))
90
+ console.error(chalk.white(' • Set a default key with `berget api-keys set-default <id>`'))
91
+ console.error(chalk.white(' • Check if your API key has expired'))
48
92
  }
93
+
94
+ // Rate limiting
95
+ if (
96
+ errorCode === 'RATE_LIMIT_EXCEEDED' ||
97
+ errorDetails?.includes('rate limit') ||
98
+ errorDetails?.includes('too many requests')
99
+ ) {
100
+ console.error(chalk.yellow(' ā±ļø Rate limit exceeded:'))
101
+ console.error(chalk.white(' • Wait a few minutes before trying again'))
102
+ console.error(chalk.white(' • Consider upgrading your plan for higher limits'))
103
+ console.error(chalk.white(' • Use `berget billing get-usage` to check your usage'))
104
+ }
105
+
106
+ // Server errors
107
+ if (
108
+ errorCode?.includes('SERVER_ERROR') ||
109
+ errorType === 'server_error' ||
110
+ (errorCode && parseInt(errorCode) >= 500)
111
+ ) {
112
+ console.error(chalk.yellow(' šŸ–„ļø Server issue detected:'))
113
+ console.error(chalk.white(' • This is a temporary problem on our end'))
114
+ console.error(chalk.white(' • Try again in a few minutes'))
115
+ console.error(chalk.white(' • Check status.berget.ai for service status'))
116
+ console.error(chalk.white(' • Contact support if the problem persists'))
117
+ }
118
+
119
+ // Cluster errors
120
+ if (
121
+ errorCode?.includes('CLUSTERS') ||
122
+ errorDetails?.includes('cluster')
123
+ ) {
124
+ console.error(chalk.yellow(' šŸ—ļø Cluster issue detected:'))
125
+ console.error(chalk.white(' • Clusters may be temporarily unavailable'))
126
+ console.error(chalk.white(' • Try again later or contact support'))
127
+ console.error(chalk.white(' • Check your cluster permissions'))
128
+ }
129
+
130
+ // Generic fallback
131
+ if (
132
+ !errorType?.includes('authentication') &&
133
+ !errorDetails?.includes('fetch failed') &&
134
+ !errorCode?.includes('API_KEY') &&
135
+ !errorCode?.includes('RATE_LIMIT') &&
136
+ !errorCode?.includes('SERVER_ERROR') &&
137
+ !errorCode?.includes('CLUSTERS')
138
+ ) {
139
+ console.error(chalk.yellow(' ā“ General issue:'))
140
+ console.error(chalk.white(' • Try running the command with --debug for more info'))
141
+ console.error(chalk.white(' • Check your configuration with `berget auth whoami`'))
142
+ console.error(chalk.white(' • Contact support if the problem persists'))
143
+ }
144
+
145
+ console.error(chalk.dim('\nNeed more help? Visit https://docs.berget.ai or contact support@berget.ai'))
49
146
  }