deepcode-hku 1.0.7__tar.gz → 1.0.8__tar.gz

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.
Files changed (65) hide show
  1. {deepcode_hku-1.0.7/deepcode_hku.egg-info → deepcode_hku-1.0.8}/PKG-INFO +26 -1
  2. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/README.md +24 -0
  3. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/__init__.py +1 -1
  4. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8/deepcode_hku.egg-info}/PKG-INFO +26 -1
  5. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/deepcode_hku.egg-info/requires.txt +1 -0
  6. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/mcp_agent.config.yaml +33 -20
  7. deepcode_hku-1.0.8/mcp_agent.secrets.yaml +7 -0
  8. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/requirements.txt +1 -0
  9. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/utils/llm_utils.py +74 -23
  10. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/workflows/agents/memory_agent_concise.py +51 -2
  11. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/workflows/agents/memory_agent_concise_index.py +51 -2
  12. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/workflows/agents/memory_agent_concise_multi.py +50 -1
  13. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/workflows/code_implementation_workflow.py +292 -17
  14. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/workflows/code_implementation_workflow_index.py +278 -14
  15. deepcode_hku-1.0.7/mcp_agent.secrets.yaml +0 -9
  16. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/.pre-commit-config.yaml +0 -0
  17. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/LICENSE +0 -0
  18. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/MANIFEST.in +0 -0
  19. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/cli/__init__.py +0 -0
  20. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/cli/cli_app.py +0 -0
  21. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/cli/cli_interface.py +0 -0
  22. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/cli/cli_launcher.py +0 -0
  23. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/cli/main_cli.py +0 -0
  24. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/cli/workflows/__init__.py +0 -0
  25. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/cli/workflows/cli_workflow_adapter.py +0 -0
  26. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/deepcode.py +0 -0
  27. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/deepcode_hku.egg-info/SOURCES.txt +0 -0
  28. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/deepcode_hku.egg-info/dependency_links.txt +0 -0
  29. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/deepcode_hku.egg-info/entry_points.txt +0 -0
  30. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/deepcode_hku.egg-info/top_level.txt +0 -0
  31. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/prompts/code_prompts.py +0 -0
  32. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/schema/mcp-agent.config.schema.json +0 -0
  33. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/setup.cfg +0 -0
  34. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/setup.py +0 -0
  35. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/tools/__init__.py +0 -0
  36. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/tools/bocha_search_server.py +0 -0
  37. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/tools/code_implementation_server.py +0 -0
  38. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/tools/code_indexer.py +0 -0
  39. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/tools/code_reference_indexer.py +0 -0
  40. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/tools/command_executor.py +0 -0
  41. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/tools/document_segmentation_server.py +0 -0
  42. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/tools/git_command.py +0 -0
  43. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/tools/pdf_converter.py +0 -0
  44. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/tools/pdf_downloader.py +0 -0
  45. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/tools/pdf_utils.py +0 -0
  46. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/ui/__init__.py +0 -0
  47. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/ui/app.py +0 -0
  48. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/ui/components.py +0 -0
  49. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/ui/handlers.py +0 -0
  50. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/ui/layout.py +0 -0
  51. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/ui/streamlit_app.py +0 -0
  52. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/ui/styles.py +0 -0
  53. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/utils/__init__.py +0 -0
  54. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/utils/cli_interface.py +0 -0
  55. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/utils/cross_platform_file_handler.py +0 -0
  56. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/utils/dialogue_logger.py +0 -0
  57. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/utils/file_processor.py +0 -0
  58. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/utils/simple_llm_logger.py +0 -0
  59. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/workflows/__init__.py +0 -0
  60. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/workflows/agent_orchestration_engine.py +0 -0
  61. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/workflows/agents/__init__.py +0 -0
  62. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/workflows/agents/code_implementation_agent.py +0 -0
  63. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/workflows/agents/document_segmentation_agent.py +0 -0
  64. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/workflows/agents/requirement_analysis_agent.py +0 -0
  65. {deepcode_hku-1.0.7 → deepcode_hku-1.0.8}/workflows/codebase_index_workflow.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deepcode-hku
3
- Version: 1.0.7
3
+ Version: 1.0.8
4
4
  Summary: AI Research Engine - Transform research papers into working code automatically
