jarvis-ai-assistant 0.1.138__py3-none-any.whl → 0.1.141__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (85) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +62 -14
  3. jarvis/jarvis_agent/builtin_input_handler.py +4 -14
  4. jarvis/jarvis_agent/main.py +1 -1
  5. jarvis/jarvis_agent/patch.py +37 -40
  6. jarvis/jarvis_agent/shell_input_handler.py +2 -3
  7. jarvis/jarvis_code_agent/code_agent.py +23 -30
  8. jarvis/jarvis_code_analysis/checklists/__init__.py +3 -0
  9. jarvis/jarvis_code_analysis/checklists/c_cpp.py +50 -0
  10. jarvis/jarvis_code_analysis/checklists/csharp.py +75 -0
  11. jarvis/jarvis_code_analysis/checklists/data_format.py +82 -0
  12. jarvis/jarvis_code_analysis/checklists/devops.py +107 -0
  13. jarvis/jarvis_code_analysis/checklists/docs.py +87 -0
  14. jarvis/jarvis_code_analysis/checklists/go.py +52 -0
  15. jarvis/jarvis_code_analysis/checklists/infrastructure.py +98 -0
  16. jarvis/jarvis_code_analysis/checklists/java.py +66 -0
  17. jarvis/jarvis_code_analysis/checklists/javascript.py +73 -0
  18. jarvis/jarvis_code_analysis/checklists/kotlin.py +107 -0
  19. jarvis/jarvis_code_analysis/checklists/loader.py +76 -0
  20. jarvis/jarvis_code_analysis/checklists/php.py +77 -0
  21. jarvis/jarvis_code_analysis/checklists/python.py +56 -0
  22. jarvis/jarvis_code_analysis/checklists/ruby.py +107 -0
  23. jarvis/jarvis_code_analysis/checklists/rust.py +58 -0
  24. jarvis/jarvis_code_analysis/checklists/shell.py +75 -0
  25. jarvis/jarvis_code_analysis/checklists/sql.py +72 -0
  26. jarvis/jarvis_code_analysis/checklists/swift.py +77 -0
  27. jarvis/jarvis_code_analysis/checklists/web.py +97 -0
  28. jarvis/jarvis_code_analysis/code_review.py +660 -0
  29. jarvis/jarvis_dev/main.py +61 -88
  30. jarvis/jarvis_git_squash/main.py +3 -3
  31. jarvis/jarvis_git_utils/git_commiter.py +242 -0
  32. jarvis/jarvis_init/main.py +62 -0
  33. jarvis/jarvis_platform/base.py +4 -0
  34. jarvis/jarvis_platform/kimi.py +173 -5
  35. jarvis/jarvis_platform/openai.py +3 -0
  36. jarvis/jarvis_platform/registry.py +1 -0
  37. jarvis/jarvis_platform/yuanbao.py +275 -5
  38. jarvis/jarvis_tools/ask_codebase.py +6 -9
  39. jarvis/jarvis_tools/ask_user.py +17 -5
  40. jarvis/jarvis_tools/base.py +3 -1
  41. jarvis/jarvis_tools/chdir.py +1 -0
  42. jarvis/jarvis_tools/create_code_agent.py +4 -3
  43. jarvis/jarvis_tools/create_sub_agent.py +1 -0
  44. jarvis/jarvis_tools/execute_script.py +170 -0
  45. jarvis/jarvis_tools/file_analyzer.py +90 -239
  46. jarvis/jarvis_tools/file_operation.py +99 -31
  47. jarvis/jarvis_tools/{find_methodolopy.py → find_methodology.py} +2 -1
  48. jarvis/jarvis_tools/lsp_get_diagnostics.py +2 -0
  49. jarvis/jarvis_tools/methodology.py +11 -11
  50. jarvis/jarvis_tools/read_code.py +2 -0
  51. jarvis/jarvis_tools/read_webpage.py +33 -196
  52. jarvis/jarvis_tools/registry.py +68 -131
  53. jarvis/jarvis_tools/search_web.py +14 -6
  54. jarvis/jarvis_tools/virtual_tty.py +399 -0
  55. jarvis/jarvis_utils/config.py +29 -3
  56. jarvis/jarvis_utils/embedding.py +0 -317
  57. jarvis/jarvis_utils/file_processors.py +343 -0
  58. jarvis/jarvis_utils/input.py +0 -1
  59. jarvis/jarvis_utils/methodology.py +94 -435
  60. jarvis/jarvis_utils/utils.py +207 -9
  61. {jarvis_ai_assistant-0.1.138.dist-info → jarvis_ai_assistant-0.1.141.dist-info}/METADATA +4 -4
  62. jarvis_ai_assistant-0.1.141.dist-info/RECORD +94 -0
  63. {jarvis_ai_assistant-0.1.138.dist-info → jarvis_ai_assistant-0.1.141.dist-info}/entry_points.txt +4 -4
  64. jarvis/jarvis_code_agent/file_select.py +0 -202
  65. jarvis/jarvis_platform/ai8.py +0 -268
  66. jarvis/jarvis_platform/ollama.py +0 -137
  67. jarvis/jarvis_platform/oyi.py +0 -307
  68. jarvis/jarvis_rag/file_processors.py +0 -138
  69. jarvis/jarvis_rag/main.py +0 -1734
  70. jarvis/jarvis_tools/code_review.py +0 -333
  71. jarvis/jarvis_tools/execute_python_script.py +0 -58
  72. jarvis/jarvis_tools/execute_shell.py +0 -97
  73. jarvis/jarvis_tools/execute_shell_script.py +0 -58
  74. jarvis/jarvis_tools/find_caller.py +0 -278
  75. jarvis/jarvis_tools/find_symbol.py +0 -295
  76. jarvis/jarvis_tools/function_analyzer.py +0 -331
  77. jarvis/jarvis_tools/git_commiter.py +0 -167
  78. jarvis/jarvis_tools/project_analyzer.py +0 -304
  79. jarvis/jarvis_tools/rag.py +0 -143
  80. jarvis/jarvis_tools/tool_generator.py +0 -221
  81. jarvis_ai_assistant-0.1.138.dist-info/RECORD +0 -85
  82. /jarvis/{jarvis_rag → jarvis_init}/__init__.py +0 -0
  83. {jarvis_ai_assistant-0.1.138.dist-info → jarvis_ai_assistant-0.1.141.dist-info}/LICENSE +0 -0
  84. {jarvis_ai_assistant-0.1.138.dist-info → jarvis_ai_assistant-0.1.141.dist-info}/WHEEL +0 -0
  85. {jarvis_ai_assistant-0.1.138.dist-info → jarvis_ai_assistant-0.1.141.dist-info}/top_level.txt +0 -0
