jarvis-ai-assistant 0.2.7__py3-none-any.whl → 0.3.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 (38) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +267 -240
  3. jarvis/jarvis_agent/agent_manager.py +85 -0
  4. jarvis/jarvis_agent/config_editor.py +53 -0
  5. jarvis/jarvis_agent/file_methodology_manager.py +105 -0
  6. jarvis/jarvis_agent/jarvis.py +37 -398
  7. jarvis/jarvis_agent/memory_manager.py +133 -0
  8. jarvis/jarvis_agent/methodology_share_manager.py +174 -0
  9. jarvis/jarvis_agent/prompts.py +18 -3
  10. jarvis/jarvis_agent/share_manager.py +176 -0
  11. jarvis/jarvis_agent/task_analyzer.py +126 -0
  12. jarvis/jarvis_agent/task_manager.py +111 -0
  13. jarvis/jarvis_agent/tool_share_manager.py +139 -0
  14. jarvis/jarvis_code_agent/code_agent.py +26 -20
  15. jarvis/jarvis_data/config_schema.json +37 -0
  16. jarvis/jarvis_platform/ai8.py +13 -1
  17. jarvis/jarvis_platform/base.py +20 -5
  18. jarvis/jarvis_platform/human.py +11 -1
  19. jarvis/jarvis_platform/kimi.py +10 -0
  20. jarvis/jarvis_platform/openai.py +20 -0
  21. jarvis/jarvis_platform/tongyi.py +14 -9
  22. jarvis/jarvis_platform/yuanbao.py +10 -0
  23. jarvis/jarvis_platform_manager/main.py +12 -12
  24. jarvis/jarvis_tools/registry.py +79 -20
  25. jarvis/jarvis_tools/retrieve_memory.py +36 -8
  26. jarvis/jarvis_utils/clipboard.py +90 -0
  27. jarvis/jarvis_utils/config.py +64 -0
  28. jarvis/jarvis_utils/git_utils.py +17 -7
  29. jarvis/jarvis_utils/globals.py +18 -12
  30. jarvis/jarvis_utils/input.py +118 -16
  31. jarvis/jarvis_utils/methodology.py +48 -5
  32. jarvis/jarvis_utils/utils.py +196 -106
  33. {jarvis_ai_assistant-0.2.7.dist-info → jarvis_ai_assistant-0.3.0.dist-info}/METADATA +1 -1
  34. {jarvis_ai_assistant-0.2.7.dist-info → jarvis_ai_assistant-0.3.0.dist-info}/RECORD +38 -28
  35. {jarvis_ai_assistant-0.2.7.dist-info → jarvis_ai_assistant-0.3.0.dist-info}/WHEEL +0 -0
  36. {jarvis_ai_assistant-0.2.7.dist-info → jarvis_ai_assistant-0.3.0.dist-info}/entry_points.txt +0 -0
  37. {jarvis_ai_assistant-0.2.7.dist-info → jarvis_ai_assistant-0.3.0.dist-info}/licenses/LICENSE +0 -0
  38. {jarvis_ai_assistant-0.2.7.dist-info → jarvis_ai_assistant-0.3.0.dist-info}/top_level.txt +0 -0
@@ -107,17 +107,13 @@ arguments:
107
107
 
108
108
 
109
109
  class OutputHandlerProtocol(Protocol):
110
- def name(self) -> str:
111
- ...
110
+ def name(self) -> str: ...
112
111
 
113
- def can_handle(self, response: str) -> bool:
114
- ...
112
+ def can_handle(self, response: str) -> bool: ...
115
113
 
116
- def prompt(self) -> str:
117
- ...
114
+ def prompt(self) -> str: ...
118
115
 
119
- def handle(self, response: str, agent: Any) -> Tuple[bool, Any]:
120
- ...
116
+ def handle(self, response: str, agent: Any) -> Tuple[bool, Any]: ...
121
117
 
122
118
 
123
119
  class ToolRegistry(OutputHandlerProtocol):
