jarvis-ai-assistant 0.7.0__py3-none-any.whl → 0.7.8__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 (159) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +243 -139
  3. jarvis/jarvis_agent/agent_manager.py +5 -10
  4. jarvis/jarvis_agent/builtin_input_handler.py +2 -6
  5. jarvis/jarvis_agent/config_editor.py +2 -7
  6. jarvis/jarvis_agent/event_bus.py +82 -12
  7. jarvis/jarvis_agent/file_context_handler.py +265 -15
  8. jarvis/jarvis_agent/file_methodology_manager.py +3 -4
  9. jarvis/jarvis_agent/jarvis.py +113 -98
  10. jarvis/jarvis_agent/language_extractors/__init__.py +57 -0
  11. jarvis/jarvis_agent/language_extractors/c_extractor.py +21 -0
  12. jarvis/jarvis_agent/language_extractors/cpp_extractor.py +21 -0
  13. jarvis/jarvis_agent/language_extractors/go_extractor.py +21 -0
  14. jarvis/jarvis_agent/language_extractors/java_extractor.py +84 -0
  15. jarvis/jarvis_agent/language_extractors/javascript_extractor.py +79 -0
  16. jarvis/jarvis_agent/language_extractors/python_extractor.py +21 -0
  17. jarvis/jarvis_agent/language_extractors/rust_extractor.py +21 -0
  18. jarvis/jarvis_agent/language_extractors/typescript_extractor.py +84 -0
  19. jarvis/jarvis_agent/language_support_info.py +486 -0
  20. jarvis/jarvis_agent/main.py +6 -12
  21. jarvis/jarvis_agent/memory_manager.py +7 -16
  22. jarvis/jarvis_agent/methodology_share_manager.py +10 -16
  23. jarvis/jarvis_agent/prompt_manager.py +1 -1
  24. jarvis/jarvis_agent/prompts.py +193 -171
  25. jarvis/jarvis_agent/protocols.py +8 -12
  26. jarvis/jarvis_agent/run_loop.py +77 -14
  27. jarvis/jarvis_agent/session_manager.py +2 -3
  28. jarvis/jarvis_agent/share_manager.py +12 -21
  29. jarvis/jarvis_agent/shell_input_handler.py +1 -2
  30. jarvis/jarvis_agent/task_analyzer.py +26 -4
  31. jarvis/jarvis_agent/task_manager.py +11 -27
  32. jarvis/jarvis_agent/tool_executor.py +2 -3
  33. jarvis/jarvis_agent/tool_share_manager.py +12 -24
  34. jarvis/jarvis_agent/web_server.py +55 -20
  35. jarvis/jarvis_c2rust/__init__.py +5 -5
  36. jarvis/jarvis_c2rust/cli.py +461 -499
  37. jarvis/jarvis_c2rust/collector.py +45 -53
  38. jarvis/jarvis_c2rust/constants.py +26 -0
  39. jarvis/jarvis_c2rust/library_replacer.py +264 -132
  40. jarvis/jarvis_c2rust/llm_module_agent.py +162 -190
  41. jarvis/jarvis_c2rust/loaders.py +207 -0
  42. jarvis/jarvis_c2rust/models.py +28 -0
  43. jarvis/jarvis_c2rust/optimizer.py +1592 -395
  44. jarvis/jarvis_c2rust/transpiler.py +1722 -1064
  45. jarvis/jarvis_c2rust/utils.py +385 -0
  46. jarvis/jarvis_code_agent/build_validation_config.py +2 -3
  47. jarvis/jarvis_code_agent/code_agent.py +394 -320
  48. jarvis/jarvis_code_agent/code_analyzer/__init__.py +3 -0
  49. jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +4 -0
  50. jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +17 -2
  51. jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +3 -0
  52. jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +36 -4
  53. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +9 -0
  54. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +9 -0
  55. jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +12 -1
  56. jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +22 -5
  57. jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +57 -32
  58. jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +62 -6
  59. jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +8 -9
  60. jarvis/jarvis_code_agent/code_analyzer/context_manager.py +290 -5
  61. jarvis/jarvis_code_agent/code_analyzer/language_support.py +21 -0
  62. jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +21 -3
  63. jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +72 -4
  64. jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +35 -3
  65. jarvis/jarvis_code_agent/code_analyzer/languages/java_language.py +212 -0
  66. jarvis/jarvis_code_agent/code_analyzer/languages/javascript_language.py +254 -0
  67. jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +52 -2
  68. jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +73 -1
  69. jarvis/jarvis_code_agent/code_analyzer/languages/typescript_language.py +280 -0
  70. jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +306 -152
  71. jarvis/jarvis_code_agent/code_analyzer/structured_code.py +556 -0
  72. jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +193 -18
  73. jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +18 -8
  74. jarvis/jarvis_code_agent/lint.py +258 -27
  75. jarvis/jarvis_code_agent/utils.py +0 -1
  76. jarvis/jarvis_code_analysis/code_review.py +19 -24
  77. jarvis/jarvis_data/config_schema.json +53 -26
  78. jarvis/jarvis_git_squash/main.py +4 -5
  79. jarvis/jarvis_git_utils/git_commiter.py +44 -49
  80. jarvis/jarvis_mcp/sse_mcp_client.py +20 -27
  81. jarvis/jarvis_mcp/stdio_mcp_client.py +11 -12
  82. jarvis/jarvis_mcp/streamable_mcp_client.py +15 -14
  83. jarvis/jarvis_memory_organizer/memory_organizer.py +55 -74
  84. jarvis/jarvis_methodology/main.py +32 -48
  85. jarvis/jarvis_multi_agent/__init__.py +79 -61
  86. jarvis/jarvis_multi_agent/main.py +3 -7
  87. jarvis/jarvis_platform/base.py +469 -199
  88. jarvis/jarvis_platform/human.py +7 -8
  89. jarvis/jarvis_platform/kimi.py +30 -36
  90. jarvis/jarvis_platform/openai.py +65 -27
  91. jarvis/jarvis_platform/registry.py +26 -10
  92. jarvis/jarvis_platform/tongyi.py +24 -25
  93. jarvis/jarvis_platform/yuanbao.py +31 -42
  94. jarvis/jarvis_platform_manager/main.py +66 -77
  95. jarvis/jarvis_platform_manager/service.py +8 -13
  96. jarvis/jarvis_rag/cli.py +49 -51
  97. jarvis/jarvis_rag/embedding_manager.py +13 -18
  98. jarvis/jarvis_rag/llm_interface.py +8 -9
  99. jarvis/jarvis_rag/query_rewriter.py +10 -21
  100. jarvis/jarvis_rag/rag_pipeline.py +24 -27
  101. jarvis/jarvis_rag/reranker.py +4 -5
  102. jarvis/jarvis_rag/retriever.py +28 -30
  103. jarvis/jarvis_sec/__init__.py +220 -3520
  104. jarvis/jarvis_sec/agents.py +143 -0
  105. jarvis/jarvis_sec/analysis.py +276 -0
  106. jarvis/jarvis_sec/cli.py +29 -6
  107. jarvis/jarvis_sec/clustering.py +1439 -0
  108. jarvis/jarvis_sec/file_manager.py +427 -0
  109. jarvis/jarvis_sec/parsers.py +73 -0
  110. jarvis/jarvis_sec/prompts.py +268 -0
  111. jarvis/jarvis_sec/report.py +83 -4
  112. jarvis/jarvis_sec/review.py +453 -0
  113. jarvis/jarvis_sec/utils.py +499 -0
  114. jarvis/jarvis_sec/verification.py +848 -0
  115. jarvis/jarvis_sec/workflow.py +7 -0
  116. jarvis/jarvis_smart_shell/main.py +38 -87
  117. jarvis/jarvis_stats/cli.py +1 -1
  118. jarvis/jarvis_stats/stats.py +7 -7
  119. jarvis/jarvis_stats/storage.py +15 -21
  120. jarvis/jarvis_tools/clear_memory.py +3 -20
  121. jarvis/jarvis_tools/cli/main.py +20 -23
  122. jarvis/jarvis_tools/edit_file.py +1066 -0
  123. jarvis/jarvis_tools/execute_script.py +42 -21
  124. jarvis/jarvis_tools/file_analyzer.py +6 -9
  125. jarvis/jarvis_tools/generate_new_tool.py +11 -20
  126. jarvis/jarvis_tools/lsp_client.py +1552 -0
  127. jarvis/jarvis_tools/methodology.py +2 -3
  128. jarvis/jarvis_tools/read_code.py +1525 -87
  129. jarvis/jarvis_tools/read_symbols.py +2 -3
  130. jarvis/jarvis_tools/read_webpage.py +7 -10
  131. jarvis/jarvis_tools/registry.py +370 -181
  132. jarvis/jarvis_tools/retrieve_memory.py +20 -19
  133. jarvis/jarvis_tools/rewrite_file.py +105 -0
  134. jarvis/jarvis_tools/save_memory.py +3 -15
  135. jarvis/jarvis_tools/search_web.py +3 -7
  136. jarvis/jarvis_tools/sub_agent.py +17 -6
  137. jarvis/jarvis_tools/sub_code_agent.py +14 -16
  138. jarvis/jarvis_tools/virtual_tty.py +54 -32
  139. jarvis/jarvis_utils/clipboard.py +7 -10
  140. jarvis/jarvis_utils/config.py +98 -63
  141. jarvis/jarvis_utils/embedding.py +5 -5
  142. jarvis/jarvis_utils/fzf.py +8 -8
  143. jarvis/jarvis_utils/git_utils.py +81 -67
  144. jarvis/jarvis_utils/input.py +24 -49
  145. jarvis/jarvis_utils/jsonnet_compat.py +465 -0
  146. jarvis/jarvis_utils/methodology.py +33 -35
  147. jarvis/jarvis_utils/utils.py +245 -202
  148. {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.8.dist-info}/METADATA +205 -70
  149. jarvis_ai_assistant-0.7.8.dist-info/RECORD +218 -0
  150. jarvis/jarvis_agent/edit_file_handler.py +0 -584
  151. jarvis/jarvis_agent/rewrite_file_handler.py +0 -141
  152. jarvis/jarvis_agent/task_planner.py +0 -496
  153. jarvis/jarvis_platform/ai8.py +0 -332
  154. jarvis/jarvis_tools/ask_user.py +0 -54
  155. jarvis_ai_assistant-0.7.0.dist-info/RECORD +0 -192
  156. {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.8.dist-info}/WHEEL +0 -0
  157. {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.8.dist-info}/entry_points.txt +0 -0
  158. {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.8.dist-info}/licenses/LICENSE +0 -0
  159. {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.8.dist-info}/top_level.txt +0 -0
