jarvis-ai-assistant 0.1.222__py3-none-any.whl → 0.7.0__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.
Files changed (162) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +1143 -245
  3. jarvis/jarvis_agent/agent_manager.py +97 -0
  4. jarvis/jarvis_agent/builtin_input_handler.py +12 -10
  5. jarvis/jarvis_agent/config_editor.py +57 -0
  6. jarvis/jarvis_agent/edit_file_handler.py +392 -99
  7. jarvis/jarvis_agent/event_bus.py +48 -0
  8. jarvis/jarvis_agent/events.py +157 -0
  9. jarvis/jarvis_agent/file_context_handler.py +79 -0
  10. jarvis/jarvis_agent/file_methodology_manager.py +117 -0
  11. jarvis/jarvis_agent/jarvis.py +1117 -147
  12. jarvis/jarvis_agent/main.py +78 -34
  13. jarvis/jarvis_agent/memory_manager.py +195 -0
  14. jarvis/jarvis_agent/methodology_share_manager.py +174 -0
  15. jarvis/jarvis_agent/prompt_manager.py +82 -0
  16. jarvis/jarvis_agent/prompts.py +46 -9
  17. jarvis/jarvis_agent/protocols.py +4 -1
  18. jarvis/jarvis_agent/rewrite_file_handler.py +141 -0
  19. jarvis/jarvis_agent/run_loop.py +146 -0
  20. jarvis/jarvis_agent/session_manager.py +9 -9
  21. jarvis/jarvis_agent/share_manager.py +228 -0
  22. jarvis/jarvis_agent/shell_input_handler.py +23 -3
  23. jarvis/jarvis_agent/stdio_redirect.py +295 -0
  24. jarvis/jarvis_agent/task_analyzer.py +212 -0
  25. jarvis/jarvis_agent/task_manager.py +154 -0
  26. jarvis/jarvis_agent/task_planner.py +496 -0
  27. jarvis/jarvis_agent/tool_executor.py +8 -4
  28. jarvis/jarvis_agent/tool_share_manager.py +139 -0
  29. jarvis/jarvis_agent/user_interaction.py +42 -0
  30. jarvis/jarvis_agent/utils.py +54 -0
  31. jarvis/jarvis_agent/web_bridge.py +189 -0
  32. jarvis/jarvis_agent/web_output_sink.py +53 -0
  33. jarvis/jarvis_agent/web_server.py +751 -0
  34. jarvis/jarvis_c2rust/__init__.py +26 -0
  35. jarvis/jarvis_c2rust/cli.py +613 -0
  36. jarvis/jarvis_c2rust/collector.py +258 -0
  37. jarvis/jarvis_c2rust/library_replacer.py +1122 -0
  38. jarvis/jarvis_c2rust/llm_module_agent.py +1300 -0
  39. jarvis/jarvis_c2rust/optimizer.py +960 -0
  40. jarvis/jarvis_c2rust/scanner.py +1681 -0
  41. jarvis/jarvis_c2rust/transpiler.py +2325 -0
  42. jarvis/jarvis_code_agent/build_validation_config.py +133 -0
  43. jarvis/jarvis_code_agent/code_agent.py +1605 -178
  44. jarvis/jarvis_code_agent/code_analyzer/__init__.py +62 -0
  45. jarvis/jarvis_code_agent/code_analyzer/base_language.py +74 -0
  46. jarvis/jarvis_code_agent/code_analyzer/build_validator/__init__.py +44 -0
  47. jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +102 -0
  48. jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +59 -0
  49. jarvis/jarvis_code_agent/code_analyzer/build_validator/detector.py +125 -0
  50. jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +69 -0
  51. jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +38 -0
  52. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +44 -0
  53. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +38 -0
  54. jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +50 -0
  55. jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +93 -0
  56. jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +129 -0
  57. jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +54 -0
  58. jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +154 -0
  59. jarvis/jarvis_code_agent/code_analyzer/build_validator.py +43 -0
  60. jarvis/jarvis_code_agent/code_analyzer/context_manager.py +363 -0
  61. jarvis/jarvis_code_agent/code_analyzer/context_recommender.py +18 -0
  62. jarvis/jarvis_code_agent/code_analyzer/dependency_analyzer.py +132 -0
  63. jarvis/jarvis_code_agent/code_analyzer/file_ignore.py +330 -0
  64. jarvis/jarvis_code_agent/code_analyzer/impact_analyzer.py +781 -0
  65. jarvis/jarvis_code_agent/code_analyzer/language_registry.py +185 -0
  66. jarvis/jarvis_code_agent/code_analyzer/language_support.py +89 -0
  67. jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +31 -0
  68. jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +231 -0
  69. jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +183 -0
  70. jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +219 -0
  71. jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +209 -0
  72. jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +451 -0
  73. jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +77 -0
  74. jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +48 -0
  75. jarvis/jarvis_code_agent/lint.py +275 -13
  76. jarvis/jarvis_code_agent/utils.py +142 -0
  77. jarvis/jarvis_code_analysis/checklists/loader.py +20 -6
  78. jarvis/jarvis_code_analysis/code_review.py +583 -548
  79. jarvis/jarvis_data/config_schema.json +339 -28
  80. jarvis/jarvis_git_squash/main.py +22 -13
  81. jarvis/jarvis_git_utils/git_commiter.py +171 -55
  82. jarvis/jarvis_mcp/sse_mcp_client.py +22 -15
  83. jarvis/jarvis_mcp/stdio_mcp_client.py +4 -4
  84. jarvis/jarvis_mcp/streamable_mcp_client.py +36 -16
  85. jarvis/jarvis_memory_organizer/memory_organizer.py +753 -0
  86. jarvis/jarvis_methodology/main.py +48 -63
  87. jarvis/jarvis_multi_agent/__init__.py +302 -43
  88. jarvis/jarvis_multi_agent/main.py +70 -24
  89. jarvis/jarvis_platform/ai8.py +40 -23
  90. jarvis/jarvis_platform/base.py +210 -49
  91. jarvis/jarvis_platform/human.py +11 -1
  92. jarvis/jarvis_platform/kimi.py +82 -76
  93. jarvis/jarvis_platform/openai.py +73 -1
  94. jarvis/jarvis_platform/registry.py +8 -15
  95. jarvis/jarvis_platform/tongyi.py +115 -101
  96. jarvis/jarvis_platform/yuanbao.py +89 -63
  97. jarvis/jarvis_platform_manager/main.py +194 -132
  98. jarvis/jarvis_platform_manager/service.py +122 -86
  99. jarvis/jarvis_rag/cli.py +156 -53
  100. jarvis/jarvis_rag/embedding_manager.py +155 -12
  101. jarvis/jarvis_rag/llm_interface.py +10 -13
  102. jarvis/jarvis_rag/query_rewriter.py +63 -12
  103. jarvis/jarvis_rag/rag_pipeline.py +222 -40
  104. jarvis/jarvis_rag/reranker.py +26 -3
  105. jarvis/jarvis_rag/retriever.py +270 -14
  106. jarvis/jarvis_sec/__init__.py +3605 -0
  107. jarvis/jarvis_sec/checkers/__init__.py +32 -0
  108. jarvis/jarvis_sec/checkers/c_checker.py +2680 -0
  109. jarvis/jarvis_sec/checkers/rust_checker.py +1108 -0
  110. jarvis/jarvis_sec/cli.py +116 -0
  111. jarvis/jarvis_sec/report.py +257 -0
  112. jarvis/jarvis_sec/status.py +264 -0
  113. jarvis/jarvis_sec/types.py +20 -0
  114. jarvis/jarvis_sec/workflow.py +219 -0
  115. jarvis/jarvis_smart_shell/main.py +405 -137
  116. jarvis/jarvis_stats/__init__.py +13 -0
  117. jarvis/jarvis_stats/cli.py +387 -0
  118. jarvis/jarvis_stats/stats.py +711 -0
  119. jarvis/jarvis_stats/storage.py +612 -0
  120. jarvis/jarvis_stats/visualizer.py +282 -0
  121. jarvis/jarvis_tools/ask_user.py +1 -0
  122. jarvis/jarvis_tools/base.py +18 -2
  123. jarvis/jarvis_tools/clear_memory.py +239 -0
  124. jarvis/jarvis_tools/cli/main.py +220 -144
  125. jarvis/jarvis_tools/execute_script.py +52 -12
  126. jarvis/jarvis_tools/file_analyzer.py +17 -12
  127. jarvis/jarvis_tools/generate_new_tool.py +46 -24
  128. jarvis/jarvis_tools/read_code.py +277 -18
  129. jarvis/jarvis_tools/read_symbols.py +141 -0
  130. jarvis/jarvis_tools/read_webpage.py +86 -13
  131. jarvis/jarvis_tools/registry.py +294 -90
  132. jarvis/jarvis_tools/retrieve_memory.py +227 -0
  133. jarvis/jarvis_tools/save_memory.py +194 -0
  134. jarvis/jarvis_tools/search_web.py +62 -28
  135. jarvis/jarvis_tools/sub_agent.py +205 -0
  136. jarvis/jarvis_tools/sub_code_agent.py +217 -0
  137. jarvis/jarvis_tools/virtual_tty.py +330 -62
  138. jarvis/jarvis_utils/builtin_replace_map.py +4 -5
  139. jarvis/jarvis_utils/clipboard.py +90 -0
  140. jarvis/jarvis_utils/config.py +607 -50
  141. jarvis/jarvis_utils/embedding.py +3 -0
  142. jarvis/jarvis_utils/fzf.py +57 -0
  143. jarvis/jarvis_utils/git_utils.py +251 -29
  144. jarvis/jarvis_utils/globals.py +174 -17
  145. jarvis/jarvis_utils/http.py +58 -79
  146. jarvis/jarvis_utils/input.py +899 -153
  147. jarvis/jarvis_utils/methodology.py +210 -83
  148. jarvis/jarvis_utils/output.py +220 -137
  149. jarvis/jarvis_utils/utils.py +1906 -135
  150. jarvis_ai_assistant-0.7.0.dist-info/METADATA +465 -0
  151. jarvis_ai_assistant-0.7.0.dist-info/RECORD +192 -0
  152. {jarvis_ai_assistant-0.1.222.dist-info → jarvis_ai_assistant-0.7.0.dist-info}/entry_points.txt +8 -2
  153. jarvis/jarvis_git_details/main.py +0 -265
  154. jarvis/jarvis_platform/oyi.py +0 -357
  155. jarvis/jarvis_tools/edit_file.py +0 -255
  156. jarvis/jarvis_tools/rewrite_file.py +0 -195
  157. jarvis_ai_assistant-0.1.222.dist-info/METADATA +0 -767
  158. jarvis_ai_assistant-0.1.222.dist-info/RECORD +0 -110
  159. /jarvis/{jarvis_git_details → jarvis_memory_organizer}/__init__.py +0 -0
  160. {jarvis_ai_assistant-0.1.222.dist-info → jarvis_ai_assistant-0.7.0.dist-info}/WHEEL +0 -0
  161. {jarvis_ai_assistant-0.1.222.dist-info → jarvis_ai_assistant-0.7.0.dist-info}/licenses/LICENSE +0 -0
  162. {jarvis_ai_assistant-0.1.222.dist-info → jarvis_ai_assistant-0.7.0.dist-info}/top_level.txt +0 -0
