github-agent 0.2.1__tar.gz → 0.2.4__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.
- {github_agent-0.2.1 → github_agent-0.2.4}/PKG-INFO +7 -7
- {github_agent-0.2.1 → github_agent-0.2.4}/README.md +4 -4
- {github_agent-0.2.1 → github_agent-0.2.4}/github_agent/github_agent.py +33 -20
- {github_agent-0.2.1 → github_agent-0.2.4}/github_agent/utils.py +137 -4
- {github_agent-0.2.1 → github_agent-0.2.4}/github_agent.egg-info/PKG-INFO +7 -7
- github_agent-0.2.4/github_agent.egg-info/requires.txt +6 -0
- {github_agent-0.2.1 → github_agent-0.2.4}/pyproject.toml +3 -3
- github_agent-0.2.1/github_agent.egg-info/requires.txt +0 -6
- {github_agent-0.2.1 → github_agent-0.2.4}/LICENSE +0 -0
- {github_agent-0.2.1 → github_agent-0.2.4}/github_agent/__init__.py +0 -0
- {github_agent-0.2.1 → github_agent-0.2.4}/github_agent.egg-info/SOURCES.txt +0 -0
- {github_agent-0.2.1 → github_agent-0.2.4}/github_agent.egg-info/dependency_links.txt +0 -0
- {github_agent-0.2.1 → github_agent-0.2.4}/github_agent.egg-info/entry_points.txt +0 -0
- {github_agent-0.2.1 → github_agent-0.2.4}/github_agent.egg-info/top_level.txt +0 -0
- {github_agent-0.2.1 → github_agent-0.2.4}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: github-agent
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: GitHub Agent for MCP
|
|
5
5
|
Author-email: Audel Rouhi <knucklessg1@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -12,8 +12,8 @@ Classifier: Programming Language :: Python :: 3
|
|
|
12
12
|
Requires-Python: >=3.10
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
15
|
-
Requires-Dist: pydantic-ai-slim[a2a,ag-ui,anthropic,fastmcp,google,huggingface,openai,web]>=1.
|
|
16
|
-
Requires-Dist: pydantic-ai-skills
|
|
15
|
+
Requires-Dist: pydantic-ai-slim[a2a,ag-ui,anthropic,fastmcp,google,groq,huggingface,mistral,openai,web]>=1.58.0
|
|
16
|
+
Requires-Dist: pydantic-ai-skills>=v0.4.0
|
|
17
17
|
Requires-Dist: fastapi>=0.128.0
|
|
18
18
|
Requires-Dist: fastmcp
|
|
19
19
|
Requires-Dist: uvicorn
|
|
@@ -43,7 +43,7 @@ Dynamic: license-file
|
|
|
43
43
|

|
|
44
44
|

|
|
45
45
|
|
|
46
|
-
*Version: 0.2.
|
|
46
|
+
*Version: 0.2.4*
|
|
47
47
|
|
|
48
48
|
## Overview
|
|
49
49
|
|
|
@@ -172,7 +172,7 @@ The `github-agent` command starts the server.
|
|
|
172
172
|
| `--port` | Port to bind the server to | `9000` |
|
|
173
173
|
| `--mcp-config` | Path to MCP configuration file | `mcp_config.json` |
|
|
174
174
|
| `--provider` | LLM Provider (openai, anthropic, google, etc.) | `openai` |
|
|
175
|
-
| `--model-id` | LLM Model ID | `qwen/qwen3-
|
|
175
|
+
| `--model-id` | LLM Model ID | `qwen/qwen3-coder-next` |
|
|
176
176
|
|
|
177
177
|
### Running the Agent Server
|
|
178
178
|
|
|
@@ -193,7 +193,7 @@ docker build -t github-agent .
|
|
|
193
193
|
```bash
|
|
194
194
|
docker run -d \
|
|
195
195
|
-p 9000:9000 \
|
|
196
|
-
-e
|
|
196
|
+
-e LLM_API_KEY=sk-... \
|
|
197
197
|
-e MCP_CONFIG=/app/mcp_config.json \
|
|
198
198
|
knucklessg1/github-agent:latest
|
|
199
199
|
```
|
|
@@ -211,7 +211,7 @@ services:
|
|
|
211
211
|
environment:
|
|
212
212
|
- PROVIDER=openai
|
|
213
213
|
- MODEL_ID=gpt-4o
|
|
214
|
-
-
|
|
214
|
+
- LLM_API_KEY=${LLM_API_KEY}
|
|
215
215
|
volumes:
|
|
216
216
|
- ./mcp_config.json:/app/mcp_config.json
|
|
217
217
|
```
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|