@@ -187,6 +187,9 @@ def run_with_agent(
187
187
  report_file: Optional[str] = None,
188
188
  cluster_limit: int = 50,
189
189
  exclude_dirs: Optional[List[str]] = None,
190
+ enable_verification: bool = True,
191
+ force_save_memory: bool = False,
192
+ output_file: Optional[str] = None,
190
193
  ) -> str:
191
194
  """
192
195
  使用单Agent逐条子任务分析模式运行(与 jarvis.jarvis_sec.__init__ 中保持一致)。
@@ -199,6 +202,7 @@ def run_with_agent(
199
202
  - report_file: JSONL 报告文件路径(可选,透传)
200
203
  - cluster_limit: 聚类时每批次最多处理的告警数(默认 50),当单个文件告警过多时按批次进行聚类
201
204
  - exclude_dirs: 要排除的目录列表(可选),默认已包含构建产物(build, out, target, dist, bin, obj)、依赖目录(third_party, vendor, deps, dependencies, libs, libraries, external, node_modules)、测试目录(test, tests, __tests__, spec, testsuite, testdata)、性能测试目录(benchmark, benchmarks, perf, performance, bench, benches, profiling, profiler)、示例目录(example, examples)、临时/缓存(tmp, temp, cache, .cache)、文档(docs, doc, documentation)、生成代码(generated, gen)和其他(mocks, fixtures, samples, sample, playground, sandbox)
205
+ - enable_verification: 是否启用二次验证(默认 True),关闭后分析Agent确认的问题将直接写入报告
202
206
  """
