jarvis-ai-assistant 0.3.18__py3-none-any.whl → 0.3.20__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 (54) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +30 -12
  3. jarvis/jarvis_agent/config_editor.py +1 -1
  4. jarvis/jarvis_agent/edit_file_handler.py +8 -13
  5. jarvis/jarvis_agent/memory_manager.py +4 -4
  6. jarvis/jarvis_agent/shell_input_handler.py +17 -2
  7. jarvis/jarvis_agent/task_analyzer.py +4 -3
  8. jarvis/jarvis_agent/task_manager.py +6 -6
  9. jarvis/jarvis_agent/tool_executor.py +2 -2
  10. jarvis/jarvis_code_agent/code_agent.py +21 -29
  11. jarvis/jarvis_code_analysis/code_review.py +2 -4
  12. jarvis/jarvis_git_utils/git_commiter.py +17 -18
  13. jarvis/jarvis_methodology/main.py +12 -12
  14. jarvis/jarvis_platform/ai8.py +0 -4
  15. jarvis/jarvis_platform/base.py +16 -15
  16. jarvis/jarvis_platform/kimi.py +13 -13
  17. jarvis/jarvis_platform/tongyi.py +17 -15
  18. jarvis/jarvis_platform/yuanbao.py +11 -11
  19. jarvis/jarvis_platform_manager/service.py +2 -2
  20. jarvis/jarvis_rag/cli.py +36 -32
  21. jarvis/jarvis_rag/embedding_manager.py +11 -6
  22. jarvis/jarvis_rag/llm_interface.py +6 -5
  23. jarvis/jarvis_rag/rag_pipeline.py +9 -8
  24. jarvis/jarvis_rag/reranker.py +3 -2
  25. jarvis/jarvis_rag/retriever.py +18 -8
  26. jarvis/jarvis_smart_shell/main.py +307 -47
  27. jarvis/jarvis_stats/cli.py +2 -1
  28. jarvis/jarvis_stats/stats.py +45 -5
  29. jarvis/jarvis_stats/storage.py +220 -9
  30. jarvis/jarvis_tools/clear_memory.py +0 -11
  31. jarvis/jarvis_tools/cli/main.py +18 -17
  32. jarvis/jarvis_tools/edit_file.py +4 -4
  33. jarvis/jarvis_tools/execute_script.py +5 -1
  34. jarvis/jarvis_tools/file_analyzer.py +6 -6
  35. jarvis/jarvis_tools/generate_new_tool.py +6 -17
  36. jarvis/jarvis_tools/read_code.py +3 -6
  37. jarvis/jarvis_tools/read_webpage.py +4 -4
  38. jarvis/jarvis_tools/registry.py +8 -28
  39. jarvis/jarvis_tools/retrieve_memory.py +5 -16
  40. jarvis/jarvis_tools/rewrite_file.py +0 -4
  41. jarvis/jarvis_tools/save_memory.py +2 -10
  42. jarvis/jarvis_tools/search_web.py +5 -8
  43. jarvis/jarvis_tools/virtual_tty.py +22 -40
  44. jarvis/jarvis_utils/clipboard.py +2 -2
  45. jarvis/jarvis_utils/input.py +316 -30
  46. jarvis/jarvis_utils/methodology.py +3 -3
  47. jarvis/jarvis_utils/output.py +215 -135
  48. jarvis/jarvis_utils/utils.py +35 -58
  49. {jarvis_ai_assistant-0.3.18.dist-info → jarvis_ai_assistant-0.3.20.dist-info}/METADATA +1 -1
  50. {jarvis_ai_assistant-0.3.18.dist-info → jarvis_ai_assistant-0.3.20.dist-info}/RECORD +54 -54
  51. {jarvis_ai_assistant-0.3.18.dist-info → jarvis_ai_assistant-0.3.20.dist-info}/WHEEL +0 -0
  52. {jarvis_ai_assistant-0.3.18.dist-info → jarvis_ai_assistant-0.3.20.dist-info}/entry_points.txt +0 -0
  53. {jarvis_ai_assistant-0.3.18.dist-info → jarvis_ai_assistant-0.3.20.dist-info}/licenses/LICENSE +0 -0
  54. {jarvis_ai_assistant-0.3.18.dist-info → jarvis_ai_assistant-0.3.20.dist-info}/top_level.txt +0 -0