@@ -2,13 +2,13 @@ import os
2
2
  import time
3
3
  import hashlib
4
4
  from pathlib import Path
5
- from typing import Dict
6
- import psutil
7
- from jarvis.jarvis_utils.config import get_max_token_count
5
+ from typing import Union, List, Dict, Any, Callable, cast
6
+ from bs4 import BeautifulSoup, Tag
7
+ from jarvis.jarvis_utils.config import get_max_input_token_count
8
8
  from jarvis.jarvis_utils.embedding import get_context_token_count
9
9
  from jarvis.jarvis_utils.input import get_single_line_input
10
10
  from jarvis.jarvis_utils.output import PrettyOutput, OutputType
11
- def init_env():
11
+ def init_env() -> None:
12
12
  """初始化环境变量从~/.jarvis/env文件
13
13
 
14
14
  功能:
@@ -35,7 +35,7 @@ def init_env():
35
35
  continue
36
36
  except Exception as e:
37
37
  PrettyOutput.print(f"警告: 读取 {env_file} 失败: {e}", OutputType.WARNING)
38
- def while_success(func, sleep_time: float = 0.1):
38
+ def while_success(func: Callable[[], Any], sleep_time: float = 0.1) -> Any:
39
39
  """循环执行函数直到成功
40
40
 
41
41
  参数:
@@ -52,7 +52,7 @@ def while_success(func, sleep_time: float = 0.1):
52
52
  PrettyOutput.print(f"执行失败: {str(e)}, 等待 {sleep_time}s...", OutputType.ERROR)
53
53
  time.sleep(sleep_time)
54
54
  continue
55
- def while_true(func, sleep_time: float = 0.1):
55
+ def while_true(func: Callable[[], bool], sleep_time: float = 0.1) -> Any:
56
56
  """Loop execution function, until the function returns True"""
57
57
  while True:
58
58
  ret = func()
@@ -100,7 +100,7 @@ def get_file_line_count(filename: str) -> int:
100
100
  return 0
101
101
 
102
102
 
103
- def is_long_context(files: list) -> bool:
103
+ def is_long_context(files: List[str]) -> bool:
104
104
  """检查文件列表是否属于长上下文
105
105
 
106
106
  判断标准:
@@ -112,8 +112,8 @@ def is_long_context(files: list) -> bool:
112
112
  返回:
113
113
  布尔值表示是否属于长上下文
114
114
  """
115
- max_token_count = get_max_token_count()
116
- threshold = max_token_count * 0.8
115
+ max_input_token_count = get_max_input_token_count()
116
+ threshold = max_input_token_count * 0.8
117
117
  total_tokens = 0
118
118
 
119
119
  for file_path in files:
@@ -152,3 +152,201 @@ def ct(tag_name: str) -> str:
152
152
  格式化的结束标签字符串
