berget 1.1.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.
- package/dist/index.js +47 -1
- package/dist/package.json +35 -0
- package/dist/src/client.js +24 -7
- package/dist/src/commands/api-keys.js +13 -7
- package/dist/src/commands/chat.js +84 -18
- package/dist/src/services/api-key-service.js +6 -16
- package/dist/src/services/chat-service.js +159 -36
- package/dist/src/utils/default-api-key.js +131 -5
- package/dist/src/utils/error-handler.js +4 -4
- package/index.ts +52 -1
- package/package.json +3 -2
- package/src/client.ts +23 -6
- package/src/commands/api-keys.ts +17 -7
- package/src/commands/chat.ts +122 -22
- package/src/services/api-key-service.ts +12 -20
- package/src/services/chat-service.ts +158 -40
- package/src/types/api.d.ts +203 -9
- package/src/types/json.d.ts +4 -0
- package/src/utils/default-api-key.ts +141 -6
- package/src/utils/error-handler.ts +4 -4
- package/tsconfig.json +1 -1
|
@@ -2,11 +2,14 @@ import * as fs from 'fs'
|
|
|
2
2
|
import * as path from 'path'
|
|
3
3
|
import * as os from 'os'
|
|
4
4
|
import chalk from 'chalk'
|
|
5
|
+
import { ApiKeyService } from '../services/api-key-service'
|
|
6
|
+
import readline from 'readline'
|
|
5
7
|
|
|
6
8
|
interface DefaultApiKeyData {
|
|
7
9
|
id: string
|
|
8
10
|
name: string
|
|
9
11
|
prefix: string
|
|
12
|
+
key: string
|
|
10
13
|
}
|
|
11
14
|
|
|
12
15
|
/**
|
|
@@ -44,7 +47,9 @@ export class DefaultApiKeyManager {
|
|
|
44
47
|
this.defaultApiKey = JSON.parse(data)
|
|
45
48
|
}
|
|
46
49
|
} catch (error) {
|
|
47
|
-
|
|
50
|
+
if (process.argv.includes('--debug')) {
|
|
51
|
+
console.error(chalk.dim('Failed to load default API key configuration'))
|
|
52
|
+
}
|
|
48
53
|
this.defaultApiKey = null
|
|
49
54
|
}
|
|
50
55
|
}
|
|
@@ -65,22 +70,31 @@ export class DefaultApiKeyManager {
|
|
|
65
70
|
}
|
|
66
71
|
}
|
|
67
72
|
} catch (error) {
|
|
68
|
-
|
|
73
|
+
if (process.argv.includes('--debug')) {
|
|
74
|
+
console.error(chalk.dim('Failed to save default API key configuration'))
|
|
75
|
+
}
|
|
69
76
|
}
|
|
70
77
|
}
|
|
71
78
|
|
|
72
79
|
/**
|
|
73
80
|
* Set the default API key
|
|
74
81
|
*/
|
|
75
|
-
public setDefaultApiKey(id: string, name: string, prefix: string): void {
|
|
76
|
-
this.defaultApiKey = { id, name, prefix }
|
|
82
|
+
public setDefaultApiKey(id: string, name: string, prefix: string, key: string): void {
|
|
83
|
+
this.defaultApiKey = { id, name, prefix, key }
|
|
77
84
|
this.saveConfig()
|
|
78
85
|
}
|
|
79
86
|
|
|
80
87
|
/**
|
|
81
|
-
* Get the default API key
|
|
88
|
+
* Get the default API key string
|
|
82
89
|
*/
|
|
83
|
-
public getDefaultApiKey():
|
|
90
|
+
public getDefaultApiKey(): string | null {
|
|
91
|
+
return this.defaultApiKey?.key || null
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Get the default API key data object
|
|
96
|
+
*/
|
|
97
|
+
public getDefaultApiKeyData(): DefaultApiKeyData | null {
|
|
84
98
|
return this.defaultApiKey
|
|
85
99
|
}
|
|
86
100
|
|
|
@@ -91,4 +105,125 @@ export class DefaultApiKeyManager {
|
|
|
91
105
|
this.defaultApiKey = null
|
|
92
106
|
this.saveConfig()
|
|
93
107
|
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Prompts the user to select a default API key if none is set
|
|
111
|
+
* @returns The selected API key or null if none was selected
|
|
112
|
+
*/
|
|
113
|
+
public async promptForDefaultApiKey(): Promise<string | null> {
|
|
114
|
+
try {
|
|
115
|
+
const isDebug = process.argv.includes('--debug')
|
|
116
|
+
|
|
117
|
+
if (isDebug) {
|
|
118
|
+
console.log(chalk.yellow('DEBUG: promptForDefaultApiKey called'))
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// If we already have a default API key, return it
|
|
122
|
+
if (this.defaultApiKey) {
|
|
123
|
+
if (isDebug) {
|
|
124
|
+
console.log(chalk.yellow('DEBUG: Using existing default API key'))
|
|
125
|
+
}
|
|
126
|
+
return this.defaultApiKey.key
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (isDebug) {
|
|
130
|
+
console.log(chalk.yellow('DEBUG: No default API key found, getting ApiKeyService'))
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const apiKeyService = ApiKeyService.getInstance()
|
|
134
|
+
|
|
135
|
+
// Get all API keys
|
|
136
|
+
let apiKeys;
|
|
137
|
+
try {
|
|
138
|
+
if (isDebug) {
|
|
139
|
+
console.log(chalk.yellow('DEBUG: Calling apiKeyService.list()'))
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
apiKeys = await apiKeyService.list()
|
|
143
|
+
|
|
144
|
+
if (isDebug) {
|
|
145
|
+
console.log(chalk.yellow(`DEBUG: Got ${apiKeys ? apiKeys.length : 0} API keys`))
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (!apiKeys || apiKeys.length === 0) {
|
|
149
|
+
console.log(chalk.yellow('No API keys found. Create one with:'))
|
|
150
|
+
console.log(chalk.blue(' berget api-keys create --name "My Key"'))
|
|
151
|
+
return null
|
|
152
|
+
}
|
|
153
|
+
} catch (error) {
|
|
154
|
+
// Check if this is an authentication error
|
|
155
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
156
|
+
const isAuthError = errorMessage.includes('Unauthorized') ||
|
|
157
|
+
errorMessage.includes('Authentication failed') ||
|
|
158
|
+
errorMessage.includes('AUTH_FAILED');
|
|
159
|
+
|
|
160
|
+
if (isAuthError) {
|
|
161
|
+
console.log(chalk.yellow('Authentication required. Please run `berget auth login` first.'));
|
|
162
|
+
} else {
|
|
163
|
+
console.log(chalk.red('Error fetching API keys:'));
|
|
164
|
+
if (error instanceof Error) {
|
|
165
|
+
console.log(chalk.red(error.message));
|
|
166
|
+
if (isDebug) {
|
|
167
|
+
console.log(chalk.yellow(`DEBUG: API key list error: ${error.message}`));
|
|
168
|
+
console.log(chalk.yellow(`DEBUG: Stack: ${error.stack}`));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
console.log(chalk.blue('Select an API key to use as default:'))
|
|
176
|
+
|
|
177
|
+
// Display available API keys
|
|
178
|
+
apiKeys.forEach((key, index) => {
|
|
179
|
+
console.log(` ${index + 1}. ${key.name} (${key.prefix}...)`)
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
// Create readline interface for user input
|
|
183
|
+
const rl = readline.createInterface({
|
|
184
|
+
input: process.stdin,
|
|
185
|
+
output: process.stdout
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
// Prompt for selection
|
|
189
|
+
const selection = await new Promise<number>((resolve) => {
|
|
190
|
+
rl.question('Enter number (or press Enter to cancel): ', (answer) => {
|
|
191
|
+
rl.close()
|
|
192
|
+
const num = parseInt(answer.trim(), 10)
|
|
193
|
+
if (isNaN(num) || num < 1 || num > apiKeys.length) {
|
|
194
|
+
resolve(-1) // Invalid selection
|
|
195
|
+
} else {
|
|
196
|
+
resolve(num - 1) // Convert to zero-based index
|
|
197
|
+
}
|
|
198
|
+
})
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
if (selection === -1) {
|
|
202
|
+
console.log(chalk.yellow('No API key selected'))
|
|
203
|
+
return null
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const selectedKey = apiKeys[selection]
|
|
207
|
+
|
|
208
|
+
// Create a new API key with the selected name
|
|
209
|
+
const newKey = await apiKeyService.create({
|
|
210
|
+
name: `CLI Default (copy of ${selectedKey.name})`,
|
|
211
|
+
description: 'Created automatically by the Berget CLI for default use'
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
// Save the new key as default
|
|
215
|
+
this.setDefaultApiKey(
|
|
216
|
+
newKey.id.toString(),
|
|
217
|
+
newKey.name,
|
|
218
|
+
newKey.key.substring(0, 8), // Use first 8 chars as prefix
|
|
219
|
+
newKey.key
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
console.log(chalk.green(`✓ Default API key set to: ${newKey.name}`))
|
|
223
|
+
return newKey.key
|
|
224
|
+
} catch (error) {
|
|
225
|
+
console.error(chalk.red('Failed to set default API key:'), error)
|
|
226
|
+
return null
|
|
227
|
+
}
|
|
228
|
+
}
|
|
94
229
|
}
|
|
@@ -30,11 +30,11 @@ export function handleError(message: string, error: any): void {
|
|
|
30
30
|
|
|
31
31
|
// Check for authentication errors
|
|
32
32
|
if (
|
|
33
|
-
(typeof error === 'string' && error.includes('Unauthorized')) ||
|
|
34
|
-
(error && error.message && error.message.includes('Unauthorized')) ||
|
|
35
|
-
(error && error.code && error.code === 401)
|
|
33
|
+
(typeof error === 'string' && (error.includes('Unauthorized') || error.includes('Authentication failed'))) ||
|
|
34
|
+
(error && error.message && (error.message.includes('Unauthorized') || error.message.includes('Authentication failed'))) ||
|
|
35
|
+
(error && error.code && (error.code === 401 || error.code === 'AUTH_FAILED'))
|
|
36
36
|
) {
|
|
37
37
|
console.error(chalk.yellow('\nYou need to be logged in to use this command.'));
|
|
38
|
-
console.error(chalk.yellow('Run `berget login` to authenticate.'));
|
|
38
|
+
console.error(chalk.yellow('Run `berget auth login` to authenticate.'));
|
|
39
39
|
}
|
|
40
40
|
}
|
package/tsconfig.json
CHANGED
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
// "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
|
|
40
40
|
// "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
|
|
41
41
|
// "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
|
|
42
|
-
|
|
42
|
+
"resolveJsonModule": true, /* Enable importing .json files. */
|
|
43
43
|
// "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
|
|
44
44
|
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
|
|
45
45
|
|