@@ -10,7 +10,7 @@
10
10
  """
11
11
  from datetime import datetime
12
12
  from enum import Enum
13
- from typing import Dict, Optional, Tuple, Any
13
+ from typing import Dict, Optional, Tuple, Any, List
14
14
 
15
15
  from pygments.lexers import guess_lexer
16
16
  from pygments.util import ClassNotFound
@@ -22,6 +22,8 @@ from rich.text import Text
22
22
 
23
23
  from jarvis.jarvis_utils.config import get_pretty_output
24
24
  from jarvis.jarvis_utils.globals import console, get_agent_list
25
+ from dataclasses import dataclass
26
+ from abc import ABC, abstractmethod
25
27
 
26
28
 
27
29
  class OutputType(Enum):
@@ -57,6 +59,181 @@ class OutputType(Enum):
57
59
  TOOL = "TOOL"
58
60
 
59
61
 
62
+ @dataclass
63
+ class OutputEvent:
64
+ """
65
+ 输出事件的通用结构,供不同输出后端(Sink)消费。
66
+ - text: 文本内容
67
+ - output_type: 输出类型
68
+ - timestamp: 是否显示时间戳
69
+ - lang: 语法高亮语言(可选,不提供则自动检测)
70
+ - traceback: 是否显示异常堆栈
71
+ - section: 若为章节标题输出,填入标题文本;否则为None
72
+ - context: 额外上下文(预留给TUI/日志等)
73
+ """
74
+ text: str
75
+ output_type: OutputType
76
+ timestamp: bool = True
77
+ lang: Optional[str] = None
78
+ traceback: bool = False
79
+ section: Optional[str] = None
80
+ context: Optional[Dict[str, Any]] = None
81
+
82
+
83
+ class OutputSink(ABC):
84
+ """输出后端抽象接口,不同前端(控制台/TUI/SSE/日志)实现该接口以消费输出事件。"""
85
+
86
+ @abstractmethod
87
+ def emit(self, event: OutputEvent) -> None: # pragma: no cover - 抽象方法
88
+ raise NotImplementedError
89
+
90
+
91
+ class ConsoleOutputSink(OutputSink):
92
+ """
93
+ 默认控制台输出实现,保持与原 PrettyOutput 行为一致。
94
+ """
95
+
96
+ def emit(self, event: OutputEvent) -> None:
97
+ # 章节输出
98
+ if event.section is not None:
99
+ text = Text(event.section, style=event.output_type.value, justify="center")
100
+ panel = Panel(text, border_style=event.output_type.value)
101
+ if get_pretty_output():
102
+ console.print(panel)
103
+ else:
104
+ console.print(text)
105
+ return
106
+
107
+ # 普通内容输出
108
+ lang = (
109
+ event.lang
110
+ if event.lang is not None
111
+ else PrettyOutput._detect_language(event.text, default_lang="markdown")
112
+ )
113
+
114
+ # 与原实现保持一致的样式定义
115
+ styles: Dict[OutputType, Dict[str, Any]] = {
116
+ OutputType.SYSTEM: dict(bgcolor="#1e2b3c"),
117
+ OutputType.CODE: dict(bgcolor="#1c2b1c"),
118
+ OutputType.RESULT: dict(bgcolor="#1c1c2b"),
119
+ OutputType.ERROR: dict(bgcolor="#2b1c1c"),
120
+ OutputType.INFO: dict(bgcolor="#2b2b1c", meta={"icon": "ℹ️"}),
121
+ OutputType.PLANNING: dict(bgcolor="#2b1c2b"),
122
+ OutputType.PROGRESS: dict(bgcolor="#1c1c1c"),
123
+ OutputType.SUCCESS: dict(bgcolor="#1c2b1c"),
124
+ OutputType.WARNING: dict(bgcolor="#2b2b1c"),
125
+ OutputType.DEBUG: dict(bgcolor="#1c1c1c"),
126
+ OutputType.USER: dict(bgcolor="#1c2b2b"),
127
+ OutputType.TOOL: dict(bgcolor="#1c2b2b"),
128
+ }
129
+
130
+ header_styles = {
131
+ OutputType.SYSTEM: RichStyle(
132
+ color="bright_cyan", bgcolor="#1e2b3c", frame=True, meta={"icon": "🤖"}
133
+ ),
134
+ OutputType.CODE: RichStyle(
135
+ color="green", bgcolor="#1c2b1c", frame=True, meta={"icon": "📝"}
136
+ ),
137
+ OutputType.RESULT: RichStyle(
138
+ color="bright_blue", bgcolor="#1c1c2b", frame=True, meta={"icon": "✨"}
139
+ ),
140
+ OutputType.ERROR: RichStyle(
141
+ color="red", frame=True, bgcolor="#2b1c1c", meta={"icon": "❌"}
142
+ ),
143
+ OutputType.INFO: RichStyle(
144
+ color="bright_cyan", frame=True, bgcolor="#2b2b1c", meta={"icon": "ℹ️"}
145
+ ),
146
+ OutputType.PLANNING: RichStyle(
147
+ color="purple",
148
+ bold=True,
149
+ frame=True,
150
+ bgcolor="#2b1c2b",
151
+ meta={"icon": "📋"},
152
+ ),
153
+ OutputType.PROGRESS: RichStyle(
154
+ color="white",
155
+ encircle=True,
156
+ frame=True,
157
+ bgcolor="#1c1c1c",
158
+ meta={"icon": "⏳"},
159
+ ),
160
+ OutputType.SUCCESS: RichStyle(
161
+ color="bright_green",
162
+ bold=True,
163
+ strike=False,
164
+ bgcolor="#1c2b1c",
165
+ meta={"icon": "✅"},
166
+ ),
167
+ OutputType.WARNING: RichStyle(
168
+ color="yellow",
169
+ bold=True,
170
+ blink2=True,
171
+ bgcolor="#2b2b1c",
172
+ meta={"icon": "⚠️"},
173
+ ),
174
+ OutputType.DEBUG: RichStyle(
175
+ color="grey58",
176
+ dim=True,
177
+ conceal=True,
178
+ bgcolor="#1c1c1c",
179
+ meta={"icon": "🔍"},
180
+ ),
181
+ OutputType.USER: RichStyle(
182
+ color="spring_green2",
183
+ frame=True,
184
+ bgcolor="#1c2b2b",
185
+ meta={"icon": "👤"},
186
+ ),
187
+ OutputType.TOOL: RichStyle(
188
+ color="dark_sea_green4",
189
+ bgcolor="#1c2b2b",
190
+ frame=True,
191
+ meta={"icon": "🔧"},
192
+ ),
193
+ }
194
+
195
+ header = Text(
196
+ PrettyOutput._format(event.output_type, event.timestamp),
197
+ style=header_styles[event.output_type],
198
+ )
199
+ content = Syntax(
200
+ event.text,
201
+ lang,
202
+ theme="monokai",
203
+ word_wrap=True,
204
+ background_color=styles[event.output_type]["bgcolor"],
205
+ )
206
+ panel = Panel(
207
+ content,
208
+ border_style=header_styles[event.output_type],
209
+ padding=(0, 0),
210
+ highlight=True,
211
+ )
212
+ if get_pretty_output():
213
+ console.print(panel)
214
+ else:
215
+ console.print(content)
216
+ if event.traceback or event.output_type == OutputType.ERROR:
217
+ try:
218
+ console.print_exception()
219
+ except Exception as e:
220
+ console.print(f"Error: {e}")
221
+
222
+
223
+ # 模块级输出分发器(默认注册控制台后端)
224
+ _output_sinks: List[OutputSink] = [ConsoleOutputSink()]
225
+
226
+
227
+ def emit_output(event: OutputEvent) -> None:
228
+ """向所有已注册的输出后端广播事件。"""
229
+ for sink in list(_output_sinks):
230
+ try:
231
+ sink.emit(event)
232
+ except Exception as e:
233
+ # 后端故障不影响其他后端
234
+ console.print(f"[输出后端错误] {sink.__class__.__name__}: {e}")
235
+
236
+
60
237
  class PrettyOutput:
61
238
  """