@@ -1,14 +1,24 @@
1
1
  #!/usr/bin/env python3
2
2
  # -*- coding: utf-8 -*-
3
- import argparse
4
3
  import os
5
- import sys
6
4
  from typing import Optional, Tuple
7
5
 
6
+ import typer
7
+
8
8
  from jarvis.jarvis_platform.registry import PlatformRegistry
9
9
  from jarvis.jarvis_utils.config import get_shell_name, set_config
10
10
  from jarvis.jarvis_utils.input import get_multiline_input
11
11
  from jarvis.jarvis_utils.utils import init_env
12
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
13
+
14
+ app = typer.Typer(
15
+ help="将自然语言要求转换为shell命令",
16
+ epilog="""
17
+ Example:
18
+ jss request "Find all Python files in the current directory"
19
+ jss install
20
+ """,
21
+ )
12
22
 
13
23
 
14
24
  def execute_command(command: str, should_run: bool) -> None:
@@ -18,59 +28,121 @@ def execute_command(command: str, should_run: bool) -> None:
18
28
  os.system(command)
19
29
 
20
30
 
21
- def _check_fish_shell() -> bool:
22
- """Check if current shell is fish
23
-
24
- Returns:
25
- bool: True if fish shell, False otherwise
26
- """
27
- return get_shell_name() == "fish"
28
-
29
31
  def _get_config_file() -> str:
