gofannon 0.25.14__py3-none-any.whl → 0.25.15__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.
gofannon/base/__init__.py CHANGED
@@ -5,11 +5,16 @@ from typing import Any, Callable
5
5
  import json
6
6
  import logging
7
7
  from pathlib import Path
8
+
9
+ import anyio
10
+
8
11
  from ..config import ToolConfig
9
12
 
10
13
  from .smol_agents import SmolAgentsMixin
11
14
  from .langchain import LangchainMixin
12
15
  from .bedrock import BedrockMixin
16
+ from .langflow import LangflowMixin
17
+ from .mcp import MCPMixin
13
18
 
14
19
 
15
20
  @dataclass
@@ -62,7 +67,12 @@ class WorkflowContext:
62
67
  self.execution_log.append(entry)
63
68
 
64
69
 
65
- class BaseTool(SmolAgentsMixin, LangchainMixin, BedrockMixin, ABC):
70
+ class BaseTool(SmolAgentsMixin,
71
+ LangchainMixin,
72
+ BedrockMixin,
73
+ LangflowMixin,
74
+ MCPMixin,
75
+ ABC):
66
76
  def __init__(self, **kwargs):
67
77
  self.logger = logging.getLogger(
68
78
  f"{self.__class__.__module__}.{self.__class__.__name__}"
@@ -111,3 +121,6 @@ class BaseTool(SmolAgentsMixin, LangchainMixin, BedrockMixin, ABC):
111
121
  return ToolResult(success=True, output=result)
112
122
  except Exception as e:
113
123
  return ToolResult(success=False, output=None, error=str(e), retryable=True)
124
+
125
+ async def execute_async(self, arguments: dict):
126
+ return await anyio.to_thread.run_sync(self.fn, **arguments)
@@ -0,0 +1,111 @@
1
+ try:
2
+ from langflow.custom import Component
3
+ from langflow.io import MessageTextInput, IntInput, BoolInput, FloatInput, Output
4
+ from langflow.schema import Data
5
+
6
+ _HAS_LANGFLOW = True
7
+ except ImportError:
8
+ _HAS_LANGFLOW = False
9
+
10
+
11
+ class LangflowMixin:
12
+ def import_from_langflow(self, langflow_component):
13
+ """Adapt a Langflow component to a Gofannon tool"""
14
+ if not _HAS_LANGFLOW:
15
+ raise RuntimeError(
16
+ "langflow is not installed. Install with `pip install langflow`"
17
+ )
18
+
19
+ self.name = langflow_component.display_name.replace(" ", "_").lower()
20
+ self.description = langflow_component.description
21
+
22
+ # Extract parameters from component inputs
23
+ parameters = {
24
+ "type": "object",
25
+ "properties": {},
26
+ "required": []
27
+ }
28
+
29
+ for component_input in langflow_component.inputs:
30
+ if component_input.name in ["self", "context"]:
31
+ continue
32
+
33
+ param_type = "string"
34
+ if isinstance(component_input, (IntInput, FloatInput)):
35
+ param_type = "number"
36
+ elif isinstance(component_input, BoolInput):
37
+ param_type = "boolean"
38
+
39
+ parameters["properties"][component_input.name] = {
40
+ "type": param_type,
41
+ "description": component_input.info or ""
42
+ }
43
+
44
+ if component_input.required:
45
+ parameters["required"].append(component_input.name)
46
+
47
+ self.definition = {
48
+ "function": {
49
+ "name": self.name,
50
+ "description": self.description,
51
+ "parameters": parameters
52
+ }
53
+ }
54
+
55
+ # Create execution wrapper
56
+ def adapted_fn(**kwargs):
57
+ result = langflow_component.build()(**kwargs)
58
+ return result.data if isinstance(result, Data) else result
59
+
60
+ self.fn = adapted_fn
61
+
62
+ def export_to_langflow(self):
63
+ """Convert Gofannon tool to Langflow component"""
64
+ if not _HAS_LANGFLOW:
65
+ raise RuntimeError(
66
+ "langflow is not installed. Install with `pip install langflow`"
67
+ )
68
+
69
+ parameters = self.definition.get("function", {}).get("parameters", {})
70
+ param_properties = parameters.get("properties", {})
71
+ required_params = parameters.get("required", [])
72
+
73
+ # Create input fields
74
+ component_inputs = []
75
+ type_map = {
76
+ "string": MessageTextInput,
77
+ "number": FloatInput,
78
+ "integer": IntInput,
79
+ "boolean": BoolInput
80
+ }
81
+
82
+ for param_name, param_def in param_properties.items():
83
+ input_type = param_def.get("type", "string")
84
+ InputClass = type_map.get(input_type, MessageTextInput)
85
+
86
+ component_inputs.append(
87
+ InputClass(
88
+ name=param_name,
89
+ display_name=param_name.replace("_", " ").title(),
90
+ info=param_def.get("description", ""),
91
+ required=param_name in required_params,
92
+ tool_mode=True
93
+ )
94
+ )
95
+
96
+ # Define component class
97
+ class ExportedComponent(Component):
98
+ display_name = self.definition["function"]["name"].title()
99
+ description = self.definition["function"]["description"]
100
+ icon = "tool"
101
+
102
+ inputs = component_inputs
103
+ outputs = [Output(display_name="Result", name="result", method="run_tool")]
104
+
105
+ def run_tool(self, **kwargs):
106
+ result = self.tool.execute(context=None, **kwargs)
107
+ return Data(data=result.output)
108
+
109
+ # Attach tool instance to component class
110
+ ExportedComponent.tool = self
111
+ return ExportedComponent
gofannon/base/mcp.py ADDED
@@ -0,0 +1,6 @@
1
+ from json import dumps
2
+
3
+ class MCPMixin:
4
+ def export_to_mcp(self, fast_mcp_server=None):
5
+ """Convert Gofannon tool definition to MCP Tool schema"""
6
+ fast_mcp_server.add_tool(fn=self.fn, name=self.name, description=dumps(self.definition))
gofannon/config.py CHANGED
@@ -13,7 +13,8 @@ class ToolConfig:
13
13
  'deepinfra_api_key': os.getenv('DEEPINFRA_API_KEY'),
14
14
  'arxiv_api_key': os.getenv('ARXIV_API_KEY'),
15
15
  'google_search_api_key': os.getenv('GOOGLE_SEARCH_API_KEY'),
16
- 'google_search_engine_id': os.getenv('GOOGLE_SEARCH_ENGINE_ID')
16
+ 'google_search_engine_id': os.getenv('GOOGLE_SEARCH_ENGINE_ID'),
17
+ 'nasa_apod_api_key': os.getenv('NASA_APOD_API_KEY'),
17
18
  }