153
153
  """
154
154
  return f"</{tag_name}>"
155
+
156
+
157
+ def create_soup_element(content: Union[str, Tag, List[Any]]) -> List[Union[Tag, str]]:
158
+ """Safely create a BeautifulSoup element, ensuring it's treated as markup
159
+
160
+ Args:
161
+ content: Input content to convert to BeautifulSoup elements
162
+ Returns:
163
+ List of BeautifulSoup elements or strings
164
+ """
165
+ if isinstance(content, str):
166
+ # Create a wrapper tag to ensure proper parsing
167
+ soup_div = BeautifulSoup(f"<div>{content}</div>", 'html.parser').div
168
+ if soup_div is not None:
169
+ return [cast(Union[Tag, str], el) for el in soup_div.contents]
170
+ return []
171
+ elif isinstance(content, list):
172
+ return content
173
+ return [content]
174
+
175
+ def extract_interactive_elements(html_content: str) -> List[Dict[str, Any]]:
176
+ """Extract all interactive elements from HTML content with their properties.
177
+
178
+ Args:
179
+ html_content: HTML content to parse
180
+
181
+ Returns:
182
+ List of dictionaries containing element properties:
183
+ - xpath: XPath of the element
184
+ - tag: HTML tag name
185
+ - text: Text content
186
+ - is_clickable: Whether element is clickable
187
+ - is_input: Whether element is an input field
188
+ - is_select: Whether element is a select dropdown
189
+ """
190
+ soup = BeautifulSoup(html_content, 'html.parser')
191
+ interactive_elements = []
192
+
193
+ # Define interactive tags
194
+ clickable_tags = {'a', 'button', 'input', 'select', 'textarea'}
195
+ input_tags = {'input', 'textarea', 'select'}
196
+
197
+ def get_xpath(element: Tag) -> str:
198
+ """Generate XPath for an element"""
199
+ components = []
200
+ current = element
201
+
202
+ while current and current.name:
203
+ siblings = current.find_previous_siblings(current.name)
204
+ index = len(siblings) + 1
205
+ components.append(f"{current.name}[{index}]")
206
+ current = current.parent
207
+
208
+ return "/".join(reversed(components))
209
+
210
+ def process_element(element: Tag) -> None:
211
+ """Process a single element and add it to interactive_elements if it's interactive"""
212
+ tag_name = element.name.lower()
213
+
214
+ # Skip non-interactive elements
215
+ if tag_name not in clickable_tags and not element.find_parent(clickable_tags):
216
+ return
217
+
218
+ # Get element properties
219
+ element_info = {
220
+ 'xpath': get_xpath(element),
221
+ 'tag': tag_name,
222
+ 'text': element.get_text().strip(),
223
+ 'is_clickable': tag_name in clickable_tags or bool(element.find_parent('a')) or bool(element.find_parent('button')),
224
+ 'is_input': tag_name in input_tags,
225
+ 'is_select': tag_name == 'select'
226
+ }
227
+
228
+ # Add additional properties for input elements
229
+ if element_info['is_input']:
230
+ element_info['input_type'] = element.get('type', 'text')
231
+ element_info['name'] = element.get('name', '')
232
+ element_info['value'] = element.get('value', '')
233
+
234
+ # Add options for select elements
235
+ if element_info['is_select']:
236
+ element_info['options'] = [
237
+ {'value': opt.get('value', ''), 'text': opt.get_text().strip()}
238
+ for opt in element.find_all('option')
239
+ if isinstance(opt, Tag)
240
+ ]
241
+
242
+ interactive_elements.append(element_info)
243
+
244
+ # Process all elements
245
+ for element in soup.find_all():
246
+ if isinstance(element, Tag):
247
+ process_element(element)
248
+
249
+ return interactive_elements
250
+
251
+ def extract_display_elements(html_content: str) -> List[Dict[str, Any]]:
252
+ """Extract all display elements from HTML content with their properties.
253
+
254
+ Args:
255
+ html_content: HTML content to parse
256
+
257
+ Returns:
258
+ List of dictionaries containing element properties:
259
+ - xpath: XPath of the element
260
+ - tag: HTML tag name
261
+ - text: Text content
262
+ - heading_level: Heading level (1-6) if the element is a heading
263
+ - is_list: Whether the element is a list
264
+ - is_list_item: Whether the element is a list item
265
+ - is_table: Whether the element is a table
266
+ - is_table_cell: Whether the element is a table cell
267
+ """
268
+ soup = BeautifulSoup(html_content, 'html.parser')
269
+ display_elements = []
270
+
271
+ # Define display tags
272
+ display_tags = {
273
+ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', # Headings
274
+ 'p', 'div', 'span', # Text containers
275
+ 'ul', 'ol', 'li', # Lists
276
+ 'table', 'tr', 'td', 'th', # Tables
277
+ 'article', 'section', 'main', # Content sections
278
+ 'header', 'footer', 'nav', # Layout sections
279
+ 'aside', 'figure', 'figcaption' # Side content
280
+ }
281
+
282
+ # Define interactive tags to exclude
283
+ interactive_tags = {'a', 'button', 'input', 'select', 'textarea', 'form'}
284
+
285
+ def get_xpath(element: Tag) -> str:
286
+ """Generate XPath for an element"""
287
+ components = []
288
+ current = element
289
+
290
+ while current and current.name:
291
+ siblings = current.find_previous_siblings(current.name)
292
+ index = len(siblings) + 1
293
+ components.append(f"{current.name}[{index}]")
294
+ current = current.parent
295
+
296
+ return "/".join(reversed(components))
297
+
298
+ def process_element(element: Tag) -> None:
299
+ """Process a single element and add it to display_elements if it's a display element"""
300
+ tag_name = element.name.lower()
301
+
302
+ # Skip non-display elements and interactive elements
303
+ if tag_name not in display_tags or element.find_parent(interactive_tags):
304
+ return
305
+
306
+ # Get text content
307
+ text = element.get_text().strip()
308
+ if not text: # Skip empty elements
309
+ return
310
+
311
+ # Get element properties
312
+ element_info = {
313
+ 'xpath': get_xpath(element),
314
+ 'tag': tag_name,
315
+ 'text': text,
316
+ 'heading_level': int(tag_name[1]) if tag_name.startswith('h') and len(tag_name) == 2 else None,
317
+ 'is_list': tag_name in {'ul', 'ol'},
318
+ 'is_list_item': tag_name == 'li',
319
+ 'is_table': tag_name == 'table',
320
+ 'is_table_cell': tag_name in {'td', 'th'}
321
+ }
322
+
323
+ # Add list-specific properties
324
+ if element_info['is_list']:
325
+ element_info['list_items'] = [
326
+ {'text': li.get_text().strip()}
327
+ for li in element.find_all('li')
328
+ if isinstance(li, Tag)
329
+ ]
330
+
331
+ # Add table-specific properties
332
+ if element_info['is_table']:
333
+ element_info['table_rows'] = [
334
+ {
335
+ 'cells': [
336
+ {'text': cell.get_text().strip(), 'is_header': cell.name == 'th'}
337
+ for cell in row.find_all(['td', 'th'])
338
+ if isinstance(cell, Tag)
339
+ ]
340
+ }
341
+ for row in element.find_all('tr')
342
+ if isinstance(row, Tag)
343
+ ]
344
+
345
+ display_elements.append(element_info)
346
+
347
+ # Process all elements
348
+ for element in soup.find_all():
349
+ if isinstance(element, Tag):
350
+ process_element(element)
351
+
352
+ return display_elements
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: jarvis-ai-assistant
3
- Version: 0.1.138
3
+ Version: 0.1.141
4
4
  Summary: Jarvis: An AI assistant that uses tools to interact with the system
