Diomedes Git commited on
Commit
e4effb4
·
1 Parent(s): 8d614a3

some cleanup, tweakery

Browse files
pyproject.toml CHANGED
@@ -14,6 +14,7 @@ dependencies = [
14
  "groq>=0.36.0",
15
  "mcp>=1.20.0",
16
  "newsapi>=0.1.1",
 
17
  "openaq>=0.5.0",
18
  "python-dotenv>=1.2.1",
19
  "pytrends>=4.9.2",
 
14
  "groq>=0.36.0",
15
  "mcp>=1.20.0",
16
  "newsapi>=0.1.1",
17
+ "newsapi-python>=0.2.7",
18
  "openaq>=0.5.0",
19
  "python-dotenv>=1.2.1",
20
  "pytrends>=4.9.2",
src/characters/check_char_init.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import logging
4
+
5
+ # Add the parent directory of 'src' to sys.path to resolve imports
6
+ sys.path.append('/Users/gboa/cluas/')
7
+
8
+ # Disable logging for cleaner output
9
+ logging.getLogger().setLevel(logging.CRITICAL)
10
+
11
+ try:
12
+ from src.characters.corvus import Corvus
13
+ from src.characters.crow import Crow
14
+ from src.characters.magpie import Magpie
15
+ from src.characters.raven import Raven
16
+ except ImportError as e:
17
+ print(f"Error importing character classes: {e}")
18
+ sys.exit(1)
19
+
20
+ characters = {
21
+ "Corvus": Corvus,
22
+ "Crow": Crow,
23
+ "Magpie": Magpie,
24
+ "Raven": Raven,
25
+ }
26
+
27
+ print("--- Initializing Characters ---")
28
+
29
+ # Set a dummy GROQ_API_KEY for testing purposes if it's not already set
30
+ # This allows the use_groq=True path to be tested without an actual key,
31
+ # but it will still raise an error if the key is explicitly checked for existence
32
+ # in the character's __init__ method (which is good, as it tests that check).
33
+ if "GROQ_API_KEY" not in os.environ:
34
+ os.environ["GROQ_API_KEY"] = "dummy_key_for_testing"
35
+
36
+ for name, char_class in characters.items():
37
+ print(f"Testing {name}...")
38
+
39
+ # Test with use_groq=True
40
+ try:
41
+ instance = char_class(use_groq=True)
42
+ print(f" ✅ {name} (use_groq=True) initialized successfully.")
43
+ except ValueError as e:
44
+ print(f" ❌ {name} (use_groq=True) failed to initialize: {e} (Expected if GROQ_API_KEY is missing or invalid)")
45
+ except Exception as e:
46
+ print(f" ❌ {name} (use_groq=True) failed to initialize with unexpected error: {e}")
47
+
48
+ # Test with use_groq=False (Ollama path)
49
+ try:
50
+ instance = char_class(use_groq=False)
51
+ print(f" ✅ {name} (use_groq=False) initialized successfully.")
52
+ except Exception as e:
53
+ print(f" ❌ {name} (use_groq=False) failed to initialize: {e}")
54
+
55
+ print("--- Character Initialization Test Complete ---")
src/characters/magpie.py CHANGED
@@ -4,7 +4,8 @@ import asyncio
4
  from typing import Optional, List, Dict
5
  from dotenv import load_dotenv
6
  from groq import Groq
7
- from src.cluas_mcp.web.web_search import search_web, find_trending_topics, get_quick_facts
 
8
 
9
  from src.cluas_mcp.common.paper_memory import PaperMemory
10
  from src.cluas_mcp.common.observation_memory import ObservationMemory
@@ -17,7 +18,7 @@ class Magpie:
17
  def __init__(self, use_groq=True, location="Brooklyn, NY"):
18
  self.name = "Magpie"
19
  self.use_groq = use_groq
20
- self.tools = ["search_web", "find_trending_topics"]
21
  self.trend_memory = TrendMemory()
22
  self.paper_memory = PaperMemory()
23
  self.observation_memory = ObservationMemory(location=location)
@@ -51,7 +52,7 @@ You're in a group chat, so keep it fun and engaging!
51
 
52
  TOOLS AVAILABLE:
53
  - search_web: Search the web for current information
54
- - find_trending_topics: Find what's trending right now
55
  - get_quick_facts: Get quick facts about any topic
56
 
57
  When you need current information or want to share something interesting, use your tools!"""
@@ -135,7 +136,7 @@ When you need current information or want to share something interesting, use yo
135
  {
136
  "type": "function",
137
  "function": {
138
- "name": "find_trending_topics",
139
  "description": "Find trending topics in a given category",
140
  "parameters": {
141
  "type": "object",
@@ -197,9 +198,9 @@ When you need current information or want to share something interesting, use yo
197
  search_results = await loop.run_in_executor(None, search_web, query)
198
  tool_result = self._format_web_search_for_llm(search_results)
199
 
200
- elif tool_name == "find_trending_topics":
201
  category = args.get("category", "general")
202
- trending_results = await loop.run_in_executor(None, find_trending_topics, category)
203
  tool_result = self._format_trending_topics_for_llm(trending_results)
204
 
205
  elif tool_name == "get_quick_facts":
 
4
  from typing import Optional, List, Dict
5
  from dotenv import load_dotenv
6
  from groq import Groq
7
+ from src.cluas_mcp.web.web_search import search_web
8
+ from src.cluas_mcp.web.trending import fetch_trends
9
 
10
  from src.cluas_mcp.common.paper_memory import PaperMemory
11
  from src.cluas_mcp.common.observation_memory import ObservationMemory
 
18
  def __init__(self, use_groq=True, location="Brooklyn, NY"):
19
  self.name = "Magpie"
20
  self.use_groq = use_groq
21
+ self.tools = ["search_web", "fetch_trends"]
22
  self.trend_memory = TrendMemory()
23
  self.paper_memory = PaperMemory()
24
  self.observation_memory = ObservationMemory(location=location)
 
52
 
53
  TOOLS AVAILABLE:
54
  - search_web: Search the web for current information
55
+ - fetch_trend_topics: Find what's trending right now
56
  - get_quick_facts: Get quick facts about any topic
57
 
58
  When you need current information or want to share something interesting, use your tools!"""
 
136
  {
137
  "type": "function",
138
  "function": {
139
+ "name": "fetch_trends",
140
  "description": "Find trending topics in a given category",
141
  "parameters": {
142
  "type": "object",
 
198
  search_results = await loop.run_in_executor(None, search_web, query)
199
  tool_result = self._format_web_search_for_llm(search_results)
200
 
201
+ elif tool_name == "fetch_trends":
202
  category = args.get("category", "general")
203
+ trending_results = await loop.run_in_executor(None, fetch_trends, category)
204
  tool_result = self._format_trending_topics_for_llm(trending_results)
205
 
206
  elif tool_name == "get_quick_facts":
src/characters/src/data/memory.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {}
src/characters/src/data/observations.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {}
src/cluas_mcp/academic/thing.py DELETED
@@ -1,2 +0,0 @@
1
- from src.cluas_mcp.academic.pubmed import PubMedClient
2
- print(hasattr(PubMedClient, "fetch_articles"))
 
 
 
src/cluas_mcp/news/news_search_entrypoint.py CHANGED
@@ -9,3 +9,4 @@ def search_news_entrypoint(query: str, max_results: int = 5) -> dict:
9
  Uses cascading fallbacks: NewsAPI -> DuckDuckGo -> Google -> Bing -> Mock.
10
  """
11
  return search_news(query, max_results)
 
 
9
  Uses cascading fallbacks: NewsAPI -> DuckDuckGo -> Google -> Bing -> Mock.
10
  """
11
  return search_news(query, max_results)
12
+
src/cluas_mcp/observation/observation_entrypoint.py CHANGED
@@ -127,3 +127,4 @@ def analyze_temporal_patterns(obs_type: str, location: Optional[str] = None, day
127
  # }
128
 
129
 
 
 
127
  # }
128
 
129
 
130
+
src/cluas_mcp/observation/sunrise_sunset.py CHANGED
@@ -1,6 +1,7 @@
1
  from astral import LocationInfo
2
  from astral.sun import sun
3
  from datetime import datetime, date
 
4
 
5
  LOCATIONS = {
6
  "brooklyn": LocationInfo("Brooklyn", "USA", "America/New_York", 40.6782, -73.9442),
 
1
  from astral import LocationInfo
2
  from astral.sun import sun
3
  from datetime import datetime, date
4
+ from typing import Optional
5
 
6
  LOCATIONS = {
7
  "brooklyn": LocationInfo("Brooklyn", "USA", "America/New_York", 40.6782, -73.9442),
src/cluas_mcp/server.py CHANGED
@@ -6,8 +6,9 @@ from mcp.server.stdio import stdio_server
6
  from mcp.types import Tool, TextContent
7
 
8
  from src.cluas_mcp.academic.academic_search_entrypoint import academic_search
9
- from src.cluas_mcp.web.web_search import search_web, find_trending_topics, get_quick_facts
10
- from src.cluas_mcp.news.news_search_entrypoint import search_news, get_environmental_data, verify_claim
 
11
  from src.cluas_mcp.observation.observation_entrypoint import get_bird_sightings, get_weather_patterns, analyze_temporal_patterns
12
 
13
  logging.basicConfig(level=logging.INFO)
@@ -50,7 +51,7 @@ async def list_tools() -> list[Tool]:
50
  }
51
  ),
52
  Tool(
53
- name="find_trending_topics",
54
  description="Find trending topics in a given category",
55
  inputSchema={
56
  "type": "object",
@@ -216,9 +217,9 @@ async def call_tool(tool_name: str, arguments: dict) -> list[TextContent]:
216
  formatted = format_web_search_results(results)
217
  return [TextContent(type="text", text=formatted)]
218
 
219
- elif tool_name == "find_trending_topics":
220
  category = arguments.get("category", "general")
221
- results = await loop.run_in_executor(None, find_trending_topics, category)
222
  formatted = format_trending_topics(results)
223
  return [TextContent(type="text", text=formatted)]
224
 
 
6
  from mcp.types import Tool, TextContent
7
 
8
  from src.cluas_mcp.academic.academic_search_entrypoint import academic_search
9
+ from src.cluas_mcp.web.web_search import search_web
10
+ from src.cluas_mcp.web.trending import fetch_trends
11
+ from src.cluas_mcp.news.news_search_entrypoint import search_news
12
  from src.cluas_mcp.observation.observation_entrypoint import get_bird_sightings, get_weather_patterns, analyze_temporal_patterns
13
 
14
  logging.basicConfig(level=logging.INFO)
 
51
  }
52
  ),
53
  Tool(
54
+ name="fetch_trends",
55
  description="Find trending topics in a given category",
56
  inputSchema={
57
  "type": "object",
 
217
  formatted = format_web_search_results(results)
218
  return [TextContent(type="text", text=formatted)]
219
 
220
+ elif tool_name == "fetch_trends":
221
  category = arguments.get("category", "general")
222
+ results = await loop.run_in_executor(None, fetch_trends, category)
223
  formatted = format_trending_topics(results)
224
  return [TextContent(type="text", text=formatted)]
225
 
src/cluas_mcp/tool_router.py DELETED
File without changes
src/cluas_mcp/tools.py DELETED
@@ -1,20 +0,0 @@
1
- def search_academic_papers(
2
- query: str,
3
- topic: str = "corvid",
4
- year_range: tuple[int, int] | None = None,
5
- sort_by: str = "relevance",
6
- max_results: int = 5
7
- ) -> list[dict] | None:
8
- """
9
- Search academic papers on a given topic using arXiv and fallback APIs.
10
-
11
- Args:
12
- query: Search terms (e.g., "tool use in crows").
13
- topic: Domain of interest (e.g., "corvid", "conservation").
14
- year_range: Optional (start_year, end_year) filter.
15
- sort_by: Sort results by "relevance" or "date".
16
- max_results: Maximum number of results to return.
17
-
18
- Returns:
19
- List of paper metadata (dicts) or None if no results.
20
- """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/cluas_mcp/web/web_search.py CHANGED
@@ -74,72 +74,4 @@ def _mock_search_web(query: str) -> dict:
74
  "total_results": 2
75
  }
76
 
77
- def fetch_trending(category: str = "general") -> dict:
78
- """
79
- Find trending topics in a given category.
80
-
81
- TODO: Implement full trending topics functionality using a trends API.
82
-
83
- Args:
84
- category: Category to search for trends (e.g., "general", "technology", "science")
85
-
86
- Returns:
87
- Dictionary with trending topics
88
- """
89
- logger.info("Finding trending topics for category: %s", category)
90
-
91
- # Mock structured data
92
- return {
93
- "trending_topics": [
94
- {
95
- "topic": "Mock Trending Topic 1",
96
- "category": category,
97
- "trend_score": 95,
98
- "description": "This is a mock trending topic. Real implementation would fetch actual trending data."
99
- },
100
- {
101
- "topic": "Mock Trending Topic 2",
102
- "category": category,
103
- "trend_score": 87,
104
- "description": "Another mock trending topic for demonstration purposes."
105
- },
106
- {
107
- "topic": "Mock Trending Topic 3",
108
- "category": category,
109
- "trend_score": 82,
110
- "description": "Third mock trending topic to show structure."
111
- }
112
- ],
113
- "category": category
114
- }
115
-
116
- def get_quick_facts(topic: str) -> dict:
117
- """
118
- Get quick facts about a topic.
119
-
120
- TODO: Implement full quick facts functionality using a knowledge API.
121
-
122
- Args:
123
- topic: Topic to get facts about
124
-
125
- Returns:
126
- Dictionary with quick facts
127
- """
128
- logger.info("Getting quick facts for topic: %s", topic)
129
-
130
- # Mock structured data
131
- return {
132
- "topic": topic,
133
- "facts": [
134
- f"Mock fact 1 about {topic}: This is a placeholder fact that would be replaced with real data in a full implementation.",
135
- f"Mock fact 2 about {topic}: Another placeholder fact demonstrating the expected structure.",
136
- f"Mock fact 3 about {topic}: A third placeholder fact to show the format."
137
- ],
138
- "source": "mock_data"
139
- }
140
-
141
-
142
-
143
-
144
-
145
 
 
74
  "total_results": 2
75
  }
76
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
 
uv.lock CHANGED
@@ -341,6 +341,7 @@ dependencies = [
341
  { name = "groq" },
342
  { name = "mcp" },
343
  { name = "newsapi" },
 
344
  { name = "openaq" },
345
  { name = "python-dotenv" },
346
  { name = "pytrends" },
@@ -365,6 +366,7 @@ requires-dist = [
365
  { name = "groq", specifier = ">=0.36.0" },
366
  { name = "mcp", specifier = ">=1.20.0" },
367
  { name = "newsapi", specifier = ">=0.1.1" },
 
368
  { name = "openaq", specifier = ">=0.5.0" },
369
  { name = "python-dotenv", specifier = ">=1.2.1" },
370
  { name = "pytrends", specifier = ">=4.9.2" },
@@ -1156,6 +1158,18 @@ wheels = [
1156
  { url = "https://files.pythonhosted.org/packages/56/70/df0dd31067f03703d06f66b6c3f324915bd43bc8a597ee1a7eef27c9e622/newsapi-0.1.1-py2.py3-none-any.whl", hash = "sha256:baef702f6e29fc2736932858528d94f18b2baaef9d330018ba78369e005e1df4", size = 4127, upload-time = "2017-03-28T22:10:12.306Z" },
1157
  ]
1158
 
 
 
 
 
 
 
 
 
 
 
 
 
1159
  [[package]]
1160
  name = "numpy"
1161
  version = "2.3.5"
 
341
  { name = "groq" },
342
  { name = "mcp" },
343
  { name = "newsapi" },
344
+ { name = "newsapi-python" },
345
  { name = "openaq" },
346
  { name = "python-dotenv" },
347
  { name = "pytrends" },
 
366
  { name = "groq", specifier = ">=0.36.0" },
367
  { name = "mcp", specifier = ">=1.20.0" },
368
  { name = "newsapi", specifier = ">=0.1.1" },
369
+ { name = "newsapi-python", specifier = ">=0.2.7" },
370
  { name = "openaq", specifier = ">=0.5.0" },
371
  { name = "python-dotenv", specifier = ">=1.2.1" },
372
  { name = "pytrends", specifier = ">=4.9.2" },
 
1158
  { url = "https://files.pythonhosted.org/packages/56/70/df0dd31067f03703d06f66b6c3f324915bd43bc8a597ee1a7eef27c9e622/newsapi-0.1.1-py2.py3-none-any.whl", hash = "sha256:baef702f6e29fc2736932858528d94f18b2baaef9d330018ba78369e005e1df4", size = 4127, upload-time = "2017-03-28T22:10:12.306Z" },
1159
  ]
1160
 
1161
+ [[package]]
1162
+ name = "newsapi-python"
1163
+ version = "0.2.7"
1164
+ source = { registry = "https://pypi.org/simple" }
1165
+ dependencies = [
1166
+ { name = "requests" },
1167
+ ]
1168
+ sdist = { url = "https://files.pythonhosted.org/packages/f8/4b/12fb9495211fc5a6d3a96968759c1a48444124a1654aaf65d0de80b46794/newsapi-python-0.2.7.tar.gz", hash = "sha256:a4b66d5dd9892198cdaa476f7542f2625cdd218e5e3121c8f880b2ace717a3c2", size = 7485, upload-time = "2023-03-02T13:15:35.89Z" }
1169
+ wheels = [
1170
+ { url = "https://files.pythonhosted.org/packages/74/47/e3b099102f0c826d37841d2266e19f1568dcf58ba86e4c6948e2a124f91d/newsapi_python-0.2.7-py2.py3-none-any.whl", hash = "sha256:11d34013a24d92ca7b7cbdac84ed2d504862b1e22467bc2a9a6913a70962318e", size = 7942, upload-time = "2023-03-02T13:15:34.475Z" },
1171
+ ]
1172
+
1173
  [[package]]
1174
  name = "numpy"
1175
  version = "2.3.5"