berget 1.3.1 → 1.4.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.
@@ -0,0 +1,56 @@
1
+ name: Publish to NPM
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ release:
8
+ types: [published]
9
+
10
+ jobs:
11
+ test:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - name: Checkout code
15
+ uses: actions/checkout@v4
16
+
17
+ - name: Setup Node.js
18
+ uses: actions/setup-node@v4
19
+ with:
20
+ node-version: '18'
21
+ cache: 'npm'
22
+
23
+ - name: Install dependencies
24
+ run: npm ci
25
+
26
+ - name: Run tests
27
+ run: npm run test:run
28
+
29
+ - name: Build project
30
+ run: npm run build
31
+
32
+ publish:
33
+ needs: test
34
+ runs-on: ubuntu-latest
35
+ if: github.ref == 'refs/heads/main' || github.event_name == 'release'
36
+ steps:
37
+ - name: Checkout code
38
+ uses: actions/checkout@v4
39
+
40
+ - name: Setup Node.js
41
+ uses: actions/setup-node@v4
42
+ with:
43
+ node-version: '18'
44
+ registry-url: 'https://registry.npmjs.org'
45
+ cache: 'npm'
46
+
47
+ - name: Install dependencies
48
+ run: npm ci
49
+
50
+ - name: Build project
51
+ run: npm run build
52
+
53
+ - name: Publish to NPM
54
+ run: npm publish
55
+ env:
56
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -0,0 +1,38 @@
1
+ name: Test
2
+
3
+ on:
4
+ pull_request:
5
+ branches:
6
+ - main
7
+ push:
8
+ branches:
9
+ - main
10
+
11
+ jobs:
12
+ test:
13
+ runs-on: ubuntu-latest
14
+ strategy:
15
+ matrix:
16
+ node-version: [18, 20]
17
+
18
+ steps:
19
+ - name: Checkout code
20
+ uses: actions/checkout@v4
21
+
22
+ - name: Setup Node.js ${{ matrix.node-version }}
23
+ uses: actions/setup-node@v4
24
+ with:
25
+ node-version: ${{ matrix.node-version }}
26
+ cache: 'npm'
27
+
28
+ - name: Install dependencies
29
+ run: npm ci
30
+
31
+ - name: Run tests
32
+ run: npm run test:run
33
+
34
+ - name: Build project
35
+ run: npm run build
36
+
37
+ - name: Check TypeScript
38
+ run: npx tsc --noEmit
package/README.md CHANGED
@@ -1,33 +1,193 @@
1
1
  # Berget CLI
2
2
 
3
- A command-line interface for interacting with the Berget AI infrastructure.
3
+ A command-line tool for interacting with Berget AI's infrastructure and AI models.
4
4
 
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
8
  npm install -g berget
9
+ # or use directly with npx
10
+ npx berget --help
9
11
  ```
10
12
 
11
13
  ## Authentication
12
14
 
13
- The CLI uses OAuth-based authentication with automatic token refresh.
15
+ Before you can use the CLI, you need to authenticate:
14
16
 
15
- ### Login
17
+ ```bash
18
+ # Login with OAuth
19
+ npx berget auth login
20
+
21
+ # Create an API key
22
+ npx berget api-keys create --name "My CLI Key"
23
+
24
+ # Or use environment variable
25
+ export BERGET_API_KEY=sk_ber_your_api_key_here
26
+ ```
27
+
28
+ ## Chat Command
29
+
30
+ ### Basic Usage
31
+
32
+ ```bash
33
+ # Interactive chat session
34
+ npx berget chat run
35
+
36
+ # Use specific model
37
+ npx berget chat run openai/gpt-oss
38
+
39
+ # Send direct message
40
+ npx berget chat run openai/gpt-oss "Explain what Docker is"
41
+
42
+ # Use pipe for input
43
+ echo "What is Kubernetes?" | npx berget chat run openai/gpt-oss
44
+ ```
45
+
46
+ ### Practical Use Cases
47
+
48
+ #### 1. Git Commit Messages
16
49
 
17
50
  ```bash
