MCPcopy
hub / github.com/Sophomoresty/gemini-web2api / _handle_google_generate

Method _handle_google_generate

gemini_web2api/server.py:313–408  ·  view source on GitHub ↗
(self, body: bytes, stream: bool)

Source from the content-addressed store, hash-verified

311 # ─── /v1beta/models (Google Gemini CLI) ──────────────────────────────────
312
313 def _handle_google_generate(self, body: bytes, stream: bool):
314 req = self._parse_body(body)
315 if req is None:
316 self.send_json({"error": {"message": "invalid JSON"}}, 400)
317 return
318 m = re.match(r'/v1beta/models/([^:?]+)', self.path)
319 model_name = m.group(1) if m else CONFIG["default_model"]
320 model_name, model_id, think_mode, err, extra_fields = resolve_model(model_name)
321 if err:
322 self.send_json({"error": {"message": err}}, 400)
323 return
324
325 tool_config = req.get("toolConfig", {})
326 fc_mode = tool_config.get("functionCallingConfig", {}).get("mode", "AUTO")
327 has_tools = bool(req.get("tools")) and fc_mode != "NONE"
328 prompt, images = google_contents_to_prompt(req)
329 if not prompt.strip():
330 self.send_json({"error": {"message": "empty content"}}, 400)
331 return
332
333 file_refs = _upload_images(images)
334 log(f"Google API: model={model_name} stream={stream} tools={has_tools} prompt_len={len(prompt)}")
335
336 if stream and not has_tools:
337 try:
338 self._start_sse()
339 full_text = ""
340 for delta in generate_stream(prompt, model_id, think_mode, file_refs, extra_fields):
341 if not delta:
342 continue
343 full_text += delta
344 chunk_obj = {
345 "candidates": [{"content": {"parts": [{"text": delta}], "role": "model"}, "index": 0}],
346 "modelVersion": model_name,
347 }
348 self.wfile.write(f"data: {json.dumps(chunk_obj, ensure_ascii=False)}\n\n".encode())
349 self.wfile.flush()
350 final_chunk = {
351 "candidates": [{"finishReason": "STOP", "index": 0}],
352 "usageMetadata": {
353 "promptTokenCount": len(prompt) // 4,
354 "candidatesTokenCount": len(full_text) // 4,
355 "totalTokenCount": (len(prompt) + len(full_text)) // 4,
356 },
357 "modelVersion": model_name,
358 }
359 self.wfile.write(f"data: {json.dumps(final_chunk, ensure_ascii=False)}\n\n".encode())
360 self.wfile.flush()
361 except (BrokenPipeError, ConnectionResetError):
362 pass
363 return
364
365 try:
366 text = generate(prompt, model_id, think_mode, file_refs, extra_fields)
367 except Exception as e:
368 self.send_json({"error": {"message": f"upstream error: {e}"}}, 502)
369 return
370

Callers 1

do_POSTMethod · 0.95

Calls 10

_parse_bodyMethod · 0.95
send_jsonMethod · 0.95
_start_sseMethod · 0.95
resolve_modelFunction · 0.85
_upload_imagesFunction · 0.85
generate_streamFunction · 0.85
generateFunction · 0.85
logFunction · 0.70

Tested by

no test coverage detected