gemini-agent-framework 0.1.15__py3-none-any.whl → 0.2.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
gemini_agent/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  from .agent import Agent
2
2
 
3
- __version__ = "0.1.15"
3
+ __version__ = "0.2.2"
4
4
  __all__ = ["Agent"]
gemini_agent/agent.py CHANGED
@@ -274,40 +274,56 @@ class Agent:
274
274
  """Substitutes variable references in arguments with their actual values."""
275
275
  result = {}
276
276
  for key, value in args.items():
277
- print("substituting variables", key, value)
278
277
  if isinstance(value, str) and value.startswith("$"):
279
- print("is string and starts with $")
280
278
  # Handle $ prefixed variables
281
279
  var_name = value[1:]
282
280
  if var_name in self._stored_variables:
283
- print("substituted")
284
281
 
285
282
  result[key] = self._stored_variables[var_name]["value"]
286
283
  else:
287
284
  result[key] = value
288
285
  elif isinstance(value, dict) and "variable" in value:
289
- print("is dict and has variable")
290
286
  # Handle dictionary-style variable references
291
287
  var_name = value["variable"]
292
288
  if var_name in self._stored_variables:
293
- print("substituted")
294
289
  result[key] = self._stored_variables[var_name]["value"]
295
290
  else:
296
- print("substituted")
297
291
  result[key] = value
298
292
  else:
299
293
  result[key] = value
300
294
  return result
301
295
 
302
- def _call_gemini_api(self, payload: Dict[str, Any]) -> Dict[str, Any]:
296
+ def _call_gemini_api(self, payload: Dict[str, Any], debug_scope: Optional[str] = None) -> Dict[str, Any]:
303
297
  """Makes a call to the Gemini API."""
304
298
  response = requests.post(
305
299
  f"{self.base_url}:generateContent?key={self.api_key}",
306
300
  headers=self.headers,
307
301
  json=payload,
308
302
  )
309
- response.raise_for_status()
310
- return response.json()
303
+ response_data = response.json()
304
+ self._log_text(response_data, debug_scope)
305
+
306
+ if not response.ok:
307
+ error_details = response_data.get('error', {})
308
+ error_message = f"Gemini API Error: {error_details.get('message', 'Unknown error')}"
309
+ if 'details' in error_details:
310
+ error_message += f"\nDetails: {error_details['details']}"
311
+ raise requests.exceptions.HTTPError(error_message, response=response)
312
+
313
+ return response_data
314
+
315
+ def _log_json(self, json_data: Dict[str, Any], file_name: str, debug_scope: Optional[str] = None) -> None:
316
+ """Logs the JSON data to a file."""
317
+ print("in log json")
318
+ if "json" not in debug_scope:
319
+ return
320
+ with open(file_name, "w") as f:
321
+ json.dump(json_data, f)
322
+ def _log_text(self, text: str, debug_scope: Optional[str] = None) -> None:
323
+ """Logs the text to a file."""
324
+ if "text" not in debug_scope:
325
+ return
326
+ print(text)
311
327
 
312
328
  def prompt(
313
329
  self,
@@ -315,6 +331,7 @@ class Agent:
315
331
  system_prompt: Optional[str] = None,
316
332
  response_structure: Optional[Dict[str, Any]] = None,
317
333
  conversation_history: Optional[List[Dict[str, Any]]] = None,
334
+ debug_scope: Optional[str] = [],
318
335
  ) -> Any:
