emdash-core 0.1.7__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.
Files changed (187) hide show
  1. emdash_core/__init__.py +3 -0
  2. emdash_core/agent/__init__.py +37 -0
  3. emdash_core/agent/agents.py +225 -0
  4. emdash_core/agent/code_reviewer.py +476 -0
  5. emdash_core/agent/compaction.py +143 -0
  6. emdash_core/agent/context_manager.py +140 -0
  7. emdash_core/agent/events.py +338 -0
  8. emdash_core/agent/handlers.py +224 -0
  9. emdash_core/agent/inprocess_subagent.py +377 -0
  10. emdash_core/agent/mcp/__init__.py +50 -0
  11. emdash_core/agent/mcp/client.py +346 -0
  12. emdash_core/agent/mcp/config.py +302 -0
  13. emdash_core/agent/mcp/manager.py +496 -0
  14. emdash_core/agent/mcp/tool_factory.py +213 -0
  15. emdash_core/agent/prompts/__init__.py +38 -0
  16. emdash_core/agent/prompts/main_agent.py +104 -0
  17. emdash_core/agent/prompts/subagents.py +131 -0
  18. emdash_core/agent/prompts/workflow.py +136 -0
  19. emdash_core/agent/providers/__init__.py +34 -0
  20. emdash_core/agent/providers/base.py +143 -0
  21. emdash_core/agent/providers/factory.py +80 -0
  22. emdash_core/agent/providers/models.py +220 -0
  23. emdash_core/agent/providers/openai_provider.py +463 -0
  24. emdash_core/agent/providers/transformers_provider.py +217 -0
  25. emdash_core/agent/research/__init__.py +81 -0
  26. emdash_core/agent/research/agent.py +143 -0
  27. emdash_core/agent/research/controller.py +254 -0
  28. emdash_core/agent/research/critic.py +428 -0
  29. emdash_core/agent/research/macros.py +469 -0
  30. emdash_core/agent/research/planner.py +449 -0
  31. emdash_core/agent/research/researcher.py +436 -0
  32. emdash_core/agent/research/state.py +523 -0
  33. emdash_core/agent/research/synthesizer.py +594 -0
  34. emdash_core/agent/reviewer_profile.py +475 -0
  35. emdash_core/agent/rules.py +123 -0
  36. emdash_core/agent/runner.py +601 -0
  37. emdash_core/agent/session.py +262 -0
  38. emdash_core/agent/spec_schema.py +66 -0
  39. emdash_core/agent/specification.py +479 -0
  40. emdash_core/agent/subagent.py +397 -0
  41. emdash_core/agent/subagent_prompts.py +13 -0
  42. emdash_core/agent/toolkit.py +482 -0
  43. emdash_core/agent/toolkits/__init__.py +64 -0
  44. emdash_core/agent/toolkits/base.py +96 -0
  45. emdash_core/agent/toolkits/explore.py +47 -0
  46. emdash_core/agent/toolkits/plan.py +55 -0
  47. emdash_core/agent/tools/__init__.py +141 -0
  48. emdash_core/agent/tools/analytics.py +436 -0
  49. emdash_core/agent/tools/base.py +131 -0
  50. emdash_core/agent/tools/coding.py +484 -0
  51. emdash_core/agent/tools/github_mcp.py +592 -0
  52. emdash_core/agent/tools/history.py +13 -0
  53. emdash_core/agent/tools/modes.py +153 -0
  54. emdash_core/agent/tools/plan.py +206 -0
  55. emdash_core/agent/tools/plan_write.py +135 -0
  56. emdash_core/agent/tools/search.py +412 -0
  57. emdash_core/agent/tools/spec.py +341 -0
  58. emdash_core/agent/tools/task.py +262 -0
  59. emdash_core/agent/tools/task_output.py +204 -0
  60. emdash_core/agent/tools/tasks.py +454 -0
  61. emdash_core/agent/tools/traversal.py +588 -0
  62. emdash_core/agent/tools/web.py +179 -0
  63. emdash_core/analytics/__init__.py +5 -0
  64. emdash_core/analytics/engine.py +1286 -0
  65. emdash_core/api/__init__.py +5 -0
  66. emdash_core/api/agent.py +308 -0
  67. emdash_core/api/agents.py +154 -0
  68. emdash_core/api/analyze.py +264 -0
  69. emdash_core/api/auth.py +173 -0
  70. emdash_core/api/context.py +77 -0
  71. emdash_core/api/db.py +121 -0
  72. emdash_core/api/embed.py +131 -0
  73. emdash_core/api/feature.py +143 -0
  74. emdash_core/api/health.py +93 -0
  75. emdash_core/api/index.py +162 -0
  76. emdash_core/api/plan.py +110 -0
  77. emdash_core/api/projectmd.py +210 -0
  78. emdash_core/api/query.py +320 -0
  79. emdash_core/api/research.py +122 -0
  80. emdash_core/api/review.py +161 -0
  81. emdash_core/api/router.py +76 -0
  82. emdash_core/api/rules.py +116 -0
  83. emdash_core/api/search.py +119 -0
  84. emdash_core/api/spec.py +99 -0
  85. emdash_core/api/swarm.py +223 -0
  86. emdash_core/api/tasks.py +109 -0
  87. emdash_core/api/team.py +120 -0
  88. emdash_core/auth/__init__.py +17 -0
  89. emdash_core/auth/github.py +389 -0
  90. emdash_core/config.py +74 -0
  91. emdash_core/context/__init__.py +52 -0
  92. emdash_core/context/models.py +50 -0
  93. emdash_core/context/providers/__init__.py +11 -0
  94. emdash_core/context/providers/base.py +74 -0
  95. emdash_core/context/providers/explored_areas.py +183 -0
  96. emdash_core/context/providers/touched_areas.py +360 -0
  97. emdash_core/context/registry.py +73 -0
  98. emdash_core/context/reranker.py +199 -0
  99. emdash_core/context/service.py +260 -0
  100. emdash_core/context/session.py +352 -0
  101. emdash_core/core/__init__.py +104 -0
  102. emdash_core/core/config.py +454 -0
  103. emdash_core/core/exceptions.py +55 -0
  104. emdash_core/core/models.py +265 -0
  105. emdash_core/core/review_config.py +57 -0
  106. emdash_core/db/__init__.py +67 -0
  107. emdash_core/db/auth.py +134 -0
  108. emdash_core/db/models.py +91 -0
  109. emdash_core/db/provider.py +222 -0
  110. emdash_core/db/providers/__init__.py +5 -0
  111. emdash_core/db/providers/supabase.py +452 -0
  112. emdash_core/embeddings/__init__.py +24 -0
  113. emdash_core/embeddings/indexer.py +534 -0
  114. emdash_core/embeddings/models.py +192 -0
  115. emdash_core/embeddings/providers/__init__.py +7 -0
  116. emdash_core/embeddings/providers/base.py +112 -0
  117. emdash_core/embeddings/providers/fireworks.py +141 -0
  118. emdash_core/embeddings/providers/openai.py +104 -0
  119. emdash_core/embeddings/registry.py +146 -0
  120. emdash_core/embeddings/service.py +215 -0
  121. emdash_core/graph/__init__.py +26 -0
  122. emdash_core/graph/builder.py +134 -0
  123. emdash_core/graph/connection.py +692 -0
  124. emdash_core/graph/schema.py +416 -0
  125. emdash_core/graph/writer.py +667 -0
  126. emdash_core/ingestion/__init__.py +7 -0
  127. emdash_core/ingestion/change_detector.py +150 -0
  128. emdash_core/ingestion/git/__init__.py +5 -0
  129. emdash_core/ingestion/git/commit_analyzer.py +196 -0
  130. emdash_core/ingestion/github/__init__.py +6 -0
  131. emdash_core/ingestion/github/pr_fetcher.py +296 -0
  132. emdash_core/ingestion/github/task_extractor.py +100 -0
  133. emdash_core/ingestion/orchestrator.py +540 -0
  134. emdash_core/ingestion/parsers/__init__.py +10 -0
  135. emdash_core/ingestion/parsers/base_parser.py +66 -0
  136. emdash_core/ingestion/parsers/call_graph_builder.py +121 -0
  137. emdash_core/ingestion/parsers/class_extractor.py +154 -0
  138. emdash_core/ingestion/parsers/function_extractor.py +202 -0
  139. emdash_core/ingestion/parsers/import_analyzer.py +119 -0
  140. emdash_core/ingestion/parsers/python_parser.py +123 -0
  141. emdash_core/ingestion/parsers/registry.py +72 -0
  142. emdash_core/ingestion/parsers/ts_ast_parser.js +313 -0
  143. emdash_core/ingestion/parsers/typescript_parser.py +278 -0
  144. emdash_core/ingestion/repository.py +346 -0
  145. emdash_core/models/__init__.py +38 -0
  146. emdash_core/models/agent.py +68 -0
  147. emdash_core/models/index.py +77 -0
  148. emdash_core/models/query.py +113 -0
  149. emdash_core/planning/__init__.py +7 -0
  150. emdash_core/planning/agent_api.py +413 -0
  151. emdash_core/planning/context_builder.py +265 -0
  152. emdash_core/planning/feature_context.py +232 -0
  153. emdash_core/planning/feature_expander.py +646 -0
  154. emdash_core/planning/llm_explainer.py +198 -0
  155. emdash_core/planning/similarity.py +509 -0
  156. emdash_core/planning/team_focus.py +821 -0
  157. emdash_core/server.py +153 -0
  158. emdash_core/sse/__init__.py +5 -0
  159. emdash_core/sse/stream.py +196 -0
  160. emdash_core/swarm/__init__.py +17 -0
  161. emdash_core/swarm/merge_agent.py +383 -0
  162. emdash_core/swarm/session_manager.py +274 -0
  163. emdash_core/swarm/swarm_runner.py +226 -0
  164. emdash_core/swarm/task_definition.py +137 -0
  165. emdash_core/swarm/worker_spawner.py +319 -0
  166. emdash_core/swarm/worktree_manager.py +278 -0
  167. emdash_core/templates/__init__.py +10 -0
  168. emdash_core/templates/defaults/agent-builder.md.template +82 -0
  169. emdash_core/templates/defaults/focus.md.template +115 -0
  170. emdash_core/templates/defaults/pr-review-enhanced.md.template +309 -0
  171. emdash_core/templates/defaults/pr-review.md.template +80 -0
  172. emdash_core/templates/defaults/project.md.template +85 -0
  173. emdash_core/templates/defaults/research_critic.md.template +112 -0
  174. emdash_core/templates/defaults/research_planner.md.template +85 -0
  175. emdash_core/templates/defaults/research_synthesizer.md.template +128 -0
  176. emdash_core/templates/defaults/reviewer.md.template +81 -0
  177. emdash_core/templates/defaults/spec.md.template +41 -0
  178. emdash_core/templates/defaults/tasks.md.template +78 -0
  179. emdash_core/templates/loader.py +296 -0
  180. emdash_core/utils/__init__.py +45 -0
  181. emdash_core/utils/git.py +84 -0
  182. emdash_core/utils/image.py +502 -0
  183. emdash_core/utils/logger.py +51 -0
  184. emdash_core-0.1.7.dist-info/METADATA +35 -0
  185. emdash_core-0.1.7.dist-info/RECORD +187 -0
  186. emdash_core-0.1.7.dist-info/WHEEL +4 -0
  187. emdash_core-0.1.7.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,592 @@
