jarvis-ai-assistant 0.1.131__py3-none-any.whl → 0.1.132__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 (61) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +48 -29
  3. jarvis/jarvis_agent/patch.py +61 -43
  4. jarvis/jarvis_agent/shell_input_handler.py +1 -1
  5. jarvis/jarvis_code_agent/code_agent.py +87 -86
  6. jarvis/jarvis_dev/main.py +335 -626
  7. jarvis/jarvis_git_squash/main.py +10 -31
  8. jarvis/jarvis_multi_agent/__init__.py +19 -28
  9. jarvis/jarvis_platform/ai8.py +7 -32
  10. jarvis/jarvis_platform/base.py +2 -7
  11. jarvis/jarvis_platform/kimi.py +3 -144
  12. jarvis/jarvis_platform/ollama.py +54 -68
  13. jarvis/jarvis_platform/openai.py +0 -4
  14. jarvis/jarvis_platform/oyi.py +0 -75
  15. jarvis/jarvis_platform/yuanbao.py +264 -0
  16. jarvis/jarvis_rag/file_processors.py +138 -0
  17. jarvis/jarvis_rag/main.py +1305 -425
  18. jarvis/jarvis_tools/ask_codebase.py +205 -39
  19. jarvis/jarvis_tools/code_review.py +125 -99
  20. jarvis/jarvis_tools/execute_python_script.py +58 -0
  21. jarvis/jarvis_tools/execute_shell.py +13 -26
  22. jarvis/jarvis_tools/execute_shell_script.py +1 -1
  23. jarvis/jarvis_tools/file_analyzer.py +271 -0
  24. jarvis/jarvis_tools/file_operation.py +1 -1
  25. jarvis/jarvis_tools/find_caller.py +213 -0
  26. jarvis/jarvis_tools/find_symbol.py +211 -0
  27. jarvis/jarvis_tools/function_analyzer.py +248 -0
  28. jarvis/jarvis_tools/git_commiter.py +4 -4
  29. jarvis/jarvis_tools/methodology.py +89 -48
  30. jarvis/jarvis_tools/project_analyzer.py +220 -0
  31. jarvis/jarvis_tools/read_code.py +23 -2
  32. jarvis/jarvis_tools/read_webpage.py +195 -81
  33. jarvis/jarvis_tools/registry.py +132 -11
  34. jarvis/jarvis_tools/search_web.py +55 -10
  35. jarvis/jarvis_tools/tool_generator.py +6 -8
  36. jarvis/jarvis_utils/__init__.py +1 -0
  37. jarvis/jarvis_utils/config.py +67 -3
  38. jarvis/jarvis_utils/embedding.py +344 -45
  39. jarvis/jarvis_utils/git_utils.py +9 -1
  40. jarvis/jarvis_utils/input.py +7 -6
  41. jarvis/jarvis_utils/methodology.py +379 -7
  42. jarvis/jarvis_utils/output.py +5 -3
  43. jarvis/jarvis_utils/utils.py +59 -7
  44. {jarvis_ai_assistant-0.1.131.dist-info → jarvis_ai_assistant-0.1.132.dist-info}/METADATA +3 -2
  45. jarvis_ai_assistant-0.1.132.dist-info/RECORD +82 -0
  46. {jarvis_ai_assistant-0.1.131.dist-info → jarvis_ai_assistant-0.1.132.dist-info}/entry_points.txt +2 -0
  47. jarvis/jarvis_codebase/__init__.py +0 -0
  48. jarvis/jarvis_codebase/main.py +0 -1011
  49. jarvis/jarvis_tools/treesitter_analyzer.py +0 -331
  50. jarvis/jarvis_treesitter/README.md +0 -104
  51. jarvis/jarvis_treesitter/__init__.py +0 -20
  52. jarvis/jarvis_treesitter/database.py +0 -258
  53. jarvis/jarvis_treesitter/example.py +0 -115
  54. jarvis/jarvis_treesitter/grammar_builder.py +0 -182
  55. jarvis/jarvis_treesitter/language.py +0 -117
  56. jarvis/jarvis_treesitter/symbol.py +0 -31
  57. jarvis/jarvis_treesitter/tools_usage.md +0 -121
  58. jarvis_ai_assistant-0.1.131.dist-info/RECORD +0 -85
  59. {jarvis_ai_assistant-0.1.131.dist-info → jarvis_ai_assistant-0.1.132.dist-info}/LICENSE +0 -0
  60. {jarvis_ai_assistant-0.1.131.dist-info → jarvis_ai_assistant-0.1.132.dist-info}/WHEEL +0 -0
  61. {jarvis_ai_assistant-0.1.131.dist-info → jarvis_ai_assistant-0.1.132.dist-info}/top_level.txt +0 -0