30
32
  """Get fish config file path
31
-
33
+
32
34
  Returns:
33
35
  str: Path to fish config file
34
36
  """
35
37
  return os.path.expanduser("~/.config/fish/config.fish")
36
38
 
39
+
37
40
  def _get_markers() -> Tuple[str, str]:
38
41
  """Get start and end markers for JSS completion
39
-
42
+
40
43
  Returns:
41
44
  Tuple[str, str]: (start_marker, end_marker)
42
45
  """
43
46
  return (
44
47
  "# ===== JARVIS JSS FISH COMPLETION START =====",
45
- "# ===== JARVIS JSS FISH COMPLETION END ====="
48
+ "# ===== JARVIS JSS FISH COMPLETION END =====",
49
+ )
50
+
51
+
52
+ def _check_bash_shell() -> bool:
53
+ """Check if current shell is bash
54
+
55
+ Returns:
56
+ bool: True if bash shell, False otherwise
57
+ """
58
+ return get_shell_name() == "bash"
59
+
60
+
61
+ def _get_bash_config_file() -> str:
62
+ """Get bash config file path
63
+
64
+ Returns:
65
+ str: Path to bash config file (~/.bashrc)
66
+ """
67
+ return os.path.expanduser("~/.bashrc")
68
+
69
+
70
+ def _get_bash_markers() -> Tuple[str, str]:
71
+ """Get start and end markers for JSS completion in bash
72
+
73
+ Returns:
74
+ Tuple[str, str]: (start_marker, end_marker)
75
+ """
76
+ return (
77
+ "# ===== JARVIS JSS BASH COMPLETION START =====",
78
+ "# ===== JARVIS JSS BASH COMPLETION END =====",
46
79
  )
