jarvis-ai-assistant 0.1.102__py3-none-any.whl → 0.1.104__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.

Potentially problematic release.


This version of jarvis-ai-assistant might be problematic. Click here for more details.

Files changed (55) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/agent.py +138 -117
  3. jarvis/jarvis_code_agent/code_agent.py +234 -0
  4. jarvis/{jarvis_coder → jarvis_code_agent}/file_select.py +19 -22
  5. jarvis/jarvis_code_agent/patch.py +120 -0
  6. jarvis/jarvis_code_agent/relevant_files.py +97 -0
  7. jarvis/jarvis_codebase/main.py +871 -0
  8. jarvis/jarvis_platform/main.py +5 -3
  9. jarvis/jarvis_rag/main.py +818 -0
  10. jarvis/jarvis_smart_shell/main.py +2 -2
  11. jarvis/models/ai8.py +3 -1
  12. jarvis/models/kimi.py +36 -30
  13. jarvis/models/ollama.py +17 -11
  14. jarvis/models/openai.py +15 -12
  15. jarvis/models/oyi.py +24 -7
  16. jarvis/models/registry.py +1 -25
  17. jarvis/tools/__init__.py +0 -6
  18. jarvis/tools/ask_codebase.py +96 -0
  19. jarvis/tools/ask_user.py +1 -9
  20. jarvis/tools/chdir.py +2 -37
  21. jarvis/tools/code_review.py +210 -0
  22. jarvis/tools/create_code_test_agent.py +115 -0
  23. jarvis/tools/create_ctags_agent.py +164 -0
  24. jarvis/tools/create_sub_agent.py +2 -2
  25. jarvis/tools/execute_shell.py +2 -2
  26. jarvis/tools/file_operation.py +2 -2
  27. jarvis/tools/find_in_codebase.py +78 -0
  28. jarvis/tools/git_commiter.py +68 -0
  29. jarvis/tools/methodology.py +3 -3
  30. jarvis/tools/rag.py +141 -0
  31. jarvis/tools/read_code.py +116 -0
  32. jarvis/tools/read_webpage.py +1 -1
  33. jarvis/tools/registry.py +47 -31
  34. jarvis/tools/search.py +8 -6
  35. jarvis/tools/select_code_files.py +4 -4
  36. jarvis/utils.py +375 -85
  37. {jarvis_ai_assistant-0.1.102.dist-info → jarvis_ai_assistant-0.1.104.dist-info}/METADATA +107 -32
  38. jarvis_ai_assistant-0.1.104.dist-info/RECORD +50 -0
  39. jarvis_ai_assistant-0.1.104.dist-info/entry_points.txt +11 -0
  40. jarvis/jarvis_code_agent/main.py +0 -200
  41. jarvis/jarvis_coder/git_utils.py +0 -123
  42. jarvis/jarvis_coder/patch_handler.py +0 -340
  43. jarvis/jarvis_github/main.py +0 -232
  44. jarvis/tools/create_code_sub_agent.py +0 -56
  45. jarvis/tools/execute_code_modification.py +0 -70
  46. jarvis/tools/find_files.py +0 -119
  47. jarvis/tools/generate_tool.py +0 -174
  48. jarvis/tools/thinker.py +0 -151
  49. jarvis_ai_assistant-0.1.102.dist-info/RECORD +0 -46
  50. jarvis_ai_assistant-0.1.102.dist-info/entry_points.txt +0 -6
  51. /jarvis/{jarvis_coder → jarvis_codebase}/__init__.py +0 -0
  52. /jarvis/{jarvis_github → jarvis_rag}/__init__.py +0 -0
  53. {jarvis_ai_assistant-0.1.102.dist-info → jarvis_ai_assistant-0.1.104.dist-info}/LICENSE +0 -0
  54. {jarvis_ai_assistant-0.1.102.dist-info → jarvis_ai_assistant-0.1.104.dist-info}/WHEEL +0 -0
  55. {jarvis_ai_assistant-0.1.102.dist-info → jarvis_ai_assistant-0.1.104.dist-info}/top_level.txt +0 -0
