(message, config)
| 2666 | |
| 2667 | // Streaming version for when no tools are needed (direct responses) |
| 2668 | async function sendToModel(message, config) { |
| 2669 | const target = config.activeModelTarget || getModelTarget(config, 'default'); |
| 2670 | const requestConfig = withModelTarget(config, target); |
| 2671 | const baseUrl = target.baseUrl || process.env.OLLAMA_HOST || 'http://localhost:11434'; |
| 2672 | const systemPrompt = `You are SmallCode, a coding assistant. You help users by reading, editing, and creating code files. |
| 2673 | Rules: |
| 2674 | - Read files before editing them. |
| 2675 | - Use search-and-replace for edits. Never rewrite entire files. |
| 2676 | - Keep responses concise and focused. |
| 2677 | - If a task is complex, break it into steps.`; |
| 2678 | |
| 2679 | // OpenAI-compatible (LM Studio, vLLM, etc.) |
| 2680 | if (target.provider === 'openai' || baseUrl.includes('/v1')) { |
| 2681 | try { |
| 2682 | const headers = buildAuthHeaders(requestConfig); |
| 2683 | |
| 2684 | const response = await fetch(`${baseUrl}/chat/completions`, { |
| 2685 | method: 'POST', |
| 2686 | headers, |
| 2687 | body: JSON.stringify({ |
| 2688 | model: target.model, |
| 2689 | messages: [ |
| 2690 | { role: 'system', content: systemPrompt }, |
| 2691 | { role: 'user', content: message }, |
| 2692 | ], |
| 2693 | stream: true, |
| 2694 | temperature: 0.1, |
| 2695 | max_tokens: 4096, |
| 2696 | }), |
| 2697 | }); |
| 2698 | |
| 2699 | if (!response.ok) { |
| 2700 | const err = await response.text(); |
| 2701 | console.log(` ✗ LM Studio error: ${response.status} ${err.slice(0, 200)}`); |
| 2702 | return; |
| 2703 | } |
| 2704 | |
| 2705 | const reader = response.body.getReader(); |
| 2706 | const decoder = new TextDecoder(); |
| 2707 | let buffer = ''; |
| 2708 | |
| 2709 | while (true) { |
| 2710 | const { done, value } = await reader.read(); |
| 2711 | if (done) break; |
| 2712 | |
| 2713 | buffer += decoder.decode(value, { stream: true }); |
| 2714 | const lines = buffer.split('\n'); |
| 2715 | buffer = lines.pop() || ''; |
| 2716 | |
| 2717 | for (const line of lines) { |
| 2718 | if (!line.trim() || !line.startsWith('data: ')) continue; |
| 2719 | const data = line.slice(6); |
| 2720 | if (data === '[DONE]') { console.log(''); return; } |
| 2721 | try { |
| 2722 | const chunk = JSON.parse(data); |
| 2723 | const delta = chunk.choices?.[0]?.delta; |
| 2724 | if (delta?.content) { |
| 2725 | process.stdout.write(delta.content); |
nothing calls this directly
no test coverage detected