5
5
  Home-page: https://github.com/skyfireitdiy/Jarvis
6
6
  Author: skyfire
@@ -45,7 +45,6 @@ Requires-Dist: pyyaml>=5.1
45
45
  Requires-Dist: colorama>=0.4.6
46
46
  Requires-Dist: prompt-toolkit>=3.0.0
47
47
  Requires-Dist: openai>=1.20.0
48
- Requires-Dist: playwright>=1.41.1
49
48
  Requires-Dist: numpy>=1.19.5
50
49
  Requires-Dist: faiss-cpu>=1.8.0
51
50
  Requires-Dist: sentence-transformers>=2.2.2
@@ -55,7 +54,7 @@ Requires-Dist: python-docx>=0.8.11
55
54
  Requires-Dist: tiktoken>=0.3.0
56
55
  Requires-Dist: tqdm>=4.65.0
57
56
  Requires-Dist: docx>=0.2.4
58
- Requires-Dist: yaspin>=2.5.0
57
+ Requires-Dist: yaspin>=2.4.0
59
58
  Requires-Dist: rich>=13.3.1
60
59
  Requires-Dist: pygments>=2.15.0
61
60
  Requires-Dist: fuzzywuzzy>=0.18.0
@@ -66,6 +65,7 @@ Requires-Dist: fastapi>=0.115.4
66
65
  Requires-Dist: uvicorn>=0.33.0
67
66
  Requires-Dist: python-pptx>=1.0.0
68
67
  Requires-Dist: pandas>=2.0.0
68
+ Requires-Dist: html2text>=2024.2.26
69
69
  Provides-Extra: dev
70
70
  Requires-Dist: pytest; extra == "dev"
71
71
  Requires-Dist: black; extra == "dev"
@@ -165,7 +165,7 @@ jarvis-ask-codebase --help
165
165
  |----------|------|
166
166
  | read_code | 支持行号和范围的代码文件读取 |
167
167
  | execute_shell | 执行系统命令并捕获输出 |
168
- | execute_shell_script | 执行shell脚本文件 |
168
+ | execute_script | 执行脚本并返回结果,支持Shell命令、Shell脚本和Python脚本 |
169
169
  | ask_codebase | 智能代码库查询和分析,用于定位功能所在文件和理解单点实现,适合查询特定功能位置和实现原理 |
170
170
  | ask_user | 交互式用户输入收集 |
171
171
  | file_operation | 基础文件操作(读取/写入/存在性检查) |