5
5
  Home-page: https://github.com/HKUDS/DeepCode
6
6
  Author: DeepCodeTeam
@@ -24,6 +24,7 @@ Requires-Dist: aiohttp>=3.8.0
24
24
  Requires-Dist: anthropic
25
25
  Requires-Dist: asyncio-mqtt
26
26
  Requires-Dist: docling
27
+ Requires-Dist: google-genai
27
28
  Requires-Dist: mcp-agent
28
29
  Requires-Dist: mcp-server-git
29
30
  Requires-Dist: nest_asyncio
@@ -587,6 +588,14 @@ curl -O https://raw.githubusercontent.com/HKUDS/DeepCode/main/mcp_agent.secrets.
587
588
  # Edit mcp_agent.secrets.yaml with your API keys and base_url:
588
589
  # - openai: api_key, base_url (for OpenAI/custom endpoints)
589
590
  # - anthropic: api_key (for Claude models)
591
+ # - google: api_key (for Gemini models)
592
+
593
+ # 🤖 Select your preferred LLM provider (optional)
594
+ # Edit mcp_agent.config.yaml to choose your LLM (line ~106):
595
+ # - llm_provider: "google" # Use Google Gemini models
596
+ # - llm_provider: "anthropic" # Use Anthropic Claude models
597
+ # - llm_provider: "openai" # Use OpenAI/compatible models
598
+ # Note: If not set or unavailable, will automatically fallback to first available provider
590
599
 
591
600
  # 🔑 Configure search API keys for web search (optional)
592
601
  # Edit mcp_agent.config.yaml to set your API keys:
@@ -623,6 +632,14 @@ uv pip install -r requirements.txt
623
632
  # Edit mcp_agent.secrets.yaml with your API keys and base_url:
624
633
  # - openai: api_key, base_url (for OpenAI/custom endpoints)
625
634
  # - anthropic: api_key (for Claude models)
635
+ # - google: api_key (for Gemini models)
636
+
637
+ # 🤖 Select your preferred LLM provider (optional)
638
+ # Edit mcp_agent.config.yaml to choose your LLM (line ~106):
639
+ # - llm_provider: "google" # Use Google Gemini models
640
+ # - llm_provider: "anthropic" # Use Anthropic Claude models
641
+ # - llm_provider: "openai" # Use OpenAI/compatible models
642
+ # Note: If not set or unavailable, will automatically fallback to first available provider
626
643
 
627
644
  # 🔑 Configure search API keys for web search (optional)
628
645
  # Edit mcp_agent.config.yaml to set your API keys:
@@ -649,6 +666,14 @@ pip install -r requirements.txt
649
666
  # Edit mcp_agent.secrets.yaml with your API keys and base_url:
650
667
  # - openai: api_key, base_url (for OpenAI/custom endpoints)
651
668
  # - anthropic: api_key (for Claude models)
669
+ # - google: api_key (for Gemini models)
670
+
671
+ # 🤖 Select your preferred LLM provider (optional)
672
+ # Edit mcp_agent.config.yaml to choose your LLM (line ~106):
673
+ # - llm_provider: "google" # Use Google Gemini models
674
+ # - llm_provider: "anthropic" # Use Anthropic Claude models
675
+ # - llm_provider: "openai" # Use OpenAI/compatible models
676
+ # Note: If not set or unavailable, will automatically fallback to first available provider
652
677
 
653
678
  # 🔑 Configure search API keys for web search (optional)
654
679
  # Edit mcp_agent.config.yaml to set your API keys:
@@ -542,6 +542,14 @@ curl -O https://raw.githubusercontent.com/HKUDS/DeepCode/main/mcp_agent.secrets.
542
542
  # Edit mcp_agent.secrets.yaml with your API keys and base_url:
543
543
  # - openai: api_key, base_url (for OpenAI/custom endpoints)
544
544
  # - anthropic: api_key (for Claude models)
545
+ # - google: api_key (for Gemini models)
546
+
547
+ # 🤖 Select your preferred LLM provider (optional)
548
+ # Edit mcp_agent.config.yaml to choose your LLM (line ~106):
549
+ # - llm_provider: "google" # Use Google Gemini models
550
+ # - llm_provider: "anthropic" # Use Anthropic Claude models
551
+ # - llm_provider: "openai" # Use OpenAI/compatible models
552
+ # Note: If not set or unavailable, will automatically fallback to first available provider
545
553
 
