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 +1 -1
- gemini_agent/agent.py +68 -37
- {gemini_agent_framework-0.1.15.dist-info → gemini_agent_framework-0.2.2.dist-info}/METADATA +1 -1
- gemini_agent_framework-0.2.2.dist-info/RECORD +6 -0
- gemini_agent_framework-0.1.15.dist-info/RECORD +0 -6
- {gemini_agent_framework-0.1.15.dist-info → gemini_agent_framework-0.2.2.dist-info}/WHEEL +0 -0
- {gemini_agent_framework-0.1.15.dist-info → gemini_agent_framework-0.2.2.dist-info}/licenses/LICENSE +0 -0
gemini_agent/__init__.py
CHANGED
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.
|
310
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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"
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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.
|
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,,
|
File without changes
|
{gemini_agent_framework-0.1.15.dist-info → gemini_agent_framework-0.2.2.dist-info}/licenses/LICENSE
RENAMED
File without changes
|