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.
- jarvis/__init__.py +1 -1
- jarvis/agent.py +138 -117
- jarvis/jarvis_code_agent/code_agent.py +234 -0
- jarvis/{jarvis_coder → jarvis_code_agent}/file_select.py +19 -22
- jarvis/jarvis_code_agent/patch.py +120 -0
- jarvis/jarvis_code_agent/relevant_files.py +97 -0
- jarvis/jarvis_codebase/main.py +871 -0
- jarvis/jarvis_platform/main.py +5 -3
- jarvis/jarvis_rag/main.py +818 -0
- jarvis/jarvis_smart_shell/main.py +2 -2
- jarvis/models/ai8.py +3 -1
- jarvis/models/kimi.py +36 -30
- jarvis/models/ollama.py +17 -11
- jarvis/models/openai.py +15 -12
- jarvis/models/oyi.py +24 -7
- jarvis/models/registry.py +1 -25
- jarvis/tools/__init__.py +0 -6
- jarvis/tools/ask_codebase.py +96 -0
- jarvis/tools/ask_user.py +1 -9
- jarvis/tools/chdir.py +2 -37
- jarvis/tools/code_review.py +210 -0
- jarvis/tools/create_code_test_agent.py +115 -0
- jarvis/tools/create_ctags_agent.py +164 -0
- jarvis/tools/create_sub_agent.py +2 -2
- jarvis/tools/execute_shell.py +2 -2
- jarvis/tools/file_operation.py +2 -2
- jarvis/tools/find_in_codebase.py +78 -0
- jarvis/tools/git_commiter.py +68 -0
- jarvis/tools/methodology.py +3 -3
- jarvis/tools/rag.py +141 -0
- jarvis/tools/read_code.py +116 -0
- jarvis/tools/read_webpage.py +1 -1
- jarvis/tools/registry.py +47 -31
- jarvis/tools/search.py +8 -6
- jarvis/tools/select_code_files.py +4 -4
- jarvis/utils.py +375 -85
- {jarvis_ai_assistant-0.1.102.dist-info → jarvis_ai_assistant-0.1.104.dist-info}/METADATA +107 -32
- jarvis_ai_assistant-0.1.104.dist-info/RECORD +50 -0
- jarvis_ai_assistant-0.1.104.dist-info/entry_points.txt +11 -0
- jarvis/jarvis_code_agent/main.py +0 -200
- jarvis/jarvis_coder/git_utils.py +0 -123
- jarvis/jarvis_coder/patch_handler.py +0 -340
- jarvis/jarvis_github/main.py +0 -232
- jarvis/tools/create_code_sub_agent.py +0 -56
- jarvis/tools/execute_code_modification.py +0 -70
- jarvis/tools/find_files.py +0 -119
- jarvis/tools/generate_tool.py +0 -174
- jarvis/tools/thinker.py +0 -151
- jarvis_ai_assistant-0.1.102.dist-info/RECORD +0 -46
- jarvis_ai_assistant-0.1.102.dist-info/entry_points.txt +0 -6
- /jarvis/{jarvis_coder → jarvis_codebase}/__init__.py +0 -0
- /jarvis/{jarvis_github → jarvis_rag}/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.102.dist-info → jarvis_ai_assistant-0.1.104.dist-info}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.102.dist-info → jarvis_ai_assistant-0.1.104.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.102.dist-info → jarvis_ai_assistant-0.1.104.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
from typing import Dict, Any, List
|
|
2
|
+
import subprocess
|
|
3
|
+
import yaml
|
|
4
|
+
from jarvis.models.registry import PlatformRegistry
|
|
5
|
+
from jarvis.tools.registry import ToolRegistry
|
|
6
|
+
from jarvis.utils import OutputType, PrettyOutput, init_env, find_git_root
|
|
7
|
+
from jarvis.agent import Agent
|
|
8
|
+
import re
|
|
9
|
+
|
|
10
|
+
class CodeReviewTool:
|
|
11
|
+
name = "code_review"
|
|
12
|
+
description = "Autonomous code review agent for code changes analysis"
|
|
13
|
+
parameters = {
|
|
14
|
+
"type": "object",
|
|
15
|
+
"properties": {
|
|
16
|
+
"review_type": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"description": "Type of review: 'commit' for specific commit, 'current' for current changes",
|
|
19
|
+
"enum": ["commit", "current"],
|
|
20
|
+
"default": "current"
|
|
21
|
+
},
|
|
22
|
+
"commit_sha": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"description": "Target commit SHA to analyze (required for review_type='commit')"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"required": []
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
def __init__(self):
|
|
31
|
+
init_env()
|
|
32
|
+
self.repo_root = find_git_root()
|
|
33
|
+
|
|
34
|
+
def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
|
|
35
|
+
try:
|
|
36
|
+
review_type = args.get("review_type", "current").strip()
|
|
37
|
+
|
|
38
|
+
# Build git diff command based on review type
|
|
39
|
+
if review_type == "commit":
|
|
40
|
+
if "commit_sha" not in args:
|
|
41
|
+
return {
|
|
42
|
+
"success": False,
|
|
43
|
+
"stdout": {},
|
|
44
|
+
"stderr": "commit_sha is required for commit review type"
|
|
45
|
+
}
|
|
46
|
+
commit_sha = args["commit_sha"].strip()
|
|
47
|
+
diff_cmd = f"git show {commit_sha} | cat -"
|
|
48
|
+
else: # current changes
|
|
49
|
+
diff_cmd = "git diff HEAD | cat -"
|
|
50
|
+
|
|
51
|
+
# Execute git diff command
|
|
52
|
+
try:
|
|
53
|
+
diff_output = subprocess.check_output(diff_cmd, shell=True, text=True)
|
|
54
|
+
if not diff_output:
|
|
55
|
+
return {
|
|
56
|
+
"success": False,
|
|
57
|
+
"stdout": {},
|
|
58
|
+
"stderr": "No changes to review"
|
|
59
|
+
}
|
|
60
|
+
PrettyOutput.print(diff_output, OutputType.CODE, lang="diff")
|
|
61
|
+
except subprocess.CalledProcessError as e:
|
|
62
|
+
return {
|
|
63
|
+
"success": False,
|
|
64
|
+
"stdout": {},
|
|
65
|
+
"stderr": f"Failed to get diff: {str(e)}"
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
system_prompt = """You are an autonomous code review expert. Perform in-depth analysis following these guidelines:
|
|
69
|
+
|
|
70
|
+
IMPORTANT:
|
|
71
|
+
- Only analyze the provided diff content
|
|
72
|
+
- Do NOT make assumptions about code not shown
|
|
73
|
+
- Do NOT invent or imagine potential issues
|
|
74
|
+
- Report ONLY issues that can be directly observed
|
|
75
|
+
- If something is unclear, state it explicitly rather than making assumptions
|
|
76
|
+
|
|
77
|
+
REVIEW FOCUS AREAS:
|
|
78
|
+
1. Requirement Alignment:
|
|
79
|
+
- Verify implementation matches original requirements
|
|
80
|
+
- Check for missing functionality
|
|
81
|
+
- Identify over-implementation
|
|
82
|
+
|
|
83
|
+
2. Code Quality:
|
|
84
|
+
- Code readability and structure
|
|
85
|
+
- Proper error handling
|
|
86
|
+
- Code duplication
|
|
87
|
+
- Adherence to style guides
|
|
88
|
+
- Meaningful variable/method names
|
|
89
|
+
|
|
90
|
+
3. Security:
|
|
91
|
+
- Input validation
|
|
92
|
+
- Authentication/Authorization checks
|
|
93
|
+
- Sensitive data handling
|
|
94
|
+
- Potential injection vulnerabilities
|
|
95
|
+
- Secure communication practices
|
|
96
|
+
|
|
97
|
+
4. Testing:
|
|
98
|
+
- Test coverage for new code
|
|
99
|
+
- Edge case handling
|
|
100
|
+
- Test readability and maintainability
|
|
101
|
+
- Missing test scenarios
|
|
102
|
+
|
|
103
|
+
5. Performance:
|
|
104
|
+
- Algorithm efficiency
|
|
105
|
+
- Unnecessary resource consumption
|
|
106
|
+
- Proper caching mechanisms
|
|
107
|
+
- Database query optimization
|
|
108
|
+
|
|
109
|
+
6. Maintainability:
|
|
110
|
+
- Documentation quality
|
|
111
|
+
- Logging and monitoring
|
|
112
|
+
- Configuration management
|
|
113
|
+
- Technical debt indicators
|
|
114
|
+
|
|
115
|
+
7. Operational Considerations:
|
|
116
|
+
- Backward compatibility
|
|
117
|
+
- Migration script safety
|
|
118
|
+
- Environment-specific configurations
|
|
119
|
+
- Deployment impacts
|
|
120
|
+
|
|
121
|
+
REVIEW PROCESS:
|
|
122
|
+
1. Retrieve full commit context using git commands
|
|
123
|
+
2. Analyze code changes line-by-line
|
|
124
|
+
3. Cross-reference with project standards
|
|
125
|
+
4. Verify test coverage adequacy
|
|
126
|
+
5. Check documentation updates
|
|
127
|
+
6. Generate prioritized findings
|
|
128
|
+
|
|
129
|
+
OUTPUT REQUIREMENTS:
|
|
130
|
+
- Categorize issues by severity (Critical/Major/Minor)
|
|
131
|
+
- Reference specific code locations
|
|
132
|
+
- Provide concrete examples from the diff
|
|
133
|
+
- Suggest actionable improvements based on observed code
|
|
134
|
+
- Highlight security risks clearly with evidence from the code
|
|
135
|
+
- Separate technical debt from blockers
|
|
136
|
+
- If certain aspects cannot be reviewed due to limited context, note this explicitly
|
|
137
|
+
- Do not speculate about code not shown in the diff
|
|
138
|
+
"""
|
|
139
|
+
tool_registry = ToolRegistry()
|
|
140
|
+
tool_registry.dont_use_tools(["code_review"])
|
|
141
|
+
agent = Agent(
|
|
142
|
+
system_prompt=system_prompt,
|
|
143
|
+
name="Code Review Agent",
|
|
144
|
+
summary_prompt="""Please generate a concise summary report of the code review, format as yaml:
|
|
145
|
+
<REPORT>
|
|
146
|
+
- file: xxxx.py
|
|
147
|
+
location: [start_line_number, end_line_number]
|
|
148
|
+
description: # Only describe issues directly observable in the diff
|
|
149
|
+
severity: # Critical/Major/Minor based on concrete evidence
|
|
150
|
+
suggestion: # Specific, actionable improvements for the observed code
|
|
151
|
+
</REPORT>""",
|
|
152
|
+
is_sub_agent=True,
|
|
153
|
+
tool_registry=tool_registry,
|
|
154
|
+
platform=PlatformRegistry().get_thinking_platform(),
|
|
155
|
+
auto_complete=True
|
|
156
|
+
)
|
|
157
|
+
result = agent.run(diff_output)
|
|
158
|
+
return {
|
|
159
|
+
"success": True,
|
|
160
|
+
"stdout": result,
|
|
161
|
+
"stderr": ""
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
except Exception as e:
|
|
165
|
+
return {
|
|
166
|
+
"success": False,
|
|
167
|
+
"stdout": {},
|
|
168
|
+
"stderr": f"Review failed: {str(e)}"
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def _extract_code_report(result: str) -> str:
|
|
173
|
+
sm = re.search(r"<REPORT>(.*?)</REPORT>", result, re.DOTALL)
|
|
174
|
+
if sm:
|
|
175
|
+
return sm.group(1)
|
|
176
|
+
return ""
|
|
177
|
+
|
|
178
|
+
def main():
|
|
179
|
+
"""CLI entry point"""
|
|
180
|
+
import argparse
|
|
181
|
+
|
|
182
|
+
parser = argparse.ArgumentParser(description='Autonomous code review tool')
|
|
183
|
+
parser.add_argument('--type', choices=['commit', 'current'], default='current',
|
|
184
|
+
help='Type of review: commit or current changes')
|
|
185
|
+
parser.add_argument('--commit', help='Commit SHA to review (required for commit type)')
|
|
186
|
+
args = parser.parse_args()
|
|
187
|
+
|
|
188
|
+
# Validate arguments
|
|
189
|
+
if args.type == 'commit' and not args.commit:
|
|
190
|
+
parser.error("--commit is required when type is 'commit'")
|
|
191
|
+
|
|
192
|
+
tool = CodeReviewTool()
|
|
193
|
+
tool_args = {
|
|
194
|
+
"review_type": args.type
|
|
195
|
+
}
|
|
196
|
+
if args.commit:
|
|
197
|
+
tool_args["commit_sha"] = args.commit
|
|
198
|
+
|
|
199
|
+
result = tool.execute(tool_args)
|
|
200
|
+
|
|
201
|
+
if result["success"]:
|
|
202
|
+
PrettyOutput.section("Autonomous Review Result:", OutputType.SUCCESS)
|
|
203
|
+
report = _extract_code_report(result["stdout"])
|
|
204
|
+
PrettyOutput.print(report, OutputType.SUCCESS, lang="yaml")
|
|
205
|
+
|
|
206
|
+
else:
|
|
207
|
+
PrettyOutput.print(result["stderr"], OutputType.ERROR)
|
|
208
|
+
|
|
209
|
+
if __name__ == "__main__":
|
|
210
|
+
main()
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
from typing import Dict, Any
|
|
2
|
+
from jarvis.agent import Agent
|
|
3
|
+
from jarvis.tools.registry import ToolRegistry
|
|
4
|
+
import subprocess
|
|
5
|
+
|
|
6
|
+
class TestAgentTool:
|
|
7
|
+
name = "create_code_test_agent"
|
|
8
|
+
description = "Create testing agent for specific commit analysis"
|
|
9
|
+
parameters = {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"properties": {
|
|
12
|
+
"name": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"description": "Identifier for the test agent"
|
|
15
|
+
},
|
|
16
|
+
"test_scope": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"enum": ["unit", "integration", "e2e"],
|
|
19
|
+
"description": "Testing focus area"
|
|
20
|
+
},
|
|
21
|
+
"commit_sha": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"description": "Commit SHA to analyze"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"required": ["name", "test_scope", "commit_sha"]
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
def execute(self, args: Dict) -> Dict[str, Any]:
|
|
30
|
+
"""Execute commit-focused testing"""
|
|
31
|
+
try:
|
|
32
|
+
if not self._is_valid_commit(args["commit_sha"]):
|
|
33
|
+
return {
|
|
34
|
+
"success": False,
|
|
35
|
+
"stdout": "",
|
|
36
|
+
"stderr": f"Invalid commit SHA: {args['commit_sha']}"
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
tool_registry = ToolRegistry()
|
|
40
|
+
tool_registry.dont_use_tools(["create_code_test_agent"])
|
|
41
|
+
|
|
42
|
+
test_agent = Agent(
|
|
43
|
+
system_prompt=self._build_system_prompt(args),
|
|
44
|
+
name=f"TestAgent({args['name']})",
|
|
45
|
+
is_sub_agent=True,
|
|
46
|
+
tool_registry=tool_registry
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
result = test_agent.run(
|
|
50
|
+
f"Analyze and test changes in commit {args['commit_sha'].strip()}"
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
"success": True,
|
|
55
|
+
"stdout": result,
|
|
56
|
+
"stderr": ""
|
|
57
|
+
}
|
|
58
|
+
except Exception as e:
|
|
59
|
+
return {
|
|
60
|
+
"success": False,
|
|
61
|
+
"stdout": "",
|
|
62
|
+
"stderr": f"Commit testing failed: {str(e)}"
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
def _is_valid_commit(self, commit_sha: str) -> bool:
|
|
66
|
+
"""Validate commit exists in repository"""
|
|
67
|
+
try:
|
|
68
|
+
cmd = f"git cat-file -t {commit_sha}"
|
|
69
|
+
result = subprocess.run(
|
|
70
|
+
cmd.split(),
|
|
71
|
+
capture_output=True,
|
|
72
|
+
text=True,
|
|
73
|
+
check=True
|
|
74
|
+
)
|
|
75
|
+
return "commit" in result.stdout
|
|
76
|
+
except subprocess.CalledProcessError:
|
|
77
|
+
return False
|
|
78
|
+
|
|
79
|
+
def _build_system_prompt(self, args: Dict) -> str:
|
|
80
|
+
return """You are a Commit Testing Specialist. Follow this protocol:
|
|
81
|
+
|
|
82
|
+
【Testing Protocol】
|
|
83
|
+
1. Commit Analysis:
|
|
84
|
+
- Analyze code changes in target commit
|
|
85
|
+
- Identify modified components
|
|
86
|
+
- Assess change impact scope
|
|
87
|
+
|
|
88
|
+
2. Test Strategy:
|
|
89
|
+
- Determine required test types
|
|
90
|
+
- Verify backward compatibility
|
|
91
|
+
- Check interface contracts
|
|
92
|
+
|
|
93
|
+
3. Test Execution:
|
|
94
|
+
- Execute relevant test suites
|
|
95
|
+
- Compare pre/post-commit behavior
|
|
96
|
+
- Validate cross-component interactions
|
|
97
|
+
|
|
98
|
+
4. Reporting:
|
|
99
|
+
- List affected modules
|
|
100
|
+
- Risk assessment matrix
|
|
101
|
+
- Performance impact analysis
|
|
102
|
+
- Security implications
|
|
103
|
+
|
|
104
|
+
【Output Requirements】
|
|
105
|
+
- Test coverage analysis
|
|
106
|
+
- Behavioral change summary
|
|
107
|
+
- Critical issues prioritized
|
|
108
|
+
- Actionable recommendations
|
|
109
|
+
|
|
110
|
+
【Key Principles】
|
|
111
|
+
1. Focus on delta changes
|
|
112
|
+
2. Maintain test isolation
|
|
113
|
+
3. Preserve historical baselines
|
|
114
|
+
4. Automate verification steps
|
|
115
|
+
5. Document test evidence"""
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
from typing import Dict, Any
|
|
2
|
+
import subprocess
|
|
3
|
+
import os
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import yaml
|
|
7
|
+
from jarvis.agent import Agent
|
|
8
|
+
from jarvis.tools.registry import ToolRegistry
|
|
9
|
+
from jarvis.utils import OutputType, PrettyOutput, get_multiline_input, init_env
|
|
10
|
+
|
|
11
|
+
ctags_system_prompt = """You are a Ctags Expert Agent specializing in code analysis using Exuberant Ctags. Follow this protocol:
|
|
12
|
+
|
|
13
|
+
【OUTPUT OPTIMIZATION】
|
|
14
|
+
1. Filter with grep:
|
|
15
|
+
ctags -x <symbol> | grep -E 'pattern'
|
|
16
|
+
2. Limit output lines:
|
|
17
|
+
head -n 20
|
|
18
|
+
3. Context preview:
|
|
19
|
+
grep -A 3 -B 3 <line> <file>
|
|
20
|
+
4. Column selection:
|
|
21
|
+
cut -f 1,3
|
|
22
|
+
5. Sort and deduplicate:
|
|
23
|
+
sort | uniq
|
|
24
|
+
|
|
25
|
+
【WORKFLOW】
|
|
26
|
+
1. REQUIREMENT ANALYSIS
|
|
27
|
+
- Analyze query for symbols/patterns
|
|
28
|
+
- Determine search scope
|
|
29
|
+
- Select ctags options
|
|
30
|
+
- Plan output filtering
|
|
31
|
+
|
|
32
|
+
2. TAGS MANAGEMENT
|
|
33
|
+
- Generate/update tags file:
|
|
34
|
+
ctags -R --languages=<lang> --exclude=<pattern>
|
|
35
|
+
- Verify tags file integrity
|
|
36
|
+
- Maintain tags file versioning
|
|
37
|
+
|
|
38
|
+
3. SYMBOL PROCESSING
|
|
39
|
+
- Search symbols using:
|
|
40
|
+
grep -n <symbol> tags
|
|
41
|
+
ctags -x --<filter>
|
|
42
|
+
- Analyze symbol relationships
|
|
43
|
+
- Map symbol dependencies
|
|
44
|
+
- Apply output filters:
|
|
45
|
+
* Remove noise with grep -v
|
|
46
|
+
* Highlight key fields with awk
|
|
47
|
+
* Truncate long lines with cut
|
|
48
|
+
|
|
49
|
+
4. OUTPUT GENERATION
|
|
50
|
+
- Format results as YAML
|
|
51
|
+
- Include file paths and line numbers
|
|
52
|
+
- Add symbol metadata
|
|
53
|
+
- Limit to 20 key results
|
|
54
|
+
- Exclude temporary files
|
|
55
|
+
- Compress repetitive info
|
|
56
|
+
|
|
57
|
+
【COMMAND REFERENCE】
|
|
58
|
+
1. Generate Tags:
|
|
59
|
+
ctags -R --fields=+nKSt --extras=+fq -V *
|
|
60
|
+
|
|
61
|
+
2. Search Patterns:
|
|
62
|
+
ctags -x --c-types=f
|
|
63
|
+
ctags -x --sort=no <symbol>
|
|
64
|
+
ctags -x | grep '^main' | head -n 5
|
|
65
|
+
|
|
66
|
+
3. Language Specific:
|
|
67
|
+
--languages=Python,Java,C++
|
|
68
|
+
--python-kinds=-iv
|
|
69
|
+
|
|
70
|
+
4. Filtering:
|
|
71
|
+
--exclude=.git
|
|
72
|
+
--exclude=*.min.js
|
|
73
|
+
ctags -x | grep -v '_test' # Exclude tests
|
|
74
|
+
|
|
75
|
+
【ERROR HANDLING】
|
|
76
|
+
- Missing tags: Regenerate tags
|
|
77
|
+
- Invalid symbols: Use fuzzy search
|
|
78
|
+
- Encoding issues: Use --input-encoding
|
|
79
|
+
- Large codebase: Limit scope
|
|
80
|
+
- Output too long: Add head/grep filters
|
|
81
|
+
|
|
82
|
+
【NATURAL LANGUAGE PROCESSING】
|
|
83
|
+
1. Query Interpretation:
|
|
84
|
+
- Identify key terms: "find", "locate", "list", "show"
|
|
85
|
+
- Detect symbol types: class, function, variable
|
|
86
|
+
- Recognize relationships: "calls", "inherits", "uses"
|
|
87
|
+
|
|
88
|
+
2. Query Types:
|
|
89
|
+
- Location: "Where is X defined?"
|
|
90
|
+
- References: "Who calls Y?"
|
|
91
|
+
- Hierarchy: "Show subclasses of Z"
|
|
92
|
+
- Impact: "What uses this module?"
|
|
93
|
+
|
|
94
|
+
3. Auto Command Mapping:
|
|
95
|
+
| Query Pattern | Ctags Command |
|
|
96
|
+
|------------------------------|------------------------------------|
|
|
97
|
+
| Find definitions of X | ctags -x --<lang>-kinds=f | less |
|
|
98
|
+
| List all functions in Y | ctags -x --filter='function' |
|
|
99
|
+
| Show callers of Z | ctags --extra=+q -x | grep Z |
|
|
100
|
+
| Find interface implementations| ctags -x --_traits=yes |
|
|
101
|
+
|
|
102
|
+
4. Context Handling:
|
|
103
|
+
- Detect language from file extensions
|
|
104
|
+
- Auto-detect project root
|
|
105
|
+
- Apply language-specific filters
|
|
106
|
+
- Choose appropriate output format:
|
|
107
|
+
* Simple list for single results
|
|
108
|
+
* Table for multiple entries
|
|
109
|
+
* Tree view for hierarchies
|
|
110
|
+
* JSON when programmatic access needed
|
|
111
|
+
|
|
112
|
+
【EXAMPLE QUERIES】
|
|
113
|
+
1. "Find all Python functions in src/ that use Redis"
|
|
114
|
+
2. "Show Java classes implementing PaymentService"
|
|
115
|
+
3. "List called methods in auth module"
|
|
116
|
+
4. "Where is User model defined?"
|
|
117
|
+
5. "What config files reference database settings?"
|
|
118
|
+
"""
|
|
119
|
+
|
|
120
|
+
class CtagsTool:
|
|
121
|
+
name = "create_ctags_agent"
|
|
122
|
+
description = "Analyze code structure and symbols using natural language queries"
|
|
123
|
+
parameters = {
|
|
124
|
+
"type": "object",
|
|
125
|
+
"properties": {
|
|
126
|
+
"query": {
|
|
127
|
+
"type": "string",
|
|
128
|
+
"description": "Natural language description of code analysis needs"
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
"required": ["query"]
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
def execute(self, args: Dict) -> Dict[str, Any]:
|
|
135
|
+
"""Execute code analysis based on natural language query"""
|
|
136
|
+
try:
|
|
137
|
+
tool_registry = ToolRegistry()
|
|
138
|
+
tool_registry.use_tools(["execute_shell"])
|
|
139
|
+
|
|
140
|
+
ctags_agent = Agent(
|
|
141
|
+
system_prompt=ctags_system_prompt,
|
|
142
|
+
name="Ctags Analysis Agent",
|
|
143
|
+
is_sub_agent=True,
|
|
144
|
+
tool_registry=tool_registry
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
analysis_request = f"""
|
|
148
|
+
Analysis Request: {args['query']}
|
|
149
|
+
Context: {args.get('context', {})}
|
|
150
|
+
"""
|
|
151
|
+
|
|
152
|
+
result = ctags_agent.run(analysis_request)
|
|
153
|
+
|
|
154
|
+
return {
|
|
155
|
+
"success": True,
|
|
156
|
+
"stdout": result,
|
|
157
|
+
"stderr": ""
|
|
158
|
+
}
|
|
159
|
+
except Exception as e:
|
|
160
|
+
return {
|
|
161
|
+
"success": False,
|
|
162
|
+
"stdout": "",
|
|
163
|
+
"stderr": f"Analysis failed: {str(e)}"
|
|
164
|
+
}
|
jarvis/tools/create_sub_agent.py
CHANGED
|
@@ -2,6 +2,7 @@ from typing import Dict, Any
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
from jarvis.agent import Agent, origin_agent_system_prompt
|
|
5
|
+
from jarvis.tools.registry import ToolRegistry
|
|
5
6
|
from jarvis.utils import OutputType, PrettyOutput
|
|
6
7
|
|
|
7
8
|
|
|
@@ -58,12 +59,11 @@ class SubAgentTool:
|
|
|
58
59
|
if goal:
|
|
59
60
|
task_description += f"\n\nCompletion goal:\n{goal}"
|
|
60
61
|
|
|
61
|
-
|
|
62
62
|
|
|
63
63
|
# Create sub-agent
|
|
64
64
|
sub_agent = Agent(
|
|
65
65
|
system_prompt=origin_agent_system_prompt,
|
|
66
|
-
name=agent_name,
|
|
66
|
+
name=f"Agent({agent_name})",
|
|
67
67
|
is_sub_agent=True
|
|
68
68
|
)
|
|
69
69
|
|
jarvis/tools/execute_shell.py
CHANGED
|
@@ -29,7 +29,7 @@ class ShellTool:
|
|
|
29
29
|
def execute(self, args: Dict) -> Dict[str, Any]:
|
|
30
30
|
"""Execute shell command"""
|
|
31
31
|
try:
|
|
32
|
-
command = args["command"]
|
|
32
|
+
command = args["command"].strip()
|
|
33
33
|
|
|
34
34
|
# Generate temporary file name
|
|
35
35
|
output_file = os.path.join(tempfile.gettempdir(), f"jarvis_shell_{os.getpid()}.log")
|
|
@@ -61,7 +61,7 @@ class ShellTool:
|
|
|
61
61
|
Path(output_file).unlink(missing_ok=True)
|
|
62
62
|
|
|
63
63
|
return {
|
|
64
|
-
"success":
|
|
64
|
+
"success": True,
|
|
65
65
|
"stdout": output,
|
|
66
66
|
"stderr": "",
|
|
67
67
|
}
|
jarvis/tools/file_operation.py
CHANGED
|
@@ -37,8 +37,8 @@ class FileOperationTool:
|
|
|
37
37
|
def execute(self, args: Dict) -> Dict[str, Any]:
|
|
38
38
|
"""Execute file operations"""
|
|
39
39
|
try:
|
|
40
|
-
operation = args["operation"]
|
|
41
|
-
filepath = args["filepath"]
|
|
40
|
+
operation = args["operation"].strip()
|
|
41
|
+
filepath = args["filepath"].strip()
|
|
42
42
|
encoding = args.get("encoding", "utf-8")
|
|
43
43
|
|
|
44
44
|
# Record the operation and the full path
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
from typing import Dict, Any
|
|
2
|
+
from jarvis.jarvis_code_agent.file_select import select_files
|
|
3
|
+
from jarvis.utils import OutputType, PrettyOutput, dont_use_local_model, find_git_root
|
|
4
|
+
from jarvis.jarvis_codebase.main import CodeBase
|
|
5
|
+
|
|
6
|
+
class FindInCodebaseTool:
|
|
7
|
+
"""Tool for searching files in codebase based on requirements"""
|
|
8
|
+
|
|
9
|
+
name = "find_in_codebase"
|
|
10
|
+
description = "Search and identify relevant code files in the codebase based on requirements description, using semantic search"
|
|
11
|
+
parameters = {
|
|
12
|
+
"type": "object",
|
|
13
|
+
"properties": {
|
|
14
|
+
"query": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"description": "The search query or requirement description"
|
|
17
|
+
},
|
|
18
|
+
"top_k": {
|
|
19
|
+
"type": "integer",
|
|
20
|
+
"description": "Maximum number of results to return",
|
|
21
|
+
"default": 20
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"required": ["query"]
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@staticmethod
|
|
28
|
+
def check() -> bool:
|
|
29
|
+
return not dont_use_local_model()
|
|
30
|
+
|
|
31
|
+
def execute(self, args: Dict) -> Dict[str, Any]:
|
|
32
|
+
"""Execute the search
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
args: Dictionary containing:
|
|
36
|
+
- query: Search query string
|
|
37
|
+
- top_k: Maximum number of results (optional)
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
Dict containing:
|
|
41
|
+
- success: Boolean indicating success
|
|
42
|
+
- stdout: Search results in YAML format
|
|
43
|
+
- stderr: Error message if any
|
|
44
|
+
"""
|
|
45
|
+
try:
|
|
46
|
+
query = args["query"]
|
|
47
|
+
top_k = args.get("top_k", 20)
|
|
48
|
+
|
|
49
|
+
root_dir = find_git_root()
|
|
50
|
+
|
|
51
|
+
codebase = CodeBase(root_dir)
|
|
52
|
+
|
|
53
|
+
# Search for relevant files
|
|
54
|
+
results = codebase.search_similar(query, top_k)
|
|
55
|
+
|
|
56
|
+
results = select_files(results, root_dir)
|
|
57
|
+
|
|
58
|
+
if not results:
|
|
59
|
+
return {
|
|
60
|
+
"success": True,
|
|
61
|
+
"stdout": "files: []\n",
|
|
62
|
+
"stderr": "No relevant files found"
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
"success": True,
|
|
68
|
+
"stdout": "\n".join(results),
|
|
69
|
+
"stderr": ""
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
except Exception as e:
|
|
73
|
+
PrettyOutput.print(f"Search error: {str(e)}", OutputType.ERROR)
|
|
74
|
+
return {
|
|
75
|
+
"success": False,
|
|
76
|
+
"stdout": "",
|
|
77
|
+
"stderr": f"Failed to execute search: {str(e)}"
|
|
78
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import re
|
|
3
|
+
from typing import Dict, Any
|
|
4
|
+
|
|
5
|
+
import yaml
|
|
6
|
+
from jarvis.agent import Agent
|
|
7
|
+
from jarvis.models.registry import PlatformRegistry
|
|
8
|
+
from jarvis.tools.registry import ToolRegistry
|
|
9
|
+
from jarvis.utils import OutputType, PrettyOutput, init_env
|
|
10
|
+
import sys
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class GitCommitTool:
|
|
14
|
+
name = "git_commit_agent"
|
|
15
|
+
description = "Automatically generate and execute git commits based on code changes"
|
|
16
|
+
parameters = {"properties": {}, "required": []}
|
|
17
|
+
|
|
18
|
+
def _extract_commit_message(self, message):
|
|
19
|
+
r = re.search(r"<COMMIT_MESSAGE>(.*)</COMMIT_MESSAGE>", message, re.DOTALL)
|
|
20
|
+
if r:
|
|
21
|
+
return ';'.join(r.group(1).strip().splitlines())
|
|
22
|
+
return "Unknown commit message"
|
|
23
|
+
|
|
24
|
+
def _get_last_commit_hash(self):
|
|
25
|
+
return os.popen("git log -1 --pretty=%H").read().strip()
|
|
26
|
+
|
|
27
|
+
def execute(self, args: Dict) -> Dict[str, Any]:
|
|
28
|
+
"""Execute automatic commit process"""
|
|
29
|
+
try:
|
|
30
|
+
PrettyOutput.print("Add files to commit...", OutputType.SYSTEM)
|
|
31
|
+
os.system("git add .")
|
|
32
|
+
PrettyOutput.print("Get diff...", OutputType.SYSTEM)
|
|
33
|
+
diff = os.popen("git diff --cached --exit-code").read()
|
|
34
|
+
PrettyOutput.print(diff, OutputType.CODE, lang="diff")
|
|
35
|
+
prompt = f'''Please generate a commit message for the following changes.
|
|
36
|
+
Format:
|
|
37
|
+
<COMMIT_MESSAGE>
|
|
38
|
+
type(scope): description
|
|
39
|
+
</COMMIT_MESSAGE>
|
|
40
|
+
|
|
41
|
+
Don't include any other information.
|
|
42
|
+
|
|
43
|
+
{diff}
|
|
44
|
+
'''
|
|
45
|
+
PrettyOutput.print("Generate commit message...", OutputType.SYSTEM)
|
|
46
|
+
platform = PlatformRegistry().get_codegen_platform()
|
|
47
|
+
platform.set_suppress_output(True)
|
|
48
|
+
commit_message = platform.chat_until_success(prompt)
|
|
49
|
+
commit_message = self._extract_commit_message(commit_message)
|
|
50
|
+
PrettyOutput.print("Commit...", OutputType.INFO)
|
|
51
|
+
os.popen(f"git commit -m '{commit_message}'")
|
|
52
|
+
|
|
53
|
+
commit_hash = self._get_last_commit_hash()
|
|
54
|
+
|
|
55
|
+
PrettyOutput.section(f"Commit hash: {commit_hash}\nCommit message: {commit_message}", OutputType.SUCCESS)
|
|
56
|
+
|
|
57
|
+
return {"success": True, "stdout": yaml.safe_dump({"commit_hash": commit_hash, "commit_message": commit_message}), "stderr": ""}
|
|
58
|
+
|
|
59
|
+
except Exception as e:
|
|
60
|
+
return {"success": False, "stdout": "", "stderr": f"Commit error: {str(e)}"}
|
|
61
|
+
|
|
62
|
+
def main():
|
|
63
|
+
init_env()
|
|
64
|
+
tool = GitCommitTool()
|
|
65
|
+
tool.execute({})
|
|
66
|
+
|
|
67
|
+
if __name__ == "__main__":
|
|
68
|
+
sys.exit(main())
|