546
554
  # 🔑 Configure search API keys for web search (optional)
547
555
  # Edit mcp_agent.config.yaml to set your API keys:
@@ -578,6 +586,14 @@ uv pip install -r requirements.txt
578
586
  # Edit mcp_agent.secrets.yaml with your API keys and base_url:
579
587
  # - openai: api_key, base_url (for OpenAI/custom endpoints)
580
588
  # - anthropic: api_key (for Claude models)
589
+ # - google: api_key (for Gemini models)
590
+
591
+ # 🤖 Select your preferred LLM provider (optional)
592
+ # Edit mcp_agent.config.yaml to choose your LLM (line ~106):
593
+ # - llm_provider: "google" # Use Google Gemini models
594
+ # - llm_provider: "anthropic" # Use Anthropic Claude models
595
+ # - llm_provider: "openai" # Use OpenAI/compatible models
596
+ # Note: If not set or unavailable, will automatically fallback to first available provider
581
597
 
582
598
  # 🔑 Configure search API keys for web search (optional)
583
599
  # Edit mcp_agent.config.yaml to set your API keys:
@@ -604,6 +620,14 @@ pip install -r requirements.txt
604
620
  # Edit mcp_agent.secrets.yaml with your API keys and base_url:
605
621
  # - openai: api_key, base_url (for OpenAI/custom endpoints)
606
622
  # - anthropic: api_key (for Claude models)
623
+ # - google: api_key (for Gemini models)
624
+
625
+ # 🤖 Select your preferred LLM provider (optional)
626
+ # Edit mcp_agent.config.yaml to choose your LLM (line ~106):
627
+ # - llm_provider: "google" # Use Google Gemini models
628
+ # - llm_provider: "anthropic" # Use Anthropic Claude models
629
+ # - llm_provider: "openai" # Use OpenAI/compatible models
630
+ # Note: If not set or unavailable, will automatically fallback to first available provider
607
631
 
608
632
  # 🔑 Configure search API keys for web search (optional)
609
633
  # Edit mcp_agent.config.yaml to set your API keys:
@@ -5,7 +5,7 @@ DeepCode - AI Research Engine
5
5
  ⚡ Transform research papers into working code automatically
