package lib import ( "bytes" "encoding/json" "fmt" "io" "net/http" "strings" ) // CallOpenRouter sends a request to OpenRouter (OpenAI-compatible API). func CallOpenRouter(apiKey, model string, messages []map[string]interface{}, maxTokens int) (string, error) { if apiKey == "" { return "", fmt.Errorf("OpenRouter API key not configured") } reqBody := map[string]interface{}{ "model": model, "messages": messages, "max_tokens": maxTokens, "temperature": 0.1, } jsonBody, err := json.Marshal(reqBody) if err != nil { return "", fmt.Errorf("marshal request: %w", err) } req, err := http.NewRequest("POST", "https://openrouter.ai/api/v1/chat/completions", bytes.NewReader(jsonBody)) if err != nil { return "", fmt.Errorf("create request: %w", err) } req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "Bearer "+apiKey) resp, err := http.DefaultClient.Do(req) if err != nil { return "", fmt.Errorf("API request: %w", err) } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { return "", fmt.Errorf("read response: %w", err) } if resp.StatusCode != 200 { return "", fmt.Errorf("OpenRouter API error %d: %s", resp.StatusCode, string(body)) } var oaiResp struct { Choices []struct { Message struct { Content string `json:"content"` } `json:"message"` } `json:"choices"` } if err := json.Unmarshal(body, &oaiResp); err != nil { return "", fmt.Errorf("parse response: %w", err) } if len(oaiResp.Choices) == 0 { return "", fmt.Errorf("empty response from OpenRouter") } text := strings.TrimSpace(oaiResp.Choices[0].Message.Content) text = strings.TrimPrefix(text, "```json") text = strings.TrimPrefix(text, "```") text = strings.TrimSuffix(text, "```") return strings.TrimSpace(text), nil }