berget 1.0.0 → 1.2.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.
Files changed (44) hide show
  1. package/README.md +92 -0
  2. package/dist/index.js +49 -467
  3. package/dist/package.json +35 -0
  4. package/dist/src/client.js +210 -102
  5. package/dist/src/commands/api-keys.js +277 -0
  6. package/dist/src/commands/auth.js +65 -0
  7. package/dist/src/commands/autocomplete.js +24 -0
  8. package/dist/src/commands/billing.js +53 -0
  9. package/dist/src/commands/chat.js +342 -0
  10. package/dist/src/commands/clusters.js +69 -0
  11. package/dist/src/commands/index.js +25 -0
  12. package/dist/src/commands/models.js +69 -0
  13. package/dist/src/commands/users.js +43 -0
  14. package/dist/src/constants/command-structure.js +14 -0
  15. package/dist/src/services/api-key-service.js +6 -16
  16. package/dist/src/services/auth-service.js +49 -47
  17. package/dist/src/services/chat-service.js +300 -0
  18. package/dist/src/utils/config-checker.js +50 -0
  19. package/dist/src/utils/default-api-key.js +237 -0
  20. package/dist/src/utils/error-handler.js +4 -4
  21. package/dist/src/utils/token-manager.js +165 -0
  22. package/index.ts +56 -566
  23. package/package.json +8 -2
  24. package/src/client.ts +279 -80
  25. package/src/commands/api-keys.ts +374 -0
  26. package/src/commands/auth.ts +58 -0
  27. package/src/commands/autocomplete.ts +19 -0
  28. package/src/commands/billing.ts +41 -0
  29. package/src/commands/chat.ts +445 -0
  30. package/src/commands/clusters.ts +65 -0
  31. package/src/commands/index.ts +23 -0
  32. package/src/commands/models.ts +63 -0
  33. package/src/commands/users.ts +37 -0
  34. package/src/constants/command-structure.ts +16 -0
  35. package/src/services/api-key-service.ts +12 -20
  36. package/src/services/auth-service.ts +90 -50
  37. package/src/services/chat-service.ts +295 -0
  38. package/src/types/api.d.ts +238 -178
  39. package/src/types/json.d.ts +4 -0
  40. package/src/utils/config-checker.ts +23 -0
  41. package/src/utils/default-api-key.ts +229 -0
  42. package/src/utils/error-handler.ts +4 -4
  43. package/src/utils/token-manager.ts +150 -0
  44. package/tsconfig.json +1 -1
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.registerUserCommands = void 0;
13
+ const command_structure_1 = require("../constants/command-structure");
14
+ const client_1 = require("../client");
15
+ const error_handler_1 = require("../utils/error-handler");
16
+ /**
17
+ * Register user commands
18
+ */
19
+ function registerUserCommands(program) {
20
+ const users = program
21
+ .command(command_structure_1.COMMAND_GROUPS.USERS)
22
+ .description('Manage users');
23
+ users
24
+ .command(command_structure_1.SUBCOMMANDS.USERS.LIST)
25
+ .description('List team members')
26
+ .action(() => __awaiter(this, void 0, void 0, function* () {
27
+ try {
28
+ const client = (0, client_1.createAuthenticatedClient)();
29
+ const { data, error } = yield client.GET('/v1/users');
30
+ if (error)
31
+ throw new Error(JSON.stringify(error));
32
+ console.log('Team Members:');
33
+ console.log('NAME EMAIL ROLE');
34
+ data.forEach((user) => {
35
+ console.log(`${user.name.padEnd(24)} ${user.email.padEnd(30)} ${user.role}`);
36
+ });
37
+ }
38
+ catch (error) {
39
+ (0, error_handler_1.handleError)('Failed to list team members', error);
40
+ }
41
+ }));
42
+ }
43
+ exports.registerUserCommands = registerUserCommands;
@@ -17,6 +17,7 @@ exports.COMMAND_GROUPS = {
17
17
  FLUX: 'flux',
18
18
  USERS: 'users',
19
19
  BILLING: 'billing',
20
+ CHAT: 'chat',
20
21
  };