319
336
  """
320
337
  Sends a prompt to the Gemini model and processes the response.
@@ -331,7 +348,6 @@ class Agent:
331
348
  self._intermediate_results = {}
332
349
 
333
350
 
334
-
335
351
  current_contents = conversation_history if conversation_history else []
336
352
 
337
353
  # Add system instruction to payload
@@ -367,13 +383,16 @@ class Agent:
367
383
  }
368
384
  final_mime_type = "application/json"
369
385
  final_response_schema = response_structure
370
-
386
+ count = 0
371
387
  while True:
372
-
373
- response_data = self._call_gemini_api(payload)
388
+ self._log_json(payload, f"payload_{count}.json", debug_scope)
389
+ count += 1
390
+ response_data = self._call_gemini_api(payload, debug_scope)
391
+ print("response data " , response_data)
374
392
  if "error" in response_data:
375
- print(
393
+ self._log_text(
376
394
  f"API call failed: {response_data['error'].get('message', 'Unknown API error')}"
395
+ , debug_scope
377
396
  )
378
397
  return response_data
379
398
 
@@ -384,24 +403,26 @@ class Agent:
384
403
  error_msg = f"Request blocked by API. Reason: {block_reason}."
385
404
  if safety_ratings:
386
405
  error_msg += f" Details: {json.dumps(safety_ratings)}"
387
- print(error_msg)
406
+
407
+ self._log_text(error_msg, debug_scope)
388
408
  return {"error": {"message": error_msg, "details": feedback}}
389
-
409
+
390
410
  try:
391
411
  candidate = response_data["candidates"][0]
392
412
  content = candidate["content"]
393
413
 
394
414
  for part in content["parts"]:
395
- payload["contents"].append({"role": "model", "parts": [part]})
415
+
396
416
 
397
417
  if "functionCall" in part:
418
+ payload["contents"].append({"role": "model", "parts": [part]})
398
419
  fc = part["functionCall"]
399
420
  tool_name = fc["name"]
400
421
  args = fc.get("args", {})
401
422
 
402
423
  if tool_name not in self._tool_functions:
403
424
  error_msg = f"Model attempted to call unknown function '{tool_name}'."
404
- print(f"Error: {error_msg}")
425
+ self._log_text(f"Error: {error_msg}", debug_scope)
405
426
  error_response_part = {
406
427
  "functionResponse": {
407
428
  "name": tool_name,
@@ -415,7 +436,7 @@ class Agent:
415
436
 
416
437
  try:
417
438
  tool_function = self._tool_functions[tool_name]
418
- print(f"--- Calling Function: {tool_name}({args}) ---")
439
+ self._log_text(f"--- Calling Function: {tool_name}({args}) ---", debug_scope)
419
440
 
420
441
  # Substitute both stored variables and intermediate results
421
442
  args = self._substitute_variables(args)
@@ -428,7 +449,7 @@ class Agent:
428
449
  # Call the function directly - it's already bound if it's a method
429
450
  function_result = tool_function(**args)
430
451
 
431
- print(f"--- Function Result: {function_result} ---")
452
+ self._log_text(f"--- Function Result: {function_result} ---", debug_scope)
432
453
 
433
454
  result_key = f"result_{len(self._intermediate_results)}"
434
455
  self._intermediate_results[result_key] = function_result
@@ -465,7 +486,7 @@ class Agent:
465
486
  )
466
487
 
467
488
  except Exception as e:
468
- print(f"Error executing function {tool_name}: {e}")
489
+ self._log_text(f"Error executing function {tool_name}: {e}", debug_scope)
469
490
  error_msg = f"Error during execution of tool '{tool_name}': {e}"
470
491
  error_response_part = {
471
492
  "functionResponse": {
@@ -490,8 +511,9 @@ class Agent:
490
511
  ):
491
512
  return structured_output
492
513
  except json.JSONDecodeError as e:
493
- print(
494
- f"Warning: Failed to parse initially structured output: {e}. Continuing with raw text."
514
+ self._log_text(
515
+ f"Warning: Failed to parse initially structured output: {e}. Continuing with raw text.",
516
+ debug_scope
495
517
  )
496
518
 
497
519
  elif apply_structure_later:
@@ -499,14 +521,15 @@ class Agent:
499
521
  "functionCall" in p
500
522
  for p in content["parts"][content["parts"].index(part) + 1 :]
501
523
  ):
502
- print("--- Attempting final structuring call ---")
524
+ self._log_text("--- Attempting final structuring call ---", debug_scope)
525
+ # Include the full conversation history in the formatting payload
503
526
  formatting_payload = {
504
- "contents": [
527
+ "contents": payload["contents"] + [
505
528
  {
506
529
  "role": "user",
507
530
  "parts": [
508
531
  {
509
- "text": f"Please format the following information according to the requested JSON structure:\n\n{final_text}"
532
+ "text": f"Based on our conversation above, please format the following information according to the requested JSON structure:\n\n{final_text}"
510
533
  }
511
534
  ],
512
535
  }
@@ -516,11 +539,14 @@ class Agent:
516
539
  "response_schema": response_structure,
517
540
  },
518
541
  }
519
- structured_response_data = self._call_gemini_api(formatting_payload)
542
+ self._log_json(formatting_payload, f"formatting_payload_{count}.json", debug_scope)
543
+ count += 1
544
+ structured_response_data = self._call_gemini_api(formatting_payload, debug_scope)
520
545
 
521
546
  if "error" in structured_response_data:
522
- print(
523
- f"Structuring call failed: {structured_response_data['error']}. Returning intermediate text."
547
+ self._log_text(
548
+ f"Structuring call failed: {structured_response_data['error']}. Returning intermediate text.",
549
+ debug_scope
524
550
  )
525
551
  return final_text
526
552
 
@@ -531,8 +557,9 @@ class Agent:
531
557
  structured_output = json.loads(structured_text)
532
558
  return structured_output
533
559
  except (KeyError, IndexError, json.JSONDecodeError) as e:
534
- print(
535
- f"Warning: Failed to parse structured output after formatting call: {e}. Returning intermediate text."
560
+ self._log_text(
561
+ f"Warning: Failed to parse structured output after formatting call: {e}. Returning intermediate text.",
562
+ debug_scope
536
563
  )
537
564
  return final_text
538
565
 
@@ -541,7 +568,7 @@ class Agent:
541
568
  for p in content["parts"][content["parts"].index(part) + 1 :]
542
569
  ):
543
570
  if response_structure and not apply_structure_later:
544
- print("--- Attempting final structuring call ---")
571
+ self._log_text("--- Attempting final structuring call ---", debug_scope)
545
572
  formatting_payload = {
546
573
  "contents": [
547
574
  {
@@ -558,11 +585,14 @@ class Agent:
558
585
  "response_schema": response_structure,
559
586
  },
560
587
  }
561
- structured_response_data = self._call_gemini_api(formatting_payload)
588
+ self._log_json(formatting_payload, f"formatting_payload_{count}.json", debug_scope)
589
+ count += 1
590
+ structured_response_data = self._call_gemini_api(formatting_payload, debug_scope)
562
591
 
563
592
  if "error" in structured_response_data:
564
- print(
593
+ self._log_text(
565
594
  f"Structuring call failed: {structured_response_data['error']}. Returning intermediate text."
595
+ , debug_scope
566
596
  )
567
597
  return final_text
568
598
 
@@ -573,15 +603,16 @@ class Agent:
573
603
  structured_output = json.loads(structured_text)
574
604
  return structured_output
575
605
  except (KeyError, IndexError, json.JSONDecodeError) as e:
576
- print(
577
- f"Warning: Failed to parse structured output after formatting call: {e}. Returning intermediate text."
606
+ self._log_text(
607
+ f"Warning: Failed to parse structured output after formatting call: {e}. Returning intermediate text.",
608
+ debug_scope
578
609
  )
579
610
  return final_text
580
611
  return final_text
581
612
  continue
582
613
 
583
614
  except (KeyError, IndexError) as e:
584
- print(f"Error parsing API response structure: {e}. Response: {response_data}")
615
+ self._log_text(f"Error parsing API response structure: {e}. Response: {response_data}", debug_scope)
585
616
  return {
586
617
  "error": {
587
618
  "message": f"Error parsing API response: {e}",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gemini-agent-framework
3
- Version: 0.1.15
3
+ Version: 0.2.2
4
4
  Summary: A framework for building agents that use Gemini's function calling capabilities
5
5
  Project-URL: Homepage, https://github.com/m7mdony/gemini-agent-framework
6
6
  Project-URL: Documentation, https://m7mdony.github.io/gemini-agent-framework
@@ -0,0 +1,6 @@
1
+ gemini_agent/__init__.py,sha256=2220VPV3WqLMo3kDIRmbjzxzY3O_kd0fkkbjjBWJ0-o,68
2
+ gemini_agent/agent.py,sha256=ymZLfcB_0W4pcnu8pFQwFRLUR2RpfMtOPTa51lb9gvg,28538
3
+ gemini_agent_framework-0.2.2.dist-info/METADATA,sha256=2Nk-YfrwziO79Al0yy2sidfpmBMx1qu4se7osek8mDo,5032
4
+ gemini_agent_framework-0.2.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
5
+ gemini_agent_framework-0.2.2.dist-info/licenses/LICENSE,sha256=NHp9eKeWbB-Fp6Ff24BXSemJOa6UEZa9IAp9U7O9oBM,1073
6
+ gemini_agent_framework-0.2.2.dist-info/RECORD,,
@@ -1,6 +0,0 @@
1
- gemini_agent/__init__.py,sha256=LFX-2Emo9kXG9rmleXchzu7GyCiwMpXLoxGETOEeKi8,69
2
- gemini_agent/agent.py,sha256=gdtr6GDKZJxq6_rgbDxvdkZmMB75vUcMop1eBrQ1adY,26527
3
- gemini_agent_framework-0.1.15.dist-info/METADATA,sha256=T9RiY-0KCOFbHkFazezxcD6-2NQdEwJPeirO_96OU64,5033
4
- gemini_agent_framework-0.1.15.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
5
- gemini_agent_framework-0.1.15.dist-info/licenses/LICENSE,sha256=NHp9eKeWbB-Fp6Ff24BXSemJOa6UEZa9IAp9U7O9oBM,1073
6
- gemini_agent_framework-0.1.15.dist-info/RECORD,,