github-agent 0.2.0__tar.gz → 0.2.2__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.0 → github_agent-0.2.2}/PKG-INFO +5 -5
- {github_agent-0.2.0 → github_agent-0.2.2}/README.md +4 -4
- {github_agent-0.2.0 → github_agent-0.2.2}/github_agent/github_agent.py +38 -22
- {github_agent-0.2.0 → github_agent-0.2.2}/github_agent/utils.py +119 -8
- {github_agent-0.2.0 → github_agent-0.2.2}/github_agent.egg-info/PKG-INFO +5 -5
- {github_agent-0.2.0 → github_agent-0.2.2}/pyproject.toml +1 -1
- {github_agent-0.2.0 → github_agent-0.2.2}/LICENSE +0 -0
- {github_agent-0.2.0 → github_agent-0.2.2}/github_agent/__init__.py +0 -0
- {github_agent-0.2.0 → github_agent-0.2.2}/github_agent.egg-info/SOURCES.txt +0 -0
- {github_agent-0.2.0 → github_agent-0.2.2}/github_agent.egg-info/dependency_links.txt +0 -0
- {github_agent-0.2.0 → github_agent-0.2.2}/github_agent.egg-info/entry_points.txt +0 -0
- {github_agent-0.2.0 → github_agent-0.2.2}/github_agent.egg-info/requires.txt +0 -0
- {github_agent-0.2.0 → github_agent-0.2.2}/github_agent.egg-info/top_level.txt +0 -0
- {github_agent-0.2.0 → github_agent-0.2.2}/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.2
|
|
4
4
|
Summary: GitHub Agent for MCP
|
|
5
5
|
Author-email: Audel Rouhi <knucklessg1@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -43,7 +43,7 @@ Dynamic: license-file
|
|
|
43
43
|

|
|
44
44
|