6
6
  """
7
7
 
8
- __version__ = "1.0.7"
8
+ __version__ = "1.0.8"
9
9
  __author__ = "DeepCode Team"
10
10
  __url__ = "https://github.com/HKUDS/DeepCode"
11
11
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deepcode-hku
3
- Version: 1.0.7
3
+ Version: 1.0.8
4
4
  Summary: AI Research Engine - Transform research papers into working code automatically
5
5
  Home-page: https://github.com/HKUDS/DeepCode
6
6
  Author: DeepCodeTeam
@@ -24,6 +24,7 @@ Requires-Dist: aiohttp>=3.8.0
24
24
  Requires-Dist: anthropic
25
25
  Requires-Dist: asyncio-mqtt
26
26
  Requires-Dist: docling
27
+ Requires-Dist: google-genai
27
28
  Requires-Dist: mcp-agent
28
29
  Requires-Dist: mcp-server-git
29
30
  Requires-Dist: nest_asyncio
@@ -587,6 +588,14 @@ curl -O https://raw.githubusercontent.com/HKUDS/DeepCode/main/mcp_agent.secrets.
587
588
  # Edit mcp_agent.secrets.yaml with your API keys and base_url:
588
589
  # - openai: api_key, base_url (for OpenAI/custom endpoints)
589
590
  # - anthropic: api_key (for Claude models)
591
+ # - google: api_key (for Gemini models)
592
+
593
+ # 🤖 Select your preferred LLM provider (optional)
594
+ # Edit mcp_agent.config.yaml to choose your LLM (line ~106):
595
+ # - llm_provider: "google" # Use Google Gemini models
596
+ # - llm_provider: "anthropic" # Use Anthropic Claude models
597
+ # - llm_provider: "openai" # Use OpenAI/compatible models
598
+ # Note: If not set or unavailable, will automatically fallback to first available provider
590
599
 
591
600
  # 🔑 Configure search API keys for web search (optional)
592
601
  # Edit mcp_agent.config.yaml to set your API keys:
@@ -623,6 +632,14 @@ uv pip install -r requirements.txt
623
632
  # Edit mcp_agent.secrets.yaml with your API keys and base_url:
624
633
  # - openai: api_key, base_url (for OpenAI/custom endpoints)
625
634
  # - anthropic: api_key (for Claude models)
635
+ # - google: api_key (for Gemini models)
636
+
637
+ # 🤖 Select your preferred LLM provider (optional)
638
+ # Edit mcp_agent.config.yaml to choose your LLM (line ~106):
639
+ # - llm_provider: "google" # Use Google Gemini models
640
+ # - llm_provider: "anthropic" # Use Anthropic Claude models
641
+ # - llm_provider: "openai" # Use OpenAI/compatible models
642
+ # Note: If not set or unavailable, will automatically fallback to first available provider
626
643
 
627
644
  # 🔑 Configure search API keys for web search (optional)
628
645
  # Edit mcp_agent.config.yaml to set your API keys:
@@ -649,6 +666,14 @@ pip install -r requirements.txt
649
666
  # Edit mcp_agent.secrets.yaml with your API keys and base_url:
650
667
  # - openai: api_key, base_url (for OpenAI/custom endpoints)
651
668
  # - anthropic: api_key (for Claude models)
669
+ # - google: api_key (for Gemini models)
670
+
671
+ # 🤖 Select your preferred LLM provider (optional)
672
+ # Edit mcp_agent.config.yaml to choose your LLM (line ~106):
673
+ # - llm_provider: "google" # Use Google Gemini models
674
+ # - llm_provider: "anthropic" # Use Anthropic Claude models
675
+ # - llm_provider: "openai" # Use OpenAI/compatible models
676
+ # Note: If not set or unavailable, will automatically fallback to first available provider
652
677
 
653
678
  # 🔑 Configure search API keys for web search (optional)
654
679
  # Edit mcp_agent.config.yaml to set your API keys:
@@ -3,6 +3,7 @@ aiohttp>=3.8.0
3
3
  anthropic
4
4
  asyncio-mqtt
5
5
  docling
6
+ google-genai
6
7
  mcp-agent
7
8
  mcp-server-git
8
9
  nest_asyncio
@@ -26,32 +26,32 @@ mcp:
26
26
  PYTHONPATH: .
27
27
  brave:
28
28
  # macos and linux should use this
29
- # args:
30
- # - -y
31
- # - '@modelcontextprotocol/server-brave-search'
32
- # command: npx
29
+ args:
30
+ - -y
31
+ - '@modelcontextprotocol/server-brave-search'
32
+ command: npx
33
33
 
34
34
  # windows should use this
35
- args:
36
- # please use the correct path for your system
37
- - C:/Users/LEGION/AppData/Roaming/npm/node_modules/@modelcontextprotocol/server-brave-search/dist/index.js
38
- command: node
35
+ # args:
36
+ # # please use the correct path for your system
37
+ # - C:/Users/LEGION/AppData/Roaming/npm/node_modules/@modelcontextprotocol/server-brave-search/dist/index.js
38
+ # command: node
39
39
  env:
40
40
  BRAVE_API_KEY: ''
41
41
  filesystem:
42
42
  # macos and linux should use this
43
- # args:
44
- # - -y
45
- # - '@modelcontextprotocol/server-filesystem'
46
- # - .
47
- # command: npx
48
-
49
- # windows should use this
50
43
  args:
51
- # please use the correct path for your system
52
- - C:/Users/LEGION/AppData/Roaming/npm/node_modules/@modelcontextprotocol/server-filesystem/dist/index.js
44
+ - -y
45
+ - '@modelcontextprotocol/server-filesystem'
53
46
  - .
54
- command: node
47
+ command: npx
48
+
49
+ # windows should use this
50
+ # args:
51
+ # # please use the correct path for your system
52
+ # - C:/Users/LEGION/AppData/Roaming/npm/node_modules/@modelcontextprotocol/server-filesystem/dist/index.js
53
+ # - .
54
+ # command: node
55
55
 
56
56
 
57
57
  code-implementation:
@@ -100,14 +100,27 @@ mcp:
100
100
  command: python
101
101
  env:
102
102
  PYTHONPATH: .
103
+ # LLM Provider Priority (选择使用哪个LLM / Choose which LLM to use)
104
+ # Options: "anthropic", "google", "openai"
105
+ # If not set or provider unavailable, will fallback to first available provider
106
+ llm_provider: "google" # 设置为 "google", "anthropic", 或 "openai"
107
+
103
108
  openai:
104
109
  base_max_tokens: 40000
105
110
  # default_model: google/gemini-2.5-pro
106
- # default_model: anthropic/claude-sonnet-4.5
111
+ default_model: anthropic/claude-sonnet-4.5
107
112
  # default_model: openai/gpt-oss-120b
108
113
  # default_model: deepseek/deepseek-v3.2-exp
109
114
  # default_model: moonshotai/kimi-k2-thinking
110
- default_model: anthropic/claude-3.5-sonnet
115
+ reasoning_effort: low # Only for thinking models
111
116
  max_tokens_policy: adaptive
112
117
  retry_max_tokens: 32768
118
+
119
+ # Configuration for Google AI (Gemini)
120
+ google:
121
+ default_model: "gemini-3-pro-preview"
122
+
123
+ anthropic:
124
+ default_model: "claude-sonnet-4.5"
125
+
113
126
  planning_mode: traditional
@@ -0,0 +1,7 @@
1
+ openai:
2
+ api_key: ""
3
+ base_url: ""
4
+ anthropic:
5
+ api_key: ""
6
+ google:
7
+ api_key: ""
@@ -3,6 +3,7 @@ aiohttp>=3.8.0
3
3
  anthropic
4
4
  asyncio-mqtt
5
5
  docling
6
+ google-genai
6
7
  mcp-agent
7
8
  mcp-server-git
8
9
  nest_asyncio
@@ -12,40 +12,77 @@ from typing import Any, Type, Dict, Tuple
12
12
  # Import LLM classes
13
13
  from mcp_agent.workflows.llm.augmented_llm_anthropic import AnthropicAugmentedLLM
14
14
  from mcp_agent.workflows.llm.augmented_llm_openai import OpenAIAugmentedLLM
15
+ from mcp_agent.workflows.llm.augmented_llm_google import GoogleAugmentedLLM
15
16
 
16
17
 
17
18
  def get_preferred_llm_class(config_path: str = "mcp_agent.secrets.yaml") -> Type[Any]:
18
19
  """