@@ -9,12 +9,168 @@
9
9
  """
10
10
  import os
11
11
  import yaml
12
+ import glob
13
+ import json
14
+ import hashlib
15
+ import pickle
12
16
  import numpy as np
13
17
  import faiss
14
- from typing import Dict, Any, List
18
+ from typing import Dict, Any, List, Tuple, Optional
15
19
  from jarvis.jarvis_utils.output import PrettyOutput, OutputType
16
20
  from jarvis.jarvis_utils.embedding import load_embedding_model
17
21
  from jarvis.jarvis_utils.config import dont_use_local_model
22
+
23
+ # 全局缓存,避免重复计算嵌入向量
24
+ _methodology_embeddings_cache = {}
25
+ _methodology_index_cache: Optional[Tuple[faiss.IndexIDMap, List[Dict[str, str]], str]] = None
26
+
27
+ def _get_cache_directory() -> str:
28
+ """
29
+ 获取缓存目录路径,如果不存在则创建
30
+
31
+ 返回:
32
+ str: 缓存目录的路径
33
+ """
34
+ cache_dir = os.path.expanduser("~/.jarvis/cache")
35
+ if not os.path.exists(cache_dir):
36
+ try:
37
+ os.makedirs(cache_dir, exist_ok=True)
38
+ except Exception as e:
39
+ PrettyOutput.print(f"创建缓存目录失败: {str(e)}", OutputType.ERROR)
40
+ return cache_dir
41
+
42
+ def _get_embeddings_cache_path() -> str:
43
+ """
44
+ 获取嵌入向量缓存文件的路径
45
+
46
+ 返回:
47
+ str: 嵌入向量缓存文件的路径
48
+ """
49
+ return os.path.join(_get_cache_directory(), "methodology_embeddings.pkl")
50
+
51
+ def _get_index_cache_path() -> str:
52
+ """
53
+ 获取索引缓存文件的路径
54
+
55
+ 返回:
56
+ str: 索引缓存文件的路径
57
+ """
58
+ return os.path.join(_get_cache_directory(), "methodology_index.faiss")
59
+
60
+ def _get_index_metadata_path() -> str:
61
+ """
62
+ 获取索引元数据文件的路径
63
+
64
+ 返回:
65
+ str: 索引元数据文件的路径
66
+ """
67
+ return os.path.join(_get_cache_directory(), "methodology_index_metadata.pkl")
68
+
69
+ def _load_embeddings_cache() -> Dict[int, np.ndarray]:
70
+ """
71
+ 从文件系统加载嵌入向量缓存
72
+
73
+ 返回:
74
+ Dict[int, np.ndarray]: 嵌入向量缓存字典
75
+ """
76
+ cache_path = _get_embeddings_cache_path()
77
+ if not os.path.exists(cache_path):
78
+ return {}
79
+
80
+ try:
81
+ with open(cache_path, "rb") as f:
82
+ embeddings_cache = pickle.load(f)
83
+ return embeddings_cache
84
+ except Exception as e:
85
+ return {}
86
+
87
+ def _save_embeddings_cache(cache: Dict[int, np.ndarray]) -> bool:
88
+ """
89
+ 将嵌入向量缓存保存到文件系统
90
+
91
+ 参数:
92
+ cache: 要保存的嵌入向量缓存字典
93
+
94
+ 返回:
95
+ bool: 保存是否成功
96
+ """
97
+ if not cache:
98
+ return False
99
+
100
+ cache_path = _get_embeddings_cache_path()
101
+
102
+ try:
103
+ with open(cache_path, "wb") as f:
104
+ pickle.dump(cache, f)
105
+ return True
106
+ except Exception as e:
107
+ PrettyOutput.print(f"保存嵌入向量缓存失败: {str(e)}", OutputType.WARNING)
108
+ return False
109
+
110
+ def _load_index_cache() -> Optional[Tuple[faiss.IndexIDMap, List[Dict[str, str]], str]]:
111
+ """
112
+ 从文件系统加载索引缓存
113
+
114
+ 返回:
115
+ Optional[Tuple[faiss.IndexIDMap, List[Dict[str, str]], str]]: 索引缓存元组
116
+ """
117
+ index_path = _get_index_cache_path()
118
+ metadata_path = _get_index_metadata_path()
119
+
120
+ if not os.path.exists(index_path) or not os.path.exists(metadata_path):
121
+ return None
122
+
123
+ try:
124
+ # 加载索引
125
+ index = faiss.read_index(index_path)
126
+
127
+ # 加载元数据
128
+ with open(metadata_path, "rb") as f:
129
+ metadata = pickle.load(f)
130
+
131
+ methodology_data = metadata.get("methodology_data", [])
132
+ methodology_hash = metadata.get("methodology_hash", "")
133
+
134
+ if isinstance(index, faiss.IndexIDMap) and methodology_data and methodology_hash:
135
+ return index, methodology_data, methodology_hash
136
+ except Exception as e:
137
+ PrettyOutput.print(f"加载索引缓存失败: {str(e)}", OutputType.WARNING)
138
+
139
+ return None
140
+
141
+ def _save_index_cache(index: faiss.IndexIDMap, methodology_data: List[Dict[str, str]], methodology_hash: str) -> bool:
142
+ """
143
+ 将索引缓存保存到文件系统
144
+
145
+ 参数:
146
+ index: FAISS索引
147
+ methodology_data: 方法论数据列表
148
+ methodology_hash: 方法论文件哈希值
149
+
150
+ 返回:
151
+ bool: 保存是否成功
152
+ """
153
+ index_path = _get_index_cache_path()
154
+ metadata_path = _get_index_metadata_path()
155
+
156
+ try:
157
+ # 保存索引
158
+ faiss.write_index(index, index_path)
159
+
160
+ # 保存元数据
161
+ metadata = {
162
+ "methodology_data": methodology_data,
163
+ "methodology_hash": methodology_hash
164
+ }
165
+
166
+ with open(metadata_path, "wb") as f:
167
+ pickle.dump(metadata, f)
168
+
169
+ return True
170
+ except Exception as e:
171
+ PrettyOutput.print(f"保存索引缓存失败: {str(e)}", OutputType.WARNING)
172
+ return False
173
+
18
174
  def _create_methodology_embedding(embedding_model: Any, methodology_text: str) -> np.ndarray:
19
175
  """
