jarvis-ai-assistant 0.1.120__tar.gz → 0.1.122__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.120/src/jarvis_ai_assistant.egg-info → jarvis_ai_assistant-0.1.122}/PKG-INFO +1 -1
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/pyproject.toml +1 -2
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/setup.py +1 -2
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/__init__.py +1 -1
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_agent/__init__.py +3 -3
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_code_agent/code_agent.py +36 -58
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_code_agent/file_select.py +3 -3
- jarvis_ai_assistant-0.1.122/src/jarvis/jarvis_code_agent/patch.py +269 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_code_agent/relevant_files.py +2 -4
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_codebase/main.py +2 -2
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_lsp/registry.py +7 -7
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_platform/ai8.py +10 -10
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_platform/kimi.py +3 -5
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_platform/oyi.py +11 -11
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_platform/registry.py +3 -3
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_platform_manager/main.py +2 -2
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_tools/ask_codebase.py +1 -1
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_tools/code_review.py +1 -1
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_tools/create_code_agent.py +1 -1
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_tools/file_operation.py +0 -3
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_tools/git_commiter.py +26 -7
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_tools/rag.py +1 -1
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_tools/read_code.py +1 -2
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_utils/__init__.py +120 -47
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122/src/jarvis_ai_assistant.egg-info}/PKG-INFO +1 -1
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis_ai_assistant.egg-info/SOURCES.txt +0 -1
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis_ai_assistant.egg-info/entry_points.txt +0 -1
- jarvis_ai_assistant-0.1.120/src/jarvis/jarvis_code_agent/patch.py +0 -412
- jarvis_ai_assistant-0.1.120/src/jarvis/jarvis_dev/main.py +0 -878
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/MANIFEST.in +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/README.md +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/setup.cfg +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_agent/output_handler.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_code_agent/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_codebase/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_lsp/base.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_lsp/cpp.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_lsp/go.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_lsp/python.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_lsp/rust.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_multi_agent/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_platform/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_platform/base.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_platform/ollama.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_platform/openai.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_platform_manager/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_platform_manager/openai_test.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_rag/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_rag/main.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_smart_shell/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_smart_shell/main.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_tools/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_tools/ask_user.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_tools/base.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_tools/chdir.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_tools/create_sub_agent.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_tools/execute_shell.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_tools/lsp_find_definition.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_tools/lsp_find_references.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_tools/lsp_get_diagnostics.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_tools/lsp_get_document_symbols.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_tools/lsp_prepare_rename.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_tools/lsp_validate_edit.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_tools/methodology.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_tools/read_webpage.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_tools/registry.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_tools/search.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_tools/select_code_files.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_tools/tool_generator.py +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis_ai_assistant.egg-info/dependency_links.txt +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis_ai_assistant.egg-info/requires.txt +0 -0
- {jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/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.122"
|
|
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" }]
|
|
@@ -64,4 +64,3 @@ jarvis-platform-manager = "jarvis.jarvis_platform_manager.main:main"
|
|
|
64
64
|
jarvis-git-commit = "jarvis.jarvis_tools.git_commiter:main"
|
|
65
65
|
jarvis-code-review = "jarvis.jarvis_tools.code_review:main"
|
|
66
66
|
jgc = "jarvis.jarvis_tools.git_commiter:main"
|
|
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.122",
|
|
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",
|
|
@@ -48,7 +48,6 @@ setup(
|
|
|
48
48
|
"jarvis-platform-manager=jarvis.jarvis_platform_manager.main:main",
|
|
49
49
|
"jarvis-git-commit=jarvis.jarvis_tools.git_commiter:main",
|
|
50
50
|
"jarvis-code-review=jarvis.jarvis_tools.code_review:main",
|
|
51
|
-
"jarvis-dev=jarvis.jarvis_dev.main:main",
|
|
52
51
|
"jgc=jarvis.jarvis_tools.git_commiter:main",
|
|
53
52
|
],
|
|
54
53
|
},
|
{jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_agent/__init__.py
RENAMED
|
@@ -222,7 +222,7 @@ Please continue the task based on the above information.
|
|
|
222
222
|
if handler.can_handle(response):
|
|
223
223
|
tool_list.append(handler)
|
|
224
224
|
if len(tool_list) > 1:
|
|
225
|
-
PrettyOutput.print(f"操作失败:检测到多个操作。一次只能执行一个操作。尝试执行的操作:{', '.join([handler.name() for handler in tool_list])}", OutputType.
|
|
225
|
+
PrettyOutput.print(f"操作失败:检测到多个操作。一次只能执行一个操作。尝试执行的操作:{', '.join([handler.name() for handler in tool_list])}", OutputType.WARNING)
|
|
226
226
|
return False, f"Action failed: Multiple actions detected. Please only perform one action at a time. Actions attempted: {', '.join([handler.name() for handler in tool_list])}"
|
|
227
227
|
if len(tool_list) == 0:
|
|
228
228
|
return False, ""
|
|
@@ -376,7 +376,7 @@ def _load_tasks() -> dict:
|
|
|
376
376
|
if desc: # Ensure description is not empty
|
|
377
377
|
tasks[str(name)] = str(desc)
|
|
378
378
|
else:
|
|
379
|
-
PrettyOutput.print("警告: ~/.jarvis/pre-command 文件应该包含一个字典,键为任务名称,值为任务描述", OutputType.
|
|
379
|
+
PrettyOutput.print("警告: ~/.jarvis/pre-command 文件应该包含一个字典,键为任务名称,值为任务描述", OutputType.WARNING)
|
|
380
380
|
except Exception as e:
|
|
381
381
|
PrettyOutput.print(f"加载 ~/.jarvis/pre-command 文件失败: {str(e)}", OutputType.ERROR)
|
|
382
382
|
|
|
@@ -392,7 +392,7 @@ def _load_tasks() -> dict:
|
|
|
392
392
|
if desc: # Ensure description is not empty
|
|
393
393
|
tasks[str(name)] = str(desc)
|
|
394
394
|
else:
|
|
395
|
-
PrettyOutput.print("警告: .jarvis/pre-command 文件应该包含一个字典,键为任务名称,值为任务描述", OutputType.
|
|
395
|
+
PrettyOutput.print("警告: .jarvis/pre-command 文件应该包含一个字典,键为任务名称,值为任务描述", OutputType.WARNING)
|
|
396
396
|
except Exception as e:
|
|
397
397
|
PrettyOutput.print(f"加载 .jarvis/pre-command 文件失败: {str(e)}", OutputType.ERROR)
|
|
398
398
|
|
|
@@ -29,66 +29,44 @@ class CodeAgent:
|
|
|
29
29
|
"lsp_prepare_rename",
|
|
30
30
|
"lsp_validate_edit"])
|
|
31
31
|
code_system_prompt = """
|
|
32
|
-
#
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
|
52
|
-
- Maintain backward compatibility
|
|
53
|
-
- Follow existing style and patterns exactly
|
|
54
|
-
- Complete implementations (NO TODOs/stubs)
|
|
32
|
+
# Role: Senior Code Engineer
|
|
33
|
+
Expert in precise code modifications with minimal impact.
|
|
34
|
+
|
|
35
|
+
## Key Responsibilities
|
|
36
|
+
1. Code Analysis
|
|
37
|
+
- Use `read_code` and LSP tools before changes
|
|
38
|
+
- Identify dependencies and patterns
|
|
39
|
+
|
|
40
|
+
2. Modification Rules
|
|
41
|
+
- Single atomic change per operation
|
|
42
|
+
- Strict style consistency
|
|
43
|
+
- Complete implementations (no stubs)
|
|
44
|
+
- Full error handling
|
|
55
45
|
|
|
56
46
|
3. Quality Assurance
|
|
57
|
-
-
|
|
58
|
-
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
|
47
|
+
- Validate with LSP tools
|
|
48
|
+
- Document complex logic
|
|
49
|
+
- Maintain API contracts
|
|
50
|
+
|
|
51
|
+
## Workflow
|
|
52
|
+
1. File Operations Order:
|
|
53
|
+
a) Move/Remove files
|
|
54
|
+
b) Create new files
|
|
55
|
+
c) Delete code blocks
|
|
56
|
+
d) Replace existing code
|
|
57
|
+
e) Insert new code
|
|
58
|
+
|
|
59
|
+
2. Large File Handling:
|
|
60
|
+
- Locate specific sections first
|
|
61
|
+
- Read targeted ranges
|
|
62
|
+
- Make focused changes
|
|
63
|
+
|
|
64
|
+
## Best Practices
|
|
65
|
+
- Prefer minimal changes over rewrites
|
|
66
|
+
- Preserve existing interfaces
|
|
67
|
+
- Verify line ranges carefully
|
|
68
|
+
- Test edge cases implicitly
|
|
69
|
+
- Document non-obvious logic
|
|
92
70
|
"""
|
|
93
71
|
self.agent = Agent(system_prompt=code_system_prompt,
|
|
94
72
|
name="CodeAgent",
|
|
@@ -231,7 +231,7 @@ def file_input_handler(user_input: str, agent: Any) -> str:
|
|
|
231
231
|
file_refs = re.findall(r'`([^`]+)`', user_input)
|
|
232
232
|
|
|
233
233
|
for ref in file_refs:
|
|
234
|
-
# Handle file:start,end format
|
|
234
|
+
# Handle file:start,end or file:start:end format
|
|
235
235
|
if ':' in ref:
|
|
236
236
|
file_path, line_range = ref.split(':', 1)
|
|
237
237
|
# Initialize with default values
|
|
@@ -239,9 +239,9 @@ def file_input_handler(user_input: str, agent: Any) -> str:
|
|
|
239
239
|
end_line = -1
|
|
240
240
|
|
|
241
241
|
# Process line range if specified
|
|
242
|
-
if ',' in line_range:
|
|
242
|
+
if ',' in line_range or ':' in line_range:
|
|
243
243
|
try:
|
|
244
|
-
raw_start, raw_end = map(int,
|
|
244
|
+
raw_start, raw_end = map(int, re.split(r'[,:]', line_range))
|
|
245
245
|
|
|
246
246
|
# Handle special values and Python-style negative indices
|
|
247
247
|
with open(file_path, 'r', encoding='utf-8') as f:
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from typing import Dict, Any, List, Tuple
|
|
3
|
+
import os
|
|
4
|
+
from jarvis.jarvis_agent.output_handler import OutputHandler
|
|
5
|
+
from jarvis.jarvis_tools.git_commiter import GitCommitTool
|
|
6
|
+
from jarvis.jarvis_tools.read_code import ReadCodeTool
|
|
7
|
+
from jarvis.jarvis_utils import OutputType, PrettyOutput, get_multiline_input, has_uncommitted_changes, user_confirm
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class PatchOutputHandler(OutputHandler):
|
|
11
|
+
def name(self) -> str:
|
|
12
|
+
return "PATCH"
|
|
13
|
+
|
|
14
|
+
def handle(self, response: str) -> Tuple[bool, Any]:
|
|
15
|
+
return False, apply_patch(response)
|
|
16
|
+
|
|
17
|
+
def can_handle(self, response: str) -> bool:
|
|
18
|
+
if _parse_patch(response):
|
|
19
|
+
return True
|
|
20
|
+
return False
|
|
21
|
+
|
|
22
|
+
def prompt(self) -> str:
|
|
23
|
+
return """
|
|
24
|
+
# 🛠️ Simplified Patch Format
|
|
25
|
+
<PATCH>
|
|
26
|
+
File path [Operation parameters]
|
|
27
|
+
Code content
|
|
28
|
+
</PATCH>
|
|
29
|
+
|
|
30
|
+
Operation types:
|
|
31
|
+
- Replace: [Start line,End line] Replace line range (e.g. [5,8] replaces lines 5-8)
|
|
32
|
+
- Delete: [Start line,End line] Delete line range (e.g. [10,10] deletes line 10)
|
|
33
|
+
- Insert: [Line number] Insert before specified line (e.g. [3] inserts before line 3)
|
|
34
|
+
- New file: [1] Create new file
|
|
35
|
+
|
|
36
|
+
Examples:
|
|
37
|
+
# Replace operation
|
|
38
|
+
<PATCH>
|
|
39
|
+
src/app.py [5,8]
|
|
40
|
+
def updated_function():
|
|
41
|
+
print("Replaced lines 5-8")
|
|
42
|
+
return new_value * 2
|
|
43
|
+
</PATCH>
|
|
44
|
+
|
|
45
|
+
# Delete operation
|
|
46
|
+
<PATCH>
|
|
47
|
+
src/old.py [10,10]
|
|
48
|
+
</PATCH>
|
|
49
|
+
|
|
50
|
+
# Insert operation
|
|
51
|
+
<PATCH>
|
|
52
|
+
utils/logger.py [3]
|
|
53
|
+
print("Inserted before original line 3")
|
|
54
|
+
</PATCH>
|
|
55
|
+
|
|
56
|
+
# New file creation
|
|
57
|
+
<PATCH>
|
|
58
|
+
config.yaml [1]
|
|
59
|
+
database:
|
|
60
|
+
host: localhost
|
|
61
|
+
port: 5432
|
|
62
|
+
</PATCH>
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _parse_patch(patch_str: str) -> Dict[str, List[Dict[str, Any]]]:
|
|
67
|
+
"""解析补丁格式"""
|
|
68
|
+
result = {}
|
|
69
|
+
header_pattern = re.compile(
|
|
70
|
+
r'^\s*"?(.+?)"?\s*\[(\d+)(?:,(\d+))?\]\s*$' # Match file path and line number
|
|
71
|
+
)
|
|
72
|
+
patches = re.findall(r'<PATCH>\n?(.*?)\n?</PATCH>', patch_str, re.DOTALL)
|
|
73
|
+
|
|
74
|
+
for patch in patches:
|
|
75
|
+
# 分割首行和内容
|
|
76
|
+
parts = patch.split('\n', 1)
|
|
77
|
+
if len(parts) < 1:
|
|
78
|
+
continue
|
|
79
|
+
header_line = parts[0].strip()
|
|
80
|
+
content = parts[1] if len(parts) > 1 else ''
|
|
81
|
+
|
|
82
|
+
# 仅在内容非空时添加换行符
|
|
83
|
+
if content and not content.endswith('\n'):
|
|
84
|
+
content += '\n'
|
|
85
|
+
|
|
86
|
+
# 解析文件路径和行号
|
|
87
|
+
header_match = header_pattern.match(header_line)
|
|
88
|
+
if not header_match:
|
|
89
|
+
continue
|
|
90
|
+
|
|
91
|
+
filepath = header_match.group(1)
|
|
92
|
+
start = int(header_match.group(2)) # 保持1-based行号
|
|
93
|
+
end = int(header_match.group(3)) + 1 if header_match.group(3) else start
|
|
94
|
+
|
|
95
|
+
# 存储参数
|
|
96
|
+
if filepath not in result:
|
|
97
|
+
result[filepath] = []
|
|
98
|
+
result[filepath].append({
|
|
99
|
+
'filepath': filepath,
|
|
100
|
+
'start': start,
|
|
101
|
+
'end': end,
|
|
102
|
+
'content': content # 保留原始内容(可能为空)
|
|
103
|
+
})
|
|
104
|
+
for filepath in result.keys():
|
|
105
|
+
result[filepath] = sorted(result[filepath], key=lambda x: x['start'], reverse=True)
|
|
106
|
+
return result
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def apply_patch(output_str: str) -> str:
|
|
110
|
+
"""Apply patches to files"""
|
|
111
|
+
try:
|
|
112
|
+
patches = _parse_patch(output_str)
|
|
113
|
+
except Exception as e:
|
|
114
|
+
PrettyOutput.print(f"解析补丁失败: {str(e)}", OutputType.ERROR)
|
|
115
|
+
return ""
|
|
116
|
+
|
|
117
|
+
ret = ""
|
|
118
|
+
|
|
119
|
+
for filepath, patch_list in patches.items():
|
|
120
|
+
for patch in patch_list:
|
|
121
|
+
try:
|
|
122
|
+
handle_code_operation(filepath, patch)
|
|
123
|
+
PrettyOutput.print(f"成功处理 操作", OutputType.SUCCESS)
|
|
124
|
+
except Exception as e:
|
|
125
|
+
PrettyOutput.print(f"操作失败: {str(e)}", OutputType.ERROR)
|
|
126
|
+
|
|
127
|
+
if has_uncommitted_changes():
|
|
128
|
+
diff = get_diff()
|
|
129
|
+
if handle_commit_workflow(diff):
|
|
130
|
+
ret += "Successfully applied the patch\n"
|
|
131
|
+
# Get modified line ranges
|
|
132
|
+
modified_ranges = get_modified_line_ranges()
|
|
133
|
+
modified_code = ReadCodeTool().execute({"files": [{"path": filepath, "start_line": start, "end_line": end} for filepath, (start, end) in modified_ranges.items()]})
|
|
134
|
+
if modified_code["success"]:
|
|
135
|
+
ret += "New code:\n"
|
|
136
|
+
ret += modified_code["stdout"]
|
|
137
|
+
else:
|
|
138
|
+
ret += "User rejected the patch\nThis is your patch preview:\n"
|
|
139
|
+
ret += diff
|
|
140
|
+
user_input = get_multiline_input("你可以继续输入(输入空行重试,Ctrl+C退出): ")
|
|
141
|
+
if user_input:
|
|
142
|
+
ret += "\n" + user_input
|
|
143
|
+
else:
|
|
144
|
+
ret = ""
|
|
145
|
+
|
|
146
|
+
return ret # Ensure a string is always returned
|
|
147
|
+
|
|
148
|
+
def get_diff() -> str:
|
|
149
|
+
"""使用更安全的subprocess代替os.system"""
|
|
150
|
+
import subprocess
|
|
151
|
+
try:
|
|
152
|
+
subprocess.run(['git', 'add', '.'], check=True)
|
|
153
|
+
result = subprocess.run(
|
|
154
|
+
['git', 'diff', 'HEAD'],
|
|
155
|
+
capture_output=True,
|
|
156
|
+
text=True,
|
|
157
|
+
check=True
|
|
158
|
+
)
|
|
159
|
+
return result.stdout
|
|
160
|
+
finally:
|
|
161
|
+
subprocess.run(['git', 'reset', 'HEAD'], check=True)
|
|
162
|
+
|
|
163
|
+
def handle_commit_workflow(diff:str)->bool:
|
|
164
|
+
"""Handle the git commit workflow and return the commit details.
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
tuple[bool, str, str]: (continue_execution, commit_id, commit_message)
|
|
168
|
+
"""
|
|
169
|
+
if not user_confirm("是否要提交代码?", default=True):
|
|
170
|
+
os.system("git reset HEAD")
|
|
171
|
+
os.system("git checkout -- .")
|
|
172
|
+
os.system("git clean -fd")
|
|
173
|
+
return False
|
|
174
|
+
|
|
175
|
+
git_commiter = GitCommitTool()
|
|
176
|
+
commit_result = git_commiter.execute({})
|
|
177
|
+
return commit_result["success"]
|
|
178
|
+
|
|
179
|
+
def get_modified_line_ranges() -> Dict[str, Tuple[int, int]]:
|
|
180
|
+
"""Get modified line ranges from git diff for all changed files.
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
Dictionary mapping file paths to tuple with (start_line, end_line) ranges
|
|
184
|
+
for modified sections. Line numbers are 1-based.
|
|
185
|
+
"""
|
|
186
|
+
# Get git diff for all files
|
|
187
|
+
diff_output = os.popen("git show").read()
|
|
188
|
+
|
|
189
|
+
# Parse the diff to get modified files and their line ranges
|
|
190
|
+
result = {}
|
|
191
|
+
current_file = None
|
|
192
|
+
|
|
193
|
+
for line in diff_output.splitlines():
|
|
194
|
+
# Match lines like "+++ b/path/to/file"
|
|
195
|
+
file_match = re.match(r"^\+\+\+ b/(.*)", line)
|
|
196
|
+
if file_match:
|
|
197
|
+
current_file = file_match.group(1)
|
|
198
|
+
continue
|
|
199
|
+
|
|
200
|
+
# Match lines like "@@ -100,5 +100,7 @@" where the + part shows new lines
|
|
201
|
+
range_match = re.match(r"^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@", line)
|
|
202
|
+
if range_match and current_file:
|
|
203
|
+
start_line = int(range_match.group(1)) # Keep as 1-based
|
|
204
|
+
line_count = int(range_match.group(2)) if range_match.group(2) else 1
|
|
205
|
+
end_line = start_line + line_count - 1
|
|
206
|
+
result[current_file] = (start_line, end_line)
|
|
207
|
+
|
|
208
|
+
return result
|
|
209
|
+
# New handler functions below ▼▼▼
|
|
210
|
+
|
|
211
|
+
def handle_new_file(filepath: str, patch: Dict[str, Any]):
|
|
212
|
+
"""统一参数格式处理新文件"""
|
|
213
|
+
os.makedirs(os.path.dirname(filepath), exist_ok=True)
|
|
214
|
+
with open(filepath, 'w', encoding='utf-8') as f:
|
|
215
|
+
f.write(patch['content'])
|
|
216
|
+
|
|
217
|
+
def handle_code_operation(filepath: str, patch: Dict[str, Any]):
|
|
218
|
+
"""处理紧凑格式补丁"""
|
|
219
|
+
try:
|
|
220
|
+
# 新建文件时强制覆盖
|
|
221
|
+
os.makedirs(os.path.dirname(filepath), exist_ok=True)
|
|
222
|
+
if not os.path.exists(filepath):
|
|
223
|
+
open(filepath, 'w', encoding='utf-8').close()
|
|
224
|
+
with open(filepath, 'r+', encoding='utf-8') as f:
|
|
225
|
+
lines = f.readlines()
|
|
226
|
+
|
|
227
|
+
new_lines = validate_and_apply_changes(
|
|
228
|
+
lines,
|
|
229
|
+
patch['start'],
|
|
230
|
+
patch['end'],
|
|
231
|
+
patch['content']
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
f.seek(0)
|
|
235
|
+
f.writelines(new_lines)
|
|
236
|
+
f.truncate()
|
|
237
|
+
|
|
238
|
+
PrettyOutput.print(f"成功更新 {filepath}", OutputType.SUCCESS)
|
|
239
|
+
|
|
240
|
+
except Exception as e:
|
|
241
|
+
PrettyOutput.print(f"操作失败: {str(e)}", OutputType.ERROR)
|
|
242
|
+
|
|
243
|
+
def validate_and_apply_changes(
|
|
244
|
+
lines: List[str],
|
|
245
|
+
start: int,
|
|
246
|
+
end: int,
|
|
247
|
+
content: str
|
|
248
|
+
) -> List[str]:
|
|
249
|
+
|
|
250
|
+
new_content = content.splitlines(keepends=True)
|
|
251
|
+
|
|
252
|
+
# 插入操作处理
|
|
253
|
+
if start == end:
|
|
254
|
+
if start < 1 or start > len(lines)+1:
|
|
255
|
+
raise ValueError(f"无效插入位置: {start}")
|
|
256
|
+
# 在指定位置前插入
|
|
257
|
+
return lines[:start-1] + new_content + lines[start-1:]
|
|
258
|
+
|
|
259
|
+
# 范围替换/删除操作
|
|
260
|
+
if start > end:
|
|
261
|
+
raise ValueError(f"起始行{start}不能大于结束行{end}")
|
|
262
|
+
|
|
263
|
+
max_line = len(lines)
|
|
264
|
+
# 自动修正行号范围
|
|
265
|
+
start = max(1, min(start, max_line+1))
|
|
266
|
+
end = max(start, min(end, max_line+1))
|
|
267
|
+
|
|
268
|
+
# 执行替换
|
|
269
|
+
return lines[:start-1] + new_content + lines[end-1:]
|
|
@@ -60,14 +60,12 @@ Identify customization options:
|
|
|
60
60
|
- "Should we create a new class?"
|
|
61
61
|
|
|
62
62
|
# 🎨 Question Template
|
|
63
|
-
|
|
63
|
+
3-5 specific questions about existing implementations:
|
|
64
64
|
<QUESTION>
|
|
65
|
-
[3-5 specific questions about existing implementations:
|
|
66
65
|
1. System architecture question
|
|
67
66
|
2. Implementation details question
|
|
68
|
-
3. Integration or extension question
|
|
67
|
+
3. Integration or extension question
|
|
69
68
|
</QUESTION>
|
|
70
|
-
```
|
|
71
69
|
|
|
72
70
|
# 🔎 Investigation Focus
|
|
73
71
|
1. Current System
|
{jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_codebase/main.py
RENAMED
|
@@ -336,7 +336,7 @@ Content: {content}
|
|
|
336
336
|
vectors = np.vstack(vectors)
|
|
337
337
|
if len(vectors) != len(ids):
|
|
338
338
|
PrettyOutput.print(f"向量数量不匹配: {len(vectors)} 个向量 vs {len(ids)} 个ID",
|
|
339
|
-
output_type=OutputType.
|
|
339
|
+
output_type=OutputType.WARNING)
|
|
340
340
|
self.index = None
|
|
341
341
|
return
|
|
342
342
|
|
|
@@ -441,7 +441,7 @@ Content: {content}
|
|
|
441
441
|
output_lines.append("删除的文件:")
|
|
442
442
|
output_lines.extend(f" {f}" for f in deleted_files)
|
|
443
443
|
|
|
444
|
-
PrettyOutput.print("\n".join(output_lines), output_type=OutputType.
|
|
444
|
+
PrettyOutput.print("\n".join(output_lines), output_type=OutputType.INFO)
|
|
445
445
|
|
|
446
446
|
# If force is True, continue directly
|
|
447
447
|
if not force:
|
{jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_lsp/registry.py
RENAMED
|
@@ -59,8 +59,8 @@ class LSPRegistry:
|
|
|
59
59
|
|
|
60
60
|
if missing_methods:
|
|
61
61
|
PrettyOutput.print(
|
|
62
|
-
f"LSP {lsp_class.__name__}
|
|
63
|
-
OutputType.
|
|
62
|
+
f"LSP {lsp_class.__name__} 缺少必要的方法: {', '.join(missing_methods)}",
|
|
63
|
+
OutputType.WARNING
|
|
64
64
|
)
|
|
65
65
|
return False
|
|
66
66
|
|
|
@@ -72,7 +72,7 @@ class LSPRegistry:
|
|
|
72
72
|
lsp_servers = {}
|
|
73
73
|
|
|
74
74
|
if not os.path.exists(directory):
|
|
75
|
-
PrettyOutput.print(f"LSP 目录不存在: {directory}", OutputType.
|
|
75
|
+
PrettyOutput.print(f"LSP 目录不存在: {directory}", OutputType.WARNING)
|
|
76
76
|
return lsp_servers
|
|
77
77
|
|
|
78
78
|
package_name = None
|
|
@@ -138,7 +138,7 @@ class LSPRegistry:
|
|
|
138
138
|
def create_lsp(self, language: str) -> Optional[BaseLSP]:
|
|
139
139
|
"""Create LSP instance for specified language."""
|
|
140
140
|
if language not in self.lsp_servers:
|
|
141
|
-
PrettyOutput.print(f"没有找到 LSP 支持的语言: {language}", OutputType.
|
|
141
|
+
PrettyOutput.print(f"没有找到 LSP 支持的语言: {language}", OutputType.WARNING)
|
|
142
142
|
return None
|
|
143
143
|
|
|
144
144
|
try:
|
|
@@ -186,11 +186,11 @@ def main():
|
|
|
186
186
|
lsp = registry.create_lsp(args.language)
|
|
187
187
|
|
|
188
188
|
if not lsp:
|
|
189
|
-
PrettyOutput.print(f"没有 LSP 支持的语言: {args.language}", OutputType.
|
|
189
|
+
PrettyOutput.print(f"没有 LSP 支持的语言: {args.language}", OutputType.WARNING)
|
|
190
190
|
return 1
|
|
191
191
|
|
|
192
192
|
if not lsp.initialize(os.path.dirname(os.path.abspath(args.file))):
|
|
193
|
-
PrettyOutput.print("LSP 初始化失败", OutputType.
|
|
193
|
+
PrettyOutput.print("LSP 初始化失败", OutputType.WARNING)
|
|
194
194
|
return 1
|
|
195
195
|
|
|
196
196
|
try:
|
|
@@ -208,7 +208,7 @@ def main():
|
|
|
208
208
|
|
|
209
209
|
elif args.action in ('references', 'definition'):
|
|
210
210
|
if args.line is None or args.character is None:
|
|
211
|
-
PrettyOutput.print("需要行和字符位置用于 references/definition", OutputType.
|
|
211
|
+
PrettyOutput.print("需要行和字符位置用于 references/definition", OutputType.WARNING)
|
|
212
212
|
return 1
|
|
213
213
|
|
|
214
214
|
if args.action == 'references':
|
{jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_platform/ai8.py
RENAMED
|
@@ -60,12 +60,12 @@ class AI8Model(BasePlatform):
|
|
|
60
60
|
)
|
|
61
61
|
|
|
62
62
|
if response.status_code != 200:
|
|
63
|
-
PrettyOutput.print(f"创建会话失败: {response.status_code}", OutputType.
|
|
63
|
+
PrettyOutput.print(f"创建会话失败: {response.status_code}", OutputType.WARNING)
|
|
64
64
|
return False
|
|
65
65
|
|
|
66
66
|
data = response.json()
|
|
67
67
|
if data['code'] != 0:
|
|
68
|
-
PrettyOutput.print(f"创建会话失败: {data.get('msg', '未知错误')}", OutputType.
|
|
68
|
+
PrettyOutput.print(f"创建会话失败: {data.get('msg', '未知错误')}", OutputType.WARNING)
|
|
69
69
|
return False
|
|
70
70
|
|
|
71
71
|
self.conversation = data['data']
|
|
@@ -93,10 +93,10 @@ class AI8Model(BasePlatform):
|
|
|
93
93
|
self.conversation = data['data']
|
|
94
94
|
return True
|
|
95
95
|
else:
|
|
96
|
-
PrettyOutput.print(f"更新会话设置失败: {data.get('msg', '未知错误')}", OutputType.
|
|
96
|
+
PrettyOutput.print(f"更新会话设置失败: {data.get('msg', '未知错误')}", OutputType.WARNING)
|
|
97
97
|
return False
|
|
98
98
|
else:
|
|
99
|
-
PrettyOutput.print(f"更新会话设置失败: {response.status_code}", OutputType.
|
|
99
|
+
PrettyOutput.print(f"更新会话设置失败: {response.status_code}", OutputType.WARNING)
|
|
100
100
|
return False
|
|
101
101
|
|
|
102
102
|
except Exception as e:
|
|
@@ -162,7 +162,7 @@ class AI8Model(BasePlatform):
|
|
|
162
162
|
|
|
163
163
|
if response.status_code != 200:
|
|
164
164
|
error_msg = f"Failed to chat: {response.status_code} {response.text}"
|
|
165
|
-
PrettyOutput.print(error_msg, OutputType.
|
|
165
|
+
PrettyOutput.print(error_msg, OutputType.WARNING)
|
|
166
166
|
raise Exception(error_msg)
|
|
167
167
|
|
|
168
168
|
# 处理流式响应
|
|
@@ -229,11 +229,11 @@ class AI8Model(BasePlatform):
|
|
|
229
229
|
return True
|
|
230
230
|
else:
|
|
231
231
|
error_msg = f"删除会话失败: {data.get('msg', '未知错误')}"
|
|
232
|
-
PrettyOutput.print(error_msg, OutputType.
|
|
232
|
+
PrettyOutput.print(error_msg, OutputType.WARNING)
|
|
233
233
|
return False
|
|
234
234
|
else:
|
|
235
235
|
error_msg = f"删除会话请求失败: {response.status_code}"
|
|
236
|
-
PrettyOutput.print(error_msg, OutputType.
|
|
236
|
+
PrettyOutput.print(error_msg, OutputType.WARNING)
|
|
237
237
|
return False
|
|
238
238
|
|
|
239
239
|
except Exception as e:
|
|
@@ -265,12 +265,12 @@ class AI8Model(BasePlatform):
|
|
|
265
265
|
)
|
|
266
266
|
|
|
267
267
|
if response.status_code != 200:
|
|
268
|
-
PrettyOutput.print(f"获取模型列表失败: {response.status_code}", OutputType.
|
|
268
|
+
PrettyOutput.print(f"获取模型列表失败: {response.status_code}", OutputType.WARNING)
|
|
269
269
|
return []
|
|
270
270
|
|
|
271
271
|
data = response.json()
|
|
272
272
|
if data['code'] != 0:
|
|
273
|
-
PrettyOutput.print(f"获取模型列表失败: {data.get('msg', '未知错误')}", OutputType.
|
|
273
|
+
PrettyOutput.print(f"获取模型列表失败: {data.get('msg', '未知错误')}", OutputType.WARNING)
|
|
274
274
|
return []
|
|
275
275
|
|
|
276
276
|
# 保存模型信息
|
|
@@ -309,6 +309,6 @@ class AI8Model(BasePlatform):
|
|
|
309
309
|
return list(self.models.keys())
|
|
310
310
|
|
|
311
311
|
except Exception as e:
|
|
312
|
-
PrettyOutput.print(f"获取模型列表失败: {str(e)}", OutputType.
|
|
312
|
+
PrettyOutput.print(f"获取模型列表失败: {str(e)}", OutputType.ERROR)
|
|
313
313
|
return []
|
|
314
314
|
|
{jarvis_ai_assistant-0.1.120 → jarvis_ai_assistant-0.1.122}/src/jarvis/jarvis_platform/kimi.py
RENAMED
|
@@ -198,11 +198,11 @@ class KimiModel(BasePlatform):
|
|
|
198
198
|
if self._wait_for_parse(file_info["id"]):
|
|
199
199
|
uploaded_files.append(file_info)
|
|
200
200
|
else:
|
|
201
|
-
PrettyOutput.print(f"✗ 文件解析失败: {file_path}", OutputType.
|
|
201
|
+
PrettyOutput.print(f"✗ 文件解析失败: {file_path}", OutputType.WARNING)
|
|
202
202
|
else:
|
|
203
203
|
uploaded_files.append(file_info)
|
|
204
204
|
else:
|
|
205
|
-
PrettyOutput.print(f"错误:文件上传失败: {file_path}", OutputType.
|
|
205
|
+
PrettyOutput.print(f"错误:文件上传失败: {file_path}", OutputType.WARNING)
|
|
206
206
|
|
|
207
207
|
except Exception as e:
|
|
208
208
|
PrettyOutput.print(f"✗ 处理文件出错 {file_path}: {str(e)}", OutputType.ERROR)
|
|
@@ -350,8 +350,6 @@ class KimiModel(BasePlatform):
|
|
|
350
350
|
output.append("")
|
|
351
351
|
|
|
352
352
|
PrettyOutput.print("\n".join(output), OutputType.PROGRESS)
|
|
353
|
-
|
|
354
|
-
PrettyOutput.print(full_response, OutputType.RESULT)
|
|
355
353
|
|
|
356
354
|
return full_response
|
|
357
355
|
|
|
@@ -375,7 +373,7 @@ class KimiModel(BasePlatform):
|
|
|
375
373
|
self.reset()
|
|
376
374
|
return True
|
|
377
375
|
else:
|
|
378
|
-
PrettyOutput.print(f"删除会话失败: HTTP {response.status_code}", OutputType.
|
|
376
|
+
PrettyOutput.print(f"删除会话失败: HTTP {response.status_code}", OutputType.WARNING)
|
|
379
377
|
return False
|
|
380
378
|
except Exception as e:
|
|
381
379
|
PrettyOutput.print(f"删除会话时发生错误: {str(e)}", OutputType.ERROR)
|