19
- Automatically select the LLM class based on API key availability in configuration.
20
+ Select the LLM class based on user preference and API key availability.
20
21
 
21
- Reads from YAML config file and returns AnthropicAugmentedLLM if anthropic.api_key
22
- is available, otherwise returns OpenAIAugmentedLLM.
22
+ Priority:
23
+ 1. Check mcp_agent.config.yaml for llm_provider preference
24
+ 2. Verify the preferred provider has API key
25
+ 3. Fallback to first available provider
23
26
 
24
27
  Args:
25
- config_path: Path to the YAML configuration file
28
+ config_path: Path to the secrets YAML configuration file
26
29
 
27
30
  Returns:
28
31
  class: The preferred LLM class
29
32
  """
30
33
  try:
31
- # Try to read the configuration file
32
- if os.path.exists(config_path):
33
- with open(config_path, "r", encoding="utf-8") as f:
34
- config = yaml.safe_load(f)
34
+ # Read API keys from secrets file
35
+ if not os.path.exists(config_path):
36
+ print(f"🤖 Config file {config_path} not found, using OpenAIAugmentedLLM")
37
+ return OpenAIAugmentedLLM
35
38
 
36
- # Check for anthropic API key in config
37
- anthropic_config = config.get("anthropic", {})
38
- anthropic_key = anthropic_config.get("api_key", "")
39
+ with open(config_path, "r", encoding="utf-8") as f:
40
+ secrets = yaml.safe_load(f)
41
+
42
+ # Get API keys
43
+ anthropic_key = secrets.get("anthropic", {}).get("api_key", "").strip()
44
+ google_key = secrets.get("google", {}).get("api_key", "").strip()
45
+ openai_key = secrets.get("openai", {}).get("api_key", "").strip()
46
+
47
+ # Read user preference from main config
48
+ main_config_path = "mcp_agent.config.yaml"
49
+ preferred_provider = None
50
+ if os.path.exists(main_config_path):
51
+ with open(main_config_path, "r", encoding="utf-8") as f:
52
+ main_config = yaml.safe_load(f)
53
+ preferred_provider = main_config.get("llm_provider", "").strip().lower()
54
+
55
+ # Map of providers to their classes and keys
56
+ provider_map = {
57
+ "anthropic": (
58
+ AnthropicAugmentedLLM,
59
+ anthropic_key,
60
+ "AnthropicAugmentedLLM",
61
+ ),
62
+ "google": (GoogleAugmentedLLM, google_key, "GoogleAugmentedLLM"),
63
+ "openai": (OpenAIAugmentedLLM, openai_key, "OpenAIAugmentedLLM"),
64
+ }
39
65
 
40
- if anthropic_key and anthropic_key.strip() and not anthropic_key == "":
41
- # print("🤖 Using AnthropicAugmentedLLM (Anthropic API key found in config)")
42
- return AnthropicAugmentedLLM
66
+ # Try user's preferred provider first
67
+ if preferred_provider and preferred_provider in provider_map:
68
+ llm_class, api_key, class_name = provider_map[preferred_provider]
69
+ if api_key:
70
+ print(f"🤖 Using {class_name} (user preference: {preferred_provider})")
71
+ return llm_class
43
72
  else:
44
- # print("🤖 Using OpenAIAugmentedLLM (Anthropic API key not configured)")
45
- return OpenAIAugmentedLLM
46
- else:
47
- print(f"🤖 Config file {config_path} not found, using OpenAIAugmentedLLM")
48
- return OpenAIAugmentedLLM
73
+ print(
74
+ f"⚠️ Preferred provider '{preferred_provider}' has no API key, checking alternatives..."
75
+ )
76
+
77
+ # Fallback: try providers in order of availability
78
+ for provider, (llm_class, api_key, class_name) in provider_map.items():
79
+ if api_key:
80
+ print(f"🤖 Using {class_name} ({provider} API key found)")
81
+ return llm_class
82
+
83
+ # No API keys found
84
+ print("⚠️ No API keys configured, falling back to OpenAIAugmentedLLM")
85
+ return OpenAIAugmentedLLM
49
86
 
50
87
  except Exception as e:
51
88
  print(f"🤖 Error reading config file {config_path}: {e}")
@@ -101,7 +138,7 @@ def get_default_models(config_path: str = "mcp_agent.config.yaml"):
101
138
  config_path: Path to the configuration file
102
139
 
103
140
  Returns:
104
- dict: Dictionary with 'anthropic' and 'openai' default models
141
+ dict: Dictionary with 'anthropic', 'openai', and 'google' default models
105
142
  """