21
22
  // Subcommands for each group
22
23
  exports.SUBCOMMANDS = {
@@ -26,6 +27,11 @@ exports.SUBCOMMANDS = {
26
27
  LOGOUT: 'logout',
27
28
  WHOAMI: 'whoami',
28
29
  },
30
+ // Chat commands
31
+ CHAT: {
32
+ RUN: 'run',
33
+ LIST: 'list',
34
+ },
29
35
  // API Keys commands
30
36
  API_KEYS: {
31
37
  LIST: 'list',
@@ -33,6 +39,8 @@ exports.SUBCOMMANDS = {
33
39
  DELETE: 'delete',
34
40
  ROTATE: 'rotate',
35
41
  DESCRIBE: 'describe',
42
+ SET_DEFAULT: 'set-default',
43
+ GET_DEFAULT: 'get-default',
36
44
  },
37
45
  // Clusters commands
38
46
  CLUSTERS: {
@@ -102,6 +110,8 @@ exports.COMMAND_DESCRIPTIONS = {
102
110
  [`${exports.COMMAND_GROUPS.API_KEYS} ${exports.SUBCOMMANDS.API_KEYS.DELETE}`]: 'Delete an API key',
103
111
  [`${exports.COMMAND_GROUPS.API_KEYS} ${exports.SUBCOMMANDS.API_KEYS.ROTATE}`]: 'Rotate an API key',
104
112
  [`${exports.COMMAND_GROUPS.API_KEYS} ${exports.SUBCOMMANDS.API_KEYS.DESCRIBE}`]: 'Get usage statistics for an API key',
113
+ [`${exports.COMMAND_GROUPS.API_KEYS} ${exports.SUBCOMMANDS.API_KEYS.SET_DEFAULT}`]: 'Set an API key as the default for chat commands',
114
+ [`${exports.COMMAND_GROUPS.API_KEYS} ${exports.SUBCOMMANDS.API_KEYS.GET_DEFAULT}`]: 'Show the current default API key',
105
115
  // Clusters group
106
116
  [exports.COMMAND_GROUPS.CLUSTERS]: 'Manage Kubernetes clusters',
107
117
  [`${exports.COMMAND_GROUPS.CLUSTERS} ${exports.SUBCOMMANDS.CLUSTERS.LIST}`]: 'List all clusters',
@@ -147,4 +157,8 @@ exports.COMMAND_DESCRIPTIONS = {
147
157
  [`${exports.COMMAND_GROUPS.BILLING} ${exports.SUBCOMMANDS.BILLING.ADD_PAYMENT_METHOD}`]: 'Add a new payment method',
148
158
  [`${exports.COMMAND_GROUPS.BILLING} ${exports.SUBCOMMANDS.BILLING.REMOVE_PAYMENT_METHOD}`]: 'Remove a payment method',
149
159
  [`${exports.COMMAND_GROUPS.BILLING} ${exports.SUBCOMMANDS.BILLING.UPDATE_SUBSCRIPTION}`]: 'Update subscription plan',
160
+ // Chat group
161
+ [exports.COMMAND_GROUPS.CHAT]: 'Interact with AI chat models',
162
+ [`${exports.COMMAND_GROUPS.CHAT} ${exports.SUBCOMMANDS.CHAT.RUN}`]: 'Run a chat session with a specified model',
163
+ [`${exports.COMMAND_GROUPS.CHAT} ${exports.SUBCOMMANDS.CHAT.LIST}`]: 'List available chat models',
150
164
  };
@@ -35,18 +35,8 @@ class ApiKeyService {
35
35
  return __awaiter(this, void 0, void 0, function* () {
36
36
  try {
37
37
  const { data, error } = yield this.client.GET('/v1/api-keys');
38
- if (error) {
39
- // Check if this is an authentication error
40
- const errorObj = typeof error === 'string' ? JSON.parse(error) : error;
41
- if (errorObj.status === 401) {
42
- throw new Error(JSON.stringify({
43
- error: "Authentication failed. Your session may have expired.",
44
- code: "AUTH_FAILED",
45
- details: "Please run 'berget login' to authenticate again."
46
- }));
47
- }
48
- throw new Error(JSON.stringify(error));
49
- }
38
+ if (error)
39
+ throw error;
50
40
  return data || [];
51
41
  }
52
42
  catch (error) {
@@ -63,7 +53,7 @@ class ApiKeyService {
63
53
  return __awaiter(this, void 0, void 0, function* () {
64
54
  try {
65
55
  const { data, error } = yield this.client.POST('/v1/api-keys', {
66
- body: options
56
+ body: options,
67
57
  });
68
58
  if (error)
69
59
  throw new Error(JSON.stringify(error));
@@ -83,7 +73,7 @@ class ApiKeyService {
83
73
  return __awaiter(this, void 0, void 0, function* () {
84
74
  try {
85
75
  const { error } = yield this.client.DELETE('/v1/api-keys/{id}', {
86
- params: { path: { id } }
76
+ params: { path: { id } },
87
77
  });
88
78
  if (error)
89
79
  throw new Error(JSON.stringify(error));
@@ -103,7 +93,7 @@ class ApiKeyService {
103
93
  return __awaiter(this, void 0, void 0, function* () {
104
94
  try {
105
95
  const { data, error } = yield this.client.PUT('/v1/api-keys/{id}/rotate', {
106
- params: { path: { id } }
96
+ params: { path: { id } },
107
97
  });
108
98
  if (error)
109
99
  throw new Error(JSON.stringify(error));
@@ -123,7 +113,7 @@ class ApiKeyService {
123
113
  return __awaiter(this, void 0, void 0, function* () {
124
114
  try {
125
115
  const { data, error } = yield this.client.GET('/v1/api-keys/{id}/usage', {
126
- params: { path: { id } }
116
+ params: { path: { id } },
127
117
  });
128
118
  if (error)
129
119
  throw new Error(JSON.stringify(error));
@@ -55,6 +55,21 @@ class AuthService {
55
55
  }
56
56
  return AuthService.instance;
57
57
  }
58
+ whoami() {
59
+ return __awaiter(this, void 0, void 0, function* () {
60
+ try {
61
+ const { data: profile, error } = yield this.client.GET('/v1/users/me');
62
+ if (error) {
63
+ throw new Error(error ? JSON.stringify(error) : 'Failed to get user profile');
64
+ }
65
+ return profile;
66
+ }
67
+ catch (error) {
68
+ (0, error_handler_1.handleError)('Failed to get user profile', error);
69
+ return null;
70
+ }
71
+ });
72
+ }
58
73
  login() {
59
74
  return __awaiter(this, void 0, void 0, function* () {
60
75
  try {
@@ -68,16 +83,20 @@ class AuthService {
68
83
  ? JSON.stringify(deviceError)
69
84
  : 'Failed to get device authorization data');
70
85
  }
86
+ // Type assertion for deviceData
87
+ const typedDeviceData = deviceData;
71
88
  // Display information to user
72
89
  console.log(chalk_1.default.cyan('\nTo complete login:'));
73
- console.log(chalk_1.default.cyan(`1. Open this URL: ${chalk_1.default.bold(deviceData.verification_url || 'https://auth.berget.ai/device')}`));
74
- console.log(chalk_1.default.cyan(`2. Enter this code: ${chalk_1.default.bold(deviceData.user_code || '')}\n`));
90
+ console.log(chalk_1.default.cyan(`1. Open this URL: ${chalk_1.default.bold(typedDeviceData.verification_url ||
91
+ 'https://keycloak.berget.ai/device')}`));
92
+ if (!typedDeviceData.verification_url)
93
+ console.log(chalk_1.default.cyan(`2. Enter this code: ${chalk_1.default.bold(typedDeviceData.user_code || '')}\n`));
75
94
  // Try to open browser automatically
76
95
  try {
77
- if (deviceData.verification_url) {
96
+ if (typedDeviceData.verification_url) {
78
97
  // Use dynamic import for the 'open' package
79
- const open = yield Promise.resolve().then(() => __importStar(require('open'))).then(m => m.default);
80
- yield open(deviceData.verification_url);
98
+ const open = yield Promise.resolve().then(() => __importStar(require('open'))).then((m) => m.default);
99
+ yield open(typedDeviceData.verification_url);
81
100
  console.log(chalk_1.default.dim("Browser opened automatically. If it didn't open, please use the URL above."));
82
101
  }
83
102
  }
@@ -87,9 +106,11 @@ class AuthService {
87
106
  console.log(chalk_1.default.dim('\nWaiting for authentication to complete...'));
88
107
  // Step 2: Poll for completion
89
108
  const startTime = Date.now();
90
- const expiresIn = deviceData.expires_in !== undefined ? deviceData.expires_in : 900;
109
+ const expiresIn = typedDeviceData.expires_in !== undefined
110
+ ? typedDeviceData.expires_in
111
+ : 900;
91
112
  const expiresAt = startTime + expiresIn * 1000;
92
- let pollInterval = (deviceData.interval || 5) * 1000;
113
+ let pollInterval = (typedDeviceData.interval || 5) * 1000;
93
114
  const spinner = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
94
115
  let spinnerIdx = 0;
95
116
  while (Date.now() < expiresAt) {
@@ -99,7 +120,7 @@ class AuthService {
99
120
  process.stdout.write(`\r${chalk_1.default.blue(spinner[spinnerIdx])} Waiting for authentication...`);
100
121
  spinnerIdx = (spinnerIdx + 1) % spinner.length;
101
122
  // Check if authentication is complete
102
- const deviceCode = deviceData.device_code || '';
123
+ const deviceCode = typedDeviceData.device_code || '';
103
124
  const { data: tokenData, error: tokenError } = yield client_1.apiClient.POST('/v1/auth/device/token', {
104
125
  body: {
105
126
  device_code: deviceCode,
@@ -147,16 +168,27 @@ class AuthService {
147
168
  continue;
148
169
  }
149
170
  }
150
- else if (tokenData && tokenData.token) {
151
- // Success!
152
- (0, client_1.saveAuthToken)(tokenData.token);
153
- process.stdout.write('\r' + ' '.repeat(50) + '\r'); // Clear the spinner line
154
- console.log(chalk_1.default.green('✓ Successfully logged in to Berget'));
155
- if (tokenData.user) {
156
- const user = tokenData.user;
157
- console.log(chalk_1.default.green(`Logged in as ${user.name || user.email || 'User'}`));
171
+ else if (tokenData) {
172
+ // Type assertion for tokenData
173
+ const typedTokenData = tokenData;
174
+ if (typedTokenData.token) {
175
+ // Success!
176
+ (0, client_1.saveAuthToken)(typedTokenData.token, typedTokenData.refresh_token || '', typedTokenData.expires_in || 3600);
177
+ if (process.argv.includes('--debug')) {
178
+ console.log(chalk_1.default.yellow('DEBUG: Token data received:'));
179
+ console.log(chalk_1.default.yellow(JSON.stringify({
180
+ expires_in: typedTokenData.expires_in,
181
+ refresh_expires_in: typedTokenData.refresh_expires_in,
182
+ }, null, 2)));
183
+ }
184
+ process.stdout.write('\r' + ' '.repeat(50) + '\r'); // Clear the spinner line
185
+ console.log(chalk_1.default.green('✓ Successfully logged in to Berget'));
186
+ if (typedTokenData.user) {
187
+ const user = typedTokenData.user;
188
+ console.log(chalk_1.default.green(`Logged in as ${user.name || user.email || 'User'}`));
189
+ }
190
+ return true;
158
191
  }
159
- return true;
160
192
  }
161
193
  }
162
194
  console.log(chalk_1.default.red('\n\nAuthentication timed out. Please try again.'));
@@ -168,36 +200,6 @@ class AuthService {
168
200
  }
169
201
  });
170
202
  }
171
- isAuthenticated() {
172
- return __awaiter(this, void 0, void 0, function* () {
173
- try {
174
- // Call an API endpoint that requires authentication
175
- const { data, error } = yield this.client.GET('/v1/users/me');
176
- return !!data && !error;
177
- }
178
- catch (_a) {
179
- return false;
180
- }
181
- });
182
- }
183
- /**
184
- * Get current user profile
185
- * Command: berget auth whoami
186
- */
187
- whoami() {
188
- return __awaiter(this, void 0, void 0, function* () {
189
- try {
190
- const { data, error } = yield this.client.GET('/v1/users/me');
191
- if (error)
192
- throw new Error(JSON.stringify(error));
193
- return data;
194
- }
195
- catch (error) {
196
- (0, error_handler_1.handleError)('Failed to get user profile', error);
197
- throw error;
198
- }
199
- });
200
- }
201
203
  }
202
204
  exports.AuthService = AuthService;
203
205
  // Command group name for this service
@@ -0,0 +1,300 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ var __rest = (this && this.__rest) || function (s, e) {
35
+ var t = {};
36
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
37
+ t[p] = s[p];
38
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
39
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
40
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
41
+ t[p[i]] = s[p[i]];
42
+ }
43
+ return t;
44
+ };
45
+ var __importDefault = (this && this.__importDefault) || function (mod) {
46
+ return (mod && mod.__esModule) ? mod : { "default": mod };
47
+ };
48
+ Object.defineProperty(exports, "__esModule", { value: true });
49
+ exports.ChatService = void 0;
50
+ const client_1 = require("../client");
51
+ const chalk_1 = __importDefault(require("chalk"));
52
+ /**
53
+ * Service for interacting with the chat API
54
+ * Command group: chat
55
+ */
56
+ class ChatService {
57
+ constructor() {
58
+ this.client = (0, client_1.createAuthenticatedClient)();
59
+ }
60
+ static getInstance() {
61
+ if (!ChatService.instance) {
62
+ ChatService.instance = new ChatService();
63
+ }
64
+ return ChatService.instance;
65
+ }
66
+ /**
67
+ * Create a chat completion
68
+ * Command: berget chat completion
69
+ */
70
+ createCompletion(options) {
71
+ return __awaiter(this, void 0, void 0, function* () {
72
+ try {
73
+ console.log(chalk_1.default.yellow('DEBUG: Starting createCompletion method'));
74
+ // Check if options is defined
75
+ if (!options) {
76
+ console.log(chalk_1.default.red('ERROR: options is undefined'));
77
+ throw new Error('Chat completion options are undefined');
78
+ }
79
+ // Log the raw options object
80
+ console.log(chalk_1.default.yellow('DEBUG: Raw options:'), typeof options, options ? 'defined' : 'undefined');
81
+ const headers = {};
82
+ // Check if debug is enabled
83
+ const isDebug = process.argv.includes('--debug');
84
+ if (isDebug) {
85
+ console.log(chalk_1.default.yellow('DEBUG: Starting createCompletion with options:'));
86
+ try {
87
+ console.log(chalk_1.default.yellow(JSON.stringify(Object.assign(Object.assign({}, options), { apiKey: options.apiKey ? '***' : undefined, messages: options.messages ? `${options.messages.length} messages` : undefined }), null, 2)));
88
+ }
89
+ catch (error) {
90
+ console.log(chalk_1.default.red('ERROR: Failed to stringify options:'), error);
91
+ }
92
+ }
93
+ // Create a copy of options to avoid modifying the original
94
+ const optionsCopy = Object.assign({}, options);
95
+ if (isDebug) {
96
+ console.log(chalk_1.default.yellow('DEBUG: Checking for API key'));
97
+ console.log(chalk_1.default.yellow(`DEBUG: optionsCopy.apiKey exists: ${!!optionsCopy.apiKey}`));
98
+ }
99
+ // Check for environment variables first - prioritize this over everything else
100
+ const envApiKey = process.env.BERGET_API_KEY;
101
+ if (envApiKey) {
102
+ if (isDebug) {
103
+ console.log(chalk_1.default.yellow('DEBUG: Using API key from BERGET_API_KEY environment variable'));
104
+ }
105
+ optionsCopy.apiKey = envApiKey;
106
+ }
107
+ // Only try to get the default API key if no API key is provided and no env var is set
108
+ else if (!optionsCopy.apiKey) {
109
+ if (isDebug) {
110
+ console.log(chalk_1.default.yellow('DEBUG: No API key provided, trying to get default'));
111
+ }
112
+ try {
113
+ // Import the DefaultApiKeyManager directly
114
+ if (isDebug) {
115
+ console.log(chalk_1.default.yellow('DEBUG: Importing DefaultApiKeyManager'));
116
+ }
117
+ const DefaultApiKeyManager = (yield Promise.resolve().then(() => __importStar(require('../utils/default-api-key')))).DefaultApiKeyManager;
118
+ const defaultApiKeyManager = DefaultApiKeyManager.getInstance();
119
+ if (isDebug) {
120
+ console.log(chalk_1.default.yellow('DEBUG: Got DefaultApiKeyManager instance'));
121
+ }
122
+ // Try to get the default API key
123
+ if (isDebug) {
124
+ console.log(chalk_1.default.yellow('DEBUG: Calling promptForDefaultApiKey'));
125
+ }
126
+ const defaultApiKeyData = defaultApiKeyManager.getDefaultApiKeyData();
127
+ const apiKey = (defaultApiKeyData === null || defaultApiKeyData === void 0 ? void 0 : defaultApiKeyData.key) || (yield defaultApiKeyManager.promptForDefaultApiKey());
128
+ if (isDebug) {
129
+ console.log(chalk_1.default.yellow(`DEBUG: Default API key data exists: ${!!defaultApiKeyData}`));
130
+ console.log(chalk_1.default.yellow(`DEBUG: promptForDefaultApiKey returned: ${apiKey ? 'a key' : 'null'}`));
131
+ }
132
+ if (apiKey) {
133
+ if (isDebug) {
134
+ console.log(chalk_1.default.yellow('DEBUG: Using API key from default API key manager'));
135
+ }
136
+ optionsCopy.apiKey = apiKey;
137
+ }
138
+ else {
139
+ console.log(chalk_1.default.yellow('No API key available. You need to either:'));
140
+ console.log(chalk_1.default.yellow('1. Create an API key with: berget api-keys create --name "My Key"'));
141
+ console.log(chalk_1.default.yellow('2. Set a default API key with: berget api-keys set-default <id>'));
142
+ console.log(chalk_1.default.yellow('3. Provide an API key with the --api-key option'));
143
+ console.log(chalk_1.default.yellow('4. Set the BERGET_API_KEY environment variable'));
144
+ console.log(chalk_1.default.yellow('\nExample:'));
145
+ console.log(chalk_1.default.yellow(' export BERGET_API_KEY=your_api_key_here'));
146
+ console.log(chalk_1.default.yellow(' # or for a single command:'));
147
+ console.log(chalk_1.default.yellow(' BERGET_API_KEY=your_api_key_here berget chat run google/gemma-3-27b-it'));
148
+ throw new Error('No API key provided and no default API key set');
149
+ }
150
+ // Set the API key in the options
151
+ if (isDebug) {
152
+ console.log(chalk_1.default.yellow('DEBUG: Setting API key in options'));
153
+ }
154
+ // Only set the API key if it's not null
155
+ if (apiKey) {
156
+ optionsCopy.apiKey = apiKey;
157
+ }
158
+ }
159
+ catch (error) {
160
+ console.log(chalk_1.default.red('Error getting API key:'));
161
+ if (error instanceof Error) {
162
+ console.log(chalk_1.default.red(error.message));
163
+ }
164
+ console.log(chalk_1.default.yellow('Please create an API key with: berget api-keys create --name "My Key"'));
165
+ throw new Error('Failed to get API key');
166
+ }
167
+ }
168
+ if (isDebug) {
169
+ console.log(chalk_1.default.yellow('DEBUG: Chat completion options:'));
170
+ console.log(chalk_1.default.yellow(JSON.stringify(Object.assign(Object.assign({}, optionsCopy), { apiKey: optionsCopy.apiKey ? '***' : undefined // Hide the actual API key in debug output
171
+ }), null, 2)));
172
+ }
173
+ // If an API key is provided, use it for this request
174
+ if (optionsCopy.apiKey) {
175
+ headers['Authorization'] = `Bearer ${optionsCopy.apiKey}`;
176
+ // Remove apiKey from options before sending to API
177
+ const { apiKey } = optionsCopy, requestOptions = __rest(optionsCopy, ["apiKey"]);
178
+ if (isDebug) {
179
+ console.log(chalk_1.default.yellow('DEBUG: Using provided API key'));
180
+ console.log(chalk_1.default.yellow('DEBUG: Request options:'));
181
+ console.log(chalk_1.default.yellow(JSON.stringify(requestOptions, null, 2)));
182
+ }
183
+ try {
184
+ const response = yield this.client.POST('/v1/chat/completions', {
185
+ body: requestOptions,
186
+ headers
187
+ });
188
+ // Check if response has an error property
189
+ const responseAny = response;
190
+ if (responseAny && responseAny.error)
191
+ throw new Error(JSON.stringify(responseAny.error));
192
+ if (isDebug) {
193
+ console.log(chalk_1.default.yellow('DEBUG: API response:'));
194
+ console.log(chalk_1.default.yellow(JSON.stringify(response, null, 2)));
195
+ // Output the complete response data for debugging
196
+ console.log(chalk_1.default.yellow('DEBUG: Complete response data:'));
197
+ console.log(chalk_1.default.yellow(JSON.stringify(response.data, null, 2)));
198
+ }
199
+ return response.data;
200
+ }
201
+ catch (requestError) {
202
+ if (process.argv.includes('--debug')) {
203
+ console.log(chalk_1.default.red(`DEBUG: Request error: ${requestError instanceof Error ? requestError.message : String(requestError)}`));
204
+ }
205
+ throw requestError;
206
+ }
207
+ }
208
+ else {
209
+ // We've exhausted all options for getting an API key
210
+ console.log(chalk_1.default.yellow('No API key available. You need to either:'));
211
+ console.log(chalk_1.default.yellow('1. Create an API key with: berget api-keys create --name "My Key"'));
212
+ console.log(chalk_1.default.yellow('2. Set a default API key with: berget api-keys set-default <id>'));
213
+ console.log(chalk_1.default.yellow('3. Provide an API key with the --api-key option'));
214
+ console.log(chalk_1.default.yellow('4. Set the BERGET_API_KEY environment variable'));
215
+ console.log(chalk_1.default.yellow('\nExample:'));
216
+ console.log(chalk_1.default.yellow(' export BERGET_API_KEY=your_api_key_here'));
217
+ console.log(chalk_1.default.yellow(' # or for a single command:'));
218
+ console.log(chalk_1.default.yellow(' BERGET_API_KEY=your_api_key_here berget chat run google/gemma-3-27b-it'));
219
+ throw new Error('No API key available. Please provide an API key or set a default API key.');
220
+ }
221
+ }
222
+ catch (error) {
223
+ // Improved error handling
224
+ let errorMessage = 'Failed to create chat completion';
225
+ if (error instanceof Error) {
226
+ try {
227
+ // Try to parse the error message as JSON
228
+ const parsedError = JSON.parse(error.message);
229
+ if (parsedError.error && parsedError.error.message) {
230
+ errorMessage = `Chat error: ${parsedError.error.message}`;
231
+ }
232
+ }
233
+ catch (e) {
234
+ // If parsing fails, use the original error message
235
+ errorMessage = `Chat error: ${error.message}`;
236
+ }
237
+ }
238
+ console.error(chalk_1.default.red(errorMessage));
239
+ throw new Error(errorMessage);
240
+ }
241
+ });
242
+ }
243
+ /**
244
+ * List available models
245
+ * Command: berget chat list
246
+ */
247
+ listModels(apiKey) {
248
+ return __awaiter(this, void 0, void 0, function* () {
249
+ try {
250
+ // Check for environment variable first, then fallback to provided API key
251
+ const envApiKey = process.env.BERGET_API_KEY;
252
+ const effectiveApiKey = envApiKey || apiKey;
253
+ if (effectiveApiKey) {
254
+ const headers = {
255
+ 'Authorization': `Bearer ${effectiveApiKey}`
256
+ };
257
+ const { data, error } = yield this.client.GET('/v1/models', { headers });
258
+ if (error)
259
+ throw new Error(JSON.stringify(error));
260
+ return data;
261
+ }
262
+ else {
263
+ const { data, error } = yield this.client.GET('/v1/models');
264
+ if (error)
265
+ throw new Error(JSON.stringify(error));
266
+ return data;
267
+ }
268
+ }
269
+ catch (error) {
270
+ // Improved error handling
271
+ let errorMessage = 'Failed to list models';
272
+ if (error instanceof Error) {
273
+ try {
274
+ // Try to parse the error message as JSON
275
+ const parsedError = JSON.parse(error.message);
276
+ if (parsedError.error) {
277
+ errorMessage = `Models error: ${typeof parsedError.error === 'string' ?
278
+ parsedError.error :
279
+ (parsedError.error.message || JSON.stringify(parsedError.error))}`;
280
+ }
281
+ }
282
+ catch (e) {
283
+ // If parsing fails, use the original error message
284
+ errorMessage = `Models error: ${error.message}`;
285
+ }
286
+ }
287
+ console.error(chalk_1.default.red(errorMessage));
288
+ throw new Error(errorMessage);
289
+ }
290
+ });
291
+ }
292
+ }
293
+ exports.ChatService = ChatService;
294
+ // Command group name for this service
295
+ ChatService.COMMAND_GROUP = 'chat';
296
+ // Subcommands for this service
297
+ ChatService.COMMANDS = {
298
+ RUN: 'run',
299
+ LIST: 'list'
300
+ };
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.checkBergetConfig = void 0;
27
+ const fs = __importStar(require("fs"));
28
+ const path = __importStar(require("path"));
29
+ /**
30
+ * Check for .bergetconfig file and handle cluster switching
31
+ */
32
+ function checkBergetConfig() {
33
+ const configPath = path.join(process.cwd(), '.bergetconfig');
34
+ if (fs.existsSync(configPath)) {
35
+ try {
36
+ const config = fs.readFileSync(configPath, 'utf8');
37
+ const match = config.match(/cluster:\s*(.+)/);
38
+ if (match && match[1]) {
39
+ const clusterName = match[1].trim();
40
+ console.log(`🔄 Berget: Switched to cluster "${clusterName}"`);
41
+ console.log('✓ kubectl config updated');
42
+ console.log('');
43
+ }
44
+ }
45
+ catch (error) {
46
+ // Silently ignore errors reading config
47
+ }
48
+ }
49
+ }
50
+ exports.checkBergetConfig = checkBergetConfig;