20
176
  为方法论文本创建嵌入向量。
@@ -27,6 +183,11 @@ def _create_methodology_embedding(embedding_model: Any, methodology_text: str) -
27
183
  np.ndarray: 嵌入向量
28
184
  """
29
185
  try:
186
+ # 检查缓存中是否已有此文本的嵌入向量
187
+ cache_key = hash(methodology_text)
188
+ if cache_key in _methodology_embeddings_cache:
189
+ return _methodology_embeddings_cache[cache_key]
190
+
30
191
  # 截断长文本
31
192
  max_length = 512
32
193
  text = ' '.join(methodology_text.split()[:max_length])
@@ -36,10 +197,16 @@ def _create_methodology_embedding(embedding_model: Any, methodology_text: str) -
36
197
  convert_to_tensor=True,
37
198
  normalize_embeddings=True)
38
199
  vector = np.array(embedding.cpu().numpy(), dtype=np.float32)
39
- return vector[0] # 返回第一个向量,因为我们只编码了一个文本
200
+ result = vector[0] # 返回第一个向量,因为我们只编码了一个文本
201
+
202
+ # 缓存嵌入向量以便后续使用
203
+ _methodology_embeddings_cache[cache_key] = result
204
+
205
+ return result
40
206
  except Exception as e:
41
207
  PrettyOutput.print(f"创建方法论嵌入向量失败: {str(e)}", OutputType.ERROR)
42
208
  return np.zeros(1536, dtype=np.float32)
209
+
43
210
  def make_methodology_prompt(data: Dict[str, str]) -> str:
44
211
  """
45
212
  从方法论数据生成格式化提示
@@ -55,6 +222,124 @@ def make_methodology_prompt(data: Dict[str, str]) -> str:
55
222
  ret += f"问题: {key}\n方法论: {value}\n"
56
223
  return ret
57
224
 