62
239
  使用rich库格式化和显示富文本输出的类。
@@ -166,148 +343,51 @@ class PrettyOutput:
166
343
  traceback: bool = False,
167
344
  ):
168
345
  """
169
- 使用样式和语法高亮打印格式化输出。
170
-
171
- 参数:
172
- text: 要打印的文本内容
173
- output_type: 输出类型(影响样式)
174
- timestamp: 是否显示时间戳
175
- lang: 语法高亮的语言
176
- traceback: 是否显示错误的回溯信息
346
+ 使用样式和语法高亮打印格式化输出(已抽象为事件 + Sink 机制)。
347
+ 保持对现有调用方的向后兼容,同时为TUI/日志等前端预留扩展点。
177
348
  """
178
- styles: Dict[OutputType, Dict[str, Any]] = {
179
- OutputType.SYSTEM: dict(bgcolor="#1e2b3c"),
180
- OutputType.CODE: dict(bgcolor="#1c2b1c"),
181
- OutputType.RESULT: dict(bgcolor="#1c1c2b"),
182
- OutputType.ERROR: dict(bgcolor="#2b1c1c"),
183
- OutputType.INFO: dict(bgcolor="#2b2b1c", meta={"icon": "ℹ️"}),
184
- OutputType.PLANNING: dict(bgcolor="#2b1c2b"),
185
- OutputType.PROGRESS: dict(bgcolor="#1c1c1c"),
186
- OutputType.SUCCESS: dict(bgcolor="#1c2b1c"),
187
- OutputType.WARNING: dict(bgcolor="#2b2b1c"),
188
- OutputType.DEBUG: dict(bgcolor="#1c1c1c"),
189
- OutputType.USER: dict(bgcolor="#1c2b2b"),
190
- OutputType.TOOL: dict(bgcolor="#1c2b2b"),
191
- }
192
-
193
- header_styles = {
194
- OutputType.SYSTEM: RichStyle(
195
- color="bright_cyan", bgcolor="#1e2b3c", frame=True, meta={"icon": "🤖"}
196
- ),
197
- OutputType.CODE: RichStyle(
198
- color="green", bgcolor="#1c2b1c", frame=True, meta={"icon": "📝"}
199
- ),
200
- OutputType.RESULT: RichStyle(
201
- color="bright_blue", bgcolor="#1c1c2b", frame=True, meta={"icon": "✨"}
202
- ),
203
- OutputType.ERROR: RichStyle(
204
- color="red", frame=True, bgcolor="#2b1c1c", meta={"icon": "❌"}
205
- ),
206
- OutputType.INFO: RichStyle(
207
- color="bright_cyan", frame=True, bgcolor="#2b2b1c", meta={"icon": "ℹ️"}
208
- ),
209
- OutputType.PLANNING: RichStyle(
210
- color="purple",
211
- bold=True,
212
- frame=True,
213
- bgcolor="#2b1c2b",
214
- meta={"icon": "📋"},
215
- ),
216
- OutputType.PROGRESS: RichStyle(
217
- color="white",
218
- encircle=True,
219
- frame=True,
220
- bgcolor="#1c1c1c",
221
- meta={"icon": "⏳"},
222
- ),
223
- OutputType.SUCCESS: RichStyle(
224
- color="bright_green",
225
- bold=True,
226
- strike=False,
227
- bgcolor="#1c2b1c",
228
- meta={"icon": "✅"},
229
- ),
230
- OutputType.WARNING: RichStyle(
231
- color="yellow",
232
- bold=True,
233
- blink2=True,
234
- bgcolor="#2b2b1c",
235
- meta={"icon": "⚠️"},
236
- ),
237
- OutputType.DEBUG: RichStyle(
238
- color="grey58",
239
- dim=True,
240
- conceal=True,
241
- bgcolor="#1c1c1c",
242
- meta={"icon": "🔍"},
243
- ),
244
- OutputType.USER: RichStyle(
245
- color="spring_green2",
246
- frame=True,
247
- bgcolor="#1c2b2b",
248
- meta={"icon": "👤"},
249
- ),
250
- OutputType.TOOL: RichStyle(
251
- color="dark_sea_green4",
252
- bgcolor="#1c2b2b",
253
- frame=True,
254
- meta={"icon": "🔧"},
255
- ),
256
- }
257
-
258
- lang = (
259
- lang
260
- if lang is not None
261
- else PrettyOutput._detect_language(text, default_lang="markdown")
349
+ event = OutputEvent(
350
+ text=text,
351
+ output_type=output_type,
352
+ timestamp=timestamp,
353
+ lang=lang,
354
+ traceback=traceback,
262
355
  )
263
- header = Text(
264
- PrettyOutput._format(output_type, timestamp),
265
- style=header_styles[output_type],
266
- )
267
- content = Syntax(
268
- text,
269
- lang,
270
- theme="monokai",
271
- word_wrap=True,
272
- background_color=styles[output_type]["bgcolor"],
273
- )
274
- panel = Panel(
275
- content,
276
- border_style=header_styles[output_type],
277
- title=header,
278
- title_align="left",
279
- padding=(0, 0),
280
- highlight=True,
281
- )
282
- if get_pretty_output():
283
- console.print(panel)
284
- else:
285
- if len(text.strip().splitlines()) > 1:
286
- console.print(header)
287
- console.print(content)
288
- else:
289
- console.print(header, content)
290
- if traceback or output_type == OutputType.ERROR:
291
- try:
292
- console.print_exception()
293
- except Exception as e:
294
- console.print(f"Error: {e}")
356
+ emit_output(event)
295
357
 
296
358
  @staticmethod
297
359
  def section(title: str, output_type: OutputType = OutputType.INFO):
298
360
  """
299
- 在样式化面板中打印章节标题。
300
-
301
- 参数:
302
- title: 章节标题文本
303
- output_type: 输出类型(影响样式)
361
+ 在样式化面板中打印章节标题(通过事件 + Sink 机制分发)。
304
362
  """
305
- text = Text(title, style=output_type.value, justify="center")
306
- panel = Panel(text, border_style=output_type.value)
307
- if get_pretty_output():
308
- console.print(panel)
363
+ event = OutputEvent(
364
+ text="",
365
+ output_type=output_type,
366
+ section=title,
367
+ )
368
+ emit_output(event)
369
+
370
+ @staticmethod
371
+ # Sink管理(为外部注册自定义后端预留)
372
+ @staticmethod
373
+ def add_sink(sink: OutputSink) -> None:
374
+ """注册一个新的输出后端。"""
375
+ _output_sinks.append(sink)
376
+
377
+ @staticmethod
378
+ def clear_sinks(keep_default: bool = True) -> None:
379
+ """清空已注册的输出后端;可选择保留默认控制台后端。"""
380
+ if keep_default:
381
+ globals()["_output_sinks"] = [
382
+ s for s in _output_sinks if isinstance(s, ConsoleOutputSink)
383
+ ]
309
384
  else:
310
- console.print(text)
385
+ _output_sinks.clear()
386
+
387
+ @staticmethod
388
+ def get_sinks() -> List[OutputSink]:
389
+ """获取当前已注册的输出后端列表(副本)。"""
390
+ return list(_output_sinks)
311
391
 
312
392
  @staticmethod
313
393
  def print_gradient_text(
@@ -139,7 +139,7 @@ def _check_pip_updates() -> bool:
139
139
  # 检测是否安装了 RAG 特性
140
140
  rag_installed = False
141
141
  try:
142
- import langchain # noqa
142
+ import langchain # type: ignore # noqa
143
143
 
144
144
  rag_installed = True
145
145
  except ImportError:
@@ -212,46 +212,37 @@ def _show_usage_stats(welcome_str: str) -> None:
212
212
  "commit": {"title": "💾 提交统计", "metrics": {}, "suffix": "个"},
213
213
  "command": {"title": "📱 命令使用", "metrics": {}, "suffix": "次"},
214
214
  "adoption": {"title": "🎯 采纳情况", "metrics": {}, "suffix": ""},
215
+ "other": {"title": "📦 其他指标", "metrics": {}, "suffix": ""},
215
216
  }
216
217
 
217
- # 遍历所有指标,获取统计数据
218
+ # 遍历所有指标,使用快速总量读取以避免全量扫描
218
219
  for metric in all_metrics:
219
- # 获取该指标的所有数据
220
- stats_data = StatsManager.get_stats(
221
- metric_name=metric,
222
- start_time=datetime(2000, 1, 1),
223
- end_time=datetime.now(),
224
- )
220
+ try:
221
+ total = StatsManager.get_metric_total(metric)
222
+ except Exception:
223
+ total = 0.0
225
224
 
226
- if stats_data and isinstance(stats_data, dict) and "records" in stats_data:
227
- # 按照标签分组统计
228
- tag_totals: Dict[str, float] = {}
229
- for record in stats_data["records"]:
230
- tags = record.get("tags", {})
231
- group = tags.get("group", "other")
232
- tag_totals[group] = tag_totals.get(group, 0) + record["value"]
233
-
234
- # 根据标签将指标分配到相应类别
235
- for group, total in tag_totals.items():
236
- if total > 0:
237
- if group == "tool":
238
- categorized_stats["tool"]["metrics"][metric] = int(total)
239
- elif group == "code_agent":
240
- # 根据指标名称细分
241
- if metric.startswith("code_lines_"):
242
- categorized_stats["lines"]["metrics"][metric] = int(
243
- total
244
- )
245
- elif "commit" in metric:
246
- categorized_stats["commit"]["metrics"][metric] = int(
247
- total
248
- )
249
- else:
250
- categorized_stats["code"]["metrics"][metric] = int(
251
- total
252
- )
253
- elif group == "command":
254
- categorized_stats["command"]["metrics"][metric] = int(total)
225
+ if not total or total <= 0:
226
+ continue
227
+
228
+ # 优先使用元信息中的分组(在写入指标时已记录)
229
+ info = StatsManager.get_metric_info(metric) or {}
230
+ group = info.get("group", "other")
231
+
232
+ if group == "tool":
233
+ categorized_stats["tool"]["metrics"][metric] = int(total)
234
+ elif group == "code_agent":
235
+ # 根据指标名称细分
236
+ if metric.startswith("code_lines_"):
237
+ categorized_stats["lines"]["metrics"][metric] = int(total)
238
+ elif "commit" in metric:
239
+ categorized_stats["commit"]["metrics"][metric] = int(total)
240
+ else:
241
+ categorized_stats["code"]["metrics"][metric] = int(total)
242
+ elif group == "command":
243
+ categorized_stats["command"]["metrics"][metric] = int(total)
244
+ else:
245
+ categorized_stats["other"]["metrics"][metric] = int(total)
255
246
 
256
247
  # 合并长短命令的历史统计数据
257
248
  command_stats = categorized_stats["command"]["metrics"]
@@ -560,7 +551,7 @@ def _show_usage_stats(welcome_str: str) -> None:
560
551
  layout_items: List[RenderableType] = []
561
552
  layout_items.append(right_column_group)
562
553
  if has_content:
563
- layout_items.append(table)
554
+ layout_items.append(Align.center(table))
564
555
  layout_renderable = Group(*layout_items)
565
556
  else:
566
557
  # 左右布局(当前)
@@ -576,8 +567,8 @@ def _show_usage_stats(welcome_str: str) -> None:
576
567
  layout_table.add_column(ratio=5) # 右侧
577
568
 
578
569
  if has_content:
579
- # 将总结信息放在左侧,统计表格放在右侧
580
- layout_table.add_row(right_column_group, table)
570
+ # 将总结信息放在左侧,统计表格放在右侧(表格居中显示)
571
+ layout_table.add_row(right_column_group, Align.center(table))
581
572
  else:
582
573
  # 如果没有统计数据,则总结信息占满
583
574
  layout_table.add_row(right_column_group)
@@ -1161,7 +1152,7 @@ def while_success(func: Callable[[], Any], sleep_time: float = 0.1) -> Any:
1161
1152
  return func()
1162
1153
  except Exception as e:
1163
1154
  PrettyOutput.print(
1164
- f"执行失败: {str(e)}, 等待 {sleep_time}s...", OutputType.WARNING
1155
+ f"重试中,等待 {sleep_time}s...", OutputType.WARNING
1165
1156
  )
1166
1157
  time.sleep(sleep_time)
1167
1158
  continue
@@ -1185,7 +1176,7 @@ def while_true(func: Callable[[], bool], sleep_time: float = 0.1) -> Any:
1185
1176
  ret = func()
1186
1177
  if ret:
1187
1178
  break
1188
- PrettyOutput.print(f"执行失败, 等待 {sleep_time}s...", OutputType.WARNING)
1179
+ PrettyOutput.print(f"重试中,等待 {sleep_time}s...", OutputType.WARNING)
1189
1180
  time.sleep(sleep_time)
1190
1181
  return ret
1191
1182
 
@@ -1267,7 +1258,7 @@ def _pull_git_repo(repo_path: Path, repo_type: str):
1267
1258
  if not git_dir.is_dir():
1268
1259
  return
1269
1260
 
1270
- PrettyOutput.print(f"正在更新{repo_type}库 '{repo_path.name}'...", OutputType.INFO)
1261
+
1271
1262
  try:
1272
1263
  # 检查是否有远程仓库
1273
1264
  remote_result = subprocess.run(
@@ -1281,10 +1272,6 @@ def _pull_git_repo(repo_path: Path, repo_type: str):
1281
1272
  timeout=10,
1282
1273
  )
1283
1274
  if not remote_result.stdout.strip():
1284
- PrettyOutput.print(
1285
- f"'{repo_path.name}' 未配置远程仓库,跳过更新。",
1286
- OutputType.INFO,
1287
- )
1288
1275
  return
1289
1276
 
1290
1277
  # 检查git仓库状态
@@ -1356,10 +1343,6 @@ def _pull_git_repo(repo_path: Path, repo_type: str):
1356
1343
  )