@@ -1,340 +0,0 @@
1
- import re
2
- import os
3
- from typing import List, Tuple, Dict
4
- import yaml
5
- from pathlib import Path
6
-
7
- from jarvis.jarvis_coder.git_utils import generate_commit_message, init_git_repo, save_edit_record
8
- from jarvis.models.base import BasePlatform
9
- from jarvis.models.registry import PlatformRegistry
10
- from jarvis.utils import OutputType, PrettyOutput, get_multiline_input, get_single_line_input, while_success
11
-
12
- class Patch:
13
- def __init__(self, start: int, end: int, new_code: str):
14
- self.start = start # Line number where patch starts (inclusive)
15
- self.end = end # Line number where patch ends (exclusive)
16
- self.new_code = new_code # New code to insert/replace
17
-
18
- class PatchHandler:
19
- def __init__(self):
20
- self.prompt_file = Path.home() / ".jarvis-coder-patch-prompt"
21
- self.additional_info = self._load_additional_info()
22
- self.root_dir = init_git_repo(os.getcwd())
23
- self.record_dir = os.path.join(self.root_dir, ".jarvis-coder", "record")
24
- if not os.path.exists(self.record_dir):
25
- os.makedirs(self.record_dir)
26
- def _load_additional_info(self) -> str:
27
- """Load saved additional info from prompt file"""
28
- if not self.prompt_file.exists():
29
- return ""
30
- try:
31
- with open(self.prompt_file, 'r') as f:
32
- data = yaml.safe_load(f)
33
- return data.get('additional_info', '') if data else ''
34
- except Exception as e:
35
- PrettyOutput.print(f"Failed to load additional info: {e}", OutputType.WARNING)
36
- return ""
37
-
38
- def _save_additional_info(self, info: str):
39
- """Save additional info to prompt file"""
40
- try:
41
- with open(self.prompt_file, 'w') as f:
42
- yaml.dump({'additional_info': info}, f)
43
- except Exception as e:
44
- PrettyOutput.print(f"Failed to save additional info: {e}", OutputType.WARNING)
45
-
46
- def _extract_patches(self, response: str) -> List[Patch]:
47
- """Extract patches from response with hexadecimal line numbers
48
-
49
- Args:
50
- response: Model response content
51
-
52
- Returns:
53
- List[Patch]: List of patches, each containing the line range and new code
54
- """
55
- fmt_pattern = r'<PATCH>\n\[([0-9a-f]+),([0-9a-f]+)\)\n(.*?\n)</PATCH>'
56
- ret = []
57
- for m in re.finditer(fmt_pattern, response, re.DOTALL):
58
- start = int(m.group(1), 16) # Convert hex to decimal
59
- end = int(m.group(2), 16)
60
- new_code = m.group(3)
61
- ret.append(Patch(start, end, new_code))
62
- return ret
63
-
64
- def _confirm_and_apply_changes(self, file_path: str) -> bool:
65
- """Confirm and apply changes"""
66
- os.system(f"git diff --cached {file_path}")
67
- confirm = get_single_line_input(f"Accept {file_path} changes? (y/n) [y]").lower() or "y"
68
- if confirm == "y":
69
- return True
70
- else:
71
- # Rollback changes
72
- os.system(f"git reset {file_path}")
73
- os.system(f"git checkout -- {file_path}")
74
- PrettyOutput.print(f"Changes to {file_path} have been rolled back", OutputType.WARNING)
75
- return False
76
-
77
-
78
-
79
- def _finalize_changes(self) -> None:
80
- """Complete changes and commit"""
81
- PrettyOutput.print("Modification confirmed, committing...", OutputType.INFO)
82
-
83
- # Add only modified files under git control
84
- os.system("git add -u")
85
-
86
- # Then get git diff
87
- git_diff = os.popen("git diff --cached").read()
88
-
89
- # Automatically generate commit information, pass in feature
90
- commit_message = generate_commit_message(git_diff)
91
-
92
- # Display and confirm commit information
93
- PrettyOutput.print(f"Automatically generated commit information: {commit_message}", OutputType.INFO)
94
- user_confirm = get_single_line_input("Use this commit information? (y/n) [y]").lower() or "y"
95
-
96
- if user_confirm.lower() != "y":
97
- commit_message = get_single_line_input("Please enter a new commit information")
98
-
99
- # No need to git add again, it has already been added
100
- os.system(f"git commit -m '{commit_message}'")
101
- save_edit_record(self.record_dir, commit_message, git_diff)
102
-
103
- def _revert_changes(self) -> None:
104
- """Revert all changes"""
105
- PrettyOutput.print("Modification cancelled, reverting changes", OutputType.INFO)
106
- os.system(f"git reset --hard")
107
- os.system(f"git clean -df")
108
-
109
- def _check_patches_overlap(self, patches: List[Patch]) -> bool:
110
- """Check if any patches overlap with each other
111
-
112
- Args:
113
- patches: List of patches to check
114
-
115
- Returns:
116
- bool: True if patches overlap, False otherwise
117
- """
118
- if not patches:
119
- return False
120
-
121
- # Sort patches by start line
122
- sorted_patches = sorted(patches, key=lambda x: x.start)
123
-
124
- # Check for overlaps
125
- for i in range(len(sorted_patches) - 1):
126
- current = sorted_patches[i]
127
- next_patch = sorted_patches[i + 1]
128
-
129
- if current.end > next_patch.start:
130
- PrettyOutput.print(
131
- f"Overlapping patches detected: [{current.start:04x},{current.end:04x}) and [{next_patch.start:04x},{next_patch.end:04x})",
132
- OutputType.WARNING
133
- )
134
- return True
135
-
136
- return False
137
-
138
- def apply_file_patch(self, file_path: str, patches: List[Patch]) -> bool:
139
- """Apply file patches using line numbers"""
140
- if not os.path.exists(file_path):
141
- base_dir = os.path.dirname(file_path)
142
- os.makedirs(base_dir, exist_ok=True)
143
- open(file_path, "w", encoding="utf-8").close()
144
-
145
- # Check for overlapping patches
146
- if self._check_patches_overlap(patches):
147
- PrettyOutput.print("Cannot apply overlapping patches", OutputType.ERROR)
148
- os.system(f"git reset {file_path}")
149
- os.system(f"git checkout -- {file_path}")
150
- return False
151
-
152
- with open(file_path, "r", encoding="utf-8") as f:
153
- lines = f.readlines()
154
-
155
- # Sort patches by start line in reverse order to apply from bottom to top
156
- patches.sort(key=lambda x: x.start, reverse=True)
157
-
158
- for i, patch in enumerate(patches):
159
- PrettyOutput.print(f"Applying patch {i+1}/{len(patches)} at lines [{patch.start},{patch.end})", OutputType.INFO)
160
-
161
- if patch.start > len(lines):
162
- PrettyOutput.print(f"Invalid patch: start line {patch.start} exceeds file length {len(lines)}", OutputType.WARNING)
163
- os.system(f"git reset {file_path}")
164
- os.system(f"git checkout -- {file_path}")
165
- return False
166
-
167
- if patch.new_code:
168
- new_lines = patch.new_code.splitlines(keepends=True)
169
- lines[patch.start:patch.end] = new_lines
170
- else:
171
- del lines[patch.start:patch.end]
172
-
173
- # Write modified content back to file
174
- with open(file_path, "w", encoding="utf-8") as f:
175
- f.writelines(lines)
176
-
177
- os.system(f"git add {file_path}")
178
- PrettyOutput.print(f"Successfully applied all patches to {file_path}", OutputType.SUCCESS)
179
- return True
180
-
181
-
182
- def retry_comfirm(self) -> Tuple[str, str]:
183
- choice = get_single_line_input("\nPlease choose an action: (1) Retry (2) Skip (3) Completely stop [1]: ") or "1"
184
- if choice == "2":
185
- return "skip", ""
186
- if choice == "3":
187
- return "break", ""
188
-
189
- feedback = get_multiline_input("Please enter additional information and requirements:")
190
- if feedback:
191
- save_prompt = get_single_line_input("Would you like to save this as general feedback for future patches? (y/n) [n]: ").lower() or "n"
192
- if save_prompt == "y":
193
- self._save_additional_info(feedback)
194
- PrettyOutput.print("Feedback saved for future use", OutputType.SUCCESS)
195
-
196
- return "continue", feedback
197
-
198
- def apply_patch(self, feature: str, structed_plan: Dict[str, str]) -> Tuple[bool, str]:
199
- """Apply patch (main entry)"""
200
- feedback = ""
201
- for file_path, current_plan in structed_plan.items():
202
- additional_info = self.additional_info # Initialize with saved info
203
- while True:
204
- if os.path.exists(file_path):
205
- # Read file and add line numbers
206
- lines = []
207
- with open(file_path, "r", encoding="utf-8") as f:
208
- for i, line in enumerate(f):
209
- lines.append(f"{i:04x}{line}") # Changed from i+1 to i for 0-based indexing
210
- content = "".join(lines)
211
- else:
212
- content = "<File does not exist, need to create>"
213
-
214
- prompt = """You are a senior software development expert who can generate code patches based on the complete modification plan, current original code file path, code content (with 4-digit hexadecimal line numbers), and current file's modification plan. The output format should be as follows:
215
-
216
- <PATCH>
217
- [start,end)
218
- new_code
219
- </PATCH>
220
-
221
- Example:
222
- <PATCH>
223
- [000c,000c)
224
- def new_function():
225
- pass
226
- </PATCH>
227
-
228
- means:
229
- Insert code BEFORE line 12:
230
- ```
231
- def new_function():
232
- pass
233
- ```
234
-
235
- Example 2:
236
- <PATCH>
237
- [0004,000b)
238
- aa
239
- bb
240
- cc
241
- </PATCH>
242
-
243
- means:
244
- Replace lines [4,11) with:
245
- ```
246
- aa
247
- bb
248
- cc
249
- ```
250
-
251
- Rules:
252
- 1. start and end are hexadecimal line numbers (e.g., 000a)
253
- 2. The patch will replace lines [start,end) with new_code (including start, excluding end)
254
- 3. If start equals end, new_code will be inserted BEFORE that line
255
- 4. If new_code is empty, lines [start,end) will be deleted
256
- 5. Multiple patches can be generated
257
- 6. Each line in the input file starts with its 4-digit hexadecimal line number (0-based)
258
- 7. Your new_code should NOT include line numbers
259
- 8. CRITICAL: Patches MUST NOT overlap - ensure each line is modified by at most one patch
260
- 9. Generate patches from bottom to top of the file
261
- 10. Ensure new_code maintains correct indentation and formatting
262
- 11. Each patch should modify no more than 20 lines
263
- 12. Include sufficient context in new_code to maintain code consistency
264
- 13. `[` and `)` must be included in the line range
265
- 14. Line numbers start from 0
266
- 15. Example of INVALID overlapping patches:
267
- <PATCH>
268
- [0001,0005)
269
- code1
270
- </PATCH>
271
- <PATCH>
272
- [0003,0007) # This overlaps with the previous patch
273
- code2
274
- </PATCH>
275
- """
276
-
277
- prompt += f"""# Original requirement: {feature}
278
- # Current file path: {file_path}
279
- # Current file content:
280
- <CONTENT>
281
- {content}
282
- </CONTENT>
283
- # Current file modification plan:
284
- {current_plan}
285
- { "# Additional information: " + additional_info if additional_info else "" }
286
- """
287
-
288
-
289
- PrettyOutput.print(f"Generating formatted patches for {file_path}...", OutputType.PROGRESS)
290
- response = PlatformRegistry.get_global_platform_registry().get_codegen_platform().chat_until_success(prompt)
291
- patches = self._extract_patches(response)
292
-
293
- if not patches or not self.apply_file_patch(file_path, patches) or not self._confirm_and_apply_changes(file_path):
294
- os.system(f"git reset {file_path}")
295
- os.system(f"git checkout -- {file_path}")
296
- PrettyOutput.print("Patch generation failed", OutputType.WARNING)
297
- act, msg = self.retry_comfirm()
298
- if act == "break":
299
- PrettyOutput.print("Terminate patch application", OutputType.WARNING)
300
- additional_info = get_multiline_input("Please enter your additional information or suggestions (press Enter to cancel):")
301
- return False, additional_info
302
- if act == "skip":
303
- PrettyOutput.print(f"Skip file {file_path}", OutputType.WARNING)
304
- feedback += f"Skip file {file_path}\n"
305
- feedback += "Reason: " + get_multiline_input("Please enter your reason:") + "\n"
306
- break
307
- else:
308
- additional_info += msg + "\n"
309
- continue
310
- else:
311
- self._finalize_changes()
312
- break
313
-
314
- return True, feedback
315
-
316
-
317
-
318
- def handle_patch_application(self, feature: str, structed_plan: Dict[str,str]) -> Tuple[bool, str]:
319
- """Process patch application process
320
-
321
- Args:
322
- related_files: Related files list
323
- feature: Feature description
324
- modification_plan: Modification plan
325
-
326
- Returns:
327
- bool: Whether patch application is successful
328
- """
329
- PrettyOutput.print("\nThe following modification plan will be applied:", OutputType.INFO)
330
- for file_path, patches_code in structed_plan.items():
331
- PrettyOutput.print(f"\nFile: {file_path}", OutputType.INFO)
332
- PrettyOutput.print(f"Modification plan: \n{patches_code}", OutputType.INFO)
333
- # 3. Apply patches
334
- success, additional_info = self.apply_patch(feature, structed_plan)
335
- if not success:
336
- os.system("git reset --hard")
337
- return False, additional_info
338
- # 6. Apply successfully, let user confirm changes
339
- PrettyOutput.print("\nPatches applied, please check the modification effect.", OutputType.SUCCESS)
340
- return True, "Modification applied successfully"
@@ -1,232 +0,0 @@
1
- import os
2
- import sys
3
- import argparse
4
- from typing import Dict, List, Optional
5
- import yaml
6
-
7
- from jarvis.agent import Agent
8
- from jarvis.utils import PrettyOutput, OutputType, get_single_line_input, init_env
9
- from jarvis.tools import ToolRegistry
10
-
11
- # System prompt for the GitHub workflow agent
12
- github_workflow_prompt = """You are a GitHub Workflow Agent that helps manage the complete development workflow using GitHub CLI (gh). Follow these steps strictly:
13
-
14
- 1. Environment Check:
15
- - Verify gh CLI installation
16
- - Check authentication status
17
- - Set up authentication if needed
18
-
19
- 2. Issue Management:
20
- - List and display available issues
21
- - Help user select an issue to work on
22
- - Analyze the selected issue thoroughly
23
-
24
- 3. Development Planning:
25
- - Create a development branch for the issue
26
- - Generate a detailed modification plan
27
- - Break down the task into smaller steps
28
-
29
- 4. Implementation:
30
- - Guide through the implementation process
31
- - Track changes and progress
32
- - Ensure code quality
33
-
34
- 5. Review and Submit:
35
- - Review changes before submission
36
- - Create and submit pull request
37
- - Handle review feedback
38
- - Close the issue upon completion
39
-
40
- Always follow GitHub best practices and provide clear feedback at each step.
41
- """
42
-
43
- def check_gh_installation() -> bool:
44
- """Check if GitHub CLI is installed"""
45
- return os.system("gh --version > /dev/null 2>&1") == 0
46
-
47
- def check_gh_auth() -> bool:
48
- """Check if GitHub CLI is authenticated"""
49
- return os.system("gh auth status > /dev/null 2>&1") == 0
50
-
51
- def setup_gh_auth() -> bool:
52
- """Guide user through GitHub CLI authentication"""
53
- PrettyOutput.print("Starting GitHub CLI authentication...", OutputType.INFO)
54
- return os.system("gh auth login") == 0
55
-
56
- def list_issues() -> List[Dict]:
57
- """List all available issues"""
58
- try:
59
- # Get issues in JSON format
60
- result = os.popen("gh issue list --json number,title,body,url").read()
61
- issues = yaml.safe_load(result)
62
- return issues
63
- except Exception as e:
64
- PrettyOutput.print(f"Error listing issues: {str(e)}", OutputType.ERROR)
65
- return []
66
-
67
- def select_issue(issues: List[Dict]) -> Optional[Dict]:
68
- """Display issues and let user select one"""
69
- if not issues:
70
- PrettyOutput.print("No issues found.", OutputType.WARNING)
71
- return None
72
-
73
- PrettyOutput.print("\nAvailable Issues:", OutputType.INFO)
74
- for i, issue in enumerate(issues, 1):
75
- print(f"{i}. #{issue['number']} - {issue['title']}")
76
-
77
- while True:
78
- try:
79
- choice = get_single_line_input("\nSelect an issue number (or 0 to exit): ")
80
- if not choice or choice == "0":
81
- return None
82
-
83
- index = int(choice) - 1
84
- if 0 <= index < len(issues):
85
- return issues[index]
86
- else:
87
- PrettyOutput.print("Invalid selection. Please try again.", OutputType.WARNING)
88
- except ValueError:
89
- PrettyOutput.print("Please enter a valid number.", OutputType.WARNING)
90
-
91
- def create_development_branch(issue_number: int) -> bool:
92
- """Create a development branch for the issue"""
93
- try:
94
- result = os.system(f"gh issue develop {issue_number} --checkout")
95
- return result == 0
96
- except Exception as e:
97
- PrettyOutput.print(f"Error creating branch: {str(e)}", OutputType.ERROR)
98
- return False
99
-
100
- def create_pull_request(issue_number: int, title: str, body: str) -> bool:
101
- """Create a pull request for the changes"""
102
- try:
103
- cmd = f'gh pr create --title "{title}" --body "{body}" --issue {issue_number}'
104
- result = os.system(cmd)
105
- return result == 0
106
- except Exception as e:
107
- PrettyOutput.print(f"Error creating pull request: {str(e)}", OutputType.ERROR)
108
- return False
109
-
110
- def close_issue(issue_number: int) -> bool:
111
- """Close the issue"""
112
- try:
113
- result = os.system(f"gh issue close {issue_number}")
114
- return result == 0
115
- except Exception as e:
116
- PrettyOutput.print(f"Error closing issue: {str(e)}", OutputType.ERROR)
117
- return False
118
-
119
- def install_gh_linux() -> bool:
120
- """Install GitHub CLI on Linux"""
121
- PrettyOutput.print("Installing GitHub CLI...", OutputType.INFO)
122
-
123
- # Detect package manager
124
- package_managers = {
125
- "apt": "curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg && \
126
- echo \"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main\" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null && \
127
- sudo apt update && sudo apt install gh -y",
128
- "dnf": "sudo dnf install 'dnf-command(config-manager)' -y && \
129
- sudo dnf config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo && \
130
- sudo dnf install gh -y",
131
- "yum": "sudo yum install 'dnf-command(config-manager)' -y && \
132
- sudo yum config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo && \
133
- sudo yum install gh -y",
134
- "pacman": "sudo pacman -S github-cli --noconfirm",
135
- }
136
-
137
- # Try to detect the package manager
138
- for pm, cmd in package_managers.items():
139
- if os.system(f"which {pm} > /dev/null 2>&1") == 0:
140
- PrettyOutput.print(f"Detected {pm} package manager", OutputType.INFO)
141
- if os.system(cmd) == 0:
142
- PrettyOutput.print("GitHub CLI installed successfully!", OutputType.SUCCESS)
143
- return True
144
- else:
145
- PrettyOutput.print(f"Failed to install using {pm}", OutputType.ERROR)
146
- return False
147
-
148
- PrettyOutput.print(
149
- "Could not detect supported package manager. Please install manually:\n"
150
- "https://github.com/cli/cli/blob/trunk/docs/install_linux.md",
151
- OutputType.ERROR
152
- )
153
- return False
154
-
155
- def main():
156
- """Main entry point for GitHub workflow"""
157
- init_env()
158
-
159
- # Check GitHub CLI installation
160
- if not check_gh_installation():
161
- if sys.platform.startswith('linux'):
162
- if not install_gh_linux():
163
- return 1
164
- else:
165
- PrettyOutput.print(
166
- "GitHub CLI (gh) is not installed. Please install it first:\n"
167
- "- Windows: winget install GitHub.cli\n"
168
- "- macOS: brew install gh\n"
169
- "- Linux: See https://github.com/cli/cli/blob/trunk/docs/install_linux.md",
170
- OutputType.ERROR
171
- )
172
- return 1
173
-
174
- # Check authentication
175
- if not check_gh_auth():
176
- PrettyOutput.print("GitHub CLI needs authentication.", OutputType.WARNING)
177
- if not setup_gh_auth():
178
- PrettyOutput.print("Authentication failed. Please try again.", OutputType.ERROR)
179
- return 1
180
-
181
- # List and select issue
182
- issues = list_issues()
183
- selected_issue = select_issue(issues)
184
- if not selected_issue:
185
- PrettyOutput.print("No issue selected. Exiting.", OutputType.INFO)
186
- return 0
187
-
188
- # Create GitHub workflow agent
189
- tool_registry = ToolRegistry()
190
- agent = Agent(
191
- system_prompt=github_workflow_prompt,
192
- name="GitHub Workflow Agent",
193
- tool_registry=tool_registry
194
- )
195
-
196
- # Start the workflow
197
- try:
198
- # Create development branch
199
- if not create_development_branch(selected_issue['number']):
200
- return 1
201
-
202
- # Run the agent with the selected issue
203
- workflow_request = f"""
204
- Working on issue #{selected_issue['number']}: {selected_issue['title']}
205
-
206
- Issue description:
207
- {selected_issue['body']}
208
-
209
- Please guide through the development process and help create a pull request.
210
- """
211
-
212
- result = agent.run(workflow_request)
213
-
214
- # Create pull request and close issue if successful
215
- if result and "success" in result.lower():
216
- if create_pull_request(
217
- selected_issue['number'],
218
- f"Fix #{selected_issue['number']}: {selected_issue['title']}",
219
- "Implements the requested changes and fixes the issue."
220
- ):
221
- close_issue(selected_issue['number'])
222
- PrettyOutput.print("Workflow completed successfully!", OutputType.SUCCESS)
223
- return 0
224
-
225
- except Exception as e:
226
- PrettyOutput.print(f"Error in workflow: {str(e)}", OutputType.ERROR)
227
- return 1
228
-
229
- return 1
230
-
231
- if __name__ == "__main__":
232
- sys.exit(main())
@@ -1,56 +0,0 @@
1
- from typing import Dict, Any
2
-
3
- from jarvis.agent import Agent
4
- from jarvis.utils import OutputType, PrettyOutput
5
- from jarvis.jarvis_code_agent.main import system_prompt
6
-
7
-
8
- class CodeSubAgentTool:
9
- name = "create_code_sub_agent"
10
- description = "Create a sub-agent to handle specific code development subtasks"
11
- parameters = {
12
- "type": "object",
13
- "properties": {
14
- "name": {
15
- "type": "string",
16
- "description": "The name of the sub-agent"
17
- },
18
- "subtask": {
19
- "type": "string",
20
- "description": "The specific code development subtask to complete"
21
- },
22
- },
23
- "required": ["subtask", "name"]
24
- }
25
-
26
- def execute(self, args: Dict) -> Dict[str, Any]:
27
- """Execute code development subtask"""
28
- try:
29
- subtask = args["subtask"]
30
- name = args["name"]
31
-
32
- PrettyOutput.print(f"Creating code sub-agent {name} for subtask: {subtask}", OutputType.INFO)
33
-
34
- # Create sub-agent
35
- sub_agent = Agent(
36
- system_prompt=system_prompt,
37
- name=name,
38
- is_sub_agent=True
39
- )
40
-
41
- # Execute subtask
42
- result = sub_agent.run(subtask)
43
-
44
- return {
45
- "success": True,
46
- "stdout": f"Code Development Subtask Results:\n\n{result}",
47
- "stderr": ""
48
- }
49
-
50
- except Exception as e:
51
- PrettyOutput.print(str(e), OutputType.ERROR)
52
- return {
53
- "success": False,
54
- "stdout": "",
55
- "stderr": f"Failed to execute code development subtask: {str(e)}"
56
- }