@@ -138,9 +134,7 @@ class ToolRegistry(OutputHandlerProtocol):
138
134
  try:
139
135
  tools_prompt += " <tool>\n"
140
136
  tools_prompt += f" <name>名称: {tool['name']}</name>\n"
141
- tools_prompt += (
142
- f" <description>描述: {tool['description']}</description>\n"
143
- )
137
+ tools_prompt += f" <description>描述: {tool['description']}</description>\n"
144
138
  tools_prompt += " <parameters>\n"
145
139
  tools_prompt += " <yaml>|\n"
146
140
 
@@ -197,20 +191,22 @@ class ToolRegistry(OutputHandlerProtocol):
197
191
  self._load_builtin_tools()
198
192
  self._load_external_tools()
199
193
  self._load_mcp_tools()
194
+ # 应用工具配置组过滤
195
+ self._apply_tool_config_filter()
200
196
 
201
197
  def _get_tool_stats(self) -> Dict[str, int]:
202
198
  """从数据目录获取工具调用统计"""
203
199
  from jarvis.jarvis_stats.stats import StatsManager
204
200
  from datetime import datetime, timedelta
205
-
201
+
206
202
  # 获取所有工具的统计数据
207
203
  tool_stats = {}
208
204
  tools = self.get_all_tools()
209
-
205
+
210
206
  # 获取所有历史数据(从很早的时间开始)
211
207
  end_time = datetime.now()
212
208
  start_time = datetime(2000, 1, 1) # 使用一个足够早的时间
213
-
209
+
214
210
  for tool in tools:
215
211
  tool_name = tool["name"]
216
212
  # 获取该工具的统计数据
@@ -218,22 +214,22 @@ class ToolRegistry(OutputHandlerProtocol):
218
214
  metric_name=tool_name,
219
215
  start_time=start_time,
220
216
  end_time=end_time,
221
- tags={"group": "tool"}
217
+ tags={"group": "tool"},
222
218
  )
223
-
219
+
224
220
  # 计算总调用次数
225
221
  if stats_data and "records" in stats_data:
226
222
  total_count = sum(record["value"] for record in stats_data["records"])
227
223
  tool_stats[tool_name] = int(total_count)
228
224
  else:
229
225
  tool_stats[tool_name] = 0
230
-
226
+
231
227
  return tool_stats
232
228
 
233
229
  def _update_tool_stats(self, name: str) -> None:
234
230
  """更新工具调用统计"""
235
231
  from jarvis.jarvis_stats.stats import StatsManager
236
-
232
+
237
233
  StatsManager.increment(name, group="tool")
238
234
 
239
235
  def use_tools(self, name: List[str]) -> None:
@@ -264,6 +260,36 @@ class ToolRegistry(OutputHandlerProtocol):
264
260
  name: tool for name, tool in self.tools.items() if name not in names
265
261
  }
266
262
 
263
+ def _apply_tool_config_filter(self) -> None:
264
+ """应用工具配置组的过滤规则"""
265
+ from jarvis.jarvis_utils.config import get_tool_use_list, get_tool_dont_use_list
266
+
267
+ use_list = get_tool_use_list()
268
+ dont_use_list = get_tool_dont_use_list()
269
+
270
+ # 如果配置了 use 列表,只保留列表中的工具
271
+ if use_list:
272
+ filtered_tools = {}
273
+ for tool_name in use_list:
274
+ if tool_name in self.tools:
275
+ filtered_tools[tool_name] = self.tools[tool_name]
276
+ else:
277
+ PrettyOutput.print(
278
+ f"警告: 配置的工具 '{tool_name}' 不存在",
279
+ OutputType.WARNING,
280
+ )
281
+ self.tools = filtered_tools
282
+
283
+ # 如果配置了 dont_use 列表,排除列表中的工具
284
+ if dont_use_list:
285
+ for tool_name in dont_use_list:
286
+ if tool_name in self.tools:
287
+ del self.tools[tool_name]
288
+ PrettyOutput.print(
289
+ f"已排除工具: {tool_name}",
290
+ OutputType.INFO,
291
+ )
292
+
267
293
  def _load_mcp_tools(self) -> None:
268
294
  """加载MCP工具,优先从配置获取,其次从目录扫描"""
269
295
  from jarvis.jarvis_utils.config import get_mcp_config
@@ -292,7 +318,9 @@ class ToolRegistry(OutputHandlerProtocol):
292
318
  config = yaml.safe_load(open(file_path, "r", encoding="utf-8"))
293
319
  self.register_mcp_tool_by_config(config)
294
320
  except Exception as e:
295
- PrettyOutput.print(f"文件 {file_path} 加载失败: {str(e)}", OutputType.WARNING)
321
+ PrettyOutput.print(
322
+ f"文件 {file_path} 加载失败: {str(e)}", OutputType.WARNING
323
+ )
296
324
 
297
325
  def _load_builtin_tools(self) -> None:
298
326
  """从内置工具目录加载工具"""
@@ -308,8 +336,33 @@ class ToolRegistry(OutputHandlerProtocol):
308
336
 
309
337
  def _load_external_tools(self) -> None:
310
338
  """从jarvis_data/tools和配置的目录加载外部工具"""
339
+ from jarvis.jarvis_utils.config import get_central_tool_repo
340
+
311
341
  tool_dirs = [str(Path(get_data_dir()) / "tools")] + get_tool_load_dirs()
312
342
 
343
+ # 如果配置了中心工具仓库,将其添加到加载路径
344
+ central_repo = get_central_tool_repo()
345
+ if central_repo:
346
+ # 中心工具仓库存储在数据目录下的特定位置
347
+ central_repo_path = os.path.join(get_data_dir(), "central_tool_repo")
348
+ tool_dirs.append(central_repo_path)
349
+
350
+ # 确保中心工具仓库被克隆/更新
351
+ if not os.path.exists(central_repo_path):
352
+ try:
353
+ import subprocess
354
+
355
+ PrettyOutput.print(
356
+ f"正在克隆中心工具仓库: {central_repo}", OutputType.INFO
357
+ )
358
+ subprocess.run(
359
+ ["git", "clone", central_repo, central_repo_path], check=True
360
+ )
361
+ except Exception as e:
362
+ PrettyOutput.print(
363
+ f"克隆中心工具仓库失败: {str(e)}", OutputType.ERROR
364
+ )
365
+
313
366
  # --- 全局每日更新检查 ---
314
367
  daily_check_git_updates(tool_dirs, "tools")
315
368
 
@@ -662,6 +715,10 @@ class ToolRegistry(OutputHandlerProtocol):
662
715
  parameters: 工具参数定义
663
716
  func: 工具执行函数
664
717
  """
718
+ if name in self.tools:
719
+ PrettyOutput.print(
720
+ f"警告: 工具 '{name}' 已存在,将被覆盖", OutputType.WARNING
721
+ )
665
722
  self.tools[name] = Tool(name, description, parameters, func)
666
723
 
667
724
  def get_tool(self, name: str) -> Optional[Tool]:
@@ -735,7 +792,9 @@ class ToolRegistry(OutputHandlerProtocol):
735
792
  """
736
793
  if len(output.splitlines()) > 60:
737
794
  lines = output.splitlines()
738
- return "\n".join(lines[:30] + ["\n...内容太长,已截取前后30行...\n"] + lines[-30:])
795
+ return "\n".join(
796
+ lines[:30] + ["\n...内容太长,已截取前后30行...\n"] + lines[-30:]
797
+ )
739
798
  return output
740
799
 
741
800
  def handle_tool_calls(self, tool_call: Dict[str, Any], agent: Any) -> str:
@@ -4,9 +4,10 @@ import random
4
4
  from pathlib import Path
5
5
  from typing import Any, Dict, List, Optional
6
6
 
7
- from jarvis.jarvis_utils.config import get_data_dir
7
+ from jarvis.jarvis_utils.config import get_data_dir, get_max_input_token_count
8
8
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
9
9
  from jarvis.jarvis_utils.globals import get_short_term_memories