|
|
45
45
|
|
|
46
|
-
*Version: 0.2.
|
|
46
|
+
*Version: 0.2.2*
|
|
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.2*
|
|
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.2"
|
|
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"))
|
|
@@ -261,7 +264,6 @@ SUPPORT_DOCS_AGENT_PROMPT = os.environ.get(
|
|
|
261
264
|
),
|
|
262
265
|
)
|
|
263
266
|
|
|
264
|
-
|
|
265
267
|
# -------------------------------------------------------------------------
|
|
266
268
|
# 2. Agent Creation Logic
|
|
267
269
|
# -------------------------------------------------------------------------
|
|
@@ -275,13 +277,20 @@ def create_agent(
|
|
|
275
277
|
mcp_url: str = DEFAULT_MCP_URL,
|
|
276
278
|
mcp_config: str = DEFAULT_MCP_CONFIG,
|
|
277
279
|
skills_directory: Optional[str] = DEFAULT_SKILLS_DIRECTORY,
|
|
280
|
+
ssl_verify: bool = DEFAULT_SSL_VERIFY,
|
|
278
281
|
) -> Agent:
|
|
279
282
|
"""
|
|
280
283
|
Creates the Supervisor Agent with sub-agents registered as tools.
|
|
281
284
|
"""
|
|
282
285
|
logger.info("Initializing Multi-Agent System for GitHub...")
|
|
283
286
|
|
|
284
|
-
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
|
+
)
|
|
285
294
|
settings = ModelSettings(
|
|
286
295
|
max_tokens=DEFAULT_MAX_TOKENS,
|
|
287
296
|
temperature=DEFAULT_TEMPERATURE,
|
|
@@ -298,21 +307,21 @@ def create_agent(
|
|
|
298
307
|
)
|
|
299
308
|
|
|
300
309
|
# Load master toolsets
|
|
301
|
-
|
|
302
|
-
if
|
|
303
|
-
mcp_toolset = load_mcp_servers(mcp_config)
|
|
304
|
-
master_toolsets.extend(mcp_toolset)
|
|
305
|
-
logger.info(f"Connected to MCP Config JSON: {mcp_toolset}")
|
|
306
|
-
elif mcp_url:
|
|
310
|
+
agent_toolsets = []
|
|
311
|
+
if mcp_url:
|
|
307
312
|
if "sse" in mcp_url.lower():
|
|
308
313
|
server = MCPServerSSE(mcp_url)
|
|
309
314
|
else:
|
|
310
315
|
server = MCPServerStreamableHTTP(mcp_url)
|
|
311
|
-
|
|
316
|
+
agent_toolsets.append(server)
|
|
312
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}")
|
|
313
322
|
|
|
314
323
|
if skills_directory and os.path.exists(skills_directory):
|
|
315
|
-
|
|
324
|
+
agent_toolsets.append(SkillsToolset(directories=[str(skills_directory)]))
|
|
316
325
|
|
|
317
326
|
# Define Tag -> Prompt map
|
|
318
327
|
# Key is the MCP Tool Tag (or set of tags), Value is (SystemPrompt, AgentName)
|
|
@@ -353,7 +362,7 @@ def create_agent(
|
|
|
353
362
|
|
|
354
363
|
for tag, (system_prompt, agent_name) in agent_defs.items():
|
|
355
364
|
tag_toolsets = []
|
|
356
|
-
for ts in
|
|
365
|
+
for ts in agent_toolsets:
|
|
357
366
|
|
|
358
367
|
def filter_func(ctx, tool_def, t=tag):
|
|
359
368
|
return tool_in_tag(tool_def, t)
|
|
@@ -570,6 +579,7 @@ def create_agent_server(
|
|
|
570
579
|
host: Optional[str] = DEFAULT_HOST,
|
|
571
580
|
port: Optional[int] = DEFAULT_PORT,
|
|
572
581
|
enable_web_ui: bool = DEFAULT_ENABLE_WEB_UI,
|
|
582
|
+
ssl_verify: bool = DEFAULT_SSL_VERIFY,
|
|
573
583
|
):
|
|
574
584
|
print(
|
|
575
585
|
f"Starting {AGENT_NAME} with provider={provider}, model={model_id}, mcp={mcp_url} | {mcp_config}"
|
|
@@ -582,6 +592,7 @@ def create_agent_server(
|
|
|
582
592
|
mcp_url=mcp_url,
|
|
583
593
|
mcp_config=mcp_config,
|
|
584
594
|
skills_directory=skills_directory,
|
|
595
|
+
ssl_verify=ssl_verify,
|
|
585
596
|
)
|
|
586
597
|
|
|
587
598
|
if skills_directory and os.path.exists(skills_directory):
|
|
@@ -609,7 +620,11 @@ def create_agent_server(
|
|
|
609
620
|
|
|
610
621
|
@asynccontextmanager
|
|
611
622
|
async def lifespan(app: FastAPI):
|
|
612
|
-
|
|
623
|
+
if hasattr(a2a_app, "router") and hasattr(a2a_app.router, "lifespan_context"):
|
|
624
|
+
async with a2a_app.router.lifespan_context(a2a_app):
|
|
625
|
+
yield
|
|
626
|
+
else:
|
|
627
|
+
yield
|
|
613
628
|
|
|
614
629
|
app = FastAPI(
|
|
615
630
|
title=f"{AGENT_NAME} - A2A + AG-UI Server",
|
|
@@ -692,10 +707,10 @@ def agent_server():
|
|
|
692
707
|
parser.add_argument("--model-id", default=DEFAULT_MODEL_ID, help="LLM Model ID")
|
|
693
708
|
parser.add_argument(
|
|
694
709
|
"--base-url",
|
|
695
|
-
default=
|
|
710
|
+
default=DEFAULT_LLM_BASE_URL,
|
|
696
711
|
help="LLM Base URL (for OpenAI compatible providers)",
|
|
697
712
|
)
|
|
698
|
-
parser.add_argument("--api-key", default=
|
|
713
|
+
parser.add_argument("--api-key", default=DEFAULT_LLM_API_KEY, help="LLM API Key")
|
|
699
714
|
parser.add_argument("--mcp-url", default=DEFAULT_MCP_URL, help="MCP Server URL")
|
|
700
715
|
parser.add_argument(
|
|
701
716
|
"--mcp-config", default=DEFAULT_MCP_CONFIG, help="MCP Server Config"
|
|
@@ -750,6 +765,7 @@ def agent_server():
|
|
|
750
765
|
host=args.host,
|
|
751
766
|
port=args.port,
|
|
752
767
|
enable_web_ui=args.web,
|
|
768
|
+
ssl_verify=not args.insecure,
|
|
753
769
|
)
|
|
754
770
|
|
|
755
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,113 @@ 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
|
+
http_client = get_http_client(ssl_verify=ssl_verify)
|
|
262
|
+
|
|
220
263
|
if provider == "openai":
|
|
221
264
|
target_base_url = base_url
|
|
222
265
|
target_api_key = api_key
|
|
266
|
+
|
|
267
|
+
# If we have a custom client or specific settings, we might want to use the explicit provider object
|
|
268
|
+
if http_client and AsyncOpenAI and OpenAIProvider:
|
|
269
|
+
client = AsyncOpenAI(
|
|
270
|
+
api_key=target_api_key or os.environ.get("LLM_API_KEY"),
|
|
271
|
+
base_url=target_base_url or os.environ.get("LLM_BASE_URL"),
|
|
272
|
+
http_client=http_client,
|
|
273
|
+
)
|
|
274
|
+
provider_instance = OpenAIProvider(openai_client=client)
|
|
275
|
+
return OpenAIChatModel(model_name=model_id, provider=provider_instance)
|
|
276
|
+
|
|
277
|
+
# Fallback to standard env vars
|
|
223
278
|
if target_base_url:
|
|
224
|
-
os.environ["
|
|
279
|
+
os.environ["LLM_BASE_URL"] = target_base_url
|
|
225
280
|
if target_api_key:
|
|
226
|
-
os.environ["
|
|
281
|
+
os.environ["LLM_API_KEY"] = target_api_key
|
|
282
|
+
return OpenAIChatModel(model_name=model_id, provider="openai")
|
|
283
|
+
|
|
284
|
+
elif provider == "ollama":
|
|
285
|
+
# Ollama is OpenAI compatible
|
|
286
|
+
target_base_url = base_url or "http://localhost:11434/v1"
|
|
287
|
+
target_api_key = api_key or "ollama"
|
|
288
|
+
|
|
289
|
+
if http_client and AsyncOpenAI and OpenAIProvider:
|
|
290
|
+
client = AsyncOpenAI(
|
|
291
|
+
api_key=target_api_key,
|
|
292
|
+
base_url=target_base_url,
|
|
293
|
+
http_client=http_client,
|
|
294
|
+
)
|
|
295
|
+
provider_instance = OpenAIProvider(openai_client=client)
|
|
296
|
+
return OpenAIChatModel(model_name=model_id, provider=provider_instance)
|
|
297
|
+
|
|
298
|
+
os.environ["LLM_BASE_URL"] = target_base_url
|
|
299
|
+
os.environ["LLM_API_KEY"] = target_api_key
|
|
227
300
|
return OpenAIChatModel(model_name=model_id, provider="openai")
|
|
228
301
|
|
|
229
302
|
elif provider == "anthropic":
|
|
230
303
|
if api_key:
|
|
231
|
-
os.environ["
|
|
304
|
+
os.environ["LLM_API_KEY"] = api_key
|
|
305
|
+
|
|
306
|
+
try:
|
|
307
|
+
if http_client and AsyncAnthropic and AnthropicProvider:
|
|
308
|
+
client = AsyncAnthropic(
|
|
309
|
+
api_key=api_key or os.environ.get("LLM_API_KEY"),
|
|
310
|
+
http_client=http_client,
|
|
311
|
+
)
|
|
312
|
+
provider_instance = AnthropicProvider(anthropic_client=client)
|
|
313
|
+
return AnthropicModel(model_name=model_id, provider=provider_instance)
|
|
314
|
+
except ImportError:
|
|
315
|
+
pass
|
|
316
|
+
|
|
232
317
|
return AnthropicModel(model_name=model_id)
|
|
233
318
|
|
|
234
319
|
elif provider == "google":
|
|
320
|
+
# Google generic setup, skipping complex SSL for now as agreed
|
|
235
321
|
if api_key:
|
|
236
|
-
os.environ["
|
|
237
|
-
os.environ["GOOGLE_API_KEY"] = api_key
|
|
322
|
+
os.environ["LLM_API_KEY"] = api_key
|
|
238
323
|
return GoogleModel(model_name=model_id)
|
|
239
324
|
|
|
325
|
+
elif provider == "groq":
|
|
326
|
+
if api_key:
|
|
327
|
+
os.environ["LLM_API_KEY"] = api_key
|
|
328
|
+
|
|
329
|
+
if http_client and AsyncGroq and GroqProvider:
|
|
330
|
+
client = AsyncGroq(
|
|
331
|
+
api_key=api_key or os.environ.get("LLM_API_KEY"),
|
|
332
|
+
http_client=http_client,
|
|
333
|
+
)
|
|
334
|
+
provider_instance = GroqProvider(groq_client=client)
|
|
335
|
+
return GroqModel(model_name=model_id, provider=provider_instance)
|
|
336
|
+
|
|
337
|
+
return GroqModel(model_name=model_id)
|
|
338
|
+
|
|
339
|
+
elif provider == "mistral":
|
|
340
|
+
if api_key:
|
|
341
|
+
os.environ["LLM_API_KEY"] = api_key
|
|
342
|
+
|
|
343
|
+
if http_client and Mistral and MistralProvider:
|
|
344
|
+
# Assuming mistral_client argument for MistralProvider
|
|
345
|
+
# Ideally we would verify this, but we'll try standard pattern
|
|
346
|
+
pass
|
|
347
|
+
|
|
348
|
+
return MistralModel(model_name=model_id)
|
|
349
|
+
|
|
240
350
|
elif provider == "huggingface":
|
|
241
351
|
if api_key:
|
|
242
|
-
os.environ["
|
|
352
|
+
os.environ["LLM_API_KEY"] = api_key
|
|
243
353
|
return HuggingFaceModel(model_name=model_id)
|
|
354
|
+
|
|
244
355
|
return OpenAIChatModel(model_name=model_id, provider="openai")
|
|
245
356
|
|
|
246
357
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: github-agent
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: GitHub Agent for MCP
|
|
5
5
|
Author-email: Audel Rouhi <knucklessg1@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -43,7 +43,7 @@ Dynamic: license-file
|
|
|
43
43
|

|
|
44
44
|

|
|
45
45
|
|
|
46
|
-
*Version: 0.2.
|
|
46
|
+
*Version: 0.2.2*
|
|
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
|
```
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|