106
143
  try:
107
144
  if os.path.exists(config_path):
@@ -111,20 +148,34 @@ def get_default_models(config_path: str = "mcp_agent.config.yaml"):
111
148
  # Handle null values in config sections
112
149
  anthropic_config = config.get("anthropic") or {}
113
150
  openai_config = config.get("openai") or {}
151
+ google_config = config.get("google") or {}
114
152
 
115
153
  anthropic_model = anthropic_config.get(
116
154
  "default_model", "claude-sonnet-4-20250514"
117
155
  )
118
156
  openai_model = openai_config.get("default_model", "o3-mini")
157
+ google_model = google_config.get("default_model", "gemini-2.0-flash")
119
158
 
120
- return {"anthropic": anthropic_model, "openai": openai_model}
159
+ return {
160
+ "anthropic": anthropic_model,
161
+ "openai": openai_model,
162
+ "google": google_model,
163
+ }
121
164
  else:
122
165
  print(f"Config file {config_path} not found, using default models")
123
- return {"anthropic": "claude-sonnet-4-20250514", "openai": "o3-mini"}
166
+ return {
167
+ "anthropic": "claude-sonnet-4-20250514",
168
+ "openai": "o3-mini",
169
+ "google": "gemini-2.0-flash",
170
+ }
124
171
 
125
172
  except Exception as e:
126
173
  print(f"❌Error reading config file {config_path}: {e}")