1357
1344
 
1358
1345
  if not ls_remote_result.stdout.strip():
1359
- PrettyOutput.print(
1360
- f"{repo_type}库 '{repo_path.name}' 的远程仓库是空的,跳过更新。",
1361
- OutputType.INFO,
1362
- )
1363
1346
  return
1364
1347
 
1365
1348
  # 执行 git pull
@@ -1387,12 +1370,6 @@ def _pull_git_repo(repo_path: Path, repo_type: str):
1387
1370
  PrettyOutput.print(
1388
1371
  f"{repo_type}库 '{repo_path.name}' 已更新。", OutputType.SUCCESS
1389
1372
  )
1390
- if pull_result.stdout.strip():
1391
- PrettyOutput.print(pull_result.stdout.strip(), OutputType.INFO)
1392
- else:
1393
- PrettyOutput.print(
1394
- f"{repo_type}库 '{repo_path.name}' 已是最新版本。", OutputType.INFO
1395
- )
1396
1373
 
1397
1374
  except FileNotFoundError:
1398
1375
  PrettyOutput.print(
@@ -1433,7 +1410,7 @@ def daily_check_git_updates(repo_dirs: List[str], repo_type: str):
1433
1410
  pass
1434
1411
 
1435
1412
  if should_check_for_updates:
1436
- PrettyOutput.print(f"执行每日{repo_type}库更新检查...", OutputType.INFO)
1413
+
1437
1414
  for repo_dir in repo_dirs:
1438
1415
  p_repo_dir = Path(repo_dir)
1439
1416
  if p_repo_dir.exists() and p_repo_dir.is_dir():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jarvis-ai-assistant
3
- Version: 0.3.18
3
+ Version: 0.3.20
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