47
80
 
48
- def install_jss_completion() -> int:
49
- """Install JSS fish shell command completion
50
-
81
+
82
+ def _check_zsh_shell() -> bool:
83
+ """Check if current shell is zsh
84
+
51
85
  Returns:
52
- int: 0 if success, 1 if failed
86
+ bool: True if zsh shell, False otherwise
53
87
  """
54
- if not _check_fish_shell():
55
- print("当前不是fish shell,无需安装")
56
- return 0
88
+ return get_shell_name() == "zsh"
57
89
 
58
- config_file = _get_config_file()
59
- start_marker, end_marker = _get_markers()
60
90
 
61
- if not os.path.exists(config_file):
62
- print("未找到config.fish文件,将创建新文件")
63
- os.makedirs(os.path.dirname(config_file), exist_ok=True)
91
+ def _get_zsh_config_file() -> str:
92
+ """Get zsh config file path
64
93
 
65
- with open(config_file, "r") as f:
66
- content = f.read()
94
+ Returns:
95
+ str: Path to zsh config file (~/.zshrc)
96
+ """
97
+ return os.path.expanduser("~/.zshrc")
67
98
 
68
- if start_marker in content:
69
- print("JSS fish completion已安装,请执行: source ~/.config/fish/config.fish")
70
- return 0
71
99
 
72
- with open(config_file, "a") as f:
73
- f.write(f"""
100
+ def _get_zsh_markers() -> Tuple[str, str]:
101
+ """Get start and end markers for JSS completion in zsh
102
+
103
+ Returns:
104
+ Tuple[str, str]: (start_marker, end_marker)
105
+ """
106
+ return (
107
+ "# ===== JARVIS JSS ZSH COMPLETION START =====",
108
+ "# ===== JARVIS JSS ZSH COMPLETION END =====",
109
+ )
110
+
111
+
112
+ @app.command("install")
113
+ def install_jss_completion(
114
+ shell: str = typer.Option("fish", help="指定shell类型(支持fish, bash, zsh)"),
115
+ ) -> None:
116
+ """为指定的shell安装'命令未找到'处理器,实现自然语言命令建议"""
117
+ if shell not in ("fish", "bash", "zsh"):
118
+ PrettyOutput.print(
119
+ f"错误: 不支持的shell类型: {shell}, 仅支持fish, bash, zsh", OutputType.ERROR
120
+ )
121
+ raise typer.Exit(code=1)
122
+
123
+ if shell == "fish":
124
+ config_file = _get_config_file()
125
+ start_marker, end_marker = _get_markers()
126
+
127
+ if not os.path.exists(config_file):
128
+ PrettyOutput.print("未找到 config.fish 文件,将创建新文件", OutputType.INFO)
129
+ os.makedirs(os.path.dirname(config_file), exist_ok=True)
130
+ with open(config_file, "w") as f:
131
+ f.write("")
132
+
133
+ with open(config_file, "r") as f:
134
+ content = f.read()
135
+
136
+ if start_marker in content:
137
+ PrettyOutput.print(
138
+ "JSS fish completion 已安装,请执行: source ~/.config/fish/config.fish",
139
+ OutputType.SUCCESS,
140
+ )
141
+ return
142
+
143
+ with open(config_file, "a") as f:
144
+ f.write(
145
+ f"""
74
146
  {start_marker}
75
147
  function fish_command_not_found
76
148
  if test (string length "$argv") -lt 10
@@ -83,41 +155,282 @@ function __fish_command_not_found_handler --on-event fish_command_not_found
83
155
  fish_command_not_found "$argv"
84
156
  end
85
157
  {end_marker}
86
- """)
87
- print("JSS fish completion已安装,请执行: source ~/.config/fish/config.fish")
88
- return 0
89
-
90
- def uninstall_jss_completion() -> int:
91
- """Uninstall JSS fish shell command completion
92
-
93
- Returns:
94
- int: 0 if success, 1 if failed
95
- """
96
- if not _check_fish_shell():
97
- print("当前不是fish shell,无需卸载")
98
- return 0
99
-
100
- config_file = _get_config_file()
101
- start_marker, end_marker = _get_markers()
102
-
103
- if not os.path.exists(config_file):
104
- print("未找到JSS fish completion配置,无需卸载")
105
- return 0
106
-
107
- with open(config_file, "r") as f:
108
- content = f.read()
109
-
110
- if start_marker not in content:
111
- print("未找到JSS fish completion配置,无需卸载")
112
- return 0
158
+ """
159
+ )
160
+ PrettyOutput.print(
161
+ "JSS fish completion 已安装,请执行: source ~/.config/fish/config.fish",
162
+ OutputType.SUCCESS,
163
+ )
164
+ elif shell == "bash":
165
+ config_file = _get_bash_config_file()
166
+ start_marker, end_marker = _get_bash_markers()
167
+
168
+ if not os.path.exists(config_file):
169
+ PrettyOutput.print("未找到 ~/.bashrc 文件,将创建新文件", OutputType.INFO)
170
+ os.makedirs(os.path.dirname(config_file), exist_ok=True)
171
+ with open(config_file, "w") as f:
172
+ f.write("")
173
+
174
+ with open(config_file, "r") as f:
175
+ content = f.read()
176
+
177
+ if start_marker in content:
178
+ PrettyOutput.print(
179
+ "JSS bash completion 已安装,请执行: source ~/.bashrc",
180
+ OutputType.SUCCESS,
181
+ )
182
+ return
183
+ else:
184
+ with open(config_file, "a") as f:
185
+ f.write(
186
+ f"""
187
+ {start_marker}
188
+ # Bash 'command not found' handler for JSS
189
+ # 行为:
190
+ # - 生成可编辑的建议命令,用户可直接编辑后回车执行
191
+ # - 非交互模式下仅打印建议
192
+ command_not_found_handle() {{
193
+ local cmd="$1"
194
+ shift || true
195
+ local text="$cmd $*"
196
+
197
+ # 与 fish 行为保持一致:对过短输入不处理
198
+ if [ ${{#text}} -lt 10 ]; then
199
+ return 127
200
+ fi
201
+
202
+ local suggestion edited
203
+ suggestion=$(jss request "$text")
204
+ if [ -n "$suggestion" ]; then
205
+ # 交互式:用 readline 预填命令,用户可直接回车执行或编辑
206
+ if [[ $- == *i* ]]; then
207
+ edited="$suggestion"
208
+ # -e 启用 readline;-i 预填默认值;无提示前缀,使体验更接近 fish 的“替换命令行”
209
+ read -e -i "$edited" edited
210
+ if [ -n "$edited" ]; then
211
+ eval "$edited"
212
+ return $?
213
+ fi
214
+ else
215
+ # 非交互:仅打印建议
216
+ printf '%s\n' "$suggestion"
217
+ fi
218
+ fi
219
+ return 127
220
+ }}
221
+ {end_marker}
222
+ """
223
+ )
224
+ PrettyOutput.print(
225
+ "JSS bash completion 已安装,请执行: source ~/.bashrc",
226
+ OutputType.SUCCESS,
227
+ )
228
+ elif shell == "zsh":
229
+ config_file = _get_zsh_config_file()
230
+ start_marker, end_marker = _get_zsh_markers()
231
+
232
+ if not os.path.exists(config_file):
233
+ PrettyOutput.print("未找到 ~/.zshrc 文件,将创建新文件", OutputType.INFO)
234
+ os.makedirs(os.path.dirname(config_file), exist_ok=True)
235
+ with open(config_file, "w") as f:
236
+ f.write("")
237
+
238
+ with open(config_file, "r") as f:
239
+ content = f.read()
240
+
241
+ if start_marker in content:
242
+ PrettyOutput.print(
243
+ "JSS zsh completion 已安装,请执行: source ~/.zshrc", OutputType.SUCCESS
244
+ )
245
+ return
246
+
247
+ with open(config_file, "a") as f:
248
+ f.write(
249
+ f"""
250
+ {start_marker}
251
+ # Zsh 'command not found' handler for JSS
252
+ # 行为:
253
+ # - 生成可编辑的建议命令,用户可直接编辑后回车执行
254
+ # - 非交互模式下仅打印建议
255
+ command_not_found_handler() {{
256
+ local cmd="$1"
257
+ shift || true
258
+ local text="$cmd $*"
259
+
260
+ # 与 fish 行为保持一致:对过短输入不处理
261
+ if [ ${{#text}} -lt 10 ]; then
262
+ return 127
263
+ fi
264
+
265
+ local suggestion edited
266
+ suggestion=$(jss request "$text")
267
+ if [ -n "$suggestion" ]; then
268
+ if [[ -o interactive ]]; then
269
+ local editor="${{VISUAL:-${{EDITOR:-vi}}}}"
270
+ local tmpfile edited
271
+ tmpfile="$(mktemp -t jss-edit-XXXXXX)"
272
+ printf '%s\n' "$suggestion" > "$tmpfile"
273
+ "$editor" "$tmpfile"
274
+ edited="$(sed -n '/./{{p;q;}}' "$tmpfile" | tr -d '\r')"
275
+ rm -f "$tmpfile"
276
+ if [ -z "$edited" ]; then
277
+ edited="$suggestion"
278
+ fi
279
+ eval "$edited"
280
+ return $?
281
+ else
282
+ # 非交互:仅打印建议
283
+ print -r -- "$suggestion"
284
+ fi
285
+ fi
286
+ return 127
287
+ }}
288
+ {end_marker}
289
+ """
290
+ )
291
+ PrettyOutput.print(
292
+ "JSS zsh completion 已安装,请执行: source ~/.zshrc", OutputType.SUCCESS
293
+ )
294
+ return
113
295
 
114
- new_content = content.split(start_marker)[0] + content.split(end_marker)[-1]
115
-
116
- with open(config_file, "w") as f:
117
- f.write(new_content)
118
-
119
- print("JSS fish completion已卸载,请执行: source ~/.config/fish/config.fish")
120
- return 0
296
+ with open(config_file, "a") as f:
297
+ f.write(
298
+ f"""
299
+ {start_marker}
300
+ # Bash 'command not found' handler for JSS
301
+ # 行为:
302
+ # - 生成可编辑的建议命令,用户可直接编辑后回车执行
303
+ # - 非交互模式下仅打印建议
304
+ command_not_found_handle() {{
305
+ local cmd="$1"
306
+ shift || true
307
+ local text="$cmd $*"
308
+
309
+ # 与 fish 行为保持一致:对过短输入不处理
310
+ if [ ${{#text}} -lt 10 ]; then
311
+ return 127
312
+ fi
313
+
314
+ local suggestion edited
315
+ suggestion=$(jss request "$text")
316
+ if [ -n "$suggestion" ]; then
317
+ # 交互式:用 readline 预填命令,用户可直接回车执行或编辑
318
+ if [[ $- == *i* ]]; then
319
+ edited="$suggestion"
320
+ # -e 启用 readline;-i 预填默认值;无提示前缀,使体验更接近 fish 的“替换命令行”
321
+ read -e -i "$edited" edited
322
+ if [ -n "$edited" ]; then
323
+ eval "$edited"
324
+ return $?
325
+ fi
326
+ else
327
+ # 非交互:仅打印建议
328
+ printf '%s\n' "$suggestion"
329
+ fi
330
+ fi
331
+ return 127
332
+ }}
333
+ {end_marker}
334
+ """
335
+ )
336
+ PrettyOutput.print(
337
+ "JSS bash completion 已安装,请执行: source ~/.bashrc", OutputType.SUCCESS
338
+ )
339
+
340
+
341
+ @app.command("uninstall")
342
+ def uninstall_jss_completion(
343
+ shell: str = typer.Option("fish", help="指定shell类型(支持fish, bash, zsh)"),
344
+ ) -> None:
345
+ """卸载JSS shell'命令未找到'处理器"""
346
+ if shell not in ("fish", "bash", "zsh"):
347
+ PrettyOutput.print(
348
+ f"错误: 不支持的shell类型: {shell}, 仅支持fish, bash, zsh", OutputType.ERROR
349
+ )
350
+ raise typer.Exit(code=1)
351
+
352
+ if shell == "fish":
353
+ config_file = _get_config_file()
354
+ start_marker, end_marker = _get_markers()
355
+
356
+ if not os.path.exists(config_file):
357
+ PrettyOutput.print(
358
+ "未找到 JSS fish completion 配置,无需卸载", OutputType.INFO
359
+ )
360
+ return
361
+
362
+ with open(config_file, "r") as f:
363
+ content = f.read()
364
+
365
+ if start_marker not in content:
366
+ PrettyOutput.print(
367
+ "未找到 JSS fish completion 配置,无需卸载", OutputType.INFO
368
+ )
369
+ return
370
+
371
+ new_content = content.split(start_marker)[0] + content.split(end_marker)[-1]
372
+
373
+ with open(config_file, "w") as f:
374
+ f.write(new_content)
375
+
376
+ PrettyOutput.print(
377
+ "JSS fish completion 已卸载,请执行: source ~/.config/fish/config.fish",
378
+ OutputType.SUCCESS,
379
+ )
380
+ elif shell == "bash":
381
+ config_file = _get_bash_config_file()
382
+ start_marker, end_marker = _get_bash_markers()
383
+
384
+ if not os.path.exists(config_file):
385
+ PrettyOutput.print(
386
+ "未找到 JSS bash completion 配置,无需卸载", OutputType.INFO
387
+ )
388
+ return
389
+
390
+ with open(config_file, "r") as f:
391
+ content = f.read()
392
+
393
+ if start_marker not in content:
394
+ PrettyOutput.print(
395
+ "未找到 JSS bash completion 配置,无需卸载", OutputType.INFO
396
+ )
397
+ return
398
+
399
+ new_content = content.split(start_marker)[0] + content.split(end_marker)[-1]
400
+
401
+ with open(config_file, "w") as f:
402
+ f.write(new_content)
403
+
404
+ PrettyOutput.print(
405
+ "JSS bash completion 已卸载,请执行: source ~/.bashrc", OutputType.SUCCESS
406
+ )
407
+ elif shell == "zsh":
408
+ config_file = _get_zsh_config_file()
409
+ start_marker, end_marker = _get_zsh_markers()
410
+
411
+ if not os.path.exists(config_file):
412
+ PrettyOutput.print(
413
+ "未找到 JSS zsh completion 配置,无需卸载", OutputType.INFO
414
+ )
415
+ return
416
+
417
+ with open(config_file, "r") as f:
418
+ content = f.read()
419
+
420
+ if start_marker not in content:
421
+ PrettyOutput.print(
422
+ "未找到 JSS zsh completion 配置,无需卸载", OutputType.INFO
423
+ )
424
+ return
425
+
426
+ new_content = content.split(start_marker)[0] + content.split(end_marker)[-1]
427
+
428
+ with open(config_file, "w") as f:
429
+ f.write(new_content)
430
+
431
+ PrettyOutput.print(
432
+ "JSS zsh completion 已卸载,请执行: source ~/.zshrc", OutputType.SUCCESS
433
+ )
121
434
 
122
435
 
123
436
  def process_request(request: str) -> Optional[str]:
@@ -148,8 +461,8 @@ def process_request(request: str) -> Optional[str]:
148
461
  4. 多个命令用&&连接
149
462
 
150
463
  # 示例
151
- 输入: "查找Python文件"
152
- 输出: find . -name "*.py"
464
+ 输入: "显示当前目录内容"
465
+ 输出: ls -la
153
466
  """
154
467
  model.set_system_prompt(system_message)
155
468
 
@@ -169,85 +482,40 @@ def process_request(request: str) -> Optional[str]:
169
482
  return None
170
483
 
171
484
 
172
- def main() -> int:
173
- # 创建参数解析器
174
- init_env("")
175
-
176
- set_config("JARVIS_PRINT_PROMPT", "false")
177
-
178
- parser = argparse.ArgumentParser(
179
- description="将自然语言要求转换为shell命令",
180
- formatter_class=argparse.RawDescriptionHelpFormatter,
181
- epilog="""
182
- Example:
183
- %(prog)s request "Find all Python files in the current directory"
184
- %(prog)s install
185
- """,
186
- )
187
-
188
- # 创建子命令解析器
189
- subparsers = parser.add_subparsers(dest="command", required=True)
190
-
191
- # request子命令
192
- request_parser = subparsers.add_parser(
193
- "request", help="描述您想要执行的操作(用自然语言描述)"
194
- )
195
- request_parser.add_argument(
196
- "request",
197
- nargs="?", # 设置为可选参数
198
- help="描述您想要执行的操作(用自然语言描述),如果未提供则从标准输入读取",
199
- )
200
-
201
- # install子命令
202
- install_parser = subparsers.add_parser(
203
- "install", help="安装JSS fish shell命令补全功能"
204
- )
205
- install_parser.add_argument(
206
- "--shell", choices=["fish"], default="fish", help="指定shell类型(仅支持fish)"
207
- )
208
-
209
- # 添加uninstall子命令
210
- uninstall_parser = subparsers.add_parser(
211
- "uninstall", help="卸载JSS fish shell命令补全功能"
212
- )
213
- uninstall_parser.add_argument(
214
- "--shell", choices=["fish"], default="fish", help="指定shell类型(仅支持fish)"
485
+ @app.command("request")
486
+ def request_command(
487
+ request: Optional[str] = typer.Argument(
488
+ None, help="描述您想要执行的操作(用自然语言描述),如果未提供则从标准输入读取"
215
489
  )
216
-
217
- # 解析参数
218
- args = parser.parse_args()
219
-
490
+ ):
491
+ """描述您想要执行的操作(用自然语言描述)"""
220
492
  should_run = False
221
-
222
- # 处理install命令
223
- if args.command == "install":
224
- if args.shell != "fish":
225
- print(f"错误: 不支持的shell类型: {args.shell}, 仅支持fish")
226
- return 1
227
- return install_jss_completion()
228
-
229
- # 处理uninstall命令
230
- if args.command == "uninstall":
231
- if args.shell != "fish":
232
- print(f"错误: 不支持的shell类型: {args.shell}, 仅支持fish")
233
- return 1
234
- return uninstall_jss_completion()
235
-
236
- # 处理request命令
237
- if not args.request:
493
+ if not request:
238
494
  # 检查是否在交互式终端中运行
239
- args.request = get_multiline_input(tip="请输入您要执行的功能:")
495
+ request = get_multiline_input(tip="请输入您要执行的功能:")
240
496
  should_run = True
497
+
241
498
  # 处理请求
242
- command = process_request(args.request)
499
+ command = process_request(request)
243
500
 
244
501
  # 输出结果
245
502
  if command:
246
503
  execute_command(command, should_run) # 显示并执行命令
247
- return 0
248
504
  else:
249
- return 1
505
+ raise typer.Exit(code=1)
506
+
507
+
508
+ def cli():
509
+ """Typer application entry point"""
510
+ init_env("")
511
+ set_config("JARVIS_PRINT_PROMPT", "false")
512
+ app()
513
+
514
+
515
+ def main():
516
+ """Main entry point for the script"""
517
+ cli()
250
518
 
251
519
 
252
520
  if __name__ == "__main__":
253
- sys.exit(main())
521
+ main()
@@ -0,0 +1,13 @@
1
+ """
2
+ Jarvis统计模块
3
+
4
+ 提供指标统计、数据持久化、可视化展示等功能
5
+ """
6
+
7
+ from jarvis.jarvis_stats.stats import StatsManager
8
+ from jarvis.jarvis_stats.storage import StatsStorage
9
+ from jarvis.jarvis_stats.visualizer import StatsVisualizer
10
+
11
+ __all__ = ["StatsManager", "StatsStorage", "StatsVisualizer"]
12
+
13
+ __version__ = "1.0.0"