10
+ from jarvis.jarvis_utils.embedding import get_context_token_count
10
11
 
11
12
 
12
13
  class RetrieveMemoryTool:
@@ -131,14 +132,41 @@ class RetrieveMemoryTool:
131
132
  # 按创建时间排序(最新的在前)
132
133
  all_memories.sort(key=lambda x: x.get("created_at", ""), reverse=True)
133
134
 
134
- # 限制最多返回50条记忆,随机选取
135
- if len(all_memories) > 50:
136
- all_memories = random.sample(all_memories, 50)
137
- # 重新排序,保持时间顺序
138
- all_memories.sort(key=lambda x: x.get("created_at", ""), reverse=True)
135
+ # 获取最大输入token数的2/3作为记忆的token限制
136
+ max_input_tokens = get_max_input_token_count()
137
+ memory_token_limit = int(max_input_tokens * 2 / 3)
139
138
 
140
- # 如果指定了限制,只返回前N个
141
- if limit:
139
+ # 基于token限制和条数限制筛选记忆
140
+ filtered_memories: List[Dict[str, Any]] = []
141
+ total_tokens = 0
142
+
143
+ for memory in all_memories:
144
+ # 计算当前记忆的token数量
145
+ memory_content = json.dumps(memory, ensure_ascii=False)
146
+ memory_tokens = get_context_token_count(memory_content)
147
+
148
+ # 检查是否超过token限制
149
+ if total_tokens + memory_tokens > memory_token_limit:
150
+ PrettyOutput.print(
151
+ f"达到token限制 ({total_tokens}/{memory_token_limit}),停止加载更多记忆",
152
+ OutputType.INFO,
153
+ )
154
+ break
155
+
156
+ # 检查是否超过50条限制
157
+ if len(filtered_memories) >= 50:
158
+ PrettyOutput.print(
159
+ f"达到记忆条数限制 (50条),停止加载更多记忆", OutputType.INFO
160
+ )
161
+ break
162
+
163
+ filtered_memories.append(memory)
164
+ total_tokens += memory_tokens
165
+
166
+ all_memories = filtered_memories
167
+
168
+ # 如果指定了额外的限制,只返回前N个
169
+ if limit and len(all_memories) > limit:
142
170
  all_memories = all_memories[:limit]
143
171
 
144
172
  # 打印结果摘要