18
- berget auth login
51
+ # Generate commit message from git diff
52
+ git diff | npx berget chat run openai/gpt-oss "Create a conventional commit message for this diff. Reply with only the message:"
53
+
54
+ # Use as alias
55
+ alias gitcommit='git diff | npx berget chat run openai/gpt-oss "Generate a conventional commit message for this diff. Reply with only the commit message, nothing else:"'
19
56
  ```
20
57
 
21
- This will open a browser window to authenticate with Berget. After successful authentication, your access token and refresh token will be stored securely in `~/.berget/auth.json`.
58
+ #### 2. Code Review and Explanations
22
59
 
23
- ### Token Refresh
60
+ ```bash
61
+ # Explain code
62
+ cat src/main.js | npx berget chat run openai/gpt-oss "Explain what this code does:"
24
63
 
25
- The CLI automatically handles token refresh when:
64
+ # Find bugs
65
+ cat problematic-file.py | npx berget chat run openai/gpt-oss "Analyze this code and find potential bugs:"
26
66
 
27
- 1. The access token is about to expire (within 10 minutes of expiration)
28
- 2. A request returns a 401 Unauthorized error
67
+ # Improvement suggestions
68
+ git diff | npx berget chat run openai/gpt-oss "Give suggestions for improvements to this code change:"
69
+ ```
29
70
 
30
- The refresh mechanism uses the stored refresh token to obtain a new access token without requiring you to log in again. If the refresh token itself is expired or invalid, you'll be prompted to log in again.
71
+ #### 3. Documentation
72
+
73
+ ```bash
74
+ # Generate README
75
+ ls -la | npx berget chat run openai/gpt-oss "Create a README.md for this project based on the file structure:"
76
+
77
+ # Comment code
78
+ cat uncommented-code.js | npx berget chat run openai/gpt-oss "Add JSDoc comments to this code:"
79
+ ```
80
+
81
+ #### 4. System Administration
82
+
83
+ ```bash
84
+ # Analyze logs
85
+ tail -n 100 /var/log/nginx/error.log | npx berget chat run openai/gpt-oss "Analyze these error logs and suggest solutions:"
86
+
87
+ # Explain commands
88
+ npx berget chat run openai/gpt-oss "Explain what this bash command does: find . -name '*.js' -exec grep -l 'TODO' {} \;"
89
+ ```
90
+
91
+ ## Useful Bash/Zsh Aliases
92
+
93
+ Add these to your `~/.bashrc`, `~/.zshrc` or similar:
94
+
95
+ ```bash
96
+ # Git-related aliases
97
+ alias gai='git diff | npx berget chat run openai/gpt-oss "Generate a conventional commit message for this diff. Reply with only the commit message, nothing else:"'
98
+ alias gexplain='git log --oneline -10 | npx berget chat run openai/gpt-oss "Explain what these commits do:"'
99
+ alias gsec='~/bin/security-check'
100
+
101
+ # Code-related aliases
102
+ alias explain='npx berget chat run openai/gpt-oss "Explain this code:"'
103
+ alias review='npx berget chat run openai/gpt-oss "Review this code and give improvement suggestions:"'
104
+ alias debug='npx berget chat run openai/gpt-oss "Find and explain potential bugs in this code:"'
105
+
106
+ # Documentation aliases
107
+ alias docgen='npx berget chat run openai/gpt-oss "Generate documentation for this code:"'
108
+ alias readme='ls -la | npx berget chat run openai/gpt-oss "Create a README.md for this project:"'
109
+
110
+ # System aliases
111
+ alias loganalyze='npx berget chat run openai/gpt-oss "Analyze these logs and suggest solutions:"'
112
+ alias cmdexplain='npx berget chat run openai/gpt-oss "Explain this command:"'
113
+
114
+ # Quick AI assistant
115
+ alias ai='npx berget chat run openai/gpt-oss'
116
+ alias ask='npx berget chat run openai/gpt-oss'
117
+ ```
118
+
119
+ ## Advanced Examples
120
+
121
+ See the `examples/` folder for complete scripts:
122
+
123
+ - **smart-commit.sh** - Automatic generation of conventional commit messages
124
+ - **ai-review.sh** - AI-driven code review
125
+ - **security-check.sh** - Security review of commits
126
+
127
+ ```bash
128
+ # Copy example scripts
129
+ cp examples/*.sh ~/bin/
130
+ chmod +x ~/bin/*.sh
131
+
132
+ # Use them
133
+ ~/bin/smart-commit.sh
134
+ ~/bin/ai-review.sh src/main.js
135
+ ~/bin/security-check.sh
136
+ ```
137
+
138
+ ## Environment Variables
139
+
140
+ ```bash
141
+ # API key (recommended)
142
+ export BERGET_API_KEY=sk_ber_your_api_key_here
143
+
144
+ # Debug mode
145
+ export LOG_LEVEL=debug
146
+
147
+ # Custom API base URL (if using your own instance)
148
+ export API_BASE_URL=https://your-custom-api.example.com
149
+ ```
150
+
151
+ ## Tips and Tricks
152
+
153
+ 1. **Use pipes**: Combine with other Unix tools for powerful workflows
154
+ 2. **Short prompts**: Be specific but concise in your prompts for best results
155
+ 3. **Streaming**: Streaming is enabled by default for faster responses
156
+ 4. **Model selection**: Experiment with different models for different tasks
157
+ 5. **Aliases**: Create aliases for common use cases to save time
158
+
159
+ ## Command Reference
160
+
161
+ - `auth login` - Login to Berget
162
+ - `auth logout` - Logout from Berget
163
+ - `auth whoami` - Show current user information
164
+ - `api-keys list` - List API keys
165
+ - `api-keys create` - Create a new API key
166
+ - `models list` - List available AI models
167
+ - `chat run` - Start a chat session with an AI model
168
+ - `chat list` - List available chat models
169
+
170
+ For a complete list of commands, run:
171
+
172
+ ```bash
173
+ npx berget --help
174
+ ```
175
+
176
+ ## Troubleshooting
177
+
178
+ ```bash
179
+ # Enable debug mode
180
+ npx berget --debug chat run openai/gpt-oss "test"
181
+
182
+ # Check authentication
183
+ npx berget auth whoami
184
+
185
+ # List available models
186
+ npx berget chat list
187
+
188
+ # Check API key status
189
+ npx berget api-keys list
190
+ ```
31
191
 
32
192
  ## Development
33
193
 
@@ -36,12 +196,12 @@ The refresh mechanism uses the stored refresh token to obtain a new access token
36
196
  Clone the repository and install dependencies:
37
197
 
38
198
  ```bash
39
- git clone https://github.com/berget/cli.git
199
+ git clone https://github.com/berget-ai/cli.git
40
200
  cd cli
41
201
  npm install
42
202
  ```
43
203
 
44
- ### Testing Locally
204
+ ### Test Locally
45
205
 
46
206
  Use the `start` script to test the CLI locally with the `--local` flag:
47
207
 
@@ -62,31 +222,10 @@ npm start -- auth whoami
62
222
  npm start -- auth whoami --debug
63
223
  ```
64
224
 
65
- The `--debug` flag provides detailed information about token refresh attempts and API responses.
66
-
67
- ### Testing Token Refresh
68
-
69
- To test the token refresh mechanism:
225
+ ## Contributing
70
226
 
71
- 1. Log in with `npm start -- auth login`
72
- 2. Make a request that requires authentication, like `npm start -- auth whoami`
73
- 3. To force a token refresh, you can:
74
- - Wait until the token is close to expiration
75
- - Manually edit `~/.berget/auth.json` and set `expires_at` to a past timestamp
76
- - Use the `--debug` flag to see the token refresh process in action
227
+ Berget CLI is open source. Contributions are welcome!
77
228
 
78
- ## Commands
79
-
80
- - `auth login` - Log in to Berget
81
- - `auth logout` - Log out from Berget
82
- - `auth whoami` - Show current user information
83
- - `api-keys list` - List API keys
84
- - `api-keys create` - Create a new API key
85
- - `models list` - List available AI models
86
- - `chat run` - Start a chat session with an AI model
87
-
88
- For a complete list of commands, run:
89
-
90
- ```bash
91
- berget --help
92
- ```
229
+ - GitHub: [berget-ai/cli](https://github.com/berget-ai/cli)
230
+ - Issues: [Report bugs](https://github.com/berget-ai/cli/issues)
231
+ - Documentation: [docs.berget.ai](https://docs.berget.ai)
package/dist/package.json CHANGED
@@ -1,17 +1,22 @@
1
1
  {
2
2
  "name": "berget",
3
- "version": "1.3.1",
3
+ "version": "1.4.0",
4
4
  "main": "dist/index.js",
5
5
  "bin": {
6
6
  "berget": "dist/index.js"
7
7
  },
8
8
  "private": false,
9
+ "publishConfig": {
10
+ "access": "public"
11
+ },
9
12
  "scripts": {
10
13
  "start": "node --import tsx ./index.ts --local",
11
14
  "login": "node --import tsx ./index.ts --local auth login",
12
15
  "logout": "node --import tsx ./index.ts --local auth logout",
13
16
  "whoami": "node --import tsx ./index.ts --local auth whoami",
14
17
  "build": "tsc",
18
+ "test": "vitest",
19
+ "test:run": "vitest run",
15
20
  "prepublishOnly": "npm run build",
16
21
  "generate-types": "openapi-typescript https://api.berget.ai/openapi.json -o src/types/api.d.ts"
17
22
  },
@@ -23,7 +28,8 @@
23
28
  "@types/marked-terminal": "^6.1.1",
24
29
  "@types/node": "^20.11.20",
25
30
  "tsx": "^4.19.3",
26
- "typescript": "^5.3.3"
31
+ "typescript": "^5.3.3",
32
+ "vitest": "^1.0.0"
27
33
  },
28
34
  "dependencies": {
29
35
  "chalk": "^4.1.2",
@@ -8,6 +8,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
+ var __asyncValues = (this && this.__asyncValues) || function (o) {
12
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
13
+ var m = o[Symbol.asyncIterator], i;
14
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
15
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
16
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
17
+ };
11
18
  var __importDefault = (this && this.__importDefault) || function (mod) {
12
19
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
20
  };
@@ -49,14 +56,16 @@ function registerChatCommands(program) {
49
56
  chat
50
57
  .command(command_structure_1.SUBCOMMANDS.CHAT.RUN)
51
58
  .description('Run a chat session with a specified model')
52
- .argument('[model]', 'Model to use (default: google/gemma-3-27b-it)')
59
+ .argument('[model]', 'Model to use (default: openai/gpt-oss)')
60
+ .argument('[message]', 'Message to send directly (skips interactive mode)')
53
61
  .option('-s, --system <message>', 'System message')
54
62
  .option('-t, --temperature <temp>', 'Temperature (0-1)', parseFloat)
55
63
  .option('-m, --max-tokens <tokens>', 'Maximum tokens to generate', parseInt)
56
64
  .option('-k, --api-key <key>', 'API key to use for this chat session')
57
65
  .option('--api-key-id <id>', 'ID of the API key to use from your saved keys')
58
- .option('--stream', 'Stream the response')
59
- .action((options) => __awaiter(this, void 0, void 0, function* () {
66
+ .option('--no-stream', 'Disable streaming (streaming is enabled by default)')
67
+ .action((model, message, options) => __awaiter(this, void 0, void 0, function* () {
68
+ var _a, e_1, _b, _c;
60
69
  try {
61
70
  const chatService = chat_service_1.ChatService.getInstance();
62
71
  // Check if we have an API key or need to get one
@@ -168,11 +177,6 @@ function registerChatCommands(program) {
168
177
  return;
169
178
  }
170
179
  }
171
- // Set up readline interface for user input
172
- const rl = readline_1.default.createInterface({
173
- input: process.stdin,
174
- output: process.stdout,
175
- });
176
180
  // Prepare messages array
177
181
  const messages = [];
178
182
  // Add system message if provided
@@ -182,12 +186,134 @@ function registerChatCommands(program) {
182
186
  content: options.system,
183
187
  });
184
188
  }
189
+ // Check if input is being piped in
190
+ let inputMessage = message;
191
+ let stdinContent = '';
192
+ if (!process.stdin.isTTY) {
193
+ // Read from stdin (piped input)
194
+ const chunks = [];
195
+ try {
196
+ for (var _d = true, _e = __asyncValues(process.stdin), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
197
+ _c = _f.value;
198
+ _d = false;
199
+ const chunk = _c;
200
+ chunks.push(chunk);
201
+ }
202
+ }
203
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
204
+ finally {
205
+ try {
206
+ if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
207
+ }
208
+ finally { if (e_1) throw e_1.error; }
209
+ }
210
+ stdinContent = Buffer.concat(chunks).toString('utf8').trim();
211
+ }
212
+ // Combine stdin content with message if both exist
213
+ if (stdinContent && message) {
214
+ inputMessage = `${stdinContent}\n\n${message}`;
215
+ }
216
+ else if (stdinContent && !message) {
217
+ inputMessage = stdinContent;
218
+ }
219
+ // If a message is provided (either as argument, from stdin, or both), send it directly and exit
220
+ if (inputMessage) {
221
+ // Add user message
222
+ messages.push({
223
+ role: 'user',
224
+ content: inputMessage,
225
+ });
226
+ try {
227
+ // Call the API
228
+ const completionOptions = {
229
+ model: model || 'openai/gpt-oss',
230
+ messages: messages,
231
+ temperature: options.temperature !== undefined ? options.temperature : 0.7,
232
+ max_tokens: options.maxTokens || 4096,
233
+ stream: options.stream !== false
234
+ };
235
+ // Only add apiKey if it actually exists
236
+ if (apiKey) {
237
+ completionOptions.apiKey = apiKey;
238
+ }
239
+ // Add streaming support (now default)
240
+ if (completionOptions.stream) {
241
+ let assistantResponse = '';
242
+ // Stream the response in real-time
243
+ completionOptions.onChunk = (chunk) => {
244
+ if (chunk.choices && chunk.choices[0] && chunk.choices[0].delta && chunk.choices[0].delta.content) {
245
+ const content = chunk.choices[0].delta.content;
246
+ try {
247
+ process.stdout.write(content);
248
+ }
249
+ catch (error) {
250
+ // Handle EPIPE errors gracefully (when pipe is closed)
251
+ if (error.code === 'EPIPE') {
252
+ // Stop streaming if the pipe is closed
253
+ return;
254
+ }
255
+ throw error;
256
+ }
257
+ assistantResponse += content;
258
+ }
259
+ };
260
+ try {
261
+ yield chatService.createCompletion(completionOptions);
262
+ }
263
+ catch (streamError) {
264
+ console.error(chalk_1.default.red('\nStreaming error:'), streamError);
265
+ // Fallback to non-streaming if streaming fails
266
+ console.log(chalk_1.default.yellow('Falling back to non-streaming mode...'));
267
+ completionOptions.stream = false;
268
+ delete completionOptions.onChunk;
269
+ const response = yield chatService.createCompletion(completionOptions);
270
+ if (response && response.choices && response.choices[0] && response.choices[0].message) {
271
+ assistantResponse = response.choices[0].message.content;
272
+ console.log(assistantResponse);
273
+ }
274
+ }
275
+ console.log(); // Add newline at the end
276
+ return;
277
+ }
278
+ const response = yield chatService.createCompletion(completionOptions);
279
+ // Check if response has the expected structure
280
+ if (!response ||
281
+ !response.choices ||
282
+ !response.choices[0] ||
283
+ !response.choices[0].message) {
284
+ console.error(chalk_1.default.red('Error: Unexpected response format from API'));
285
+ console.error(chalk_1.default.red('Response:', JSON.stringify(response, null, 2)));
286
+ throw new Error('Unexpected response format from API');
287
+ }
288
+ // Get assistant's response
289
+ const assistantMessage = response.choices[0].message.content;
290
+ // Display the response
291
+ if ((0, markdown_renderer_1.containsMarkdown)(assistantMessage)) {
292
+ console.log((0, markdown_renderer_1.renderMarkdown)(assistantMessage));
293
+ }
294
+ else {
295
+ console.log(assistantMessage);
296
+ }
297
+ return;
298
+ }
299
+ catch (error) {
300
+ console.error(chalk_1.default.red('Error: Failed to get response'));
301
+ if (error instanceof Error) {
302
+ console.error(chalk_1.default.red(error.message));
303
+ }
304
+ process.exit(1);
305
+ }
306
+ }
307
+ // Set up readline interface for user input (only for interactive mode)
308
+ const rl = readline_1.default.createInterface({
309
+ input: process.stdin,
310
+ output: process.stdout,
311
+ });
185
312
  console.log(chalk_1.default.cyan('Chat with Berget AI (type "exit" to quit)'));
186
313
  console.log(chalk_1.default.cyan('----------------------------------------'));
187
314
  // Start the conversation loop
188
315
  const askQuestion = () => {
189
316
  rl.question(chalk_1.default.green('You: '), (input) => __awaiter(this, void 0, void 0, function* () {
190
- var _a;
191
317
  // Check if user wants to exit
192
318
  if (input.toLowerCase() === 'exit') {
193
319
  console.log(chalk_1.default.cyan('Goodbye!'));
@@ -202,30 +328,53 @@ function registerChatCommands(program) {
202
328
  try {
203
329
  // Call the API
204
330
  const completionOptions = {
205
- model: ((_a = options.args) === null || _a === void 0 ? void 0 : _a[0]) || 'google/gemma-3-27b-it',
331
+ model: model || 'openai/gpt-oss',
206
332
  messages: messages,
207
333
  temperature: options.temperature !== undefined ? options.temperature : 0.7,
208
334
  max_tokens: options.maxTokens || 4096,
209
- stream: options.stream || false
335
+ stream: options.stream !== false
210
336
  };
211
337
  // Only add apiKey if it actually exists
212
338
  if (apiKey) {
213
339
  completionOptions.apiKey = apiKey;
214
340
  }
215
- // Add streaming support
216
- if (options.stream) {
341
+ // Add streaming support (now default)
342
+ if (completionOptions.stream) {
217
343
  let assistantResponse = '';
218
344
  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
345
+ // Stream the response in real-time
221
346
  completionOptions.onChunk = (chunk) => {
222
347
  if (chunk.choices && chunk.choices[0] && chunk.choices[0].delta && chunk.choices[0].delta.content) {
223
348
  const content = chunk.choices[0].delta.content;
224
- process.stdout.write(content);
349
+ try {
350
+ process.stdout.write(content);
351
+ }
352
+ catch (error) {
353
+ // Handle EPIPE errors gracefully (when pipe is closed)
354
+ if (error.code === 'EPIPE') {
355
+ // Stop streaming if the pipe is closed
356
+ return;
357
+ }
358
+ throw error;
359
+ }
225
360
  assistantResponse += content;
226
361
  }
227
362
  };
228
- yield chatService.createCompletion(completionOptions);
363
+ try {
364
+ yield chatService.createCompletion(completionOptions);
365
+ }
366
+ catch (streamError) {
367
+ console.error(chalk_1.default.red('\nStreaming error:'), streamError);
368
+ // Fallback to non-streaming if streaming fails
369
+ console.log(chalk_1.default.yellow('Falling back to non-streaming mode...'));
370
+ completionOptions.stream = false;
371
+ delete completionOptions.onChunk;
372
+ const response = yield chatService.createCompletion(completionOptions);
373
+ if (response && response.choices && response.choices[0] && response.choices[0].message) {
374
+ assistantResponse = response.choices[0].message.content;
375
+ console.log(assistantResponse);
376
+ }
377
+ }
229
378
  console.log('\n');
230
379
  // Add assistant response to messages
231
380
  messages.push({
@@ -256,26 +256,26 @@ class ChatService {
256
256
  */