127
- return {"anthropic": "claude-sonnet-4-20250514", "openai": "o3-mini"}
174
+ return {
175
+ "anthropic": "claude-sonnet-4-20250514",
176
+ "openai": "o3-mini",
177
+ "google": "gemini-2.0-flash",
178
+ }
128
179
 
129
180
 
130
181
  def get_document_segmentation_config(
@@ -63,8 +63,9 @@ class ConciseMemoryAgent:
63
63
 
64
64
  # Store default models configuration
65
65
  self.default_models = default_models or {
66
- "anthropic": "anthropic/claude-sonnet-4.5",
67
- "openai": "openai/gpt-4o",
66
+ "anthropic": "claude-sonnet-4-20250514",
67
+ "openai": "o3-mini",
68
+ "google": "gemini-2.0-flash",
68
69
  }
69
70
 
70
71
  # Memory state tracking - new logic: trigger after each write_file
@@ -1422,6 +1423,54 @@ class ConciseMemoryAgent:
1422
1423
  self.logger.warning("OpenAI response is empty or malformed")
1423
1424
  return {"content": ""}
1424
1425
 
1426
+ elif client_type == "google":
1427
+ from google.genai import types
1428
+
1429
+ # Convert messages to Gemini format
1430
+ system_instruction = "You are an expert code implementation summarizer. Create structured summaries of implemented code files that preserve essential information about functions, dependencies, and implementation approaches."
1431
+
1432
+ gemini_messages = []
1433
+ for msg in summary_messages:
1434
+ role = msg.get("role", "user")
1435
+ content = msg.get("content", "")
1436
+
1437
+ # Convert role names: "assistant" -> "model"
1438
+ if role == "assistant":
1439
+ role = "model"
1440
+ elif role not in ["user", "model"]:
1441
+ role = "user"
1442
+
1443
+ gemini_messages.append(
1444
+ types.Content(role=role, parts=[types.Part.from_text(text=content)])
1445
+ )
1446
+
1447
+ config = types.GenerateContentConfig(
1448
+ max_output_tokens=5000,
1449
+ temperature=0.2,
1450
+ system_instruction=system_instruction,
1451
+ )
1452
+
1453
+ response = await client.aio.models.generate_content(
1454
+ model=self.default_models.get("google", "gemini-2.0-flash"),
1455
+ contents=gemini_messages,
1456
+ config=config,
1457
+ )
1458
+
1459
+ # Extract content from Gemini response
1460
+ content = ""
1461
+ if response and hasattr(response, "candidates") and response.candidates:
1462
+ candidate = response.candidates[0]
1463
+ if hasattr(candidate, "content") and candidate.content:
1464
+ if hasattr(candidate.content, "parts") and candidate.content.parts:
1465
+ for part in candidate.content.parts:
1466
+ if hasattr(part, "text") and part.text:
1467
+ content += part.text
1468
+
1469
+ if not content:
1470
+ self.logger.warning("Google response is empty or malformed")
1471
+
1472
+ return {"content": content}
1473
+
1425
1474
  else:
1426
1475
  raise ValueError(f"Unsupported client type: {client_type}")
1427
1476
 
@@ -63,8 +63,9 @@ class ConciseMemoryAgent:
63
63
 
64
64
  # Store default models configuration
65
65
  self.default_models = default_models or {
66
- "anthropic": "anthropic/claude-sonnet-4.5",
67
- "openai": "openai/gpt-4o",
66
+ "anthropic": "claude-sonnet-4-20250514",
67
+ "openai": "o3-mini",
68
+ "google": "gemini-2.0-flash",
68
69
  }
69
70
 
70
71
  # Memory state tracking - new logic: trigger after each write_file
@@ -1422,6 +1423,54 @@ class ConciseMemoryAgent:
1422
1423
  self.logger.warning("OpenAI response is empty or malformed")
1423
1424
  return {"content": ""}
1424
1425
 
1426
+ elif client_type == "google":
1427
+ from google.genai import types
1428
+
1429
+ # Convert messages to Gemini format
1430
+ system_instruction = "You are an expert code implementation summarizer. Create structured summaries of implemented code files that preserve essential information about functions, dependencies, and implementation approaches."
1431
+
1432
+ gemini_messages = []
1433
+ for msg in summary_messages:
1434
+ role = msg.get("role", "user")
1435
+ content = msg.get("content", "")
1436
+
1437
+ # Convert role names: "assistant" -> "model"
1438
+ if role == "assistant":
1439
+ role = "model"
1440
+ elif role not in ["user", "model"]:
1441
+ role = "user"
1442
+
1443
+ gemini_messages.append(
1444
+ types.Content(role=role, parts=[types.Part.from_text(text=content)])
1445
+ )
1446
+
1447
+ config = types.GenerateContentConfig(
1448
+ max_output_tokens=5000,
1449
+ temperature=0.2,
1450
+ system_instruction=system_instruction,
1451
+ )
1452
+
1453
+ response = await client.aio.models.generate_content(
1454
+ model=self.default_models.get("google", "gemini-2.0-flash"),
1455
+ contents=gemini_messages,
1456
+ config=config,
1457
+ )
1458
+
1459
+ # Extract content from Gemini response
1460
+ content = ""
1461
+ if response and hasattr(response, "candidates") and response.candidates:
1462
+ candidate = response.candidates[0]
1463
+ if hasattr(candidate, "content") and candidate.content:
1464
+ if hasattr(candidate.content, "parts") and candidate.content.parts:
1465
+ for part in candidate.content.parts:
1466
+ if hasattr(part, "text") and part.text:
1467
+ content += part.text
1468
+
1469
+ if not content:
1470
+ self.logger.warning("Google response is empty or malformed")
1471
+
1472
+ return {"content": content}
1473
+
1425
1474
  else:
1426
1475
  raise ValueError(f"Unsupported client type: {client_type}")
1427
1476
 
@@ -70,7 +70,8 @@ class ConciseMemoryAgent:
70
70
  # Store default models configuration
71
71
  self.default_models = default_models or {
72
72
  "anthropic": "claude-sonnet-4-20250514",
73
- "openai": "gpt-4o",
73
+ "openai": "o3-mini",
74
+ "google": "gemini-2.0-flash",
74
75
  }
75
76
 
76
77
  # Memory state tracking - new logic: trigger after each write_multiple_files
@@ -657,6 +658,54 @@ class ConciseMemoryAgent:
657
658
 
658
659
  return {"content": response.choices[0].message.content or ""}
659
660
 
661
+ elif client_type == "google":
662
+ from google.genai import types
663
+
664
+ # Convert messages to Gemini format
665
+ system_instruction = "You are an expert code implementation summarizer. Create structured summaries of implemented code files that preserve essential information about functions, dependencies, and implementation approaches."
666
+
667
+ gemini_messages = []
668
+ for msg in summary_messages:
669
+ role = msg.get("role", "user")
670
+ content = msg.get("content", "")
671
+
672
+ # Convert role names: "assistant" -> "model"
673
+ if role == "assistant":
674
+ role = "model"
675
+ elif role not in ["user", "model"]:
676
+ role = "user"
677
+
678
+ gemini_messages.append(
679
+ types.Content(role=role, parts=[types.Part.from_text(text=content)])
680
+ )
681
+
682
+ config = types.GenerateContentConfig(
683
+ max_output_tokens=8000, # Increased for multi-file support
684
+ temperature=0.2,
685
+ system_instruction=system_instruction,
686
+ )
687
+
688
+ response = await client.aio.models.generate_content(
689
+ model=self.default_models.get("google", "gemini-2.0-flash"),
690
+ contents=gemini_messages,
691
+ config=config,
692
+ )
693
+
694
+ # Extract content from Gemini response
695
+ content = ""
696
+ if response and hasattr(response, "candidates") and response.candidates:
697
+ candidate = response.candidates[0]
698
+ if hasattr(candidate, "content") and candidate.content:
699
+ if hasattr(candidate.content, "parts") and candidate.content.parts:
700
+ for part in candidate.content.parts:
701
+ if hasattr(part, "text") and part.text:
702
+ content += part.text
703
+
704
+ if not content:
705
+ self.logger.warning("Google response is empty or malformed")
706
+
707
+ return {"content": content}
708
+
660
709
  else:
661
710
  raise ValueError(f"Unsupported client type: {client_type}")
662
711