@@ -0,0 +1,90 @@
1
+ # -*- coding: utf-8 -*-
2
+ import platform
3
+ import subprocess
4
+
5
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
6
+
7
+
8
+ def copy_to_clipboard(text: str) -> None:
9
+ """将文本复制到剪贴板,支持Windows、macOS和Linux
10
+
11
+ 参数:
12
+ text: 要复制的文本
13
+ """
14
+ print("--- 剪贴板内容开始 ---")
15
+ print(text)
16
+ print("--- 剪贴板内容结束 ---")
17
+
18
+ system = platform.system()
19
+
20
+ # Windows系统
21
+ if system == "Windows":
22
+ try:
23
+ # 使用Windows的clip命令
24
+ process = subprocess.Popen(
25
+ ["clip"],
26
+ stdin=subprocess.PIPE,
27
+ stdout=subprocess.DEVNULL,
28
+ stderr=subprocess.DEVNULL,
29
+ shell=True,
30
+ )
31
+ if process.stdin:
32
+ process.stdin.write(text.encode("utf-8"))
33
+ process.stdin.close()
34
+ return
35
+ except Exception as e:
36
+ PrettyOutput.print(f"使用Windows clip命令时出错: {e}", OutputType.WARNING)
37
+
38
+ # macOS系统
39
+ elif system == "Darwin":
40
+ try:
41
+ process = subprocess.Popen(
42
+ ["pbcopy"],
43
+ stdin=subprocess.PIPE,
44
+ stdout=subprocess.DEVNULL,
45
+ stderr=subprocess.DEVNULL,
46
+ )
47
+ if process.stdin:
48
+ process.stdin.write(text.encode("utf-8"))
49
+ process.stdin.close()
50
+ return
51
+ except Exception as e:
52
+ PrettyOutput.print(f"使用macOS pbcopy命令时出错: {e}", OutputType.WARNING)
53
+
54
+ # Linux系统
55
+ else:
56
+ # 尝试使用 xsel
57
+ try:
58
+ process = subprocess.Popen(
59
+ ["xsel", "-b", "-i"],
60
+ stdin=subprocess.PIPE,
61
+ stdout=subprocess.DEVNULL,
62
+ stderr=subprocess.DEVNULL,
63
+ )
64
+ if process.stdin:
65
+ process.stdin.write(text.encode("utf-8"))
66
+ process.stdin.close()
67
+ return
68
+ except FileNotFoundError:
69
+ pass # xsel 未安装,继续尝试下一个
70
+ except Exception as e:
71
+ PrettyOutput.print(f"使用xsel时出错: {e}", OutputType.WARNING)
72
+
73
+ # 尝试使用 xclip
74
+ try:
75
+ process = subprocess.Popen(
76
+ ["xclip", "-selection", "clipboard"],
77
+ stdin=subprocess.PIPE,
78
+ stdout=subprocess.DEVNULL,
79
+ stderr=subprocess.DEVNULL,
80
+ )
81
+ if process.stdin:
82
+ process.stdin.write(text.encode("utf-8"))
83
+ process.stdin.close()
84
+ return
85
+ except FileNotFoundError:
86
+ PrettyOutput.print(
87
+ "xsel 和 xclip 均未安装, 无法复制到剪贴板", OutputType.WARNING
88
+ )
89
+ except Exception as e:
90
+ PrettyOutput.print(f"使用xclip时出错: {e}", OutputType.WARNING)
@@ -319,6 +319,16 @@ def get_central_methodology_repo() -> str:
319
319
  return GLOBAL_CONFIG_DATA.get("JARVIS_CENTRAL_METHODOLOGY_REPO", "")
320
320
 
321
321
 
322
+ def get_central_tool_repo() -> str:
323
+ """
324
+ 获取中心工具Git仓库地址。
325
+
326
+ 返回:
327
+ str: 中心工具Git仓库地址,如果未配置则返回空字符串
328
+ """
329
+ return GLOBAL_CONFIG_DATA.get("JARVIS_CENTRAL_TOOL_REPO", "")
330
+
331
+
322
332
  def is_print_prompt() -> bool:
323
333
  """
324
334
  获取是否打印提示。
@@ -477,3 +487,57 @@ def get_rag_use_rerank() -> bool:
477
487
  """
478
488
  config = _get_resolved_rag_config()
479
489
  return config.get("use_rerank", True) is True
490
+
491
+
492
+ # ==============================================================================
493
+ # Tool Configuration
494
+ # ==============================================================================
495
+
496
+
497
+ def _get_resolved_tool_config(
498
+ tool_group_override: Optional[str] = None,
499
+ ) -> Dict[str, Any]:
500
+ """
501
+ 解析并合并工具配置,处理工具组。
502
+
503
+ 优先级顺序:
504
+ 1. JARVIS_TOOL_GROUP 中定义的组配置
505
+ 2. 默认配置(所有工具都启用)
506
+
507
+ 返回:
508
+ Dict[str, Any]: 解析后的工具配置字典,包含 'use' 和 'dont_use' 列表
509
+ """
510
+ group_config = {}
511
+ tool_group_name = tool_group_override or GLOBAL_CONFIG_DATA.get("JARVIS_TOOL_GROUP")
512
+ tool_groups = GLOBAL_CONFIG_DATA.get("JARVIS_TOOL_GROUPS", [])
513
+
514
+ if tool_group_name and isinstance(tool_groups, list):
515
+ for group_item in tool_groups:
516
+ if isinstance(group_item, dict) and tool_group_name in group_item:
517
+ group_config = group_item[tool_group_name]
518
+ break
519
+
520
+ # 如果没有找到配置组,返回默认配置(空列表表示使用所有工具)
521
+ return group_config.copy() if group_config else {"use": [], "dont_use": []}
522
+
523
+
524
+ def get_tool_use_list() -> List[str]:
525
+ """
526
+ 获取要使用的工具列表。
527
+
528
+ 返回:
529
+ List[str]: 要使用的工具名称列表,空列表表示使用所有工具
530
+ """
531
+ config = _get_resolved_tool_config()
532
+ return config.get("use", [])
533
+
534
+
535
+ def get_tool_dont_use_list() -> List[str]:
536
+ """
537
+ 获取不使用的工具列表。
538
+
539
+ 返回:
540
+ List[str]: 不使用的工具名称列表
541
+ """
542
+ config = _get_resolved_tool_config()
543
+ return config.get("dont_use", [])
@@ -214,7 +214,9 @@ def handle_commit_workflow() -> bool:
214
214
  Returns:
215
215
  bool: 提交是否成功
216
216
  """
217
- if is_confirm_before_apply_patch() and not user_confirm("是否要提交代码?", default=True):
217
+ if is_confirm_before_apply_patch() and not user_confirm(
218
+ "是否要提交代码?", default=True
219
+ ):
218
220
  revert_change()
219
221
  return False
220
222
 
@@ -280,7 +282,7 @@ def get_latest_commit_hash() -> str:
280
282
  return ""
281
283
 
282
284
 
283
- def get_modified_line_ranges() -> Dict[str, Tuple[int, int]]:
285
+ def get_modified_line_ranges() -> Dict[str, List[Tuple[int, int]]]:
284
286
  """从Git差异中获取所有更改文件的修改行范围
285
287
 
286
288
  返回:
@@ -291,7 +293,7 @@ def get_modified_line_ranges() -> Dict[str, Tuple[int, int]]:
291
293
  diff_output = os.popen("git show").read()
292
294
 
293
295
  # 解析差异以获取修改的文件及其行范围
294
- result = {}
296
+ result: Dict[str, List[Tuple[int, int]]] = {}
295
297
  current_file = None
296
298
 
297
299
  for line in diff_output.splitlines():
@@ -427,7 +429,9 @@ def check_and_update_git_repo(repo_path: str) -> bool:
427
429
  if not in_venv and (
428
430
  "Permission denied" in error_msg or "not writeable" in error_msg
429
431
  ):