|
|
22
22
|

|
|
23
23
|
|
|
24
|
-
*Version: 0.2.
|
|
24
|
+
*Version: 0.2.4*
|
|
25
25
|
|
|
26
26
|
## Overview
|
|
27
27
|
|
|
@@ -150,7 +150,7 @@ The `github-agent` command starts the server.
|
|
|
150
150
|
| `--port` | Port to bind the server to | `9000` |
|
|
151
151
|
| `--mcp-config` | Path to MCP configuration file | `mcp_config.json` |
|
|
152
152
|
| `--provider` | LLM Provider (openai, anthropic, google, etc.) | `openai` |
|
|
153
|
-
| `--model-id` | LLM Model ID | `qwen/qwen3-
|
|
153
|
+
| `--model-id` | LLM Model ID | `qwen/qwen3-coder-next` |
|
|
154
154
|
|
|
155
155
|
### Running the Agent Server
|
|
156
156
|
|
|
@@ -171,7 +171,7 @@ docker build -t github-agent .
|
|
|
171
171
|
```bash
|
|
172
172
|
docker run -d \
|
|
173
173
|
-p 9000:9000 \
|
|
174
|
-
-e
|
|
174
|
+
-e LLM_API_KEY=sk-... \
|
|
175
175
|
-e MCP_CONFIG=/app/mcp_config.json \
|
|
176
176
|
knucklessg1/github-agent:latest
|
|
177
177
|
```
|
|
@@ -189,7 +189,7 @@ services:
|
|
|
189
189
|
environment:
|
|
190
190
|
- PROVIDER=openai
|
|
191
191
|
- MODEL_ID=gpt-4o
|
|
192
|
-
-
|
|
192
|
+
- LLM_API_KEY=${LLM_API_KEY}
|
|
193
193
|
volumes:
|
|
194
194
|
- ./mcp_config.json:/app/mcp_config.json
|
|
195
195
|
```
|
|
@@ -11,7 +11,11 @@ from typing import Optional, Any
|
|
|
11
11
|
from contextlib import asynccontextmanager
|
|
12
12
|
|
|
13
13
|
from pydantic_ai import Agent, ModelSettings, RunContext
|
|
14
|
-
from pydantic_ai.mcp import
|
|
14
|
+
from pydantic_ai.mcp import (
|
|
15
|
+
load_mcp_servers,
|
|
16
|
+
MCPServerStreamableHTTP,
|
|
17
|
+
MCPServerSSE,
|
|
18
|
+
)
|
|
15
19
|
from pydantic_ai_skills import SkillsToolset
|
|
16
20
|
from fasta2a import Skill
|
|
17
21
|
from github_agent.utils import (
|
|
@@ -34,7 +38,7 @@ from pydantic import ValidationError
|
|
|
34
38
|
from pydantic_ai.ui import SSE_CONTENT_TYPE
|
|
35
39
|
from pydantic_ai.ui.ag_ui import AGUIAdapter
|
|
36
40
|
|
|
37
|
-
__version__ = "0.2.
|
|
41
|
+
__version__ = "0.2.4"
|
|
38
42
|
|
|
39
43
|
logging.basicConfig(
|
|
40
44
|
level=logging.INFO,
|
|
@@ -50,18 +54,17 @@ DEFAULT_HOST = os.getenv("HOST", "0.0.0.0")
|
|
|
50
54
|
DEFAULT_PORT = to_integer(string=os.getenv("PORT", "9000"))
|
|
51
55
|
DEFAULT_DEBUG = to_boolean(string=os.getenv("DEBUG", "False"))
|
|
52
56
|
DEFAULT_PROVIDER = os.getenv("PROVIDER", "openai")
|
|
53
|
-
DEFAULT_MODEL_ID = os.getenv("MODEL_ID", "qwen/qwen3-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
)
|
|
57
|
-
DEFAULT_OPENAI_API_KEY = os.getenv("OPENAI_API_KEY", "ollama")
|
|
57
|
+
DEFAULT_MODEL_ID = os.getenv("MODEL_ID", "qwen/qwen3-coder-next")
|
|
58
|
+
DEFAULT_LLM_BASE_URL = os.getenv("LLM_BASE_URL", "http://host.docker.internal:1234/v1")
|
|
59
|
+
DEFAULT_LLM_API_KEY = os.getenv("LLM_API_KEY", "ollama")
|
|
58
60
|
DEFAULT_MCP_URL = os.getenv("MCP_URL", None)
|
|
59
61
|
DEFAULT_MCP_CONFIG = os.getenv("MCP_CONFIG", get_mcp_config_path())
|
|
60
62
|
DEFAULT_SKILLS_DIRECTORY = os.getenv("SKILLS_DIRECTORY", get_skills_path())
|
|
61
63
|
DEFAULT_ENABLE_WEB_UI = to_boolean(os.getenv("ENABLE_WEB_UI", "False"))
|
|
64
|
+
DEFAULT_SSL_VERIFY = to_boolean(os.getenv("SSL_VERIFY", "True"))
|
|
62
65
|
|
|
63
66
|
# Model Settings
|
|
64
|
-
DEFAULT_MAX_TOKENS = to_integer(os.getenv("MAX_TOKENS", "
|
|
67
|
+
DEFAULT_MAX_TOKENS = to_integer(os.getenv("MAX_TOKENS", "16384"))
|
|
65
68
|
DEFAULT_TEMPERATURE = to_float(os.getenv("TEMPERATURE", "0.7"))
|
|
66
69
|
DEFAULT_TOP_P = to_float(os.getenv("TOP_P", "1.0"))
|
|
67
70
|
DEFAULT_TIMEOUT = to_float(os.getenv("TIMEOUT", "32400.0"))
|
|
@@ -274,13 +277,20 @@ def create_agent(
|
|
|
274
277
|
mcp_url: str = DEFAULT_MCP_URL,
|
|
275
278
|
mcp_config: str = DEFAULT_MCP_CONFIG,
|
|
276
279
|
skills_directory: Optional[str] = DEFAULT_SKILLS_DIRECTORY,
|
|
280
|
+
ssl_verify: bool = DEFAULT_SSL_VERIFY,
|
|
277
281
|
) -> Agent:
|
|
278
282
|
"""
|
|
279
283
|
Creates the Supervisor Agent with sub-agents registered as tools.
|
|
280
284
|
"""
|
|
281
285
|
logger.info("Initializing Multi-Agent System for GitHub...")
|
|
282
286
|
|
|
283
|
-
model = create_model(
|
|
287
|
+
model = create_model(
|
|
288
|
+
provider=provider,
|
|
289
|
+
model_id=model_id,
|
|
290
|
+
base_url=base_url,
|
|
291
|
+
api_key=api_key,
|
|
292
|
+
ssl_verify=ssl_verify,
|
|
293
|
+
)
|
|
284
294
|
settings = ModelSettings(
|
|
285
295
|
max_tokens=DEFAULT_MAX_TOKENS,
|
|
286
296
|
temperature=DEFAULT_TEMPERATURE,
|
|
@@ -297,21 +307,21 @@ def create_agent(
|
|
|
297
307
|
)
|
|
298
308
|
|
|
299
309
|
# Load master toolsets
|
|
300
|
-
|
|
301
|
-
if
|
|
302
|
-
mcp_toolset = load_mcp_servers(mcp_config)
|
|
303
|
-
master_toolsets.extend(mcp_toolset)
|
|
304
|
-
logger.info(f"Connected to MCP Config JSON: {mcp_toolset}")
|
|
305
|
-
elif mcp_url:
|
|
310
|
+
agent_toolsets = []
|
|
311
|
+
if mcp_url:
|
|
306
312
|
if "sse" in mcp_url.lower():
|
|
307
313
|
server = MCPServerSSE(mcp_url)
|
|
308
314
|
else:
|
|
309
315
|
server = MCPServerStreamableHTTP(mcp_url)
|
|
310
|
-
|
|
316
|
+
agent_toolsets.append(server)
|
|
311
317
|
logger.info(f"Connected to MCP Server: {mcp_url}")
|
|
318
|
+
elif mcp_config:
|
|
319
|
+
mcp_toolset = load_mcp_servers(mcp_config)
|
|
320
|
+
agent_toolsets.extend(mcp_toolset)
|
|
321
|
+
logger.info(f"Connected to MCP Config JSON: {mcp_toolset}")
|
|
312
322
|
|
|
313
323
|
if skills_directory and os.path.exists(skills_directory):
|
|
314
|
-
|
|
324
|
+
agent_toolsets.append(SkillsToolset(directories=[str(skills_directory)]))
|
|
315
325
|
|
|
316
326
|
# Define Tag -> Prompt map
|
|
317
327
|
# Key is the MCP Tool Tag (or set of tags), Value is (SystemPrompt, AgentName)
|
|
@@ -352,7 +362,7 @@ def create_agent(
|
|
|
352
362
|
|
|
353
363
|
for tag, (system_prompt, agent_name) in agent_defs.items():
|
|
354
364
|
tag_toolsets = []
|
|
355
|
-
for ts in
|
|
365
|
+
for ts in agent_toolsets:
|
|
356
366
|
|
|
357
367
|
def filter_func(ctx, tool_def, t=tag):
|
|
358
368
|
return tool_in_tag(tool_def, t)
|
|
@@ -569,6 +579,7 @@ def create_agent_server(
|
|
|
569
579
|
host: Optional[str] = DEFAULT_HOST,
|
|
570
580
|
port: Optional[int] = DEFAULT_PORT,
|
|
571
581
|
enable_web_ui: bool = DEFAULT_ENABLE_WEB_UI,
|
|
582
|
+
ssl_verify: bool = DEFAULT_SSL_VERIFY,
|
|
572
583
|
):
|
|
573
584
|
print(
|
|
574
585
|
f"Starting {AGENT_NAME} with provider={provider}, model={model_id}, mcp={mcp_url} | {mcp_config}"
|
|
@@ -581,6 +592,7 @@ def create_agent_server(
|
|
|
581
592
|
mcp_url=mcp_url,
|
|
582
593
|
mcp_config=mcp_config,
|
|
583
594
|
skills_directory=skills_directory,
|
|
595
|
+
ssl_verify=ssl_verify,
|
|
584
596
|
)
|
|
585
597
|
|
|
586
598
|
if skills_directory and os.path.exists(skills_directory):
|
|
@@ -695,10 +707,10 @@ def agent_server():
|
|
|
695
707
|
parser.add_argument("--model-id", default=DEFAULT_MODEL_ID, help="LLM Model ID")
|
|
696
708
|
parser.add_argument(
|
|
697
709
|
"--base-url",
|
|
698
|
-
default=
|
|
710
|
+
default=DEFAULT_LLM_BASE_URL,
|
|
699
711
|
help="LLM Base URL (for OpenAI compatible providers)",
|
|
700
712
|
)
|
|
701
|
-
parser.add_argument("--api-key", default=
|
|
713
|
+
parser.add_argument("--api-key", default=DEFAULT_LLM_API_KEY, help="LLM API Key")
|
|
702
714
|
parser.add_argument("--mcp-url", default=DEFAULT_MCP_URL, help="MCP Server URL")
|
|
703
715
|
parser.add_argument(
|
|
704
716
|
"--mcp-config", default=DEFAULT_MCP_CONFIG, help="MCP Server Config"
|
|
@@ -753,6 +765,7 @@ def agent_server():
|
|
|
753
765
|
host=args.host,
|
|
754
766
|
port=args.port,
|
|
755
767
|
enable_web_ui=args.web,
|
|
768
|
+
ssl_verify=not args.insecure,
|
|
756
769
|
)
|
|
757
770
|
|
|
758
771
|
|
|
@@ -2,6 +2,38 @@
|
|
|
2
2
|
# coding: utf-8
|
|
3
3
|
|
|
4
4
|
import os
|
|
5
|
+
|
|
6
|
+
# Try importing specific clients/providers, but don't fail if variables are missing
|
|
7
|
+
try:
|
|
8
|
+
|
|
9
|
+
from openai import AsyncOpenAI
|
|
10
|
+
from pydantic_ai.providers.openai import OpenAIProvider
|
|
11
|
+
except ImportError:
|
|
12
|
+
AsyncOpenAI = None
|
|
13
|
+
OpenAIProvider = None
|
|
14
|
+
|
|
15
|
+
try:
|
|
16
|
+
from groq import AsyncGroq
|
|
17
|
+
from pydantic_ai.providers.groq import GroqProvider
|
|
18
|
+
except ImportError:
|
|
19
|
+
AsyncGroq = None
|
|
20
|
+
GroqProvider = None
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
from mistralai import Mistral
|
|
24
|
+
from pydantic_ai.providers.mistral import MistralProvider
|
|
25
|
+
except ImportError:
|
|
26
|
+
Mistral = None
|
|
27
|
+
MistralProvider = None
|
|
28
|
+
|
|
29
|
+
try:
|
|
30
|
+
from anthropic import AsyncAnthropic
|
|
31
|
+
from pydantic_ai.providers.anthropic import AnthropicProvider
|
|
32
|
+
except ImportError:
|
|
33
|
+
AsyncAnthropic = None
|
|
34
|
+
AnthropicProvider = None
|
|
35
|
+
|
|
36
|
+
import httpx
|
|
5
37
|
import pickle
|
|
6
38
|
import yaml
|
|
7
39
|
from pathlib import Path
|
|
@@ -12,6 +44,8 @@ from pydantic_ai.models.openai import OpenAIChatModel
|
|
|
12
44
|
from pydantic_ai.models.anthropic import AnthropicModel
|
|
13
45
|
from pydantic_ai.models.google import GoogleModel
|
|
14
46
|
from pydantic_ai.models.huggingface import HuggingFaceModel
|
|
47
|
+
from pydantic_ai.models.groq import GroqModel
|
|
48
|
+
from pydantic_ai.models.mistral import MistralModel
|
|
15
49
|
from pydantic_ai_skills import Skill
|
|
16
50
|
|
|
17
51
|
|
|
@@ -211,36 +245,135 @@ def load_skills_from_directory(directory: str) -> List[Skill]:
|
|
|
211
245
|
return skills
|
|
212
246
|
|
|
213
247
|
|
|
248
|
+
def get_http_client(ssl_verify: bool = True) -> httpx.AsyncClient | None:
|
|
249
|
+
if not ssl_verify:
|
|
250
|
+
return httpx.AsyncClient(verify=False)
|
|
251
|
+
return None
|
|
252
|
+
|
|
253
|
+
|
|
214
254
|
def create_model(
|
|
215
255
|
provider: str,
|
|
216
256
|
model_id: str,
|
|
217
|
-
base_url: Optional[str],
|
|
218
|
-
api_key: Optional[str],
|
|
257
|
+
base_url: Optional[str] = None,
|
|
258
|
+
api_key: Optional[str] = None,
|
|
259
|
+
ssl_verify: bool = True,
|
|
219
260
|
):
|
|
261
|
+
"""
|
|
262
|
+
Create a Pydantic AI model with the specified provider and configuration.
|
|
263
|
+
|
|
264
|
+
Args:
|
|
265
|
+
provider: The model provider (openai, anthropic, google, groq, mistral, huggingface, ollama)
|
|
266
|
+
model_id: The specific model ID to use
|
|
267
|
+
base_url: Optional base URL for the API
|
|
268
|
+
api_key: Optional API key
|
|
269
|
+
ssl_verify: Whether to verify SSL certificates (default: True)
|
|
270
|
+
|
|
271
|
+
Returns:
|
|
272
|
+
A Pydantic AI Model instance
|
|
273
|
+
"""
|
|
274
|
+
# Create a custom HTTP client if SSL verification is disabled
|
|
275
|
+
http_client = None
|
|
276
|
+
if not ssl_verify:
|
|
277
|
+
http_client = httpx.AsyncClient(verify=False)
|
|
278
|
+
|
|
220
279
|
if provider == "openai":
|
|
221
280
|
target_base_url = base_url
|
|
222
281
|
target_api_key = api_key
|
|
282
|
+
|
|
283
|
+
# If we have a custom client or specific settings, we might want to use the explicit provider object
|
|
284
|
+
if http_client and AsyncOpenAI and OpenAIProvider:
|
|
285
|
+
client = AsyncOpenAI(
|
|
286
|
+
api_key=target_api_key or os.environ.get("OPENAI_API_KEY"),
|
|
287
|
+
base_url=target_base_url or os.environ.get("OPENAI_BASE_URL"),
|
|
288
|
+
http_client=http_client,
|
|
289
|
+
)
|
|
290
|
+
provider_instance = OpenAIProvider(openai_client=client)
|
|
291
|
+
return OpenAIChatModel(model_name=model_id, provider=provider_instance)
|
|
292
|
+
|
|
293
|
+
# Fallback to standard env vars
|
|
223
294
|
if target_base_url:
|
|
224
295
|
os.environ["OPENAI_BASE_URL"] = target_base_url
|
|
225
296
|
if target_api_key:
|
|
226
297
|
os.environ["OPENAI_API_KEY"] = target_api_key
|
|
227
298
|
return OpenAIChatModel(model_name=model_id, provider="openai")
|
|
228
299
|
|
|
300
|
+
elif provider == "ollama":
|
|
301
|
+
# Ollama is OpenAI compatible
|
|
302
|
+
target_base_url = base_url or "http://localhost:11434/v1"
|
|
303
|
+
target_api_key = api_key or "ollama"
|
|
304
|
+
|
|
305
|
+
if http_client and AsyncOpenAI and OpenAIProvider:
|
|
306
|
+
client = AsyncOpenAI(
|
|
307
|
+
api_key=target_api_key,
|
|
308
|
+
base_url=target_base_url,
|
|
309
|
+
http_client=http_client,
|
|
310
|
+
)
|
|
311
|
+
provider_instance = OpenAIProvider(openai_client=client)
|
|
312
|
+
return OpenAIChatModel(model_name=model_id, provider=provider_instance)
|
|
313
|
+
|
|
314
|
+
os.environ["OPENAI_BASE_URL"] = target_base_url
|
|
315
|
+
os.environ["OPENAI_API_KEY"] = target_api_key
|
|
316
|
+
return OpenAIChatModel(model_name=model_id, provider="openai")
|
|
317
|
+
|
|
229
318
|
elif provider == "anthropic":
|
|
230
319
|
if api_key:
|
|
231
320
|
os.environ["ANTHROPIC_API_KEY"] = api_key
|
|
321
|
+
|
|
322
|
+
# AnthropicModel supports http_client directly via some paths,
|
|
323
|
+
# but pydantic-ai might prefer we pass the client to the provider or use a custom client
|
|
324
|
+
|
|
325
|
+
try:
|
|
326
|
+
if http_client and AsyncAnthropic and AnthropicProvider:
|
|
327
|
+
client = AsyncAnthropic(
|
|
328
|
+
api_key=api_key or os.environ.get("ANTHROPIC_API_KEY"),
|
|
329
|
+
http_client=http_client,
|
|
330
|
+
)
|
|
331
|
+
provider_instance = AnthropicProvider(anthropic_client=client)
|
|
332
|
+
return AnthropicModel(model_name=model_id, provider=provider_instance)
|
|
333
|
+
except ImportError:
|
|
334
|
+
pass
|
|
335
|
+
|
|
232
336
|
return AnthropicModel(model_name=model_id)
|
|
233
337
|
|
|
234
338
|
elif provider == "google":
|
|
235
339
|
if api_key:
|
|
236
340
|
os.environ["GEMINI_API_KEY"] = api_key
|
|
237
|
-
|
|
341
|
+
# Google SSL disable is tricky with genai, skipping for now unless specifically requested/researched
|
|
238
342
|
return GoogleModel(model_name=model_id)
|
|
239
343
|
|
|
344
|
+
elif provider == "groq":
|
|
345
|
+
if api_key:
|
|
346
|
+
os.environ["GROQ_API_KEY"] = api_key
|
|
347
|
+
|
|
348
|
+
if http_client and AsyncGroq and GroqProvider:
|
|
349
|
+
client = AsyncGroq(
|
|
350
|
+
api_key=api_key or os.environ.get("GROQ_API_KEY"),
|
|
351
|
+
http_client=http_client,
|
|
352
|
+
)
|
|
353
|
+
provider_instance = GroqProvider(groq_client=client)
|
|
354
|
+
return GroqModel(model_name=model_id, provider=provider_instance)
|
|
355
|
+
|
|
356
|
+
return GroqModel(model_name=model_id)
|
|
357
|
+
|
|
358
|
+
elif provider == "mistral":
|
|
359
|
+
if api_key:
|
|
360
|
+
os.environ["MISTRAL_API_KEY"] = api_key
|
|
361
|
+
|
|
362
|
+
if http_client and Mistral and MistralProvider:
|
|
363
|
+
# Assuming mistral_client argument for MistralProvider
|
|
364
|
+
# Ideally we would verify this, but we'll try standard pattern
|
|
365
|
+
pass
|
|
366
|
+
# client = Mistral(...) - Mistral SDK might be different
|
|
367
|
+
# Skipping Mistral custom client for now to avoid breaking without verification
|
|
368
|
+
# If user needs Mistral SSL disable, we'll need to research Mistral SDK + Provider
|
|
369
|
+
|
|
370
|
+
return MistralModel(model_name=model_id)
|
|
371
|
+
|
|
240
372
|
elif provider == "huggingface":
|
|
241
373
|
if api_key:
|
|
242
|
-
os.environ["
|
|
374
|
+
os.environ["HUGGING_FACE_API_KEY"] = api_key
|
|
243
375
|
return HuggingFaceModel(model_name=model_id)
|
|
376
|
+
|
|
244
377
|
return OpenAIChatModel(model_name=model_id, provider="openai")
|
|
245
378
|
|
|
246
379
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: github-agent
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: GitHub Agent for MCP
|
|
5
5
|
Author-email: Audel Rouhi <knucklessg1@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -12,8 +12,8 @@ Classifier: Programming Language :: Python :: 3
|
|
|
12
12
|
Requires-Python: >=3.10
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
15
|
-
Requires-Dist: pydantic-ai-slim[a2a,ag-ui,anthropic,fastmcp,google,huggingface,openai,web]>=1.
|
|
16
|
-
Requires-Dist: pydantic-ai-skills
|
|
15
|
+
Requires-Dist: pydantic-ai-slim[a2a,ag-ui,anthropic,fastmcp,google,groq,huggingface,mistral,openai,web]>=1.58.0
|
|
16
|
+
Requires-Dist: pydantic-ai-skills>=v0.4.0
|
|
17
17
|
Requires-Dist: fastapi>=0.128.0
|
|
18
18
|
Requires-Dist: fastmcp
|
|
19
19
|
Requires-Dist: uvicorn
|
|
@@ -43,7 +43,7 @@ Dynamic: license-file
|
|
|
43
43
|

|
|
44
44
|

|
|
45
45
|
|
|
46
|
-
*Version: 0.2.
|
|
46
|
+
*Version: 0.2.4*
|
|
47
47
|
|
|
48
48
|
## Overview
|
|
49
49
|
|
|
@@ -172,7 +172,7 @@ The `github-agent` command starts the server.
|
|
|
172
172
|
| `--port` | Port to bind the server to | `9000` |
|
|
173
173
|
| `--mcp-config` | Path to MCP configuration file | `mcp_config.json` |
|
|
174
174
|
| `--provider` | LLM Provider (openai, anthropic, google, etc.) | `openai` |
|
|
175
|
-
| `--model-id` | LLM Model ID | `qwen/qwen3-
|
|
175
|
+
| `--model-id` | LLM Model ID | `qwen/qwen3-coder-next` |
|
|
176
176
|
|
|
177
177
|
### Running the Agent Server
|
|
178
178
|
|
|
@@ -193,7 +193,7 @@ docker build -t github-agent .
|
|
|
193
193
|
```bash
|
|
194
194
|
docker run -d \
|
|
195
195
|
-p 9000:9000 \
|
|
196
|
-
-e
|
|
196
|
+
-e LLM_API_KEY=sk-... \
|
|
197
197
|
-e MCP_CONFIG=/app/mcp_config.json \
|
|
198
198
|
knucklessg1/github-agent:latest
|
|
199
199
|
```
|
|
@@ -211,7 +211,7 @@ services:
|
|
|
211
211
|
environment:
|
|
212
212
|
- PROVIDER=openai
|
|
213
213
|
- MODEL_ID=gpt-4o
|
|
214
|
-
-
|
|
214
|
+
- LLM_API_KEY=${LLM_API_KEY}
|
|
215
215
|
volumes:
|
|
216
216
|
- ./mcp_config.json:/app/mcp_config.json
|
|
217
217
|
```
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "github-agent"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.4"
|
|
8
8
|
readme = "README.md"
|
|
9
9
|
description = "GitHub Agent for MCP"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -18,8 +18,8 @@ classifiers = [
|
|
|
18
18
|
"Programming Language :: Python :: 3",
|
|
19
19
|
]
|
|
20
20
|
dependencies = [
|
|
21
|
-
"pydantic-ai-slim[fastmcp,openai,anthropic,google,huggingface,a2a,ag-ui,web]>=1.
|
|
22
|
-
"pydantic-ai-skills",
|
|
21
|
+
"pydantic-ai-slim[fastmcp,openai,anthropic,groq,mistral,google,huggingface,a2a,ag-ui,web]>=1.58.0",
|
|
22
|
+
"pydantic-ai-skills>=v0.4.0",
|
|
23
23
|
"fastapi>=0.128.0",
|
|
24
24
|
"fastmcp",
|
|
25
25
|
"uvicorn",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|