225
+ def _get_methodology_directory() -> str:
226
+ """
227
+ 获取方法论目录路径,如果不存在则创建
228
+
229
+ 返回:
230
+ str: 方法论目录的路径
231
+ """
232
+ methodology_dir = os.path.expanduser("~/.jarvis/methodologies")
233
+ if not os.path.exists(methodology_dir):
234
+ try:
235
+ os.makedirs(methodology_dir, exist_ok=True)
236
+ except Exception as e:
237
+ PrettyOutput.print(f"创建方法论目录失败: {str(e)}", OutputType.ERROR)
238
+ return methodology_dir
239
+
240
+ def _get_methodology_files_hash() -> str:
241
+ """
242
+ 计算所有方法论文件的组合哈希值,用于检测文件变化
243
+
244
+ 返回:
245
+ str: 所有方法论文件的组合哈希值
246
+ """
247
+ methodology_dir = _get_methodology_directory()
248
+ if not os.path.exists(methodology_dir):
249
+ return ""
250
+
251
+ # 获取所有方法论文件的路径和修改时间
252
+ files_data = []
253
+ for filepath in glob.glob(os.path.join(methodology_dir, "*.json")):
254
+ mtime = os.path.getmtime(filepath)
255
+ files_data.append((filepath, mtime))
256
+
257
+ # 按路径排序,保证哈希值的一致性
258
+ files_data.sort(key=lambda x: x[0])
259
+
260
+ # 计算组合哈希值
261
+ if not files_data:
262
+ return ""
263
+
264
+ hasher = hashlib.md5()
265
+ for filepath, mtime in files_data:
266
+ hasher.update(f"{filepath}:{mtime}".encode("utf-8"))
267
+
268
+ return hasher.hexdigest()
269
+
270
+ def _load_all_methodologies() -> Dict[str, str]:
271
+ """
272
+ 加载所有方法论文件
273
+
274
+ 返回:
275
+ Dict[str, str]: 方法论字典,键为问题类型,值为方法论内容
276
+ """
277
+ methodology_dir = _get_methodology_directory()
278
+ all_methodologies = {}
279
+
280
+ if not os.path.exists(methodology_dir):
281
+ return all_methodologies
282
+
283
+ for filepath in glob.glob(os.path.join(methodology_dir, "*.json")):
284
+ try:
285
+ with open(filepath, "r", encoding="utf-8", errors="ignore") as f:
286
+ methodology = json.load(f)
287
+ problem_type = methodology.get("problem_type", "")
288
+ content = methodology.get("content", "")
289
+ if problem_type and content:
290
+ all_methodologies[problem_type] = content
291
+ except Exception as e:
292
+ filename = os.path.basename(filepath)
293
+ PrettyOutput.print(f"加载方法论文件 {filename} 失败: {str(e)}", OutputType.WARNING)
294
+
295
+ return all_methodologies
296
+
297
+ def _migrate_from_old_format():
298
+ """
299
+ 从旧的单文件格式迁移到新的多文件格式
300
+ """
301
+ old_format_file = os.path.expanduser("~/.jarvis/methodology")
302
+ if not os.path.exists(old_format_file):
303
+ return
304
+
305
+ try:
306
+ # 加载旧格式文件
307
+ with open(old_format_file, "r", encoding="utf-8", errors="ignore") as f:
308
+ old_data = yaml.safe_load(f) or {}
309
+
310
+ if not old_data:
311
+ return
312
+
313
+ # 创建新目录
314
+ methodology_dir = _get_methodology_directory()
315
+
316
+ # 迁移每个方法论
317
+ migrated_count = 0
318
+ for problem_type, content in old_data.items():
319
+ # 为每个方法论创建文件名(使用问题类型的MD5哈希作为文件名)
320
+ safe_filename = hashlib.md5(problem_type.encode('utf-8')).hexdigest()
321
+ file_path = os.path.join(methodology_dir, f"{safe_filename}.json")
322
+
323
+ # 保存为新格式
324
+ with open(file_path, "w", encoding="utf-8", errors="ignore") as f:
325
+ json.dump({
326
+ "problem_type": problem_type,
327
+ "content": content
328
+ }, f, ensure_ascii=False, indent=2)
329
+
330
+ migrated_count += 1
331
+
332
+ if migrated_count > 0:
333
+ # 备份旧文件
334
+ backup_path = old_format_file + ".bak"
335
+ try:
336
+ os.rename(old_format_file, backup_path)
337
+ PrettyOutput.print(f"已成功迁移 {migrated_count} 个方法论,旧文件已备份为 {backup_path}", OutputType.INFO)
338
+ except Exception as e:
339
+ PrettyOutput.print(f"备份旧文件失败,但已完成迁移: {str(e)}", OutputType.WARNING)
340
+ except Exception as e:
341
+ PrettyOutput.print(f"迁移方法论失败: {str(e)}", OutputType.ERROR)
342
+
58
343
  def load_methodology(user_input: str) -> str:
59
344
  """
60
345
  加载方法论并构建向量索引以进行相似性搜索。
@@ -66,19 +351,91 @@ def load_methodology(user_input: str) -> str:
66
351
  str: 相关的方法论提示,如果未找到方法论则返回空字符串
67
352
  """
68
353
  from yaspin import yaspin
69
- user_jarvis_methodology = os.path.expanduser("~/.jarvis/methodology")
70
- if not os.path.exists(user_jarvis_methodology):
354
+
355
+ # 加载嵌入向量缓存
356
+ global _methodology_embeddings_cache
357
+ if not _methodology_embeddings_cache:
358
+ with yaspin(text="加载嵌入向量缓存...", color="yellow") as spinner:
359
+ _methodology_embeddings_cache = _load_embeddings_cache()
360
+ spinner.text = f"加载嵌入向量缓存完成 ({len(_methodology_embeddings_cache)} 个向量)"
361
+ spinner.ok("✅")
362
+
363
+ # 检查是否需要从旧格式迁移
364
+ with yaspin(text="检查方法论格式...", color="yellow") as spinner:
365
+ _migrate_from_old_format()
366
+ spinner.text = "检查方法论格式完成"
367
+ spinner.ok("✅")
368
+
369
+ # 获取方法论目录
370
+ methodology_dir = _get_methodology_directory()
371
+ if not os.path.exists(methodology_dir) or not glob.glob(os.path.join(methodology_dir, "*.json")):
71
372
  return ""
72
373
 
73
374
  try:
375
+ # 获取文件的修改时间戳组合哈希,用于检测文件是否被修改
376
+ methodology_hash = _get_methodology_files_hash()
377
+
74
378
  with yaspin(text="加载方法论文件...", color="yellow") as spinner:
75
- with open(user_jarvis_methodology, "r", encoding="utf-8", errors="ignore") as f:
76
- data = yaml.safe_load(f)
379
+ data = _load_all_methodologies()
77
380
  if dont_use_local_model():
78
381
  spinner.text = "加载方法论文件完成"
79
382
  spinner.ok("✅")
80
383
  return make_methodology_prompt(data)
81
384
 
385
+ # 检查缓存的索引是否可用且方法论文件未被修改
386
+ global _methodology_index_cache
387
+ if _methodology_index_cache is None:
388
+ # 尝试从文件系统加载索引缓存
389
+ with yaspin(text="加载索引缓存...", color="yellow") as spinner:
390
+ _methodology_index_cache = _load_index_cache()
391
+ if _methodology_index_cache:
392
+ spinner.text = "加载索引缓存完成"
393
+ spinner.ok("✅")
394
+ else:
395
+ spinner.text = "没有可用的索引缓存"
396
+ spinner.fail("❌")
397
+
398
+ if _methodology_index_cache is not None:
399
+ cached_index, cached_data, cache_hash = _methodology_index_cache
400
+ if cache_hash == methodology_hash:
401
+ # 直接使用缓存的索引和数据
402
+ with yaspin(text="使用缓存的方法论索引...", color="yellow") as spinner:
403
+ methodology_index = cached_index
404
+ methodology_data = cached_data
405
+ spinner.text = "使用缓存的方法论索引完成"
406
+ spinner.ok("✅")
407
+
408
+ with yaspin(text="加载嵌入模型...", color="yellow") as spinner:
409
+ embedding_model = load_embedding_model()
410
+ spinner.text = "加载嵌入模型完成"
411
+ spinner.ok("✅")
412
+
413
+ with yaspin(text="执行搜索...", color="yellow") as spinner:
414
+ # 使用缓存构造输入文本的嵌入
415
+ query_embedding = _create_methodology_embedding(embedding_model, user_input)
416
+ k = min(3, len(methodology_data))
417
+ distances, indices = methodology_index.search(
418
+ query_embedding.reshape(1, -1), k
419
+ ) # type: ignore
420
+ spinner.text = "执行搜索完成"
421
+ spinner.ok("✅")
422
+
423
+ with yaspin(text="处理搜索结果...", color="yellow") as spinner:
424
+ relevant_methodologies = {}
425
+ for dist, idx in zip(distances[0], indices[0]):
426
+ if idx >= 0:
427
+ similarity = 1.0 / (1.0 + float(dist))
428
+ methodology = methodology_data[idx]
429
+ if similarity >= 0.5:
430
+ relevant_methodologies[methodology["key"]] = methodology["value"]
431
+ spinner.text = "处理搜索结果完成"
432
+ spinner.ok("✅")
433
+
434
+ if relevant_methodologies:
435
+ return make_methodology_prompt(relevant_methodologies)
436
+ return make_methodology_prompt(data)
437
+
438
+ # 如果缓存无效,从头构建索引
82
439
  with yaspin(text="初始化数据结构...", color="yellow") as spinner:
83
440
  methodology_data: List[Dict[str, str]] = []
84
441
  vectors: List[np.ndarray] = []
@@ -115,6 +472,12 @@ def load_methodology(user_input: str) -> str:
115
472
  hnsw_index.hnsw.efSearch = 16
116
473
  methodology_index = faiss.IndexIDMap(hnsw_index)
117
474
  methodology_index.add_with_ids(vectors_array, np.array(ids)) # type: ignore
475
+ # 缓存构建好的索引和数据以及时间戳哈希
476
+ _methodology_index_cache = (methodology_index, methodology_data, methodology_hash)
477
+
478
+ # 将索引和嵌入向量缓存保存到文件系统
479
+ _save_index_cache(methodology_index, methodology_data, methodology_hash)
480
+
118
481
  spinner.text = "构建索引完成"
119
482
  spinner.ok("✅")
120
483
 
@@ -137,10 +500,19 @@ def load_methodology(user_input: str) -> str:
137
500
  relevant_methodologies[methodology["key"]] = methodology["value"]
138
501
  spinner.text = "处理搜索结果完成"
139
502
  spinner.ok("✅")
140
-
503
+
504
+ # 保存嵌入向量缓存到文件系统
505
+ with yaspin(text="保存嵌入向量缓存...", color="yellow") as spinner:
506
+ if _save_embeddings_cache(_methodology_embeddings_cache):
507
+ spinner.text = f"保存嵌入向量缓存完成 ({len(_methodology_embeddings_cache)} 个向量)"
508
+ spinner.ok("✅")
509
+ else:
510
+ spinner.text = "保存嵌入向量缓存失败"
511
+ spinner.fail("❌")
141
512
 
142
513
  if relevant_methodologies:
143
514
  return make_methodology_prompt(relevant_methodologies)
144
515
  return make_methodology_prompt(data)
145
516
  except Exception as e:
517
+ PrettyOutput.print(f"加载方法论失败: {str(e)}", OutputType.ERROR)
146
518
  return ""
@@ -186,7 +186,7 @@ class PrettyOutput:
186
186
  )
187
187
  console.print()
188
188
  console.print(panel)
189
- if traceback or output_type == OutputType.ERROR:
189
+ if traceback:
190
190
  console.print_exception()
191
191
  @staticmethod
192
192
  def section(title: str, output_type: OutputType = OutputType.INFO):
@@ -205,14 +205,16 @@ class PrettyOutput:
205
205
  console.print(panel)
206
206
  console.print()
207
207
  @staticmethod
208
- def print_stream(text: str):
208
+ def print_stream(text: str, is_thinking: bool = False):
209
209
  """
210
210
  打印流式输出,不带换行符。
211
211
 
212
212
  参数:
213
213
  text: 要打印的文本
214
214
  """
215
- style = RichStyle(color="bright_cyan", italic=True, frame=True, meta={"icon": "🤖"})
215
+ style = RichStyle(color="bright_cyan", bold=True, frame=True, meta={"icon": "🤖"})
216
+ if is_thinking:
217
+ style = RichStyle(color="grey58", italic=True, frame=True, meta={"icon": "🤖"})
216
218
  console.print(text, style=style, end="")
217
219
  @staticmethod
218
220
  def print_stream_end():
@@ -9,10 +9,12 @@ 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
11
  def init_env():
12
- """Initialize environment variables from ~/.jarvis/env file.
12
+ """初始化环境变量从~/.jarvis/env文件
13
13
 