430
- if user_confirm("检测到权限问题,是否尝试用户级安装(--user)?", True):
432
+ if user_confirm(
433
+ "检测到权限问题,是否尝试用户级安装(--user)?", True
434
+ ):
431
435
  user_result = subprocess.run(
432
436
  install_cmd + ["--user"],
433
437
  cwd=git_root,
@@ -442,7 +446,9 @@ def check_and_update_git_repo(repo_path: str) -> bool:
442
446
  PrettyOutput.print(f"代码安装失败: {error_msg}", OutputType.ERROR)
443
447
  return False
444
448
  except Exception as e:
445
- PrettyOutput.print(f"安装过程中发生意外错误: {str(e)}", OutputType.ERROR)
449
+ PrettyOutput.print(
450
+ f"安装过程中发生意外错误: {str(e)}", OutputType.ERROR
451
+ )
446
452
  return False
447
453
  # 更新检查日期文件
448
454
  with open(last_check_file, "w") as f:
@@ -476,7 +482,9 @@ def get_diff_file_list() -> List[str]:
476
482
  subprocess.run(["git", "reset"], check=True)
477
483
 
478
484
  if result.returncode != 0:
479
- PrettyOutput.print(f"获取差异文件列表失败: {result.stderr}", OutputType.ERROR)
485
+ PrettyOutput.print(
486
+ f"获取差异文件列表失败: {result.stderr}", OutputType.ERROR
487
+ )
480
488
  return []
481
489
 
482
490
  return [f for f in result.stdout.splitlines() if f]
@@ -626,7 +634,9 @@ def confirm_add_new_files() -> None:
626
634
  need_confirm = True
627
635
 
628
636
  if binary_files:
629
- output_lines.append(f"检测到{len(binary_files)}个二进制文件(选择N将重新检测)")
637
+ output_lines.append(
638
+ f"检测到{len(binary_files)}个二进制文件(选择N将重新检测)"
639
+ )
630
640
  output_lines.append("二进制文件列表:")
631
641
  output_lines.extend(f" - {file}" for file in binary_files)
632
642
  need_confirm = True
@@ -264,7 +264,7 @@ def get_all_memory_tags() -> Dict[str, List[str]]:
264
264
  """
265
265
  获取所有记忆类型中的标签集合。
266
266
  每个类型最多返回200个标签,超过时随机提取。
267
-
267
+
268
268
  返回:
269
269
  Dict[str, List[str]]: 按记忆类型分组的标签列表
270
270
  """
@@ -272,25 +272,27 @@ def get_all_memory_tags() -> Dict[str, List[str]]:
272
272
  import json
273
273
  import random
274
274
  from jarvis.jarvis_utils.config import get_data_dir
275
-
276
- tags_by_type = {
275
+
276
+ tags_by_type: Dict[str, List[str]] = {
277
277
  "short_term": [],
278
278
  "project_long_term": [],
279
- "global_long_term": []
279
+ "global_long_term": [],
280
280
  }
281
-
281
+
282
282
  MAX_TAGS_PER_TYPE = 200
283
-
283
+
284
284
  # 获取短期记忆标签
285
285
  short_term_tags = set()
286
286
  for memory in short_term_memories:
287
287
  short_term_tags.update(memory.get("tags", []))
288
288
  short_term_tags_list = sorted(list(short_term_tags))
289
289
  if len(short_term_tags_list) > MAX_TAGS_PER_TYPE:
290
- tags_by_type["short_term"] = sorted(random.sample(short_term_tags_list, MAX_TAGS_PER_TYPE))
290
+ tags_by_type["short_term"] = sorted(
291
+ random.sample(short_term_tags_list, MAX_TAGS_PER_TYPE)
292
+ )
291
293
  else:
292
294
  tags_by_type["short_term"] = short_term_tags_list
293
-
295
+
294
296
  # 获取项目长期记忆标签
295
297
  project_memory_dir = Path(".jarvis/memory")
296
298
  if project_memory_dir.exists():
@@ -304,10 +306,12 @@ def get_all_memory_tags() -> Dict[str, List[str]]:
304
306
  pass
305
307
  project_tags_list = sorted(list(project_tags))
306
308
  if len(project_tags_list) > MAX_TAGS_PER_TYPE:
307
- tags_by_type["project_long_term"] = sorted(random.sample(project_tags_list, MAX_TAGS_PER_TYPE))
309
+ tags_by_type["project_long_term"] = sorted(
310
+ random.sample(project_tags_list, MAX_TAGS_PER_TYPE)
311
+ )
308
312
  else:
309
313
  tags_by_type["project_long_term"] = project_tags_list
310
-
314
+
311
315
  # 获取全局长期记忆标签
312
316
  global_memory_dir = Path(get_data_dir()) / "memory" / "global_long_term"
313
317
  if global_memory_dir.exists():
@@ -321,8 +325,10 @@ def get_all_memory_tags() -> Dict[str, List[str]]:
321
325
  pass
322
326
  global_tags_list = sorted(list(global_tags))
323
327
  if len(global_tags_list) > MAX_TAGS_PER_TYPE:
324
- tags_by_type["global_long_term"] = sorted(random.sample(global_tags_list, MAX_TAGS_PER_TYPE))
328
+ tags_by_type["global_long_term"] = sorted(
329
+ random.sample(global_tags_list, MAX_TAGS_PER_TYPE)
330
+ )
325
331
  else:
326
332
  tags_by_type["global_long_term"] = global_tags_list
327
-
333
+
328
334
  return tags_by_type