203
207
  from jarvis.jarvis_sec import run_security_analysis # 延迟导入,避免循环
204
208
  return run_security_analysis(
@@ -208,6 +212,9 @@ def run_with_agent(
208
212
  report_file=report_file,
209
213
  cluster_limit=cluster_limit,
210
214
  exclude_dirs=exclude_dirs,
215
+ enable_verification=enable_verification,
216
+ force_save_memory=force_save_memory,
217
+ output_file=output_file,
211
218
  )
212
219
 
213
220
 
@@ -9,7 +9,6 @@ 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
12
 
14
13
  app = typer.Typer(
15
14
  help="将自然语言要求转换为shell命令",
@@ -115,8 +114,8 @@ def install_jss_completion(
115
114
  ) -> None:
116
115
  """为指定的shell安装'命令未找到'处理器,实现自然语言命令建议"""
117
116
  if shell not in ("fish", "bash", "zsh"):
118
- PrettyOutput.print(
119
- f"错误: 不支持的shell类型: {shell}, 仅支持fish, bash, zsh", OutputType.ERROR
117
+ print(
118
+ f"错误: 不支持的shell类型: {shell}, 仅支持fish, bash, zsh"
120
119
  )
121
120
  raise typer.Exit(code=1)
122
121
 
@@ -125,7 +124,7 @@ def install_jss_completion(
125
124
  start_marker, end_marker = _get_markers()
126
125
 
127
126
  if not os.path.exists(config_file):
128
- PrettyOutput.print("未找到 config.fish 文件,将创建新文件", OutputType.INFO)
127
+ print("ℹ️ 未找到 config.fish 文件,将创建新文件")
129
128
  os.makedirs(os.path.dirname(config_file), exist_ok=True)
130
129
  with open(config_file, "w") as f:
131
130
  f.write("")
@@ -134,9 +133,8 @@ def install_jss_completion(
134
133
  content = f.read()
135
134
 
136
135
  if start_marker in content:
137
- PrettyOutput.print(
138
- "JSS fish completion 已安装,请执行: source ~/.config/fish/config.fish",
139
- OutputType.SUCCESS,
136
+ print(
137
+ "JSS fish completion 已安装,请执行: source ~/.config/fish/config.fish"
140
138
  )
141
139
  return
142
140
 
@@ -157,16 +155,15 @@ end
157
155
  {end_marker}
158
156
  """
159
157
  )
160
- PrettyOutput.print(
161
- "JSS fish completion 已安装,请执行: source ~/.config/fish/config.fish",
162
- OutputType.SUCCESS,
158
+ print(
159
+ "JSS fish completion 已安装,请执行: source ~/.config/fish/config.fish"
163
160
  )
164
161
  elif shell == "bash":
165
162
  config_file = _get_bash_config_file()
166
163
  start_marker, end_marker = _get_bash_markers()
167
164
 
168
165
  if not os.path.exists(config_file):
169
- PrettyOutput.print("未找到 ~/.bashrc 文件,将创建新文件", OutputType.INFO)
166
+ print("ℹ️ 未找到 ~/.bashrc 文件,将创建新文件")
170
167
  os.makedirs(os.path.dirname(config_file), exist_ok=True)
171
168
  with open(config_file, "w") as f:
172
169
  f.write("")
@@ -175,9 +172,8 @@ end
175
172
  content = f.read()
176
173
 
177
174
  if start_marker in content:
178
- PrettyOutput.print(
179
- "JSS bash completion 已安装,请执行: source ~/.bashrc",
180
- OutputType.SUCCESS,
175
+ print(
176
+ "JSS bash completion 已安装,请执行: source ~/.bashrc"
181
177
  )
182
178
  return
183
179
  else:
@@ -221,16 +217,15 @@ command_not_found_handle() {{
221
217
  {end_marker}
222
218
  """
223
219
  )
224
- PrettyOutput.print(
225
- "JSS bash completion 已安装,请执行: source ~/.bashrc",
226
- OutputType.SUCCESS,
220
+ print(
221
+ "JSS bash completion 已安装,请执行: source ~/.bashrc"
227
222
  )
228
223
  elif shell == "zsh":
229
224
  config_file = _get_zsh_config_file()
230
225
  start_marker, end_marker = _get_zsh_markers()
231
226
 
232
227
  if not os.path.exists(config_file):
233
- PrettyOutput.print("未找到 ~/.zshrc 文件,将创建新文件", OutputType.INFO)
228
+ print("ℹ️ 未找到 ~/.zshrc 文件,将创建新文件")
234
229
  os.makedirs(os.path.dirname(config_file), exist_ok=True)
235
230
  with open(config_file, "w") as f:
236
231
  f.write("")
@@ -239,8 +234,8 @@ command_not_found_handle() {{
239
234
  content = f.read()
240
235
 
241
236
  if start_marker in content:
242
- PrettyOutput.print(
243
- "JSS zsh completion 已安装,请执行: source ~/.zshrc", OutputType.SUCCESS
237
+ print(
238
+ "JSS zsh completion 已安装,请执行: source ~/.zshrc"
244
239
  )
245
240
  return
246
241
 
@@ -288,55 +283,11 @@ command_not_found_handler() {{
288
283
  {end_marker}
289
284
  """
290
285
  )
291
- PrettyOutput.print(
292
- "JSS zsh completion 已安装,请执行: source ~/.zshrc", OutputType.SUCCESS
286
+ print(
287
+ "JSS zsh completion 已安装,请执行: source ~/.zshrc"
293
288
  )
294
289
  return
295
290
 
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
291
 
341
292
  @app.command("uninstall")
342
293
  def uninstall_jss_completion(
@@ -344,8 +295,8 @@ def uninstall_jss_completion(
344
295
  ) -> None:
345
296
  """卸载JSS shell'命令未找到'处理器"""
346
297
  if shell not in ("fish", "bash", "zsh"):
347
- PrettyOutput.print(
348
- f"错误: 不支持的shell类型: {shell}, 仅支持fish, bash, zsh", OutputType.ERROR
298
+ print(
299
+ f"错误: 不支持的shell类型: {shell}, 仅支持fish, bash, zsh"
349
300
  )
350
301
  raise typer.Exit(code=1)
351
302
 
@@ -354,8 +305,8 @@ def uninstall_jss_completion(
354
305
  start_marker, end_marker = _get_markers()
355
306
 
356
307
  if not os.path.exists(config_file):
357
- PrettyOutput.print(
358
- "未找到 JSS fish completion 配置,无需卸载", OutputType.INFO
308
+ print(
309
+ "ℹ️ 未找到 JSS fish completion 配置,无需卸载"
359
310
  )
360
311
  return
361
312
 
@@ -363,8 +314,8 @@ def uninstall_jss_completion(
363
314
  content = f.read()
364
315
 
365
316
  if start_marker not in content:
366
- PrettyOutput.print(
367
- "未找到 JSS fish completion 配置,无需卸载", OutputType.INFO
317
+ print(
318
+ "ℹ️ 未找到 JSS fish completion 配置,无需卸载"
368
319
  )
369
320
  return
370
321
 
@@ -373,17 +324,16 @@ def uninstall_jss_completion(
373
324
  with open(config_file, "w") as f:
374
325
  f.write(new_content)
375
326
 
376
- PrettyOutput.print(
377
- "JSS fish completion 已卸载,请执行: source ~/.config/fish/config.fish",
378
- OutputType.SUCCESS,
327
+ print(
328
+ "JSS fish completion 已卸载,请执行: source ~/.config/fish/config.fish"
379
329
  )
380
330
  elif shell == "bash":
381
331
  config_file = _get_bash_config_file()
382
332
  start_marker, end_marker = _get_bash_markers()
383
333
 
384
334
  if not os.path.exists(config_file):
385
- PrettyOutput.print(
386
- "未找到 JSS bash completion 配置,无需卸载", OutputType.INFO
335
+ print(
336
+ "ℹ️ 未找到 JSS bash completion 配置,无需卸载"
387
337
  )
388
338
  return
389
339
 
@@ -391,8 +341,8 @@ def uninstall_jss_completion(
391
341
  content = f.read()
392
342
 
393
343
  if start_marker not in content:
394
- PrettyOutput.print(
395
- "未找到 JSS bash completion 配置,无需卸载", OutputType.INFO
344
+ print(
345
+ "ℹ️ 未找到 JSS bash completion 配置,无需卸载"
396
346
  )
397
347
  return
398
348
 
@@ -401,16 +351,16 @@ def uninstall_jss_completion(
401
351
  with open(config_file, "w") as f:
402
352
  f.write(new_content)
403
353
 
404
- PrettyOutput.print(
405
- "JSS bash completion 已卸载,请执行: source ~/.bashrc", OutputType.SUCCESS
354
+ print(
355
+ "JSS bash completion 已卸载,请执行: source ~/.bashrc"
406
356
  )
407
357
  elif shell == "zsh":
408
358
  config_file = _get_zsh_config_file()
409
359
  start_marker, end_marker = _get_zsh_markers()
410
360
 
411
361
  if not os.path.exists(config_file):
412
- PrettyOutput.print(
413
- "未找到 JSS zsh completion 配置,无需卸载", OutputType.INFO
362
+ print(
363
+ "ℹ️ 未找到 JSS zsh completion 配置,无需卸载"
414
364
  )
415
365
  return
416
366
 
@@ -418,8 +368,8 @@ def uninstall_jss_completion(
418
368
  content = f.read()
419
369
 
420
370
  if start_marker not in content:
421
- PrettyOutput.print(
422
- "未找到 JSS zsh completion 配置,无需卸载", OutputType.INFO
371
+ print(
372
+ "ℹ️ 未找到 JSS zsh completion 配置,无需卸载"
423
373
  )
424
374
  return
425
375
 
@@ -428,8 +378,8 @@ def uninstall_jss_completion(
428
378
  with open(config_file, "w") as f:
429
379
  f.write(new_content)
430
380
 
431
- PrettyOutput.print(
432
- "JSS zsh completion 已卸载,请执行: source ~/.zshrc", OutputType.SUCCESS
381
+ print(
382
+ "JSS zsh completion 已卸载,请执行: source ~/.zshrc"
433
383
  )
434
384
 
435
385
 
@@ -444,6 +394,7 @@ def process_request(request: str) -> Optional[str]:
444
394
  """
445
395
  try:
446
396
  # Get language model instance
397
+ # 使用normal平台,智能shell命令生成是一般任务
447
398
  model = PlatformRegistry.get_global_platform_registry().get_normal_platform()
448
399
 
449
400
  shell = get_shell_name()
@@ -379,7 +379,7 @@ def demo():
379
379
  def main():
380
380
  """主入口函数"""
381
381
  # 初始化环境,防止设置初始化太迟
382
- init_env("欢迎使用 Jarvis-Stats,您的统计分析工具已准备就绪!", None)
382
+ init_env()
383
383
  app()
384
384
 
385
385
 
@@ -9,7 +9,7 @@ from typing import Dict, List, Optional, Union, Any
9
9
 
10
10
  from jarvis.jarvis_stats.storage import StatsStorage
11
11
  from jarvis.jarvis_stats.visualizer import StatsVisualizer
12
- from jarvis.jarvis_utils.output import OutputType, PrettyOutput
12
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput # 保留用于语法高亮
13
13
 
14
14
 
15
15
  class StatsManager:
@@ -549,8 +549,8 @@ class StatsManager:
549
549
  )
550
550
 
551
551
  if not aggregated:
552
- PrettyOutput.print(
553
- f"没有找到指标 '{metric_name}' 的数据", OutputType.WARNING
552
+ print(
553
+ f"⚠️ 没有找到指标 '{metric_name}' 的数据"
554
554
  )
555
555
  return
556
556
 
@@ -585,7 +585,7 @@ class StatsManager:
585
585
  show_values=True,
586
586
  )
587
587
 
588
- PrettyOutput.print(chart, OutputType.CODE, lang="text")
588
+ PrettyOutput.print(chart, OutputType.CODE, lang="text") # 保留用于语法高亮
589
589
 
590
590
  # 显示时间范围
591
591
  from rich.panel import Panel
@@ -681,8 +681,8 @@ class StatsManager:
681
681
  )
682
682
 
683
683
  if not aggregated:
684
- PrettyOutput.print(
685
- f"没有找到指标 '{metric_name}' 的数据", OutputType.WARNING
684
+ print(
685
+ f"⚠️ 没有找到指标 '{metric_name}' 的数据"
686
686
  )
687
687
  return
688
688
 
@@ -693,7 +693,7 @@ class StatsManager:
693
693
  # 显示汇总
694
694
  summary = visualizer.show_summary(aggregated, metric_name, unit, tags)
695
695
  if summary: # 如果返回了内容才打印(兼容性)
696
- PrettyOutput.print(summary, OutputType.INFO)
696
+ print(f"ℹ️ {summary}")
697
697
 
698
698
  # 显示时间范围
699
699
  from rich.panel import Panel
@@ -71,7 +71,7 @@ class StatsStorage:
71
71
  with open(filepath, "r", encoding="utf-8") as f:
72
72
  data = json.load(f)
73
73
  return data
74
- except (json.JSONDecodeError, IOError):
74
+ except Exception:
75
75
  if attempt < max_retries - 1:
76
76
  time.sleep(0.1 * (attempt + 1)) # 递增延迟
77
77
  continue
@@ -160,6 +160,9 @@ class StatsStorage:
160
160
 
161
161
  # 更新元数据
162
162
  meta = self._load_json(self.meta_file)
163
+ # 确保 meta 字典中有 "metrics" 键
164
+ if "metrics" not in meta:
165
+ meta["metrics"] = {}
163
166
  if metric_name not in meta["metrics"]:
164
167
  meta["metrics"][metric_name] = {
165
168
  "unit": unit,
@@ -218,9 +221,9 @@ class StatsStorage:
218
221
  new_total = current_total + float(value)
219
222
  self._save_text_atomic(total_file, str(new_total))
220
223
  else:
221
- # 首次生成:扫描历史数据(包含刚写入的这条记录)并写入
222
- # 注意:get_metric_total 内部会完成扫描并写入 totals 文件,这里无需再额外写入或累加
223
- _ = self.get_metric_total(metric_name)
224
+ # 首次生成:直接写入当前值,避免扫描所有历史文件
225
+ # 如果后续需要精确总量,可以通过 get_metric_total 重新计算
226
+ self._save_text_atomic(total_file, str(float(value)))
224
227
  except Exception:
225
228
  # 静默失败,不影响主流程
226
229
  pass
@@ -452,21 +455,11 @@ class StatsStorage:
452
455
 
453
456
  def list_metrics(self) -> List[str]:
454
457
  """列出所有指标"""
455
- # 从元数据文件获取指标
458
+ # 从元数据文件获取指标(主要来源,避免扫描所有历史文件)
456
459
  meta = self._load_json(self.meta_file)
457
460
  metrics_from_meta = set(meta.get("metrics", {}).keys())
458
461
 
459
- # 扫描所有数据文件获取实际存在的指标
460
- metrics_from_data: Set[str] = set()
461
- for data_file in self.data_dir.glob("stats_*.json"):
462
- try:
463
- data = self._load_json(data_file)
464
- metrics_from_data.update(data.keys())
465
- except (json.JSONDecodeError, OSError):
466
- # 忽略无法读取的文件
467
- continue
468
-
469
- # 扫描总量缓存目录中已有的指标文件
462
+ # 扫描总量缓存目录中已有的指标文件(快速)
470
463
  metrics_from_totals: Set[str] = set()
471
464
  try:
472
465
  for f in self.totals_dir.glob("*"):
@@ -475,10 +468,9 @@ class StatsStorage:
475
468
  except Exception:
476
469
  pass
477
470
 
478
- # 合并三个来源的指标并返回排序后的列表
479
- all_metrics = metrics_from_meta.union(metrics_from_data).union(
480
- metrics_from_totals
481
- )
471
+ # 合并两个来源的指标并返回排序后的列表
472
+ # 注意:不再扫描所有历史数据文件,避免性能问题
473
+ all_metrics = metrics_from_meta.union(metrics_from_totals)
482
474
  return sorted(list(all_metrics))
483
475
 
484
476
  def aggregate_metrics(
@@ -560,7 +552,9 @@ class StatsStorage:
560
552
  """
561
553
  # 检查指标是否存在
562
554
  meta = self._load_json(self.meta_file)
563
- if metric_name not in meta.get("metrics", {}):
555
+ if "metrics" not in meta:
556
+ meta["metrics"] = {}
557
+ if metric_name not in meta["metrics"]:
564
558
  return False
565
559
 
566
560
  # 从元数据中删除指标
@@ -4,7 +4,6 @@ from pathlib import Path
4
4
  from typing import Any, Dict, List, Optional
5
5
 
6
6
  from jarvis.jarvis_utils.config import get_data_dir
7
- from jarvis.jarvis_utils.output import OutputType, PrettyOutput
8
7
  from jarvis.jarvis_utils.globals import (
9
8
  clear_short_term_memories,
10
9
  short_term_memories,
@@ -15,21 +14,7 @@ class ClearMemoryTool:
15
14
  """清除记忆工具,用于批量清除指定的记忆"""
16
15
 
17
16
  name = "clear_memory"
18
- description = """批量清除指定的记忆。
19
-
20
- 支持的清除方式:
21
- 1. 按记忆类型清除所有记忆
22
- 2. 按标签清除特定记忆
23
- 3. 按记忆ID清除单个记忆
24
-
25
- 支持的记忆类型:
26
- - project_long_term: 项目长期记忆
27
- - global_long_term: 全局长期记忆
28
- - short_term: 短期记忆
29
- - all: 所有类型的记忆
30
-
31
- 注意:清除操作不可恢复,请谨慎使用
32
- """
17
+ description = "批量清除指定的记忆。支持按类型、标签或ID清除。记忆类型:project_long_term/global_long_term/short_term/all。注意:清除操作不可恢复。"
33
18
 
34
19
  parameters = {
35
20
  "type": "object",
@@ -160,9 +145,7 @@ class ClearMemoryTool:
160
145
  removed_count += 1
161
146
 
162
147
  except Exception as e:
163
- PrettyOutput.print(
164
- f"处理记忆文件 {memory_file} 时出错: {str(e)}", OutputType.WARNING
165
- )
148
+ print(f"⚠️ 处理记忆文件 {memory_file} 时出错: {str(e)}")
166
149
 
167
150
  # 如果目录为空,可以删除目录
168
151
  if not any(memory_dir.iterdir()) and memory_dir != self.project_memory_dir:
@@ -235,5 +218,5 @@ class ClearMemoryTool:
235
218
 
236
219
  except Exception as e:
237
220
  error_msg = f"清除记忆失败: {str(e)}"
238
- PrettyOutput.print(error_msg, OutputType.ERROR)
221
+ print(f"❌ {error_msg}")
239
222
  return {"success": False, "stdout": "", "stderr": error_msg}
@@ -38,7 +38,7 @@ def list_tools(
38
38
  lang="json",
39
39
  )
40
40
  else:
41
- PrettyOutput.section("可用工具列表", OutputType.SYSTEM)
41
+ print("📋 可用工具列表")
42
42
  # 为避免 PrettyOutput 对每行加框造成信息稀疏,先拼接字符串再统一打印
43
43
  lines = []
44
44
  import json as _json # local import to ensure available
@@ -54,7 +54,7 @@ def list_tools(
54
54
  except Exception:
55
55
  lines.append(str(tool.get("parameters")))
56
56
  lines.append("```")
57
- PrettyOutput.print("\n".join(lines), OutputType.INFO, lang="markdown")
57
+ PrettyOutput.print("\n".join(lines), OutputType.CODE, lang="markdown")
58
58
 
59
59
 
60
60
  @app.command("stat")
@@ -90,7 +90,7 @@ def stat_tools(
90
90
  )
91
91
  else:
92
92
  time_desc = f"最近{last_days}天" if last_days else "所有历史"
93
- PrettyOutput.section(f"工具调用统计 ({time_desc})", OutputType.SYSTEM)
93
+ print(f"📊 工具调用统计 ({time_desc})")
94
94
  if table_data:
95
95
  PrettyOutput.print(
96
96
  tabulate(
@@ -99,15 +99,12 @@ def stat_tools(
99
99
  OutputType.CODE,
100
100
  lang="text",
101
101
  )
102
- PrettyOutput.print(
103
- f"\n总计: {len(table_data)} 个工具被使用,共 {sum(x[1] for x in table_data)} 次调用",
104
- OutputType.INFO,
105
- )
102
+ print(f"ℹ️ 总计: {len(table_data)} 个工具被使用,共 {sum(x[1] for x in table_data)} 次调用")
106
103
  else:
107
- PrettyOutput.print("暂无工具调用记录", OutputType.INFO)
104
+ print("ℹ️ 暂无工具调用记录")
108
105
  else:
109
106
  # 使用 stats 系统的高级功能
110
- PrettyOutput.section("工具组统计", OutputType.SYSTEM)
107
+ print("📊 工具组统计")
111
108
  # 显示所有标记为 tool 组的指标
112
109
  metrics = StatsManager.list_metrics()
113
110
  tool_metrics = []
@@ -166,7 +163,7 @@ def stat_tools(
166
163
  tags={"group": "tool"},
167
164
  )
168
165
  else:
169
- PrettyOutput.print("暂无工具调用记录", OutputType.INFO)
166
+ print("ℹ️ 暂无工具调用记录")
170
167
 
171
168
 
172
169
  @app.command("call")
@@ -182,24 +179,24 @@ def call_tool(
182
179
  tool_obj = registry.get_tool(tool_name)
183
180
 
184
181
  if not tool_obj:
185
- PrettyOutput.print(f"错误: 工具 '{tool_name}' 不存在", OutputType.ERROR)
182
+ print(f"错误: 工具 '{tool_name}' 不存在")
186
183
  available_tools = ", ".join([t["name"] for t in registry.get_all_tools()])
187
- PrettyOutput.print(f"可用工具: {available_tools}", OutputType.INFO)
184
+ print(f"ℹ️ 可用工具: {available_tools}")
188
185
  raise typer.Exit(code=1)
189
186
 
190
187
  tool_args = {}
191
188
  if args:
192
189
  try:
193
190
  tool_args = json.loads(args)
194
- except json.JSONDecodeError:
195
- PrettyOutput.print("错误: 参数必须是有效的JSON格式", OutputType.ERROR)
191
+ except Exception:
192
+ print("错误: 参数必须是有效的JSON格式")
196
193
  raise typer.Exit(code=1)
197
194
  elif args_file:
198
195
  try:
199
196
  with open(args_file, "r", encoding="utf-8") as f:
200
197
  tool_args = json.load(f)
201
- except (json.JSONDecodeError, FileNotFoundError) as e:
202
- PrettyOutput.print(f"错误: 无法从文件加载参数: {str(e)}", OutputType.ERROR)
198
+ except (Exception, FileNotFoundError) as e:
199
+ print(f"错误: 无法从文件加载参数: {str(e)}")
203
200
  raise typer.Exit(code=1)
204
201
 
205
202
  required_params = tool_obj.parameters.get("required", [])
@@ -217,23 +214,23 @@ def call_tool(
217
214
  param_info = params.get(param_name, {})
218
215
  desc = param_info.get("description", "无描述")
219
216
  lines.append(f" - {param_name}: {desc}")
220
- PrettyOutput.print("\n".join(lines), OutputType.ERROR)
217
+ print("❌ " + "\n".join(lines))
221
218
  raise typer.Exit(code=1)
222
219
 
223
220
  result = registry.execute_tool(tool_name, tool_args)
224
221
 
225
222
  if result["success"]:
226
- PrettyOutput.section(f"工具 {tool_name} 执行成功", OutputType.SUCCESS)
223
+ print(f"工具 {tool_name} 执行成功")
227
224
  else:
228
- PrettyOutput.section(f"工具 {tool_name} 执行失败", OutputType.ERROR)
225
+ print(f"工具 {tool_name} 执行失败")
229
226
 
230
227
  if result.get("stdout"):
231
- PrettyOutput.print("\n输出:", OutputType.INFO)
228
+ print("\n📤 输出:")
232
229
  PrettyOutput.print(result["stdout"], OutputType.CODE, lang="text")
233
230
 
234
231
  if result.get("stderr"):
235
- PrettyOutput.print("\n错误:", OutputType.ERROR)
236
- PrettyOutput.print(result["stderr"], OutputType.ERROR, lang="text")
232
+ print("\n错误:")
233
+ PrettyOutput.print(result["stderr"], OutputType.CODE, lang="text")
237
234
 
238
235
  if not result["success"]:
239
236
  raise typer.Exit(code=1)
@@ -241,7 +238,7 @@ def call_tool(
241
238
 
242
239
  def cli():
243
240
  """Typer application entry point"""
244
- init_env("欢迎使用 Jarvis-Tools,您的工具系统已准备就绪!")
241
+ init_env()
245
242
  app()
246
243
 
247
244