@@ -0,0 +1,94 @@
1
+ jarvis/__init__.py,sha256=qDMhmaE2-m_heV7fzBRSqmELTVxciZSojL01NXLJgCU,50
2
+ jarvis/jarvis_agent/__init__.py,sha256=doFjWa2a6nVGkKkuQkgrupswqqY8dBNJxUDxUfckvPo,23557
3
+ jarvis/jarvis_agent/builtin_input_handler.py,sha256=aWb5RiKaY5-07LtiLi_mMh9Z-l4DaA_3nLbmFbBGb-w,2429
4
+ jarvis/jarvis_agent/file_input_handler.py,sha256=6rIF_FgC9_3UcQhFCmoMoECG4tjKaLBZZ5zDtBl037I,3235
5
+ jarvis/jarvis_agent/jarvis.py,sha256=NmxVJ8KwSc4fumntNL1T5TWj-FvcRgssLeBhG4sA3xk,5368
6
+ jarvis/jarvis_agent/main.py,sha256=Hx1cavfGkrGVEk_HrOJX6FNE0fEh2CDLy7Efr_VSiKI,2636
7
+ jarvis/jarvis_agent/output_handler.py,sha256=4limQ-Kf-YYvQjT5SMjJIyyvD1DVG8tINv1A_qbv4ho,405
8
+ jarvis/jarvis_agent/patch.py,sha256=ZVde3b7MobwGWR0KFKaGXfeCrMQjmT47GWoGpt2nM3c,19796
9
+ jarvis/jarvis_agent/shell_input_handler.py,sha256=Pcm__ldcBp7GcHm5r3hbRc4nKe86LLWvNl0UE5JlAiU,1173
10
+ jarvis/jarvis_code_agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ jarvis/jarvis_code_agent/code_agent.py,sha256=c6UBBJku-yoH70f-uapsewewp4EKYxevTnMCZ-KqWKA,12599
12
+ jarvis/jarvis_code_analysis/code_review.py,sha256=I_Bc0hDPz3m5textX9Yqreq7_f28CGd7KDW_-i4Cjgs,29543
13
+ jarvis/jarvis_code_analysis/checklists/__init__.py,sha256=PCjlyxLa939613cAzS7pfEPgP57setO-1RvcdzzPivw,54
14
+ jarvis/jarvis_code_analysis/checklists/c_cpp.py,sha256=8lfWmhImAxeTBdHPOgVXDjMllaq280Qki1ZOOSDBnvk,1293
15
+ jarvis/jarvis_code_analysis/checklists/csharp.py,sha256=fg35Iima2nIsirEmAjianfAybVjwRYml9BtbSQFff7w,2396
16
+ jarvis/jarvis_code_analysis/checklists/data_format.py,sha256=g8lubTeEY2Sx5bdPaMmn2PmaSIpxDZu5d1GgPc-DlDk,2981
17
+ jarvis/jarvis_code_analysis/checklists/devops.py,sha256=kTvzFybZ0i1uo5ABD-pbn__h3t8n4QaURSrJ2o-MplQ,3518
18
+ jarvis/jarvis_code_analysis/checklists/docs.py,sha256=7Tq9woxeYqbqmiql3PkbFZ59ui7uIHKRAOUFUGhjCPc,3317
19
+ jarvis/jarvis_code_analysis/checklists/go.py,sha256=yF4gu1YNxyv6Ptgx9Qj4bxeyQHIwAgPQzt4Nm6gdhUc,1364
20
+ jarvis/jarvis_code_analysis/checklists/infrastructure.py,sha256=l64mExwNc49Z8Ol1hy6qdVGFc00SMbagyvn0gOTOR04,3741
21
+ jarvis/jarvis_code_analysis/checklists/java.py,sha256=KIQMukhnMqI8oRsm8oVLaX_s_dggECo2OX8eXqjjG_4,2061
22
+ jarvis/jarvis_code_analysis/checklists/javascript.py,sha256=a0RAqQUfnhK6IItXT_zU5PW5_IH7uwc8BWKo49KuX2c,2316
23
+ jarvis/jarvis_code_analysis/checklists/kotlin.py,sha256=FDtEa2Dyzd4bTSZkusllaLbGFhQKD6OW4g0yvKkBNgw,4412
24
+ jarvis/jarvis_code_analysis/checklists/loader.py,sha256=l6k6Z7oeo1Hy4KAIeM5bGfcqZ7ftwzZoCDNUxAwkm9g,1895
25
+ jarvis/jarvis_code_analysis/checklists/php.py,sha256=LoWeE-I5KonZCc_7fDcekgbPVbK7oVgyUwqq7ZqnDsc,2457
26
+ jarvis/jarvis_code_analysis/checklists/python.py,sha256=ULPQoJBe5B_XKzbAqUv3DOCB7posc4sSv2IWFA4_7lA,1428
27
+ jarvis/jarvis_code_analysis/checklists/ruby.py,sha256=qbaRNGk0VFeZFUYJSJRhLVdZK0JSmlGygHZOHr806YU,4250
28
+ jarvis/jarvis_code_analysis/checklists/rust.py,sha256=6qNtIPxb4VWlyVx6dukMKITkYxqD_jLi5MlB-_jjzHQ,1622
29
+ jarvis/jarvis_code_analysis/checklists/shell.py,sha256=UBtGhi3d5sIhyUSGmDckYOXwpeaQEAfJ-FKCH4izSC8,2595
30
+ jarvis/jarvis_code_analysis/checklists/sql.py,sha256=-bGfYhaFJyHrbcJrUMbkMyPCNVbk8UljNqebqVJJKxM,2331
31
+ jarvis/jarvis_code_analysis/checklists/swift.py,sha256=d-zPPbM_J1G8fgZ2M2-ASQbIxEocsdL1owL4Z2PCnOc,2542
32
+ jarvis/jarvis_code_analysis/checklists/web.py,sha256=phdvLGqRHNijA0OyEwVtgHgz1Hi4ldtJJscOhEQvbSQ,3919
33
+ jarvis/jarvis_dev/main.py,sha256=Rl2COZqMUds-SFyjrroLPfs056gtwTcIliMTJhrtWnM,27751
34
+ jarvis/jarvis_git_details/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
+ jarvis/jarvis_git_details/main.py,sha256=YowncVxYyJ3y2EvGrZhAJeR4yizXp6aB3dqvoYTepFY,6117
36
+ jarvis/jarvis_git_squash/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
+ jarvis/jarvis_git_squash/main.py,sha256=xBNkAl7_8_pQC-C6RcUImA1mEU4KTqhjtA57rG_mMJ8,2179
38
+ jarvis/jarvis_git_utils/git_commiter.py,sha256=6q70zosBrTM6vHqp01DV4780-y3zmazdSfJFGJT9jiw,10643
39
+ jarvis/jarvis_init/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
+ jarvis/jarvis_init/main.py,sha256=Mb41DdhkWRYxdqEqCJPiQRAT4IspbRmak6la9ITcXdg,2102
41
+ jarvis/jarvis_lsp/base.py,sha256=CWfiqiQ6ZBc_lrW64Y1YAsFQeNPGoWcgTBGKgOrPVQg,2047
42
+ jarvis/jarvis_lsp/cpp.py,sha256=SOXFhpipvbdhlwUZ7Rh0hdWGXWnrNOxZVsmTN6ZXoZk,3148
43
+ jarvis/jarvis_lsp/go.py,sha256=h7vA0ArGSq9rhLZcrPXg5HdnEbKwnjVr322IkYI1jHw,3465
44
+ jarvis/jarvis_lsp/python.py,sha256=xMqSVJn8w6CZEquSIO2I-6TJ7-YOABgpt3SjNOV6UAk,1860
45
+ jarvis/jarvis_lsp/registry.py,sha256=LduRCEVH5y75IODdY8lZ3ZB3OHKpgwbZnYNxuhUmA_o,6439
46
+ jarvis/jarvis_lsp/rust.py,sha256=9UOiYTUwMwz2raj1G8Uec0aB5Oun7wMiWYGDhC4JMpI,3693
47
+ jarvis/jarvis_methodology/main.py,sha256=IBv87UOmdCailgooMtWEcqZcQHmNLhZD-kkGw5jOcVg,3375
48
+ jarvis/jarvis_multi_agent/__init__.py,sha256=SX8lBErhltKyYRM-rymrMz3sJ0Zl3hBXrpsPdFgzkQc,4399
49
+ jarvis/jarvis_multi_agent/main.py,sha256=aGuUC3YQmahabqwDwZXJjfQLYsZ3KIZdf8DZDlVNMe4,1543
50
+ jarvis/jarvis_platform/__init__.py,sha256=WIJtD5J7lOrWLX2bsgZGkmlMcN0NOJsnh_reybmHPjg,58
51
+ jarvis/jarvis_platform/base.py,sha256=Ge-UgZGCHICFWOqrHzg-_qXQXjS1I2lZSxfYs5Angwo,3234
52
+ jarvis/jarvis_platform/kimi.py,sha256=N2iNIjJzB57SMAgrfbCvRd595DvlbKtg038wXAz4BqU,16578
53
+ jarvis/jarvis_platform/openai.py,sha256=V_76W4hwKXRQ4Je7qj4nrTOedgQDc2_8l_NUuJq3Q2U,4115
54
+ jarvis/jarvis_platform/registry.py,sha256=QuH8V65uwqf-x_Y-T_rmvIDtPLzkX_COWPfzsH1eH0s,7612
55
+ jarvis/jarvis_platform/yuanbao.py,sha256=MjJVD0z28HHCSxpZaBFQAYxUCDIQdaYjuGv08uIWP-w,21754
56
+ jarvis/jarvis_platform_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
+ jarvis/jarvis_platform_manager/main.py,sha256=o7UDrcCkLf9dTh2LOO-_bQVHjWf2X6RuSY5XRtCGvZs,20245
58
+ jarvis/jarvis_platform_manager/openai_test.py,sha256=8L9Xx-oR82X8l38NsVhkymYucICwMb-6yrH17Usk2TI,4954
59
+ jarvis/jarvis_smart_shell/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
60
+ jarvis/jarvis_smart_shell/main.py,sha256=slP_8CwpfMjWFZis0At1ANRlPb3gx1KteAg1B7R7dl4,4546
61
+ jarvis/jarvis_tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
+ jarvis/jarvis_tools/ask_codebase.py,sha256=xQTcuDl7cbH6uVkWlkA1HXJAo4_3r09-3SboUkBEBDU,10062
63
+ jarvis/jarvis_tools/ask_user.py,sha256=yafF6D54rFTIuRzIZKg6OiYZD35ZT5n8LrmVclZbfk0,2203
64
+ jarvis/jarvis_tools/base.py,sha256=MqUyC0R0Q960dioO0EYrcN25XrRWFwnUcxpA4Gp37Jo,1249
65
+ jarvis/jarvis_tools/chdir.py,sha256=tijYhhGbaAiTcA877w9thlxt0smoK2SX2AntcBBETmA,2727
66
+ jarvis/jarvis_tools/create_code_agent.py,sha256=7AOte1Ua6tOXjLYuetN6qwBx6ID0XX29IEjXmMAouxY,4295
67
+ jarvis/jarvis_tools/create_sub_agent.py,sha256=Hpu50UO-ekakYHxD6-5Civi9lvti5aPnRpTwSxAbFVo,3046
68
+ jarvis/jarvis_tools/execute_script.py,sha256=dMUwg_8nFkYqL-9gFO6LHM1kEKXYLW8PXHRtEWLFcBI,6485
69
+ jarvis/jarvis_tools/file_analyzer.py,sha256=b8FuU6zRlAO_g2p_AbBaCyEfgc7U3yPwfoAKgHwvCiQ,4870
70
+ jarvis/jarvis_tools/file_operation.py,sha256=efFTysX7G-4O8GyChZZRi_ozlDUV14ybflri_cGHRx0,10374
71
+ jarvis/jarvis_tools/find_methodology.py,sha256=zLxDPhoxrkECu_K6OlUDgvOWKewokCOp8VJMdomQns0,2276
72
+ jarvis/jarvis_tools/lsp_get_diagnostics.py,sha256=v_tnnaOgXBWog_73pbZdK-vR3MW2vC6BDmHVxlOF1GA,5363
73
+ jarvis/jarvis_tools/methodology.py,sha256=Nh5dvsUuRaWuLtN9TjdSa1qdAtWk2eLj_bNpKZfQJKE,5200
74
+ jarvis/jarvis_tools/read_code.py,sha256=8TFvORPxu_juMAPqj-UBa3qo810AMqXh8S3Gbq_IXaY,6133
75
+ jarvis/jarvis_tools/read_webpage.py,sha256=6ILzxZm45lW1zke4_01RLclFUbxgI_7mKgaTQtTovYU,2231
76
+ jarvis/jarvis_tools/registry.py,sha256=2rWau4Ib8AtJ2ZsckkNQp3CMC06wBQwSMktzGbv3v8I,17187
77
+ jarvis/jarvis_tools/search_web.py,sha256=ZM1LKb7VApSBn7H1a7oawkhkv7_KBPcCSBKfETED7vo,1397
78
+ jarvis/jarvis_tools/virtual_tty.py,sha256=9aSA14thmJ1e0PVhi0TNAj5lICiVD5j8DVIvzknDupc,15524
79
+ jarvis/jarvis_utils/__init__.py,sha256=KMg-KY5rZIhGTeOD5e2Xo5CU7DX1DUz4ULWAaTQ-ZNw,825
80
+ jarvis/jarvis_utils/config.py,sha256=W0N7aD0uMAQPLLbFapzK02uzGFtjlfotBQt6FbCIlwA,5190
81
+ jarvis/jarvis_utils/embedding.py,sha256=NjbhqoUrSH0p0upQCalGO3O34CyXQ8MMvF1eQTRn5JQ,7129
82
+ jarvis/jarvis_utils/file_processors.py,sha256=VchHOIXxxGWqSu5q0Q_epVWUHJTxaKz2wmqiDoRy5Ik,14324
83
+ jarvis/jarvis_utils/git_utils.py,sha256=rAMXKlAYIvqF64iDFc_FDLxi5SMqEuKYH8GzC7RaZGY,4967
84
+ jarvis/jarvis_utils/globals.py,sha256=DaQ-lfLtK8bDyGVlR6jtkenkkgxQVsIkSZCZwklelzc,2769
85
+ jarvis/jarvis_utils/input.py,sha256=yBrak_UP9ZN3fgV7G19o6TDBjEYVdh3UOyjQ_IpRvz8,6585
86
+ jarvis/jarvis_utils/methodology.py,sha256=A_LA-J2eOY22H0_NSTovcQA8f7BVwgpV6eWCoEZmvdM,6003
87
+ jarvis/jarvis_utils/output.py,sha256=EUJQ1pnCj7PcD9-gXIXMFNrxAwyZBeUd8X-fNEJYJ1k,8443
88
+ jarvis/jarvis_utils/utils.py,sha256=ZYclSrkrHBxatxYQkoNpAgIupO0j9CjiLIp8xBijWXc,12164
89
+ jarvis_ai_assistant-0.1.141.dist-info/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
90
+ jarvis_ai_assistant-0.1.141.dist-info/METADATA,sha256=McbbEQVqMZ1quCSQKwEbgQq21MvzZfVabCgSvo1N1wU,10004
91
+ jarvis_ai_assistant-0.1.141.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
92
+ jarvis_ai_assistant-0.1.141.dist-info/entry_points.txt,sha256=vuvEtcYSta_LgCFHS4m0OjtF7z1jKX_Dy2pG0rOMNIE,972
93
+ jarvis_ai_assistant-0.1.141.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
94
+ jarvis_ai_assistant-0.1.141.dist-info/RECORD,,
@@ -3,17 +3,17 @@ jarvis = jarvis.jarvis_agent.jarvis:main
3
3
  jarvis-agent = jarvis.jarvis_agent.main:main
