()
| 354 | |
| 355 | // ---- Helper: send messages and stream response ---- |
| 356 | async function sendMessages(): Promise<void> { |
| 357 | if (state.messages.length === 0) { |
| 358 | stdout.write(`${dim}No messages to send. Type something first.${reset}\n`); |
| 359 | return; |
| 360 | } |
| 361 | |
| 362 | const body: ChatRequest = { |
| 363 | model: state.model, |
| 364 | messages: state.messages, |
| 365 | max_tokens: state.maxTokens, |
| 366 | stream: true, |
| 367 | }; |
| 368 | if (state.system) body.system = state.system; |
| 369 | if (state.temperature !== undefined) body.temperature = state.temperature; |
| 370 | if (state.topP !== undefined) body.top_p = state.topP; |
| 371 | |
| 372 | waitingForResponse = true; |
| 373 | const url = chatEndpoint(config.baseUrl); |
| 374 | |
| 375 | try { |
| 376 | const res = await request(config, { |
| 377 | url, |
| 378 | method: 'POST', |
| 379 | body, |
| 380 | stream: true, |
| 381 | authStyle: 'x-api-key', |
| 382 | }); |
| 383 | |
| 384 | const contentType = res.headers.get('content-type') || ''; |
| 385 | if (!contentType.includes('text/event-stream') && !contentType.includes('stream')) { |
| 386 | throw new CLIError( |
| 387 | `Expected SSE stream but got content-type "${contentType}".`, |
| 388 | ExitCode.GENERAL, |
| 389 | ); |
| 390 | } |
| 391 | |
| 392 | let textContent = ''; |
| 393 | let inThinking = false; |
| 394 | |
| 395 | for await (const event of parseSSE(res)) { |
| 396 | if (event.data === '[DONE]') break; |
| 397 | try { |
| 398 | const parsed = JSON.parse(event.data) as StreamEvent; |
| 399 | |
| 400 | if (parsed.type === 'content_block_start') { |
| 401 | if (parsed.content_block.type === 'thinking') { |
| 402 | inThinking = true; |
| 403 | stdout.write(`${dim}Thinking:\n`); |
| 404 | } else if (parsed.content_block.type === 'text' && inThinking) { |
| 405 | stdout.write(`${reset}\nResponse:\n`); |
| 406 | inThinking = false; |
| 407 | } |
| 408 | } else if (parsed.type === 'content_block_delta') { |
| 409 | if (parsed.delta.type === 'text_delta') { |
| 410 | textContent += parsed.delta.text; |
| 411 | stdout.write(parsed.delta.text); |
| 412 | } else if (parsed.delta.type === 'thinking_delta') { |
| 413 | stdout.write(parsed.delta.thinking); |
no test coverage detected