18
19
 
19
20
  @classmethod
File without changes
gofannon/nasa/apod.py ADDED
@@ -0,0 +1,68 @@
1
+ from ..base import BaseTool
2
+ from ..config import FunctionRegistry, ToolConfig
3
+ import logging
4
+ import requests
5
+
6
+ logger = logging.getLogger(__name__)
7
+
8
+ """Fetch the Astronomy Picture of the Day (APOD) from NASA's API.
9
+
10
+ This tool retrieves the daily astronomy image, including metadata such as the
11
+ title, explanation, date, and media type. It interacts with NASA's APOD API
12
+ and returns the data as a structured dictionary.
13
+
14
+ Authentication:
15
+ Requires an API key from NASA, available at https://api.nasa.gov/
16
+ The API key should be set in the environment as NASA_APOD_API_KEY
17
+ or passed as an argument during initialization.
18
+ """
19
+
20
+ @FunctionRegistry.register
21
+ class AstronomyPhotoOfTheDayTool(BaseTool):
22
+ def __init__(self, api_key=None ,name='apod'):
23
+ super().__init__()
24
+ self.name = name
25
+ self.api_key = api_key or ToolConfig.get("nasa_apod_api_key")
26
+
27
+ @property
28
+ def definition(self):
29
+ return {
30
+ "type": "function",
31
+ "function": {
32
+ "name": self.name,
33
+ "description": "Get the Astronomy Picture of the Day from NASA",
34
+ "parameters":{
35
+ "type": "object",
36
+ "properties": {},
37
+ "required": []
38
+ }
39
+ }
40
+ }
41
+
42
+ def fn(self):
43
+ logger.debug("Fetching NASA APOD data")
44
+ if not self.api_key:
45
+ logger.error("API key is missing. Cannot fetch APOD data.")
46
+ return {"error": "API key is missing. Please set it in the environment or pass it as an argument."}
47
+ url = "https://api.nasa.gov/planetary/apod"
48
+ params = {
49
+ "api_key": self.api_key
50
+ }
51
+
52
+ try:
53
+ response = requests.get(url, params=params)
54
+ response.raise_for_status()
55
+ data = response.json()
56
+
57
+ return{
58
+ "title": data.get("title", "No title available"),
59
+ "date": data.get("date", "No date available"),
60
+ "explanation": data.get("explanation", "No explanation available"),
61
+ "url": data.get("url", None),
62
+ "media_type": data.get("media_type", "unknown"),
63
+ }
64
+ except requests.exceptions.RequestException as e:
65
+ logger.error(f"Error fetching data from NASA APOD: {e}")
66
+ return {
67
+ "error": str(e)
68
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: gofannon
3
- Version: 0.25.14
3
+ Version: 0.25.15
4
4
  Summary: A collection of tools for LLMs
5
5
  License: ASFv2
6
6
  Author: Trevor Grant
@@ -16,17 +16,18 @@ Provides-Extra: aws
16
16
  Provides-Extra: google
17
17
  Provides-Extra: headless-browser
18
18
  Provides-Extra: langchain
19
+ Provides-Extra: langflow
19
20
  Provides-Extra: smolagents
20
21
  Provides-Extra: testing
21
22
  Requires-Dist: GitPython (>=3.1.43,<4.0.0)
22
23
  Requires-Dist: boto3 (>=1.34.97,<2.0.0) ; extra == "aws"
23
- Requires-Dist: google-api-python-client (>=2.161.0,<3.0.0) ; extra == "google"
24
+ Requires-Dist: google-api-python-client (>=2.154.0,<3.0.0) ; extra == "google"
24
25
  Requires-Dist: jsonschema (>=4.23.0,<5.0.0)
25
- Requires-Dist: langchain (>=0.3.16,<0.4.0) ; extra == "langchain"
26
+ Requires-Dist: langchain-core (>=0.3.16,<0.4.0) ; (python_version < "3.13") and (extra == "langchain")
26
27
  Requires-Dist: openai (>=1.60.2,<2.0.0)
27
28
  Requires-Dist: pydantic (>=2.10.6,<3.0.0) ; extra == "langchain"
28
29
  Requires-Dist: pygithub (>=2.6.1,<3.0.0)
29
- Requires-Dist: pytest (>=8.3.4,<9.0.0) ; extra == "testing"
30
+ Requires-Dist: pytest (>=8.3.5,<9.0.0) ; extra == "testing"
30
31
  Requires-Dist: python-dotenv (>=1.0.1,<2.0.0)
31
32
  Requires-Dist: requests (>=2.32.3,<3.0.0)
32
33
  Requires-Dist: requests-mock (>=1.12.1,<2.0.0) ; extra == "testing"
@@ -60,7 +61,7 @@ functionality for various tasks.
60
61
  3. New Contributor Friendly
61
62
  - [Curated contribution pathways](https://the-ai-alliance.github.io/gofannon/developers/)
62
63
  - [Gamified Contributor Process](https://the-ai-alliance.github.io/gofannon/leaderboard.html)
63
- ## 🎓🎓 Why the name `gofanon`? 🎓🎓
64
+ ## 🎓🎓 Why the name `gofannon`? 🎓🎓
64
65
 
65
66
  See [`why_the_name_gofannon`](https://the-ai-alliance.github.io/gofannon/about/the_name_gofannon/) for the rich story on why we chose to honor this Celtic Diety
66
67
 
@@ -2,9 +2,11 @@ gofannon/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  gofannon/arxiv/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  gofannon/arxiv/get_article.py,sha256=SRGTXFXdXdXTIOLZKWUTXxZEYEqZFWFJEV2nTsU5qqU,1167
4
4
  gofannon/arxiv/search.py,sha256=37Zx1y2vAX1xYIKaAxzBGXE3qPHUZdAD2XR0H1Acs-4,4225
5
- gofannon/base/__init__.py,sha256=8-uJsYAbLD-2e4clX73QZ8eip9S2PJlQ9JMRNWFHxSI,3387
5
+ gofannon/base/__init__.py,sha256=gFBxYPxhyy1yLyXIEgbVPqQSgnr6PzXnEb1S054IYQM,3685
6
6
  gofannon/base/bedrock.py,sha256=Z2c36R8jaIusgpmegbYVz2eR7lDBc0IhTtwiqUGOcT4,25646
7
7
  gofannon/base/langchain.py,sha256=25z9opy7E7qWP-DSn6oYAqKDg8i21az-kAKrsYLfyiQ,2704
8
+ gofannon/base/langflow.py,sha256=0WfNJ9MnndyLJ-yUAStIuXZpCzOPItsGKgtxdNifmLM,3833
9
+ gofannon/base/mcp.py,sha256=2e7f1FiD_M7wk4gOd7YNt4zLBgdLQTnWWYL0Kf5CzTY,253
8
10
  gofannon/base/smol_agents.py,sha256=p2YU5BrscavGk5X9R7HSJmtVR5OpOsQwCd9hwC9eBMk,2229
9
11
  gofannon/basic_math/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
10
12
  gofannon/basic_math/addition.py,sha256=zA-xtUBNnGnQVqTJkBvjZwX0gnGZ6mrUGhrlTbsH1ts,1148
@@ -13,7 +15,7 @@ gofannon/basic_math/exponents.py,sha256=w4qDlFZ9M1lf6X-tjG-ndpECfCOS7Qtc_VLICw0o
13
15
  gofannon/basic_math/multiplication.py,sha256=PJ5sKWMCVlBaTeZ_j3gwYOEQXAhN-qIXhnrNcyhWGKM,1168
14
16
  gofannon/basic_math/subtraction.py,sha256=gM1_N1mZ3qAXC6qnkzfijKXiOx27Gg93-CaB_ifMbOQ,1164
15
17
  gofannon/cli.py,sha256=-T-jjBNl_74TsGRcrjxsQnG0-wA2neYhncnaqCiEzPo,1733
16
- gofannon/config.py,sha256=N1xmWTbcyDPZT3r_ZuwW1RI0VRhDcbf3qIasEZZNwyc,1718
18
+ gofannon/config.py,sha256=KPVtjBnpwfM39EQg-_xiqL1UFxcuQehrQIUS6HHBP6k,1784
17
19
  gofannon/github/__init__.py,sha256=VFw4sJIt4Zc0-__eYnksN8Ku9qMhbPpHJEkXMWUiD30,4
18
20
  gofannon/github/commit_file.py,sha256=jdQGQHbrZx4521XgTbx5N0Ss8fDyl7hvp9sjDW15v9U,2573
19
21
  gofannon/github/commit_files.py,sha256=OZclhhSejRB1CYmd7IGYvdJZEWBzpaRRKK5S8NQxALU,4554
@@ -27,6 +29,8 @@ gofannon/google_search/google_search.py,sha256=WRaGSLoeZjy5Qtn89Sp01nNugiGI0NL1Z
27
29
  gofannon/headless_browser/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
30
  gofannon/headless_browser/base.py,sha256=bgvBvkTNCqRnhC8Ffc6oZ3yoxpOl6fkAq0doDKnQtt8,1721
29
31
  gofannon/headless_browser/headless_browser_get.py,sha256=kOnHxfoZayfCuS6OKloLdwxehiInwcd5dM0HbKAeM5U,1182
32
+ gofannon/nasa/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
+ gofannon/nasa/apod.py,sha256=YhH3pdAoIGvteJt6krYzfjNsIx0g4Y4yOTh2DvRuzEo,2404
30
34
  gofannon/nhsta/__init__.py,sha256=jTV6arXumVgJagKOq6GnYhHwcX9t7Jjqq5JvsE5-zxQ,1925
31
35
  gofannon/open_notify_space/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
32
36
  gofannon/open_notify_space/iss_locator.py,sha256=STLNSD5HriRR6grpRpiTRDbqVRtWMPVoGuV8SygHGNY,4734
@@ -39,7 +43,7 @@ gofannon/reasoning/sequential_cot.py,sha256=m9c8GnyTtmI-JntCuhkoFfULAabVOxsYgTRU
39
43
  gofannon/reasoning/tree_of_thought.py,sha256=TRhRJQNsFVauCLw4TOvQCDcX1nGmp_wSg9H67GJn1hs,10574
40
44
  gofannon/wikipedia/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
45
  gofannon/wikipedia/wikipedia_lookup.py,sha256=J6wKPbSivCF7cccaiRaJW1o0VqNhQAGfrh5U1ULLesg,2869
42
- gofannon-0.25.14.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
43
- gofannon-0.25.14.dist-info/METADATA,sha256=1kkXxb_c_NmP30eDMPwktODU5SwQ2uaPIKH1b9pPX9s,5352
44
- gofannon-0.25.14.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
45
- gofannon-0.25.14.dist-info/RECORD,,
46
+ gofannon-0.25.15.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
47
+ gofannon-0.25.15.dist-info/METADATA,sha256=vyfSJCkUQCWoM_KNFCwjikONrV7kcVo7rv8vVvY0DWE,5415
48
+ gofannon-0.25.15.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
49
+ gofannon-0.25.15.dist-info/RECORD,,