4
4
  jarvis-ask-codebase = jarvis.jarvis_tools.ask_codebase:main
5
5
  jarvis-code-agent = jarvis.jarvis_code_agent.code_agent:main
6
- jarvis-code-review = jarvis.jarvis_tools.code_review:main
6
+ jarvis-code-review = jarvis.jarvis_code_analysis.code_review:main
7
7
  jarvis-dev = jarvis.jarvis_dev.main:main
8
- jarvis-git-commit = jarvis.jarvis_tools.git_commiter:main
8
+ jarvis-git-commit = jarvis.jarvis_git_utils.git_commiter:main
9
9
  jarvis-git-details = jarvis.jarvis_git_details.main:main
10
10
  jarvis-git-squash = jarvis.jarvis_git_squash.main:main
11
+ jarvis-init = jarvis.jarvis_init.main:main
11
12
  jarvis-methodology = jarvis.jarvis_methodology.main:main
12
13
  jarvis-multi-agent = jarvis.jarvis_multi_agent.main:main
13
14
  jarvis-platform-manager = jarvis.jarvis_platform_manager.main:main
14
- jarvis-rag = jarvis.jarvis_rag.main:main
15
15
  jarvis-smart-shell = jarvis.jarvis_smart_shell.main:main
16
16
  jarvis-tool = jarvis.jarvis_tools.registry:main
