Handle Google native generateContent / streamGenerateContent.
(self, body: bytes, stream: bool)
| 739 | return "\n\n".join(p for p in parts if p) |
| 740 | |
| 741 | def _handle_google_generate(self, body: bytes, stream: bool): |
| 742 | """Handle Google native generateContent / streamGenerateContent.""" |
| 743 | req = json.loads(body) |
| 744 | model_name = self._parse_google_model_from_path() |
| 745 | if not model_name: |
| 746 | self.send_json({"error": {"message": "model not specified in path"}}, 400) |
| 747 | return |
| 748 | |
| 749 | model_name, model_id, think_mode, err = self._resolve_model(model_name) |
| 750 | if err: |
| 751 | self.send_json({"error": {"message": err}}, 400) |
| 752 | return |
| 753 | |
| 754 | prompt = self._google_contents_to_prompt(req) |
| 755 | if not prompt.strip(): |
| 756 | self.send_json({"error": {"message": "empty content"}}, 400) |
| 757 | return |
| 758 | |
| 759 | try: |
| 760 | text, _ = self._call_gemini(prompt, model_id, think_mode, None) |
| 761 | except Exception as e: |
| 762 | self.send_json({"error": {"message": f"upstream error: {e}"}}, 502) |
| 763 | return |
| 764 | |
| 765 | candidate = { |
| 766 | "content": {"parts": [{"text": text or ""}], "role": "model"}, |
| 767 | "finishReason": "STOP", |
| 768 | "index": 0, |
| 769 | } |
| 770 | usage = { |
| 771 | "promptTokenCount": len(prompt) // 4, |
| 772 | "candidatesTokenCount": len(text) // 4, |
| 773 | "totalTokenCount": (len(prompt) + len(text)) // 4, |
| 774 | } |
| 775 | response_obj = { |
| 776 | "candidates": [candidate], |
| 777 | "usageMetadata": usage, |
| 778 | "modelVersion": model_name, |
| 779 | } |
| 780 | |
| 781 | if stream: |
| 782 | self.send_response(200) |
| 783 | self.send_header("Content-Type", "text/event-stream") |
| 784 | self.send_header("Cache-Control", "no-cache") |
| 785 | self.send_header("Access-Control-Allow-Origin", "*") |
| 786 | self.end_headers() |
| 787 | self.wfile.write(f"data: {json.dumps(response_obj)}\n\n".encode()) |
| 788 | self.wfile.flush() |
| 789 | else: |
| 790 | self.send_json(response_obj) |
| 791 | |
| 792 | |
| 793 | # ─── Main ──────────────────────────────────────────────────────────────────── |
no test coverage detected