github-agent 0.2.4__tar.gz → 0.2.6__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.4 → github_agent-0.2.6}/PKG-INFO +2 -2
- {github_agent-0.2.4 → github_agent-0.2.6}/README.md +1 -1
- {github_agent-0.2.4 → github_agent-0.2.6}/github_agent/github_agent.py +27 -24
- {github_agent-0.2.4 → github_agent-0.2.6}/github_agent/utils.py +2 -22
- {github_agent-0.2.4 → github_agent-0.2.6}/github_agent.egg-info/PKG-INFO +2 -2
- {github_agent-0.2.4 → github_agent-0.2.6}/pyproject.toml +1 -1
- {github_agent-0.2.4 → github_agent-0.2.6}/LICENSE +0 -0
- {github_agent-0.2.4 → github_agent-0.2.6}/github_agent/__init__.py +0 -0
- {github_agent-0.2.4 → github_agent-0.2.6}/github_agent.egg-info/SOURCES.txt +0 -0
- {github_agent-0.2.4 → github_agent-0.2.6}/github_agent.egg-info/dependency_links.txt +0 -0
- {github_agent-0.2.4 → github_agent-0.2.6}/github_agent.egg-info/entry_points.txt +0 -0
- {github_agent-0.2.4 → github_agent-0.2.6}/github_agent.egg-info/requires.txt +0 -0
- {github_agent-0.2.4 → github_agent-0.2.6}/github_agent.egg-info/top_level.txt +0 -0
- {github_agent-0.2.4 → github_agent-0.2.6}/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.6
|
|
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.6*
|
|
47
47
|
|
|
48
48
|
## Overview
|
|
49
49
|
|
|
@@ -7,6 +7,7 @@ import os
|
|
|
7
7
|
import argparse
|
|
8
8
|
import logging
|
|
9
9
|
import uvicorn
|
|
10
|
+
import httpx
|
|
10
11
|
from typing import Optional, Any
|
|
11
12
|
from contextlib import asynccontextmanager
|
|
12
13
|
|
|
@@ -38,7 +39,7 @@ from pydantic import ValidationError
|
|
|
38
39
|
from pydantic_ai.ui import SSE_CONTENT_TYPE
|
|
39
40
|
from pydantic_ai.ui.ag_ui import AGUIAdapter
|
|
40
41
|
|
|
41
|
-
__version__ = "0.2.
|
|
42
|
+
__version__ = "0.2.6"
|
|
42
43
|
|
|
43
44
|
logging.basicConfig(
|
|
44
45
|
level=logging.INFO,
|
|
@@ -63,7 +64,6 @@ DEFAULT_SKILLS_DIRECTORY = os.getenv("SKILLS_DIRECTORY", get_skills_path())
|
|
|
63
64
|
DEFAULT_ENABLE_WEB_UI = to_boolean(os.getenv("ENABLE_WEB_UI", "False"))
|
|
64
65
|
DEFAULT_SSL_VERIFY = to_boolean(os.getenv("SSL_VERIFY", "True"))
|
|
65
66
|
|
|
66
|
-
# Model Settings
|
|
67
67
|
DEFAULT_MAX_TOKENS = to_integer(os.getenv("MAX_TOKENS", "16384"))
|
|
68
68
|
DEFAULT_TEMPERATURE = to_float(os.getenv("TEMPERATURE", "0.7"))
|
|
69
69
|
DEFAULT_TOP_P = to_float(os.getenv("TOP_P", "1.0"))
|
|
@@ -83,9 +83,6 @@ AGENT_DESCRIPTION = (
|
|
|
83
83
|
"A multi-agent system for interacting with GitHub via delegated specialists."
|
|
84
84
|
)
|
|
85
85
|
|
|
86
|
-
# -------------------------------------------------------------------------
|
|
87
|
-
# 1. System Prompts
|
|
88
|
-
# -------------------------------------------------------------------------
|
|
89
86
|
|
|
90
87
|
SUPERVISOR_SYSTEM_PROMPT = os.environ.get(
|
|
91
88
|
"SUPERVISOR_SYSTEM_PROMPT",
|
|
@@ -264,16 +261,12 @@ SUPPORT_DOCS_AGENT_PROMPT = os.environ.get(
|
|
|
264
261
|
),
|
|
265
262
|
)
|
|
266
263
|
|
|
267
|
-
# -------------------------------------------------------------------------
|
|
268
|
-
# 2. Agent Creation Logic
|
|
269
|
-
# -------------------------------------------------------------------------
|
|
270
|
-
|
|
271
264
|
|
|
272
265
|
def create_agent(
|
|
273
266
|
provider: str = DEFAULT_PROVIDER,
|
|
274
267
|
model_id: str = DEFAULT_MODEL_ID,
|
|
275
|
-
base_url: Optional[str] =
|
|
276
|
-
api_key: Optional[str] =
|
|
268
|
+
base_url: Optional[str] = DEFAULT_LLM_BASE_URL,
|
|
269
|
+
api_key: Optional[str] = DEFAULT_LLM_API_KEY,
|
|
277
270
|
mcp_url: str = DEFAULT_MCP_URL,
|
|
278
271
|
mcp_config: str = DEFAULT_MCP_CONFIG,
|
|
279
272
|
skills_directory: Optional[str] = DEFAULT_SKILLS_DIRECTORY,
|
|
@@ -306,25 +299,29 @@ def create_agent(
|
|
|
306
299
|
extra_body=DEFAULT_EXTRA_BODY,
|
|
307
300
|
)
|
|
308
301
|
|
|
309
|
-
# Load master toolsets
|
|
310
302
|
agent_toolsets = []
|
|
311
303
|
if mcp_url:
|
|
312
304
|
if "sse" in mcp_url.lower():
|
|
313
|
-
server = MCPServerSSE(
|
|
305
|
+
server = MCPServerSSE(
|
|
306
|
+
mcp_url, http_client=httpx.AsyncClient(verify=ssl_verify)
|
|
307
|
+
)
|
|
314
308
|
else:
|
|
315
|
-
server = MCPServerStreamableHTTP(
|
|
309
|
+
server = MCPServerStreamableHTTP(
|
|
310
|
+
mcp_url, http_client=httpx.AsyncClient(verify=ssl_verify)
|
|
311
|
+
)
|
|
316
312
|
agent_toolsets.append(server)
|
|
317
313
|
logger.info(f"Connected to MCP Server: {mcp_url}")
|
|
318
314
|
elif mcp_config:
|
|
319
315
|
mcp_toolset = load_mcp_servers(mcp_config)
|
|
316
|
+
for server in mcp_toolset:
|
|
317
|
+
if hasattr(server, "http_client"):
|
|
318
|
+
server.http_client = httpx.AsyncClient(verify=ssl_verify)
|
|
320
319
|
agent_toolsets.extend(mcp_toolset)
|
|
321
320
|
logger.info(f"Connected to MCP Config JSON: {mcp_toolset}")
|
|
322
321
|
|
|
323
322
|
if skills_directory and os.path.exists(skills_directory):
|
|
324
323
|
agent_toolsets.append(SkillsToolset(directories=[str(skills_directory)]))
|
|
325
324
|
|
|
326
|
-
# Define Tag -> Prompt map
|
|
327
|
-
# Key is the MCP Tool Tag (or set of tags), Value is (SystemPrompt, AgentName)
|
|
328
325
|
agent_defs = {
|
|
329
326
|
"person": (CONTEXT_AGENT_PROMPT, "GitHub_Context_Agent"),
|
|
330
327
|
"workflow": (ACTIONS_AGENT_PROMPT, "GitHub_Actions_Agent"),
|
|
@@ -383,7 +380,6 @@ def create_agent(
|
|
|
383
380
|
)
|
|
384
381
|
child_agents[tag] = agent
|
|
385
382
|
|
|
386
|
-
# Create Supervisor
|
|
387
383
|
supervisor = Agent(
|
|
388
384
|
name=AGENT_NAME,
|
|
389
385
|
system_prompt=SUPERVISOR_SYSTEM_PROMPT,
|
|
@@ -392,9 +388,6 @@ def create_agent(
|
|
|
392
388
|
deps_type=Any,
|
|
393
389
|
)
|
|
394
390
|
|
|
395
|
-
# Define delegation tools
|
|
396
|
-
# We define these explicitly to give the Supervisor clear, typed tools.
|
|
397
|
-
|
|
398
391
|
@supervisor.tool
|
|
399
392
|
async def assign_task_to_context_agent(ctx: RunContext[Any], task: str) -> str:
|
|
400
393
|
"""Assign a task related to user context and general GitHub status to the Context Agent."""
|
|
@@ -570,8 +563,8 @@ def create_agent(
|
|
|
570
563
|
def create_agent_server(
|
|
571
564
|
provider: str = DEFAULT_PROVIDER,
|
|
572
565
|
model_id: str = DEFAULT_MODEL_ID,
|
|
573
|
-
base_url: Optional[str] =
|
|
574
|
-
api_key: Optional[str] =
|
|
566
|
+
base_url: Optional[str] = DEFAULT_LLM_BASE_URL,
|
|
567
|
+
api_key: Optional[str] = DEFAULT_LLM_API_KEY,
|
|
575
568
|
mcp_url: str = DEFAULT_MCP_URL,
|
|
576
569
|
mcp_config: str = DEFAULT_MCP_CONFIG,
|
|
577
570
|
skills_directory: Optional[str] = DEFAULT_SKILLS_DIRECTORY,
|
|
@@ -582,7 +575,12 @@ def create_agent_server(
|
|
|
582
575
|
ssl_verify: bool = DEFAULT_SSL_VERIFY,
|
|
583
576
|
):
|
|
584
577
|
print(
|
|
585
|
-
f"Starting {AGENT_NAME}
|
|
578
|
+
f"Starting {AGENT_NAME}:"
|
|
579
|
+
f"\tprovider={provider}"
|
|
580
|
+
f"\tmodel={model_id}"
|
|
581
|
+
f"\tbase_url={base_url}"
|
|
582
|
+
f"\tmcp={mcp_url} | {mcp_config}"
|
|
583
|
+
f"\tssl_verify={ssl_verify}"
|
|
586
584
|
)
|
|
587
585
|
agent = create_agent(
|
|
588
586
|
provider=provider,
|
|
@@ -651,7 +649,6 @@ def create_agent_server(
|
|
|
651
649
|
status_code=422,
|
|
652
650
|
)
|
|
653
651
|
|
|
654
|
-
# Prune large messages from history
|
|
655
652
|
if hasattr(run_input, "messages"):
|
|
656
653
|
run_input.messages = prune_large_messages(run_input.messages)
|
|
657
654
|
|
|
@@ -726,6 +723,12 @@ def agent_server():
|
|
|
726
723
|
default=DEFAULT_ENABLE_WEB_UI,
|
|
727
724
|
help="Enable Pydantic AI Web UI",
|
|
728
725
|
)
|
|
726
|
+
|
|
727
|
+
parser.add_argument(
|
|
728
|
+
"--insecure",
|
|
729
|
+
action="store_true",
|
|
730
|
+
help="Disable SSL verification for LLM requests (Use with caution)",
|
|
731
|
+
)
|
|
729
732
|
parser.add_argument("--help", action="store_true", help="Show usage")
|
|
730
733
|
|
|
731
734
|
args = parser.parse_args()
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
|
|
4
4
|
import os
|
|
5
5
|
|
|
6
|
-
# Try importing specific clients/providers, but don't fail if variables are missing
|
|
7
6
|
try:
|
|
8
7
|
|
|
9
8
|
from openai import AsyncOpenAI
|
|
@@ -128,22 +127,17 @@ def prune_large_messages(messages: list[Any], max_length: int = 5000) -> list[An
|
|
|
128
127
|
f"... {content[-200:]}"
|
|
129
128
|
)
|
|
130
129
|
|
|
131
|
-
# Replace content
|
|
132
130
|
if isinstance(msg, dict):
|
|
133
131
|
msg["content"] = summary
|
|
134
132
|
pruned_messages.append(msg)
|
|
135
133
|
elif hasattr(msg, "content"):
|
|
136
|
-
# Try to create a copy or modify in place if mutable
|
|
137
|
-
# If it's a Pydantic model it might be immutable or require copy
|
|
138
134
|
try:
|
|
139
|
-
# Attempt shallow copy with update
|
|
140
135
|
from copy import copy
|
|
141
136
|
|
|
142
137
|
new_msg = copy(msg)
|
|
143
138
|
new_msg.content = summary
|
|
144
139
|
pruned_messages.append(new_msg)
|
|
145
140
|
except Exception:
|
|
146
|
-
# Fallback: keep original if we can't modify
|
|
147
141
|
pruned_messages.append(msg)
|
|
148
142
|
else:
|
|
149
143
|
pruned_messages.append(msg)
|
|
@@ -218,7 +212,6 @@ def load_skills_from_directory(directory: str) -> List[Skill]:
|
|
|
218
212
|
if skill_file.exists():
|
|
219
213
|
try:
|
|
220
214
|
with open(skill_file, "r") as f:
|
|
221
|
-
# Extract frontmatter
|
|
222
215
|
content = f.read()
|
|
223
216
|
if content.startswith("---"):
|
|
224
217
|
_, frontmatter, _ = content.split("---", 2)
|
|
@@ -254,8 +247,8 @@ def get_http_client(ssl_verify: bool = True) -> httpx.AsyncClient | None:
|
|
|
254
247
|
def create_model(
|
|
255
248
|
provider: str,
|
|
256
249
|
model_id: str,
|
|
257
|
-
base_url: Optional[str]
|
|
258
|
-
api_key: Optional[str]
|
|
250
|
+
base_url: Optional[str],
|
|
251
|
+
api_key: Optional[str],
|
|
259
252
|
ssl_verify: bool = True,
|
|
260
253
|
):
|
|
261
254
|
"""
|
|
@@ -271,7 +264,6 @@ def create_model(
|
|
|
271
264
|
Returns:
|
|
272
265
|
A Pydantic AI Model instance
|
|
273
266
|
"""
|
|
274
|
-
# Create a custom HTTP client if SSL verification is disabled
|
|
275
267
|
http_client = None
|
|
276
268
|
if not ssl_verify:
|
|
277
269
|
http_client = httpx.AsyncClient(verify=False)
|
|
@@ -280,7 +272,6 @@ def create_model(
|
|
|
280
272
|
target_base_url = base_url
|
|
281
273
|
target_api_key = api_key
|
|
282
274
|
|
|
283
|
-
# If we have a custom client or specific settings, we might want to use the explicit provider object
|
|
284
275
|
if http_client and AsyncOpenAI and OpenAIProvider:
|
|
285
276
|
client = AsyncOpenAI(
|
|
286
277
|
api_key=target_api_key or os.environ.get("OPENAI_API_KEY"),
|
|
@@ -290,7 +281,6 @@ def create_model(
|
|
|
290
281
|
provider_instance = OpenAIProvider(openai_client=client)
|
|
291
282
|
return OpenAIChatModel(model_name=model_id, provider=provider_instance)
|
|
292
283
|
|
|
293
|
-
# Fallback to standard env vars
|
|
294
284
|
if target_base_url:
|
|
295
285
|
os.environ["OPENAI_BASE_URL"] = target_base_url
|
|
296
286
|
if target_api_key:
|
|
@@ -298,7 +288,6 @@ def create_model(
|
|
|
298
288
|
return OpenAIChatModel(model_name=model_id, provider="openai")
|
|
299
289
|
|
|
300
290
|
elif provider == "ollama":
|
|
301
|
-
# Ollama is OpenAI compatible
|
|
302
291
|
target_base_url = base_url or "http://localhost:11434/v1"
|
|
303
292
|
target_api_key = api_key or "ollama"
|
|
304
293
|
|
|
@@ -319,9 +308,6 @@ def create_model(
|
|
|
319
308
|
if api_key:
|
|
320
309
|
os.environ["ANTHROPIC_API_KEY"] = api_key
|
|
321
310
|
|
|
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
311
|
try:
|
|
326
312
|
if http_client and AsyncAnthropic and AnthropicProvider:
|
|
327
313
|
client = AsyncAnthropic(
|
|
@@ -338,7 +324,6 @@ def create_model(
|
|
|
338
324
|
elif provider == "google":
|
|
339
325
|
if api_key:
|
|
340
326
|
os.environ["GEMINI_API_KEY"] = api_key
|
|
341
|
-
# Google SSL disable is tricky with genai, skipping for now unless specifically requested/researched
|
|
342
327
|
return GoogleModel(model_name=model_id)
|
|
343
328
|
|
|
344
329
|
elif provider == "groq":
|
|
@@ -360,12 +345,7 @@ def create_model(
|
|
|
360
345
|
os.environ["MISTRAL_API_KEY"] = api_key
|
|
361
346
|
|
|
362
347
|
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
348
|
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
349
|
|
|
370
350
|
return MistralModel(model_name=model_id)
|
|
371
351
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: github-agent
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.6
|
|
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.6*
|
|
47
47
|
|
|
48
48
|
## Overview
|
|
49
49
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|