17
17
  jca = jarvis.jarvis_code_agent.code_agent:main
18
- jgc = jarvis.jarvis_tools.git_commiter:main
18
+ jgc = jarvis.jarvis_git_utils.git_commiter:main
19
19
  jss = jarvis.jarvis_smart_shell.main:main
@@ -1,202 +0,0 @@
1
- import os
2
- import re
3
- from typing import Dict, List
4
- from prompt_toolkit import PromptSession
5
- from prompt_toolkit.completion import Completer, Completion
6
-
7
- from jarvis.jarvis_utils.input import get_single_line_input
8
- from jarvis.jarvis_utils.output import OutputType, PrettyOutput
9
- from jarvis.jarvis_utils.utils import user_confirm
10
-
11
-
12
- def _parse_file_selection(input_str: str, max_index: int) -> List[int]:
13
- selected = set()
14
-
15
- # Remove all whitespace characters
16
- input_str = "".join(input_str.split())
17
-
18
- # Process comma-separated parts
19
- for part in input_str.split(","):
20
- if not part:
21
- continue
22
-
23
- # Process range (e.g.: 3-6)
24
- if "-" in part:
25
- try:
26
- start, end = map(int, part.split("-"))
27
- # Convert to index starting from 0
28
- start = max(0, start - 1)
29
- end = min(max_index, end - 1)
30
- if start <= end:
31
- selected.update(range(start, end + 1))
32
- except ValueError:
33
- PrettyOutput.print(f"忽略无效的范围表达式: {part}", OutputType.WARNING)
34
- # Process single number
35
- else:
36
- try:
37
- index = int(part) - 1 # Convert to index starting from 0
38
- if 0 <= index < max_index:
39
- selected.add(index)
40
- else:
41
- PrettyOutput.print(f"忽略超出范围的索引: {part}", OutputType.WARNING)
42
- except ValueError:
43
- PrettyOutput.print(f"忽略无效的数字: {part}", OutputType.WARNING)
44
-
45
- return sorted(list(selected))
46
-
47
- def _get_file_completer(root_dir: str) -> Completer:
48
- """Create file path completer"""
49
- class FileCompleter(Completer):
50
- def __init__(self, root_dir: str):
51
- self.root_dir = root_dir
52
-
53
- def get_completions(self, document, complete_event):
54
- text = document.text_before_cursor
55
-
56
- if not text:
57
- for path in self._list_files(""):
58
- yield Completion(path, start_position=0)
59
- return
60
-
61
- # Generate fuzzy matching pattern
62
- pattern = '.*'.join(map(re.escape, text))
63
- try:
64
- regex = re.compile(pattern, re.IGNORECASE)
65
- except re.error:
66
- return
67
-
68
- for path in self._list_files(""):
69
- if regex.search(path):
70
- yield Completion(path, start_position=-len(text))
71
-
72
- def _list_files(self, current_dir: str) -> List[str]:
73
- """List all files in the specified directory (recursively)"""
74
- files = []
75
- search_dir = os.path.join(self.root_dir, current_dir)
76
-
77
- for root, _, filenames in os.walk(search_dir):
78
- for filename in filenames:
79
- full_path = os.path.join(root, filename)
80
- rel_path = os.path.relpath(full_path, self.root_dir)
81
- if not any(part.startswith('.') for part in rel_path.split(os.sep)):
82
- files.append(rel_path)
83
-
84
- return sorted(files)
85
-
86
- return FileCompleter(root_dir)
87
-
88
- def _fuzzy_match_files(root_dir: str, pattern: str) -> List[str]:
89
- """Fuzzy match file path
90
-
91
- Args:
92
- pattern: Matching pattern
93
-
94
- Returns:
95
- List[str]: List of matching file paths
96
- """
97
- matches = []
98
-
99
- # 将模式转换为正则表达式
100
- pattern = pattern.replace('.', r'\.').replace('*', '.*').replace('?', '.')
101
- pattern = f".*{pattern}.*" # 允许部分匹配
102
- regex = re.compile(pattern, re.IGNORECASE)
103
-
104
- # 遍历所有文件
105
- for root, _, files in os.walk(root_dir):
106
- for file in files:
107
- full_path = os.path.join(root, file)
108
- rel_path = os.path.relpath(full_path, root_dir)
109
- # 忽略 .git 目录和其他隐藏文件
110
- if not any(part.startswith('.') for part in rel_path.split(os.sep)):
111
- if regex.match(rel_path):
112
- matches.append(rel_path)
113
-
114
- return sorted(matches)
115
-
116
- def select_files(related_files: List[Dict[str, str]], root_dir: str) -> List[Dict[str, str]]:
117
- """Let the user select and supplement related files"""
118
- output = ""
119
- # Display found files
120
- selected_files = list(related_files) # Default select all
121
- for i, file in enumerate(related_files, 1):
122
- output += f"[{i}] {file['file']} ({file['reason']})\n"
123
-
124
- # Filter out files that do not exist
125
- related_files = [f for f in related_files if os.path.isfile(os.path.join(root_dir, f["file"]))]
126
-
127
- if output:
128
- PrettyOutput.section("相关文件", OutputType.INFO)
129
- PrettyOutput.print(output, OutputType.INFO, lang="markdown")
130
-
131
- if len(related_files) > 0:
132
- # Ask the user if they need to adjust the file list
133
- if user_confirm("是否需要调整文件列表?", False):
134
- # Let the user select files
135
- numbers = get_single_line_input("请输入要包含的文件编号(支持: 1,3-6格式, 按回车保持当前选择)").strip()
136
- if numbers:
137
- selected_indices = _parse_file_selection(numbers, len(related_files))
138
- if selected_indices:
139
- selected_files = [related_files[i] for i in selected_indices]
140
- else:
141
- PrettyOutput.print("没有有效的文件被选择, 保持当前选择", OutputType.WARNING)
142
-
143
- tips = ""
144
- # Ask if they need to supplement files
145
- if user_confirm("是否需要补充其他文件?", False):
146
- # Create file completion session
147
- session = PromptSession(
148
- completer=_get_file_completer(root_dir),
149
- complete_while_typing=True
150
- )
151
- PrettyOutput.print("请输入要补充的文件路径(支持Tab补全和*?通配符, 输入空行结束)", OutputType.INFO)
152
- while True:
153
- try:
154
- file_path = session.prompt(">>> ").strip()
155
- except KeyboardInterrupt:
156
- break
157
-
158
- if not file_path:
159
- break
160
-
161
- # Process wildcard matching
162
- if '*' in file_path or '?' in file_path:
163
- matches = _fuzzy_match_files(root_dir, file_path)
164
- if not matches:
165
- PrettyOutput.print("没有找到匹配的文件", OutputType.WARNING)
166
- continue
167
-
168
- # Display matching files
169
- tips = "找到以下匹配的文件:"
170
- for i, path in enumerate(matches, 1):
171
- tips += f"\n[{i}] {path}"
172
- PrettyOutput.print(tips, OutputType.INFO)
173
-
174
- # Let the user select
175
- numbers = get_single_line_input("请选择要添加的文件编号(支持: 1,3-6格式, 按回车选择所有)").strip()
176
- if numbers:
177
- indices = _parse_file_selection(numbers, len(matches))
178
- if not indices:
179
- continue
180
- paths_to_add = [matches[i] for i in indices]
181
- else:
182
- paths_to_add = matches
183
- else:
184
- paths_to_add = [file_path]
185
-
186
- # Add selected files
187
- tips = "添加以下文件:"
188
- for path in paths_to_add:
189
- full_path = os.path.join(root_dir, path)
190
- if not os.path.isfile(full_path):
191
- tips += f"\n文件不存在: {path}"
192
- continue
193
-
194
- try:
195
- selected_files.append({"file": path, "reason": "I Added"})
196
- tips += f"\n文件已添加: {path}"
197
- except Exception as e:
198
- tips += f"\n读取文件失败: {str(e)}"
199
- selected_files = [f for f in selected_files if os.path.isfile(os.path.join(root_dir, f["file"]))]
200
- if tips:
201
- PrettyOutput.print(tips, OutputType.INFO)
202
- return selected_files