1
+ """GitHub MCP tools for live GitHub integration.
2
+
3
+ These tools use the GitHub MCP server to provide real-time
4
+ GitHub functionality including code search, PR analysis, and more.
5
+ """
6
+
7
+ import json
8
+ from typing import Any, Optional
9
+
10
+ from .base import BaseTool, ToolResult, ToolCategory
11
+ from ...utils.logger import log
12
+
13
+
14
+ class MCPBaseTool(BaseTool):
15
+ """Base class for MCP-backed tools."""
16
+
17
+ category = ToolCategory.HISTORY
18
+
19
+ def _get_mcp_client(self):
20
+ """Get the MCP client, starting if needed.
21
+
22
+ Returns:
23
+ GitHubMCPClient instance or None
24
+ """
25
+ try:
26
+ from ..mcp.client import GitHubMCPClient
27
+
28
+ client = GitHubMCPClient()
29
+ if not client.is_running:
30
+ client.start()
31
+ return client
32
+ except Exception as e:
33
+ log.warning(f"Failed to get MCP client: {e}")
34
+ return None
35
+
36
+ def _call_mcp_tool(
37
+ self,
38
+ tool_name: str,
39
+ arguments: dict,
40
+ ) -> ToolResult:
41
+ """Call an MCP tool and return result.
42
+
43
+ Args:
44
+ tool_name: MCP tool name
45
+ arguments: Tool arguments
46
+
47
+ Returns:
48
+ ToolResult
49
+ """
50
+ client = self._get_mcp_client()
51
+ if not client:
52
+ return ToolResult.error_result(
53
+ "GitHub MCP not available",
54
+ suggestions=["Check GITHUB_TOKEN is set", "Install github-mcp-server"],
55
+ )
56
+
57
+ try:
58
+ response = client.call_tool(tool_name, arguments)
59
+
60
+ if response.is_error:
61
+ return ToolResult.error_result(response.get_text())
62
+
63
+ # Parse response content
64
+ result_data = {"raw": response.get_text()}
65
+
66
+ # Try to parse as JSON
67
+ for item in response.content:
68
+ if item.get("type") == "text":
69
+ try:
70
+ parsed = json.loads(item.get("text", ""))
71
+ if isinstance(parsed, dict):
72
+ result_data.update(parsed)
73
+ elif isinstance(parsed, list):
74
+ result_data["results"] = parsed
75
+ except json.JSONDecodeError:
76
+ pass
77
+
78
+ return ToolResult.success_result(data=result_data)
79
+
80
+ except Exception as e:
81
+ log.exception(f"MCP tool call failed: {tool_name}")
82
+ return ToolResult.error_result(f"MCP call failed: {str(e)}")
83
+
84
+
85
+ class GitHubSearchCodeTool(MCPBaseTool):
86
+ """Search code on GitHub."""
87
+
88
+ name = "github_search_code"
89
+ description = """Search for code across GitHub repositories.
90
+ Finds code matching a query, useful for finding implementations,
91
+ patterns, or usage examples."""
92
+
93
+ def execute(
94
+ self,
95
+ query: str,
96
+ repo: Optional[str] = None,
97
+ language: Optional[str] = None,
98
+ per_page: int = 10,
99
+ ) -> ToolResult:
100
+ """Search GitHub code.
101
+
102
+ Args:
103
+ query: Search query
104
+ repo: Optional repo filter (owner/repo)
105
+ language: Optional language filter
106
+ per_page: Results per page
107
+
108
+ Returns:
109
+ ToolResult with code matches
110
+ """
111
+ full_query = query
112
+ if repo:
113
+ full_query += f" repo:{repo}"
114
+ if language:
115
+ full_query += f" language:{language}"
116
+
117
+ return self._call_mcp_tool("search_code", {
118
+ "query": full_query,
119
+ "per_page": per_page,
120
+ })
121
+
122
+ def get_schema(self) -> dict:
123
+ """Get OpenAI function schema."""
124
+ return self._make_schema(
125
+ properties={
126
+ "query": {
127
+ "type": "string",
128
+ "description": "Search query for code",
129
+ },
130
+ "repo": {
131
+ "type": "string",
132
+ "description": "Repository filter (owner/repo)",
133
+ },
134
+ "language": {
135
+ "type": "string",
136
+ "description": "Language filter",
137
+ },
138
+ "per_page": {
139
+ "type": "integer",
140
+ "description": "Results per page",
141
+ "default": 10,
142
+ },
143
+ },
144
+ required=["query"],
145
+ )
146
+
147
+
148
+ class GitHubGetFileContentTool(MCPBaseTool):
149
+ """Get file content from GitHub."""
150
+
151
+ name = "github_get_file_content"
152
+ description = """Get the content of a file from a GitHub repository.
153
+ Retrieves the actual file content for analysis."""
154
+
155
+ def execute(
156
+ self,
157
+ owner: str,
158
+ repo: str,
159
+ path: str,
160
+ ref: Optional[str] = None,
161
+ ) -> ToolResult:
162
+ """Get file content.
163
+
164
+ Args:
165
+ owner: Repository owner
166
+ repo: Repository name
167
+ path: File path
168
+ ref: Optional git ref (branch, tag, commit)
169
+
170
+ Returns:
171
+ ToolResult with file content
172
+ """
173
+ args = {"owner": owner, "repo": repo, "path": path}
174
+ if ref:
175
+ args["ref"] = ref
176
+
177
+ return self._call_mcp_tool("get_file_contents", args)
178
+
179
+ def get_schema(self) -> dict:
180
+ """Get OpenAI function schema."""
181
+ return self._make_schema(
182
+ properties={
183
+ "owner": {
184
+ "type": "string",
185
+ "description": "Repository owner",
186
+ },
187
+ "repo": {
188
+ "type": "string",
189
+ "description": "Repository name",
190
+ },
191
+ "path": {
192
+ "type": "string",
193
+ "description": "Path to the file",
194
+ },
195
+ "ref": {
196
+ "type": "string",
197
+ "description": "Git reference (branch, tag, commit)",
198
+ },
199
+ },
200
+ required=["owner", "repo", "path"],
201
+ )
202
+
203
+
204
+ class GitHubPRDetailsTool(MCPBaseTool):
205
+ """Get detailed PR information."""
206
+
207
+ name = "github_pr_details"
208
+ description = """Get detailed information about a pull request.
209
+ Includes diff, comments, reviews, and status."""
210
+
211
+ def execute(
212
+ self,
213
+ owner: str,
214
+ repo: str,
215
+ pull_number: int,
216
+ ) -> ToolResult:
217
+ """Get PR details.
218
+
219
+ Args:
220
+ owner: Repository owner
221
+ repo: Repository name
222
+ pull_number: PR number
223
+
224
+ Returns:
225
+ ToolResult with PR details
226
+ """
227
+ return self._call_mcp_tool("get_pull_request", {
228
+ "owner": owner,
229
+ "repo": repo,
230
+ "pull_number": pull_number,
231
+ })
232
+
233
+ def get_schema(self) -> dict:
234
+ """Get OpenAI function schema."""
235
+ return self._make_schema(
236
+ properties={
237
+ "owner": {
238
+ "type": "string",
239
+ "description": "Repository owner",
240
+ },
241
+ "repo": {
242
+ "type": "string",
243
+ "description": "Repository name",
244
+ },
245
+ "pull_number": {
246
+ "type": "integer",
247
+ "description": "Pull request number",
248
+ },
249
+ },
250
+ required=["owner", "repo", "pull_number"],
251
+ )
252
+
253
+
254
+ class GitHubListPRsTool(MCPBaseTool):
255
+ """List pull requests."""
256
+
257
+ name = "github_list_prs"
258
+ description = """List pull requests for a repository.
259
+ Can filter by state (open, closed, all)."""
260
+
261
+ def execute(
262
+ self,
263
+ owner: str,
264
+ repo: str,
265
+ state: str = "open",
266
+ per_page: int = 10,
267
+ ) -> ToolResult:
268
+ """List PRs.
269
+
270
+ Args:
271
+ owner: Repository owner
272
+ repo: Repository name
273
+ state: PR state filter (open, closed, all)
274
+ per_page: Results per page
275
+
276
+ Returns:
277
+ ToolResult with PR list
278
+ """
279
+ return self._call_mcp_tool("list_pull_requests", {
280
+ "owner": owner,
281
+ "repo": repo,
282
+ "state": state,
283
+ "per_page": per_page,
284
+ })
285
+
286
+ def get_schema(self) -> dict:
287
+ """Get OpenAI function schema."""
288
+ return self._make_schema(
289
+ properties={
290
+ "owner": {
291
+ "type": "string",
292
+ "description": "Repository owner",
293
+ },
294
+ "repo": {
295
+ "type": "string",
296
+ "description": "Repository name",
297
+ },
298
+ "state": {
299
+ "type": "string",
300
+ "enum": ["open", "closed", "all"],
301
+ "description": "PR state filter",
302
+ "default": "open",
303
+ },
304
+ "per_page": {
305
+ "type": "integer",
306
+ "description": "Results per page",
307
+ "default": 10,
308
+ },
309
+ },
310
+ required=["owner", "repo"],
311
+ )
312
+
313
+
314
+ class GitHubSearchReposTool(MCPBaseTool):
315
+ """Search GitHub repositories."""
316
+
317
+ name = "github_search_repos"
318
+ description = """Search for repositories on GitHub.
319
+ Find repos by topic, name, or description."""
320
+
321
+ def execute(
322
+ self,
323
+ query: str,
324
+ per_page: int = 10,
325
+ ) -> ToolResult:
326
+ """Search repositories.
327
+
328
+ Args:
329
+ query: Search query
330
+ per_page: Results per page
331
+
332
+ Returns:
333
+ ToolResult with repo matches
334
+ """
335
+ return self._call_mcp_tool("search_repositories", {
336
+ "query": query,
337
+ "per_page": per_page,
338
+ })
339
+
340
+ def get_schema(self) -> dict:
341
+ """Get OpenAI function schema."""
342
+ return self._make_schema(
343
+ properties={
344
+ "query": {
345
+ "type": "string",
346
+ "description": "Search query",
347
+ },
348
+ "per_page": {
349
+ "type": "integer",
350
+ "description": "Results per page",
351
+ "default": 10,
352
+ },
353
+ },
354
+ required=["query"],
355
+ )
356
+
357
+
358
+ class GitHubSearchPRsTool(MCPBaseTool):
359
+ """Search pull requests on GitHub."""
360
+
361
+ name = "github_search_prs"
362
+ description = """Search for pull requests across GitHub.
363
+ Find PRs by title, body, or comments."""
364
+
365
+ def execute(
366
+ self,
367
+ query: str,
368
+ repo: Optional[str] = None,
369
+ state: Optional[str] = None,
370
+ per_page: int = 10,
371
+ ) -> ToolResult:
372
+ """Search PRs.
373
+
374
+ Args:
375
+ query: Search query
376
+ repo: Optional repo filter
377
+ state: Optional state filter
378
+ per_page: Results per page
379
+
380
+ Returns:
381
+ ToolResult with PR matches
382
+ """
383
+ full_query = query + " is:pr"
384
+ if repo:
385
+ full_query += f" repo:{repo}"
386
+ if state:
387
+ full_query += f" is:{state}"
388
+
389
+ return self._call_mcp_tool("search_issues", {
390
+ "query": full_query,
391
+ "per_page": per_page,
392
+ })
393
+
394
+ def get_schema(self) -> dict:
395
+ """Get OpenAI function schema."""
396
+ return self._make_schema(
397
+ properties={
398
+ "query": {
399
+ "type": "string",
400
+ "description": "Search query",
401
+ },
402
+ "repo": {
403
+ "type": "string",
404
+ "description": "Repository filter (owner/repo)",
405
+ },
406
+ "state": {
407
+ "type": "string",
408
+ "enum": ["open", "closed"],
409
+ "description": "PR state filter",
410
+ },
411
+ "per_page": {
412
+ "type": "integer",
413
+ "description": "Results per page",
414
+ "default": 10,
415
+ },
416
+ },
417
+ required=["query"],
418
+ )
419
+
420
+
421
+ class GitHubGetIssueTool(MCPBaseTool):
422
+ """Get issue details from GitHub."""
423
+
424
+ name = "github_get_issue"
425
+ description = """Get detailed information about an issue.
426
+ Includes body, comments, labels, and assignees."""
427
+
428
+ def execute(
429
+ self,
430
+ owner: str,
431
+ repo: str,
432
+ issue_number: int,
433
+ ) -> ToolResult:
434
+ """Get issue details.
435
+
436
+ Args:
437
+ owner: Repository owner
438
+ repo: Repository name
439
+ issue_number: Issue number
440
+
441
+ Returns:
442
+ ToolResult with issue details
443
+ """
444
+ return self._call_mcp_tool("get_issue", {
445
+ "owner": owner,
446
+ "repo": repo,
447
+ "issue_number": issue_number,
448
+ })
449
+
450
+ def get_schema(self) -> dict:
451
+ """Get OpenAI function schema."""
452
+ return self._make_schema(
453
+ properties={
454
+ "owner": {
455
+ "type": "string",
456
+ "description": "Repository owner",
457
+ },
458
+ "repo": {
459
+ "type": "string",
460
+ "description": "Repository name",
461
+ },
462
+ "issue_number": {
463
+ "type": "integer",
464
+ "description": "Issue number",
465
+ },
466
+ },
467
+ required=["owner", "repo", "issue_number"],
468
+ )
469
+
470
+
471
+ class GitHubViewRepoStructureTool(MCPBaseTool):
472
+ """View repository structure."""
473
+
474
+ name = "github_view_repo_structure"
475
+ description = """View the directory structure of a GitHub repository.
476
+ Shows files and folders in a tree format."""
477
+
478
+ def execute(
479
+ self,
480
+ owner: str,
481
+ repo: str,
482
+ path: str = "",
483
+ ref: Optional[str] = None,
484
+ ) -> ToolResult:
485
+ """View repo structure.
486
+
487
+ Args:
488
+ owner: Repository owner
489
+ repo: Repository name
490
+ path: Path within repo
491
+ ref: Git reference
492
+
493
+ Returns:
494
+ ToolResult with directory structure
495
+ """
496
+ args = {"owner": owner, "repo": repo}
497
+ if path:
498
+ args["path"] = path
499
+ if ref:
500
+ args["ref"] = ref
501
+
502
+ return self._call_mcp_tool("get_directory_contents", args)
503
+
504
+ def get_schema(self) -> dict:
505
+ """Get OpenAI function schema."""
506
+ return self._make_schema(
507
+ properties={
508
+ "owner": {
509
+ "type": "string",
510
+ "description": "Repository owner",
511
+ },
512
+ "repo": {
513
+ "type": "string",
514
+ "description": "Repository name",
515
+ },
516
+ "path": {
517
+ "type": "string",
518
+ "description": "Path within the repository",
519
+ "default": "",
520
+ },
521
+ "ref": {
522
+ "type": "string",
523
+ "description": "Git reference (branch, tag, commit)",
524
+ },
525
+ },
526
+ required=["owner", "repo"],
527
+ )
528
+
529
+
530
+ class GitHubCreateReviewTool(MCPBaseTool):
531
+ """Create a PR review."""
532
+
533
+ name = "github_create_review"
534
+ description = """Create a review on a pull request.
535
+ Can approve, request changes, or comment."""
536
+
537
+ def execute(
538
+ self,
539
+ owner: str,
540
+ repo: str,
541
+ pull_number: int,
542
+ event: str,
543
+ body: str,
544
+ ) -> ToolResult:
545
+ """Create a review.
546
+
547
+ Args:
548
+ owner: Repository owner
549
+ repo: Repository name
550
+ pull_number: PR number
551
+ event: Review event (APPROVE, REQUEST_CHANGES, COMMENT)
552
+ body: Review body
553
+
554
+ Returns:
555
+ ToolResult with review details
556
+ """
557
+ return self._call_mcp_tool("create_pull_request_review", {
558
+ "owner": owner,
559
+ "repo": repo,
560
+ "pull_number": pull_number,
561
+ "event": event,
562
+ "body": body,
563
+ })
564
+
565
+ def get_schema(self) -> dict:
566
+ """Get OpenAI function schema."""
567
+ return self._make_schema(
568
+ properties={
569
+ "owner": {
570
+ "type": "string",
571
+ "description": "Repository owner",
572
+ },
573
+ "repo": {
574
+ "type": "string",
575
+ "description": "Repository name",
576
+ },
577
+ "pull_number": {
578
+ "type": "integer",
579
+ "description": "Pull request number",
580
+ },
581
+ "event": {
582
+ "type": "string",
583
+ "enum": ["APPROVE", "REQUEST_CHANGES", "COMMENT"],
584
+ "description": "Review event type",
585
+ },
586
+ "body": {
587
+ "type": "string",
588
+ "description": "Review body/comment",
589
+ },
590
+ },
591
+ required=["owner", "repo", "pull_number", "event", "body"],
592
+ )
@@ -0,0 +1,13 @@
1
+ """History tools placeholder.
2
+
3
+ History tools have been moved to GitHub MCP for live GitHub integration.
4
+ Use the following GitHub MCP tools instead:
5
+
6
+ - github_list_prs: List pull requests
7
+ - github_pr_details: Get PR details with diff
8
+ - github_search_prs: Search PRs by keywords
9
+ - github_get_issue: Get issue details
10
+ """
11
+
12
+ # This file is intentionally minimal.
13
+ # All history functionality is now provided by GitHub MCP tools.