gofannon 0.25.17__py3-none-any.whl → 0.25.18__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
@@ -15,6 +15,7 @@ from .langchain import LangchainMixin
15
15
  from .bedrock import BedrockMixin
16
16
  from .langflow import LangflowMixin
17
17
  from .mcp import MCPMixin
18
+ from .llamastack import LlamaStackMixin
18
19
 
19
20
 
20
21
  @dataclass
@@ -72,6 +73,7 @@ class BaseTool(SmolAgentsMixin,
72
73
  BedrockMixin,
73
74
  LangflowMixin,
74
75
  MCPMixin,
76
+ LlamaStackMixin,
75
77
  ABC):
76
78
  def __init__(self, **kwargs):
77
79
  self.logger = logging.getLogger(
@@ -0,0 +1,266 @@
1
+ # gofannon/base/llamastack.py
2
+
3
+ import inspect
4
+ import re
5
+ from textwrap import dedent
6
+ from typing import Callable, Any
7
+
8
+ # Type mapping from Gofannon definition to Python types (primarily for potential future use,
9
+ # as Llama Stack example doesn't heavily rely on type hints in the generated function)
10
+ GOFANNON_TO_PYTHON_TYPE_MAP = {
11
+ "string": str,
12
+ "number": float,
13
+ "integer": int,
14
+ "boolean": bool,
15
+ "object": dict,
16
+ "array": list,
17
+ }
18
+
19
+ # Type mapping from Python types/common hints to Gofannon definition types
20
+ PYTHON_TO_GOFANNON_TYPE_MAP = {
21
+ str: "string",
22
+ float: "number",
23
+ int: "integer",
24
+ bool: "boolean",
25
+ dict: "object",
26
+ list: "array",
27
+ Any: "string", # Default fallback
28
+ type(None): "string" # Default fallback for untyped
29
+ }
30
+
31
+
32
+ class LlamaStackMixin:
33
+ """
34
+ Mixin for converting Gofannon tools to and from the Llama Stack custom tool format.
35
+
36
+ Llama Stack expects custom tools as Python functions with specific docstrings.
37
+ See: https://github.com/meta-llama/llama-stack/blob/main/docs/tools.md#adding-custom-tools
38
+ """
39
+
40
+ def _parse_llamastack_docstring(self, docstring: str) -> tuple[str, dict[str, str], list[str]]:
41
+ """
42
+ Parses a Llama Stack style docstring to extract description and parameters.
43
+
44
+ Args:
45
+ docstring: The docstring content.
46
+
47
+ Returns:
48
+ A tuple containing:
49
+ - description (str): The main tool description.
50
+ - params (dict): A dictionary mapping parameter names to their descriptions.
51
+ - required (list): A list of required parameter names (inferred if not explicitly optional).
52
+ NOTE: Llama Stack's doc example doesn't show optional syntax, so we assume all
53
+ documented params are required unless function signature has defaults.
54
+ """
55
+ if not docstring:
56
+ return "No description provided.", {}, []
57
+
58
+ lines = docstring.strip().split('\n')
59
+ description_lines = []
60
+ params = {}
61
+ param_section_started = False
62
+
63
+ # Simple regex to find ':param <name>:' or ':param <name> (<type>):'
64
+ param_regex = re.compile(r":param\s+([\w_]+)(?:\s*\([^)]+\))?:\s*(.*)")
65
+
66
+ for line in lines:
67
+ line = line.strip()
68
+ if not line: # Skip empty lines between description and params
69
+ if description_lines and not param_section_started:
70
+ param_section_started = True # Assume blank line separates desc from params
71
+ continue
72
+
73
+ match = param_regex.match(line)
74
+ if match:
75
+ param_section_started = True
76
+ param_name = match.group(1)
77
+ param_desc = match.group(2).strip()
78
+ params[param_name] = param_desc
79
+ elif not param_section_started:
80
+ description_lines.append(line)
81
+
82
+ description = " ".join(description_lines).strip()
83
+ # Llama Stack example doesn't specify required/optional in docstring.
84
+ # We'll infer from function signature later.
85
+ # For now, return an empty required list based purely on docstring parsing.
86
+ required = list(params.keys()) # Assume all documented params are required initially
87
+
88
+ return description, params, required
89
+
90
+ def import_from_llamastack(self, llamastack_tool_func: Callable):
91
+ """
92
+ Adapts a Llama Stack custom tool function to a Gofannon tool.
93
+
94
+ Args:
95
+ llamastack_tool_func: The Python function representing the Llama Stack tool.
96
+ """
97
+ if not callable(llamastack_tool_func):
98
+ raise ValueError("Input must be a callable function.")
99
+
100
+ self.name = llamastack_tool_func.__name__
101
+ docstring = inspect.getdoc(llamastack_tool_func) or ""
102
+
103
+ # Parse docstring for description and param descriptions
104
+ description, param_descriptions, _ = self._parse_llamastack_docstring(docstring)
105
+ self.description = description # Set top-level description
106
+
107
+ # Use inspect.signature to get parameter names, types, and defaults
108
+ try:
109
+ sig = inspect.signature(llamastack_tool_func)
110
+ parameters_properties = {}
111
+ required_params = []
112
+
113
+ for name, param in sig.parameters.items():
114
+ param_type_hint = param.annotation
115
+ gofannon_type = PYTHON_TO_GOFANNON_TYPE_MAP.get(param_type_hint, "string") # Default to string if unknown
116
+
117
+ parameters_properties[name] = {
118
+ "type": gofannon_type,
119
+ "description": param_descriptions.get(name, f"Parameter '{name}'") # Use parsed desc or default
120
+ }
121
+
122
+ # If the parameter has no default value, it's required
123
+ if param.default is inspect.Parameter.empty:
124
+ required_params.append(name)
125
+
126
+ self.definition = {
127
+ "function": {
128
+ "name": self.name,
129
+ "description": self.description,
130
+ "parameters": {
131
+ "type": "object",
132
+ "properties": parameters_properties,
133
+ "required": required_params,
134
+ }
135
+ }
136
+ }
137
+
138
+ except Exception as e:
139
+ # Fallback if signature inspection fails (e.g., built-in function)
140
+ # Create a basic definition based only on name/docstring
141
+ self.logger.warning(f"Could not inspect signature for {self.name}: {e}. Creating basic definition.")
142
+ self.definition = {
143
+ "function": {
144
+ "name": self.name,
145
+ "description": self.description,
146
+ "parameters": { # Assume no parameters if signature fails
147
+ "type": "object",
148
+ "properties": {},
149
+ "required": []
150
+ }
151
+ }
152
+ }
153
+
154
+
155
+ # The core function is the Llama Stack function itself
156
+ self.fn = llamastack_tool_func
157
+
158
+ self.logger.info(f"Imported Llama Stack tool: {self.name}")
159
+
160
+
161
+ def export_to_llamastack(self) -> Callable:
162
+ """
163
+ Convert the Gofannon tool to a Llama Stack compatible function.
164
+
165
+ Returns:
166
+ A callable function with a Llama Stack-style docstring.
167
+ """
168
+ gofannon_def = self.definition.get("function", {})
169
+ tool_name = gofannon_def.get("name", getattr(self, "name", "gofannon_exported_tool"))
170
+ tool_description = gofannon_def.get("description", getattr(self, "description", "No description provided."))
171
+ parameters = gofannon_def.get("parameters", {})
172
+ param_properties = parameters.get("properties", {})
173
+ required_params = parameters.get("required", [])
174
+
175
+ # Construct the docstring
176
+ docstring_lines = [tool_description, ""]
177
+ param_lines = []
178
+ arg_names = []
179
+
180
+ for param_name, param_def in param_properties.items():
181
+ param_desc = param_def.get("description", "")
182
+ # Llama Stack example doesn't show type in docstring, just param name and description
183
+ # param_type = param_def.get("type", "string") # Could potentially add :type if needed
184
+ docstring_line = f":param {param_name}: {param_desc}"
185
+ # NOTE: Llama Stack example doesn't explicitly mark required/optional in docstring
186
+ # We could add (required) or (optional) if desired, but sticking to example format.
187
+ # if param_name in required_params:
188
+ # docstring_line += " (required)"
189
+ param_lines.append(docstring_line)
190
+ arg_names.append(param_name)
191
+
192
+ if param_lines:
193
+ docstring_lines.extend(param_lines)
194
+ docstring_lines.append("") # Add blank line after params if any
195
+
196
+ # Add a basic return description (Gofannon definition doesn't store this explicitly)
197
+ docstring_lines.append(":return: The result of executing the tool.")
198
+
199
+ final_docstring = "\n".join(docstring_lines)
200
+
201
+ # Create the wrapper function dynamically
202
+ original_fn = self.fn
203
+ args_string = ", ".join(arg_names)
204
+
205
+ # We need to define the function in a scope where original_fn is accessible
206
+ # Using exec can be risky, but is one way to dynamically create a function
207
+ # with a specific signature and docstring. A safer alternative might involve
208
+ # function factories or functools.wraps if the signature complexity allows.
209
+
210
+ # Let's try a closure approach which is generally safer:
211
+ def make_wrapper(original_func, doc, name, signature_args):
212
+ # Construct the function signature string dynamically
213
+ sig_str = f"({', '.join(signature_args)})"
214
+ # Use eval to create the function with the correct signature
215
+ # This is still somewhat risky, ensure signature_args are sanitized if needed.
216
+ # Define the wrapper within this factory function's scope
217
+ def wrapper(*args, **kwargs):
218
+ # Map positional args to keywords if necessary, or rely on kwargs
219
+ call_kwargs = {}
220
+ if args:
221
+ for i, arg_val in enumerate(args):
222
+ if i < len(signature_args):
223
+ call_kwargs[signature_args[i]] = arg_val
224
+ else:
225
+ # Handle extra positional args if necessary, maybe raise error?
226
+ pass
227
+ call_kwargs.update(kwargs)
228
+ return original_func(**call_kwargs)
229
+
230
+ wrapper.__doc__ = doc
231
+ wrapper.__name__ = name
232
+ # Try to mimic signature for inspection tools (might not be perfect)
233
+ try:
234
+ # Build parameter list for inspect.Signature
235
+ params = [inspect.Parameter(arg, inspect.Parameter.POSITIONAL_OR_KEYWORD) for arg in signature_args]
236
+ wrapper.__signature__ = inspect.Signature(parameters=params)
237
+ except Exception as e:
238
+ self.logger.warning(f"Could not set __signature__ for {name}: {e}")
239
+
240
+ return wrapper
241
+
242
+ # Generate the arguments list for the signature
243
+ signature_args_list = list(param_properties.keys())
244
+ exported_function = make_wrapper(original_fn, final_docstring, tool_name, signature_args_list)
245
+
246
+
247
+ # Alternative using exec (use with caution):
248
+ # func_code = f"""
249
+ # def {tool_name}({args_string}):
250
+ # '''{final_docstring}'''
251
+ # # Prepare kwargs for the original function
252
+ # kwargs_for_original = {{}}
253
+ # """
254
+ # for arg_name in arg_names:
255
+ # func_code += f" kwargs_for_original['{arg_name}'] = {arg_name}\n"
256
+ #
257
+ # func_code += f"""
258
+ # return original_fn(**kwargs_for_original)
259
+ # """
260
+ # local_scope = {'original_fn': original_fn}
261
+ # exec(dedent(func_code), local_scope)
262
+ # exported_function = local_scope[tool_name]
263
+
264
+ self.logger.info(f"Exported Gofannon tool '{self.name}' to Llama Stack format as function '{tool_name}'")
265
+ return exported_function
266
+
File without changes
@@ -0,0 +1,82 @@
1
+ import os
2
+
3
+ from..base import BaseTool
4
+ from ..config import FunctionRegistry
5
+ import logging
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+ @FunctionRegistry.register
10
+ class ListDirectory(BaseTool):
11
+ def __init__(self, name="list_directory"):
12
+ super().__init__()
13
+ self.name = name
14
+
15
+ @property
16
+ def definition(self):
17
+ return {
18
+ "type": "function",
19
+ "function": {
20
+ "name": self.name,
21
+ "description": "List the contents of a directory recursively in a tree-like format",
22
+ "parameters": {
23
+ "type": "object",
24
+ "properties": {
25
+ "directory_path": {
26
+ "type": "string",
27
+ "description": "The path of the directory to list"
28
+ },
29
+ "max_depth": {
30
+ "type": "integer",
31
+ "description": "Maximum depth to recurse into (default: 5)",
32
+ "default": 5
33
+ }
34
+ },
35
+ "required": ["directory_path"]
36
+ }
37
+ }
38
+ }
39
+
40
+ def _build_tree(self, path, prefix="", depth=0, max_depth=5):
41
+ if depth > max_depth:
42
+ return ""
43
+
44
+ try:
45
+ entries = os.listdir(path)
46
+ except PermissionError:
47
+ return f"{prefix}[Permission Denied]\n"
48
+ except FileNotFoundError:
49
+ return f"{prefix}[Directory Not Found]\n"
50
+
51
+ tree = ""
52
+ entries.sort()
53
+ length = len(entries)
54
+
55
+ for i, entry in enumerate(entries):
56
+ full_path = os.path.join(path, entry)
57
+ is_last = i == length - 1
58
+
59
+ if os.path.isdir(full_path):
60
+ tree += f"{prefix}{'└── ' if is_last else '├── '}{entry}/\n"
61
+ tree += self._build_tree(
62
+ full_path,
63
+ prefix + (" " if is_last else "│ "),
64
+ depth + 1,
65
+ max_depth
66
+ )
67
+ else:
68
+ tree += f"{prefix}{'└── ' if is_last else '├── '}{entry}\n"
69
+
70
+ return tree
71
+
72
+ def fn(self, directory_path, max_depth=5):
73
+ logger.debug(f"Listing directory: {directory_path}")
74
+
75
+ if not os.path.exists(directory_path):
76
+ return f"Error: Directory '{directory_path}' does not exist"
77
+
78
+ if not os.path.isdir(directory_path):
79
+ return f"Error: '{directory_path}' is not a directory"
80
+
81
+ tree = self._build_tree(directory_path, max_depth=max_depth)
82
+ return f"{directory_path}/\n{tree}"
@@ -0,0 +1,56 @@
1
+ import os
2
+
3
+ from..base import BaseTool
4
+ from ..config import FunctionRegistry
5
+ import logging
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+ @FunctionRegistry.register
10
+ class ReadFile(BaseTool):
11
+ """
12
+ A tool for reading the contents of a file from the local filesystem.
13
+
14
+ This class provides a function that takes a file path as input and returns
15
+ the contents of that file as a string.
16
+
17
+ Attributes:
18
+ file_path (str): The path to the file that should be read.
19
+ """
20
+ def __init__(self, name="read_file"):
21
+ super().__init__()
22
+ self.name = name
23
+
24
+ @property
25
+ def definition(self):
26
+ return {
27
+ "type": "function",
28
+ "function": {
29
+ "name": self.name,
30
+ "description": "Read the contents of a specified file.",
31
+ "parameters": {
32
+ "type": "object",
33
+ "properties": {
34
+ "file_path": {
35
+ "type": "string",
36
+ "description": "The path to the file to be read."
37
+ }
38
+ },
39
+ "required": ["file_path"]
40
+ }
41
+ }
42
+ }
43
+
44
+ def fn(self, file_path):
45
+ logger.debug(f"Reading file: {file_path}")
46
+ try:
47
+ if not os.path.exists(file_path):
48
+ raise FileNotFoundError(f"The file '{file_path}' does not exist.")
49
+
50
+ with open(file_path, 'r') as file:
51
+ content = file.read()
52
+
53
+ return content
54
+ except Exception as e:
55
+ logger.error(f"Error reading file: {e}")
56
+ return f"Error reading file: {e}"
@@ -0,0 +1,46 @@
1
+ from..base import BaseTool
2
+ from ..config import FunctionRegistry
3
+ import logging
4
+
5
+ logger = logging.getLogger(__name__)
6
+
7
+ @FunctionRegistry.register
8
+ class WriteFile(BaseTool):
9
+ def __init__(self, name="write_file"):
10
+ super().__init__()
11
+ self.name = name
12
+
13
+ @property
14
+ def definition(self):
15
+ return {
16
+ "type": "function",
17
+ "function": {
18
+ "name": self.name,
19
+ "description": "Write the contents of a sting to a specified file.",
20
+ "parameters": {
21
+ "type": "object",
22
+ "properties": {
23
+ "file_path": {
24
+ "type": "string",
25
+ "description": "The path to the file to be written."
26
+ },
27
+ "content": {
28
+ "type": "string",
29
+ "description": "The content to be written to the file."
30
+ }
31
+ },
32
+ "required": ["file_path", "content"]
33
+ }
34
+ }
35
+ }
36
+
37
+ def fn(self, file_path, content):
38
+ logger.debug(f"Writing file: {file_path}")
39
+ try:
40
+ with open(file_path, 'w') as file:
41
+ file.write(content)
42
+
43
+ return f"File {file_path} written successfully."
44
+ except Exception as e:
45
+ logger.error(f"Error writing file: {e}")
46
+ return f"Error writing file: {e}"
@@ -0,0 +1,110 @@
1
+ from..base import BaseTool
2
+ from requests import get
3
+ import json
4
+ from ..config import FunctionRegistry
5
+ import logging
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+
10
+ @FunctionRegistry.register
11
+ class ListIssues(BaseTool):
12
+ def __init__(self, api_key=None, name="list_issues"):
13
+ super().__init__()
14
+ self.api_key = api_key
15
+ self.name = name
16
+ self.API_SERVICE = 'github'
17
+
18
+ @property
19
+ def definition(self):
20
+ return {
21
+ "type": "function",
22
+ "function": {
23
+ "name": self.name,
24
+ "description": "List all issues in a GitHub repository",
25
+ "parameters": {
26
+ "type": "object",
27
+ "properties": {
28
+ "repo_url": {
29
+ "type": "string",
30
+ "description": "The URL of the repository, e.g. https://github.com/The-AI-Alliance/gofannon"
31
+ },
32
+ "state": {
33
+ "type": "string",
34
+ "enum": ["open", "closed", "all"],
35
+ "description": "Filter issues by state (default: open)",
36
+ "default": "open"
37
+ },
38
+ "labels": {
39
+ "type": "string",
40
+ "description": "Comma-separated list of label names to filter by"
41
+ },
42
+ "sort": {
43
+ "type": "string",
44
+ "enum": ["created", "updated", "comments"],
45
+ "description": "What to sort results by (default: created)",
46
+ "default": "created"
47
+ },
48
+ "direction": {
49
+ "type": "string",
50
+ "enum": ["asc", "desc"],
51
+ "description": "Sort direction (default: desc)",
52
+ "default": "desc"
53
+ },
54
+ "since": {
55
+ "type": "string",
56
+ "description": "Only show issues updated after this date (ISO 8601 format)"
57
+ }
58
+ },
59
+ "required": ["repo_url"]
60
+ }
61
+ }
62
+ }
63
+
64
+ def fn(self, repo_url, state="open", labels=None, sort="created", direction="desc", since=None):
65
+ logger.debug(f"Listing issues for repo {repo_url} with state={state}")
66
+ # Extracting the owner and repo name from the URL
67
+ repo_parts = repo_url.rstrip('/').split('/')
68
+ owner = repo_parts[-2]
69
+ repo = repo_parts[-1]
70
+
71
+ api_url = f"https://api.github.com/repos/{owner}/{repo}/issues"
72
+ headers = {
73
+ 'Authorization': f'token {self.api_key}',
74
+ 'Accept': 'application/vnd.github.v3+json'
75
+ }
76
+ params = {
77
+ 'state': state,
78
+ 'sort': sort,
79
+ 'direction': direction
80
+ }
81
+
82
+ if labels:
83
+ params['labels'] = labels
84
+ if since:
85
+ params['since'] = since
86
+
87
+ response = get(api_url, headers=headers, params=params)
88
+ response.raise_for_status()
89
+
90
+ issues = response.json()
91
+
92
+ # Format the response
93
+ formatted_issues = []
94
+ for issue in issues:
95
+ # Skip pull requests (GitHub API returns PRs as issues too)
96
+ if 'pull_request' in issue:
97
+ continue
98
+
99
+ formatted_issues.append({
100
+ "number": issue['number'],
101
+ "title": issue['title'],
102
+ "state": issue['state'],
103
+ "created_at": issue['created_at'],
104
+ "updated_at": issue['updated_at'],
105
+ "html_url": issue['html_url'],
106
+ "labels": [label['name'] for label in issue['labels']],
107
+ "user": issue['user']['login']
108
+ })
109
+
110
+ return formatted_issues
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: gofannon
3
- Version: 0.25.17
3
+ Version: 0.25.18
4
4
  Summary: A collection of tools for LLMs
5
5
  License: ASFv2
6
6
  Author: Trevor Grant
@@ -2,10 +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=gFBxYPxhyy1yLyXIEgbVPqQSgnr6PzXnEb1S054IYQM,3685
5
+ gofannon/base/__init__.py,sha256=wnTkASBszxkZiWugQOgvSdAghFFBUwxzRzz7wTMxg3c,3757
6
6
  gofannon/base/bedrock.py,sha256=Z2c36R8jaIusgpmegbYVz2eR7lDBc0IhTtwiqUGOcT4,25646
7
7
  gofannon/base/langchain.py,sha256=25z9opy7E7qWP-DSn6oYAqKDg8i21az-kAKrsYLfyiQ,2704
8
8
  gofannon/base/langflow.py,sha256=0WfNJ9MnndyLJ-yUAStIuXZpCzOPItsGKgtxdNifmLM,3833
9
+ gofannon/base/llamastack.py,sha256=M1820wdKgNBDca12fjO5PMWyhHu7Inj0qSioKqmFj8o,11251
9
10
  gofannon/base/mcp.py,sha256=2e7f1FiD_M7wk4gOd7YNt4zLBgdLQTnWWYL0Kf5CzTY,253
10
11
  gofannon/base/smol_agents.py,sha256=p2YU5BrscavGk5X9R7HSJmtVR5OpOsQwCd9hwC9eBMk,2229
11
12
  gofannon/basic_math/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
@@ -15,12 +16,17 @@ gofannon/basic_math/exponents.py,sha256=w4qDlFZ9M1lf6X-tjG-ndpECfCOS7Qtc_VLICw0o
15
16
  gofannon/basic_math/multiplication.py,sha256=PJ5sKWMCVlBaTeZ_j3gwYOEQXAhN-qIXhnrNcyhWGKM,1168
16
17
  gofannon/basic_math/subtraction.py,sha256=gM1_N1mZ3qAXC6qnkzfijKXiOx27Gg93-CaB_ifMbOQ,1164
17
18
  gofannon/config.py,sha256=KPVtjBnpwfM39EQg-_xiqL1UFxcuQehrQIUS6HHBP6k,1784
19
+ gofannon/file/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
+ gofannon/file/list_directory.py,sha256=Jw0F50_hdtyDSFBmcy9e8F4KajtsPyT8Gsm_eyjMUuQ,2679
21
+ gofannon/file/read_file.py,sha256=kYf-4aGCHLj-D-XQs0YBEnbB1MbIccgcWbiLnVXidp4,1669
22
+ gofannon/file/write_file.py,sha256=fQ5P4cqZKdoq8Bk7nys2Esau0Q5WvbeY8srGvfx36NQ,1495
18
23
  gofannon/github/__init__.py,sha256=VFw4sJIt4Zc0-__eYnksN8Ku9qMhbPpHJEkXMWUiD30,4
19
24
  gofannon/github/clone_repo.py,sha256=UNXh1JaZkzK94REJUfQrBAhF66ncFWkzcZj34Si34cI,2287
20
25
  gofannon/github/commit_file.py,sha256=jdQGQHbrZx4521XgTbx5N0Ss8fDyl7hvp9sjDW15v9U,2573
21
26
  gofannon/github/commit_files.py,sha256=OZclhhSejRB1CYmd7IGYvdJZEWBzpaRRKK5S8NQxALU,4554
22
27
  gofannon/github/create_issue.py,sha256=oS4Q-3urpd-qTJ9K4cCCrwMl_QumlVFsM5q-M1_pc_I,2475
23
28
  gofannon/github/get_repo_contents.py,sha256=9k6M2BqGlNsSGVjyfW7nxZpk1TFuhyPoZvURkv1PEyo,3637
29
+ gofannon/github/list_issues.py,sha256=F1YkRrmtequaGAPo-dIanyi75SQ-Gq5UWMf6cmhOLcY,4018
24
30
  gofannon/github/pr_review_tool.py,sha256=srBbfgqBWy-J4wdAM0kLJfQr8LJ6uaA4vkDErqhyMxI,4336
25
31
  gofannon/github/read_issue.py,sha256=JrnBAlZxknhHm3aLC0uB9u0bSvoQNfK3OKmxYlr8jgQ,2308
26
32
  gofannon/github/search.py,sha256=yuX_dZ6f8ogUnskIRMUgF8wuN7JepqRtTDFrbmbwrrs,2183
@@ -43,7 +49,7 @@ gofannon/reasoning/sequential_cot.py,sha256=m9c8GnyTtmI-JntCuhkoFfULAabVOxsYgTRU
43
49
  gofannon/reasoning/tree_of_thought.py,sha256=TRhRJQNsFVauCLw4TOvQCDcX1nGmp_wSg9H67GJn1hs,10574
44
50
  gofannon/wikipedia/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
51
  gofannon/wikipedia/wikipedia_lookup.py,sha256=J6wKPbSivCF7cccaiRaJW1o0VqNhQAGfrh5U1ULLesg,2869
46
- gofannon-0.25.17.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
47
- gofannon-0.25.17.dist-info/METADATA,sha256=CHzEBQQRiROqssrVgBKj2e3Qk-sZaV-NcGZfK6aXNh4,5415
48
- gofannon-0.25.17.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
49
- gofannon-0.25.17.dist-info/RECORD,,
52
+ gofannon-0.25.18.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
53
+ gofannon-0.25.18.dist-info/METADATA,sha256=fEPx-nCBs3eCopXGFC-fo7UODM7aHKBSt5KE2X2i5Qk,5415
54
+ gofannon-0.25.18.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
55
+ gofannon-0.25.18.dist-info/RECORD,,