14
- Creates the .jarvis directory if it doesn't exist and loads environment variables
15
- from the env file. Handles file reading errors gracefully.
14
+ 功能:
15
+ 1. 创建不存在的.jarvis目录
16
+ 2. 加载环境变量到os.environ
17
+ 3. 处理文件读取异常
16
18
  """
17
19
  jarvis_dir = Path.home() / ".jarvis"
18
20
  env_file = jarvis_dir / "env"
@@ -34,6 +36,15 @@ def init_env():
34
36
  except Exception as e:
35
37
  PrettyOutput.print(f"警告: 读取 {env_file} 失败: {e}", OutputType.WARNING)
36
38
  def while_success(func, sleep_time: float = 0.1):
39
+ """循环执行函数直到成功
40
+
41
+ 参数:
42
+ func -- 要执行的函数
43
+ sleep_time -- 每次失败后的等待时间(秒)
44
+
45
+ 返回:
46
+ 函数执行结果
47
+ """
37
48
  while True:
38
49
  try:
39
50
  return func()
@@ -87,10 +98,16 @@ def get_file_line_count(filename: str) -> int:
87
98
  except Exception as e:
88
99
  return 0
89
100
  def init_gpu_config() -> Dict:
90
- """Initialize GPU configuration based on available hardware.
101
+ """初始化GPU配置
91
102
 
92
- Returns:
93
- Dict: GPU configuration including memory sizes and availability
103
+ 功能:
104
+ 1. 检测CUDA可用性
105
+ 2. 计算设备内存和共享内存
106
+ 3. 设置CUDA内存分配策略
107
+ 4. 处理异常情况
108
+
109
+ 返回:
110
+ 包含GPU配置信息的字典
94
111
  """
95
112
  config = {
96
113
  "has_gpu": False,
@@ -98,6 +115,8 @@ def init_gpu_config() -> Dict:
98
115
  "device_memory": 0,
99
116
  "memory_fraction": 0.8 # 默认使用80%的可用内存
100
117
  }
118
+
119
+ os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "expandable_segments:True"
101
120
 
102
121
  try:
103
122
  import torch
@@ -130,7 +149,17 @@ def init_gpu_config() -> Dict:
130
149
 
131
150
 
132
151
  def is_long_context(files: list) -> bool:
133
- """检查文件列表是否属于长上下文(总字符数超过最大上下文长度的80%)"""
152
+ """检查文件列表是否属于长上下文
153
+
154
+ 判断标准:
155
+ 当总token数超过最大上下文长度的80%时视为长上下文
156
+
157
+ 参数:
158
+ files -- 要检查的文件路径列表
159
+
160
+ 返回:
161
+ 布尔值表示是否属于长上下文
162
+ """
134
163
  max_token_count = get_max_token_count()
135
164
  threshold = max_token_count * 0.8
136
165
  total_tokens = 0
@@ -148,3 +177,26 @@ def is_long_context(files: list) -> bool:
148
177
  continue
149
178
 
150
179
  return total_tokens > threshold
180
+
181
+
182
+ def ot(tag_name: str) -> str:
183
+ """生成HTML标签开始标记
184
+
185
+ 参数:
186
+ tag_name -- HTML标签名称
187
+
188
+ 返回:
189
+ 格式化的开始标签字符串
190
+ """
191
+ return f"<{tag_name}>"
192
+
193
+ def ct(tag_name: str) -> str:
194
+ """生成HTML标签结束标记
195
+
196
+ 参数:
197
+ tag_name -- HTML标签名称
198
+
199
+ 返回:
200
+ 格式化的结束标签字符串
201
+ """
202
+ return f"</{tag_name}>"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: jarvis-ai-assistant
3
- Version: 0.1.131
3
+ Version: 0.1.132
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
@@ -64,7 +64,8 @@ Requires-Dist: jedi>=0.17.2
64
64
  Requires-Dist: psutil>=7.0.0
65
65
  Requires-Dist: fastapi>=0.115.4
66
66
  Requires-Dist: uvicorn>=0.33.0
67
- Requires-Dist: tree-sitter>=0.20.0
67
+ Requires-Dist: python-pptx>=1.0.0
68
+ Requires-Dist: pandas>=2.0.0
68
69
  Provides-Extra: dev
69
70
  Requires-Dist: pytest; extra == "dev"
70
71
  Requires-Dist: black; extra == "dev"