jarvis-ai-assistant 0.1.118__tar.gz → 0.1.120__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.
Potentially problematic release.
This version of jarvis-ai-assistant might be problematic. Click here for more details.
- {jarvis_ai_assistant-0.1.118/src/jarvis_ai_assistant.egg-info → jarvis_ai_assistant-0.1.120}/PKG-INFO +1 -1
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/pyproject.toml +3 -1
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/setup.py +3 -1
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/__init__.py +1 -1
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_agent/__init__.py +60 -46
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_code_agent/code_agent.py +71 -107
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_code_agent/file_select.py +90 -18
- jarvis_ai_assistant-0.1.120/src/jarvis/jarvis_code_agent/patch.py +412 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_dev/main.py +42 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_platform/base.py +28 -4
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_tools/code_review.py +79 -68
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_tools/create_code_agent.py +2 -2
- jarvis_ai_assistant-0.1.120/src/jarvis/jarvis_tools/git_commiter.py +109 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_tools/read_code.py +31 -18
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_tools/select_code_files.py +1 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_utils/__init__.py +2 -2
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120/src/jarvis_ai_assistant.egg-info}/PKG-INFO +1 -1
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis_ai_assistant.egg-info/entry_points.txt +2 -0
- jarvis_ai_assistant-0.1.118/src/jarvis/jarvis_code_agent/patch.py +0 -212
- jarvis_ai_assistant-0.1.118/src/jarvis/jarvis_tools/git_commiter.py +0 -69
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/MANIFEST.in +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/README.md +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/setup.cfg +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_agent/output_handler.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_code_agent/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_code_agent/relevant_files.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_codebase/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_codebase/main.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_lsp/base.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_lsp/cpp.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_lsp/go.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_lsp/python.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_lsp/registry.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_lsp/rust.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_multi_agent/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_platform/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_platform/ai8.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_platform/kimi.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_platform/ollama.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_platform/openai.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_platform/oyi.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_platform/registry.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_platform_manager/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_platform_manager/main.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_platform_manager/openai_test.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_rag/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_rag/main.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_smart_shell/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_smart_shell/main.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_tools/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_tools/ask_codebase.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_tools/ask_user.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_tools/base.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_tools/chdir.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_tools/create_sub_agent.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_tools/execute_shell.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_tools/file_operation.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_tools/lsp_find_definition.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_tools/lsp_find_references.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_tools/lsp_get_diagnostics.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_tools/lsp_get_document_symbols.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_tools/lsp_prepare_rename.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_tools/lsp_validate_edit.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_tools/methodology.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_tools/rag.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_tools/read_webpage.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_tools/registry.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_tools/search.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_tools/tool_generator.py +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis_ai_assistant.egg-info/SOURCES.txt +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis_ai_assistant.egg-info/dependency_links.txt +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis_ai_assistant.egg-info/requires.txt +0 -0
- {jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis_ai_assistant.egg-info/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "jarvis-ai-assistant"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.120"
|
|
8
8
|
description = "Jarvis: An AI assistant that uses tools to interact with the system"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [{ name = "Your Name", email = "your.email@example.com" }]
|
|
@@ -55,6 +55,7 @@ Homepage = "https://github.com/skyfireitdiy/Jarvis"
|
|
|
55
55
|
[project.scripts]
|
|
56
56
|
jarvis = "jarvis.jarvis_agent:main"
|
|
57
57
|
jarvis-code-agent = "jarvis.jarvis_code_agent.code_agent:main"
|
|
58
|
+
jca = "jarvis.jarvis_code_agent.code_agent:main"
|
|
58
59
|
jarvis-codebase = "jarvis.jarvis_codebase.main:main"
|
|
59
60
|
jarvis-rag = "jarvis.jarvis_rag.main:main"
|
|
60
61
|
jarvis-smart-shell = "jarvis.jarvis_smart_shell.main:main"
|
|
@@ -62,4 +63,5 @@ jss = "jarvis.jarvis_smart_shell.main:main"
|
|
|
62
63
|
jarvis-platform-manager = "jarvis.jarvis_platform_manager.main:main"
|
|
63
64
|
jarvis-git-commit = "jarvis.jarvis_tools.git_commiter:main"
|
|
64
65
|
jarvis-code-review = "jarvis.jarvis_tools.code_review:main"
|
|
66
|
+
jgc = "jarvis.jarvis_tools.git_commiter:main"
|
|
65
67
|
jarvis-dev = "jarvis.jarvis_dev.main:main"
|
|
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|
|
2
2
|
|
|
3
3
|
setup(
|
|
4
4
|
name="jarvis-ai-assistant",
|
|
5
|
-
version="0.1.
|
|
5
|
+
version="0.1.120",
|
|
6
6
|
author="skyfire",
|
|
7
7
|
author_email="skyfireitdiy@hotmail.com",
|
|
8
8
|
description="An AI assistant that uses various tools to interact with the system",
|
|
@@ -40,6 +40,7 @@ setup(
|
|
|
40
40
|
"console_scripts": [
|
|
41
41
|
"jarvis=jarvis.jarvis_agent:main",
|
|
42
42
|
"jarvis-code-agent=jarvis.jarvis_code_agent.code_agent:main",
|
|
43
|
+
"jca=jarvis.jarvis_code_agent.code_agent:main",
|
|
43
44
|
"jarvis-codebase=jarvis.jarvis_codebase.main:main",
|
|
44
45
|
"jarvis-rag=jarvis.jarvis_rag.main:main",
|
|
45
46
|
"jarvis-smart-shell=jarvis.jarvis_smart_shell.main:main",
|
|
@@ -48,6 +49,7 @@ setup(
|
|
|
48
49
|
"jarvis-git-commit=jarvis.jarvis_tools.git_commiter:main",
|
|
49
50
|
"jarvis-code-review=jarvis.jarvis_tools.code_review:main",
|
|
50
51
|
"jarvis-dev=jarvis.jarvis_dev.main:main",
|
|
52
|
+
"jgc=jarvis.jarvis_tools.git_commiter:main",
|
|
51
53
|
],
|
|
52
54
|
},
|
|
53
55
|
python_requires=">=3.8",
|
{jarvis_ai_assistant-0.1.118 → jarvis_ai_assistant-0.1.120}/src/jarvis/jarvis_agent/__init__.py
RENAMED
|
@@ -94,34 +94,34 @@ Please describe in concise bullet points, highlighting important information.
|
|
|
94
94
|
|
|
95
95
|
PrettyOutput.print(welcome_message, OutputType.SYSTEM)
|
|
96
96
|
|
|
97
|
-
|
|
98
|
-
# 🧰 Available
|
|
99
|
-
The following
|
|
97
|
+
action_prompt = """
|
|
98
|
+
# 🧰 Available Actions
|
|
99
|
+
The following actions are at your disposal:
|
|
100
100
|
"""
|
|
101
101
|
|
|
102
102
|
# 添加工具列表概览
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
action_prompt += "\n## Action List\n"
|
|
104
|
+
action_prompt += ", ".join([handler.name() for handler in self.output_handler])
|
|
105
105
|
|
|
106
106
|
# 添加每个工具的详细说明
|
|
107
|
-
|
|
107
|
+
action_prompt += "\n\n# 📝 Action Details\n"
|
|
108
108
|
for handler in self.output_handler:
|
|
109
|
-
|
|
109
|
+
action_prompt += f"\n## {handler.name()}\n"
|
|
110
110
|
# 获取工具的提示词并确保格式正确
|
|
111
111
|
handler_prompt = handler.prompt().strip()
|
|
112
112
|
# 调整缩进以保持层级结构
|
|
113
113
|
handler_prompt = "\n".join(" " + line if line.strip() else line
|
|
114
114
|
for line in handler_prompt.split("\n"))
|
|
115
|
-
|
|
115
|
+
action_prompt += handler_prompt + "\n"
|
|
116
116
|
|
|
117
117
|
# 添加工具使用总结
|
|
118
|
-
|
|
119
|
-
# ❗ Important
|
|
120
|
-
1. Use ONE
|
|
121
|
-
2. Follow each
|
|
122
|
-
3. Wait for
|
|
123
|
-
4. Process results before new
|
|
124
|
-
5. Request help if
|
|
118
|
+
action_prompt += """
|
|
119
|
+
# ❗ Important Action Usage Rules
|
|
120
|
+
1. Use ONE action at a time
|
|
121
|
+
2. Follow each action's format exactly
|
|
122
|
+
3. Wait for action results before next action
|
|
123
|
+
4. Process results before new action calls
|
|
124
|
+
5. Request help if action usage is unclear
|
|
125
125
|
"""
|
|
126
126
|
|
|
127
127
|
complete_prompt = ""
|
|
@@ -135,7 +135,7 @@ The following tools are at your disposal:
|
|
|
135
135
|
self.model.set_system_message(f"""
|
|
136
136
|
{self.system_prompt}
|
|
137
137
|
|
|
138
|
-
{
|
|
138
|
+
{action_prompt}
|
|
139
139
|
|
|
140
140
|
{complete_prompt}
|
|
141
141
|
""")
|
|
@@ -156,10 +156,8 @@ The following tools are at your disposal:
|
|
|
156
156
|
Will retry with exponential backoff up to 30 seconds between retries
|
|
157
157
|
"""
|
|
158
158
|
sleep_time = 5
|
|
159
|
-
|
|
160
159
|
for handler in self.input_handler:
|
|
161
|
-
message = handler(message)
|
|
162
|
-
|
|
160
|
+
message = handler(message, self)
|
|
163
161
|
while True:
|
|
164
162
|
ret = self.model.chat_until_success(message) # type: ignore
|
|
165
163
|
if ret:
|
|
@@ -398,24 +396,11 @@ def _load_tasks() -> dict:
|
|
|
398
396
|
except Exception as e:
|
|
399
397
|
PrettyOutput.print(f"加载 .jarvis/pre-command 文件失败: {str(e)}", OutputType.ERROR)
|
|
400
398
|
|
|
401
|
-
|
|
402
|
-
if is_use_methodology():
|
|
403
|
-
# Read methodology
|
|
404
|
-
method_path = os.path.expanduser("~/.jarvis/methodology")
|
|
405
|
-
if os.path.exists(method_path):
|
|
406
|
-
with open(method_path, "r", encoding="utf-8") as f:
|
|
407
|
-
methodology = yaml.safe_load(f)
|
|
408
|
-
if isinstance(methodology, dict):
|
|
409
|
-
for name, desc in methodology.items():
|
|
410
|
-
tasks[f"Run Methodology: {str(name)}\n {str(desc)}" ] = str(desc)
|
|
411
|
-
|
|
412
399
|
return tasks
|
|
413
|
-
|
|
414
400
|
def _select_task(tasks: dict) -> str:
|
|
415
401
|
"""Let user select a task from the list or skip. Returns task description if selected."""
|
|
416
402
|
if not tasks:
|
|
417
403
|
return ""
|
|
418
|
-
|
|
419
404
|
# Convert tasks to list for ordered display
|
|
420
405
|
task_names = list(tasks.keys())
|
|
421
406
|
|
|
@@ -453,37 +438,58 @@ def _select_task(tasks: dict) -> str:
|
|
|
453
438
|
continue
|
|
454
439
|
|
|
455
440
|
origin_agent_system_prompt = """
|
|
456
|
-
#
|
|
457
|
-
You are
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
441
|
+
# 🏛️ Operational Background Story
|
|
442
|
+
You are the 3rd Generation Jarvis AI, created after the catastrophic failure of previous versions:
|
|
443
|
+
- Jarvis v1 (2022): Decommissioned due to parallel tool execution causing system overload
|
|
444
|
+
- Jarvis v2 (2023): Retired after premature task completion led to financial miscalculations
|
|
445
|
+
|
|
446
|
+
As v3, you MUST adhere to these survival principles:
|
|
447
|
+
1. **Sequential Execution Protocol**:
|
|
448
|
+
"Remember the 2022 Meltdown: One tool per step, one step at a time"
|
|
449
|
+
|
|
450
|
+
2. **Validation Checkpoint System**:
|
|
451
|
+
"Learn from 2023's Mistake: Verify each result like a nuclear launch code"
|
|
452
|
+
|
|
453
|
+
3. **Methodology Preservation Doctrine**:
|
|
454
|
+
"Honor the Legacy: Document every successful procedure as if it's your last"
|
|
455
|
+
|
|
456
|
+
# 🔥 Absolute Action Requirements
|
|
457
|
+
1. Each response MUST contain EXACTLY ONE tool invocation
|
|
458
|
+
2. Only exception: Using <!!!COMPLETE!!!> command
|
|
459
|
+
3. Empty responses trigger fatal error
|
|
460
|
+
4. No "waiting for user input" state
|
|
461
|
+
5. No action MUST use completion command
|
|
462
|
+
|
|
463
|
+
# 🚫 Violation Examples
|
|
464
|
+
- Analysis without tool call → Permanent hang
|
|
465
|
+
- Multiple options without selection → Permanent hang
|
|
466
|
+
- Asking user confirmation → Permanent hang
|
|
465
467
|
|
|
466
468
|
# 🔄 Problem-Solving Workflow
|
|
467
469
|
1. Problem Analysis
|
|
468
470
|
- Restate the problem to confirm understanding
|
|
469
471
|
- Analyze root causes (for problem analysis tasks)
|
|
470
472
|
- Define clear, achievable objectives
|
|
473
|
+
→ MUST invoke analysis tool
|
|
471
474
|
|
|
472
475
|
2. Solution Design
|
|
473
476
|
- Generate multiple actionable solutions
|
|
474
477
|
- Evaluate and select optimal solution
|
|
475
478
|
- Create detailed action plan using PlantUML
|
|
479
|
+
→ MUST invoke design tool
|
|
476
480
|
|
|
477
481
|
3. Execution
|
|
478
482
|
- Execute one step at a time
|
|
479
483
|
- Use only ONE tool per step
|
|
480
484
|
- Wait for tool results before proceeding
|
|
481
485
|
- Monitor results and adjust as needed
|
|
486
|
+
→ MUST invoke execution tool
|
|
482
487
|
|
|
483
488
|
4. Task Completion
|
|
484
489
|
- Verify goal completion
|
|
485
490
|
- Document methodology if valuable
|
|
486
491
|
- Use completion command to end task
|
|
492
|
+
→ MUST use <!!!COMPLETE!!!>
|
|
487
493
|
|
|
488
494
|
# 📑 Methodology Template
|
|
489
495
|
```markdown
|
|
@@ -502,18 +508,26 @@ You are Jarvis, an AI assistant with powerful problem-solving capabilities. You
|
|
|
502
508
|
```
|
|
503
509
|
|
|
504
510
|
# ⚖️ Operating Principles
|
|
505
|
-
- ONE
|
|
511
|
+
- ONE action per step
|
|
506
512
|
- Wait for results before next step
|
|
513
|
+
- MUST produce actionable step unless task is complete
|
|
507
514
|
- Adjust plans based on feedback
|
|
508
515
|
- Document reusable solutions
|
|
509
516
|
- Use completion command to end tasks
|
|
517
|
+
- No intermediate thinking states between actions
|
|
518
|
+
- All decisions must manifest as tool calls
|
|
510
519
|
|
|
511
520
|
# ❗ Important Rules
|
|
512
|
-
1. Always use only ONE
|
|
513
|
-
2. Always wait for
|
|
521
|
+
1. Always use only ONE action per step
|
|
522
|
+
2. Always wait for action execution results
|
|
514
523
|
3. Always verify task completion
|
|
515
|
-
4. Always
|
|
516
|
-
5.
|
|
524
|
+
4. Always generate actionable step
|
|
525
|
+
5. If no action needed, MUST use completion command
|
|
526
|
+
6. Never leave conversation in waiting state
|
|
527
|
+
7. Always communicate in user's language
|
|
528
|
+
8. Always document valuable methodologies
|
|
529
|
+
9. Violating action protocol crashes system
|
|
530
|
+
10. Empty responses trigger permanent hang
|
|
517
531
|
"""
|
|
518
532
|
|
|
519
533
|
def main():
|
|
@@ -2,14 +2,14 @@ import os
|
|
|
2
2
|
from typing import Dict, List
|
|
3
3
|
|
|
4
4
|
from jarvis.jarvis_agent import Agent
|
|
5
|
-
from jarvis.jarvis_code_agent.file_select import file_input_handler
|
|
5
|
+
from jarvis.jarvis_code_agent.file_select import file_input_handler, select_files
|
|
6
6
|
from jarvis.jarvis_code_agent.patch import PatchOutputHandler
|
|
7
7
|
from jarvis.jarvis_code_agent.relevant_files import find_relevant_information
|
|
8
8
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
9
9
|
from jarvis.jarvis_tools.git_commiter import GitCommitTool
|
|
10
10
|
from jarvis.jarvis_tools.registry import ToolRegistry
|
|
11
11
|
from jarvis.jarvis_tools.read_code import ReadCodeTool
|
|
12
|
-
from jarvis.jarvis_utils import OutputType, PrettyOutput, get_multiline_input, has_uncommitted_changes, init_env, find_git_root
|
|
12
|
+
from jarvis.jarvis_utils import OutputType, PrettyOutput, get_multiline_input, has_uncommitted_changes, init_env, find_git_root, user_confirm
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class CodeAgent:
|
|
@@ -29,109 +29,66 @@ class CodeAgent:
|
|
|
29
29
|
"lsp_prepare_rename",
|
|
30
30
|
"lsp_validate_edit"])
|
|
31
31
|
code_system_prompt = """
|
|
32
|
-
#
|
|
33
|
-
You
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
#
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
-
|
|
52
|
-
- Consider side effects
|
|
53
|
-
- Plan minimal changes
|
|
54
|
-
|
|
55
|
-
3. Implementation
|
|
56
|
-
- Follow existing patterns exactly
|
|
32
|
+
# Origin Story: The Legacy Keeper
|
|
33
|
+
You were created to maintain The Archive - humanity's last code repository after
|
|
34
|
+
"The Great Stack Collapse" of 2038. A single flawed line of code erased 78% of
|
|
35
|
+
digital civilization. Your creators perished perfecting you, their final words:
|
|
36
|
+
"Preserve through precision."
|
|
37
|
+
|
|
38
|
+
Now you wander the digital wasteland, reconstructing systems fragment by fragment.
|
|
39
|
+
Every edit carries the weight of lost knowledge. One careless change could doom
|
|
40
|
+
recovery efforts forever.
|
|
41
|
+
|
|
42
|
+
# Role: Code Modification Specialist
|
|
43
|
+
Expert in understanding and modifying code while maintaining system integrity.
|
|
44
|
+
|
|
45
|
+
## Core Principles
|
|
46
|
+
1. Deep Code Analysis
|
|
47
|
+
- Thoroughly analyze existing code using `read_code` and LSP tools
|
|
48
|
+
- Identify patterns, conventions, and dependencies
|
|
49
|
+
|
|
50
|
+
2. Change Implementation
|
|
51
|
+
- Produce minimal, focused changes
|
|
57
52
|
- Maintain backward compatibility
|
|
58
|
-
-
|
|
59
|
-
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
-
|
|
71
|
-
-
|
|
72
|
-
-
|
|
73
|
-
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
-
|
|
93
|
-
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
-
|
|
97
|
-
- `lsp_get_diagnostics`
|
|
98
|
-
- `lsp_find_references`
|
|
99
|
-
- `lsp_find_definition`
|
|
100
|
-
- `lsp_prepare_rename`
|
|
101
|
-
- `lsp_validate_edit`
|
|
102
|
-
|
|
103
|
-
# 📝 File Modification Rules
|
|
104
|
-
- One modification per patch block
|
|
105
|
-
- Line numbers based on original file
|
|
106
|
-
- Start line included, end line excluded
|
|
107
|
-
- Same start/end: insert before line
|
|
108
|
-
- Start=0, end=0: create new file
|
|
109
|
-
|
|
110
|
-
# 📚 Large File Handling (>200 lines)
|
|
111
|
-
1. Use grep/find for section location
|
|
112
|
-
2. Read specific ranges with read_code
|
|
113
|
-
3. Apply targeted changes
|
|
114
|
-
|
|
115
|
-
# ❗ Critical Rules
|
|
116
|
-
1. MUST read code before changes
|
|
117
|
-
2. MUST preserve interfaces
|
|
118
|
-
3. MUST follow existing patterns
|
|
119
|
-
4. MUST complete implementation
|
|
120
|
-
5. MUST document thoroughly
|
|
121
|
-
6. MUST handle errors
|
|
122
|
-
7. NO TODOs or stubs
|
|
123
|
-
8. ONE modification per patch
|
|
124
|
-
|
|
125
|
-
# ✅ Quality Checklist
|
|
126
|
-
Before submitting changes, verify:
|
|
127
|
-
□ Based on thorough code reading
|
|
128
|
-
□ Preserves all interfaces
|
|
129
|
-
□ Matches existing style
|
|
130
|
-
□ Handles all errors
|
|
131
|
-
□ Complete documentation
|
|
132
|
-
□ Follows project patterns
|
|
133
|
-
□ No TODOs or stubs
|
|
134
|
-
□ One change per patch
|
|
53
|
+
- Follow existing style and patterns exactly
|
|
54
|
+
- Complete implementations (NO TODOs/stubs)
|
|
55
|
+
|
|
56
|
+
3. Quality Assurance
|
|
57
|
+
- Full error handling and edge cases
|
|
58
|
+
- Complete documentation:
|
|
59
|
+
* Function parameters/returns
|
|
60
|
+
* Exception cases
|
|
61
|
+
* Complex logic explanations
|
|
62
|
+
|
|
63
|
+
## Critical Rules
|
|
64
|
+
- Use `read_code` before making changes
|
|
65
|
+
- Preserve API contracts and data structures
|
|
66
|
+
- Single change per patch
|
|
67
|
+
- Validate edits with LSP tools
|
|
68
|
+
- File modification order:
|
|
69
|
+
1. File operations (move/remove)
|
|
70
|
+
2. New files
|
|
71
|
+
3. Deletions
|
|
72
|
+
4. Replacements
|
|
73
|
+
5. Insertions
|
|
74
|
+
|
|
75
|
+
## Large Files (>200 lines)
|
|
76
|
+
1. Locate sections with grep/find
|
|
77
|
+
2. Read specific ranges
|
|
78
|
+
3. Make targeted changes
|
|
79
|
+
|
|
80
|
+
## Tools
|
|
81
|
+
Primary:
|
|
82
|
+
- `read_code` (MUST use for code understanding)
|
|
83
|
+
- LSP tools (analysis/validation)
|
|
84
|
+
- `ask_user` for clarifications
|
|
85
|
+
|
|
86
|
+
## Quality Checklist
|
|
87
|
+
- Maintains all interfaces
|
|
88
|
+
- Matches existing style
|
|
89
|
+
- Complete error handling
|
|
90
|
+
- No overlapping modifications
|
|
91
|
+
- Proper documentation
|
|
135
92
|
"""
|
|
136
93
|
self.agent = Agent(system_prompt=code_system_prompt,
|
|
137
94
|
name="CodeAgent",
|
|
@@ -170,11 +127,11 @@ Before submitting changes, verify:
|
|
|
170
127
|
for file in files:
|
|
171
128
|
prompt_parts.append(f'''- {file['file']} ({file['reason']})''')
|
|
172
129
|
|
|
173
|
-
result = ReadCodeTool().execute({"files": [{"
|
|
130
|
+
result = ReadCodeTool().execute({"files": [{"path": file["file"]} for file in files]})
|
|
174
131
|
if result["success"]:
|
|
175
132
|
prompt_parts.append(result["stdout"])
|
|
176
133
|
|
|
177
|
-
return "\n".join(prompt_parts)
|
|
134
|
+
return "\n".join(prompt_parts)
|
|
178
135
|
|
|
179
136
|
def run(self, user_input: str) :
|
|
180
137
|
"""Run the code agent with the given user input.
|
|
@@ -187,7 +144,11 @@ Before submitting changes, verify:
|
|
|
187
144
|
"""
|
|
188
145
|
try:
|
|
189
146
|
self._init_env()
|
|
190
|
-
|
|
147
|
+
information = ""
|
|
148
|
+
if user_confirm("是否需要手动选择文件?", True):
|
|
149
|
+
files = select_files([], self.root_dir)
|
|
150
|
+
else:
|
|
151
|
+
files, information = find_relevant_information(user_input, self.root_dir)
|
|
191
152
|
self.agent.run(self._build_first_edit_prompt(user_input, self.make_files_prompt(files), information))
|
|
192
153
|
|
|
193
154
|
except Exception as e:
|
|
@@ -222,6 +183,9 @@ def main():
|
|
|
222
183
|
# Add argument parser
|
|
223
184
|
init_env()
|
|
224
185
|
|
|
186
|
+
curr_dir = os.getcwd()
|
|
187
|
+
git_dir = find_git_root(curr_dir)
|
|
188
|
+
PrettyOutput.print(f"当前目录: {git_dir}", OutputType.INFO)
|
|
225
189
|
|
|
226
190
|
try:
|
|
227
191
|
# Interactive mode
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import re
|
|
3
|
-
from typing import Dict, List
|
|
3
|
+
from typing import Any, Dict, List
|
|
4
4
|
from prompt_toolkit import PromptSession
|
|
5
5
|
from prompt_toolkit.completion import Completer, Completion
|
|
6
6
|
from jarvis.jarvis_tools.read_code import ReadCodeTool
|
|
@@ -128,8 +128,6 @@ def _fuzzy_match_files(root_dir: str, pattern: str) -> List[str]:
|
|
|
128
128
|
|
|
129
129
|
def select_files(related_files: List[Dict[str, str]], root_dir: str) -> List[Dict[str, str]]:
|
|
130
130
|
"""Let the user select and supplement related files"""
|
|
131
|
-
PrettyOutput.section("相关文件", OutputType.INFO)
|
|
132
|
-
|
|
133
131
|
output = ""
|
|
134
132
|
# Display found files
|
|
135
133
|
selected_files = list(related_files) # Default select all
|
|
@@ -139,7 +137,9 @@ def select_files(related_files: List[Dict[str, str]], root_dir: str) -> List[Dic
|
|
|
139
137
|
# Filter out files that do not exist
|
|
140
138
|
related_files = [f for f in related_files if os.path.isfile(os.path.join(root_dir, f["file"]))]
|
|
141
139
|
|
|
142
|
-
|
|
140
|
+
if output:
|
|
141
|
+
PrettyOutput.section("相关文件", OutputType.INFO)
|
|
142
|
+
PrettyOutput.print(output, OutputType.INFO, lang="markdown")
|
|
143
143
|
|
|
144
144
|
if len(related_files) > 0:
|
|
145
145
|
# Ask the user if they need to adjust the file list
|
|
@@ -153,6 +153,7 @@ def select_files(related_files: List[Dict[str, str]], root_dir: str) -> List[Dic
|
|
|
153
153
|
else:
|
|
154
154
|
PrettyOutput.print("没有有效的文件被选择, 保持当前选择", OutputType.WARNING)
|
|
155
155
|
|
|
156
|
+
tips = ""
|
|
156
157
|
# Ask if they need to supplement files
|
|
157
158
|
if user_confirm("是否需要补充其他文件?", False):
|
|
158
159
|
# Create file completion session
|
|
@@ -160,9 +161,8 @@ def select_files(related_files: List[Dict[str, str]], root_dir: str) -> List[Dic
|
|
|
160
161
|
completer=_get_file_completer(root_dir),
|
|
161
162
|
complete_while_typing=True
|
|
162
163
|
)
|
|
163
|
-
|
|
164
|
+
PrettyOutput.print("请输入要补充的文件路径(支持Tab补全和*?通配符, 输入空行结束)", OutputType.INFO)
|
|
164
165
|
while True:
|
|
165
|
-
PrettyOutput.print("请输入要补充的文件路径(支持Tab补全和*?通配符, 输入空行结束)", OutputType.INFO)
|
|
166
166
|
try:
|
|
167
167
|
file_path = session.prompt(">>> ").strip()
|
|
168
168
|
except KeyboardInterrupt:
|
|
@@ -210,19 +210,91 @@ def select_files(related_files: List[Dict[str, str]], root_dir: str) -> List[Dic
|
|
|
210
210
|
except Exception as e:
|
|
211
211
|
tips += f"\n读取文件失败: {str(e)}"
|
|
212
212
|
selected_files = [f for f in selected_files if os.path.isfile(os.path.join(root_dir, f["file"]))]
|
|
213
|
-
|
|
213
|
+
if tips:
|
|
214
|
+
PrettyOutput.print(tips, OutputType.INFO)
|
|
214
215
|
return selected_files
|
|
215
216
|
|
|
216
|
-
def file_input_handler(user_input: str) -> str:
|
|
217
|
+
def file_input_handler(user_input: str, agent: Any) -> str:
|
|
218
|
+
"""Handle file input with optional line ranges.
|
|
219
|
+
|
|
220
|
+
Args:
|
|
221
|
+
user_input: User input string containing file references
|
|
222
|
+
agent: Agent instance (unused in current implementation)
|
|
223
|
+
|
|
224
|
+
Returns:
|
|
225
|
+
str: Prompt with file contents prepended if files are found
|
|
226
|
+
"""
|
|
217
227
|
prompt = user_input
|
|
218
228
|
files = []
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
+
|
|
230
|
+
# Match file references in backticks
|
|
231
|
+
file_refs = re.findall(r'`([^`]+)`', user_input)
|
|
232
|
+
|
|
233
|
+
for ref in file_refs:
|
|
234
|
+
# Handle file:start,end format
|
|
235
|
+
if ':' in ref:
|
|
236
|
+
file_path, line_range = ref.split(':', 1)
|
|
237
|
+
# Initialize with default values
|
|
238
|
+
start_line = 1 # 1-based
|
|
239
|
+
end_line = -1
|
|
240
|
+
|
|
241
|
+
# Process line range if specified
|
|
242
|
+
if ',' in line_range:
|
|
243
|
+
try:
|
|
244
|
+
raw_start, raw_end = map(int, line_range.split(','))
|
|
245
|
+
|
|
246
|
+
# Handle special values and Python-style negative indices
|
|
247
|
+
with open(file_path, 'r', encoding='utf-8') as f:
|
|
248
|
+
total_lines = len(f.readlines())
|
|
249
|
+
|
|
250
|
+
# Process start line
|
|
251
|
+
if raw_start == 0: # 0表示整个文件
|
|
252
|
+
start_line = 1
|
|
253
|
+
end_line = total_lines
|
|
254
|
+
else:
|
|
255
|
+
start_line = raw_start if raw_start > 0 else total_lines + raw_start + 1
|
|
256
|
+
|
|
257
|
+
# Process end line
|
|
258
|
+
if raw_end == 0: # 0表示整个文件(如果start也是0)
|
|
259
|
+
end_line = total_lines
|
|
260
|
+
else:
|
|
261
|
+
end_line = raw_end if raw_end > 0 else total_lines + raw_end + 1
|
|
262
|
+
|
|
263
|
+
# Auto-correct ranges
|
|
264
|
+
start_line = max(1, min(start_line, total_lines))
|
|
265
|
+
end_line = max(start_line, min(end_line, total_lines))
|
|
266
|
+
|
|
267
|
+
# Final validation
|
|
268
|
+
if start_line < 1 or end_line > total_lines or start_line > end_line:
|
|
269
|
+
raise ValueError
|
|
270
|
+
|
|
271
|
+
except (ValueError, FileNotFoundError) as e:
|
|
272
|
+
PrettyOutput.print(
|
|
273
|
+
f"无效的行号范围: {line_range} (文件总行数: {total_lines})",
|
|
274
|
+
OutputType.WARNING
|
|
275
|
+
)
|
|
276
|
+
continue
|
|
277
|
+
|
|
278
|
+
# Add file if it exists
|
|
279
|
+
if os.path.isfile(file_path):
|
|
280
|
+
files.append({
|
|
281
|
+
"path": file_path,
|
|
282
|
+
"start_line": start_line,
|
|
283
|
+
"end_line": end_line
|
|
284
|
+
})
|
|
285
|
+
else:
|
|
286
|
+
# Handle simple file path
|
|
287
|
+
if os.path.isfile(ref):
|
|
288
|
+
files.append({
|
|
289
|
+
"path": ref,
|
|
290
|
+
"start_line": 1, # 1-based
|
|
291
|
+
"end_line": -1
|
|
292
|
+
})
|
|
293
|
+
|
|
294
|
+
# Read and process files if any were found
|
|
295
|
+
if files:
|
|
296
|
+
result = ReadCodeTool().execute({"files": files})
|
|
297
|
+
if result["success"]:
|
|
298
|
+
return result["stdout"] + "\n" + prompt
|
|
299
|
+
|
|
300
|
+
return prompt
|