257
257
  handleStreamingResponse(options, headers) {
258
258
  return __awaiter(this, void 0, void 0, function* () {
259
- logger_1.logger.debug('Handling streaming response');
260
- // Create URL with query parameters
261
- const url = new URL(`${client_1.API_BASE_URL}/v1/chat/completions`);
262
- // Debug the headers and options
263
- logger_1.logger.debug('Streaming headers:');
264
- logger_1.logger.debug(JSON.stringify(headers, null, 2));
265
- logger_1.logger.debug('Streaming options:');
266
- logger_1.logger.debug(JSON.stringify(Object.assign(Object.assign({}, options), { onChunk: options.onChunk ? 'function present' : 'no function' }), null, 2));
259
+ // Use the same base URL as the client
260
+ const baseUrl = process.env.API_BASE_URL || 'https://api.berget.ai';
261
+ const url = new URL(`${baseUrl}/v1/chat/completions`);
267
262
  try {
263
+ logger_1.logger.debug(`Making streaming request to: ${url.toString()}`);
264
+ logger_1.logger.debug(`Headers:`, JSON.stringify(headers, null, 2));
265
+ logger_1.logger.debug(`Body:`, JSON.stringify(options, null, 2));
268
266
  // Make fetch request directly to handle streaming
269
267
  const response = yield fetch(url.toString(), {
270
268
  method: 'POST',
271
269
  headers: Object.assign({ 'Content-Type': 'application/json', Accept: 'text/event-stream' }, headers),
272
270
  body: JSON.stringify(options),
273
271
  });
272
+ logger_1.logger.debug(`Response status: ${response.status}`);
273
+ logger_1.logger.debug(`Response headers:`, JSON.stringify(Object.fromEntries(response.headers.entries()), null, 2));
274
274
  if (!response.ok) {
275
275
  const errorText = yield response.text();
276
276
  logger_1.logger.error(`Stream request failed: ${response.status} ${response.statusText}`);
277
- logger_1.logger.debug(`Error response: ${errorText}`);
278
- throw new Error(`Stream request failed: ${response.status} ${response.statusText}`);
277
+ logger_1.logger.error(`Error response: ${errorText}`);
278
+ throw new Error(`Stream request failed: ${response.status} ${response.statusText} - ${errorText}`);
279
279
  }
280
280
  if (!response.body) {
281
281
  throw new Error('No response body received');